pax_global_header00006660000000000000000000000064121717607540014524gustar00rootroot0000000000000052 comment=19ccaca4aec366a9c243d79bbff920db3f707af2 dff-1.3.0+dfsg.1/000077500000000000000000000000001217176075400133425ustar00rootroot00000000000000dff-1.3.0+dfsg.1/CHANGES000066400000000000000000006441371217176075400143540ustar00rootroot00000000000000DFF (Digital Forensics Framework) See the CHANGES.current file for changes in the current version. See the RELEASENOTES file for a summary of changes in each release. Version 1.3.0 (27 February 2013) =============================== CHANGES after 10/04/11 are now split in corresponding category. * ui repository : ------------- Author: fba Date: Mon Feb 18 13:39:29 2013 +0100 update of usage message Author: fba Date: Thu Feb 14 10:59:01 2013 +0100 fixes bad unicode handling in processus state Author: fba Date: Tue Feb 12 18:15:13 2013 +0100 update of french translation Author: fba Date: Tue Feb 12 18:12:02 2013 +0100 update of german and french translation Author: sja Date: Mon Feb 11 17:08:50 2013 +0100 use inheritance for modules_path launcher Author: fba Date: Mon Jan 14 19:21:22 2013 +0100 * Update to new building macros Author: fba Date: Mon Jan 14 13:46:24 2013 +0100 * Changes in target creation Author: sja Date: Tue Dec 4 12:19:35 2012 +0100 FIX for widget without titleName use widget name Author: sja Date: Mon Dec 3 19:27:49 2012 +0100 FIX 'toolbar' translation for browser, now mainwindow use windowTitle as id not widget.name() Author: fba Date: Mon Dec 3 11:45:45 2012 +0100 Adds German translation provided by D. Schreiber Author: sja Date: Thu Nov 15 20:11:54 2012 +0100 update translation for taskmanager Author: sja Date: Thu Nov 15 18:36:53 2012 +0100 remove old indexation engine Author: sja Date: Thu Nov 15 16:36:30 2012 +0100 update for translation Author: sja Date: Thu Nov 15 11:37:05 2012 +0100 FIX translation loading Author: sja Date: Wed Nov 14 17:09:46 2012 +0100 update french translation Author: sja Date: Thu Nov 8 17:48:32 2012 +0100 fix import * modules repository : ------------------- Author: sja Date: Mon Feb 25 11:42:30 2013 +0100 FIX module local : typo in attribute name (orignal for original) Author: sja Date: Fri Feb 22 17:16:39 2013 +0100 module exchange : rename __identifier to __id because it's keyword for VS ... Author: sja Date: Thu Feb 21 11:12:58 2013 +0100 Change module/mfso name from pff to exchange Author: sja Date: Tue Feb 19 16:28:40 2013 +0100 FIX #181 PFF fix bug with item attachments Author: sja Date: Mon Feb 18 19:30:57 2013 +0100 FIX pff bug introducing a new structure ItemInfo to handle item type and recovery more easily and dynamically Author: fba Date: Thu Feb 14 11:23:10 2013 +0100 fixes issue with self.vnode which was still a variant Author: sja Date: Wed Feb 13 14:44:30 2013 +0100 fix hexeditor add try/catch for open/close Author: sja Date: Mon Feb 11 17:41:09 2013 +0100 pff_fix test Author: sja Date: Mon Feb 11 14:27:16 2013 +0100 delete experimental will move it to parent directory Author: sja Date: Mon Feb 11 14:23:13 2013 +0100 Module name, description or category was changed to be clearer Author: fba Date: Thu Jan 31 13:07:55 2013 +0100 * Carver GUI ** Adds checks and appropriate message box when: *** No items have been selected *** Input is a folder Author: sja Date: Tue Jan 29 12:15:14 2013 +0100 FIX possible infinite loop on lnk modules applyied on carved or bad lnk Author: fba Date: Wed Jan 16 14:42:43 2013 +0100 *Build process Windows ** Changes *.dll with respective _DYN_LIBRARIES cmake variables Author: jmo Date: Tue Jan 15 15:13:40 2013 +0100 Fixes #152 : Search from cursor error Author: fba Date: Mon Jan 14 13:44:36 2013 +0100 * Include pyrun.swg in all .i files * Changes CMakeLists.txt to support dff_cpp_module macro Author: sja Date: Mon Jan 7 18:13:16 2013 +0100 Use new method to update state of the hash attributes Author: fba Date: Mon Jan 7 15:06:36 2013 +0100 adds a new config parameters for footer instead of using existing one. Made double free when deleting config Author: fba Date: Fri Dec 14 16:04:26 2012 +0100 * Extract ** adds better event handling for reporting failed extraction and renamed files Author: fba Date: Fri Dec 7 18:39:21 2012 +0100 * Modules regviewer ** Adds absolute "path" information and timestamp for each key Author: cma Date: Thu Dec 6 18:35:31 2012 +0100 * NTFS improvements ** Adds filesystem parameters as attributes to the "NTFS" top-level node ** Adds the MFT cluster number as attribute for each file or directory ** Adds the first data cluster as attribute for each file ** Creates a "NTFS unallocated" node near the top-level module node *** Filled with unallocated area from the $Bitmap file *** Each node file is a continuous unallocated area named "starting cluster--ending cluster" *** This commit refs #167, need feedback. Author: cma Date: Mon Dec 3 17:52:04 2012 +0100 * NTFS Fixes ** Infinite loop in directory parsing resulting in NTFS module never ends ** Random files detection on huge directory Author: udgover Date: Wed Nov 28 06:53:34 2012 +0100 fixes an issue due to ModuleRoot asking absolute to early. RegisterTree of RootNode is called before creating subtrees Author: udgover Date: Wed Nov 28 06:52:37 2012 +0100 adding UTF16-LE, UTF16-BE decoders and adds support to 64 bits timestamps in Date decoder Author: udgover Date: Wed Nov 28 06:51:40 2012 +0100 fixes some issues with bad timestamp Author: udgover Date: Wed Nov 28 06:51:13 2012 +0100 if first character of objectName < 0x05, remove it Author: sja Date: Fri Nov 9 16:10:57 2012 +0100 Module use new 'relative' loading method * API repository : ----------------- Author: sja Date: Wed Feb 20 14:45:40 2013 +0100 FIX thread concurrency problem Author: sja Date: Tue Feb 12 14:40:46 2013 +0100 FIX UTF-8 display for node absolute path in configuration widget Author: sja Date: Mon Feb 11 17:30:24 2013 +0100 add thread name to taskmanager Author: sja Date: Mon Feb 11 17:30:00 2013 +0100 add worker name to scheduler thread Author: fba Date: Thu Jan 17 11:24:23 2013 +0100 * Building process ** remove target's name from install_file Author: sja Date: Thu Jan 17 11:01:05 2013 +0100 extract add check before closing file if open fail Author: sja Date: Wed Jan 16 18:21:22 2013 +0100 set import api.gui.video Author: sja Date: Wed Jan 16 18:12:31 2013 +0100 gui/thumbnail.py FIX infinite blocking loop when video api is not present and trying to thumbnail certain video also limit thumbnail size to 100Mo for image to avoid error on false postive file type Author: sja Date: Wed Jan 16 18:12:00 2013 +0100 vfs/extract more verbose error msg when extracted file can't match node size Author: sja Date: Wed Jan 16 15:49:56 2013 +0100 vfs/extract add more error check for extraction Author: sja Date: Wed Jan 16 13:14:13 2013 +0100 close file on exception Author: fba Date: Tue Jan 15 13:52:35 2013 +0100 adds missing %include in swig file of libdevices to be able to use EXPORT Author: fba Date: Tue Jan 15 11:05:27 2013 +0100 * Windows compilation and runtime issues fixed ** without EXPORT in device.hpp and wmidev.hpp, devices.lib is not created and _libdevices.pyd cannot link ** path to magic.mgc in magichandler.py didn't reflect new pathes organisation ** path to *.dll in magic.py didn't reflect new pathes orgatisation ** linked libraries were not coherent for datatype (change datatypes to types...) ** CMakeLists.txt for devices under Windows didn't provide cpp files ** CMakeLists.txt in search didn't provide __init__.py because of bad variables handling Author: fba Date: Mon Jan 14 19:19:10 2013 +0100 * Update to the new building macro Author: fba Date: Mon Jan 14 13:42:02 2013 +0100 * Adds pyrun.swg in all .i files to support our patch to SWIG * changes CMakeLists.txt by using dff_cpp_api macro Author: jmo Date: Fri Jan 11 13:10:30 2013 +0100 Fixes #158, refresh queries line edit on various actions Author: sja Date: Fri Jan 11 12:35:15 2013 +0100 node_list, thumbnail more detailed error message events/eventhandler remove error message vfs/extract.py add static method to check freespace on a disk relative to a path Author: jmo Date: Fri Jan 11 10:58:03 2013 +0100 Fixes #88, save state of sort in navigation, and default sort when changing model list Author: jmo Date: Fri Jan 11 10:23:54 2013 +0100 Fixes #170 Stop scrolling when searching Author: fba Date: Wed Jan 9 11:30:36 2013 +0100 * Variant ** fixes a bug when dealing with Variant of type Char Author: sja Date: Tue Jan 8 18:57:49 2013 +0100 FIX widget resize bug who sometimes lead to crash because of refreshing node_list item scrollbar Author: sja Date: Mon Jan 7 18:11:22 2013 +0100 fixes #162 Add new classes and method to update the state of attributes caches Author: sja Date: Mon Jan 7 18:08:20 2013 +0100 fixes #162 Add new classes AttributesHandlers to more easily manage AttributeHandler and to update the state and notice the DynamicAttribute cache Add new virtual method _attributesState to update the state of the AttributeCache Author: fba Date: Fri Dec 14 16:03:07 2012 +0100 * API: Extract ** adds new notification when file is renamed ** better enclose possible error in try / except with notification for each Author: sja Date: Thu Dec 13 19:29:48 2012 +0100 extract return utf8-encoded renamed file name Author: fba Date: Thu Dec 13 17:41:44 2012 +0100 * API: Extract ** fixes too much arguments provided for extractFolder Author: sja Date: Thu Dec 13 17:06:15 2012 +0100 fix for non utf-8 system Author: fba Date: Thu Dec 13 17:08:02 2012 +0100 * API: Extract ** fixes strange folder renaming behaviour ** changes renaming type for file. It is now based on node uid ** overwrite is better handled Author: sja Date: Thu Dec 13 13:33:19 2012 +0100 FIX extract API for system not using utf-8 as default encoding Author: sja Date: Tue Dec 4 13:09:18 2012 +0100 FIX: try/catch attribute handler to get some attributes even if there is errors Author: sja Date: Fri Nov 30 17:45:05 2012 +0100 Lock refcount Author: sja Date: Fri Nov 30 10:36:20 2012 +0100 FIX refcount issue Author: udgover Date: Wed Nov 28 06:49:29 2012 +0100 private methods going public to enable chunk Author: sja Date: Tue Nov 27 13:31:30 2012 +0100 processus is info is now upcase Author: sja Date: Thu Nov 22 14:06:15 2012 +0100 Taskmanager : add a default output class Author: fba Date: Wed Nov 21 16:04:45 2012 +0100 * API / GUI ** fixes bad variable substitution while performing unicode in launchFilter method Author: sja Date: Thu Nov 15 19:30:07 2012 +0100 FIX devices library import for windows Author: sja Date: Thu Nov 15 18:36:09 2012 +0100 remove old and unused indexation engine Author: sja Date: Thu Nov 15 16:33:34 2012 +0100 update for translation Author: fba Date: Wed Nov 14 17:57:54 2012 +0100 * API: devices ** Uses UDEV_LIBRARY set by cmake instead of -ludev Author: fba Date: Wed Nov 14 17:21:58 2012 +0100 * API: devices ** better management to take into account udev library and headers files Author: sja Date: Wed Nov 14 13:02:25 2012 +0100 FIX utf8 encoded string for additional column Author: sja Date: Tue Nov 13 15:00:03 2012 +0100 FIX Unicode search & filters, remove dead code Author: sja Date: Fri Nov 9 16:03:11 2012 +0100 loader : add method modulesPaths() to get path for modules/__init__.py module: FIX Config owner problem who lead to crash when re-loading a module * cmake_modules repository : ------------------------ Author: fba Date: Wed Jan 16 12:26:48 2013 +0100 fixes some issues for ICU libraries lookup Author: fba Date: Tue Jan 15 19:02:22 2013 +0100 fixes bad variables setting under windows Author: fba Date: Mon Jan 14 19:15:54 2013 +0100 * Fixes an issue in FindICU which was not able to find all components * Main repository : ----------------- Author: fba Date: Thu Feb 14 11:08:13 2013 +0100 provides named parameters when instanciating ui class. Author: fba Date: Tue Feb 12 15:32:52 2013 +0100 adds unsupported submodule and update of api Author: sja Date: Mon Feb 11 17:10:25 2013 +0100 use inheritance for modules path loading rather than copy/paste of imcomprehnsible code Author: fba Date: Thu Jan 31 13:27:34 2013 +0100 Packaging, remove pyc at uninstall Author: fba Date: Thu Jan 31 11:17:08 2013 +0100 * Build process under Windows ** better dependencies management for packaging pass Author: fba Date: Wed Jan 30 17:21:34 2013 +0100 moving some section before cpack configuration to have coherent install / deinstall process on Windows Author: fba Date: Wed Jan 30 13:20:57 2013 +0100 changes minimum version of swig to 2.0.7 Author: fba Date: Wed Jan 30 13:05:55 2013 +0100 * Adds Prerequisites submodules Author: fba Date: Wed Jan 30 13:01:05 2013 +0100 * Change dff's icon Author: fba Date: Thu Jan 17 12:46:11 2013 +0100 * Build process Windows ** changes to provide working installer Author: fba Date: Wed Jan 16 15:57:30 2013 +0100 * Building process: ** Change macro filename_to_path to split_path_file_extension which set __PATH__, __FILE__, __EXTENSION__ when appropriate Author: fba Date: Wed Jan 16 14:28:52 2013 +0100 minor fixes for file command must be in uppercase Author: fba Date: Wed Jan 16 14:07:36 2013 +0100 * Build Process Windows ** update for building the project under Windows ** adds a new macro filename_from_path and set ${filename} variable Author: fba Date: Tue Jan 15 15:08:57 2013 +0100 fixes issue for version of cmake < 2.8.9 Author: fba Date: Tue Jan 15 11:11:45 2013 +0100 * CMakeLists.txt minor changes in path_to_target for windows build process * update of dff/api submodules Author: fba Date: Mon Jan 14 19:22:23 2013 +0100 * Update all building process to new cmake macros Author: fba Date: Mon Jan 14 13:48:28 2013 +0100 * Refactored all target creation system. ** Adds new macros to ease target creation for api and modules *** dff_cpp_api is used to create DFF's API libraries *** dff_cpp_module is used to create DFF's modules ** targets' name are now based on their current path *** it is now possible to do make dff.api.vfs *** all parent targets depend on their children i.e.: make dff.api will call each subtargets Author: fba Date: Wed Jan 9 11:50:33 2013 +0100 * Adds new submodule 'doc' dedicated to documentation Author: fba Date: Wed Jan 9 11:34:21 2013 +0100 * remove of docs folder Author: sja Date: Thu Nov 15 20:13:09 2012 +0100 update translation for taskmanager Author: sja Date: Thu Nov 15 18:40:28 2012 +0100 remove old and unused indexation engine Author: sja Date: Thu Nov 15 16:43:56 2012 +0100 translation update Author: fba Date: Wed Nov 14 18:14:03 2012 +0100 remove of backup cmake_modules Author: fba Date: Wed Nov 14 18:13:05 2012 +0100 * change cmake_modules as a submodule Author: fba Date: Wed Nov 14 17:58:43 2012 +0100 ** adds FindUDEV.cmake ** find_package(udev), ... Author: fba Date: Mon Nov 12 15:51:12 2012 +0100 update of FindTRE.cmake Author: sja Date: Fri Nov 9 16:20:06 2012 +0100 new loading mechanism for modules Author: sja Date: Thu Nov 8 17:49:04 2012 +0100 FIX import in ui Advanced search bugfix; enable thread ** add %option never-interactive in scanner to not add isatty Author: cma Date: Thu Oct 25 16:59:59 2012 +0200 Windows compilation error C2589 fix in video. Some other header file is polluting the global name space with a max macro. Author: cma Date: Thu Oct 25 16:56:59 2012 +0200 Windows compilation : missing code after %extend Author: cma Date: Thu Oct 25 16:29:12 2012 +0200 Windows compilation : include missing Author: cma Date: Thu Oct 25 15:42:02 2012 +0200 FFMpeg DLLs dependencies versions bump for Win32. Author: fba Date: Wed Oct 24 14:38:41 2012 +0200 * API Types ** minor changes to render correctly str on nodes attributes in python *** in libtypes.i map.__str__ did not provide key *** in variant.cpp toString for vtime did not add single quote Author: sja Date: Wed Oct 24 14:19:05 2012 +0200 add rootnode to swig .i files Author: sja Date: Wed Oct 24 13:02:36 2012 +0200 vlink change in ui/gui Author: sja Date: Wed Oct 24 13:01:34 2012 +0200 add vlink to variant Author: sja Date: Wed Oct 24 12:58:51 2012 +0200 add rootnode for modules Author: sja Date: Wed Oct 17 17:11:43 2012 +0200 Remove all 'using namespace std' and put std:: where it's needed Author: sja Date: Wed Oct 17 13:13:57 2012 +0200 HEADER REFACTO include less in .hpp do forward declaration import in cpp ! Author: fba Date: Tue Oct 16 21:35:18 2012 +0200 * API: GUI ** changes contains with matches in clauses Author: sja Date: Tue Oct 16 11:41:02 2012 +0200 processus add lock on exists Author: sja Date: Mon Oct 15 15:09:36 2012 +0200 Cache delref fix Author: sja Date: Mon Oct 15 13:12:30 2012 +0200 Use a template for class Cache Author: sja Date: Mon Oct 15 12:39:49 2012 +0200 Add cache for attribute & dynamicAttribute Author: sja Date: Wed Oct 10 15:21:12 2012 +0200 Move cache & pool used in mfso to cachefile to prepare for attribute cache nothing added in node just group similar function in the file to be more redable Author: sja Date: Wed Oct 10 13:38:30 2012 +0200 small optim of decoder Author: sja Date: Tue Oct 9 17:11:33 2012 +0200 forget to unlock new method fsobjArgumentsByType Author: sja Date: Tue Oct 9 17:02:03 2012 +0200 check if proc was found by fsobj before returning Author: sja Date: Tue Oct 9 16:58:53 2012 +0200 add proc by fsobj and fsbojArgumentsByType method in processus manager Author: fba Date: Mon Oct 8 17:37:01 2012 +0200 * API: Filter ** adds 'path' keyword ** adds wildcard support for attributes *** useful while looking for multiple Recipients with mailboxes: @pff.Recipients.*.Display Name@ matches any of ["Alonso", "Tom", $*Tim*$] Author: fba Date: Mon Oct 8 16:37:52 2012 +0200 * API: Filter ** it is now possible to use == with string ** replaces contain with matches Author: sja Date: Mon Oct 1 13:12:06 2012 +0200 delete variant in astnode.cpp:976 lead to crash Author: sja Date: Thu Sep 27 14:58:10 2012 +0200 Add a question if the same module with the same conf was already applied Author: sja Date: Thu Sep 27 12:52:45 2012 +0200 fix try/catch on bad value for libtypes.i metaexif set date tags to vtime Author: sja Date: Mon Sep 24 15:26:39 2012 +0200 remove lock unecessary after swig patch Author: sja Date: Mon Sep 24 15:14:59 2012 +0200 FIX node_list in case of attributesByType throw Author: sja Date: Mon Sep 24 15:12:33 2012 +0200 add some try/catch but maybe not needed as fixed elsewhere Author: sja Date: Mon Sep 24 15:10:23 2012 +0200 FIX small memory leaks and try/catch on dynamicAttributes & fsoAttributes in case of throwing modules attributes method Author: sja Date: Thu Sep 20 19:42:44 2012 +0200 Selectattributes : Add default attribute and fix other little things (cancel button , ...) Author: sja Date: Thu Sep 20 16:29:10 2012 +0200 hash: add a lock release after a try catch to avoid dead lock ! selectattributes code is now merged (to use right click select all, etc.. in select attributes) nodelistwidgets fix bug for column sort on vtime (use vtime.get_time and special func key sort because vtime.operator< have a really strange behavior ..) and use a key function to avoid None datetime value and none obj nodelistwidgets now header(s) are movable so Author: sja Date: Wed Sep 19 17:31:40 2012 +0200 date text correction Author: sja Date: Wed Sep 19 16:56:18 2012 +0200 check if udev in libdevices.i Author: cma Date: Wed Sep 19 16:19:52 2012 +0200 * BFIO and PFF required version was swapped Author: sja Date: Wed Sep 19 16:10:42 2012 +0200 varianttreewidget now it's possible to copy attribute or value directly by right clicking Author: sja Date: Wed Sep 19 14:34:22 2012 +0200 variant treewidget on double-click show attribute & value, now it's copyable Author: cma Date: Wed Sep 19 14:31:53 2012 +0200 * Build process ** Checks required version of libbfio & libpff, don't build the mailbox module otherwise ** Cleans status messages ** modules/connector/CMakeLists.txt checks for EWF but not for BFIO it has to be fixed Author: jmo Date: Wed Sep 19 11:19:38 2012 +0200 Add registry viewer Author: sja Date: Tue Sep 18 11:09:42 2012 +0200 PFF & libbfio update for the last lib version (libbfio 20120425 & libpff20120802) need to update CMakeList accordingly Author: sja Date: Mon Sep 17 16:46:05 2012 +0200 add use udev rule to be sure to build even if udev not present Author: sja Date: Mon Sep 17 16:32:57 2012 +0200 Device: add a new device library compatibility with libudev build should continue even if udev is not found (linux < 2.6 or using HAL) -> must add this in MakeFile Author: sja Date: Mon Sep 17 09:05:16 2012 +0200 taskmanager add first sort column as int Author: sja Date: Fri Sep 14 18:04:31 2012 +0200 fix for designer taskmanager Author: sja Date: Fri Sep 14 18:03:09 2012 +0200 Add sort to task manager Author: cma Date: Fri Sep 14 15:36:01 2012 +0200 Fixes for timeline not working when it encounters bad date like 0000-00-00 00:00:00. Author: cma Date: Fri Sep 14 15:34:50 2012 +0200 Adds timestamps from $FILENAME attribute in each NTFS node. Also adds attribute offset from start of MFT entry. Author: sja Date: Thu Sep 13 16:10:33 2012 +0200 didn't use vlist anymore as there is sometime the same problem as vmap evn in different list Author: sja Date: Thu Sep 13 13:07:13 2012 +0200 remove some 'print' in extract.py Author: fba Date: Thu Sep 13 12:54:25 2012 +0200 * Modules: Carver ** fixes bad parameters settings Author: sja Date: Wed Sep 12 17:32:03 2012 +0200 ADD a small but neat functionality, save the last opened in the window usefull when loading many files/directory different time Author: sja Date: Tue Sep 11 16:20:03 2012 +0200 metacompund remove 'debug error' Author: sja Date: Tue Sep 11 15:43:13 2012 +0200 FIX a bug in magichandler when open return -1 (fail) UPDATE libbfio_wrapper now use latest version : 20120425 libpff now use latest version : 20120802 -> there is still a bug on attachment of attachment even using clone mode Author: sja Date: Tue Sep 11 15:43:13 2012 +0200 FIX a bug in magichandler when open return -1 (fail) UPDATE libbfio_wrapper now use latest version : 20120425 libpff now use latest version : 20120802 -> there is still a bug on attachment of attachment even using clone mode, it seem to come from libpff itself. Author: sja Date: Tue Sep 11 11:05:09 2012 +0200 mfso add a vfile cache not used yet Author: jmo Date: Thu Sep 6 18:19:18 2012 +0200 Fix stop filter event; Fix visible rows in table/list view Author: jmo Date: Thu Sep 6 17:38:55 2012 +0200 Fix search append item Author: sja Date: Thu Sep 6 15:01:35 2012 +0200 Add lacking EXPORT on addref/delref/refcount method on class FileMapping Author: sja Date: Thu Sep 6 14:04:06 2012 +0200 FileMappingCache rewrote, lock fdmanager & lock filemapping should work better No vfile pool yet, or page caching Author: sja Date: Fri Aug 31 15:21:57 2012 +0200 Change video thumbnail QImage format from RGB32 to ARGB32 Author: jmo Date: Fri Aug 31 11:04:29 2012 +0200 Display last row and scroll by rows in icon view; Author: sja Date: Thu Aug 30 18:44:55 2012 +0200 APSWVFS FIX FOR WINDOWS Author: cma Date: Thu Aug 30 17:46:46 2012 +0200 Deploys video library in system library directory on Unix. Author: sja Date: Thu Aug 30 17:36:12 2012 +0200 node list modified for table view to show all Author: cma Date: Thu Aug 30 17:12:00 2012 +0200 Fixes for Windows all in one, proper NSIS hooks for Python install prior to create .lnk with Python path. Also adds REGLOOKUP path for distributing it on Windows and PIL in Prerequisites Author: jmo Date: Thu Aug 30 16:40:37 2012 +0200 Fix last row update Author: sja Date: Thu Aug 30 15:35:40 2012 +0200 WINDOWS: use mutex rather than critical sections, mutex is lot slower but block on same thread ( != posix recurisve ) ! Author: sja Date: Wed Aug 29 17:31:43 2012 +0200 FIX apswvfs for windows and last lib version Author: sja Date: Wed Aug 29 12:37:09 2012 +0200 Move fuse / extract -> ds tag export Author: sja Date: Tue Aug 28 17:52:21 2012 +0200 CAT module now it's possible to choose text codec for decoding Author: sja Date: Tue Aug 28 15:33:21 2012 +0200 node_list and tree icon use node.fsobj != child[0].fsobj rather than node.fsobj != parent.fsobj to detect root Author: fba Date: Tue Aug 28 15:29:51 2012 +0200 * Modules: Extract ** fixes issue with event handling Author: sja Date: Tue Aug 28 13:30:40 2012 +0200 recommit of preview Author: fba Date: Tue Aug 28 13:30:32 2012 +0200 * Modules: extract ** refactored to use the extraction functionnalities of the API Author: fba Date: Tue Aug 28 13:29:56 2012 +0200 * API: Extract ** moves Extract capabilities to the API Author: sja Date: Tue Aug 28 12:32:36 2012 +0200 Tree & list model : Add a composite '+' on root node icons to differentiate more easily root node Author: sja Date: Mon Aug 27 18:10:56 2012 +0200 Preview : come back of the checkstate button, now that we can add our own button to dockwidget ( must be push in open too) Author: sja Date: Mon Aug 27 16:05:51 2012 +0200 add bookmark to the menu and toolbar , put the code in menu to be able callable from menumanager & nodelistwidgets Author: jmo Date: Mon Aug 27 15:13:11 2012 +0200 New RCPVariant sort accessor; Fixe custom attribute search Author: sja Date: Mon Aug 27 11:59:01 2012 +0200 API thumbnail fix add 'return' to avoid sending two signals Author: sja Date: Tue Aug 14 16:14:05 2012 +0200 remove margins from layout Author: sja Date: Tue Aug 14 14:55:03 2012 +0200 preview add some button to switch preview type Author: jmo Date: Tue Aug 14 12:34:29 2012 +0200 Bugfix loading Unicode filename Author: sja Date: Mon Aug 13 18:34:26 2012 +0200 add filehash icon in module hash Author: sja Date: Mon Aug 13 18:20:35 2012 +0200 new icon for module lnk Author: sja Date: Mon Aug 13 18:20:19 2012 +0200 add new icon link.png Author: sja Date: Mon Aug 13 17:58:18 2012 +0200 add icon to vmware module Author: sja Date: Mon Aug 13 17:57:02 2012 +0200 new icon for vm Author: sja Date: Mon Aug 13 17:53:51 2012 +0200 add icons to device & metacompund Author: sja Date: Mon Aug 13 17:49:57 2012 +0200 new icons movie Author: sja Date: Mon Aug 13 17:49:40 2012 +0200 add new icon Author: jmo Date: Mon Aug 13 17:24:07 2012 +0200 BugFix exception in property table Author: cma Date: Thu Aug 9 13:55:15 2012 +0200 minor * Fix misstake for Windows build ; elseif was used instead of else Author: sja Date: Wed Aug 8 17:17:14 2012 +0200 Add clickable link for node in variant tree widget Author: sja Date: Wed Aug 8 15:19:04 2012 +0200 add 'broken thumbnail' for corrupted picture/video Author: cma Date: Wed Aug 8 14:01:36 2012 +0200 * minor. Bump patch version to 14. Author: sja Date: Wed Aug 8 13:14:45 2012 +0200 fix 'escape from dialog in dialog problem' Author: sja Date: Tue Aug 7 17:23:28 2012 +0200 thumbnail didn't render last image of a row Author: fba Date: Tue Aug 7 17:05:42 2012 +0200 * Modules: Extract ** adds depth argument for countItems and extractTree *** enables to extract one folder content Author: sja Date: Tue Aug 7 16:55:04 2012 +0200 thumbnailer emit signal even if thumbnail can't be created thumbnailer have a new blocking mode Author: sja Date: Tue Aug 7 15:49:50 2012 +0200 fix thumbnail size and corrupted mode for thumbnailer Author: fba Date: Tue Aug 7 15:11:51 2012 +0200 * Modules / Gui: Extraction ** extraction better handles case sensitive destination file system *** renames by suffixing _ ** extraction handles forbidden and reserved characters and words (0x00-0x1f, <, ..., COM1, LPT1, ...) ** new option to preserve absolute path from DFF's vfs ** overwrite option is now provided. Default is no to rename the root folder by suffixing _ Author: cma Date: Mon Aug 6 17:31:21 2012 +0200 Fixes for libraries rename with development build. * Runtime path is set to ./api (cmake magic transparency), where every libNAME.so are copied. * Import chain: libNAME.py importing _libNAME.so linked to libNAME.so is now OK * Problem was with libNAME.so in it's own dir, Python was importing the .so before the .py. Author: cma Date: Mon Aug 6 16:20:37 2012 +0200 Fixes installation on Unix. API libraries are now installed in ${prefix}/lib/dff, each named libNAME instead of liblibNAME. Author: sja Date: Fri Aug 3 17:48:42 2012 +0200 Remove old search_widget and remove 'Searched item' as it not used anymore (better use bookmarks) Author: sja Date: Fri Aug 3 17:21:56 2012 +0200 remove removed file frome dff.pro Author: jmo Date: Fri Aug 3 16:59:05 2012 +0200 New splashscreen Author: sja Date: Fri Aug 3 16:52:30 2012 +0200 remove old logo Author: sja Date: Fri Aug 3 15:41:04 2012 +0200 add new logo to ressource Author: sja Date: Fri Aug 3 13:53:24 2012 +0200 add check recursif for checked/unchecked doc Author: sja Date: Fri Aug 3 13:05:53 2012 +0200 remove search items Author: fba Date: Mon Jul 30 15:14:23 2012 +0200 API: Filters | Index * adds a registry (IndexedPatterns singleton) for all patterns matched during a search * provides method to register a new pattern addPattern(string, Node*) * provides method to get nodes matching a pattern nodesByPattern(string pattern) * provides method to get matched pattern for a node patternsByNode(Node*) Author: cma Date: Thu Jul 26 13:56:57 2012 +0200 * API gui video ** Makes seperate video library. ** Adds EXPORT to video.hpp * Full Windows package ** Adds NumPy and matplotlib as prerequisites for full windows version * Windows version ** Deploys FFMpeg dependencies into build dir. Author: sja Date: Wed Jul 18 13:17:24 2012 +0200 METAEXIF with PIL Author: sja Date: Wed Jul 18 12:47:23 2012 +0200 New thumbnailer Author: sja Date: Wed Jul 18 12:46:41 2012 +0200 Try to remove old node browser Author: sja Date: Mon Jul 16 16:53:25 2012 +0200 FIX time duration in taskmanager Author: fba Date: Fri Jul 13 15:59:19 2012 +0200 Files resulting of the previous commit message... Author: fba Date: Fri Jul 13 15:53:56 2012 +0200 * Build process ** changes cpack generation process *** check if Python and PyQt4 installed *** adds path to python exe into generated shortcuts to enable RunAs feature ** Creates separated dynamic shared libraries for all API components Author: sja Date: Fri Jul 13 13:15:54 2012 +0200 New thumbnailer & video thumbnailer Author: sja Date: Fri Jul 6 18:12:32 2012 +0200 postprocessstate change signal type Author: jmo Date: Fri Jul 6 17:48:36 2012 +0200 Fix switch between search / browser filter view Author: jmo Date: Fri Jul 6 16:19:16 2012 +0200 Fix search issue on advanced mode Author: sja Date: Fri Jul 6 16:15:10 2012 +0200 FIX structuparser -> delete data buff ADD new module -> video thumbnailer preview -> preview video with thumbnail Author: jmo Date: Fri Jul 6 15:07:29 2012 +0200 You can now lock your filter query; fixe some bugs Author: jmo Date: Wed Jul 4 18:04:41 2012 +0200 Advanced search bugfix; enable thread Author: jmo Date: Wed Jul 4 17:35:10 2012 +0200 Drag items in PathList Author: jmo Date: Wed Jul 4 17:26:40 2012 +0200 * Nodebrowser (New feature) : Add filter list * Selection (Bugfix) : remove exception * Search (New feature) : Save / load queries * Search (New feature) : Select search method in quick search Author: fba Date: Wed Jul 4 12:11:26 2012 +0200 * Modules: Extfs ** module description: inform users that module supports EXT version 2, 3 and 4 Author: sja Date: Tue Jul 3 20:19:08 2012 +0200 FIX node->addChild check if child is not null Author: sja Date: Tue Jul 3 20:16:31 2012 +0200 processus add lock at processus creation cause of singleton module structparser delete data content ... mscfb add check before adding file because node.addChild didn't check for null could cause crash in case of error Author: fba Date: Tue Jul 3 18:40:49 2012 +0200 * API: Filters ** reconnect Event handling in Expressions ** fixes some connection / deconnection issues Author: sja Date: Mon Jul 2 19:46:42 2012 +0200 Add tooltip to dockwidget default button Author: fba Date: Mon Jul 2 18:42:46 2012 +0200 * API: TwoThreeTree ** return if value has been inserted or not in method insert Author: fba Date: Mon Jul 2 18:24:48 2012 +0200 * Build process ** add link libexceptions dependencies for events and types Author: fba Date: Mon Jul 2 18:23:08 2012 +0200 * API: TwoTreeTree ** adds return value in two methods... ** when calling find or exists, check size before calling __bsearch... Author: fba Date: Mon Jul 2 15:29:13 2012 +0200 * API TwoThreeTree ** complete refactoring to avoid deep recursion on merge / split / ... ** code is now shorter and easier to understand. Mainly based on FileMapping algorith + merge when inserting can join two elements Author: sja Date: Mon Jul 2 12:52:50 2012 +0200 FIX mfso with scoped mutex FIX vmware didn't close some FD when throw error Author: sja Date: Fri Jun 29 18:15:43 2012 +0200 Patch MFSO -> use new dff:map get_value in place of exists mscfb -> remove some comment vmware-> add some close in case of exceptions Author: jmo Date: Fri Jun 29 15:53:05 2012 +0200 Tree/List model bugfixes Author: jmo Date: Fri Jun 29 15:52:12 2012 +0200 Change icon size and add new ressource files Author: jmo Date: Fri Jun 29 15:50:30 2012 +0200 Add dictionnary search / filter capability Author: fba Date: Fri Jun 29 12:41:32 2012 +0200 * API: exceptions ** exceptions are now handled correctly even whith call like python --> c++ --> python Author: fba Date: Fri Jun 29 10:17:07 2012 +0200 * API: ** Dictionnary *** When creating a dictionnary (FileDictionnary currently), no longer need to associate a name. Name is only needed when registring to DictRegistry ** Filter *** Syntax has been enhanced to let the ability to use dictionnary list, ie: data contain any of [:dict1:, :dict2:, :dict3:] Author: fba Date: Thu Jun 28 15:01:24 2012 +0200 * API: filters ** adds dictionnaries method to DictRegistry to have access to all registered dict ** changes in how to construct Dictionnary : autoregistration disabled ** changes in how to add na dictionnary to registry, name is now longer needed Author: fba Date: Thu Jun 28 12:04:17 2012 +0200 * API mfso ** revert changes concerning scoped mutex map Author: sja Date: Wed Jun 27 18:22:56 2012 +0200 MSLOPES attributes as sometimes wrong length size parameter FIX this by checking if parameter size is > node size to avoid ineficient very large read Author: sja Date: Mon Jun 25 17:41:16 2012 +0200 Error is not set anymore in processus 'res' VMap because this can lead to swig errors Author: sja Date: Thu Jun 21 18:29:06 2012 +0200 Come back of metacompound as it should work now (Need some little fix tough) Author: sja Date: Thu Jun 21 17:26:25 2012 +0200 Add new class Processus Manager to ease processus management ... Modify all module that use it mainly 'builtins' console commands FIX some concurency problem in processus, taskmanager for singleton module like hash who was fixed too Author: sja Date: Thu Jun 21 11:51:53 2012 +0200 Windows threading remove spin Author: sja Date: Wed Jun 20 18:42:17 2012 +0200 change compound lock hash and processus Author: sja Date: Wed Jun 20 13:39:39 2012 +0200 Partitions set a root node for registering Author: sja Date: Wed Jun 20 12:24:09 2012 +0200 Move scoped mutex in api/types/threading, use scoped mutex map in mfso Fix vfile::read(int32_t ) to check for allocated memory Author: fba Date: Tue Jun 19 19:34:17 2012 +0200 * API: Filter ** removes of debug messages Author: fba Date: Tue Jun 19 19:29:43 2012 +0200 * Build: ** define for strtoull Author: fba Date: Tue Jun 19 19:25:00 2012 +0200 * Build: ** Variant comparison operator export Author: fba Date: Tue Jun 19 18:55:37 2012 +0200 * Build: ** adds _ before and after TRUE, FALSE, IN tokens Author: fba Date: Tue Jun 19 18:54:37 2012 +0200 * Build: ** removes EXPORT in front of private idententifier... Author: fba Date: Tue Jun 19 18:04:06 2012 +0200 * Build: ** fixes Windows cmake error Author: fba Date: Tue Jun 19 17:47:13 2012 +0200 * API: Filter ** Huge refactoring of grammar (backward compatible) which is now generic and extends the previous one ** adds dictionnary support * API: GUI ** reflects changes in grammar Author: fba Date: Tue Jun 19 17:42:03 2012 +0200 * API: search ** implement recount, fzcount, ... and fixes some bug Author: fba Date: Tue Jun 19 17:41:11 2012 +0200 * API: Variant ** adds comparison operators for vtime Author: fba Date: Tue Jun 19 17:39:29 2012 +0200 * API: vtime ** better handling of vtime ctor with string *** can be created from YYYY-MM-DD, HH:MM:SS or both YYYY-MM-DDTHH:MM:SS Author: fba Date: Tue Jun 19 17:38:10 2012 +0200 * UI: console ** removes not implemented shell keys Author: fba Date: Tue Jun 19 17:37:32 2012 +0200 * API: vfile ** fixes a bug in search methods Author: sja Date: Mon Jun 18 19:24:09 2012 +0200 Add signal when model receive an registerTree event Author: jmo Date: Mon Jun 18 18:23:25 2012 +0200 Tree model optimization Author: sja Date: Mon Jun 18 17:32:53 2012 +0200 Add icon to partition and remove root 'Partition' node Author: jmo Date: Mon Jun 18 16:36:46 2012 +0200 Set uniform icon size in list view; catch exception in search (percent) Author: sja Date: Mon Jun 18 15:53:43 2012 +0200 FIX BUG in vtime threading and add new version of libmagic (5.11) for windows Author: jmo Date: Mon Jun 18 11:31:16 2012 +0200 Change default icon size on list view Author: jmo Date: Mon Jun 18 10:35:27 2012 +0200 Add resize Icon features, Tree model optimization Author: fba Date: Mon Jun 11 15:56:34 2012 +0200 * API: iostat ** fixes build error on Windows Author: fba Date: Mon Jun 11 14:32:14 2012 +0200 * Modules: local ** forget to declare iterator for arguments Author: fba Date: Tue Jun 5 17:30:19 2012 +0200 * API / Profiling: ** this commit adds IOStat Singleton used in VFile class to: *** provide number of created VFile instances per fsobj *** provide total read bytes per fsobj ** Since it adds calls during reading, this option can only be enabled at compile time with -DWITH_IOSTAT=1 Author: fba Date: Tue Jun 5 12:04:24 2012 +0200 * Modules: local ** On Windows, when parent is not provide use root node by default Author: fba Date: Tue Jun 5 12:03:51 2012 +0200 * API datatype ** adds EXPORT for compiling under Windows Author: fba Date: Mon Jun 4 19:18:54 2012 +0200 * Modules: ** NTFS: uses dff::Mutex + dff::ScopedMutex when calling _attributes method of NtfsNode Author: fba Date: Mon Jun 4 19:15:27 2012 +0200 * Modules: ** NTFS: uses dff::Mutex + dff::ScopedMutex when calling _attributes method of NtfsNode Author: jmo Date: Mon Jun 4 18:52:33 2012 +0200 Avoid edit cell in search filter query dialog Author: fba Date: Mon Jun 4 17:59:18 2012 +0200 * API: datatype ** adds a namespace dff to *** provide Mutex class with lock / trylock / release **** Linux implem is based on pthread mutex and attrs (PTHREAD_MUTEX_RECURSIVE) **** Windows implem is based on CriticalSection and is initialized wiht InitializeCriticalSectionAndSpinCount *** provide ScopedMutex *** adds new map and vector composition class to add thread safe methods (push_back, operator[], ...) by using ScopedMutex Author: jmo Date: Mon Jun 4 17:04:05 2012 +0200 Edit query : Refresh query name Author: jmo Date: Mon Jun 4 16:39:44 2012 +0200 Bugfix: attributeByName list Author: jmo Date: Mon Jun 4 16:19:02 2012 +0200 Set root timeline export node to searched item Author: jmo Date: Mon Jun 4 16:03:19 2012 +0200 Missing import RCVariant in timeline Author: jmo Date: Mon Jun 4 16:00:19 2012 +0200 Fix RCVariant in timeline and bookmark Author: sja Date: Mon Jun 4 15:25:37 2012 +0200 NTFS patch from open 1.2.14 Author: jmo Date: Mon Jun 4 13:30:08 2012 +0200 Avoid noneType issue on nodelistwidget Author: jmo Date: Mon Jun 4 13:20:52 2012 +0200 Remove unused action in menu manager Author: jmo Date: Mon Jun 4 13:18:57 2012 +0200 Quick fix name error in ressource Author: jmo Date: Mon Jun 4 13:11:30 2012 +0200 Add selection menu when right clicking; Treemodel optimization when expand treeview Author: sja Date: Mon Jun 4 11:53:22 2012 +0200 remove error catch in mainwindow for processus widget launching as it was already set in taskmanager Author: sja Date: Mon Jun 4 11:52:11 2012 +0200 Comment module unzip/player/metacompound to avoid crash during Author: sja Date: Mon Jun 4 11:50:40 2012 +0200 Processus -> now widget change state to 'finish' once launched ... , 'fail' state was never set as it was override by finish ... Author: jmo Date: Fri Jun 1 16:07:24 2012 +0200 Enhence expand node and activate pathchanges Author: jmo Date: Fri Jun 1 15:26:49 2012 +0200 Complete rewrite of treemodel Author: cma Date: Thu May 31 18:59:36 2012 +0200 Missing file removed. Author: cma Date: Thu May 31 18:16:40 2012 +0200 Adds EXPORTs to api/include/rc.hpp fixing compilation on Windows. Author: cma Date: Thu May 31 18:14:21 2012 +0200 Adds header needed for ffmpeg/libavutil to compile on Windows. Author: cma Date: Thu May 31 18:06:00 2012 +0200 Removes avcodec_init() in api/gui/video/video.cpp, tested on: * Windows x86 ffmpeg 20120407 * Linux x86_64 ffmpeg 0.10.2 Video module was not working on Windows we have to add libswscale to be linked with video module Author: cma Date: Thu May 31 17:02:41 2012 +0200 Fixes for ffmpeg CMake finder script. The PATHS keyword was missing, resulting in a very odd behavior (INCLUDEs variables was polluted). Author: cma Date: Thu May 31 16:58:48 2012 +0200 Cleaning, magic (py_magic return of the back) validated on Windows. Author: cma Date: Thu May 31 16:52:46 2012 +0200 Fixes for standard output and error output graphically on Windows. Standards file descriptors does not exist on Windows on 100% graphical app. * Create it by opening the file descriptor 1 or 2 * Close it, except number 2 this one need to stay open on Windows to pipe stderr * Pipe and dupe it * That's all stdout and stderr works on 100% graphical app on Windows Author: cma Date: Thu May 31 16:35:52 2012 +0200 Bumps patch version to 12, also Fixes graphical version string. Application version is set in ui/gui/gui.py at the configure step by CMake, this file has again been overwritten in the past. Author: sja Date: Thu May 31 15:18:57 2012 +0200 FIX close in iodevice with signal Author: jmo Date: Thu May 31 14:26:00 2012 +0200 Search from list : avoid NoneType in currentNode Author: fba Date: Thu May 31 13:21:02 2012 +0200 * API ** datatype: avoid segfault on datatypes by adding ref and unref deatures in libdatatype.i ** It means that all c++ code / libraries providing Variant_p mechanism have to declare ref / unref in swig templates * Modules: ** extract now provides extraction progression for each file larger than 10 MB Author: sja Date: Wed May 30 19:30:45 2012 +0200 New thumbnail proxy Author: jmo Date: Wed May 30 19:26:52 2012 +0200 * Improve refresh in list view * Multiselection bugfix in treeview Author: fba Date: Wed May 30 14:54:43 2012 +0200 * API: ** libtypes.i: adds value() and __str__ methods to Variant too (only RCVariant supported these method) Author: jmo Date: Wed May 30 13:02:47 2012 +0200 Add open default when double click Icon view Author: jmo Date: Wed May 30 12:00:21 2012 +0200 Disable search button on simple widget : future replace by quick filter feature on current list Author: sja Date: Tue May 29 19:13:20 2012 +0200 add __init__.py with video & FindFFmpeg swscale missing library that was add on the open who had a bad pushed and was deleted and now was recoded and was recommited here so it will not be loose again ..... add video thumbnailer to node_list who copy/paste the code rather than importing the class ... Author: jmo Date: Tue May 29 16:47:41 2012 +0200 Enable / disable edit custom filter button Author: fba Date: Tue May 29 16:22:45 2012 +0200 * Build ** removes duplicates in CMakeLists.txt of ui/gui/resources Author: fba Date: Tue May 29 16:00:32 2012 +0200 * GUI ** add generated .py in CMakeLists.txt Author: fba Date: Tue May 29 15:41:42 2012 +0200 * Build ** py_magic.c return of the back for Windows... * Module ** carver minor changes Author: fba Date: Tue May 29 14:59:15 2012 +0200 * API / Modules ** removes of all .thisown = False when applied on Variant / VMap / VList Author: sja Date: Tue May 29 13:35:03 2012 +0200 compoundfile : avoid loop in orphaned files when multiple root is present (msdoc said it's impossible ;) Author: jmo Date: Tue May 29 13:01:25 2012 +0200 Add search error messagebox and fix empty query name Author: fba Date: Tue May 29 12:39:06 2012 +0200 * API ** types *** overload of append method for VList to support vlist and vmap assignation *** adds __str__ method for Variant_p Author: fba Date: Fri May 25 18:52:30 2012 +0200 * API ** variant.cpp --> define snprintf _snprintf for windows * Module: ** wlocal.cpp change Variant* --> Variant_p Author: fba Date: Fri May 25 17:43:50 2012 +0200 * Modules: ** removes conflicting target name in CMakeLists (libevents) Author: fba Date: Fri May 25 16:35:37 2012 +0200 before calling absolute in RCVariant.__str__(), first call value... Author: fba Date: Fri May 25 15:51:08 2012 +0200 remove of reverse() Author: fba Date: Fri May 25 15:46:00 2012 +0200 * Modules / ui / api ** Remove of all thisown = False for Variant in Python code * API ** libtypes *** adds __str__ for RCVariant *** adds VLIST.append(VLIST | VMAP) Author: jmo Date: Fri May 25 11:41:19 2012 +0200 Nodeview : Improve scrollbar refresh policy; Search : Improve OnlyFilters (true/false); Model : bugfix segfault issues from insertRows Author: fba Date: Fri May 25 11:37:54 2012 +0200 * API GUI: ** remove of mods.reverse() in nodebrowser. compatibleModules list is now interpreted as a tuple... * Module ** filechart works and char.py has the same functionnalities as pyqt4 examples ** progression is now displayed Author: fba Date: Thu May 24 18:26:49 2012 +0200 * API: ** Variant *** Now Variant inheriths RCObj to be refcounted *** Attributes now handles RCPtr< Variant* > as values *** removes of ugly code in swig file ** Node *** Node no longer returns pointers concerning attributes methods *** attributesByName now returns directly std::list< Variant_p > rather than Variant* *** dataType now returns directly Attributes rather than Variant* * Modules: ** Reflect changes with Variant Author: jmo Date: Mon May 21 19:43:01 2012 +0200 Set default selection color in listModel Author: jmo Date: Mon May 21 19:22:39 2012 +0200 VFSEvent : Avoid nonetype error when no navigation selected Author: jmo Date: Mon May 21 19:05:03 2012 +0200 FileDialog refresh Fix, and remove selectAll feature from headerView Author: sja Date: Mon May 14 18:36:02 2012 +0200 Modify raid modules CMakelist to remove md_superblock who was not pushed Author: jmo Date: Mon May 14 16:04:10 2012 +0200 Fix Issue 154 Author: jmo Date: Mon May 14 16:01:46 2012 +0200 *NodeBrowser: Add EventHandler in order to refresh list model Author: fba Date: Mon May 14 13:08:40 2012 +0200 This commit results to the creation of mcleodz's branches which add: * GUI ** Completly refactored GUI *** Full MVC compliant GUI (models / views and delegates are now distinct) *** Search widget has also been refactored Author: fba Date: Mon May 14 12:23:00 2012 +0200 This commit results to the merging of vertrex's branches which add: * API ** Implementation of references counting system for DFF's objects (working for Python and C++) ** Implementation of Node tagging methods * GUI ** Implementation of node tagging dialog boxes *** adds tags column and tags information in nodes properties widget *** adds tag managment windows to add new tags and edit existing ones (changing names and colors) Author: rbe Date: Fri May 11 12:33:41 2012 +0200 * beggining of the raid module (raid1 ok) * some changes on ext (warning compilation removed) Author: sja Date: Wed May 9 17:50:25 2012 +0200 NTFS fix infinite loop in deleted, and some random read Author: fba Date: Mon May 7 13:27:28 2012 +0200 * Build system: ** provide ffmpeg cmake module ** main cmakelists informs if ffmpeg libraries are found if so, api/gui/video directory will be included to be compiled ** modifies vfsitemmodel to be able to launch dff even if video module has not been compiled To sum up, this commit just adds what other doesn't :) Author: sja Date: Mon May 7 13:21:42 2012 +0200 FIX 'fat' time usecond was not set to 0 so was set to a random value Author: sja Date: Mon May 7 13:21:18 2012 +0200 remove printed error message Author: sja Date: Mon May 7 13:20:09 2012 +0200 FIX widget taskmanager: when a process is waiting is time was not set to 0 but ctime Author: sja Date: Mon May 7 13:19:38 2012 +0200 FIX preview in case of variant errors Author: sja Date: Mon May 7 13:18:54 2012 +0200 FIX PNG type carving Author: sja Date: Mon May 7 13:17:55 2012 +0200 vlink remove comment Author: sja Date: Mon May 7 13:17:02 2012 +0200 FIX close problem, if somethings try to seek/read/search on a closed vfile throw an error Author: sja Date: Mon May 7 13:16:33 2012 +0200 FIX open/close problem on WINREG & MSIECF modules Author: fba Date: Mon May 7 12:45:30 2012 +0200 * Module FAT ** remove of tree registration for Unallocated and Bad Clusters, directly provides parent node to Node ctor Author: sja Date: Thu May 3 13:22:33 2012 +0200 FIX ntfs segfault when mft is not found Author: fba Date: Wed May 2 19:53:26 2012 +0200 new viewer module for file histogram (byte distribution) need matplotlib Author: fba Date: Tue Apr 24 19:21:11 2012 +0200 simple module which take as input a sample file and look for each chunk of chunk_size in provided dump file Author: sja Date: Fri Apr 20 17:46:00 2012 +0200 varianttreewidget remove print Author: sja Date: Fri Apr 20 16:52:51 2012 +0200 Add relative link path to lnk Author: rbe Date: Fri Apr 20 14:12:09 2012 +0200 extfs : * memory leak fix Author: sja Date: Fri Apr 20 13:06:45 2012 +0200 Video: set log level to QUIET ! Author: rbe Date: Fri Apr 20 10:57:25 2012 +0200 Extfs : * add some documentation * remove useless files / classes / methods * bug fixes * add the Fsck option, which check if inode size matches the number of allocated blocks * add an option used to NOT parse the entire file system if the user just needs to start a simple option (fsstat for example). * add slack files (if any) ; this must be triggered by using the --slack option Others : * remove some compilation warnings in vfs, node and fso * fix a bug which used to occur in magichandler Author: sja Date: Thu Apr 19 13:37:24 2012 +0200 Video Some little refactoring Author: sja Date: Thu Apr 19 12:43:29 2012 +0200 New api video & videoDecoder to get thumbnail and metadata from a video (need ffmpeg libav*) Author: fba Date: Tue Apr 10 11:48:33 2012 +0200 * API: types ** Add VLink support to Variant. This patch enables cast VLink to Node for arguments provided to module. Author: sja Date: Fri Apr 6 13:46:42 2012 +0200 libvfs : getNodeFromPointer can return Node or VLink same for every Node* func() propertytable: start showing of hyperlink Author: sja Date: Thu Apr 5 17:27:52 2012 +0200 Add typemout so getnode return VLink instead of Node Author: rbe Date: Thu Apr 5 14:37:48 2012 +0200 * add slack's nodes and an option to chose to display them (or not by default) * fix a bug that prevented file names to be parsed properly Author: sja Date: Thu Apr 5 13:34:57 2012 +0200 add compound file Author: sja Date: Thu Apr 5 12:29:49 2012 +0200 reanme module and directory Author: sja Date: Thu Apr 5 12:23:03 2012 +0200 office some little fix Author: sja Date: Wed Apr 4 18:52:34 2012 +0200 Metaole add options and editing time fix Author: sja Date: Tue Apr 3 19:38:34 2012 +0200 Metaole: Add options to the module, and metadata attributes to the root node Author: sja Date: Tue Apr 3 13:34:49 2012 +0200 Metaole: some fixes and cleanup Author: sja Date: Fri Mar 30 13:23:24 2012 +0200 metaole : add ppt picture extraction Author: sja Date: Thu Mar 29 18:45:53 2012 +0200 Picture in datastream & picture in worddocument Split the code to reflect ms-documentation Author: sja Date: Tue Mar 27 19:51:40 2012 +0200 Office : worddocument picture extraction near finish to read the picture in the data stream (must do last blip type, create node, comment, remove debug, split code in different file, function , ...) could certainly use the same technique to find extract data and picture in worddocument stream Author: rbe Date: Fri Mar 23 13:56:32 2012 +0100 extfs * all options are back on-line ! Author: sja Date: Thu Mar 22 17:53:24 2012 +0100 Metaoffice start to extract text Author: sja Date: Wed Mar 21 18:30:49 2012 +0100 Start of decoding worddocument Author: rbe Date: Wed Mar 21 11:41:42 2012 +0100 bug fixes on extfs module Author: sja Date: Tue Mar 20 15:24:23 2012 +0100 add olestructure Author: sja Date: Tue Mar 20 13:56:41 2012 +0100 Metaole: Parse word DocumentSummary, SumarryInformation, add some VT class, parse red/black tree correctly, ... Author: sja Date: Fri Mar 16 17:02:14 2012 +0100 Add office document metadata Author: sja Date: Thu Mar 15 19:09:06 2012 +0100 OLE add PropertySetStream decoder Author: sja Date: Wed Mar 14 18:14:29 2012 +0100 FIX DIFAT now handle large file, FAT table is now read enterly and set in memory (faster but use mor memory) Author: sja Date: Wed Mar 14 15:02:55 2012 +0100 ole: minifat parsing is now ok , fix recursive loop in fat index Author: sja Date: Tue Mar 13 18:33:36 2012 +0100 update structure size to ssize Author: sja Date: Tue Mar 13 17:49:52 2012 +0100 commit filecharts fix + libtype.i fix ! les variant inside map are not deleted any more -> huge memory leak Author: sja Date: Tue Mar 13 17:48:57 2012 +0100 add new file olestructure Author: sja Date: Tue Mar 13 17:45:16 2012 +0100 office ->metaoffice Author: sja Date: Tue Mar 13 17:39:09 2012 +0100 add metaole CMakeLists Author: sja Date: Tue Mar 13 17:38:30 2012 +0100 add metaole Author: sja Date: Tue Mar 13 17:38:18 2012 +0100 add metaoffice to cmakelists Author: sja Date: Tue Mar 6 12:38:38 2012 +0100 FIX model save/restor painter Author: sja Date: Tue Mar 6 12:32:04 2012 +0100 VLink fix for tags Author: sja Date: Mon Mar 5 15:53:17 2012 +0100 Tags now use a refcount mechanism Author: sja Date: Tue Feb 28 16:51:19 2012 +0100 FIX magichandler self.load / mime.load Author: sja Date: Tue Feb 28 16:43:53 2012 +0100 TAG: unicode, add nodes number in tagmanager and create a TagItem do handle it PROPERTYTABLE: tag unicode Author: sja Date: Tue Feb 28 16:42:14 2012 +0100 FIX magichandler cmakelist & magichandler.load() != magichandler.load(None) Author: sja Date: Fri Feb 24 17:32:06 2012 +0100 TAG: new widget for tagmanagement and editing add this widget action to nodeviewbox Author: fba Date: Fri Feb 24 15:27:31 2012 +0100 fixes issue in CMakeLists.txt of datatype which omitted to add magichandler.py Author: sja Date: Thu Feb 23 12:14:11 2012 +0100 TAG: fix remove in tags.cpp added to property table added to vfsitemmodel with a vfsitemdelegate add to hash Author: rbe Date: Wed Feb 22 14:14:19 2012 +0100 fix dans magichandler.py Author: sja Date: Tue Feb 21 13:04:06 2012 +0100 layoutmanger : add save of argument forq pathcontainer node/tags/libvfs.i : add class tags and implementation in node winreg : don't create node because didn't close and take too much ram must fix that! must also fix how file are managed because just check the name for the hive is insufficient are all hive are parse but very few used hash: rewrote of hash module to support database !! Author: sja Date: Tue Feb 21 12:47:48 2012 +0100 FIX : Come back of the python magic handle, because of better thread / IO handling, don't need to block anymore, so remove thread block in libfilters.i and libvfs.i, this must be tested on windows ... Add lock in mfso cache, check for NULL in filemapping Author: sja Date: Tue Feb 21 12:29:39 2012 +0100 batch: Now DFF shell command in batch must preceed by ! , other command will be interepret as python code, so you can merge the two in a batch script. Comment line starting with # will no be printed anymore as you can use the python print command. When using it with python think to launch DFF in '-d' mode to have the output redirected Author: sja Date: Tue Feb 21 12:24:05 2012 +0100 FIX: get rid of the limit of mergeable nodes Author: sja Date: Tue Feb 21 12:20:17 2012 +0100 FIX: AttributesMap ownership Author: sja Date: Tue Feb 21 12:13:37 2012 +0100 FIX: Many VFile is open when searching for deleted entry most of them where not close (This still need to have an other FIX and better way to handle the underlying node) Memory leak some object was not deleted Add an options to not check for deleted/orphan files (This fonctionality is still buggy and sometimes goes into infinites loop, so it's a way to bypass iti, or gain time when deleted recovery is not needed) Author: sja Date: Tue Feb 21 12:04:15 2012 +0100 FIX: close opened VFile for bootsector on error Author: Frederic Baguelin Date: Wed Feb 8 19:00:31 2012 +0100 * API: ** changed list to vector (which consumes far less memory and is faster) in VFile searches ** methods also return pointer to avoid copy... * Modules: ** Extfs to reflect changes in VFile search Author: Frederic Baguelin Date: Thu Jan 19 13:14:29 2012 +0100 * Build process: ** patch to ease integration and linking of ICU library by giving the ability to specify the libraries and include dirs Author: Frederic Baguelin Date: Tue Jan 17 18:13:10 2012 +0100 * fixes typo error in ide skeletton generator Author: sja Date: Thu Jan 12 17:10:56 2012 +0100 FIX time of processus raising exception didn't stop Author: sja Date: Mon Jan 9 12:24:07 2012 +0100 Set subject as node name (rather than message1, task2, ...) Author: jmo Date: Fri Jan 6 12:59:50 2012 +0100 * New attribute selection system * Bugfix model / view * Disable attributeworker Author: sja Date: Fri Jan 6 12:57:13 2012 +0100 EWF FIX: Open only one time the files with libewf_..._open and use locks (like AFF modules) because libewf_..._open is too slow to be called each times a file is virtually opened Author: jmo Date: Fri Dec 23 11:53:07 2011 +0100 * Model / View : ** Improve model ** Add List view with icon view ** Add toolbar in main widget ** Add workers Author: Frederic Baguelin Date: Thu Dec 22 14:25:52 2011 +0100 * API: Filter ** some refactoring concerning notification to watchers ** process now supports list and vector of nodes Author: jmo Date: Mon Dec 19 15:55:56 2011 +0100 * Model / view ** Add attribute widget ** Connect all signals for keypressevent and mouseclick ** Refresh attributes and preview widgets Author: jmo Date: Mon Dec 19 14:13:17 2011 +0100 * Model bugfix : missing refresh setVisibleRows if not condition Author: Frederic Baguelin Date: Fri Dec 16 15:54:10 2011 +0100 * Modules: Fatfs ** fixes bug in fileMapping when cluster chain is empty Author: Frederic Baguelin Date: Thu Dec 15 12:30:25 2011 +0100 * API: GUI ** Search widget now handles utf8 for all input *** node path, selected node, attributes, search clauses Author: Frederic Baguelin Date: Wed Dec 14 17:17:16 2011 +0100 * Modules: FATFS: ** removes all warnings *** signed / unsigned comparisons *** set but not used Author: Frederic Baguelin Date: Wed Dec 14 16:52:18 2011 +0100 * Modules: FATFS ** fixes dataType for FAT node which can be mapped to boot sector because of silly use lseek in local ** all return of read are fully checked Author: Frederic Baguelin Date: Wed Dec 14 15:06:43 2011 +0100 * Modules: FATFS This commit adds several new features and some bugfixes ** faster algorithms for FAT statistics (I/O reduced) ** clusters loop is now handled in cluster chain (one cluster points to the first one of the list for example) ** bad clusters are fully handled at several steps and nodes are created for each bad clusters space ** nodes representing FAT have new attributes: *** free clusters count *** bad clusters count *** allocated clusters count ** nodes representing files provide new attributes: *** missing clusters (if there are) *** size of missing part *** truncated status ** better slack space managment *** no longer relies on (filesize % clustersize) but on the size of the chain of clusters. Clusters chain is now used for file slack mapping (if possible) Author: Frederic Baguelin Date: Thu Dec 8 16:27:07 2011 +0100 * BUGFIX this commit fixes #127 ** FileMapping chunk resolution from offset has been fixed ** Pushing chunks in an unordered way is now fully functionnal ** requesting chunk from an offset which is not mapped will result in a shadow chunk automatically inserted in the chunk list ** typo error for chunck has been replaced (chunk) Author: sja Date: Thu Nov 24 12:42:38 2011 +0100 Layoutmanger fix module config graphical generator bug when right with module taking a single path argument (ex: fuse) Author: sja Date: Wed Nov 23 18:22:20 2011 +0100 FIX bug in fuse modules, disallow debug options, disallow threads, run in background Author: sja Date: Wed Nov 23 16:27:02 2011 +0100 LNK: move item related codes into a dedicated file use function Author: sja Date: Wed Nov 23 13:57:53 2011 +0100 LNK: continue to refacto item Author: sja Date: Wed Nov 23 13:24:53 2011 +0100 LNK: start moving Item function in lnkheader Author: sja Date: Tue Nov 22 18:09:46 2011 +0100 lnk/CMakelists add lnkheader.py Author: sja Date: Tue Nov 22 18:06:21 2011 +0100 LNK: move AttributesVMap, attributesMap (codes), to structparser as it's reusable Author: sja Date: Tue Nov 22 17:37:31 2011 +0100 LNK: Move ResolveAttributesMap (most attributesMap code) to structparser as it could be reused Author: sja Date: Tue Nov 22 16:46:52 2011 +0100 Move FlagsList (getFlags) to structparser as it could be usefull for other module Author: sja Date: Tue Nov 22 15:22:33 2011 +0100 LNK: refacto -> getDataBlock() Author: sja Date: Tue Nov 22 15:02:37 2011 +0100 LNK refacto, HasLinkInfo Author: sja Date: Tue Nov 22 14:56:07 2011 +0100 LNK refacto => HasLinkTargetIDList Author: sja Date: Tue Nov 22 13:52:44 2011 +0100 LNK: Move header and structure in a separate files Author: Frederic Baguelin Date: Mon Nov 21 13:16:51 2011 +0100 * Module: Fatfs: ** patching issue with toUTF8String in fattree Author: Frederic Baguelin Date: Tue Nov 15 13:08:11 2011 +0100 * Module NTFS ** names are now converted from UTF-16LE to UTF-8. Author: Frederic Baguelin Date: Tue Nov 15 13:01:21 2011 +0100 * Module FATFS ** Long File Names are now converted from UTF-16LE to UTF-8 ** converting 8+3 names will be more difficult since it depends on codepage used on the computer which created an entry Author: Frederic Baguelin Date: Tue Nov 15 12:50:28 2011 +0100 * Building process ** adds cmake module for ICU library and find_package(ICU REQUIRED) in main CMakeLists.txt ** this provides support for character encodings managment in DFF. The aim is that all strings are encoded in UTF-8 Author: sja Date: Mon Nov 7 18:06:19 2011 +0100 structparser add short type parsing Author: sja Date: Thu Nov 3 18:58:26 2011 +0100 New lnk attributes parsing more readable Author: sja Date: Thu Nov 3 16:17:53 2011 +0100 Found new way of decoding item id / shellbag 0x35 & 0x36, seem to work better, also test 'next strings' seem to work well too Author: sja Date: Thu Nov 3 13:14:38 2011 +0100 Decode Item ID type 0x36 Author: sja Date: Wed Nov 2 19:31:21 2011 +0100 Found how work 0x35 undocumented struct ... Author: Frederic Baguelin Date: Fri Oct 28 17:25:10 2011 +0200 * BUGFIX: bad condition checking in Variant ctor Author: sja Date: Fri Oct 28 16:55:30 2011 +0200 LNK darwin datablock & avoid infinite loop Author: sja Date: Fri Oct 28 14:22:47 2011 +0200 LNK add darwin data block Author: sja Date: Fri Oct 28 13:35:55 2011 +0200 LNK add ConsoleDataBlock ! Author: sja Date: Thu Oct 27 20:14:29 2011 +0200 Parse list value of PropertyStorage Author: sja Date: Thu Oct 27 18:18:19 2011 +0200 Add property store and some unpack of serialized data Author: sja Date: Thu Oct 27 14:00:44 2011 +0200 lnk start to add PropertyStorage Author: sja Date: Thu Oct 27 13:04:00 2011 +0200 FIX unicode EnvironmentVariableDataBlock IconEnvironmentVariableDataBlock Author: sja Date: Wed Oct 26 20:23:06 2011 +0200 LNK add first DataBlock decoding Author: sja Date: Tue Oct 25 20:54:36 2011 +0200 LNK : Net name added Author: sja Date: Tue Oct 25 20:17:24 2011 +0200 LNK : Add network provider maps Author: sja Date: Tue Oct 25 19:53:36 2011 +0200 LNK : Before parsing CommonNetworkRelativeLink Author: sja Date: Tue Oct 25 18:46:20 2011 +0200 LNK : Add VolumeID and other very fun stuff Author: sja Date: Tue Oct 25 14:11:43 2011 +0200 Get recursive dictionary / list and other type the right way Author: sja Date: Tue Oct 25 13:02:48 2011 +0200 move structparser to metadata Author: sja Date: Tue Oct 25 12:51:24 2011 +0200 Add msdos32bits time to vtime contstructor, modify FATFS module to use it directly Author: sja Date: Mon Oct 24 20:30:03 2011 +0200 LNK : Add support for list target link not finished yet Author: sja Date: Mon Oct 24 14:24:01 2011 +0200 LNK :Add hotkey flags to lnk Author: sja Date: Mon Oct 24 14:03:21 2011 +0200 LNK : Add showcommand and other decoding sutff to lnk Author: sja Date: Mon Oct 24 13:15:06 2011 +0200 change prefetch path to structparsre Author: sja Date: Mon Oct 24 13:14:30 2011 +0200 move structparser and add it to cmakelist Author: sja Date: Mon Oct 24 13:13:54 2011 +0200 Add start of lnk parser Author: fba Date: Thu Oct 20 16:01:03 2011 +0200 * Packaging: ** removes wrong entries in some CMakeLists resulting in cpack errors Author: fba Date: Thu Oct 20 15:59:01 2011 +0200 * Packaging ** temporary workaround for pyregfi on Windows platform Author: fba Date: Thu Oct 20 15:57:30 2011 +0200 * BUGFIX: winreg ** CVariant method in nodes.py now encloses Variant creation un try / except Author: jmo Date: Thu Oct 20 12:53:52 2011 +0200 * Browsers bugfixes ** Add try / except in inputHistory when parsing registry elements Author: Frederic Baguelin Date: Wed Oct 19 18:57:11 2011 +0200 * BUGFIX threading (credits: Solal Jacob) ** For some cases, there was a deadlock while performing a search and clicking on a matching node. When there was a Python MFSO in the I/O stack, leads to deadlock between Python GIL and datatype mutex. ** This fix is not optimized yet (very slow datatype currently) but avoids the deadlock. Author: Frederic Baguelin Date: Wed Oct 19 18:47:22 2011 +0200 * BUGFIX: Variant ** all ctor taking a pointer now check if it is not NULL. Otherwise throw an error Author: Frederic Baguelin Date: Wed Oct 19 18:33:45 2011 +0200 * BUGFIX: Variant ** Variant ctor used in Python (Variant(PyObject*, uint8_t) now checks that PyObject is not None. Otherwise, it throws an error Author: sja Date: Wed Oct 19 13:20:08 2011 +0200 FIX bug : some time pyregfi iterator throw exception, catch it and continue Author: fba Date: Tue Oct 18 16:02:37 2011 +0200 * Packaging: apsw ** adds apsw installer for Windows Author: sja Date: Sat Nov 12 17:59:44 2011 +0100 Fix Variant deletion problem with prefetch module Version 1.2.0 (04 October 2011) =============================== Author: jmo Date: Tue Oct 4 12:50:38 2011 +0200 * Module: hexviewer ** QGraphicsView is now instantiate with arguments ! QGraphicsScene is setted to None and QWidget to provided parent. If not instantiated with parent, it leads to crashes with the preview which destroys each widget Author: sja Date: Mon Oct 3 19:08:29 2011 +0000 Change ui/gui/gui.py to add version number dynamically in version 1.2 Author: Frederic Baguelin Date: Mon Oct 3 19:14:14 2011 +0000 * GUI: search ** disable quick search functions since model are totally desynchro with filtering results. Start SearchWidget when clicking the binoculars icon Author: sja Date: Mon Oct 3 18:27:57 2011 +0000 NTFS : boot change printf to DEBUG message Author: Frederic Baguelin Date: Thu Sep 29 17:31:08 2011 +0000 * GUI: Interpreter ** excecutes runsource in a thread to prevent GUI freeze for huge process ** import useful class in the interpreter environment Author: sja Date: Wed Sep 28 15:53:38 2011 +0000 now sort the modules tags before creating the tags menu Author: sja Date: Wed Sep 28 15:37:51 2011 +0000 k800i.py use new find syntax Author: Frederic Baguelin Date: Wed Sep 28 15:43:28 2011 +0000 * Modules: web viewer ** deactivate javascript and activate private browsing Author: Frederic Baguelin Date: Wed Sep 28 15:33:07 2011 +0000 * Modules: batch ** why removing \n ? Author: Frederic Baguelin Date: Wed Sep 28 15:19:46 2011 +0000 * Modules: web viewer ** When links are external, do not let the possibility to go on the remote URL Author: Frederic Baguelin Date: Wed Sep 28 15:18:56 2011 +0000 * Modules: text viewer ** when setting text, interpret it as PlainText Author: Frederic Baguelin Date: Wed Sep 28 13:47:08 2011 +0000 * Modules: carverui ** wait for the real carving process before returning Author: Frederic Baguelin Date: Wed Sep 28 13:40:02 2011 +0000 * Modules: carver ** removes print ** changes tags from Search to builtins in carverui and carver.i to be not displayed in gui Author: fba Date: Wed Sep 28 01:38:35 2011 +0200 * Modules: open ** better information when there's no module to handle types of a node Author: fba Date: Wed Sep 28 01:38:02 2011 +0200 * Modules: load ** handles argument as it has to be... Author: fba Date: Wed Sep 28 01:36:56 2011 +0200 * API: loader ** if a module has to be reloaded, before destroying its instance, unregister its configuration first Author: fba Date: Wed Sep 28 01:34:13 2011 +0200 * API: libtypes ** argument, config and constant dtor implemented ** add unregisterConf(string modname) method to remove an already registered configuration. This is mainly used when a module already loaded is loaded another time ** module.py when creating Config, removes ownership of the config since it is owned in ConfigManager singleton Author: Frederic Baguelin Date: Tue Sep 27 15:43:27 2011 +0000 * Build ** removes useless linking with libmagic in datatype (does not link on Windows) ** adds proper linking information with libmagic in magic api Author: cma Date: Tue Sep 27 15:57:16 2011 +0200 Fixes for Windows version shipped with all dependencies. There was a problem on Python and PyQt4 installation, Python was not installed for all users instead of PyQt4, resulting in launch failure and unusable Python Qt4. Author: Frederic Baguelin Date: Mon Sep 26 15:43:39 2011 +0000 * API: magic ** removes useless python wrappers for libmagic Author: Frederic Baguelin Date: Mon Sep 26 15:37:17 2011 +0000 * API: manager ** changes import in manager to get MimeType and MagicType from libmagichandler * Build: datatype ** removes magichandler.py Author: Frederic Baguelin Date: Mon Sep 26 15:20:13 2011 +0000 * API: datatype / magic ** call to magic handlers is fully implemented in C++. This removes bad behaviour when calling dataType in two threads. Author: jmo Date: Mon Sep 26 11:22:00 2011 +0200 * Attributes tree ** Connect doubleClicked signal in order to catch attribute item ** Display item name + value in a messagebox (Information) Author: Frederic Baguelin Date: Fri Sep 23 18:52:10 2011 +0000 * Build ** removes no longer generated file in ui/gui/resources Author: Frederic Baguelin Date: Fri Sep 23 15:51:01 2011 +0000 * API: GUI ** removes bugs and bad widget size Author: Frederic Baguelin Date: Fri Sep 23 15:21:52 2011 +0000 * API: GUI ** removes calls on non existent checkboxattributes Author: Frederic Baguelin Date: Fri Sep 23 14:22:06 2011 +0000 * GUI: preview ** when widget is not visible, do not refresh content ** when used viewer is player, do not delete on close (otherwise, global audio / video / media are destroyed and player won't work anymore) Author: Frederic Baguelin Date: Fri Sep 23 12:57:46 2011 +0000 * API: GUI ** selection of extended attributes to add new column was broken since there is now GC on VMap. Author: cma Date: Fri Sep 23 14:26:51 2011 +0200 Updates Italian translation, thanks to Francesco ! Author: Frederic Baguelin Date: Fri Sep 23 12:14:15 2011 +0000 * API: loader ** changes try / except based on ImportError to Exception when loading modules Author: Frederic Baguelin Date: Fri Sep 23 12:10:22 2011 +0000 * GUI: search nodebrowser ** disables sorting for each columns Author: Frederic Baguelin Date: Fri Sep 23 11:44:23 2011 +0000 * GUI: search widget ** __totalhits class attribute was not updated and was always setted to 0. This disables the possibility to export selected nodes Author: Frederic Baguelin Date: Fri Sep 23 11:43:07 2011 +0000 * GUI: search widget dialog ** When extended attributes were added and then removed, they appeared in the QComboBox. Author: Frederic Baguelin Date: Fri Sep 23 11:40:10 2011 +0000 * GUI: search widget ** better ergonomy. Path information has been moved at top Author: Frederic Baguelin Date: Thu Sep 22 19:23:19 2011 +0000 * API: loader ** Errors generated while loading a module are only provided after all succefully loaded modules Author: Frederic Baguelin Date: Thu Sep 22 19:22:33 2011 +0000 * GUI: ** Splashscreen no longers provide version Author: cma Date: Thu Sep 22 15:43:57 2011 +0200 Updates translation: - German, thanks to Denis ! - Spanish, thanks to Pablo ! - French - Every others files remaining to update Fixes typo in several files: dictionary & an attribute. Author: cma Date: Thu Sep 22 14:57:45 2011 +0200 Graphical clean of advanced search engine. Author: Frederic Baguelin Date: Thu Sep 22 13:48:20 2011 +0000 * Build: pff ** libbfio.dll was not set as source_files resulting of unloadable module Author: Frederic Baguelin Date: Thu Sep 22 13:47:24 2011 +0000 * Starter script ** there were both spaces and tabs for indentation. IDLE does not seem to like it... Author: Frederic Baguelin Date: Thu Sep 22 13:17:47 2011 +0000 * Build ** Automatic installer scanning work fine but CMAKE variables are GLOBAL from one directory to all its subdirectories but not available from parent's one... It's needed to specify PARENT_SCOPE while using SET() command Author: Frederic Baguelin Date: Thu Sep 22 13:14:28 2011 +0000 * Build: ** two generated (uitopy) files in ui/gui/ressources were missing, resulting to bad packages generation Author: Frederic Baguelin Date: Thu Sep 22 12:34:58 2011 +0000 * Build ** dependencies binaries for Windows are no longer hand written in CMakeLists.txt. It now scan the content of the directory and find python, pyqt and vcredist executable by itself ** Minor version change from 1 to 2 Author: Frederic Baguelin Date: Thu Sep 22 12:32:47 2011 +0000 * Modules: web viewer ** add __init__.py to be able to import module and to let cpack run properly Author: Frederic Baguelin Date: Wed Sep 21 17:22:00 2011 +0000 * Build: readlines ** copy _READLINE.dll from release directory into current_binary_dir Author: Frederic Baguelin Date: Wed Sep 21 17:21:37 2011 +0000 * Build: ewf ** changes ewf.dll to libewf.dll Author: Frederic Baguelin Date: Wed Sep 21 17:20:45 2011 +0000 * Build: Search api ** removes useless dll and changes name tre4.dll to tre.dll Author: Frederic Baguelin Date: Wed Sep 21 15:29:07 2011 +0000 * GUI: Preview ** Each generated widget (and so the underlying module instance) were never deleted because widgets were not deleted on close(). Refcount never reached 1 Author: Frederic Baguelin Date: Wed Sep 21 15:26:27 2011 +0000 * API: Variant ** adds VMap destructor. Removes lots of memory leak ! Before this patch, each time a method returning a VMap (map), the latter were never delete. ** python extended code for value method has been adapated to only removes ownership on vtime, vlist and vmap Author: Frederic Baguelin Date: Tue Sep 20 16:08:55 2011 +0000 * API: VFS (Nodes and VLinks) ** For attributes*, dataType and compatibleModules methods provided by Node and VLink, ownership of returned objects is transfered to Python by with %newobject macro of SWIG (removes lots of memory leak !) *** next commit will provide a new wrapper for delete_VMap in order to delete all contained pointers of Variant Author: Frederic Baguelin Date: Tue Sep 20 16:01:49 2011 +0000 * Module: Fatfs ** bootsector result attributes changed for "cluster size" to "sectors per cluster" ** ReservedSectors node missed one sector and size was not handled correctly. Since ReservedSectors node starts at bootsector, dataType() method has been overloaded to avoid infinite loop when postprocessing ** UnallocatedSpace nodes didn't handle size correctly in fileMapping (forget to multiply by sector size...) ** Memory leak free concerning _attributes method. opened VFile was closed but never deleted Author: Frederic Baguelin Date: Tue Sep 20 15:55:46 2011 +0000 * API: Node ** All attributes method have been rewritten and optimized. ** Thanks to the new Variant ctor, all memory leaks have been removed. Temporary Variant are deleted and Variant based results relies on copy ctor ** extension() method has been added which (as its name is self explanatory), returns the extension if "." is rfind in its name Author: Frederic Baguelin Date: Tue Sep 20 15:54:52 2011 +0000 * API: VFS ** removes warning comparison between signed and unsigned Author: Frederic Baguelin Date: Tue Sep 20 15:51:47 2011 +0000 * API: Variant ** reflects new constructor which changes wrapping number with SWIG ** value() method in Python extended code removes ownership to avoid crashes !!! Author: Frederic Baguelin Date: Tue Sep 20 15:48:26 2011 +0000 * API: Variant ** A new constructor is provided to create a copy of a Variant (Variant::Variant(class Variant* origin) ** In dtor, additionnal checks are done before calling delete, and pointers are set to NULL ** In toString method, check if pointer is NULL Author: Frederic Baguelin Date: Tue Sep 20 15:45:43 2011 +0000 * API: Filters ** AstNodes are now able to evaluate relative attributes name Author: Frederic Baguelin Date: Tue Sep 20 15:41:33 2011 +0000 * API: GUI ** search_widget no longer emits signal when nodes match. It directly calls model addNode and current matching nodes counter is based on model rowCount() method ** nodefilterbox no longer relies on signals to refresh view. It's FilterThread which directly calls addNode on its model Author: Frederic Baguelin Date: Tue Sep 20 15:39:15 2011 +0000 * Module: cat ** uses vfile search abilities (instead of reading buffer and applying python re) to find \n ** fixes a bug when there were only one line Author: Frederic Baguelin Date: Tue Sep 20 15:38:23 2011 +0000 * Build ** add subdirectory(web) in viewer CMakeLists.txt Author: Frederic Baguelin Date: Tue Sep 20 15:37:20 2011 +0000 * API: search node browser ** remove useless connection to VFS events Author: Frederic Baguelin Date: Tue Sep 20 15:35:32 2011 +0000 * API: GUI ** changes fillingList method to addNode in vfsitemmodel class to have the same interface than ListModel Author: Frederic Baguelin Date: Tue Sep 20 15:34:03 2011 +0000 * Module: Partition ** removes unused variables Author: Frederic Baguelin Date: Tue Sep 20 15:30:17 2011 +0000 * API: mimetree ** mimetree extracts mimetype in compiled magic files (magic.mgc) and support version 7 and 8. The resulting extraction is a two-level tree filled with main categories of mimetype (images, videos, ...) and their subcategories (jpeg, avi, ...) ** This class was previously implemented in SelectMimeTypes file and has been moved in the datatype API Author: Frederic Baguelin Date: Tue Sep 20 15:28:42 2011 +0000 * Modules ** new viewer module to display html pages (css taken into account if found) ** enhancement of text viewer (cat), which is streamed ! Author: Frederic Baguelin Date: Tue Sep 13 17:58:57 2011 +0000 * GUI ** search widget: remove of dictionnary abilities and ts() for date time Author: cma Date: Tue Sep 13 18:07:40 2011 +0200 Translation ; removes no more used strings from fba. Author: cma Date: Tue Sep 13 17:31:01 2011 +0200 Translation updates, adds strings to be translated in: - Dff_de.ts, German translation - Dff_es.ts, Spanish translation - Dff_it.ts, Italian translation - Dff_nl.ts, Dutch translation - Dff_zh.ts, Chinese translation Translates Dff_fr.ts ; French language file. Also fix typo, rename 'pannel' to 'panel' everywhere in sources. Author: cma Date: Tue Sep 13 16:57:35 2011 +0200 Removes attributes checkbox in node browser buttons box and uses an icon instead, as others functions do. So adds an icon for it, disabled or no. Also swap icon states for thumbnail view, there was a misstake. Author: cma Date: Tue Sep 13 14:49:46 2011 +0200 Minor: removes unused and forgotten treeModel Author: Frederic Baguelin Date: Tue Sep 13 12:38:08 2011 +0000 * API: vtime ** just check if provided vtime in operator methods is not NULL else return appropriate boolean Author: Frederic Baguelin Date: Tue Sep 13 12:34:54 2011 +0000 * API: Filters ** add very bad and ugly try {} catch (...) because DFF lacks of exceptions Author: Frederic Baguelin Date: Tue Sep 13 12:08:39 2011 +0000 * Modules: Carver ** removes wildcard abilities in carving. Carver has to be rewritten for next release Author: jmo Date: Thu Sep 8 16:00:38 2011 +0200 * Evidence dialog ** Set a fixed height size and inscrease default height size Author: jmo Date: Thu Sep 8 11:39:33 2011 +0200 * Preview ** Remove debug Author: jmo Date: Thu Sep 8 11:32:26 2011 +0200 * Preview ** Remove checkbox in preview dockwidget ** Create a new checkable action (actionPreview) in view menu (mainwindow) ** Connect this action to preview dockwidget (enable / disable preview) Author: jmo Date: Wed Sep 7 11:42:19 2011 +0200 * Evidence dialog various bugfixes ** Change layout stretch factor for files formats ** Do not add empty entry in list when cancel directory dialog Author: Frederic Baguelin Date: Tue Sep 6 18:00:34 2011 +0000 * API: GUI ** search_widget events has been changed and e.value.value() is now associated to a value begore emitting... (possible cause of not catchable exceptions) ** ListNodeModel addNode method now takes node.this in argument Author: Frederic Baguelin Date: Tue Sep 6 17:54:11 2011 +0000 * API: Filters ** event types are now an enum to use them easily. A new event has also been added --> EnfOfProcessing ** when processing matched nodes are stored internally and can be request through matchedNodes() method ** stop event is better handled (every astnodes received the event but main *process* method did not check the __stop attributes in their loop... Author: Frederic Baguelin Date: Mon Sep 5 18:44:14 2011 +0000 * Modules: FAT ** adds unallocated space ** adds slack space for regular files *** default behaviour is to create all regular files slack space with .SLACK extension. There's also an option to check is the slack is empty. If empty (only zero) nodes are NOT created ** adds state information ** Author: Frederic Baguelin Date: Mon Sep 5 16:51:18 2011 +0000 * Modules: FAT ** removes compile warning (uninitialez / not used variables) Author: Frederic Baguelin Date: Mon Sep 5 16:42:41 2011 +0000 * Modules: FAT ** add Unallocated and FileSlacks Nodes classes Author: Frederic Baguelin Date: Mon Sep 5 16:40:39 2011 +0000 * Modules: FAT ** adds stateinfo while getting free clusters count ** allocated clusters = total clusters - freeclusters Author: Frederic Baguelin Date: Mon Sep 5 16:35:12 2011 +0000 * Modules: Fat ** added fat type information (12/16/32) in results Author: rbe Date: Mon Sep 5 16:53:54 2011 +0200 add a fix Author: jmo Date: Mon Sep 5 16:47:28 2011 +0200 Slider operations are now implemented in pixel and string view. String view should be considerated as beta version. Indeed some navigation features are not very intuitives Author: jmo Date: Mon Sep 5 16:32:44 2011 +0200 You can now trigger the cursor or its area to navigate within the page view Author: Frederic Baguelin Date: Mon Sep 5 10:10:24 2011 +0000 * Modules: Partition ** PartitionNode overloads dataType() method when it is an unallocated space node to avoid infinite loop with post-processing. Author: Frederic Baguelin Date: Fri Sep 2 19:36:14 2011 +0000 * Modules: Fat ** Adds file system slack space (size diff between reading file (parent) and total sector defined in boot sector) ** Adds reserved sectors space ** Adds FAT as Nodes with metadata (free cluster + allocated clusters) <-- algos have to be merged + bad cluster checks ** When first FAT size is less than 10MB, it is loaded in RAM to enhance cluster reading. If size is greater or another FAT is used to request cluster, fallback to read method (slower since reading 2 or 4 bytes at a time for each cluster... When there's a huge cluster chain it's too slow) Need to develop a read cache ! ** Adds Volume Label name as first root instead of "Fat File System". If none, it is setted to NONAME Author: Frederic Baguelin Date: Thu Sep 1 14:05:03 2011 +0000 * Modules: ewf ** changes return -1 to 0 in close() method when successful Author: Frederic Baguelin Date: Thu Sep 1 14:02:50 2011 +0000 * Modules: hash ** when several hash algorithms are provided, processed them all together in the reading loop and not one after one... Author: Frederic Baguelin Date: Thu Sep 1 12:56:50 2011 +0000 * Modules: Partition ** cast in uint64_t pte->total_blocks (which is uint32_t) to avoid overflow and so bad size settings Author: Frederic Baguelin Date: Thu Sep 1 12:55:58 2011 +0000 * API: Search ** defines tre_free as tre_regfre on Windows platform Author: Frederic Baguelin Date: Thu Sep 1 12:54:46 2011 +0000 * Build process: ** checks if compiling for WIN32 target on 64 bits platform to not set HAVE_64_BITS and -DSWIGWORDSIZE=64 Author: Frederic Baguelin Date: Wed Aug 31 17:43:35 2011 +0000 * Modules: Ewf ** BUGFIX: when volume name was not define module crashed due a bad handling of returned value ** hashes are provided in nodes attributes Author: Frederic Baguelin Date: Wed Aug 31 16:45:14 2011 +0000 * Modules: dos partitions: ** Mostly rewritten to manage more information *** unallocated space is now created *** meta information are better handled *** first extended partition (in mbr) is no longer created *** manages up to uint32_t entries (primary + logical) *** complete results *** node fileMapping manages odd cases Author: Frederic Baguelin Date: Thu Aug 25 16:29:40 2011 +0000 * Build process: ** remove of add_custom_target(module ...) which caused strange behaviour. Provide yourself -i switch to command make if you don't want to stop at the first encountered error Author: Frederic Baguelin Date: Thu Aug 25 15:02:32 2011 +0000 * GUI: taksmanager widget ** fixes a typo error which led to the unavailability of module's results Author: Frederic Baguelin Date: Thu Aug 25 13:53:23 2011 +0000 * API: magic ** bugfix in magichandler.py. When libmagic cannot determine type properly, buffer function return NULL. Check is now done if filemime exists, otherwise returns "data" Author: Frederic Baguelin Date: Thu Aug 25 11:23:52 2011 +0000 * API: GUI search_widget: ** adds a Warning messagebox when compiling clauses throws an error Author: Frederic Baguelin Date: Thu Aug 25 11:22:02 2011 +0000 * API: Filter ** astnodes --> at compile step, call Search::compile() method instead of doing it (internally in search class) during processing ** enables to know at compile time (and no longer at runtime) when a pattern is not valid Author: Frederic Baguelin Date: Thu Aug 25 11:14:44 2011 +0000 * API: Search ** use internal tre_free instead of tre_regfree to avoid crashes when libtre uses system regex.h *** in tre.h if the library is compiled with system regex --> #define tre_regfree regfree... *** workaround is to declare extern void tre_free(regex_t*) and use tre_free directly ** compile method which was private becomes public: __compile() --> compile(). It is used by filters api when compiling itself Author: Frederic Baguelin Date: Wed Aug 24 18:33:36 2011 +0000 * API: search ** on some architecture and depending of compiler (and flags), tre_regcomp has strange behaviour. tre_regncomp is now used Author: Frederic Baguelin Date: Wed Aug 24 16:42:04 2011 +0000 * GUI: search_widget ** BUGFIX: default name searches with regexp processor based on r() instead of re() Author: Frederic Baguelin Date: Wed Aug 24 14:25:09 2011 +0000 * API: Graphical Search ** FilterThread supports new Filter method processFolder: *** (de)activate by using setOneFolder(True/False) ** QuickSearch now handles to filter the current folder Author: Frederic Baguelin Date: Wed Aug 24 14:24:28 2011 +0000 * API: Node ** totalChildrenCount now handles depth Author: Frederic Baguelin Date: Wed Aug 24 14:23:24 2011 +0000 * API: Filters ** new method added to process one folder only --> processFolers(Node* folder) Author: Frederic Baguelin Date: Wed Aug 24 13:17:24 2011 +0000 * GUI: search_widget ** removes default behaviour (debug) in filterThread Author: Frederic Baguelin Date: Wed Aug 24 12:53:35 2011 +0000 * GUI: SearchWidget ** search now supports stopping process ** Events are managed in FilterThread which emit the a signal for progress bar (between 0 and 100), and for matched nodes Author: Frederic Baguelin Date: Wed Aug 24 12:50:50 2011 +0000 * API: Stop processing event ** Filters, astnodes and VFiles can now stop their processing when receiving an event Author: Frederic Baguelin Date: Tue Aug 23 13:06:40 2011 +0000 * API: filters: ** remove 3 rules in parser.y (related to time_filter which added one reduce conflict). Need to "refactor" grammar ** astnodes StringFilter for mime type only use "mime type" attribute and is now search as fixed string *** either you can search main categories such as "image" or more accurate categories such as "image/jpeg" but "jpeg" alone won't work. To enable jpeg, you have to provide a processor by providing a filter such as mime == w("jpeg", i) Author: Frederic Baguelin Date: Mon Aug 22 19:37:38 2011 +0000 * GUI: ** When filtering Mime types are based on mime types found in compiled magic file Author: Frederic Baguelin Date: Mon Aug 22 17:14:35 2011 +0000 * Build process ** Find{TRE,AFF,EWF,BFIO,PFF} enhancements to be able to compile version programs on Windows. ** On Windows, no longer need to modify include files of bfio, pff and ewf * Includes ** stdint.h is now included when _MSC_VER >= 1600 * Module: ewf ** strdup added when copying path variable to ewf::files Author: Frederic Baguelin Date: Wed Aug 17 16:32:37 2011 +0000 * Build ** clean of root CMakeLists.txt * API search ** remove define for tre functions call (minimum version is now 0.8) Author: Frederic Baguelin Date: Wed Aug 17 16:03:55 2011 +0000 * Build process: ** BFIO, EWF, PFF and TRE needed variables are obtained via cmake modules ** adds -D INCLUDEDIR= and -D LIBDIR= to add non standard include and library directories respectively Author: Frederic Baguelin Date: Tue Aug 16 19:22:04 2011 +0000 * API: vfs ** removes codes which does not compile on Windows Platform Author: Frederic Baguelin Date: Tue Aug 16 19:20:53 2011 +0000 * API: search ** adds wrappers to compile on Windows Platform (libtre differences in prototypes + __value class attributes forbidden with VS...) Author: Frederic Baguelin Date: Tue Aug 16 19:19:39 2011 +0000 * API: filters ** adds try / catch block when performing keywords searches in node content ** adds wrappers to compile on Windows Platform Author: Frederic Baguelin Date: Tue Aug 16 19:16:47 2011 +0000 * Module AFF: ** minor patch to compile and run with aff version lesser than 3.6.8 (default distribution packages are 3.5.12) Author: Frederic Baguelin Date: Tue Aug 16 19:14:31 2011 +0000 * Build process ** enhancements: *** will detect installed version of AFF library. If version > 3.6.6, "new" API is used in cpp (provides cmake module for AFF) ** bugfixes: *** build process for Windows Platform patch Author: Frederic Baguelin Date: Tue Aug 16 15:47:03 2011 +0000 * Modules: ewf connector ** the module is now libewf API 2 compliant (tested with 20110801 version) Author: rbe Date: Thu Aug 4 17:51:10 2011 +0200 search * fix a bug in the quick search Author: rbe Date: Thu Aug 4 10:51:15 2011 +0200 search * add a kind of fetch more in the widget displaying search results * some tests are required Author: Frederic Baguelin Date: Wed Aug 3 16:24:02 2011 +0000 * Search API: ** minor fix in wildcard search Author: Frederic Baguelin Date: Tue Aug 2 16:32:03 2011 +0000 * Console ** When generating arguments, if it is of type String, all escape are replaced ("\ ", " ") Author: Frederic Baguelin Date: Tue Aug 2 16:30:36 2011 +0000 * Filter API ** when compile method is called, check is done on root ast node to know if we need to delete the AST before compiling Author: Frederic Baguelin Date: Tue Aug 2 16:29:09 2011 +0000 * Filter API ** All filters now handles correctly extended attributes Author: Frederic Baguelin Date: Mon Aug 1 18:05:29 2011 +0000 * Search API ** adds #if HAVE_TRE in Search ctor to enable compile when library is not installed Author: Frederic Baguelin Date: Mon Aug 1 18:01:37 2011 +0000 * Module find ** tag changed from "search" to "Search" ** description of expression reflects the good syntax ** root node to save results changed from "Searched Items" to "Searched items" Author: Frederic Baguelin Date: Mon Aug 1 18:01:08 2011 +0000 * widget Preview re-enabled Author: Frederic Baguelin Date: Mon Aug 1 16:07:57 2011 +0000 * New module: find ** console module providing filter capabilities ** recursion control, save matching node under /Searched Items, verbose mode (print matching nodes during processing) Author: Frederic Baguelin Date: Mon Aug 1 16:07:17 2011 +0000 * Filter API ** Filters dtor implemented Author: Frederic Baguelin Date: Mon Aug 1 12:51:47 2011 +0000 * Carver ** reflect changes in event structure Author: Frederic Baguelin Date: Mon Aug 1 12:50:24 2011 +0000 * Filter API ** progress information sent by event ** refactoring of process method (split in two method: __process only for recursive filtering) ** parser updated for time filtering Author: Frederic Baguelin Date: Mon Aug 1 12:48:55 2011 +0000 * Events ** changes in event struct. Predefined types can be found in an external enum named etype ** event structure now handles event type based on an uint32_t Author: Frederic Baguelin Date: Mon Aug 1 12:47:56 2011 +0000 * Filter API ** TimeFilter implemented ** AstNode inherits EventHandler (event management not fully implemented currently) Author: Frederic Baguelin Date: Thu Jul 28 16:21:44 2011 +0000 * Search API: ** refactoring of method in charge to compile pattern (wildcard especially) ** __wfind refactored and manages more cases Author: Frederic Baguelin Date: Thu Jul 28 16:19:08 2011 +0000 * Filter changes ** refactoring of most of the code. The code is far more generic and far more redundant ! *** Main classes ares based on classical types encountered in the framework: Numeric, String, Boolean and Timestamps: ** Parser has been enhanced, only references are used, each SAVE_STRING are now deleted at parsing time. Author: Frederic Baguelin Date: Thu Jul 28 16:14:26 2011 +0000 * Find libtre package moved to main CMakeList.txt ** Declaring -DHAVE_TRE in api/search/CMakeLists.txt did very strange behaviour conducting to segfault / aborted and so on... For example, datatypes, compiled before search includes nodes.hpp which include vfile.hpp where search is used. At this moment, -DHAVE_TRE were not added to definitions, datatypes having a different version of class Search. The issue were when calling new Search, sizeof this one were not always the good one... Author: Frederic Baguelin Date: Wed Jul 27 11:14:23 2011 +0000 * Filter: adds file (or folder) filter and deleted (or not) filter Author: Frederic Baguelin Date: Tue Jul 26 19:27:09 2011 +0000 * Filter new keyword ** Timestamp are managed: *** either a timestamp number (UNIX) or a string formatted as follow YYYY-MM-DDThh:mm:ss *** managed operators: ==, !=, >, >=, <, <=, in, not in Author: Frederic Baguelin Date: Tue Jul 26 19:22:57 2011 +0000 * Adds vtime ctor with string ** Format must be YYYY-MM-DDThh:mm:ss (currently, no check are done, must be enhanced for release) * Adds vtime comparison operators == != > < >= <= Author: Frederic Baguelin Date: Mon Jul 25 16:14:35 2011 +0000 * MimeCmp::__createCtx(), adds wildcard (*) before and after provided pattern Author: Frederic Baguelin Date: Mon Jul 25 16:04:24 2011 +0000 * fixes non assignation of this->__ctx in NameCmp * std::string::compare() returns 0 --> add of == 0... Author: Frederic Baguelin Date: Mon Jul 25 15:36:03 2011 +0000 * add AstNode::compile method ** call after ast has been created. It removes huge initialization process during ctor Author: Frederic Baguelin Date: Mon Jul 25 14:54:11 2011 +0000 STILL EXPERIMENTAL * Filtering work in progress ** name and mime implemented * Search wfind new algo (recursive) Author: Frederic Baguelin Date: Wed Jul 20 19:00:51 2011 +0000 * refactoring of AstNodes ** parser is more strict but nodes are directly typed based on the provided keyword (name, size, mime, time, ...) ** far far faster than the Python PoC * Size filtering is fully implemented, other will be very soon Author: Frederic Baguelin Date: Wed Jun 29 19:58:06 2011 +0000 * First commit of new filters API: ** provides lexer and parser (rules + generated cpp and hpp) ** provides Filter class for API ** CMakeLists.txt and swig definition Author: sja Date: Mon Aug 1 15:07:03 2011 +0000 Move 'module browser' before the separator in the list Author: jmo Date: Mon Aug 1 15:12:39 2011 +0200 * Add a new graphical way to view / browse and apply modules Author: sja Date: Mon Aug 1 13:44:37 2011 +0000 Add batch option to DFF man page Author: sja Date: Thu Jul 28 16:22:39 2011 +0000 add batch module to CMakeLists Author: sja Date: Tue Jul 26 15:19:16 2011 +0000 Add preview widget in cmakelists for install Author: sja Date: Tue Jul 26 15:00:15 2011 +0000 Add an ugly checkbox to activate/desactivate preview mode Author: sja Date: Mon Jul 25 11:27:41 2011 +0000 iodevice : check if file is open before using it hexeditor : add closeEvent and preview mode Author: sja Date: Fri Jul 22 19:39:11 2011 +0000 Module hexedit add preview mode Author: sja Date: Fri Jul 22 14:27:04 2011 +0000 modules player: fix bug of phonon when opening multiple audio source, but could only have one video/audio stream preview : add translation and icon dff pro : add preview widget Author: sja Date: Thu Jul 21 16:52:29 2011 +0000 module cat : set cursor at top of the document, use c_display for console to avoid print in stdout when using gui Author: sja Date: Thu Jul 21 14:35:46 2011 +0000 add the preview widget ... Author: sja Date: Thu Jul 21 14:34:23 2011 +0000 viewerimage : Add 'preview' mode and change next/previous to parse node list on click Author: sja Date: Wed Jul 20 18:18:01 2011 +0000 start of the 'preview widget' need enhancement and dffierent 'viewer' modules too Author: sja Date: Wed Jul 20 14:59:30 2011 +0000 clean comment Author: sja Date: Tue Jul 19 17:45:38 2011 +0000 FIX ewf module, nicer to don't add void attributes Author: sja Date: Tue Jul 19 17:41:22 2011 +0000 ewf module FIX for void attributes Author: sja Date: Tue Jul 19 16:48:54 2011 +0000 Add header and remove some comment Author: sja Date: Tue Jul 19 12:00:02 2011 +0000 ewf module: remove unused variable Author: sja Date: Mon Jul 18 19:28:46 2011 +0000 replace ewf module python implementation by a c++ implementation Author: Frederic Baguelin Date: Mon Jul 18 18:02:45 2011 +0000 * mini patch for gui import issues Author: Frederic Baguelin Date: Mon Jul 18 17:21:04 2011 +0000 * Implementation of search methods: ** find implemented for fixed, wildcarded, regexp and fuzzy patterns (case sensitivity taken into account too) ** rfind for fixed and wildcard patterns (regexp and fuzzy not implemented) ** count for fixed and wildcard patterns (regexp and fuzzy not implemented) * New methods in vfile to implement previous search capabilities: ** same method naming as existing ones (find, rfind, count and indexes) with first argument being a configured search context Tests still need to be performed, especially concerning fuzzy matching. Concerning wildcarded search, we (user and developers) needs to debate how to handle a pattern in a stream Author: Frederic Baguelin Date: Thu Jun 30 18:36:21 2011 +0000 * Refactoring of search API ** dedicated class Search which wraps Regexp, Fuzzy, Wildcard and Fixed searches ** link with TRE library concerning regexp and fuzzy searches Author: sja Date: Wed Jul 13 17:37:15 2011 +0000 CMakelists for ewf cpp Author: sja Date: Wed Jul 13 17:35:25 2011 +0000 Start of EWF module in CPP Author: cma Date: Wed Jul 13 19:27:44 2011 +0200 Removes unused designs, updates strings to translate, updates french language Author: cma Date: Wed Jul 13 17:43:56 2011 +0200 Design lifting = beautiful search Author: rbe Date: Tue Jul 12 13:16:37 2011 +0200 gui-filters: * last minutes changes Author: sja Date: Mon Jul 11 16:34:12 2011 +0000 add apswtest in CMakelist for developers only, should not be installed Author: sja Date: Mon Jul 11 16:24:50 2011 +0000 CMake install for apswvfs Author: cma Date: Wed Jun 29 12:59:11 2011 +0200 Fix NTFS for valid files detected as deleted files, an integer overflow was present in attribute.cpp. Also prints boot block parsing messages when loading module. Author: rbe Date: Tue Jun 28 18:39:00 2011 +0200 gui-filters * minor changes Author: rbe Date: Tue Jun 28 16:42:03 2011 +0200 gui-filters: * an other little modif about dictionnaries Author: rbe Date: Tue Jun 28 16:03:53 2011 +0200 gui-filters * can now open dir in new tabs * fixe the timestamps syntax Author: rbe Date: Tue Jun 28 15:42:24 2011 +0200 gui-filters: * can now display attributes in search tab Author: rbe Date: Tue Jun 28 14:01:10 2011 +0200 gui-filters * some other minor changes to be syntax complient with the search engine Author: rbe Date: Tue Jun 28 11:40:55 2011 +0200 gui-filters: * modify a bit the syntax of the search clauses Author: rbe Date: Mon Jun 27 17:20:50 2011 +0200 gui-filters: * can now manually edit clauses and the query is derictly modified Author: rbe Date: Mon Jun 27 17:02:04 2011 +0200 gui-filters * modify the query generation Author: rbe Date: Fri Jun 24 17:07:52 2011 +0200 gui-filters: * add a widget which permit to select one or several mime types to search * the resulting string is not always well formatted Author: sja Date: Wed Jun 22 18:14:44 2011 +0000 FIX 'connections' parameter Author: sja Date: Wed Jun 22 16:40:42 2011 +0000 FIX mftentry validateSignature() check if structure is allocated before using it... Author: sja Date: Wed Jun 22 14:14:39 2011 +0000 FIX open node in new tab Author: rbe Date: Wed Jun 22 13:45:24 2011 +0200 search * modify the widget to load a dict * use a list widget to see its content (not editable) Author: sja Date: Tue Jun 21 18:02:01 2011 +0000 Add output from modules in results widget from taskmanger Author: rbe Date: Tue Jun 21 15:42:29 2011 +0200 search * modify the widget * can add / delete clause * can chose or / and operator between clauses Author: rbe Date: Mon Jun 20 12:24:05 2011 +0200 * adding new Ui file for search * modify the search widget * generate a query that can be manually modified * this is up to users not to input inconsistant values Author: sja Date: Thu Jun 16 18:41:57 2011 +0000 Clean apswvfs & apswtest, should work Author: sja Date: Thu Jun 16 16:58:47 2011 +0000 apsw vfs in api and test modules Author: sja Date: Thu Jun 16 17:40:17 2011 +0000 FIX batch command scheduling (exec command only when previous one have finished) Author: sja Date: Sun Jun 5 22:49:22 2011 +0000 Add config key "extension-type" to detect file by extension Author: sja Date: Sat May 28 04:12:40 2011 +0000 Add a batch to dff : dff --batch=path_tobatch_file or use the batch module : batch path_to_batchfile the batch file are text file examples : # comment that will be displayed at exec of the batch file # load a fat dump with local # open dump.fat (open auto-detect file type and launch the corresponding module) local /home/examinor/dump.fat open dump.fat Author: Frederic Baguelin Date: Wed May 25 17:48:10 2011 +0000 * Re-enables search after merging master back branch Author: sja Date: Mon May 23 20:50:17 2011 +0000 FIX spare module didn't get the argument value for spare and block size Author: cma Date: Fri May 20 16:58:55 2011 +0200 Fixes afflib found by cmake proper link Author: jmo Date: Fri May 20 16:45:35 2011 +0200 Add AFF support in evidence dialog Author: cma Date: Fri May 20 15:45:10 2011 +0200 Latest PyQt version on Windows changes path of required binaries. Author: cma Date: Fri May 20 15:33:32 2011 +0200 PyQt windows dependency 4.8.2 to 4.8.4 in CMakeLists.txt Author: cma Date: Fri May 20 15:12:46 2011 +0200 Another variable to keep Author: cma Date: Fri May 20 14:41:17 2011 +0200 NTFS ; revert bad free in attributes ; need to investigate. Version 1.1.0 (20 May 2011) =========================== Author: cma Date: Fri May 20 13:52:02 2011 +0200 Adds zh to i18n process. Try to fix mem leaks in NTFS. Author: jmo Date: Thu May 19 17:57:34 2011 +0200 Double commit : 1. DeviceDialog : Change from str() to QString.fromUtf8() for device informations 2. Bugfix NTFS issue : check if fullFileName is NULL permit to avoid segfault -> Check XXX && jmo in ntfs.cpp Author: sja Date: Thu May 19 13:43:29 2011 +0000 Translation : Chinese languages added thanks to Zhang Jun Author: jmo Date: Wed May 18 18:05:32 2011 +0200 Change splashscreen to Version 1.1 Author: cma Date: Wed May 18 17:49:20 2011 +0200 Re-enables app version sets from CMak\e Author: jmo Date: Wed May 18 17:11:03 2011 +0200 Resolve Segmentation Fault Issue on NTFS module : Parsing Attributes -> resident Flags -> return 0 instead of continue (_data issue) Author: Frederic Baguelin Date: Wed May 18 15:09:24 2011 +0000 * Better handling of Orphaned files ** if free cluster has already been walked earlier by walkDeleted, it won't be parsed * Better attributes management in created nodes ** dos attributes decoded, dos name provided Author: cma Date: Wed May 18 15:32:34 2011 +0200 Adds check for AFFlib, link with static version on linux at install. Author: cma Date: Wed May 18 14:57:16 2011 +0200 AFF works on Windows. Also modifies CMake rules for thirdparty dll copy. Author: sja Date: Wed May 18 14:27:11 2011 +0000 Change VTIME TIME_MS flag to TIME_MS_64 as it's already define by ms in some headers Author: sja Date: Wed May 18 14:05:24 2011 +0000 AFF: add cache size options and handle multiple input files Author: Frederic Baguelin Date: Wed May 18 12:33:48 2011 +0000 * removes Nodefilterbox dependencies Author: jmo Date: Wed May 18 13:21:25 2011 +0200 This commit fixes minor issue #126 by checking focus state of dockwidgets Author: cma Date: Wed May 18 12:14:52 2011 +0200 Modifies Visual Studio rule in many CMakeLists.txt, PREFIX .. no longuer needed. Author: Frederic Baguelin Date: Tue May 17 19:40:44 2011 +0000 * FAT module enhancements: ** added slack space as attributes for not deleted files ** for deleted files mapping does not rely on cluster chain: *** get the first cluster and mapped size * nodefilterbox and nodeviewbox patched Author: sja Date: Tue May 17 17:44:43 2011 +0000 FIX: use old find API for creating thumbnails Author: sja Date: Tue May 17 17:37:38 2011 +0000 PFF : Remove unused definition Author: cma Date: Tue May 17 17:57:20 2011 +0200 CMakeLists.txt update for PFF module to compile on Windows. Author: sja Date: Tue May 17 15:35:42 2011 +0000 VTIME: add unix 64 bits time stamp to constructor, select between unix and ms 64bits with a flag, default is unix (if not specified) AFF: update use only one open -> to be faster as multi open is really to slow on this lib, need to fix for multi file loading Author: rbe Date: Tue May 17 11:54:35 2011 +0200 TreeModel / viewModel / *model / *view * Fixes a couple of stuff : https://tracker.digital-forensic.org/issues/125 Author: cma Date: Tue May 17 09:44:16 2011 +0200 Dutch translation update about #121, thanks to Bram. Author: cma Date: Mon May 16 19:32:59 2011 +0200 Adds fine check for PFF library ; link with static version of the library in installation mode. Compile without check on Windows because PFF is added separately. Author: Frederic Baguelin Date: Mon May 16 19:13:15 2011 +0000 * vmware compiler warnings remove Author: Frederic Baguelin Date: Mon May 16 19:12:44 2011 +0000 * carver compiler warnings remove Author: Frederic Baguelin Date: Mon May 16 19:12:13 2011 +0000 * API compiler warnings remove Author: Frederic Baguelin Date: Mon May 16 18:06:17 2011 +0000 * removes some Warnings Author: Frederic Baguelin Date: Mon May 16 18:05:37 2011 +0000 * removes some compiltation Warnings Author: sja Date: Mon May 16 19:19:05 2011 +0200 FIX bug with WMI Devices with QT FileDialog who CoInitialize before it, ... must be test under Windows XP Author: sja Date: Mon May 16 17:08:33 2011 +0000 devices StringList is already define in vfs.i remove this definition Author: sja Date: Mon May 16 16:55:42 2011 +0000 EXTFS: avoid warning Author: sja Date: Mon May 16 16:48:27 2011 +0000 Correct some reported some warning Author: cma Date: Mon May 16 18:22:00 2011 +0200 This commit closes #122 ; typo in ui/conf.py. This commit also adds a check for PFF library installation in top level CMakeLists.txt, remember libbfio from PFF have to be installed separatly. Without separate libbfio installation, usage of libpff through DFF is not possible. Author: cma Date: Mon May 16 17:51:29 2011 +0200 Spanish translation update refs. #121 , thanks to Pablo. Author: cma Date: Mon May 16 17:25:51 2011 +0200 Translatable string in file nodeviewbox.py adds to dff.pro, related to #121. Updates french translation for it. Author: sja Date: Mon May 16 13:51:51 2011 +0000 vfile::vread Change error message Author: sja Date: Mon May 16 14:34:58 2011 +0200 WDEVICE avoid warning Author: sja Date: Mon May 16 13:21:50 2011 +0200 VFile::Read check if there is enough memory to allocate buffer Author: jmo Date: Mon May 16 13:02:06 2011 +0200 Enhencement : Add a new icon in order to detect when thumbnails are activated or not into the nodebrowser Author: sja Date: Mon May 16 12:49:12 2011 +0200 Initialize windows thread Author: sja Date: Mon May 16 11:28:30 2011 +0000 Add threading hpp to define for win thread and pthread Author: jmo Date: Mon May 16 12:24:11 2011 +0200 Relove Open as New tab bug : pass node.absolute() to getnode function Author: sja Date: Sun May 15 22:57:57 2011 +0000 PFF use Variant to store buffer Author: sja Date: Sun May 15 21:41:20 2011 +0000 Remove some call to the filemapping cache Author: sja Date: Sun May 15 20:46:29 2011 +0000 FIX mfso cache filemapping Author: sja Date: Sun May 15 18:09:45 2011 +0000 Add cache for mfso filemapping and lock for mfso opened vfiles Author: mcleodz Date: Sat May 14 16:30:25 2011 +0200 Resolve Issue Enhancement #121, now a dialog box pop up when try to bookmark with none selected nodes Author: sja Date: Thu May 12 23:03:32 2011 +0000 mfso::close() remove delete fdinfo as it's deleted by fdremove Author: sja Date: Thu May 12 20:33:29 2011 +0000 Remove comment and indent correctly Author: sja Date: Thu May 12 20:28:52 2011 +0200 DEVICES add icon for nodes MFSO fix big problem with underlaying opened files -> this must be tested Author: sja Date: Thu May 12 15:57:23 2011 +0200 FIX Loader print exception but didn't return Author: sja Date: Thu May 12 15:27:50 2011 +0000 Must use RELWITHDEBINFO in UPPER case in CMakeLists Author: sja Date: Thu May 12 15:15:09 2011 +0000 Add RelWithDebInfo in vs prefix for cmake Author: sja Date: Fri May 6 18:28:58 2011 +0200 Change CMakeList to build lib and modules in the right place when compiled with VS2010 Author: sja Date: Mon May 2 14:06:35 2011 +0000 getnode unicode fix Author: sja Date: Mon May 2 12:46:14 2011 +0000 LOCAL argument parent is no optional like it was before Author: sja Date: Mon May 2 12:45:47 2011 +0000 Fix unicode for console in getnode Author: sja Date: Thu Apr 28 18:04:40 2011 +0000 Change size of bookmark and search icon to 128x128 Author: sja Date: Thu Apr 28 17:59:13 2011 +0000 Modifit attach.png from size 64x64 to 128x128 Author: sja Date: Thu Apr 28 17:38:04 2011 +0000 Fix memory leak in lib EXIF.py Author: sja Date: Thu Apr 28 12:30:46 2011 +0000 Remove AFF module from CMakeLists as a check if present but be done before compiling it Author: sja Date: Thu Apr 28 12:29:08 2011 +0000 Remove unused __init__.py from the CMakeLits Author: sja Date: Tue Apr 26 17:47:53 2011 +0000 AFF fix register_tree when list of files is given as argument Author: sja Date: Tue Apr 26 16:52:54 2011 +0000 AFF Remove some code comment Author: sja Date: Tue Apr 26 16:40:14 2011 +0000 AFF: add basical lock mechanism to avoid crash when used by multiple thread Author: sja Date: Tue Apr 26 14:18:07 2011 +0000 Remove PFF from CMakeLists must be build only if libpff with libbfio support is present Author: sja Date: Tue Apr 26 13:22:41 2011 +0000 Viewerimage Change the qlabel that display the name of the picture by a qlineedit to avoid problem with too long absolute path that made wiget to automatically resize Author: sja Date: Tue Apr 26 11:35:01 2011 +0000 Vieweriamge Add unicode support in file names display in widget Author: sja Date: Tue Apr 26 11:32:29 2011 +0000 Add unicode support in module widget name Author: sja Date: Fri Apr 22 17:10:36 2011 +0000 PFF: Add wrapper for DFF IO subsytem to be use with libpff, in order to made libpff module stackable To use this module you must install libbfio before installing libpff (libpff with libbfio external support) Author: sja Date: Thu Apr 21 14:24:09 2011 +0000 PFF: add options .i (to NOT create default items, recoverable, unallocated, orphans) Author: sja Date: Thu Apr 21 13:06:22 2011 +0000 ressource: add the needed icon for PFF Author: sja Date: Thu Apr 21 13:05:44 2011 +0000 PFF: Add more detailed results and some beautifull icons ! Author: sja Date: Wed Apr 20 17:40:25 2011 +0000 VTIME : new contrustor uint64_t convert directly for MS 64bits timestamp format TYPECONV : add some macro to convert endianess PFF : didn't add transport headers if size is 0 Author: sja Date: Wed Apr 20 16:24:35 2011 +0000 PFF: Attribute recipients now handle multiples recipients Add Attribute conversation index Attribute message header now handle multiple flags Author: Frederic Baguelin Date: Wed Apr 20 13:03:25 2011 +0000 * fixes bugs in datatype (datatype + magichandler) * adds thread safe operations for datatype call (libvfs.i) Author: sja Date: Tue Apr 19 16:34:29 2011 +0000 Add UTF8 display support for key in variant map Author: sja Date: Tue Apr 19 15:47:43 2011 +0000 PFF: add recovered items (fully deleted) as nodes add orphan items as nodes handle error differenly (set it in result) change stateinfo according to current parsing state Author: sja Date: Mon Apr 18 18:16:38 2011 +0000 PFF node_task add percentage complete as attributes Author: sja Date: Mon Apr 18 17:33:40 2011 +0000 PFF: add all type not fully handled by libpff (without attributes) as PffNodeEmailMessageText node Author: sja Date: Mon Apr 18 16:58:51 2011 +0000 PFF add item type note as node Author: sja Date: Mon Apr 18 16:38:22 2011 +0000 Add item type meeting as node Author: sja Date: Mon Apr 18 16:03:38 2011 +0000 Contact & task now inherit from PffNodeEmailMessageText to avoid redondant code Author: sja Date: Mon Apr 18 15:24:45 2011 +0000 Remove unnecessary comment Author: sja Date: Mon Apr 18 13:38:42 2011 +0000 FIX appointmnent & attachment for appointment/attachment/appointment & attachment/attachment using identifier whem possible Author: cma Date: Mon Apr 18 12:56:22 2011 +0200 NTFS fix for file contents ending with chunks of 0 Author: sja Date: Fri Apr 15 12:11:28 2011 +0000 Modifiy getnode to be functional with unicode Author: sja Date: Fri Apr 15 11:40:49 2011 +0000 PFF now use iterator identifier to use less memory when it's possible Need to fix attachment / attachment / appointment Need to fix attachment / attachment / files Author: Frederic Baguelin Date: Thu Apr 14 17:26:31 2011 +0000 * api.vfs.vfs.py ** added depth argument to manage maximum recursion ** can take as arguments either a node or a string Author: rbe Date: Thu Apr 14 17:04:29 2011 +0200 indexation * update the CMakeList and add missing files Author: rbe Date: Thu Apr 14 15:51:19 2011 +0200 indexation * modify index and search * the indexer is not a module anymore * can configure the index a bit * add a form to perform "advanced" searches (wip) * can add / remove content in the index Author: sja Date: Wed Apr 13 23:20:49 2011 +0000 PFF use macro when possible for attribute, delete some comment Author: sja Date: Wed Apr 13 19:18:23 2011 +0000 Add task node (not finished yet lacks 2 attributes) Start to use macro to made the code more redable and lot shorter Author: sja Date: Wed Apr 13 16:02:56 2011 +0000 Change datatype->type to return string rather that string* Author: sja Date: Wed Apr 13 15:23:39 2011 +0000 PFF add item type contact Author: cma Date: Wed Apr 13 13:24:21 2011 +0200 NTFS code cleaning, fix warning on 64b Author: cma Date: Wed Apr 13 13:17:57 2011 +0200 NTFS fix for small content. When content of a file is stored directly in a MFT, fixup (bad block in metadata detection feature) was replaced with an absolute offset instead of physical offset from NTFS image. Author: sja Date: Tue Apr 12 19:02:16 2011 +0000 PFF : Appoinment is now ok PFF : Appointment who as appointment as attachment work ok Author: sja Date: Tue Apr 12 18:58:04 2011 +0000 add thread block for compatibleModules who call dataType Author: sja Date: Tue Apr 12 18:57:05 2011 +0000 Improve unicode support Author: sja Date: Tue Apr 12 17:16:51 2011 +0000 check if str pointer is null and that all path return string in magichandler.py Author: sja Date: Tue Apr 12 17:15:26 2011 +0000 block node->dataType in libvfs.i map insertion is not thread safe and could be the cause of the segfault Author: cma Date: Mon Apr 11 18:44:10 2011 +0200 NTFS beginning of fix for heavy fragmented files, need validation to avoid regression. Author: sja Date: Mon Apr 4 12:27:24 2011 +0000 PFF: Add unallocated data to a node Author: Frederic Baguelin Date: Fri Apr 1 20:03:56 2011 +0000 * enables access from Python to pattern struct in libsearch.i and swig interface to handle unsigned char * type * add method walk in vfs.py. It provides the same behaviour as walk in os module of Python ** for dirpath, dirs, files in v.walk("/", [topdown=True|False]): do something Author: sja Date: Fri Apr 1 16:59:05 2011 +0000 PFF : add unallocated page as mfso node add icon attach for node attachment modifiy mfso to have fdmanager accessible from inherited class (public) must set an accessor later Author: sja Date: Thu Mar 31 17:57:07 2011 +0000 Remove some old comment in viewerimage Author: sja Date: Thu Mar 31 17:52:49 2011 +0000 Add some forgotten type compatible with viewerimage Author: sja Date: Thu Mar 31 16:49:34 2011 +0000 little fix in aff module Author: sja Date: Thu Mar 31 15:48:22 2011 +0000 CMakeLists Remove swig optimization (swig -O) Libexceptions remove unlock of thread because is set twice without swig -O Libtypes.i add lock to variant Author: sja Date: Mon Mar 28 00:22:55 2011 +0000 use delete for pdata* for python read Author: sja Date: Sun Mar 27 04:50:10 2011 +0000 vmware remove unused variable Author: sja Date: Sun Mar 27 04:44:24 2011 +0000 remove unused variable Author: sja Date: Sun Mar 27 04:43:48 2011 +0000 remove unused variable Author: sja Date: Sun Mar 27 04:40:43 2011 +0000 remove unused variable Author: sja Date: Sun Mar 27 04:39:30 2011 +0000 carver.cpp remove unused variable Author: sja Date: Sun Mar 27 04:32:45 2011 +0000 shm module : remove unused variable Author: sja Date: Sun Mar 27 04:27:06 2011 +0000 Now compile with Wall flag in debug mode Remove unitialized variable in ulocalnode Author: sja Date: Sun Mar 27 04:03:43 2011 +0000 Add result to AFF Module Author: sja Date: Sun Mar 27 02:23:59 2011 +0000 AFF Module is now fully working Add void pointer type to Variant class Author: sja Date: Sun Mar 27 01:05:17 2011 +0000 New module AFF AffNode Attributes as all info except for encryted blocks Author: sja Date: Fri Mar 25 16:19:36 2011 +0000 FIXES #113 EWF Now the id is set as Variant solve the negative handle problem fix libvfs.i fixes the returned size in vread for python (it returned the readed size rather than the to read size) reset time value in singleton module (could made strange time execution value in taskmanager) Author: cma Date: Fri Mar 25 16:31:49 2011 +0100 Works on MacOS X.5 32bits, python-magic and libmagic has to be installed separatly. Author: cma Date: Fri Mar 25 16:30:50 2011 +0100 Backward compatibility for Python < 2.6 Author: cma Date: Fri Mar 25 16:02:43 2011 +0100 Dutch translation update thanks to Bram Mooij. Author: Pablo J. Rogina Date: Thu Mar 24 19:17:42 2011 -0300 Fixed bug #112 - Labels not disabled in Preferences dialog When "No footprint" is checked some labels weren't disabled. Fixed by reviewing several setEnabled() methods to follow the proper logic. Signed-off-by: cma Author: cma Date: Thu Mar 24 15:57:03 2011 +0100 Fixes NTFS crash or infinite loop when searching for parent of deleted or orphan items. Author: sja Date: Sun Mar 20 21:56:01 2011 +0000 Fix somes strings in italian translation Author: cma Date: Thu Mar 17 17:56:09 2011 +0100 Adds license copyright and header in italian translation file. Author: Frederic Baguelin Date: Thu Mar 17 17:40:55 2011 +0000 * bugfix with output name variable. Author: cma Date: Thu Mar 17 17:27:41 2011 +0100 EWF was not working on Windows. Fixes one missing letter n for Dennis. Author: sja Date: Thu Mar 17 18:09:49 2011 +0000 Add authors of italian translation Author: sja Date: Thu Mar 17 17:41:21 2011 +0000 Add some missing string in italian translation Author: sja Date: Thu Mar 17 17:34:31 2011 +0000 Add italian translation to cmakelist and dff.pro Author: sja Date: Thu Mar 17 17:33:17 2011 +0000 New Italian translation by Francesco Acchiappati Author: mcleodz Date: Thu Mar 17 17:03:41 2011 +0100 Layout manager : Change fieldValidator to acces any characters for not INT types Author: cma Date: Thu Mar 17 16:12:00 2011 +0100 Removes useless string in loader when loading module without dependency. Removes LD_PRELOAD from linux launcher for installation, now also useless. Author: mcleodz Date: Thu Mar 17 16:07:06 2011 +0100 layoutmanager:Line 541 : Remove retranslateUi in layoutmanager Author: Frederic Baguelin Date: Thu Mar 17 14:36:14 2011 +0000 * update Author: cma Date: Thu Mar 17 13:59:11 2011 +0100 Adds missing spaces in translation files Author: sja Date: Thu Mar 17 12:37:50 2011 +0000 Fix ewf error message line 91 Author: cma Date: Thu Mar 17 13:01:52 2011 +0100 Translation updates. Adds GPL header and copyright to each author. Thanks to Denis for Dff_de.ts, Bram for Dff_nl.ts and Pablo for Dff_es.ts ! Author: sja Date: Thu Mar 17 13:18:13 2011 +0000 Updated Spanish translation by Pablo J. Rogina Author: cma Date: Wed Mar 16 19:38:15 2011 +0100 Try to fix english. Author: cma Date: Wed Mar 16 18:37:51 2011 +0100 Hexedit = hex viewer ... Translation update for fr Author: rbe Date: Wed Mar 16 18:21:11 2011 +0100 RELEASESNOTES' file: * correction of a few typos. Author: sja Date: Wed Mar 16 19:00:15 2011 +0000 RELASENOTES reformat some text Author: sja Date: Wed Mar 16 18:56:32 2011 +0000 RELEASENOTES wrap underline text Author: sja Date: Wed Mar 16 18:55:21 2011 +0000 set RELASENOTES to 80 col Author: cma Date: Wed Mar 16 18:08:45 2011 +0100 Modifies top level CMakeLists.txt to add manpage, readme and licenses on install Author: cma Date: Wed Mar 16 17:14:53 2011 +0100 Adds AUTHORS file Author: cma Date: Wed Mar 16 17:06:12 2011 +0100 Modules version OK, modifies remaining ones. Author: sja Date: Wed Mar 16 16:52:20 2011 +0000 Remove ressources directory from top CMakeLists Author: Frederic Baguelin Date: Wed Mar 16 16:17:08 2011 +0000 * carver.py has been added in versionning but is generated at compile time. Author: Frederic Baguelin Date: Wed Mar 16 15:34:19 2011 +0000 * remove of long key name in attributes Author: Frederic Baguelin Date: Wed Mar 16 15:33:15 2011 +0000 * Completer were removed in layoutmanager NavBar * every signals are binded to completerWidget Author: cma Date: Wed Mar 16 16:19:32 2011 +0100 Adds version to each module, need test, some modules remains to be converted. Author: cma Date: Wed Mar 16 15:54:30 2011 +0100 Dutch translation update, thanks to Bram Mooij. Author: sja Date: Wed Mar 16 16:23:30 2011 +0000 Add changeslog for v1.0 and releasesnotes Author: cma Date: Wed Mar 16 15:44:55 2011 +0100 Licenses and Copyright updates. Author: Frederic Baguelin Date: Wed Mar 16 13:50:24 2011 +0000 * check if Index section exist. When changing from ENABLE_INDEXER OFF to ON, and having already started DFF, there is no index section in config.cfg which avoids DFF to be started Author: Frederic Baguelin Date: Wed Mar 16 13:39:25 2011 +0000 * indexing fully optional either in GUI or CMakeLists.txt Author: Frederic Baguelin Date: Wed Mar 16 13:03:05 2011 +0000 * remove of Indexation in GUI preferences Author: Frederic Baguelin Date: Wed Mar 16 12:43:06 2011 +0000 * hides search button in nodeviewbox Version 1.0.0 (16 March 2011) ============================= Author: sja Date: Tue Mar 15 18:53:56 2011 +0000 Add ExtFs block attributes as an options ( this attribute will not be created by default ) Author: Frederic Baguelin Date: Tue Mar 15 17:56:36 2011 +0000 * man module added * variant, typeid mapping for bool was not done... so value method always retuned default bool ctor setted to False * extract module patched * carver: remove debug * taskamanager bug fix Author: mcleodz Date: Tue Mar 15 17:04:50 2011 +0100 (re)Change splash screen with "new" logo Author: sja Date: Tue Mar 15 16:32:10 2011 +0000 Add a generic flag for post_processing module without type compatibility (like hash) Author: sja Date: Tue Mar 15 16:05:40 2011 +0000 FIX hash when no algo is choosed default to md5 Author: rbe Date: Tue Mar 15 16:53:48 2011 +0100 ide * refresh tool bar Author: sja Date: Tue Mar 15 15:47:18 2011 +0000 FIX column filter when module as not attributes Author: Frederic Baguelin Date: Tue Mar 15 14:59:49 2011 +0000 * propertytable (varianttreewidget), nodeview (treewidget), taskmanager(varianttreewidget) ** adapting column width to contents (enables scrollbar) * carver ** better GUI rendering and checkboxes mangement ** aligned switch was not correctly handled Author: rbe Date: Tue Mar 15 15:07:18 2011 +0100 ide * add "CTRL + S" (save script) in branch pre-1.0 Author: rbe Date: Tue Mar 15 13:38:15 2011 +0100 extfs * some stuff who are supposed to fix an extfs crash, but I could not reproduce the bug so I could not test. Good luck. Author: Frederic Baguelin Date: Tue Mar 15 12:32:15 2011 +0000 * setting Variant for res["error"] and thisown = False Author: sja Date: Tue Mar 15 12:53:38 2011 +0000 Add refresh of menu for languages selection Author: sja Date: Tue Mar 15 12:52:41 2011 +0000 FIX for VMAP with key and value set to None (0) normally must be set to Variant() but avoid problem Author: Frederic Baguelin Date: Tue Mar 15 12:06:21 2011 +0000 * vfsitemmodel TreeModel ** abort when providing an empty list to appendRows * processus ** remove of junk code Author: Frederic Baguelin Date: Mon Mar 14 18:59:04 2011 +0000 * carver almost done Author: sja Date: Mon Mar 14 18:53:53 2011 +0000 Add some translation path Author: sja Date: Mon Mar 14 18:53:28 2011 +0000 Add some french translation Author: sja Date: Mon Mar 14 18:37:04 2011 +0000 FIX now send an event to register is node Author: sja Date: Mon Mar 14 18:30:02 2011 +0000 FIX change module order autodetection Author: sja Date: Mon Mar 14 18:21:37 2011 +0000 EWF now take list of path rather than searching by itself all needed file Dialog connector now add ewf in path 'Logical Files' Author: cma Date: Mon Mar 14 18:41:01 2011 +0100 Removes old removed files from CMakeLists or fixes typo for install. Modifies man page with new arguments. Fixes in ui/history.py for console only run without history file. Re-enable conffile in ui/ui.py, please remove *.pyc files and/or useless old directories before making noise. Author: sja Date: Mon Mar 14 17:39:27 2011 +0000 node pass id of fd as no long , maybe better need to be tested on windows Author: sja Date: Mon Mar 14 17:19:38 2011 +0000 timeline now send event to refresh tree once Node are created Author: sja Date: Mon Mar 14 17:01:20 2011 +0000 Remove debug in print SMSdecode conf was ported but not arg Author: sja Date: Mon Mar 14 15:46:42 2011 +0000 FIX sort problem when node as no magic/ magic mime attributes FIX sort problem node was sort on dynamicAttributes when ask for fsoAttributes, so object never exist ... FIX sort on Variant time is not implemented (?), so convert as python time object before sorting Author: cma Date: Mon Mar 14 16:25:17 2011 +0100 Forces iconVisibleInMenu in several files, fixes icon display in menu for Ubuntu and Fedora for example. Author: mcleodz Date: Mon Mar 14 16:13:30 2011 +0100 Clear linedit when reopen a node or path Author: cma Date: Mon Mar 14 15:13:27 2011 +0100 Minor fix for preferences about history file. Author: mcleodz Date: Mon Mar 14 15:09:53 2011 +0100 Check if Argument.Empty isChecked and not only Activated Author: cma Date: Mon Mar 14 14:52:26 2011 +0100 Removes QScintilla checks/dependency, no longer needed. Author: mcleodz Date: Mon Mar 14 14:51:21 2011 +0100 Activate Argument.Empty parameters in applymodule Author: sja Date: Mon Mar 14 13:23:16 2011 +0000 FIX bug in pixel view when buff size < Pixmap size making Qt segfault at pixmap creation Author: sja Date: Mon Mar 14 13:06:44 2011 +0000 Disable menurelevant when no choice is possible Author: sja Date: Mon Mar 14 12:40:27 2011 +0000 Pass selected node to the module when use the menu 'Relevant modules' Author: mcleodz Date: Mon Mar 14 10:21:49 2011 +0100 BugFix layoutmanager for selectedNodes Author: fba Date: Sun Mar 13 22:25:57 2011 +0100 minor changes for VfsDialog Author: fba Date: Sun Mar 13 22:08:24 2011 +0100 * Conf in ui does not work Author: fba Date: Sun Mar 13 22:06:48 2011 +0100 * minor fixes in console completion * GUI completer almost done ** need to changed path in views when enter pressed ** need to better handle when no / at the beginning Author: sja Date: Sun Mar 13 04:50:52 2011 +0000 add relevant module menu need to auto exec ? Author: sja Date: Sun Mar 13 00:16:33 2011 +0000 delete a print for test Author: fba Date: Sun Mar 13 01:14:39 2011 +0100 * console ** better display message when errors encountered Author: sja Date: Sat Mar 12 23:53:00 2011 +0000 fix the launch of hexedit by default Author: sja Date: Sat Mar 12 23:29:06 2011 +0000 Add question box when double-click on node : Ask yes/ always/ no before applying a module , to let the user choose what he want if always click the question is not ask anymore -> need translation -> need to be add in global conf ? Also now take a Viewers by default if available Author: sja Date: Sat Mar 12 19:04:34 2011 +0000 defaut icon as none in module and script Author: sja Date: Sat Mar 12 19:03:34 2011 +0000 Add module icon in place of default module icon if present Author: sja Date: Sat Mar 12 18:54:36 2011 +0000 Add description strings Author: sja Date: Sat Mar 12 18:37:53 2011 +0000 add possiblity to set icon for a modules add icons for some modules Author: cma Date: Fri Mar 11 19:53:58 2011 +0100 Configuration update. Checkboxes/states and path have default values or are fetched from a .ini file. Help/documentation filepath managed from preferences. No footprint mode (default) works well. Add a --config to provide a configuration file instead of defaut one. Author: Frederic Baguelin Date: Fri Mar 11 18:56:21 2011 +0000 * VFSDialog navigation bar added * Completer WIP Author: sja Date: Fri Mar 11 18:39:43 2011 +0000 Modify __repr__ so str(variant) doesn't return the __repr__ as hex string also must be in __str__ not in __repr__ Author: mcleodz Date: Fri Mar 11 16:21:57 2011 +0100 BugFix when nodeselected was none Author: mcleodz Date: Fri Mar 11 15:35:55 2011 +0100 Insert node selected in applymodule dialog Author: Frederic Baguelin Date: Fri Mar 11 11:52:16 2011 +0000 * better display in VariantTreeWidget * When Opening Processus Information (double click on processus in taskmanager), provided arguments are shown Author: cma Date: Thu Mar 10 22:03:34 2011 +0100 Preferences dialog lifting. Removes configuration directory from ui/gui Puts conf.py directly in ui/ Puts translator.py in ui/gui/ Configuration has to be modified by something like a .ini, if exists and if footprint enabled. Author: sja Date: Thu Mar 10 21:22:55 2011 +0000 Remove a old res.add_const ... Author: Frederic Baguelin Date: Thu Mar 10 20:43:29 2011 +0000 * carver in console mode implemented * carver results enhancement WIP * better display when calling print on Variant of type string or carray: ** if string is not alpha num, print in hex format Author: sja Date: Thu Mar 10 20:33:42 2011 +0000 Add a space in the stateinfo Author: sja Date: Thu Mar 10 20:17:38 2011 +0000 Remove insert of a 0 value by default in layoutmanager argument list widget with predefine Author: sja Date: Thu Mar 10 18:26:36 2011 +0000 fixes #91 this fix exec time problem Author: sja Date: Thu Mar 10 16:31:45 2011 +0000 remove some unnecessary comment Author: sja Date: Thu Mar 10 16:24:15 2011 +0000 remove unneccessary file Author: sja Date: Thu Mar 10 16:17:15 2011 +0000 get rid of some unecessary commentary in modules and ui Author: rbe Date: Thu Mar 10 17:06:36 2011 +0100 extfs * clean the code Author: cma Date: Thu Mar 10 16:56:08 2011 +0100 There was several files with 2010 instead of 2011, in license header. Also modify many files where url in licence starts with http: *// instead of http://. Program version was not dinamically set at cmake step, ui/ui.py and ui/gui/gui.py ; fixed. Also inc 0.9.0 to 1.0.0 in top level CMakeLists.txt Author: sja Date: Thu Mar 10 15:54:29 2011 +0000 Get rid of unecessary commentary in hpp & cpp file Author: Frederic Baguelin Date: Thu Mar 10 15:41:47 2011 +0000 Conflicts: api/gui/widget/nodebrowser.py Author: sja Date: Thu Mar 10 15:33:13 2011 +0000 Get rid of unnecessary comment in api/ python files Author: Frederic Baguelin Date: Thu Mar 10 15:32:37 2011 +0000 * bug fixes in module fg * fixes in console ** manages thread correctly both in console and gui console ** better error handling: more user friendly Author: sja Date: Thu Mar 10 15:23:01 2011 +0000 Remove unnecessary comment Author: rbe Date: Thu Mar 10 16:01:33 2011 +0100 IDE * Modify module skeletons so they can be loaded by the new API. Author: rbe Date: Thu Mar 10 15:54:26 2011 +0100 model (minor commit) * add a translation in TreeModel Author: cma Date: Thu Mar 10 15:48:40 2011 +0100 Updates translation files, using already (obsolete) translated strings, but some untranslated strings remains in dutch, german and spanish files. Removes useless translated strings in every .ts files. Modify design of preferences, for index tab to look better, also make title of nodeviewbox untranslatable, this title is not viewable. Author: sja Date: Thu Mar 10 13:57:13 2011 +0000 FIX block of shell in GUI, A line was put in else (bad indentation ?) Author: sja Date: Thu Mar 10 13:35:07 2011 +0000 Uncomment print for gui module in console Author: Frederic Baguelin Date: Thu Mar 10 13:10:46 2011 +0000 * changes debug verbosity in console * better completion on predefined parameters Author: rbe Date: Thu Mar 10 13:30:06 2011 +0100 Misc * remove QSortFilterProxyModel * remove debug displays in extfs Module Author: sja Date: Thu Mar 10 11:44:47 2011 +0000 Remove init of qwidget in __init__ to block launch of gui script in console Author: fba Date: Thu Mar 10 02:24:53 2011 +0100 * better completion management Author: sja Date: Wed Mar 9 20:37:27 2011 +0000 FIX modules argument for new api Author: Frederic Baguelin Date: Wed Mar 9 19:20:36 2011 +0000 * new python magic had changed naming convention ** try / except added in magichandler to reflect it * nodefilterbox.py ** try / except on ImportError when indexer module not compiled Author: Frederic Baguelin Date: Wed Mar 9 18:21:21 2011 +0000 * remove of comment in eventhandler.cpp * libexception ** remove of Python thread block with notify method * argument ** argument can now store subarguments * variant ** manages argument typeid ** bugfixes in variant.cpp *** strings are now stored in __data in std::string* str indead of ptr *** for CArray type, provided array is now converted to string and stored in __data.str *** changes in to* methods reflect these changes ** enhancement *** toHexString method now handles std::string and char* type. Resulting hexstring has the format of a classical hexdump ** bugfixes in libtypes --> Variant(PyObject*, uint8_t) method *** for typeId::int16_t in PyInt_Check || PyLong_Check, bad value was passed to Variant() *** for typeId::CArray in PyString_Check, string::c_str() return a const char*, add a (char*) cast. Otherwise, a boolean Variant was created *** for typeId::Char in PyString_Check, let the possibility to provide and empty char * carver ** refactored and split in several modules: ** carver *** c++ carver based on new possibility of subargument ** GUI *** Tow possibilities: use predefined patterns and user defined patterns *** GUI carver is a wrapper for the c++ carver which generate the arguments ** UI *** carver for console is under development Author: rbe Date: Wed Mar 9 17:12:09 2011 +0100 indexation * use _CLNEW and _CLDELETE instead of new and delete with clucene objects * change the default index path Author: cma Date: Wed Mar 9 15:29:37 2011 +0100 Fixes for content of NTFS ADS files, parent node was not set. Author: rbe Date: Wed Mar 9 14:43:53 2011 +0100 model * an other fix Author: rbe Date: Wed Mar 9 14:29:19 2011 +0100 model * bug fix in vfsitemmodel Author: sja Date: Tue Mar 8 15:55:47 2011 +0000 Delete all none use CLucene headers .... Author: sja Date: Tue Mar 8 15:47:48 2011 +0000 Add pipe_exec tagged builtins in process Made change in CMakelists Add error as Variant in processus Author: rbe Date: Tue Mar 8 16:36:02 2011 +0100 indexation * remove useless search fields * modify a bit display of search results (minot chnages) Author: sja Date: Tue Mar 8 15:30:18 2011 +0000 add eval exp and CMakeList is now uptodate Author: sja Date: Tue Mar 8 15:27:28 2011 +0000 Port evalexp to new API didn't use old argument hex because now numeric value are always displayed as decimal and hexadecimal Author: sja Date: Tue Mar 8 15:15:07 2011 +0000 Remove this modules as it must be ported with a correct api Author: sja Date: Tue Mar 8 14:02:29 2011 +0000 fix to run not to work well .. Author: sja Date: Tue Mar 8 13:45:55 2011 +0000 Add a minimalistic libindex.i to avoid wrapping all libCLucene Author: cma Date: Tue Mar 8 12:48:09 2011 +0100 Adds check for CLucene. We also check for clucene-config.h in /usr/lib, what is ugly but it is the way CLucene stores its config ...! Author: rbe Date: Tue Mar 8 11:42:32 2011 +0100 configuration index * create index director(y)(ies) only when users click on the 'OK' button of the preference * BUG : the user cannot change the index directory when launching the indexer module Author: rbe Date: Mon Mar 7 18:37:19 2011 +0100 index + configuration * can now chose the index directories usinf Edit -> preferences * modify indexer and search so they use the configuration to create / locate the index file * add icons Author: rbe Date: Mon Mar 7 18:09:20 2011 +0100 to merge Author: rbe Date: Mon Mar 7 11:59:53 2011 +0100 model * an otehr fix Author: fba Date: Sun Mar 6 18:51:29 2011 +0100 * carver porting WIP. Need tracking segfault in boyermoore search Author: fba Date: Sun Mar 6 17:49:22 2011 +0100 * fixes compile error on 64 bits platform for libtypes.i ** do not forget to add ${CMAKE_SWIG_FLAGS} when adding new definitions ! Author: Frederic Baguelin Date: Fri Mar 4 19:40:45 2011 +0000 * fileinfo ported to new API * enhancement for console printer ** manages termsize ** manages max depth for Variant Tree ** manages max items to print for VList * variant ** implements toString for boolean type * libtypes.i ** implements value() for boolean type * shell gui ** hook for VariantTreePrinter.__[nt|posix].terminalSize to ShellView.get_term_size * ui class ** ability to provide wait to ui.cmd(line, wait=False) Author: sja Date: Fri Mar 4 18:48:09 2011 +0000 add icon for mailbox Author: sja Date: Fri Mar 4 15:37:07 2011 +0000 FIX property table to display compat modules not only for node as file in filesystem but also for every node with content FIX vmware modules return NULL in virtual methode that must not be overwritted Author: sja Date: Fri Mar 4 15:08:11 2011 +0000 FIX local bug with post_process on one file because of registering before adding to internal file list -> put original file directly in the Node PORT taskmanager to new attributes api CHANGE argument of winreg to be post_processable Author: cma Date: Fri Mar 4 14:58:36 2011 +0100 Fixes timeline failing to found valid time, especially with extfs. Author: sja Date: Fri Mar 4 13:42:58 2011 +0000 Port post_process to new argument system Author: sja Date: Fri Mar 4 13:22:06 2011 +0000 Correct if vmap == NoneType in case of no _attributes in a modules Author: sja Date: Fri Mar 4 13:12:04 2011 +0000 restore magic handler Author: cma Date: Fri Mar 4 14:08:33 2011 +0100 Reverts configured file commited with local variables Author: rbe Date: Fri Mar 4 13:31:17 2011 +0100 search / indexation : * modify the search widget * add the indexer module (unfinished) * search results added in 'Searched items' node, at the VFS root * exception on regexp filtering Author: sja Date: Fri Mar 4 12:04:12 2011 +0100 FIX conflict datatype Author: sja Date: Fri Mar 4 12:02:07 2011 +0100 FIX all singleton Author: sja Date: Thu Mar 3 20:18:05 2011 +0000 FIX include in #define win Author: Frederic Baguelin Date: Thu Mar 3 19:21:17 2011 +0000 * new feature: VmWare modules is now available ! * fixes minor issue in utils and action to pop up module configuration dialog when there are more than one argument Author: sja Date: Thu Mar 3 19:21:02 2011 +0100 Singleton in Shared memory for windows ... must test on linux Author: Frederic Baguelin Date: Thu Mar 3 17:27:11 2011 +0000 * Volatility 1.3 is now arguments / conf compliant * enhancements in applymodule * DialogNodeBrowser implemented when asking user for node selections * reflects changes in layoutmanager and VfsDialog ** set good selectionMode when only one node or several needed Author: sja Date: Thu Mar 3 16:45:14 2011 +0100 FIX NTFS SetDateToString for Windows Author: sja Date: Thu Mar 3 16:42:46 2011 +0100 FIX NTFS MAC TIME on Windows Author: sja Date: Thu Mar 3 17:19:12 2011 +0000 Time.h is no in vtime -> because Time.h is a standard unix headers ... Author: sja Date: Thu Mar 3 16:50:38 2011 +0000 unix devices Author: cma Date: Thu Mar 3 16:14:32 2011 +0100 Windows registry module initial commit. Code by Jeremy Mounier. Author: rbe Date: Thu Mar 3 15:55:24 2011 +0100 gui / model: * display '+' button ONLY when nodes have children in the qtreeview Author: sja Date: Thu Mar 3 13:33:17 2011 +0000 update devices dialod for linux Author: sja Date: Thu Mar 3 13:32:47 2011 +0000 move old windevies to devies remove tmp.py in extfs Author: sja Date: Thu Mar 3 13:31:47 2011 +0000 Port linux devices to new argument API Author: rbe Date: Thu Mar 3 13:00:46 2011 +0100 gui / model * minor fixes Author: Frederic Baguelin Date: Thu Mar 3 10:44:56 2011 +0000 * adds option to gen_node module for providing number of node to create Author: sja Date: Wed Mar 2 19:27:04 2011 +0000 remove comment Author: sja Date: Wed Mar 2 18:33:28 2011 +0100 dialog devices window up to date Author: sja Date: Wed Mar 2 19:08:38 2011 +0000 Fix node name insertion Author: Frederic Baguelin Date: Wed Mar 2 18:30:53 2011 +0000 * port of show_db Author: sja Date: Wed Mar 2 17:49:58 2011 +0100 Windevices and devices widget is now ported to new argument api Author: rbe Date: Wed Mar 2 13:30:46 2011 +0100 tree model / tree view * replaced the model by QStandardItemModel to improve performances Author: sja Date: Wed Mar 2 11:37:47 2011 +0100 Change windevices module tag to Connectors Author: Frederic Baguelin Date: Tue Mar 1 19:11:56 2011 +0000 * libexceptions --> added handler for const char * * variant --> added Variant.toString() for Path type * utils --> VariantTreePrinter class allows to print Variant, VMap and VList easily * builtins porting WIP Author: sja Date: Tue Mar 1 19:08:42 2011 +0100 Windevices ported to new argument API, GUI interfaces must be changed and modules must be tested Author: sja Date: Tue Mar 1 18:06:25 2011 +0000 add "orignal path" attributes to linux version of local mod Author: sja Date: Tue Mar 1 18:00:19 2011 +0000 Add Path argument for local module Author: sja Date: Tue Mar 1 16:58:01 2011 +0100 Port LOCAL to windows add "orignal path" key in attributes for aff4 modules Author: sja Date: Tue Mar 1 12:22:32 2011 +0100 FIX typedId problem on windows std::map.find( char *) compare pointer value not *(char *) content value Author: Frederic Baguelin Date: Mon Feb 28 19:09:26 2011 +0000 * adds builtins cd and ls Author: Frederic Baguelin Date: Mon Feb 28 18:08:40 2011 +0000 * libypes: ** when boolean PyObject, PyLong_Check and PyInt_Check matches... Taking into account when creating Variant * console + completion, better tricky cases handling * extract: corrected some errors Author: Frederic Baguelin Date: Fri Feb 25 19:30:24 2011 +0000 * console, minor patches ;) * modules extract up to date Author: Frederic Baguelin Date: Fri Feb 25 18:44:55 2011 +0000 * patch for a stupid mistake ! ** loop with non initialized values are bad !!! Thx vertrex to have audited it ;) Author: Frederic Baguelin Date: Fri Feb 25 17:59:52 2011 +0000 * console / completion / raw_input terminated ! Author: sja Date: Fri Feb 25 13:14:30 2011 +0100 Modify library load order for windows in ApiManager Start modificaiton of Local for new argument system, and list of nodes Author: cma Date: Fri Feb 25 12:52:51 2011 +0100 NTFS optimize failed ; reverting for a more stable module. Author: cma Date: Fri Feb 25 12:36:08 2011 +0100 Removes old useles and slow Element class in list_thread.py Creates node matching by date range in timeline.py to made 'Export' reworks when selection (in navigation panel) is active. Need to: - refresh vfs when node has been exported (VLink created), especially tree on the left - improves dichotomic matching ; it as actually too slow when select/zoom/sekect/zoom Author: cma Date: Fri Feb 25 12:24:07 2011 +0100 Add missing EXPORT for Windows Author: Frederic Baguelin Date: Thu Feb 24 20:34:38 2011 +0000 * Console porting almost done. * completion rewrite from scratch with context manager used by console too Author: sja Date: Thu Feb 24 18:34:30 2011 +0000 convert string to UTF-8 Author: rbe Date: Thu Feb 24 15:36:01 2011 +0100 tree view * display a progress bar when a lot of nodes are expanded * gui freeze when a lot of nodes are added at the same time * minor changes in gen_nodes.py module, ignore Author: cma Date: Thu Feb 24 11:46:42 2011 +0100 Adds dichotomy to timestamp lists ; improve speed. Author: Frederic Baguelin Date: Wed Feb 23 19:26:32 2011 +0000 * new style console in progress ** merging setContext, split_line and so in one big class to manage all context instantly ** everything based on python re Author: Frederic Baguelin Date: Wed Feb 23 17:47:53 2011 +0000 * Argument class: ** adds method parametersCount() * console completion ** working and API compliant ** manages argument with list as input parameters ** merge of completeNode and completePath --> completePathes ** STILL MISSING *** check before completing if maximum argument has been provided for input list *** managing completion when braquets are present Author: Frederic Baguelin Date: Tue Feb 22 19:43:59 2011 +0000 * Console completion WIP almost done Author: cma Date: Tue Feb 22 19:42:11 2011 +0100 Modify loader to load a module even directory (package) name and .py file (module) are equal. Add timeline module ; fetch all timestamp from children of a node and create a nice view. Several speed improvements can be made to this module. Author: cma Date: Tue Feb 22 17:45:09 2011 +0100 Add explicit typing to vtime for exif metadata extraction. Author: cma Date: Tue Feb 22 13:14:11 2011 +0100 NTFS optimize Author: sja Date: Mon Feb 21 12:08:11 2011 +0000 Add gen_nodes modules for testing purposes Author: sja Date: Mon Feb 21 12:06:22 2011 +0000 start to include fetch more for treemodel Author: Frederic Baguelin Date: Fri Feb 18 19:06:56 2011 +0000 console compliance in progress Author: mcleodz Date: Fri Feb 18 14:11:43 2011 +0100 Resize layouts inside the dialog Author: fba Date: Fri Feb 18 10:41:56 2011 +0100 * starts console changes to be new API compliant * Config::argumentsByFlags method now supports partial flags ** it's possible to request argument by providing 1, 2 ored, 3 ored flags * minor changes in libtypes.i to provide python wrapper for ** std::list ** std::list ** std::map ** std::map Author: Frederic Baguelin Date: Thu Feb 17 19:56:57 2011 +0000 * re-enables right-click Open with * when modules have no results, popups a simple dialog telling no results... Author: Frederic Baguelin Date: Thu Feb 17 18:34:23 2011 +0000 * results are now re-enabled and are more user friendly * partitions has been enhanced to provide better results * propertytable has been cleaned and simplified * new gui class to render Variant (map + vlist and classical values) * translation updates * env no longer exists (who used it ?) Author: mcleodz Date: Thu Feb 17 11:45:32 2011 +0100 rewrite of open local files and new icon style in mainwindow Author: rbe Date: Wed Feb 16 19:14:40 2011 +0100 treemodel * some nodes do not appear in the tree (must be solved) Author: Frederic Baguelin Date: Tue Feb 15 19:29:06 2011 +0000 * update of extfs.i to re-enables mime-type * remove obsolete code in cat.py Author: Frederic Baguelin Date: Tue Feb 15 19:14:37 2011 +0000 * confmanager is implemented * all modules have been upated to addConstant() mime-type Author: rbe Date: Tue Feb 15 17:47:46 2011 +0100 extfs * version pre1.0 Author: Frederic Baguelin Date: Mon Feb 14 19:48:24 2011 +0000 Start implementation of ConfigManager class * this singleton is used to handle all generated configuration and be available in C++ * it's a kind of replacement to old env class Author: mcleodz Date: Mon Feb 14 17:59:15 2011 +0100 Rework layoutmanager with VFSDialog Author: sja Date: Mon Feb 14 14:20:35 2011 +0000 add larger files size support to viewerimage Author: sja Date: Mon Feb 14 13:55:19 2011 +0000 come back of the fuse modules Author: sja Date: Mon Feb 14 13:04:30 2011 +0000 change cmakelists for fuse Author: sja Date: Mon Feb 14 13:04:13 2011 +0000 mv fuse to connector Author: mcleodz Date: Mon Feb 14 10:30:28 2011 +0100 Applymodule : user can choose to add bot files or directory Author: fba Date: Sat Feb 12 19:25:58 2011 +0100 Updating modules: * ewf, shm, unzip, hash and touch * need testing Author: Frederic Baguelin Date: Fri Feb 11 15:44:05 2011 +0000 * merge attributes fully implemented Author: Frederic Baguelin Date: Fri Feb 11 15:12:29 2011 +0000 * min / max for input parameters of type implemented * check done + generation OK * merge mostly implement * hexviewer ported * opening hexviewer with right-click enabled Author: Frederic Baguelin Date: Fri Feb 11 12:39:06 2011 +0000 * temporary fix in layoutmanager VfsDialogs, remove of proxymodel (it always segfaults...) * minor patch in layoutmanager Author: rbe Date: Fri Feb 11 13:33:47 2011 +0100 sortitems * can now sort by deleted nodes * need some refactoring Author: fba Date: Fri Feb 11 03:25:40 2011 +0100 * add minimum and maximum field for argument taking list as input * update of merge and cut Author: Frederic Baguelin Date: Thu Feb 10 19:31:54 2011 +0000 * minor changes in libtypes.i for error messages Author: Frederic Baguelin Date: Thu Feb 10 19:22:08 2011 +0000 * more error messages and better check when empty list provived in place of required parameters Author: Frederic Baguelin Date: Thu Feb 10 19:03:07 2011 +0000 * more explicit error messages in Config::generate Author: Frederic Baguelin Date: Thu Feb 10 18:46:52 2011 +0000 * adds Constant class * adds new methods to Config to support Constant * patch libtypes: ** in Variant(PyObject*, uint8_t) to convert string to [u]int[16][32][64] ** in Config::generate to try catch directly on argument iteration to be able to throw the name of the current arguments with bad value Author: mcleodz Date: Thu Feb 10 19:32:02 2011 +0100 Last apply module version, with single|list node creation Author: mcleodz Date: Thu Feb 10 18:26:17 2011 +0100 Convert to node argument, improve layoutmanager Author: mcleodz Date: Thu Feb 10 17:12:16 2011 +0100 Add error dialog when bad configuration in apply module, set widget validator by typeid Author: rbe Date: Thu Feb 10 14:47:47 2011 +0100 vfs model * minor graphic changes Author: Frederic Baguelin Date: Thu Feb 10 13:36:47 2011 +0000 When an argument is optional and is not provided, do not process its value Author: Frederic Baguelin Date: Thu Feb 10 12:56:50 2011 +0000 * adds missing throw (std::string) for declaration methods in libtypes.i Author: mcleodz Date: Thu Feb 10 12:38:34 2011 +0100 First step of module validation : Aborte need debug Author: rbe Date: Thu Feb 10 12:12:04 2011 +0100 vfsitemmodel * add header dynamically in the table view * add possibility to display the data type as a header in the tavble view * can sort by the different headers * performances issues when sorting by type (??) Author: mcleodz Date: Thu Feb 10 11:54:25 2011 +0100 Add pixmap and change layout of applymodule in designer Author: Frederic Baguelin Date: Thu Feb 10 09:45:53 2011 +0000 * just renaming changes in config.hpp/cpp ** argumentBy changed to argumentsBy since each method returns a list Author: Frederic Baguelin Date: Wed Feb 9 20:15:32 2011 +0000 * conf::generate(PyObject*) implemented. Need to be tested and stressed Author: mcleodz Date: Wed Feb 9 19:08:39 2011 +0100 * Portage of spare and cut module with new argument system, Add Argument.Empty in applyModule Author: mcleodz Date: Wed Feb 9 17:30:43 2011 +0100 * Applymodule dialog : code and shape clean Author: mcleodz Date: Wed Feb 9 16:23:29 2011 +0100 Change applymodule widget Author: Frederic Baguelin Date: Wed Feb 9 15:01:03 2011 +0000 * remove declaration of pyObjectToVariant in libtypes.i Author: Frederic Baguelin Date: Wed Feb 9 14:57:15 2011 +0000 * class configuration has new implemented methods * libtypes.i compiles and has been cleaned Author: rbe Date: Wed Feb 9 14:51:02 2011 +0100 gui * refresh view when an item is added * refresh view when a column is added in the qtableview Author: mcleodz Date: Wed Feb 9 14:51:00 2011 +0100 Apply module integration Work In progress (auto creation of widgets) Author: rbe Date: Wed Feb 9 11:58:01 2011 +0100 attributes * modify the pop up so it handles advanced attributes * unused for now Author: sja Date: Tue Feb 8 19:28:45 2011 +0000 add new method Node.ynamicAttributesNames that return all modules name that have applyed DynamicAttributes add new method std::list* Node.dynamicAttributes(names) that return all the attributes from one dynamic modules del a print debug in metaexif pass nodebrowser event to vfsitemmmodel Author: Frederic Baguelin Date: Tue Feb 8 19:24:20 2011 +0000 * added Variant::Variant(bool) * Variant.toBool() * convert to bool * reflect changes in libtypes.i * changes Parameter::Fixed --> Parameter::NotEditable * changes Parameter::Customizable --> Parameter::Editable * when no parameters field defined, assume Editable (Argument::Argument()) * reflects all these changes in config of local.i and hash.py Author: sja Date: Tue Feb 8 18:17:19 2011 +0000 new methode in node fsoAttributes / dynamicAttributes vfsiitemmodel now use fsoAttributes by default to faster display on extfs for examples Author: sja Date: Tue Feb 8 17:28:21 2011 +0000 Extfs attributes block_pointer now is a dynamic attributes using attributesHandler for faster implem Author: rbe Date: Tue Feb 8 17:36:17 2011 +0100 extfs * remove a lagging part Author: cma Date: Tue Feb 8 17:32:11 2011 +0100 Outsource build OK on Win. Adds API_DATATYPE_VERSION in top level CMakeLists.txt. Also in top level CMakeLists.txt adds pyuic4.bat to resource compiler check, .bat suffix was not checked. Year rise in COPYRIGHT top level file. Re-adds magic directory in api ; solves compilation problem on VS building magic C-Python bindings with C++ sources in same CMakeLists.txt. Revert magic.mgc in this directory. Modifies api/include/variant.hpp ; *_instance singleton ; strange VS linker behavior. Author: Frederic Baguelin Date: Tue Feb 8 14:38:47 2011 +0000 * reactivate menu for modules Author: mcleodz Date: Tue Feb 8 15:07:26 2011 +0100 Add layout manager Author: Frederic Baguelin Date: Tue Feb 8 13:33:32 2011 +0000 Status: WIP * changes taskmanager to test local module * res added in fso.hpp --> std::map aka VMap in Python * libtypes now support Variant([...], type) which results in a Variant(std::list) * dialog reflects changes of arguments Author: Frederic Baguelin Date: Tue Feb 8 10:32:27 2011 +0000 * minor changes in ui/gui/widget/modules.py to work properly * comment of not compatible modules in modules/CMakeLists.txt Author: sja Date: Tue Feb 8 11:53:59 2011 +0000 add selectAttrs Author: sja Date: Tue Feb 8 11:53:27 2011 +0000 add ui_selectattrs in CMakeLists.txt Author: rbe Date: Tue Feb 8 11:03:24 2011 +0100 ui file Author: rbe Date: Tue Feb 8 10:39:22 2011 +0100 vfsitemmodel * add the ui file * add a pop-up to display the attributes Author: rbe Date: Tue Feb 8 10:31:50 2011 +0100 vfs model * modify vfsitemmodel so it can use the new attributes' system. * Problem of performances Author: Frederic Baguelin Date: Tue Feb 8 00:08:34 2011 +0000 * Status: almost done ** rebase on origin/master ** conflicts fixes ** added config and arguments wrappers with PyObject ** added Variant ctor for PyObject + typeId Author: sja Date: Mon Feb 7 15:12:39 2011 +0000 fix args in taskmanager and processus for single modules Author: fba Date: Sun Feb 6 16:21:50 2011 +0100 * defines module configuration Author: Frederic Baguelin Date: Fri Feb 4 18:54:12 2011 +0000 Status: WIP * implementing last part arguments: ** examples provided in libtypestest.py Author: Frederic Baguelin Date: Fri Feb 4 11:10:32 2011 +0000 Status: WIP All comparison operators implemented: * Variant compared to Variant * Variant compared to PyObject ** operators > < >= and <= between Variant and PyObject implemented Author: Frederic Baguelin Date: Thu Feb 3 19:45:07 2011 +0000 Status: WIP * all comparison operators implemented !!! * Need to do advanced tests (c++ side not yet done) Author: fba Date: Thu Feb 3 01:18:16 2011 +0100 * testing compile on 64 bits architecture ** API and local compile fine * set SWIGDWORDSIZE64 in CMAKE_SWIG_FLAGS when 64 bits architecture ** stdint.i needs this definition to correclty handle [u]int64_t type *** libvfs.i no longer needs ifdef 64_BITS to correctly handle list ** libtypes.i changes swig function call if setted ** libvfs.i no uses this flags for generating appropriate getNodeFromPointer method. Author: Frederic Baguelin Date: Wed Feb 2 19:26:00 2011 +0000 * Variant::to*() implemented and 5 other added * Variant::operator==(Variant*) almost done * Variant::convert() refactored: based on Variant::to* ** handles every possibility. Before, types had to be the same Author: Frederic Baguelin Date: Mon Jan 31 18:54:34 2011 +0000 * overload of Variant::operator== in progress * variant.hpp --> templated operator==(T val) * libtypes.i --> extend Variant::operator==(PyObject *) ** call to Variant_operator_Se__Se_ when PyList. Otherwise, call the templated operator with PyObject* as val. (ugly hack, I know ;) * libtypes.i --> overload of std::list::operator==(PyOject* obj) working Other operators overloading will be fast to develop since based on the same basis as the == operator Author: Frederic Baguelin Date: Fri Jan 28 19:39:43 2011 +0000 * implementing operator on Variant and other tricky features... Author: Frederic Baguelin Date: Mon Jan 24 18:21:09 2011 +0000 EXPERIMENTAL API compiles fine and tests can be launched: Argument class: * all options concerning the argument (base type (string, uint64, ...) input type (list or single), requirement (optional/required) and params type (fixed/custom)) are used as flags (Argument::__flags). They can be setted through setFlags(uint16_t) and getted with flags() methods * setter and getter concerning each flag are implemented * libvfs.i and libtypes.i have been cleaned (uncesseary %include) * modified .hpp files have been cleaned and some useless #include removed Author: Frederic Baguelin Date: Fri Jan 21 19:03:38 2011 +0000 * Only the API can be compiled and tested * Refactoring of some parts of the API: ** fso has now (as before ;) its own files fso.hpp and fso.cpp ** fdmanager, filemapping have their own files too (code is easier to read and to maintain) ** DEventHandler has been renamed to eventhandler and moved in api/events ** all other modified files in api/vfs reflect previous changes * fso::start and mfso::start no longer take Arguments as parameters but std::map * event enum is now directly in Event struct which has been renamend to event... * event struct is now fully Variant compliant ;) that's all folks ! Author: Frederic Baguelin Date: Tue Jan 18 11:54:40 2011 +0000 * Update of API to reflect changes of API based on Variant * Update of console to reflect same changes Author: sja Date: Fri Feb 4 19:33:01 2011 +0000 add the file to the CMakeLists Author: sja Date: Fri Feb 4 19:29:36 2011 +0000 Split node.cpp in three file filemapping.cpp node.cpp and vlink.cpp Author: sja Date: Fri Feb 4 16:56:00 2011 +0000 datatype manager modified for node.dataType Author: sja Date: Fri Feb 4 16:54:38 2011 +0000 node.dataType no return a map with generator name and type Author: cma Date: Fri Feb 4 16:39:47 2011 +0100 NTFS infinite loop fix. Appears for small directory with an INDEX_ROOT outside main MFT entry (in ATTRIBUTE_LIST) without INDEX_ALLOCATION. Author: rbe Date: Fri Feb 4 16:16:40 2011 +0100 add N / A if attributes are empty in the QTableView Author: sja Date: Fri Feb 4 14:35:53 2011 +0000 add attributesNames -> return all the attributes names containe in a map recursivly add ctags to CMakeList ( make tags ) remove SIP compatiblity check in CMakeLists Author: rbe Date: Fri Feb 4 14:36:43 2011 +0100 gui * minor changes * fix in Node.cpp Author: sja Date: Fri Feb 4 13:21:04 2011 +0000 add Ctags support in CMakeList (just do make tags), could be improved for different versions (etags, cscope, ...) Author: rbe Date: Fri Feb 4 13:00:41 2011 +0100 gui * re-implement sort() in vfsitemmodel * implement (can)fetchMore in vfsitemmodel * the 2 previous points were developed to avoid the GUI freewing while loading content of huge directories * WARNING : for now, content can only be sorted by 'name' and 'size', more to come... Author: rbe Date: Thu Feb 3 11:05:25 2011 +0100 gui * improve performances when sorting data in views * add fetchMore in VfsItemModel * add a model for the tree view of the VFS Author: sja Date: Wed Feb 2 13:41:34 2011 +0000 Start of new post process method Author: sja Date: Tue Feb 1 12:45:13 2011 +0000 Fix double click on results Processus Graphical Widget doesn't have mainWindow set in __init__ Author: mcleodz Date: Mon Jan 31 18:31:11 2011 +0100 Bugfix : * Avoid segfault when create a new category * convert to Utf8 the name of the added category, (avoid unicode error) Author: mcleodz Date: Mon Jan 31 18:22:26 2011 +0100 Check if maximizemode is activated and disable it when open a new dockwidget Author: mcleodz Date: Mon Jan 31 18:07:47 2011 +0100 Disable some actions when maximize is activated Author: mcleodz Date: Mon Jan 31 17:29:30 2011 +0100 * Change action name for open As new tab * Change device.py : bugfix load of unicode Author: cma Date: Mon Jan 31 16:58:07 2011 +0100 Drop by previous merge, re-add: - Node browser icon size translatable - Translation for some attributes in Property table Author: mcleodz Date: Mon Jan 31 16:33:17 2011 +0100 New add device dialog * Translate device dialog * Remove old table view Author: sja Date: Mon Jan 31 15:23:44 2011 +0000 Add Node::attributesByType Add Node::attributesByName Add new modules category metadata Add new meta data modules exif that generates exif metadata as node attributes dynamicly modules ported to new attributes system change mime-type tag for ntfs and extfs so it can be autodetected refactor modules for the new new attributes system changed vfsitemmodel so it doesn't call old attributes times method (just commented must be changed) add typedef Attributes std::map to facilitate portage change setIconSize to setGridIconSize Data type handler now cache file type to use less memory Fix there was a wrong mime-type for fat & ntfs that's why the module can't autoload when double click on the node Add compatibleModule node icon as virtual not use sortFilterProxyModel anymore and use batch mode for thumbnails Change nodebrowser so the left tree made appear node without children but with setDir() (display file system directories in left tree) Author: cma Date: Mon Jan 31 14:25:49 2011 +0100 Everything is translated for french language, need to update de, nl and es. Author: cma Date: Mon Jan 31 13:42:44 2011 +0100 Removes hidden texts in extractor dialog, used only for translation, translatable texts back again in extractor.py file. Author: mcleodz Date: Mon Jan 31 13:34:41 2011 +0100 change splash screen image Author: cma Date: Mon Jan 31 13:22:49 2011 +0100 Removes ugly hidden labels in propertytabel, used only for translation, translatable text back again in .py file. Author: mcleodz Date: Mon Jan 31 12:50:05 2011 +0100 * restraint qpushbutton size in nodeviewbox Author: mcleodz Date: Mon Jan 31 12:41:18 2011 +0100 Nodeviewbox : * Remove "None" text on some plateform About : * Change pushbutton to qlabel with pixmap Author: mcleodz Date: Mon Jan 31 12:09:32 2011 +0100 Dockwidget icons : refresh tabbars when reopen closed single dockwidgets Author: mcleodz Date: Mon Jan 31 12:00:32 2011 +0100 IDE : * Connect actions into IDE menu in mainwindow Author: mcleodz Date: Mon Jan 31 11:27:47 2011 +0100 IDE bugfix : * add import Utils (menutags) (remove by previous merge ?) * Open file : replace first argument by self.mainWindow (old : self.parent doesn't exists) Interpreter bugfix : * Add interpreter.ui in ressource CMakeList.txt Menu help : * Change about names actions Author: cma Date: Fri Jan 28 21:00:24 2011 +0100 Makes VFSItemModel hot-translatable. Makes all IDE hot-translatable. Creates ui files for ide main view and dialog. Author: cma Date: Fri Jan 28 18:06:08 2011 +0100 Removes internal border in dockWidgers like nodeBrowser, IDE, hexviewer. Fix for unique dockwidget to be really uniq and to increment title of widget wich can be opened many times. Removes IDE actions, it will be dynamically added once IDE designed with Qt designer. Commit .ts files ; with old string to provide guesses in Qt linguist. Author: mcleodz Date: Fri Jan 28 16:03:09 2011 +0100 IDE : * Centralize actions in ide.py * Remove QScintilla dependency and rewrite of editor.py * write of python syntax highlighting * Add comment and uncomment actions in editor * Add the possibility to create empty script * Change ide wizard and complete some script informations Author: cma Date: Thu Jan 27 21:29:11 2011 +0100 Qt designer ui file for bookmark adding dialog Author: cma Date: Thu Jan 27 20:30:43 2011 +0100 Qt designer ui file for extract dialog. Author: cma Date: Thu Jan 27 19:14:58 2011 +0100 Qt designer file for propertytable. Author: cma Date: Thu Jan 27 17:49:49 2011 +0100 Removes no more used gui Python files. Configuration singleton saves language if provided from command line. Creates .ui files for : - node browser - node view box - apply module - python interpreter - about - evidence dialog Author: cma Date: Wed Jan 26 19:00:19 2011 +0100 minor; fix new ui files not add in ui/gui/i18n/dff.pro and ui/gui/ressources/CMakeLists.txt Author: cma Date: Wed Jan 26 18:54:43 2011 +0100 UI file for nodebrowser and nodeviewbox. Author: mcleodz Date: Wed Jan 26 17:40:34 2011 +0100 Add icon to errors, env & output Author: mcleodz Date: Wed Jan 26 17:07:02 2011 +0100 add new icon ressources and set icon to module widget Author: cma Date: Wed Jan 26 16:35:15 2011 +0100 Use QString instead of str for better unicode comparison Author: cma Date: Wed Jan 26 16:15:58 2011 +0100 minor: use new action for toolbar in mainwindow Author: cma Date: Wed Jan 26 15:59:55 2011 +0100 Creates a resources directory in ui/gui , to place .ui files in. Moves icons and gui.qrc in ui/gui/resources directory. Generated code from .ui files can easily import generated gui_qrc with a common resources directory. Transform env, taskmanager, modules and shell to be translated on the fly. Author: mcleodz Date: Wed Jan 26 14:58:20 2011 +0100 Add dockwidget icon system * Add it manually in the widget with setWindowIcon() * Or add it with qt designer Author: cma Date: Tue Jan 25 16:33:26 2011 +0100 Adds a Edit/Preferences menu, providing hot-language change of GUI. Creates mainwindow.ui to facilitate design and translation. Several modifications in mainwindow.py ; interface is not usable ! Toolbar, shell, IDE and dynamic modules have are not deployed. Author: mcleodz Date: Tue Jan 25 16:11:43 2011 +0100 rename stdio widgets Author: mcleodz Date: Tue Jan 25 15:57:52 2011 +0100 * new dockwidget system ** Add maximize ** add Fullscreen mode ** Remove centralwidget and cut code as widgets Author: cma Date: Mon Jan 24 17:45:43 2011 +0100 Add Patch from Pablo J. Rogina: [PATCH] Proof of concept to use Qt Designer and .ui files for GUI Using Qt Designer to create .ui files will allow DFF to have a graphical way to design GUI components Also: Delete of api/gui/widget/selectdevices.py In top level CMakeLists.txt: - Adds a new check for pyuic4. - Creates a new macro to convert XML ui files to Python files only in build dir. Usage of .ui files enables fast translation and graphical preview of what is to be translated using Qt linguist tool. Author: mcleodz Date: Wed Jan 19 14:25:58 2011 +0100 rename parser to hash Author: sja Date: Wed Jan 19 13:24:10 2011 +0000 Fix there was a wrong mime-type for fat & ntfs that's why the module can't autoload when double click on the node Author: cma Date: Tue Jan 18 12:24:30 2011 +0100 From: Pablo J. Rogina Date: Mon, 17 Jan 2011 14:45:07 -0300 Subject: [PATCH] Updated NodeViewBox to make it translatable Added missing tr() calls along with adding Python files into the list of translatable files and updated Spanish .ts file Thanks to Pablo J. Rogina for this patch. Also update: - French .ts file for new translatable files. - Other .ts files to be updated : Deutsch and Dutch Author: cma Date: Mon Jan 17 15:17:29 2011 +0100 Thanks to Bram Mooij : add support for Dutch language. Use it with -l nl when launching DFF. Author: Frederic Baguelin Date: Fri Jan 14 17:30:28 2011 +0000 it is added as before. Author: cma Date: Thu Jan 13 18:54:26 2011 +0100 Add Deutsch translation in Dff_de.ts. Thanks to Dennis Schreiber. Also modify Dff_fr.ts for new translatable strings. Others .ts modified because of line number change in sources files. Author: mcleodz Date: Wed Jan 12 11:34:01 2011 +0100 open as new tab, QAction commit Author: mcleodz Date: Wed Jan 12 11:26:47 2011 +0100 Issue #87 : Add new action in right click menu : open as new tab Author: mcleodz Date: Tue Jan 11 17:20:05 2011 +0100 close issue #85 : Disable previous and next action when picture viewer load only one image Author: rbe Date: Mon Jan 10 16:08:57 2011 +0100 extfs * minor changes Author: rbe Date: Mon Jan 10 14:16:56 2011 +0100 extfs * uses boyer-moore algorthm to search for the superblock signature if users use the --SB_check option Author: rbe Date: Mon Jan 10 11:22:42 2011 +0100 extfs * rename --run option in --parse_fs (set to True by default) dff-1.3.0+dfsg.1/CHANGES.current000066400000000000000000002425501217176075400160260ustar00rootroot00000000000000DFF (Digital Forensics Framework) This file contains the changes for the current release. See the CHANGES file for changes in older releases. See the RELEASENOTES file for a summary of changes in each release. Version 1.3.0 (27 February 2013) =============================== CHANGES after 10/04/11 are now split in corresponding category. * ui repository : ------------- Author: fba Date: Mon Feb 18 13:39:29 2013 +0100 update of usage message Author: fba Date: Thu Feb 14 10:59:01 2013 +0100 fixes bad unicode handling in processus state Author: fba Date: Tue Feb 12 18:15:13 2013 +0100 update of french translation Author: fba Date: Tue Feb 12 18:12:02 2013 +0100 update of german and french translation Author: sja Date: Mon Feb 11 17:08:50 2013 +0100 use inheritance for modules_path launcher Author: fba Date: Mon Jan 14 19:21:22 2013 +0100 * Update to new building macros Author: fba Date: Mon Jan 14 13:46:24 2013 +0100 * Changes in target creation Author: sja Date: Tue Dec 4 12:19:35 2012 +0100 FIX for widget without titleName use widget name Author: sja Date: Mon Dec 3 19:27:49 2012 +0100 FIX 'toolbar' translation for browser, now mainwindow use windowTitle as id not widget.name() Author: fba Date: Mon Dec 3 11:45:45 2012 +0100 Adds German translation provided by D. Schreiber Author: sja Date: Thu Nov 15 20:11:54 2012 +0100 update translation for taskmanager Author: sja Date: Thu Nov 15 18:36:53 2012 +0100 remove old indexation engine Author: sja Date: Thu Nov 15 16:36:30 2012 +0100 update for translation Author: sja Date: Thu Nov 15 11:37:05 2012 +0100 FIX translation loading Author: sja Date: Wed Nov 14 17:09:46 2012 +0100 update french translation Author: sja Date: Thu Nov 8 17:48:32 2012 +0100 fix import * modules repository : ------------------- Author: sja Date: Mon Feb 25 11:42:30 2013 +0100 FIX module local : typo in attribute name (orignal for original) Author: sja Date: Fri Feb 22 17:16:39 2013 +0100 module exchange : rename __identifier to __id because it's keyword for VS ... Author: sja Date: Thu Feb 21 11:12:58 2013 +0100 Change module/mfso name from pff to exchange Author: sja Date: Tue Feb 19 16:28:40 2013 +0100 FIX #181 PFF fix bug with item attachments Author: sja Date: Mon Feb 18 19:30:57 2013 +0100 FIX pff bug introducing a new structure ItemInfo to handle item type and recovery more easily and dynamically Author: fba Date: Thu Feb 14 11:23:10 2013 +0100 fixes issue with self.vnode which was still a variant Author: sja Date: Wed Feb 13 14:44:30 2013 +0100 fix hexeditor add try/catch for open/close Author: sja Date: Mon Feb 11 17:41:09 2013 +0100 pff_fix test Author: sja Date: Mon Feb 11 14:27:16 2013 +0100 delete experimental will move it to parent directory Author: sja Date: Mon Feb 11 14:23:13 2013 +0100 Module name, description or category was changed to be clearer Author: fba Date: Thu Jan 31 13:07:55 2013 +0100 * Carver GUI ** Adds checks and appropriate message box when: *** No items have been selected *** Input is a folder Author: sja Date: Tue Jan 29 12:15:14 2013 +0100 FIX possible infinite loop on lnk modules applyied on carved or bad lnk Author: fba Date: Wed Jan 16 14:42:43 2013 +0100 *Build process Windows ** Changes *.dll with respective _DYN_LIBRARIES cmake variables Author: jmo Date: Tue Jan 15 15:13:40 2013 +0100 Fixes #152 : Search from cursor error Author: fba Date: Mon Jan 14 13:44:36 2013 +0100 * Include pyrun.swg in all .i files * Changes CMakeLists.txt to support dff_cpp_module macro Author: sja Date: Mon Jan 7 18:13:16 2013 +0100 Use new method to update state of the hash attributes Author: fba Date: Mon Jan 7 15:06:36 2013 +0100 adds a new config parameters for footer instead of using existing one. Made double free when deleting config Author: fba Date: Fri Dec 14 16:04:26 2012 +0100 * Extract ** adds better event handling for reporting failed extraction and renamed files Author: fba Date: Fri Dec 7 18:39:21 2012 +0100 * Modules regviewer ** Adds absolute "path" information and timestamp for each key Author: cma Date: Thu Dec 6 18:35:31 2012 +0100 * NTFS improvements ** Adds filesystem parameters as attributes to the "NTFS" top-level node ** Adds the MFT cluster number as attribute for each file or directory ** Adds the first data cluster as attribute for each file ** Creates a "NTFS unallocated" node near the top-level module node *** Filled with unallocated area from the $Bitmap file *** Each node file is a continuous unallocated area named "starting cluster--ending cluster" *** This commit refs #167, need feedback. Author: cma Date: Mon Dec 3 17:52:04 2012 +0100 * NTFS Fixes ** Infinite loop in directory parsing resulting in NTFS module never ends ** Random files detection on huge directory Author: udgover Date: Wed Nov 28 06:53:34 2012 +0100 fixes an issue due to ModuleRoot asking absolute to early. RegisterTree of RootNode is called before creating subtrees Author: udgover Date: Wed Nov 28 06:52:37 2012 +0100 adding UTF16-LE, UTF16-BE decoders and adds support to 64 bits timestamps in Date decoder Author: udgover Date: Wed Nov 28 06:51:40 2012 +0100 fixes some issues with bad timestamp Author: udgover Date: Wed Nov 28 06:51:13 2012 +0100 if first character of objectName < 0x05, remove it Author: sja Date: Fri Nov 9 16:10:57 2012 +0100 Module use new 'relative' loading method * API repository : ----------------- Author: sja Date: Wed Feb 20 14:45:40 2013 +0100 FIX thread concurrency problem Author: sja Date: Tue Feb 12 14:40:46 2013 +0100 FIX UTF-8 display for node absolute path in configuration widget Author: sja Date: Mon Feb 11 17:30:24 2013 +0100 add thread name to taskmanager Author: sja Date: Mon Feb 11 17:30:00 2013 +0100 add worker name to scheduler thread Author: fba Date: Thu Jan 17 11:24:23 2013 +0100 * Building process ** remove target's name from install_file Author: sja Date: Thu Jan 17 11:01:05 2013 +0100 extract add check before closing file if open fail Author: sja Date: Wed Jan 16 18:21:22 2013 +0100 set import api.gui.video Author: sja Date: Wed Jan 16 18:12:31 2013 +0100 gui/thumbnail.py FIX infinite blocking loop when video api is not present and trying to thumbnail certain video also limit thumbnail size to 100Mo for image to avoid error on false postive file type Author: sja Date: Wed Jan 16 18:12:00 2013 +0100 vfs/extract more verbose error msg when extracted file can't match node size Author: sja Date: Wed Jan 16 15:49:56 2013 +0100 vfs/extract add more error check for extraction Author: sja Date: Wed Jan 16 13:14:13 2013 +0100 close file on exception Author: fba Date: Tue Jan 15 13:52:35 2013 +0100 adds missing %include in swig file of libdevices to be able to use EXPORT Author: fba Date: Tue Jan 15 11:05:27 2013 +0100 * Windows compilation and runtime issues fixed ** without EXPORT in device.hpp and wmidev.hpp, devices.lib is not created and _libdevices.pyd cannot link ** path to magic.mgc in magichandler.py didn't reflect new pathes organisation ** path to *.dll in magic.py didn't reflect new pathes orgatisation ** linked libraries were not coherent for datatype (change datatypes to types...) ** CMakeLists.txt for devices under Windows didn't provide cpp files ** CMakeLists.txt in search didn't provide __init__.py because of bad variables handling Author: fba Date: Mon Jan 14 19:19:10 2013 +0100 * Update to the new building macro Author: fba Date: Mon Jan 14 13:42:02 2013 +0100 * Adds pyrun.swg in all .i files to support our patch to SWIG * changes CMakeLists.txt by using dff_cpp_api macro Author: jmo Date: Fri Jan 11 13:10:30 2013 +0100 Fixes #158, refresh queries line edit on various actions Author: sja Date: Fri Jan 11 12:35:15 2013 +0100 node_list, thumbnail more detailed error message events/eventhandler remove error message vfs/extract.py add static method to check freespace on a disk relative to a path Author: jmo Date: Fri Jan 11 10:58:03 2013 +0100 Fixes #88, save state of sort in navigation, and default sort when changing model list Author: jmo Date: Fri Jan 11 10:23:54 2013 +0100 Fixes #170 Stop scrolling when searching Author: fba Date: Wed Jan 9 11:30:36 2013 +0100 * Variant ** fixes a bug when dealing with Variant of type Char Author: sja Date: Tue Jan 8 18:57:49 2013 +0100 FIX widget resize bug who sometimes lead to crash because of refreshing node_list item scrollbar Author: sja Date: Mon Jan 7 18:11:22 2013 +0100 fixes #162 Add new classes and method to update the state of attributes caches Author: sja Date: Mon Jan 7 18:08:20 2013 +0100 fixes #162 Add new classes AttributesHandlers to more easily manage AttributeHandler and to update the state and notice the DynamicAttribute cache Add new virtual method _attributesState to update the state of the AttributeCache Author: fba Date: Fri Dec 14 16:03:07 2012 +0100 * API: Extract ** adds new notification when file is renamed ** better enclose possible error in try / except with notification for each Author: sja Date: Thu Dec 13 19:29:48 2012 +0100 extract return utf8-encoded renamed file name Author: fba Date: Thu Dec 13 17:41:44 2012 +0100 * API: Extract ** fixes too much arguments provided for extractFolder Author: sja Date: Thu Dec 13 17:06:15 2012 +0100 fix for non utf-8 system Author: fba Date: Thu Dec 13 17:08:02 2012 +0100 * API: Extract ** fixes strange folder renaming behaviour ** changes renaming type for file. It is now based on node uid ** overwrite is better handled Author: sja Date: Thu Dec 13 13:33:19 2012 +0100 FIX extract API for system not using utf-8 as default encoding Author: sja Date: Tue Dec 4 13:09:18 2012 +0100 FIX: try/catch attribute handler to get some attributes even if there is errors Author: sja Date: Fri Nov 30 17:45:05 2012 +0100 Lock refcount Author: sja Date: Fri Nov 30 10:36:20 2012 +0100 FIX refcount issue Author: udgover Date: Wed Nov 28 06:49:29 2012 +0100 private methods going public to enable chunk Author: sja Date: Tue Nov 27 13:31:30 2012 +0100 processus is info is now upcase Author: sja Date: Thu Nov 22 14:06:15 2012 +0100 Taskmanager : add a default output class Author: fba Date: Wed Nov 21 16:04:45 2012 +0100 * API / GUI ** fixes bad variable substitution while performing unicode in launchFilter method Author: sja Date: Thu Nov 15 19:30:07 2012 +0100 FIX devices library import for windows Author: sja Date: Thu Nov 15 18:36:09 2012 +0100 remove old and unused indexation engine Author: sja Date: Thu Nov 15 16:33:34 2012 +0100 update for translation Author: fba Date: Wed Nov 14 17:57:54 2012 +0100 * API: devices ** Uses UDEV_LIBRARY set by cmake instead of -ludev Author: fba Date: Wed Nov 14 17:21:58 2012 +0100 * API: devices ** better management to take into account udev library and headers files Author: sja Date: Wed Nov 14 13:02:25 2012 +0100 FIX utf8 encoded string for additional column Author: sja Date: Tue Nov 13 15:00:03 2012 +0100 FIX Unicode search & filters, remove dead code Author: sja Date: Fri Nov 9 16:03:11 2012 +0100 loader : add method modulesPaths() to get path for modules/__init__.py module: FIX Config owner problem who lead to crash when re-loading a module * cmake_modules repository : ------------------------ Author: fba Date: Wed Jan 16 12:26:48 2013 +0100 fixes some issues for ICU libraries lookup Author: fba Date: Tue Jan 15 19:02:22 2013 +0100 fixes bad variables setting under windows Author: fba Date: Mon Jan 14 19:15:54 2013 +0100 * Fixes an issue in FindICU which was not able to find all components * Main repository : ----------------- Author: fba Date: Thu Feb 14 11:08:13 2013 +0100 provides named parameters when instanciating ui class. Author: fba Date: Tue Feb 12 15:32:52 2013 +0100 adds unsupported submodule and update of api Author: sja Date: Mon Feb 11 17:10:25 2013 +0100 use inheritance for modules path loading rather than copy/paste of imcomprehnsible code Author: fba Date: Thu Jan 31 13:27:34 2013 +0100 Packaging, remove pyc at uninstall Author: fba Date: Thu Jan 31 11:17:08 2013 +0100 * Build process under Windows ** better dependencies management for packaging pass Author: fba Date: Wed Jan 30 17:21:34 2013 +0100 moving some section before cpack configuration to have coherent install / deinstall process on Windows Author: fba Date: Wed Jan 30 13:20:57 2013 +0100 changes minimum version of swig to 2.0.7 Author: fba Date: Wed Jan 30 13:05:55 2013 +0100 * Adds Prerequisites submodules Author: fba Date: Wed Jan 30 13:01:05 2013 +0100 * Change dff's icon Author: fba Date: Thu Jan 17 12:46:11 2013 +0100 * Build process Windows ** changes to provide working installer Author: fba Date: Wed Jan 16 15:57:30 2013 +0100 * Building process: ** Change macro filename_to_path to split_path_file_extension which set __PATH__, __FILE__, __EXTENSION__ when appropriate Author: fba Date: Wed Jan 16 14:28:52 2013 +0100 minor fixes for file command must be in uppercase Author: fba Date: Wed Jan 16 14:07:36 2013 +0100 * Build Process Windows ** update for building the project under Windows ** adds a new macro filename_from_path and set ${filename} variable Author: fba Date: Tue Jan 15 15:08:57 2013 +0100 fixes issue for version of cmake < 2.8.9 Author: fba Date: Tue Jan 15 11:11:45 2013 +0100 * CMakeLists.txt minor changes in path_to_target for windows build process * update of dff/api submodules Author: fba Date: Mon Jan 14 19:22:23 2013 +0100 * Update all building process to new cmake macros Author: fba Date: Mon Jan 14 13:48:28 2013 +0100 * Refactored all target creation system. ** Adds new macros to ease target creation for api and modules *** dff_cpp_api is used to create DFF's API libraries *** dff_cpp_module is used to create DFF's modules ** targets' name are now based on their current path *** it is now possible to do make dff.api.vfs *** all parent targets depend on their children i.e.: make dff.api will call each subtargets Author: fba Date: Wed Jan 9 11:50:33 2013 +0100 * Adds new submodule 'doc' dedicated to documentation Author: fba Date: Wed Jan 9 11:34:21 2013 +0100 * remove of docs folder Author: sja Date: Thu Nov 15 20:13:09 2012 +0100 update translation for taskmanager Author: sja Date: Thu Nov 15 18:40:28 2012 +0100 remove old and unused indexation engine Author: sja Date: Thu Nov 15 16:43:56 2012 +0100 translation update Author: fba Date: Wed Nov 14 18:14:03 2012 +0100 remove of backup cmake_modules Author: fba Date: Wed Nov 14 18:13:05 2012 +0100 * change cmake_modules as a submodule Author: fba Date: Wed Nov 14 17:58:43 2012 +0100 ** adds FindUDEV.cmake ** find_package(udev), ... Author: fba Date: Mon Nov 12 15:51:12 2012 +0100 update of FindTRE.cmake Author: sja Date: Fri Nov 9 16:20:06 2012 +0100 new loading mechanism for modules Author: sja Date: Thu Nov 8 17:49:04 2012 +0100 FIX import in ui Advanced search bugfix; enable thread ** add %option never-interactive in scanner to not add isatty Author: cma Date: Thu Oct 25 16:59:59 2012 +0200 Windows compilation error C2589 fix in video. Some other header file is polluting the global name space with a max macro. Author: cma Date: Thu Oct 25 16:56:59 2012 +0200 Windows compilation : missing code after %extend Author: cma Date: Thu Oct 25 16:29:12 2012 +0200 Windows compilation : include missing Author: cma Date: Thu Oct 25 15:42:02 2012 +0200 FFMpeg DLLs dependencies versions bump for Win32. Author: fba Date: Wed Oct 24 14:38:41 2012 +0200 * API Types ** minor changes to render correctly str on nodes attributes in python *** in libtypes.i map.__str__ did not provide key *** in variant.cpp toString for vtime did not add single quote Author: sja Date: Wed Oct 24 14:19:05 2012 +0200 add rootnode to swig .i files Author: sja Date: Wed Oct 24 13:02:36 2012 +0200 vlink change in ui/gui Author: sja Date: Wed Oct 24 13:01:34 2012 +0200 add vlink to variant Author: sja Date: Wed Oct 24 12:58:51 2012 +0200 add rootnode for modules Author: sja Date: Wed Oct 17 17:11:43 2012 +0200 Remove all 'using namespace std' and put std:: where it's needed Author: sja Date: Wed Oct 17 13:13:57 2012 +0200 HEADER REFACTO include less in .hpp do forward declaration import in cpp ! Author: fba Date: Tue Oct 16 21:35:18 2012 +0200 * API: GUI ** changes contains with matches in clauses Author: sja Date: Tue Oct 16 11:41:02 2012 +0200 processus add lock on exists Author: sja Date: Mon Oct 15 15:09:36 2012 +0200 Cache delref fix Author: sja Date: Mon Oct 15 13:12:30 2012 +0200 Use a template for class Cache Author: sja Date: Mon Oct 15 12:39:49 2012 +0200 Add cache for attribute & dynamicAttribute Author: sja Date: Wed Oct 10 15:21:12 2012 +0200 Move cache & pool used in mfso to cachefile to prepare for attribute cache nothing added in node just group similar function in the file to be more redable Author: sja Date: Wed Oct 10 13:38:30 2012 +0200 small optim of decoder Author: sja Date: Tue Oct 9 17:11:33 2012 +0200 forget to unlock new method fsobjArgumentsByType Author: sja Date: Tue Oct 9 17:02:03 2012 +0200 check if proc was found by fsobj before returning Author: sja Date: Tue Oct 9 16:58:53 2012 +0200 add proc by fsobj and fsbojArgumentsByType method in processus manager Author: fba Date: Mon Oct 8 17:37:01 2012 +0200 * API: Filter ** adds 'path' keyword ** adds wildcard support for attributes *** useful while looking for multiple Recipients with mailboxes: @pff.Recipients.*.Display Name@ matches any of ["Alonso", "Tom", $*Tim*$] Author: fba Date: Mon Oct 8 16:37:52 2012 +0200 * API: Filter ** it is now possible to use == with string ** replaces contain with matches Author: sja Date: Mon Oct 1 13:12:06 2012 +0200 delete variant in astnode.cpp:976 lead to crash Author: sja Date: Thu Sep 27 14:58:10 2012 +0200 Add a question if the same module with the same conf was already applied Author: sja Date: Thu Sep 27 12:52:45 2012 +0200 fix try/catch on bad value for libtypes.i metaexif set date tags to vtime Author: sja Date: Mon Sep 24 15:26:39 2012 +0200 remove lock unecessary after swig patch Author: sja Date: Mon Sep 24 15:14:59 2012 +0200 FIX node_list in case of attributesByType throw Author: sja Date: Mon Sep 24 15:12:33 2012 +0200 add some try/catch but maybe not needed as fixed elsewhere Author: sja Date: Mon Sep 24 15:10:23 2012 +0200 FIX small memory leaks and try/catch on dynamicAttributes & fsoAttributes in case of throwing modules attributes method Author: sja Date: Thu Sep 20 19:42:44 2012 +0200 Selectattributes : Add default attribute and fix other little things (cancel button , ...) Author: sja Date: Thu Sep 20 16:29:10 2012 +0200 hash: add a lock release after a try catch to avoid dead lock ! selectattributes code is now merged (to use right click select all, etc.. in select attributes) nodelistwidgets fix bug for column sort on vtime (use vtime.get_time and special func key sort because vtime.operator< have a really strange behavior ..) and use a key function to avoid None datetime value and none obj nodelistwidgets now header(s) are movable so Author: sja Date: Wed Sep 19 17:31:40 2012 +0200 date text correction Author: sja Date: Wed Sep 19 16:56:18 2012 +0200 check if udev in libdevices.i Author: cma Date: Wed Sep 19 16:19:52 2012 +0200 * BFIO and PFF required version was swapped Author: sja Date: Wed Sep 19 16:10:42 2012 +0200 varianttreewidget now it's possible to copy attribute or value directly by right clicking Author: sja Date: Wed Sep 19 14:34:22 2012 +0200 variant treewidget on double-click show attribute & value, now it's copyable Author: cma Date: Wed Sep 19 14:31:53 2012 +0200 * Build process ** Checks required version of libbfio & libpff, don't build the mailbox module otherwise ** Cleans status messages ** modules/connector/CMakeLists.txt checks for EWF but not for BFIO it has to be fixed Author: jmo Date: Wed Sep 19 11:19:38 2012 +0200 Add registry viewer Author: sja Date: Tue Sep 18 11:09:42 2012 +0200 PFF & libbfio update for the last lib version (libbfio 20120425 & libpff20120802) need to update CMakeList accordingly Author: sja Date: Mon Sep 17 16:46:05 2012 +0200 add use udev rule to be sure to build even if udev not present Author: sja Date: Mon Sep 17 16:32:57 2012 +0200 Device: add a new device library compatibility with libudev build should continue even if udev is not found (linux < 2.6 or using HAL) -> must add this in MakeFile Author: sja Date: Mon Sep 17 09:05:16 2012 +0200 taskmanager add first sort column as int Author: sja Date: Fri Sep 14 18:04:31 2012 +0200 fix for designer taskmanager Author: sja Date: Fri Sep 14 18:03:09 2012 +0200 Add sort to task manager Author: cma Date: Fri Sep 14 15:36:01 2012 +0200 Fixes for timeline not working when it encounters bad date like 0000-00-00 00:00:00. Author: cma Date: Fri Sep 14 15:34:50 2012 +0200 Adds timestamps from $FILENAME attribute in each NTFS node. Also adds attribute offset from start of MFT entry. Author: sja Date: Thu Sep 13 16:10:33 2012 +0200 didn't use vlist anymore as there is sometime the same problem as vmap evn in different list Author: sja Date: Thu Sep 13 13:07:13 2012 +0200 remove some 'print' in extract.py Author: fba Date: Thu Sep 13 12:54:25 2012 +0200 * Modules: Carver ** fixes bad parameters settings Author: sja Date: Wed Sep 12 17:32:03 2012 +0200 ADD a small but neat functionality, save the last opened in the window usefull when loading many files/directory different time Author: sja Date: Tue Sep 11 16:20:03 2012 +0200 metacompund remove 'debug error' Author: sja Date: Tue Sep 11 15:43:13 2012 +0200 FIX a bug in magichandler when open return -1 (fail) UPDATE libbfio_wrapper now use latest version : 20120425 libpff now use latest version : 20120802 -> there is still a bug on attachment of attachment even using clone mode Author: sja Date: Tue Sep 11 15:43:13 2012 +0200 FIX a bug in magichandler when open return -1 (fail) UPDATE libbfio_wrapper now use latest version : 20120425 libpff now use latest version : 20120802 -> there is still a bug on attachment of attachment even using clone mode, it seem to come from libpff itself. Author: sja Date: Tue Sep 11 11:05:09 2012 +0200 mfso add a vfile cache not used yet Author: jmo Date: Thu Sep 6 18:19:18 2012 +0200 Fix stop filter event; Fix visible rows in table/list view Author: jmo Date: Thu Sep 6 17:38:55 2012 +0200 Fix search append item Author: sja Date: Thu Sep 6 15:01:35 2012 +0200 Add lacking EXPORT on addref/delref/refcount method on class FileMapping Author: sja Date: Thu Sep 6 14:04:06 2012 +0200 FileMappingCache rewrote, lock fdmanager & lock filemapping should work better No vfile pool yet, or page caching Author: sja Date: Fri Aug 31 15:21:57 2012 +0200 Change video thumbnail QImage format from RGB32 to ARGB32 Author: jmo Date: Fri Aug 31 11:04:29 2012 +0200 Display last row and scroll by rows in icon view; Author: sja Date: Thu Aug 30 18:44:55 2012 +0200 APSWVFS FIX FOR WINDOWS Author: cma Date: Thu Aug 30 17:46:46 2012 +0200 Deploys video library in system library directory on Unix. Author: sja Date: Thu Aug 30 17:36:12 2012 +0200 node list modified for table view to show all Author: cma Date: Thu Aug 30 17:12:00 2012 +0200 Fixes for Windows all in one, proper NSIS hooks for Python install prior to create .lnk with Python path. Also adds REGLOOKUP path for distributing it on Windows and PIL in Prerequisites Author: jmo Date: Thu Aug 30 16:40:37 2012 +0200 Fix last row update Author: sja Date: Thu Aug 30 15:35:40 2012 +0200 WINDOWS: use mutex rather than critical sections, mutex is lot slower but block on same thread ( != posix recurisve ) ! Author: sja Date: Wed Aug 29 17:31:43 2012 +0200 FIX apswvfs for windows and last lib version Author: sja Date: Wed Aug 29 12:37:09 2012 +0200 Move fuse / extract -> ds tag export Author: sja Date: Tue Aug 28 17:52:21 2012 +0200 CAT module now it's possible to choose text codec for decoding Author: sja Date: Tue Aug 28 15:33:21 2012 +0200 node_list and tree icon use node.fsobj != child[0].fsobj rather than node.fsobj != parent.fsobj to detect root Author: fba Date: Tue Aug 28 15:29:51 2012 +0200 * Modules: Extract ** fixes issue with event handling Author: sja Date: Tue Aug 28 13:30:40 2012 +0200 recommit of preview Author: fba Date: Tue Aug 28 13:30:32 2012 +0200 * Modules: extract ** refactored to use the extraction functionnalities of the API Author: fba Date: Tue Aug 28 13:29:56 2012 +0200 * API: Extract ** moves Extract capabilities to the API Author: sja Date: Tue Aug 28 12:32:36 2012 +0200 Tree & list model : Add a composite '+' on root node icons to differentiate more easily root node Author: sja Date: Mon Aug 27 18:10:56 2012 +0200 Preview : come back of the checkstate button, now that we can add our own button to dockwidget ( must be push in open too) Author: sja Date: Mon Aug 27 16:05:51 2012 +0200 add bookmark to the menu and toolbar , put the code in menu to be able callable from menumanager & nodelistwidgets Author: jmo Date: Mon Aug 27 15:13:11 2012 +0200 New RCPVariant sort accessor; Fixe custom attribute search Author: sja Date: Mon Aug 27 11:59:01 2012 +0200 API thumbnail fix add 'return' to avoid sending two signals Author: sja Date: Tue Aug 14 16:14:05 2012 +0200 remove margins from layout Author: sja Date: Tue Aug 14 14:55:03 2012 +0200 preview add some button to switch preview type Author: jmo Date: Tue Aug 14 12:34:29 2012 +0200 Bugfix loading Unicode filename Author: sja Date: Mon Aug 13 18:34:26 2012 +0200 add filehash icon in module hash Author: sja Date: Mon Aug 13 18:20:35 2012 +0200 new icon for module lnk Author: sja Date: Mon Aug 13 18:20:19 2012 +0200 add new icon link.png Author: sja Date: Mon Aug 13 17:58:18 2012 +0200 add icon to vmware module Author: sja Date: Mon Aug 13 17:57:02 2012 +0200 new icon for vm Author: sja Date: Mon Aug 13 17:53:51 2012 +0200 add icons to device & metacompund Author: sja Date: Mon Aug 13 17:49:57 2012 +0200 new icons movie Author: sja Date: Mon Aug 13 17:49:40 2012 +0200 add new icon Author: jmo Date: Mon Aug 13 17:24:07 2012 +0200 BugFix exception in property table Author: cma Date: Thu Aug 9 13:55:15 2012 +0200 minor * Fix misstake for Windows build ; elseif was used instead of else Author: sja Date: Wed Aug 8 17:17:14 2012 +0200 Add clickable link for node in variant tree widget Author: sja Date: Wed Aug 8 15:19:04 2012 +0200 add 'broken thumbnail' for corrupted picture/video Author: cma Date: Wed Aug 8 14:01:36 2012 +0200 * minor. Bump patch version to 14. Author: sja Date: Wed Aug 8 13:14:45 2012 +0200 fix 'escape from dialog in dialog problem' Author: sja Date: Tue Aug 7 17:23:28 2012 +0200 thumbnail didn't render last image of a row Author: fba Date: Tue Aug 7 17:05:42 2012 +0200 * Modules: Extract ** adds depth argument for countItems and extractTree *** enables to extract one folder content Author: sja Date: Tue Aug 7 16:55:04 2012 +0200 thumbnailer emit signal even if thumbnail can't be created thumbnailer have a new blocking mode Author: sja Date: Tue Aug 7 15:49:50 2012 +0200 fix thumbnail size and corrupted mode for thumbnailer Author: fba Date: Tue Aug 7 15:11:51 2012 +0200 * Modules / Gui: Extraction ** extraction better handles case sensitive destination file system *** renames by suffixing _ ** extraction handles forbidden and reserved characters and words (0x00-0x1f, <, ..., COM1, LPT1, ...) ** new option to preserve absolute path from DFF's vfs ** overwrite option is now provided. Default is no to rename the root folder by suffixing _ Author: cma Date: Mon Aug 6 17:31:21 2012 +0200 Fixes for libraries rename with development build. * Runtime path is set to ./api (cmake magic transparency), where every libNAME.so are copied. * Import chain: libNAME.py importing _libNAME.so linked to libNAME.so is now OK * Problem was with libNAME.so in it's own dir, Python was importing the .so before the .py. Author: cma Date: Mon Aug 6 16:20:37 2012 +0200 Fixes installation on Unix. API libraries are now installed in ${prefix}/lib/dff, each named libNAME instead of liblibNAME. Author: sja Date: Fri Aug 3 17:48:42 2012 +0200 Remove old search_widget and remove 'Searched item' as it not used anymore (better use bookmarks) Author: sja Date: Fri Aug 3 17:21:56 2012 +0200 remove removed file frome dff.pro Author: jmo Date: Fri Aug 3 16:59:05 2012 +0200 New splashscreen Author: sja Date: Fri Aug 3 16:52:30 2012 +0200 remove old logo Author: sja Date: Fri Aug 3 15:41:04 2012 +0200 add new logo to ressource Author: sja Date: Fri Aug 3 13:53:24 2012 +0200 add check recursif for checked/unchecked doc Author: sja Date: Fri Aug 3 13:05:53 2012 +0200 remove search items Author: fba Date: Mon Jul 30 15:14:23 2012 +0200 API: Filters | Index * adds a registry (IndexedPatterns singleton) for all patterns matched during a search * provides method to register a new pattern addPattern(string, Node*) * provides method to get nodes matching a pattern nodesByPattern(string pattern) * provides method to get matched pattern for a node patternsByNode(Node*) Author: cma Date: Thu Jul 26 13:56:57 2012 +0200 * API gui video ** Makes seperate video library. ** Adds EXPORT to video.hpp * Full Windows package ** Adds NumPy and matplotlib as prerequisites for full windows version * Windows version ** Deploys FFMpeg dependencies into build dir. Author: sja Date: Wed Jul 18 13:17:24 2012 +0200 METAEXIF with PIL Author: sja Date: Wed Jul 18 12:47:23 2012 +0200 New thumbnailer Author: sja Date: Wed Jul 18 12:46:41 2012 +0200 Try to remove old node browser Author: sja Date: Mon Jul 16 16:53:25 2012 +0200 FIX time duration in taskmanager Author: fba Date: Fri Jul 13 15:59:19 2012 +0200 Files resulting of the previous commit message... Author: fba Date: Fri Jul 13 15:53:56 2012 +0200 * Build process ** changes cpack generation process *** check if Python and PyQt4 installed *** adds path to python exe into generated shortcuts to enable RunAs feature ** Creates separated dynamic shared libraries for all API components Author: sja Date: Fri Jul 13 13:15:54 2012 +0200 New thumbnailer & video thumbnailer Author: sja Date: Fri Jul 6 18:12:32 2012 +0200 postprocessstate change signal type Author: jmo Date: Fri Jul 6 17:48:36 2012 +0200 Fix switch between search / browser filter view Author: jmo Date: Fri Jul 6 16:19:16 2012 +0200 Fix search issue on advanced mode Author: sja Date: Fri Jul 6 16:15:10 2012 +0200 FIX structuparser -> delete data buff ADD new module -> video thumbnailer preview -> preview video with thumbnail Author: jmo Date: Fri Jul 6 15:07:29 2012 +0200 You can now lock your filter query; fixe some bugs Author: jmo Date: Wed Jul 4 18:04:41 2012 +0200 Advanced search bugfix; enable thread Author: jmo Date: Wed Jul 4 17:35:10 2012 +0200 Drag items in PathList Author: jmo Date: Wed Jul 4 17:26:40 2012 +0200 * Nodebrowser (New feature) : Add filter list * Selection (Bugfix) : remove exception * Search (New feature) : Save / load queries * Search (New feature) : Select search method in quick search Author: fba Date: Wed Jul 4 12:11:26 2012 +0200 * Modules: Extfs ** module description: inform users that module supports EXT version 2, 3 and 4 Author: sja Date: Tue Jul 3 20:19:08 2012 +0200 FIX node->addChild check if child is not null Author: sja Date: Tue Jul 3 20:16:31 2012 +0200 processus add lock at processus creation cause of singleton module structparser delete data content ... mscfb add check before adding file because node.addChild didn't check for null could cause crash in case of error Author: fba Date: Tue Jul 3 18:40:49 2012 +0200 * API: Filters ** reconnect Event handling in Expressions ** fixes some connection / deconnection issues Author: sja Date: Mon Jul 2 19:46:42 2012 +0200 Add tooltip to dockwidget default button Author: fba Date: Mon Jul 2 18:42:46 2012 +0200 * API: TwoThreeTree ** return if value has been inserted or not in method insert Author: fba Date: Mon Jul 2 18:24:48 2012 +0200 * Build process ** add link libexceptions dependencies for events and types Author: fba Date: Mon Jul 2 18:23:08 2012 +0200 * API: TwoTreeTree ** adds return value in two methods... ** when calling find or exists, check size before calling __bsearch... Author: fba Date: Mon Jul 2 15:29:13 2012 +0200 * API TwoThreeTree ** complete refactoring to avoid deep recursion on merge / split / ... ** code is now shorter and easier to understand. Mainly based on FileMapping algorith + merge when inserting can join two elements Author: sja Date: Mon Jul 2 12:52:50 2012 +0200 FIX mfso with scoped mutex FIX vmware didn't close some FD when throw error Author: sja Date: Fri Jun 29 18:15:43 2012 +0200 Patch MFSO -> use new dff:map get_value in place of exists mscfb -> remove some comment vmware-> add some close in case of exceptions Author: jmo Date: Fri Jun 29 15:53:05 2012 +0200 Tree/List model bugfixes Author: jmo Date: Fri Jun 29 15:52:12 2012 +0200 Change icon size and add new ressource files Author: jmo Date: Fri Jun 29 15:50:30 2012 +0200 Add dictionnary search / filter capability Author: fba Date: Fri Jun 29 12:41:32 2012 +0200 * API: exceptions ** exceptions are now handled correctly even whith call like python --> c++ --> python Author: fba Date: Fri Jun 29 10:17:07 2012 +0200 * API: ** Dictionnary *** When creating a dictionnary (FileDictionnary currently), no longer need to associate a name. Name is only needed when registring to DictRegistry ** Filter *** Syntax has been enhanced to let the ability to use dictionnary list, ie: data contain any of [:dict1:, :dict2:, :dict3:] Author: fba Date: Thu Jun 28 15:01:24 2012 +0200 * API: filters ** adds dictionnaries method to DictRegistry to have access to all registered dict ** changes in how to construct Dictionnary : autoregistration disabled ** changes in how to add na dictionnary to registry, name is now longer needed Author: fba Date: Thu Jun 28 12:04:17 2012 +0200 * API mfso ** revert changes concerning scoped mutex map Author: sja Date: Wed Jun 27 18:22:56 2012 +0200 MSLOPES attributes as sometimes wrong length size parameter FIX this by checking if parameter size is > node size to avoid ineficient very large read Author: sja Date: Mon Jun 25 17:41:16 2012 +0200 Error is not set anymore in processus 'res' VMap because this can lead to swig errors Author: sja Date: Thu Jun 21 18:29:06 2012 +0200 Come back of metacompound as it should work now (Need some little fix tough) Author: sja Date: Thu Jun 21 17:26:25 2012 +0200 Add new class Processus Manager to ease processus management ... Modify all module that use it mainly 'builtins' console commands FIX some concurency problem in processus, taskmanager for singleton module like hash who was fixed too Author: sja Date: Thu Jun 21 11:51:53 2012 +0200 Windows threading remove spin Author: sja Date: Wed Jun 20 18:42:17 2012 +0200 change compound lock hash and processus Author: sja Date: Wed Jun 20 13:39:39 2012 +0200 Partitions set a root node for registering Author: sja Date: Wed Jun 20 12:24:09 2012 +0200 Move scoped mutex in api/types/threading, use scoped mutex map in mfso Fix vfile::read(int32_t ) to check for allocated memory Author: fba Date: Tue Jun 19 19:34:17 2012 +0200 * API: Filter ** removes of debug messages Author: fba Date: Tue Jun 19 19:29:43 2012 +0200 * Build: ** define for strtoull Author: fba Date: Tue Jun 19 19:25:00 2012 +0200 * Build: ** Variant comparison operator export Author: fba Date: Tue Jun 19 18:55:37 2012 +0200 * Build: ** adds _ before and after TRUE, FALSE, IN tokens Author: fba Date: Tue Jun 19 18:54:37 2012 +0200 * Build: ** removes EXPORT in front of private idententifier... Author: fba Date: Tue Jun 19 18:04:06 2012 +0200 * Build: ** fixes Windows cmake error Author: fba Date: Tue Jun 19 17:47:13 2012 +0200 * API: Filter ** Huge refactoring of grammar (backward compatible) which is now generic and extends the previous one ** adds dictionnary support * API: GUI ** reflects changes in grammar Author: fba Date: Tue Jun 19 17:42:03 2012 +0200 * API: search ** implement recount, fzcount, ... and fixes some bug Author: fba Date: Tue Jun 19 17:41:11 2012 +0200 * API: Variant ** adds comparison operators for vtime Author: fba Date: Tue Jun 19 17:39:29 2012 +0200 * API: vtime ** better handling of vtime ctor with string *** can be created from YYYY-MM-DD, HH:MM:SS or both YYYY-MM-DDTHH:MM:SS Author: fba Date: Tue Jun 19 17:38:10 2012 +0200 * UI: console ** removes not implemented shell keys Author: fba Date: Tue Jun 19 17:37:32 2012 +0200 * API: vfile ** fixes a bug in search methods Author: sja Date: Mon Jun 18 19:24:09 2012 +0200 Add signal when model receive an registerTree event Author: jmo Date: Mon Jun 18 18:23:25 2012 +0200 Tree model optimization Author: sja Date: Mon Jun 18 17:32:53 2012 +0200 Add icon to partition and remove root 'Partition' node Author: jmo Date: Mon Jun 18 16:36:46 2012 +0200 Set uniform icon size in list view; catch exception in search (percent) Author: sja Date: Mon Jun 18 15:53:43 2012 +0200 FIX BUG in vtime threading and add new version of libmagic (5.11) for windows Author: jmo Date: Mon Jun 18 11:31:16 2012 +0200 Change default icon size on list view Author: jmo Date: Mon Jun 18 10:35:27 2012 +0200 Add resize Icon features, Tree model optimization Author: fba Date: Mon Jun 11 15:56:34 2012 +0200 * API: iostat ** fixes build error on Windows Author: fba Date: Mon Jun 11 14:32:14 2012 +0200 * Modules: local ** forget to declare iterator for arguments Author: fba Date: Tue Jun 5 17:30:19 2012 +0200 * API / Profiling: ** this commit adds IOStat Singleton used in VFile class to: *** provide number of created VFile instances per fsobj *** provide total read bytes per fsobj ** Since it adds calls during reading, this option can only be enabled at compile time with -DWITH_IOSTAT=1 Author: fba Date: Tue Jun 5 12:04:24 2012 +0200 * Modules: local ** On Windows, when parent is not provide use root node by default Author: fba Date: Tue Jun 5 12:03:51 2012 +0200 * API datatype ** adds EXPORT for compiling under Windows Author: fba Date: Mon Jun 4 19:18:54 2012 +0200 * Modules: ** NTFS: uses dff::Mutex + dff::ScopedMutex when calling _attributes method of NtfsNode Author: fba Date: Mon Jun 4 19:15:27 2012 +0200 * Modules: ** NTFS: uses dff::Mutex + dff::ScopedMutex when calling _attributes method of NtfsNode Author: jmo Date: Mon Jun 4 18:52:33 2012 +0200 Avoid edit cell in search filter query dialog Author: fba Date: Mon Jun 4 17:59:18 2012 +0200 * API: datatype ** adds a namespace dff to *** provide Mutex class with lock / trylock / release **** Linux implem is based on pthread mutex and attrs (PTHREAD_MUTEX_RECURSIVE) **** Windows implem is based on CriticalSection and is initialized wiht InitializeCriticalSectionAndSpinCount *** provide ScopedMutex *** adds new map and vector composition class to add thread safe methods (push_back, operator[], ...) by using ScopedMutex Author: jmo Date: Mon Jun 4 17:04:05 2012 +0200 Edit query : Refresh query name Author: jmo Date: Mon Jun 4 16:39:44 2012 +0200 Bugfix: attributeByName list Author: jmo Date: Mon Jun 4 16:19:02 2012 +0200 Set root timeline export node to searched item Author: jmo Date: Mon Jun 4 16:03:19 2012 +0200 Missing import RCVariant in timeline Author: jmo Date: Mon Jun 4 16:00:19 2012 +0200 Fix RCVariant in timeline and bookmark Author: sja Date: Mon Jun 4 15:25:37 2012 +0200 NTFS patch from open 1.2.14 Author: jmo Date: Mon Jun 4 13:30:08 2012 +0200 Avoid noneType issue on nodelistwidget Author: jmo Date: Mon Jun 4 13:20:52 2012 +0200 Remove unused action in menu manager Author: jmo Date: Mon Jun 4 13:18:57 2012 +0200 Quick fix name error in ressource Author: jmo Date: Mon Jun 4 13:11:30 2012 +0200 Add selection menu when right clicking; Treemodel optimization when expand treeview Author: sja Date: Mon Jun 4 11:53:22 2012 +0200 remove error catch in mainwindow for processus widget launching as it was already set in taskmanager Author: sja Date: Mon Jun 4 11:52:11 2012 +0200 Comment module unzip/player/metacompound to avoid crash during Author: sja Date: Mon Jun 4 11:50:40 2012 +0200 Processus -> now widget change state to 'finish' once launched ... , 'fail' state was never set as it was override by finish ... Author: jmo Date: Fri Jun 1 16:07:24 2012 +0200 Enhence expand node and activate pathchanges Author: jmo Date: Fri Jun 1 15:26:49 2012 +0200 Complete rewrite of treemodel Author: cma Date: Thu May 31 18:59:36 2012 +0200 Missing file removed. Author: cma Date: Thu May 31 18:16:40 2012 +0200 Adds EXPORTs to api/include/rc.hpp fixing compilation on Windows. Author: cma Date: Thu May 31 18:14:21 2012 +0200 Adds header needed for ffmpeg/libavutil to compile on Windows. Author: cma Date: Thu May 31 18:06:00 2012 +0200 Removes avcodec_init() in api/gui/video/video.cpp, tested on: * Windows x86 ffmpeg 20120407 * Linux x86_64 ffmpeg 0.10.2 Video module was not working on Windows we have to add libswscale to be linked with video module Author: cma Date: Thu May 31 17:02:41 2012 +0200 Fixes for ffmpeg CMake finder script. The PATHS keyword was missing, resulting in a very odd behavior (INCLUDEs variables was polluted). Author: cma Date: Thu May 31 16:58:48 2012 +0200 Cleaning, magic (py_magic return of the back) validated on Windows. Author: cma Date: Thu May 31 16:52:46 2012 +0200 Fixes for standard output and error output graphically on Windows. Standards file descriptors does not exist on Windows on 100% graphical app. * Create it by opening the file descriptor 1 or 2 * Close it, except number 2 this one need to stay open on Windows to pipe stderr * Pipe and dupe it * That's all stdout and stderr works on 100% graphical app on Windows Author: cma Date: Thu May 31 16:35:52 2012 +0200 Bumps patch version to 12, also Fixes graphical version string. Application version is set in ui/gui/gui.py at the configure step by CMake, this file has again been overwritten in the past. Author: sja Date: Thu May 31 15:18:57 2012 +0200 FIX close in iodevice with signal Author: jmo Date: Thu May 31 14:26:00 2012 +0200 Search from list : avoid NoneType in currentNode Author: fba Date: Thu May 31 13:21:02 2012 +0200 * API ** datatype: avoid segfault on datatypes by adding ref and unref deatures in libdatatype.i ** It means that all c++ code / libraries providing Variant_p mechanism have to declare ref / unref in swig templates * Modules: ** extract now provides extraction progression for each file larger than 10 MB Author: sja Date: Wed May 30 19:30:45 2012 +0200 New thumbnail proxy Author: jmo Date: Wed May 30 19:26:52 2012 +0200 * Improve refresh in list view * Multiselection bugfix in treeview Author: fba Date: Wed May 30 14:54:43 2012 +0200 * API: ** libtypes.i: adds value() and __str__ methods to Variant too (only RCVariant supported these method) Author: jmo Date: Wed May 30 13:02:47 2012 +0200 Add open default when double click Icon view Author: jmo Date: Wed May 30 12:00:21 2012 +0200 Disable search button on simple widget : future replace by quick filter feature on current list Author: sja Date: Tue May 29 19:13:20 2012 +0200 add __init__.py with video & FindFFmpeg swscale missing library that was add on the open who had a bad pushed and was deleted and now was recoded and was recommited here so it will not be loose again ..... add video thumbnailer to node_list who copy/paste the code rather than importing the class ... Author: jmo Date: Tue May 29 16:47:41 2012 +0200 Enable / disable edit custom filter button Author: fba Date: Tue May 29 16:22:45 2012 +0200 * Build ** removes duplicates in CMakeLists.txt of ui/gui/resources Author: fba Date: Tue May 29 16:00:32 2012 +0200 * GUI ** add generated .py in CMakeLists.txt Author: fba Date: Tue May 29 15:41:42 2012 +0200 * Build ** py_magic.c return of the back for Windows... * Module ** carver minor changes Author: fba Date: Tue May 29 14:59:15 2012 +0200 * API / Modules ** removes of all .thisown = False when applied on Variant / VMap / VList Author: sja Date: Tue May 29 13:35:03 2012 +0200 compoundfile : avoid loop in orphaned files when multiple root is present (msdoc said it's impossible ;) Author: jmo Date: Tue May 29 13:01:25 2012 +0200 Add search error messagebox and fix empty query name Author: fba Date: Tue May 29 12:39:06 2012 +0200 * API ** types *** overload of append method for VList to support vlist and vmap assignation *** adds __str__ method for Variant_p Author: fba Date: Fri May 25 18:52:30 2012 +0200 * API ** variant.cpp --> define snprintf _snprintf for windows * Module: ** wlocal.cpp change Variant* --> Variant_p Author: fba Date: Fri May 25 17:43:50 2012 +0200 * Modules: ** removes conflicting target name in CMakeLists (libevents) Author: fba Date: Fri May 25 16:35:37 2012 +0200 before calling absolute in RCVariant.__str__(), first call value... Author: fba Date: Fri May 25 15:51:08 2012 +0200 remove of reverse() Author: fba Date: Fri May 25 15:46:00 2012 +0200 * Modules / ui / api ** Remove of all thisown = False for Variant in Python code * API ** libtypes *** adds __str__ for RCVariant *** adds VLIST.append(VLIST | VMAP) Author: jmo Date: Fri May 25 11:41:19 2012 +0200 Nodeview : Improve scrollbar refresh policy; Search : Improve OnlyFilters (true/false); Model : bugfix segfault issues from insertRows Author: fba Date: Fri May 25 11:37:54 2012 +0200 * API GUI: ** remove of mods.reverse() in nodebrowser. compatibleModules list is now interpreted as a tuple... * Module ** filechart works and char.py has the same functionnalities as pyqt4 examples ** progression is now displayed Author: fba Date: Thu May 24 18:26:49 2012 +0200 * API: ** Variant *** Now Variant inheriths RCObj to be refcounted *** Attributes now handles RCPtr< Variant* > as values *** removes of ugly code in swig file ** Node *** Node no longer returns pointers concerning attributes methods *** attributesByName now returns directly std::list< Variant_p > rather than Variant* *** dataType now returns directly Attributes rather than Variant* * Modules: ** Reflect changes with Variant Author: jmo Date: Mon May 21 19:43:01 2012 +0200 Set default selection color in listModel Author: jmo Date: Mon May 21 19:22:39 2012 +0200 VFSEvent : Avoid nonetype error when no navigation selected Author: jmo Date: Mon May 21 19:05:03 2012 +0200 FileDialog refresh Fix, and remove selectAll feature from headerView Author: sja Date: Mon May 14 18:36:02 2012 +0200 Modify raid modules CMakelist to remove md_superblock who was not pushed Author: jmo Date: Mon May 14 16:04:10 2012 +0200 Fix Issue 154 Author: jmo Date: Mon May 14 16:01:46 2012 +0200 *NodeBrowser: Add EventHandler in order to refresh list model Author: fba Date: Mon May 14 13:08:40 2012 +0200 This commit results to the creation of mcleodz's branches which add: * GUI ** Completly refactored GUI *** Full MVC compliant GUI (models / views and delegates are now distinct) *** Search widget has also been refactored Author: fba Date: Mon May 14 12:23:00 2012 +0200 This commit results to the merging of vertrex's branches which add: * API ** Implementation of references counting system for DFF's objects (working for Python and C++) ** Implementation of Node tagging methods * GUI ** Implementation of node tagging dialog boxes *** adds tags column and tags information in nodes properties widget *** adds tag managment windows to add new tags and edit existing ones (changing names and colors) Author: rbe Date: Fri May 11 12:33:41 2012 +0200 * beggining of the raid module (raid1 ok) * some changes on ext (warning compilation removed) Author: sja Date: Wed May 9 17:50:25 2012 +0200 NTFS fix infinite loop in deleted, and some random read Author: fba Date: Mon May 7 13:27:28 2012 +0200 * Build system: ** provide ffmpeg cmake module ** main cmakelists informs if ffmpeg libraries are found if so, api/gui/video directory will be included to be compiled ** modifies vfsitemmodel to be able to launch dff even if video module has not been compiled To sum up, this commit just adds what other doesn't :) Author: sja Date: Mon May 7 13:21:42 2012 +0200 FIX 'fat' time usecond was not set to 0 so was set to a random value Author: sja Date: Mon May 7 13:21:18 2012 +0200 remove printed error message Author: sja Date: Mon May 7 13:20:09 2012 +0200 FIX widget taskmanager: when a process is waiting is time was not set to 0 but ctime Author: sja Date: Mon May 7 13:19:38 2012 +0200 FIX preview in case of variant errors Author: sja Date: Mon May 7 13:18:54 2012 +0200 FIX PNG type carving Author: sja Date: Mon May 7 13:17:55 2012 +0200 vlink remove comment Author: sja Date: Mon May 7 13:17:02 2012 +0200 FIX close problem, if somethings try to seek/read/search on a closed vfile throw an error Author: sja Date: Mon May 7 13:16:33 2012 +0200 FIX open/close problem on WINREG & MSIECF modules Author: fba Date: Mon May 7 12:45:30 2012 +0200 * Module FAT ** remove of tree registration for Unallocated and Bad Clusters, directly provides parent node to Node ctor Author: sja Date: Thu May 3 13:22:33 2012 +0200 FIX ntfs segfault when mft is not found Author: fba Date: Wed May 2 19:53:26 2012 +0200 new viewer module for file histogram (byte distribution) need matplotlib Author: fba Date: Tue Apr 24 19:21:11 2012 +0200 simple module which take as input a sample file and look for each chunk of chunk_size in provided dump file Author: sja Date: Fri Apr 20 17:46:00 2012 +0200 varianttreewidget remove print Author: sja Date: Fri Apr 20 16:52:51 2012 +0200 Add relative link path to lnk Author: rbe Date: Fri Apr 20 14:12:09 2012 +0200 extfs : * memory leak fix Author: sja Date: Fri Apr 20 13:06:45 2012 +0200 Video: set log level to QUIET ! Author: rbe Date: Fri Apr 20 10:57:25 2012 +0200 Extfs : * add some documentation * remove useless files / classes / methods * bug fixes * add the Fsck option, which check if inode size matches the number of allocated blocks * add an option used to NOT parse the entire file system if the user just needs to start a simple option (fsstat for example). * add slack files (if any) ; this must be triggered by using the --slack option Others : * remove some compilation warnings in vfs, node and fso * fix a bug which used to occur in magichandler Author: sja Date: Thu Apr 19 13:37:24 2012 +0200 Video Some little refactoring Author: sja Date: Thu Apr 19 12:43:29 2012 +0200 New api video & videoDecoder to get thumbnail and metadata from a video (need ffmpeg libav*) Author: fba Date: Tue Apr 10 11:48:33 2012 +0200 * API: types ** Add VLink support to Variant. This patch enables cast VLink to Node for arguments provided to module. Author: sja Date: Fri Apr 6 13:46:42 2012 +0200 libvfs : getNodeFromPointer can return Node or VLink same for every Node* func() propertytable: start showing of hyperlink Author: sja Date: Thu Apr 5 17:27:52 2012 +0200 Add typemout so getnode return VLink instead of Node Author: rbe Date: Thu Apr 5 14:37:48 2012 +0200 * add slack's nodes and an option to chose to display them (or not by default) * fix a bug that prevented file names to be parsed properly Author: sja Date: Thu Apr 5 13:34:57 2012 +0200 add compound file Author: sja Date: Thu Apr 5 12:29:49 2012 +0200 reanme module and directory Author: sja Date: Thu Apr 5 12:23:03 2012 +0200 office some little fix Author: sja Date: Wed Apr 4 18:52:34 2012 +0200 Metaole add options and editing time fix Author: sja Date: Tue Apr 3 19:38:34 2012 +0200 Metaole: Add options to the module, and metadata attributes to the root node Author: sja Date: Tue Apr 3 13:34:49 2012 +0200 Metaole: some fixes and cleanup Author: sja Date: Fri Mar 30 13:23:24 2012 +0200 metaole : add ppt picture extraction Author: sja Date: Thu Mar 29 18:45:53 2012 +0200 Picture in datastream & picture in worddocument Split the code to reflect ms-documentation Author: sja Date: Tue Mar 27 19:51:40 2012 +0200 Office : worddocument picture extraction near finish to read the picture in the data stream (must do last blip type, create node, comment, remove debug, split code in different file, function , ...) could certainly use the same technique to find extract data and picture in worddocument stream Author: rbe Date: Fri Mar 23 13:56:32 2012 +0100 extfs * all options are back on-line ! Author: sja Date: Thu Mar 22 17:53:24 2012 +0100 Metaoffice start to extract text Author: sja Date: Wed Mar 21 18:30:49 2012 +0100 Start of decoding worddocument Author: rbe Date: Wed Mar 21 11:41:42 2012 +0100 bug fixes on extfs module Author: sja Date: Tue Mar 20 15:24:23 2012 +0100 add olestructure Author: sja Date: Tue Mar 20 13:56:41 2012 +0100 Metaole: Parse word DocumentSummary, SumarryInformation, add some VT class, parse red/black tree correctly, ... Author: sja Date: Fri Mar 16 17:02:14 2012 +0100 Add office document metadata Author: sja Date: Thu Mar 15 19:09:06 2012 +0100 OLE add PropertySetStream decoder Author: sja Date: Wed Mar 14 18:14:29 2012 +0100 FIX DIFAT now handle large file, FAT table is now read enterly and set in memory (faster but use mor memory) Author: sja Date: Wed Mar 14 15:02:55 2012 +0100 ole: minifat parsing is now ok , fix recursive loop in fat index Author: sja Date: Tue Mar 13 18:33:36 2012 +0100 update structure size to ssize Author: sja Date: Tue Mar 13 17:49:52 2012 +0100 commit filecharts fix + libtype.i fix ! les variant inside map are not deleted any more -> huge memory leak Author: sja Date: Tue Mar 13 17:48:57 2012 +0100 add new file olestructure Author: sja Date: Tue Mar 13 17:45:16 2012 +0100 office ->metaoffice Author: sja Date: Tue Mar 13 17:39:09 2012 +0100 add metaole CMakeLists Author: sja Date: Tue Mar 13 17:38:30 2012 +0100 add metaole Author: sja Date: Tue Mar 13 17:38:18 2012 +0100 add metaoffice to cmakelists Author: sja Date: Tue Mar 6 12:38:38 2012 +0100 FIX model save/restor painter Author: sja Date: Tue Mar 6 12:32:04 2012 +0100 VLink fix for tags Author: sja Date: Mon Mar 5 15:53:17 2012 +0100 Tags now use a refcount mechanism Author: sja Date: Tue Feb 28 16:51:19 2012 +0100 FIX magichandler self.load / mime.load Author: sja Date: Tue Feb 28 16:43:53 2012 +0100 TAG: unicode, add nodes number in tagmanager and create a TagItem do handle it PROPERTYTABLE: tag unicode Author: sja Date: Tue Feb 28 16:42:14 2012 +0100 FIX magichandler cmakelist & magichandler.load() != magichandler.load(None) Author: sja Date: Fri Feb 24 17:32:06 2012 +0100 TAG: new widget for tagmanagement and editing add this widget action to nodeviewbox Author: fba Date: Fri Feb 24 15:27:31 2012 +0100 fixes issue in CMakeLists.txt of datatype which omitted to add magichandler.py Author: sja Date: Thu Feb 23 12:14:11 2012 +0100 TAG: fix remove in tags.cpp added to property table added to vfsitemmodel with a vfsitemdelegate add to hash Author: rbe Date: Wed Feb 22 14:14:19 2012 +0100 fix dans magichandler.py Author: sja Date: Tue Feb 21 13:04:06 2012 +0100 layoutmanger : add save of argument forq pathcontainer node/tags/libvfs.i : add class tags and implementation in node winreg : don't create node because didn't close and take too much ram must fix that! must also fix how file are managed because just check the name for the hive is insufficient are all hive are parse but very few used hash: rewrote of hash module to support database !! Author: sja Date: Tue Feb 21 12:47:48 2012 +0100 FIX : Come back of the python magic handle, because of better thread / IO handling, don't need to block anymore, so remove thread block in libfilters.i and libvfs.i, this must be tested on windows ... Add lock in mfso cache, check for NULL in filemapping Author: sja Date: Tue Feb 21 12:29:39 2012 +0100 batch: Now DFF shell command in batch must preceed by ! , other command will be interepret as python code, so you can merge the two in a batch script. Comment line starting with # will no be printed anymore as you can use the python print command. When using it with python think to launch DFF in '-d' mode to have the output redirected Author: sja Date: Tue Feb 21 12:24:05 2012 +0100 FIX: get rid of the limit of mergeable nodes Author: sja Date: Tue Feb 21 12:20:17 2012 +0100 FIX: AttributesMap ownership Author: sja Date: Tue Feb 21 12:13:37 2012 +0100 FIX: Many VFile is open when searching for deleted entry most of them where not close (This still need to have an other FIX and better way to handle the underlying node) Memory leak some object was not deleted Add an options to not check for deleted/orphan files (This fonctionality is still buggy and sometimes goes into infinites loop, so it's a way to bypass iti, or gain time when deleted recovery is not needed) Author: sja Date: Tue Feb 21 12:04:15 2012 +0100 FIX: close opened VFile for bootsector on error Author: Frederic Baguelin Date: Wed Feb 8 19:00:31 2012 +0100 * API: ** changed list to vector (which consumes far less memory and is faster) in VFile searches ** methods also return pointer to avoid copy... * Modules: ** Extfs to reflect changes in VFile search Author: Frederic Baguelin Date: Thu Jan 19 13:14:29 2012 +0100 * Build process: ** patch to ease integration and linking of ICU library by giving the ability to specify the libraries and include dirs Author: Frederic Baguelin Date: Tue Jan 17 18:13:10 2012 +0100 * fixes typo error in ide skeletton generator Author: sja Date: Thu Jan 12 17:10:56 2012 +0100 FIX time of processus raising exception didn't stop Author: sja Date: Mon Jan 9 12:24:07 2012 +0100 Set subject as node name (rather than message1, task2, ...) Author: jmo Date: Fri Jan 6 12:59:50 2012 +0100 * New attribute selection system * Bugfix model / view * Disable attributeworker Author: sja Date: Fri Jan 6 12:57:13 2012 +0100 EWF FIX: Open only one time the files with libewf_..._open and use locks (like AFF modules) because libewf_..._open is too slow to be called each times a file is virtually opened Author: jmo Date: Fri Dec 23 11:53:07 2011 +0100 * Model / View : ** Improve model ** Add List view with icon view ** Add toolbar in main widget ** Add workers Author: Frederic Baguelin Date: Thu Dec 22 14:25:52 2011 +0100 * API: Filter ** some refactoring concerning notification to watchers ** process now supports list and vector of nodes Author: jmo Date: Mon Dec 19 15:55:56 2011 +0100 * Model / view ** Add attribute widget ** Connect all signals for keypressevent and mouseclick ** Refresh attributes and preview widgets Author: jmo Date: Mon Dec 19 14:13:17 2011 +0100 * Model bugfix : missing refresh setVisibleRows if not condition Author: Frederic Baguelin Date: Fri Dec 16 15:54:10 2011 +0100 * Modules: Fatfs ** fixes bug in fileMapping when cluster chain is empty Author: Frederic Baguelin Date: Thu Dec 15 12:30:25 2011 +0100 * API: GUI ** Search widget now handles utf8 for all input *** node path, selected node, attributes, search clauses Author: Frederic Baguelin Date: Wed Dec 14 17:17:16 2011 +0100 * Modules: FATFS: ** removes all warnings *** signed / unsigned comparisons *** set but not used Author: Frederic Baguelin Date: Wed Dec 14 16:52:18 2011 +0100 * Modules: FATFS ** fixes dataType for FAT node which can be mapped to boot sector because of silly use lseek in local ** all return of read are fully checked Author: Frederic Baguelin Date: Wed Dec 14 15:06:43 2011 +0100 * Modules: FATFS This commit adds several new features and some bugfixes ** faster algorithms for FAT statistics (I/O reduced) ** clusters loop is now handled in cluster chain (one cluster points to the first one of the list for example) ** bad clusters are fully handled at several steps and nodes are created for each bad clusters space ** nodes representing FAT have new attributes: *** free clusters count *** bad clusters count *** allocated clusters count ** nodes representing files provide new attributes: *** missing clusters (if there are) *** size of missing part *** truncated status ** better slack space managment *** no longer relies on (filesize % clustersize) but on the size of the chain of clusters. Clusters chain is now used for file slack mapping (if possible) Author: Frederic Baguelin Date: Thu Dec 8 16:27:07 2011 +0100 * BUGFIX this commit fixes #127 ** FileMapping chunk resolution from offset has been fixed ** Pushing chunks in an unordered way is now fully functionnal ** requesting chunk from an offset which is not mapped will result in a shadow chunk automatically inserted in the chunk list ** typo error for chunck has been replaced (chunk) Author: sja Date: Thu Nov 24 12:42:38 2011 +0100 Layoutmanger fix module config graphical generator bug when right with module taking a single path argument (ex: fuse) Author: sja Date: Wed Nov 23 18:22:20 2011 +0100 FIX bug in fuse modules, disallow debug options, disallow threads, run in background Author: sja Date: Wed Nov 23 16:27:02 2011 +0100 LNK: move item related codes into a dedicated file use function Author: sja Date: Wed Nov 23 13:57:53 2011 +0100 LNK: continue to refacto item Author: sja Date: Wed Nov 23 13:24:53 2011 +0100 LNK: start moving Item function in lnkheader Author: sja Date: Tue Nov 22 18:09:46 2011 +0100 lnk/CMakelists add lnkheader.py Author: sja Date: Tue Nov 22 18:06:21 2011 +0100 LNK: move AttributesVMap, attributesMap (codes), to structparser as it's reusable Author: sja Date: Tue Nov 22 17:37:31 2011 +0100 LNK: Move ResolveAttributesMap (most attributesMap code) to structparser as it could be reused Author: sja Date: Tue Nov 22 16:46:52 2011 +0100 Move FlagsList (getFlags) to structparser as it could be usefull for other module Author: sja Date: Tue Nov 22 15:22:33 2011 +0100 LNK: refacto -> getDataBlock() Author: sja Date: Tue Nov 22 15:02:37 2011 +0100 LNK refacto, HasLinkInfo Author: sja Date: Tue Nov 22 14:56:07 2011 +0100 LNK refacto => HasLinkTargetIDList Author: sja Date: Tue Nov 22 13:52:44 2011 +0100 LNK: Move header and structure in a separate files Author: Frederic Baguelin Date: Mon Nov 21 13:16:51 2011 +0100 * Module: Fatfs: ** patching issue with toUTF8String in fattree Author: Frederic Baguelin Date: Tue Nov 15 13:08:11 2011 +0100 * Module NTFS ** names are now converted from UTF-16LE to UTF-8. Author: Frederic Baguelin Date: Tue Nov 15 13:01:21 2011 +0100 * Module FATFS ** Long File Names are now converted from UTF-16LE to UTF-8 ** converting 8+3 names will be more difficult since it depends on codepage used on the computer which created an entry Author: Frederic Baguelin Date: Tue Nov 15 12:50:28 2011 +0100 * Building process ** adds cmake module for ICU library and find_package(ICU REQUIRED) in main CMakeLists.txt ** this provides support for character encodings managment in DFF. The aim is that all strings are encoded in UTF-8 Author: sja Date: Mon Nov 7 18:06:19 2011 +0100 structparser add short type parsing Author: sja Date: Thu Nov 3 18:58:26 2011 +0100 New lnk attributes parsing more readable Author: sja Date: Thu Nov 3 16:17:53 2011 +0100 Found new way of decoding item id / shellbag 0x35 & 0x36, seem to work better, also test 'next strings' seem to work well too Author: sja Date: Thu Nov 3 13:14:38 2011 +0100 Decode Item ID type 0x36 Author: sja Date: Wed Nov 2 19:31:21 2011 +0100 Found how work 0x35 undocumented struct ... Author: Frederic Baguelin Date: Fri Oct 28 17:25:10 2011 +0200 * BUGFIX: bad condition checking in Variant ctor Author: sja Date: Fri Oct 28 16:55:30 2011 +0200 LNK darwin datablock & avoid infinite loop Author: sja Date: Fri Oct 28 14:22:47 2011 +0200 LNK add darwin data block Author: sja Date: Fri Oct 28 13:35:55 2011 +0200 LNK add ConsoleDataBlock ! Author: sja Date: Thu Oct 27 20:14:29 2011 +0200 Parse list value of PropertyStorage Author: sja Date: Thu Oct 27 18:18:19 2011 +0200 Add property store and some unpack of serialized data Author: sja Date: Thu Oct 27 14:00:44 2011 +0200 lnk start to add PropertyStorage Author: sja Date: Thu Oct 27 13:04:00 2011 +0200 FIX unicode EnvironmentVariableDataBlock IconEnvironmentVariableDataBlock Author: sja Date: Wed Oct 26 20:23:06 2011 +0200 LNK add first DataBlock decoding Author: sja Date: Tue Oct 25 20:54:36 2011 +0200 LNK : Net name added Author: sja Date: Tue Oct 25 20:17:24 2011 +0200 LNK : Add network provider maps Author: sja Date: Tue Oct 25 19:53:36 2011 +0200 LNK : Before parsing CommonNetworkRelativeLink Author: sja Date: Tue Oct 25 18:46:20 2011 +0200 LNK : Add VolumeID and other very fun stuff Author: sja Date: Tue Oct 25 14:11:43 2011 +0200 Get recursive dictionary / list and other type the right way Author: sja Date: Tue Oct 25 13:02:48 2011 +0200 move structparser to metadata Author: sja Date: Tue Oct 25 12:51:24 2011 +0200 Add msdos32bits time to vtime contstructor, modify FATFS module to use it directly Author: sja Date: Mon Oct 24 20:30:03 2011 +0200 LNK : Add support for list target link not finished yet Author: sja Date: Mon Oct 24 14:24:01 2011 +0200 LNK :Add hotkey flags to lnk Author: sja Date: Mon Oct 24 14:03:21 2011 +0200 LNK : Add showcommand and other decoding sutff to lnk Author: sja Date: Mon Oct 24 13:15:06 2011 +0200 change prefetch path to structparsre Author: sja Date: Mon Oct 24 13:14:30 2011 +0200 move structparser and add it to cmakelist Author: sja Date: Mon Oct 24 13:13:54 2011 +0200 Add start of lnk parser Author: fba Date: Thu Oct 20 16:01:03 2011 +0200 * Packaging: ** removes wrong entries in some CMakeLists resulting in cpack errors Author: fba Date: Thu Oct 20 15:59:01 2011 +0200 * Packaging ** temporary workaround for pyregfi on Windows platform Author: fba Date: Thu Oct 20 15:57:30 2011 +0200 * BUGFIX: winreg ** CVariant method in nodes.py now encloses Variant creation un try / except Author: jmo Date: Thu Oct 20 12:53:52 2011 +0200 * Browsers bugfixes ** Add try / except in inputHistory when parsing registry elements Author: Frederic Baguelin Date: Wed Oct 19 18:57:11 2011 +0200 * BUGFIX threading (credits: Solal Jacob) ** For some cases, there was a deadlock while performing a search and clicking on a matching node. When there was a Python MFSO in the I/O stack, leads to deadlock between Python GIL and datatype mutex. ** This fix is not optimized yet (very slow datatype currently) but avoids the deadlock. Author: Frederic Baguelin Date: Wed Oct 19 18:47:22 2011 +0200 * BUGFIX: Variant ** all ctor taking a pointer now check if it is not NULL. Otherwise throw an error Author: Frederic Baguelin Date: Wed Oct 19 18:33:45 2011 +0200 * BUGFIX: Variant ** Variant ctor used in Python (Variant(PyObject*, uint8_t) now checks that PyObject is not None. Otherwise, it throws an error Author: sja Date: Wed Oct 19 13:20:08 2011 +0200 FIX bug : some time pyregfi iterator throw exception, catch it and continue Author: fba Date: Tue Oct 18 16:02:37 2011 +0200 * Packaging: apsw ** adds apsw installer for Windows Author: sja Date: Sat Nov 12 17:59:44 2011 +0100 Fix Variant deletion problem with prefetch module dff-1.3.0+dfsg.1/CMakeLists.txt000077500000000000000000001306551217176075400161170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # Solal Jacob project (dff) #### Basic Cmake definitions cmake_minimum_required (VERSION 2.6) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/") ## Swig find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) STRING (COMPARE LESS "${SWIG_VERSION}" "2.0.7" SWIGOK) if (${SWIGOK}) MESSAGE(FATAL_ERROR "Need SWIG version >= 2.0.7 (current version is ${SWIG_VERSION})") endif (${SWIGOK}) set(CMAKE_INCLUDE_PATH "${INCLUDEDIR}") set(CMAKE_LIBRARY_PATH "${LIBDIR}") # Optional dependencies required version set(BFIO_REQUIRED_VERSION "20120425") set(PFF_REQUIRED_VERSION "20120802") # Check 64 bit if( "${CMAKE_SIZEOF_VOID_P}" EQUAL 4 ) set( HAVE_64_BIT 0 ) else( "${CMAKE_SIZEOF_VOID_P}" EQUAL 4 ) if (WIN32) set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} -DSWIGWORDSIZE32) else() set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} -DSWIGWORDSIZE64) endif() set( HAVE_64_BIT 1 ) endif( "${CMAKE_SIZEOF_VOID_P}" EQUAL 4 ) # Set installation mode, include all items (*.py, ...) Default is development mode option(DEVELOP "Start installation mode ?" OFF) IF(DEVELOP) message(" /==========================\\") message(" | Running development mode |") message(" \\==========================/") ENDIF(DEVELOP) IF (NOT ${CMAKE_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) SET(DEDICATED_BUILD_DIR 1) message(STATUS "Building project in dedicated build directory : ${CMAKE_BINARY_DIR}") ENDIF (NOT ${CMAKE_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) option(BUILD_UNSUPPORTED "Build unsupported modules ?" OFF) option(ENABLE_DEBUG "Compile using -g flag ? Useful for debugging" OFF) add_definitions(-D__STDC_LIMIT_MACROS) if(UNIX) if(ENABLE_DEBUG) add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -g -Wall) message(STATUS "Will use -g for debugging -- yes") else(ENABLE_DEBUG) #change flag here add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -O2) message(STATUS "Will use -g for debugging -- no") endif(ENABLE_DEBUG) endif(UNIX) # $> cmake -DENABLE_DEBUG:BOOLEAN=OFF option(WITH_IOSTAT "enable statistics on input / output comsumption ?" OFF) if (WITH_IOSTAT) add_definitions(-DWITH_IOSTAT=1) message(STATUS "input / output stats enabled") else (WITH_IOSTAT) message(STATUS "input / output stats disabled") endif (WITH_IOSTAT) option(WITH_TTT_DEBUG "Compile with two three tree debugging" OFF) if (WITH_TTT_DEBUG) add_definitions(-DTWO_THREE_TREE_DEBUG=1) message(STATUS "Compile WITH TwoThreeTree debug information") else (WITH_TTT_DEBUG) message(STATUS "Compile WITHOUT TwoThreeTree debug information") endif (WITH_TTT_DEBUG) IF (WIN32) option(WINALL "Package with windows Dependencies ?" OFF) IF(WINALL) message(STATUS "Packaging windows version with dependencies") ELSE(WINALL) message(STATUS "Packaging windows version without dependencies") ENDIF(WINALL) ENDIF(WIN32) if (ICU_DEP_PATH) if (WIN32) if (HAVE_64_BIT) set(ICU_PATH_SUFFIX "64") else() set(ICU_PATH_SUFFIX "") endif() set(ICU_INCLUDE_PATH "${ICU_DEP_PATH}/include") set(ICU_LIBRARIES_PATH "${ICU_DEP_PATH}/lib${ICU_PATH_SUFFIX}") set(ICU_DYNLIB_PATH "${ICU_DEP_PATH}/bin${ICU_PATH_SUFFIX}") endif (WIN32) endif (ICU_DEP_PATH) find_package(ICU REQUIRED) find_package(AFF) find_package(BFIO) find_package(EWF) find_package(PFF) find_package(TRE) find_package(FFmpeg) if (UNIX) find_package(UDEV) if (UDEV_FOUND) SET(HAVE_UDEV TRUE) message(STATUS "udev include and libraries: FOUND") endif (UDEV_FOUND) endif(UNIX) if (FFMPEG_FOUND) message(STATUS "FFmpeg includes and libraries found video module: ENABLED") else () message(STATUS "FFmpeg includes and libraries not found video module: DISABLED") endif (FFMPEG_FOUND) IF (TRE_FOUND) add_definitions(-DHAVE_TRE) include_directories(${TRE_INCLUDE_DIR}) message(STATUS "TRE installed version: ${TRE_VERSION} approximative matching support : ${TRE_HAVE_APPROX} wide character support : ${TRE_HAVE_WCHAR} multibyte character support : ${TRE_HAVE_MULTIBYTE}") ENDIF (TRE_FOUND) if(PFF_FOUND) if("${PFF_VERSION}" VERSION_EQUAL "${PFF_REQUIRED_VERSION}" OR "${PFF_VERSION}" VERSION_GREATER "${PFF_REQUIRED_VERSION}") message(STATUS "PFF installed version: ${PFF_VERSION} >= ${PFF_REQUIRED_VERSION} -- yes") else("${PFF_VERSION}" VERSION_EQUAL "${PFF_REQUIRED_VERSION}" OR "${PFF_VERSION}" VERSION_GREATER "${PFF_REQUIRED_VERSION}") message(STATUS "PFF installed version: ${PFF_VERSION} >= ${PFF_REQUIRED_VERSION} -- no") unset(PFF_FOUND) unset(PFF_VERSION) endif("${PFF_VERSION}" VERSION_EQUAL "${PFF_REQUIRED_VERSION}" OR "${PFF_VERSION}" VERSION_GREATER "${PFF_REQUIRED_VERSION}") endif(PFF_FOUND) if(BFIO_FOUND) if("${BFIO_VERSION}" VERSION_EQUAL "${BFIO_REQUIRED_VERSION}" OR "${BFIO_VERSION}" VERSION_GREATER "${BFIO_REQUIRED_VERSION}") message(STATUS "BFIO installed version: ${BFIO_VERSION} >= ${BFIO_REQUIRED_VERSION} -- yes") else("${BFIO_VERSION}" VERSION_EQUAL "${BFIO_REQUIRED_VERSION}" OR "${BFIO_VERSION}" VERSION_GREATER "${BFIO_REQUIRED_VERSION}") message(STATUS "BFIO installed version: ${BFIO_VERSION} >= ${BFIO_REQUIRED_VERSION} -- no") unset(BFIO_FOUND) unset(BFIO_VERSION) endif("${BFIO_VERSION}" VERSION_EQUAL "${BFIO_REQUIRED_VERSION}" OR "${BFIO_VERSION}" VERSION_GREATER "${BFIO_REQUIRED_VERSION}") endif(BFIO_FOUND) IF (EWF_FOUND) message(STATUS "EWF installed version: ${EWF_VERSION}") message(STATUS "library: ${EWF_LIBRARY}") ENDIF (EWF_FOUND) if(AFF_FOUND) message(STATUS "AFF installed version: ${AFF_VERSION}") endif(AFF_FOUND) # Project-wide swig options #SET(CMAKE_SWIG_FLAGS "-py3") option(DISABLE_SWIG_THREADING "Wrap cpp code to python without -threads" OFF) if(DISABLE_SWIG_THREADING) message(STATUS "Will we use swig -threads -- no") else() #message(STATUS "Will we use swig -threads -- yes") #set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} -O -threads) set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} -threads) endif(DISABLE_SWIG_THREADING) # $> cmake -DDISABLE_SWIG_THREADING:BOOLEAN=ON find_library(HAVE_FUSE NAMES fuse) if(NOT HAVE_FUSE) message(STATUS "(Optional) fuse library not found; file system module 'fuse' will not be built") endif(NOT HAVE_FUSE) IF(WIN32) SET(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} -DWIN32 -DSWIGWIN) add_definitions("/W3 /D_CRT_SECURE_NO_WARNINGS /wd4290 /nologo") ENDIF(WIN32) ## Python check FIND_PACKAGE(PythonInterp REQUIRED) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_version; print(get_python_version())" OUTPUT_VARIABLE PYTHON_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) if (UNIX) if (APPLE) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_config_vars; print(get_config_vars()[\"PYTHONFRAMEWORKPREFIX\"] + \"/\" + get_config_vars()[\"LDLIBRARY\"])" OUTPUT_VARIABLE PYTHON_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE) else () execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_config_vars; print(get_config_vars()[\"LIBDIR\"] + \"/\" + get_config_vars()[\"LDLIBRARY\"])" OUTPUT_VARIABLE PYTHON_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE) endif (APPLE) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())" OUTPUT_VARIABLE PYTHON_INCLUDE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_config_vars; print(get_config_vars()[\"BINDIR\"])" OUTPUT_VARIABLE PYTHON_BIN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT PYTHON_LIBRARIES) message(SEND_ERROR "No Python library found ; please install Python package, at least version 2.5.") else(NOT PYTHON_LIBRARIES) message(STATUS "Python library found: ${PYTHON_LIBRARIES}") endif(NOT PYTHON_LIBRARIES) if(NOT EXISTS ${PYTHON_INCLUDE_PATH}/Python.h) message(SEND_ERROR "No Python include/header file found; install Python development package.") else(NOT EXISTS ${PYTHON_INCLUDE_PATH}/Python.h) message(STATUS "Python header found: ${PYTHON_INCLUDE_PATH}") endif(NOT EXISTS ${PYTHON_INCLUDE_PATH}/Python.h) else (UNIX) find_package(PythonLibs) find_package(PythonInterp) SET(PYTHON_BIN_PATH ${PYTHON_EXECUTABLE}) # FIXME for windows validate presence of Python.h in PYTHON_INCLUDE_PATH endif(UNIX) message(STATUS "Python in: ${PYTHON_BIN_PATH}") FIND_PACKAGE(PythonLibrary REQUIRED) FIND_PACKAGE(PyQt4 REQUIRED) INCLUDE(PythonMacros) IF (NOT MSVC) ADD_DEFINITIONS(-fPIC) ENDIF () #FIND_PACKAGE(Qt4 REQUIRED) #INCLUDE(${QT_USE_FILE}) if(UNIX) # Search for gzip program, to compress manpage for Unix find_program(GZIP_TOOL NAMES gzip PATHS /bin /usr/bin /usr/local/bin) if(NOT GZIP_TOOL) message(FATAL_ERROR "Unable to find 'gzip' program") endif(NOT GZIP_TOOL) endif(UNIX) ## Python-magic check for Unix only if(UNIX) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import magic; print magic.__file__" OUTPUT_VARIABLE PYTHON_MAGIC_PATH ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT PYTHON_MAGIC_PATH) message(STATUS "Python magic not found. Not needed at build step but mandatory to start DFF.") else(NOT PYTHON_MAGIC_PATH) message(STATUS "Python magic found: ${PYTHON_MAGIC_PATH}") endif(NOT PYTHON_MAGIC_PATH) endif(UNIX) ## Python-QT bindings check execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import PyQt4; print PyQt4.__path__[0]" OUTPUT_VARIABLE PYTHON_QT4_PATH ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT PYTHON_QT4_PATH) message(STATUS "Python QT4 bindings not found. Not needed at build step but mandatory to start DFF.") else(NOT PYTHON_QT4_PATH) message(STATUS "Python QT4 libraries bindings found: ${PYTHON_QT4_PATH}") endif(NOT PYTHON_QT4_PATH) ## PyQt linguist transalation updater check, to create or update translation ## files find_program(PYTHON_QT4_LANGUAGE NAMES pylupdate4 PATHS ${CMAKE_SYSTEM_PROGRAM_PATH} ${PYTHON_QT4_PATH}/bin ${PYTHON_QT4_PATH}) if(PYTHON_QT4_LANGUAGE) message(STATUS "Python Qt4 linguist translation files updater found: ${PYTHON_QT4_LANGUAGE}") else(PYTHON_QT4_LANGUAGE) message(STATUS "Python Qt4 linguist translation files updater not found, unable to check for new tranlatable strings.") endif(PYTHON_QT4_LANGUAGE) ## QT .ts to .qm compiler, used by translator objects find_program(QT_LANGUAGE_COMPILER NAMES lrelease lrelease-qt4 PATHS ${CMAKE_SYSTEM_PROGRAM_PATH} ${PYTHON_QT4_PATH}/bin ${PYTHON_QT4_PATH}) if(QT_LANGUAGE_COMPILER) message(STATUS "QT translation compiler found: ${QT_LANGUAGE_COMPILER}") else(QT_LANGUAGE_COMPILER) message(ERROR "QT translation compiler not found.") endif(QT_LANGUAGE_COMPILER) ## PyQt UI compiler check, to generate widgets find_program(PYTHON_QT4_UIC NAMES pyuic4 pyuic4.bat PATHS ${CMAKE_SYSTEM_PROGRAM_PATH} ${PYTHON_QT4_PATH}/bin ${PYTHON_QT4_PATH}) if(PYTHON_QT4_UIC) message(STATUS "Python Qt4 user interface compiler found: ${PYTHON_QT4_UIC}") else(PYTHON_QT4_UIC) message(SEND_ERROR "Python Qt4 user interface compiler not found.") endif(PYTHON_QT4_UIC) ## PyQt resource compiler check, to generate icons find_program(PYTHON_QT4_RCC NAMES pyrcc4 PATHS ${CMAKE_SYSTEM_PROGRAM_PATH} ${PYTHON_QT4_PATH}/bin ${PYTHON_QT4_PATH}) if(PYTHON_QT4_RCC) message(STATUS "Python Qt4 resource compiler found: ${PYTHON_QT4_RCC}") else(PYTHON_QT4_RCC) message(SEND_ERROR "Python Qt4 resource compiler not found.") endif(PYTHON_QT4_RCC) # Backing up original install prefix, some files have to sit elsewhere than python path, see at the end of this file. SET(CMAKE_INSTALL_ORIG_PREFIX ${CMAKE_INSTALL_PREFIX}) # Install prefix used by Python installer. SET(CMAKE_INSTALL_PREFIX ${PYTHON_SITE_PACKAGES_PATH}/${CMAKE_PROJECT_NAME}/) #message("${CMAKE_INSTALL_ORIG_PREFIX}") ## Main purpose of this macro if to copy Python files at install. # It also deploys .py files in build directory if there is one. LIST(APPEND PYC_FILES "") set_property(GLOBAL PROPERTY PYC_FILES) FILE(WRITE "${CMAKE_BINARY_DIR}/installed_files.log" "") FILE(APPEND "${CMAKE_BINARY_DIR}/targets" "") LIST(APPEND CUSTOM_DEPENDENCIES "") set_property(GLOBAL PROPERTY CUSTOM_DEPENDENCIES) LIST(APPEND CREATED_TARGETS "") set_property(GLOBAL PROPERTY CREATED_TARGET) if (WIN32) set(INSTALL_FILE_DESTINATION "dff") elseif (UNIX) set(INSTALL_FILE_DESTINATION ${PYTHON_SITE_PACKAGES_PATH}) endif (WIN32) macro(log text) if (LOG_BUILD) message(${text}) endif (LOG_BUILD) endmacro(log text) macro(SPLIT_PATH_FILE_EXTENSION item) file(TO_CMAKE_PATH ${item} path) string(FIND "${path}" "/" slash_rpos REVERSE) if (slash_rpos EQUAL -1) set(__FILE__ ${path}) set(__PATH__ "") else() math(EXPR slash_rpos "${slash_rpos} + 1") string(SUBSTRING ${path} ${slash_rpos} -1 __FILE__) string(SUBSTRING ${path} 0 ${slash_rpos} __PATH__) endif() string(FIND "${__FILE__}" "." dot_rpos REVERSE) if (dot_rpos EQUAL -1) set(__EXTENSION__ "") else() math(EXPR dot_rpos "${dot_rpos} + 1") string(SUBSTRING ${__FILE__} ${dot_rpos} -1 __EXTENSION__) endif() endmacro() #split_path_file_extension("/usr/lib/pouet.py") #message("path: ${__PATH__} -- file: ${__FILE__} -- extension: ${__EXTENSION__}") #split_path_file_extension("/usr\\\\lib\\\\pouet.py") #message("path: ${__PATH__} -- file: ${__FILE__} -- extension: ${__EXTENSION__}") #split_path_file_extension("/usr/lib/pouet") #message("path: ${__PATH__} -- file: ${__FILE__} -- extension: ${__EXTENSION__}") #split_path_file_extension("pouet") #message("path: ${__PATH__} -- file: ${__FILE__} -- extension: ${__EXTENSION__}") #split_path_file_extension("pouet.py") #message("path: ${__PATH__} -- file: ${__FILE__} -- extension: ${__EXTENSION__}") macro(DFF_CPP_CONTEXT_INIT library_name) INCLUDE_DIRECTORIES(../include) list(APPEND arguments CPP_FILES SWIG_FILE LINK_LIBRARIES SWIG_FLAGS DEFINITIONS EXTRA_FILES INCLUDE_DIRS INCLUDE_FILES NO_SWIG_LIB_PREFIX) set(arglist "${ARGN}") foreach(argument ${arguments}) list(REMOVE_ITEM arguments ${argument}) string(FIND "${arglist}" ${argument} start_pos) if (NOT ${start_pos} EQUAL -1) string(LENGTH "${arglist}" end_pos) foreach(delim_arg ${arguments}) string(FIND "${arglist}" ${delim_arg} idx) if (idx GREATER start_pos AND idx LESS end_pos) set(end_pos ${idx}) endif() endforeach() math(EXPR length "${end_pos} - ${start_pos}") string(SUBSTRING "${arglist}" ${start_pos} ${length} extracted) string(REPLACE "${extracted}" "" arglist "${arglist}") string(LENGTH "${argument}" val_start) string(SUBSTRING "${extracted}" ${val_start} -1 __${argument}__) string(STRIP "${__${argument}__}" __${argument}__) log("Values for ${argument} : ${__${argument}__}") else () list(REMOVE_ITEM arguments ${argument}) endif () endforeach() endmacro() macro(VS_LIBRARY_PROPERTIES library_name extension) set_target_properties (${library_name} PROPERTIES SUFFIX "${extension}" RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_BINARY_DIR}" RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_BINARY_DIR}" RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_BINARY_DIR}" ) endmacro() macro(DFF_COMPILE_HEAD) # setting default context when compiling CPP dff_cpp_context_init(library_name ${ARGN}) # getting target from path path_to_target() #include(${SWIG_USE_FILE}) include_directories(${PYTHON_INCLUDE_PATH}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_HOME_DIRECTORY}/dff/api/include) if (NOT "${__INCLUDE_DIRS__}" STREQUAL "") include_directories(${__INCLUDE_DIRS__}) endif () if (NOT "${__INCLUDE__}" STREQUAL "") include("${__INCLUDE__}") endif() if (NOT "${__DEFINITIONS__}" STREQUAL "") add_definitions(${__DEFINITIONS__}) endif() if (NOT "${__SWIG_FLAGS__}" STREQUAL "") set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} ${__SWIG_FLAGS__}) endif() endmacro() # Following macro is used to generate DFF's API and Python bindings libraries # # First argument to provide is the name of the library to create then # # Mandatory arguments are : # - CPP_FILES followed by .cpp files # - SWIG_FILE followed by .i files # # Optional arguments are : # - LINK_LIBRARIES followed by needed library # - SWIG_FLAGS followed by needed flags # - DEFINITIONS followed by needed definitions # - EXTRA_FILES followed by extra files you need to install # - INCLUDE_DIRS followed by absolute path to include directories # By default following include dirs are managed # * ${CMAKE_CURRENT_SOURCE_DIR} # * ${CMAKE_HOME_DIRECTORY}/dff/api/include # * ${PYTHON_INCLUDE_PATH} # - INCLUDE followed by files to include # By Default ${SWIG_USE_FILE} are included # # Ex: to create library foo which needs to be linked with # library 'bar' # # DFF_CPP_API(foo # CPP_FILES foo.cpp # SWIG_FILE libfoo.i # LINK_LIBRARIES bar # DEFINITIONS -D__STDC_LIMIT_MACROS # SWIG_FLAGS -threads -fvirtual -fastdispatch # EXTRA_FILES __init__.py # ) macro(DFF_CPP_API library_name) # Setting default context to compile cpp / swig libraries dff_compile_head(${ARGN}) # General purpose DFF's library generation add_library(${library_name} SHARED ${__CPP_FILES__}) target_link_libraries(${library_name} ${__LINK_LIBRARIES__}) if ( CMAKE_GENERATOR MATCHES "Visual Studio") vs_library_properties(${library_name} ".dll") file(APPEND "${CMAKE_BINARY_DIR}/installed_files.log" "${rpath}/${library_name}.dll\n") install(TARGETS ${library_name} DESTINATION ${INSTALL_FILE_DESTINATION}/${rpath}) elseif (UNIX) set_target_properties(${library_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" ) install(TARGETS ${library_name} DESTINATION "${CMAKE_INSTALL_ORIG_PREFIX}/lib/dff/") endif () # Python's binding library generation if (${__NO_SWIG_LIB_PREFIX__}) set(swig_lib_name "${library_name}") else() set(swig_lib_name "lib${library_name}") endif() set_source_files_properties(${__SWIG_FILE__} PROPERTIES CPLUSPLUS ON) swig_add_module(${swig_lib_name} python ${__SWIG_FILE__}) swig_link_libraries(${swig_lib_name} ${PYTHON_LIBRARIES} ${library_name}) if ( CMAKE_GENERATOR MATCHES "Visual Studio") vs_library_properties(${SWIG_MODULE_${swig_lib_name}_REAL_NAME} ".pyd") file(APPEND "${CMAKE_BINARY_DIR}/installed_files.log" "${rpath}/${SWIG_MODULE_${swig_lib_name}_REAL_NAME}.pyd\n") install (TARGETS ${SWIG_MODULE_${swig_lib_name}_REAL_NAME} DESTINATION ${INSTALL_FILE_DESTINATION}/${rpath}) elseif (UNIX) set_target_properties(${SWIG_MODULE_${swig_lib_name}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH FALSE BUILD_WITH_INSTALL_RPATH FALSE INSTALL_RPATH "${CMAKE_INSTALL_ORIG_PREFIX}/lib/dff/" INSTALL_RPATH_USE_LINK_PATH TRUE ) file(APPEND "${CMAKE_BINARY_DIR}/installed_files.log" "${rpath}/${SWIG_MODULE_${swig_lib_name}_REAL_NAME}.so\n") install(TARGETS ${SWIG_MODULE_${swig_lib_name}_REAL_NAME} DESTINATION ${PYTHON_SITE_PACKAGES_PATH}/${rpath}) endif() # Final rules install_file("${swig_lib_name}.py" ${__EXTRA_FILES__}) add_dependencies(${current_target} ${library_name} ${SWIG_MODULE_${library_name}_REAL_NAME}) endmacro() macro(DFF_CPP_MODULE library_name) # Setting default context to compile cpp / swig libraries dff_compile_head(${ARGN}) set_source_files_properties(${__SWIG_FILE__} PROPERTIES CPLUSPLUS ON) swig_add_module(${library_name} python ${__SWIG_FILE__} ${__CPP_FILES__}) swig_link_libraries(${library_name} ${PYTHON_LIBRARIES} ${__LINK_LIBRARIES__}) if ( CMAKE_GENERATOR MATCHES "Visual Studio") vs_library_properties(${SWIG_MODULE_${library_name}_REAL_NAME} ".pyd") file(APPEND "${CMAKE_BINARY_DIR}/installed_files.log" "${rpath}/${SWIG_MODULE_${library_name}_REAL_NAME}.pyd\n") install (TARGETS ${SWIG_MODULE_${library_name}_REAL_NAME} DESTINATION ${INSTALL_FILE_DESTINATION}/${rpath}) elseif (UNIX) file(APPEND "${CMAKE_BINARY_DIR}/installed_files.log" "${rpath}/${SWIG_MODULE_${library_name}_REAL_NAME}.so\n") install(TARGETS ${SWIG_MODULE_${library_name}_REAL_NAME} DESTINATION ${PYTHON_SITE_PACKAGES_PATH}/${rpath}) endif ( CMAKE_GENERATOR MATCHES "Visual Studio" ) install_file("${library_name}.py" ${__EXTRA_FILES__}) add_dependencies(${current_target} ${SWIG_MODULE_${library_name}_REAL_NAME}) endmacro() macro(PATH_TO_TARGET) # Obtain relative path file(RELATIVE_PATH rpath ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) # Replace all '/' with '.' resulting variable becomes current_target string(REPLACE "/" "." current_target "${rpath}") # From current_target, extract the parent_target # parent_target completion depends on all its sub current_target string(FIND "${current_target}" "." dot_rpos REVERSE) if (${dot_rpos} EQUAL -1) set(parent_target "ALL") else (${dot_rpos} EQUAL -1) string(SUBSTRING ${current_target} 0 ${dot_rpos} parent_target) endif (${dot_rpos} EQUAL -1) log("[CONTEXT] : current target : ${current_target} parent target : ${parent_target} relative path : ${rpath}") endmacro() macro(install_rule file) if (NOT DEVELOP) split_path_file_extension(${file}) if (NOT ${__PATH__} STREQUAL "") file(COPY ${file} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) endif() if("${rpath}" STREQUAL "") set(ifile "${__FILE__}") else("${rpath}" STREQUAL "") set(ifile "${rpath}/${__FILE__}") endif("${rpath}" STREQUAL "") file(APPEND "${CMAKE_BINARY_DIR}/installed_files.log" "${ifile}\n") if (${ifile} MATCHES "^.*\\.py$") string(REPLACE "\\" "\\\\" pyc_file "${ifile}") string(REPLACE "/" "\\\\" pyc_file "${pyc_file}") get_property(pyc_list GLOBAL PROPERTY PYC_FILES) list(APPEND pyc_list "${pyc_file}c") set_property(GLOBAL PROPERTY PYC_FILES ${pyc_list}) endif (${ifile} MATCHES "^.*\\.py$") log(" install rule : ${CMAKE_CURRENT_BINARY_DIR}/${__FILE__} DESTINATION ${INSTALL_FILE_DESTINATION}/${rpath}") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${__FILE__} DESTINATION ${INSTALL_FILE_DESTINATION}/${rpath}) endif (NOT DEVELOP) endmacro() macro(install_file) # Create empty strings which will contain all commands for the resulting current_target set(cmds "") path_to_target() # this loop iter on all files provided in ${ARGN} : # * In install mode (default) # - generate install rules # - For windows targeted platfrom, generate all .py to .pyc to remove # pyc files during desinstallation # * all mode with build_dir != src_dir # - create 'copy if different' command for each .py foreach(file ${ARGV}) install_rule(${file}) if (DEDICATED_BUILD_DIR) #message("Copying ${CMAKE_CURRENT_SOURCE_DIR}/${file} in ${CMAKE_CURRENT_BINARY_DIR}") # SWIG generated files are already present in CMAKE_CURRENT_BINARY_DIR if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) if (cmds) set(cmds ${cmds} &&) endif (cmds) set(cmds ${cmds} ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${file} ${CMAKE_CURRENT_BINARY_DIR}/${file}) endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) endif (DEDICATED_BUILD_DIR) endforeach(file ${ARGN}) add_custom_target(${current_target} ALL ${cmds}) set_target_properties(${current_target} PROPERTIES CREATED "true") get_property(created_targets GLOBAL PROPERTY CREATED_TARGETS) list(APPEND created_targets "${current_target}") set_property(GLOBAL PROPERTY CREATED_TARGETS ${created_targets}) log("\n") endmacro(install_file) ## Macro to copy lib at install macro(install_lib target_name) file(RELATIVE_PATH rpath ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) string(REPLACE "/" "." current_target ${rpath}) # From current_target, extract the parent_target # parent_target completion depends on all its sub current_target string(FIND "${current_target}" "." dot_rpos REVERSE) if (${dot_rpos} EQUAL -1) set(parent_target "ALL") else (${dot_rpos} EQUAL -1) string(SUBSTRING ${current_target} 0 ${dot_rpos} parent_target) endif (${dot_rpos} EQUAL -1) log("[CONTEXT] : current target : ${current_target} parent target : ${parent_target} relative path : ${rpath}") endmacro(install_lib) if (APPLE) SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") SET(CMAKE_SHARED_MODULE_SUFFIX ".so") endif(APPLE) ## Macro to convert XML ui files to Python Qt widget code # We are unable to use pyuic4 with QTreeWidget as base class # It is why has to be appended to .ui # files using QTreeWidget. Be carreful, QtDesigner place this second widget at # the end of the .ui file ; which make pyuic4 fails to compile. macro(gui_resources_files target_name) path_to_target() set(cmds "") foreach(file ${ARGV}) string(FIND ${file} "." ext_pos REVERSE) math(EXPR ext_pos "${ext_pos} + 1") string(SUBSTRING ${file} ${ext_pos} -1 extension) if (extension STREQUAL "ui") string(REGEX REPLACE "^(.*)\\.ui$" "ui_\\1.py" PYUICFILE ${file}) set(cmd ${PYTHON_QT4_UIC} -o ${CMAKE_CURRENT_BINARY_DIR}/${PYUICFILE} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) install_rule(${PYUICFILE}) elseif (extension STREQUAL "qrc") string(REGEX REPLACE "^(.*)\\.qrc$" "\\1_rc.py" PY_QRC_FILE ${file}) set(cmd ${PYTHON_QT4_RCC} ${CMAKE_CURRENT_SOURCE_DIR}/${file} -o ${CMAKE_CURRENT_BINARY_DIR}/${PY_QRC_FILE}) install_rule(${PY_QRC_FILE}) elseif (extension STREQUAL "py") if (DEDICATED_BUILD_DIR) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) set(cmd ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${file} ${CMAKE_CURRENT_BINARY_DIR}/${file}) endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) endif (DEDICATED_BUILD_DIR) install_rule(${file}) endif () if (cmds) set(cmds ${cmds} && ${cmd}) else() set(cmds ${cmd}) endif() endforeach() add_custom_target(${current_target} ALL ${cmds}) set_target_properties(${current_target} PROPERTIES CREATED "true") get_property(created_targets GLOBAL PROPERTY CREATED_TARGETS) list(APPEND created_targets "${current_target}") set_property(GLOBAL PROPERTY CREATED_TARGETS ${created_targets}) endmacro() # Override deployment of launcher to add proper Python binary prefix configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dff.py ${CMAKE_CURRENT_BINARY_DIR}/dff.py) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dff-gui.py ${CMAKE_CURRENT_BINARY_DIR}/dff-gui.py) # Create launcher. Replace CMake variables in it, used after install. #configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ressources/linux_launcher.sh ${CMAKE_CURRENT_BINARY_DIR}/dff) #### Subdirectories to recurse add_subdirectory (dff) if (WIN32) foreach (icu_dynlib ${ICU_DYN_LIBRARIES}) install_rule(${icu_dynlib}) endforeach() if (FFMPEG_FOUND) file(GLOB ffmpeg_dyn_libraries ${FFMPEG_ROOT}/bin/*.dll) foreach(ffmpeg_dynlib ${ffmpeg_dyn_libraries}) install_rule(${ffmpeg_dynlib}) endforeach() endif (FFMPEG_FOUND) if (REGLOOKUP_PATH) message(STATUS "Reglookup/pyregfi path: ${REGLOOKUP_PATH}") file(COPY ${REGLOOKUP_PATH}/python/pyregfi DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(pyregfi) file(GLOB reglookup_dyn_libraries ${REGLOOKUP_PATH}/*.dll) foreach(reglookup_dynlib ${reglookup_dyn_libraries}) install_rule(${reglookup_dynlib}) endforeach() else (REGLOOKUP_PATH) message(STATUS "Reglookup/pyregfi path not set") endif (REGLOOKUP_PATH) endif (WIN32) if (UNIX) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_BINARY_DIR}/ctags COMMAND ctags --languages=+C++,+Python --exclude=[*.cxx,*wrap.h] --recurse=yes ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) ADD_CUSTOM_TARGET(tags DEPENDS ${CMAKE_BINARY_DIR}/ctags) endif (UNIX) #### Project install SET(CPACK_SET_DESTDIR "ON") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Digital Forensics Framework") SET(CPACK_PACKAGE_VENDOR "ArxSys") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYRIGHT") # In order to provide top-level setting of DFF version, three variables bellow # must be used in those two files : # ui/gui/gui.py # ui/ui.py # See corresponding CMakeLists.txt for CONFIGURE_FILE. SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "3") SET(CPACK_PACKAGE_VERSION_PATCH "0") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "DFF") message(STATUS "DFF target version is ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") #### Project API versionning set(API_DEVICES_VERSION "0.4.0") set(API_ENV_VERSION "1.1.0") set(API_EXCEPTIONS_VERSION "1.0.0") set(API_GUI_VERSION "1.1.0") set(API_LOADER_VERSION "1.3.0") set(API_MAGIC_VERSION "1.7.0") set(API_MANAGER_VERSION "1.0.0") set(API_MODULE_VERSION "1.0.0") set(API_SEARCH_VERSION "1.0.0") set(API_TASKMANAGER_VERSION "1.1.0") set(API_TREE_VERSION "1.0.0") set(API_TYPE_VERSION "1.0.0") set(API_VARIANT_VERSION "1.0.0") set(API_VFS_VERSION "2.7.0") set(API_DATATYPE_VERSION "1.0.0") set(API_EVENT_VERSION "1.0.0") #### Project install for windows IF(WIN32 AND NOT UNIX) SET(CPACK_SET_DESTDIR "OFF") IF(CMAKE_CL_64) SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") SET(CPACK_NSIS_PACKAGE_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} 64-bit") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION} 64-bit") SET(CPACK_NSIS_DISPLAY_NAME "Digital Forensics Framework 64-bit") ELSE(CMAKE_CL_64) SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") SET(CPACK_NSIS_PACKAGE_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}") SET(CPACK_NSIS_DISPLAY_NAME "Digital Forensics Framework") ENDIF(CMAKE_CL_64) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff.py DESTINATION ${CMAKE_PROJECT_NAME} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff-gui.py DESTINATION ${CMAKE_PROJECT_NAME} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE RENAME dff-gui.pyw) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ressources/dff.ico DESTINATION ${CMAKE_PROJECT_NAME}/ressources/) # Install docs and licenses install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_SOURCE_DIR}/COPYRIGHT ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE-THIRDPARTY DESTINATION ${CMAKE_PROJECT_NAME}/ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) SET(CPACK_MONOLITHIC_INSTALL "ON") SET(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\ressources\\\\arxsys.bmp") SET(CPACK_BUNDLE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\ressources\\\\arxsys.bmp") SET(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\ressources\\\\dff.ico") SET(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\ressources\\\\dff.ico") SET(CPACK_NSIS_HELP_LINK "http://www.digital-forensic.org/") SET(CPACK_NSIS_URL_INFO_ABOUT "http://www.arxsys.fr/") SET(CPACK_NSIS_CONTACT "contact@arxsys.fr") SET(CPACK_NSIS_MODIFY_PATH OFF) SET(CPACK_NSIS_COMPRESSOR "/SOLID lzma") SET(CPACK_GENERATOR "NSIS") SET(NSIS_GET_32_BITS_PATHES " !include \\\"x64.nsh\\\" Var /GLOBAL pypath Var /GLOBAL pyqtpath Var /GLOBAL py_hkcu_path Var /GLOBAL py_hklm_path StrCpy \\\$pypath \\\"\\\" StrCpy \\\$py_hkcu_path \\\"\\\" StrCpy \\\$py_hklm_path \\\"\\\" StrCpy \\\$pyqtpath \\\"\\\" \\\${If} \\\${RunningX64} SetRegView 64 \\\${EndIf} ReadRegStr \\\$py_hkcu_path HKCU \\\"SOFTWARE\\\\Python\\\\PythonCore\\\\2.7\\\\InstallPath\\\" \\\"\\\" ReadRegStr \\\$py_hklm_path HKLM \\\"SOFTWARE\\\\Python\\\\PythonCore\\\\2.7\\\\InstallPath\\\" \\\"\\\" ReadRegStr \\\$pyqtpath HKLM \\\"SOFTWARE\\\\PyQt4\\\\Py2.7\\\\InstallPath\\\" \\\"\\\" \\\${If} \\\$py_hklm_path != \\\"\\\" StrCpy \\\$pypath \\\$py_hklm_path \\\${Else} StrCpy \\\$pypath \\\$py_hkcu_path \\\${EndIf} " ) SET(NSIS_GET_64_BITS_PATHES " Var /GLOBAL pypath Var /GLOBAL pyqtpath StrCpy \\\$pypath \\\"\\\" StrCpy \\\$pyqtpath \\\"\\\" ReadRegStr \\\$pyqtpath HKLM \\\"SOFTWARE\\\\PyQt4\\\\Py2.7\\\" \\\"\\\" ReadRegStr \\\$pypath HKLM \\\"SOFTWARE\\\\Python\\\\PythonCore\\\\2.7\\\\InstallPath\\\" \\\"\\\" " ) SET(NSIS_DEFAULT_LABELS " !include \\\"x64.nsh\\\" \\\${If} \\\${RunningX64} SetRegView 64 \\\${EndIf} inst: Var /GLOBAL installed_version StrCpy \\\$installed_version \\\"\\\" ReadRegStr \\\$R0 HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\dff\\\" \\\"DisplayVersion\\\" ReadRegStr \\\$R1 HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\dff\\\" \\\"UninstallString\\\" \\\${If} \\\$R0 != \\\"\\\" StrCpy \\\$installed_version \\\$R0 \\\${ElseIf} \\\$R1 != \\\"\\\" StrCpy \\\$installed_version \\\$R1 \\\${EndIf} \\\${If} \\\$installed_version != \\\"\\\" MessageBox MB_YESNO|MB_ICONQUESTION \\\"DFF version \\\$installed_version is already installed.\\\$\\\\n\\\$\\\\nClick 'YES' to uninstall it first, or 'NO' to overwrite already installed version.\\\" IDYES uninst Goto done \\\${Else} Goto cont \\\${EndIf} end_with_errors: MessageBox MB_OK|MB_ICONEXCLAMATION \\\"Error uninstalling DFF version \\\$R0.\\\" Goto cont uninst: ClearErrors ExecWait '$R1 _?=$INSTDIR' IfErrors end_with_errors MessageBox MB_OK|MB_ICONINFORMATION \\\"Uninstalling previous DFF version \\\$R0 done, continue with install.\\\" Goto cont cont: File /r \\\"\\\${INST_DIR}\\\\*.*\\\" done: " ) SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS " SetOutPath \\\"$INSTDIR\\\\dff\\\" !include \\\"x64.nsh\\\" \\\${If} \\\${RunningX64} CreateShortCut \\\"$DESKTOP\\\\DFF (64-bit shell).lnk\\\" \\\"\\\$pypath\\\\python.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff.py\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" CreateShortCut \\\"$DESKTOP\\\\DFF (64-bit gui).lnk\\\" \\\"\\\$pypath\\\\pythonw.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff-gui.pyw\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" CreateShortCut \\\"$SMPROGRAMS\\\\Digital Forensics Framework 64-bit\\\\DFF (shell).lnk\\\" \\\"\\\$pypath\\\\python.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff.py\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" CreateShortCut \\\"$SMPROGRAMS\\\\Digital Forensics Framework 64-bit\\\\DFF (gui).lnk\\\" \\\"\\\$pypath\\\\python.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff-gui.pyw\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" \\\${Else} CreateShortCut \\\"$DESKTOP\\\\DFF (shell).lnk\\\" \\\"\\\$pypath\\\\python.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff.py\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" CreateShortCut \\\"$DESKTOP\\\\DFF (gui).lnk\\\" \\\"\\\$pypath\\\\pythonw.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff-gui.pyw\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" CreateShortCut \\\"$SMPROGRAMS\\\\Digital Forensics Framework\\\\DFF (shell).lnk\\\" \\\"\\\$pypath\\\\python.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff.py\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" CreateShortCut \\\"$SMPROGRAMS\\\\Digital Forensics Framework\\\\DFF (gui).lnk\\\" \\\"\\\$pypath\\\\python.exe\\\" \\\"\\\$\\\\\\\"$INSTDIR\\\\dff\\\\dff-gui.pyw\\\$\\\\\\\"\\\" \\\"$INSTDIR\\\\dff\\\\ressources\\\\dff.ico\\\" \\\${EndIf} " ) # # *.pyc files are not deleted by installer, because they are created at # # runtime. So, below, we force deletion of those files. get_property(pyc_list GLOBAL PROPERTY PYC_FILES) foreach (pyc_file ${pyc_list}) set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} Delete \\\"$INSTDIR\\\\dff\\\\${pyc_file}\\\"" ) endforeach (pyc_file ${pyc_list}) SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS " ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} Delete \\\"$DESKTOP\\\\DFF (shell).lnk\\\" Delete \\\"$DESKTOP\\\\DFF (gui).lnk\\\" Delete \\\"$SMPROGRAMS\\\\Digital Forensics Framework\\\\DFF (shell).lnk\\\" Delete \\\"$SMPROGRAMS\\\\Digital Forensics Framework\\\\DFF (gui).lnk\\\" " ) if (WINALL) add_subdirectory (prerequisites) message(STATUS "python installer: ${PYTHON_INSTALLER}") message(STATUS "pyqt installer: ${PYQT_INSTALLER}") message(STATUS "vcredist installer: ${VCREDIST_INSTALLER}") message(STATUS "apsw installer: ${APSW_INSTALLER}") message(STATUS "numpy installer: ${NUMPY_INSTALLER}") message(STATUS "matplotlib installer: ${MATPLOTLIB_INSTALLER}") message(STATUS "PIL installer: ${PIL_INSTALLER}") IF(CMAKE_CL_64) SET(CPACK_SYSTEM_NAME "win64_all_in_one") ELSE(CMAKE_CL_64) SET(CPACK_SYSTEM_NAME "win32_all_in_one") ENDIF(CMAKE_CL_64) SET(CPACK_NSIS_FULL_INSTALL ${CPACK_NSIS_FULL_INSTALL} ${NSIS_DEFAULT_LABELS} " MessageBox MB_YESNO \\\"Install ${PYTHON_INSTALLER} ? \\\" /SD IDYES IDNO InstPyQt ExecWait '\\\"msiexec\\\" /i \\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${PYTHON_INSTALLER}\\\" /passive ALLUSERS=1' Goto InstPyQt InstPyQt: MessageBox MB_YESNO \\\"Install ${PYQT_INSTALLER} ? \\\" /SD IDYES IDNO InstAPSW ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${PYQT_INSTALLER}\\\"' Goto InstAPSW InstAPSW: MessageBox MB_YESNO \\\"Install ${APSW_INSTALLER}? \\\" /SD IDYES IDNO InstPil ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${APSW_INSTALLER}\\\"' Goto InstPil InstPil: MessageBox MB_YESNO \\\"Install ${PIL_INSTALLER}? \\\" /SD IDYES IDNO InstVcredist ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${PIL_INSTALLER}\\\"' Goto InstVcredist ") if (BUILD_UNSUPPORTED) set(CPACK_NSIS_FULL_INSTALL ${CPACK_NSIS_FULL_INSTALL} " InstVcredist: MessageBox MB_YESNO \\\"Install Microsoft Visual Studio DLL dependencies ? \\\" /SD IDYES IDNO InstNumpy ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${VCREDIST_INSTALLER}\\\" /q:a' Goto InstNumpy InstNumpy: MessageBox MB_YESNO \\\"Install ${NUMPY_INSTALLER}? \\\" /SD IDYES IDNO InstMatplotlib ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${NUMPY_INSTALLER}\\\"' Goto InstMatplotlib IntMatplotlib: MessageBox MB_YESNO \\\"Install ${MATPLOTLIB_INSTALLER}? \\\" /SD IDYES IDNO InstEnd ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${MATPLOTLIB_INSTALLER}\\\"' Goto InstEnd ") else() set(CPACK_NSIS_FULL_INSTALL ${CPACK_NSIS_FULL_INSTALL} " InstVcredist: MessageBox MB_YESNO \\\"Install Microsoft Visual Studio DLL dependencies ? \\\" /SD IDYES IDNO InstEnd ExecWait '\\\"$INSTDIR\\\\dff\\\\Prerequisites\\\\${VCREDIST_INSTALLER}\\\" /q:a' Goto InstEnd ") endif() set(CPACK_NSIS_FULL_INSTALL ${CPACK_NSIS_FULL_INSTALL} " InstEnd: RMDir /r \\\"$INSTDIR\\\\dff\\\\Prerequisites\\\" " ${NSIS_GET_32_BITS_PATHES}) else(WINALL) if (HAVE_64_BIT) else() SET(CPACK_NSIS_FULL_INSTALL ${NSIS_GET_32_BITS_PATHES} " \\\${If} \\\$pypath == \\\"\\\" MessageBox MB_OK|MB_ICONEXCLAMATION \\\"Python 2.7 32 bits not found.\\\$\\\\nPlease install it before installing DFF.\\\" Goto done \\\${Else} Goto pyqt_check \\\${EndIf} pyqt_check: \\\${If} \\\$pyqtpath == \\\"\\\" MessageBox MB_OK|MB_ICONEXCLAMATION \\\"PyQt4 for Python 2.7 32 bits not found.\\\$\\\\nPlease install it before installing DFF.\\\" Goto done \\\${Else} Goto inst \\\${EndIf} " ${NSIS_DEFAULT_LABELS} ) endif() endif(WINALL) SET(CPACK_SOURCE_GENERATOR "ZIP") SET(CMAKE_INSTALL_PREFIX "") ELSE(WIN32 AND NOT UNIX) SET(CPACK_SOURCE_GENERATOR "TGZ") # SET(CPACK_SOURCE_IGNORE_FILES "") SET(CPACK_GENERATOR "DEB" "RPM") ENDIF(WIN32 AND NOT UNIX) # Debian deb dependencies # python${PYTHON_VERSION} (>=${PYTHON_VERSION}.0), python-qt4 (>= 4.4.0), python-magic (>= 4.26) # RedHat rpm dependencies # python >= ${PYTHON_VERSION}.0, PyQt4 >= 4.4.0, python-magic >= 4.26 if (UNIX) # Compress manpage add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dff.1.gz COMMAND ${GZIP_TOOL} -c ${CMAKE_CURRENT_SOURCE_DIR}/doc/man/dff.1 > ${CMAKE_CURRENT_BINARY_DIR}/dff.1.gz COMMENT "Building dff.1.gz") add_custom_target(manpage ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dff.1.gz) # Install man page install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff.1.gz DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/share/man/man1 PERMISSIONS OWNER_READ GROUP_READ WORLD_READ RENAME dff.1.gz) # Install docs and licenses install(FILES README COPYRIGHT LICENSE LICENSE-THIRDPARTY DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/share/doc/${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} PERMISSIONS OWNER_READ GROUP_READ WORLD_READ RENAME) # Install binary launcher, icons, shortcuts. #install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff #DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/bin #PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ressources/dff.png ${CMAKE_CURRENT_SOURCE_DIR}/ressources/dff.xpm DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/share/pixmaps PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ressources/dff.desktop DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/share/applications PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff.py DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/bin/ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE RENAME dff) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff-gui.py DESTINATION ${CMAKE_INSTALL_ORIG_PREFIX}/bin/ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE RENAME dff-gui) #else (UNIX) # install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dff.py # DESTINATION ${PYTHON_SITE_PACKAGES_PATH}/${CMAKE_PROJECT_NAME} # PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif(UNIX) INCLUDE(CPack) ENABLE_TESTING() SUBDIRS(testsuite) function(CHECK_ORPHANED_PARENT_DEPENDENCIES target) set(dot_pos 0) set(tmp ${target}) list(APPEND prefixes "") set(current_target ${target}) while((NOT ${dot_pos} EQUAL -1) AND (NOT ${tmp} STREQUAL "dff")) string(FIND ${tmp} "." dot_pos REVERSE) string(SUBSTRING ${tmp} 0 ${dot_pos} tmp) list(APPEND prefixes ${tmp}) endwhile() list(REVERSE prefixes) set(parent_target "") foreach(prefix ${prefixes}) get_target_property(prop ${prefix} CREATED) if (NOT prop STREQUAL "true") log("Target <${prefix}> does not exist") add_custom_target("${prefix}" ALL DEPENDS ${parent_target}) log(" custom target created with DEPENDS setted to ${parent_target}") set_target_properties(${prefix} PROPERTIES CREATED "true") endif() set(parent_target ${prefix}) endforeach() endfunction() get_property(created_targets GLOBAL PROPERTY CREATED_TARGETS) foreach(current_target ${created_targets}) string(FIND ${current_target} "." dot_pos REVERSE) string(SUBSTRING ${current_target} 0 ${dot_pos} parent_target) log("Making build dependencies between ${current_target} and its parent ${parent_target}") if (NOT ${current_target} STREQUAL "dff") check_orphaned_parent_dependencies(${current_target}) add_dependencies(${parent_target} ${current_target}) endif() endforeach() log(" ========================================== | .pyc files to be uninstalled with NSIS | ==========================================\n") get_property(pyc_list GLOBAL PROPERTY PYC_FILES) foreach (pyc_file ${pyc_list}) log("${pyc_file}") endforeach (pyc_file ${pyc_list}) dff-1.3.0+dfsg.1/COPYRIGHT000066400000000000000000000014111217176075400146320ustar00rootroot00000000000000DFF -- An open source Digital Forensics Framework Copyright (C) 2009-2013 ArxSys This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. dff-1.3.0+dfsg.1/LICENSE000066400000000000000000000431031217176075400143500ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dff-1.3.0+dfsg.1/LICENSE-THIRDPARTY000066400000000000000000000137141217176075400160450ustar00rootroot00000000000000Copyright and license below covers the images in directory ui/gui/icons/ ************************************************************************ TITLE: Crystal Project Icons AUTHOR: Everaldo Coelho SITE: http://www.everaldo.com CONTACT: everaldo@everaldo.com LICENSE: LGPL Staff: Ingolfur Haraldsson (ingo@linpire.com) Luiz Claudio dos Santos (luiz@yellowicon.com) Rhandros Dembicki (rhandros@yellowicon.com) Paulo andre (paulo@yellowicon.com) Edson Farias (edson@yellowicon.com) Andre Souza (andre@yellowicon.com) One of those have been modified to fit Digital Forensics Framework requirements Jeremy MOUNIER (jmo@arxsys.fr) Copyright and license below covers the scripts in directory cmake_modules/ ************************************************************************** Files FindPyQt.py, FindLibPython.py, SIPMacros.cmake, PythonMacros.cmake, FindSIP.cmake, FindSIP.py and FindPythonLibrary.cmake: Copyright (c) 2007, Simon Edwards Redistribution and use is allowed according to the terms of the BSD license. For details see the accompanying COPYING-CMAKE-SCRIPTS file. File FindPyQt4.cmake: Copyright (c) 2007-2008, Simon Edwards Redistribution and use is allowed according to the terms of the BSD license. For details see the accompanying COPYING-CMAKE-SCRIPTS file. File PythonCompile.py: By Simon Edwards This file is in the public domain. Copyright and license below covers the script file modules/metadata/metaexif/EXIF.py ************************************************** Copyright (c) 2002-2007 Gene Cash All rights reserved Copyright (c) 2007-2008 Ianaré Sévi All rights reserved Redistribution and use is allowed according to the terms of the BSD license. # Copyright (C) 2007,2008 Volatile Systems Copyright and license below covers the scripts in directory modules/mem/Volatility-1.3_Beta/ *********************************************************** File vutils.py, vtypes.py, vmodules.py, forensics/win32/datetime.py, forensics/win32/handles.py, forensics/win32/info.py, forensics/win32/network.py, forensics/win32/tasks.py and forensics/object.py: Copyright (C) 2007,2008 Volatile Systems Copyright (C) 2007 Komoku, Inc. File vsyms.py, forensics/win32/vad.py, forensics/win32/modules.py, forensics/symbols.py: Copyright (C) 2007 Komoku, Inc. File forensics/win32/crashdump.py, forensics/win32/executable.py: Copyright (c) 2007,2008 Volatile Systems Copyright (c) 2008 Brendan Dolan-Gavitt File forensics/win32/registry.py, forensics/win32/meta_info.py: Copyright (C) 2007,2008 Volatile Systems File memory_objects/Windows/xp_sp2.py: Copyright (c) 2008 Volatile Systems Copyright (c) 2008 Brendan Dolan-Gavitt File forensics/win32/xpress.py, forensics/win32/hiber_addrspace.py: Copyright (c) 2008 Volatile Systems Copyright (c) 2008 Brendan Dolan-Gavitt Code found inspired by the work of Matthieu Suiche. File forensics/win32/scan2.py, forensics/registry.py: Copyright (C) 2007,2008 Volatile Systems Copyright 2004: Commonwealth of Australia. Derived from source in PyFlag developed by Michael Cohen and David Collett File forensics/win32/scan.py: Copyright (C) 2007,2008 Volatile Systems Source code in this file was inspired by the work of Andreas Schuster and ptfinder. File forensics/win32/crash_addrspace.py: Copyright (C) 2007,2008 Volatile Systems Copyright (C) 2005,2006,2007 4tphi Research Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) File forensics/object2.py: Copyright (C) 2007,2008 Volatile Systems Copyright (C) 2005,2006 4tphi Research Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) File forensics/addrspace.py, forensics/x86.py: Copyright (C) 2007,2008 Volatile Systems Copyright (C) 2004,2005,2006 4tphi Research Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) File forensics/commands.py, memory_plugins/example3.py, memory_plugins/example2.py, memory_plugins/example1.py: Copyright (C) 2008 Volatile Systems 31 files listed above are licensed: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. File thirdparty/progressbar.py: Copyright (c) 2005 Nilton Volpato This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Copyright and license below covers the source file api/include/wstdint.h ************************************************************************ Copyright (c) 2006-2008 Alexander Chemeris Redistribution and use is allowed according to the terms of the BSD license. Copyright and license below covers the source file api/include/wstdint.i ************************************************************************ SWIG is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the LICENSE-GPL file for the full terms of the GNU General Public license version 3. Copyright and license below covers the sources files api/magic/py_magic.c, ./api/magic/py_magic.h ************************************************************************** Copyright (C) Brett Funderburg, Deepfile Corp. Austin, TX, US 2003 Redistribution and use is allowed according to the terms of the BSD license. Copyright and license below covers the source file api/magic/magic.h ******************************************************************** Copyright (c) Christos Zoulas 2003. Redistribution and use is allowed according to the terms of the BSD license. dff-1.3.0+dfsg.1/README000066400000000000000000000113521217176075400142240ustar00rootroot00000000000000Digital Forensics Framework 1. Introduction 2. Installation 2.1 Windows 2.2 Linux 3. Usage 4. Support 1. Introduction DFF is a simple but powerfull open source tool with a flexible module system which will help you in your digital forensics works, including files recovery due to error or crash, evidence research and analysis, etc. The source code is written in C++ and Python, allowing performances and great extensibility. Although dff is quite young, it already provides a robust architecture and some handy modules. You could download and try it via the Dowload page. Source code, Debian packages and even windows setup are available. Any contribution, suggestion or remark is welcome ! (see 4. Support) Nowadays computer forensic analysis tools are mainly large proprietary software developed by some well-known companies. Few free and open source tools offers the same type of fully integrated software, most of them are implemented as stand alone tools. Although some framework exists, they are not very user or developer friendly. That is why we decided to develop this tool as a free and open source and multi-platform framework. This project follows three main goals : - Modularity. In contrary to the monolithic model, the modular model is based on an a host and many modules. This modular conception presents two advantages : it permits to improve rapidly the software and to split easily tasks for developers - Scriptability, it is obvious that the ability to be scripted gives more flexibility to a tool, but it enables automation and gives the possibility to extend features - Genericity, the project tries to remain OS independent. We want to help people where they are ! Letting them choose any Operating System to use this software. 2. Installation 2.1 Windows Python and Python QT have to be installed first. Two packages are provided for Windows, one with those two dependencies add to DFF installer and an other with DFF installer alone. Web-page where Python should be downloaded : http://www.python.org/download/releases/2.7.1/. Web-page where Python QT should be downloaded : http://www.riverbankcomputing.co.uk/software/pyqt/download DFF is provided with a Nullsoft installer. Users just have to launch it and follow instructions to install DFF. 2.2 Linux Using distribution package : RPM and DEB packages are provided on http://www.digital-forensic.org. Graphical helper from window manager can be used when double clicking on the package. DEB installation from terminal : #> dpkg -i dff-.deb RPM installation from terminal #> rpm -i dff-.rpm Compiling from sources : A GZipped tarball is also provided. Cmake and latest version of swig are needed (http://www.swig.org, developer have to compile and install the latest version himself). In the top-source tree type : $> cmake -DINSTALL=TRUE . It creates make files. To build type : $> make Install : #> make install Console Run : $> dff.py Graphical Run : $> dff.py -g 3. Usage DFF reads a disk dump (for example from GNU 'dd' utils). Two user interfaces are provided ; graphical and console. Command-line console also sits in graphical as well. Graphical : Click on the 'File(s)' menu and select 'Open evidence file(s)', then add your disk dump. Right-click on the dump, in the 'Browser' tab, select 'Open with' and apply a filesystem module ; select 'file system' and 'fat' for example. Files appears in the 'Virtual File System' tab. Many informations are provided under 'Task Manager', 'Output' and 'Errors' tabs. Console : Opening a local folder : dff / > local --path /home/user/dumps --parent / --path is the directory to open --parent is a virtual node, first specify the root one : / Applying fat module on a dump : dff / > fat dumps/test.fat.dd Listing nodes : dff / > ls Completion is provided using the key. User can obtain help using : dff / > man 4. Support Online chat is on an IRC channel : #digital-forensic on irc.freenode.net network. Main website : http://www.digital-forensic.org . 3 mailing lists are provided : - User discussions about DFF : dff@digital-forensic.org, registration and posting freely available. - Developers discussions about DFF : dff-devel@digital-forensic.org, registration and posting freely available. - News about DFF releases and event : dff-announce@digital-forensic.org, registration freely available, low level traffic. Archives of this mailing lists : http://lists.digital-forensic.org A project manager exists at https://tracker.digital-forensic.org , ideas and bug submited by e-mail will be reported on it. Documentation sits on http://wiki.digital-forensic.org. dff-1.3.0+dfsg.1/RELEASENOTES000066400000000000000000000140001217176075400151510ustar00rootroot00000000000000Release Notes ============= Detailed description of changes is available in the CHANGES.current and CHANGES files. The summary below just contains a brief overview of the changes made in each release. DFF-1.3.0 summary: Features: --------- User Interfaces: ---------------- * Node browser : - The browser is now UTF-8 aware, so it means that characters of file name and directory will be readable in any languages. - You can use the arrow icon near the foldername in the treeview to display the content of a directory and its subdirectories (recursively). - You can now tag nodes - You can now filter nodes - The menu of the search panel was entirely rewritten and is much more easy to use now - You can now easily create attribute list and dynamically change column - Video have thumbnail - A blue icon with a blue '+' now appears on top of node which created children (Has a module applied on it). - A new icon which looks like a 'link' now appears on top of nodes which is a VFS link to an other node. You can double-click on it to be redirected to the linked node. - A new root icon called "modules root" gives shortcut to all nodes which have created children. - A new check box system is in place to select files you want to bookmark or do another operations on them. You can also use the right button menu to select/deselect your choices. - The path bar has now a button and an edit mode * batch : Now DFF shell command in batch must be preceeded by : ! , other commands will be interepreted as python code. So you can merge DFF commands and python in a batch script. Comment line starting with # will no longer be printed as you can use the python print function directly. When using it with python think to launch DFF in '-d'debug mode ('-d') to have the output redirected * preview widget : You can now disable preview by clicking the check box on the top of the widget. This can fasten the browsing of files with the keyboard arrow in the node browser as the preview menu doesn't need to update each time a file is selected Modules: -------- * Compound : Parse and extract content of compound documents : MS office document before 2010, MSI, thumbs.db, ... This module also has specific functionallity for MS office document. It can extract metadata for document and sub document streams contained in the archive. It can also extracts pictures embedded in datastream, WordDocument stream (.doc) and Pictures stream (.ppt) * Prefetch : Extract metadata of prefetch file (.pf) * Lnk : Extract metadata of link file (.lnk) * Text: Module has been enhanced to let you choose the encoding of the document you are reading * Video thumbnail viewer : It displays 10 thumbnails of a video (generated each 10%) * Devices : For linux now devices modules can be built to use libudev rather than dbus and HAL * Registry : The registry modules is now based on pyregfi. You can choose to simply execute the module then use the viewer to view the content of gathered hives or you can choose to extract content directly in DFF tree by specfying option * Registry viewer : A regedit like viewer to browse registry content * hash : - The module can now tag nodes by using a hash set (One hash per line) - It can detect hash set base type (md5, sha1, ...) automatically - You can specify a maximum size of file to be hashed - You can specify a cache limit where files will not be cached but results will be obtained dynamically. (To use less memory when there is a very large amount of files to hash) API: ---- * Variant : Variant are now reference counted in C++. You must use variant_p to declare you variant as refcounted * VFS : - A cache template was created and used for fileMapping, vfile, and attribute - A refcount template was added - A tag manager was added to the API, the ability to tag node node.setTag("malware"), search and filter by tags * Search : - You can now search keyword entered in a dictionary (file) - Syntax has been enhanced and supports more keywords - You can dynamically created alias for too long attributes Build: ------ * GIT : The achitecture has changed. Now it's subdivised in several submodules * Launch permission : It's now possible to directly launch DFF as administrator by right-clicking on the desktop link on Windows Bug Fixes : ----------- GUI: ---- * taskmanager : - Time of process not yet started is now set to 0. - When a script or module has finished its execution the state will be set to 'finished' even if it's a graphical module with an opened window Modules: -------- * FATFS : - Conversion of filename to UTF-8, speed optimization - More detailed attributes - Fix for time in usecond which was not set to 0 but was random * NTFS : - Support UTF-8 filename - Close of vfile - Memory leaks - Adds option to not check for deleted and orphan files - Crashes when MFT was not found - Infinite loop on deleted items - Adds timestamps from $FILENAME attributes for each NTFS nodes * FUSE : - Now run in background mode - Use one thread * EWF : Speed improvement * PFF: - Fix bug when parsing attributes of attached item attributes - Set subject as node name * EXTFS: - Add slack's nodes and an option to chose to display them - Fix a bug that prevented file names to be parsed properly - Fix some memory leaks * carver: - Use the new search API - Fix problem with footer size - The start button is now greyed when it's not configured * metaexif : Use the PIL library to extract metadata * extract : - Fix unicode encoding problem that lead to not extract some files - Some forbidden character and filename are now renamed to be able to be created on some file system * timeline : - Fix for nodes with bad time attribute like 0000-00-00 00:00:00 dff-1.3.0+dfsg.1/cmake_modules/000077500000000000000000000000001217176075400161525ustar00rootroot00000000000000dff-1.3.0+dfsg.1/cmake_modules/COPYING-CMAKE-SCRIPTS000066400000000000000000000024571217176075400211600ustar00rootroot00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dff-1.3.0+dfsg.1/cmake_modules/FindAFF.cmake000066400000000000000000000045661217176075400203640ustar00rootroot00000000000000# - Find AFF # This module finds an installed AFF. It sets the following variables: # AFF_FOUND - set to true if AFF is found # AFF_LIBRARY - dynamic libraries for aff # AFF_INCLUDE_DIR - the path to the include files # AFF_VERSION - the version number of the aff library # SET(AFF_FOUND FALSE) FIND_LIBRARY(AFF_LIBRARY afflib) IF (AFF_LIBRARY) FIND_PATH(AFF_INCLUDE_DIR afflib) IF (AFF_INCLUDE_DIR) IF (CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "afflib.lib" "" AFF_DYN_LIB_PATH "${AFF_LIBRARY}") SET(AFF_LIBRARY Ws2_32;${AFF_DYN_LIB_PATH}/afflib.lib;${AFF_DYN_LIB_PATH}/libeay32.lib;${AFF_DYN_LIB_PATH}/ssleay32.lib;${AFF_DYN_LIB_PATH}/zlib.lib) SET(AFF_DYN_LIBRARIES ${AFF_DYN_LIB_PATH}/afflib.dll;${AFF_DYN_LIB_PATH}/zlib.dll) FILE(COPY ${AFF_DYN_LIBRARIES} DESTINATION ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/Debug/) ENDIF (CMAKE_GENERATOR MATCHES "Visual Studio") FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/affversion.c "#include #include int main() { const char* version; version = af_version(); printf(\"%s\", version); return 1; }") IF (UNIX) SET (COMP_DEF "-DHAVE_INTTYPES_H") ENDIF (UNIX) TRY_RUN(AFF_RUN_RESULT AFF_COMP_RESULT ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/affversion.c CMAKE_FLAGS -DINCLUDE_DIRECTORIES:STRING=${AFF_INCLUDE_DIR} "-DLINK_LIBRARIES:STRING=${AFF_LIBRARY}" COMPILE_DEFINITIONS ${COMP_DEF} COMPILE_OUTPUT_VARIABLE COMP_OUTPUT RUN_OUTPUT_VARIABLE RUN_OUTPUT) #message(STATUS ${AFF_COMP_RESULT}) #message(STATUS ${COMP_OUTPUT}) #message(STATUS ${RUN_OUPUT}) #message(STATUS ${AFF_RUN_RESULT}) IF (AFF_COMP_RESULT) IF (AFF_RUN_RESULT) set(AFF_FOUND TRUE) SET(AFF_VERSION ${RUN_OUTPUT}) SET(AFFVERSION ${AFF_VERSION}) STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" AFF_VERSION_MAJOR "${AFFVERSION}") STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+.*" "\\1" AFF_VERSION_MINOR "${AFFVERSION}") STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" AFF_VERSION_PATCH "${AFFVERSION}") ENDIF (AFF_RUN_RESULT) ELSE (AFF_COMP_RESULT) message(STATUS "${COMP_OUTPUT}") ENDIF (AFF_COMP_RESULT) ENDIF (AFF_INCLUDE_DIR) ENDIF (AFF_LIBRARY)dff-1.3.0+dfsg.1/cmake_modules/FindBFIO.cmake000066400000000000000000000041701217176075400204760ustar00rootroot00000000000000# - Find BFIO # This module finds an installed BFIO. It sets the following variables: # BFIO_FOUND - set to true if BFIO is found # BFIO_LIBRARY - dynamic libraries for aff # BFIO_INCLUDE_DIR - the path to the include files # BFIO_VERSION - the version number of the aff library # SET(BFIO_FOUND FALSE) FIND_LIBRARY(BFIO_LIBRARY bfio) IF (BFIO_LIBRARY) FIND_PATH(BFIO_INCLUDE_FILE libbfio.h) IF (BFIO_INCLUDE_FILE) IF (CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "libbfio.lib" "" BFIO_DYN_LIB_PATH "${BFIO_LIBRARY}") STRING(REPLACE "libbfio.h" "" BFIO_INCLUDE_DIR "${BFIO_INCLUDE_FILE}") SET(BFIO_DYN_LIBRARIES ${BFIO_DYN_LIB_PATH}/libbfio.dll) FILE(COPY ${BFIO_DYN_LIBRARIES} DESTINATION ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/Debug/) ENDIF (CMAKE_GENERATOR MATCHES "Visual Studio") FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/bfioversion.c "#ifdef WIN32 #if _MSC_VER >= 1600 #include #else #include #endif #endif #include #include int main() { const char* version; version = libbfio_get_version(); printf(\"%s\", version); return 1; }") IF (UNIX) SET(COMP_BFIO_DEF "-DHAVE_STDINT_H -DHAVE_INTTYPES_H -D_LIBBFIO_TYPES_H_INTEGERS") ENDIF (UNIX) TRY_RUN(BFIO_RUN_RESULT BFIO_COMP_RESULT ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/bfioversion.c CMAKE_FLAGS -DINCLUDE_DIRECTORIES:STRING=${BFIO_INCLUDE_DIR} -DLINK_LIBRARIES:STRING=${BFIO_LIBRARY} COMPILE_DEFINITIONS ${COMP_BFIO_DEF} COMPILE_OUTPUT_VARIABLE COMP_OUTPUT RUN_OUTPUT_VARIABLE RUN_OUTPUT) #message(STATUS ${BFIO_COMP_RESULT}) #message(STATUS ${COMP_OUTPUT}) #message(STATUS ${RUN_OUPUT}) #message(STATUS ${BFIO_RUN_RESULT}) IF (BFIO_COMP_RESULT) IF (BFIO_RUN_RESULT) set(BFIO_FOUND TRUE) SET(BFIO_VERSION ${RUN_OUTPUT}) ENDIF (BFIO_RUN_RESULT) ELSE (BFIO_COMP_RESULT) message(STATUS "${COMP_OUTPUT}") ENDIF (BFIO_COMP_RESULT) ENDIF (BFIO_INCLUDE_FILE) ENDIF (BFIO_LIBRARY)dff-1.3.0+dfsg.1/cmake_modules/FindEWF.cmake000066400000000000000000000043431217176075400204020ustar00rootroot00000000000000# - Find EWF # This module finds an installed EWF. It sets the following variables: # EWF_FOUND - set to true if EWF is found # EWF_LIBRARY - dynamic libraries for aff # EWF_INCLUDE_DIR - the path to the include files # EWF_VERSION - the version number of the aff library # SET(EWF_FOUND FALSE) FIND_LIBRARY(EWF_LIBRARY ewf) IF (EWF_LIBRARY) FIND_FILE(EWF_INCLUDE_FILE libewf.h) IF (EWF_INCLUDE_FILE) IF (CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "libewf.lib" "" EWF_DYN_LIB_PATH "${EWF_LIBRARY}") ENDIF (CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "libewf.h" "" EWF_INCLUDE_DIR "${EWF_INCLUDE_FILE}") #message(STATUS "LIBEWF include path found ${EWF_INCLUDE_DIR}") #message(STATUS "${EWF_DYN_LIB_PATH}") IF (CMAKE_GENERATOR MATCHES "Visual Studio") SET (EWF_DYN_LIBRARIES ${EWF_DYN_LIB_PATH}/libewf.dll;${EWF_DYN_LIB_PATH}/zlib.dll) FILE(COPY ${EWF_DYN_LIBRARIES} DESTINATION ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/Debug/) ENDIF (CMAKE_GENERATOR MATCHES "Visual Studio") #message(STATUS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}") FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/ewfversion.c "#ifdef WIN32 #if _MSC_VER >= 1600 #include #else #include #endif #endif #include #include int main() { const char* version; version = libewf_get_version(); printf(\"%s\", version); return 1; }") IF (UNIX) SET(COMP_EWF_DEF "-DHAVE_STDINT_H -DHAVE_INTTYPES_H -D_LIBEWF_TYPES_H_INTEGERS") ENDIF (UNIX) TRY_RUN(EWF_RUN_RESULT EWF_COMP_RESULT ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/ewfversion.c CMAKE_FLAGS -DINCLUDE_DIRECTORIES:STRING=${EWF_INCLUDE_DIR} -DLINK_LIBRARIES:STRING=${EWF_LIBRARY} COMPILE_DEFINITIONS ${COMP_EWF_DEF} COMPILE_OUTPUT_VARIABLE COMP_OUTPUT RUN_OUTPUT_VARIABLE RUN_OUTPUT) IF (EWF_COMP_RESULT) IF (EWF_RUN_RESULT) SET(EWF_FOUND TRUE) SET(EWF_VERSION ${RUN_OUTPUT}) ENDIF (EWF_RUN_RESULT) ELSE (EWF_COMP_RESULT) message(STATUS "${COMP_OUTPUT}") ENDIF (EWF_COMP_RESULT) ENDIF (EWF_INCLUDE_FILE) ENDIF (EWF_LIBRARY)dff-1.3.0+dfsg.1/cmake_modules/FindFFmpeg.cmake000066400000000000000000000111551217176075400211240ustar00rootroot00000000000000# Locate ffmpeg # This module defines # FFMPEG_LIBRARIES # FFMPEG_FOUND, if false, do not try to link to ffmpeg # FFMPEG_INCLUDE_DIR, where to find the headers # # $FFMPEG_DIR is an environment variable that would # correspond to the ./configure --prefix=$FFMPEG_DIR # # Created by Robert Osfield. #In ffmpeg code, old version use "#include " and newer use "#include " #In OSG ffmpeg plugin, we use "#include " for compatibility with old version of ffmpeg #We have to search the path which contain the header.h (usefull for old version) #and search the path which contain the libname/header.h (usefull for new version) #Then we need to include ${FFMPEG_libname_INCLUDE_DIRS} (in old version case, use by ffmpeg header and osg plugin code) # (in new version case, use by ffmpeg header) #and ${FFMPEG_libname_INCLUDE_DIRS/libname} (in new version case, use by osg plugin code) # Macro to find header and lib directories # example: FFMPEG_FIND(AVFORMAT avformat avformat.h) MACRO(FFMPEG_FIND varname shortname headername) # old version of ffmpeg put header in $prefix/include/[ffmpeg] # so try to find header in include directory FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS ${headername} PATHS ${FFMPEG_ROOT}/include $ENV{FFMPEG_DIR}/include $ENV{OSGDIR}/include $ENV{OSG_ROOT}/include ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include PATH_SUFFIXES ffmpeg DOC "Location of FFMPEG Headers" ) # newer version of ffmpeg put header in $prefix/include/[ffmpeg/]lib${shortname} # so try to find lib${shortname}/header in include directory IF(NOT FFMPEG_${varname}_INCLUDE_DIRS) FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS lib${shortname}/${headername} PATHS ${FFMPEG_ROOT}/include $ENV{FFMPEG_DIR}/include $ENV{OSGDIR}/include $ENV{OSG_ROOT}/include ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include/ /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include PATH_SUFFIXES ffmpeg DOC "Location of FFMPEG Headers" ) ENDIF(NOT FFMPEG_${varname}_INCLUDE_DIRS) FIND_LIBRARY(FFMPEG_${varname}_LIBRARIES NAMES ${shortname} PATHS ${FFMPEG_ROOT}/lib $ENV{FFMPEG_DIR}/lib $ENV{OSGDIR}/lib $ENV{OSG_ROOT}/lib ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 DOC "Location of FFMPEG Libraries" ) IF (FFMPEG_${varname}_LIBRARIES AND FFMPEG_${varname}_INCLUDE_DIRS) SET(FFMPEG_${varname}_FOUND 1) ENDIF(FFMPEG_${varname}_LIBRARIES AND FFMPEG_${varname}_INCLUDE_DIRS) ENDMACRO(FFMPEG_FIND) SET(FFMPEG_ROOT "$ENV{FFMPEG_DIR}" CACHE PATH "Location of FFMPEG") FFMPEG_FIND(LIBAVFORMAT avformat avformat.h) FFMPEG_FIND(LIBAVDEVICE avdevice avdevice.h) FFMPEG_FIND(LIBAVCODEC avcodec avcodec.h) FFMPEG_FIND(LIBAVUTIL avutil avutil.h) FFMPEG_FIND(LIBSWSCALE swscale swscale.h) # not sure about the header to look for here. SET(FFMPEG_FOUND FALSE) # Note we don't check FFMPEG_LIBSWSCALE_FOUND here, it's optional. IF (FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND AND FFMPEG_LIBSWSCALE_FOUND) SET(FFMPEG_FOUND TRUE) SET(FFMPEG_INCLUDE_DIRS ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS}) SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBRARY_DIRS}) # Note we don't add FFMPEG_LIBSWSCALE_LIBRARIES here, it will be added if found later. SET(FFMPEG_LIBRARIES ${FFMPEG_LIBAVFORMAT_LIBRARIES} ${FFMPEG_LIBAVDEVICE_LIBRARIES} ${FFMPEG_LIBAVCODEC_LIBRARIES} ${FFMPEG_LIBAVUTIL_LIBRARIES} ${FFMPEG_LIBSWSCALE_LIBRARIES} ) ELSE (FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND AND FFMPEG_LIBSWSCALE_FOUND) # MESSAGE(STATUS "Could not find FFMPEG") ENDIF(FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND AND FFMPEG_LIBSWSCALE_FOUND) dff-1.3.0+dfsg.1/cmake_modules/FindICU.cmake000066400000000000000000000163261217176075400204050ustar00rootroot00000000000000# This module can find the International Components for Unicode (ICU) Library # # Requirements: # - CMake >= 2.8.3 # # The following variables will be defined for your use: # - ICU_FOUND : were all of your specified components found (include dependencies)? # - ICU_INCLUDE_DIRS : ICU include directory # - ICU_LIBRARIES : ICU libraries # - ICU_VERSION : complete version of ICU (x.y.z) # - ICU_MAJOR_VERSION : major version of ICU # - ICU_MINOR_VERSION : minor version of ICU # - ICU_PATCH_VERSION : patch version of ICU # - ICU__FOUND : were found? (FALSE for non specified component if it is not a dependency) # # Example Usage: # # 1. Copy this file in the root of your project source directory # 2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt: # set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}) # 3. Finally call find_package() once, here are some examples to pick from # # Require ICU 4.4 or later # find_package(ICU 4.4 REQUIRED) # # if(ICU_FOUND) # include_directories(${ICU_INCLUDE_DIRS}) # add_executable(myapp myapp.c) # target_link_libraries(myapp ${ICU_LIBRARIES}) # endif() #============================================================================= # Copyright (c) 2011, julp # # Distributed under the OSI-approved BSD License # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. #============================================================================= find_package(PkgConfig) ########## Private ########## function(icudebug _varname) if(ICU_DEBUG) message("${_varname} = ${${_varname}}") endif(ICU_DEBUG) endfunction(icudebug) set(IcuComponents ) # ... macro(declare_icu_component _NAME) list(APPEND IcuComponents ${_NAME}) set("IcuComponents_${_NAME}" ${ARGN}) endmacro(declare_icu_component) if (WIN32) declare_icu_component(data icudt) declare_icu_component(i18n icuin) # Internationalization library else() declare_icu_component(data icudata) declare_icu_component(i18n icui18n) # Internationalization library endif () declare_icu_component(uc icuuc) # Common and Data libraries declare_icu_component(io icuio) # Stream and I/O Library declare_icu_component(le icule) # Layout library declare_icu_component(lx iculx) # Paragraph Layout library ########## Public ########## set(ICU_FOUND TRUE) set(ICU_LIBRARIES ) set(ICU_DYN_LIBRARIES) set(ICU_INCLUDE_DIRS ) set(ICU_DEFINITIONS ) foreach(_icu_component ${IcuComponents}) string(TOUPPER "${_icu_component}" _icu_upper_component) set("ICU_${_icu_upper_component}_FOUND" FALSE) # may be done in the declare_icu_component macro endforeach(_icu_component) # Check components if(NOT IcuComponents) # uc required at least set(IcuComponents uc) else() list(APPEND IcuComponents uc) list(REMOVE_DUPLICATES IcuComponents) foreach(_icu_component ${IcuComponents}) if(NOT DEFINED "IcuComponents_${_icu_component}") message(FATAL_ERROR "Unknown ICU component: ${_icu_component}") endif() endforeach(_icu_component) endif() # Includes find_path( ICU_INCLUDE_DIRS NAMES unicode/utypes.h HINTS ${ICU_INCLUDE_PATH} DOC "Include directories for ICU" ) # Check dependencies if(PKG_CONFIG_FOUND) set(_components_dup ${IcuComponents}) foreach(_icu_component ${_components_dup}) pkg_check_modules(PC_ICU "icu-${_icu_component}" QUIET) if(PC_ICU_FOUND) foreach(_pc_icu_library ${PC_ICU_LIBRARIES}) string(REGEX REPLACE "^icu" "" _pc_stripped_icu_library ${_pc_icu_library}) list(APPEND IcuComponents ${_pc_stripped_icu_library}) endforeach(_pc_icu_library) endif(PC_ICU_FOUND) endforeach(_icu_component) list(REMOVE_DUPLICATES IcuComponents) endif(PKG_CONFIG_FOUND) # Check libraries foreach(_icu_component ${IcuComponents}) find_library( _icu_lib_${_icu_component} NAMES ${IcuComponents_${_icu_component}} HINTS ${ICU_LIBRARIES_PATH} DOC "Libraries for ICU" ) string(TOUPPER "${_icu_component}" _icu_upper_component) if(_icu_lib STREQUAL _icu_lib-NOTFOUND) set("ICU_${_icu_upper_component}_FOUND" FALSE) set(ICU_FOUND FALSE) else() if (WIN32) file(GLOB dylib "${ICU_DYNLIB_PATH}/${IcuComponents_${_icu_component}}*.dll") list(LENGTH dylib length) if (length GREATER 0) list(GET dylib 0 dylib) list(APPEND ICU_DYN_LIBRARIES ${dylib}) set("ICU_${_icu_upper_component}_FOUND" TRUE) list(APPEND ICU_LIBRARIES ${_icu_lib_${_icu_component}}) else() set("ICU_${_icu_upper_component}_FOUND" FALSE) set(ICU_FOUND FALSE) endif() else() set("ICU_${_icu_upper_component}_FOUND" TRUE) list(APPEND ICU_LIBRARIES ${_icu_lib_${_icu_component}}) endif() endif() endforeach(_icu_component) if(ICU_FOUND) list(REMOVE_DUPLICATES ICU_LIBRARIES) message(STATUS "Found ICU libraries:") foreach (item ${ICU_LIBRARIES}) message(" ${item}") endforeach() if (WIN32) list(REMOVE_DUPLICATES ICU_DYN_LIBRARIES) message(STATUS "Found ICU dynamic libraries:") foreach (item ${ICU_DYN_LIBRARIES}) message(" ${item}") endforeach() endif() if(EXISTS "${ICU_INCLUDE_DIRS}/unicode/uvernum.h") file(READ "${ICU_INCLUDE_DIRS}/unicode/uvernum.h" _icu_contents) endif() string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MAJOR_NUM *([0-9]+).*" "\\1" ICU_MAJOR_VERSION "${_icu_contents}") string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ICU_MINOR_VERSION "${_icu_contents}") string(REGEX REPLACE ".*# *define *U_ICU_VERSION_PATCHLEVEL_NUM *([0-9]+).*" "\\1" ICU_PATCH_VERSION "${_icu_contents}") set(ICU_VERSION "${ICU_MAJOR_VERSION}.${ICU_MINOR_VERSION}.${ICU_PATCH_VERSION}") elseif(ICU_FIND_REQUIRED AND NOT ICU_FIND_QUIETLY) message(FATAL_ERROR "ICU libraries not found or missing. Please specify path to libraries or install them") endif(ICU_FOUND) if(ICU_INCLUDE_DIRS) include(FindPackageHandleStandardArgs) if(ICU_FIND_REQUIRED AND NOT ICU_FIND_QUIETLY) find_package_handle_standard_args(ICU REQUIRED_VARS ICU_LIBRARIES ICU_INCLUDE_DIRS VERSION_VAR ICU_VERSION) else() find_package_handle_standard_args(ICU "ICU not found" ICU_LIBRARIES ICU_INCLUDE_DIRS) endif() else(ICU_INCLUDE_DIRS) if(ICU_FIND_REQUIRED AND NOT ICU_FIND_QUIETLY) message(FATAL_ERROR "Could not find ICU include directory") endif() endif(ICU_INCLUDE_DIRS) mark_as_advanced( ICU_INCLUDE_DIRS ICU_LIBRARIES ICU_DEFINITIONS ICU_VERSION ICU_MAJOR_VERSION ICU_MINOR_VERSION ICU_PATCH_VERSION ) # IN (args) icudebug("IcuComponents") icudebug("ICU_FIND_REQUIRED") icudebug("ICU_FIND_QUIETLY") icudebug("ICU_FIND_VERSION") # OUT # Found icudebug("ICU_FOUND") icudebug("ICU_UC_FOUND") icudebug("ICU_I18N_FOUND") icudebug("ICU_IO_FOUND") icudebug("ICU_LE_FOUND") icudebug("ICU_LX_FOUND") # Linking icudebug("ICU_INCLUDE_DIRS") icudebug("ICU_LIBRARIES") # Version icudebug("ICU_MAJOR_VERSION") icudebug("ICU_MINOR_VERSION") icudebug("ICU_PATCH_VERSION") icudebug("ICU_VERSION")dff-1.3.0+dfsg.1/cmake_modules/FindLibPython.py000066400000000000000000000010131217176075400212300ustar00rootroot00000000000000 # Copyright (c) 2007, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. import sys import distutils.sysconfig print("exec_prefix:%s" % sys.exec_prefix) print("short_version:%s" % sys.version[:3]) print("long_version:%s" % sys.version.split()[0]) print("py_inc_dir:%s" % distutils.sysconfig.get_python_inc()) print("site_packages_dir:%s" % distutils.sysconfig.get_python_lib(plat_specific=1)) dff-1.3.0+dfsg.1/cmake_modules/FindPFF.cmake000066400000000000000000000037011217176075400203710ustar00rootroot00000000000000# - Find PFF # This module finds an installed PFF. It sets the following variables: # PFF_FOUND - set to true if PFF is found # PFF_LIBRARY - dynamic libraries for aff # PFF_INCLUDE_DIR - the path to the include files # PFF_VERSION - the version number of the aff library # SET(PFF_FOUND FALSE) FIND_LIBRARY(PFF_LIBRARY pff) IF (PFF_LIBRARY) FIND_FILE(PFF_INCLUDE_FILE libpff.h) IF (PFF_INCLUDE_FILE) IF (CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "libpff.h" "" PFF_INCLUDE_DIR "${PFF_INCLUDE_FILE}") STRING(REPLACE "libpff.lib" "" PFF_DYN_LIB_PATH "${PFF_LIBRARY}") SET (PFF_DYN_LIBRARIES ${PFF_DYN_LIB_PATH}/libpff.dll) FILE(COPY ${BFIO_DYN_LIBRARIES} ${PFF_DYN_LIBRARIES} DESTINATION ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/Debug/) ENDIF (CMAKE_GENERATOR MATCHES "Visual Studio") FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/pffversion.c "#ifdef WIN32 #if _MSC_VER >= 1600 #include #else #include #endif #endif #include #include int main() { const char* version; version = libpff_get_version(); printf(\"%s\", version); return 1; }") IF (UNIX) SET(COMP_PFF_DEF "-DHAVE_STDINT_H -DHAVE_INTTYPES_H -D_LIBPFF_TYPES_H_INTEGERS") ENDIF (UNIX) TRY_RUN(PFF_RUN_RESULT PFF_COMP_RESULT ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/pffversion.c CMAKE_FLAGS -DINCLUDE_DIRECTORIES:STRING=${PFF_INCLUDE_DIR} -DLINK_LIBRARIES:STRING=${PFF_LIBRARY} COMPILE_DEFINITIONS ${COMP_PFF_DEF} COMPILE_OUTPUT_VARIABLE COMP_OUTPUT RUN_OUTPUT_VARIABLE RUN_OUTPUT) IF (PFF_COMP_RESULT) IF (PFF_RUN_RESULT) SET(PFF_FOUND TRUE) SET(PFF_VERSION ${RUN_OUTPUT}) ENDIF (PFF_RUN_RESULT) ELSE (PFF_COMP_RESULT) message(STATUS "${COMP_OUTPUT}") ENDIF (PFF_COMP_RESULT) ENDIF (PFF_INCLUDE_FILE) ENDIF (PFF_LIBRARY)dff-1.3.0+dfsg.1/cmake_modules/FindPyQt.py000066400000000000000000000013761217176075400202310ustar00rootroot00000000000000# Copyright (c) 2007, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. import PyQt4.pyqtconfig pyqtcfg = PyQt4.pyqtconfig.Configuration() print("pyqt_version:%06.0x" % pyqtcfg.pyqt_version) print("pyqt_version_str:%s" % pyqtcfg.pyqt_version_str) pyqt_version_tag = "" in_t = False for item in pyqtcfg.pyqt_sip_flags.split(' '): if item=="-t": in_t = True elif in_t: if item.startswith("Qt_4"): pyqt_version_tag = item else: in_t = False print("pyqt_version_tag:%s" % pyqt_version_tag) print("pyqt_sip_dir:%s" % pyqtcfg.pyqt_sip_dir) print("pyqt_sip_flags:%s" % pyqtcfg.pyqt_sip_flags) dff-1.3.0+dfsg.1/cmake_modules/FindPyQt4.cmake000066400000000000000000000037001217176075400207360ustar00rootroot00000000000000# Find PyQt4 # ~~~~~~~~~~ # Copyright (c) 2007-2008, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # PyQt4 website: http://www.riverbankcomputing.co.uk/pyqt/index.php # # Find the installed version of PyQt4. FindPyQt4 should only be called after # Python has been found. # # This file defines the following variables: # # PYQT4_VERSION - The version of PyQt4 found expressed as a 6 digit hex number # suitable for comparision as a string # # PYQT4_VERSION_STR - The version of PyQt4 as a human readable string. # # PYQT4_VERSION_TAG - The PyQt version tag using by PyQt's sip files. # # PYQT4_SIP_DIR - The directory holding the PyQt4 .sip files. # # PYQT4_SIP_FLAGS - The SIP flags used to build PyQt. IF(EXISTS PYQT4_VERSION) # Already in cache, be silent SET(PYQT4_FOUND TRUE) ELSE(EXISTS PYQT4_VERSION) FIND_FILE(_find_pyqt_py FindPyQt.py PATHS ${CMAKE_MODULE_PATH}) EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt_py} OUTPUT_VARIABLE pyqt_config) IF(pyqt_config) STRING(REGEX REPLACE "^pyqt_version:([^\n]+).*$" "\\1" PYQT4_VERSION ${pyqt_config}) STRING(REGEX REPLACE ".*\npyqt_version_str:([^\n]+).*$" "\\1" PYQT4_VERSION_STR ${pyqt_config}) STRING(REGEX REPLACE ".*\npyqt_version_tag:([^\n]+).*$" "\\1" PYQT4_VERSION_TAG ${pyqt_config}) STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT4_SIP_DIR ${pyqt_config}) STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT4_SIP_FLAGS ${pyqt_config}) SET(PYQT4_FOUND TRUE) ENDIF(pyqt_config) IF(PYQT4_FOUND) IF(NOT PYQT4_FIND_QUIETLY) MESSAGE(STATUS "Found PyQt4 version: ${PYQT4_VERSION_STR}") ENDIF(NOT PYQT4_FIND_QUIETLY) ELSE(PYQT4_FOUND) IF(PYQT4_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find Python") ENDIF(PYQT4_FIND_REQUIRED) ENDIF(PYQT4_FOUND) ENDIF(EXISTS PYQT4_VERSION) dff-1.3.0+dfsg.1/cmake_modules/FindPythonLibrary.cmake000066400000000000000000000076101217176075400225670ustar00rootroot00000000000000# Find Python # ~~~~~~~~~~~ # Find the Python interpreter and related Python directories. # # This file defines the following variables: # # PYTHON_EXECUTABLE - The path and filename of the Python interpreter. # # PYTHON_SHORT_VERSION - The version of the Python interpreter found, # excluding the patch version number. (e.g. 2.5 and not 2.5.1)) # # PYTHON_LONG_VERSION - The version of the Python interpreter found as a human # readable string. # # PYTHON_SITE_PACKAGES_DIR - Location of the Python site-packages directory. # # PYTHON_INCLUDE_PATH - Directory holding the python.h include file. # # PYTHON_LIBRARY, PYTHON_LIBRARIES- Location of the Python library. # Copyright (c) 2007, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. INCLUDE(CMakeFindFrameworks) if(EXISTS PYTHON_LIBRARY) # Already in cache, be silent set(PYTHONLIBRARY_FOUND TRUE) else(EXISTS PYTHON_LIBRARY) FIND_PACKAGE(PythonInterp) if(PYTHONINTERP_FOUND) FIND_FILE(_find_lib_python_py FindLibPython.py PATHS ${CMAKE_MODULE_PATH}) EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_lib_python_py} OUTPUT_VARIABLE python_config) if(python_config) STRING(REGEX REPLACE ".*exec_prefix:([^\n]+).*$" "\\1" PYTHON_PREFIX ${python_config}) STRING(REGEX REPLACE ".*\nshort_version:([^\n]+).*$" "\\1" PYTHON_SHORT_VERSION ${python_config}) STRING(REGEX REPLACE ".*\nlong_version:([^\n]+).*$" "\\1" PYTHON_LONG_VERSION ${python_config}) STRING(REGEX REPLACE ".*\npy_inc_dir:([^\n]+).*$" "\\1" PYTHON_INCLUDE_PATH ${python_config}) if(NOT PYTHON_SITE_PACKAGES_DIR) if(NOT PYTHON_LIBS_WITH_KDE_LIBS) STRING(REGEX REPLACE ".*\nsite_packages_dir:([^\n]+).*$" "\\1" PYTHON_SITE_PACKAGES_DIR ${python_config}) else(NOT PYTHON_LIBS_WITH_KDE_LIBS) set(PYTHON_SITE_PACKAGES_DIR ${KDE4_LIB_INSTALL_DIR}/python${PYTHON_SHORT_VERSION}/site-packages) endif(NOT PYTHON_LIBS_WITH_KDE_LIBS) endif(NOT PYTHON_SITE_PACKAGES_DIR) STRING(REGEX REPLACE "([0-9]+).([0-9]+)" "\\1\\2" PYTHON_SHORT_VERSION_NO_DOT ${PYTHON_SHORT_VERSION}) set(PYTHON_LIBRARY_NAMES python${PYTHON_SHORT_VERSION} python${PYTHON_SHORT_VERSION_NO_DOT}) if(WIN32) STRING(REPLACE "\\" "/" PYTHON_SITE_PACKAGES_DIR ${PYTHON_SITE_PACKAGES_DIR}) endif(WIN32) FIND_LIBRARY(PYTHON_LIBRARY NAMES ${PYTHON_LIBRARY_NAMES} PATHS ${PYTHON_PREFIX}/lib ${PYTHON_PREFIX}/libs NO_DEFAULT_PATH) set(PYTHONLIBRARY_FOUND TRUE) endif(python_config) # adapted from cmake's builtin FindPythonLibs if(APPLE) CMAKE_FIND_FRAMEWORKS(Python) set(PYTHON_FRAMEWORK_INCLUDES) if(Python_FRAMEWORKS) # If a framework has been selected for the include path, # make sure "-framework" is used to link it. if("${PYTHON_INCLUDE_PATH}" MATCHES "Python\\.framework") set(PYTHON_LIBRARY "") set(PYTHON_DEBUG_LIBRARY "") endif("${PYTHON_INCLUDE_PATH}" MATCHES "Python\\.framework") if(NOT PYTHON_LIBRARY) set (PYTHON_LIBRARY "-framework Python" CACHE FILEPATH "Python Framework" FORCE) endif(NOT PYTHON_LIBRARY) set(PYTHONLIBRARY_FOUND TRUE) endif(Python_FRAMEWORKS) endif(APPLE) endif(PYTHONINTERP_FOUND) if(PYTHONLIBRARY_FOUND) set(PYTHON_LIBRARIES ${PYTHON_LIBRARY}) if(NOT PYTHONLIBRARY_FIND_QUIETLY) message(STATUS "Found Python executable: ${PYTHON_EXECUTABLE}") message(STATUS "Found Python version: ${PYTHON_LONG_VERSION}") message(STATUS "Found Python library: ${PYTHON_LIBRARY}") endif(NOT PYTHONLIBRARY_FIND_QUIETLY) else(PYTHONLIBRARY_FOUND) if(PYTHONLIBRARY_FIND_REQUIRED) message(FATAL_ERROR "Could not find Python") endif(PYTHONLIBRARY_FIND_REQUIRED) endif(PYTHONLIBRARY_FOUND) endif (EXISTS PYTHON_LIBRARY) dff-1.3.0+dfsg.1/cmake_modules/FindSIP.cmake000066400000000000000000000036121217176075400204120ustar00rootroot00000000000000# Find SIP # ~~~~~~~~ # # SIP website: http://www.riverbankcomputing.co.uk/sip/index.php # # Find the installed version of SIP. FindSIP should be called after Python # has been found. # # This file defines the following variables: # # SIP_VERSION - The version of SIP found expressed as a 6 digit hex number # suitable for comparision as a string. # # SIP_VERSION_STR - The version of SIP found as a human readable string. # # SIP_EXECUTABLE - Path and filename of the SIP command line executable. # # SIP_INCLUDE_DIR - Directory holding the SIP C++ header file. # # SIP_DEFAULT_SIP_DIR - Default directory where .sip files should be installed # into. # Copyright (c) 2007, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. IF(SIP_VERSION) # Already in cache, be silent SET(SIP_FOUND TRUE) ELSE(SIP_VERSION) FIND_FILE(_find_sip_py FindSIP.py PATHS ${CMAKE_MODULE_PATH}) EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_sip_py} OUTPUT_VARIABLE sip_config) IF(sip_config) STRING(REGEX REPLACE "^sip_version:([^\n]+).*$" "\\1" SIP_VERSION ${sip_config}) STRING(REGEX REPLACE ".*\nsip_version_str:([^\n]+).*$" "\\1" SIP_VERSION_STR ${sip_config}) STRING(REGEX REPLACE ".*\nsip_bin:([^\n]+).*$" "\\1" SIP_EXECUTABLE ${sip_config}) STRING(REGEX REPLACE ".*\ndefault_sip_dir:([^\n]+).*$" "\\1" SIP_DEFAULT_SIP_DIR ${sip_config}) STRING(REGEX REPLACE ".*\nsip_inc_dir:([^\n]+).*$" "\\1" SIP_INCLUDE_DIR ${sip_config}) SET(SIP_FOUND TRUE) ENDIF(sip_config) IF(SIP_FOUND) IF(NOT SIP_FIND_QUIETLY) MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}") ENDIF(NOT SIP_FIND_QUIETLY) ELSE(SIP_FOUND) IF(SIP_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find SIP") ENDIF(SIP_FIND_REQUIRED) ENDIF(SIP_FOUND) ENDIF(SIP_VERSION) dff-1.3.0+dfsg.1/cmake_modules/FindSIP.py000066400000000000000000000010051217176075400177540ustar00rootroot00000000000000# FindSIP.py # # Copyright (c) 2007, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. import sys import sipconfig sipcfg = sipconfig.Configuration() print("sip_version:%06.0x" % sipcfg.sip_version) print("sip_version_str:%s" % sipcfg.sip_version_str) print("sip_bin:%s" % sipcfg.sip_bin) print("default_sip_dir:%s" % sipcfg.default_sip_dir) print("sip_inc_dir:%s" % sipcfg.sip_inc_dir) dff-1.3.0+dfsg.1/cmake_modules/FindSWIG.cmake000066400000000000000000000047021217176075400205310ustar00rootroot00000000000000# - Find SWIG # This module finds an installed SWIG. It sets the following variables: # SWIG_FOUND - set to true if SWIG is found # SWIG_DIR - the directory where swig is installed # SWIG_EXECUTABLE - the path to the swig executable # SWIG_VERSION - the version number of the swig executable # # All informations are collected from the SWIG_EXECUTABLE so the # version to be found can be changed from the command line by # means of setting SWIG_EXECUTABLE # SET(SWIG_FOUND FALSE) FIND_PROGRAM(SWIG_EXECUTABLE swig) IF(SWIG_EXECUTABLE) EXECUTE_PROCESS(COMMAND ${SWIG_EXECUTABLE} -swiglib OUTPUT_VARIABLE SWIG_swiglib_output ERROR_VARIABLE SWIG_swiglib_error RESULT_VARIABLE SWIG_swiglib_result) IF(SWIG_swiglib_result) IF(SWIG_FIND_REQUIRED) MESSAGE(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}") ELSE(SWIG_FIND_REQUIRED) MESSAGE(STATUS "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}") ENDIF(SWIG_FIND_REQUIRED) ELSE(SWIG_swiglib_result) STRING(REGEX REPLACE "[\n\r]+" ";" SWIG_swiglib_output ${SWIG_swiglib_output}) # force the path to be computed each time in case SWIG_EXECUTABLE has changed. SET(SWIG_DIR SWIG_DIR-NOTFOUND) FIND_PATH(SWIG_DIR swig.swg PATHS ${SWIG_swiglib_output}) IF(SWIG_DIR) SET(SWIG_FOUND 1) SET(SWIG_USE_FILE ${CMAKE_SOURCE_DIR}/cmake_modules/UseSWIG.cmake) EXECUTE_PROCESS(COMMAND ${SWIG_EXECUTABLE} -version OUTPUT_VARIABLE SWIG_version_output ERROR_VARIABLE SWIG_version_output RESULT_VARIABLE SWIG_version_result) IF(SWIG_version_result) MESSAGE(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -version\" failed with output:\n${SWIG_version_output}") ELSE(SWIG_version_result) STRING(REGEX REPLACE ".*SWIG Version[^0-9.]*\([0-9.]+\).*" "\\1" SWIG_version_output "${SWIG_version_output}") SET(SWIG_VERSION ${SWIG_version_output} CACHE STRING "Swig version" FORCE) ENDIF(SWIG_version_result) ENDIF(SWIG_DIR) ENDIF(SWIG_swiglib_result) ENDIF(SWIG_EXECUTABLE) IF(NOT SWIG_FOUND) IF(NOT SWIG_FIND_QUIETLY) IF(SWIG_FIND_REQUIRED) MESSAGE(FATAL_ERROR "SWIG was not found. Please specify Swig executable location") ELSE(SWIG_FIND_REQUIRED) MESSAGE(STATUS "SWIG was not found. Please specify Swig executable location") ENDIF(SWIG_FIND_REQUIRED) ENDIF(NOT SWIG_FIND_QUIETLY) ENDIF(NOT SWIG_FOUND) dff-1.3.0+dfsg.1/cmake_modules/FindTRE.cmake000066400000000000000000000031171217176075400204110ustar00rootroot00000000000000# - Find TRE # This module finds an installed TRE. It sets the following variables: # TRE_FOUND - set to true if TRE is found # TRE_LIBRARY - dynamic libraries for aff # TRE_INCLUDE_DIR - the path to the include files # TRE_VERSION - the version number of the aff library # SET(TRE_FOUND FALSE) FIND_LIBRARY(TRE_LIBRARY tre) IF (TRE_LIBRARY) FIND_PATH(TRE_INCLUDE_PATH tre) IF (TRE_INCLUDE_PATH) IF (CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "tre" "" TRE_INCLUDE_DIR "${TRE_INCLUDE_PATH}") STRING(REPLACE "tre.lib" "" TRE_DYN_LIB_PATH "${TRE_LIBRARY}") SET(TRE_DYN_LIBRARIES ${TRE_DYN_LIB_PATH}/tre.dll) ENDIF (CMAKE_GENERATOR MATCHES "Visual Studio") if(EXISTS "${TRE_INCLUDE_PATH}/tre/tre-config.h") file(READ "${TRE_INCLUDE_PATH}/tre/tre-config.h" _tre_contents) #generally, to match dot you have to escape but cmake complains... so leave the interpreted dot version string(REGEX REPLACE ".*# *define *TRE_VERSION *\"([0-9].[0-9].[0-9])\".*" "\\1" TRE_VERSION "${_tre_contents}") string(REGEX REPLACE ".*# *define *TRE_APPROX *([0-9]+).*" "\\1" TRE_HAVE_APPROX "${_tre_contents}") string(REGEX REPLACE ".*# *define *TRE_WCHAR *([0-9]+).*" "\\1" TRE_HAVE_WCHAR "${_tre_contents}") string(REGEX REPLACE ".*# *define *TRE_MULTIBYTE *([0-9]+).*" "\\1" TRE_HAVE_MULTIBYTE "${_tre_contents}") set(TRE_FOUND TRUE) else(EXISTS "${TRE_INCLUDE_PATH}/tre/tre-config.h") set(TRE_FOUND FALSE) endif(EXISTS "${TRE_INCLUDE_PATH}/tre/tre-config.h") ENDIF (TRE_INCLUDE_PATH) ENDIF (TRE_LIBRARY)dff-1.3.0+dfsg.1/cmake_modules/FindUDEV.cmake000066400000000000000000000007261217176075400205250ustar00rootroot00000000000000# Locate udev # This module defines # UDEV_LIBRARY # UDEV_FOUND, if false, do not try to link to ffmpeg # UDEV_INCLUDE_DIR, where to find the headers # SET(UDEV_FOUND FALSE) IF (NOT UDEV_INCLUDE_DIR) FIND_PATH(UDEV_INCLUDE_DIR NAMES libudev.h) ENDIF (NOT UDEV_INCLUDE_DIR) IF (NOT UDEV_LIBRARY) FIND_LIBRARY(UDEV_LIBRARY NAMES udev) ENDIF (NOT UDEV_LIBRARY) IF (UDEV_INCLUDE_DIR AND UDEV_LIBRARY) SET(UDEV_FOUND TRUE) ENDIF (UDEV_INCLUDE_DIR AND UDEV_LIBRARY) dff-1.3.0+dfsg.1/cmake_modules/PythonCompile.py000066400000000000000000000001621217176075400213150ustar00rootroot00000000000000# By Simon Edwards # This file is in the public domain. import py_compile py_compile.main() dff-1.3.0+dfsg.1/cmake_modules/PythonMacros.cmake000066400000000000000000000043611217176075400216060ustar00rootroot00000000000000# Python macros # ~~~~~~~~~~~~~ # Copyright (c) 2007, Simon Edwards # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # This file defines the following macros: # # PYTHON_INSTALL (SOURCE_FILE DESINATION_DIR) # Install the SOURCE_FILE, which is a Python .py file, into the # destination directory during install. The file will be byte compiled # and both the .py file and .pyc file will be installed. GET_FILENAME_COMPONENT(PYTHON_MACROS_MODULE_PATH ${CMAKE_CURRENT_LIST_FILE} PATH) MACRO(PYTHON_INSTALL SOURCE_FILE DESINATION_DIR) FIND_FILE(_python_compile_py PythonCompile.py PATHS ${CMAKE_MODULE_PATH}) # Install the source file. INSTALL(FILES ${SOURCE_FILE} DESTINATION ${DESINATION_DIR}) # Byte compile and install the .pyc file. GET_FILENAME_COMPONENT(_absfilename ${SOURCE_FILE} ABSOLUTE) GET_FILENAME_COMPONENT(_filename ${SOURCE_FILE} NAME) GET_FILENAME_COMPONENT(_filenamebase ${SOURCE_FILE} NAME_WE) GET_FILENAME_COMPONENT(_basepath ${SOURCE_FILE} PATH) if(WIN32) string(REGEX REPLACE ".:/" "/" _basepath "${_basepath}") endif(WIN32) SET(_bin_py ${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/${_filename}) SET(_bin_pyc ${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/${_filenamebase}.pyc) FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_basepath}) SET(_message "-DMESSAGE=Byte-compiling ${_bin_py}") GET_FILENAME_COMPONENT(_abs_bin_py ${_bin_py} ABSOLUTE) IF(_abs_bin_py STREQUAL ${_absfilename}) # Don't copy the file onto itself. ADD_CUSTOM_COMMAND( TARGET compile_python_files COMMAND ${CMAKE_COMMAND} -E echo ${message} COMMAND ${PYTHON_EXECUTABLE} ${_python_compile_py} ${_bin_py} DEPENDS ${_absfilename} ) ELSE(_abs_bin_py STREQUAL ${_absfilename}) ADD_CUSTOM_COMMAND( TARGET compile_python_files COMMAND ${CMAKE_COMMAND} -E echo ${message} COMMAND ${CMAKE_COMMAND} -E copy ${_absfilename} ${_bin_py} COMMAND ${PYTHON_EXECUTABLE} ${_python_compile_py} ${_bin_py} DEPENDS ${_absfilename} ) ENDIF(_abs_bin_py STREQUAL ${_absfilename}) INSTALL(FILES ${_bin_pyc} DESTINATION ${DESINATION_DIR}) ENDMACRO(PYTHON_INSTALL) dff-1.3.0+dfsg.1/cmake_modules/SIPMacros.cmake000066400000000000000000000116511217176075400207600ustar00rootroot00000000000000# Macros for SIP # ~~~~~~~~~~~~~~ # Copyright (c) 2007, Simon Edwards # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # SIP website: http://www.riverbankcomputing.co.uk/sip/index.php # # This file defines the following macros: # # ADD_SIP_PYTHON_MODULE (MODULE_NAME MODULE_SIP [library1, libaray2, ...]) # Specifies a SIP file to be built into a Python module and installed. # MODULE_NAME is the name of Python module including any path name. (e.g. # os.sys, Foo.bar etc). MODULE_SIP the path and filename of the .sip file # to process and compile. libraryN are libraries that the Python module, # which is typically a shared library, should be linked to. The built # module will also be install into Python's site-packages directory. # # The behaviour of the ADD_SIP_PYTHON_MODULE macro can be controlled by a # number of variables: # # SIP_INCLUDES - List of directories which SIP will scan through when looking # for included .sip files. (Corresponds to the -I option for SIP.) # # SIP_TAGS - List of tags to define when running SIP. (Corresponds to the -t # option for SIP.) # # SIP_CONCAT_PARTS - An integer which defines the number of parts the C++ code # of each module should be split into. Defaults to 8. (Corresponds to the # -j option for SIP.) # # SIP_DISABLE_FEATURES - List of feature names which should be disabled # running SIP. (Corresponds to the -x option for SIP.) # # SIP_EXTRA_OPTIONS - Extra command line options which should be passed on to # SIP. SET(SIP_INCLUDES) SET(SIP_TAGS) SET(SIP_CONCAT_PARTS 8) SET(SIP_DISABLE_FEATURES) SET(SIP_EXTRA_OPTIONS) MACRO(ADD_SIP_PYTHON_MODULE MODULE_NAME MODULE_SIP) SET(EXTRA_LINK_LIBRARIES ${ARGN}) STRING(REPLACE "." "/" _x ${MODULE_NAME}) GET_FILENAME_COMPONENT(_parent_module_path ${_x} PATH) GET_FILENAME_COMPONENT(_child_module_name ${_x} NAME) GET_FILENAME_COMPONENT(_module_path ${MODULE_SIP} PATH) GET_FILENAME_COMPONENT(_abs_module_sip ${MODULE_SIP} ABSOLUTE) # We give this target a long logical target name. # (This is to avoid having the library name clash with any already # install library names. If that happens then cmake dependancy # tracking get confused.) STRING(REPLACE "." "_" _logical_name ${MODULE_NAME}) SET(_logical_name "python_module_${_logical_name}") FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_module_path}) # Output goes in this dir. SET(_sip_includes) FOREACH (_inc ${SIP_INCLUDES}) GET_FILENAME_COMPONENT(_abs_inc ${_inc} ABSOLUTE) LIST(APPEND _sip_includes -I ${_abs_inc}) ENDFOREACH (_inc ) SET(_sip_tags) FOREACH (_tag ${SIP_TAGS}) LIST(APPEND _sip_tags -t ${_tag}) ENDFOREACH (_tag) SET(_sip_x) FOREACH (_x ${SIP_DISABLE_FEATURES}) LIST(APPEND _sip_x -x ${_x}) ENDFOREACH (_x ${SIP_DISABLE_FEATURES}) SET(_message "-DMESSAGE=Generating CPP code for module ${MODULE_NAME}") SET(_sip_output_files) FOREACH(CONCAT_NUM RANGE 0 ${SIP_CONCAT_PARTS} ) IF( ${CONCAT_NUM} LESS ${SIP_CONCAT_PARTS} ) SET(_sip_output_files ${_sip_output_files} ${CMAKE_CURRENT_BINARY_DIR}/${_module_path}/sip${_child_module_name}part${CONCAT_NUM}.cpp ) ENDIF( ${CONCAT_NUM} LESS ${SIP_CONCAT_PARTS} ) ENDFOREACH(CONCAT_NUM RANGE 0 ${SIP_CONCAT_PARTS} ) IF(NOT WIN32) SET(TOUCH_COMMAND touch) ELSE(NOT WIN32) SET(TOUCH_COMMAND echo) # instead of a touch command, give out the name and append to the files # this is basically what the touch command does. FOREACH(filename ${_sip_output_files}) FILE(APPEND filename "") ENDFOREACH(filename ${_sip_output_files}) ENDIF(NOT WIN32) ADD_CUSTOM_COMMAND( OUTPUT ${_sip_output_files} COMMAND ${CMAKE_COMMAND} -E echo ${message} COMMAND ${TOUCH_COMMAND} ${_sip_output_files} COMMAND ${SIP_EXECUTABLE} ${_sip_tags} ${_sip_x} ${SIP_EXTRA_OPTIONS} -j ${SIP_CONCAT_PARTS} -c ${CMAKE_CURRENT_BINARY_DIR}/${_module_path} ${_sip_includes} ${_abs_module_sip} DEPENDS ${_abs_module_sip} ${SIP_EXTRA_FILES_DEPEND} ) # not sure if type MODULE could be uses anywhere, limit to cygwin for now IF (CYGWIN) ADD_LIBRARY(${_logical_name} MODULE ${_sip_output_files} ) ELSE (CYGWIN) ADD_LIBRARY(${_logical_name} SHARED ${_sip_output_files} ) ENDIF (CYGWIN) TARGET_LINK_LIBRARIES(${_logical_name} ${PYTHON_LIBRARY}) TARGET_LINK_LIBRARIES(${_logical_name} ${EXTRA_LINK_LIBRARIES}) SET_TARGET_PROPERTIES(${_logical_name} PROPERTIES PREFIX "" OUTPUT_NAME ${_child_module_name}) IF (WIN32) SET_TARGET_PROPERTIES(${_logical_name} PROPERTIES SUFFIX ".pyd") ENDIF (WIN32) INSTALL(TARGETS ${_logical_name} DESTINATION "${PYTHON_SITE_PACKAGES_DIR}/${_parent_module_path}") ENDMACRO(ADD_SIP_PYTHON_MODULE) dff-1.3.0+dfsg.1/cmake_modules/UseSWIG.cmake000066400000000000000000000215251217176075400204070ustar00rootroot00000000000000# - SWIG module for CMake # Defines the following macros: # SWIG_ADD_MODULE(name language [ files ]) # - Define swig module with given name and specified language # SWIG_LINK_LIBRARIES(name [ libraries ]) # - Link libraries to swig module # All other macros are for internal use only. # To get the actual name of the swig module, # use: ${SWIG_MODULE_name_REAL_NAME}. # Set Source files properties such as CPLUSPLUS and SWIG_FLAGS to specify # special behavior of SWIG. Also global CMAKE_SWIG_FLAGS can be used to add # special flags to all swig calls. # Another special variable is CMAKE_SWIG_OUTDIR, it allows one to specify # where to write all the swig generated module (swig -outdir option) # The name-specific variable SWIG_MODULE__EXTRA_DEPS may be used # to specify extra dependencies for the generated modules. SET(SWIG_CXX_EXTENSION "cxx") SET(SWIG_EXTRA_LIBRARIES "") SET(SWIG_PYTHON_EXTRA_FILE_EXTENSION "py") # # For given swig module initialize variables associated with it # MACRO(SWIG_MODULE_INITIALIZE name language) STRING(TOUPPER "${language}" swig_uppercase_language) STRING(TOLOWER "${language}" swig_lowercase_language) SET(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}") SET(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}") IF("x${SWIG_MODULE_${name}_LANGUAGE}x" MATCHES "^xUNKNOWNx$") MESSAGE(FATAL_ERROR "SWIG Error: Language \"${language}\" not found") ENDIF("x${SWIG_MODULE_${name}_LANGUAGE}x" MATCHES "^xUNKNOWNx$") SET(SWIG_MODULE_${name}_REAL_NAME "${name}") IF("x${SWIG_MODULE_${name}_LANGUAGE}x" MATCHES "^xPYTHONx$") SET(SWIG_MODULE_${name}_REAL_NAME "_${name}") ENDIF("x${SWIG_MODULE_${name}_LANGUAGE}x" MATCHES "^xPYTHONx$") IF("x${SWIG_MODULE_${name}_LANGUAGE}x" MATCHES "^xPERLx$") SET(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow") ENDIF("x${SWIG_MODULE_${name}_LANGUAGE}x" MATCHES "^xPERLx$") ENDMACRO(SWIG_MODULE_INITIALIZE) # # For a given language, input file, and output file, determine extra files that # will be generated. This is internal swig macro. # MACRO(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile) GET_SOURCE_FILE_PROPERTY(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename ${infile} SWIG_MODULE_NAME) IF(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND") GET_FILENAME_COMPONENT(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${infile}" NAME_WE) ENDIF(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND") FOREACH(it ${SWIG_${language}_EXTRA_FILE_EXTENSION}) SET(${outfiles} ${${outfiles}} "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}.${it}") ENDFOREACH(it) ENDMACRO(SWIG_GET_EXTRA_OUTPUT_FILES) # # Take swig (*.i) file and add proper custom commands for it # MACRO(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) SET(swig_full_infile ${infile}) GET_FILENAME_COMPONENT(swig_source_file_path "${infile}" PATH) GET_FILENAME_COMPONENT(swig_source_file_name_we "${infile}" NAME_WE) GET_SOURCE_FILE_PROPERTY(swig_source_file_generated ${infile} GENERATED) GET_SOURCE_FILE_PROPERTY(swig_source_file_cplusplus ${infile} CPLUSPLUS) GET_SOURCE_FILE_PROPERTY(swig_source_file_flags ${infile} SWIG_FLAGS) IF("${swig_source_file_flags}" STREQUAL "NOTFOUND") SET(swig_source_file_flags "") ENDIF("${swig_source_file_flags}" STREQUAL "NOTFOUND") SET(swig_source_file_fullname "${infile}") IF(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_SOURCE_DIR}") STRING(REGEX REPLACE "^${CMAKE_CURRENT_SOURCE_DIR}" "" swig_source_file_relative_path "${swig_source_file_path}") ELSE(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_SOURCE_DIR}") IF(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_BINARY_DIR}") STRING(REGEX REPLACE "^${CMAKE_CURRENT_BINARY_DIR}" "" swig_source_file_relative_path "${swig_source_file_path}") SET(swig_source_file_generated 1) ELSE(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_BINARY_DIR}") SET(swig_source_file_relative_path "${swig_source_file_path}") IF(swig_source_file_generated) SET(swig_source_file_fullname "${CMAKE_CURRENT_BINARY_DIR}/${infile}") ELSE(swig_source_file_generated) SET(swig_source_file_fullname "${CMAKE_CURRENT_SOURCE_DIR}/${infile}") ENDIF(swig_source_file_generated) ENDIF(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_BINARY_DIR}") ENDIF(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_SOURCE_DIR}") SET(swig_generated_file_fullname "${CMAKE_CURRENT_BINARY_DIR}") IF(swig_source_file_relative_path) SET(swig_generated_file_fullname "${swig_generated_file_fullname}/${swig_source_file_relative_path}") ENDIF(swig_source_file_relative_path) # If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir IF(CMAKE_SWIG_OUTDIR) SET(swig_outdir ${CMAKE_SWIG_OUTDIR}) ELSE(CMAKE_SWIG_OUTDIR) SET(swig_outdir ${CMAKE_CURRENT_BINARY_DIR}) ENDIF(CMAKE_SWIG_OUTDIR) SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE} swig_extra_generated_files "${swig_outdir}" "${infile}") # If swig module name contains uppercase letters, macro above will generates # bad extra files, resulting in swig generation at each 'make'. # This Regexp fixes it. STRING(REGEX REPLACE "(.*/).*\\.py" "\\1${name}.py" swig_extra_generated_files ${swig_extra_generated_files}) SET(swig_generated_file_fullname "${swig_generated_file_fullname}/${swig_source_file_name_we}") # add the language into the name of the file (i.e. TCL_wrap) # this allows for the same .i file to be wrapped into different languages SET(swig_generated_file_fullname "${swig_generated_file_fullname}${SWIG_MODULE_${name}_LANGUAGE}_wrap") IF(swig_source_file_cplusplus) SET(swig_generated_file_fullname "${swig_generated_file_fullname}.${SWIG_CXX_EXTENSION}") ELSE(swig_source_file_cplusplus) SET(swig_generated_file_fullname "${swig_generated_file_fullname}.c") ENDIF(swig_source_file_cplusplus) #MESSAGE("Full path to source file: ${swig_source_file_fullname}") #MESSAGE("Full path to the output file: ${swig_generated_file_fullname}") GET_DIRECTORY_PROPERTY(cmake_include_directories INCLUDE_DIRECTORIES) SET(swig_include_dirs) FOREACH(it ${cmake_include_directories}) SET(swig_include_dirs ${swig_include_dirs} "-I${it}") ENDFOREACH(it) SET(swig_special_flags) # default is c, so add c++ flag if it is c++ IF(swig_source_file_cplusplus) SET(swig_special_flags ${swig_special_flags} "-c++") ENDIF(swig_source_file_cplusplus) SET(swig_extra_flags) IF(SWIG_MODULE_${name}_EXTRA_FLAGS) SET(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS}) ENDIF(SWIG_MODULE_${name}_EXTRA_FLAGS) ADD_CUSTOM_COMMAND( OUTPUT "${swig_generated_file_fullname}" ${swig_extra_generated_files} COMMAND "${SWIG_EXECUTABLE}" ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" ${swig_source_file_flags} ${CMAKE_SWIG_FLAGS} -outdir ${swig_outdir} ${swig_special_flags} ${swig_extra_flags} ${swig_include_dirs} -o "${swig_generated_file_fullname}" "${swig_source_file_fullname}" MAIN_DEPENDENCY "${swig_source_file_fullname}" DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS} COMMENT "Swig source") SET_SOURCE_FILES_PROPERTIES("${swig_generated_file_fullname}" ${swig_extra_generated_files} PROPERTIES GENERATED 1) SET(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files}) ENDMACRO(SWIG_ADD_SOURCE_TO_MODULE) # # Create Swig module # MACRO(SWIG_ADD_MODULE name language) SWIG_MODULE_INITIALIZE(${name} ${language}) SET(swig_dot_i_sources) SET(swig_other_sources) FOREACH(it ${ARGN}) IF(${it} MATCHES ".*\\.i$") SET(swig_dot_i_sources ${swig_dot_i_sources} "${it}") ELSE(${it} MATCHES ".*\\.i$") SET(swig_other_sources ${swig_other_sources} "${it}") ENDIF(${it} MATCHES ".*\\.i$") ENDFOREACH(it) SET(swig_generated_sources) FOREACH(it ${swig_dot_i_sources}) SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it}) SET(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}") ENDFOREACH(it) GET_DIRECTORY_PROPERTY(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES) SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}") ADD_LIBRARY(${SWIG_MODULE_${name}_REAL_NAME} SHARED ${swig_generated_sources} ${swig_other_sources}) SET_TARGET_PROPERTIES(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") ENDMACRO(SWIG_ADD_MODULE) # # Like TARGET_LINK_LIBRARIES but for swig modules # MACRO(SWIG_LINK_LIBRARIES name) IF(SWIG_MODULE_${name}_REAL_NAME) TARGET_LINK_LIBRARIES(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN}) ELSE(SWIG_MODULE_${name}_REAL_NAME) MESSAGE(SEND_ERROR "Cannot find Swig library \"${name}\".") ENDIF(SWIG_MODULE_${name}_REAL_NAME) ENDMACRO(SWIG_LINK_LIBRARIES name) dff-1.3.0+dfsg.1/dff-gui.py000077500000000000000000000023671217176075400152500ustar00rootroot00000000000000#!/usr/bin/python -i # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # """@package dff Digital-forensic framework launcher """ import os, sys, getopt from dff.api.manager.manager import ApiManager from dff.ui.gui.gui import GUI from dff.ui.console.console import Console from dff.ui.ui import Usage MODULES_PATHS = ["dff/modules"] def fg(): """Launch shell loop""" ui.launch() if __name__ == "__main__": """You can place some script command here for testing purpose""" argv = Usage(sys.argv[1:]) if argv.batch: console = Console(debug=argv.debug, verbosity=argv.verbosity) console.loadModules(MODULES_PATHS) console.onecmd("batch " + argv.batch, False) ui = GUI(argv.debug, argv.verbosity) ui.launch(MODULES_PATHS) dff-1.3.0+dfsg.1/dff.py000077500000000000000000000025151217176075400144610ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # """@package dff Digital-forensic framework launcher """ import os, sys, getopt from dff.api.manager.manager import ApiManager from dff.ui.gui.gui import GUI from dff.ui.console.console import Console from dff.ui.ui import Usage MODULES_PATHS = ["dff/modules"] def fg(): """Launch shell loop""" ui.launch() if __name__ == "__main__": """You can place some script command here for testing purpose""" argv = Usage(sys.argv[1:]) if argv.graphical == 0 or argv.batch: ui = console = Console(debug=argv.debug, verbosity=argv.verbosity) console.loadModules(MODULES_PATHS) if argv.batch: console.onecmd("batch " + argv.batch, False) if argv.graphical: ui = gui = GUI(argv.debug, argv.verbosity) ui.launch(MODULES_PATHS) dff-1.3.0+dfsg.1/dff/000077500000000000000000000000001217176075400141015ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/CMakeLists.txt000066400000000000000000000013671217176075400166500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob add_subdirectory(api) add_subdirectory(modules) add_subdirectory(ui) if (BUILD_UNSUPPORTED) add_subdirectory(unsupported) endif() install_file(__init__.py) dff-1.3.0+dfsg.1/dff/__init__.py000066400000000000000000000000001217176075400162000ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/000077500000000000000000000000001217176075400146525ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/CMakeLists.txt000066400000000000000000000021161217176075400174120ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file(__init__.py) # compiled add_subdirectory (exceptions) add_subdirectory (events) add_subdirectory (loader) add_subdirectory (module) add_subdirectory (types) add_subdirectory (vfs) add_subdirectory (search) add_subdirectory (filters) add_subdirectory (tree) if (WIN32) add_subdirectory (magic) endif (WIN32) # python only add_subdirectory (taskmanager) add_subdirectory (manager) add_subdirectory (datatype) add_subdirectory (gui) add_subdirectory (devices) add_subdirectory (apswvfs) dff-1.3.0+dfsg.1/dff/api/__init__.py000066400000000000000000000013211217176075400167600ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["loader", "vfs", "events", "scheduler", "magic", "module", "utils", "type", "exceptions", "manager", "gui", "devices", "tree", "datatype", "index", "analysis"] dff-1.3.0+dfsg.1/dff/api/apswvfs/000077500000000000000000000000001217176075400163435ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/apswvfs/CMakeLists.txt000066400000000000000000000012651217176075400211070ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py apswvfs.py ) dff-1.3.0+dfsg.1/dff/api/apswvfs/__init__.py000066400000000000000000000011371217176075400204560ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __version__ = "${API_ENV_VERSION}" __all__ = ["apswvfs"] dff-1.3.0+dfsg.1/dff/api/apswvfs/apswvfs.py000066400000000000000000000047631217176075400204200ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob < sja@arxsys.fr> # from dff.api.vfs.vfs import vfs import apsw class apswVFS(apsw.VFS): def __init__(self, vfsname="dff-vfs", basevfs=""): self.vfsname = vfsname self.basevfs = basevfs self.vfs = vfs() apsw.VFS.__init__(self, self.vfsname, self.basevfs) def xAccess(self, pathname, flags): if pathname[0:2] == "C:": pathname = pathname[2:] pathname = pathname.replace('\\', '/') if pathname.rfind('-wal') != -1: pathname = pathname[0:pathname.rfind('-wal')] if self.vfs.getnode(pathname): return True else: return False def xOpen(self, name, flags): try: if isinstance(name, apsw.URIFilename): name = str(name.filename()) if name[0:2] == "C:": name = name[2:] name = name.replace('\\', '/') except AttributeError: pass if name.rfind('-wal') != -1: name = name[0:name.rfind('-wal')] return apswVFile(self.basevfs, name, flags) class apswVFile(apsw.VFSFile): def __init__(self, inheritfromvfsname, filename, flags): self.vfile = None self.vfs = vfs() self.node = self.vfs.getnode(filename) if self.node: self.vfile = self.node.open() def xCheckReservedLock(self): return False def xRead(self, size, offset): if self.vfile: self.vfile.seek(offset) buff = self.vfile.read(size) return buff else: return "" def xWrite(self): return 0 def xClose(self): if self.vfile: self.vfile.close() def xSectorSize(self): return 512 def xDeviceCharacteristics(self): return 0 def xLock(self, level): pass def xUnlock(self, level): pass def xSync(self, flags): pass def xTruncate(self, newsize): pass def xFileSize(self): if self.vfile: return self.vfile.node().size() else: return 0 def xFileControl(self, op, ptr): return False dff-1.3.0+dfsg.1/dff/api/datatype/000077500000000000000000000000001217176075400164655ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/datatype/CMakeLists.txt000066400000000000000000000016151217176075400212300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # Frederic Baguelin # Solal Jacob if (WIN32) set(link_libraries types) else () set(link_libraries pthread types) endif () dff_cpp_api(datatype SWIG_FILE libdatatype.i CPP_FILES datatype.cpp LINK_LIBRARIES ${link_libraries} EXTRA_FILES __init__.py mimetree.py magichandler.py ) dff-1.3.0+dfsg.1/dff/api/datatype/__init__.py000066400000000000000000000012501217176075400205740ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_DATATYPE_VERSION}" __all__ = ["libdatatype", "magichandler"] dff-1.3.0+dfsg.1/dff/api/datatype/datatype.cpp000066400000000000000000000043411217176075400210060ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "exceptions.hpp" #include "variant.hpp" #include "node.hpp" #include "datatype.hpp" DataTypeManager* DataTypeManager::Get() { static DataTypeManager single; return &single; } DataTypeManager::DataTypeManager() { idCounter = 0; } DataTypeManager::~DataTypeManager() { } bool DataTypeManager::registerHandler(DataTypeHandler* handler) { this->handlers.push_back(handler); return true; } Attributes DataTypeManager::type(Node* node) { std::list::iterator handler; Attributes vars; if (node == NULL) return vars; if (this->nodeTypeId[node].empty()) { for (handler = this->handlers.begin(); handler != this->handlers.end(); handler++) { std::string res = (*handler)->type(node); uint32_t id = uniq[res]; if (id) nodeTypeId[node].push_back(id); else { uniq[res] = ++idCounter; typeIdString[idCounter] = res; typeIdHandler[idCounter] = *handler; nodeTypeId[node].push_back(idCounter); } } } dff::vector< uint32_t > ids = nodeTypeId[node]; unsigned int count = 0; unsigned int size = ids.size(); DataTypeHandler* dthptr; while (count != size) { uint32_t id = ids[count]; if ((dthptr = typeIdHandler[id]) != NULL) vars[dthptr->name] = new Variant(typeIdString[id]); count++; } return vars; } const std::map& DataTypeManager::foundTypes() { return (this->uniq.getInternals()); } DataTypeHandler::DataTypeHandler(std::string hname) { DataTypeManager* dataTypeManager = DataTypeManager::Get(); this->name = hname; dataTypeManager->registerHandler(this); } DataTypeHandler::~DataTypeHandler() { } dff-1.3.0+dfsg.1/dff/api/datatype/libdatatype.i000066400000000000000000000024611217176075400211440ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module(package="dff.api.datatype", directors="1") libdatatype %feature("director") DataTypeHandler; %ignore dff::vector; %ignore dff::map; %ignore dff::Mutex; %ignore dff::ScopedMutex; #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include "std_string.i" %include "std_list.i" %include "std_map.i" %include "windows.i" %feature("ref") RCObj "$this->addref();" %feature("unref") RCObj "$this->delref();" %{ #include "export.hpp" #include "datatype.hpp" %} %include "../include/export.hpp" %include "../include/datatype.hpp" namespace std { %template(ListDataType) list; %template(MapDataType) map; } dff-1.3.0+dfsg.1/dff/api/datatype/magichandler.py000066400000000000000000000046651217176075400214700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # import os, sys if hasattr(sys, "frozen"): from dff.api.magic import magic else: try: import magic except: from dff.api.magic import magic from dff.api.exceptions.libexceptions import vfsError from dff.api.types.libtypes import Variant from dff.api.datatype.libdatatype import DataTypeHandler, DataTypeManager class MagicHandler(DataTypeHandler): def __init__(self, name): DataTypeHandler.__init__(self, name) self.__disown__() self.mgc_path = None if os.name == "nt": if hasattr(sys, "frozen"): self.mgc_path = os.path.abspath(os.path.join(os.path.dirname(sys.executable), "resources/magic.mgc")) else: self.mgc_path = os.path.join(sys.path[0], "dff/api/magic/magic.mgc") def type(self, node): if node.size() > 0: mime = magic.open(self.magic_type()) if self.mgc_path: mime.load(self.mgc_path) else: mime.load() filemime = None try: f = node.open() except : return self.empty(node) try: buff = f.read(0x2000) filemime = mime.buffer(buff) finally: f.close() mime.close() if filemime: return filemime else: return "data" else: return self.empty(node) class Magic(MagicHandler): def __init__(self): MagicHandler.__init__(self, "magic") def magic_type(self): return magic.MAGIC_NONE def empty(self, node): if node.hasChildren(): return "directory" else: return "empty" class MagicMime(MagicHandler): def __init__(self): MagicHandler.__init__(self, "magic mime") def magic_type(self): return magic.MAGIC_MIME def empty(self, node): if node.hasChildren(): return "application/x-directory; charset=binary" else: return "application/x-empty; charset=binary" magicMimeHandler = MagicMime() magicHandler = Magic() dff-1.3.0+dfsg.1/dff/api/datatype/mimetree.py000066400000000000000000000051451217176075400206530ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # import os import sys import struct class MimeTree(): def __init__(self): self.mimetypes = {} if os.name == "nt": self.mgc = sys.path[0] + "./api/magic/magic.mgc" else: self.mgc = "/usr/share/misc/magic.mgc" try: self.mgcfile = open(self.mgc, 'rb') except: self.__err("can't open magic file") buff = self.mgcfile.read() lbuff = len(buff) if lbuff < 8: self.__err("magic file is too short") self.mgcsize = lbuff magicno, = struct.unpack("I", buff[0:4]) bswap = False if magicno != 0xF11E041C: if smagicno != 0xF11E041C: self.__err("bad magic file") else: bswap = True if bswap: version, = struct.unpack(">I", buff[4:8]) else: version, = struct.unpack(" if (UNIX) if (HAVE_UDEV) set(cpp_files device.cpp udevice.cpp) set(swig_flags "-DHAVE_LIBUDEV_H=1") set(definitions "-DHAVE_LIBUDEV_H") set(link_libraries ${UDEV_LIBRARY}) else () set(cpp_files device.cpp) endif() dff_cpp_api(devices SWIG_FILE libdevices.i CPP_FILES ${cpp_files} LINK_LIBRARIES ${link_libraries} DEFINITIONS ${definitions} SWIG_FLAGS ${swig_flags} EXTRA_FILES __init__.py devices.py dbushaldev.py ) else (UNIX) dff_cpp_api(devices SWIG_FILE libdevices.i CPP_FILES device.cpp wmidev.cpp EXTRA_FILES __init__.py devices.py ) endif(UNIX) dff-1.3.0+dfsg.1/dff/api/devices/__init__.py000066400000000000000000000011131217176075400204010ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["devices", "libdevices"] dff-1.3.0+dfsg.1/dff/api/devices/dbushaldev.py000066400000000000000000000067741217176075400210050ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from dff.api.devices.libdevices import Device, DeviceList try : import dbus import gobject except ImportError: pass class DBusHalDevice(Device): def __init__(self, uid, proxy_dev): Device.__init__(self) self.thisown = 0 self.uid = uid self.ddev = proxy_dev setattr(self, "serialNumber", self.serialNumber) def getAllProperties(self): return dev_obj.GetAllProperties() def allProperties(self): buff = self.uid + "\n" for key, val in self.ddev.GetAllProperties().iteritems(): buff += str(key) + " : " + str(val) + "\n" return buff def blockDevice(self): try : return str(self.ddev.GetProperty('block.device')) except dbus.exceptions.DBusException: return Device.blockDevice(self) def serialNumber(self): try: return str(self.ddev.GetProperty('storage.serial')) except dbus.exceptions.DBusException: return Device.serialNumber(self) def model(self): try: return str(self.ddev.GetProperty('storage.model')) except dbus.exceptions.DBusException: Device.model(self) def size(self): if int(self.ddev.GetProperty('storage.removable')) == 1: try: return str(self.ddev.GetProperty('storage.removable.media_size')) except dbus.exceptions.DBusException: return Device.size(self) else: return str(self.ddev.GetProperty('storage.size')) ##def blockMajor(self): #return self.ddev.GetProperty('block.major') #def blockMinor(self): #return self.ddev.GetProperty('block.minor') #def isVolume(self): #return self.ddev.GetProperty('block.is_volume') #def noPartitions(self): #return self.ddev.GetProperty('block.no_partitions') #def haveScanned(self): #return self.ddev.GetProperty('block.have_scanned') def __str__(self): buff = "" buff += "Device uid : " + str(self.uid) + "\n" buff += "Block device : " + str(self.blockDevice()) + "\n" #buff += "Block no partitions :" + str(self.noPartitions()) + "\n" #buff += "Block have scanned :" + str(self.haveScanned()) + "\n" return buff class DBusHalDevices(DeviceList): """This class try to initialize devices list through dbus-HAL""" def __init__(self): DeviceList.__init__(self) self.deviceList = [] self.thisown = 0 system_bus = dbus.SystemBus() bus_name = "org.freedesktop.Hal" object = "/org/freedesktop/Hal/Manager" miface = "org.freedesktop.Hal.Manager" proxy = system_bus.get_object(bus_name, object) iface = dbus.Interface(proxy, miface) devices_uid = iface.FindDeviceByCapability('block') for dev_uid in devices_uid: dev_obj = system_bus.get_object('org.freedesktop.Hal', dev_uid) dev_obj = dbus.Interface(dev_obj, 'org.freedesktop.Hal.Device') if dev_obj.GetProperty('info.category') == "storage": self.deviceList.append(DBusHalDevice(dev_uid, dev_obj)) def __str__(self): buff = "" for dev in self.deviceList: buff += dev.allProperties() buff += "\n" return buff dff-1.3.0+dfsg.1/dff/api/devices/device.cpp000066400000000000000000000016611217176075400202430ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "device.hpp" Device::Device() { } Device::~Device() { } wchar_t* Device::blockDevice(void) { return ((wchar_t*)L"Not available"); } wchar_t* Device::serialNumber(void) { return ((wchar_t*)L"Not available"); } wchar_t* Device::model(void) { return ((wchar_t*)L"Not available"); } uint64_t Device::size(void) { return (0); } DeviceList::DeviceList() { } dff-1.3.0+dfsg.1/dff/api/devices/devices.py000066400000000000000000000022231217176075400202670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import os from dff.api.devices.libdevices import Device, DeviceList DevicesLib = None if os.name == "posix": try : from dff.api.devices.libdevices import UDevices DevicesLib = UDevices except : from dff.api.devices.dbushaldev import DBusHalDevices import dbus DevicesLib = DBusHalDevices else: try : from dff.api.devices.libdevices import WMIDevices DevicesLib = WMIDevices except ImportError: pass class Devices(): def __init__(self): if DevicesLib: self.__instance = DevicesLib() def __getattr__(self, attr): return getattr(self.__instance, attr) dff-1.3.0+dfsg.1/dff/api/devices/libdevices.i000066400000000000000000000040411217176075400205560ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module(package="dff.api.devices") libdevices %feature("director") Device; %feature("director") DeviceList; %include "std_string.i" %include "std_vector.i" %include "windows.i" #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include %apply wchar_t * {WCHAR *} %apply wchar_t const * {WCHAR const *} %apply const wchar_t * {const WCHAR *} %{ #include "../include/export.hpp" #include "../include/device.hpp" #ifdef WIN32 #include "../include/wmidev.hpp" #elif HAVE_LIBUDEV_H #include "../include/udevice.hpp" #endif %} %include "../include/export.hpp" %include "../include/device.hpp" #ifdef WIN32 %include "../include/wmidev.hpp" #elif HAVE_LIBUDEV_H %include "../include/udevice.hpp" #endif namespace std { %template(devList) vector; } #ifdef WIN32 %extend WMIDevices { %pythoncode %{ def __iter__(self): for dev in self.deviceList: yield dev def __len__(self): return len(self.deviceList) def __getitem__(self, c): return self.deviceList[c] %} }; #elif HAVE_LIBUDEV_H %extend UDevices { %pythoncode %{ def __iter__(self): for dev in self.deviceList: yield dev def __len__(self): return len(self.deviceList) def __getitem__(self, c): return self.deviceList[c] %} }; #endif %extend DeviceList { %pythoncode %{ def __iter__(self): for dev in self.deviceList: yield dev def __len__(self): return len(self.deviceList) def __getitem__(self, c): return self.deviceList[c] %} }; dff-1.3.0+dfsg.1/dff/api/devices/udevice.cpp000066400000000000000000000071401217176075400204260ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include #include #include "udevice.hpp" /* This use udev to get devices informations */ UDevice::UDevice() { this->__blockDevice = NULL; this->__serialNumber = NULL; this->__model = NULL; this->__size = 0; } UDevice::~UDevice() { if (this->__blockDevice) delete this->__blockDevice; if (this->__serialNumber) delete this->__serialNumber; if (this->__model) delete this->__model; } UDevice::UDevice(const char* blockDevice, const char* serialNumber, const char* model, uint64_t size) { this->__blockDevice = new wchar_t[strlen(blockDevice) + 1]; mbstowcs(this->__blockDevice, blockDevice, strlen(blockDevice) + 1); this->__serialNumber = new wchar_t[strlen(serialNumber) + 1]; mbstowcs(this->__serialNumber, serialNumber, strlen(serialNumber) + 1); this->__model = new wchar_t[strlen(model) + 1]; mbstowcs(this->__model, model, strlen(model) + 1); this->__size = size; } wchar_t* UDevice::blockDevice(void) { if (this->__blockDevice) return (this->__blockDevice); return ((wchar_t*)L"Not Found"); } wchar_t* UDevice::serialNumber(void) { if (this->__serialNumber) return (this->__serialNumber); return ((wchar_t*)L"Not Found"); } wchar_t* UDevice::model(void) { if (this->__model) return (this->__model); return ((wchar_t*)L"Not Found"); } uint64_t UDevice::size(void) { return this->__size; } UDevices::UDevices(void) { udev* udev; udev_enumerate* enumerate; udev_list_entry* devices; udev_list_entry* dev_list_entry; udev_device* dev; udev = udev_new(); if (udev == NULL) { std::cout << "can't access udev" << std::endl; return ; } enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "block"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(dev_list_entry, devices) { const char* path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); if (std::string(udev_device_get_devtype(dev)) == std::string("disk")) { const char* type = udev_device_get_property_value(dev, "ID_TYPE"); if (type == NULL) continue; else if (std::string(type) == std::string("disk")) { const char* blockDevice = udev_device_get_devnode(dev); const char* serialNumber = udev_device_get_property_value(dev, "ID_SERIAL"); const char* model = udev_device_get_property_value(dev, "ID_MODEL"); const char* size = udev_device_get_sysattr_value(dev, "size"); const char* block_size = udev_device_get_sysattr_value(dev, "queue/physical_block_size"); int bs = 512; uint64_t realSize = 0; if (block_size != NULL) bs = atoi(block_size); realSize = atoll(size) * bs; UDevice* ud = new UDevice(blockDevice, serialNumber, model, realSize); this->deviceList.push_back(ud); } } } udev_enumerate_unref(enumerate); udev_unref(udev); } UDevices::~UDevices() { std::vector::iterator i = this->deviceList.begin(); for (; i != this->deviceList.end(); i++) delete (*i); } dff-1.3.0+dfsg.1/dff/api/devices/wmidev.cpp000066400000000000000000000077051217176075400203040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "wmidev.hpp" /* This use WMI to get devices informations */ WMIDevice::WMIDevice() { } WMIDevice::WMIDevice(IWbemClassObject *pcls) { this->pclsObj = pcls; } WMIDevice::~WMIDevice() { this->pclsObj->Release(); } wchar_t* WMIDevice::blockDevice(void) { HRESULT hr; _variant_t vtProp; hr = this->pclsObj->Get(L"Name", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { wchar_t* var = (wchar_t*)vtProp.pbstrVal; return (var); } return (L"Not Found"); } wchar_t* WMIDevice::serialNumber(void) { HRESULT hr; VARIANT vtProp; hr = this->pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0); wchar_t* var = (wchar_t*)vtProp.pbstrVal; VariantClear(&vtProp); return (var); } wchar_t* WMIDevice::model(void) { HRESULT hr; VARIANT vtProp; hr = this->pclsObj->Get(L"Model", 0, &vtProp, 0, 0); wchar_t* var = (wchar_t*)vtProp.pbstrVal; VariantClear(&vtProp); return (var); } uint64_t WMIDevice::size(void) { HRESULT hr; VARIANT vtProp; hr = this->pclsObj->Get(L"Name", 0, &vtProp, NULL, NULL); if (SUCCEEDED(hr)) { wchar_t* var = (wchar_t*)vtProp.pbstrVal; HANDLE hnd = CreateFileW(var , GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hnd == INVALID_HANDLE_VALUE) return (0); else { GET_LENGTH_INFORMATION diskSize; DWORD lpBytesReturned = 0; DeviceIoControl(hnd, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &lpBytesReturned, NULL); if (DeviceIoControl(hnd, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &diskSize, sizeof(diskSize), &lpBytesReturned,0)) { CloseHandle(hnd); return ((uint64_t)diskSize.Length.QuadPart); } CloseHandle(hnd); } } return (0); } WMIDevices::WMIDevices(void) { HRESULT hres; this->pLoc = NULL; this->pSvc = NULL; hres = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hres)) { return; } hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); if (FAILED(hres) && !(hres == RPC_E_TOO_LATE)) { return; } hres = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &(this->pLoc)); if (FAILED(hres)) return ; hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL , NULL, 0, NULL, 0, 0, &(this->pSvc)); if (FAILED(hres)) return; hres = CoSetProxyBlanket(this->pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); if (FAILED(hres)) return; IEnumWbemClassObject* pEnumerator = NULL; hres = this->pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_DiskDrive"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,&pEnumerator); if (FAILED(hres)) return; IWbemClassObject *pclsObj; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (!uReturn) break; WMIDevice* dev = new WMIDevice(pclsObj); this->deviceList.push_back(dev); } pEnumerator->Release(); } WMIDevices::~WMIDevices() { std::vector::iterator i = deviceList.begin(); for (; i != deviceList.end(); i++) delete (*i); if (this->pSvc) this->pSvc->Release(); if (this->pLoc) this->pLoc->Release(); } dff-1.3.0+dfsg.1/dff/api/events/000077500000000000000000000000001217176075400161565ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/events/CMakeLists.txt000066400000000000000000000013371217176075400207220ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob dff_cpp_api(events SWIG_FILE libevents.i CPP_FILES eventhandler.cpp LINK_LIBRARIES types exceptions EXTRA_FILES __init__.py ) dff-1.3.0+dfsg.1/dff/api/events/__init__.py000066400000000000000000000011511217176075400202650ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __version__ = "${API_EVENT_VERSION}" __all__ = ["libevents"] dff-1.3.0+dfsg.1/dff/api/events/eventhandler.cpp000066400000000000000000000027041217176075400213440ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "eventhandler.hpp" EventHandler::EventHandler() { } bool EventHandler::connection(class EventHandler *obs) { std::vector::iterator it; for (it = this->watchers.begin(); it != this->watchers.end(); it++) if (*it == obs) { return false; } this->watchers.push_back(obs); return true; } bool EventHandler::deconnection(class EventHandler *obs) { std::vector::iterator it; for (it = this->watchers.begin(); it != this->watchers.end(), *it != obs; it++) ; if (it != this->watchers.end()) { this->watchers.erase(it); return true; } else return false; } bool EventHandler::notify(event *e) { std::vector::iterator it; for (it = this->watchers.begin(); it != this->watchers.end(); it++) (*it)->Event(e); return true; } dff-1.3.0+dfsg.1/dff/api/events/libevents.i000066400000000000000000000024371217176075400203310ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "pyrun.swg" %module(package="dff.api.events",docstring="libevents: c++ generated inteface", directors="1") libevents %feature("autodoc", 1); %feature("docstring"); %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "std_except.i" #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include "windows.i" %feature("director") EventHandler; %feature("director:except") EventHandler { if ($error != NULL) { throw Swig::DirectorMethodException(); } } %import "../exceptions/libexceptions.i" %{ #include "exceptions.hpp" #include "variant.hpp" #include "eventhandler.hpp" %} %include "../include/eventhandler.hpp" dff-1.3.0+dfsg.1/dff/api/exceptions/000077500000000000000000000000001217176075400170335ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/exceptions/CMakeLists.txt000066400000000000000000000024201217176075400215710ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob dff_cpp_api(exceptions CPP_FILES exceptions.cpp SWIG_FILE libexceptions.i EXTRA_FILES __init__.py ) if (UNIX) add_custom_target(patchexceptions ALL DEPENDS ${SWIG_MODULE_libexceptions_REAL_NAME} COMMENT "Patching libexceptions.py" COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/patch.py ${CMAKE_CURRENT_BINARY_DIR}/libexceptions.py ) elseif(UNIX) add_custom_target(patchexceptions ALL DEPENDS ${SWIG_MODULE_libexceptions_REAL_NAME} COMMENT "Patching libexceptions.py" COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/patch.py ${CMAKE_CURRENT_BINARY_DIR}/libexceptions.py ) endif(UNIX) add_dependencies("dff.api.exceptions" patchexceptions)dff-1.3.0+dfsg.1/dff/api/exceptions/__init__.py000066400000000000000000000012341217176075400211440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_EXCEPTIONS_VERSION}" __all__ = ["libexceptions"] dff-1.3.0+dfsg.1/dff/api/exceptions/exceptions.cpp000066400000000000000000000013071217176075400217210ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "exceptions.hpp" envError::envError(std::string emsg) { error = emsg; } vfsError::vfsError(std::string emsg) { error = emsg; } dff-1.3.0+dfsg.1/dff/api/exceptions/libexceptions.i000066400000000000000000000065741217176075400220710ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module(package="dff.api.exceptions", directors="1") libexceptions %{ #include "exceptions.hpp" %} %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "std_except.i" #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include "windows.i" /* %exception start */ /* { */ /* try */ /* { */ /* // SWIG_PYTHON_THREAD_BEGIN_ALLOW; */ /* $action */ /* // SWIG_PYTHON_THREAD_END_ALLOW; */ /* } */ /* catch (vfsError &e) */ /* { */ /* SWIG_exception(SWIG_IOError, e.error.c_str()); */ /* } */ /* catch (envError &e) */ /* { */ /* SWIG_PYTHON_THREAD_BEGIN_BLOCK; */ /* PyErr_SetString(PyExc_KeyError, e.error.c_str()); */ /* SWIG_PYTHON_THREAD_END_BLOCK; */ /* return NULL; */ /* } */ /* catch (std::string e) */ /* { */ /* SWIG_exception(SWIG_RuntimeError, e.c_str()); */ /* } */ /* catch (char const* cstr) */ /* { */ /* SWIG_exception(SWIG_RuntimeError, cstr); */ /* } */ /* catch (Swig::DirectorException e) */ /* { */ /* SWIG_PYTHON_THREAD_BEGIN_BLOCK; */ /* SWIG_fail; */ /* SWIG_PYTHON_THREAD_END_BLOCK; */ /* } */ /* } */ /* %exception notify */ /* { */ /* try */ /* { */ /* $action */ /* } */ /* catch (vfsError &e) */ /* { */ /* SWIG_exception(SWIG_IOError, e.error.c_str()); */ /* } */ /* catch (envError &e) */ /* { */ /* SWIG_PYTHON_THREAD_BEGIN_BLOCK; */ /* PyErr_SetString(PyExc_KeyError, e.error.c_str()); */ /* SWIG_PYTHON_THREAD_END_BLOCK; */ /* return NULL; */ /* } */ /* catch (std::string e) */ /* { */ /* SWIG_exception(SWIG_RuntimeError, e.c_str()); */ /* } */ /* catch (char const* cstr) */ /* { */ /* SWIG_exception(SWIG_RuntimeError, cstr); */ /* } */ /* catch (Swig::DirectorException e) */ /* { */ /* SWIG_PYTHON_THREAD_BEGIN_BLOCK; */ /* SWIG_fail; */ /* SWIG_PYTHON_THREAD_END_BLOCK; */ /* } */ /* } */ %exception { try { $action; } catch (vfsError &e) { SWIG_exception(SWIG_IOError, e.error.c_str()); } catch (envError &e) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_KeyError, e.error.c_str()); SWIG_PYTHON_THREAD_END_BLOCK; return NULL; } catch (std::string e) { SWIG_exception(SWIG_RuntimeError, e.c_str()); } catch (char const* cstr) { SWIG_exception(SWIG_RuntimeError, cstr); } catch (Swig::DirectorException e) { SWIG_exception(SWIG_RuntimeError, "Unknown Exception"); } } %feature("director:except") { if ($error != NULL) { throw vfsError("Exception caught"); } } %include "../include/export.hpp" %include "../include/exceptions.hpp" dff-1.3.0+dfsg.1/dff/api/exceptions/patch.py000066400000000000000000000020601217176075400205020ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # import os, sys if __name__ == "__main__": if len(sys.argv) == 2: file = open(sys.argv[1], 'r') fbuff = file.read() if fbuff.find("import exceptions") == -1: buff = "import exceptions\n" buff += fbuff else: buff = fbuff file.close() buff = buff.replace('Error(_object)', 'Error(exceptions.Exception)') buff = buff.replace('Error(object)', 'Error(exceptions.Exception)') file = open(sys.argv[1], 'w') file.write(buff) file.close() dff-1.3.0+dfsg.1/dff/api/filters/000077500000000000000000000000001217176075400163225ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/filters/CMakeLists.txt000066400000000000000000000047271217176075400210740ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin #INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) #INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) #INCLUDE_DIRECTORIES(../include) # you can use -DAPI_FILTER_DEV to call flex and bison for each make if (API_FILTER_DEV) find_package(BISON REQUIRED) BISON_TARGET(parser parser.y ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp) find_package(FLEX REQUIRED) FLEX_TARGET(scanner scanner.l ${CMAKE_CURRENT_SOURCE_DIR}/scanner.cpp) else (API_FILTER_DEV) if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp ) message(STATUS "bison files NOT generated, Bison executable is required") find_package(BISON REQUIRED) BISON_TARGET(parser parser.y ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp) else ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp ) set(BISON_parser_OUTPUTS ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp) message(STATUS "BISON files already generated and setted to ${CMAKE_CURRENT_SOURCE_DIR}/parser.c") endif ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp ) if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/scanner.cpp ) message(STATUS "flex files NOT generated, Flex executable is required") find_package(FLEX REQUIRED) FLEX_TARGET(scanner scanner.l ${CMAKE_CURRENT_SOURCE_DIR}/scanner.cpp) else (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/scanner.cpp ) message(STATUS "FLEX files already generated and setted to ${CMAKE_CURRENT_SOURCE_DIR}/scanner.c") set(FLEX_scanner_OUTPUTS ${CMAKE_CURRENT_SOURCE_DIR}/scanner.cpp) endif ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/scanner.cpp ) endif (API_FILTER_DEV) message(STATUS ${FLEX_scanner_OUTPUTS} ${BISON_parser_OUTPUTS}) # does not seem to be mandatory. Here just in case and as a reminder... #ADD_FLEX_BISON_DEPENDENCY(scanner parser) dff_cpp_api(filters SWIG_FILE libfilters.i CPP_FILES factory.cpp dictionnary.cpp filter.cpp astnodes.cpp ${BISON_parser_OUTPUTS} ${FLEX_scanner_OUTPUTS} LINK_LIBRARIES events vfs types search EXTRA_FILES __init__.py ) dff-1.3.0+dfsg.1/dff/api/filters/__init__.py000066400000000000000000000000001217176075400204210ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/filters/astnodes.cpp000066400000000000000000000626531217176075400206620ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include #include "vfile.hpp" #include "fso.hpp" #include "tags.hpp" #include "astnodes.hpp" #include "parser.hpp" static int __namedcreator__ = AttributeFactory::instance()->registerCreator(AttributeFactory::Named, NamedAttribute::create); static int __timestampcreator__ = AttributeFactory::instance()->registerCreator(AttributeFactory::Timestamp, TimestampAttribute::create); KEYWORD(time, time, AttributeFactory::Timestamp, QueryFlags::Advanced) KEYWORD(year, year, AttributeFactory::Timestamp, QueryFlags::Advanced) KEYWORD(magic, type.magic, AttributeFactory::Named, QueryFlags::DataType) KEYWORD(mime, type.magic mime, AttributeFactory::Named, QueryFlags::DataType) KEYWORD(size, filesize, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(deleted, deleted, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(folder, folder, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(file, file, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(extension, extension, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(name, filename, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(path, path, AttributeFactory::Named, QueryFlags::Primitive) KEYWORD(tags, tags, AttributeFactory::Named, QueryFlags::Tags) KEYWORD(tagged, tagged, AttributeFactory::Named, QueryFlags::Tags) KEYWORD(to, pff.Transport headers.To, AttributeFactory::Named, QueryFlags::Advanced) KEYWORD(from, pff.Transport headers.From, AttributeFactory::Named, QueryFlags::Advanced) InterpreterContext::InterpreterContext() { this->__cnode = NULL; this->__data = NULL; this->__qflags = QueryFlags::Empty; } InterpreterContext::~InterpreterContext() { Attributes::iterator it; if (this->__data != NULL) { this->__data->close(); delete this->__data; } if (!this->__attributes.empty()) this->__attributes.clear(); } void InterpreterContext::clear() { if (this->__data != NULL) { this->__data->close(); delete this->__data; this->__data = NULL; } if (!this->__attributes.empty()) this->__attributes.clear(); this->__cnode = NULL; this->__qflags = QueryFlags::Empty; } void InterpreterContext::setQueryFlags(QueryFlags::Level qflags) { this->__qflags |= qflags; } void InterpreterContext::setCurrentNode(Node* node) { Attributes::iterator it; Variant* vptr; Attributes attr; fso* fsobj; if (!this->__attributes.empty()) this->__attributes.clear(); if (this->__data != NULL) { this->__data->close(); delete this->__data; this->__data = NULL; } if (node != NULL) { this->__cnode = node; if ((this->__qflags & QueryFlags::Primitive) == QueryFlags::Primitive) { this->__attributes["path"] = new Variant(node->path()); this->__attributes["filename"] = new Variant(node->name()); this->__attributes["extension"] = new Variant(node->extension()); this->__attributes["filesize"] = new Variant(node->size()); this->__attributes["deleted"] = new Variant(node->isDeleted()); this->__attributes["folder"] = new Variant(node->hasChildren() && (node->size() == 0)); this->__attributes["file"] = new Variant((node->size() > 0)); } if ((this->__qflags & QueryFlags::DataType) == QueryFlags::DataType) { attr = this->__cnode->dataType(); this->__attributes["type"] = new Variant(attr); } if ((this->__qflags & QueryFlags::Advanced) == QueryFlags::Advanced) { if ((fsobj = this->__cnode->fsobj()) != NULL) { try { attr = this->__cnode->fsoAttributes(); } catch (...) { std::cout << "astnodes InterpreterContext::setCurrentNode can't get node->fsoAttributes()" << std::endl; } if (!attr.empty()) { if ((vptr = new Variant(attr)) != NULL) this->__attributes.insert(std::pair(fsobj->name, vptr)); } } try { attr = this->__cnode->dynamicAttributes(); } catch (...) { std::cout << "astnodes InterpreterContext::setCurrentNode can't get node->dynamicAttributes()" << std::endl; } if (!attr.empty()) this->__attributes.insert(attr.begin(), attr.end()); } if ((this->__qflags & QueryFlags::Tags) == QueryFlags::Tags) { std::vector< Tag_p > tags; VLIST vtags; size_t i; tags = node->tags(); if (tags.size() > 0) this->__attributes["tagged"] = new Variant(true); else this->__attributes["tagged"] = new Variant(false); for (i = 0; i != tags.size(); ++i) vtags.push_back(new Variant(tags[i]->name())); this->__attributes["tags"] = new Variant(vtags); } } } void InterpreterContext::__lookupByName(Variant_p rcvar, std::string name, std::list< Variant_p >* result) { if (rcvar->type() == typeId::List) { std::list< Variant_p > lvariant = rcvar->value >(); std::list< Variant_p >::iterator it; for (it = lvariant.begin(); it != lvariant.end(); it++) this->__lookupByName((*it), name, result); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value< Attributes >(); Attributes::iterator it; for (it = mvariant.begin(); it != mvariant.end(); it++) { if (it->first == name) result->push_back(it->second); else this->__lookupByName(it->second, name, result); } } } void InterpreterContext::__lookupByAbsoluteName(Variant_p rcvar, std::string name, std::list< Variant_p >* result) { std::string subname; std::string subabs; size_t idx; idx = name.find("."); if (idx != std::string::npos) { subname = name.substr(0, idx); subabs = name.substr(idx+1, name.size()); } else { subname = name; subabs = ""; } if ((rcvar->type() == typeId::List) && (!subabs.empty())) { std::list< Variant_p > lvariant = rcvar->value >(); std::list< Variant_p >::iterator it; for (it = lvariant.begin(); it != lvariant.end(); it++) if ((*it)->type() == typeId::Map) this->__lookupByAbsoluteName((*it), subabs, result); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value< Attributes >(); Attributes::iterator it; if (subname == "*") { for (it = mvariant.begin(); it != mvariant.end(); ++it) { if (!subabs.empty()) this->__lookupByAbsoluteName(it->second, subabs, result); else result->push_back(it->second); } } else { it = mvariant.find(subname); if (it != mvariant.end()) { if (!subabs.empty()) this->__lookupByAbsoluteName(it->second, subabs, result); else result->push_back(it->second); } } } } std::list< Variant_p > InterpreterContext::lookupByName(std::string name, attributeNameType tname) { Attributes::iterator attrit; std::list< Variant_p > result; if (tname == ABSOLUTE_ATTR_NAME) { std::string subname; std::string subabs; size_t idx; idx = name.find("."); if (idx != std::string::npos) { subname = name.substr(0, idx); subabs = name.substr(idx+1, name.size()); if ((attrit = this->__attributes.find(subname)) != this->__attributes.end()) this->__lookupByAbsoluteName(attrit->second, subabs, &result); } else if ((attrit = this->__attributes.find(name)) != this->__attributes.end()) result.push_back(attrit->second); } else { for (attrit = this->__attributes.begin(); attrit != this->__attributes.end(); attrit++) { if (attrit->first == name) result.push_back(attrit->second); this->__lookupByName(attrit->second, name, &result); } } return result; } void InterpreterContext::__lookupByType(Variant_p rcvar, uint8_t type, std::list< Variant_p >* result) { if (rcvar->type() == typeId::List) { std::list lvariant = rcvar->value >(); std::list::iterator it = lvariant.begin(); for (; it != lvariant.end(); it++) this->__lookupByType((*it), type, result); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value(); Attributes::iterator it = mvariant.begin(); for (; it != mvariant.end(); it++) { if (it->second->type() == type) result->push_back(it->second); else this->__lookupByType(it->second, type, result); } } } std::list< Variant_p > InterpreterContext::lookupByType(uint8_t type) { std::list< Variant_p > result; Attributes::iterator attrit; for (attrit = this->__attributes.begin(); attrit != this->__attributes.end(); attrit++) { if (attrit->second->type() == type) result.push_back(attrit->second); this->__lookupByType(attrit->second, type, &result); } return result; } VFile* InterpreterContext::data() { if (this->__data == NULL) { try { this->__data = this->__cnode->open(); } catch (vfsError err) { this->__data = NULL; } } return this->__data; } LogicalAnd::LogicalAnd(Expression* lhs, Expression* rhs) throw (std::string) { this->__lhs = NULL; this->__rhs = NULL; if (lhs != NULL && rhs != NULL) { this->__lhs = lhs; this->__rhs = rhs; this->connection(this->__lhs); this->connection(this->__rhs); } else throw std::string("And expression, right or left expression cannot be NULL"); } LogicalAnd::~LogicalAnd() { if (this->__lhs != NULL && this->__rhs != NULL) { this->deconnection(this->__lhs); this->deconnection(this->__rhs); delete this->__lhs; delete this->__rhs; } } bool LogicalAnd::compile(InterpreterContext* ic) { this->_ic = ic; return (this->__lhs->compile(ic) && this->__rhs->compile(ic)); } Variant* LogicalAnd::evaluate() { Variant* vlhs; Variant* vrhs; bool ret; ret = false; vlhs = NULL; vrhs = NULL; if (((vlhs = this->__lhs->evaluate()) != NULL) && (vlhs->type() == typeId::Bool)) { ret = vlhs->value(); if (ret && ((vrhs = this->__rhs->evaluate()) != NULL) && (vrhs->type() == typeId::Bool)) ret = vrhs->value(); else ret = false; } if (vlhs != NULL) delete vlhs; if (vrhs != NULL) delete vrhs; return new Variant(ret); } LogicalOr::LogicalOr(Expression* lhs, Expression* rhs) throw (std::string) { this->__lhs = NULL; this->__rhs = NULL; if (lhs != NULL && rhs != NULL) { this->__lhs = lhs; this->__rhs = rhs; this->connection(this->__lhs); this->connection(this->__rhs); } else throw std::string("Or expression, right or left expression cannot be NULL"); } LogicalOr::~LogicalOr() { if (this->__lhs != NULL && this->__rhs != NULL) { this->deconnection(this->__lhs); this->deconnection(this->__rhs); delete this->__lhs; delete this->__rhs; } } bool LogicalOr::compile(InterpreterContext* ic) { this->_ic = ic; return (this->__lhs->compile(ic) && this->__rhs->compile(ic)); } Variant* LogicalOr::evaluate() { Variant* vlhs; Variant* vrhs; bool ret; ret = false; vlhs = NULL; vrhs = NULL; if (((vlhs = this->__lhs->evaluate()) != NULL) && (vlhs->type() == typeId::Bool)) { ret = vlhs->value(); if (!ret && ((vrhs = this->__rhs->evaluate()) != NULL) && (vrhs->type() == typeId::Bool)) ret = vrhs->value(); } if (vlhs != NULL) delete vlhs; if (vrhs != NULL) delete vrhs; return new Variant(ret); } ComparisonExpression::ComparisonExpression(Expression* lhs, Expression* rhs, int op) throw (std::string) { this->__lhs = NULL; this->__rhs = NULL; if (lhs != NULL && rhs != NULL) { this->__lhs = lhs; this->__rhs = rhs; this->connection(this->__lhs); this->connection(this->__rhs); switch (op) { case GT: __cmp = &ComparisonExpression::__gt; break; case GTE: __cmp = &ComparisonExpression::__gte; break; case LT: __cmp = &ComparisonExpression::__lt; break; case LTE: __cmp = &ComparisonExpression::__lte; break; case EQ: __cmp = &ComparisonExpression::__eq; break; case NEQ: __cmp = &ComparisonExpression::__lt; break; default: __cmp = NULL; break; } } else throw ("Comparison expression, left or right expression cannot be NULL"); } ComparisonExpression::~ComparisonExpression() { if (this->__lhs != NULL && this->__rhs != NULL) { this->deconnection(this->__lhs); this->deconnection(this->__rhs); delete this->__lhs; delete this->__rhs; } } bool ComparisonExpression::compile(InterpreterContext* ic) { this->_ic = ic; return (this->__lhs->compile(ic) && this->__rhs->compile(ic)); } Variant* ComparisonExpression::evaluate() { bool ret; Variant* vlhs; Variant* vrhs; vlhs = this->__lhs->evaluate(); vrhs = this->__rhs->evaluate(); ret = false; if (vlhs && vrhs) { if (vlhs->type() == typeId::List && vrhs->type() == typeId::List) { VLIST lhs = vlhs->value< VLIST >(); VLIST rhs = vrhs->value< VLIST >(); VLIST::iterator lit = lhs.begin(); VLIST::iterator rit = rhs.begin(); while (lit != lhs.end() && !ret && !this->_stop) { while (rit != rhs.end() && !ret && !this->_stop) { ret = (this->*(__cmp))(*lit, *rit); rit++; } lit++; } } else if (vlhs->type() == typeId::List && vrhs->type() != typeId::List) { VLIST lhs = vlhs->value< VLIST >(); VLIST::iterator lit = lhs.begin(); while (lit != lhs.end() && !ret && !this->_stop) { ret = (this->*(__cmp))(*lit, vrhs); lit++; } } else if (vrhs->type() == typeId::List && vlhs->type() != typeId::List) { VLIST rhs = vrhs->value< VLIST >(); VLIST::iterator rit = rhs.begin(); while (rit != rhs.end() && !ret && !this->_stop) { ret = (this->*(__cmp))(vlhs, *rit); rit++; } } else ret = (this->*(__cmp))(vlhs, vrhs); } return new Variant(ret); } LogicalNot::LogicalNot(Expression* expr) throw (std::string) { this->__expr = NULL; if (expr != NULL) { this->__expr = expr; this->connection(this->__expr); } else throw std::string("Not expression cannot be NULL"); } LogicalNot::~LogicalNot() { if (this->__expr) { this->deconnection(this->__expr); delete this->__expr; } } bool LogicalNot::compile(InterpreterContext* ic) { this->_ic = ic; return this->__expr->compile(ic); } Variant* LogicalNot::evaluate() { Variant* vexpr; bool ret; ret = true; vexpr = NULL; if (((vexpr = this->__expr->evaluate()) != NULL) && (vexpr->type() == typeId::Bool)) ret = vexpr->value(); if (vexpr != NULL) delete vexpr; return new Variant(!ret); } Number::Number(uint64_t val) : __val(val) { } Number::~Number() { } bool Number::compile(InterpreterContext* ic) { this->_ic = ic; return true; } Variant* Number::evaluate() { return new Variant(__val); } Boolean::Boolean(bool val) : __val(val) { } Boolean::~Boolean() { } bool Boolean::compile(InterpreterContext* ic) { this->_ic = ic; return true; } Variant* Boolean::evaluate() { return new Variant(__val); } TimestampAttribute::TimestampAttribute(std::string val) : __val(val) { } TimestampAttribute::~TimestampAttribute() { } bool TimestampAttribute::compile(InterpreterContext* ic) { this->_ic = ic; this->_ic->setQueryFlags(QueryFlags::Advanced); return true; } Variant* TimestampAttribute::evaluate() { std::list< Variant_p > types = this->_ic->lookupByType(typeId::VTime); if (types.size() > 0) return new Variant(types); else return NULL; } Expression* TimestampAttribute::create(std::string val) { return new TimestampAttribute(val); } NamedAttribute::NamedAttribute(std::string val) : __val(val) { } NamedAttribute::~NamedAttribute() { } bool NamedAttribute::compile(InterpreterContext* ic) { this->_ic = ic; QueryFlags::Level _qflags; try { _qflags = AttributeFactory::instance()->getQueryFlags(__val); this->_ic->setQueryFlags(_qflags); } catch (std::string) { _qflags = QueryFlags::Advanced; this->_ic->setQueryFlags(_qflags); } if (__val.find(".") != std::string::npos) __attrtype = ABSOLUTE_ATTR_NAME; else __attrtype = RELATIVE_ATTR_NAME; return true; } Variant* NamedAttribute::evaluate() { std::list< Variant_p > types = this->_ic->lookupByName(__val, __attrtype); if (types.size() == 1) { return new Variant(types.front().get()); } else if (types.size() > 1) return new Variant(types); else return NULL; } Expression* NamedAttribute::create(std::string val) { return new NamedAttribute(val); } String::String(std::string val) : __val(val) { } String::~String() { } bool String::compile(InterpreterContext* ic) { this->_ic = ic; return true; } Variant* String::evaluate() { return new Variant(__val); } Timestamp::Timestamp(std::string val) : __val(val) { } Timestamp::Timestamp(uint32_t val) { std::stringstream vstr; vstr << val; __val = vstr.str(); __val += "-01-01"; } Timestamp::~Timestamp() { } bool Timestamp::compile(InterpreterContext* ic) { this->_ic = ic; return true; } Variant* Timestamp::evaluate() { return new Variant(new vtime(__val)); } DataPatternCount::DataPatternCount(uint64_t count, PatternContainer* container) : __count(count), __container(container) { } DataPatternCount::~DataPatternCount() { } bool DataPatternCount::compile(InterpreterContext* ic) { this->_ic = ic; return true; } Variant* DataPatternCount::evaluate() { VFile* vf; Search* s; uint64_t counter; vf = NULL; try { if ((vf = this->_ic->data()) != NULL) { this->connection(vf); counter = 0; this->__container->reset(); while (counter != this->__count && !this->_stop && ((s = this->__container->getPattern()) != NULL)) { if (vf->find(s) != -1) { IndexedPatterns::instance()->addPattern(s->pattern(), vf->node()); ++counter; } } } } catch (vfsError err) { std::cout << err.error << std::endl; } catch (std::exception err) { //std::cout << err.error << std::endl; } if (vf != NULL) this->deconnection(vf); return new Variant(counter == this->__count); } DataMatches::DataMatches(uint64_t count, Search* pattern) : __count(count), __pattern(pattern) { } DataMatches::~DataMatches() { } bool DataMatches::compile(InterpreterContext* ic) { bool ret; ret = false; try { this->__pattern->compile(); this->_ic = ic; ret = true; } catch (std::string) { } return ret; } Variant* DataMatches::evaluate() { VFile* vf; bool ret; int32_t counter; ret = false; vf = NULL; try { if ((vf = this->_ic->data()) != NULL) { counter = 0; this->connection(vf); if (this->__count > 1) { if ((counter = vf->count(this->__pattern, (int32_t)this->__count)) == this->__count) ret = true; } else { int64_t off = vf->find(this->__pattern); if (off != -1) counter = 1; ret = ((__count == 0 && off == -1) || (__count == 1 && off != -1)); } if (counter) IndexedPatterns::instance()->addPattern(this->__pattern->pattern(), vf->node()); } } catch (vfsError err) { std::cout << err.error << std::endl; } catch (std::exception err) { //std::cout << err.error << std::endl; } if (vf != NULL) this->deconnection(vf); return new Variant(ret); } AttributeExpression::AttributeExpression(Expression* attr, uint64_t count, ExpressionList* exprs) throw (std::string) { this->__attr = NULL; this->__count = 0; this->__exprs = NULL; this->__patterns = NULL; if (attr != NULL && exprs != NULL) { ExpressionList::iterator eit; this->__attr = attr; this->__count = count; this->__exprs = exprs; this->connection(this->__attr); for (eit = this->__exprs->begin(); eit != this->__exprs->end(); ++eit) { this->connection(*eit); } } } AttributeExpression::AttributeExpression(Expression* attr, uint64_t count, PatternContainer* patterns) throw (std::string) { this->__attr = NULL; this->__count = 0; this->__exprs = NULL; this->__patterns = NULL; if (attr != NULL && patterns != NULL) { this->__attr = attr; this->__count = count; this->__patterns = patterns; this->connection(this->__attr); } } AttributeExpression::~AttributeExpression() { ExpressionList::iterator eit; if (this->__exprs != NULL) { for (eit = this->__exprs->begin(); eit != this->__exprs->end(); ++eit) { this->deconnection(*eit); delete (*eit); } delete this->__exprs; } if (this->__patterns != NULL) { delete this->__patterns; } if (this->__attr != NULL) { this->deconnection(this->__attr); delete this->__attr; } } bool AttributeExpression::compile(InterpreterContext* ic) { this->_ic = ic; return this->__attr->compile(ic); } void AttributeExpression::__evaluate(Variant_p vattr, uint64_t* counter) { if (vattr->type() == typeId::String || vattr->type() == typeId::CArray) { std::string attr = vattr->value(); Search* sh; this->__patterns->reset(); while (*counter != this->__count && ((sh = this->__patterns->getPattern()) != NULL)) { if (sh->find(attr) != -1) ++(*counter); } } } Variant* AttributeExpression::evaluate() { bool ret; Variant* vattr = NULL; uint64_t counter = 0; ret = false; if ((vattr = this->__attr->evaluate()) != NULL) { if (this->__patterns != NULL) { if (vattr->type() == typeId::List) { VLIST vlist = vattr->value< VLIST >(); VLIST::iterator it; it = vlist.begin(); while (counter != this->__count && it != vlist.end()) { this->__evaluate(*it, &counter); ++it; } } else this->__evaluate(vattr, &counter); ret = (counter == this->__count); } } // else if (this->__exprs != NULL) // { // } // } return new Variant(ret); } // PropertiesExpression::PropertiesExpression(uint64_t count, AttributeList* attrs) // { // } // PropertiesExpression::~PropertiesExpression() // { // } // bool PropertiesExpression::compile(InterpreterContext* ic) // { // } // Variant* PropertiesExpression::evaluate() // { // return new Variant(false); // } MatchExpression::MatchExpression(Expression *expr, Search* pattern) throw (std::string) { this->__expr = NULL; this->__pattern = NULL; if (expr != NULL && pattern != NULL) { this->__expr = expr; this->connection(this->__expr); this->__pattern = pattern; } else throw std::string("Match expression cannot be NULL"); } MatchExpression::~MatchExpression() { if (this->__expr != NULL) { this->deconnection(this->__expr); delete this->__expr; } if (this->__pattern != NULL) delete this->__pattern; } bool MatchExpression::compile(InterpreterContext* ic) { this->_ic = ic; this->__expr->compile(ic); this->__pattern->compile(); return true; } Variant* MatchExpression::evaluate() { Variant* lexpr = NULL; std::string str; int32_t off; bool ret; ret = false; lexpr = this->__expr->evaluate(); if (lexpr != NULL && (lexpr->type() == typeId::String || lexpr->type() == typeId::CArray)) { str = lexpr->value< std::string >(); if ((off = this->__pattern->find(str)) != -1) ret = true; } if (lexpr != NULL) delete lexpr; return new Variant(ret); } // DataMatchExpression::DataMatchExpression(uint64_t count, Search* pattern) : __count(count), __pattern(pattern) // { // } // DataMatchExpression::~DataMatchExpression() // { // } // bool DataMatchExpression::compile(InterpreterContext* ic) // { // this->_ic = ic; // return true; // } // Variant* DataMatchExpression::evaluate() // { // } PatternList::PatternList() { this->__pos = 0; } PatternList::PatternList(Search* pattern) { this->__pos = 0; this->__patterns.push_back(pattern); } PatternList::~PatternList() { } void PatternList::push(Search* pattern) { this->__patterns.push_back(pattern); } Search* PatternList::getPattern() { Search* pattern; pattern = NULL; if (this->__pos < this->__patterns.size()) { pattern = this->__patterns[this->__pos]; this->__pos++; } return pattern; } void PatternList::reset() { this->__pos = 0; } PatternDictionnary::PatternDictionnary(Dictionnary* dict) { this->__idx = this->__dicts.begin(); dict->compile(); this->__dicts.push_back(dict); } void PatternDictionnary::push(Dictionnary* dict) { dict->compile(); this->__dicts.push_back(dict); } PatternDictionnary::~PatternDictionnary() { } Search* PatternDictionnary::getPattern() { Search* s; s = NULL; while (this->__idx != this->__dicts.end()) { if ((s = (*this->__idx)->nextSearchPattern()) != NULL) return s; else this->__idx++; } return s; } void PatternDictionnary::reset() { std::vector::iterator it; for (it = this->__dicts.begin(); it != this->__dicts.end(); it++) (*it)->reset(); this->__idx = this->__dicts.begin(); } dff-1.3.0+dfsg.1/dff/api/filters/astnodes.hpp000066400000000000000000000203511217176075400206540ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #ifndef __ASTNODES_HPP__ #define __ASTNODES_HPP__ #include #include #include "node.hpp" #include "search.hpp" #include "eventhandler.hpp" #include "factory.hpp" #include "dictionnary.hpp" // forward declaration class Expression; class PatternContainer; #define KEYWORD(_kwd, _fqn, _type, _qflag) \ static int _kwd ## _default_kw = AttributeFactory::instance()->addKeyword(#_kwd, #_fqn, _type, _qflag); typedef std::vector NumberList; typedef std::vector StringList; typedef std::vector AttributeList; typedef std::vector TimeList; typedef std::vector ExpressionList; typedef std::list< Variant_p > VLIST; #define IN_RANGE 0 #define NOT_IN_RANGE 1 typedef struct { std::string* pattern; Search::CaseSensitivity cs; } sfunc_params; // class PatternIndexer // { // private: // EXPORT PatternIndexer() {} // EXPORT PatternIndexer(PatternIndexer &) {} // EXPORT ~PatternIndexer() {} // PatternIndexer& operator=(PatternIndexer &) {} // public: // EXPORT static PatternIndexer* instance() // { // static PatternIndexery fact; // return &fact; // } // }; class InterpreterContext { public : InterpreterContext(); ~InterpreterContext(); void setCurrentNode(Node* node); void setQueryFlags(QueryFlags::Level qflags); std::list< Variant_p > lookupByType(uint8_t type); std::list< Variant_p > lookupByName(std::string name, attributeNameType tname); VFile* data(); void clear(); private: Attributes __attributes; Node* __cnode; void __lookupByName(Variant_p rcvar, std::string name, std::list< Variant_p >* result); void __lookupByAbsoluteName(Variant_p rcvar, std::string name, std::list< Variant_p >* result); void __lookupByType(Variant_p rcvar, uint8_t type, std::list< Variant_p >* result); VFile* __data; int __qflags; }; class Expression : public EventHandler { protected: bool _stop; InterpreterContext* _ic; Expression() : _stop(false), _ic(NULL) {} public: virtual ~Expression() {} virtual Variant* evaluate() = 0; virtual bool compile(InterpreterContext* ic) = 0; virtual void Event(event* e) { if (e != NULL) { if (e->type == 0x4242) { _stop = false; notify(e); } else if (e->type == 0x204) { _stop = true; notify(e); } } } }; class LogicalAnd : public Expression { private: Expression* __lhs; Expression* __rhs; public: LogicalAnd(Expression* lhs, Expression* rhs) throw (std::string); ~LogicalAnd(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class LogicalOr : public Expression { private: Expression* __lhs; Expression* __rhs; public: LogicalOr(Expression* lhs, Expression* rhs) throw (std::string); ~LogicalOr(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class ComparisonExpression : public Expression { private: Expression* __lhs; Expression* __rhs; typedef bool (ComparisonExpression::*Op)(Variant* lhs, Variant* rhs); bool __gt(Variant* lhs, Variant*rhs) { return lhs->operator>(rhs); } bool __gte(Variant* lhs, Variant*rhs) { return lhs->operator>=(rhs); } bool __lt(Variant* lhs, Variant*rhs) { return lhs->operator<(rhs); } bool __lte(Variant* lhs, Variant*rhs) { return lhs->operator<=(rhs); } bool __eq(Variant* lhs, Variant*rhs) { return lhs->operator==(rhs); } bool __neq(Variant* lhs, Variant*rhs) { return lhs->operator!=(rhs); } Op __cmp; public: ComparisonExpression(Expression* lhs, Expression* rhs, int op) throw (std::string); ~ComparisonExpression(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class LogicalNot : public Expression { private: Expression* __expr; public: LogicalNot(Expression* expr) throw (std::string); ~LogicalNot(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class Number : public Expression { private: uint64_t __val; public: Number(uint64_t val); ~Number(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class Boolean : public Expression { private: bool __val; public: Boolean(bool val); ~Boolean(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class TimestampAttribute : public Expression { private: std::string __val; public: TimestampAttribute(std::string val); ~TimestampAttribute(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); static Expression* create(std::string val); }; class NamedAttribute : public Expression { private: std::string __val; attributeNameType __attrtype; public: NamedAttribute(std::string val); ~NamedAttribute(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); static Expression* create(std::string val); }; class String : public Expression { private: std::string __val; public: String(std::string val); ~String(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; //typedef std::list StringList; class Timestamp : public Expression { private: std::string __val; public: Timestamp(std::string val); Timestamp(uint32_t val); ~Timestamp(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class DataPatternCount: public Expression { private: uint64_t __count; PatternContainer* __container; public: DataPatternCount(uint64_t count, PatternContainer* container); ~DataPatternCount(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class DataMatches : public Expression { private: uint64_t __count; Search* __pattern; public: DataMatches(uint64_t count, Search* pattern); ~DataMatches(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class AttributeExpression : public Expression { private: Expression* __attr; uint64_t __count; ExpressionList* __exprs; PatternContainer* __patterns; void __evaluate(Variant_p attr, uint64_t* counter); public: AttributeExpression(Expression* attr, uint64_t count, ExpressionList* exprs) throw (std::string); AttributeExpression(Expression* attr, uint64_t count, PatternContainer* patterns) throw (std::string); ~AttributeExpression(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; // class PropertiesExpression : public Expression // { // private: // uint64_t __count; // AttributeList* __attrs; // public: // PropertiesExpression(uint64_t count, AttributeList* attrs); // ~PropertiesExpression(); // virtual bool compile(InterpreterContext* ic); // virtual Variant* evaluate(); // }; class MatchExpression : public Expression { private: Expression* __expr; Search* __pattern; public: MatchExpression(Expression *expr, Search* pattern) throw (std::string); ~MatchExpression(); virtual bool compile(InterpreterContext* ic); virtual Variant* evaluate(); }; class PatternContainer { public: virtual ~PatternContainer() {} virtual Search* getPattern() = 0; virtual void reset() = 0; }; class PatternList : public PatternContainer { private: std::vector __patterns; size_t __pos; public: PatternList(); PatternList(Search* pattern); ~PatternList(); void push(Search* pattern); virtual Search* getPattern(); virtual void reset(); }; class PatternDictionnary : public PatternContainer { private: std::vector __dicts; std::vector::iterator __idx; public: explicit PatternDictionnary(Dictionnary* dict); ~PatternDictionnary(); virtual Search* getPattern(); virtual void reset(); void push(Dictionnary* dict); }; #endif dff-1.3.0+dfsg.1/dff/api/filters/dictionnary.cpp000066400000000000000000000203171217176075400213540ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "dictionnary.hpp" // LiveIndexer::LiveIndexer() : AttributesHandler("matched patterns") // { // } // LiveIndexer::~LiveIndexer() // { // } // LiveIndexer::addPattern(std::string pattern, Node* node) // { // } // Attributes LiveIndexer::attributes(Node* node) // { // } void IndexedPatterns::addPattern(std::string pattern, Node* node) { if (node != NULL) { uint32_t id; id = this->__uniq[pattern]; if (!id) { this->__uniq[pattern] = ++__counter; id = __counter; this->__idString[id] = pattern; } this->__nodePatterns[node].push_back(id); this->__patternNodes[id].push_back(node); } } std::vector IndexedPatterns::patternsByNode(Node* node) { dff::vector patterns; std::vector ret; unsigned int iter; if (this->__nodePatterns.exist(node)) { patterns = this->__nodePatterns[node]; for (iter = 0; iter != patterns.size(); ++iter) { ret.push_back(this->__idString[patterns.at(iter)]); } } return ret; } std::vector IndexedPatterns::nodesByPattern(std::string pattern) { dff::vector nodes; std::vector ret; uint32_t pid; unsigned int iter; if (this->__uniq.exist(pattern)) { pid = this->__uniq[pattern]; nodes = this->__patternNodes[pid]; for (iter = 0; iter != nodes.size(); ++iter) ret.push_back(nodes[iter]); } return ret; } void DictRegistry::add(std::string name, Dictionnary* dict) throw (std::string) { if (dict == NULL) throw (std::string("provided dictionnary is NULL")); else { if (__dictionnaries.find(name) != __dictionnaries.end()) throw (std::string(name) + std::string(" already exists in registry")); __dictionnaries[name] = dict; } } void DictRegistry::remove(std::string id) throw (std::string) { Dictionnary* dict; dictit it; dict = NULL; it = __dictionnaries.find(id); if (it == __dictionnaries.end()) throw (std::string(id) + std::string(" does not exist in registry")); else { dict = it->second; __dictionnaries.erase(it); delete dict; } } Dictionnary* DictRegistry::get(std::string id) throw (std::string) { Dictionnary* dict; dictit it = __dictionnaries.find(id); dict = NULL; if (it == __dictionnaries.end()) throw (std::string(id) + std::string(" does not exist in registry")); else dict = it->second; return dict; } std::map DictRegistry::dictionnaries() { return this->__dictionnaries; } Dictionnary::Dictionnary() { this->__cp_pos = 0; this->_compileErrors = false; } Dictionnary::~Dictionnary() { std::vector::iterator sit; std::vector::iterator bit; try { for (sit = this->__cpatterns.begin(); sit != this->__cpatterns.end(); sit++) delete *sit; for (bit = this->__bad_patterns.begin(); bit != this->__bad_patterns.end(); bit++) delete *bit; } catch (std::string) { } } std::vector Dictionnary::badPatterns() { return this->__bad_patterns; } Search* Dictionnary::nextSearchPattern() { Search* s; s = NULL; if (this->__cp_pos < this->__cpatterns.size()) { s = this->__cpatterns[this->__cp_pos]; this->__cp_pos++; } return s; } void Dictionnary::reset() { this->__cp_pos = 0; } void Dictionnary::_addBadPattern(std::string pattern, std::string message, unsigned int line) { BadPattern* bp; this->_compileErrors = true; bp = new BadPattern(); bp->line = line; bp->pattern = pattern; bp->message = message; this->__bad_patterns.push_back(bp); } void Dictionnary::_compilePattern(std::string pattern, unsigned int line) { std::string err; Search* s; Search::CaseSensitivity cs; size_t subend; size_t psize; char cstart; char cend; s = NULL; psize = pattern.size(); if (psize <= 1) this->_addBadPattern(pattern, std::string("Pattern is too short"), line); else { cstart = pattern.at(0); cend = pattern.at(psize-1); if (cend == 'i') { if (psize > 3) { cend = pattern.at(pattern.size() - 2); subend = pattern.size() - 3; cs = Search::CaseInsensitive; } else subend = 0; //volontary set to 0 to fail all case condition } else { subend = pattern.size() - 2; cs = Search::CaseInsensitive; } switch (cstart) { case '/': { if (cend == '/' && subend != 0) s = new Search(pattern.substr(1, subend), cs, Search::Regexp); else err = "unterminated regular expression"; break; } case '~': { if (cend == '~' && subend != 0) s = new Search(pattern.substr(1, subend), cs, Search::Fuzzy); else err = "unterminated fuzzy expression"; break; } case '$': { if (cend == '$' && subend != 0) s = new Search(pattern.substr(1, subend), cs, Search::Wildcard); else err = "unterminated wildcard expression"; break; } case '"': { if (cend == '"' && subend != 0) s = new Search(pattern.substr(1, subend), cs, Search::Fixed); else err = "unterminated fixed expression"; break; } default: err = "unrecognized pattern type"; break; } if (!err.empty()) this->_addBadPattern(pattern, err, line); else if (s != NULL) { try { s->compile(); this->__cpatterns.push_back(s); } catch (std::string e) { this->_addBadPattern(pattern, e, line); } } else this->_addBadPattern(pattern, std::string("Error while creating Search instance"), line); } } FileDictionnary::FileDictionnary(std::string ifile) { this->__ifile = ifile; this->__line_count = 0; this->__fdict.exceptions(std::ifstream::failbit|std::ifstream::badbit); try { this->__fdict.open(ifile.c_str(), std::fstream::in); } catch (std::ifstream::failure e) { throw std::string("FileDictionnary: error while opening file: ") + this->__ifile; } } FileDictionnary::~FileDictionnary() { this->__fdict.close(); } void FileDictionnary::__commitPattern(std::string pattern) { size_t epos; if (!pattern.empty()) { epos = pattern.size() - 1; while (epos > 0 && (pattern[epos] == '\t' || pattern[epos] == '\v' || pattern[epos] == '\f' || pattern[epos] == '\r' || pattern[epos] == ' ')) --epos; this->_compilePattern(pattern.erase(epos+1), this->__line_count); } } bool FileDictionnary::compile() { std::string pattern; char c; try { pattern = ""; while (this->__fdict.good()) { c = this->__fdict.get(); if (c == '\n') { ++this->__line_count; this->__commitPattern(pattern); pattern.clear(); } else if (!pattern.empty() || (c != '\t' && c != '\v' && c != '\f' && c != '\r' && c != ' ')) { if (pattern.size() < 256) pattern += c; else { this->_addBadPattern(pattern.substr(0, 10) + "[...]" + pattern.substr(246, 256), std::string("Pattern is too long"), this->__line_count); pattern.clear(); while (this->__fdict.good() && this->__fdict.get() != '\n') ; ++this->__line_count; } } } } catch (std::ios_base::failure e) { if (this->__fdict.eof()) { ++this->__line_count; this->__commitPattern(pattern); } else throw std::string("Error with provided file: ") + e.what(); } return !this->_compileErrors; } void FileDictionnary::save(std::string path) throw (std::string) { throw std::string("Not implemented"); } std::string FileDictionnary::fileName() { return this->__ifile; } dff-1.3.0+dfsg.1/dff/api/filters/dictionnary.hpp000066400000000000000000000077411217176075400213670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #ifndef __DICTIONNARY_HPP__ #define __DICTIONNARY_HPP__ // forward declaration #include #include #include #include #include #include #include "search.hpp" #include "export.hpp" #include "threading.hpp" class Dictionnary; class Node; class IndexedPatterns { private: EXPORT IndexedPatterns() {} EXPORT IndexedPatterns(IndexedPatterns&) {} EXPORT ~IndexedPatterns() {} EXPORT IndexedPatterns& operator=(IndexedPatterns&); dff::map > __nodePatterns; dff::map > __patternNodes; dff::map __uniq; dff::map __idString; uint32_t __counter; public: EXPORT static IndexedPatterns* instance() { static IndexedPatterns __instance; return &__instance; } EXPORT void addPattern(std::string, Node* node); EXPORT std::vector patternsByNode(Node* node); EXPORT std::vector nodesByPattern(std::string pattern); }; class BadPattern { public: unsigned int line; std::string pattern; std::string message; }; class DictRegistry { private: EXPORT DictRegistry() {}; EXPORT DictRegistry(DictRegistry &) {}; EXPORT ~DictRegistry() {}; DictRegistry& operator=(DictRegistry &); std::map __dictionnaries; typedef std::map::iterator dictit; public: EXPORT static DictRegistry* instance() { static DictRegistry __instance; return &__instance; } EXPORT void add(std::string name, Dictionnary* dict) throw (std::string); EXPORT void remove(std::string id) throw (std::string); EXPORT Dictionnary* get(std::string id) throw (std::string); EXPORT std::map dictionnaries(); }; class Dictionnary //: public DEventHandler ??? to notify watchers for compile error and instance reporting and be able to stop compile { private: std::vector __cpatterns; std::vector __bad_patterns; size_t __cp_pos; protected: void _addBadPattern(std::string pattern, std::string message, unsigned int line); void _compilePattern(std::string pattern, unsigned int line); bool _compileErrors; public: EXPORT Dictionnary(); EXPORT virtual ~Dictionnary(); EXPORT std::vector badPatterns(); EXPORT Search* nextSearchPattern(); EXPORT void reset(); EXPORT virtual void save(std::string path) throw (std::string) = 0; EXPORT virtual std::string fileName() = 0; EXPORT virtual bool compile() = 0; }; class FileDictionnary : public Dictionnary { private: std::fstream __fdict; std::string __ifile; unsigned int __line_count; void __commitPattern(std::string pattern); public: EXPORT FileDictionnary(std::string ifile); EXPORT ~FileDictionnary(); EXPORT virtual bool compile(); EXPORT virtual void save(std::string path) throw (std::string); EXPORT virtual std::string fileName(); }; // class BufferDictionnary : public Dictionnary // { // private: // std::fstream __fdict; // std::string __ifile; // unsigned int __line_count; // void __commitPattern(std::string pattern); // public: // BufferDictionnary(std::string dname, char* buffer, unsigned int len, bool recordOnCreate=false); // ~BufferDictionnary(); // virtual bool compile(); // virtual void save(std::string path) throw (std::string); // virtual std::string fileName(); // }; #endif dff-1.3.0+dfsg.1/dff/api/filters/factory.cpp000066400000000000000000000040021217176075400204710ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "factory.hpp" int AttributeFactory::registerCreator(CName type, CreateInstance creator) throw (std::string) { this->__creator[type] = creator; return 1; } int AttributeFactory::addKeyword(std::string keyword, std::string fqn, CName type, QueryFlags::Level flags) throw (std::string) { finfo* info; if (__objects.find(fqn) != __objects.end()) { std::string _err; _err = "Attribute " + fqn + " already assigned to a keyword"; throw _err; } if ((info = new finfo) != NULL) { info->func = this->__creator[type]; info->qflags = flags; __objects[fqn] = info; __kw_map[keyword] = fqn; } return 0; } Expression* AttributeFactory::create(std::string keyword) throw (std::string) { std::map::iterator idx; finfo* info; idx = __kw_map.find(keyword); if (idx != __kw_map.end()) { if ((info = __objects[idx->second]) != NULL) return info->func(idx->second); else return NULL; } else return NULL; } QueryFlags::Level AttributeFactory::getQueryFlags(std::string fqn) throw (std::string) { finfo* info; std::map::iterator idx; idx = __objects.find(fqn); if (idx != __objects.end()) { if ((info = idx->second) != NULL) return info->qflags; else throw std::string("id " + fqn + " is not setted properly"); } else throw std::string("id " + fqn + " does not exist"); } dff-1.3.0+dfsg.1/dff/api/filters/factory.hpp000066400000000000000000000036241217176075400205070ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #ifndef __FACTORY_HPP__ #define __FACTORY_HPP__ #include #include #include "export.hpp" struct QueryFlags { enum Level { Empty = 0x0000, Primitive = 0x0001, Tags = 0x0002, DataType = 0x0004, Advanced = 0x0008 }; }; class Expression; class AttributeFactory { public: enum CName { Named = 0, Timestamp = 1 }; typedef Expression* (*factoryMethod)(); typedef Expression* (*CreateInstance)(std::string); EXPORT static AttributeFactory* instance() { static AttributeFactory fact; return &fact; } EXPORT int addKeyword(std::string keyword, std::string fqn, CName type, QueryFlags::Level qflag) throw (std::string); EXPORT int registerCreator(CName type, CreateInstance creator) throw (std::string); EXPORT Expression* create(std::string keyword) throw (std::string); EXPORT QueryFlags::Level getQueryFlags(std::string fqn) throw (std::string); private: EXPORT AttributeFactory() {} EXPORT AttributeFactory(AttributeFactory &) {} EXPORT ~AttributeFactory() {} AttributeFactory& operator=(AttributeFactory &); typedef struct { CreateInstance func; QueryFlags::Level qflags; } finfo; std::map __objects; std::map __kw_map; std::map __creator; }; #endif dff-1.3.0+dfsg.1/dff/api/filters/filter.cpp000066400000000000000000000205401217176075400203140ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "filter.hpp" #include "scanner.hpp" #include Filter::Filter(std::string fname) throw (std::string) { this->__stop = false; this->__fname = fname; this->__query = ""; this->__uid = 0; if ((this->__ctx = (filter_ctx*)malloc(sizeof(filter_ctx))) == NULL) throw (std::string("Filter: cannot allocate memory for context")); this->__ctx->ic = new InterpreterContext(); this->__ctx->root = NULL; this->__ctx->buf = NULL; this->__ctx->column = 0; this->__ev = new event; } Filter::~Filter() { if (this->__ctx != NULL) { if (this->__ctx->ic != NULL) delete this->__ctx->ic; if (this->__ctx->root != NULL) { //this->deconnection(this->__ctx->root); delete this->__ctx->root; } if (this->__ctx->buf != NULL) delete this->__ctx->buf; free(this->__ctx); } if (this->__ev != NULL) delete this->__ev; } void Filter::__reset() { this->__stop = false; this->__matchednodes.clear(); if (this->__ctx->root != NULL && this->__ev != NULL) { this->__ev->type = Filter::AstReset; this->__ev->value = NULL; this->__ctx->root->Event(this->__ev); } } void Filter::__initCtx() throw (std::string) { this->__matchednodes.clear(); if (this->__ctx == NULL) throw std::string("Filter: context has not been allocated yet"); this->__ctx->ic->clear(); if (this->__ctx->buf == NULL) this->__ctx->buf = new std::string; else this->__ctx->buf->clear(); if (this->__ctx->root != NULL) { this->deconnection(this->__ctx->root); delete this->__ctx->root; this->__ctx->root = NULL; } this->__ctx->column = 0; } std::string Filter::__formatErrorMsg() { std::string err; return err; } // Future implementation will provide a filter manager with precompiled // queries. // Currently, fname is automatically associated but in future, method will // ask if it can register the provided name. If name already registered, // the method will throw an exception to warn the user. void Filter::setFilterName(std::string fname) throw (std::string) { this->__fname = fname; } std::string Filter::filterName() { return this->__fname; } std::string Filter::query() { return this->__query; } void Filter::compile(std::string query) throw (std::string) { std::string err; int status; this->__initCtx(); this->__query = query; status = parse_filter_string(query.c_str(), this->__ctx); if (status == -1) { if (this->__ctx->root != NULL) { delete this->__ctx->root; this->__ctx->root = NULL; } err = this->__formatErrorMsg(); throw (std::string(err)); } this->__ctx->root->compile(this->__ctx->ic); this->connection(this->__ctx->root); } void Filter::processFolder(Node* nodeptr) throw (std::string) { uint64_t nodescount; std::vector children; size_t i; this->__reset(); if (this->__ctx->root != NULL) { if (nodeptr != NULL) { if (nodeptr->hasChildren()) { nodescount = nodeptr->childCount(); this->__notifyNodesToProcess(nodescount); children = nodeptr->children(); i = 0; while ((i != children.size()) && (!this->__stop) ) { if (this->__eval(children[i])) this->__notifyMatch(children[i]); i++; this->__notifyProgress(i); } } } else throw std::string("provided node does not exist"); } else throw std::string("no query compiled yet"); this->__notifyEndOfProcessing(i); } void Filter::process(Node* nodeptr, bool recursive) throw (std::string) { uint64_t nodescount; uint64_t processed; this->__reset(); processed = 0; if (this->__ctx->root != NULL) { if (nodeptr != NULL) { if (nodeptr->hasChildren() && recursive) { nodescount = nodeptr->totalChildrenCount(); this->__notifyNodesToProcess(nodescount); this->__process(nodeptr, &processed); } else { this->__notifyNodesToProcess(1); try { if (this->__eval(nodeptr)) this->__notifyMatch(nodeptr); } catch (...) { std::cout << "Filter::process catch an error " << std::endl; } this->__notifyProgress(1); } } else throw std::string("provided node does not exist"); } else throw std::string("no query compiled yet"); this->__notifyEndOfProcessing(processed); } void Filter::process(std::list nodes) throw (std::string) { uint64_t processed; std::list::iterator it; this->__reset(); processed = 0; if (this->__ctx->root != NULL) { if (nodes.size() > 0) { this->__notifyNodesToProcess(nodes.size()); it = nodes.begin(); while (it != nodes.end() && !this->__stop) { if (this->__eval(*it)) this->__notifyMatch(*it); this->__notifyProgress(processed++); it++; } } this->__notifyEndOfProcessing(processed); } else throw std::string("no query compiled yet"); } void Filter::process(std::vector nodes) throw (std::string) { uint64_t processed; std::vector::iterator it; this->__reset(); processed = 0; if (this->__ctx->root != NULL) { if (nodes.size() > 0) { this->__notifyNodesToProcess(nodes.size()); it = nodes.begin(); while (it != nodes.end() && !this->__stop) { if (this->__eval(*it)) this->__notifyMatch(*it); this->__notifyProgress(processed++); it++; } } this->__notifyEndOfProcessing(processed); } else throw std::string("no query compiled yet"); } void Filter::__notifyNodesToProcess(uint64_t nodescount) { if (this->__ev != NULL) { this->__ev->type = Filter::TotalNodesToProcess; this->__ev->value = Variant_p(new Variant(nodescount)); this->notify(this->__ev); } } void Filter::__notifyMatch(Node* nodeptr) { this->__matchednodes.push_back(nodeptr); if (this->__ev != NULL) { this->__ev->type = Filter::NodeMatched; this->__ev->value = Variant_p(new Variant(nodeptr)); this->notify(this->__ev); } } void Filter::__notifyProgress(uint64_t processed) { if (this->__ev != NULL) { this->__ev->value = Variant_p(new Variant(processed)); this->__ev->type = Filter::ProcessedNodes; this->notify(this->__ev); } } void Filter::__notifyEndOfProcessing(uint64_t processed) { if (this->__ev != NULL) { this->__ev->type = Filter::EndOfProcessing; this->__ev->value = Variant_p(new Variant(processed)); this->notify(this->__ev); } } void Filter::__process(Node* nodeptr, uint64_t* processed) { std::vector children; uint32_t i; if (nodeptr != NULL && !this->__stop) { (*processed)++; this->__notifyProgress(*processed); if (this->__eval(nodeptr)) this->__notifyMatch(nodeptr); if (nodeptr->hasChildren()) { children = nodeptr->children(); i = 0; while ((i != children.size()) && (!this->__stop)) { this->__process(children[i], processed); i++; } } } return; } bool Filter::__eval(Node* node) { Variant* vptr; bool ret; ret = false; vptr = NULL; this->__ctx->ic->setCurrentNode(node); try { if (((vptr = this->__ctx->root->evaluate()) != NULL) && (vptr->type() == typeId::Bool)) ret = vptr->value(); } catch (...) { std::cout << "Filter::__eval catch an error" << std::endl; } if (vptr != NULL) delete vptr; return ret; } void Filter::process(uint64_t nodeid, bool recursive) throw (std::string) { } void Filter::process(uint16_t fsoid, bool recursive) throw (std::string) { } std::vector Filter::matchedNodes() { return this->__matchednodes; } void Filter::Event(event* e) { if (e != NULL && e->type == Filter::StopProcessing) { this->__stop = true; if (this->__ctx->root != NULL) this->__ctx->root->Event(e); } } dff-1.3.0+dfsg.1/dff/api/filters/libfilters.i000066400000000000000000000031441217176075400206350ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "pyrun.swg" %module(package="dff.api.filters") libfilters #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include "std_string.i" %include "std_map.i" %include "std_vector.i" %include "windows.i" %exception Filter::process { SWIG_PYTHON_THREAD_BEGIN_BLOCK; $action SWIG_PYTHON_THREAD_END_BLOCK; } %{ #include "variant.hpp" #include "vtime.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "mfso.hpp" #include "factory.hpp" #include "rootnode.hpp" /* #include "../include/export.hpp" */ /* #include "../include/eventhandler.hpp" */ #include "../include/filter.hpp" #include "dictionnary.hpp" %} %import "../vfs/libvfs.i" namespace std { %template(BadPatterns) std::vector; %template(VectString) std::vector; %template(Dictionnaries) std::map; }; %traits_swigtype(Dictionnary); %fragment(SWIG_Traits_frag(Dictionnary)); %include "../include/filter.hpp" %include "factory.hpp" %include "dictionnary.hpp" dff-1.3.0+dfsg.1/dff/api/filters/parser.y000066400000000000000000000401771217176075400200210ustar00rootroot00000000000000%{ #define YYERROR_VERBOSE #include #include #include "scanner.hpp" #include "astnodes.hpp" #include "dictionnary.hpp" Expression* check_for_timestamp(Expression* lhs, Expression* rhs); %} %debug %verbose %define api.pure %parse-param {void* yyscanner} %lex-param {yyscan_t yyscanner} /* reserved identifier (keywords) are the following: * filesize * timestamp * time * date * datetime * setted * data * deleted * extension * filetype * mime * name */ %token CONTAIN %token DATA %token DOTDOT %token ATTRIBUTE %token FILESIZE %token TIMESTAMP %token IDENTIFIER %token NUMBER %token STRING %token REGEXP %token WILDCARD %token FUZZY %token DICT %token ATTRIBUTES %token MATCHES %token _TRUE_ %token _FALSE_ %token ALL %token ANY %token NONE %token OF %token OR %token AND %token BIN_OR %token BIN_XOR %token BIN_AND %token LT LTE GT GTE EQ NEQ IS _IN_ //"<" "<=" ">" ">=" "==" "!=" "is" "in" %token LSHIFT RSHIFT //"<<" ">>" %token PLUS MINUS %token MUL DIV MOD %token POW %token NOT /* "extension" */ /* "filename" */ /* "filetype" */ /* "filesize" */ /* "deleted" */ /* "date" */ /* "time" */ /* "datetime" */ /* operators precedence from lowest to highest */ %left OR %left AND %left BIN_OR %left BIN_XOR %left BIN_AND %left LT LTE GT GTE EQ NEQ IS _IN_ //"<" "<=" ">" ">=" "==" "!=" "is" "in" %left LSHIFT RSHIFT //"<<" ">>" %left PLUS MINUS %left MUL DIV MOD %right NOT //%right '~' /* %type arith_operator */ /* %type comp_operator */ %type boolean_expression %type comparison_expression %type expression %type match_expression %type contain_expression %type contain_expression_attr %type contain_expression_id %type attribute_id %type pattern search_function %type pattern_container pattern_list dict_list %type search_func_params %type counter //%type attribute_list //%type expression_list /* %type bitwise_expression */ /* %type arith_expression */ /* %type counter */ /* %type string_list_form */ /* %type attributes_list_form */ /* %type attributes_list */ /* %type range_form */ /* %type range_left_expression */ /* %type call_expression */ /* %type expression_list */ %type literal %type primary /* %type string_list */ /* %type string_list_item */ /* union used for all possible data types and used in lexer */ /* defined in scanner.hpp with YYSTYPE union */ /* %union { */ /* AstNode* node; */ /* //void* node; */ /* void* list; */ /* void* set; */ /* void* range; */ /* void* func; */ /* uint64_t number; */ /* void* str; */ /* } */ %{ //Function declaration %} %start input %% input: boolean_expression { filter_ctx* ctx = yyget_extra(yyscanner); ctx->root = $1; } ; boolean_expression : boolean_expression AND boolean_expression { $$ = new LogicalAnd($1, $3); } | boolean_expression OR boolean_expression { $$ = new LogicalOr($1, $3); } | NOT boolean_expression { $$ = new LogicalNot($2); } | '(' boolean_expression ')' { $$ = $2; } | comparison_expression { $$ = $1; } | match_expression { $$ = $1; } | contain_expression { $$ = $1; } ; pattern_container : '[' pattern_list ']' { $$ = $2; } | DICT { try { Dictionnary* dict = DictRegistry::instance()->get(*$1); delete $1; if (($$ = new PatternDictionnary(dict)) == NULL) { yyerror(yyscanner, NULL); YYERROR; } } catch (std::string) { delete $1; yyerror(yyscanner, NULL); YYERROR; } } | '[' dict_list ']' { $$ = $2; } ; dict_list: DICT { try { Dictionnary* dict = DictRegistry::instance()->get(*$1); delete $1; if (($$ = new PatternDictionnary(dict)) == NULL) { yyerror(yyscanner, NULL); YYERROR; } } catch (std::string) { delete $1; yyerror(yyscanner, NULL); YYERROR; } } | dict_list ',' DICT { try { Dictionnary* dict = DictRegistry::instance()->get(*$3); delete $3; ((PatternDictionnary*)$1)->push(dict); } catch (std::string) { delete $3; yyerror(yyscanner, NULL); YYERROR; } } ; /* attribute_expression: attribute_id CONTAIN counter OF '[' expression_list ']' { $$ = new AttributeExpression($1, $3, $6); } */ /* ; */ /* properties_expression : ATTRIBUTES CONTAIN counter OF '[' attributes_list ']' { $$ = new PropertiesExpression($3, $6); } */ /* | ATTRIBUTES HAS ATTRIBUTE { $$ = new PropertiesExpression(1, $3); } */ /* ; */ /* contain_expression: attribute_id CONTAIN counter OF '[' expression_list ']' */ /* { */ /* $$ = new AttributeExpression($1, $3, $6); */ /* } */ /* | attribute_id IN pattern_container { $$ = new AttributeExpression($1, 1, $3); } */ //| ATTRIBUTE CONTAIN counter OF '[' pattern_list ']' { $$ = new AttributeExpression($1, $3, $6); } /* | contain_expression_id */ /* { */ /* $$ = $1; */ /* } */ //; contain_expression: attribute_id _IN_ pattern_container { $$ = new AttributeExpression($1, 1, $3); } | contain_expression_attr { $$ = $1; } | contain_expression_id { $$ = $1; } ; contain_expression_attr: ATTRIBUTE MATCHES counter OF pattern_container { Expression* expr; if ((expr = new NamedAttribute(*$1)) != NULL) $$ = new AttributeExpression(expr, $3, $5); else { delete $1; delete $5; yyerror(yyscanner, NULL); YYERROR; } } /*| ATTRIBUTE CONTAIN counter OF '[' expression_list ']' */ /* { */ /* Expression* expr; */ /* if ((expr = new NamedAttribute(*$1)) != NULL) */ /* $$ = new AttributeExpression(expr, $3, $6); */ /* else */ /* { */ /* delete $1; */ /* delete $6; */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ ; contain_expression_id: IDENTIFIER MATCHES counter OF pattern_container { Expression* expr; if ((expr = AttributeFactory::instance()->create(*$1)) != NULL) { delete $1; $$ = new AttributeExpression(expr, $3, $5); } else { delete $1; yyerror(yyscanner, NULL); YYERROR; } } | DATA MATCHES counter OF pattern_container { $$ = new DataPatternCount($3, $5); } ; /* attribute_list : ATTRIBUTE */ /* { */ /* AttributeList* attrs; */ /* if ((attrs = new AttributeList) != NULL) */ /* { */ /* attrs->push_back(*$1); */ /* delete $1; */ /* } */ /* else */ /* { */ /* delete $1; */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ /* | attribute_list ',' ATTRIBUTE */ /* { */ /* ((AttributeList*)$1)->push_back(*$3); */ /* delete $3; */ /* } */ /* ; */ pattern_list : pattern { $$ = new PatternList($1); } | pattern_list ',' pattern { ((PatternList*)$1)->push($3); } ; /* expression_list : expression */ /* { */ /* ExpressionList* exprs; */ /* if ((exprs = new ExpressionList()) != NULL) */ /* { */ /* exprs->push_back($1); */ /* $$ = exprs; */ /* } */ /* else */ /* { */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ /* | expression_list ',' expression { ((ExpressionList*)$1)->push_back($3); } */ /* ; */ match_expression : ATTRIBUTE MATCHES pattern { Expression* expr; if ((expr = new NamedAttribute(*$1)) != NULL) $$ = new MatchExpression(expr, $3); else { delete $3; yyerror(yyscanner, NULL); YYERROR; } } | DATA MATCHES NUMBER pattern { if (($$ = new DataMatches($3, $4)) == NULL) { delete $4; yyerror(yyscanner, NULL); YYERROR; } } | DATA MATCHES pattern { if (($$ = new DataMatches(1, $3)) == NULL) { delete $3; yyerror(yyscanner, NULL); YYERROR; } } | IDENTIFIER MATCHES pattern { Expression* expr; if ((expr = AttributeFactory::instance()->create(*$1)) != NULL) { delete $1; $$ = new MatchExpression(expr, $3); } else { delete $1; delete $3; yyerror(yyscanner, NULL); YYERROR; } } ; attribute_id : ATTRIBUTE { $$ = new NamedAttribute(*$1); delete $1; } | IDENTIFIER { $$ = AttributeFactory::instance()->create(*$1); delete $1; if ($$ == NULL) { yyerror(yyscanner, NULL); YYERROR; } } ; pattern : STRING { Search* s = new Search(*$1, Search::CaseInsensitive, Search::Fixed); delete $1; try { s->compile(); } catch (std::string) { yyerror(yyscanner, NULL); YYERROR; } $$ = s; } | REGEXP { Search* s = new Search(*$1, Search::CaseInsensitive, Search::Regexp); try { s->compile(); } catch (std::string) { yyerror(yyscanner, NULL); YYERROR; } $$ = s; delete $1; } | WILDCARD { Search* s = new Search(*$1, Search::CaseInsensitive, Search::Wildcard); try { s->compile(); } catch (std::string) { yyerror(yyscanner, NULL); YYERROR; } $$ = s; delete $1; } | FUZZY { Search* s = new Search(*$1, Search::CaseInsensitive, Search::Fuzzy); try { s->compile(); } catch (std::string) { yyerror(yyscanner, NULL); YYERROR; } $$ = s; delete $1; } | search_function { try { $1->compile(); } catch (std::string) { yyerror(yyscanner, NULL); YYERROR; } $$ = $1; } ; /* | range_left_expression IN range_form */ /* { */ /* $$ = new_range_search(yyscanner, $1, IN_RANGE, $3); */ /* if ($$ == NULL) */ /* { */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ /* | range_left_expression NOT IN range_form */ /* { */ /* $$ = new_range_search(yyscanner, $1, NOT_IN_RANGE, $4); */ /* if ($$ == NULL) */ /* { */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ ; /* range_expression : range_left_expression IN range_form { $$ = new RangeIn($1, $3); } */ /* | range_left_expression NOT IN range_form { $$ = new RangeNotIn($1, $3); } */ /* ; */ comparison_expression : expression LT expression { Expression* num_to_ts; if ((num_to_ts = check_for_timestamp($1, $3)) != NULL) $$ = new ComparisonExpression($1, num_to_ts, LT); else $$ = new ComparisonExpression($1, $3, LT); } | expression LTE expression { Expression* num_to_ts; if ((num_to_ts = check_for_timestamp($1, $3)) != NULL) $$ = new ComparisonExpression($1, num_to_ts, LTE); else $$ = new ComparisonExpression($1, $3, LTE); } | expression GT expression { Expression* num_to_ts; if ((num_to_ts = check_for_timestamp($1, $3)) != NULL) $$ = new ComparisonExpression($1, num_to_ts, GT); else $$ = new ComparisonExpression($1, $3, GT); } | expression GTE expression { Expression* num_to_ts; if ((num_to_ts = check_for_timestamp($1, $3)) != NULL) $$ = new ComparisonExpression($1, num_to_ts, GTE); else $$ = new ComparisonExpression($1, $3, GTE); } | expression EQ expression { Expression* num_to_ts; if ((num_to_ts = check_for_timestamp($1, $3)) != NULL) $$ = new ComparisonExpression($1, num_to_ts, EQ); else $$ = new ComparisonExpression($1, $3, EQ); } | expression NEQ expression { Expression* num_to_ts; if ((num_to_ts = check_for_timestamp($1, $3)) != NULL) $$ = new ComparisonExpression($1, num_to_ts, NEQ); else $$ = new ComparisonExpression($1, $3, NEQ); } ; /* range_left_expression : IDENTIFIER */ /* { */ /* $$ = new_identifier(yyscanner, $1); */ /* if ($$ == NULL) */ /* { */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ /* | ATTRIBUTE { $$ = new_attribute(yyscanner, $1); } */ /* ; */ expression : primary { $$ = $1; } ; /* bitwise_expression : arith_expression { $$ = $1; } */ /* | bitwise_expression LSHIFT arith_expression { $$ = new_bitwise_expression(yyscanner, $1, $2, $3); } */ /* | bitwise_expression RSHIFT arith_expression { $$ = new_bitwise_expression(yyscanner, $1, $2, $3); } */ /* | bitwise_expression BIN_AND arith_expression { $$ = new_bitwise_expression(yyscanner, $1, $2, $3); } */ /* | bitwise_expression BIN_OR arith_expression { $$ = new_bitwise_expression(yyscanner, $1, $2, $3); } */ /* | bitwise_expression BIN_XOR arith_expression { $$ = new_bitwise_expression(yyscanner, $1, $2, $3); } */ /* ; */ /* arith_expression : primary { $$ = $1; } */ /* | arith_expression arith_operator primary */ /* { */ /* $$ = new_arith_expression(yyscanner, $1, $2, $3); */ /* if ($$ == NULL) */ /* { */ /* yyerror(yyscanner, NULL); */ /* YYERROR; */ /* } */ /* } */ /* ; */ /* arith_operator : PLUS { $$ = PLUS; } */ /* | MINUS { $$ = MINUS; } */ /* | MUL { $$ = MUL; } */ /* | DIV { $$ = DIV; } */ /* | MOD { $$ = MOD; } */ /* | POW { $$ = POW; } */ /* ; */ primary : literal { $$ = $1; } | '(' expression ')' { $$ = $2; } ; literal : NUMBER { $$ = new Number($1); } | ATTRIBUTE { $$ = new NamedAttribute(*$1); delete $1; } | IDENTIFIER { $$ = AttributeFactory::instance()->create(*$1); delete $1; if ($$ == NULL) { yyerror(yyscanner, NULL); YYERROR; } } | STRING { $$ = new String(*$1); delete $1; } | TIMESTAMP { $$ = new Timestamp(*$1); delete $1; } | _TRUE_ { $$ = new Boolean(true); } | _FALSE_ { $$ = new Boolean(false); } /*| REGEXP {$$ = new Regexp(*$1); delete $1; } | FUZZY { $$ = new Fuzzy(*$1); delete $1; } | WILDCARD { $$ = new Wildcard(*$1); delete $1; }*/ ; /* attributes_list_form : '[' attributes_list ']' { $$ = $2; } */ /* ; */ /* attributes_list : ATTRIBUTE { $$ = new_attributes_list(yyscanner, $1); } */ /* | attributes_list ',' ATTRIBUTE { push_attribute(yyscanner, $1, $3); } //check if attribute already exists... */ /* ; */ counter: NUMBER { $$ = $1; } | ANY { $$ = 1; } | ALL { $$ = UINT64_MAX; } | NONE { $$ = 0; } ; search_function : IDENTIFIER '(' search_func_params ')' { Search* s; std::string pattern; Search::CaseSensitivity cs; s = NULL; pattern = *($3->pattern); cs = $3->cs; delete $3->pattern; free($3); if (*$1 == "re") s = new Search(pattern, cs, Search::Regexp); else if (*$1 == "w") s = new Search(pattern, cs, Search::Wildcard); else if (*$1 == "fz") s = new Search(pattern, cs, Search::Fuzzy); else if (*$1 == "f") s = new Search(pattern, cs, Search::Fixed); else { yyerror(yyscanner, NULL); YYERROR; } $$ = s; } ; search_func_params : STRING { sfunc_params* sfp; sfp = NULL; if ((sfp = (sfunc_params*)malloc(sizeof(sfunc_params))) == NULL) { yyerror(yyscanner, NULL); YYERROR; } else { sfp->pattern = $1; sfp->cs = Search::CaseSensitive; } $$ = sfp; } | search_func_params ',' IDENTIFIER { if (*$3 != "i") { yyerror(yyscanner, NULL); YYERROR; } else $1->cs = Search::CaseInsensitive; $$ = $1; } ; /* string_list_form : '[' string_list ']' { $$ = $2; } */ /* ; */ /* string_list : string_list_item { $$ = new StringList($1); } */ /* | string_list ',' string_list_item { $1->push_back($3); } */ /* ; */ /* string_list_item : STRING { $$ = new String(*$1); delete $1; } */ /* //| call_expression { $$ = $1; } */ /* ; */ /* /\* list_form : '[' expression_list ']' {}//{ $$ = $2; } *\/ */ /* /\* ; *\/ */ /* range_form : '(' expression DOTDOT expression ')' { $$ = new_range_form(yyscanner, $2, $4); } */ /* | '(' DOTDOT expression ')' { $$ = new_range_form(yyscanner, NULL, $3); } */ /* | '(' expression DOTDOT ')' { $$ = new_range_form(yyscanner, $2, NULL); } */ /* ; */ /* expression_list : { $$ = new_expression_list(yyscanner, NULL); } */ /* | expression { $$ = new_expression_list(yyscanner, $1); } */ /* | expression_list ',' expression { push_expression(yyscanner, $1, $3); } */ /* ; */ /* rules end here */ %% Expression* check_for_timestamp(Expression* lhs, Expression* rhs) { TimestampAttribute* tsattr = dynamic_cast(lhs); Number* numattr = dynamic_cast(rhs); Expression* ts = NULL; if (tsattr != NULL && numattr != NULL) { Variant* vptr; if ((vptr = numattr->evaluate()) != NULL) { try { uint32_t val = vptr->value(); ts = new Timestamp(val); delete numattr; } catch (std::string) { } } } return ts; } dff-1.3.0+dfsg.1/dff/api/filters/parserparam.hpp000066400000000000000000000013651217176075400213550ustar00rootroot00000000000000/* * parserparam.h * Definitions of the parameters for the reentrant functions * of flex (yylex) and bison (yyparse) */ #ifndef __PARSERPARAM_H__ #define __PARSERPARAM_H__ #ifndef YY_NO_UNISTD_H #define YY_NO_UNISTD_H 1 #endif // YY_NO_UNISTD_H #include "typeparser.hpp" #include "lexer.hpp" #include "astnodes.hpp" /** * @brief structure given as argument to the reentrant 'yyparse' function. */ typedef struct parserParam { yyscan_t scanner; AstNode* root; } parserParam; // the parameter name (of the reentrant 'yyparse' function) // data is a pointer to a 'parserParam' structure #define YYPARSE_PARAM data // the argument for the 'yylex' function #define YYLEX_PARAM ((parserParam*)data)->scanner #endif // __PARSERPARAM_H__ dff-1.3.0+dfsg.1/dff/api/filters/scanner.cpp000066400000000000000000002262251217176075400204700ustar00rootroot00000000000000#line 2 "/home/udgover/projects/dff_merge_mvc_tags/api/filters/scanner.cpp" #line 4 "/home/udgover/projects/dff_merge_mvc_tags/api/filters/scanner.cpp" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin yyg->yyin_r #define yyout yyg->yyout_r #define yyextra yyg->yyextra_r #define yyleng yyg->yyleng_r #define yytext yyg->yytext_r #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ,yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break * existing scanners that call yyless() from OUTSIDE yylex. * One obvious solution it to make yy_act a global. I tried that, and saw * a 5% performance hit in a non-yylineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. */ #define YY_LESS_LINENO(n) \ do { \ int yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = yyg->yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] void yyrestart (FILE *input_file ,yyscan_t yyscanner ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); void yypop_buffer_state (yyscan_t yyscanner ); static void yyensure_buffer_stack (yyscan_t yyscanner ); static void yy_load_buffer_state (yyscan_t yyscanner ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); void *yyalloc (yy_size_t ,yyscan_t yyscanner ); void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); void yyfree (void * ,yyscan_t yyscanner ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define yywrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; typedef int yy_state_type; #define yytext_ptr yytext_r static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); static int yy_get_next_buffer (yyscan_t yyscanner ); static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; #define YY_NUM_RULES 68 #define YY_END_OF_BUFFER 69 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[170] = { 0, 66, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 67, 66, 66, 67, 46, 53, 14, 10, 13, 15, 16, 67, 62, 33, 33, 63, 1, 67, 2, 49, 35, 12, 35, 35, 35, 35, 35, 35, 35, 35, 35, 11, 56, 44, 68, 39, 68, 48, 47, 60, 61, 57, 68, 55, 54, 52, 50, 68, 64, 65, 66, 6, 9, 17, 33, 0, 0, 0, 0, 8, 3, 5, 4, 7, 35, 35, 35, 35, 35, 35, 35, 23, 24, 35, 35, 25, 22, 35, 44, 45, 41, 42, 40, 45, 48, 60, 59, 58, 55, 52, 0, 64, 33, 0, 33, 34, 26, 21, 27, 35, 35, 35, 35, 35, 35, 20, 35, 0, 0, 33, 0, 35, 35, 31, 35, 35, 28, 18, 43, 51, 0, 33, 0, 35, 35, 19, 35, 0, 0, 35, 35, 35, 0, 0, 35, 30, 32, 0, 38, 35, 0, 35, 37, 29, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 1, 6, 7, 8, 1, 1, 1, 9, 10, 1, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 1, 17, 18, 19, 1, 20, 21, 22, 21, 21, 21, 21, 23, 24, 24, 24, 25, 24, 26, 24, 24, 24, 24, 24, 24, 27, 24, 24, 24, 28, 24, 24, 1, 29, 1, 30, 31, 1, 32, 33, 34, 35, 36, 37, 24, 38, 39, 24, 24, 40, 41, 42, 43, 24, 24, 44, 45, 46, 47, 24, 24, 48, 49, 24, 1, 50, 1, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[52] = { 0, 1, 1, 2, 1, 3, 4, 1, 1, 1, 1, 1, 1, 5, 6, 6, 7, 1, 1, 1, 8, 6, 6, 9, 9, 9, 9, 9, 9, 10, 1, 9, 6, 6, 6, 6, 6, 6, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 11 } ; static yyconst flex_int16_t yy_base[190] = { 0, 0, 0, 49, 50, 341, 340, 53, 54, 53, 54, 57, 65, 58, 61, 359, 362, 70, 73, 340, 362, 362, 362, 362, 348, 362, 362, 344, 362, 70, 66, 362, 70, 337, 81, 362, 0, 362, 61, 311, 321, 320, 64, 319, 307, 53, 305, 362, 362, 0, 362, 362, 97, 0, 362, 0, 362, 362, 335, 0, 362, 0, 362, 299, 0, 362, 108, 362, 362, 362, 98, 324, 323, 322, 0, 362, 362, 362, 362, 362, 0, 303, 73, 296, 299, 294, 299, 0, 0, 292, 23, 0, 0, 290, 0, 362, 362, 362, 362, 0, 0, 0, 362, 362, 0, 0, 0, 0, 102, 105, 362, 0, 0, 0, 0, 292, 289, 302, 288, 298, 295, 0, 294, 0, 0, 121, 115, 290, 296, 0, 291, 284, 0, 0, 362, 362, 119, 125, 301, 281, 269, 0, 271, 123, 127, 259, 255, 240, 271, 138, 231, 0, 0, 140, 362, 238, 142, 224, 222, 0, 144, 146, 226, 148, 150, 225, 152, 154, 362, 362, 169, 180, 191, 202, 213, 224, 230, 239, 250, 261, 272, 283, 294, 304, 315, 232, 231, 143, 125, 109 } ; static yyconst flex_int16_t yy_def[190] = { 0, 169, 1, 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, 175, 175, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 176, 169, 176, 176, 176, 176, 176, 176, 176, 176, 176, 169, 169, 177, 169, 169, 178, 179, 169, 180, 169, 169, 181, 182, 169, 183, 169, 169, 184, 169, 169, 169, 169, 169, 169, 169, 169, 169, 185, 169, 169, 169, 169, 169, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 177, 169, 169, 169, 169, 186, 179, 180, 169, 169, 182, 183, 187, 184, 169, 169, 169, 185, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 188, 189, 169, 169, 176, 176, 176, 176, 176, 176, 176, 169, 169, 169, 169, 169, 176, 176, 176, 176, 169, 169, 176, 176, 176, 169, 169, 176, 176, 176, 169, 169, 176, 169, 176, 169, 176, 169, 169, 169, 169, 169, 169, 169, 169, 169, 0, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169 } ; static yyconst flex_int16_t yy_nxt[414] = { 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 36, 16, 37, 36, 38, 36, 39, 40, 36, 41, 36, 42, 36, 43, 44, 45, 36, 36, 46, 36, 36, 36, 47, 48, 50, 50, 51, 51, 56, 56, 50, 50, 50, 50, 50, 62, 50, 120, 57, 57, 50, 121, 50, 62, 66, 66, 65, 66, 66, 65, 52, 52, 70, 70, 58, 58, 70, 70, 63, 75, 76, 71, 91, 72, 73, 71, 63, 72, 73, 92, 74, 78, 79, 81, 96, 82, 60, 60, 87, 83, 113, 88, 66, 66, 108, 108, 109, 135, 125, 125, 74, 126, 126, 71, 114, 72, 73, 71, 97, 72, 73, 138, 138, 134, 136, 143, 143, 137, 137, 148, 148, 137, 137, 149, 149, 98, 71, 99, 72, 73, 71, 124, 72, 73, 154, 154, 156, 156, 158, 158, 161, 161, 162, 162, 164, 164, 165, 165, 167, 167, 168, 168, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 80, 123, 111, 80, 94, 166, 163, 94, 94, 94, 94, 94, 94, 160, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 100, 100, 100, 100, 100, 100, 100, 159, 100, 100, 100, 101, 157, 101, 101, 155, 101, 101, 101, 101, 153, 101, 102, 152, 102, 102, 102, 102, 102, 102, 102, 102, 102, 104, 104, 151, 104, 104, 104, 104, 104, 104, 104, 105, 150, 147, 146, 105, 105, 105, 105, 105, 145, 105, 107, 144, 107, 107, 107, 107, 142, 107, 107, 107, 107, 141, 140, 139, 133, 132, 131, 130, 129, 128, 127, 122, 119, 118, 117, 116, 115, 112, 110, 110, 110, 106, 103, 93, 90, 89, 86, 85, 84, 77, 69, 68, 67, 169, 54, 54, 15, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169 } ; static yyconst flex_int16_t yy_chk[414] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 3, 4, 7, 8, 9, 10, 11, 13, 11, 11, 14, 90, 7, 8, 12, 90, 12, 12, 17, 17, 13, 18, 18, 14, 3, 4, 30, 30, 7, 8, 29, 29, 11, 32, 32, 30, 45, 30, 30, 29, 12, 29, 29, 45, 29, 34, 34, 38, 52, 38, 9, 10, 42, 38, 82, 42, 66, 66, 70, 70, 70, 189, 108, 108, 29, 109, 109, 70, 82, 70, 70, 108, 52, 108, 108, 126, 126, 188, 125, 136, 136, 125, 125, 143, 143, 137, 137, 144, 144, 52, 125, 52, 125, 125, 137, 187, 137, 137, 149, 149, 153, 153, 156, 156, 160, 160, 161, 161, 163, 163, 164, 164, 166, 166, 167, 167, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 186, 185, 176, 177, 165, 162, 177, 177, 177, 177, 177, 177, 158, 177, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 179, 179, 179, 179, 179, 179, 179, 157, 179, 179, 179, 180, 155, 180, 180, 150, 180, 180, 180, 180, 148, 180, 181, 147, 181, 181, 181, 181, 181, 181, 181, 181, 181, 182, 182, 146, 182, 182, 182, 182, 182, 182, 182, 183, 145, 142, 140, 183, 183, 183, 183, 183, 139, 183, 184, 138, 184, 184, 184, 184, 131, 184, 184, 184, 184, 130, 128, 127, 122, 120, 119, 118, 117, 116, 115, 93, 89, 86, 85, 84, 83, 81, 73, 72, 71, 63, 58, 46, 44, 43, 41, 40, 39, 33, 27, 24, 19, 15, 6, 5, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169 } ; /* Table of booleans, true if rule could match eol. */ static yyconst flex_int32_t yy_rule_can_match_eol[69] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "scanner.l" /* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ /* Some parts (str token) of the lexer have been inspired from yara-project developed by Victor M. Alvarez and released under GPLv2 http://code.google.com/p/yara-project/ */ #line 27 "scanner.l" #include #include #include #include "parser.hpp" #include "scanner.hpp" #ifdef _WIN32 || _WIN64 #define strtoll(x, y, z) _strtoi64(x, y, z) #define strtoull(x, y, z) _strtoui64(x, y, z) #endif #define YY_NO_UNISTD_H 1 #line 656 "/home/udgover/projects/dff_merge_mvc_tags/api/filters/scanner.cpp" #define INITIAL 0 #define str 1 #define attribute 2 #define regexp 3 #define fuzzy 4 #define wildcard 5 #define dict 6 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif /* Holds the entire state of the reentrant scanner. */ struct yyguts_t { /* User-defined. Not touched by flex. */ YY_EXTRA_TYPE yyextra_r; /* The rest are the same as the globals declared in the non-reentrant scanner. */ FILE *yyin_r, *yyout_r; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; int yy_n_chars; int yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; int yy_did_buffer_switch_on_eof; int yy_start_stack_ptr; int yy_start_stack_depth; int *yy_start_stack; yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; int yylineno_r; int yy_flex_debug_r; char *yytext_r; int yy_more_flag; int yy_more_len; YYSTYPE * yylval_r; }; /* end struct yyguts_t */ static int yy_init_globals (yyscan_t yyscanner ); /* This must go here because YYSTYPE and YYLTYPE are included * from bison output in section 1.*/ # define yylval yyg->yylval_r int yylex_init (yyscan_t* scanner); int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (yyscan_t yyscanner ); int yyget_debug (yyscan_t yyscanner ); void yyset_debug (int debug_flag ,yyscan_t yyscanner ); YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner ); void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); FILE *yyget_in (yyscan_t yyscanner ); void yyset_in (FILE * in_str ,yyscan_t yyscanner ); FILE *yyget_out (yyscan_t yyscanner ); void yyset_out (FILE * out_str ,yyscan_t yyscanner ); int yyget_leng (yyscan_t yyscanner ); char *yyget_text (yyscan_t yyscanner ); int yyget_lineno (yyscan_t yyscanner ); void yyset_lineno (int line_number ,yyscan_t yyscanner ); YYSTYPE * yyget_lval (yyscan_t yyscanner ); void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (yyscan_t yyscanner ); #else extern int yywrap (yyscan_t yyscanner ); #endif #endif static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner ); #else static int input (yyscan_t yyscanner ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex \ (YYSTYPE * yylval_param ,yyscan_t yyscanner); #define YY_DECL int yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; #line 61 "scanner.l" #line 903 "/home/udgover/projects/dff_merge_mvc_tags/api/filters/scanner.cpp" yylval = yylval_param; if ( !yyg->yy_init ) { yyg->yy_init = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yyg->yy_start ) yyg->yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } yy_load_buffer_state(yyscanner ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yyg->yy_c_buf_p; /* Support of yytext. */ *yy_cp = yyg->yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yyg->yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 170 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 169 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; yy_find_action: yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { int yyl; for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) do{ yylineno++; yycolumn=0; }while(0) ; } do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yyg->yy_hold_char; yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 63 "scanner.l" { return LT; } YY_BREAK case 2: YY_RULE_SETUP #line 64 "scanner.l" { return GT; } YY_BREAK case 3: YY_RULE_SETUP #line 65 "scanner.l" { return LTE; } YY_BREAK case 4: YY_RULE_SETUP #line 66 "scanner.l" { return GTE; } YY_BREAK case 5: YY_RULE_SETUP #line 67 "scanner.l" { return EQ; } YY_BREAK case 6: YY_RULE_SETUP #line 68 "scanner.l" { return NEQ; } YY_BREAK case 7: YY_RULE_SETUP #line 69 "scanner.l" { return RSHIFT; } YY_BREAK case 8: YY_RULE_SETUP #line 70 "scanner.l" { return LSHIFT; } YY_BREAK case 9: YY_RULE_SETUP #line 71 "scanner.l" { return POW; } YY_BREAK case 10: YY_RULE_SETUP #line 72 "scanner.l" { return BIN_AND; } YY_BREAK case 11: YY_RULE_SETUP #line 73 "scanner.l" { return BIN_OR; } YY_BREAK case 12: YY_RULE_SETUP #line 74 "scanner.l" { return BIN_XOR; } YY_BREAK case 13: YY_RULE_SETUP #line 75 "scanner.l" { return MUL; } YY_BREAK case 14: YY_RULE_SETUP #line 76 "scanner.l" { return MOD; } YY_BREAK case 15: YY_RULE_SETUP #line 77 "scanner.l" { return PLUS; } YY_BREAK case 16: YY_RULE_SETUP #line 78 "scanner.l" { return MINUS; } YY_BREAK case 17: YY_RULE_SETUP #line 79 "scanner.l" { return DOTDOT; } YY_BREAK case 18: YY_RULE_SETUP #line 80 "scanner.l" { return _TRUE_; } YY_BREAK case 19: YY_RULE_SETUP #line 81 "scanner.l" { return _FALSE_; } YY_BREAK case 20: YY_RULE_SETUP #line 82 "scanner.l" { return NOT; } YY_BREAK case 21: YY_RULE_SETUP #line 83 "scanner.l" { return AND; } YY_BREAK case 22: YY_RULE_SETUP #line 84 "scanner.l" { return OR; } YY_BREAK case 23: YY_RULE_SETUP #line 85 "scanner.l" { return _IN_; } YY_BREAK case 24: YY_RULE_SETUP #line 86 "scanner.l" { return IS; } YY_BREAK case 25: YY_RULE_SETUP #line 87 "scanner.l" { return OF; } YY_BREAK case 26: YY_RULE_SETUP #line 88 "scanner.l" { return ALL; } YY_BREAK case 27: YY_RULE_SETUP #line 89 "scanner.l" { return ANY; } YY_BREAK case 28: YY_RULE_SETUP #line 90 "scanner.l" { return NONE; } YY_BREAK case 29: YY_RULE_SETUP #line 91 "scanner.l" { return ATTRIBUTES; } YY_BREAK case 30: YY_RULE_SETUP #line 92 "scanner.l" { return CONTAIN; } YY_BREAK case 31: YY_RULE_SETUP #line 93 "scanner.l" { return DATA; } YY_BREAK case 32: YY_RULE_SETUP #line 94 "scanner.l" { return MATCHES; } YY_BREAK case 33: YY_RULE_SETUP #line 96 "scanner.l" { uint64_t mul = 1; uint64_t val = 0; char* ptr = NULL; if ((ptr = strstr(yytext, "KB")) != NULL) { mul = 1024; } else if ((ptr = strstr(yytext, "MB")) != NULL) { mul = 1024*1024; } else if ((ptr = strstr(yytext, "GB")) != NULL) { mul = 1024*1024*1024; } errno = 0; if (ptr != NULL) { val = strtoull(yytext, NULL, 10); } else { val = strtoull(yytext, NULL, 10); } if (errno == ERANGE && val == ULLONG_MAX) { //OVERFLOW_ERROR; yyerror(yyscanner, "Overflow error\n"); } if (val > ULLONG_MAX / mul) { //OVERFLOW_ERROR; yyerror(yyscanner, "overflow error\n"); } val *= mul; yylval->number = val; return NUMBER; } YY_BREAK case 34: YY_RULE_SETUP #line 139 "scanner.l" { uint64_t val = 0; errno = 0; val = strtoull(yytext, NULL, 16); if (errno == ERANGE && val == ULLONG_MAX) { //OVERFLOW_ERROR; yyerror(yyscanner, "overflow error\n"); } yylval->number = val; return NUMBER; } YY_BREAK case 35: YY_RULE_SETUP #line 155 "scanner.l" { yylval->cstr = new std::string(yytext, yyleng); return IDENTIFIER; } YY_BREAK case 36: YY_RULE_SETUP #line 161 "scanner.l" { yylval->cstr = new std::string(yytext, yyleng); return TIMESTAMP; } YY_BREAK case 37: YY_RULE_SETUP #line 167 "scanner.l" { yylval->cstr = new std::string(yytext, yyleng); return TIMESTAMP; } YY_BREAK case 38: YY_RULE_SETUP #line 173 "scanner.l" { yylval->cstr = new std::string(yytext, yyleng); return TIMESTAMP; } YY_BREAK case 39: YY_RULE_SETUP #line 180 "scanner.l" { /* saw closing quote - all done */ if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty string"); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return STRING; } YY_BREAK case 40: YY_RULE_SETUP #line 190 "scanner.l" { yyextra->buf->append(1, '\t'); } YY_BREAK case 41: YY_RULE_SETUP #line 191 "scanner.l" { yyextra->buf->append("\""); } YY_BREAK case 42: YY_RULE_SETUP #line 192 "scanner.l" { yyextra->buf->append("\\"); } YY_BREAK case 43: YY_RULE_SETUP #line 194 "scanner.l" { int result; sscanf( yytext + 2, "%x", &result ); yyextra->buf->append(1, (char)result); } YY_BREAK case 44: YY_RULE_SETUP #line 201 "scanner.l" { yyextra->buf->append(yytext, yyleng); } YY_BREAK case 45: /* rule 45 can match eol */ YY_RULE_SETUP #line 206 "scanner.l" { yyerror(yyscanner, "illegal escape sequence"); } YY_BREAK case 46: YY_RULE_SETUP #line 211 "scanner.l" { yyextra->buf->clear(); BEGIN(str); } YY_BREAK case 47: YY_RULE_SETUP #line 217 "scanner.l" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty attribute"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return ATTRIBUTE; } YY_BREAK case 48: /* rule 48 can match eol */ YY_RULE_SETUP #line 230 "scanner.l" { yyextra->buf->append(yytext, yyleng); } YY_BREAK case 49: YY_RULE_SETUP #line 236 "scanner.l" { yyextra->buf->clear(); BEGIN(attribute); } YY_BREAK case 50: YY_RULE_SETUP #line 243 "scanner.l" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty wildcard pattern"); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return WILDCARD; } YY_BREAK case 51: YY_RULE_SETUP #line 254 "scanner.l" { int result; sscanf( yytext + 2, "%x", &result ); yyextra->buf->append(1, (char)result); } YY_BREAK case 52: YY_RULE_SETUP #line 261 "scanner.l" { yyextra->buf->append(yytext, yyleng); } YY_BREAK case 53: YY_RULE_SETUP #line 267 "scanner.l" { yyextra->buf->clear(); BEGIN(wildcard); } YY_BREAK case 54: YY_RULE_SETUP #line 274 "scanner.l" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty fuzzy pattern"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return FUZZY; } YY_BREAK case 55: /* rule 55 can match eol */ YY_RULE_SETUP #line 286 "scanner.l" { yyextra->buf->append(yytext, yyleng); } YY_BREAK case 56: YY_RULE_SETUP #line 292 "scanner.l" { yyextra->buf->clear(); BEGIN(fuzzy); } YY_BREAK case 57: YY_RULE_SETUP #line 298 "scanner.l" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty regexp pattern"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return REGEXP; } YY_BREAK case 58: YY_RULE_SETUP #line 310 "scanner.l" { yyextra->buf->append(1, '/'); } YY_BREAK case 59: YY_RULE_SETUP #line 314 "scanner.l" { yyextra->buf->append(yytext, 2); } YY_BREAK case 60: YY_RULE_SETUP #line 318 "scanner.l" { yyextra->buf->append(yytext, yyleng); } YY_BREAK case 61: /* rule 61 can match eol */ YY_RULE_SETUP #line 322 "scanner.l" { yyerror(yyscanner, "unterminated regular expression"); yyterminate(); } YY_BREAK case 62: YY_RULE_SETUP #line 328 "scanner.l" { yyextra->buf->clear(); BEGIN(regexp); } YY_BREAK case 63: YY_RULE_SETUP #line 334 "scanner.l" { yyextra->buf->clear(); BEGIN(dict); } YY_BREAK case 64: YY_RULE_SETUP #line 340 "scanner.l" { yyextra->buf->append(yytext, yyleng); } YY_BREAK case 65: YY_RULE_SETUP #line 345 "scanner.l" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty dictionnary term"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return DICT; } YY_BREAK case 66: /* rule 66 can match eol */ YY_RULE_SETUP #line 357 "scanner.l" { /* skip whitespace */ } YY_BREAK case 67: YY_RULE_SETUP #line 359 "scanner.l" { return yytext[0]; } YY_BREAK case 68: YY_RULE_SETUP #line 364 "scanner.l" ECHO; YY_BREAK #line 1513 "/home/udgover/projects/dff_merge_mvc_tags/api/filters/scanner.cpp" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(str): case YY_STATE_EOF(attribute): case YY_STATE_EOF(regexp): case YY_STATE_EOF(fuzzy): case YY_STATE_EOF(wildcard): case YY_STATE_EOF(dict): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yyg->yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yyg->yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; } } else switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_END_OF_FILE: { yyg->yy_did_buffer_switch_on_eof = 0; if ( yywrap(yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yyg->yy_c_buf_p = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = yyg->yytext_ptr; register int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), yyg->yy_n_chars, (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } if ( yyg->yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ,yyscanner); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } yyg->yy_n_chars += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { register yy_state_type yy_current_state; register char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 170 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { register int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ register char *yy_cp = yyg->yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 170 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 169); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner) { register char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_cp = yyg->yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yyg->yy_hold_char; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yyg->yy_n_chars + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; if ( c == '\n' ){ --yylineno; } yyg->yytext_ptr = yy_bp; yyg->yy_hold_char = *yy_cp; yyg->yy_c_buf_p = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner) #else static int input (yyscan_t yyscanner) #endif { int c; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; *yyg->yy_c_buf_p = yyg->yy_hold_char; if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) /* This was really a NUL. */ *yyg->yy_c_buf_p = '\0'; else { /* need more input */ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ,yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap(yyscanner ) ) return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(yyscanner); #else return input(yyscanner); #endif } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + offset; break; } } } c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ yyg->yy_hold_char = *++yyg->yy_c_buf_p; if ( c == '\n' ) do{ yylineno++; yycolumn=0; }while(0) ; return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); yy_load_buffer_state(yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state(yyscanner ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } static void yy_load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; yyg->yy_hold_char = *yyg->yy_c_buf_p; } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * @param yyscanner The scanner object. * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ,yyscanner); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * @param yyscanner The scanner object. */ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ,yyscanner ); yyfree((void *) b ,yyscanner ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flush_buffer(b ,yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state(yyscanner ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * @param yyscanner The scanner object. */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; yyensure_buffer_stack(yyscanner); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * @param yyscanner The scanner object. */ void yypop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { yy_load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (yyscan_t yyscanner) { int num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!yyg->yy_buffer_stack) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; } if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ,yyscanner ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) { return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ,yyscanner ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ,yyscanner); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = yyg->yy_hold_char; \ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ yyg->yy_hold_char = *yyg->yy_c_buf_p; \ *yyg->yy_c_buf_p = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; } /** Get the current line number. * @param yyscanner The scanner object. */ int yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yylineno; } /** Get the current column number. * @param yyscanner The scanner object. */ int yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yycolumn; } /** Get the input stream. * @param yyscanner The scanner object. */ FILE *yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; } /** Get the output stream. * @param yyscanner The scanner object. */ FILE *yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; } /** Get the length of the current token. * @param yyscanner The scanner object. */ int yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; } /** Get the current token. * @param yyscanner The scanner object. */ char *yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; } /** Set the user-defined data. This data is never touched by the scanner. * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; } /** Set the current line number. * @param line_number * @param yyscanner The scanner object. */ void yyset_lineno (int line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner); yylineno = line_number; } /** Set the current column. * @param line_number * @param yyscanner The scanner object. */ void yyset_column (int column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) yy_fatal_error( "yyset_column called with no buffer" , yyscanner); yycolumn = column_no; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * @param yyscanner The scanner object. * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = in_str ; } void yyset_out (FILE * out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = out_str ; } int yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } void yyset_debug (int bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = bdebug ; } /* Accessor methods for yylval and yylloc */ YYSTYPE * yyget_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; } /* User-visible API */ /* yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ int yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); return yy_init_globals ( *ptr_yy_globals ); } /* yylex_init_extra has the same functionality as yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). * The user defined value in the first argument will be available to yyalloc in * the yyextra field. */ int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); yyset_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ yyg->yy_buffer_stack = 0; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; yyg->yy_c_buf_p = (char *) 0; yyg->yy_init = 0; yyg->yy_start = 0; yyg->yy_start_stack_ptr = 0; yyg->yy_start_stack_depth = 0; yyg->yy_start_stack = NULL; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ yyfree(yyg->yy_buffer_stack ,yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ yyfree(yyg->yy_start_stack ,yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ yyfree ( yyscanner , yyscanner ); yyscanner = NULL; return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size , yyscan_t yyscanner) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr , yyscan_t yyscanner) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 364 "scanner.l" void yyerror(yyscan_t yyscanner, const char* error_msg) { // if (error_msg != NULL) // printf("%s\n", error_msg); } int parse_filter_string(const char* filter_string, filter_ctx* ctx) { yyscan_t yyscanner; YY_BUFFER_STATE state; int status; yylex_init(&yyscanner); yyset_extra(ctx,yyscanner); state = yy_scan_string(filter_string,yyscanner); if (yyparse(yyscanner) != 0) status = -1; else status = 0; yylex_destroy(yyscanner); return status; } dff-1.3.0+dfsg.1/dff/api/filters/scanner.hpp000066400000000000000000000017351217176075400204720ustar00rootroot00000000000000#ifndef __SCANNER_H__ #define __SCANNER_H__ #include "astnodes.hpp" #define LEX_BUF_SIZE 1024 typedef struct s_filter_ctx { int column; std::string* buf; Expression* root; InterpreterContext* ic; } filter_ctx; #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif #define YY_EXTRA_TYPE filter_ctx* #define YY_USE_CONST typedef union YYSTYPE { Expression* node; Search* search; PatternContainer* pcontainer; AttributeList* lattrs; ExpressionList* lexprs; std::string* cstr; uint64_t number; int tok; sfunc_params* sfp; } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 void yyerror(yyscan_t yyscanner, const char *error_message); YY_EXTRA_TYPE yyget_extra(yyscan_t yyscanner); int yylex(YYSTYPE*, yyscan_t); int yyparse(yyscan_t); int parse_filter_string(const char* filter_string, filter_ctx* ctx); #endif dff-1.3.0+dfsg.1/dff/api/filters/scanner.l000066400000000000000000000246201217176075400201340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ /* Some parts (str token) of the lexer have been inspired from yara-project developed by Victor M. Alvarez and released under GPLv2 http://code.google.com/p/yara-project/ */ %{ #include #include #include #include "parser.hpp" #include "scanner.hpp" #ifdef _WIN32 || _WIN64 #define strtoll(x, y, z) _strtoi64(x, y, z) #define strtoull(x, y, z) _strtoui64(x, y, z) #endif %} %option reentrant bison-bridge %option never-interactive %option noyywrap %option nounistd %option yylineno %option verbose %option warn %x str %x attribute %x regexp %x fuzzy %x wildcard %x dict digit [0-9] letter [a-zA-Z] hexdigit [a-fA-F0-9] %% "<" { return LT; } ">" { return GT; } "<=" { return LTE; } ">=" { return GTE; } "==" { return EQ; } "!=" { return NEQ; } ">>" { return RSHIFT; } "<<" { return LSHIFT; } "**" { return POW; } "&" { return BIN_AND; } "|" { return BIN_OR; } "^" { return BIN_XOR; } "*" { return MUL; } "%" { return MOD; } "+" { return PLUS; } "-" { return MINUS; } ".." { return DOTDOT; } "true" { return _TRUE_; } "false" { return _FALSE_; } "not" { return NOT; } "and" { return AND; } "or" { return OR; } "in" { return _IN_; } "is" { return IS; } "of" { return OF; } "all" { return ALL; } "any" { return ANY; } "none" { return NONE; } "attributes" { return ATTRIBUTES; } "contain" { return CONTAIN; } "data" { return DATA; } "matches" { return MATCHES; } {digit}+(KB|MB|GB){0,1} { uint64_t mul = 1; uint64_t val = 0; char* ptr = NULL; if ((ptr = strstr(yytext, "KB")) != NULL) { mul = 1024; } else if ((ptr = strstr(yytext, "MB")) != NULL) { mul = 1024*1024; } else if ((ptr = strstr(yytext, "GB")) != NULL) { mul = 1024*1024*1024; } errno = 0; if (ptr != NULL) { val = strtoull(yytext, NULL, 10); } else { val = strtoull(yytext, NULL, 10); } if (errno == ERANGE && val == ULLONG_MAX) { //OVERFLOW_ERROR; yyerror(yyscanner, "Overflow error\n"); } if (val > ULLONG_MAX / mul) { //OVERFLOW_ERROR; yyerror(yyscanner, "overflow error\n"); } val *= mul; yylval->number = val; return NUMBER; } 0(x|X){hexdigit}+ { uint64_t val = 0; errno = 0; val = strtoull(yytext, NULL, 16); if (errno == ERANGE && val == ULLONG_MAX) { //OVERFLOW_ERROR; yyerror(yyscanner, "overflow error\n"); } yylval->number = val; return NUMBER; } ({letter}|_)({letter}|{digit}|_)* { yylval->cstr = new std::string(yytext, yyleng); return IDENTIFIER; } [0-9]{4}("-"[0-9]{2}){2}"T"[0-9]{2}(":"[0-9]{2}){2} { yylval->cstr = new std::string(yytext, yyleng); return TIMESTAMP; } [0-9]{4}("-"[0-9]{2}){2} { yylval->cstr = new std::string(yytext, yyleng); return TIMESTAMP; } [0-9]{2}(":"[0-9]{2}){2} { yylval->cstr = new std::string(yytext, yyleng); return TIMESTAMP; } \" { /* saw closing quote - all done */ if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty string"); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return STRING; } \\t { yyextra->buf->append(1, '\t'); } \\\" { yyextra->buf->append("\""); } \\\\ { yyextra->buf->append("\\"); } \\x{hexdigit}{2} { int result; sscanf( yytext + 2, "%x", &result ); yyextra->buf->append(1, (char)result); } [^\\\n\"]+ { yyextra->buf->append(yytext, yyleng); } \\(.|\n) { yyerror(yyscanner, "illegal escape sequence"); } \" { yyextra->buf->clear(); BEGIN(str); } @ { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty attribute"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return ATTRIBUTE; } [^@]+ { yyextra->buf->append(yytext, yyleng); } @ { yyextra->buf->clear(); BEGIN(attribute); } "$" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty wildcard pattern"); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return WILDCARD; } \\x{hexdigit}{2} { int result; sscanf( yytext + 2, "%x", &result ); yyextra->buf->append(1, (char)result); } [^\\\n\"$]+ { yyextra->buf->append(yytext, yyleng); } "$" { yyextra->buf->clear(); BEGIN(wildcard); } "~" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty fuzzy pattern"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return FUZZY; } [^"~"]+ { yyextra->buf->append(yytext, yyleng); } "~" { yyextra->buf->clear(); BEGIN(fuzzy); } "/" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty regexp pattern"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return REGEXP; } \\\/ { yyextra->buf->append(1, '/'); } \\. { yyextra->buf->append(yytext, 2); } [^/\n\\]+ { yyextra->buf->append(yytext, yyleng); } \n { yyerror(yyscanner, "unterminated regular expression"); yyterminate(); } "/" { yyextra->buf->clear(); BEGIN(regexp); } ":" { yyextra->buf->clear(); BEGIN(dict); } [^:\n]+ { yyextra->buf->append(yytext, yyleng); } ":" { if (yyextra->buf->size() == 0) { yyerror(yyscanner, "empty dictionnary term"); yyterminate(); } BEGIN(INITIAL); yylval->cstr = new std::string(yyextra->buf->c_str()); return DICT; } [ \t\r\n]* { /* skip whitespace */ } . { return yytext[0]; } %% void yyerror(yyscan_t yyscanner, const char* error_msg) { // if (error_msg != NULL) // printf("%s\n", error_msg); } int parse_filter_string(const char* filter_string, filter_ctx* ctx) { yyscan_t yyscanner; YY_BUFFER_STATE state; int status; yylex_init(&yyscanner); yyset_extra(ctx, yyscanner); state = yy_scan_string(filter_string, yyscanner); if (yyparse(yyscanner) != 0) status = -1; else status = 0; yylex_destroy(yyscanner); return status; } dff-1.3.0+dfsg.1/dff/api/filters/typeparser.hpp000066400000000000000000000011351217176075400212310ustar00rootroot00000000000000/* * typeparser.h * Definition of the structure used internally by the parser and lexer * to exchange data. */ #ifndef __TYPEPARSER_H__ #define __TYPEPARSER_H__ #include "astnodes.hpp" /** * @brief The structure used by flex and bison */ typedef union stypeParser { AstNode* node; NumberList* numlist; StringList* strlist; TimeList* timelist; Processor* proc; uint64_t number; std::string* str; std::string* token; CmpOperator::Op comp; bool boolean; } typeParser; // define the type for flex and bison #define YYSTYPE typeParser #endif // __TYPE_PARSER_H__ dff-1.3.0+dfsg.1/dff/api/gui/000077500000000000000000000000001217176075400154365ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/CMakeLists.txt000066400000000000000000000016031217176075400201760ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py thumbnail.py ) # compiled add_subdirectory (dialog) add_subdirectory (widget) #add_subdirectory (box) add_subdirectory (model) add_subdirectory (view) if (FFMPEG_FOUND) add_subdirectory (video) endif (FFMPEG_FOUND) dff-1.3.0+dfsg.1/dff/api/gui/__init__.py000066400000000000000000000012271217176075400175510ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __version__ = "1.1.0" __all__ = ["widget", "itemview","dialog", "box", "button", "model", "thumbnail", "video"] dff-1.3.0+dfsg.1/dff/api/gui/dialog/000077500000000000000000000000001217176075400166755ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/dialog/CMakeLists.txt000066400000000000000000000012331217176075400214340ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py applymodule.py extractor.py tagmanager.py tagedit.py selectattributes.py ) dff-1.3.0+dfsg.1/dff/api/gui/dialog/__init__.py000066400000000000000000000012301217176075400210020ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["applymodule", "extractor", "property", "selectnodes", "uiapplymodule", "uiproperty", "uiselectnode"] dff-1.3.0+dfsg.1/dff/api/gui/dialog/applymodule.py000066400000000000000000000222511217176075400216040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # import traceback, sys from PyQt4.QtGui import QAbstractItemView, QApplication, QCheckBox, QDialog, QGridLayout, QLabel, QMessageBox,QSplitter, QVBoxLayout, QWidget, QDialogButtonBox, QPushButton, QLineEdit, QCompleter, QSortFilterProxyModel, QGroupBox, QFileDialog, QSpinBox, QFormLayout, QHBoxLayout, QStackedWidget, QListWidget, QListWidgetItem, QTextEdit, QPalette, QComboBox, QIntValidator, QPixmap from PyQt4.QtCore import Qt, QObject, QRect, QSize, SIGNAL, QModelIndex, QString, QEvent from dff.api.loader import loader from dff.api.vfs.vfs import vfs from dff.api.taskmanager.taskmanager import TaskManager from dff.api.types.libtypes import Argument, Parameter, Variant, VMap, VList, typeId from dff.api.gui.widget.layoutmanager import layoutManager from dff.ui.gui.utils.utils import Utils from dff.ui.gui.resources.ui_applymodule import Ui_applyModule class ApplyModule(QDialog, Ui_applyModule): def __init__(self, mainWindow): QDialog.__init__(self, mainWindow) Ui_applyModule.__init__(self) self.setupUi(self) self.labActivate.setVisible(False) self.labType.setVisible(False) self.labDescription.setVisible(False) self.connect(self.buttonBox,SIGNAL("accepted()"), self.validateModule) self.__mainWindow = mainWindow self.loader = loader.loader() self.vfs = vfs() self.valueArgs = {} self.translation() def initAllInformations(self, nameModule, typeModule, nodesSelected): self.__nodesSelected = nodesSelected self.nameModule = nameModule try: self.module = self.loader.modules[str(nameModule)] except KeyError: self.module = None if self.module and self.module.icon: p = QPixmap(self.module.icon) p.scaled(64, 64, Qt.KeepAspectRatio) self.modulepix.setPixmap(p) else: p = self.modulepix.pixmap().scaled(64,64, Qt.KeepAspectRatio) self.modulepix.setPixmap(p) title = self.windowTitle() + ' ' + str(nameModule) self.setWindowTitle(title) self.nameModuleField.setText(nameModule) self.typeModuleField.setText(typeModule) if not nodesSelected: self.__nodesSelected = [] self.conf = self.loader.get_conf(str(nameModule)) try: self.textEdit.setText(self.conf.description) except TypeError: self.textEdit.setText(self.conf.description()) args = self.conf.arguments() self.createArgShape(args) def createArgShape(self, args): self.connect(self.listargs, SIGNAL("currentItemChanged(QListWidgetItem*,QListWidgetItem*)"), self.argChanged) for arg in args: self.createArgument(arg) if len(self.listargs): self.listargs.item(0).setSelected(True) self.argsLayout.setStretchFactor(0, 1) self.argsLayout.setStretchFactor(1, 3) def createArgument(self, arg): warg = QWidget() vlayout = QVBoxLayout() vlayout.setSpacing(5) vlayout.setMargin(0) winfo = QWidget() infolayout = QFormLayout() infolayout.setMargin(0) requirement = arg.requirementType() # Generate argument's widget warguments = self.getWidgetFromType(arg) if arg.requirementType() in (Argument.Optional, Argument.Empty): checkBox = checkBoxWidget(self, winfo, warguments, self.labActivate.text()) vlayout.addWidget(checkBox, 0) infolayout.addRow(self.labType.text(), QLabel(str(typeId.Get().typeToName(arg.type())))) tedit = QTextEdit(str(arg.description())) tedit.setReadOnly(True) infolayout.addRow(tedit) winfo.setLayout(infolayout) vlayout.addWidget(winfo, 1) if warguments: vlayout.addWidget(warguments, 2) self.valueArgs[arg.name()] = warguments else: self.valueArgs[arg.name()] = winfo warg.setLayout(vlayout) self.stackedargs.addWidget(warg) argitem = QListWidgetItem(str(arg.name()), self.listargs) def getWidgetFromType(self, arg): warguments = layoutManager() inputype = arg.inputType() predefs = arg.parameters() ptype = arg.parametersType() if ptype == Parameter.Editable: editable = True else: editable = False if inputype == Argument.Single: if arg.type() in (typeId.Node, typeId.Path): warguments.addPath(arg.name(), arg.type(), predefs, self.__nodesSelected, editable) else: warguments.addSingleArgument(arg.name(), predefs, arg.type(), editable) elif inputype == Argument.List: if arg.type() in (typeId.Node, typeId.Path): warguments.addPathList(arg.name(), arg.type(), predefs, self.__nodesSelected) else: warguments.addListArgument(arg.name(), arg.type(), predefs, editable) else: # Argument.Empty (typically, bool arguments) return None return warguments def validateModule(self): # get values args = {} try : for argname, lmanager in self.valueArgs.iteritems(): if lmanager.isEnabled(): arg = self.conf.argumentByName(argname) if arg.type() == typeId.Node and arg.inputType() == Argument.List: plist = lmanager.get(argname) params = [] for param in plist: params.append(self.vfs.getnode(param)) elif arg.type() == typeId.Node and arg.inputType() == Argument.Single: params = self.vfs.getnode(lmanager.get(argname)) elif arg.inputType() == Argument.Empty: params = True else: params = lmanager.get(argname) args[argname] = params genargs = self.conf.generate(args) self.taskmanager = TaskManager() self.taskmanager.add(str(self.nameModule), genargs, ["thread", "gui"]) self.accept() except RuntimeError: err_type, err_value, err_traceback = sys.exc_info() err_trace = traceback.format_tb(err_traceback) err_typeval = traceback.format_exception_only(err_type, err_value) terr = QString() detailerr = QString() for err in err_trace: detailerr.append(err) for errw in err_typeval: terr.append(errw) detailerr.append(err) self.messageBox(terr, detailerr) return def openApplyModule(self, nameModule = None, typeModule = None, nodesSelected = None): self.initAllInformations(nameModule, typeModule, nodesSelected) self.exec_() def argChanged(self, curitem, previtem): self.stackedargs.setCurrentIndex(self.listargs.row(curitem)) def messageBox(self, coretxt, detail): msg = QMessageBox(self) msg.setWindowTitle(self.configureError) msg.setText(self.configureErrorMsg) msg.setInformativeText(coretxt) msg.setIcon(QMessageBox.Critical) msg.setDetailedText(detail) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def translation(self): self.configureError = self.tr("Configuration error") self.configureErrorMsg = self.tr("An error was detected in the configuration") def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) title = self.windowTitle() + ' ' + self.nameModule self.setWindowTitle(title) self.translation() else: QDialog.changeEvent(self, event) class checkBoxWidget(QCheckBox): def __init__(self, parent, info, widget, label): QCheckBox.__init__(self) self.__info = info self.__widget = widget self.setText(label) self.stateChangedWidget(Qt.Unchecked) self.initCallback() def initCallback(self): self.connect(self, SIGNAL("stateChanged(int )"), self.stateChangedWidget) def stateChangedWidget(self, state): if state == Qt.Checked : if self.__widget: self.__widget.setEnabled(1) self.__info.setEnabled(1) else : if self.__widget: self.__widget.setEnabled(0) self.__info.setEnabled(0) dff-1.3.0+dfsg.1/dff/api/gui/dialog/extractor.py000066400000000000000000000111641217176075400212650ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin import os from PyQt4.QtCore import QSize, SIGNAL, pyqtSignature, QEvent from PyQt4.QtGui import QDockWidget, QWidget, QVBoxLayout, QHBoxLayout, QIcon, QComboBox, QPushButton, QSortFilterProxyModel from PyQt4.Qt import * from dff.ui.gui.resources.ui_extractdialog import Ui_ExtractDialog class Extractor(QDialog, Ui_ExtractDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.setupUi(self) self.translation() self.nodes = None self.actions() self.showArgs() self.path = "" self.hide() self.selectedNodes = [] def launch(self, nodes): self.nodes = nodes self.exec_() def getArgs(self): args = {} args["files"] = self.nodes args["recursive"] = self.recurseCheck.isChecked() args["preserve"] = self.preserveTree.isChecked() args["overwrite"] = self.overwriteExisting.isChecked() args["syspath"] = str(unicode(self.syspathLine.text())) return args def actions(self): self.connect(self.buttonBox, SIGNAL("accepted()"), self.verify) self.connect(self.buttonBox, SIGNAL("rejected()"), self.close) def verify(self): if self.syspathLine.text() != "": self.close() self.emit(SIGNAL("filled")) else: msg = QMessageBox(self) msg.setText(self.pathMandatoryText) msg.setIcon(QMessageBox.Warning) msg.setStandardButtons(QMessageBox.Ok) msg.exec_() def showArgs(self): self.connect(self.syspathBrowse, SIGNAL("clicked()"), self.getExtractFolder) def getExtractFolder(self): dialog = QFileDialog(self, self.browseTitleText, "/home") dialog.setFileMode(QFileDialog.DirectoryOnly) dialog.setViewMode(QFileDialog.Detail) ret = dialog.exec_() if ret: self.path = str(dialog.selectedFiles()[0]) self.syspathLine.setText(self.path) return ret def removeIdentical(self, toRemove): res = [] for node in self.nodes: if node.name() not in toRemove: res.append(node) return res def checkIfExist(self): same = [] content = os.listdir(self.path) for node in self.nodes: if node.isFile() and node.hasChildren(): if node.name() + ".bin" in content: same.append(str(node.name() + ".bin")) if node.name() in content: same.append(str(node.name())) if len(same) > 0: msg = QMessageBox() msg.setWindowTitle(self.warningTitleText) msg.setText(self.warningExistText + '\n' + str(self.path)) msg.setInformativeText(self.warningOWText) msg.setIcon(QMessageBox.Warning) items = "".join(s.join(["", "\n"]) for s in same) msg.setDetailedText(items) msg.setStandardButtons(QMessageBox.NoToAll | QMessageBox.YesToAll) msg.setDefaultButton(QMessageBox.NoToAll) ret = msg.exec_() if ret == QMessageBox.NoToAll: self.selectedNodes = self.removeIdentical(same) else: self.selectedNodes = self.nodes else: self.selectedNodes = self.nodes def translation(self): self.pathMandatoryText = self.tr('Extraction path is mandatory') self.browseTitleText = self.tr('Choose the destination folder for extraction') self.warningTitleText = self.tr('Overwrite attempt') self.warningExistText = self.tr('Some selected files or folders already exist in the destination folder') self.warningOWText = self.tr('Overwrite with selected ones ?') def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() else: QDialog.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/api/gui/dialog/selectattributes.py000066400000000000000000000200631217176075400226360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER import os from sets import Set from PyQt4.QtCore import Qt, QSize, SIGNAL, pyqtSignature, QEvent, QCoreApplication, QString from PyQt4.QtGui import QDockWidget, QWidget, QVBoxLayout, QHBoxLayout, QIcon, QComboBox, QPushButton, QDialog, QWizard, QCursor, QMenu, QListWidget, QAbstractItemView, QListWidgetItem from dff.api.vfs.libvfs import VFS, ABSOLUTE_ATTR_NAME from dff.api.types.libtypes import typeId from dff.ui.gui.resources.ui_attributes_selection_dialog import Ui_AttributesSelectionDialog from dff.ui.gui.resources.ui_select_attributes import Ui_SelectAttributesWiz INT_T = [typeId.Int16, typeId.UInt16, typeId.Int32, typeId.UInt16, typeId.Int64, typeId.UInt64] STRING_T = [typeId.String, typeId.Char, typeId.CArray] TIME_T = [typeId.VTime] BOOL_T = [typeId.Bool] class AttributeSelectorMenu(QMenu): def __init__(self, parent): QMenu.__init__(self, parent) action = self.addAction(self.tr("Select")) self.connect(action, SIGNAL("triggered()"), parent.select) action = self.addAction(self.tr("Unselect")) self.connect(action, SIGNAL("triggered()"), parent.unselect) action = self.addAction(self.tr("Select all")) self.connect(action, SIGNAL("triggered()"), parent.selectAll) action = self.addAction(self.tr("Unselect all")) self.connect(action, SIGNAL("triggered()"), parent.unselectAll) class AttributeSelector(QListWidget): def __init__(self, name = None, attributes = [], selectedAttributes = []): QListWidget.__init__(self) self.menu = AttributeSelectorMenu(self) self.setSelectionMode(QAbstractItemView.ExtendedSelection) if name: self.name = name self.attributes = attributes for attribute in self.attributes: item = QListWidgetItem(attribute) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) if attribute in selectedAttributes: item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) self.addItem(item) def selectedAttributes(self): selected = [] for itemId in range(self.count()): item = self.item(itemId) if item.checkState() != Qt.Unchecked: selected.append(str(item.text().toUtf8())) if len(selected): return selected return None def mousePressEvent(self, e): index = self.indexAt(e.pos()) if index.isValid(): item = self.itemAt(e.pos()) if e.button() == Qt.RightButton: self.menu.popup(QCursor.pos()) QListWidget.mousePressEvent(self, e) def select(self): for item in self.selectedItems(): item.setCheckState(Qt.Checked) def unselect(self): for item in self.selectedItems(): item.setCheckState(Qt.Unchecked) def selectAll(self): for itemId in range(self.count()): item = self.item(itemId) item.setCheckState(Qt.Checked) def unselectAll(self): for itemId in range(self.count()): item = self.item(itemId) item.setCheckState(Qt.Unchecked) class SelectAttributesWizard(QWizard, Ui_SelectAttributesWiz): def __init__(self, model, selectedAttributes=None, defaultAttributes = []): QWizard.__init__(self) self.setupUi(self) self.model = model self.selectedAttributes = selectedAttributes self.defaultAttributes = defaultAttributes self.attributes = {} self.setOption(QWizard.DisabledBackButtonOnLastPage) self.connect(self, SIGNAL("currentIdChanged(int)"), self.idChanged) self.connect(self, SIGNAL("updateProgress"), self.updateProgress) self.stop = False def idChanged(self, pageid): if pageid == 0: if len(self.model.selection.get()) == 0: self.selected.setEnabled(False) else: self.selected.setEnabled(True) elif pageid == 1: nextButton = self.button(QWizard.NextButton) nextButton.setEnabled(False) self.progress.setMinimum(0) self.progress.setValue(0) if self.current.isChecked(): self.progress.setMaximum(1) self.setCurrentAvailableAttributes(self.model.currentNode(), self.attributes) elif self.list.isChecked(): if len(self.model.list()): self.progress.setMaximum(len(self.model.list())) self.setAllAvailableAttributes(self.model.list(), self.attributes) else: self.progress.setMaximum(1) self.progress.setValue(1) elif self.selected.isChecked(): nodes = self.model.selection.getNodes() self.progress.setMaximum(len(nodes)) self.setAllAvailableAttributes(nodes, self.attributes) nextButton.setEnabled(True) elif pageid == 2: self.tabWidget.clear() if self.group_type.isChecked(): mode = 0 else: mode = 1 self.generateWidget(self.attributes, mode) def updateProgress(self, node): self.progress.setValue(self.progress.value() + 1) self.currentnode.setText(QString.fromUtf8(node.absolute())) def setAllAvailableAttributes(self, nodelist, attributes): for node in nodelist: QCoreApplication.processEvents() self.setCurrentAvailableAttributes(node, attributes) def setCurrentAvailableAttributes(self, node, attributes): if node != None: attrs = node.attributesNamesAndTypes() for attrname, attrtype in attrs.iteritems(): attributes[attrname] = attrtype self.emit(SIGNAL("updateProgress"), node) else: self.progress.setValue(self.progress.value() + 1) def attributesByTypes(self, attributes): res = {} for path, atype in attributes.iteritems(): if atype not in (typeId.Map, typeId.List): try: l = res[self.getTypeName(atype)] except KeyError: l = [] res[self.getTypeName(atype)] = l l.append(path) return res def getTypeName(self, atype): if atype in STRING_T: return "String" elif atype in INT_T: return "Integer" elif atype in TIME_T: return "Time" elif atype in BOOL_T: return "Boolean" else: return "Other" def attributesByModule(self, attributes): result = {} for attr, atype in attributes.iteritems(): if atype not in (typeId.Map, typeId.List): root = attr.split('.')[0] if not root in result: l = [] result[root] = l else: l = result[root] l.append(attr) return result # 0 : type, 1 : module def generateWidget(self, attrs, mode=0): if mode == 0: attributes = self.attributesByTypes(attrs) else: attributes = self.attributesByModule(attrs) if len(self.defaultAttributes): widget = AttributeSelector("default", self.defaultAttributes, self.selectedAttributes) self.tabWidget.addTab(widget, 'default') for modsource, attr_l in attributes.iteritems(): attr_l.sort() widget = AttributeSelector(modsource, attr_l, self.selectedAttributes) self.tabWidget.addTab(widget, modsource) def getSelectedAttributes(self): result = [] for itab in xrange(self.tabWidget.count()): listwidget = self.tabWidget.widget(itab) cresult = listwidget.selectedAttributes() if cresult != None: result += cresult return result dff-1.3.0+dfsg.1/dff/api/gui/dialog/tagedit.py000066400000000000000000000055751217176075400207040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from random import randint from PyQt4.QtCore import Qt, QString, SIGNAL from PyQt4.QtGui import QWidget, QDialog, QColorDialog, QListWidgetItem, QColor, QColorDialog, QPalette from dff.api.vfs.libvfs import VFS, TagsManager from dff.ui.gui.resources.ui_tagedit import Ui_edittag class TagEditDialog(QDialog, Ui_edittag): def __init__(self, parent = None, tag = None): QDialog.__init__(self, parent) self.setupUi(self) self.VFS = VFS.Get() self.tagsManager = TagsManager.get() self.connect(self.setColorButton, SIGNAL("clicked()"), self.setColor) self.connect(self.tagEdit, SIGNAL("editingFinished()"), self.setName) self.tag = tag if self.tag: self.tagColor = None self.tagName = None self.fill(tag) else: self.tagName = unicode(self.tagEdit.text()) self.tagColor = (randint(0, 255), randint(0, 255), randint(0, 255)) self.setEditColor(QColor(*self.tagColor)) def fill(self, tag): self.setEditName(tag.name()) color = tag.color() qcolor = QColor(color.r, color.g, color.b) self.setEditColor(qcolor) def setEditName(self, name): self.tagEdit.clear() self.tagEdit.insert(QString.fromUtf8(name)) def setEditColor(self, qcolor): palette = QPalette() palette.setColor(QPalette.Base, qcolor) self.tagEdit.setPalette(palette) def setName(self): self.tagName = self.tagEdit.text().toUtf8() def setColor(self): colorDialog = QColorDialog() if self.tag: color = self.tag.color() qcolor = colorDialog.getColor(QColor(color.r, color.g, color.b)) else: qcolor = colorDialog.getColor() if qcolor.isValid(): self.setEditColor(qcolor) self.tagColor = (qcolor.red(), qcolor.green(), qcolor.blue()) def reject(self): QDialog.reject(self) def accept(self): if self.tag: if self.tagName or self.tagColor: if self.tagName: self.tag.setName(unicode(self.tagName, 'UTF-8').encode('UTF-8')) if self.tagColor: self.tag.setColor(*self.tagColor) QDialog.accept(self) return else: try: self.newTag = self.tagsManager.add(unicode(self.tagName, 'UTF-8').encode('UTF-8'), *self.tagColor) except: self.newTag = None QDialog.accept(self) return QDialog.reject(self) return dff-1.3.0+dfsg.1/dff/api/gui/dialog/tagmanager.py000066400000000000000000000147351217176075400213670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from PyQt4.QtCore import Qt, SIGNAL, QString from PyQt4.QtGui import QWidget, QDialog, QListWidgetItem, QColor, QMessageBox from dff.api.vfs.libvfs import VFS, TagsManager from dff.api.gui.dialog.tagedit import TagEditDialog from dff.ui.gui.resources.ui_tags import Ui_Tags class TagItem(QListWidgetItem): def __init__(self, tag = None, count = None): QListWidgetItem.__init__(self) self.nodesCount = count self.__tag = tag def tag(self): return self.__tag def setNodesCount(self, count): self.nodesCount = count def data(self, role): if role == Qt.DisplayRole: if self.nodesCount : return QString.fromUtf8(self.__tag.name() + ' (' + str(self.nodesCount) + ')') else: return QString.fromUtf8(self.__tag.name()) elif role == Qt.BackgroundRole: color = self.__tag.color() return QColor(color.r, color.g, color.b) return QListWidgetItem.data(self, role) class TagManagerDialog(QDialog, Ui_Tags): def __init__(self, parent = None, selectedNodesList = []): QDialog.__init__(self, parent) self.setupUi(self) self.VFS = VFS.Get() self.connect(self.newTagButton, SIGNAL("clicked()"), self.editTag) self.connect(self.deleteTagButton, SIGNAL("clicked()"), self.deleteTag) self.connect(self.addTagNodesButton, SIGNAL("clicked()"), self.addTagNodes) self.connect(self.removeTagNodesButton, SIGNAL("clicked()"), self.removeTagNodes) self.connect(self.selectedTags, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.editTag) self.connect(self.allTags, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.editTag) self.tagsManager = TagsManager.get() self.selectedNodesList = selectedNodesList self.selectedNodes = [] self.fillLists() self.translation() def translation(self): self.msgWarning = self.tr("Warning") self.msgNoNodes = self.tr('No nodes was selected in the browser.') self.msgNoAllTags = self.tr("No tags was selected in the available tags list.") self.msgNoSelectedTags = self.tr("No tags was selected in the selected nodes tags list.") self.msgDefaultTag = self.tr("This is a default tag it cannot be deleted. All tagged VFS nodes was untagged.") self.msgDelete = self.tr("Are you sure ? This will delete this tag for all nodes in the VFS !") def listNodes(self): if len(self.selectedNodes): return self.selectedNodes if len(self.selectedNodesList): self.selectedNodes = self.selectedNodesList labelText = unicode(self.selectedLabel.text().toUtf8(), 'UTF-8') if labelText.find('(') == -1: text = labelText + ' (' + str(len(self.selectedNodes)) + ')' self.selectedLabel.setText(text) return self.selectedNodes def fillLists(self): self.fillAllTags() self.fillNodesTags() def fillNodesTags(self): nodes = self.listNodes() if len(nodes): dicSelectedTags = {} for node in nodes: tags = node.tags() for tag in tags: try: dicSelectedTags[tag.id()] += 1 except KeyError: dicSelectedTags[tag.id()] = 1 for tagId in dicSelectedTags: tag = self.tagsManager.tag(tagId) item = TagItem(tag, dicSelectedTags[tag.id()]) self.selectedTags.addItem(item) def fillAllTags(self): tags = self.tagsManager.tags() for tag in tags: item = TagItem(tag) self.allTags.addItem(item) def accept(self): QDialog.accept(self) def findTagItem(self, listWidget, tagId): for i in xrange(0, listWidget.count()): if listWidget.item(i).tag().id() == tagId: return listWidget.item(i) return None def addTagNodes(self): currentItem = self.allTags.currentItem() if (currentItem): nodes = self.listNodes() tag = currentItem.tag() if len(nodes) == 0: msgBox = QMessageBox(QMessageBox.Warning, self.msgWarning, self.msgNoNodes, QMessageBox.Ok, self) msgBox.exec_() return for node in nodes: node.setTag(tag.id()) item = self.findTagItem(self.selectedTags, tag.id()) if not item: item = TagItem(tag, len(nodes)) self.selectedTags.addItem(item) else: item.setNodesCount(len(nodes)) else: msgBox = QMessageBox(QMessageBox.Warning, self.msgWarning, self.msgNoAllTags, QMessageBox.Ok, self) msgBox.exec_() def removeTagNodes(self): currentItem = self.selectedTags.currentItem() if (currentItem): nodes = self.listNodes() tag = currentItem.tag() for node in nodes: node.removeTag(tag.id()) row = self.selectedTags.row(currentItem) self.selectedTags.takeItem(row) del currentItem else: msgBox = QMessageBox(QMessageBox.Warning, self.msgWarning, self.msgNoSelectedTags, QMessageBox.Ok, self) msgBox.exec_() def editTag(self, item = None): if item: tag = item.tag() else: tag = None dialog = TagEditDialog(self, tag) if dialog.exec_(): if not tag: item = TagItem(self.tagsManager.tag(dialog.newTag)) self.allTags.addItem(item) def deleteTag(self): currentItem = self.allTags.currentItem() msgBox = QMessageBox(QMessageBox.Warning, self.msgWarning, self.msgDelete, QMessageBox.Yes | QMessageBox.No, self) button = msgBox.exec_() if button == QMessageBox.Yes: if currentItem: tag = currentItem.tag() if self.tagsManager.remove(tag.id()) != 0: row = self.allTags.row(currentItem) self.allTags.takeItem(row) del currentItem else: msgBox = QMessageBox(QMessageBox.Warning, self.msgWarning, self.msgDefaultTag, QMessageBox.Ok, self) msgBox.exec_() item = self.findTagItem(self.selectedTags, tag.id()) if item: row = self.selectedTags.row(item) self.selectedTags.takeItem(row) del item else: msgBox = QMessageBox(QMessageBox.Warning, self.msgWarning, self.msgNoAllTags, QMessageBox.Ok, self) msgBox.exec_() dff-1.3.0+dfsg.1/dff/api/gui/model/000077500000000000000000000000001217176075400165365ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/model/CMakeLists.txt000066400000000000000000000011551217176075400213000ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py node_list.py tree.py selection.py ) dff-1.3.0+dfsg.1/dff/api/gui/model/__init__.py000066400000000000000000000011241217176075400206450ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["tree", "node_list", "selection"] dff-1.3.0+dfsg.1/dff/api/gui/model/node_list.py000066400000000000000000000425311217176075400210750ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER from PyQt4.QtCore import SIGNAL, QAbstractItemModel, QModelIndex, QVariant, Qt, QDateTime, QString, QSize from PyQt4.QtGui import QColor, QIcon, QPixmap, QPainter, QStandardItemModel, QStandardItem, QApplication, QCursor, QPalette from dff.api.types.libtypes import Variant, vtime from dff.api.events.libevents import EventHandler from dff.api.vfs.libvfs import VFS, ABSOLUTE_ATTR_NAME, VecNode, VLink from dff.api.types.libtypes import typeId from dff.api.filters.libfilters import Filter from dff.api.gui.thumbnail import Thumbnailer IMAGES = ["bmp", "gif", "jpg", "jpeg", "png", "psd", "tif", "BMP", "GIF", "JPG", "JPEG", "PNG", "PSD", "TIF"] DOCUMENT = ["doc", "docx", "odt", "DOC", "DOCX", "ODT"] SPREADSHEET = ["xlsx", "xls", "ods", "XLSX", "XLS", "ODF"] VIDEO = ["wmv", "mpg", "mpg4", "mov", "avi", "3gp", "3ga", "asf", "3GA", "WMV", "MOV", "MPG", "MPG4", "AVI", "3GP"] AUDIO = ["wav", "mp3", "wma", "m4a", "aif", "mid", "mpa", "WAV", "MP3", "WMA", "M4A", "AIF", "MID", "MPA"] ARCHIVES = ["zip", "rar", "7zip", "gz", "ZIP", "RAR", "7ZIP", "GZ"] class NodeListModel(QAbstractItemModel): def __init__(self, selection): QAbstractItemModel.__init__(self) self.__list = [] self.__rows = [] self.__current_row = 0 self.__row_selected = 0 self.__thumb = True self.__visible_rows = 0 self.__visible_cols = 0 self.selection = selection self.setDefaultAttributes() self.connectSignals() self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.thumbnailUpdate) self.headerorder = {0:0} def thumbnailUpdate(self, node, pixmap): currentRow = self.currentRow() visibleRow = self.visibleRows() nodeList = self.list() currentList = nodeList[currentRow:currentRow + visibleRow] index = 0 for cnode in currentList: if str(long(node.this)) == str(long(cnode.this)): modelIndex = self.index(index, 0) self.emit(SIGNAL("dataChanged"), modelIndex, modelIndex) index += 1 def connectSignals(self): self.connect(self, SIGNAL("appendList"), self.appendList) self.connect(self, SIGNAL("changeList"), self.changeList) def setData(self, index, value, role): """ \reimp Set the data which value is `value` at index `index` with role `role`. \return `True` if no error occured, `False` otherwise. """ if not index.isValid(): return QVariant() column = index.column() if role == Qt.CheckStateRole: if column == HNAME: node = self.VFS.getNodeFromPointer(index.internalId()) if value == Qt.Unchecked: if (long(node.this), 1) in self.checkedNodes: self.checkedNodes.remove((long(node.this), 1)) else: self.checkedNodes.add((long(node.this) , 1)) QAbstractItemModel.setData(self, index, value, role) return True def changeList(self, nodelist): """ Reset current list and set an existing node list to the model""" if nodelist != None: self.__list = [] self.row_selected = 0 self.__current_row = 0 try: self.__list = nodelist except: print "Error while setting new node List" # Sort list and refresh it self.sort(self.headerorder.keys()[0], self.headerorder[self.headerorder.keys()[0]]) self.emit(SIGNAL("maximum"), len(self.__list)) self.select(self.__current_row) def appendList(self, node): """ Append a new node to the existing model's list and emit an appended signal with the new size. """ if node != None: try: self.__list.append(node) self.emit(SIGNAL("nodeAppended")) self.emit(SIGNAL("maximum"), len(self.__list)) self.refresh(self.__current_row) except: print "Error while appending node" return def defaultAttributes(self): return self.__default_attributes def clearList(self): self.__list = [] self.__current_row = 0 self.refresh(self.__current_row) def columnCount(self, index): attrs = self.availableAttributes() return len(attrs) def data(self, index, role): attributes = self.availableAttributes() if not index.isValid(): return QVariant() if index.row() > len(self.__list) or index.row() < 0: return QVariant() try: node = self.__rows[index.row()] except: return QVariant() if role == Qt.DisplayRole : attrpath = str(unicode(attributes[index.column()]).encode('utf-8')) if attrpath == "name": return QVariant(QString.fromUtf8(node.name())) elif attrpath == "size": return QVariant(node.size()) elif attrpath == "extension": return QVariant(QString.fromUtf8(node.extension())) elif attrpath == "path": if isinstance(node, VLink): return QVariant(QString.fromUtf8(node.linkPath())) else: return QVariant(QString.fromUtf8(node.path())) elif attrpath == "absolute": if isinstance(node, VLink): return QVariant(QString.fromUtf8(node.linkAbsolute())) else: return QVariant(QString.fromUtf8(node.absolute())) elif attrpath == "module": if node.fsobj(): return QVariant(QString.fromUtf8(node.fsobj().name)) return QVariant() elif attrpath == "has children": if isinstance(node, VLink): return QVariant(node.linkHasChildren()) else: return QVariant(node.hasChildren()) elif attrpath == "child count": if isinstance(node, VLink): return QVariant(node.linkChildCount()) else: return QVariant(node.childCount()) elif attrpath == "is deleted": return QVariant(node.isDeleted()) else: try : val = node.attributesByName(attrpath, ABSOLUTE_ATTR_NAME) except Exception as e: print "NodeListModel data can't get attribute " + attrpath + " by name " + str(e) return QVariant() if len(val) == 1: if val[0].type() == typeId.VTime: vtime = val[0].value() if vtime: return QVariant(str(vtime.get_time())) elif val[0].type() == typeId.String: return QVariant(QString.fromUtf8(val[0].value())) else: return QVariant(val[0].value()) if role == Qt.ToolTipRole : return QVariant(QString.fromUtf8(node.name())) # Display icons if (role == Qt.DecorationRole) and (attributes[index.column()] == "name"): pixmap = None if self.__thumb: if self.thumbnailer.isThumbnailable(node): pixmap = self.thumbnailer.generate(node) if not pixmap: pixmap = QPixmap(":file_temporary.png") if not pixmap: pixmap = self.getIconPixmap(node) if not pixmap: pixmap = QPixmap(node.icon()) if isinstance(node, VLink): pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) linkPixmap = QPixmap(":vlink") painter.drawPixmap(0, 0, linkPixmap) painter.end() elif node.hasChildren(): try: pfsobj = node.children()[0].fsobj().this except AttributeError: pfsobj = None try: nfsobj = node.fsobj().this except AttributeError: nfsobj = None if pfsobj != nfsobj: pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) rootPixmap = QPixmap(":root") painter.drawPixmap(0, 0, rootPixmap) painter.end() return QVariant(QIcon(pixmap)) if role == Qt.BackgroundRole: if index.row() == self.activeSelection(): palette = QPalette().color(QPalette.Highlight) return QVariant(QColor(palette)) if role == Qt.ForegroundRole: if index.row() == self.activeSelection(): palette = QPalette().color(QPalette.HighlightedText) return QVariant(QColor(palette)) if node.isDeleted(): return QVariant(QColor(Qt.red)) if (role == Qt.CheckStateRole) and (attributes[index.column()] == "name"): if long(node.this) in self.selection.get(): return Qt.Checked else: return Qt.Unchecked return QVariant() def setThumb(self, state): self.__thumb = state def getIconPixmap(self, node): ext = self.getExtension(node) if ext != None: if ext in IMAGES: return QPixmap(":image.png") elif ext in AUDIO: return QPixmap(":sound.png") elif ext == "pdf": return QPixmap(":pdf.png") elif ext in DOCUMENT: return QPixmap(":document.png") elif ext in VIDEO: return QPixmap(":video.png") elif ext in ARCHIVES: return QPixmap(":zip") elif ext in SPREADSHEET: return QPixmap(":spreadsheet.png") else: return None def getExtension(self, node): name = node.name() sext = name.split(".") if len(sext) > 1: return sext[len(sext) - 1] else: return None def getNode(self, row): try: node = self.__list[row] if node: return node else: return None except IndexError: return None def index(self, row, column, parent = QModelIndex()): if not self.hasIndex(row, column, parent): return QModelIndex() if not parent.isValid(): index = self.createIndex(row, column, self.__rows[row]) return index return QModelIndex() def parent(self, index): return QModelIndex() def refresh(self, start): llist = len(self.__list) if start < 0: rstart = 0 elif (start >= llist): # End of list rstart = llist - (self.__visible_rows) if rstart < 0: rstart = 0 # elif ((llist - start) <= self.__visible_rows + 1): # rstart = self.__current_row # if rstart < 0: # rstart = 0 else: rstart = start # End of List range if (rstart + self.__visible_rows) > len(self.__list): end = len(self.__list) else: end = rstart + self.__visible_rows + 1 self.resetDisplay() try: tmplist = self.__list[rstart:end] except IndexError: return try: for nodeId in range(0, len(tmplist)): if tmplist[nodeId] != None: self.__rows.append(tmplist[nodeId]) self.emit(SIGNAL("layoutAboutToBeChanged()")) self.emit(SIGNAL("layoutChanged()")) if self.__current_row >= 0: self.__current_row = rstart else: self.__current_row = 0 self.emit(SIGNAL("current"), self.__current_row) except IndexError: print "Error while refreshing model" pass def resetDisplay(self): if len(self.__rows) > 0: self.__rows = [] self.emit(SIGNAL("layoutAboutToBeChanged()")) self.emit(SIGNAL("layoutChanged()")) def rowCount(self, parent = None): return len(self.__rows) def currentRow(self): return self.__current_row def size(self): return len(self.__list) def setVisibleRows(self, rows): self.__visible_rows = rows self.emit(SIGNAL("maximum"), len(self.__list)) if self.__visible_rows > self.size(): self.emit(SIGNAL("hideScroll")) self.refresh(self.__current_row) def visibleRows(self): return self.__visible_rows def seek(self, position, where = 0): if where == 0: self.refresh(position) elif where == 1: pos = self.__current_row + position self.refresh(pos) else: self.refresh(self.__current_row) def select(self, row): """ Set absolute selected row id in model's list """ absrow = self.__current_row + row try: node = self.__list[absrow] self.__row_selected = absrow self.refresh(self.__current_row) self.emit(SIGNAL("nodeListClicked"), Qt.NoButton) return True except: return False def activeSelection(self): """ Return relative selected row id """ return self.__row_selected - self.__current_row def currentNode(self): try: node = self.__list[self.__row_selected] if node != None: return node else: return None except: return None def nodeSelected(self): nodes = [] nodes.append(self.__list[self.__row_selected]) return nodes def setDefaultAttributes(self): self.__default_attributes = ["name", "size","tags", "path", "extension", "absolute", "module", "has children", "child count", "is deleted"] self.setSelectedAttributes(["name", "size", "tags", "path"]) def setSelectedAttributes(self, attributes): self.__selected_attributes = attributes self.refresh(self.__current_row) def selectedAttributes(self): return self.__selected_attributes def availableAttributes(self): attrs = self.selectedAttributes()[:] return attrs def setHeaderData(self, section, orientation, value, role): self.emit(SIGNAL("layoutAboutToBeChanged()")) QAbstractItemModel.setHeaderData(self, section, orientation, value, role) self.emit(SIGNAL("layoutChanged()")) def headerData(self, section, orientation, role=Qt.DisplayRole): if role != Qt.DisplayRole: return QVariant() if orientation == Qt.Horizontal: attrs = self.availableAttributes() return QVariant(attrs[section]) def sort(self, column, order): """ Sort model's list and check. """ self.headerorder.clear() self.headerorder[column] = order QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) if order == Qt.DescendingOrder: Reverse = True else: Reverse = False attrs = self.availableAttributes() try: attrpath = str(unicode(attrs[column]).encode('utf-8')) except IndexError: QApplication.restoreOverrideCursor() self.headerorder.clear() self.headerorder = {0:0} self.refresh(0) self.select(0) return if isinstance(self.__list, VecNode): tmplist = [] for i in range(0, len(self.__list)): tmplist.append(self.__list[i]) self.__list = tmplist if attrpath in self.__default_attributes: if attrpath == "name": self.__list = sorted(self.__list, key=lambda Node: Node.name(), reverse=Reverse) elif attrpath == "size": self.__list = sorted(self.__list, key=lambda Node: Node.size(), reverse=Reverse) elif attrpath == "extension": self.__list = sorted(self.__list, key=lambda Node: Node.extension(), reverse=Reverse) elif attrpath == "path": self.__list = sorted(self.__list, key=lambda Node: Node.path(), reverse=Reverse) elif attrpath == "absolute": self.__list = sorted(self.__list, key=lambda Node: Node.absolute(), reverse=Reverse) elif attrpath == "module": self.__list = sorted(self.__list, cmp=self.cmp_fsobj, key=lambda Node: Node.fsobj(), reverse=Reverse) elif attrpath == "has children": self.__list = sorted(self.__list, key=lambda Node: Node.hasChildren(), reverse=Reverse) elif attrpath == "child count": self.__list = sorted(self.__list, key=lambda Node: Node.childCount(), reverse=Reverse) elif attrpath == "is deleted": self.__list = sorted(self.__list, key=lambda Node: Node.isDeleted(), reverse=Reverse) elif attrpath == "tags": self.__list = sorted(self.__list, key=lambda Node: len(Node.tags()), reverse=Reverse) else: self.__list = sorted(self.__list, cmp=self.cmp_none, key=lambda Node: self.attributesByName(Node, attrpath, ABSOLUTE_ATTR_NAME), reverse=Reverse) QApplication.restoreOverrideCursor() self.refresh(0) self.select(0) return def cmp_fsobj(self, x, y): try: return cmp(x.name, y.name) except AttributeError: if x == y == None: return 0 elif x == None: return -1 elif y is None: return 1 def cmp_none(self,x, y): try: return cmp(x, y) except TypeError: if x == y == None: return 0 elif x == None: return -1 elif y is None: return 1 def attributesByName(self, node, attrpath, ABSOLUTE_ATTR_NAME): val = node.attributesByName(attrpath, ABSOLUTE_ATTR_NAME) if len(val) == 1: if val[0].type() == typeId.VTime: vtime = val[0].value() if vtime: return vtime.get_time() else: return val[0].value() def list(self): return self.__list def allListChecked(self): checked = self.selection.get() for node in self.__list: if not long(node.this) in checked: return False return True def selectAll(self): for node in self.__list: self.selection.add(node) def unselectAll(self): for node in self.__list: self.selection.rm(node) dff-1.3.0+dfsg.1/dff/api/gui/model/selection.py000066400000000000000000000054311217176075400211000ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4 import QtCore, QtGui from PyQt4.QtCore import QObject, SIGNAL, Qt from PyQt4.QtGui import QApplication, QCursor from dff.api.vfs.libvfs import VFS, VLink class SelectionManager(QObject): def __init__(self): QObject.__init__(self) self.VFS = VFS.Get() self._selection = set() def add(self, node): if node.isDir() or node.hasChildren(): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.recurseNodes(node, True) QApplication.restoreOverrideCursor() else: self._selection.add(long(node.this)) self.emit(SIGNAL("selectionChanged()")) def rm(self, node): if node.isDir() or node.hasChildren(): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.recurseNodes(node, False) QApplication.restoreOverrideCursor() else: try: self._selection.remove(long(node.this)) except KeyError: pass self.emit(SIGNAL("selectionChanged()")) def get(self): return self._selection def childrenChecked(self, node): children = node.children() for child in children: if not long(child.this) in self._selection: return False return True def isChecked(self, node): if long(node.this) in self._selection: return True return False def getNodes(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) nodes = [] for nodeid in self._selection: node = self.VFS.getNodeFromPointer(nodeid) if isinstance(node, VLink): node = node.linkNode() nodes.append(node) QApplication.restoreOverrideCursor() return nodes def recurseNodes(self, node, add): if add: self._selection.add(long(node.this)) else: try: self._selection.remove(long(node.this)) except KeyError: pass if node.hasChildren(): childs = node.children() for child in childs: self.recurseNodes(child, add) def clear(self): self._selection.clear() dff-1.3.0+dfsg.1/dff/api/gui/model/tree.py000066400000000000000000000251131217176075400200510ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # Romain Bertholon # import re from Queue import * from PyQt4.QtCore import SIGNAL, QAbstractItemModel, QModelIndex, QVariant, Qt, QDateTime, QSize, QThread, QMutex, QSemaphore, QString, Qt from PyQt4.QtGui import QColor, QIcon, QImage, QImageReader, QPixmap, QPixmapCache, QStandardItemModel, QStandardItem, QStyledItemDelegate, QBrush, QPen, QPalette, QPainter from PyQt4 import QtCore from dff.api.types.libtypes import Variant, vtime from dff.api.vfs.libvfs import VFS from dff.api.events.libevents import EventHandler class TreeModel(QStandardItemModel, EventHandler): def __init__(self, __parent = None, selection=None): QStandardItemModel.__init__(self, __parent) EventHandler.__init__(self) self.__parent = __parent self.VFS = VFS.Get() # init translation self.translation() self.indexmap = {} self.createRootItems() self.currentIndex = self.root_item self.ch = True self.selection = selection self.VFS.connection(self) # keep track of index - node pointers self.connect(self, SIGNAL("refreshModel"), self.refreshModel) def createRootItems(self): # Add Root children items (bookmarks, logical etc.) self.root_item = self.invisibleRootItem() self.root_node = self.VFS.GetNode("/") tmp = self.root_node.children() item_list = [] for i in tmp: node_item = QStandardItem(i.name()) node_item.setData(QVariant(long(i.this)), Qt.UserRole + 1) node_item.setData(QVariant(False), Qt.UserRole + 2) item_list.append(node_item) self.indexmap[long(i.this)] = node_item if len(item_list): self.root_item.appendRows(item_list) def headerData(self, section, orientation, role=Qt.DisplayRole): """ \reimp The only column is the `name` column. \return QVariant("Name") if the role is Qt.DisplatRole, an invalid QVariant otherwise. """ if role != Qt.DisplayRole: return QVariant() else: return QVariant(self.nameTr) def data(self, index, role): """ \reimp Nodes' pointers are encapsulated in QStandardItem (role : Qt.UserRole + 1). Most of the data can only be retrieved only if the node is retrieved: * The node name * The node icon * ... To do so, the TreeModel.data() method calls the QStandardItemModel.data() method by passing the `index` parameter and `Qt.UserRole + 1` or `Qt.UserRole + 2` to it. In the second case, it retrieves a boolean used to know if the node is already expended and returns directly. \param index the index of the data we want to get \param role the role of the data we want to retrieve \return a QVariant containing the data, or an invalid QVariant if the data could not be retrieved. """ if not index.isValid(): return QVariant() # Qt.UserRole + 2 contain a boolean indicating if the node has already been expanded # in the tree. if role == Qt.UserRole + 3: return QStandardItemModel.data(self, index, role) if role == Qt.UserRole + 2: return QStandardItemModel.data(self, index, role) # call QStandardItemModel.data method with a Qt.UserRole + 1 to get the pointer on the node # (returns a invalid QVariant if the node or the data is None) data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return data # getting the node or returning an invalid QVariant() if the node is not valid node = self.VFS.getNodeFromPointer(data.toULongLong()[0]) if node == None: return QVariant() # if role == UserRole + 1, it means that the node itself must be returned (the pointer # on the node, encapsulated in a QVariant() if role == (Qt.UserRole + 1): return data # in other cases, returns the requires data : icon, color, etc. or an invalid QVariant() # if the role does not correpond to anything. if role == Qt.DisplayRole : return QVariant(QString.fromUtf8(node.name())) if role == Qt.DecorationRole: pixmap = QPixmap(node.icon()) if node.hasChildren(): try: pfsobj = node.children()[0].fsobj().this except AttributeError: pfsobj = None try: nfsobj = node.fsobj().this except AttributeError: nfsobj = None if pfsobj != nfsobj: pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) rootPixmap = QPixmap(":root") painter.drawPixmap(0, 0, rootPixmap) painter.end() return QVariant(QIcon(pixmap)) if role == Qt.BackgroundRole: if index == self.currentIndex: palette = QPalette().color(QPalette.Highlight) return QVariant(QColor(palette)) if role == Qt.ForegroundRole: if (index == self.currentIndex) and not node.isDeleted(): palette = QPalette().color(QPalette.HighlightedText) return QVariant(QColor(palette)) if node.isDeleted(): return QVariant(QColor(Qt.red)) if self.ch == True: if role == Qt.CheckStateRole: if index.column() == 0: if long(node.this) in self.selection.get(): return Qt.Checked else: return Qt.Unchecked return QVariant() def setData(self, index, value, role): """ \reimp Set the data which value is `value` at index `index` with role `role`. \return `True` if no error occured, `False` otherwise. """ if self.ch == True: if role == Qt.CheckStateRole: ret = QStandardItemModel.setData(self, index, value, role) if ret == False: return False data = QStandardItemModel.data(self, index, Qt.UserRole + 1) if not data.isValid(): return False self.emit(SIGNAL("stateChanged"), index) return True def columnCount(self, parent = QModelIndex()): """ \reimp The number of columns of the model, which is always set to `1` in this case. \return `1` """ return 1 def hasChildren(self, parent): if parent.isValid(): item = self.itemFromIndex(parent) node = self.getNodeFromItem(item) if node != None: tmp = node.children() for i in tmp: if i.isDir() or i.hasChildren(): return True elif self.root_item.index().internalId() == parent.internalId(): return True else: return False return False def setCurrentIndex(self, old, new): self.data(old, Qt.BackgroundRole) self.data(old, Qt.ForegroundRole) self.data(new, Qt.BackgroundRole) self.data(new, Qt.ForegroundRole) self.currentIndex = new def flags(self, flag): """ \reimp \returns the flag set in the model. """ return (Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) def getParentNodeList(self, node): parents = [] parent = node while long(parent.this) != long(self.root_node.this): if parent != None: parents.append(parent) parent = parent.parent() else: break parents.reverse() return parents def Event(self, e): """ Add e.value, which is a Variant containing a Node, in the tree (only if it has children or is a directory). """ value = e.value if value == None: return node = value.value() if node == None: return self.emit(SIGNAL("refreshModel"), node) def getItemFromNode(self, node): for nodeptr, item in self.indexmap.iteritems(): if long(node.this) == nodeptr: return item return None def refreshModel(self, node): parents = self.getParentNodeList(node) for parent in parents: try: item = self.indexmap[long(parent.this)] if item.rowCount() !=0: dircount = self.dirCount(parent) if item.rowCount() != dircount: new_nodes = self.getItemsToInsert(item, parent) if len(new_nodes) == (dircount - item.rowCount()): self.emit(SIGNAL("layoutAboutToBeChanged()")) self.insertRows(item, new_nodes) self.emit(SIGNAL("layoutChanged()")) else: children = parent.children() self.emit(SIGNAL("layoutAboutToBeChanged()")) self.insertRows(item, children) self.emit(SIGNAL("layoutChanged()")) except KeyError: continue def getChildrenDirectories(self, parent): children = parent.children() childrendir = [] for child in children: if child.isDir() or child.hasChildren(): childrendir.append(child) return childrendir def getItemsToInsert(self, item, parent): children = self.getChildrenDirectories(parent) new_nodes = [] for child in children: founded = False for childitem in range(0, item.rowCount()): node = self.getNodeFromItem(item.child(childitem)) if node != None: if long(node.this) == long(child.this): founded = True if not founded: new_nodes.append(child) return new_nodes def getNodeFromItem(self, item): try: index = self.indexFromItem(item) node = self.getNodeFromIndex(index) return node except: print "Exeption:GetNodeFromItem" return None def getNodeFromIndex(self, index): try: ptr = self.data(index, Qt.UserRole + 1).toULongLong()[0] node = self.VFS.getNodeFromPointer(ptr) if node == None: return None return node except: print "Exeption:GetNodeFromIndex" return None def dirCount(self, node): count = 0 children = node.children() for child in children: if child.isDir() or child.hasChildren(): count += 1 return count def createItem(self, node): new_item = QStandardItem(node.name()) new_item.setData(long(node.this), Qt.UserRole + 1) self.indexmap[long(node.this)] = new_item return new_item def insertRows(self, item_parent, node_list): for child in node_list: if child.isDir() or child.hasChildren(): new_item = self.createItem(child) item_parent.appendRow(new_item) def translation(self): """ Used for translating the framework. """ self.nameTr = self.tr('Name') dff-1.3.0+dfsg.1/dff/api/gui/thumbnail.py000066400000000000000000000213161217176075400177760ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import re from PyQt4.QtCore import pyqtSlot, Qt, QObject, SIGNAL, SLOT, QSize, QThread, QEvent, QThreadPool, QRunnable, QEventLoop from PyQt4.QtGui import QApplication, QImage, QPixmap, QPixmapCache, QPainter from dff.api.types.libtypes import Variant, VMap from dff.api.vfs.libvfs import AttributesHandler, Node try: from dff.api.gui.video import video VIDEO_API_EXISTS = True except ImportError as e: VIDEO_API_EXISTS = False print "Can't load video api : " + str(e) class CorruptedPictureHandler(AttributesHandler): def __init__(self): AttributesHandler.__init__(self, "Corrupted") self.__disown__() self.nodes = [] def setAttributes(self, node): self.nodes.append((long(node.this))) node.registerAttributes(self) def isCorrupted(self, node): if long(node.this) in self.nodes: return True return False def attributes(self, node): attr = VMap() attr["Picture"] = Variant("Corrupted") return attr class Scaler(QObject): def __init__(self): QObject.__init__(self) self.img = None self.imageMaximumSize = 100000000 #don't try to create thumbnail for image larger than size (To avoid false positive) def event(self, event): if (event.type() == 11003): try: self.convert(event) except Exception as e: print 'Thumbnailer event exceptions ' + e self.emit(SIGNAL("scaledFinished"), event.config, None) return True return QObject.event(self, event) def convert(self, event): node = event.config.node buff = "" if (str(node.dataType()).find('video') != -1): if VIDEO_API_EXISTS: try: md = video.VideoDecoder(node) if event.config.frames == 1: img = md.thumbnailAtPercent(event.config.percent, event.config.size) else: img = QImage(event.config.size * event.config.frames / 2, event.config.size * 2, 4) img.fill(0) painter = QPainter(img) for y in range(0, 2): try: for x in range(1, event.config.frames/2 + 1): try: frame = md.thumbnailAtPercent((x + ((event.config.frames/2) * y)) * (100/event.config.frames), event.config.size) painter.drawImage((x - 1) * event.config.size, y * event.config.size , frame) except RuntimeError, e: raise e except RuntimeError: break painter.end() self.emit(SIGNAL("scaledFinished"), event.config, img) return except : pass self.emit(SIGNAL("scaledFinished"), event.config, None) return img = QImage() load = None buff = "" if str(node.dataType()).find('jpeg') != -1 and node.size() < self.imageMaximumSize: try: buff = self.jpegInternalThumbnail(node) if (buff): load = img.loadFromData(buff, 'jpeg') if load == False: buff = "" except IOError: buff = "" if not len(buff) and node.size() < self.imageMaximumSize: try: f = node.open() buff = f.read() f.close() load = img.loadFromData(buff) except IOError: load = False if load: img = img.scaled(QSize(event.config.size, event.config.size), Qt.KeepAspectRatio, Qt.FastTransformation) self.emit(SIGNAL("scaledFinished"), event.config, img) return self.emit(SIGNAL("scaledFinished"), event.config, None) return def jpegInternalThumbnail(self, node): buff = "" if node.size() > 6: try: file = node.open() head = file.find("\xff\xd8\xff", "", 3) if head > 0 and head < node.size(): foot = file.find("\xff\xd9", "", long(head)) if foot > 0 and foot < node.size(): file.seek(head) buff = file.read(foot + 2 - head) file.close() except IOError: return "" return buff class ScaleConfig(object): def __init__(self, node, size = 128, percent = 10, frames = 1): self.node = node self.size = size self.percent = percent self.frames = frames def __hash__(self): return 1 def __eq__(self, other): if long(self.node.this) == long(other.node.this) and self.size == other.size and self.percent == other.percent and self.frames == other.frames: return True else: return False def __str__(self): return str(str(long(self.node.this)) + str(self.size) + str(self.percent) + str(self.frames)) class ScaleEvent(QEvent): Type = QEvent.Type(QEvent.registerEventType()) def __init__(self, config): QEvent.__init__(self, 11003) self.config = config class ThumbnailManager(object): __instance = None def __init__(self): if ThumbnailManager.__instance is None: ThumbnailManager.__instance = ThumbnailManager.__ThumbnailManager() def __getattr__(self, attr): return getattr(self.__instance, attr) class __ThumbnailManager(QObject): def __init__(self): QObject.__init__(self) self.pixmapCache = QPixmapCache() self.pixmapCache.setCacheLimit(61440) self.thread = QThread() self.scaler = Scaler() self.scaler.moveToThread(self.thread) self.connect(self.scaler, SIGNAL("scaledFinished"), self.finished) self.thread.start() self.thumbnailers = [] self.handledRequest = set() self.corruptionHandler = CorruptedPictureHandler() self.pixmapCorrupted = QPixmap(":file_broken.png") def register(self, thumbnailer): self.thumbnailers.append(thumbnailer) def unregister(self, thumbnailer): try: self.thumbnailers.remove(thumbnailer) except: pass def generate(self, config): pixmap = self.pixmapCache.find(str(config)) if pixmap: return pixmap elif self.corruptionHandler.isCorrupted(config.node): return self.pixmapCorrupted else: if config not in self.handledRequest: QApplication.postEvent(self.scaler, ScaleEvent(config)) self.handledRequest.add(config) def finished(self, config, scaledImage): if scaledImage: pixmap = QPixmap().fromImage(scaledImage) self.pixmapCache.insert(str(config), pixmap) self.emitUpdate(config, pixmap) else: self.corruptionHandler.setAttributes(config.node) self.emitUpdate(config, self.pixmapCorrupted) def emitUpdate(self, config, pixmap): for thumbnailer in self.thumbnailers: try: if thumbnailer.request(config): thumbnailer.emit(SIGNAL("ThumbnailUpdate"), config.node, pixmap) thumbnailer.requestRemove(config) except: pass try: self.handledRequest.remove(config) except KeyError: pass class ThumbnailBlockingLoop(QEventLoop): def __init__(self): QEventLoop.__init__(self) def quit(self): return @pyqtSlot(Node, QPixmap) def quit(self, node, pixmap): QEventLoop.quit(self) return pixmap class Thumbnailer(QObject): compatibleType = re.compile("(JPEG|JPG|jpg|jpeg|GIF|gif|bmp|BMP|png|PNG|pbm|PBM|pgm|PGM|ppm|PPM|xpm|XPM|xbm|XBM|TIFF|tiff|video).*", re.IGNORECASE) def __init__(self): QObject.__init__(self) self.thumbnailManager = ThumbnailManager() self.thumbnailManager.register(self) self.requests = set() @staticmethod def isThumbnailable(node): if Thumbnailer.compatibleType.search(str(node.dataType())) != None: return True return False def generate(self, node, iconSize = 128, percent = 10, frames = 1, blocking = False): if blocking: self.blockingLoop = QEventLoop() self.blockingLoop.connect(self, SIGNAL("ThumbnailUpdate"), self.blockingUpdate) config = ScaleConfig(node, iconSize, percent, frames) self.requests.add(config) pixmap = self.thumbnailManager.generate(config) if pixmap: return pixmap if blocking: self.blockingLoop.exec_() return self.pixmap def blockingUpdate(self, node, pixmap): self.pixmap = pixmap self.blockingLoop.quit() def requestRemove(self, config): try: self.requests.remove(config) except: pass def request(self, config): if config in self.requests: return True else: return False def unregister(self): self.thumbnailManager.unregister(self) dff-1.3.0+dfsg.1/dff/api/gui/video/000077500000000000000000000000001217176075400165445ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/video/CMakeLists.txt000066400000000000000000000013671217176075400213130ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob dff_cpp_api(video CPP_FILES video.cpp SWIG_FILE video.i INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} LINK_LIBRARIES exceptions types vfs ${FFMPEG_LIBRARIES} EXTRA_FILES __init__.py NO_SWIG_LIB_PREFIX 1 ) dff-1.3.0+dfsg.1/dff/api/gui/video/__init__.py000066400000000000000000000010721217176075400206550ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ['video'] dff-1.3.0+dfsg.1/dff/api/gui/video/video.cpp000066400000000000000000000315551217176075400203670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ /* * Most of code come from libffmpegthumbnailer by * Dirk Vanden Boer */ #include "node.hpp" #include "vfile.hpp" #include "video.hpp" #include Image::Image(uint8_t* idata, uint32_t size, int32_t width, int32_t height) { this->_data.size = size; this->_data.buff = (char*)malloc(size); memcpy(this->_data.buff, idata, size); this->_width = width; this->_height = height; } Image::~Image(void) { free(this->_data.buff); } ImageData Image::data(void) { return (this->_data); } int32_t Image::width(void) { return (this->_width); } int32_t Image::height(void) { return (this->_height); } extern "C" { int FFMpegRead(void* opaque, uint8_t* buf, int size) { VFile* file = (VFile*)opaque; if (file == NULL) return (-1); return (file->read(buf, size)); } int64_t FFMpegSeek(void* opaque, int64_t offset, int whence) { VFile* file = (VFile*)opaque; if (file == NULL) return (-1); if (whence == AVSEEK_SIZE) return ((int64_t)file->node()->size()); return ((int64_t)file->seek((uint64_t)offset, whence)); } } VideoDecoder::VideoDecoder(Node* node) { this->_file = NULL; this->_buffer = NULL; this->_IOContext = NULL; this->_formatContext = NULL; this->_codecContext = NULL; this->_codec = NULL; this->_stream = NULL; this->_frame = NULL; this->_packet = NULL; this->_videoStream = -1; this->_frameBuffer = NULL; try { if ((node != NULL) && (node->size() > 0)) { this->_file = node->open(); this->_buffer = (unsigned char *)av_malloc(4096*640); if (this->_buffer == NULL) { this->_clear(); throw std::string("Can't allocate buffer"); } } this->_IOContext = avio_alloc_context(this->_buffer, 4096*640, 0, this->_file, FFMpegRead, NULL, FFMpegSeek); } catch (...) { this->_clear(); av_free(this->_buffer); throw std::string("Error can't init class"); } av_register_all(); avcodec_register_all(); av_log_set_level(-8); this->_formatContext = avformat_alloc_context(); this->_formatContext->pb = this->_IOContext; if (avformat_open_input(&(this->_formatContext), node->name().c_str(), NULL, NULL) != 0) { this->_clear(); throw std::string("can't open input stream"); } if (av_find_stream_info(this->_formatContext) < 0) { this->_clear(); throw std::string("can't find video info"); } this->_initializeVideo(); this->_frame = avcodec_alloc_frame(); } VideoDecoder::~VideoDecoder() { this->_clear(); } void VideoDecoder::_clear(void) { //error in ffmpeg av_close_input_file fail to free IOContext buff causing memory leak //maybe didn't find the AVFMT_FLAG_CUSTOM_IO if (this->_IOContext->buffer) { av_free(this->_IOContext->buffer); this->_IOContext->buffer = NULL; } if (this->_IOContext) { av_free(this->_IOContext); this->_IOContext = NULL; } if (this->_codecContext) { avcodec_close(this->_codecContext); this->_codecContext = NULL; } if (this->_formatContext) { av_close_input_file(this->_formatContext); this->_formatContext = NULL; } if (this->_codec) //return by avcodec_find_decoder not allocated ? this->_codec = NULL; if (this->_stream) this->_stream = NULL; if (this->_frame) av_free(this->_frame); if (this->_frameBuffer) av_free(this->_frameBuffer); if (this->_packet) { av_free_packet(this->_packet); delete this->_packet; this->_packet = NULL; } if (this->_file) this->_file->close(); delete this->_file; } void VideoDecoder::_convertAndScaleFrame(PixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight) { this->_calculateDimensions(scaledSize, maintainAspectRatio, scaledWidth, scaledHeight); #ifdef LATEST_GREATEST_FFMPEG // Enable this when it hits the released ffmpeg version SwsContext* scaleContext = sws_alloc_context(); if (scaleContext == NULL) throw std::logic_error("Failed to allocate scale context"); av_set_int(scaleContext, "srcw", this->_codecContext->width); av_set_int(scaleContext, "srch", this->_codecContext->height); av_set_int(scaleContext, "src_format", this->_codecContext->pix_fmt); av_set_int(scaleContext, "dstw", scaledWidth); av_set_int(scaleContext, "dsth", scaledHeight); av_set_int(scaleContext, "dst_format", format); av_set_int(scaleContext, "sws_flags", SWS_BICUBIC); const int* coeff = sws_getCoefficients(SWS_CS_DEFAULT); if (sws_setColorspaceDetails(scaleContext, coeff, this->_codecContext->pix_fmt, coeff, format, 0, 1<<16, 1<<16) < 0) { sws_freeContext(scaleContext); throw std::logic_error("Failed to set colorspace details"); } if (sws_init_context(scaleContext, NULL, NULL) < 0) { sws_freeContext(scaleContext); throw std::logic_error("Failed to initialise scale context"); } #endif SwsContext* scaleContext = sws_getContext(this->_codecContext->width, this->_codecContext->height, this->_codecContext->pix_fmt, scaledWidth, scaledHeight, format, SWS_BICUBIC, NULL, NULL, NULL); if (scaleContext == NULL) { throw std::string("Failed to create resize context"); } AVFrame* convertedFrame = NULL; uint8_t* convertedFrameBuffer = NULL; this->_createAVFrame(&convertedFrame, &convertedFrameBuffer, scaledWidth, scaledHeight, format); sws_scale(scaleContext, this->_frame->data, this->_frame->linesize, 0, this->_codecContext->height, convertedFrame->data, convertedFrame->linesize); sws_freeContext(scaleContext); av_free(this->_frame); av_free(this->_frameBuffer); this->_frame = convertedFrame; this->_frameBuffer = convertedFrameBuffer; } void VideoDecoder::_calculateDimensions(int squareSize, bool maintainAspectRatio, int& destWidth, int& destHeight) { if (squareSize == 0) { #undef max // Fixes Windows compilation error C2589, some other header // file is polluting the global name space with a max // macro. squareSize = std::max(this->_codecContext->width, this->_codecContext->height); } if (!maintainAspectRatio) { destWidth = squareSize; destHeight = squareSize; } else { int srcWidth = this->_codecContext->width; int srcHeight = this->_codecContext->height; int ascpectNominator = this->_codecContext->sample_aspect_ratio.num; int ascpectDenominator = this->_codecContext->sample_aspect_ratio.den; if (ascpectNominator != 0 && ascpectDenominator != 0) { srcWidth = srcWidth * ascpectNominator / ascpectDenominator; } if (srcWidth > srcHeight) { destWidth = squareSize; destHeight = static_cast(static_cast(squareSize) / srcWidth * srcHeight); } else { destWidth = static_cast(static_cast(squareSize) / srcHeight * srcWidth); destHeight = squareSize; } } } void VideoDecoder::_createAVFrame(AVFrame** pAvFrame, uint8_t** pFrameBuffer, int width, int height, PixelFormat format) { *pAvFrame = avcodec_alloc_frame(); int numBytes = avpicture_get_size(format, width, height); *pFrameBuffer = reinterpret_cast(av_malloc(numBytes)); avpicture_fill((AVPicture*) *pAvFrame, *pFrameBuffer, format, width, height); } void VideoDecoder::_seek(int64_t seconds) { //if allowSEek return ? int64_t timestamp = AV_TIME_BASE * seconds; if (timestamp < 0) timestamp = 0; if (av_seek_frame(this->_formatContext, -1, timestamp, 0) >= 0) avcodec_flush_buffers(this->_formatContext->streams[this->_videoStream]->codec); else throw std::string("Seek failed"); int keyFrameAttempts = 0; bool gotFrame = 0; do { int count = 0; gotFrame = 0; while (!gotFrame && count < 20) { this->_getVideoPacket(); try { gotFrame = this->_decodeVideoPacket(); } catch (...) {} ++count; } ++keyFrameAttempts; } while ((!gotFrame || !this->_frame->key_frame) && keyFrameAttempts < 200); if (gotFrame == 0) throw std::string("Can't seek in video"); } void VideoDecoder::_decodeVideoFrame() { bool frameFinished = false; while (!frameFinished && this->_getVideoPacket()) frameFinished = this->_decodeVideoPacket(); if (!frameFinished) throw std::string("decodeVideoFrame : frame not finished"); } bool VideoDecoder::_decodeVideoPacket() { if (this->_packet->stream_index != this->_videoStream) return false; avcodec_get_frame_defaults(this->_frame); int frameFinished; int bytesDecoded = avcodec_decode_video2(this->_codecContext, this->_frame, &frameFinished, this->_packet); if (bytesDecoded < 0) throw std::string("fail to decode video frame"); return (frameFinished > 0); } bool VideoDecoder::_getVideoPacket(void) { bool framesAvailable = true; bool frameDecoded = false; int attempts = 0; if (this->_packet) { av_free_packet(this->_packet); delete this->_packet; } this->_packet = new AVPacket(); while (framesAvailable && !frameDecoded && (attempts++ < 1000)) { if (av_read_frame(this->_formatContext, this->_packet) >= 0) framesAvailable = true; else framesAvailable = false; if (framesAvailable) { frameDecoded = this->_packet->stream_index == this->_videoStream; if (!frameDecoded) { av_free_packet(this->_packet); } } } return (frameDecoded); } void VideoDecoder::_initializeVideo() { unsigned int i = 0; for (; i < this->_formatContext->nb_streams; i++) { #if LIBAVCODEC_VERSION_MAJOR < 53 if (this->_formatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) #else if (this->_formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) #endif { this->_stream = this->_formatContext->streams[i]; this->_videoStream = i; break; } } if (this->_videoStream < 0) { this->_clear(); throw std::string("Could not find video stream"); } this->_codecContext = this->_formatContext->streams[this->_videoStream]->codec; this->_codec = avcodec_find_decoder(this->_codecContext->codec_id); if (this->_codec == NULL) { this->_codecContext = NULL; this->_clear(); throw std::string("Codec not found, can't decode"); } this->_codecContext->workaround_bugs = 1; if (avcodec_open(this->_codecContext, this->_codec) < 0) { this->_clear(); throw std::string("Could not open video"); } } Image_p VideoDecoder::_thumbnail(int32_t scaledSize) { int scaledHeight, scaledWidth; bool maintainAspectRatio = 0; if (this->_frame->interlaced_frame) avpicture_deinterlace((AVPicture*) this->_frame, (AVPicture*) this->_frame, this->_codecContext->pix_fmt, this->_codecContext->width, this->_codecContext->height); this->_convertAndScaleFrame(PIX_FMT_RGB32, scaledSize, maintainAspectRatio, scaledWidth, scaledHeight); Image_p image(new Image(this->_frame->data[0], this->_frame->linesize[0] * scaledHeight, scaledWidth, scaledHeight)); return (image); } Image_p VideoDecoder::thumbnailAt(int64_t seconds, int32_t scaledSize) { //try { this->_decodeVideoFrame(); this->_seek(seconds); //} //catch (std::string e) //{ //cout << "error " << endl; ////this->_clear(); //this->_seek(0); //this->_initializeVideo(); //this->_decodeVideoFrame(); //} return (this->_thumbnail(scaledSize)); } Image_p VideoDecoder::thumbnailAtPercent(uint8_t percent, int32_t scaledSize) { //check if 0 > x < 100 % int64_t seconds = ((int64_t) ((float)this->duration() * (percent/100.00))); return (this->thumbnailAt(seconds, scaledSize)); } int32_t VideoDecoder::width() { if (this->_codecContext) return (this->_codecContext->width); return (-1); } int32_t VideoDecoder::height() { if (this->_codecContext) return (this->_codecContext->height); return (-1); } int32_t VideoDecoder::duration() { if (this->_formatContext) return (this->_formatContext->duration / AV_TIME_BASE); return (0); } std::string VideoDecoder::codec() { if (this->_codec) { return std::string(this->_codec->name); } return std::string(""); } dff-1.3.0+dfsg.1/dff/api/gui/video/video.hpp000066400000000000000000000053211217176075400203640ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __VIDEO_HH__ #define __VIDEO_HH__ #include #include #include #include #include "exceptions.hpp" #include "export.hpp" #include "rc.hpp" class Node; class VFile; extern "C" { #ifndef INT64_C #define INT64_C(c) (c ## LL) #define UINT64_C(c) (c ## ULL) #endif #include #include #include #ifdef LATEST_GREATEST_FFMPEG #include #endif #include } struct ImageData { char* buff; uint32_t size; } ; class Image : public RCObj { private: ImageData _data; int32_t _width; int32_t _height; public: EXPORT Image(uint8_t* idata, uint32_t size, int32_t width, int32_t height); EXPORT ~Image(void); EXPORT ImageData data(void); EXPORT int32_t height(void); EXPORT int32_t width(void); }; #define Image_p RCPtr< Image > class VideoDecoder { private: VFile* _file; AVFormatContext* _formatContext; AVIOContext* _IOContext; AVCodecContext* _codecContext; AVCodec* _codec; AVStream* _stream; AVFrame* _frame; AVPacket* _packet; unsigned char* _buffer; uint8_t* _frameBuffer; int _videoStream; void _clear(); void _initializeVideo(void); void _decodeVideoFrame(void); bool _decodeVideoPacket(void); bool _getVideoPacket(void); void _seek(int64_t seconds); void _convertAndScaleFrame(PixelFormat format, int scaledSize, bool maintainAspectRatio, int &scaledWidth, int &scaledHeight); void _calculateDimensions(int squareSize, bool maintainAspectRatio, int& destWidth, int& destHeight); void _createAVFrame(AVFrame** pAvFrame, uint8_t** pFrameBuffer, int width, int height, PixelFormat format); Image_p _thumbnail(int32_t scale = 64); public: EXPORT VideoDecoder(Node* node); EXPORT ~VideoDecoder(void); EXPORT int32_t width(void); EXPORT int32_t height(void); EXPORT int32_t duration(void); EXPORT std::string codec(void); EXPORT Image_p thumbnailAtPercent(uint8_t timeInPercent, int32_t scaledSize = 64); EXPORT Image_p thumbnailAt(int64_t timeInSeconds, int32_t scaledSize = 64); }; #endif dff-1.3.0+dfsg.1/dff/api/gui/video/video.i000066400000000000000000000054431217176075400200320ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module(package="api.gui.video", docstring="video api to extract thumbnail and metadata") video %feature("autodoc", 1); %feature("docstring") VideoDecoder::VideoDecoder " Initialize VideoDecoder class, take a Node as parameter. If error occurs throw an std::string containg error message. " %feature("docstring") VideoDecoder::width " Return video width or -1 if video can't be decoded. " %feature("docstring") VideoDecoder::height " Return video height or -1 if video can't be decoded. " %feature("docstring") VideoDecoder::duration " Return video duration in seconds or 0 if video can't be decoded. " %feature("docstrng") VideoDecoder::codec " Return a string containing the video codec name. " %feature("docstring") VideoDecoder::thumbnailAt " Take a time in seconds and scale size as parameters. Return a QImage containg a thumbnail of the video at time x in seconds, scaled size by default is 64. Returned class use ref counting. If error occurs throw a std::string containing error message. " %feature("docstring") VideoDecoder::thumbnailAtPercent " Take a percent of video length and scale size as parameters. Return a QImage containg a thumbnail of the video at percent x of the duration, scaled size by default is 64. Returned class use ref counting. If error occurs throw a std::string containing error message. " %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %typemap(out) ImageData { $result = PyString_FromStringAndSize((const char*)$1.buff, $1.size); } %newobject VideoDecoder::thumbnail; %newobject VideoDecoder::thumbnailAt; %newobject VideoDecoder::thumbnailAtPercent; %pythoncode { from PyQt4.QtGui import QImage } %pythonappend VideoDecoder::thumbnailAt %{ return QImage(val.data(), val.width(), val.height(), 5) %} %pythonappend VideoDecoder::thumbnailAtPercent %{ return QImage(val.data(), val.width(), val.height(), 5) %} %{ #include "export.hpp" #include "rc.hpp" #include "video.hpp" %} %refobject RCObj "$this->addref();" %unrefobject RCObj "$this->delref();" %import "../../exceptions/libexceptions.i" %include "export.hpp" %include "rc.hpp" %include "video.hpp" %extend_smart_pointer(Image_p); %template(RCPtrImage) Image_p; dff-1.3.0+dfsg.1/dff/api/gui/view/000077500000000000000000000000001217176075400164105ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/view/CMakeLists.txt000066400000000000000000000011631217176075400211510ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER install_file( __init__.py node_list.py node_table.py tree.py ) dff-1.3.0+dfsg.1/dff/api/gui/view/__init__.py000066400000000000000000000011211217176075400205140ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER __all__ = ["node_list", "node_table"] dff-1.3.0+dfsg.1/dff/api/gui/view/node_list.py000066400000000000000000000127461217176075400207540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.api.vfs.libvfs import VLink DEFAULT_SIZE = 16 class NodeListView(QListView): def __init__(self, widget): super(NodeListView, self).__init__(widget) self.width = DEFAULT_SIZE self.height = DEFAULT_SIZE self.wpad = 25 self.hpad = 30 self.factor = 1 self.tablewidget = widget self.delegate = CheckStateListDelegate(self) self.configure() def configure(self): self.setItemDelegate(self.delegate) self.w = self.width + (self.factor * 32) self.h = self.height + (self.factor * 32) self.setIconSize(QSize(self.w, self.h)) self.setGridSize(QSize(self.w + self.wpad, self.h + self.hpad)) self.setLayoutMode(QListView.Batched) self.setViewMode(QListView.IconMode) self.setUniformItemSizes(True) self.setFlow(QListView.LeftToRight) self.setSelectionMode(QAbstractItemView.NoSelection) self.setBatchSize(50) self.setWordWrap(True) self.setTextElideMode(Qt.ElideRight) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setWrapping(True) def resizeEvent(self, event): self.refreshVisible() def refreshVisible(self): try: self.rows = (self.viewport().height() / (self.h + self.hpad)) self.cols = self.viewport().width() / (self.w + self.wpad) visible = ((self.rows + 1) * self.cols) - 1 self.model().setVisibleRows(visible) except: return def viewOptions(self): option = QStyleOptionViewItem() option.decorationPosition = QStyleOptionViewItem.Top option.decorationAlignment = Qt.AlignCenter option.decorationSize = QSize(self.w,self.h) option.displayAlignment = Qt.AlignBottom option.state = QStyle.State_Enabled return option def select(self, row): self.update(self.model().index(self.model().activeSelection(), 0)) self.model().select(row) self.update(self.model().index(self.model().activeSelection(), 0)) index = self.model().index(row, 0) node = self.model().getNode(self.model().currentRow() + row) if node: self.tablewidget.emit(SIGNAL("nodePressed"), node) def mousePressEvent(self, event): index = self.indexAt(event.pos()) self.select(index.row()) def mouseDoubleClickEvent(self, event): index = self.indexAt(event.pos()) self.select(index.row()) node = self.model().getNode(self.model().currentRow() + index.row()) if isinstance(node, VLink): node = node.linkNode() if node.isDir() or node.hasChildren(): self.emit(SIGNAL("enterDirectory"), node) else: self.emit(SIGNAL("nodeListDoubleClicked"), node) def wheelEvent(self, event): scroll = self.tablewidget.scrollbar if event.delta() > 0: v = self.model().seek(-self.cols, 1) else: v = self.model().seek(self.cols, 1) def keyPressEvent(self, event): if event.matches(QKeySequence.MoveToNextLine): if self.model().activeSelection() + self.cols >= self.model().visibleRows() - self.cols: self.model().seek(self.cols, 1) self.select(self.model().activeSelection() + self.cols) elif event.matches(QKeySequence.MoveToPreviousLine): if self.model().activeSelection() - self.cols <= 0: self.model().seek(-self.cols, 1) self.select(self.model().activeSelection() - self.cols) elif event.matches(QKeySequence.MoveToPreviousPage): self.model().seek(-(self.model().visibleRows() - 1), 1) self.select(0) elif event.matches(QKeySequence.MoveToNextPage): self.model().seek(self.model().visibleRows() - 1, 1) self.select(0) elif event.matches(QKeySequence.MoveToNextChar): self.select(self.model().activeSelection() + 1) elif event.matches(QKeySequence.MoveToPreviousChar): self.select(self.model().activeSelection() - 1) class CheckStateListDelegate(QStyledItemDelegate): def __init__(self, parent): QStyledItemDelegate.__init__(self, parent) self.view = parent def sizeHint(self, option, index): w = (self.view.width + (self.view.factor * 32)) + self.view.wpad h = (self.view.height + (self.view.factor * 32)) + self.view.hpad return QSize(w, h) def editorEvent(self, event, model, option, index): if event.type() == QEvent.MouseButtonRelease and index.isValid(): model.select(index.row()) self.view.emit(SIGNAL("nodeListClicked"), event.button()) # Detect checkbox click in order to avoid column style detection element = self.view.style().subElementRect(QStyle.SE_CheckBoxIndicator, option) if element.contains(event.pos()): node = model.currentNode() if node != None: if not model.selection.isChecked(node): model.selection.add(node) else: model.selection.rm(node) return QStyledItemDelegate.editorEvent(self, event, model, option, index) else: return False dff-1.3.0+dfsg.1/dff/api/gui/view/node_table.py000066400000000000000000000217341217176075400210650ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.api.vfs.libvfs import VFS, VLink DEFAULT_SIZE = 20 class NodeTableView(QTableView): def __init__(self, tablewidget): QTableView.__init__(self) self.tablewidget = tablewidget self.headerorder = {} self.delegate = CheckStateDelegate(self) self.setItemDelegate(self.delegate) self.factor = 1 self.configure() def configure(self): self.verticalHeader().setDefaultSectionSize(DEFAULT_SIZE * self.factor) self.setIconSize(QSize(DEFAULT_SIZE * self.factor, DEFAULT_SIZE * self.factor)) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setShowGrid(False) self.setAutoScroll(False) self.setSelectionMode(QAbstractItemView.NoSelection) self.configureHeaders() def configureHeaders(self): self.horizontalHeader().setStretchLastSection(True) # self.horizontalHeader().setSortIndicatorShown(True) self.horizontalHeader().setMovable(True) self.connect(self.horizontalHeader(), SIGNAL("sectionClicked(int)"), self.headerClicked) self.verticalHeader().hide() def refreshVisible(self): height = self.factor * DEFAULT_SIZE try: visible = self.viewport().height() / height if visible > 0: self.model().setVisibleRows(visible) except: return def resizeEvent(self, event): self.refreshVisible() def wheelEvent(self, event): currentrow = self.model().currentRow() if self.model().size() <= self.model().visibleRows(): return if event.delta() < 0: if currentrow + 3 >= (self.model().size() - self.model().visibleRows()): v = self.model().seek(self.model().size()) return if event.delta() > 0: v = self.model().seek(-3, 1) return else: v = self.model().seek(3, 1) return def mouseDoubleClickEvent(self, event): index = self.indexAt(event.pos()) self.model().select(index.row()) node = self.model().getNode(self.model().currentRow() + index.row()) if node != None: # This is a directory if isinstance(node, VLink): node = node.linkNode() if node.isDir() or node.hasChildren(): self.emit(SIGNAL("enterDirectory"), node) else: self.emit(SIGNAL("nodeListDoubleClicked"), node) def keyPressEvent(self, event): if event.matches(QKeySequence.MoveToNextLine): if self.model().activeSelection() + 1 >= self.model().visibleRows(): self.model().seek(1, 1) self.model().select(self.model().visibleRows() - 1) else: self.model().select(self.model().activeSelection() + 1) elif event.matches(QKeySequence.MoveToPreviousLine): if self.model().activeSelection() - 1 <= 0: self.model().seek(-1, 1) self.model().select(0) else: self.model().select(self.model().activeSelection() - 1) elif event.matches(QKeySequence.MoveToPreviousPage): self.model().seek(-(self.model().visibleRows() - 1), 1) self.model().select(0) elif event.matches(QKeySequence.MoveToNextPage): self.model().seek(self.model().visibleRows() - 1, 1) self.model().select(0) def headerClicked(self, col): self.horizontalHeader().setSortIndicatorShown(True) if col in self.headerorder: if self.headerorder[col] == Qt.DescendingOrder: order = Qt.AscendingOrder else: order = Qt.DescendingOrder else: order = Qt.DescendingOrder self.headerorder[col] = order # print self.headerorder self.model().sort(col, order) class HeaderView(QHeaderView): def __init__(self, view): QHeaderView.__init__(self, Qt.Horizontal) self.isOn = False self.view = view self.setStretchLastSection(True) self.setClickable(True) def paintSection(self, painter, rect, logicalIndex): painter.save() QHeaderView.paintSection(self, painter, rect, logicalIndex) painter.restore() option = QStyleOptionButton() if logicalIndex == 0: option.rect = QRect(3,2,20,20) model = self.view.model() if (self.isOn): option.state = QStyle.State_On|QStyle.State_Enabled else: option.state = QStyle.State_Off|QStyle.State_Enabled self.setSortIndicator(logicalIndex, True) self.style().drawPrimitive(QStyle.PE_IndicatorCheckBox, option, painter) def mousePressEvent(self, event): option = QStyleOptionButton() option.rect = QRect(3,2,20,20) element = self.style().subElementRect(QStyle.SE_CheckBoxIndicator, option) if element.contains(event.pos()): if self.isOn: self.isOn = False self.emit(SIGNAL("headerSelectionClicked"), False) else: self.emit(SIGNAL("headerSelectionClicked"), True) self.isOn = True self.update() self.headerDataChanged(Qt.Horizontal, 0, 0) else: index = self.logicalIndexAt(event.pos()) if self.cursor().shape() != Qt.SplitHCursor: self.view.headerClicked(index) QHeaderView.mousePressEvent(self, event) class CheckStateDelegate(QStyledItemDelegate): def __init__(self, parent): QStyledItemDelegate.__init__(self, parent) self.view = parent self.tagSpacement = 10 self.tagBorderSpacement = 10 def paint(self, painter, options, index): QStyledItemDelegate.paint(self, painter, options, index) if index.isValid(): try: attrname = self.view.model().availableAttributes()[index.column()] except KeyError: attrname == None if attrname == "tags": absrow = self.view.model().currentRow() + index.row() node = self.view.model().getNode(absrow) tags = node.tags() if len(tags) and node != None: painter.save() self.initStyleOption(options, index) painter.setClipRect(options.rect) options.rect.setX(self.tagBorderSpacement + options.rect.x()) for tag in tags: textRect = painter.boundingRect(options.rect, Qt.AlignLeft | Qt.AlignVCenter, tag.name()) textRect.setWidth(textRect.width() + self.tagBorderSpacement) #space inside drawing rect for cented text oldBrush = painter.brush() color = tag.color() oldPen = painter.pen() painter.setPen(QPen(QColor(color.r, color.g, color.b))) painter.setBrush(QColor(color.r, color.g, color.b)) painter.drawRect(textRect) painter.setPen(oldPen) textCenter = options.rect #space to center text textCenter.setX(textCenter.x() + (self.tagBorderSpacement / 2)) painter.drawText(textCenter, Qt.AlignLeft | Qt.AlignVCenter, QString.fromUtf8(tag.name())) #space between tag options.rect.setX(options.rect.x() + textRect.width() + self.tagSpacement) painter.restore() def editorEvent(self, event, model, option, index): if event.type() == QEvent.MouseButtonPress and index.isValid(): model.select(index.row()) self.view.emit(SIGNAL("nodeListClicked"), event.button()) # Detect checkbox click in order to avoid column style detection element = self.view.style().subElementRect(QStyle.SE_CheckBoxIndicator, option) if element.contains(event.pos()) and index.column() == 0: node = model.currentNode() if node != None: if not model.selection.isChecked(node): model.selection.add(node) else: model.selection.rm(node) self.view.refreshVisible() return QStyledItemDelegate.editorEvent(self, event, model, option, index) else: return False dff-1.3.0+dfsg.1/dff/api/gui/view/tree.py000066400000000000000000000150651217176075400177300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Romain Bertholon # import os from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.api.vfs.libvfs import VFS class NodeTreeView(QTreeView): """ This view is used to display the node tree view (in the left part of the Gui). Only directories and nodes having children does appear in this tree, files are not displayed. """ def __init__(self, parent = None, coord = False): """ Constructor """ QTreeView.__init__(self) self.VFS = VFS.Get() self.setSelectionMode(QAbstractItemView.NoSelection) self.setState(QAbstractItemView.NoState) self.setUniformRowHeights(True) self.setSortingEnabled(False) self.coord = coord self.delegate = CheckDelegate(self) self.setItemDelegate(self.delegate) self.connect(self, SIGNAL("expanded(QModelIndex)"), self.indexExpanded) # self.loadStylesheet() def indexExpanded(self, index): # try: node = self.model().getNodeFromIndex(index) if node != None: self.model().refreshModel(node) def keyPressEvent(self, e): row = self.currentIndex().row() if e.matches(QKeySequence.MoveToNextLine): index = self.moveCursor(QAbstractItemView.MoveDown, Qt.NoModifier) elif e.matches(QKeySequence.MoveToPreviousLine): index = self.moveCursor(QAbstractItemView.MoveUp, Qt.NoModifier) elif e.matches(QKeySequence.MoveToNextChar): self.expand(self.currentIndex()) return elif e.matches(QKeySequence.MoveToPreviousChar): self.collapse(self.currentIndex()) return else: index = self.currentIndex() if index.isValid(): self.model().emit(SIGNAL("layoutAboutToBeChanged")) self.model().setCurrentIndex(self.currentIndex(), index) self.setCurrentIndex(index) self.model().emit(SIGNAL("layoutChanged")) node = self.model().getNodeFromIndex(index) if (node != None): rec = index.data(Qt.UserRole + 3).toBool() self.emit(SIGNAL("nodeTreeClicked"), node, 0, rec) def mouseMoveEvent(self, e): pass def mousePressEvent(self, e): try: index = self.indexAt(e.pos()) if index.isValid(): self.model().emit(SIGNAL("layoutAboutToBeChanged")) self.model().setCurrentIndex(self.currentIndex(), index) self.setCurrentIndex(index) self.model().emit(SIGNAL("layoutChanged")) if self.coord: self.resizeColumnToContents(0) except: pass QTreeView.mousePressEvent(self, e) def mouseDoubleClickEvent(self, e): """ \reimp When users double-click on a node in the tree view, it expands the node. A nodeTreeClicked signal is emitted. \param e the event """ try: index = self.indexAt(e.pos()) if index.isValid(): self.model().emit(SIGNAL("layoutAboutToBeChanged")) self.model().setCurrentIndex(self.currentIndex(), index) self.setCurrentIndex(index) self.model().emit(SIGNAL("layoutChanged")) except: return QTreeView.mouseDoubleClickEvent(self, e) def expandToNode(self, node): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) item = self.model().getItemFromNode(node) if item != None: index = item.index() if index.isValid(): n = self.model().getNodeFromIndex(index) self.model().setCurrentIndex(self.currentIndex(), index) self.setCurrentIndex(index) self.setExpanded(index, True) self.scrollTo(index) else: self.model().refreshModel(node) QApplication.restoreOverrideCursor() def indexRowSizeHint(self, index): return 2 def loadStylesheet(self): path = os.path.abspath(os.path.join(os.getcwd(), "ui", "gui", "resources", "stylesheets", "treeview.qss")) f = QFile(path) f.open(QFile.ReadOnly) styleSheet = QLatin1String(f.readAll()) self.setStyleSheet(styleSheet) f.close() class CheckDelegate(QStyledItemDelegate): def __init__(self, parent): QStyledItemDelegate.__init__(self, parent) self.view = parent def paint(self, painter, options, index): if index.isValid(): if index.column() == 0: painter.save() data = index.data(Qt.UserRole + 3) if data.toBool(): icon = QPixmap(":rectree_on").scaled(QSize(16, 16), Qt.KeepAspectRatio) else: icon = QPixmap(":rectree_off").scaled(QSize(16, 16), Qt.KeepAspectRatio) zx = options.rect.x() zy = options.rect.y() painter.drawPixmap(QRect(zx, zy + 2, icon.width(), icon.height()), icon) painter.restore() options.rect.setX(options.rect.x() + icon.width()) QStyledItemDelegate.paint(self, painter, options, index) def editorEvent(self, event, model, option, index): e = event if index.isValid(): var = model.data(index, Qt.UserRole + 1) node = self.view.VFS.getNodeFromPointer(var.toULongLong()[0]) rec = index.data(Qt.UserRole + 3).toBool() pos = event.pos() newposx = event.pos().x() - 16 if event.type() not in [QEvent.MouseMove, QEvent.MouseButtonRelease] or not (option.state & QStyle.State_Enabled): if (newposx <= option.rect.x()) and (newposx >= option.rect.x() - 16): # We are on recursive icon item = model.itemFromIndex(index) if rec: item.setData(False, Qt.UserRole + 3) rec = False else: item.setData(True, Qt.UserRole + 3) rec = True # XXX CheckBox positions elif (newposx >= option.rect.x() + 6) and (newposx <= option.rect.x() + 19): state = index.data(Qt.CheckStateRole).toBool() if not state: model.selection.add(node) else: model.selection.rm(node) pos.setX(newposx) e = QMouseEvent(event.type(), pos, event.button(), event.buttons(), event.modifiers()) if (node != None): self.view.emit(SIGNAL("nodeTreeClicked"), node, event.button(), rec) return QStyledItemDelegate.editorEvent(self, e, model, option, index) else: return False dff-1.3.0+dfsg.1/dff/api/gui/widget/000077500000000000000000000000001217176075400167215ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/widget/CMakeLists.txt000066400000000000000000000015431217176075400214640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Christophe Malinge #### Deploying python __init__ script install_file( __init__.py dockwidget.py layoutmanager.py varianttreewidget.py propertytable.py textedit.py devicesdialog.py generateModuleShape.py nodewidget.py nodelistwidgets.py ) add_subdirectory (search) dff-1.3.0+dfsg.1/dff/api/gui/widget/__init__.py000066400000000000000000000010451217176075400210320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob dff-1.3.0+dfsg.1/dff/api/gui/widget/devicesdialog.py000066400000000000000000000042521217176075400221000ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER # from PyQt4.QtGui import QFileDialog, QMessageBox, QInputDialog, QTableWidget, QTableWidgetItem, QDialog, QHBoxLayout, QPushButton, QVBoxLayout, QSplitter, QDialogButtonBox, QFormLayout, QWidget, QComboBox, QLabel, QPixmap from PyQt4.QtCore import QString, Qt, SIGNAL, SLOT from dff.api.taskmanager import * from dff.api.taskmanager.taskmanager import * from dff.api.loader import * from dff.api.vfs import vfs from dff.api.devices.devices import Devices from dff.ui.gui.resources.ui_devicesdialog import Ui_DevicesDialog class DevicesDialog(QDialog, Ui_DevicesDialog): def __init__(self, parent = None): QDialog.__init__(self) self.setupUi(self) self.selectedDevice = None self.listdevices = {} self.devices = Devices() for n in range(0, len(self.devices)): self.combodevice.addItem(self.devices[n].model()) self.listdevices[n] = self.devices[n] self.setDeviceInformations(self.devices[0], True) self.selectedDevice = self.devices[0] self.connect(self.combodevice, SIGNAL("currentIndexChanged(int)"), self.deviceChanged) def __del__(self): del self.devices def setDeviceInformations(self, device, init=False): self.blockdevice.setText(QString.fromUtf8(device.blockDevice())) self.model.setText(QString.fromUtf8(device.model())) self.serial.setText(QString.fromUtf8(device.serialNumber())) self.size.setText(str(device.size())) def deviceChanged(self, index): self.setDeviceInformations(self.listdevices[index]) self.selectedDevice = self.listdevices[index] dff-1.3.0+dfsg.1/dff/api/gui/widget/dockwidget.py000066400000000000000000000233131217176075400214210ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # Solal Jacob from PyQt4.QtCore import Qt, SIGNAL, QEvent, QPoint, QSize, QRect, QTimer from PyQt4.QtGui import QAbstractButton, QComboBox, QStyle, QPainter, QPushButton, QDockWidget, QApplication, QStylePainter, QIcon, QHBoxLayout, QStyleOptionToolButton, QWidget, QStyleOptionDockWidgetV2, QLayout, QCheckBox class DockWidgetTitleBarButton(QAbstractButton): def __init__(self, titlebar): QAbstractButton.__init__(self, titlebar) self.setFocusPolicy(Qt.NoFocus) def sizeHint(self): self.ensurePolished() margin = self.style().pixelMetric(QStyle.PM_DockWidgetTitleBarButtonMargin, None, self) if self.icon().isNull(): return QSize(margin, margin) iconSize = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self) pm = self.icon().pixmap(iconSize) return QSize(pm.width() + margin, pm.height() + margin) def enterEvent(self, event): if self.isEnabled(): self.update() QAbstractButton.enterEvent(self, event) def leaveEvent(self, event): if self.isEnabled(): self.update() QAbstractButton.leaveEvent(self, event) def paintEvent(self, _event): p = QPainter(self) opt = QStyleOptionToolButton() opt.init(self) opt.state |= QStyle.State_AutoRaise if self.isEnabled() and self.underMouse() and not self.isChecked() and not self.isDown(): opt.state |= QStyle.State_Raised if self.isChecked(): opt.state |= QStyle.State_On if self.isDown(): opt.state |= QStyle.State_Sunken self.style().drawPrimitive(QStyle.PE_PanelButtonTool, opt, p, self) opt.icon = self.icon() opt.subControls = QStyle.SubControls() opt.activeSubControls = QStyle.SubControls() opt.features = QStyleOptionToolButton.None opt.arrowType = Qt.NoArrow size = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self) opt.iconSize = QSize(size, size) self.style().drawComplexControl(QStyle.CC_ToolButton, opt, p, self) class DockWidgetTitleBar(QWidget): def __init__(self, dockWidget, hasCheckState = False): super(DockWidgetTitleBar, self).__init__(dockWidget) q = dockWidget self.floatButton = DockWidgetTitleBarButton(self) self.floatButton.setIcon(q.style().standardIcon(QStyle.SP_TitleBarNormalButton, None, q)) self.floatButton.clicked.connect(self.toggleFloating) self.floatButton.setVisible(True) self.floatButton.setToolTip(self.tr("Undock")) self.closeButton = DockWidgetTitleBarButton(self) self.closeButton.setIcon(q.style().standardIcon(QStyle.SP_TitleBarCloseButton, None, q)) self.closeButton.clicked.connect(dockWidget.close) self.closeButton.setVisible(True) self.closeButton.setToolTip(self.tr("Close")) if hasCheckState: self.checkStateButton = QCheckBox(self) self.checkStateButton.setCheckState(2) self.checkStateButton.setToolTip(self.tr("Disable this window")) self.connect(self.checkStateButton, SIGNAL("stateChanged(int)"), self.toggleCheckState) else: self.checkStateButton = False dockWidget.featuresChanged.connect(self.featuresChanged) self.featuresChanged(0) def hasFeature(self, dockwidget, feature): return dockwidget.features() & feature == feature def minimumSizeHint(self): return self.sizeHint() def sizeHint(self): q = self.parentWidget() mw = q.style().pixelMetric(QStyle.PM_DockWidgetTitleMargin, None, q) fw = q.style().pixelMetric(QStyle.PM_DockWidgetFrameWidth, None, q) closeSize = QSize(0, 0) if self.closeButton: closeSize = self.closeButton.sizeHint() floatSize = QSize(0, 0) if self.floatButton: floatSize = self.floatButton.sizeHint() hideSize = self.hideSizeHint() buttonHeight = max(max(closeSize.height(), floatSize.height()), hideSize.height()) + 2 buttonWidth = closeSize.width() + floatSize.width() + hideSize.width() titleFontMetrics = q.fontMetrics() fontHeight = titleFontMetrics.lineSpacing() + 2 * mw height = max(buttonHeight, fontHeight) return QSize(buttonWidth + height + 4 * mw + 2 * fw, height) def hideSizeHint(self): if self.checkStateButton: return self.checkStateButton.sizeHint() else: return QSize(0, 0) def paintEvent(self, _event): p = QStylePainter(self) q = self.parentWidget() fw = q.isFloating() and q.style().pixelMetric(QStyle.PM_DockWidgetFrameWidth, None, q) or 0 mw = q.style().pixelMetric( QStyle.PM_DockWidgetTitleMargin, None, q) titleOpt = QStyleOptionDockWidgetV2() titleOpt.initFrom(q) titleOpt.rect = self.titleOptionRect(fw, mw) titleOpt.title = q.windowTitle() titleOpt.closable = self.hasFeature(q, QDockWidget.DockWidgetClosable) titleOpt.floatable = self.hasFeature(q, QDockWidget.DockWidgetFloatable) p.drawControl(QStyle.CE_DockWidgetTitle, titleOpt) def titleOptionRect(self, fw, mw): if self.checkStateButton: return QRect(QPoint(fw + mw + self.checkStateButton.size().width(), fw), QSize(self.geometry().width() - ( fw * 2 ) - mw - self.checkStateButton.size().width(), self.geometry().height() - ( fw * 2 ))) else: return QRect(QPoint(fw + mw, fw), QSize(self.geometry().width() - ( fw * 2 ) - mw, self.geometry().height() - ( fw * 2 ))) def resizeEvent(self, _event): q = self.parentWidget() fw = q.isFloating() and q.style().pixelMetric(QStyle.PM_DockWidgetFrameWidth, None, q) or 0 opt = QStyleOptionDockWidgetV2() opt.initFrom(q) opt.rect = QRect(QPoint(fw, fw), QSize(self.geometry().width() - (fw * 2), self.geometry().height() - (fw * 2))) opt.title = q.windowTitle() opt.closable = self.hasFeature(q, QDockWidget.DockWidgetClosable) opt.floatable = self.hasFeature(q, QDockWidget.DockWidgetFloatable) floatRect = q.style().subElementRect(QStyle.SE_DockWidgetFloatButton, opt, q) if not floatRect.isNull(): self.floatButton.setGeometry(floatRect) closeRect = q.style().subElementRect(QStyle.SE_DockWidgetCloseButton, opt, q) if not closeRect.isNull(): self.closeButton.setGeometry(closeRect) top = fw if not floatRect.isNull(): top = floatRect.y() elif not closeRect.isNull(): top = closeRect.y() if self.checkStateButton: size = self.checkStateButton.size() if not closeRect.isNull(): size = self.closeButton.size() elif not floatRect.isNull(): size = self.floatButton.size() checkStateRect = QRect(QPoint(fw, top), size) self.checkStateButton.setGeometry(checkStateRect) def toggleFloating( self ): parent = self.parentWidget() parent.setFloating(not parent.isFloating()) def toggleCheckState(self, state): parent = self.parentWidget() if parent: if state != 0: parent.updateCheckState(True) else: parent.updateCheckState(False) def featuresChanged(self, _features): parent = self.parentWidget() self.closeButton.setVisible(self.hasFeature(parent, QDockWidget.DockWidgetClosable)) self.floatButton.setVisible(self.hasFeature(parent, QDockWidget.DockWidgetFloatable)) class DockWidget(QDockWidget): def __init__(self, mainWindow, childWidget, name): QDockWidget.__init__(self, mainWindow) self.mainwindow = mainWindow self.childWidget = childWidget self.init(childWidget) self.show() self.setObjectName(name) self.visibilityState = True self.setTitleBarWidget(self.initTitleBar()) def hasCheckState(self): try: getattr(self.childWidget, 'updateCheckState') return True except AttributeError: return False def initTitleBar(self): return DockWidgetTitleBar(self, self.hasCheckState()) def init(self, widget): self.name = widget.name self.setAllowedAreas(Qt.AllDockWidgetAreas) self.setFeatures(QDockWidget.AllDockWidgetFeatures) self.setWidget(widget) self.connect(self, SIGNAL("topLevelChanged(bool)"), self.toplevel_changed) self.connect(self, SIGNAL("visibilityChanged(bool)"), self.setVisibility) def updateCheckState(self, state): self.childWidget.updateCheckState(state) def toplevel_changed(self, state): if not state: self.mainwindow.refreshTabifiedDockWidgets() def setVisibility(self, state): self.visibilityState = state def visibility(self): return self.visibilityState def visibility_changed(self, enable): if enable: self.raise_() self.setFocus() def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: try: self.widget().retranslateUi(self) except AttributeError: pass else: QDockWidget.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/api/gui/widget/generateModuleShape.py000066400000000000000000000223171217176075400232210ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # import sys import traceback from types import * from PyQt4.QtGui import QAbstractItemView, QApplication, QCheckBox, QDialog, QGridLayout, QLabel, QMessageBox,QSplitter, QVBoxLayout, QWidget, QDialogButtonBox, QPushButton, QLineEdit, QCompleter, QSortFilterProxyModel, QGroupBox, QFileDialog, QSpinBox, QFormLayout, QHBoxLayout, QStackedWidget, QListWidget, QListWidgetItem, QTextEdit, QPalette, QComboBox, QIntValidator, QPixmap from PyQt4.QtCore import Qt, QObject, QRect, QSize, SIGNAL, QModelIndex, QString, QEvent from dff.api.loader import * from dff.api.vfs import * from dff.api.taskmanager.taskmanager import * from dff.api.types.libtypes import Argument, Parameter, Variant, VMap, VList, typeId from dff.api.gui.widget.layoutmanager import layoutManager from dff.ui.gui.utils.utils import Utils from dff.ui.gui.resources.ui_modulegeneratorwidget import Ui_moduleGeneratorWidget class moduleShapeGenerator(QWidget, Ui_moduleGeneratorWidget): def __init__(self, modulename, moduletag, nodeSelected=None): QWidget.__init__(self) Ui_moduleGeneratorWidget.__init__(self) self.setupUi(self) self.labActivate.setVisible(False) self.labDescription.setVisible(False) self.loader = loader.loader() self.vfs = vfs.vfs() self.valueArgs = {} self.modulename = modulename self.moduletag = moduletag self.nodeSelected = nodeSelected self.infoContainer.setTitle(QString(self.modulename)) self.translation() self.setWidget() def setWidget(self): try: self.module = self.loader.modules[str(self.modulename)] except KeyError: self.module = None if self.module and self.module.icon: p = QPixmap(self.module.icon) p.scaled(64, 64, Qt.KeepAspectRatio) self.modulepix.setPixmap(p) else: p = self.modulepix.pixmap().scaled(64,64, Qt.KeepAspectRatio) self.modulepix.setPixmap(p) if not self.nodeSelected: self.nodeSelected = [] self.conf = self.loader.get_conf(str(self.modulename)) try: self.textEdit.setText(self.conf.description) except TypeError: self.textEdit.setText(self.conf.description()) args = self.conf.arguments() self.createArgShape(args) def createArgShape(self, args): self.listargs.connect(self.listargs, SIGNAL("currentItemChanged(QListWidgetItem*,QListWidgetItem*)"), self.argChanged) for arg in args: self.createArgument(arg) self.listargs.item(0).setSelected(True) self.argsLayout.setStretchFactor(0, 1) self.argsLayout.setStretchFactor(1, 3) def createArgument(self, arg): warg = QWidget() vlayout = QVBoxLayout() vlayout.setSpacing(5) vlayout.setMargin(0) winfo = QWidget() infolayout = QFormLayout() infolayout.setMargin(0) requirement = arg.requirementType() # Generate argument's widget warguments = self.getWidgetFromType(arg) if arg.requirementType() in (Argument.Optional, Argument.Empty): checkBox = checkBoxWidget(self, winfo, warguments, self.labActivate.text()) vlayout.addWidget(checkBox, 0) tedit = QTextEdit(str(arg.description())) tedit.setReadOnly(True) infolayout.addRow(tedit) winfo.setLayout(infolayout) vlayout.addWidget(winfo, 1) if warguments: vlayout.addWidget(warguments, 2) self.valueArgs[arg.name()] = warguments else: self.valueArgs[arg.name()] = winfo warg.setLayout(vlayout) self.stackedargs.addWidget(warg) argitem = QListWidgetItem(str(arg.name()), self.listargs) def getWidgetFromType(self, arg): warguments = layoutManager() inputype = arg.inputType() predefs = arg.parameters() ptype = arg.parametersType() if ptype == Parameter.Editable: editable = True else: editable = False if inputype == Argument.Single: if arg.type() in (typeId.Node, typeId.Path): warguments.addPath(arg.name(), arg.type(), predefs, self.nodeSelected, editable) else: warguments.addSingleArgument(arg.name(), predefs, arg.type(), editable) elif inputype == Argument.List: if arg.type() in (typeId.Node, typeId.Path): warguments.addPathList(arg.name(), arg.type(), predefs, self.nodeSelected) else: warguments.addListArgument(arg.name(), arg.type(), predefs, editable) else: # Argument.Empty (typically, bool arguments) return None return warguments def argChanged(self, curitem, previtem): self.stackedargs.setCurrentIndex(self.listargs.row(curitem)) def messageBox(self, coretxt, detail): msg = QMessageBox(self) msg.setWindowTitle(self.configureError) msg.setText(self.configureErrorMsg) msg.setInformativeText(coretxt) msg.setIcon(QMessageBox.Critical) msg.setDetailedText(detail) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def translation(self): self.configureError = self.tr("Configuration error") self.configureErrorMsg = self.tr("An error was detected in the configuration") def validateModule(self): args = {} try : for argname, lmanager in self.valueArgs.iteritems(): if lmanager.isEnabled(): arg = self.conf.argumentByName(argname) if arg.type() == typeId.Node and arg.inputType() == Argument.List: plist = lmanager.get(argname) params = [] for param in plist: params.append(self.vfs.getnode(param)) elif arg.type() == typeId.Node and arg.inputType() == Argument.Single: params = self.vfs.getnode(lmanager.get(argname)) elif arg.inputType() == Argument.Empty: params = True else: params = lmanager.get(argname) args[argname] = params return self.conf.generate(args) except RuntimeError: err_type, err_value, err_traceback = sys.exc_info() err_trace = traceback.format_tb(err_traceback) err_typeval = traceback.format_exception_only(err_type, err_value) terr = QString() detailerr = QString() for err in err_trace: detailerr.append(err) for errw in err_typeval: terr.append(errw) detailerr.append(err) self.messageBox(terr, detailerr) def launchTask(self, genargs): try: self.taskmanager = TaskManager() self.taskmanager.add(str(self.modulename), genargs, ["thread", "gui"]) except RuntimeError: err_type, err_value, err_traceback = sys.exc_info() err_trace = traceback.format_tb(err_traceback) err_typeval = traceback.format_exception_only(err_type, err_value) terr = QString() detailerr = QString() for err in err_trace: detailerr.append(err) for errw in err_typeval: terr.append(errw) detailerr.append(err) self.messageBox(terr, detailerr) return def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) title = self.windowTitle() + ' ' + self.modulename self.setWindowTitle(title) self.translation() else: QDialog.changeEvent(self, event) class checkBoxWidget(QCheckBox): def __init__(self, parent, info, widget, label): QCheckBox.__init__(self) self.__info = info self.__widget = widget self.setText(label) self.stateChangedWidget(Qt.Unchecked) self.initCallback() def initCallback(self): self.connect(self, SIGNAL("stateChanged(int )"), self.stateChangedWidget) def stateChangedWidget(self, state): if state == Qt.Checked : if self.__widget: self.__widget.setEnabled(1) self.__info.setEnabled(1) else : if self.__widget: self.__widget.setEnabled(0) self.__info.setEnabled(0) dff-1.3.0+dfsg.1/dff/api/gui/widget/layoutmanager.py000066400000000000000000000552641217176075400221570ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os, types from PyQt4.QtGui import QWidget, QMenu, QDialog, QLabel, QVBoxLayout, QSplitter, QDialogButtonBox, QFormLayout, QCheckBox, QComboBox, QLineEdit, QTextEdit, QListWidget, QHBoxLayout, QPushButton, QIcon, QFileDialog, QAbstractItemView, QRegExpValidator, QListWidgetItem, QApplication from PyQt4.QtCore import Qt, QEvent, SIGNAL, QRegExp, QSize, QString from dff.api.vfs import vfs from dff.api.vfs.libvfs import VFS, Node from dff.api.types.libtypes import typeId class DialogNodeBrowser(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.title = QLabel("Select a node in the Virtual File System :") self.createLayout() self.createButtons() def createLayout(self): self.baseLayout = QVBoxLayout(self) mw = QApplication.instance().mainWindow self.browser = mw.getNodeBrowser() self.baseLayout.addWidget(self.browser) self.setLayout(self.baseLayout) def createButtons(self): self.buttonBox = QDialogButtonBox() self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.connect(self.buttonBox, SIGNAL("accepted()"),self.accept) self.connect(self.buttonBox, SIGNAL("rejected()"),self.reject) self.baseLayout.addWidget(self.buttonBox) def getSelectedNodes(self): if len(self.browser.selection.get()) == 0: nodes = [self.browser.browserview.model.currentNode()] else: nodes = self.browser.selection.getNodes() return nodes def getSelectedNode(self): try: n = self.getSelectedNodes()[0] return n except: return None def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.model.translation() else: QWidget.changeEvent(self, event) class layoutManager(QWidget): '''Create a layout manager which will help widget creation and data managment The system work with a key / value system and return python type data (ex: str, int, long, list, tupple, etc..) ''' def __init__(self, displaykey=False): QWidget.__init__(self) self.layout = QFormLayout() self.layout.setMargin(0) self.widgets = {} self.displaykey = displaykey self.setLayout(self.layout) self.translation() def overwriteKeys(self, key): ''' Check if inserted key already exists in the layout system ''' for k, v in self.widgets.iteritems(): if k == key: return True return False def addBool(self, key, state = False): ''' Create a non-exclusive checkbox widget and add it into the layout. It permit you to create Bool data representations ''' if not self.overwriteKeys(key): if type(key).__name__=='str': w = QCheckBox(key) if not self.displaykey: self.layout.addRow(w) else: self.layout.addRow(key, w) self.widgets[key] = w else: return -1 else: return -1 return 1 def addList(self, key, predefs, editable=False): if len(predefs) > 0 and not self.overwriteKeys(key): # Check if value list has the same type if type(key) == types.StringType: w = QComboBox() self.connect(w, SIGNAL("currentIndexChanged(QString)"), self.argumentChanged) w.setEditable(editable) w.setValidator(QIntValidator()) for value in predefs: if type(value).__name__=='str': if w.findText(value) == -1: w.addItem(value) elif type(value).__name__=='int': if w.findText(str(value)) == -1: w.addItem(str(value)) else: return -1 if not self.displaykey: self.layout.addRow(w) else: self.layout.addRow(key, w) self.widgets[key] = w return 1 else: return -1 else: return -1 def addSingleArgument(self, key, predefs, typeid, editable=False): if not self.overwriteKeys(key): if type(key) == types.StringType: if len(predefs) > 0: w = QComboBox() self.connect(w, SIGNAL("editTextChanged(QString)"), self.argumentChanged) self.connect(w, SIGNAL("currentIndexChanged(QString)"), self.argumentChanged) w.setEditable(editable) for value in predefs: w.addItem(value.toString()) else: w = QLineEdit() self.connect(w, SIGNAL("editingFinished()"), self.argumentChanged) if typeid not in (typeId.String, typeId.Char, typeId.Node, typeId.Path): w.insert("0") w.setReadOnly(not editable) w.setValidator(fieldValidator(self, typeid)) if not self.displaykey: self.layout.addRow(w) else: self.layout.addRow(key, w) self.widgets[key] = w return 1 else: return -1 else: return -1 def addString(self, key, value=""): if not self.overwriteKeys(key): if type(key).__name__=='str': w = QLineEdit() self.connect(w, SIGNAL("editingFinished()"), self.argumentChanged) w.insert(value) if not self.displaykey: self.layout.addRow(w) else: self.layout.addRow(key, w) self.widgets[key] = w return 1 else: return -1 else: return -1 def addText(self, key, value=""): if not self.overwriteKeys(key): if type(key).__name__=='str': w = QTextEdit() self.connect(w, SIGNAL("textChanged()"), self.argumentChanged) w.setPlainText(value) if not self.displaykey: self.layout.addRow(w) else: self.layout.addRow(key, w) self.widgets[key] = w return 1 else: return -1 else: return -1 def addListArgument(self, key, typeid, predefs, editable=False, config=None): if not self.overwriteKeys(key) and type(key) == types.StringType: w = multipleListWidget(self, typeid, predefs, editable) if not self.displaykey: self.layout.addRow(w) else: self.layout.addRow(key, w) self.widgets[key] = w.valuelist if config: w.addParameterConfig(config) return 1 else: return -1 def addPathList(self, key, typeid, predefs, selectednodes): if not self.overwriteKeys(key) and type(key).__name__=='str': layout = QVBoxLayout() listpathcontainer = QListWidget() ##XXX listpathcontainer.setDragDropMode(QAbstractItemView.InternalMove) if len(predefs) > 0: if not self.checkUnifiedTypes(predefs): return -1 for predef in predefs: listpathcontainer.insertItem(listpathcontainer.count() + 1, str(predef)) if selectednodes and len(selectednodes) > 0: for node in selectednodes: if type(node) == Node and typeid == typeId.Node: listpathcontainer.insertItem(listpathcontainer.count() + 1, QString.fromUtf8(node.absolute())) elif type(node) != Node: listpathcontainer.insertItem(listpathcontainer.count() + 1, node) hbox = QHBoxLayout() buttonbox = QDialogButtonBox() if typeid == typeId.Path: combo = QComboBox() self.connect(combo, SIGNAL("editTextChanged(QString)"), self.argumentChanged) self.connect(combo, SIGNAL("currentIndexChanged(QString)"), self.argumentChanged) combo.addItem(self.inputFile) combo.addItem(self.inputDirectory) add = addLocalPathButton(self, key, listpathcontainer, combo) else: add = addLocalPathButton(self, key, listpathcontainer, nodetype=True) buttonbox.addButton(add, QDialogButtonBox.ActionRole) rm = rmLocalPathButton(self, listpathcontainer) buttonbox.addButton(rm, QDialogButtonBox.ActionRole) self.connect(add, SIGNAL("clicked()"), self.argumentChanged) self.connect(rm, SIGNAL("clicked()"), self.argumentChanged) hbox.addWidget(buttonbox, 3, Qt.AlignLeft) if typeid == typeId.Path: hbox.addWidget(combo, 1, Qt.AlignRight) layout.addLayout(hbox, 0) layout.addWidget(listpathcontainer, 2) if not self.displaykey: self.layout.addRow(layout) else: self.layout.addRow(key, layout) self.widgets[key] = listpathcontainer return 1 else: return -1 def addPath(self, key, typeid, predefs, selectednodes, editable=False, config=None): if config: predefs.push_front(config[0]) if not self.overwriteKeys(key) and type(key).__name__=='str': vbox = QVBoxLayout() if typeid == typeId.Path: combo = QComboBox() self.connect(combo, SIGNAL("editTextChanged(QString)"), self.argumentChanged) self.connect(combo, SIGNAL("currentIndexChanged(QString)"), self.argumentChanged) combo.addItem(self.inputFile) combo.addItem(self.inputDirectory) vbox.addWidget(combo) layout = QHBoxLayout() if len(predefs) > 0 or len(selectednodes) > 0: pathcontainer = QComboBox() self.connect(pathcontainer, SIGNAL("editTextChanged(QString)"), self.argumentChanged) self.connect(pathcontainer, SIGNAL("currentIndexChanged(QString)"), self.argumentChanged) pathcontainer.setEditable(editable) for value in predefs: if typeid == typeId.Node: pathcontainer.addItem(value.value().name()) else: pathcontainer.addItem(value.toString()) if typeid == typeId.Node: for node in selectednodes: pathcontainer.addItem(QString.fromUtf8(node.absolute())) else: pathcontainer = QLineEdit() pathcontainer.setReadOnly(not editable) self.connect(pathcontainer, SIGNAL("editingFinished()"), self.argumentChanged) if typeid == typeId.Path: browse = addLocalPathButton(self, key, pathcontainer, inputchoice=combo) else: browse = addLocalPathButton(self, key, pathcontainer, nodetype=True) layout.addWidget(pathcontainer, 2) layout.addWidget(browse, 0) vbox.addLayout(layout) if not self.displaykey: self.layout.addRow(vbox) else: self.layout.addRow(key, vbox) self.widgets[key] = pathcontainer return 1 else: return -1 def checkUnifiedTypes(self, values): if len(values) == 0: return vtype = type(values[0]).__name__ for v in values: if type(v).__name__!=vtype: return False return True def get(self, key): for k, v in self.widgets.iteritems(): if k == key: if isinstance(self.widgets[k], QLineEdit): return str(v.text().toUtf8()) elif isinstance(self.widgets[k], QListWidget): items = [] for index in xrange(self.widgets[k].count()): items.append(str(self.widgets[k].item(index).text().toUtf8())) return items elif isinstance(self.widgets[k], QCheckBox): state = self.widgets[k].checkState() if state == Qt.Unchecked: return False else: return True elif isinstance(self.widgets[k], QTextEdit): return str(self.widgets[k].toPlainText().toUtf8()) elif isinstance(self.widgets[k], QComboBox): return str(self.widgets[k].currentText().toUtf8()) else: return -1 def argumentChanged(self, event = None): self.emit(SIGNAL("argumentChanged()")) def translation(self): self.inputFile = self.tr("File") self.inputDirectory = self.tr("Directory") def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() else: QWidget.changeEvent(self, event) class fieldValidator(QRegExpValidator): def __init__(self, parent, typeid): QRegExpValidator.__init__(self, parent) self.typeid = typeid self.init() def init(self): if self.typeid in (typeId.Int16, typeId.Int32, typeId.Int64): exp = "^(\+|-)?\d+$" elif self.typeid in (typeId.UInt16, typeId.UInt32, typeId.UInt64): exp = "^\d+$" else: exp = "^.+$" regexp = QRegExp(exp) regexp.setCaseSensitivity(Qt.CaseInsensitive) self.setRegExp(regexp) class multipleListWidget(QWidget): def __init__(self, parent, typeid, predefs, editable): QWidget.__init__(self) self.parent = parent self.typeid = typeid self.editable = editable self.predefs = predefs self.init() def init(self): self.vbox = QVBoxLayout() self.vbox.setSpacing(5) self.vbox.setMargin(0) self.createHeader() self.valuelist = QListWidget() self.vbox.addWidget(self.valuelist) self.setLayout(self.vbox) def createHeader(self): self.whead = QWidget() self.headerlayout = QHBoxLayout() self.headerlayout.setSpacing(0) self.headerlayout.setMargin(0) if self.typeid in (typeId.Node, typeId.Path) and self.editable: self.addPath() else: self.addSingleArgument() self.addButton = QPushButton(QIcon(":add.png"), "") self.rmButton = QPushButton(QIcon(":del_dump.png"), "") self.addButton.setIconSize(QSize(16, 16)) self.rmButton.setIconSize(QSize(16, 16)) self.connect(self.addButton, SIGNAL("clicked()"), self.addParameter) self.connect(self.rmButton, SIGNAL("clicked()"), self.rmParameter) self.connect(self.addButton, SIGNAL("clicked()"), self.parent.argumentChanged) self.connect(self.rmButton, SIGNAL("clicked()"), self.parent.argumentChanged) self.headerlayout.addWidget(self.addButton, 0) self.headerlayout.addWidget(self.rmButton, 0) self.whead.setLayout(self.headerlayout) self.vbox.addWidget(self.whead) def addParameterConfig(self, config): try : if len(config) : for item in config: self.valuelist.insertItem(self.valuelist.count() + 1, item) except TypeError: self.valuelist.insertItem(self.valuelist.count() + 1, config) def addParameter(self): if isinstance(self.container, QComboBox): item = self.container.currentText() else: item = self.container.text() if len(self.valuelist.findItems(item, Qt.MatchExactly)) == 0: self.valuelist.insertItem(self.valuelist.count() + 1, item) def rmParameter(self): selected = self.valuelist.selectedItems() for item in selected: row = self.valuelist.row(item) self.valuelist.takeItem(row) def addSingleArgument(self): if len(self.predefs) > 0: self.container = QComboBox() for value in self.predefs: if self.typeid == typeId.Node: self.container.addItem(value.value().name()) else: self.container.addItem(value.toString()) self.container.setEditable(self.editable) else: self.container = QLineEdit() self.container.setReadOnly(self.editable) self.headerlayout.addWidget(self.container, 2) def addPath(self): if len(self.predefs) > 0: self.container = QComboBox() self.container.setReadOnly(False) for value in self.predefs: self.container.addItem(value.toString()) else: self.container = QLineEdit() self.container.setReadOnly(False) if self.typeid == typeId.Path: browse = addLocalPathButton(self, key, self.container, isdir=False) else: browse = addLocalPathButton(self, key, self.container, isdir=False, nodetype=True) self.headerlayout.addWidget(self.container, 2) self.headerlayout.addWidget(browse, 0) def addPredefValue(self): selected = self.predefs.selectedItems() for item in selected: self.valuelist.insertItem(self.valuelist.count() + 1, item.text()) class addLocalPathButton(QPushButton): lastPath = os.path.expanduser('~') def __init__(self, parent, key, container, inputchoice=None, nodetype=False): if isinstance(container, QListWidget): QPushButton.__init__(self, QIcon(":add.png"), "") else: QPushButton.__init__(self, QIcon(":folder.png"), "...") self.setIconSize(QSize(16, 16)) self.manager = parent self.inputcombo = inputchoice self.ckey = key self.container = container self.parent = container self.nodetype = nodetype self.connect(self, SIGNAL("clicked()"), self.browse) def setLastPath(self, path): path = str(path.toUtf8()) if path.rfind('/') != -1: addLocalPathButton.lastPath = path[:path.rfind('/') + 1] elif path.rfind('\\') != -1: addLocalPathButton.lastPath = path[:path.rfind('\\') + 1] def browse(self): title = "Load " + str(self.ckey) if not self.nodetype: if self.inputcombo and self.inputcombo.currentIndex() == 0: if isinstance(self.container, QListWidget): sFileName = QFileDialog.getOpenFileNames(self.parent, title, addLocalPathButton.lastPath) if len(sFileName) > 0: self.setLastPath(sFileName[0]) for name in sFileName: item = QListWidgetItem(name, self.container) elif isinstance(self.container, QLineEdit): sFileName = QFileDialog.getOpenFileName(self.parent, title, addLocalPathButton.lastPath) self.setLastPath(sFileName) self.container.clear() self.container.insert(sFileName) elif isinstance(self.container, QComboBox): sFileName = QFileDialog.getOpenFileName(self.parent, title, addLocalPathButton.lastPath) self.setLastPath(sFileName) self.container.insertItem(0, sFileName) self.container.setCurrentIndex(0) else: return -1 else: sFileName = QFileDialog.getExistingDirectory(self.parent, title, addLocalPathButton.lastPath, QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) self.setLastPath(sFileName) if isinstance(self.container, QListWidget): if sFileName: item = QListWidgetItem(sFileName, self.container) elif isinstance(self.container, QComboBox): self.container.insertItem(0, sFileName) self.container.setCurrentIndex(0) else: self.container.insert(sFileName) self.manager.emit(SIGNAL("managerChanged")) else: BrowseVFSDialog = DialogNodeBrowser(self) if isinstance(self.container, QListWidget) or isinstance(self.container, QComboBox): iReturn = BrowseVFSDialog.exec_() if iReturn : nodes = BrowseVFSDialog.getSelectedNodes() index = 0 if len(nodes): for node in nodes: self.container.insertItem(index, QString.fromUtf8(node.absolute())) index += 1 if isinstance(self.container, QListWidget): self.container.setCurrentItem(self.container.item(0)) else: self.container.setCurrentIndex(0) else: iReturn = BrowseVFSDialog.exec_() if iReturn : node = BrowseVFSDialog.getSelectedNode() print node if node: self.container.clear() self.container.insert(QString.fromUtf8(node.absolute())) BrowseVFSDialog.browser.__del__() class rmLocalPathButton(QPushButton): def __init__(self, parent, container): QPushButton.__init__(self, QIcon(":del_dump.png"),"") self.setIconSize(QSize(16, 16)) self.container = container self.manager = parent self.connect(self, SIGNAL("clicked()"), self.rm) def rm(self): selected = self.container.selectedItems() for item in selected: row = self.container.row(item) self.container.takeItem(row) self.manager.emit(SIGNAL("managerChanged")) dff-1.3.0+dfsg.1/dff/api/gui/widget/nodelistwidgets.py000066400000000000000000000747631217176075400225240ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * import re from dff.api.vfs.vfs import vfs, Node from dff.api.vfs.libvfs import VFS, VecNode, TagsManager from dff.api.types.libtypes import typeId, Variant, RCVariant from dff.api.filters.libfilters import Filter from dff.api.events.libevents import event, EventHandler from dff.api.gui.widget.propertytable import PropertyTable from dff.api.gui.model.node_list import NodeListModel from dff.api.gui.model.tree import TreeModel from dff.api.gui.model.selection import SelectionManager from dff.api.gui.view.tree import NodeTreeView from dff.api.gui.widget.nodewidget import NodeWidget from dff.api.gui.widget.search.thread import SearchThread from dff.api.gui.widget.search.search_widget import SearchPanel from dff.api.gui.widget.search.filter import FilterBar from dff.api.gui.dialog.selectattributes import SelectAttributesWizard from dff.ui.gui.utils.menu import tagMenu, typeFilterMenu, BookmarkManager from dff.ui.gui.resources.ui_browser_toolbar import Ui_BrowserToolBar from dff.ui.gui.resources.ui_filter_widget import Ui_filterWidget from dff.ui.gui.resources.ui_filter_tagwidget import Ui_filterTagwidget # browser modes SIMPLE = 0 # No navigation, no filters, no search, no tree #FILTER = 1 # No navigation, no search, no tree ADVANCED = 1 # All features #VIEW PAN LIST_VIEW = 0 ICON_VIEW = 1 SEARCH_RESULT = 2 FILTER_RESULT = 3 # LEFT PAN TREE_VIEW = 0 SEARCH_PAN = 1 class NodeListWidgets(Ui_BrowserToolBar, QWidget, EventHandler): def __init__(self, parent=None, mode=ADVANCED): EventHandler.__init__(self) super(QWidget, self).__init__(parent) self.setupUi(self) self.type = "filebrowser" self.icon = None self.name = "nodebrowser" self.setObjectName(self.name) #Define browser functions self.mode = mode self.mainwindow = QApplication.instance().mainWindow # Main layout self.mainlayout = QVBoxLayout() self.mainlayout.setSpacing(0) self.mainlayout.setMargin(0) self.createSelection() self.attributes = PropertyTable(self) if mode == ADVANCED: self.createNavigationHeader() self.createToolbar() self.createViewPan() self.createViews() self.setLayout(self.mainlayout) self.VFS = VFS.Get() self.VFS.connection(self) self.connect(self, SIGNAL("refreshList"), self.refreshList) self.bookManager = BookmarkManager(self.model()) def __del__(self): self.VFS.deconnection(self) self.treemodel.VFS.deconnection(self.treemodel) def Event(self, e): """ Add e.value, which is a Variant containing a Node, in the tree (only if it has children or is a directory). """ self.emit(SIGNAL("refreshList"), e) def refreshList(self, e): if e.value != None: if self.mode == ADVANCED: node = e.value.value() if node == None or self.navigation.currentNode == None: return try: parent = node.parent() navnode = self.navigation.currentNode # XXX Identify event type (add node or apply module) if navnode.absolute() == parent.absolute(): child = parent.children() elif navnode.absolute() == parent.parent().absolute(): child = parent.parent().children() else: return self.currentView().model.changeList(child) self.currentView().refreshVisible() except: pass def createSelection(self): self.selection = SelectionManager() self.connect(self.selection, SIGNAL("selectionChanged()"), self.refreshModels) def createNavigationHeader(self): self.header = QSplitter(Qt.Horizontal) self.navigation = NavigationBar(self) self.navigationtoolbar = self.navigation.getPathbar() self.header.addWidget(self.navigationtoolbar) self.header.setStretchFactor(0, 60) self.mainlayout.addWidget(self.header, 0) def createToolbar(self): self.toolbar = QToolBar() self.toolbar.setMaximumHeight(32) self.toolbar.addAction(self.actionFactorMinus) self.connect(self.factorSlider, SIGNAL("valueChanged(int)"), self.refreshIconSize) self.toolbar.addWidget(self.factorSlider) self.toolbar.addAction(self.actionFactorPlus) self.connect(self.actionFactorMinus, SIGNAL("triggered()"), self.factorminus) self.connect(self.actionFactorPlus, SIGNAL("triggered()"), self.factorplus) self.toolbar.addWidget(self.changeView) self.connect(self.changeView, SIGNAL("currentIndexChanged(int)"), self.viewChanged) self.toolbar.addAction(self.actionAttributes) self.connect(self.actionAttributes, SIGNAL("triggered()"), self.selectAttributes) self.toolbar.addAction(self.actionBookmark) self.connect(self.actionBookmark, SIGNAL("triggered()"), self.bookmark) menutag = tagMenu(self, self.mainwindow) self.tags.setMenu(menutag) self.toolbar.addWidget(self.tags) if self.mode == ADVANCED: self.toolbar.addWidget(self.search) self.connect(self.search, SIGNAL("clicked(bool)"), self.activateSearchPan) else: self.search.setVisible(False) self.toolbar.addWidget(self.filter) self.connect(self.filter, SIGNAL("clicked(bool)"), self.viewFilter) self.mainlayout.addWidget(self.toolbar, 0) def viewFilter(self): if self.filter.isChecked(): self.infostack.setCurrentWidget(self.filterwidget) self.viewpan.setCurrentWidget(self.filterview) self.filterwidget.resetFilter() m = self.currentView().model # if self.filter.isChecked(): self.filterview.model.setDefaultAttributes() self.filterview.model.setSelectedAttributes(m.selectedAttributes()) self.infostack.show() else: self.infostack.setCurrentWidget(self.filterwidget) self.viewpan.setCurrentWidget(self.currentView()) self.infostack.hide() def factorminus(self): value = self.factorSlider.value() - 1 if value >= 1: self.factorSlider.setValue(value) self.refreshIconSize(value) def factorplus(self): value = self.factorSlider.value() + 1 if value <= 4: self.factorSlider.setValue(value) self.refreshIconSize(value) def refreshIconSize(self, value): for view in self.views: view.refreshIconSize(value) def createViewPan(self): self.viewstack = QWidget() self.viewlayout = QVBoxLayout() self.viewlayout.setSpacing(0) self.viewlayout.setMargin(0) self.viewpan = QStackedWidget() self.infostack = QStackedWidget() self.filterwidget = FilterWidget(self) self.infostack.addWidget(self.filterwidget) self.infostack.hide() self.viewlayout.addWidget(self.infostack, 0) self.viewlayout.addWidget(self.viewpan, 90) self.viewstack.setLayout(self.viewlayout) def createNodeWidget(self, selection, tabmode=False, filtermode=False): return NodeWidget(selection, tabmode, filtermode) def createViews(self): self.views = [] self.splitter = QSplitter(self) self.browserview = self.createNodeWidget(self.selection) self.connect(self.browserview, SIGNAL("nodePressed"), self.nodePressed) # append self.views.append(self.browserview) self.viewpan.addWidget(self.browserview) self.leftpan = QStackedWidget() if self.mode == ADVANCED: # Tree view self.treeview = NodeTreeView(self) self.treemodel = TreeModel(self, self.selection) self.treeview.setModel(self.treemodel) self.leftpan.addWidget(self.treeview) self.connect(self.treeview, SIGNAL("nodeTreeClicked"), self.nodetreeclicked) self.navigation.connect(self.browserview, SIGNAL("pathChanged"), self.navigation.rootpathchanged) self.navigation.connect(self.treeview, SIGNAL("nodeTreeClicked"), self.navigation.pathChanged) # Search view self.searchview = self.createNodeWidget(self.selection,tabmode=True) self.connect(self.searchview, SIGNAL("nodePressed"), self.nodePressed) self.views.append(self.searchview) self.viewpan.addWidget(self.searchview) # Filter view self.filterview = self.createNodeWidget(self.selection, filtermode=True) self.connect(self.filterview, SIGNAL("enterFilter"), self.enterFilter) self.connect(self.filterview, SIGNAL("nodePressed"), self.nodePressed) if self.mode == ADVANCED: self.navigation.connect(self.filterview, SIGNAL("pathChanged"), self.navigation.rootpathchanged) self.views.append(self.filterview) self.viewpan.addWidget(self.filterview) if self.mode == ADVANCED: self.searchwidget = SearchPanel(self, self.searchview) self.leftpan.addWidget(self.searchwidget) self.splitter.addWidget(self.leftpan) self.splitter.addWidget(self.viewstack) self.splitter.addWidget(self.attributes) self.splitter.setStretchFactor(0, 25) self.splitter.setStretchFactor(1, 60) self.splitter.setStretchFactor(2, 15) self.mainlayout.addWidget(self.splitter, 50) def nodePressed(self, node): self.attributes.fill(node) self.mainwindow.emit(SIGNAL("previewUpdate"), node) def enterFilter(self, node): if self.filterwidget.lock.isChecked(): self.browserview.enterDirectory(node) self.filterwidget.quickFilter() else: self.browserview.enterDirectory(node) self.filterwidget.resetFilter() def refreshModels(self): self.model().emit(SIGNAL("layoutChanged()")) if self.mode == ADVANCED: self.treemodel.emit(SIGNAL("layoutChanged()")) def activateSearchPan(self, state): if self.mode == ADVANCED: if state: self.leftpan.setCurrentIndex(SEARCH_PAN) self.navigationtoolbar.setEnabled(False) if not self.filter.isChecked(): self.viewpan.setCurrentWidget(self.searchview) else: self.viewpan.setCurrentWidget(self.filterview) else: self.leftpan.setCurrentIndex(TREE_VIEW) self.navigationtoolbar.setEnabled(True) if not self.filter.isChecked(): self.viewpan.setCurrentWidget(self.browserview) else: self.viewpan.setCurrentWidget(self.filterview) self.model().refresh(self.model().currentRow()) else: if state: self.searchwidget = SearchPanel(self, self.searchview) self.leftpan.addWidget(self.searchwidget) self.leftpan.setCurrentWidget(self.searchwidget) if not self.filter.isChecked(): self.viewpan.setCurrentWidget(self.searchview) else: self.viewpan.setCurrentWidget(self.filterview) self.leftpan.show() else: self.leftpan.removeWidget(self.searchwidget) self.model().refresh(self.model().currentRow()) if not self.filter.isChecked(): self.viewpan.setCurrentWidget(self.browserview) else: self.viewpan.setCurrentWidget(self.filterview) self.leftpan.hide() self.filterwidget.resetFilter() def applyFilter(self): if self.filter.isChecked(): if self.filterwidget.lock.isChecked(): self.filterwidget.quickFilter() else: self.filterwidget.resetFilter() def nodetreeclicked(self, node, button, rec=False): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) if not rec: self.currentView().model.emit(SIGNAL("changeList"), node.children()) else: res = [] self.recurseNodes(node, res) res.remove(node) self.currentView().model.emit(SIGNAL("changeList"), res) self.currentView().model.refresh(self.model().currentRow()) self.currentView().refreshVisible() self.applyFilter() QApplication.restoreOverrideCursor() def recurseNodes(self, node, res): res.append(node) if node.hasChildren(): childs = node.children() for child in childs: self.recurseNodes(child, res) def viewChanged(self, index): curentview = self.viewpan.currentWidget() curentview.emit(SIGNAL("changeView"), index) def selectAttributes(self): model = self.currentView().model attr = model.availableAttributes() wiz = SelectAttributesWizard(self.currentView().model, model.selectedAttributes(), model.defaultAttributes()) iret = wiz.exec_() if iret == 1: selected = wiz.getSelectedAttributes() model.setSelectedAttributes(selected) if self.filter.isChecked(): self.filterview.model.setSelectedAttributes(selected) def bookmark(self): self.bookManager.launch() def currentView(self): if not self.search.isChecked(): return self.browserview else: return self.searchview def views(self): views = [] views.append(self.browser) views.append(self.search) def models(self): model_list = [] model_list.append(self.browser.model) model_list.append(self.search.model) return model_list def model(self): return self.viewpan.currentWidget().model def changeList(self, nodelist): self.browserview.model.emit(SIGNAL("changeList"), nodelist) ######################################## # NAVIGATION ######################################## class FilterWidget(Ui_filterWidget, QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.setupUi(self) self.parent = parent self.edit = self.filterCombo.lineEdit() self.filterMode = {0: "$", 1: "~", 2: "/", 3: "\""} self.query = "" self.createFilterThread() self.connect(self.filterTH, SIGNAL("match"), self.updateMatchedNodes) self.connect(self.filterTH, SIGNAL("finished"), self.searchStoped) self.connect(self.filterTH, SIGNAL("started"), self.searchStarted) self.connect(self.filterTH, SIGNAL("stoped"), self.searchStoped) self.connect(self.clear, SIGNAL("clicked(bool)"), self.resetFilter) self.connect(self.stop, SIGNAL("clicked(bool)"), self.stopFilter) self.connect(self.edit, SIGNAL("textChanged(QString)"), self.updateQuery) self.connect(self.mode, SIGNAL("currentIndexChanged(int)"), self.modeChanged) self.redstyle = QString("QWidget {color:red}") self.greenstyle = QString("QWidget {color:green}") self.blackstyle = QString("QWidget {color:black}") self.matched = 0 self.stop.setEnabled(False) self.timer = QTimer(self) self.timer.setSingleShot(True) self.filtertagwidget = FilterTagWidget(self) self.filtertagwidget.hide() self.connect(self.timer, SIGNAL("timeout()"), self.quickFilter) def createFilterThread(self): self.filterTH = SearchThread(self) def updateQuery(self, query): self.timer.start(1000) if self.mode.currentIndex() in xrange(0,4): self.query = query else: f = Filter("completer") try: q = str(unicode(query).encode('utf-8')) f.compile(q) self.edit.setStyleSheet(self.greenstyle) except RuntimeError: self.edit.setStyleSheet(self.redstyle) def modeChanged(self, index): if index == 5: self.verticalLayout.addWidget(self.filtertagwidget) self.filtertagwidget.toolbar.refreshTags() self.filterCombo.setEnabled(False) self.filtertagwidget.show() else: self.verticalLayout.removeWidget(self.filtertagwidget) self.filterCombo.setEnabled(True) self.filtertagwidget.hide() def launchFilter(self, query=None): if not query: query = self.filterCombo.lineEdit().text() else: query = query nodelist = self.sourceModel().list() if len(nodelist) > 0: self.parent.filterview.model.clearList() q = str(unicode(query).encode('utf-8')) r = self.filterTH.setListContext(q, nodelist, self.parent.filterview.model) if r: self.filterTH.start() def quickFilter(self): self.timer.stop() index = self.mode.currentIndex() if index in xrange(0,4): self.filterTH.stopSearch() if self.query == "": self.resetFilter() else: self.resetFilter() q = "name matches " + self.filterMode[index] + self.query + self.filterMode[index] self.launchFilter(q) else: try: query = self.filterCombo.lineEdit().text() if query != "": f = Filter("test") q = str(unicode(query).encode('utf-8')) f.compile(q) self.edit.setStyleSheet(self.greenstyle) self.resetFilter() self.launchFilter() else: self.resetFilter() except RuntimeError: self.edit.setStyleSheet(self.redstyle) def stopFilter(self): self.filterTH.stopSearch def sourceModel(self): if self.parent.search.isChecked(): return self.parent.searchview.model else: return self.parent.browserview.model def resetFilter(self): self.edit.setStyleSheet(self.blackstyle) self.parent.filterview.model.changeList(self.sourceModel().list()) count = len(self.sourceModel().list()) if count > 0: self.reslabel.setStyleSheet(self.greenstyle) self.countlabel.setStyleSheet(self.greenstyle) else: self.reslabel.setStyleSheet(self.redstyle) self.countlabel.setStyleSheet(self.redstyle) self.countlabel.setText(str(count)) self.reslabel.setText(str(count)) self.parent.filterview.refreshVisible() def updateMatchedNodes(self): if self.matched == 0: self.reslabel.setStyleSheet(self.greenstyle) self.countlabel.setStyleSheet(self.greenstyle) self.matched += 1 self.countlabel.setText(str(self.matched)) self.parent.filterview.refreshVisible() def searchStoped(self): QApplication.restoreOverrideCursor() self.stop.setEnabled(False) def searchStarted(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.stop.setEnabled(True) self.matched = 0 self.reslabel.setStyleSheet(self.redstyle) self.countlabel.setStyleSheet(self.redstyle) self.countlabel.setText(str(self.matched)) self.reslabel.show() self.countlabel.show() class FilterTagWidget(Ui_filterTagwidget, QWidget): def __init__(self, filterw): QWidget.__init__(self, filterw) self.setupUi(self) self.filterw = filterw self.toolbar = TagToolbar(self) self.horizontalLayout.addWidget(self.toolbar, 100) class TagToolbar(QToolBar): def __init__(self, parent): QToolBar.__init__(self) self.filtertw = parent self.filterw = parent.filterw self.tagsmanager = TagsManager.get() self.tagbuttons = [] self.refreshTags() def refreshTags(self): self.clear() tags = self.tagsmanager.tags() for tag in tags: t = TagAction(self, tag) self.addWidget(t) self.tagbuttons.append(t) def refreshQuery(self): # Count checked : count = 0 for tagb in self.tagbuttons: if tagb.isChecked(): count += 1 # Build Query if count > 0: if self.filtertw.exclude.isChecked(): q = "not tags in [" else: q = "tags in [" check = 0 for tagb in self.tagbuttons: if tagb.isChecked(): q += "\"" + str(unicode(tagb.text()).encode('utf-8')) + "\"" if check < count -1: q += "," check += 1 q += "]" self.filterw.filterCombo.lineEdit().clear() self.filterw.filterCombo.lineEdit().setText(QString(q)) else: q = "" self.filterw.filterCombo.lineEdit().clear() self.filterw.quickFilter() class TagAction(QToolButton): def __init__(self, toolbar, tag): QToolButton.__init__(self) self.tag = tag self.toolbar = toolbar self.setCheckable(True) self.createStyle() self.connect(self, SIGNAL("clicked()"), self.toolbar.refreshQuery) self.setText(QString.fromUtf8(self.tag.name())) def createStyle(self): color = self.tag.color() s = "QToolButton {color: rgb(" + str(color.r) + "," + str(color.g) + "," + str(color.b) + ")}" self.setStyleSheet(QString(s)) class ToolButtonBar(QToolBar): def __init__(self, parent): QToolBar.__init__(self) self.navigation = parent self.setIconSize(QSize(16,16)) self.createStyle() self.setStyleSheet(self.mainstyle) sizepolicy = QSizePolicy() sizepolicy.setHorizontalStretch(50) sizepolicy.setHorizontalPolicy(QSizePolicy.Expanding) self.setSizePolicy(sizepolicy) self.linedit = QLineEdit() def createStyle(self): self.mainstyle = "QToolBar {background: #eeeeee;spacing: 3px; border: 1px solid grey; border-radius: 2px;}" self.hoverstyle = "QToolBar {background: white;spacing: 3px; border: 1px solid grey; border-radius: 2px;}" # self.teststyle = "QToolBar {background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #000000);}" def mousePressEvent(self, event): self.navigation.navbars.setCurrentIndex(1) def enterEvent(self, event): self.setStyleSheet(self.hoverstyle) def leaveEvent(self, event): self.setStyleSheet(self.mainstyle) class ToolEditBar(QLineEdit): def __init__(self, parent): QLineEdit.__init__(self) self.navigation = parent self.vfs = vfs() QObject.connect(self, SIGNAL("textEdited(const QString &)"), self.updatePath) self.connect(self, SIGNAL("editingFinished()"), self.focusOut) def updatePath(self, path): path = unicode(path).encode('utf-8') spath = path.split("/") spath.pop(0) node = self.vfs.getnode("/") for nodename in spath: if node != None: tmpnode = self.getChild(node, nodename) if tmpnode == None: complete = self.filter(nodename, node) if len(complete) > 0: menu = Completer(self) for count, comp in enumerate(complete): item = QAction(self) item.setText(QString.fromUtf8(comp.name())) item.setIcon(QIcon(":folder.png")) item.setData(comp.absolute()) if count == 0: menu.setDefaultAction(item) menu.addAction(item) menu.setFixedWidth(self.width()) menu.popup(self.mapToGlobal(QPoint(0,self.height()))) else: node = tmpnode def getChild(self, parent, childname): children = parent.children() for child in children: if parent.absolute() != "/": if child.isDir() or child.hasChildren(): if child.name() == childname: return child else: if child.name() == childname: return child return None def filter(self, pattern, node): children = self.getDirectories(node) if len(children) > 0: f = Filter("completer") exp = '(name matches re("^'+ pattern +'",i))' f.compile(exp) f.process(children) possible = f.matchedNodes() return possible return [] def signalRouter(self, action): self.emit(SIGNAL("changeDirectory"), action) def getDirectories(self, node): res = VecNode() if node.absolute() != "/": children = node.children() for child in children: if child.isDir() or child.hasChildren(): res.append(child) else: res = node.children() return res def focusOut(self): self.navigation.navbars.setCurrentIndex(0) class Completer(QMenu): def __init__(self, linedit): QMenu.__init__(self, linedit) self.linedit = linedit self.connect(self, SIGNAL("triggered(QAction*)"), self.resetLineEdit) self.connect(self, SIGNAL("hovered(QAction*)"), self.resetLineEdit) def keyPressEvent(self, event): actions = self.actions() active = self.activeAction() try: idaction = actions.index(active) except: idaction = -1 if event.matches(QKeySequence.MoveToPreviousLine): if idaction > 0: idaction = idaction - 1 else: idaction = 0 self.setActiveAction(actions[idaction]) self.resetLineEdit(actions[idaction]) elif event.matches(QKeySequence.MoveToNextLine): if idaction < len(actions) - 1: self.setActiveAction(actions[idaction + 1]) self.resetLineEdit(actions[idaction + 1]) elif event.matches(QKeySequence.InsertParagraphSeparator): if idaction >= 0: self.resetLineEdit(actions[idaction], True) self.hide() else: QLineEdit.keyPressEvent(self.linedit, event) else: self.hide() QLineEdit.keyPressEvent(self.linedit, event) def resetLineEdit(self, action, route=False): self.linedit.clear() self.linedit.setText(QString.fromUtf8(action.data().toString())) if route: self.linedit.signalRouter(action) class NavigationBar(QWidget): def __init__(self, parent): QWidget.__init__(self) self.parent = parent self.vfs = vfs() self.history = ["/"] self.currentPathId = -1 self.currentNode = self.vfs.getnode("/") # Create navigation buttons self.maintoolbar = QToolBar(self) self.maintoolbar.setIconSize(QSize(24,24)) self.setPreviousButton() self.setNextButton() self.setTopButton() self.setHomeButton() self.pathbar = ToolButtonBar(self) self.editbar = ToolEditBar(self) self.navbars = QStackedWidget() self.navbars.setMaximumHeight(25) self.navbars.addWidget(self.pathbar) self.navbars.addWidget(self.editbar) self.maintoolbar.addWidget(self.navbars) self.connect(self.editbar, SIGNAL("changeDirectory"), self.pathbarchanged) self.connect(self.pathbar, SIGNAL("actionTriggered(QAction*)"), self.pathbarchanged) def mousePressEvent(self, event): self.navbars.setCurrentIndex(0) def setHomeButton(self): self.historymenu = QMenu() self.homebutton = QToolButton() self.homebutton.setIcon(QIcon(":home.png")) self.homebutton.setMenu(self.historymenu) self.homebutton.setPopupMode(QToolButton.MenuButtonPopup) self.maintoolbar.addWidget(self.homebutton) self.connect(self.homebutton, SIGNAL("clicked()"), self.goHome) self.connect(self.historymenu, SIGNAL("triggered(QAction*)"), self.menuTriggered) def setPreviousButton(self): self.prevbutton = QToolButton() self.prevbutton.setIcon(QIcon(":previous.png")) self.prevbutton.setDisabled(True) self.maintoolbar.addWidget(self.prevbutton) self.connect(self.prevbutton, SIGNAL("pressed()"), self.moveToPrevious) def setNextButton(self): self.nextbutton = QToolButton() self.nextbutton.setIcon(QIcon(":next.png")) self.nextbutton.setDisabled(True) self.maintoolbar.addWidget(self.nextbutton) self.connect(self.nextbutton, SIGNAL("pressed()"), self.moveToNext) def setTopButton(self): self.topbutton = QToolButton() self.topbutton.setIcon(QIcon(":top.png")) self.topbutton.setDisabled(True) self.maintoolbar.addWidget(self.topbutton) self.connect(self.topbutton, SIGNAL("pressed()"), self.moveToTop) def setHistoryMenu(self): self.historymenu.clear() for path in self.history: p = QString.fromUtf8(path) self.historymenu.addAction(p) def menuTriggered(self, action): path = action.text().toUtf8() path = unicode(path, 'UTF-8').encode("UTF-8") node = self.vfs.getnode(path) if node: self.refreshNode(node) def pathInHistory(self, path, hlist): for p in hlist: if p == path: return True return False def goHome(self): home = self.vfs.getnode("/") if home != None: self.refreshNode(home) def moveToTop(self): if self.currentNode != None: self.refreshNode(self.currentNode.parent()) def moveToPrevious(self): if self.currentPathId > 0: self.currentPathId = self.currentPathId - 1 path = self.history[self.currentPathId] node = self.vfs.getnode(path) self.refreshNode(node) def moveToNext(self): if self.currentPathId < len(self.history) - 1: self.currentPathId = self.currentPathId + 1 path = self.history[self.currentPathId] node = self.vfs.getnode(path) self.refreshNode(node) def refreshNode(self, node): if node != None: self.parent.changeList(node.children()) self.currentNode = node self.changeNavigationState() self.parent.treeview.expandToNode(self.currentNode) self.parent.viewpan.currentWidget().refreshVisible() self.history.append(str(node.absolute())) self.parent.applyFilter() def pathChanged(self, node): try: path = node.absolute() if len(self.history) > 0: if not self.pathInHistory(path, self.history): self.history.append(str(node.absolute())) self.currentPathId = len(self.history) - 1 self.currentNode = node self.parent.browserview.refreshVisible() self.changeNavigationState() return True return True except: return False def rootpathchanged(self, node, button=None): self.pathChanged(node) self.parent.treeview.expandToNode(node) def changeNavigationState(self): if self.currentNode: if self.currentNode.absolute() != "/": self.topbutton.setEnabled(True) else: self.topbutton.setEnabled(False) self.editbar.clear() self.editbar.setText(QString.fromUtf8(self.currentNode.absolute())) self.setHistoryMenu() if self.currentPathId > 0: self.prevbutton.setEnabled(True) else: self.prevbutton.setEnabled(False) if self.currentPathId < len(self.history) -1: self.nextbutton.setEnabled(True) else: self.nextbutton.setEnabled(False) self.refreshPathbar() def getPathbar(self): return self.maintoolbar def pathbarchanged(self, action): path = action.data().toByteArray() path = unicode(path, 'UTF-8').encode("UTF-8") node = self.vfs.getnode(path) if node: self.refreshNode(node) def refreshPathbar(self): if self.currentNode: spath = self.currentNode.absolute().split('/')[1:] actions = [] for count, path in enumerate(spath): if path: a = QAction(self) a.setText(QString.fromUtf8(path)) abspath = "/" + "/".join(spath[:count + 1]) a.setData(abspath) if count == 0: self.setIcon(a, path) actions.append(a) self.pathbar.clear() if len(actions) > 0: for act in actions: self.pathbar.addAction(act) font = QFont() font.setItalic(True) font.setBold(True) act.setFont(font) def setIcon(self, action, path): if path == "Logical files": action.setIcon(QIcon(":folder.png")) elif path == "Local devices": action.setIcon(QIcon(":dev_hd.png")) elif path == "Bookmarks": action.setIcon(QIcon(":bookmark.png")) dff-1.3.0+dfsg.1/dff/api/gui/widget/nodewidget.py000066400000000000000000000166641217176075400214410ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.api.vfs.libvfs import VFS from dff.api.gui.view.node_list import NodeListView from dff.api.gui.view.node_table import NodeTableView from dff.api.gui.model.node_list import NodeListModel from dff.ui.gui.utils.menumanager import MenuManager from dff.ui.gui.resources.ui_filter_mode import Ui_filterMode TABLEVIEW_ID = 0 LISTVIEW_ID = 1 class NodeWidget(QWidget): """ This Widget provide a list model with various view """ def __init__(self, selectionManager, tabmode=False, filtermode=False): QWidget.__init__(self) self.tabmode = tabmode self.filtermode = filtermode # setup model and views self.viewid = TABLEVIEW_ID self.model = NodeListModel(selection=selectionManager) self.tableview = NodeTableView(self) self.listview = NodeListView(self) self.tableview.setModel(self.model) self.tableview.setColumnWidth(0, 180) self.listview.setModel(self.model) # Keep track of model list in case of filtering self.initialist = [] # setup graphic stuff self.createMainLayout() self.createViewLayout() self.createStack() self.createScrollbar() self.createConnections() self.menuManager(selectionManager) self.connect(self.model, SIGNAL("dataChanged"), self.dataChanged) def menuManager(self, selectionManager): self.menumanager = MenuManager(selectionManager, self.model) def refreshIconSize(self, factor): self.tableview.factor = factor self.tableview.configure() self.listview.factor = factor self.listview.configure() self.refreshVisible() def dataChanged(self, x, y): self.viewstack.currentWidget().dataChanged(x, y) def createMainLayout(self): self.vlayout = QVBoxLayout(self) self.vlayout.setSpacing(0) self.vlayout.setMargin(0) def createViewLayout(self): container = QWidget() self.hlayout = QHBoxLayout() self.hlayout.setSpacing(0) self.hlayout.setMargin(0) container.setLayout(self.hlayout) self.vlayout.addWidget(container) def createStack(self): self.viewstack = QStackedWidget() self.viewstack.addWidget(self.tableview) self.viewstack.addWidget(self.listview) self.hlayout.addWidget(self.viewstack, 99) def createScrollbar(self): self.scrollbar = ScrollBar(self) self.hlayout.addWidget(self.scrollbar, 1) self.scrollbar.lower() def refreshVisible(self): view = self.viewstack.currentWidget() view.refreshVisible() def createConnections(self): self.connect(self, SIGNAL("changeView"), self.changeView) self.connect(self.tableview, SIGNAL("nodeListClicked"), self.nodelistclicked) self.connect(self.tableview, SIGNAL("nodeListDoubleClicked"), self.nodelistDoubleclicked) self.connect(self.model, SIGNAL("nodeListClicked"), self.nodelistclicked) self.connect(self.tableview, SIGNAL("enterDirectory"), self.enterDirectory) self.connect(self.listview, SIGNAL("enterDirectory"), self.enterDirectory) self.connect(self.listview, SIGNAL("nodeListClicked"), self.nodelistclicked) self.connect(self.listview, SIGNAL("nodeListDoubleClicked"), self.nodelistDoubleclicked) self.connect(self.model, SIGNAL("nodeAppended"), self.refreshVisible) def enterDirectory(self, sourcenode): if sourcenode != None: if (not self.tabmode) and (not self.filtermode): self.model.emit(SIGNAL("changeList"), sourcenode.children()) self.emit(SIGNAL("pathChanged"), sourcenode) if len(self.model.list()) > 0: self.nodelistclicked(0) if self.filtermode: self.emit(SIGNAL("enterFilter"), sourcenode) if self.tabmode: self.openAsNewTab(sourcenode) self.refreshVisible() def nodelistclicked(self, button): if button == Qt.RightButton: self.menumanager.createMenu() else: node = self.model.currentNode() self.emit(SIGNAL("nodePressed"), node) def nodelistDoubleclicked(self, node): self.menumanager.openDefault(node) def changeView(self, index): self.viewid = index if index == TABLEVIEW_ID: self.viewstack.setCurrentWidget(self.tableview) self.model.refresh(self.model.currentRow()) self.scrollbar.setMaximum(self.scrollbar.value() - 2) elif index == LISTVIEW_ID: self.viewstack.setCurrentWidget(self.listview) self.model.refresh(self.model.currentRow()) self.scrollbar.setMaximum(self.scrollbar.value() + 2) self.refreshVisible() def openAsNewTab(self, rootnode): QApplication.instance().mainWindow.addNodeBrowser(rootpath=rootnode) class ScrollBar(QScrollBar): def __init__(self, nodeview): QScrollBar.__init__(self, nodeview) self.model = nodeview.model self.nodeview = nodeview self.setMinimum(0) self.setMaximum(0) self.setVisible(False) self.connect(self, SIGNAL("sliderMoved(int)"), self.moveTo) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) # Model signals self.connect(self.model, SIGNAL("maximum"), self.updateMaximum) self.connect(self.model, SIGNAL("hideScroll"), self.hideScrollbar) self.connect(self.model, SIGNAL("current"), self.updateCurrent) self.nodeview.hlayout.addWidget(self, 1) def hideScrollbar(self): self.setMinimum(0) self.setMaximum(0) self.setVisible(False) def updateMaximum(self, stop): if stop <= self.model.visibleRows(): self.setMinimum(0) self.setMaximum(0) self.setVisible(False) else: m = stop - self.model.visibleRows() self.setMaximum(m) self.setSingleStep(1) self.setVisible(True) def updateCurrent(self, current): if current >= 0: self.setValue(current) def triggered(self, action): if self.nodeview.viewid == TABLEVIEW_ID: f = 1 else: f = self.nodeview.listview.cols if action == QAbstractSlider.SliderSingleStepAdd: self.model.seek(self.value() + f) elif action == QAbstractSlider.SliderPageStepAdd: self.model.seek(self.value() + self.model.visibleRows() - f) elif action == QAbstractSlider.SliderSingleStepSub: self.model.seek(self.value() - f) elif action == QAbstractSlider.SliderPageStepSub: self.model.seek(self.value() - self.model.visibleRows() - f) else: return def moveTo(self, value): self.model.seek(value) dff-1.3.0+dfsg.1/dff/api/gui/widget/propertytable.py000066400000000000000000000131041217176075400221660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from PyQt4.QtCore import Qt, QString, QEvent, QVariant, SIGNAL from PyQt4.QtGui import QTreeWidget, QTreeWidgetItem, QBrush, QColor, QLabel from dff.api.vfs.libvfs import VLink from dff.api.gui.widget.varianttreewidget import VariantTreeWidget class PropertyTable(VariantTreeWidget): def __init__(self, parent): VariantTreeWidget.__init__(self, parent) self.node = None self.translation() def fillBase(self, node): fsobj = node.fsobj() fsobjname = "" if fsobj != None: fsobjname = fsobj.name itemName = QTreeWidgetItem(self) itemName.setText(0, self.nameText) itemName.setText(1, QString.fromUtf8(node.name())) if isinstance(node, VLink): linkPath = QTreeWidgetItem(self) linkPath.setText(0, self.linkPath) label = QLabel(''+QString.fromUtf8(node.linkAbsolute())+' ') label.connect(label, SIGNAL("linkActivated(QString)"), self.gotolink) self.setItemWidget(linkPath, 1, label) itemName = QTreeWidgetItem(self) itemName.setText(0, self.nodeTypeText) typestr = "" if node.isFile(): typestr += self.fileText if node.hasChildren(): typestr += self.modAppliedText self.fillCompatModule(node) if node.hasChildren(): self.fillChildren(node) if node.isDir(): typestr += self.folderText if not node.hasChildren(): typestr += self.emptyText if node.isDeleted(): typestr += self.deletedText itemName.setText(1, typestr) itemModule = QTreeWidgetItem(self) itemModule.setText(0, self.generateText) itemModule.setText(1, str(fsobjname)) itemSize = QTreeWidgetItem(self) itemSize.setText(0, self.sizeText) itemSize.setText(1, str(node.size())) tags = node.tags() if len(tags): itemTags = QTreeWidgetItem(self) itemTags.setText(0, "tags") tags = node.tags() for tag in tags: itemTag = QTreeWidgetItem(itemTags) color = tag.color() itemTag.setBackground(0, QBrush(QColor(color.r, color.g, color.b))) itemTag.setForeground(0, QBrush(QColor(255,255,255))) itemTag.setText(0, QString.fromUtf8(tag.name())) self.expandItem(itemTags) def fillCompatModule(self, node): l = node.compatibleModules() if len(l) > 0: itemCompat = QTreeWidgetItem(self) itemCompat.setText(0, self.relevantText) buff = "" for i in l: buff += str(i) + " " itemCompat.setText(1, buff) def fillChildren(self, node): itemChildren = QTreeWidgetItem(self) itemChildren.setText(0, self.childrenText) itemChildren.setText(1, str(node.childCount())) children = node.children() filessize = 0 filecount = 0 dircount = 0 for child in children: if child.size(): filessize += child.size() filecount += 1 elif child.isDir() or child.hasChildren(): dircount += 1 if filecount > 0: itemFile = QTreeWidgetItem(itemChildren) itemFile.setText(0, self.filesText) itemFile.setText(1, str(filecount) + self.totText + str(filessize) + self.bytesText) if dircount > 0: itemFolder = QTreeWidgetItem(itemChildren) itemFolder.setText(0, self.foldersText) itemFolder.setText(1, str(dircount)) self.expandItem(itemChildren) def fillAttributes(self, node): try: vmap = node.attributes() if vmap: if len(vmap) > 0: itemExtendedAttr = QTreeWidgetItem(self) itemExtendedAttr.setText(0, self.attributeText) self.fillMap(itemExtendedAttr, vmap) self.expandItem(itemExtendedAttr) except: pass def fill(self, node = None): if not node: node = self.node self.node = node self.clear() if self.isVisible(): self.fillBase(node) self.fillAttributes(node) self.resizeColumnToContents(0) self.resizeColumnToContents(1) def translation(self): self.nameText = self.tr('name') self.linkPath = self.tr('link path') self.nodeTypeText = self.tr('node type') self.fileText = self.tr('file') self.modAppliedText = self.tr(' with module(s) applied on it') self.folderText = self.tr('folder') self.emptyText = self.tr(' empty') self.deletedText = self.tr(' deleted') self.generateText = self.tr('generated by') self.sizeText = self.tr('size') self.relevantText = self.tr('relevant module(s)') self.childrenText = self.tr('children') self.filesText = self.tr('file(s)') self.totText = self.tr(' totalizing ') self.bytesText = self.tr(' bytes') self.foldersText = self.tr('folder(s)') self.attributeText = self.tr('attributes') def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() if self.node is not None: self.fill() else: QTreeWidget.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/api/gui/widget/search/000077500000000000000000000000001217176075400201665ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/gui/widget/search/CMakeLists.txt000066400000000000000000000012771217176075400227350ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER #### Deploying python __init__ script install_file( __init__.py search_widget.py filter.py thread.py dico_manager.py predefilters.py ) dff-1.3.0+dfsg.1/dff/api/gui/widget/search/__init__.py000066400000000000000000000011201217176075400222710ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER __all__ = ["search_widget", "filter"] dff-1.3.0+dfsg.1/dff/api/gui/widget/search/dico_manager.py000066400000000000000000000122161217176075400231520ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os from PyQt4 import QtCore, QtGui from PyQt4.QtGui import QWidget, QTableWidgetItem, QFileDialog, QDialog, QVBoxLayout, QDialogButtonBox from PyQt4.QtCore import QVariant, SIGNAL,Qt, SLOT, QEvent, QString, QSize from dff.api.filters.libfilters import QueryFlags, AttributeFactory, Filter, DictRegistry, FileDictionnary from dff.ui.gui.resources.ui_dico_manager import Ui_dicoManager class DicoManager(QWidget, Ui_dicoManager): def __init__(self): QWidget.__init__(self) self.setupUi(self) self.manager = DictRegistry.instance() self.initConnexions() self.dicos.horizontalHeaderItem(1).setSizeHint(QSize(200, 25)); def initConnexions(self): self.connect(self.addDico, SIGNAL("clicked()"), self.addDictionnary) self.connect(self.rmDico, SIGNAL("clicked()"), self.removeDictionnary) def addDictionnary(self): fn = QFileDialog.getOpenFileName(self, self.tr("Select your dictionnary"), os.path.expanduser('~')) if fn != "": ufn = str(unicode(fn).encode('utf-8')) dicname = self.autoDicName(ufn) if dicname != None: currow = self.dicos.rowCount() self.dicos.setRowCount(currow + 1) item = QTableWidgetItem(QString.fromUtf8(ufn)) item.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) item.setCheckState(Qt.Unchecked) self.dicos.setItem(currow, 0, item) name = QTableWidgetItem(QString.fromUtf8(dicname)) name.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) self.dicos.setItem(currow, 1, name) dict_ = FileDictionnary(ufn) dict_.thisown = False try: self.manager.add(dicname, dict_) except RuntimeError: print "Error adding new dictionnary" def autoDicName(self, path): try: filename = os.path.split(path)[1] sdic = filename.split('.')[0] return sdic except: print "error getting auto dictionnary name" return None def populateList(self): dicts = self.manager.dictionnaries() currow = 0 for _dict in dicts.iterkeys(): self.dicos.setRowCount(currow + 1) item = QTableWidgetItem(QString.fromUtf8(dicts[_dict].fileName())) item.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) item.setCheckState(Qt.Unchecked) self.dicos.setItem(currow, 0, item) name = QTableWidgetItem(QString.fromUtf8(_dict)) name.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) self.dicos.setItem(currow, 1, name) currow += 1 def removeDictionnary(self): row = self.dicos.currentRow() if row >= 0: try: name = self.dicos.item(row, 1) self.manager.remove(str(unicode(name.text()).encode('utf-8'))) self.dicos.removeRow(row) except RuntimeError as e: print str(e) print "Error removing dictionnary" except TypeError as e: print str(e) def selectedDictionnaries(self): # Return checked dictionnaries dicnames = [] for row in xrange(0, self.dicos.rowCount()): item = self.dicos.item(row, 0) if item.checkState() == Qt.Checked: itemname = self.dicos.item(row, 1) dicname = str(unicode(itemname.text()).encode('utf-8')) dicnames.append(dicname) return dicnames def selectedDicoNames(self): dicnames = self.selectedDictionnaries() dics = [] if len(dicnames) > 0: for d in dicnames: ret = ":" + d dics.append(ret) return dics else: return None class DicoDialog(QDialog): def __init__(self, parent): super(QDialog, self).__init__() self.parent = parent self.vbox = QVBoxLayout() self.manager = DicoManager() self.manager.populateList() self.vbox.addWidget(self.manager) buttons = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) self.vbox.addWidget(buttons) self.setLayout(self.vbox) self.connect(buttons, SIGNAL("accepted()"), self.accept) self.connect(buttons, SIGNAL("rejected()"), self.reject) self.selectedDicos = None def reject(self): QDialog.reject(self) def accept(self): QDialog.accept(self) dff-1.3.0+dfsg.1/dff/api/gui/widget/search/filter.py000066400000000000000000000041101217176075400220210ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER from PyQt4 import QtCore, QtGui from PyQt4.QtGui import QLineEdit, QHBoxLayout, QWidget from PyQt4.QtCore import QString, SIGNAL, Qt, QSize from dff.api.gui.widget.search.search_widget import CustomFiltersTable from dff.ui.gui.resources.ui_filter_bar import Ui_filterBar class FilterBar(Ui_filterBar, QWidget): def __init__(self, parent = None): super(QWidget, self).__init__(parent) self.setupUi(self) self.activated = False self.parent = parent self.custom = CustomFiltersTable(self) self.custom.setWindowFlags(Qt.Popup) self.connect(self.showFilters, SIGNAL("clicked(bool)"), self.editFilters) self.connect(self.execFilter, SIGNAL("clicked(bool)"), self.runFilter) def buildQuery(self): query = "" if self.filterEdit.text() != "": query += "(name == w(\"" + str(unicode(self.filterEdit.text()).encode('utf-8')) + "\"))" else: return None return query def runFilter(self): query = self.buildQuery() if query != None: self.parent.currentView().launchFilter(query) def editFilters(self): self.custom.setFixedWidth(self.filterEdit.width()) self.custom.move(self.filterEdit.mapToGlobal(self.filterEdit.rect().bottomLeft())) self.custom.show() def autoEnabled(self): return self.autoApply.isChecked() def initStyleSheets(self): self.founded = "QLineEdit {background: #eeeeee;}" self.notfounded = "QLineEdit {background: #000000;}" dff-1.3.0+dfsg.1/dff/api/gui/widget/search/predefilters.py000066400000000000000000000011431217176075400232270ustar00rootroot00000000000000# -*- coding: utf-8 -*- DEFAULT_FILTERS = { "Images" : "(mime in [\"image\"])", "Videos" : "(mime in [\"video\"])", "Audios" : "(mime in [\"audio\"])", "Documents" : "(mime in [\"text\",\"application/pdf\",\"application/vnd.oasis.opendocument.text\",\"application/vnd.oasis.opendocument.graphics\",\"application/vnd.oasis.opendocument.presentation\",\"application/vnd.oasis.opendocument.spreadsheet\",\"application/vnd.oasis.opendocument.chart\",\"application/vnd.oasis.opendocument.formula\",\"application/vnd.oasis.opendocument.database\",\"application/vnd.oasis.opendocument.image\"])" } dff-1.3.0+dfsg.1/dff/api/gui/widget/search/search_widget.py000066400000000000000000000635121217176075400233570ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # import os import sys from os.path import exists, expanduser, normpath from PyQt4 import QtCore, QtGui from PyQt4.QtCore import QVariant, SIGNAL, QThread, Qt, QFile, QIODevice, QStringList, QRect, SLOT, QEvent, QString, QSignalMapper, pyqtSignal, pyqtSlot, SLOT from PyQt4.QtGui import QWidget, QDateTimeEdit, QLineEdit, QHBoxLayout, QLabel, QPushButton, QMessageBox, QListWidget, QTableWidget, QTableWidgetItem, QAbstractItemView, QIcon, QInputDialog, QTableView, QMessageBox, QVBoxLayout, QComboBox, QCheckBox, QHeaderView, QDialog, QTreeWidget, QIntValidator, QDialogButtonBox, QApplication, QCursor, QFileDialog from dff.api.vfs import vfs from dff.api.vfs.libvfs import VFS, Node, VLink from dff.api.types.libtypes import Variant, typeId from dff.api.filters.libfilters import Filter from dff.api.gui.model.node_list import NodeListModel from dff.api.gui.view.node_list import NodeListView from dff.api.gui.widget.search.thread import SearchThread from dff.api.gui.widget.search.dico_manager import DicoManager, DicoDialog from dff.api.gui.widget.search.predefilters import DEFAULT_FILTERS from dff.ui.gui.widget.SelectMimeTypes import MimeTypesTree from dff.ui.gui.resources.ui_filter_add import Ui_filterAdd from dff.ui.gui.resources.ui_filter_mime import Ui_filterMime from dff.ui.gui.resources.ui_filter_dico import Ui_filterDico from dff.ui.gui.resources.ui_filter_only import Ui_filterOnly from dff.ui.gui.resources.ui_search_panel import Ui_searchPanel from dff.ui.gui.resources.ui_filter_fields import Ui_filterFields from dff.ui.gui.resources.ui_filter_matchmode import Ui_filterMatchMode from dff.ui.gui.resources.ui_filter_attributes import Ui_filterAttributes from dff.ui.gui.resources.ui_filter_mimedialog import Ui_filterMimeDialog from dff.ui.gui.resources.ui_search_customtable import Ui_searchCustomTable from dff.ui.gui.resources.ui_filter_conjunction import Ui_filterConjunction # DEFINES COLUMNS FIELDS = ["name", "data", "size", "time", "mime", "dico", "deleted","file", "attributes"] SPECIAL_FIELDSID = range(5, 9) CONJONCTIONS = ["and", "and not", "or", "or not"] #ONLY = ["deleted", "file"] MATCHMODE = ["w(", "re(", "fz(", "f("] OPERATORS = ["<", "<=", "==", "!=", ">=", ">"] SIZE_T = [1024, 1024*1024, 1024*1024*1024] DICO_TYPE = ["name", "data"] DICO_MATCH = [" any of ", " all of ", " none of "] DOCUMENT_Q = "\"text\",\"application/pdf\",\"application/vnd.oasis.opendocument.text\",\"application/vnd.oasis.opendocument.graphics\",\"application/vnd.oasis.opendocument.presentation\",\"application/vnd.oasis.opendocument.spreadsheet\",\"application/vnd.oasis.opendocument.chart\",\"application/vnd.oasis.opendocument.formula\",\"application/vnd.oasis.opendocument.database\",\"application/vnd.oasis.opendocument.image\"" IMAGE_Q = "\"image\"" VIDEO_Q = "\"video\"" APPLICATION_Q = "\"application\"" AUDIO_Q = "\"audio\"" class SearchPanel(Ui_searchPanel, QWidget): def __init__(self, parent, searchview): super(QWidget, self).__init__(parent) self.setupUi(self) self.filters = CustomFiltersTable(self) self.searchFiltersLayout.addWidget(self.filters) self.browser = parent self.vfs = vfs.vfs() self.model = searchview.model self.searchview = searchview self.matched = 0 self.searchTH = SearchThread(self) self.qmode = {0: "$", 1: "/", 2: "~", 3: "\""} self.configure() def configure(self): # Quick search self.connect(self.quickSearch, SIGNAL("clicked(bool)"), self.quickSearchMode) # Thread self.connect(self.startButton, SIGNAL("clicked(bool)"), self.startSearch) self.connect(self.stopButton, SIGNAL("clicked(bool)"), self.searchTH.stopSearch) self.connect(self.searchTH, SIGNAL("count"), self.updateProgressbar) self.connect(self.searchTH, SIGNAL("match"), self.updateMatchedNodes) self.connect(self.searchTH, SIGNAL("finished"), self.searchStoped) self.connect(self.searchTH, SIGNAL("started"), self.searchStarted) self.connect(self.searchTH, SIGNAL("stoped"), self.searchStoped) # Advanced search self.connect(self.advancedSearch, SIGNAL("clicked(bool)"), self.advancedSearchMode) # Typebuttons self.connect(self.imageType, SIGNAL("clicked()"), self.buttonClicked) self.connect(self.videoType, SIGNAL("clicked()"), self.buttonClicked) self.connect(self.soundType, SIGNAL("clicked()"), self.buttonClicked) self.connect(self.documentType, SIGNAL("clicked()"), self.buttonClicked) def buttonClicked(self): if not self.buttonsChecked(): self.quickEdit.setEnabled(True) self.quickMode.setEnabled(True) else: self.quickEdit.setEnabled(False) self.quickMode.setEnabled(False) # self.refreshQueryEdit() def buttonsChecked(self): self.quickEdit.clear() if self.imageType.isChecked() or self.videoType.isChecked() or self.soundType.isChecked() or self.documentType.isChecked(): self.quickEdit.insert(self.generateButtonsClicked()) return True return False def generateButtonsClicked(self): r = "" count = 0 if self.imageType.isChecked(): r += DEFAULT_FILTERS["Images"] count += 1 if self.videoType.isChecked(): if count != 0: r += " or " r += DEFAULT_FILTERS["Videos"] count += 1 if self.soundType.isChecked(): if count != 0: r += " or " r += DEFAULT_FILTERS["Audios"] count += 1 if self.documentType.isChecked(): if count != 0: r += " or " r += DEFAULT_FILTERS["Documents"] count += 1 return r def startSearch(self): query = self.buildQuery() if query != None: if self.fromRoot.isChecked(): rootnode = self.vfs.getnode("/") else: rootnode = self.browser.navigation.currentNode if self.browser.filter.isChecked(): self.browser.viewpan.setCurrentWidget(self.browser.searchview) self.model.clearList() self.matchedNodeLabel.setText("0") self.matched = 0 r = self.searchTH.setContext(query, rootnode, self.model) if r: self.searchTH.start() else: box = QMessageBox(QMessageBox.Critical, self.tr("Error"), self.tr("Please, specify your query"), \ QMessageBox.NoButton, self) box.exec_() def buildQuery(self): if self.quickSearch.isChecked(): query = "" if self.quickEdit.text() != "": # Check if buttons are checked if not self.quickEdit.isEnabled(): query += str(unicode(self.quickEdit.text()).encode('utf-8')) else: if self.quickMode.currentIndex() in xrange(0,4): pat = self.qmode[self.quickMode.currentIndex()] query += "name matches" + pat + str(unicode(self.quickEdit.text()).encode('utf-8')) + pat else: query += str(unicode(self.quickEdit.text()).encode('utf-8')) else: return None return query else: return self.filters.buildAllQueries() def updateProgressbar(self, count): self.searchProgress.setValue(count) def updateMatchedNodes(self): self.matched += 1 self.matchedNodeLabel.setText(str(self.matched)) self.searchview.refreshVisible() def searchStarted(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.searchProgress.setValue(0) self.matchedNodeLabel.setText(QString("0")) self.startButton.setEnabled(False) self.stopButton.setEnabled(True) def searchStoped(self): self.startButton.setEnabled(True) self.stopButton.setEnabled(False) if self.browser.filter.isChecked(): self.browser.viewpan.setCurrentWidget(self.browser.filterview) self.browser.filterwidget.resetFilter() QApplication.restoreOverrideCursor() def quickSearchMode(self, state): if state: self.advancedSearch.setChecked(False) else: self.advancedSearch.setChecked(True) def advancedSearchMode(self, state): if state: self.quickSearch.setChecked(False) else: self.quickSearch.setChecked(True) # Search filter widget class CustomFiltersTable(Ui_searchCustomTable, QWidget): def __init__(self, parent = None): super(QWidget, self).__init__(parent) self.setupUi(self) self.table.verticalHeader().hide() self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setSelectionMode(QAbstractItemView.SingleSelection) self.table.setColumnWidth(0, 180) self.filters = [] self.enabled = [] self.connect(self.newButton, SIGNAL("clicked(bool)"), self.add) self.connect(self.deleteButton, SIGNAL("clicked(bool)"), self.remove) self.connect(self.editButton, SIGNAL("clicked(bool)"), self.edit) self.connect(self.table, SIGNAL("cellClicked(int, int)"), self.cellClick) self.connect(self.loadButton, SIGNAL("clicked(bool)"), self.load) self.connect(self.saveButton, SIGNAL("clicked(bool)"), self.save) self.editButton.setEnabled(False) self.deleteButton.setEnabled(False) self.saveButton.setEnabled(False) def buildAllQueries(self): query = "" enabled = 0 filters = self.get() for count, filt in enumerate(filters): if self.filterEnabled(filt): if enabled > 0: query += " and " query += filt.buildRequest() enabled += 1 if query != "": return query else: return None def cellClick(self, row, col): try: filt = self.filters[row] self.deleteButton.setEnabled(True) if filt.isEditable(): self.editButton.setEnabled(True) else: self.editButton.setEnabled(False) if self.filterEnabled(filt): self.saveButton.setEnabled(True) else: self.saveButton.setEnabled(False) self.refreshQueryEdit() except: pass def addFilter(self, name, query): filt = Filter(self, name, query) currow = self.table.rowCount() self.table.setRowCount(self.table.rowCount() + 1) name = QTableWidgetItem(QString(name)) name.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.table.setItem(currow, 0, name) check = QCheckBox() check.setChecked(True) self.filters.append(filt) self.emit(SIGNAL("filterAdded")) self.table.horizontalHeader().setResizeMode(1, QHeaderView.ResizeToContents) self.refreshQueryEdit() def filterState(self, state): self.refreshQueryEdit() def add(self): filt = Filter(self) ret = filt.exec_() if ret == 1: currow = self.table.rowCount() self.table.setRowCount(self.table.rowCount() + 1) name = QTableWidgetItem(QString(filt.name())) name.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.table.setItem(currow, 0, name) check = QCheckBox() check.setChecked(True) self.connect(check, SIGNAL("stateChanged(int)"), self.filterState) self.table.setCellWidget(currow, 1, check) self.filters.append(filt) self.refreshQueryEdit() self.emit(SIGNAL("filterAdded")) self.table.horizontalHeader().setResizeMode(1, QHeaderView.ResizeToContents) def refreshQueryEdit(self): self.queryEdit.clear() query = self.buildAllQueries() if not query: query = "" self.queryEdit.insert(query) def remove(self): row = self.table.currentRow() if row >= 0: self.filters.pop(row) self.table.removeRow(row) self.emit(SIGNAL("filterRemoved")) if len(self.filters) == 0: self.editButton.setEnabled(False) self.refreshQueryEdit() def edit(self): row = self.table.currentRow() filt = self.filters[row] ret = filt.exec_() if ret == 1: cell = self.table.currentItem() cell.setText(QString(filt.name())) self.refreshQueryEdit() def get(self): return self.filters def closeEvent(self, event): pass def filterEnabled(self, filt): for count, f in enumerate(self.filters): if f == filt: state = self.table.cellWidget(count, 1).checkState() if state == Qt.Unchecked: return False else: return True def selectedFilters(self): f = [] for count, filt in enumerate(self.filters): state = self.table.cellWidget(count, 1).checkState() if state == Qt.Checked: f.append(filt) return f def save(self): fdial = QFileDialog() sFileName = fdial.getSaveFileName(self, "Save as", os.path.expanduser('~')) if sFileName != "": sFileName += ".py" ufn = str(unicode(sFileName).encode('utf-8')) f = open(ufn, "w") filts = self.selectedFilters() buff = "# -*- coding: utf-8 -*-\n" buff += "FILTERS = {\n" for filt in filts: buff += "\t" + "\"" + filt.name() + "\"" + " : " + "'" + filt.buildRequest() + "'" + ",\n" buff += "}\n" f.write(buff) f.close def load(self): fdial = QFileDialog() sFileName = fdial.getOpenFileName(self, "Save as", os.path.expanduser('~'), "Python (*.py)") if sFileName != "": try: ufn = str(unicode(sFileName).encode('utf-8')) location = os.path.dirname(ufn) basename = os.path.basename(ufn) modname = os.path.splitext(basename) sys.path.append(location) f = __import__(modname[0]) for name, query in f.FILTERS.iteritems(): self.addFilter(name, query) except: pass class Filter(Ui_filterAdd, QDialog): def __init__(self, filtertable, fname=None, query=None): super(QDialog, self).__init__(filtertable) self.filtertable = filtertable self.setupUi(self) self.editable = False self.defaultquery = None self.fname = None if (fname == None) and (query == None): self.editable = True self.filterRequest = FilterRequests(self) self.requestLayout.addWidget(self.filterRequest) else: self.defaultquery = query self.fname = fname def reject(self): QDialog.reject(self) def accept(self): if not self.name().isEmpty(): QDialog.accept(self) else: box = QMessageBox(QMessageBox.Critical, self.tr("Error"), self.tr("Please, specify a query name"), \ QMessageBox.NoButton, self) box.exec_() def isEditable(self): return self.editable def name(self): if self.editable: return self.filterName.text() else: return self.fname def buildRequest(self): if self.editable: row = 0 res = "(" while row < self.filterRequest.rowCount(): if row > 0: conj = self.filterRequest.cellWidget(row, 0) res += " " + CONJONCTIONS[conj.conjunctionCombo.currentIndex()] + " " widget = self.filterRequest.cellWidget(row, 2) res += widget.request() row += 1 res += ")" return res else: return self.defaultquery class FilterRequests(QTableWidget): def __init__(self, parent = None): super(QTableWidget, self).__init__(parent) self.parent = parent self.configure() # Keep a list of FieldCombo object self.fieldMapper = [] self.removeMapper = [] self.addRequest() def configure(self): self.setColumnCount(5) self.setRowCount(0) self.verticalHeader().setDefaultSectionSize(30) self.horizontalHeader().setDefaultSectionSize(30) self.horizontalHeader().setResizeMode(1, QHeaderView.ResizeToContents) self.horizontalHeader().setResizeMode(2, QHeaderView.Stretch) self.horizontalHeader().setResizeMode(3, QHeaderView.ResizeToContents) self.horizontalHeader().setResizeMode(4, QHeaderView.ResizeToContents) self.setSelectionMode(QAbstractItemView.NoSelection) self.horizontalHeader().setStretchLastSection(False) self.setShowGrid(False) self.horizontalHeader().hide() self.verticalHeader().hide() def addRequest(self, widget=None): currow = self.rowCount() self.setRowCount(self.rowCount() + 1) # Add conjonctions if not First widget if len(self.fieldMapper) != 0: conjonction = ConjonctionCombo(self) self.setCellWidget(currow, 0, conjonction) self.horizontalHeader().setResizeMode(0, QHeaderView.ResizeToContents) else: empty = QTableWidgetItem(QString("")) empty.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.setItem(currow, 0, empty) # Add Field choice fields = FieldCombo(self) self.connect(fields, SIGNAL("fieldChanged"), self.changeFilterType) self.setCellWidget(currow, 1, fields) self.fieldMapper.append(fields.fieldCombo) # Add Widget if widget == None: widget = NameRequest(self) self.setCellWidget(currow, 2, widget) # Add request button add = self.createAddRequestButton() self.setCellWidget(currow, 3, add) # Remove request button rm = removeRequestButton() self.removeMapper.append(rm) self.connect(rm, SIGNAL("removeRequest"), self.removeRequest) self.setCellWidget(currow, 4, rm) def changeFilterType(self, fieldwidget, index): # ["name", "data", "size", "time", "mime", "file", "deleted", "attributes"] if fieldwidget in self.fieldMapper: row = self.fieldMapper.index(fieldwidget) ftype = fieldwidget.currentIndex() if ftype == FIELDS.index("name"): widget = NameRequest(self) elif ftype == FIELDS.index("data"): widget = NameRequest(self, data=True) elif ftype == FIELDS.index("size"): widget = SizeRequest(self) elif ftype == FIELDS.index("time"): widget = DateRequest(self) elif ftype == FIELDS.index("mime"): widget = MimeRequest(self) elif ftype == FIELDS.index("dico"): widget = DicoRequest(self) elif ftype == FIELDS.index("deleted"): widget = OnlyRequest(self, field="deleted") elif ftype == FIELDS.index("file"): widget = OnlyRequest(self, field="file") elif ftype == FIELDS.index("attributes"): widget = AttributeRequest(self) else: return self.setCellWidget(row, 2, widget) def removeRequest(self, rmbutton): if (rmbutton in self.removeMapper): if self.removeMapper.index(rmbutton) > 0: row = self.removeMapper.index(rmbutton) self.removeRow(row) self.fieldMapper.pop(row) self.removeMapper.pop(row) def createAddRequestButton(self): addRequestButton = QPushButton() addRequestButton.setIcon(QIcon(":add.png")) self.connect(addRequestButton, SIGNAL("clicked()"), self.addRequest) return addRequestButton class removeRequestButton(QPushButton): def __init__(self): QPushButton.__init__(self) self.setIcon(QIcon(":remove.png")) self.connect(self, SIGNAL("clicked(bool)"), self.removeMapper) def removeMapper(self): self.emit(SIGNAL("removeRequest"), self) class Request(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.hlayout = QHBoxLayout(self) self.hlayout.setMargin(2) self.setLayout(self.hlayout) class ConjonctionCombo(Ui_filterConjunction, Request): def __init__(self, parent): Request.__init__(self, parent) self.setupUi(self) self.hlayout.addWidget(self.conjunctionCombo) class NameRequest(Ui_filterMatchMode, Request): def __init__(self, parent, data=False): Request.__init__(self, parent) self.data = data self.setupUi(self) self.setContent() self.setMatchMode() self.setCase() def setContent(self): self.content = QLineEdit(self) self.hlayout.addWidget(self.content) def setMatchMode(self): self.hlayout.addWidget(self.matchModeCombo) def setCase(self): self.casse.setChecked(True) self.hlayout.addWidget(self.casse) def request(self): result = "(" if not self.data: result += "name matches " else: result += "data matches " result += MATCHMODE[self.matchModeCombo.currentIndex()] result += "\"" + str(unicode(self.content.text()).encode('utf-8')) + self.case() + ")" return result def case(self): if not self.casse.isChecked(): return "\",i)" else: return "\")" class SizeRequest(Request): def __init__(self, parent): Request.__init__(self, parent) self.setOperators() self.setContent() self.setSizeType() def setOperators(self): self.operatorCombo = OperatorCombo(self) self.hlayout.addWidget(self.operatorCombo) def setContent(self): self.content = QLineEdit(self) self.validator = QIntValidator(0,2147483647, self) self.content.setValidator(self.validator) self.hlayout.addWidget(self.content) def setSizeType(self): self.stype = QComboBox(self) self.stype.addItem(QString("KB")) self.stype.addItem(QString("MB")) self.stype.addItem(QString("GB")) self.hlayout.addWidget(self.stype) def request(self): operator = str(self.operatorCombo.currentText()) factor = SIZE_T[self.stype.currentIndex()] size = self.content.text().toULongLong()[0] size = size * factor res = "(size " + operator + " " + str(size) + ")" return res class DateRequest(Request): def __init__(self, parent): Request.__init__(self, parent) self.setOperators() self.setDateTime() def setOperators(self): self.operatorCombo = OperatorCombo(self) self.hlayout.addWidget(self.operatorCombo) def setDateTime(self): self.datetime = QDateTimeEdit(self) self.datetime.setCalendarPopup(True) self.hlayout.addWidget(self.datetime, 50) def request(self): res = "(time " + str(self.operatorCombo.currentText()) date_time = self.datetime.dateTime() res += str(date_time.toString("yyyy-MM-ddThh:mm:ss")) + ")" return res class MimeRequest(Ui_filterMime, Request): def __init__(self, parent): Request.__init__(self, parent) self.setupUi(self) self.setContent() self.setSelectButton() def setContent(self): self.content.setReadOnly(True) self.hlayout.addWidget(self.content, 50) def setSelectButton(self): self.hlayout.addWidget(self.selectButton) self.connect(self.selectButton, SIGNAL("clicked()"), self.selectMimeDialog) def selectMimeDialog(self): dialog = MimeDialog(self) ret = dialog.exec_() if ret == 1: result = dialog.selectedTypes() self.content.clear() self.content.setText(result) def request(self): res = "(mime in[" + str(unicode(self.content.text()).encode('utf-8')) + "])" return res class MimeDialog(Ui_filterMimeDialog, QDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.setupUi(self) self.mime = MimeTypesTree(self.treeWidget) def selectedTypes(self): mimes = self.mime.selectedItems() result = "" for count, mime in enumerate(mimes): result += "\"" + mime + "\"" if count < len(mimes) - 1: result += "," return result class DicoRequest(Ui_filterDico, Request): def __init__(self, parent): Request.__init__(self, parent) self.setupUi(self) self.setContent() self.dicos = [] def setContent(self): self.hlayout.addWidget(self.dicoPath, 50) self.hlayout.addWidget(self.dicoManager, 5) self.hlayout.addWidget(self.dicoType, 10) self.hlayout.addWidget(self.dicoMatch, 10) self.connect(self.dicoManager, SIGNAL("clicked()"), self.selectDico) def selectDico(self): dialog = DicoDialog(self) r = dialog.exec_() if r > 0: self.dicos = dialog.manager.selectedDicoNames() if self.dicos != None: label = str() for dico in self.dicos: label += dico self.dicoPath.clear() self.dicoPath.insert(QString.fromUtf8(label)) def request(self): res = str("(") if len(self.dicos) > 0: res += DICO_TYPE[self.dicoType.currentIndex()] + " matches" res += DICO_MATCH[self.dicoMatch.currentIndex()] + "[" for count, dico in enumerate(self.dicos): res += dico + ":" if count < len(self.dicos) - 1: res += "," res += "])" return res class OnlyRequest(Ui_filterOnly, Request): def __init__(self, parent, field): Request.__init__(self, parent) self.setupUi(self) self.field = field self.setOnly() def setOnly(self): self.hlayout.addWidget(self.onlyCombo) def request(self): index = self.onlyCombo.currentIndex() # Deleted if self.field == "deleted": res = "(deleted == " elif self.field == "file": res = "(file == " # Files if index == 0: res += "true)" else: res += "false)" return res class AttributeRequest(Ui_filterAttributes, Request): def __init__(self, parent, iss=True): Request.__init__(self, parent) self.setupUi(self) self.setOperators() self.setShape() def setOperators(self): self.operatorCombo = OperatorCombo(self, attrmode=True) self.hlayout.addWidget(self.operatorCombo) def setShape(self): self.hlayout.addWidget(self.key) self.hlayout.addWidget(self.operatorCombo) self.hlayout.addWidget(self.value) def request(self): res = "(@" + str(unicode(self.key.text()).encode('utf-8')) + "@ " res += str(self.operatorCombo.currentText()) + " \"" res += str(unicode(self.value.text()).encode('utf-8')) + "\")" return res class FieldCombo(Ui_filterFields, Request): def __init__(self, parent): Request.__init__(self, parent) self.setupUi(self) self.hlayout.addWidget(self.fieldCombo) self.connect(self.fieldCombo, SIGNAL("currentIndexChanged(int)"), self.indexChangedMapper) def indexChangedMapper(self, index): self.emit(SIGNAL("fieldChanged"), self.fieldCombo, index) class OperatorCombo(QComboBox): def __init__(self, parent, attrmode=False): QComboBox.__init__(self, parent) if attrmode: self.addItem(QString("matches")) for op in OPERATORS: self.addItem(QString(op)) dff-1.3.0+dfsg.1/dff/api/gui/widget/search/thread.py000066400000000000000000000070311217176075400220100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon # from PyQt4 import QtCore, QtGui from PyQt4.QtGui import QWidget, QDateTimeEdit, QLineEdit, QHBoxLayout, QLabel, QPushButton, QMessageBox, QListWidget, QTableWidget, QTableWidgetItem, QAbstractItemView, QIcon, QInputDialog, QTableView from PyQt4.QtCore import QVariant, SIGNAL, QThread, Qt, QFile, QIODevice, QStringList, QRect, SLOT, QEvent, QString from dff.api.vfs.vfs import vfs from dff.api.vfs.libvfs import VFS, Node, VLink, VecNode from dff.api.filters.libfilters import Filter from dff.api.types.libtypes import Variant, typeId from dff.api.events.libevents import EventHandler, event class SearchThread(QThread, EventHandler): def __init__(self, parent=None): EventHandler.__init__(self) QThread.__init__(self) self.__parent = parent self.nodes = [] self.filters = Filter("search") self.filters.connection(self) self.model = None self.listmode = False def setListContext(self, query, nodelist, targetmodel): self.listmode = True self.nodes = VecNode() for node in nodelist: self.nodes.append(node) self.model = targetmodel try: self.filters.compile(query) return True except: box = QMessageBox(QMessageBox.Critical, self.tr("Error"), self.tr("Error compiling query"), \ QMessageBox.NoButton, self.__parent) box.setDetailedText(QString.fromUtf8(query)) box.exec_() return False def setContext(self, query, rootnode, targetmodel): self.listmode = False self.rootnode = rootnode self.model = targetmodel try: self.filters.compile(query) return True except Exception as e: print e box = QMessageBox(QMessageBox.Critical, self.tr("Error"), self.tr("Error compiling query"), \ QMessageBox.NoButton, self.__parent) box.setDetailedText(QString.fromUtf8(query)) box.exec_() return False def Event(self, e): if e != None: if e.value != None: if e.type == Filter.EndOfProcessing: self.emit(SIGNAL("finished")) if e.type == Filter.TotalNodesToProcess: self.total = e.value.value() if e.type == Filter.ProcessedNodes: self.processed += 1 if e.type == Filter.NodeMatched: self.match += 1 val = e.value.value() self.model.emit(SIGNAL("appendList"), val) self.emit(SIGNAL("match")) pc = self.processed * 100 / self.total try: if pc > self.percent: self.percent = pc self.emit(SIGNAL("count"), self.percent) except: self.percent = 0 def run(self): self.emit(SIGNAL("started")) self.match = 0 self.processed = 0 self.total = 0 self.percent = 0 try: if not self.listmode: self.filters.process(self.rootnode, True) else: self.filters.process(self.nodes) except: pass def stopSearch(self): e = event() e.thisown = False e.type = Filter.StopProcessing self.filters.Event(e) dff-1.3.0+dfsg.1/dff/api/gui/widget/textedit.py000066400000000000000000000017321217176075400211300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from PyQt4.QtGui import QTextEdit from PyQt4.QtCore import SIGNAL class TextEdit(QTextEdit): def __init__(self, proc): QTextEdit.__init__(self) self.setReadOnly(1) self.icon = 0 self.name = proc.name self.type = "autogen" self.proc = proc proc.widget = self self.connect(self, SIGNAL("puttext"), self.puttext) def puttext(self, text): if text: self.append(text) dff-1.3.0+dfsg.1/dff/api/gui/widget/varianttreewidget.py000066400000000000000000000160161217176075400230270ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # from PyQt4.QtCore import Qt, QString, QEvent, SIGNAL, QSize from PyQt4.QtGui import QTreeWidget, QTreeWidgetItem, QApplication, QLineEdit, QDialog, QDialogButtonBox, QLayout, QVBoxLayout, QHBoxLayout, QLabel, QStyle, QPixmap, QSizePolicy, QFontMetrics, QMenu, QCursor, QClipboard from dff.api.types.libtypes import typeId from dff.api.vfs.vfs import vfs from dff.ui.gui.resources.ui_varianttreewidget import Ui_VariantTreeWidget class VariantTreeWidget(QTreeWidget, Ui_VariantTreeWidget): def __init__(self, parent=None): QTreeWidget.__init__(self, parent) self.setupUi(self) self.connect(self, SIGNAL("itemDoubleClicked(QTreeWidgetItem*, int)"), self.displayItem) self.copyMenu = AttributeCopyMenu(self) self.mainwindow = QApplication.instance().mainWindow def setItemText(self, item, vval): if vval == None: item.setText(1, str("None")) elif vval.type() == typeId.VTime: vtime = vval.value() if vtime: item.setText(1, str(vtime.get_time())) elif vval.type() in [typeId.Int16, typeId.UInt16, typeId.Int32, typeId.UInt32, typeId.Int64, typeId.UInt64]: item.setText(1, vval.toString() + " - " + vval.toHexString()) elif vval.type() in [typeId.Char, typeId.String, typeId.CArray]: val = vval.toString() item.setText(1, QString.fromUtf8(val)) elif vval.type() == typeId.Node: label = QLabel(''+ QString.fromUtf8(vval.value().absolute()) + ' ') label.connect(label, SIGNAL("linkActivated(QString)"), self.gotolink) self.setItemWidget(item, 1, label) elif vval.type() == typeId.Path: item.setText(1, QString.fromUtf8(vval.value().path)) else: item.setText(1, str(vval.value())) def fillMap(self, parent, vmap): for key in vmap.iterkeys(): item = QTreeWidgetItem(parent) item.setText(0, QString.fromUtf8(key)) vval = vmap[key] expand = True if vval == None: self.setItemText(item, vval) elif vval.type() == typeId.Map: vvmap = vval.value() self.fillMap(item, vvmap) elif vval.type() == typeId.List: vlist = vval.value() size = len(vlist) if size > 30: expand = False item.setText(1, "total items (" + str(size) + ")") self.fillList(item, vlist) else: self.setItemText(item, vval) if expand: self.expandItem(item) def fillList(self, parent, vlist): for vval in vlist: if vval.type() == typeId.Map: vmap = vval.value() self.fillMap(parent, vmap) elif vval.type() == typeId.List: vvlist = vval.value() self.fillList(parent, vvlist) else: item = QTreeWidgetItem(parent) self.setItemText(item, vval) def itemAttributeValue(self, item): message = QString() it = 0 itemPath = "" currentItem = item.parent() while currentItem and currentItem.text(0) != "attributes": itemPath = currentItem.text(0) + '.' + itemPath currentItem = currentItem.parent() itemPath += item.text(0) return (itemPath, item.text(1)) def displayItem(self, item, col): attribute, value = self.itemAttributeValue(item) dialog = ItemValueDialog(self, attribute, value) dialog.exec_() def gotolink(self, path): if path: p = str(path.toUtf8()) v = vfs() n = v.getnode(str(path.toUtf8())) self.mainwindow.addNodeBrowser(rootpath=n) def copyToClipboard(self): clipboard = QApplication.clipboard() item = self.currentItem() column = self.currentColumn() attribute, value = self.itemAttributeValue(item) if column == 0: clipboard.setText(attribute, QClipboard.Clipboard) clipboard.setText(attribute, QClipboard.Selection) else: clipboard.setText(value, QClipboard.Clipboard) clipboard.setText(value, QClipboard.Selection) def mousePressEvent(self, event): index = self.indexAt(event.pos()) if index.isValid(): item = self.itemAt(event.pos()) if event.button() == Qt.RightButton: self.copyMenu.popup(QCursor.pos()) QTreeWidget.mousePressEvent(self, event) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) else: QTreeWidget.changeEvent(self, event) class AttributeCopyMenu(QMenu): def __init__(self, parent): QMenu.__init__(self, parent) action = self.addAction(self.tr("copy")) self.connect(action, SIGNAL("triggered()"), parent.copyToClipboard) class ItemLineEdit(QLineEdit): def __init__(self, text): QLineEdit.__init__(self, text) self.setFrame(False) self.setReadOnly(True) def sizeHint(self): fm = QFontMetrics(self.font()) h = fm.height() w = fm.width(self.displayText()) + (fm.width(' ') * 2) return QSize(w, h) class ItemValueDialog(QDialog): def __init__(self, parent, path, value): QDialog.__init__(self) self.setWindowTitle(self.tr("Attribute value")) vlayout = QVBoxLayout() hlayout = QHBoxLayout() label = QLabel() label.setPixmap(self.style().standardIcon(QStyle.SP_MessageBoxInformation).pixmap(32, 32)) hlayout.addWidget(label) button = QDialogButtonBox(QDialogButtonBox.Ok) self.connect(button, SIGNAL('accepted()'), self.accept) attributeLayout = QHBoxLayout() attributeLabel = QLabel(self.tr("Attribute") + ":") linePath = ItemLineEdit(path) attributeLayout.addWidget(attributeLabel) attributeLayout.addWidget(linePath) attributeLayout.setSizeConstraint(QLayout.SetFixedSize) vlayout.addLayout(attributeLayout) if value: valueLayout = QHBoxLayout() valueLabel = QLabel(self.tr("Value" + ":")) lineValue = ItemLineEdit(value) valueLayout.addWidget(valueLabel) valueLayout.addWidget(lineValue) valueLayout.setSizeConstraint(QLayout.SetFixedSize) vlayout.addLayout(valueLayout) vlayout.addWidget(button) hlayout.addLayout(vlayout) self.setLayout(hlayout) self.setFixedHeight(self.sizeHint().height()) dff-1.3.0+dfsg.1/dff/api/include/000077500000000000000000000000001217176075400162755ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/include/argument.hpp000066400000000000000000000042331217176075400206320ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __ARGUMENT_HPP__ #define __ARGUMENT_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include "variant.hpp" #include "export.hpp" #define TYPEMASK 0x00FF #define INPUTMASK 0x0300 #define NEEDMASK 0x0C00 #define PARAMMASK 0x3000 struct Parameter { enum types { NotEditable = 0x1000, Editable = 0x2000 }; }; class Argument { private: std::string __name; uint16_t __flags; std::string __description; bool __enabled; std::list< Variant_p > __parameters; bool __paramslocked; int32_t __minparams; int32_t __maxparams; std::list __subarguments; void setParametersType(uint16_t t); public: enum inputTypes { Empty = 0x0000, Single = 0x0100, List = 0x0200, Optional = 0x0400, Required = 0x0800 }; EXPORT Argument(std::string name, uint16_t flags, std::string description = ""); EXPORT ~Argument(); EXPORT void addSubArgument(Argument* arg); EXPORT void addParameters(std::list< Variant_p > params, uint16_t type, int32_t min = -1, int32_t max=-1); EXPORT std::list< Variant_p > parameters(); EXPORT uint32_t parametersCount(); EXPORT std::string name(); EXPORT uint16_t flags(); EXPORT std::string description(); EXPORT uint16_t type(); EXPORT uint16_t inputType(); EXPORT uint16_t parametersType(); EXPORT uint16_t requirementType(); EXPORT int32_t minimumParameters(); EXPORT int32_t maximumParameters(); }; #endif dff-1.3.0+dfsg.1/dff/api/include/cache.hpp000066400000000000000000000126001217176075400200500ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __CACHE_HPP__ #define __CACHE_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include "export.hpp" #include "threading.hpp" #include "rc.hpp" class Node; class VFile; class FileMapping; class Variant; typedef std::map > Attributes; struct CacheContainer { void* content; void* key; uint64_t state; uint64_t cacheHits; bool used; }; class VFilePool { private: mutex_def(__mutex); EXPORT VFilePool(); EXPORT VFilePool(uint32_t pool); VFilePool& operator=(VFilePool&); VFilePool(const VFilePool&); EXPORT ~VFilePool(); uint64_t __poolHits; uint32_t __poolSize; CacheContainer** __poolSlot; void __allocate(uint32_t poolSize); public: EXPORT static VFilePool& instance(); EXPORT CacheContainer* find(Node* node); EXPORT bool insert(VFile* vfile); EXPORT void unused(CacheContainer* container); }; template< class T > class Cache { public: mutex_def(__mutex); uint32_t __cacheSize; CacheContainer** __cacheSlot; void __allocCache(uint32_t cacheSize) { uint32_t i; this->__cacheSize = cacheSize; this->__cacheSlot = (CacheContainer**)malloc(sizeof(CacheContainer*) * cacheSize); for (i = 0; i < this->__cacheSize; i++) { CacheContainer* container; container = (CacheContainer*)malloc(sizeof(CacheContainer)); memset(container, 0, sizeof(CacheContainer)); this->__cacheSlot[i] = container; } }; EXPORT Cache() { mutex_init(&this->__mutex); this->__allocCache(20); }; EXPORT Cache(uint32_t cacheSize) { mutex_init(&this->__mutex); this->__allocCache(cacheSize); }; EXPORT ~Cache() { free(this->__cacheSlot); mutex_destroy(&this->__mutex); }; EXPORT T find(Node* node, uint64_t state = 0) { uint32_t i; mutex_lock(&this->__mutex); for (i = 0; i < this->__cacheSize; i++) { if (this->__cacheSlot[i]->used == true) { if (this->__cacheSlot[i]->key == (void*)node && this->__cacheSlot[i]->state == state) { this->__cacheSlot[i]->cacheHits++; T attributes = *((T*)this->__cacheSlot[i]->content); mutex_unlock(&this->__mutex); return (attributes); } } } mutex_unlock(&this->__mutex); throw std::string("can't find attribute"); }; EXPORT bool insert(Node* node, T content, uint64_t state = 0) { uint32_t i; mutex_lock(&this->__mutex); for (i = 0; i < this->__cacheSize; i++) { if (this->__cacheSlot[i]->used == false) { T* newContent = new T(content); this->__cacheSlot[i]->content = (void*)newContent; this->__cacheSlot[i]->key = (void*)node; this->__cacheSlot[i]->state = state; this->__cacheSlot[i]->used = true; this->__cacheSlot[i]->cacheHits = 1; mutex_unlock(&this->__mutex); return (true); } } uint64_t oldest = (this->__cacheSlot[0])->cacheHits; int32_t oldestIt = 0; for (i = 1; i < this->__cacheSize; i++) { if (this->__cacheSlot[i]->cacheHits < oldest) { oldest = this->__cacheSlot[i]->cacheHits; oldestIt = i; } } T* newContent = new T(content); delete ((T*)this->__cacheSlot[oldestIt]->content); this->__cacheSlot[oldestIt]->content = (void*)newContent; this->__cacheSlot[oldestIt]->key = (void*)node; this->__cacheSlot[oldestIt]->state = state; this->__cacheSlot[oldestIt]->cacheHits = 1; mutex_unlock(&this->__mutex); return (false); }; }; class AttributeCache : private Cache< Attributes > { private: AttributeCache& operator=(AttributeCache&); AttributeCache(const AttributeCache&); ~AttributeCache(); public: EXPORT static Cache& instance(); }; class DynamicAttributesCache : private Cache < Attributes > { private: DynamicAttributesCache& operator=(DynamicAttributesCache&); DynamicAttributesCache(const DynamicAttributesCache&); ~DynamicAttributesCache(); public: EXPORT static Cache& instance(); }; class FileMappingCache : private Cache < FileMapping* > { public: EXPORT FileMappingCache(uint32_t CacheSize); EXPORT FileMapping* find(Node* node); EXPORT bool insert(FileMapping* fm); }; #endif dff-1.3.0+dfsg.1/dff/api/include/config.hpp000066400000000000000000000036351217176075400202620ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. * Frederic Baguelin */ #ifndef __CONFIG_HPP__ #define __CONFIG_HPP__ #include #include #include #include #include "export.hpp" #include "argument.hpp" #include "constant.hpp" class Config { private: std::string __origin; std::string __description; std::map __arguments; std::map __constants; public: EXPORT Config(std::string origin, std::string description = ""); EXPORT ~Config(); EXPORT std::string origin(); EXPORT std::string description(); EXPORT void addArgument(Argument* arg) throw (std::string); EXPORT std::list arguments(); EXPORT std::list argumentsName(); EXPORT Argument* argumentByName(std::string argname); EXPORT std::list argumentsByName(std::list argsname); EXPORT std::list argumentsByFlags(uint16_t flags); EXPORT std::list argumentsByInputType(uint16_t itype); EXPORT std::list argumentsByRequirementType(uint16_t rtype); EXPORT std::list argumentsByType(uint16_t type); EXPORT void addConstant(Constant* constant) throw (std::string); EXPORT std::list constants(); EXPORT Constant* constantByName(std::string cname); EXPORT std::list constantByType(uint8_t type); }; #endif dff-1.3.0+dfsg.1/dff/api/include/confmanager.hpp000066400000000000000000000027661217176075400213010ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __CONFMANAGER_HPP__ #define __CONFMANAGER_HPP__ #include #include #include #include #include "export.hpp" #include "argument.hpp" #include "constant.hpp" #include "config.hpp" class ConfigManager { private: std::map __configs; EXPORT ConfigManager(); EXPORT ~ConfigManager(); ConfigManager& operator=(ConfigManager&); ConfigManager(const ConfigManager&); public: EXPORT static ConfigManager* Get(); EXPORT void unregisterConf(std::string confname); EXPORT void registerConf(class Config* c) throw(std::string); EXPORT std::list configs(); EXPORT std::list configsName(); EXPORT class Config* configByName(std::string confname); EXPORT std::map constantsByName(std::string constname); EXPORT std::map argumentsByName(std::string argname); }; #endif dff-1.3.0+dfsg.1/dff/api/include/constant.hpp000066400000000000000000000024211217176075400206360ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #ifndef __CONSTANT_HPP__ #define __CONSTANT_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include "variant.hpp" #include "export.hpp" class Constant { private: std::string __name; uint8_t __type; std::string __description; bool __valueslocked; std::list __values; public: EXPORT Constant(std::string name, uint8_t type, std::string description); EXPORT ~Constant(); EXPORT std::string name(); EXPORT std::string description(); EXPORT uint8_t type(); EXPORT void addValues(std::list< Variant_p > values); EXPORT std::list< Variant_p > values(); }; #endif dff-1.3.0+dfsg.1/dff/api/include/datatype.hpp000066400000000000000000000034411217176075400206230ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __DATATYPE_HPP__ #define __DATATYPE_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include #include "threading.hpp" #include "rc.hpp" #include "variant.hpp" class Node; typedef std::map > Attributes; class DataTypeHandler { public: EXPORT DataTypeHandler(std::string); EXPORT virtual ~DataTypeHandler(); EXPORT virtual std::string type(Node* ) = 0; std::string name; }; class DataTypeManager { private: EXPORT DataTypeManager(); EXPORT ~DataTypeManager(); DataTypeManager& operator=(DataTypeManager&); DataTypeManager(const DataTypeManager&); std::list handlers; uint32_t idCounter; dff::map > nodeTypeId; dff::map uniq; dff::map typeIdString; dff::map typeIdHandler; public: EXPORT static DataTypeManager* Get(); EXPORT bool registerHandler(DataTypeHandler*); EXPORT const std::map& foundTypes(); EXPORT Attributes type(Node*); }; #endif dff-1.3.0+dfsg.1/dff/api/include/device.hpp000066400000000000000000000021101217176075400202370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __DEVICE_HPP__ #define __DEVICE_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include "export.hpp" class Device { public: EXPORT Device(); EXPORT virtual ~Device(); EXPORT virtual wchar_t* blockDevice(void); EXPORT virtual wchar_t* serialNumber(void); EXPORT virtual wchar_t* model(void); EXPORT virtual uint64_t size(void); }; class DeviceList { public: EXPORT DeviceList(); }; #endif dff-1.3.0+dfsg.1/dff/api/include/eventhandler.hpp000066400000000000000000000026221217176075400214670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __EVENTHANDLER_HPP__ #define __EVENTHANDLER_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "export.hpp" #include "variant.hpp" #include #include #include typedef struct { enum { OPEN = 0, CLOSE = 1, READ = 2, WRITE = 3, SEEK = 4, OTHER = 5 }; } etype; typedef struct { uint32_t type; RCPtr< Variant > value; } event; class EventHandler { private: std::vector watchers; public: EXPORT EventHandler(); EXPORT virtual ~EventHandler() {}; EXPORT virtual void Event(event *e) = 0; EXPORT bool connection(class EventHandler *obs); EXPORT bool deconnection(class EventHandler *obs); EXPORT bool notify(event *e); }; #endif dff-1.3.0+dfsg.1/dff/api/include/exceptions.hpp000066400000000000000000000015151217176075400211710ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __EXCEPTIONS_HH__ #define __EXCEPTIONS_HH__ #include #include "export.hpp" class envError { public: std::string error; EXPORT envError(std::string msg); }; class vfsError { public: std::string error; EXPORT vfsError(std::string msg); }; #endif dff-1.3.0+dfsg.1/dff/api/include/export.hpp000066400000000000000000000014461217176075400203340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __EXPORT_HPP__ #define __EXPORT_HPP__ #ifndef WIN32 #define IMPORT extern #define EXPORT #else #define EXPORT __declspec( dllexport ) #define IMPORT __declspec(dllimport) #include #include "windows.h" #endif #endif dff-1.3.0+dfsg.1/dff/api/include/fastsearch.hpp000066400000000000000000000277511217176075400211450ustar00rootroot00000000000000/* fastsearch implementation this implementation comes from Python. This implementation is faster than the one provided in DFF until version 1.0. The algorithm has been kept untouched, only types have been changed to reflect base type and coding style too: STRINGLIB_CHAR --> unsigned char* Py_ssize_t --> int32_t Py_LOCAL_INLINE --> inline */ #ifndef __FASTSEARCH_HPP__ #define __FASTSEARCH_HPP__ /* fast search/count implementation, based on a mix between boyer- moore and horspool, with a few more bells and whistles on the top. for some more background, see: http://effbot.org/zone/stringlib.htm */ /* note: fastsearch may access s[n], which isn't a problem when using Python's ordinary string types, but may cause problems if you're using this code in other contexts. also, the count mode returns -1 if there cannot possible be a match in the target string, and 0 if it has actually checked for matches, but didn't find any. callers beware! */ #define FAST_COUNT 0 #define FAST_SEARCH 1 #define FAST_RSEARCH 2 #define LONG_SIZE (8 * CMAKE_SIZEOF_VOID_P) #ifdef SWIGWORDSIZE64 #define BLOOM_WIDTH 64 #else #define BLOOM_WIDTH 32 #endif #define BLOOM_ADD(mask, ch) \ ((mask |= (1UL << ((ch) & (BLOOM_WIDTH -1))))) #define BLOOM(mask, ch) \ ((mask & (1UL << ((ch) & (BLOOM_WIDTH -1))))) inline int32_t fastsearch(const unsigned char* s, int32_t n, const unsigned char* p, int32_t m, int32_t maxcount, int mode) { unsigned long mask; int32_t skip, count = 0; int32_t i, j, mlast, w; w = n - m; if (w < 0 || (mode == FAST_COUNT && maxcount == 0)) return -1; /* look for special cases */ if (m <= 1) { if (m <= 0) return -1; /* use special case for 1-character strings */ if (mode == FAST_COUNT) { for (i = 0; i < n; i++) if (s[i] == p[0]) { count++; if (count == maxcount) return maxcount; } return count; } else if (mode == FAST_SEARCH) { for (i = 0; i < n; i++) if (s[i] == p[0]) return i; } else { /* FAST_RSEARCH */ for (i = n - 1; i > -1; i--) if (s[i] == p[0]) return i; } return -1; } mlast = m - 1; skip = mlast - 1; mask = 0; if (mode != FAST_RSEARCH) { /* create compressed boyer-moore delta 1 table */ /* process pattern[:-1] */ for (i = 0; i < mlast; i++) { BLOOM_ADD(mask, p[i]); if (p[i] == p[mlast]) skip = mlast - i - 1; } /* process pattern[-1] outside the loop */ BLOOM_ADD(mask, p[mlast]); for (i = 0; i <= w; i++) { /* note: using mlast in the skip path slows things down on x86 */ if (s[i+m-1] == p[m-1]) { /* candidate match */ for (j = 0; j < mlast; j++) if (s[i+j] != p[j]) break; if (j == mlast) { /* got a match! */ if (mode != FAST_COUNT) return i; count++; if (count == maxcount) return maxcount; i = i + mlast; continue; } /* miss: check if next character is part of pattern */ if (!BLOOM(mask, s[i+m])) i = i + m; else i = i + skip; } else { /* skip: check if next character is part of pattern */ if (!BLOOM(mask, s[i+m])) i = i + m; } } } else { /* FAST_RSEARCH */ /* create compressed boyer-moore delta 1 table */ /* process pattern[0] outside the loop */ BLOOM_ADD(mask, p[0]); /* process pattern[:0:-1] */ for (i = mlast; i > 0; i--) { BLOOM_ADD(mask, p[i]); if (p[i] == p[0]) skip = i - 1; } for (i = w; i >= 0; i--) { if (s[i] == p[0]) { /* candidate match */ for (j = mlast; j > 0; j--) if (s[i+j] != p[j]) break; if (j == 0) /* got a match! */ return i; /* miss: check if previous character is part of pattern */ if (i > 0 && !BLOOM(mask, s[i-1])) i = i - m; else i = i - skip; } else { /* skip: check if previous character is part of pattern */ if (i > 0 && !BLOOM(mask, s[i-1])) i = i - m; } } } if (mode != FAST_COUNT) return -1; return count; } inline int32_t wfastsearch(const unsigned char* s, int32_t n, const unsigned char* p, int32_t m, unsigned char wildcard, int32_t maxcount, int mode) { unsigned long mask; int32_t skip, count = 0; int32_t i, j, mlast, w; w = n - m; if (w < 0 || (mode == FAST_COUNT && maxcount == 0)) return -1; /* look for special cases */ if (m <= 1) { if (m <= 0) return -1; /* use special case for 1-character strings */ if (mode == FAST_COUNT) { for (i = 0; i < n; i++) if ((s[i] == p[0]) || (s[i] == wildcard)) { count++; if (count == maxcount) return maxcount; } return count; } else if (mode == FAST_SEARCH) { for (i = 0; i < n; i++) if ((s[i] == p[0]) || (s[i] == wildcard)) return i; } else { /* FAST_RSEARCH */ for (i = n - 1; i > -1; i--) if ((s[i] == p[0]) || (s[i] == wildcard)) return i; } return -1; } mlast = m - 1; skip = mlast - 1; mask = 0; if (mode != FAST_RSEARCH) { /* create compressed boyer-moore delta 1 table */ /* process pattern[:-1] */ for (i = 0; i < mlast; i++) { if (p[i] != wildcard) BLOOM_ADD(mask, p[i]); if ((p[i] == p[mlast]) || (p[i] == wildcard)) skip = mlast - i - 1; } /* process pattern[-1] outside the loop */ if (p[mlast] != wildcard) BLOOM_ADD(mask, p[mlast]); for (i = 0; i <= w; i++) { /* note: using mlast in the skip path slows things down on x86 */ if ((s[i+m-1] == p[m-1]) || (p[m-1] == wildcard)) { /* candidate match */ for (j = 0; j < mlast; j++) if ((s[i+j] != p[j]) && (p[j] != wildcard)) break; if (j == mlast) { /* got a match! */ if (mode != FAST_COUNT) return i; count++; if (count == maxcount) return maxcount; i = i + mlast; continue; } /* miss: check if next character is part of pattern */ i = i + skip; } else { /* skip: check if next character is part of pattern */ if (!BLOOM(mask, s[i+m])) i = i + m; } } } else { /* FAST_RSEARCH */ /* create compressed boyer-moore delta 1 table */ /* process pattern[0] outside the loop */ if (p[0] != wildcard) BLOOM_ADD(mask, p[0]); /* process pattern[:0:-1] */ for (i = mlast; i > 0; i--) { if (p[i] != wildcard) BLOOM_ADD(mask, p[i]); if ((p[i] == p[0]) || (p[i] == wildcard)) skip = i - 1; } for (i = w; i >= 0; i--) { if ((s[i] == p[0]) || (p[0] == wildcard)) { /* candidate match */ for (j = mlast; j > 0; j--) if ((s[i+j] != p[j]) && (p[j] != wildcard)) break; if (j == 0) /* got a match! */ return i; /* miss: check if previous character is part of pattern */ if (i > 0) i = i - skip; } else { /* skip: check if previous character is part of pattern */ if (i > 0 && !BLOOM(mask, s[i-1])) i = i - m; } } } if (mode != FAST_COUNT) return -1; return count; } #include inline unsigned char upper(unsigned char c) { if ((c >= 'a') && (c <= 'z')) return (c - 32); else return c; } inline char cicmp(unsigned char c1, unsigned char c2) { return (upper(c1) == upper(c2)); } inline int32_t cifastsearch(const unsigned char* s, int32_t n, const unsigned char* p, int32_t m, int32_t maxcount, int mode) { unsigned long mask; int32_t skip, count = 0; int32_t i, j, mlast, w; w = n - m; if (w < 0 || (mode == FAST_COUNT && maxcount == 0)) return -1; /* look for special cases */ if (m <= 1) { if (m <= 0) return -1; /* use special case for 1-character strings */ if (mode == FAST_COUNT) { for (i = 0; i < n; i++) if (cicmp(s[i], p[0])) { count++; if (count == maxcount) return maxcount; } return count; } else if (mode == FAST_SEARCH) { for (i = 0; i < n; i++) if (cicmp(s[i], p[0])) return i; } else { /* FAST_RSEARCH */ for (i = n - 1; i > -1; i--) if (cicmp(s[i], p[0])) return i; } return -1; } mlast = m - 1; skip = mlast - 1; mask = 0; if (mode != FAST_RSEARCH) { /* create compressed boyer-moore delta 1 table */ /* process pattern[:-1] */ for (i = 0; i < mlast; i++) { BLOOM_ADD(mask, p[i]); BLOOM_ADD(mask, upper(p[i])); if (cicmp(p[i], p[mlast])) skip = mlast - i - 1; } /* process pattern[-1] outside the loop */ BLOOM_ADD(mask, upper(p[mlast])); BLOOM_ADD(mask, p[mlast]); for (i = 0; i <= w; i++) { /* note: using mlast in the skip path slows things down on x86 */ if (cicmp(s[i+m-1], p[m-1]) == 1) { /* candidate match */ for (j = 0; j < mlast; j++) if (!cicmp(s[i+j], p[j])) break; if (j == mlast) { /* got a match! */ if (mode != FAST_COUNT) return i; count++; if (count == maxcount) return maxcount; i = i + mlast; continue; } /* miss: check if next character is part of pattern */ if (!(BLOOM(mask, s[i+m]) || !BLOOM(mask, upper(s[i+m])))) i = i + m; else i = i + skip; } else { //printf(" SKIPPING check if %c in pattern \n", s[i+m]); /* skip: check if next character is part of pattern */ if (!(BLOOM(mask, s[i+m]) || BLOOM(mask, upper(s[i+m])))) i = i + m; } } } else { /* FAST_RSEARCH */ /* create compressed boyer-moore delta 1 table */ /* process pattern[0] outside the loop */ BLOOM_ADD(mask, p[0]); BLOOM_ADD(mask, upper(p[0])); /* process pattern[:0:-1] */ for (i = mlast; i > 0; i--) { BLOOM_ADD(mask, p[i]); BLOOM_ADD(mask, upper(p[i])); if (cicmp(p[i], p[0])) skip = i - 1; } for (i = w; i >= 0; i--) { if (cicmp(s[i], p[0])) { /* candidate match */ for (j = mlast; j > 0; j--) if (!cicmp(s[i+j], p[j])) break; if (j == 0) /* got a match! */ return i; /* miss: check if previous character is part of pattern */ if (i > 0 && !(BLOOM(mask, s[i-1]) || BLOOM(mask, upper(s[i-1])))) i = i - m; else i = i - skip; } else { /* skip: check if previous character is part of pattern */ if (i > 0 && !(BLOOM(mask, s[i-1]) || BLOOM(mask, upper(s[i-1])))) i = i - m; } } } if (mode != FAST_COUNT) return -1; return count; } #endif dff-1.3.0+dfsg.1/dff/api/include/fdmanager.hpp000066400000000000000000000023551217176075400207370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FDMANAGER_HPP__ #define __FDMANAGER_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "export.hpp" #include "exceptions.hpp" #include "filemapping.hpp" #include "vfile.hpp" #include #include typedef struct { Node* node; class Variant* id; uint64_t offset; VFile* file; } fdinfo; class FdManager { private: mutex_def(__mutex); uint32_t allocated; std::vector fds; public: EXPORT FdManager(); EXPORT ~FdManager(); EXPORT fdinfo* get(int32_t fd); EXPORT void remove(int32_t fd); EXPORT int32_t push(fdinfo* fi); }; #endif dff-1.3.0+dfsg.1/dff/api/include/filemapping.hpp000066400000000000000000000042021217176075400212770ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FILEMAPPING_HPP__ #define __FILEMAPPING_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "threading.hpp" #include "rc.hpp" #include "export.hpp" #include typedef struct { public: uint64_t offset; uint64_t size; class Node* origin; uint64_t originoffset; } chunk; class FileMapping { private: mutex_def(__fm_mutex); uint64_t __refcount; Node* __node; std::vector __chunks; uint64_t __maxOffset; chunk* __prevChunk; uint32_t __bsearch(uint64_t offset, uint32_t leftbound, uint32_t rightbound, bool* found); void allocChunk(uint64_t offset, uint64_t size, class Node* origin, uint64_t originoffset); chunk* chunkFromIdx(uint32_t idx); std::vector chunksFromIdxRange(uint32_t begidx, uint32_t endidx); public: EXPORT FileMapping(Node* node); EXPORT ~FileMapping(); EXPORT void addref(); EXPORT void delref(); EXPORT uint64_t refcount(); EXPORT Node* node(void); EXPORT uint64_t maxOffset(); EXPORT chunk* chunkFromOffset(uint64_t offset); EXPORT void push(uint64_t offset, uint64_t size, class Node* origin=NULL, uint64_t originoffset=0); EXPORT uint32_t chunkCount(void); EXPORT chunk* firstChunk(void); EXPORT chunk* lastChunk(void); EXPORT uint32_t chunkIdxFromOffset(uint64_t offset, uint32_t begidx=0); EXPORT std::vector chunksFromOffsetRange(uint64_t begoffset, uint64_t endoffset); EXPORT std::vector chunks(void); }; #endif dff-1.3.0+dfsg.1/dff/api/include/filter.hpp000066400000000000000000000045771217176075400203100ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FILTER_HPP__ #define __FILTER_HPP__ #include #include "eventhandler.hpp" #include "node.hpp" #include "../filters/astnodes.hpp" #include "../filters/scanner.hpp" class Filter : public EventHandler { public: EXPORT Filter(std::string fname) throw (std::string); EXPORT ~Filter(); EXPORT std::string query(); EXPORT std::string filterName(); EXPORT virtual void Event(event* e); EXPORT void setFilterName(std::string fname) throw (std::string); EXPORT void compile(std::string query) throw (std::string); EXPORT void processFolder(Node* nodeptr) throw (std::string); EXPORT void process(Node* nodeptr, bool recursive=true) throw (std::string); EXPORT void process(std::list nodes) throw (std::string); EXPORT void process(std::vector nodes) throw (std::string); EXPORT void process(uint64_t nodeid, bool recursive=true) throw (std::string); EXPORT void process(uint16_t fsoid, bool recursive=true) throw (std::string); //bool match(Node* ptr); throw (std::string); EXPORT std::vector matchedNodes(); enum EventTypes { TotalNodesToProcess = 0x200, ProcessedNodes = 0x201, NodeMatched = 0x202, StopProcessing = 0x204, EndOfProcessing = 0x205, AstReset = 0x4242 }; private: void __process(Node* nodeptr, uint64_t* processed); void __reset(); void __notifyNodesToProcess(uint64_t nodescount); void __notifyMatch(Node* nodeptr); void __notifyProgress(uint64_t processed); void __notifyEndOfProcessing(uint64_t processed); std::string __formatErrorMsg(); void __initCtx() throw (std::string); bool __eval(Node* node); event* __ev; std::vector __matchednodes; std::string __fname; uint32_t __uid; std::string __query; filter_ctx* __ctx; bool __stop; }; #endif dff-1.3.0+dfsg.1/dff/api/include/fso.hpp000066400000000000000000000045271217176075400176050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FSO_HPP__ #define __FSO_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include #include #include #include "variant.hpp" #include "vfs.hpp" #include "node.hpp" //typedef std::map RunTimeArguments; class fso { private: std::vector __nodes; uint16_t __uid; std::vector __children; fso* __parent; public: std::map res; std::string stateinfo; std::string name; EXPORT fso(std::string name); EXPORT virtual ~fso(); EXPORT virtual void start(std::map > args) = 0; EXPORT virtual int32_t vopen(class Node *n) = 0; EXPORT virtual int32_t vread(int32_t fd, void *rbuff, uint32_t size) = 0; EXPORT virtual int32_t vwrite(int32_t fd, void *wbuff, uint32_t size) = 0; EXPORT virtual int32_t vclose(int32_t fd) = 0; EXPORT virtual uint64_t vseek(int32_t fd, uint64_t offset, int32_t whence) = 0; EXPORT virtual uint32_t status(void) = 0; EXPORT virtual uint64_t vtell(int32_t fd) = 0; EXPORT virtual void setVerbose(bool verbose){ (void)verbose;} EXPORT virtual bool verbose() { return false; } EXPORT void registerTree(Node* parent, Node* head); EXPORT uint64_t registerNode(Node* n); EXPORT std::vector nodes(); EXPORT uint64_t nodeCount(); EXPORT uint16_t uid(); EXPORT Node* getNodeById(uint64_t id); EXPORT bool hasChildren(); EXPORT std::vector children(); EXPORT uint32_t childCount(); EXPORT void setParent(class fso* parent); EXPORT class fso* parent(); EXPORT void addChild(class fso* child); }; #endif dff-1.3.0+dfsg.1/dff/api/include/index.hpp000066400000000000000000000125051217176075400201200ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon */ #ifndef __INDEX_H__ # define __INDEX_H__ #include #include #include #include #include "../include/node.hpp" class AttributeIndex : public AttributesHandler { public: AttributeIndex(std::string name, std::string query); virtual Attributes attributes(class Node*); private: std::string __query; }; class Index { /*! \class Index \brief Indexing the content of Nodes. The purpose of this class is to create an index which will index the content of Nodes so reIndexSearch using key words can be performed. */ public: //! Create an index object. EXPORT Index(); /*! \brief Create an index object. \param location the path to the index file */ EXPORT Index(const std::string & location); //! Destructor. Free resources. EXPORT ~Index(); /*! \brief Create the index. If the location is empty, try to create it at the default location. \return true if the creattion did not met any errors, False otherwise. */ EXPORT bool createIndex(); /*! \brief Close the open index. Optimize and close the IndexWriter. Does nothing if the index is not opened. */ EXPORT void closeIndex(); //! \return the location of the index const std::string & location() const; //! \param location the path to the index file void setLocation(const std::string & location); /*! \brief Add a document to the index. Does nothing if the index is not opened. \param doc the document which must be added. */ void addDocument(lucene::document::Document * doc); /*! \brief Create a new document. The caller musts clean the document when he does not need it anymore. \return a pointer to the instance of the Document class, or NULL if something went wrong. */ lucene::document::Document * newDocument(); /*! \brief Index data. Index the content of the Node ``data``. \param data the node which content musts be indexed. \return true if the indexing went fine, false otherwise. */ EXPORT bool indexData(Node * data); /*! \return a pointer to the Document instance associated with the Index. */ lucene::document::Document * document() const; /*! Associate a document with the Index. \param doc a pointer to the document instance. */ void setDocument(lucene::document::Document * doc); void setIndexContent(bool index); void setIndexAttr(bool index); private: void __indexContent(Node * data, lucene::document::Field * content); std::string __location; lucene::index::IndexWriter * __writer; lucene::document::Document * __doc; lucene::analysis::standard::StandardAnalyzer * __an; lucene::document::Field * __content; bool index_content, index_attr; }; class IndexSearch { /*! \class IndexSearch \brief This class is used to search a keyword in an index. */ public: //! Constructor. IndexSearch(); /*! \brief Constructor \param location the path to the directory where the index file is located. */ IndexSearch(const std::string & location); //! Descructor. Free resources. ~IndexSearch(); /*! \brief Do the search. This method do the search within the indexed content. If params '''query''' and '''must_contain_query''' are empty, does nothing. Once the search is done, the result will be accessible through a node callled '''Search::''', located in the node '''Searched Items''', itself located at the root of the VFS (this '''Searched Items''' node is always created when DFF is launched). The two parameters can be a word or a list of words separated by spaces. If '''query''' is not empty, the search will retrieved all data containing at least one of the word contained in query. It acts as a logical OR. If the parameter '''must_contain_query''' is not empty, the research will return the data where all the words of '''must_contain_query''' were found. It acts as a logical AND. \param query a basic query composed of a word or a list of word separated by spaces. \param must_contain_query a query composed of a words or a liste of words separated by spaces. All the world of the query will be in each found results. */ void exec_query(const std::string & query, const std::string & must_contain_query = ""); char* narrow( const wstring& str ); static bool deleteDoc(std::string path, std::string location); private: void __displayResults(lucene::search::Hits * h); Node * __newIndexation(Node * root); lucene::search::Query * __getMultiSearchQuery(const std::string & query, lucene::analysis::standard::StandardAnalyzer * an); std::string __query; std::string __must; std::string __location; }; #endif /* __INDEX_H__*/ dff-1.3.0+dfsg.1/dff/api/include/iostat.hpp000066400000000000000000000021741217176075400203150ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __IOSTAT_HPP__ #define __IOSTAT_HPP__ #include "datatype.hpp" class IOStat { public: EXPORT static IOStat& getInstance(); EXPORT void pushReadStats(uint16_t fsoid, uint64_t read); EXPORT void pushInstanceStats(uint16_t fsoid); EXPORT uint64_t totalReadById(uint16_t fsoid); EXPORT uint64_t totalInstanceById(uint16_t fsoid); private: EXPORT IOStat() {} EXPORT ~IOStat() {} EXPORT IOStat(const IOStat&) {} EXPORT const IOStat& operator=(const IOStat&); dff::map __io; dff::map __instances; }; #endif dff-1.3.0+dfsg.1/dff/api/include/magichandler.hpp000066400000000000000000000033431217176075400214270ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __MAGICHANDLER_HPP__ #define __MAGICHANDLER_HPP__ #include "datatype.hpp" #include "vfile.hpp" #include class MagicType : public DataTypeHandler { protected: magic_t _ctx; std::string _mfile; bool _ready; void* _buff; public: EXPORT MagicType(std::string name, int flags) throw (std::string); EXPORT ~MagicType(); EXPORT virtual std::string type(Node* node) = 0; EXPORT bool setMagicFile(std::string mfile) throw (std::string); EXPORT std::string magicFile(); }; class MagicHandler : public MagicType { private: EXPORT MagicHandler() : MagicType("magic", MAGIC_NONE) {} EXPORT ~MagicHandler() {} MagicHandler& operator=(MagicHandler&); MagicHandler(const MagicHandler&); public: EXPORT static MagicHandler* Get() throw (std::string); EXPORT virtual std::string type(Node* node); }; class MimeHandler : public MagicType { private: EXPORT MimeHandler() : MagicType("magic mime", MAGIC_MIME) {} EXPORT ~MimeHandler() {} MimeHandler& operator=(MimeHandler&); MimeHandler(const MimeHandler&); public: EXPORT static MimeHandler* Get() throw (std::string); EXPORT virtual std::string type(Node* node); }; #endif dff-1.3.0+dfsg.1/dff/api/include/mfso.hpp000066400000000000000000000036661217176075400177650ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __MFSO_HPP__ #define __MFSO_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include #include #include #include "fso.hpp" #include "fdmanager.hpp" #include "vfile.hpp" //#include "cache.hpp" #include "threading.hpp" class FileMappingCache; class mfso: public fso { private: bool __verbose; class VFile* __vfile; std::list __children; class mfso* __parent; FileMappingCache* __fmCache; int32_t readFromMapping(FileMapping* fm, fdinfo* fi, void* buff, uint32_t size); FileMapping* mapFile(Node* node); public: FdManager* __fdmanager; EXPORT mfso(std::string name); EXPORT virtual ~mfso(); EXPORT virtual void start(std::map > args) = 0; EXPORT virtual int32_t vopen(class Node *n); EXPORT virtual int32_t vread(int32_t fd, void *buff, uint32_t size); EXPORT virtual int32_t vwrite(int32_t fd, void *buff, uint32_t size); EXPORT virtual int32_t vclose(int32_t fd); EXPORT virtual uint64_t vseek(int32_t fd, uint64_t offset, int32_t whence); EXPORT virtual uint32_t status(void); EXPORT virtual uint64_t vtell(int32_t fd); EXPORT virtual void setVerbose(bool verbose); EXPORT virtual bool verbose(); }; #endif dff-1.3.0+dfsg.1/dff/api/include/node.hpp000066400000000000000000000146671217176075400177510ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __NODE_HPP__ #define __NODE_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include #include #include #include #include "export.hpp" #include "rc.hpp" class Constant; class FileMapping; class Variant; class Tag; #define Variant_p RCPtr< Variant > #define Tag_p RCPtr< Tag > typedef std::map > Attributes; class AttributesHandler { std::string __handlerName; public: EXPORT AttributesHandler(std::string handlerName); EXPORT virtual ~AttributesHandler(); EXPORT virtual Attributes attributes(class Node*) = 0; EXPORT std::string name(void); }; class AttributesHandlers { private: uint64_t __state; std::set __handlers; public: EXPORT AttributesHandlers(); EXPORT ~AttributesHandlers(); EXPORT size_t count(); EXPORT std::set& handlers(); EXPORT void updateState(void); EXPORT const uint64_t state(void); EXPORT bool add(AttributesHandler* attributeHandler); EXPORT bool remove(AttributesHandler* attributeHandler); EXPORT bool remove(std::string name); }; #define ISFILE 0x01 #define ISDIR 0x02 #define ISLINK 0x04 #define ISDELETED 0x08 enum attributeNameType { ABSOLUTE_ATTR_NAME = 0, RELATIVE_ATTR_NAME = 1 }; class Node { protected: class Node* __parent; AttributesHandlers __attributesHandlers; std::vector __children; uint32_t __childcount; std::string __name; uint64_t __size; class fso* __fsobj; uint64_t __common_attributes; uint32_t __id; uint64_t __uid; uint64_t __tags; EXPORT virtual Attributes _attributes(); EXPORT virtual uint64_t _attributesState(); EXPORT void attributesByTypeFromVariant(Variant_p rcvar, uint8_t, Attributes*, std::string current); EXPORT void attributesByNameFromVariant(Variant_p rcvar, std::string name, std::list< Variant_p >* result); EXPORT void attributeByAbsoluteNameFromVariant(Variant_p rcvar, std::string name, std::list< Variant_p >* result); EXPORT void attributesNamesFromVariant(Variant_p rcvar, std::list* names); EXPORT void attributesNamesFromVariant(Variant_p rcvar, std::list* names, std::string current); EXPORT void attributesNamesAndTypesFromVariant(Variant_p rcvar, std::map *namestypes, std::string current); EXPORT bool constantValuesMatch(Constant* constant, Attributes vars); EXPORT void __compatibleModulesByType(const std::map& cmime, Attributes& dtypes, std::list& result); EXPORT void __compatibleModulesByExtension(const std::map& constants, std::string& ext, std::list& result); public: EXPORT Node(std::string name, uint64_t size=0, Node* parent=NULL, fso* fsobj=NULL); EXPORT Node(); EXPORT virtual ~Node(); uint32_t __at; EXPORT void setId(uint32_t id); EXPORT virtual uint32_t id(void); EXPORT void setFile(void); EXPORT void setDir(void); EXPORT void setLink(void); EXPORT void setDeleted(void); EXPORT void setSize(uint64_t size); EXPORT void setFsobj(fso* obj); EXPORT void setParent(Node* parent); EXPORT virtual void fileMapping(FileMapping *); EXPORT virtual uint64_t size(void); EXPORT std::string path(void); EXPORT std::string name(void); EXPORT std::string absolute(void); EXPORT std::string extension(void); EXPORT virtual bool isFile(void); EXPORT virtual bool isDir(void); EXPORT virtual bool isLink(void); EXPORT virtual bool isVDir(void); EXPORT virtual bool isDeleted(void); EXPORT virtual class fso* fsobj(void); EXPORT Node* parent(void); EXPORT std::vector children(void); EXPORT bool addChild(class Node* child); EXPORT bool hasChildren(void); EXPORT uint32_t childCount(void); EXPORT uint64_t totalChildrenCount(uint32_t depth=(uint32_t)-1); EXPORT virtual class VFile* open(void); EXPORT uint32_t at(void); EXPORT uint64_t uid(void); EXPORT virtual AttributesHandlers& attributesHandlers(void); EXPORT virtual bool registerAttributes(AttributesHandler*); EXPORT virtual Attributes dataType(void); EXPORT virtual Attributes attributes(void); EXPORT virtual Attributes attributesByType(uint8_t type); EXPORT virtual std::list< Variant_p > attributesByName(std::string name, attributeNameType tname=RELATIVE_ATTR_NAME); EXPORT virtual std::list attributesNames(attributeNameType tname=RELATIVE_ATTR_NAME); EXPORT virtual std::map attributesNamesAndTypes(void); EXPORT virtual std::string icon(void); EXPORT virtual std::list compatibleModules(void); EXPORT virtual bool isCompatibleModule(std::string); EXPORT virtual Attributes dynamicAttributes(void); EXPORT virtual Attributes dynamicAttributes(std::string name); EXPORT virtual std::list dynamicAttributesNames(void); EXPORT virtual Attributes fsoAttributes(void); EXPORT virtual bool setTag(std::string name); EXPORT virtual bool setTag(uint32_t id); EXPORT virtual bool removeTag(std::string name); EXPORT virtual bool removeTag(uint32_t id); EXPORT virtual bool isTagged(std::string name); EXPORT virtual bool isTagged(uint32_t id); EXPORT virtual std::vector tags(void); EXPORT virtual std::vector tagsId(void); }; #endif dff-1.3.0+dfsg.1/dff/api/include/path.hpp000066400000000000000000000014271217176075400177460ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __PATH_HPP__ #define __PATH_HPP__ #include "export.hpp" #include #include #include #include class Path { public: std::string path; EXPORT Path(std::string p); }; #endif dff-1.3.0+dfsg.1/dff/api/include/pyrun.swg000066400000000000000000001452241217176075400202040ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- * pyrun.swg patched from 2.0.9 original version for DFF * * This file contains the runtime support for Python modules * and includes code for managing global variables and pointer * type checking. * * ----------------------------------------------------------------------------- */ /* Common SWIG API */ /* for raw pointers */ #define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) #define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) #ifdef SWIGPYTHON_BUILTIN #define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) #else #define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) #endif #define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) #define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) #define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) #define swig_owntype int /* for raw packed data */ #define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) #define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) /* for class or struct pointers */ #define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) #define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) /* for C or C++ function pointers */ #define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) #define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) /* for C++ member pointers, ie, member methods */ #define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) #define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) /* Runtime API */ #define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) #define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) #define SWIG_NewClientData(obj) SwigPyClientData_New(obj) #define SWIG_SetErrorObj SWIG_Python_SetErrorObj #define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg #define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) #define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) #define SWIG_fail goto fail /* Runtime API implementation */ /* Error manipulation */ SWIGINTERN void SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetObject(errtype, obj); Py_DECREF(obj); SWIG_PYTHON_THREAD_END_BLOCK; } SWIGINTERN void SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(errtype, msg); SWIG_PYTHON_THREAD_END_BLOCK; } #define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) /* Set a constant value */ #if defined(SWIGPYTHON_BUILTIN) SWIGINTERN void SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { PyObject *s = PyString_InternFromString(key); PyList_Append(seq, s); Py_DECREF(s); } SWIGINTERN void SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { #if PY_VERSION_HEX < 0x02030000 PyDict_SetItemString(d, (char *)name, obj); #else PyDict_SetItemString(d, name, obj); #endif Py_DECREF(obj); if (public_interface) SwigPyBuiltin_AddPublicSymbol(public_interface, name); } #else SWIGINTERN void SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { #if PY_VERSION_HEX < 0x02030000 PyDict_SetItemString(d, (char *)name, obj); #else PyDict_SetItemString(d, name, obj); #endif Py_DECREF(obj); } #endif /* Append a value to the result obj */ SWIGINTERN PyObject* SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { #if !defined(SWIG_PYTHON_OUTPUT_TUPLE) if (!result) { result = obj; } else if (result == Py_None) { Py_DECREF(result); result = obj; } else { if (!PyList_Check(result)) { PyObject *o2 = result; result = PyList_New(1); PyList_SetItem(result, 0, o2); } PyList_Append(result,obj); Py_DECREF(obj); } return result; #else PyObject* o2; PyObject* o3; if (!result) { result = obj; } else if (result == Py_None) { Py_DECREF(result); result = obj; } else { if (!PyTuple_Check(result)) { o2 = result; result = PyTuple_New(1); PyTuple_SET_ITEM(result, 0, o2); } o3 = PyTuple_New(1); PyTuple_SET_ITEM(o3, 0, obj); o2 = result; result = PySequence_Concat(o2, o3); Py_DECREF(o2); Py_DECREF(o3); } return result; #endif } /* Unpack the argument tuple */ SWIGINTERN int SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) { if (!args) { if (!min && !max) { return 1; } else { PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", name, (min == max ? "" : "at least "), (int)min); return 0; } } if (!PyTuple_Check(args)) { if (min <= 1 && max >= 1) { register int i; objs[0] = args; for (i = 1; i < max; ++i) { objs[i] = 0; } return 2; } PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); return 0; } else { register Py_ssize_t l = PyTuple_GET_SIZE(args); if (l < min) { PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", name, (min == max ? "" : "at least "), (int)min, (int)l); return 0; } else if (l > max) { PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", name, (min == max ? "" : "at most "), (int)max, (int)l); return 0; } else { register int i; for (i = 0; i < l; ++i) { objs[i] = PyTuple_GET_ITEM(args, i); } for (; l < max; ++l) { objs[l] = 0; } return i + 1; } } } /* A functor is a function object with one single object argument */ #if PY_VERSION_HEX >= 0x02020000 #define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); #else #define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); #endif /* Helper for static pointer initialization for both C and C++ code, for example static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); */ #ifdef __cplusplus #define SWIG_STATIC_POINTER(var) var #else #define SWIG_STATIC_POINTER(var) var = 0; if (!var) var #endif /* ----------------------------------------------------------------------------- * Pointer declarations * ----------------------------------------------------------------------------- */ /* Flags for new pointer objects */ #define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) #define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) #define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) #define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) #define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) #ifdef __cplusplus extern "C" { #endif /* How to access Py_None */ #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # ifndef SWIG_PYTHON_NO_BUILD_NONE # ifndef SWIG_PYTHON_BUILD_NONE # define SWIG_PYTHON_BUILD_NONE # endif # endif #endif #ifdef SWIG_PYTHON_BUILD_NONE # ifdef Py_None # undef Py_None # define Py_None SWIG_Py_None() # endif SWIGRUNTIMEINLINE PyObject * _SWIG_Py_None(void) { PyObject *none = Py_BuildValue((char*)""); Py_DECREF(none); return none; } SWIGRUNTIME PyObject * SWIG_Py_None(void) { static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); return none; } #endif /* The python void return value */ SWIGRUNTIMEINLINE PyObject * SWIG_Py_Void(void) { PyObject *none = Py_None; Py_INCREF(none); return none; } /* SwigPyClientData */ typedef struct { PyObject *klass; PyObject *newraw; PyObject *newargs; PyObject *destroy; int delargs; int implicitconv; PyTypeObject *pytype; } SwigPyClientData; SWIGRUNTIMEINLINE int SWIG_Python_CheckImplicit(swig_type_info *ty) { SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; return data ? data->implicitconv : 0; } SWIGRUNTIMEINLINE PyObject * SWIG_Python_ExceptionType(swig_type_info *desc) { SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; PyObject *klass = data ? data->klass : 0; return (klass ? klass : PyExc_RuntimeError); } SWIGRUNTIME SwigPyClientData * SwigPyClientData_New(PyObject* obj) { if (!obj) { return 0; } else { SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); /* the klass element */ data->klass = obj; Py_INCREF(data->klass); /* the newraw method and newargs arguments used to create a new raw instance */ if (PyClass_Check(obj)) { data->newraw = 0; data->newargs = obj; Py_INCREF(obj); } else { #if (PY_VERSION_HEX < 0x02020000) data->newraw = 0; #else data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); #endif if (data->newraw) { Py_INCREF(data->newraw); data->newargs = PyTuple_New(1); PyTuple_SetItem(data->newargs, 0, obj); } else { data->newargs = obj; } Py_INCREF(data->newargs); } /* the destroy method, aka as the C++ delete method */ data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); if (PyErr_Occurred()) { PyErr_Clear(); data->destroy = 0; } if (data->destroy) { int flags; Py_INCREF(data->destroy); flags = PyCFunction_GET_FLAGS(data->destroy); #ifdef METH_O data->delargs = !(flags & (METH_O)); #else data->delargs = 0; #endif } else { data->delargs = 0; } data->implicitconv = 0; data->pytype = 0; return data; } } SWIGRUNTIME void SwigPyClientData_Del(SwigPyClientData *data) { Py_XDECREF(data->newraw); Py_XDECREF(data->newargs); Py_XDECREF(data->destroy); } /* =============== SwigPyObject =====================*/ typedef struct { PyObject_HEAD void *ptr; swig_type_info *ty; int own; PyObject *next; int implicitconv; #ifdef SWIGPYTHON_BUILTIN PyObject *dict; #endif } SwigPyObject; SWIGRUNTIME PyObject * SwigPyObject_long(SwigPyObject *v) { return PyLong_FromVoidPtr(v->ptr); } SWIGRUNTIME PyObject * SwigPyObject_format(const char* fmt, SwigPyObject *v) { PyObject *res = NULL; PyObject *args = PyTuple_New(1); if (args) { if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { PyObject *ofmt = SWIG_Python_str_FromChar(fmt); if (ofmt) { #if PY_VERSION_HEX >= 0x03000000 res = PyUnicode_Format(ofmt,args); #else res = PyString_Format(ofmt,args); #endif Py_DECREF(ofmt); } Py_DECREF(args); } } return res; } SWIGRUNTIME PyObject * SwigPyObject_oct(SwigPyObject *v) { return SwigPyObject_format("%o",v); } SWIGRUNTIME PyObject * SwigPyObject_hex(SwigPyObject *v) { return SwigPyObject_format("%x",v); } SWIGRUNTIME PyObject * #ifdef METH_NOARGS SwigPyObject_repr(SwigPyObject *v) #else SwigPyObject_repr(SwigPyObject *v, PyObject *args) #endif { const char *name = SWIG_TypePrettyName(v->ty); PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); if (v->next) { # ifdef METH_NOARGS PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); # else PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); # endif # if PY_VERSION_HEX >= 0x03000000 PyObject *joined = PyUnicode_Concat(repr, nrep); Py_DecRef(repr); Py_DecRef(nrep); repr = joined; # else PyString_ConcatAndDel(&repr,nrep); # endif } return repr; } SWIGRUNTIME int SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { char *str; #ifdef METH_NOARGS PyObject *repr = SwigPyObject_repr(v); #else PyObject *repr = SwigPyObject_repr(v, NULL); #endif if (repr) { str = SWIG_Python_str_AsChar(repr); fputs(str, fp); SWIG_Python_str_DelForPy3(str); Py_DECREF(repr); return 0; } else { return 1; } } SWIGRUNTIME PyObject * SwigPyObject_str(SwigPyObject *v) { char result[SWIG_BUFFER_SIZE]; return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ? SWIG_Python_str_FromChar(result) : 0; } SWIGRUNTIME int SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) { void *i = v->ptr; void *j = w->ptr; return (i < j) ? -1 : ((i > j) ? 1 : 0); } /* Added for Python 3.x, would it also be useful for Python 2.x? */ SWIGRUNTIME PyObject* SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) { PyObject* res; if( op != Py_EQ && op != Py_NE ) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); return res; } SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); #ifdef SWIGPYTHON_BUILTIN static swig_type_info *SwigPyObject_stype = 0; SWIGRUNTIME PyTypeObject* SwigPyObject_type(void) { SwigPyClientData *cd; assert(SwigPyObject_stype); cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; assert(cd); assert(cd->pytype); return cd->pytype; } #else SWIGRUNTIME PyTypeObject* SwigPyObject_type(void) { static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); return type; } #endif SWIGRUNTIMEINLINE int SwigPyObject_Check(PyObject *op) { #ifdef SWIGPYTHON_BUILTIN PyTypeObject *target_tp = SwigPyObject_type(); if (PyType_IsSubtype(op->ob_type, target_tp)) return 1; return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); #else return (Py_TYPE(op) == SwigPyObject_type()) || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); #endif } SWIGRUNTIME PyObject * SwigPyObject_New(void *ptr, swig_type_info *ty, int own); SWIGRUNTIME void SwigPyObject_dealloc(PyObject *v) { SwigPyObject *sobj = (SwigPyObject *) v; PyObject *next = sobj->next; if (sobj->own == SWIG_POINTER_OWN) { swig_type_info *ty = sobj->ty; SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; PyObject *destroy = data ? data->destroy : 0; if (destroy) { /* destroy is always a VARARGS method */ PyObject *res; if (data->delargs) { /* we need to create a temporary object to carry the destroy operation */ PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); res = SWIG_Python_CallFunctor(destroy, tmp); Py_DECREF(tmp); } else { PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); PyObject *mself = PyCFunction_GET_SELF(destroy); res = ((*meth)(mself, v)); } Py_XDECREF(res); } #if !defined(SWIG_PYTHON_SILENT_MEMLEAK) else { const char *name = SWIG_TypePrettyName(ty); printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); } #endif } Py_XDECREF(next); PyObject_DEL(v); } SWIGRUNTIME PyObject* SwigPyObject_append(PyObject* v, PyObject* next) { SwigPyObject *sobj = (SwigPyObject *) v; #ifndef METH_O PyObject *tmp = 0; if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; next = tmp; #endif if (!SwigPyObject_Check(next)) { return NULL; } sobj->next = next; Py_INCREF(next); return SWIG_Py_Void(); } SWIGRUNTIME PyObject* #ifdef METH_NOARGS SwigPyObject_next(PyObject* v) #else SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) #endif { SwigPyObject *sobj = (SwigPyObject *) v; if (sobj->next) { Py_INCREF(sobj->next); return sobj->next; } else { return SWIG_Py_Void(); } } SWIGINTERN PyObject* #ifdef METH_NOARGS SwigPyObject_disown(PyObject *v) #else SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) #endif { SwigPyObject *sobj = (SwigPyObject *)v; sobj->own = 0; return SWIG_Py_Void(); } SWIGINTERN PyObject* #ifdef METH_NOARGS SwigPyObject_acquire(PyObject *v) #else SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) #endif { SwigPyObject *sobj = (SwigPyObject *)v; sobj->own = SWIG_POINTER_OWN; return SWIG_Py_Void(); } SWIGINTERN PyObject* SwigPyObject_own(PyObject *v, PyObject *args) { PyObject *val = 0; #if (PY_VERSION_HEX < 0x02020000) if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) #elif (PY_VERSION_HEX < 0x02050000) if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) #else if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) #endif { return NULL; } else { SwigPyObject *sobj = (SwigPyObject *)v; PyObject *obj = PyBool_FromLong(sobj->own); if (val) { #ifdef METH_NOARGS if (PyObject_IsTrue(val)) { SwigPyObject_acquire(v); } else { SwigPyObject_disown(v); } #else if (PyObject_IsTrue(val)) { SwigPyObject_acquire(v,args); } else { SwigPyObject_disown(v,args); } #endif } return obj; } } #ifdef METH_O static PyMethodDef swigobject_methods[] = { {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"aquires ownership of the pointer"}, {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, {0, 0, 0, 0} }; #else static PyMethodDef swigobject_methods[] = { {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"aquires ownership of the pointer"}, {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, {0, 0, 0, 0} }; #endif #if PY_VERSION_HEX < 0x02020000 SWIGINTERN PyObject * SwigPyObject_getattr(SwigPyObject *sobj,char *name) { return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); } #endif SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void) { static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; static PyNumberMethods SwigPyObject_as_number = { (binaryfunc)0, /*nb_add*/ (binaryfunc)0, /*nb_subtract*/ (binaryfunc)0, /*nb_multiply*/ /* nb_divide removed in Python 3 */ #if PY_VERSION_HEX < 0x03000000 (binaryfunc)0, /*nb_divide*/ #endif (binaryfunc)0, /*nb_remainder*/ (binaryfunc)0, /*nb_divmod*/ (ternaryfunc)0,/*nb_power*/ (unaryfunc)0, /*nb_negative*/ (unaryfunc)0, /*nb_positive*/ (unaryfunc)0, /*nb_absolute*/ (inquiry)0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ #if PY_VERSION_HEX < 0x03000000 0, /*nb_coerce*/ #endif (unaryfunc)SwigPyObject_long, /*nb_int*/ #if PY_VERSION_HEX < 0x03000000 (unaryfunc)SwigPyObject_long, /*nb_long*/ #else 0, /*nb_reserved*/ #endif (unaryfunc)0, /*nb_float*/ #if PY_VERSION_HEX < 0x03000000 (unaryfunc)SwigPyObject_oct, /*nb_oct*/ (unaryfunc)SwigPyObject_hex, /*nb_hex*/ #endif #if PY_VERSION_HEX >= 0x03000000 /* 3.0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ #elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ #elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ #endif }; static PyTypeObject swigpyobject_type; static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX >= 0x03000000 PyVarObject_HEAD_INIT(NULL, 0) #else PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif (char *)"SwigPyObject", /* tp_name */ sizeof(SwigPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyObject_dealloc, /* tp_dealloc */ (printfunc)SwigPyObject_print, /* tp_print */ #if PY_VERSION_HEX < 0x02020000 (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ #else (getattrfunc)0, /* tp_getattr */ #endif (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX >= 0x03000000 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ #else (cmpfunc)SwigPyObject_compare, /* tp_compare */ #endif (reprfunc)SwigPyObject_repr, /* tp_repr */ &SwigPyObject_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)0, /* tp_hash */ (ternaryfunc)0, /* tp_call */ (reprfunc)SwigPyObject_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ swigobject_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ 0, /* tp_weaklistoffset */ #if PY_VERSION_HEX >= 0x02020000 0, /* tp_iter */ 0, /* tp_iternext */ swigobject_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ #endif #if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ #endif #if PY_VERSION_HEX >= 0x02060000 0, /* tp_version */ #endif #ifdef COUNT_ALLOCS 0,0,0,0 /* tp_alloc -> tp_next */ #endif }; swigpyobject_type = tmp; type_init = 1; #if PY_VERSION_HEX < 0x02020000 swigpyobject_type.ob_type = &PyType_Type; #else if (PyType_Ready(&swigpyobject_type) < 0) return NULL; #endif } return &swigpyobject_type; } SWIGRUNTIME PyObject * SwigPyObject_New(void *ptr, swig_type_info *ty, int own) { SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); if (sobj) { sobj->ptr = ptr; sobj->ty = ty; sobj->own = own; sobj->next = 0; sobj->implicitconv = 0; } return (PyObject *)sobj; } /* ----------------------------------------------------------------------------- * Implements a simple Swig Packed type, and use it instead of string * ----------------------------------------------------------------------------- */ typedef struct { PyObject_HEAD void *pack; swig_type_info *ty; size_t size; } SwigPyPacked; SWIGRUNTIME int SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { char result[SWIG_BUFFER_SIZE]; fputs("pack, v->size, 0, sizeof(result))) { fputs("at ", fp); fputs(result, fp); } fputs(v->ty->name,fp); fputs(">", fp); return 0; } SWIGRUNTIME PyObject * SwigPyPacked_repr(SwigPyPacked *v) { char result[SWIG_BUFFER_SIZE]; if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { return SWIG_Python_str_FromFormat("", result, v->ty->name); } else { return SWIG_Python_str_FromFormat("", v->ty->name); } } SWIGRUNTIME PyObject * SwigPyPacked_str(SwigPyPacked *v) { char result[SWIG_BUFFER_SIZE]; if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); } else { return SWIG_Python_str_FromChar(v->ty->name); } } SWIGRUNTIME int SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) { size_t i = v->size; size_t j = w->size; int s = (i < j) ? -1 : ((i > j) ? 1 : 0); return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); } SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); SWIGRUNTIME PyTypeObject* SwigPyPacked_type(void) { static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); return type; } SWIGRUNTIMEINLINE int SwigPyPacked_Check(PyObject *op) { return ((op)->ob_type == SwigPyPacked_TypeOnce()) || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); } SWIGRUNTIME void SwigPyPacked_dealloc(PyObject *v) { if (SwigPyPacked_Check(v)) { SwigPyPacked *sobj = (SwigPyPacked *) v; free(sobj->pack); } PyObject_DEL(v); } SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void) { static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; static PyTypeObject swigpypacked_type; static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX>=0x03000000 PyVarObject_HEAD_INIT(NULL, 0) #else PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif (char *)"SwigPyPacked", /* tp_name */ sizeof(SwigPyPacked), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ (printfunc)SwigPyPacked_print, /* tp_print */ (getattrfunc)0, /* tp_getattr */ (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX>=0x03000000 0, /* tp_reserved in 3.0.1 */ #else (cmpfunc)SwigPyPacked_compare, /* tp_compare */ #endif (reprfunc)SwigPyPacked_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)0, /* tp_hash */ (ternaryfunc)0, /* tp_call */ (reprfunc)SwigPyPacked_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ swigpacked_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ #if PY_VERSION_HEX >= 0x02020000 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ #endif #if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ #endif #if PY_VERSION_HEX >= 0x02060000 0, /* tp_version */ #endif #ifdef COUNT_ALLOCS 0,0,0,0 /* tp_alloc -> tp_next */ #endif }; swigpypacked_type = tmp; type_init = 1; #if PY_VERSION_HEX < 0x02020000 swigpypacked_type.ob_type = &PyType_Type; #else if (PyType_Ready(&swigpypacked_type) < 0) return NULL; #endif } return &swigpypacked_type; } SWIGRUNTIME PyObject * SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) { SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); if (sobj) { void *pack = malloc(size); if (pack) { memcpy(pack, ptr, size); sobj->pack = pack; sobj->ty = ty; sobj->size = size; } else { PyObject_DEL((PyObject *) sobj); sobj = 0; } } return (PyObject *) sobj; } SWIGRUNTIME swig_type_info * SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) { if (SwigPyPacked_Check(obj)) { SwigPyPacked *sobj = (SwigPyPacked *)obj; if (sobj->size != size) return 0; memcpy(ptr, sobj->pack, size); return sobj->ty; } else { return 0; } } /* ----------------------------------------------------------------------------- * pointers/data manipulation * ----------------------------------------------------------------------------- */ SWIGRUNTIMEINLINE PyObject * _SWIG_This(void) { return SWIG_Python_str_FromChar("this"); } static PyObject *swig_this = NULL; SWIGRUNTIME PyObject * SWIG_This(void) { if (swig_this == NULL) swig_this = _SWIG_This(); return swig_this; } /* #define SWIG_PYTHON_SLOW_GETSET_THIS */ /* TODO: I don't know how to implement the fast getset in Python 3 right now */ #if PY_VERSION_HEX>=0x03000000 #define SWIG_PYTHON_SLOW_GETSET_THIS #endif SWIGRUNTIME SwigPyObject * SWIG_Python_GetSwigThis(PyObject *pyobj) { PyObject *obj; if (SwigPyObject_Check(pyobj)) return (SwigPyObject *) pyobj; #ifdef SWIGPYTHON_BUILTIN (void)obj; # ifdef PyWeakref_CheckProxy if (PyWeakref_CheckProxy(pyobj)) { pyobj = PyWeakref_GET_OBJECT(pyobj); if (pyobj && SwigPyObject_Check(pyobj)) return (SwigPyObject*) pyobj; } # endif return NULL; #else obj = 0; #if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) if (PyInstance_Check(pyobj)) { obj = _PyInstance_Lookup(pyobj, SWIG_This()); } else { PyObject **dictptr = _PyObject_GetDictPtr(pyobj); if (dictptr != NULL) { PyObject *dict = *dictptr; obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; } else { #ifdef PyWeakref_CheckProxy if (PyWeakref_CheckProxy(pyobj)) { PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; } #endif obj = PyObject_GetAttr(pyobj,SWIG_This()); if (obj) { Py_DECREF(obj); } else { if (PyErr_Occurred()) PyErr_Clear(); return 0; } } } #else obj = PyObject_GetAttr(pyobj,SWIG_This()); if (obj) { Py_DECREF(obj); } else { if (PyErr_Occurred()) PyErr_Clear(); return 0; } #endif if (obj && !SwigPyObject_Check(obj)) { /* a PyObject is called 'this', try to get the 'real this' SwigPyObject from it */ return SWIG_Python_GetSwigThis(obj); } return (SwigPyObject *)obj; #endif } /* Acquire a pointer value */ SWIGRUNTIME int SWIG_Python_AcquirePtr(PyObject *obj, int own) { if (own == SWIG_POINTER_OWN) { SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); if (sobj) { int oldown = sobj->own; sobj->own = own; return oldown; } } return 0; } /* Convert a pointer value */ SWIGRUNTIME int SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { int res; SwigPyObject *sobj; if (!obj) return SWIG_ERROR; if (obj == Py_None) { if (ptr) *ptr = 0; return SWIG_OK; } res = SWIG_ERROR; sobj = SWIG_Python_GetSwigThis(obj); if (own) *own = 0; while (sobj) { void *vptr = sobj->ptr; if (ty) { swig_type_info *to = sobj->ty; if (to == ty) { /* no type cast needed */ if (ptr) *ptr = vptr; break; } else { swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); if (!tc) { sobj = (SwigPyObject *)sobj->next; } else { if (ptr) { int newmemory = 0; *ptr = SWIG_TypeCast(tc,vptr,&newmemory); if (newmemory == SWIG_CAST_NEW_MEMORY) { assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ if (own) *own = *own | SWIG_CAST_NEW_MEMORY; } } break; } } } else { if (ptr) *ptr = vptr; break; } } if (sobj) { if (own) *own = *own | sobj->own; if (flags & SWIG_POINTER_DISOWN) { sobj->own = 0; } res = SWIG_OK; } else { if (flags & SWIG_POINTER_IMPLICIT_CONV) { SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; sobj = SWIG_Python_GetSwigThis(obj); if (data && sobj && !sobj->implicitconv) { PyObject *klass = data->klass; if (klass) { PyObject *impconv; sobj->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ impconv = SWIG_Python_CallFunctor(klass, obj); sobj->implicitconv = 0; if (PyErr_Occurred()) { PyErr_Clear(); impconv = 0; } if (impconv) { SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); if (iobj) { void *vptr; res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); if (SWIG_IsOK(res)) { if (ptr) { *ptr = vptr; /* transfer the ownership to 'ptr' */ iobj->own = 0; res = SWIG_AddCast(res); res = SWIG_AddNewMask(res); } else { res = SWIG_AddCast(res); } } } Py_DECREF(impconv); } } } } } return res; } /* Convert a function ptr value */ SWIGRUNTIME int SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { if (!PyCFunction_Check(obj)) { return SWIG_ConvertPtr(obj, ptr, ty, 0); } else { void *vptr = 0; /* here we get the method pointer for callbacks */ const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; if (desc) desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; if (!desc) return SWIG_ERROR; if (ty) { swig_cast_info *tc = SWIG_TypeCheck(desc,ty); if (tc) { int newmemory = 0; *ptr = SWIG_TypeCast(tc,vptr,&newmemory); assert(!newmemory); /* newmemory handling not yet implemented */ } else { return SWIG_ERROR; } } else { *ptr = vptr; } return SWIG_OK; } } /* Convert a packed value value */ SWIGRUNTIME int SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); if (!to) return SWIG_ERROR; if (ty) { if (to != ty) { /* check type cast? */ swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); if (!tc) return SWIG_ERROR; } } return SWIG_OK; } /* ----------------------------------------------------------------------------- * Create a new pointer object * ----------------------------------------------------------------------------- */ /* Create a new instance object, without calling __init__, and set the 'this' attribute. */ SWIGRUNTIME PyObject* SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) { #if (PY_VERSION_HEX >= 0x02020000) PyObject *inst = 0; PyObject *newraw = data->newraw; if (newraw) { inst = PyObject_Call(newraw, data->newargs, NULL); if (inst) { #if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) PyObject **dictptr = _PyObject_GetDictPtr(inst); if (dictptr != NULL) { PyObject *dict = *dictptr; if (dict == NULL) { dict = PyDict_New(); *dictptr = dict; PyDict_SetItem(dict, SWIG_This(), swig_this); } } #else PyObject *key = SWIG_This(); PyObject_SetAttr(inst, key, swig_this); #endif } } else { #if PY_VERSION_HEX >= 0x03000000 inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); if (inst) { PyObject_SetAttr(inst, SWIG_This(), swig_this); Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; } #else PyObject *dict = PyDict_New(); if (dict) { PyDict_SetItem(dict, SWIG_This(), swig_this); inst = PyInstance_NewRaw(data->newargs, dict); Py_DECREF(dict); } #endif } return inst; #else #if (PY_VERSION_HEX >= 0x02010000) PyObject *inst = 0; PyObject *dict = PyDict_New(); if (dict) { PyDict_SetItem(dict, SWIG_This(), swig_this); inst = PyInstance_NewRaw(data->newargs, dict); Py_DECREF(dict); } return (PyObject *) inst; #else PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); if (inst == NULL) { return NULL; } inst->in_class = (PyClassObject *)data->newargs; Py_INCREF(inst->in_class); inst->in_dict = PyDict_New(); if (inst->in_dict == NULL) { Py_DECREF(inst); return NULL; } #ifdef Py_TPFLAGS_HAVE_WEAKREFS inst->in_weakreflist = NULL; #endif #ifdef Py_TPFLAGS_GC PyObject_GC_Init(inst); #endif PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); return (PyObject *) inst; #endif #endif } SWIGRUNTIME void SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) { PyObject *dict; #if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) PyObject **dictptr = _PyObject_GetDictPtr(inst); if (dictptr != NULL) { dict = *dictptr; if (dict == NULL) { dict = PyDict_New(); *dictptr = dict; } PyDict_SetItem(dict, SWIG_This(), swig_this); return; } #endif dict = PyObject_GetAttrString(inst, (char*)"__dict__"); PyDict_SetItem(dict, SWIG_This(), swig_this); Py_DECREF(dict); } SWIGINTERN PyObject * SWIG_Python_InitShadowInstance(PyObject *args) { PyObject *obj[2]; if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { return NULL; } else { SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); if (sthis) { SwigPyObject_append((PyObject*) sthis, obj[1]); } else { SWIG_Python_SetSwigThis(obj[0], obj[1]); } return SWIG_Py_Void(); } } /* Create a new pointer object */ SWIGRUNTIME PyObject * SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { SwigPyClientData *clientdata; PyObject * robj; int own; if (!ptr) return SWIG_Py_Void(); clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; if (clientdata && clientdata->pytype) { SwigPyObject *newobj; if (flags & SWIG_BUILTIN_TP_INIT) { newobj = (SwigPyObject*) self; if (newobj->ptr) { PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); while (newobj->next) newobj = (SwigPyObject *) newobj->next; newobj->next = next_self; newobj = (SwigPyObject *)next_self; } } else { newobj = PyObject_New(SwigPyObject, clientdata->pytype); } if (newobj) { newobj->ptr = ptr; newobj->ty = type; newobj->own = own; newobj->next = 0; #ifdef SWIGPYTHON_BUILTIN newobj->dict = 0; #endif return (PyObject*) newobj; } return SWIG_Py_Void(); } assert(!(flags & SWIG_BUILTIN_TP_INIT)); robj = SwigPyObject_New(ptr, type, own); if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); Py_DECREF(robj); robj = inst; } return robj; } /* Create a new packed object */ SWIGRUNTIMEINLINE PyObject * SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); } /* -----------------------------------------------------------------------------* * Get type list * -----------------------------------------------------------------------------*/ #ifdef SWIG_LINK_RUNTIME void *SWIG_ReturnGlobalTypeList(void *); #endif SWIGRUNTIME swig_module_info * SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { static void *type_pointer = (void *)0; /* first check if module already created */ if (!type_pointer) { #ifdef SWIG_LINK_RUNTIME type_pointer = SWIG_ReturnGlobalTypeList((void *)0); #else # ifdef SWIGPY_USE_CAPSULE type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); # else type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); # endif if (PyErr_Occurred()) { PyErr_Clear(); type_pointer = (void *)0; } #endif } return (swig_module_info *) type_pointer; } #if PY_MAJOR_VERSION < 2 /* PyModule_AddObject function was introduced in Python 2.0. The following function is copied out of Python/modsupport.c in python version 2.3.4 */ SWIGINTERN int PyModule_AddObject(PyObject *m, char *name, PyObject *o) { PyObject *dict; if (!PyModule_Check(m)) { PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg"); return SWIG_ERROR; } if (!o) { PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value"); return SWIG_ERROR; } dict = PyModule_GetDict(m); if (dict == NULL) { /* Internal error -- modules must have a dict! */ PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", PyModule_GetName(m)); return SWIG_ERROR; } if (PyDict_SetItemString(dict, name, o)) return SWIG_ERROR; Py_DECREF(o); return SWIG_OK; } #endif SWIGRUNTIME void #ifdef SWIGPY_USE_CAPSULE SWIG_Python_DestroyModule(PyObject *obj) #else SWIG_Python_DestroyModule(void *vptr) #endif { #ifdef SWIGPY_USE_CAPSULE swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); #else swig_module_info *swig_module = (swig_module_info *) vptr; #endif swig_type_info **types = swig_module->types; size_t i; for (i =0; i < swig_module->size; ++i) { swig_type_info *ty = types[i]; if (ty->owndata) { SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; if (data) SwigPyClientData_Del(data); } } Py_DECREF(SWIG_This()); swig_this = NULL; } SWIGRUNTIME void SWIG_Python_SetModule(swig_module_info *swig_module) { #if PY_VERSION_HEX >= 0x03000000 /* Add a dummy module object into sys.modules */ PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); #else static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); #endif #ifdef SWIGPY_USE_CAPSULE PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); if (pointer && module) { PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); } else { Py_XDECREF(pointer); } #else PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); if (pointer && module) { PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); } else { Py_XDECREF(pointer); } #endif } /* The python cached type query */ SWIGRUNTIME PyObject * SWIG_Python_TypeCache(void) { static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); return cache; } SWIGRUNTIME swig_type_info * SWIG_Python_TypeQuery(const char *type) { PyObject *cache = SWIG_Python_TypeCache(); PyObject *key = SWIG_Python_str_FromChar(type); PyObject *obj = PyDict_GetItem(cache, key); swig_type_info *descriptor; if (obj) { #ifdef SWIGPY_USE_CAPSULE descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); #else descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); #endif } else { swig_module_info *swig_module = SWIG_GetModule(0); descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); if (descriptor) { #ifdef SWIGPY_USE_CAPSULE obj = PyCapsule_New((void*) descriptor, NULL, NULL); #else obj = PyCObject_FromVoidPtr(descriptor, NULL); #endif PyDict_SetItem(cache, key, obj); Py_DECREF(obj); } } Py_DECREF(key); return descriptor; } /* For backward compatibility only */ #define SWIG_POINTER_EXCEPTION 0 #define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) #define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) SWIGRUNTIME int SWIG_Python_AddErrMesg(const char* mesg, int infront) { if (PyErr_Occurred()) { PyObject *type = 0; PyObject *value = 0; PyObject *traceback = 0; PyErr_Fetch(&type, &value, &traceback); if (value) { char *tmp; PyObject *old_str = PyObject_Str(value); Py_XINCREF(type); PyErr_Clear(); if (infront) { PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); } else { PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); } SWIG_Python_str_DelForPy3(tmp); Py_DECREF(old_str); } return 1; } else { return 0; } } SWIGRUNTIME int SWIG_Python_ArgFail(int argnum) { if (PyErr_Occurred()) { /* add information about failing argument */ char mesg[256]; PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); return SWIG_Python_AddErrMesg(mesg, 1); } else { return 0; } } SWIGRUNTIMEINLINE const char * SwigPyObject_GetDesc(PyObject *self) { SwigPyObject *v = (SwigPyObject *)self; swig_type_info *ty = v ? v->ty : 0; return ty ? ty->str : ""; } SWIGRUNTIME void SWIG_Python_TypeError(const char *type, PyObject *obj) { if (type) { #if defined(SWIG_COBJECT_TYPES) if (obj && SwigPyObject_Check(obj)) { const char *otype = (const char *) SwigPyObject_GetDesc(obj); if (otype) { PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", type, otype); return; } } else #endif { const char *otype = (obj ? obj->ob_type->tp_name : 0); if (otype) { PyObject *str = PyObject_Str(obj); const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; if (cstr) { PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", type, otype, cstr); SWIG_Python_str_DelForPy3(cstr); } else { PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", type, otype); } Py_XDECREF(str); return; } } PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); } else { PyErr_Format(PyExc_TypeError, "unexpected type is received"); } } /* Convert a pointer value, signal an exception on a type mismatch */ SWIGRUNTIME void * SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { void *result; if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { PyErr_Clear(); #if SWIG_POINTER_EXCEPTION if (flags) { SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); SWIG_Python_ArgFail(argnum); } #endif } return result; } #ifdef SWIGPYTHON_BUILTIN SWIGRUNTIME int SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { PyTypeObject *tp = obj->ob_type; PyObject *descr; PyObject *encoded_name; descrsetfunc f; int res; # ifdef Py_USING_UNICODE if (PyString_Check(name)) { name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); if (!name) return -1; } else if (!PyUnicode_Check(name)) # else if (!PyString_Check(name)) # endif { PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); return -1; } else { Py_INCREF(name); } if (!tp->tp_dict) { if (PyType_Ready(tp) < 0) goto done; } res = -1; descr = _PyType_Lookup(tp, name); f = NULL; if (descr != NULL) f = descr->ob_type->tp_descr_set; if (!f) { if (PyString_Check(name)) { encoded_name = name; Py_INCREF(name); } else { encoded_name = PyUnicode_AsUTF8String(name); } PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); Py_DECREF(encoded_name); } else { res = f(descr, obj, value); } done: Py_DECREF(name); return res; } #endif #ifdef __cplusplus } #endif dff-1.3.0+dfsg.1/dff/api/include/rc.hpp000066400000000000000000000044451217176075400174210ustar00rootroot00000000000000#ifndef __RC_HPP__ #define __RC_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include "export.hpp" #include "threading.hpp" struct RCObjBase { public: EXPORT int32_t ref_count() const { return (refCount); } EXPORT int32_t addref() const { return (++refCount); } EXPORT int32_t delref() const { if (refCount == 0 || --refCount == 0) { delete this; return (0); } return (refCount); } protected: EXPORT RCObjBase(); EXPORT RCObjBase(const RCObjBase& ); EXPORT virtual ~RCObjBase() = 0; private: RCObjBase& operator=(const RCObjBase& ); friend struct RCObj; mutable int32_t refCount; }; struct RCObj : virtual RCObjBase { protected: RCObj() { } }; template inline T* addref(T* r) { return (r && r->addref()) ? r : 0; } template inline T* delref(T* r) { return (r && r->delref()) ? r : 0; } template struct RCPtr { typedef T* pointer_type; typedef T& refernce_type; typedef T value_type; RCPtr() : pointee(0) { }; RCPtr(T* realPtr) :pointee(realPtr) { dff::ScopedMutex locker(__mutex); addref(pointee); }; RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) { dff::ScopedMutex locker(__mutex); addref(pointee); }; ~RCPtr() { dff::ScopedMutex locker(__mutex); delref(pointee); }; RCPtr& operator=(const RCPtr& rhs) { dff::ScopedMutex locker(__mutex); if (pointee != rhs.pointee) { delref(pointee); pointee = rhs.pointee; addref(pointee); } return (*this); }; T* operator->() { return (pointee); } T& operator*() { return (*pointee); } const T* operator->() const { return (pointee); } const T& operator*() const { return (*pointee); } operator T*() { return (pointee); } operator T&() { return (*pointee); } operator const T*() const { return (pointee); } operator const T&() const { return (*pointee); } T* get() { return (pointee); } T* get() const { return (pointee); } private: T* pointee; dff::Mutex __mutex; }; #endif dff-1.3.0+dfsg.1/dff/api/include/rootnode.hpp000066400000000000000000000023051217176075400206370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __ROOTNODE_HPP__ #define __ROOTNODE_HPP__ #include #include #include "eventhandler.hpp" #include "threading.hpp" #include "node.hpp" class VFSRootNode : public Node { public: EXPORT VFSRootNode(std::string name); EXPORT ~VFSRootNode(); }; class ModulesRootNode: public Node, public EventHandler { private: mutex_def(__mutex); std::map __modulesNameRootNode; public: EXPORT ModulesRootNode(EventHandler* vfs, Node* root); EXPORT ~ModulesRootNode(); EXPORT std::string icon(); EXPORT void Event(event* e); }; #endif dff-1.3.0+dfsg.1/dff/api/include/search.hpp000066400000000000000000000112351217176075400202550ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #ifndef __SEARCH_HPP__ #define __SEARCH_HPP__ #ifndef WIN32 #include #else #if _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #endif #include #include #include #include "export.hpp" #include "fastsearch.hpp" #ifdef HAVE_TRE #include #ifdef WIN32 #undef HAVE_ALLOCA #undef HAVE_ALLOCA_H #define tre_free tre_regfree; #else #ifdef __cplusplus extern "C" { #endif extern void tre_free(regex_t *preg); #ifdef __cplusplus } #endif #endif #endif class FastSearch { public: EXPORT FastSearch(); EXPORT virtual ~FastSearch(); EXPORT virtual int32_t find(unsigned char* haystack, uint32_t hslen, unsigned char* needle, uint32_t ndlen, unsigned char wildcard='\0'); EXPORT virtual int32_t rfind(unsigned char* haystack, uint32_t hslen, unsigned char* needle, uint32_t ndlen, unsigned char wildcard='\0'); EXPORT virtual int32_t count(unsigned char* haystack, uint32_t hslen, unsigned char* needle, uint32_t ndlen, unsigned char wildcard='\0', int32_t maxcount=-1); }; typedef int32_t (*sfunc)(const unsigned char*, int32_t, const unsigned char*, int32_t, int32_t, int); class Search { public: enum PatternSyntax { Fixed = 0, Wildcard = 1, Regexp = 2, Fuzzy = 3 }; enum CaseSensitivity { CaseInsensitive = 0, CaseSensitive = 1 }; EXPORT Search(); EXPORT Search(std::string pattern, CaseSensitivity cs = CaseSensitive, PatternSyntax syntax = Fixed); EXPORT ~Search(); EXPORT uint32_t needleLength(); EXPORT void setPattern(std::string pattern); EXPORT std::string pattern(); EXPORT void setPatternSyntax(PatternSyntax syntax); EXPORT PatternSyntax patternSyntax(); EXPORT void setCaseSensitivity(CaseSensitivity cs); EXPORT CaseSensitivity caseSensitivity(); //void setFuzzyWeight(); EXPORT int32_t find(char* haystack, uint32_t hslen) throw (std::string); EXPORT int32_t find(std::string haystack) throw (std::string); EXPORT int32_t rfind(char* haystack, uint32_t hslen) throw (std::string); EXPORT int32_t rfind(std::string haystack) throw (std::string); EXPORT int32_t count(char* haystack, uint32_t hslen, int32_t maxcount=-1) throw (std::string); EXPORT int32_t count(std::string haystack, int32_t maxcount=-1) throw (std::string); EXPORT void compile() throw (std::string); // std::vector indexes(char* haystack, uint32_t hslen) throw (std::string); // std::vector indexes(std::string haystack) throw (std::string); private: #ifdef HAVE_TRE regex_t __preg; regaparams_t __aparams; #endif std::vector __wctxs; std::string __pattern; CaseSensitivity __cs; PatternSyntax __syntax; bool __compiled; bool __needtrefree; uint32_t __nlen; typedef int32_t (Search::*findptr)(char* haystack, uint32_t hslen); typedef int32_t (Search::*rfindptr)(char* haystack, uint32_t hslen); typedef int32_t (Search::*countptr)(char* haystack, uint32_t hslen, int32_t maxcount); findptr __find; rfindptr __rfind; countptr __count; //compile methods void __wcompile() throw (std::string); void __recompile() throw (std::string); void __fzcompile() throw (std::string); //find methods implementation EXPORT int32_t __ffind(char* haystack, uint32_t hslen); EXPORT int32_t __wfind(char* haystack, uint32_t hslen); EXPORT int32_t __wfindint(unsigned char* haystack, uint32_t hslen, sfunc s, size_t vpos, uint32_t window); EXPORT int32_t __refind(char* haystack, uint32_t hslen); EXPORT int32_t __afind(char* haystack, uint32_t hslen); //rfind methods implementation EXPORT int32_t __frfind(char* haystack, uint32_t hslen); EXPORT int32_t __wrfind(char* haystack, uint32_t hslen); //count methods implementation EXPORT int32_t __fcount(char* haystack, uint32_t hslen, int32_t maxcount); EXPORT int32_t __wcount(char* haystack, uint32_t hslen, int32_t maxcount); EXPORT int32_t __recount(char* haystack, uint32_t hslen, int32_t maxcount); EXPORT int32_t __acount(char* haystack, uint32_t hslen, int32_t maxcount); }; #endif dff-1.3.0+dfsg.1/dff/api/include/tags.hpp000066400000000000000000000047331217176075400177530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __TAGS_HPP__ #define __TAGS_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include "export.hpp" #include "rc.hpp" #define Tag_p RCPtr< Tag > class Node; class Color { public: EXPORT Color(); EXPORT Color(uint8_t r, uint8_t g, uint8_t b); uint8_t r; uint8_t g; uint8_t b; }; class Tag : public RCObj { private: uint32_t __id; std::string __name; Color __color; public: EXPORT ~Tag(); EXPORT Tag(); EXPORT Tag(uint32_t id, std::string, Color color); EXPORT Tag(uint32_t id, std::string, uint8_t r, uint8_t g, uint8_t b); EXPORT uint32_t id(void); EXPORT std::string name(void); EXPORT Color color(void); EXPORT void setColor(Color color); EXPORT void setColor(uint8_t r, uint8_t g, uint8_t b); EXPORT void setName(std::string name); }; class TagsManager { private: TagsManager(const TagsManager&); EXPORT TagsManager(); TagsManager* operator=(TagsManager&); void __removeNodesTag(uint32_t id); void __removeNodesTag(uint32_t id, class Node* node); std::vector __tagsList; uint32_t __defaults; public: EXPORT static TagsManager& get(void); EXPORT Tag_p tag(uint32_t id); EXPORT Tag_p tag(std::string name); EXPORT std::vector* tags(void); EXPORT uint32_t add(std::string name); EXPORT uint32_t add(std::string name, Color color); EXPORT uint32_t add(std::string name, uint8_t r, uint8_t g, uint8_t b); EXPORT bool remove(uint32_t id); EXPORT bool remove(std::string name); }; #endif dff-1.3.0+dfsg.1/dff/api/include/threading.hpp000066400000000000000000000070031217176075400207530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __THREADING_HPP__ #define __THREADING_HPP__ #include #include #include #include "export.hpp" #ifdef WIN32 #define mutex_lock EnterCriticalSection #define mutex_unlock LeaveCriticalSection #define mutex_def(var) CRITICAL_SECTION var #define mutex_init(var) InitializeCriticalSection(var) #define mutex_destroy(var) DeleteCriticalSection(var) #else #include #define mutex_lock pthread_mutex_lock #define mutex_unlock pthread_mutex_unlock #define mutex_def(var) pthread_mutex_t var #define mutex_init(var) pthread_mutex_init(var, NULL) #define mutex_destroy(var) pthread_mutex_destroy(var) #endif namespace dff { class Mutex { public: EXPORT Mutex(); EXPORT ~Mutex(); EXPORT Mutex(const Mutex& other); EXPORT void lock(); EXPORT void release(); private: mutex_def(__mutex); }; class ScopedMutex { public: EXPORT ScopedMutex(Mutex& mutex); EXPORT ~ScopedMutex(); private: Mutex& __mutex; }; template< typename key, typename value > class map { public: EXPORT map() { } EXPORT ~map() { ScopedMutex locker(__mutex); internals.clear(); } EXPORT value& operator[](const key _k) { ScopedMutex locker(__mutex); return internals[_k]; } EXPORT bool exist(key _k) { ScopedMutex locker(__mutex); return internals.find(_k) != internals.end(); } EXPORT bool empty() const { ScopedMutex locker(__mutex); return internals.empty(); } EXPORT value get_value(key _k) { ScopedMutex locker(__mutex); typename std::map::iterator iv; iv = internals.find(_k); if (iv != internals.end()) { return(value(iv->second)); } throw std::string("Can't find value"); } EXPORT const std::map< key, value > & getInternals() { return internals; } EXPORT void erase(key _k) { ScopedMutex locker(__mutex); internals.erase(_k); return ; } private: std::map< key, value > internals; mutable Mutex __mutex; }; template< typename value > class vector { public: EXPORT vector() { } EXPORT ~vector() { ScopedMutex locker(__mutex); internals.clear(); } EXPORT value& operator[](unsigned int n) throw (std::out_of_range) { ScopedMutex locker(__mutex); return internals[n]; } EXPORT const value at(unsigned int idx) const { ScopedMutex locker(__mutex); return internals.at(idx); } EXPORT bool empty() const { ScopedMutex locker(__mutex); return internals.empty(); } EXPORT unsigned int size() const { return internals.size(); } EXPORT void push_back(const value& val) { ScopedMutex locker(__mutex); internals.push_back(val); } private: mutable Mutex __mutex; std::vector< value > internals; }; }; #endif dff-1.3.0+dfsg.1/dff/api/include/typesconv.hpp000066400000000000000000000024321217176075400210410ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __TYPESCONV_HPP__ union s_ull { struct { unsigned long Low; unsigned long High; }; struct { unsigned long Low; unsigned long High; } u; unsigned long long ull; }; #define bytes_swap64(x)\ ((((x) & 0xff00000000000000ull) >> 56)\ | (((x) & 0x00ff000000000000ull) >> 40)\ | (((x) & 0x0000ff0000000000ull) >> 24)\ | (((x) & 0x000000ff00000000ull) >> 8)\ | (((x) & 0x00000000ff000000ull) << 8)\ | (((x) & 0x0000000000ff0000ull) << 24)\ | (((x) & 0x000000000000ff00ull) << 40)\ | (((x) & 0x00000000000000ffull) << 56)) #define bytes_swap32(x)\ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) |\ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) #endif dff-1.3.0+dfsg.1/dff/api/include/udevice.hpp000066400000000000000000000023301217176075400204300ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __UDEV_HPP__ #define __UDEV_HPP__ #include "device.hpp" #include class UDevice : public Device { private: wchar_t* __blockDevice; wchar_t* __serialNumber; wchar_t* __model; uint64_t __size; public: UDevice(); UDevice(const char* blockDevice, const char* serialNumber, const char* model, uint64_t size); ~UDevice(); wchar_t* blockDevice(void); wchar_t* serialNumber(void); wchar_t* model(void); uint64_t size(void); }; class UDevices : public DeviceList { public: UDevices(); ~UDevices(); std::vector deviceList; }; #endif dff-1.3.0+dfsg.1/dff/api/include/variant.hpp000066400000000000000000000217121217176075400204550ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __VARIANT_HPP__ #define __VARIANT_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #pragma warning(disable: 4290) #endif #include #include #include #include #include #include #include #include "path.hpp" #include "vtime.hpp" #include "rc.hpp" class VLink; class Node; class Path; class Argument; #define Variant_p RCPtr< Variant > typedef std::map > Attributes; class typeId { private: std::map mapping; std::map rmapping; EXPORT typeId(); EXPORT ~typeId(); typeId& operator=(typeId&); typeId(const typeId&); public: EXPORT static typeId* Get(); enum Type { Invalid = 0, // classic types String, CArray, Char, // Int8, // UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Bool, Map, List, // dff types VTime, Node, Path, Argument, // user types VoidPtr, VLink }; EXPORT uint8_t getType(std::string type); EXPORT std::string typeToName(uint8_t t); }; class Variant : public RCObj { public: EXPORT Variant(); EXPORT Variant(class Variant* ) throw (std::string); EXPORT ~Variant(); EXPORT Variant(std::string str); EXPORT Variant(char *carray) throw (std::string); EXPORT Variant(char c); EXPORT Variant(uint16_t us); EXPORT Variant(int16_t s); EXPORT Variant(uint32_t ui); EXPORT Variant(int32_t i); EXPORT Variant(int64_t ull); EXPORT Variant(uint64_t ll); EXPORT Variant(bool b); EXPORT Variant(vtime *vt) throw (std::string); EXPORT Variant(Node* node) throw (std::string); EXPORT Variant(Path* path) throw (std::string); EXPORT Variant(Argument* argument) throw (std::string); EXPORT Variant(std::list< Variant_p > l); EXPORT Variant(std::map m); EXPORT Variant(void *user) throw (std::string); EXPORT Variant(VLink* node) throw (std::string); EXPORT bool convert(uint8_t itype, void *res) { bool ret; try { ret = false; if (itype == typeId::Int16) { int16_t *s = static_cast(res); *s = this->toInt16(); ret = true; } else if (itype == typeId::UInt16) { uint16_t *us = static_cast(res); *us = this->toUInt16(); ret = true; } else if (itype == typeId::Int32) { int32_t *i = static_cast(res); *i = this->toInt32(); ret = true; } else if (itype == typeId::UInt32) { uint32_t *ui = static_cast(res); *ui = this->toUInt32(); ret = true; } else if (itype == typeId::Int64) { int64_t *ll = static_cast(res); *ll = this->toInt64(); ret = true; } else if (itype == typeId::UInt64) { uint64_t *ull = static_cast(res); *ull = this->toUInt64(); ret = true; } else if (itype == typeId::Char) { char *c = static_cast(res); *c = this->toChar(); ret = true; } else if (itype == typeId::CArray) { char **cstr = static_cast(res); *cstr = this->toCArray(); ret = true; } else if (itype == typeId::String) { std::string *str = static_cast(res); *str = this->toString(); ret = true; } else if ((itype == typeId::Node) && (this->_type == typeId::Node)) { class Node **n = static_cast(res); *n = (class Node*)this->__data.ptr; ret = true; } else if ((itype == typeId::VLink) && (this->_type == typeId::VLink)) { class VLink **n = static_cast(res); *n = (class VLink*)this->__data.ptr; ret = true; } else if ((itype == typeId::Path) && (this->_type == typeId::Path)) { class Path **p = static_cast(res); *p = (Path*)this->__data.ptr; ret = true; } else if ((itype == typeId::Bool) && (this->_type == typeId::Bool)) { bool *b = static_cast(res); *b = this->__data.b; ret = true; } else if ((itype == typeId::VTime) && (this->_type == typeId::VTime)) { vtime **vt = static_cast(res); *vt = (vtime*)this->__data.ptr; ret = true; } else if ((itype == typeId::List) && (this->_type == typeId::List)) { std::list< Variant_p > *l = static_cast*>(res); *l = *((std::list*)this->__data.ptr); ret = true; } else if ((itype == typeId::Map) && (this->_type == typeId::Map)) { std::map *m = static_cast*>(res); *m = *((std::map*)this->__data.ptr); ret = true; } else if ((itype == typeId::VoidPtr) && (this->_type == typeId::VoidPtr)) { (*(void**)res) = this->__data.ptr; ret = true; } else ret = false; return ret; } catch (std::string e) { return false; } } template EXPORT bool operator==(T val) { std::string type; uint8_t itype; T mine; itype = typeId::Get()->getType((char*)typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &mine)) return (mine == val); else return false; } else return false; } template EXPORT bool operator!=(T val) { std::string type; uint8_t itype; T mine; itype = typeId::Get()->getType((char*)typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &mine)) return (mine != val); else return true; } else return true; } template EXPORT bool operator>(T val) { std::string type; uint8_t itype; T mine; itype = typeId::Get()->getType((char*)typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &mine)) return (mine > val); else return true; } else return true; } template EXPORT bool operator>=(T val) { std::string type; uint8_t itype; T mine; itype = typeId::Get()->getType((char*)typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &mine)) return (mine >= val); else return true; } else return true; } template EXPORT bool operator<(T val) { std::string type; uint8_t itype; T mine; itype = typeId::Get()->getType((char*)typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &mine)) return (mine < val); else return false; } else return false; } template EXPORT bool operator<=(T val) { std::string type; uint8_t itype; T mine; itype = typeId::Get()->getType((char*)typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &mine)) return (mine <= val); else return false; } else return false; } EXPORT bool operator==(Variant* v); EXPORT bool operator!=(Variant* v); EXPORT bool operator>(Variant* v); EXPORT bool operator>=(Variant* v); EXPORT bool operator<(Variant* v); EXPORT bool operator<=(Variant* v); template T value(void) { std::string type; uint8_t itype; T t; itype = typeId::Get()->getType(typeid(static_cast(0)).name()); if (itype != 0) { if (this->convert(itype, &t)) return t; else return T(); } else { return T(); } } EXPORT std::string toString() throw (std::string); EXPORT std::string toHexString() throw (std::string); EXPORT std::string toOctString() throw (std::string); EXPORT uint16_t toUInt16() throw (std::string); EXPORT int16_t toInt16() throw (std::string); EXPORT uint32_t toUInt32() throw (std::string); EXPORT int32_t toInt32() throw (std::string); EXPORT uint64_t toUInt64() throw (std::string); EXPORT int64_t toInt64() throw (std::string); EXPORT char* toCArray() throw (std::string); EXPORT char toChar() throw (std::string); EXPORT bool toBool() throw (std::string); EXPORT uint8_t type(); EXPORT std::string typeName(); private: uint8_t _type; union Data { bool b; char c; // int8_t c; // uint8_t uc; int16_t s; uint16_t us; int32_t i; uint32_t ui; int64_t ll; uint64_t ull; std::string *str; void *ptr; } __data; }; #endif dff-1.3.0+dfsg.1/dff/api/include/vfile.hpp000066400000000000000000000073351217176075400201230ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __VFILE_HH__ #define __VFILE_HH__ #include #include #include #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "threading.hpp" #include "fso.hpp" #include "node.hpp" #include "export.hpp" #include "search.hpp" #include "eventhandler.hpp" #define BUFFSIZE 1024*1024*10 typedef struct _pdata { void *buff; uint64_t len; } pdata; class VFile: public EventHandler { private: FastSearch *__fs; class fso* __fsobj; int32_t __fd; class Node* __node; bool __recordUnread; bool __stop; public: EXPORT VFile(int32_t fd, class fso *fsobj, class Node *node); EXPORT ~VFile(); EXPORT class Node* node(); EXPORT pdata* read(); EXPORT pdata* read(uint32_t size); EXPORT int32_t read(void *buff, uint32_t size); EXPORT uint64_t seek(uint64_t offset, char *whence); EXPORT uint64_t seek(uint64_t offset, int32_t whence); EXPORT uint64_t seek(uint64_t offset); EXPORT uint64_t seek(int32_t offset, int32_t whence); EXPORT int32_t write(std::string buff); EXPORT int32_t write(char *buff, uint32_t size); EXPORT int32_t dfileno(); EXPORT uint64_t tell(); EXPORT int32_t close(); EXPORT virtual void Event(event* e) { __stop = true; (void)e;} EXPORT std::string readline(uint32_t size=0) throw (std::string); EXPORT int64_t find(unsigned char* needle, uint32_t nlen, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int64_t rfind(unsigned char* needle, uint32_t nlen, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int32_t count(unsigned char* needle, uint32_t nlen, unsigned char wildcard='\0', int32_t maxcount=INT32_MAX, uint64_t start=0, uint64_t end=0) throw (std::string); EXPORT std::vector* indexes(unsigned char* needle, uint32_t nlen, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT std::vector* search(char* needle, uint32_t nlen, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int64_t find(std::string needle, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int64_t rfind(std::string needle, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int32_t count(std::string needle, unsigned char wildcard='\0', int32_t maxcount=INT32_MAX, uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT std::vector* indexes(std::string needle, unsigned char wildcard='\0', uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int64_t find(Search* sctx, uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int64_t rfind(Search* sctx, uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT int32_t count(Search* sctx, int32_t=INT32_MAX, uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); EXPORT std::vector* indexes(Search* sctx, uint64_t start=0, uint64_t end=UINT64_MAX) throw (std::string); }; #endif dff-1.3.0+dfsg.1/dff/api/include/vfs.hpp000066400000000000000000000042571217176075400176140ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ // \brief This class implements the virtual file system of the framework. // The Virtual File System (VFS) is a central point of the framework. // It permits to register nodes and browse them. #ifndef __VFS_HPP__ #define __VFS_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include #include "eventhandler.hpp" #include "export.hpp" #include "exceptions.hpp" class Node; class fso; class vfsError; class VfsNode; class VFS: public EventHandler { private: EXPORT VFS(); EXPORT ~VFS(); VFS& operator=(VFS&); VFS(const VFS&); std::vector __fsobjs; std::vector __orphanednodes; public: class Node* cwd; Node* root; std::set Tree; EXPORT static VFS& Get(); EXPORT uint16_t registerFsobj(fso* fsobj) throw (vfsError); EXPORT uint64_t registerOrphanedNode(Node* n) throw (vfsError); EXPORT virtual void Event(event *e); EXPORT std::set* GetTree(void); EXPORT void cd(Node *); EXPORT Node* GetCWD(void); EXPORT Node* GetNode(std::string path); EXPORT Node* GetNode(std::string path, Node* where); EXPORT void AddNode(Node *parent, Node* head); EXPORT std::vector fsobjs(); EXPORT uint64_t totalNodes(); EXPORT Node* getNodeById(uint64_t id); }; #endif dff-1.3.0+dfsg.1/dff/api/include/vlink.hpp000066400000000000000000000040411217176075400201300ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __VLINK_HPP__ #define __VLINK_HPP__ #include #include #include #include #include #include #include "node.hpp" class VLink : public Node { private : Node* __linkedNode; public : EXPORT uint32_t id(); EXPORT void fileMapping(FileMapping *); EXPORT uint64_t size(); EXPORT std::string linkPath(); EXPORT std::string linkName(); EXPORT std::string linkAbsolute(); EXPORT bool isFile(); EXPORT bool isDir(); EXPORT bool isLink(); EXPORT bool isVDir(); EXPORT bool isDeleted(); EXPORT class fso* fsobj(); EXPORT class VFile* open(); EXPORT VLink(Node *linkedNode, Node* parent, std::string newname = ""); EXPORT ~VLink(); EXPORT Node* linkParent(); EXPORT std::vector linkChildren(); EXPORT bool linkHasChildren(); EXPORT uint32_t linkChildCount(); EXPORT Node* linkNode(); EXPORT Attributes dataType(void); EXPORT Attributes attributes(void); EXPORT std::string icon(void); EXPORT std::list compatibleModules(void); EXPORT bool isCompatibleModule(std::string); EXPORT bool setTag(std::string name); EXPORT bool setTag(uint32_t id); EXPORT bool removeTag(std::string name); EXPORT bool removeTag(uint32_t id); EXPORT bool isTagged(std::string name); EXPORT bool isTagged(uint32_t id); EXPORT std::vector tags(); EXPORT std::vector tagsId(); }; #endif dff-1.3.0+dfsg.1/dff/api/include/vtime.hpp000066400000000000000000000040711217176075400201340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __VTIME_HPP__ #define __VTIME_HPP__ #include "export.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #include #include #include #include /** * Nanoseconds between 01.01.1601 and 01.01.1970 * Leap year : * (year modulo 4 is 0 and year modulo 100 is not 0) or year modulo 400 is 0 * So, 1700, 1800 and 1900 are not leap years. * ((1970 - 1601) * 365 + int((1970-1601) / 4) - 3) * 24 * 3600 * 10000000 */ #if __WORDSIZE == 64 #define NANOSECS_1601_TO_1970 (uint64_t)(116444736000000000UL) #else #define NANOSECS_1601_TO_1970 (uint64_t)(116444736000000000ULL) #endif #define TIME_UNIX 0 #define TIME_MS_64 1 class vtime { private: void __setFromDate(std::string date); void __setFromTime(std::string time); public: EXPORT vtime(); EXPORT vtime(int, int, int, int, int, int, int); EXPORT vtime(uint16_t dos_time, uint16_t dos_date);//DOS 32 bits format EXPORT vtime(uint64_t value, int type); EXPORT vtime(std::string ts); EXPORT bool operator==(vtime* v); EXPORT bool operator!=(vtime* v); EXPORT bool operator>(vtime* v); EXPORT bool operator<(vtime* v); EXPORT bool operator>=(vtime* v); EXPORT bool operator<=(vtime* v); EXPORT virtual ~vtime(); int year; int month; int day; int hour; int minute; int second; int usecond; int wday; int yday; int dst; }; #endif dff-1.3.0+dfsg.1/dff/api/include/wmidev.hpp000066400000000000000000000024511217176075400203030ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #ifndef __WMIDEVICES_HPP__ #define __WMIDEVICES_HPP__ #include "export.hpp" #include "device.hpp" #define _WIN32_DCOM #include #include #include # pragma comment(lib, "wbemuuid.lib") class WMIDevice : public Device { private: IWbemClassObject *pclsObj; public: EXPORT WMIDevice(); EXPORT WMIDevice(IWbemClassObject *pcls); EXPORT ~WMIDevice(); EXPORT wchar_t* blockDevice(void); EXPORT wchar_t* serialNumber(void); EXPORT wchar_t* model(void); EXPORT uint64_t size(void); }; class WMIDevices : public DeviceList { private: IWbemLocator *pLoc; IWbemServices *pSvc; public: std::vector deviceList; EXPORT WMIDevices(); EXPORT ~WMIDevices(); }; #endif dff-1.3.0+dfsg.1/dff/api/include/wstdint.h000066400000000000000000000170601217176075400201460ustar00rootroot00000000000000// ISO C9x compliant stdint.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006-2008 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] #ifndef _MSC_STDINT_H_ // [ #define _MSC_STDINT_H_ #if _MSC_VER > 1000 #pragma once #endif #include // For Visual Studio 6 in C++ mode and for many Visual Studio versions when // compiling for ARM we should wrap include with 'extern "C++" {}' // or compiler give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed #ifdef __cplusplus extern "C" { #endif # include #ifdef __cplusplus } #endif // Define _W64 macros to mark types changing their size, like intptr_t. #ifndef _W64 # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 # define _W64 __w64 # else # define _W64 # endif #endif // 7.18.1 Integer types // 7.18.1.1 Exact-width integer types // Visual Studio 6 and Embedded Visual C++ 4 doesn't // realize that, e.g. char has the same size as __int8 // so we give up on __intX for them. #if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; // 7.18.1.2 Minimum-width integer types typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; // 7.18.1.3 Fastest minimum-width integer types typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; // 7.18.1.4 Integer types capable of holding object pointers #ifdef _WIN64 // [ typedef signed __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else // _WIN64 ][ typedef _W64 signed int intptr_t; typedef _W64 unsigned int uintptr_t; #endif // _WIN64 ] // 7.18.1.5 Greatest-width integer types typedef int64_t intmax_t; typedef uint64_t uintmax_t; // 7.18.2 Limits of specified-width integer types #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 // 7.18.2.1 Limits of exact-width integer types #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX // 7.18.2.2 Limits of minimum-width integer types #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX // 7.18.2.3 Limits of fastest minimum-width integer types #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX // 7.18.2.4 Limits of integer types capable of holding object pointers #ifdef _WIN64 // [ # define INTPTR_MIN INT64_MIN # define INTPTR_MAX INT64_MAX # define UINTPTR_MAX UINT64_MAX #else // _WIN64 ][ # define INTPTR_MIN INT32_MIN # define INTPTR_MAX INT32_MAX # define UINTPTR_MAX UINT32_MAX #endif // _WIN64 ] // 7.18.2.5 Limits of greatest-width integer types #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ # define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MAX _I64_MAX #else // _WIN64 ][ # define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MAX _I32_MAX #endif // _WIN64 ] #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX // [ # ifdef _WIN64 // [ # define SIZE_MAX _UI64_MAX # else // _WIN64 ][ # define SIZE_MAX _UI32_MAX # endif // _WIN64 ] #endif // SIZE_MAX ] // WCHAR_MIN and WCHAR_MAX are also defined in #ifndef WCHAR_MIN // [ # define WCHAR_MIN 0 #endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ # define WCHAR_MAX _UI16_MAX #endif // WCHAR_MAX ] #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif // __STDC_LIMIT_MACROS ] // 7.18.4 Limits of other integer types #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 // 7.18.4.1 Macros for minimum-width integer constants #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 // 7.18.4.2 Macros for greatest-width integer constants #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif // __STDC_CONSTANT_MACROS ] #endif // _MSC_STDINT_H_ ] dff-1.3.0+dfsg.1/dff/api/include/wstdint.i000066400000000000000000000050671217176075400201530ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- * See the LICENSE file for information on copyright, usage and redistribution * of SWIG, and the README file for authors - http://www.swig.org/release.html. * * stdint.i * * SWIG library file for ISO C99 types: 7.18 Integer types * ----------------------------------------------------------------------------- */ %{ #if (_MSC_VER >= 1600) #include #else #include "wstdint.h" // Use the C99 official header #endif %} %include /* Exact integral types. */ /* Signed. */ #if (_MSC_VER < 1600) typedef signed char int8_t; typedef short int int16_t; typedef int int32_t; #if defined(SWIGWORDSIZE64) typedef long int int64_t; #else typedef long long int int64_t; #endif /* Unsigned. */ typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef unsigned int uint32_t; #if defined(SWIGWORDSIZE64) typedef unsigned long int uint64_t; #else typedef unsigned long long int uint64_t; #endif /* Small types. */ /* Signed. */ typedef signed char int_least8_t; typedef short int int_least16_t; typedef int int_least32_t; #if defined(SWIGWORDSIZE64) typedef long int int_least64_t; #else typedef long long int int_least64_t; #endif /* Unsigned. */ typedef unsigned char uint_least8_t; typedef unsigned short int uint_least16_t; typedef unsigned int uint_least32_t; #if defined(SWIGWORDSIZE64) typedef unsigned long int uint_least64_t; #else typedef unsigned long long int uint_least64_t; #endif /* Fast types. */ /* Signed. */ typedef signed char int_fast8_t; #if defined(SWIGWORDSIZE64) typedef long int int_fast16_t; typedef long int int_fast32_t; typedef long int int_fast64_t; #else typedef int int_fast16_t; typedef int int_fast32_t; typedef long long int int_fast64_t; #endif /* Unsigned. */ typedef unsigned char uint_fast8_t; #if defined(SWIGWORDSIZE64) typedef unsigned long int uint_fast16_t; typedef unsigned long int uint_fast32_t; typedef unsigned long int uint_fast64_t; #else typedef unsigned int uint_fast16_t; typedef unsigned int uint_fast32_t; typedef unsigned long long int uint_fast64_t; #endif /* Types for `void *' pointers. */ #if defined(SWIGWORDSIZE64) typedef long int intptr_t; typedef unsigned long int uintptr_t; #else typedef int intptr_t; typedef unsigned int uintptr_t; #endif /* Largest integral types. */ #if defined(SWIGWORDSIZE64) typedef long int intmax_t; typedef unsigned long int uintmax_t; #else typedef long long int intmax_t; typedef unsigned long long int uintmax_t; #endif #endifdff-1.3.0+dfsg.1/dff/api/loader/000077500000000000000000000000001217176075400161205ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/loader/CMakeLists.txt000066400000000000000000000013411217176075400206570ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py loader.py ) dff-1.3.0+dfsg.1/dff/api/loader/__init__.py000066400000000000000000000012211217176075400202250ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_LOADER_VERSION}" __all__ = ["loader"] dff-1.3.0+dfsg.1/dff/api/loader/loader.py000066400000000000000000000314411217176075400177430ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # import os, sys import imp import re import traceback from distutils.version import StrictVersion from stat import * from dff.api.module.module import * from dff.api.types.libtypes import ConfigManager from dff.api.vfs.libvfs import VFS, fso, mfso __module_prepend__ = '__dff_module_' __module_append__ = '_version__' # Depencies are in this form : __api_env_minversion__ = '1.0.0' __api_components__ = ['devices', 'env', 'exceptions', 'gui', 'loader', 'magic', 'manager', 'module', 'search', 'taskmanager', 'tree', 'type', 'variant', 'vfs'] __api_version_prepend__ = '__api_' __api_version_append__ = '_minversion__' class loader(): class __loader(): def pprint(self, args): print args def LoadFile(self, module_path): filename = module_path[module_path.rfind("/")+1:] path = module_path[:module_path.rfind("/")+1] # Strict .py check ; avoid .pyc, for example if filename.endswith(".py"): # if filename.rfind(".py") != -1: if path not in sys.path: # Append to sys.path only once sys.path.append(path) self.ModuleImport(module_path, filename[:filename.rfind(".py")]) def LoadDir(self, module_path): files = os.listdir(module_path) if module_path[len(module_path) - 1] != "/": module_path += "/" for filename in files: if not filename.startswith(".") and not filename.startswith("__") and not filename.startswith("#"): try: mode = os.stat(module_path+filename)[ST_MODE] except: print "Can't access " + str(module_path+filename) return if mode: if S_ISDIR(mode): self.LoadDir(module_path+filename) else: self.LoadFile(module_path+filename) def Load(self, args): module_path = args mode = None self.loadingErrors = "" try: self.pprint("loading modules in " + module_path) mode = os.stat(module_path)[ST_MODE] except: print "File doesn't exist" if mode: if S_ISDIR(mode): self.LoadDir(module_path) elif S_ISREG(mode): self.LoadFile(module_path) else: print "unsupported stat type" if len(self.loadingErrors): print "\n" + self.loadingErrors print "\n" + "If you really need theses modules, please consider either" print "\n - to install dependencies by yourself" print "\n - or to have a look at our professional support -- http://www.arxsys.fr/support" def _versionFromLine(self, line): ''' ''' if line.startswith(__module_prepend__) and line.find(__module_append__) != -1: m = re.search('^' + __module_prepend__ + '([a-zA-Z0-9_]+)' + __module_append__ + '\s*=\s*[\'\"]([ab0-9\.]+)[\'\"]\s*$', line) if m and len(m.groups()) == 2: return (__module_prepend__, [m.group(1), m.group(2)]) if not line.startswith(__api_version_prepend__): return None for oneComponent in __api_components__: if line.startswith(__api_version_prepend__ + oneComponent + __api_version_append__): m = re.search('^' + __api_version_prepend__ + oneComponent + __api_version_append__ + '\s*=\s*[\'\"]([ab0-9\.]+)[\'\"]\s*$', line) if m and len(m.groups()) == 1: return (oneComponent, m.group(1)) return None # future : must return api component name in order to warn about missing component def _validateDFFModule(self, module_path): ''' Return a version dict if file path given is a valid DFF module. A valid DFF module has variable __dff_module_NAME_version__ sets right after header. Header is : - Each line starting with a sharp character - Text block delimited by three quote characters - Text block delimited by three double quote characters ''' vDict = dict() f = open(module_path, 'r') if f: b = f.read(4096) start = -1 headerT1, headerT2 = False, False rest = '' while len(b): b = b + rest end = b.find('\n', start + 1) while end != -1: line = b[start + 1:end] # Skip header line starting with # if line.startswith('#'): pass # Skip header block with ''' as delimiter elif not headerT1 and line.find('\'\'\'') != -1: headerT1 = True elif headerT1 and line.find('\'\'\'') != -1: headerT1 = False elif headerT1: pass # Skip header block with """ as delimiter elif not headerT2 and line.find('\'\'\'') != -1: headerT2 = True elif headerT2 and line.find('\'\'\'') != -1: headerT2 = False elif headerT2: pass # Skip whitespaces-only or empty lines elif not len(line) or line.isspace(): pass # Search for __dff_module_version__ or # __api_*_minversion__ elif line.startswith('__'): vFound = self._versionFromLine(line) if vFound: vDict[vFound[0]] = vFound[1] start = b.find('\n', start + 1) end = b.find('\n', start + 1) if start > 0: rest = b[start - 1:] start = 0 else: rest = b b = f.read(4096) if f: f.close() return vDict def ModuleImport(self, module_path, modname): start = False init = False type = False status = '' warnwithoutload = False if modname == "loader": return vDict = self._validateDFFModule(module_path) if vDict and __module_prepend__ in vDict: if __module_prepend__ in vDict: if len(vDict) < 2: status += 'v' + vDict[__module_prepend__][1] else: status += 'v' + vDict[__module_prepend__][1] + ', requires' for k, v in vDict.iteritems(): if k != __module_prepend__: status += ' ' + k + ' v' + vDict[k] if hasattr(sys.modules['api.' + k], '__version__'): # Component version >= required version if StrictVersion(sys.modules['api.' + k].__version__) >= StrictVersion(vDict[k]): status += ' (<= v' + sys.modules['api.' + k].__version__ + ')' else: status += ' (> v' + sys.modules['api.' + k].__version__ + ' !!)' warnwithoutload = True else: # About to be deprecated ; read all module content to find "(Module)" status += 'using old style module check' flag = False f = open(module_path, 'r') if f: for line in f: if line.find("(Module)") != -1: flag = True break if f: f.close() if not flag: return if warnwithoutload: self.pprint('[WARN]\tnot loading ' + status + ': API required version greather than actual API component version') return usedmodules = self.vfs.fsobjs() if modname in sys.modules: module = sys.modules[modname] cl = getattr(module, modname) tmod = cl() rmodname = tmod.name removable = True if removable: self.cm.unregisterConf(rmodname) del tmod del module self.__load(module_path, modname, status, False) else: print "module", modname, "cannot be deleted because it is already in use" else: self.__load(module_path, modname, status, True) def __load(self, module_path, modname, status, first=True): file, pathname, description = imp.find_module(modname, [os.path.dirname(module_path)]) try: module = imp.load_module(modname, file, pathname, description) cl = getattr(module, modname) mod = cl() self.modules[mod.name] = mod try : self.tags[mod.tags].append(mod.name) except KeyError: self.tags[mod.tags] = [mod.name] sys.modules[modname] = module self.cm.registerConf(mod.conf) self.pprint('[OK]\tloading ' + modname + ' ' + status) except : err_type, err_value, err_traceback = sys.exc_info() for l in traceback.format_exception_only(err_type, err_value): print l for l in traceback.format_tb(err_traceback): print l def __init__(self): self.cm = ConfigManager.Get() self.vfs = VFS.Get() self.cmodules = {} self.scripts = {} self.builtins = {} self.modules = {} self.tags = {} self.loadedPaths = [] self.__modulesPaths = [] __instance = None def __init__(self): if loader.__instance is None: loader.__instance = loader.__loader() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) def get_modules(self, modules=None): if modules: try: mod = self.modules[modules] return mod.name except KeyError: return None else: lmod = [] for name, mod in self.modules.iteritems(): lmod += [name] return lmod def is_modules(self, mod): try: mod = self.__instance.modules[mod] except KeyError: return False return True def get_conf(self, mod): try: mod = self.__instance.modules[mod] except KeyError: return None return mod.conf def get_tags(self, modu): try: mod = self.__instance.modules[modu] except KeyError: return None return mod.tags def modulesPaths(self): return self.__modulesPaths def do_load(self, args, pprint = None, reload = False): for arg in args: self.__modulesPaths.append(arg) if type(args) != list: args = [args] for arg in args: path = arg if os.name == "nt": if arg[1] != ":": path = os.getcwd() + "/" + arg else: if arg[0] != "/": path = os.getcwd() + "/" + arg if pprint: self.__instance.pprint = pprint if not path in self.loadedPaths or reload: self.__instance.Load(path) self.loadedPaths.append(path) def help_load(self): print "load [path/[file]]" def do_lsmod(self, args): """List loaded modules""" return [] dff-1.3.0+dfsg.1/dff/api/magic/000077500000000000000000000000001217176075400157325ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/magic/CMakeLists.txt000066400000000000000000000015301217176075400204710ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # Frederic Baguelin if(WIN32 AND NOT UNIX) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py magic.mgc magic.py libmagic-1.dll libgnurx-0.dll ) endif(WIN32 AND NOT UNIX) dff-1.3.0+dfsg.1/dff/api/magic/__init__.py000066400000000000000000000012401217176075400200400ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_MAGIC_VERSION}" __all__ = ["magic"] dff-1.3.0+dfsg.1/dff/api/magic/magic.mgc000066400000000000000000105443201217176075400175130ustar00rootroot00000000000000ñ =(C64S tape image fileT64 tape Imagex )Version:0x%x! $*Entries:%ix(+Name:%.24s =((*This is a Mathematica binary Mathematica binary file>X+from %s = ûFoglio di lavoro Microsoft Exce%sapplication/vnd.ms-excel =&** This file contains an SQLiteSQLite 2.x database =1.0 Fri Feb 3 09:55:56 MET 1995Erlang JAM file - version 4.3 =4# Bazaar merge directive formatBazaar merge directive =Cobalt Networks Inc. Firmware vPaged COBALT boot romx&€V%.4s =:SC68 Music-file / (c) (BeN)jamisc68 Atari ST music =#C64 tape image fileT64 tape Imagex $Version:0x%x! $%Entries:%ix(&Name:%.24s =óNetImmerse File Format, Versio=ôn NetImmerse game engine file= õ[0-9a-z.]+, version %s =---BEGIN PGP PUBLIC KEY BLOCK-PGP public key blockapplication/pgp-keys =çGamebryo File Format, Version Gamebryo game engine file= è[0-9a-z.]+, version %s =old timezone data =old timezone data = must be converted with BinHexBinHex binary textapplication/mac-binhex40x) , version %.3s =old timezone data = øMicrosoft Excel 5.0 Worksheet%sapplication/vnd.ms-excel = old timezone data =>SNES-SPC700 Sound File Data vSNES SPC700 sound file=?0.30, version %s=#@, without ID666 tag=#A, with ID666 tag>.B, song "%.32s">NC, game "%.32s" =old timezone data =old timezone data =ûinnotek VirtualBox Disk Image%s =%!PS-Adobe-3.0 Resource-FontPostScript Type 1 font text =OTue Jan 22 14:32:44 MET 1991Erlang JAM file - version 4.2 =SStart/Stop parameter header:Caris ASCII project summary =1002003old ACE/gr binary file>'- version %c =Tue Jan 22 14:32:44 MET 1991Erlang JAM file - version 4.2 =í;Gamebryo KFM File Version Gamebryo game engine animation File= î[0-9a-z.]+, version %s =(*^ ::[ frontEndVersion = Mathematica notebook =-----BEGIN CERTIFICATE-----PEM certificate =-SVN-fs-dump-format-version:Subversion dumpfile>.(version: %s) = ãMicrosoft Word 6.0 Document%sapplication/msword =-----BEGIN CERTIFICATE REQPEM certificate request =3# Bazaar revision bundle vBazaar Bundle = åDocumento Microsoft Word 6Spanish Microsoft Word 6 document dataapplication/msword =Identification_InformationFGDC ASCII metadata =§Warcraft III recorded game%s = Í# This is a shell archiveshell archive textapplication/octet-stream =þPaint Shop Pro Image FilePaint Shop Pro Image File =-----BEGIN PGP SIGNATURE-PGP signatureapplication/pgp-signature =Enut/multimedia containerNUT multimedia container =# ACE/gr fit description ACE/gr fit description file =?AVG7_ANTIVIRUS_VAULT_FILEAVG 7 Antivirus vault file data =sWindows Registry Editor =tVersion 5.00 Windows Registry text (Win2K or above) = BDNetscape Address book =Þ@ÐÏࡱá +4AAF file using MS Structured Storage=ß (512B sectors)=à (4kB sectors) =Û@ÐÏࡱáAAFB OM+4ÿAAF legacy file using MS Structured Storage=Ü (512B sectors)=Ý (4kB sectors) =¬`Ph`P@@@@@@@@Linux S390=­@ ‹­ÌÌ=¯ÁïãðhZ10 64bit kernel=°ÁïÃZ9-109 64bit kernel=±À Z990 64bit kernel=²Z900 64bit kernel=´È€Z10 32bit kernel=µÈ€Z9-109 32bit kernel=¶€ Z990 32bit kernel=·€Z900 32bit kernel =9(***********************Mathematica 3.0 notebook =Ž5 East_Side_InvertationaQuake I save: ddm4 East side invertationa =€5 The_Incinerator_PlantQuake I save: d7 The incinerator plant =-----BEGIN PGP MESSAGE-PGP messageapplication/pgp =gFICHIER GUITAR PRO v3.Guitar Pro Ver. 3 Tablature =NetWare Loadable ModuleNetWare Loadable Module =# Netscape folder cacheNetscape folder cache =¢~from '%s' =e5 The_Gremlin's_DomainQuake I save: hip2m6 The gremlin's domain (secret) =45 Castle_of_the_DamnedQuake I save: e1m2 Castle of the damned =A5 the_Dismal_OublietteQuake I save: e2m6 The dismal oubliette = Copyright (c) 199Adobe Multiple Master font =f5 The_Black_CathedralQuake I save: hip2m2 The black cathedral = # xvgr parameter fileACE/gr ascii file =1EXTENDED CPC DSK FilAmstrad/Spectrum Extended .DSK data =95 The_Door_To_ChthonQuake I save: e1m6 The door to Chthon = ¶GameBoy Music ModuleNintendo Gameboy Music Module@=!"#! /usr/local/bin/aeNeil Brown's ae script text executabletext/x-shellscript =# Grace project fileGrace project file= @version (version> %c>!.%.2s>#.%.2s) =RLÀFMS Windows shortcut =W5 The_Abandoned_BaseQuake I save: dm3 The abandoned base =*¡‹ skiplist fileCyrus skiplist DB =7@MDIFú&@}MS Windows special zipped file =V5 ClaustrophobopolisQuake I save: dm2 Claustrophobopolis =3‰?3ŸW9¶i4%A›PGP sig =L5 the_Palace_of_HateQuake I save: e4m4 The palace of hate =¡„%c>…%c>†%c>‡%c>bˆ, "%s" =I# CAR archive headerSAPCAR archive data =!@Nullsoft AVS Preset Winamp plug in =0‰?3ŸW6¶i4%A›PGP sig ==5 the_Crypt_of_DecayQuake I save: e2m3 The crypt of decay (dopefish lives!) =# PaCkAgE DaTaStReAmpkg Datastream (SVR4)application/x-svr4-package =/‰?3ŸW5¶i4%A›PGP sig =/MV - CPCEMU Disk-FilAmstrad/Spectrum .DSK data =F5 the_Haunted_HallsQuake I save: e3m7 The haunted halls (secret) =¯Sharp JisakuMelodySHARP Cell-Phone ringing Melody=°Ver01.00Ver. 1.00x ±, %d tracks =ìGSWAPSPACE2S1SUSPENDLinux/i386 swap file (new style) with SWSUSP1 image =I5 the_Sewage_SystemQuake I save: e4m1 The sewage system =N5 the_Nameless_CityQuake I save: e4m8 The nameless city (secret)@= [KDE Desktop Entry]KDE desktop entryapplication/x-kdelnk =80123456789012345BZhEXP1 archive data =^Interplay MVE FileInterplay MVE Movie =C! __________EMIPS archive=DUwith MIPS Ucode members=ELwith MIPSEL members=FBwith MIPSEB members=GLand an EL hash table=HBand an EB hash table=IX-- out of date =cClient UrlCache MMFInternet Explorer cache file>dversion %s =! ________64EAlpha archive=X-- out of date = ML4D '92Smith Corona PWP=, single spaced= , 1.5 spaced= , double spaced= B, letter= T, legal= F, A4 =FRoot EntryMicrosoft Word Documentapplication/msword =bCreative Voice FileCreative Labs voice dataaudio/x-unknown=e>f- version %d>g.%d =?5 the_Ebon_FortressQuake I save: e2m4 The ebon fortress =0MV - CPC format DisAmstrad/Spectrum DU54 .DSK data =65 the_Grisly_GrottoQuake I save: e1m4 The grisly grotto =c5 Research_FacilityQuake I save: hip1m4 Research facility =75 Ziggurat_VertigoQuake I save: e1m8 Ziggurat vertigo (secret) =a5 Military_ComplexQuake I save: hip1m5 Military complex (secret) =çMIT-MAGIC-COOKIE-1X11 Xauthority data@=>"#! /usr/local/bashBourne-Again shell script text executabletext/x-shellscript =x5 The_Genetics_LabQuake I save: d11 The genetics lab (secret) =þImagefile version-iff image data> %s =æMIT-MAGIC-COOKIE-1X11 Xauthority data = ßMIT-MAGIC-COOKIE-1X11 Xauthority data@="#! /usr/local/tcshTenex C shell script text executabletext/x-shellscript =;5 the_InstallationQuake I save: e2m1 The installation =`5 Storage_FacilityQuake I save: hip1m2 Storage facility =+# GIMP Curves FileGIMP curve file =SOUND SAMPLE DATA Sample Vision file = àMIT-MAGIC-COOKIE-1X11 Xauthority data =)(SYSTEM::VERSION 'CLISP byte-compiled Lisp program (pre 2004-03-27) = áMIT-MAGIC-COOKIE-1X11 Xauthority data =<5 the_Ogre_CitadelQuake I save: e2m2 The ogre citadel = âMIT-MAGIC-COOKIE-1X11 Xauthority data =ãMIT-MAGIC-COOKIE-1X11 Xauthority data =äMIT-MAGIC-COOKIE-1X11 Xauthority data =åMIT-MAGIC-COOKIE-1X11 Xauthority data =0[Equalizer preset]XMMS equalizer preset =‘5 SANDRA'S_LADDERQuake I save: ddm7 Sandra's ladder ={5 Takahiro_TowersQuake I save: d2 Takahiro towers@= # KDE Config FileKDE config fileapplication/x-kdelnk = %!PS-AdobeFont-1.PostScript Type 1 font text> (%s) =5 # ## `-ÿÿÿÿÿÿÿÿvolume %ld>0type %s>1device %s,>2original filename %s,= D'4not compressed= D'5gzip compressed= D'6bzip2 compressed> D'7compressed with unknown algorithm> 80.6.1file version %s< 90.6.1file version %s =œ7B9d9GEPOC MBM image file =á#VRML V1.0 asciiVRML 1 filemodel/vrml = RAD by REALiTY!!RAD Adlib Tracker Module RAD =6ObserverPktBuffeNetwork Instruments Observer capture file =KLinuxGuestRecordXen saved domain=L(namexM(name %s) =}5 Into_The_FloodQuake I save: d4 Into the flood =ÿWPC (WP) loadable file=Optimized for Intel=Optimized for Non-Intel =QLinuxGuestRecordXen saved domain=S(name(namexT%s...) = õ, %d channels> ö%d Hz =StartFontMetricsASCII font metrics =ûRF64ÿÿÿÿWAVEds64MBWF/RF64 audioaudio/x-wav=(ýfmt = þ, mono= ÿ, stereo> , %d channels> %d Hz = NIST_1A 1024 NIST SPHERE file =o5 Armagon's_LairQuake I save: hipend Armagon's lair =q“MICROSOFT PIFEXWindows Program Information Fileapplication/x-dosexec>$– for %.63s>e—, directory=%.64s>¥˜, parameters=%.64s=‡œU WINDOWS VMM 4.0 >^< ÿÿÿÿžPIFMGR.DLL, icon=%s> ÿÿÿÿ PIFMGR.DLL, icon=%s >ð¡<ÿÿÿÿ¢Terminal, font=%.32s>ÿÿÿÿ¤Terminal, font=%.32s >¥<ÿÿÿÿ¦Lucida Console, TrueTypeFont=%.32s>ÿÿÿÿ¨Lucida Console, TrueTypeFont=%.32s=‡«U WINDOWS NT 3.1, Windows NT-style=‡­U CONFIG SYS 4.0 +CONFIG.SYS=‡¯U AUTOEXECBAT 4.0 +AUTOEXEC.BAT =VoIP Startup andAculab VoIP firmwarex#format %s =9# ## Maple something anomalous. =Interpress/XeroxXerox InterPress data=/(version>%s) =žBEA TUXEDO DES mask data =7# ##  , crypto type %hhu (unknown)= , hash type 0 (MD5)> , hash type %hhu (unknown)=ÿÿÿÿ, name NULL !ÿÿÿÿ>üÿÿÿÿ, name too long for file's pstring type <üÿÿÿx ÿÿÿÿ€, name "%s"x, last modified %sx, created %s &x, locked if idle for %u seconds^, not locked if idlex, hash iterations %ux, salt %llux4, %u item(s) =ëSIDPLAY INFOFILESidplay info file = Microsoft C/C++ MSVC program database=!program database >!"ver %s =  !NTITLE REMARKCNS ASCII electron density map =8MMXMAR Area Detector Image,>09Compressed(%d),>L:%d headers,>P;%d x>T<%d,>`=%d bits/pixel =XPCOM TypeLib XPConnect Typelibxversion %dx.%d =õ@(#)ADF DatabaseCGNS Advanced Data Format =ªExtended Module:Fasttracker II module sound dataaudio/x-mod>­Title: "%s"@=<"#! /usr/bin/bashBourne-Again shell script text executabletext/x-shellscript@=+è =e=e==eversion %s =X5 The_Bad_PlaceQuake I save: dm4 The bad place =&_SGI_SoundTrackSGI SoundTrack project file =5 Nuclear_PlantQuake I save: d6 Nuclear plant@=2"#! /usr/bin/awkawk script text executabletext/x-awk = version=SPECjbbSPECjbb< :%.4s<%:v%.4s raw result text =.#pmieconf-rulesPCP pmieconf rules>/(V.%1.1s) =ã#VRML V2.0 utf8ISO/IEC 14772 VRML 97 filemodel/vrml =…5 Stayin'_AliveQuake I save: d13 Stayin' alive@=: >%.3s document text=? %s = 2%-12345X@PJLHP Printer Job Language data = ;%-12345X@PJLHP Printer Job Language data><%s >=%s >>%s >?%s = GIMP GradientGIMP gradient data = '1(V.%1.1s)@=  Delivered-To:SMTP mail textmessage/rfc822 = OSplineFontDB:Spline Font Database application/vnd.font-fontforge-sfdxQversion %s = h5 the_Crypt__Quake I save: hip2m4 The crypt =  %SEMI-OASIS OASIS Stream file = Y5 The_CisternQuake I save: dm5 The cistern = cBEGIN:IMELODYiMelody Ringtone Format = '+&, %d kbit/s>#', %d kHz@=  Return-Path:SMTP mail textmessage/rfc822 = DTJPCH0C€Microsoft Visual C .pch = 85 Gloom_KeepQuake I save: e1m5 Gloom keep@= )"#! /bin/gawkGNU awk script text executabletext/x-gawk = >5 UnderearthQuake I save: e2m7 Underearth (secret) = ýDVDVIDEO-VMGVideo manager,x!þv%x@= :"#! /bin/bashBourne-Again shell script text executabletext/x-shellscript = Joy!peffpwpcheader for PowerPC PEF executable = rREGEDIT4 Windows Registry text (Win95 or above) = ¡KenSilvermanBuild engine group filex ¢containing %d files = 0Packed File Personal NetWare Packed Filex 1, was "%.12s" = ^tfMR MS Windows help cache = õ*dvdisaster*dvdisaster error correction file = œ jP ‡ JPEG 2000 image data = #!teapot xdrteapot work sheet (XDR format) = ûDVDVIDEO-VTSVideo title set,x!üv%x@= "#! /bin/tcshTenex C shell script text executabletext/x-shellscript = ## SE Linux policy interface source@=  /1 :pserver:cvs password text file = ßÀMarvell Libertas firmware = ?CyrSBytecodeCyrus sieve bytecode data,= @version 1, big-endian= Aversion 1, little-endianx Bversion %d, network-endian = '#pmdahotprocPCP pmdahotproc config= (Version>)(V%-3.3s) = F0 HEADGEDCOM data = .*PPD-Adobe: PPD filex/, version %s = œ  L%s saved game data@= #"#! /bin/nawknew awk script text executabletext/x-nawk =   0Clam AntiVirus database %-.23s="1:!#2:, version x#3%-.1s!$4:x$5%-.1s!%6:x%7%-.1s !&8: x&9%-.1s=:‹, gzipped=;ustar, tarred = VT3-image x WTADS 3 game data (format version %d) = ûd8:announceBitTorrent fileapplication/x-bittorrent = ÎstreamtypedNeXT/Apple typedstream data, little endianxÏ, version %hhd<Ð= Ñÿÿÿÿÿÿÿx Ò, system %hd@=  "#! /bin/kshKorn shell script text executabletext/x-shellscript =  ïž2061PUCrunch archive data = iptrace 1.0"iptrace" capture file@= "#! /bin/zshPaul Falstad's zsh script text executabletext/x-shellscript = iptrace 2.0"iptrace" capture file = ˆBOBO†Claris works document = ÉtypedstreamNeXT/Apple typedstream data, big endianxÊ, version %hhd<Ë= ÌÿÿÿÿÿÿÿxÍ, system %hd = divert(-1) sendmail m4 text file =*ELFELF=invalid class=32-bit=64-bit=invalid byte order=LSB= no file type,application/octet-stream= relocatable,application/x-object= executable,application/x-executable= shared object,application/x-sharedlib=  core fileapplication/x-coredump& %ÿÿÿÿÿÿÿprocessor-specific,= &no machine,= 'AT&T WE32100 - invalid byte order,= (SPARC - invalid byte order,= )Intel 80386,= *Motorola& $+68000 - invalid byte order,& $,CPU32 - invalid byte order,= $-68020 - invalid byte order,= .Motorola 88000 - invalid byte order,= /Intel 80486,= 0Intel 80860,= 4MIPS,& $5 N32= 6 MIPS,& $7 N32= 8=:= $;ðÿÿÿÿMIPS-I= $<ðÿÿÿÿMIPS-II= $=ðÿÿÿÿ MIPS-III= $>ðÿÿÿÿ0MIPS-IV= $?ðÿÿÿÿ@MIPS-V= $@ðÿÿÿÿPMIPS32= $Aðÿÿÿÿ`MIPS64= $BðÿÿÿÿpMIPS32 rel2= $Cðÿÿÿÿ€ÿÿÿÿMIPS64 rel2=E= 0FðÿÿÿÿMIPS-I= 0GðÿÿÿÿMIPS-II= 0Hðÿÿÿÿ MIPS-III= 0Iðÿÿÿÿ0MIPS-IV= 0Jðÿÿÿÿ@MIPS-V= 0KðÿÿÿÿPMIPS32= 0Lðÿÿÿÿ`MIPS64= 0MðÿÿÿÿpMIPS32 rel2= 0Nðÿÿÿÿ€ÿÿÿÿMIPS64 rel2= O Amdahl - invalid byte order,= P MIPS (deprecated),= Q RS6000 - invalid byte order,= RPA-RISC - invalid byte order,= 2S2.0& 0T(LP64),= UnCUBE,= VFujitsu VPP500,= WSPARC32PLUS - invalid byte order,= XPowerPC,= YIBM S/390,= Z$NEC V800,= [%Fujitsu FR20,= \&TRW RH-32,= ]'Motorola RCE,= ^(ARM,= _)Alpha,= `£ÿÿÿÿÿÿIBM S/390 (obsolete),= a*Renesas SH,= b+SPARC V9 - invalid byte order,= c,Siemens Tricore Embedded Processor,= d-Argonaut RISC Core, Argonaut Technologies Inc.,= e.Renesas H8/300,= f/Renesas H8/300H,= g0Renesas H8S,= h1Renesas H8/500,= i2IA-64,= j3Stanford MIPS-X,= k4Motorola Coldfire,= l5Motorola M68HC12,= m6Fujitsu MMA,= n7Siemens PCP,= o8Sony nCPU,= p9Denso NDR1,= q:Start*Core,= r;Toyota ME16,= s<ST100,= t=Tinyj emb.,= u>x86-64,= v?Sony DSP,= wBFX66,= xCST9+ 8/16 bit,= yDST7 8 bit,= zEMC68HC16,= {FMC68HC11,= |GMC68HC08,= }HMC68HC05,= ~ISGI SVx,= JST19 8 bit,= €KDigital VAX,= LAxis cris,= ‚MInfineon 32-bit embedded,= ƒNElement 14 64-bit DSP,= „OLSI Logic 16-bit DSP,= …PMMIX,= †QHarvard machine-independent,= ‡RSiTera Prism,= ˆSAtmel AVR 8-bit,= ‰TFujitsu FR30,= ŠUMitsubishi D10V,= ‹VMitsubishi D30V,= ŒWNEC v850,= XRenesas M32R,= ŽYMatsushita MN10300,= ZMatsushita MN10200,= [picoJava,= ‘\OpenRISC,= ’]ARC Cores Tangent-A5,= “^Tensilica Xtensa,= ”aNatSemi 32k,= •jAnalog Devices Blackfin,= –qAltera Nios II,= —®META,= ˜»Tilera TILE64,= ™¼Tilera TILEPro,= š¿Tilera TILE-Gx,= ›&4OpenRISC (obsolete),= œr„ÿÿÿÿÿÿOpenRISC (obsolete),= &ÿÿÿÿÿÿAlpha (unofficial),= žinvalid version= Ÿversion 1= $ MathCoPro/FPU/MAU Required=¡MSB=¢no file type,application/octet-stream=¤relocatable,application/x-object=¦executable,application/x-executable=¨shared object,application/x-sharedlib=ªcore file,application/x-coredump&®ÿÿÿÿÿÿÿprocessor-specific,=¯no machine,=°AT&T WE32100,=±SPARC,=²Intel 80386 - invalid byte order,=³Motorola&$´68000,&$µCPU32,=$¶68020,=·Motorola 88000,=¸Intel 80486 - invalid byte order,=¹Intel 80860,=»MIPS,&$¼ N32=½ MIPS,&$¾ N32=¿=Á=$ÂðÿÿÿÿMIPS-I=$ÃðÿÿÿÿMIPS-II=$Äðÿÿÿÿ MIPS-III=$Åðÿÿÿÿ0MIPS-IV=$Æðÿÿÿÿ@MIPS-V=$ÇðÿÿÿÿPMIPS32=$Èðÿÿÿÿ`MIPS64=$ÉðÿÿÿÿpMIPS32 rel2=$Êðÿÿÿÿ€ÿÿÿÿMIPS64 rel2=Ì=0ÍðÿÿÿÿMIPS-I=0ÎðÿÿÿÿMIPS-II=0Ïðÿÿÿÿ MIPS-III=0Ððÿÿÿÿ0MIPS-IV=0Ñðÿÿÿÿ@MIPS-V=0ÒðÿÿÿÿPMIPS32=0Óðÿÿÿÿ`MIPS64=0ÔðÿÿÿÿpMIPS32 rel2=0Õðÿÿÿÿ€ÿÿÿÿMIPS64 rel2=Ö Amdahl,=× MIPS (deprecated),=Ø RS6000,=ÙPA-RISC=2Ú2.0&0Û(LP64)=ÜnCUBE,=ÝFujitsu VPP500,=ÞSPARC32PLUS,=$ßÿÿV8+ Required,=$àÿÿSun UltraSPARC1 Extensions Required,=$áÿÿHaL R1 Extensions Required,=$âÿÿSun UltraSPARC3 Extensions Required,=ãPowerPC or cisco 4500,=ä64-bit PowerPC or cisco 7500,=åIBM S/390,=æCell SPU,=çcisco SVIP,=ècisco 7200,=é$NEC V800 or cisco 12000,=ê%Fujitsu FR20,=ë&TRW RH-32,=ì'Motorola RCE,=í(ARM,=î)Alpha,=ï*Renesas SH,=ð+SPARC V9,=0ñÿÿSun UltraSPARC1 Extensions Required,=0òÿÿHaL R1 Extensions Required,=0óÿÿSun UltraSPARC3 Extensions Required,=0ôtotal store ordering,=0õpartial store ordering,=0örelaxed memory ordering,=÷,Siemens Tricore Embedded Processor,=ø-Argonaut RISC Core, Argonaut Technologies Inc.,=ù.Renesas H8/300,=ú/Renesas H8/300H,=û0Renesas H8S,=ü1Renesas H8/500,=ý2IA-64,=þ3Stanford MIPS-X,=ÿ4Motorola Coldfire,=5Motorola M68HC12,=ICray NV1,=KDigital VAX,=XRenesas M32R,= \OpenRISC,= &4OpenRISC (obsolete),= r„ÿÿÿÿÿÿOpenRISC (obsolete),=^Tensilica Xtensa,=aNatSemi 32k,= »Tilera TILE64,= ¼Tilera TILEPro,= ¿Tilera TILE-Gx,= ­AVR32 (unofficial),= &ÿÿÿÿÿÿAlpha (unofficial),=£ÿÿÿÿÿÿIBM S/390 (obsolete),=invalid version=version 1=$MathCoPro/FPU/MAU Required<€ÿÿÿÿÿÿÿ>(%s)==(SYSV)=(HP-UX)=(NetBSD)=(GNU/Linux)=(GNU/Hurd)=(86Open)=(Solaris)=(Monterey)=(IRIX)=  (FreeBSD)=! (Tru64)=" (Novell Modesto)=# (OpenBSD)=$=% (OpenVMS)=&a(ARM)='ÿÿÿÿÿÿÿÿ(embedded) = y[autorun] Microsoft Windows Autorun file.application/x-setupscript.@=  "#! /bin/cshC shell script text executabletext/x-shellscript = mscdocumentMessage Sequence Chart (document) = yOctaMEDCmprOctaMED Soundstudio compressed file = &Spreadsheetsc spreadsheet fileapplication/x-sc = NuppelVideoMythTV NuppelVideox v%sx (%dx x%d),=$ Pprogressive,=$ Iinterlaced,x&( aspect:%.2f,x&0 fps:%.2f = ¿#?RADIANCE Radiance HDR image data@= 0"#! /bin/awkawk script text executabletext/x-awk =  filedesc://Internet Archive Fileapplication/x-ia-arc=  > version %c = (*^ ::[ Mathematica notebook version 2.x =  BEGIN:VCARDvCard visiting cardtext/x-vcard = \[DEPOT\] Quick Database Manager, big endian = \[depot\] Quick Database Manager, little endian = ~5 The_FloodQuake I save: d5 The flood =  1Size=%dx> 2%d<3Big-endian, IP #%d,>4Size=%dx>5%d = 'R-AXIS4 R-Axis Area Detector Image:< (Little-endian, IP #%d,> )Size=%dx> *%d<+Big-endian, IP #%d,>,Size=%dx>-%d = ÄBitmapfileHP Bitmapfile = OTADS2 saveTADS! P saved game data, CORRUPTED= Q >R%s saved game data@= 7"#! /bin/rcPlan 9 rc shell script text executable = Å@GFA-BASIC3GFA-BASIC 3 data = Octave-1-LOctave binary data (little endian) = W@document(Imagen printer= Ylanguage impress(imPRESS data)= Zlanguage daisy(daisywheel text)= [language diablo(daisywheel text)= \language printer(line printer emulation)= ]language tektronix(Tektronix 4014 emulation) = :-) OriginBRIX Electron Density Map>ª0, Sigma:%.12s = öDSWAP-SPACELinux/i386 swap file = ‚¾ïABCDEFGHHP LaserJet 1000 series downloadable firmware = FTNCHEK_ Pproject file for ftnchek= 1version 2.7= 2version 2.8 to 2.10= 3version 2.11 or later@=  Forward tomail forwarding textmessage/rfc822 = €LockStreamLockStream Embedded file (mostly MP3 on old Nokia phones) = JCAR 2.00RGSAPCAR archive data = Octave-1-BOctave binary data (big endian) = öMSWAPSPACE2Linux/i386 swap file (new style),xNversion %d (4K pages),xOsize %d pages,=Pno label,>QLABEL=%s,x RUUID=%08xxS-%04xxT-%04xxU-%04xxV-%08xxW%04x = PII*CRCanon CR2 raw image dataimage/x-canon-cr2x R, version %d.x S%d = öÿZSWAPSPACE2Linux/ppc swap file =  uGERBILCLIPFirst Choice database = MeTaSt00r3Metastore data file, x version %0llx =  1(net-order %d)&2(network-ordered)=3(major 1)=4(major 1) = \%% TDR 2.0IVS Fledermaus TDR file = ËBoomæÿBoom or linuxdoom demo = 18 !NTITLEXPLOR ASCII Electron Density Map@Z=+--- = =+++ = =@@unified diff output texttext/x-diff = 1@databaseAmigaGuide file = $#pmloggerPCP pmlogger config= %Version>&(V%1.1s) = :SIMPLE =FITS image data=m;8, 8-bit, character or unsigned binary integer=l<16, 16-bit, two's complement binary integer=k= 32, 32-bit, two's complement binary integer=k>-32, 32-bit, floating point, single precision=k?-64, 64-bit, floating point, double precision = ðÎDECFILE11Files-11 On-Disk Structurex ÏLevel %dx Ð(ODS-%d);=ùÑARSX-11, VAX/VMS or OpenVMS VAX file system;=ùÒB= ÓVAX/VMS or OpenVMS file system;= ÔOpenVMS Alpha or Itanium file system;xØÕvolume label is '%-12.12s' = z!MKS Spell hash list = "{VERSION Maple worksheet> #version %.1s.> $%.1s = 4ÿReIsEr3FsReiserFS V3.6.19x ,block size %d& 2(mounted or unclean)x num blocks %d= @tea hash= @yura hash= @r5 hash = A/E SGML binary styles file> Type %s =  ÿMSVC .res = t5 The_LabQuake I save: d1 The lab =  sGERBILDOCFirst Choice document = îgtktalog GTKtalog catalog data,= ï3version 3=ðzg(gzipped)!ñzg(not gzipped)> ò3version %s = ~.ê$ÿ®QiNintendo Game Boy Advance ROM Image = ª#InventorV2 Open Inventor 2.0 file = šÐð DOS floppy 360k= þ›Uªÿÿÿÿÿÿ, x86 hard disk boot sector = ©#InventorV IRIS Inventor 1.0 file = @WordPro ûLotus WordProapplication/vnd.lotus-wordpro = @èMSWordDocMicrosoft Word document dataapplication/msword = StartFontASCII font bits = œ ù DOS floppy 720k= þUªÿÿÿÿÿÿ, x86 hard disk boot sector = VimCrypt~Vim encrypted file data = u5 Area_33Quake I save: d1b Area 33 = BTADS2 rscTADS! C resource data, CORRUPTED= D > E%s resource data = 4þReIsEr2FsReiserFS V3.6 = =TADS2 binTADS! > game data, CORRUPTED= ? > @%s game data = ž@ ð DOS floppy 1440k= þŸUªÿÿÿÿÿÿ, x86 hard disk boot sector@=  N#! rnewsmailed, batched news textmessage/rfc822 = ÔNõFélÃ¥NuLIB archive data = (*^ ::[ Mathematica notebook version 2.x = ¡ ù DOS floppy 720k, IBM= þ¢Uªÿÿÿÿÿÿ, x86 hard disk boot sector = %£Composer: "%s" =  SBMBAKUP_Smart Boot Manager backup filex !, version %-5.5s="_x#%-.1s=$_.x%%-.1s=&_.x'%-.1s=(x), from drive 0x%x>*x+, from drive %s@=  Received:RFC 822 mail textmessage/rfc822 =  (*^ ::[ Mathematica notebook version 2.x = ¹OracleCFSOracle Clustered Filesystem,xºrev %dx».%d,x0¼label: %.64s,xˆ½mountpoint: %.128s = !(*^ ::[ Mathematica notebook version 2.x =  HWBÿMicrosoft Visual C .APS file =  A/E SGML Document binary> Type %s =  Compiled SGML rules file> Type %s = èTFMX-SONGTFMX module sound data = „‰LZO  lzop compressed data< …@ = †ðÿÿÿÿÿÿÿ- version 0.x ‡ÿ%03x,= ˆLZO1X-1,= ‰LZO1X-1(15),= ŠLZO1X-999,=Œos: MS-DOS=os: Amiga=Žos: VMS=os: Unix=os: Atari=‘os: OS/2=’os: MacOS=“ os: Tops/20=” os: WinNT=•os: Win32> –9 = —ðÿÿÿÿÿÿÿ- version 0.= ˜ðÿÿÿÿÿÿÿ- version 1.= ™ðÿÿÿÿÿÿÿ - version 2.x šÿ%03x,=›LZO1X-1,=œLZO1X-1(15),=LZO1X-999,=Ÿos: MS-DOS= os: Amiga=¡os: VMS=¢os: Unix=£os: Atari=¤os: OS/2=¥os: MacOS=¦ os: Tops/20=§ os: WinNT=¨os: Win32 = § ù Atari-ST floppy 720k =  PLUS3DOSSpectrum +3 data= - BASIC program= - number array=- character array=- memory block=@(screen)=- Tasword document=TAPEFILE- ZXT tapefile =`AT&TFORM= aDJVMDjVu multiple page documentimage/vnd.djvu= cDJVUDjVu image or single page documentimage/vnd.djvu= eDJVIDjVu shared documentimage/vnd.djvu= gTHUMDjVu page thumbnailsimage/vnd.djvu =;= <Digital Symphony sequence (RISC OS),x=version %d,= >1 line,! ?%d lines,= @1 position! A%d positions= BDigital Symphony pattern data (RISC OS),xCversion %d,= D1 pattern! E%d patterns =dÚI7 Ø·=e­^éN¦Windows Television DVR Media =X@DDS |Microsoft DirectDraw Surface (DDS),> Y%hd x> Z%hd,xT[%.4s = mpu401trMPU-401 Trakker =®**TI92**TI-92 Graphing Calculator=H¯(expression)=H°(list)=H±(matrix)=H² (data)=H³ (text)=H´ (string)=Hµ (graphic data base)=H¶(figure)=H·(picture)=H¸(program)=H¹(function)=Hº(macro)=H»(backup) = gtktalogGNOME Catalogue (gtktalog)> version %s =l@MSWIMWindows imaging (WIM) image =ZXAYEMULSpectrum 128 tune =5 DOMINOQuake I save: ddm6 Domino =!package0Newton package, NOS 1.x,& "€ÿÿÿÿAutoRemove,& #@CopyProtect,& $NoCompression,& %Relocation,& &UseFasterCompression,x'version %d =OKTASONGOktalyzer module data =¿**TI92P*TI-92+/V200 Graphing Calculator=HÀ(expression)=HÁ(list)=HÂ(matrix)=Hà (data)=HÄ (text)=HÅ (string)=HÆ (graphic data base)=HÇ(figure)=HÈ(picture)=HÉ(program)=HÊ(function)=HË(macro)=HÌ(zipped)=HÍ!(assembler) =)package1Newton package, NOS 2.x,& *€ÿÿÿÿAutoRemove,& +@CopyProtect,& ,NoCompression,& -Relocation,& .UseFasterCompression,x/version %d =\**TI85**TI-85 Graphing Calculator=;](real number)=;^(complex number)=;_(real vector)=;`(complex vector)=;a(real list)=;b(complex list)=;c(real matrix)=;d(complex matrix)=;e(real constant)=;f (complex constant)=;g (equation)=;h (string)=;i (function GDB)=;j(polar GDB)=;k(parametric GDB)=;l(diffeq GDB)=;m(picture)=;n(program)=;o(range)=;p(window settings)=;q(window settings)=;r(window settings)=;s(window settings)=;t(zoom)=;u(backup)=;v(unknown)=;w*(equation)=2xZS4- ZShell Version 4 File.=2yZS3- ZShell Version 3 File. =G**TI83F*TI-83+ Graphing Calculator=;H(real number)=;I(list)=;J(matrix)=;K(equation)=;L(string)=;M(program)=;N(assembly program)=;O(picture)=;P(gdb)=;Q (complex number)=;R(window settings)=;S(zoom)=;T(table setup)=;U(backup)=;V(application variable)=;W(group of variable) =ÑAdvancedTI-XX Graphing Calculator (FLASH) =”MComprHDMAME CHD compressed hard disk image,x •version %lu =1package4Newton package,=2NOS 1.x,=3 NOS 2.x,& 4€ÿÿÿÿAutoRemove,& 5@CopyProtect,& 6NoCompression, =5**TI83**TI-83 Graphing Calculator=;6(real)=;7(list)=;8(matrix)=;9(Y-variable)=;:(string)=;;(program)=;<(protected prgm)=;=(picture)=;>(gdb)=;? (window settings)=;@ (window settings)=;A (table setup)=;B(screenshot)=;C(backup) =}**TI86**TI-86 Graphing Calculator=;~(real number)=;(complex number)=;€(real vector)=;(complex vector)=;‚(real list)=;ƒ(complex list)=;„(real matrix)=;…(complex matrix)=;†(real constant)=;‡ (complex constant)=;ˆ (equation)=;‰ (string)=;Š (function GDB)=;‹(polar GDB)=;Œ(parametric GDB)=;(diffeq GDB)=;Ž(picture)=;(program)=;(range)=;‘(window settings)=;’(window settings)=;“(window settings)=;”(window settings)=;•(zoom)=;–(backup)=;—(unknown)=;˜*(equation) =œ**TI89**TI-89 Graphing Calculator=H(expression)=Hž(list)=HŸ(matrix)=H  (data)=H¡ (text)=H¢ (string)=H£ (graphic data base)=H¤(figure)=H¥(picture)=H¦(program)=H§(function)=H¨(macro)=H©(zipped)=Hª!(assembler) =z5 Area44Quake I save: d1c Area 44 =ÐÏࡱáOLE 2 Compound Document= € Dgn~H: Microstation V8 DGN=€VisioDoc: Visio Document =YARMovie ARMovie =¬bplist00Apple binary property list =RAWADATARdosPlay RAW =ŒSCRSHOT_scrshot(1) screenshot,xversion %d,= Ž%d bytes in header,x %d chars wide byx %d chars high =#pmchartPCP pmchart view= Version>(V%-3.3s) =CRBLCR= x86= alpha= x86-64= ARMx context data (little endian, version %d) =CRBLCR=SPARC=ppc=ppc64=ARMEB=SPARC64xcontext data (big endian, version %d) =PCPFolioPCP= Version:Archive Folio>(V.%s) =Ò**TIFL**TI-XX Graphing Calculator (FLASH)>Ó- Revision %dx Ô.%d,> ÕRevision date %02xx Ö/%02xx×/%04x,>Ø/0name: '%s',=0Ùtdevice: TI-73,=0Úsdevice: TI-83+,=0Û˜ÿÿÿÿÿÿÿdevice: TI-89,=0܈ÿÿÿÿÿÿÿdevice: TI-92+,=1Ý#type: OS upgrade,=1Þ$type: application,=1ß%type: certificate,=1à>type: license,> Jásize: %ld bytes =$**TI82**TI-82 Graphing Calculator=;%(real)=;&(list)=;'(matrix)=;((Y-variable)=;)(program)=;*(protected prgm)=;+(picture)=;,(gdb)=;- (window settings)=;. (window settings)=;/ (table setup)=;0(screenshot)=;1(backup) =2 Digital Symphony song (RISC OS),x3version %d,= 41 voice,! 5%d voices,= 61 track,! 7%d tracks,= 81 pattern! 9%d patterns =**TI73**TI-73 Graphing Calculator=;(real number)=;(list)=;(matrix)=;(equation)=;(string)=;(program)=;(assembly program)=;(picture)=;(gdb)=; (complex number)=;(window settings)=;(zoom)=;(table setup)=; (backup) =**TI81**TI-81 Graphing Calculator File. =?SB2100DRSeaBeam 2100 DR multibeam sonar = µORCLCLRDOracle ASM Volume (cleared),x(¶Disk Name: %0.12s =@SB2100PRSeaBeam 2100 PR multibeam sonar = %s,x%lu xx%lu,=RGB Color=Greyscale=Indexed Color>Unknown Image Type. =' Digital Symphony sound sample (RISC OS),x(version %d,x )€named "%s",= *8-bit logarithmic= +LZW-compressed linear= ,8-bit linear signed= -16-bit linear signed= .SigmaDelta-compressed linear= /SigmaDelta-compressed logarithmic> 0unknown format =§WNGZWZHPWingz help file =¦MODINFO1Open Cubic Player Module Inforation MDZ =²BMOD2STMScreamtracker 2 module sound dataaudio/x-mod =¯!SCREAM!Screamtracker 2 module sound dataaudio/x-mod = **TI80**TI-80 Graphing Calculator File. =btsnoopBTSnoopxversion %d,= éUnencapsulated HCI= êHCI UART (H4)= ëHCI BCSP= ìHCI Serial (H5)x type %d =#kmchartPCP kmchart view= Version> (V.%s) =%XDELTA%XDelta binary patch file 0.14 = ÀORCLDISKOracle ASM Volume,x(ÁDisk Name: %0.12s =JGART =Ëmsgcat01HP NLS message catalog,>Ì%d messages =SX961999Net2phone = ustar GNU tar archiveapplication/x-tar =$sacspMSFTMicrosoft ICM Color Profileapplication/vnd.iccprofile =GNU tar-GNU tar incremental snapshot data=[0-9].[0-9]+-[0-9]+version %s =¦WNGZWZSSWingz spreadsheet(=Hÿÿÿÿ ÿÿÿÿDOS executable (=(IUPX!UPX compressed = K€block device driver= M€€= Nclock = Pfast > Rstandard = Sinput= T/= Uoutput = V€€character device driverxW=(YUPX!x(Z> \' > ] ! ^.! _*%c> ` ! a.%c> b ! c9! d.%c> e ! f.%c>g !h.%c>i !j.%c>k !l.<mË%c>n !o.<p%c= r€€< s/>u%-.5s= v€= x,32-bit sector-= z@@,IOCTL-= |,close media-= ~€€=  ,until busy-= @@,control strings-= ‚€€> ƒ@hsupport= „€> …BHsupportx†) =†LRFBBeB ebook data, unencryptedx‡, version %d=$ˆ, front-to-back=$‰, back-to-frontx*Š, (%dx,x,‹%d) =\ PLOT%%84Plot84 plotting file=4 , Little-endian=7, Big-endian =0xabcdefAIX message catalog =[KGB_archKGB Archiver filex \with compression level %.1s =ÐTDB fileTDB database= Ñm&version 6, little-endianx $Òhash size %d bytes =c@ITOLITLSMicrosoft Reader eBook Datax d, version %uapplication/x-ms-reader = ÂORCLCLRDOracle ASM Volume (cleared),x(ÃDisk Name: %0.12s =¥WNGZWZSCWingz compiled script =PK00PKZip archive data =h‰PNG  PNG image dataimage/pngxj, %ld xxk%ld,xl%d-bit=mgrayscale,=n/color RGB,=ocolormap,=pgray+alpha,=q/color RGBA,=snon-interlaced=tinterlaced =GCR-1541GCR Imagexversion: %ix tracks: %i = Maestro RISC OS music filex!version %dx#type %d =¡SGIAUDITSGI Audit filex¢- version %dx £.%ld = ³ORCLDISKOracle ASM Volume,x(´Disk Name: %0.12s =C64ImagePC64 Freezer Image =Ã%bitmapFBM image data=Ä1, mono=Å3, color =:PKPKZip multi-volume archive data, at least PKZIP v2.50 to extractapplication/zip =‡PS-X EXESony Playstation executablexq‰(%s) =žCrshDumpIRIX vmcore dump of>$Ÿ'%s' =dNJPL1I00PDS (JPL) image data =iLBLSIZE=PDS (VICAR) image data =ä SMJPEGSMJPEGxå%d.x data=ê_SND,>ë%d Hz=ì8-bit=í16-bit=îNONEuncompressed=ðmono=ñstereo= ó_VID,>(õ%d frames>,ö(%d x>.÷%d)=ø_VID,>ú%d frames>û(%d x>ü%d) =0ÿÿÿÿOS/2 INI@= BSDIFF40bsdiff(1) patch file =C«‘g˜Webshots Desktop .wbz file =CKD_P370Hercules CKD DASD image filex, %d heads per cylinderx , track size %d bytesx, device type 33%2.2X =›-rom1fs-romfs filesystem, version 1xœ%d bytes,xnamed %s. =CKD_C370Hercules compressed CKD DASD image filex, %d heads per cylinderx , track size %d bytesx, device type 33%2.2X = CKD_S370Hercules CKD DASD shadow filex!, %d heads per cylinderx ", track size %d bytesx#, device type 33%2.2X =GOOF----Guile Object= LE, little endian= BE, big endian= 4, 32bit= 8, 64bit= ..., bytecode v%s =%XDZ000%XDelta binary patch file 0.18 =%XDZ001%XDelta binary patch file 0.20 = %XDZ002%XDelta binary patch file 1.0 = %XDZ003%XDelta binary patch file 1.0.4 =w‰HDF  Hierarchical Data Format (version 5) dataapplication/x-hdf =ºHDMV0100AVCHD Clip Information =ª@_wå‚ PAQ archive data = DrawFileIslandDraw document = NqNqNq`QL firmware executable (BCPL) = %XDZ004%XDelta binary patch file 1.1 =@ Microsoft Excel Worksheetapplication/vnd.ms-excel =KarmaRHDVersion Karma Data Structure Versionx %lu =‘WINIMAGEWinImage archive data =4ýReIsErFsReiserFS V3.5 =BÒ4f"ˆRADCOM WAN/LAN Analyzer capture file =@WordProLotus WordProapplication/vnd.lotus-wordpro =<BVokBDICBDicty PalmOS document>"%s" =<DB99DBOSDB PalmOS document>"%s" = LBLSIZE=VICAR image data= BYTE, 8 bits = VAX byte= HALF, 16 bits = VAX word = Fortran INTEGER*2= FULL, 32 bits = VAX longword = Fortran INTEGER*4= REAL, 32 bits = VAX longword = Fortran REAL*4= DOUB, 64 bits = VAX quadword = Fortran REAL*8= COMPLEX, 64 bits = VAX quadword = Fortran COMPLEX*8 =)@8tz3 ms-works file =†¸ÀŽØ¸Linux= ñ‡x86 boot sector=ˆŽof a kernel from the dawn of time!=‰´ØŽÿÿÿÿversion 0.99-1.1.42=Š¸ØŽÿÿÿÿfor memtest86! ñŒx86 kernel> øRAMdisksize=%u KB> öŽswap=0x%X> üroot=0x%X= ò-ro= ò‘-rw= ú’ÿÿÿÿÿÿÿÿvga=normal= ú“þÿÿÿÿÿÿÿvga=extended= ú”ýÿÿÿÿÿÿÿvga=ask> ú•vga=%d=–ØŽÿÿÿÿversion 1.1.43-1.1.45=—Ͳ=Ž ˜ZZªUversion 1.1.46-1.2.13,1.3.0=™ ™ZZªUversion 1.3.1,2=£ šZZªUversion 1.3.3-1.3.30=¦ ›ZZªUversion 1.3.31-1.3.41=+ œZZªUversion 1.3.42-1.3.45=÷ ZZªUversion 1.3.46-1.3.72=žHdrS> Ÿÿ= , zImage=¡, bzImage> ¢, version %s =*@8tz3 ms-works file =< vIMGViewFireViewer/ImageViewer PalmOS document>!"%s" = ESTFBINREST flat binary =¹² tClaris works dictionary =+@8tz3 ms-works file =xFSdump0xfsdump archivex(version %d) =þLVM2 001LVM2 PV (Linux Logical Volume Manager)x ôÿÿÿ!>/, UUID: %.6s>/-%.4s> /-%.4s>/-%.4s>/-%.4s>/-%.4s> /-%.6sx , size: %lld = LVM2 001LVM2 PV (Linux Logical Volume Manager)x ôÿÿÿ! >/, UUID: %.6s>/-%.4s> /-%.4s>/-%.4s>/-%.4s>/-%.4s>/-%.6sx , size: %lld =LVM2 001LVM2 PV (Linux Logical Volume Manager)x ôÿÿÿ!>/, UUID: %.6s>/-%.4s> /-%.4s>/-%.4s>/-%.4s> /-%.4s>!/-%.6sx ", size: %lld =$LVM2 001LVM2 PV (Linux Logical Volume Manager)x ôÿÿÿ!%>'/, UUID: %.6s>(/-%.4s> )/-%.4s>*/-%.4s>+/-%.4s>,/-%.4s>-/-%.6sx ., size: %lld = conectixMicrosoft Disk Image, Virtual Server or Virtual PC =<"PmDBPmDBHanDBase PalmOS document>#"%s" =<$InfoINDBInfoView PalmOS document>%"%s" =E¬ËºõZFS shapshot (little-endian machine),x Fversion %lu,= Gtype: NONE,= Htype: META,= Itype: ZFS,= Jtype: ZVOL,= Ktype: OTHER,= Ltype: ANY,> Mtype: UNKNOWN (%lu),x/Ndestination GUID: %02Xx.O%02Xx-P%02Xx,Q%02Xx+R%02Xx*S%02Xx)T%02Xx(U%02X,>0V>4Wx7Xsource GUID: %02Xx6Y%02Xx5Z%02Xx4[%02Xx3\%02Xx2]%02Xx1^%02Xx0_%02X,>8`name: '%s' =<&ToGoToGoiSilo PalmOS document>'"%s" =<(JfDbJBasJFile PalmOS document>)"%s" =<*JfDbJFilJFile Pro PalmOS document>+"%s" =<,DATALSdbList PalmOS document>-"%s" = tGERBILDBFirst Choice database =ïÍ«Erlang DETS file =<.Mdb1Mdb1MobileDB PalmOS document>/"%s" =þPBC  Parrot bytecodex@ %d.xH %d,> %d byte words,= little-endian,= big-endian,= IEEE-754 8 byte double floats,= x86 12 byte long double floats,= IEEE-754 16 byte long double floats,= MIPS 16 byte long double floats,= AIX 16 byte long double floats,= 4-byte floats,x(Parrot %d.x0%d.x8%d =zBOMStoreMac OS X bill of materials (BOM) file =<0PNRdPPrsPeanutPress PalmOS document>1"%s"@= #! rnewsbatched news textmessage/rfc822 =4!! profiling data file =<2DataPlkrPlucker PalmOS document>3"%s" =3ElfFileMS Windows Vista Event Logx *4, %d chunksx 5 (no. %d in use)> 6, next record no. %d= 7, empty& x8, DIRTY& x9, FULL =<4DataSprdQuickSheet PalmOS document>5"%s" =<bBOOKMOBIMobipocket E-book>c"%s" =<DToRaTRPWTomeRaider PalmOS document>E"%s" =<6SM01SMemSuperMemo PalmOS document>7"%s" =<8TEXtTlDcTealDoc PalmOS document>9"%s" =y!MKS Spell hash list (old format) =e]ŒTSComp archive data =ÇCPQRFBLOCompaq/HP RILOE floppy image =ssh-rsa OpenSSH RSA public key =ssh-dss OpenSSH DSA public key =<BTdatTideTides PalmOS document>C"%s" =<@dataTDBPThinkDB PalmOS document>A"%s" = 4 Mathematica version 2 notebook =@ì_BHRfS_MBTRFS Filesystem>+í(label "%s",x îsectorsize %d,x ”ïnodesize %d,x ˜ðleafsize %d) =!Synth4.0Synthesis Module sound file =DMayaFOR4Alias Maya Binary File,> Eversion %s scene = 4 Mathematica version 2 notebook =<:InfoTlIfTealInfo PalmOS document>;"%s" =BMAYAFOR4Alias Maya Binary File,> Cversion %s scene =¡archiveRISC OS archive (ArcFS format) =¢ArchiveRISC OS archive (ArcFS format) =nRootHangul (Korean) Word Processor File 2000application/x-hwp =(*^ ::[ Mathematica notebook version 2.x ="(*^ ::[ Mathematica notebook version 2.x =Ê@MSCFMicrosoft Cabinet archive dataapplication/vnd.ms-cab-compressedx Ì, %u bytes= Í, 1 file> Î, %u files =<<DataTlMlTealMeal PalmOS document>="%s" =2SINCLAIRSpectrum .SCL Betadisk image ='õºË¬ZFS shapshot (big-endian machine),x(version %lu,= )type: NONE,= *type: META,= +type: ZFS,= ,type: ZVOL,= -type: OTHER,= .type: ANY,> /type: UNKNOWN (%lu),x(0destination GUID: %02Xx)1%02Xx*2%02Xx+3%02Xx,4%02Xx-5%02Xx.6%02Xx/7%02X,>08>49x0:source GUID: %02Xx1;%02Xx2<%02Xx3=%02Xx4>%02Xx5?%02Xx6@%02Xx7A%02X,>8Bname: '%s' =×@MSCEMicrosoft WinCE install header= Ø, architecture-independent= Ùg, Hitachi SH3= Úh, Hitachi SH4= Û , StrongARM= Ü , MIPS R4000= Ý', Hitachi SH3= Þ', Hitachi SH3E= ß', Hitachi SH4= àq, ARM 7TDMI= 4á, 1 file> 4â, %u files= 8ã, 1 registry entry> 8ä, %u registry entries =;@ÐÏࡱáMicrosoft Office Document=">bjbjMicrosoft Word Documentapplication/msword="@jbjbMicrosoft Word Documentapplication/msword =AMANDA: AMANDA =TAPESTART DATEtape header file,=X> Unused %s> DATE %s= FILE dump file,> DATE %s =<>DataTlPtTealPaint PalmOS document>?"%s" =%ZXTape!Spectrum .TZX datax&version %dx '.%d =Caml1999OCaml=Xexec file=Iinterface file (.cmi)=Oobject file (.cmo)= Alibrary file (.cma)= Ynative object file (.cmx)= Znative library file (.cmxa)= Mabstract syntax tree implementation file= Nabstract syntax tree interface file> (Version %3.3s) =ÚDAAPowerISO Direct-Access-Archive =/DOSEMU= ~0Uªÿÿÿÿÿÿ=2€ =3DOS Emulator image> 4, %u heads> 5, %d sectors/track> 6, %d cylinders =LxD 203Linuxdoom savex , name=%sx,!, world=%s =O@pkBGIBorland device >P%s =I@PKBGIBorland font >J%s =C64FilePC64 Emulator file>"%s" =l5 LimboQuake I save: hip3m3 Limbo = !b.out archive=  __.SYMDEFrandom library = BLENDERBlender3D,= _saved as 32-bits= vlittle endianx with version %c.x %cx %c=@GLOB.x X%.4d=Vbig endianx with version %c.x %cx %c=@GLOB.xX%.4d=-saved as 64-bits=vlittle endianx with version %c.x %cx %c=DGLOB.x `%.4d=Vbig endianx with version %c.x !%cx "%c=D#GLOB.x`$%.4d =<>BBx= indexed file= serial file= keyed file= (sort)= programx(LEVEL %d)>psaved=mkeyed file= (sort)=(mkey) =BagpipeBagpipe= ReaderReader> (version %.3s)=  Music WriterMusic Writer= :> (version %.3s)=GoldGold=:>(version %.3s) =«ˆNOA NOA Nancy Codec Movie file =”ExtremeExtreme Tracker AMS Module v1.3 =“AMShdrVelvet Studio AMS Module v2.2 =:Start:-GeoSwatch auf text file =i$@MID@$elog journal entry =‹RDC-megMegaDots >Œ/version %c> /.%c file =y.RMFRealMedia fileapplication/vnd.rn-realmedia =ÆIMGfileCIS compimg HP Bitmapfile =EZD_MAPNEWEZD Electron Density Map =archive =archive (big format) = **ACE**ACE archive data> version %d= , from MS-DOS=, from OS/2=, from Win/32=, from Unix=, from MacOS=, from WinNT=, from Primos=, from AppleGS=, from Atari= , from Vax/VMS= , from Amiga= , from Nextx, version %d to extract& €, multiple volumes,x (part %d),& , contains comment& , sfx& , small dictionary& , multi-volume&  , contains AV-String=!*UNREGISTERED VERSION*(unregistered)& " , with recovery record& #@, locked& $€ÿÿÿÿÿÿ, solid =/PCD_IPIKodak Photo CD image pack file=0, landscape mode=1, portrait mode=2, landscape mode=3, portrait mode =i@B000FF Windows Embedded CE binary image =3DOSFONTDOSFONT2 encrypted font data =4PCD_OPAKodak Photo CD overview pack file =fCCSD3ZFPDS (CCSD) image data =²ZZZZZ3DO "Opera" file system =.SYSTEMSHARC architecture file =.systemSHARC architecture file =øé,JAM JAM archive,>ùversion %.4s=&ú'->+ûlabel %.11s,x 'üserial %08x,>6ýfstype %.8s =/LOCATEGNU findutils locate database data>0, format %s=102 (frcode) =]!current ar archiveapplication/x-archive= ___.SYMDEFrandom library=`- pre SR9.5=a- post SR9.5=b- object archive=c- shared library module=d- debug break-pointed module=e- absolute code program module =“CMP0CMPCompressia archive data =StuffItStuffIt Archiveapplication/x-stuffitSIT@= # Magicmagic text file for file(1) cmd =@PHILIPPPar archive data@= Pipe tomail piping textmessage/rfc822@= Articlesaved news textmessage/news = MVR4 IMapleVr4 library = kbd!mapkbd map file> Ver %d:> with %d table(s) =7BEAM!Old Erlang BEAM file> - version %d =GSTImGNU SmallTalk= LE image versionx %d.x %d.x %d=BE image versionx%d.x %d.x %d =ÜDSIGDCCCrossePAC archive data =ÃJRchiveJRC archive data =5RS-IDESpectrum .HDF hard disk imagex6, version 0x%02x =³bplistx´CoreFoundation binary property list data, version 0x%cxµ%c=¶00=·ðÿÿÿÿÿÿÿ=¸, root type: null=¹, root type: false boolean=º , root type: true boolean=»ðÿÿÿÿÿÿÿ, root type: integer=¼ðÿÿÿÿÿÿÿ , root type: real=½ðÿÿÿÿÿÿÿ0, root type: date=¾ðÿÿÿÿÿÿÿ@, root type: data=¿ðÿÿÿÿÿÿÿP, root type: ascii string=Àðÿÿÿÿÿÿÿ`, root type: unicode string=Áðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, root type: uid (CORRUPT)=Âðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, root type: array=ÃðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, root type: dictionary = = ¡=¢BOpenVMS backup saveset datax (£(block size %d,>1¤original name '%s',=¥VAX generated)=¦AXP generated)=§I64 generated) =q¨= Stirling Technologies,InstallShield Uninstall Script =!pmviewPCP pmview config="Version>#(V%-3.3s) =$X imprSoftQuad troff Context intermediate for IMAGEN imPRESS =1 Version %s='iHP-100[H Series]@=@ //MayaASCII Alias Maya Ascii File,> Aversion %s =submscMessage Sequence Chart (subchart) = $SuiteTTCN Abstract Test Suite= $SuiteId> %s= $SuiteId> %s=$SuiteId> %s =vGERBILFirst Choice device file =áClaris Works pallete files .plt =»7z¼¯'7-zip archive data,x¼version %dx½.%dapplication/x-7z-compressed =RuneCTCitrus locale declaration for LC_CTYPE =ptabPower-Tab v4 Tablature File = ZyXELZyXEL voice data= - CELP encoding= - ADPCM2 encoding=  - ADPCM3 encoding=  - ADPCM4 encoding=  - New ADPCM3 encoding= with resync =ptabPower-Tab v3 Tablature File = {titleChord text file =ó@Û¥-Microsoft Office Documentapplication/msword =sAC1015AutoDesk AutoCAD R2000 =rAC1014AutoDesk AutoCAD R14 =qAC1012AutoDesk AutoCAD R13 =@AC1024DWG AutoDesk AutoCAD 2010/2011 =?AC1021DWG AutoDesk AutoCAD 2007/2008/2009 =>AC1018DWG AutoDesk AutoCAD 2004/2005/2006 =8AC1014DWG AutoDesk AutoCad (release 14) =7AC1013DWG AutoDesk AutoCad (release 13) =6AC1012DWG AutoDesk AutoCad (release 12) =CBMdPower 64 C64 Emulator Snapshot =1cscopecscope reference datax2version %.2s>714= 8d -q with inverted index= 9d -c text (non-compressed) = MythTVMythTV NuppelVideox v%sx (%dx x%d),=$Pprogressive,=$Iinterlaced,x&(aspect:%.2f,x&0fps:%.2f =%TGIF Tgif file versionx%s =6[licq]LICQ configuration file =!MDMP“§MDMP crash report data =ofTAZ!eXtra Simple Music = NuFileNuFile archive (apple ][) data = NõFélåNuFile archive (apple ][) data =_LM8953Yamaha TX Wave=`Ilooped=aÉÿÿÿÿÿÿÿnon-looped=b33kHz=c50kHz=d16kHz =ÿCROMFSCROMFS> version %2.2s,> block data at %lld,> fblock table at %lld,> inode table at %lld,>  root at %lld,> ( fblock size = %ld,> , block size = %ld,>0 bytes = %lld =>SB2100SeaBeam 2100 multibeam sonar =*HSP›OS/2 INF>k+0(%s) =,HSP›OS/2 HLP>k-0(%s) =*BEGINApplixware=WORDSWords Document= GRAPHICSGraphic= RASTERBitmap=  SPREADSHEETSSpreadsheet= MACROMacro= BUILDERBuilder Object = ustarPOSIX tar archiveapplication/x-tar =€MMXPRaMotorola Quark Express Document (Korean) =#070707ASCII cpio archive (pre-SVR4 or odc) =$070701ASCII cpio archive (SVR4 with no CRC) =%070702ASCII cpio archive (SVR4 with CRC) =zGIF94zZIF image (GIF+deflate alpha)image/x-unknown =FGF95aFGF image (GIF+deflate beta)image/x-unknown =~MMXPR3Motorola Quark Express Document (English)application/x-quark-xpress-3 =¼VCLMTFStarView MetaFilex½, version %dx¾, size %d =}IIXPRaIntel Quark Express Document (Korean) =eNJPL1IPDS (JPL) image data =gCCSD3ZPDS (CCSD) image data =ÎP7 332XV thumbnail image data =P7 332XV "thumbnail file" (icon) data =}XARA££Xara graphics file =†@EJLEpson ESC/Page language printer data =avaobjAVR assembler object code>version '%s' =|IIXPR3Intel Quark Express Document (English)@= # xmcdxmcd database file for kscdtext/x-xmcd =<rµJ†Linux/i386 PC Screen Font v2 data,x =%d characters,= >no directory,! ?Unicode directory,x @%dx Ax%d =FCS3.0Flow Cytometry Standard (FCS) data, version 3.0 =uTPACTPac archive data =ALUKSº¾LUKS encrypted file,xBver %dxC[%s,x(D%s,xHE%s]x¨FUUID: %s =FCS2.0Flow Cytometry Standard (FCS) data, version 2.0 =FCS1.0Flow Cytometry Standard (FCS) data, version 1.0 =LUKSº¾LUKS encrypted file,x ver %dx [%s,x( %s,xH %s]x¨ UUID: %s =<žnrvÿNRV archive data =# daubMaple help file, old style =$‘Maple worksheet = OctSquSquash archive data =ôFOXSQZFoxSQZ archive data =.MCAD Mathcad document =à¨MP¨KBoom archive data =b0VIM Vim swap file>, version %s =ÖLEOLZWPAKLeo archive data =AMATLABMatlab v5 mat-file=~BMI(big endian)x|Cversion 0x%04x=~DIM(little endian)x |Eversion 0x%04x =7HP-UX=8= 9<=L:=X;D= <=¬==°>=´?core file >@from '%s' =ÄA- received SIGQUIT =ÄB- received SIGILL =ÄC- received SIGTRAP =ÄD- received SIGABRT =ÄE- received SIGEMT =ÄF- received SIGFPE =ÄG - received SIGBUS =ÄH - received SIGSEGV =ÄI - received SIGSYS =ÄJ!- received SIGXCPU =ÄK"- received SIGXFSZ=LM=XN=\O=`P=lQD=´Rcore file >¤Sfrom '%s' =ÄT- received SIGQUIT =ÄU- received SIGILL =ÄV- received SIGTRAP =ÄW- received SIGABRT =ÄX- received SIGEMT =ÄY- received SIGFPE =ÄZ - received SIGBUS =Ä[ - received SIGSEGV =Ä\ - received SIGSYS =Ä]!- received SIGXCPU =Ä^"- received SIGXFSZ =dvHP-UX=w= xD=Ty=`z<= {=¬|=°}=´~core file >Dfrom '%s' =Ä€- received SIGQUIT =Ä- received SIGILL =Ä‚- received SIGTRAP =ă- received SIGABRT =Ä„- received SIGEMT =Ä…- received SIGFPE =Ć - received SIGBUS =ć - received SIGSEGV =Ĉ - received SIGSYS =ĉ!- received SIGXCPU =ÄŠ"- received SIGXFSZ =xŒHP-UX== Ž=== ‘D=h’=t“<=´”core file >X•from '%s' =Ä–- received SIGQUIT =Ä—- received SIGILL =Ę- received SIGTRAP =Ä™- received SIGABRT =Äš- received SIGEMT =Ä›- received SIGFPE =Äœ - received SIGBUS =Ä - received SIGSEGV =Äž - received SIGSYS =ÄŸ!- received SIGXCPU =Ä "- received SIGXFSZ=¢= £D=T¤=`¥=d¦=h§=t¨,=´©core file >Dªfrom '%s' =Ä«- received SIGQUIT =Ĭ- received SIGILL =Ä­- received SIGTRAP =Ä®- received SIGABRT =į- received SIGEMT =İ- received SIGFPE =ı - received SIGBUS =IJ - received SIGSEGV =ij - received SIGSYS =Ä´!- received SIGXCPU =ĵ"- received SIGXFSZ =<RINEX=P XXRINEXBRINEX Data, GEO SBAS Broadcastx , date %15.15sx , version %6.6srinex/broadcast=P XXRINEXDRINEX Data, Observation (Hatanaka comp)x , date %15.15sx, version %6.6srinex/observation=PXXRINEXCRINEX Data, Clockx , date %15.15sx, version %6.6srinex/clock=PXXRINEXHRINEX Data, GEO SBAS Navigationx , date %15.15sx, version %6.6srinex/navigation=PXXRINEXGRINEX Data, GLONASS Navigationx , date %15.15sx, version %6.6srinex/navigation=PXXRINEXLRINEX Data, Galileo Navigationx , date %15.15sx, version %6.6srinex/navigation=P!XXRINEXMRINEX Data, Meteorologicalx ", date %15.15sx#, version %6.6srinex/meteorological=P%XXRINEXNRINEX Data, Navigation x &, date %15.15sx', version %6.6srinex/navigation=P)XXRINEXORINEX Data, Observationx *, date %15.15sx+, version %6.6srinex/observation =+PK=[Content_Types].xml= 1ÐPK=èPK=word/Microsoft Word 2007+application/msword=ppt/Microsoft PowerPoint 2007+application/vnd.ms-powerpoint=xl/Microsoft Excel 2007+application/vnd.ms-excelx Microsoft OOXML@= ¤ifrom '%s' =Äj- received SIGQUIT =Äk- received SIGILL =Äl- received SIGTRAP =Äm- received SIGABRT =Än- received SIGEMT =Äo- received SIGFPE =Äp - received SIGBUS =Äq - received SIGSEGV =Är - received SIGSYS =Äs!- received SIGXCPU =Ät"- received SIGXFSZ =/EMODAmiga E module =0ECXMECX module =o65o65= executable,= object,xversion %d,= €ÿÿÿÿÿÿ€ÿÿÿÿÿÿ65816,= €ÿÿÿÿÿÿ6502,=  32 bit,=  16 bit,= @@page reloc,= @byte reloc,= alignment 1= alignment 2= alignment 4= alignment 256 =IBiff5Microsoft Excel 5.0 Worksheetapplication/vnd.ms-excel =BÿBiff5Microsoft Excel 5.0 Worksheetapplication/vnd.ms-excel =î@PO^Q`Microsoft Word 6.0 Documentapplication/msword =ñHVQM4%s>òv%sxóGameCube movie,x4ô%d xx6õ%d,x&ö%dµs,=B÷no audio>Bø%dHz audio =¨@¸þLÍ!COM executable (COM32R) =„Netscape folder cache =!PVF2 portable voice format>"(ascii %s) =PVF1 portable voice format>(binary %s) =KO====AppleWorks word processor data>UL, zoomed>ZM, paginated>\N, with mail merge =w\1cw ChiWriter file>xversion %s =«CRUSHCrush archive data =­HLSQZSqueeze It archive data =¯SQWEZSQWEZ archive data =ÞŸJ Freeze archive data =lSHCC3MS Windows 3.1 registry file =ìZPKZPack archive data =TRd"nettl" capture file =!ULEB RAX archive data =#ULEBXtreme archive data =$CoreAlpha COFF format core dump (Digital UNIX)>%, from '%s' ="CoreAlpha COFF format core dump (Digital UNIX)>#, from '%s' =%@âPack Magic archive data ='*mbx*MBX mail folder@= BABYLEmacs RMAIL text@= From:news or mail textmessage/rfc822@= Xref:news textmessage/news@= Path:news textmessage/news =WARC/WARC Archivexversion %.4sapplication/warc =%PDF-PDF documentapplication/pdfx , version %cx .%c =ëPGDMPPostgreSQL custom database dumpxì- v%dxí.%d<î-0>ïxð-%d =%FDF-FDF documentx, version %cx.%c =\rootROOT filex]Version %dx!^(Compression: %d) =ZChfLZChiefLZA archive data =\BlinkBlink archive data = llvc2LLVM byte-codes, bzip2 compression = llvc1LLVM byte-codes, gzip compression = llvc0LLVM byte-codes, null compression =bAKT32AKT32 archive data =$COSOHippel-COSO Module sound file =wAiAi archive data =xAiAi archive data =#BeEpJamCracker Module sound file =¥xpaXPA32 archive data =­à jmXPack single archive data = %.3s =~%!VMFSunClock's Vector Map Format data =¿ZZ ZZip archive data =ÇPFS1 PFS HDR image data=É[0-9]* , %s= Ê [0-9]{4}x%s =ÇJarJAR (ARJ Software, Inc.) archive data =¦IIO2HUlead Photo Explorer5 =ÈJARCSJAR (ARJ Software, Inc.) archive data =žÿOÿQJPEG-2000 Code Stream Bitmap data =šÿ ÿ¨Wavelet Scalar Quantization image data =-lh0-LHarc 1.x/ARX archive data [lh0]application/x-lharc =-lh1-LHarc 1.x/ARX archive data [lh1]application/x-lharc =-lz4-LHarc 1.x archive data [lz4]application/x-lharc =-lz5-LHarc 1.x archive data [lz5]application/x-lharc =€ÔCD001#application/x-iso9660-image!˜ÖNSR0ISO 9660 CD-ROM filesystem data=˜×NSR0UDF filesystem data=˜Ø1(version 1.0)=˜Ù2(version 1.5)=˜Ú3(version 2.0)>˜Û3(unknown version, ID 0x%X)<˜Ü1(unknown version, ID 0x%X)>(€Þ'%s'=ˆßCD001EL TORITO SPECIFICATION(bootable) =“àCD001ISO 9660 CD-ROM filesystem data (raw 2352 byte sectors)application/x-iso9660-image = -lzs-LHa/LZS archive data [lzs]application/x-lha = -lh -LHa 2.x? archive data [lh ]application/x-lha = -lhd-LHa 2.x? archive data [lhd]application/x-lha =-lh2-LHa 2.x? archive data [lh2]application/x-lha =%MSVC .sbr>&%s =-lh3-LHa 2.x? archive data [lh3]application/x-lha =-lh4-LHa (2.x) archive data [lh4]application/x-lha =-lh5-LHa (2.x) archive data [lh5]application/x-lha =-lh6-LHa (2.x) archive data [lh6]application/x-lha =-lh7-LHa (2.x)/LHark archive data [lh7]application/x-lhax- header level %d =-sw1-Swag archive data =Ø-pm0-PMarc archive data [pm0] =PACKGit pack>, version %d>, %d objects =ºBEGMFclear text Computer Graphics Metafile =Ù-pm1-PMarc archive data [pm1] =Ú-pm2-PMarc archive data [pm2] =Û-pms-PMarc SFX archive (CP/M, DOS) =³¡"AFS DumpxŽ(v%d)=vxVol %d,=‘nx’%s=“t=”x •on: %s= –full dump! —incremental since: %s =Ü-pc1-PopCom compressed executable (CP/M) =*sfArksfArk compressed Soundfont=+2>,Version %s>*-: %s =FONTRISC OS 4bpp font dataxversion %d ={\rtfRich Text Format data,text/rtf= 1version 1,= \ansiANSI= \macApple Macintosh= \pcIBM PC, code page 437=\pcaIBM PS/2, code page 850xunknown character setxunknown version ="X 495SoftQuad troff Context intermediate for AT&T 495 laser printer =mMAP (Old EZD Electron Density Map =(Š€3b2 core file>l)of '%s' =FONTRISC OS 1bpp font data,xversion %d =FONTRISC OS outline font data,xversion %d =eMSTSMNPack archive data =€âCDROMHigh Sierra CD-ROM filesystem data =ï%%HP:HP text=ðT(0)- T(0)=ñT(1)- T(1)=òT(2)- T(2)=óT(3)- T(3)= ôA(D)A(D)= õA(R)A(R)= öA(G)A(G)=÷F(.)F(.);=øF(,)F(,); =‡MAS_UULT(imate) Module sound data =ëTiEmuTiEmu skin=ìv- Version>í %cx î.%cx ï%c = LMGD77MGD77 Header, Marine Geophysical Data Exchange Format =GGSF-vSAIC generic sensor format (GSF) sonar data,= H[0-9]*.[0-9]*version %s =2NESMNES Sound File>3("%s" by>.4%s, copyright>N5%s),x6version %d,x7%d tracks,=z8dual PAL/NTSC=z9PAL=z:NTSC =BONKBONK,x%d channel(s),=lossless,=lossy,xmid-side =o#!AMRAdaptive Multi-Rate Codec (GSM telephony) ='#!BPYBlender3D BPython script =esnoopSnoop capture file>f- version %ld= g(IEEE 802.3)= h(IEEE 802.4)= i(IEEE 802.5)= j(IEEE 802.6)= k(Ethernet)= l(HDLC)= m(Character synchronous)= n(IBM channel-to-channel adapter)= o(FDDI)= p (Unknown) =-LH1-LHA archive (c64) = AC101AutoCAD= 2DWG ver. R13= 4DWG ver. R14 =ÿÿÿÿClaris clip art?= yes. =ÿÿÿÿClaris clip art?= yes. =UZendPHP script Zend Optimizer data =Ò-afx-AFX compressed file data =:TrueType font dataapplication/x-font-ttf =D1.0 X11 Speedo font data =¹PPF30Playstation Patch File version 3.0=º, PPF 1.0 patch=», PPF 2.0 patch=¼, PPF 3.0 patch=8½, Imagetype BIN (any)=8¾, Imagetype GI (PrimoDVD)=9¿, Blockcheck disabled=9À, Blockcheck enabled=:Á, Undo data not available=:Â, Undo data availablexÃ, description: %s =ÅPPF20Playstation Patch File version 2.0=Æ, PPF 1.0 patch=Ç, PPF 2.0 patch> 8È, size of file to patch %dxÉ, description: %s =ËPPF10Playstation Patch File version 1.0=Ì, Simple EncodingxÍ, description: %s =L@$RBU=MDell%s system BIOS=Nx0Oversion %d.x1P%d.x2Q%d<Rx0Sversion %.3s = ŽL= Windows shortcut file = ¹úñ= Universal EFI binary with 1 architecture= , i386= , x86_64=  Universal EFI binary with 2 architectures= , i386= , x86_64=  , i386= , x86_64> Universal EFI binary with %ld architectures = ]= ^ Windows Recycle Bin INFO2 file (Win2k - WinXP) = Z= [Windows Recycle Bin INFO2 file (Win98 or below) =K=LJVT NAL sequence, H.264 video=MB, baseline=NM, main=OX, extendedxP @ L %u =Qÿÿÿÿÿÿÿ=RºÿÿÿÿÿÿÿMPEG sequencevideo/mpeg&T@, v2, program multiplex^U@, v1, system multiplex=V»ÿÿÿÿÿÿÿMPEG sequence, v1/2, multiplex (missing pack header)=WMPEG sequence, H.264 video=XB, baseline=YM, main=ZX, extendedx[ @ L %u=\°ÿÿÿÿÿÿÿMPEG sequence, v4video/mpeg4-generic=^µ& _€ÿÿÿÿÿÿÿ= `ðÿÿÿÿÿÿÿ, video= aðÿÿÿÿÿÿÿ , still texture= bðÿÿÿÿÿÿÿ0, mesh= cðÿÿÿÿÿÿÿ@, face= døÿÿÿÿÿÿÿ, video= eøÿÿÿÿÿÿÿ, still texture= føÿÿÿÿÿÿÿ, mesh= gøÿÿÿÿÿÿÿ , face=h, simple @ L1=i, simple @ L2=j, simple @ L3=k, simple @ L0=l, simple scalable @ L1=m, simple scalable @ L2=n!, core @ L1=o", core @ L2=p2, main @ L2=q3, main @ L3=r5, main @ L4=sB, n-bit @ L2=tQ, scalable texture @ L1=ua, simple face animation @ L1=vb, simple face animation @ L2=wc, simple face basic animation @ L1=xd, simple face basic animation @ L2=yq, basic animation text @ L1=zr, basic animation text @ L2={ÿÿÿÿÿÿÿ, hybrid @ L1=|‚ÿÿÿÿÿÿÿ, hybrid @ L2=}‘ÿÿÿÿÿÿÿ, advanced RT simple @ L!=~’ÿÿÿÿÿÿÿ, advanced RT simple @ L2=“ÿÿÿÿÿÿÿ, advanced RT simple @ L3=€”ÿÿÿÿÿÿÿ, advanced RT simple @ L4=¡ÿÿÿÿÿÿÿ, core scalable @ L1=‚¢ÿÿÿÿÿÿÿ, core scalable @ L2=ƒ£ÿÿÿÿÿÿÿ, core scalable @ L3=„±ÿÿÿÿÿÿÿ, advanced coding efficiency @ L1=…²ÿÿÿÿÿÿÿ, advanced coding efficiency @ L2=†³ÿÿÿÿÿÿÿ, advanced coding efficiency @ L3=‡´ÿÿÿÿÿÿÿ, advanced coding efficiency @ L4=ˆÁÿÿÿÿÿÿÿ, advanced core @ L1=‰Âÿÿÿÿÿÿÿ, advanced core @ L2=ŠÑÿÿÿÿÿÿÿ, advanced scalable texture @ L1=‹Òÿÿÿÿÿÿÿ, advanced scalable texture @ L2=ŒÓÿÿÿÿÿÿÿ, advanced scalable texture @ L3=áÿÿÿÿÿÿÿ, simple studio @ L1=Žâÿÿÿÿÿÿÿ, simple studio @ L2=ãÿÿÿÿÿÿÿ, simple studio @ L3=äÿÿÿÿÿÿÿ, simple studio @ L4=‘åÿÿÿÿÿÿÿ, core studio @ L1=’æÿÿÿÿÿÿÿ, core studio @ L2=“çÿÿÿÿÿÿÿ, core studio @ L3=”èÿÿÿÿÿÿÿ, core studio @ L4=•ðÿÿÿÿÿÿÿ, advanced simple @ L0=–ñÿÿÿÿÿÿÿ, advanced simple @ L1=—òÿÿÿÿÿÿÿ, advanced simple @ L2=˜óÿÿÿÿÿÿÿ, advanced simple @ L3=™ôÿÿÿÿÿÿÿ, advanced simple @ L4=šõÿÿÿÿÿÿÿ, advanced simple @ L5=›÷ÿÿÿÿÿÿÿ, advanced simple @ L3b=œøÿÿÿÿÿÿÿ, FGS @ L0=ùÿÿÿÿÿÿÿ, FGS @ L1=žúÿÿÿÿÿÿÿ, FGS @ L2=Ÿûÿÿÿÿÿÿÿ, FGS @ L3= üÿÿÿÿÿÿÿ, FGS @ L4=¡ýÿÿÿÿÿÿÿ, FGS @ L5=¢µÿÿÿÿÿÿÿMPEG sequence, v4video/mpeg4-generic&¤€ÿÿÿÿÿÿÿ=¥ðÿÿÿÿÿÿÿ, video (missing profile header)=¦ðÿÿÿÿÿÿÿ , still texture (missing profile header)=§ðÿÿÿÿÿÿÿ0, mesh (missing profile header)=¨ðÿÿÿÿÿÿÿ@, face (missing profile header)=©øÿÿÿÿÿÿÿ, video (missing profile header)=ªøÿÿÿÿÿÿÿ, still texture (missing profile header)=«øÿÿÿÿÿÿÿ, mesh (missing profile header)=¬øÿÿÿÿÿÿÿ , face (missing profile header)=­³ÿÿÿÿÿÿÿMPEG sequencevideo/mpeg= ¯¸, v1, progressive Y'CbCr 4:2:0 video= °², v1, progressive Y'CbCr 4:2:0 video= ±µ, v2,=² HP=³ Spt=´ SNR=µ MP=¶ SP=·ðÿÿÿÿÿÿÿ@@HL=¸ðÿÿÿÿÿÿÿ`@H-14=¹ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ@ML=ºðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ@LL&» progressive^¼ interlaced=½ Y'CbCr 4:2:0 video=¾ Y'CbCr 4:2:2 video=¿ Y'CbCr 4:4:4 video& À&KÁ=ŒÂ¸, v1, progressive Y'CbCr 4:2:0 video=ŒÃ², v1, progressive Y'CbCr 4:2:0 video=ŒÄµ, v2,=Å HP=Æ Spt=Ç SNR=È MP=É SP=‘Êðÿÿÿÿÿÿÿ@@HL=‘Ëðÿÿÿÿÿÿÿ`@H-14=‘Ìðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ@ML=‘Íðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ@LL&‘Î progressive^‘Ï interlaced=‘Ð Y'CbCr 4:2:0 video=‘Ñ Y'CbCr 4:2:2 video=‘Ò Y'CbCr 4:4:4 video=LÓ¸, v1, progressive Y'CbCr 4:2:0 video=LÔ², v1, progressive Y'CbCr 4:2:0 video=LÕµ, v2,=PÖ HP=P× Spt=PØ SNR=PÙ MP=PÚ SP=QÛðÿÿÿÿÿÿÿ@@HL=QÜðÿÿÿÿÿÿÿ`@H-14=QÝðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ@ML=QÞðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ@LL&Qß progressive^Qà interlaced=Qá Y'CbCr 4:2:0 video=Qâ Y'CbCr 4:2:2 video=Qã Y'CbCr 4:4:4 video=äÿÿÿÿÿÿÿ8x, HD-TV 1920P=åðÿÿÿÿÿÿÿ, 16:9=æÿÿÿÿÿÿÿ-P, SD-TV 1280I=çðÿÿÿÿÿÿÿ, 16:9=èÿÿÿÿÿÿÿ@0, PAL Capture=éðÿÿÿÿÿÿÿ, 4:3=êðÿÿÿÿÿÿÿ,, 4CIF=ëÿà NTSC=ìÿ@ PAL=íðÿÿÿÿÿÿÿ , 4:3=îðÿÿÿÿÿÿÿ0, 16:9=ïðÿÿÿÿÿÿÿ@, 11:5=ððÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, PAL 4:3=ñðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, NTSC 4:3=òÿÿÿÿÿÿÿà(, LD-TV 640P=óðÿÿÿÿÿÿÿ, 4:3=ôÿÿÿÿÿÿÿð, 320x240=õðÿÿÿÿÿÿÿ, 4:3=öÿÿÿÿÿÿÿ , 240x160=÷ðÿÿÿÿÿÿÿ, 4:3=øÿÿÿÿÿÿÿx , 160x120=ùðÿÿÿÿÿÿÿ, 4:3=úðÿÿÿÿÿÿÿ, CIF=ûÿð NTSC=üÿ  PAL=ýðÿÿÿÿÿÿÿ , 4:3=þðÿÿÿÿÿÿÿ0, 16:9=ÿðÿÿÿÿÿÿÿ@, 11:5=ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, PAL 4:3=ðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, NTSC 4:3=ÿ@ PAL 625=ðÿÿÿÿÿÿÿ , 4:3=ðÿÿÿÿÿÿÿ0, 16:9=ðÿÿÿÿÿÿÿ@, 11:5=ðÿÿÿÿÿÿÿ-, CCIR/ITU=ÿà NTSC 525=ÿ@ PAL 625= ðÿÿÿÿÿÿÿ , 4:3= ðÿÿÿÿÿÿÿ0, 16:9= ðÿÿÿÿÿÿÿ@, 11:5= ðÿÿÿÿÿÿÿ, SVCD= ÿà NTSC 525=ÿ@ PAL 625=ðÿÿÿÿÿÿÿ , 4:3=ðÿÿÿÿÿÿÿ0, 16:9=ðÿÿÿÿÿÿÿ@, 11:5=, 23.976 fps=, 24 fps=, 25 fps=, 29.97 fps=, 30 fps=, 50 fps=, 59.94 fps=, 60 fps& , Constrained =º&@video/mp2p^@video/mpeg =»video/mpeg = °video/mp4v-es ="µvideo/mp4v-es =$³video/mpv =&ÿ_ÿÿÿÿÿ@Gvideo/mp2t =(=)video/h264 = FOR1= BEAMErlang BEAM file =£ßE=B‚=webmWebMvideo/webm = £ßE= ‚B=matroskaMatroska datavideo/x-matroska(= =M<+pcap-ng capture filex - version %dx.%d(=  = M<+pcap-ng capture filex - version %dx  .%d = PAGE=!DUMPMS Windows 32bit crash dump=\", no PAE=\#, PAE= ˆ$, full dump= ˆ%, kernel dump= ˆ&, small dumpx h', %ld pages=(DU64MS Windows 64bit crash dump= ˜), full dump= ˜*, kernel dump= ˜+, small dumpx,, %lld pages =x‚=ƒtnfsMac OSX datafork font, TrueType=„TNOFMac OSX datafork font, 'FONT'=…TNFNMac OSX datafork font, 'NFNT'=†TSOPMac OSX datafork font, PostScript =#;ELC>$<% Emacs/XEmacs v%d byte-compiled Lisp dataapplication/x-elc =PK= =!doc.kmlCompressed Google KML Document, including resources.application/vnd.google-earth.kmz =dey =dey [0-9][0-9][0-9]Dalvik dex file (optimized for host)>000version %s =dex =dex [0-9][0-9][0-9]Dalvik dex file>000version %s =pJZJZ=qZZZenographics ZjStream printer data (big-endian) =rZJZJ=sZZZenographics ZjStream printer data (little-endian)(= ê=(ë EMFWindows Enhanced Metafile (EMF) image datax ,ìversion 0x%x =>PK=Dmimetypeapplication/=2Kvnd.kde.KOffice (>=1.2)=:LkarbonKarbon document=:MkchartKChart document=:NkformulaKFormula document=:OkivioKivio document=:PkontourKontour document= :QkpresenterKPresenter document=:RkspreadKSpread document=:SkwordKWord document= 2Wvnd.sun.xml.OpenOffice.org 1.x=>XwriterWriter!DY.document= DZ.templatetemplate=D[.globalglobal document=>\calcCalc!B].spreadsheet= B^.templatetemplate=>_drawDraw!B`.document= Ba.templatetemplate=>bimpressImpress!Ec.presentation= Ed.templatetemplate=>emathMath document=>fbaseDatabase file=2kvnd.oasis.opendocument.OpenDocument=Iltext!Mm-Textapplication/vnd.oasis.opendocument.text= Mo-templateText Templateapplication/vnd.oasis.opendocument.text-template=Mq-webHTML Document Templateapplication/vnd.oasis.opendocument.text-web=Ms-masterMaster Documentapplication/vnd.oasis.opendocument.text-master=Iugraphics!Qv-Drawingapplication/vnd.oasis.opendocument.graphics= Qx-templateTemplateapplication/vnd.oasis.opendocument.graphics-template= Izpresentation!U{-Presentationapplication/vnd.oasis.opendocument.presentation= U}-templateTemplateapplication/vnd.oasis.opendocument.presentation-template= Ispreadsheet!T€-Spreadsheetapplication/vnd.oasis.opendocument.spreadsheet= T‚-templateTemplateapplication/vnd.oasis.opendocument.spreadsheet-template=I„chart!N…-Chartapplication/vnd.oasis.opendocument.chart= N‡-templateTemplateapplication/vnd.oasis.opendocument.chart-template=I‰formula!PŠ-Formulaapplication/vnd.oasis.opendocument.formula= PŒ-templateTemplateapplication/vnd.oasis.opendocument.formula-template=IŽdatabaseDatabaseapplication/vnd.oasis.opendocument.database=Iimage!N‘-Imageapplication/vnd.oasis.opendocument.image= N“-templateTemplateapplication/vnd.oasis.opendocument.image-template=2šepub+zipEPUB ebook dataapplication/epub+zip!2£epub+zip!2¤vnd.oasis.opendocument.! 2¥vnd.sun.xml.!2¦vnd.kde.= &§[!-OQ-~]+Zip data (MIME type "%s"?)application/zip= ªmimetype! &«application/= &¬[!-OQ-~]+Zip data (MIME type "%s"?)application/zip! ±mimetypeZip archive dataapplication/zip=³ , at least v0.9 to extract=´ , at least v1.0 to extract=µ , at least v1.1 to extract=¶, at least v2.0 to extract=·-, at least v3.0 to extract=a¸WINZIP, WinZIP self-extracting =zPK={mimetypeapplication/epub+zipEPUB documentapplication/epub+zip =ãp=äGFS1 Filesystemx$å(blocksize %d,>`ælockproto %s)=ç GFS2 Filesystemx$è(blocksize %d,>`élockproto %s) =úXFSM=ûXFSBXFS filesystem metadump image = XFSM=XFSBXFS filesystem metadump image =€JFS1< JFS2 filesystem image= [ -~]{1,16}(label "%s")x , %lld blocksx !, blocksize %d> "(dirty)> $#(compressed) =¾ºþÊÿÿÿÿapplication/x-java-applet>compiled Java class data,xversion %d.x%d=.(Java 1.2)=/(Java 1.3)=0(Java 1.4)=1(Java 1.5)=2(Java 1.6) = ¾ºþÊÿÿÿÿ=!Mach-O fat file with 1 architecture>"<#Mach-O fat file with %ld architectures = Áÿÿÿ]= ÂÿLZMA compressed data,=Ãÿÿÿÿÿÿÿÿstreamed!Äÿÿÿÿÿÿÿÿnon-streamed, size %lldapplication/x-lzma = 4SpeedShop data file =ÌLRZILRZIP compressed dataxÍ- version %dxÎ.%dapplication/x-lrzip =…iHDLld.so hints file (Big Endian>†, version %d)<‡) =±PP20Power Packer 2.0 compressed data,=² fast compression=³ mediocre compression=´ good compression=µ very good compression=¶ best compression = &P„ÿÿÿÿPCP archivex(V.%d)=þÿÿÿÿÿÿÿtemporal index=ÿÿÿÿÿÿÿÿmetadata=log volume #0>log volume #%ld>host: %s =IDP2Quake II 3D Model file,x %lu skin(s),x (%lu xx %lu),x( %lu frame(s),x Frame size %lu bytes,x%lu vertices/frame,x%lu texture coordinates,x %lu triangles/frame =IBSPQuake=&II Map file (BSP)=.III Map file (BSP) =IDS2Quake II SP2 sprite file =°PP11Power Packer 1.1 compressed data =¯XPKFAmiga xpkf.library compressed data =%PACKQuake I or II world or extension> &, %d entries =*RZX!Spectrum .RZX datax+version %dx,.%d =QLZIPlzip compressed dataapplication/x-lzipxS, version: %d = ÿÿÿÿÿÿÿþþÿÿÿÿMySQL MISAM index filex Version %d = ÿÿÿÿÿÿÿþþÿÿÿÿMySQL MISAM compressed data filexVersion %d =ÿÿÿÿÿÿÿþþÿÿÿÿMySQL ISAM index filexVersion %d =ÿÿÿÿÿÿÿþþÿÿÿÿMySQL ISAM compressed data filexVersion %d =þbinMySQL replication log =MConvex old-style pre-paged executable>not stripped =AprofCLIPPER instruction profile =@pipeCLIPPER instruction trace = ÿÿÿ sparc demand paged& €ÿÿÿÿÿÿÿ< shared library= dynamically linked executable> dynamically linked executable^€ÿÿÿÿÿÿÿexecutable>not stripped =OConvex old-style pre-paged, non-swapped executable>not stripped =WCore file =ÿÿÿsparc pure&€ÿÿÿÿÿÿÿdynamically linked executable^€ÿÿÿÿÿÿÿexecutable>not stripped =ÿÿÿsparc&€ÿÿÿÿÿÿÿdynamically linked executable^€ÿÿÿÿÿÿÿexecutable>not stripped =ÿÿÿ mc68020 demand paged&€ÿÿÿÿÿÿÿ<shared library=dynamically linked executable>dynamically linked executable^ €ÿÿÿÿÿÿÿexecutable>!not stripped = ÿÿÿÿÿÿÿË…ÿÿÿÿcisco IOS experimental microcode> for '%s' = ÿÿÿÿÿÿÿ…ÿÿÿÿcisco IOS microcode> for '%s' =#ÿÿÿmc68020 pure&$€ÿÿÿÿÿÿÿdynamically linked executable^%€ÿÿÿÿÿÿÿexecutable>&not stripped =% ÐþÊÿÿÿÿJAR compressed with pack200,x&version %d.x'%dapplication/x-java-pack200 = ‚iHDLld.so hints file (Little Endian> ƒ, version %d)<„) =ÚRZIPrzip compressed dataxÛ- version %dxÜ.%dxÝ(%d bytes) =(ÿÿÿmc68020&)€ÿÿÿÿÿÿÿdynamically linked executable^*€ÿÿÿÿÿÿÿexecutable>+not stripped =mþ ÈÿÿÿÿBentley/Intergraph MicroStation DGN vector CAD =lþ Bentley/Intergraph MicroStation DGN vector CAD =kBentley/Intergraph MicroStation DGN cell library =-ÿÿÿ mc68010 demand paged&.€ÿÿÿÿÿÿÿ</shared library=0dynamically linked executable>1dynamically linked executable^2€ÿÿÿÿÿÿÿexecutable>3not stripped =5ÿÿÿmc68010 pure&6€ÿÿÿÿÿÿÿdynamically linked executable^7€ÿÿÿÿÿÿÿexecutable>8not stripped = 7b9mdbm file, version 0 (obsolete) =ÿLBÿÿÿÿÿWRAptor packer (c64) =:ÿÿÿmc68010&;€ÿÿÿÿÿÿÿdynamically linked executable^<€ÿÿÿÿÿÿÿexecutable>=not stripped =8mdbmmdbm file,x9version %d,x:2^%d pages,x;pagesize 2^%d,x<hash %d,x =dataformat %d = PSURARC archive (c64) = dACX64 Image = D(D81 Image =e €AD71 Image =eAD64 Image =@old sun-2 executable>Anot stripped =Bold sun-2 pure executable>Cnot stripped =D old sun-2 demand paged executable>Enot stripped =KVSunOS core file=L°(SPARC)>„Mfrom '%s'=tN(quit)=tO(illegal instruction)=tP(trace trap)=tQ(abort)=tR(emulator trap)=tS(arithmetic exception)=tT (kill)=tU (bus error)=tV (segmentation violation)=tW (bad argument to system call)=tX(resource lost)xxY(T=%dK,x|ZD=%dK,x€[S=%dK)=\:(68K)>€]from '%s'=^È(SPARC 4.x BCP)>˜_from '%s' =aŽÀ3úÿÿÿÿSunPC 4.0 Hard Disk =!kêdump format, 4.1 BSD or earlier =$vacspKodak Color Management System, ICC Profileapplication/vnd.iccprofile =„CRfsCOBALT boot rom data (Flat boot rom or file system) =>T707Roland TR-707 Data =i#LyXLyX document text =XIA1Chiasmus encrypted data ='ÿÿÿsparc&(€ÿÿÿÿÿÿÿdynamically linked executable^)€ÿÿÿÿÿÿÿexecutable>*not stripped=$+´ÿÿÿÿ(uses shared libs) =!ÿÿÿsparc pure&"€ÿÿÿÿÿÿÿdynamically linked executable^#€ÿÿÿÿÿÿÿexecutable>$not stripped=$%´ÿÿÿÿ(uses shared libs) =ÿÿÿ sparc demand paged&€ÿÿÿÿÿÿÿ<shared library=dynamically linked executable>dynamically linked executable^€ÿÿÿÿÿÿÿexecutable>not stripped=$´ÿÿÿÿ(uses shared libs) =  386 demand paged pure executable> not stripped= j(uses shared libs) = 386 pure executable> not stripped= j(uses shared libs) = 386 executable>  not stripped= j(uses shared libs) = Ì386 compact demand paged pure executable> not stripped= j(uses shared libs) = i960 b.out relocatable object>not stripped =68k Blit mpx/mux executable = kÿÿÿ̆FreeBSD/i386 compact demand paged< l&mÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿshared library=nÀÿÿÿÿÿÿÿ@PIC object=oÀÿÿÿÿÿÿÿobject> pÿ=q€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿdynamically linked executable=r€ÿÿÿÿÿÿÿexecutable> snot stripped =bFLTBFLT executablex - version %ld= =$ ram=$ gotpic=$ gzip=$gzdata =~wvpkWavPack Lossless Audio =yTTA1True Audio Lossless Audio =sSCgfSuperCollider3 Synth Definition file,xtversion %d =DISODelta ISO data,xversion %d =<jSONGSoundFX Module sound file =9ICE!SNDH Atari ST music = aÿÿÿ †FreeBSD/i386 demand paged< b&cÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿshared library=dÀÿÿÿÿÿÿÿ@PIC object=eÀÿÿÿÿÿÿÿobject> fÿ=g€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿdynamically linked executable=h€ÿÿÿÿÿÿÿexecutable> inot stripped =XAD!eXotic ADlib = SAdTSurprise! Adlib Trackerx Version %d =íMAC Monkey's Audio compressed formataudio/x-ape> ï‹version %d = ðèwith fast compression = ñÐwith normal compression = ò¸ with high compression = ó with extra high compression = ôˆwith insane compression= õ, mono= ö, stereox ÷, sample rate %d< øŒversion %d= ùèwith fast compression= úÐwith normal compression= û¸ with high compression= ü with extra high compression= ýˆwith insane compression= þ, mono= ÿ, stereox , sample rate %d =ÞRB40RBS Song file=ßReBorncreated by ReBorn= %àPropellerheadcreated by ReBirth =ÚVBOXVBOX voice message data =µfLaCFLAC audio bitstream dataaudio/x-flac>·, unknown version=¸=ºð0, 4 bit=»ðP, 6 bit=¼ðp, 8 bit=½ð°, 12 bit=¾ðð, 16 bit=¿ðp, 24 bit=À, mono=Á, stereo=Â, 3 channels=Ã, 4 channels=Ä, 5 channels=Å , 6 channels=Æ , 7 channels=Ç, 8 channels=Éðÿÿ@Ä , 44.1 kHz=Êðÿÿ¸ , 48 kHz=ËðÿÿÐ, 32 kHz=Ìðÿÿ b, 22.05 kHz=ÍðÿÿÜ, 24 kHz=Îðÿÿè, 16 kHz=Ïðÿÿ±, 11.025 kHz=Ððÿÿî, 12 kHz=Ñðÿÿô, 8 kHz=Òðÿÿp, 96 kHz=Óðÿÿ , 64 kHz>Ô, >4G samples=Õ>Ö, %u samples=×, length unknown =­MMMDYamaha SMAF file =¡RTMMRTM Module =ŸMT20MadTracker 2.0 Module MT2 =,PTMFPoly Tracker PTM Module>žTitle: "%s" =œPSMProtracker Studio PSM Module =›DMDLDigiTrakker MDL Module =šSONGDigiTrekker DTM Module =™DSMDynamic Studio Module DSM =•DDMFXtracker DMF Modulex–v%i> —Title: "%s">+˜Composer: "%s" =FTMNFaceTheMusic module>d, "%s" =ŠDBM0DIGI Booster Pro Module>‹V%X.xŒ%02X>, "%s" ={SymMSymphonie SymMOD music file =xMMD3OctaMED Soundstudio music file, version 3 =™IWADdoom main IWAD datax šcontaining %d lumps =›PWADdoom patch PWAD datax œcontaining %d lumps =wMMD1OctaMED Pro music file, version 1 =vMMD0MED music file, version 0 =­HM3WWarcraft III map file = PmNsPCP compiled namespace (V.0) =LiSCRSScream Tracker Sample=jsample=kadlib melody>ladlib drum&mstereo^nmono&o16bit little endian^p8bit=qunpacked=rpacked =YIMPIImpulse Tracker Instrument! ZITv%x![%d samples =TIMPSImpulse Tracker Sample&U16 bit^V8 bit&Wstereo^Xmono = ê0BALANCE NS32000 standalone executable> not stripped> |version %ld = Áƒ*žÿÿÿÿUnreal Engine Package,x version: %i! , names: %i! , imports: %i!  , exports: %i =gpchGCC precompiled headerx (version %cx %cx %c)=Cfor C=ofor Objective C=+for C++=Ofor Objective C++ = ê BALANCE NS32000 executable (invalid @ 0)> not stripped> |version %ld =<MIM10Imago Orpheus module sound data ->N"%s" =KEB Knudsen seismic KEL binary (KEB) -= [-A-Z0-9]*Software: %s= V[0-9]*.[0-9]*version %s = êBALANCE NS32000 executable (0 @ 0)>  not stripped> | version %ld = êBALANCE NS32000 .o>  not stripped> | version %ld =FIMPMImpulse Tracker module sound data -audio/x-mod>H"%s"! (Icompatible w/ITv%x! *Jcreated w/ITv%x ="lêdump format, 4.2 or 4.3 BSD without IDC =2BITAudio Visual Research file,= mono,= ÿÿÿÿÿÿÿÿstereo,x%d bits=unsigned,=ÿÿÿÿÿÿÿÿsigned,xÿÿÿ%d Hz,=no loop,=ÿÿÿÿÿÿÿÿloop,<€note %d,=replay 5.485 KHz=replay 8.084 KHz=replay 10.971 KHz=replay 16.168 KHz= replay 21.942 KHz=!replay 32.336 KHz="replay 43.885 KHz=#replay 47.261 KHz = d£IRCAM file (NeXT little-endian) =£dIRCAM file (NeXT big-endian) =D$HSFXSE multibeam = Wÿÿÿ†FreeBSD/i386 pure< X&YÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿshared library=ZÀÿÿÿÿÿÿÿ@PIC object=[Àÿÿÿÿÿÿÿobject> \ÿ=]€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿdynamically linked executable=^€ÿÿÿÿÿÿÿexecutable> _not stripped =#mêdump format, 4.2 or 4.3 BSD (IDC compatible) =£dIRCAM file (NeXT big-endian) =RHDCSCaris multibeam sonar related data =d£IRCAM file (MIPS big-endian) =£dIRCAM file (MIPS little-endian) =d£IRCAM file (Sun little-endian) =£dIRCAM file (Sun big-endian) =SÁEÇÿÿÿÿGEOS=(executable=(VMFile=( binary=( directory label<( unknown>( unknown> , name "%s" =d£IRCAM file (VAX big-endian) =£dIRCAM file (VAX little-endian) =GPATGIMP pattern data,x %s ='GIMPGIMP brush data =öRSIDRSID sidtune PlaySID compatible>÷w/ header v%d,=øsingle song,>ù%d songs,>údefault song: %d>ûname: "%s">6üauthor: "%s">Výcopyright: "%s" =íPSIDPlaySID v2.2+ (AMIGA) sidtune>îw/ header v%d,=ïsingle song,>ð%d songs,>ñdefault song: %d>òname: "%s">6óauthor: "%s">Vôcopyright: "%s" = Þ•GNU message catalog (little endian),x  revision %d.>  %d,x  %d messages,x $%d sysdep messages= %d,x %d messages =•ÞGNU message catalog (big endian),xrevision %d.>%d,x%d messages,x$%d sysdep messages=%d,x%d messages =gpgGPG key trust databasexversion %d =$nêdump format, Convex Storage Manager by-reference dump =8à32CN32-channel Taketracker module sound dataaudio/x-mod>ãTitle: "%s" =8Ü16CN16-channel Taketracker module sound dataaudio/x-mod>ßTitle: "%s" =8ÕOKTA8-channel Octalyzer module sound dataaudio/x-mod>ØTitle: "%s" =4•ÞÿÿÿÿGNU-format message catalog data =5Þ•ÿÿÿÿGNU-format message catalog data = ÿ|ùÿÿÿÿSE Linux modular policyx version %d,x %d sections,= ÿ|ùÿÿÿÿx   mod version %d,=   Not MLS,=   MLS,=   >  /module name %s=  base =8ÑCD818-channel Octalyser module sound dataaudio/x-mod>ÔTitle: "%s" =8Í8CHN8-channel Fasttracker module sound dataaudio/x-mod>ÐTitle: "%s" =8É6CHN6-channel Fasttracker module sound dataaudio/x-mod>ÌTitle: "%s" =8Å4CHN4-channel Fasttracker module sound dataaudio/x-mod>ÈTitle: "%s" =8ÁFLT88-channel Startracker module sound dataaudio/x-mod>ÄTitle: "%s" =8½FLT44-channel Startracker module sound dataaudio/x-mod>ÀTitle: "%s" =8¹M!K!4-channel Protracker module sound dataaudio/x-mod>¼Title: "%s" =þíþíÿÿÿÿSun 'jks' Java Keystore File data =8µM.K.4-channel Protracker module sound dataaudio/x-mod>¸Title: "%s" =fGDSII Stream file=gxhversion %d.0>iversion %dxj.%d =¨UN05MikMod UNI format module sound data =,ŒSCRMScreamTracker III Module sound data>Title: "%s" = Mÿÿÿ†FreeBSD/i386< N&OÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿshared library=PÀÿÿÿÿÿÿÿ@PIC object=QÀÿÿÿÿÿÿÿobject> Rÿ=S€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿdynamically linked executable=T€ÿÿÿÿÿÿÿexecutable> Unot stripped =0 TML 0123 byte-order format =1 TML 1032 byte-order format =2 TML 2301 byte-order format =3 TML 3210 byte-order format =5PA-RISC1.1 relocatable object =6PA-RISC1.1 executable&¨7dynamically linked=80öNdynamically linked>`9- not stripped =;PA-RISC1.1 shared executable=¨<dynamically linked==0öNdynamically linked>`>- not stripped =@ PA-RISC1.1 demand-load executable=¨Adynamically linked=B0öNdynamically linked>`C- not stripped =EPA-RISC1.1 shared library>`F- not stripped =H PA-RISC1.1 dynamic load library>`I- not stripped =LPA-RISC2.0 relocatable object =NPA-RISC2.0 executable&¨Odynamically linked=P0öNdynamically linked>`Q- not stripped =SPA-RISC2.0 shared executable&¨Tdynamically linked=U0öNdynamically linked>`V- not stripped =X PA-RISC2.0 demand-load executable&¨Ydynamically linked=Z0öNdynamically linked>`[- not stripped =]PA-RISC2.0 shared library>`^- not stripped =` PA-RISC2.0 dynamic load library>`a- not stripped =d PA-RISC1.0 relocatable object =f PA-RISC1.0 executable=¨gdynamically linked=h0öNdynamically linked>`i- not stripped =k PA-RISC1.0 shared executable=¨ldynamically linked=m0öNdynamically linked>`n- not stripped =p  PA-RISC1.0 demand-load executable=¨qdynamically linked=r0öNdynamically linked>`s- not stripped =u PA-RISC1.0 shared library>`v- not stripped =x  PA-RISC1.0 dynamic load library>`y- not stripped ={raƒ- version %ld =…HP s500 executable>†- version %ld =ˆHP s500 pure executable>‰- version %ld =Œ HP s200 pure executable>- version %ld&Ž€ÿÿÿÿsave fp regs&@dynamically linked& debuggable>$‘not stripped =“ HP s200 executable>”- version %ld&•€ÿÿÿÿsave fp regs&–@dynamically linked&— debuggable>$˜not stripped =š  HP s200 demand-load executable>›- version %ld&œ€ÿÿÿÿsave fp regs&@dynamically linked&ž debuggable>$Ÿnot stripped =¡ HP s200 relocatable executable>¢- version %ld>£- highwater %d&¤€ÿÿÿÿsave fp regs&¥ debuggable&¦PIC =¨ HP s200 (2.x release) pure executable>©- version %ld>$ªnot stripped =¬ HP s200 (2.x release) executable>­- version %ld>$®not stripped =° HP s200 shared library>±- version %ld>²- highwater %d>$³not stripped =µ  HP s200 dynamic load library>¶- version %ld>·- highwater %d>$¸not stripped =»eÿHP old archive =¼eÿ HP s200 old archive =½eÿ HP s200 old archive =¾eÿHP s500 old archive =À¦!XHP core file =Âèî§MHP-WINDOWS font>Ã- version %ld =wýar.RealAudio sound fileaudio/x-pn-realaudio =oEMODExtended MOD sound data,xpðÿÿÿÿÿÿÿversion %dxq.%d,x-r%d instruments=Ss(module)=St(song) =É  compiled Lisp =jKRTNMultiTrack sound dataxk- version %ld =ÒHPHPHP=Ó4848 binary=Ô4949 binary>Õ@- Rev %c= Ö)(ADR)= ×3)(REAL)= ØU)(LREAL)= Ùw)(COMPLX)= Ú)(LCOMPLX)= Û¿)(CHAR)= Üè)(ARRAY)= Ý *(LNKARRAY)= Þ,*(STRING)= ßN*(HXS)= àt*(LIST)= á–*(DIR)= â¸*(ALG)= ãÚ*(UNIT)= äü*(TAGGED)= å+(GROB)= æ@+(LIB)= çb+(BACKUP)= èˆ+(LIBDATA)= é-(PROG)= êÌ-(CODE)= ëH.(GNAME)= ìm.(LNAME)= í’.(XLIB) =)Convex SOFF=X*c1&X+c2&X,c2mp&X-parallel&X.intrinsic&X/demand paged&X0pre-paged&X1non-swapped&X2POSIX&T4€ÿÿÿÿexecutable&T5@object=T6 not stripped=T7native fpmode=T8ieee fpmode=T9undefined fpmode = TZiftimezone data= , old version> , version %c= , no gmt time flags= , 1 gmt time flag>, %d gmt time flags=, no std time flags=, 1 std time flag>, %d std time flags=, no leap seconds=, 1 leap second>, %d leap seconds= , no transition times= , 1 transition time> , %d transition times=$, no abbreviation chars=$, 1 abbreviation char>$, %d abbreviation chars =^CTMFCreative Music (CMF) dataaudio/x-unknown =VMThdStandard MIDI dataaudio/midixX(format %d)x Yusing %d track> Zsx [ÿat 1/%d> \€ÿÿÿÿÿÿSMPTE = 1.sdDEC audio data:= 28-bit ISDN mu-law,audio/x-dec-basic= 48-bit linear PCM [REF-PCM],audio/x-dec-basic= 616-bit linear PCM,audio/x-dec-basic= 824-bit linear PCM,audio/x-dec-basic= :32-bit linear PCM,audio/x-dec-basic= <32-bit IEEE floating point,audio/x-dec-basic= >64-bit IEEE floating point,audio/x-dec-basic= @Fragmented sample data,= A DSP program,= B 8-bit fixed point,= C 16-bit fixed point,= D 24-bit fixed point,= E32-bit fixed point,= F16-bit linear with emphasis,= G16-bit linear compressed,= H16-bit linear with emphasis and compression,= IMusic kit DSP commands,= J8-bit ISDN mu-law compressed (CCITT G.721 ADPCM voice enc.),audio/x-dec-basic= Lcompressed (8-bit CCITT G.722 ADPCM)= Mcompressed (3-bit CCITT G.723.3 ADPCM),= Ncompressed (5-bit CCITT G.723.5 ADPCM),= O8-bit A-law (CCITT G.711),= Pmono,= Qstereo,= Rquad,> S%d Hz =;…Convex SOFF core ==‡Convex SOFF checkpoint=X>c1&X?c2&X@c2mp&XAparallel&XBintrinsic&XCPOSIX=TEnative fpmode=TFieee fpmode=TGundefined fpmode = 1VwpCracklib password index, little endian>(%i words)=("64-bit")> ÿÿÿÿÿÿÿÿ(%i words) = 1VwpCracklib password index, big endian> ÿÿÿÿÿÿÿÿ(%i words) = .sndSun/NeXT audio data:= 8-bit ISDN mu-law,audio/basic= 8-bit linear PCM [REF-PCM],audio/basic= 16-bit linear PCM,audio/basic= 24-bit linear PCM,audio/basic= 32-bit linear PCM,audio/basic= 32-bit IEEE floating point,audio/basic= 64-bit IEEE floating point,audio/basic= Fragmented sample data,=  DSP program,=  8-bit fixed point,=  16-bit fixed point,=  24-bit fixed point,= 32-bit fixed point,= 16-bit linear with emphasis,= !16-bit linear compressed,= "16-bit linear with emphasis and compression,= #Music kit DSP commands,= $8-bit ISDN mu-law compressed (CCITT G.721 ADPCM voice enc.),audio/x-adpcm= &compressed (8-bit CCITT G.722 ADPCM)= 'compressed (3-bit CCITT G.723.3 ADPCM),= (compressed (5-bit CCITT G.723.5 ADPCM),= )8-bit A-law (CCITT G.711),=*mono,=+stereo,=,quad,>-%d Hz =ÐMAP CCP4 Electron Density Map=Ô , Big-endian=Ô!", VAX format=Ô"D, Little-endian=Ô#U, Convex native =%X psSoftQuad troff Context intermediate for PostScript = 2278Aster*x Version 2=6Words Document=5Graphic=2Spreadsheet=8Macro =*STAAster*x= WORDWords Document= GRAPGraphic= SPRESpreadsheet= MACRMacro =#X hpSoftQuad troff Context intermediate for HP LaserJet =ßArCFreeArc archive = pBB02Bacula volumex q, started %s = MTZ MTZ reflection file =kPAR2Parity Archive Volume Set =ÃTCDDACT compressed data>ÿÿÿÿÿÿÿÿ(version %i.>ÿÿÿÿÿÿÿÿ$BS%i.> ÿÿÿÿÿÿÿÿ$BS%i)> $BS, original size: %i bytes> $BS, block size: %i bytes =2drpmDelta RPMapplication/x-rpmx 4%s ="drpmDelta RPMapplication/x-rpmx $%s=& MIPSel=' ARM=( MiNT=)S/390=*S/390x=+PowerPC64=,SuperH=-Xtensax .%s =Ûî«íÿÿÿÿRPMapplication/x-rpmx v%dx .%d= src= bin= i386/x86_64=Alpha/Sparc64=Sparc=MIPS=PowerPC=68000=SGI=RS6000= IA64= Sparc64= MIPSel= ARM= MiNT=S/390=S/390x=PowerPC64=SuperH=Xtensa=ÿnoarch =`xar!xar archivexbversion %d,=eno checksum=fSHA-1 checksum=gMD5 checksum =ùAIX compiled message catalog =Vxar!xar archivexW- version %ld =RMPQMoPaQ (MPQ) archive = FORMIFF data=AIFF, AIFF audioaudio/x-aiff=AIFC, AIFF-C compressed audioaudio/x-aiff=8SVX, 8SVX 8-bit sampled sound voiceaudio/x-aiff=16SV, 16SV 16-bit sampled sound voice=SAMP, SAMP sampled audio=MAUD, MAUD MacroSystem audio=SMUS, SMUS simple music=CMUS, CMUS complex music=ILBMBMHD, ILBM interleaved imagex, %d xx%d=RGBN, RGBN 12-bit RGB image= RGB8, RGB8 24-bit RGB image=!DEEP, DEEP TVPaint/XiPaint image="DR2D, DR2D 2-D object=#TDDD, TDDD 3-D rendering=$LWOB, LWOB 3-D object=%LWO2, LWO2 3-D object, v2=&LWLO, LWLO 3-D layered object='REAL, REAL Real3D rendering=(MC4D, MC4D MaxonCinema4D rendering=)ANIM, ANIM animation=*YAFA, YAFA animation=+SSA , SSA super smooth animation=,ACBM, ACBM continuous image=-FAXX, FAXX fax image=/FTXT, FTXT formatted text=0CTLG, CTLG message catalog=1PREF, PREF preferences=2DTYP, DTYP datatype description=3PTCH, PTCH binary patch=4AMFF, AMFF AmigaMetaFile format=5WZRD, WZRD StormWIZARD resource=6DOC , DOC desktop publishing document=7WVQA, Westwood Studios VQA Multimedia,x 8%d video frames,x 9%d xx :%d=;MOVE, Wing Commander III Video= <_PC_, PC version= =3DO_, 3DO version=EIFRS, Blorb Interactive Fiction=FExecwith executable chunk=GIFZS, Z-machine or Glulx saved game file (Quetzal) =ÿÿ÷ÿÿÿÿÿTarga image data - Map=- RLE> %hd x> %hd =ÿÿ÷ÿÿÿÿÿTarga image data - RGB=- RLE> %hd x> %hd =ÿÿ÷ÿÿÿÿÿTarga image data - Mono=- RLE> %hd x> %hd = ΚWGNU dbm 1.x or ndbm database, big endianapplication/x-gdbm = ÅÆËÃÿÿÿÿRISC OS Chunk data= OBJ_, AOF object= LIB_, ALF library = Nz Symbian installation file (Symbian OS 9.x)x-epoc/x-sisx-app = JSymbian installation fileapplication/vnd.symbian.install= Lm(EPOC release 3/4/5)= M:(EPOC release 6) =¿RIFXRIFF (big-endian) data=ÁPAL, palettexÂ, version %dxÃ, %d entries=ÅRDIB, device-independent bitmap=ÆBM=Ç , OS/2 1.x formatx"È, %d xx$É%d=Ê@, OS/2 2.x formatx"Ë, %d xx$Ì%d=Í(, Windows 3.x formatx"Î, %d xx&Ï%d xx,Ð%d=ÒRMID, MIDI=ÔRMMP, multimedia movie=ÖWAVE, WAVE audio= ×, Microsoft PCM> "Ø, %d bit=Ù, mono=Ú, stereo>Û, %d channels>Ü%d Hz=ÞCDRA, Corel Draw Picture=àAVI , AVI=âACON, animated cursor=äNIFF, Notation Interchange File Format=æsfbkSoundFont/Bank = RIFFRIFF (little-endian) data= PAL, palettex , version %dx , %d entries=RDIB, device-independent bitmap=BM=  , OS/2 1.x formatx ", %d xx $%d= @, OS/2 2.x formatx ", %d xx $%d= (, Windows 3.x formatx ", %d xx &%d xx ,%d=RMID, MIDI= RMMP, multimedia movie="RMP3, MPEG Layer 3 audio=$WAVE, WAVE audioaudio/x-wav= &, Microsoft PCM> "', %d bit= (, Microsoft ADPCM= ), ITU G.711 A-law= *, ITU G.711 mu-law= +, Microsoft DTS= ,, IMA ADPCM= -, ITU G.723 ADPCM (Yamaha)= .1, GSM 6.10= /@, ITU G.721 ADPCM= 0P, MPEG= 1U, MPEG Layer 3= 2 , DTS= 3, mono= 4, stereo> 5, %d channels> 6%d Hz=8CDRA, Corel Draw Pictureimage/x-coreldraw=;AVI , AVIvideo/x-msvideo= =LIST=>hdrlavihx $?, %lu xx (@%lu,> A@B<1 fps,= B@B1.00 fps,= C ¡2.00 fps,= D3.00 fps,= EÐ4.00 fps,= F@ 5.00 fps,= G ‹6.00 fps,= H .7.00 fps,= IHè8.00 fps,= J²9.00 fps,= K †10.00 fps,< M’Š> üÿÿÿN‚! üÿÿÿO †~10 fps,= P…E12.00 fps,< RBH> üÿÿÿSÕB! üÿÿÿT…E~12 fps,= Uk15.00 fps,< W*> üÿÿÿX±! üÿÿÿYk~15 fps,= ZPÃ20.00 fps,= [ì¢23.98 fps,= \â24.00 fps,< ^q£> üÿÿÿ_¢! üÿÿÿ`ì¢! üÿÿÿaâ~24 fps,= b@œ25.00 fps,< dáœ> üÿÿÿe¡›! üÿÿÿf@œ~25 fps,= gW‚29.97 fps,= h5‚30.00 fps,< j¥‚> üÿÿÿkÇ! üÿÿÿlW‚! üÿÿÿm5‚~30 fps,< nà}>30 fps,=XuLIST=`vstrlstrh=lwvidsvideo:= xuncompressed= hlzstrf= h„{RLE 8bpp= h„|cvidCinepak= h„}i263Intel I.263= h„~iv32Indeo 3.2= h„iv41Indeo 4.1= h„€iv50Indeo 5.0= h„mp42Microsoft MPEG-4 v2= h„‚mp43Microsoft MPEG-4 v3= h„ƒfmp4FFMpeg MPEG-4= h„„mjpgMotion JPEG= h„…div3DivX 3=p†div3Low-Motion=p‡div4Fast-Motion= h„ˆdivxDivX 4= h„‰dx50DivX 5= h„ŠxvidXviD= h„‹h264H.264= h„Œwmv3Windows Media Video 9= h„h264X.264 or H.264= h„Ž= \`‘LIST= \h’strlstrh= \t“auds, audio:= \¬•strf= \´–uncompressed PCM= \´—ADPCM= \´˜aLaw= \´™uLaw= \´šPMPEG-1 Layer 1 or 2= \´›UMPEG-1 Layer 3= \´œ Dolby AC3= \´aDivX= \¶Ÿ(mono,= \¶ (stereo,> \¶¡(%d channels,x \¸¢%d Hz)= \´¤strf= \¼¥uncompressed PCM= \¼¦ADPCM= \¼§UMPEG-1 Layer 3= \¼¨ Dolby AC3= \¼©aDivX= \¾«(mono,= \¾¬(stereo,> \¾­(%d channels,x \À®%d Hz)=°ACON, animated cursor=²sfbkSoundFont/Bank=´CDXA, wrapped MPEG-1 (CDXA)=µ4XMV, 4X Movie file =·AMV , AMV =?{dar archive,x@label "%.8xxA%.8xx B%.4x"=CTend slice=DNNmulti-part=ESNmulti-part, with -S =9RZIPrzip compressed datax:- version %dx;.%dx<(%d bytes) =6.MDAMicroDesign data=70version 2=83version 3 =9.MDPMicroDesign page data=:0version 2=;3version 3 =?IIN1NIFF image dataimage/x-niff =5ÿçEET archiveapplication/x-eet = ΚWGNU dbm 1.x or ndbm database, little endianapplication/x-gdbm =XMM*TIFF image data, big-endianimage/tiff =ZII*TIFF image data, little-endianimage/tiff =]MM+Big TIFF image data, big-endianimage/tiff =_II+Big TIFF image data, little-endianimage/tiff = +/v8Unicode text, UTF-7 =öPARPARity archive data= 0÷- Index file> 0ø- file number %d = +/v9Unicode text, UTF-7 =›DISODelta ISO dataxœversion %d =‰GIF8GIF image dataimage/gif8BIMGIFf=Œ7a, version 8%s,=9a, version 8%s,> Ž%hd x> %hd =œñ@»CMU window manager raster image data> %d x> ž%d,> Ÿ%d-bit =GDBMGNU dbm 2.x databaseapplication/x-gdbm =¥$ðBArtisan image data=¦, rectangular 24-bit=§, rectangular 8-bit with colormap=¨, rectangular 32-bit (24-bit with matte) ='HG10Mercurial bundle,=(UNuncompressed=)BZbzip2 compressed =qhsqsSquashfs filesystem, little endian,x rversion %d.x s%d,< tx u%d bytes,> v< wx?x%lld bytes,> yx(z%lld bytes,x |%d inodes,< }x ~blocksize: %d bytes,> < €x 3blocksize: %d bytes,> ‚x ƒblocksize: %d bytes,< „x '…created: %s> †x ‡created: %s =ZsqshSquashfs filesystem, big endian,x[version %d.x\%d,<]x^%d bytes,>_<`x?a%lld bytes,>bx(c%lld bytes,xe%d inodes,<fx gblocksize: %d bytes,>h<ix3jblocksize: %d bytes,>kx lblocksize: %d bytes,<mx 'ncreated: %s>ox pcreated: %s =¶GKSMGKS Metafile=·SunGKS, SunGKS =aBerkeley DBapplication/x-dbm=á>1.86<1.85> (Hash, version %d, native byte-order)=!Ò>"1.86<#1.85>$(Hash, version %d, little-endian) =!DIRCGit index>", version %d>#, %d entries =ÿtOcGit pack index=, version 2 =FCIMGAlias Maya Image File =V'u-boot legacy uImage,x %s,=Invalid os/=OpenBSD/=NetBSD/=FreeBSD/=4.4BSD/=Linux/=SVR4/=Esix/= Solaris/=! Irix/=" SCO/=# Dell/=$ NCR/=% LynxOS/=&VxWorks/='pSOS/=(QNX/=)Firmware/=*RTEMS/=+ARTOS/=,Unity OS/=-INTEGRITY/=.Invalid CPU,=/Alpha,=0ARM,=1Intel x86,=2IA64,=3MIPS,=4MIPS 64-bit,=5PowerPC,=6IBM S390,=7 SuperH,=8 Sparc,=9 Sparc 64-bit,=: M68K,=; Nios-32,=<MicroBlaze,==Nios-II,=>Blackfin,=?AVR32,=@STMicroelectronics ST200,=AInvalid Image=BStandalone Program=COS Kernel Image=DRAMDisk Image=EMulti-File Image=FFirmware Image=GScript File=HFilesystem Image (any type)=IBinary Flat Device Tree BLOB=J(Not compressed),=K(gzip),=L(bzip2),=M(lzma),x N%d bytes,x O%s,xPLoad Address: 0x%08X,xQEntry Point: 0x%08X,xRHeader CRC: 0x%08X,xSData CRC: 0x%08X = ÁܧÄýÿÿÿÿZoo archive dataapplication/x-zoo>Ã0, v%c.>Ä/%c>Å/%c> Æ, modify: v%dx!Ç.%d+= *ÈܧÄýÿÿÿÿ,>FÉextract: v%dxGÊ.%d+ =âÃTCDDACT compressed data>ãÿÿÿÿÿÿÿÿ(version %i.>äÿÿÿÿÿÿÿÿ%i.>åÿÿÿÿÿÿÿÿ%i)>æ, original size: %i bytes>ç, block size: %i bytes =ÌSfffstructured fax file = »?êÿÿÿÿConary changeset data =7UC2UC2 archive data = lpython 3.2 byte-compiled =3SQSHsquished archive data (Acorn RISCOS) =•j¦YSun raster image data>, %d x>%d,> %d-bit,=old format,= compressed,= RGB,= TIFF,= IFF,=ÿÿreserved for testing,=no colormap=RGB colormap=raw colormap = Opython 3.1 byte-compiled =%IT01FIT image datax&, %d xx'%d xx (%d =*IT02FIT image datax+, %d xx,%d xx -%d =0RE~^RAR archive data ="Rar!RAR archive data,application/x-rarx,$v%0x,> %flags:& &Archive volume,& 'Commented,& (Locked,& )Solid,& * Authenticated,=#+os: MS-DOS=#,os: OS/2=#-os: Win32=#.os: Unix =&aBerkeley DB='á>(1.86<)1.85>*(Hash, version %d, big-endian)=+Ò>,1.86<-1.85>.(Hash, version %d, native byte-order) = +/v+Unicode text, UTF-7 = ;python 3.0 byte-compiled =€JDICMDICOM medical imaging dataapplication/dicom = ópython 2.7 byte-compiled = +/v/Unicode text, UTF-7 =0b1Berkeley DB 1.85/1.86>1(Btree, version %d, native byte-order) = 1984Linux Journalled Flash File system, big endian = 1984Linux Journalled Flash File system, little endian =hPDS_PDS image data =2b1Berkeley DB 1.85/1.86>3(Btree, version %d, big-endian) =tpM85Atari ST STAD bitmap image data (hor)=u(white background)=vÿÿÿÿÿÿÿÿ(black background) =wpM86Atari ST STAD bitmap image data (vert)=x(white background)=yÿÿÿÿÿÿÿÿ(black background) = òÑÿÿÿÿpython 2.6 byte-compiled = 4b1Berkeley DB 1.85/1.86> 5(Btree, version %d, little-endian) = ò³ÿÿÿÿpython 2.5 byte-compiled = òmpython 2.4 byte-compiled = ò;python 2.3 byte-compiled = 7aBerkeley DB>8(Hash, version %d, native byte-order) = ë*python 2.1 byte-compiled =·8BPSAdobe Photoshop Imageimage/vnd.adobe.photoshop=¹(PSB)xº, %d xx»%d,=¼bitmap=½grayscale= ¾with alpha=¿indexed=ÀRGB= ÁA=ÂCMYK= ÃA=Ämultichannel=Åduotone=Æ lab> Çx È, %dx= É,xÊ%d-bit channel> Ës =òE=Í(Linux Compressed ROM File System data, big endianxósize %lu&ôversion #2&õsorted_dirs&öhole_supportx ÷CRC 0x%x,x$øedition %lu,x(ù%lu blocks,x,ú%lu files =ÑNITFNational Imagery Transmission Format>Òdated %.14s =ÕGEM Image datax Ö%d xx×%d,xØ%d planes,xÙ%d xx Ú%d pixelsize = ÝÿÿGEM Metafile datax Þversion %d = èE=Í(Linux Compressed ROM File System data, little endianx ésize %lu& êversion #2& ësorted_dirs& ìhole_supportx íCRC 0x%x,x $îedition %lu,x (ï%lu blocks,x ,ð%lu files =åCISOCompressed ISO CD image = 9aBerkeley DB>:(Hash, version %d, big-endian) =KiSSKISS/GS=colorx%d bitx %d colorsx %d groups=  cellx %d bitx  %d xx %dx +%dx +%d = ;aBerkeley DB> <(Hash, version %d, little-endian) = >b1Berkeley DB>?(Btree, version %d, native byte-order) = @b1Berkeley DB>A(Btree, version %d, big-endian) = Bb1Berkeley DB> C(Btree, version %d, little-endian) =&fSqueak image data = Ƈÿÿÿÿpython 2.0 byte-compiled =õHPAKHPACK archive data = >±hÞ:DCX multi-page PCX image data = C€*_×ÿÿÿÿCineon image data>ÈD, %ld x>ÌE%ld = N™ÿÿÿÿpython 1.5/1.6 byte-compiled =YMRMMinolta Dimage camera raw image data =ëüÿÿÿÿÿÿAHHA archive data= ì1 file,> í%u files,=îfirst is type CPY=ïfirst is type ASC=ðfirst is type HSC=ñfirst is type DIR=òfirst is type SPECIAL = lv/1OpenEXR image data =pCDFNetCDF Data Format data =uHierarchical Data Format (version 4) dataapplication/x-hdf = ÝsfsUnicode text, UTF-8-EBCDIC =þÿUnicode text, UTF-32, big-endian =€CPC²Cartesian Perceptual Compression imageimage/x-cpi =‹C565OLPC firmware icon image datax Œ%u xx %u =‘ÎÚÞúCytovision Metaphases file =’í­ï¬Cytovision Karyotype file =“ Cytovision FISH Probe file =”íþÚ¾Cytovision FLEX file =•í«íþCytovision FLEX file =–­ýê­Cytovision RATS file = ES"Berkeley DB>F(Queue, version %d, native byte-order) = GS"Berkeley DB>H(Queue, version %d, big-endian) = IS"Berkeley DB> J(Queue, version %d, little-endian) =”'üFAtari-ST Minix kernel image= • ù , 720k floppy= –Ðø , 360k floppy =«XcurX11 cursor =°MMOROlympus ORF raw image data, big-endianimage/x-olympus-orf =²IIROOlympus ORF raw image data, little-endianimage/x-olympus-orf =´IIRSOlympus ORF raw image data, little-endianimage/x-olympus-orf =ŒBSFXSGI XFS filesystem datax(blksz %d,xhŽinosz %d,^d v1 dirs)&d v2 dirs) =# not stripped = PPyramid 90x family pure executable> not stripped =PPyramid 90x family executable = ñçPulsar POP3 daemon mailbox cache file.x Version: %d.x %d =ÿÿÿÿÿÿÿVps database>version %s>from kernel %s =! unknown demand paged pure executable>"not stripped =GDEEPAlias Maya Image File =#unknown readable demand paged pure executable =\FTUnix Fast File system [v2] (big-endian)xtûÿÿGlast mounted on %s,>HýÿÿHvolume name %s,x ÐþÿÿIlast written at %s,xqûÿÿJclean flag %d,xpûÿÿKreadonly flag %d,xØþÿÿLnumber of blocks %lld,xàþÿÿMnumber of data blocks %lld,xÌúÿÿNnumber of cylinder groups %d,xÐúÿÿOblock size %d,xÔúÿÿPfragment size %d,xLÿÿÿQaverage file size %d,xPÿÿÿRaverage number of files in dir %d,xðþÿÿSpending blocks to free %lld,xøþÿÿTpending inodes to free %ld,xhýÿÿUsystem-wide uuid %0llx,xÜúÿÿVminimum percentage of free blocks %d,= ûÿÿWTIME optimization= ûÿÿXSPACE optimization = 4Z¥ðIntel serial flash for ICH/PCH ROM <= 5 or 3400 series A-step = 5Z¥ðIntel serial flash for PCH ROM =ˆOPSInterleaf saved data =\¥2TUnix Fast File system [v2] (big-endian)xtûÿÿ3last mounted on %s,>Hýÿÿ4volume name %s,x Ðþÿÿ5last written at %s,xqûÿÿ6clean flag %d,xpûÿÿ7readonly flag %d,xØþÿÿ8number of blocks %lld,xàþÿÿ9number of data blocks %lld,xÌúÿÿ:number of cylinder groups %d,xÐúÿÿ;block size %d,xÔúÿÿ<fragment size %d,xLÿÿÿ=average file size %d,xPÿÿÿ>average number of files in dir %d,xðþÿÿ?pending blocks to free %lld,xøþÿÿ@pending inodes to free %ld,xhýÿÿAsystem-wide uuid %0llx,xÜúÿÿBminimum percentage of free blocks %d,= ûÿÿCTIME optimization= ûÿÿDSPACE optimization =\%TUnix Fast File system [v1] (big-endian),=LBALApple UFS Volumex named %s,x!volume label version %d,x "created on %s,xÔ #last mounted on %s,x %last written at %s,xÑ &clean flag %d,x$ 'number of blocks %d,x( (number of data blocks %d,x, )number of cylinder groups %d,x0 *block size %d,x4 +fragment size %d,x< ,minimum percentage of free blocks %d,x@ -rotational delay %dms,xD .disk rotational speed %drps,=€ /TIME optimization=€ 0SPACE optimization =TXßÿÿUltrix core file>Xfrom '%s' = NESiNES ROM dump,x %dx16k PRGx , %dx8k CHR= , [Vert.]= , [Horiz.]=, [SRAM]=, [Trainer]=, [4-Scr] =ffíÎÿÿÿÿGameboy ROM:>4"%.16s"=F,[SGB]=G, [ROM ONLY]=G, [ROM+MBC1]=G, [ROM+MBC1+RAM]=G, [ROM+MBC1+RAM+BATT]=G, [ROM+MBC2]=G, [ROM+MBC2+BATTERY]=G, [ROM+RAM]=G , [ROM+RAM+BATTERY]=G , [ROM+MMM01]=G! , [ROM+MMM01+SRAM]=G" , [ROM+MMM01+SRAM+BATT]=G#, [ROM+MBC3+TIMER+BATT]=G$, [ROM+MBC3+TIMER+RAM+BATT]=G%, [ROM+MBC3]=G&, [ROM+MBC3+RAM]=G', [ROM+MBC3+RAM+BATT]=G(, [ROM+MBC5]=G), [ROM+MBC5+RAM]=G*, [ROM+MBC5+RAM+BATT]=G+, [ROM+MBC5+RUMBLE]=G,, [ROM+MBC5+RUMBLE+SRAM]=G-, [ROM+MBC5+RUMBLE+SRAM+BATT]=G., [Pocket Camera]=G/ýÿÿÿÿÿÿÿ, [Bandai TAMA5]=G0þÿÿÿÿÿÿÿ, [Hudson HuC-3]=G1ÿÿÿÿÿÿÿÿ, [Hudson HuC-1]=H3, ROM: 256Kbit=H4, ROM: 512Kbit=H5, ROM: 1Mbit=H6, ROM: 2Mbit=H7, ROM: 4Mbit=H8, ROM: 8Mbit=H9, ROM: 16Mbit=H:R, ROM: 9Mbit=H;S, ROM: 10Mbit=H<T, ROM: 12Mbit=I>, RAM: 16Kbit=I?, RAM: 64Kbit=I@, RAM: 128Kbit=IA, RAM: 1Mbit =:ISPLispellx;hash file version %d,x<lexletters %d,x =lexsize %d,x>hashsize %d,x?stblsize %d =IsZ!ISO Zipped filex, header size %ux, version %ux  , serial %u> , password protected =§SZ SZip archive data = íþíþÿÿÿÿJava KeyStoreapplication/x-java-keystore =ÎÎÎÎÿÿÿÿJava JCE KeyStoreapplication/x-java-jce-keystore =HSEGASega MegaDrive/Genesis raw ROM dump> IName: "%.16s">J%.16s=°KRAwith SRAM =€PEAGNSuper MagicDrive ROM dumpxQ%dx16k blocks=R, last in series or standalone>S, split ROM=Tªÿÿÿÿÿÿÿ= U»ÿÿÿÿÿÿÿ = \ TUnix Fast File system [v2] (little-endian)xtûÿÿ last mounted on %s,>Hýÿÿ volume name %s,xÐþÿÿ last written at %s,xqûÿÿclean flag %d,xpûÿÿreadonly flag %d,xØþÿÿnumber of blocks %lld,xàþÿÿnumber of data blocks %lld,x Ìúÿÿnumber of cylinder groups %d,x Ðúÿÿblock size %d,x Ôúÿÿfragment size %d,x Lÿÿÿaverage file size %d,x Pÿÿÿaverage number of files in dir %d,xðþÿÿpending blocks to free %lld,x øþÿÿpending inodes to free %ld,xhýÿÿsystem-wide uuid %0llx,x Üúÿÿminimum percentage of free blocks %d,= ûÿÿTIME optimization= ûÿÿSPACE optimization =cRastRST-format raster font data>-d0face %s =™hsi1JPEG image data, HSI proprietary =gmonGNU prof performance datax- version %ld = QÿOÿÿÿÿÿJPEG 2000 codestream = ÀHRBHarbour HRB filex !version %d =#ÀHBVHarbour variable dump filex $version %d = ,~ñ©ST40 component image format>-, name '%s' =ÿBSGBSN archive data =œÿBSGBSN archive data = \¥öTUnix Fast File system [v2] (little-endian)xtûÿÿ÷last mounted on %s,>Hýÿÿøvolume name %s,xÐþÿÿùlast written at %s,xqûÿÿúclean flag %d,xpûÿÿûreadonly flag %d,xØþÿÿünumber of blocks %lld,xàþÿÿýnumber of data blocks %lld,x Ìúÿÿþnumber of cylinder groups %d,x Ðúÿÿÿblock size %d,x Ôúÿÿfragment size %d,x Lÿÿÿaverage file size %d,x Pÿÿÿaverage number of files in dir %d,xðþÿÿpending blocks to free %lld,x øþÿÿpending inodes to free %ld,xhýÿÿsystem-wide uuid %0llx,x Üúÿÿminimum percentage of free blocks %d,= ûÿÿTIME optimization= ûÿÿSPACE optimization =€ZEAMGSuper MagicDrive ROM dumpx[%dx16k blocksx\, last in series or standalone=]ªÿÿÿÿÿÿÿ= ^»ÿÿÿÿÿÿÿ =lectDEC SRC Virtual Paper Lectern file =›ÿBSGBSN archive data =—a\WinHKI archive data = oƒVAX single precision APL workspace = nƒVAX double precision APL workspace = dLinux/i386 impure executable (OMAGIC)= , stripped = dLinux/i386 pure executable (NMAGIC)= , stripped =  dLinux/i386 demand-paged executable (ZMAGIC)= , stripped = ÌdLinux/i386 demand-paged executable (QMAGIC)= , stripped =!ÆÓÐÅÿÿÿÿDOS EPS Binary File>"Postscript starts at byte %d>#length %d> $Metafile starts at byte %d>%length %d>&TIFF starts at byte %d>'length %d =Linux-8086 impure executable!not stripped = Linux-8086 executable!not stripped =!£†Linux-8086 object file =#Minix-386 impure executable!$not stripped =% Minix-386 executable!&not stripped = Ø(Linux/i386 core file>Ü)of '%s'> È*(signal %d) =.LILOLinux/i386 LILO boot/chain loader =GCAXGCA archive data =‹rdqxReDuq archive data = VAX executable>  not stripped = VAX pure executable> not stripped =…¯¬ŒEPC archive data =ƒDMS!DMS archive data =  VAX demand paged pure executable> not stripped = VAX demand paged (first page unmapped) pure executable> not stripped =aHdrSLinux kernel= þbUªÿÿÿÿÿÿx86 boot executable> cÿ=dzImage,=ebzImage,> fversion %s,= ògRO-rootFS,= òhRW-rootFS,> üiroot_dev 0x%X,> öjswap_dev 0x%X,> økRAMdisksize %u KB,= úlÿÿÿÿÿÿÿÿNormal VGA= úmþÿÿÿÿÿÿÿExtended VGA= únýÿÿÿÿÿÿÿPrompt for Videomode> úoVideo mode %d =qŽÀ¸ÿÿÿÿLinux kernel=ãrLoadingversion 1.3.79 or older=ésLoadingfrom prehistoric times =KPlan 9 executable, DEC Alpha =—Plan 9 executable, MIPS R4000 LE =ëPlan 9 executable, PowerPC =}MOOOUser-mode Linux COW file<~, version %d>, backing file %s>€, version %d> , backing file %s ={AiAi32 archive data =¥ŽÀ¸ÿÿÿÿLinux=æ¦SKLEELKS Kernel!æ§SKLEstyle boot sector =zAiAi32 archive data = $»(oLinux kernel ARM boot executable zImage (little-endian) =$¼(oLinux kernel ARM boot executable zImage (big-endian) = ÀÿÿÿÿÿÿéÃÿÿÿÿLinux-Dev86 executable, headerless=Á.>Â, libc version %s = ÄÿÿÿÿÿÿÿLinux-8086 executable!Å, unmapped zero page=Æ , impure!Ç !È, A_EXEC!É, A_PAL!Ê, A_NSYM!Ë, A_STAND!Ì@, A_PURE!Í€ÿÿÿÿÿÿÿ, A_TOVLY!Î, not stripped=%Ï.>$Ð, libc version %s = Ú=óSYSLINUX' LSS16 image datax Û, width %dx Ü, height %d =ÞOOOMUser-Mode-Linux's Copy-On-Write disk imagexßversion %d = ãŒÿ|ùÿÿÿÿSE Linux policyx äv%d= åMLSx æ%d symbolsx ç%d ocons =GPlan 9 executable, ARM 7-something =«Plan 9 executable, AMD 29000 = \%æTUnix Fast File system [v1] (little-endian),xÔ çlast mounted on %s,x élast written at %s,xÑ êclean flag %d,x $ ënumber of blocks %d,x ( ìnumber of data blocks %d,x , ínumber of cylinder groups %d,x 0 îblock size %d,x 4 ïfragment size %d,x < ðminimum percentage of free blocks %d,x @ ñrotational delay %dms,x D òdisk rotational speed %drps,= € óTIME optimization= € ôSPACE optimization = Mˆ Berkeley DB>N(Log, version %d, native byte-order) =s D, major %u> F, minor %u =,Ò‹vpCLISP memory image data =-pv‹ÒÿÿÿÿCLISP memory image data, other endian =0úúúúMIT scheme (library?)(= ¬ê|pxelinux Loader =llvmLLVM byte-codes, uncompressed(= ªúê@|isolinux Loader =‹¦OS/2OS/2 Boot Manager =  6Netboot image,= ¡ÿÿÿÿÿÿÿ= ¢mode 2= £mode 3! ¤ÿÿÿÿÿÿÿunknown mode = ÞÀ LLVM bitcode, wrapper = BCÀÞLLVM bitcode =‰¿ƒVirtutech CRAFFxv%d= uncompressed= bzipp2ed= gzipped= not clean = Oˆ Berkeley DB >P(Log, version %d, big-endian) = Qˆ Berkeley DB> R(Log, version %d, little-endian) =6pst0perl Storable (v0.7) data>7&8(network-ordered)=9(major 2)=:(major 2)>;(minor %d) =LuaLua bytecode,=Pversion 5.0=Qversion 5.1 =XBIX0BIX archive data =VBHBlakHole archive data = þÿÿÿÿÿÿÿÎúíþÿÿÿÿMach-O= Ïÿÿÿÿÿÿÿ64-bit= object= executable= fixed virtual memory shared library= core= preload executable= dynamically linked shared library= dynamic linker= bundle=  dynamically linked shared library stub>  x filetype=%ld< x architecture=%ld= vax= romp= architecture=3= ns32032= ns32332= m68k= i386= mips=  ns32532= ! architecture=10= " hppa= # acorn= $ m88k= %sparc= &i860-big= 'i860= (rs6000= )ppc= *ppc64> +x ,architecture=%ld =.þÿÿÿÿÿÿÿÎúíþÿÿÿÿMach-O=/Ïÿÿÿÿÿÿÿ64-bit= 0object= 1executable= 2fixed virtual memory shared library= 3core= 4preload executable= 5dynamically linked shared library= 6dynamic linker= 7bundle= 8 dynamically linked shared library stub> 9 x :filetype=%ld<;x<architecture=%ld==vax=>romp=?architecture=3=@ns32032=Ans32332=Bfor m68k architecture=F(mc68040)=G(mc68030 only)=Hi386=Imips=J ns32532=K architecture=10=L hppa=M acorn=N m88k=Osparc=Pi860-big=Qi860=Rrs6000=Sppc=Tppc64>UxVarchitecture=%ld =°0VMS VAX executable=¬PK, Info-ZIP SFX archive v5.12 w/decryption =SIT!StuffIt Archive (data)application/x-stuffitSITx: %s =SITDStuffIt Deluxe (data)x: %s = lƒPDP-11 double precision APL workspace =PISc(InstallShield CAB =fîmBINMacBinary III data with surprising version number = mƒPDP-11 single precision APL workspace = ÕŒÿ|ùÿÿÿÿSE Linux policyx Öv%d= ×MLSx Ø%d symbolsx Ù%d ocons =ÉÃâÁÿÿÿÿSPSS Portable Filex(%s =$FL2SPSS System Filex%s =%FS21Zope Object Database File Storage (data) =VMS Alpha executable=&PK, Info-ZIP SFX archive v5.12 w/decryption =NVRMVMware nvram =sLCDiDream Animator file =OggSOgg dataapplication/ogg!UNKNOWN REVISION %u== FLAC, FLAC audio="€theora, Theora video= $€kate, Katex%%v%ux&&.%u,=('utf8 encoding,!((unknown character encoding,><)language %s,=<*no language set,>L+category %s=L,no category set=.fishead, Skeletonx$/v%ux(0.%u=2Speex , Speex audio= 4video, OGM video=%5div3(DivX 3)=%6divx(DivX 4)=%7dx50(DivX 5)=%8xvid(XviD)=:vorbis, Vorbis audio,! #;UNKNOWN VERSION %lu,= #=='>mono,='?stereo,>'@%u channels,x (A%lu Hz< 0Cÿÿÿÿÿÿÿÿÿÿÿÿ,! 4Eÿÿÿÿÿÿÿÿ! 4I! 4Jüÿÿÿÿÿÿx 4K<%lu! 0Lÿÿÿÿÿÿÿÿx 0M~%lu! ,Nÿÿÿÿÿÿÿÿ! ,Oüÿÿÿÿÿÿ! ,Px ,Q>%lu< 0Rÿÿÿÿÿÿÿÿÿÿÿÿbps=TUZvorbis=T`[Xiphophorus libVorbis I, created by: Xiphophorus libVorbis I>Tx\00000000<Tx^20000508(Tx`20000508<Txa20001031(beta2-3)=Txb20001031(1.0 beta 3)>Txc20001031<Txd20010225(beta3-4)=Txe20010225(1.0 beta 4)>Txf20010225<Txg20010615(beta4-RC1)=Txh20010615(1.0 RC1)=Txi20010813(1.0 RC2)=Txj20010816(RC2 - Garf tuned v1)=Txk20011014(RC2 - Garf tuned v2)=Txl20011217(1.0 RC3)=Txm20011231(1.0 RC3)>Txo20011231(pre-1.0 CVS)=T`qXiph.Org libVorbis I, created by: Xiph.Org libVorbis I>Tur00000000<Tus20020717(pre-1.0 CVS)=Tut20020717(1.0)=Tuu20030909(1.0.1)=Tuv20040629(1.1.0 RC1) = ñÿÿÿÿmagic binary file for file(1) cmdx (version %d) (little endian) = ñÿÿÿÿmagic binary file for file(1) cmdx (version %d) (big endian) =Eðÿÿÿÿÿÿ0BSSBX archive data =  N,+GVXL data file,> schema version no %d ='ZEC3Zope Object Database Client Cache File (data) =>s²ôSquish archive data =:IMP IMP archive data =Ï­þMS Outlook Express DBX file=Åÿÿÿÿÿÿÿ, message database=Æÿÿÿÿÿÿÿ, folder database=Çÿÿÿÿÿÿÿ, account information=0, offline database =2sTaCLZS221 archive data =;ªªªª5View capture file =1VNFVisual Networks traffic capture file =,verEtherPeek/AiroPeek capture file =KOTTOOpenType font dataapplication/vnd.ms-opentype =&NetSNetStumbler log filex ', %d stations found =,QFQFC archive data =+FCQFC archive data = $xŸ>"Transport Neutral Encapsulation Format =rFATXFATX filesystem data =)Ora ELI 5750 archive data =.JAMJAM message area header file> /(%d messages) ='ÿÿÿþÿÿÿÿeDBTS archive data ='ûJQDOS executablex (€'%s' =<^ptchPalm OS operating system patch data>_"%s" =<\librPalm OS dynamic library data>]"%s" =<LzTXTA GutenPalm zTXT e-book>M"%s"=NNxNO(v0.%02d)=NPxNQ(v1.%02d)>N R<N S- 1 bookmark>N T- %d bookmarks>NU<NV- 1 annotation>NW- %d annotations>NX(v%d.xNY%02d) =+ûJQL plugin-ROM data,= ,€un-named> -€named: %s =ööööPC formatted floppy with no filesystem =Maple help database =?PMCCMS Windows 3.1 group files = E?_MS Windows 3.x help file =]eŒInstallShield Z archive Data =AB2ABComp archive data = W!BDNMicrosoft Outlook email folder= X(<=2002)= Y(>=2003) =Terse archive data = gWARQ archive data ='$Maple something=,EAn old revision=-RThe latest save =OZÃZET archive data =MP3MP3-Archiver archive data =øPPMZPPMZ archive data =ö,AR7AR7 archive data =ò-H2ODRY archive data =jregfMS Windows registry file, NT/2000 or above =kCREGMS Windows 95/98/ME registry file =BttcfTrueType font collection data=C, 1.0>D, %d fonts=E, 2.0>F, %d fonts=HGISD, digitally signed =x@€7V64 Nintendo 64 ROM dump = 'ESRI Shapefile== = = = x  version %dxlength %d= type Null Shape= type Point= type PolyLine= type Polygon= type MultiPoint=  type PointZ=  type PolyLineZ= type PolygonZ= type MultiPointZ= type PointM= type PolyLineM= type PolygonM= type MultiPointM= type MultiPatch =ØSChFChArc archive data =RGDBCRDA wireless regulatory database file=(Version 1) =Ðàÿÿÿÿÿÿ ÿvCDC Codec archive data =ÎXhDrX1 archive data =(*^ Mathematica notebook version 2.x =ÇPKReSOF archive data =rCSBKTed Neslson's CosmicBook hypertext file =»ŠSB\0 BSArc/BS2 archive data =tEYWRAmigaWriter file =·LIMLIM archive data =µMDmdMDCD archive data =³‘3HFHAP archive data =±HPAKHPack archive data =2‡ÖX image(= è4Ͳ¡extended tcpdump capture file (little-endian)x é- version %dx ê.%d= ë(No link-layer encapsulation= ì(Ethernet= í(3Mb Ethernet= î(AX.25= ï(ProNET= ð(CHAOS= ñ(Token Ring= ò(ARCNET= ó(SLIP= ô (PPP= õ (FDDI= ö (RFC 1483 ATM= ÷ (raw IP= ø (BSD/OS SLIP= ù(BSD/OS PPPx ú, capture length %d) =XBEHXBE, Microsoft Xbox executable=  = = ‘, not signed> ’ > “> ”, signed= –= `ÿ—€€, all regions ! `ÿ˜€€ > `ÿ™(regions: & `ÿšNA & `ÿ›Japan & `ÿœRest_of_World & `ÿ€Manufacturer> `ÿž) =KConvex old-style demand paged executable>not stripped(=Õ4Ͳ¡extended tcpdump capture file (big-endian)xÖ- version %dx×.%d=Ø(No link-layer encapsulation=Ù(Ethernet=Ú(3Mb Ethernet=Û(AX.25=Ü(ProNET=Ý(CHAOS=Þ(Token Ring=ß(ARCNET=à(SLIP=á (PPP=â (FDDI=ã (RFC 1483 ATM=ä (raw IP=å (BSD/OS SLIP=æ(BSD/OS PPPxç, capture length %d) = ™ÿÿ€€ÿÿÿÿHHYP archive dataapplication/x-arc = HG10Mercurial changeset bundle= UN(uncompressed)= GZ(gzip compressed)= BZ(bzip2 compressed) = —ÿÿ€€ÿÿÿÿARC+ archive dataapplication/x-arc = •ÿÿ€€ÿÿÿÿ PAK archive dataapplication/x-arc = ’ÿÿ€€ÿÿÿÿARC archive data, crunchedapplication/x-arc = ÿÿ€€ÿÿÿÿARC archive data, squeezedapplication/x-arc =old SGI 68020 executable =old SGI 68020 pure executable = Žÿÿ€€ÿÿÿÿARC archive data, packedapplication/x-arc = Œÿÿ€€ÿÿÿÿARC archive data, uncompressedapplication/x-arc = Šÿÿ€€ÿÿÿÿ ARC archive data, squashedapplication/x-arc =MFCSIRIS Showcase filex- version %ld =MFCTIRIS Showcase templatex- version %ld =¾º­ÞÿÿÿÿIRIX Parallel Arena>- version %ld = ˆÿÿ€€ÿÿÿÿARC archive data, dynamic LZWapplication/x-arc = î›PDP-11 4.0 archive = ~í›PDP-11 old archive =lênew-fs dump file (big endian),x  Previous dump %s,x  This dump %s,> Volume %ld,=´ Level zero, type:>´ Level %d, type:=tape header,=beginning of file record,=map of inodes on tape,=continuation of file record,=end of volume,=map of inodes deleted,=end of medium (for floppy),>¤Label %s,>¸Filesystem %s,>øDevice %s,>8Host %s,>xFlags %x = weÿold VAX archive= x__.SYMDEFrandom library =y\1cwChiWriter file = qmÿvery old VAX archive =prara<VAX 5.0 archive =mÿeVAX 3.0 archive =garchive =fSystem V Release 1 ar archive =¾ïOSF/Rose object =>archiveapplication/x-archive =’°­­ÞÿÿÿÿIRIX core dump=“of>”'%s' =–@­­ÞÿÿÿÿIRIX 64-bit core dump=—of>˜'%s' =š»À¾ºÿÿÿÿIRIX N32 core dump=›of>œ'%s' ==lapl workspace =;eÿold archive =9mÿvery old archive =ƒõíAdobe InDesign=„DOCUMENTDocument =õÁ ÞúÿÿÿÿMac OS X Detached Code Signature>ö(%d elements)x÷- %d bytes =òÀ ÞúÿÿÿÿMac OS X Detached Code Signature (non-executable)xó- %d bytes =í ÞúÿÿÿÿMac OS X Code Directoryxîversion %x> ïflags 0x%xxð- %d bytes =é ÞúÿÿÿÿMac OS X Code Requirement Set>êcontaining %d itemsxë- %d bytes =å ÞúÿÿÿÿMac OS X Code Requirement=æ(opExpr)xç- %d bytes =ákychMac OS X Keychain File =ÚcaffCoreAudio Format audio file<Û version %dxÜ =OLFOLF=invalid class=32-bit=64-bit=invalid os=OpenBSD=NetBSD=FreeBSD=4.4BSD=Linux=SVR4=esix=Solaris= Irix= SCO= Dell= NCR=invalid byte order= LSB= !no file type,= "relocatable,= #executable,= $shared object,= 'core file>8Ì(of '%s'> 8)(signal %d),& *ÿÿÿÿÿÿÿprocessor-specific,= +no machine,= ,AT&T WE32100 - invalid byte order,= -SPARC - invalid byte order,= .Intel 80386,= /Motorola 68000 - invalid byte order,= 0Motorola 88000 - invalid byte order,= 1Intel 80486,= 2Intel 80860,= 3MIPS R3000_BE - invalid byte order,= 4 Amdahl - invalid byte order,= 5 MIPS R3000_LE,= 6 RS6000 - invalid byte order,= 7PA-RISC - invalid byte order,= 8nCUBE,= 9VPP500,= :SPARC32PLUS,= ;PowerPC,= <&ÿÿÿÿÿÿAlpha,= =invalid version= >version 1= $?MathCoPro/FPU/MAU Required>@(%s)=AMSB=Bno file type,=Crelocatable,=Dexecutable,=Eshared object,=Fcore file,>8ÌGof '%s'>8H(signal %d),&Iÿÿÿÿÿÿÿprocessor-specific,=Jno machine,=KAT&T WE32100,=LSPARC,=MIntel 80386 - invalid byte order,=NMotorola 68000,=OMotorola 88000,=PIntel 80486 - invalid byte order,=QIntel 80860,=RMIPS R3000_BE,=S Amdahl,=T MIPS R3000_LE - invalid byte order,=U RS6000,=VPA-RISC,=WnCUBE,=XVPP500,=YSPARC32PLUS,=ZPowerPC or cisco 4500,=[cisco 7500,=\cisco SVIP,=]cisco 7200,=^$cisco 12000,=_&ÿÿÿÿÿÿAlpha,=`invalid version=aversion 1=$bMathCoPro/FPU/MAU Required =”ÿÿÿÿÿÿÿÐdApple Mechanic font =·zMirage Assembler m.out executable =nÿÿApplesoft BASIC program data =6PFR1PFR1 font>f70: %s =2IMGApple ][ 2IMG Disk Image=XGS!, XGS=CTKG, Catakig=ShIm, Sheppy's ImageMaker=WOOF, Sweet 16=B2TR, Bernie ][ the Rescue!nfc, ASIMOV2x, Unknown Format= , DOS 3.3 sector order=, Volume 254x, Volume %u= , ProDOS sector orderx, %u Blocks= , NIB data = AppleDouble encoded Macintosh file = ðÞÀÿÿÿÿGStreamer binary registryx, version %s = AppleSingle encoded Macintosh file =lAPL workspace (Ken's original?) = wsdlPHP WSDL cache,x version 0x%02xx  , created %s< ÿÿÿx , uri: "%s"< ÿÿÿx üÿÿÿ, source: "%s"< ÿÿÿx üÿÿÿ, target_ns: "%s" =vBBCDBBC Dirac Video = Í«ÿÿÿÿÿÿMLSSA datafile,x algorithm %d,x %d samples =MMDF mailbox =qTHPNintendo THP Multimedia =NPFFNItpicker Flow File xV%d.x%dx  started: %sx stopped: %sx Bytes: %ux Bytes1: %ux Flows: %uxPkts: %u = H+zX11/NeWS font family =RMD1raw modem data>(%s />compression type 0x%04x) =kêold-fs dump file (big endian),> Volume %ld,=´Level zero, type:>´ Level %d, type:=!tape header,="beginning of file record,=#map of inodes on tape,=$continuation of file record,=%end of volume,=&map of inodes deleted,='end of medium (for floppy),>¤(Label %s,>¸)Filesystem %s,>ø*Device %s,>8+Host %s,>x,Flags %x = 5zPsion Series 5 executable = E+zX11/NeWS bitmap font = Q)zencrypted scalable OpenFont binary = P)zscalable OpenFont binary = G)zNeWS font family =D)zNeWS bitmap font =jFILMSega FILM/CPK Multimedia,x k%d xxl%d =*ðÿÿÿÿÿÿÿ`Atari ST M68K contiguous executablex+(txt=%ld,x,dat=%ld,x -bss=%ld,x.sym=%ld) =/ðÿÿÿÿÿÿÿ`Atari ST M68K non-contig executablex0(txt=%ld,x1dat=%ld,x 2bss=%ld,x3sym=%ld) =TAMVSMTV Multimedia File =ORED1REDCode Video =JNSVfNullsoft Video =¢XIP0XIP, Microsoft Xbox data =2DIVDOS code page font data (from Linux?) = 'yPsion Series 5 binary:= (DLL= )Icomms hardware library= *Jcomms protocol library= +]OPX= ,lapplication= -DLL= .¬logical device driver= /­physical device driver= 0åfile transfer protocol= 1åfile transfer protocol= 2@printer definition= 3Aprinter definition =1AGEDOS code page font data = BINetscape Communicator address book =0NOFÿÿÿÿÿDOS code page font data collection =úÿÿÊNetBSD kernel core file=ûÿ, Unknown=üÿ, sun 68010/68020=ýÿ, sun 68020=þÿd, 386 PC=ÿÿ†, i386 BSD=ÿ‡, m68k BSD (8K pages)=ÿˆ, m68k BSD (4K pages)=ÿ‰, ns32532 BSD=ÿŠ, sparc/32 BSD=ÿ‹, pmax BSD=ÿŒ, vax BSD (1K pages)=ÿ, alpha BSD=ÿŽ, mips BSD (Big Endian)=ÿ, arm6 BSD= ÿ, m68k BSD (2K pages)= ÿ‘, sh3 BSD= ÿ’, ppc BSD (Big Endian)= ÿ“, vax BSD (4K pages)= ÿ”, mips1 BSD=ÿ•, mips2 BSD=ÿ–, parisc BSD=ÿ—, sh5/64 BSD=ÿ˜, sparc/64 BSD=ÿ™, amd64 BSD=ÿš, hp200 (68010) BSD=ÿ›, hp300 (68020+68881) BSD=ÿ›, hp300 (68020+68881) BSD=ÿÈ, hp200=ÿ , hp300 (68020+68881) HP-UX=ÿ , hp300 (68020+68881) HP-UX=üÿÿÿÿ, CPU=üÿÿÿÿ, DATA=üÿÿÿÿ, STACKx , (headersize = %dx , segmentsize = %dx , segments = %d) =õÿÿÿGa.out NetBSD/arm core> öfrom '%s'! ÷(signal %d) =ìÿÿÿa.out NetBSD/arm32&í€ÿÿÿÿÿÿÿdynamically linked executable^î€ÿÿÿÿÿÿÿ&ï@position independent! ðexecutable= ñobject file> ònot stripped =èÿÿÿa.out NetBSD/arm32 pure&é€ÿÿÿÿÿÿÿdynamically linked executable^ê€ÿÿÿÿÿÿÿexecutable> ënot stripped =áÿÿÿ a.out NetBSD/arm32 demand paged&â€ÿÿÿÿÿÿÿ< ãshared library= ädynamically linked executable> ådynamically linked executable^æ€ÿÿÿÿÿÿÿexecutable> çnot stripped =ÝÿÿÿGŽa.out NetBSD/mips core> Þfrom '%s'! ß(signal %d) =+YlibGrx font data,x ,%dxx -%dx(.%s =ÖÿÿÿŽa.out NetBSD/mips&×€ÿÿÿÿÿÿÿdynamically linked executable^Ø€ÿÿÿÿÿÿÿ&Ù@position independent!Úexecutable=Ûobject file>Ünot stripped =£XTF0XTF, Microsoft Xbox data =ÒÿÿÿŽa.out NetBSD/mips pure&Ó€ÿÿÿÿÿÿÿdynamically linked executable^Ô€ÿÿÿÿÿÿÿexecutable>Õnot stripped(= ‘ëÿÿDR-DOS executable (COM) =Ëÿÿÿ Ža.out NetBSD/mips demand paged&Ì€ÿÿÿÿÿÿÿ<Í shared library=Î dynamically linked executable>Ï dynamically linked executable^Ѐÿÿÿÿÿÿÿexecutable>Ñnot stripped =ÇÿÿÿGa.out NetBSD/alpha core> Èfrom '%s'! É(signal %d) = Ä…ECOFF NetBSD/alpha binary= Ånot stripped= Æstripped = #PPsion Series 5= $mdatabase= %äini file =½ÿÿÿG–a.out NetBSD/vax 4k core> ¾from '%s'! ¿(signal %d) =¶ÿÿÿ–a.out NetBSD/vax 4k&·€ÿÿÿÿÿÿÿdynamically linked executable^¸€ÿÿÿÿÿÿÿ&¹@position independent! ºexecutable= »object file> ¼not stripped =specSPEC= .cpuCPU< :%.4s= .raw result text ="³UPX!FREE-DOS executable (COM), UPX compressed =#´UPX!FREE-DOS executable (COM), UPX compressed =²ÿÿÿ–a.out NetBSD/vax 4k pure&³€ÿÿÿÿÿÿÿdynamically linked executable^´€ÿÿÿÿÿÿÿexecutable> µnot stripped =«ÿÿÿ –a.out NetBSD/vax 4k demand paged&¬€ÿÿÿÿÿÿÿ< ­shared library= ®dynamically linked executable> ¯dynamically linked executable^°€ÿÿÿÿÿÿÿexecutable> ±not stripped =§ÿÿÿGŒa.out NetBSD/vax 1k core> ¨from '%s'! ©(signal %d) = ÿÿÿŒa.out NetBSD/vax 1k&¡€ÿÿÿÿÿÿÿdynamically linked executable^¢€ÿÿÿÿÿÿÿ&£@position independent! ¤executable= ¥object file> ¦not stripped =œÿÿÿŒa.out NetBSD/vax 1k pure&€ÿÿÿÿÿÿÿdynamically linked executable^ž€ÿÿÿÿÿÿÿexecutable> Ÿnot stripped =•ÿÿÿ Œa.out NetBSD/vax 1k demand paged&–€ÿÿÿÿÿÿÿ< —shared library= ˜dynamically linked executable> ™dynamically linked executable^š€ÿÿÿÿÿÿÿexecutable> ›not stripped =‘ÿÿÿG‹a.out NetBSD/pmax core> ’from '%s'! “(signal %d) =Šÿÿÿ‹a.out NetBSD/pmax&‹€ÿÿÿÿÿÿÿdynamically linked executable^Œ€ÿÿÿÿÿÿÿ&@position independent! Žexecutable= object file> not stripped =†ÿÿÿ‹a.out NetBSD/pmax pure&‡€ÿÿÿÿÿÿÿdynamically linked executable^ˆ€ÿÿÿÿÿÿÿexecutable> ‰not stripped =ÿÿÿ ‹a.out NetBSD/pmax demand paged&€€ÿÿÿÿÿÿÿ< shared library= ‚dynamically linked executable> ƒdynamically linked executable^„€ÿÿÿÿÿÿÿexecutable> …not stripped ={ÿÿÿGŠa.out NetBSD/sparc core> |from '%s'! }(signal %d) =tÿÿÿŠa.out NetBSD/sparc&u€ÿÿÿÿÿÿÿdynamically linked executable^v€ÿÿÿÿÿÿÿ&w@position independent!xexecutable=yobject file>znot stripped = !APsion Series 5 ROM multi-bitmap image =pÿÿÿŠa.out NetBSD/sparc pure&q€ÿÿÿÿÿÿÿdynamically linked executable^r€ÿÿÿÿÿÿÿexecutable>snot stripped =Ö‹JNGJNG video data,video/x-jng!Ø  CORRUPTED,=Ù  xÚ%ld xxÛ%ld =ΊMNGMNG video data,video/x-mng!Ð  CORRUPTED,=Ñ  xÒ%ld xxÓ%ld =Êu²&0Microsoft ASFvideo/x-ms-asf =ÃÿÿÿÿÿÿÿDIF&Ä(DVCPRO) movie file^Å(DV) movie file&Æ€ÿÿÿÿÿÿÿ(PAL)^Ç€ÿÿÿÿÿÿÿ(NTSC) =¿ÿ_ÿÿÿÿÿ@GMPEG transport stream data!¼ÀGCORRUPTED =ë¾1Microsoft Word Documentapplication/msword = 7Psion Series 5=  9font file=  :printer driver=  ;clipboard=  Bmulti-bitmap imageimage/x-epoc-mbm= japplication information file= m= }Sketch imageimage/x-epoc-sketch= ~voice note= Word fileapplication/x-epoc-word= …OPL program (TextEd)application/x-epoc-opl= ˆSheet fileapplication/x-epoc-sheet= ÄEasyFax initialisation file= sOPO moduleapplication/x-epoc-opo= tOPL applicationapplication/x-epoc-app= Šexported multi-bitmap image =ñ@þ7#Microsoft Office Documentapplication/msword =,ADIFMPEG ADIF, AACaudio/x-hx-aac-adif&.€ÿÿÿÿÿÿÿ& /, VBR^ 0, CBR=1, single stream=2, 2 streams=3, 3 streams&4, 4 or more streams&5, 8 or more streams&6€ÿÿÿÿÿÿÿ, Copyrighted& 7@, Original Source& 8 , Home Flag^9€ÿÿÿÿÿÿÿ&:, VBR^;, CBR=<, single stream==, 2 streams=>, 3 streams&?, 4 or more streams&@, 8 or more streams&A@, Original Stream(s)&B , Home Source =iÿÿÿ Ša.out NetBSD/sparc demand paged&j€ÿÿÿÿÿÿÿ<k shared library=l dynamically linked executable>m dynamically linked executable^n€ÿÿÿÿÿÿÿexecutable>onot stripped = ÖÃÄVCDIFF binary diff =corecore file (Xenix) = .lênew-fs dump file (little endian),x /This dump %s,x 0Previous dump %s,> 1Volume %ld,= ´2Level zero, type:> ´3Level %d, type:= 4tape header,= 5beginning of file record,= 6map of inodes on tape,= 7continuation of file record,= 8end of volume,= 9map of inodes deleted,= :end of medium (for floppy),>¤;Label %s,>¸<Filesystem %s,>ø=Device %s,>8>Host %s,> x?Flags %x = RTSSNetMon capture filex - version %dx.%d= (Unknown)= (Ethernet)= (Token Ring)= (FDDI)= (ATM) = 6b.out& 7overlay& 8separate& 9pure& :segmented& ;standalone& <executable^ =object file& >@V2.3& ?€ÿÿÿÿÿÿV3.0&@86&A 186&B 286&C)286&D 386& ELarge Text& FLarge Data& GHuge Objects Enabled =Lotus 1-2-3application/x-123= wk3 document data= wk4 document data= €fm3 or fmb document data= €fm3 or fmb document data =Lotus 1-2-3application/x-123=wk1 document data=€fmt document data =Uznaxo65 object,x version %d,=  with debug info=  no debug info = naUzxo65 library,x version %d = GConvex old-style object> not stripped =fcpX11 Portable Compiled Font data= , LSB first=  , MSB first =$@×ÍÆšms-windows metafont .wmf =%@ ms-windows metafont .wmf =&@ ms-windows metafont .wmf =#ftypISO Media=$isom, MPEG v4 system, version 1video/mp4=&iso2, MPEG v4 system, part 12 revision='mp41, MPEG v4 system, version 1video/mp4=)mp42, MPEG v4 system, version 2video/mp4=+mp7t, MPEG v4 system, MPEG v7 XML=,mp7b, MPEG v4 system, MPEG v7 binary XML=-jp2, JPEG 2000image/jp2=/3ge, MPEG v4 system, 3GPPvideo/3gpp=13gg, MPEG v4 system, 3GPPvideo/3gpp=33gp, MPEG v4 system, 3GPPvideo/3gpp=53gs, MPEG v4 system, 3GPPvideo/3gpp=73g2, MPEG v4 system, 3GPP2video/3gpp2= 9 v4 (H.263/AMR GSM 6.10)= : v5 (H.263/AMR GSM 6.10)= ; v6 (ITU H.264/AMR GSM 6.10)=<mmp4, MPEG v4 system, 3GPP Mobilevideo/mp4=>avc1, MPEG v4 system, 3GPP JVT AVCvideo/3gpp=@M4A, MPEG v4 system, iTunes AAC-LCaudio/mp4=BM4V, MPEG v4 system, iTunes AVC-LCvideo/mp4=DM4P, MPEG v4 system, iTunes AES encrypted=EM4B, MPEG v4 system, iTunes bookmarked=Fqt, Apple QuickTime movievideo/quicktime = Akêold-fs dump file (little endian),> DVolume %ld,= ´ELevel zero, type:> ´FLevel %d, type:= Gtape header,= Hbeginning of file record,= Imap of inodes on tape,= Jcontinuation of file record,= Kend of volume,= Lmap of inodes deleted,= Mend of medium (for floppy),>¤NLabel %s,>¸OFilesystem %s,>øPDevice %s,>8QHost %s,> xRFlags %x =pckgApple QuickTime compressed archiveapplication/x-quicktime-player =idscApple QuickTime image (fast start)image/x-quicktime =mdatApple QuickTime movie (unoptimized)video/quicktime = moovApple QuickTimevideo/quicktime= mvhd movie (fast start)= mdra URL= cmov movie (fast start, compressed header)= rmra multiple URLs = MOVISilicon Graphics movie filevideo/x-sgi-movie ==KICKKickstart disk =<DOSAmiga Fastdir FFS disk =;DOSAmiga Fastdir DOS disk =:DOSAmiga Inter FFS disk =>@MS Windows icon resourceimage/x-icon=@- 1 icon>A- %d icons>B, %dx>C%d=D, 256-colors>E, %d-colors =9DOSAmiga Inter DOS disk =8DOSAmiga FFS disk =*PcPhPCP Help=+1Index=,2Text>-(V.%1.1s) = X11 SNF font data, LSB first =eÿÿÿÿÿÿÿPFM data=f>g0- %s =iÿÿÿÿÿÿÿPFM data=j>k0- %s =7DOSAmiga DOS disk =5RDSKRigid Disk Blockx 6on %.24s =X11 SNF font data, MSB first(= Ôò¡tcpdump capture file (little-endian)application/vnd.tcpdump.pcapx - version %dx .%d= ‘(No link-layer encapsulation= ’(Ethernet= “(3Mb Ethernet= ”(AX.25= •(ProNET= –(CHAOS= —(Token Ring= ˜(ARCNET= ™(SLIP= š (PPP= › (FDDI= œ (RFC 1483 ATM=  (raw IP= ž (BSD/OS SLIP= Ÿ(BSD/OS PPP=  (Linux ATM Classical IP= ¡2(PPP or Cisco HDLC= ¢3(PPP-over-Ethernet= £c(Symantec Enterprise Firewall= ¤d(RFC 1483 ATM= ¥e(raw IP= ¦f(BSD/OS SLIP= §g(BSD/OS PPP= ¨h(BSD/OS Cisco HDLC= ©i(802.11= ªj(Linux Classical IP over ATM= «k(Frame Relay= ¬l(OpenBSD loopback= ­m(OpenBSD IPsec encrypted= ®p(Cisco HDLC= ¯q(Linux "cooked"= °r(LocalTalk= ±u(OpenBSD PFLOG= ²w(802.11 with Prism header= ³z(RFC 2625 IP over Fibre Channel= ´{(SunATM= µ(802.11 with radiotap header= ¶(Linux ARCNET= ·Š(Apple IP over IEEE 1394= ¸Œ(MTP2= ¹(MTP3= º(DOCSIS= »(IrDA= ¼“(Private use 0= ½”(Private use 1= ¾•(Private use 2= ¿–(Private use 3= À—(Private use 4= Á˜(Private use 5= ™(Private use 6= Ú(Private use 7= Ä›(Private use 8= Åœ(Private use 9= Æ(Private use 10= Çž(Private use 11= ÈŸ(Private use 12= É (Private use 13= Ê¡(Private use 14= Ë¢(Private use 15= Ì£(802.11 with AVS headerx Í, capture length %d) =-€ÿÿÿÿAmigaOS outline tag =xDCU1Borland Delphi .DCU file =Î Jaleo XFS filex- version %ldx- [%ld -x%ldxx%ldx=ðYUV422]=èRGB24] = XcurXcursor dataimage/x-xcursorx "version %hdx #.%hd = }pkTurboC BGI file = ~PKTurboC Font file =fÿÿÿG•a.out NetBSD/powerpc core> gfrom '%s' =bÿÿÿG‰a.out NetBSD/ns32532 core> cfrom '%s'! d(signal %d) =[ÿÿÿ‰a.out NetBSD/ns32532&\€ÿÿÿÿÿÿÿdynamically linked executable^]€ÿÿÿÿÿÿÿ&^@position independent! _executable= `object file> anot stripped =ŠPMCCWindows 3.x .GRP file =`Tnew-fs dump file (ufs2, big endian),x€aPrevious dump %s,xˆbThis dump %s,> cVolume %ld,=´dLevel zero, type:>´eLevel %d, type:=ftape header,=gbeginning of file record,=hmap of inodes on tape,=icontinuation of file record,=jend of volume,=kmap of inodes deleted,=lend of medium (for floppy),>¤mLabel %s,>¸nFilesystem %s,>øoDevice %s,>8pHost %s,>xqFlags %x =SCVMScummVM savegame> "%s" =@CT T602 document data,=0Kamenicky=1CP 852= 2KOI8-CS> 2unknown encoding =´ÆÓÐÅÿÿÿÿDOS EPS Binary File>µPostscript starts at byte %d>¶length %d> ·Metafile starts at byte %d>¸length %d>¹TIFF starts at byte %d>ºlength %d =Wÿÿÿ‰a.out NetBSD/ns32532 pure&X€ÿÿÿÿÿÿÿdynamically linked executable^Y€ÿÿÿÿÿÿÿexecutable> Znot stripped ="ARP.The Holy Noise Module sound file =SMODFuture Composer 1.3 Module sound file =FC14Future Composer 1.4 Module sound file =Ñ@ISc(InstallShield Cabinet archive data=Òðÿÿÿÿÿÿÿ`version 6,!Óðÿÿÿÿÿÿÿ`version 4/5,x  (Ô%u files = çAmigaOS object/library data =ÿþUnicode text, UTF-32, little-endian =ï@COWDVMWare3=ðdisk imagex ñ(%d/x $ò%d/x (ó%d)=ôundoable disk image> õ(%s) =÷@VMDKVMware4 disk image =ø@KDMVVMware4 disk image =@QFIûQEMU QCOW Image=(v1)> , has backing file (> path %s> , mtime %s)x)x, %lld bytes=$, AES-encrypted=(v2)>", has backing file> *(path %s)x+, %lld bytes= ,, AES-encryptedx.(unknown version) =0@QEVMQEMU suspend to disk image = óAmigaOS loadseg()ble executable/binary = 6ΊFBochs Sparse disk image = úAmigaOS shared library =Pÿÿÿ ‰a.out NetBSD/ns32532 demand paged&Q€ÿÿÿÿÿÿÿ< Rshared library= Sdynamically linked executable> Tdynamically linked executable^U€ÿÿÿÿÿÿÿexecutable> Vnot stripped = èobject file (z8000 a.out) =ÑSMVSNES9x input recordingx Ò, version %d< Ôx Õ, recorded at %s> Ö, rerecorded %d timesx ×, %d frames long>Ø, data for controller(s):&Ù#1&Ú#2&Û#3&Ü#4&Ý#5^Þ, begins from snapshot&ß, begins from reset^à, NTSC standard&á, PAL standard&â, settings:< ä&åWIP1Timing&æLeft+Right&çVolumeEnvX&èFakeMute&é SyncSound> ë&ì€ÿÿÿÿÿÿÿNoCPUShutdown< í> î#! ïx ð, metadata: "%s"> ñ>$ò, port 1:=$ójoypad=$ômouse=$õSuperScope=$öJustifier=$÷multitap>$ø, port 2:=%ùjoypad=%úmouse=%ûSuperScope=%üJustifier=%ýmultitap> þC! @ÿx@, metadata: "%s"&@, ROM:x CRC32 0x%08xx "%s" = +hlsAllegro datafile (appended exe data) =LÿÿÿGˆa.out NetBSD/m68k4k core> Mfrom '%s'! N(signal %d) =.hlsAllegro datafile (not packed/autodetect) =!hlsAllegro datafile (packed) =.GlulGlulx game datax/(Version %dx0.%dx1.%d)=$2InfoCompiled by Inform =£ßEEBML file=d@B‚x, creator %.8s = èpure object file (z8000 a.out) = èseparate object file (z8000 a.out) = èoverlay object file (z8000 a.out) =GMBUNetMon capture filex- version %dx.%d= (Unknown)= (Ethernet)= (Token Ring)= (FDDI)= (ATM) = sTnew-fs dump file (ufs2, little endian),x€tThis dump %s,xˆuPrevious dump %s,> vVolume %ld,= ´wLevel zero, type:> ´xLevel %d, type:= ytape header,= zbeginning of file record,= {map of inodes on tape,= |continuation of file record,= }end of volume,= ~map of inodes deleted,= end of medium (for floppy),>¤€Label %s,>¸Filesystem %s,>ø‚Device %s,>8ƒHost %s,> x„Flags %x =ð Microsoft Visual C library =ð=Microsoft Visual C library =ð}Microsoft Visual C library ==XCPNetXRay capture file>>- version %s= ,?(Ethernet)= ,@(Token Ring)= ,A(FDDI)= ,B(WAN)= ,C(ATM)= ,D (802.11) =DrawRISC OS Draw file data = í-python 2.2 byte-compiled =)MSVC .bsc = ïÿÿÿÿRISC OS AIF executable =Eÿÿÿˆa.out NetBSD/m68k4k&F€ÿÿÿÿÿÿÿdynamically linked executable^G€ÿÿÿÿÿÿÿ&H@position independent!Iexecutable=Jobject file>Knot stripped(=LÔò¡tcpdump capture file (big-endian)application/vnd.tcpdump.pcapxN- version %dxO.%d=P(No link-layer encapsulation=Q(Ethernet=R(3Mb Ethernet=S(AX.25=T(ProNET=U(CHAOS=V(Token Ring=W(BSD ARCNET=X(SLIP=Y (PPP=Z (FDDI=[ (RFC 1483 ATM=\ (raw IP=] (BSD/OS SLIP=^(BSD/OS PPP=_(Linux ATM Classical IP=`2(PPP or Cisco HDLC=a3(PPP-over-Ethernet=bc(Symantec Enterprise Firewall=cd(RFC 1483 ATM=de(raw IP=ef(BSD/OS SLIP=fg(BSD/OS PPP=gh(BSD/OS Cisco HDLC=hi(802.11=ij(Linux Classical IP over ATM=jk(Frame Relay=kl(OpenBSD loopback=lm(OpenBSD IPsec encrypted=mp(Cisco HDLC=nq(Linux "cooked"=or(LocalTalk=pu(OpenBSD PFLOG=qw(802.11 with Prism header=rz(RFC 2625 IP over Fibre Channel=s{(SunATM=t(802.11 with radiotap header=u(Linux ARCNET=vŠ(Apple IP over IEEE 1394=wŒ(MTP2=x(MTP3=y(DOCSIS=z(IrDA={“(Private use 0=|”(Private use 1=}•(Private use 2=~–(Private use 3=—(Private use 4=€˜(Private use 5=™(Private use 6=‚š(Private use 7=ƒ›(Private use 8=„œ(Private use 9=…(Private use 10=†ž(Private use 11=‡Ÿ(Private use 12=ˆ (Private use 13=‰¡(Private use 14=Š¢(Private use 15=‹£(802.11 with AVS headerxŒ, capture length %d) = RSRCNational Instruments,=LVLabVIEW File,= SBCode Resource File, data= INVirtual Instrument Program, data= ARVI Library, data=LMNULBVWPortable File Names, data=rscResources File, data =VMAPNational Instruments, VXI File, data =Aÿÿÿˆa.out NetBSD/m68k4k pure&B€ÿÿÿÿÿÿÿdynamically linked executable^C€ÿÿÿÿÿÿÿexecutable>Dnot stripped =:ÿÿÿ ˆa.out NetBSD/m68k4k demand paged&;€ÿÿÿÿÿÿÿ<<shared library==dynamically linked executable>>dynamically linked executable^?€ÿÿÿÿÿÿÿexecutable>@not stripped =6ÿÿÿG‡a.out NetBSD/m68k core> 7from '%s'! 8(signal %d) =/ÿÿÿ‡a.out NetBSD/m68k&0€ÿÿÿÿÿÿÿdynamically linked executable^1€ÿÿÿÿÿÿÿ&2@position independent!3executable=4object file>5not stripped =+ÿÿÿ‡a.out NetBSD/m68k pure&,€ÿÿÿÿÿÿÿdynamically linked executable^-€ÿÿÿÿÿÿÿexecutable>.not stripped =$ÿÿÿ ‡a.out NetBSD/m68k demand paged&%€ÿÿÿÿÿÿÿ<& shared library=' dynamically linked executable>( dynamically linked executable^)€ÿÿÿÿÿÿÿexecutable>*not stripped = ÿÿÿG†a.out NetBSD/i386 core> !from '%s'! "(signal %d) = a.out NetBSD little-endian object file>  not stripped = a.out NetBSD big-endian object file> not stripped =ÿÿÿ †a.out NetBSD/i386 demand paged&€ÿÿÿÿÿÿÿ< shared library= dynamically linked executable> dynamically linked executable^€ÿÿÿÿÿÿÿexecutable> not stripped =ÿÿÿ†a.out NetBSD/i386 pure&€ÿÿÿÿÿÿÿdynamically linked executable^€ÿÿÿÿÿÿÿexecutable> not stripped =ÿÿÿ†a.out NetBSD/i386&€ÿÿÿÿÿÿÿdynamically linked executable^€ÿÿÿÿÿÿÿ&@position independent! executable= object file> not stripped@=+1\documentstyleLaTeX document texttext/x-tex =yOAK=z= {Oak Technologies printer stream =HP3=8HP 38=9HP 39=Binbinary=AscASCII=A(Directory List)=B(Zaplet)=C(Note)=D(Program)=E(Variable)=F(List)=G(Matrix)=H(Library)=I(Target List)=J(ASCII Vector specification)=K(wildcard) =DOC=+ŽJust System Word Processor Ichitaro v4application/x-ichitaro4=JDASHapplication/x-ichitaro4@=c% BibTeX standard bibliography BibTeX standard bibliography style text file =ýHP3=þ8HP 38=ÿ9HP 39=Binbinary=AscASCII=A(Directory List)=B(Zaplet)=C(Note)=D(Program)=E(Variable)=F(List)=G(Matrix)= H(Library)= I(Target List)= J(ASCII Vector specification)= K(wildcard)@=eval '(exit $?0)' && eval 'execPerl script texttext/x-perl@=Decode the following with bdecobencoded News text =0SaR=1tCups Raster version 1, Little Endian=22Cups Raster version 2, Little Endian=33Cups Raster version 3, Little Endianapplication/vnd.cups-rasterx 5, %dx 6x%d dpix x7, %dxx |8%d pixelsx „9%d bits/colorx ˆ:%d bits/pixel= ;ColorOrder=Chunky= <ColorOrder=Banded= =ColorOrder=Planar= ”>ColorSpace=gray= ”?ColorSpace=RGB= ”@ColorSpace=RGBA= ”AColorSpace=black= ”BColorSpace=CMY= ”CColorSpace=YMC= ”DColorSpace=CMYK= ”EColorSpace=YMCK= ”FColorSpace=KCMY= ”G ColorSpace=KCMYcm= ”H ColorSpace=GMCK= ”I ColorSpace=GMCS= ”J ColorSpace=WHITE= ”K ColorSpace=GOLD= ”LColorSpace=SILVER= ”MColorSpace=CIE XYZ= ”NColorSpace=CIE Lab= ”OColorSpace=RGBW= ”PColorSpace=sGray= ”QColorSpace=sRGB= ”RColorSpace=AdobeRGB = RaSapplication/vnd.cups-raster= tCups Raster version 1, Big Endian= 2Cups Raster version 2, Big Endian=3Cups Raster version 3, Big Endianx, %dxx%d dpixx, %dxx|%d pixelsx„%d bits/colorxˆ%d bits/pixel=ColorOrder=Chunky=ColorOrder=Banded=ColorOrder=Planar=”ColorSpace=gray=”ColorSpace=RGB=”ColorSpace=RGBA=”ColorSpace=black=”ColorSpace=CMY=”ColorSpace=YMC=”ColorSpace=CMYK=”ColorSpace=YMCK=” ColorSpace=KCMY=”! ColorSpace=KCMYcm=”" ColorSpace=GMCK=”# ColorSpace=GMCS=”$ ColorSpace=WHITE=”% ColorSpace=GOLD=”&ColorSpace=SILVER=”'ColorSpace=CIE XYZ=”(ColorSpace=CIE Lab=”)ColorSpace=RGBW=”*ColorSpace=sGray=”+ColorSpace=sRGB=”,ColorSpace=AdobeRGB =><Spectrum .TAP data "%-10.10s"=- BASIC program=- number array=- character array= - memory block=!@(screen) =–DOC=+—Just System Word Processor Ichitaro v6application/x-ichitaro6 =’DOC=+“Just System Word Processor Ichitaro v5application/x-ichitaro5@=^[ ]*require[ ]'[A-Za-z_/]+'=include [A-Z]|def [a-z]| do$=^[ ]*end([ ]*[;#].*)?$Ruby script texttext/x-ruby =õ@ì¥ÁMicrosoft Word Documentapplication/msword =æVTIVirtual TI skin=çv- Version>è %cxé.%c =çTOCTOC sound file =`SBISoundBlaster instrument dataaudio/x-unknown =zMEDMED_Song =}THXAHX version=~1 module data=2 module data =€zPQZPAQ streamx, level %d = þMicrostation==EDGNFile=EDGNFile= ;GDGNFile=!;HDGNFile="FGDGNFile=#HCDGNFile=$PDDGNFile=%zDDGNFile=&zEDGNFile='zFDGNFile=(œFDGNFile=)»EDGNFile=*ÆFDGNFile=+ÈDDGNFile=,áDDGNFile=-úCDGNFile=.úDDGNFile=/úFDGNFile=0þCDGNFile=1CITFile=2CITFile =-lzLZS archive data =-lZPUT archive data =ÃPAQPAQ archive data=Äðÿÿÿÿÿÿÿ0xÅ(v%c) =mscMessage Sequence Chart (chart) =LBZhbzip2 compressed dataapplication/x-bzip2>N/, block size = %c00k =¤AMFAMF Module>¥Title: "%s" =µGBSNintendo Gameboy Music/Audio Data =þÿUnicode text, SCSU (Standard Compression Scheme for Unicode) =C@”¦.Microsoft Word Documentapplication/msword =,RoRAMUSIC Adlib Tracker =WRRDRRDTool DBxXversion %s =ÜICEICE authority data =@LZXLZX compressed archive (Amiga) =4@KLFFreeDOS KEYBoard Layout filex 6, version 0x%x>8x9, name=%-.2s =)@KCFFreeDOS KEYBoard Layout collectionx +, version 0x%x>->/, author=%-.14s=0þÿ, info=x2%-.15s =ÀZZ0ZZip archive data =.ÿÿddis/ddif =/ÿÿ|ddis/dots archive =0ÿÿ~ddis/dtif table data =1cLN03 output =JCHEdLib =ÅDSQuantum archive data = xkmCompiled XKB Keymap: msb,> version %d= obsolete =mkxCompiled XKB Keymap: lsb,> version %d= obsolete =:) Smile binary dataxðÿÿÿÿÿÿÿversion %d:=binary raw,=binary encoded,=shared String values enabled,=shared String values disabled,= shared field names enabled=!shared field names disabled = QL5QL disk dump data,= A720 KB,= B1.44 MB,= C3.2 MB,> label:%.10s =WPC(Corel/WP)=WordPerfect macro=WordPerfect help file=WordPerfect keyboard file= WordPerfect document= WordPerfect dictionary= WordPerfect thesaurus= WordPerfect block=WordPerfect rectangular block=WordPerfect column block=WordPerfect printer data=WordPerfect printer data=WordPerfect driver resource data= WordPerfect hyphenation code=!WordPerfect hyphenation data="WordPerfect macro resource data=#WordPerfect hyphenation lex=$WordPerfect wordlist=%WordPerfect equation resource data=&!WordPerfect spell rules='"WordPerfect dictionary rules=('WordPerfect spell rules (Microlytics)=)+WordPerfect settings file=*-WordPerfect 4.2 document=+EWordPerfect dialog file=,LWordPerfect button bar=-Shell macro=. Shell definition=/Notebook macro=0Notebook help file=1Notebook keyboard file=2 Notebook definition=3Calculator help file=4Calendar help file=5 Calendar data file=6Editor macro=7Editor help file=8Editor keyboard file=9Editor macro resource file=:Macro editor macro=;Macro editor help file=<Macro editor keyboard file== PlanPerfect macro=> PlanPerfect help file=? PlanPerfect keyboard file=@ PlanPerfect worksheet=A PlanPerfect printer definition=B PlanPerfect graphic definition=C PlanPerfect data=D PlanPerfect temporary printer=E PlanPerfect macro resource data=F Mail=G help file=H distribution list=I out box=J in box=K users archived mailbox=L archived message database=M archived attachments=N Printer temporary file=O Scheduler help file=P Scheduler in file=Q Scheduler out file=R GroupWise settings file=SGroupWise directory services=T+GroupWise settings file=U Terminal resource data=V Terminal resource data=W+Terminal resource data=X GUI loadable text=Y graphics resource data=Z printer settings file=[port definition file=\print queue parameters=]compressed file=^ Network service msg file=_ Network service msg file=` Async gateway login msg=aGroupWise message file=bGroupWise admin domain database=cGroupWise admin host database=dGroupWise admin remote host database=eGroupWise admin ADS deferment data file=f !IntelliTAG (SGML) compiled DTD=gWordPerfect graphic image (1.0)=hWordPerfect graphic image (2.0) =«xpaXPack archive data = ®BSN archive data =Ÿ®BSN archive data =ž®BSN archive data =™WWPWWPack archive data =•UHBUHBC archive data =‰PDZPDZ archive data =‡VSVSARC archive data =žDitPack archive data = GLBinary II (apple ][) data ==MP+Musepack audio=>ÿÿÿÿÿÿÿÿ, SV pre8=?, SV 6=@, SV 8=A, SV 7=Bðÿÿÿÿÿÿÿ.0=Cðÿÿÿÿÿÿÿ.1=Dðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿ.15= Eðÿÿÿÿÿÿÿ, no profile= Fðÿÿÿÿÿÿÿ, profile 'Unstable/Experimental'= GðÿÿÿÿÿÿÿP, quality 0= Hðÿÿÿÿÿÿÿ`, quality 1= Iðÿÿÿÿÿÿÿp, quality 2 (Telephone)= Jðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, quality 3 (Thumb)= Kðÿÿÿÿÿÿÿÿÿÿÿÿÿÿ, quality 4 (Radio)= Lðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, quality 5 (Standard)= Mðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿ, quality 6 (Xtreme)= NðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, quality 7 (Insane)= OðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, quality 8 (BrainDead)= Pðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ, quality 9= Qðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿ, quality 10=R, Buschmann 1.7.0-9, Klemm 0.90-1.05=Sf, Beta 1.02=Th, Beta 1.04=Ui, Alpha 1.05=Vj, Beta 1.06=Wn, Release 1.1=Xo, Alpha 1.11=Yp, Beta 1.12=Zq, Alpha 1.13=[r, Beta 1.14=\s, Alpha 1.15 =YBSYbs archive data =‰tdfloppy image data (TeleDisk) = FWSMacromedia Flash data,x version %dapplication/x-shockwave-flash = CWSMacromedia Flash data (compressed),application/x-shockwave-flashxversion %d =FLVMacromedia Flash Videovideo/x-flv =¹LH5SAR archive data =mFIZFIZ archive data =$flfFIGlet font>%2aversion %-2.2s =&flcFIGlet controlfile>'2aversion %-2.2s =iSEMSemOne archive data =cAKTAKT archive data =]‰FuseCompress(ed) data=(none format)=(bz2 format)=(gz format)= (lzo format)= (xor format)> (unknown format)x uncompressed size: %d = PmNPCP compiled namespace> (V.%1.1s) =*HCALADS Caris Ascii Format (CAF) bathymetric lidar= +[0-9]*.[0-9]*version %s =-HCBLADS Caris Binary Format (CBF) bathymetric lidar waveform datax.version %d .x/%d =`U3DECMA-363, Universal 3D =GRGGringotts data file= 1v.1, MCRYPT S2K, SERPENT crypt, SHA-256 hash, ZLib lvl.9= 2v.2, MCRYPT S2K, = pRIJNDAEL-128 crypt,=pSERPENT crypt,=p TWOFISH crypt, =p0CAST-256 crypt,=p@SAFER+ crypt,=pPLOKI97 crypt,=p`3DES crypt,=ppRIJNDAEL-256 crypt,=SHA1 hash,=RIPEMD-160 hash,=ZLib=BZip2=lvl.0=lvl.3=lvl.6=lvl.9=3v.3, OpenPGP S2K, =pRIJNDAEL-128 crypt,= pSERPENT crypt,=!p TWOFISH crypt, ="p0CAST-256 crypt,=#p@SAFER+ crypt,=$pPLOKI97 crypt,=%p`3DES crypt,=&ppRIJNDAEL-256 crypt,='SHA1 hash,=(RIPEMD-160 hash,=)ZLib=*BZip2=+lvl.0=,lvl.3=-lvl.6=.lvl.9>03v.%.1s (unknown details)@=eval "exec /usr/local/bin/perlPerl script texttext/x-perl =Ò­6"AMGC archive data = XISChiasmus key =½-ahMAR archive data =RT4TOP4 archive data =s SCCS archive data@=^[ ]*(class|module)[ ][A-Z]=(modul|includ)e [A-Z]|def [a-z]=^[ ]*end([ ]*[;#].*)?$Ruby module source texttext/x-ruby =(ID3Audio file with ID3 version 2x).%dx*.%d&+€ÿÿÿÿÿÿÿ, unsynchronized frames&,@, extended header&- , experimental&., footer presentx)'/, contains: =NASDASD archive data =LDSTDisintegrator archive data = mmcrypt 2.2 encrypted data,= algorithm: blowfish-448,= algorithm: DES,=algorithm: 3DES,=algorithm: 3-WAY,=algorithm: GOST,=algorithm: SAFER-SK64,=algorithm: SAFER-SK128,=algorithm: CAST-128,= algorithm: xTEA,= algorithm: TWOFISH-128,= algorithm: RC2,= algorithm: TWOFISH-192,= algorithm: TWOFISH-256,=algorithm: blowfish-128,=algorithm: blowfish-192,=algorithm: blowfish-256,=dalgorithm: RC6,=ealgorithm: IDEA,=mode: CBC,=mode: ECB,= mode: CFB,=!mode: OFB,="mode: nOFB,=#keymode: 8bit=$keymode: 4bit=%keymode: SHA-1 hash=&keymode: MD5 hash =mmcrypt 2.5 encrypted data,>algorithm: %s,> keysize: %d bytes,> mode: %s, =5 A~MAthematica .ml file =ôHMLVM1 (Linux Logical Volume Manager), version 2>,õ, System ID: %s =GNSKNaShrink archive data =…PBFPBF image (deflate compression)image/x-unknown =APARPar archive data =4HPAHPA archive data =0777777 archive data =.RNCPRO-PACK archive data =BOABOA archive data ={SMKRAD Game Tools Smacker Multimediax|version %c,x }%d xx ~%d,x %d frames =GTHGather archive data =“¹Splint archive data =COCMP archive data =ABABComp archive data@= """Python script text executable =TûSASSAS 7+=œüDATAdata file=œýCATALOGcatalog=œþINDEXdata file index=œÿVIEWdata view =ôSASSAS=õDATAdata file=öCATALOGcatalog=÷INDEXdata file index=øVIEWdata view =SegStuffIt Deluxe Segment (data)x: %s =UHAUHarc archive data =}SBCSBC archive data =úˆð'MS Compress archive data= ü=ýKWAJ=þÑMS Compress archive data>ÿ, original size: %ld bytes>ex, was %.8sx .%.3s =HEHP PCL printer data=I&l0A- default page size=J&l1A- US executive page size=K&l2A- US letter page size=L&l3A- US legal page size=M&l26A- A4 page size=N&l80A- Monarch envelope size=O&l81A- No. 10 envelope size=P&l90A- Intl. DL envelope size=Q&l91A- Intl. C5 envelope size=R&l100A- Intl. B5 envelope size=S&l-81A- No. 10 envelope size (landscape)=T&l-90A- Intl. DL envelope size (landscape) =ðUFAUFA archive data =êESPESP archive data =Linux/i386 object file>  , DLL library =%!PostScript document textapplication/postscriptASPSTEXT= PS-Adobe-conforming> DSC level %.3s=EPS, type %s=Query, type %s= ExitServer, type %s=è%%LanguageLevel: >, Level %s =ÚPSAPSA archive data =0BIKBink Video=1[a-z]rev.%sx 3, %dx 4x%dx 5, %d framesx 6at rate %d/> 7%d= (8, no audio! (9, %d audio track! (:sx 0<%dHz=3= mono!3> stereo =ñHMLVM1 (Linux Logical Volume Manager), version 1>,ò, System ID: %s@= must be converted with BinHexBinHex binary textx), version %.3s@=^\.[A-Za-z0-9][A-Za-z0-9][ ]troff or preprocessor input texttext/troff@=+7\documentclassLaTeX 2e document texttext/x-tex@=P.la - a libtool library filelibtool library file@=-----BEGIN CERTIFICATE------RFC1421 Security Certificate text@= +=\contentslineLaTeX table of contentstext/x-tex@=%^from\s+(\w|\.)+\s+import.*$Python script text executabletext/x-python@=X# Netscape HTTP Cookie FileNetscape cookie text@=P.lo - a libtool object filelibtool object file@=+4\chapterLaTeX document texttext/x-tex@=++\sectionLaTeX document texttext/x-tex@=-----BEGIN NEW CERTIFICATERFC1421 Security Certificate Signing Request text@=^\.[A-Za-z0-9][A-Za-z0-9]$troff or preprocessor input texttext/troff@= +.\setlengthLaTeX document texttext/x-tex@=#! /usr/local/bin/pythonPython script text executabletext/x-python@=Ia%%% @BibTeX-style-file{BibTeX style text file (with full header)@=eval "exec /usr/bin/perlPerl script texttext/x-perl@= Common subdirectories: diff output texttext/x-diff@=^%?[ ]*SiSU[ ][0-9.]+SiSU text=[0-9.]+%s@=^%?[ ]*SiSU[ ]+insertSiSU text insert=[0-9.]+%s@=#! /usr/local/bin/wishTcl/Tk script text executabletext/x-tcl@=#! /usr/local/bin/perlPerl script text executabletext/x-perl@=^%[ ]+SiSU[ ]+masterSiSU text master= [0-9.]+%s@= #! /usr/local/bin/rubyRuby script text executabletext/x-ruby@=(custom-set-variables Lisp/Scheme program texttext/x-lisp@= #! /usr/bin/env pythonPython script text executabletext/x-python =¬@ü=­wÍ ¹=$®UPX!FREE-DOS executable (COM), UPX compressed(= £ÿÀ¸À= ¤ÿLÍ!COM executable (32-bit COMBOOT)(= ÿ€¸! ŸÿLÍ!COM executable for DOS =,@MZapplication/x-dosexec< /@MS-DOS executable> 7?= <:PEPE= <; 32 executable= << 32+ executable= <=ROM imagex <>Unknown PE signaturex ?0x%x> <@ (DLL)= <\A(native)= <\B(GUI)= <\C(console)= <\D(POSIX)= <\E (Windows CE)= <\F (EFI application)= <\G (EFI boot service driver)= <\H (EFI runtime driver)= <\I (EFI ROM)= <\J(XBOX)= <\K(Windows boot application)x <\L(Unknown subsystemx M0x%x)= <NLIntel 80386= <OfMIPS R4000= <PhMIPS R10000= <Q„Alpha= <R¢Hitachi SH3= <S¦Hitachi SH4= <TÀARM= <UÂARM Thumb= <VðPowerPC= <WIntel Itanium= <XfMIPS16= <YhMotorola 68000= <ZPA-RISC= <[fMIPSIV= <\fMIPS16 with FPU= <]¼EFI byte code= <^d†ÿÿÿÿÿÿx86-64= <_îÀÿÿÿÿÿÿMSILx <`Unknown processor typex a0x%x> <b(stripped to external PDB)> <csystem file= <d > <èeMono/.Net assembly= <f > <øgMono/.Net assembly= k32STUB, 32rtm DOS extender! l32STUB, for MS Windows= <ømUPX0, UPX compressed= <øn@PEC2, PECompact2 compressed= <øo@UPX2= ƒüÿÿÿpPK, ZIP self-extracting archive (Info-Zip)= <øq@.idata= ƒüÿÿÿrPK, ZIP self-extracting archive (Info-Zip)= ƒüÿÿÿsZZ0, ZZip self-extracting archive= ƒüÿÿÿtZZ1, ZZip self-extracting archive= <øu@.rsrc= ƒüÿÿÿva\, WinHKI self-extracting archive= ƒüÿÿÿwRar!, RAR self-extracting archive= ƒüÿÿÿx0MSCF, InstallShield self-extracting archive= ƒüÿÿÿy Nullsoft, Nullsoft Installer self-extracting archive= <øz@.data= {WEXTRACT, MS CAB-Installer self-extracting archive= <ø|@.petite, Petite compressedx <÷}= ƒüÿÿÿ~!sfx!, ACE self-extracting archive= <ø@.WISE, WISE installer self-extracting archive= <ø€@.dz, Dzip self-extracting archive= <ø_winzip_, ZIP self-extracting archive (WinZip)= <ø‚SharedD, Microsoft Installer self-extracting archive=0ƒInno, InnoSetup self-extracting archive! <‡PEMS-DOS executable= <‰NE, NE= <6Šfor OS/2 1.x= <6‹for MS Windows 3.x= <6Œfor MS-DOS= <6for Windows 386= <6Žfor Borland Operating System Servicesx <6x <6(unknown OS %x)= <6‘ÿÿÿÿÿÿÿfor MS-DOS, Phar Lap DOS extender= < ’€ÿÿÿÿÿÿ€ÿÿÿÿÿÿ(DLL)= < “€ÿÿÿÿÿÿ€ÿÿÿÿÿÿ(driver)= $”ARJSFX, ARJ self-extracting archive= <p•€WinZip(R) Self-Extractor, ZIP self-extracting archive (WinZip)= <—LX, LX< < ˜(unknown OS)= < ™for OS/2= < šfor MS Windows= < ›for DOS> < œ(unknown OS)= <€€(DLL)> <ž(device driver)= <Ÿ(GUI)< < ƒ(console)= <¡i80286= <¢i80386= <£i80486= ¤emx, emxx¥%s= T¦arjsfx, ARJ self-extracting archive= <©W3, W3 for MS Windows= <«LE, LE executable= < ¬=@®DOS/4Gfor MS-DOS, DOS4GW DOS extender= @¯WATCOM C/C++for MS-DOS, DOS4GW DOS extender=@°CauseWay DOS Extenderfor MS-DOS, CauseWay DOS extender=@±@PMODE/Wfor MS-DOS, PMODE/W DOS extender=@²@STUB/32Afor MS-DOS, DOS/32A DOS extender (stub)=@³€STUB/32Cfor MS-DOS, DOS/32A DOS extender (configurable stub)=@´€DOS/32Afor MS-DOS, DOS/32A DOS extender (embedded)< $¶P= L·ü¸WATCOM=¸3Ûf¹, 32Lite compressed= < ¼for MS Windows= < ½for DOS= < ¾for MS Windows (VxD)= |&¿UPX, UPX compressed= TÀUNACE, ACE self-extracting archive> <Ä ! ÅL, MZ for MS-DOS!Ç< È@! ÉL! ËLE!þÿÿÿÌBW, MZ for MS-DOS= ÍLE, LE=@ÎDOS/4Gfor MS-DOS, DOS4GW DOS extender= ÒBW=@ÓDOS/4G,\b LE for MS-DOS, DOS4GW DOS extender (embedded)!@ÔDOS/4G,\b BW collection for MS-DOS= ×L, COFF= Øgo32stubfor MS-DOS, DJGPP go32 DOS extender= ÙemxxÚfor DOS, Win or OS/2, emx %sx BÛ=&ÜUPX, UPX compressed=,Þ .text< ß > à`, 32lite compressed= â$WdX, WDos/X DOS extender=5êŽÀ¹ó¥JuëŽÃŽØ3ÿ¾0, aPack compressed=çëLH/2 Self-Extract \b, %s=ìUC2X, UCEXE compressed=íWWP , WWPACK compressed=îRJSX, ARJ self-extracting archive=ïdiet, diet compressed=ðLZ09, LZEXE v0.90 compressed=ñLZ91, LZEXE v0.91 compressed=òtz, TinyProg compressed=óCopyright 1989-1990 PKWARE Inc.Self-extracting PKZIP archiveapplication/zip= öPKLITE Copr.Self-extracting PKZIP archiveapplication/zip= ùàaRJsfX, ARJ self-extracting archive= úAIN=#û2, AIN 2.x compressed<#ü2, AIN 1.x compressed>#ý2, AIN 1.x compressed= $þLHa's SFX, LHa self-extracting archiveapplication/x-lha= $LHA's SFX, LHa self-extracting archiveapplication/x-lha=$ $ARX, ARX self-extracting archive=$ $LHarc, LHarc self-extracting archive=  SFX by LARC, LARC self-extracting archive=@aPKG, aPackage self-extracting archive= dW Collis, Compack compressed=zWindows self-extracting ZIP, ZIP self-extracting archive=ô@@= ƒ MSCF, WinHKI CAB self-extracting archive=f -lh5-, LHa self-extracting archive v2.13S=ˆx Rar!, RAR self-extracting archivex x =PK, ZIP self-extracting archive=Rar!, RAR self-extracting archive=!, AIN 2.x self-extracting archive=!, AIN 2.x self-extracting archive=!, AIN 1.x self-extracting archive=!, AIN 1.x self-extracting archive=**ACE**, ACE self-extracting archive= €UC2SFX Header, UC2 self-extracting archive=  PKSFX, ZIP self-extracting archive (PKZIP)=‰Â"yÿ€ÿvÿ, CODEC archive v3.21=  Â#, 1 file>  Â$, %u files =ª€ÿÿÿÿÿÿ=«BS93Lynx homebrew cartridgex¬, RAM start $%04x=­LYNXLynx cartridgex®, RAM start $%04x@= #! /usr/local/bin/luaLua script text executabletext/x-lua =¾Í!!¿¸ÿÿÿÿÿÿÿCOM executable for DOS = ƒ=  COFF format alpha pure=  COFF format alpha demand paged!  0 executable!  dynamically linked! not stripped= strippedx- version %dx.%dx-%d= COFF format alpha object= 0 shared libraryx- version %dx.%dx-%d@=K#! /usr/local/bin/phpPHP script text executabletext/x-php@= ^%?[ ]*SiSU[ ]+textSiSU text= [0-9.]+%s@=+:\relaxLaTeX auxiliary filetext/x-tex = ÁÍ!!ÂÍ!COM executable for DOS =ü ¾Úÿÿÿÿÿÿ>ø Sun disk labelx '%s>%s>?%s>_%sx'>Ü%d rpm,>Þ%d phys cys,>à%d alts/cyl,>æ%d interleave,>è%d data cyls,>ê%d alt cyls,>ì%d heads/partition,>î%d sectors/track,>ôstart cyl %ld,xø%ld blocks=ÿÿÿ, boot block present = †h$<‡dMinix filesystem, V2, %d zones=ˆminix, bootable =‰h$<ŠdMinix filesystem, V2 (big endian), %d zones=‹minix, bootable =$þÿÿÿÿÿÿÿúÿÿÿÿÿÿÿ=&ðÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 32 kbpsaudio/mpeg=(ðÿÿÿÿÿÿÿ MPEG ADTS, layer III, v1, 40 kbpsaudio/mpeg=*ðÿÿÿÿÿÿÿ0MPEG ADTS, layer III, v1, 48 kbpsaudio/mpeg=,ðÿÿÿÿÿÿÿ@MPEG ADTS, layer III, v1, 56 kbpsaudio/mpeg=.ðÿÿÿÿÿÿÿPMPEG ADTS, layer III, v1, 64 kbpsaudio/mpeg=0ðÿÿÿÿÿÿÿ`MPEG ADTS, layer III, v1, 80 kbpsaudio/mpeg=2ðÿÿÿÿÿÿÿpMPEG ADTS, layer III, v1, 96 kbpsaudio/mpeg=4ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 112 kbpsaudio/mpeg=6ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 128 kbpsaudio/mpeg=8ðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 160 kbpsaudio/mpeg=:ðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 192 kbpsaudio/mpeg=<ðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 224 kbpsaudio/mpeg=>ðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 256 kbpsaudio/mpeg=@ðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿMPEG ADTS, layer III, v1, 320 kbpsaudio/mpeg=C , 44.1 kHz=D , 48 kHz=E , 32 kHz=GÀÿÿÿÿÿÿÿ, Stereo=HÀÿÿÿÿÿÿÿ@, JntStereo=IÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 2x Monaural=JÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, Monaural = x$<ŽdMinix filesystem, V2, 30 char names, %d zones=minix, bootable = x$<‘dMinix filesystem, V2, 30 char names, %d zones=’minix, bootable =“x$!”Minix filesystem, V2, 30 char names (big endian), %d zones=•minix, bootable = –ZM!—Minix filesystem, V3, %d zones=˜minix, bootable(= ´êp>¶>¸)>¹)>¼)GRand Unified Bootloader=¾ÿstage1_5<¿ÿstage2xÀ version %uxÁ.%u< Ãÿÿÿ, installed partition %u> Åÿÿÿ, installed partition %u= Ç0.0.x É, identifier 0x%x> Ë, LBA flag 0x%x>Í, GRUB version %-s=Ïÿÿÿÿ>Ð, configuration file %-s!Ñÿÿÿÿ>Ò, configuration file %-s! Ô0.0.> Ö, saved entry %dxÚ, identifier 0x%x>Ý, LBA flag 0x%x>ß, GRUB version %-s=áÿÿÿÿ>â, configuration file %-s!ãÿÿÿÿ>ä, configuration file %-s@=+(\inputTeX document texttext/x-tex =-¡Rÿÿÿÿÿÿÿ =+ ØÿÿÿÿÿÿÿJPEG image dataimage/jpeg8BIMJPEG=JFIF, JFIF standardx  %d.x %02d!, thumbnail %dxx%d=$Exif, EXIF standard= *II= F,i‡ÿÿÿÿÿÿ= N.ÿÿÿÿÿÿx N/%cx N0.%c! N10%c= v3i‡ÿÿÿÿÿÿ= ~&5ÿÿÿÿÿÿx ~/6%cx ~07.%c! ~180%c= ‚:i‡ÿÿÿÿÿÿ= Š&<ÿÿÿÿÿÿx Š/=%cx Š0>.%c! Š1?0%c= Š2Aÿÿÿÿÿÿx Š;B%cx Š<C.%c! Š=D0%c= Š>Fÿÿÿÿÿÿx ŠGG%cx ŠHH.%c! ŠII0%c= ŽKi‡ÿÿÿÿÿÿ= –&Mÿÿÿÿÿÿx –/N%cx –0O.%c! –1P0%c= –2Rÿÿÿÿÿÿx –;S%cx –<T.%c! –=U0%c= –>Wÿÿÿÿÿÿx –GX%cx –HY.%c! –IZ0%c= \MM=v^i‡ÿÿÿÿÿÿ=~`ÿÿÿÿÿÿx~a%cx~b.%c!~c0%c=~&eÿÿÿÿÿÿx~/f%cx~0g.%c!~1h0%c=‚ji‡ÿÿÿÿÿÿ=Š&lÿÿÿÿÿÿxŠ/m%cxŠ0n.%c!Š1o0%c=Š>qÿÿÿÿÿÿxŠGr%cxŠHs.%c!ŠIt0%c=Žvi‡ÿÿÿÿÿÿ=–2xÿÿÿÿÿÿx–;y%cx–<z.%c!–={0%c=‚þÿÿÿÿÿÿÿ, comment:x ƒ"%s"=†Àÿÿÿÿÿÿÿ, baselinex‡, precision %dxˆ, %dxx ‰%d=ŠÁÿÿÿÿÿÿÿ, extended sequentialx‹, precision %dxŒ, %dxx %d=ŽÂÿÿÿÿÿÿÿ, progressivex, precision %dx, %dxx ‘%d = = ðð= ðð= = €aXilinx BIT datax €- from %s==bx €- for %s==cx €- built %s==dx  €(%s)=!="ex#- data length 0x%lx@=¶\(;.*GM\[[0-9]{1,2}\]Smart Game Format=·@GM[=¸1](Go)=¹2](Othello)=º3](chess)=»4](Gomoku+Renju)=¼5](Nine Men's Morris)=½6](Backgammon)=¾7](Chinese chess)=¿8](Shogi)=À9](Lines of Action)=Á10](Ataxx)=Â11](Hex)=Ã12](Jungle)=Ä13](Neutron)=Å14](Philosopher's Football)=Æ15](Quadrature)=Ç16](Trax)=È17](Tantrix)=É18](Amazons)=Ê19](Octi)=Ë20](Gess)=Ì21](Twixt)=Í22](Zertz)=Î23](Plateau)=Ï24](Yinsh)=Ð25](Punct)=Ñ26](Gobblet)=Ò27](hive)=Ó28](Exxit)=Ô29](Hnefatal)=Õ30](Kuba)=Ö31](Tripples)=×32](Chase)=Ø33](Tumbling Down)=Ù34](Sahara)=Ú35](Byte)=Û36](Focus)=Ü37](Dvonn)=Ý38](Tamsk)=Þ39](Gipf)=ß40](Kropki)@=ú\(;.*GM\[[0-9]{1,2}\]Smart Game Format=ûGM\[1\]- Go Game=üGM\[6\]- BackGammon Game=ýGM\[11\]- Hex Game=þGM\[18\]- Amazons Game=ÿGM\[19\]- Octi Game=GM\[20\]- Gess Game=GM\[21\]- twix Game =MKF=N NKompas drawing 12.0 SP1 =O MKompas drawing 12.0 =P 2Kompas drawing 11.0 SP1 =Q 1Kompas drawing 11.0 =R #Kompas drawing 10.0 SP1 =S !Kompas drawing 10.0 =T Kompas drawing 9.0 SP1 =U Kompas drawing 9.0 =V3Kompas drawing 8+ =WKompas drawing 8.0 =X,Kompas drawing 7+ =YKompas drawing 7.0 =Z2Kompas drawing 6+ =[ Kompas drawing 6.0 =\\Kompas drawing 5.11R03 =]TKompas drawing 5.11R02 =^QKompas drawing 5.11R01 =_"Kompas drawing 5.10R03 =`"Kompas drawing 5.10R02 mar =a!Kompas drawing 5.10R02 febr =bKompas drawing 5.10R01 =c€ôÿÿÿÿKompas drawing 5.9R01.003 =d€Kompas drawing 5.9R01.002 =e€Kompas drawing 5.8R01.003 = 45=(^[0-9]{5})[acdnp][^bhlnqsu-z]MARC21 Bibliographicapplication/marc=(^[0-9]{5})[acdnosx][z]MARC21 Authorityapplication/marc=(^[0-9]{5})[cdn][uvxy]MARC21 Holdingsapplication/marc =ÐBM= Ñ PC bitmap, OS/2 1.x formatimage/x-ms-bmpx Ó, %d xx Ô%d= Õ@PC bitmap, OS/2 2.x formatimage/x-ms-bmpx ×, %d xx Ø%d= Ù(PC bitmap, Windows 3.x formatimage/x-ms-bmpx Û, %d xx Ü%d xx Ý%d= Þ€PC bitmap, Windows NT/2000 formatimage/x-ms-bmpx à, %d xx á%d xx â%d(= ªÿÀ¸À= «þLÍ!COM executable (32-bit COMBOOT, relocatable)@=#!/usr/bin/env pythonPython script text executabletext/x-python@= #! /usr/local/bin/tclTcl script text executabletext/x-tcl = €¯ÿÿÿÿÿÿ= ‚@= ƒÈ= „FLI animation, 320x200x8video/x-flix †, %d framesx ˆ, %d/70s per frame = ¯ÿÿÿÿÿÿ= FLC animationvideo/x-flcx ‘, %dx ’x%dx8x “, %d framesx ”, %dms per frame = Cbasic-16 executable (TV)> not stripped = Bbasic-16 executable> not stripped = PDP-11 executable>  not stripped> - version %ld =×ÒÿÿÿÿÿÿMacintosh MFS data=KL(bootable)& €ÿÿÿÿÿÿ(locked)x€°%|created: %s,>€°%|last backup: %s,xblock size: %d,xnumber of blocks: %d,x $€volume name: %s =*"compact bitmap" format (Poskanzer) = Hx86 executable> not stripped =¤ PCX ver. 3.0 image datax ¥bounding box [%hd,x ¦%hd] -x §[%hd,x ¨%hd],>A©%d planes each ofxª%hhd-bit=D«image,=D¬colour,=D­grayscale,>D®image,<D¯image,> °%hd xx ±%hd dpi,=²uncompressed=³RLE compressed =£ PCX for Windows image data =¢ PCX ver. 2.8 image data, without palette =¡ PCX ver. 2.8 image data, with palette =  PCX ver. 2.5 image data = }–Atari ATR image = Ix86 executable (TV)> not stripped =GPEX Binary Archive =ÚSGI image data=, RLE=, high precisionx, %d-Dx, %d xx %dx !, %d channel! "s>P#0, "%s" = ðRÌÿÿÿÿÿÿRLE image data,x ñ%d xx ò%d> ó, lower left corner: %d> ô, lower right corner: %d= õ, clear first= ö, no background= ÷, alpha channel= ø, comment> ù, %d color channels> ú, %d bits per pixel> û, %d color map channels =jàÿÿÿÿÿÿÿàVMPEG-4 LOASaudio/x-mp4a-latm=màÿÿÿÿÿÿÿ@=n<, single stream=o<, 2 streams=p< , 3 streams&q, 4 or more streams&r , 8 or more streams=sÀÿÿÿÿÿÿÿ=tx, single stream=ux, 2 streams=vx, 3 streams&w , 4 or more streams&x@, 8 or more streams = JiAPX 286 executable small model (COFF)> not stripped = RiAPX 286 executable large model (COFF)> not stripped = "L80386 COFF executable> #not stripped> $- version %ld =/+HMacintosh HFS Extendedx0version %d data=1KL(bootable)^2(mounted)&3(spared blocks)&4(unclean)&5€(locked)x6last mounted by: '%.4s',x9€°%|created: %s,x ;€°%|last modified: %s,> <€°%|last backup: %s,> =€°%|last checked: %s,x&>block size: %d,x*?number of blocks: %d,x.@free blocks: %d =ÿÎ PARIX= ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿT800= ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿT9000= executable= object= not stripped =EöÿÿÿÿÿÿÿðÿÿÿÿÿÿÿMPEG ADTS, AACaudio/x-hx-aac-adts&G, v2^H, v4&JÀÿÿÿÿÿÿÿ LTP=KÀÿÿÿÿÿÿÿ Main=LÀÿÿÿÿÿÿÿ@ LC=MÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ SSR=O<, 96 kHz=P<, 88.2 kHz=Q<, 64 kHz=R< , 48 kHz=S<, 44.1 kHz=T<, 32 kHz=U<, 24 kHz=V<, 22.05 kHz=W< , 16 kHz=X<$, 12 kHz=Y<(, 11.025 kHz=Z<,, 8 kHz=\À@, monaural=]À€, stereo=^ÀÀ, stereo + center=_À, stereo+center+LFE=`À@, surround=aÀ€, surround + LFE&bÀ, surround + side =þÿÿÿÿÿÿÿâÿÿÿÿÿÿÿMPEG ADTS, layer III, v2.5audio/mpeg= ðÿÿÿÿÿÿÿ, 8 kbps= ðÿÿÿÿÿÿÿ , 16 kbps= ðÿÿÿÿÿÿÿ0, 24 kbps= ðÿÿÿÿÿÿÿ@, 32 kbps=ðÿÿÿÿÿÿÿP, 40 kbps=ðÿÿÿÿÿÿÿ`, 48 kbps=ðÿÿÿÿÿÿÿp, 56 kbps=ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 64 kbps=ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿ, 80 kbps=ðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, 96 kbps=ðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿ, 112 kbps=ðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, 128 kbps=ðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, 144 kbps=ðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ, 160 kbps= , 11.025 kHz= , 12 kHz= , 8 kHz=Àÿÿÿÿÿÿÿ, Stereo=Àÿÿÿÿÿÿÿ@, JntStereo=Àÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 2x Monaural= ÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, Monaural =äþÿÿÿÿÿÿÿöÿÿÿÿÿÿÿMPEG ADTS, layer I, v2audio/mpeg=çðÿÿÿÿÿÿÿ, 32 kbps=èðÿÿÿÿÿÿÿ , 48 kbps=éðÿÿÿÿÿÿÿ0, 56 kbps=êðÿÿÿÿÿÿÿ@, 64 kbps=ëðÿÿÿÿÿÿÿP, 80 kbps=ìðÿÿÿÿÿÿÿ`, 96 kbps=íðÿÿÿÿÿÿÿp, 112 kbps=îðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 128 kbps=ïðÿÿÿÿÿÿÿÿÿÿÿÿÿÿ, 144 kbps=ððÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, 160 kbps=ñðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿ, 176 kbps=òðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, 192 kbps=óðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, 224 kbps=ôðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ, 256 kbps=ö , 22.05 kHz=÷ , 24 kHz=ø , 16 kHz=úÀÿÿÿÿÿÿÿ, Stereo=ûÀÿÿÿÿÿÿÿ@, JntStereo=üÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 2x Monaural=ýÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, Monaural =6LGArhangel archive data =)ªUBIOS (ia32) ROM Ext.=*USBUSB=+LDRUNDI image=,IBMIBM comp. Video=-AdaptecAdaptec=.AdaptecAdaptec=*/PROMISEPromisex0(%d*512) =ÀyxMGR bitmap, modern format, squeezed =¿xzMGR bitmap, old format, 1-bit deep, 32-bit aligned =¾zzMGR bitmap, old format, 1-bit deep, 16-bit aligned =½yzMGR bitmap, modern format, 8-bit aligned =ÂþÿÿÿÿÿÿÿôÿÿÿÿÿÿÿMPEG ADTS, layer II, v2=Äðÿÿÿÿÿÿÿ, 8 kbps=Åðÿÿÿÿÿÿÿ , 16 kbps =Æðÿÿÿÿÿÿÿ0, 24 kbps=Çðÿÿÿÿÿÿÿ@, 32 kbps=ÈðÿÿÿÿÿÿÿP, 40 kbps=Éðÿÿÿÿÿÿÿ`, 48 kbps=Êðÿÿÿÿÿÿÿp, 56 kbps=Ëðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 64 kbps=Ìðÿÿÿÿÿÿÿÿÿÿÿÿÿÿ, 80 kbps=Íðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, 96 kbps=Îðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿ, 112 kbps=ÏðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, 128 kbps=ÐðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, 144 kbps=Ñðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ, 160 kbps=Ó , 22.05 kHz=Ô , 24 kHz=Õ , 16 kHz=×Àÿÿÿÿÿÿÿ, Stereo=ØÀÿÿÿÿÿÿÿ@, JntStereo=ÙÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 2x Monaural=ÚÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, Monaural = eÿÿÿÿÿÿÿx.out= __.SYMDEFrandomizedxarchive =3O:Solitaire Image Recorder format=4 MGI Type 11=5MGI Type 17 =/P7Netpbm PAM image fileimage/x-portable-pixmap =-P6Netpbm PPM "rawbits" image dataimage/x-portable-pixmap =+P5Netpbm PGM "rawbits" image dataimage/x-portable-greymap =)P4Netpbm PBM "rawbits" image dataimage/x-portable-bitmap =CUBHIT archive data = PDP-11 UNIX/RT ldp =þÿÿÿÿÿÿstructured file@=(^[0-9]{5})[acdn][w]MARC21 Classificationapplication/marc=(^[0-9]{5})[cdn][q]MARC21 Communityapplication/marc=(^.{21})([^0]{2})(non-conforming)application/marc = shared library =ßexecutable (RISC System/6000 V3.1) or obj module> not stripped =e‡ÿÿÿÿÿÿdisk quotas file = üÿÿÿÿÿÿÿ–ÿÿÿÿÿÿlittle endian ispell= hash file (?),=3.0 hash file,=3.1 hash file,=hash file (?),= 8-bit, no capitalization, 26 flags= 7-bit, no capitalization, 26 flags= 8-bit, capitalization, 26 flags= 7-bit, capitalization, 26 flags= 8-bit, no capitalization, 52 flags= 7-bit, no capitalization, 52 flags= 8-bit, capitalization, 52 flags= 7-bit, capitalization, 52 flags= 8-bit, no capitalization, 128 flags=  7-bit, no capitalization, 128 flags=  8-bit, capitalization, 128 flags=  7-bit, capitalization, 128 flags=  8-bit, no capitalization, 256 flags=  7-bit, no capitalization, 256 flags= 8-bit, capitalization, 256 flags=  7-bit, capitalization, 256 flags> !and %d string characters =IRIS Showcase file=I-x- version %ld@=#! /usr/bin/env rubyRuby script text executabletext/x-ruby =&IRIS Showcase template=c-x- version %ld =`MIPSEB ECOFF executable= (impure)=!(swapped)=" (paged)>#not stripped=$strippedx%- version %ldx&.%ld =.]SVR2 executable (USS/370)> /not stripped>0- version %ld =(bMIPSEL-BE ECOFF executable=)(impure)=*(swapped)=+ (paged)>,not stripped=-strippedx.- version %dx/.%ld =+XSVR2 pure executable (USS/370)> ,not stripped>-- version %ld =(\SVR2 pure executable (Amdahl-UTS)> )not stripped>*- version %ld =%YSVR2 executable (Amdahl-UTS)> &not stripped>'- version %ld =#_370 XA sysV executable> $not stripped =!]370 sysV executable> "not stripped =Z370 XA sysV pure executable> not stripped =X370 sysV pure executable> not stripped =Z370 XA sysV pure executable > not stripped>- version %d>- 5.2 format =_370 XA sysV executable > not stripped>- version %d>- 5.2 format =&,hp300 (68020+68881) BSD='impure binary=(read-only binary=) demand paged binary ="Èhp200 (68010) BSD=#impure binary=$read-only binary=% demand paged binary =1`MIPSEB-LE ECOFF executable=2(impure)=3(swapped)=4 (paged)>5not stripped=6strippedx7- version %dx8.%ld =:bMIPSEL ECOFF executable=;(impure)=<(swapped)== (paged)>>not stripped=?strippedx@- version %ldxA.%ld =EcMIPSEB MIPS-II ECOFF executable=F(impure)=G(swapped)=H (paged)>Inot stripped=JstrippedxK- version %ldxL.%ld =-”apollo a88k COFF executable^.@not stripped>/- version %ld =*—Apollo m68k COFF executable^+@not stripped>,- version %ld = PHitachi SH little-endian COFF= object= executable= , stripped= , not stripped =Hitachi SH big-endian COFF= object= executable= , stripped= , not stripped =NfMIPSEL-BE MIPS-II ECOFF executable=O(impure)=P(swapped)=Q (paged)>Rnot stripped=SstrippedxT- version %ldxU.%ld =WcMIPSEB-LE MIPS-II ECOFF executable=X(impure)=Y(swapped)=Z (paged)>[not stripped=\strippedx]- version %ldx^.%ld =`fMIPSEL MIPS-II ECOFF executable=a(impure)=b(swapped)=c (paged)>dnot stripped=estrippedxf- version %ldxg.%ld =UUVISX image file=(zero)=(unsigned char)= (short integer)= (float 32)= (float 64)= (signed char)= (bit-plane)=(classes)=(statistics)= (ascii text)=(image segments)=d(image set)=e(unsigned char vector)=f(short integer vector)=g(float 32 vector)=h(float 64 vector)=i(signed char vector)=j(bit plane vector)=y(feature vector)=z(feature vector library)=|(chain code)=~(bit vector)=‚ÿÿÿÿÿÿÿ(graph)=ƒÿÿÿÿÿÿÿ(adjacency graph)=„ÿÿÿÿÿÿÿ(adjacency graph library)= .VISIX(ascii text) =%™ÿÿÿÿÿÿGPG key public ringapplication/x-gnupg-keyring = …ÿÿÿÿÿÿGPG encrypted datatext/PGP =k@MIPSEB MIPS-III ECOFF executable=l(impure)=m(swapped)=n (paged)>onot stripped=pstrippedxq- version %ldxr.%ld =^ÚúLogitech Compress archive data = 'Sendmail frozen configuration> - version %s =9 GeoSwath RDF =tBMIPSEL-BE MIPS-III ECOFF executable=u(impure)=v(swapped)=w (paged)>xnot stripped=ystrippedxz- version %ldx{.%ld =}@MIPSEB-LE MIPS-III ECOFF executable=~(impure)=(swapped)=€ (paged)>not stripped=‚strippedxƒ- version %ldx„.%ld = RDI Acoustic Doppler Current Profiler (ADCP) ="üÿÿÿÿÿÿÿ–ÿÿÿÿÿÿbig endian ispell=#hash file (?),=$3.0 hash file,=%3.1 hash file,=&hash file (?),='8-bit, no capitalization, 26 flags=(7-bit, no capitalization, 26 flags=)8-bit, capitalization, 26 flags=*7-bit, capitalization, 26 flags=+8-bit, no capitalization, 52 flags=,7-bit, no capitalization, 52 flags=-8-bit, capitalization, 52 flags=.7-bit, capitalization, 52 flags=/8-bit, no capitalization, 128 flags=0 7-bit, no capitalization, 128 flags=1 8-bit, capitalization, 128 flags=2 7-bit, capitalization, 128 flags=3 8-bit, no capitalization, 256 flags=4 7-bit, no capitalization, 256 flags=58-bit, capitalization, 256 flags=67-bit, capitalization, 256 flags>7and %d string characters = ëSYMMETRY i386 .o> not stripped> |version %ld = ë"SYMMETRY i386 executable (0 @ 0)> not stripped> |version %ld = ë2SYMMETRY i386 executable (invalid @ 0)> not stripped> | version %ld = !ëBSYMMETRY i386 standalone executable> "not stripped> |#version %ld = í¬ÿÿÿÿÿÿJava serialization data> , version %d =†BMIPSEL MIPS-III ECOFF executable=‡(impure)=ˆ(swapped)=‰ (paged)>Šnot stripped=‹strippedxŒ- version %ldx.%ld = ui386 COFF object =ufsav macro virus signatures>  (%d-> %02d-> %02d) =€MIPSEB Ucode =5üJOS9/68K module:=8€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿre-entrant=9@@ghost=: system-state=>machine language=?BASIC I-code=@Pascal P-code=AC I-code=BCOBOL I-code=CFortran I-code=Hprogram executable=Isubroutine=Jmulti-module=Kdata module=L trap library=M system module=N file manager=Odevice driver=Pdevice descriptor ="TLPEmbedded OpenType (EOT)application/vnd.ms-fontobject =͇ÿÿÿÿÿÿOS9/6809 module:=!non-executable="machine language=#BASIC I-code=$Pascal P-code=%C I-code=&COBOL I-code='Fortran I-code=)ðÿÿÿÿÿÿÿprogram executable=*ðÿÿÿÿÿÿÿ subroutine=+ðÿÿÿÿÿÿÿ0multi-module=,ðÿÿÿÿÿÿÿ@data module=.ðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿsystem module=/ðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿfile manager=0ðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿdevice driver=1ðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿdevice descriptor = Microsoft a.out= Middle model& overlay& separate& pure& segmented& standalone& fixed-stack&€ÿÿÿÿÿÿÿbyte-swapped&@word-swapped> not-stripped^ Àÿÿÿÿÿÿpre-SysV& @V2.3&  €ÿÿÿÿÿÿV3.0&!86&" 186&# 286&$ 386<%@small model=&Hlarge model ='Ihuge model & (executable^ )object file& *@Large Text& + Large Data& , Huge Objects Enabled> -not stripped =‚MIPSEL-BE Ucode =byte-swapped Berkeley vfont data =Berkeley vfont data = /@old Microsoft 8086 x.out&0separate&1pure&2executable^3relocatable> 4not stripped =ŸþÿÿÿÿÿÿÿòÿÿÿÿÿÿÿMPEG ADTS, layer III, v2audio/mpeg=¢ðÿÿÿÿÿÿÿ, 8 kbps=£ðÿÿÿÿÿÿÿ , 16 kbps=¤ðÿÿÿÿÿÿÿ0, 24 kbps=¥ðÿÿÿÿÿÿÿ@, 32 kbps=¦ðÿÿÿÿÿÿÿP, 40 kbps=§ðÿÿÿÿÿÿÿ`, 48 kbps=¨ðÿÿÿÿÿÿÿp, 56 kbps=©ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 64 kbps=ªðÿÿÿÿÿÿÿÿÿÿÿÿÿÿ, 80 kbps=«ðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, 96 kbps=¬ðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿ, 112 kbps=­ðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, 128 kbps=®ðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, 144 kbps=¯ðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ, 160 kbps=± , 22.05 kHz=² , 24 kHz=³ , 16 kHz=µÀÿÿÿÿÿÿÿ, Stereo=¶Àÿÿÿÿÿÿÿ@, JntStereo=·Àÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 2x Monaural=¸ÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, Monaural = I€XENIX 8086 relocatable or 80286 small model = PDP-11 old overlay = PDP-11 pure executable> not stripped>- version %ld = W…Linux jffs2 filesystem data little endian = V„Linux old jffs2 filesystem data little endian = 8^SïÿÿÿÿÿÿLinuxx L_rev %dx >`.%d^ \bext2 filesystem data^ :c(mounted or unclean)& \e< `g@< diext3 filesystem data> dkext4 filesystem data> `m?ext4 filesystem dataxhn, UUID=%08xxlo-%04xxnp-%04xxpq-%04xxrr-%08xxvs%04x>xt0, volume name "%s"& `v(needs journal recovery)& :w(errors)& `y(compressed)& `|@(extents)& `}€(64bit)& d‚(large files)& dƒ(huge files) =  PDP-11 separate I&D executable> not stripped>- version %ld =î¼@Sky archive data = PDP-11 kernel overlay =€ÿÿÿÿÿÿlif file =  PDP-11 demand-paged pure executable> not stripped = !}VAX COFF pure executable> "not stripped> #- version %ld = xVAX COFF executable> not stripped>  - version %ld = 66Linux/i386 PC Screen Font v1 data,=7256 characters,!8512 characters,=9no directory,!:Unicode directory,>;8x%d = ÉÄID tags data> version %d = raw G3 data, byte-padded = raw G3 data =pNPPMN archive data =Pmc68k COFF^ object& executable> not stripped=¨ .lowmemApple toolbox= (impure)=(pure)= (demand paged)=(standalone) =Qmc68k executable (shared)> not stripped = PDP-11 overlaid pure executable> !not stripped =%!PostScript document textapplication/postscriptASPSTEXT=  PS-Adobe-conforming> DSC level %.3s= EPS, type %s=Query, type %s= ExitServer, type %s=è%%LanguageLevel: >, Level %s =Rmc68k executable (shared demand paged)> not stripped =l68K BCS executable =m88K BCS executable =¢3AIN archive data =£3AIN archive data =©jmXPack DiskImage archive data =!S0Motorola S-Record; binary data in text format =6`Atari 68xxx executable,x7text len %lu,x8data len %lu,x 9BSS len %lu,x:symboltab len %lu,=;&<fastload flag,&=may be loaded to alternate RAM,&>malloc may be from alternate RAM,x?flags: 0x%lX,=@no relocation tab!A+ relocation tab=BSFX[Self-Extracting LZH SFX archive]=&CSFX[Self-Extracting LZH SFX archive]=,DZIP![Self-Extracting ZIP SFX archive] =unicos (cray) executable =àÿÿÿÿÿÿamd 29k coff archive = zamd 29k coff prebar executable = RSHARC COFF binary> , %hd sections> , not stripped =FdAtari 68xxx CPX filexG(version %04lx) = zamd 29k coff noprebar executable =#ûÿÿÿÿÿÿQDOS objectx $€'%s' = þ:Uªÿÿÿÿÿÿx86 boot sector=?OSBS, OS/BS MBR=ŒAInvalid partition table, MS-DOS MBR=CInvalid partition table$=µDNo Operating System$=ÉEOperating System load error$, DR-DOS MBR, Version 7.01 to 7.03=FInvalid partition table$=µGNo operating system$=ÉHOperating system load error$, DR-DOS MBR, Version 7.01 to 7.03=VIInvalid partition table$=nJNo operating system$=‚KOperating system load error$, DR-DOS MBR, version 7.01 to 7.03='LNEWLDR=.MBad PT $=6NNo OS $= =OOS load err$=IPMoved or missing IBMBIO.LDR =fQPress any key to continue. $=ƒRCopyright (c) 1984,1998= ›SCaldera Inc., DR-DOS MBR (IBMBIO.LDR)=TUngltige Partitionstabelle, MS-DOS MBR, german version 4.10.1998, 4.10.2222>¸U, Serial 0x%-.4x=‹VUngltige Partitionstabelle, MS-DOS MBR, german version 5.00 to 4.00.950=WInvalid partition table='XError loading operating system=FYMissing operating system, mbr=‹[Invalid partition table=£\Error loading operating system=Â]Missing operating system, Microsoft Windows XP mbr> ¸`,Serial 0x%-.4x=,aInvalid partition table=DbError loading operating system=ccMissing operating system, Microsoft Windows XP MBR> ¸e, Serial 0x%-.4x=,fUngltige Partitionstabelle=HhFehler beim Laden =Zides Betriebssystems=njBetriebssystem nicht vorhanden, Microsoft Windows XP MBR (german)> ¸k, Serial 0x%-.4x= EnDefault: F, FREE-DOS MBR=@rno active partition found=`sread error while reading drive, FREE-DOS Beta 0.9 MBR= ƒu Error! =zvVirus!=wBooting =˜xHD1/, Ranish MBR (= yWriting changes...2.37x¶z,0x%x dots>¸{,virus check>¹|,partition %c! ~Writing changes...=¢virus check,x£€0x%x seconds>¤,partition<¤‚ %x=¤ƒ askx¤„)=†Operating system loading=(‡error , SYSLINUX MBR (2.10)= j‰MBR Error =xŠress any key to =ˆ‹boot from floppy..., Acronis MBR=5No bootable partition found =SI/O Error reading boot sector , Visopsys MBR=]‘No bootable partition found ={’I/O Error reading boot sector , simple Visopsys MBR=@”SBML= +–SMART BTMGR= ®—SBMK Bad! , Smart Boot Manager>š, version %s= ~›XOSLLOADXCF, eXtended Operating System Loader=œLILO, LInux i386 boot LOader=xLILO, version 22.3.4 SuSe=¬žLILO, version 22.5.8 Debian=V£<Geom<A¥>>¦; GRand Unified Bootloaderx>¨, stage1 version 0x%x<@ªÿ, boot drive 0x%x>A¬, LBA flag 0x%x< B­€, stage2 address 0x%x> B¯€, stage2 address 0x%x> D±, 1st sector stage2 0x%x< H², stage2 segment 0x%x> H´, stage2 segment 0x%x=’µGeomHard DiskRead Error=жstage1, GRUB version 0.5.95=~·GeomHard DiskRead Error=x¸GRUB , GRUB version 0.93 or 1.94=¹GeomHard DiskRead Error=yºGRUB , GRUB version 0.94=»GeomHard DiskRead Error={¼GRUB , GRUB version 0.95 or 0.96=‡½GeomHard DiskRead Error=¾GRUB , GRUB version 0.97=WÀGeomRead Error=AÁLoading stage1.5, GRUB version x.y=|ÂGeomHard DiskRead Error=vÃGRUB , GRUB version n.m= ÞÅBoot failed = ïÆLDLINUX SYS, SYSLINUX bootloader (1.62)= àÇBoot failed = ïÈLDLINUX SYS, SYSLINUX bootloader (2.06 or 2.11)= äÉBoot error , SYSLINUX bootloader (3.11)=‹Êchksum ERROR!, Gujin bootloader=ÌBCDL= òÍBCDL BIN, Bootable CD Loader (1.50Z)!ÐMS!ÑSYSLINUX!ÒMTOOL!ÓNEWLDR!ÔDOS!RÖFAT32!ØHdrS!¦ÚBe Boot Loader <¾Ü =¾Ý >ÂÞ; partition 1: ID=0x%x =¾߀, active x¿à, starthead %u x Æã, startsector %u x Êä, %u sectors <Îæ =Îç >Òè; partition 2: ID=0x%x =Îé€, active xÏê, starthead %u x Öí, startsector %u x Úî, %u sectors <Þð =Þñ >âò; partition 3: ID=0x%x =Þó€, active xßô, starthead %u x æø, startsector %u x êù, %u sectors <îû =îü >òý; partition 4: ID=0x%x =îþ€, active xïÿ, starthead %u x ö, startsector %u x ú, %u sectors=ºNon-system disk, =Ë press any key..., Acronis Startup Recovery Loader>Ý ßxÝ  %-.3s>à ßxà%-.5s>åßxå.%-.3s=¹FDBOOT Version =Ì No Systemdisk. =ÜBooting from harddisk. =õCannot load from harddisk. =Insert Systemdisk =#and press any key. , FDBOOT harddisk Bootloader>È, version %-3s=òBootsector from C.H. Hochst„=No Systemdisk. =%Booting from harddisk. =¹Cannot load from harddisk. =ÕInsert Systemdisk =çand press any key. , WinImage harddisk Bootloader>Ñ, version %-4.4s =  =! ="¾ =#w =$| =%¬ =&" = 'À = (t = ) = *V = +´, mkdosfs boot message display=Ö,Please try to install FreeDOS , DOS Emulator boot message display=g1This is not a bootable disk. =„2Please insert a bootable = 3floppy and =©4press any key to try again... , FREE-DOS message display=B6Solaris Boot Sector=c7Incomplete MDBoot load.=Y8Version, Sun Solaris Bootloaderxa9version %c=˜;OS/2 !! SYS01475 =­<OS/2 !! SYS02025 =Â=OS/2 !! SYS02027 = Õ>OS2BOOT , IBM OS/2 Warp bootloader=™@OS/2 !! SYS01475 =®AOS/2 !! SYS02025 =ÃBOS/2 !! SYS02027 = ÖCOS2BOOT , IBM OS/2 Warp Bootloader=pDThis disk is not bootable =ŽEIf you wish to make it bootable=°Frun the DOS program SYS = ÈGafter the =ØHsystem has been loaded =òIPlease insert a DOS diskette =Jinto the drive and =$Kstrike any key..., IBM OS/2 Warp message display=®MNTLDR is missingÿ = ÁNDisk errorÿ =ÎOPress any key to restart , Microsoft Windows XP Bootloader>¡Qßx¡R%-.5s>¦Sßx¦T%-.3s>©Uß>©V .%-.3s>sX >pYßxpZ%-.5s>u[ßxu\%-.3s>x]ßxx^.%-.3s=®`NTLDR nicht gefundenÿ =ÅaDatentr„gerfehlerÿ =ÙbNeustart mit beliebiger Taste , Microsoft Windows XP Bootloader (german)>¡cßx¡d%-.5s>¦eßx¦f%-.3s>©gß>©h .%-.3s={j>pkßxpl%-.5s>umßxun%-.3s=®pNTLDR fehltÿ =¼qDatentr„gerfehlerÿ =ÐrNeustart mit beliebiger Taste , Microsoft Windows XP Bootloader (2.german)>¡sßx¡t%-.5s>¦ußx¦v%-.3s>©wß>©x .%-.3s>sz >p{ßxp|%-.5s>u}ßxu~%-.3s>xßxx€.%-.3s=®‚NTLDR fehltÿ =¼ƒMedienfehlerÿ =Ë„Neustart: Taste drcken , Microsoft Windows XP Bootloader (3.german)>s… >p†ßxp‡%-.5s>uˆßxu‰%-.3s>xŠßxx‹.%-.3s>¡ßx¡Ž%-.5s>¦ßx¦%-.3s>©‘ß>©’ .%-.3s=®”Datentr„ger entfernenÿ =Æ•Medienfehlerÿ =Õ–Neustart: Taste drcken , Microsoft Windows XP Bootloader (4.german)={—>p˜ßxp™%-.5s>ušßxu›%-.3s>xœßxx.%-.3s>¡Ÿßx¡ %-.5s>¦¡ßx¦¢%-.3s>©£ß>©¤ .%-.3s=…¨Fehler beim Lesen =—©des Datentr„gers= ªªNTLDR fehlt=¸«NTLDR ist komprimiert=ЬNeustart mit Strg+Alt+Entf , Microsoft Windows XP Bootloader NTFS (german)=9®A disk read error occurred. =Y¯A kernel file is missing =r°from the disk. =ä±NTLDR is compressed=­²Insert a system diskette =Ƴand restart the system. , Microsoft Windows XP Bootloader NTFS>صß=…¶Invalid system diskÿ =›·Disk I/O error=¬¸Replace the disk, and = ǹpress any key, Microsoft Windows 98 Bootloader>Ø»ßxؼ %-.2s>Ú½ß xÚ¾%-.5s >ß¿ß xßÀ%-.1s>àÁßxàÂ.%-.3s>ãÄß+xãÅ%-.5s >èÆß xèÇ%-.3s>ëÈß xëÉ.%-.3s=†ËInvalid system diskÿ =œÌDisk I/O errorÿ =­ÍReplace the disk, and =ÃÎthen press any key , Microsoft Windows 98 Bootloader=„ÏUngueltiges System ÿ =šÐE/A-Fehler ÿ =«ÑDatentraeger wechseln und =ÅÒTaste druecken , Microsoft Windows 95/98/ME Bootloader (german)>ñÔßxñÕ%-.5s>öÖß xö×%-.1s >÷Øß x÷Ù%-.1s >øÚß xøÛ%-.1s>ùÜßxùÝ.%-.3s>ØßßorxØà %-.2s>Úáß xÚâ%-.5s >ßãß xßä%-.1s>àåßxàæ.%-.3s>ãèß+xãé%-.5s >èêß xèë%-.3s>ëìß xëí.%-.3s=†ïUngueltiges System ÿ =œðE/A-Fehler ÿ =­ñDatentraeger wechseln und =ÇòTaste druecken , Microsoft Windows 95/98/ME Bootloader (German)>ñôßxñõ%-.7s>øöß xø÷%-.1s>ùøßxùù.%-.3s>ØûßorxØü %-.2s>Úýß xÚþ%-.6s>àÿßxà.%-.3s>ãß+xã%-.5s >èß xè%-.3s>ëß xë.%-.3s=… Ungueltiges System ÿ =› E/A-Fehler ÿ =¬ Datentraeger wechseln und =Æ Taste druecken , Microsoft Windows 95/98/ME Bootloader (GERMAN)xØ%-.2s>ÚßxÚ%-.5s>ßß xß%-.1s>àßxà.%-.3s>ãß+xã%-.5s>èßxè%-.2s>êß xê%-.1s>ëßxë.%-.3s>ßß= Kein System oder =±Laufwerksfehler= Wechseln und Taste drcken, Microsoft DOS Bootloader (german)xß" %-.2s>á#ßxá$%-.6s>ç%ßxç&.%-.3s>ê(ß+xê)%-.5s>ï*ß xï+%-.3s>ò,ßxò-.%-.3s=x/)Non-System disk or = ‹0)disk error = —1)Replace and =£2)press ,=£3)strike , old=ª4)any key when ready MS or PC-DOS bootloader=Ô7x9 %-.2s >ìÿÿÿ:ßxÿÿÿÿ;%-.4s >ðÿÿÿ<ß xÿÿÿÿ=%-.2s>>ß.xÿÿÿÿ?%-.3s> Aß+xÿÿÿÿB%-.5s >úÿÿÿCß xÿÿÿÿD%-.1s >ûÿÿÿEß xÿÿÿÿF%-.2s>Gß.xÿÿÿÿH%-.3s=¹ICannot load from harddisk. =ÕJInsert Systemdisk =çKand press any key. , MS (2.11) DOS bootloader=6MSYS=DNVASKK=ïONEWLDR, DR-DOS Bootloader (LOADER.SYS)=bQPress a key to retry =xRCannot find file =‹SDisk read error = œTLoading ..., DR-DOS (3.41) Bootloader>,Vßx,W %-.6s>2Xßx2Y%-.2s>4Zßx4[.%-.3s= F]IBMBIO COM=Ø^Cannot load DOS! =é_Any key to retry, DR-DOS Bootloader=×`Cannot load DOS =çapress key to retry, Open-DOS Bootloader= ¼cKERNEL SYS= :dBOOT error!, FREE-DOS Bootloader= óeKERNEL SYS= 1fBOOT err!, Free-DOS Bootloader= ÁgKERNEL SYS= ?hBOOT error!, FREE-DOS 0.5 Bootloader=ÁjLoading FreeDOS> ¯k, FREE-DOS 0.95,1.0 Bootloader>ñlßxñm %-.6s>÷nßx÷o%-.1s>øpßxøq%-.1s>ùrßxùs.%-.3s=KuError!.0, FREE-DOS 1.0 bootloader=}wLoading FreeDOS... = 7xBOOT error! , FREE-DOS bootloader>¹yßx¹z %-.6s>¿{ßx¿|%-.1s>À}ßxÀ~%-.1s>ÁßxÁ€.%-.3s=|FreeDOS=K‚ err, FREE-DOS BETa 0.9 Bootloader>ñ„ßxñ… %-.6s>÷†ßx÷‡%-.1s>øˆßxø‰%-.1s>ùŠßxù‹.%-.3s=MŒ err, FREE-DOS BEta 0.9 Bootloader>ñßxñŽ %-.6s>÷ßx÷%-.1s>ø‘ßxø’%-.1s>ù“ßxù”.%-.3s=N• err, FREE-DOS Beta 0.9 Bootloader>ñ–ßxñ— %-.6s>÷˜ßx÷™%-.1s>øšßxø›%-.1s>ùœßxù.%-.3s=PžError! =WŸHit a key to reboot., FREE-DOS Beta 0.9sr1 Bootloader>ñ ßxñ¡ %-.6s>÷¢ßx÷£%-.1s>ø¤ßxø¥%-.1s>ù¦ßxù§.%-.3s= Þ¬=F­I/O Error reading =X®Visopsys loader =i¯Press any key to continue. , Visopsys loader>î±M>ï²E<ï³S=µBootProg>ó¹ß, COM/EXE Bootloaderxóº %-.1s>ô»ßxô¼%-.1s>õ½ß xõ¾%-.1s >ö¿ß xöÀ%-.1s >÷Áß x÷Â%-.1s>øÃßxøÄ%-.1s>ùÅßxùÆ%-.1s>úÇßxúÈ%-.1s>ûÊß.xûË%-.1s>üÌßxüÍ%-.1s >ýÎß xýÏ%-.1s=ìÔRENF, FAT (12 bit)=ïÕRENF, FAT (16 bit)>î×M>ïØE<ïÙS=ÛBootProg>óßß, COM/EXE Bootloaderxóà %-.1s>ôáßxôâ%-.1s>õãß xõä%-.1s >öåß xöæ%-.1s >÷çß x÷è%-.1s>øéßxøê%-.1s>ùëßxùì%-.1s>úíßxúî%-.1s>ûðß.xûñ%-.1s>üòßxüó%-.1s >ýôß xýõ%-.1s=ìúRENF, FAT (12 bit)=ïûRENF, FAT (16 bit)=þ=¾>Â=â=ò<Ò=Ò, extended partition table=Ò , extended partition table (LBA)=Ò , extended partition table (last) = ëë= éé<ÿ, code offset 0x%xx < €> =ðð>, OEM-ID "%8.8s"=IHC cached by Windows 9M> , Bytes/sector %u< , Bytes/sector %u> , sectors/cluster %u> " , reserved sectors %u< &, reserved sectors %u>', FATs %u=), FAT %u>*> +, root entries %u> -, sectors %u (volumes <=32 MB) >/ð, Media descriptor 0x%x<1ð, Media descriptor 0x%x> 2, sectors/FAT %u>4, heads %u=6, heads %u!&8p> 9, hidden sectors %u> ;, sectors %u (volumes > 32 MB) !R>FAT32!$A€!$B, physical drive 0x%x>%C, reserved 0x%x>&E), dos < 4.0 BootSector (0x%x)<&F), dos < 4.0 BootSector (0x%x)=&G)x 'H, serial number 0x%x<+INO NAME, label: "%11.11s">+JNO NAME, label: "%11.11s"=+KNO NAME, unlabeled=6LFAT, FAT=6MFAT12 (12 bit)=6NFAT16 (16 bit)=RPFAT32, FAT (32 bit)x $Q, sectors/FAT %u> (R, extension flags %u> *T, fsVersion %u> ,V, rootdir cluster %u> 0Y, infoSector %u< 0[, infoSector %u> 2\, Backup boot sector %u< 2^, Backup boot sector %u> 6_, reserved1 0x%x> :`, reserved2 0x%x> >a, reserved3 0x%x>@c€, physical drive 0x%x>@e, physical drive 0x%x>Ag, reserved 0x%x>Bh), dos < 4.0 BootSector (0x%x)<Bi), dos < 4.0 BootSector (0x%x)=Bj)x Ck, serial number 0x%x<GlNO NAME, label: "%11.11s">GmNO NAME, label: "%11.11s"=GnNO NAME, unlabeled= pWEV‚ÿÿÿÿ, BSD disklabel = Zmumps blt global> (V%d)>- %d byte blocks=- P/D format=- P/K/D format=- K/D format>- Bad Flags =Ymumps avl global> (V%d)> with %d byte name> and %d byte data cells =èTTComp archive data =âvÿNSQ archive data = #PDP-11 overlaid separate executable> $not stripped@=^%*[ ]*sisu-[0-9.]+SiSU text=[0-9.]+%s = ˆPerkin-Elmer executable =UEncore unsupported executable> not stripped>- version %ld=- =!jPJPEG 2000 imageimage/jp2 = TEncore= executable= pure executable= demand-paged executable= unsupported executable> not stripped>- version %ld=- =.``Dyalog APL transfer = LMS Windows COFF Intel 80386 object file =ªÿÿÿÿÿÿDyalog APLxworkspace type %dxsubtype %d=(32-bit=( 64-bit= classic= unicode=ˆÿÿÿÿÿÿÿbig-endian=ˆÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿlittle-endian = fMS Windows COFF MIPS R4000 object file = Tkêÿÿÿÿÿÿold-fs dump file (16-bit, assuming PDP-11 endianness),xUPrevious dump %s,xVThis dump %s,> WVolume %ld,= Xtape header.= Ybeginning of file record.= Zmap of inodes on tape.= [continuation of file record.= \end of volume.= ]map of inodes deleted.= ^end of medium (for floppy). = w ATSC A/52 aka AC-3 aka Dolby Digital stream,= Àÿÿÿÿÿÿÿ48 kHz,= Àÿÿÿÿÿÿÿ@44.1 kHz,= Àÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ32 kHz,=ÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿreserved frequency,=, complete main (CM)=, music and effects (ME)=, visually impaired (VI)=, hearing impaired (HI)=, dialogue (D)=, commentary (C)=, emergency (E)=àÿÿÿÿÿÿÿ1+1 front,=àÿÿÿÿÿÿÿ 1 front/0 rear,=àÿÿÿÿÿÿÿ@2 front/0 rear,=àÿÿÿÿÿÿÿ`3 front/0 rear,=àÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ2 front/1 rear,=àÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ3 front/1 rear,=àÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ2 front/2 rear,= àÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ3 front/2 rear,="@LFE off,=#@@LFE on,=%>, 32 kbit/s=&>, 40 kbit/s='>, 48 kbit/s=(>, 56 kbit/s=)>, 64 kbit/s=*> , 80 kbit/s=+> , 96 kbit/s=,>, 112 kbit/s=->, 128 kbit/s=.>, 160 kbit/s=/>, 192 kbit/s=0>, 224 kbit/s=1>, 256 kbit/s=2>, 320 kbit/s=3>, 384 kbit/s=4>, 448 kbit/s=5> , 512 kbit/s=6>", 576 kbit/s=7>$, 640 kbit/s=9€Dolby Surround not indicated=:€€not Dolby Surround encoded=;€Dolby Surround encoded=<€€reserved Dolby Surround mode =8locale data table=9$for MIPS=:@for Alpha = „MS Windows COFF Alpha object file = !hMS Windows COFF Motorola 68000 object file = #ðMS Windows COFF PowerPC object file = %MS Windows COFF PA-RISC object file = LANalyzer capture file = LANalyzer capture file = *Alpha u-code object = )ˆAlpha compressed COFF@= eval "exec /bin/perlPerl script texttext/x-perl =»DZDzip archive datax¼, version %ix½.%i =ÍX1X1 archive data =ËYCYAC archive data = unknown pure executable>not stripped> - version %ld = PDP-11 separate I&D>not stripped>- version %ld =,AmigaOS outline font =+AmigaOS bitmap font =ÞÀÿÿÿÿÿÿCompiled PSI (v1) data =ÚÀÿÿÿÿÿÿCompiled PSI (v2) data>(%s) =ªªÿÿÿÿÿÿSoftQuad DESC or font file binary>- version %d =unknown pure executable>not stripped>- version %ld =X SoftQuad troff Context intermediate=495for AT&T 495 laser printer=hpfor Hewlett-Packard LaserJet=imprfor IMAGEN imPRESS=psfor PostScript@=#! /usr/bin/env perlPerl script text executabletext/x-perl =É7QuArk archive data =unknown machine executable>not stripped>- version %ld = (Emacs v18 byte-compiled Lisp dataapplication/x-elc =vÿSqueezed (apple ][) data =Çqcpio archiveapplication/x-cpio =¬¡Quasijarus strong compressed data =c SCO compress -H (LZH) data =¸Í!COM executable for DOS =`žfrozen file 1.0 (or gzip 0.5) =_Ÿfrozen file 2.1 =[ývLZH compressed data,x\original name %s =Yþvcrunched data,xZoriginal name %s =Wÿvsqueezed data,xXoriginal name %s =ºÍ!COM executable for DOS =HËÿÿÿÿÿÿhuf outputapplication/octet-stream = þÿÿÿÿÿÿMySQL table definition filex Version %d =Fÿcompacted dataapplication/octet-stream =Bÿcompacted dataapplication/octet-stream =<old packed dataapplication/octet-stream =6packed dataapplication/octet-stream>8, %d characters originally=9, %d character originally =‹gzip compressed dataapplication/x-gzip<, reserved method>, unknown method&, ASCII&, has CRC&, extra field= x , was "%s"& , has comment= !, from FAT filesystem (MS-DOS, OS/2, NT)= ", from Amiga= #, from VMS= $, from Unix= %, from VM/CMS= &, from Atari= ', from HPFS filesystem (OS/2, NT)= (, from MacOS= ), from Z-System= * , from CP/M= + , from TOPS/20= , , from NTFS filesystem (NT)= - , from QDOS= . , from Acorn RISCOS&/, comment&0 , encrypted> 1, last modified: %s=2, max compression=3, max speed = compress'd dataapplication/x-compressLZIVZIVU>€ÿÿÿÿÿÿÿblock compressedx%d bits =¼Í!COM executable for DOS@=W $!DCL command file =!qÇÿÿÿÿÿÿbyte-swapped cpio archiveapplication/x-cpio = ¦ÿÿÿÿÿÿPGP encrypted datatext/PGP = Ë`êÿÿÿÿÿÿARJ archive dataapplication/x-arjxÍ, v%d,&Îmulti-volume,&Ïslash-switched,&Ð backup,x"Ñoriginal name: %s,=Òos: MS-DOS=Óos: PRIMOS=Ôos: Unix=Õos: Amiga=Öos: Macintosh=×os: OS/2=Øos: Apple ][ GS=Ùos: Atari ST=Úos: NeXT=Û os: VAX/VMS>Ü%d] = Þ`êÿÿÿÿÿÿARJ archive data = •ÿÿÿÿÿÿPGP key security ringapplication/x-pgp-keyring = ÄÍ!COM executable for DOS ='CLIPPER COFF executable=(xC1 R1 =)xC2 R1=*xC3 R1=+xxTEST=,(impure)=-(pure)=. (separate I&D)=/ (paged)=0#(target shared library)> 1not stripped>2- version %ld=03alignment trap enabled=44-Ctnc=45-Ctsw=46-Ctpw=47-Ctcb=58-Cdnc=59-Cdsw=5:-Cdpw=5;-Cdcb=6<-Csnc=6=-Cssw=6>-Cspw=6?-Cscb =}CLIPPER COFF executable (VAX #)= (impure)=!(5.2 compatible)=" (pure)=# (demand paged)=$#(target shared library)> %not stripped>&- version %ld = àIClarion Developer (v2 and above) help data = M3Clarion Developer (v2 and above) memo data = C3Clarion Developer (v2 and above) data file&  , locked&  , encrypted& , memo file exists& , compressed& @, read onlyx , %ld records = âëÿÿÿÿÿÿPRCS packaged project =n Bentley/Intergraph MicroStation=oþÿÿÿÿÿÿÿ=pCIT raster CAD = •ÿÿÿÿÿÿPGP key security ringapplication/x-pgp-keyring =ÆÍ!COM executable for MS-DOS =Í8C64 PCLink Image =ÿAtari MSA archive datax, %d sectors per track=, 1 sided=, 2 sidedx, starting track: %dx, ending track: %d =ÈÍ!COM executable for MS-DOS =&@ïvery old (C/A/T) troff output data =ÊÍ!COM executable for MS-DOS =FÌÍ!COM executable for DOS =pWE32000 COFF^object&executable> not stripped^N/A on 3b2/300 w/paging& 32100 required&@and MAU hardware required=(impure)=(pure)= (demand paged)=#(target shared library)> - version %ld =!qWE32000 COFF executable (TV)> "not stripped = ãÿÿÿÿÿÿAmiga Workbench==0disk icon=0drawer icon=0tool icon=0project icon=0garbage icon=0device icon=0kickstart icon=0workbench application icon>icon, vers. %d =0421 Alliant compact executable& common library>not stripped =Õ@LZMS-DOS executable (built-in) = 0420 Alliant virtual executable& common library>not stripped = ALAN game data< version 2.6%d = ‰DBase 3 index file = ¾xŸÿÿÿÿÿÿTNEFapplication/vnd.ms-tnef =™ÿÿÿÿÿÿPGP key public ringapplication/x-pgp-keyring =`EPMicrosoft Document Imaging Format = RCOFF DSP21k& executable,^  &  static object,^  relocatable object,&  stripped^  not stripped = ˆTower/XP rel 2 object> not stripped= executable= pure executable>- version %ld = yeÿÿÿÿÿÿÿold PDP-11 archive= z__.SYMDEFrandom library =VAX-order 68K Blit (standalone) executable@=#! /usr/bin/env wishTcl/Tk script text executabletext/x-tcl =VAX-order2 68k Blit mpx/mux executable =VAX-order 68k Blit mpx/mux executable =Tower/XP rel 2 object> not stripped=executable=pure executable>- version %ld =Compiled terminfo entry = Curses screen image = Curses screen image = ÷TeX DVI fileapplication/x-dvi>(%s) =÷ƒTeX generic font data =÷YTeX packed font data>(%s) =÷ÊTeX virtual font data =Tower/XP rel 3 object> not stripped=executable=pure executable>- version %ld = rmÿÿÿÿÿÿÿvery old PDP-11 archive =TeX font metric dataapplication/x-tex-tfm>!(%s) =TeX font metric dataapplication/x-tex-tfm>!(%s) =•Tower/XP rel 3 object> not stripped=executable=pure executable>- version %ld =<eÿÿÿÿÿÿÿold PDP-11 archive =TþÿÿÿÿÿÿÿüÿÿÿÿÿÿÿMPEG ADTS, layer II, v1audio/mpeg=Wðÿÿÿÿÿÿÿ, 32 kbps=Xðÿÿÿÿÿÿÿ , 48 kbps=Yðÿÿÿÿÿÿÿ0, 56 kbps=Zðÿÿÿÿÿÿÿ@, 64 kbps=[ðÿÿÿÿÿÿÿP, 80 kbps=\ðÿÿÿÿÿÿÿ`, 96 kbps=]ðÿÿÿÿÿÿÿp, 112 kbps=^ðÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 128 kbps=_ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿ, 160 kbps=`ðÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿ, 192 kbps=aðÿÿÿÿÿÿÿ°ÿÿÿÿÿÿÿ, 224 kbps=bðÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, 256 kbps=cðÿÿÿÿÿÿÿÐÿÿÿÿÿÿÿ, 320 kbps=dðÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ, 384 kbps=f , 44.1 kHz=g , 48 kHz=h , 32 kHz=jÀÿÿÿÿÿÿÿ, Stereo=kÀÿÿÿÿÿÿÿ@, JntStereo=lÀÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ, 2x Monaural=mÀÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿ, Monaural =˜Tower32/600/400 68020 object> not stripped= executable=!pure executable>"- version %ld =:mÿÿÿÿÿÿÿvery old PDP-11 archive =# Tower32/800 68020&$ w/68881 object&%@compatible object&&`object='executable=( pure executable> )not stripped>*- version %ld =ctab data =+¥Tower32/800 68010&,@compatible object&-`object=.executable=/ pure executable> 0not stripped>1- version %ld@=#!/usr/bin/env wishTcl/Tk script text executabletext/x-tcl@=#! /usr/bin/env luaLua script text executabletext/x-lua@ = +,^private:C++ source texttext/x-c++@= #!/usr/bin/env rubyRuby script text executabletext/x-ruby@=#!/usr/bin/env perlPerl script text executabletext/x-perl@ = + ^templateC++ source texttext/x-c++@= #! /usr/bin/env tclTcl script text executabletext/x-tcl@=J\begin{theglossary}LaTeX sorted glossary@= #!/usr/bin/env tclTcl script text executabletext/x-tcl@= FiLeStArTfIlEsTaRtbinscii (apple ][) text@ =+)^public:C++ source texttext/x-c++@=#! /usr/bin/pythonPython script text executabletext/x-python@ =+#^virtualC++ source texttext/x-c++@=W# HTTP Cookie FileWeb browser cookie text@= #!/usr/bin/env luaLua script text executabletext/x-lua@=This is METAFONT,METAFONT transcript text@=Y# KDE Cookie FileKonqueror cookie text@=KThis is makeindexMakeindex log file@= dgenerated by flexC program text (from flex)@=$This is Info fileGNU Info texttext/x-info@= #! /usr/bin/perlPerl script text executabletext/x-perl@=  (URL=<%s>)@=H\begin{theindex}LaTeX sorted index@=M#! /usr/bin/phpPHP script text executabletext/x-php@=4^\s*BEGIN\s*[{]awk script text@= #! /usr/bin/luaLua script text executabletext/x-lua@=W@inproceedings{BibTeX text file@=#! /usr/bin/tclTcl script text executabletext/x-lua@=V@incollection{BibTeX text file@=I\glossaryentryLaTeX raw glossary@="\input texinfoTexinfo source texttext/x-texinfo@=%%Vd<W< X!=YXWD X Window Dump image dataimage/x-xwindowdump>d[, "%s"x\, %dxx]%dxx ^%d =ªÿÿÿÿÿÿÿ<Dyalog APL=incomplete workspace= component file= external variable= workspacex version %dx .%d@= @=   echo offDOS batch file texttext/x-msdos-batch= echo offDOS batch file texttext/x-msdos-batch=remDOS batch file texttext/x-msdos-batch=set DOS batch file texttext/x-msdos-batch =<‚DBase 3 data file= ƒ(no records)> „(%ld records)@= G\indexentryLaTeX raw index file =…ƒÿÿÿÿÿÿÿ<†DBase 3 data file with memo(s)= ‡(no records)> ˆ(%ld records)@= [@phdthesis{BibTeX text file@= dÿÿrxfuncadd=d^[ ]{0,10}call[ ]{1,10}rxfuncOS/2 REXX batch file text@=dÿÿsay=d^[ ]{0,10}say ['"]OS/2 REXX batch file text@=^dnl M4 macro processor script texttext/x-m4@= e% BibTeX `BibTeX custom bibliography style text file@=\"troff or preprocessor input texttext/troff@=I_%%% BibTeX-file{ BibTex text file (with full header)@=(=pod Perl POD document text =-µGLS_BINARY_MSB_FIRST@= 4[playlist]PLS playlist text@=  ^.PRECIOUSmakefile script texttext/x-makefile@= (autoload Lisp/Scheme program texttext/x-lisp@= (defparam Lisp/Scheme program texttext/x-lisp@= Z@preamble{BibTeX text file@= %{lex description text@=!_TAGExuberant Ctags tag file text@= SQ BITMAP1SoftQuad Raster Format text@=diff diff output texttext/x-diff =BéÿÿÿÿÿÿÿDOS executable (COM)= þCUªÿÿÿÿÿÿ, boot code= DSFX of LHarc(%s)@= dyypreviousC program text (from lex)>for %s =ŒÿÿÿÿÿÿÿDOS executable (COM)@= main(C source texttext/x-c =€ÿÿÿÿÿÿÿ8086 relocatable (Microsoft) = BáÛØâÙÄââ×ÃIBM OS/400 save file data=Ô, created with SAVOBJ=Ô, created with SAVLIB=Ô, created with SAVCFG=Ô, created with SAVSECDTA=Ô , created with SAVSECDTA=Ô , created with SAVDLO=Ô , created with SAVLICPGM=Ô, created with SAVCHGOBJ=ÕD, at least V5R4 to open=ÕC, at least V5R3 to open=ÕB, at least V5R2 to open=ÕA, at least V5R1 to open=Õ@, at least V4R5 to open=Õ?, at least V4R4 to open=Õ>, at least V4R3 to open=Õ<, at least V4R2 to open=Õ =, at least V4R1M4 to open=Õ!;, at least V4R1 to open=Õ":, at least V3R7 to open=Õ#5, at least V3R6 to open=Õ$6, at least V3R2 to open=Õ%4, at least V3R1 to open=Õ&1, at least V3R0M5 to open=Õ'0, at least V2R3 to open =-­}GLF_BINARY_LSB_FIRST =ªÿÿÿÿÿÿÿDyalog APL=aplcore=component file 32-bit non-journaled non-checksummed=external variable exclusive=external variable shared=session=mapped file 32-bit= component file 64-bit non-journaled non-checksummed=! mapped file 64-bit=" component file 32-bit level 1 journaled non-checksummed=# component file 64-bit level 1 journaled non-checksummed=$ component file 32-bit level 1 journaled checksummed=%component file 64-bit level 1 journaled checksummed=&component file 32-bit level 2 journaled checksummed='component file 64-bit level 2 journaled checksummed=(component file 32-bit level 3 journaled checksummed=)component file 64-bit level 3 journaled checksummed=*component file 32-bit non-journaled checksummed=+component file 64-bit non-journaled checksummed=,€ÿÿÿÿÿÿÿDDB =Î üWó¥ÃCOM executable for MS-DOS =-¯}GLF_BINARY_MSB_FIRST@=.'''=/.*'''$Python script text executabletext/x-python@=2"""=3.*"""$Python script text executabletext/x-python =Ï üWó¤ÃCOM executable for DOS=ÐP¤ÿÕs, aPack compressed =-³GLS_BINARY_LSB_FIRST@='P3Netpbm PPM image textimage/x-portable-pixmap@=#P1Netpbm PBM image textimage/x-portable-bitmap =ðÿÿÿÿÿÿÿSysEx File -= Sequential= IDP= OctavePlateau= Moog=Passport=Lexicon=Kurzweil/Future Retro=w777=Bank=Song=16=15= 14= 13= 12= 11= 10=9=8=7=6=5= 4=!3="2=#1=$(ALL)x%, Channel %d=&Fender=' Gulbransen=( AKG=) Voyce=* Waveframe=+ ADA=,Garfield=-Ensoniq=.Oberheim=/Matrix 6 series=0 Dump (All)=1Dump (Bank)=2Matrix 1000< 3User bank %d> 4Preset bank %d=5Apple=6GreyMatter=7PalmTree=8JLCooper=9Lowrey=:AdamsSmith=;E-mu=<Harmony==ART=>Baldwin=?Eventide=@Inventronics=AClarity=D!SIEL=E"Synthaxe=F$Hohner=G%Twister=H&Solton=I'Jellinghaus=J(Southworth=K)PPG=L*JEN=M+SSL=N,AudioVertrieb=P/ELKA=Q EK-44=S0Dynacord=T1Jomox=U3Clavia=V9Soundcraft=X>Waldorf=YmicroWave=Zmicrowave2 / XT=[Q / Q+=\(default id)>](<^device %d)=_broadcast id)=`Microwave I=aSNDR (Sound Request)=bSNDD (Sound Dump)=c SNDP (Sound Parameter Change)=d0SNDQ (Sound Parameter Inquiry)=epBOOT (Sound Reserved)=fMULR (Multi Request)=gMULD (Multi Dump)=h!MULP (Multi Parameter Change)=i1MULQ (Multi Parameter Inquiry)=jqOS (Multi Reserved)=kDRMR (Drum Map Request)=lDRMD (Drum Map Dump)=m"DRMP (Drum Map Parameter Change)=n2DRMQ (Drum Map Parameter Inquiry)=orBIN (Drum Map Reserved)=pPATR (Sequencer Pattern Request)=qPATD (Sequencer Pattern Dump)=r#PATP (Sequencer Pattern Parameter Change)=s3PATQ (Sequencer Pattern Parameter Inquiry)=tsAFM (Sequencer Pattern Reserved)=uGLBR (Global Parameter Request)=vGLBD (Global Parameter Dump)=w$GLBP (Global Parameter Parameter Change)=x4GLBQ (Global Parameter Parameter Inquiry)=yMODR (Mode Parameter Request)=zMODD (Mode Parameter Dump)={'MODP (Mode Parameter Parameter Change)=|7MODQ (Mode Parameter Parameter Inquiry)=}microQ=~SNDR (Sound Request)=SNDD (Sound Dump)=€ SNDP (Sound Parameter Change)=0SNDQ (Sound Parameter Inquiry)=‚p(Sound Reserved)=ƒMULR (Multi Request)=„MULD (Multi Dump)=…!MULP (Multi Parameter Change)=†1MULQ (Multi Parameter Inquiry)=‡qOS (Multi Reserved)=ˆDRMR (Drum Map Request)=‰DRMD (Drum Map Dump)=Š"DRMP (Drum Map Parameter Change)=‹2DRMQ (Drum Map Parameter Inquiry)=ŒrBIN (Drum Map Reserved)=GLBR (Global Parameter Request)=ŽGLBD (Global Parameter Dump)=$GLBP (Global Parameter Parameter Change)=4GLBQ (Global Parameter Parameter Inquiry)=‘rackAttack=’SNDR (Sound Parameter Request)=“SNDD (Sound Parameter Dump)=” SNDP (Sound Parameter Parameter Change)=•0SNDQ (Sound Parameter Parameter Inquiry)=–PRGR (Program Parameter Request)=—PRGD (Program Parameter Dump)=˜!PRGP (Program Parameter Parameter Change)=™1PRGQ (Program Parameter Parameter Inquiry)=šqOS (Program Parameter Reserved)=›PATR (Pattern Parameter Request)=œPATD (Pattern Parameter Dump)=#PATP (Pattern Parameter Parameter Change)=ž3PATQ (Pattern Parameter Parameter Inquiry)=ŸGLBR (Global Parameter Request)= GLBD (Global Parameter Dump)=¡$GLBP (Global Parameter Parameter Change)=¢4GLBQ (Global Parameter Parameter Inquiry)=£EFXR (FX Parameter Request)=¤EFXD (FX Parameter Dump)=¥%EFXP (FX Parameter Parameter Change)=¦5EFXQ (FX Parameter Parameter Inquiry)=§MODR (Mode Command Request)=¨MODD (Mode Command Dump)=©'MODP (Mode Command Parameter Change)=ª7MODQ (Mode Command Parameter Inquiry)=«Wave=¬SBPR (Soundprogram)=­SAPR (Performance)=®SWAVE (Wave)=¯SWTBL (Wave control table)=°SVT (Velocity Curve)=±STT (Tuning Table)=²SGLB (Global Parameters)=³SARRMAP (Performance Program Change Map)=´SBPRMAP (Sound Program Change Map)=µ SBPRPAR (Sound Parameter)=¶ SARRPAR (Performance Parameter)=· SINSPAR (Instrument/External Parameter)=¸SBULK (Bulk Switch on/off)=»@Kawai=¼ K1=½"K4=¿ARoland=ÀD-50=Á+U-220=ÂTR-707=ÄBKorg=ÅM1=ÇCYamaha=ÈDCasio=ÉFKamiya=ÊGAkai=ËHVictor=ÌIMesosha=ÍKFujitsu=ÎLSony=ÏNTeac=ÐPMatsushita=ÑQFostex=ÒRZoom=ÓTMatsushita=ÔWAcoustic tech. lab.=ÖÿÿÿÿÿÿÿtTa Horng=×ÿÿÿÿÿÿÿue-Tek=ØÿÿÿÿÿÿÿvE-Voice=ÙÿÿÿÿÿÿÿwMidisoft=ÚÿÿÿÿÿÿÿxQ-Sound=ÛÿÿÿÿÿÿÿyWestrex=ÜÿÿÿÿÿÿÿzNvidia*=Ýÿÿÿÿÿÿÿ{ESS=Þÿÿÿÿÿÿÿ|Mediatrix=ßÿÿÿÿÿÿÿ}Brooktree=àÿÿÿÿÿÿÿ~Otari=áÿÿÿÿÿÿÿKey Electronics=âÿÿÿÿÿÿÿShure=ãÿÿÿÿÿÿÿAuraSound=äÿÿÿÿÿÿÿCrystal=åÿÿÿÿÿÿÿRockwell=æÿÿÿÿÿÿÿSilicon Graphics=çÿÿÿÿÿÿÿMidiman=èÿÿÿÿÿÿÿPreSonus=éÿÿÿÿÿÿÿTopaz=êÿÿÿÿÿÿÿ Cast Lightning=ëÿÿÿÿÿÿÿ Microsoft=ìÿÿÿÿÿÿÿ Sonic Foundry=íÿÿÿÿÿÿÿ Line 6=îÿÿÿÿÿÿÿ Beatnik Inc.=ïÿÿÿÿÿÿÿVan Koerving=ðÿÿÿÿÿÿÿAltech Systems=ñÿÿÿÿÿÿÿS & S Research=òÿÿÿÿÿÿÿVLSI Technology=óÿÿÿÿÿÿÿChromatic=ôÿÿÿÿÿÿÿSapphire=õÿÿÿÿÿÿÿIDRC=öÿÿÿÿÿÿÿJustonic Tuning=÷ÿÿÿÿÿÿÿTorComp=øÿÿÿÿÿÿÿNewtek Inc.=ùÿÿÿÿÿÿÿSound Sculpture=úÿÿÿÿÿÿÿWalker Technical=ûÿÿÿÿÿÿÿDigital Harmony=üÿÿÿÿÿÿÿInVision=ýÿÿÿÿÿÿÿT-Square=þÿÿÿÿÿÿÿNemesys=ÿÿÿÿÿÿÿÿDBX=ÿÿÿÿÿÿÿSyndyne=ÿÿÿÿÿÿÿ Bitheadz =ÿÿÿÿÿÿÿ!Cakewalk=ÿÿÿÿÿÿÿ"Staccato=ÿÿÿÿÿÿÿ#National Semicon.=ÿÿÿÿÿÿÿ$Boom Theory=ÿÿÿÿÿÿÿ%Virtual DSP Corp=ÿÿÿÿÿÿÿ&Antares=ÿÿÿÿÿÿÿ'Angel Software= ÿÿÿÿÿÿÿ(St Louis Music= ÿÿÿÿÿÿÿ)Lyrrus dba G-VOX= ÿÿÿÿÿÿÿ*Ashley Audio= ÿÿÿÿÿÿÿ+Vari-Lite= ÿÿÿÿÿÿÿ,Summit Audio=ÿÿÿÿÿÿÿ-Aureal Semicon.=ÿÿÿÿÿÿÿ.SeaSound=ÿÿÿÿÿÿÿ/U.S. Robotics=ÿÿÿÿÿÿÿ0Aurisis=ÿÿÿÿÿÿÿ1Nearfield Multimedia=ÿÿÿÿÿÿÿ2FM7 Inc.=ÿÿÿÿÿÿÿ3Swivel Systems=ÿÿÿÿÿÿÿ4Hyperactive=ÿÿÿÿÿÿÿ5MidiLite=ÿÿÿÿÿÿÿ6Radical=ÿÿÿÿÿÿÿ7Roger Linn=ÿÿÿÿÿÿÿ8Helicon=ÿÿÿÿÿÿÿ9Event=ÿÿÿÿÿÿÿ:Sonic Network=ÿÿÿÿÿÿÿ;Realtime Music=ÿÿÿÿÿÿÿ<Apogee Digital=ÿÿÿÿÿÿÿ+ Medeli Electronics= ÿÿÿÿÿÿÿ, Charlie Lab=!ÿÿÿÿÿÿÿ- Blue Chip Music="ÿÿÿÿÿÿÿ. BEE OH Corp=#ÿÿÿÿÿÿÿ/ LG Semicon America=$ÿÿÿÿÿÿÿ0 TESI=%ÿÿÿÿÿÿÿ1 EMAGIC=&ÿÿÿÿÿÿÿ2 Behringer='ÿÿÿÿÿÿÿ3 Access Music=(ÿÿÿÿÿÿÿ4 Synoptic=)ÿÿÿÿÿÿÿ5 Hanmesoft Corp=*ÿÿÿÿÿÿÿ6 Terratec=+ÿÿÿÿÿÿÿ7 Proel SpA=,ÿÿÿÿÿÿÿ8 IBK MIDI=-ÿÿÿÿÿÿÿ9 IRCAM=.ÿÿÿÿÿÿÿ: Propellerhead Software=/ÿÿÿÿÿÿÿ; Red Sound Systems=0ÿÿÿÿÿÿÿ< Electron ESI AB=1ÿÿÿÿÿÿÿ= Sintefex Audio=2ÿÿÿÿÿÿÿ> Music and More=3ÿÿÿÿÿÿÿ? Amsaro=4ÿÿÿÿÿÿÿ@ CDS Advanced Technology=5ÿÿÿÿÿÿÿA Touched by Sound=6ÿÿÿÿÿÿÿB DSP Arts=7ÿÿÿÿÿÿÿC Phil Rees Music=8ÿÿÿÿÿÿÿD Stamer Musikanlagen GmbH=9ÿÿÿÿÿÿÿE Soundart=:ÿÿÿÿÿÿÿF C-Mexx Software=;ÿÿÿÿÿÿÿG Klavis Tech.=<ÿÿÿÿÿÿÿH Noteheads AB@=E - version %s@=^charC source texttext/x-c@= STARTFONT X11 BDF font text@= ^all:makefile script texttext/x-makefile =%@P2Netpbm PGM image textimage/x-portable-greymap@='& (%i words)@=v A _textLinux kernel symbol map text@=(defvar Lisp/Scheme program texttext/x-lisp@=%%!!X-Post-It-Note text@=*=head1 Perl POD document text@=^CFLAGSmakefile script texttext/x-makefile@= (input,Pascal source texttext/x-pascal@=(defun Lisp/Scheme program texttext/x-lisp@=-&D%s@=T@book{BibTeX text file@=) =pod Perl POD document text@=Y@misc{BibTeX text file@=^floatC source texttext/x-c@= # xmcdCDDB(tm) format CD text data@=)&%s script text executable@=/ #! /a> %s script text executable@=/ #!/a> %s script text executable@ =-I"“ëë=•ëÿÿÿÿÿÿÿ= þ–UªÿÿÿÿÿÿDOS executable (COM), boot code=U—UPXDOS executable (COM), UPX compressed=˜ $ARXDOS executable (COM), ARX self-extracting archive=™ $LHarcDOS executable (COM), LHarc self-extracting archive= šSFX by LARCDOS executable (COM), LARC self-extracting archive < N< >O= 6P90Bio-Rad .PIC Image File> Q%hd x> R%hd,= S1 image in file> T%hd images in file@=/ #! script text executable>for %s@^ import.*;$Java sourcetext/x-java@ =/ #! /usr/bin/enva> %s script text executable@ =/ #!/usr/bin/enva> %s script text executable(>"<# =$ððþÿÿÿÿ00Infocom game datax%(Z-machine %d,x&Release %d />'Serial %.6s)@!p=^package[ ]+reqTcl script@! p=!^package[ ]+[0-9A-Za-z_:]+ *;="^1 *;|^(use|sub|my) .*[(;{=]Perl5 module source textdff-1.3.0+dfsg.1/dff/api/magic/magic.py000066400000000000000000000154251217176075400173730ustar00rootroot00000000000000#!/usr/bin/env python ''' Python bindings for libmagic ''' import ctypes from ctypes import * from ctypes.util import find_library import sys, os sys.path.append('.') def _init(): """ Loads the shared library through ctypes and returns a library L{ctypes.CDLL} instance """ if hasattr(sys, 'frozen'): os.environ['PATH'] = os.path.join(os.path.dirname(sys.executable), "resources") + ";" + os.environ['PATH'] ctypes.cdll.LoadLibrary('libgnurx-0.dll') return ctypes.cdll.LoadLibrary('libmagic-1.dll') else: ctypes.cdll.LoadLibrary('dff/api/magic/libgnurx-0.dll') return ctypes.cdll.LoadLibrary('dff/api/magic/libmagic-1.dll') _libraries = {} _libraries['magic'] = _init() # Flag constants for open and setflags MAGIC_NONE = NONE = 0 MAGIC_DEBUG = DEBUG = 1 MAGIC_SYMLINK = SYMLINK = 2 MAGIC_COMPRESS = COMPRESS = 4 MAGIC_DEVICES = DEVICES = 8 MAGIC_MIME_TYPE = MIME_TYPE = 16 MAGIC_CONTINUE = CONTINUE = 32 MAGIC_CHECK = CHECK = 64 MAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128 MAGIC_RAW = RAW = 256 MAGIC_ERROR = ERROR = 512 MAGIC_MIME_ENCODING = MIME_ENCODING = 1024 MAGIC_MIME = MIME = 1040 MAGIC_APPLE = APPLE = 2048 MAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096 MAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192 MAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384 MAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768 MAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536 MAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072 MAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144 MAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576 MAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152 MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824 class magic_set(Structure): pass magic_set._fields_ = [] magic_t = POINTER(magic_set) _open = _libraries['magic'].magic_open _open.restype = magic_t _open.argtypes = [c_int] _close = _libraries['magic'].magic_close _close.restype = None _close.argtypes = [magic_t] _file = _libraries['magic'].magic_file _file.restype = c_char_p _file.argtypes = [magic_t, c_char_p] _descriptor = _libraries['magic'].magic_descriptor _descriptor.restype = c_char_p _descriptor.argtypes = [magic_t, c_int] _buffer = _libraries['magic'].magic_buffer _buffer.restype = c_char_p _buffer.argtypes = [magic_t, c_void_p, c_size_t] _error = _libraries['magic'].magic_error _error.restype = c_char_p _error.argtypes = [magic_t] _setflags = _libraries['magic'].magic_setflags _setflags.restype = c_int _setflags.argtypes = [magic_t, c_int] _load = _libraries['magic'].magic_load _load.restype = c_int _load.argtypes = [magic_t, c_char_p] _compile = _libraries['magic'].magic_compile _compile.restype = c_int _compile.argtypes = [magic_t, c_char_p] _check = _libraries['magic'].magic_check _check.restype = c_int _check.argtypes = [magic_t, c_char_p] _list = _libraries['magic'].magic_list _list.restype = c_int _list.argtypes = [magic_t, c_char_p] _errno = _libraries['magic'].magic_errno _errno.restype = c_int _errno.argtypes = [magic_t] class Magic(object): def __init__(self, ms): self._magic_t = ms def close(self): """ Closes the magic database and deallocates any resources used. """ _close(self._magic_t) def file(self, filename): """ Returns a textual description of the contents of the argument passed as a filename or None if an error occurred and the MAGIC_ERROR flag is set. A call to errno() will return the numeric error code. """ try: # attempt python3 approach first bi = bytes(filename, 'utf-8') return str(_file(self._magic_t, bi), 'utf-8') except: return _file(self._magic_t, filename) def descriptor(self, fd): """ Like the file method, but the argument is a file descriptor. """ return _descriptor(self._magic_t, fd) def buffer(self, buf): """ Returns a textual description of the contents of the argument passed as a buffer or None if an error occurred and the MAGIC_ERROR flag is set. A call to errno() will return the numeric error code. """ try: # attempt python3 approach first return str(_buffer(self._magic_t, buf, len(buf)), 'utf-8') except: return _buffer(self._magic_t, buf, len(buf)) def error(self): """ Returns a textual explanation of the last error or None if there was no error. """ try: # attempt python3 approach first return str(_error(self._magic_t), 'utf-8') except: return _error(self._magic_t) def setflags(self, flags): """ Set flags on the magic object which determine how magic checking behaves; a bitwise OR of the flags described in libmagic(3), but without the MAGIC_ prefix. Returns -1 on systems that don't support utime(2) or utimes(2) when PRESERVE_ATIME is set. """ return _setflags(self._magic_t, flags) def load(self, filename=None): """ Must be called to load entries in the colon separated list of database files passed as argument or the default database file if no argument before any magic queries can be performed. Returns 0 on success and -1 on failure. """ return _load(self._magic_t, filename) def compile(self, dbs): """ Compile entries in the colon separated list of database files passed as argument or the default database file if no argument. Returns 0 on success and -1 on failure. The compiled files created are named from the basename(1) of each file argument with ".mgc" appended to it. """ return _compile(self._magic_t, dbs) def check(self, dbs): """ Check the validity of entries in the colon separated list of database files passed as argument or the default database file if no argument. Returns 0 on success and -1 on failure. """ return _check(self._magic_t, dbs) def list(self, dbs): """ Check the validity of entries in the colon separated list of database files passed as argument or the default database file if no argument. Returns 0 on success and -1 on failure. """ return _list(self._magic_t, dbs) def errno(self): """ Returns a numeric error code. If return value is 0, an internal magic error occurred. If return value is non-zero, the value is an OS error code. Use the errno module or os.strerror() can be used to provide detailed error information. """ return _errno(self._magic_t) def open(flags): """ Returns a magic object on success and None on failure. Flags argument as for setflags. """ return Magic(_open(flags)) dff-1.3.0+dfsg.1/dff/api/manager/000077500000000000000000000000001217176075400162645ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/manager/CMakeLists.txt000066400000000000000000000013431217176075400210250ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py manager.py ) dff-1.3.0+dfsg.1/dff/api/manager/__init__.py000066400000000000000000000012231217176075400203730ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_MANAGER_VERSION}" __all__ = ["manager"] dff-1.3.0+dfsg.1/dff/api/manager/manager.py000066400000000000000000000031231217176075400202470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob from dff.api.types import libtypes from dff.api.search import libsearch from dff.api.datatype import libdatatype from dff.api.exceptions import libexceptions from dff.api.events import libevents from dff.api.vfs import vfs, libvfs from dff.api.loader import loader from dff.api.taskmanager.taskmanager import TaskManager from dff.api.taskmanager.scheduler import sched from dff.api.taskmanager.processus import Processus from dff.api.datatype.magichandler import * from dff.api.tree import libtree class ApiManager(): class __ApiManager(): def __init__(self): self.vfs = vfs.vfs self.TaskManager = TaskManager self.loader = loader.loader self.Path = libtypes.Path __instance = None def __init__(self): if ApiManager.__instance is None: ApiManager.__instance = ApiManager.__ApiManager() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) dff-1.3.0+dfsg.1/dff/api/module/000077500000000000000000000000001217176075400161375ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/module/CMakeLists.txt000066400000000000000000000013721217176075400207020ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py module.py script.py manager.py ) dff-1.3.0+dfsg.1/dff/api/module/__init__.py000066400000000000000000000012331217176075400202470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_MODULE_VERSION}" __all__ = ["script", "module"] dff-1.3.0+dfsg.1/dff/api/module/manager.py000066400000000000000000000027331217176075400201300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # class ModuleProcessusManager(): __instance = None class __ModuleProcessusManager(): def __init__(self): self.handlers = {} def register(self, handler): self.handlers[handler.name] = handler return True def update(self, processus): try: self.handlers[processus.name].update(processus) except KeyError: pass def get(self, moduleName): try: return self.handlers[moduleName] except KeyError: return None def __init__(self): if ModuleProcessusManager.__instance is None: ModuleProcessusManager.__instance = ModuleProcessusManager.__ModuleProcessusManager() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) class ModuleProcessusHandler(): def __init__(self, name): self.name = name ModuleProcessusManager().register(self) dff-1.3.0+dfsg.1/dff/api/module/module.py000066400000000000000000000045601217176075400200030ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # import sys import traceback from dff.api.module.script import * from dff.api.exceptions.libexceptions import * from dff.api.vfs import * from dff.api.types import libtypes from dff.api.vfs.libvfs import * class Module(object): def __init__(self, name, icl): self.cl = icl self.name = name self.single = None self.icon = None try : if issubclass(self.cl, Script): self.conf = libtypes.Config(name) self.conf.thisown = False if self.__doc__: self.conf.description = self.__doc__ self.getflags() except TypeError: pass try : if issubclass(self.cl, mfso) or issubclass(self.cl, fso): self.conf = libtypes.Config(name) self.conf.thisown = False if self.__doc__: self.conf.description = self.__doc__ self.getflags() except TypeError: pass try : if self.tags == "": self.tags = "others" except AttributeError: self.tags = "others" def getflags(self): try : if self.flags: pass except AttributeError: self.flags = [""] try : if self.cl.c_display : self.flags += ["console"] except AttributeError: pass try : if self.cl.g_display: self.flags += ["gui"] except AttributeError: pass def create(self): if "single" in self.flags: if self.single == None: self.single = self.cl() return self.single try : if issubclass(self.cl, Script): return self.cl() except TypeError: pass try : if issubclass(self.cl, mfso) or issubclass(self.cl, fso): try : fs = self.cl() return fs except : exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, None, sys.stdout) except TypeError: pass dff-1.3.0+dfsg.1/dff/api/module/script.py000066400000000000000000000015221217176075400200150ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # import sys, traceback from dff.api.vfs import * from dff.api.types.libtypes import VMap from dff.api.exceptions.libexceptions import * class Script(object): def __init__(self, name): self.name = name self.vfs = vfs.vfs() self.stateinfo = "" self.res = VMap() self.icon = None dff-1.3.0+dfsg.1/dff/api/search/000077500000000000000000000000001217176075400161175ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/search/CMakeLists.txt000066400000000000000000000016771217176075400206720ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin if (TRE_FOUND) set(search_files __init__.py) if(WIN32) file(COPY ${TRE_DYN_LIBRARIES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) set(search_files ${search_files} tre.dll) endif(WIN32) set(link_libraries ${TRE_LIBRARY}) endif (TRE_FOUND) dff_cpp_api(search CPP_FILES search.cpp boyer_moore.cpp SWIG_FILE libsearch.i LINK_LIBRARIES ${link_libraries} EXTRA_FILES ${search_files} ) dff-1.3.0+dfsg.1/dff/api/search/__init__.py000066400000000000000000000011521217176075400202270ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __version__ = "${API_SEARCH_VERSION}" __all__ = ["libsearch"] dff-1.3.0+dfsg.1/dff/api/search/boyer_moore.cpp000066400000000000000000000132651217176075400211530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "boyer_moore.hpp" BoyerMoore::BoyerMoore() { this->bcs = NULL; } BoyerMoore::BoyerMoore(unsigned char *needle, unsigned int needlesize, unsigned char wildcard) { this->bcs = NULL; if (needle != NULL) this->needle = needle; this->needleSize = needlesize; if (wildcard != 0x00) this->wildcard = wildcard; else this->wildcard = 0x00; this->computeBcs(); } BoyerMoore::~BoyerMoore() { if (this->bcs != NULL) free(this->bcs); } bool BoyerMoore::preprocess() { bool ret; if (this->bcs != NULL) free(this->bcs); ret = this->computeBcs(); return ret; } bool BoyerMoore::computeBcs() { unsigned int i; unsigned int j; unsigned int ridx = 0; if (this->needle != NULL) { this->bcs = (unsigned char*)malloc(sizeof(unsigned char) * UCHAR_MAX + 1); if (this->bcs == NULL || this->needleSize <= 0) return false; for (i = 0; i != UCHAR_MAX + 1; i++) this->bcs[i] = this->needleSize; for (i = 0; i < this->needleSize - 1; i++) { ridx = this->needleSize - i - 1; if (this->needle[i] == wildcard) for (j = 0; j <= UCHAR_MAX; j++) this->bcs[j] = ridx; this->bcs[this->needle[i]] = ridx; } return true; } return false; } unsigned int BoyerMoore::charMatch(unsigned char c1, unsigned char c2) { if (((wildcard != '\0') && (c1 == wildcard)) || (c1 == c2)) return 1; else return 0; } unsigned int BoyerMoore::charMatch(unsigned char c1, unsigned char c2, unsigned char w) { if (((w != '\0') && (c1 == w)) || (c1 == c2)) return 1; else return 0; } unsigned char *BoyerMoore::generateBcs(pattern *p) { unsigned int i; unsigned int j; unsigned int ridx = 0; unsigned char *bcs; bcs = (unsigned char*)malloc(sizeof(unsigned char) * UCHAR_MAX + 1); if ((bcs != NULL) && (p->size > 0)) { for (i = 0; i != UCHAR_MAX + 1; i++) bcs[i] = p->size; for (i = 0; i < p->size - 1; i++) { ridx = p->size - i - 1; if (p->needle[i] == p->wildcard) for (j = 0; j <= UCHAR_MAX; j++) bcs[j] = ridx; bcs[p->needle[i]] = ridx; } } return bcs; } int BoyerMoore::search(unsigned char *haystack, unsigned int hslen, pattern *p, unsigned char *bcs, bool debug) { unsigned int hspos; int ndpos; //list *l = new list; int shift; hspos = 0; if (p->size > hslen) return -1; while (hspos <= (hslen - p->size)) { for (ndpos = p->size - 1; ndpos != -1; ndpos--) { if (debug) { printf("hslen: %d -- ndpos: %d -- hspos: %d\n", hslen, ndpos, hspos); printf("needle: %x -- haystack: %x\n", p->needle[ndpos], haystack[hspos+ndpos]); } if (this->charMatch(p->needle[ndpos], haystack[hspos+ndpos], p->wildcard) == 0) { break; } } if (ndpos == -1) return hspos; else { if (debug) printf("HERE\n"); shift = bcs[(unsigned char)haystack[hspos + ndpos]] - p->size + 1 + ndpos; if (shift <= 0) shift = 1; hspos += shift; } } return -1; } std::list *BoyerMoore::search(unsigned char *haystack, unsigned int hslen, unsigned int *count) { unsigned int hspos; int ndpos; std::list *l = new std::list; int shift; hspos = 0; if (this->needleSize > hslen) return l; while ((hspos <= (hslen - this->needleSize)) && (*count != 0)) { for (ndpos = this->needleSize - 1; ndpos != -1; ndpos--) if (this->charMatch(this->needle[ndpos], haystack[hspos+ndpos]) == 0) break; if (ndpos == -1) { l->push_back(hspos); if (this->needleSize == 1) hspos++; else hspos += this->needleSize - 1; (*count)--; } else { shift = this->bcs[(unsigned char)haystack[hspos + ndpos]] - this->needleSize + 1 + ndpos; if (shift <= 0) shift = 1; hspos += shift; } } return l; } std::list *BoyerMoore::search(unsigned char *haystack, unsigned int hslen) { unsigned int hspos; int ndpos; std::list *l = new std::list; int shift; hspos = 0; if (this->needleSize > hslen) return l; while (hspos <= hslen - this->needleSize) { for (ndpos = this->needleSize - 1; ndpos != -1; ndpos--) if (this->charMatch(this->needle[ndpos], haystack[hspos+ndpos]) == 0) break; if (ndpos == -1) { l->push_back(hspos); if (this->needleSize == 1) hspos++; else hspos += this->needleSize - 1; } else { shift = this->bcs[(unsigned char)haystack[hspos + ndpos]] - this->needleSize + 1 + ndpos; if (shift <= 0) shift = 1; hspos += shift; } } return l; } bool BoyerMoore::setNeedleSize(unsigned int ns) { bool ret; ret = true; if (ns != 0) this->needleSize = ns; else ret = false; return ret; } bool BoyerMoore::setNeedle(unsigned char *n) { bool ret; ret = true; if (n != NULL) this->needle = n; else ret = false; return ret; } bool BoyerMoore::setWildcard(unsigned char w) { bool ret; ret = true; if (wildcard != '\0') this->wildcard = w; else ret = false; return ret; } unsigned char *BoyerMoore::getNeedle() { return this->needle; } unsigned char BoyerMoore::getWildcard() { return this->wildcard; } dff-1.3.0+dfsg.1/dff/api/search/boyer_moore.hpp000066400000000000000000000045061217176075400211560ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #ifndef __BOYER_MORE_HPP__ #define __BOYER_MORE_HPP__ #define HAYSTACKLEN 10*1024*1024 #include #include #include #include #include "export.hpp" #include "pattern.hpp" #ifndef UCHAR_MAX #define UCHAR_MAX 255 #endif typedef struct s_bmContext { unsigned char* bcs; unsigned int len; unsigned char* needle; unsigned char wildcard; unsigned int window; unsigned int count; } bmContext; class BoyerMoore { private: unsigned char* needle; unsigned char wildcard; unsigned int needleSize; unsigned char* bcs; bool debug; bool computeBcs(); unsigned int charMatch(unsigned char c1, unsigned char c2); unsigned int charMatch(unsigned char c1, unsigned char c2, unsigned char w); public: EXPORT BoyerMoore(); EXPORT BoyerMoore(unsigned char *needle, unsigned int needlesize, unsigned char wildcard); EXPORT ~BoyerMoore(); EXPORT virtual std::list *search(unsigned char *haystack, unsigned int hslen, unsigned int *count); EXPORT virtual std::list *search(unsigned char *haystack, unsigned int hslen); EXPORT unsigned char* generateBcs(pattern *p); EXPORT int search(unsigned char *haystack, unsigned int len, pattern *p, unsigned char *bcs, bool debug=false); EXPORT virtual bool preprocess(); EXPORT virtual bool setNeedle(unsigned char *needle); EXPORT virtual bool setNeedleSize(unsigned int size); EXPORT virtual bool setWildcard(unsigned char wildcard); EXPORT virtual unsigned char* getNeedle(); EXPORT virtual unsigned char getWildcard(); }; #endif dff-1.3.0+dfsg.1/dff/api/search/libsearch.i000066400000000000000000000034341217176075400202310ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "pyrun.swg" %module(package="dff.api.search") libsearch /*%module(package="dff.api.vfs",docstring="searching...", directors="1") libsearch */ %feature("autodoc", 1); //1 = generate type for func proto, no work for typemap %feature("docstring"); /* %feature("docstring") Search */ /* " */ /* This class is used to search patterns. */ /* " */ /* %feature("docstring") algorithm */ /* " */ /* This class is an interface which must be extended. It allows users to develope */ /* custom search algorithms. */ /* " */ %feature("director") SearchAlgorithm; %feature("director") FastSearch; #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include "std_string.i" %include "std_list.i" %include "windows.i" %typemap(in) (unsigned char* haystack, uint32_t hslen) { if (!PyString_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a string"); return NULL; } $1 = (unsigned char *) PyString_AsString($input); $2 = (uint32_t) PyString_Size($input); } %apply (unsigned char* haystack, uint32_t hslen) { (unsigned char* needle, uint32_t ndlen) }; %{ #include "../include/export.hpp" #include "../include/search.hpp" %} %import "../include/export.hpp" %include "../include/search.hpp" dff-1.3.0+dfsg.1/dff/api/search/pattern.hpp000066400000000000000000000016141217176075400203070ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __PATTERN_HPP__ #define __PATTERN_HPP__ // This structure will certainly evolved in the future as a class in order // to manage more complex pattern matching which could be used in our regexp // engine. typedef struct s_pattern { unsigned char *needle; unsigned int size; unsigned char wildcard; } pattern; #endif dff-1.3.0+dfsg.1/dff/api/search/search.cpp000066400000000000000000000450611217176075400200760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "search.hpp" #include #include //#define DEBUGSEARCH 1 Search::Search() { this->__pattern = ""; this->__compiled = false; this->__needtrefree = false; this->__cs = CaseSensitive; this->__nlen = 512; this->__syntax = Fixed; #if HAVE_TRE this->__aparams.max_err = 3; this->__aparams.max_ins = this->__aparams.max_del = this->__aparams.max_subst = 1; #endif } Search::Search(std::string pattern, CaseSensitivity cs, PatternSyntax syntax) { this->__pattern = pattern; this->__cs = cs; this->__syntax = syntax; this->__compiled = false; this->__needtrefree = false; this->__nlen = 0; #if HAVE_TRE this->__aparams.max_err = 3; this->__aparams.max_ins = this->__aparams.max_del = this->__aparams.max_subst = 1; #endif } Search::~Search() { #if HAVE_TRE if (this->__needtrefree) tre_free(&this->__preg); #endif } void Search::setPattern(std::string pattern) { this->__compiled = false; this->__pattern = pattern; } std::string Search::pattern() { return this->__pattern; } void Search::setPatternSyntax(Search::PatternSyntax syntax) { #ifndef HAVE_TRE if ((syntax == Regexp) || (syntax == Fuzzy)) std::cout << "not compiled with tre library, search won't provide results" << std::endl; #endif if (this->__syntax != syntax) this->__compiled = false; this->__syntax = syntax; } Search::PatternSyntax Search::patternSyntax() { return this->__syntax; } void Search::setCaseSensitivity(Search::CaseSensitivity cs) { if (this->__cs != cs) this->__compiled = false; this->__cs = cs; } Search::CaseSensitivity Search::caseSensitivity() { return this->__cs; } uint32_t Search::needleLength() { return this->__nlen; } int32_t Search::find(char* haystack, uint32_t hslen) throw (std::string) { if (!this->__compiled) this->compile(); if (hslen) return (this->*(__find))(haystack, hslen); else return -1; } int32_t Search::find(std::string haystack) throw (std::string) { if (!this->__compiled) this->compile(); if (haystack.size()) return (this->*(__find))((char*)haystack.c_str(), haystack.size()); else return -1; } int32_t Search::rfind(char* haystack, uint32_t hslen) throw (std::string) { if (this->__syntax == Regexp || this->__syntax == Fuzzy) throw std::string("regexp and fuzzy rfind not supported"); if (!this->__compiled) this->compile(); if (hslen) return (this->*(__rfind))(haystack, hslen); else return -1; } int32_t Search::rfind(std::string haystack) throw (std::string) { if (this->__syntax == Regexp || this->__syntax == Fuzzy) throw std::string("regexp and fuzzy rfind not supported"); if (!this->__compiled) this->compile(); if (haystack.size()) return (this->*(__rfind))((char*)haystack.c_str(), haystack.size()); else return -1; } int32_t Search::count(char* haystack, uint32_t hslen, int32_t maxcount) throw (std::string) { if (!this->__compiled) this->compile(); if (hslen) return (this->*(__count))(haystack, hslen, maxcount); else return -1; } int32_t Search::count(std::string haystack, int32_t maxcount) throw (std::string) { if (!this->__compiled) this->compile(); if (haystack.size()) return (this->*(__count))((char*)haystack.c_str(), haystack.size(), maxcount); else return -1; } void Search::compile() throw (std::string) { if (this->__pattern == "") throw(std::string("pattern not setted")); if (this->__syntax == Fixed) { this->__nlen = this->__pattern.size(); __find = &Search::__ffind; __rfind = &Search::__frfind; __count = &Search::__fcount; } else if (this->__syntax == Wildcard) this->__wcompile(); else if (this->__syntax == Regexp) this->__recompile(); else if (this->__syntax == Fuzzy) this->__fzcompile(); else throw std::string("syntax is neither setted nor correct"); this->__compiled = true; } void Search::__wcompile() throw (std::string) { size_t i; std::string needle; bool rpattern = false; this->__nlen = 0; needle = ""; this->__wctxs.clear(); for (i = 0; i != this->__pattern.size(); i++) { if ((this->__pattern[i] != '?') && (this->__pattern[i] != '*')) { rpattern = true; needle += this->__pattern[i]; this->__nlen++; } else { if (this->__pattern[i] != '?') this->__nlen += 1; else if (this->__pattern[i] != '*') this->__nlen += 512; if (needle.size()) { this->__wctxs.push_back(needle); needle.clear(); } this->__wctxs.push_back(std::string(1, this->__pattern[i])); } } if (needle.size()) this->__wctxs.push_back(needle); if (!rpattern) throw (std::string("pattern is not useful, only * and ? provided")); #ifdef DEBUGSEARCH std::cout << "original pattern --> " << this->__pattern; std::cout << "compile pattern with max length of: " << this->__nlen; for (i = 0; i != this->__wctxs.size(); i++) std::cout << std::string(3, ' ') << this->__wctxs[i] << std::endl; #endif __find = &Search::__wfind; __rfind = &Search::__wrfind; __count = &Search::__wcount; } void Search::__recompile() throw (std::string) { #ifdef HAVE_TRE int cflags; if (this->__needtrefree) tre_free(&this->__preg); cflags = REG_EXTENDED; if (this->__cs == Search::CaseInsensitive) cflags |= REG_ICASE; if (tre_regncomp(&this->__preg, this->__pattern.c_str(), this->__pattern.size(), cflags) == REG_OK) this->__needtrefree = true; else throw std::string("error while compiling regexp: " + this->__pattern); __find = &Search::__refind; __rfind = NULL; __count = &Search::__recount; #else throw std::string("regexp support not activated (libtre not linked)"); #endif } void Search::__fzcompile() throw (std::string) { #ifdef HAVE_TRE int cflags; if (this->__needtrefree) tre_free(&this->__preg); cflags = REG_LITERAL; if (this->__cs == Search::CaseInsensitive) cflags |= REG_ICASE; if (tre_regncomp(&this->__preg, this->__pattern.c_str(), this->__pattern.size(), cflags) == REG_OK) this->__needtrefree = true; else throw std::string("error while compiling regexp: " + this->__pattern); __find = &Search::__afind; __rfind = NULL; __count = &Search::__acount; #else throw std::string("fuzzy support not activated (libtre not linked)"); #endif } int32_t Search::__ffind(char* haystack, uint32_t hslen) { if (this->__cs == CaseInsensitive) return cifastsearch((unsigned char*)haystack, hslen, (unsigned char*)this->__pattern.c_str(), this->__nlen, 1, FAST_SEARCH); else return fastsearch((unsigned char*)haystack, hslen, (unsigned char*)this->__pattern.c_str(), this->__nlen, 1, FAST_SEARCH); } #include #include int32_t Search::__wfind(char* haystack, uint32_t hslen) { if (this->__cs == CaseSensitive) return this->__wfindint((unsigned char*)haystack, hslen, &fastsearch, 0, 0); else return this->__wfindint((unsigned char*)haystack, hslen, &cifastsearch, 0, 0); } int32_t Search::__wfindint(unsigned char* haystack, uint32_t hslen, sfunc s, size_t vpos, uint32_t window) { std::string needle; uint32_t rwindow; int32_t idx; uint32_t oidx; #ifdef DEBUGSEARCH std::ostringstream ostr; #endif needle = this->__wctxs[vpos]; if (needle != "?" && needle != "*") { if (vpos == (this->__wctxs.size() - 1)) { if ((needle.size() + window) < hslen) rwindow = needle.size() + window; else rwindow = hslen; #ifdef DEBUGSEARCH ostr << std::string(vpos, '\t') << "vpos: %d / %d -- token: %s -- hslen: %d -- nsize: %d -- haystack: %" << hslen << "s\n"; printf(ostr.str().c_str(), vpos, this->__wctxs.size(), needle.c_str(), rwindow, needle.size(), haystack); #endif return s((unsigned char*)haystack, rwindow, (unsigned char*)needle.c_str(), needle.size(), 1, FAST_SEARCH); } else { if (hslen == 0) return -1; idx = -1; #ifdef DEBUGSEARCH ostr << std::string(vpos, '\t') << "vpos: %d / %d -- token: %s -- hslen: %d -- nsize: %d -- haystack: %" << hslen << "s\n"; printf(ostr.str().c_str(), vpos, this->__wctxs.size(), needle.c_str(), hslen, needle.size(), haystack); #endif oidx = 0; while ((idx = s((unsigned char*)haystack+oidx, hslen-oidx, (unsigned char*)needle.c_str(), needle.size(), 1, FAST_SEARCH)) != -1) { #ifdef DEBUGSEARCH ostr.str(""); ostr << std::string(vpos, '\t') << "%d / %d -- token: %s -- hslen: %d -- nsize: %d -- haystack: %" << hslen-oidx << "s\n"; printf(ostr.str().c_str(), vpos, this->__wctxs.size(), needle.c_str(), hslen-oidx, needle.size(), haystack+oidx); #endif oidx += idx + needle.size(); if (this->__wfindint(haystack+oidx, hslen-oidx, s, vpos+1, 0) != -1) return idx; } } } else { if (vpos == (this->__wctxs.size() - 1)) return 0; if (needle == "?") rwindow = 1; else rwindow = 512; #ifdef DEBUGSEARCH ostr << std::string(vpos, '\t') << "vpos: %d / %d -- token: %s -- hslen: %d -- nsize: %d -- haystack: %" << hslen << "s -- %d\n"; printf(ostr.str().c_str(), vpos, this->__wctxs.size(), needle.c_str(), hslen, needle.size(), haystack, this->__cs); #endif return this->__wfindint(haystack, hslen, s, vpos+1, rwindow); } //never reached return -1; } int32_t Search::__refind(char* haystack, uint32_t hslen) { int32_t ret; ret = -1; #ifdef HAVE_TRE regmatch_t pmatch[1]; if (tre_regnexec(&this->__preg, haystack, hslen, 1, pmatch, 0) == REG_OK) { ret = pmatch[0].rm_so; this->__nlen = pmatch[0].rm_eo - pmatch[0].rm_so; } else this->__nlen = 512; #endif this->__nlen = 1; return ret; } int32_t Search::__afind(char* haystack, uint32_t hslen) { int32_t ret; ret = -1; #ifdef HAVE_TRE regamatch_t match; regmatch_t pmatch[1]; regaparams_t params; params.max_err = 3; params.max_cost = INT32_MAX; params.cost_ins = INT32_MAX; params.cost_subst = INT32_MAX; params.cost_del = INT32_MAX; params.max_subst = INT32_MAX; params.max_del = INT32_MAX; params.max_ins = INT32_MAX; memset(&match, 0, sizeof(match)); match.pmatch = pmatch; match.nmatch = 1; if (tre_reganexec(&this->__preg, haystack, hslen, &match, params, 0) == REG_OK) { ret = match.pmatch[0].rm_so; this->__nlen = match.pmatch[0].rm_eo - match.pmatch[0].rm_so; // std::cout << std::string(42, '=') << std::endl; // std::cout << std::string(haystack+ret, this->__nlen) << std::endl; // std::cout << "match cost ------> " << match.cost << std::endl; // std::cout << "num_ins ---------> " << match.num_ins << std::endl; // std::cout << "num_del ---------> " << match.num_del << std::endl; // std::cout << "num_subst -------> " << match.num_subst << std::endl; // std::cout << std::string(42, '=') << std::endl; } else { //Current implementation only provide support for fixed litteral. If the //provided string described a regexp, it won't be interpreted. //Since max_err is set to 3, maximum needle len (when there's no match) can //be 3 insertion so this->__pattern.size() + 3 //Further implementation would let user to custom its weigth and regexp will //be enable though changing needle length at each round. //this->__nlen = this->__pattern.size() + 3; } #endif this->__nlen = 1; return ret; } int32_t Search::__frfind(char* haystack, uint32_t hslen) { if (this->__cs == CaseInsensitive) return cifastsearch((unsigned char*)haystack, hslen, (unsigned char*)this->__pattern.c_str(), this->__nlen, 1, FAST_RSEARCH); else return fastsearch((unsigned char*)haystack, hslen, (unsigned char*)this->__pattern.c_str(), this->__nlen, 1, FAST_RSEARCH); } int32_t Search::__wrfind(char* haystack, uint32_t hslen) { // std::vector::iterator it, sit; // int32_t buffpos; // int32_t sidx; // int32_t idx; // uint32_t skip; // int32_t (*sfunc)(const unsigned char*, int32_t, // const unsigned char*, int32_t, // int32_t, int); // if (this->__cs == CaseSensitive) // sfunc = &fastsearch; // else // sfunc = &cifastsearch; // it = this->__wctxs.end() - 1; // skip = 0; // while (it != this->__wctxs.begin()) // { // if (*(*it) == "?") // skip = 1; // else if (*(*it) == "*") // skip = 512; // else // { // sit = it; // break; // } // it--; // } // buffpos = hslen; // while ((buffpos > 0)) // { // DEBUG(INFO, " buffpos: %d -- sidx: %d\n", buffpos, sidx); // for (it = sit; it != this->__wctxs.begin(); it--) // { // if (*(*it) == "?") // { // DEBUG(INFO, " setting skip to 1\n"); // if (buffpos >= 1) // buffpos -= 1; // else // buffpos = 0; // skip = 1; // } // else if (*(*it) == "*") // { // DEBUG(INFO, " setting skip to 512\n"); // if (buffpos >= 512) // buffpos -= 512; // else // buffpos = 0; // skip = 512; // } // else // { // uint32_t size = (*it)->size(); // uint32_t curhlen = 0; // if (buffpos < size + skip) // buffpos = 0; // else // buffpos -= (size + skip); // if (hslen < buffpos + size + skip) // curhlen = hslen - buffpos; // else // curhlen = size + skip; // DEBUG(INFO, " searching needle %s -- needle size %d -- buffpos: %d -- skip: %d -- haystack length: %d\n", // (*it)->c_str(), size, buffpos, skip, curhlen); // if ((idx = sfunc((unsigned char*)(haystack+buffpos), curhlen, // (unsigned char*)((*it)->c_str()), size, // 1, FAST_RSEARCH)) == -1) // { // DEBUG(INFO, " no match found\n"); // return -1; // } // else // skip = 0; // } // } // DEBUG(INFO, "OUT OF LOOP -- buffpos: %d\n", buffpos); // DEBUG(INFO, "wctx.begin() --> %s\n", (*it)->c_str()); // if (it == this->__wctxs.begin()) // { // if (*(*it) == "?") // { // if (buffpos >= 1) // return buffpos - 1; // else // return buffpos; // } // else if (*(*it) == "*") // { // if (buffpos >= 512) // return buffpos - 512; // else // return 0; // } // else // { // int32_t ret; // if (hslen < (skip + (*it)->size())) // buffpos = 0; // else // buffpos = hslen - (skip + (*it)->size()); // DEBUG(INFO, "First pattern is last of context %s\n", (*it)->c_str()); // ret = sfunc((unsigned char*)(haystack+buffpos), skip+(*it)->size(), // (unsigned char*)((*it)->c_str()), (*it)->size(), // 1, FAST_RSEARCH); // if (ret != -1) // return buffpos + ret; // else // return -1; // } // } // } return -1; } int32_t Search::__fcount(char* haystack, uint32_t hslen, int32_t maxcount) { if (this->__cs == CaseInsensitive) return cifastsearch((unsigned char*)haystack, hslen, (unsigned char*)this->__pattern.c_str(), this->__nlen, maxcount, FAST_COUNT); else return fastsearch((unsigned char*)haystack, hslen, (unsigned char*)this->__pattern.c_str(), this->__nlen, maxcount, FAST_COUNT); } int32_t Search::__wcount(char* haystack, uint32_t hslen, int32_t maxcount) { int32_t ret; int32_t count; int32_t pos; sfunc s; count = 0; ret = 0; pos = 0; if (this->__cs == CaseSensitive) s = &fastsearch; else s = &cifastsearch; while (ret != -1) { ret = this->__wfind(haystack+pos, hslen-pos); pos += ret; count++; } return count; } int32_t Search::__recount(char* haystack, uint32_t hslen, int32_t maxcount) { int32_t hpos; int32_t count; count = 0; hpos = 0; #ifdef HAVE_TRE regmatch_t pmatch[1]; this->__nlen = 512; while ((maxcount > 0) && (hpos < hslen) && (tre_regnexec(&this->__preg, haystack+hpos, hslen-hpos, 1, pmatch, 0) == REG_OK)) { hpos += pmatch[0].rm_eo; this->__nlen = hslen-hpos; count++; maxcount--; } #endif return count; } int32_t Search::__acount(char* haystack, uint32_t hslen, int32_t maxcount) { int32_t hpos; int32_t count; count = 0; hpos = 0; #ifdef HAVE_TRE regmatch_t pmatch[1]; this->__nlen = 512; while ((maxcount > 0) && (hpos < hslen) && (tre_regnexec(&this->__preg, haystack+hpos, hslen-hpos, 1, pmatch, 0) == REG_OK)) { hpos += pmatch[0].rm_eo; this->__nlen = hslen-hpos; count++; maxcount--; } #endif return count; } FastSearch::FastSearch()//: SearchAlgorithm() { } FastSearch::~FastSearch() { } int32_t FastSearch::find(unsigned char* haystack, uint32_t hslen, unsigned char* needle, uint32_t ndlen, unsigned char wildcard) { if (wildcard == '\0') return fastsearch(haystack, hslen, needle, ndlen, 1, FAST_SEARCH); else { if (fastsearch(needle, ndlen, &wildcard, 1, 1, FAST_SEARCH) == -1) return fastsearch(haystack, hslen, needle, ndlen, 1, FAST_SEARCH); else return wfastsearch(haystack, hslen, needle, ndlen, wildcard, 1, FAST_SEARCH); } } int32_t FastSearch::rfind(unsigned char* haystack, uint32_t hslen, unsigned char* needle, uint32_t ndlen, unsigned char wildcard) { if (wildcard == '\0') return fastsearch(haystack, hslen, needle, ndlen, 1, FAST_RSEARCH); else { if (fastsearch(needle, ndlen, &wildcard, 1, 1, FAST_SEARCH) == -1) return fastsearch(haystack, hslen, needle, ndlen, 1, FAST_RSEARCH); else return wfastsearch(haystack, hslen, needle, ndlen, wildcard, 1, FAST_RSEARCH); } } int32_t FastSearch::count(unsigned char* haystack, uint32_t hslen, unsigned char* needle, uint32_t ndlen, unsigned char wildcard, int32_t maxcount) { if (wildcard == '\0') return fastsearch(haystack, hslen, needle, ndlen, maxcount, FAST_COUNT); else { if (fastsearch(needle, ndlen, &wildcard, 1, 1, FAST_SEARCH) == -1) return fastsearch(haystack, hslen, needle, ndlen, maxcount, FAST_COUNT); else return wfastsearch(haystack, hslen, needle, ndlen, wildcard, maxcount, FAST_COUNT); } } dff-1.3.0+dfsg.1/dff/api/taskmanager/000077500000000000000000000000001217176075400171475ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/taskmanager/CMakeLists.txt000066400000000000000000000014041217176075400217060ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) install_file( __init__.py processus.py scheduler.py taskmanager.py ) dff-1.3.0+dfsg.1/dff/api/taskmanager/__init__.py000066400000000000000000000012651217176075400212640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "${API_TASKMANAGER_VERSION}" __all__ = ["taskmanager","scheduler", "processus"] dff-1.3.0+dfsg.1/dff/api/taskmanager/processus.py000066400000000000000000000201361217176075400215510ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import threading, time, sys, traceback from Queue import Queue from dff.api.vfs import vfs from dff.api.module.module import Script from dff.api.types.libtypes import VMap, Variant from dff.api.taskmanager.scheduler import sched from dff.api.module.manager import ModuleProcessusManager from dff.ui.console.utils import VariantTreePrinter class ProcessusManager(object): """This class store list of launched processus, and provide way to add or list them.""" __instance = None def __init__(self): if ProcessusManager.__instance is None: ProcessusManager.__instance = ProcessusManager.__ProcessusManager() def __setattr(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) def __iter__(self): if ProcessusManager.__instance is not None: for processus in ProcessusManager.__instance: yield processus def __len__(self): if ProcessusManager.__instance: return len(__instance) else: return 0 def __getitem__(self, item): if ProcessusManager.__instance: return ProcessusManager.__instance[item] else: return None class __ProcessusManager(object): def __init__(self): self.processus = [] self.dprocessus = {} self.lock = threading.Lock() #add for 'single' module, certainly better to have them be real singleton self.npid = 0 def pid(self, pid): """Return processus by pid""" self.lock.acquire() proc = self.processusID[pid] self.lock.release() return proc def exist(self, module, argument): """Search is a processus was created from the given module and argument. Return True or False. """ try: self.lock.acquire() procList = self.dprocessus[module.name] #map is thread safe for proc in procList: #proc list is not thread safe... flag = 1 procArgs = proc.args #XXX if != singleton -> hash ! # vmap is not tgread if isinstance(procArgs, VMap): for k, v in procArgs.iteritems(): #des fois c pas un DICT ? try : if str(v) != str(argument[k]): flag = 0 break except (IndexError, KeyError, TypeError): flag = 0 break if flag == 1: self.lock.release() return True else: print 'tm::exist::proc args ' + str(type(procArgs)) + ' mod: ' + str(module.name) self.lock.release() return False except KeyError: pass self.lock.release() return False def fsobj(self, fsobj): """Get processus by fsobj """ self.lock.acquire() try: procList = self.processus for proc in procList: try: if proc.this == fsobj.this: self.lock.release() return proc except: pass except KeyError: pass self.lock.release() return None def fsobjArgumentsByType(self, fsobj, argumentType): proc = self.fsobj(fsobj) match = [] if proc: arguments = proc.mod.conf.argumentsByType(argumentType) for argument in arguments: try: arg = proc.args[argument.name()] match.append(arg) except KeyError: pass return match def create(self, mod, args, exec_flags): self.lock.acquire() proc = Processus(mod, self.npid, None, exec_flags) self.__addProcessus__(proc) self.npid += 1 self.lock.release() return proc def singleCreate(self, mod, args, exec_flags): self.lock.acquire() try: proc = self.dprocessus[mod.name][0] self.lock.release() return proc except KeyError: proc = Processus(mod, self.npid, None, exec_flags) self.__addProcessus__(proc) self.npid += 1 self.lock.release() return proc def __addProcessus__(self, processus): """Add a newly created processus to the processus list""" self.processus.append(processus) try: self.dprocessus[processus.mod.name].append(processus) except KeyError: self.dprocessus[processus.mod.name] = [processus] def remove(self, processus): """Remove a processus from the list""" self.lock.acquire() self.dprocessus[processus.mod.name].remove(processus) self.processus.remove(processus) self.lock.release() def module(self, module): """Return processus by module""" try: self.lock.acquire() proc = self.dprocessus[module.name] self.lock.release() return proc except KeyError: self.lock.release() return None def __iter__(self): for processus in self.processus: yield processus def __len__(self): return len(self.processus) def __getitem__(self, processus): self.lock.acquire() proc = self.processus[processus] self.lock.release() return proc class Processus(Script): def __init__(self, mod, pid, args, exec_flags): #ProcessusManager().add(self) done elswere self.vfs = vfs.vfs() self.mod = mod self.inst = mod.create() self.exec_flags = exec_flags self.state = "wait" self.pid = pid self.args = args self.stream = Queue() self.event = threading.Event() self.vtreeprinter = VariantTreePrinter() self.timestart = 0 self.timeend = 0 self.streamOut = None #XXX test for singleton module that could be launch multiple time foder locker/ self.error_result = '' self.lock = threading.Lock() self.lock.acquire() self.launchCount = 0 self.lock.release() def launch(self, args): self.state = "Running" self.lock.acquire() self.launchCount += 1 self.timestart = time.time() self.timeend = 0 self.lock.release() try : self.args = args self.start(args) ModuleProcessusManager().update(self) try : if "gui" in self.exec_flags: if "gui" in self.mod.flags: for func in sched.event_func["add_qwidget"]: func(self) if "console" in self.exec_flags: if "console" in self.mod.flags: self.c_display() except AttributeError: pass except : error = sys.exc_info() self.error(error) self.setState() self.event.set() if not "thread" in self.exec_flags: self.result() def result(self): if self.res and len(self.res): self.lock.acquire() #singleton module can modify results buff = self.vtreeprinter.fillMap(0, self.res) self.lock.release() print buff def error(self, trace = None): if trace: err_type, err_value, err_traceback = trace res = "\n\nWhat:\n" res += "----------\n" err_typeval = traceback.format_exception_only(err_type, err_value) for err in err_typeval: res += err res += "\nWhere:\n" res += "-----------\n" err_trace = traceback.format_tb(err_traceback) for err in err_trace: res += err self.lock.acquire() #res = Variant(res) self.error_result += res self.state = "Fail" self.lock.release() def setState(self): #if trace == None and"gui" in self.exec_flags and "gui" in self.mod.flags: #self.state = "wait" self.lock.acquire() self.launchCount -= 1 if self.launchCount <= 0: self.timeend = time.time() if self.state != "Fail": self.state = "Finish" self.lock.release() def __getattr__(self, attr): return getattr(self.inst, attr) dff-1.3.0+dfsg.1/dff/api/taskmanager/scheduler.py000066400000000000000000000045421217176075400215040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # import threading, sys, traceback, multiprocessing from Queue import Queue from dff.api.types.libtypes import VMap event_type = ["add_qwidget"] class WorkQueue(): class __WorkQueue(): def launch(self): while True: work = self.waitQueue.get() self.workerQueue.put(work) def enqueue(self, proc): self.waitQueue.put(proc) def set_callback(self, type, func): if type in self.event_func: self.event_func[type].append(func) def worker(self): while True: queuedTask = self.workerQueue.get() for (func, arg) in queuedTask: try: if func.im_class.__name__ == "Processus": func(arg) elif arg: func(*arg) else: func() except : print "worker error" err_type, err_value, err_traceback = sys.exc_info() for n in traceback.format_exception_only(err_type, err_value): print n for n in traceback.format_tb(err_traceback): print n self.workerQueue.task_done() def __init__(self, max = multiprocessing.cpu_count() * 2 + 1): self.waitQueue = Queue() self.workerQueue = Queue(max) self.max = max self.event_func = {} for type in event_type: self.event_func[type] = [] for i in range(max): thread = threading.Thread(target = self.worker, name = "Worker" + str(i)) thread.setDaemon(True) thread.start() __instance = None def __init__(self): if WorkQueue.__instance is None: WorkQueue.__instance = WorkQueue.__WorkQueue() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) sched = WorkQueue() def voidcall(node): pass sched.set_callback("add_widget", voidcall) thread = threading.Thread(target = sched.launch) thread.setDaemon(True) thread.start() dff-1.3.0+dfsg.1/dff/api/taskmanager/taskmanager.py000066400000000000000000000404261217176075400220240ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from Queue import Queue import threading, time, datetime,sys, traceback from dff.api.vfs.libvfs import VFS, VLink from dff.api.events.libevents import EventHandler from dff.api.exceptions.libexceptions import envError, vfsError from dff.api.types.libtypes import Variant, VMap, typeId, Argument, Parameter, ConfigManager from dff.api.taskmanager.scheduler import sched from dff.api.taskmanager.processus import ProcessusManager, Processus from dff.api.loader import loader class ModulesConfig(): def __init__(self): self.modules = {} def __iter__(self): for mod in self.modules: yield mod def __len__(self): return len(self.modules) def __getitem__(self, mod): return self.modules[mod] def __str__(self): return str(self.modules) def modulesConfig(self): return self.modules def isSet(self, module): try : self.modules[module] return True except KeyError: return False def config(self, module): try: self.modules[module] return self.modules[module] except KeyError: return None def addArgument(self, module, argument, value): try: arguments = self.modules[module][0] if arguments == None: arguments = {} arguments[argument] = value self.modules[module] = (arguments, self.modules[module][1]) return True except KeyError, key: return False def argument(self, module, argument): try: arguments = self.modules[module][0] if arguments: return arguments[argument] else: return None except KeyError: return None return None def removeArgument(self, module, argument): try: arguments = self.modules[module][0] if arguments: arguments.pop(argument) self.modules[module] = (arguments, self.modules[module][1]) else: return False return True except KeyError, key: return False def flag(self, module): try: return self.modules[module][1] except KeyError: return [] def addFlag(self, module, flag): try: flags = self.modules[module][1] if flag == None: flag = [] flags.append(flag) self.modules[module] = (self.modules[module][0], flags) return True except KeyError, key: return False def removeFlag(self, module, flag): try: flags = self.modules[module][1] if flag in flags: flags.remove(flag) self.modules[module] = (self.modules[module][0], flags) else: return False return True except KeyError, key: return False def add(self, mod, args = None, exec_flags = []): try : #if module already choosen overwrite argument or exec_flags only if none was set before (margs, mexec_flags) = self.modules[mod] if margs: args = margs if mexec_flags: exec_flags = mexec_flags self.modules[mod] = (args, exec_flags) return False except KeyError: self.modules[mod] = (args, exec_flags) return True def remove(self, mod, args = None, exec_flags = None): try : self.modules.pop(mod) return True except KeyError: return False def clear(self): self.modules.clear() class TaskManager(): class __TaskManager(EventHandler): def __init__(self): EventHandler.__init__(self) self.loader = loader.loader() self.processusManager = ProcessusManager() self.VFS = VFS.Get() self.VFS.connection(self) self.ppModules = ModulesConfig() self.ppAnalyses = ModulesConfig() def addAnalyseDependencies(self): requiered = set() for moduleName in self.ppAnalyses: try: for module in self.loader.modules[moduleName].depends: requiered.add(module) except AttributeError: pass for moduleName in requiered: try: self.loader.modules[moduleName] self.ppModules.add(moduleName) except KeyError: try: modules = self.loader.tags[moduleName] for moduleName in modules: self.ppModules.add(moduleName) except KeyError: pass def moduleInstancesByName(self, name): instances = [] for proc in self.processusManager: if proc.name == name: instances.append(proc) return instances def processusByName(self, name): processus = [] for proc in self.processusManager: if proc.name == name: processus.append(proc) return processus def clearPostProcess(self): self.ppModules.clear() self.ppAnalyses.clear() def Event(self, e): if len(self.ppModules) and e != None and e.value != None: node = e.value.value() if node and not isinstance(node, VLink): ppsched.enqueueRegister(node) def postProcessWalk(self, node): job = (self.postProcess, (node,)) ppsched.enqueueProcessing(job) if node.hasChildren(): childrens = node.children() for child in childrens: self.postProcessWalk(child) def postProcess(self, node, recursive = False): try: compatModule = node.compatibleModules() for mod in self.ppModules: moduleObj = self.loader.modules[mod] if (node.isCompatibleModule(mod)) or ("generic" in moduleObj.flags): (args, exec_flags) = self.ppModules[mod] nodeName = moduleObj.conf.argumentsByType(typeId.Node)[0].name() if args == None: args = {} if exec_flags == None: exec_flags = ["console", "thread"] else: if not ("gui" in exec_flags or "console" in exec_flags): exec_flags.append("console") if not "thread" in exec_flags: exec_flags.append("thread") args[nodeName] = node arg = moduleObj.conf.generate(args) if not self.processusManager.exist(moduleObj, arg): ppsched.enqueueProcessus((self.add, (mod, arg, exec_flags, True))) except: err_type, err_value, err_traceback = sys.exc_info() for l in traceback.format_exception_only(err_type, err_value): print l for l in traceback.format_tb(err_traceback): print l def postProcessAnalyse(self, root): for mod in self.ppAnalyses: (args, exec_flags) = self.ppAnalyses[mod] moduleObj = self.loader.modules[mod] nodeName = moduleObj.conf.argumentsByType(typeId.Node) if args == None: args = {} if exec_flags == None: exec_flags = ["gui", "thread"] else: if not "thread" in exec_flags: exec_flags.append("thread") if not ("gui" in exec_flags) and ("gui" in moduleObj.flags): exec_flags.append("gui") try : if nodeName: args[nodeName[0].name()] = root arg = moduleObj.conf.generate(args) ppsched.enqueueAnalyse((self.add, (mod, arg, exec_flags, True))) except RuntimeError: pass def add(self, cmd, args, exec_flags, enqueued = False): mod = self.loader.modules[cmd] proc = None if "single" in mod.flags: proc = self.processusManager.singleCreate(mod, None, exec_flags) else: proc = self.processusManager.create(mod, None, exec_flags) if not "thread" in exec_flags: try : if "gui" in proc.mod.flags and not "console" in proc.mod.flags: print "This script is gui only" self.processusManager.remove(proc) proc.event.set() return proc except AttributeError: pass if enqueued: proc.launch(args) else: sched.enqueue(((proc.launch, args),) ) return proc __instance = None def __init__(self): if TaskManager.__instance is None: TaskManager.__instance = TaskManager.__TaskManager() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) def add(self, cmd, args, exec_flags, endfunc = None): return self.__instance.add(cmd, args, exec_flags, endfunc) class ScanQueue(Queue): def __init__(self): Queue.__init__(self) self.display = None self.count = 0 self.countLock = threading.Lock() self.moduleMapCount = {} def registerDisplay(self, item, progress): self.displayItem = item self.displayProgress = progress def refresh(self): self.count = 0 self.moduleMapCount.clear() def task_done_scan(self, root, module): self.countLock.acquire() self.count += 1 try: self.moduleMapCount[module] += 1 except KeyError: self.moduleMapCount[module] = 1 self.countLock.release() self.displayProgress(root, self.count, module, self.moduleMapCount[module]) self.task_done() def scanJoin(self, root, modulesToApply = None): modMap = {} modCount = 0 jobs = [] while not self.empty(): task = self.get() if modulesToApply != None: if not task[1][0] in modulesToApply: self.task_done() continue try : modMap[task[1][0]] += 1 except KeyError: modMap[task[1][0]] = 1 job2 = (self.task_done_scan, (root, task[1][0],)) job = (task, job2) jobs.append(job) modCount += 1 if modCount: self.displayItem(root, modCount, modMap) for job in jobs: sched.enqueue(job) self.join() self.refresh() class ProcessingQueue(ScanQueue): def __init__(self): ScanQueue.__init__(self) self.total = 0 self.percent = 0 def refresh(self): ScanQueue.refresh(self) self.total = 0 self.percent = 0 def task_done_scan(self, root): self.countLock.acquire() self.count += 1 newpercent = int(self.count * (100.00/self.total)) if newpercent > self.percent: self.percent = newpercent newpercent = True else: newpercent = False self.countLock.release() if newpercent : self.displayProgress(root, self.count) self.task_done() def scanJoin(self, root): total = self.qsize() self.displayItem(root, total) self.total = total while not self.empty(): task = self.get() job2 = (self.task_done_scan, (root,)) jobs = (task, job2) sched.enqueue(jobs) self.join() self.refresh() class PostProcessDisplay(): def __init__(self, verbose = True): self.state = True self.verbose = verbose self.init() def init(self): self.processingRoot = {} self.processusRoot = {} self.processusModules = {} self.analyseRoot = {} self.analyseModules = {} def output(self, string): if self.verbose: print string def info(self, root): self.output(root.absolute()) def updateState(self, state): self.state = state self.init() def ask(self, messageName, message): self.output(messageName + " " + message) def askWait(self, messageName, message): self.output(messageName + " " + message) return True def processingItem(self, root, count): self.processingRoot[root] = count def processingProgress(self, root, number): self.output(root.absolute() + " " + str(number) + " / " + str(self.processingRoot[root])) def processusItem(self, root, moduleCount, modMap): self.processusRoot[root] = moduleCount self.processusModules[root] = {} for modname, count in modMap.iteritems(): self.processusModules[root][modname] = count def processusProgress(self, root, count, module, moduleCount): self.output(root.absolute() + " " + str(count) + " / " + str(self.processusRoot[root])) self.output(root.absolute() + ":" + module + " " + str(moduleCount) + " / " + str(self.processusModules[root][module])) def analyseItem(self, root, moduleCount, modMap): self.analyseRoot[root] = moduleCount self.analyseModules[root] = {} for modname, count in modMap.iteritems(): self.analyseModules[root][modname] = count def analyseProgress(self, root, count, module, moduleCount): self.output(root.absolute() + " " + str(count) + " / " + str(self.analyseRoot[root])) self.output(root.absolute() + ":" + str(module) + " " + str(moduleCount) + " / " + str(self.analyseModules[root][module])) class PostProcessScheduler(): class __PostProcessScheduler(): def __init__(self): self.taskManager = TaskManager() self.registerQueue = Queue() self.processingQueue = ProcessingQueue() self.processusQueue = ScanQueue() self.analyseQueue = ScanQueue() self.display = PostProcessDisplay() self.displayState = self.display self.processingQueue.registerDisplay(self.display.processingItem, self.display.processingProgress) self.processusQueue.registerDisplay(self.display.processusItem, self.display.processusProgress) self.analyseQueue.registerDisplay(self.display.analyseItem, self.display.analyseProgress) self.fullAuto = True def fullAutoMode(self, mode): self.fullAuto = mode def getDisplay(self): return self.display def displayRoot(self, root): if self.display: self.display.info(root) def registerState(self, func): self.displayState = func def registerDisplay(self, func): self.display = func def enqueueRegister(self, root): if self.firstRoot and root.absolute().find(self.firstRoot.absolute()) != 0: self.displayState.ask('Alert', 'Post processing is currently running ! To process ' + str(root.absolute()) + ' you can right-click it and choose scan, once current processing is finished.') else: self.registerQueue.put(root) def enqueueProcessing(self, work): self.processingQueue.put(work) def enqueueProcessus(self, work): self.processusQueue.put(work) def enqueueAnalyse(self, work): self.analyseQueue.put(work) def scanProcessus(self, root): if root.fsobj(): #logical files don't have fsobj ... flags = self.taskManager.ppModules.flag(root.fsobj().name) else: flags = [] if not 'noscan' in flags: modulesToApply = None if (not self.fullAuto) and self.display: if not self.displayState.askWait('Scanner', 'Do you want to scan ' + str(root.absolute())): return self.displayState.updateState(True) self.displayRoot(root) self.taskManager.postProcessWalk(root) self.processingQueue.scanJoin(root) if (not self.fullAuto) and self.display: h = {} for n in self.processusQueue.queue: try: h[n[1][0]] += 1 except KeyError: h[n[1][0]] = 1 modulesToApply = self.displayState.askModulesWait('Apply module', 'Please select modules to apply', h) self.processusQueue.scanJoin(root, modulesToApply) def scanAnalyse(self, root, firstRoot): if (not self.fullAuto) and self.display: if not self.displayState.askWait('Scanner', 'Do you want to launch analyse on ' + str(firstRoot.absolute())): return self.taskManager.postProcessAnalyse(firstRoot) self.analyseQueue.scanJoin(root) def launch(self): self.firstRoot = None while True: root = self.registerQueue.get() if self.firstRoot == None: self.firstRoot = root self.scanProcessus(root) if self.registerQueue.empty(): self.scanAnalyse(root, self.firstRoot) self.displayState.updateState(False) self.taskManager.clearPostProcess() self.firstRoot = None __instance = None def __init__(self): if PostProcessScheduler.__instance is None: PostProcessScheduler.__instance = PostProcessScheduler.__PostProcessScheduler() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) ppsched = PostProcessScheduler() thread = threading.Thread(target = ppsched.launch, name = "TaskManager") thread.setDaemon(True) thread.start() dff-1.3.0+dfsg.1/dff/api/tree/000077500000000000000000000000001217176075400156115ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/tree/CMakeLists.txt000066400000000000000000000012401217176075400203460ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin dff_cpp_api(tree CPP_FILES TwoThreeTree.cpp TwoThreeNode.cpp SWIG_FILE libtree.i EXTRA_FILES __init__.py ) dff-1.3.0+dfsg.1/dff/api/tree/TwoThreeNode.cpp000066400000000000000000000056251217176075400206740ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Romain Bertholon */ #include "TwoThreeNode.hpp" TwoThreeNode::TwoThreeNode(uint32_t val, TwoThreeNode * node) { this->__lval = val; this->__twonode = true; this->__parent = node; this->__lchild = NULL; this->__mchild = NULL; this->__rchild = NULL; this->__rval = 0; } TwoThreeNode::TwoThreeNode(uint32_t lval, uint32_t rval, TwoThreeNode * node) { if (lval > rval) { this->__rval = lval; this->__lval = rval; } else { this->__lval = lval; this->__rval = rval; } this->__twonode = false; this->__parent = node; this->__lchild = NULL; this->__mchild = NULL; this->__rchild = NULL; } TwoThreeNode::~TwoThreeNode() { } void TwoThreeNode::toThreeNode() { this->__twonode = false; } void TwoThreeNode::setLeftChild(class TwoThreeNode* lchild) { this->__lchild = lchild; if (this->__lchild != NULL) this->__lchild->setParent(this); } void TwoThreeNode::setMiddleChild(class TwoThreeNode* mchild) { this->__mchild = mchild; if (this->__mchild != NULL) this->__mchild->setParent(this); } void TwoThreeNode::setRightChild(class TwoThreeNode* rchild) { this->__rchild = rchild; if (this->__rchild != NULL) this->__rchild->setParent(this); } TwoThreeNode* TwoThreeNode::leftChild() { return this->__lchild; } TwoThreeNode* TwoThreeNode::middleChild() { return this->__mchild; } TwoThreeNode* TwoThreeNode::rightChild() { return this->__rchild; } void TwoThreeNode::setLeftVal(uint32_t lval) { this->__lval = lval; } void TwoThreeNode::setRightVal(uint32_t rval) { this->__rval = rval; } uint32_t TwoThreeNode::leftVal() { return this->__lval; } uint32_t TwoThreeNode::rightVal() { return this->__rval; } void TwoThreeNode::toThreeNode(uint32_t val) { if (val < this->__lval) { this->__rval = this->__lval; this->__lval = val; } else this->__rval = val; this->__twonode = false; } bool TwoThreeNode::isTwoNode() { return this->__twonode; } void TwoThreeNode::setNodeType(bool node_type) { this->__twonode = node_type; } void TwoThreeNode::setParent(class TwoThreeNode* parent) { this->__parent = parent; } TwoThreeNode* TwoThreeNode::parent() { return this->__parent; } bool TwoThreeNode::isLeaf() { return ((this->__lchild == NULL) && (this->__rchild == NULL) && (this->__mchild == NULL)); } dff-1.3.0+dfsg.1/dff/api/tree/TwoThreeNode.hpp000066400000000000000000000036421217176075400206760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Romain Bertholon */ #ifndef __TWOTHREENODE_HPP__ #define __TWOTHREENODE_HPP__ #define TWO_NODE (true) #define THREE_NODE (false) #include "export.hpp" #include #if (defined(WIN64) || defined(WIN32)) #if _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #else #include #endif #include class TwoThreeNode { public: TwoThreeNode(uint32_t val, TwoThreeNode *); TwoThreeNode(uint32_t lval, uint32_t rval, TwoThreeNode * node); ~TwoThreeNode(); void setLeftChild(class TwoThreeNode* lchild); void setMiddleChild(class TwoThreeNode* mchild); void setRightChild(class TwoThreeNode* rchild); class TwoThreeNode* leftChild(); class TwoThreeNode* middleChild(); class TwoThreeNode* rightChild(); void setLeftVal(uint32_t lval); void setRightVal(uint32_t rval); uint32_t val(); uint32_t leftVal(); uint32_t rightVal(); bool isTwoNode(); void setNodeType(bool node_type); void toThreeNode(); void toThreeNode(uint32_t val); void setParent(class TwoThreeNode* parent); class TwoThreeNode* parent(); bool isLeaf(); private: class TwoThreeNode* __parent; class TwoThreeNode* __lchild; class TwoThreeNode* __mchild; class TwoThreeNode* __rchild; uint32_t __lval; uint32_t __rval; bool __twonode; }; #endif dff-1.3.0+dfsg.1/dff/api/tree/TwoThreeTree.cpp000066400000000000000000000153521217176075400207040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Romain Bertholon */ #include #include #include "TwoThreeTree.hpp" #ifdef TWO_THREE_TREE_DEBUG #if (!defined(WIN64) && !defined(WIN32)) #define DEBUG(str, args...) printf(str, ##args); #else #define DEBUG(str, ...) printf(str, __VA_ARGS__); #endif #define DEBUG_START(val) std::cout << "STATE BEFORE INSERTING " << val << std::endl; \ this->dump() #define DEBUG_END(val) std::cout << "STATE AFTER INSERTING " << val << std::endl; \ this->dump(); \ std::cout << std::endl #else #if (!defined(WIN64) && !defined(WIN32)) #define DEBUG(str, args...) #else #define DEBUG(str, ...) #endif #define DEBUG_START(val) #define DEBUG_END(val) #endif TwoThreeTree::TwoThreeTree() { } TwoThreeTree::~TwoThreeTree() { } uint32_t TwoThreeTree::__bsearch(uint64_t val, uint64_t lbound, uint64_t rbound, bool* found) { uint32_t mbound; if (rbound < lbound) return rbound; mbound = (rbound + lbound) / 2; if (val < this->__elems[mbound]->lhs) { if (mbound > 0) return this->__bsearch(val, lbound, mbound - 1, found); else return 0; } else if (val > this->__elems[mbound]->rhs) return this->__bsearch(val, mbound + 1, rbound, found); else { *found = true; return mbound; } } void TwoThreeTree::clear() { } TwoThreeTree::elem* TwoThreeTree::__allocElem(uint64_t lhs, uint64_t rhs) { elem* e; e = new elem; e->lhs = lhs; e->rhs = rhs; return e; } void TwoThreeTree::__insert(uint64_t val, uint32_t lidx, uint32_t ridx) { elem* lbound; elem* rbound; elem* e; lbound = this->__elems[lidx]; rbound = this->__elems[ridx]; DEBUG(" disambiguation to insert %llu between (%lu - %lu) and (%lu - %lu)\n", val, lbound->lhs, lbound->rhs, rbound->lhs, rbound->rhs) if (lbound->rhs + 1 < val) { DEBUG(" lbound->rhs + 1 < val\n"); if (val == rbound->lhs - 1) { DEBUG(" val == rbound->lhs - 1\n"); rbound->lhs = val; } else { DEBUG(" alloc + insert after ridx"); e = this->__allocElem(val, val); this->__elems.insert(this->__elems.begin()+ridx, e); } } else if (val == rbound->lhs - 1) { DEBUG(" val == rbound->lhs -1 update lbound->rhs to rbound->rhs and remove rbound\n"); lbound->rhs = rbound->rhs; this->__elems.erase(this->__elems.begin() + ridx); delete rbound; } else { DEBUG(" update lbound->rhs\n"); lbound->rhs = val; } } bool TwoThreeTree::insert(uint64_t val) { uint32_t idx; elem *e; elem *tmp; bool found; bool inserted; found = false; inserted = true; DEBUG_START(val); if (this->__elems.size() == 0) { DEBUG(" First insertion with %llu\n", val); e = this->__allocElem(val, val); this->__elems.push_back(e); } else if (this->__elems.size() == 1) { DEBUG(" One element exists, inserting with %llu\n", val); tmp = this->__elems[0]; // First check if val is not allocated if (val < tmp->lhs || val > tmp->rhs) { // Then test if we can merge if (val == tmp->lhs - 1) { DEBUG(" val == tmp->lhs - 1\n"); tmp->lhs = val; } else if (val == tmp->rhs + 1) { tmp->rhs = val; DEBUG(" val == tmp->rhs + 1\n"); } // otherwise where to insert val else { DEBUG(" inserting val "); e = this->__allocElem(val, val); if (val < tmp->lhs) { this->__elems.insert(this->__elems.begin(), e); DEBUG("before\n"); } else { this->__elems.push_back(e); DEBUG("after\n"); } } } else { DEBUG(" value already existed"); inserted = false; } } else { // More than one elem, binary search to find where to insert or if already existing idx = this->__bsearch(val, 0, this->__elems.size() - 1, &found); if (!found) { if (idx == 0) { DEBUG(" size > 1 and idx == 0\n"); if (val == this->__elems[idx]->lhs - 1) { DEBUG(" val = lhs - 1\n"); this->__elems[idx]->lhs = val; } else if (val < this->__elems[idx]->lhs) { DEBUG(" val < lhs (inserting front)\n"); e = this->__allocElem(val, val); this->__elems.insert(this->__elems.begin(), e); } else { DEBUG(" need insertion choice betwen indexes: %lu and %lu ", idx, idx+1); this->__insert(val, idx, idx+1); } } else if (idx == (this->__elems.size() - 1)) { DEBUG(" size > 1 and idx = size - 1"); if (val == (this->__elems[idx]->rhs + 1)) { DEBUG(" val == rhs + 1"); this->__elems[idx]->rhs = val; } else if (val > this->__elems[idx]->rhs) { DEBUG(" val > rhs (inserting back)"); e = this->__allocElem(val, val); this->__elems.push_back(e); } else { DEBUG(" need insertion choice between indexes: %lu and %lu", idx-1, idx); this->__insert(val, idx-1, idx); } } else { DEBUG(" size > 1 inserting between"); if (val < this->__elems[idx]->lhs) { DEBUG(" val < this->__elems[idx]->lhs -- %llu < %llu", val, this->__elems[idx]->lhs); this->__insert(val, idx-1, idx); } else { DEBUG(" val > this->__elems[idx]->lhs -- %llu > %llu", val, this->__elems[idx]->lhs); this->__insert(val, idx, idx+1); } } } else inserted = false; } DEBUG_END(val); return inserted; } bool TwoThreeTree::find(uint64_t val) { return this->exists(val); } bool TwoThreeTree::exists(uint64_t val) { uint32_t idx; bool found; found = false; if (this->__elems.size() == 0) found = false; else if (this->__elems.size() == 1) { if (val >= this->__elems[0]->lhs && val <= this->__elems[0]->rhs) found = true; } else idx = this->__bsearch(val, 0, this->__elems.size() - 1, &found); return found; } bool TwoThreeTree::remove(uint64_t val) { return false; } bool TwoThreeTree::empty() { return this->__elems.size() == 0; } void TwoThreeTree::dump() { std::vector::iterator it; for (it = this->__elems.begin(); it != this->__elems.end(); ++it) std::cout << (*it)->lhs << "-" << (*it)->rhs << ", "; std::cout << std::endl; } dff-1.3.0+dfsg.1/dff/api/tree/TwoThreeTree.hpp000066400000000000000000000031511217176075400207030ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Romain Bertholon */ #ifndef __TWOTHREETREE_HPP__ #define __TWOTHREETREE_HPP__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "export.hpp" //XXX #include #include #include class TwoThreeTree { public: typedef struct { uint64_t lhs; uint64_t rhs; } elem; EXPORT TwoThreeTree(); EXPORT ~TwoThreeTree(); EXPORT bool insert(uint64_t val); EXPORT bool exists(uint64_t val); EXPORT bool find(uint64_t val); EXPORT bool remove(uint64_t val); EXPORT void dump(); EXPORT void clear(); EXPORT bool empty(); private: std::vector __elems; uint32_t __bsearch(uint64_t offset, uint64_t lbound, uint64_t rbound, bool* found); elem* __allocElem(uint64_t lhs, uint64_t rhs); void __firstIdxInsert(uint64_t val); void __betweenIdxInsert(uint64_t val, uint32_t idx); void __lastIdxInsert(uint64_t val); void __insert(uint64_t val, uint32_t lidx, uint32_t ridx); }; #endif dff-1.3.0+dfsg.1/dff/api/tree/__init__.py000066400000000000000000000011461217176075400177240ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __version__ = "${API_TREE_VERSION}" __all__ = ["libtree"] dff-1.3.0+dfsg.1/dff/api/tree/libtree.i000066400000000000000000000017431217176075400174160ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "pyrun.swg" %module(package="dff.api.tree") libtree %include "std_string.i" #ifndef WIN32 %include "stdint.i" #elif _MSC_VER >= 1600 %include "stdint.i" #else %include "wstdint.i" #endif %include "std_list.i" %include "std_map.i" %include "windows.i" %include "std_except.i" %{ #include "../include/export.hpp" #include "TwoThreeTree.hpp" %} %include "../include/export.hpp" %include "TwoThreeTree.hpp" dff-1.3.0+dfsg.1/dff/api/types/000077500000000000000000000000001217176075400160165ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/types/CMakeLists.txt000066400000000000000000000017741217176075400205670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob set(swig_flags ${CMAKE_SWIG_FLAGS} -threads -fvirtual -fastdispatch) IF (WIN32) set(swig_flags ${swig_flags} -DWIN32) ENDIF(WIN32) dff_cpp_api(types CPP_FILES constant.cpp argument.cpp config.cpp path.cpp vtime.cpp variant.cpp confmanager.cpp threading.cpp ../vfs/rc.cpp SWIG_FILE libtypes.i DEFINITIONS -D__STDC_LIMIT_MACROS SWIG_FLAGS ${swig_flags} LINK_LIBRARIES exceptions EXTRA_FILES __init__.py ) dff-1.3.0+dfsg.1/dff/api/types/__init__.py000066400000000000000000000011561217176075400201320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __all__ = ["libtypes"] dff-1.3.0+dfsg.1/dff/api/types/argument.cpp000066400000000000000000000055651217176075400203570ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "argument.hpp" Argument::Argument(std::string name, uint16_t flags, std::string description) { this->__name = name; this->__flags = flags; this->__description = description; this->__paramslocked = false; if ((flags & 0x0300) == Argument::List) this->__minparams = 1; else this->__minparams = -1; this->__maxparams = -1; this->setParametersType(Parameter::Editable); } Argument::~Argument() { std::list::iterator ait; this->__parameters.clear(); for (ait = this->__subarguments.begin(); ait != this->__subarguments.end(); ait++) if (*ait != NULL) delete *ait; this->__subarguments.clear(); } std::string Argument::name() { return this->__name; } uint16_t Argument::flags() { return this->__flags; } std::string Argument::description() { return this->__description; } // void Argument::setType(uint16_t type) // { // this->__flags = (this->__flags&0xFF00)|(type&0x00FF); // } uint16_t Argument::type() { return (this->__flags & TYPEMASK); } // void Argument::setInputType(uint16_t itype) // { // this->__flags = (this->__flags&0xFCFF)|(itype&0x0300); // } uint16_t Argument::inputType() { return (this->__flags & 0x0300); } void Argument::setParametersType(uint16_t ptype) { this->__flags = (this->__flags&0x0FFF)|(ptype&0xF000); } uint16_t Argument::parametersType() { return (this->__flags & 0xF000); } // void Argument::setRequirementType(uint16_t ntype) // { // this->__flags = (this->__flags&0xF3FF)|(ntype&0x0C00); // } uint16_t Argument::requirementType() { return (this->__flags & 0x0c00); } void Argument::addSubArgument(Argument* arg) { this->__subarguments.push_back(arg); } void Argument::addParameters(std::list< Variant_p > params, uint16_t type, int32_t min, int32_t max) { if (!this->__paramslocked) { this->__minparams = min; this->__maxparams = max; this->__paramslocked = true; this->setParametersType(type); this->__parameters = params; } else return; } std::list< Variant_p > Argument::parameters() { return this->__parameters; } uint32_t Argument::parametersCount() { return this->__parameters.size(); } int32_t Argument::minimumParameters() { return this->__minparams; } int32_t Argument::maximumParameters() { return this->__maxparams; } dff-1.3.0+dfsg.1/dff/api/types/arguments.cpp000066400000000000000000000017641217176075400205370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. * Frederic B. */ #include "arguments.hpp" Arguments::Arguments(std::string origin) { this->__origin = origin; } Arguments::~Arguments() { } bool Arguments::add(std::string name, Variant* value) { } Variant* Arguments::valueFromKey(std::string name) { } std::map Arguments::items() { } std::list Arguments::keys() { } std::list Arguments::values() { } dff-1.3.0+dfsg.1/dff/api/types/config.cpp000066400000000000000000000135051217176075400177730ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. * Frederic B. */ #include "config.hpp" Config::Config(std::string origin, std::string description) { this->__origin = origin; this->__description = description; } Config::~Config() { std::map::iterator ait; std::map::iterator cit; for (ait = this->__arguments.begin(); ait != this->__arguments.end(); ait++) if (ait->second != NULL) delete ait->second; this->__arguments.clear(); for (cit = this->__constants.begin(); cit != this->__constants.end(); cit++) if (cit->second != NULL) delete cit->second; this->__constants.clear(); } std::string Config::origin() { return this->__origin; } std::string Config::description() { return this->__description; } void Config::addArgument(Argument* arg) throw (std::string) { std::string argname; if (arg != NULL) { argname = arg->name(); if (!(argname.empty())) { if (this->__arguments.find(argname) != this->__arguments.end()) throw (std::string("argument" + argname + " has already been added")); this->__arguments.insert(std::pair(argname, arg)); } else throw (std::string("argument name is empty")); } else throw (std::string("provided argument is NULL")); } std::list Config::arguments() { std::map::iterator it; std::list larg; for (it = this->__arguments.begin(); it != this->__arguments.end(); it++) larg.push_back(it->second); return larg; } std::list Config::argumentsName() { std::map::iterator it; std::list lname; for (it = this->__arguments.begin(); it != this->__arguments.end(); it++) lname.push_back(it->first); return lname; } Argument* Config::argumentByName(std::string argname) { std::map::iterator it; it = this->__arguments.find(argname); if (it != this->__arguments.end()) return it->second; else return NULL; } std::list Config::argumentsByName(std::list argsname) { std::list::iterator it; Argument* carg; std::list nargs; for (it = argsname.begin(); it != argsname.end(); it++) if ((carg = this->argumentByName(*it)) != NULL) nargs.push_back(carg); return nargs; } std::list Config::argumentsByFlags(uint16_t flags) { std::map::iterator mit; std::list fargs; uint16_t itype; uint16_t rtype; uint16_t type; bool match; itype = flags & 0x0300; rtype = flags & 0x0c00; type = flags & 0x00FF; for (mit = this->__arguments.begin(); mit != this->__arguments.end(); mit++) { match = true; if ((type != 0) && (mit->second->type() != type)) match = false; if ((itype != 0) && mit->second->inputType() != itype) match = false; if ((rtype != 0) && (mit->second->requirementType() != rtype)) match = false; if (match) fargs.push_back(mit->second); } return fargs; } std::list Config::argumentsByInputType(uint16_t itype) { std::map::iterator mit; std::list iargs; for (mit = this->__arguments.begin(); mit != this->__arguments.end(); mit++) if (mit->second->inputType() == itype) iargs.push_back(mit->second); return iargs; } std::list Config::argumentsByRequirementType(uint16_t rtype) { std::map::iterator mit; std::list rargs; for (mit = this->__arguments.begin(); mit != this->__arguments.end(); mit++) if (mit->second->requirementType() == rtype) rargs.push_back(mit->second); return rargs; } std::list Config::argumentsByType(uint16_t type) { std::map::iterator mit; std::list targs; for (mit = this->__arguments.begin(); mit != this->__arguments.end(); mit++) { if (mit->second->type() == type) targs.push_back(mit->second); } return targs; } void Config::addConstant(Constant* constant) throw(std::string) { std::string cname; if (constant != NULL) { cname = constant->name(); if (!(cname.empty())) { if (this->__constants.find(cname) != this->__constants.end()) throw(std::string("constant " + cname + " has already been added")); this->__constants.insert(std::pair(cname, constant)); } } else throw(std::string("provided constant is NULL")); } std::list Config::constants() { std::list lconst; std::map::iterator it; for (it = this->__constants.begin(); it != this->__constants.end(); it++) lconst.push_back(it->second); return lconst; } Constant* Config::constantByName(std::string cname) { std::map::iterator it; it = this->__constants.find(cname); if (it != this->__constants.end()) return it->second; else return NULL; } std::list Config::constantByType(uint8_t type) { std::map::iterator it; std::list lconsts; for (it = this->__constants.begin(); it != this->__constants.end(); it++) if (it->second->type() == type) lconsts.push_back(it->second); return lconsts; } dff-1.3.0+dfsg.1/dff/api/types/confmanager.cpp000066400000000000000000000062061217176075400210060ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "confmanager.hpp" ConfigManager::ConfigManager() { } ConfigManager::~ConfigManager() { } ConfigManager* ConfigManager::Get() { static ConfigManager single; return &single; } void ConfigManager::unregisterConf(std::string confname) { std::map::iterator it; it = this->__configs.find(confname); if (it != this->__configs.end()) { if (it->second != NULL) delete it->second; this->__configs.erase(it); } } void ConfigManager::registerConf(class Config* conf) throw(std::string) { std::string cname; if (conf != NULL) { cname = conf->origin(); if (!cname.empty()) { if (this->__configs.find(cname) != this->__configs.end()) throw (std::string("argument" + cname + " has already been added")); this->__configs.insert(std::pair(cname, conf)); } else throw (std::string("argument name is empty")); } else throw (std::string("provided argument is NULL")); } std::list ConfigManager::configs() { std::map::iterator it; std::list lconf; for (it = this->__configs.begin(); it != this->__configs.end(); it++) lconf.push_back(it->second); return lconf; } std::list ConfigManager::configsName() { std::map::iterator it; std::list lname; for (it = this->__configs.begin(); it != this->__configs.end(); it++) lname.push_back(it->first); return lname; } class Config* ConfigManager::configByName(std::string confname) { std::map::iterator it; it = this->__configs.find(confname); if (it != this->__configs.end()) return it->second; else return NULL; } std::map ConfigManager::constantsByName(std::string constname) { std::map::iterator it; std::map mconsts; Constant* constant; for (it = this->__configs.begin(); it != this->__configs.end(); it++) if ((constant = it->second->constantByName(constname)) != NULL) mconsts.insert(std::pair(it->first, constant)); return mconsts; } std::map ConfigManager::argumentsByName(std::string argname) { std::map::iterator it; std::map margs; Argument* arg; for (it = this->__configs.begin(); it != this->__configs.end(); it++) if ((arg = it->second->argumentByName(argname)) != NULL) margs.insert(std::pair(it->first, arg)); return margs; } dff-1.3.0+dfsg.1/dff/api/types/constant.cpp000066400000000000000000000024161217176075400203560ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "constant.hpp" Constant::Constant(std::string name, uint8_t type, std::string description) { this->__name = name; this->__type = type; this->__description = description; this->__valueslocked = false; } Constant::~Constant() { this->__values.clear(); } std::string Constant::name() { return this->__name; } std::string Constant::description() { return this->__description; } uint8_t Constant::type() { return (this->__type); } void Constant::addValues(std::list< Variant_p > values) { if (!this->__valueslocked) { this->__valueslocked = true; this->__values = values; } else return; } std::list< Variant_p > Constant::values() { return this->__values; } dff-1.3.0+dfsg.1/dff/api/types/libtypes.i000066400000000000000000001641071217176075400200340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Solal J. */ #include "pyrun.swg" %module(package="dff.api.types") libtypes %feature("autodoc", 1); //1 = generate type for func proto, no work for typemap %feature("docstring"); %{ #include #include #include "export.hpp" #include "exceptions.hpp" #include "rc.hpp" #include "variant.hpp" #include "constant.hpp" #include "argument.hpp" #include "config.hpp" #include "confmanager.hpp" #include "path.hpp" #include "vtime.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif %} #ifndef WIN32 %include "stdint.i" #elif _MSC_VER >= 1600 %include "stdint.i" #else %include "wstdint.i" #endif %include "std_string.i" %include "std_list.i" %include "std_map.i" %include "windows.i" %include "std_except.i" %import "../exceptions/libexceptions.i" %inline %{ static bool std_list_Sl_RCPtr_Sl_Variant_Sg__Sg__operator_Se__Se_(std::list< Variant_p > *self,PyObject *obj); static bool std_map_Sl_std_string_Sc_RCPtr_Sl_Variant_Sg__Sg__operator_Se__Se_(std::map< std::string, Variant_p > *self,PyObject *obj); static int SWIG_AsVal_std_string(PyObject*, std::string*); %} %ignore Variant::operator==(T val); %ignore Variant::operator!=(T val); %ignore Variant::operator>(T val); %ignore Variant::operator>=(T val); %ignore Variant::operator<(T val); %ignore Variant::operator<=(T val); /* let SWIG handle reference counting for all RCObj derived classes */ %refobject RCObj "$this->addref();" %unrefobject RCObj "$this->delref();" %include "../include/rc.hpp" %include "../include/variant.hpp" %include "../include/argument.hpp" %include "../include/constant.hpp" %include "../include/export.hpp" %include "../include/config.hpp" %include "../include/path.hpp" %include "../include/vtime.hpp" %include "../include/confmanager.hpp" %extend_smart_pointer( Variant_p ); %template(RCVariant) Variant_p; namespace std { %template(MapString) map; %template(ListString) std::list; %template(ArgumentList) std::list; %template(ConfigList) std::list; %template(ConstantList) std::list; %template(VList) std::list< Variant_p >; %template(VMap) std::map; %template(MapVtime) map; %template(MapConstant) map; %template(MapArgument) map; %template(MapInt) map; }; %traits_swigtype(vtime); %fragment(SWIG_Traits_frag(vtime)); /* %typemap(in) (std::map< std::string,Variant * >::key_type const &, Variant*) */ /* { */ /* if ((SWIG_ConvertPtr($input, (void **) &$3, $3_descriptor, 0)) == -1) */ /* return NULL; */ /* $3->addref(); */ /* } */ %template(__Char) Variant::value; %template(__Int16) Variant::value; %template(__UInt16) Variant::value; %template(__Int32) Variant::value; %template(__UInt32) Variant::value; %template(__Int64) Variant::value; %template(__UInt64) Variant::value; %template(__Bool) Variant::value; %template(__CArray) Variant::value; %template(__Node) Variant::value; %template(__Path) Variant::value; %template(__VTime) Variant::value; %template(__VLink) Variant::value; %template(__String) Variant::value; %template(__VList) Variant::value< std::list< Variant_p > >; %template(__VMap) Variant::value< std::map >; %extend Constant { void addValues(PyObject* obj) throw (std::string) { std::string err; Py_ssize_t lsize; Py_ssize_t i; PyObject* item; std::list< Variant_p > vlist; Variant* v; uint8_t itype; SWIG_PYTHON_THREAD_BEGIN_BLOCK; itype = self->type(); if (PyList_Check(obj)) { if ((lsize = PyList_Size(obj)) == 0) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + self->name() + " > provided list of values is empty")); } else { i = 0; while ((i != lsize) && err.empty()) { item = PyList_GetItem(obj, i); if ((v = new_Variant__SWIG_20(item, itype)) == NULL) err = "Constant < " + self->name() + " >\n provided list of values must be of type < " + typeId::Get()->typeToName(itype) + " >"; else vlist.push_back( Variant_p(v) ); i++; } } } else err = "Constant < " + self->name() + " > values must be a list"; if (err.empty()) self->addValues(vlist); else { vlist.clear(); SWIG_PYTHON_THREAD_END_BLOCK; throw(err); } SWIG_PYTHON_THREAD_END_BLOCK; } }; %extend Argument { PyObject* validateParams(PyObject* obj, uint16_t* ptype, int32_t* min, int32_t* max) throw(std::string) { PyObject* ptype_obj = NULL; PyObject* min_obj = NULL; PyObject* max_obj = NULL; PyObject* predef_obj = NULL; Py_ssize_t lsize; int ecode = 0; SWIG_PYTHON_THREAD_BEGIN_BLOCK; if ((ptype_obj = PyDict_GetItemString(obj, "type")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("No field < type > defined for provided parameters")); } ecode = SWIG_AsVal_unsigned_SS_short(ptype_obj, ptype); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < type >")); } if ((min_obj = PyDict_GetItemString(obj, "minimum")) != NULL) { if (self->inputType() != Argument::List) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("minimum must not be defined when argument does not need list of parameters")); } if (PyInt_Check(min_obj)) { ecode = SWIG_AsVal_int(min_obj, min); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < minimum >")); } if (*min < 0) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("minimum must be >= 0")); } } else { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < minimum >")); } } else *min = -1; if ((max_obj = PyDict_GetItemString(obj, "maximum")) != NULL) { if (self->inputType() != Argument::List) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("maximum must not be defined when argument does not need list of parameters")); } if (PyInt_Check(max_obj)) { ecode = SWIG_AsVal_int(max_obj, max); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < maximum >")); } if (*max <= 0) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("maximum must be >= 1")); } if (*min >= *max) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("maximum must be greater than minimum")); } } else { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < maximum >")); } } else *max = -1; predef_obj = PyDict_GetItemString(obj, "predefined"); if (predef_obj == NULL) { if (*ptype == Parameter::NotEditable) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("not editable parameters must have < predefined > field")); } } else { if (!PyList_Check(predef_obj)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("< predefined > field of parameters must be a list")); } if (*ptype == Parameter::NotEditable) { lsize = PyList_Size(predef_obj); if (*min > lsize) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("minimum cannot be greater than length of predefined not editable parameters")); } else if (*min == -1) *min = 1; if (*max > lsize) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("maximum cannot be greater than length of predefined not editable parameters")); } else if (*max == -1) *max = lsize; } else if (*min == -1) *min = 1; } SWIG_PYTHON_THREAD_END_BLOCK; return predef_obj; } void addParameters(PyObject* obj) throw(std::string) { PyObject* predef_obj; uint16_t ptype; int32_t min; int32_t max; uint16_t itype; PyObject* item; Py_ssize_t lsize; Py_ssize_t i; Variant* v; std::string err; std::list< Variant_p > vlist; SWIG_PYTHON_THREAD_BEGIN_BLOCK; try { predef_obj = Argument_validateParams(self, obj, &ptype, &min, &max); if (predef_obj != NULL) { itype = self->type(); lsize = PyList_Size(predef_obj); i = 0; while ((i != lsize) && err.empty()) { item = PyList_GetItem(predef_obj, i); //Maybe change this call with _wrap_new_Variant to not depend on swig overload method generation (at the moment it s SWIG_18 but could change if new Variant ctor implemented...). Then use Swig_ConvertPtr to get Variant from the returned PyObject. if ((v = new_Variant__SWIG_20(item, itype)) == NULL) err = "Argument < " + self->name() + " >\n predefined parameters must be of type < " + typeId::Get()->typeToName(self->type()) + " >"; else vlist.push_back( Variant_p(v) ); i++; } } } catch (std::string e) { err = "Argument < " + self->name() + " >\n" + e; } if (!err.empty()) { vlist.erase(vlist.begin(), vlist.end()); SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string(err)); } else { self->addParameters(vlist, ptype, min, max); } SWIG_PYTHON_THREAD_END_BLOCK; } }; %extend Config { bool matchNotEditable(std::list< Variant_p > params, PyObject* obj) { std::list< Variant_p >::iterator it; bool found; SWIG_PYTHON_THREAD_BEGIN_BLOCK; found = false; for (it = params.begin(); it != params.end(); it++) { if (Variant_operator_Se__Se___SWIG_1(it->get(), obj)) { found = true; break; } } SWIG_PYTHON_THREAD_END_BLOCK; return found; } Variant* generateSingleInput(PyObject* obj, Argument* arg) throw (std::string) { Variant* v = NULL; SWIG_PYTHON_THREAD_BEGIN_BLOCK; if ((arg != NULL) && (obj != NULL)) { if ((arg->parametersType() == Parameter::NotEditable) && (!Config_matchNotEditable(self, arg->parameters(), obj))) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + arg->name() + " >\npredefined parameters are immutable and those provided do not correspond to available ones")); } if ((v = new_Variant__SWIG_20(obj, arg->type())) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + arg->name() + " >\nparameter is not compatible")); } if ((v->type() == typeId::String) && (v->toString().empty())) { delete v; SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + arg->name() + " >\nprovided string cannot be empty")); } } else { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("values provided to generateSingleInput are not valid")); } SWIG_PYTHON_THREAD_END_BLOCK; return v; } Variant* generateListInput(PyObject* obj, Argument* arg) throw (std::string) { std::list< Variant_p > vlist; Variant* v = NULL; Py_ssize_t lsize; Py_ssize_t i; PyObject* item; std::string err = ""; int32_t min; int32_t max; SWIG_PYTHON_THREAD_BEGIN_BLOCK; if ((arg != NULL) && (obj != NULL)) { if (PyList_Check(obj)) { i = 0; min = arg->minimumParameters(); max = arg->maximumParameters(); lsize = PyList_Size(obj); if (lsize == 0) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + arg->name() + " >\nlist of parameters is empty")); } if ((min != -1) && (lsize < min)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + arg->name() + " >\nnot enough parameters provided")); } if ((max != -1) && (lsize > max)) { SWIG_PYTHON_THREAD_END_BLOCK; throw (std::string("Argument < " + arg->name() + " >\ntoo many parameters provided")); } try { while ((i != lsize) && err.empty()) { item = PyList_GetItem(obj, i); v = Config_generateSingleInput(self, item, arg); vlist.push_back( Variant_p(v) ); i++; } } catch(std::string e) { err = e; } } else { try { v = Config_generateSingleInput(self, obj, arg); vlist.push_back( Variant_p(v) ); } catch(std::string e) { err = e; } } } else err = "values provided to generateListInput are not valid"; if (!err.empty()) { vlist.clear(); SWIG_PYTHON_THREAD_END_BLOCK; throw(err); } v = new Variant(vlist); SWIG_PYTHON_THREAD_END_BLOCK; return v; } //XXX std::map generate(PyObject* obj) throw (std::string) { std::map res; std::list args; std::list::iterator argit; PyObject* itemval; std::string argname; uint16_t itype; uint16_t rtype; int ecode; std::string err; SWIG_PYTHON_THREAD_BEGIN_BLOCK; ecode = PyDict_Check(obj); if (ecode) { args = self->arguments(); argit = args.begin(); while ((argit != args.end()) && err.empty()) { argname = (*argit)->name(); itype = (*argit)->inputType(); rtype = (*argit)->requirementType(); itemval = PyDict_GetItemString(obj, argname.c_str()); if (itemval == NULL) { if (rtype == Argument::Required) err = "Argument < " + argname + " >\n this argument is required"; } else { //std::cout << "current argument: " << argname << " argument type " << (*argit)->type() << " -- provided parameter type " << obj->ob_type->tp_name << std::endl; try { Variant * v = NULL; if (itype == Argument::Empty) v = new_Variant__SWIG_20(itemval, typeId::Bool); else if (itype == Argument::Single) v = Config_generateSingleInput(self, itemval, *argit); else if (itype == Argument::List) v = Config_generateListInput(self, itemval, *argit); if (v != NULL) res[argname] = Variant_p(v); else err = "Argument < " + argname + " >\n" + "parameter provided is not valid (wrong type)"; } catch (std::string e) { err = "Argument < " + argname + " >\n" + "parameter provided is not valid\ndetails:\n" + e; } } argit++; } } else err = "generating configuration failed because provided value is not of type dict"; if (!err.empty()) { res.clear(); throw(err); } SWIG_PYTHON_THREAD_END_BLOCK; return res; } void addConstant(PyObject* obj) throw(std::string) { uint32_t pydictsize; Constant* constant; PyObject* name_obj = 0; PyObject* type_obj = 0; PyObject* values_obj = 0; PyObject* descr_obj = 0; int ecode = 0; std::string name; uint8_t type; std::string description; SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (PyDict_Check(obj)) { pydictsize = PyDict_Size(obj); if ((name_obj = PyDict_GetItemString(obj, "name")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("No field < name > defined for current constant")); } ecode = SWIG_AsVal_std_string(name_obj, &name); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < name >")); } if (self->constantByName(name) != NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + name + " > already added")); } if ((type_obj = PyDict_GetItemString(obj, "type")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + name + ">\nfield < type > must be defined")); } ecode = SWIG_AsVal_unsigned_SS_char(type_obj, &type); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + name + ">\ninvalid type for field < type >")); } if ((descr_obj = PyDict_GetItemString(obj, "description")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + name + " >\nfield < description > must be defined")); } ecode = SWIG_AsVal_std_string(descr_obj, &description); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + name + " >\ninvalid type for field < description >")); } if ((values_obj = PyDict_GetItemString(obj, "values")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Constant < " + name + ">\nfield < values > must be defined")); } try { constant = new Constant(name, type, description); Constant_addValues__SWIG_1(constant, values_obj); self->addConstant(constant); } catch (std::string e) { delete constant; SWIG_PYTHON_THREAD_END_BLOCK; throw("Constant < " + name + " >\n error while processing argument\ndetails:\n" + e); } } SWIG_PYTHON_THREAD_END_BLOCK; } void addArgument(PyObject* obj) throw(std::string) { uint32_t pydictsize; Argument* arg; PyObject* name_obj = 0; PyObject* input_obj = 0; PyObject* param_obj = 0; PyObject* descr_obj = 0; uint16_t input; std::string name; std::string description; std::list names; int ecode = 0; SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (PyDict_Check(obj)) { pydictsize = PyDict_Size(obj); if ((name_obj = PyDict_GetItemString(obj, "name")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("No field < name > defined for current argument")); } ecode = SWIG_AsVal_std_string(name_obj, &name); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("invalid type for field < name >")); } if (self->argumentByName(name) != NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + " > already added")); } if ((input_obj = PyDict_GetItemString(obj, "input")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + ">\nfield < input > must be defined")); } ecode = SWIG_AsVal_unsigned_SS_short(input_obj, &input); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + ">\ninvalid type for field < input >")); } if ((descr_obj = PyDict_GetItemString(obj, "description")) == NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + " >\nfield < description > must be defined")); } ecode = SWIG_AsVal_std_string(descr_obj, &description); if (!SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + " >\ninvalid type for field < description >")); } param_obj = PyDict_GetItemString(obj, "parameters"); if (input == Argument::Empty) { if (param_obj != NULL) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + ">\nfield < predefined > forbidden")); } else { arg = new Argument(name, input, description); self->addArgument(arg); } } else if (( ((input & 0x0300) == Argument::List) || ((input & 0x0300) == Argument::Single)) && (((input & 0x0c00) == Argument::Optional) || ((input & 0x0c00) == Argument::Required))) { arg = new Argument(name, input, description); if (param_obj != NULL) { if (!PyDict_Check(param_obj)) { delete arg; SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + ">\nparameters field is not of type dict")); } else { try { Argument_addParameters__SWIG_3(arg, param_obj); self->addArgument(arg); } catch (std::string e) { delete arg; SWIG_PYTHON_THREAD_END_BLOCK; throw("Argument < " + name + " >\n error while processing argument\ndetails:\n" + e); } } } else self->addArgument(arg); } else { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Argument < " + name + ">\nflags provided to field < input > are not valid")); } } SWIG_PYTHON_THREAD_END_BLOCK; } }; %extend std::map { /* ~map() */ /* { */ /* // std::map::iterator mit; */ /* //for (mit = self->begin(); mit != self->end(); mit++) */ /* //if (mit->second != NULL) */ /* //delete mit->second; */ /* delete self; */ /* } */ char* __str__() { std::string str; size_t size; size_t counter; std::map::iterator mit; char* cstr; size = self->size(); counter = 0; str = "{"; for (mit = self->begin(); mit != self->end(); mit++) { counter++; str += "'" + mit->first + "': "; if (mit->second->type() == typeId::String || mit->second->type() == typeId::CArray || mit->second->type() == typeId::Path) str += "'" + mit->second->toString() + "'"; else str += mit->second->toString(); if (counter != size) str += ", "; } str += "}"; cstr = NULL; if ((cstr = (char*)malloc(sizeof(char) * (str.size()+1))) != NULL) strncpy (cstr, str.c_str(), str.size()+1); return cstr; } void __setitem__(std::map< std::string,RCPtr< Variant > >::key_type const &key, std::map &vmap) { Variant* vptr; if ((vptr = new Variant(vmap)) != NULL) self->insert(std::pair >(key, Variant_p(vptr))); return; } void __setitem__(std::map< std::string,RCPtr< Variant > >::key_type const &key, std::list< Variant_p > &vlist) { Variant* vptr; if ((vptr = new Variant(vlist)) != NULL) self->insert(std::pair >(key, Variant_p(vptr))); return; } bool operator==(PyObject* obj) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (PyDict_Check(obj)) { //printf("std::map::operator==(PyObject* obj) ---> obj == PyDict\n"); if (self->size() == (unsigned int)PyDict_Size(obj)) { std::map::const_iterator it; PyObject *value; for (it = self->begin(); it != self->end(); it++) { if ((value = PyDict_GetItemString(obj, it->first.c_str())) != NULL) { if (!Variant_operator_Se__Se___SWIG_1(it->second.get(), value)) { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } SWIG_PYTHON_THREAD_END_BLOCK; return true; } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (strncmp("VMap", obj->ob_type->tp_name, 5) == 0) { //printf("std::map::operator==(PyObject* obj) ---> obj == VMap\n"); void* argp1 = 0; std::map< std::string, Variant_p > *arg1 = (std::map< std::string, Variant_p > *) 0 ; int res1 = SWIG_ConvertPtr(obj, &argp1, $descriptor(std::map< std::stirng, Variant_p >), 0 | 0); if (SWIG_IsOK(res1)) { arg1 = reinterpret_cast< std::map * >(argp1); if (arg1->size() != self->size()) { SWIG_PYTHON_THREAD_END_BLOCK; return false; } else { std::map::iterator smit; std::map::iterator mit; for (smit = self->begin(), mit = arg1->begin(); smit != self->end(), mit != arg1->end(); smit++, mit++) { //std::cout << "self actual key " << smit->first << " -- provided vmap actual key " << mit->first << std::endl; if ((smit->first != mit->first) || (!(smit->second == mit->second))) { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } SWIG_PYTHON_THREAD_END_BLOCK; return true; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } SWIG_PYTHON_THREAD_END_BLOCK; return false; } }; %extend std::list { char* __str__() { std::string str; size_t size; size_t counter; std::list< Variant_p >::iterator lit; char* cstr; size = self->size(); counter = 0; str = "["; for (lit = self->begin(); lit != self->end(); lit++) { counter++; if ((*lit)->type() == typeId::String || (*lit)->type() == typeId::CArray || (*lit)->type() == typeId::Path) str += "'" + (*lit)->toString() + "'"; else str += (*lit)->toString(); if (counter != size) str += ", "; } str += "]"; cstr = NULL; if ((cstr = (char*)malloc(sizeof(char) * (str.size()+1))) != NULL) strncpy (cstr, str.c_str(), str.size()+1); return cstr; } void append(std::list< Variant_p > other) { Variant* vptr; if ((vptr = new Variant(other)) != NULL) self->push_back(Variant_p(vptr)); return; } void append(std::map< std::string, Variant_p > other) { Variant* vptr; if ((vptr = new Variant(other)) != NULL) self->push_back(Variant_p(vptr)); return; } bool operator==(PyObject* obj) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (PyList_Check(obj)) { if (self->size() == (unsigned int) PyList_Size(obj)) { std::list< Variant_p >::const_iterator it; int i; PyObject* item; for (it = self->begin(), i = 0; it != self->end(); it++, i++) { item = PyList_GetItem(obj, i); if (!Variant_operator_Se__Se___SWIG_1(it->get(), item)) { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } SWIG_PYTHON_THREAD_END_BLOCK; return true; } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (strncmp("VList", obj->ob_type->tp_name, 5) == 0) { void* argp1 = 0; std::list< Variant_p > *arg1 = (std::list< Variant_p > *) 0 ; int res1 = SWIG_ConvertPtr(obj, &argp1, $descriptor(std::list< Variant_p >), 0 | 0); if (SWIG_IsOK(res1)) { arg1 = reinterpret_cast< std::list * >(argp1); if (self->size() != arg1->size()) { SWIG_PYTHON_THREAD_END_BLOCK; return false; } else { std::list::iterator sit; std::list::iterator lit; for (sit = self->begin(), lit = arg1->begin(); sit != self->end(), lit != arg1->end(); sit++, lit++) if (!(*lit == *sit)) { SWIG_PYTHON_THREAD_END_BLOCK; return false; } SWIG_PYTHON_THREAD_END_BLOCK; return true; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } SWIG_PYTHON_THREAD_END_BLOCK; return false; } }; %extend Variant { /* Variant(PyObject* obj) throw (std::string) */ /* { */ /* Variant* v = NULL; */ /* std::string err = ""; */ /* if (obj == NULL) */ /* throw(std::string("Provided PyObject is NULL")); */ /* if (obj == Py_None) */ /* throw(std::string("Provided PyObject cannot be None")); */ /* SWIG_PYTHON_THREAD_BEGIN_BLOCK; */ /* if (PyLong_Check(obj) || PyInt_Check(obj)) */ /* { */ /* int16_t s; */ /* uint16_t us; */ /* int32_t i; */ /* uint32_t ui; */ /* int64_t ll; */ /* uint64_t ull; */ /* if (SWIG_IsOK(SWIG_AsVal_short(obj, &s))) */ /* v = new Variant(s); */ /* else if (SWIG_IsOK(SWIG_AsVal_unsigned_SS_short(obj, &us))) */ /* v = new Variant(us); */ /* else if (SWIG_IsOK(SWIG_AsVal_int(obj, &i))) */ /* v = new Variant(i); */ /* else if (SWIG_IsOK(SWIG_AsVal_unsigned_SS_int(obj, &ui))) */ /* v = new Variant(ui); */ /* #ifdef SWIGWORDSIZE64 */ /* else if (SWIG_IsOK(SWIG_AsVal_long(obj, &ll))) */ /* #else */ /* else if (SWIG_IsOK(SWIG_AsVal_long_SS_long(obj, &ll))) */ /* #endif */ /* v = new Variant(ll); */ /* #ifdef SWIGWORDSIZE64 */ /* else if (SWIG_IsOK(SWIG_AsVal_unsigned_SS_long(obj, &ull))) */ /* #else */ /* else if (SWIG_IsOK(SWIG_AsVal_unsigned_SS_long_SS_long(obj, &ull))) */ /* #endif */ /* v = new Variant(ull); */ /* else */ /* err = "error while converting integer"; */ /* } */ /* else if (PyBool_Check(obj)) */ /* { */ /* bool b; */ /* if (SWIG_IsOK(SWIG_AsVal_bool(obj, &b))) */ /* v = new Variant(b); */ /* else */ /* err = "Error while converting boolean"; */ /* } */ /* else if (PyString_Check(obj)) */ /* { */ /* std::string str; */ /* if (SWIG_IsOK(SWIG_AsVal_std_string(obj, &str))) */ /* v = new Variant(str); */ /* else */ /* err = "Error while converting string"; */ /* } */ /* else if (strncmp("Node", obj->ob_type->tp_name, 4) == 0) */ /* { */ /* void* vptr; */ /* Node* node; */ /* if (SWIG_IsOK(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_Node, 0))) */ /* { */ /* node = reinterpret_cast< Node * >(vptr); */ /* v = new Variant(node); */ /* } */ /* else */ /* err = "Error while converting Node"; */ /* } */ /* else if (strncmp("VLink", obj->ob_type->tp_name, 5) == 0) */ /* { */ /* void* vptr; */ /* VLink* node; */ /* if (SWIG_IsOK(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_VLink, 0))) */ /* { */ /* node = reinterpret_cast< VLink * >(vptr); */ /* v = new Variant((Node*)node); */ /* } */ /* else */ /* err = "Error while converting VLink"; */ /* } */ /* else if (strncmp("Path", obj->ob_type->tp_name, 4) == 0) */ /* { */ /* void* vptr; */ /* Path* path; */ /* if (SWIG_IsOK(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_Path, 0))) */ /* { */ /* path = reinterpret_cast< Path * >(vptr); */ /* v = new Variant(path); */ /* } */ /* else */ /* err = "Error while converting Path"; */ /* } */ /* else if (PyList_Check(obj)) */ /* { */ /* Py_ssize_t size = PyList_Size(obj); */ /* Py_ssize_t it; */ /* PyObject* item = NULL; */ /* std::list vlist; */ /* Variant* vitem = NULL; */ /* for (it = 0; it != size; it++) */ /* { */ /* item = PyList_GetItem(obj, it); */ /* try */ /* { */ /* vitem = new_Variant__SWIG_19(item); */ /* vlist.push_back(Variant_p(vitem)); */ /* } */ /* catch (std::string e) */ /* { */ /* err = e; */ /* break; */ /* } */ /* } */ /* if (!err.empty()) */ /* vlist.erase(vlist.begin(), vlist.end()); */ /* else */ /* v = new Variant(vlist); */ /* } */ /* else if (PyDict_Check(obj)) */ /* { */ /* std::map vmap; */ /* Variant* vitem = NULL; */ /* std::string strkey; */ /* PyObject *key, *value; */ /* Py_ssize_t pos = 0; */ /* while (PyDict_Next(obj, &pos, &key, &value)) */ /* { */ /* if (!PyString_Check(key)) */ /* { */ /* err = "Keys must be of type string"; */ /* break; */ /* } */ /* else if (SWIG_IsOK(SWIG_AsVal_std_string(key, &strkey))) */ /* { */ /* try */ /* { */ /* vitem = new_Variant__SWIG_19(value); */ /* vmap[strkey] = Variant_p(vitem); */ /* } */ /* catch (std::string e) */ /* { */ /* err = e; */ /* break; */ /* } */ /* } */ /* else */ /* { */ /* err = "Error while converting string"; */ /* break; */ /* } */ /* } */ /* if (!err.empty()) */ /* vmap.clear(); */ /* else */ /* v = new Variant(vmap); */ /* } */ /* SWIG_PYTHON_THREAD_END_BLOCK; */ /* if (!err.empty()) */ /* throw(std::string(err)); */ /* return v; */ /* } */ Variant(PyObject* obj, uint8_t type) throw(std::string) { Variant* v = NULL; bool err = true; int ecode; if (obj == NULL) throw(std::string("Provided PyObject is NULL")); if (obj == Py_None) throw(std::string("Provided PyObject cannot be None")); //std::cout << "Variant::Variant(PyObject*, uint8_t) -- PyObject type " << obj->ob_type->tp_name << std::endl; SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (PyLong_Check(obj) || PyInt_Check(obj)) { if (type == uint8_t(typeId::Bool)) { bool b; int ecode = SWIG_AsVal_bool(obj, &b); if (SWIG_IsOK(ecode)) { v = new Variant(b); err = false; } } else if (type == uint8_t(typeId::Int16)) { int16_t s; ecode = SWIG_AsVal_short(obj, &s); if (SWIG_IsOK(ecode)) { v = new Variant(s); err = false; } } else if (type == uint8_t(typeId::UInt16)) { uint16_t us; int ecode = SWIG_AsVal_unsigned_SS_short(obj, &us); if (SWIG_IsOK(ecode)) { v = new Variant(us); err = false; } } else if (type == uint8_t(typeId::Int32)) { int32_t i; int ecode = SWIG_AsVal_int(obj, &i); if (SWIG_IsOK(ecode)) { v = new Variant(i); err = false; } } else if (type == uint8_t(typeId::UInt32)) { uint32_t ui; int ecode = SWIG_AsVal_unsigned_SS_int(obj, &ui); if (SWIG_IsOK(ecode)) { v = new Variant(ui); err = false; } } else if (type == uint8_t(typeId::Int64)) { int64_t ll; #ifdef SWIGWORDSIZE64 int ecode = SWIG_AsVal_long(obj, &ll); #else int ecode = SWIG_AsVal_long_SS_long(obj, &ll); #endif if (SWIG_IsOK(ecode)) { v = new Variant(ll); err = false; } } else if (type == uint8_t(typeId::UInt64)) { uint64_t ull; #ifdef SWIGWORDSIZE64 int ecode = SWIG_AsVal_unsigned_SS_long(obj, &ull); #else int ecode = SWIG_AsVal_unsigned_SS_long_SS_long(obj, &ull); #endif if (SWIG_IsOK(ecode)) { v = new Variant(ull); err = false; } } } else if (PyBool_Check(obj)) { bool b; int ecode = SWIG_AsVal_bool(obj, &b); if (SWIG_IsOK(ecode)) { v = new Variant(b); err = false; } } else if (PyString_Check(obj)) { std::string str; ecode = SWIG_AsVal_std_string(obj, &str); if (SWIG_IsOK(ecode)) { if (type == typeId::String) { v = new Variant(str); err = false; } else if (type == typeId::CArray) { v = new Variant((char*)str.c_str()); err = false; } else if (type == typeId::Char) { char c; if ((str.size() == 1) || (str.size() == 0)) { c = *(str.c_str()); v = new Variant(c); err = false; } } else if (type == typeId::Path) { Path* p; p = new Path(str); v = new Variant(p); err = false; } else if (type == typeId::Int16) { int16_t s; std::istringstream conv(str); if (conv >> s) { v = new Variant(s); err = false; } } else if (type == typeId::UInt16) { uint16_t us; std::istringstream conv(str); if (conv >> us) { v = new Variant(us); err = false; } } else if (type == typeId::Int32) { int32_t i; std::istringstream conv(str); if (conv >> i) { v = new Variant(i); err = false; } } else if (type == typeId::UInt32) { int32_t ui; std::istringstream conv(str); if (conv >> ui) { v = new Variant(ui); err = false; } } else if (type == typeId::Int64) { int64_t ll; std::istringstream conv(str); if (conv >> ll) { v = new Variant(ll); err = false; } } else if (type == typeId::UInt64) { uint64_t ull; std::istringstream conv(str); if (conv >> ull) { v = new Variant(ull); err = false; } } } } else if (strncmp("Node", obj->ob_type->tp_name, 4) == 0) { if (type == typeId::Node) { void* vptr; Node* node; int res = SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_Node, 0); if (SWIG_IsOK(res)) { node = reinterpret_cast< Node * >(vptr); v = new Variant(node); err = false; } } } else if (strncmp("VLink", obj->ob_type->tp_name, 5) == 0) { if (type == typeId::Node) { void* vptr; VLink* node; int res = SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_VLink, 0); if (SWIG_IsOK(res)) { node = reinterpret_cast< VLink * >(vptr); v = new Variant(node); err = false; } } } else if (strncmp("Path", obj->ob_type->tp_name, 4) == 0) { if (type == typeId::Path) { void* vptr; Path* path; int res = SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_Path, 0); if (SWIG_IsOK(res)) { path = reinterpret_cast< Path * >(vptr); v = new Variant(path); err = false; } } } else if (PyList_Check(obj) && type == typeId::List) { Py_ssize_t size = PyList_Size(obj); Py_ssize_t it; PyObject* item = NULL; std::list< Variant_p > vlist; Variant* vitem = NULL; bool lbreak = false; for (it = 0; it != size; it++) { item = PyList_GetItem(obj, it); if ((vitem = new_Variant__SWIG_20(item, type)) == NULL) { lbreak = true; break; } vlist.push_back(Variant_p(vitem)); } if (lbreak) vlist.erase(vlist.begin(), vlist.end()); else { v = new Variant(vlist); err = false; } } /* else if (PyDict_Check(obj) && type == typeId::Map) */ /* { */ /* PyObject* item = NULL; */ /* std::map vmap; */ /* Variant* vitem = NULL; */ /* bool lbreak = false; */ /* char* strkey; */ /* PyObject *key, *value; */ /* Py_ssize_t pos = 0; */ /* while (PyDict_Next(obj, &pos, &key, &value)) */ /* { */ /* if (!PyString_Check(key)) */ /* err */ /* strkey */ /* Py_DECREF(o); */ /* } */ /* } */ if (err) { SWIG_PYTHON_THREAD_END_BLOCK; throw(std::string("Cannot create Variant, Provided PyObject and requested type are not compatible")); } SWIG_PYTHON_THREAD_END_BLOCK; return v; } bool operator==(PyObject* obj) { Variant* v = NULL; uint8_t type; SWIG_PYTHON_THREAD_BEGIN_BLOCK; type = self->type(); if (obj == NULL) { //printf(" !!! obj is NULL !!!\n"); SWIG_PYTHON_THREAD_END_BLOCK; return false; } if (obj->ob_type == NULL) { //printf(" !!! obj->ob_type is NULL !!!\n"); SWIG_PYTHON_THREAD_END_BLOCK; return false; } if (obj->ob_type->tp_name == NULL) { //printf(" !!! obj->ob_type->tp_name is NULL !!!\n"); SWIG_PYTHON_THREAD_END_BLOCK; return false; } if (strncmp("Variant", obj->ob_type->tp_name, 7) == 0) { //printf("Variant::operator==(PyObject* obj) ---> obj == Variant\n"); void* argp1 = 0; Variant *arg1 = (Variant *) 0 ; int res1 = SWIG_ConvertPtr(obj, &argp1, SWIGTYPE_p_Variant, 0 | 0); if (SWIG_IsOK(res1)) { arg1 = reinterpret_cast< Variant * >(argp1); SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(arg1); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (((strncmp("VList", obj->ob_type->tp_name, 5) == 0) || PyList_Check(obj)) && (type == typeId::List)) { //printf("Variant::operator==(PyObject* obj) ---> obj == VList\n"); std::list< Variant_p > selflist; selflist = self->value >(); SWIG_PYTHON_THREAD_END_BLOCK; return std_list_Sl_RCPtr_Sl_Variant_Sg__Sg__operator_Se__Se_(&selflist, obj); } else if (((strncmp("VMap", obj->ob_type->tp_name, 4) == 0) || PyDict_Check(obj)) && (type == typeId::Map)) { //printf("Variant::operator==(PyObject* obj) ---> obj == VMap\n"); std::map selfmap; selfmap = self->value >(); SWIG_PYTHON_THREAD_END_BLOCK; return std_map_Sl_std_string_Sc_RCPtr_Sl_Variant_Sg__Sg__operator_Se__Se_(&selfmap, obj); } else if (PyLong_Check(obj) || PyInt_Check(obj)) { //printf("Variant::operator==(PyObject* obj) ---> obj == PyLong_Check || PyInt_Check provided\n"); if (type == uint8_t(typeId::Int16)) { int16_t v; int ecode = SWIG_AsVal_short(obj, &v); if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (type == uint8_t(typeId::UInt16)) { uint16_t v; int ecode = SWIG_AsVal_unsigned_SS_short(obj, &v); if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (type == uint8_t(typeId::Int32)) { int32_t v; int ecode = SWIG_AsVal_int(obj, &v); if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (type == uint8_t(typeId::UInt32)) { uint32_t v; int ecode = SWIG_AsVal_unsigned_SS_int(obj, &v); if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (type == uint8_t(typeId::Int64)) { int64_t v; #ifdef SWIGWORDSIZE64 int ecode = SWIG_AsVal_long(obj, &v); #else int ecode = SWIG_AsVal_long_SS_long(obj, &v); #endif if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (type == uint8_t(typeId::UInt64)) { uint64_t v; #ifdef SWIGWORDSIZE64 int ecode = SWIG_AsVal_unsigned_SS_long(obj, &v); #else int ecode = SWIG_AsVal_unsigned_SS_long_SS_long(obj, &v); #endif if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if (PyBool_Check(obj) && (type == typeId::Bool)) { bool b; int ecode = SWIG_AsVal_bool(obj, &b); if (SWIG_IsOK(ecode)) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(v); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else if ((PyString_Check(obj)) && (type == typeId::String)) { char* cstr; if ((cstr = PyString_AsString(obj)) != NULL) { SWIG_PYTHON_THREAD_END_BLOCK; return self->operator==(cstr); } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } else { SWIG_PYTHON_THREAD_END_BLOCK; return false; } } bool operator!=(PyObject* obj) { return (!Variant_operator_Se__Se___SWIG_1(self, obj)); } bool operator>(PyObject* obj) { uint8_t type; type = self->type(); if (obj == NULL) { //printf(" !!! obj is NULL !!!\n"); return false; } if (obj->ob_type == NULL) { //printf(" !!! obj->ob_type is NULL !!!\n"); return false; } if (obj->ob_type->tp_name == NULL) { //printf(" !!! obj->ob_type->tp_name is NULL !!!\n"); return false; } if (strncmp("Variant", obj->ob_type->tp_name, 7) == 0) { //printf("Variant::operator>(PyObject* obj) ---> obj == Variant\n"); void* argp1 = 0; Variant *arg1 = (Variant *) 0 ; int res1 = SWIG_ConvertPtr(obj, &argp1, SWIGTYPE_p_Variant, 0 | 0); if (SWIG_IsOK(res1)) { arg1 = reinterpret_cast< Variant * >(argp1); return self->operator>(arg1); } else return false; } else if (PyLong_Check(obj) || PyInt_Check(obj)) { //printf("Variant::operator>(PyObject* obj) ---> obj == PyLong_Check || PyInt_Check provided\n"); if (type == uint8_t(typeId::Int16)) { int16_t v; int ecode = SWIG_AsVal_short(obj, &v); if (SWIG_IsOK(ecode)) return self->operator>(v); else return false; } else if (type == uint8_t(typeId::UInt16)) { uint16_t v; int ecode = SWIG_AsVal_unsigned_SS_short(obj, &v); if (SWIG_IsOK(ecode)) return self->operator>(v); else return false; } else if (type == uint8_t(typeId::Int32)) { int32_t v; int ecode = SWIG_AsVal_int(obj, &v); if (SWIG_IsOK(ecode)) return self->operator>(v); else return false; } else if (type == uint8_t(typeId::UInt32)) { uint32_t v; int ecode = SWIG_AsVal_unsigned_SS_int(obj, &v); if (SWIG_IsOK(ecode)) return self->operator>(v); else return false; } else if (type == uint8_t(typeId::Int64)) { int64_t v; #ifdef SWIGWORDSIZE64 int ecode = SWIG_AsVal_long(obj, &v); #else int ecode = SWIG_AsVal_long_SS_long(obj, &v); #endif if (SWIG_IsOK(ecode)) return self->operator>(v); else return false; } else if (type == uint8_t(typeId::UInt64)) { uint64_t v; #ifdef SWIGWORDSIZE64 int ecode = SWIG_AsVal_unsigned_SS_long(obj, &v); #else int ecode = SWIG_AsVal_unsigned_SS_long_SS_long(obj, &v); #endif if (SWIG_IsOK(ecode)) return self->operator>(v); else return false; } else return false; } else if ((PyString_Check(obj)) && (type == typeId::String)) { char* cstr; //printf("Variant::operator>(PyObject* obj) ---> obj == PyLong_Check || PyInt_Check provided\n"); if ((cstr = PyString_AsString(obj)) != NULL) return self->operator>(cstr); else return false; } else return false; } bool operator<(PyObject* obj) { if (Variant_operator_Se__Se___SWIG_1(self, obj)) return false; else return (!Variant_operator_Sg___SWIG_1(self, obj)); } bool operator>=(PyObject* obj) { if (Variant_operator_Sg___SWIG_1(self, obj) || Variant_operator_Se__Se___SWIG_1(self, obj)) return true; else return false; } bool operator<=(PyObject* obj) { if (Variant_operator_Sl___SWIG_1(self, obj) || Variant_operator_Se__Se___SWIG_1(self, obj)) return true; else return false; } }; %extend Variant { %pythoncode %{ funcMapper = {typeId.Char: "_Variant__Char", typeId.Int16: "_Variant__Int16", typeId.UInt16: "_Variant__UInt16", typeId.Int32: "_Variant__Int32", typeId.UInt32: "_Variant__UInt32", typeId.Int64: "_Variant__Int64", typeId.UInt64: "_Variant__UInt64", typeId.Bool: "_Variant__Bool", typeId.String: "_Variant__String", typeId.CArray: "_Variant__CArray", typeId.Node: "_Variant__Node", typeId.Path: "_Variant__Path", typeId.VTime: "_Variant__VTime", typeId.List: "_Variant__VList", typeId.Map: "_Variant__VMap", typeId.VLink: "_Variant__VLink"} def __str__(self): if self.type() == typeId.Node: return self.value().absolute() elif self.type() == typeId.VTime: return self.value() else: return self.toString() def value(self): try: valType = self.type() if valType in self.funcMapper.keys(): func = getattr(self, Variant.funcMapper[valType]) if func != None: val = func() return val else: return None else: return None except : return None %} }; %extend Variant_p { %pythoncode %{ funcMapper = {typeId.Char: "_RCVariant__Char", typeId.Int16: "_RCVariant__Int16", typeId.UInt16: "_RCVariant__UInt16", typeId.Int32: "_RCVariant__Int32", typeId.UInt32: "_RCVariant__UInt32", typeId.Int64: "_RCVariant__Int64", typeId.UInt64: "_RCVariant__UInt64", typeId.Bool: "_RCVariant__Bool", typeId.String: "_RCVariant__String", typeId.CArray: "_RCVariant__CArray", typeId.Node: "_RCVariant__Node", typeId.Path: "_RCVariant__Path", typeId.VTime: "_RCVariant__VTime", typeId.List: "_RCVariant__VList", typeId.Map: "_RCVariant__VMap", typeId.VLink: "_RCVariant__VLink"} def __str__(self): if self.type() == typeId.Node: return self.value().absolute() elif self.type() == typeId.VTime: return self.value() else: return self.toString() def value(self): try: valType = self.type() if valType in self.funcMapper.keys(): func = getattr(self, RCVariant.funcMapper[valType]) if func != None: val = func() return val else: return None else: return None except : return None %} }; %extend vtime { PyObject* vtime::get_time(void) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyDateTime_IMPORT; SWIG_PYTHON_THREAD_END_BLOCK; PyObject* v; v = PyDateTime_FromDateAndTime(self->year, self->month, self->day, self->hour, self->minute, self->second, self->usecond); return (v); } }; dff-1.3.0+dfsg.1/dff/api/types/path.cpp000066400000000000000000000011741217176075400174610ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "path.hpp" Path::Path(std::string p) { this->path = p; } dff-1.3.0+dfsg.1/dff/api/types/results.cpp000066400000000000000000000020311217176075400202170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. * Frederic B. */ #include "results.hpp" Results::Results(std::string origin) { } Results::~Results() { } bool Results::add(std::string name, Variant* val, std::string description) { } Variant* Results::valueFromKey(std::string name) { } std::string Results::descriptionFromKey(std::string) { } std::map Results::items() { } std::list Results::keys() { } std::list Results::values() { } dff-1.3.0+dfsg.1/dff/api/types/threading.cpp000066400000000000000000000021041217176075400204640ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "threading.hpp" #include namespace dff { Mutex::Mutex() { mutex_init(&__mutex); } Mutex::Mutex(const Mutex& other) { mutex_init(&__mutex); } Mutex::~Mutex() { mutex_destroy(&__mutex); } void Mutex::lock() { mutex_lock(&__mutex); } void Mutex::release() { mutex_unlock(&__mutex); } ScopedMutex::ScopedMutex(Mutex& mutex) : __mutex(mutex) { __mutex.lock(); } ScopedMutex::~ScopedMutex() { __mutex.release(); } }; dff-1.3.0+dfsg.1/dff/api/types/variant.cpp000066400000000000000000001037161217176075400201760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "variant.hpp" #include "typeinfo" #include "string.h" #include #ifdef WIN32 #define snprintf _snprintf #endif typeId* typeId::Get() { static typeId single; return &single; } typeId::typeId() { this->mapping.insert(std::pair( typeid(int16_t*).name(), typeId::Int16)); this->mapping.insert(std::pair(typeid(uint16_t*).name(), typeId::UInt16)); this->mapping.insert(std::pair(typeid(int32_t*).name(), typeId::Int32)); this->mapping.insert(std::pair(typeid(uint32_t*).name(), typeId::UInt32)); this->mapping.insert(std::pair(typeid(int64_t*).name(), typeId::Int64)); this->mapping.insert(std::pair(typeid(uint64_t*).name(), typeId::UInt64)); this->mapping.insert(std::pair(typeid(char*).name(), typeId::Char)); this->mapping.insert(std::pair(typeid(bool*).name(), typeId::Bool)); this->mapping.insert(std::pair(typeid(char**).name(), typeId::CArray)); this->mapping.insert(std::pair(typeid(void**).name(), typeId::VoidPtr)); this->mapping.insert(std::pair(typeid(std::string *).name(), typeId::String)); this->mapping.insert(std::pair(typeid(class vtime**).name(), typeId::VTime)); this->mapping.insert(std::pair(typeid(class Node**).name(), typeId::Node)); this->mapping.insert(std::pair(typeid(class VLink**).name(), typeId::VLink)); this->mapping.insert(std::pair(typeid(class Path * *).name(), typeId::Path)); this->mapping.insert(std::pair(typeid(class Argument * *).name(), typeId::Argument)); this->mapping.insert(std::pair(typeid(std::map *).name(), typeId::Map)); this->mapping.insert(std::pair(typeid(std::list< Variant_p > *).name(), typeId::List)); this->rmapping.insert(std::pair(typeId::Invalid, "Invalid")); this->rmapping.insert(std::pair(typeId::String, "std::string")); this->rmapping.insert(std::pair(typeId::Int16, "int16_t")); this->rmapping.insert(std::pair(typeId::UInt16, "uint16_t")); this->rmapping.insert(std::pair(typeId::Int32, "int32_t")); this->rmapping.insert(std::pair(typeId::UInt32, "uint32_t")); this->rmapping.insert(std::pair(typeId::Int64, "int64_t")); this->rmapping.insert(std::pair(typeId::UInt64, "uint64_t")); this->rmapping.insert(std::pair(typeId::Bool, "bool")); this->rmapping.insert(std::pair(typeId::Map, "std::map")); this->rmapping.insert(std::pair(typeId::List, "std::list< Variant_p >")); this->rmapping.insert(std::pair(typeId::VTime, "vtime*")); this->rmapping.insert(std::pair(typeId::Node, "Node*")); this->rmapping.insert(std::pair(typeId::Path, "Path*")); this->rmapping.insert(std::pair(typeId::Argument, "Argument*")); this->rmapping.insert(std::pair(typeId::VoidPtr, "void*")); this->rmapping.insert(std::pair(typeId::VLink, "VLink*")); //this->mapping.insert(std::pair((char*)typeid(std::vector *).name(), typeId::List)); //this->mapping.insert(std::pair((char*)typeid(std::set *).name(), typeId::List)); } typeId::~typeId() { // delete this->mapping; } uint8_t typeId::getType(std::string type) { std::map::iterator it; it = this->mapping.find(type); if (it != this->mapping.end()) { return it->second; } else { return 0; } } std::string typeId::typeToName(uint8_t t) { std::map::iterator it; it = this->rmapping.find(t); if (it != this->rmapping.end()) return it->second; else return std::string(""); } Variant::Variant() { this->_type = typeId::Invalid; } Variant::Variant(class Variant* orig) throw (std::string) { if (orig != NULL) { if (orig->type() == typeId::Invalid) throw (std::string("provided Variant cannot be of type Invalid")); this->_type = orig->type(); if ((this->_type == typeId::String) || (this->_type == typeId::CArray)) this->__data.str = new std::string(orig->value()); if (this->_type == typeId::Char) this->__data.c = orig->value(); if (this->_type == typeId::UInt16) this->__data.us = orig->value(); if (this->_type == typeId::Int16) this->__data.s = orig->value(); if (this->_type == typeId::UInt32) this->__data.ui = orig->value(); if (this->_type == typeId::Int32) this->__data.i = orig->value(); if (this->_type == typeId::UInt64) this->__data.ull = orig->value(); if (this->_type == typeId::Int64) this->__data.ll = orig->value(); if (this->_type == typeId::Bool) this->__data.b = orig->value(); if (this->_type == typeId::VTime) { vtime* vt = orig->value(); this->__data.ptr = new vtime(vt->year, vt->month, vt->day, vt->hour, vt->minute, vt->second, vt->usecond); } if (this->_type == typeId::Node) this->__data.ptr = (void*)orig->value(); if (this->_type == typeId::VLink) this->__data.ptr = (void*)orig->value(); if (this->_type == typeId::Path) this->__data.ptr = (void*)orig->value(); if (this->_type == typeId::Argument) this->__data.ptr = (void*)orig->value(); if (this->_type == typeId::List) { std::list< Variant_p >* lmine; std::list< Variant_p > lorig; std::list< Variant_p >::iterator it; lorig = orig->value< std::list< Variant_p > >(); lmine = new std::list< Variant_p >; for (it = lorig.begin(); it != lorig.end(); it++) lmine->push_back(*it); this->__data.ptr = (void*)lmine; } if (this->_type == typeId::Map) { std::map* mmine; std::map morig; std::map::iterator mit; mmine = new std::map; morig = orig->value< std::map >(); for (mit = morig.begin(); mit != morig.end(); mit++) mmine->insert(std::pair(mit->first, mit->second)); this->__data.ptr = (void*)mmine; } if (this->_type == typeId::VoidPtr) this->__data.ptr = orig->value(); } else throw (std::string("NULL Pointer provided")); } Variant::~Variant() { if ((this->_type == typeId::String) || (this->_type == typeId::CArray)) { if (this->__data.str != NULL) delete this->__data.str; this->__data.str = NULL; } if (this->_type == typeId::VTime) { if (this->__data.ptr != NULL) { vtime* vt = (vtime*)this->__data.ptr; delete vt; } this->__data.ptr = NULL; } if (this->_type == typeId::List) { std::list* l; if (this->__data.ptr != NULL) { l = (std::list< Variant_p >*)this->__data.ptr; l->clear(); delete l; } this->__data.ptr = NULL; } if (this->_type == typeId::Map) { std::map* m; if (this->__data.ptr != NULL) { m = (std::map*)this->__data.ptr; m->clear(); delete m; } } } Variant::Variant(std::string str) { this->__data.str = new std::string(str); this->_type = typeId::String; } Variant::Variant(char *carray) throw (std::string) { if (carray != NULL) { this->__data.str = new std::string(carray); this->_type = typeId::CArray; } else throw (std::string("NULL Pointer provided")); } Variant::Variant(char c) { this->__data.c = c; this->_type = typeId::Char; } Variant::Variant(int16_t s) { this->__data.s = s; this->_type = typeId::Int16; } Variant::Variant(uint16_t us) { this->__data.us = us; this->_type = typeId::UInt16; } Variant::Variant(int32_t i) { this->__data.i = i; this->_type = typeId::Int32; } Variant::Variant(uint32_t ui) { this->__data.ui = ui; this->_type = typeId::UInt32; } Variant::Variant(int64_t ll) { this->__data.ll = ll; this->_type = typeId::Int64; } Variant::Variant(uint64_t ull) { this->__data.ull = ull; this->_type = typeId::UInt64; } Variant::Variant(bool b) { this->__data.b = b; this->_type = typeId::Bool; } Variant::Variant(vtime *vt) throw (std::string) { if (vt != NULL) { this->__data.ptr = (void*)vt; this->_type = typeId::VTime; } else throw (std::string("NULL Pointer provided")); } Variant::Variant(class Node *node) throw (std::string) { if (node != NULL) { this->__data.ptr = node; this->_type = typeId::Node; } else throw (std::string("NULL Pointer provided")); } Variant::Variant(class VLink *node) throw (std::string) { if (node != NULL) { this->__data.ptr = node; this->_type = typeId::VLink; } else throw (std::string("NULL Pointer provided")); } Variant::Variant(Path *path) throw (std::string) { if (path != NULL) { this->__data.ptr = path; this->_type = typeId::Path; } else throw (std::string("NULL Pointer provided")); } Variant::Variant(Argument *arg) throw (std::string) { if (arg != NULL) { this->__data.ptr = arg; this->_type = typeId::Argument; } else throw (std::string("NULL Pointer provided")); } Variant::Variant(std::list< Variant_p > l) { this->__data.ptr = (void*)new std::list< Variant_p >(l); this->_type = typeId::List; } Variant::Variant(std::map m) { this->__data.ptr = (void*)new std::map(m); this->_type = typeId::Map; } Variant::Variant(void *user) throw (std::string) { if (user != NULL) { this->__data.ptr = (void*)user; this->_type = typeId::VoidPtr; } else throw (std::string("NULL Pointer provided")); } std::string Variant::toString() throw (std::string) { std::stringstream res; if (this->_type == typeId::Int16) res << this->__data.s; else if (this->_type == typeId::UInt16) res << this->__data.us; else if (this->_type == typeId::Int32) res << this->__data.i; else if (this->_type == typeId::UInt32) res << this->__data.ui; else if (this->_type == typeId::Int64) res << this->__data.ll; else if (this->_type == typeId::UInt64) res << this->__data.ull; else if (this->_type == typeId::Char) res << this->__data.c; else if ((this->_type == typeId::String || this->_type == typeId::CArray) && this->__data.str != NULL) res << *(this->__data.str); else if (this->_type == typeId::Path && this->__data.ptr != NULL) { class Path* p; p = static_cast(this->__data.ptr); res << p->path; } else if (this->_type == typeId::Bool) { if (this->__data.b) res << "True"; else res << "False"; } else if (this->_type == typeId::VTime && this->__data.ptr != NULL) { vtime* vt = (vtime*)this->__data.ptr; char dest[32]; snprintf(dest, 32, "'%.4d-%.2d-%.2dT%.2d:%.2d:%.2d:%.2d'", vt->year, vt->month, vt->day, vt->hour, vt->minute, vt->second, vt->usecond); res << dest; } else if (this->_type == typeId::List && this->__data.ptr != NULL) { std::list< Variant_p > l; std::list< Variant_p >::iterator lit; size_t size; size_t counter; l = *(static_cast * >(this->__data.ptr)); res << "["; size = l.size(); counter = 0; for (lit = l.begin(); lit != l.end(); lit++) { if ((*lit)->type() == typeId::String || (*lit)->type() == typeId::CArray || (*lit)->type() == typeId::Path) res << "'" << (*lit)->toString() << "'"; else res << (*lit)->toString(); counter++; if (counter != size) res << ", "; } res << "]"; } else if (this->_type == typeId::Map && this->__data.ptr != NULL) { std::map m; std::map::iterator mit; size_t size; size_t counter; m = *(static_cast * >(this->__data.ptr)); res << "{"; size = m.size(); counter = 0; for (mit = m.begin(); mit != m.end(); mit++) { res << "'"; res << mit->first; res << "': "; if (mit->second->type() == typeId::String || mit->second->type() == typeId::CArray || mit->second->type() == typeId::Path) res << "'" << mit->second->toString() << "'"; else res << mit->second->toString(); counter++; if (counter != size) res << ", "; } res << "}"; } else if (this->_type == typeId::Node) res << " Node * at " << this->__data.ptr; else throw std::string("Cannot convert type < " + this->typeName() + " > to < std::string >"); return res.str(); } std::string Variant::toHexString() throw (std::string) { std::stringstream res; if (this->_type == typeId::UInt16) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.us; else if (this->_type == typeId::UInt32) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.ui; else if (this->_type == typeId::UInt64) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.ull; else if (this->_type == typeId::Int16) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.s; else if (this->_type == typeId::Int32) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.i; else if (this->_type == typeId::Int64) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.ll; else if (this->_type == typeId::Char) res << "0x" << std::setw(2) << std::setfill('0') << std::hex << this->__data.c; else if ((this->_type == typeId::CArray) || (this->_type == typeId::String)) { std::string::iterator it; std::string str = *(this->__data.str); for (it = str.begin(); it != str.end(); it++) { res << std::setw(2) << std::setfill('0') << std::hex << static_cast(static_cast(*it)); res << " "; } } else throw std::string("Cannot represent type < " + this->typeName() + " > to an hexadecimal string"); return res.str(); } std::string Variant::toOctString() throw (std::string) { std::stringstream res; res << std::oct << std::setiosflags (std::ios_base::showbase); if (this->_type == typeId::UInt16) res << this->__data.us; else if (this->_type == typeId::UInt32) res << this->__data.ui; else if (this->_type == typeId::UInt64) res << this->__data.ull; else if (this->_type == typeId::Int16) res << this->__data.s; else if (this->_type == typeId::Int32) res << this->__data.i; else if (this->_type == typeId::Int64) res << this->__data.ll; else if (this->_type == typeId::Char) res << this->__data.c; else throw std::string("Cannot represent type < " + this->typeName() + " > to an octal string"); return res.str(); } uint16_t Variant::toUInt16() throw (std::string) { uint16_t res; std::stringstream err; if (this->_type == typeId::UInt16) res = this->__data.us; else if (this->_type == typeId::UInt32) if (this->__data.ui <= UINT16_MAX) res = static_cast(this->__data.ui); else err << "value [ " << this->__data.ui; else if (this->_type == typeId::UInt64) if (this->__data.ull <= UINT16_MAX) res = static_cast(this->__data.ull); else err << "value [ " << this->__data.ull; else if (this->_type == typeId::Int16) if (this->__data.s >= 0) res = static_cast(this->__data.s); else err << "value [ " << this->__data.s; else if (this->_type == typeId::Int32) if ((this->__data.i >= 0) && (this->__data.i <= UINT16_MAX)) res = static_cast(this->__data.i); else err << "value [ " << this->__data.i; else if (this->_type == typeId::Int64) if ((this->__data.ll >= 0) && (this->__data.ll <= UINT16_MAX)) res = static_cast(this->__data.ll); else err << "value [ " << this->__data.ll; else if (this->_type == typeId::Char) if (this->__data.c >= 0) res = static_cast(this->__data.c); else err << "value [ " << this->__data.c; else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < uint16_t >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < uint16_t >"; throw err.str(); } else return res; } int16_t Variant::toInt16() throw (std::string) { int16_t res; std::stringstream err; if (this->_type == typeId::Int16) res = this->__data.s; else if (this->_type == typeId::Int32) if ((this->__data.i >= INT16_MIN) && (this->__data.i <= INT16_MAX)) res = static_cast(this->__data.i); else err << "value [ " << this->__data.i; else if (this->_type == typeId::Int64) if ((this->__data.ll >= INT16_MIN) && (this->__data.ll <= INT16_MAX)) res = static_cast(this->__data.ll); else err << "value [ " << this->__data.ll; else if (this->_type == typeId::UInt16) if (this->__data.us <= INT16_MAX) res = static_cast(this->__data.us); else err << "value [ " << this->__data.us; else if (this->_type == typeId::UInt32) if (this->__data.ui <= INT16_MAX) res = static_cast(this->__data.ui); else err << "value [ " << this->__data.ui; else if (this->_type == typeId::UInt64) if (this->__data.ull <= INT16_MAX) res = static_cast(this->__data.ull); else err << "value [ " << this->__data.ull; else if (this->_type == typeId::Char) res = static_cast(this->__data.c); else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < int16_t >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < int16_t >"; throw err.str(); } else return res; } uint32_t Variant::toUInt32() throw (std::string) { uint32_t res; std::stringstream err; if (this->_type == typeId::UInt16) res = static_cast(this->__data.us); else if (this->_type == typeId::UInt32) res = this->__data.ui; else if (this->_type == typeId::UInt64) if (this->__data.ull <= UINT32_MAX) res = static_cast(this->__data.ull); else err << "value [ " << this->__data.ull; else if (this->_type == typeId::Int16) if (this->__data.s >= 0) res = static_cast(this->__data.s); else err << "value [ " << this->__data.s; else if (this->_type == typeId::Int32) if (this->__data.i >= 0) res = static_cast(this->__data.i); else err << "value [ " << this->__data.i; else if (this->_type == typeId::Int64) if ((this->__data.ll >= 0) && (this->__data.ll <= UINT32_MAX)) res = static_cast(this->__data.ll); else err << "value [ " << this->__data.ll; else if (this->_type == typeId::Char) if (this->__data.c >= 0) res = static_cast(this->__data.c); else err << "value [ " << this->__data.c; else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < uint32_t >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < uint32_t >"; throw err.str(); } else return res; } int32_t Variant::toInt32() throw (std::string) { int32_t res; std::stringstream err; if (this->_type == typeId::Int16) res = static_cast(this->__data.s); else if (this->_type == typeId::Int32) res = this->__data.i; else if (this->_type == typeId::Int64) if ((this->__data.ll >= INT32_MIN) && (this->__data.ll <= INT32_MAX)) res = static_cast(this->__data.ll); else err << "value [ " << this->__data.ll; else if (this->_type == typeId::UInt16) res = static_cast(this->__data.us); else if (this->_type == typeId::UInt32) if (this->__data.ui <= INT32_MAX) res = static_cast(this->__data.ui); else err << "value [ " << this->__data.ui; else if (this->_type == typeId::UInt64) if (this->__data.ull <= INT32_MAX) res = static_cast(this->__data.ull); else err << "value [ " << this->__data.ull; else if (this->_type == typeId::Char) res = static_cast(this->__data.c); else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < int32_t >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < int32_t >"; throw err.str(); } else return res; } uint64_t Variant::toUInt64() throw (std::string) { uint64_t res; std::stringstream err; if (this->_type == typeId::UInt16) res = static_cast(this->__data.us); else if (this->_type == typeId::UInt32) res = static_cast(this->__data.ui); else if (this->_type == typeId::UInt64) res = this->__data.ull; else if (this->_type == typeId::Int16) if (this->__data.s >= 0) res = static_cast(this->__data.s); else err << "value [ " << this->__data.s; else if (this->_type == typeId::Int32) if (this->__data.i >= 0) res = static_cast(this->__data.i); else err << "value [ " << this->__data.i; else if (this->_type == typeId::Int64) if (this->__data.ll >= 0) res = static_cast(this->__data.ll); else err << "value [ " << this->__data.ll; else if (this->_type == typeId::Char) if (this->__data.c >= 0) res = static_cast(this->__data.c); else err << "value [ " << this->__data.c; else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < uint64_t >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < uint64_t >"; throw err.str(); } else return res; } int64_t Variant::toInt64() throw (std::string) { int64_t res; std::stringstream err; if (this->_type == typeId::Int16) res = static_cast(this->__data.s); else if (this->_type == typeId::Int32) res = static_cast(this->__data.i); else if (this->_type == typeId::Int64) res = this->__data.ll; else if (this->_type == typeId::UInt16) res = static_cast(this->__data.us); else if (this->_type == typeId::UInt32) res = static_cast(this->__data.ui); else if (this->_type == typeId::UInt64) if (this->__data.ull <= INT64_MAX) res = static_cast(this->__data.ull); else err << "value [ " << this->__data.ull; else if (this->_type == typeId::Char) res = static_cast(this->__data.c); else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < int64_t >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < int64_t >"; throw err.str(); } else return res; } char* Variant::toCArray() throw (std::string) { char *res; std::string str; try { res = new char[this->__data.str->size() + 1]; memcpy(res, this->__data.str->c_str(), this->__data.str->size()); res[this->__data.str->size()] = '\0'; } catch (std::string e) { throw std::string("Cannot convert type < " + this->typeName() + " > to type "); } return res; } char Variant::toChar() throw (std::string) { char res; std::stringstream err; if (this->_type == typeId::Char) res = this->__data.c; else if (this->_type == typeId::Int16) { if ((this->__data.s >= INT8_MIN) && (this->__data.s <= INT8_MAX)) res = static_cast(this->__data.s); else err << "value [ " << this->__data.s; } else if (this->_type == typeId::Int32) { if ((this->__data.i >= INT8_MIN) && (this->__data.i <= INT8_MAX)) res = static_cast(this->__data.i); else err << "value [ " << this->__data.i; } else if (this->_type == typeId::Int64) { if ((this->__data.ll >= INT8_MIN) && (this->__data.ll <= INT8_MAX)) res = static_cast(this->__data.ll); else err << "value [ " << this->__data.ll; } else if (this->_type == typeId::UInt16) { if ((this->__data.us >= INT8_MIN) && (this->__data.us <= INT8_MAX)) res = static_cast(this->__data.us); else err << "value [ " << this->__data.us; } else if (this->_type == typeId::UInt32) { if (this->__data.ui <= INT8_MAX) res = static_cast(this->__data.ui); else err << "value [ " << this->__data.ui; } else if (this->_type == typeId::UInt64) { if(this->__data.ull <= INT8_MAX) res = static_cast(this->__data.ull); else err << "value [ " << this->__data.ull; } else if (this->_type == typeId::CArray) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else if (this->_type == typeId::String) { std::istringstream istr(*(this->__data.str)); if (!(istr >> res)) err << "value [ " << *(this->__data.str); } else throw std::string("type < " + this->typeName() + " > cannot be converted to < char >"); if (!(err.str().empty())) { err << " ] of type < " << this->typeName() << " > does not fit in type < char >"; throw err.str(); } else return res; } bool Variant::toBool() throw (std::string) { if (this->_type == typeId::Bool) return this->__data.b; else throw (std::string("value of type < " + this->typeName() + " > cannot be converted to < bool >")); } uint8_t Variant::type() { return this->_type; } std::string Variant::typeName() { return typeId::Get()->typeToName(this->_type); } bool Variant::operator==(Variant* v) { std::stringstream tmp; if (v == NULL) return false; try { if (this->_type == typeId::Char) return (this->toChar() == v->toChar()); else if (this->_type == typeId::Int16) return this->toInt16() == v->toInt16(); else if (this->_type == typeId::Int32) return this->toInt32() == v->toInt32(); else if (this->_type == typeId::Int64) return this->toInt64() == v->toInt64(); else if (this->_type == typeId::UInt16) { return this->toUInt16() == v->toUInt16(); } else if (this->_type == typeId::UInt32) return this->toUInt32() == v->toUInt32(); else if (this->_type == typeId::UInt64) return this->toUInt64() == v->toUInt64(); else if (this->_type == typeId::Bool) return this->toBool() == v->toBool(); else if (this->_type == typeId::String) { if ((v->type() == typeId::String) || (v->type() == typeId::CArray) || (v->type() == typeId::Char)) { std::string mine; std::string other; mine = this->toString(); other = v->toString(); return (mine == other); } else return false; } else if (this->_type == typeId::VTime) { if (v->type() == typeId::VTime) { vtime* mine; vtime* other; mine = (vtime*)this->__data.ptr; other = v->value(); return (mine->operator==(other)); } else return false; } else if (this->_type == typeId::Map) { std::map mine; std::map other; std::map::iterator mit; std::map::iterator oit; mine = *(static_cast * >(this->__data.ptr)); other = v->value >(); if (other.size() == mine.size()) { for (mit = mine.begin(), oit = other.begin(); mit != mine.end(), oit != other.end(); mit++, oit++) if ((mit->first != oit->first) || (!(*(mit->second) == oit->second))) return false; return true; } else return false; } else if (this->_type == typeId::List) { std::list< Variant_p > mine; std::list< Variant_p > other; std::list< Variant_p >::iterator mit; std::list< Variant_p >::iterator oit; mine = *(static_cast * >(this->__data.ptr)); other = v->value >(); if (other.size() == mine.size()) { for (mit = mine.begin(), oit = other.begin(); mit != mine.end(), oit != other.end(); mit++, oit++) if (!(*(*mit) == *oit)) return false; return true; } else return false; } else return false; } catch (std::string e) { return false; } } bool Variant::operator!=(Variant* v) { return !(this->operator==(v)); } bool Variant::operator>(Variant* v) { int64_t ll; uint64_t ull; int64_t oll; uint64_t oull; uint8_t otype; if (v == NULL) return true; if (this->operator==(v)) return false; otype = v->type(); if ((this->_type == typeId::Char) || (this->_type == typeId::Int16) || (this->_type == typeId::Int32) || (this->_type == typeId::Int64)) { ll = this->toInt64(); if ((otype == typeId::Char) || (otype == typeId::Int16) || (otype == typeId::Int32) || (otype == typeId::Int64)) return (ll > v->toInt64()); else if ((ll >= 0) && ((otype == typeId::UInt16) || (otype == typeId::UInt32) || (otype == typeId::UInt64))) { ull = static_cast(ll); return (ull > v->toUInt64()); } else return false; } else if ((this->_type == typeId::UInt16) || (this->_type == typeId::UInt32) || (this->_type == typeId::UInt64)) { ull = this->toUInt64(); if ((otype == typeId::UInt16) || (otype == typeId::UInt32) || (otype == typeId::UInt64)) return (ull > v->toUInt64()); else if ((otype == typeId::Char) || (otype == typeId::Int16) || (otype == typeId::Int32) || (otype == typeId::Int64)) { oll = v->toInt64(); if (oll >= 0) { oull = static_cast(oll); return (ull > oull); } else return true; } else return false; } else if (this->_type == typeId::String) { if ((v->type() == typeId::String) || (v->type() == typeId::CArray) || (v->type() == typeId::Char)) { std::string mine; std::string other; mine = this->toString(); other = v->toString(); return (mine > other); } else return true; } else if (this->_type == typeId::VTime) { if (v->type() == typeId::VTime) { vtime* mine; vtime* other; mine = (vtime*)this->__data.ptr; other = v->value(); return (mine->operator>(other)); } else return false; } return false; } bool Variant::operator>=(Variant* v) { if (this->operator>(v) || this->operator==(v)) return true; else return false; } bool Variant::operator<(Variant* v) { if (this->operator==(v)) return false; else return !(this->operator>(v)); } bool Variant::operator<=(Variant* v) { if (this->operator<(v) || this->operator==(v)) return true; else return false; } dff-1.3.0+dfsg.1/dff/api/types/vtime.cpp000066400000000000000000000124441217176075400176530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "vtime.hpp" vtime::vtime() { year = month = day = hour = minute = second = usecond = 0; } vtime::vtime(int y, int mo, int d, int h, int mi, int s, int us) { year = y; month = mo; day = d; hour = h; minute = mi; second = s; usecond = us; } vtime::vtime(uint16_t dos_time, uint16_t dos_date) { this->day = (dos_date & 31); this->month = ((dos_date >> 5) & 15); this->year = ((dos_date >> 9) + 1980); if (dos_time != 0) { this->second = (dos_time & 31) * 2; this->minute = ((dos_time >> 5) & 63); this->hour = (dos_time >> 11); } else { this->second = 0; this->minute = 0; this->hour = 0; } this->usecond = 0; } vtime::vtime(uint64_t value, int type = 0) { if (value > 0) { if (type == TIME_MS_64) { value -= NANOSECS_1601_TO_1970; value /= 10000000; } struct tm date; #ifdef WIN32 if (_gmtime64_s(&date, (__time64_t*)&value) == 0) #else if (gmtime_r((time_t *)&value, &date) != NULL) #endif { this->year = date.tm_year + 1900; this->month = date.tm_mon + 1; this->day = date.tm_mday; this->hour = date.tm_hour; this->minute = date.tm_min; this->second = date.tm_sec; this->dst = date.tm_isdst; this->wday = date.tm_wday; this->yday = date.tm_yday; this->usecond = 0; return; } } year = month = day = hour = minute = second = usecond = 0; } void vtime::__setFromDate(std::string date) { size_t cpos; size_t opos; cpos = date.find("-"); if (cpos != std::string::npos) { std::istringstream(date.substr(0, cpos)) >> this->year; opos = cpos + 1; cpos = date.find("-", opos); if (cpos != std::string::npos) { std::istringstream(date.substr(opos, cpos)) >> this->month; if (cpos < date.size()) std::istringstream(date.substr(cpos+1)) >> this->day; } else if (opos < std::string::npos) std::istringstream(date.substr(opos)) >> this->month; } else std::istringstream(date.substr(0)) >> this->year; } void vtime::__setFromTime(std::string time) { size_t cpos; size_t opos; cpos = time.find(":"); if (cpos != std::string::npos) { std::istringstream(time.substr(0, cpos)) >> this->hour; opos = cpos + 1; cpos = time.find(":", opos); if (cpos != std::string::npos) { std::istringstream(time.substr(opos, cpos)) >> this->minute; if (cpos < time.size()) std::istringstream(time.substr(cpos+1)) >> this->second; } else if (opos < std::string::npos) std::istringstream(time.substr(opos)) >> this->minute; } else std::istringstream(time.substr(0)) >> this->hour; } vtime::vtime(std::string ts) { size_t midx; std::string date; std::string time; year = month = day = hour = minute = second = usecond = 0; if ((midx = ts.find("T")) != std::string::npos) { date = ts.substr(0, midx); this->__setFromDate(date); time = ts.substr(midx+1); this->__setFromTime(time); } else if (ts.find(":") != std::string::npos && ts.find("-") == std::string::npos) this->__setFromTime(ts); else if (ts.find("-") != std::string::npos && ts.find(":") == std::string::npos) this->__setFromDate(ts); } bool vtime::operator==(vtime* v) { if (v != NULL) return ((this->year == v->year) && (this->month == v->month) && (this->day == v->day) && (this->hour == v->hour) && (this->minute == v->minute) && (this->second == v->second) && (this->usecond == v->usecond)); else return false; } bool vtime::operator!=(vtime* v) { return !(this->operator==(v)); } bool vtime::operator>(vtime* v) { if (v != NULL) return ((this->year > v->year) || ((this->year == v->year) && ((this->month > v->month) || ((this->month == v->month) && ((this->day > v->day) || ((this->day == v->day) && ((this->hour > v->hour) || ((this->hour == v->hour) && ((this->minute > v->minute) || ((this->minute == v->minute) && ((this->second > v->second) || ((this->second == v->second) && (this->usecond > v->usecond))))))))))))); else return true; } bool vtime::operator<(vtime* v) { return !(this->operator>(v)); } bool vtime::operator>=(vtime* v) { if (v != NULL) return ((this->year > v->year) || ((this->year == v->year) && ((this->month > v->month) || ((this->month == v->month) && ((this->day > v->day) || ((this->day == v->day) && ((this->hour > v->hour) || ((this->hour == v->hour) && ((this->minute > v->minute) || ((this->minute == v->minute) && ((this->second > v->second) || ((this->second == v->second) && ((this->usecond > v->usecond) || (this->usecond == v->usecond)))))))))))))); else return true; } bool vtime::operator<=(vtime* v) { return !(this->operator>=(v)); } vtime::~vtime() { } dff-1.3.0+dfsg.1/dff/api/vfs/000077500000000000000000000000001217176075400154505ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/api/vfs/CMakeLists.txt000066400000000000000000000016061217176075400202130ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob dff_cpp_api(vfs SWIG_FILE libvfs.i CPP_FILES rc.cpp tags.cpp node.cpp vlink.cpp vfile.cpp vfs.cpp fso.cpp mfso.cpp filemapping.cpp fdmanager.cpp cache.cpp iostat.cpp rootnode.cpp LINK_LIBRARIES datatype search exceptions types events EXTRA_FILES vfs.py __init__.py iodevice.py extract.py ) dff-1.3.0+dfsg.1/dff/api/vfs/__init__.py000066400000000000000000000012241217176075400175600ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __version__ = "2.7.0" __all__ = ["vfs", "libvfs", "iodevice"] dff-1.3.0+dfsg.1/dff/api/vfs/cache.cpp000066400000000000000000000122161217176075400172210ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "vfile.hpp" #include "filemapping.hpp" #include "cache.hpp" VFilePool& poolInit = VFilePool::instance(); Cache& attributeInit = AttributeCache::instance(); Cache& dynamicAttributeInit = DynamicAttributesCache::instance(); VFilePool& VFilePool::instance(void) { static VFilePool pool(100); return pool; } VFilePool::VFilePool(void) { mutex_init(&this->__mutex); this->__allocate(20); } VFilePool::VFilePool(uint32_t poolSize) { mutex_init(&this->__mutex); this->__allocate(poolSize); } VFilePool::~VFilePool() { uint32_t i; for (i = 0; i < this->__poolSize; i++) { free(this->__poolSlot[i]); } free(this->__poolSlot); } void VFilePool::__allocate(uint32_t poolSize) { uint32_t i; this->__poolSize = poolSize; this->__poolSlot = (CacheContainer**)malloc(sizeof(CacheContainer*) * poolSize); for (i = 0; i < this->__poolSize; i++) { CacheContainer* container; container = (CacheContainer*)malloc(sizeof(CacheContainer)); memset(container, 0, sizeof(CacheContainer)); this->__poolSlot[i] = container; } } CacheContainer* VFilePool::find(Node *node) { uint32_t i; VFile* vfile; mutex_lock(&this->__mutex); for (i = 0; i < this->__poolSize; i++) { if (this->__poolSlot[i]->content != NULL) { vfile = (VFile*)this->__poolSlot[i]->content; if ((this->__poolSlot[i]->used == false) && (vfile->node() == node)) { this->__poolSlot[i]->cacheHits++; this->__poolSlot[i]->used = true; mutex_unlock(&this->__mutex); return (this->__poolSlot[i]); } } } mutex_unlock(&this->__mutex); return (NULL); } void VFilePool::unused(CacheContainer* container) { mutex_lock(&this->__mutex); container->used = false; mutex_unlock(&this->__mutex); } bool VFilePool::insert(VFile *vfile) { uint32_t i; mutex_lock(&this->__mutex); for (i = 0; i < this->__poolSize; i++) { if (this->__poolSlot[i]->content == NULL) { this->__poolSlot[i]->content = vfile; this->__poolSlot[i]->cacheHits++; this->__poolSlot[i]->used = false; mutex_unlock(&this->__mutex); return (true); } } uint64_t oldest = ((int64_t)-1); int32_t oldestIt = 0; VFile* toClose = NULL; for (i = 0; i < this->__poolSize; i++) { if (this->__poolSlot[i]->used == false && this->__poolSlot[i]->cacheHits < oldest) { oldest = this->__poolSlot[i]->cacheHits; oldestIt = i; } } if (this->__poolSlot[oldestIt]->used == false && (oldest != (uint64_t((int64_t)-1)) )) { toClose = (VFile*)this->__poolSlot[oldestIt]->content; this->__poolSlot[oldestIt]->cacheHits = 1; this->__poolSlot[oldestIt]->used = false; this->__poolSlot[oldestIt]->content = vfile; } else toClose = vfile; mutex_unlock(&this->__mutex); delete toClose; return false; } /* Attributes Cache * */ Cache& AttributeCache::instance(void) { static Cache attributeCache(200); return attributeCache; } /* Dynamic Attributes Cache * */ Cache& DynamicAttributesCache::instance(void) { static Cache dynamicAttributesCache(200); return dynamicAttributesCache; } /* * FileMapping Cache */ FileMappingCache::FileMappingCache(uint32_t cacheSize) : Cache(cacheSize) { } FileMapping* FileMappingCache::find(Node* node) { uint32_t i; FileMapping* fm; mutex_lock(&this->__mutex); for (i = 0; i < this->__cacheSize; i++) { if (this->__cacheSlot[i]->used == true) { fm = (FileMapping*)this->__cacheSlot[i]->content; if (node == fm->node()) { this->__cacheSlot[i]->cacheHits++; fm->addref(); mutex_unlock(&this->__mutex); return (fm); } } } mutex_unlock(&this->__mutex); return (NULL); } bool FileMappingCache::insert(FileMapping* fm) { uint32_t i; mutex_lock(&this->__mutex); for (i = 0; i < this->__cacheSize; i++) { if (this->__cacheSlot[i]->used == false) { this->__cacheSlot[i]->content = (void*)fm; this->__cacheSlot[i]->used = true; this->__cacheSlot[i]->cacheHits = 1; fm->addref(); mutex_unlock(&this->__mutex); return (true); } } uint64_t oldest = this->__cacheSlot[0]->cacheHits; int32_t oldestIt = 0; for (i = 1; i < this->__cacheSize; i++) { if (this->__cacheSlot[i]->cacheHits < oldest) { oldest = this->__cacheSlot[i]->cacheHits; oldestIt = i; } } ((FileMapping*)this->__cacheSlot[oldestIt]->content)->delref(); this->__cacheSlot[oldestIt]->content = (void*)fm; this->__cacheSlot[oldestIt]->cacheHits = 1; fm->addref(); mutex_unlock(&this->__mutex); return false; } dff-1.3.0+dfsg.1/dff/api/vfs/extract.py000066400000000000000000000334351217176075400175040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # import os, shutil, time, traceback, types if os.name == "nt": import ctypes, sys from dff.api.vfs.libvfs import Node from dff.api.exceptions.libexceptions import vfsError from dff.api.events.libevents import EventHandler, event from dff.api.types.libtypes import VList, Variant, RCVariant class Extract(EventHandler): reservednames = ['CON', 'PRN', 'AUX', 'CLOCK$', 'NUL', 'COM0', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT0', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', '$AttrDef', '$BadClus', '$Bitmap', '$Boot', '$LogFile', '$MFT', '$MFTMirr', 'pagefile.sys', '$Secure', '$UpCase', '$Volume', '$Extend'] max_depth = 2**31-1 FileProgress = 0x01 OverallProgress = 0x02 FileFailed = 0x04 FolderFailed = 0x08 DataFailed = 0x10 PreserveFailed = 0x20 RenameOccured = 0x40 def __init__(self): EventHandler.__init__(self) self.__extracted = {} self.__errors = {} self.total_files = 0 self.total_folders = 0 self.extracted_files = 0 self.extracted_folders = 0 self.files_errors = 0 self.folders_errors = 0 self.ommited_files = 0 self.ommited_folders = 0 @staticmethod def freeSpace(path): """Return available free space for the disk containing path""" if os.name == "posix": st = os.statvfs(path) return st.f_bavail * st.f_frsize elif os.name == "nt": freeSpace = ctypes.c_ulonglong() if isinstance(path, unicode): ctypes.windll.kernel32.GetDiskFreeSpaceExW(path, None, None, ctypes.byref(freeSpace)) else: ctypes.windll.kernel32.GetDiskFreeSpaceExA(path, None, None, ctypes.byref(freeSpace)) return freeSpace.value else: raise Exception("Extract.freeSpace is not implemented for this OS") def checkFsCapacity(self): #perform more tests (reserved words, chars, links, ...) try: f1 = tempfile.mkstemp("casesensitive") f2 = tempfile.mkstemp("caseSensitive") f1.close() f2.close() self.case_insensitive = True except: self.case_insensitive = False pass # # Public Interface # def extractFile(self, src, dst, preserve=False, overwrite=False): dst = self.__toUtf8(dst) if preserve: try: dst = self.__makePreservedDirs(src, dst) except Exception: tb = traceback.format_exc() self.__notifyFailure(src.path(), Extract.PreserveFailed, tb) try: absfile, absfolder, renamed = self.__generateAbsolutePath(src, dst) absfile = unicode(absfile, 'utf-8', 'replace').encode('utf-8') except Exception: tb = traceback.format_exc() self.__notifyFailure(src.absolute(), Extract.FileFailed, tb) return None if absfile: #since requesting file extraction, if node is both file and folder, extract original filename if absfolder: absfile = absfolder self.total_files += 1 self.__extractFile(src, absfile, overwrite) return absfile return None def extractFolder(self, src, dst, preserve=False, overwrite=False): dst = self.__toUtf8(dst) if preserve: try: dst = self.__makePreservedDirs(src, dst) except Exception: tb = traceback.format_exc() self.__notifyFailure(src.path(), Extract.PreserveFailed, tb) return self.__countItems(src, False, 1) self.__extractTree(src, dst, overwrite, False, 1) def extractTree(self, src, dst, preserve=False, overwrite=False, extract_original=False, depth=max_depth): dst = self.__toUtf8(dst) if preserve: try: dst = self.__makePreservedDirs(src, dst) except Exception: tb = traceback.format_exc() self.__notifyFailure(src.path(), Extract.PreserveFailed, tb) return self.__countItems(src, extract_original, depth) self.__extractTree(src, dst, overwrite, extract_original, depth) def extractData(self, data, name, dst, overwrite=False): try: dst = self.__toUtf8(dst) absfile, absfolder, renamed = self.__generateAbsolutePath(name, dst) if absfile: if type(absfile) == types.UnicodeType: f = open(absfile.encode('utf-8')) else: f = open(absfile) f.write(data) f.close() except Exception as e: 'Extract.Extract data ' + str(e) f.close() tb = traceback.format_exc() self.__notifyFailure(name, Extract.DataFailed, tb) # # Private Interface # def __toUtf8(self, data): if type(data) == types.UnicodeType: return data.encode(data, 'utf-8', 'replace') return data def __countItems(self, node, extract_original, depth): if node.size(): if node.hasChildren(): if extract_original: self.total_files += 1 self.total_folders += 1 if depth > 0: children = node.children() for child in children: self.__countItems(child, extract_original, depth-1) else: self.total_files += 1 elif node.hasChildren() or node.isDir(): self.total_folders += 1 if node.hasChildren() and depth > 0: children = node.children() for child in children: self.__countItems(child, extract_original, depth-1) else: self.total_files += 1 def __makePreservedDirs(self, node, dst): npath = self.__toUtf8(node.path()) if npath == "/": abspath = dst else: lpath = os.path.dirname(npath[1:]).split("/") relpath = "" for cpath in lpath: encpath = self.__encode(cpath) relpath = os.path.join(relpath, encpath) abspath = os.path.join(dst, relpath) if os.path.exists(abspath): if os.path.isfile(abspath): os.remove(abspath) os.mkdir(abspath) else: os.mkdir(abspath) return abspath def __generateAbsolutePath(self, node, dst): absfile = "" absfolder = "" renamed = False if node.isDir() or node.hasChildren(): if node.size(): absfile = os.path.join(dst, self.__encode(self.__toUtf8(node.name()) + ".bin")) absfolder = os.path.join(dst, self.__encode(self.__toUtf8(node.name()))) else: absfile, renamed = self.__generateItemName(dst, node) absfile = os.path.join(dst, absfile) if renamed: self.__notifyRename(node.absolute(), absfile) return (absfile, absfolder, renamed) def __extractTree(self, src, dst, overwrite, extract_original, depth): try: absfile, absfolder, renamed = self.__generateAbsolutePath(src, dst) except Exception: tb = traceback.format_exc() if src.isFile(): self.__notifyFailure(src.absolute(), Extract.FileFailed, tb) else: self.__notifyFailure(src.absolute(), Extract.FolderFailed, tb) return if len(absfolder): if len(absfile) and extract_original: self.__extractFile(src, absfile, overwrite) self.__makeFolder(src, absfolder, extract_original, depth) if depth > 0: children = src.children() for child in children: self.__extractTree(child, absfolder, overwrite, extract_original, depth-1) elif len(absfile): self.__extractFile(src, absfile, overwrite) def __extractFile(self, src, dst, overwrite): self.__notifyOverallProgress() if os.path.exists(dst) and not overwrite: self.extracted_files += 1 self.__notifyOverallProgress() return sysfile = None vfile = None try: vfile = src.open() if type(dst) == types.UnicodeType: sysfile = open(dst.encode('utf-8'), 'wb') else: sysfile = open(dst, 'wb') readsize = 8192 filesize = src.size() update = False if filesize > 10*1024*1024: update = True percent = 0 totalread = 0 readed = 1 while totalread < filesize and readed > 0: toread = filesize - totalread if toread > readsize: toread = readsize buff = vfile.read(toread) readed = len(buff) if readed != toread: #try a gain one time vfile.seek(totalread) buff = vfile.read(toread) readed = len(buff) if readed != toread: raise Exception("Can't read whole file " + src.absolute() + "\n (" + str(totalread) + "/" + str(filesize) + ") .") totalread += readed sysfile.write(buff) if update and percent < round(totalread * 100 / filesize): percent = round(totalread * 100 / filesize) self.__notifyFileProgress(src, percent) vfile.close() sysfile.close() self.extracted_files += 1 except Exception as e: if sysfile: sysfile.close() if vfile: vfile.close() self.files_errors += 1 tb = traceback.format_exc() print 'Extract.ExtractFile' + str(e) self.__notifyFailure(src.absolute(), Extract.FileFailed, tb) self.__notifyOverallProgress() def __makeFolder(self, node, syspath, extract_original, depth): ret = True if not os.path.exists(syspath): try: os.mkdir(syspath) self.extracted_folders += 1 except Exception: tb = traceback.format_exc() self.__notifyFailure(node.absolute(), Extract.FolderFailed, tb) self.__countOmmited(node, extract_original, depth-1) ret = False else: self.extracted_folders += 1 self.__notifyOverallProgress() return ret def __encode(self, path): apath = "" for byte in path: if ord(byte) <= 0x1f or byte in "\"*:<>?\/|": apath += "0x%0.2x" % ord(byte) else: apath += byte for reserved in Extract.reservednames: if apath.startswith(reserved): apath = "_" + apath break path = apath return path def __generateItemName(self, abspath, node): item = self.__encode(self.__toUtf8(node.name())) renamed = False try: targets = os.listdir(abspath) except OSError: return ("", "") item_base, item_ext = os.path.splitext(item) for target in targets: if item == target: item = item_base + "_" + str(node.uid()) + item_ext renamed = True break return (item, renamed) def __notifyRename(self, src, dst): e = event() e.thisown = False e.type = Extract.RenameOccured vl = VList() vl.append(Variant(src)) vl.append(Variant(dst)) e.value = RCVariant(Variant(vl)) self.notify(e) def __notifyFileProgress(self, node, percent): e = event() e.thisown = False e.type = Extract.FileProgress vl = VList() vl.append(Variant(node)) vl.append(Variant(int(percent))) e.value = RCVariant(Variant(vl)) self.notify(e) def __notifyFailure(self, src, ftype, tb): e = event() e.thisown = False e.type = ftype vl = VList() vl.append(Variant(src)) vl.append(Variant(str(tb))) e.value = RCVariant(Variant(vl)) self.notify(e) def __notifyOverallProgress(self): buff = "" if self.total_files > 0: percent = (float(self.extracted_files) * 100) / self.total_files buff += "extracted file(s): " + str(self.extracted_files) + "/" + str(self.total_files) + " (" + str(round(percent, 2)) + "%)\n" if self.total_folders > 0: percent = (float(self.extracted_folders) * 100) / self.total_folders buff += "extracted folder(s): " + str(self.extracted_folders) + "/" + str(self.total_folders) + " (" + str(round(percent, 2)) + "%)\n" if self.files_errors > 0 and self.total_files > 0: percent = (float(self.files_errors) * 100) / self.total_files buff += "file(s) error: " + str(self.files_errors) + "/" + str(self.total_files) + " (" + str(round(percent, 2)) + "%)\n" if self.folders_errors > 0 and self.total_folders > 0: percent = (float(self.folders_errors) * 100) / self.total_folders buff += "folder(s) error: " + str(self.folders_errors) + "/" + str(self.total_folders) + " (" + str(round(percent, 2)) + "%)\n" if self.ommited_files > 0 and self.total_files > 0: percent = (float(self.ommited_files) * 100) / self.total_files buff += "ommited file(s): " + str(self.ommited_files) + "/" + str(self.total_files) + " (" + str(round(percent, 2)) + "%)\n" if self.ommited_folders > 0 and self.total_folders > 0: percent = (float(self.ommited_folders) * 100) / self.total_folders buff += "ommited folder(s): " + str(self.ommited_folders) + "/" + str(self.total_folders) + " (" + str(round(percent, 2)) + "%)\n" e = event() e.type = Extract.OverallProgress e.value = RCVariant(Variant(buff)) e.thisown = False self.notify(e) def __countOmmited(self, node, extract_original, depth): if node.size(): if node.hasChildren(): if extract_original: self.ommited_files += 1 self.ommited_folders += 1 if depth > 0: children = node.children() for child in children: self.__countOmmited(child, extract_original, depth-1) else: self.ommited_files += 1 elif node.hasChildren() or node.isDir(): self.ommited_folders += 1 if node.hasChildren() and depth > 0: children = node.children() for child in children: self.__countOmmited(child, extract_original, depth-1) else: self.ommited_files += 1 dff-1.3.0+dfsg.1/dff/api/vfs/fdmanager.cpp000066400000000000000000000047201217176075400201030ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "fdmanager.hpp" #include "threading.hpp" FdManager::FdManager() { mutex_init(&this->__mutex); this->fds.assign(16384, (fdinfo*)0); this->allocated = 0; } FdManager::~FdManager() { mutex_destroy(&this->__mutex); } fdinfo* FdManager::get(int32_t fd) { fdinfo* fi; mutex_lock(&this->__mutex); if (fd > (int32_t)this->fds.size()) { mutex_unlock(&this->__mutex); throw(vfsError("fdmanager::get -> Provided fd is too high")); } else { fi = this->fds[fd]; if (fi != 0) { mutex_unlock(&this->__mutex); return fi; } else { mutex_unlock(&this->__mutex); throw(vfsError("fdmanager::get -> fd not allocated")); } } mutex_unlock(&this->__mutex); } int32_t FdManager::push(fdinfo* fi) { uint32_t i; bool empty; mutex_lock(&this->__mutex); empty = false; if (this->allocated == this->fds.size()) { mutex_unlock(&this->__mutex); throw(vfsError("fdmanager::push -> there is no room for new fd")); } else { i = 0; while ((i < this->fds.size()) && !empty) { if (this->fds[i] == 0) empty = true; else i++; } if (empty && (i < this->fds.size())) { this->allocated++; this->fds[i] = fi; mutex_unlock(&this->__mutex); return i; } else { mutex_unlock(&this->__mutex); throw(vfsError("fdmanager::push -> new fd allocation failed")); } } mutex_unlock(&this->__mutex); } void FdManager::remove(int32_t fd) { fdinfo* fi; mutex_lock(&this->__mutex); if (fd > (int32_t)this->fds.size()) { std::cout << "fdmanager::remove -> fd not allocated" << std::endl; //throw(vfsError("fdmanager::remove -> fd not allocated")); } else { fi = this->fds[fd]; if (fi != 0) { delete fi; this->fds[fd] = 0; this->allocated--; } } mutex_unlock(&this->__mutex); } dff-1.3.0+dfsg.1/dff/api/vfs/filemapping.cpp000066400000000000000000000244141217176075400204540ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "node.hpp" #include "filemapping.hpp" FileMapping::FileMapping(Node* node) { this->__node = node; this->__maxOffset = 0; this->__prevChunk = NULL; this->__refcount = 1; mutex_init(&this->__fm_mutex); } FileMapping::~FileMapping() { uint32_t i; for (i = 0; i != this->__chunks.size(); i++) { if (this->__chunks[i] != NULL) { this->__chunks[i] = NULL; delete this->__chunks[i]; } } mutex_destroy(&this->__fm_mutex); } void FileMapping::addref(void) { mutex_lock(&this->__fm_mutex); this->__refcount++; mutex_unlock(&this->__fm_mutex); } void FileMapping::delref(void) { mutex_lock(&this->__fm_mutex); this->__refcount--; if (this->__refcount == 0) { delete this; return ; } mutex_unlock(&this->__fm_mutex); } uint64_t FileMapping::refcount(void) { uint64_t count; mutex_lock(&this->__fm_mutex); count = this->__refcount; mutex_unlock(&this->__fm_mutex); return count; } Node* FileMapping::node(void) { return (this->__node); } uint32_t FileMapping::chunkCount() { return this->__chunks.size(); } chunk* FileMapping::chunkFromIdx(uint32_t idx) { if (idx < this->__chunks.size()) return this->__chunks[idx]; else return NULL; } std::vector FileMapping::chunksFromIdxRange(uint32_t begidx, uint32_t endidx) { std::vector v; uint32_t vsize; std::vector::iterator begit; std::vector::iterator endit; vsize = this->__chunks.size(); if ((begidx < endidx) && (begidx < vsize) && (endidx < vsize)) { begit = this->__chunks.begin()+begidx; endit = this->__chunks.begin()+endidx; v.assign(begit, endit); } return v; } std::vector FileMapping::chunksFromOffsetRange(uint64_t begoffset, uint64_t endoffset) { std::vector v; uint32_t begidx; uint32_t endidx; if ((begoffset > endoffset) || (begoffset > this->__maxOffset) || (endoffset > this->__maxOffset)) throw("provided offset too high"); try { begidx = this->chunkIdxFromOffset(begoffset); endidx = this->chunkIdxFromOffset(endoffset); v = this->chunksFromIdxRange(begidx, endidx); } catch (...) { } return v; } chunk* FileMapping::firstChunk() { if (this->__chunks.size() > 0) return this->__chunks.front(); else return NULL; } chunk* FileMapping::lastChunk() { if (this->__chunks.size() > 0) return this->__chunks.back(); else return NULL; } std::vector FileMapping::chunks() { return this->__chunks; } uint32_t FileMapping::__bsearch(uint64_t offset, uint32_t lbound, uint32_t rbound, bool* found) { uint32_t mbound; if (rbound < lbound) return rbound; mbound = (rbound + lbound) / 2; if (offset < this->__chunks[mbound]->offset) { if (mbound > 0) return this->__bsearch(offset, lbound, mbound - 1, found); else return 0; } else if (offset > this->__chunks[mbound]->offset + this->__chunks[mbound]->size - 1) return this->__bsearch(offset, mbound + 1, rbound, found); else { *found = true; return mbound; } } chunk* FileMapping::chunkFromOffset(uint64_t offset) { chunk* chk; uint32_t idx; bool found; mutex_lock(&this->__fm_mutex); found = false; if (this->__chunks.size() == 0) { mutex_unlock(&this->__fm_mutex); throw(std::string("file mapping is empty")); } if (offset > this->__maxOffset) { mutex_unlock(&this->__fm_mutex); throw("provided offset too high"); } if (this->__chunks.size() == 1) { //if there's only one chunk, there are two possibilities: // - either file's mapping is represented by only one chunk starting from 0 // - or file's mapping is partial and only represents parts of the file. The stored chunk starts from an offset != 0 chk = this->__chunks[0]; //first, check if stored chunk contains the requested offset if (offset >= chk->offset && offset <= chk->offset + chk->size - 1) { mutex_unlock(&this->__fm_mutex); return chk; } // if not, it means the offset is lesser than the starting offset of the stored chunk // if offset is greater than chk->offset + chk->size, an exception has been raised (offset > __maxOffset) else { // a virtual chunk is created and is treated as a buffer full of 0 in mfso::readFromMapping chk = new chunk; chk->offset = 0; chk->size = this->__chunks[0]->offset; chk->origin = NULL; chk->originoffset = 0; this->__chunks.insert(this->__chunks.begin(), chk); mutex_unlock(&this->__fm_mutex); return chk; } } else { //otherwise, there are at least 2 chunks and two possibilities: // - either the chunk containing the requested offset is found // - or the chunk containing thes requested offset is NOT found idx = this->__bsearch(offset, 0, this->__chunks.size() - 1, &found); if (found) { mutex_unlock(&this->__fm_mutex); return this->__chunks[idx]; } else { //__bsearch always provide the left-most chunk meaning provided offset //is greater than chunk[idx]->offset + chunk[idx]->size - 1. //We need to map the gap //If returned idx is the last chunk, check if size of node is greater than //chunks[idx]->offset + chunks[idx]->size ? //at the moment, we throw an exception if (idx == this->__chunks.size() - 1) { mutex_unlock(&this->__fm_mutex); throw(std::string("no more chunk available. file is not complete")); } //if idx is the first chunk, it means first part of the mapping of the file is //missing. A virtual chunk is created to fill the gap. else if (idx == 0) { if (offset < this->__chunks[0]->offset) { //std::cout << "offset < this->__chunks[0]->offset" << std::endl; chk = new chunk; chk->offset = 0; chk->size = this->__chunks[0]->offset; chk->origin = NULL; chk->originoffset = 0; this->__chunks.insert(this->__chunks.begin(), chk); mutex_unlock(&this->__fm_mutex); return chk; } else { chk = new chunk; //std::cout << "offset > this->__chunks[0]->offset" << std::endl; chk->offset = this->__chunks[0]->offset + this->__chunks[0]->size; chk->size = this->__chunks[1]->offset - chk->offset; chk->origin = NULL; chk->originoffset = 0; this->__chunks.insert(this->__chunks.begin()+1, chk); mutex_unlock(&this->__fm_mutex); return chk; } } //requested offset is in the middle of two mapped chunks. A virtual chunk //is created which fill the gap. else { chk = new chunk; //std::cout << idx << " < offset < " << (idx + 1) << std::endl; chk->offset = this->__chunks[idx]->offset + this->__chunks[idx]->size; chk->size = this->__chunks[idx+1]->offset - chk->offset; chk->origin = NULL; chk->originoffset = 0; this->__chunks.insert(this->__chunks.begin()+idx+1, chk); mutex_unlock(&this->__fm_mutex); return chk; } } } } uint32_t FileMapping::chunkIdxFromOffset(uint64_t offset, uint32_t sidx) { uint32_t idx; chunk* chk; bool found; if (offset > this->__maxOffset) throw("provided offset too high"); if (this->__chunks.size() == 0) throw(std::string("provided offset is not mapped")); if (sidx > this->__chunks.size() - 1) throw(std::string("provided idx is too high")); if (this->__chunks.size() == 1) { chk = this->__chunks[0]; if (offset >= chk->offset && offset <= chk->offset + chk->size - 1) return 0; else throw(std::string("provided offset is not mapped")); } else { idx = this->__bsearch(offset, sidx, this->__chunks.size() - 1, &found); if (found) return idx; else throw(std::string("provided offset is not mapped")); } } void FileMapping::allocChunk(uint64_t offset, uint64_t size, class Node* origin, uint64_t originoffset) { std::vector::iterator it; uint32_t idx; chunk *c; bool found; found = false; if (this->__chunks.size() == 0) it = this->__chunks.begin(); else if (this->__chunks.size() == 1) { if (offset < this->__chunks[0]->offset) it = this->__chunks.begin(); else if (offset > (this->__chunks[0]->offset + this->__chunks[0]->size - 1)) it = this->__chunks.begin() + 1; else throw (std::string("provided offset is already mapped !")); } else { idx = this->__bsearch(offset, 0, this->__chunks.size() - 1, &found); if (found) throw (std::string("provided offset is already mapped !")); if (idx >= 1) { if (idx == this->__chunks.size() - 1) { if (offset >= (this->__chunks[idx-1]->offset + this->__chunks[idx-1]->size)) it = this->__chunks.end(); else throw (std::string("provided offset is already mapped !")); } else if (offset >= (this->__chunks[idx-1]->offset + this->__chunks[idx-1]->size) && (offset + size) <= this->__chunks[idx+1]->offset) it = this->__chunks.begin() + idx + 1; else throw (std::string("provided offset is already mapped !")); } else if ((offset + size) <= this->__chunks[idx]->offset) it = this->__chunks.begin(); else throw (std::string("provided offset is already mapped !")); } c = new chunk; c->offset = offset; c->size = size; if (this->__maxOffset < offset + size) this->__maxOffset = offset + size; c->origin = origin; c->originoffset = originoffset; this->__chunks.insert(it, c); this->__prevChunk = c; } void FileMapping::push(uint64_t offset, uint64_t size, class Node* origin, uint64_t originoffset) { this->allocChunk(offset, size, origin, originoffset); } uint64_t FileMapping::maxOffset() { return this->__maxOffset; } dff-1.3.0+dfsg.1/dff/api/vfs/fso.cpp000066400000000000000000000042641217176075400167510ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "fso.hpp" fso::fso(std::string name) { this->name = name; this->stateinfo = ""; this->__uid = VFS::Get().registerFsobj(this); this->__parent = NULL; } fso::~fso() { } uint64_t fso::nodeCount() { return this->__nodes.size(); } std::vector fso::children() { return this->__children; } bool fso::hasChildren() { return this->__children.size() > 0; } uint32_t fso::childCount() { return this->__children.size(); } void fso::setParent(fso* parent) { if (parent != NULL) { this->__parent = parent; } } fso* fso::parent() { return this->__parent; } void fso::addChild(fso* child) { if (child != NULL) { child->setParent(this); this->__children.push_back(child); } } void fso::registerTree(Node* parent, Node* head) { event* e = new event; e->value = Variant_p(new Variant(head)); fso* pfsobj; if (((pfsobj = parent->fsobj()) != NULL) && (pfsobj != this)) pfsobj->addChild(this); //AttributesIndexer::Get().registerAttributes(head); parent->addChild(head); VFS::Get().notify(e); } std::vector fso::nodes() { return this->__nodes; } uint16_t fso::uid() { return this->__uid; } Node* fso::getNodeById(uint64_t id) { uint64_t nid; uint16_t fsoid; fsoid = id >> 48; if (fsoid == this->__uid) { nid = id & 0x0000ffffffffffffLL; if (nid < this->__nodes.size()) return this->__nodes[nid]; else return NULL; } else return NULL; } uint64_t fso::registerNode(Node* n) { uint64_t nid; nid = this->__uid; nid = nid << 48; this->__nodes.push_back(n); nid |= this->__nodes.size() - 1; return nid; } dff-1.3.0+dfsg.1/dff/api/vfs/iodevice.py000066400000000000000000000035101217176075400176100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from PyQt4.QtCore import SIGNAL, QIODevice class IODevice(QIODevice): def __init__(self, node): super(QIODevice, self).__init__() self.connect(self, SIGNAL('aboutToClose'), self.__close) self.file = None self.node = node def __del__(self): if self.file: self.__close() def open(self, mode = None): try : self.file = self.node.open() self.setOpenMode(QIODevice.ReadOnly | QIODevice.Unbuffered) return True except (AttributeError, IOError): return False def seek(self, pos): if self.file : n = self.file.seek(pos) if n == pos: return True return False def __close(self): self.file.close() self.file = None return True def readData(self, size): if self.file: return self.file.read(size) return "" def pos(self): if self.file: return long(self.file.tell()) return 0 def isSequential(self): return False def size(self): return long(self.node.size()) def reset(self): if self.file: self.file.seek(0) return True return False def atEnd(self): if self.file: if self.file.tell() >= self.node.size(): return True return False dff-1.3.0+dfsg.1/dff/api/vfs/iostat.cpp000066400000000000000000000024731217176075400174650ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "iostat.hpp" IOStat& IOStat::getInstance() { static IOStat instance; return instance; } void IOStat::pushReadStats(uint16_t fsoid, uint64_t read) { if (this->__io.exist(fsoid)) this->__io[fsoid] += read; else this->__io[fsoid] = read; } void IOStat::pushInstanceStats(uint16_t fsoid) { if (this->__instances.exist(fsoid)) this->__instances[fsoid] += 1; else this->__instances[fsoid] = 1; } uint64_t IOStat::totalReadById(uint16_t fsoid) { uint64_t total; total = 0; if (this->__io.exist(fsoid)) total = this->__io[fsoid]; return total; } uint64_t IOStat::totalInstanceById(uint16_t fsoid) { uint64_t total; total = 0; if (this->__instances.exist(fsoid)) total = this->__instances[fsoid]; return total; } dff-1.3.0+dfsg.1/dff/api/vfs/libvfs.i000066400000000000000000000653261217176075400171230ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module(package="dff.api.vfs",docstring="libvfs: c++ generated inteface", directors="1") libvfs %feature("autodoc", 1); //1 = generate type for func proto, no work for typemap %feature("docstring"); %feature("docstring") FileMapping " Most of the time (with a few exceptions), nodes in DFF are associated with a set of meta-data and a content. For example, a file system driver will parse the real file system of a dump or device and then create one node for each files and directories. These files are associated with content, such as pictures, text, videos, etc. The content of a file is located somewhere on the dump and can be found by following the file system specification. For each modules, the specification is different so file content position will be different. As far as each file systems and dumps do not have the same specification and content, it is necessary to have a standard way to represent their content position in DFF. The FileMapping class is used to give this standard way to describe file content positions on the dump. So when the file is opened its content can be displayed in DFF interface using a viewer. File content can be fragmented on the disk so generally there are several chunks to describe the entire content of a file, especially on big files. More precisely, the FileMapping class contains a list of chunks giving the different offsets of the file blocks on the vfile. Each chunks are used to describe one of these different positions on the vfile by providing two informations : * the offset of the data on the vfile * the size it occupies In other words, the chunk's list will, for each areas the file occupies, give its begining offset and its size. We could say something like : * The file `foo` first chunk start at offset 0x42 and occupies 10 bytes. * The second chunk of `foo` file starts at offset 0x84 and occupies 20 bytes. * etc. For example, lets imagine we open a 100 bytes big node which is fragmented in three parts. When mapping the file, three chunks will be created and will look like this : * chunk 1 => offset : x; size : s bytes * chunk 1 => offset : y; size : t bytes * chunk 1 => offset : z; size : u bytes The sum `s + t + u` should be equal to the file size (100 bytes in our example). The \"main\" method of FileMapping class is push, which must be called to create the different chunks. This method muts be called in the Node::fileMapping method, which is called by DFF when the node is opened. " %feature("docstring") FileMapping::mappedFileSize " Return the total size of the different chunks. Should be equal to the node size. " %feature("docstring") FileMapping::chunkCount " Return the number of mapped chunks. " %feature("docstring") FileMapping::firstChunk " Return a pointer to the first chunk of the list. " %feature("docstring") FileMapping::lastChunk " Return a pointer to the last chunk of the list. " %feature("docstring") FileMapping::chunkFromIdx " Return a pointer on the chunk structure corresponding to index `idx` in the list of chunk. " %feature("docstring") FileMapping::chunkFromOffset " Return a pointer to the chunk in which offset `offset` is. " %feature("docstring") fso " The fso or 'File System Object' class is the base class of the API. All modules must inheritates it (or inherit mfso, which itself inherit fso). It provides several virtual methods which must be reimplemented, such as start, vopen, vread, vwrite, vclose and vseek. They are used to read, open, write and seek within the content of a node. The start method does the job the module is supposed to do. This is the method which is called when a module is launched. The main difference between fso and mfso is the fact that the open, read and seek method are pure virtual in fso and virtual in mfso. Indeed, using the fso class rather than the mfso class, where implentations of open and read are provided, supposes that the developer of the module does not wish to use the FileMapping system. The behaviour, use and prototype of methods open, read and seek are pretty similar to their UNIX equivalent. The vwrite method is generally not used, and even left empty in modules implementations. " %feature("docstring") fso::start " This method is called when the module starts. It does the job the module is supposed to do. This method is declared as a pure virtual so each modules must reiplements it (see the developer's documentations for more details) in python or C++, depending on which language you choose. The parameter 'args' is a pointer to the arguments list which were passed to the module when it was launched. You can get them by using the method args->get(\"arg_name\", &variable) where variable must be of the same type than the argument \"arg_name\" If you create nodes, you must not forget to call the method register_tree at the end of the module execution. If an error occured while getting a parameter, a envError exception is thrown. Params : * args : the list of arguments passed to the module. " %feature("docstring") fso::vopen " Open a node. Param : * n : the node you want to open Return the opened file descriptor, or 0 if it failed. " %feature("docstring") fso::vread " vread(self, int32_t fd, void rbuff, uint32_t size) -> int32_t Perform readings on an open node and returns the number of bytes which wereread. Params : * fd : the file descriptor of the node you want to read on. * rbuff : a pointer to an allocated buffer where the read bytes will be stored * size : the number of characters you want to read. Return the number of read characters. " %feature("docstring") fso::vwrite " Not used. " %feature("docstring") fso::vclose " Close an open file descriptor and make it available again for others openings. Return `0` if everything went fine, `0` otherwise. " %feature("docstring") fso::vseek " vseek(self, int32_t fd, uint64_t offset, int32_t whence) -> uint64_t This method is used to change position within an open node (i.e. modifies the offset of the current position). The offset is set to 0 when the file is open. Throws a vfsError if something goes wrong (typically if the seeking position is after the end of the file). It takes three parameters : * a file descriptor of an open node * the offset where you want to seek * the third parameter is optional : it defines if the offset passed in second parameter is absolute or relative. Return an uint64_t " %feature("docstring") fso::status " Return the status of the module. " %feature("docstring") fso::vtell " Returns the current offset in a file. " %feature("docstring") fso::setVerbose " Set the module in verbose mode if the param `verbose` is et to `true`, shutdown the verbose mode otherwise. Verbose mode should not be enabled in production environment. Params : * verbose : the verbosity " %feature("docstring") fso::verbose " Return `true` if the module is in verbose mode, `false` otherwise. " %feature("docstring") mfso " The mfso purpose has pretty the same role as the fso one. It inheritates fso. The main difference is based on the file mapping : the fso class do not use file mapping, mfso uses it. The mfso class provides implementations for the vopen, vread and vseek methods and a file descriptor manager (which not the case in the fso interface). It provides an abstraction of the node's content to developers, making the code easier to write. File mapping is detailed in libvfs.fileMapping. " %feature("docstring") mfso::start " start(self, argument args) This method is pure virtual in mfso so musts be implemented while developing a module. This method is called when the module starts. It does the job the module is supposed to do. This method is declared as a pure virtual so each modules must reiplements it (see the developer\'s documentations for more details) in python or C++, depending on which language you choose. The parameter \'args\' is pointer to the arguments list which were passed to the module when it was launched. You can get them by using the method args->get(\"arg_name\", &variable) where variable must be of the same type than the argument \"arg_name\" If you create nodes, you must not forget to call the method register_tree at the end of the module execution. If an error occured while getting a parameter, a envError exception is thrown. Params : * args : the list of arguments. " %feature("docstring") mfso::open " Open the node `n`. Params : * n : the node you want to open. An implentation of this method is provided with mfso, so developers should not have to reimplement it. " %feature("docstring") mfso::vread " Perform readings on an open node and returns the number of bytes which were read. The reading is performed at the current offset on the file. If the user tries to read more bytes that they are in the file, read will stop reading at the end of the file and return the actual number of read characters. Params : * fd : the file descroiptor of the node you want to read on. * buff : a pointer to an allocated buffer where the read bytes will be stored * size : the number of characters you want to read. Throw a vfsError if something goes wrong. An implentation of this method is provided with mfso, so developers should not have to reimplement it. Return the number of read characters. " %feature("docstring") mfso::vwrite " Not used in most cases. " %feature("docstring") mfso::vclose " Close an open file descriptor and make it available again for others openings. An implentation of this method is provided with mfso, so developers should not have to reimplement it. Params : * fd : the file decsriptor you want to close. Return 0. " %feature("docstring") mfso::vseek " This method is used to change offset within an open node. The offset is set to 0 when the file is open. Throws a vfsError if something goes wrong (typically if the seeking position is after the end of the file). Params : * fd : a file descriptor of an open node * offset : the offset where you want to seek * whence : the third parameter is optional : it defines if the offset passed in second parameter is absolute or relative. An implentation of this method is provided with mfso, so developers should not have to reimplement it. Return of how many bytes the position changed. " %feature("docstring") mfso::vtell " Returns the current offset in a file. An implentation of this method is provided with mfso, so developers should not have to reimplement it. Param : * fd : the file descriptor of the node on which you want to use vtell. " %feature("docstring") mfso::setVerbose """ setVerbose(self, bool verbose) Set the module in verbose mode if the param `verbose` is set to `true`, shutdown the verbose mode otherwise. """ %feature("docstring") mfso::verbose """ verbose(self) -> bool Return `true` if the module is in verbose mode, `false` otherwise. """ %feature("docstring") Node " This class is the base interface of every nodes reprensented in DFF virtual file system tree view. Most of the modules will have to extend this class before using it, that is why some of the methods are virtual. " %feature("docstring") Node::setId " Set an ID of type uint32_t Params : * id : the id you want to set to node. " %feature("docstring") Node::id " Return the ID. " %feature("docstring") Node::setFile " If the node is a file this method should be called to set proper attributes. " %feature("docstring") Node::setDir " If the node is a directory this method should be called to set proper attributes. " %feature("docstring") Node::setLink " If the node is a link this method should be called to set proper attributes. " %feature("docstring") Node::setDeleted " If the node corresponds to a data which was deleted (and recovered by the module), this method should be called to set proper attributes. " %feature("docstring") Node::setSize " Set the node size in bytes. " %feature("docstring") Node::setFsobj " Set a fso object. " %feature("docstring") Node::setParent " Set the parent's node of the current node. " %feature("docstring") Node::fileMapping " The fileMapping method takes a pointer to an instance of a FileMapping object as parameter. This method is called when a node is opened. The fileMapping method must \"filled up\" the FileMapping object which was passed to it by creating chunks of the files. A chunk is a structure containing 2 important informations : * The size (in bytes) of the chunk * Its address on the vfile. In human speakable langugage it means that the FileMapping structure contains a list of data structure, each of them giving a part of the file content position on the vfile. FileMapping can be filled up by calling their push() method. " %feature("docstring") Node::extendedAttributes " This method is used to set extended attributes to a node. It takes a pointer to an Attributes instance as parameter. This parameter can be filled up with attributes of any types by using the Variant type. ExtendedAttributes can be filled up by calling their push() method. " %feature("docstring") Node::modifiedTime " Set the time of last modification " %feature("docstring") Node::accessedTime " Set the time of last access " %feature("docstring") Node::createdTime " Set the time of creation " %feature("docstring") Node::changedTime " Set the time of last change " %feature("docstring") Node::times " Return a map containing the different time informations on a node. " %feature("docstring") Node::size " Return the size of the node " %feature("docstring") Node::path " return the path to the node " %feature("docstring") Node::name " return the name of the node " %feature("docstring") Node::absolute " return the absolute path of the node (equivalent to Node::path() + Node::name()) " %feature("docstring") Node::isFile " return true if the node is a file, false otherwise " %feature("docstring") Node::isDir " return true if the node is a directory, false otherwise " %feature("docstring") Node::isLink " return true if the node is a link, false otherwise " %feature("docstring") Node::isVDir " return true if the node is a link to a directory, false otherwise " %feature("docstring") Node::isDeleted " return true if the node is deleted, false otherwise " %feature("docstring") Node::fsobj " return a pointer to fso instance associated with the node " %feature("docstring") Node::parent " return a pointer to the node which is the parent of the cuurent node. " %feature("docstring") Node::children " return a vector containing pointers to the children of the current node. If the node has no child, the vector is empty. " %feature("docstring") Node::addChild " Take a pointer to a node in parameter. This node will be added to the current node as one of its child. " %feature("docstring") Node::hasChildren " return true if the node has one or more children, false otherwise " %feature("docstring") Node::childCount " return the number of children the node has " %feature("docstring") Node::open " Open the node and return a pointer to a VFile instance " %feature("docstring") VLink " The class VLink inherits the Node class. It a specific type of Node corresponding to a link to an other node. This class can be useful to create nodes \"pointing\" on other nodes, such as Linux symbolic links or Windows short-cuts for example. Otherwise, the VLink class is pretty similar to the Node class. " %feature("docstring") VLink::__init__ " Constructor. Params : * linkedNode * parent : the parent's node of the VLink * newname : the name of the node (empty by default) " %feature("docstring") VLink::linkPath " Return the path to the pointed node. " %feature("docstring") VLink::linkName " Return the name of the pointed node. " %feature("docstring") VLink::linkAbsolute " Return the absolute path + name of the pointed node. Is equivalent to VLink::linkPath() + \"/\" + VLink::linkName() " %feature("docstring") VLink::linkParent " Return a pointer to the parent node of the pointed node. " %feature("docstring") VLink::linkChildren " Return the list of children of the pointed node. " %feature("docstring") VLink::linkHasChildren " Return `true` if the pointed node has children, `false` otherwise. " %feature("docstring") VLink::linkChildCount " Return the number of child the pointed nodes has. " %feature("docstring") VLink::linkNode " Return a pointer to the node pointed by the link. " %feature("docstring") Attributes " The Attributes class is designed to store a list of attributes related to a Node, such as, among others, time informations, file mode or UNIX access rights for example. Each attributes are made of a string describing the attribute and a value, which is Variant type. For more precisions on Variant, see the Variant documentation. " %feature("docstring") Attributes::push " push(self, string key, Variant value) Add an attribute to the attributes list. Params : * key : the description of the attributes. * value : the value of the attribute " %feature("docstring") Attributes::keys " keys(self) -> std::list<(std::string,std::allocator<(std::string)>)> Returns a std::list where each values are a key of attributes. " %feature("docstring") Attributes::value " value(self, string key) -> Variant Return the value of the attributes which key is `key` " %feature("docstring") Attributes::attributes " attributes(self) -> std::map<(std::string,p.Variant,std::less<(std::string)>,std::allocator<(std::pair<(q(const).std::string,p.Variant)>)>)> Return a std::map which contains the entire list of attributes " %feature("docstring") FdManager " The FdManager is used to manage all open file descriptors. " %feature("docstring") FdManager::get " Return a pointer to the fdinfo structure correponding to file descriptor `fd` Params : * fd : the file decsriptor on which you want to get the fdinfo structure " %feature("docstring") FdManager::remove " Free the resources occupied by the fdinfo structure correponding to `fd` " %feature("docstring") FdManager::push " Push the fdinfo `fi` into the list of opened file descriptors. " #pragma SWIG nowarn=473 %warnfilter(SWIGWARN_IGNORE_OPERATOR_EQ,SWIGWARN_LANG_IDENTIFIER); %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "std_except.i" #ifndef WIN32 %include "stdint.i" #elif _MSC_VER >= 1600 %include "stdint.i" #else %include "wstdint.i" #endif %include "windows.i" %feature("director") fso; %feature("director") mfso; %feature("director") Node; %feature("director") VLink; %feature("director") AttributesHandler; %newobject VFile::search; %newobject VFile::indexes; %newobject Node::open; %newobject VLink::open; %newobject TagsManager::tags; /* %feature("director:except") fso */ /* { */ /* if ($error != NULL) */ /* { */ /* throw Swig::DirectorMethodException(); */ /* } */ /* } */ /* %feature("director:except") mfso */ /* { */ /* if ($error != NULL) */ /* { */ /* throw Swig::DirectorMethodException(); */ /* } */ /* } */ /* %feature("director:except") Node */ /* { */ /* if ($error != NULL) */ /* { */ /* throw Swig::DirectorMethodException(); */ /* } */ /* } */ /* %feature("director:except") VLink */ /* { */ /* if ($error != NULL) */ /* { */ /* throw Swig::DirectorMethodException(); */ /* } */ /* } */ %import "../exceptions/libexceptions.i" //XXX fix iterator ! %typemap(out) (Node*) { //#int dcast = 0; VLink *dobj = dynamic_cast($1); if (dobj) { %set_output(SWIG_NewPointerObj(dobj, SWIGTYPE_p_VLink, $owner | %newpointer_flags)); } else { %set_output(SWIG_NewPointerObj($1, SWIGTYPE_p_Node, $owner | %newpointer_flags)); } } %typemap(directorargout) (int32_t fd, void *rbuff, uint32_t size) { memcpy((char *)rbuff, PyString_AsString($input) , PyString_Size($input)); } %typemap(out) pdata* { Py_XDECREF($result); $result = PyString_FromStringAndSize((const char *)$1->buff, $1->len); free($1->buff); delete $1; } %typecheck(SWIG_TYPECHECK_CHAR) unsigned char { $1 = (((PyString_Check($input) && ((PyString_Size($input) == 1) || PyString_Size($input) == 0))) || (PyInt_Check($input) && ((PyInt_AsLong($input) >= 0) && (PyInt_AsLong($input) <= 255)))) ? 1 : 0; } %typemap(in) (unsigned char wildcard) { if (!PyString_Check($input) || (PyString_Size($input) > 1)) { PyErr_SetString(PyExc_ValueError, "Expecting a string"); return NULL; } $1 = (unsigned char) PyString_AsString($input)[0]; } %ignore VFile::find(unsigned char* needle, uint32_t nlen); %ignore VFile::find(unsigned char* needle, uint32_t nlen, unsigned char wildcard); %ignore VFile::find(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start); %ignore VFile::find(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end); %ignore VFile::rfind(unsigned char* needle, uint32_t nlen); %ignore VFile::rfind(unsigned char* needle, uint32_t nlen, unsigned char wildcard); %ignore VFile::rfind(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start); %ignore VFile::rfind(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end); %ignore VFile::count(unsigned char* needle, uint32_t nlen); %ignore VFile::count(unsigned char* needle, uint32_t nlen, unsigned char wildcard); %ignore VFile::count(unsigned char* needle, uint32_t nlen, unsigned char wildcard, int32_t maxcount); %ignore VFile::count(unsigned char* needle, uint32_t nlen, unsigned char wildcard, int32_t maxcount, uint64_t start); %ignore VFile::count(unsigned char* needle, uint32_t nlen, unsigned char wildcard, int32_t maxcount, uint64_t start, uint64_t end); %ignore VFile::indexes(unsigned char* needle, uint32_t nlen); %ignore VFile::indexes(unsigned char* needle, uint32_t nlen, unsigned char wildcard); %ignore VFile::indexes(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start); %ignore VFile::indexes(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end); %{ #include "rc.hpp" #include "tags.hpp" #include "eventhandler.hpp" #include "vfs.hpp" #include "exceptions.hpp" #include "fdmanager.hpp" #include "filemapping.hpp" #include "export.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "variant.hpp" #include "vtime.hpp" #include "path.hpp" #include "iostat.hpp" #include "rootnode.hpp" %} %import "../types/libtypes.i" %refobject RCObj "$this->addref();" %unrefobject RCObj "$this->delref();" %import "../events/libevents.i" %include "../include/rc.hpp" %include "../include/tags.hpp" %include "../include/vfs.hpp" %include "../include/export.hpp" %include "../include/fdmanager.hpp" %include "../include/filemapping.hpp" %include "../include/exceptions.hpp" %include "../include/fso.hpp" %include "../include/mfso.hpp" %include "../include/node.hpp" %include "../include/vlink.hpp" %include "../include/vfile.hpp" %include "../include/iostat.hpp" %include "../include/rootnode.hpp" %extend_smart_pointer(Tag_p); %template(RCPtrTag) Tag_p; namespace std { %template(VecNode) vector; %template(ListNode) list; %template(SetNode) set; %template(VectChunk) vector; %template(Listui64) list; %template(Vectui64) vector; %template(Vectui32) vector; %template(MapTime) map; %template(MapNameTypes) map; %template(FsoVect) vector; %template(RCPtrTagVect) vector; }; /* %traits_swigtype(Variant); */ /* %fragment(SWIG_Traits_frag(Variant)); */ %traits_swigtype(vtime); %fragment(SWIG_Traits_frag(vtime)); %extend VFile { %pythoncode %{ def __iter__(self): return self def next(self): cpos = self.tell() idx = self.find('\n') if idx != -1: self.seek(cpos) buff = self.read(idx - cpos+1) if len(buff) == 0: raise StopIteration() else: return buff else: raise StopIteration() %} }; %extend VFS { #ifdef SWIGWORDSIZE64 PyObject* getNodeFromPointer(unsigned long pnode) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyObject* obj; VLink *dobj = dynamic_cast(((Node*)pnode)); if (dobj) { obj = SWIG_NewPointerObj(dobj, SWIGTYPE_p_VLink, 0); } else { obj = SWIG_NewPointerObj((void*)pnode, SWIGTYPE_p_Node, 0); } SWIG_PYTHON_THREAD_END_BLOCK; return obj; } #else PyObject* getNodeFromPointer(unsigned int pnode) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyObject* obj; VLink *dobj = dynamic_cast(((Node*)pnode)); if (dobj) { obj = SWIG_NewPointerObj(dobj, SWIGTYPE_p_VLink, 0); } else { obj = SWIG_NewPointerObj((void*)pnode, SWIGTYPE_p_Node, 0); } SWIG_PYTHON_THREAD_END_BLOCK; return obj; } #endif }; %extend Node { %pythoncode %{ def __iter__(self): for node in self.next: yield node %} }; dff-1.3.0+dfsg.1/dff/api/vfs/mfso.cpp000066400000000000000000000151441217176075400171250ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Solal Jacob */ #include #include #include #include "mfso.hpp" #include "threading.hpp" #include "cache.hpp" mfso::mfso(std::string name): fso(name) { this->__fdmanager = new FdManager(); this->__fmCache = new FileMappingCache(20); this->__verbose = false; } mfso::~mfso() { } FileMapping* mfso::mapFile(Node* node) { FileMapping* fm; fm = this->__fmCache->find(node); if (fm == NULL) { fm = new FileMapping(node); node->fileMapping(fm); this->__fmCache->insert(fm); } return fm; } int32_t mfso::vopen(Node *node) { fdinfo* fi = NULL; int32_t fd; if (node != NULL) { try { fi = new fdinfo; fi->offset = 0; fi->node = node; fd = this->__fdmanager->push(fi); return fd; } catch(...) { return (-1); } } else throw("Node null"); return (-1); } std::string hexlify(uint64_t val) { std::ostringstream os; os << "0x" << std::hex << val; return os.str(); } void mfso::setVerbose(bool verbose) { this->__verbose = verbose; } bool mfso::verbose() { return this->__verbose; } int32_t mfso::readFromMapping(FileMapping* fm, fdinfo* fi, void* buff, uint32_t size) { VFile* vfile; chunk* current; uint64_t relativeoffset; uint32_t currentread; uint32_t totalread; bool eof; uint32_t relativesize; CacheContainer* container; VFilePool& vfilePool = VFilePool::instance(); //this->vfilePool ? eof = false; totalread = 0; while ((totalread < size) && (!eof)) { try { current = fm->chunkFromOffset(fi->offset); relativeoffset = current->originoffset + (fi->offset - current->offset); if ((size - totalread) < (current->offset + current->size - fi->offset)) relativesize = size - totalread; else relativesize = current->offset + current->size - fi->offset; if (current->origin != NULL) { if (this->__verbose == true) { std::cout << "[" << this->name << "] reading " << fi->node->absolute() << std::endl << " " << hexlify(fi->offset) << "-" << hexlify(fi->offset + relativesize) << " mapped @ " << hexlify(relativeoffset) << "-" << hexlify(relativeoffset + relativesize) << " in " << current->origin->absolute() << std::endl; } container = vfilePool.find(current->origin); if (container == NULL) vfile = current->origin->open(); else vfile = (VFile*)container->content; //vfile = current->origin->open(); vfile->seek(relativeoffset); if ((currentread = vfile->read(((uint8_t*)buff) + totalread, relativesize)) == 0) eof = true; if (container != NULL) vfilePool.unused(container); else vfilePool.insert(vfile); //vfile->close(); fi->offset += currentread; totalread += currentread; } else if (current->size != 0) { memset((uint8_t*)buff+totalread, 0, relativesize); if (this->__verbose == true) { std::cout << "[" << this->name << "] reading " << fi->node->absolute() << std::endl << " " << hexlify(fi->offset) << "-" << hexlify(fi->offset + relativesize) << " mapped @ " << hexlify(relativeoffset) << "-" << hexlify(relativeoffset + relativesize) << " in shadow node" << std::endl; } fi->offset += relativesize; totalread += relativesize; } else { throw("chunk is not valid"); } } catch(...) { eof = true; } } return (totalread); } int32_t mfso::vread(int32_t fd, void *buff, uint32_t size) { fdinfo* fi; uint64_t realsize; int32_t bytesread; FileMapping* fm = NULL; try { fi = this->__fdmanager->get(fd); if (fi->node != NULL) fm = this->mapFile(fi->node); if (fm != NULL) { uint64_t fileSize = fm->maxOffset(); if (fi->node->size() <= fileSize) { if (size <= (fi->node->size() - fi->offset)) realsize = size; else realsize = fi->node->size() - fi->offset; } else { if (size <= (fileSize - fi->offset)) realsize = size; else realsize = fileSize - fi->offset; } bytesread = this->readFromMapping(fm, fi, buff, realsize); fm->delref(); return bytesread; } else { return (0); } } catch(...) { //throw(vfsError("problem while reading file")); } if (fm) fm->delref(); return (0); } uint64_t mfso::vtell(int32_t fd) { fdinfo* fi; try { fi = this->__fdmanager->get(fd); return (fi->offset); } catch(vfsError e) { return ((uint64_t)-1); } } int32_t mfso::vwrite(int32_t fd, void *buff, unsigned int size) { return (0); } int32_t mfso::vclose(int32_t fd) { fdinfo* fi; try { fi = this->__fdmanager->get(fd); // delete fi; ? this->__fdmanager->remove(fd); } catch (vfsError e) { std::cout << "mfso::close vfserror " << e.error << std::endl; } return (0); } uint64_t mfso::vseek(int32_t fd, uint64_t offset, int32_t whence) { fdinfo* fi; FileMapping* fm; try { fi = this->__fdmanager->get(fd); fm = this->mapFile(fi->node); if (fm == NULL) throw std::string("can't allocate fm"); if (whence == 0) { if (offset > fm->maxOffset()) { fm->delref(); return ((uint64_t)-1); } else fi->offset = offset; } else if (whence == 1) { if ((fi->offset + offset) > fm->maxOffset()) { fm->delref(); return ((uint64_t)-1); } else fi->offset += offset; } else if (whence == 2) fi->offset = fm->maxOffset(); fm->delref(); return (fi->offset); } catch(...) { std::cout << "problem while getting fd information" << std::endl; } if (fm != NULL) fm->delref(); return ((uint64_t)-1); } uint32_t mfso::status(void) { return 0; } dff-1.3.0+dfsg.1/dff/api/vfs/node.cpp000066400000000000000000000556161217176075400171160ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin * Solal J. */ #include "cache.hpp" #include "fso.hpp" #include "vfile.hpp" #include "datatype.hpp" #include "tags.hpp" #include "confmanager.hpp" #include "node.hpp" Node::Node() { } Node::Node(std::string name, uint64_t size, Node* parent, fso* fsobj) { this->__common_attributes = 0; this->__childcount = 0; this->__at = 0; this->__fsobj = fsobj; this->__size = size; this->__parent = parent; if (this->__fsobj != NULL) this->__uid = this->__fsobj->registerNode(this); else if (parent != NULL) { this->__uid = VFS::Get().registerOrphanedNode(this); } else this->__uid = 0; if (this->__parent != NULL) { this->__parent->addChild(this); } this->__name = name; this->__tags = 0; } Node::~Node() { if (!this->__children.empty()) this->__children.clear(); } void Node::fileMapping(FileMapping *) { } void Node::setFsobj(fso *obj) { this->__fsobj = obj; } fso* Node::fsobj() { return this->__fsobj; } uint64_t Node::uid() { return this->__uid; } uint32_t Node::at() { return this->__at; } void Node::setId(uint32_t id) { this->__id = id; } uint32_t Node::id() { return this->__id; } std::string Node::name() { return this->__name; } std::string Node::extension() { size_t dpos; std::string ext; if ((dpos = this->__name.rfind(".")) != std::string::npos) ext = this->__name.substr(dpos+1); return ext; } std::string Node::absolute() { return this->path() + this->__name; } void Node::setParent(Node *parent) { if (parent != NULL) { this->__parent = parent; //this->__parent->addChild(this); } } Node* Node::parent() { return this->__parent; } bool Node::addChild(class Node *child) { if (child != NULL) { child->setParent(this); child->__at = this->__childcount; this->__children.push_back(child); this->__childcount++; return true; } return false; } std::vector Node::children() { return this->__children; } std::string Node::path() { std::string path; Node *tmp; if (this->__parent == this) return ""; path = ""; tmp = this->__parent; if (!tmp) { path = ""; return path; } while ((tmp->__parent != tmp) && (tmp->__parent != NULL)) { path = tmp->name() + "/" + path; tmp = tmp->parent(); } if (tmp->__parent == tmp) path = "/" + path; return path; } bool Node::hasChildren() { if (this->__childcount > 0) return true; else return false; } uint32_t Node::childCount() { return this->__childcount; } uint64_t Node::totalChildrenCount(uint32_t depth) { uint64_t totalsub; size_t i; totalsub = this->__childcount; if (depth != 0) { for (i = 0; i != this->__children.size(); i++) if (this->__children[i]->hasChildren()) totalsub += this->__children[i]->totalChildrenCount(depth-1); } return totalsub; } void Node::setSize(uint64_t size) { this->__size = size; } uint64_t Node::size() { return this->__size; } void Node::setFile() { if (!this->isDir()) this->__common_attributes |= ISFILE; else throw("attribute ISDIR already setted"); } bool Node::isFile() { if ((this->__common_attributes & ISFILE) == ISFILE) return true; else return false; } void Node::setDir() { if (!this->isFile()) this->__common_attributes |= ISDIR; else throw("attribute ISFILE already setted"); } bool Node::isDir() { if ((this->__common_attributes & ISDIR) == ISDIR) return true; else return false; } void Node::setLink() { this->__common_attributes |= ISLINK; } bool Node::isLink() { if ((this->__common_attributes & ISLINK) == ISLINK) return true; else return false; } bool Node::isVDir() { if (this->isFile() && this->hasChildren()) return true; else return false; } void Node::setDeleted() { this->__common_attributes |= ISDELETED; } bool Node::isDeleted() { if ((this->__common_attributes & ISDELETED) == ISDELETED) return true; else return false; } VFile* Node::open() { int32_t fd; VFile *temp; if (this->__fsobj == NULL) throw vfsError("Can't Open file"); try { if ((fd = this->__fsobj->vopen(this)) >= 0) { temp = new VFile(fd, this->__fsobj, this); return (temp); } throw vfsError("Can't Open file"); } catch (vfsError e) { throw vfsError("Node::open(void) throw\n" + e.error); } } std::string Node::icon(void) { if (!(this->hasChildren())) { if (this->isDir()) return (":folder_128.png"); if (!(this->size())) return (":folder_empty_128.png"); return (":folder_empty_128.png"); } else { if (this->size() != 0) return (":folder_documents_128.png"); else return (":folder_128.png"); } } Attributes Node::dataType(void) { Attributes types; class DataTypeManager* typeDB = DataTypeManager::Get(); types = typeDB->type(this); return types; } Attributes Node::_attributes(void) { Attributes attr; return (attr); } uint64_t Node::_attributesState(void) { return (0); } Attributes Node::fsoAttributes() { try { return AttributeCache::instance().find(this, this->_attributesState()); } catch (std::string) { Attributes attributes; try { attributes = this->_attributes(); AttributeCache::instance().insert(this, attributes, this->_attributesState()); } catch (...) { std::cout << this->absolute() << " fso attribute raise error\n" << std::endl; } return attributes; } } Attributes Node::dynamicAttributes() { Attributes attr; Variant* vptr; size_t size = this->__attributesHandlers.count(); if (size == 0) return attr; try { return DynamicAttributesCache::instance().find(this, this->__attributesHandlers.state()); } catch (std::string) { std::set& handlers = this->__attributesHandlers.handlers(); std::set::iterator handler; for (handler = handlers.begin(); handler != handlers.end(); handler++) { try { if ((vptr = new Variant((*handler)->attributes(this))) != NULL) attr[(*handler)->name()] = Variant_p(vptr); } catch (...) { std::cout << this->absolute() << " attribute handler " << (*handler)->name() << " raise error\n" << std::endl; } } DynamicAttributesCache::instance().insert(this, attr, this->__attributesHandlers.state()); } return attr; } Attributes Node::dynamicAttributes(std::string name) { std::set& handlers = this->__attributesHandlers.handlers(); std::set::iterator handler; Attributes attrs; for (handler = handlers.begin(); handler != handlers.end(); handler++) { if ((*handler)->name() == name) { try { attrs = (*handler)->attributes(this); } catch (...) { std::cout << this->absolute() << " attribute handler " << (*handler)->name() << " raise error\n" << std::endl; } break; } } return attrs; } Attributes Node::attributes() { Attributes attr; Attributes dtypes; Attributes nodeAttributes; Variant* vptr; std::set::iterator handler; Attributes::iterator it; dtypes = this->dataType(); if (!dtypes.empty() && ((vptr = new Variant(dtypes)) != NULL)) attr["type"] = Variant_p(vptr); if (this->__fsobj != NULL) { nodeAttributes = this->fsoAttributes(); if (!nodeAttributes.empty()) { vptr = new Variant(nodeAttributes); if (vptr != NULL) attr[this->__fsobj->name] = Variant_p(vptr); } } Attributes dynAttrs = this->dynamicAttributes(); attr.insert(dynAttrs.begin(), dynAttrs.end()); return attr; } std::list Node::dynamicAttributesNames(void) { std::set& handlers = this->__attributesHandlers.handlers(); std::set::iterator handler; std::list names; for (handler = handlers.begin(); handler != handlers.end(); handler++) names.push_back((*handler)->name()); return (names); } AttributesHandlers& Node::attributesHandlers(void) { return (this->__attributesHandlers); } bool Node::registerAttributes(AttributesHandler* ah) { return (this->__attributesHandlers.add(ah)); } void Node::attributesByTypeFromVariant(Variant_p rcvar, uint8_t type, Attributes* result, std::string current) { if (rcvar->type() == typeId::List) { std::list lvariant = rcvar->value >(); std::list::iterator it = lvariant.begin(); for (; it != lvariant.end(); it++) this->attributesByTypeFromVariant((*it), type, result, current); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value(); Attributes::iterator it = mvariant.begin(); std::string abs; for (; it != mvariant.end(); it++) { if (current.empty()) abs = (*it).first; else abs = current + '.' + (*it).first; if (it->second->type() == type) result->insert(std::pair(abs, it->second)); else this->attributesByTypeFromVariant(it->second, type, result, abs); } } } void Node::attributesNamesAndTypesFromVariant(Variant_p rcvar, std::map *namestypes, std::string current) { if (rcvar->type() == typeId::List) { std::list lvariant = rcvar->value >(); std::list::iterator it = lvariant.begin(); for (; it != lvariant.end(); it++) this->attributesNamesAndTypesFromVariant((*it), namestypes, current); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value(); Attributes::iterator it = mvariant.begin(); std::string abs; for (; it != mvariant.end(); it++) { if (current.empty()) abs = it->first; else abs = current + '.' + it->first; namestypes->insert(std::pair(abs, it->second->type())); this->attributesNamesAndTypesFromVariant(it->second, namestypes, abs); } } } void Node::attributesNamesFromVariant(Variant_p rcvar, std::list *names) { if (rcvar->type() == typeId::List) { std::list< Variant_p > lvariant = rcvar->value >(); std::list< Variant_p >::iterator it = lvariant.begin(); for (; it != lvariant.end(); it++) this->attributesNamesFromVariant((*it), names); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value< Attributes >(); Attributes::iterator it = mvariant.begin(); for (; it != mvariant.end(); it++) { names->push_back(it->first); this->attributesNamesFromVariant(it->second, names); } } } void Node::attributesNamesFromVariant(Variant_p rcvar, std::list *names, std::string current) { if (rcvar->type() == typeId::List) { std::list lvariant = rcvar->value >(); std::list::iterator it = lvariant.begin(); for (; it != lvariant.end(); it++) this->attributesNamesFromVariant((*it), names, current); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value< Attributes >(); Attributes::iterator it = mvariant.begin(); std::string abs; for (; it != mvariant.end(); it++) { if (current.empty()) abs = it->first; else abs = current + '.' + it->first; names->push_back(abs); this->attributesNamesFromVariant(it->second, names, abs); } } } std::list Node::attributesNames(attributeNameType tname) { std::list result; Attributes attr; Attributes::iterator attrit; attr = this->attributes(); for (attrit = attr.begin(); attrit != attr.end(); attrit++) { result.push_back(attrit->first); if (tname == ABSOLUTE_ATTR_NAME) this->attributesNamesFromVariant(attrit->second, &result, attrit->first); else this->attributesNamesFromVariant(attrit->second, &result); } return (result); } void Node::attributesByNameFromVariant(Variant_p rcvar, std::string name, std::list< Variant_p >* result) { if (rcvar->type() == typeId::List) { std::list< Variant_p > lvariant = rcvar->value >(); std::list< Variant_p >::iterator it; for (it = lvariant.begin(); it != lvariant.end(); it++) this->attributesByNameFromVariant((*it), name, result); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value< Attributes >(); Attributes::iterator it; for (it = mvariant.begin(); it != mvariant.end(); it++) { if (it->first == name) result->push_back(it->second); else this->attributesByNameFromVariant(it->second, name, result); } } } void Node::attributeByAbsoluteNameFromVariant(Variant_p rcvar, std::string name, std::list< Variant_p >* result) { std::string subname; std::string subabs; size_t idx; idx = name.find("."); if (idx != std::string::npos) { subname = name.substr(0, idx); subabs = name.substr(idx+1, name.size()); } else { subname = name; subabs = ""; } if ((rcvar->type() == typeId::List) && (!subabs.empty())) { std::list< Variant_p > lvariant = rcvar->value >(); std::list< Variant_p >::iterator it; for (it = lvariant.begin(); it != lvariant.end(); it++) if ((*it)->type() == typeId::Map) this->attributeByAbsoluteNameFromVariant((*it), subabs, result); } else if (rcvar->type() == typeId::Map) { Attributes mvariant = rcvar->value< Attributes >(); Attributes::iterator it; it = mvariant.find(subname); if (it != mvariant.end()) { if (!subabs.empty()) this->attributeByAbsoluteNameFromVariant(it->second, subabs, result); else result->push_back(it->second); } } } std::list< Variant_p > Node::attributesByName(std::string name, attributeNameType tname) { Attributes attr; Attributes::iterator attrit; std::list< Variant_p > result; attr = this->attributes(); if (tname == ABSOLUTE_ATTR_NAME) { std::string subname; std::string subabs; size_t idx; idx = name.find("."); if (idx != std::string::npos) { subname = name.substr(0, idx); subabs = name.substr(idx+1, name.size()); if ((attrit = attr.find(subname)) != attr.end()) this->attributeByAbsoluteNameFromVariant(attrit->second, subabs, &result); } else if ((attrit = attr.find(name)) != attr.end()) result.push_back(attrit->second); } else { for (attrit = attr.begin(); attrit != attr.end(); attrit++) { if (attrit->first == name) result.push_back(attrit->second); this->attributesByNameFromVariant(attrit->second, name, &result); } } return result; } Attributes Node::attributesByType(uint8_t type) { Attributes attr; Attributes result; Attributes::iterator attrit; attr = this->attributes(); for (attrit = attr.begin(); attrit != attr.end(); attrit++) { if (attrit->second->type() == type) result[attrit->first] = attrit->second; this->attributesByTypeFromVariant(attrit->second, type, &result, attrit->first); } return result; } std::map Node::attributesNamesAndTypes() { std::map result; Attributes attr; Attributes::iterator attrit; attr = this->attributes(); for (attrit = attr.begin(); attrit != attr.end(); attrit++) { result.insert(std::pair(attrit->first, attrit->second->type())); this->attributesNamesAndTypesFromVariant(attrit->second, &result, attrit->first); } return result; } std::list Node::compatibleModules(void) { std::list result; Attributes dtypes; ConfigManager* cm; std::map constants; std::string ext; if ((cm = ConfigManager::Get()) != NULL) { constants = cm->constantsByName("mime-type"); if (!constants.empty()) { dtypes = this->dataType(); if (!dtypes.empty()) this->__compatibleModulesByType(constants, dtypes, result); } ext = this->extension(); if (!ext.empty()) { constants = cm->constantsByName("extension-type"); if (!constants.empty()) this->__compatibleModulesByExtension(constants, ext, result); } } return result; } bool Node::isCompatibleModule(std::string modname) { ConfigManager* cm; Config* conf; Constant* constant; std::list< Variant_p > values; std::list< Variant_p >::iterator it; bool compat; compat = false; if (((cm = ConfigManager::Get()) != NULL) && ((conf = cm->configByName(modname)) != NULL)) { Attributes dtypes; std::string ext; dtypes = this->dataType(); ext = this->extension(); if ((constant = conf->constantByName("mime-type")) != NULL) { values = constant->values(); for (Attributes::iterator mit = dtypes.begin(); mit != dtypes.end(); mit++) { if (mit->second->type() == typeId::String) { std::string dtype = mit->second->value(); it = values.begin(); while (it != values.end() && !compat) { if ((*it)->type() == typeId::String && dtype.find((*it)->value()) != std::string::npos) compat = true; it++; } } } } if (!ext.empty() && !compat && ((constant = conf->constantByName("extension-type")) != NULL)) { values = constant->values(); it = values.begin(); while (it != values.end() && !compat) { if ((*it)->type() == typeId::String && (*it)->value().find(ext) != std::string::npos) compat = true; it++; } } } return compat; } void Node::__compatibleModulesByType(const std::map& cmime, Attributes& dtypes, std::list& result) { std::map::const_iterator cit; std::list lvalues; std::list::iterator lit; Attributes::iterator dit; bool match; for (cit = cmime.begin(); cit != cmime.end(); cit++) { match = false; if ((cit->second != NULL) && (cit->second->type() == typeId::String)) { lvalues = cit->second->values(); lit = lvalues.begin(); while (lit != lvalues.end() && !match) { dit = dtypes.begin(); while (dit != dtypes.end() && !match) { std::string cval = (*lit)->value(); if ((dit->second != NULL) && (dit->second->type() == typeId::String) && (dit->second->value().find(cval) != std::string::npos)) { match = true; result.push_back(cit->first); } dit++; } lit++; } } } } void Node::__compatibleModulesByExtension(const std::map& cextensions, std::string& ext, std::list& result) { std::map::const_iterator cit; std::list< Variant_p > lvalues; std::list< Variant_p >::iterator lit; for (cit = cextensions.begin(); cit != cextensions.end(); cit++) { if ((cit->second != NULL) && (cit->second->type() == typeId::String)) { lvalues = cit->second->values(); for (lit = lvalues.begin(); lit != lvalues.end(); lit++) if (ext == (*lit)->value()) result.push_back(cit->first); } } } bool Node::setTag(std::string name) { Tag_p t = TagsManager::get().tag(name); if (t != NULL) { this->__tags |= ((uint64_t) 1) << t->id(); return true; } return false; } bool Node::setTag(uint32_t id) { if (id != 0 && (TagsManager::get().tag(id) != NULL)) { this->__tags |= ((uint64_t) 1) << id; return true; } return false; } bool Node::removeTag(std::string name) { Tag_p t = TagsManager::get().tag(name); if (t != NULL) return (this->removeTag(t->id())); return false; } bool Node::removeTag(uint32_t id) { if ((this->__tags & (((uint64_t) 1) << id)) == (((uint64_t) 1) << id)) { this->__tags ^= ((uint64_t) 1) << id; return true; } return false; } bool Node::isTagged(uint32_t id) { if ((this->__tags & (((uint64_t) 1) << id)) == (((uint64_t) 1) << id)) return true; return false; } bool Node::isTagged(std::string name) { Tag_p t = TagsManager::get().tag(name); if (t->id() != 0) return (this->isTagged(t->id())); return false; } std::vector Node::tags() { uint8_t i = 1; TagsManager& tm = TagsManager::get(); std::vector tags; for (; i < 64; i++) if (this->isTagged(i)) { try { Tag_p t = tm.tag(i); if (t != NULL) tags.push_back(t); } catch (envError) { } } return (tags); } std::vector Node::tagsId() { uint32_t i = 1; std::vector tags; for (; i < 64; i++) if (this->isTagged(i)) tags.push_back(i); return (tags); } /* * Attributes Handler */ AttributesHandler::AttributesHandler(std::string handlerName) { this->__handlerName = handlerName; } std::string AttributesHandler::name(void) { return (this->__handlerName); } AttributesHandler::~AttributesHandler() { } /* * Attributes Handlers */ AttributesHandlers::AttributesHandlers() { this->__state = 0; } AttributesHandlers::~AttributesHandlers() { } size_t AttributesHandlers::count() { return this->__handlers.size(); } std::set& AttributesHandlers::handlers() { return this->__handlers; } void AttributesHandlers::updateState(void) { this->__state++; } const uint64_t AttributesHandlers::state(void) { return (this->__state); } bool AttributesHandlers::add(AttributesHandler* ah) { return this->__handlers.insert(ah).second; } bool AttributesHandlers::remove(AttributesHandler* attributeHandler) { this->__handlers.erase(attributeHandler); return true; } bool AttributesHandlers::remove(std::string handlerName) { std::set::iterator handler; for (handler = this->__handlers.begin(); handler != this->__handlers.end(); handler++) { if (handlerName == (*handler)->name()) { this->__handlers.erase(handler); return true; } } return false; } dff-1.3.0+dfsg.1/dff/api/vfs/rc.cpp000066400000000000000000000014251217176075400165620ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "rc.hpp" RCObjBase::RCObjBase() : refCount(0) { } RCObjBase::~RCObjBase() { } RCObjBase::RCObjBase(const RCObjBase&) : refCount(0) { } RCObjBase& RCObjBase::operator=(const RCObjBase&) { return *this; } dff-1.3.0+dfsg.1/dff/api/vfs/rootnode.cpp000066400000000000000000000047731217176075400200200ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "rootnode.hpp" #include "vfs.hpp" #include "vlink.hpp" #include "fso.hpp" VFSRootNode::VFSRootNode(std::string name) : Node(name) { this->setParent(this); this->setDir(); } VFSRootNode::~VFSRootNode() { } ModulesRootNode::ModulesRootNode(EventHandler* vfs, Node* root) : Node(std::string("Modules root")) { mutex_init(&this->__mutex); this->setParent(root); root->addChild(this); vfs->connection(this); } ModulesRootNode::~ModulesRootNode() { mutex_destroy(&this->__mutex); } std::string ModulesRootNode::icon() { return std::string(":module2.png"); } void ModulesRootNode::Event(event* e) { RCPtr variantNode = e->value; if (variantNode) { Node* root = variantNode->value(); if (root && (!dynamic_cast(root)) && root->parent()->parent()->absolute() != "/") { if (root->fsobj()) { Node* moduleRoot; mutex_lock(&this->__mutex); std::map::iterator it = this->__modulesNameRootNode.find(root->fsobj()->name); if (it == this->__modulesNameRootNode.end()) { moduleRoot = new Node(root->fsobj()->name, 0, this); this->__modulesNameRootNode[root->fsobj()->name] = moduleRoot; } else moduleRoot = it->second; std::vector children = moduleRoot->children(); std::vector::iterator child = children.begin(); for (; child != children.end(); child++) { VLink* childLink = NULL; if (((childLink = dynamic_cast(*child)) != NULL) && (childLink->linkNode() == root->parent())) { mutex_unlock(&this->__mutex); return ; } } VLink* link = new VLink(root->parent(), moduleRoot); event* e = new event; e->value = Variant_p(new Variant(link)); mutex_unlock(&this->__mutex); VFS::Get().notify(e); } } } } dff-1.3.0+dfsg.1/dff/api/vfs/tags.cpp000066400000000000000000000115411217176075400171140ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "vfs.hpp" #include "node.hpp" #include "tags.hpp" Color::Color() { r = g = b = 0; } Color::Color(uint8_t cr, uint8_t cg, uint8_t cb) { this->r = cr; this->g = cg; this->b = cb; } Tag::Tag() { } Tag::Tag(uint32_t id, std::string name, Color color) { this->__id = id; this->__name = name; this->__color = color; } Tag::Tag(uint32_t id, std::string name, uint8_t r, uint8_t g, uint8_t b) { this->__id = id; this->__name = name; this->__color.r = r; this->__color.g = g; this->__color.b = b; } Tag::~Tag() { } std::string Tag::name(void) { return this->__name; } Color Tag::color(void) { return this->__color; } uint32_t Tag::id(void) { return this->__id; } void Tag::setColor(Color color) { this->__color = color; } void Tag::setColor(uint8_t r, uint8_t g, uint8_t b) { this->__color.r = r; this->__color.g = g; this->__color.b = b; } void Tag::setName(std::string name) { this->__name = name; } #define DEFAULT_TAG(n, r, g, b) this->add(std::string(n), r, g, b); TagsManager::TagsManager() { DEFAULT_TAG("known good", 0, 255, 0) DEFAULT_TAG("known bad", 0, 0, 255) DEFAULT_TAG("malware", 255, 0, 0) DEFAULT_TAG("viewed", 255, 255, 0) this->__defaults = this->__tagsList.size(); } TagsManager& TagsManager::get() { static TagsManager single; return single; } uint32_t TagsManager::add(std::string name, Color color) { return (this->add(name, color.r, color.g, color.b)); } uint32_t TagsManager::add(std::string name, uint8_t r, uint8_t g, uint8_t b) { try { Tag_p t = this->tag(name); return (t->id()); } catch (envError) { } if (this->__tagsList.size() < 63) { uint32_t id = this->__tagsList.size() + 1; Tag_p tag(new Tag(id, name, r, g, b)); this->__tagsList.push_back(tag); return (id); } else { uint32_t id = 0; for (; id < 63; id++) { if (this->__tagsList[id] == NULL) { this->__tagsList[id] = Tag_p(new Tag(id + 1, name, r, g, b)); return (id + 1); } } } return (0); } uint32_t TagsManager::add(std::string name) { //getcolorauto XXX //random ?? return (this->add(name, 100, 170, 80)); } void TagsManager::__removeNodesTag(uint32_t id, Node* node) { node->removeTag(id); if (!(node->hasChildren())) return ; std::vector childs = node->children(); std::vector::iterator it = childs.begin(); for (; it != childs.end(); it++) if ((*it) != NULL) this->__removeNodesTag(id, (*it)); } void TagsManager::__removeNodesTag(uint32_t id) { Node* root = VFS::Get().GetNode("/"); this->__removeNodesTag(id, root); } bool TagsManager::remove(uint32_t id) { try { Tag_p t = this->__tagsList.at(id - 1); if (t != NULL) { this->__removeNodesTag(id); if (id > this->__defaults) { this->__tagsList[id - 1] = NULL; //delete t; //t = NULL;// hum ca delete vraiment ou vue que c a null ca delte pas et du coup ca reste en rammmmm et ca segfault pas ds le removescript XXX return true; } else return false; } } catch (std::exception) { return false; } return false; } bool TagsManager::remove(std::string name) { std::vector::iterator it = this->__tagsList.begin(); for (; it != this->__tagsList.end(); it++) { if (((*it) != NULL) && ((*it)->name() == name)) return (this->remove((*it)->id())); } return false; } std::vector* TagsManager::tags(void) { std::vector* tagsList = new std::vector; std::vector::iterator it = this->__tagsList.begin(); for (; it != this->__tagsList.end(); it++) { if ((*it) != NULL) tagsList->push_back(Tag_p(*it)); } return (tagsList); } Tag_p TagsManager::tag(uint32_t id) { try { Tag_p t = this->__tagsList.at(id - 1); if (t != NULL) return t; } catch (std::exception) { } throw envError("Tag not found"); } Tag_p TagsManager::tag(std::string name) { std::vector::iterator it = this->__tagsList.begin(); for (; it != this->__tagsList.end(); it++) if (((*it) != NULL) && (*it)->name() == name) return (*it); throw envError("Tag not found"); } dff-1.3.0+dfsg.1/dff/api/vfs/vfile.cpp000066400000000000000000000543651217176075400172760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "vfile.hpp" #include "iostat.hpp" #ifdef WITH_IOSTAT #define stat_instance() IOStat::getInstance().pushInstanceStats(this->__fsobj->uid()) #define stat_read(readcount) IOStat::getInstance().pushReadStats(this->__fsobj->uid(), readcount) #else #define stat_instance() #define stat_read(readcount) #endif VFile::VFile(int32_t fd, class fso *fsobj, class Node *node) { this->__fs = new FastSearch(); this->__fd = fd; this->__fsobj = fsobj; this->__node = node; this->__stop = false; stat_instance(); } VFile::~VFile() { try { this->close(); } catch (const vfsError& e) { } delete this->__fs; } class Node* VFile::node() { return this->__node; } pdata* VFile::read(void) { int32_t n; pdata* data; uint64_t size; if (this->__fd < 0) throw vfsError("VFile::read() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); data = new pdata; size = this->__node->size(); try { data->buff = malloc(size); if (data->buff == NULL) throw vfsError("VFile::read() can't allocate memory\n"); memset(data->buff, 0, size); n = this->__fsobj->vread(this->__fd, (void*)data->buff, size); if (n < 0) throw vfsError(this->__fsobj->name + " read error\n"); stat_read(n); data->len = n; return (data); } catch (vfsError e) { free(data->buff); delete data; throw vfsError("VFile::read() throw\n" + e.error); } } pdata* VFile::read(uint32_t size) { int32_t n; pdata* data; if (this->__fd < 0) throw vfsError("VFile::read() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); data = new pdata; try { data->buff = malloc(size); if (data->buff == NULL) { std::string error = this->node()->absolute() + "->VFile::read(uint32_t) can't allocate enough memory (" ; error += size; error += ") bytes\n" ; throw vfsError(error); } data->len = size; memset(data->buff, 0, size); n = this->__fsobj->vread(this->__fd, data->buff, size); if (n < 0) throw vfsError(this->__fsobj->name + " read error\n"); data->len = n; stat_read(n); return (data); } catch (vfsError e) { free(data->buff); delete data; throw vfsError("VFile::read(size) throw\n" + e.error); } } int VFile::read(void *buff, uint32_t size) { int32_t n; if (this->__fd < 0) throw vfsError("VFile::read() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { n = this->__fsobj->vread(this->__fd, buff, size); if (n < 0) throw vfsError(this->__fsobj->name + " read error\n"); stat_read(n); return (n); } catch (vfsError e) { throw vfsError("Vfile::read(buff, size) throw\n" + e.error); } } uint64_t VFile::seek(uint64_t offset, char *cwhence) { int32_t wh; std::string whence = cwhence; if (this->__fd < 0) throw vfsError("VFile::seek() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); if (whence == std::string("SET")) wh = 0; else if (whence == std::string("CUR")) wh = 1; else if (whence == std::string("END")) wh = 2; else throw vfsError("VFile::vseek(dff_ui64, char *) error whence not defined ( SET, CUR, END )"); try { return (this->__fsobj->vseek(this->__fd, offset, wh)); } catch (vfsError e) { throw vfsError("VFile::seek(dff_ui64, char*) throw\n" + e.error); } } uint64_t VFile::seek(uint64_t offset, int32_t whence) { if (this->__fd < 0) throw vfsError("VFile::seek() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); if (whence > 2) throw vfsError("VFile::vseek(offset, whence) error whence not defined ( SET, CUR, END )"); try { return (this->__fsobj->vseek(this->__fd, offset, whence)); } catch (vfsError e) { throw vfsError("VFile::seek(dff_ui64, whence) throw\n" + e.error); } } uint64_t VFile::seek(uint64_t offset) { if (this->__fd < 0) throw vfsError("VFile::seek() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { return (this->__fsobj->vseek(this->__fd, offset, 0)); } catch (vfsError e) { throw vfsError("VFile::seek(dff_ui64) throw\n" + e.error); } } uint64_t VFile::seek(int32_t offset, int32_t whence) { if (this->__fd < 0) throw vfsError("VFile::seek() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); if (whence > 2) throw vfsError("VFile::vseek(offset, whence) error whence not defined ( SET, CUR, END )"); try { return (this->__fsobj->vseek(this->__fd, (uint64_t)offset, whence)); } catch (vfsError e) { throw vfsError("Vfile::seek(int offset, int whence) throw\n" + e.error); } } int32_t VFile::write(std::string buff) { int32_t n; if (this->__fd < 0) throw vfsError("VFile::write() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { n = this->__fsobj->vwrite(this->__fd, (void *)buff.c_str(), buff.size()); return (n); } catch (vfsError e) { throw vfsError("VFile::write(string) throw\n" + e.error); } } int32_t VFile::write(char *buff, uint32_t size) { int32_t n; if (this->__fd < 0) throw vfsError("VFile::write() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { n = this->__fsobj->vwrite(this->__fd, buff, size); return (n); } catch (vfsError e) { throw vfsError("VFile::write(buff, size) throw\n" + e.error); } } int32_t VFile::close(void) { try { if (this->__fd != -1) { this->__fsobj->vclose(this->__fd); this->__fd = -1; } } catch (vfsError e) { } return 0; } int32_t VFile::dfileno() { return (this->__fd); } uint64_t VFile::tell() { if (this->__fd < 0) throw vfsError("VFile::tell() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); return (this->__fsobj->vtell(this->__fd)); } std::string VFile::readline(uint32_t size) throw (std::string) { std::string res; unsigned char* buffer; uint32_t bread; uint32_t bsize; uint32_t consumed; uint32_t i; uint64_t oldoff; bool found; if (this->__fd < 0) throw vfsError("VFile::readline() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (size == 0) size = INT32_MAX; if (size < 300) bsize = size; else bsize = 300; res = ""; oldoff = this->tell(); if ((buffer = (unsigned char*)malloc(bsize)) != NULL) { consumed = 0; found = false; while (((bread = this->read(buffer, bsize)) > 0) && (consumed != size) && (!found) && !this->__stop) { i = 0; while ((i != bread) && (consumed != size) && (!found) && !this->__stop) { res += buffer[i]; consumed += 1; if (buffer[i] == '\n') found = true; i++; } } this->seek(oldoff+consumed); free(buffer); } else throw(std::string("VFile::readline() --> malloc failed")); return res; } int64_t VFile::find(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { unsigned char *buffer; int32_t bread; int32_t idx; int32_t hlen; uint64_t totalread; int64_t pos; if (this->__fd < 0) throw vfsError("VFile::find() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::find 'end' argument must be greater than 'start' argument"); if (nlen == 0) return 0; idx = -1; totalread = this->seek(start); buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (totalread < end) && (idx == -1) && !this->__stop) { if (end < totalread + bread) hlen = (int32_t)(end - totalread); else hlen = bread; idx = this->__fs->find(buffer, hlen, needle, nlen, wildcard); if (idx == -1) { if (hlen == BUFFSIZE) totalread = this->seek(this->tell() - nlen); else totalread = this->seek(this->tell()); } } free(buffer); if (idx == -1) pos = -1; else pos = totalread + idx; return pos; } int64_t VFile::rfind(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { unsigned char *buffer; int32_t bread; int32_t idx; int32_t hlen; uint64_t rpos; int64_t pos; if (this->__fd < 0) throw vfsError("VFile::rfind() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::rfind 'end' argument must be greater than 'start' argument"); if (nlen == 0) return 0; idx = -1; buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); if (end < start + BUFFSIZE) { rpos = this->seek(start); bread = this->read(buffer, end-start); idx = this->__fs->rfind(buffer, bread, needle, nlen, wildcard); } else { rpos = end-BUFFSIZE; this->seek(rpos); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (rpos > start) && (idx == -1) && !this->__stop) { if (rpos < start + bread) hlen = (int32_t)(rpos - start); else hlen = bread; idx = this->__fs->rfind(buffer, hlen, needle, nlen, wildcard); if (idx == -1) { if (hlen == BUFFSIZE) rpos = this->seek(rpos - hlen + nlen); else rpos = this->seek(rpos - hlen); } } } free(buffer); if (idx == -1) pos = -1; else pos = rpos + idx; return pos; } int32_t VFile::count(unsigned char* needle, uint32_t nlen, unsigned char wildcard, int32_t maxcount, uint64_t start, uint64_t end) throw (std::string) { unsigned char *buffer; int32_t bread; uint64_t totalread; int32_t tcount; int32_t count; int32_t hlen; if (this->__fd < 0) throw vfsError("VFile::count() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::count 'end' argument must be greater than 'start' argument"); if (nlen == 0) { if (start == 0) return (end + 1); else return (end - start + 1); } buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); count = 0; totalread = this->seek(start); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (totalread < end) && (maxcount > 0) && !this->__stop) { if (end < totalread + bread) hlen = (int32_t)(end - totalread); else hlen = bread; tcount = this->__fs->count(buffer, hlen, needle, nlen, wildcard, maxcount); if (tcount > 0) { count += tcount; maxcount -= tcount; } if ((hlen == BUFFSIZE) && (this->__fs->find(buffer+(BUFFSIZE-nlen), nlen, needle, nlen, wildcard) != -1)) totalread = this->seek(this->tell() - nlen); else totalread = this->seek(this->tell()); } free(buffer); return count; } std::vector* VFile::indexes(unsigned char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { unsigned char* buffer; std::vector* indexes; int32_t bread; int32_t idx; int32_t buffpos; uint64_t totalread; int32_t hlen; if (this->__fd < 0) throw vfsError("VFile::indexes() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::indexes 'end' argument must be greater than 'start' argument"); if (nlen == 0) return NULL; indexes = new std::vector; totalread = this->seek(start); buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); event* e = new event; while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (totalread < end) && !this->__stop) { buffpos = 0; if (end < totalread + bread) hlen = (int32_t)(end - totalread); else hlen = bread; while ((buffpos < hlen - (int32_t)nlen) && ((idx = this->__fs->find(buffer+buffpos, hlen - buffpos, needle, nlen, wildcard)) != -1) && !this->__stop) { buffpos += idx + nlen; indexes->push_back(this->tell() - bread + buffpos - nlen); } if ((hlen == BUFFSIZE) && (buffpos != hlen)) totalread = this->seek(this->tell() - nlen); else totalread = this->seek(this->tell()); e->value = Variant_p(new Variant(totalread)); this->notify(e); } free(buffer); return indexes; } int64_t VFile::find(std::string needle, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { int64_t ret; if (this->__fd < 0) throw vfsError("VFile::find() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { ret = this->find((unsigned char*)needle.c_str(), needle.size(), wildcard, start, end); return ret; } catch (std::string e) { throw e; } } int64_t VFile::rfind(std::string needle, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { int64_t ret; if (this->__fd < 0) throw vfsError("VFile::rfind() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { ret = this->rfind((unsigned char*)needle.c_str(), needle.size(), wildcard, start, end); return ret; } catch (std::string e) { throw e; } } int32_t VFile::count(std::string needle, unsigned char wildcard, int32_t maxcount, uint64_t start, uint64_t end) throw (std::string) { int32_t ret; if (this->__fd < 0) throw vfsError("VFile::count() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); try { ret = this->count((unsigned char*)needle.c_str(), needle.size(), wildcard, maxcount, start, end); return ret; } catch (std::string e) { throw e; } } std::vector* VFile::indexes(std::string needle, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { std::vector* ret; if (this->__fd < 0) throw vfsError("VFile::indexes() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); ret = NULL; try { ret = this->indexes((unsigned char*)needle.c_str(), needle.size(), wildcard, start, end); return ret; } catch (std::string e) { throw e; } } /* The following method is only for backward compatibility */ std::vector* VFile::search(char* needle, uint32_t nlen, unsigned char wildcard, uint64_t start, uint64_t end) throw (std::string) { std::vector* ret; if (this->__fd < 0) throw vfsError("VFile::search() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); ret = NULL; try { ret = this->indexes((unsigned char*)needle, nlen, wildcard, start, end); return ret; } catch (std::string e) { throw e; } } /* Following methods will be part of the future API. Use the ones from now as they'll become default. */ int64_t VFile::find(Search* sctx, uint64_t start, uint64_t end) throw (std::string) { unsigned char *buffer; int32_t bread; int32_t idx; int32_t hlen; uint64_t totalread; int64_t pos; uint32_t nlen; if (this->__fd < 0) throw vfsError("VFile::find() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (sctx == NULL) throw (std::string("VFile::find, Search context is not set.")); if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::find 'end' argument must be greater than 'start' argument"); idx = -1; totalread = this->seek(start); buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); nlen = sctx->needleLength(); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (totalread < end) && (idx == -1) && !this->__stop) { if (end < totalread + bread) hlen = (int32_t)(end - totalread); else hlen = bread; try { idx = sctx->find((char*)buffer, hlen); } catch (std::string err) { if (buffer != NULL) free(buffer); throw (err); } if (idx == -1) { if (hlen == BUFFSIZE) totalread = this->seek(this->tell() - nlen); else totalread = this->seek(this->tell()); } } free(buffer); if (idx == -1) pos = -1; else pos = totalread + idx; return pos; } int64_t VFile::rfind(Search* sctx, uint64_t start, uint64_t end) throw (std::string) { unsigned char *buffer; int32_t bread; int32_t idx; int32_t hlen; uint64_t rpos; int64_t pos; uint32_t nlen; if (this->__fd < 0) throw vfsError("VFile::rfind() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (sctx == NULL) throw (std::string("VFile::rfind, Search context is not set.")); if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::rfind 'end' argument must be greater than 'start' argument"); idx = -1; buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); nlen = sctx->needleLength(); if (end < start + BUFFSIZE) { rpos = this->seek(start); bread = this->read(buffer, end-start); try { idx = sctx->rfind((char*)buffer, bread); } catch (std::string err) { throw (err); } } else { rpos = end-BUFFSIZE; this->seek(rpos); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (rpos > start) && (idx == -1) && !this->__stop) { if (rpos < start + bread) hlen = (int32_t)(rpos - start); else hlen = bread; try { idx = sctx->rfind((char*)buffer, hlen); } catch (std::string err) { if (buffer != NULL) free(buffer); throw (err); } if (idx == -1) { if (hlen == BUFFSIZE) rpos = this->seek(rpos - hlen + nlen); else rpos = this->seek(rpos - hlen); } } } free(buffer); if (idx == -1) pos = -1; else pos = rpos + idx; return pos; } int32_t VFile::count(Search* sctx, int32_t maxcount, uint64_t start, uint64_t end) throw (std::string) { unsigned char *buffer; int32_t bread; uint64_t totalread; int32_t tcount; int32_t count; int32_t hlen; uint32_t nlen; if (this->__fd < 0) throw vfsError("VFile::count() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (sctx == NULL) throw (std::string("VFile::count, Search context is not set.")); if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::count 'end' argument must be greater than 'start' argument"); buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); count = 0; totalread = this->seek(start); nlen = sctx->needleLength(); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (totalread < end) && (maxcount > 0) && !this->__stop) { if (end < totalread + bread) hlen = (int32_t)(end - totalread); else hlen = bread; try { if (buffer != NULL) free(buffer); tcount = sctx->count((char*)buffer, hlen, maxcount); } catch (std::string err) { throw (err); } if (tcount > 0) { count += tcount; maxcount -= tcount; } if ((hlen == BUFFSIZE) && (sctx->find((char*)(buffer+(BUFFSIZE-nlen)), nlen) != -1)) totalread = this->seek(this->tell() - nlen); else totalread = this->seek(this->tell()); } free(buffer); return count; } std::vector* VFile::indexes(Search* sctx, uint64_t start, uint64_t end) throw (std::string) { unsigned char* buffer; std::vector* indexes; int32_t bread; int32_t idx; int32_t buffpos; uint64_t totalread; int32_t hlen; uint32_t nlen; if (this->__fd < 0) throw vfsError("VFile::indexes() on closed file " + this->__fsobj->name + ":" + this->__node->absolute() + "\n"); this->__stop = false; if (sctx == NULL) throw (std::string("VFile::indexes, Search context is not set.")); if (end > this->__node->size()) end = this->__node->size(); if ((end != 0) && (end < start)) throw std::string("VFile::indexes 'end' argument must be greater than 'start' argument"); indexes = new std::vector; totalread = this->seek(start); buffer = (unsigned char*)malloc(sizeof(char) * BUFFSIZE); event* e = new event; nlen = sctx->needleLength(); while (((bread = this->read(buffer, BUFFSIZE)) > 0) && (totalread < end) && !this->__stop) { buffpos = 0; if (end < totalread + bread) hlen = (int32_t)(end - totalread); else hlen = bread; try { while ((buffpos < hlen - (int32_t)nlen) && ((idx = sctx->find((char*)(buffer+buffpos), hlen - buffpos)) != -1) && !this->__stop) { nlen = sctx->needleLength(); buffpos += idx + nlen; indexes->push_back(this->tell() - bread + buffpos - nlen); } } catch (std::string err) { if (buffer != NULL) free(buffer); } if ((hlen == BUFFSIZE) && (buffpos != hlen)) totalread = this->seek(this->tell() - nlen); else totalread = this->seek(this->tell()); e->value = Variant_p(new Variant(totalread)); this->notify(e); } free(buffer); return indexes; } dff-1.3.0+dfsg.1/dff/api/vfs/vfs.cpp000066400000000000000000000062351217176075400167600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "fso.hpp" #include "node.hpp" #include "vfs.hpp" #include "rootnode.hpp" VFS& VFS::Get() { static VFS single; return single; } VFS::VFS() { this->root = new VFSRootNode("/"); this->__orphanednodes.push_back(this->root); cwd = root; } VFS::~VFS() { } void VFS::Event(event *e) { } void VFS::cd(Node *path) { cwd = path; } Node* VFS::GetCWD(void) { return (cwd); } std::set* VFS::GetTree(void) { return (&Tree); } uint16_t VFS::registerFsobj(fso* fsobj) throw (vfsError) { if (fsobj != NULL) this->__fsobjs.push_back(fsobj); else throw (vfsError("registerFsobj() NULL pointer provided")); return (uint16_t)(this->__fsobjs.size()); } uint64_t VFS::registerOrphanedNode(Node* n) throw (vfsError) { if (n != NULL) this->__orphanednodes.push_back(n); else throw (vfsError("registerOrphanedNode() NULL pointer provided")); return (uint64_t)(this->__orphanednodes.size() - 1); } std::vector VFS::fsobjs() { return this->__fsobjs; } uint64_t VFS::totalNodes() { size_t i; uint64_t totalnodes; totalnodes = this->__orphanednodes.size(); for (i = 0; i != this->__fsobjs.size(); i++) totalnodes += this->__fsobjs[i]->nodeCount(); return totalnodes; } Node* VFS::getNodeById(uint64_t id) { uint16_t fsoid; fso* fsobj; fsoid = id >> 48; if ((fsoid == 0) && (id < this->__orphanednodes.size())) return this->__orphanednodes[id]; else if ((fsoid > 0) && ((fsoid - 1) < (uint16_t)this->__fsobjs.size())) { if ((fsobj = this->__fsobjs[fsoid-1]) != NULL) return fsobj->getNodeById(id); else return NULL; } else return NULL; } Node* VFS::GetNode(std::string path, Node* where) { std::vector next; uint32_t i; if (path == "..") return (where->parent()); if (where->hasChildren()) { next = where->children(); for (i = 0; i < next.size(); i++) { if (next[i]->name() == path) return (next[i]); } return (0); } else return (0); } Node* VFS::GetNode(std::string path) { if (path == "/") return root; path = path.substr(path.find('/') + 1); std::string lpath; std::string rpath = path; Node* tmp = root; do { if (rpath.find('/') != std::string::npos) { lpath = rpath.substr(0, rpath.find('/')); rpath = rpath.substr(rpath.find('/') + 1); } else { lpath = rpath; rpath = ""; } tmp = GetNode(lpath, tmp); } while (tmp && rpath.size()); return (tmp); } void VFS::AddNode(Node *parent, Node* head) { parent->addChild(head); event* e = new event; e->value = Variant_p(new Variant(head)); this->notify(e); } dff-1.3.0+dfsg.1/dff/api/vfs/vfs.py000066400000000000000000000103041217176075400166160ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal J. # from dff.api.vfs.libvfs import * import types class vfs(): def __init__(self): self.libvfs = VFS.Get() def walk(self, top, topdown=True, depth=-1): if depth == 0: return if type(top) == types.StringType: node = self.getnode(top.replace("//", "/")) elif isinstance(top, Node): node = top else: raise ValueError("top must be a string or a Node") if node == None: return children = node.children() dirs, files = [], [] for child in children: if type(top) == types.StringType: item = child.name() elif isinstance(top, Node): item = child if child.hasChildren() or child.isDir(): if child.size(): files.append(item) dirs.append(item) else: files.append(item) #if child.size() > 0: # files.append(item) if topdown: yield top, dirs, files for name in dirs: if type(top) == types.StringType: newtop = str(top + "/" + name).replace("//", "/") elif isinstance(top, Node): newtop = name for x in self.walk(newtop, topdown, depth-1): yield x if not topdown: yield top, dirs, files def getnode(self, path): if not path: return self.getcwd() #if type(path) != type(""): #return path if path and path[0] != "/": abspath = self.getcwd().absolute() path = str(abspath + "/" + path).replace("//", "/") # Avoid trailing '/' while len(path) > 1 and path[-1:] == "/": path = path[:-1] if type(path) == unicode: path = str(path) node = self.libvfs.GetNode(path) if node: return node return None def open(self, path): if type(path) == type(""): node = self.getnode(path) if node: #and node.is_file: return node.open() else: return def gettree(self): return self.libvfs.GetTree() def getcwd(self): return self.libvfs.GetCWD() def setcwd(self, path): self.libvfs.cd(path) def deletenode(self, node): return self.libvfs.DeleteNode(node) # return a Node's Dictionary with directory of nodeDir def listingDirectories(self, nodeDir): if nodeDir == False: return False listing = [] list = nodeDir.children() for i in list: if i.hasChildren():# or not i.is_file : listing.append(i) return listing # return a Node's Dictionary with files and directory of nodeDir def listingDirectoriesAndFiles(self, nodeDir): if nodeDir == False: return False if not nodeDir.hasChildren(): #and nodeDir.is_file: return False listing = [] list = nodeDir.children() for i in list: listing.append(i) return listing def getInfoDirectory(self, nodeDir): list = nodeDir.children() info = {} info['size'] = 0 info['item'] = 0 for i in list : if i.hasChildren(): #or not i.is_file : info_child = self.getInfoDirectory(i) info['size'] = info['size'] + info_child['size'] info['item'] = info['item'] + info_child['item'] + 1 else : info['item'] = info['item'] + 1 info['size'] = info['size'] + i.size() return info def link(self, node, dest): pass #Link(node, dest) dff-1.3.0+dfsg.1/dff/api/vfs/vlink.cpp000066400000000000000000000064751217176075400173130ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "variant.hpp" #include "tags.hpp" #include "vlink.hpp" uint32_t VLink::id() { return this->__linkedNode->id(); } VLink::VLink(Node* linkedNode, Node* parent, std::string newname) { this->__childcount = 0; this->__at = 0; this->__linkedNode = linkedNode; this->__parent = parent; if (newname == "") this->__name = __linkedNode->name(); else this->__name = newname; this->__parent->addChild(this); } void VLink::fileMapping(FileMapping *fm) { this->__linkedNode->fileMapping(fm); } uint64_t VLink::size() { return this->__linkedNode->size(); } std::string VLink::linkPath() { return this->__linkedNode->path(); } std::string VLink::linkName() { return this->__linkedNode->name(); } std::string VLink::linkAbsolute() { return this->__linkedNode->absolute(); } bool VLink::isFile() { return this->__linkedNode->isFile(); } bool VLink::isDir() { return this->__linkedNode->isDir(); } bool VLink::isVDir() { return this->__linkedNode->isVDir(); } bool VLink::isDeleted() { return this->__linkedNode->isDeleted(); } bool VLink::isLink() { return this->__linkedNode->isLink(); } class fso* VLink::fsobj() { return this->__linkedNode->fsobj(); } Node* VLink::linkParent() { return this->__linkedNode->parent(); } std::vector VLink::linkChildren() { return this->__linkedNode->children(); } bool VLink::linkHasChildren() { return this->__linkedNode->hasChildren(); } uint32_t VLink::linkChildCount() { return this->__linkedNode->childCount(); } Node* VLink::linkNode() { return this->__linkedNode; } VFile* VLink::open() { return this->__linkedNode->open(); } Attributes VLink::dataType(void) { return this->__linkedNode->dataType(); } Attributes VLink::attributes(void) { return this->__linkedNode->attributes(); } std::string VLink::icon(void) { return this->__linkedNode->icon(); } std::list VLink::compatibleModules(void) { return this->__linkedNode->compatibleModules(); } bool VLink::isCompatibleModule(std::string moduleName) { return this->__linkedNode->isCompatibleModule(moduleName); } bool VLink::setTag(std::string name) { return this->__linkedNode->setTag(name); } bool VLink::setTag(uint32_t id) { return this->__linkedNode->setTag(id); } bool VLink::removeTag(std::string name) { return this->__linkedNode->removeTag(name); } bool VLink::removeTag(uint32_t id) { return this->__linkedNode->removeTag(id); } bool VLink::isTagged(uint32_t id) { return this->__linkedNode->isTagged(id); } bool VLink::isTagged(std::string name) { return this->__linkedNode->isTagged(name); } std::vector VLink::tags() { return this->__linkedNode->tags(); } std::vector VLink::tagsId() { return this->__linkedNode->tagsId(); } VLink::~VLink() {} dff-1.3.0+dfsg.1/dff/modules/000077500000000000000000000000001217176075400155515ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/CMakeLists.txt000066400000000000000000000017421217176075400203150ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file(__init__.py) add_subdirectory (volumes) add_subdirectory (fs) add_subdirectory (builtins) add_subdirectory (search) add_subdirectory (viewer) add_subdirectory (statistics) add_subdirectory (ram) add_subdirectory (node) add_subdirectory (connector) add_subdirectory (hash) add_subdirectory (metadata) add_subdirectory (databases) add_subdirectory (mailbox) add_subdirectory (export) dff-1.3.0+dfsg.1/dff/modules/__init__.py000066400000000000000000000022001217176075400176540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import os, sys from dff.api.loader.loader import loader pathset = set() for moduleDirectory in loader().modulesPaths(): if moduleDirectory[0] != "/": for files in os.listdir(os.getcwd() + "/" + moduleDirectory): directory = os.getcwd() + "/" + moduleDirectory + "/" + files if os.path.isdir(directory): pathset.add(directory[len(os.getcwd()) + 1:]) else: for files in os.listdir(moduleDirectory): directory = moduleDirectory + "/" + files if os.path.isdir(directory): pathset.add(directory) for path in pathset: __path__.append(path) dff-1.3.0+dfsg.1/dff/modules/builtins/000077500000000000000000000000001217176075400174025ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/builtins/CMakeLists.txt000066400000000000000000000013421217176075400221420ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( cd.py batch.py fg.py fileinfo.py find.py history.py info.py jobs.py link.py load.py ls.py man.py open.py show_cwd.py show_db.py __init__.py ) dff-1.3.0+dfsg.1/dff/modules/builtins/__init__.py000066400000000000000000000012231217176075400215110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['cd', 'fg', 'history', 'info', 'jobs', 'link', 'load', 'ls', 'open', 'show_cwd', 'show_db'] dff-1.3.0+dfsg.1/dff/modules/builtins/batch.py000066400000000000000000000037471217176075400210500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_postprocess_version__ = "1.0.0" from code import InteractiveConsole from dff.api.module.script import Script from dff.api.taskmanager.taskmanager import TaskManager from dff.api.module.module import Module from dff.api.types.libtypes import Variant, Argument, typeId, ConfigManager from dff.ui.console.completion import LineParser class BATCH(Script): def __init__(self): Script.__init__(self, "batch") self.tm = TaskManager() self.DEBUG = False self.VERBOSITY = 0 self.lp = LineParser(self.DEBUG, self.VERBOSITY -1) self.cm = ConfigManager.Get() def start(self, args): ic = InteractiveConsole() path = args["path"].value().path print "executing batch script " + path file = open(path) for line in file.xreadlines(): if line[0] == "#": continue elif line[0] == "!": cmds = self.lp.makeCommands(line[1:]) for cmd in cmds: exec_type = ["console"] config = self.cm.configByName(cmd[0]) args = config.generate(cmd[1]) proc = self.tm.add(cmd[0], args, exec_type) proc.event.wait() else: ic.push(line) ic.resetbuffer() file.close() return class batch(Module): """Process a dff batch file""" def __init__(self): Module.__init__(self, "batch", BATCH) self.conf.addArgument({"name":"path", "description": "Path to a dff batch file", "input" : Argument.Required|Argument.Single|typeId.Path}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/cd.py000066400000000000000000000027331217176075400203470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_cd_version__ = "1.0.0" from dff.api.vfs import vfs from dff.api.module.module import Script, Module from dff.api.types.libtypes import Variant, Argument, typeId class CD(Script): def __init__(self): Script.__init__(self, "cd") def start(self, args): node = args["dir"].value() if not node: self.res["error"] = Variant("Can't find file") return if not node.hasChildren(): self.res["error"] = Variant("Can't change current directory on file") return self.vfs.setcwd(node) self.res["result"] = Variant("change path to " + str(node.absolute())) class cd(Module): """Change current directory""" def __init__(self): Module.__init__(self, "cd", CD) self.conf.addArgument({"name": "dir", "description": "Directory to go in", "input": Argument.Single|Argument.Optional|typeId.Node}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/fg.py000066400000000000000000000035601217176075400203540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_fg_version__ = "1.0.0" from Queue import Empty from dff.api.taskmanager.processus import ProcessusManager from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Argument, typeId from dff.ui.console.utils import VariantTreePrinter class FG(Script): def __init__(self): Script.__init__(self, "fg") self.processusManager = ProcessusManager() self.vtreeprinter = VariantTreePrinter() def start(self, args): jobs = args["pid"].value() for proc in self.processusManager: if jobs == proc.pid: print "Displaying processus: " + str(proc.pid) + " name: " + str(proc.name) + " state: " + str(proc.state) + "\n" try : text = self.processusManager[jobs].stream.get(0) while text: print text text = self.processusManager[jobs].stream.get(0) except Empty: pass print self.vtreeprinter.fillMap(0, proc.res) class fg(Module): """Switch to a process in background""" def __init__(self): Module.__init__(self, "fg", FG) self.conf.addArgument({"name": "pid", "description": "Process id (use jobs to list process id)", "input": Argument.Single|Argument.Required|typeId.UInt32}) self.tags = "builtins" self.flags = ["console"] dff-1.3.0+dfsg.1/dff/modules/builtins/fileinfo.py000066400000000000000000000077341217176075400215620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_fileinfo_version__ = "1.0.0" from dff.api.vfs import * from dff.api.loader import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import Variant, typeId, Argument from dff.ui.console.utils import VariantTreePrinter class FILEINFO(Script): def __init__(self): Script.__init__(self, "fileinfo") self.vtreeprinter = VariantTreePrinter() def start(self, args): buff = "" node = args["file"].value() if args.has_key("max-items"): self.vtreeprinter.setMaxItemListToExpand(args["max-items"].value()) else: self.vtreeprinter.setMaxItemListToExpand(-1) if args.has_key("max-depth"): self.vtreeprinter.setMaxDepth(args["max-depth"].value()) else: self.vtreeprinter.setMaxDepth(-1) buff += self.fillBase(node) buff += self.fillAttributes(node) self.res["result"] = Variant(buff) def fillBase(self, node): buff = "" fsobj = node.fsobj() fsobjname = "" if fsobj != None: fsobjname = fsobj.name buff += "name :\t\t" + str(node.name()) + "\n" buff += "node type :\t\t" if node.isFile(): buff += "file" if node.hasChildren(): buff += " " + "with module(s) applied on it" if node.isDir(): buff += "folder" if not node.hasChildren(): buff += " " + "empty" if node.isDeleted(): buff += " " + "deleted" buff += "\n" buff += self.fillCompatModule(node) if node.hasChildren(): buff += self.fillChildren(node) buff += "generated by:\t\t" buff += fsobjname + "\n" buff += "size:\t\t\t" buff += str(node.size()) buff += "\n" return buff def fillCompatModule(self, node): buff = "" l = node.compatibleModules() if len(l) > 0: buff += "relevant module(s) :\t" for i in l: buff += str(i) + " " buff += "\n" return buff def fillChildren(self, node): buff = "children\t\t" children = node.children() filessize = 0 filecount = 0 dircount = 0 for child in children: if child.size(): filessize += child.size() filecount += 1 elif child.isDir() or child.hasChildren(): dircount += 1 if filecount > 0: buff += "file(s)" buff += str(filecount) + " totalizing " + str(filessize) + " bytes\n" if dircount > 0: buff += "folder(s) " buff += str(dircount) + "\n" return buff def fillAttributes(self, node): buff = "" vmap = node.attributes() if len(vmap) > 0: buff = self.vtreeprinter.fillMap(1, vmap, "attributes:\n") return buff class fileinfo(Module): """Display file attribute informations. (size, MAC time, ...)""" def __init__(self): Module.__init__(self, "fileinfo", FILEINFO) self.conf.addArgument({"name": "file", "input": Argument.Single|Argument.Required|typeId.Node, "description": "File for which metadata will be shown"}) self.conf.addArgument({"name": "max-items", "input": Argument.Single|Argument.Optional|typeId.UInt64, "description": "sets max items to expand in list (useful with large list)"}) self.conf.addArgument({"name": "max-depth", "input": Argument.Single|Argument.Optional|typeId.UInt64, "description": "sets max depth on variant tree"}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/find.py000066400000000000000000000105321217176075400206750ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_find_version__ = "1.2.0" from dff.api.vfs.libvfs import Node, VLink from dff.api.module.module import Module, Script from dff.api.events.libevents import EventHandler from dff.api.types.libtypes import typeId, Variant, Argument from dff.api.filters.libfilters import Filter class FIND(Script, EventHandler): def __init__(self): Script.__init__(self, "find") EventHandler.__init__(self) self.nodes = [] self.nodescount = 1 self.oldcur = 0 def start(self, args): self.nodes = [] self.nodescount = 1 self.oldcur = 0 fname = args["filter_name"].value() expression = args["expression"].value() root_node = args["root_node"].value() if args.has_key("verbose"): self.verbose = True else: self.verbose = False if args.has_key("recursive"): recursive = True else: recursive = False f = Filter(fname) f.connection(self) try: f.compile(expression) except RuntimeError: self.res["error"] = Variant("provided expression is not valid") f.process(root_node, recursive) self.res["total of matching nodes"] = Variant(len(self.nodes)) if args.has_key("save_result"): si_node = self.vfs.getnode("/Bookmarks") if si_node == None: root = self.vfs.getnode("/") si_node = Node("Bookmarks", 0, root) si_node.__disown__() fnode = Node(fname, 0, si_node) fnode.__disown__() for node in self.nodes: vl = VLink(node, fnode, node.name()) vl.__disown__() def Event(self, e): if e.type == 0x200: self.nodescount = e.value.value() self.res["total nodes"] = Variant(self.nodescount) elif e.type == 0x201: cur = e.value.value() progress = (cur * 100) / self.nodescount if progress > self.oldcur: self.stateinfo = str(progress) + " % (matching node: " + str(len(self.nodes)) + ")" elif e.type == 0x202: node = e.value.value() if self.verbose == True: print node.absolute() self.nodes.append(node) class find(Module): """Find files and folders based on provided filter expression""" def __init__(self): Module.__init__(self, "find", FIND) self.conf.addArgument({"name": "filter_name", "description": "Name of the filter", "input": Argument.Single|Argument.Required|typeId.String}) self.conf.addArgument({"name": "expression", "description": 'Expression provided to filter engine (e.g: name == w("*.jp?g", i)', "input": Argument.Single|Argument.Required|typeId.String}) self.conf.addArgument({"name": "root_node", "description": "node from which apply filter expression", "input": Argument.Single|Argument.Required|typeId.Node}) self.conf.addArgument({"name": "recursive", "description": "apply filter expression in recursive way (on all thre subtree from provided root_node)", "input": Argument.Empty}) self.conf.addArgument({"name": "save_result", "description": "save results by creating links to matching nodes", "input": Argument.Empty}) self.conf.addArgument({"name": "verbose", "description": "outputs matching node on console during processing", "input": Argument.Empty}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/history.py000066400000000000000000000036531217176075400214640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_history_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import Variant, typeId, Argument import dff.ui.history as hist class HISTORY(Script): def __init__(self): Script.__init__(self, "history") self.h = hist.history() def start(self, args): if len(args) > 1: self.res["error"] = Variant("too many arguments") elif args.has_key("clear"): self.h.clear() elif args.has_key("last"): last = args["last"].value() if last > len(self.h.hist): last = 0 else: last = len(self.h.hist) - last for i in xrange(last, len(self.h.hist)): print (str(i) + '\t' + self.h.hist[i]).strip('\n') else: for i in xrange(0, len(self.h.hist)): print (str(i) + '\t' + self.h.hist[i]).strip('\n') class history(Module): """Display an history of all launched command""" def __init__(self): Module.__init__(self, "history", HISTORY) self.conf.addArgument({"name": "clear", "description": "clear the history", "input": Argument.Empty}) self.conf.addArgument({"name": "last", "description": "lists only the last n lines", "input": Argument.Single|Argument.Optional|typeId.UInt32}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/info.py000066400000000000000000000130741217176075400207140ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_info_version__ = "1.0.0" import time from datetime import timedelta, datetime from dff.api.module.script import Script from dff.api.loader import loader from dff.api.module.module import Module from dff.api.taskmanager.processus import ProcessusManager from dff.api.types.libtypes import Parameter, Variant, Argument, typeId, ConfigManager from dff.ui.console.utils import VariantTreePrinter class INFO(Script, VariantTreePrinter): def __init__(self): Script.__init__(self, "info") VariantTreePrinter.__init__(self) self.loader = loader.loader() self.processusManager = ProcessusManager() self.cm = ConfigManager.Get() def show_config(self, modname): conf = self.cm.configByName(modname) res = "\n\tConfig:" arguments = conf.arguments() for argument in arguments: res += "\n\t\tname: " + str(argument.name()) res += "\n\t\tdescription: " + str(argument.description()) if argument.inputType() == Argument.Empty: res += "\n\t\tno input parameters" else: res += "\n\t\ttype: " + str(typeId.Get().typeToName(argument.type())) res += "\n\t\trequirement: " if argument.requirementType() == Argument.Optional: res += "optional" else: res += "mandatory" res += "\n\t\tinput parameters: " if argument.parametersType() == Parameter.NotEditable: res += "not editable " else: res += "editable " if argument.inputType() == Argument.List: res += "list" else: res += "single" pcount = argument.parametersCount() if pcount != 0: parameters = argument.parameters() res += "\n\t\tpredefined parameters: " for parameter in parameters: if argument.type() == typeId.Node: res += str(parameter.value().absolute()) else: res += parameter.toString() pcount -= 1 if pcount != 0: res += ", " res += "\n" constants = conf.constants() if len(constants) > 0: res += "\n\tConstant: \t" for constant in constants: res += "\n\t\tname: " + str(constant.name()) res += "\n\t\tdescription: " + str(constant.description()) res += "\n\t\ttype: " + str(typeId.Get().typeToName(constant.type())) cvalues = constant.values() cvallen = len(cvalues) if cvallen > 0: res += "\n\t\tvalues: " for cvalue in cvalues: if cvalue.type() == typeId.Node: res += str(cvalue.value().absolute()) else: res += cvalue.toString() cvallen -= 1 if cvallen != 0: res += ", " res += "\n" return res def show_arg(self, args): res = "" if len(args): res += "\n\n\t\tArguments: \t" for argname in args.keys(): res += "\n\t\t\tname: " + argname res += "\n\t\t\tparameters: " val = args[argname] if val.type() == typeId.List: vlist = val.value() vlen = len(vlist) for item in vlist: if item.type == typeId.Node: res += str(val.value().absolute()) else: res += item.toString() vlen -= 1 if vlen != 0: res += ", " elif val.type() == typeId.Node: res += str(val.value().absolute()) return res def show_res(self, results): res = self.fillMap(3, results, "\n\n\t\tResults:") return res def c_display(self): print self.info def getmodinfo(self, modname): conf = self.cm.configByName(modname) if conf == None: return self.info += "\n" + modname + self.show_config(modname) for proc in self.processusManager: if proc.mod.name == modname: self.info += "\n\tProcessus " + str(proc.pid) stime = datetime.fromtimestamp(proc.timestart) self.info += "\n\t\texecution started at : " + str(stime) if proc.timeend: etime = datetime.fromtimestamp(proc.timeend) self.info += "\n\t\texecution finished at : " + str(etime) else: etime = datetime.fromtimestamp(time.time()) delta = etime - stime self.info += "\n\t\texecution time: " + str(delta) self.info += self.show_arg(proc.args) self.info += self.show_res(proc.res) def start(self, args): self.info = "" if args.has_key("modules"): modnames = args['modules'].value() for modname in modnames: self.getmodinfo(modname.value()) else: self.modules = self.loader.modules for modname in self.modules: self.getmodinfo(modname) class info(Module): """Show info on loaded drivers: configuration, arguments, results """ def __init__(self): Module.__init__(self, "info", INFO) self.tags = "builtins" self.conf.addArgument({"name": "modules", "description": "Display information concerning provided modules", "input": Argument.Optional|Argument.List|typeId.String}) dff-1.3.0+dfsg.1/dff/modules/builtins/jobs.py000066400000000000000000000026151217176075400207150ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_jobs_version__ = "1.0.0" from dff.api.module.module import Module from dff.api.taskmanager.processus import ProcessusManager from dff.api.module.script import Script from dff.api.types.libtypes import Variant class JOBS(Script): def __init__(self): Script.__init__(self, "jobs") self.processusManager = ProcessusManager() def start(self, args): buff = "pid\tname\tstate\tinfo\n" for proc in self.processusManager: if proc.name != "jobs": buff += "[" + str(proc.pid) + "]\t" + proc.name + "\t" + proc.state + "\t" + str(proc.stateinfo) + "\n" if not buff: buff += "No processus launched yet !" self.res["result"] = Variant(buff) class jobs(Module): """Display launched processus""" def __init__(self): Module.__init__(self, "jobs", JOBS) self.tags = "builtins" self.flags = ["console"] dff-1.3.0+dfsg.1/dff/modules/builtins/link.py000066400000000000000000000030521217176075400207110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_link_version__ = "1.0.0" from dff.api.module.module import * from dff.api.exceptions.libexceptions import * from dff.api.types.libtypes import Argument, typeId, Variant class LINK(Script): def __init__(self): Script.__init__(self, "link") def start(self, args): dest = args["dest"].value() node = args["file"].value() self.vfs.link(node, dest) self.res["result"] = Variant(str("linked " + dest.path() + "/" + node.name() + " created").replace("//", "/")) class link(Module): def __init__(self): """Create a link to a file""" Module.__init__(self, "link", LINK) self.conf.addArgument({"name": "file", "description": "File to link to", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "dest", "description": "File pointing to the link", "input": Argument.Required|Argument.Single|typeId.Node}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/load.py000066400000000000000000000025001217176075400206700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_load_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module.module import * from dff.api.loader import * from dff.api.types.libtypes import Argument, typeId class LOAD(Script): def __init__(self): Script.__init__(self, "load") self.loader = loader.loader() def start(self, args): paths = args['files'].value() for vpath in paths: path = vpath.value() self.loader.do_load(path.path) class load(Module): """Load an external module""" def __init__(self): Module.__init__(self, "load", LOAD) self.conf.addArgument({"name": "files", "description": "local files or folders containing modules", "input": Argument.List|Argument.Required|typeId.Path}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/ls.py000066400000000000000000000055771217176075400204100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_ls_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import typeId, Argument class LS(Script): def __init__(self) : Script.__init__(self, "ls") self.vfs = vfs.vfs() def start(self, args): try: self.nodes = args["nodes"].value() except IndexError: self.nodes = [self.vfs.getcwd()] if args.has_key('recursive'): self.rec = True else: self.rec = False if args.has_key('long'): self.long = True else: self.long = False self._res = self.launch() def launch(self): for vnode in self.nodes: try: node = vnode.value() except AttributeError: node = vnode if self.rec: self.recurse(node) else: if node.hasChildren(): children = node.children() for child in children: self.ls(child) def recurse(self, cur_node): if cur_node.hasChildren(): self.ls(cur_node) next = cur_node.children() for next_node in next: if next_node.hasChildren(): self.recurse(next_node) def ls(self, node): buff = "" print self.display_node(node) def display_node(self, node): if self.long: return self.display_node_long(node) else: return self.display_node_simple(node) def display_node_long(self, node): buff = node.absolute() if not node.hasChildren(): buff += "/" if not node.hasChildren(): buff += '\t' + str(node.size()) return buff def display_node_simple(self, node): buff = '' buff = node.name() if node.hasChildren(): buff += "/" return buff class ls(Module): """List file and directory""" def __init__(self): Module.__init__(self, "ls", LS) self.conf.addArgument({"name": "nodes", "description": "files to list", "input": Argument.List|Argument.Optional|typeId.Node}) self.conf.addArgument({"name": "long", "description": "Display more information for each files", "input": Argument.Empty}) self.conf.addArgument({"name": "recursive", "description": "enables recursion on folders", "input": Argument.Empty}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/man.py000066400000000000000000000105531217176075400205330ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_man_version__ = "1.0.0" from dff.api.vfs import * from dff.api.loader import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.loader.loader import loader from dff.api.types.libtypes import Variant, Argument, typeId, Parameter, ConfigManager class MAN(Script): def __init__(self): Script.__init__(self, "man") self.type = "man" self.loader = loader() self.cm = ConfigManager.Get() def show_config(self, modname): conf = self.cm.configByName(modname) lconf = self.loader.get_conf(modname) if conf == None: return "no module <" + modname + "> found" res = "\nhelp for module <" + modname + ">:\n" if lconf != None and len(lconf.description): res += "Description:\n\t" + lconf.description arguments = conf.arguments() for argument in arguments: res += "\nArgument: " + str(argument.name()) res += "\n\tdescription: " + str(argument.description()) if argument.inputType() == Argument.Empty: res += "\n\tno input parameters\n" else: res += "\n\ttype: " + str(typeId.Get().typeToName(argument.type())) res += "\n\trequirement: " if argument.requirementType() == Argument.Optional: res += "optional" else: res += "mandatory" res += "\n\tinput parameters: " if argument.parametersType() == Parameter.NotEditable: res += "not editable " else: res += "editable " if argument.inputType() == Argument.List: res += "list" else: res += "single" pcount = argument.parametersCount() if pcount != 0: parameters = argument.parameters() res += "\n\tpredefined parameters: " for parameter in parameters: if argument.type() == typeId.Node: res += str(parameter.value().absolute()) else: res += parameter.toString() pcount -= 1 if pcount != 0: res += ", " res += "\n" constants = conf.constants() if len(constants) > 0: for constant in constants: res += "\nConstant: " + str(constant.name()) res += "\n\tdescription: " + str(constant.description()) res += "\n\ttype: " + str(typeId.Get().typeToName(constant.type())) cvalues = constant.values() cvallen = len(cvalues) if cvallen > 0: res += "\n\tvalues: " for cvalue in cvalues: if cvalue.type() == typeId.Node: res += str(cvalue.value().absolute()) else: res += cvalue.toString() cvallen -= 1 if cvallen != 0: res += ", " res += "\n" return res def c_display(self): print self.info def start(self, args): self.info = "" module = args["module"].value() self.info = self.show_config(module) class man(Module): """Displays help on other module""" def __init__(self): Module.__init__(self, "man", MAN) self.conf.addArgument({"name": "module", "input": Argument.Single|Argument.Required|typeId.String, "description": "module for which to print help"}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/open.py000066400000000000000000000046251217176075400207240ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_open_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module.module import * from dff.api.exceptions.libexceptions import * from dff.api.loader import * from dff.api.taskmanager.taskmanager import TaskManager from dff.api.taskmanager.scheduler import sched from dff.api.types.libtypes import Argument, typeId, ConfigManager from dff.ui.console.utils import VariantTreePrinter class Open(Script): def __init__(self): Script.__init__(self, "open") self.loader = loader.loader() self.cm = ConfigManager.Get() self.vtreeprinter = VariantTreePrinter() self.lmodules = self.loader.modules self.taskmanager = TaskManager() def start(self, args): node = args["file"].value() self.open(node) def open(self, node): try: mod = node.compatibleModules()[0] conf = self.cm.configByName(mod) argsnode = conf.argumentsByFlags(typeId.Node|Argument.Required) if len(argsnode) == 1: argnode = argsnode[0] margs = {argnode.name(): node} args = conf.generate(margs) self.taskmanager.add(mod, args, ["thread", "gui"], True) else: print "There are more than 1 file to provides" print "applying module " + mod + " on " + node.absolute() except IndexError: typeattr = node.attributesByName("type") if typeattr.type() == typeId.List: res = self.vtreeprinter.fillList(1, typeattr.value()) print "No module registered to handle following types " + res class open(Module): """Automatically apply module in background on a file. The module is determined by the file type.""" def __init__(self): Module.__init__(self, "open", Open) self.conf.addArgument({"name": "file", "description": "file to open", "input": Argument.Single|Argument.Required|typeId.Node}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/show_cwd.py000066400000000000000000000020201217176075400215630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_show_cwd_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module.module import * from dff.api.module import * class SHOW_CWD(Script): def __init__(self): Script.__init__(self, "show_cwd") self.vfs = vfs.vfs() def start(self, args): cwd = self.vfs.getcwd() print cwd.absolute() class show_cwd(Module): """Display current working directory""" def __init__(self): Module.__init__(self, "show_cwd", SHOW_CWD) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/builtins/show_db.py000066400000000000000000000304461217176075400214100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_show_db_version__ = "1.0.0" from dff.api.module.script import Script from dff.api.types.libtypes import Variant, Argument, typeId, ConfigManager from dff.api.taskmanager.processus import ProcessusManager from dff.api.module.module import Module from dff.ui.console.utils import VariantTreePrinter class SHOW_DB(Script): def __init__(self): Script.__init__(self, "show_db") self.cm = ConfigManager.Get() self.processusManager = ProcessusManager() self.ti = typeId.Get() self.vtreeprinter = VariantTreePrinter() def processesByModuleName(self, modname): processes = [] for proc in self.processusManager: if proc.name == modname: processes.append(proc) return processes def keyInConfigArguments(self, config, key): res = "" argument = config.argumentByName(key) if argument: if argument.type() == 0: res += "\n\targument switch" else: res += "\n\t\targument of type < " + self.ti.typeToName(argument.type()) + " >" count = argument.parametersCount() if count: res += "\n\t\tpredefined parameters: " parameters = argument.parameters() for parameter in parameters: if argument.type() == typeId.Node: res += str(parameter.value().absolute()) else: res += str(parameter.toString()) count -= 1 if count: res += ", " return res def keyInConfigConstants(self, config, key): res = "" constant = config.constantByName(key) if constant: res += "\n\t\tconstant of type < " + self.ti.typeToName(constant.type()) + " >" items = constant.values() count = len(items) res += "\n\t\tdefined constants: " for item in items: if constant.type() == typeId.Node: res += str(item.value().absolute()) else: res += str(item.toString()) count -= 1 if count: res += ", " return res def keyInProcessArguments(self, processes, key): res = "" for proc in processes: if proc.args.has_key(key): res += "\n\t\tparameters provided to process id " + str(proc.pid) + ":\n\t\t\t" arg = proc.args[key] if arg.type() == typeId.List: vlist = arg.value() lenvlist = len(vlist) for item in vlist: lenvlist -= 1 if item.type() == typeId.Node: res += str(item.value().absolute()) else: res += str(item.toString()) if lenvlist: res += ", " elif arg.type() == typeId.Node: res += str(arg.value().absolute()) else: res += str(arg.toString()) return res def keyInVMap(self, vmap, key): res = "" for ikey in vmap.keys(): vval = vmap[ikey] if vval.type() == typeId.Map: res += self.keyInVMap(vval.value(), key) elif vval.type() == typeId.List: res += self.keyInVList(vval.value(), key) elif ikey == key: if vval.type() == typeId.Node: res += "\n\t\t\t" + str(vval.value().absolute()) elif vval.type() == typeId.List: res += self.vtreeprinter.fillList(3, vval.value()) elif vval.type() == typeId.Map: res += self.vtreeprinter.fillMap(3, vval.value()) else: res += "\n\t\t\t" + str(vval.toString()) res += " (type < " + self.ti.typeToName(vval.type()) + " >)" return res def keyInVList(self, vlist, key): res = "" for item in vlist: if item.type() == typeId.Map: res += self.keyInVMap(item.value(), key) elif item.type() == typeId.List: res += self.keyInVList(item.value(), key) return res def keyInProcessResults(self, processes, key): res = "" for proc in processes: match = "" if len(proc.res): results = proc.res for ikey in results.keys(): item = results[ikey] if ikey == key: if item.type() == typeId.Node: match += "\n\t\t\t" + str(item.value().absolute()) elif item.type() == typeId.List: match += self.vtreeprinter.fillList(3, item.value()) elif item.type() == typeId.Map: match += self.vtreeprinter.fillMap(3, item.value()) else: match += "\n\t\t\t" + str(item.toString()) match += " (type < " + self.ti.typeToName(item.type()) + " >)" elif item.type() == typeId.Map: match += self.keyInVMap(item.value(), key) elif item.type() == typeId.List: match += self.keyInVList(item.value(), key) if match: res += "\n\t\tresults of process id " + str(proc.pid) + ":" res += match return res def get_dbinfo(self, key): res = "" configs = self.cm.configs() for config in configs: if config.origin() != "show_db": processes = self.processesByModuleName(config.origin()) match = self.keyInConfigArguments(config, key) if match: res += "\n\tmodule: " + config.origin() res += match res += self.keyInProcessArguments(processes, key) match = self.keyInConfigConstants(config, key) if match: res += "\n\tmodule: " + config.origin() res += match match = self.keyInProcessResults(processes, key) if match: res += "\n\tmodule: " + config.origin() res += match return res def fillProcessArgumentsKeys(self, keymap): for proc in self.processusManager: args = proc.args if args and proc.name != "show_db": for key in args.keys(): if not keymap.has_key(key): keymap[key] = [] arg = args[key] if arg.type() == 0: res = "\n\tswitch argument" else: res = "\n\targument of type " + self.ti.typeToName(arg.type()) res += " from " + proc.mod.conf.origin() + " in processus " + str(proc.pid) if arg.type() == typeId.List: res += "\n\t\t" vlist = arg.value() lenvlist = len(vlist) for item in vlist: lenvlist -= 1 if item.type() == typeId.Node: res += str(item.value().absolute()) else: res += str(item.toString()) if lenvlist: res += ", " elif arg.type() == typeId.Node: res += "\n\t\t" res += str(arg.value().absolute()) elif arg.type() != 0: res += "\n\t\t" res += str(arg.toString()) keymap[key].append(res) return keymap def fillKeyInList(self, vlist, keymap, cname, pid): for item in vlist: if item.type() == typeId.Map: keymap = self.fillKeyInMap(item.value(), keymap, cname, pid) return keymap def fillKeyInMap(self, vmap, keymap, cname, pid): for key in vmap.keys(): if not keymap.has_key(key): keymap[key] = [] val = vmap[key] if val.type() == typeId.List: res = "\n\tresult of type " + self.ti.typeToName(val.type()) res += " from " + cname + " in processus " + str(pid) keymap[key].append(res) keymap = self.fillKeyInList(val.value(), keymap, cname, pid) elif val.type() == typeId.Map: res = "\n\tresult of type " + self.ti.typeToName(val.type()) res += " from " + cname + " in processus " + str(pid) keymap[key].append(res) keymap = self.fillKeyInMap(val.value(), keymap, cname, pid) else: res = "\n\tresult of type " + self.ti.typeToName(val.type()) res += " from " + cname + " in processus " + str(pid) if val.type() == typeId.Node: res += "\n\t\t" + str(val.value().absolute()) else: res += "\n\t\t" + val.toString() keymap[key].append(res) return keymap def fillProcessResultsKeys(self, keymap): for proc in self.processusManager: results = proc.res if results and proc.name != "show_db": for key in results.keys(): if not keymap.has_key(key): keymap[key] = [] item = results[key] res = "\n\tresult of type " + self.ti.typeToName(item.type()) res += " from " + proc.mod.conf.origin() + " in processus " + str(proc.pid) if item.type() == typeId.Node: res += "\n\t\t" + str(item.value().absolute()) keymap[key].append(res) elif item.type() == typeId.List: keymap[key].append(res) keymap = self.fillKeyInList(item.value(), keymap, proc.mod.conf.origin(), proc.pid) elif item.type() == typeId.Map: keymap[key].append(res) keymap = self.fillKeyInMap(item.value(), keymap, proc.mod.conf.origin(), proc.pid) else: res += "\n\t\t" + str(item.value()) keymap[key].append(res) return keymap def fillAllArgumentsKey(self, keymap): configs = self.cm.configs() for config in configs: if config.origin() != "show_db": arguments = config.arguments() for argument in arguments: argname = argument.name() if not keymap.has_key(argname): keymap[argname] = [] if argument.type() == 0: stres = "\n\tswitch argument" else: stres = "\n\targument of type " + self.ti.typeToName(argument.type()) stres += " from " + config.origin() pcount = argument.parametersCount() if pcount != 0: parameters = argument.parameters() stres += "\n\t\t" for parameter in parameters: if argument.type() == typeId.Node: stres += str(parameter.value().absolute()) else: stres += parameter.toString() pcount -= 1 if pcount != 0: stres += ", " keymap[argname].append(stres) return keymap def fillAllConstantsKey(self, keymap): configs = self.cm.configs() for config in configs: if config.origin() != "show_db": constants = config.constants() for constant in constants: cname = constant.name() if not keymap.has_key(cname): keymap[cname] = [] stres = "\n\tconstant of type " + self.ti.typeToName(constant.type()) + " from " + config.origin() items = constant.values() pcount = len(items) stres += "\n\t\t" for item in items: if item.type() == typeId.Node: stres += str(item.value().absolute()) else: stres += item.toString() pcount -= 1 if pcount != 0: stres += ", " keymap[cname].append(stres) return keymap def get_alldbinfo(self): keymap = {} keymap = self.fillAllArgumentsKey(keymap) keymap = self.fillAllConstantsKey(keymap) keymap = self.fillProcessArgumentsKeys(keymap) keymap = self.fillProcessResultsKeys(keymap) res = "" for key in keymap.keys(): res += "\n\n" + key for item in keymap[key]: res += item return res def start(self, args): res = "Variable DB\n" if args.has_key("key"): key = args['key'].value() res += "key <" + key + ">" match = self.get_dbinfo(key) if match: res += match else: res += " not found in db" else: res += self.get_alldbinfo() print res class show_db(Module): """Show DFF Data-Base from a key-centric view""" def __init__(self): Module.__init__(self, "show_db", SHOW_DB) self.conf.addArgument({"name": "key", "description": "Display only this key value", "input": Argument.Single|Argument.Optional|typeId.String}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/connector/000077500000000000000000000000001217176075400175435ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/connector/CMakeLists.txt000066400000000000000000000015221217176075400223030ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py ) add_subdirectory(devices) add_subdirectory (local) IF (EWF_FOUND) add_subdirectory (ewf) ENDIF (EWF_FOUND) if (AFF_FOUND) add_subdirectory(aff) else (AFF_FOUND) message(STATUS "AFF library not found. Connector module will not be built.") endif(AFF_FOUND) dff-1.3.0+dfsg.1/dff/modules/connector/__init__.py000066400000000000000000000011001217176075400216440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ["local"] dff-1.3.0+dfsg.1/dff/modules/connector/aff/000077500000000000000000000000001217176075400202775ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/connector/aff/CMakeLists.txt000066400000000000000000000016701217176075400230430ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob IF (${AFF_VERSION} VERSION_GREATER "3.6.6") set(definitions -DNEW_AFF_LIB) ENDIF(${AFF_VERSION} VERSION_GREATER "3.6.6") if(WIN32) set(aff_files ${AFF_DYN_LIBRARIES}) endif(WIN32) dff_cpp_module(AFF CPP_FILES aff.cpp affnode.cpp SWIG_FILE aff.i INCLUDE_DIRS ${AFF_INCLUDE_DIR} LINK_LIBRARIES exceptions types vfs ${AFF_LIBRARY} DEFINITIONS ${definitions} EXTRA_FILES ${aff_files} ) dff-1.3.0+dfsg.1/dff/modules/connector/aff/aff.cpp000066400000000000000000000074651217176075400215530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "aff.hpp" #include "affnode.hpp" aff::aff() : fso("aff") { mutex_init(&this->__io_mutex); this->__fdm = new FdManager(); } aff::~aff() { mutex_destroy(&this->__io_mutex); } void aff::start(std::map args) { std::list vl; std::list::iterator vpath; AffNode* node; if (args.find("parent") != args.end()) this->parent = args["parent"]->value(); else this->parent = VFS::Get().GetNode("/"); if (args.find("path") != args.end()) vl = args["path"]->value >(); else throw(envError("aff module requires path argument")); if (args.find("cache size") != args.end()) { std::ostringstream cs; cs << args["cache size"]->value(); this->cache_size = cs.str(); } else this->cache_size = "2"; #ifndef WIN32 setenv("AFFLIB_CACHE_PAGES", this->cache_size.c_str(), 1); #else _putenv_s("AFFLIB_CACHE_PAGES", this->cache_size.c_str()); #endif for (vpath = vl.begin(); vpath != vl.end(); vpath++) { std::string path = (*vpath)->value()->path; AFFILE* affile = af_open(path.c_str(), O_RDONLY, 0); if (affile) { std::string nname = path.substr(path.rfind('/') + 1); node = new AffNode(nname, af_get_imagesize(affile), NULL, this, path, affile); this->registerTree(this->parent, node); this->res[path] = Variant_p(new Variant(std::string("added successfully by aff module"))); } else this->res[path] = Variant_p(new Variant(std::string("can't be added by aff module"))); } return ; } int aff::vopen(Node *node) { AffNode* affNode = dynamic_cast(node); if (affNode->affile) { fdinfo* fi = new fdinfo(); fi->node = node; fi->offset = 0; return (this->__fdm->push(fi)); } else return (-1); } int aff::vread(int fd, void *buff, unsigned int size) { int result; fdinfo* fi; AffNode* affNode = NULL; try { fi = this->__fdm->get(fd); affNode = dynamic_cast(fi->node); } catch (...) { return (-1); } mutex_lock(&this->__io_mutex); af_seek(affNode->affile, (int64_t)fi->offset, SEEK_SET); result = af_read(affNode->affile, (unsigned char*)buff, size); if (result > 0) fi->offset += result; mutex_unlock(&this->__io_mutex); return (result); } int aff::vclose(int fd) { this->__fdm->remove(fd); return (0); } uint64_t aff::vseek(int fd, uint64_t offset, int whence) { Node* node; fdinfo* fi; try { fi = this->__fdm->get(fd); node = fi->node; if (whence == 0) { if (offset <= node->size()) { fi->offset = offset; return (fi->offset); } } else if (whence == 1) { if (fi->offset + offset <= node->size()) { fi->offset += offset; return (fi->offset); } } else if (whence == 2) { fi->offset = node->size(); return (fi->offset); } } catch (...) { return ((uint64_t) -1); } return ((uint64_t) -1); } uint64_t aff::vtell(int32_t fd) { fdinfo* fi; try { fi = this->__fdm->get(fd); return (fi->offset); } catch (...) { return (uint64_t)-1; } } unsigned int aff::status(void) { return (0); } dff-1.3.0+dfsg.1/dff/modules/connector/aff/aff.hpp000066400000000000000000000026611217176075400215510ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __AFF_HH__ #define __AFF_HH__ #include "fso.hpp" #include "node.hpp" #include #include #include #include #include #include "variant.hpp" #include "vfs.hpp" #include "path.hpp" #include "fdmanager.hpp" #include "threading.hpp" #include #include #include class aff : public fso { private: mutex_def(__io_mutex); Node *parent; FdManager* __fdm; std::string cache_size; public: aff(); ~aff(); int32_t vopen(Node* handle); int32_t vread(int fd, void *buff, unsigned int size); int32_t vclose(int fd); uint64_t vseek(int fd, uint64_t offset, int whence); int32_t vwrite(int fd, void *buff, unsigned int size) { return 0; }; uint32_t status(void); uint64_t vtell(int32_t fd); virtual void start(std::map args); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/aff/aff.i000066400000000000000000000044151217176075400212110ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module AFF %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "rootnode.hpp" #include "aff.hpp" %} %import "../../../api/vfs/libvfs.i" %include "aff.hpp" %pythoncode %{ __dff_module_AFF_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import * from dff.api.vfs import vfs class AFF(Module): """Load AFF v3 files""" def __init__(self): Module.__init__(self, 'aff', aff) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "parent", "description": "files or folders will be added as child(ren) of this node or as the root node by default", "parameters": {"type": Parameter.Editable, "predefined": [vfs.vfs().getnode("/")]} }) self.conf.addArgument({"input": Argument.Required|Argument.List|typeId.Path, "name": "path", "description": "Path to the file or directory on your operating system."}) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.UInt32, "name": "cache size", "description": "Size of the pages cache, one page is 16 megabytes", "parameters": {"type": Parameter.Editable, "predefined" : [2]} }) self.tags = "Connectors" %} dff-1.3.0+dfsg.1/dff/modules/connector/aff/affnode.cpp000066400000000000000000000120451217176075400224070ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "affnode.hpp" int AffNode::addSegmentAttribute(Attributes* vmap, AFFILE* af, const char* segname) { #ifdef NEW_AFF_LIB uint32_t arg; #else unsigned long arg; #endif unsigned char *data = 0; if (segname[0] == 0) return (0); size_t data_len = 0; if(af_get_seg(af, segname, &arg, 0, &data_len)) { return (0); } data = (unsigned char *)malloc(data_len); if(af_get_seg(af, segname, 0, data, &data_len)) { free(data); return (0); } if(strcmp(segname, AF_ACQUISITION_SECONDS) == 0) { int hours = arg / 3600; int minutes = (arg / 60) % 60; int seconds = arg % 60; vtime* time = new vtime; time->hour = hours; time->minute = minutes; time->second = seconds; (*vmap)[std::string(segname)] = Variant_p(new Variant(time)); free(data); return (1); } if(((arg == AF_SEG_QUADWORD) && (data_len==8)) || af_display_as_quad(segname)) { switch(data_len) { case 8: (*vmap)[segname] = Variant_p(new Variant(af_decode_q(data))); break; case 0: (*vmap)[segname] = Variant_p(new Variant(0)); break; default: (*vmap)[segname] = Variant_p(new Variant(std::string("Cannot decode segment"))); } free(data); return (1); } if (data_len == 0 && arg != 0) { (*vmap)[std::string(segname)] = Variant_p(new Variant((uint64_t)arg)); free(data); return (1); } if(af_display_as_hex(segname) || (data_len == 16 && strstr(segname, "md5")) || (data_len == 20 && strstr(segname, "sha1"))) { char buf[80]; af_hexbuf(buf, sizeof(buf), data, data_len, AF_HEXBUF_NO_SPACES); (*vmap)[std::string(segname)] = Variant_p(new Variant(std::string(buf))); free(data); return (1); } else { (*vmap)[segname] = Variant_p(new Variant(std::string((char *)data))); free(data); return (1); } } Attributes AffNode::_attributes() { Attributes vmap; struct af_vnode_info vni; unsigned long total_segs = 0; unsigned long total_pages = 0; unsigned long total_hashes = 0; unsigned long total_signatures =0; unsigned long total_nulls = 0; vmap["orignal path"] = Variant_p(new Variant(this->originalPath)); AFFILE* affile = af_open(this->originalPath.c_str(), O_RDONLY, 0); if (affile) { vmap["dump type"] = Variant_p(new Variant(std::string(af_identify_file_name(this->originalPath.c_str(), 1)))); if (af_vstat(affile, &vni) == 0) { if (vni.segment_count_encrypted > 0 || vni.segment_count_signed > 0) { vmap["encrypted segments"] = Variant_p(new Variant(vni.segment_count_encrypted)); vmap["signed segments"] = Variant_p(new Variant(vni.segment_count_signed)); } std::vector segments; char segname[AF_MAX_NAME_LEN]; af_rewind_seg(affile); int64_t total_datalen = 0; size_t total_segname_len = 0; size_t datalen = 0; int aes_segs=0; while(af_get_next_seg(affile, segname, sizeof(segname), 0, 0, &datalen)==0) { total_segs++; total_datalen += datalen; total_segname_len += strlen(segname); if(segname[0]==0) total_nulls++; char hash[64]; int64_t page_num = af_segname_page_number(segname); int64_t hash_num = af_segname_hash_page_number(segname,hash,sizeof(hash)); if(page_num>=0) total_pages++; if(hash_num>=0) total_hashes++; if(strstr(segname,AF_SIG256_SUFFIX)) total_signatures++; if(strstr(segname,AF_AES256_SUFFIX)) aes_segs++; if((page_num>=0||hash_num>=0)) continue; if(af_is_encrypted_segment(segname)) continue; this->addSegmentAttribute(&vmap, affile, segname); } vmap["Total segments"] = Variant_p(new Variant((uint64_t)total_segs)); vmap["Total segments real"] = Variant_p(new Variant((uint64_t)(total_segs - total_nulls))); if (aes_segs) vmap["Encrypted segments"] = Variant_p(new Variant(aes_segs)); vmap["Page segments"] = Variant_p(new Variant((uint64_t)total_pages)); vmap["Hash segments"] = Variant_p(new Variant((uint64_t)total_hashes)); vmap["Signature segments"] = Variant_p(new Variant((uint64_t)total_signatures)); vmap["Null segments"] = Variant_p(new Variant((uint64_t)total_nulls)); vmap["Total data bytes"] = Variant_p(new Variant((uint64_t)total_datalen)); } } af_close(affile); return vmap; } AffNode::AffNode(std::string Name, uint64_t size, Node* parent, aff* fsobj, std::string origPath, AFFILE* _affile): Node(Name, size, parent, fsobj) { this->originalPath = origPath; this->affile = _affile; } AffNode::~AffNode() { } dff-1.3.0+dfsg.1/dff/modules/connector/aff/affnode.hpp000066400000000000000000000017711217176075400224200ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __AFFNODE_HPP__ #define __AFFNODE_HPP__ #include "aff.hpp" #include class AffNode : public Node { public: AffNode(std::string name, uint64_t size, Node* parent, class aff* fsobj, std::string originalPath, AFFILE* affFile); ~AffNode(); int addSegmentAttribute(Attributes* vmap, AFFILE* af, const char* segname); std::string originalPath; AFFILE* affile; virtual Attributes _attributes(); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/devices/000077500000000000000000000000001217176075400211655ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/connector/devices/CMakeLists.txt000066400000000000000000000014631217176075400237310ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob if (UNIX) set(devices_srcs devicenode.cpp udevices.cpp ) else (UNIX) set(devices_srcs devicenode.cpp wdevices.cpp ) endif (UNIX) dff_cpp_module(DEVICES CPP_FILES ${devices_srcs} SWIG_FILE devices.i LINK_LIBRARIES exceptions types vfs ) dff-1.3.0+dfsg.1/dff/modules/connector/devices/devicenode.cpp000066400000000000000000000015731217176075400240040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "devices.hpp" DeviceNode::DeviceNode(std::string devname, uint64_t size, fso* fsobj,std::string name = "") : Node(devname, size, 0, fsobj) { if (name != "") this->__name = name; else this->__name = devname; this->__devname = devname; } std::string DeviceNode::icon() { return (":dev_hd.png"); }dff-1.3.0+dfsg.1/dff/modules/connector/devices/devices.hpp000066400000000000000000000037741217176075400233330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __WINDEVICES_HH__ #define __WINDEVICES_HH__ #include "variant.hpp" #include "mfso.hpp" #include #include #include #include #include #include "node.hpp" #include "vfs.hpp" #include "path.hpp" #ifdef WIN32 #pragma comment(lib, "advapi32.lib") #include #include #include class DeviceBuffer { private: uint8_t* __buffer; uint64_t __offset; uint32_t __BPS; DWORD __currentSize; HANDLE __handle; uint64_t __devSize; void fillBuff(uint64_t offset); public: DeviceBuffer(HANDLE handle, uint32_t size, uint32_t BPS, uint64_t DevSize); ~DeviceBuffer(); uint32_t __size; uint32_t getData(void* buff, uint32_t size, uint64_t offset); }; #endif class DeviceNode : public Node { public: std::string icon(); std::string __devname; DeviceNode(std::string devname, uint64_t size, fso* fsobj,std::string name); }; class devices : public fso { private: Node *parent; class Node* __root; FdManager* __fdm; public: std::string devicePath; devices(); ~devices(); int32_t vopen(Node* handle); int32_t vread(int fd, void *buff, unsigned int size); int32_t vclose(int fd); uint64_t vseek(int fd, uint64_t offset, int whence); int32_t vwrite(int fd, void *buff, unsigned int size) { return 0; }; uint32_t status(void); uint64_t vtell(int32_t fd); virtual void start(std::map args); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/devices/devices.i000066400000000000000000000043731217176075400227700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module DEVICES %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vlink.hpp" #include "vtime.hpp" #include "export.hpp" #include "devices.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "devices.hpp" %pythoncode %{ __dff_module_devices_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import * from dff.api.vfs import vfs class DEVICES(Module): """Access devices connected to your computer.""" def __init__(self): Module.__init__(self, 'devices', devices) self.tags = "Connectors" self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "parent", "description": "The file will be added as son of this node or as the root node by default.", "parameters": {"type": Parameter.Editable, "predefined": [vfs.vfs().getnode("/")]} }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Path, "name": "path", "description": "Path to the file or directory on your operating system."}) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.UInt64, "name": "size", "description": "Size of the devices."}) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.String, "name": "name", "description": "Name of the created node."}) self.icon = ":dev_hd.png" %} dff-1.3.0+dfsg.1/dff/modules/connector/devices/udevices.cpp000066400000000000000000000063151217176075400235050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "devices.hpp" #include #include #include #include #include #include #include #include #include #include devices::devices(): fso("devices") { } devices::~devices() { } void devices::start(std::map args) { std::map::iterator argit; std::string path; std::string name; uint64_t size; if (args["parent"] == NULL) throw envError("Device module requires a parent argument."); else this->parent = args["parent"]->value(); if (args["path"] == NULL) throw envError("Device module require a device path argument."); else path = args["path"]->value()->path; if (args["size"] == NULL) size = 0; else size = args["size"]->value(); if (args["name"] == NULL) name = path.substr(path.rfind('/') + 1); else name = args["name"]->value(); DeviceNode* dev = new DeviceNode(path, size, this, name); this->registerTree(this->parent, dev); return ; } int devices::vopen(Node *node) { int n; struct stat stbuff; std::string file; DeviceNode* dev = dynamic_cast(node); #if defined(__FreeBSD__) if ((n = open(dev->__devname.c_str(), O_RDONLY)) == -1) #elif defined(__linux__) if ((n = open(dev->__devname.c_str(), O_RDONLY | O_LARGEFILE)) == -1) #endif throw vfsError("devices::open error can't open file"); if (stat(dev->__devname.c_str(), &stbuff) == -1) throw vfsError("devices::open error can't stat"); return (n); } int devices::vread(int fd, void *buff, unsigned int size) { int n; n = read(fd, buff, size); if (n < 0) { if (errno == EIO) { throw vfsError("devicess::EIO error"); } else throw vfsError("devices::vread error read = -1"); } return n; } int devices::vclose(int fd) { if (close(fd) == -1) { throw vfsError("devices::close error can't close"); } return (0); } uint64_t devices::vseek(int fd, uint64_t offset, int whence) { uint64_t n = 0; if (whence == 0) whence = SEEK_SET; else if (whence == 1) whence = SEEK_CUR; else if (whence == 2) whence = SEEK_END; #if defined(__FreeBSD__) || defined(__APPLE__) n = lseek(fd, offset, whence); #elif defined(__linux__) n = lseek64(fd, offset, whence); #endif if (n == ((uint64_t)-1)) { throw vfsError("devices::vseek can't seek error " + std::string(strerror(errno))); } return (n); } uint64_t devices::vtell(int32_t fd) { uint64_t pos; pos = this->vseek(fd, 0, 1); return pos; } unsigned int devices::status(void) { return (1); } dff-1.3.0+dfsg.1/dff/modules/connector/devices/wdevices.cpp000066400000000000000000000137231217176075400235100ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "devices.hpp" #include "typesconv.hpp" #include #include #include DeviceBuffer::DeviceBuffer(HANDLE hndl, uint32_t size, uint32_t bps, uint64_t devSize) { this->__handle = hndl; this->__size = size * bps; this->__currentSize = 0; this->__BPS = bps; this->__buffer = (uint8_t *)malloc(this->__size); this->__offset = 0; this->__devSize = devSize; this->fillBuff(0); } DeviceBuffer::~DeviceBuffer() { CloseHandle(this->__handle); free(this->__buffer); } void DeviceBuffer::fillBuff(uint64_t offset) { LARGE_INTEGER sizeConv; LARGE_INTEGER newOffset; if (this->__offset > this->__devSize) { this->__currentSize = 0; return; } this->__offset = ((offset / this->__BPS) * this->__BPS); sizeConv.QuadPart = this->__offset; SetFilePointerEx(this->__handle, sizeConv, &newOffset, 0); DWORD gsize; if (this->__offset + this->__size > this->__devSize) gsize = (DWORD)(this->__devSize - this->__offset); else gsize = this->__size; ReadFile(this->__handle, (void*)(this->__buffer), gsize, &(this->__currentSize) ,0); } uint32_t DeviceBuffer::getData(void *buff, uint32_t size, uint64_t offset) { if ((offset < this->__offset) || (offset > this->__offset + this->__currentSize) ||(offset + size > this->__offset + this->__currentSize)) { this->fillBuff(offset); } uint64_t leak = offset - this->__offset; if (size > this->__currentSize - leak) size = (uint32_t)(this->__currentSize - leak); memcpy(buff, (((char*)this->__buffer) + leak), size); return (size); } devices::devices(): fso("devices") { this->__fdm = new FdManager; } devices::~devices() { } void devices::start(std::map args) { std::string path; Path *lpath; s_ull sizeConverter; uint64_t size =0; std::string nname; if (args.find("parent") == args.end()) throw envError("Device module requires a parent argument."); else this->parent = args["parent"]->value(); if (args.find("path") == args.end()) throw envError("Device module require a device path argument."); else lpath = args["path"]->value(); if (args.find("size") == args.end()) size = 0; else size = args["size"]->value(); if (args.find("name") == args.end()) nname = ""; else nname = args["name"]->value(); this->devicePath = lpath->path; sizeConverter.ull = size; HANDLE hnd = CreateFileA(this->devicePath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (((HANDLE)hnd) == INVALID_HANDLE_VALUE) { res["error"] = Variant_p(new Variant(std::string("Can't open devices."))); return ; } else { LPDWORD lpBytesReturned = 0; DeviceIoControl(hnd, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, lpBytesReturned, NULL); if (!size) { GET_LENGTH_INFORMATION diskSize; if (DeviceIoControl(hnd, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &diskSize, sizeof(diskSize), lpBytesReturned,0)) size = (uint64_t)diskSize.Length.QuadPart; CloseHandle(hnd); } this->__root = new DeviceNode(this->devicePath, sizeConverter.ull, this, nname); this->__root->setFile(); this->registerTree(this->parent, this->__root); } } int devices::vopen(Node *node) { fdinfo* fi; int32_t fd; if (node != NULL) { fi = new fdinfo; int hnd = (int)CreateFileA(((DeviceNode*)node)->__devname.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); fi->id = new Variant((void*) (new DeviceBuffer((HANDLE)hnd, 100 * sizeof(uint8_t), 4096, node->size()))); fi->node = node; fi->offset = 0; fd = this->__fdm->push(fi); return (fd); } else return -1; } int devices::vread(int fd, void *buff, unsigned int origSize) { fdinfo* fi; DeviceBuffer* dbuff; uint32_t readed; uint32_t aReaded = 0; try { fi = this->__fdm->get(fd); dbuff = (DeviceBuffer*)fi->id->value(); } catch (...) { return (0); } while (aReaded < origSize) { readed = dbuff->getData(((uint8_t *)buff + aReaded), origSize - aReaded, fi->offset); fi->offset += ((uint64_t)readed); aReaded += readed; if (fi->offset > this->__root->size()) { fi->offset = this->__root->size(); return (aReaded); } if (readed < dbuff->__size) return (aReaded); } return aReaded; } int devices::vclose(int fd) { try { fdinfo* fi = this->__fdm->get(fd); delete ((DeviceBuffer*)fi->id->value()); this->__fdm->remove(fd); return (0); } catch (...) { return -1; } } uint64_t devices::vseek(int fd, uint64_t offset, int whence) { fdinfo* fi; Node* node; try { fi = this->__fdm->get(fd); node = dynamic_cast(fi->node); if (whence == 0) { if (offset <= node->size()) { fi->offset = offset; return (fi->offset); } } else if (whence == 1) { if (fi->offset + offset <= node->size()) { fi->offset += offset; return (fi->offset); } } else if (whence == 2) { fi->offset = node->size(); return (fi->offset); } } catch (...) { return ((uint64_t) -1); } return ((uint64_t) -1); } uint64_t devices::vtell(int32_t fd) { fdinfo* fi; try { fi = this->__fdm->get(fd); return (fi->offset); } catch (...) { return (uint64_t)-1; } } unsigned int devices::status(void) { return (1); } dff-1.3.0+dfsg.1/dff/modules/connector/ewf/000077500000000000000000000000001217176075400203245ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/connector/ewf/CMakeLists.txt000066400000000000000000000015521217176075400230670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob if(WIN32) set(ewf_files ${EWF_DYN_LIBRARIES}) set(definitions -D_LIBEWF_TYPES_H_INTEGERS) endif(WIN32) dff_cpp_module(EWF CPP_FILES ewf.cpp ewfnode.cpp SWIG_FILE ewf.i DEFINITIONS ${definitions} LINK_LIBRARIES exceptions types vfs ${EWF_LIBRARY} INCLUDE_DIRS ${EWF_INCLUDE_DIR} EXTRA_FILES ${ewf_files} ) dff-1.3.0+dfsg.1/dff/modules/connector/ewf/ewf.cpp000066400000000000000000000147121217176075400216160ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "ewf.hpp" #include "ewfnode.hpp" ewf::ewf() : fso("ewf") { mutex_init(&this->__io_mutex); this->__fdm = new FdManager(); this->ewf_ghandle = NULL; this->__ewf_error = NULL; this->files = NULL; } ewf::~ewf() { this->__cleanup(); mutex_destroy(&this->__io_mutex); } void ewf::__cleanup() { if (this->__ewf_error != NULL) { libewf_error_free(&this->__ewf_error); this->__ewf_error = NULL; } if (this->ewf_ghandle != NULL) { libewf_handle_close(this->ewf_ghandle, NULL); libewf_handle_free(&this->ewf_ghandle, NULL); this->ewf_ghandle = NULL; } if (this->files != NULL) { this->files = NULL; free(this->files); } } void ewf::__checkSignature(std::list< Variant_p > vl) throw (std::string) { std::list::iterator vpath; std::string err; char* cerr; this->files = (char**)malloc(sizeof(char*) * (vl.size() + 1)); this->nfiles = 0; for (vpath = vl.begin(); vpath != vl.end(); vpath++) { std::string path = (*vpath)->value()->path; if (libewf_check_file_signature(path.c_str(), &this->__ewf_error) == 1) { this->files[nfiles] = strdup((char*)path.c_str()); this->nfiles++; } else { if (this->__ewf_error != NULL) { cerr = new char[512]; libewf_error_backtrace_sprint(this->__ewf_error, cerr, 511); err = std::string(cerr); } else { std::ostringstream error; error << "file " << path << " is not a ewf file." << std::endl; err = error.str(); } throw (err); } } this->files[nfiles] = NULL; return ; } void ewf::__initHandle(libewf_handle_t** handle, libewf_error_t** error) throw (std::string) { std::string err; char* cerr; if (libewf_handle_initialize(handle, error) != 1) { if (error != NULL) { cerr = new char[512]; libewf_error_backtrace_sprint(*error, cerr, 511); err = std::string(cerr); delete cerr; } else err = std::string("Ewf: Unable to initialize handle"); throw (err); } return; } void ewf::__openHandle(libewf_handle_t* handle, libewf_error_t** error) throw (std::string) { std::string err; char* cerr; if (libewf_handle_open(handle, this->files, this->nfiles, LIBEWF_OPEN_READ, error) != 1) { if (error != NULL) { cerr = new char[512]; libewf_error_backtrace_sprint(*error, cerr, 511); err = std::string(cerr); } else err = std::string("Can't open EWF files"); throw (err); } return; } void ewf::__getVolumeName() { uint8_t* value; size_t val_size; std::string volume; if (libewf_handle_get_utf8_header_value_size(this->ewf_ghandle, (uint8_t*)"description", 11, &val_size, &this->__ewf_error) != 1) this->volumeName = std::string("ewf_volume"); else { value = new uint8_t[val_size]; if (libewf_handle_get_utf8_header_value(this->ewf_ghandle, (uint8_t*)"description", 11, value, val_size, &this->__ewf_error) == 1) this->volumeName = std::string((char*)value, val_size-1); else this->volumeName = std::string("ewf_volume"); delete value; } return; } void ewf::__getVolumeSize() throw (std::string) { std::string err; if (libewf_handle_get_media_size(this->ewf_ghandle, &this->volumeSize, &this->__ewf_error) != 1) { if (this->__ewf_error != NULL) { char* cerr = new char[512]; libewf_error_backtrace_sprint(this->__ewf_error, cerr, 511); err = std::string(cerr); } else err = std::string("Can't get EWF dump size."); throw (err); } return; } void ewf::start(std::map args) { std::list vl; EWFNode* ewfNode; if (args.find("parent") != args.end()) this->parent = args["parent"]->value(); else this->parent = VFS::Get().GetNode("/"); if (args.find("files") != args.end()) vl = args["files"]->value >(); else throw(envError("ewf module requires path argument")); try { this->__initHandle(&this->ewf_ghandle, &this->__ewf_error); this->__checkSignature(vl); this->__openHandle(this->ewf_ghandle, &this->__ewf_error); this->__getVolumeSize(); this->__getVolumeName(); ewfNode = new EWFNode(this->volumeName, this->volumeSize, NULL, this, vl); this->registerTree(this->parent, ewfNode); } catch (std::string err) { this->__cleanup(); this->res["error"] = Variant_p(new Variant(err)); } return ; } int ewf::vopen(Node *node) { fdinfo* fi = new fdinfo(); fi->node = node; fi->offset = 0; return (this->__fdm->push(fi)); } int ewf::vread(int fd, void *buff, unsigned int size) { fdinfo* fi; try { fi = this->__fdm->get(fd); } catch (...) { return (0); } int res = 0; mutex_lock(&this->__io_mutex); res = libewf_handle_read_random(this->ewf_ghandle, buff, size, fi->offset, NULL); if (res > 0) fi->offset += res; mutex_unlock(&this->__io_mutex); if (res < 0) return (0); return (res); } int ewf::vclose(int fd) { this->__fdm->remove(fd); return 0; } uint64_t ewf::vseek(int fd, uint64_t offset, int whence) { Node* node; fdinfo* fi; try { fi = this->__fdm->get(fd); node = fi->node; if (whence == 0) { if (offset <= node->size()) { fi->offset = offset; return (fi->offset); } } else if (whence == 1) { if (fi->offset + offset <= node->size()) { fi->offset += offset; return (fi->offset); } } else if (whence == 2) { fi->offset = node->size(); return (fi->offset); } } catch (...) { return ((uint64_t) -1); } return ((uint64_t) -1); } uint64_t ewf::vtell(int32_t fd) { fdinfo* fi; try { fi = this->__fdm->get(fd); return fi->offset; } catch (...) { return (-1); } } unsigned int ewf::status(void) { return (0); } dff-1.3.0+dfsg.1/dff/modules/connector/ewf/ewf.hpp000066400000000000000000000037101217176075400216170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __EWF_HH__ #define __EWF_HH__ #if defined( _MSC_VER ) #if defined( _WIN64 ) typedef __int64 ssize_t; #else typedef __int32 ssize_t; #endif #endif #include "fso.hpp" #include "node.hpp" #include #include #include #include #include "variant.hpp" #include "vfs.hpp" #include "path.hpp" #include "fdmanager.hpp" #include "threading.hpp" #include class ewf : public fso { private: mutex_def(__io_mutex); Node* parent; FdManager* __fdm; size64_t volumeSize; std::string volumeName; char** files; uint16_t nfiles; libewf_error_t* __ewf_error; void __checkSignature(std::list< Variant_p > vl) throw (std::string); void __initHandle(libewf_handle_t** handle, libewf_error_t** error) throw (std::string); void __openHandle(libewf_handle_t* handle, libewf_error_t** error) throw (std::string); void __getVolumeSize() throw (std::string); void __getVolumeName(); void __cleanup(); public: ewf(); ~ewf(); libewf_handle_t* ewf_ghandle; int32_t vopen(Node* handle); int32_t vread(int fd, void *buff, unsigned int size); int32_t vclose(int fd); uint64_t vseek(int fd, uint64_t offset, int whence); int32_t vwrite(int fd, void *buff, unsigned int size) { return 0; }; uint32_t status(void); uint64_t vtell(int32_t fd); virtual void start(std::map args); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/ewf/ewf.i000066400000000000000000000034751217176075400212700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module EWF %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "rootnode.hpp" #include "ewf.hpp" %} %import "../../../api/vfs/libvfs.i" %include "ewf.hpp" %pythoncode %{ __dff_module_EWF_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import * from dff.api.vfs import vfs class EWF(Module): """EWF connector, load E01 dump""" def __init__(self): Module.__init__(self, 'ewf', ewf) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.Node, "name": "parent", "description": "Path where the EWF dump will be created", "parameters": {"type": Parameter.Editable, "predefined": [vfs.vfs().getnode("/")]} }) self.conf.addArgument({"input": Argument.Required|Argument.List|typeId.Path, "name": "files", "description": "EWF files to open"}) self.tags = "Connectors" %} dff-1.3.0+dfsg.1/dff/modules/connector/ewf/ewfnode.cpp000066400000000000000000000076761217176075400224770ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "ewfnode.hpp" std::string EWFNode::__getHashIdentifier(uint32_t index) throw() { size_t id_size; uint8_t* id; std::string identifier; identifier = ""; if (libewf_handle_get_hash_value_identifier_size(this->ewfso->ewf_ghandle, index, &id_size, NULL) == 1) { id = new uint8_t[id_size]; if (libewf_handle_get_hash_value_identifier(this->ewfso->ewf_ghandle, index, id, id_size, NULL) == 1) identifier = std::string((char*)id); delete id; } return identifier; } std::string EWFNode::__getHashValue(std::string identifier) throw () { size_t val_size; uint8_t* val; std::string value; value = ""; if (libewf_handle_get_utf8_hash_value_size(this->ewfso->ewf_ghandle, (uint8_t*)identifier.c_str(), identifier.size(), &val_size, NULL) == 1) { val = new uint8_t[val_size]; if (libewf_handle_get_utf8_hash_value(this->ewfso->ewf_ghandle, (uint8_t*)identifier.c_str(), identifier.size(), val, val_size, NULL) == 1) value = std::string((char*)val); delete val; } return value; } std::string EWFNode::__getIdentifier(uint32_t index) throw () { size_t id_size; uint8_t* id; std::string identifier; identifier = ""; if (libewf_handle_get_header_value_identifier_size(this->ewfso->ewf_ghandle, index, &id_size, NULL) == 1) { id = new uint8_t[id_size]; if (libewf_handle_get_header_value_identifier(this->ewfso->ewf_ghandle, index, id, id_size, NULL) == 1) identifier = std::string((char*)id); delete id; } return identifier; } std::string EWFNode::__getValue(std::string identifier) throw () { size_t val_size; uint8_t* val; std::string value; value = ""; if (libewf_handle_get_utf8_header_value_size(this->ewfso->ewf_ghandle, (uint8_t*)identifier.c_str(), identifier.size(), &val_size, NULL) == 1) { val = new uint8_t[val_size]; if (libewf_handle_get_utf8_header_value(this->ewfso->ewf_ghandle, (uint8_t*)identifier.c_str(), identifier.size(), val, val_size, NULL) == 1) value = std::string((char*)val); delete val; } return value; } Attributes EWFNode::_attributes() { Attributes attr; uint32_t numval; std::string identifier; std::string value; if (libewf_handle_set_header_values_date_format(this->ewfso->ewf_ghandle, LIBEWF_DATE_FORMAT_CTIME, NULL) == 1) { if (libewf_handle_get_number_of_header_values(this->ewfso->ewf_ghandle, &numval, NULL) == 1) { for (uint32_t i = 0; i != numval; i++) { try { identifier = this->__getIdentifier(i); if (!identifier.empty()) { value = this->__getValue(identifier); if (!value.empty()) attr[identifier] = Variant_p(new Variant(value)); } } catch (std::exception) { } } } } if (libewf_handle_get_number_of_hash_values(this->ewfso->ewf_ghandle, &numval, NULL) == 1) { for (uint32_t i = 0; i != numval; i++) { try { identifier = this->__getHashIdentifier(i); if (!identifier.empty()) { value = this->__getHashValue(identifier); if (!value.empty()) attr[identifier] = Variant_p(new Variant(value)); } } catch (std::exception) { } } } return attr; } EWFNode::EWFNode(std::string Name, uint64_t size, Node* parent, ewf* fsobj, std::list origPath): Node(Name, size, parent, fsobj) { this->originalPath = origPath; this->ewfso = fsobj; } EWFNode::~EWFNode() { } dff-1.3.0+dfsg.1/dff/modules/connector/ewf/ewfnode.hpp000066400000000000000000000023021217176075400224610ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __EWFNODE_HPP__ #define __EWFNODE_HPP__ #include "typesconv.hpp" #include "ewf.hpp" #include class EWFNode : public Node { private: std::string __getHashIdentifier(uint32_t index) throw(); std::string __getHashValue(std::string identifier) throw (); std::string __getIdentifier(uint32_t index) throw (); std::string __getValue(std::string identifier) throw (); public: EWFNode(std::string name, uint64_t size, Node* parent, class ewf* fsobj, std::list originalPath); ~EWFNode(); ewf* ewfso; std::list originalPath; virtual Attributes _attributes(); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/local/000077500000000000000000000000001217176075400206355ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/connector/local/CMakeLists.txt000066400000000000000000000015621217176075400234010ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob if (UNIX) set(local_srcs ulocal.cpp ulocalnode.cpp ) else (UNIX) set(local_srcs wlocal.cpp wlocalnode.cpp ) endif(UNIX) dff_cpp_module(LOCAL CPP_FILES ${local_srcs} SWIG_FILE local.i LINK_LIBRARIES exceptions types vfs EXTRA_FILES __init__.py ) dff-1.3.0+dfsg.1/dff/modules/connector/local/__init__.py000066400000000000000000000011001217176075400227360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ["LOCAL"] dff-1.3.0+dfsg.1/dff/modules/connector/local/local.hpp000066400000000000000000000033711217176075400224440ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __LOCAL_HH__ #define __LOCAL_HH__ #include "fso.hpp" #include "node.hpp" #include #include #include #include #include #include "variant.hpp" #include "vfs.hpp" #include "path.hpp" #ifdef WIN32 #include "wlocalnode.hpp" #else #include "ulocalnode.hpp" #endif class local : public fso { private: unsigned int nfd; std::string basePath; int vread_error(int fd, void *buff, unsigned int size); Node *parent; void createTree(std::list); #ifndef WIN32 class ULocalNode* __root; #else class WLocalNode* __root; #endif public: #ifndef WIN32 void iterdir(std::string path, Node* parent); #else std::string relativePath(std::string path); void createPath(std::string origPath); void frec(const char *, Node *rfv); #endif local(); ~local(); int32_t vopen(Node* handle); int32_t vread(int fd, void *buff, unsigned int size); int32_t vclose(int fd); uint64_t vseek(int fd, uint64_t offset, int whence); int32_t vwrite(int fd, void *buff, unsigned int size) { return 0; }; uint32_t status(void); uint64_t vtell(int32_t fd); virtual void start(std::map args); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/local/local.i000066400000000000000000000036251217176075400221070ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module LOCAL %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "local.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "local.hpp" %pythoncode %{ __dff_module_LOCAL_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import * from dff.api.vfs import vfs class LOCAL(Module): """Add file from your operating system to the VFS""" def __init__(self): Module.__init__(self, 'local', local) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.Node, "name": "parent", "description": "files or folders will be added as child(ren) of this node or as the root node by default", "parameters": {"type": Parameter.Editable, "predefined": [vfs.vfs().getnode("/")]} }) self.conf.addArgument({"input": Argument.Required|Argument.List|typeId.Path, "name": "path", "description": "Path to the file or directory on your operating system."}) self.tags = "Connectors" %} dff-1.3.0+dfsg.1/dff/modules/connector/local/ulocal.cpp000066400000000000000000000126221217176075400226230ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "local.hpp" #include #include #include #include #include #include #include #include #include #include void local::iterdir(std::string dir, Node *parent) { struct stat stbuff; struct dirent* dp; DIR* dfd; ULocalNode* tmp; uint64_t total; std::string upath; if ((dfd = opendir(dir.c_str()))) { while ((dp = readdir(dfd))) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; upath = dir + "/" + dp->d_name; if (lstat(upath.c_str(), &stbuff) != -1) { if (((stbuff.st_mode & S_IFMT) == S_IFDIR )) { tmp = new ULocalNode(dp->d_name, 0, parent, this, ULocalNode::DIR, upath); total++; this->iterdir(upath, tmp); } else { tmp = new ULocalNode(dp->d_name, stbuff.st_size, parent, this, ULocalNode::FILE, upath); total++; } } } closedir(dfd); } } local::local(): fso("local") { } local::~local() { } void local::createTree(std::list vl) { std::list::iterator it; Path* tpath; std::string name; struct stat stbuff; uint64_t size = 0; for (it = vl.begin(); it != vl.end(); it++) { tpath = (*it)->value(); if ((tpath->path.rfind('/') + 1) == tpath->path.length()) tpath->path.resize(tpath->path.rfind('/')); name = tpath->path.substr(tpath->path.rfind("/") + 1); this->basePath = tpath->path.substr(0, tpath->path.rfind('/')); if (stat(tpath->path.c_str(), &stbuff) == -1) { return ; } if (((stbuff.st_mode & S_IFMT) == S_IFDIR )) { Node *dir = new ULocalNode(name, 0, NULL, this, ULocalNode::DIR, tpath->path); this->iterdir(tpath->path, dir); this->registerTree(this->parent, dir); } else { Node *f; if (size) { f = new ULocalNode(name, size, NULL, this, ULocalNode::FILE, tpath->path); this->registerTree(this->parent, f); } else { f = new ULocalNode(name, stbuff.st_size, NULL, this, ULocalNode::FILE, tpath->path); this->registerTree(this->parent, f); } } } } void local::start(std::map args) { std::map::iterator argit; this->nfd = 0; if ((argit = args.find("parent")) != args.end()) this->parent = argit->second->value(); else this->parent = VFS::Get().GetNode("/"); if ((argit = args.find("path")) != args.end()) if (argit->second != NULL) this->createTree(argit->second->value >()); else throw(envError("local module requires at least one path parameter")); else throw(envError("local module requires path argument")); return ; } int local::vopen(Node *node) { int n; struct stat stbuff; std::string file; ULocalNode* unode = dynamic_cast(node); if (unode == NULL) return (0); file = unode->originalPath; #if defined(__FreeBSD__) || defined(__APPLE__) if ((n = open(file.c_str(), O_RDONLY)) == -1) #elif defined(__linux__) if ((n = open(file.c_str(), O_RDONLY | O_LARGEFILE)) == -1) #endif throw vfsError("local::open error can't open file"); if (stat(file.c_str(), &stbuff) == -1) throw vfsError("local::open error can't stat"); if (((stbuff.st_mode & S_IFMT) == S_IFDIR )) throw vfsError("local::open error can't open directory"); nfd++; return (n); } int local::vread_error(int fd, void *buff, unsigned int size) { unsigned int pos; int n; int toread; pos = 0; while (pos < size) { if (size - pos < 512) toread = size - pos; else toread = 512; if ((n = read(fd, ((char*)buff)+pos, toread)) == -1) { memset(((char*)buff)+pos, 0, toread); this->vseek(fd, toread, 1); } pos += toread; } return size; } int local::vread(int fd, void *buff, unsigned int size) { int n; n = read(fd, buff, size); if (n < 0) { if (errno == EIO) { return this->vread_error(fd, buff, size); } else throw vfsError("local::vread error read = -1"); } return n; } int local::vclose(int fd) { if (close(fd) == -1) { throw vfsError("local::close error can't close"); } nfd--; return (0); } uint64_t local::vseek(int fd, uint64_t offset, int whence) { uint64_t n = 0; if (whence == 0) whence = SEEK_SET; else if (whence == 1) whence = SEEK_CUR; else if (whence == 2) whence = SEEK_END; #if defined(__FreeBSD__) || defined(__APPLE__) n = lseek(fd, offset, whence); #elif defined(__linux__) n = lseek64(fd, offset, whence); #endif if (n == ((uint64_t)-1)) { throw vfsError("local::vseek can't seek error " + std::string(strerror(errno))); } return (n); } uint64_t local::vtell(int32_t fd) { uint64_t pos; pos = this->vseek(fd, 0, 1); return pos; } unsigned int local::status(void) { return (nfd); } dff-1.3.0+dfsg.1/dff/modules/connector/local/ulocalnode.cpp000066400000000000000000000045561217176075400235000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "ulocalnode.hpp" #include #include #include Attributes ULocalNode::_attributes() { struct stat* st; Attributes vmap; vmap["original path"] = Variant_p(new Variant(this->originalPath)); if ((st = this->localStat()) != NULL) { vmap["uid"] = Variant_p(new Variant(st->st_uid)); vmap["gid"] = Variant_p(new Variant(st->st_gid)); vmap["inode"] = Variant_p(new Variant(st->st_ino)); vmap["modified"] = Variant_p(new Variant(this->utimeToVtime(&(st->st_mtime)))); vmap["accessed"] = Variant_p(new Variant(this->utimeToVtime(&(st->st_atime)))); vmap["changed"] = Variant_p(new Variant(this->utimeToVtime(&(st->st_ctime)))); free(st); } return vmap; } struct stat* ULocalNode::localStat(void) { std::string file; struct stat* st; st = (struct stat*)malloc(sizeof(struct stat)); if (lstat(this->originalPath.c_str(), st) != -1) return st; else { free(st); return NULL; } } vtime* ULocalNode::utimeToVtime(time_t* tt) { struct tm* t; vtime *vt = new vtime; if (tt != NULL) { if ((t = gmtime(tt)) != NULL) { vt->year = t->tm_year + 1900; vt->month = t->tm_mon + 1; vt->day = t->tm_mday; vt->hour = t->tm_hour; vt->minute = t->tm_min; vt->second = t->tm_sec; vt->dst = t->tm_isdst; vt->wday = t->tm_wday; vt->yday = t->tm_yday; vt->usecond = 0; } } return vt; } ULocalNode::ULocalNode(std::string Name, uint64_t size, Node* parent, local* fsobj, uint8_t type, std::string origPath): Node(Name, size, parent, fsobj) { this->originalPath = origPath; switch (type) { case DIR: this->setDir(); break; case FILE: this->setFile(); break; default: break; } } ULocalNode::~ULocalNode() { } dff-1.3.0+dfsg.1/dff/modules/connector/local/ulocalnode.hpp000066400000000000000000000020341217176075400234720ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __ULOCALNODE_HPP__ #define __ULOCALNODE_HPP__ #include "local.hpp" #include "node.hpp" class ULocalNode: public Node { private: struct stat* localStat(void); vtime* utimeToVtime(time_t* t1); public: std::string originalPath; enum Type { FILE, DIR }; ULocalNode(std::string name, uint64_t size, Node* parent, class local* fsobj, uint8_t type, std::string origPath); virtual Attributes _attributes(); ~ULocalNode(); }; #endif dff-1.3.0+dfsg.1/dff/modules/connector/local/wlocal.cpp000066400000000000000000000115421217176075400226250ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob * Christophe Malinge */ #include "local.hpp" #include "typesconv.hpp" #include #include #include void local::frec(const char *name, Node *rfv) { HANDLE hd; WIN32_FIND_DATAA find; std::string nname; std::string searchPath = name; s_ull sizeConverter; searchPath += "\\*"; if ((hd = FindFirstFileA(searchPath.c_str(), &find)) != INVALID_HANDLE_VALUE) { do { WLocalNode *tmp; if (!strcmp(find.cFileName, ".") || !strcmp(find.cFileName, "..")) continue ; nname = name; nname += "\\"; nname += find.cFileName; if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { tmp = new WLocalNode(std::string(find.cFileName), 0, rfv, this, WLocalNode::DIR, nname); this->frec((char *)nname.c_str(), tmp); } else { sizeConverter.Low = find.nFileSizeLow; sizeConverter.High = find.nFileSizeHigh; tmp = new WLocalNode(std::string(find.cFileName), sizeConverter.ull, rfv, this, WLocalNode::FILE, nname); } } while (FindNextFileA(hd, &find)); FindClose(hd); } } local::local(): fso("local") { } local::~local() { } void local::start(std::map args) { std::list paths; std::map::iterator argit; if ((argit = args.find("parent")) != args.end()) this->parent = argit->second->value(); else this->parent = VFS::Get().GetNode("/"); if ((argit = args.find("path")) != args.end()) { paths = argit->second->value >(); if (paths.size() == 0) throw (envError("local module requires at least one path parameter")); } else throw (envError("local modules requires path argument")); std::list::iterator path = paths.begin(); for (; path != paths.end(); ++path) { this->createPath(((*path)->value())->path); } } std::string local::relativePath(std::string path) { std::string relPath; while (path.find('/') != std::string::npos) { path[path.find('/')] = '\\'; } if ((path.rfind('/') + 1) == path.length()) path.resize(path.rfind('/')); if ((path.rfind('\\') + 1) == path.length()) path.resize(path.rfind('\\')); relPath = path; if (relPath.rfind("\\") <= relPath.size()) relPath = relPath.substr(relPath.rfind("\\") + 1); else relPath = relPath.substr(relPath.rfind("/") + 1); return relPath; } void local::createPath(std::string origPath) { WIN32_FILE_ATTRIBUTE_DATA info; s_ull sizeConverter; if(!GetFileAttributesExA(origPath.c_str(), GetFileExInfoStandard, &info)) { res["error"] = Variant_p(new Variant(std::string("error stating file: " + origPath))); return ; } if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { WLocalNode* node = new WLocalNode(this->relativePath(origPath), 0, NULL, this, WLocalNode::DIR, origPath); this->frec(origPath.c_str(), node); this->registerTree(this->parent, node); } else { sizeConverter.Low = info.nFileSizeLow; sizeConverter.High = info.nFileSizeHigh; WLocalNode* node = new WLocalNode(this->relativePath(origPath), sizeConverter.ull, NULL, this, WLocalNode::FILE, origPath); this->registerTree(this->parent, node); } return ; } int local::vopen(Node *wnode) { WLocalNode* node = dynamic_cast(wnode); if (node != NULL) { std::string filePath = node->originalPath; return ((int)CreateFileA(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0)); } else return -1; } int local::vread(int fd, void *buff, unsigned int size) { DWORD readed; if (ReadFile((HANDLE)fd, buff, size, &readed ,0)) return (readed); else return (0); } int local::vclose(int fd) { return (!CloseHandle((HANDLE)fd)); } uint64_t local::vseek(int fd, uint64_t offset, int whence) { s_ull sizeConverter; sizeConverter.ull = offset; if (whence == 0) whence = FILE_BEGIN; else if (whence == 1) whence = FILE_CURRENT; else if (whence == 2) whence = FILE_END; return (SetFilePointer((HANDLE)fd, sizeConverter.Low, ((long*)&sizeConverter.High), whence)); } uint64_t local::vtell(int32_t fd) { uint64_t pos; pos = this->vseek(fd, 0, 1); return pos; } unsigned int local::status(void) { return (nfd); } dff-1.3.0+dfsg.1/dff/modules/connector/local/wlocalnode.cpp000066400000000000000000000037601217176075400234760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge */ #include "wlocalnode.hpp" #include WLocalNode::WLocalNode(std::string Name, uint64_t size, Node* parent, fso* fsobj, uint8_t type, std::string origPath): Node(Name, size, parent, fsobj) { switch (type) { case DIR: this->setDir(); break; case FILE: this->setFile(); break; default: break; } this->originalPath = origPath; } WLocalNode::~WLocalNode() { } Attributes WLocalNode::_attributes(void) { WIN32_FILE_ATTRIBUTE_DATA info; Attributes attr; attr["original path"] = Variant_p(new Variant(this->originalPath)); if(!GetFileAttributesExA(this->originalPath.c_str(), GetFileExInfoStandard, &info)) return attr; attr["modified"] = Variant_p(new Variant(this->wtimeToVtime(&(info.ftLastWriteTime)))); attr["accessed"] = Variant_p(new Variant(this->wtimeToVtime(&(info.ftLastAccessTime)))); attr["creation"] = Variant_p(new Variant(this->wtimeToVtime(&(info.ftCreationTime)))); return attr; } vtime* WLocalNode::wtimeToVtime(FILETIME *tt) { SYSTEMTIME stUTC; vtime* vt = new vtime; if (tt == NULL) return vt; if (FileTimeToSystemTime(tt, &stUTC) == 0) return vt; vt->year = stUTC.wYear; vt->month = stUTC.wMonth; vt->day = stUTC.wDay; vt->hour = stUTC.wHour; vt->minute = stUTC.wMinute; vt->second = stUTC.wSecond; vt->dst = 0; vt->wday = stUTC.wDayOfWeek; vt->yday = 0; vt->usecond = stUTC.wMilliseconds; return vt; } dff-1.3.0+dfsg.1/dff/modules/connector/local/wlocalnode.hpp000066400000000000000000000017121217176075400234760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge */ #ifndef __WLOCALNODE_HPP__ #define __WLOCALNODE_HPP__ #include "node.hpp" #include "vfile.hpp" class WLocalNode: public Node { private: vtime* wtimeToVtime(FILETIME *); public: std::string originalPath; enum Type { FILE, DIR }; WLocalNode(std::string, uint64_t, Node *, fso *, uint8_t, std::string); ~WLocalNode(); Attributes _attributes(void); }; #endif dff-1.3.0+dfsg.1/dff/modules/databases/000077500000000000000000000000001217176075400175005ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/databases/CMakeLists.txt000066400000000000000000000011721217176075400222410ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # jeremy MOUNIER install_file( __init__.py ) add_subdirectory(winreg) add_subdirectory(sqlite) dff-1.3.0+dfsg.1/dff/modules/databases/__init__.py000066400000000000000000000011411217176075400216060ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # __all__ = ["winreg", "msiecf", "firecache", "sqlite"] dff-1.3.0+dfsg.1/dff/modules/databases/sqlite/000077500000000000000000000000001217176075400210015ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/databases/sqlite/CMakeLists.txt000066400000000000000000000011501217176075400235360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER install_file( __init__.py sqlitedb.py sqlitemanager.py ) dff-1.3.0+dfsg.1/dff/modules/databases/sqlite/__init__.py000066400000000000000000000011161217176075400231110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier __all__ = ["sqlite", "sqlitemanager"] dff-1.3.0+dfsg.1/dff/modules/databases/sqlite/sqlitedb.py000066400000000000000000000030571217176075400231670ustar00rootroot00000000000000__dff_module_testapsw_version__ = "1.0.0" import apsw from struct import unpack from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Variant, VList, VMap, Argument, Parameter, typeId from dff.api.apswvfs import apswvfs from dff.api.module.manager import ModuleProcessusManager from sqlitemanager import SqliteManager ModuleProcessusManager().register(SqliteManager('SqliteDB')) class SqliteDB(Script): def __init__(self): Script.__init__(self, "SqliteDB") self.name = "SqliteDB" def start(self, args): self.node = args["node"].value() avfs = apswvfs.apswVFS() self.db = apsw.Connection(self.node.absolute(), vfs = avfs.vfsname) def execute(self, cmd): try: c = self.db.cursor() c.execute("PRAGMA locking_mode=EXCLUSIVE;") c.execute(cmd) return c except: return None class sqlitedb(Module): """Allows to query sqlite database trough the VFS""" def __init__(self): Module.__init__(self, "sqlitedb", SqliteDB) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.Node, "name": "node", "description": "sqlite base wrapper." }) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["SQLite"]}) self.tags = "Databases" dff-1.3.0+dfsg.1/dff/modules/databases/sqlite/sqlitemanager.py000066400000000000000000000025501217176075400242110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # from dff.api.module.manager import ModuleProcessusHandler class SqliteManager(ModuleProcessusHandler): def __init__(self, name): ModuleProcessusHandler.__init__(self, name) self.databases = {} def update(self, processus): self.databases[processus] = processus.node def execute(self, basename, cmd, root): responses = [] rootAbsolute = root.absolute() for base, node in self.databases.iteritems(): if node.absolute().find(rootAbsolute) == 0: if node.name() == basename: responses.append(Cursor(base.node, base.execute(cmd))) return responses class Cursor: def __init__(self, source, cursor): self._cursor = cursor setattr(self, "source", source) def __iter__(self): return iter(self._cursor) def fetchall(self): return self._cursor.fetchall() dff-1.3.0+dfsg.1/dff/modules/databases/winreg/000077500000000000000000000000001217176075400207735ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/databases/winreg/CMakeLists.txt000066400000000000000000000012511217176075400235320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER install_file( __init__.py winreg.py hive.py pathmanager.py nodes.py regtype.py registrymanager.py decoders.py ) dff-1.3.0+dfsg.1/dff/modules/databases/winreg/__init__.py000066400000000000000000000011341217176075400231030ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier __all__ = ["winreg", "registrymanager", "decoders"] dff-1.3.0+dfsg.1/dff/modules/databases/winreg/decoders.py000066400000000000000000000060371217176075400231430ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import string from struct import unpack from dff.api.types.libtypes import Argument, typeId, TIME_UNIX, TIME_MS_64, vtime #class DateDecoder(): # def __init__(self, data, keyname): # self.data = None # if str(keyname) == 'InstallDate': # self.data = str(vtime(data, TIME_UNIX).get_time()) # else: # self.data = data # def decode(self): # return self.data class DateDecoder(): def __init__(self, data): self.data = data if type(data) == bytearray: self.data = str(vtime(unpack('Q', str(data))[0], TIME_MS_64).get_time()) else: self.data = str(vtime(data, TIME_UNIX).get_time()) def decode(self): return self.data class Rot13decoder(): def __init__(self, data): self.data = data def decode(self): buff = unicode() for c in self.data: if c in string.ascii_uppercase: buff += chr((((ord(c) - 0x41)+13)%26) + 0x41) elif c in string.ascii_lowercase: buff += chr((((ord(c) - 0x61)+13)%26) + 0x61) else: buff += c return buff.encode('UTF-8').decode('UTF-8') class UTF16LEDecoder(): def __init__(self, data): self.data = data def decode(self): buff = unicode() return self.data.decode('UTF-16LE').encode("UTF8") class UTF16BEDecoder(): def __init__(self, data): self.data = data def decode(self): buff = unicode() return self.data.decode('UTF-16BE').encode("UTF8") class UserAssistDecoder(): def __init__(self, data, keyname): self.count = 0 self.lastUpdate = "N/A" self.id = 0 if len(data) <= 16: try: self.id = unpack(" 5: self.count -= 5 else: self.count = 0 self.lastUpdate = vtime(unpack(" # import pyregfi from dff.modules.winreg.nodes import ValueNode, KeyNode class RHive(): def __init__(self, node, mfso, verbose=False): self.node = node self.mfso = mfso self.verbose = verbose self.open() def __del__(self): del self.hive if self.vfile != None: self.vfile.close() self.vfile = None def open(self): try: self.vfile = self.node.open() except : self.mfso.stateinfo = "Error Opening " + str(self.node.absolute()) self.vfile = None self.hive = None try: self.hive = pyregfi.Hive(self.vfile) self.minor_version = self.hive.minor_version self.major_version = self.hive.major_version self.iterator = self.hive.__iter__() self.root = self.hive.root if self.verbose: self.countKeys() except: self.mfso.stateinfo = "Error Opening " + str(self.node.absolute()) self.vfile.close() self.vfile = None self.hive = None def countKeys(self): self.mfso.stateinfo = "Compute hive keys" self.nkeys = 0 self.parsedKeys = 0 for key in self.iterator: self.nkeys += 1 def updateCount(self): if self.verbose: self.parsedKeys += 1 percent = (self.parsedKeys * 100) / self.nkeys self.mfso.stateinfo = str(percent) + "%" def mount(self): self.mfso.stateinfo = "Mounting Registry File System" self.registree(self.root, self.node) try: self.mfso.registerTree(self.node, self.rootnode) except AttributeError: self.mfso.stateinfo = "Error mounting " + str(self.node.absolute()) self.mfso.stateinfo = "" def registree(self, current, parent): if len(current.subkeys) > 0: if current.is_root(): self.rootnode = knode = self.createNode(None, current) else: knode = self.createNode(parent, current) try : for key in current.subkeys: self.registree(key, knode) except : pass else: knode = self.createNode(parent, current) def createNode(self, parentNode, currentKey): if isinstance(currentKey.name, unicode): name = currentKey.name.encode('utf-8', 'replace') else: name = currentKey.name.decode('latin1').encode("utf-8", "replace") knode = KeyNode(self.mfso, parentNode, name, self.node, currentKey) try: if currentKey.values: for value in currentKey.values: ValueNode(self, knode, self.node, value) except Exception as e: pass self.updateCount() return knode def optim(self, current, parent): if self.iter.first_subkey(): cursub = self.iter.current_subkey() knode = self.createNode(parent, current) while cursub: self.iter.down() self.optim(cursub, knode) cursub = self.iter.next_subkey() self.iter.up() else: knode = self.createNode(parent, current) self.iter.up() dff-1.3.0+dfsg.1/dff/modules/databases/winreg/nodes.py000066400000000000000000000167321217176075400224660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import pyregfi from struct import unpack from ctypes import pointer, byref, create_string_buffer, c_uint32, c_bool from dff.api.vfs.libvfs import Node from dff.api.types.libtypes import Variant, VList, VMap, vtime, TIME_MS_64 from dff.modules.winreg.pathmanager import pathManager from dff.modules.winreg.regtype import regtype class ValueNode(Node): REGFI_BIG_DATA_MIN_LENGTH = 0xC def __init__(self, rhive, parent, node, value): mfso = rhive.mfso if value.name: name = value.name.encode('utf-8') else: name = "default" self.__type = value.type self.__chunk = None try: size = self.fetchData(value.data_off, value.data_size, value.data_in_offset, value, rhive) except Exception as e: size = 0 if not size: size = 0 Node.__init__(self, name, size, parent, mfso) self.__disown__() def fetchData(self, voffset, length, data_in_offset, value, rhive): self.__offset = voffset if data_in_offset: self.__chunk = [(value.offset + 0xC, length,)] return length else: offset = voffset + pyregfi.REGFI_REGF_SIZE max_size = pyregfi.regfi.regfi_calc_maxsize(value._hive.file, offset) if max_size < 0: return cell_length = c_uint32() unalloc = c_bool() if not pyregfi.regfi.regfi_parse_cell(pointer(value._hive.raw_file), c_uint32(offset), None, c_uint32(0), byref(cell_length), byref(unalloc)): return cell_length = cell_length.value if (cell_length & 0x00000007) != 0: return if cell_length > max_size: return if cell_length - 4 < length: if rhive.major_version >= 1 and rhive.minor_version >= 5: try: return self.parse_big_data(value, offset, length, cell_length) except Exception as e: return else: length = cell_length - 4 return self.parse_data(offset, length) def parse_data(self, offset, length): self.__chunk = [(offset + 4, length,)] return length def parse_big_data(self, value, offset, data_length, cell_length): bd_header = self.parse_big_data_header(value._hive.file, offset, cell_length, value) if not bd_header: return num_chunks = unpack('H', bd_header[0x2:0x2+2])[0] indirect_offset = unpack('I', bd_header[0x4:0x4+4])[0] + pyregfi.REGFI_REGF_SIZE indirect_ptrs = self.parse_big_data_indirect(value, indirect_offset, num_chunks) if not indirect_ptrs: return range_list = self.parse_big_data_cells(value, indirect_ptrs, num_chunks) self.__chunk = [] size = 0 for (off, sz) in range_list: sz -= 8 if size + sz > data_length: sz = data_length - size size += sz self.__chunk.append((off + 4, sz,)) return size def parse_big_data_cells(self, value, offsets, num_chunks): range_list = [] for i in range(0, num_chunks): chunk_offset = offsets[i] + pyregfi.REGFI_REGF_SIZE cell_length = c_uint32() unalloc = c_bool() if not pyregfi.regfi.regfi_parse_cell(pointer(value._hive.raw_file), c_uint32(chunk_offset), None, c_uint32(0), byref(cell_length), byref(unalloc)): return None range_list.append( (chunk_offset, cell_length.value,) ) return range_list def parse_big_data_indirect(self, value, offset, num_chunks): max_size = pyregfi.regfi.regfi_calc_maxsize(value._hive.file, offset) if ((max_size < 0) or (num_chunks*4 + 4 > max_size)): return None buff = create_string_buffer(num_chunks * 4) indirect_length = c_uint32() unalloc = c_bool() if not pyregfi.regfi.regfi_parse_cell(pointer(value._hive.raw_file), c_uint32(offset), buff, num_chunks*4, byref(indirect_length), byref(unalloc)): return None return unpack('I'*num_chunks, buff) def parse_big_data_header(self, file, offset, max_size, value): if ValueNode.REGFI_BIG_DATA_MIN_LENGTH > max_size: return None buff = create_string_buffer(ValueNode.REGFI_BIG_DATA_MIN_LENGTH) cell_length = c_uint32() unalloc = c_bool() if not pyregfi.regfi.regfi_parse_cell(pointer(value._hive.raw_file), c_uint32(offset), buff, c_uint32(ValueNode.REGFI_BIG_DATA_MIN_LENGTH), byref(cell_length), byref(unalloc)): return None if (buff[0] != 'd') or (buff[1] != 'b'): return None return buff def fileMapping(self, fm): if self.__chunk: currentOffset = 0 for (offset, size) in self.__chunk: fm.push(currentOffset, size, self.fsobj().hive, offset) currentOffset += size def _attributes(self): try: attr = VMap() attr['type'] = Variant(regtype[self.__type]) data = self.decodeData() if data != None: attr['data'] = data except Exception as e: pass return attr def decodeData(self): size = self.size() vfile = self.open() data = vfile.read(size) vfile.close() if size <= 4: if size == 4: if self.__type != 5: return Variant(unpack('I', data)[0]) elif size == 1: return Variant(unpack('B', data)[0]) elif size == 2: return Variant(unpack('H', data)[0]) elif size == 3: return Variant(unpack('I', data + '\x00')[0]) return try: return getattr(self, 'decode_' + regtype[self.__type])(data) except Exception as e: pass return None def decode_REG_SZ(self, data): return Variant(unicode(data, 'UTF-16').encode('UTF-8')) def decode_REG_EXPAND_SZ(self, data): return Variant(unicode(data, 'UTF-16').encode('UTF-8')) def decode_REG_LINK(self, data): return Variant(unicode(data, 'UTF-16').encode('UTF-8')) def decode_REG_DWORD(self, data): return Variant(unpack('I', data[0:4])[0]) def decode_REG_QWORD(self, data): return Variant(unpack('Q', data[0:8])[0]) def decode_REG_MULTI_SZ(self, data): vlist = VList() for line in unicode(data, 'UTF-16').split('\x00'): if line: vlist.append(Variant(line.encode('UTF-8'))) return vlist def icon(self): return (":password.png") class KeyNode(Node): def __init__(self, mfso, parent, name, node, key): Node.__init__(self, name, key.cell_size, parent, mfso) self.__disown__() self.timestamp = key.mtime self.offset = key.offset def fileMapping(self, fm): fm.push(0, self.size(), self.fsobj().hive, self.offset) def _attributes(self): attr = VMap() vt = vtime(self.timestamp, TIME_MS_64) vt.thisown = False vmodified = Variant(vt) attr["modified"] = vmodified return attr def dataType(self): dtype = VMap() dtype["registry"] = Variant("key") return dtype dff-1.3.0+dfsg.1/dff/modules/databases/winreg/pathmanager.py000066400000000000000000000052251217176075400236400ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import pyregfi from dff.api.module.module import * from dff.api.vfs.vfs import vfs HKLM_PATH = ["/WINDOWS/system32/config/software", "/WINDOWS/system32/config/system", "/WINDOWS/system32/config/default", "/WINDOWS/system32/config/SAM", "/WINDOWS/system32/config/SECURITY"] HKUSERS = "/Documents and Settings/" class rootManager(): def __init__(self, mountpoint): self.vfs = vfs() self.mountpoint = mountpoint self.hives = [] def checkGeneration(self): if self.mountpoint.fsobj().name in ("ntfs", "fat"): return True return False def getHives(self): if self.checkGeneration(): hives = [] rootpath = self.mountpoint.absolute() for path in HKLM_PATH: print rootpath + path n = self.vfs.getnode(rootpath + path) hives.append(n) return hives class pathManager(): def __init__(self, hive, path=None): self.setPath(path) self.hive = hive self.iterator = self.hive.__iter__() def setPath(self, path): if path == "": self.path = None else: self.path = path def splitPath(self, path): if path: rpath = path[1:len(path)] return rpath.split('/') else: return None def getValues(self): key = self.getKey() if key and len(key.values) > 0: return key.values else: return None def getKey(self): if not self.path: return None else: self.iterator.descend(self.splitPath(self.path)) ckey = self.iterator.current_key() if ckey: return ckey else: return None def getSecurity(self): key = self.getKey() if key: return self.key.fetch_security() return None def getClassName(self): key = self.getKey() if key: return self.key.fetch_classname() return None dff-1.3.0+dfsg.1/dff/modules/databases/winreg/registrymanager.py000066400000000000000000000113021217176075400245450ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # import re from dff.api.module.manager import ModuleProcessusHandler class RegistryManager(ModuleProcessusHandler): def __init__(self, moduleName): ModuleProcessusHandler.__init__(self, moduleName) self.registry = {} def update(self, processus): rtype = processus.regType() if rtype != None: self.registry[processus] = rtype def splitPath(self, path): if path: return path.split('\\') else: return None def getKeys(self, kvdict, root): # Dict of key path : value list # or Dict of key path : Dict { 'values' : '', 'description', ...} responses = [] rkeys = {} rootAbsolute = root.absolute() for key, values in kvdict.iteritems(): if isinstance(values, dict): values = values['values'] spath = self.splitPath(key) tag = self.getTag(spath) if tag: for regmod, (rtag, node) in self.registry.iteritems(): if node.absolute().find(rootAbsolute) == 0: if rtag.capitalize() == tag.capitalize(): args = self.searchRegExp(spath, regmod) if args: phive, klist = args if klist: resp = self.formatToResponse(phive, klist, values, tag, key) responses.extend(resp) return RegKeyManager(responses) def formatToResponse(self, phive, keys, values, tag, query = None): responses = [] if not values or not keys: return responses for k in keys: responses.append(RegKey(phive, k, values, tag, query)) return responses def searchRegExp(self, spath, regmod): phive = regmod.getHive() if phive.hive: rootkey = phive.hive.root else: return None if rootkey: keys = [rootkey] for curkey in spath: nkeys = [] match = curkey.find('*') for k in keys: try: for sk in k.subkeys: if match >= 0: pattern = curkey.replace('*', '.*') else: pattern = curkey pattern += '$' if re.match(pattern, sk.name, re.IGNORECASE): nkeys.append(sk) except : pass #pyregfi ERROR check XXX # else: # return None keys = nkeys[:] return (phive, keys) #we must have a ref to hive to avoid deleting it else: return None def getTag(self, spath): if spath[0] == "HKLM": tag = spath[0] + "\\" + spath[1] # Remove node tag name (ex: SYSTEM) from path spath.remove(spath[1]) elif spath[0] in ["HKU", "HKUCL"]: tag = spath[0] else: return None # Remove spath.remove(spath[0]) return tag class RegKey: def __init__(self, phive, key, vlist, tag, query = None): self._key = key self._vlist = vlist self._tag = tag self.query = query self.mtime = self._key.mtime self.phive = phive setattr(self, "name", self._key.name) setattr(self, "hive", self._key._hive._fh.node()) #XXX sans () fonction def path(self): c = self._key.get_parent() path = [c.name] while c.get_parent(): path.insert(0, c.name) c = c.get_parent() return '\\'.join(path) def values(self): values = [] if self._key.values: if len(self._vlist) == 1 and self._vlist[0] == '*': for v in self._key.values: values.append(RegValue(self._key, v)) else: for value in self._key.values: for v in self._vlist: if re.match(v, value.name, re.IGNORECASE): values.append(RegValue(self._key, value)) return values else: return None class RegValue: def __init__(self, key, value): self._key = key self._value = value setattr(self, "name", self._value.name) def data(self): return self._value.fetch_data() def __unicode(self): return getattr(self, "name") class RegKeyManager: def __init__(self, RegKeyList): self._keys = RegKeyList def __iter__(self): return iter(self._keys) def split(self): response = {} for key in self._keys: if key.hive.absolute() in response: response[key.hive].append(key) else: response[key.hive] = [key] return response dff-1.3.0+dfsg.1/dff/modules/databases/winreg/regtype.py000066400000000000000000000016751217176075400230350ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # regtype = { 0: "REG_NONE", 1: "REG_SZ", 2: "REG_EXPAND_SZ", 3: "REG_BINARY", 4: "REG_DWORD", 5: "REG_DWORD_BIG_ENDIAN", 6: "REG_LINK", 7: "REG_MULTI_SZ", 8: "REG_RESOURCE_LIST", 9: "REG_FULL_RESOURCE_DESCRIPTOR", 10: "REG_RESOURCE_REQUIREMENTS_LIST", 11: "REG_QWORD"} dff-1.3.0+dfsg.1/dff/modules/databases/winreg/winreg.py000066400000000000000000000063431217176075400226460ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER < jmo@arxsys.fr> # __dff_module_winreg_version__ = "1.0.0" import re from dff.api.vfs.libvfs import mfso from dff.api.module.module import Module from dff.api.module.manager import ModuleProcessusManager from dff.api.types.libtypes import Argument, typeId from hive import RHive from registrymanager import RegistryManager ModuleProcessusManager().register(RegistryManager("winreg")) HKLM = ["^SYSTEM", "^SOFTWARE", "^SAM", "^SECURITY"] HKU = ["^NTUSER.DAT", "^DEFAULT", "^USRCLASS.DAT"] class WINREG(mfso): def __init__(self): mfso.__init__(self, "winreg") self.name = "winreg" self.__disown__() def start(self, args): self.hive = args['file'].value() if args.has_key("verbose"): self.verbose = True else: self.verbose = False if args.has_key('mount'): self.mount = True else: self.mount = False phive = self.getHive() if self.mount and phive: phive.mount() def splitPath(self, path): if path: rpath = path[1:len(path)] return rpath.split('\\') else: return None def getHive(self): try: phive = RHive(self.hive, self, self.verbose) return phive except AttributeError: return None def regType(self): try: fn = self.hive.name() for hname in HKLM: if re.match(hname, fn, re.IGNORECASE): return ("HKLM" + "\\" + hname[1:], self.hive) for hname in HKU: if re.match(hname, fn, re.IGNORECASE): return ("HKU", self.hive) return None except AttributeError: return None class winreg(Module): """This modules permit to virtualy reconstruct windows registry hives files on the VFS.""" def __init__(self): Module.__init__(self, "winreg", WINREG) self.conf.addArgument({"name": "file", "description": "Registry hive file", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "verbose", "description": "Display module progression", "input": Argument.Empty}) self.conf.addArgument({"name": "mount", "description": "Mount registry key and value in the VFS (This can consume lot of memory)", "input": Argument.Empty}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["registry file"]}) self.tags = "Databases" self.flags = ["noscan"] self.icon = ":password.png" dff-1.3.0+dfsg.1/dff/modules/export/000077500000000000000000000000001217176075400170725ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/export/CMakeLists.txt000066400000000000000000000011751217176075400216360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob if(HAVE_FUSE) add_subdirectory (fuse) endif(HAVE_FUSE) install_file( extract.py ) dff-1.3.0+dfsg.1/dff/modules/export/extract.py000066400000000000000000000164541217176075400211300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_extract_version__ = "1.0.0" import os import time import traceback import types import shutil from dff.api.vfs import * from dff.api.vfs.extract import Extract from dff.api.module.script import * from dff.api.events.libevents import EventHandler from dff.api.exceptions.libexceptions import * from dff.api.types.libtypes import Argument, typeId, Variant, VList, VMap from dff.api.module.module import * # Extract algorithm # Examples are based on the following tree: # / # |- foo # |- bar # |- tutu # |- toto # |- tata # # and extraction folder is /home/user/extract # # Preserve tree example while extracting from /foo/bar/tutu # if enabled: # tutu will be extracted as follow: /home/user/extract/foo/bar/tutu # if disabled # tutu will be extracted as follow: /home/user/extract/tutu # # Recursive example while extracting from /foo # if enabled: # if bar is both a file and a folder (after applying a module on it) # /home/user/extract/bar.bin # /home/user/extract/bar/{tutu,toto,tata} # else # /home/user/extract/bar/{tutu,toto,tata} # if disabled: # either bar is both a file and a folder or a single file # /home/user/extract/bar (extracted as a file) # # File System destination folder handling # Since # # class EXTRACT(Script, EventHandler): reservednames = ['CON', 'PRN', 'AUX', 'CLOCK$', 'NUL', 'COM0', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT0', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', '$AttrDef', '$BadClus', '$Bitmap', '$Boot', '$LogFile', '$MFT', '$MFTMirr', 'pagefile.sys', '$Secure', '$UpCase', '$Volume', '$Extend'] max_depth = 2**31-1 def __init__(self): Script.__init__(self, "extract") EventHandler.__init__(self) self.vfs = vfs.vfs() self.extractor = Extract() self.extractor.connection(self) def start(self, args): self.total_files = 0 self.total_folders = 0 self.extracted_files = 0 self.extracted_folders = 0 self.files_errors = 0 self.folders_errors = 0 self.ommited_files = 0 self.ommited_folders = 0 self.__failed_files = [] self.__failed_folders = [] self.__renamed = {} try: self.nodes = args['files'].value() self.syspath = args['syspath'].value().path if not os.path.isdir(self.syspath): self.res["errors"] = Variant(self.syspath + " is not a valid directory") return if args.has_key('recursive'): self.recursive = args["recursive"].value() else: self.recursive = False if args.has_key('preserve'): self.preserve = args["preserve"].value() else: self.preserve = False if args.has_key('overwrite'): self.overwrite = args["overwrite"].value() else: self.overwrite = False self.__extract() self.__createReport() except KeyError: pass def Event(self, e): if e.type == Extract.FileProgress: idx = self.stateinfo.rfind("extracting") vl = e.value.value() node = vl[0].value() percent = vl[1].value() if idx != -1: buff = self.stateinfo[:idx] buff += "extracting " + node.absolute() + ": " + str(percent) + " %" self.stateinfo = buff else: self.stateinfo += "extracting " + node.absolute() + ": " + str(percent) + " %" if e.type == Extract.OverallProgress: self.stateinfo = str(e.value) if e.type == Extract.FileFailed: vl = e.value.value() self.__failed_files.append(vl[0].value()) print "extracting file failed", vl[0].value(), "\n", vl[1] if e.type == Extract.FolderFailed: vl = e.value.value() self.__failed_folders.append(vl[0].value()) print "extracting folder failed", vl[0].value(), "\n", vl[1] if e.type == Extract.PreserveFailed: vl = e.value.value() self.__preserved_failed = vl[0].value() print "preserving tree failed", vl[0].value(), "\n", vl[1] if e.type == Extract.RenameOccured: vl = e.value.value() if not self.__renamed.has_key(vl[0].value()): self.__renamed[str(vl[0])] = [] self.__renamed[str(vl[0])].append(str(vl[1])) print "rename: ", vl[0], " --> ", vl[1] del e def __extract(self): for vnode in self.nodes: node = vnode.value() if self.recursive: self.extractor.extractTree(node, self.syspath, self.preserve, self.overwrite) else: if node.hasChildren() or node.isDir(): self.extractor.extractFolder(node, self.syspath, self.preserve, self.overwrite) else: self.extractor.extractFile(node, self.syspath, self.preserve, self.overwrite) def __createReport(self): if len(self.__failed_files): vl = VList() for ffile in self.__failed_files: vl.append(Variant(ffile)) self.res["failed extraction for files"] = vl if len(self.__failed_folders): vl = VList() for ffolder in self.__failed_folders: vl.append(Variant(ffolder)) self.res["failed extraction for folders"] = vl if len(self.__renamed): vmap = VMap() for key in self.__renamed: vl = VList() for val in self.__renamed[key]: vl.append(Variant(val)) vmap[key] = vl self.res["renamed"] = vmap class extract(Module): """Extract file in your operating system file system.""" def __init__(self): Module.__init__(self, "extract", EXTRACT) self.conf.addArgument({"name": "files", "description": "Files or directories list to extract", "input": Argument.Required|Argument.List|typeId.Node}) self.conf.addArgument({"name": "syspath", "description": "Local file system path where files will be extracted", "input": Argument.Required|Argument.Single|typeId.Path}) self.conf.addArgument({"name": "recursive", "description": "Extract recursivly each files in all sub-directories", "input": Argument.Empty}) self.conf.addArgument({"name": "preserve", "description": "Enables if the absolute path needs to be preserved", "input": Argument.Empty}) self.conf.addArgument({"name": "overwrite", "description": "Enables if already existing files in extraction folder exist", "input": Argument.Empty}) #self.conf.addArgument({"name": "ascii_only", # "description": "Enables if destination folder's filesystem only supports ascii filenames", # "input": Argument.Empty}) self.tags = "Export" self.icon = ":extract.png" dff-1.3.0+dfsg.1/dff/modules/export/fuse/000077500000000000000000000000001217176075400200345ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/export/fuse/CMakeLists.txt000066400000000000000000000012601217176075400225730ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob dff_cpp_module(FUSE CPP_FILES fuse.cpp SWIG_FILE fuse.i LINK_LIBRARIES exceptions types vfs fuse INCLUDE_DIRS /usr/include/fuse ) dff-1.3.0+dfsg.1/dff/modules/export/fuse/fuse.cpp000066400000000000000000000057401217176075400215100ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "fuse.hpp" extern "C" { VFS& vfs = VFS::Get(); static int f_getattr(const char *path, struct stat *stbuf) { Node* node; memset(stbuf, 0, sizeof(struct stat)); node = vfs.GetNode(path); if (!node) return -ENOENT; if (node->hasChildren()) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2 + node->childCount(); } else { stbuf->st_mode = S_IFREG | 0444; stbuf->st_nlink = 1; stbuf->st_size = node->size(); } return 0; } static int f_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { Node *node; node = vfs.GetNode(path); if (!node) return -ENOENT; if (node->hasChildren()) { filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); std::vectorchilds = node->children(); std::vector::iterator i = childs.begin(); for (; i != childs.end(); i++) { filler(buf, (*i)->name().c_str(), NULL, 0); } } else return -ENOENT; return 0; } static int f_open(const char *path, struct fuse_file_info *fi) { Node *node; node = vfs.GetNode(path); if (!node) return -ENOENT; if (!node->size()) return -ENOENT; if ((fi->flags & 3) != O_RDONLY) return -EACCES; return 0; } static int f_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { Node *node; VFile *file; int n; node = vfs.GetNode(path); if (!node) return 0; try { file = node->open(); file->seek(offset); n = file->read(buf, size); file->close(); } catch (vfsError e) { return 0; } return n; } struct f_oper : fuse_operations { f_oper() { getattr = f_getattr; open = f_open; readdir = f_readdir; read = f_read; } }; static struct f_oper f_opers; } void fuse::start(std::map args) { std::map::iterator argit; Path *tpath; char **argv; tpath = args["path"]->value(); if (!tpath) return ; argv = (char **)malloc(sizeof(char*) * 4); *argv = (char *)"dff-fuse"; *(argv + 1) = (char *)tpath->path.c_str(); *(argv + 2) = (char *)"-s"; *(argv + 3) = (char *)"-f"; fuse_main(4, argv, &f_opers, 0); return ; } fuse::fuse() : mfso("fuse") { } fuse::~fuse() { } dff-1.3.0+dfsg.1/dff/modules/export/fuse/fuse.hpp000066400000000000000000000022401217176075400215050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __FUSE_HH__ #define __FUSE_HH__ #include #include #include #include #include "vfs.hpp" #include "mfso.hpp" #include "path.hpp" #include "variant.hpp" #define FUSE_USE_VERSION 26 #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_SETXATTR #include #endif class fuse : public mfso { public: fuse(); ~fuse(); virtual void start(std::map args); }; #endif dff-1.3.0+dfsg.1/dff/modules/export/fuse/fuse.i000066400000000000000000000025441217176075400211550ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module FUSE %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %exception; %{ #include "variant.hpp" #include "vtime.hpp" #include "fuse.hpp" %} %import "../../../api/vfs/libvfs.i" %include "fuse.hpp" %pythoncode %{ __dff_module_fuse_version__ = "1.0.0" from dff.api.module.module import Module from dff.api.types.libtypes import Argument, typeId class FUSE(Module): """Mount DFF VFS directly under your OS VFS""" def __init__(self): Module.__init__(self, 'fuse', fuse) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Path, "name": "path", "description":"Path where to mount DFF VFS in your OS VFS."}) self.tags = "Export" %} dff-1.3.0+dfsg.1/dff/modules/fs/000077500000000000000000000000001217176075400161615ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/CMakeLists.txt000066400000000000000000000013121217176075400207160ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob add_subdirectory (extfs) add_subdirectory (fat) add_subdirectory (ntfs) install_file( __init__.py spare.py ) dff-1.3.0+dfsg.1/dff/modules/fs/__init__.py000066400000000000000000000011511217176075400202700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __all__ = ['shm'] dff-1.3.0+dfsg.1/dff/modules/fs/extfs/000077500000000000000000000000001217176075400173125ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/BlkList.cpp000066400000000000000000000044511217176075400213660ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "include/BlkList.h" BlkList::BlkList(GroupDescriptor * GD, SuperBlock * SB, VFile * vfile) { __GD = GD; __SB = SB; __vfile = vfile; __end = 0; } BlkList::~BlkList() { } void BlkList::stat(const std::string & blk_list) { size_t pos; if ((pos = blk_list.find("-")) != std::string::npos) { std::string tmp = blk_list.substr(pos + 1, blk_list.size() - 1); std::istringstream iss(tmp); iss >> __end; } std::stringstream iss; if (pos == std::string::npos) iss << blk_list; else iss << blk_list.substr(0, pos); iss >> __begin; if (__end && (__begin > __end)) throw vfsError("BlkList::stat() : last block number > first."); if (__end == 0) __end = __begin; for (; __begin <= __end; ++__begin) { std::cout << __begin << " | "; std::cout << (blk_allocation_status(__begin) ? "Allocated | " : "Not allocated | "); std::cout << "Group : " << __group << " | "; std::cout << "Byte addr : " << std::dec << __bit_addr << std::hex << " (0x" << __bit_addr << ")" << " | "; std::cout << "Bit position : " << (int)__dec; std::cout << std::endl; } } bool BlkList::blk_allocation_status(uint64_t blk_nb) { if ((blk_nb > __SB->blocks_number())) throw vfsError("InodeUtils::blk_allocation_status() : " "block number out of range."); __group = blk_nb / __SB->block_in_groups_number(); uint64_t blk_bitmap_addr = ((uint64_t)__GD->block_bitmap_addr(__group)) * __SB->block_size(); __bit_addr = ((uint64_t)blk_bitmap_addr) + blk_nb / 8; uint8_t bits; if (!__vfile->seek(__bit_addr) || !__vfile->read(&bits, sizeof(uint8_t))) return false; __dec = blk_nb % 8; return ((bits >> __dec) & 1); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/CMakeLists.txt000066400000000000000000000025371217176075400220610ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon dff_cpp_module(EXTFS CPP_FILES extfs.cpp Directory.cpp SymLink.cpp Journal.cpp JournalType.tpp FileNameRecovery.cpp CustomResults.cpp CustomAttrib.cpp fsck.cpp FsStat.cpp InodeStat.cpp JournalStat.cpp InodesList.cpp InodeUtils.cpp SuperBlockUtils.cpp ExtfsNode.cpp ExtfsSlackNode.cpp ExtfsRawDataNode.cpp ExtfsSymLinkNode.cpp BlkList.cpp MfsoAttrib.cpp Option.cpp OrphansInodes.cpp data_structure/InodeStructure.cpp data_structure/SuperBlock.cpp data_structure/GroupDescriptor.cpp data_structure/Inode.cpp data_structure/DirEntry.cpp data_structure/SuperBlockStructure.cpp data_structure/ExtendedAttr.cpp data_structure/Ext4Extents.cpp SWIG_FILE extfs.i LINK_LIBRARIES exceptions types vfs tree INCLUDE_DIRS ${CMAKE_HOME_DIRECTORY}/dff/api/tree ) dff-1.3.0+dfsg.1/dff/modules/fs/extfs/CustomAttrib.cpp000066400000000000000000000051041217176075400224360ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "include/CustomAttrib.h" CustomAttrib::CustomAttrib() { } CustomAttrib::~CustomAttrib() { } void CustomAttrib::setTime(Inode * _inode) { setTime((time_t)_inode->access_time()); setTime((time_t)_inode->change_time()); setTime((time_t)_inode->modif_time()); setTime((time_t)0); #ifndef WIN32 if (_inode->delete_time()) { time_t tmp = _inode->delete_time(); this->smap.insert(std::make_pair("Deletion time:", ctime(&tmp))); } #endif } void CustomAttrib::setTime(time_t timestamp) { #ifndef WIN32 tm * t; time_t tmp = timestamp; t = gmtime(&tmp); new vtime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, 0); #endif } void CustomAttrib::setAttr(Inode * _inode) { this->imap.insert(std::make_pair("Link number", _inode->link_coun())); this->imap.insert(std::make_pair("NFS generation number", _inode->generation_number_nfs())); this->imap.insert(std::make_pair("Extended attribute header", _inode->file_acl_ext_attr())); this->imap.insert(std::make_pair("Fragment block", _inode->fragment_addr())); this->imap.insert(std::make_pair("Fragment index", _inode->fragment_index())); this->imap.insert(std::make_pair("Fragment size", _inode->fragment_size())); this->imap.insert(std::make_pair("Sector count", _inode->sector_count())); } void CustomAttrib::setSetUidGid(Inode * _inode) { this->smap.insert(std::make_pair("Set UID / GID ?", _inode->set_uid_gid(_inode->file_mode()))); } void CustomAttrib::setMode(Inode * _inode) { InodeUtils i_utils(NULL, NULL); this->smap.insert(std::make_pair("Permissions", i_utils.mode(_inode->file_mode()))); } bool CustomAttrib::setMode(uint16_t mask, Inode * _inode) { if (!(mask & _inode->file_mode())) return true; return false; } void CustomAttrib::setUidGid(Inode * _inode) { this->smap.insert(std::make_pair("UID / GID", _inode->uid_gid(_inode->lower_uid(), _inode->lower_gid()))); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/CustomResults.cpp000066400000000000000000000306251217176075400226600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include "include/CustomResults.h" #include "include/FsStat.h" CustomResults::CustomResults() { } CustomResults::~CustomResults() { } void CustomResults::set(Attributes * attr, Inode * inode) { std::map m; std::ostringstream sig; std::ostringstream auth_uid_gid; sig << std::hex << inode->SB()->signature(); m["Signature"] = Variant_p(new Variant(std::string("0x") + sig.str())); m["Creator OS"] = Variant_p(new Variant(getOs(inode->SB()->creator_os()))); m["File system ID"] = Variant_p(new Variant(getFSID(inode->SB()->file_system_ID()))); m["Error handling"] = Variant_p(new Variant(getErrorHandling(inode->SB()->error_handling_method()))); std::string vol_name = (char *)inode->SB()->volume_name(); m["Volume name"] = Variant_p(new Variant(vol_name)); std::string path_mount = (char *)inode->SB()->path_last_mount(); m["Path to last mount"] = Variant_p(new Variant(path_mount)); m["Algorithm usage bitmap"] = Variant_p(new Variant(inode->SB()->algorithm_bitmap())); m["Current mount count"] = Variant_p(new Variant(inode->SB()->current_mount_count())); m["Max mount count"] = Variant_p(new Variant(inode->SB()->max_mount_count())); m["File system"] = Variant_p(new Variant(m)); m["Orphan inode list"] = Variant_p(new Variant(inode->SB()->orphan_node_list())); m["Major version"] = Variant_p(new Variant(inode->SB()->major_version())); m["Minor version"] = Variant_p(new Variant(inode->SB()->minor_version())); m.clear(); m["Block size (in Bytes)"] = Variant_p(new Variant(inode->SB()->block_size())); m["Inode size (in bytes)"] = Variant_p(new Variant(inode->SB()->inodes_struct_size())); m["Block number"] = Variant_p(new Variant(inode->SB()->blocks_number())); m["Inodes number"] = Variant_p(new Variant(inode->SB()->inodesNumber())); m["Blocks per group"] = Variant_p(new Variant(inode->SB()->block_in_groups_number())); m["Inodes per group"] = Variant_p(new Variant(inode->SB()->inodes_in_group_number())); m["Group number"] = Variant_p(new Variant(inode->SB()->blocks_number() / inode->SB()->block_in_groups_number())); m["Fragment size"] = Variant_p(new Variant(inode->SB()->fragment_size())); m["group descriptor size"] = Variant_p(new Variant((inode->SB()->getSuperBlock()->s_desc_size ? inode->SB()->getSuperBlock()->s_desc_size : 32))); (*attr)["File system size"] = Variant_p(new Variant(m)); m.clear(); m["Last mount time"] = Variant_p(add_time(inode->SB()->last_mount_time())); m["Last written time"] = Variant_p(add_time(inode->SB()->last_written_time())); m["Last consistency check time"] = Variant_p(add_time(inode->SB()->l_consistency_ct())); m["Forced consistency interval"] = Variant_p(add_time(inode->SB()->consitency_forced_interval())); (*attr)["Time"] = Variant_p(new Variant(m)); m.clear(); auth_uid_gid << inode->SB()->gid_reserved_block() << " / " << inode->SB()->uid_reserved_block(); m["Reserved block GID / UID"] = Variant_p(new Variant(auth_uid_gid.str())); m["First non reserved inode"] = Variant_p(new Variant(inode->SB()->f_non_r_inodes())); m["Preallocate file blocks"] = Variant_p(new Variant(inode->SB()->preallocate_blocks_files())); m["Preallocate directory blocks"] = Variant_p(new Variant(inode->SB()->preallocate_block_dir())); m["Reserved blocks"] = Variant_p(new Variant(inode->SB()->r_blocks_number())); m["Unallocated blocks"] = Variant_p(new Variant(inode->SB()->u_blocks_number())); m["Unallocated inodes"] = Variant_p(new Variant(inode->SB()->u_inodes_number())); m["Group 0's block"] = Variant_p(new Variant(inode->SB()->first_block())); (*attr)["Content"] = Variant_p(new Variant(m)); m.clear(); std::string jr_id = (char *)inode->SB()->journal_id(); m["Journal ID"] = Variant_p(new Variant(jr_id)); m["Journal inode"] = Variant_p(new Variant(inode->SB()->journal_inode())); m["journal device"] = Variant_p(new Variant(inode->SB()->journal_device())); (*attr)["Journal"] = Variant_p(new Variant(m)); m.clear(); (*attr)["Flags"] = Variant_p(getFlags(inode->SB())); m["Compatible features"] = Variant_p(getCompatibleFeatures(inode->SB())); m["Incompatible features"] = Variant_p(getIncompatibleFeatures(inode->SB())); m["Read only features"] = Variant_p(getReadOnlyFeatures(inode->SB())); (*attr)["Features"] = Variant_p(new Variant(m)); m.clear(); FsStat fs_stat; fs_stat.attr_stat(inode->SB(), inode->extfs()->vfile(), attr); // m[layout] } Variant * CustomResults::add_time(time_t t) { #ifndef WIN32 std::string ti(t ? ctime(&t) : "NA\n"); ti[ti.size() - 1] = 0; #else std::string ti = "fixme"; #endif return new Variant(ti); } std::string CustomResults::getFlags(uint16_t fs_state) { std::string flags = ""; if (fs_state & SuperBlock::_FS_STATE_CLEAN) flags = flags + "Clean - "; if (fs_state & SuperBlock::_FS_HAS_ERRORS) flags = flags + "Errors - "; if (fs_state & SuperBlock::_ORPHAN_RECOVERY) flags = flags + "Orphan recovery "; return flags; } Variant * CustomResults::getFlags(const SuperBlock * SB) { std::list l; uint32_t fs_state = SB->fs_state(); if (fs_state & SuperBlock::_FS_STATE_CLEAN) l.push_back(Variant_p(new Variant(std::string("Clean")))); if (fs_state & SuperBlock::_FS_HAS_ERRORS) l.push_back(Variant_p(new Variant(std::string("Errors")))); if (fs_state & SuperBlock::_ORPHAN_RECOVERY) l.push_back(Variant_p(new Variant(std::string("Orphan recovery")))); if (l.empty()) l.push_back(Variant_p(new Variant(std::string("(None)")))); return new Variant(l); } std::string CustomResults::getErrorHandling(uint16_t error_handling_method) { std::string err = "None"; if (error_handling_method == SuperBlock::_ERROR_HANDLING_CONTINUE) err = "Continue"; else if (error_handling_method == SuperBlock::_RO_REMOUNT) err = "Read-only remount"; else if (error_handling_method == SuperBlock::_PANIC) err = "Panic"; return err; } std::string CustomResults::getOs(uint32_t creator_os) { std::string os = "Unknown"; if (creator_os == SuperBlock::_OS_LINUX) os = "Linux"; else if (creator_os == SuperBlock::_OS_GNU_HURD) os = "Gnu HURD"; else if (creator_os == SuperBlock::_OS_MASIX) os = "Masix"; else if (creator_os == SuperBlock::_OS_FREE_BSD) os = "Free BSD"; else if (creator_os == SuperBlock::_OS_LITES) os = "Lites"; return os; } std::string CustomResults::getCompatibleFeatures(uint32_t c_f_flags) { std::string feat = ""; if (c_f_flags & SuperBlock::_COMP_PDIR) feat += "Directory preallocation - "; if (c_f_flags & SuperBlock::_COMP_AFS_INODE) feat += "Afs server - "; if (c_f_flags & SuperBlock::_COMP_HAS_JOURNAL) feat += "Journal - "; if (c_f_flags & SuperBlock::_COMP_EXT_ATTR) feat += "Ext attr - "; if (c_f_flags & SuperBlock::_COMP_CAN_RESIZE) feat += "Resize - "; if (c_f_flags & SuperBlock::_COMP_DIR_HASH_INDEX) feat += "Hash index"; return feat; } Variant * CustomResults::getCompatibleFeatures(const SuperBlock * SB) { std::list< Variant_p > l; uint32_t c_f_flags; c_f_flags = SB->compatible_feature_flags(); if (c_f_flags & SuperBlock::_COMP_PDIR) l.push_back(Variant_p(new Variant(std::string("Directory preallocation")))); if (c_f_flags & SuperBlock::_COMP_AFS_INODE) l.push_back(Variant_p(new Variant(std::string("Afs sercer")))); if (c_f_flags & SuperBlock::_COMP_HAS_JOURNAL) l.push_back(Variant_p(new Variant(std::string("Using journal")))); if (c_f_flags & SuperBlock::_COMP_EXT_ATTR) l.push_back(Variant_p(new Variant(std::string("Extended attributes")))); if (c_f_flags & SuperBlock::_COMP_CAN_RESIZE) l.push_back(Variant_p(new Variant(std::string("Inodes resize")))); if (c_f_flags & SuperBlock::_COMP_DIR_HASH_INDEX) l.push_back(Variant_p(new Variant(std::string("Directories index")))); return new Variant(l); } std::string CustomResults::getIncompatibleFeatures(uint32_t i_f_flags) { std::string feat = ""; if (i_f_flags & SuperBlock::_COMPRESSION) feat += "Compression - "; if (i_f_flags & SuperBlock::_DIR_FILE_TYPE) feat += "File type in dir entries - "; if (i_f_flags & SuperBlock::_NEEDS_RECOVERY) feat += "Need recovery - "; if (i_f_flags & SuperBlock::_JOURNAL_DEVICE) feat += "Use journal device - "; if (i_f_flags & SuperBlock::_META_BG) feat += "Meta block group - "; if (i_f_flags & SuperBlock::_EXTENTS) feat += "Support for extents - "; if (i_f_flags & SuperBlock::_64BITS) feat += "64 bits support - "; if (i_f_flags & SuperBlock::_FLEX_BG) feat += "Flex block group - "; if (i_f_flags & SuperBlock::_EA_INODE) feat += "EA in inodes - "; if (i_f_flags & SuperBlock::_DIRENT_DATA) feat += "Data in dirents"; return feat; } Variant * CustomResults::getIncompatibleFeatures(const SuperBlock * SB) { std::list< Variant_p > l; uint32_t i_f_flags; i_f_flags = SB->incompatible_feature_flags(); if (i_f_flags & SuperBlock::_COMPRESSION) l.push_back(Variant_p(new Variant(std::string("Compression")))); if (i_f_flags & SuperBlock::_DIR_FILE_TYPE) l.push_back(Variant_p(new Variant(std::string("File type in directory entries")))); if (i_f_flags & SuperBlock::_NEEDS_RECOVERY) l.push_back(Variant_p(new Variant(std::string("Needs recovery")))); if (i_f_flags & SuperBlock::_JOURNAL_DEVICE) l.push_back(Variant_p(new Variant(std::string("Use journal device")))); if (i_f_flags & SuperBlock::_META_BG) l.push_back(Variant_p(new Variant(std::string("Meta block group")))); if (i_f_flags & SuperBlock::_EXTENTS) l.push_back(Variant_p(new Variant(std::string("Support for extents")))); if (i_f_flags & SuperBlock::_64BITS) l.push_back(Variant_p(new Variant(std::string("64 bits support")))); if (i_f_flags & SuperBlock::_FLEX_BG) l.push_back(Variant_p(new Variant(std::string("Flex block group")))); if (i_f_flags & SuperBlock::_EA_INODE) l.push_back(Variant_p(new Variant(std::string("EA in inodes")))); if (i_f_flags & SuperBlock::_DIRENT_DATA) l.push_back(Variant_p(new Variant(std::string("Data in dirents")))); return new Variant(l); } std::string CustomResults::getReadOnlyFeatures(uint32_t r_o_flags) { std::string feat = ""; if (r_o_flags & SuperBlock::_SPARSE_SUPERBLOCK) feat += "Sparse superblock - "; if (r_o_flags & SuperBlock::_LARGE_FILE) feat += "Large file - "; if (r_o_flags & SuperBlock::_B_TREES) feat += "Directories B-Trees - "; if (r_o_flags & SuperBlock::_HUGE_FILE) feat += "Huge files - "; if (r_o_flags & SuperBlock::_GD_CSUM) feat += "Group descriptor checksum - "; if (r_o_flags & SuperBlock::_DIR_NLINK) feat += "Directory nlink - "; if (r_o_flags & SuperBlock::_EXTRA_ISIZE) feat += "Extra inode size"; return feat; } Variant * CustomResults::getReadOnlyFeatures(const SuperBlock * SB) { std::list< Variant_p > l; uint32_t i_f_flags; i_f_flags = SB->ro_features_flags(); if (i_f_flags & SuperBlock::_SPARSE_SUPERBLOCK) l.push_back(Variant_p(new Variant(std::string("Sparse superblock")))); if (i_f_flags & SuperBlock::_LARGE_FILE) l.push_back(Variant_p(new Variant(std::string("Large files")))); if (i_f_flags & SuperBlock::_B_TREES) l.push_back(Variant_p(new Variant(std::string("Directories B-Trees")))); if (i_f_flags & SuperBlock::_HUGE_FILE) l.push_back(Variant_p(new Variant(std::string("Huge files")))); if (i_f_flags & SuperBlock::_GD_CSUM) l.push_back(Variant_p(new Variant(std::string("Group descriptor checksum")))); if (i_f_flags & SuperBlock::_DIR_NLINK) l.push_back(Variant_p(new Variant(std::string("Directory nlink")))); if (i_f_flags & SuperBlock::_EXTRA_ISIZE) l.push_back(Variant_p(new Variant(std::string("Extra inode size")))); return new Variant(l); } std::string CustomResults::getFSID(const uint8_t * fs_id) { std::ostringstream id; for (int i = 0; i < 16; ++i) id << std::hex << (int)fs_id[i]; return "0x" + id.str(); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/Directory.cpp000066400000000000000000000144571217176075400217750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the proje`ct provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ //#define DIREC_DEBUG #include #include #include "include/utils/InodeUtils.h" #include "include/Directory.h" #include "include/FileNameRecovery.h" #include "include/MfsoAttrib.h" #include "include/ExtfsRawDataNode.h" #include "include/ExtfsSlackNode.hpp" Directory::Directory(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD) : Inode(extfs, SB, GD) { __i_list = new TwoThreeTree; } Directory::Directory(const Directory * dir) : Inode(dir) { _recovery = dir->recovery(); __i_list = dir->i_list(); } Directory::~Directory() { } void Directory::dir_init() { Journal * journal = NULL; _recovery = NULL; journal = new Journal(_extfs, _SB, _GD); if (_SB->useCompatibleFeatures(SuperBlock::_COMP_HAS_JOURNAL, _SB->compatible_feature_flags())) if (journal->init() == false) { delete journal; journal = NULL; } _recovery = new FileNameRecovery(journal); } uint8_t Directory::searchDirEntries(uint64_t content_addr, uint64_t end_addr, Node * parent) { DirEntry * dir_e = new DirEntry; inodes_t * inter = new (inodes_t); uint8_t * tab = (uint8_t *)operator new(end_addr - content_addr); std::string name; uint64_t inode_addr; uint8_t valid = 0; ExtfsNode * node; _extfs->v_seek_read(content_addr, tab, _SB->block_size()); for (end_addr -= content_addr, content_addr = 0; (content_addr + 12) < end_addr; ) // a dirent is at least 12 bytes big { dir_e->setDir((dir_entry_v2 *)(tab + content_addr)); // if the entry is valid and the name not empty if (((valid = _recovery->valid_entry(dir_e) == 0)) && !(name = _recovery->setDirName(dir_e, tab, content_addr)).empty()) { #ifdef DIREC_DEBUG if (!parent->path().empty()) std::cout << parent->path() << "/"; std::cout << parent->name() << " " << name << std::endl; std::cout << "\tinode_nb : " << dir_e->inode_value() << std::endl; std::cout << "\tinode addr : " << inode_addr << std::endl; std::cout << "\tcontent addr : " << content_addr << " end_addr : " << end_addr << std::endl; std::cout << "\tentry len : " << dir_e->entry_length() << std::endl; std::cout << "\tnext : " << dir_e->next() << std::endl; #endif inode_addr = getInodeByNumber(dir_e->inode_value()); read(inode_addr, inter); if (this->is_fucked_up()) { std::ostringstream oss; oss << dir_e->inode_value(); new ExtfsRawDataNode(oss.str(), _SB->inodes_struct_size(), _extfs->suspiscious_inodes(), _extfs, inode_addr + _SB->offset() - __BOOT_CODE_SIZE); } if (!__i_list->find(dir_e->inode_value())) __i_list->insert(dir_e->inode_value()); else { if ((inter->file_mode & __IFMT) == __IFDIR) node = createNewNode(0, parent, name, inter); else node = createNewNode(inode_addr, parent, name, inter); if (node) { node->set_i_nb(dir_e->inode_value()); if ((dir_e->entry_length() != dir_e->next())) valid = _recovery->deletedFileNames(tab, content_addr + dir_e->next(), parent, this, dir_e); } content_addr += dir_e->entry_length(); continue ; } std::ostringstream oss; oss << _extfs->nb_parsed_inode() << " / " << _extfs->alloc_inode(); _extfs->for_aiur(); _extfs->stateinfo = ("parsed " + oss.str() + " files"); node = createNewNode(inode_addr, parent, name, inter); if (node) { node->set_i_nb(dir_e->inode_value()); if (((inter->file_mode & __IFMT) == __IFDIR) && (dir_e->file_type_v2() == DirEntry::_DIRECTORY)) { Directory * new_dir = new Directory(this); new_dir->dirContent(node, inter, inode_addr, dir_e->inode_value()); node->setDir(); delete new_dir; } if ((dir_e->entry_length() != dir_e->next())) valid = _recovery->deletedFileNames(tab, content_addr + dir_e->next(), parent, this, dir_e); } content_addr += dir_e->entry_length(); } else { if ((dir_e->entry_length() != dir_e->next())) valid = _recovery->deletedFileNames(tab, content_addr + dir_e->next(), parent, this, dir_e); content_addr += dir_e->entry_length(); } } delete inter; delete dir_e; delete tab; if (valid == 2) return false; return true; } ExtfsNode * Directory::createNewNode(uint64_t inode_addr, Node * parent, const std::string & name, inodes_t * inter) { return _extfs->createVfsNode(parent, name, inode_addr, inter); } void Directory::clean() { delete _recovery; __i_list->clear(); delete __i_list; } void Directory::dirContent(Node * parent, inodes_t * inode, uint64_t a, uint32_t i_nb) { uint32_t block_number; uint64_t addr, i_addr = __inode_addr; bool valid_dir = true; if (a) i_addr = a; if ((inode->file_mode & __IFMT) != __IFDIR) // we are not in a dir return ; setInode(inode); init(); // skip the hash tree blocks if any if ((_SB->compatible_feature_flags() & SuperBlockStructure::_COMP_DIR_HASH_INDEX) // compatible feature && (flags() & 0x1000)) // hash indexed dir if (!_current_block) nextBlock(); while ((block_number = nextBlock())) // get all directory inode blocks { addr = ((uint64_t)block_number) * ((uint64_t)_SB->block_size()); valid_dir = searchDirEntries(addr, addr + _SB->block_size(), parent); this->_calculated_size += _SB->block_size(); } if (!valid_dir) /*if one or several invalid dirents were found, mark the inode as suspiscious */ { std::ostringstream oss; oss << i_nb; new ExtfsNode(oss.str(), this->lower_size(), _extfs->suspiscious_dir(), _extfs, i_addr, false, _extfs->addBlockPointers); } } FileNameRecovery * Directory::recovery() const { return _recovery; } TwoThreeTree * Directory::i_list() const { return __i_list; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/ExtfsNode.cpp000066400000000000000000000162221217176075400217200ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/ExtfsNode.h" #include "data_structure/includes/Inode.h" #include "data_structure/includes/Ext4Extents.h" #include "include/MfsoAttrib.h" #include "include/CustomResults.h" void BlockPointerAttributes::__extents_block(Inode * inode, Attributes * attr) { Ext4Extents extents(NULL); std::list > ext_list; std::list >::const_iterator it; std::map m; std::list< Variant_p > blk_l; extents.push_extended_blocks(inode); ext_list = extents.extents_list(); it = ext_list.begin(); while (it != ext_list.end()) { std::ostringstream oss; oss << (*it).second; oss << " -> "; oss << (*it).first + (*it).second - 1; blk_l.push_back(Variant_p(new Variant(oss.str()))); it++; } if (!blk_l.empty()) (*attr)["Extent blocks"] = Variant_p(new Variant(blk_l)); } void BlockPointerAttributes::__block_pointers(Inode * inode, Attributes * attr) { uint32_t block_number; uint32_t tmp = inode->SB()->block_size() / 4; uint32_t i; std::map m; std::list blk_list; if (inode->flags() & 0x80000) // extents, do nothing for now __extents_block(inode, attr); else { uint32_t previous_block = 0, blk = 0; for (i = 0; i <= (tmp * tmp); ++i) { block_number = inode->goToBlock(i); if (!previous_block) blk = block_number; else if (block_number != (previous_block + 1)) { std::ostringstream oss; oss << blk << " -> " << previous_block; blk_list.push_back(Variant_p(new Variant(oss.str()))); blk = previous_block; } previous_block = block_number; if ((i == 12) && !blk_list.empty()) { m["Direct"] = Variant_p(new Variant(blk_list)); blk_list.clear(); } else if (((i - 12) == tmp) && !blk_list.empty() ) { if (!blk_list.empty()) { m["Single indirect"] = Variant_p(new Variant(blk_list)); blk_list.clear(); } } else if (((i - 12 - tmp) == (tmp * tmp)) && !blk_list.empty()) { if (!blk_list.empty()) { m["Double indirect"] = Variant_p(new Variant(blk_list)); blk_list.clear(); } } } } (*attr)[std::string("Block pointers")] = Variant_p(new Variant(m)); } BlockPointerAttributes::BlockPointerAttributes(std::string name) : AttributesHandler(name) { } Attributes BlockPointerAttributes::attributes(Node* node) { Attributes attr; ExtfsNode* enode = dynamic_cast(node); Inode * inode = enode->read_inode(); if (inode->type_mode(inode->file_mode())[0] != 'l') // file is not a symlink this->__block_pointers(inode, &attr); return (attr); } ExtfsNode::ExtfsNode(std::string name, uint64_t size, Node* parent, Extfs * fsobj, uint64_t inode_addr, bool is_root, bool add_attribute_blocks) : Node (name, size, parent, fsobj) { this->__inode_addr = inode_addr; this->__extfs = fsobj; this->__i_nb = 0; this->__is_root = is_root; if (add_attribute_blocks) this->registerAttributes(fsobj->attributeHandler); } ExtfsNode::~ExtfsNode() { } void ExtfsNode::fileMapping(FileMapping* fm) { Inode * inode = read_inode(); if (!inode) return ; if (inode->flags() & 0x80000) // Use extent. (should be defined in Inode.h) { Ext4Extents * ext4 = new Ext4Extents(fm); ext4->push_extended_blocks(inode); delete ext4; } else push_block_pointers(inode, fm); delete inode->inode(); delete inode; } void ExtfsNode::push_block_pointers(Inode * inode, FileMapping * file_mapping) { uint64_t blk_addr, offset = 0, size; uint64_t b_size = __extfs->SB()->block_size(); uint64_t ooffset = __extfs->SB()->offset() - __BOOT_CODE_SIZE; uint32_t tmp = inode->SB()->block_size() / sizeof(uint32_t); size = this->size(); if (!size) return ; while ((inode->currentBlock() < ((tmp * tmp * tmp) + (tmp * tmp) + 12))) { blk_addr = inode->nextBlock(); if (!blk_addr) { if (inode->currentBlock() < 12) continue ; if (inode->currentBlock() < tmp + 12) { if (!(inode->simple_indirect_block_pointer())) inode->goToBlock(tmp + 12); } else if (inode->currentBlock() < ((tmp * tmp) + 12)) { if (!inode->double_indirect_block_pointer()) inode->goToBlock((tmp * tmp) + 12); } else if (!inode->triple_indirect_block_pointer()) { break ; } } else if (__extfs->SB()->block_size() < size) { size -= b_size; file_mapping->push(offset, b_size, __extfs->node(), blk_addr * __extfs->SB()->block_size() + ooffset); offset += inode->SB()->block_size(); } else { file_mapping->push(offset, size, __extfs->node(), blk_addr * __extfs->SB()->block_size() + ooffset); break ; } } } Attributes ExtfsNode::_attributes() { Attributes attr; Inode * inode = this->read_inode(); if (!inode) return (attr); if (this->__is_root) { CustomResults c_res; c_res.set(&attr, inode); } else { MfsoAttrib * c_attr = new MfsoAttrib; c_attr->setAttrs(inode, &attr, this->__i_nb, this->__inode_addr); attr["modified"] = Variant_p(new Variant(new vtime(inode->modif_time(), TIME_UNIX))); attr["accessed"] = Variant_p(new Variant(new vtime(inode->access_time(), TIME_UNIX))); attr["changed"] = Variant_p(new Variant(new vtime(inode->change_time(), TIME_UNIX))); if (inode->SB()->inodes_struct_size() > sizeof(inodes_t)) { uint8_t * tab = (uint8_t *)operator new(sizeof(__inode_reminder_t)); __inode_reminder_t * i_reminder = (__inode_reminder_t *)tab; inode->extfs()->vfile()->read(tab, sizeof(__inode_reminder_t)); attr["creation"] = Variant_p(new Variant(new vtime(i_reminder->creation_time, TIME_UNIX))); } delete c_attr; } delete inode->inode(); delete inode; return (attr); } void ExtfsNode::set_i_nb(uint64_t i_id) { __i_nb = i_id; } uint64_t ExtfsNode::i_nb() const { return __i_nb; } Inode * ExtfsNode::read_inode() { Inode * inode = NULL; inodes_t * i = NULL; try { inode = new Inode(this->__extfs, this->__extfs->SB(), this->__extfs->GD()); i = new inodes_t; inode->setInode(i); inode->read(__inode_addr, i); inode->init(); } catch (vfsError & e) { std::cerr << "Exception caught in ExtfNode::_attributes() : " << e.error << std::endl; delete i; delete inode; return NULL; } catch(std::exception & e) { std::cerr << "Not enought memory" << std::endl; delete i; delete inode; return NULL; } return inode; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/ExtfsRawDataNode.cpp000066400000000000000000000017361217176075400231700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "extfs.hpp" #include "include/ExtfsRawDataNode.h" ExtfsRawDataNode::ExtfsRawDataNode(std::string name, uint64_t size, Node * parent, Extfs * fsobj, uint64_t offset) : Node (name, size, parent, fsobj) { __offset = offset; __node = fsobj->node(); } ExtfsRawDataNode::~ExtfsRawDataNode() { } void ExtfsRawDataNode::fileMapping(FileMapping* fm) { fm->push(0, size(), __node, __offset); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/ExtfsSlackNode.cpp000066400000000000000000000071221217176075400226750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/ExtfsSlackNode.hpp" #include "data_structure/includes/Inode.h" #include "include/utils/SuperblockStructure.h" #include "data_structure/includes/Ext4Extents.h" ExtfsSlackNode::ExtfsSlackNode(std::string name, uint64_t size, Node * parent, Extfs * fsobj, uint64_t inode_addr) : Node(name, size, parent, fsobj) { Inode * inode = NULL; uint32_t blk_addr; this->__inode_addr = inode_addr; this->__size = size; this->__extfs = fsobj; if ((inode = read_inode())) { size = 0; if (inode->flags() & 0x80000) // uses extents { Ext4Extents * ext4 = new Ext4Extents(NULL); try { size = ext4->calc_size(inode); } catch(vfsError & e) { std::cerr << "vfsError caught in OrphansInode::load() : " << e.error << std::endl; return ; } } else { while ((blk_addr = inode->nextBlock())) size += __extfs->SB()->block_size(); bool large_files = __extfs->SB()->useRoFeatures(SuperBlockStructure::_LARGE_FILE, __extfs->SB()->ro_features_flags()); uint64_t inode_size = inode->getSize(inode->lower_size(), large_files); if (size > inode_size) size -= inode_size; else size = 0; } this->setSize(size); __size = size; } else { __size = 0; setSize(__size); } } ExtfsSlackNode::~ExtfsSlackNode() { } void ExtfsSlackNode::fileMapping(FileMapping * fm) { Inode * inode = NULL; uint64_t size = 0, blk_addr = 0, inode_size = 0; uint64_t block_size = __extfs->SB()->block_size(); bool large_files = false; uint32_t count = 0; uint64_t ooffset = __extfs->SB()->offset() - __BOOT_CODE_SIZE; if (!(inode = read_inode())) return ; large_files = __extfs->SB()->useRoFeatures(SuperBlockStructure::_LARGE_FILE, __extfs->SB()->ro_features_flags()); inode_size = inode->getSize(inode->lower_size(), inode->upper_size_dir_acl(), large_files); large_files = false; while ((blk_addr = inode->nextBlock())) { size += block_size; if (size > inode_size) { if (!large_files) { fm->push(0, block_size - inode_size, __extfs->node(), blk_addr * block_size + inode_size + ooffset); large_files = true; } else { fm->push(count * block_size - inode_size, block_size, __extfs->node(), blk_addr * block_size + ooffset); } } ++count; } } Inode * ExtfsSlackNode::read_inode() { Inode * inode = NULL; inodes_t * i = NULL; try { inode = new Inode(this->__extfs, this->__extfs->SB(), this->__extfs->GD()); i = new inodes_t; inode->setInode(i); inode->read(__inode_addr, i); inode->init(); } catch (vfsError & e) { std::cerr << "Exception caught in ExtfNode::_attributes() : " << e.error << std::endl; delete i; delete inode; return NULL; } catch(std::exception & e) { std::cerr << "Not enought memory" << std::endl; delete i; delete inode; return NULL; } return inode; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/ExtfsSymLinkNode.cpp000066400000000000000000000046351217176075400232340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/SymLink.h" #include "include/ExtfsSymLinkNode.h" ExtfsSymLinkNode::ExtfsSymLinkNode(std::string name, uint64_t size, Node * parent, Extfs * fsobj, uint64_t offset) : Node(name, size, parent, fsobj) { __offset = offset; __extfs = fsobj; } ExtfsSymLinkNode::~ExtfsSymLinkNode() { } void ExtfsSymLinkNode::fileMapping(FileMapping* fm) { SymLink * i_symlink = new SymLink(__extfs, __extfs->SB(), __extfs->GD()); inodes_t i; std::string path; ExtfsNode * n; if (!__offset) throw vfsError("Symbolic link size is NULL."); i_symlink->setInode(&i); try { i_symlink->read(__offset, &i); if (i_symlink->lower_size() <= 60) path.insert(0, (char *)&i_symlink->block_pointers()[0], i_symlink->lower_size()); else { uint64_t blk = i_symlink->nextBlock() * __extfs->SB()->block_size(); uint8_t * array = (uint8_t *)operator new(__extfs->SB()->block_size()); __extfs->v_seek_read(blk, array, __extfs->SB()->block_size()); path.insert(0, (char *)array, i_symlink->lower_size()); delete array; } path = i_symlink->resolveAbsolutePath(path, this); Node * node = i_symlink->find_target(path, __extfs); delete i_symlink; if (!node) throw vfsError("Node " + path + " does not exist.\n"); n = dynamic_cast(node); if (!n) throw vfsError("Node " + path + " does not exist (cast).\n"); this->setSize(n->size()); n->fileMapping(fm); } catch (vfsError & e) { std::cerr << "vfsError exception caught in ExtfsSymLinkNode::fileMapping() : " << e.error << std::endl; throw ; } catch (std::exception & e) { std::cerr << "ExtfsSymLinkNode::fileMapping() : std::exception caught : " << e.what() << std::endl; } } Attributes ExtfsSymLinkNode::_attributes() { Attributes attr; return attr; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/FileNameRecovery.cpp000066400000000000000000000177761217176075400232370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include #include "include/FileNameRecovery.h" #include "include/utils/InodeUtils.h" #include "include/ExtfsRawDataNode.h" //#define DIR_DEBUG FileNameRecovery::FileNameRecovery(Journal * journal) { _journal = journal; } FileNameRecovery::~FileNameRecovery() { delete _journal; } uint8_t FileNameRecovery::deletedFileNames(uint8_t * tab, uint64_t content_addr, Node * parent, Directory * inode_dir, DirEntry * dir) { DirEntry * del_dirent = new DirEntry; std::string name; Node * new_node = NULL; inodes_t * _inter = new (inodes_t); uint8_t valid = 0, tmp; for (uint64_t pos = content_addr; pos < (dir->entry_length() + content_addr - dir->next() - 12); ) { del_dirent->setDir((dir_entry_v2 *)(tab + pos)); tmp = valid_entry(del_dirent); valid = (valid == 2 ? valid : tmp); if (!tmp) { if (inode_dir->i_list()->find(del_dirent->inode_value())) { new_node = inode_dir->createNewNode(0, parent, setDirName(del_dirent, tab, pos), _inter); pos += del_dirent->next(); new_node->setDeleted(); continue ; } if (!(name = setDirName(del_dirent, tab, pos)).empty()) { Directory * inode_d = new Directory(inode_dir); #ifdef DIR_DEBUG if (name.compare(std::string("os-prober.VzowBI")) == 0) std::cout << "matched deleted" << std::endl; std::cout << "\tdel file : " << name << "\tcontent_addr : " << content_addr << std::endl; #endif if ((new_node = retrieve_inode(inode_d, del_dirent, parent, name, _inter))) { if (((_inter->file_mode & __IFMT) == __IFDIR) && (del_dirent->file_type_v2() == DirEntry::_DIRECTORY)) { if (!inode_dir->isAllocated(dir->inode_value(), _journal->extfs()->vfile())) { new_node->setDeleted(); Directory * new_dir = new Directory(inode_dir); new_dir->dirContent(new_node, _inter, __addr, del_dirent->inode_value()); delete new_dir; } } } delete inode_d; } pos += del_dirent->next(); new_node = NULL; } else pos += 4; if (pos >= inode_dir->SB()->block_size() || pos >= (dir->entry_length() + content_addr)) break ; } delete _inter; delete del_dirent; return valid; } ExtfsNode * FileNameRecovery::retrieve_inode(Directory * inode_dir, DirEntry * del_dirent, Node * parent, const std::string & name, inodes_t * _inter) { uint64_t inode_addr; ExtfsNode * node = NULL; __addr = inode_addr = inode_dir->getInodeByNumber(del_dirent->inode_value()); inode_dir->read(inode_addr, _inter); if (inode_dir->is_fucked_up()) { std::ostringstream oss; oss << del_dirent->inode_value(); new ExtfsRawDataNode(oss.str(), inode_dir->extfs()->SB()->inodes_struct_size(), inode_dir->extfs()->suspiscious_inodes(), inode_dir->extfs(), inode_addr + inode_dir->extfs()->SB()->offset() - __BOOT_CODE_SIZE); } if (retrieve_inode_direct(_inter, del_dirent->inode_value())) node = inode_dir->createNewNode(inode_addr, parent, name, _inter); else if (_journal) node = recovery(inode_addr / inode_dir->SB()->block_size(), inode_dir, del_dirent, _inter, parent); else { node = inode_dir->createNewNode(0, parent, (char *)name.c_str(), _inter); node->setDeleted(); return NULL; } if (node) { node->setDeleted(); node->set_i_nb(del_dirent->inode_value()); } if (inode_dir->i_list()->find(del_dirent->inode_value())) node = NULL; return node; } ExtfsNode * FileNameRecovery::recovery(uint32_t block_number, Directory * dir, DirEntry * dir_e, inodes_t * inode, Node * parent) { std::map >::const_iterator it_l; std::vector addr_list; ExtfsNode * node = NULL; uint64_t inode_addr = 0; it_l = _journal->journal_cache().find(block_number); if (it_l == _journal->journal_cache().end()) { node = dir->createNewNode(0, parent, __name, inode); node->setDeleted(); node = NULL; } else { addr_list = (*it_l).second; if (!addr_list.empty()) { std::vector::iterator it = addr_list.begin(); uint32_t nb_i_per_block = dir->SB()->block_size() / dir->SB()->inodes_struct_size(); bool found = false; for (; it != addr_list.end(); it++) { if (!(*it)) continue ; inode_addr = (*it) * ((uint64_t)_journal->SB()->block_size()); if (!((dir_e->inode_value() % nb_i_per_block))) inode_addr += (((dir_e->inode_value() % nb_i_per_block) + 1) * dir->SB()->inodes_struct_size()); else inode_addr += (((dir_e->inode_value() % nb_i_per_block) - 1) * dir->SB()->inodes_struct_size()); dir->extfs()->v_seek_read(inode_addr, (void *)inode, sizeof(inodes_t)); if (inode->block_pointers[0] && !inode->delete_time) { if (((inode->file_mode & __IFMT) == __IFREG) && dir_e->file_type_v2() == DirEntry::_REG_FILE) node = dir->createNewNode(inode_addr, parent, __name, inode); else node = dir->createNewNode(0, parent, __name, inode); node->setDeleted(); node->set_i_nb(dir_e->inode_value()); found = true; } if (!found) { node = dir->createNewNode(0, parent, __name, inode); node->setDeleted(); } } } else { node = dir->createNewNode(0, parent, __name, inode); node->setDeleted(); node->set_i_nb(dir_e->inode_value()); node = NULL; } } return node; } bool FileNameRecovery::retrieve_inode_direct(inodes_t * inode, uint32_t inode_nb) { if (inode->block_pointers[0] && !_journal->isAllocated(inode_nb, _journal->extfs()->vfile())) return true; return false; } uint8_t FileNameRecovery::valid_entry(DirEntry * dir) { uint8_t ret = 0; // 0 : OK, 1 : valide, 2 : invalide if (!dir) return 1; else if (!dir->inode_value() && !dir->name_length_v1() && !dir->entry_length()) return 1; else if (dir->inode_value() > _journal->SB()->inodesNumber()) ret = 2; else if ((dir->entry_length() >= _journal->SB()->block_size()) || !dir->entry_length()) ret = 2; else if (dir->entry_length() < 12) // min rec len == 12 ret = 2; else if (_journal->SB()->incompatible_feature_flags() & SuperBlockStructure::_DIR_FILE_TYPE) { if (!dir->name_length_v2()) ret = 2; if (dir->file_type_v2() > 7) ret = 2; } else { if (!dir->name_length_v1()) ret = 2; if (dir->name_length_v1() > 255) ret = 2; } return ret; } bool FileNameRecovery::valid_name(char * name, uint8_t name_len, uint16_t entry_len) { if (name[0] == 0) return false; /* consider . and .. as invalid names to avoid weird behaviors such as infinite recursion */ if (!strcmp((char *)name, "..") || !strcmp((char *)name, ".")) return false; if (name_len > entry_len) return false; return true; } std::string FileNameRecovery::setDirName(DirEntry * del_dirent, uint8_t * tab, uint64_t pos) { std::string name(""); name.append((char *)(tab + pos) + 8 * sizeof(uint8_t), del_dirent->name_length_v2()); del_dirent->setName((uint8_t *)(name.c_str())); if (!valid_name((char *)name.c_str(), del_dirent->name_length_v2(), del_dirent->entry_length())) return (__name = ""); __name = name; return name; } Journal * FileNameRecovery::getJournal() const { return _journal; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/FsStat.cpp000066400000000000000000000235271217176075400212330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include #include "node.hpp" #include "include/FsStat.h" #include "include/CustomResults.h" FsStat::FsStat() { _gd_table = NULL; } FsStat::~FsStat() { delete _gd_table; } void FsStat::disp(SuperBlock * SB, VFile * vfile) { general(SB); features(SB); groupInformations(SB, vfile); } void FsStat::general(SuperBlock * SB) { std::cout << "-------- GENERAL INFORMATIONS --------" << std::endl; std::cout << "Volume name : " << SB->volume_name() << std::endl; std::cout << "Number of blocks : " << SB->blocks_number() << std::endl; std::cout << "Groups number : " << SB->group_number() << std::endl; std::cout << "Number of inodes : " << SB->inodesNumber() << std::endl; std::cout << "Number of free inodes : " << SB->u_inodes_number() << std::endl; std::cout << "Inodes per groups : " << SB->inodes_in_group_number() << std::endl; std::cout << "Block size : " << SB->block_size() << std::endl; std::cout << "Journal inode : " << SB->journal_inode() << std::endl; std::cout << "Orphans inode : " << SB->orphan_node_list() << std::endl; std::cout << "Descriptor size : " << SB->getSuperBlock()->s_desc_size << std::endl; std::cout << std::endl; } void FsStat::features(SuperBlock * SB) { std::cout << " ---- FEATURES ---- " << std::endl; compatible_features(SB); incompatible_features(SB); read_only_features(SB); std::cout << std::endl; } void FsStat::compatible_features(SuperBlock * SB) { std::cout << "Compatible features : " << CustomResults::getCompatibleFeatures(SB->compatible_feature_flags()) << std::endl; } void FsStat::incompatible_features(SuperBlock * SB) { std::cout << "Incompatible features : " << CustomResults::getIncompatibleFeatures(SB->incompatible_feature_flags()) << std::endl; } void FsStat::read_only_features(SuperBlock * SB) { std::cout << "Read only features : " << CustomResults::getReadOnlyFeatures(SB->ro_features_flags()) << std::endl; } void FsStat::groupInformations(SuperBlock * SB, VFile * vfile) { _gd_table = getGroupDescriptor(SB->block_size(), vfile, SB->offset()); bool sparse = SB->useRoFeatures(SuperBlock::_SPARSE_SUPERBLOCK, SB->ro_features_flags()); std::cout << "-------- GROUPS --------" << std::endl; for (unsigned int i = 0; i < SB->group_number(); ++i) { std::cout << "Group " << i << std::endl; std::pair i_range = inode_range(SB->inodes_in_group_number(), i); std::cout << "Inode range : " << i_range.first << " -> " << i_range.second << std::endl; std::pair b_range = block_range(i, SB->block_in_groups_number(), SB->blocks_number()); std::cout << "Blocks range : " << b_range.first << " -> " << b_range.second << std::endl; sparse_option(sparse, i, SB->block_in_groups_number()); std::cout << "\tBlock bitmap : " << _gd_table[i].block_bitmap_addr << std::endl; std::cout << "\tInode bitmap : " << _gd_table[i].inode_bitmap_addr << std::endl; std::pair it_range = inode_table_range(i, SB); std::cout << "\tInode table : " << it_range.first << " -> " << it_range.second << std::endl; std::pair data_range = d_range(i, SB->block_in_groups_number(), it_range.second + 1); std::cout << "\tData range : " << data_range.first << " -> " << data_range.second << std::endl; std::cout << "Directories number : " << _gd_table[i].dir_nbr << std::endl; unallocated_inodes(SB->inodes_in_group_number(), i); unallocated_blocks(SB->block_in_groups_number(), i, SB->blocks_number()); std::cout << std::endl; } } std::pair FsStat::inode_range(uint32_t i_nb_gr, uint32_t gr) { uint32_t begin; begin = gr * i_nb_gr; return std::make_pair(begin + 1, begin + i_nb_gr); } std::pair FsStat::block_range(uint32_t gr, uint32_t b_in_gr, uint32_t b_nb) { uint32_t begin, end; begin = gr * b_in_gr; end = begin + b_in_gr; end = (end > b_nb ? b_nb - 1 : end - 1); return std::make_pair(begin, end); } group_descr_table_t * FsStat::getGroupDescriptor(uint32_t block_size, VFile * vfile, uint64_t offset) { group_descr_table_t * gd_table = (group_descr_table_t *)operator new(block_size); // read the block containing the group descriptor table. try { if (block_size != __BOOT_CODE_SIZE) vfile->seek(block_size + offset - __BOOT_CODE_SIZE); else vfile->seek(block_size + offset); vfile->read((void *)gd_table, block_size); return gd_table; } catch (vfsError & e) { // delete gd_table and throw the exception delete gd_table; throw ; } } std::pair FsStat::inode_table_range(uint32_t gr, SuperBlock * SB) { uint32_t begin, end; uint32_t inode_per_block; begin = _gd_table[gr].inode_table_block_addr; inode_per_block = SB->block_size() / SB->inodes_struct_size(); end = SB->inodes_in_group_number() / inode_per_block; return std::make_pair(begin, begin + end - 1); } void FsStat::sparse_option(bool sparse, uint32_t gr, uint32_t nb_b_b) { if (!sparse || (_gd_table[gr].block_bitmap_addr != (gr * nb_b_b))) { std::cout << "\tSuperBlock : " << gr * nb_b_b << std::endl; std::cout << "\tGroup descriptor : " << gr * nb_b_b + 1 << std::endl; } } std::pair FsStat::d_range(uint32_t gr, uint32_t b_gr_nb, uint32_t begin) { uint32_t end; end = (gr + 1) * b_gr_nb; return std::make_pair(begin, end - 1); } std::string FsStat::unallocated_inodes(uint32_t nb_i_gr, uint32_t gr, bool display) { float proportion; std::ostringstream oss; std::string res; proportion = _gd_table[gr].unallocated_inodes_nbr * 100; proportion /= (nb_i_gr ? nb_i_gr : 1); oss << _gd_table[gr].unallocated_inodes_nbr; oss << "(" << (int)proportion << "%)"; res = oss.str(); if (display) std::cout << res << std::endl; return res; } std::string FsStat::unallocated_blocks(uint32_t nb_b_gr, uint32_t gr, uint32_t nb_blocks, bool display) { float proportion; std::string res; if (gr == (nb_blocks / nb_b_gr)) nb_b_gr = (nb_blocks - gr * nb_b_gr); proportion = _gd_table[gr].unallocated_block_nbr * 100; proportion /= (nb_b_gr ? nb_b_gr : 1); std::ostringstream oss; oss << _gd_table[gr].unallocated_block_nbr; oss << " (" << (int)proportion << "%)"; res = oss.str(); if (display) std::cout << res << std::endl; return res; } void FsStat::attr_stat(const SuperBlock * SB, VFile * vfile, Attributes * attr) { _gd_table = getGroupDescriptor(SB->block_size(), vfile, SB->offset()); bool sparse = SB->useRoFeatures(SuperBlock::_SPARSE_SUPERBLOCK, SB->ro_features_flags()); std::map l; std::map m; std::map details; for (unsigned int i = 0; i < SB->group_number(); ++i) { std::ostringstream oss; std::string key; m.clear(); details.clear(); key = __build_range(inode_range(SB->inodes_in_group_number(), i)); m["Inode range"] = Variant_p(new Variant(key)); key = __build_range(block_range(i, SB->block_in_groups_number(), SB->blocks_number())); m["Block range"] = Variant_p(new Variant(key)); m["Directories number"] = Variant_p(new Variant(_gd_table[i].dir_nbr)); key = unallocated_blocks(SB->block_in_groups_number(), i, SB->blocks_number(), false); m["Unallocated blocks"] = Variant_p(new Variant(key)); key = unallocated_inodes(SB->inodes_in_group_number(), i, false); m["Unallocated inodes"] = Variant_p(new Variant(key)); oss << i; std::pair sb_gd_bkp = sb_gd_backups(sparse, i, SB->block_in_groups_number()); if (sb_gd_bkp.first != sb_gd_bkp.second) { details["Superblock"] = Variant_p(new Variant(sb_gd_bkp.first)); details["Group descriptor"] = Variant_p(new Variant(sb_gd_bkp.second)); } details["Block bitmap"] = Variant_p(new Variant(_gd_table[i].block_bitmap_addr)); details["Inode bitmap"] = Variant_p(new Variant(_gd_table[i].inode_bitmap_addr)); std::pair it_range = inode_table_range(i, (SuperBlock *)SB); key = __build_range(it_range); details["Inode table block range"] = Variant_p(new Variant(key)); key = __build_range(d_range(i, SB->block_in_groups_number(), it_range.second + 1)); details["Data blocks range"] = Variant_p(new Variant(key)); m["Details"] = Variant_p(new Variant(details)); l[std::string("Group ") + oss.str()] = Variant_p(new Variant(m)); } (*attr)[std::string("File system layout")] = Variant_p(new Variant(l)); } std::pair FsStat::sb_gd_backups(bool sparse, uint32_t gr, uint32_t nb_b_b) { std::pair p; if (!sparse || (_gd_table[gr].block_bitmap_addr != (gr * nb_b_b))) p = std::make_pair(gr * nb_b_b, gr * nb_b_b + 1); else p = std::make_pair(0, 0); return p; } std::string FsStat::__build_range(std::pair p) { std::ostringstream oss, oss2; std::string key; oss << p.first; key = oss.str() + std::string(" -> "); oss2 << p.second; key += oss2.str(); return key; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/InodeStat.cpp000066400000000000000000000123761217176075400217210ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include "include/InodeStat.h" #include "include/utils/InodeUtils.h" #include "include/CustomAttrib.h" InodeStat::InodeStat(SuperBlock * SB, Extfs * extfs) { _SB = SB; _extfs = extfs; } InodeStat::~InodeStat() { } void InodeStat::stat(std::string opt) { size_t pos; uint32_t inode_nb; while ((pos = opt.rfind(",")) != std::string::npos) { std::string tmp = opt.substr(pos + 1, opt.size()); opt = opt.substr(0, pos); std::istringstream iss(tmp); iss >> inode_nb; stat(inode_nb); } std::istringstream iss2(opt); iss2 >> inode_nb; stat(inode_nb); } void InodeStat::stat(uint32_t inode_nb) { std::auto_ptr GD (new GroupDescriptor(_SB, _SB->block_size())); CustomAttrib * attr = new CustomAttrib; std::auto_ptr inode(new Inode(_extfs, _SB, GD.get())); std::map times; uint64_t inode_addr = 0; inodes_t inode_struct; GD->init(_SB->block_size(), _extfs->vfile(), _SB->group_number()); try { inode->setInode(&inode_struct); _extfs->v_seek_read((inode_addr = inode->getInodeByNumber(inode_nb)), (void *)inode->inode(), sizeof(inodes_t)); } catch(vfsError & e) { std::cerr << "InodeStat::stat(uint32_t) : vfsError exception caught : " << e.error << std::endl; return ; } attr->imap.insert(std::make_pair("Inode number", inode_nb)); attr->imap.insert(std::make_pair("Address", inode_addr)); attr->imap.insert(std::make_pair("Size (in Bytes)", inode->getSize(inode->lower_size(), inode->upper_size_dir_acl(), true))); if (inode->flags() & 0x80000) attr->smap.insert(std::make_pair("Inode uses extents", "yes")); else attr->smap.insert(std::make_pair("Inode uses extents", "no")); attr->imap.insert(std::make_pair("Group", inode->groupNumber(inode_nb))); attr->smap.insert(std::make_pair("mode", inode->type_mode(inode->file_mode()))); attr->setAttr(inode.get()); attr->setSetUidGid(inode.get()); attr->setUidGid(inode.get()); attr->setTime(inode.get()); std::cout << "Inode nb " << inode_nb << std::endl; display(attr->imap); display(attr->smap); if (inode->file_acl_ext_attr()) { std::auto_ptr ext_attr(new ExtendedAttr(inode->file_acl_ext_attr(), _SB->block_size())); ext_attr->init(_extfs); disp_xattr(ext_attr.get()); disp_acl(ext_attr.get()); } block_list(inode.get()); std::cout << std::endl; } template void InodeStat::display(const std::map & attr) { typename std::map::const_iterator it; for (it = attr.begin(); it != attr.end(); it++) std::cout << "\t" << (*it).first << " : " << (*it).second << std::endl; } void InodeStat::disp_xattr(ExtendedAttr * xattr) { std::map >::const_iterator user; user = xattr->getUserXAttr().begin(); std::cout << "\tUser attr :" << std::endl; for (; user != xattr->getUserXAttr().end(); user++) std::cout << "\t\tuser." << (*user).second.first << "=" << (*user).second.second << std::endl; std::cout << std::endl; } void InodeStat::disp_acl(ExtendedAttr * xattr) { std::map >::const_iterator acl; std::cout << "\tACL :" << std::endl; acl = xattr->getPosixACL().begin(); for (; acl != xattr->getPosixACL().end(); acl++) { std::list::const_iterator acl_l = (*acl).second.begin(); while (acl_l != (*acl).second.end()) { std::cout << "\t\t"; if (xattr->acl_size((*acl_l)->type) == sizeof(posix_acl_entries)) { std::cout << "id : " << (*acl_l)->user_group_id; std::cout << xattr->aclPermissions((*acl_l)->permissions) << std::endl; } acl_l++; } } } void InodeStat::block_list(Inode * inode) { uint32_t block_number; uint32_t tmp = _SB->block_size() / 4; uint32_t tab = 0; if (inode->flags() & 0x80000) // extents, do nothing for now ; else for(uint32_t i = 0; i <= (tmp * tmp); ++i) { block_number = inode->goToBlock(i); if (i == 0) { std::cout << "\nDirect blocks :" << std::endl; tab = 1; } else if (i == 12) { std::cout << "\nSingle indirect blocks :" << std::endl; tab = 1; } else if ((i - 12) == tmp) { std::cout << "\nDouble indirect blocks :" << std::endl; tab = 1; } else if ((i - 12 - tmp) == (tmp * tmp)) { std::cout << "\nTriple indirect blocks :" << std::endl; tab = 1; } if (block_number) { std::cout << "\t" << block_number; if (!(tab % 8)) std::cout << std::endl; tab++; } } } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/InodeUtils.cpp000066400000000000000000000073301217176075400221000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "data_structure/includes/Inode.h" #include "include/utils/InodeUtils.h" InodeUtils::InodeUtils(const SuperBlock * SB, GroupDescriptor * GD) { _SB = SB; _GD = GD; } InodeUtils::~InodeUtils() { } uint64_t InodeUtils::getSize(uint32_t l_size, uint32_t h_size, bool large_file) const { if (large_file) { uint64_t size = h_size; return (size << 32) + l_size; } return l_size; } uint64_t InodeUtils::getInodeByNumber(uint32_t inode_number) { if (!inode_number || inode_number > _SB->inodesNumber()) return 0; uint16_t group = groupNumber(inode_number); uint64_t inode_table_addr = ((uint64_t)_GD->inode_table_block_addr(group)) * _SB->block_size(); uint64_t tmp = ((inode_number - 1) % _SB->inodes_in_group_number()); return (uint64_t)inode_table_addr + (tmp * _SB->inodes_struct_size()); } bool InodeUtils::isAllocated(uint32_t inode_number, VFile * vfile) { if (!inode_number || (inode_number > _SB->inodesNumber())) return false; uint16_t group = groupNumber(inode_number); uint64_t inode_bitmap_addr = ((uint64_t)_GD->inode_bitmap_addr(group)) * _SB->block_size(); uint64_t bit_addr = ((uint64_t)inode_bitmap_addr) + (inode_number - 1) / 8; uint8_t bits; if (!vfile->seek(bit_addr + _SB->offset() - __BOOT_CODE_SIZE) || !vfile->read(&bits, sizeof(uint8_t))) return false; inode_number--; uint8_t tmp = inode_number % 8; return ((bits >> tmp) & 1); } uint16_t InodeUtils::groupNumber(uint32_t inode_number) { return (inode_number - 1) / _SB->inodes_in_group_number(); } std::string InodeUtils::allocationStatus(uint32_t inode_number, VFile * vfile) { return isAllocated(inode_number, vfile) ? "Allocated" : "Not allocated"; } std::string InodeUtils::mode(uint16_t file_mode) { std::string access = "rwxrwxrwx"; uint16_t mode = 0x100; for (int i = 0; i < 9; ++i, mode = (mode >> 1)) access[i] = ((mode & file_mode) ? access[i] : '-'); return access; } std::string InodeUtils::uid_gid(uint16_t uid, uint16_t gid) { std::string uid_gid; std::ostringstream uid_s; uid_s << uid; std::ostringstream gid_s; gid_s << gid; uid_gid = uid_s.str() + "/" + gid_s.str(); return uid_gid; } std::string InodeUtils::set_uid_gid(uint16_t file_mode) { std::string uidgid; if (file_mode & Inode::_ISUID) uidgid = " Yes / "; else uidgid = " No / "; if (file_mode & Inode::_ISGID) uidgid += "Yes"; else uidgid += "No"; return uidgid; } std::string InodeUtils::type(uint16_t file_mode) { switch (file_mode & __IFMT) { case __IFDIR : return "d"; case __IFREG : return "-"; case __IFLNK : return "l"; case __IFBLK : return "b"; case __IFIFO : return "p"; case __IFCHR : return "c"; case __IFSOCK : return "s"; } return "?"; } std::string InodeUtils::type_mode(uint16_t file_mode) { return type(file_mode) + mode(file_mode); } const SuperBlock * InodeUtils::SB() const { return _SB; } GroupDescriptor * InodeUtils::GD() const { return _GD; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/InodesList.cpp000066400000000000000000000064761217176075400221100ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include "include/InodesList.h" #include "include/InodeStat.h" #include "data_structure/includes/Inode.h" InodesList::InodesList(SuperBlock * SB, VFile * vfile) { _begin = 0; _end = 0; _SB = SB; _vfile = vfile; } InodesList::~InodesList() { } void InodesList::list(const std::string & opt, uint32_t nb_inodes) throw (vfsError) { size_t pos; if ((pos = opt.find("-")) != std::string::npos) { std::string tmp = opt.substr(pos + 1, opt.size() - 1); std::istringstream iss(tmp); iss >> _end; } std::stringstream iss; if (pos == std::string::npos) iss << opt; else iss << opt.substr(0, pos); iss >> _begin; if (_end && (_begin > _end)) throw vfsError("InodesList::list() : last inode number > first."); if (!check_inode_range(nb_inodes)) throw vfsError("InodesList::list() : inodes out of range."); } bool InodesList::check_inode_range(uint32_t nb_inodes) { bool ok; ok = (_begin > nb_inodes); if (_end) ok = (_end > nb_inodes); return !ok; } void InodesList::display(Extfs * extfs) { for (uint32_t it = _begin; it <= _end; ++it) infos(extfs, it); if (!_end) infos(extfs, _begin); } void InodesList::infos(Extfs * extfs, uint32_t inode_nb) { std::auto_ptr i (new Inode(extfs, _SB, extfs->GD())); inodes_t inode; i->setInode(&inode); std::string alloc; uint64_t size; bool large_files; InodeStat i_stat(_SB, extfs); // read inode and gt its allocation status. i->read(i->getInodeByNumber(inode_nb), &inode); alloc = i->allocationStatus(inode_nb, extfs->vfile()); std::cout << inode_nb << " | " << alloc; std::cout << " | " << i->type(i->file_mode()) << i->mode(i->file_mode()); // access time if (i->access_time()) disp_time("A", i->access_time()); // modification time if ( i->modif_time()) disp_time("M", i->modif_time()); // change time if ( i->change_time()) disp_time("C", i->change_time()); // deletion time if (i->delete_time()) disp_time("D", i->delete_time()); std::cout << " | UID / GID : " << i->uid_gid(i->lower_uid(), i->lower_gid()); large_files = _SB->useRoFeatures(SuperBlock::_LARGE_FILE, _SB->ro_features_flags()); size = i->getSize(i->lower_size(), i->upper_size_dir_acl(), large_files); if (size) std::cout << " | " << size << "B"; if (i->file_acl_ext_attr()) std::cout << " | Ext attr : " << i->file_acl_ext_attr(); std::cout << std::endl; } void InodesList::disp_time(const std::string & name, const uint32_t t) { #ifndef WIN32 if (t) { time_t ti = t; std::string t_str = ctime(&ti); t_str[t_str.size() - 1] = 0; std::cout << " | " << name << " : " << t_str; } #endif } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/Journal.cpp000066400000000000000000000100571217176075400214330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "include/Journal.h" #include "include/JournalType.h" Journal::Journal(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD) : Inode(extfs, SB, GD), __J_SB(NULL), __J_V2_reminder(NULL) { __inode = NULL; __inode = (inodes_t *)operator new (sizeof(inodes_t)); } Journal::~Journal() { delete this->__J_SB; delete this->__J_V2_reminder; delete __inode; } bool Journal::init() { uint8_t * read_array = NULL; if (!_SB->journal_inode()) return false; /* get the inode address and read it */ uint64_t addr = getInodeByNumber(_SB->journal_inode()); _extfs->v_seek_read(addr, (void *)__inode, sizeof(inodes_t)); /* got to journal first block and read it */ uint64_t journal_addr = nextBlock(); journal_addr *= _SB->block_size(); read_array = (uint8_t *)operator new(sizeof(journal_superblock)); _extfs->v_seek_read(journal_addr, (void *)read_array, sizeof(journal_superblock)); __J_SB = (journal_superblock *)read_array; /* if there is a reminder, read it */ if (__J_SB->header.block_type == Journal::__SB_V2) { read_array = (uint8_t *)operator new(sizeof(journal_v2_reminder)); _extfs->vfile()->read((void *)read_array, sizeof(journal_v2_reminder)); __J_V2_reminder = (journal_v2_reminder *)read_array; } caching(); return true; } void Journal::caching() { uint64_t addr; JournalType j_block_size(__J_SB->block_size); uint8_t * j_block; journal_header * j_header; goToBlock(1); j_block = (uint8_t *)operator new (j_block_size.value() * sizeof(uint8_t)); while ((addr = browseBlock(1, __J_SB->blocks_number))) { _extfs->v_seek_read(addr * _SB->block_size(), (void *)j_block, j_block_size.value()); j_header = ((journal_header *)j_block); JournalType sig(j_header->signature), b_type(j_header->block_type); if ((sig.value() == __J_SIGNATURE) && (b_type.value() == Journal::__DESCR_BLOCK)) parseCommitBlocks(j_block + sizeof(journal_header), j_block_size.value()); } delete j_block; } void Journal::parseCommitBlocks(uint8_t * j_block, uint32_t j_block_size) { journal_block_entries * j_block_descr; JournalType fs_block, flags; std::list b_list; for (uint32_t offset = 0; offset <= (j_block_size - sizeof(journal_header) - sizeof(journal_block_entries));) { j_block_descr = ((journal_block_entries *)(j_block + offset)); fs_block.setValue(j_block_descr->file_system_block); flags.setValue(j_block_descr->entry_flags); b_list.push_back(fs_block.value()); offset += sizeof(journal_block_entries); if (!(flags.value() & 0x02)) offset += (4 * sizeof(uint32_t)); } getBlocksAddr(b_list); } void Journal::getBlocksAddr(const std::list & b_list) { std::list::const_iterator it; std::map >::iterator c_it; uint64_t addr; for (it = b_list.begin(); it != b_list.end(); it++) if (*it) { if ((addr = nextBlock())) { _extfs->vfile()->seek(addr); c_it = __j_cache.find(*it); if (c_it == __j_cache.end()) { std::vector tmp; tmp.push_back(addr); __j_cache.insert(std::make_pair(*it, tmp)); } else (*c_it).second.push_back(addr); } } } const std::map > & Journal::journal_cache() const { return __j_cache; } const journal_superblock * Journal::j_super_block() const { return this->__J_SB; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/JournalStat.cpp000066400000000000000000000112451217176075400222670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "include/JournalStat.h" #include "include/JournalType.h" JournalStat::JournalStat(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD) { _journal = std::auto_ptr (new Journal(extfs, SB, GD)); _extfs = extfs; _SB = SB; } JournalStat::~JournalStat() { } void JournalStat::stat() { if (!_journal->init()) { std::cerr << "An error occured while initializing the journal. " "Cannot stat." << std::endl; return ; } JournalType j_type(_journal->j_super_block()->header.signature), b_type(_journal->j_super_block()->header.block_type); if (j_type.value() != __J_SIGNATURE) { std::cerr << "JournalStat error : signature is different from 0x" << std::hex << __J_SIGNATURE << std::endl; std::cerr << "sig : " << std::hex << j_type.value() << std::endl; return ; } std::cout << "Journal stat :" << std::endl; std::cout << "\tJournal inode : " << _journal->SB()->journal_inode() << std::endl; std::cout << "\tSuper block version : " << (( b_type.value() == Journal::__SB_V2) ? 2 : 1) << std::endl; b_type.setValue(_journal->j_super_block()->block_size); std::cout << "\tBlock size : " << b_type.value() << std::endl; b_type.setValue(_journal->j_super_block()->blocks_number); std::cout << "\tNumber of blocks : " << b_type.value() << std::endl; b_type.setValue(_journal->j_super_block()->block_first_transaction); std::cout << "\tBlock first transaction : " << b_type.value() << std::endl; jlist(); } void JournalStat::jlist() { uint64_t addr; uint8_t * j_block; journal_header * j_header; JournalType nb_blocks(_journal->j_super_block()->blocks_number), begin(_journal->j_super_block()->block_first_transaction), j_block_size(_journal->j_super_block()->block_size); j_block = (uint8_t *)operator new (j_block_size.value() * sizeof(uint8_t)); while ((addr = _journal->browseBlock(begin.value(), nb_blocks.value()))) { _extfs->v_seek_read(addr * _SB->block_size(), (void *)j_block, j_block_size.value()); j_header = ((journal_header *)j_block); JournalType sig(j_header->signature), b_type(j_header->block_type); if ((sig.value() == __J_SIGNATURE) && (b_type.value() == Journal::__DESCR_BLOCK)) { JournalType trans(j_header->sequence_number); std::cout << _journal->currentBlock() - 1 << " : Descriptor block (Seq " << trans.value() << ")" << std::endl; uint32_t mini_pouce = commitBlock(j_block + sizeof(journal_header), j_block_size.value()); _journal->goToBlock(_journal->currentBlock() + mini_pouce); } else if ((sig.value() == __J_SIGNATURE) && (b_type.value() == Journal::__COMMIT_BLOCK)) { JournalType trans(j_header->sequence_number); std::cout << _journal->currentBlock() - 1 << " : Commit block (Seq " << trans.value() << ")" << std::endl << std::endl; } else if ((sig.value() == __J_SIGNATURE) && (b_type.value() == Journal::__REVOKE_BLOCK)) { JournalType trans(j_header->sequence_number); std::cout << _journal->currentBlock() - 1 << " : Revoke block (Seq " << trans.value() << ")" << std::endl; } else std::cout << _journal->currentBlock() - 1 << " : Unknown block. " << std::endl; } } unsigned int JournalStat::commitBlock(uint8_t * j_block, uint32_t j_block_size) { journal_block_entries * j_block_descr; JournalType fs_block, flags; unsigned int count = 0; unsigned int nb = 0; for (uint32_t offset = 0; offset < (j_block_size - sizeof(journal_header)); ++count) { j_block_descr = ((journal_block_entries *)(j_block + offset)); fs_block.setValue(j_block_descr->file_system_block); flags.setValue(j_block_descr->entry_flags); if (fs_block.value()) { std::cout << _journal->currentBlock() + count << ": " << "Fs block\t" << fs_block.value() << std::endl; nb++; } offset += sizeof(journal_block_entries); if (!(flags.value() & 0x02)) offset += (4 * sizeof(uint32_t)); } return nb; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/JournalType.tpp000066400000000000000000000046211217176075400223160ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include template JournalType::JournalType(T val) { _value = val; if (val) _value = _convert(); } template T JournalType::value() { return this->_value; } template bool JournalType::_test() { uint32_t Value32; uint8_t *VPtr = (uint8_t *)&Value32; VPtr[0] = VPtr[1] = VPtr[2] = 0; VPtr[3] = 1; return Value32; } template T JournalType::_convert() { if (typeid(T) == typeid(uint32_t)) _value = _convert_htob32(); else if (typeid(T) == typeid(uint16_t)) _value = _convert_htob16(); else if (typeid(T) == typeid(uint64_t)) _value = _convert_htob64(); return _value; } template uint16_t JournalType::_convert_htob16() { if (_test()) return ((((_value) >> 8) & 0xffu) | (((_value) & 0xffu) << 8)); return _value; } template uint32_t JournalType::_convert_htob32() { if (_test()) return ((((_value) & 0xff000000u) >> 24) | (((_value) & 0x00ff0000u) >> 8) | (((_value) & 0x0000ff00u) << 8) | (((_value) & 0x000000ffu) << 24)); return _value; } template uint64_t JournalType::_convert_htob64() { if (_test()) return ((((_value) & 0xff00000000000000ull) >> 56) | (((_value) & 0x00ff000000000000ull) >> 40) | (((_value) & 0x0000ff0000000000ull) >> 24) | (((_value) & 0x000000ff00000000ull) >> 8) | (((_value) & 0x00000000ff000000ull) << 8) | (((_value) & 0x0000000000ff0000ull) << 24) | (((_value) & 0x000000000000ff00ull) << 40) | (((_value) & 0x00000000000000ffull) << 56)); return _value; } template void JournalType::setValue(T val) { _value = val; _convert(); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/MfsoAttrib.cpp000066400000000000000000000100551217176075400220710ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include "data_structure/includes/ExtendedAttr.h" #include "data_structure/includes/Ext4Extents.h" #include "include/MfsoAttrib.h" #include "vtime.hpp" MfsoAttrib::MfsoAttrib() { } MfsoAttrib::~MfsoAttrib() { } void MfsoAttrib::setAttrs(Inode * inode, Attributes * attr, uint64_t i_nb, uint64_t i_addr) { if (inode->delete_time()) (*attr)["Deletion time"] = Variant_p(new Variant(new vtime(inode->delete_time(), TIME_UNIX))); if (!i_nb) return ; (*attr)["Number"] = Variant_p(new Variant(i_nb)); std::ostringstream oss; oss << i_addr << " ( 0x" << std::hex << i_addr << ") "; (*attr)["Address"] = Variant_p(new Variant(oss.str())); (*attr)["Group"] = Variant_p(new Variant(inode->groupNumber(i_nb))); (*attr)["UID / GID"] = Variant_p(new Variant(inode->uid_gid(inode->lower_uid(), inode->lower_gid()))); (*attr)["File mode"] = Variant_p(new Variant(inode->type_mode(inode->file_mode()))); (*attr)["Set UID / GID ?"] = Variant_p(new Variant(inode->set_uid_gid(inode->file_mode()))); if (inode->flags() & 0x80000) (*attr)["Inode uses extents"] = Variant_p(new Variant(std::string("yes"))); else (*attr)["Inode uses extents"] = Variant_p(new Variant(std::string("no"))); (*attr)["Link number"] = Variant_p(new Variant(inode->link_coun())); (*attr)["Sector count"] = Variant_p(new Variant(inode->sector_count())); (*attr)["NFS generation number"] = Variant_p(new Variant(inode->generation_number_nfs())); (*attr)["Fragment block"] = Variant_p(new Variant(inode->fragment_addr())); (*attr)["Fragment index"] = Variant_p(new Variant(inode->fragment_index())); (*attr)["Fragment size"] = Variant_p(new Variant(inode->fragment_size())); if (inode->file_acl_ext_attr()) { __add_xtd_attr(inode, attr); __add_acl(inode, attr); } } void MfsoAttrib::__add_xtd_attr(Inode * inode, Attributes * attr) { ExtendedAttr * xtd_attr; (*attr)["Extended attribute header"] = Variant_p(new Variant(inode->file_acl_ext_attr())); xtd_attr = new ExtendedAttr(inode->file_acl_ext_attr(), inode->SB()->block_size()); xtd_attr->init(inode->extfs()); std::map >::const_iterator user; std::string xtd = "Inode extended attributes"; std::map m; user = xtd_attr->getUserXAttr().begin(); for (; user != xtd_attr->getUserXAttr().end(); user++) m["user." + (*user).second.first] = Variant_p(new Variant((*user).second.second)); (*attr)[xtd] = Variant_p(new Variant(m)); } void MfsoAttrib::__add_acl(Inode * inode, Attributes * attr) { (void)inode; // to avoid a warning (*attr)[std::string("Posix ACL")] = Variant_p(new Variant(std::string("Not handled yet. \ Please use the --istat option."))); // TODO } void MfsoAttrib::__symlink_path(Inode * inode, Attributes * attr) { std::string path(""); uint16_t size; // max path length contained directly in the inode if ((size = inode->lower_size()) < 60) path.insert(0, (char *)&inode->block_pointers()[0], size); else { uint8_t * tab; uint64_t addr; tab = (uint8_t *)operator new(size * sizeof(uint8_t)); addr = inode->block_pointers()[0] * inode->SB()->block_size(); inode->extfs()->v_seek_read(addr, tab, size); path.insert(0, (char *)tab, size); (*attr)["Link block"] = Variant_p(new Variant(inode->block_pointers()[0])); } (*attr)["Link target"] = Variant_p(new Variant(path)); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/Option.cpp000066400000000000000000000046421217176075400212740ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the proje`ct provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "include/Option.h" #include "include/FsStat.h" #include "include/InodeStat.h" #include "include/InodesList.h" #include "include/JournalStat.h" #include "include/BlkList.h" Option::Option(std::map arg, SuperBlock * SB, VFile * vfile, GroupDescriptor * GD) { this->arg = arg; __SB = SB; __vfile = vfile; __GD = GD; } Option::~Option() { } void Option::parse(Extfs * extfs) { std::map::iterator it; std::string blk(""), dir_path(""), istat_opt(""); std::string ils(""), jstat(""); bool fs_stat = false; if ((it = arg.find("jstat")) != arg.end()) jstat = it->second->value(); if ((it = arg.find("fsstat")) != arg.end()) fs_stat = it->second->value(); if ((it = arg.find("blk")) != arg.end()) blk = it->second->value(); if ((it = arg.find("ils")) != arg.end()) ils = it->second->value(); if ((it = arg.find("istat")) != arg.end()) istat_opt = it->second->value(); // stat on file system if (fs_stat) { std::auto_ptr stat(new FsStat); stat->disp(__SB, __vfile); } // inodes list if (!ils.empty()) { std::auto_ptr i_list(new InodesList(__SB, __vfile)); i_list->list(ils, __SB->inodesNumber()); i_list->display(extfs); } // stat on an inode if (!istat_opt.empty()) { std::auto_ptr i_stat(new InodeStat(__SB, extfs)); i_stat->stat(istat_opt); } // stat on the journal (if there is any) if (!jstat.empty()) { std::auto_ptr j_stat(new JournalStat(extfs, __SB, __GD)); j_stat->stat(); } // block list if (!blk.empty()) { std::auto_ptr blk_list(new BlkList(__GD, __SB, __vfile)); blk_list->stat(blk); } } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/OrphansInodes.cpp000066400000000000000000000063461217176075400226030ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include "data_structure/includes/Inode.h" #include "data_structure/includes/Ext4Extents.h" #include "include/OrphansInodes.h" #include "include/ExtfsRawDataNode.h" OrphansInodes::OrphansInodes(TwoThreeTree * parsed_i_list) { __i_list = parsed_i_list; } OrphansInodes::~OrphansInodes() { } void OrphansInodes::load(class Extfs * extfs) { Inode * inode = new Inode(extfs, extfs->SB(), extfs->GD()); uint8_t * tab = (uint8_t *)operator new(extfs->SB()->inodes_struct_size()); inodes_t * inodes_s = (inodes_t *)tab; inode->setInode(inodes_s); for (unsigned int i = extfs->SB()->f_non_r_inodes(); i < extfs->SB()->inodesNumber(); ++i) { if (!__i_list->find(i)) { uint64_t addr; std::ostringstream oss; oss << i; addr = inode->getInodeByNumber(i) + extfs->SB()->offset() - __BOOT_CODE_SIZE; extfs->vfile()->seek(addr); extfs->vfile()->read(tab, extfs->SB()->inodes_struct_size()); inode->init(); if (inode->block_pointers()[0] || inode->simple_indirect_block_pointer() || inode->double_indirect_block_pointer() || inode->triple_indirect_block_pointer()) { uint64_t size = 0; if (inode->flags() & 0x80000) // uses extents { Ext4Extents * ext4 = new Ext4Extents(NULL); try { size = ext4->calc_size(inode); } catch(vfsError & e) { std::cerr << "vfsError caught in OrphansInode::load() : " << e.error << std::endl; return ; } } else for (unsigned int i = 0; i < 12; ++i) if (inode->block_pointers()[i]) size += extfs->SB()->block_size(); if (size) { ExtfsNode * node = NULL; node = new ExtfsNode(oss.str() + std::string("_content"), size, extfs->orphans(), extfs, addr, false, extfs->addBlockPointers); node->set_i_nb(i); } } if (extfs->SB()->inodes_struct_size() > sizeof(inodes_t)) { __inode_reminder_t * i_reminder = (__inode_reminder_t *)((uint8_t*)tab + sizeof(inodes_t)); if (i_reminder->padding) new ExtfsRawDataNode(oss.str(), extfs->SB()->inodes_struct_size(), extfs->orphans(), extfs, addr); else if (inode->unused2() || inode->unused3()) new ExtfsRawDataNode(oss.str(), extfs->SB()->inodes_struct_size(), extfs->orphans(), extfs, addr); else for (unsigned int j = sizeof(__inode_reminder_t) + sizeof(inodes_t); j < extfs->SB()->inodes_struct_size(); ++j) if (tab[j]) { new ExtfsRawDataNode(oss.str(), extfs->SB()->inodes_struct_size(), extfs->orphans(), extfs, addr); break ; } } } } } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/SuperBlockUtils.cpp000066400000000000000000000020651217176075400231130ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/utils/SuperBlockUtils.h" SuperBlockUtils::SuperBlockUtils() { } SuperBlockUtils::~SuperBlockUtils() { } bool SuperBlockUtils::useCompatibleFeatures(uint32_t feature, uint32_t SB_flag) const { return SB_flag & feature; } bool SuperBlockUtils::useRoFeatures(uint32_t feature, uint32_t SB_flag) const { return SB_flag & feature; } bool SuperBlockUtils::useIncompatibleFeatures(uint32_t feature, uint32_t SB_flag) const { return SB_flag & feature; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/SymLink.cpp000066400000000000000000000033051217176075400214050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/SymLink.h" SymLink::SymLink(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD) : Inode(extfs, SB, GD) { __depth = 0; } SymLink::~SymLink() { } std::string SymLink::resolveAbsolutePath(const std::string & target, Node * node) { size_t pos; std::string absolute_path = node->path(); std::string target_name; while ((pos = target.rfind("/")) != std::string::npos) { std::string tmp = target.substr(pos + 1, absolute_path.size() - 1); if (tmp == "..") absolute_path = absolute_path.substr(0, pos); else if (tmp == ".") continue ; else absolute_path += ("/" + tmp); } absolute_path += target; std::cout << "link path : " << absolute_path << std::endl; return absolute_path; } Node * SymLink::find_target(std::string path, Extfs * extfs) { if (__depth >= EXT4_LINK_MAX) return NULL; Node * node = VFS::Get().GetNode(path); if (!node) return NULL; else if (node->isFile()) return node; else if (node->isLink()) { path = resolveAbsolutePath(path, node); __depth++; return find_target(path, extfs); } return NULL; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/000077500000000000000000000000001217176075400223435ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/DirEntry.cpp000066400000000000000000000040661217176075400246150ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include #include "vfile.hpp" #include "includes/DirEntry.h" DirEntry::DirEntry() { _name = NULL; } DirEntry::~DirEntry() { } dir_entry_v2 * DirEntry::getDir() { return _dir; } uint8_t * DirEntry::allocName() { _name = (uint8_t *)operator new ((name_length_v2() + 1) * sizeof(uint8_t)); if (!_name) throw vfsError("DirEntry::allocName() : " "cannot alocate enough memory.\n"); return _name; } void DirEntry::read(uint64_t content_addr, VFile * vfile) { vfile->seek(content_addr); vfile->read(getDir(), sizeof(dir_entry_v2)); allocName(); vfile->read(getName(), name_length_v2()); getName()[name_length_v2()] = '\0'; } uint64_t DirEntry::next() { uint32_t real_size; real_size = sizeof(dir_entry_v2) + this->name_length_v2(); real_size += (4 - (real_size % 4)); return real_size; } uint8_t * DirEntry::getName() { return _name; } uint32_t DirEntry::inode_value() const { return _dir->inode_value; } uint16_t DirEntry::entry_length() const { return _dir->entry_length; } uint8_t DirEntry::name_length_v2() const { return _dir->name_length; } uint16_t DirEntry::name_length_v1() const { return ((dir_entry_v1 *)_dir)->name_length; } uint8_t DirEntry::file_type_v2() const { return _dir->file_type; } void DirEntry::setDir(dir_entry_v2 * dir) { _dir = dir; } void DirEntry::setName(uint8_t * name) { _name = name; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/Ext4Extents.cpp000066400000000000000000000122121217176075400252440ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "../extfs.hpp" #include "node.hpp" #include "includes/Ext4Extents.h" Ext4Extents::Ext4Extents(FileMapping * file_mapping) : __offset(0) { this->__mapping = file_mapping; this->__c_size = 0; } Ext4Extents::~Ext4Extents() { } std::pair Ext4Extents::extents(ext4_extent * extent) { if (!extent) return std::make_pair(0, 0); return std::make_pair(extent->length, concat_uint16_32(extent->phys_blk_high, extent->phys_blk_low)); } uint64_t Ext4Extents::next_level(ext4_extents_index * idx) { if (!idx) return 0; return this->concat_uint16_32(idx->next_level_high, idx->next_level_low); } uint64_t Ext4Extents::concat_uint16_32(uint16_t hi, uint32_t lo) { uint64_t tot = 0; tot = hi; tot <<= 32; tot += lo; return tot; } ext4_extents_header * Ext4Extents::read_header(uint8_t * block) { ext4_extents_header * header = NULL; if (block) header = (ext4_extents_header *)block; if (header->magic != 0xF30A) return NULL; return header; } void Ext4Extents::read_indexes(ext4_extents_header * header, uint8_t * block) { ext4_extents_index * idx; uint64_t addr; uint8_t * current_block; ext4_extents_header * current_header; if (!header) return ; if (header->magic != 0xF30A) return ; for (int i = 0; i < header->entries; ++i) { idx = (ext4_extents_index *)(block + i * sizeof(ext4_extents_index)); addr = concat_uint16_32(idx->next_level_high, idx->next_level_low) * ((uint64_t)__block_size); if (!(current_block = read_block(addr))) return ; current_header = (ext4_extents_header *)current_block; if (current_header->depth) read_indexes(current_header, current_block + sizeof(ext4_extents_header)); else read_extents(current_header, current_block + sizeof(ext4_extents_header)); delete current_block; } } void Ext4Extents::read_extents(ext4_extents_header * header, uint8_t * block) { uint64_t b_size; if (!header) return ; if (header->magic != 0xF30A) return ; for (int i = 0; i < header->entries; ++i) { ext4_extent * extent = (ext4_extent *)(block + i * sizeof(ext4_extent)); std::pair p = extents(extent); b_size = p.first * ((uint64_t)__block_size); if (b_size > __size) b_size = __size; else __size -= b_size; if (__mapping) __mapping->push(__offset, b_size, __node, p.second * ((uint64_t)__block_size) + __inode->SB()->offset() - __BOOT_CODE_SIZE); else __extents_list.push_back(p); __offset += (p.first * ((uint64_t)__block_size)); } } uint8_t * Ext4Extents::read_block(uint64_t addr) { uint8_t * array = NULL; if (!addr) return array; array = (uint8_t *)operator new (__block_size); __extfs->v_seek_read(addr, array, __block_size); return array; } void Ext4Extents::push_extended_blocks(Inode * inode) throw (vfsError) { if (!inode) throw vfsError("Ext4Extents::push_extended_blocks() : inode is NULL."); __inode = inode; __size = inode->lower_size(); __block_size = inode->SB()->block_size(); __node = inode->extfs()->node(); __extfs = inode->extfs(); if (!inode->extent_header()->depth) read_extents(inode->extent_header(), (uint8_t *)&inode->block_pointers()[3]); else read_indexes(inode->extent_header(), (uint8_t *)&inode->block_pointers()[3]); } const std::list > Ext4Extents::extents_list() const { return __extents_list; } uint64_t Ext4Extents::calc_size(Inode * inode) { if (!inode) throw vfsError("Ext4Extents::calc_size() : inode is NULL."); __inode = inode; __size = inode->lower_size(); __block_size = inode->SB()->block_size(); __node = inode->extfs()->node(); __extfs = inode->extfs(); if (!inode->extent_header()) __c_size = 0; else if (!inode->extent_header()->depth) read_extents_x(inode->extent_header(), (uint8_t *)&inode->block_pointers()[3]); else read_indexes(inode->extent_header(), (uint8_t *)&inode->block_pointers()[3]); return __c_size; } void Ext4Extents::read_extents_x(ext4_extents_header * header, uint8_t * block) { if (!header) return ; if (header->magic != 0xF30A) return ; for (int i = 0; i < header->entries; ++i) { ext4_extent * extent = (ext4_extent *)(block + i * sizeof(ext4_extent)); std::pair p = extents(extent); //b_size = p.first * ((uint64_t)__block_size); __extents_list.push_back(p); __c_size += (extent->length * __block_size); __offset += (p.first * ((uint64_t)__block_size)); } } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/ExtendedAttr.cpp000066400000000000000000000074261217176075400254530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "includes/ExtendedAttr.h" ExtendedAttr::ExtendedAttr(uint32_t block, uint32_t block_size) { _block = block; _header = NULL; _xattr_block = (uint8_t *)operator new(block_size * sizeof(uint8_t)); } ExtendedAttr::~ExtendedAttr() { std::map::iterator it; _user.clear(); _posix_acl.clear(); delete _xattr_block; } void ExtendedAttr::init(const Extfs * extfs) { uint64_t addr; if (!extfs || !_block) return ; addr = _block * extfs->SB()->block_size(); extfs->vfile()->seek(addr); extfs->vfile()->read(_xattr_block, extfs->SB()->block_size() * sizeof(uint8_t)); _header = (xattr_header *)_xattr_block; parse(extfs->SB()->block_size()); } void ExtendedAttr::parse(uint32_t block_size) { xattr_name_entries * ent = NULL; uint32_t offset; for (offset = sizeof(xattr_header); offset < (block_size / 2); offset += (sizeof(xattr_name_entries) + ent->name_length)) { ent = (xattr_name_entries *)(_xattr_block + offset); if (ent->attr_type == ExtendedAttr::POSIX_ACL || ent->attr_type == ExtendedAttr::DEFAULT_POSIX_ACL) _posix_acl.insert(std::make_pair(ent, posix_acl(ent))); else if (ent->attr_type == ExtendedAttr::USER_SPACE_ATTR || ent->attr_type == ExtendedAttr::TRUSTED_SPACE_ATTR || ent->attr_type == ExtendedAttr::SECURITY_SPACE_ATTR) { std::pair name_value = std::make_pair(findName(ent, offset), findValue(ent)); _user.insert(std::make_pair(ent, name_value)); } } } std::string ExtendedAttr::findName(const xattr_name_entries * ent, uint32_t offset) { return std::string((char *)(_xattr_block + offset + sizeof(xattr_name_entries)), ent->name_length); } std::string ExtendedAttr::findValue(const xattr_name_entries * ent) { return std::string((char *)(_xattr_block + ent->value_offset), ent->size); } std::list ExtendedAttr::posix_acl(xattr_name_entries * ent) { std::list acl_list; for (unsigned int offset = sizeof(posix_acl_header); offset < ent->size;) { posix_acl_entries * acl = (posix_acl_entries *)(_xattr_block + ent->value_offset + offset); acl_list.push_back(acl); offset += acl_size(acl->type); } return acl_list; } const xattr_header * ExtendedAttr::getHeader() const { return _header; } const std::map > & ExtendedAttr::getUserXAttr() const { return _user; } const std::map > & ExtendedAttr::getPosixACL() const { return _posix_acl; } std::string ExtendedAttr::aclTag(uint16_t tag) { // TODO (void)tag; //to avoid a warning return std::string(""); } std::string ExtendedAttr::aclPermissions(uint16_t permission) { if (permission == ExtendedAttr::EXECUTE) return "x"; else if (permission == ExtendedAttr::WRITE) return "w"; else if (permission == ExtendedAttr::READ) return "r"; return "?"; } uint32_t ExtendedAttr::acl_size(uint16_t flag) { if (flag == ExtendedAttr::USER_INODE || flag == ExtendedAttr::GROUP_INODE || flag == ExtendedAttr::OTHERS) return 2 * sizeof(uint16_t); return sizeof(posix_acl_entries); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/GroupDescriptor.cpp000066400000000000000000000156101217176075400262050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "vfile.hpp" #include "includes/GroupDescriptor.h" GroupDescriptor::GroupDescriptor(SuperBlock * SB, uint32_t block_size) { __bg_checksum = SB->ro_features_flags() & SuperBlockStructure::_GD_CSUM; _SB_offset = SB->offset(); this->__64_bits_field = (SB->getSuperBlock()->s_desc_size <= 32 ? true : false); if (block_size == __BOOT_CODE_SIZE) _block_addr = __BOOT_CODE_SIZE * 2; else _block_addr = block_size; _block_addr += (SB->offset() - __BOOT_CODE_SIZE); __FS_ID = SB->file_system_ID(); __SB = SB; } GroupDescriptor::~GroupDescriptor() { } uint64_t GroupDescriptor::groupDescriptorAddr() const { return _block_addr; } void GroupDescriptor::init(uint32_t block_size, VFile * vfile, uint32_t gr_number) { uint64_t gd_addr = groupDescriptorAddr(); uint32_t coeff; if (__64_bits_field) coeff = 64 * gr_number; else coeff = 32 * gr_number; _gr_descr = (group_descr_table_t * )operator new(coeff); _gr_descr_64 = (group_descr_table_64_t *)_gr_descr; _gr_descr_array = (uint8_t *)_gr_descr; vfile->seek(gd_addr); vfile->read((void *)_gr_descr_array, coeff); if (__bg_checksum) for (unsigned int i = 0; i < gr_number; ++i) { uint16_t crc; crc = crc16(~0, __FS_ID, 16); crc = crc16(crc, (uint8_t *)&i, sizeof(uint32_t)); crc = crc16(crc, (uint8_t *)getGroupTable(i), sizeof(group_descr_table_t) - 2); if (crc != checksum(i)) std::cerr << "Group " << i << " : bad checksum = " << checksum(i) << "; should be " << crc << std::endl; } else std::cout << "No group descriptor checksum." << std::endl; if (false == true) { __check_inode_nb(gr_number, block_size, vfile); __check_blk_nb(gr_number, block_size, vfile); } } void GroupDescriptor::__check_inode_nb(uint32_t gr_number, uint32_t block_size, VFile * vfile) { uint8_t * tab = (uint8_t *)operator new(block_size); uint64_t tot = 0; for (unsigned int i = 0; i < gr_number; ++i) { uint64_t addr; uint8_t byte; uint64_t count = 0; addr = inode_bitmap_addr(i) * block_size; vfile->seek(addr + _SB_offset - __BOOT_CODE_SIZE); vfile->read(tab, block_size); if (unused_inodes_low(i) != __SB->inodes_in_group_number()) { for (unsigned int j = 0; j < (__SB->inodes_in_group_number() / 8); ++j) { byte = tab[j]; for (unsigned int k = 0; k < 8; ++k) if (!((byte >> k) & 1)) count++; } tot += count; } else { tot += unused_inodes_low(i); continue ; } if (count != unallocated_inodes_nbr(i)) std::cerr << "Group " << i << " : free inodes number mismatch. " << unallocated_inodes_nbr(i) << ", counted " << count << std::endl; } if (tot != __SB->u_inodes_number()) std::cerr << std::endl << " ******* Total free inodes number mismatch : " << __SB->u_inodes_number() << ", counted " << tot << " *******" << std::endl; else std::cout << "Free inodes count seem to be correct." << std::endl; delete tab; } void GroupDescriptor::__check_blk_nb(uint32_t gr_number, uint32_t block_size, VFile * vfile) { uint8_t * tab = (uint8_t *)operator new(block_size); uint64_t tot = 0; for (unsigned int i = 0; i < gr_number; ++i) { uint64_t addr; uint8_t byte; uint64_t count = 0; addr = block_bitmap_addr(i) * block_size; vfile->seek(addr + _SB_offset - __BOOT_CODE_SIZE); vfile->read(tab, block_size); for (unsigned int j = 0; j < __SB->block_in_groups_number() / 8; ++j) { byte = tab[j]; for (unsigned int k = 0; k < 8; ++k) if (!((byte >> k) & 1)) count++; } tot += count; if (count != unallocated_block_nbr(i)) std::cerr << "Group " << i << " : free blocks number mismatch. " << unallocated_block_nbr(i) << ", counted " << count << std::endl; } if (tot != __SB->u_blocks_number()) std::cerr << std::endl << " ******* Total free blocks number mismatch : " << __SB->u_blocks_number() << ", counted " << tot << " *******" << std::endl; else std::cout << "Free blocks count seem to be correct." << std::endl; delete tab; } uint16_t GroupDescriptor::crc16(uint16_t crc, uint8_t const * buf, size_t len) { while (len--) crc = crc16_byte(crc, *buf++); return crc; } uint16_t GroupDescriptor::crc16_byte(uint16_t crc, const uint8_t data) { return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; } const group_descr_table_t * GroupDescriptor::getGroupTable() const { return _gr_descr; } const group_descr_table_t * GroupDescriptor::getGroupTable(uint32_t group) const { if (!this->__64_bits_field) return (group_descr_table_t *)&_gr_descr_64[group]; return &_gr_descr[group]; } uint32_t GroupDescriptor::block_bitmap_addr(uint32_t group) const { if (!this->__64_bits_field) return _gr_descr_64[group].block_bitmap_addr; return _gr_descr[group].block_bitmap_addr; } uint32_t GroupDescriptor::inode_bitmap_addr(uint32_t group) const { if (!this->__64_bits_field) return _gr_descr_64[group].inode_bitmap_addr; return _gr_descr[group].inode_bitmap_addr; } uint32_t GroupDescriptor::inode_table_block_addr(uint32_t group) const { if (!this->__64_bits_field) return _gr_descr_64[group].inode_table_block_addr; return _gr_descr[group].inode_table_block_addr; } uint16_t GroupDescriptor::unallocated_block_nbr(uint32_t group) const { if (!this->__64_bits_field) return _gr_descr_64[group].unallocated_block_nbr; return _gr_descr[group].unallocated_block_nbr; } uint16_t GroupDescriptor::unallocated_inodes_nbr(uint32_t group) const { if (!this->__64_bits_field) return _gr_descr_64[group].unallocated_inodes_nbr; return _gr_descr[group].unallocated_inodes_nbr; } uint16_t GroupDescriptor::dir_nbr(uint32_t group) const { if (!this->__64_bits_field) return _gr_descr_64[group].dir_nbr; return _gr_descr[group].dir_nbr; } uint16_t GroupDescriptor::GD_size() const { if (__64_bits_field) return 32; return 64; } uint16_t GroupDescriptor::checksum(uint32_t group) const { if (this->__64_bits_field) return _gr_descr[group].bg_checksum; return _gr_descr_64[group].bg_checksum; } uint16_t GroupDescriptor::unused_inodes_low(uint32_t group) const { if (this->__64_bits_field) return _gr_descr[group].bg_itable_unused_lo; return _gr_descr_64[group].bg_itable_unused_lo; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/Inode.cpp000066400000000000000000000201351217176075400241060ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "includes/Inode.h" #include "includes/GroupDescriptor.h" #include "includes/Ext4Extents.h" #include "../include/Directory.h" #include "../extfs.hpp" #include "../include/utils/InodeUtils.h" #include "../include/ExtfsRawDataNode.h" Inode::Inode(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD) : InodeUtils(SB, GD) { _extfs = extfs; __extents = false; _current_block = 0; _extent_nb = 0; _blk_nb = 0; _cur_extent_blk = 0; _head = NULL; for (int i = 0; i < 4; ++i) _blk_nb_l[i] = 0; __s_i_blk = __d_i_blk = __t_i_blk = 0; __inode_addr = 0; __inode_nb = 0; } Inode::Inode(const Inode * inode) : InodeUtils(inode->SB(), inode->GD()), _extfs(NULL) { __extents = false; if (inode) _extfs = inode->extfs(); _current_block = 0; _extent_nb = 0; _blk_nb = 0; _cur_extent_blk = 0; _head = NULL; for (int i = 0; i < 4; ++i) _blk_nb_l[i] = 0; __s_i_blk = __d_i_blk = __t_i_blk = 0; __inode_addr = 0; __inode_nb = 0; } Inode::~Inode() { } void Inode::read(uint64_t addr) { _extfs->v_seek_read(addr, (void *)InodeArray(), sizeof(inodes_t)); __inode_addr = addr + _SB->offset() - __BOOT_CODE_SIZE; } void Inode::read(uint64_t addr, inodes_t * inode) { _extfs->v_seek_read(addr, (void *)inode, sizeof(inodes_t)); __inode_addr = addr + _SB->offset() - __BOOT_CODE_SIZE; } void Inode::setInodeNb(uint32_t inode_nb) { __inode_nb = inode_nb; } uint32_t Inode::singleIndirectBlockContentAddr(uint32_t block_number) { uint64_t addr; uint32_t blocks; block_number -= 12; addr = ((uint64_t)simple_indirect_block_pointer()) * _SB->block_size(); if (!addr) return 0; addr += (block_number * 4); _extfs->v_seek_read(addr, (void *)&blocks, sizeof(uint32_t)); return blocks; } uint32_t Inode::doubleIndirectBlockContentAddr(uint32_t block_number) { uint64_t tmp = 0; uint64_t size = _SB->block_size() / sizeof(uint32_t); uint64_t addr = ((uint64_t)double_indirect_block_pointer()) * _SB->block_size(); uint32_t tmp_block_nb = block_number - 12 - size; uint32_t sub_block = tmp_block_nb / size; if (!addr) return 0; addr += (sub_block * sizeof(uint32_t)); _extfs->v_seek_read(addr, &tmp, 4); if (!tmp) { _current_block += ((_SB->block_size() / sizeof(uint32_t))); return 0; } tmp *= ((uint64_t)_SB->block_size()); sub_block = tmp_block_nb % size; tmp += (sub_block * sizeof(uint32_t)); _extfs->v_seek_read(tmp, &addr, 4); if (!addr) _current_block++; return addr; } uint32_t Inode::tripleIndirectBlockContentAddr(uint32_t block_number) { uint64_t tmp = 0, size = _SB->block_size() / sizeof(uint32_t); uint64_t addr = ((uint64_t)double_indirect_block_pointer()) * _SB->block_size(); if (!addr) return 0; uint32_t tmp_block_nb = block_number - 12 - size * size; uint32_t sub_block = tmp_block_nb / (size * size); addr += (sub_block * sizeof(uint32_t)); _extfs->v_seek_read(addr, &tmp, 4); if (!tmp) return 0; tmp *= ((uint64_t)_SB->block_size()); tmp += (sub_block / size); _extfs->v_seek_read(tmp, &addr, sizeof(uint32_t)); addr *= _SB->block_size(); addr += (sub_block % size); _extfs->v_seek_read(tmp, &addr, 4); return addr; } uint32_t Inode::nextBlock() { uint64_t addr; if (flags() & 0x80000) // uses extents { if (!_head) init(); if (_head->depth) addr = go_to_extent_blk(); else if (_current_block > _blk_nb) addr = 0; else addr = null_extent_depth(_current_block); } else addr = goToBlock(_current_block); ++_current_block; return addr; } void Inode::init() { if (flags() & 0x80000) // uses extents { // initialisation of extents _head = (ext4_extents_header *)&block_pointers()[0]; if (_head->magic == 0xF30A) for (int i = 0; (i < 4) && (i < _head->max_entries); ++i) { // one extent occupies 3 block pointers (12 bytes) ext4_extent * extent = (ext4_extent *)&block_pointers()[3 + (i * 3)]; _blk_nb_l[i] = extent->length; _blk_nb += extent->length; } } } uint32_t Inode::goToBlock(uint32_t block_number) { uint32_t tmp = _SB->block_size() / 4; _current_block = block_number; if (flags() & 0x80000) // uses extents { if (!_head) init(); if (_head->depth) return go_to_extent_blk(); if (_current_block > _blk_nb) return 0; return null_extent_depth(block_number); } if (block_number < 12) return block_pointers()[block_number]; else if ((block_number - 12) < tmp) return singleIndirectBlockContentAddr(block_number); else if ((block_number - 12 - tmp) < (tmp * tmp)) return doubleIndirectBlockContentAddr(block_number); else if ((block_number - 12 - tmp - tmp * tmp) < (tmp * tmp * tmp)) return tripleIndirectBlockContentAddr(block_number); return 0; } uint32_t Inode::browseBlock(uint32_t begin, uint32_t end) { static bool flag = true; uint64_t addr = 0; if (flag) { _current_block = begin; flag = false; } if (!end || (_current_block <= end)) { addr = nextBlock(); if (!addr) flag = true; else return addr; } return 0; } uint32_t Inode::currentBlock() { return _current_block; } Extfs * Inode::extfs() const { return _extfs; } ext4_extents_header * Inode::extent_header() const { return _head; } uint64_t Inode::null_extent_depth(uint32_t block_number) { uint32_t tot = 0, i; for (i = 0; tot <= block_number; ++i) tot += _blk_nb_l[i]; _extent_nb = i - 1; if (_extent_nb >= 4) return 0; _cur_extent_blk = block_number; for (int j = 0; j < _extent_nb; ++j) { block_number -= _blk_nb_l[j]; _cur_extent_blk = block_number; } ext4_extent * extent = (ext4_extent *)&block_pointers()[3 + (_extent_nb * 3)]; if (_cur_extent_blk >= extent->length) { _extent_nb++; _cur_extent_blk = 0; if ((_extent_nb >= _head->entries) || (_extent_nb >= 4)) { _extent_nb = 0; return 0; } extent = (ext4_extent *)&block_pointers()[3 + (_extent_nb * 3)]; } return extent->phys_blk_low + _cur_extent_blk; } uint64_t Inode::go_to_extent_blk() { uint64_t t; uint16_t length; uint64_t blk_nb; if (!__extents) __extents = init_extents(); length = __extents_list.front().first; blk_nb = __extents_list.front().second; if (__offset_in_extent >= length) { __extents_list.pop_front(); if (__extents_list.empty()) return 0; blk_nb = __extents_list.front().second; __offset_in_extent = 0; } t = __offset_in_extent + blk_nb; __offset_in_extent++; return t; } bool Inode::init_extents() { Ext4Extents * ext = new Ext4Extents(NULL); ext->push_extended_blocks(this); __extents_list = ext->extents_list(); __offset_in_extent = 0; delete ext; return true; } uint32_t Inode::s_i_blk() const { return __s_i_blk; } uint32_t Inode::d_i_blk() const { return __d_i_blk; } uint32_t Inode::t_i_blk() const { return __t_i_blk; } bool Inode::is_fucked_up() const { if (!__inode) return false; if (this->unused2() || this->unused3()) return true; if (_SB->inodes_struct_size() > sizeof(inodes_t)) { __inode_reminder_t * i_reminder; uint8_t * tab = (uint8_t *)operator new(_SB->inodes_struct_size() - sizeof(inodes_t)); i_reminder = (__inode_reminder_t *)tab; _extfs->vfile()->read(tab, _SB->inodes_struct_size() - sizeof(inodes_t)); if (i_reminder->padding) return true; else for (unsigned int j = sizeof(__inode_reminder_t); j < _SB->inodes_struct_size() - sizeof(inodes_t); ++j) if (tab[j]) return true; } return false; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/InodeAccessors.cpp000066400000000000000000000051631217176075400257600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "includes/Inode.h" void Inode::setVFile(VFile * vfile) { _vfile = vfile; } const inodes_t* Inode::getInode() const { return &_inode; } uint16 Inode::file_mode() const { return _inode.file_mode; } uint16 Inode::lower_uid() const { return _inode.lower_uid; } uint32 Inode::lower_size() const { return _inode.lower_size; } uint32 Inode::access_time() const { return _inode.access_time; } uint32 Inode::change_time() const { return _inode.change_time; } uint32 Inode::modif_time() const { return _inode.modif_time; } uint32 Inode::delete_time() const { return _inode.delete_time; } uint16 Inode::lower_gid() const { return _inode.lower_gid; } uint16 Inode::link_coun() const { return _inode.sector_count; } uint32 Inode::sector_count() const { return _inode.sector_count; } uint32 Inode::flags() const { return _inode.flags; } uint32 Inode::unused1() const { return _inode.unused1; } const uint32* Inode::block_pointers() const { return _inode.block_pointers; } uint32 Inode::simple_indirect_block_pointer() const { return _inode.simple_indirect_block_pointer; } uint32 Inode::double_indirect_block_pointer() const { return _inode.double_indirect_block_pointer; } uint32 Inode::triple_indirect_block_pointer() const { return _inode.triple_indirect_block_pointer; } uint32 Inode::generation_number_nfs() const { return _inode.generation_number_nfs; } uint32 Inode::file_acl_ext_attr() const { return _inode.file_acl_ext_attr; } uint32 Inode::upper_size_dir_acl() const { return _inode.upper_size_dir_acl; } uint32 Inode::fragment_addr() const { return _inode.fragment_addr; } uchar Inode::fragment_index() const { return _inode.fragment_index; } uchar Inode::fragment_size() const { return _inode.fragment_size; } uint16 Inode::unused2() const { return _inode.unused2; } uint16 Inode::upper_uid() const { return _inode.upper_uid; } uint16 Inode::upper_gid() const { return _inode.upper_gid; } uint32 Inode::unused3() const { return _inode.unused3; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/InodeStructure.cpp000066400000000000000000000076221217176075400260350ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/utils/InodeStructure.h" InodeStructure::InodeStructure() { this->__inode = NULL; this->__inode_array = NULL; } InodeStructure::~InodeStructure() { } const inodes_t * InodeStructure::inode() const { return this->__inode; } const uint8_t * InodeStructure::InodeArray() const { return !this->__inode_array ? NULL : this->__inode_array; } void InodeStructure::setInode(const inodes_t * inode) { this->__inode = inode; } uint16_t InodeStructure::file_mode() const { return !this->__inode ? 0 : this->__inode->file_mode; } uint16_t InodeStructure::lower_uid() const { return !this->__inode ? 0 : this->__inode->lower_uid; } uint32_t InodeStructure::lower_size() const { return !this->__inode ? 0 : this->__inode->lower_size; } uint32_t InodeStructure::access_time() const { return !this->__inode ? 0 : this->__inode->access_time; } uint32_t InodeStructure::change_time() const { return !this->__inode ? 0 : this->__inode->change_time; } uint32_t InodeStructure::modif_time() const { return !this->__inode ? 0 : this->__inode->modif_time; } uint32_t InodeStructure::delete_time() const { return !this->__inode ? 0 : this->__inode->delete_time; } uint16_t InodeStructure::lower_gid() const { return !this->__inode ? 0 : this->__inode->lower_gid; } uint16_t InodeStructure::link_coun() const { return !this->__inode ? 0 : this->__inode->link_count; } uint32_t InodeStructure::sector_count() const { return !this->__inode ? 0 : this->__inode->sector_count; } uint32_t InodeStructure::flags() const { return !this->__inode ? 0 : this->__inode->flags; } uint32_t InodeStructure::unused1() const { return !this->__inode ? 0 : this->__inode->unused1; } const uint32_t* InodeStructure::block_pointers() const { return !this->__inode ? NULL : this->__inode->block_pointers; } uint32_t InodeStructure::simple_indirect_block_pointer() const { return !this->__inode ? 0 : this->__inode->simple_indirect_block_pointer; } uint32_t InodeStructure::double_indirect_block_pointer() const { return !this->__inode ? 0 : this->__inode->double_indirect_block_pointer; } uint32_t InodeStructure::triple_indirect_block_pointer() const { return !this->__inode ? 0 : this->__inode->triple_indirect_block_pointer; } uint32_t InodeStructure::generation_number_nfs() const { return !this->__inode ? 0 : this->__inode->generation_number_nfs; } uint32_t InodeStructure::file_acl_ext_attr() const { return !this->__inode ? 0 : this->__inode->file_acl_ext_attr; } uint32_t InodeStructure::upper_size_dir_acl() const { return !this->__inode ? 0 : this->__inode->upper_size_dir_acl; } uint32_t InodeStructure::fragment_addr() const { return !this->__inode ? 0 : this->__inode->fragment_addr; } uint8_t InodeStructure::fragment_index() const { return !this->__inode ? 0 : this->__inode->fragment_index; } uint8_t InodeStructure::fragment_size() const { return !this->__inode ? 0 : this->__inode->fragment_size; } uint16_t InodeStructure::unused2() const { return !this->__inode ? 0 : this->__inode->unused2; } uint16_t InodeStructure::upper_uid() const { return !this->__inode ? 0 : this->__inode->upper_uid; } uint16_t InodeStructure::upper_gid() const { return !this->__inode ? 0 : this->__inode->upper_gid; } uint32_t InodeStructure::unused3() const { return !this->__inode ? 0 : this->__inode->unused3; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/SuperBlock.cpp000066400000000000000000000121351217176075400251220ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include "includes/SuperBlock.h" #include "../extfs.hpp" SuperBlock::SuperBlock() : SuperBlockStructure() { _offset = __BOOT_CODE_SIZE; } SuperBlock::~SuperBlock() { } void SuperBlock::init(VFile * vfile, bool sb_check, uint64_t sb_force_addr) { //seek and read boot code : 1024 bytes read(vfile, __BOOT_CODE_SIZE); if (sb_force_addr != 1024) force_addr(vfile, sb_force_addr); // check the super block validity if (!sanity_check() || sb_check) { if (sb_check) { std::cerr << "The superblock signature doesn't match 0x53ef. " "Trying to locate a backup..." << std::endl; if (!(sigfind(vfile))) throw vfsError("Error while reading Extfs superblock : " "Could not verify the validity or find valid backups.\n"); else { most_recent_backup(vfile); file_system_sanity(); } } else throw vfsError("Error while reading extfs superblock. Exiting."); } } void SuperBlock::force_addr(VFile * vfile, uint64_t addr) { _offset = addr; /* seek and read to the super block at _offset, or throw if an exception is caught */ try { vfile->seek(_offset); vfile->read((void *)getSuperBlock(), __BOOT_CODE_SIZE); } catch(vfsError & e) { throw ; } } bool SuperBlock::sanity_check() const { if (signature() != __SB_SIG) return false; if (!block_size()) return false; if (creator_os() != _OS_FREE_BSD && creator_os() != _OS_GNU_HURD && creator_os() != _OS_LINUX && creator_os() != _OS_LITES && creator_os() != _OS_MASIX) return false; if (u_inodes_number() > inodesNumber() || inodes_in_group_number() > inodesNumber()) return false; return true; } bool SuperBlock::sigfind(VFile * vfile) { bool possible_sb_found = false; uint64_t previous_hit = 0; std::vector * offset_list; char noodle[2]; noodle[0] = 0x53; noodle[1] = 0xEF; _offset = 0; //offset of signature in the superblock offset_list = vfile->search(noodle, 2, '\0'); if (offset_list->empty()) { delete offset_list; return possible_sb_found; } std::vector::iterator it = offset_list->begin(), end = offset_list->end(); while (it != end) { _offset = *it; vfile->seek(_offset - 56); vfile->read((void *)getSuperBlock(), __BOOT_CODE_SIZE); std::cout << "Hit : " << (_offset) / 1024 << "\tPrevious : " << previous_hit / 1024 << " (" << (_offset - previous_hit) / 1024 << ")"; if (sanity_check()) { possible_sb_found = true; _backup_list.insert(std::make_pair(_offset, last_written_time())); std::cout << "\t -> Possibly valid." << std::endl; } else std::cout << "\t -> Invalid." << std::endl; previous_hit = _offset; _offset -= sizeof(super_block_t_); it++; } delete offset_list; return possible_sb_found; } uint64_t SuperBlock::most_recent_backup(VFile * vfile) throw(vfsError) { uint64_t offset = 0; uint32_t prev_date = 0; if (_backup_list.empty()) throw vfsError("SuperBlock::most_recent_backup() : " "the backup list is empty.\n"); std::map::iterator it = _backup_list.begin(), it_end = _backup_list.end(); for (; it != it_end; it++) if ((*it).second > prev_date) { prev_date = (*it).second; offset = (*it).first; } std::cout << "The most recent superblock backup has been located at offset " << offset << "." << std::endl; _offset = offset - 56; return read(vfile, _offset); } void SuperBlock::file_system_sanity() { // if we are in group 0, this is not a backup, no need to check anything. if (!current_block_group()) return ; // otherwise, this is a backup and we need to verify some data consistency. if ((current_block_group() * block_in_groups_number()) != (_offset / block_size())) std::cout << "WARNING : the file system doesn't seem to be valid." << std::endl << "\t -> Are you sure you are analyzing an EXT file system?" << std::endl; else std::cout << "The file system seems to be valid." << std::endl; return ; } uint32_t SuperBlock::read(VFile * vfile, uint64_t offset) { vfile->seek(offset); return vfile->read(getSuperBlock(), sizeof(super_block_t_)); } uint32_t SuperBlock::group_number() const { uint32_t gr_nb = blocks_number() / block_in_groups_number(); if (blocks_number() % block_in_groups_number()) ++gr_nb; return gr_nb; } uint64_t SuperBlock::offset() const { return _offset; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/SuperBlockStructure.cpp000066400000000000000000000127201217176075400270430ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "includes/SuperBlock.h" SuperBlockStructure::SuperBlockStructure() { try { this->__sb_array = (uint8_t *)operator new(SUPER_BLOCK_SIZE); } catch(std::exception) { throw ; } this->_super_block = (super_block_t_ *)this->__sb_array; } SuperBlockStructure::~SuperBlockStructure() { delete _super_block; } super_block_t_ * SuperBlockStructure::getSuperBlock() const { return _super_block; } uint32_t SuperBlockStructure::inodesNumber() const { return _super_block->inodes_number; } uint32_t SuperBlockStructure::blocks_number() const { return _super_block->blocks_number; } uint32_t SuperBlockStructure::r_blocks_number() const { return _super_block->r_blocks_number; } uint32_t SuperBlockStructure::u_blocks_number() const { return _super_block->u_blocks_number; } uint32_t SuperBlockStructure::u_inodes_number() const { return _super_block->u_inodes_number; } uint32_t SuperBlockStructure::first_block() const { return _super_block->first_block; } uint32_t SuperBlockStructure::block_size() const { uint32_t blk_size; blk_size = 1024 << _super_block->block_size; if ((blk_size > MAX_BLK_SIZE) || (blk_size < 1024)) throw vfsError("SuperBlockStructure::block_size() : invalid block size"); return blk_size; } uint32_t SuperBlockStructure::fragment_size() const { return 1024 << _super_block->fragment_size; } uint32_t SuperBlockStructure::block_in_groups_number() const { return _super_block->block_in_groups_number; } uint32_t SuperBlockStructure::fragment_in_group_number() const { return _super_block->fragment_in_group_number; } uint32_t SuperBlockStructure::inodes_in_group_number() const { return _super_block->inodes_in_group_number; } uint32_t SuperBlockStructure::last_mount_time() const { return _super_block->last_mount_time; } uint32_t SuperBlockStructure::last_written_time() const { return _super_block->last_written_time; } uint16_t SuperBlockStructure::current_mount_count() const { return _super_block->current_mount_count; } uint16_t SuperBlockStructure::max_mount_count() const { return _super_block->max_mount_count; } uint16_t SuperBlockStructure::signature() const // must be 0xef53 { return _super_block->signature; } uint16_t SuperBlockStructure::fs_state() const { return _super_block->fs_state; } uint16_t SuperBlockStructure::error_handling_method() const { return _super_block->error_handling_method; } uint16_t SuperBlockStructure::minor_version() const { return _super_block->minor_version; } uint32_t SuperBlockStructure::l_consistency_ct() const { return _super_block->l_consistency_ct; } uint32_t SuperBlockStructure::consitency_forced_interval() const { return _super_block->consitency_forced_interval; } uint32_t SuperBlockStructure::creator_os() const { return _super_block->creator_os; } uint32_t SuperBlockStructure::major_version() const { return _super_block->major_version; } uint16_t SuperBlockStructure::uid_reserved_block() const { return _super_block->uid_reserved_block; } uint16_t SuperBlockStructure::gid_reserved_block() const { return _super_block->gid_reserved_block; } uint32_t SuperBlockStructure::f_non_r_inodes() const { return _super_block->f_non_r_inodes; } uint16_t SuperBlockStructure::inodes_struct_size() const { return _super_block->inodes_struct_size; } uint16_t SuperBlockStructure::current_block_group() const { return _super_block->current_block_group; } uint32_t SuperBlockStructure::compatible_feature_flags() const { return _super_block->compatible_feature_flags; } uint32_t SuperBlockStructure::incompatible_feature_flags() const { return _super_block->incompatible_feature_flags; } uint32_t SuperBlockStructure::ro_features_flags() const { return _super_block->ro_features_flags; } const uint8_t* SuperBlockStructure::file_system_ID() const { return _super_block->file_system_ID; } const uint8_t* SuperBlockStructure::volume_name() const { return _super_block->volume_name; } const uint8_t* SuperBlockStructure::path_last_mount() const { return _super_block->path_last_mount; } uint32_t SuperBlockStructure::algorithm_bitmap() const { return _super_block->algorithm_bitmap; } uint8_t SuperBlockStructure::preallocate_blocks_files() const { return _super_block->preallocate_blocks_files; } uint8_t SuperBlockStructure::preallocate_block_dir() const { return _super_block->preallocate_block_dir; } uint16_t SuperBlockStructure::unused() const { return _super_block->unused; } const uint8_t* SuperBlockStructure::journal_id() const { return _super_block->journal_id; } uint32_t SuperBlockStructure::journal_inode() const { return _super_block->journal_inode; } uint32_t SuperBlockStructure::journal_device() const { return _super_block->journal_device; } uint32_t SuperBlockStructure::orphan_node_list() const { return _super_block->orphan_node_list; } const uint32_t* SuperBlockStructure::empty() const { return _super_block->s_reserved; } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/000077500000000000000000000000001217176075400251005ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/directory_entry.h000066400000000000000000000020701217176075400304750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __DIRECTORY_ENTRY_H__ #define __DIRECTORY_ENTRY_H__ //#include "types.h" #ifdef WIN32 #define PACK #else #define PACK __attribute__ ((packed)) #endif #ifdef WIN32 #pragma pack(1) #endif typedef struct __directory_entry_original_s { uint32 inode_value; uint16 entry_length; uint16 name_length; }PACK dir_entry_v1; typedef struct __directory_entry_2nd_version_s { uint32 inode_value; uint16 entry_length; uchar name_length; uchar file_type; }PACK dir_entry_v2; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/ext_attr_header.h000066400000000000000000000014741217176075400304210ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXT_ATTR_HEADER_H__ #define __EXT_ATTR_HEADER_H__ typedef struct __ext_attr_header_s { uint32 signature; //0xEA020000 uint32 reference_count; uint32 blocks_number; uint32 hash; uint32 reserved[4]; } ext_attr_header; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/extended_attr_name_entries.h000066400000000000000000000017671217176075400326470ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXT_ATTR_NAME_ENTRIES_H__ #define __EXT_ATTR_NAME_ENTRIES_H__ enum type { USER_SPACE_ATTR = 1, POSIX_ACL = 2, DEFAULT_POSIX_ACL = 3, TRUSTED_SPACE_ATTR = 4, LUSTRE = 5, SECURITY_SPACE_ATTR = 6 }; typedef struct __ext_attr_name_entries_s { uchar name_length; uchar attr_type; uint16 value_offset; uint32 block_location; uint32 size; uint32 hash; } ext_attr_name_entries; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/extfs_super_block.hpp000066400000000000000000000041001217176075400313250ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXTFS_SUPER_BLOCK_HPP__ #define __EXTFS_SUPER_BLOCK_HPP__ #include "types.h" #ifdef WIN32 #define PACK #else #define PACK __attribute__ ((packed)) #endif #ifdef WIN32 #pragma pack(1) #endif typedef struct __extfs_super_block_s { uint32 inodes_number; // number of inodes on the fs; uint32 blocks_number; // number of blocks on the fs; uint32 r_blocks_number; uint32 u_blocks_number; uint32 u_inodes_number; uint32 first_block; uint32 block_size; uint32 fragment_size; uint32 block_in_groups_number; uint32 fragment_in_group_number; uint32 inodes_in_group_number; uint32 last_mount_time; uint32 last_written_time; uint16 current_mount_count; uint16 max_mount_count; uint16 signature; // must be 0xef53 uint16 fs_state; uint16 error_handling_method; uint16 minor_version; uint32 l_consistency_ct; uint32 consitency_forced_interval; uint32 creator_os; uint32 major_version; uint16 uid_reserved_block; uint16 gid_reserved_block; uint32 f_non_r_inodes; uint16 inodes_struct_size; uint16 current_block_group; uint32 compatible_feature_flags; uint32 incompatible_feature_flags; uint32 ro_features_flags; uchar file_system_ID[16]; uchar volume_name[16]; uchar path_last_mount[64]; uint32 algorithm_bitmap; uchar preallocate_blocks_files; uchar preallocate_block_dir; uint16 unused; uchar journal_id[16]; uint32 journal_inode; uint32 journal_device; uint32 orphan_node_list; uint32 empty[197]; }PACK super_block_t_; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/first_block.h000066400000000000000000000012721217176075400275540ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifdef __FIRST_BLOCK_H__ #define __FIRST_BLOCK_H__ typedef struct first_block { uint32 *boot_code; } #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/group_descr_table.h000066400000000000000000000020071217176075400307330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __GROUP_DESCR_TABLE_H__ #define __GROUP_DESCR_TABLE_H__ #ifdef WIN32 #define PACK #else #define PACK __attribute__ ((packed)) #endif #ifdef WIN32 #pragma pack(1) #endif typedef struct __group_descr_table_s { uint32 block_bitmap_addr; uint32 inode_bitmap_addr; uint32 inode_table_block_addr; uint16 unallocated_block_nbr; uint16 unallocated_inodes_nbr; uint16 dir_nbr; uchar unused[14]; }PACK group_descr_table_t; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/hash_tree.h000066400000000000000000000020571217176075400272170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __HASH_TREE_HH__ #define __HASH_TREE_HH__ typedef struct __hash_tree_node_descriptor_header_s { uint32 unused; uchar hash_version; uchar length; uchar level_leaves; uchar unused2; } hash_tree_header; typedef struct __hash_tree_node_descriptor_entries_s { uint32 min_hash_value; uint32 block_addr; } hash_node_descriptor; typedef struct __first_node_descriptor_entry { uint16 max_nbr; uint16 current_nbr; uint32 block_addr; } first_node_entry; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/inodes.h000066400000000000000000000050731217176075400265370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __INODES__H__ #define __INODES__H__ #ifdef WIN32 #define PACK #else #define PACK __attribute__ ((packed)) #endif #ifdef WIN32 #pragma pack(1) #endif /* permissions bits: */ #define _ISUID 0x0004000 #define _ISGID 0x0002000 #define _ISSTI 0x0001000 /* access rights */ #define _IRUSR 00400 #define _IWUSR 00200 #define _IXUSR 00100 #define _IRGRP 00040 #define _IWGRP 00020 #define _IXGRP 00010 #define _IROTH 00004 #define _IWOTH 00002 #define _IXOTH 00001 /* Encoding of the file mode. */ #define __IFMT 0170000 /* These bits determine file type. */ /* File types. */ #define __IFIFO 0010000 /* FIFO. */ #define __IFCHR 0020000 /* Character device. */ #define __IFDIR 0040000 /* Directory. */ #define __IFBLK 0060000 /* Block device. */ #define __IFREG 0100000 /* Regular file. */ #define __IFLNK 0120000 /* Symbolic link. */ #define __IFSOCK 0140000 /* Socket. */ #define _ISTYPE(mode, mask) (((mode) & __IFMT) == (mask)) #define _ISDIR(mode) __ISTYPE((mode), __IFDIR) #define _ISCHR(mode) __ISTYPE((mode), __IFCHR) #define _ISBLK(mode) __ISTYPE((mode), __IFBLK) #define _ISREG(mode) __ISTYPE((mode), __IFREG) #define _ISFIFO(mode) __ISTYPE((mode), __IFIFO) #define _ISLNK(mode) __ISTYPE((mode), __IFLNK) #define _ISSOCK(mode) __ISTYPE((mode), __IFSOCK) typedef struct inodes_s { uint16 file_mode; uint16 lower_uid; uint32 lower_size; uint32 access_time; uint32 change_time; uint32 modif_time; uint32 delete_time; uint16 lower_gid; uint16 link_count; uint32 sector_count; uint32 flags; uint32 unused1; uint32 block_pointers[12]; uint32 simple_indirect_block_pointer; uint32 double_indirect_block_pointer; uint32 triple_indirect_block_pointer; uint32 generation_number_nfs; uint32 file_acl_ext_attr; uint32 upper_size_dir_acl; uint32 fragment_addr; uchar fragment_index; uchar fragment_size; uint16 unused2; uint16 upper_uid; uint16 upper_gid; uint32 unused3; }PACK inodes_t; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/journal.h000066400000000000000000000044701217176075400267300ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __JOURNAL_H__ #define __JOURNAL_H__ typedef struct __journal_standard_header { uint32 signature; //0xC03B33998 uint32 block_type; uint32 sequence_number; } journal_header; typedef struct __journal_superblock_v1 { journal_header header; uint32 block_size; uint32 blocks_number; uint32 block_starts; uint32 first_transaction; uint32 block_first_transaction; uint32 error_number; } journal_superblock_v1; typedef struct __journal_superblock_v2_reminder { uint32 compatible_features; uint32 incompatible_features; uint32 ro_compatible_features; uint32 journal_uuid[4]; uint32 using_by_fs_nbr; uint32 superblock_copy; uint32 max_block_per_transaction; uint32 max_fs_block_per_transation; uint32 unused[44]; uint32 ids_fs[48][4]; } journal_v2_reminder; typedef struct __journal_superblock_v2 { journal_header header; uint32 block_size; uint32 blocks_number; uint32 block_starts; uint32 first_transaction; uint32 block_first_transaction; uint32 error_number; journal_v2_reminder end; } journal_superblock_v2; union journal_v1_v2 { journal_superblock_v1 journal_v1; journal_superblock_v2 journal_v2; } journal; typedef struct __journal_descriptor_block_entries_s { uint32 file_system_block; uint32 entry_flags; uint32 uuid[4]; } block_entries; typedef struct __journal_revoke_block_s { journal_header header; uint32 size; uint32 *block_addr; } revoke_block; enum entry_flag { JOURNAL_BLOCK_ESCAPED = 0x01, SAME_UUID = 0x02, BLOCK_DELETED = 0x04, LAST_ENTRY_BLOCK }; enum type_jounal_header { DESCRIPTOR_BLOCK = 1, COMMIT_BLOCK = 2, SUPERBLOCK_V1 = 3, SUPERBLOCK_V2 = 4, REVOKE_BLOCK = 5 }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/extfs_struct/posix_acl.h000066400000000000000000000022101217176075400272250ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __POSIX_ACL_H__ #define __POSIX_ACL_H__ typedef struct __posix_acl_header_s { uint32 version; } posix_acl_header; typedef posix_acl_header a; #define acl_version (a.version) typedef struct __posix_acl_entries { uint16 type; uint16 permissions; uint32 user_group_id; } posix_acl_entries; enum posix_acl_values { USER_INODE = 0x01, GROUP_INODE = 0x04, OTHERS = 0x20, EFFECTIVE_RIGHTS_MASK = 0x10, USER_ATTR = 0x02, GROUP_ATTR = 0x08 }; enum posic_acl_flags { EXECUTE = 0x01, WRITE = 0x02, READ = 0x04 }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/000077500000000000000000000000001217176075400241515ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/DirEntry.h000066400000000000000000000064361217176075400260730ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __DIR_ENTRY__ #define __DIR_ENTRY__ #include "vfs.hpp" #include "extfs_struct/directory_entry.h" class VFile; class DirEntry { /*! \class DirEntry \brief Directory entries (or dirents) Directories content are made of directory entries, often shortened to 'dirents'. \sa Inode \sa Directory */ public: enum FILE_TYPE { _UNKNOWN = 0, _REG_FILE = 1, _DIRECTORY = 2, _CHAR_DEVICE = 3, _BLOCK_DEVICE = 4, _FIFO = 5, _UNIX_SOCKET = 6, _SYM_LINK = 7 }; //! Constructor. DirEntry(); //! Destructor. ~DirEntry(); /*! \brief File name. \return the name of the file of the current dirent, or \c \b NULL if it hasn't been allocated. */ uint8_t * getName(); /*! \brief Dir entry structure. \return the address of the dir_entry structure \sa dir_entry_v2 */ dir_entry_v2 * getDir(); /*! \brief File name allocation. Allocate enough space for the file name according to the value returned by name_length_v1() or name_length_v2(), depending one the dirent used version. It doesn't read the file name though. The reading must be performed by the caller. \return a pointer to the allocated area, or \c \b NULL if the allocation failed. */ uint8_t * allocName(); /*! \brief Read a dirent content. Seek at \e \b content_addr, read the dirent content, allocate and read the file name (by calling \c \b allocName()). \param content_addr the address on the vfs where readName must read. \param vfile the vfs, necessary to seek and read \sa allocName */ void read(uint64_t content_addr, VFile * vfile); /*! \brief Next directory entry. \return what \e \b SHOULD be the size of the current dir entry. */ uint64_t next(); /*! \brief Inode number. \return the inode number. */ uint32_t inode_value() const; /*! \brief Dirent length. \return the length of the directory entry. */ uint16_t entry_length() const; /*! \brief Name's length v1. \return the lenght of the name (version 1). */ uint16_t name_length_v1() const; /*! \brief Name's length v2. \return the lenght of the name (version 2). */ uint8_t name_length_v2() const; /*! \brief File type (v2). \return the file type (version 2). */ uint8_t file_type_v2() const; /*! \brief Set directory entry. \param dir the pointer to the dir_entry_v2 structure we want to use. */ void setDir(dir_entry_v2 * dir); /*! \brief Set a directory name. \param name an array containing the name we want to set. */ void setName(uint8_t * name); private: dir_entry_v2 * _dir; uint8_t * _name; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/Ext4Extents.h000066400000000000000000000105511217176075400265230ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXT4_EXTENTS__ #define __EXT4_EXTENTS__ #include #include #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "Inode.h" #include "data_structure/includes/extfs_struct/ext4/extents.h" class Ext4Extents { /*! \class Ext4Extents \brief Used to parse extents. Extents are only available on ext4. A inode flag indicates if they are used by the inode or not. This class is designed to parse them and get all blocks an inode using extents is composed of. */ public : /*! \brief Constructor. \param file_mapping the FileMapping where blocks will be push. */ Ext4Extents(FileMapping * file_mapping = NULL); //! Destructor. Do nothing. ~Ext4Extents(); //! \return the address of the next level, or 0 if idx is NULL uint64_t next_level(ext4_extents_index * idx); /*! \brief Conversion of uint32_t and uint16_t into uint64_t Block numbers are 48 bytes long in extent structures. They occupy : \li an uint16_t for the higher bytes. \li an uint32_t for the lower bytes This method calculate the corresponding uint64_t. It doesn't return an uint48_t as far as this type doesn't exits in the standard lib. \param hi the higher two bytes \param lo the lower two bytes \return the concatenation of \e \b hi and \e \b and lo. */ static uint64_t concat_uint16_32(uint16_t hi, uint32_t lo); /*! \brief Extents block range. \param an extent structure address. \return a std::pair filled up with the number of block and the starting block number of the block range. If \e \b extent is NULL, the pair is filed up with 0s. */ std::pair extents(ext4_extent * extent); /*! \brief Read an extent header. \param block the block where the header is located. \return a pointer to an extent header. */ ext4_extents_header * read_header(uint8_t * block); /*! \brief Read extents indexes. \param header the extent header \param block the content of the curently read block. */ void read_indexes(ext4_extents_header * header, uint8_t * block); /*! \brief Read extents. \param header the extent header \param block the content of the curently read block. */ void read_extents(ext4_extents_header * header, uint8_t * block); /*! \brief Read a block on the vfile. \param addr the address where the driver musts go read. \return a pointer to the allocated area. */ uint8_t * read_block(uint64_t addr); /*! \brief File mapping push Push the different blocks in the file mapping. \param inode the inode we are treating. \throw vfsError if something goes zrong. */ void push_extended_blocks(Inode * inode) throw (vfsError); /*! \brief Block list. \return a list of the blocks which compose the current file. */ const std::list > extents_list() const; /*! \brief Calculate a file size. Only used for deleted inode, where the size is set to 0. Try to calculate the size by counting the number of blocks the inode is composed of. \param inode the inode we want to have the size. */ uint64_t calc_size(Inode * inode); /*! \brief Read extents Read extents, but not based on the file size stored in the inode. \param header the extents header. \param block the area we are currently parsing. */ void read_extents_x(ext4_extents_header * header, uint8_t * block); private : FileMapping * __mapping; uint64_t __size; uint64_t __offset; uint32_t __block_size; Node * __node; Extfs * __extfs; uint64_t __c_size; Inode * __inode; std::list > __extents_list; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/ExtendedAttr.h000066400000000000000000000110761217176075400267220ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXTENDED_ATTR__ #define __EXTENDED_ATTR__ #include #include #include #include "../../extfs.hpp" #include "extfs_struct/xtd_attr.h" class ExtendedAttr { /*! \class ExtendedAttr \brief Linux xattr (Extended attributes). This class purpose is to get the xattr/acl from an inode. The block number of the xattr is stored in the inode (the field is set to 0 if they are no xattr). A xattr block can be shared by several inodes. There are 2 main types of extended attributes: \li User attributes \li Posix acl. \note to set / remove xattr or acl to/from a file, the packages 'attr' and 'acl' are available on linux. \note to use those functionnalyties there are 2 conditions: \li your kernel must support it. \li your file file system must be mounted with the options user_xattr and/or acl (depending if you need acls or xattr). */ public: /*! \enum type \brief The xattr type. */ enum type { USER_SPACE_ATTR = 1, /*!< User xattr. */ POSIX_ACL = 2, /*!< Posix acl. */ DEFAULT_POSIX_ACL = 3, /*!< Default acl (for directories) */ TRUSTED_SPACE_ATTR = 4, /*!< Trusted space */ LUSTRE = 5, /*!< Unused */ SECURITY_SPACE_ATTR = 6 /*!< Security */ }; enum posix_acl_values { USER_INODE = 0x01, USER_ATTR = 0x02, GROUP_INODE = 0x04, GROUP_ATTR = 0x08, EFFECTIVE_RIGHTS_MASK = 0x10, OTHERS = 0x20 }; /*! \enum posic_acl_flags \brief Permissions. */ enum posic_acl_flags { EXECUTE = 0x01, /*!< Execution. */ WRITE = 0x02, /*!< Writing. */ READ = 0x04 /*!< Reading. */ }; /*! \brief Constructor. \param block the block number of the exented attributes. \param block_size the size in bytes of one fs block. */ ExtendedAttr(uint32_t block, uint32_t block_size); //! Destructor. ~ExtendedAttr(); /*! \brief Initialisation. \param extfs a pointer to the Extfs instance. */ void init(const Extfs * extfs); /*! \brief Xattr parsing. Parse all extended attributes in the block. \param block_size the size of on fs block. */ void parse(uint32_t block_size); /*! \brief Posix acl. Get all the posix acl corresponding to the entry \e \b ent. \param ent a xattr_name_entries. \return a list of acl. */ std::list posix_acl(xattr_name_entries * ent); /*! \brief Name. \return the name of an extended attribute. */ std::string findName(const xattr_name_entries * ent, uint32_t offset); /*! \brief Value. \return the value of an extended attribute. */ std::string findValue(const xattr_name_entries * ent); /*! \brief Xattr header. \return a pointer to the extended attribute header. */ const xattr_header * getHeader() const; /*! \brief User xattr \return a map of all user xattr with their xattr_name_entries, name and value. */ const std::map > & getUserXAttr() const; /*! \brief Posix acl. \return a map containing xattr_name_entries and a list of acl for each of them. */ const std::map > & getPosixACL() const; /*! \brief Acl structure size. \param flag used to determine the size. \return the size of an acl. */ uint32_t acl_size(uint16_t flag); /*! \brief Tag. \param tag the tag \return a human readable string. */ std::string aclTag(uint16_t tag); /*! \brief permissions \param permission the permission \return a human readable string. */ std::string aclPermissions(uint16_t permission); private: uint32_t _block; xattr_header * _header; uint8_t * _xattr_block; // entry, value std::map > _user; // entry, acl std::map > _posix_acl; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/GroupDescriptor.h000066400000000000000000000152731217176075400274650ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __GROUP_DESCRIPTOR_H__ #define __GROUP_DESCRIPTOR_H__ #include "extfs_struct/group_descr_table.h" #include "SuperBlock.h" #include "vfs.hpp" //! this table is used to calculate the crc16 in group descriptor uint16_t const crc16_table[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; class GroupDescriptor { /*! \class GroupDescriptor \brief A group descriptor structure. The ext file system family is composed of blocks (usually 4 kB big on ext3, but this can be modified in the Superblock), divided in group blocks. In the block following the superblock block is a table containing group descriptors (one for each group). Backup of this table can be found in all groups, UNLESS the sparse superblock feature is enabled. There are two versions of the group descriptor table : \li one which is 32 bytes big. \li the other is 64 bytes big. There is a field in the superblock that indicates the size. If this size is set to 0, we assume that the group descriptor is 32 bytes big. The check is made in the constructor and the attributes __64_bits_field is set appropriatly. \sa SuperBlock */ public: //! Constructor : do nothing GroupDescriptor(SuperBlock * SB, uint32_t block_size); //! Desctructor : do nothing. ~GroupDescriptor(); /*! \brief Group descriptor address. \return the address of the block descriptor. */ uint64_t groupDescriptorAddr() const; /*! \brief Read a group descriptor. Read the content of a group descriptor structure in the descriptor table. \param block_size the size of a file system block \param vfile a pointer to the vfile \param gr_number the group number \param check_alloc_nb if true, check the allocation number of inodes and blocks. \throw vfsError if something goes wrong. */ void init(uint32_t block_size, VFile * vfile, uint32_t gr_number); /*! \brief Descriptor group structure. \return a pointer to the \c \b group_descr_table_t. \typedef group_descr_table_t */ const group_descr_table_t * getGroupTable() const; /*! \brief Descriptor group table. \param group the number of the group we need the descriptor. \return a pointer to the group_descr_table_t of group \e \b group. */ const group_descr_table_t * getGroupTable(uint32_t group) const; /*! \brief Group descriptor size. \return the group descriptor size. */ uint16_t GD_size() const; /*! \brief Block bitmap. \return the block bitmap address. \sa group_descr_table_t */ uint32_t block_bitmap_addr(uint32_t group) const; /*! \brief Inode bitmap. \return the inode bitmap address. \sa group_descr_table_t */ uint32_t inode_bitmap_addr(uint32_t group) const; /*! \brief Inode table. \return the inode table address. \sa group_descr_table_t */ uint32_t inode_table_block_addr(uint32_t group) const; /*! \brief Unallocated blocks. \return the number of unallocated blocks in the group. \sa group_descr_table_t */ uint16_t unallocated_block_nbr(uint32_t group) const; /*! \brief Unallocated inodes. \return the number of unallocated inodes in the group. \sa group_descr_table_t */ uint16_t unallocated_inodes_nbr(uint32_t group) const; /*! \brief Directories number. \return the number of directories in the group. \sa group_descr_table_t */ uint16_t dir_nbr(uint32_t group) const; uint16_t checksum(uint32_t group) const; uint16_t unused_inodes_low(uint32_t group) const; private: void __check_inode_nb(uint32_t, uint32_t, VFile *); void __check_blk_nb(uint32_t, uint32_t, VFile *); uint16_t crc16(uint16_t crc, uint8_t const * buf, size_t len); inline uint16_t crc16_byte(uint16_t crc, const uint8_t data); group_descr_table_t * _gr_descr; group_descr_table_64_t * _gr_descr_64; uint8_t * _gr_descr_array; uint64_t _SB_offset; uint64_t _block_addr; const uint8_t * __FS_ID; bool __64_bits_field; bool __bg_checksum; SuperBlock * __SB; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/Inode.h000066400000000000000000000164061217176075400253670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __INODE_H__ #define __INODE_H__ #include #include "extfs.hpp" #include "include/utils/InodeStructure.h" #include "include/utils/InodeUtils.h" #include "extfs_struct/ext4/extents.h" class Inode : public InodeStructure, public InodeUtils { /*! \class Inode. \brief Extfs metadata. This class encapsulate an \c \b inodes_t typedef. Accessors can be used to get all the fields. An inode contains metadatas of files. This consist of, among other things: \li the file size \li the file mode (access right) \li MAC times \li block pointers, to locate the content on the file system. It is ineritated by \c \b Directory (which are inodes too). 'Everything is a file', so everything has an inode, though the content is not the same between a file, a directory and other file types. The three most important types of files are : \li Regular files. \li Directories. \li Symbolic links. The type is defined in the file mode field of the inode structure. The other type are stuff like FIFO, devices, socket, etc. The file mode also contains informations about the access rights and group and user ID (set UID / GID). The content of a file is refered by block pointers which can be directs or indirect. \li 12 direct block pointers, directly stored in the inode. \li 1 single indirect block pointer. \li 1 double indirect block pointer. \li 1 triple indirect block pointer. When a file is deleted, the behaviour is different between ext2 and ext3 : on ext3 block pointers and the file size are reset to 0. This make the recovery harder : one solution is to look into the journal to check if the inode can be found in its previous state. But even if this is the case we cannot be sure the content blocks haven't been reallocated in the mid time. \sa inodes_t */ public: /*! \enum PERMISSIONS_BITS \brief Permissions bits. */ enum PERMISSIONS_BITS { _ISUID = 0x0004000, _ISGID = 0x0002000, _ISSTI = 0x0001000 }; //! Constructor. Inode(Extfs *, const SuperBlock *, GroupDescriptor * GD); //! Copy constructor. Inode(const Inode *); //! Desctructor, free resources. ~Inode(); /*! \brief Read the inode content. \param addr the address of the inode on the vfs. */ void read(uint64_t addr); /*! \brief Read an inode content. Overload provided for convenience. \param addr the address of the inode on the vfs. \param inode a pointer to the \c \b inodes_t where the result will be stored. */ void read(uint64_t addr, inodes_t * inode); /*! \brief Content blocks number. The content of files is stored in file system blocks which are 'pointed' by block pointers in the inode: \li 12 direct block pointers \li 1 single indirect block pointer \li 1 double indirect block pointer \li 1 triple indirect block pointer \warning in those block pointers, BLOCK NUMBERS are stored, not addresses. The address on the vfile must be calculated using the calculation : \verbatim block_pointer * SuperBlock->block_size(); \endverbatim The content of the destination block in not read, it is up to the caller to perform the reading. Notice that data can be hidden at the end of the last content block (the slack). At least one block is allocated per file, even if his size is just a few bytes. The \c \b nextBlock() method returns the next file system content block number (the current content block number can be known by calling \c \b currentBlock()). This method also increments the value of the current block by 1 each time it is called. If the current block reaches a value which is out a range, an exception is thrown. \warning the current block is a block number IN THE INODE but the method \c \b nextBlock() returns a block number ON THE VFS. In other words, if the current block is equal to 0, it will refer to the first direct block pointer, if it is equal to 1 it will refer to the second direct block pointer, if it is equal to 13 it will refer to the first single indirect block pointer and so on. \return The number of the next content block. In the following example \c \b nextBlock() will return all content block numbers one after the others. \code Inode * inode = new Inode; uint32_t block_number; while (block_number = inode->nextBlock()) do_something(block_number); \endcode */ uint32_t nextBlock(); void init(); /*! \brief Current block. \return the number of the current content block. */ uint32_t currentBlock(); /*! \brief Get a file system content block number. Set the current block to \e \b block_number and return return the corresponding file system block number. \param block_number the block number you want to go to. \return the file system block number */ uint32_t goToBlock(uint32_t block_number); /*! \brief Browsing several blocks. Example of use : \code uint32_t block_number; while (block_number = goToBlock(5, 15)) doSomething(block_number); \endcode In the the previous example, \c \b browseBlock() will return one after the other the file system block number of inode content blocks 1 to 15. The current block is incremented by one at each call. \param begin the first block the user wants to go. \param end the block where the browsing stops. \throw a vfsError if the block \e \b block_number is out of range. \return the file system block number of the current block. */ uint32_t browseBlock(uint32_t begin, uint32_t end); /*! \brief EXtfs. \return a pointer to an Extfs instance \sa Extfs */ Extfs * extfs() const; bool is_fucked_up() const; ext4_extents_header * extent_header() const; uint32_t s_i_blk() const; uint32_t d_i_blk() const; uint32_t t_i_blk() const; inline uint32_t inodeNb() const { return __inode_nb; } void setInodeNb(uint32_t inode_nb); protected: uint32_t singleIndirectBlockContentAddr(uint32_t); uint32_t doubleIndirectBlockContentAddr(uint32_t); uint32_t tripleIndirectBlockContentAddr(uint32_t); uint64_t go_to_extent_blk(); uint64_t null_extent_depth(uint32_t block_number); bool init_extents(); protected: std::list > __extents_list; uint32_t __inode_nb; uint16_t __offset_in_extent; Extfs * _extfs; uint32_t _current_block; uint64_t _calculated_size; // extents (only on ext4) ext4_extents_header * _head; uint8_t _extent_nb; uint32_t _blk_nb; uint32_t _blk_nb_l[4]; uint32_t _cur_extent_blk; bool __extents; uint32_t __s_i_blk; uint32_t __d_i_blk; uint32_t __t_i_blk; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/SuperBlock.h000066400000000000000000000114451217176075400264000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __SUPER_BLOCK_ #define __SUPER_BLOCK_ #include #include #include "../../include/utils/SuperblockStructure.h" #include "../../include/utils/SuperBlockUtils.h" class Extfs; class SuperBlock : public SuperBlockStructure, public SuperBlockUtils { /*! \class SuperBlock \brief The ext file system superblock. This block is located at 1024 bytes from the begining of the file system. The 1024 previous bytes are dedicated to the boot code and are set to 0 if there is no boot code. Some data could be hidden in this area. The driver create a node for it. The superblock is 1024 bytes big. It can be seen as the main configuration of the file system. All the informations stored in it are passed to the result class and can be diplayed by the user when the extfs driver has finished running. */ public: /*! \brief Constructor. Initialization. */ SuperBlock(); /*! \brief Desctructor. Do nothing. */ ~SuperBlock(); /*! \brief Super block initilization. Initialize the superblock, ie seek at the offset where it should be and then read his content. If the signature doesn't match 0xEF53 the method \c \b sigfind() si called. \param fs_size the total size of the file system. \param vfile a pointer to the virtual file system. \param sb_check an option to indicate if a superblock backup search must be done. \param sb_force_addr force the adress of the superblock \throw vfsError if the initilization failed. */ void init(VFile * vfile, bool sb_check, uint64_t sb_force_addr); void force_addr(VFile * vfile, uint64_t addr); /*! \brief Check the validity of the superblock. \return true if it is considered as valid, false otherwise. */ bool sanity_check() const; /*! \brief Find super block backup. The method \c \b sigfind() try locating the signature \c \b #__SB_SIG of the superblock to find possible backups. I dont know yet how it will work though... It looks every 1024 bytes if the signature \c \b #__SB_SIG could be found at bytes 56. \warning \b \c sigfind() is only called when the superblock seems to be corrupted. False hits must be expected. \param fs_size the file system size in bytes. \param vfile a pointer to the virtual file system, used to perform reads and seeks. \return false is no backup were, true otherwise. */ bool sigfind(VFile * vfile); /*! \brief Superblock offset on file system. The offset is set to #__BOOT_CODE_SIZE by default. \return the offset of the superblock on the vfs. \warning If the returned value is different from #__BOOT_CODE_SIZE it means that this superblock is a backup and can be out of date. */ uint64_t offset() const; /*! \brief Most recent superblock backup. Seek and read to the position where the most recent backup is located. \param vfile a pointer to the virtual file system. \return the number of bytes read. \throw vfsError when the reading or seeking failed. */ uint64_t most_recent_backup(VFile * vfile) throw(vfsError); /*! \brief Verify file system consistency. Verify if the superblock offset indicated in the field current_block_group corresponds to the real offset on the file system. If no, print a warning message. */ void file_system_sanity(); /*! \brief Read superblock. Goes to offset \e \b offset and read sizeof(super_block_t_) bytes. \param vfile a pointer to the virtual file system. \param offset the offset where we want to read. \return the number of bytes effectively read. */ uint32_t read(VFile * vfile, uint64_t offset); /*! \brief Group Blocks number. \return the number of group blocks on the file system. */ uint32_t group_number() const; private: uint64_t _offset; // std::auto_ptr _sb_utils; //offset, last written time std::map _backup_list; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/000077500000000000000000000000001217176075400267065ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/directory_entry.h000066400000000000000000000037051217176075400323110ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __DIRECTORY_ENTRY_H__ #define __DIRECTORY_ENTRY_H__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif typedef struct __directory_entry_original_s { /*! \struct __directory_entry_original_s \brief The first version of a dirent structure. The file type is not present. */ //! Inode value. uint32_t inode_value; //! Lenght of the entry. uint16_t entry_length; //! Lenght of the name. uint16_t name_length; } dir_entry_v1; /*! \struct __directory_entry_2nd_version_s \brief The second version of a dirent structure. The file type is present. The uint16_t \c \b name_length is splitted in two 8 bits fields which respectively are : \li The name lenght. \li The file type. The file type can take the following values : \li 0 : Unknown type. \li 1 : Regular file. \li 2 : Directory. \li 3 : Character device. \li 4 : Block device. \li 5 : FIFO \li 6 : Unix socket. \li 7 : Symbolic link. \sa DirEntry */ typedef struct __directory_entry_2nd_version_s { //! Inode value. uint32_t inode_value; //! Lenght of the entry. uint16_t entry_length; //! Lenght of the name. uint8_t name_length; //! Type of the file. uint8_t file_type; } dir_entry_v2; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/ext4/000077500000000000000000000000001217176075400275725ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/ext4/extents.h000066400000000000000000000026051217176075400314400ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXTENTS_H__ #define __EXTENTS_H__ #include "node.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif /*! \struct __ext4_extents_header_s \brief Extents header. */ typedef struct __ext4_extents_header_s { //! Magic : 0xF30A uint16_t magic; //! Number of valid entries. uint16_t entries; //! Max entry number. uint16_t max_entries; //! Depth uint16_t depth; //! Tree generation uint32_t generation; } ext4_extents_header; typedef struct __ext4_extents_index_s { uint32_t block; uint32_t next_level_low; uint16_t next_level_high; uint16_t unused; } ext4_extents_index; typedef struct __ext4_extent_s { uint32_t block; uint16_t length; uint16_t phys_blk_high; uint32_t phys_blk_low; } ext4_extent; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/first_block.h000066400000000000000000000012721217176075400313620ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifdef __FIRST_BLOCK_H__ #define __FIRST_BLOCK_H__ typedef struct first_block { uint32 *boot_code; } #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/group_descr_table.h000066400000000000000000000050241217176075400325430ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __GROUP_DESCR_TABLE_H__ #define __GROUP_DESCR_TABLE_H__ #include "node.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */ #define EXT4_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not in use */ #define EXT4_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */ typedef struct __group_descr_table_s { uint32_t block_bitmap_addr; uint32_t inode_bitmap_addr; uint32_t inode_table_block_addr; uint16_t unallocated_block_nbr; uint16_t unallocated_inodes_nbr; uint16_t dir_nbr; uint16_t bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ uint32_t bg_reserved[2]; /* Likely block/inode bitmap checksum*/ uint16_t bg_itable_unused_lo; /* Unused inodes count */ uint16_t bg_checksum; /* crc16(sb_uuid+group+desc) */ } group_descr_table_t; typedef struct __group_descr_table_64_s { uint32_t block_bitmap_addr; uint32_t inode_bitmap_addr; uint32_t inode_table_block_addr; uint16_t unallocated_block_nbr; uint16_t unallocated_inodes_nbr; uint16_t dir_nbr; uint16_t bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ uint32_t bg_reserved[2]; /* Likely block/inode bitmap checksum*/ uint16_t bg_itable_unused_lo; /* Unused inodes count */ uint16_t bg_checksum; /* crc16(sb_uuid+group+desc) */ uint32_t bg_block_bitmap_hi; /* Blocks bitmap block MSB */ uint32_t bg_inode_bitmap_hi; /* Inodes bitmap block MSB */ uint32_t bg_inode_table_hi; /* Inodes table block MSB */ uint16_t bg_free_blocks_count_hi;/* Free blocks count MSB */ uint16_t bg_free_inodes_count_hi;/* Free inodes count MSB */ uint16_t bg_used_dirs_count_hi; /* Directories count MSB */ uint16_t bg_itable_unused_hi; /* Unused inodes count MSB */ uint32_t bg_reserved2[3]; } group_descr_table_64_t; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/hash_tree.h000066400000000000000000000020571217176075400310250ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __HASH_TREE_HH__ #define __HASH_TREE_HH__ typedef struct __hash_tree_node_descriptor_header_s { uint32 unused; uchar hash_version; uchar length; uchar level_leaves; uchar unused2; } hash_tree_header; typedef struct __hash_tree_node_descriptor_entries_s { uint32 min_hash_value; uint32 block_addr; } hash_node_descriptor; typedef struct __first_node_descriptor_entry { uint16 max_nbr; uint16 current_nbr; uint32 block_addr; } first_node_entry; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/inodes.h000066400000000000000000000102211217176075400303340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __INODES__H__ #define __INODES__H__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif /* access rights */ #define _IRUSR 400 #define _IWUSR 200 #define _IXUSR 100 #define _IRGRP 040 #define _IWGRP 020 #define _IXGRP 010 #define _IROTH 004 #define _IWOTH 002 #define _IXOTH 001 /* Encoding of the file mode. */ #define __IFMT 0170000 /* These bits determine file type. */ /* File types. */ #define __IFIFO 0010000 /* FIFO. */ #define __IFCHR 0020000 /* Character device. */ #define __IFDIR 0040000 /* Directory. */ #define __IFBLK 0060000 /* Block device. */ #define __IFREG 0100000 /* Regular file. */ #define __IFLNK 0120000 /* Symbolic link. */ #define __IFSOCK 0140000 /* Socket. */ #define _ISTYPE(mode, mask) (((mode) & __IFMT) == (mask)) #define _ISDIR(mode) __ISTYPE((mode), __IFDIR) #define _ISCHR(mode) __ISTYPE((mode), __IFCHR) #define _ISBLK(mode) __ISTYPE((mode), __IFBLK) #define _ISREG(mode) __ISTYPE((mode), __IFREG) #define _ISFIFO(mode) __ISTYPE((mode), __IFIFO) #define _ISLNK(mode) __ISTYPE((mode), __IFLNK) #define _ISSOCK(mode) __ISTYPE((mode), __IFSOCK) typedef struct inodes_s { /*! \struct inodes_s \brief The 'raw' structure of an inode. \sa Inode */ //! the file mode. uint16_t file_mode; //! Lower 16 bits of user id. uint16_t lower_uid; //! the lower 16 bits of size. uint32_t lower_size; //! The last access timestamp. uint32_t access_time; //! The last change timestamp. uint32_t change_time; //! The last modification time. uint32_t modif_time; //! The deletion timestamp. uint32_t delete_time; //! The 16 lower bits of group ID. uint16_t lower_gid; //! The number of link pointing the inode. uint16_t link_count; //! The number of sector. uint32_t sector_count; //! Some flags. uint32_t flags; //! Unused area. This area is OS dependent. uint32_t unused1; //! 12 direct block pointers. uint32_t block_pointers[12]; //! Single indirect block pointer. uint32_t simple_indirect_block_pointer; //! Double indirect block pointer. uint32_t double_indirect_block_pointer; //! Triple indirect block pointer. uint32_t triple_indirect_block_pointer; //! NFS generation number. uint32_t generation_number_nfs; //! Extended attributes. uint32_t file_acl_ext_attr; //! Upper 32 bits of size. uint32_t upper_size_dir_acl; //! Fragment address. Obsolote on ext4. uint32_t fragment_addr; //! Index of fragment. uint8_t fragment_index; //! Size of fragments. uint8_t fragment_size; //! Unused area. uint16_t unused2; //! Upper 16 bits of user ID. uint16_t upper_uid; //! Upper 16 bits of group ID. uint16_t upper_gid; //! Unused area. uint32_t unused3; } inodes_t; typedef struct __ext3_4_inode_reminder { /*! \struct __ext3_4_inode_reminder \brief Inode fields used only on ext4. */ //! Extra inode size uint16_t extra_inode_size; //! Padding uint16_t padding; //! Extra change time (nanoseconds) uint32_t extra_change_time; //! Extra modification time (nanoseconds) uint32_t extra_modif_time; //! Extra access time (nanoseconds) uint32_t extra_access_time; //! Creation time (seconds) uint32_t creation_time; //! Extra creation time (nanoseconds) uint32_t extra_creation_time; //! High 32 bits for 64 bit version. uint32_t version_high; } __inode_reminder_t; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/journal.h000066400000000000000000000036651217176075400305430ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __JOURNAL_H__ #define __JOURNAL_H__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif /*! \def __J_SIGNATURE \brief The journal block signature. */ #define __J_SIGNATURE (0xC03B3998) typedef struct __journal_standard_header_s { uint32_t signature; //0xC03B33998 uint32_t block_type; uint32_t sequence_number; } journal_header; typedef struct __journal_superblock_v1_s { journal_header header; uint32_t block_size; uint32_t blocks_number; uint32_t block_starts; uint32_t first_transaction; uint32_t block_first_transaction; uint32_t error_number; } journal_superblock; typedef struct __journal_superblock_v2_reminder_s { uint32_t compatible_features; uint32_t incompatible_features; uint32_t ro_compatible_features; uint32_t journal_uuid[4]; uint32_t using_by_fs_nbr; uint32_t superblock_copy; uint32_t max_block_per_transaction; uint32_t max_fs_block_per_transation; uint32_t unused[44]; uint32_t ids_fs[48][4]; } journal_v2_reminder; typedef struct __journal_descriptor_block_entries_s { uint32_t file_system_block; uint32_t entry_flags; } journal_block_entries; typedef struct __journal_revoke_block_s { journal_header header; uint32_t size; uint32_t * block_addr; } journal_revoke_block; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/super_block.h000066400000000000000000000127701217176075400313760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXTFS_SUPER_BLOCK_HPP__ #define __EXTFS_SUPER_BLOCK_HPP__ #include "node.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif /*! \def SUPER_BLOCK_SIZE \brief Size of the superblock. The size is expressed in bytes. */ #define SUPER_BLOCK_SIZE 1024 /*! \def __SB_SIG \brief The superblock signature. Must be 0xEF53. */ #define __SB_SIG 0xEF53 /*! \def __BOOT_CODE_SIZE \brief The size of the boot code, located at the offset 0 of the file system. Should always be 1024 bytes. */ #define __BOOT_CODE_SIZE 1024 typedef struct __extfs_super_block_s { /*! \struct __extfs_super_block_s \brief The 'raw' structure of the super block. \sa SuperBlock */ //! Inodes number on the file system. uint32_t inodes_number; //! Blocks number on the file system. uint32_t blocks_number; //! Reserved block number. uint32_t r_blocks_number; //! Unallocated block number. uint32_t u_blocks_number; //! Unallocated inodes number. uint32_t u_inodes_number; /* 16 */ //! First data block. uint32_t first_block; //! Size of blocks. uint32_t block_size; //! Size of fragments. uint32_t fragment_size; //! Number of blocks per group. uint32_t block_in_groups_number; //! Number of fragments per groups. uint32_t fragment_in_group_number; /* 32 */ //! Number of inodes per group. uint32_t inodes_in_group_number; //! Last mount time. uint32_t last_mount_time; //! Last written time. uint32_t last_written_time; //! Current mount count. uint16_t current_mount_count; //! Maximum mount number. uint16_t max_mount_count; //! Signature. Must be \b 0xEF53 uint16_t signature; // must be 0xef53 //! File system state. uint16_t fs_state; //! Error handling method. uint16_t error_handling_method; //! Version. uint16_t minor_version; //! Time of the last consistency check. uint32_t l_consistency_ct; //! Interval between consistency checks. uint32_t consitency_forced_interval; //! OS who created the file system. uint32_t creator_os; //! Version. uint32_t major_version; //! UID. uint16_t uid_reserved_block; //! GID. uint16_t gid_reserved_block; //! First non reserved inode number. uint32_t f_non_r_inodes; //! Size of an inode structure. uint16_t inodes_struct_size; //! Block group number (if we are in a superblock backup). uint16_t current_block_group; //! Compatible features. uint32_t compatible_feature_flags; //! Incompatible features. uint32_t incompatible_feature_flags; //! Read only features. uint32_t ro_features_flags; //! File system ID. uint8_t file_system_ID[16]; //! Name of the volume. uint8_t volume_name[16]; //! Path to where it was last mounted. uint8_t path_last_mount[64]; //! Allocation algorithm. uint32_t algorithm_bitmap; //! Preallocation for file. uint8_t preallocate_blocks_files; //! Preallocation for directories. uint8_t preallocate_block_dir; //! Unused area. uint16_t unused; //! Journal ID. uint8_t journal_id[16]; //! Journal inode (usually 8). uint32_t journal_inode; //! Journal device (feature). uint32_t journal_device; //! Orphan inode list number. uint32_t orphan_node_list; uint32_t s_hash_seed[4]; /* HTREE hash seed */ uint8_t s_def_hash_version; /* Default hash version to use */ uint8_t s_reserved_char_pad; uint16_t s_desc_size; /* size of group descriptor */ /*100*/ uint32_t s_default_mount_opts; uint32_t s_first_meta_bg; /* First metablock block group */ uint32_t s_mkfs_time; /* When the filesystem was created */ uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */ /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */ /*150*/ uint32_t s_blocks_count_hi; /* Blocks count */ uint32_t s_r_blocks_count_hi; /* Reserved blocks count */ uint32_t s_free_blocks_count_hi; /* Free blocks count */ uint16_t s_min_extra_isize; /* All inodes have at least # bytes */ uint16_t s_want_extra_isize; /* New inodes should reserve # bytes */ uint32_t s_flags; /* Miscellaneous flags */ uint16_t s_raid_stride; /* RAID stride */ uint16_t s_mmp_interval; /* # seconds to wait in MMP checking */ uint64_t s_mmp_block; /* Block for multi-mount protection */ uint32_t s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ uint8_t s_log_groups_per_flex; /* FLEX_BG group size */ uint8_t s_reserved_char_pad2; uint16_t s_reserved_pad; uint64_t s_kbytes_written; /* nr of lifetime kilobytes written */ uint32_t s_reserved[160]; /* Padding to the end of the block */ } super_block_t_; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/data_structure/includes/extfs_struct/xtd_attr.h000066400000000000000000000041401217176075400307070ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXT_ATTR_HEADER_H__ #define __EXT_ATTR_HEADER_H__ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif typedef struct __ext_attr_header_s { /*! \struct __ext_attr_header_s \brief The xattr header structure. \sa ExtendedAttr */ //! Signature (0xEA020000) uint32_t signature; //0xEA020000 //! Number of inode using this xattr block. uint32_t reference_count; //! Unused. uint32_t blocks_number; //! Hash of the attribute. uint32_t hash; //! Reserved. uint32_t reserved[4]; } xattr_header; typedef struct __ext_attr_name_entries_s { /*! \struct __ext_attr_name_entries_s \brief The xattr name entries. \sa ExtendedAttr */ //! Name length. uint8_t name_length; //! Type of extended attr. uint8_t attr_type; //! Offset to the value. uint16_t value_offset; //! Block number of value (unused) uint32_t block_location; //! Value size. uint32_t size; //! Value hash. uint32_t hash; } xattr_name_entries; typedef struct __posix_acl_header_s { /*! \struct __posix_acl_header_s \brief acl version */ //! Version number. uint32_t version; } posix_acl_header; typedef struct __posix_acl_entries { /*! \struct __posix_acl_entries \brief The posix acl structure. \sa ExtendedAttr */ //! Type of the ACL. uint16_t type; //! Permissions (write, execute or read). uint16_t permissions; //! User or group id (not always used). uint32_t user_group_id; } posix_acl_entries; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/extfs.cpp000066400000000000000000000207611217176075400211550ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include #include "extfs.hpp" #include "include/Option.h" #include "include/ExtfsNode.h" #include "include/ExtfsRawDataNode.h" #include "include/ExtfsSymLinkNode.h" #include "data_structure/includes/Inode.h" #include "include/FileNameRecovery.h" #include "include/OrphansInodes.h" #include "include/ExtfsSlackNode.hpp" #include "include/fsck.h" Extfs::Extfs() : mfso("extfs"), __root_dir(NULL), __node(NULL), __vfile(NULL), __first_node(NULL), __fs_node(NULL), __metadata_node(NULL), __first_inodes_nodes(NULL) { __SB = NULL; __orphans_i = NULL; __fsck = NULL; __slack = NULL; //XXX if "extfs" shadow a parameters attributeHandler = new BlockPointerAttributes("extfs-extended"); } Extfs::~Extfs() { delete __SB; delete __GD; delete __root_dir; } void Extfs::start(std::map args) { try { launch(args); } catch (envError & e) { std::cerr << "Extfs::start() : envError Exception caught : \n\t ->" << e.error << std::endl; } catch (vfsError & e) { std::cerr << "Extfs::start() : vfsError exeption caught :" << std::endl << "\t -> " << e.error << std::endl; } catch (std::exception & e) { std::cerr << "Extfs::start() : std::exception caught :\n\t -> " << e.what() << std::endl; } catch (...) { std::cerr << "Extfs::start() : unknown exception caught." << std::endl; } } void Extfs::launch(std::map args) { bool sb_check = false; uint64_t sb_force_addr; bool run_driver = true; uint64_t root_i_nb = ROOT_INODE; std::map::iterator it; // get arguments, initialize and run. if ((it = args.find("file")) != args.end()) this->__node = it->second->value(); else throw (std::string("Extfs::launch(): no parent provided")); if ((it = args.find("SB_addr")) != args.end()) sb_force_addr = it->second->value(); else sb_force_addr = 1024; // initialization this->init(sb_check, sb_force_addr); Option * opt = new Option(args, __SB, __vfile, __GD); opt->parse(this); // parsing file system ? if ((it = args.find("dont_parse_fs")) != args.end()) run_driver = false; if ((it = args.find("blockpointers")) != args.end()) this->addBlockPointers = it->second->value(); else this->addBlockPointers = false; if (run_driver) { bool orphans = false; std::string root_inode(""); if ((it = args.find("i_orphans")) != args.end()) orphans = true; if ((it = args.find("slack")) != args.end()) this->__slack = true; if ((it = args.find("fsck")) != args.end()) this->__fsck = true; if ((it = args.find("root_inode")) != args.end()) root_i_nb = it->second->value(); else root_i_nb = ROOT_INODE; run(root_i_nb); /* parse orphans inode (i.e. inodes which are not part of the file system content) */ if (orphans) __orphan_inodes(); __root_dir->clean(); this->registerTree(__node, __first_node); } } void Extfs::init(bool sb_check, uint64_t sb_force_addr) { __SB = new SuperBlock; __vfile = __node->open(); __SB->init(__vfile, sb_check, sb_force_addr); __GD = new GroupDescriptor(__SB, __SB->block_size()); __GD->init(__SB->block_size(), __vfile, __SB->group_number()); __alloc_inode = __SB->inodesNumber() - __SB->u_inodes_number(); __nb_parsed_inode = 0; } void Extfs::run(uint64_t root_i_nb) { uint64_t addr; inodes_t inode; __root_dir = new Directory(this, __SB, __GD); addr = __root_dir->getInodeByNumber(root_i_nb); __root_dir->setInode(&inode); __root_dir->dir_init(); __root_dir->i_list()->insert(root_i_nb); __root_dir->read(addr, &inode); __first_node = new ExtfsNode("Extfs", 0, NULL, this, 0, true, this->addBlockPointers); __fs_node = new ExtfsNode("File system", 0, __first_node, this, addr, false, this->addBlockPointers); __fs_node->set_i_nb(root_i_nb); __metadata_node = new ExtfsNode("Metadata", 0, __first_node, this, 0, false, this->addBlockPointers); __suspiscious_i = new ExtfsNode("Suspiscious inodes", 0, __first_node, this, 0, false, this->addBlockPointers); __suspiscious_dir = new ExtfsNode("Suspiscious directory", 0, __first_node, this, 0, false, this->addBlockPointers); __root_dir->dirContent(__fs_node, (inodes_t *)__root_dir->inode(), addr, root_i_nb); __add_meta_nodes(); __reserved_inodes(); this->stateinfo = "Finished"; } void Extfs::v_seek_read(uint64_t addr, void * buf, uint64_t size) { __vfile->seek(addr + __SB->offset() - __BOOT_CODE_SIZE); __vfile->read(buf, size); } class ExtfsNode * Extfs::createVfsNode(Node * parent, std::string name, uint64_t id, inodes_t * inode) { uint64_t size = 0; ExtfsNode * node = NULL; if (!inode || !parent) return NULL; if (!id) node = new ExtfsNode(name, 0, parent, this, 0, false, false); else if ((inode->file_mode & __IFMT) == __IFLNK) { size = inode->lower_size; node = new ExtfsNode(name, 0, parent, this, id, false, this->addBlockPointers); } else if (id && ((inode->file_mode & __IFMT) == __IFREG)) { size = inode->lower_size; node = new ExtfsNode(name, size, parent, this, id, false, this->addBlockPointers); node->setFile(); if (this->__fsck) { Fsck fsck(inode, this->__vfile, id); fsck.run(this, name); } if (this->__slack) createSlack(node, id); } else node = new ExtfsNode(name, size, parent, this, id, false, this->addBlockPointers); return node; } void Extfs::createSlack(Node * node, uint64_t addr) { new ExtfsSlackNode(node->name() + ".slack", 0, node->parent(), this, addr); } Node * Extfs::node() const { return __node; } class GroupDescriptor * Extfs::GD() const { return __GD; } class SuperBlock * Extfs::SB() const { return __SB; } class VFile * Extfs::vfile() const { return __vfile; } ExtfsNode * Extfs::orphans() const { return __orphans_i; } ExtfsNode * Extfs::suspiscious_inodes() const { return __suspiscious_i; } ExtfsNode * Extfs::suspiscious_dir() const { return __suspiscious_dir; } void Extfs::__reserved_inodes() { Inode * inode = new Inode(this, __SB, __GD); inodes_t * inode_s = new inodes_t; __first_inodes_nodes = new ExtfsNode("Reserved inodes", 0, __first_node, this, 0, false, this->addBlockPointers); inode->setInode(inode_s); for (unsigned int i = 1; i < __SB->f_non_r_inodes(); ++i) if ((i != ROOT_INODE) && (i != __SB->journal_inode())) { uint64_t addr; ExtfsNode * node; std::ostringstream oss; addr = inode->getInodeByNumber(i); inode->read(addr, inode_s); oss << i; node = createVfsNode(__first_inodes_nodes, oss.str(), addr, (inodes_t *)inode->inode()); node->set_i_nb(i); } } void Extfs::__add_meta_nodes() { ExtfsNode * node; uint64_t gd_size; uint64_t addr; if (__SB->journal_inode()) // create a journal node (if there is a journal) { addr = __root_dir->getInodeByNumber(__SB->journal_inode()); node = createVfsNode(__metadata_node, "Journal", addr, (inodes_t *)__root_dir->recovery()->getJournal()->inode()); node->set_i_nb(__SB->journal_inode()); } new ExtfsRawDataNode("Boot code area", 1024, __metadata_node, this, __SB->offset() - __BOOT_CODE_SIZE); new ExtfsRawDataNode("Superblock", 1024, __metadata_node, this, 1024 + __SB->offset() - __BOOT_CODE_SIZE); gd_size = __SB->group_number() * __GD->GD_size(); gd_size += (__SB->block_size() - gd_size % __SB->block_size()); new ExtfsRawDataNode("Group descriptor table", gd_size, __metadata_node, this, __GD->groupDescriptorAddr()); } void Extfs::__orphan_inodes() { OrphansInodes * orphans_i = new OrphansInodes(__root_dir->i_list()); this->__orphans_i = new ExtfsNode("Orphans inodes", 0, __first_node, this, 0, false, this->addBlockPointers); orphans_i->load(this); } dff-1.3.0+dfsg.1/dff/modules/fs/extfs/extfs.hpp000066400000000000000000000116641217176075400211640ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __EXTFS_HPP__ #define __EXTFS_HPP__ #include #include #include #include #include "variant.hpp" #include "vfs.hpp" #include "mfso.hpp" #include "include/ExtfsNode.h" #include "data_structure/includes/GroupDescriptor.h" #include "data_structure/includes/extfs_struct/inodes.h" #include "data_structure/includes/SuperBlock.h" #define DRIVER_NAME "extfs" #define ROOT_INODE 2 class Extfs : public mfso { /*! \class Extfs. \brief Implementation of the API. When the \c \b Extfs driver is loaded, the \c \b start() method is called. */ public: //! Constructor. Initialize some values. Extfs(); //! Destructor. Free resources. ~Extfs(); /*! \brief Start the driver. The first called method when the extfs driver is executed. It lauches the execution and catches the eventual exceptions which couls occur when the driver is running. \param arg the arguments of extfs */ virtual void start(std::map args); /*! \brief Lauch the driver. In this method all the options are parsed and the proper method called. \param arg arguments passed to the driver */ void launch(std::map args); /*! \brief Initialize the driver. The first thing the \c \b start() method does is trying to read the superblock which is located at byte 1024 of the file system. Once the super block has been read, the driver can access the \b Group \b Descriptor table to locate the position of inode 2, which is the root directory inode. \param sb_check an option used to force superblock checking \param sb_force_addr an option to force the superblock address on the vfile. \param check_alloc check allocation status */ void init(bool sb_check, uint64_t sb_force_addr); /*! \brief Run driver. \param root_i_nb the number of the root inode. */ void run(uint64_t root_i_nb); /*! \brief Creates a vfs node. The \e \b id of the node is the address of its inode on the vfile. It can be set to \e \b 0. \param parent the parent node. \param name the name of the file. \param id the address of the file's inode. \param inode the inode of the file. \return a pointer to the newly created Node. */ class ExtfsNode * createVfsNode(Node * parent, std::string name, uint64_t id, inodes_t * inode); /*! \brief vfile accessor. \return a pointer to the VFile */ class VFile * vfile() const; /*! \brief Group descriptor. \return a pointer to the GroupDescriptor instance. */ class GroupDescriptor * GD() const; /*! \brief Super block. \return a pointer to a SuperBlock instance. */ class SuperBlock * SB() const; /*! \brief Seek and read. Written for convenience. Seek to address \e \b addr, then read \e \b size bytes and stores the result in \e \b buf. */ void v_seek_read(uint64_t addr, void * buf, uint64_t size); /*! \brief Node accessor. \return a pointer to the vfile node. */ Node * node() const; /*! \brief Orphans accessor. \return a pointer to the orphans inode node. */ ExtfsNode * orphans() const; /*! \brief Suspicious inode accessor. \return a pointer to the suspicious inodes node. */ ExtfsNode * suspiscious_inodes() const; inline bool slack() const { return this->__slack; } /*! \brief Suspiscious directories accessor. \return a pointer to suspiscious directories node. */ ExtfsNode * suspiscious_dir() const; inline uint32_t nb_parsed_inode() const { return __nb_parsed_inode; } inline void for_aiur() { __nb_parsed_inode++; } inline uint32_t alloc_inode() { return __alloc_inode; } void createSlack(Node * node, uint64_t addr); bool addBlockPointers; BlockPointerAttributes* attributeHandler; private: void __reserved_inodes(); void __add_meta_nodes(); void __orphan_inodes(); class Directory * __root_dir; // root directory class GroupDescriptor* __GD; // group descriptor class SuperBlock * __SB; // superblock Node * __node; VFile * __vfile; // vfs bool __slack; bool __fsck; Node * __first_node; ExtfsNode * __fs_node; ExtfsNode * __metadata_node; ExtfsNode * __first_inodes_nodes; ExtfsNode * __orphans_i; ExtfsNode * __suspiscious_i; ExtfsNode * __suspiscious_dir; uint32_t __nb_parsed_inode; uint32_t __alloc_inode; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/extfs.i000066400000000000000000000107131217176075400206170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "pyrun.swg" %module EXTFS %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "mfso.hpp" #include "node.hpp" #include "vfile.hpp" #include "vlink.hpp" #include "extfs.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "extfs.hpp" /* namespace std { }; */ %pythoncode %{ __dff_module_extfs_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId, Parameter class EXTFS(Module): """This module parses extented file system (EXT 2/3/4) and tries to recover deleted data.""" def __init__(self): Module.__init__(self, 'extfs', Extfs) self.conf.addArgument({"name": "file", "description": "file containing an EXT 2, 3 or 4 file system", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "blockpointers", "description": "Add block pointer as extfs extended attributes", "input": Argument.Empty}) self.conf.addArgument({"name": "dont_parse_fs", "description": "Parse the entire file system.", "input": Argument.Empty}) self.conf.addArgument({"name": "ils", "description": "List inodes", "input": Argument.Optional|typeId.String|Argument.Single, "parameters":{"type":Parameter.Editable} }) self.conf.addArgument({"name": "blk", "description": "Block allocation status", "input": Argument.Optional|typeId.String|Argument.Single, "parameters":{"type":Parameter.Editable} }) self.conf.addArgument({"name": "fsstat", "description": "File system statistic", "input": Argument.Empty}) self.conf.addArgument({"name": "istat", "description": "Inode statistics", "input": Argument.Optional|typeId.String|Argument.Single, "parameters": {"type": Parameter.Editable} }) self.conf.addArgument({"name": "fsck", "description": "check if the number of allocated block matches inode's size", "input": Argument.Empty}) self.conf.addArgument({"name": "jstat", "description": "journal statistics", "input": Argument.Empty}) self.conf.addArgument({"name": "slack", "description": "Create slack nodes", "input": Argument.Empty}) self.conf.addArgument({"name": "SB_check", "description": "check superblock validity", "input": Argument.Empty}) self.conf.addArgument({"name": "i_orphans", "description": "Parse orphan inodes", "input": Argument.Empty}) self.conf.addArgument({"name": "root_inode", "description": "Root inode number", "input": Argument.Optional|Argument.Single|typeId.UInt64, "parameters": {"type": Parameter.Editable, "predefined": [2]} }) self.conf.addArgument({"name": "SB_addr", "description": "Super block address specified manualy", "input": Argument.Optional|Argument.Single|typeId.UInt64, "parameters": {"type": Parameter.Editable, "predefined": [1024]} }) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["ext2", "ext3", "ext4"]}) self.tags = "File systems" %} dff-1.3.0+dfsg.1/dff/modules/fs/extfs/fsck.cpp000066400000000000000000000031221217176075400207420ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "include/fsck.h" Fsck::Fsck(inodes_t * inode, VFile * vfile, uint64_t addr) { __inode = inode; __vfile = vfile; __addr = addr; } Fsck::~Fsck() { } void Fsck::run(Extfs * extfs, std::string name) { Inode * inode = new Inode(extfs, extfs->SB(), extfs->GD()); uint64_t size = 0, blk_addr; bool large_file = extfs->SB()->useRoFeatures(SuperBlockStructure::_LARGE_FILE, extfs->SB()->ro_features_flags()); inode->setInode(__inode); // inode->read(__addr, __inode); inode->init(); uint64_t inode_size = inode->getSize(inode->lower_size(), large_file); while ((blk_addr = inode->nextBlock())) size += extfs->SB()->block_size(); if (size < inode_size) std::cout << "the size of node " << name << " is wrong is:" << inode_size << "\ts: " << size << std::endl; else if ((size - inode_size) >= extfs->SB()->block_size()) { std::cout << "the block size of node " << name << " is wrong is: " << inode_size << "\ts: " < * */ #ifndef BLK_LIST_ #define BLK_LIST_ #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "../data_structure/includes/GroupDescriptor.h" #include "../data_structure/includes/SuperBlock.h" #include "vfile.hpp" class BlkList { /*! \class BlkList \brief Display the allocation status of file system blocks. This class is used when the user uses the \e --blk option. It displays, for each block number passed to \e --blk, the allocation status of the block. \note The block's allocation status are in the block bitmap table. The display has the following appearance : \verbatim | | | | \endverbatim For example : \verbatim 42 | Allocated | Group : 0 | Byte addr : 266245 (0x41005) | Bit position : 2 \endverbatim In the previous example, the block 42 is allocated, it is located in the group 0 and the bit defining its location status is the second bit of the byte located at the address 0x41005. */ public : //! Setup some variables. BlkList(GroupDescriptor * GD, SuperBlock * SB, VFile * vfile); //! Free what needs to be freed. ~BlkList(); /* \brief Display block allocation status. This method parse the arguments of the option \e --blk and display the allocation status of the different blocks. \param blk_list the list of block number the user wish to know the allocation status. */ void stat(const std::string & blk_list); /*! \brief block allocation status. \param blk_nb a block number \display print some information if set to True. \return true if the block \e \b blk_nb is allocated, false otherwise. */ bool blk_allocation_status(uint64_t blk_nb); private : GroupDescriptor * __GD; VFile * __vfile; SuperBlock * __SB; uint64_t __begin; uint64_t __end; uint64_t __bit_addr; uint8_t __dec; uint16_t __group; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/CustomAttrib.h000066400000000000000000000027431217176075400235340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __CUSTOM_ATTRIB_H__ #define __CUSTOM_ATTRIB_H__ #include "../data_structure/includes/Inode.h" class CustomAttrib { /*! \class CustomAttrib \brief Vfs node's attributes. This class inheritates attrib. Attributes are used to set some properties to nodes, as the modification time or the size. In case of extfs som other attributes can be set as access rights, file's owner, etc. \sa attrib */ public: CustomAttrib(); virtual ~CustomAttrib(); void setTime(Inode *); void setTime(time_t); void setMode(Inode *); bool setMode(uint16_t, Inode * _inode); void setSetUidGid(Inode *); void setUidGid(Inode *); void setAttr(Inode * inode); std::map imap; std::map smap; private: }; #endif // __CUSTOM_ATTRIB_H__ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/CustomResults.h000066400000000000000000000057651217176075400237570ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef CUSTOMRESULTS_H #define CUSTOMRESULTS_H #include "../data_structure/includes/SuperBlock.h" #include "../data_structure/includes/Inode.h" class CustomResults { public: CustomResults(); //! Destructor. Do nothing. ~CustomResults(); /*! \brief Set extfs results. This method fill in the extfs results with the superblock fields value so the dff user can easilly access them. \param SB a pointer to the \c \b SuperBlock instance. */ void set(Attributes * attr, Inode * inode); /*! \brief File system flags. Build a human-readable string of the file system flags (field \c \b fs_state). \return a string containing the state. */ std::string getFlags(uint16_t flags); Variant * getFlags(const SuperBlock * SB); /*! \brief Error handling. Build a human-readable string of the file system error handling method (field error_handling_method). \param error_handling the error handling method \return the error handling method. */ std::string getErrorHandling(uint16_t error_handling); /*! \brief Creator OS. \param os the os who created the file system. \return the name of the OS who created the file sytem. */ std::string getOs(uint32_t os); /*! \brief Compatible features. \param c_f_flags the compatible fearures flag. \return the list of the compatible features. */ static std::string getCompatibleFeatures(uint32_t c_f_flags); Variant * getCompatibleFeatures(const SuperBlock * SB); /*! \brief incompatible features. \param i_f_flags the incompatible features flag. \return the list of the incompatible features. */ static std::string getIncompatibleFeatures(uint32_t i_f_flags); Variant * getIncompatibleFeatures(const SuperBlock * SB); /*! \brief Read-only features. \param r_o_flag the read only features flag. \return the list of the read-only features. */ static std::string getReadOnlyFeatures(uint32_t r_o_flag); Variant * getReadOnlyFeatures(const SuperBlock * SB); /*! \brief File sytem ID. \param fs_id the file system ID. \return the file system ID. */ std::string getFSID(const uint8_t * fs_id); /*! \brief Add time to results. Add a human readable date in the result's map. \param text the text assiociated with the date. \param t the timestamp we need to insert in the date. */ Variant * add_time(time_t t); }; #endif // CUSTOMRESULTS_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/Directory.h000066400000000000000000000101031217176075400230450ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __DIRECTORY_H__ #define __DIRECTORY_H__ #include #include #include "vfs.hpp" #include "data_structure/includes/Inode.h" #include "data_structure/includes/DirEntry.h" #include "TwoThreeTree.hpp" #include "Journal.h" class FileNameRecovery; class Directory : public Inode { /*! \class Directory. \brief A directory's inode. Inherits \b \c Inode, and contains some specific methods about directories. A directory is like a regular file, the only difference is the file mode. The content of a directory is composed of directory entries (dirent). Dirents contains an inode number and a file name. The root directory of an ext file system is usually located in the inode 2. This class also has a method used to browse the entire FS when the extfs driver is launched : \c \b dirContent(). \c \b dirContent() calls an other method, \c \b searchDirEntries(), to discover what is the content of the directory. \c \b searchDirEntries() does not look for deleted entries, this is up to the \c \b FileNameRecovery class. For each file name, a new node is created on the vfs. When the node is not a regular file his size is set to \e \b 0. \sa DirEntry \sa FileNameRecovery \sa Inode */ public: /*! \brief Constructor. Initialize the journal to \c NULL. If the compatible feature 'has journal' is enabled, instantiate it. Instanciate the recovery class. \param extfs a pointer to the \c \b Extfs instance. \param SB a pointer to the \c \b SuperBlock instance. \param GD a pointer to the GroupsDescripor instance. */ Directory(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD); Directory(const Directory * dir); //! Destructor. Unallocate resources. ~Directory(); /*! \brief Browse a directory content. Search the content of a directory by looking in his contents blocks. Call \c \b searchDirEntries() for each content block. \param parent the parent node \param inode the directory inode */ void dirContent(Node * parent, inodes_t * inode, uint64_t a = 0, uint32_t i_nb = 0); /*! \brief Getting dirents. Read each dirent contained in a directory. Call a recovery method from the class \c \b FileNameRecovery if it discovers some deleted entries. \param content_addr the offset on the vfs \param end_addr the end of the current content block \param parent the parent Node \throw vfsError if something goes wrong. */ uint8_t searchDirEntries(uint64_t content_addr, uint64_t end_addr, Node * parent); /*! \brief Create a new vfs Node. \param inode_addr the address of the inode. \param parent the parent Node. \param name the name of the file. \param inter the inode. \return a pointer to the new created node. */ ExtfsNode * createNewNode(uint64_t inode_addr, Node * parent, const std::string & name, inodes_t * inter); /*! \brief Recovery. \return a pointer to the \c \b FileNameRecovery instance. */ FileNameRecovery * recovery() const; //! Initialization void dir_init(); //! Clean resources. void clean(); TwoThreeTree * i_list() const; private: FileNameRecovery * _recovery; TwoThreeTree * __i_list; }; #endif // __DIRECTORY_H__ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/ExtfsNode.h000066400000000000000000000032661217176075400230140ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef EXTFS_NODE_H_ #define EXTFS_NODE_H_ #include #include #include #include "data_structure/includes/extfs_struct/ext4/extents.h" #include "node.hpp" class Extfs; class Inode; class ExtfsNode : public Node { public: ExtfsNode(std::string name, uint64_t size = 0, Node * parent = NULL, Extfs * fsobj = NULL, uint64_t inode_addr = 0, bool is_root = false, bool add_attribute_blocks = false); ~ExtfsNode(); virtual void fileMapping(FileMapping* fm); //! return NULL if an error occurs. void push_block_pointers(Inode * inode, FileMapping * file_mapping); void set_i_nb(uint64_t i_id); uint64_t i_nb() const; virtual Attributes _attributes(); Inode * read_inode(); private : uint64_t __inode_addr; uint64_t __i_nb; Extfs * __extfs; bool __is_root; }; class BlockPointerAttributes : public AttributesHandler { private: void __block_pointers(Inode * inode, Attributes * attr); void __extents_block(Inode * inode, Attributes * attr); public: BlockPointerAttributes(std::string name); Attributes attributes(class Node*); }; #endif /* EXTFS_NODE_H_ */ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/ExtfsRawDataNode.h000066400000000000000000000016501217176075400242530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef EXTFS_RAW_DATA_NODE #define EXTFS_RAW_DATA_NODE #include "node.hpp" class ExtfsRawDataNode : public Node { public: ExtfsRawDataNode(std::string name, uint64_t size, Node * parent, Extfs * fsobj, uint64_t offset); ~ExtfsRawDataNode(); virtual void fileMapping(FileMapping* fm); private: uint64_t __offset; Node * __node; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/ExtfsSlackNode.hpp000066400000000000000000000020201217176075400243150ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef EXTFS_SLACK_NODE_ # define EXTFS_SLACK_NODE_ #include #include "extfs.hpp" #include "node.hpp" class ExtfsSlackNode : public Node { public: ExtfsSlackNode(std::string name, uint64_t size, Node * parent, Extfs * fsobj, uint64_t inode_addr); ~ExtfsSlackNode(); virtual void fileMapping(FileMapping* fm); private: uint64_t __inode_addr; uint64_t __size; Extfs * __extfs; Inode * read_inode(); }; #endif /* EXTFS_SLACK_NODE_ */ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/ExtfsSymLinkNode.h000066400000000000000000000017531217176075400243220ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef EXTFS_SYMLINK_NODE_H #define EXTFS_SYMLINK_NODE_H #include "node.hpp" #include "../extfs.hpp" class ExtfsSymLinkNode : public Node { public : ExtfsSymLinkNode(std::string name, uint64_t size, Node * parent, Extfs * fsobj, uint64_t offset); ~ExtfsSymLinkNode(); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(); private : uint64_t __offset; Extfs * __extfs; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/FileNameRecovery.h000066400000000000000000000120331217176075400243040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef RECOVERY_H #define RECOVERY_H #include "data_structure/includes/DirEntry.h" #include "Directory.h" #include "../extfs.hpp" class FileNameRecovery { /*! \class FileNameRecovery. \brief Recover deleted files. The class purpose is to retrieve hidden / deleted file names from a given directory. Remember that a directory content is composed of directory entries, themself composed of : \li an inode number \li a file name \li a size pointing to the next directory entry, or to the end of the current content block if it the last allocated directory entry. The size is a multiple of 4, at least as big as the directory entry structure size + the name length When a file is removed, the directory entry containing his name is not deleted. The size of the previous directory entry is modified so it jumps directly to the directory entry following the deleted one. For more precisions, please refer to the \c \b DirEntry class. It is possible to 'guess' where deleted dirents might be, and then recover some file names. Of course these are just guesses and consequently false hits happen sometimes. Notice that this class only retrieve file names, not file content. Indeed, retrieving data from a non allocated inode is quiet different between ext2, ext3 and ext4. On ext2 when a file is deleted, the directory entry is 'hidden' as we already explain and the inode is marked as unallocated in the inode bitmap table. That's all. On ext3, it is the same procedure, but the file size is set to 0 as are the block pointers in the inode. The recovery becomes harder but the journal can be used in some cases. Notice that when a file is deleted MAC time are set to the deletion date and the field 'deletion time' is also set to the deletion date. \sa DirEntry \sa Inode \sa Directory \sa dir_entry_v1 dir_entry_v2 */ public: /*! \brief Constructor. */ FileNameRecovery(Journal * journal); /*! \brief Destructor. */ ~FileNameRecovery(); /*! \brief Names recovery. Recover files name which have been deleted. This method is called only when some directory entries might have been deleted. \param tab a pointer to the dir entry block. \param content_addr the address where the dir entry is on the VFile. \param parent a pointer to the parent node \param dir_inode the inode of the parent directory. \param dir a \c \b DirEntry struct (the current directory entry). \sa DirEntry */ uint8_t deletedFileNames(uint8_t * tab, uint64_t content_addr, Node * parent, Directory * dir_inode, DirEntry * dir); /*! \brief Check a dirent validity. The valid_entry method tries to check a dirent validity. 'tries' because some data could match the condition, without being a dirent. Some false hits must be excpected. \param dir the dirent we are investigating. \return true if the dirent is valid, false otherwise. */ uint8_t valid_entry(DirEntry * dir); /*! \brief Check name validity. A name is considered as invalid if it starts with NULL or if it is "." or "..". Some other checks using the name length and the entry length are done. \param name the name that has to be checked. \param name_len the length of the name set in the dir entry \param entry_len the length of the dir entry \return true if the name is valid, false otherwise. */ bool valid_name(char * name, uint8_t name_len, uint16_t entry_len); /*! \brief Data recovery. \param block_number the number of the file system block we are looking for. \param dir a directory \param dir_e a dir entry \param inode an inode \param parent the parent node. \return a new node */ ExtfsNode * recovery(uint32_t block_number, Directory * dir, DirEntry * dir_e, inodes_t * inode, Node * parent); bool retrieve_inode_direct(inodes_t * inode, uint32_t inode_nb); std::string setDirName(DirEntry * del_dirent, uint8_t * tab, uint64_t pos); ExtfsNode * retrieve_inode(Directory * inode_dir, DirEntry * del_dirent, Node * parent, const std::string & name, inodes_t * inode); //! \return a pointer to the journal instance, or NULL if there are no journal. Journal * getJournal() const; private: Journal * _journal; inodes_t * __inter; std::string __name; uint64_t __addr; }; #endif // RECOVERY_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/FsStat.h000066400000000000000000000125351217176075400223200ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef FSSTAT_H #define FSSTAT_H #include #include "../data_structure/includes/SuperBlock.h" #include "../data_structure/includes/GroupDescriptor.h" class FsStat { /*! \class FsStat \brief File system informations. This class' purpose is to retrieve and display informations about the file system which is under invgestigation. */ public: /*! \brief Constructor. Do nothing. */ FsStat(); /*! \brief Destructor. Do nothing. */ ~FsStat(); /*! \brief Display informations. Display informations on the file system. Can be used with the option --fsstat. \param SB a pointer to the \c \b SuperBlock instance. \param vfile a pointer to the virtual file system. */ void disp(SuperBlock * SB, VFile * vfile); /*! \brief General informations. Display general informations about the file system. \param SB a pointer to the SuperBlock instance. */ void general(SuperBlock * SB); /*! \brief Features. Display the file system features. \param SB a pointer to the SuperBlock instance. */ void features(SuperBlock * SB); /*! \brief Compatible features. Display the compatible features. \param SB a pointer to the SuperBlock instance. */ void compatible_features(SuperBlock * SB); /*! \brief Incompatible features. Display the incompatible features. \param SB a pointer to the SuperBlock instance. */ void incompatible_features(SuperBlock * SB); /*! \brief Read only features. Display the read-only features. \param SB a pointer to the SuperBlock instance. */ void read_only_features(SuperBlock * SB); /*! \brief Block groups. Display informations about block groups. \param SB a pointer to the \c \b SuperBlock instance. \param vfile a pointer to the virtual file system. */ void groupInformations(SuperBlock * SB, VFile * vfile); /*! \brief Inodes range. Calculate the first and last inode number of the group \b \e gr. \param i_nb_gr number of inodes per groups. \param gr group number. \return a pair containing the first and last inodes number of the group. */ std::pair inode_range(uint32_t i_nb_gr, uint32_t gr); /*! \brief Blocks range. Calculate the first and last block number of the group \b \e gr. \param gr the group number. \param b_in_gr the number of blocks per group. \param b_nb the total number of blocks on the file system. \return a pair containing the first and last blocks number of the group. */ std::pair block_range(uint32_t gr, uint32_t b_in_gr, uint32_t b_nb); /*! \brief Inode range. Calculate the first and last inode number of the group \b \e gr \param gr the group number \param SB a pointer to the SuperBlock instance \return a pair containing the first and last inode number of the group. */ std::pair inode_table_range(uint32_t gr, SuperBlock * SB); /*! \brief Data range. Calculate the first and last dat block number of the group \b \e gr \param gr the group number \param b_gr_nb the number of block per groups. \param begin the first data block of the group. \return a pair containing the first and last data block number of the group. */ std::pair d_range(uint32_t gr, uint32_t b_gr_nb, uint32_t begin); /*! \brief Group descriptor. Read the group descriptor table. \param block_size the size of a block. \param vfile a pointer to the virtual file system. \param offset the offset of the super block. \return a pointer to the group descriptor table. */ group_descr_table_t * getGroupDescriptor(uint32_t block_size, VFile * vfile, uint64_t offset); /*! \brief Sparse superblock. \param sparse sparse option, true or false \param gr the group number \param nb_b_b the number of block. */ void sparse_option(bool sparse, uint32_t gr, uint32_t nb_b_b); std::pair sb_gd_backups(bool sparse, uint32_t gr, uint32_t nb_b_b); /*! \brief Unallocated inodes. \param nb_i_gr the number of inodes per groups. \param gr the group number. */ std::string unallocated_inodes(uint32_t nb_i_gr, uint32_t gr, bool display = true); /*! \brief Unallocated blocks. \param nb_b_gr the number of blocks per groups. \param gr the group number. \param nb_blocks the number of blocks on the file system. */ std::string unallocated_blocks(uint32_t nb_b_gr, uint32_t gr, uint32_t nb_blocks, bool display = true); void attr_stat(const SuperBlock * SB, VFile * vfile, Attributes * attr); private: std::string __build_range(std::pair); group_descr_table_t * _gd_table; }; #endif // FSSTAT_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/InodeStat.h000066400000000000000000000056051217176075400230060ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef INODESTAT_H #define INODESTAT_H #include #include "../data_structure/includes/Inode.h" #include "../data_structure/includes/ExtendedAttr.h" //#include "../data_structure/includes/SuperBlock.h" #include "../extfs.hpp" class InodeStat { /*! \class InodeStat \brief Stat about an inode. Display an inode status under the following format: \verbatim dff / > extfs --parent /ext3.test.dd --run no --istat 42 Inode : 42 Group : 0 Allocated Permissions : rw-r--r-- Set UID / GID ? : No / No UID / GID : 1000 / 1000 Extended attribute header : 0 Fragment block : 0 Fragment index : 0 Fragment size : 0 Link number : 8 NFS generation number : 277478324 Accessed : Mon Mar 8 18:06:17 2010 Changed : Mon Mar 8 18:06:17 2010 Modification : Mon Mar 8 18:06:17 2010 Direct blocks : 166 167 168 169 170 171 172 173 174 175 176 177 Single indirect blocks : Double indirect blocks : \endverbatim */ public: //! Constructor. InodeStat(SuperBlock * SB, Extfs * extfs); //! Destructor. ~InodeStat(); /*! \brief Inode stat. Display the stat. \param opt the option passed to the istat command. Must be a list of inode number separated by ,. */ void stat(std::string opt); /*! \brief Inode stat. Display the stat of the inode \b \e inode_nb. \param inode_nb the inode number. */ void stat(uint32_t inode_nb); /*! \brief Display. Display the content (key + value) of the map \b \e attr. \param attr a map containing informations that must be displayed. */ template void display(const std::map & attr); /*! \brief Content block list. Display the content block number of inode \e \b inode. \param inode the inode we want to display content blocks. */ void block_list(Inode * inode); /* \brief Xattr Display extended attr (if any). \param xattr the extended attributes. */ void disp_xattr(ExtendedAttr * xattr); void disp_acl(ExtendedAttr * xattr); private: SuperBlock * _SB; Extfs * _extfs; }; #endif // INODESTAT_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/InodesList.h000066400000000000000000000056611217176075400231730ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef INODESLIST_H #define INODESLIST_H #include #include "../data_structure/includes/SuperBlock.h" #include "../extfs.hpp" class InodesList { /*! \class InodesList \brief Detailed inodes list. This class purpose is to find and display informations about a list of inodes. The option \b \e --ils must be used follow by a range of inode. Examples: \verbatim --ils 1-10 --ils 42 \endverbatim An example of result: \verbatim 42 | Allocated | ?--------- | A : Thu Jan 22 16:05:27 2009 | UID / GID : 0/0 \endverbatim */ public: //!Constructor. InodesList(SuperBlock * SB, VFile * vfile); //! Destructor. Do nothing. ~InodesList(); /*! \brief Parse the option. This method determine the first and last inode number passed to the command \b \e ils and initialize _begin and _end. \param opt the option passed to the command --ils \param nb_inodes the total nimber of inodes on the file system. \throw vfsError if one of the inode number specified on the command line is out of range. */ void list(const std::string & opt, uint32_t nb_inodes) throw (vfsError); /*! \brief Inodes range. \param nb_inodes the total number of inodes on the file system. \return false when the inodes number are out of range, true otherwise. */ bool check_inode_range(uint32_t nb_inodes); /*! \brief Inodes informations. This method call infos() which display the informations for each inodes number between _begin and _end. _begin and _end are included in the range. \param extfs a pointer to the Extfs instance. */ void display(Extfs * extfs); /*! \brief Display informations. Display a line of informations about inode \c \e inode_nb. \param extfs a pointer to the Extfs instance. \param inode_nb the number of the inode we want to analize. */ void infos(Extfs * extfs, uint32_t inode_nb); /*! \brief Display a date. Display a human readable date according to a UNIX time stamp. \param name \param t the timestamp. */ void disp_time(const std::string & name, const uint32_t t); private: uint32_t _begin; uint32_t _end; SuperBlock * _SB; VFile * _vfile; }; #endif // INODESLIST_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/Journal.h000066400000000000000000000121311217176075400225160ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef JOURNAL_H #define JOURNAL_H #include #include #include "../data_structure/includes/extfs_struct/journal.h" #include "../data_structure/includes/Inode.h" class Journal : public Inode { /*! \class Journal \brief The journal of the ext3 file system. This class only concern Ext3 file systems. It inheritates the Inode class. The journal purpose is to make system recoveries faster if it crashes. The journal is used (in most cases) to only save metadata blocks when they are modified (inodes tables, inode bitmap allocation table, etc). By activating I dont remember what option, blocks content can also be saved. Having inodes' backups can be very useful to get lost pointers back by retrieving inodes in their previous state. Each data blocks of the journal contains one file system block, consequently journal blocks should have the same size as file system blocks. The journal size is defined in the journal superblock. The journal acts as round-robin : when the end is reached, it jumps back to the beginning so oldest data are removed while inserting new ones. To make sure the ext3 journal is enabled, check the corresponding compatible-features in the superblock. Usually the journal is located in the inode 8, but this can be modified in the superblock. All journal's structures are defined in the file \e data_structure/extfs_struct/journal.h The journal is made of transactions delimited by a sequence descriptor and a commit block. Each transaction has a unique sequence number. The first block of the journal is the journal superblock (version 1 or 2). The superblock starts with 12 bytes wich are the standard header of the journal. The standard header contains the journal signature in his first 4 bytes : \c \b 0xC03B3998. It also contains a block type and a sequence number in the 8 following bytes. A journal block type can be : \li 1 : a descriptor block \li 2 : a commit block \li 3 / 4 : a superblock v1 / v2 \li 5 : a revoke block A descriptor block starts with the standard journal header, and is followed by descriptors block entries (see the journal_block_entries structure). Each descriptor entry corresponds to a file system block. Following the superblock are transactions, with, at their beginning a descriptor block, followed by blocks backups. The end of a transaction is marked with a commit block. | superblock | descriptor block | .... some metadata blocks .... | commit block | \warning \verbatim The journal data are stored in big endian. \endverbatim */ public: /*! \enum J_BLOCK_TYPE \brief Journal block type. */ enum __J_BLOCK_TYPE { __DESCR_BLOCK = 1, /*!< Descriptor block. */ __COMMIT_BLOCK = 2, /*!< Commit block */ __SB_V1 = 3, /*!< Superblock version 1 */ __SB_V2 = 4, /*!< Superblock version 2 */ __REVOKE_BLOCK = 5 /*!< Revoke block */ }; enum __J_FLAGS { __ESCAPED_JBLK = 0x01, __SAME_UUID = 0x02, __BLK_DELETED = 0x04, __LAST_ENT_DESCR_BLK = 0x08 }; /*! \brief Constructor. \param extfs a pointer to the Extfs instance. \param SB a pointer to the SuperBlock instance. \param GD a pointer to the GroupDescriptor instance. */ Journal(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD); //! \brief Destructor. Do nothing. ~Journal(); /*! \brief Journal initialization. Initialize the journal : read the journal superblock, eventually the superblock reminder if it a version 2 journal and put some values into cache. This method does not throw any exceptions because even if the journal initializarion didn't go well, the driver still can be runned. It is up to the caller to test the return value. \return true if no problem occurs, false otherwise. */ bool init(); /*! \brief Cache. \return a constant reference to the cache map. */ const std::map > & journal_cache() const; /*! \brief Journal superblock. \return a pointer to the journal superblock. \sa journal_superblock */ const journal_superblock * j_super_block() const; private: std::map > __j_cache; journal_superblock * __J_SB; journal_v2_reminder * __J_V2_reminder; private: void caching(); void parseCommitBlocks(uint8_t * j_block, uint32_t j_block_size); void getBlocksAddr(const std::list & b_list); }; #endif // JOURNAL_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/JournalStat.h000066400000000000000000000030721217176075400233560ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef JOURNAL_STAT_ #define JOURNAL_STAT_ #include // auto_ptr<> #include "Journal.h" class JournalStat { /*! \class JournalStat \brief Stat on the ext journal Only available on ext3 and ext4. */ public: //! Constructor. Instanciate a Journal. JournalStat(Extfs * extfs, const SuperBlock * SB, GroupDescriptor * GD); //! Destructor. Do nothing. ~JournalStat(); /*! \brief Journal informations. Display informations about the journal. */ void stat(); /*! \brief Journal list. List journal blocks. */ void jlist(); /*! \brief Commit blocks. Search for commit block in the journal. \param j_block a journal block. \param j_block_size the size in byte of a journal block. \return the number of fs block in the transaction. */ unsigned int commitBlock(uint8_t * j_block, uint32_t j_block_size); private: std::auto_ptr _journal; Extfs * _extfs; const SuperBlock * _SB; }; #endif /* JOURNAL_STAT_ */ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/JournalType.h000066400000000000000000000035131217176075400233640ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef JOURNAL_TYPE_H #define JOURNAL_TYPE_H #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif template class JournalType { /*! \class JournalType \brief Convert journal data to host endian. The journal is stored in big endian. This template class is used to convert the journal's values from big endian to the host endian. It is quiet simple to use. If you read an uint32_t from the journal the conversion will be done as in the following example : \code JournalType ex(val_to_convert); uint32_t whatever = ex.value(); \endcode The conversion is done in the constructor. */ public: /*! \brief Constructor. \param val the value we want to convert. */ JournalType(T val = 0); /*! \brief Converted value. \return the value once it is converted to big endian. */ T value(); /*! \brief set value needing to be converted. \param val the value we want to set. */ void setValue(T val); private: uint16_t _convert_htob16(); uint32_t _convert_htob32(); uint64_t _convert_htob64(); bool _test(); T _convert(); T _value; }; #include "../JournalType.tpp" #endif // JOURNAL_TYPE_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/MfsoAttrib.h000066400000000000000000000020711217176075400231600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef MFSO_ATTRIB #define MFSO_ATTRIB #include "node.hpp" #include "../data_structure/includes/Inode.h" typedef std::map Attributes; class MfsoAttrib { public : MfsoAttrib(); ~MfsoAttrib(); void setAttrs(Inode * inode, Attributes * attr, uint64_t i_nb, uint64_t i_addr); private : void __add_acl(Inode * inode, Attributes * attr); void __add_xtd_attr(Inode * inode, Attributes * attr); void __symlink_path(Inode * inode, Attributes * attr); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/Option.h000066400000000000000000000027741217176075400223700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the proje`ct provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef _OPTION_H_ # define _OPTION_H_ #include "argument.hpp" #include "vfile.hpp" #include "data_structure/includes/SuperBlock.h" #include "data_structure/includes/GroupDescriptor.h" class Option { /*! \class Option \brief Start functionnality depending in input options. */ public : /*! \brief Init. \param arg the list of argument under a key -> value form. \param SB a pointer to the superblock struct \param vfile a pointer to the extfs vfile \param GD a pointer to the group descriptor struct */ Option(std::map arg, SuperBlock * SB, VFile * vfile, GroupDescriptor * GD); ~Option(); /*! \brief get the options and start the functionnnalities. \param extfs a pointer to the extfs structure (mfso object) */ void parse(Extfs * extfs); private : std::map arg; SuperBlock * __SB; VFile * __vfile; GroupDescriptor * __GD; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/OrphansInodes.h000066400000000000000000000030001217176075400236530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef ORPHANS_INODES_H_ #define ORPHANS_INODES_H_ #include "vfile.hpp" #include "TwoThreeTree.hpp" #include "../data_structure/includes/SuperBlock.h" #include "../data_structure/includes/GroupDescriptor.h" #include "../extfs.hpp" class OrphansInodes { /*! \brief Create nodes for orphaned inodes. This class is used to identify orphaned inodes. Orphaned inodes are inodes (allocated or not) that have block pointers but were not be parsed with the rest of the file system. This can happened if the have no parents. */ public : /*! \brief Initialisation \param parsed_i_list the list of the already parsed inodes. */ OrphansInodes(TwoThreeTree * parsed_i_list); //! Do nothing. ~OrphansInodes(); /*! \brief create the nodes for orphaned inodes. \param extfs a pointer to the \e \i mfso object of the module. */ void load(class Extfs * extfs); private : TwoThreeTree * __i_list; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/SymLink.h000066400000000000000000000017501217176075400224770ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef SYMLINK_H #define SYMLINK_H #define EXT4_LINK_MAX 65000 #include "../data_structure/includes/Inode.h" class SymLink : public Inode { public: SymLink(Extfs *, const SuperBlock *, GroupDescriptor * GD = NULL); ~SymLink(); std::string resolveAbsolutePath(const std::string & path, Node * node); Node * find_target(std::string path, Extfs * extfs); private: uint32_t __depth; }; #endif // SYMLINK_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/fsck.h000066400000000000000000000020671217176075400220410ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __FSCK_HPP__ # define __FSCK_HPP__ #include #include "vfs.hpp" #include "data_structure/includes/Inode.h" class Fsck { /* \class Fsck \brief Verify that the size of inode matches the number of occupied blocks. */ public: Fsck(inodes_t * inode, VFile * vfile, uint64_t addr); ~Fsck(); //! run the checks void run(class Extfs * extfs, std::string name); private: VFile * __vfile; inodes_t * __inode; uint64_t __addr; }; #endif /* __FSCK_HPP__ */ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/utils/000077500000000000000000000000001217176075400220755ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/utils/InodeStructure.h000066400000000000000000000112561217176075400252320ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef INODESTRUCTURE_H_ #define INODESTRUCTURE_H_ #include #include "vfs.hpp" #include "../../data_structure/includes/extfs_struct/inodes.h" class InodeStructure { public: InodeStructure(); ~InodeStructure(); void setInode(const inodes_t * inode); /*! \brief Inode structure. \return a pointer to the \c \b inodes_t structure. */ const inodes_t * inode() const; const uint8_t * InodeArray() const; /*! \brief File mode. \return the file mode. \sa inodes_t */ uint16_t file_mode() const; /*! \brief Lower UID \return the lower 16 bits of UID. \sa inodes_t */ uint16_t lower_uid() const; /*! \brief Lower size. \return the lower 16 bits of size. \sa inodes_t */ uint32_t lower_size() const; /*! \brief Access time. \return the access time. \sa inodes_t */ uint32_t access_time() const; /*! \brief Change time. \return the change time. \sa inodes_t */ uint32_t change_time() const; /*! \brief Modification time. \return the modification time. \sa inodes_t */ uint32_t modif_time() const; /*! \brief Deletion time. \return the deletion time. \sa inodes_t */ uint32_t delete_time() const; /*! \brief Lower GID \return The lower 16 bits of GID. \sa inodes_t */ uint16_t lower_gid() const; /*! \brief Number of links. \return the number of links pointing the inode. \sa inodes_t */ uint16_t link_coun() const; /*! \brief Sector count. \return the sector count. \sa inodes_t */ uint32_t sector_count() const; /*! \brief Flags See \c \b inodes_t to have their signification. \return flags \sa inodes_t */ uint32_t flags() const; //! Unused area. uint32_t unused1() const; /*! \brief Direct block pointers. There are 12 direct block pointers per inode. \return the address of the uint32_t array containing the pointers. \sa inodes_t */ const uint32_t * block_pointers() const; /*! \brief Simple indirect block pointer. \return the block number of the simple indirect block pointer. \sa inodes_t */ uint32_t simple_indirect_block_pointer() const; /*! \brief Double indirect block pointer. \return the block number of the double indirect block pointer. \sa inodes_t */ uint32_t double_indirect_block_pointer() const; /*! \brief Simple indirect block pointer. \return the block number of the triple indirect block pointer. \sa inodes_t */ uint32_t triple_indirect_block_pointer() const; /*! \brief NFS generation number. \return the NFS generation number. \sa inodes_t */ uint32_t generation_number_nfs() const; /*! \brief EXtended attribute block. \return the block number of the extended attribute. \sa inodes_t */ uint32_t file_acl_ext_attr() const; /*! \brief Upper 32 bits of size. \return the upper 32 bits of size \sa inodes_t */ uint32_t upper_size_dir_acl() const; /*! \brief Fragment block. \return the address of the fragment block. \sa inodes_t */ uint32_t fragment_addr() const; /*! \brief Fragment index. \return the fragment index in block. \sa inodes_t */ uint8_t fragment_index() const; /*! \brief Fragment size. \return the fragment size. \sa inodes_t */ uint8_t fragment_size() const; //! Unused area. uint16_t unused2() const; /*! \brief Upper uid. \return the upper 16 bits of user ID. \sa inodes_t */ uint16_t upper_uid() const; /*! \brief Upper gid. \return the upper 16 bits of group ID. \sa inodes_t */ uint16_t upper_gid() const; //! Unused area. uint32_t unused3() const; protected: const inodes_t * __inode; const uint8_t * __inode_array; uint64_t __inode_addr; }; #endif // INODESTRUCTURE_H_ dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/utils/InodeUtils.h000066400000000000000000000105711217176075400243310ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef INODEUTILS_H #define INODEUTILS_H #include "vfs.hpp" #include "../../data_structure/includes/GroupDescriptor.h" #include "../../data_structure/includes/SuperBlock.h" class InodeUtils { /*! \class InodeUtils \brief Useful methods. This class provides some useful methods relatives to an inode. \sa Inode. */ public: /*! \brief Constructor Initialize the instance. \param SB a pointer to the SuperBlock instance. \param GD a pointer to the GroupDescriptor instance. \sa SuperBlock \sa GroupDescriptor */ InodeUtils(const SuperBlock * SB = NULL, GroupDescriptor * GD = NULL); //! Destructor. Do nothing. ~InodeUtils(); /*! \brief File size. Calculate and returned the file size. \param l_size the 4 lower bytes of the size. \param h_size the 4 higher bytes of the size. \param large_file a flag set to \c \b true if the file system supports large files, and to \c \b false otherwise. \return the size of the file (in bytes). */ uint64_t getSize(uint32_t l_size, uint32_t h_size = 0, bool large_file = false) const; /*! \brief Get an inode address. Get an inode address on the vfs according to the inode number \b \e nb. \warning The method does not check if the block number is valid. \param nb the inode number we are looking for. \return the address of the inode on the vfile, or \c \b 0 if \e \b nb is equal to \c \b 0. */ uint64_t getInodeByNumber(uint32_t nb); /*! \brief inode allocation status. Determine the inode allocation status using the inode bitmap table. In this table each bits determine the allocation status of an inode. \return true if the inode is allocated, false otherwise. */ bool isAllocated(uint32_t, VFile * vfile); /*! \brief Group number. \return the group number of the inode \b \e inode_number. */ uint16_t groupNumber(uint32_t inode_number); /*! \brief File mode. Build a human readable string of the access rights on the file. Example: \verbatim wr--r--r- \endverbatim The notation is the same as the UNIX one. \param file_mode the file mode. \return access rights on the file. */ std::string mode(uint16_t file_mode); /*! \brief Allocation status. \param inode_number the inode we want to know the allocation status. \param vfile a pointer to the virtual file system. \return the string "Allocated" if the inode is allocated, "Not allocated" otherwise. */ std::string allocationStatus(uint32_t inode_number, VFile * vfile); /*! \brief File type. Return a human readable file type: \li `-' : regular file \li `b' : block special file \li `c' : character special file \li `d' : directory \li `l' : symbolic link \li `p' : FIFO (named pipe) \li `s' : socket \li `?' : some other file type \param file_mode the file mode. \return the file type. */ std::string type(uint16_t file_mode); std::string uid_gid(uint16_t uid, uint16_t gid); std::string set_uid_gid(uint16_t file_mode); /*! \brief Superblock. \return a pointer to a SuperBlock instance \sa SuperBlock */ const SuperBlock * SB() const; /*! \brief Group descriptor. \return a pointer to a GroupDescriptor instance. \sa GroupDescriptor */ GroupDescriptor * GD() const; /*! \brief File type and mode. \param file_mode the file mode. \return a human readable string of the file mode : dwr--r--r- for example. */ std::string type_mode(uint16_t file_mode); protected: const SuperBlock * _SB; GroupDescriptor * _GD; }; #endif // INODEUTILS_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/utils/SuperBlockUtils.h000066400000000000000000000033341217176075400253430ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef SUPERBLOCKUTILS_H #define SUPERBLOCKUTILS_H #include "node.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif class SuperBlockUtils { public: //! Constructor. Do nothing. SuperBlockUtils(); //! Destructor. Do nothing. ~SuperBlockUtils(); /*! \brief Compatible features. \param feature the feature. \param SB_flag a flag \return true if the file system uses the feature \b \e feature, false otherwise. */ bool useCompatibleFeatures(uint32_t feature, uint32_t SB_flag) const; /*! \brief Incompatible features. \param feature the feature. \param SB_flag a flag \return true if the file system uses the feature \b \e feature, false otherwise. */ bool useRoFeatures(uint32_t feature, uint32_t SB_flag) const; /*! \brief RO features. \param feature the feature. \param SB_flag a flag \return true if the file system uses the feature \b \e feature, false otherwise. */ bool useIncompatibleFeatures(uint32_t feature, uint32_t SB_flag) const; private: }; #endif // SUPERBLOCKUTILS_H dff-1.3.0+dfsg.1/dff/modules/fs/extfs/include/utils/SuperblockStructure.h000066400000000000000000000223031217176075400263000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef SUPERBLOCKSTRUCTURE_H_ #define SUPERBLOCKSTRUCTURE_H_ #include #include "../../data_structure/includes/extfs_struct/super_block.h" #include "vfs.hpp" /*! \def MAX_BLK_SIZE \brief The maximum size of a file system block. */ #define MAX_BLK_SIZE 64536 class SuperBlockStructure { public: /*! \enum FS_STATE \brief File system state. */ enum FS_STATE { _FS_STATE_CLEAN = 0x0001, /*!< The file system is clean. */ _FS_HAS_ERRORS = 0x0002, /*!< The file system has errors. */ _ORPHAN_RECOVERY = 0x0004 /*!< Orphan inodes are being recovered. */ }; /*! \enum ERROR_HANDLING_METHOD \brief Error handling method. */ enum ERROR_HANDLING_METHOD { _ERROR_HANDLING_CONTINUE = 1, /*!< Continue. */ _RO_REMOUNT = 2, /*!< Remount as read only. */ _PANIC = 3 /*!< Oh yeeaah. */ }; /*! \enum OS_CREATOR \brief Operating system who created the file system. */ enum OS_CREATOR { _OS_LINUX, /*!< Linux. */ _OS_GNU_HURD, /*!< GNU Hurd */ _OS_MASIX, /*!< Masix */ _OS_FREE_BSD, /*!< Free BSD */ _OS_LITES /*!< Lites */ }; /*! \enum C_FEATURES \brief Compatible features flag. */ enum C_FEATURES { _COMP_PDIR = 0x0001, /*!< Preallocate directory blocks. Used to reduce fragmentation. */ _COMP_AFS_INODE = 0x0002, /*!< Afs server inode. */ _COMP_HAS_JOURNAL = 0x0004, /*!< The file system uses a journal. */ _COMP_EXT_ATTR = 0x0008, /*!< Inode have extended attributes. */ _COMP_CAN_RESIZE = 0x0010, /*!< File system can resize itself to use bigger partitions. */ _COMP_DIR_HASH_INDEX = 0x0020 /*!< Directories use a hash index. */ }; /*! \enum INC_FEATURES \brief Incompatible features. */ enum INC_FEATURES { _COMPRESSION = 0x0001, /*!< Compression. */ _DIR_FILE_TYPE = 0x0002, /*!< The file type is contained in dirents. */ _NEEDS_RECOVERY = 0x0004, /*!< A recovery is needed by the file system. */ _JOURNAL_DEVICE = 0x0008, /*!< Use a journal device. */ _META_BG = 0x0010, _EXTENTS = 0x0040, _64BITS = 0x0080, _MMP = 0x0100, _FLEX_BG = 0x0200, _EA_INODE = 0x0400, _DIRENT_DATA = 0x1000 }; /*! \enum RO_FEATURES \brief Read-only features. */ enum RO_FEATURES { _SPARSE_SUPERBLOCK = 0x0001, /*!< Sparse group descriptor and superblock. */ _LARGE_FILE = 0x0002, /*!< File system can contain large files. */ _B_TREES = 0x0004, /*!< Directories use b-trees. */ _HUGE_FILE = 0x0008, _GD_CSUM = 0x0010, _DIR_NLINK = 0x0020, _EXTRA_ISIZE = 0x0040 }; //! Constructor. Do nothing. SuperBlockStructure(); //! Desctructor. Do nothing. ~SuperBlockStructure(); //! return a pointer to the \c super_block_t_. super_block_t_* getSuperBlock() const; /*! \brief Inodes number on file system. \return the number of inodes on the file system. \sa super_block_t_ */ uint32_t inodesNumber() const; /*! \brief Blocks number on file system. \return the number of blocks in the file system. \sa super_block_t_ */ uint32_t blocks_number() const; //! Reserved block number. uint32_t r_blocks_number() const; //! Unallocated block number. uint32_t u_blocks_number() const; //! Unallocated inodes number. uint32_t u_inodes_number() const; //! First data block. uint32_t first_block() const; /*! \brief Size of blocks. To get the size, we must shift 1024 to the left. The field block_size of the structure contains the number of places 1024 must be shift: \code uint32_t block_size; block_size = 1024 << _super_block.block_size; \endcode \return the size of a file system block. */ uint32_t block_size() const; //! Size of fragments. uint32_t fragment_size() const; //! Number of blocks per groups. uint32_t block_in_groups_number() const; //! Number of fragments per group. uint32_t fragment_in_group_number() const; //! Number of inodes per group. uint32_t inodes_in_group_number() const; //! Last mount time. uint32_t last_mount_time() const; //! Current mount count. uint32_t last_written_time() const; //! Maximum mount number. uint16_t current_mount_count() const; //! Signature. Must be \b 0xEF53 uint16_t max_mount_count() const; /*! \brief Signature. The signature must be \c 0xEF53. \return the superblock signature. \sa inodes_t */ uint16_t signature() const; /*! \brief File system state. Can take the following values : \li #_FS_STATE_CLEAN \li #_FS_HAS_ERRORS \li #_ORPHAN_RECOVERY \return the file system state. */ uint16_t fs_state() const; /*! \brief Error handling method. Can take the following values : \li #_ERROR_HANDLING_CONTINUE \li #_RO_REMOUNT \li #_PANIC \return the handling method error. */ uint16_t error_handling_method() const; //! Version. uint16_t minor_version() const; //! Time of the last consistency check. uint32_t l_consistency_ct() const; //! Interval between consistency checks. uint32_t consitency_forced_interval() const; /*! \brief OS creator. OS who created the file system. Can take the following values: \li #_OS_LINUX \li #_OS_GNU_HURD \li #_OS_MASIX \li #_OS_FREE_BSD \li #_OS_LITES \return the creator OS. */ uint32_t creator_os() const; //! Version. uint32_t major_version() const; //! UID. uint16_t uid_reserved_block() const; //! GID. uint16_t gid_reserved_block() const; //! First non reserved inode number. uint32_t f_non_r_inodes() const; //! Size of an inode structure. uint16_t inodes_struct_size() const; //! Block group number (if we are in a superblock backup). uint16_t current_block_group() const; /*! \brief Compatible features. Can take the following values : \li #_COMP_PDIR \li #_COMP_AFS_INODE \li #_COMP_HAS_JOURNAL \li #_COMP_EXT_ATTR \li #_COMP_CAN_RESIZE \li #_COMP_DIR_HASH_INDEX \return the field compatible features. */ uint32_t compatible_feature_flags() const; /*! \brief Incompatible features. Can take the following values: \li #_COMPRESSION \li #_DIR_FILE_TYPE \li #_NEEDS_RECOVERY \li #_JOURNAL_DEVICE \return the incompatible features flag. */ uint32_t incompatible_feature_flags() const; /*! \brief Read only features. Can take the following values: \li #_SPARSE_SUPERBLOCK \li #_LARGE_FILE \li #_B_TREES \return the read only features flag. */ uint32_t ro_features_flags() const; //! File system ID. const uint8_t * file_system_ID() const; //! Name of the volume. const uint8_t * volume_name() const; //! Path to where it was last mounted. const uint8_t * path_last_mount() const; //! Allocation algorithm. uint32_t algorithm_bitmap() const; //! Preallocation for file. uint8_t preallocate_blocks_files() const; //! Preallocation for directories. uint8_t preallocate_block_dir() const; //! Unused area. uint16_t unused() const; //! Journal ID. const uint8_t * journal_id() const; //! Journal inode (usually 8). uint32_t journal_inode() const; //! Journal device (feature). uint32_t journal_device() const; //! Orphan inode list number. uint32_t orphan_node_list() const; //! Unused area. const uint32_t * empty() const; private: super_block_t_ * _super_block; uint8_t * __sb_array; }; #endif // SUPERBLOCKSTRUCTURE_H_ dff-1.3.0+dfsg.1/dff/modules/fs/fat/000077500000000000000000000000001217176075400167335ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/fat/CMakeLists.txt000066400000000000000000000014551217176075400215000ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin dff_cpp_module(FATFS CPP_FILES fatfs.cpp bootsector.cpp fat.cpp fattree.cpp fatnodes.cpp entries.cpp SWIG_FILE fatfs.i LINK_LIBRARIES ${ICU_LIBRARIES} exceptions types vfs tree INCLUDE_DIRS ${ICU_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY}/dff/api/tree ) dff-1.3.0+dfsg.1/dff/modules/fs/fat/bootsector.cpp000066400000000000000000000232441217176075400216270ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "bootsector.hpp" BootSector::BootSector() { this->errlog = ""; this->err = 0; } BootSector::~BootSector() { } void BootSector::process(Node *origin, class Fatfs* fs) { this->fs = fs; this->origin = origin; try { this->vfile = this->origin->open(); if (this->vfile->read(&(this->bs), sizeof(bootsector)) == 512) this->fillCtx(); else throw(std::string("cannot read boot sector")); this->vfile->close(); } catch(...) { this->vfile->close(); throw("err"); } } void BootSector::fillSectorSize() { this->ssize = *((uint16_t*)this->bs.ssize); if ((this->ssize != 512) && (this->ssize != 1024) && (this->ssize != 2048) && (this->ssize != 4096)) { this->errlog += "invalid sector size field\n"; this->err |= BADSSIZE; } } void BootSector::fillClusterSize() { this->csize = this->bs.csize; if ((this->csize != 0x01) && (this->csize != 0x02) && (this->csize != 0x04) && (this->csize != 0x08) && (this->csize != 0x10) && (this->csize != 0x20) && (this->csize != 0x40) && (this->csize != 0x80)) { this->errlog += "invalid cluster size field\n"; this->err |= BADCSIZE; } } void BootSector::fillTotalSector() { uint16_t sectors16; uint32_t sectors32; sectors16 = *((uint16_t*)this->bs.sectors16); sectors32 = *((uint32_t*)this->bs.sectors32); if (sectors16 != 0) this->totalsector = (uint32_t)sectors16; else if (sectors32 != 0) this->totalsector = sectors32; else { this->errlog += "total sector field not defined\n"; this->err |= BADTOTALSECTOR; } // if (this->totalsector * this->ssize > this->node->size()) // this->warnlog.push_back("total sector size "); } void BootSector::fillTotalSize() { // uint32_t missingsect; // missingsect = 0; if (((this->err & BADTOTALSECTOR) != BADTOTALSECTOR) && ((this->err & BADSSIZE) != BADSSIZE)) { this->totalsize = (uint64_t)this->totalsector * (uint64_t)this->ssize; if (this->totalsize > this->origin->size()) { //missingsect = (this->totalsize - this->origin->size()) / (uint64_t)this->ssize; this->errlog += "total size exceeds node size\n"; } } } void BootSector::fillReserved() { this->reserved = *((uint16_t*)this->bs.reserved); if (((this->err & BADTOTALSECTOR) != BADTOTALSECTOR) && (this->reserved > this->totalsector)) { this->errlog += "number of reserved sector(s) exceeds total number of sectors\n"; this->err |= BADRESERVED; } } //if numfat setted to 0, search for FAT pattern void BootSector::fillSectorPerFat() { uint16_t sectperfat16; uint32_t sectperfat32; this->sectperfat = 0; sectperfat16 = *((uint16_t*)this->bs.sectperfat16); sectperfat32 = *((uint32_t*)this->bs.a.f32.sectperfat32); if (sectperfat16 != 0) this->sectperfat = (uint32_t)sectperfat16; else if (sectperfat32 != 0) this->sectperfat = sectperfat32; else { this->errlog += "total sector per fat not defined\n"; this->err |= BADSECTPERFAT; } if (((this->err & BADTOTALSECTOR) != BADTOTALSECTOR) && (this->sectperfat > this->totalsector)) { this->errlog += "total number of sector(s) per fat exceeds total number of sectors\n"; this->err |= BADSECTPERFAT; } } void BootSector::fillNumberOfFat() { this->numfat = this->bs.numfat; if (this->numfat == 0) { this->errlog += "number of fat not defined\n"; this->err |= BADNUMFAT; } if (((this->err & BADTOTALSECTOR) != BADTOTALSECTOR) && ((this->err & BADSECTPERFAT) != BADSECTPERFAT) && ((this->numfat * this->sectperfat) > this->totalsector)) { this->errlog += "total number of sector allocated for FAT(s) exceeds total number of sectors\n"; this->err |= BADNUMFAT; } } void BootSector::fillNumRoot() { this->numroot = *((uint16_t*)this->bs.numroot); // if (((this->fattype == 12) || (this->fattype == 16)) && (this->numroot < 2)) // . and .. entries // { // this->err |= BADNUMROOT; // this->errlog += "total number of entries in root directory less than 2 (. and .. entries)\n"; // } // else if (((this->numroot * 32) / this->ssize) > this->totalsector) // { // this->err |= BADNUMROOT; // this->errlog += "total number of entries in root directory exceeds total number of sector\n"; // } } void BootSector::fillFatType() { this->rootdirsector = ((this->numroot * 32) + (this->ssize - 1)) / this->ssize; this->rootdirsize = (this->numroot * 32); this->datasector = this->reserved + (this->numfat * this->sectperfat) + this->rootdirsector; this->totaldatasector = this->totalsector - (this->reserved + (this->numfat * this->sectperfat) + this->rootdirsector); this->totalcluster = this->totaldatasector / this->csize; this->firstfatoffset = this->reserved * this->ssize; if(this->totalcluster < 4085) this->fattype = 12; else if(this->totalcluster < 65525) this->fattype = 16; else this->fattype = 32; } void BootSector::fillExtended() { this->totalsize = (uint64_t)this->totalsector * this->ssize; this->totaldatasize = (uint64_t)this->totaldatasector * this->ssize; if (this->fattype == 32) { this->vol_id = *((uint32_t*)this->bs.a.f32.vol_id); memcpy(this->vol_lab, this->bs.a.f32.vol_lab, 11); memcpy(this->fs_type, this->bs.a.f32.fs_type, 8); this->rootclust = *((uint32_t*)this->bs.a.f32.rootclust); this->ext_flag = *((uint16_t*)this->bs.a.f32.ext_flag); this->fs_ver = *((uint16_t*)this->bs.a.f32.fs_ver); this->fsinfo = *((uint16_t*)this->bs.a.f32.fsinfo); this->bs_backup = *((uint16_t*)this->bs.a.f32.bs_backup); this->drvnum = this->bs.a.f32.drvnum; this->rootdiroffset = ((this->rootclust - 2) * this->csize) + this->datasector * this->ssize; this->dataoffset = this->reserved * this->ssize + this->fatsize * this->numfat; } else { this->vol_id = *((uint32_t*)this->bs.a.f16.vol_id); memcpy(this->vol_lab, this->bs.a.f16.vol_lab, 11); memcpy(this->fs_type, this->bs.a.f16.fs_type, 8); this->rootdiroffset = this->firstfatoffset + this->fatsize * this->numfat; this->dataoffset = this->firstfatoffset + this->fatsize * this->numfat + rootdirsector * this->ssize; } } void BootSector::fillCtx() { memcpy(this->oemname, this->bs.oemname, 8); this->fillSectorSize(); this->fillClusterSize(); this->fillTotalSector(); this->fillReserved(); this->fillSectorPerFat(); this->fillNumberOfFat(); this->fillNumRoot(); this->prevsect = *((uint32_t*)this->bs.prevsect); if (this->err != 0) { //std::cout << "error: " << this->errlog << std::endl; throw("bad bootsector"); } else { this->fatsize = this->sectperfat * this->ssize; this->fillFatType(); this->fillExtended(); this->fs->res["fat type"] = Variant_p(new Variant(this->fattype)); this->fs->res["oemname"] = Variant_p(new Variant(this->oemname)); this->fs->res["sector size"] = Variant_p(new Variant(this->ssize)); this->fs->res["sectors per cluster"] = Variant_p(new Variant(this->csize)); this->fs->res["reserved cluster"] = Variant_p(new Variant(this->reserved)); this->fs->res["number of fat"] = Variant_p(new Variant(this->numfat)); this->fs->res["number of entries in root directory"] = Variant_p(new Variant(this->numroot)); this->fs->res["number of sectors before FS partition"] = Variant_p(new Variant(this->prevsect)); this->fs->res["volume id"] = Variant_p(new Variant(this->vol_id)); this->fs->res["volume label"] = Variant_p(new Variant(this->vol_lab)); this->fs->res["FS type"] = Variant_p(new Variant(this->fs_type)); this->fs->res["root cluster"] = Variant_p(new Variant(this->rootclust)); this->fs->res["total sectors for data"] = Variant_p(new Variant(this->totaldatasector)); this->fs->res["total sectors"] = Variant_p(new Variant(this->totalsector)); this->fs->res["sectors per fat"] = Variant_p(new Variant(this->sectperfat)); this->fs->res["total clusters"] = Variant_p(new Variant(this->totalcluster)); this->fs->res["first sector of root directory"] = Variant_p(new Variant(this->rootdirsector)); this->fs->res["offset of first fat"] = Variant_p(new Variant(this->firstfatoffset)); this->fs->res["offset of root directory"] = Variant_p(new Variant(this->rootdiroffset)); this->fs->res["size of root directory"] = Variant_p(new Variant(this->rootdirsize)); this->fs->res["start offset of data"] = Variant_p(new Variant(this->dataoffset)); this->fs->res["first sector of data"] = Variant_p(new Variant(this->datasector)); this->fs->res["size of fat"] = Variant_p(new Variant(this->fatsize)); this->fs->res["total size"] = Variant_p(new Variant(this->totalsize)); this->fs->res["total data size"] = Variant_p(new Variant(this->totaldatasize)); } } //Further implementation: // - create translation based on endianness // void BootSector::createCtx() // { // uint32_t rootdirsector; // } // bool bootSector::DetermineFatType() // { // } // bsctx* bootSector::getBootSectorContext() // { // return (this->ctx); // } dff-1.3.0+dfsg.1/dff/modules/fs/fat/bootsector.hpp000066400000000000000000000073511217176075400216350ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __BOOTSECTOR_HPP__ #define __BOOTSECTOR_HPP__ #include "vfile.hpp" #include "fatfs.hpp" #include #include typedef struct { uint8_t f1[3]; char oemname[8]; uint8_t ssize[2]; /* sector size in bytes */ uint8_t csize; /* cluster size in sectors */ uint8_t reserved[2]; /* number of reserved sectors for boot sectors */ uint8_t numfat; /* Number of FATs */ uint8_t numroot[2]; /* Number of Root dentries */ uint8_t sectors16[2]; /* number of sectors in FS */ uint8_t f2[1]; uint8_t sectperfat16[2]; /* size of FAT */ uint8_t f3[4]; uint8_t prevsect[4]; /* number of sectors before FS partition */ uint8_t sectors32[4]; /* 32-bit value of number of FS sectors */ /* The following are different for fat12/fat16 and fat32 */ union { struct { uint8_t f5[3]; uint8_t vol_id[4]; uint8_t vol_lab[11]; uint8_t fs_type[8]; uint8_t f6[448]; } f16; struct { uint8_t sectperfat32[4]; uint8_t ext_flag[2]; uint8_t fs_ver[2]; uint8_t rootclust[4]; /* cluster where root directory is stored */ uint8_t fsinfo[2]; /* TSK_FS_INFO Location */ uint8_t bs_backup[2]; /* sector of backup of boot sector */ uint8_t f5[12]; uint8_t drvnum; uint8_t f6[2]; uint8_t vol_id[4]; uint8_t vol_lab[11]; uint8_t fs_type[8]; uint8_t f7[420]; } f32; } a; uint8_t magic[2]; /* MAGIC for all versions */ } bootsector; typedef struct { char oemname[8]; uint16_t ssize; uint8_t csize; uint16_t reserved; uint8_t numfat; uint16_t numroot; uint32_t prevsect; uint32_t vol_id; uint8_t vol_lab[11]; uint8_t fs_type[8]; //Only for Fat32 uint16_t ext_flag; uint16_t fs_ver; uint32_t rootclust; uint16_t fsinfo; uint16_t bs_backup; uint8_t drvnum; //total sector count uint32_t totaldatasector; uint32_t totalsector; uint32_t sectperfat; uint32_t totalcluster; //precomputed values based on bytes per sector and cluster size uint32_t rootdirsector; uint64_t firstfatoffset; uint64_t rootdiroffset; uint32_t rootdirsize; uint64_t dataoffset; uint32_t datasector; uint32_t fatsize; uint64_t totalsize; uint64_t totaldatasize; //fat type based on computation uint8_t fattype; } fsctx; #define BADSSIZE 0x01 #define BADCSIZE 0x02 #define BADTOTALSECTOR 0x04 #define BADRESERVED 0x08 #define BADNUMFAT 0x10 #define BADSECTPERFAT 0x20 #define BADNUMROOT 0x40 //#define BAD 0x70 #define ERRFATTYPEMASK 0x7F class BootSector: public fsctx { private: uint8_t err; std::string errlog; bootsector bs; Node* origin; VFile* vfile; class Fatfs* fs; void fillSectorSize(); void fillClusterSize(); void fillTotalSector(); void fillTotalSize(); void fillReserved(); void fillSectorPerFat(); void fillNumberOfFat(); void fillNumRoot(); void fillFatType(); void fillExtended(); void fillCtx(); // bool checkBootSectorFields(); // bool fillBaseParameters(); // bool fillExtendedParameters(); public: BootSector(); ~BootSector(); void process(Node* node, class Fatfs* fs); void addResults(); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/fat/entries.cpp000066400000000000000000000154071217176075400211170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "entries.hpp" EntriesManager::EntriesManager(uint8_t fattype) { this->fattype = fattype; this->c = NULL; } EntriesManager::~EntriesManager() { } // void EntriesManager::setContext(Node* origin) // { // } // void EntriesManager::setContext(uint8_t fattype) // { // this->fattype = fattype; // } lfnentry* EntriesManager::toLfn(uint8_t* entry) { lfnentry* lfn; lfn = new lfnentry; lfn->order = entry[0]; memcpy(lfn->first, entry+1, 10); lfn->attributes = entry[11]; lfn->reserved = entry[12]; lfn->checksum = entry[13]; memcpy(lfn->second, entry+14, 12); memcpy(&(lfn->cluster), entry+26, 2); memcpy(lfn->third, entry+28, 4); return lfn; } dosentry* EntriesManager::toDos(uint8_t* entry) { dosentry* dos; dos = new dosentry; memcpy(dos->name, entry, 8); memcpy(dos->ext, entry+8, 3); dos->attributes = entry[11]; dos->ntres = entry[12]; dos->ctimetenth = entry[13]; memcpy(&(dos->ctime), entry+14, 2); memcpy(&(dos->cdate), entry+16, 2); memcpy(&(dos->adate), entry+18, 2); memcpy(&(dos->clusthigh), entry+20, 2); memcpy(&(dos->mtime), entry+22, 2); memcpy(&(dos->mdate), entry+24, 2); memcpy(&(dos->clustlow), entry+26, 2); memcpy(&(dos->size), entry+28, 4); return dos; } void EntriesManager::updateLfnName(lfnentry* lfn) { int i; std::string name; uint16_t *ptr; i = 0; name = ""; ptr = (uint16_t*)lfn->first; i = 0; while (i != 5 && *ptr != 0 && *ptr != 0xFFFF) { ptr++; i++; } if (i != 0) name.append((char*)lfn->first, i*2); ptr = (uint16_t*)lfn->second; i = 0; while (i != 6 && *ptr != 0 && *ptr != 0xFFFF) { ptr++; i++; } if (i != 0) name.append((char*)lfn->second, i*2); ptr = (uint16_t*)lfn->third; i = 0; while (i != 2 && *ptr != 0 && *ptr != 0xFFFF) { ptr++; i++; } if (i != 0) name.append((char*)lfn->third, i*2); this->c->lfnname = name + this->c->lfnname; } bool EntriesManager::isDosName(uint8_t* buff) { int i; if ((buff[0] != 0xE5) && (buff[0] != '.') && (FATFS_IS_83_NAME(buff[0]) == 0)) return false; if (buff[0] == 0x20) return false; if ((memcmp(buff, "\x2E\x20\x20\x20\x20\x20\x20\x20", 8) == 0) || (memcmp(buff, "\x2E\x2E\x20\x20\x20\x20\x20\x20", 8) == 0)) return false; else { for (i = 2; i != 8; i++) if (FATFS_IS_83_NAME(buff[i]) == 0) return false; for (i = 0; i != 3; i++) if (FATFS_IS_83_EXT(buff[8+i]) == 0) return false; } return true; } bool EntriesManager::isDosEntry(uint8_t* buff) { if (*(buff+11) & ATTR_NORMAL) { if ((*(buff+11) & ATTR_VOLUME) || (*(buff+11) & ATTR_DIRECTORY)) return false; } if (*(buff+11) & ATTR_VOLUME) { if ((*(buff+11) & ATTR_DIRECTORY) || (*(buff+11) & ATTR_READ_ONLY) || (*(buff+11) & ATTR_ARCHIVE)) return false; } return this->isDosName(buff); } std::string EntriesManager::formatDosname(dosentry* dos) { std::string name; int i; name = ""; i = 0; if (dos->name[0] == 0xe5) { name += "_"; i = 1; } while ((i != 8) && (dos->name[i] != '\x20')) { if (((dos->ntres & FATFS_CASE_LOWER_BASE) == FATFS_CASE_LOWER_BASE) && (dos->name[i] >= 'A') && (dos->name[i] <= 'Z')) name += dos->name[i] + 32; else name += dos->name[i]; i++; } i = 0; while ((i != 3) && (dos->ext[i] != '\x20')) { if (i == 0) name += "."; if (((dos->ntres & FATFS_CASE_LOWER_EXT) == FATFS_CASE_LOWER_EXT) && (dos->ext[i] >= 'A') && (dos->ext[i] <= 'Z')) name += dos->ext[i] + 32; else name += dos->ext[i]; i++; } return name; } void EntriesManager::setDosName(dosentry* dos) { this->c->dosname = this->formatDosname(dos); } bool EntriesManager::isChecksumValid(uint8_t* buff) { uint8_t sum; int i; if (this->c->lfnmetaoffset != 0) { for (i = 11; i; i--) sum = ((sum & 1) << 7) + (sum >> 1) + *buff++; if (sum == this->c->checksum) return true; else return false; } else return true; } bool EntriesManager::push(uint8_t* buff, uint64_t offset) { lfnentry* lfn; dosentry* dos; if (this->c == NULL) this->initCtx(); if (*(buff+11) > 0x3F) return false; if (((*(buff+11)) & ATTR_LFN) == ATTR_LFN) { if ((*(buff) > (FATFS_LFN_SEQ_FIRST | 0x0f)) && ((*buff) != 0xE5)) return false; else { lfn = this->toLfn(buff); if (this->c->lfnmetaoffset == 0) { //this->c->checksum = *(buff+13); this->c->lfnmetaoffset = offset; } // else if (this->c->checksum == *(buff+13)) this->updateLfnName(lfn); // else // { // //printf("bad checksum between: 0x%llx / 0x%llx -- prev checksum: %d -- current checksum: %d\n", this->c->lfnmetaoffset, offset, this->c->checksum, *(buff+13)); // this->c->checksum = 0; // this->c->lfnmetaoffset = 0; // this->c->lfnname = ""; // } delete lfn; return false; } } else { if (this->isDosEntry(buff)) { // if (this->isChecksumValid(buff)) // { // this->c->lfnmetaoffset = 0; // this->c->lfnname = ""; // } this->c->dosmetaoffset = offset; dos = this->toDos(buff); this->setDosName(dos); if ((dos->attributes & ATTR_VOLUME) == ATTR_VOLUME) this->c->volume = true; if ((dos->attributes & ATTR_DIRECTORY) == ATTR_DIRECTORY) { // if (dos->size != 0) // this->c->valid = false; this->c->dir = true; } if (dos->name[0] == 0xE5) this->c->deleted = true; this->c->size = dos->size; if ((this->fattype == 12) || (this->fattype == 16)) this->c->cluster = dos->clustlow; else { this->c->cluster = dos->clustlow; this->c->cluster |= (dos->clusthigh << 16); } delete dos; return true; } else return false; } } void EntriesManager::initCtx() { this->c = new ctx; this->c->valid = true; this->c->dosname = ""; this->c->lfnname = ""; this->c->dir = false; this->c->deleted = false; this->c->volume = false; this->c->size = 0; this->c->cluster = 0; this->c->lfnmetaoffset = 0; this->c->dosmetaoffset = 0; } // void EntriesManager::convert() // { // } ctx* EntriesManager::fetchCtx() { ctx* ret; ret = this->c; this->c = NULL; return ret; } dff-1.3.0+dfsg.1/dff/modules/fs/fat/entries.hpp000066400000000000000000000113521217176075400211170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __LFNENTRY_HPP__ #define __LFNENTRY_HPP__ #include "node.hpp" #include "vfile.hpp" #define ATTR_NORMAL 0x00 #define ATTR_READ_ONLY 0x01 #define ATTR_HIDDEN 0x02 #define ATTR_SYSTEM 0x04 #define ATTR_VOLUME 0x08 #define ATTR_DIRECTORY 0x10 #define ATTR_ARCHIVE 0x20 #define ATTR_LFN 0x0f #define ATTR_ALL 0x3f #define FATFS_LFN_SEQ_FIRST 0x40 #define FATFS_CASE_LOWER_BASE 0x08 /* base is lower case */ #define FATFS_CASE_LOWER_EXT 0x10 /* extension is lower case */ #define FATFS_CASE_LOWER_ALL 0x18 /* both are lower */ #define FATFS_IS_83_NAME(c) \ ((((c) < 0x20) || \ ((c) == 0x22) || \ (((c) >= 0x2a) && ((c) <= 0x2c)) || \ ((c) == 0x2e) || \ ((c) == 0x2f) || \ (((c) >= 0x3a) && ((c) <= 0x3f)) || \ (((c) >= 0x5b) && ((c) <= 0x5d)) || \ ((c) == 0x7c)) == 0) #define FATFS_IS_83_EXT(c) \ (FATFS_IS_83_NAME((c)) && ((c) < 0x7f)) typedef struct s_dosentry { uint8_t name[8]; uint8_t ext[3]; uint8_t attributes; uint8_t ntres; uint8_t ctimetenth; uint16_t ctime; uint16_t cdate; uint16_t adate; uint16_t clusthigh; uint16_t mtime; uint16_t mdate; uint16_t clustlow; uint32_t size; } dosentry; typedef struct s_lfnentry { uint8_t order; uint8_t first[10]; uint8_t attributes; uint8_t reserved; uint8_t checksum; uint8_t second[12]; uint16_t cluster; uint8_t third[4]; } lfnentry; typedef struct s_ctx { bool valid; std::string dosname; std::string lfnname; uint32_t lfncount; uint8_t checksum; bool dir; bool deleted; bool volume; uint32_t size; uint32_t cluster; uint64_t lfnmetaoffset; uint64_t dosmetaoffset; } ctx; typedef struct s_decodedentry { std::string dosname; std::string longfilename; bool dir; bool readonly; bool hidden; bool system; bool archive; bool deleted; bool orphaned; vtime* mtime; vtime* atime; vtime* ctime; uint32_t cluster; uint32_t size; uint64_t lfnstart; uint64_t dosstart; } decodedentry; class EntryConverter { private: public: EntryConverter(); virtual ~EntryConverter(); }; // class LfnEntry // { // public: // LfnEntry(); // ~LfnEntry(); // }; class EntriesManager { private: ctx* c; uint8_t fattype; // uint64_t lfnmetaoffset; // uint64_t dosmetaoffset; //std::vector lfns; // std::string lfnname; // std::string dosname; bool isChecksumValid(uint8_t* buff); bool isDosEntry(uint8_t* buff); bool isDosName(uint8_t* buff); void updateLfnName(lfnentry* lfn); void setDosName(dosentry* dos); lfnentry* toLfn(uint8_t* entry); //lfnentry* LfnFromOffset(uint64_t offset); //dosentry* DosFromOffset(uint64_t* offset); //void convert(uint8_t* entry, uint64_t offset); void initCtx(); public: EntriesManager(uint8_t fattype); ~EntriesManager(); //void setContext(Node* origin); std::string formatDosname(dosentry* dos); dosentry* toDos(uint8_t* entry); bool push(uint8_t* buff, uint64_t offset); ctx* fetchCtx(); //compmeta* fetchCompleteMeta(); //explicitedentry* explicitedEntry(uint64_t offset); }; // typedef struct // { // uint8_t name[8]; // uint8_t ext[3]; // uint8_t attrib; // uint8_t lowercase; // uint8_t ctimeten; /* create times */ // uint8_t ctime[2]; // uint8_t cdate[2]; // uint8_t adate[2]; /* access time */ // uint8_t highclust[2]; // uint8_t wtime[2]; /* last write time */ // uint8_t wdate[2]; // uint8_t startclust[2]; // uint8_t size[4]; // } dosentry; // typedef struct // { // uint8_t name[8]; // uint8_t ext[3]; // uint8_t attrib; // uint8_t lowercase; // uint8_t ctimeten; /* create times */ // uint16_t ctime; // uint16_t cdate; // uint16_t adate; /* access time */ // uint16_t highclust; // uint16_t wtime; /* last write time */ // uint16_t wdate; // uint16_t startclust; // uint32_t size; // } dectx; // class Dos // { // private: // bool sanitizeEntry(dectx* ctx); // dectx* createDentryCtx(Node* n); // public: // Dos(); // ~Dos(); // }; // class Entry: public Dos, LongFileName // { // public: // Entry(); // ~Entry(); // }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/fat/fat.cpp000066400000000000000000000355371217176075400202260ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "fat.hpp" FileAllocationTableNode::FileAllocationTableNode(std::string name, uint64_t size, Node* parent, class Fatfs* fatfs) : Node(name, size, parent, fatfs) { } FileAllocationTableNode::~FileAllocationTableNode() { } void FileAllocationTableNode::setContext(FileAllocationTable* fat, uint8_t fatnum) { this->__fat = fat; this->__fatnum = fatnum; } void FileAllocationTableNode::fileMapping(FileMapping* fm) { this->__fat->fileMapping(fm, this->__fatnum); } Attributes FileAllocationTableNode::_attributes(void) { return this->__fat->attributes(this->__fatnum); } Attributes FileAllocationTableNode::dataType(void) { Attributes dtype; dtype["fatfs"] = Variant_p(new Variant(std::string("File allocation table"))); return dtype; } FileAllocationTable::FileAllocationTable() { this->vfile = NULL; } // FileAllocationTable::FileAllocationTable(fsinfo* ctx, mfso* fsobj, Node* parent): Decoder("Fat module File Allocation Table reader") // { // this->ctx = ctx; // this->fsobj = fsobj; // } FileAllocationTable::~FileAllocationTable() { if (this->vfile != NULL) { //XXX VFile dtor must close the opened file... this->vfile->close(); delete this->vfile; } } void FileAllocationTable::setContext(Node* origin, Fatfs* fatfs) { std::stringstream sstr; uint64_t offset; uint32_t freeclust; uint32_t badclust; uint32_t alloclust; uint32_t cidx, clustent; this->origin = origin; this->fatfs = fatfs; this->bs = fatfs->bs; offset = 0; try { this->vfile = this->origin->open(); if ((this->bs->fatsize < 1024*1024*10) && ((this->__fat = malloc(this->bs->fatsize)) != NULL)) { offset = this->bs->firstfatoffset; this->vfile->seek(offset); if (this->vfile->read(this->__fat, this->bs->fatsize) != (int32_t)this->bs->fatsize) throw (std::string("cannot read fat")); } else this->__fat = NULL; for (uint8_t i = 0; i != this->bs->numfat; i++) { sstr << "gathering information for FAT " << i+1 << " / " << this->bs->numfat; this->fatfs->stateinfo = sstr.str(); freeclust = 0; badclust = 0; alloclust = 0; for (cidx = 0; cidx != this->bs->totalcluster; cidx++) { clustent = this->clusterEntry(cidx, i); if (this->isFreeCluster(clustent)) freeclust++; else if (this->isBadCluster(clustent)) badclust++; else alloclust++; } this->__freeClustCount[i] = freeclust; this->__badClustCount[i] = badclust; this->__allocClustCount[i] = alloclust; sstr.str(""); } } catch(vfsError e) { this->vfile = NULL; throw("Fat module: FileAllocationTable error while opening node" + e.error); } } uint64_t FileAllocationTable::clusterOffsetInFat(uint64_t cluster, uint8_t which) { uint64_t baseoffset; uint64_t idx; uint64_t fatsectnum; uint64_t fatentryoffset; baseoffset = this->bs->firstfatoffset + (uint64_t)which * (uint64_t)this->bs->fatsize; if (this->bs->fattype == 12) idx = cluster + cluster / 2; if (this->bs->fattype == 16) idx = cluster * 2; if (this->bs->fattype == 32) idx = cluster * 4; fatsectnum = idx / this->bs->ssize; fatentryoffset = idx % this->bs->ssize; idx = fatsectnum * this->bs->ssize + fatentryoffset; return (baseoffset + idx); } uint32_t FileAllocationTable::ioCluster12(uint32_t current, uint8_t which) { uint16_t next; uint64_t offset; offset = this->clusterOffsetInFat((uint64_t)current, which); this->vfile->seek(offset); if (this->vfile->read(&next, 2) == 2) return (uint32_t)next; else return 0; } uint32_t FileAllocationTable::ioCluster16(uint32_t current, uint8_t which) { uint16_t next; uint64_t offset; offset = this->clusterOffsetInFat((uint64_t)current, which); this->vfile->seek(offset); if (this->vfile->read(&next, 2) == 2) return (uint32_t)next; else return 0; } uint32_t FileAllocationTable::ioCluster32(uint32_t current, uint8_t which) { uint32_t next; uint64_t offset; offset = this->clusterOffsetInFat((uint64_t)current, which); this->vfile->seek(offset); if (this->vfile->read(&next, 4) == 4) return next; else return 0; } uint32_t FileAllocationTable::cluster12(uint32_t current, uint8_t which) { uint16_t next; uint32_t idx; next = 0; if (which < this->bs->numfat) { if (which == 0 && this->__fat != NULL) { idx = current + current / 2; idx = ((idx / this->bs->ssize) * this->bs->ssize) + (idx % this->bs->ssize); memcpy(&next, (uint8_t*)this->__fat+idx, 2); } else next = this->ioCluster12(current, which); if (current & 0x0001) next = next >> 4; else next &= 0x0FFF; } return (uint32_t)next; } uint32_t FileAllocationTable::cluster16(uint32_t current, uint8_t which) { uint16_t next; next = 0; if (which < this->bs->numfat) { if (which == 0 && this->__fat != NULL) next = *((uint16_t*)this->__fat+current); else next = this->ioCluster16(current, which); } return (uint32_t)next; } uint32_t FileAllocationTable::cluster32(uint32_t current, uint8_t which) { uint32_t next; next = 0; if (which < this->bs->numfat) { if (which == 0 && this->__fat != NULL) next = *((uint32_t*)this->__fat+current); else next = this->ioCluster32(current, which); next &= 0x0FFFFFFF; } return next; } uint32_t FileAllocationTable::clusterEntry(uint32_t current, uint8_t which) { uint32_t next; next = 0; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else if (current > this->bs->totalcluster) throw(vfsError(std::string("Fat module: provided cluster is too high"))); else { if (this->bs->fattype == 12) next = this->cluster12(current, which); if (this->bs->fattype == 16) next = this->cluster16(current, which); if (this->bs->fattype == 32) next = this->cluster32(current, which); } return next; } std::vector FileAllocationTable::clusterChainOffsets(uint32_t cluster, uint8_t which) { std::vector clustersoffset; std::vector clusters; uint64_t offset; uint32_t i; clusters = this->clusterChain(cluster, which); for (i = 0; i != clusters.size(); i++) { offset = this->clusterToOffset(clusters[i]); clustersoffset.push_back(offset); } return clustersoffset; } std::vector FileAllocationTable::clusterChain(uint32_t cluster, uint8_t which) { std::vector clusters; std::set parsed; uint64_t max; uint32_t eoc; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else if (cluster > this->bs->totalcluster) throw(vfsError(std::string("Fat module: provided cluster is too high"))); else { if (this->bs->fattype == 12) eoc = 0x0FF8; if (this->bs->fattype == 16) eoc = 0xFFF8; if (this->bs->fattype == 32) eoc = 0x0FFFFFF8; max = 0; while ((cluster > 1) && (cluster < eoc) && (max < 0xFFFFFFFFL) && !this->isBadCluster(cluster) && (parsed.find(cluster) == parsed.end())) { clusters.push_back(cluster); parsed.insert(cluster); max += this->bs->csize; try { cluster = this->clusterEntry(cluster); } catch(vfsError e) { break; } } } return clusters; } /* /=========================================================\ | For each list*Clusters(uint8_t which), compute a bitmap | \=========================================================/ */ bool FileAllocationTable::isFreeCluster(uint32_t cluster) { return cluster == 0 ? true : false; } bool FileAllocationTable::isBadCluster(uint32_t cluster) { if (this->bs->fattype == 12) return cluster == 0x0FF7 ? true : false; if (this->bs->fattype == 16) return cluster == 0xFFF7 ? true : false; if (this->bs->fattype == 32) return cluster == 0x0FFFFFF7 ? true : false; return false; } bool FileAllocationTable::clusterEntryIsFree(uint32_t cluster, uint8_t which) { if (this->bs->fattype == 12) return (this->cluster12(cluster, which) == 0 ? true : false); if (this->bs->fattype == 16) return (this->cluster16(cluster, which) == 0 ? true : false); if (this->bs->fattype == 32) return (this->cluster32(cluster, which) == 0 ? true : false); return false; } bool FileAllocationTable::clusterEntryIsBad(uint32_t cluster, uint8_t which) { if (this->bs->fattype == 12) return (this->cluster12(cluster, which) == 0x0FF7 ? true : false); if (this->bs->fattype == 16) return (this->cluster16(cluster, which) == 0xFFF7 ? true : false); if (this->bs->fattype == 32) return (this->cluster32(cluster, which) == 0x0FFFFFF7 ? true : false); return false; } std::vector FileAllocationTable::listFreeClustersOffset(uint8_t which) { uint32_t cidx; std::vector freeclusters; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else for (cidx = 0; cidx != this->bs->totalcluster; cidx++) if (this->clusterEntryIsFree(cidx, which)) freeclusters.push_back(this->clusterToOffset(cidx)); return freeclusters; } std::vector FileAllocationTable::listFreeClusters(uint8_t which) { uint32_t cidx; std::vector freeclusters; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else for (cidx = 0; cidx != this->bs->totalcluster; cidx++) if (this->clusterEntryIsFree(cidx, which)) freeclusters.push_back(cidx); return freeclusters; } uint32_t FileAllocationTable::freeClustersCount(uint8_t which) { uint32_t freeclust; uint32_t cidx; std::map::iterator it; freeclust = 0; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else { if ((it = this->__freeClustCount.find(which)) != this->__freeClustCount.end()) freeclust = it->second; else { for (cidx = 0; cidx != this->bs->totalcluster; cidx++) if (this->clusterEntryIsFree(cidx, which)) freeclust++; this->__freeClustCount[which] = freeclust; } } return freeclust; } std::list FileAllocationTable::listAllocatedClusters(uint8_t which) { std::list alloc; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else return alloc; } uint32_t FileAllocationTable::allocatedClustersCount(uint8_t which) { uint32_t cidx; uint32_t alloc; std::map::iterator it; uint32_t clustent; alloc = 0; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else { if ((it = this->__allocClustCount.find(which)) != this->__allocClustCount.end()) alloc = it->second; else { for (cidx = 0; cidx != this->bs->totalcluster; cidx++) { clustent = this->clusterEntry(cidx, which); if (!this->isFreeCluster(clustent) && !this->isBadCluster(clustent)) alloc++; } this->__allocClustCount[which] = alloc; } } return alloc; } std::vector FileAllocationTable::listBadClusters(uint8_t which) { std::vector badclust; uint32_t cidx; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else for (cidx = 0; cidx != this->bs->totalcluster; cidx++) if (this->clusterEntryIsBad(cidx, which)) badclust.push_back(cidx); return badclust; } uint32_t FileAllocationTable::badClustersCount(uint8_t which) { uint32_t badclust = 0; uint32_t cidx; std::map::iterator it; if (which >= this->bs->numfat) throw(vfsError(std::string("Fat module: provided fat number for reading is too high"))); else { if ((it = this->__badClustCount.find(which)) != this->__badClustCount.end()) badclust = it->second; else { for (cidx = 0; cidx != this->bs->totalcluster; cidx++) if (this->clusterEntryIsBad(cidx, which)) badclust++; this->__badClustCount[which] = badclust; } } return badclust; } uint64_t FileAllocationTable::clusterToOffset(uint32_t cluster) { uint64_t offset; if (this->bs->fattype == 12) cluster &= FATFS_12_MASK; if (this->bs->fattype == 16) cluster &= FATFS_16_MASK; if (this->bs->fattype == 32) cluster &= FATFS_32_MASK; offset = ((uint64_t)cluster - 2) * this->bs->csize * this->bs->ssize + this->bs->dataoffset; return offset; } uint32_t FileAllocationTable::offsetToCluster(uint64_t offset) { //FIXME return 0; } void FileAllocationTable::diffFats() { } void FileAllocationTable::makeNodes(Node* parent) { FileAllocationTableNode* node; std::stringstream sstr; uint8_t i; for (i = 0; i != this->bs->numfat; i++) { sstr << "FAT " << i + 1; node = new FileAllocationTableNode(sstr.str(), this->bs->fatsize, parent, this->fatfs); //this->__fclusterscount.push_back(this->freeClustersCount(i)); //this->__aclusterscount.push_back(this->allocatedClustersCount(i)); node->setContext(this, i); sstr.str(""); } } void FileAllocationTable::fileMapping(FileMapping* fm, uint8_t which) { uint64_t offset; offset = this->bs->firstfatoffset + (uint64_t)which * (uint64_t)this->bs->fatsize; fm->push(0, this->bs->fatsize, this->origin, offset); } Attributes FileAllocationTable::attributes(uint8_t which) { Attributes attrs; uint64_t clustsize; uint32_t badclust; clustsize = (uint64_t)this->bs->csize * this->bs->ssize; if (which < this->bs->numfat) { attrs["free clusters"] = Variant_p(new Variant(this->freeClustersCount(which))); attrs["free space"] = Variant_p(new Variant(clustsize * this->freeClustersCount(which))); attrs["allocated clusters"] = Variant_p(new Variant(this->allocatedClustersCount(which))); attrs["used space"] = Variant_p(new Variant(clustsize * this->allocatedClustersCount(which))); if ((badclust = this->badClustersCount(which)) != 0) { attrs["bad clusters"] = Variant_p(new Variant(this->badClustersCount(which))); attrs["bad clusters space"] = Variant_p(new Variant(clustsize * badclust)); } else attrs["bad clusters"] = Variant_p(new Variant(0)); } return attrs; } dff-1.3.0+dfsg.1/dff/modules/fs/fat/fat.hpp000066400000000000000000000062371217176075400202260ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FAT_HPP__ #define __FAT_HPP__ #include "node.hpp" #include "vfile.hpp" #include "bootsector.hpp" #include "fatfs.hpp" #define FATFS_12_MASK 0x00000fff #define FATFS_16_MASK 0x0000ffff #define FATFS_32_MASK 0x0fffffff class FileAllocationTable; class FileAllocationTableNode: public Node { private: FileAllocationTable* __fat; uint8_t __fatnum; public: FileAllocationTableNode(std::string name, uint64_t size, Node* parent, class Fatfs* fatfs); ~FileAllocationTableNode(); void setContext(FileAllocationTable* fat, uint8_t fatnum); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(void); virtual Attributes dataType(); }; class FileAllocationTable { private: VFile* vfile; Node* origin; class Fatfs* fatfs; class BootSector* bs; void* __fat; std::map __freeClustCount; std::map __allocClustCount; std::map __badClustCount; void __processClustersStatus(); bool __isBadCluster(uint32_t clust); public: FileAllocationTable(); ~FileAllocationTable(); void setContext(Node* origin, class Fatfs* fatfs); uint32_t ioCluster12(uint32_t current, uint8_t which); uint32_t ioCluster16(uint32_t current, uint8_t which); uint32_t ioCluster32(uint32_t current, uint8_t which); uint32_t cluster12(uint32_t current, uint8_t which); uint32_t cluster16(uint32_t current, uint8_t which); uint32_t cluster32(uint32_t current, uint8_t which); uint32_t clusterEntry(uint32_t current, uint8_t which=0); uint64_t clusterOffsetInFat(uint64_t cluster, uint8_t which); std::vector clusterChainOffsets(uint32_t cluster, uint8_t which=0); std::vector clusterChain(uint32_t start, uint8_t which=0); bool isFreeCluster(uint32_t cluster); bool isBadCluster(uint32_t cluster); bool clusterEntryIsFree(uint32_t cluster, uint8_t which); bool clusterEntryIsBad(uint32_t cluster, uint8_t which); std::vector listFreeClustersOffset(uint8_t which=0); std::vector listFreeClusters(uint8_t which=0); uint32_t freeClustersCount(uint8_t which=0); std::list listAllocatedClusters(uint8_t which=0); uint32_t allocatedClustersCount(uint8_t which=0); std::vector listBadClusters(uint8_t which=0); uint32_t badClustersCount(uint8_t which=0); uint64_t clusterToOffset(uint32_t cluster); uint32_t offsetToCluster(uint64_t offset); void diffFats(); void makeNodes(Node* parent); void fileMapping(FileMapping* fm, uint8_t which); Attributes attributes(uint8_t which); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/fat/fatfs.cpp000066400000000000000000000064211217176075400205450ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "fatfs.hpp" void Fatfs::process() { Node* fsroot; std::string volname; try { if (this->parent->size() > 0) { this->vfile = this->parent->open(); this->bs->process(this->parent, this); this->fat->setContext(this->parent, this); fsroot = new Node("[root]", 0, NULL, this); fsroot->setDir(); this->tree->process(this->parent, this, fsroot); volname = this->tree->volname(); if (volname.empty()) this->root = new Node("NONAME", 0, NULL, this); else this->root = new Node(volname, 0, NULL, this); this->root->setDir(); this->root->addChild(fsroot); if (this->bs->reserved != 0) new ReservedSectors("reserved sectors", (uint64_t)(this->bs->reserved) * (uint64_t)this->bs->ssize, this->root, this); if (this->bs->totalsize < this->parent->size()) new FileSystemSlack("file system slack", this->parent->size() - this->bs->totalsize, this->root, this); this->fat->makeNodes(this->root); std::vector clusters; if (this->fat->freeClustersCount()) { Node* unalloc = new Node("unallocated space", 0, this->root, this); unalloc->setDir(); clusters = this->fat->listFreeClusters(); this->tree->processUnallocated(unalloc, clusters); } if (this->fat->badClustersCount()) { Node* bad = new Node("bad clusters", 0, this->root, this); bad->setDir(); clusters = this->fat->listBadClusters(); this->tree->processUnallocated(bad, clusters); } this->registerTree(this->parent, this->root); if (this->carveunalloc) this->tree->walk_free(this->root); } } catch(...) { throw("Fatfs module: error while processing"); } return; } void Fatfs::setContext(std::map args) throw (std::string) { std::map::iterator it; if ((it = args.find("file")) != args.end()) this->parent = it->second->value(); else throw(std::string("Fatfs module: no file provided")); if ((it = args.find("meta_carve")) != args.end()) this->carveunalloc = true; else this->carveunalloc = false; if ((it = args.find("check_slack")) != args.end()) this->checkslack = true; else this->checkslack = false; return; } void Fatfs::start(std::map args) { try { this->setContext(args); this->process(); } catch(std::string e) { throw (e); } catch(vfsError e) { throw (e); } catch(envError e) { throw (e); } return ; } Fatfs::~Fatfs() { //delete this->ctx; } Fatfs::Fatfs(): mfso("Fat File System") { this->bs = new BootSector(); this->fat = new FileAllocationTable(); this->tree = new FatTree(); } dff-1.3.0+dfsg.1/dff/modules/fs/fat/fatfs.hpp000066400000000000000000000022321217176075400205460ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FATFS_HPP__ #define __FATFS_HPP__ #include #include "variant.hpp" #include "mfso.hpp" #include "bootsector.hpp" #include "fat.hpp" #include "fattree.hpp" #include "node.hpp" class Fatfs : public mfso { public: Fatfs(); ~Fatfs(); Node* root; Node* parent; bool carveunalloc; bool checkslack; class FatTree* tree; class BootSector* bs; class FileAllocationTable* fat; VFile* vfile; virtual void start(std::map args); void setContext(std::map args) throw (std::string); void process(); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/fat/fatfs.i000066400000000000000000000043301217176075400202100ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "pyrun.swg" %module FATFS %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "mfso.hpp" #include "fatfs.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "fatfs.hpp" %pythoncode %{ __dff_module_fatfs_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId class FATFS(Module): """This module create the tree contained in a fat file system, for normal and deleted files.""" def __init__(self): Module.__init__(self, 'fatfs', Fatfs) self.conf.addArgument({"name": "file", "description": "file containing a FAT file system", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "meta_carve", "description": "carve directory entries in unallocated clusters (more accurate but slower)", "input": Argument.Empty}) self.conf.addArgument({"name": "check_slack", "description": "This option enables to create slack space for regular files ONLY if not empty.\nIf enabled, processing is slower (default: disable)", "input": Argument.Empty}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["FAT"]}) self.tags = "File systems" %} dff-1.3.0+dfsg.1/dff/modules/fs/fat/fatnodes.cpp000066400000000000000000000223631217176075400212500ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "fatnodes.hpp" FileSlack::FileSlack(std::string name, uint64_t size, Node* parent, class Fatfs* fs) : Node(name, size, parent, fs) { this->__fs = fs; } FileSlack::~FileSlack() { } void FileSlack::setContext(uint32_t ocluster, uint64_t originsize) { this->__ocluster = ocluster; this->__originsize = originsize; } void FileSlack::fileMapping(FileMapping* fm) { std::vector clusters; uint64_t idx; uint64_t remaining; uint64_t voffset; uint64_t clustsize; voffset = 0; clustsize = (uint64_t)this->__fs->bs->csize * this->__fs->bs->ssize; clusters = this->__fs->fat->clusterChainOffsets(this->__ocluster); if (clusters.size() > 0) { idx = this->__originsize / clustsize; remaining = this->__originsize % clustsize; //first chunk can be truncated fm->push(voffset, clustsize - remaining, this->__fs->parent, clusters[idx] + remaining); voffset += (clustsize - remaining); idx++; while (idx != clusters.size()) { fm->push(voffset, clustsize, this->__fs->parent, clusters[idx]); voffset += clustsize; idx++; } } } Attributes FileSlack::_attributes() { Attributes attrs; //attrs["starting offset"] = new Variant(this->__offset); return attrs; } UnallocatedSpace::UnallocatedSpace(std::string name, uint64_t size, Node* parent, class Fatfs* fs): Node(name, size, parent, fs) { this->__fs = fs; } UnallocatedSpace::~UnallocatedSpace() { } void UnallocatedSpace::setContext(uint32_t scluster, uint32_t count) { this->__scluster = scluster; this->__count = count; } void UnallocatedSpace::fileMapping(FileMapping* fm) { uint64_t soffset; uint64_t size; soffset = this->__fs->fat->clusterToOffset(this->__scluster); size = (uint64_t)this->__count * this->__fs->bs->csize * this->__fs->bs->ssize; fm->push(0, size, this->__fs->parent, soffset); } Attributes UnallocatedSpace::_attributes(void) { Attributes attrs; attrs["starting cluster"] = Variant_p(new Variant(this->__scluster)); attrs["total clusters"] = Variant_p(new Variant(this->__count)); return attrs; } Attributes UnallocatedSpace::dataType() { Attributes dtype; dtype["fatfs"] = Variant_p(new Variant(std::string("unallocated space"))); return dtype; } ReservedSectors::ReservedSectors(std::string name, uint64_t size, Node* parent, class Fatfs* fs) : Node(name, size, parent, fs) { this->fs = fs; } ReservedSectors::~ReservedSectors() { } Attributes ReservedSectors::dataType() { Attributes dtype; dtype["fatfs"] = Variant_p(new Variant(std::string("reserved sectors"))); return dtype; } void ReservedSectors::fileMapping(FileMapping* fm) { fm->push(0, (uint64_t)(this->fs->bs->reserved) * (uint64_t)this->fs->bs->ssize, this->fs->parent, 0); } Attributes ReservedSectors::_attributes(void) { Attributes attrs; attrs["starting sector"] = Variant_p(new Variant(1)); attrs["total sectors"] = Variant_p(new Variant(this->fs->bs->reserved)); return attrs; } FileSystemSlack::FileSystemSlack(std::string name, uint64_t size, Node* parent, class Fatfs* fs) : Node(name, size, parent, fs) { this->fs = fs; } FileSystemSlack::~FileSystemSlack() { } void FileSystemSlack::fileMapping(FileMapping* fm) { uint64_t offset; uint64_t size; offset = this->fs->bs->totalsize; size = this->fs->parent->size() - offset; fm->push(0, size, this->fs->parent, offset); } Attributes FileSystemSlack::_attributes(void) { Attributes attrs; uint64_t esect; uint64_t tsect; uint64_t ssect; esect = this->fs->parent->size() / this->fs->bs->ssize; tsect = (this->fs->parent->size() - this->fs->bs->totalsize) / this->fs->bs->ssize; ssect = esect - tsect; attrs["ending sector"] = Variant_p(new Variant(esect)); attrs["total sectors"] = Variant_p(new Variant(tsect)); attrs["starting sector"] = Variant_p(new Variant(ssect)); return attrs; } Attributes FileSystemSlack::dataType() { Attributes dtype; dtype["fatfs"] = Variant_p(new Variant(std::string("file system slack"))); return dtype; } FatNode::FatNode(std::string name, uint64_t size, Node* parent, class Fatfs* fs): Node(name, size, parent, fs) { this->fs = fs; } FatNode::~FatNode() { } void FatNode::setLfnMetaOffset(uint64_t lfnmetaoffset) { this->lfnmetaoffset = lfnmetaoffset; } void FatNode::setDosMetaOffset(uint64_t dosmetaoffset) { this->dosmetaoffset = dosmetaoffset; } void FatNode::setCluster(uint32_t cluster, bool reallocated) { this->__clustrealloc = reallocated; this->cluster = cluster; } void FatNode::fileMapping(FileMapping* fm) { std::vector clusters; unsigned int i; uint64_t voffset; uint64_t clustsize; uint64_t rsize; voffset = 0; rsize = this->size(); clustsize = (uint64_t)this->fs->bs->csize * this->fs->bs->ssize; if (!this->__clustrealloc || (this->__clustrealloc && !this->isDeleted())) { clusters = this->fs->fat->clusterChainOffsets(this->cluster); uint64_t clistsize = clusters.size(); //cluster chain is not complete if (clistsize > 0) { if ((clistsize*clustsize) < this->size()) { for (i = 0; i != clistsize; i++) { fm->push(voffset, clustsize, this->fs->parent, clusters[i]); voffset += clustsize; } uint64_t gap = this->size() - clistsize*clustsize; //last chunk corresponds to the last gap between last cluster and the size and is //based on the following blocks of the last cluster fm->push(voffset, gap, this->fs->parent, clusters[clistsize-1]+clustsize); } else { //manage the mapping based on cluster chain untill node->size() is reached for (i = 0; i != clusters.size(); i++) { if (rsize < clustsize) fm->push(voffset, rsize, this->fs->parent, clusters[i]); else fm->push(voffset, clustsize, this->fs->parent, clusters[i]); rsize -= clustsize; voffset += clustsize; } } } } } Attributes FatNode::_attributes() { Attributes attr; VFile* vf; std::vector clusters; uint8_t* entry; EntriesManager* em; dosentry* dos; em = new EntriesManager(this->fs->bs->fattype); vf = this->fs->parent->open(); attr["lfn entries start offset"] = Variant_p(new Variant(this->lfnmetaoffset)); attr["dos entry offset"] = Variant_p(new Variant(this->dosmetaoffset)); if ((entry = (uint8_t*)malloc(sizeof(dosentry))) != NULL) { vf->seek(this->dosmetaoffset); if (vf->read(entry, sizeof(dosentry)) != sizeof(dosentry)) { free(entry); return attr; } dos = em->toDos(entry); free(entry); attr["modified"] = Variant_p(new Variant(new vtime(dos->mtime, dos->mdate))); attr["accessed"] = Variant_p(new Variant(new vtime(0, dos->adate))); attr["created"] = Variant_p(new Variant(new vtime(dos->ctime, dos->cdate))); attr["dos name (8+3)"] = Variant_p(new Variant(em->formatDosname(dos))); delete em; attr["Read Only"] = Variant_p(new Variant(bool(dos->attributes & ATTR_READ_ONLY))); attr["Hidden"] = Variant_p(new Variant(bool(dos->attributes & ATTR_HIDDEN))); attr["System"] = Variant_p(new Variant(bool(dos->attributes & ATTR_SYSTEM))); attr["Archive"] = Variant_p(new Variant(bool(dos->attributes & ATTR_ARCHIVE))); attr["Volume"] = Variant_p(new Variant(bool(dos->attributes & ATTR_VOLUME))); delete dos; try { uint64_t clustsize = (uint64_t)this->fs->bs->csize * this->fs->bs->ssize; if (this->__clustrealloc) attr["first cluster (!! reallocated to another existing entry)"] = Variant_p(new Variant(this->cluster)); else { if (!this->isDeleted() && this->size()) { clusters = this->fs->fat->clusterChain(this->cluster); uint64_t clistsize = clusters.size(); attr["allocated clusters"] = Variant_p(new Variant(clistsize)); if (this->size() < clistsize * clustsize) { uint64_t ssize = clistsize * clustsize - this->size(); attr["slack space size"] = Variant_p(new Variant(ssize)); } else { uint32_t missclust; uint64_t gap; gap = this->size() - clistsize * clustsize; missclust = gap / clustsize; attr["file truncated"] = Variant_p(new Variant(true)); attr["missing cluters"] = Variant_p(new Variant(missclust)); attr["missing size"] = Variant_p(new Variant(gap)); } } //for (i = 0; i != clusters.size(); i++) //clustlist.push_back(new Variant(clusters[i])); attr["first cluster"] = Variant_p(new Variant(this->cluster)); //attr["allocated clusters"] = new Variant(clustlist); } } catch(vfsError e) { } } if (vf != NULL) { vf->close(); delete vf; } return attr; } dff-1.3.0+dfsg.1/dff/modules/fs/fat/fatnodes.hpp000066400000000000000000000053311217176075400212510ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FATNODES_HPP__ #define __FATNODES_HPP__ #include "fatfs.hpp" #include "node.hpp" #include "variant.hpp" #include "entries.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif class FileSlack: public Node { private: uint64_t __ocluster; uint64_t __originsize; class Fatfs* __fs; public: FileSlack(std::string name, uint64_t size, Node* parent, class Fatfs* fs); ~FileSlack(); void setContext(uint32_t ocluster, uint64_t osize); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(); }; class UnallocatedSpace: public Node { private: class Fatfs* __fs; uint32_t __scluster; uint32_t __count; public: UnallocatedSpace(std::string name, uint64_t size, Node* parent, class Fatfs* fs); ~UnallocatedSpace(); void setContext(uint32_t scluster, uint32_t count); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(void); virtual Attributes dataType(); }; class ReservedSectors: public Node { private: class Fatfs* fs; public: ReservedSectors(std::string name, uint64_t size, Node* parent, class Fatfs* fs); ~ReservedSectors(); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(void); virtual Attributes dataType(); }; class FileSystemSlack: public Node { private: class Fatfs* fs; public: FileSystemSlack(std::string name, uint64_t size, Node* parent, class Fatfs* fs); ~FileSystemSlack(); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(void); virtual Attributes dataType(); }; class FatNode: public Node { private: class Fatfs* fs; uint64_t lfnmetaoffset; uint64_t dosmetaoffset; uint32_t cluster; bool __clustrealloc; public: vtime* dosToVtime(uint16_t dos_time, uint16_t dos_date); FatNode(std::string name, uint64_t size, Node* parent, class Fatfs* fs); ~FatNode(); void setLfnMetaOffset(uint64_t lfnmetaoffset); void setDosMetaOffset(uint64_t dosmetaoffset); void setCluster(uint32_t cluster, bool reallocated=false); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(void); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/fat/fattree.cpp000066400000000000000000000327401217176075400210770ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "fattree.hpp" #include FatTree::FatTree() { //this->ectx = new EntryContext(); //this->converter = new EntryConverter(); this->__volname = ""; this->depth = 0; this->allocatedClusters = new TwoThreeTree(); } FatTree::~FatTree() { this->vfile->close(); } void FatTree::rootdir(Node* parent) { uint32_t bpos; uint8_t* buff; Node* node; ctx* c; buff = NULL; try { if ((buff = (uint8_t*)malloc(this->fs->bs->rootdirsize)) == NULL) return; this->vfile->seek(this->fs->bs->rootdiroffset); if (this->vfile->read(buff, this->fs->bs->rootdirsize) != (int32_t)this->fs->bs->rootdirsize) { free(buff); return; } for (bpos = 0; bpos != this->fs->bs->rootdirsize; bpos += 32) { if (this->emanager->push(buff+bpos, this->fs->bs->rootdiroffset + bpos)) { c = this->emanager->fetchCtx(); if ((c->valid) && (c->cluster < this->fs->bs->totalcluster)) { if (!c->deleted) { if (c->volume) this->__volname = c->dosname; else { node = this->allocNode(c, parent); if (c->dir) { this->depth++; this->walk(c->cluster, node); this->depth--; } // else // this->updateAllocatedClusters(c->cluster); delete c; } } else this->updateDeletedItems(c, parent); } else delete c; } } free(buff); } catch(...) { if (buff != NULL) free(buff); } } void hexlify(uint8_t *entry) { char hex[512]; int i; int pos; memset(hex, 0, 512); pos = 0; for (i = 0; i != 32; i++) { if ((i % 4) == 0) { sprintf(hex+pos, " "); pos++; } if ((i == 20) || (i == 21)) { sprintf(hex+pos, "\e[32m"); pos += 5; } if ((i == 26) || (i == 27)) { sprintf(hex+pos, "\e[33m"); pos += 5; } if (entry[i] <= 15) { sprintf(hex+pos, "0%x ", entry[i]); pos += 3; } else { sprintf(hex+pos, "%x ", entry[i]); pos += 3; } if ((i == 20) || (i == 21) || (i == 26) || (i == 27)) { sprintf(hex+pos, "\e[m"); pos += 3; } if (i == 15) { sprintf(hex+pos, "\n"); pos++; } } printf("%s\n", hex); } // void FatTree::CheckSlackNode() // { // void* zeroed; // void* buff; // if ((zeroed = malloc(clustsize)) != NULL) // memset(zeroed, 0, clustsize); // else // return; // if ((buff = malloc(clustsize)) == NULL) // { // free(zeroed); // return; // } // this->vfile->seek(offset); // if ((uint64_t)this->vfile->read(buff, size) == size) // if (memcmp(zeroed, buff, size) != 0) // { // FileSlack* fslack = new FileSlack(mit->second->name() + ".SLACK", size, mit->second->parent(), this->fs); // fslack->setContext(mit->first, mit->second->size()); // } // free(buff); // free(zeroed); // } void FatTree::makeSlackNodes() { std::map::iterator mit; uint64_t clustsize, slackcount; slackcount = this->_slacknodes.size(); clustsize = (uint64_t)this->fs->bs->csize * this->fs->bs->ssize; if (slackcount != 0) { uint64_t sprocessed, percent, prevpercent, size, clistsize; std::stringstream sstr; std::vector clusters; sprocessed = percent = prevpercent = 0; for (mit = this->_slacknodes.begin(); mit != this->_slacknodes.end(); mit++) { clusters = this->fs->fat->clusterChain(mit->first); clistsize = clusters.size(); if (mit->second->size() < clistsize * clustsize) { size = clistsize * clustsize - mit->second->size(); FileSlack* fslack = new FileSlack(mit->second->name() + ".SLACK", size, mit->second->parent(), this->fs); fslack->setContext(mit->first, mit->second->size()); } percent = (sprocessed * 100) / slackcount; if (prevpercent < percent) { sstr << "processing slack space for each regular files " << percent << "%"; this->fs->stateinfo = sstr.str(); sstr.str(""); prevpercent = percent; } sprocessed += 1; } } } Node* FatTree::allocNode(ctx* c, Node* parent) { FatNode* node; if (!c->lfnname.empty()) { UnicodeString us(c->lfnname.data(), c->lfnname.size(), "UTF-16LE"); std::string utf8 = ""; std::string ret = us.toUTF8String(utf8); node = new FatNode(std::string(utf8.data(), utf8.size()), c->size, parent, this->fs); } else node = new FatNode(c->dosname, c->size, parent, this->fs); if (!this->allocatedClusters->find(c->cluster)) node->setCluster(c->cluster); else node->setCluster(c->cluster, true); if (c->deleted) node->setDeleted(); if (c->dir) node->setDir(); else { node->setFile(); if (!c->deleted) { this->updateAllocatedClusters(c->cluster); this->_slacknodes[c->cluster] = node; } } node->setLfnMetaOffset(c->lfnmetaoffset); node->setDosMetaOffset(c->dosmetaoffset); return node; } void FatTree::updateAllocatedClusters(uint32_t cluster) { std::vector clusters; uint32_t cidx; std::stringstream sstr; if (cluster != 0) { this->allocatedClusters->insert(cluster); clusters = this->fs->fat->clusterChain(cluster); this->processed += clusters.size(); sstr << "processing regular tree " << (this->processed * 100) / this->allocount << "%"; this->fs->stateinfo = sstr.str(); for (cidx = 0; cidx != clusters.size(); cidx++) if (clusters[cidx] != 0) this->allocatedClusters->insert(clusters[cidx]); } } void FatTree::updateDeletedItems(ctx* c, Node* parent) { deletedItems* d; d = new deletedItems; d->c = c; d->node = parent; this->deleted.push_back(d); } void FatTree::walk(uint32_t cluster, Node* parent) { std::vector clusters; uint32_t cidx; uint32_t bpos; uint8_t* buff; Node* node; ctx* c; buff = NULL; try { this->updateAllocatedClusters(cluster); clusters = this->fs->fat->clusterChainOffsets(cluster); if ((buff = (uint8_t*)malloc(this->fs->bs->csize * this->fs->bs->ssize)) == NULL) return; for (cidx = 0; cidx != clusters.size(); cidx++) { this->vfile->seek(clusters[cidx]); if (this->vfile->read(buff, this->fs->bs->csize * this->fs->bs->ssize) != (this->fs->bs->csize * this->fs->bs->ssize)) { free(buff); return; } for (bpos = 0; bpos != this->fs->bs->csize * this->fs->bs->ssize; bpos += 32) { if (this->emanager->push(buff+bpos, clusters[cidx]+bpos)) { c = this->emanager->fetchCtx(); if ((c->valid) && (c->cluster < this->fs->bs->totalcluster)) { if (c->volume) this->__volname = c->dosname; else { if (!c->deleted) { node = this->allocNode(c, parent); if (c->dir) { this->depth++; this->walk(c->cluster, node); this->depth--; } delete c; } else this->updateDeletedItems(c, parent); } } else delete c; } } } free(buff); } catch(...) { if (buff != NULL) free(buff); } } void FatTree::walk_free(Node* parent) { std::vector clusters; uint32_t cidx; uint32_t bpos; uint8_t* buff; Node* rootunalloc; ctx* c; uint32_t fcsize; std::stringstream sstr; buff = NULL; try { rootunalloc = NULL; clusters = this->fs->fat->listFreeClusters(); if ((buff = (uint8_t*)malloc(this->fs->bs->csize * this->fs->bs->ssize)) == NULL) return; fcsize = clusters.size(); for (cidx = 0; cidx != fcsize; cidx++) { sstr << "carving entries in free clusters " << ((cidx * 100) / fcsize) << "%"; this->fs->stateinfo = sstr.str(); sstr.str(""); if ((!this->allocatedClusters->find(clusters[cidx])) && (clusters[cidx] != 0)) { uint64_t clustoff; clustoff = this->fs->fat->clusterToOffset(clusters[cidx]); this->vfile->seek(clustoff); if (this->vfile->read(buff, this->fs->bs->csize * this->fs->bs->ssize) != (this->fs->bs->csize * this->fs->bs->ssize)) { free(buff); return; } for (bpos = 0; bpos != this->fs->bs->csize * this->fs->bs->ssize; bpos += 32) { if (*(buff+bpos) == 0xE5) { if (this->emanager->push(buff+bpos, clustoff+bpos)) { c = this->emanager->fetchCtx(); if (c->valid) { if (rootunalloc == NULL) { rootunalloc = new Node("$OrphanedFiles", 0, NULL, this->fs); rootunalloc->setDir(); } if ((c->size < this->fs->bs->totalsize) && (c->cluster < this->fs->bs->totalcluster)) this->allocNode(c, rootunalloc); } delete c; } } } } } this->fs->stateinfo = std::string("carving entries in free clusters 100%"); free(buff); if (rootunalloc != NULL) this->fs->registerTree(parent, rootunalloc); } catch(...) { if (buff != NULL) free(buff); } } void FatTree::walkDeleted(uint32_t cluster, Node* parent) { std::vector clusters; uint64_t coffset; uint32_t cidx; uint32_t bpos; uint8_t* buff; Node* node; ctx* c; buff = NULL; if ((!this->allocatedClusters->find(cluster)) && (cluster != 0)) { try { clusters = this->fs->fat->clusterChain(cluster); if ((buff = (uint8_t*)malloc(this->fs->bs->csize * this->fs->bs->ssize)) == NULL) return; for (cidx = 0; cidx != clusters.size(); cidx++) { if ((!this->allocatedClusters->find(clusters[cidx])) && (clusters[cidx] != 0)) { coffset = this->fs->fat->clusterToOffset(clusters[cidx]); this->vfile->seek(coffset); if (this->vfile->read(buff, this->fs->bs->csize * this->fs->bs->ssize) != this->fs->bs->csize * this->fs->bs->ssize) { free(buff); return; } for (bpos = 0; bpos != this->fs->bs->csize * this->fs->bs->ssize; bpos += 32) { if (this->emanager->push(buff+bpos, coffset+bpos)) { c = this->emanager->fetchCtx(); if ((c->valid) && (c->cluster < this->fs->bs->totalcluster)) { if (c->deleted) { node = this->allocNode(c, parent); this->updateAllocatedClusters(cluster); if ((c->dir) && (!this->allocatedClusters->find(c->cluster))) this->walkDeleted(c->cluster, node); this->updateAllocatedClusters(c->cluster); } } delete c; } } } } free(buff); } catch(...) { if (buff != NULL) free(buff); } } } void FatTree::processUnallocated(Node* parent, std::vector &clusters) { uint32_t cidx; uint32_t start; uint32_t count; UnallocatedSpace* unode; std::stringstream sstr; start = count = (uint32_t)-1; for (cidx = 0; cidx != clusters.size(); cidx++) { if (clusters[cidx] != 0) { if (start == (uint32_t)-1) { start = clusters[cidx]; count = 1; } else { //current unallocated cluster starts another area. Push the current context and start another one if (clusters[cidx] != start+count) { sstr << start << "--" << start+count; unode = new UnallocatedSpace(sstr.str(), (uint64_t)count*this->fs->bs->ssize*this->fs->bs->csize, parent, this->fs); sstr.str(""); unode->setContext(start, count); start = clusters[cidx]; count = 1; } else count++; } } } if (start != (uint32_t)-1) { sstr << start << "--" << start+count; unode = new UnallocatedSpace(sstr.str(), (uint64_t)count*this->fs->bs->ssize*this->fs->bs->csize, parent, this->fs); sstr.str(""); unode->setContext(start, count); } } void FatTree::processDeleted() { uint32_t i; Node* node; deletedItems* d; std::stringstream sstr; uint32_t dsize; dsize = this->deleted.size(); for (i = 0; i != dsize; i++) { d = this->deleted[i]; sstr << "processing deleted entries " << ((i * 100) / dsize) << "%"; this->fs->stateinfo = sstr.str(); sstr.str(""); node = this->allocNode(d->c, d->node); if (d->c->dir) this->walkDeleted(d->c->cluster, node); delete d->c; delete d; } this->fs->stateinfo = std::string("processing deleted entries 100%"); } void FatTree::process(Node* origin, Fatfs* fs, Node* parent) { this->origin = origin; this->fs = fs; try { this->vfile = this->origin->open(); this->allocount = this->fs->fat->allocatedClustersCount(0); this->processed = 0; this->fs->stateinfo = std::string("processing regular tree 0%"); this->emanager = new EntriesManager(this->fs->bs->fattype); if (this->fs->bs->fattype == 32) this->walk(this->fs->bs->rootclust, parent); else this->rootdir(parent); this->fs->stateinfo = std::string("processing regular tree 100%"); this->makeSlackNodes(); this->processDeleted(); // int32_t max = ucnv_countAvailable(); // for (int32_t i = 0; i != max; i++) // printf("%04i -- %s\n", i, ucnv_getAvailableName(i)); // printf("current --> %s\n", ucnv_getDefaultName()); } catch(...) { throw("err"); } } dff-1.3.0+dfsg.1/dff/modules/fs/fat/fattree.hpp000066400000000000000000000034161217176075400211020ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __FATTREE_HPP__ #define __FATTREE_HPP__ #include "fatfs.hpp" #include "node.hpp" #include "fatnodes.hpp" #include "vfile.hpp" #include "entries.hpp" #include "TwoThreeTree.hpp" typedef struct s_deletedItems { Node* node; ctx* c; } deletedItems; class FatTree { private: Node* origin; uint64_t allocount; uint64_t processed; VFile* vfile; class Fatfs* fs; std::vector deleted; std::map _slacknodes; std::set deletedUsedClusters; TwoThreeTree *allocatedClusters; uint32_t depth; void makeSlackNodes(); void processDeleted(); void walkDeleted(uint32_t cluster, Node* parent); void updateDeletedItems(ctx* c, Node* parent); void updateAllocatedClusters(uint32_t cluster); Node* allocNode(ctx* c, Node* parent); void walk(uint32_t cluster, Node* parent); void rootdir(Node* parent); std::string __volname; public: EntriesManager* emanager; FatTree(); ~FatTree(); void processUnallocated(Node* parent, std::vector &clusters); void walk_free(Node* parent); void process(Node* origin, class Fatfs* fs, Node* parent); std::string volname() {return __volname;} }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/000077500000000000000000000000001217176075400171335ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/CMakeLists.txt000066400000000000000000000021741217176075400216770ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge include_directories(${ICU_INCLUDE_DIRS}) #add_definitions(-Wall -Wunused -Wextra) dff_cpp_module(NTFS CPP_FILES ntfs.cpp boot.cpp mftentry.cpp mftfile.cpp attribute.cpp ntfsnode.cpp bitmapnode.cpp attributes/data.cpp attributes/bitmap.cpp attributes/filename.cpp attributes/standardinformation.cpp attributes/attributelist.cpp attributes/indexroot.cpp attributes/reparsepoint.cpp attributes/indexallocation.cpp attributes/securitydescriptor.cpp SWIG_FILE ntfs.i INCLUDE_DIRS ${ICU_INCLUDE_DIRS} LINK_LIBRARIES ${ICU_LIBRARIES} exceptions types vfs ) dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attribute.cpp000066400000000000000000000537271217176075400216600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "vfile.hpp" #include "attribute.hpp" Attribute::Attribute(VFile *vfile) { _vfile = vfile; _offsetListSize = 0; _parentMftOffset = 0; _mftIndex = 0; _baseOffset = 0; _attributeRealOffset = 0; _mftEntrySize = 0; _indexRecordSize = 0; _sectorSize = 0; _clusterSize = 0; _currentRunIndex = 0; _fixupIndexes = NULL; _runAmount = 0; } Attribute::~Attribute() { ; } void Attribute::setOrigin(AttributeHeader *header, uint8_t *readBuffer, uint16_t bufferOffset, uint16_t attributeOffset) { _attributeHeader = header; if (!_parentMftOffset) _parentMftOffset = bufferOffset; _bufferOffset = bufferOffset; _attributeOffset = attributeOffset; _readBuffer = readBuffer; } uint16_t Attribute::getType() { return _attributeHeader->attributeTypeIdentifier; } void Attribute::content() { ; } void Attribute::readHeader() { _attributeHeader = (AttributeHeader *)(_readBuffer + _bufferOffset); if (_attributeHeader->nonResidentFlag) { _attributeNonResidentDataHeader = (AttributeNonResidentDataHeader *) (_readBuffer + _bufferOffset + ATTRIBUTE_HEADER_SIZE); _attributeResidentDataHeader = NULL; } else { _attributeNonResidentDataHeader = NULL; _attributeResidentDataHeader = (AttributeResidentDataHeader *) (_readBuffer + _bufferOffset + ATTRIBUTE_HEADER_SIZE); } _parentMftOffset = _bufferOffset - _attributeOffset; //_bufferOffset += _attributeHeader->attributeLength; //_attributeOffset += _attributeHeader->attributeLength; } void Attribute::dumpHeader() { printf("Attribute %s Header in 0x%x:\n", getFullName().c_str(), _attributeOffset); printf("\tattributeTypeIdentifier 0x%x\n", getType()); printf("\tattributeLength 0x%x\n", _attributeHeader->attributeLength); printf("\tnonResidentFlag 0x%x\n", _attributeHeader->nonResidentFlag); printf("\tnameLength 0x%x\n", _attributeHeader->nameLength); printf("\tnameOffset 0x%x\n", _attributeHeader->nameOffset); printf("\tFlags 0x%x\n", _attributeHeader->flags); if (_attributeHeader->flags & ATTRIBUTE_FLAG_COMPRESSED) { printf("\t\tis compressed\n"); } if (_attributeHeader->flags & ATTRIBUTE_FLAG_ENCRYPTED) { printf("\t\tis encrypted\n"); } if (_attributeHeader->flags & ATTRIBUTE_FLAG_SPARSE) { printf("\t\tis sparse\n"); } if (!(_attributeHeader->flags & ATTRIBUTE_FLAG_COMPRESSED) && !(_attributeHeader->flags & ATTRIBUTE_FLAG_ENCRYPTED) && !(_attributeHeader->flags & ATTRIBUTE_FLAG_SPARSE)) { printf("\t\tunknown\n"); } printf("\tattributeIdentifier 0x%x\n", _attributeHeader->attributeIdentifier); if (_attributeHeader->nonResidentFlag) { printf("\tNon-resident data header:\n"); #if __WORDSIZE == 64 printf("\t\tStarting VCN\t0x%.16lx\n", _attributeNonResidentDataHeader->startingVCN); printf("\t\tEnding VCN\t0x%.16lx\n", _attributeNonResidentDataHeader->endingVCN); #else printf("\t\tStarting VCN 0x%.16llx\n", _attributeNonResidentDataHeader->startingVCN); printf("\t\tEnding VCN 0x%.16llx\n", _attributeNonResidentDataHeader->endingVCN); #endif printf("\t\tRun list offset 0x%x\n", _attributeNonResidentDataHeader->runListOffset); printf("\t\tCompression unit size 0x%x\n", _attributeNonResidentDataHeader->compressionUnitSize); printf("\t\tUnused 0x%x\n", _attributeNonResidentDataHeader->unused); #if __WORDSIZE == 64 printf("\t\tAttribute content allocated size\t%lu bytes\n", _attributeNonResidentDataHeader->attributeContentAllocatedSize); printf("\t\tAttribute content actual size\t\t%lu bytes\n", _attributeNonResidentDataHeader->attributeContentActualSize); printf("\t\tAttribute content initialized size\t%lu bytes\n", _attributeNonResidentDataHeader->attributeContentInitializedSize); #else printf("\t\tAttribute content allocated size\t%llu bytes\n", _attributeNonResidentDataHeader->attributeContentAllocatedSize); printf("\t\tAttribute content actual size\t\t%llu bytes\n", _attributeNonResidentDataHeader->attributeContentActualSize); printf("\t\tAttribute content initialized size\t%llu bytes\n", _attributeNonResidentDataHeader->attributeContentInitializedSize); #endif } else { printf("\tResident data header:\n"); printf("\t\tContent size %u bytes (0x%x)\n", _attributeResidentDataHeader->contentSize, _attributeResidentDataHeader->contentSize); printf("\t\tContent offset 0x%x\n", _attributeResidentDataHeader->contentOffset); printf("Attribute Content:\n"); } } void Attribute::setContent() { if (_attributeHeader->nonResidentFlag) { setRunList(); return ; } } /** * Specific to non resident attributes */ void Attribute::setRunList() { uint16_t runListSize; uint16_t runListIndex = 0; OffsetRun *offsetRunToSet; uint16_t runDescOffset = 0; runListSize = getRunListSize(); _runAmount = 0; while (runListIndex < runListSize) { offsetRunToSet = getOffsetRun(runListIndex); runDescOffset = setNextRun(runDescOffset, &(offsetRunToSet->runLength), &(offsetRunToSet->runOffset)); if (!_baseOffset) { #if __WORDSIZE == 64 DEBUG(INFO, "No base Offset, 0x%lx, 0x%x\n", offsetRunToSet->runOffset, _clusterSize); #else DEBUG(INFO, "No base Offset, 0x%llx, 0x%x\n", offsetRunToSet->runOffset, _clusterSize); #endif _baseOffset = offsetRunToSet->runOffset * _clusterSize; } // _runAmount += _offsetList[runListIndex].runLength; _runAmount += offsetRunToSet->runLength; if (runListIndex) { // Also transform relative offset addr to real addr // Be carefull ; runLength is relative to previous offset it can be signed ! _offsetList[runListIndex].runLength += _offsetList[runListIndex - 1].runLength; _offsetList[runListIndex].runOffset += _offsetList[runListIndex - 1].runOffset; } runListIndex++; } runListIndex = 0; } uint16_t Attribute::_runList(uint16_t runDescOffset) { uint8_t *runList = (_readBuffer + runDescOffset); uint8_t runLengthSize; uint8_t runOffsetSize; DEBUG(INFO, "\t\tRun list in 0x%x\n", runDescOffset); runLengthSize = runList[0] & 0xF; runOffsetSize = runList[0] >> 4; DEBUG(INFO, "\t\t\trunLenghtSize: 0x%x\n", runLengthSize); if (runLengthSize == 0) { DEBUG(INFO, "\t\t\tover\n"); return 0; } DEBUG(INFO, "\t\t\trunOffsetSize: 0x%x\n", runOffsetSize); DEBUG(INFO, "\t\tNew desc offset: 0x%x\n", runDescOffset + SIZE_BYTE + runLengthSize + runOffsetSize); return runDescOffset + SIZE_BYTE + runLengthSize + runOffsetSize; } uint16_t Attribute::getRunListSize() { uint16_t runDescOffset; uint16_t items = 0; if (!(_attributeHeader->nonResidentFlag)) // XXX return 0; if (_offsetListSize) return _offsetListSize; _previousRunOffset = 0; _attributeNonResidentDataHeader = (AttributeNonResidentDataHeader *) (_readBuffer + _bufferOffset + ATTRIBUTE_HEADER_SIZE); runDescOffset = _bufferOffset + _attributeNonResidentDataHeader->runListOffset; DEBUG(INFO, "offset: 0x%x versus 0x%x\n", runDescOffset, _bufferOffset + _attributeOffset + _attributeHeader->attributeLength); while ((runDescOffset = _runList(runDescOffset)) && runDescOffset < _bufferOffset + _attributeOffset + _attributeHeader->attributeLength) { items++; } _offsetList = new OffsetRun[items]; _offsetListSize = items; DEBUG(INFO, "offsetListSize: %u\n", _offsetListSize); return items; } OffsetRun *Attribute::getOffsetRun(uint16_t index) { return &(_offsetList[index]); } uint16_t Attribute::getOffsetListSize() { return _offsetListSize; } uint16_t Attribute::setNextRun(uint16_t runDescOffset, uint32_t *lengthPtr, int64_t *offsetPtr) { uint8_t *runList; uint8_t runLengthSize; uint8_t runOffsetSize; uint32_t runLength = 0; int64_t runOffset = 0; // Offset is signed, relative to previous offset uint16_t index; bool isSigned = false; int64_t signConv = 0; uint8_t value; if (!runDescOffset) { _previousRunOffset = 0; DEBUG(INFO, "bufferOffset: 0x%x\n", _bufferOffset); DEBUG(INFO, "runListOffset: 0x%x\n", _attributeNonResidentDataHeader->runListOffset); runDescOffset = _bufferOffset + _attributeNonResidentDataHeader->runListOffset; } runList = _readBuffer + runDescOffset; DEBUG(INFO, "\t\tAttribute DATA in 0x%x\n", runDescOffset); runLengthSize = runList[0] & 0xF; runOffsetSize = runList[0] >> 4; DEBUG(INFO, "\t\t\trunLenghtSize: 0x%x\n", runLengthSize); if (runLengthSize == 0) { DEBUG(INFO, "\t\t\tover\n"); return 0; } DEBUG(INFO, "\t\t\trunOffsetSize: 0x%x\n", runOffsetSize); // Read run length byte per byte for (index = 0; index < runLengthSize; index++) runLength += ((uint32_t)*((uint8_t *)(runList + (index + 1) * SIZE_BYTE))) << (index * BITS_IN_BYTE); // Read run offset byte per byte // Be carreful ; offset is signed, because it is relative to previous offset if (runOffsetSize) { for (index = 0; index < runOffsetSize; index++) { value = *((uint8_t *)(runList + runLengthSize + (index + 1) * SIZE_BYTE)); if (index == runOffsetSize - 1) if (value > 0x7f) isSigned = true; runOffset += ((int64_t)value) << (index * BITS_IN_BYTE); signConv += 0xff << (index * BITS_IN_BYTE); } if (isSigned) { runOffset = -(signConv - runOffset + 1); } } else { // shadow node #if __WORDSIZE == 64 runOffset = 0x0UL; #else runOffset = 0x0ULL; #endif } DEBUG(INFO, "\t\t\trunLength: 0x%.8x\n", runLength); #if __WORDSIZE == 64 DEBUG(INFO, "\t\t\trunOffset: 0x%.16lx (relative: %li) (from %lu to %lu)\n", runOffset + _previousRunOffset, runOffset, runOffset + _previousRunOffset, runOffset + _previousRunOffset + runLength - 1); #else DEBUG(INFO, "\t\t\trunOffset: 0x%.16llx (relative: %lli) (from %llu to %llu)\n", runOffset + _previousRunOffset, runOffset, runOffset + _previousRunOffset, runOffset + _previousRunOffset + runLength - 1); #endif if (runOffsetSize) _previousRunOffset = runOffset + _previousRunOffset; *lengthPtr = runLength; *offsetPtr = runOffset; return runDescOffset + SIZE_BYTE + runLengthSize + runOffsetSize; } uint32_t Attribute::idFromOffset(uint64_t offset) { uint16_t currentRunIndex = 0; uint16_t offsetRunIndex = 0; uint32_t offsetInRun = 0; uint32_t i; uint8_t mftIndex = 0; uint16_t runLength; uint64_t runOffset; for (i = 0; offsetRunIndex <= _offsetListSize; i++) { runLength = getOffsetRun(offsetRunIndex)->runLength; if (currentRunIndex >= runLength) { offsetRunIndex++; offsetInRun = 0; mftIndex = 0; } runOffset = (uint64_t)(getOffsetRun(offsetRunIndex)->runOffset * _clusterSize); #if __WORDSIZE == 64 DEBUG(CRITICAL, "id %u (0x%x) is @ 0x%lx\n", i, i, runOffset + (offsetInRun * _clusterSize) + (mftIndex * _mftEntrySize)); #else DEBUG(CRITICAL, "id %u (0x%x) is @ 0x%llx\n", i, i, runOffset + (offsetInRun * _clusterSize) + (mftIndex * _mftEntrySize)); #endif // if (offset == (getOffsetRun(offsetRunIndex)->runOffset) * _clusterSize + (offsetInRun * _clusterSize) + (mftIndex * _mftEntrySize)) if (offset == (runOffset + (offsetInRun * _clusterSize) + (mftIndex * _mftEntrySize))) { return i; } mftIndex++; if (mftIndex == _clusterSize / _mftEntrySize) { mftIndex = 0; offsetInRun++; currentRunIndex++; } } return 0; } uint64_t Attribute::offsetFromID(uint32_t id) { uint32_t currentRunIndex = 0; uint16_t offsetRunIndex = 0; uint32_t offsetInRun = 0; uint32_t i; uint32_t mftIndex = 0; uint32_t runLength; int64_t runOffset; if (_mftEntrySize > _clusterSize) { id *= (_mftEntrySize / _clusterSize); } runLength = getOffsetRun(0)->runLength; runOffset = getOffsetRun(0)->runOffset; //cout << "offsetRunIndex " << offsetRunIndex << " _offsetListSize " << _offsetListSize << endl; for (i = 0; offsetRunIndex <= _offsetListSize; i++) { if (currentRunIndex >= runLength) { offsetRunIndex++; offsetInRun = 0; mftIndex = 0; runLength = getOffsetRun(offsetRunIndex)->runLength; runOffset = getOffsetRun(offsetRunIndex)->runOffset; } //else //cout << "current run index " << currentRunIndex << " runLength " << runLength << endl; DEBUG(VERBOSE, "id is 0x%x we are searching for 0x%x\n", i, id); if (i == id) { #if __WORDSIZE == 64 DEBUG(INFO, "id %u (0x%x) found @ 0x%lx\n", id, id, runOffset * _clusterSize + (offsetInRun * _clusterSize) + (mftIndex * _mftEntrySize)); #else DEBUG(INFO, "id %u (0x%x) found @ 0x%llx\n", id, id, runOffset * _clusterSize + (offsetInRun * _clusterSize) + (mftIndex * _mftEntrySize)); #endif return (runOffset * _clusterSize + offsetInRun * _clusterSize + mftIndex * _mftEntrySize); } if (_mftEntrySize < _clusterSize) { mftIndex++; if (mftIndex == (uint16_t)(_clusterSize / _mftEntrySize)) { mftIndex = 0; offsetInRun++; currentRunIndex++; } } else { mftIndex = 0; offsetInRun++; currentRunIndex++; } } return 0; } uint64_t Attribute::nextOffset() { #if __WORDSIZE == 64 DEBUG(INFO, "current run %u offset in it 0x%lx run length %u\n", _currentRunIndex, getOffsetRun(_offsetRunIndex)->runOffset + _offsetInRun, getOffsetRun(_offsetRunIndex)->runLength); #else DEBUG(INFO, "current run %u offset in it 0x%llx run length %u\n", _currentRunIndex, getOffsetRun(_offsetRunIndex)->runOffset + _offsetInRun, getOffsetRun(_offsetRunIndex)->runLength); #endif if (_currentRunIndex >= getOffsetRun(_offsetRunIndex)->runLength) { _offsetInRun = 0; _offsetRunIndex++; if (_offsetRunIndex >= _offsetListSize) { _offsetInRun = 0; _offsetRunIndex = 0; return 0; } } if (_currentRunIndex++) return (getOffsetRun(_offsetRunIndex)->runOffset) * _clusterSize + (_offsetInRun++ * _clusterSize); else { #if __WORDSIZE == 64 DEBUG(INFO, "returning 0x%lx + (0x%x * 0x%x)\n", _baseOffset, _offsetInRun, _clusterSize); #else DEBUG(INFO, "returning 0x%llx + (0x%x * 0x%x)\n", _baseOffset, _offsetInRun, _clusterSize); #endif return _baseOffset + (_offsetInRun++ * _clusterSize); // + 0 first pass } } uint64_t Attribute::nextMftOffset() { #if __WORDSIZE == 64 DEBUG(INFO, "current run %u offset in it 0x%lx run length %u run index %u size of list %u\n", _currentRunIndex, getOffsetRun(_offsetRunIndex)->runOffset + _offsetInRun, getOffsetRun(_offsetRunIndex)->runLength, _offsetRunIndex, _offsetListSize); #else DEBUG(INFO, "current run %u offset in it 0x%llx run length %u run index %u size of list %u\n", _currentRunIndex, getOffsetRun(_offsetRunIndex)->runOffset + _offsetInRun, getOffsetRun(_offsetRunIndex)->runLength, _offsetRunIndex, _offsetListSize); #endif if (_currentRunIndex >= getOffsetRun(_offsetRunIndex)->runLength) { _offsetInRun = 0; _mftIndex = 0; _offsetRunIndex++; if (_offsetRunIndex >= _offsetListSize) { _offsetInRun = 0; _offsetRunIndex = 0; return 0; } } if (_currentRunIndex) { if (_mftIndex == _clusterSize / _mftEntrySize) { _mftIndex = 0; _currentRunIndex++; _offsetInRun++; } return (getOffsetRun(_offsetRunIndex)->runOffset) * _clusterSize + (_offsetInRun * _clusterSize) + (_mftIndex++ * _mftEntrySize); } else { if ((_mftIndex + 1) == (_clusterSize / _mftEntrySize)) _currentRunIndex++; return _baseOffset + (_mftIndex++ * _mftEntrySize); } } void Attribute::setDateToString(uint64_t value, struct tm **date, std::string *dateString, bool usecond) { uint64_t origValue; if (value > 0) { value -= NANOSECS_1601_TO_1970; origValue = value; value /= 10000000; *date = gmtime((time_t *)&(value)); if (usecond) { std::ostringstream nanoBuff; char firstPart[100]; strftime(firstPart, 100, "%a %b %d %Y %H:%M:%S.", *date); nanoBuff << firstPart << origValue - (((value * 10000000))); while (nanoBuff.str().size() < std::string("Day Mon DD YYYY HH:MM:SS.NNNNNNN").size()) { nanoBuff << '0'; } *dateString = nanoBuff.str(); } else { *dateString = std::string(asctime(*date)); *dateString = dateString->substr(0, dateString->size() - 1); } } else { uint32_t zero = 0; *date = gmtime((time_t *)&zero); *dateString = std::string("Not set"); } } void Attribute::fixupOffsets(uint8_t fixupAmount) { uint8_t i = 0; if (_fixupIndexes == NULL) { _fixupIndexes = new uint64_t[fixupAmount]; _fixupIndexesSize = fixupAmount; } if (fixupAmount > _fixupIndexesSize) { delete _fixupIndexes; _fixupIndexes = new uint64_t[fixupAmount]; _fixupIndexesSize = fixupAmount; } while (i < _fixupIndexesSize) { #if __WORDSIZE == 64 _fixupIndexes[i++] = 0x0UL; #else _fixupIndexes[i++] = 0x0ULL; #endif } } void Attribute::fixupOffset(uint8_t fixupIndex, uint64_t value) { if (fixupIndex > _fixupIndexesSize) { throw(vfsError(std::string("Attribute::fixupOffset failed"))); } _fixupIndexes[fixupIndex] = value; #if __WORDSIZE == 64 DEBUG(INFO, "fixup array %u set to 0x%lx\n", fixupIndex, value); #else DEBUG(INFO, "fixup array %u set to 0x%llx\n", fixupIndex, value); #endif } uint64_t Attribute::getFixupOffset(uint8_t fixupIndex) { return _fixupIndexes[fixupIndex]; } std::string Attribute::getName() { return getName(_attributeHeader->attributeTypeIdentifier); } std::string Attribute::getExtName() { std::ostringstream extName; uint8_t i = 0; while (i < (_attributeHeader->nameLength * 2)) { extName << (char)*(_readBuffer + _bufferOffset + _attributeHeader->nameOffset + i); i += 2; } if (extName.str().size()) { return std::string(":") + extName.str(); } return std::string(""); } std::string Attribute::getFullName() { std::string baseName = getName(_attributeHeader->attributeTypeIdentifier); std::ostringstream extName; uint8_t i = 0; DEBUG(INFO, "i is 0x%x nameLength is 0x%x bufferoffset 0x%x\n", i, _attributeHeader->nameLength, _bufferOffset + _attributeHeader->nameOffset); while (i < (_attributeHeader->nameLength * 2)) { DEBUG(INFO, "i is 0x%x nameLength is 0x%x bufferoffset 0x%x\n", i, _attributeHeader->nameLength, _bufferOffset + _attributeHeader->nameOffset); DEBUG(INFO, "Got %c\n", (char)*(_readBuffer + _bufferOffset + _attributeHeader->nameOffset + i)); extName << (char)*(_readBuffer + _bufferOffset + _attributeHeader->nameOffset + i); i += 2; } if (extName.str().size()) { return baseName + std::string(":") + extName.str(); } return baseName; } std::string Attribute::getName(uint32_t attributeType) { if (attributeType == ATTRIBUTE_STANDARD_INFORMATION) { return std::string("$STANDARD_INFORMATION"); ; } else if (attributeType == ATTRIBUTE_ATTRIBUTE_LIST) { return std::string("$ATTRIBUTE_LIST"); ; } else if (attributeType == ATTRIBUTE_FILE_NAME) { return std::string("$FILE_NAME"); ; } else if (attributeType == ATTRIBUTE_VOLUME_VERSION_OR_OBJECT_ID) { return std::string("$VOLUME_VERSION_OR_OBJECT_ID"); ; } else if (attributeType == ATTRIBUTE_SECURITY_DESCRIPTOR) { return std::string("$SECURITY_DESCRIPTOR"); ; } else if (attributeType == ATTRIBUTE_VOLUME_NAME) { return std::string("$VOLUME_NAME"); ; } else if (attributeType == ATTRIBUTE_VOLUME_INFORMATION) { return std::string("$VOLUME_INFORMATION"); ; } else if (attributeType == ATTRIBUTE_DATA) { return std::string("$DATA"); ; } else if (attributeType == ATTRIBUTE_INDEX_ROOT) { return std::string("$INDEX_ROOT"); ; } else if (attributeType == ATTRIBUTE_INDEX_ALLOCATION) { return std::string("$INDEX_ALLOCATION"); ; } else if (attributeType == ATTRIBUTE_BITMAP) { return std::string("$BITMAP"); ; } else if (attributeType == ATTRIBUTE_SYMBOLINC_LINK_OR_REPARSE_POINT) { return std::string("$SYMBOLINC_LINK_OR_REPARSE_POINT"); ; } else if (attributeType == ATTRIBUTE_EA_INFORMATION) { return std::string("$EA_INFORMATION"); ; } else if (attributeType == ATTRIBUTE_EA) { return std::string("$EA");\ ; } else if (attributeType == ATTRIBUTE_LOGGED_UTILITY_STREAM) { return std::string("$LOGGED_UTILITY_STREAM"); ; } return std::string("unknown"); } /* void Attribute::_attributeSecurityDescriptor() { AttributeSecurityDescriptor *attribute = (AttributeSecurityDescriptor *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } void Attribute::_attributeVolumeName() { AttributeVolumeName *attribute = (AttributeVolumeName *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } void Attribute::_attributeVolumeInformation() { AttributeVolumeInformation *attribute = (AttributeVolumeInformation *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } void Attribute::_attributeBitmap() { AttributeBitmap *attribute = (AttributeBitmap *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } void Attribute::_attributeEAInformation() { AttributeEAInformation *attribute = (AttributeEAInformation *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } void Attribute::_attributeEA() { AttributeEA *attribute = (AttributeEA *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } void Attribute::_attributeLoggedUtilityStream() { AttributeLoggedUtilityStream *attribute = (AttributeLoggedUtilityStream *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); ; } */ dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attribute.hpp000066400000000000000000000170671217176075400216620ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __ATTRIBUTE_HPP__ #define __ATTRIBUTE_HPP__ #include "vfs.hpp" #include "common.hpp" #if (defined(WIN64) || defined(WIN32)) #if _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include #include #else #include #endif class VFile; #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * Attribute header */ /* Basic attributes */ #define ATTRIBUTE_STANDARD_INFORMATION 0x10 // Exists for every file and directory, always resident #define ATTRIBUTE_ATTRIBUTE_LIST 0x20 #define ATTRIBUTE_FILE_NAME 0x30 // Always resident #define ATTRIBUTE_VOLUME_VERSION_OR_OBJECT_ID 0x40 #define ATTRIBUTE_SECURITY_DESCRIPTOR 0x50 #define ATTRIBUTE_VOLUME_NAME 0x60 #define ATTRIBUTE_VOLUME_INFORMATION 0x70 #define ATTRIBUTE_DATA 0x80 // Exists for every file, if content > 700 bytes : attribute becomes non-resident. If more than one $DATA attribute : additional attribute are ADS (Alternate Data Streams) #define ATTRIBUTE_INDEX_ROOT 0x90 // Exists for every directory. Typically have name $I30, always resident #define ATTRIBUTE_INDEX_ALLOCATION 0xA0 // Typically have name $I30 #define ATTRIBUTE_BITMAP 0xB0 #define ATTRIBUTE_SYMBOLINC_LINK_OR_REPARSE_POINT 0xC0 #define ATTRIBUTE_EA_INFORMATION 0xD0 #define ATTRIBUTE_EA 0xE0 #define ATTRIBUTE_LOGGED_UTILITY_STREAM 0x100 #define ATTRIBUTE_HEADER_SIZE 16U #define ATTRIBUTE_FLAG_COMPRESSED 0x0001 #define ATTRIBUTE_FLAG_ENCRYPTED 0x4000 #define ATTRIBUTE_FLAG_SPARSE 0x8000 #define ATTRIBUTE_END 0xFFFFFFFF #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeHeader { uint32_t attributeTypeIdentifier; uint32_t attributeLength; uint8_t nonResidentFlag; uint8_t nameLength; uint16_t nameOffset; uint16_t flags; uint16_t attributeIdentifier; } PACK AttributeHeader; /** * $VOLUME_VERSION_OR_OBJECT_ID attribute */ #define ATTRIBUTE_ID_SIZE 16U #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeObjectID { uint8_t objectID[ATTRIBUTE_ID_SIZE]; uint8_t birthVolumeID[ATTRIBUTE_ID_SIZE]; uint8_t birthObjectID[ATTRIBUTE_ID_SIZE]; uint8_t birthDomainID[ATTRIBUTE_ID_SIZE]; } PACK AttributeObjectID_t; /** * $VOLUME_NAME attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeVolumeName { uint8_t todo; } PACK AttributeVolumeName_t; /** * $VOLUME_INFORMATION attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeVolumeInformation { uint8_t todo; } PACK AttributeVolumeInformation_t; /** * $EA_INFORMATION attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeEAInformation { uint8_t todo; } PACK AttributeEAInformation_t; /** * $EA attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeEA { uint8_t todo; } PACK AttributeEA_t; /** * $LOGGED_UTILITY_STREAM attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeLoggedUtilityStream { uint8_t todo; } PACK AttributeLoggedUtilityStream_t; #ifdef WIN32 #pragma pack(1) #endif typedef struct s_OffsetRun { uint32_t runLength; int64_t runOffset; } PACK OffsetRun; /** * Resident attribute header */ #define ATTRIBUTE_RESIDENT_DATA_HEADER_SIZE 6 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeResidentDataHeader { uint32_t contentSize; uint16_t contentOffset; } PACK AttributeResidentDataHeader; /** * Non-resident attribute header */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeNonResidentDataHeader { // AttributeHeader just before uint64_t startingVCN; // Starting and ending VCN (Virtual Cluster uint64_t endingVCN; // Number) of the run list. uint16_t runListOffset; uint16_t compressionUnitSize; uint32_t unused; uint64_t attributeContentAllocatedSize; uint64_t attributeContentActualSize; uint64_t attributeContentInitializedSize; } PACK AttributeNonResidentDataHeader; class Attribute { public: Attribute() {}; Attribute(VFile *); virtual ~Attribute(); void setOrigin(AttributeHeader *, uint8_t *, uint16_t, uint16_t); uint16_t getType(); void readHeader(); void dumpHeader(); virtual void content(); void setContent(); // Used in case attribute is non resident void setRunList(); uint16_t getRunListSize(); OffsetRun *getOffsetRun(uint16_t); uint16_t getOffsetListSize(); OffsetRun *offsetsRuns() { return _offsetList; }; uint16_t setNextRun(uint16_t, uint32_t *, int64_t *); uint64_t nextOffset(); uint64_t nextMftOffset(); void setDateToString(uint64_t, struct tm **, std::string *, bool); uint32_t getRunAmount() { return _runAmount; }; // For children copy constructor AttributeHeader *attributeHeader() { return _attributeHeader; }; uint8_t *readBuffer() { return _readBuffer; }; uint16_t attributeOffset() { return _attributeOffset; }; uint64_t attributeRealOffset() { return _attributeRealOffset; }; void attributeRealOffset(uint64_t real) { _attributeRealOffset = real; }; uint16_t bufferOffset() { return _bufferOffset; }; VFile *vfile() { return _vfile; }; AttributeResidentDataHeader *residentDataHeader() { return _attributeResidentDataHeader; }; AttributeNonResidentDataHeader *nonResidentDataHeader() { return _attributeNonResidentDataHeader; }; uint16_t mftEntrySize() { return _mftEntrySize; }; uint16_t indexRecordSize() { return _indexRecordSize; }; uint16_t sectorSize() { return _sectorSize; }; uint16_t clusterSize() { return _clusterSize; }; uint16_t parentMftOffset() { return _parentMftOffset; }; uint64_t *fixupIndexes() { return _fixupIndexes; }; uint16_t fixupIndexesSize() { return _fixupIndexesSize; }; uint64_t baseOffset() { return _baseOffset; }; void mftEntrySize(uint16_t size) { _mftEntrySize = size; }; void indexRecordSize(uint16_t size) { _indexRecordSize = size; }; void sectorSize(uint16_t size) { _sectorSize = size; }; void clusterSize(uint16_t size) { _clusterSize = size; }; uint64_t offsetFromID(uint32_t); uint32_t idFromOffset(uint64_t); void fixupOffsets(uint8_t); void fixupOffset(uint8_t, uint64_t); uint64_t getFixupOffset(uint8_t); std::string getName(); std::string getExtName(); std::string getFullName(); std::string getName(uint32_t); protected: uint16_t _parentMftOffset; uint16_t _bufferOffset; uint16_t _attributeOffset; uint8_t *_readBuffer; AttributeHeader *_attributeHeader; AttributeResidentDataHeader *_attributeResidentDataHeader; AttributeNonResidentDataHeader *_attributeNonResidentDataHeader; VFile *_vfile; uint8_t _fixupIndexesSize; uint64_t *_fixupIndexes; // Used in case attribute is non resident uint64_t _previousRunOffset; OffsetRun *_offsetList; uint16_t _currentRunIndex; uint16_t _offsetListSize; uint32_t _offsetInRun; uint16_t _offsetRunIndex; uint8_t _mftIndex; uint32_t _runAmount; uint64_t _baseOffset; uint64_t _attributeRealOffset; uint16_t _mftEntrySize; uint16_t _indexRecordSize; uint16_t _sectorSize; uint16_t _clusterSize; uint16_t _runList(uint16_t); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/000077500000000000000000000000001217176075400213215ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/attributelist.cpp000066400000000000000000000171051217176075400247300ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "vfile.hpp" #include "attributelist.hpp" AttributeAttributeList::AttributeAttributeList(VFile *vFile, Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _readBuffer = parent.readBuffer(); _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _currentEntry = 0; _vfile = vFile; _clusterSize = parent.clusterSize(); _baseOffset = 0; _bufferOffset = parent.bufferOffset(); _offsetListSize = 0; _mftIndex = 0; _mftEntrySize = parent.mftEntrySize(); _indexRecordSize = parent.indexRecordSize(); _sectorSize = parent.sectorSize(); _clusterSize = parent.clusterSize(); _currentRunIndex = 0; if (_attributeHeader->nonResidentFlag) { _attributeNonResidentDataHeader = new AttributeNonResidentDataHeader(*(parent.nonResidentDataHeader())); setRunList(); size(_attributeNonResidentDataHeader->attributeContentActualSize); _contentBuffer = new uint8_t[_size]; uint64_t readOffset; uint64_t readPos = 0; uint64_t readSize = _size; uint64_t readed = 0; while ((readOffset = nextOffset())) { readed = _vfile->seek(readOffset); if (readSize > _clusterSize) { readed = _vfile->read(_contentBuffer + readPos, _clusterSize); //XXX if (readed == 0) break; readPos += readed; readSize -= readed; } else { readed = _vfile->read(_contentBuffer + readPos, readSize); //XXX if (readed == 0) break; readPos += readed; readSize = 0; } } _dataOffset = 0; } else { uint8_t i; _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); size(_attributeResidentDataHeader->contentSize); offset(_attributeResidentDataHeader->contentOffset); _fixupIndexesSize = parent.fixupIndexesSize(); _fixupIndexes = new uint64_t[_fixupIndexesSize]; for (i = 0; i < _fixupIndexesSize; i++) { _fixupIndexes[i] = parent.fixupIndexes()[i]; } _dataOffset = _attributeResidentDataHeader->contentOffset; } // content(); } AttributeAttributeList::~AttributeAttributeList() { ; } void AttributeAttributeList::content() { uint16_t contentSize; if (_attributeHeader->nonResidentFlag) { DEBUG(CRITICAL, "This attribute list is non-resident, content display not developped yet\n"); return; } else { contentSize = _attributeResidentDataHeader->contentSize; } while (_dataOffset < contentSize) { if (_attributeHeader->nonResidentFlag) { ; } else { DEBUG(INFO, "attribute content ? offset 0x%x size 0x%x\n", _dataOffset + _bufferOffset, _attributeResidentDataHeader->contentSize); _data = (AttributeAttributeList_t *)(_readBuffer + _bufferOffset + _dataOffset); } printf("\t\tAttribute type 0x%x: %s\n", _data->attributeType, getName(_data->attributeType).c_str()); printf("\t\tEntry length 0x%x\n", _data->entryLength); printf("\t\tLength of name 0x%x\n", _data->nameLength); printf("\t\tOffset to name 0x%x\n", _data->nameOffset); #if __WORDSIZE == 64 printf("\t\tStarting VCN in attribute 0x%lx\n", _data->startingVCNInAttribute); printf("\t\tFile reference where attribute is located 0x%lx\n", _data->fileReference); printf("\t\tMftEntry reference %lu (0x%lx)\n", _data->fileReference & 0xffffffUL, _data->fileReference & 0xffffffUL); #else printf("\t\tStarting VCN in attribute 0x%llx\n", _data->startingVCNInAttribute); printf("\t\tFile reference where attribute is located 0x%llx\n", _data->fileReference); printf("\t\tMftEntry reference %llu (0x%llx)\n", _data->fileReference & 0xffffffULL, _data->fileReference & 0xffffffULL); #endif printf("\t\tAttribute ID 0x%x\n\n", _data->attributeID); _dataOffset += _data->entryLength; } _dataOffset = _attributeResidentDataHeader->contentOffset; } uint32_t AttributeAttributeList::getExternalAttributeIndexRoot() { uint16_t contentSize; if (_attributeHeader->nonResidentFlag) { return 0; } else { contentSize = _attributeResidentDataHeader->contentSize; } while (_dataOffset < contentSize) { if (_attributeHeader->nonResidentFlag) { return 0; } else { _data = (AttributeAttributeList_t *)(_readBuffer + _bufferOffset + _dataOffset); } if (_data->attributeType == ATTRIBUTE_INDEX_ROOT) { #if __WORDSIZE == 64 return _data->fileReference & 0xffffffUL; #else return _data->fileReference & 0xffffffULL; #endif } _dataOffset += _data->entryLength; } return 0; } uint32_t AttributeAttributeList::getExternalAttributeIndexAlloc() { uint16_t contentSize; if (_attributeHeader->nonResidentFlag) { return 0; } else { contentSize = _attributeResidentDataHeader->contentSize; } while (_dataOffset < contentSize) { if (_attributeHeader->nonResidentFlag) { return 0; } else { _data = (AttributeAttributeList_t *)(_readBuffer + _bufferOffset + _dataOffset); } if (_data->attributeType == ATTRIBUTE_INDEX_ALLOCATION) { #if __WORDSIZE == 64 return _data->fileReference & 0xffffffUL; #else return _data->fileReference & 0xffffffULL; #endif } _dataOffset += _data->entryLength; } return 0; } uint32_t AttributeAttributeList::getExternalAttributeFileName() { uint32_t mftEntry; uint16_t contentSize; if (_attributeHeader->nonResidentFlag) { contentSize = _size; } else { contentSize = _attributeResidentDataHeader->contentSize; } while (_dataOffset < contentSize) { if (_attributeHeader->nonResidentFlag) { _data = (AttributeAttributeList_t *)(_contentBuffer + _dataOffset); } else { _data = (AttributeAttributeList_t *)(_readBuffer + _bufferOffset + _dataOffset); } if (_data->attributeType == ATTRIBUTE_FILE_NAME) { #if __WORDSIZE == 64 mftEntry = _data->fileReference & 0xffffffUL; #else mftEntry = _data->fileReference & 0xffffffULL; #endif if (mftEntry != _currentEntry && mftEntry != _id) { _currentEntry = mftEntry; return mftEntry; } } if (!_data->entryLength) { return 0; } _dataOffset += _data->entryLength; } return 0; } uint32_t AttributeAttributeList::getExternalAttributeData() { uint16_t contentSize; if (_attributeHeader->nonResidentFlag) { contentSize = _size; } else { contentSize = _attributeResidentDataHeader->contentSize; } while (_dataOffset < contentSize) { if (_attributeHeader->nonResidentFlag) { _data = (AttributeAttributeList_t *)(_contentBuffer + _dataOffset); } else { _data = (AttributeAttributeList_t *)(_readBuffer + _bufferOffset + _dataOffset); } if (_data->attributeType == ATTRIBUTE_DATA) { _dataOffset += _data->entryLength; #if __WORDSIZE == 64 return _data->fileReference & 0xffffffUL; #else return _data->fileReference & 0xffffffULL; #endif } if (_data->entryLength == 0) //XXX fixed but it always come here sometime ? { return 0; } _dataOffset += _data->entryLength; } return 0; } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/attributelist.hpp000066400000000000000000000040351217176075400247330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __ATTRIBUTELIST_HPP__ #define __ATTRIBUTELIST_HPP__ #include "common.hpp" #include "attribute.hpp" #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $ATTRIBUTE_LIST attribute * Used for files that have attribute headers that will not fit into one * MFT entry, contains a list with an entry for every attribute in the file * or directory. * * windows/system32 have it */ #define ATTRIBUTE_ATTRIBUTE_LIST_SIZE 25 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeAttributeList { uint32_t attributeType; uint16_t entryLength; uint8_t nameLength; uint8_t nameOffset; // relative to start of this entry uint64_t startingVCNInAttribute; uint64_t fileReference; // file reference where attribute is located uint8_t attributeID; } PACK AttributeAttributeList_t; class AttributeAttributeList : Attribute { public: AttributeAttributeList(VFile *, Attribute &); ~AttributeAttributeList(); void content(); void setMftEntry(uint32_t id) { _id = id; }; uint32_t getExternalAttributeIndexRoot(); uint32_t getExternalAttributeIndexAlloc(); uint32_t getExternalAttributeFileName(); uint32_t getExternalAttributeData(); void size(uint64_t size) { _size = size; }; void offset(uint64_t offset) { _offset = offset; }; private: AttributeAttributeList_t *_data; uint32_t _id; uint32_t _currentEntry; uint16_t _dataOffset; uint64_t _size; uint64_t _offset; uint8_t *_contentBuffer; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/bitmap.cpp000066400000000000000000000055311217176075400233050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include #include #include "bitmap.hpp" AttributeBitmap::AttributeBitmap(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _readBuffer = parent.readBuffer(); _baseOffset = 0; _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _offsetListSize = 0; _mftEntrySize = parent.mftEntrySize(); _indexRecordSize = parent.indexRecordSize(); _sectorSize = parent.sectorSize(); _clusterSize = parent.clusterSize(); _currentRunIndex = 0; if (_attributeHeader->nonResidentFlag) { setRunList(); _attributeNonResidentDataHeader = new AttributeNonResidentDataHeader(*(parent.nonResidentDataHeader())); size(_attributeNonResidentDataHeader->attributeContentActualSize); } else { uint8_t i; _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); size(_attributeResidentDataHeader->contentSize); offset(_attributeResidentDataHeader->contentOffset); _fixupIndexesSize = parent.fixupIndexesSize(); _fixupIndexes = new uint64_t[_fixupIndexesSize]; for (i = 0; i < _fixupIndexesSize; i++) { _fixupIndexes[i] = parent.fixupIndexes()[i]; } } } AttributeBitmap::~AttributeBitmap() { ; } template std::ostringstream &AttributeBitmap::bin(T &value, std::ostringstream &o) { for (T bit = highbit(bit); bit; bit >>= 1 ) { o << ( ( value & bit ) ? '1' : '0' ); } return o; } void AttributeBitmap::content() { uint32_t i = 0; std::ostringstream bitmap; bitmap.str(""); while (i < _size) { bitmap << std::hex << std::setw(2) << std::setfill('0') << (uint16_t)(*(uint8_t *)(_readBuffer + _attributeOffset + _offset + i)); if (i % 2) { bitmap << ' '; } i++; } printf("\t%s\n", bitmap.str().c_str()); bitmap.str(""); i = 0; while (i < _size) { // bitmap << std::binary((uint16_t)(*(uint8_t *)(_readBuffer + _attributeOffset + _offset + i))); // bin( uint8_t val = (uint8_t)(*(uint8_t *)(_readBuffer + _attributeOffset + _offset + i)); bin(val, bitmap); if (i % 2) { bitmap << std::endl << "\t"; } i++; } printf("\t%s\n", bitmap.str().c_str()); } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/bitmap.hpp000066400000000000000000000027601217176075400233130ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __BITMAP_HPP__ #define __BITMAP_HPP__ #include "common.hpp" #include "attribute.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $BITMAP attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeBitmap { uint8_t todo; } PACK AttributeBitmap_t; class AttributeBitmap : public Attribute { public: AttributeBitmap(Attribute &); ~AttributeBitmap(); void content(); // uint64_t nextOffset(); void size(uint64_t size) { _size = size; }; void offset(uint64_t offset) { _offset = offset; }; template inline T highbit(T &t) { return t = (((T)(-1)) >> 1) + 1; }; template std::ostringstream &bin(T &, std::ostringstream &); private: uint64_t _currentOffset; uint64_t _size; uint64_t _offset; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/data.cpp000066400000000000000000000040321217176075400227350ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include "stdio.h" #include "data.hpp" AttributeData::AttributeData() { size(0); offset(0); } AttributeData::AttributeData(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _readBuffer = parent.readBuffer(); _baseOffset = 0; _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _offsetListSize = 0; _mftIndex = 0; _mftEntrySize = parent.mftEntrySize(); _indexRecordSize = parent.indexRecordSize(); _sectorSize = parent.sectorSize(); _clusterSize = parent.clusterSize(); _currentRunIndex = 0; if (_attributeHeader->nonResidentFlag) { setRunList(); _attributeNonResidentDataHeader = new AttributeNonResidentDataHeader(*(parent.nonResidentDataHeader())); size(_attributeNonResidentDataHeader->attributeContentActualSize); } else { uint8_t i; _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); size(_attributeResidentDataHeader->contentSize); offset(_attributeResidentDataHeader->contentOffset); _fixupIndexesSize = parent.fixupIndexesSize(); _fixupIndexes = new uint64_t[_fixupIndexesSize]; for (i = 0; i < _fixupIndexesSize; i++) { _fixupIndexes[i] = parent.fixupIndexes()[i]; } } DEBUG(INFO, "Data copy ok !!!!\n"); } AttributeData::~AttributeData() { ; } void AttributeData::content() { DEBUG(INFO, "In data content !!\n"); } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/data.hpp000066400000000000000000000031131217176075400227410ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __DATA_HPP__ #define __DATA_HPP__ #include "common.hpp" #include "attribute.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $DATA attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeData { uint8_t todo; } PACK AttributeData_t; class AttributeData : public Attribute { public: AttributeData(); AttributeData(Attribute &); ~AttributeData(); void content(); uint64_t getSize() { return _size; }; uint64_t getInitSize() { return _attributeNonResidentDataHeader->attributeContentInitializedSize; }; void size(uint64_t size) { _size = size; }; uint64_t getOffset() { return _offset; }; void offset(uint64_t offset) { _offset = offset; }; uint64_t getAttributeOffset() { return _attributeOffset; }; uint16_t getSectorSize() { return _sectorSize; }; private: uint64_t _size; uint64_t _offset; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/filename.cpp000066400000000000000000000141131217176075400236050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include #include "filename.hpp" AttributeFileName::AttributeFileName(Attribute &parent) { uint8_t *name; UnicodeString us; _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); _readBuffer = parent.readBuffer(); _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _data = new AttributeFileName_t(*((AttributeFileName_t *)(_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset))); name = (_readBuffer + _bufferOffset + ATTRIBUTE_FN_SIZE + _attributeResidentDataHeader->contentOffset); us = UnicodeString((char*)name, _attributeResidentDataHeader->contentSize - ATTRIBUTE_FN_SIZE, "UTF-16LE"); us.toUTF8String(_filename); //DEBUG(INFO, "found filename: %s\n", _filename.c_str()); // content(); } AttributeFileName::~AttributeFileName() { ; } std::string AttributeFileName::getFileName() { return _filename; } void AttributeFileName::content() { struct tm *date; std::string dateString; #if __WORDSIZE == 64 printf("\tParent directory fileref 0x%.16lx\n", _data->parentDirectoryFileReference); printf("\tReal size of file %ld bytes\n", _data->realSizeOfFile); #else printf("\tParent directory fileref 0x%.16llx\n", _data->parentDirectoryFileReference); printf("\tReal size of file %lld bytes\n", _data->realSizeOfFile); #endif printf("\tFilename data: %s\n", _filename.c_str()); setDateToString(_data->fileCreationTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tFile creation time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->fileCreationTime); #else printf("\tFile creation time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->fileCreationTime); #endif setDateToString(_data->fileModificationTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tFile modification time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->fileModificationTime); #else printf("\tFile modification time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->fileModificationTime); #endif setDateToString(_data->mftModificationTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tMFT modification time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->mftModificationTime); #else printf("\tMFT modification time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->mftModificationTime); #endif setDateToString(_data->fileAccessTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tFile access time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->fileAccessTime); #else printf("\tFile access time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->fileAccessTime); #endif printf("\tFlags 0x%x\n", _data->flags); if (_data->flags & ATTRIBUTE_SI_FLAG_READ_ONLY) { printf("\t\tRead only\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_HIDDEN) { printf("\t\tHidden\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_SYSTEM) { printf("\t\tSystem\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) { printf("\t\tArchive\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_DEVICE) { printf("\t\tDevice\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_SHARPNORMAL) { printf("\t\t#Normal\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_TEMPORARY) { printf("\t\tTemporary\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_SPARSE_FILE) { printf("\t\tSparse\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_REPARSE_POINT) { printf("\t\tReparse point\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_COMPRESSED) { printf("\t\tCompressed\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_OFFLINE) { printf("\t\tOffline\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED) { printf("\t\tContent is not being indexed for faster searches\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_ENCRYPTED) { printf("\t\tEncrypted\n"); } if (!(_data->flags & ATTRIBUTE_SI_FLAG_READ_ONLY) && !(_data->flags & ATTRIBUTE_SI_FLAG_HIDDEN) && !(_data->flags & ATTRIBUTE_SI_FLAG_SYSTEM) && !(_data->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) && !(_data->flags & ATTRIBUTE_SI_FLAG_DEVICE) && !(_data->flags & ATTRIBUTE_SI_FLAG_SHARPNORMAL) && !(_data->flags & ATTRIBUTE_SI_FLAG_TEMPORARY) && !(_data->flags & ATTRIBUTE_SI_FLAG_SPARSE_FILE) && !(_data->flags & ATTRIBUTE_SI_FLAG_REPARSE_POINT) && !(_data->flags & ATTRIBUTE_SI_FLAG_COMPRESSED) && !(_data->flags & ATTRIBUTE_SI_FLAG_OFFLINE) && !(_data->flags & ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED) && !(_data->flags & ATTRIBUTE_SI_FLAG_ENCRYPTED)) { printf("\t\tunknown\n"); } printf("\tReparse value 0x%x\n", _data->reparseValue); printf("\tName length 0x%x\n", _data->nameLength); printf("\tNamespace is 0x%x corresponding to:\n", _data->nameSpace); if (_data->nameSpace & ATTRIBUTE_FN_NAMESPACE_POSIX) { printf("\t\tPOSIX (name is case sensitive, allows all Unicode chars except '/' and NULL)\n"); } if (_data->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32_AND_DOS) { printf("\t\tWin32 and DOS (original name fits in DOS namespace)\n"); } if (_data->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32) { printf("\t\tWin32 (name is case insensitive, allows most Unicode chars except '/', '\', ':', '>', '<' and '?')\n"); } if (_data->nameSpace & ATTRIBUTE_FN_NAMESPACE_DOS) { printf("\t\tDOS (name is case insensitive, upper case, no special chars, name length <= 8, extension length <= 3\n"); } } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/filename.hpp000066400000000000000000000042211217176075400236110ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __FILENAME_HPP__ #define __FILENAME_HPP__ #include "common.hpp" #include "attribute.hpp" #include "standardinformation.hpp" // need flags #include #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $FILE_NAME attribute * Used in two places : * - As MFT entry : does not contain any essential information * - As directory index : does contain essential information */ #define ATTRIBUTE_FN_NAMESPACE_POSIX 0x0 #define ATTRIBUTE_FN_NAMESPACE_WIN32_AND_DOS 0x3 #define ATTRIBUTE_FN_NAMESPACE_WIN32 0x1 #define ATTRIBUTE_FN_NAMESPACE_DOS 0x2 #define ATTRIBUTE_FN_SIZE 66 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeFileName { uint64_t parentDirectoryFileReference; // Windows displays/update times uint64_t fileCreationTime; // from $STANDARD_INFORMATION, uint64_t fileModificationTime; // not these ones uint64_t mftModificationTime; uint64_t fileAccessTime; uint64_t allocatedSizeOfFile; uint64_t realSizeOfFile; uint32_t flags; // Same as for $STANDARD_INFORMATION uint32_t reparseValue; uint8_t nameLength; // Essential in directory index uint8_t nameSpace; // Essential in directory index //uint8_t *name // Essential in directory index } PACK AttributeFileName_t; class AttributeFileName : public Attribute { public: AttributeFileName(Attribute &); ~AttributeFileName(); void content(); std::string getFileName(); void appendToFileName(std::string); AttributeFileName_t *data() { return _data; }; private: std::string _filename; AttributeFileName_t *_data; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/indexallocation.cpp000066400000000000000000000404041217176075400252040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "vfile.hpp" #include "indexallocation.hpp" #include "attributes/filename.hpp" AttributeIndexAllocation::AttributeIndexAllocation(VFile *vFile, uint64_t indexAllocOffset) { _vfile = vFile; _baseOffset = indexAllocOffset; _indexRecordSize = 4096; _sectorSize = 512; _contentBuffer = new uint8_t[_indexRecordSize]; _vfile->seek(_baseOffset); _vfile->read(_contentBuffer, _indexRecordSize); _data = (AttributeIndexAllocation_t *)(_contentBuffer); _contentBufferOffset = 0; dumpHeader(); //fixup if (_data->fixupAmount > 0) { uint8_t i; uint8_t lbreak = 0; i = 0; DEBUG(INFO, "Fixup register\n"); _fixupValues = new uint16_t[_data->fixupAmount]; _contentBufferOffset += _data->fixupArrayOffset; _fixupSignature = *(uint16_t *)(_contentBuffer + _contentBufferOffset); DEBUG(INFO, "\tfixupSignature: 0x%.4x\n", _fixupSignature); _contentBufferOffset += SIZE_2BYTES; while (i < _data->fixupAmount) { _fixupValues[i] = *(uint16_t *)(_contentBuffer + _contentBufferOffset); DEBUG(INFO, "\tfixupValue #%u: 0x%.4x\n", i, _fixupValues[i]); _contentBufferOffset += SIZE_2BYTES; i++; if (lbreak++ == 255) break; } DEBUG(INFO, "Fixup validate and set\n"); i = 0; lbreak = 0; while (i < _data->fixupAmount - 1) { uint16_t *valToFix = (uint16_t *)(_contentBuffer + ((i + 1) * _sectorSize) - 2); DEBUG(INFO, "\tGot: 0x%.4x\n", *valToFix); *valToFix = _fixupValues[i]; DEBUG(INFO, "\tWrote: 0x%.4x\n", *valToFix); i++; if (lbreak++ == 255) break; } } _nodeHeader = (NodeHeader *)(_contentBuffer + ATTRIBUTE_IA_SIZE); _entryOffset = ATTRIBUTE_IA_SIZE + _nodeHeader->relOffsetStart; } AttributeIndexAllocation::AttributeIndexAllocation(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _readBuffer = parent.readBuffer(); _baseOffset = parent.baseOffset(); _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _offsetListSize = 0; _vfile = parent.vfile(); _mftEntrySize = parent.mftEntrySize(); _indexRecordSize = parent.indexRecordSize(); _sectorSize = parent.sectorSize(); _clusterSize = parent.clusterSize(); _currentRunIndex = 0; DEBUG(INFO, "setting clustersize to 0x%x\n", _clusterSize); _entryOffset = 0; _nodeHeader = NULL; _parentMftOffset = parent.parentMftOffset(); if (_attributeHeader->nonResidentFlag) { setRunList(); #if __WORDSIZE == 64 DEBUG(INFO, "run amount1 0x%lx\n", offsetsRuns()[0].runOffset); #else DEBUG(INFO, "run amount1 0x%llx\n", offsetsRuns()[0].runOffset); #endif } } AttributeIndexAllocation::~AttributeIndexAllocation() { ; } /** * Also fill buffer of first records */ void AttributeIndexAllocation::fillRecords(uint32_t sectorSize, uint32_t clusterSize, uint32_t indexRecordSize) { uint8_t i; uint8_t lbreak = 0; #if __WORDSIZE == 64 DEBUG(INFO, "run amount2 0x%lx\n", offsetsRuns()[0].runOffset); #else DEBUG(INFO, "run amount2 0x%llx\n", offsetsRuns()[0].runOffset); #endif _indexRecordSize = indexRecordSize; _sectorSize = sectorSize; _clusterSize = clusterSize; if (_attributeHeader->nonResidentFlag) { _realOffset = nextOffset();// * _indexRecordSize; } else { #if __WORDSIZE == 64 DEBUG(INFO, "0x%lx 0x%x 0x%x\n", _baseOffset, _attributeOffset, _bufferOffset); #else DEBUG(INFO, "0x%llx 0x%x 0x%x\n", _baseOffset, _attributeOffset, _bufferOffset); #endif ; } _contentBuffer = new uint8_t[_indexRecordSize]; _contentBufferOffset = 0; #if __WORDSIZE == 64 DEBUG(INFO, "Reading 0x%x bytes IndexAllocation @ 0x%lx\n", _indexRecordSize, _realOffset); #else DEBUG(INFO, "Reading 0x%x bytes IndexAllocation @ 0x%llx\n", _indexRecordSize, _realOffset); #endif _vfile->seek(_realOffset); _vfile->read(_contentBuffer, _indexRecordSize); _data = (AttributeIndexAllocation_t *)_contentBuffer; if (_data->fixupArrayOffset >= _indexRecordSize || (_data->fixupAmount * sectorSize) > _indexRecordSize + sectorSize) { _nodeHeader = NULL; return ; } // TODO validate signature DEBUG(INFO, "fixupArrayOffset: 0x%x\n", _data->fixupArrayOffset); DEBUG(INFO, "fixupAmount: 0x%x\n", _data->fixupAmount); #if __WORDSIZE == 64 DEBUG(INFO, "sequenceNumber 0x%.16lx\n", _data->sequenceNumber); DEBUG(INFO, "VCN of this record: 0x%.16lx\n", _data->recordVCN); #else DEBUG(INFO, "sequenceNumber 0x%.16llx\n", _data->sequenceNumber); DEBUG(INFO, "VCN of this record: 0x%.16llx\n", _data->recordVCN); #endif //fixup if (_data->fixupAmount > 0) { i = 0; _fixupValues = new uint16_t[_data->fixupAmount]; _contentBufferOffset += _data->fixupArrayOffset; _fixupSignature = *(uint16_t *)(_contentBuffer + _contentBufferOffset); DEBUG(INFO, "fixupSignature: 0x%.4x\n", _fixupSignature); _contentBufferOffset += SIZE_2BYTES; while (i < _data->fixupAmount) { _fixupValues[i] = *(uint16_t *)(_contentBuffer + _contentBufferOffset); DEBUG(INFO, "fixupValue: 0x%.4x\n", _fixupValues[i]); _contentBufferOffset += SIZE_2BYTES; i++; if (lbreak++ == 255) break; } i = 0; lbreak = 0; while (i < _data->fixupAmount - 1) { uint16_t *valToFix = (uint16_t *)(_contentBuffer + ((i + 1) * _sectorSize) - 2); DEBUG(INFO, "Got: 0x%.4x\n", *valToFix); *valToFix = _fixupValues[i]; DEBUG(INFO, "Wrote: 0x%.4x\n", *valToFix); i++; if (lbreak++ == 255) break; } } _nodeHeader = (NodeHeader *)(_contentBuffer + ATTRIBUTE_IA_SIZE); _entryOffset = ATTRIBUTE_IA_SIZE + _nodeHeader->relOffsetStart; } bool AttributeIndexAllocation::_hasMoreAllocation() { uint8_t i; uint8_t lbreak = 0; uint8_t chunckShift = _indexRecordSize / _clusterSize; if (_currentRunIndex >= getOffsetRun(_offsetRunIndex)->runLength && (_offsetRunIndex + 1) >= _offsetListSize) { return false; } // FIXME getting next indexallocation is not reliable if _indexRecordSize > _clusterSize, // except if chunck are NOT fragmented. while (chunckShift) { if (!(_realOffset = nextOffset())) { return false; } chunckShift--; } delete _contentBuffer; _contentBuffer = new uint8_t[_indexRecordSize]; _contentBufferOffset = 0; #if __WORDSIZE == 64 DEBUG(INFO, "Reading 0x%x bytes IndexAllocation @ 0x%lx\n", _indexRecordSize, _realOffset); #else DEBUG(INFO, "Reading 0x%x bytes IndexAllocation @ 0x%llx\n", _indexRecordSize, _realOffset); #endif _vfile->seek(_realOffset); _vfile->read(_contentBuffer, _indexRecordSize); _data = (AttributeIndexAllocation_t *)_contentBuffer; DEBUG(INFO, "fixup amount is %u attribute is non-resident ? %u\n", _data->fixupAmount, _attributeHeader->nonResidentFlag); if (!(_attributeHeader->nonResidentFlag) && _data->fixupAmount > 0) { i = 0; delete _fixupValues; _fixupValues = new uint16_t[_data->fixupAmount]; _contentBufferOffset += _data->fixupArrayOffset; _fixupSignature = *(uint16_t *)(_contentBuffer + _contentBufferOffset); _contentBufferOffset += SIZE_2BYTES; while (i < _data->fixupAmount) { _fixupValues[i] = *(uint16_t *)(_contentBuffer + _contentBufferOffset); _contentBufferOffset += SIZE_2BYTES; i++; if (lbreak++ == 255) break; } i = 0; lbreak = 0; while (i < _data->fixupAmount - 1) { uint16_t *valToFix = (uint16_t *)(_contentBuffer + ((i + 1) * _sectorSize) - 2); *valToFix = _fixupValues[i]; i++; if (lbreak++ == 255) break; } } _nodeHeader = (NodeHeader *)(_contentBuffer + ATTRIBUTE_IA_SIZE); _entryOffset = ATTRIBUTE_IA_SIZE + _nodeHeader->relOffsetStart; return true; } uint32_t AttributeIndexAllocation::getEntryOffset() { if (_nodeHeader == NULL) { return 0; } uint16_t end = _nodeHeader->relOffsetEndUsed; if (_entryOffset >= end || _entryOffset >= _indexRecordSize) { DEBUG(INFO, "before 0x%x\n", _nodeHeader->relOffsetEndUsed); if (!(_hasMoreAllocation())) { DEBUG(INFO, "after 0x%x\n", _nodeHeader->relOffsetEndUsed); DEBUG(INFO, "no more indexalloc end is 0x%x\n", end); // return end; return _nodeHeader->relOffsetEndUsed; } } // FIXME : Validate INDX signature ! if (_entryOffset >= _nodeHeader->relOffsetEndUsed || _entryOffset >= _indexRecordSize) { while (_nodeHeader && _nodeHeader->relOffsetEndUsed && _hasMoreAllocation() && _entryOffset > _nodeHeader->relOffsetEndUsed) { DEBUG(INFO, "entry now 0x%x end 0x%x\n", _entryOffset, _nodeHeader->relOffsetEndUsed); } } return _entryOffset; } uint32_t AttributeIndexAllocation::readNextIndex() { DirectoryIndexEntry *indexEntry; AttributeFileName_t *attributeFileName; std::ostringstream filename; uint32_t i; uint8_t *name; uint32_t mftEntry; if (_entryOffset == 0) { _entryOffset = ATTRIBUTE_IA_SIZE + _nodeHeader->relOffsetStart; } DEBUG(INFO, "relOffsetEndUsed 0x%x\n", _nodeHeader->relOffsetEndUsed); DEBUG(INFO, "relOffsetEndAlloc 0x%x\n", _nodeHeader->relOffsetEndAlloc); DEBUG(INFO, "flags 0x%x\n\n", _nodeHeader->flags); if (_entryOffset >= _nodeHeader->relOffsetEndUsed || _entryOffset >= _indexRecordSize) { return 0; } indexEntry = (DirectoryIndexEntry *)(_contentBuffer + _entryOffset); if (indexEntry->entryLength == 0) { return 0; } #if __WORDSIZE == 64 mftEntry = indexEntry->fileNameMFTFileReference & 0xffffffUL; #else mftEntry = indexEntry->fileNameMFTFileReference & 0xffffffULL; #endif DEBUG(INFO, "mftEntry: 0x%x (%u)\n", mftEntry, mftEntry); DEBUG(INFO, "currentOffset: 0x%x\n", _entryOffset); DEBUG(INFO, " entryLength: 0x%x\n", indexEntry->entryLength); DEBUG(INFO, " fileNameLength: 0x%x\n", indexEntry->fileNameLength); if (indexEntry->flags & ENTRY_CHILD_NODE_EXIST) { DEBUG(INFO, " Has child\n"); ; } if (indexEntry->flags & ENTRY_LAST_ONE) { ; DEBUG(INFO, " Is the last entry\n"); } filename.str(""); attributeFileName = (AttributeFileName_t *)(_contentBuffer + _entryOffset + DIRECTORY_INDEX_ENTRY_SIZE); DEBUG(INFO, " attributeFileNameLength: 0x%x\n", attributeFileName->nameLength); #if __WORDSIZE == 64 DEBUG(INFO, " nameoffset: 0x%lx\n", _realOffset + _entryOffset + DIRECTORY_INDEX_ENTRY_SIZE + ATTRIBUTE_FN_SIZE); #else DEBUG(INFO, " nameoffset: 0x%llx\n", _realOffset + _entryOffset + DIRECTORY_INDEX_ENTRY_SIZE + ATTRIBUTE_FN_SIZE); #endif name = (_contentBuffer + _entryOffset + DIRECTORY_INDEX_ENTRY_SIZE + ATTRIBUTE_FN_SIZE + 8); for (i = 0; i < 100; i++) { if (!(i % 2)) { if (name[i] >= 0x20 && name[i] <= 0x7e) { filename << name[i]; } if (name[i] == 0) break; } } #if __WORDSIZE == 64 DEBUG(INFO, " parent fileref: 0x%.16lx\n", attributeFileName->parentDirectoryFileReference); DEBUG(INFO, " seqNumber: 0x%.16lx, mftEntry: 0x%.16lx\n", (attributeFileName->parentDirectoryFileReference & 0xffff000000000000UL) >> 0x30, attributeFileName->parentDirectoryFileReference & 0x0000ffffffffffffUL); DEBUG(INFO, " realSizeOfFile: 0x%lx\n", attributeFileName->realSizeOfFile); #else DEBUG(INFO, " parent fileref: 0x%.16llx\n", attributeFileName->parentDirectoryFileReference); DEBUG(INFO, " seqNumber: 0x%.16llx, mftEntry: 0x%.16llx\n", (attributeFileName->parentDirectoryFileReference & 0xffff000000000000ULL) >> 0x30, attributeFileName->parentDirectoryFileReference & 0x0000ffffffffffffULL); DEBUG(INFO, " realSizeOfFile: 0x%llx\n", attributeFileName->realSizeOfFile); #endif DEBUG(INFO, " length1: %u\n", indexEntry->fileNameLength); DEBUG(INFO, " length2: %u\n", attributeFileName->nameLength); DEBUG(INFO, " length3: %u\n", indexEntry->entryLength); DEBUG(INFO, " filename: %s\n", filename.str().c_str()); DEBUG(INFO, " flags: 0x%x\n", attributeFileName->flags); DEBUG(INFO, "current 0x%x end 0x%x mft# %u entryLength %u\n", _entryOffset, _nodeHeader->relOffsetEndUsed, mftEntry, indexEntry->entryLength); _entryOffset += indexEntry->entryLength; return mftEntry; } void AttributeIndexAllocation::content() { uint64_t currentOffset; while ((currentOffset = nextOffset())) { // currentOffset *= 1024; #if __WORDSIZE == 64 printf("currentOffset indexAllocation: 0x%lx\n", currentOffset); #else printf("currentOffset indexAllocation: 0x%llx\n", currentOffset); #endif } } void AttributeIndexAllocation::dumpHeader() { DEBUG(INFO, "Index allocation record header:\n\tsignature %c%c%c%c\n", _data->signature[0], _data->signature[1], _data->signature[2], _data->signature[3]); DEBUG(INFO, "\tfixupArrayOffset 0x%x\n", _data->fixupArrayOffset); DEBUG(INFO, "\tfixupAmount 0x%x\n", _data->fixupAmount); #if __WORDSIZE == 64 DEBUG(INFO, "\tsequenceNumber 0x%lx\n", _data->sequenceNumber); DEBUG(INFO, "\trecordVCN 0x%lx\n", _data->recordVCN); #else DEBUG(INFO, "\tsequenceNumber 0x%llx\n", _data->sequenceNumber); DEBUG(INFO, "\trecordVCN 0x%llx\n", _data->recordVCN); #endif } void AttributeIndexAllocation::dumpNodeHeader() { printf("Node header:\n"); printf("\trelOffsetStart: 0x%x\n", _nodeHeader->relOffsetStart); printf("\trelOffsetEndUsed: 0x%x\n", _nodeHeader->relOffsetEndUsed); printf("\trelOffsetEndAlloc: 0x%x\n", _nodeHeader->relOffsetEndAlloc); printf("\tflags: 0x%x\n", _nodeHeader->flags); } void AttributeIndexAllocation::dumpEntries() { DirectoryIndexEntry *current; AttributeFileName_t *attrFileName; std::ostringstream filename; uint32_t i; uint8_t *name; _bufferOffset = 0; while (_entryOffset < _indexRecordSize) { current = (DirectoryIndexEntry *)(_contentBuffer + _entryOffset); printf("Entry at offset 0x%x\n", _entryOffset); if (current->fileNameMFTFileReference & 0xffffffUL) { #if __WORDSIZE == 64 printf("\tmftEntry %lu\n", current->fileNameMFTFileReference & 0xffffffUL); #else printf("\tmftEntry %llu\n", current->fileNameMFTFileReference & 0xffffffUL); #endif } printf("\tentryLength 0x%x\n", current->entryLength); printf("\tfileNameLength 0x%x\n", current->fileNameLength); filename.str(""); attrFileName = (AttributeFileName_t *)(_contentBuffer + _entryOffset + DIRECTORY_INDEX_ENTRY_SIZE); printf("\tFilename attribute:\n"); printf("\t\tattributeFileNameLength: 0x%x\n", attrFileName->nameLength); name = (_contentBuffer + _entryOffset + DIRECTORY_INDEX_ENTRY_SIZE + ATTRIBUTE_FN_SIZE); for (i = 0; i < (uint32_t)(attrFileName->nameLength * 2); i++) { if (!(i % 2)) { // if (name[i] >= 0x20 && name[i] <= 0x7e) { filename << name[i]; // } // if (name[i] == 0) // break; } } #if __WORDSIZE == 64 printf("\t\tparent fileref: 0x%.16lx\n", attrFileName->parentDirectoryFileReference); printf("\t\t\tseqNumber: 0x%.16lx, mftEntry: %lu (0x%.16lx)\n", (attrFileName->parentDirectoryFileReference & 0xffff000000000000UL) >> 0x30, attrFileName->parentDirectoryFileReference & 0x0000ffffffffffffUL, attrFileName->parentDirectoryFileReference & 0x0000ffffffffffffUL); printf("\t\trealSizeOfFile: %lu (0x%lx\n)", attrFileName->realSizeOfFile, attrFileName->realSizeOfFile); #else printf("\t\tparent fileref: 0x%.16llx\n", attrFileName->parentDirectoryFileReference); printf("\t\t\tseqNumber: 0x%.16llx, mftEntry: 0x%.16llx\n", (attrFileName->parentDirectoryFileReference & 0xffff000000000000ULL) >> 0x30, attrFileName->parentDirectoryFileReference & 0x0000ffffffffffffULL); printf("\t\trealSizeOfFile: 0x%llx\n", attrFileName->realSizeOfFile); #endif printf("\t\tfilename: %s\n", filename.str().c_str()); printf("\t\tflags: 0x%x\n", attrFileName->flags); if (current->flags & ENTRY_CHILD_NODE_EXIST) { printf("\t\t Has child\n"); } if (current->flags & ENTRY_LAST_ONE) { printf("\t\t Is the last entry\n"); break; } _entryOffset += current->entryLength; } } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/indexallocation.hpp000066400000000000000000000040361217176075400252120ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __INDEXALLOCATION_HPP__ #define __INDEXALLOCATION_HPP__ #include "common.hpp" #include "attribute.hpp" #include "attributes/indexroot.hpp" #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $INDEX_ALLOCATION attribute */ #define ATTRIBUTE_IA_SIGNATURE "INDX" #define ATTRIBUTE_IA_SIZE 24 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeIndexAllocation { char signature[4]; uint16_t fixupArrayOffset; uint16_t fixupAmount; uint64_t sequenceNumber; //$Logfile LSN uint64_t recordVCN; // The VCN of this record in the full index stream } PACK AttributeIndexAllocation_t; class AttributeIndexAllocation : public Attribute { public: AttributeIndexAllocation(VFile *, uint64_t); AttributeIndexAllocation(Attribute &); ~AttributeIndexAllocation(); void content(); void fillRecords(uint32_t, uint32_t, uint32_t); uint32_t readNextIndex(); uint32_t getEntryOffset(); NodeHeader *getNodeHeader() { return _nodeHeader; }; uint64_t realOffset() { return _realOffset; }; void dumpHeader(); void dumpNodeHeader(); void dumpEntries(); private: AttributeIndexAllocation_t *_data; NodeHeader *_nodeHeader; // uint16_t _sectorSize; // uint16_t _clusterSize; // uint16_t _indexRecordSize; uint64_t _realOffset; uint8_t *_contentBuffer; uint32_t _contentBufferOffset; uint32_t _entryOffset; uint16_t *_fixupValues; uint16_t _fixupSignature; bool _hasMoreAllocation(); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/indexroot.cpp000066400000000000000000000152231217176075400240430ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "indexroot.hpp" AttributeIndexRoot::AttributeIndexRoot(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); _readBuffer = parent.readBuffer(); _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _data = new AttributeIndexRoot_t(*(AttributeIndexRoot_t *)(_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset)); _nodeHeader = new NodeHeader(*(NodeHeader *)(_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset + ATTRIBUTE_INDEXROOT_SIZE)); _currentRelativeOffset = _nodeHeader->relOffsetStart; _baseReadingOffset = _bufferOffset + ATTRIBUTE_INDEXROOT_SIZE + _attributeResidentDataHeader->contentOffset; _nextVCN = 0; _baseOffset = parent.baseOffset(); _lastEntryFound = false; _attributeRealOffset = parent.attributeRealOffset(); _entriesAmount = _saveEntries(); DEBUG(INFO, "found %u entries\n", _entriesAmount); // content(); } AttributeIndexRoot::~AttributeIndexRoot() { ; } uint32_t AttributeIndexRoot::_saveEntries() { uint32_t entriesCount = 0; uint32_t currentOffset = _nodeHeader->relOffsetStart; uint32_t baseOffset = _bufferOffset + ATTRIBUTE_INDEXROOT_SIZE + _attributeResidentDataHeader->contentOffset; IndexEntry *indexEntry; while (currentOffset < _nodeHeader->relOffsetEndAlloc) { indexEntry = (IndexEntry *)(_readBuffer + currentOffset + baseOffset); DEBUG(INFO, "indexEntryContentLength %u\n", indexEntry->contentLength); if (indexEntry->contentLength) { entriesCount++; } currentOffset += indexEntry->entryLength; } if (!entriesCount) { _indexEntries = NULL; _currentIndexEntry = 0; return 0; } _indexEntries = new IndexEntry *[entriesCount]; _entriesContent = new uint8_t *[entriesCount]; entriesCount = 0; currentOffset = _nodeHeader->relOffsetStart; while (currentOffset < _nodeHeader->relOffsetEndAlloc) { uint16_t i = 0; indexEntry = (IndexEntry *)(_readBuffer + currentOffset + baseOffset); if (indexEntry->contentLength) { _indexEntries[entriesCount] = new IndexEntry(*indexEntry); _entriesContent[entriesCount] = new uint8_t[indexEntry->contentLength]; while (i < indexEntry->contentLength) { _entriesContent[entriesCount] = (_readBuffer + currentOffset + baseOffset + INDEX_ENTRY_SIZE + i); i++; } entriesCount++; } currentOffset += indexEntry->entryLength; } _currentIndexEntry = 0; return entriesCount; } bool AttributeIndexRoot::hasNext() { DirectoryIndexEntry *indexEntry; if (_currentIndexEntry >= _entriesAmount || !_entriesAmount) { _currentMftEntry = 0; return false; } #if __WORDSIZE == 64 DEBUG(INFO, "base offset ? 0x%lx\n", _baseOffset); #else DEBUG(INFO, "base offset ? 0x%llx\n", _baseOffset); #endif indexEntry = (DirectoryIndexEntry *)_indexEntries[_currentIndexEntry]; if (!indexEntry->fileNameMFTFileReference) { _currentMftEntry = 0; return false; } _currentRelativeOffset += indexEntry->entryLength; #if __WORDSIZE == 64 DEBUG(INFO, "indexEntry: fileRef: 0x%lx\n\tentryLength: 0x%x\n\tfileNameLength: 0x%x\n", indexEntry->fileNameMFTFileReference, indexEntry->entryLength, indexEntry->fileNameLength); _currentMftEntry = indexEntry->fileNameMFTFileReference & 0xffffffUL; #else DEBUG(INFO, "indexEntry: fileRef: 0x%llx\n\tentryLength: 0x%x\n\tfileNameLength: 0x%x\n", indexEntry->fileNameMFTFileReference, indexEntry->entryLength, indexEntry->fileNameLength); _currentMftEntry = indexEntry->fileNameMFTFileReference & 0xffffffULL; #endif DEBUG(INFO, "_currentMftEntry is now %u\n", _currentMftEntry); _currentLength = _indexEntries[_currentIndexEntry]->entryLength; _currentIndexEntry++; return true; } uint32_t AttributeIndexRoot::nextMftEntry() { DEBUG(INFO, "_currentMftEntry return %u\n", _currentMftEntry); return _currentMftEntry; } void AttributeIndexRoot::content() { printf("\tType of attribute in index 0x%x: %s\n", _data->attributeInIndexType, getName(_data->attributeInIndexType).c_str()); printf("\tCollation sorting rule 0x%x\n", _data->collationSortingRule); printf("\tSize of each index record in bytes 0x%x\n", _data->indexRecordSizeBytes); printf("\tSize of each index record in clusters 0x%x\n", _data->indexRecordSizeClusters); printf("\tUnused 0x%.2x%.2x%.2x\n", _data->unused[0], _data->unused[1], _data->unused[2]); printf("\trelOffsetStart 0x%x\n", _nodeHeader->relOffsetStart); printf("\trelOffsetEndUsed 0x%x\n", _nodeHeader->relOffsetEndUsed); printf("\trelOffsetEndAlloc 0x%x\n", _nodeHeader->relOffsetEndAlloc); if (_nodeHeader->flags == ENTRY_CHILD_NODE_EXIST) { printf("\tflags 0x%x: child node exist\n", _nodeHeader->flags); } if (_data->attributeInIndexType == ATTRIBUTE_FILE_NAME) { uint32_t currentOffset = _nodeHeader->relOffsetStart; uint32_t baseOffset = _bufferOffset + ATTRIBUTE_INDEXROOT_SIZE + _attributeResidentDataHeader->contentOffset; IndexEntry *indexEntry; while (currentOffset < _nodeHeader->relOffsetEndAlloc) { indexEntry = (IndexEntry *)(_readBuffer + currentOffset + baseOffset); printf("\tEntry at index 0x%x:\n", currentOffset); printf("\t\tentryLength: 0x%x\n", indexEntry->entryLength); printf("\t\tcontentLength: 0x%x\n", indexEntry->contentLength); if (indexEntry->flags & ENTRY_CHILD_NODE_EXIST) printf("\t\tHas child\n"); if (indexEntry->flags & ENTRY_LAST_ONE) printf("\t\tIs the last entry\n"); currentOffset += indexEntry->entryLength; } } printf("\n"); } uint32_t AttributeIndexRoot::indexRecordSizeBytes() { return _data->indexRecordSizeBytes; } uint32_t AttributeIndexRoot::currentEntryLength() { if (_currentIndexEntry > _entriesAmount || !_entriesAmount) { return 0; } return _currentLength; } bool AttributeIndexRoot::canGetNext() { return (_currentIndexEntry >= _entriesAmount || !_entriesAmount); } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/indexroot.hpp000066400000000000000000000064531217176075400240550ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __INDEXROOT_HPP__ #define __INDEXROOT_HPP__ #include "common.hpp" #include "attribute.hpp" #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $INDEX_ROOT attribute */ #define ATTRIBUTE_INDEXROOT_SIZE 16 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeIndexRoot { uint32_t attributeInIndexType; // 0 if this entry does not use an attribute uint32_t collationSortingRule; uint32_t indexRecordSizeBytes; uint8_t indexRecordSizeClusters; uint8_t unused[3]; } PACK AttributeIndexRoot_t; /** * Node header following IndexRoot header */ #define NODEHEADER_SIZE 16 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_NodeHeader { uint32_t relOffsetStart; // Offset to start of index entry list, rel to start of node header uint32_t relOffsetEndUsed; // Offset to end of index entry list used area uint32_t relOffsetEndAlloc; uint32_t flags; // only 0x01, if this entry has children nodes } PACK NodeHeader; /** * Generic Index entry */ #define ENTRY_CHILD_NODE_EXIST 0x01 #define ENTRY_LAST_ONE 0x02 #define ENTRY_VCN_RELATIVE_OFFSET -8 #define INDEX_ENTRY_SIZE 16 #ifdef WIN32 #pragma pack(1) #endif typedef struct IndexEntry { uint64_t undefined; uint16_t entryLength; uint16_t contentLength; uint32_t flags; // 0x01 or 0x02 // content // last 8 bytes is starting VCN of child node in $INDEX_ALLOCATION (if flag set), // on an 8-byte boundary } PACK IndexEntry; /** * Directory Index entry */ #define DIRECTORY_INDEX_ENTRY_SIZE 16 #ifdef WIN32 #pragma pack(1) #endif typedef struct DirectoryIndexEntry { uint64_t fileNameMFTFileReference; uint16_t entryLength; uint16_t fileNameLength; uint32_t flags; // same as above // content // last 8 bytes is starting VCN of child node in $INDEX_ALLOCATION (if flag set), // on an 8-byte boundary } PACK DirectoryIndexEntry; class AttributeIndexRoot : Attribute { public: AttributeIndexRoot(Attribute &); ~AttributeIndexRoot(); void content(); uint32_t indexRecordSizeBytes(); bool hasNext(); AttributeIndexRoot_t *data() { return _data; }; NodeHeader *nodeHeader() { return _nodeHeader; }; uint32_t currentEntryOffset() { return _currentRelativeOffset; }; uint32_t currentEntryLength(); uint32_t nextMftEntry(); uint32_t entriesAmount() { return _entriesAmount; }; bool canGetNext(); private: AttributeIndexRoot_t *_data; NodeHeader *_nodeHeader; IndexEntry **_indexEntries; uint8_t **_entriesContent; uint16_t _currentIndexEntry; uint32_t _currentLength; uint32_t _currentRelativeOffset; uint32_t _baseReadingOffset; uint32_t _currentMftEntry; uint64_t _nextVCN; bool _lastEntryFound; uint32_t _entriesAmount; uint32_t _saveEntries(); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/reparsepoint.cpp000066400000000000000000000033001217176075400245340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "reparsepoint.hpp" AttributeReparsePoint::AttributeReparsePoint(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); _readBuffer = parent.readBuffer(); _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; } AttributeReparsePoint::~AttributeReparsePoint() { ; } void AttributeReparsePoint::content() { _data = (AttributeReparsePoint_t *)(_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); printf("\t\tFlags: 0x%x\n", _data->flags); printf("\t\tReparse data size: 0x%x\n", _data->reparseDataSize); printf("\t\tUnused: 0x%x\n", _data->unused); printf("\t\tOffset to target name: 0x%x\n", _data->targetNameOffset); printf("\t\tLength of target name: 0x%x\n", _data->targetNameLength); printf("\t\tOffset to print name of target: 0x%x\n", _data->targetPrintNameOffset); printf("\t\tLength of print name: 0x%x\n", _data->targetPrintNameLength); } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/reparsepoint.hpp000066400000000000000000000024431217176075400245500ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __REPARSEPOINT_HPP__ #define __REPARSEPOINT_HPP__ #include "common.hpp" #include "attribute.hpp" #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $SYMBOLINK_LINK_OR_REPARSE_POINT attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeReparsePoint { uint32_t flags; uint16_t reparseDataSize; uint16_t unused; uint16_t targetNameOffset; uint16_t targetNameLength; uint16_t targetPrintNameOffset; uint16_t targetPrintNameLength; } PACK AttributeReparsePoint_t; class AttributeReparsePoint : Attribute { public: AttributeReparsePoint(Attribute &); ~AttributeReparsePoint(); void content(); private: AttributeReparsePoint_t *_data; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/securitydescriptor.cpp000066400000000000000000000031651217176075400260000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "securitydescriptor.hpp" AttributeSecurityDescriptor::AttributeSecurityDescriptor(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _readBuffer = parent.readBuffer(); _baseOffset = 0; _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _offsetInRun = 0; _offsetRunIndex = 0; _offsetListSize = 0; _mftEntrySize = parent.mftEntrySize(); _indexRecordSize = parent.indexRecordSize(); _sectorSize = parent.sectorSize(); _clusterSize = parent.clusterSize(); _currentRunIndex = 0; if (_attributeHeader->nonResidentFlag) { setRunList(); DEBUG(INFO, "TODO !!\n"); } else { _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); _data = (AttributeSecurityDescriptor_t *)(_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset); } } AttributeSecurityDescriptor::~AttributeSecurityDescriptor() { ; } void AttributeSecurityDescriptor::content() { ; } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/securitydescriptor.hpp000066400000000000000000000022401217176075400257760ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __SECURITYDESCRIPTOR_HPP__ #define __SECURITYDESCRIPTOR_HPP__ #include "common.hpp" #include "attribute.hpp" #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $SECURITY_DESCRIPTOR attribute */ #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeSecurityDescriptor { uint8_t todo; } PACK AttributeSecurityDescriptor_t; class AttributeSecurityDescriptor : public Attribute { public: AttributeSecurityDescriptor(Attribute &); ~AttributeSecurityDescriptor(); void content(); private: AttributeSecurityDescriptor_t *_data; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/standardinformation.cpp000066400000000000000000000131121217176075400260710ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "standardinformation.hpp" AttributeStandardInformation::AttributeStandardInformation(Attribute &parent) { _attributeHeader = new AttributeHeader(*(parent.attributeHeader())); _attributeResidentDataHeader = new AttributeResidentDataHeader(*(parent.residentDataHeader())); _readBuffer = parent.readBuffer(); _attributeOffset = parent.attributeOffset(); _bufferOffset = parent.bufferOffset(); _mftEntrySize = parent.mftEntrySize(); _indexRecordSize = parent.indexRecordSize(); _sectorSize = parent.sectorSize(); _clusterSize = parent.clusterSize(); _offsetInRun = 0; _offsetRunIndex = 0; _data = new AttributeStandardInformation_t(*((AttributeStandardInformation_t *) (_readBuffer + _bufferOffset + _attributeResidentDataHeader->contentOffset))); // content(); } AttributeStandardInformation::~AttributeStandardInformation() { delete _data; delete _attributeHeader; delete _attributeResidentDataHeader; } void AttributeStandardInformation::content() { struct tm *date; std::string dateString; // _data = (AttributeStandardInformation_t *)(_readBuffer + _bufferOffset + // _attributeResidentDataHeader->contentOffset); setDateToString(_data->creationTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tSI Creation time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->creationTime); #else printf("\tSI Creation time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->creationTime); #endif setDateToString(_data->fileAlteredTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tSI File altered time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->fileAlteredTime); #else printf("\tSI File altered time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->fileAlteredTime); #endif setDateToString(_data->mftAlteredTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tSI MFT altered time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->mftAlteredTime); #else printf("\tSI MFT altered time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->mftAlteredTime); #endif setDateToString(_data->fileAccessedTime, &date, &dateString, true); #if __WORDSIZE == 64 printf("\tSI File accessed time:\t%s\t(0x%.16lx)\n", dateString.c_str(), _data->fileAccessedTime); #else printf("\tSI File accessed time:\t%s\t(0x%.16llx)\n", dateString.c_str(), _data->fileAccessedTime); #endif printf("\tFlags 0x%x\n", _data->flags); if (_data->flags & ATTRIBUTE_SI_FLAG_READ_ONLY) { printf("\t\tRead only\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_HIDDEN) { printf("\t\tHidden\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_SYSTEM) { printf("\t\tSystem\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) { printf("\t\tArchive\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_DEVICE) { printf("\t\tDevice\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_SHARPNORMAL) { printf("\t\t#Normal\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_TEMPORARY) { printf("\t\tTemporary\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_SPARSE_FILE) { printf("\t\tSparse\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_REPARSE_POINT) { printf("\t\tReparse point\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_COMPRESSED) { printf("\t\tCompressed\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_OFFLINE) { printf("\t\tOffline\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED) { printf("\t\tContent is not being indexed for faster searches\n"); } if (_data->flags & ATTRIBUTE_SI_FLAG_ENCRYPTED) { printf("\t\tEncrypted\n"); } if (!(_data->flags & ATTRIBUTE_SI_FLAG_READ_ONLY) && !(_data->flags & ATTRIBUTE_SI_FLAG_HIDDEN) && !(_data->flags & ATTRIBUTE_SI_FLAG_SYSTEM) && !(_data->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) && !(_data->flags & ATTRIBUTE_SI_FLAG_DEVICE) && !(_data->flags & ATTRIBUTE_SI_FLAG_SHARPNORMAL) && !(_data->flags & ATTRIBUTE_SI_FLAG_TEMPORARY) && !(_data->flags & ATTRIBUTE_SI_FLAG_SPARSE_FILE) && !(_data->flags & ATTRIBUTE_SI_FLAG_REPARSE_POINT) && !(_data->flags & ATTRIBUTE_SI_FLAG_COMPRESSED) && !(_data->flags & ATTRIBUTE_SI_FLAG_OFFLINE) && !(_data->flags & ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED) && !(_data->flags & ATTRIBUTE_SI_FLAG_ENCRYPTED)) { printf("\tunknown\n"); } if (_data->maxNumberOfVersions) { printf("\tMaximum number of versions 0x%x\n", _data->maxNumberOfVersions); } else { printf("\tMaximum number of versions not used\n"); } if (_data->versionNumber) { printf("\tVersion number 0x%x\n", _data->versionNumber); } else { printf("\tVersion number not used\n"); printf("\tClass ID 0x%x\n", _data->classID); printf("\tOwner ID 0x%x\n", _data->ownerID); printf("\tSecurity ID 0x%x\n", _data->securityID); printf("\tQuota charged 0x%x\n", _data->quotaCharged); #if __WORDSIZE == 64 printf("\tUpdate sequence number (USN) 0x%lx\n", _data->updateSequenceNumber); #else printf("\tUpdate sequence number (USN) 0x%llx\n", _data->updateSequenceNumber); #endif } } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/attributes/standardinformation.hpp000066400000000000000000000047211217176075400261040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __STANDARDINFORMATION_HPP__ #define __STANDARDINFORMATION_HPP__ #include "common.hpp" #include "attribute.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif /** * $STANDARD_INFORMATION attribute */ /* SI_FLAG : Strandard_Information_Flag */ #define ATTRIBUTE_SI_FLAG_READ_ONLY 0x1 #define ATTRIBUTE_SI_FLAG_HIDDEN 0x2 #define ATTRIBUTE_SI_FLAG_SYSTEM 0x4 #define ATTRIBUTE_SI_FLAG_ARCHIVE 0x20 #define ATTRIBUTE_SI_FLAG_DEVICE 0x40 #define ATTRIBUTE_SI_FLAG_SHARPNORMAL 0x80 #define ATTRIBUTE_SI_FLAG_TEMPORARY 0x100 #define ATTRIBUTE_SI_FLAG_SPARSE_FILE 0x200 #define ATTRIBUTE_SI_FLAG_REPARSE_POINT 0x400 #define ATTRIBUTE_SI_FLAG_COMPRESSED 0x800 #define ATTRIBUTE_SI_FLAG_OFFLINE 0x1000 #define ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED 0x2000 // Content is not being indexed for faster searches #define ATTRIBUTE_SI_FLAG_ENCRYPTED 0x4000 #define ATTRIBUTE_SI_FLAG_DIRECTORY 0x10000000 #define ATTRIBUTE_SI_FLAG_INDEX_VIEW 0x20000000 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_AttributeStandardInformation { uint64_t creationTime; // Windows display/update those times uint64_t fileAlteredTime; uint64_t mftAlteredTime; uint64_t fileAccessedTime; uint32_t flags; // See defines above uint32_t maxNumberOfVersions; uint32_t versionNumber; uint32_t classID; uint32_t ownerID; // v3.0+ uint32_t securityID; // v3.0+ uint32_t quotaCharged; // v3.0+ uint64_t updateSequenceNumber; // USN v3.0+ } PACK AttributeStandardInformation_t; class AttributeStandardInformation : public Attribute { public: AttributeStandardInformation(Attribute &); ~AttributeStandardInformation(); void content(); AttributeStandardInformation_t *data() { return _data; }; private: AttributeStandardInformation_t *_data; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/bitmapnode.cpp000066400000000000000000000026101217176075400217600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include "bitmapnode.hpp" #include BitmapNode::BitmapNode(std::string Name, uint64_t size, Node *parent, Node *rootFile, Ntfs *fsobj, uint64_t startingCluster, uint16_t clusterSize): Node(Name, size, parent, fsobj) { _startingCluster = startingCluster; _clusterSize = clusterSize; _node = rootFile; setSize(size); } BitmapNode::~BitmapNode() { ; } Attributes BitmapNode::_attributes() { Attributes attr; dff::ScopedMutex locker(dynamic_cast< Ntfs* >(this->fsobj())->_mutex); attr["Starting cluster"] = Variant_p(new Variant(this->_startingCluster)); attr["Free clusters"] = Variant_p(new Variant(this->size() / this->_clusterSize)); return attr; } void BitmapNode::fileMapping(FileMapping *fm) { if (size()) fm->push(0, this->size(), this->_node, this->_startingCluster); } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/bitmapnode.hpp000066400000000000000000000027711217176075400217750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __BITMAPNODE_HPP__ #define __BITMAPNODE_HPP__ #include "ntfs.hpp" #include "node.hpp" #include "vfile.hpp" #include "mftentry.hpp" class BitmapNode : public Node { public: BitmapNode(std::string, uint64_t, Node *, Node *, Ntfs *, uint64_t, uint16_t); ~BitmapNode(); virtual void fileMapping(FileMapping *); Attributes _attributes(void); void contentOffset(uint64_t offset) { _contentOffset = offset; }; void data(AttributeData *data) { _data = data; }; uint32_t getMftEntry() { return _mftEntry; }; void dataOffsets(std::list d) { _dataOffsets = d; }; private: bool _isFile; uint32_t _mftEntry; uint64_t _physOffset; MftEntry *_mft; uint16_t _clusterSize; uint64_t _startingCluster; FileMapping *_fm; Node *_node; AttributeData *_data; uint64_t _contentOffset; std::list _dataOffsets; AttributeFileName *_metaFileName; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/boot.cpp000066400000000000000000000066341217176075400206130ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include "common.hpp" #include "boot.hpp" #include Boot::Boot(VFile *vfile) { _clusterSize = 0; _mftEntrySize = 0; _vfile = vfile; _indexRecordSize = 0; } Boot::~Boot() { if (_bootBlock) delete _bootBlock; } bool Boot::isPow2(int num) { int i = num / 2; while (i > 1) { if (num != i * 2) return false; num /= 2; i = num / 2; } if (i == 1 && i * 2 != num) return false; return true; } BootBlock *Boot::getBootBlock() { return _bootBlock; } void Boot::setBootBlock(BootBlock *bootBlock) { _bootBlock = bootBlock; _clusterSize = _bootBlock->bytePerSector * _bootBlock->sectorPerCluster; if (isPow2(_bootBlock->clusterIndexRecord)) _indexRecordSize = _bootBlock->clusterIndexRecord * _clusterSize; else { DEBUG(INFO, "Invalid index record size in BootSector\n"); ; } } /** * Check * - BOOT_MEDIA_DESCRIPTOR_ID in mediaDescriptorId * - BOOT_FAT_NTFS_SIGNATURE in signature */ bool Boot::isBootBlock(uint64_t offset) { std::ostringstream expectedMediaID; BootBlock *bootBlock = new BootBlock; _vfile->seek(offset); _vfile->read(bootBlock, BOOT_BLOCK_SIZE); expectedMediaID << BOOT_MEDIA_DESCRIPTOR_ID; if ((expectedMediaID.str() == std::string(bootBlock->mediaDescriptorId)) && (bootBlock->signature == BOOT_FAT_NTFS_SIGNATURE)) { setBootBlock(bootBlock); #if __WORDSIZE == 64 DEBUG(VERBOSE, "NTFS Boot block found at offset 0x%lx in vfile %s\n", offset, _vfile->node()->absolute().c_str()); #else DEBUG(VERBOSE, "NTFS Boot block found at offset 0x%llx in vfile %s\n", offset, _vfile->node()->absolute().c_str()); #endif DEBUG(VERBOSE, "Byte per sector: %u\n", bootBlock->bytePerSector); DEBUG(VERBOSE, "Sector per cluster: %u\n", bootBlock->sectorPerCluster); #if __WORDSIZE == 64 DEBUG(VERBOSE, "Number of sector: %lx\n", bootBlock->numberOfSector); DEBUG(VERBOSE, "Start Mft: 0x%lx\n", bootBlock->startMft); DEBUG(VERBOSE, "Start Mft 16b Mirror: 0x%lx\n", bootBlock->startMftMirr); #else DEBUG(VERBOSE, "Number of sector: %llx\n", bootBlock->numberOfSector); DEBUG(VERBOSE, "Start Mft: 0x%llx\n", bootBlock->startMft); DEBUG(VERBOSE, "Start Mft 16b Mirror: 0x%llx\n", bootBlock->startMftMirr); #endif DEBUG(VERBOSE, "Cluster Mft record: %u\n", bootBlock->clusterMftRecord); if (isPow2(bootBlock->clusterMftRecord)) { _mftEntrySize = bootBlock->clusterMftRecord * _clusterSize; DEBUG(VERBOSE,"MFT Entry size: %u\n", _mftEntrySize); } else { DEBUG(VERBOSE, "MFT Entry size not valid in bootblock"); DEBUG(VERBOSE, "Will search for it"); ; } DEBUG(VERBOSE, "Cluster Index record: %u\n", bootBlock->clusterIndexRecord); DEBUG(VERBOSE, "Cluster Size: %u\n", _clusterSize); } else { delete bootBlock;; return false; } return true; } /* TODO searchForBootBlock() { } */ dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/boot.hpp000066400000000000000000000050321217176075400206070ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __BOOT_HPP__ #define __BOOT_HPP__ #include "mfso.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif #define BOOT_BLOCK_SIZE 512 #define BOOT_MEDIA_DESCRIPTOR_ID "NTFS " #define BOOT_FAT_NTFS_SIGNATURE 0xAA55 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_BootBlock { uint8_t jmpLoaderRoutine[3]; char mediaDescriptorId[8]; uint16_t bytePerSector; uint8_t sectorPerCluster; uint8_t unused1[2]; // reservedSectors, Microsoft says it must be 0 uint8_t unused2[5]; // Microsoft says it must be 0 uint8_t mediaDescriptor; uint8_t unused3[2]; // Microsoft says it must be 0 uint8_t unused4[8]; // Microsoft says it is not checked (uint16_t sectorByTrack and uint16_t numberOfHead ?!?) uint8_t unused5[4]; // Microsoft says it must be 0 uint8_t unused6[4]; // Microsoft says it is not checked uint64_t numberOfSector; uint64_t startMft; uint64_t startMftMirr; uint8_t clusterMftRecord; // size of one file record (MFT entry) uint8_t unused7[3]; uint8_t clusterIndexRecord; // size of Index record uint8_t unused8[3]; uint64_t volumeSerialNumber; uint8_t unused9[4]; uint8_t bootCode[426]; uint16_t signature; // BOOT_FAT_NTFS_SIGNATURE } PACK BootBlock; class Boot { public: Boot(VFile *); ~Boot(); bool isBootBlock(uint64_t offset); BootBlock *getBootBlock(); void setBootBlock(BootBlock *); void mftEntrySize(uint16_t size) { _mftEntrySize = size; }; uint16_t mftEntrySize() { return _mftEntrySize; }; bool isPow2(int); uint16_t indexRecordSize() { return _bootBlock->clusterIndexRecord * _clusterSize; }; uint16_t sectorSize() { return _bootBlock->bytePerSector; }; uint16_t clusterSize() { return _clusterSize; }; private: BootBlock *_bootBlock; VFile *_vfile; uint16_t _clusterSize; uint16_t _mftEntrySize; uint16_t _indexRecordSize; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/common.hpp000066400000000000000000000036051217176075400211400ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __COMMON_HPP_ #define __COMMON_HPP_ /** * 0 : nothing * 3 : everything */ #define DEBUG_LEVEL 0 #define VERBOSE 3 #define INFO 2 #define CRITICAL 1 #if (!defined(WIN64) && !defined(WIN32)) #define DEBUG(level, str, args...) do { \ if (DEBUG_LEVEL) \ if (level <= DEBUG_LEVEL) \ printf("%s:%d\t" str, __FILE__, __LINE__, ##args); \ } while (0) #else #define DEBUG(level, str, ...) do { \ if (DEBUG_LEVEL) \ if (level <= DEBUG_LEVEL) \ printf("%s:%d\t" str, __FILE__, __LINE__, __VA_ARGS__); \ } while (0) #endif /** * Avoid sizeof(uint*_t) calls */ #define SIZE_BYTE 1 #define SIZE_2BYTES 2 #define SIZE_3BYTES 3 #define SIZE_4BYTES 4 #define SIZE_5BYTES 5 #define SIZE_6BYTES 6 #define SIZE_7BYTES 7 #define SIZE_8BYTES 8 #define BITS_IN_BYTE 8 #define BITS_IN_2BYTE 16 #define BITS_IN_3BYTE 24 #define BITS_IN_4BYTE 32 #define BITS_IN_5BYTE 40 #define BITS_IN_6BYTE 48 #define BITS_IN_7BYTE 56 #define BITS_IN_8BYTE 64 #endif // #defined __DEBUG_HPP_ dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/mftentry.cpp000066400000000000000000000453721217176075400215220ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "vfile.hpp" #include "mftentry.hpp" MftEntry::MftEntry(VFile *vfile) { _vfile = vfile; _mftEntryBlock = new MftEntryBlock; _bufferOffset = 0; _previousReadOffset = 0; _clusterSize = 0; _mftEntrySize = 0; _attributeOffset = 0; _indexRecordSize = 0; _sectorSize = 0; _currentAttribute = new Attribute(_vfile); _readBuffer = NULL; _fixupValues = NULL; _fixupSignature = 0; _attributeHeader = NULL; } //XXX fix sometime it's deleted but fd of vfile is already used elsewhere so it must not close it, and some time it's not used so it must be closed void MftEntry::close() { _vfile->close(); } MftEntry::~MftEntry() { // _vfile->close(); delete _currentAttribute; if (_fixupValues != NULL) { delete _fixupValues; } } MftEntryBlock *MftEntry::getMftEntryBlock() { return _mftEntryBlock; } void MftEntry::clusterSize(uint16_t size) { _clusterSize = size; DEBUG(INFO, "cs: 0x%x\n", size); _currentAttribute->clusterSize(size); } void MftEntry::mftEntrySize(uint16_t size) { _mftEntrySize = size; _readBuffer = new uint8_t[size]; _currentAttribute->mftEntrySize(size); } void MftEntry::indexRecordSize(uint16_t size) { _indexRecordSize = size; _currentAttribute->indexRecordSize(size); } void MftEntry::sectorSize(uint16_t size) { _sectorSize = size; _currentAttribute->sectorSize(size); } void MftEntry::dumpHeader() { uint8_t i; #if __WORDSIZE == 64 DEBUG(CRITICAL, "MftEntry at offset 0x%lx\n", _previousReadOffset); #else DEBUG(CRITICAL, "MftEntry at offset 0x%llx\n", _previousReadOffset); #endif DEBUG(CRITICAL, "\tfixupArrayOffset 0x%x\n", _mftEntryBlock->fixupArrayOffset); DEBUG(CRITICAL, "\tfixupNumber 0x%x\n", _mftEntryBlock->fixupNumber); DEBUG(CRITICAL, "\tsequenceValue 0x%x\n", _mftEntryBlock->sequenceValue); DEBUG(CRITICAL, "\tlinkCount 0x%x\n", _mftEntryBlock->linkCount); DEBUG(CRITICAL, "\tfirstAttributeOffset 0x%x\n", _mftEntryBlock->firstAttributeOffset); DEBUG(CRITICAL, "\tflag 0x%x\n", _mftEntryBlock->flag); DEBUG(CRITICAL, "\tusedSizeMftEntry 0x%x\n", _mftEntryBlock->usedSizeMftEntry); DEBUG(CRITICAL, "\tallocatedSizeMftEntry 0x%x\n", _mftEntryBlock->allocatedSizeMftEntry); #if __WORDSIZE == 64 DEBUG(CRITICAL, "\tlogFileLSN 0x%lx\n", _mftEntryBlock->logFileLSN); DEBUG(CRITICAL, "\tfileReferenceToBaseRecord %ld\n", _mftEntryBlock->fileReferenceToBaseRecord); #else DEBUG(CRITICAL, "\tlogFileLSN 0x%llx\n", _mftEntryBlock->logFileLSN); DEBUG(CRITICAL, "\tfileReferenceToBaseRecord %lld\n", _mftEntryBlock->fileReferenceToBaseRecord); #endif DEBUG(CRITICAL, "\tnextAttributeId 0x%x\n", _mftEntryBlock->nextAttributeId); DEBUG(CRITICAL, "\tEntry have fixup:\n"); DEBUG(CRITICAL, "\tSignature 0x%.4x\n", _fixupSignature); for (i = 0; i < _mftEntryBlock->fixupNumber - 1; i++) { DEBUG(CRITICAL, "\t\tValue to replace #%u 0x%.4x\n", i, _fixupValues[i]); ; } // _fixFixup(); } /** * Read in _vfile, based on a cluster size * TODO * once sector fixup values are known, we must replace it in _readBuffer */ void MftEntry::_bufferedRead(uint64_t offset) { #if __WORDSIZE == 64 DEBUG(INFO, "requesting read to 0x%lx with size 0x%x\n", offset, _mftEntrySize); #else DEBUG(INFO, "requesting read to 0x%llx with size 0x%x\n", offset, _mftEntrySize); #endif if (offset - _previousReadOffset >= _mftEntrySize || (offset == 0 && _previousReadOffset == 0)) { if (_readBuffer == NULL && _mftEntrySize > 0) { _readBuffer = new uint8_t[_mftEntrySize]; } memset(_readBuffer, 0, _mftEntrySize); _vfile->seek(offset); _vfile->read(_readBuffer, _mftEntrySize); _previousReadOffset = offset; _mftEntryBlock = (MftEntryBlock *)_readBuffer; _bufferOffset = 0; _entryOffset = 0; #if __WORDSIZE == 64 DEBUG(INFO, "NEAD to read @ 0x%lx previous read offset: 0x%lx buffOffset: 0x%x\n", offset, _previousReadOffset, _bufferOffset); #else DEBUG(INFO, "NEAD to read @ 0x%llx previous read offset: 0x%llx buffOffset: 0x%x\n", offset, _previousReadOffset, _bufferOffset); #endif } else { _bufferOffset = offset - _previousReadOffset; _mftEntryBlock = (MftEntryBlock *)(_readBuffer + _bufferOffset); _entryOffset = _bufferOffset; DEBUG(INFO, "NO nead to read bufferOffset is now 0x%x\n", _bufferOffset); DEBUG(INFO, "fiiiixup number 0x%x\n", _mftEntryBlock->fixupNumber); } // _fixFixup(); } void MftEntry::_bufferedRead(uint64_t offset, uint32_t size) { #if __WORDSIZE == 64 DEBUG(INFO, "requesting read to 0x%lx with size 0x%x\n", offset, size); #else DEBUG(INFO, "requesting read to 0x%llx with size 0x%x\n", offset, size); #endif if (_readBuffer != NULL) { delete _readBuffer; } _readBuffer = new uint8_t[size]; if (offset - _previousReadOffset >= size || (offset == 0 && _previousReadOffset == 0)) { memset(_readBuffer, 0, size); _vfile->seek(offset); _vfile->read(_readBuffer, size); _previousReadOffset = offset; _mftEntryBlock = (MftEntryBlock *)_readBuffer; _bufferOffset = 0; _entryOffset = 0; #if __WORDSIZE == 64 DEBUG(INFO, "NEAD to read @ 0x%lx previous read offset: 0x%lx\n", offset, _previousReadOffset); #else DEBUG(INFO, "NEAD to read @ 0x%llx previous read offset: 0x%llx\n", offset, _previousReadOffset); #endif } else { _bufferOffset = offset - _previousReadOffset; _mftEntryBlock = (MftEntryBlock *)(_readBuffer + _bufferOffset); _entryOffset = _bufferOffset; DEBUG(INFO, "NO nead to read bufferOffset is now 0x%x\n", _bufferOffset); DEBUG(INFO, "fiiiixup number 0x%x\n", _mftEntryBlock->fixupNumber); } // _fixFixup(); } bool MftEntry::_validateSignature() { std::ostringstream expectedSignature; uint8_t i; _previousReadOffset = 0; expectedSignature << MFTENTRY_SIGNATURE; if (_mftEntryBlock == NULL) return false; if (_mftEntryBlock->signature == NULL) return false; for (i = 0; i < expectedSignature.str().size(); i++) { /* Char by char because no trailing \0 at end of signature */ if (expectedSignature.str()[i] != _mftEntryBlock->signature[i]) { DEBUG(INFO, "No valid MFTEntry entry found got '%c' expected '%c'\n", _mftEntryBlock->signature[i], expectedSignature.str()[i]); return false; } } return true; } bool MftEntry::isMftEntryBlock(uint64_t offset) { #if __WORDSIZE == 64 DEBUG(INFO, "Seek to 0x%lx\n", offset); #else DEBUG(INFO, "Seek to 0x%llx\n", offset); #endif /* Direct read amount of data needed in _vfile to validate if we are at the * begining of an MFT entry */ _vfile->seek(offset); _vfile->read(_mftEntryBlock, MFTENTRY_HEADER_SIZE); /* Validate MFT Signature */ return _validateSignature(); } /** * Like isMftEntryBlock but read more data to decode content * and set offset */ bool MftEntry::decode(uint64_t offset) { uint8_t i; uint8_t lbreak = 0; #if __WORDSIZE == 64 DEBUG(INFO, "Reading 0x%lx\n", offset); #else DEBUG(INFO, "Reading 0x%llx\n", offset); #endif /* Read from previous buffer or read again in _vfile */ _bufferedRead(offset); /* Validate MFT Signature */ #if __WORDSIZE == 64 DEBUG(INFO, "reading at 0x%lx\n", offset); #else DEBUG(INFO, "reading at 0x%llx\n", offset); #endif if (!_validateSignature()) { DEBUG(INFO, "sign not valid\n"); return false; } /* Set fixup values */ if (_mftEntryBlock->fixupNumber > 0) { i = 0; _fixupValues = new uint16_t[_mftEntryBlock->fixupNumber]; _bufferOffset += _mftEntryBlock->fixupArrayOffset; _fixupSignature = (uint16_t)(*(uint16_t *)(_readBuffer + _bufferOffset)); DEBUG(VERBOSE, "fixup signature: 0x%.4x buffOffset: 0x%x\n", _fixupSignature, _bufferOffset); _bufferOffset += SIZE_2BYTES; while (i < _mftEntryBlock->fixupNumber) { _fixupValues[i] = (uint16_t)(*(uint16_t *)(_readBuffer + _bufferOffset)); DEBUG(VERBOSE, "fixup value found: 0x%.4x buffOffset: 0x%x\n", _fixupValues[i], _bufferOffset); _bufferOffset += SIZE_2BYTES; i++; } } DEBUG(VERBOSE, "mft sign: %s\n", _mftEntryBlock->signature); DEBUG(VERBOSE, "fixup offset: 0x%x\n", _mftEntryBlock->fixupArrayOffset); DEBUG(VERBOSE, "fixup number of fixup: 0x%x\n", _mftEntryBlock->fixupNumber); #if __WORDSIZE == 64 DEBUG(INFO, "lsn: 0x%lx\n", _mftEntryBlock->logFileLSN); #else DEBUG(INFO, "lsn: 0x%llx\n", _mftEntryBlock->logFileLSN); #endif /* _attributeOffset = _mftEntryBlock->fixupArrayOffset + (_mftEntryBlock->fixupNumber + 1) * SIZE_2BYTES; */ _attributeOffset = _mftEntryBlock->firstAttributeOffset; _bufferOffset = _mftEntryBlock->firstAttributeOffset; /* fixup */ i = 0; lbreak = 0; while (_mftEntryBlock->fixupNumber && i < _mftEntryBlock->fixupNumber - 1) { DEBUG(VERBOSE, "jumping to 0x%x\n", _entryOffset + ((i + 1) * _sectorSize) - 2); uint16_t *valToFix = (uint16_t *)(_readBuffer + _entryOffset + ((i + 1) * _sectorSize) - 2); DEBUG(VERBOSE, "fixup Got: 0x%.4x\n", *valToFix); *valToFix = (uint16_t)(_fixupValues[i]); DEBUG(VERBOSE, "fixup Wrote: 0x%.4x\n", *valToFix); i++; if (lbreak++ == 255) break; } return true; } void MftEntry::_fixFixup() { uint16_t *valToFix = (uint16_t *)(_readBuffer + _bufferOffset + _sectorSize - 2); DEBUG(INFO, "=== FIXUP VALIDATION AND CLEANING ===\n"); DEBUG(INFO, "\tSector size is 0x%x\n", _sectorSize); DEBUG(INFO, "\tFixup signature is 0x%.4x\n", _fixupSignature); DEBUG(INFO, "\tValue1 to fix: 0x%.4x\n", *valToFix); *valToFix = _fixupValues[0]; DEBUG(INFO, "\tFixed to 0x%.4x\n", *valToFix); valToFix = (uint16_t *)(_readBuffer + _bufferOffset + (_sectorSize * 2) - 2); DEBUG(INFO, "\tValue2 to fix: 0x%.4x\n", *valToFix); *valToFix = _fixupValues[1]; DEBUG(INFO, "\tFixed to 0x%.4x\n", *valToFix); DEBUG(INFO, "\tFixed to 0x%.4x\n", *((uint16_t *)(_readBuffer + _bufferOffset + _sectorSize - 2))); } Attribute *MftEntry::getNextAttribute() { if ((_attributeOffset + ATTRIBUTE_HEADER_SIZE) >= _mftEntryBlock->usedSizeMftEntry) { if (_readBuffer != NULL) { delete _readBuffer; _readBuffer = NULL; } return NULL; } if (*(uint32_t *)(_readBuffer + _bufferOffset) == ATTRIBUTE_END) { if (_readBuffer != NULL) { delete _readBuffer; _readBuffer = NULL; } return NULL; } _attributeHeader = (AttributeHeader *)(_readBuffer + _bufferOffset); _currentAttribute->setOrigin(_attributeHeader, _readBuffer, _bufferOffset, _attributeOffset); _bufferOffset += _attributeHeader->attributeLength; _attributeOffset += _attributeHeader->attributeLength; if (_mftEntryBlock->fixupNumber > 0) { uint8_t i; _currentAttribute->fixupOffsets(_mftEntryBlock->fixupNumber); for(i = 0; i < _mftEntryBlock->fixupNumber; i++) _currentAttribute->fixupOffset(i, _previousReadOffset + _entryOffset + _mftEntryBlock->fixupArrayOffset + (i + 1) * SIZE_2BYTES); } DEBUG(INFO, "\tattr @ 0x%x, type: 0x%x: %s, non resident: 0x%x, attribute length: 0x%x\n", _attributeOffset - _attributeHeader->attributeLength, _attributeHeader->attributeTypeIdentifier, _currentAttribute->getName(_attributeHeader->attributeTypeIdentifier).c_str(), _attributeHeader->nonResidentFlag, _attributeHeader->attributeLength); return _currentAttribute; } void MftEntry::dumpAttribute(Attribute *attribute) { if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_STANDARD_INFORMATION) { AttributeStandardInformation *metaStandardInformation = new AttributeStandardInformation(*attribute); metaStandardInformation->content(); } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_ATTRIBUTE_LIST) { AttributeAttributeList *metaAttributeList = new AttributeAttributeList(_vfile, *attribute); metaAttributeList->content(); } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_FILE_NAME) { AttributeFileName *metaFileName = new AttributeFileName(*attribute); metaFileName->content(); } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_VOLUME_VERSION_OR_OBJECT_ID) { //_attributeObjectID(); ; } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_SECURITY_DESCRIPTOR) { //_attributeSecurityDescriptor(); ; } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_VOLUME_NAME) { //_attributeVolumeName(); ; } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_VOLUME_INFORMATION) { //_attributeVolumeInformation(); ; } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_DATA) { AttributeData *data = new AttributeData(*attribute); if (attribute->attributeHeader()->nonResidentFlag) { dumpChunks(data->offsetsRuns(), data->getRunListSize()); } else { data->content(); } } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_INDEX_ROOT) { AttributeIndexRoot *metaIndexRoot = new AttributeIndexRoot(*attribute); metaIndexRoot->content(); } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_INDEX_ALLOCATION) { // TODO should not exist without an INDEX_ROOT attribute, check it // also check signature is INDX for carving AttributeIndexAllocation *data = new AttributeIndexAllocation(*attribute); if (attribute->attributeHeader()->nonResidentFlag) { dumpChunks(data->offsetsRuns(), data->getRunListSize()); } else { data->content(); } } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_BITMAP) { AttributeBitmap *data = new AttributeBitmap(*attribute); if (attribute->attributeHeader()->nonResidentFlag) { dumpChunks(data->offsetsRuns(), data->getRunListSize()); } else { data->content(); } } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_SYMBOLINC_LINK_OR_REPARSE_POINT) { AttributeReparsePoint *metaReparsePoint = new AttributeReparsePoint(*attribute); metaReparsePoint->content(); } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_EA_INFORMATION) { //_attributeEAInformation(); ; } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_EA) { //_attributeEA(); ; } else if (_attributeHeader->attributeTypeIdentifier == ATTRIBUTE_LOGGED_UTILITY_STREAM) { //_attributeLoggedUtilityStream(); ; } DEBUG(INFO, "\n"); } uint16_t MftEntry::_runList(uint16_t runDescOffset) { uint8_t *runList = (_readBuffer + runDescOffset); uint8_t runLengthSize; uint8_t runOffsetSize; uint64_t runLength = 0; uint64_t runOffset = 0; // Offset is signed, relative to previous offset uint16_t index; DEBUG(INFO, "\t\tAttribute DATA in 0x%x\n", runDescOffset); runLengthSize = runList[0] & 0xF; runOffsetSize = runList[0] >> 4; DEBUG(INFO, "\t\t\trunLenghtSize: 0x%x\n", runLengthSize); if (runLengthSize == 0) { DEBUG(INFO, "\t\t\tover\n"); return 0; } DEBUG(INFO, "\t\t\trunOffsetSize: 0x%x\n", runOffsetSize); // Read run length byte per byte for (index = 0; index < runLengthSize; index++) runLength += ((uint64_t)*((uint8_t *)(runList + (index + 1) * SIZE_BYTE))) << (index * BITS_IN_BYTE); // Read run offset byte per byte // FIXME offset is signed, because it is relative to previous offset for (index = 0; index < runOffsetSize; index++) { runOffset += ((uint64_t)*((uint8_t *)(runList + runLengthSize + (index + 1) * SIZE_BYTE))) << (index * BITS_IN_BYTE); } #if __WORDSIZE == 64 DEBUG(INFO, "\t\t\trunLength: 0x%.16lx\n", runLength); DEBUG(INFO, "\t\t\trunOffset: 0x%.16lx (from %lu to %lu)\n", runOffset + _previousRunOffset, runOffset + _previousRunOffset, runOffset + _previousRunOffset + runLength - 1); #else DEBUG(INFO, "\t\t\trunLength: 0x%.16llx\n", runLength); DEBUG(INFO, "\t\t\trunOffset: 0x%.16llx (from %llu to %llu)\n", runOffset + _previousRunOffset, runOffset + _previousRunOffset, runOffset + _previousRunOffset + runLength - 1); #endif _previousRunOffset = runOffset + _previousRunOffset; return runDescOffset + SIZE_BYTE + runLengthSize + runOffsetSize; } uint16_t MftEntry::discoverMftEntrySize(uint64_t offset) { uint16_t mftEntrySize = 512; // Start at the minimum, size of a sector.. uint8_t i = 0; _bufferedRead(offset, 8192); while (mftEntrySize && i != 4 && (mftEntrySize <( 8192 - 4))) { if ((uint32_t)*(_readBuffer + mftEntrySize) != (uint32_t)*MFTENTRY_SIGNATURE) mftEntrySize *= 2; else { DEBUG(INFO, "MftEntrySize of %u bytes found valid\n", mftEntrySize); DEBUG(INFO, "return %u\n", mftEntrySize); _readBuffer = new uint8_t[mftEntrySize]; return mftEntrySize; } } return 0; } void MftEntry::dumpChunks(OffsetRun *offsets, uint16_t runListSize) { uint16_t runListIndex = 0; uint32_t prevLength = 0; int64_t prevOffset = 0; OffsetRun *offset; printf("\t\t\tChunks amount: %u\n", runListSize); while (runListIndex < runListSize) { offset = &(offsets[runListIndex]); printf("\t\t\t\tChunk #%u\tlength %u (0x%x)\n", runListIndex + 1, offset->runLength - prevLength, offset->runLength - prevLength); #if __WORDSIZE == 64 if (offset->runLength - prevLength > 1) { printf("\t\t\t\t\t\tcluster %lu (0x%lx) to %lu (0x%lx)\n", offset->runOffset, offset->runOffset, offset->runOffset + (offset->runLength - prevLength) - 1, offset->runOffset + (offset->runLength - prevLength) - 1); } else { printf("\t\t\t\t\t\tcluster %lu (0x%lx)\n", offset->runOffset, offset->runOffset); } if (prevOffset) { printf("\t\t\t\t\t\trelative from previous %li (0x%lx)\n", offset->runOffset - prevOffset, offset->runOffset - prevOffset); } #else if (offset->runLength - prevLength > 1) { printf("\t\t\t\t\t\tcluster %llu (0x%llx) to %llu (0x%llx)\n", offset->runOffset, offset->runOffset, offset->runOffset + (offset->runLength - prevLength) - 1, offset->runOffset + (offset->runLength - prevLength) - 1); } else { printf("\t\t\t\t\t\tcluster %llu (0x%llx)\n", offset->runOffset, offset->runOffset); } if (prevOffset) { printf("\t\t\t\t\t\trelative from previous %lli (0x%llx)\n", prevOffset - offset->runOffset, prevOffset - offset->runOffset); } #endif prevLength = offset->runLength; prevOffset = offset->runOffset; runListIndex++; } } void MftEntry::continueAt(uint16_t bufferOffset, uint16_t attributeOffset) { _bufferOffset = bufferOffset; _attributeOffset = attributeOffset; } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/mftentry.hpp000066400000000000000000000067301217176075400215220ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __MFTENTRY_HPP__ #define __MFTENTRY_HPP__ #include "vfs.hpp" #include "common.hpp" #include "attribute.hpp" #include "attributes/bitmap.hpp" #include "attributes/data.hpp" #include "attributes/filename.hpp" #include "attributes/indexroot.hpp" #include "attributes/standardinformation.hpp" #include "attributes/reparsepoint.hpp" #include "attributes/attributelist.hpp" #include "attributes/indexallocation.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #ifdef WIN32 #define PACK #else #define PACK __attribute__((packed)) #endif #define MFTENTRY_HEADER_SIZE 42 #define MFTENTRY_SIGNATURE "FILE" #define MFTENTRY_ROOT 0x5 #ifdef WIN32 #pragma pack(1) #endif typedef struct s_MftEntryBlock { char signature[4]; uint16_t fixupArrayOffset; uint16_t fixupNumber; // TODO rename fixupAmount uint64_t logFileLSN; // Long File Sequence number uint16_t sequenceValue; uint16_t linkCount; uint16_t firstAttributeOffset; uint16_t flag; // in use directory uint32_t usedSizeMftEntry; uint32_t allocatedSizeMftEntry; uint64_t fileReferenceToBaseRecord; uint16_t nextAttributeId; uint16_t unused; uint16_t fileRef; //uint8_t attributesAndFixupValues[982]; } PACK MftEntryBlock; class MftEntry { public: MftEntry(VFile *); ~MftEntry(); bool isMftEntryBlock(uint64_t); MftEntryBlock *getMftEntryBlock(); void dumpHeader(); bool decode(uint64_t); uint16_t setNextRun(uint16_t, uint32_t *, uint64_t *); Attribute *getNextAttribute(); void dumpAttribute(Attribute *); uint16_t discoverMftEntrySize(uint64_t); uint16_t clusterSize() { return _clusterSize; }; uint16_t mftEntrySize() { return _mftEntrySize; }; uint16_t indexRecordSize() { return _indexRecordSize; }; // For BTrees uint16_t sectorSize() { return _sectorSize; }; // For Fixup void clusterSize(uint16_t); void mftEntrySize(uint16_t); void indexRecordSize(uint16_t); // For BTrees void sectorSize(uint16_t); // For Fixup void _fixFixup(); void dumpChunks(OffsetRun *, uint16_t); void continueAt(uint16_t, uint16_t); uint16_t bufferOffset() { return _bufferOffset; }; uint16_t attributeOffset() { return _attributeOffset; }; void close(); private: VFile *_vfile; MftEntryBlock *_mftEntryBlock; Attribute *_currentAttribute; AttributeHeader *_attributeHeader; uint16_t _clusterSize; uint16_t _mftEntrySize; uint16_t _indexRecordSize; uint16_t _sectorSize; uint8_t *_readBuffer; uint16_t _bufferOffset; uint64_t _previousReadOffset; uint16_t _attributeOffset; uint16_t _fixupSignature; uint16_t *_fixupValues; uint64_t _previousRunOffset; uint16_t _entryOffset; uint16_t _runList(uint16_t); bool _validateSignature(); void _bufferedRead(uint64_t); void _bufferedRead(uint64_t, uint32_t); // void _setDateToString(uint64_t, struct tm **, std::string *); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/mftfile.cpp000066400000000000000000000137071217176075400212750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include #include "mftfile.hpp" MftFile::MftFile(VFile *vfile, uint16_t mftEntrySize, uint16_t indexRecordSize, uint16_t sectorSize, uint16_t clusterSize) { _vfile = vfile; // _offsetListSize = offsetListSize; _currentOffset = 0; // _offsetList = new OffsetRun[_offsetListSize]; _numberOfRecords = 0; _mftEntrySize = mftEntrySize; _indexRecordSize = indexRecordSize; _sectorSize = sectorSize; _clusterSize = clusterSize; _allocatedSize = 0; } MftFile::~MftFile() { if (_data) delete _data; if (_bitmap) delete _bitmap; } uint16_t MftFile::getOffsetListSize() { return _data->getOffsetListSize(); } uint32_t MftFile::getNumberOfRecords() { return _numberOfRecords; } MftEntry *MftFile::get(uint64_t parentReference) { uint32_t fileReference; uint16_t sequenceNumber; uint32_t mftEntry; uint64_t offset; MftEntry *parent; fileReference = parentReference >> 32; #if __WORDSIZE == 64 DEBUG(INFO, "got reference: 0x%.16lx\n", parentReference); sequenceNumber = parentReference & 0xff000000UL; mftEntry = parentReference & 0xffffffUL; DEBUG(INFO, "searching for 0x%lx, got 0x%x\n", parentReference, mftEntry); #else DEBUG(INFO, "got reference: 0x%.16llx\n", parentReference); sequenceNumber = parentReference & 0xff000000ULL; mftEntry = parentReference & 0xffffffULL; DEBUG(INFO, "searching for 0x%llx, got 0x%x\n", parentReference, mftEntry); #endif if (mftEntry == MFTENTRY_ROOT) return NULL; DEBUG(INFO, "fileReference: 0x%x\n", fileReference); DEBUG(INFO, "sequenceNumber: 0x%x\n", sequenceNumber); DEBUG(INFO, "searching for mftEntry: 0x%x\n", mftEntry); if (!(offset = _data->offsetFromID(mftEntry))) return NULL; #if __WORDSIZE == 64 DEBUG(INFO, "parent is @ 0x%lx\n", offset); #else DEBUG(INFO, "parent is @ 0x%llx\n", offset); #endif parent = new MftEntry(_vfile); //XXX must find a real fix parent->indexRecordSize(_indexRecordSize); parent->sectorSize(_sectorSize); parent->clusterSize(_clusterSize); parent->mftEntrySize(_mftEntrySize); DEBUG(INFO, "parent on da way\n"); if (parent->decode(offset) == false) { delete parent; return NULL; } if (parent->getMftEntryBlock()->fixupArrayOffset > _mftEntrySize) { delete parent; return NULL; } DEBUG(INFO, "parent set !\n"); return parent; } void MftFile::dumpDiscoveredEntries() { std::map::iterator it; DEBUG(CRITICAL, "map size: %u items\n", (uint32_t)_discoveredEntries.size()); it = _discoveredEntries.begin(); while (it != _discoveredEntries.end()) { if (it->first && !(it->first % 20)) { DEBUG(CRITICAL, "\n"); } else if (it->first && !(it->first % 10)) { DEBUG(CRITICAL, " "); } else if (it->first && !(it->first % 5)) { DEBUG(CRITICAL, " "); } if (it->second) { DEBUG(CRITICAL, "X"); } else { DEBUG(CRITICAL, "."); } it++; } DEBUG(CRITICAL, "\n"); } uint32_t MftFile::discoverPercent() { return ((_discoveredEntries.size() * 100) / _numberOfRecords); } void MftFile::entryDiscovered(uint32_t i) { _discoveredEntries.insert(std::pair(i, true)); } bool MftFile::isEntryDiscovered(uint32_t i) { return (_discoveredEntries.find(i) != _discoveredEntries.end()); } void MftFile::data(Attribute *dataAttribute) { DEBUG(INFO, "setting data to mftmainfile\n"); _data = new AttributeData(*dataAttribute); _data->mftEntrySize(_mftEntrySize); _data->indexRecordSize(_indexRecordSize); _data->sectorSize(_sectorSize); _data->clusterSize(_clusterSize); _data->setRunList(); // _numberOfRecords = _data->getRunAmount(); _numberOfRecords = _data->getSize() / _mftEntrySize; #if __WORDSIZE == 64 DEBUG(CRITICAL, "number of mft records: %u datasize: %lu bytes mftentrysize %u\n", _numberOfRecords, _data->getSize(), _mftEntrySize); #else DEBUG(CRITICAL, "number of mft records: %u datasize: %llu bytes mftentrysize %u\n", _numberOfRecords, _data->getSize(), _mftEntrySize); #endif } void MftFile::bitmap(Attribute *bitmapAttribute) { _bitmap = new AttributeBitmap(*bitmapAttribute); _bitmap->setContent(); } void MftFile::standardInformation(Attribute *attribute) { _standardInformation = new AttributeStandardInformation(*attribute); if (attribute->attributeHeader()->nonResidentFlag) _standardInformation->setRunList(); } void MftFile::fileName(Attribute *attribute) { _fileName = new AttributeFileName(*attribute); if (attribute->attributeHeader()->nonResidentFlag) _fileName->setRunList(); } void MftFile::securityDescriptor(Attribute *attribute) { _securityDescriptor = new AttributeSecurityDescriptor(*attribute); if (attribute->attributeHeader()->nonResidentFlag) { _securityDescriptor->setRunList(); } } void MftFile::indexRoot(Attribute *attribute) { _indexRoot = new AttributeIndexRoot(*attribute); } void MftFile::indexAllocation(Attribute *attribute) { _indexAllocation = new AttributeIndexAllocation(*attribute); _indexAllocation->mftEntrySize(_mftEntrySize); _indexAllocation->indexRecordSize(_indexRecordSize); _indexAllocation->sectorSize(_sectorSize); _indexAllocation->clusterSize(_clusterSize); DEBUG(INFO, "sizes: 0x%x 0x%x 0x%x 0x%x\n", _indexAllocation->mftEntrySize(), _indexAllocation->indexRecordSize(), _indexAllocation->sectorSize(), _indexAllocation->clusterSize()); if (attribute->attributeHeader()->nonResidentFlag) _indexAllocation->setRunList(); } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/mftfile.hpp000066400000000000000000000052321217176075400212740ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __MFTFILE_HPP__ #define __MFTFILE_HPP__ #include "vfs.hpp" #include "common.hpp" #include "attribute.hpp" #ifndef WIN32 #include #elif _MSC_VER >= 1600 #include #else #include "wstdint.h" #endif #include "attributes/standardinformation.hpp" #include "attributes/filename.hpp" #include "attributes/securitydescriptor.hpp" #include "attributes/indexroot.hpp" #include "attributes/indexallocation.hpp" #include "attributes/data.hpp" #include "attributes/bitmap.hpp" #include "mftentry.hpp" class MftFile { public: MftFile(VFile *, uint16_t, uint16_t, uint16_t, uint16_t); ~MftFile(); uint16_t getOffsetListSize(); uint32_t getNumberOfRecords(); uint64_t getAllocatedSize(); // Attributes setters void data(Attribute *); void bitmap(Attribute *); void standardInformation(Attribute *); void fileName(Attribute *); AttributeFileName *fileName() { return _fileName; }; void securityDescriptor(Attribute *); void indexRoot(Attribute *); void indexAllocation(Attribute *); // Attributes getters AttributeData *data() { return _data; }; AttributeBitmap *bitmap() { return _bitmap; }; AttributeIndexRoot *indexRoot() { return _indexRoot; }; AttributeIndexAllocation *indexAllocation() { return _indexAllocation; }; void entryDiscovered(uint32_t); bool isEntryDiscovered(uint32_t); void dumpDiscoveredEntries(); uint32_t discoverPercent(); std::map getEntryMap() { return _discoveredEntries; }; MftEntry *get(uint64_t); private: VFile *_vfile; uint64_t _currentOffset; uint16_t _offsetListSize; uint32_t _numberOfRecords; AttributeStandardInformation *_standardInformation; AttributeFileName *_fileName; AttributeSecurityDescriptor *_securityDescriptor; AttributeIndexRoot *_indexRoot; AttributeIndexAllocation *_indexAllocation; AttributeData *_data; AttributeBitmap *_bitmap; uint16_t _mftEntrySize; uint16_t _indexRecordSize; uint16_t _sectorSize; uint16_t _clusterSize; uint64_t _allocatedSize; std::map _discoveredEntries; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/ntfs.cpp000066400000000000000000001432321217176075400206160ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * * TODO: * - Deleted items : creation when MFT entry number differ but file-name * and path are equal. * - Directory indexes : deep search of deleted files event without content. * */ #include "ntfs.hpp" #include "attributes/filename.hpp" #include "attributes/attributelist.hpp" #include "bitmapnode.hpp" Ntfs::Ntfs() : mfso("ntfs") { _rootOffset = 0; _orphan = NULL; _root = NULL; _mftDecode = -1; _indexDecode = -1; _unallocRootNode = NULL; try { DEBUG(INFO, "Constructor OK\n"); } catch (std::exception & e) { std::cerr << "Ntfs::Ntfs() failed : could not build instance." << e.what() << std::endl; if (_boot) delete _boot; } } Ntfs::~Ntfs() { if (_mftMainFile) delete _mftMainFile; } void Ntfs::_setMftMainFile(uint64_t mftEntryOffset) { uint16_t attributeNumber; Attribute *attribute; #if __WORDSIZE == 64 DEBUG(INFO, "entry offset is 0x%lx\n", mftEntryOffset); #else DEBUG(INFO, "entry offset is 0x%llx\n", mftEntryOffset); #endif if (_mftEntry->decode(mftEntryOffset)) { // _mftEntry->dumpHeader(); attributeNumber = 0; while ((attribute = _mftEntry->getNextAttribute())) { attributeNumber++; DEBUG(INFO, "resident is 0x%x\n", attribute->attributeHeader()->nonResidentFlag); attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_DATA) { _mftMainFile->data(attribute); } else if (attribute->getType() == ATTRIBUTE_BITMAP) { _mftMainFile->bitmap(attribute); } else if (attribute->getType() == ATTRIBUTE_FILE_NAME) { _mftMainFile->fileName(attribute); } // _mftEntry->dumpAttribute(attribute); } DEBUG(INFO, "Data has %u runs\n", _mftMainFile->data()->getRunListSize()); DEBUG(INFO, "Bitmap has %u runs\n", _mftMainFile->bitmap()->getRunListSize()); } } /** * Create a deleted node with its parent, not for an orphan node. */ void Ntfs::_createDeletedWithParent(std::string fileNameS, std::list pathRefs, uint32_t mftEntry, AttributeFileName *fileName, AttributeData *data, bool file, AttributeStandardInformation *SI, uint64_t offset) { NtfsNode *current = _root; std::list::const_iterator iter(pathRefs.begin()); std::list::const_iterator listend(pathRefs.end()); std::string dirName; Attribute *attribute; AttributeFileName *metaFileName = NULL; AttributeStandardInformation *metaSI = NULL; NtfsNode *checkNode = NULL; uint32_t parentId; NtfsNode *newFile; MftEntry *parent; /** * Iter every parents */ while (iter != listend) { if (!(parent = _mftMainFile->get(*iter))) { break; } // parent->dumpHeader(); while ((attribute = parent->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_FILE_NAME) { /** * Read parent directory name */ if (metaFileName != NULL) { delete metaFileName; } metaFileName = new AttributeFileName(*attribute); if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace == ATTRIBUTE_FN_NAMESPACE_POSIX) { dirName = metaFileName->getFileName(); DEBUG(INFO, "filename PARENT %s flags 0x%x\n", metaFileName->getFileName().c_str(), metaFileName->data()->flags); } } if (attribute->getType() == ATTRIBUTE_STANDARD_INFORMATION) { metaSI = new AttributeStandardInformation(*attribute); } } /** * Check if parent exists in current directory, create it if needed */ if ((checkNode = _ntfsNodeExists(dirName, current)) == NULL) { #if __WORDSIZE == 64 parentId = (*iter) & 0xffffffUL; #else parentId = (*iter) & 0xffffffULL; #endif _mftMainFile->entryDiscovered(parentId); current = new NtfsNode(dirName.c_str(), 0, current, this, false, metaFileName, metaSI, parent, parentId, _mftMainFile->data()->offsetFromID(parentId)); //XXX _mftMainFile->entryDiscovered(id); DEBUG(INFO, "creating %s as deleted\n", dirName.c_str()); current->setDeleted(); } else { current = checkNode; } ++iter; } DEBUG(INFO, "%s in %s\n", fileName->getFileName().c_str(), current->name().c_str()); if (_ntfsNodeExists(fileNameS, current) == NULL || !_mftMainFile->isEntryDiscovered(mftEntry)) { newFile = new NtfsNode(fileNameS, data->getSize(), current, this, file, fileName, SI, _mftEntry, mftEntry, offset); DEBUG(INFO, "Created (usual) node : %s in %s\n", fileName->getFileName().c_str(), "tmp"); newFile->node(_node); if (file) { newFile->data(data); } DEBUG(INFO, "creating %s as deleted in current2\n", fileName->getFileName().c_str()); newFile->setDeleted(); } } void Ntfs::_createOrphanOrDeleted(std::string fileNameS, AttributeFileName *fileName, bool file, AttributeData *data, uint32_t mftEntry, AttributeStandardInformation *SI, uint64_t offset) { uint64_t parentRef = fileName->data()->parentDirectoryFileReference; //uint64_t prevParentRef = 0; MftEntry *parent = NULL; Attribute *attribute; bool orphan = false; std::list pathRefs; NtfsNode *newFile; AttributeFileName *metaFileName = NULL; std::set previousParent; /** * Create a list of parents */ while ((parent = _mftMainFile->get(parentRef))) { // parent->dumpHeader(); // if (prevParentRef == parentRef) if (previousParent.find(parentRef) != previousParent.end()) { //XXX if (parent) { delete parent; parent = NULL; } break; } else { // prevParentRef = parentRef; previousParent.insert(parentRef); } while ((attribute = parent->getNextAttribute())) { attribute->readHeader(); DEBUG(INFO, "type 0x%x\n", attribute->getType()); if (attribute->getType() == ATTRIBUTE_FILE_NAME) { metaFileName = new AttributeFileName(*attribute); DEBUG(INFO, "filename PARENT: %s\n", metaFileName->getFileName().c_str()); DEBUG(INFO, "flags FN PARENT 0x%x\n", metaFileName->data()->flags); if (parentRef != NTFS_ROOT_DIR_PARENTREF) { #if __WORDSIZE == 64 DEBUG(INFO, "PUSHING 0x%lx\n", parentRef); #else DEBUG(INFO, "PUSHING 0x%llx\n", parentRef); #endif pathRefs.push_front(parentRef); } parentRef = metaFileName->data()->parentDirectoryFileReference; if (!(metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_DIRECTORY)) { DEBUG(INFO, "\tIS NOT A DIRECTORY -> Orphan\n"); orphan = true; } if (metaFileName != NULL) { delete metaFileName; metaFileName = NULL; } break; } } if (parent) { delete parent; parent = NULL; } } DEBUG(INFO, "over\n"); /** * Create node if it is orphan */ if (orphan) { if (!_orphan) { _orphan = new NtfsNode("$Orphans", 0, _root, this, false, NULL, SI, _mftEntry); _orphan->setDeleted(); } if (_ntfsNodeExists(fileNameS, _orphan) == NULL || !_mftMainFile->isEntryDiscovered(mftEntry)) { newFile = new NtfsNode(fileNameS, data->getSize(), _orphan, this, true, fileName, SI, _mftEntry, mftEntry, offset); newFile->node(_node); newFile->data(data); DEBUG(INFO, "creating %s as deleted in orphans\n", fileName->getFileName().c_str()); newFile->setDeleted(); } } else { _createDeletedWithParent(fileNameS, pathRefs, mftEntry, fileName, data, file, SI, offset); } DEBUG(INFO, "Out from _createOrphanOrDeleted\n"); } NtfsNode *Ntfs::_ntfsNodeExists(std::string nodeName, NtfsNode *parent) { uint32_t childCount = parent->childCount(); uint32_t i = 0; std::vector children = parent->children(); NtfsNode *out = NULL; if (!nodeName.size()) { return NULL; } DEBUG(INFO, "childCount: %u\n", childCount); DEBUG(INFO, "parent is %s\n", parent->name().c_str()); while (i != childCount && out == NULL) { DEBUG(VERBOSE, "checking for %s\n", children[i]->name().c_str()); if (children[i]->name() == nodeName) { out = (NtfsNode *)children[i]; } ++i; } return out; } /** * Search for files index/btree in entry */ uint32_t Ntfs::_searchIndexesInEntry(uint64_t mftEntryDirOffset, AttributeIndexRoot **indexRoot, AttributeIndexAllocation **indexAllocation) { Attribute *attribute; AttributeAttributeList *attributeList; uint32_t indexRecordSize = 0; while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); #if __WORDSIZE == 64 DEBUG(INFO, "0x%lx\t\tattr @ 0x%x, type: 0x%x: %s, non resident: 0x%x, attribute length: 0x%x\n", mftEntryDirOffset, attribute->attributeOffset() - attribute->attributeHeader()->attributeLength, attribute->attributeHeader()->attributeTypeIdentifier, attribute->getName(attribute->attributeHeader()->attributeTypeIdentifier).c_str(), attribute->attributeHeader()->nonResidentFlag, attribute->attributeHeader()->attributeLength); #else DEBUG(INFO, "0x%llx\t\tattr @ 0x%x, type: 0x%x: %s, non resident: 0x%x, attribute length: 0x%x\n", mftEntryDirOffset, attribute->attributeOffset() - attribute->attributeHeader()->attributeLength, attribute->attributeHeader()->attributeTypeIdentifier, attribute->getName(attribute->attributeHeader()->attributeTypeIdentifier).c_str(), attribute->attributeHeader()->nonResidentFlag, attribute->attributeHeader()->attributeLength); #endif if (attribute->getType() == ATTRIBUTE_INDEX_ROOT) { (*indexRoot) = new AttributeIndexRoot(*attribute); DEBUG(INFO, "Index root stores attribute type 0x%x: %s\n", (*indexRoot)->data()->attributeInIndexType, attribute->getName((*indexRoot)->data()->attributeInIndexType).c_str()); indexRecordSize = (*indexRoot)->indexRecordSizeBytes(); (*indexRoot)->hasNext(); } if (attribute->getType() == ATTRIBUTE_INDEX_ALLOCATION) { (*indexAllocation) = new AttributeIndexAllocation(*attribute); #if __WORDSIZE == 64 DEBUG(INFO, "0x%lx\tIndex allocation has %u runs\n", mftEntryDirOffset, (*indexAllocation)->getRunListSize()); #else DEBUG(INFO, "0x%llx\tIndex allocation has %u runs\n", mftEntryDirOffset, (*indexAllocation)->getRunListSize()); #endif //XXX case of multiple index_allocation ? break; } if (((*indexAllocation) == NULL || (*indexRoot) == NULL) && attribute->getType() == ATTRIBUTE_ATTRIBUTE_LIST) { uint32_t externalIndexRoot; uint32_t externalIndexAlloc; Attribute *searchIndex; uint16_t savedBufferOffset; uint16_t savedAttributeOffset; #if __WORDSIZE == 64 DEBUG(CRITICAL, "Parsing for 0x%lx\n", mftEntryDirOffset); #else DEBUG(CRITICAL, "Parsing for 0x%llx\n", mftEntryDirOffset); #endif attributeList = new AttributeAttributeList(_vfile, *attribute); attributeList->setMftEntry(_mftMainFile->data()->idFromOffset(mftEntryDirOffset)); externalIndexRoot = attributeList->getExternalAttributeIndexRoot(); externalIndexAlloc = attributeList->getExternalAttributeIndexAlloc(); #if __WORDSIZE == 64 DEBUG(CRITICAL, "index root is external and is mftentry %u (0x%x) offset 0x%lx\n", externalIndexRoot, externalIndexRoot, _mftMainFile->data()->offsetFromID(externalIndexRoot)); DEBUG(CRITICAL, "index allocation is external and is mftentry %u (0x%x) offset 0x%lx\n", externalIndexAlloc, externalIndexAlloc, _mftMainFile->data()->offsetFromID(externalIndexAlloc)); #else DEBUG(CRITICAL, "index root is external and is mftentry %u (0x%x) offset 0x%llx\n", externalIndexRoot, externalIndexRoot, _mftMainFile->data()->offsetFromID(externalIndexRoot)); DEBUG(CRITICAL, "index allocation is external and is mftentry %u (0x%x) offset 0x%llx\n", externalIndexAlloc, externalIndexAlloc, _mftMainFile->data()->offsetFromID(externalIndexAlloc)); #endif if (externalIndexRoot) { savedBufferOffset = _mftEntry->bufferOffset(); savedAttributeOffset = _mftEntry->attributeOffset(); if (_mftEntry->decode(_mftMainFile->data()->offsetFromID(externalIndexRoot))) { while ((searchIndex = _mftEntry->getNextAttribute())) { searchIndex->readHeader(); if (searchIndex->getType() == ATTRIBUTE_INDEX_ROOT) { (*indexRoot) = new AttributeIndexRoot(*searchIndex); } } } // Resync _mftEntry to the one used in _parseDirTree _mftEntry->decode(mftEntryDirOffset); _mftEntry->continueAt(savedBufferOffset, savedAttributeOffset); } if (externalIndexAlloc) { savedBufferOffset = _mftEntry->bufferOffset(); savedAttributeOffset = _mftEntry->attributeOffset(); if (_mftEntry->decode(_mftMainFile->data()->offsetFromID(externalIndexAlloc))) { while ((searchIndex = _mftEntry->getNextAttribute())) { searchIndex->readHeader(); if (searchIndex->getType() == ATTRIBUTE_INDEX_ALLOCATION) { (*indexAllocation) = new AttributeIndexAllocation(*searchIndex); } } } // Resync _mftEntry to the one used in _parseDirTree _mftEntry->decode(mftEntryDirOffset); _mftEntry->continueAt(savedBufferOffset, savedAttributeOffset); } } DEBUG(INFO, "trying to read next attribute\n"); } return indexRecordSize; } void Ntfs::_initTreeWalk(AttributeIndexRoot *indexRoot, AttributeIndexAllocation *indexAllocation, uint32_t indexRecordSize, uint32_t *entryOffset, uint32_t *relOffsetEndUsed) { if (indexAllocation) { indexAllocation->fillRecords(_boot->getBootBlock()->bytePerSector, _boot->clusterSize(), indexRecordSize); #if __WORDSIZE == 64 DEBUG(INFO, "Reading 0x%x bytes IndexAllocation @ 0x%lx\n", indexAllocation->indexRecordSize(), indexAllocation->realOffset()); #else DEBUG(INFO, "Reading 0x%x bytes IndexAllocation @ 0x%llx\n", indexAllocation->indexRecordSize(), indexAllocation->realOffset()); #endif if (indexRoot->currentEntryLength()) { (*entryOffset) = indexRoot->currentEntryOffset(); (*relOffsetEndUsed) = indexRoot->nodeHeader()->relOffsetEndUsed; } else { (*entryOffset) = indexAllocation->getEntryOffset(); if (indexAllocation->getNodeHeader()) { (*relOffsetEndUsed) = indexAllocation->getNodeHeader()->relOffsetEndUsed; } else { (*relOffsetEndUsed) = (*entryOffset); } } if ((*entryOffset) == 0) { DEBUG(INFO, "0\n"); return ; } DEBUG(INFO, "with indexAlloc entryOffset 0x%x offsetEnd 0x%x\n", (*entryOffset), (*relOffsetEndUsed)); } else { (*entryOffset) = indexRoot->currentEntryOffset(); (*relOffsetEndUsed) = indexRoot->nodeHeader()->relOffsetEndUsed; DEBUG(INFO, "with only indexRoot entryOffset 0x%x offsetEnd 0x%x\n", (*entryOffset), (*relOffsetEndUsed)); } } void Ntfs::_updateTreeWalk(AttributeIndexRoot *indexRoot, AttributeIndexAllocation *indexAllocation, uint32_t *entryOffset, uint32_t *relOffsetEndUsed, bool *indexRootOver) { if (indexAllocation) { if (indexRoot->hasNext() && indexRoot->currentEntryLength()) { (*entryOffset) = indexRoot->currentEntryOffset(); } else { (*indexRootOver) = true; (*entryOffset) = indexAllocation->getEntryOffset(); if (indexAllocation->getNodeHeader()) { (*relOffsetEndUsed) = indexAllocation->getNodeHeader()->relOffsetEndUsed; } else { (*relOffsetEndUsed) = (*entryOffset); } if ((*entryOffset) >= (*relOffsetEndUsed)) { ; #if __WORDSIZE == 64 DEBUG(INFO, "end of indexalloc\n"); #else DEBUG(INFO, "end of indexalloc\n"); #endif } } DEBUG(INFO, "current 0x%x end 0x%x\n", (*entryOffset), (*relOffsetEndUsed)); } else { if (indexRoot->hasNext()) { (*entryOffset) = indexRoot->currentEntryOffset(); } else { (*entryOffset) = (*relOffsetEndUsed); } } } NtfsNode *Ntfs::_createRegularADSNodes(uint64_t offset, uint32_t adsAmount, uint32_t mftID, AttributeStandardInformation *metaSI, Node *currentDir, AttributeFileName *metaFName) { AttributeData **data = new AttributeData *[adsAmount]; uint32_t iADS = 0; Attribute *attribute; AttributeAttributeList *attributeList = NULL; uint32_t extAttrData; NtfsNode *returnNode = NULL; _mftEntry->decode(offset); while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_DATA) { data[iADS] = new AttributeData(*attribute); if (!data[iADS]->attributeHeader()->nonResidentFlag) { data[iADS]->offset(data[iADS]->getOffset() + offset + data[iADS]->attributeOffset()); } iADS++; } if (attribute->getType() == ATTRIBUTE_ATTRIBUTE_LIST) { attributeList = new AttributeAttributeList(_vfile, *attribute); attributeList->setMftEntry(mftID); } } if (attributeList) { extAttrData = attributeList->getExternalAttributeData(); if (extAttrData && _mftEntry->decode(_mftMainFile->data()->offsetFromID(extAttrData))) { while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_DATA) { data[iADS] = new AttributeData(*attribute); if (!data[iADS]->attributeHeader()->nonResidentFlag) { data[iADS]->offset(data[iADS]->getOffset() + offset + data[iADS]->attributeOffset()); } iADS++; } } } } for (iADS = 0; iADS < adsAmount; iADS++) { std::ostringstream name; name << metaFName->getFileName() << data[iADS]->getExtName(); returnNode = new NtfsNode(name.str(), data[iADS]->getSize(), currentDir, this, true, metaFName, metaSI, _mftEntry, mftID, offset); returnNode->node(_node); returnNode->data(data[iADS]); } return returnNode; } void Ntfs::_createRegularNode(Node *currentDir, uint32_t dirMftEntry, uint64_t offset, uint32_t curMftEntry) { Attribute *attribute; AttributeAttributeList *attributeList = NULL; AttributeFileName *fullFileName = NULL; AttributeFileName *metaFileName = NULL; AttributeStandardInformation *metaSI = NULL; AttributeData *data = new AttributeData(); uint8_t fileType = 0; uint64_t size = 0; uint32_t extAttrData; NtfsNode *newNode = NULL; uint32_t ads = 0; std::list dataOffsets; while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); #if __WORDSIZE == 64 DEBUG(INFO, "\tattr @ 0x%x, type: 0x%x: %s, non resident: 0x%x, attribute length: 0x%x\n", attribute->attributeOffset(), attribute->attributeHeader()->attributeTypeIdentifier, attribute->getName(attribute->attributeHeader()->attributeTypeIdentifier).c_str(), attribute->attributeHeader()->nonResidentFlag, attribute->attributeHeader()->attributeLength); #else DEBUG(INFO, "\tattr @ 0x%x, type: 0x%x: %s, non resident: 0x%x, attribute length: 0x%x\n", attribute->attributeOffset(), attribute->attributeHeader()->attributeTypeIdentifier, attribute->getName(attribute->attributeHeader()->attributeTypeIdentifier).c_str(), attribute->attributeHeader()->nonResidentFlag, attribute->attributeHeader()->attributeLength); #endif if (attribute->getType() == ATTRIBUTE_STANDARD_INFORMATION) { metaSI = new AttributeStandardInformation(*attribute); if (metaSI->data()->flags & ATTRIBUTE_SI_FLAG_DIRECTORY) { DEBUG(INFO, "setting dir\n"); fileType = 2; } else if (metaSI->data()->flags & ATTRIBUTE_SI_FLAG_SYSTEM || metaSI->data()->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) { DEBUG(INFO, "setting file\n"); fileType = 1; } } if (attribute->getType() == ATTRIBUTE_FILE_NAME) { metaFileName = new AttributeFileName(*attribute); if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace == ATTRIBUTE_FN_NAMESPACE_POSIX) { #if __WORDSIZE == 64 if ((metaFileName->data()->parentDirectoryFileReference & 0xffffffUL) == dirMftEntry) #else if ((metaFileName->data()->parentDirectoryFileReference & 0xffffffULL) == dirMftEntry) #endif { fullFileName = metaFileName; } if (metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_DIRECTORY) { DEBUG(INFO, "setting dir\n"); fileType = 2; } else if (metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_SYSTEM || metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) { DEBUG(INFO, "setting file\n"); fileType = 1; } if (!size) { size = metaFileName->data()->realSizeOfFile; #if __WORDSIZE == 64 DEBUG(INFO, "size from filename %lu\n", size); DEBUG(INFO, "size from data attr %lu\n", metaFileName->data()->allocatedSizeOfFile); #else DEBUG(INFO, "size from filename %llu\n", size); DEBUG(INFO, "size from data attr %llu\n", metaFileName->data()->allocatedSizeOfFile); #endif } DEBUG(INFO, "filename is %s\n", metaFileName->getFileName().c_str()); } } if (attribute->getType() == ATTRIBUTE_DATA) { // XXX delete previous data ? data = new AttributeData(*attribute); if (!size) { size = data->getSize(); } if (!data->attributeHeader()->nonResidentFlag) { data->offset(data->getOffset() + offset + data->attributeOffset()); } ads++; } if (attribute->getType() == ATTRIBUTE_ATTRIBUTE_LIST) { attributeList = new AttributeAttributeList(_vfile, *attribute); attributeList->setMftEntry(curMftEntry); } } #if __WORDSIZE == 64 DEBUG(INFO, "data size before %lu size is %lu\n", data->getSize(), size); #else DEBUG(INFO, "data size before %llu sise is %llu\n", data->getSize(), size); #endif if (attributeList && (fileType == 1) && !data->getOffset()) { while ((extAttrData = attributeList->getExternalAttributeData())) { // Fetch every offsets of external $DATA attributes if (extAttrData) { dataOffsets.push_back(_mftMainFile->data()->offsetFromID(extAttrData)); #if __WORDSIZE == 64 DEBUG(INFO, "External attrdata: 0x%x @ size: 0x%x latest addr pushed: 0x%lx\n", extAttrData, (uint32_t)dataOffsets.size(), dataOffsets.back()); #else DEBUG(INFO, "External attrdata: 0x%x @ size: 0x%x latest addr pushed: 0x%llx\n", extAttrData, (uint32_t)dataOffsets.size(), dataOffsets.back()); #endif } } if (dataOffsets.size()) { if (_mftEntry->decode(dataOffsets.front())) { // Set data from the first $DATA attribute while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_DATA) { data = new AttributeData(*attribute); if (!data->attributeHeader()->nonResidentFlag) { data->offset(data->getOffset() + offset + data->attributeOffset()); } if (!size && data->attributeHeader()->nonResidentFlag) { // Here we assume this first external $DATA attr holds real size of file ! size = data->nonResidentDataHeader()->attributeContentActualSize; #if __WORDSIZE == 64 DEBUG(INFO, "sizes from external attr $DATA are: %lu (alloc), %lu (actual), %lu (init)\n", data->nonResidentDataHeader()->attributeContentAllocatedSize, data->nonResidentDataHeader()->attributeContentActualSize, data->nonResidentDataHeader()->attributeContentInitializedSize); #else DEBUG(INFO, "sizes from external attr $DATA are: %llu (alloc), %llu (actual), %llu (init)\n", data->nonResidentDataHeader()->attributeContentAllocatedSize, data->nonResidentDataHeader()->attributeContentActualSize, data->nonResidentDataHeader()->attributeContentInitializedSize); #endif } ads++; } } } } } #if __WORDSIZE == 64 DEBUG(INFO, "data size after %lu\n", data->getSize()); #else DEBUG(INFO, "data size after %llu\n", data->getSize()); #endif if (fullFileName) { #if __WORDSIZE == 64 DEBUG(INFO, "\t\tmftentry %u about to create %s offset 0x%lx\n", curMftEntry, fullFileName->getFileName().c_str(), offset); #else DEBUG(INFO, "\t\tmftentry %u about to create %s offset 0x%llx\n", curMftEntry, fullFileName->getFileName().c_str(), offset); #endif if (curMftEntry != NTFS_ROOT_DIR_MFTENTRY) { if (ads <= 1) { newNode = new NtfsNode(fullFileName->getFileName().c_str(), data->getSize(), currentDir, this, (fileType == 1), fullFileName, metaSI, _mftEntry, curMftEntry, offset); newNode->node(_node); if (fileType == 1 && newNode) { newNode->data(data); if (dataOffsets.size() > 1) { newNode->dataOffsets(dataOffsets); } } } else { // XXX Case of heavy fragmented file + ADS ignored newNode = _createRegularADSNodes(offset, ads, curMftEntry, metaSI, currentDir, fullFileName); } std::vector newVector; newVector.push_back(newNode); _mftEntryToNode.insert(std::pair >(curMftEntry, newVector)); } if (fileType == 2 && curMftEntry != NTFS_ROOT_DIR_MFTENTRY && newNode) { #if __WORDSIZE == 64 DEBUG(INFO, "\t\tcreate dir %s mftentry %u offset 0x%lx\n", fullFileName->getFileName().c_str(), curMftEntry, offset); #else DEBUG(INFO, "\t\tcreate dir %s mftentry %u offset 0x%llx\n", fullFileName->getFileName().c_str(), curMftEntry, offset); #endif _parseDirTree(newNode, curMftEntry, offset); } } } void Ntfs::_createLinkedNode(Node *currentDir, uint32_t dirMftEntry, uint32_t curMftEntry) { Attribute *attribute; std::vector::iterator it = _mftEntryToNode[curMftEntry].begin(); AttributeFileName *metaFileName = NULL; AttributeFileName *fullFileName = NULL; uint64_t offset; AttributeAttributeList *attrList = NULL; uint32_t externalFileName = 0; while (it != _mftEntryToNode[curMftEntry].end()) { if (currentDir == (*it)->parent()) { DEBUG(INFO, "%u already discovered\n", curMftEntry); return ; } else { DEBUG(INFO, "%u already discovered in node %s discovered as link in %s\n", curMftEntry, currentDir->name().c_str(), (*it)->parent()->name().c_str()); ; } it++; } if (_mftEntryToNode[curMftEntry].size()) { DEBUG(INFO, "%u searching real filename\n", curMftEntry); if ((offset = _mftMainFile->data()->offsetFromID(curMftEntry))) { #if __WORDSIZE == 64 DEBUG(INFO, "%u offset is 0x%lx\n", curMftEntry, offset); #else DEBUG(INFO, "%u offset is 0x%llx\n", curMftEntry, offset); #endif _mftEntry->decode(offset); while ((attribute = _mftEntry->getNextAttribute())) { DEBUG(INFO, "%u attribute\n", curMftEntry); attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_FILE_NAME) { metaFileName = new AttributeFileName(*attribute); if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace == ATTRIBUTE_FN_NAMESPACE_POSIX) { DEBUG(INFO, "%u filename %s\n", curMftEntry, metaFileName->getFileName().c_str()); #if __WORDSIZE == 64 if ((metaFileName->data()->parentDirectoryFileReference & 0xffffffUL) == dirMftEntry) #else if ((metaFileName->data()->parentDirectoryFileReference & 0xffffffULL) == dirMftEntry) #endif { fullFileName = metaFileName; break; } } } if (attribute->getType() == ATTRIBUTE_ATTRIBUTE_LIST) { attrList = new AttributeAttributeList(_vfile, *attribute); attrList->setMftEntry(curMftEntry); } } if (attrList && !fullFileName) { while ((externalFileName = attrList->getExternalAttributeFileName())) { DEBUG(INFO, "got %u\n", externalFileName); if (_mftEntry->decode(_mftMainFile->data()->offsetFromID(externalFileName))) { // XXX no need to resync _mftEntry ? while ((attribute = _mftEntry->getNextAttribute())) { DEBUG(INFO, "reading\n"); attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_FILE_NAME) { metaFileName = new AttributeFileName(*attribute); if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace == ATTRIBUTE_FN_NAMESPACE_POSIX) { DEBUG(INFO, "%u filename %s\n", curMftEntry, metaFileName->getFileName().c_str()); #if __WORDSIZE == 64 if ((metaFileName->data()->parentDirectoryFileReference & 0xffffffUL) == dirMftEntry) #else if ((metaFileName->data()->parentDirectoryFileReference & 0xffffffULL) == dirMftEntry) #endif { fullFileName = metaFileName; break; } } } } } } } } } if (fullFileName) { VLink *newLink = new VLink(_mftEntryToNode[curMftEntry][0], currentDir, fullFileName->getFileName().c_str()); DEBUG(INFO, "link created for mft #%u with name %s\n", curMftEntry, fullFileName->getFileName().c_str()); _mftEntryToNode[curMftEntry].push_back(newLink); } } void Ntfs::_parseDirTree(Node *currentDir, uint32_t dirMftEntry, uint64_t mftEntryDirOffset) { AttributeIndexRoot *indexRoot = NULL; AttributeIndexAllocation *indexAllocation = NULL; uint32_t indexRecordSize; uint32_t entryOffset; uint32_t relOffsetEndUsed; uint32_t curMftEntry; bool indexRootOver = false; uint64_t offset; uint32_t prevEntryOffset = 0; #if __WORDSIZE == 64 DEBUG(INFO, "0x%lx\tParsedir tree beginning\n", mftEntryDirOffset); #else DEBUG(INFO, "0x%llx\tParsedir tree beginning\n", mftEntryDirOffset); #endif if (!_mftEntry->decode(mftEntryDirOffset)) { return; } /** * Search for files index/btree in _mftEntry */ indexRecordSize = _searchIndexesInEntry(mftEntryDirOffset, &indexRoot, &indexAllocation); DEBUG(INFO, "Indexes search done.\n"); if (!indexRoot) { return ; } if (indexAllocation == NULL && indexRoot != NULL && indexRoot->nodeHeader()->flags == ENTRY_CHILD_NODE_EXIST) { return ; } if (indexRoot->data()->attributeInIndexType != ATTRIBUTE_FILE_NAME || (!indexRoot->entriesAmount() && indexAllocation == NULL)) { return ; } /** * Set indexes depending of attributes discovered */ _initTreeWalk(indexRoot, indexAllocation, indexRecordSize, &entryOffset, &relOffsetEndUsed); #if __WORDSIZE == 64 DEBUG(INFO, "Next entry is at 0x%x, amount of entries in indexRoot %u\n", entryOffset, indexRoot->entriesAmount()); #else DEBUG(INFO, "Next entry is at 0x%x, amount of entries in indexRoot %u\n", entryOffset, indexRoot->entriesAmount()); #endif /** * Iter every valid files index */ while (entryOffset < relOffsetEndUsed) { // Get next file entry to create from tree if (indexAllocation) { if (!indexRootOver) { curMftEntry = indexRoot->nextMftEntry(); } else { curMftEntry = indexAllocation->readNextIndex(); } } else { curMftEntry = indexRoot->nextMftEntry(); } if (curMftEntry == 0 && prevEntryOffset == entryOffset) { break; } #if __WORDSIZE == 64 DEBUG(INFO, "0x%lx\tcurrent 0x%x end 0x%x mft# %u length entry %u\n", mftEntryDirOffset, entryOffset, relOffsetEndUsed, curMftEntry, indexRoot->currentEntryLength()); #else DEBUG(INFO, "0x%llx\tcurrent 0x%x end 0x%x mft# %u\n", mftEntryDirOffset, entryOffset, relOffsetEndUsed, curMftEntry); #endif if (!(_mftMainFile->isEntryDiscovered(curMftEntry)) && curMftEntry < _mftMainFile->getNumberOfRecords()) { _mftMainFile->entryDiscovered(curMftEntry); _setStateInfo(_mftMainFile->discoverPercent()); if ((offset = _mftMainFile->data()->offsetFromID(curMftEntry))) { if (_mftEntry->decode(offset)) { /** * Entry is valid and has never been discovered. * Create file or dir and recurse if needed. */ _createRegularNode(currentDir, dirMftEntry, offset, curMftEntry); } } } else if (curMftEntry && curMftEntry < _mftMainFile->getNumberOfRecords()) { /** * Entry can already be discovered but sit in an other directory. * Create link. */ _createLinkedNode(currentDir, dirMftEntry, curMftEntry); } prevEntryOffset = entryOffset; _updateTreeWalk(indexRoot, indexAllocation, &entryOffset, &relOffsetEndUsed, &indexRootOver); #if __WORDSIZE == 64 DEBUG(INFO, "0x%lx\tend of loop current 0x%x end 0x%x mft# %u\n", mftEntryDirOffset, entryOffset, relOffsetEndUsed, curMftEntry); #else DEBUG(INFO, "0x%llx\tend of loop current 0x%x end 0x%x mft# %u\n", mftEntryDirOffset, entryOffset, relOffsetEndUsed, curMftEntry); #endif } DEBUG(INFO, "loop...\n"); //_mftMainFile->dumpDiscoveredEntries(); } void Ntfs::_walkMftMainFile() { std::string filename; uint64_t rootDirOffset; DEBUG(INFO, "totalRecords: %u\n", _mftMainFile->getNumberOfRecords()); rootDirOffset = _mftMainFile->data()->offsetFromID(NTFS_ROOT_DIR_MFTENTRY); #if __WORDSIZE == 64 DEBUG(INFO, "Root directory offset is 0x%lx\n", rootDirOffset); #else DEBUG(INFO, "Root directory offset is 0x%llx\n", rootDirOffset); #endif /** * Here we can set offset of a directory to recurse in */ _parseDirTree(_root, NTFS_ROOT_DIR_MFTENTRY, rootDirOffset); } void Ntfs::_setRootDirectory(uint64_t mftEntryOffset) { Attribute *attribute; #if __WORDSIZE == 64 DEBUG(INFO, "root directory mftentry is @0x%lx\n", mftEntryOffset); #else DEBUG(INFO, "root directory mftentry is @0x%llx\n", mftEntryOffset); #endif if (_mftEntry->decode(mftEntryOffset)) { // _mftEntry->dumpHeader(); /** * Set root entry meta data */ while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_STANDARD_INFORMATION) { _rootDirectory->standardInformation(attribute); } else if (attribute->getType() == ATTRIBUTE_FILE_NAME) { _rootDirectory->fileName(attribute); } else if (attribute->getType() == ATTRIBUTE_SECURITY_DESCRIPTOR) { _rootDirectory->securityDescriptor(attribute); } else if (attribute->getType() == ATTRIBUTE_INDEX_ROOT) { _rootDirectory->indexRoot(attribute); } else if (attribute->getType() == ATTRIBUTE_INDEX_ALLOCATION) { _rootDirectory->indexAllocation(attribute); } } DEBUG(INFO, "Index allocation has %u runs\n", _rootDirectory->indexAllocation()->getRunListSize()); std::ostringstream filename; _rootDirectory->indexAllocation()->fillRecords(_boot->getBootBlock()->bytePerSector, _boot->clusterSize(), _rootDirectory->indexRoot()->indexRecordSizeBytes()); \ while (_rootDirectory->indexRoot()->hasNext()) { _rootDirectory->indexAllocation()->readNextIndex(); } } } void Ntfs::_deletedNodeWithADS(uint64_t offset, uint32_t adsAmount, uint32_t mftID, AttributeStandardInformation *metaSI) { Attribute *attribute; AttributeFileName *metaFileName = NULL; AttributeFileName *fullFileName = NULL; AttributeData **data = new AttributeData *[adsAmount]; uint8_t fileType = 0; uint64_t size = 0; uint32_t iADS = 0; _mftEntry->decode(offset); while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_FILE_NAME) { metaFileName = new AttributeFileName(*attribute); if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace == ATTRIBUTE_FN_NAMESPACE_POSIX) { fullFileName = metaFileName; } if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_POSIX) { if (metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_SYSTEM || metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) { fileType = 1; } } if (!size) size = metaFileName->data()->realSizeOfFile; } if (attribute->getType() == ATTRIBUTE_DATA) { data[iADS] = new AttributeData(*attribute); if (!size) size = data[iADS]->getSize(); if (!data[iADS]->attributeHeader()->nonResidentFlag) data[iADS]->offset(data[iADS]->getOffset() + offset + data[iADS]->attributeOffset()); iADS++; } } for (iADS = 0; iADS < adsAmount; iADS++) { std::ostringstream name; if (fullFileName != NULL){ // XXX Added by jmo in order to avoid Segfault when fullFileName == 0 name << fullFileName->getFileName() << data[iADS]->getExtName(); _createOrphanOrDeleted(name.str(), fullFileName, true, data[iADS], mftID, metaSI, offset); } } //done before: _setStateInfo(_mftMainFile->discoverPercent()); } void Ntfs::_checkOrphanEntries() { std::map entryMap = _mftMainFile->getEntryMap(); std::map::iterator it = entryMap.begin(); uint64_t offset; Attribute *attribute; uint32_t i = 0; uint32_t mftAmountOfRecords = _mftMainFile->getNumberOfRecords(); while (i < mftAmountOfRecords) { if (it == entryMap.end() || i != it->first) { DEBUG(INFO, "Checking id 0x%x\n", i); _mftMainFile->entryDiscovered(i); if ((offset = _mftMainFile->data()->offsetFromID(i))) { DEBUG(INFO, "Parsing id 0x%x\n", i); if (_mftEntry->decode(offset)) { AttributeFileName *metaFileName = NULL; AttributeFileName *fullFileName = NULL; AttributeStandardInformation *metaSI = NULL; AttributeData *data = new AttributeData(); uint8_t fileType = 0; uint64_t size = 0; uint32_t ads = 0; #if __WORDSIZE == 64 DEBUG(INFO, "Offset is 0x%lx\n", offset); #else DEBUG(INFO, "Offset is 0x%llx\n", offset); #endif while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_STANDARD_INFORMATION) { metaSI = new AttributeStandardInformation(*attribute); } if (attribute->getType() == ATTRIBUTE_FILE_NAME) { metaFileName = new AttributeFileName(*attribute); if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace == ATTRIBUTE_FN_NAMESPACE_POSIX) { fullFileName = metaFileName; } if (metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_DIRECTORY) { fileType = 2; } else if (metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_WIN32 || metaFileName->data()->nameSpace & ATTRIBUTE_FN_NAMESPACE_POSIX) { if (metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_SYSTEM || metaFileName->data()->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) { fileType = 1; } } if (!size) size = metaFileName->data()->realSizeOfFile; } if (attribute->getType() == ATTRIBUTE_DATA) { data = new AttributeData(*attribute); if (!size) size = data->getSize(); if (!data->attributeHeader()->nonResidentFlag) data->offset(data->getOffset() + offset + data->attributeOffset()); ads++; } } if (ads <= 1) { if (fileType == 1 && fullFileName) { _createOrphanOrDeleted(fullFileName->getFileName(), fullFileName, true, data, i, metaSI, offset); _setStateInfo(_mftMainFile->discoverPercent()); } else if (fileType == 2 && fullFileName) { _createOrphanOrDeleted(fullFileName->getFileName(), fullFileName, false, data, i, metaSI, offset); _setStateInfo(_mftMainFile->discoverPercent()); } } // FIXME metaSI can be null ? else if (metaSI) { _deletedNodeWithADS(offset, ads, i, metaSI); } } } } if (it != entryMap.end() && i == it->first) { DEBUG(INFO, "inc it\n"); it++; } i++; } //_mftMainFile->dumpDiscoveredEntries(); } /** * Read the $Bitmap FS top-level metafile create nodes made of unallocated * space if "bitmap-parse" argument is true. * - Searches for $Bitmap file with MFT entry number 6. * - Reads $Bitmap content. * - Fills the unallocated top-level node directory with one node file for * each unallocated cluster chunk. */ void Ntfs::_readBitmap() { std::string nodeName = std::string("$Bitmap"); uint32_t childCount = _root->childCount(); uint32_t i = 0; std::vector children = _root->children(); NtfsNode *bitmap = NULL; VFile *vfile; uint8_t *data; Node *unallocatedByAddresses = NULL; uint8_t bit; uint64_t clusterIndex = 0; uint64_t unallocChunkStart = 0; bool inUnalloc = false; // Gets the $Bitmap metafile if (!nodeName.size()) { return ; } DEBUG(CRITICAL, "childCount: %u\n", childCount); DEBUG(CRITICAL, "parent is %s\n", _root->name().c_str()); while (i != childCount && bitmap == NULL) { DEBUG(VERBOSE, "checking for %s\n", children[i]->name().c_str()); if (children[i]->name() == nodeName) { bitmap = (NtfsNode *)children[i]; if (bitmap->getMftEntry() != 6) { // $Bitmap metafile is always entry #6 bitmap = NULL; } } ++i; } if (bitmap == NULL) { DEBUG(CRITICAL, "Can't find a valid $Bitmap metafile\n"); return ; } #if __WORDSIZE == 64 DEBUG(CRITICAL, "Opening $Bitmap file, %lu bytes.\n", bitmap->size()); #else DEBUG(CRITICAL, "Opening $Bitmap file, %llu bytes.\n", bitmap->size()); #endif // Reads $Bitmap content data = new uint8_t[bitmap->size()]; vfile = bitmap->open(); vfile->read(data, bitmap->size()); vfile->close(); i = 0; while (i != bitmap->size()) { DEBUG(CRITICAL, "0x%x bytes is 0x%x\n", i, data[i]); for (bit = 0x1; ; bit <<= 1 ) { // Iterates inside each bit DEBUG(CRITICAL, " %c %lu %lu\n", ((data[i] & bit) ? '1' : '0'), clusterIndex, unallocChunkStart); if (!((data[i] & bit) || inUnalloc)) { unallocChunkStart = clusterIndex; /* Must use a boolean in case of $Bitmap file starting with unallocated area unallocChunkStart remains 0 */ inUnalloc = true; } if ((data[i] & bit) && inUnalloc) { std::ostringstream unallocChunkName; unallocChunkName << unallocChunkStart << "--" << clusterIndex; // Creates a 'by addresses' node new BitmapNode(unallocChunkName.str(), (clusterIndex - unallocChunkStart) * _boot->clusterSize(), _unallocRootNode, _node, this, unallocChunkStart, _boot->clusterSize()); unallocChunkStart = 0; inUnalloc = false; } ++clusterIndex; if (bit == 0x80) /* 0x80 = b10000000 = MSB mask Don't loop ; uint8_t overflow */ break; } ++i; } if (inUnalloc) { // End of $Bitmap file reached ending with unallocated area std::ostringstream unallocChunkName; unallocChunkName << unallocChunkStart << "--" << clusterIndex; new Node(unallocChunkName.str(), (clusterIndex - unallocChunkStart) * _boot->clusterSize(), unallocatedByAddresses, NULL); } delete data; } void Ntfs::_setStateInfo(std::string currentState) { stateinfo = currentState; _currentState = currentState; } void Ntfs::_setStateInfo(uint32_t percent) { std::ostringstream stateBuff; stateBuff.str(""); stateBuff << percent << "% " << _currentState; stateinfo = stateBuff.str(); } void Ntfs::start(std::map args) { uint64_t offset = 0; uint16_t mftEntryNumber; std::map::iterator it; bool noorphan = false; bool unalloc = true; if ((it = args.find("mftdecode")) != args.end()) this->_mftDecode = it->second->value(); else this->_mftDecode = (uint64_t)-1; #if __WORDSIZE == 64 DEBUG(INFO, "Only have to decode mft entry at offset 0x%lx\n", _mftDecode); #else DEBUG(INFO, "Only have to decode mft entry at offset 0x%llx\n", _mftDecode); #endif if ((it = args.find("indexdecode")) != args.end()) this->_indexDecode = it->second->value(); else this->_indexDecode = (uint64_t)-1; #if __WORDSIZE == 64 DEBUG(INFO, "Only have to decode index entries at offset 0x%lx\n", _indexDecode); #else DEBUG(INFO, "Only have to decode index entries at offset 0x%llx\n", _indexDecode); #endif if ((it = args.find("no-orphan")) != args.end()) noorphan = true; if ((it = args.find("no-bitmap-parse")) != args.end()) { DEBUG(CRITICAL, "Will create unallocated space as $Bitmap children\n"); unalloc = false; } /* Assume NTFS Boot sector is present */ if ((it = args.find("file")) != args.end()) { try { this->_node = it->second->value(); _vfile = _node->open(); _boot = new Boot(_vfile); _mftEntry = new MftEntry(_vfile); //XXX TMP VFILE #if __WORDSIZE == 64 if (_boot->isBootBlock(offset) && _mftDecode == 0x0UL - 1 && _indexDecode == 0x0UL - 1) #else if (_boot->isBootBlock(offset) && _mftDecode == 0x0ULL - 1 && _indexDecode == 0x0ULL - 1) #endif { /* Set offset to first MFT Entry */ offset = _boot->clusterSize() * _boot->getBootBlock()->startMft; /* Set size of read buffer * and set size of a tree node */ _mftEntry->clusterSize(_boot->clusterSize()); _mftEntry->indexRecordSize(_boot->indexRecordSize()); _mftEntry->sectorSize(_boot->sectorSize()); _mftEntry->mftEntrySize(_boot->mftEntrySize()); _setStateInfo("Boot block found"); } #if __WORDSIZE == 64 else if (_mftDecode == 0x0UL - 1 && _indexDecode == 0x0UL - 1) #else else if (_mftDecode == 0x0ULL - 1 && _indexDecode == 0x0ULL - 1) #endif { std::cerr << "No NTFS Boot Sector found" << std::endl; _setStateInfo(std::string("No NTFS Boot Sector found")); } #if __WORDSIZE == 64 else if (_mftDecode != 0x0UL -1) #else else if (_mftDecode != 0x0ULL - 1) #endif { std::ostringstream result; // switching to mft decode only, usefull for DC3 2k10 _mftEntry->clusterSize(4096); _mftEntry->indexRecordSize(4096); _mftEntry->sectorSize(512); _mftEntry->mftEntrySize(1024); if (_mftEntry->decode(_mftDecode)) { Attribute *attribute; //_mftEntry->dumpHeader(); #if __WORDSIZE == 64 printf("Decoding MFT entry at offset 0x%lx\n", _mftDecode); #else printf("Decoding MFT entry at offset 0x%llx\n", _mftDecode); #endif while ((attribute = _mftEntry->getNextAttribute())) { attribute->readHeader(); attribute->dumpHeader(); if (attribute->getType() == ATTRIBUTE_DATA) { AttributeData *_data = new AttributeData(*attribute); _data->setRunList(); } _mftEntry->dumpAttribute(attribute); } result << "MFT entry at offset " << _mftDecode << " (0x" << std::hex << _mftDecode << ") decoded, see std::out"; } else { result << "Unable to decode MFT entry at offset " << _mftDecode << " (0x" << std::hex << _mftDecode << ")"; } _setStateInfo(std::string(result.str())); return ; } #if __WORDSIZE == 64 else if (_indexDecode != 0x0UL - 1) #else else if (_indexDecode != 0x0ULL - 1) #endif { // switching to index decode only AttributeIndexAllocation *content = new AttributeIndexAllocation(_vfile, _indexDecode); std::ostringstream result; #if __WORDSIZE == 64 printf("Decoding Index entry at offset 0x%lx\n", _indexDecode); #else printf("Decoding Index entry at offset 0x%llx\n", _indexDecode); #endif content->dumpNodeHeader(); content->dumpEntries(); result << "Index record entry at offset " << _indexDecode << " (0x" << std::hex << _indexDecode << ") decoded, see std::out"; _setStateInfo(std::string(result.str())); return ; } /* MFTEntry size related */ if (!_boot->mftEntrySize()) { // No mft entry size discovered, so discover it DEBUG(INFO, "No MFTEntry size found, trying to search it\n"); _boot->mftEntrySize(_mftEntry->discoverMftEntrySize(offset)); } /* in case mftEntrySize is not present in boot block */ if (!_boot->mftEntrySize() && _boot->isPow2(_mftEntry->getMftEntryBlock()->allocatedSizeMftEntry)) { /* Set MFT entry size if ones in bootsector is invalid */ _boot->mftEntrySize(_mftEntry->getMftEntryBlock()->allocatedSizeMftEntry); } if (_boot->mftEntrySize() == 0) { /* Unable to find mft entry size either in bootsector or directly in an mft entry */ DEBUG(INFO, "Unable to find mft entry size either in bootsector or directly in an mft entry\n"); throw(vfsError(std::string("Unable to find mft entry size either in bootsector or directly in an mft entry"))); } _mftEntry->mftEntrySize(_boot->mftEntrySize()); if (_mftEntry->isMftEntryBlock(offset)) { // Mft is valid DEBUG(INFO, "\tValid MFTEntry found\n"); _root = new NtfsNode("NTFS", 0, NULL, this, _boot->getBootBlock()); mftEntryNumber = 0; _mftMainFile = new MftFile(_vfile, _boot->mftEntrySize(), _boot->indexRecordSize(), _boot->sectorSize(), _boot->clusterSize()); _setMftMainFile(offset); // search every files in MFT _setStateInfo("Searching for regular files and directories"); _walkMftMainFile(); if (noorphan == false) { _setStateInfo("Searching for deleted and orphans files and directories"); DEBUG(INFO, "Searching for deleted and orphans files\n"); _checkOrphanEntries(); } if (unalloc == true) { _setStateInfo("Read $Bitmap to create unallocated space nodes"); DEBUG(INFO, "Read $Bitmap to create unallocated space nodes\n"); _unallocRootNode = new NtfsNode("NTFS unallocated", 0, NULL, this, false, NULL, NULL, NULL); _readBitmap(); } _setStateInfo("Done"); } else { std::cerr << "No NTFS MFT Entry found" << std::endl; _setStateInfo(std::string("No NTFS MFT Entry found")); } if (_node && _root) { registerTree(_node, _root); } if (_node && _unallocRootNode) { registerTree(_node, _unallocRootNode); } } catch (vfsError & e) { std::cerr << "Exception vfsError caught in module Ntfs method start(): " << e.error << std::endl; _setStateInfo(std::string(e.error)); //throw e; } catch (envError & e) { std::cerr << "Exception envError caught in module Ntfs method start(): " << e.error << std::endl; _setStateInfo(e.error); //throw e; } catch (std::exception & e) { std::cerr << "Exception std::exception caught in module Ntfs method start(): " << e.what() << std::endl; _setStateInfo(e.what()); //throw e; } } else { std::cerr << "Ntfs method start(): no file provided" << std::endl; } } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/ntfs.hpp000066400000000000000000000065341217176075400206260ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __NTFS_HPP__ #define __NTFS_HPP__ //#include "vfile.hpp" //#include "type.hpp" //#include "vfs.hpp" //#include "conf.hpp" #include #include "common.hpp" #include "boot.hpp" #include "mftentry.hpp" #include "attribute.hpp" #include "ntfsnode.hpp" #include "mftfile.hpp" #include "vlink.hpp" #include "mfso.hpp" #if defined(__linux__) #include #elif defined(__FreeBSD__) #include #define __WORDSIZE __ELF_WORD_SIZE #elif defined(WIN64) || defined(WIN32) #if defined(WIN64) #define __WORDSIZE 64 #else #define __WORDSIZE 32 #endif #endif #define NTFS_ROOT_DIR_MFTENTRY 0x5 #if __WORDSIZE == 64 #define NTFS_ROOT_DIR_PARENTREF 0x0005000000000005UL #else #define NTFS_ROOT_DIR_PARENTREF 0x0005000000000005ULL #endif class Ntfs : public mfso { public: Ntfs(); ~Ntfs(); virtual void start(std::map); dff::Mutex _mutex; private: Node *_node; uint64_t _mftDecode; uint64_t _indexDecode; class NtfsNode *_root; class NtfsNode *_unallocRootNode; NtfsNode *_orphan; VFile *_vfile; Boot *_boot; MftEntry *_mftEntry; // one MFT entry MftFile *_mft; // MFT file MftFile *_mftMainFile; uint64_t _rootOffset; // offset of mftEntry corresponding to root of filesystem MftFile *_rootDirectory; std::string _currentState; std::map > _mftEntryToNode; void _setStateInfo(std::string); void _setStateInfo(uint32_t); void _setMftMainFile(uint64_t); void _setRootDirectory(uint64_t); void _walkMftMainFile(); void _rootSearch(); void _deletedNodeWithADS(uint64_t, uint32_t, uint32_t, AttributeStandardInformation *); void _createOrphanOrDeleted(std::string, AttributeFileName *, bool, AttributeData *, uint32_t, AttributeStandardInformation *, uint64_t); void _createDeletedWithParent(std::string, std::list, uint32_t, AttributeFileName *, AttributeData *, bool, AttributeStandardInformation *, uint64_t); NtfsNode *_ntfsNodeExists(std::string, NtfsNode *); uint32_t _searchIndexesInEntry(uint64_t, AttributeIndexRoot **, AttributeIndexAllocation **); void _initTreeWalk(AttributeIndexRoot *, AttributeIndexAllocation *, uint32_t, uint32_t *, uint32_t *); void _updateTreeWalk(AttributeIndexRoot *, AttributeIndexAllocation *, uint32_t *, uint32_t *, bool *); NtfsNode *_createRegularADSNodes(uint64_t, uint32_t, uint32_t, AttributeStandardInformation *, Node *, AttributeFileName *); void _createRegularNode(Node *, uint32_t, uint64_t, uint32_t); void _createLinkedNode(Node *, uint32_t, uint32_t); void _parseDirTree(Node *, uint32_t, uint64_t); void _checkOrphanEntries(); void _readBitmap(); }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/ntfs.i000066400000000000000000000052231217176075400202610ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include "pyrun.swg" %module NTFS %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "mfso.hpp" #include "rootnode.hpp" #include "ntfs.hpp" %} %import "../../../api/vfs/libvfs.i" %include "ntfs.hpp" %pythoncode %{ __dff_module_NTFS_version__ = "0.5.1" from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId class NTFS(Module): def __init__(self): Module.__init__(self, 'ntfs', Ntfs) self.conf.addArgument({"name": "file", "description": "file containing a NTFS file system", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "mftdecode", "description": "Only try to decode mft at this offset", "input": Argument.Optional|Argument.Single|typeId.UInt64}) self.conf.addArgument({"name": "indexdecode", "description": "Only try to decode index records at this offset", "input": Argument.Optional|Argument.Single|typeId.UInt64}) self.conf.addArgument({"name": "no-orphan", "description": "Don't check for orphaned or deleted files", "input": Argument.Empty}) self.conf.addArgument({"name": "no-bitmap-parse", "description": "Don't parse the top-level $Bitmap NTFS metafile to create a node filled with unallocated space", "input": Argument.Empty}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["NTFS"]}) self.conf.description = "Creates a tree from a NTFS file system, for regular and deleted/orphan files.\nIt also provides human-readable dump of MFT or Indexex entries." self.tags = "File systems" %} dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/ntfsnode.cpp000066400000000000000000000627451217176075400214750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #include "ntfsnode.hpp" #include NtfsNode::NtfsNode(std::string Name, uint64_t size, Node *parent, Ntfs *fsobj, bool isFile, AttributeFileName *metaFileName, AttributeStandardInformation *metaStandardInformation, MftEntry *mft): Node(Name, size, parent, fsobj) { _metaFileName = metaFileName; if (metaStandardInformation) { _SI = new AttributeStandardInformation(*metaStandardInformation); } else { _SI = NULL; } _isFile = isFile; if (isFile) { this->setFile(); setSize(size); } else { this->setDir(); } _mftEntry = 0; _physOffset = 0; _mft = mft; _data = NULL; setSize(size); _bootBlock = NULL; } NtfsNode::NtfsNode(std::string Name, uint64_t size, Node *parent, Ntfs *fsobj, bool isFile, AttributeFileName *metaFileName, AttributeStandardInformation *metaStandardInformation, MftEntry *mft, uint32_t mftEntry, uint64_t offset): Node(Name, size, parent, fsobj) { _metaFileName = metaFileName; if (metaStandardInformation) { _SI = new AttributeStandardInformation(*metaStandardInformation); } else { _SI = NULL; } _isFile = isFile; #if __WORDSIZE == 64 DEBUG(INFO, "%s %lu\n", Name.c_str(), size); #else DEBUG(INFO, "%s %llu\n", Name.c_str(), size); #endif if (isFile) { this->setFile(); setSize(size); } else this->setDir(); _mftEntry = mftEntry; _physOffset = offset; _mft = mft; _data = NULL; _bootBlock = NULL; } NtfsNode::NtfsNode(std::string Name, uint64_t size, Node *parent, Ntfs *fsobj, BootBlock *bootBlock): Node(Name, size, parent, fsobj) { _isFile = false; _metaFileName = NULL; _SI = NULL; _mft = NULL; _mftEntry = 0; _physOffset = 0; _data = NULL; this->setDir(); setSize(0); _bootBlock = bootBlock; } NtfsNode::~NtfsNode() { ; } std::map NtfsNode::_headerToAttribute(Attribute *attr) { std::map headerMap; std::map flagsMap; std::ostringstream stringBuff; headerMap["Length"] = Variant_p(new Variant(attr->attributeHeader()->attributeLength)); headerMap["Is non-resident"] = Variant_p(new Variant(attr->attributeHeader()->nonResidentFlag)); headerMap["Name length"] = Variant_p(new Variant(attr->attributeHeader()->nameLength)); headerMap["Attribute number"] = Variant_p(new Variant(attr->attributeHeader()->attributeIdentifier)); flagsMap["Value"] = Variant_p(new Variant(attr->attributeHeader()->flags)); flagsMap["Compressed"] = Variant_p(new Variant((attr->attributeHeader()->flags & ATTRIBUTE_FLAG_COMPRESSED) > 0)); flagsMap["Encrypted"] = Variant_p(new Variant((attr->attributeHeader()->flags & ATTRIBUTE_FLAG_ENCRYPTED) > 0)); flagsMap["Sparse"] = Variant_p(new Variant((attr->attributeHeader()->flags & ATTRIBUTE_FLAG_SPARSE) > 0)); flagsMap["Unknown flag present"] = Variant_p(new Variant((attr->attributeHeader()->flags && !(attr->attributeHeader()->flags & ATTRIBUTE_FLAG_COMPRESSED) && !(attr->attributeHeader()->flags & ATTRIBUTE_FLAG_ENCRYPTED) && !(attr->attributeHeader()->flags & ATTRIBUTE_FLAG_SPARSE)))); headerMap["Flags"] = Variant_p(new Variant(flagsMap)); if (attr->attributeHeader()->nonResidentFlag) { headerMap["Starting VCN"] = Variant_p(new Variant(attr->nonResidentDataHeader()->startingVCN)); headerMap["Ending VCN"] = Variant_p(new Variant(attr->nonResidentDataHeader()->endingVCN)); headerMap["Run-list offset"] = Variant_p(new Variant(attr->nonResidentDataHeader()->runListOffset)); headerMap["Compression unit size"] = Variant_p(new Variant(attr->nonResidentDataHeader()->compressionUnitSize)); headerMap["Content allocated size"] = Variant_p(new Variant(attr->nonResidentDataHeader()->attributeContentAllocatedSize)); headerMap["Content actual size"] = Variant_p(new Variant(attr->nonResidentDataHeader()->attributeContentActualSize)); headerMap["Content initialized size"] = Variant_p(new Variant(attr->nonResidentDataHeader()->attributeContentInitializedSize)); } else { headerMap["Content size"] = Variant_p(new Variant(attr->residentDataHeader()->contentSize)); headerMap["Content offset"] = Variant_p(new Variant(attr->residentDataHeader()->contentOffset)); } return headerMap; } Attributes NtfsNode::_attributes() { Attributes attr; DEBUG(INFO, "in extended attributes\n"); dff::ScopedMutex locker(dynamic_cast< Ntfs* >(this->fsobj())->_mutex); if (this->_bootBlock) { uint16_t clusterSize = this->_bootBlock->bytePerSector * this->_bootBlock->sectorPerCluster; // We are in a root NTFS node, populates it with NTFS parameters attr["Byte per sector"] = Variant_p(new Variant(this->_bootBlock->bytePerSector)); attr["Sector per cluster"] = Variant_p(new Variant(this->_bootBlock->sectorPerCluster)); attr["Cluster byte size"] = Variant_p(new Variant(clusterSize)); attr["Number of sector"] = Variant_p(new Variant(this->_bootBlock->numberOfSector)); attr["Number of byte"] = Variant_p(new Variant(this->_bootBlock->numberOfSector * clusterSize)); attr["MFT start cluster"] = Variant_p(new Variant(this->_bootBlock->startMft)); attr["MFT start address"] = Variant_p(new Variant(this->_bootBlock->startMft * clusterSize)); attr["MFTMirr start cluster"] = Variant_p(new Variant(this->_bootBlock->startMftMirr)); attr["MFTMirr start address"] = Variant_p(new Variant(this->_bootBlock->startMftMirr * clusterSize)); attr["MFT record cluster size"] = Variant_p(new Variant(this->_bootBlock->clusterMftRecord)); attr["MFT record byte size"] = Variant_p(new Variant(this->_bootBlock->clusterMftRecord * clusterSize)); attr["Index record cluster size"] = Variant_p(new Variant(this->_bootBlock->clusterIndexRecord)); attr["Index record byte size"] = Variant_p(new Variant(this->_bootBlock->clusterIndexRecord * clusterSize)); attr["Volume serial number"] = Variant_p(new Variant(this->_bootBlock->volumeSerialNumber)); } if (!(this->_SI)) { return attr; } attr["MFT entry number"] = Variant_p(new Variant(this->_mftEntry)); attr["MFT physical offset"] = Variant_p(new Variant(this->_physOffset)); attr["MFT cluster number"] = Variant_p(new Variant(this->_physOffset / this->_SI->clusterSize())); Attribute *attribute; attr["altered"] = Variant_p(new Variant(new vtime(this->_SI->data()->fileAlteredTime, TIME_MS_64))); attr["accessed"] = Variant_p(new Variant(new vtime(this->_SI->data()->fileAccessedTime, TIME_MS_64))); attr["creation"] = Variant_p(new Variant(new vtime(this->_SI->data()->creationTime, TIME_MS_64))); if (!(this->_mft->decode(this->_physOffset))) { return attr; } while ((attribute = (this->_mft->getNextAttribute()))) { std::map attributeMap; std::string attributeFullName; std::map attributeHeaderMap; attribute->readHeader(); attributeFullName = attribute->getFullName(); attributeHeaderMap = this->_headerToAttribute(attribute); if (attribute->getType() == ATTRIBUTE_STANDARD_INFORMATION) { this->_standardInformation(&attributeMap, new AttributeStandardInformation(*attribute)); } else if (attribute->getType() == ATTRIBUTE_FILE_NAME) { this->_fileName(&attributeMap, new AttributeFileName(*attribute)); } else if (attribute->getType() == ATTRIBUTE_DATA) { // Creates a 'Runs list' vmap made of every data chunk addresses. // FIXME does it impact performances ? Toggle it with a module argument. this->_dataAttribute(&attributeMap, new AttributeData(*attribute)); } DEBUG(INFO, "got name: %s\n", attributeFullName.c_str()); attributeMap.insert(std::pair("Header", Variant_p(new Variant(attributeHeaderMap)))); attributeMap.insert(std::pair("Offset", Variant_p(new Variant(attribute->attributeOffset())))); attr[attributeFullName] = Variant_p(new Variant(attributeMap)); } delete attribute; return attr; } void NtfsNode::_standardInformation(std::map *vmap, AttributeStandardInformation *nAttr) { std::map flagsMap; flagsMap["Value"] = Variant_p(new Variant(nAttr->data()->flags)); flagsMap["Read only"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_READ_ONLY) > 0)); flagsMap["Hidden"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_HIDDEN) > 0)); flagsMap["System"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_SYSTEM) > 0)); flagsMap["Archive"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) > 0)); flagsMap["Device"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_DEVICE) > 0)); flagsMap["#Normal"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_SHARPNORMAL) > 0)); flagsMap["Temporary"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_TEMPORARY) > 0)); flagsMap["Sparse"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_SPARSE_FILE) > 0)); flagsMap["Reparse point"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_REPARSE_POINT) > 0)); flagsMap["Compressed"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_COMPRESSED) > 0)); flagsMap["Offline"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_OFFLINE) > 0)); flagsMap["Content is not being indexed for faster searches"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED) > 0)); flagsMap["Encrypted"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_ENCRYPTED) > 0)); flagsMap["Directory"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_DIRECTORY) > 0)); flagsMap["Index view"] = Variant_p(new Variant((nAttr->data()->flags & ATTRIBUTE_SI_FLAG_INDEX_VIEW) > 0)); flagsMap["Unknown flag present"] = Variant_p(new Variant((nAttr->data()->flags && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_READ_ONLY) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_HIDDEN) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_SYSTEM) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_ARCHIVE) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_DEVICE) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_SHARPNORMAL) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_TEMPORARY) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_SPARSE_FILE) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_REPARSE_POINT) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_COMPRESSED) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_OFFLINE) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_CONTENT_NOT_INDEXED) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_ENCRYPTED) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_DIRECTORY) && !(nAttr->data()->flags & ATTRIBUTE_SI_FLAG_INDEX_VIEW)))); (*vmap)["Creation time"] = Variant_p(new Variant(new vtime(nAttr->data()->creationTime, TIME_MS_64))); (*vmap)["File altered time"] = Variant_p(new Variant(new vtime(nAttr->data()->fileAlteredTime, TIME_MS_64))); (*vmap)["MFT altered time"] = Variant_p(new Variant(new vtime(nAttr->data()->mftAlteredTime, TIME_MS_64))); (*vmap)["File accessed time"] = Variant_p(new Variant(new vtime(nAttr->data()->fileAccessedTime, TIME_MS_64))); (*vmap)["Flags"] = Variant_p(new Variant(flagsMap)); (*vmap)["Max number of versions"] = Variant_p(new Variant(nAttr->data()->maxNumberOfVersions)); (*vmap)["Version number"] = Variant_p(new Variant(nAttr->data()->versionNumber)); (*vmap)["Class ID"] = Variant_p(new Variant(nAttr->data()->classID)); (*vmap)["Owner ID"] = Variant_p(new Variant(nAttr->data()->ownerID)); (*vmap)["Security ID"] = Variant_p(new Variant(nAttr->data()->securityID)); (*vmap)["Quota charged"] = Variant_p(new Variant(nAttr->data()->quotaCharged)); (*vmap)["Update sequence number"] = Variant_p(new Variant(nAttr->data()->updateSequenceNumber)); delete nAttr; } void NtfsNode::_fileName(std::map *vmap, AttributeFileName *nAttr) { (*vmap)["Creation time"] = Variant_p(new Variant(new vtime(nAttr->data()->fileCreationTime, TIME_MS_64))); (*vmap)["File altered time"] = Variant_p(new Variant(new vtime(nAttr->data()->fileModificationTime, TIME_MS_64))); (*vmap)["MFT altered time"] = Variant_p(new Variant(new vtime(nAttr->data()->mftModificationTime, TIME_MS_64))); (*vmap)["File accessed time"] = Variant_p(new Variant(new vtime(nAttr->data()->fileAccessTime, TIME_MS_64))); delete nAttr; } void NtfsNode::_dataAttribute(std::map *vmap, AttributeData *data) { std::map runMap; OffsetRun *run; if (!data->attributeHeader()->nonResidentFlag || !data->getOffsetListSize()) return; run = data->getOffsetRun(0); runMap["length"] = Variant_p(new Variant(run->runLength)); runMap["cluster"] = Variant_p(new Variant(run->runOffset)); (*vmap)["First chunk"] = Variant_p(new Variant(runMap)); (*vmap)["Number of chunk"] = Variant_p(new Variant(data->getOffsetListSize())); delete data; } void NtfsNode::fileMapping(FileMapping *fm) { if (_isFile && size()) { if (_data->attributeHeader()->nonResidentFlag) { DEBUG(CRITICAL, "NtfsNode::fileMapping nonResident\n"); _offsetFromRunList(fm); } else { DEBUG(CRITICAL, "NtfsNode::fileMapping resident\n"); _offsetResident(fm); } } } /** * Set data chunks for data inside of MFT attribute * Fixups values are present in the last two bytes of sector * * TODO if mftEntrySize > sectorSize * 2 ; we need to loop to replace fixup */ void NtfsNode::_offsetResident(FileMapping *fm) { uint16_t dataStart = _data->residentDataHeader()->contentOffset + _data->getAttributeOffset(); uint16_t firstChunkSize = _data->getSectorSize() - SIZE_2BYTES - dataStart; uint16_t remainSize = size() - firstChunkSize - SIZE_2BYTES; DEBUG(CRITICAL, "\tdataStart: 0x%x\n", dataStart); DEBUG(CRITICAL, "\tsectorSize - 2: 0x%x\n", _data->getSectorSize() - 2); #if __WORDSIZE == 64 DEBUG(CRITICAL, "\tfirst fixup: 0x%lx\n", _physOffset + _data->getFixupOffset(0)); #else DEBUG(CRITICAL, "\tfirst fixup: 0x%llx\n", _physOffset + _data->getFixupOffset(0)); #endif fm->push(0, firstChunkSize, _node, _data->getOffset()); fm->push(firstChunkSize, SIZE_2BYTES, _node, _physOffset + _data->getFixupOffset(0)); fm->push(firstChunkSize + SIZE_2BYTES, remainSize, _node, SIZE_2BYTES + firstChunkSize + _data->getOffset()); } /** * Set data chunks for data outside of MFT attribute, offsets are in a runlist */ void NtfsNode::_offsetFromRunList(FileMapping *fm) { uint16_t currentRunIndex = 0; uint64_t currentOffset = 0; uint64_t registeredClusters = 0; uint64_t newSize; AttributeData currentData = *(_data); uint16_t offsetListSize = currentData.getOffsetListSize(); OffsetRun *run; DEBUG(CRITICAL, "Offset list size: %u\n", offsetListSize); while ((currentRunIndex < offsetListSize)) { run = currentData.getOffsetRun(currentRunIndex); newSize = (run->runLength - registeredClusters) * currentData.clusterSize(); if (run->runOffset) { //1.1 + 2.1 + 3.1 if (currentOffset + newSize > currentData.getSize()) { //1.1 if ((currentOffset + newSize) > currentData.getInitSize() && currentData.getSize() > currentData.getInitSize()) { // > initSize, need to create shadow node fm->push(currentOffset, currentData.getInitSize() - currentOffset, _node, run->runOffset * currentData.clusterSize()); fm->push(currentOffset + (currentData.getInitSize() - currentOffset), newSize - (currentData.getInitSize() - currentOffset), NULL, 0); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM0.1 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", currentOffset, currentData.getInitSize() - currentOffset, run->runOffset * currentData.clusterSize()); DEBUG(CRITICAL, "FM0.1 for offset 0x%lx push size 0x%lx as shadow (empty content)\n", currentOffset + (currentData.getInitSize() - currentOffset), newSize - (currentData.getInitSize() - currentOffset)); #else DEBUG(CRITICAL, "FM0.1 for offset 0x%llx push size 0x%llx at origin offset 0x%llx\n", currentOffset, currentData.getInitSize() - currentOffset, run->runOffset * currentData.clusterSize()); DEBUG(CRITICAL, "FM0.1 for offset 0x%llx push size 0x%llx as shadow (empty content)\n", currentOffset + (currentData.getInitSize() - currentOffset), newSize - (currentData.getInitSize() - currentOffset)); #endif } else { fm->push(currentOffset, newSize - (currentOffset + newSize - currentData.getSize()), _node, run->runOffset * currentData.clusterSize()); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM1.1 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", currentOffset, newSize - (currentOffset + newSize - currentData.getSize()), run->runOffset * currentData.clusterSize()); #else DEBUG(CRITICAL, "FM1.1 for offset 0x%llx push size 0x%llx at origin offset 0x%llx\n", currentOffset, newSize - (currentOffset + newSize - currentData.getSize()), run->runOffset * currentData.clusterSize()); #endif } } else { //2.1 + 3.1 if ((currentOffset + newSize) > currentData.getInitSize()) { //2.1 // > initSize, need to create shadow node fm->push(currentOffset, currentData.getInitSize() - currentOffset, _node, run->runOffset * currentData.clusterSize()); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM2.1 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", currentOffset, currentData.getInitSize() - currentOffset, run->runOffset * currentData.clusterSize()); #else DEBUG(CRITICAL, "FM2.1 for offset 0x%llx push size 0x%llx at origin offset 0x%llx\n", currentOffset, currentData.getInitSize() - currentOffset, run->runOffset * currentData.clusterSize()); #endif fm->push(currentOffset + (currentData.getInitSize() - currentOffset), newSize - (currentData.getInitSize() - currentOffset), NULL, 0); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM2.1 for offset 0x%lx push size 0x%lx as shadow (empty content)\n", currentOffset + (currentData.getInitSize() - currentOffset), newSize - (currentData.getInitSize() - currentOffset)); #else DEBUG(CRITICAL, "FM2.1 for offset 0x%llx push size 0x%llx as shadow (empty content)\n", currentOffset + (currentData.getInitSize() - currentOffset), newSize - (currentData.getInitSize() - currentOffset)); #endif } else { //3.1 fm->push(currentOffset, newSize, _node, run->runOffset * currentData.clusterSize()); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM3.1 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", currentOffset, newSize, run->runOffset * currentData.clusterSize()); #else DEBUG(CRITICAL, "FM3.1 for offset 0x%llx push size 0x%llx at origin offset 0x%llx\n", currentOffset, newSize, run->runOffset * currentData.clusterSize()); #endif } } } else { // shadow //4.1 fm->push(currentOffset, newSize, NULL, 0); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM4.1 for offset 0x%lx push size 0x%lx as shadow (empty content)\n", currentOffset, newSize); #else DEBUG(CRITICAL, "FM4.1 for offset 0x%llx push size 0x%llx as shadow (empty content)\n", currentOffset, newSize); #endif } currentOffset += (run->runLength - registeredClusters) * currentData.clusterSize(); registeredClusters = run->runLength; currentRunIndex++; if (currentRunIndex >= offsetListSize && _dataOffsets.size() > 1) { // There are several $DATA attributes, we have to fetch the next one. // We also have to take care of $DATA attribute's name because of ADS // feature, we should rely of next valid VCN. #if __WORDSIZE == 64 DEBUG(CRITICAL, "starting VCN 0x%lx ending VCN 0x%lx\n", currentData.nonResidentDataHeader()->startingVCN, currentData.nonResidentDataHeader()->endingVCN); #else DEBUG(CRITICAL, "starting VCN 0x%llx ending VCN 0x%llx\n", currentData.nonResidentDataHeader()->startingVCN, currentData.nonResidentDataHeader()->endingVCN); #endif _setNextAttrData(fm, currentOffset); } } DEBUG(CRITICAL, "\n"); } void NtfsNode::_setNextAttrData(FileMapping *fm, uint64_t totalOffset) { std::list::const_iterator iter(_dataOffsets.begin()); std::list::const_iterator listend(_dataOffsets.end()); MftEntry *externalData; VFile *vfile; Attribute *attribute; AttributeData *data; uint64_t totalSize = _data->getSize(); uint64_t initSize = _data->getInitSize(); if (!_SI || _dataOffsets.size() <= 1) { DEBUG(CRITICAL, "No $STANDARD_INFORMATION attribute, returns\n"); return ; } // TODO _dataOffsets list should be ordered by VCN, but it seams to be done // in $ATTRIBUTE_LIST. // Init mft decoder vfile = _node->open(); externalData = new MftEntry(vfile); // Init sizes from previously registered attribute _data externalData->clusterSize(_data->clusterSize()); externalData->indexRecordSize(_data->indexRecordSize()); externalData->sectorSize(_data->sectorSize()); externalData->mftEntrySize(_data->mftEntrySize()); // First $DATA attribute is _data, has already been mapped above, // so increment iter. ++iter; while (iter != listend) { if (externalData->decode(*iter)) { while ((attribute = externalData->getNextAttribute())) { attribute->readHeader(); if (attribute->getType() == ATTRIBUTE_DATA) { data = new AttributeData(*attribute); #if __WORDSIZE == 64 DEBUG(CRITICAL, "data @ 0x%lx starting VCN 0x%lx ending VCN 0x%lx\n", *iter, data->nonResidentDataHeader()->startingVCN, data->nonResidentDataHeader()->endingVCN); #else DEBUG(CRITICAL, "data @ 0x%llx starting VCN 0x%llx ending VCN 0x%llx\n", *iter, data->nonResidentDataHeader()->startingVCN, data->nonResidentDataHeader()->endingVCN); #endif // TODO Same code as in _offsetFromRunList( merge in one func ? uint16_t currentRunIndex = 0; uint64_t currentOffset = 0; uint64_t newSize; uint16_t offsetListSize = data->getOffsetListSize(); uint64_t registeredClusters = 0; OffsetRun *run; DEBUG(CRITICAL, "Offset list size: %u\n", offsetListSize); while ((currentRunIndex < offsetListSize)) { run = data->getOffsetRun(currentRunIndex); newSize = (run->runLength - registeredClusters) * data->clusterSize(); if (run->runOffset) { if (currentOffset + newSize > totalSize) { // XXX if > initSize, need to create shadow node fm->push(totalOffset, newSize - (currentOffset + newSize - totalSize), _node, run->runOffset * data->clusterSize()); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM1.2 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", totalOffset, newSize - (currentOffset + newSize - totalSize), run->runOffset * data->clusterSize()); #else DEBUG(CRITICAL, "FM1.2 for offset 0x%llx push size 0x%llx at origin offset 0x%llx, runLength 0x%x clustSize 0x%x\n", totalOffset, newSize - (currentOffset + newSize - totalSize), run->runOffset * data->clusterSize(), run->runLength, data->clusterSize()); #endif } else { if ((currentOffset + newSize) > initSize) { // > initSize, need to create shadow node fm->push(totalOffset, initSize - currentOffset, _node, run->runOffset * data->clusterSize()); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM2.2 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", totalOffset, initSize - currentOffset, run->runOffset * data->clusterSize()); #else DEBUG(CRITICAL, "FM2.2 for offset 0x%llx push size 0x%llx at origin offset 0x%llx\n", totalOffset, initSize - currentOffset, run->runOffset * data->clusterSize()); #endif fm->push(totalOffset + (initSize - currentOffset), newSize - (initSize - currentOffset), NULL, 0); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM2.2 for offset 0x%lx push size 0x%lx as shadow (empty content)\n", totalOffset + (initSize - currentOffset), newSize - (initSize - currentOffset)); #else DEBUG(CRITICAL, "FM2.2 for offset 0x%llx push size 0x%llx as shadow (empty content)\n", totalOffset + (initSize - currentOffset), newSize - (initSize - currentOffset)); #endif } else { fm->push(totalOffset, newSize, _node, run->runOffset * data->clusterSize()); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM3.2 for offset 0x%lx push size 0x%lx at origin offset 0x%lx\n", totalOffset, newSize, run->runOffset * data->clusterSize()); #else DEBUG(CRITICAL, "FM3.2 for offset 0x%llx push size 0x%llx at origin offset 0x%llx\n", totalOffset, newSize, run->runOffset * data->clusterSize()); #endif } } } else { // shadow fm->push(totalOffset, newSize, NULL, 0); #if __WORDSIZE == 64 DEBUG(CRITICAL, "FM4.2 for offset 0x%lx push size 0x%lx as shadow (empty content)\n", totalOffset, newSize); #else DEBUG(CRITICAL, "FM4.2 for offset 0x%llx push size 0x%llx as shadow (empty content)\n", totalOffset, newSize); #endif } currentOffset += (run->runLength - registeredClusters) * data->clusterSize(); totalOffset += (run->runLength - registeredClusters) * data->clusterSize(); //currentOffset += (run->runLength) * data->clusterSize(); registeredClusters = run->runLength; currentRunIndex++; } //delete data; DEBUG(CRITICAL, "\n"); // throw("yeah"); break; } } } ++iter; } externalData->close(); //XXX close the vfile ... delete externalData; } dff-1.3.0+dfsg.1/dff/modules/fs/ntfs/ntfsnode.hpp000066400000000000000000000046221217176075400214700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Christophe Malinge * */ #ifndef __NTFSNODE_HPP__ #define __NTFSNODE_HPP__ #include "ntfs.hpp" #include "node.hpp" #include "vfile.hpp" #include "mftentry.hpp" #include "attributes/data.hpp" #include "attributes/filename.hpp" #include "boot.hpp" class NtfsNode : public Node { public: NtfsNode(std::string, uint64_t, Node *, class Ntfs *, bool, AttributeFileName *, AttributeStandardInformation *, MftEntry *); NtfsNode(std::string, uint64_t, Node *, Ntfs *, bool, AttributeFileName *, AttributeStandardInformation *, MftEntry *, uint32_t, uint64_t); NtfsNode(std::string Name, uint64_t size, Node *parent, Ntfs *fsobj, BootBlock *bootBlock); ~NtfsNode(); virtual void fileMapping(FileMapping *); void node(Node *node) { _node = node; }; void contentOffset(uint64_t offset) { _contentOffset = offset; }; void data(AttributeData *data) { _data = data; }; uint32_t getMftEntry() { return _mftEntry; }; void dataOffsets(std::list d) { _dataOffsets = d; }; Attributes _attributes(void); private: bool _isFile; AttributeStandardInformation *_SI; uint32_t _mftEntry; uint64_t _physOffset; MftEntry *_mft; BootBlock *_bootBlock; std::map _headerToAttribute(Attribute *); void _standardInformation(std::map *, AttributeStandardInformation *); void _fileName(std::map *, AttributeFileName *); void _dataAttribute(std::map *, AttributeData *); void _setNextAttrData(FileMapping *fm, uint64_t totalOffset); FileMapping *_fm; Node *_node; AttributeData *_data; uint64_t _contentOffset; std::list _dataOffsets; void _offsetResident(FileMapping *); void _offsetFromRunList(FileMapping *); AttributeFileName *_metaFileName; }; #endif dff-1.3.0+dfsg.1/dff/modules/fs/spare.py000066400000000000000000000105361217176075400176520ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob < sja@arxsys.fr> # __dff_module_spare_version__ = "1.0.0" from struct import unpack from dff.api.vfs import * from dff.api.module.module import * from dff.api.types.libtypes import Variant, VMap, Parameter, Argument, typeId from dff.api.vfs.libvfs import AttributesHandler class SpareNode(Node): def __init__(self, mfso, parent, name, pageSize = 512, spareSize = 16, lparent = None, invert = False): self.invert = invert if not self.invert: self.ssize = parent.size() - ((parent.size() / (pageSize + spareSize)) * spareSize) else: self.ssize = ((parent.size() / (pageSize + spareSize)) * spareSize) Node.__init__(self, name, self.ssize, lparent, mfso) self.setFile() self.__disown__() self.nparent = parent self.pageSize = pageSize self.spareSize = spareSize def fileMapping(self, fm): fm.thisown = False voffset = 0 offset = 0 if not self.invert: while voffset < self.ssize: fm.push(voffset, self.pageSize, self.nparent, offset) offset += (self.spareSize + self.pageSize) voffset += self.pageSize if self.invert: voffset = 0 offset = self.pageSize while voffset < self.ssize: fm.push(voffset, self.spareSize, self.nparent, offset) offset += (self.spareSize + self.pageSize) voffset += self.spareSize def _attributes(self): attr = VMap() attr["page size"] = Variant(self.pageSize) attr["spare size"] = Variant(self.spareSize) return attr class Spare(mfso): def __init__(self): mfso.__init__(self, "spare") self.name = "spare" self.__disown__() def start(self, args): self.invert = None try: self.parent = args['node'].value() except IndexError: return try: self.spareSize = args["spare size"].value() except IndexError: self.spareSize = 16 try: self.pageSize = args["page size"].value() except IndexError: self.pageSize = 512 try: self.invert = args["dump spare"] except IndexError: pass self.nosparenode = SpareNode(self, self.parent, "no-spare", self.pageSize, self.spareSize, None, False) if self.invert: self.sparenode = SpareNode(self, self.parent, "spare", self.pageSize, self.spareSize, self.parent, True) self.registerTree(self.parent, self.nosparenode) class spare(Module): """Recreate a dump without spare area. This could be usefull for recovering more data when carving a dump with slack, or before applying a file system reconstruction modules.""" def __init__(self): Module.__init__(self, 'spare', Spare) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "node", "description": "Delete spare areas in this node" }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.UInt16, "name": "spare size", "description": "Spare size", "parameters": {"type": Parameter.Editable, "predefined": [16, 8, 24, 32]} }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.UInt32, "name": "page size", "description": "Iterate on each page size", "parameters": {"type": Parameter.Editable, "predefined": [512, 256, 1024]} }) self.conf.addArgument({"input": Argument.Empty, "name": "dump spare", "description": "Create a node with only spares data" }) self.tags = "Node" dff-1.3.0+dfsg.1/dff/modules/hash/000077500000000000000000000000001217176075400164745ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/hash/CMakeLists.txt000066400000000000000000000011211217176075400212270ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER install_file( hash.py __init__.py ) dff-1.3.0+dfsg.1/dff/modules/hash/__init__.py000066400000000000000000000011021217176075400205770ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # __all__ = ["hash"] dff-1.3.0+dfsg.1/dff/modules/hash/hash.py000066400000000000000000000277701217176075400200060ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_hash_version__ = "1.0.0" import hashlib, os from dff.api.vfs import vfs from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.types.libtypes import Variant, VMap, VList, Parameter, Argument, typeId from dff.api.vfs.libvfs import AttributesHandler class HashSets(object): KNOWN_GOOD = True KNOWN_BAD = False def __init__(self): self.hsets = [] def add(self, hsetpath, hsettype): for hid in xrange(0, len(self.hsets)): hset = self.hsets[hid] if hset.path == hsetpath: if hset.knownGood != hsettype: if hset.knownGood == self.KNOWN_GOOD: print 'Hash set ' + str(hsetpath) + ' was already set as good, keeping old value' else: print 'Hash set ' + str(hsetpath) + ' was already set as bad, keeping old value' return hid try: self.hsets.append(HashSet(hsetpath, hsettype)) except RuntimeError: raise return len(self.hsets) - 1 def get(self, hsetid): return self.hsets[hsetid] def find(self, baseIDs, hash_value): foundinbase = [] for baseID in baseIDS: if getBase(baseIds).find(hash_value): foundinbase += baseID return foundinbase class HashSet(object): def __init__(self, hash_set, hsettype): self.hashType = None self.path = hash_set self.knownGood = hsettype if len(hash_set.split('\\')) != 1: self.name = hash_set.split('\\')[-1] elif len(hash_set.split('/')) != 1: self.name = hash_set.split('/')[-1] else: self.name = hash_set self.size = os.path.getsize(hash_set) self.gettype() def algo(self): return self.hashType def gettype(self): f = open(self.path) self.headerSize = 0 self.lineSize = len(f.readline()) self.hashSize = self.lineSize - 1 for algo in hashlib.algorithms: hobj = getattr(hashlib, algo) if (hobj().digestsize * 2) == self.hashSize: self.hashType = algo continue if self.hashType == None: f.close() raise RuntimeError("Hash set " + self.path + " type not found") self.len = (self.size - self.headerSize) / self.lineSize f.close() def getLine(self, file, line): file.seek(self.headerSize + (line * self.lineSize), 0) return int(file.read(self.hashSize), 16) def find(self, h): file = open(self.path) h = int(h, 16) found = self.binSearch(file, h, 0, self.len - 1) file.close() return found def binSearch(self, file, sha, low, high): while low <= high: mid = (low + high) / 2 fsha = self.getLine(file, mid) if fsha < sha: low = mid + 1 elif fsha > sha: high = mid - 1 else: file.close() return True return False def __len__(self): return self.len class HashInfo(object): def __init__(self): self.hashes = {} self.hsets = set() class AttributeHash(AttributesHandler): def __init__(self, parent, modname): AttributesHandler.__init__(self, modname) self.calculatedHash = {} self.parent = parent self.__disown__() def haveHash(self, node, algo): try: if self.calculatedHash[long(node.this)].has_key(algo): return True finally: return False def getHashes(self, node): hdic = {} calclist = [] try: hashes = self.calculatedHash[long(node.this)].hashes for h in hashes: if hashes[h] == None: calclist.append(h) else: hdic[h] = hashes[h] if len(calclist): hinstances = self.parent.calc(node, calclist) for hinstance in hinstances: hdic[hinstance.name] = hinstance.hexdigest() return hdic except KeyError: return {} def getHash(self, node, algo): try : h = self.calculatedHash[long(node.this)].hashes[algo] if h == None: return self.parent.calc(node, [algo])[0].hexdigest() return h except KeyError: return None def setHash(self, node, algo, h): try: hashInfo = self.calculatedHash[long(node.this)] except KeyError: hashInfo = HashInfo() self.calculatedHash[long(node.this)] = hashInfo hashInfo.hashes[algo] = h node.attributesHandlers().updateState() def setKnown(self, node, setId): try: hashInfo = self.calculatedHash[long(node.this)] except KeyError: hashInfo = HashInfo() self.calculatedHash[long(node.this)] = hashInfo hashInfo.hsets.add(setId) node.attributesHandlers().updateState() def attributes(self, node): m = VMap() hinfos = self.calculatedHash[long(node.this)] hashes = self.getHashes(node) for algo in hashes: v = Variant(str(hashes[algo])) m[str(algo)] = v if len(hinfos.hsets): knownBad = [] knownGood = [] for setId in hinfos.hsets: hset = self.parent.hashSets.get(setId) if hset.knownGood: knownGood.append(hset) else: knownBad.append(hset) if len(knownBad): badList = VList() for badSet in knownBad: vname = Variant(badSet.name) badList.append(vname) m["known bad"] = badList if len(knownGood): goodList = VList() for goodSet in knownGood: vname = Variant(goodSet.name) goodList.append(vname) m["known good"] = goodList return m def __del__(self): pass class HASH(Script): def __init__(self): Script.__init__(self, "hash") self.vfs = vfs.vfs() self.attributeHash = AttributeHash(self, "hash") self.hashSets = HashSets() self.knownBadFiles = 0 self.knownGoodFiles = 0 self.errorFiles = 0 self.skippedFiles = 0 self.setResults() def setResults(self): v = Variant(len(self.attributeHash.calculatedHash)) self.res["hashed files"] = v v = Variant(self.knownGoodFiles) self.res["known good files"] = v v = Variant(self.knownBadFiles) self.res["known bad files"] = v v = Variant(self.skippedFiles) self.res["skipped files"] = v v = Variant(self.errorFiles) self.res["Errors"] = v def start(self, args): currentSetId = [] lalgorithms = [] try: goodBases = args["known_good"].value() for base in goodBases: try: base = self.hashSets.add(base.value().path, HashSets.KNOWN_GOOD) currentSetId.append(base) except RuntimeError as error: print error except IndexError: pass try: badBases = args["known_bad"].value() for base in badBases: try : base = self.hashSets.add(base.value().path, HashSets.KNOWN_BAD) currentSetId.append(base) except RuntimeError as error: print error except IndexError: pass try: algorithms = args["algorithm"].value() except IndexError: algorithms = [] node = args["file"].value() try: maxSize = args["skip_size"].value() if node.size() > maxSize: self.skippedFiles += 1 self.setResults() return except IndexError: pass try: self.cacheSize = args["low_cache-limit"].value() except IndexError: self.cacheSize = 0 pass lalgorithms = set() for hsetId in currentSetId: algo = self.hashSets.get(hsetId).algo() lalgorithms.add(algo) for algo in algorithms: algo = algo.value() lalgorithms.add(algo) if len(lalgorithms) == 0: lalgorithms.add('sha1') if self.hashCalc(node, lalgorithms) == True: node.registerAttributes(self.attributeHash) if len(currentSetId): hset = [] hsetresults = None hashes = self.attributeHash.getHashes(node) for algo in lalgorithms: for hsetid in currentSetId: hset = self.hashSets.get(hsetid) if algo == hset.algo(): if hset.find(hashes[algo]): self.attributeHash.setKnown(node, hsetid) if hset.knownGood: self.knownGoodFiles += 1 node.setTag("known good") else: self.knownBadFiles += 1 node.setTag("known bad") self.setResults() def hashCalc(self, node, algorithms): if node.size() == 0: return False doalgo = [] for algo in algorithms: if not self.attributeHash.haveHash(node, algo): if node.size() > self.cacheSize: doalgo.append(algo) else: self.attributeHash.setHash(node, algo, None) if len(doalgo) == 0: return True hinstances = self.calc(node, doalgo) if len(hinstances) == 0: return False for hinstance in hinstances: self.attributeHash.setHash(node, hinstance.name, hinstance.hexdigest()) return True def calc(self, node, algorithms): buffsize = 10*1024*1024 hinstances = [] for algo in algorithms: if hasattr(hashlib, algo): func = getattr(hashlib, algo) instance = func() hinstances.append(instance) if len(hinstances): try : f = node.open() except IOError as e: f.close() self.errorFiles += 1 return [] buff = f.read(buffsize) total = len(buff) while len(buff) > 0: self.stateinfo = node.name() + " %d" % ((total / float(node.size())) * 100) + "%" for hinstance in hinstances: hinstance.update(buff) try : buff = f.read(buffsize) total += len(buff) except IOError as e: print "Error hashing files " + str(node.absolute()) + " can't read between offsets " + str(total) + " and " + str(total+buffsize) break self.stateinfo = node.name() + " %d" % ((total / float(node.size())) * 100) + "%" f.close() return hinstances self.errorFiles += 1 return [] class hash(Module): """Hash a file and add the results in the file attribute. ex: hash /myfile""" def __init__(self): Module.__init__(self, "hash", HASH) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "file", "description": "file to hash" }) self.conf.addArgument({"input": Argument.Optional|Argument.List|typeId.String, "name": "algorithm", "description": "algorithm(s) used to hash file", "parameters": {"type": Parameter.NotEditable, "predefined": ["sha1", "md5", "sha224", "sha256", "sha384", "sha512"]} }) self.conf.addArgument({"input": Argument.Optional|Argument.List|typeId.Path, "name": "known_good", "description" : "Path to file containing a sets of known good hashes", }) self.conf.addArgument({"input": Argument.Optional|Argument.List|typeId.Path, "name": "known_bad", "description" : "Path to file containing a sets of known bad hashes", }) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.UInt64, "name": "skip_size", "description" : "Each node with a size greater or equal to the one set will node be hashed"}) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.UInt64, "name": "low_cache-limit", "description" : "Set a low bound size for the cache.\nEach hash of a node with a size lesser or equal to the one set will not be cached,\nthis could lower the RAM usage on a dump with a very huge amount of nodes", }) self.flags = ["single", "generic"] self.tags = "Hash" self.icon = ":filehash" dff-1.3.0+dfsg.1/dff/modules/mailbox/000077500000000000000000000000001217176075400172045ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/mailbox/CMakeLists.txt000066400000000000000000000013661217176075400217520ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob if(PFF_FOUND AND BFIO_FOUND) add_subdirectory (exchange) else(PFF_FOUND AND BFIO_FOUND) message(STATUS "PFF or BFIO library not found. Exchange module will not be built.") endif(PFF_FOUND AND BFIO_FOUND) dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/000077500000000000000000000000001217176075400207665ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/CMakeLists.txt000066400000000000000000000025411217176075400235300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob if(WIN32) set(definitions -DLIBPFF_HAVE_BFIO -D_LIBPFF_TYPES_H_INTEGERS -D_LIBBFIO_TYPES_H_INTEGERS) set(pff_files ${PFF_DYN_LIBRARIES} ${BFIO_DYN_LIBRARIES}) endif() dff_cpp_module(PFF CPP_FILES pff.cpp pff_info.cpp pff_export.cpp pff_item_info.cpp pff_node_data.cpp pff_node_task.cpp pff_node_folder.cpp pff_node_contact.cpp pff_node_attachment.cpp pff_node_appointment.cpp pff_node_unallocated_blocks.cpp pff_node_email.cpp pff_node_email_message.cpp pff_node_email_attributes.cpp pff_node_email_transport_headers.cpp libbfio_wrapper.cpp SWIG_FILE pff.i DEFINITIONS ${definitions} LINK_LIBRARIES exceptions types vfs ${PFF_LIBRARY} ${BFIO_LIBRARY} INCLUDE_DIRS ${PFF_INCLUDE_DIR} ${BFIO_INCLUDE_DIR} EXTRA_FILES ${pff_files} ) dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/libbfio_wrapper.cpp000066400000000000000000000134011217176075400246370ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" #include "libbfio_wrapper.hpp" int dff_libbfio_file_io_handle_initialize(dff_libbfio_file_io_handle_t** dff_io_handle, libbfio_error_t** error) { if (dff_io_handle == NULL) return (-1); if (*dff_io_handle == NULL) { *dff_io_handle = (dff_libbfio_file_io_handle_t*)malloc(sizeof(dff_libbfio_file_io_handle_t)); if (*dff_io_handle == NULL) return (-1); } return (1); } int dff_libbfio_file_initialize(libbfio_handle_t **handle, libbfio_error_t** error, Node* parent) { dff_libbfio_file_io_handle_t *io_handle = NULL; if (handle == NULL) return( -1 ); if (*handle == NULL) { if (dff_libbfio_file_io_handle_initialize(&io_handle, error) == -1) return (-1); io_handle->access_flags = 0; io_handle->file = NULL; io_handle->parent = parent; if (libbfio_handle_initialize(handle, (intptr_t*)io_handle, dff_libbfio_file_io_handle_free, dff_libbfio_file_io_handle_clone, dff_libbfio_file_open, dff_libbfio_file_close, dff_libbfio_file_read, dff_libbfio_file_write, dff_libbfio_file_seek_offset, dff_libbfio_file_exists, dff_libbfio_file_is_open, dff_libbfio_file_get_size, LIBBFIO_FLAG_IO_HANDLE_MANAGED | LIBBFIO_FLAG_IO_HANDLE_CLONE_BY_FUNCTION, error) != 1 ) { libbfio_error_free(error); dff_libbfio_file_io_handle_free((intptr_t **) &io_handle, NULL ); return (-1); } } return (1); } int dff_libbfio_file_open(intptr_t *io_handle, int access_flags, libbfio_error_t** error) { dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (-1); if (file_io_handle->parent == NULL) return (-1); VFile* file = file_io_handle->parent->open(); if (file == NULL) return (-1); file_io_handle->file = file; file_io_handle->access_flags = access_flags; return (1); } int dff_libbfio_file_io_handle_free(intptr_t **io_handle, libbfio_error_t** error) { if (io_handle == NULL) return (-1); if (*io_handle == NULL) return (-1); dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*)(*io_handle); if (file_io_handle->file != NULL) { file_io_handle->file->close(); delete file_io_handle->file; file_io_handle->file = NULL; } free(file_io_handle); return (1); } int dff_libbfio_file_io_handle_clone(intptr_t **destination_io_handle, intptr_t *source_io_handle, libbfio_error_t** error) { if (destination_io_handle == NULL) return (-1); if (*destination_io_handle != NULL) return (-1); dff_libbfio_file_io_handle_t* source_file_io_handle = (dff_libbfio_file_io_handle_t*)source_io_handle; dff_libbfio_file_io_handle_t** destination_file_io_handle = (dff_libbfio_file_io_handle_t**) destination_io_handle; *destination_file_io_handle = (dff_libbfio_file_io_handle_t*)malloc(sizeof(dff_libbfio_file_io_handle_t)); (*destination_file_io_handle)->access_flags = source_file_io_handle->access_flags; (*destination_file_io_handle)->parent = source_file_io_handle->parent; (*destination_file_io_handle)->file = NULL; return (1); } int dff_libbfio_file_close(intptr_t *io_handle, libbfio_error_t** error) { dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (-1); if (file_io_handle->file == NULL) return (-1); file_io_handle->file->close(); file_io_handle->file = NULL; return (0); } ssize_t dff_libbfio_file_read(intptr_t *io_handle, uint8_t *buffer, size_t size, libbfio_error_t** error) { dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (0); if (file_io_handle->file == NULL) return (0); return (file_io_handle->file->read((void*)buffer, size)); } ssize_t dff_libbfio_file_write(intptr_t *io_handle, const uint8_t *buffer, size_t size, libbfio_error_t** error) { return (-1); } off64_t dff_libbfio_file_seek_offset(intptr_t *io_handle, off64_t offset, int whence, libbfio_error_t** error) { dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (0); if (file_io_handle->file == NULL) return (0); return file_io_handle->file->seek((uint64_t)offset, (int32_t)whence); } int dff_libbfio_file_exists(intptr_t *io_handle, libbfio_error_t** error) { dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (0); if (file_io_handle->parent == NULL) return (0); return (1); } int dff_libbfio_file_is_open(intptr_t *io_handle, libbfio_error_t** error) { dff_libbfio_file_io_handle* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (-1); if (file_io_handle->file == 0) return (0); else return (1); return (-1); } int dff_libbfio_file_get_size(intptr_t *io_handle, size64_t *size, libbfio_error_t** error) { dff_libbfio_file_io_handle_t* file_io_handle = (dff_libbfio_file_io_handle_t*) io_handle; if (file_io_handle == NULL) return (0); if (file_io_handle->parent == NULL) return (0); *size = (size64_t) file_io_handle->parent->size(); return (1); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/libbfio_wrapper.hpp000066400000000000000000000036601217176075400246520ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __PFF_IO_HH__ #define __PFF_IO_HH__ #include #include struct dff_libbfio_file_io_handle { int access_flags; Node* parent; VFile* file; } typedef dff_libbfio_file_io_handle_t; int dff_libbfio_file_initialize(libbfio_handle_t **handle, libbfio_error_t **error, Node* parent); int dff_libbfio_file_io_handle_initialize(dff_libbfio_file_io_handle_t** io_handle, libbfio_error_t **error); int dff_libbfio_file_io_handle_free(intptr_t **io_handle, libbfio_error_t **error); int dff_libbfio_file_io_handle_clone(intptr_t **destination_io_handle, intptr_t *source_io_handle, libbfio_error_t **error); int dff_libbfio_file_open(intptr_t *io_handle, int access_flags, libbfio_error_t **error); int dff_libbfio_file_close(intptr_t *io_handle, libbfio_error_t **error); ssize_t dff_libbfio_file_read(intptr_t *io_handle, uint8_t *buffer, size_t size, libbfio_error_t **error); ssize_t dff_libbfio_file_write(intptr_t *io_handle, const uint8_t *buffer, size_t size, libbfio_error_t **error); off64_t dff_libbfio_file_seek_offset(intptr_t *io_handle, off64_t offset, int whence, libbfio_error_t **error); int dff_libbfio_file_exists(intptr_t *io_handle, libbfio_error_t **error); int dff_libbfio_file_is_open(intptr_t *io_handle, libbfio_error_t **error); int dff_libbfio_file_get_size(intptr_t *io_handle, size64_t *size, libbfio_error_t **error); #endif dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff.cpp000066400000000000000000000223271217176075400222530ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include #include "pff.hpp" #include "pff_macro.hpp" pff::pff() : mfso("exchange") { } pff::~pff() { libpff_error_t* pff_error = NULL; if (libpff_file_close(this->__pff_file, &pff_error) != 1) check_error(pff_error); if (libpff_file_free(&(this->__pff_file), &pff_error) != 1) check_error(pff_error); } void pff::start(std::map args) { std::string path; if (args.find("file") != args.end()) this->parent = args["file"]->value(); else throw envError("pff need a file argument."); try { this->initialize(this->parent); this->info(); if (args.find("unallocated") == args.end()) { this->stateinfo = std::string("Searching unallocated data"); this->create_unallocated(); } if (args.find("recoverable") == args.end()) { this->stateinfo = std::string("Searching recoverable items"); this->create_recovered(); } if (args.find("orphan") == args.end()) { this->stateinfo = std::string("Searching orphan items"); this->create_orphan(); } if (args.find("default") == args.end()) { this->stateinfo = std::string("Creating mailbox items"); this->create_item(); } } catch (vfsError e) { this->res["error"] = Variant_p(new Variant(e.error)); this->stateinfo = std::string(e.error); return ; } this->stateinfo = std::string("Mailbox parsed successfully"); res["Result"] = Variant_p(new Variant(std::string("Mailbox parsed successfully."))); } void pff::create_recovered(void) { int number_of_recovered_items = 0; int recovered_item_iterator = 0; int number_of_found_recovered_items = 0; libpff_item_t* pff_recovered_item = NULL; libpff_error_t* pff_error = NULL; if (libpff_file_recover_items(this->__pff_file, 0, &pff_error) != 1) { check_error(pff_error) return ; } if (libpff_file_get_number_of_recovered_items(this->__pff_file, &number_of_recovered_items, &pff_error) != 1) { check_error(pff_error) return ; } if (number_of_recovered_items > 0) { Node* recoveredNode = new Node(std::string("recovered"), 0, NULL, this); for (recovered_item_iterator = 0; recovered_item_iterator < number_of_recovered_items; recovered_item_iterator++) { if (libpff_file_get_recovered_item(this->__pff_file, recovered_item_iterator, &pff_recovered_item, &pff_error) == 1) { if (pff_recovered_item != NULL) { ItemInfo itemInfo = ItemInfo(pff_recovered_item, recovered_item_iterator, ItemInfo::Recovered); this->export_item(&itemInfo, recoveredNode); if (libpff_item_free(&pff_recovered_item, &pff_error) != 1) check_error(pff_error) number_of_found_recovered_items++; } } else check_error(pff_error) } this->res["Number of recovered items"] = Variant_p(new Variant(number_of_found_recovered_items)); this->registerTree(this->parent, recoveredNode); } } void pff::create_orphan() { int orphan_item_iterator = 0; int number_of_orphan_items = 0; int number_of_found_orphan_items = 0; libpff_item_t* pff_orphan_item = NULL; libpff_error_t* pff_error = NULL; if (libpff_file_get_number_of_orphan_items(this->__pff_file, &(number_of_orphan_items), &pff_error) != 1) { check_error(pff_error) return ; } if (number_of_orphan_items > 0) { Node* orphansNode = new Node(std::string("orphans"), 0, NULL, this); for (orphan_item_iterator = 0; orphan_item_iterator < number_of_orphan_items; orphan_item_iterator++) { if (libpff_file_get_orphan_item(this->__pff_file, orphan_item_iterator, &pff_orphan_item, &(pff_error)) == 1) { if (pff_orphan_item != NULL) { ItemInfo itemInfo = ItemInfo(pff_orphan_item, orphan_item_iterator, ItemInfo::Orphan); this->export_item(&itemInfo, orphansNode); if (libpff_item_free(&pff_orphan_item, &(pff_error))) check_error(pff_error) number_of_found_orphan_items++; } } else check_error(pff_error) } this->registerTree(this->parent, orphansNode); this->res["Number of orphan items"] = Variant_p(new Variant(number_of_found_orphan_items)); } } void pff::create_unallocated(void) { PffNodeUnallocatedBlocks* unallocatedPage = new PffNodeUnallocatedBlocks(std::string("unallocated page blocks"), NULL, this, this->parent, LIBPFF_UNALLOCATED_BLOCK_TYPE_PAGE); this->registerTree(this->parent, unallocatedPage); PffNodeUnallocatedBlocks* unallocatedData = new PffNodeUnallocatedBlocks(std::string("unallocated data blocks"), NULL, this, this->parent, LIBPFF_UNALLOCATED_BLOCK_TYPE_DATA); this->registerTree(this->parent, unallocatedData); } void pff::create_item() { libpff_item_t *pff_root_item = NULL; libpff_error_t* pff_error = NULL; int number_of_sub_items = 0; if (libpff_file_get_root_folder(this->__pff_file, &pff_root_item, &(pff_error)) != 1) { check_error(pff_error) throw vfsError(std::string("Unable to retrieve root item")); } if (libpff_item_get_number_of_sub_items(pff_root_item, &number_of_sub_items, &(pff_error)) != 1) { check_error(pff_error) throw vfsError(std::string("Unable to retrive number of sub items.")); } if (number_of_sub_items > 0) { PffNodeFolder* mbox = new PffNodeFolder(std::string("Mailbox"), NULL, this); this->export_sub_items(pff_root_item, mbox); if (libpff_item_free(&pff_root_item, &(pff_error))) check_error(pff_error) this->registerTree(this->parent, mbox); } } void pff::initialize(Node* parent) { libbfio_handle_t *handle = NULL; libbfio_error_t *error = NULL; libpff_error_t* pff_error = NULL; this->__pff_file = NULL; pff_error = NULL; if (libpff_file_initialize(&(this->__pff_file), &(pff_error)) != 1) { check_error(pff_error) throw vfsError(std::string("Unable to initialize system values.")); } if (dff_libbfio_file_initialize(&handle, &error, parent) != 1) { throw vfsError(std::string("Can't initialize libbfio wrapper for dff")); } if (libpff_file_open_file_io_handle(this->__pff_file, handle, LIBPFF_OPEN_READ, &(pff_error)) != 1) { check_error(pff_error) throw vfsError(std::string("Can't open file with libbfio")); } } int32_t pff::vopen(Node* tnode) { fdinfo* fi; int32_t fd; PffNodeData* node = dynamic_cast(tnode); if (node == NULL) { PffNodeUnallocatedBlocks* pnode = dynamic_cast(tnode); if (pnode) return (mfso::vopen(pnode)); return (-1); } if (!node->size()) return (-1); fi = node->vopen(); if (fi == NULL) return (-1); fd = this->__fdmanager->push(fi); return (fd); } int32_t pff::vread(int fd, void *buff, unsigned int size) { fdinfo* fi; try { fi = this->__fdmanager->get(fd); } catch (vfsError e) { return (0); } PffNodeData* node = dynamic_cast(fi->node); if (node == NULL) { if (dynamic_cast(fi->node)) return (mfso::vread(fd, buff, size)); return (0); } return (node->vread(fi, buff, size)); } int32_t pff::vclose(int fd) { fdinfo* fi; PffNodeData* node; try { fi = this->__fdmanager->get(fd); node = dynamic_cast(fi->node); PffNodeData* node = dynamic_cast(fi->node); if (node == NULL) { if(dynamic_cast(fi->node)) return (mfso::vclose(fd)); return (-1); } node->vclose(fi); this->__fdmanager->remove(fd); } catch (vfsError e) { return (-1); } return (0); } uint64_t pff::vseek(int fd, uint64_t offset, int whence) { fdinfo* fi; PffNodeData* node; try { fi = this->__fdmanager->get(fd); node = dynamic_cast(fi->node); if (node == NULL) { if (dynamic_cast(fi->node)) return (mfso::vseek(fd, offset, whence)); return ((uint64_t) -1); } return (node->vseek(fi, offset, whence)); } catch (vfsError e) { return ((uint64_t) -1); } return ((uint64_t) -1); } uint64_t pff::vtell(int32_t fd) { fdinfo* fi; try { fi = this->__fdmanager->get(fd); return (fi->offset); } catch (vfsError e) { return (uint64_t)-1; } } int32_t pff::vwrite(int fd, void* buff, unsigned int size) { return (0); } uint32_t pff::status(void) { return (0); } libpff_file_t* pff::pff_file(void) { return (this->__pff_file); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff.hpp000066400000000000000000000045671217176075400222660ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __PFF_HH__ #define __PFF_HH__ #include "pff_common.hpp" #include "pff_node.hpp" #include "pff_macro.hpp" #include "pff_item_info.hpp" #include "libbfio_wrapper.hpp" class pff : public mfso { private: Node* parent; libpff_file_t* __pff_file; int export_attachments(ItemInfo* item, Node* parent); int export_task(ItemInfo* item, Node* parent); int export_note(ItemInfo* item, Node* parent); int export_email(ItemInfo* item, Node* parent); int export_contact(ItemInfo* item, Node* parent); int export_meeting(ItemInfo* item, Node* parent); int export_appointment(ItemInfo* item, Node* parent); int export_message_default(ItemInfo* item, Node* parent, std::string item_type_name); int export_folder(ItemInfo* item, Node* parent); int export_sub_messages(ItemInfo* folder, PffNodeFolder* message); int export_sub_folders(ItemInfo* folder, PffNodeFolder* nodeFolder); public: pff(); ~pff(); void initialize(Node* parent); void info(); void info_file(); void info_message_store(); void create_item(); void create_recovered(); void create_orphan(); void create_unallocated(); void export_sub_items(libpff_item_t* item, Node* parent); int export_item(ItemInfo* item, Node* parent); int32_t vopen(Node*); int32_t vread(int fd, void *buff, unsigned int size); int32_t vclose(int fd); int32_t vwrite(int fd, void *buff, unsigned int size); uint32_t status(void); uint64_t vseek(int fd, uint64_t offset, int whence); uint64_t vtell(int32_t fd); virtual void start(std::map); libpff_file_t* pff_file(void); }; #endif dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff.i000066400000000000000000000044471217176075400217240ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module PFF %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "rootnode.hpp" #include "pff.hpp" %} %import "../../../api/vfs/libvfs.i" %include "pff.hpp" %pythoncode %{ from dff.api.module.module import * from dff.api.types.libtypes import * class PFF(Module): """Extract PST/PAB/OST mailbox content.""" def __init__(self): Module.__init__(self, 'exchange', pff) self.conf.addArgument({"input":Argument.Required|Argument.Single|typeId.Node, "name": "file", "description": "Path to mailbox file"}) self.conf.addArgument({"name":"unallocated", "description":"Don't search for unallocated data", "input": Argument.Empty}) self.conf.addArgument({"name":"recoverable", "description":"Don't search for recoverable items", "input": Argument.Empty}) self.conf.addArgument({"name":"orphan", "description":"Don't search for oprhan items", "input": Argument.Empty}) self.conf.addArgument({"name":"default", "description":"Don't create (allocated) items", "input": Argument.Empty}) self.conf.addConstant({"name":"mime-type", "type":typeId.String, "description":"managed mime type", "values":["Outlook"]}) self.tags = "Mailbox" self.icon = ":mailbox" %} dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_common.hpp000066400000000000000000000016711217176075400236270ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __PFF_COMMON_HH__ #define __PFF_COMMON_HH__ #include "vfs.hpp" #include "mfso.hpp" #include "node.hpp" #include "variant.hpp" #include "typesconv.hpp" #include #include #include #include #include #include #include #include #endif dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_export.cpp000066400000000000000000000446341217176075400236610ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include #include "pff.hpp" void pff::export_sub_items(libpff_item_t *item, Node* parent) { libpff_error_t* pff_error = NULL; libpff_item_t* sub_item = NULL; int number_of_sub_items = 0; int sub_item_iterator = 0; if (libpff_item_get_number_of_sub_items(item, &number_of_sub_items, &(pff_error)) != 1) { std::string error_name = "error on " + parent->name(); this->res[error_name] = new Variant(std::string("Unable to retrieve number of items.")); check_error(pff_error) return ; } for (sub_item_iterator = 0; sub_item_iterator < number_of_sub_items; sub_item_iterator++) { if (libpff_item_get_sub_item(item, sub_item_iterator, &sub_item, &(pff_error)) != 1) { error_on_item("Unable to retrieve subitem", sub_item_iterator, parent) check_error(pff_error) continue ; } ItemInfo itemInfo = ItemInfo(sub_item, sub_item_iterator, ItemInfo::SubItem); this->export_item(&itemInfo, parent); if (libpff_item_free(&sub_item, &(pff_error)) != 1) { error_on_item("Unable to free subitem", sub_item_iterator, parent) check_error(pff_error) continue ; } } } int pff::export_item(ItemInfo * itemInfo, Node* parent) { uint8_t item_type = 0; int result = 0; try { item_type = itemInfo->type(); } catch (std::string error) { return (0); } if (item_type == LIBPFF_ITEM_TYPE_ACTIVITY) { result = this->export_message_default(itemInfo, parent, std::string("Activity")); } else if (item_type == LIBPFF_ITEM_TYPE_APPOINTMENT) { result = this->export_appointment(itemInfo, parent); } else if (item_type == LIBPFF_ITEM_TYPE_CONTACT) { result = this->export_contact(itemInfo, parent); } else if (item_type == LIBPFF_ITEM_TYPE_DOCUMENT) { result = this->export_message_default(itemInfo, parent, std::string("Document")); } else if (item_type == LIBPFF_ITEM_TYPE_CONFLICT_MESSAGE || item_type == LIBPFF_ITEM_TYPE_EMAIL || item_type == LIBPFF_ITEM_TYPE_EMAIL_SMIME) { result = this->export_email(itemInfo, parent); } else if (item_type == LIBPFF_ITEM_TYPE_FOLDER) { result = this->export_folder(itemInfo, parent); } else if (item_type == LIBPFF_ITEM_TYPE_MEETING) { result = this->export_meeting(itemInfo, parent); } else if (item_type == LIBPFF_ITEM_TYPE_NOTE) { result = this->export_note(itemInfo, parent); } else if (item_type == LIBPFF_ITEM_TYPE_RSS_FEED) { result = this->export_message_default(itemInfo, parent, std::string("RSS")); } else if (item_type == LIBPFF_ITEM_TYPE_TASK) { result = this->export_task(itemInfo, parent); } else { error_on_item("Exporting unknown type for item", itemInfo->index(), parent) result = 1; } return (result); } int pff::export_message_default(ItemInfo* itemInfo, Node* parent, std::string item_type_name) { std::ostringstream folderName; folderName << std::string(item_type_name) << itemInfo->index() + 1; PffNodeFolder* nodeFolder = new PffNodeFolder(folderName.str(), parent, this); new PffNodeEmailMessageText(std::string(item_type_name), nodeFolder, this, itemInfo); return (1); } int pff::export_note(ItemInfo* itemInfo, Node* parent) { int result; std::ostringstream folderName; libpff_error_t* pff_error = NULL; size_t subject_string_size = 0; result = libpff_message_get_utf8_subject_size(itemInfo->pff_item(), &subject_string_size, &(pff_error)); if (result != 0 && result != -1 && subject_string_size > 0) { char* subject = (char*)malloc(sizeof(char *) * subject_string_size); if (libpff_message_get_utf8_subject(itemInfo->pff_item(), (uint8_t*)subject, subject_string_size, &(pff_error)) != 1) check_error(pff_error) folderName << std::string(subject); free(subject); } else { check_error(pff_error) folderName << "Note" << itemInfo->index() + 1; } PffNodeFolder* nodeFolder = new PffNodeFolder(folderName.str(), parent, this); new PffNodeNote("Note", nodeFolder, this, itemInfo); return (1); } int pff::export_meeting(ItemInfo* itemInfo, Node* parent) { libpff_error_t* pff_error = NULL; std::ostringstream folderName; size_t subject_string_size = 0; int result; result = libpff_message_get_utf8_subject_size(itemInfo->pff_item(), &subject_string_size, &(pff_error)); if (result != 0 && result != -1 && subject_string_size > 0) { char* subject = (char*)malloc(sizeof(char *) * subject_string_size); if (libpff_message_get_utf8_subject(itemInfo->pff_item(), (uint8_t*)subject, subject_string_size, &(pff_error)) != 1) check_error(pff_error) folderName << std::string(subject); free(subject); } else { check_error(pff_error) folderName << "Meeting" << itemInfo->index() + 1; } PffNodeFolder* nodeFolder = new PffNodeFolder(folderName.str(), parent, this); new PffNodeMeeting("Meeting", nodeFolder, this, itemInfo); return (1); } int pff::export_task(ItemInfo* itemInfo, Node* parent) { libpff_error_t* pff_error = NULL; std::ostringstream taskName; size_t subject_string_size = 0; int result; result = libpff_message_get_utf8_subject_size(itemInfo->pff_item(), &subject_string_size, &(pff_error)); if (result != 0 && result != -1 && subject_string_size > 0) { char* subject = (char*)malloc(sizeof(char *) * subject_string_size); if (libpff_message_get_utf8_subject(itemInfo->pff_item(), (uint8_t*)subject, subject_string_size, &(pff_error)) != 1) check_error(pff_error) taskName << std::string(subject); free(subject); } else { check_error(pff_error) taskName << std::string("Task") << itemInfo->index() + 1; } PffNodeFolder* nodeFolder = new PffNodeFolder(taskName.str(), parent, this); new PffNodeTask(std::string("Task"), nodeFolder, this, itemInfo); this->export_attachments(itemInfo, nodeFolder); return (1); } int pff::export_contact(ItemInfo* itemInfo, Node* parent) { libpff_error_t* pff_error = NULL; std::ostringstream contactName; size_t subject_string_size = 0; int result; result = libpff_message_get_utf8_subject_size(itemInfo->pff_item(), &subject_string_size, &(pff_error)); if (result != 0 && result != -1 && subject_string_size > 0) { char* subject = (char*)malloc(sizeof(char *) * subject_string_size); if (libpff_message_get_utf8_subject(itemInfo->pff_item(), (uint8_t*)subject, subject_string_size, &(pff_error)) != -1) check_error(pff_error) contactName << std::string(subject); free(subject); } else { check_error(pff_error) contactName << std::string("Contact") << itemInfo->index() + 1; } PffNodeFolder* nodeFolder = new PffNodeFolder(contactName.str(), parent, this); new PffNodeContact(std::string("Contact"), nodeFolder, this, itemInfo); this->export_attachments(itemInfo, nodeFolder); return (1); } int pff::export_appointment(ItemInfo* itemInfo, Node* parent) { libpff_error_t* pff_error = NULL; std::ostringstream messageName; size_t subject_string_size = 0; int result; result = libpff_message_get_utf8_subject_size(itemInfo->pff_item(), &subject_string_size, &(pff_error)); if (result != 0 && result != -1 && subject_string_size > 0) { char* subject = (char*)malloc(sizeof(char *) * subject_string_size); if (libpff_message_get_utf8_subject(itemInfo->pff_item(), (uint8_t*)subject, subject_string_size, &(pff_error)) != -1) check_error(pff_error) messageName << std::string(subject); free(subject); } else { check_error(pff_error) messageName << std::string("Appointment") << itemInfo->index() + 1; } PffNodeFolder* nodeFolder = new PffNodeFolder(messageName.str(), parent, this); new PffNodeAppointment(std::string("Appointment"), nodeFolder, this, itemInfo); this->export_attachments(itemInfo, nodeFolder); return (1); } int pff::export_folder(ItemInfo* itemInfo, Node* parent) { libpff_error_t* pff_error = NULL; PffNodeFolder* subFolder = NULL; uint8_t* folder_name = NULL; size_t folder_name_size = 0; int result = 0; result = libpff_folder_get_utf8_name_size(itemInfo->pff_item(), &folder_name_size, &(pff_error)); if (result == 0 || result == -1 || folder_name_size == 0) { std::ostringstream folderName; folderName << std::string("Folder") << itemInfo->index() + 1; subFolder = new PffNodeFolder(folderName.str(), parent, this); } else { folder_name = (uint8_t *) new uint8_t[folder_name_size]; result = libpff_folder_get_utf8_name(itemInfo->pff_item(), folder_name, folder_name_size, NULL); subFolder = new PffNodeFolder(std::string((char *)folder_name), parent, this); } if (export_sub_folders(itemInfo, subFolder) != 1) { check_error(pff_error) error_on_item("Unable to export subfolders", itemInfo->index(), subFolder) return (0); } if (export_sub_messages(itemInfo, subFolder) != 1) { check_error(pff_error) error_on_item("Unable to export submessages", itemInfo->index(), subFolder) return (0); } return (1); } int pff::export_email(ItemInfo* itemInfo, Node *parent) { libpff_error_t* pff_error = NULL; size_t email_html_body_size = 0; size_t email_rtf_body_size = 0; size_t email_text_body_size = 0; size_t transport_headers_size = 0; size_t subject_string_size = 0; int result; int has_html_body = 0; int has_rtf_body = 0; int has_text_body = 0; std::ostringstream messageName; result = libpff_message_get_utf8_subject_size(itemInfo->pff_item(), &subject_string_size, &(pff_error)); if (result != 0 && result != -1 && subject_string_size > 0) { char* subject = (char*)malloc(sizeof(char *) * subject_string_size); if (libpff_message_get_utf8_subject(itemInfo->pff_item(), (uint8_t*)subject, subject_string_size, &(pff_error)) != -1) check_error(pff_error) messageName << std::string(subject); free(subject); } else { check_error(pff_error) messageName << std::string("Message") << itemInfo->index() + 1; } has_html_body = libpff_message_get_html_body_size(itemInfo->pff_item(), &email_html_body_size, &(pff_error)); has_rtf_body = libpff_message_get_rtf_body_size(itemInfo->pff_item(), &email_rtf_body_size, &(pff_error)); has_text_body = libpff_message_get_plain_text_body_size(itemInfo->pff_item(), &email_text_body_size, &(pff_error)); PffNodeFolder* nodeFolder = new PffNodeFolder(messageName.str(), parent, this); if (libpff_message_get_utf8_transport_headers_size(itemInfo->pff_item(), &transport_headers_size, &(pff_error)) == 1) { if (transport_headers_size > 0) new PffNodeEmailTransportHeaders("Transport Headers", nodeFolder, this, itemInfo); } else check_error(pff_error) if (has_text_body == 1) { new PffNodeEmailMessageText("Message", nodeFolder, this, itemInfo); } else check_error(pff_error) if (has_html_body == 1) { new PffNodeEmailMessageHTML("Message HTML", nodeFolder, this, itemInfo); } else check_error(pff_error) if (has_rtf_body == 1) { new PffNodeEmailMessageRTF("Message RTF", nodeFolder, this, itemInfo); } else check_error(pff_error) this->export_attachments(itemInfo, nodeFolder); return (1); } int pff::export_attachments(ItemInfo* itemInfo, Node* parent) { int result = 0; int attachment_type = 0; int attachment_iterator = 0; int number_of_attachments = 0; size_t attachment_filename_size = 0; size64_t attachment_data_size = 0; uint8_t* attachment_filename = NULL; libpff_error_t* pff_error = NULL; if (libpff_message_get_number_of_attachments(itemInfo->pff_item(), &number_of_attachments, &(pff_error) ) != 1 ) { check_error(pff_error) return (-1); } if (number_of_attachments <= 0) { check_error(pff_error) return (-1); } for (attachment_iterator = 0; attachment_iterator < number_of_attachments; attachment_iterator++) { libpff_item_t *attachment = NULL; if (libpff_message_get_attachment(itemInfo->pff_item(), attachment_iterator, &attachment, &(pff_error)) != 1) { check_error(pff_error) continue ; } if (libpff_attachment_get_type(attachment, &attachment_type, &(pff_error)) != 1) { check_error(pff_error) if (libpff_item_free(&attachment, &(pff_error)) != 1) check_error(pff_error) continue; } if ((attachment_type != LIBPFF_ATTACHMENT_TYPE_DATA) && (attachment_type != LIBPFF_ATTACHMENT_TYPE_ITEM) && (attachment_type != LIBPFF_ATTACHMENT_TYPE_REFERENCE)) { if (libpff_item_free(&attachment, &(pff_error)) != 1) check_error(pff_error) continue; } if ((attachment_type == LIBPFF_ATTACHMENT_TYPE_REFERENCE)) { if (libpff_item_free(&attachment, &(pff_error)) != 1) check_error(pff_error) continue; } if (attachment_type == LIBPFF_ATTACHMENT_TYPE_DATA) if (libpff_attachment_get_utf8_long_filename_size(attachment, &attachment_filename_size, &(pff_error)) != 1) check_error(pff_error) attachment_filename = new uint8_t[attachment_filename_size]; if (attachment_filename == NULL) { if (libpff_item_free(&attachment, &(pff_error)) == 1) check_error(pff_error) delete attachment_filename; continue; } std::ostringstream attachmentName; if (attachment_type == LIBPFF_ATTACHMENT_TYPE_DATA) { if (libpff_attachment_get_utf8_long_filename(attachment, attachment_filename, attachment_filename_size, NULL) != 1 ) attachmentName << std::string("Attachment") << attachment_iterator + 1; else attachmentName << std::string((char*)attachment_filename); } else if (attachment_type == LIBPFF_ATTACHMENT_TYPE_ITEM) attachmentName << std::string("Attachment") << attachment_iterator + 1; if (attachment_type == LIBPFF_ATTACHMENT_TYPE_DATA) { result = libpff_attachment_get_data_size(attachment, &attachment_data_size, &(pff_error)); if (result == -1) { check_error(pff_error) libpff_item_free(&attachment, &(pff_error)); delete attachment_filename; continue; } if ((result != 0) && (attachment_data_size > 0 )) { new PffNodeAttachment(attachmentName.str(), parent, this, itemInfo, attachment_data_size, attachment_iterator); delete attachment_filename; libpff_item_free(&attachment, &(pff_error)); } } else if(attachment_type == LIBPFF_ATTACHMENT_TYPE_ITEM) { libpff_item_t* attached_item = NULL; if (libpff_attachment_get_item(attachment, &attached_item, &(pff_error)) == 1) { PffNodeFolder* folder = new PffNodeFolder(attachmentName.str(), parent, this); ItemInfo attachedItemInfo = ItemInfo(attached_item, attachment_iterator, ItemInfo::AttachmentItem, itemInfo); this->export_item(&attachedItemInfo, folder); if (libpff_item_free(&attached_item, &(pff_error)) != 1) check_error(pff_error) } else check_error(pff_error) if (libpff_item_free(&attachment, &(pff_error)) != 1) check_error(pff_error) delete attachment_filename; } } return (1); } int pff::export_sub_folders(ItemInfo* itemInfo, PffNodeFolder* nodeFolder) { libpff_item_t* sub_folder = NULL; int number_of_sub_folders = 0; int sub_folder_iterator = 0; libpff_error_t* pff_error = NULL; if (libpff_folder_get_number_of_sub_folders(itemInfo->pff_item(), &number_of_sub_folders, &(pff_error)) != 1) { check_error(pff_error) std::string error_name = "error on " + nodeFolder->name(); this->res[error_name] = new Variant(std::string("Unable to retrieve number of subfolders")); return (0); } for (sub_folder_iterator = 0; sub_folder_iterator < number_of_sub_folders; sub_folder_iterator++) { if (libpff_folder_get_sub_folder(itemInfo->pff_item(), sub_folder_iterator, &sub_folder, &(pff_error)) != 1) { check_error(pff_error) error_on_item("Unable to retrieve subfolders", sub_folder_iterator, nodeFolder) continue ; } ItemInfo itemInfo = ItemInfo(sub_folder, sub_folder_iterator, ItemInfo::SubFolder); if (export_folder(&itemInfo, nodeFolder) != 1) { error_on_item("Unable to export subfolder", sub_folder_iterator, nodeFolder) } if (libpff_item_free(&sub_folder, &(pff_error)) != 1) { check_error(pff_error) error_on_item("Unable to free subfolder", sub_folder_iterator, nodeFolder) } } return (1); } int pff::export_sub_messages(ItemInfo* itemInfo, PffNodeFolder* nodeFolder) { libpff_item_t *sub_message = NULL; int number_of_sub_messages = 0; int sub_message_iterator = 0; libpff_error_t* pff_error = NULL; if (libpff_folder_get_number_of_sub_messages(itemInfo->pff_item(), &number_of_sub_messages, &(pff_error)) != 1) { std::string error_name = "error on " + nodeFolder->name(); this->res[error_name] = new Variant(std::string("Unable to retrieve number of submessages")); return (0); } for (sub_message_iterator = 0; sub_message_iterator < number_of_sub_messages; sub_message_iterator++) { if (libpff_folder_get_sub_message(itemInfo->pff_item(), sub_message_iterator, &sub_message, &(pff_error)) != 1) { check_error(pff_error) error_on_item("Unable to retrieve submessage", sub_message_iterator, nodeFolder) continue ; } ItemInfo itemInfo = ItemInfo(sub_message, sub_message_iterator, ItemInfo::SubFolder); if (export_item(&itemInfo, nodeFolder) != 1) { error_on_item("Unable to export submessage", sub_message_iterator, nodeFolder) continue ; } if (libpff_item_free(&sub_message, &(pff_error)) != 1) { check_error(pff_error) error_on_item("Unable to free submessage", sub_message_iterator, nodeFolder) continue ; } } return (1); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_info.cpp000066400000000000000000000101571217176075400232640ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" libpff_macro_s LIBPFF_VALID_FOLDER_MASK[8] = { { LIBPFF_VALID_FOLDER_MASK_SUBTREE, "Subtree" }, { LIBPFF_VALID_FOLDER_MASK_INBOX, "Inbox" }, { LIBPFF_VALID_FOLDER_MASK_OUTBOX, "Outbox" }, { LIBPFF_VALID_FOLDER_MASK_WASTEBOX, "Wastebox" }, { LIBPFF_VALID_FOLDER_MASK_SENTMAIL, "Sentmail" }, { LIBPFF_VALID_FOLDER_MASK_VIEWS, "Views" }, { LIBPFF_VALID_FOLDER_MASK_COMMON_VIEWS, "Common views" }, { LIBPFF_VALID_FOLDER_MASK_FINDER, "Finder" } }; libpff_macro_s FILE_CONTENT_TYPE[3] = { { LIBPFF_FILE_CONTENT_TYPE_PAB, "Personal Address Book (PAB)" }, { LIBPFF_FILE_CONTENT_TYPE_PST, "Personal Storage Tables (PST)" }, { LIBPFF_FILE_CONTENT_TYPE_OST, "Offline Storage Tables (OST)" } }; libpff_macro_s FILE_TYPE[2] = { { LIBPFF_FILE_TYPE_32BIT, "32-bit" }, { LIBPFF_FILE_TYPE_64BIT, "64-bit" } }; libpff_macro_s FILE_ENCRYPTION_TYPE[3] = { { LIBPFF_ENCRYPTION_TYPE_NONE, "none" }, { LIBPFF_ENCRYPTION_TYPE_COMPRESSIBLE, "compressible" }, { LIBPFF_ENCRYPTION_TYPE_HIGH, "high" } }; void pff::info() { this->info_file(); this->info_message_store(); } void pff::info_file() { libpff_error_t* pff_error = NULL; size64_t file_size = 0; uint8_t file_content_type = 0; uint8_t file_type = 0; uint8_t encryption_type = 0; if (libpff_file_get_size(this->__pff_file, &file_size, &(pff_error)) != 1) { check_error(pff_error); return ; } if (libpff_file_get_content_type(this->__pff_file, &file_content_type, &(pff_error)) != 1) { check_error(pff_error); return ; } if (libpff_file_get_type(this->__pff_file, &file_type, &(pff_error)) != 1) { check_error(pff_error); return ; } if (libpff_file_get_encryption_type(this->__pff_file, &encryption_type, &(pff_error)) != 1) { check_error(pff_error); return ; } std::string message = ""; for (uint8_t n = 0; n < 3; n++) { if (file_content_type == FILE_CONTENT_TYPE[n].type) { message = FILE_CONTENT_TYPE[n].message; break; } } if (message != "") this->res["File type content"] = new Variant(message); else this->res["File type content"] = new Variant(std::string("Unknown")); message = ""; for (uint8_t n = 0; n < 2; n++) { if (file_type == FILE_TYPE[n].type) { message = FILE_TYPE[n].message; break; } } if (message != "") this->res["PFF file type"] = new Variant(message); else this->res["PFF file type"] = new Variant(std::string("Unknown")); message = ""; for (uint8_t n = 0; n < 3; n++) { if (encryption_type == FILE_ENCRYPTION_TYPE[n].type) { message = FILE_ENCRYPTION_TYPE[n].message; break; } } if (message != "") this->res["Encryption type"] = new Variant(message); else this->res["Encryption type"] = new Variant(std::string("Unknown")); } void pff::info_message_store() { libpff_error_t* pff_error = NULL; libpff_item_t* message_store = NULL; uint32_t password_checksum = 0; if (libpff_file_get_message_store(this->__pff_file, &message_store, &(pff_error)) == -1) { check_error(pff_error) return ; } if (libpff_message_store_get_password_checksum(message_store, &password_checksum, NULL) == 1) { if (password_checksum == 0) this->res["Password checksum"] = new Variant(std::string("N/A")); else this->res["Password checksum"] = new Variant(password_checksum); } if (libpff_item_free(&message_store, &(pff_error)) != 1) { check_error(pff_error) return ; } } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_item_info.cpp000066400000000000000000000104031217176075400242740ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff_item_info.hpp" Item::Item(libpff_item_t* item) { this->__item = item; this->__attacher = NULL; this->__attachment = NULL; } Item::Item(libpff_item_t* item, Item* attacher, libpff_item_t* attachment) { this->__item = item; this->__attacher = attacher; this->__attachment = attachment; } Item::~Item() { libpff_error_t* pff_error = NULL; if (this->__item != NULL) { if (libpff_item_free(&this->__item, &pff_error) != 1) check_error(pff_error); this->__item = NULL; } if (this->__attacher != NULL) { delete this->__attacher; this->__attacher = NULL; } if (this->__attachment != NULL) { if (libpff_item_free(&this->__attachment, &pff_error) != 1) check_error(pff_error); this->__attachment = NULL; } } libpff_item_t* Item::pff_item(void) { return (this->__item); } ItemInfo::ItemInfo(libpff_item_t* item, int index, ItemStatusType statusType, ItemInfo* attachedInfo) { libpff_error_t* pff_error; this->__item = item; this->__index = index; this->__id = 0; this->__statusType = statusType; this->__attachedInfo = attachedInfo; if (this->__statusType != Recovered && this->__statusType != Orphan && this->__statusType != AttachmentItem) if (libpff_item_get_identifier(this->__item, &(this->__id), &pff_error) != 1) check_error(pff_error); } ItemInfo::ItemInfo(ItemInfo* itemInfo) { this->__item = NULL; this->__index = itemInfo->index(); this->__id = itemInfo->identifier(); this->__statusType = itemInfo->statusType(); if (itemInfo->attachedInfo() != NULL) this->__attachedInfo = new ItemInfo(itemInfo->attachedInfo()); } ItemInfo::~ItemInfo() { } libpff_item_t* ItemInfo::pff_item(void) { return (this->__item); } Item* ItemInfo::item(libpff_file_t* const pff_file) { libpff_item_t* pff_item = NULL; libpff_error_t* pff_error = NULL; if (this->__statusType == Recovered) { if (libpff_file_get_recovered_item(pff_file, this->__index, &pff_item, &pff_error) == 1) return (new Item(pff_item)); else check_error(pff_error); } else if (this->__statusType == Orphan) { if (libpff_file_get_orphan_item(pff_file, this->__index, &pff_item, &pff_error) == 1) return (new Item(pff_item)); else check_error(pff_error); } else if (this->__statusType == AttachmentItem) { Item* attacher; if ((attacher = this->__attachedInfo->item(pff_file)) != NULL) { libpff_item_t* attachment = NULL; if (libpff_message_get_attachment(attacher->pff_item(), this->__index, &attachment, &pff_error) == 1) { if (libpff_attachment_get_item(attachment, &pff_item, &pff_error) == 1) return (new Item(pff_item, attacher, attachment)); else check_error(pff_error) delete attacher; if (libpff_item_free(&attachment, &pff_error) != 1) check_error(pff_error); } else { delete attacher; } } } else { if (libpff_file_get_item_by_identifier(pff_file, this->__id, &pff_item, &pff_error) == 1) return (new Item(pff_item)); else check_error(pff_error); } return (NULL); } ItemInfo* ItemInfo::attachedInfo(void) { return (this->__attachedInfo); } ItemInfo::ItemStatusType ItemInfo::statusType(void) { return (this->__statusType); } uint32_t ItemInfo::identifier(void) { return (this->__id); } uint8_t ItemInfo::type(void) { uint8_t item_type; libpff_error_t* pff_error = NULL; if (libpff_item_get_type(this->pff_item(), &item_type, &pff_error) == 1) return (item_type); check_error(pff_error) throw std::string("Can't get item type"); } int ItemInfo::index(void) { return (this->__index); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_item_info.hpp000066400000000000000000000033271217176075400243100ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __PFF_ITEM_INFO_HH__ #define __PFF_ITEM_INFO_HH__ #include "pff_common.hpp" #include "pff_macro.hpp" class Item { private: Item* __attacher; libpff_item_t* __item; libpff_item_t* __attachment; public: Item(libpff_item_t* item); Item(libpff_item_t* item, Item* attacher, libpff_item_t* attachment); ~Item(); libpff_item_t* pff_item(); }; class ItemInfo { public: enum ItemStatusType { Normal, Recovered, AttachmentItem, SubItem, SubFolder, Orphan }; ItemInfo(libpff_item_t* item, int index, ItemStatusType statusType, ItemInfo* attachedInfo = NULL); ItemInfo(ItemInfo* item); ~ItemInfo(); libpff_item_t* pff_item(void); Item* item(libpff_file_t* const pff_file); ItemInfo* attachedInfo(void); ItemStatusType statusType(void); uint32_t identifier(void); uint8_t type(void); int index(void); private: int __index; uint32_t __id; ItemStatusType __statusType; ItemInfo* __attachedInfo; libpff_item_t* __item; }; #endif dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_macro.hpp000066400000000000000000000044361217176075400234420ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __PFF_MACRO_HH__ #define __PFF_MACRO_HH__ #include "pff_common.hpp" struct libpff_macro_t { uint8_t type; const char* message; } typedef libpff_macro_s; struct libpff_macro32_t { uint32_t type; const char* message; } typedef libpff_macro32_s; #define check_error(error)\ libpff_error_free(&error); #define check_maximum_size(func) \ result = func(item, &entry_value_string_size, (&pff_error)); \ if (result != 0 && result != -1) \ {\ if (entry_value_string_size > maximum_entry_value_string_size)\ maximum_entry_value_string_size = entry_value_string_size;\ }\ else\ check_error(pff_error) #define value_string_to_attribute(func, key) \ result = func(item, (uint8_t *)entry_value_string, \ maximum_entry_value_string_size, &pff_error); \ if (result != -1 && result != 0) \ (*attr)[key] = new Variant(std::string(entry_value_string));\ else\ check_error(pff_error) #define value_time_to_attribute(func, key) \ result = func(item, &entry_value_64bit, &pff_error); \ if (result != -1 && result != 0) \ { \ vtime* value_time = new vtime(entry_value_64bit, TIME_MS_64); \ Variant* variant_time = new Variant(value_time); \ (*attr)[key] = variant_time; \ }\ else\ check_error(pff_error) #define value_uint32_to_attribute(func, key) \ result = func(item, &entry_value_32bit, &pff_error); \ if (result != -1 && result != 0) \ {\ (*attr)[key] = new Variant(entry_value_32bit); \ }\ else\ check_error(pff_error) #define error_on_item(error_value, Item_index, Parent)\ std::ostringstream error_name;\ error_name << "Error on " << Parent->name() << " item " << Item_index + 1;\ this->res[error_name.str()] = new Variant(std::string(error_value)); #endif dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node.hpp000066400000000000000000000121771217176075400232670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __PFF_NODE_HH__ #define __PFF_NODE_HH__ #include "pff.hpp" class pff; class ItemInfo; class PffNodeFolder : public Node { public: EXPORT PffNodeFolder(std::string name, Node* parent, pff* fsobj); EXPORT ~PffNodeFolder(); std::string icon(void); }; class PffNodeData : public Node { protected: ItemInfo* __itemInfo; pff* __pff(); public: EXPORT PffNodeData(std::string name, Node* parent, pff* fsobj); EXPORT PffNodeData(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo); EXPORT ~PffNodeData(); virtual fdinfo* vopen(); virtual int32_t vread(fdinfo* fi, void *buff, unsigned int size); virtual int32_t vclose(fdinfo* fi); virtual uint64_t vseek(fdinfo* fi, uint64_t offset, int whence); }; class PffNodeEMail : public PffNodeData { private: int attributesMessageHeader(Attributes* attr, libpff_item_t* item); int attributesMessageConversationIndex(Attributes* attr, libpff_item_t* item); int attributesRecipients(Attributes* attr, libpff_item_t* item); int attributesTransportHeaders(Attributes* attr, libpff_item_t* item); void splitTextToAttributes(std::string text, Attributes* attr); public: EXPORT PffNodeEMail(std::string name, Node* parent, pff* fsobj); EXPORT PffNodeEMail(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo); EXPORT virtual Attributes _attributes(void); Attributes allAttributes(libpff_item_t* item); fdinfo* vopen(void); int32_t vread(fdinfo* fi, void *buff, unsigned int size); int32_t vclose(fdinfo* fi); uint64_t vseek(fdinfo* fi, uint64_t offset, int whence); virtual uint8_t * dataBuffer(void); std::string icon(void); }; class PffNodeEmailTransportHeaders : public PffNodeEMail { public: EXPORT PffNodeEmailTransportHeaders(std::string, Node*, pff*, ItemInfo* itemInfo); EXPORT uint8_t * dataBuffer(void); }; class PffNodeEmailMessageText : public PffNodeEMail { public: EXPORT PffNodeEmailMessageText(std::string , Node*, pff*, ItemInfo* itemInfo); EXPORT uint8_t* dataBuffer(void); }; class PffNodeEmailMessageHTML : public PffNodeEMail { public: EXPORT PffNodeEmailMessageHTML(std::string , Node*, pff*, ItemInfo* itemInfo); EXPORT uint8_t* dataBuffer(void); }; class PffNodeEmailMessageRTF : public PffNodeEMail { public: EXPORT PffNodeEmailMessageRTF(std::string , Node*, pff*, ItemInfo* itemInfo); EXPORT uint8_t* dataBuffer(void); }; class PffNodeAttachment : public PffNodeEMail { private: int attachment_iterator; public: EXPORT PffNodeAttachment(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo, size64_t, int attachment_iterator); EXPORT uint8_t* dataBuffer(void); EXPORT std::string icon(void); }; class PffNodeAppointment : public PffNodeEMail { public: EXPORT PffNodeAppointment(std::string name, Node *parent, pff* fsobj, ItemInfo* itemInfo); EXPORT virtual Attributes _attributes(void); EXPORT void attributesAppointment(Attributes* attr, libpff_item_t*); EXPORT std::string icon(void); }; class PffNodeContact : public PffNodeEmailMessageText { public: EXPORT PffNodeContact(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo); EXPORT virtual Attributes _attributes(void); EXPORT void attributesContact(Attributes* attr, libpff_item_t*); EXPORT std::string icon(void); }; class PffNodeTask : public PffNodeEmailMessageText { public: EXPORT PffNodeTask(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo); EXPORT virtual Attributes _attributes(void); EXPORT void attributesTask(Attributes* attr, libpff_item_t*); EXPORT std::string icon(void); }; class PffNodeMeeting : public PffNodeEmailMessageText { public: EXPORT PffNodeMeeting(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo); EXPORT std::string icon(void); }; class PffNodeNote : public PffNodeEmailMessageText { public: EXPORT PffNodeNote(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo); EXPORT std::string icon(void); }; class PffNodeUnallocatedBlocks : public Node { private: pff* __pff(); Node* root; int block_type; public: EXPORT PffNodeUnallocatedBlocks(std::string name, Node* parent, pff* fsobj, Node* root, int block_type); virtual void fileMapping(FileMapping* fm); }; #endif dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_appointment.cpp000066400000000000000000000052251217176075400256740ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeAppointment::PffNodeAppointment(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEMail(name, parent, fsobj, itemInfo) { this->setFile(); } std::string PffNodeAppointment::icon(void) { return (":appointment"); } void PffNodeAppointment::attributesAppointment(Attributes* attr, libpff_item_t* item) { libpff_error_t* pff_error = NULL; char* entry_value_string = NULL; size_t entry_value_string_size = 0; size_t maximum_entry_value_string_size = 1; uint64_t entry_value_64bit = 0; uint32_t entry_value_32bit = 0; int result = 0; check_maximum_size(libpff_appointment_get_utf8_location_size) check_maximum_size(libpff_appointment_get_utf8_recurrence_pattern_size) if (maximum_entry_value_string_size == 0) return ; entry_value_string = (char *)malloc(sizeof(char *) * maximum_entry_value_string_size); if (entry_value_string == NULL) return ; value_time_to_attribute(libpff_appointment_get_start_time, "Start time") value_time_to_attribute(libpff_appointment_get_end_time, "End time") value_uint32_to_attribute(libpff_appointment_get_duration, "Duration") value_string_to_attribute(libpff_appointment_get_utf8_location, "Location") value_string_to_attribute(libpff_appointment_get_utf8_recurrence_pattern, "Recurrence pattern") value_time_to_attribute(libpff_appointment_first_effective_time, "First effective time") value_time_to_attribute(libpff_appointment_last_effective_time, "Last effective time") value_uint32_to_attribute(libpff_appointment_get_busy_status, "Busy status") free(entry_value_string); } Attributes PffNodeAppointment::_attributes() { Attributes attr; Item* item = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return attr; attr = this->allAttributes(item->pff_item()); Attributes appointment; this->attributesAppointment(&appointment, item->pff_item()); attr[std::string("Appointment")] = new Variant(appointment); delete item; return attr; } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_attachment.cpp000066400000000000000000000040211217176075400254570ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeAttachment::PffNodeAttachment(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo, size64_t size, int attachment_iterator) : PffNodeEMail(name, parent, fsobj, itemInfo) { this->attachment_iterator = attachment_iterator; this->setSize(size); } std::string PffNodeAttachment::icon(void) { return (":attach"); } uint8_t* PffNodeAttachment::dataBuffer(void) { uint8_t* buff = NULL; Item* item = NULL; libpff_item_t* attachment = NULL; libpff_error_t* pff_error = NULL; if (this->size() <= 0) return (NULL); if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return (NULL); if (libpff_message_get_attachment(item->pff_item(), attachment_iterator, &attachment, &pff_error) != 1) { check_error(pff_error) delete item; return (NULL); } buff = new uint8_t[this->size()]; ssize_t read_count = 0; if (libpff_attachment_data_seek_offset(attachment, 0, SEEK_SET, &pff_error) != 0) { check_error(pff_error) if (libpff_item_free(&attachment, &pff_error) != 1) check_error(pff_error) delete item; return (NULL); } read_count = libpff_attachment_data_read_buffer(attachment, (uint8_t*)buff , this->size(), &pff_error); if (read_count != (ssize_t)this->size()) check_error(pff_error) if (libpff_item_free(&attachment, &pff_error) != 1) check_error(pff_error) delete item; return (buff); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_contact.cpp000066400000000000000000000113531217176075400247700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeContact::PffNodeContact(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEmailMessageText(name, parent, fsobj, itemInfo) { } std::string PffNodeContact::icon(void) { return (":contact"); } Attributes PffNodeContact::_attributes(void) { Attributes attr; Item* item = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return attr; attr = this->allAttributes(item->pff_item()); Attributes contact; this->attributesContact(&contact, item->pff_item()); attr[std::string("Contact")] = new Variant(contact); delete item; return (attr); } void PffNodeContact::attributesContact(Attributes* attr, libpff_item_t* item) { libpff_error_t* pff_error = NULL; char* entry_value_string = 0; size_t entry_value_string_size = 0; size_t maximum_entry_value_string_size = 1; int result = 0; check_maximum_size(libpff_address_get_utf8_file_under_size) check_maximum_size(libpff_contact_get_utf8_given_name_size) check_maximum_size(libpff_contact_get_utf8_initials_size) check_maximum_size(libpff_contact_get_utf8_surname_size) check_maximum_size(libpff_contact_get_utf8_generational_abbreviation_size) check_maximum_size(libpff_contact_get_utf8_title_size) check_maximum_size(libpff_contact_get_utf8_callback_phone_number_size) check_maximum_size(libpff_contact_get_utf8_primary_phone_number_size) check_maximum_size(libpff_contact_get_utf8_home_phone_number_size) check_maximum_size(libpff_contact_get_utf8_mobile_phone_number_size) check_maximum_size(libpff_contact_get_utf8_company_name_size) check_maximum_size(libpff_contact_get_utf8_job_title_size) check_maximum_size(libpff_contact_get_utf8_postal_address_size) check_maximum_size(libpff_contact_get_utf8_office_location_size) check_maximum_size(libpff_contact_get_utf8_department_name_size) check_maximum_size(libpff_contact_get_utf8_country_size) check_maximum_size(libpff_contact_get_utf8_locality_size) check_maximum_size(libpff_contact_get_utf8_business_phone_number_1_size) check_maximum_size(libpff_contact_get_utf8_business_phone_number_2_size) check_maximum_size(libpff_contact_get_utf8_business_fax_number_size) if (maximum_entry_value_string_size == 0) return ; entry_value_string = (char *)malloc(sizeof(char*) * maximum_entry_value_string_size); if (entry_value_string == NULL) return ; value_string_to_attribute(libpff_address_get_utf8_file_under, "File under") value_string_to_attribute(libpff_contact_get_utf8_given_name, "Given name") value_string_to_attribute(libpff_contact_get_utf8_initials, "Initials") value_string_to_attribute(libpff_contact_get_utf8_surname, "Surname") value_string_to_attribute(libpff_contact_get_utf8_generational_abbreviation, "Generational abbreviation") value_string_to_attribute(libpff_contact_get_utf8_title, "Title") value_string_to_attribute(libpff_contact_get_utf8_callback_phone_number, "Callback phone number") value_string_to_attribute(libpff_contact_get_utf8_primary_phone_number, "Primary phone number") value_string_to_attribute(libpff_contact_get_utf8_home_phone_number, "Home phone number") value_string_to_attribute(libpff_contact_get_utf8_mobile_phone_number, "Mobile phone number") value_string_to_attribute(libpff_contact_get_utf8_company_name, "Company name") value_string_to_attribute(libpff_contact_get_utf8_job_title, "Job title") value_string_to_attribute(libpff_contact_get_utf8_office_location, "Office location") value_string_to_attribute(libpff_contact_get_utf8_department_name, "Department name") value_string_to_attribute(libpff_contact_get_utf8_postal_address, "Postal address") value_string_to_attribute(libpff_contact_get_utf8_country, "Country") value_string_to_attribute(libpff_contact_get_utf8_locality, "Locality") value_string_to_attribute(libpff_contact_get_utf8_business_phone_number_1, "Primary business phone number") value_string_to_attribute(libpff_contact_get_utf8_business_phone_number_2, "Secondary business phone nubmer") value_string_to_attribute(libpff_contact_get_utf8_business_fax_number, "Business fax number") free(entry_value_string); entry_value_string = NULL; } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_data.cpp000066400000000000000000000025251217176075400242470ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeData::PffNodeData(std::string name, Node* parent, pff* fsobj) : Node(name, 0, parent, fsobj) { this->__itemInfo = NULL; this->setFile(); } PffNodeData::PffNodeData(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : Node(name, 0, parent, fsobj) { this->__itemInfo = new ItemInfo(itemInfo); this->setFile(); } PffNodeData::~PffNodeData() { delete this->__itemInfo; } pff* PffNodeData::__pff(void) { return (static_cast(this->fsobj())); } fdinfo* PffNodeData::vopen(void) { return (NULL); } int32_t PffNodeData::vread(fdinfo* fi, void *buff, unsigned int size) { return (0); } int32_t PffNodeData::vclose(fdinfo* fi) { return (-1); } uint64_t PffNodeData::vseek(fdinfo* fd, uint64_t offset, int whence) { return (0); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_email.cpp000066400000000000000000000042301217176075400244200ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeEMail::PffNodeEMail(std::string name, Node* parent, pff* fsobj) : PffNodeData(name, parent, fsobj) { } PffNodeEMail::PffNodeEMail(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeData(name, parent, fsobj, itemInfo) { } std::string PffNodeEMail::icon(void) { return (":mail_generic"); } uint8_t* PffNodeEMail::dataBuffer(void) { return (NULL); } fdinfo* PffNodeEMail::vopen(void) { fdinfo* fi; uint8_t* buff; fi = new fdinfo; if ((buff = this->dataBuffer()) == NULL) return (NULL); fi->id = new Variant((void*)buff); fi->node = this; fi->offset = 0; return (fi); } int32_t PffNodeEMail::vread(fdinfo* fi, void *buff, unsigned int size) { uint8_t* rbuff; rbuff = (uint8_t*)fi->id->value(); if (fi->offset > this->size()) { return (0); } if ((fi)->offset + size > this->size()) size = this->size() - fi->offset; memcpy(buff, rbuff + (uint32_t)fi->offset, size); fi->offset += size; return (size); } uint64_t PffNodeEMail::vseek(fdinfo* fi, uint64_t offset, int whence) { if (whence == 0) { if (offset <= this->size()) { fi->offset = offset; return (fi->offset); } } else if (whence == 1) { if (fi->offset + offset <= this->size()) { fi->offset += offset; return (fi->offset); } } else if (whence == 2) { fi->offset = this->size(); return (fi->offset); } return ((uint64_t) -1); } int32_t PffNodeEMail::vclose(fdinfo *fi) { uint8_t* rbuff; rbuff = (uint8_t*)fi->id->value(); delete rbuff; return (0); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_email_attributes.cpp000066400000000000000000000415101217176075400266700ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" libpff_macro32_s LIBPFF_MESSAGE_FLAG[9] = { { LIBPFF_MESSAGE_FLAG_UNMODIFIED, "Unmodified" }, { LIBPFF_MESSAGE_FLAG_SUBMIT, "Submit" }, { LIBPFF_MESSAGE_FLAG_UNSENT, "Unsent" }, { LIBPFF_MESSAGE_FLAG_HAS_ATTACHMENTS, "Has attachments" }, { LIBPFF_MESSAGE_FLAG_FROM_ME, "From me" }, { LIBPFF_MESSAGE_FLAG_ASSOCIATED, "Associated" }, { LIBPFF_MESSAGE_FLAG_RESEND, "Resend" }, { LIBPFF_MESSAGE_FLAG_RN_PENDING, "RN pending" }, { LIBPFF_MESSAGE_FLAG_NRN_PENDING, "NRN pending" } }; libpff_macro32_s LIBPFF_RECIPIENT_TYPE[4] = { { LIBPFF_RECIPIENT_TYPE_ORIGINATOR, "Originator"}, { LIBPFF_RECIPIENT_TYPE_TO, "To"}, { LIBPFF_RECIPIENT_TYPE_CC, "CC"}, { LIBPFF_RECIPIENT_TYPE_BCC, "BCC"} }; libpff_macro32_s LIBPFF_MESSAGE_IMPORTANCE_TYPE[3] = { { LIBPFF_MESSAGE_IMPORTANCE_TYPE_LOW, "Low"}, { LIBPFF_MESSAGE_IMPORTANCE_TYPE_NORMAL, "Normal"}, { LIBPFF_MESSAGE_IMPORTANCE_TYPE_HIGH, "High"} }; libpff_macro32_s LIBPFF_MESSAGE_PRIORITY_TYPE[3] = { { LIBPFF_MESSAGE_PRIORITY_TYPE_NON_URGENT, "Non Urgent"}, { LIBPFF_MESSAGE_PRIORITY_TYPE_NORMAL, "Normal"}, { LIBPFF_MESSAGE_PRIORITY_TYPE_URGENT, "Urgent"} }; libpff_macro32_s LIBPFF_MESSAGE_SENSITIVITY_TYPE[4] = { { LIBPFF_MESSAGE_SENSITIVITY_TYPE_NONE, "None"}, { LIBPFF_MESSAGE_SENSITIVITY_TYPE_PERSONAL, "Personal"}, { LIBPFF_MESSAGE_SENSITIVITY_TYPE_PRIVATE, "Private"}, { LIBPFF_MESSAGE_SENSITIVITY_TYPE_CONFIDENTIAL, "Confidential"} }; Attributes PffNodeEMail::allAttributes(libpff_item_t* item) { Attributes attr; Attributes messageHeader; if (this->attributesMessageHeader(&messageHeader, item)) attr["Message headers"] = new Variant(messageHeader); Attributes recipients; if (this->attributesRecipients(&recipients, item)) attr["Recipients"] = new Variant(recipients); Attributes transportHeaders; if (this->attributesTransportHeaders(&transportHeaders, item)) attr["Transport headers"] = new Variant(transportHeaders); Attributes conversationIndex; if (this->attributesMessageConversationIndex(&conversationIndex, item)) attr["Conversation index"] = new Variant(conversationIndex); return (attr); } Attributes PffNodeEMail::_attributes() { Attributes attr; Item* item = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return attr; attr = this->allAttributes(item->pff_item()); delete item; return attr; } void PffNodeEMail::splitTextToAttributes(std::string text, Attributes* attr) { size_t splitter = 0; size_t next_splitter = 0; size_t eol = 0; size_t next_eol = 0; size_t line = 0; size_t buff_size = text.length(); std::string key; std::string value; while (splitter < buff_size && next_eol + 3 < buff_size && line != std::string::npos) { splitter = text.find(": ", splitter); if (splitter == std::string::npos) return ; eol = text.rfind("\n", splitter); if (eol == std::string::npos) { eol = 0; key = text.substr(eol, splitter - eol); } else key = text.substr(eol + 1, splitter - eol - 1); next_splitter = text.find(": ", splitter + 1); if (next_splitter == std::string::npos) next_splitter = buff_size; next_eol = text.rfind("\n", next_splitter); if (next_eol == buff_size - 1) next_eol -= 2; line = text.find("\n", splitter + 1); if (next_splitter < line) { next_splitter = text.find(": ", line); if (next_splitter == std::string::npos) next_splitter = buff_size; next_eol = text.rfind("\n", next_splitter); if (next_eol == std::string::npos) { next_eol = buff_size; } } value = text.substr(splitter + 2, next_eol - splitter - 3); if (value.length() > 256) (*attr)[key] = new Variant(std::string("Value too long")); else { (*attr)[key] = new Variant(value); } splitter = next_eol + 2; } } int PffNodeEMail::attributesTransportHeaders(Attributes* attr, libpff_item_t* item) { size_t message_transport_headers_size = 0; libpff_error_t* pff_error = NULL; uint8_t* entry_string = NULL; if (libpff_message_get_utf8_transport_headers_size(item, &message_transport_headers_size, &pff_error) != 1) { check_error(pff_error) return (0); } if (message_transport_headers_size <= 0) return (0); entry_string = new uint8_t [message_transport_headers_size]; if (libpff_message_get_utf8_transport_headers(item, entry_string, message_transport_headers_size, &pff_error) != 1 ) { check_error(pff_error) delete entry_string; return (0); } this->splitTextToAttributes(std::string((char *)entry_string), attr); delete entry_string; return (1); } int PffNodeEMail::attributesRecipients(Attributes* attr, libpff_item_t* item) { libpff_error_t* pff_error = NULL; libpff_item_t* recipients = NULL; uint8_t* entry_value_string = NULL; int number_of_recipients = 0; size_t entry_value_string_size = 0; size_t maximum_entry_value_string_size = 0; uint32_t entry_value_32bit = 0; int recipient_iterator = 0; if (libpff_message_get_recipients(item, &recipients, &pff_error) == 1) { if (libpff_item_get_number_of_sets(recipients, (uint32_t*) &number_of_recipients, &pff_error) != 1) { check_error(pff_error) if (libpff_item_free(&recipients, &pff_error) != 1) check_error(pff_error) return (0); } if (number_of_recipients > 0) { for (recipient_iterator = 0; recipient_iterator < number_of_recipients; recipient_iterator++) { if (libpff_item_get_entry_value_utf8_string_size(recipients, recipient_iterator, LIBPFF_ENTRY_TYPE_DISPLAY_NAME, &entry_value_string_size, 0, &pff_error) == 1) { if (entry_value_string_size > maximum_entry_value_string_size) { maximum_entry_value_string_size = entry_value_string_size; } } else check_error(pff_error) if (libpff_recipients_get_utf8_display_name_size(recipients, recipient_iterator, &entry_value_string_size, &pff_error) == 1) { if (entry_value_string_size > maximum_entry_value_string_size) maximum_entry_value_string_size = entry_value_string_size; } else check_error(pff_error) if (libpff_item_get_entry_value_utf8_string_size(recipients, recipient_iterator, LIBPFF_ENTRY_TYPE_ADDRESS_TYPE, &entry_value_string_size, 0, &pff_error) == 1) { if (entry_value_string_size > maximum_entry_value_string_size) maximum_entry_value_string_size = entry_value_string_size; } else check_error(pff_error) if (libpff_item_get_entry_value_utf8_string_size(recipients, recipient_iterator, LIBPFF_ENTRY_TYPE_EMAIL_ADDRESS, &entry_value_string_size, 0, &pff_error) == 1) { if (entry_value_string_size > maximum_entry_value_string_size) maximum_entry_value_string_size = entry_value_string_size; } else check_error(pff_error) if ((maximum_entry_value_string_size == 0)) continue ; Attributes attrRecipient; entry_value_string = (uint8_t*) new uint8_t[maximum_entry_value_string_size]; if (libpff_item_get_entry_value_utf8_string(recipients, recipient_iterator, LIBPFF_ENTRY_TYPE_DISPLAY_NAME, entry_value_string, maximum_entry_value_string_size, 0, &pff_error) == 1) attrRecipient["Display Name"] = new Variant(std::string((char *)entry_value_string)); else check_error(pff_error) if (libpff_recipients_get_utf8_display_name(recipients, recipient_iterator, entry_value_string, maximum_entry_value_string_size, &pff_error) == 1) attrRecipient["Recipient display name"] = new Variant(std::string((char*)entry_value_string)); else check_error(pff_error) if (libpff_item_get_entry_value_utf8_string(recipients, recipient_iterator, LIBPFF_ENTRY_TYPE_ADDRESS_TYPE, entry_value_string, maximum_entry_value_string_size, 0, &pff_error) == 1) attrRecipient["Address type"] = new Variant((char*) entry_value_string); else check_error(pff_error) if (libpff_item_get_entry_value_utf8_string(recipients, recipient_iterator, LIBPFF_ENTRY_TYPE_EMAIL_ADDRESS, entry_value_string, maximum_entry_value_string_size, 0, &pff_error) == 1) attrRecipient["Email address"] = new Variant((char*)entry_value_string); else check_error(pff_error) if (libpff_recipients_get_type(recipients, recipient_iterator, &entry_value_32bit, &pff_error) == 1) { for (uint32_t n = 0; n < 5; n++) { if (n == 5) { attrRecipient["Recipient type"] = new Variant(std::string("Unknown")); } if (entry_value_32bit == LIBPFF_RECIPIENT_TYPE[n].type) { attrRecipient["Recipient type"] = new Variant(std::string(LIBPFF_RECIPIENT_TYPE[n].message)); break; } } } else check_error(pff_error) std::ostringstream keyRecipient; keyRecipient << "Recipient " << recipient_iterator + 1; (*attr)[keyRecipient.str()] = new Variant(attrRecipient); delete entry_value_string; } } else { if (libpff_item_free(&recipients, &pff_error) != 1) check_error(pff_error) return (0); } } else { check_error(pff_error) return (0); } if (libpff_item_free(&recipients, &pff_error) != 1) check_error(pff_error) return (1); } int PffNodeEMail::attributesMessageConversationIndex(Attributes* attr, libpff_item_t* item) { libpff_error_t* pff_error = NULL; uint8_t* entry_value = NULL; uint32_t entry_value_index = 0; size_t entry_value_size = 0; uint64_t entry_value_64bit = 0; uint64_t current_time = 0; int list_iterator = 0; int result = 0; result = libpff_message_get_conversation_index_size(item, &entry_value_size, &pff_error); if (result == -1 || result == 0 || entry_value_size == 0) { check_error(pff_error) return (0); } entry_value = (uint8_t *)malloc(sizeof(uint8_t) * entry_value_size); if (entry_value == NULL) return (0); result = libpff_message_get_conversation_index(item, entry_value, entry_value_size, &pff_error); if ((result != 1) || (entry_value_size < 22) || (entry_value[0] != 0x01)) { if (result != 1) check_error(pff_error) free(entry_value); return (0); } Attributes headerBlock; std::ostringstream guid; entry_value_64bit = bytes_swap64(*((uint64_t*)(entry_value))); *((uint8_t*)&entry_value_64bit) = 0; *(((uint8_t*)&entry_value_64bit) + 1) = 0; current_time = entry_value_64bit; vtime* value_filetime = new vtime(entry_value_64bit, TIME_MS_64); Variant* variant_filetime = new Variant(value_filetime); headerBlock["File time"] = variant_filetime; entry_value_64bit = bytes_swap64(*((uint64_t*) (entry_value + 6))); guid << std::hex << entry_value_64bit; entry_value_64bit = bytes_swap64(*((uint64_t*) (entry_value + 14))); guid << entry_value_64bit; headerBlock["GUID"] = new Variant(guid.str()); (*attr)["Header block"] = new Variant(headerBlock); list_iterator = 1; for (entry_value_index = 22; entry_value_index < entry_value_size; entry_value_index += 5) { Attributes childBlock; std::ostringstream childBlockId; entry_value_64bit = 0; entry_value_64bit = *((uint32_t*) (entry_value + entry_value_index)); entry_value_64bit &= 0x07fffffffUL; if ((*(entry_value + entry_value_index) & 0x80) == 0) entry_value_64bit <<= 18; else entry_value_64bit <<= 23; current_time += entry_value_64bit; childBlock["File time"] = new Variant(new vtime(current_time, TIME_MS_64)); childBlock["Random number"] = new Variant((*(entry_value + entry_value_index + 4) & 0xf0) >> 4); childBlock["Sequence count"] = new Variant(*(entry_value + entry_value_index + 4) & 0x0f); childBlockId << "Child block " << list_iterator; (*attr)[childBlockId.str()] = new Variant(childBlock); list_iterator++; } free(entry_value); return (1); } int PffNodeEMail::attributesMessageHeader(Attributes* attr, libpff_item_t* item) { std::ostringstream flags; libpff_error_t* pff_error = NULL; char* entry_value_string = NULL; size_t entry_value_string_size = 0; size_t maximum_entry_value_string_size = 0; uint64_t entry_value_64bit = 0; uint32_t entry_value_32bit = 0; uint8_t entry_value_boolean = 0; int result = 0; maximum_entry_value_string_size = 24; check_maximum_size(libpff_item_get_utf8_display_name_size) check_maximum_size(libpff_message_get_utf8_conversation_topic_size) check_maximum_size(libpff_message_get_utf8_subject_size) check_maximum_size(libpff_message_get_utf8_sender_name_size) check_maximum_size(libpff_message_get_utf8_sender_email_address_size) if (!(maximum_entry_value_string_size)) return (0); entry_value_string = (char *) new char[maximum_entry_value_string_size]; value_time_to_attribute(libpff_message_get_client_submit_time, "Client submit time") value_time_to_attribute(libpff_message_get_delivery_time, "Delivery time") value_time_to_attribute(libpff_message_get_creation_time, "Creation time") value_time_to_attribute(libpff_message_get_modification_time, "Modification time") value_uint32_to_attribute(libpff_message_get_size, "Message size") if (libpff_message_get_flags(item, &entry_value_32bit, &pff_error) == 1) { if ((entry_value_32bit & LIBPFF_MESSAGE_FLAG_READ) == LIBPFF_MESSAGE_FLAG_READ) (*attr)["Is readed"] = new Variant(std::string("Yes")); else (*attr)["Is readed"] = new Variant(std::string("No")); for (uint32_t n = 0; n < 9; n ++) { if ((entry_value_32bit & LIBPFF_MESSAGE_FLAG[n].type) == LIBPFF_MESSAGE_FLAG[n].type) { if (flags.str().size()) flags << ", "; flags << LIBPFF_MESSAGE_FLAG[n].message; } } if (flags.str().size()) (*attr)["Flags"] = new Variant(flags.str()); } else check_error(pff_error) value_string_to_attribute(libpff_item_get_utf8_display_name, "Display name") value_string_to_attribute(libpff_message_get_utf8_conversation_topic, "Conversation topic") value_string_to_attribute(libpff_message_get_utf8_subject, "Subject") value_string_to_attribute(libpff_message_get_utf8_sender_name, "Sender name") value_string_to_attribute(libpff_message_get_utf8_sender_email_address, "Sender email address") if (libpff_message_get_importance(item, &entry_value_32bit, &pff_error) == 1) { for (uint32_t n = 0; n < 3; n++) if (entry_value_32bit == LIBPFF_MESSAGE_IMPORTANCE_TYPE[n].type) { (*attr)["Importance"] = new Variant(std::string(LIBPFF_MESSAGE_IMPORTANCE_TYPE[n].message)); break; } } else check_error(pff_error) if (libpff_message_get_priority(item, &entry_value_32bit, &pff_error) == 1) { for (uint32_t n = 0; n < 3; n++) if (entry_value_32bit == LIBPFF_MESSAGE_PRIORITY_TYPE[n].type) { (*attr)["Priority"] = new Variant(std::string(LIBPFF_MESSAGE_PRIORITY_TYPE[n].message)); break; } } else check_error(pff_error) if (libpff_message_get_sensitivity(item, &entry_value_32bit, &pff_error) == 1) { for (uint32_t n = 0; n < 4; n++) if (entry_value_32bit == LIBPFF_MESSAGE_SENSITIVITY_TYPE[n].type) { (*attr)["Sensitivity"] = new Variant(std::string(LIBPFF_MESSAGE_SENSITIVITY_TYPE[n].message)); break; } } else check_error(pff_error) if (libpff_message_get_is_reminder(item, &entry_value_boolean, &pff_error) == 1) { if (!(entry_value_boolean)) (*attr)["Is a reminder"] = new Variant(std::string("no")); else (*attr)["Is a reminder"] = new Variant(std::string("yes")); } else check_error(pff_error) value_time_to_attribute(libpff_message_get_reminder_time, "Reminder time") value_time_to_attribute(libpff_message_get_reminder_signal_time, "Reminder signal time") if (libpff_message_get_is_private(item, &entry_value_boolean, &pff_error) == 1) { if (!(entry_value_boolean)) (*attr)["Is private"] = new Variant(std::string("no")); else (*attr)["Is private"] = new Variant(std::string("yes")); } else check_error(pff_error) delete entry_value_string; return (1); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_email_message.cpp000066400000000000000000000107141217176075400261300ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeEmailMessageText::PffNodeEmailMessageText(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEMail(name, parent, fsobj, itemInfo) { size_t headers_size = 0; Item* item = NULL; libpff_error_t* pff_error = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return ; if (libpff_message_get_plain_text_body_size(item->pff_item(), &headers_size, &pff_error) == 1) { if (headers_size > 0) this->setSize(headers_size); } else check_error(pff_error); delete item; } uint8_t* PffNodeEmailMessageText::dataBuffer(void) { uint8_t* entry_string = NULL; Item* item = NULL; libpff_error_t* pff_error = NULL; if (this->size() <= 0) return (NULL); if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return (NULL); entry_string = new uint8_t [this->size()]; if (libpff_message_get_plain_text_body(item->pff_item(), entry_string, this->size(), &pff_error) != 1) { check_error(pff_error) delete item; delete entry_string; return (NULL); } delete item; return (entry_string); } PffNodeEmailMessageHTML::PffNodeEmailMessageHTML(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEMail(name, parent, fsobj, itemInfo) { size_t headers_size = 0; Item* item = NULL; libpff_error_t* pff_error = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return ; if (libpff_message_get_html_body_size(item->pff_item(), &headers_size, &pff_error) == 1) { if (headers_size > 0) this->setSize(headers_size); } else check_error(pff_error) delete item; } uint8_t* PffNodeEmailMessageHTML::dataBuffer(void) { uint8_t* entry_string = NULL; Item* item = NULL; libpff_error_t* pff_error = NULL; if (this->size() <= 0) return (NULL); if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return (NULL); entry_string = new uint8_t [this->size()]; if (libpff_message_get_html_body(item->pff_item(), entry_string, this->size(), &pff_error ) != 1) { check_error(pff_error) delete item; delete entry_string; return (NULL); } delete item; return (entry_string); } PffNodeEmailMessageRTF::PffNodeEmailMessageRTF(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEMail(name, parent, fsobj, itemInfo) { size_t headers_size = 0; Item* item = NULL; libpff_error_t* pff_error = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return ; if (libpff_message_get_rtf_body_size(item->pff_item(), &headers_size, &pff_error) == 1) { if (headers_size > 0) this->setSize(headers_size); } else check_error(pff_error) delete item; } uint8_t* PffNodeEmailMessageRTF::dataBuffer(void) { uint8_t* entry_string = NULL; Item* item = NULL; libpff_error_t* pff_error = NULL; if (this->size() <= 0) return (NULL); if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return (NULL); entry_string = new uint8_t [this->size()]; if (libpff_message_get_rtf_body(item->pff_item(), entry_string, this->size(), &pff_error) != 1) { check_error(pff_error) delete item; delete entry_string; return (NULL); } delete item; return (entry_string); } PffNodeNote::PffNodeNote(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEmailMessageText(name, parent, fsobj, itemInfo) { } std::string PffNodeNote::icon() { return (":notes"); } PffNodeMeeting::PffNodeMeeting(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEmailMessageText(name, parent, fsobj, itemInfo) { } std::string PffNodeMeeting::icon() { return (":meeting"); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_email_transport_headers.cpp000066400000000000000000000034151217176075400302330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeEmailTransportHeaders::PffNodeEmailTransportHeaders(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEMail(name, parent, fsobj, itemInfo) { size_t headers_size = 0; Item* item = NULL; libpff_error_t* pff_error = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return ; if (libpff_message_get_utf8_transport_headers_size(item->pff_item(), &headers_size, &pff_error) == 1) { if (headers_size > 0) this->setSize(headers_size); } else check_error(pff_error) delete item; } uint8_t* PffNodeEmailTransportHeaders::dataBuffer(void) { uint8_t* entry_string = NULL; Item* item = NULL; libpff_error_t* pff_error = NULL; if (this->size() <= 0) return (NULL); if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return (NULL); entry_string = new uint8_t [this->size()]; if (libpff_message_get_utf8_transport_headers(item->pff_item(), entry_string, this->size(), &pff_error ) != 1) { check_error(pff_error) delete item; delete entry_string; return (NULL); } delete item; return (entry_string); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_folder.cpp000066400000000000000000000030531217176075400246060ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeFolder::PffNodeFolder(std::string name, Node* parent, pff* nfsobj) : Node(name, 0, parent, nfsobj) { this->setDir(); } PffNodeFolder::~PffNodeFolder() { } std::string PffNodeFolder::icon() { if (this->name().find("Mailbox") != std::string::npos) return (":mailbox"); if (this->name().find("Tasks") != std::string::npos) return (":tasks"); if (this->name().find("Notes") != std::string::npos) return (":notes"); if (this->name().find("Calendar") != std::string::npos) return (":appointment"); if (this->name().find("Contacts") != std::string::npos) return (":contact"); if (this->name().find("Sent") != std::string::npos) return (":folder_sent_mail"); if (this->name().find("Outbox") != std::string::npos) return (":folder_outbox"); if (this->name().find("Deleted") != std::string::npos) return (":mail_delete"); if (this->name().find("Inbox") != std::string::npos) return (":folder_inbox"); return (":folder_128.png"); } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_task.cpp000066400000000000000000000050621217176075400242770ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeTask::PffNodeTask(std::string name, Node* parent, pff* fsobj, ItemInfo* itemInfo) : PffNodeEmailMessageText(name, parent, fsobj, itemInfo) { } std::string PffNodeTask::icon(void) { return (":tasks"); } Attributes PffNodeTask::_attributes(void) { Attributes attr; Item* item = NULL; if ((item = this->__itemInfo->item(this->__pff()->pff_file())) == NULL) return (attr); attr = this->allAttributes(item->pff_item()); Attributes task; this->attributesTask(&task, item->pff_item()); attr[std::string("Task")] = new Variant(task); delete item; return (attr); } void PffNodeTask::attributesTask(Attributes* attr, libpff_item_t* item) { libpff_error_t* pff_error = NULL; uint64_t entry_value_64bit = 0; uint32_t entry_value_32bit = 0; uint8_t entry_value_boolean = 0; double entry_value_floating_point = 0.0; int result = 0; value_time_to_attribute(libpff_task_start_date, "Start date") value_time_to_attribute(libpff_task_due_date, "Due date") value_uint32_to_attribute(libpff_task_get_status, "Status") result = libpff_task_get_percentage_complete(item, &entry_value_floating_point, &pff_error); if (result != -1 && result != 0) { std::ostringstream sfloat; sfloat << entry_value_floating_point; (*attr)["Percentage complete"] = new Variant(sfloat.str()); } else check_error(pff_error) value_uint32_to_attribute(libpff_task_get_actual_effort, "Actual effort") value_uint32_to_attribute(libpff_task_get_total_effort, "Total effort") result = libpff_task_get_is_complete(item, &entry_value_boolean, &pff_error); if (result != -1 && result != 0) { if (entry_value_boolean) (*attr)["Is complete"] = new Variant(std::string("Yes")); else (*attr)["Is complete"] = new Variant(std::string("No")); } else check_error(pff_error) value_uint32_to_attribute(libpff_task_get_version, "Version") } dff-1.3.0+dfsg.1/dff/modules/mailbox/exchange/pff_node_unallocated_blocks.cpp000066400000000000000000000055621217176075400271720ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http: *www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "pff.hpp" PffNodeUnallocatedBlocks::PffNodeUnallocatedBlocks(std::string name, Node *parent, pff* fsobj, Node* root, int block_type) : Node(name, 0, parent, fsobj) { libpff_error_t* pff_error = NULL; off64_t offset = 0; size64_t size = 0; int number_of_unallocated_blocks = 0; int block_iterator = 0; uint64_t node_size = 0; this->root = root; this->block_type = block_type; if (libpff_file_get_number_of_unallocated_blocks(this->__pff()->pff_file(), this->block_type, &number_of_unallocated_blocks, &pff_error) != 1) { check_error(pff_error) return ; } if (block_type == LIBPFF_UNALLOCATED_BLOCK_TYPE_PAGE) fsobj->res["Number of unallocated page blocks"] = new Variant(number_of_unallocated_blocks); else fsobj->res["Number of unallocated data blocks"] = new Variant(number_of_unallocated_blocks); if (number_of_unallocated_blocks > 0) { for (block_iterator = 0; block_iterator < number_of_unallocated_blocks; block_iterator++) { if (libpff_file_get_unallocated_block(this->__pff()->pff_file(), this->block_type, block_iterator, &offset, &size, &pff_error) == 1) { node_size += size; } else check_error(pff_error) } } this->setSize(node_size); } void PffNodeUnallocatedBlocks::fileMapping(FileMapping* fm) { libpff_error_t* pff_error = NULL; off64_t offset = 0; size64_t size = 0; int number_of_unallocated_blocks = 0; int block_iterator = 0; uint64_t voffset = 0; libpff_file_t* pff_file = this->__pff()->pff_file(); if (libpff_file_get_number_of_unallocated_blocks(pff_file, this->block_type, &number_of_unallocated_blocks, &pff_error) != 1) { check_error(pff_error) return ; } if (number_of_unallocated_blocks > 0) { for (block_iterator = 0; block_iterator < number_of_unallocated_blocks; block_iterator++) { if (libpff_file_get_unallocated_block(pff_file, this->block_type, block_iterator, &offset, &size, &pff_error) == 1) { fm->push(voffset, size, this->root, offset); voffset += size; } else check_error(pff_error) } } return ; } pff* PffNodeUnallocatedBlocks::__pff() { return (static_cast(this->fsobj())); } dff-1.3.0+dfsg.1/dff/modules/metadata/000077500000000000000000000000001217176075400173315ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/metadata/CMakeLists.txt000066400000000000000000000013141217176075400220700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py structparser.py ) add_subdirectory (metaexif) add_subdirectory (prefetch) add_subdirectory (lnk) add_subdirectory (compoundfile) dff-1.3.0+dfsg.1/dff/modules/metadata/__init__.py000066400000000000000000000011241217176075400214400ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ['metaexif', 'structparser', 'lnk'] dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/000077500000000000000000000000001217176075400220155ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/CMakeLists.txt000066400000000000000000000012621217176075400245560ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py compound.py mscfb.py msdoc.py msdocheader.py msodraw.py msoleps.py msoshared.py msppt.py ) dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/__init__.py000066400000000000000000000000001217176075400241140ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/compound.py000066400000000000000000000145071217176075400242220ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __dff_module_prefetch_version__ = "1.0.0" import datetime, sys, traceback from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.module.manager import ModuleProcessusHandler from dff.api.vfs.libvfs import AttributesHandler, VFS, mfso from dff.api.types.libtypes import Argument, typeId, VMap, Variant from mscfb import CompoundDocumentHeader from msoleps import PropertySetStream from msdoc import WordDocument from msoshared import OfficeDocumentSectionCLSID from msppt import PPT def error(): err_type, err_value, err_traceback = sys.exc_info() for n in traceback.format_exception_only(err_type, err_value): print n for n in traceback.format_tb(err_traceback): print n class CompoundDocumentParser(object): def __init__(self, node, largs, mfsobj = None): self.node = node self.attr = {} self.extraAttr = [] try : self.cdh = CompoundDocumentHeader(node, mfsobj) self.cdh.parseDocument(not 'no-extraction' in largs) except : #error() raise Exception("Can't parse document") streams = self.cdh.streams() for stream in streams: if stream.objectType == "StreamObject": try: if stream.objectName == "WordDocument": if not 'no-extraction' in largs: wd = WordDocument(stream) if not 'no-text' in largs: wd.createTextNodes() if not 'no-pictures' in largs: wd.createPictureNodes() elif stream.objectName == "Pictures": if not ('no-pictures' in largs or 'no-extraction' in largs): ppt = PPT(stream) ppt.createPictureNodes() else: propertySet = PropertySetStream(stream, OfficeDocumentSectionCLSID.keys()) for clsid in OfficeDocumentSectionCLSID.iterkeys(): section = propertySet.sectionCLSID(clsid) if section: (sectionName, sectionIDS) = OfficeDocumentSectionCLSID[clsid] mattr = VMap() for k, v in sectionIDS.iteritems(): Property = section.PropertyList.propertyID(k) if Property and Property.Variant.Value: p = section.PropertyList.propertyID(k).Variant.Value if p and isinstance(p, Variant): #Thumbnail is type node if v == 'Total editing time': #special case see msoshared.py p = Variant(str(datetime.timedelta(seconds=(p.value()/10000000)))) else: p = Variant(p) mattr[v] = p stream.setExtraAttributes((sectionName, mattr,)) if not 'no-root_metadata' in largs: self.extraAttr.append((sectionName, stream.parent().name(), mattr,)) #except RuntimeError, e: #pass except : #error() pass if not 'no-extraction' in largs: del stream def _attributes(self): vmap = VMap() vmap["Compound document"] = self.cdh._attributes() for (name, parent, attr) in self.extraAttr: vmap[name + ' (' + parent + ')'] = attr return vmap class MetaCompoundHandler(AttributesHandler, ModuleProcessusHandler): def __init__(self): AttributesHandler.__init__(self, "metacompound") ModuleProcessusHandler.__init__(self, "metacompound") self.__disown__() self.nodeAttributes = {} self.vfs = VFS.Get() def setAttributes(self, node, classAttributes): self.nodeAttributes[long(node.this)] = classAttributes def update(self, processus): pass def nodes(self, root): nodes = [] rootAbsolute = root.absolute() for node in self.nodeAttributes.keys(): node = self.vfs.getNodeFromPointer(node) if node.absolute().find(rootAbsolute) == 0: nodes.append(node) return nodes def attributes(self, node): try: classAttributes = self.nodeAttributes[long(node.this)] return classAttributes._attributes() except KeyError: attr = VMap() attr.thisown = False return attr class MetaCompound(mfso): def __init__(self): mfso.__init__(self, 'metacompound') self.__disown__() self.handler = MetaCompoundHandler() def start(self, args): try: largs = [] node = args['file'].value() for arg in ['no-extraction', 'no-text', 'no-pictures', 'no-root_metadata']: try: value = args[arg].value() if value: largs.append(arg) except IndexError: pass self.stateinfo = "Registering node: " + str(node.name()) p = CompoundDocumentParser(node, largs, self) self.handler.setAttributes(node, p) node.registerAttributes(self.handler) self.stateinfo = "" except (KeyError, Exception): self.stateinfo = "Error" class compound(Module): """This modules extract metadata and content of compound files (doc,xls,msi, ....).;""" def __init__(self): Module.__init__(self, "compound", MetaCompound) self.conf.addArgument({"name": "file", "description": "file to extract metadata", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "compatible extension", "values": ["Composite Document File V2"]}) self.conf.addArgument({"name": "no-extraction", "description" : "Don't create nodes for files stored inside compound document", "input": Argument.Empty}) self.conf.addArgument({"name": "no-text", "description" : "Don't extract text from word document", "input": Argument.Empty}) self.conf.addArgument({"name": "no-pictures", "description" : "Don't extract pictures from word and powerpoint document", "input": Argument.Empty}) self.conf.addArgument({"name" : "no-root_metadata", "description" : "Don't apply metadata on the root document", "input": Argument.Empty}) #self.flags = ["single"] self.tags = "Metadata" self.icon = ":document.png" dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/mscfb.py000066400000000000000000000336621217176075400234730ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from struct import unpack from dff.api.vfs.libvfs import Node from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime, TIME_MS_64 from dff.modules.structparser import Struct, Header, ResolveAttributesMap, AttributesVMap from dff.modules.lnk.lnkitem import UUID OLEHeader = ({ "info" : { "os":"None", "arch":"None", "name":"OLE2"}, "descr" : { "CompoundDocumentHeader" : ((512), { "OleSignature" : (8, 0), "CLSID" : (16, 8), "MinorVersion" : (2, 24), "MajorVersion" : (2, 26), "ByteOrder" : (2, 28), "SectorShift" : (2, 30), "MiniSectorShift" : (2, 32), "Reserved1" : (6, 34), "NumberOfDirSect": (4, 40), "NumberOfFatSect": (4, 44), "FirstDirSectLocation" : (4, 48), "TransactionSignNumber" : (4, 52), "MiniStreamCutoffSize" : (4, 56), "FirstMiniFatSectLocation" : (4, 60), "NumberOfMiniFatSectors" : (4, 64), "FirstDIFATSectLocation" : (4, 68), "NumberOfDIFATSector" : (4, 72), }), "DirectoryEntry" : ((128), { "objectName" : (64, 0), "nameLen" : (2, 64), "objectType" : (1, 66), "colorFlag" : (1, 67), "leftSiblingID" : (4, 68), "rightSiblingID" : (4, 72), "childID" : (4, 76), "CLSID" : (16, 80), "stateBits" : (4, 96), "creationTime" : (8, 100), "modifiedTime" : (8, 108), "startingSectorLocation" : (4, 116), "streamSize" : (8, 120), }), } }) class DIFAT(object): def __init__(self, node, numberOfSector, firstSectLocation, sectorSize): self.numberSector = numberOfSector self.firstSectLocation = firstSectLocation self.sectorSize = sectorSize self.node = node vfile = self.node.open() try : vfile.seek(76) self.table = vfile.read(436) sector = self.firstSectLocation while sector < 0xFFFFFFFA: vfile.seek(512 + (sector * self.sectorSize)) self.table += vfile.read(self.sectorSize) sector = self.readSector(sector) except : vfile.close() raise vfile.close() def readSector(self, fatsector): vfile = self.node.open() try : currentfattableid = fatsector / (self.sectorSize / 4) currentfatsector = unpack('I', self.table[currentfattableid*4:(currentfattableid*4)+4])[0] vfile.seek(512 + (currentfatsector * self.sectorSize)) fattable = unpack((self.sectorSize/4)*'I', vfile.read(self.sectorSize)) except : error() vfile.close() raise vfile.close() return fattable[fatsector - ((self.sectorSize/4)* currentfattableid)] class FAT(object): def __init__(self, node, difat, numberOfSector, sectorSize): self.difat = difat self.node = node self.numberOfSector = numberOfSector self.sectorSize = sectorSize vfile = self.node.open() try: self.table = "" for index in range(0, self.numberOfSector): sector = unpack('I', self.difat.table[index*4:(index*4)+4])[0] vfile.seek(512 + (sector * self.sectorSize)) data = vfile.read(self.sectorSize) self.table += data except : pass #Sometime file try to read at an invalid sector vfile.close() def readSector(self, sector): parsedIndex = set() data = "" vfile = self.node.open() try: while (sector < 0xFFFFFFFA) and (sector not in parsedIndex): parsedIndex.add(sector) vfile.seek(512 + ((sector) * self.sectorSize)) data += vfile.read(self.sectorSize) sector = unpack('I', self.table[sector*4:(sector*4)+4])[0] except : vfile.close() raise vfile.close() return data def offsetsSector(self, sector): parsedIndex = set() offsets = [] while (sector < 0xFFFFFFFA) and (sector not in parsedIndex): parsedIndex.add(sector) pos = 512 + ((sector) * self.sectorSize) off = (pos, self.sectorSize, self.node) offsets.append(off) sector = unpack('I', self.table[sector*4:(sector*4)+4])[0] return offsets class MiniFAT(object): def __init__(self, fat, firstSector, numberOfSector, cutoffSize, sectorSize): self.fat = fat self.numberOfSector = numberOfSector self.sectorSize = sectorSize self.cutoffSize = cutoffSize self.table = self.fat.readSector(firstSector) self.node = None def setRootStorageObject(self, root): self.node = root def offsetsRoot(self, dataSector): return self.fat.offsetsSector(dataSector) def offsetsSector(self, index): parsedIndex = set() offsets = [] while (index < 0xFFFFFFFA) and (index not in parsedIndex): parsedIndex.add(index) offsets.append(((index * 64), 64, self.node)) index = unpack('I', self.table[index*4:(index*4)+4])[0] return offsets class CompoundDocumentHeader(Struct): CompoundDocumentAttributesMap = { "Minor version" : ("MinorVersion" ,int), "Major version" : ("MajorVersion" ,int), "Byte order" : ("ByteOrder" ,int), "Sector shift" : ("SectorShift" ,int), "MiniSectorShift" : ("MiniSectorShift" ,int), "Number of directory sector" : ("NumberOfDirSect" ,int), "Number of FAT sector" : ("NumberOfFatSect" ,int), "First directory sector location" : ("FirstDirSectLocation" ,int), "Mini stream cutoff size" : ("MiniStreamCutoffSize" ,int), "First mini fat sector location" : ("FirstMiniFatSectLocation" ,int), "Number of mini fat sectors" : ("NumberOfMiniFatSectors" ,int), "First DIFAT sector location" : ("FirstDIFATSectLocation" ,int), "Number of DIFAT sector" : ("NumberOfDIFATSector", int), } OLEHeaderSignature = unpack('Q', "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1")[0] def __init__(self, node, mfsobj): self.header = Header(OLEHeader) self.node = node self.mfsobj = mfsobj self.vfile = node.open() try : self.vfile.seek(0) data = self.vfile.read(self.header.CompoundDocumentHeader.ssize) except : self.vfile.close() raise self.vfile.close() Struct.__init__(self, self.header, None, self.header.CompoundDocumentHeader, data) if self.OLEHeaderSignature != self.OleSignature: raise Exception('OLE Header is not valid.') if self.SectorShift == 0x9: self.SectorSize = 512 elif self.SectorShift == 0xc: self.SectorSize = 4096 self.CLSID = UUID(self.CLSID) self.entries = [] def parseDocument(self, register): difat = DIFAT(self.node, self.NumberOfDIFATSector, self.FirstDIFATSectLocation, self.SectorSize) fat = FAT(self.node, difat, self.NumberOfFatSect, self.SectorSize) minifat = MiniFAT(fat, self.FirstMiniFatSectLocation, self.NumberOfMiniFatSectors, self.MiniStreamCutoffSize, self.SectorSize) self.entries = DirectoryEntries(fat, minifat, self.FirstDirSectLocation, self.header, self.node, self.mfsobj, register) def streams(self): return self.entries.entries() def _attributes(self): try: return AttributesVMap(ResolveAttributesMap(self, self.CompoundDocumentAttributesMap)) except: pass import datetime, sys, traceback def error(): err_type, err_value, err_traceback = sys.exc_info() for n in traceback.format_exception_only(err_type, err_value): print n for n in traceback.format_tb(err_traceback): print n class DirectoryEntries(object): def __init__(self, fat, minifat, sectorLocation, header, parent, mfsobj, register = True): data = fat.readSector(sectorLocation) self.__entries = [] self.__addedEntriesID = [] size = 0 root = None node = parent while size < len(data): try: entry = DirectoryEntry(header, data[size:size+128], fat, minifat, node, mfsobj) size += 128 if len(entry.objectName) == 0 or entry.objectType == 'TypeUnknown': continue if entry.objectType == 'RootStorageObject' and root == None: root = entry self.__entries.append(entry) elif entry.objectType != 'RootStorageObject': self.__entries.append(entry) except : self.__entries.append(None) size += 128 error() if root: self.parseChild(root) self.__addedEntriesID.append(0) orphaned = self.parseOrphan(root, mfsobj) if register and root: mfsobj.registerTree(parent, root) elif register and orphaned: mfsobj.registerTree(parent, orphaned) def addChild(self, root, entry, entryID): if entryID not in self.__addedEntriesID: root.addChild(entry) self.__addedEntriesID.append(entryID) def parseOrphan(self, root, mfsobj): orphaned = None if len(self.__entries) != len(self.__addedEntriesID): orphaned = Node('Orphaned', 0, root, mfsobj) orphaned.__disown__() for eid in xrange(0, len(self.__entries)): if eid not in self.__addedEntriesID: try: if self.__entries[eid]: orphaned.addChild(self.__entries[eid]) except KeyError: pass return orphaned def parseChild(self, root): if root.childID != 0xffffffff: try: entry = self.__entries[root.childID] self.addChild(root, entry, root.childID) self.parseLeft(root, entry) self.parseRight(root, entry) self.parseChild(entry) except KeyError: pass def parseLeft(self, root, entry): if entry.leftSiblingID != 0xffffffff: try: leftSibling = self.__entries[entry.leftSiblingID] self.addChild(root, leftSibling, entry.leftSiblingID) self.parseLeft(root, leftSibling) self.parseRight(root, leftSibling) if leftSibling.childID != 0xffffffff: self.parseChild(leftSibling) except KeyError: pass def parseRight(self, root, entry): if entry.rightSiblingID != 0xffffffff: try: rightSibling = self.__entries[entry.rightSiblingID] self.addChild(root, rightSibling, entry.rightSiblingID) self.parseRight(root, rightSibling) self.parseLeft(root, rightSibling) if rightSibling.childID != 0xffffffff: self.parseChild(rightSibling) except KeyError: pass def entries(self): return self.__entries #invalidNameCounter = 0 class DirectoryEntry(Node, Struct): Type = { 0x0 : "TypeUnknown", 0x1 : "StorageObject", 0x2 : "StreamObject", 0x5 : "RootStorageObject" } AttributesMap = { "Object type" : ("objectType", str), "CLSID" : ("CLSID", str), "Creation time" : (("creationTime", TIME_MS_64), vtime), "Modified time" : (("modifiedTime", TIME_MS_64), vtime), "Starting sector" : ("startingSectorLocation", int), "Child ID" : ("childID", int), "Right Sibling ID" : ("rightSiblingID", int), "Left Sibling ID" : ("leftSiblingID", int), } def __init__(self, header, data, fat, minifat, parent, mfsobj): self.extraAttr = None Struct.__init__(self,header, None, header.DirectoryEntry, data) self.fat = fat self.minifat = minifat invalidNameCounter = 1 if self.objectName[1] == "\x00": #Some compound file like MSI as invalid name this is an ugly way to test self.objectName = unicode(self.objectName[:self.nameLen - 2], 'UTF-16').encode('UTF-8') else: #global invalidNameCounter #invalidNameCounter += 1 self.objectName = str("Unknown-" + str(invalidNameCounter)).encode('UTF-8') try: self.objectType = self.Type[ord(self.objectType)] except KeyError: self.objectType = self.Type[0x0] if len(self.objectName) == 0 or self.objectType == 'TypeUnknown': return self.CLSID = UUID(self.CLSID) if len(self.objectName) and mfsobj: realSize = self.offsetsSize() if self.streamSize > realSize: streamSize = realSize else: streamSize = self.streamSize if self.objectName[0] <= "\x05": self.objectName = self.objectName[1:] Node.__init__(self, self.objectName, streamSize, None, mfsobj) self.__disown__() if self.objectType == "RootStorageObject": self.minifat.setRootStorageObject(self) def offsets(self): offsets = None try: if self.objectType == "StreamObject" and self.streamSize >= self.minifat.cutoffSize: offsets = self.fat.offsetsSector(self.startingSectorLocation) elif self.objectType == "StreamObject" and self.streamSize < self.minifat.cutoffSize: offsets = self.minifat.offsetsSector(self.startingSectorLocation) elif self.objectType == "RootStorageObject": offsets = self.minifat.offsetsRoot(self.startingSectorLocation) except: pass #error() return offsets def offsetsSize(self): offsets = self.offsets() sizes = 0 if offsets: for offset, size, node in offsets: sizes += size return sizes def fileMapping(self, fm): offsets = self.offsets() if offsets: curoffset = 0 for offset, size, node in offsets: if curoffset + size > self.streamSize: size = self.streamSize - curoffset fm.push(curoffset, size, node, offset) curoffset += size if curoffset >= self.streamSize: break def setExtraAttributes(self, extraAttr): self.extraAttr = extraAttr def _attributes(self): try: attr = AttributesVMap(ResolveAttributesMap(self, self.AttributesMap)) if self.extraAttr: (name, vmap) = self.extraAttr attr[name] = vmap return attr except : attr = VMap() return attr dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/msdoc.py000066400000000000000000000327601217176075400235040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob import sys, traceback from struct import unpack from dff.api.vfs.libvfs import Node from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime, TIME_MS_64 from dff.modules.structparser import Struct, Header, ResolveAttributesMap, AttributesVMap from dff.modules.compoundfile.msdocheader import MSDocHeader from dff.modules.compoundfile.msodraw import OfficeArtInlineSpContainer, OfficeArtDggContainer, PictureNode class WordDocument(Struct): cbRgFcLcbSizeFibVersion = { 744 : 4, 864 : 3, 1088 : 2, 1312 : 1, 1464 : 0, } VersionList = ["FibRgFcLcb2007", "FibRgFcLcb2003", "FibRgFcLcb2002", "FibRgFcLcb2000", "FibRgFcLcb97"] BitField1 = ["fDot", "fGlsy", "fComplex", "fHasPic", "cQuickSaves", "fEncrypted", "fWhichTblStm", "fReadOnlyRecommended", "fWriteReservation", "fExtChar", "fLoadOverride", "fFatEast", "fObfuscated"] def __init__(self, node): header = Header(MSDocHeader) self.node = node vfile = self.node.open() try : data = vfile.read(154) Struct.__init__(self, header, None, header.Fib, data) if self.FibBase.wIdent != 0xA5EC: vfile.close() raise RuntimeError("Header wIdent is invalid on stream " + str(self.node.absolute())) self.readFib(vfile, header) self.readFibRgCsNew(vfile, header) except : vfile.close() raise vfile.close() self.initBitField() self.setTableAndDataStream() def initBitField(self): b = bin(self.FibBase.bitfield1).replace('0b', '')[::-1] b += (16 - len(b))*'0' for i in xrange(0, 4): setattr(self.FibBase, self.BitField1[i], int(b[i])) setattr(self.FibBase, self.BitField1[4], int(b[4:8], 2)) for i in xrange(8, 16): setattr(self.FibBase, self.BitField1[i-3], int(b[i])) #find nFib version according to cbRgFcLcb as nFib is always set a '97' #then loop and set each Fib structure to self to ease access def readFib(self, vfile, header): try: fibRgFcLcbVersion = self.VersionList[self.cbRgFcLcbSizeFibVersion[self.cbRgFcLcb*8]] except KeyError: raise Exception("No valid nFib/version") fibRgFcLcbVersionHeader = getattr(header, fibRgFcLcbVersion) data = vfile.read(fibRgFcLcbVersionHeader.ssize) currentc = Struct(header, None, fibRgFcLcbVersionHeader, data) setattr(self, fibRgFcLcbVersion, currentc) #After have reading so much MS header I started to write code as cryptic as them for x in range(self.cbRgFcLcbSizeFibVersion[self.cbRgFcLcb*8] + 1, 5): currentc = getattr(currentc, self.VersionList[x]) setattr(self, self.VersionList[x], currentc) def readFibRgCsNew(self, vfile, header): #getting right nFib self.cswNew = unpack('H', vfile.read(2))[0] self.FibRgCswNew = None data = vfile.read(self.cswNew * 2) if self.cswNew == 0: self.nFib = self.FibBase.nFib elif self.cswNew * 2 == 4: self.FibRgCswNew = Struct(header, None, header.FibRgCswNewData2000, data) self.nFib = self.FibRgCswNew.nFibNew elif self.cswNew * 2 == 10: self.FibRgCswNew = Struct(header, None, header.FibRgCswNewData2007, data) self.nFib = self.FibRgCswNew.nFibNew def setTableAndDataStream(self): if self.FibBase.fWhichTblStm == 0: tableName = '0Table' else: tableName = '1Table' children = self.node.parent().children() for node in children: if node.name() == tableName: self.tableStream = node if node.name() == 'Data': self.dataStream = node #wAlgo retrieve text from MS-DOC this give us the PlPcd /acp /aPcd table who permit to find text offset def text(self): #print hex(self.FibBase.fcMin) #start of text block / non-offical #print hex(self.FibBase.fcMac) # end of last text block offset = self.FibRgFcLcb97.fcClx #offset of a Clx in the table stream size = self.FibRgFcLcb97.lcbClx pcdt = Pcdt(self.tableStream, offset, size) #pLCpCD #now get the text from main document who CP is always 0 maindocument = (self.fibRgLw97.ccpText, pcdt.cpOffset(0)) #footnote = (self.fibRgLw97.ccpFtn, pcdt.cpOffset(1)) #headers = (self.fibRgLw97.ccpHdd, pcdt.cpOffset(2)) #comments = (self.fibRgLw97.ccpAtn, pcdt.cpOffset(3)) #endnotes = (self.fibRgLw97.ccpEdn, pcdt.cpOffset(4)) #textboxes = (self.fibRgLw97.ccpTxbx, pcdt.cpOffset(5)) #headertextboxes = (self.fibRgLw97.ccpHdrTxbx, pcdt.cpOffset(6)) offsets = [maindocument] #, footnote, headers, comments, endnotes, textboxes, headertextboxes] #, last return offsets def pictures(self): pictures = [] try: pictures += self.dataStreamPictures() except: pass try: pictures += self.worddocumentPictures() except : pass return pictures def worddocumentPictures(self): pictures = [] if self.FibRgFcLcb97.lcbDggInfo == 0: return pictures offset = self.FibRgFcLcb97.fcDggInfo size = self.FibRgFcLcb97.lcbDggInfo oac = OfficeArtContent(self.tableStream, offset, size, self.node) for blip in oac.pictures.blipStore.blips: pictures.append((blip.offset, blip.size, self.node)) return pictures def dataStreamPictures(self): pictures = [] offset = self.FibRgFcLcb97.fcPlcfBteChpx size = self.FibRgFcLcb97.lcbPlcfBteChpx plcBteChpx = PlcBteChpx(self.tableStream, offset, size) stChpxFKPs = ChpxFKPs(plcBteChpx, self.node) worddocument = self.node.open() try: for chpxFKPidx in xrange(0, len(stChpxFKPs.CHPXFKP)): for chpx in stChpxFKPs.CHPXFKP[chpxFKPidx].Chpxs: for grpprl in chpx.grpprl: if grpprl.sprm.sgc == 2 and grpprl.sprm.ispmd == 3 and grpprl.sprm.fSpec == 1: offset = unpack('I', grpprl.operand)[0] chpxfkp = stChpxFKPs.CHPXFKP[chpxFKPidx] runstart = chpxfkp.RGFCs[chpx.rfc] runend = chpxfkp.RGFCs[chpx.rfc + 1] worddocument.seek(runstart) run = worddocument.read(runend +1 -runstart) if run.find('\x01') != -1: data = 0 for grpprldata in chpx.grpprl: if grpprldata.sprm.sgc == 2 and grpprldata.sprm.ispmd == 6: data = unpack('B', grpprldata.operand)[0] break if data == 0: try: paoad = PICFAndOfficeArtData(self.dataStream, offset) if paoad.picture.blip: pictures.append((paoad.picture.blip.offset, paoad.picture.blip.size, self.dataStream)) except : pass except : pass worddocument.close() return pictures def createPictureNodes(self): offsets = self.pictures() count = 1 for offset, size, node in offsets: PictureNode(node, offset, size, count) count += 1 def createTextNodes(self): offsets = self.text() ssize = 0 for size, off in offsets: ssize += size WordTextNode(self.node, offsets, ssize) class WordTextNode(Node): def __init__(self, worddocument, offsets, size): self.offsets = offsets self.worddocument = worddocument #nom du document Node.__init__(self, 'Text', size, self.worddocument, self.worddocument.fsobj()) self.__disown__() def fileMapping(self, fm): cursize = 0 for size, offset in self.offsets: if size: fm.push(cursize, size, self.worddocument, offset) cursize += size def _attributes(self): v = VMap() return v #MS-DOC page 420 class PICFAndOfficeArtData(object): def __init__(self, datastream, offset): vfile = datastream.open() try: vfile.seek(offset) data = vfile.read(68) picf = PICF(data) if picf.mm == 0x66: nameSize = unpack('B', vfile.read(1))[0] self.name = vfile.read(nameSize) self.name += '\x00' else: self.name = None self.picture = OfficeArtInlineSpContainer(vfile) except : vfile.close() raise vfile.close() #MS-DOC Page 404 class OfficeArtContent(object): def __init__(self, tablestream, offset, size, delay = None): vfile = tablestream.open() try: vfile.seek(offset) self.pictures = OfficeArtDggContainer(vfile, delay) except : vfile.close() raise vfile.close() class PICF(object): mmType = { 0x64 : "MM_SHAPE", 0x66 : "MM_SHAPEFILE" } def __init__(self, data): self.lcb = unpack('I', data[0:4])[0] self.cbHeader = unpack('H', data[4:6])[0] self.mm = unpack('H', data[6:8])[0] class PlcBteChpx(object): def __init__(self, worddocument, offset, size): self.worddocument = worddocument self.offset = offset self.size = size self.nPNFKPCHPX = (self.size - 4) / (4 + 4) self.naFC = 1 + self.nPNFKPCHPX vfile = self.worddocument.open() try: vfile.seek(self.offset) data = vfile.read((self.naFC * 4)) self.aFC = unpack('I'*self.naFC, data) data = vfile.read(self.nPNFKPCHPX * 4) #must be 22 bits : self.PNFKPCHPX = unpack('I'*self.nPNFKPCHPX, data) except : vfile.close() raise vfile.close() def KPCHPXoffset(self, n): return (self.PNFKPCHPX[n]) * 512 #MS-DOC Page 551 class ChpxFKPs(object): def __init__(self, plcBteChpx, worddocument): self.CHPXFKP = [] vfile = worddocument.open() try: for x in xrange(0, plcBteChpx.nPNFKPCHPX): offset = plcBteChpx.KPCHPXoffset(x) vfile.seek(offset) data = vfile.read(512) self.CHPXFKP.append(ChpxFKP(data)) except : vfile.close() raise vfile.close() #MS-DOC page 235 class ChpxFKP(object): def __init__(self, data): crun = unpack('B' ,data[511:512])[0] crun = unpack('B' ,data[-1])[0] nRGFC = crun + 1 nRGB = crun self.RGFCs = unpack(nRGFC*'I', data[:nRGFC*4]) RGBs = unpack(nRGB*'B', data[nRGFC*4:nRGFC*4+nRGB]) self.Chpxs = [] rgbskip = [] rfccounter = 0 for rgb in RGBs: if rgb != 0 and (rgb not in rgbskip): rgbskip.append(rgb) self.Chpxs.append(Chpx(data[rgb*2:], rfccounter)) rfccounter += 1 class Chpx(object): def __init__(self, data, rfc): cb = unpack('B', data[0])[0] data = data[1:cb+1] self.grpprl = [] self.rfc = rfc count = 0 while count < cb: prl = PRL(data) self.grpprl.append(prl) data = data[len(prl):] count += len(prl) #MS-Doc page 31 / 414 class PRL(object): def __init__(self, data): self.sprm = SPRM(data[0:2]) operandSize = self.sprm.spraTable[self.sprm.spra] if operandSize == 0: if (self.sprm.ispmd == 0x8 and self.sprm.sgc == 5): #TDefOperandTable sz = unpack('H', data[2:4])[0] r = 2 elif (self.sprm.ispmd == 0x1 and self.sprm.sgc == 0x15): #sprmPchgTabs sz = unpack('B', data[2:3])[0] r = 1 if sz == 255: delctabs = unpack('B', data[3:4])[0] r += 1 deladdtabs = unpack('B', data[4+delctabs:4+delctabs+1])[0] sz = (4 * delctabs) + (3 * deladdtabs) r += 1 else: sz = unpack('B', data[2:3])[0] r = 1 operandSize = r + sz self.size = 2 + operandSize self.operand = data[2:operandSize+2] def __len__(self): return self.size #MS-Doc page 30 class SPRM(object): sgcTable = { 1 : "Paragraph", 2 : "Character", 3 : "Picture", 4 : "Section", 5 : "Table", } spraTable = { 0 : 1, 1 : 1, 2 : 2, 3 : 4, 4 : 2, 5 : 2, 6 : 0, #Variable if sprmTDefTable or sprmPChTabs 7 : 3, } def __init__(self, data): c = unpack('H', data)[0] c = bin(c).replace('0b', '')[::-1] c += (16-len(c))*'0' self.ispmd = int(c[0:9][::-1], 2) self.fSpec = int(c[9], 2) self.sgc = int(c[10:13][::-1], 2) self.spra = int(c[13:16][::-1], 2) class Pcdt(object): def __init__(self, table, offset, size): vfile = table.open() try: vfile.seek(offset) data = vfile.read(size) except : vfile.close() raise vfile.close() self.cltx = unpack('c', data[0])[0] data = data[1:] if self.cltx == 0x1: self.cbGrppl = unpack('I', data[0:4])[0] data = data[4:] self.GrpPrl = unpack('I'*self.cbGrppl, data[:self.cbGrppl]) data = data[:self.cbGrppl] #else cltx == 0x2: self.lcb = unpack('I', data[0:4])[0] data = data[4:] plcdData = data[:self.lcb] naPcd = (self.lcb-4)/(4+8) naCP = naPcd + 1 self.aCP = unpack('I'*naCP, plcdData[0:naCP*4]) plcdData = plcdData[naCP*4:] self.aPcd = [] for x in range(0, naPcd): data = plcdData[x*8:(x*8)+8] self.aPcd.append(PCD(data)) def cpOffset(self,cp): i = cp if self.aPcd[cp].fCompressed == 0: #16 Bit unicode return self.aPcd[cp].fc# + (2*(cp - self.aCP[i])) else: return (self.aPcd[cp].fc/2) #+ (cp- self.aCP[i]) class PCD(object): def __init__(self, data): fcstruct = unpack(' MSDocHeader = ({ "info" : { "os" : "None", "arch":"None", "name" : "Fib"}, "descr" : { "Fib" : ((154), { "FibBase" : (32, 0, "FibBase"), #The fibBase "csw" : (2, 32), #count int16 in FibRgW must be 0x000E *2 (0xe * 2 == 28) "fibRgW97" : (28, 34, "FibRgW97"), "cslw" : (2, 62), #count of 32 bit value in gibRgLw 0x16 * 4== 8 "fibRgLw97" : (88, 64, "FibRgLw97"), "cbRgFcLcb" : (2, 152), #count of 64 bit value for fibRgFcLcbBlob table nfib -> cgbRgFcLcb #"cswNew" count of 16 bit variable of fibRgCswNew depend of nfib et table .. # "fibRgCswNew" if cswNew not 0 variable length ... }), "FibBase" : ((32), # #Take care of bitfield and ms implem is false ! { "wIdent" : (2, 0), #Magic specifie this is a word file -> 0xA5EC "nFib" : (2, 2), #0x00c1 00c0 00c2 version number of file, superseed by FibRgCswNew.nFibNew if present "unused" : (2, 4), #product version "lid" : (2, 6), #install language of the application "pnNext" : (2, 8), #offset of FIB who contains all the AutoText item, "bitfield1" : (2, 10), # "fDot" : (1, 9), #specifies if it's a template # "fGlsy" : (1, 10), #specifies if it contain only autotext # "fComplex" : (1, 11), #specifie if last save was incremental # "fHasPic" : (1, 12), #specifie if there is pictuer ! # "cQuickSaves" : (4, 13), #if nFib < 0x09 specifie number of inc save done # "fEncrypted" : (1, 14), #specifie if encrypted # "fWichTblStm" : (1, 15), #specifie the table stream 0Table or 1Table # "fReadOnlyRecommended" : (1, 16), #is the doc auto opened in RO mode # "fWriteReservation" : (1, 17), #is the doc have write recomendation pasword # "fExtChar" : (1, 18), #? must be 1 # "fLoadOverride" : (1, 19), #overide font and lang # "fFarEast" : (1, 20), #specifie the language was east asian # "fObfuscated" : (1, 21), #the doc use XOR obfuscation "nFibBack" : (2, 12), "Ikey" : (4, 14), #if encrypted is 1 and fObfuscaiton 1 size of rc4 table or XOR password verifier "envr" : (1, 18), #? must be 0 "bitfield2" : (1, 19), "Chs" : (2 ,20), "chsTables" : (2, 22), "fcMin" : (4, 24), "fcMac" : (4, 28), # "fMac" : (1, 19), #must be 0 # "fEmptySpecial" : (1, 31) #msut be .. # "fLoadOverridePage" : (1, 32), #overide ... # "reserved1" : (1, 33), # "reserved2" : (1, 34), # "fSpare"0 : (3, 35), # "reserved3" : (2, 38), # "reserved4" : (2, 40), # "reserved5" : (4, 42), # "reserved6" : (4, 46), }), "FibRgW97" : ((34), { "Unused" : (24, 0), #nothing really interesting here, skipping ... }), "FibRgLw97" : ((88), { "cbMac" : (4, 0), #64 "lProductCreated" : (4, 4), #"build date of the creator in special format #68 "lProductRevised" : (4, 8), #build date of file last modifier #72 "ccpText" : (4, 12), #"length of the main doc text stream 1" #76 "ccpFtn" : (4, 16), #length of footnote sub doc text stream #80 "ccpHdd" : (4, 20), #length of header sub doc #84 "ccpMcr" : (4, 24), #length of macro ? should be 0 ? #88 "ccpAtn" : (4, 28), #length of annoation #92 "ccpEdn" : (4, 32), # " endnote #96 "ccpTxbx" : (4, 36), # "" text box subdoc #100 "ccpHdrTxbx" : (4, 40), # " header text box #!04 "pnFbpChpFirst" : (4, 44), # #108 "pnChpFirst" : (4, 48), # .. #112 "cpnBteChp" : (4, 52), # #116 "pnFbPapFirst" : (4, 56), #120 "pnPapFirst" : (4, 60), #124 "cpnBtePap" : (4, 64), #128 "pbFbpLvcFirst" : (4, 68), #132 "pnLvcFirst" : (4, 72), #136 "cpnBteLvc" : (4, 76), #140 "fcIslandFirst" : (4, 80), #144 "fcIslandLim" : (4, 84) #148 }), "FibRgFcLcb97" : ((744), { "fcStshfOrig" : (4, 0), "lcbStshfOrig" : (4, 4), "fcStshf" : (4, 8), "lcbStshf" : (4, 12), "fcPlcffndRef" : (4, 16), "lcbPlcffndRef" : (4, 20), "fcPlcffndTxt" : (4, 24), "lcbPlcffndTxt" : (4, 28), "fcPlcfandRef" : (4, 32), "lcbPlcfandRef" : (4, 36), "fcPlcfandTxt" : (4, 40), "lcbPlcfandTxt" : (4, 44), "fcPlcfSed" : (4, 48), "lcbPlcfSed" : (4, 52), "fcPlcPad" : (4, 56), "lcbPlcPad" : (4, 60), "fcPlcfPhe" : (4, 64), "lcbPlcfPhe" : (4, 68), "fcSttbfGlsy" : (4, 72), "lcbSttbfGlsy" : (4, 76), "fcPlcfGlsy" : (4, 80), "lcbPlcfGlsy" : (4, 84), "fcPlcfHdd" : (4, 88), "lcbPlcfHdd" : (4, 92), "fcPlcfBteChpx" : (4, 96), "lcbPlcfBteChpx" : (4, 100), "fcPlcfBtePapx" : (4, 104), "lcbPlcfBtePapx" : (4, 108), "fcPlcfSea" : (4, 112), "lcbPlcfSea" : (4, 116), "fcSttbfFfn" : (4, 120), "lcbSttbfFfn" : (4, 124), "fcPlcfFldMom" : (4, 128), "lcbPlcfFldMom" : (4, 132), "fcPlcfFldHdr" : (4, 136), "lcbPlcfFldHdr" : (4, 140), "fcPlcfFldFtn" : (4, 144), "lcbPlcfFldFtn" : (4, 148), "fcPlcfFldAtn" : (4, 152), "lcbPlcfFldAtn" : (4, 156), "fcPlcfFldMcr" : (4, 160), "lcbPlcfFldMcr" : (4, 164), "fcSttbfBkmk" : (4, 168), "lcbSttbfBkmk" : (4, 172), "fcPlcfBkf" : (4, 176), "lcbPlcfBkf" : (4, 180), "fcPlcfBkl" : (4, 184), "lcbPlcfBkl" : (4, 188), "fcCmds" : (4, 192), "lcbCmds" : (4, 196), "fcUnused1" : (4, 200), "lcbUnused1" : (4, 204), "fcSttbfMcr" : (4, 208), "lcbSttbfMcr" : (4, 212), "fcPrDrvr" : (4, 216), "lcbPrDrvr" : (4, 220), "fcPrEnvPort" : (4, 224), "lcbPrEnvPort" : (4, 228), "fcPrEnvLand" : (4, 232), "lcbPrEnvLand" : (4, 236), "fcWss" : (4, 240), "lcbWss" : (4, 244), "fcDop" : (4, 248), "lcbDop" : (4, 252), "fcSttbfAssoc" : (4, 256), "lcbSttbfAssoc" : (4, 260), "fcClx" : (4, 264), "lcbClx" : (4, 268), "fcPlcfPgdFtn" : (4, 272), "lcbPlcfPgdFtn" : (4, 276), "fcAutosaveSource" : (4, 280), "lcbAutosaveSource" : (4, 284), "fcGrpXstAtnOwners" : (4, 288), "lcbGrpXstAtnOwners" : (4, 292), "fcSttbfAtnBkmk" : (4, 296), "lcbSttbfAtnBkmk" : (4, 300), "fcUnused2" : (4, 304), "lcbUnused2" : (4, 308), "fcUnused3" : (4, 312), "lcbUnused3" : (4, 316), "fcPlcSpaMom" : (4, 320), "lcbPlcSpaMom" : (4, 324), "fcPlcSpaHdr" : (4, 328), "lcbPlcSpaHdr" : (4, 332), "fcPlcfAtnBkf" : (4, 336), "lcbPlcfAtnBkf" : (4, 340), "fcPlcfAtnBkl" : (4, 344), "lcbPlcfAtnBkl" : (4, 348), "fcPms" : (4, 352), "lcbPms" : (4, 356), "fcFormFldSttbs" : (4, 360), "lcbFormFldSttbs" : (4, 364), "fcPlcfendRef" : (4, 368), "lcbPlcfendRef" : (4, 372), "fcPlcfendTxt" : (4, 376), "lcbPlcfendTxt" : (4, 380), "fcPlcfFldEdn" : (4, 384), "lcbPlcfFldEdn" : (4, 388), "fcUnused4" : (4, 392), "lcbUnused4" : (4, 396), "fcDggInfo" : (4, 400), "lcbDggInfo" : (4, 404), "fcSttbfRMark" : (4, 408), "lcbSttbfRMark" : (4, 412), "fcSttbfCaption" : (4, 416), "lcbSttbfCaption" : (4, 420), "fcSttbfAutoCaption" : (4, 424), "lcbSttbfAutoCaption" : (4, 428), "fcPlcfWkb" : (4, 432), "lcbPlcfWkb" : (4, 436), "fcPlcfSpl" : (4, 440), "lcbPlcfSpl" : (4, 444), "fcPlcftxbxTxt" : (4, 448), "lcbPlcftxbxTxt" : (4, 452), "fcPlcfFldTxbx" : (4, 456), "lcbPlcfFldTxbx" : (4, 460), "fcPlcfHdrtxbxTxt" : (4, 464), "lcbPlcfHdrtxbxTxt" : (4, 468), "fcPlcffldHdrTxbx" : (4, 472), "lcbPlcffldHdrTxbx" : (4, 476), "fcStwUser" : (4, 480), "lcbStwUser" : (4, 484), "fcSttbTtmbd" : (4, 488), "lcbSttbTtmbd" : (4, 492), "fcCookieData" : (4, 496), "lcbCookieData" : (4, 500), "fcPgdMotherOldOld" : (4, 504), "lcbPgdMotherOldOld" : (4, 508), "fcBkdMotherOldOld" : (4, 512), "lcbBkdMotherOldOld" : (4, 516), "fcPgdFtnOldOld" : (4, 520), "lcbPgdFtnOldOld" : (4, 524), "fcBkdFtnOldOld" : (4, 528), "lcbBkdFtnOldOld" : (4, 532), "fcPgdEdnOldOld" : (4, 536), "lcbPgdEdnOldOld" : (4, 540), "fcBkdEdnOldOld" : (4, 544), "lcbBkdEdnOldOld" : (4, 548), "fcSttbfIntlFld" : (4, 552), "lcbSttbfIntlFld" : (4, 556), "fcRouteSlip" : (4, 560), "lcbRouteSlip" : (4, 564), "fcSttbSavedBy" : (4, 568), "lcbSttbSavedBy" : (4, 572), "fcSttbFnm" : (4, 576), "lcbSttbFnm" : (4, 580), "fcPlfLst" : (4, 584), "lcbPlfLst" : (4, 588), "fcPlfLfo" : (4, 592), "lcbPlfLfo" : (4, 596), "fcPlcfTxbxBkd" : (4, 600), "lcbPlcfTxbxBkd" : (4, 604), "fcPlcfTxbxHdrBkd" : (4, 608), "lcbPlcfTxbxHdrBkd" : (4, 612), "fcDocUndoWord9" : (4, 616), "lcbDocUndoWord9" : (4, 620), "fcRgbUse" : (4, 624), "lcbRgbUse" : (4, 628), "fcUsp" : (4, 632), "lcbUsp" : (4, 636), "fcUskf" : (4, 640), "lcbUskf" : (4, 644), "fcPlcupcRgbUse" : (4, 648), "lcbPlcupcRgbUse" : (4, 652), "fcPlcupcUsp" : (4, 656), "lcbPlcupcUsp" : (4, 660), "fcSttbGlsyStyle" : (4, 664), "lcbSttbGlsyStyle" : (4, 668), "fcPlgosl" : (4, 672), "lcbPlgosl" : (4, 676), "fcPlcocx" : (4, 680), "lcbPlcocx" : (4, 684), "fcPlcfBteLvc" : (4, 688), "lcbPlcfBteLvc" : (4, 692), "dwLowDateTime" : (4, 696), "dwHighDateTime" : (4, 700), "fcPlcfLvcPre10" : (4, 704), "lcbPlcfLvcPre10" : (4, 708), "fcPlcfAsumy" : (4, 712), "lcbPlcfAsumy" : (4, 716), "fcPlcfGram" : (4, 720), "lcbPlcfGram" : (4, 724), "fcSttbListNames" : (4, 728), "lcbSttbListNames" : (4, 732), "fcSttbfUssr" : (4, 736), "lcbSttbfUssr" : (4, 740), }), "FibRgFcLcb2000" : ((864), #self 120 { "FibRgFcLcb97" : (744, 0, "FibRgFcLcb97"), "fcPlcfTch" : (4, 744), "lcbPlcfTch" : (4, 748), "fcRmdThreading" : (4, 752), "lcbRmdThreading" : (4, 756), "fcMid" : (4, 760), "lcbMid" : (4, 764), "fcSttbRgtplc" : (4, 768), "lcbSttbRgtplc" : (4, 772), "fcMsoEnvelope" : (4, 776), "lcbMsoEnvelope" : (4, 780), "fcPlcfLad" : (4, 784), "lcbPlcfLad" : (4, 788), "fcRgDofr" : (4, 792), "lcbRgDofr" : (4, 796), "fcPlcosl" : (4, 800), "lcbPlcosl" : (4, 804), "fcPlcfCookieOld" : (4, 808), "lcbPlcfCookieOld" : (4, 812), "fcPgdMotherOld" : (4, 816), "lcbPgdMotherOld" : (4, 820), "fcBkdMotherOld" : (4, 824), "lcbBkdMotherOld" : (4, 828), "fcPgdFtnOld" : (4, 832), "lcbPgdFtnOld" : (4, 836), "fcBkdFtnOld" : (4, 840), "lcbBkdFtnOld" : (4, 844), "fcPgdEdnOld" : (4, 848), "lcbPgdEdnOld" : (4, 852), "fcBkdEdnOld" : (4, 856), "lcbBkdEdnOld" : (4, 860), }), "FibRgFcLcb2002" : ((1088), #self 224 { "FibRgFcLcb2000" : (864, 0, "FibRgFcLcb2000"), "fcUnused1" : (4, 864), "lcbUnused1" : (4, 868), "fcPlcfPgp" : (4, 872), "lcbPlcfPgp" : (4, 876), "fcPlcfuim" : (4, 880), "lcbPlcfuim" : (4, 884), "fcPlfguidUim" : (4, 888), "lcbPlfguidUim" : (4, 892), "fcAtrdExtra" : (4, 896), "lcbAtrdExtra" : (4, 900), "fcPlrsid" : (4, 904), "lcbPlrsid" : (4, 908), "fcSttbfBkmkFactoid" : (4, 912), "lcbSttbfBkmkFactoid" : (4, 916), "fcPlcfBkfFactoid" : (4, 920), "lcbPlcfBkfFactoid" : (4, 924), "fcPlcfcookie" : (4, 928), "lcbPlcfcookie" : (4, 932), "fcPlcfBklFactoid" : (4, 936), "lcbPlcfBklFactoid" : (4, 940), "fcFactoidData" : (4, 944), "lcbFactoidData" : (4, 948), "fcDocUndo" : (4, 952), "lcbDocUndo" : (4, 956), "fcSttbfBkmkFcc" : (4, 960), "lcbSttbfBkmkFcc" : (4, 964), "fcPlcfBkfFcc" : (4, 968), "lcbPlcfBkfFcc" : (4, 972), "fcPlcfBklFcc" : (4, 976), "lcbPlcfBklFcc" : (4, 980), "fcSttbfbkmkBPRepairs" : (4, 984), "lcbSttbfbkmkBPRepairs" : (4, 988), "fcPlcfbkfBPRepairs" : (4, 992), "lcbPlcfbkfBPRepairs" : (4, 996), "fcPlcfbklBPRepairs" : (4, 1000), "lcbPlcfbklBPRepairs" : (4, 1004), "fcPmsNew" : (4, 1008), "lcbPmsNew" : (4, 1012), "fcODSO" : (4, 1016), "lcbODSO" : (4, 1020), "fcPlcfpmiOldXP" : (4, 1024), "lcbPlcfpmiOldXP" : (4, 1028), "fcPlcfpmiNewXP" : (4, 1032), "lcbPlcfpmiNewXP" : (4, 1036), "fcPlcfpmiMixedXP" : (4, 1040), "lcbPlcfpmiMixedXP" : (4, 1044), "fcUnused2" : (4, 1048), "lcbUnused2" : (4, 1052), "fcPlcffactoid" : (4, 1056), "lcbPlcffactoid" : (4, 1060), "fcPlcflvcOldXP" : (4, 1064), "lcbPlcflvcOldXP" : (4, 1068), "fcPlcflvcNewXP" : (4, 1072), "lcbPlcflvcNewXP" : (4, 1076), "fcPlcflvcMixedXP" : (4, 1080), "lcbPlcflvcMixedXP" : (4, 1084), }), "FibRgFcLcb2003" : ((1312), #self 224 { "FibRgFcLcb2002" : (1088, 0, "FibRgFcLcb2002"), "fcHplxsdr" : (4, 1088), "lcbHplxsdr" : (4, 1092), "fcSttbfBkmkSdt" : (4, 1096), "lcbSttbfBkmkSdt" : (4, 1100), "fcPlcfBkfSdt" : (4, 1104), "lcbPlcfBkfSdt" : (4, 1108), "fcPlcfBklSdt" : (4, 1112), "lcbPlcfBklSdt" : (4, 1116), "fcCustomXForm" : (4, 1120), "lcbCustomXForm" : (4, 1124), "fcSttbfBkmkProt" : (4, 1128), "lcbSttbfBkmkProt" : (4, 1132), "fcPlcfBkfProt" : (4, 1136), "lcbPlcfBkfProt" : (4, 1140), "fcPlcfBklProt" : (4, 1144), "lcbPlcfBklProt" : (4, 1148), "fcSttbProtUser" : (4, 1152), "lcbSttbProtUser" : (4, 1156), "fcUnused" : (4, 1160), "lcbUnused" : (4, 1164), "fcPlcfpmiOld" : (4, 1168), "lcbPlcfpmiOld" : (4, 1172), "fcPlcfpmiOldInline" : (4, 1176), "lcbPlcfpmiOldInline" : (4, 1180), "fcPlcfpmiNew" : (4, 1184), "lcbPlcfpmiNew" : (4, 1188), "fcPlcfpmiNewInline" : (4, 1192), "lcbPlcfpmiNewInline" : (4, 1196), "fcPlcflvcOld" : (4, 1200), "lcbPlcflvcOld" : (4, 1204), "fcPlcflvcOldInline" : (4, 1208), "lcbPlcflvcOldInline" : (4, 1212), "fcPlcflvcNew" : (4, 1216), "lcbPlcflvcNew" : (4, 1220), "fcPlcflvcNewInline" : (4, 1224), "lcbPlcflvcNewInline" : (4, 1228), "fcPgdMother" : (4, 1232), "lcbPgdMother" : (4, 1236), "fcBkdMother" : (4, 1240), "lcbBkdMother" : (4, 1244), "fcAfdMother" : (4, 1248), "lcbAfdMother" : (4, 1252), "fcPgdFtn" : (4, 1256), "lcbPgdFtn" : (4, 1260), "fcBkdFtn" : (4, 1264), "lcbBkdFtn" : (4, 1268), "fcAfdFtn" : (4, 1272), "lcbAfdFtn" : (4, 1276), "fcPgdEdn" : (4, 1280), "lcbPgdEdn" : (4, 1284), "fcBkdEdn" : (4, 1288), "lcbBkdEdn" : (4, 1292), "fcAfdEdn" : (4, 1296), "lcbAfdEdn" : (4, 1300), "fcAfd" : (4, 1304), "lcbAfd" : (4, 1308), }), "FibRgFcLcb2007" : ((1464), #self 152 { "FibRgFcLcb2003" : (1312, 0, "FibRgFcLcb2003"), "fcPlcfmthd" : (4, 1312), "lcbPlcfmthd" : (4, 1316), "fcSttbfBkmkMoveFrom" : (4, 1320), "lcbSttbfBkmkMoveFrom" : (4, 1324), "fcPlcfBkfMoveFrom" : (4, 1328), "lcbPlcfBkfMoveFrom" : (4, 1332), "fcPlcfBklMoveFrom" : (4, 1336), "lcbPlcfBklMoveFrom" : (4, 1340), "fcSttbfBkmkMoveTo" : (4, 1344), "lcbSttbfBkmkMoveTo" : (4, 1348), "fcPlcfBkfMoveTo" : (4, 1352), "lcbPlcfBkfMoveTo" : (4, 1356), "fcPlcfBklMoveTo" : (4, 1360), "lcbPlcfBklMoveTo" : (4, 1364), "fcUnused1" : (4, 1368), "lcbUnused1" : (4, 1372), "fcUnused2" : (4, 1376), "lcbUnused2" : (4, 1380), "fcUnused3" : (4, 1384), "lcbUnused3" : (4, 1388), "fcSttbfBkmkArto" : (4, 1392), "lcbSttbfBkmkArto" : (4, 1396), "fcPlcfBkfArto" : (4, 1400), "lcbPlcfBkfArto" : (4, 1404), "fcPlcfBklArto" : (4, 1408), "lcbPlcfBklArto" : (4, 1412), "fcArtoData" : (4, 1416), "lcbArtoData" : (4, 1420), "fcUnused4" : (4, 1424), "lcbUnused4" : (4, 1428), "fcUnused5" : (4, 1432), "lcbUnused5" : (4, 1436), "fcUnused6" : (4, 1440), "lcbUnused6" : (4, 1444), "fcOssTheme" : (4, 1448), "lcbOssTheme" : (4, 1452), "fcColorSchemeMapping" : (4, 1456), "lcbColorSchemeMapping" : (4, 1460), }), "FibRgCswNewData2000" : ((4), { "nFibNew" : (2, 0), "nQuickSavesNew" : (2,2), }), "FibRgCswNewData2007" : ((10), { "nFibNew" : (2, 0), "nQuickSaveNew" : (2, 2), "lidThemeOther" : (2, 4), "lidThemeFE" : (2, 6), "lidThemeCS" : (2, 8), }) } }) dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/msodraw.py000066400000000000000000000141531217176075400240470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from struct import unpack from dff.api.types.libtypes import VMap from dff.api.vfs.libvfs import Node class OfficeArtDggContainer(object): def __init__(self, vfile, delay = None): self.rh = OfficeArtRecordHeader(vfile) self.drawingGroup = OfficeArtFDGGBlock(vfile) self.blipStore = OfficeArtBStoreContainer(vfile, delay) #MS-ODRAW page 49 class OfficeArtFDGGBlock(object): def __init__(self, vfile): self.rh = OfficeArtRecordHeader(vfile) vfile.seek(self.rh.recLen, 1) class OfficeArtBStoreDelay(object): def __init__(self, vfile): self.blips = [] rgfb = OfficeArtRecordHeader(vfile) while vfile.tell() < vfile.node().size(): if rgfb.recType == 0xF007: oafbse = OfficeArtFBSE(vfile) if oafbse.blip.offset != None: self.blips.append(oafbse.blip) elif rgfb.recType >= 0xF018 and rgfb.recType <= 0xF117: blip = OfficeArtBlip(rgfb, vfile.tell()) self.blips.append(blip) try: if rgfb.recLen == 0: break vfile.seek(rgfb.recLen , 1) rgfb = OfficeArtRecordHeader(vfile) except : break class OfficeArtBStoreContainer(object): def __init__(self, vfile, delay = None): self.blips = [] self.rh = OfficeArtRecordHeader(vfile) rgfb = OfficeArtRecordHeader(vfile) fpos = self.rh.recLen + vfile.tell() while vfile.tell() < fpos: if rgfb.recType == 0xF007: oafbse = OfficeArtFBSE(vfile, delay) if oafbse.blip.offset != None: self.blips.append(oafbse.blip) elif rgfb.recType >= 0xF018 and rgfb.recType <= 0xF117: vfile.seek(rgfb.recLen, 1) #blip = OfficeArtBlip(rgfb, vfile.tell()) #self.blips.append(blip) else: if rgfb.recLen != 0: vfile.seek(rgfb.recLen , 1) else: break rgfb = OfficeArtRecordHeader(vfile) #MS_ODRAW page 55 class OfficeArtInlineSpContainer(object): def __init__(self, vfile): self.shape = OfficeArtSpContainer(vfile) vfile.seek(self.shape.rh.recLen ,1) self.rgfb = OfficeArtRecordHeader(vfile) self.blip = None #loop ? like BSToreContainer ? if self.rgfb.recType == 0xF007: oafbse = OfficeArtFBSE(vfile) self.blip = oafbse.blip elif self.rgfb.recType >= 0xF018 and self.rgfb.recType <= 0xF117: self.blip = OfficeArtBlip(self.rgfb, vfile.tell()) else: if self.rgfb.recLen != 0: vfile.seek(self.rgfb.recLen, 1) class OfficeArtFBSE(object): def __init__(self, vfile, delay = None): self.blip = None self.rh = OfficeArtRecordHeader(vfile) vfile.seek(12, 1) self.size, self.cRef, self.foDelay, u1, cbName, u2, u3 = unpack('IIIBBBB', vfile.read(16)) if (cbName > 0) and (cbName < 0xff): self.nameData = vfile.read(cbName) if delay == None: self.bliprh = OfficeArtRecordHeader(vfile) self.blip = OfficeArtBlip(self.bliprh, vfile.tell()) else: fdelay = delay.open() try: fdelay.seek(self.foDelay) self.bliprh = OfficeArtRecordHeader(fdelay) self.blip = OfficeArtBlip(self.bliprh, fdelay.tell()) except : fdelay.close() raise fdelay.close() class OfficeArtBlip(object): Type = { 0xF01A : "EMF", 0xF01B : "WMF", 0xF01C : "PICT", 0xF01D : "JPEG", 0xF01E : "PNG", 0xF01F : "DIB", 0xF029 : "TIFF", 0xF02A : "JPEG", } TypeOffset = { "JPEG" : [(0x46A, 17), (0x6E2, 17), (0x46B, 33), (0x6E3, 33)] , "PNG" : [(0x6E0, 17), (0x6E1, 33)], "EMF" : [(0x3D4, 50), (0x3D5, 66)], "WMF" : [(0x216, 50), (0x217, 66)], "PICT" : [(0x542, 50), (0x543, 66)], "DIB" : [(0x7A8, 17), (0x7A9, 33)], "TIFF" : [(0x6E4, 17), (0x6E5, 33)], } def __init__(self, rh, voffset): self.rh = rh self.offset = None self.size = None try : offsets = self.TypeOffset[self.Type[self.rh.recType]] except KeyError, e: return for (instance, shift) in offsets: if self.rh.recInstance == instance: self.offset = voffset + shift self.size = self.rh.recLen - shift break class OfficeArtSpContainer(object): ['fGroup', 'fChild', 'fPatriarch', 'fDeleted', 'fOleShape', 'fHaveMaster', 'fFlipH', 'fFlipV', 'fConnector', 'fHaveAnchor', 'fBackground', 'fHaveSpt'] def __init__(self, vfile): self.rh = OfficeArtRecordHeader(vfile) #offset = vfile.tell() #vfile.seek(24) #self.shapeGroup #self.shapeProp = OfficeArtFSP(vfile) #vfile.seek(offset) #self.shapeProp = #self.deletedShape = #self.shaprePrimaryOptions1 = #self.shapeSecondaryOptions1 = #self.shapeTertiaryOptions1 = #self.childAnchor = #self.clientAnchor = #self.clientData = #self.clientTextbox #self.shapeSecondaryOptions2 = #self.shapeSecondaryOptions2 = #self.shapeTertiaryOptions2 = class OfficeArtFSP(object): def __init__(self, vfile): self.rh = OfficeArtRecordHeader(vfile) spid = unpack('HH', vfile.read(4))[0] spid = bin(spid).replace('0b', '') class OfficeArtRecordHeader(object): def __init__(self, vfile): recVerInstance, self.recType, self.recLen = unpack('> 4 class PictureNode(Node): def __init__(self, parent, offset, size, count): self.parent = parent self.offset = offset Node.__init__(self, 'Picture' + str(count), size, self.parent, self.parent.fsobj()) self.__disown__() def fileMapping(self, fm): fm.push(0, self.size(), self.parent, self.offset) def _attributes(self): v = VMap() return v dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/msoleps.py000066400000000000000000000103271217176075400240540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from dff.modules.structparser import Struct, Header, ResolveAttributesMap, AttributesVMap from dff.modules.lnk.lnkitem import UUID from dff.modules.compoundfile.msoshared import MSVariant PropertySetStreamHeader = ({ "info" : { "os":"None", "arch":"None", "name":"PropertySetStream"}, "descr" : { "PropertySetStream" : ((28), { "magic" : (2, 0), "void" : (2, 2), "OSVersion" : (2, 4), "OSType" : (2, 6), "CLSID" : (16, 8), "SectionCount" : (4, 24), }), "SectionList" : ((20), { "CLSID" : (16, 0), "Offset" : (4, 16) }), "Section" : ((8), { "Length" : (4, 0), "PropertyCount" : (4, 4), }), "PropertyList" : ((8), { "PropertyID" : (4, 0), "Offset" : (4, 4) }), } }) class PropertyList(list): def __init__(self): list.__init__(self) def propertyID(self, ID): for Property in self: if Property.PropertyID == ID: return Property return [] class PropertySetStream(Struct): OSID = { 0x0 : "Windows 16", 0x1 : "Macintosh", 0x2 : "Windows 32"} def __init__(self, stream, matchingSectionCLSID = None): #add some sectionCLSID to match to avoid parsing all section self.sectionList = [] vfile = stream.open() try: magic = vfile.read(2) if magic != "\xfe\xff": vfile.close() raise RuntimeError('Not a property stream') vfile.seek(0) data = vfile.read(28) self.header = Header(PropertySetStreamHeader) Struct.__init__(self, self.header, None, self.header.PropertySetStream, data) self.CLSID = UUID(self.CLSID) try : os = self.OSID[self.OSType] self.OSVersion = os + ' - ' + str(self.OSVersion & 0x00ff) + '.' + str(self.OSVersion >> 8) except KeyError: self.OSVersion = "Unknown" count = 0 vfile.seek(28) while count < self.SectionCount: sectionListData = vfile.read(20) sectionHeader = Struct(self.header, None, self.header.SectionList, sectionListData) sectionHeader.CLSID = UUID(sectionHeader.CLSID) currentSectionListOffset = vfile.tell() if not matchingSectionCLSID or (sectionHeader.CLSID in matchingSectionCLSID): vfile.seek(sectionHeader.Offset) data = vfile.read(8) sectionHeader.Section = Struct(self.header, None, self.header.Section, data) sectionHeader.Section.PropertyList = PropertyList() maxReadSize = stream.size() - vfile.tell() if maxReadSize <= 0: break if sectionHeader.Section.Length < maxReadSize: readSize = sectionHeader.Section.Length else: readSize = maxReadSize data = vfile.read(readSize) propertyCount = 0 while propertyCount < sectionHeader.Section.PropertyCount: propert = Struct(self.header, None, self.header.PropertyList, data[propertyCount*8:(propertyCount*8)+8]) sectionHeader.Section.PropertyList.append(propert) propertyCount += 1 vfile.seek(sectionHeader.Offset + propert.Offset) propert.Variant = MSVariant(vfile) self.sectionList.append(sectionHeader) vfile.seek(currentSectionListOffset) count += 1 except : vfile.close() raise vfile.close() def sectionCLSID(self, sectionCLSID): for section in self.sectionList: if section.CLSID == sectionCLSID: return section.Section return None def show_sections(self): print self.magic, self.void, self.OSVersion, self.CLSID, self.SectionCount for section in self.sectionList: print section.CLSID, section.Section for propert in section.Section.PropertyList: print propert print propert.Variant.Type print propert.Variant.Value dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/msoshared.py000066400000000000000000000125361217176075400243630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob import sys, traceback from struct import unpack from dff.api.vfs.libvfs import Node from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime, TIME_MS_64 from dff.modules.structparser import Struct, Header, ResolveAttributesMap, AttributesVMap from dff.modules.lnk.lnkheader import PropertyType OfficeDocumentSectionCLSID = { "F29F85E0-4FF9-1068-AB91-08002B27B3D9" : ("SummaryInformation", { 1: "Code page", 2: "Title", 3: "Subject", 4: "Author", 5: "Keywords", 6: "Comments", 7: "Template", 8: "Last author", 9: "Revision number", 10: "Total editing time", #MSVariant is filetime but it's an absolute time 11: "Last Printed", 12: "Created time", 13: "Last saved time", 14: "Number of pages", 15: "Number of words", 16: "Number of characters", 17: "Thumbnail", 18: "Application name", 19: "Security", }), "D5CDD502-2E9C-101B-9397-08002B2CF9AE" : ("DocumentSummaryInformation", { 0: "Dictionary", 1 : "Code page", 2 : "Category", 3 : "Presentation format", 4 : "Estimated size", 5 : "Number of lines", 6 : "Number of paragraphs", 7 : "Number of slides", 8 : "Number of notes", 9 : "Number of hidden slides", 10 : "Number of multimedia clips", 11 : "Scale crop", 12 : "Heading pairs", 13 : "Titles of parts", 14 : "Manager", 15 : "Company", 16 : "Links dirty", 17 : "Number of characters", 19 : "Application version", 26 : "Content type", 27 : "Content status", }), } class MSVariant(object): def __init__(self, vfile): try: self.Type = PropertyType[unpack('I', vfile.read(4))[0]] self.Value = MSVariantConverter[self.Type](vfile) except : self.Value = None class VT_CF(Node): ClipboardFormat = { -1 : "CFTAG_WINDOWS", -2 : "CTAG_MACINTOSH", -3 : "CFTAG_FMTID", 0 : "CFTAG_NODATA", } ClipboardDataFormat = { 3 : "CF_METAFILEPICT", 8 : "CF_DIB", 14: "CF_ENHMETAFILE", 2: "CF_BITMAP", } def __init__(self, vfile): #XXX WMF and other type self.parent = vfile.node() self.Size = unpack('I', vfile.read(4))[0] self.cbFormat = self.ClipboardFormat[unpack('i', vfile.read(4))[0]] self.cbDataFormat = self.ClipboardDataFormat[unpack('I', vfile.read(4))[0]] if self.cbDataFormat == "CF_METAFILEPICT": (mappingMode, x) = unpack('II', vfile.read(8)) self.Size -= 8 self.Size -= 4 self.pos = vfile.tell() Node.__init__(self, 'Thumbnail', self.Size, self.parent, vfile.node().fsobj()) self.__disown__() def fileMapping(self, fm): fm.push(0, self.size(), self.parent, self.pos) def _attributes(self): vmap = VMap() v = Variant(self.cbFormat) vmap['Clibboard Format'] = v v = Variant(self.cbDataFormat) vmap['Clibboard Data Format'] = v return vmap #Could be done automatically class VT_VECTOR_LPSTR(VList): def __init__(self, vfile): vsize = unpack('I', vfile.read(4))[0] VList.__init__(self) count = 0 while count < vsize: try: v = VT_LPSTR(vfile) self.push_back(v) except : pass count += 1 class VT_VECTOR_VARIANT(VList): def __init__(self, vfile): vsize = unpack('I', vfile.read(4))[0] VList.__init__(self) count = 0 while count < vsize: try: msv = MSVariant(vfile) v = msv.Value self.push_back(v) except : pass count += 1 class VT_LPWSTR(Variant): #untested def __init__(self, vfile): size = unpack('I', vfile.read(4))[0] data = vfile.read(size) data = unicode(data, 'UTF-16').encode('UTF-8') Variant.__init__(self, data) class VT_LPSTR(Variant): def __init__(self, vfile): size = unpack('I', vfile.read(4))[0] data = vfile.read(size) if len(data) > 1: Variant.__init__(self, str(data)) else: Variant.__init__(self, None) class VT_FILETIME(Variant): def __init__(self, vfile): data = unpack('Q', vfile.read(8))[0] #MS didn't differentiate absolute and relative time (time/datetime) #so use ugly trick heare if data >= 116444736000000000: #a date time should be superior than the lep between unix & ms epoch vt = vtime(data, TIME_MS_64) vt.thisown = False Variant.__init__(self, vt) else: Variant.__init__(self, data) class VT_BOOL(Variant): def __init__(self, vfile): Variant.__init__(self, bool(unpack('H', vfile.read(2))[0])) class VT_I4(Variant): def __init__(self, vfile): Variant.__init__(self, unpack('I', vfile.read(4))[0]) class VT_I2(Variant): def __init__(self, vfile): Variant.__init__(self, unpack('H', vfile.read(2))[0]) MSVariantConverter = { "VT_LPSTR" : VT_LPSTR, "VT_FILETIME" : VT_FILETIME, "VT_I4" : VT_I2, "VT_I2" : VT_I2, "VT_BOOL" : VT_BOOL, "VT_CF" : VT_CF, "VT_VECTOR_LPSTR" : VT_VECTOR_LPSTR, "VT_VECTOR_VARIANT" : VT_VECTOR_VARIANT, } dff-1.3.0+dfsg.1/dff/modules/metadata/compoundfile/msppt.py000066400000000000000000000022421217176075400235320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from msodraw import OfficeArtBStoreDelay, PictureNode class PPT(object): def __init__(self, picturesStream): self.picturesStream = picturesStream def pictures(self): pictures = [] vfile = self.picturesStream.open() try : oabsc = OfficeArtBStoreDelay(vfile) except : vfile.close() raise vfile.close() for blip in oabsc.blips: pictures.append((blip.offset, blip.size, self.picturesStream)) return pictures def createPictureNodes(self): pictures = self.pictures() count = 1 for offset, size, node in pictures: PictureNode(node, offset, size, count) count += 1 dff-1.3.0+dfsg.1/dff/modules/metadata/lnk/000077500000000000000000000000001217176075400201155ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/metadata/lnk/CMakeLists.txt000066400000000000000000000011511217176075400226530ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py lnk.py lnkheader.py lnkitem.py ) dff-1.3.0+dfsg.1/dff/modules/metadata/lnk/__init__.py000066400000000000000000000000001217176075400222140ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/metadata/lnk/lnk.py000066400000000000000000000357601217176075400212660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __dff_module_lnk_version__ = "1.0.0" from struct import unpack from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.module.manager import ModuleProcessusHandler from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime, TIME_MS_64 from dff.api.vfs.libvfs import AttributesHandler, VFS, VLink from dff.modules.structparser import Struct, Header, FlagsList, ResolveAttributesMap, AttributesVMap from dff.modules.lnk.lnkheader import FileAttributesFlags, LinkFlags, ShowCommandFlagsMap, HotKeysLowFlagsMap, HotKeysHighFlagsMap, LinkInfoFlags, DriveTypeMaps, NetworkProviderType, CommonNetworkRelativeLinkFlags, ExtraDataBlockMaps, FillAttributesFlags, FontFamily, PropertyType, PropertyTypeConverter, SerializedPropertyHeader, DataBlockHeader, ShellLinkHeader, LPWSTR, LnkAttributesMap from dff.modules.lnk.lnkitem import ItemType, ItemTypeConverter, UnicodeBuff, UUID import sys, os, traceback class LNKParser(): def __init__(self, node): try: self.node = node self.vfile = node.open() self.header = Header(ShellLinkHeader) self.vfile.seek(0) self.data = self.vfile.read(self.header.ShellLinkHeader.ssize) self.shellLink = Struct(self.header, self.vfile, self.header.ShellLinkHeader, self.data) self.shellLink.FileAttributes = FlagsList(self.shellLink.FileAttributes, FileAttributesFlags) self.shellLink.LinkFlags = FlagsList(self.shellLink.LinkFlags, LinkFlags) self.shellLink.LinkCLSID = UUID(self.shellLink.LinkCLSID) try : self.shellLink.ShowCommand = ShowCommandFlagsMap[self.shellLink.ShowCommand] except KeyError: self.shellLink.ShowCommand = str(hex(self.shellLink.ShowCommand)) if ("HasLinkTargetIDList",str) in self.shellLink.LinkFlags: self.getLinkTargetIDList() if ("HasLinkInfo", str) in self.shellLink.LinkFlags: self.getLinkInfo() for dataName in ("HasName", "HasRelativePath", "HasWorkingDir", "HasArguments", "HasIconLocation"): self.readStringData(dataName) if self.vfile.tell() < self.vfile.node().size(): self.getDataBlock() self.vfile.close() except : err_type, err_value, err_traceback = sys.exc_info() print traceback.format_exception_only(err_type, err_value) print traceback.format_tb(err_traceback) self.vfile.close() def getLinkInfo(self): linkInfoStartOffset = self.vfile.tell() self.data = self.vfile.read(self.header.LinkInfo.ssize) self.linkInfo = Struct(self.header, self.vfile, self.header.LinkInfo, self.data) self.linkInfoAttr = {} self.linkInfoAttr["Link info header size"] = (self.linkInfo.HeaderSize, int) self.linkInfo.Flags = FlagsList(self.linkInfo.Flags, LinkInfoFlags) self.linkInfoAttr["Link info flags"] = (self.linkInfo.Flags, list) if ("VolumeIDAndLocalBasePath", str) in self.linkInfo.Flags: self.vfile.seek(linkInfoStartOffset + self.linkInfo.VolumeIDOffset) sizeMax = self.linkInfo.StructSize - self.vfile.tell() + linkInfoStartOffset buff = self.vfile.read(sizeMax) VolumeIDStruct = Struct(self.header, self.vfile, self.header.VolumeID, buff) VolumeIDAttr = {} try : VolumeIDAttr["Drive type"] = (DriveTypeMaps[VolumeIDStruct.DriveType], str) except KeyError: pass VolumeIDAttr["Drive serial number"] = (VolumeIDStruct.DriveSerialNumber, int) if VolumeIDStruct.LabelOffset != 0x14: pos = buff[VolumeIDStruct.LabelOffset:].find('\x00') if pos != -1: VolumeIDAttr["Volume label"] = (buff[VolumeIDStruct.LabelOffset:VolumeIDStruct.LabelOffset+pos+1], str) else: LabelOffsetUnicode = buff[16:20] VolumeIDAttr["Volume label (Unicode)"]= (UnicodeBuff(buff[LabelOffsetUnicode:]), str) if len(VolumeIDAttr): self.linkInfoAttr["Volume ID"] = (VolumeIDAttr, dict) self.vfile.seek(linkInfoStartOffset + self.linkInfo.LocalBasePathOffset) sizeMax = self.linkInfo.StructSize - self.vfile.tell() + linkInfoStartOffset buff = self.vfile.read(sizeMax) pos = buff.find('\x00') if pos != -1: self.linkInfoAttr["Local base path"] = (buff[:pos], str) if self.linkInfo.HeaderSize >= 0x24: self.vfile.seek(linkInfoStartOffset + self.linkInfo.LocalBasePathUnicode) sizeMax = self.linkInfo.StructSize - self.vfile.tell() + linkInfoStartOffset buff = self.vfile.read(sizeMax) self.linkInfoAttr["Local base path (Unicode)"] = (UnicodeBuff(buff), str) elif ("CommonNetworkRelativeLinkAndPathSuffix", str) in self.linkInfo.Flags: self.vfile.seek(linkInfoStartOffset + self.linkInfo.CommonNetworkRelativeLinkOffset) sizeMax = self.linkInfo.StructSize - self.vfile.tell() + linkInfoStartOffset buff = self.vfile.read(sizeMax) CommonNetworkRelativeLinkStruct = Struct(self.header, self.vfile, self.header.CommonNetworkRelativeLink, buff) CommonNetworkRelativeLinkAttr = {} CommonNetworkRelativeLinkStruct.LinkFlags = FlagsList(CommonNetworkRelativeLinkStruct.LinkFlags, CommonNetworkRelativeLinkFlags) CommonNetworkRelativeLinkAttr["Link flags"] = (CommonNetworkRelativeLinkStruct.LinkFlags, list) if ("ValidDevice", str) in CommonNetworkRelativeLinkStruct.LinkFlags: #XXX UNTESTED if CommonNetworkRelativeLinkStruct.NetNameOffset > 0x14: DeviceNameUnicodeOffset = unpack("I", buff[24:28])[0] pos = buff[DeviceNameUnicodeOffset:].find('\x00\x00') if pos != -1: CommonNetworkRelativeLinkAttr["Deivce name (unicode)"] = (unicode(buff[DeviceNameUnicodeOffset:DeviceNameUnicodeOffset+pos+3].decode('UTF-16')), str) else: pos = buff[CommonNetworkRelativeLinkStruct.DeviceNameOffset:].find('\x00') if pos != -1: CommonNetworkRelativeLinkAttr["Device name"] = (buff[CommonNetworkRelativeLinkStruct.DeviceNameOffset:CommonNetworkRelativeLinkStruct.DeviceNameOffset + pos+1], str) if ("ValidNetType", str) in CommonNetworkRelativeLinkStruct.LinkFlags: if CommonNetworkRelativeLinkStruct.NetNameOffset > 0x14: NetNameUnicodeOffset = unpack("I", buff[20:24])[0] pos = buff[NetNameUnicodeOffset:].find('\x00\x00') if pos != -1: CommonNetworkRelativeLinkAttr["Net name (unicode)"] = (unicode(buff[NetNameUnicodeOffset:NetNameUnicodeOffset+pos+3].decode('UTF-16')), str) else: pos = buff[CommonNetworkRelativeLinkStruct.NetNameOffset:].find('\x00') if pos != -1: CommonNetworkRelativeLinkAttr["Net name"] = (buff[CommonNetworkRelativeLinkStruct.NetNameOffset:CommonNetworkRelativeLinkStruct.NetNameOffset + pos+1], str) try: CommonNetworkRelativeLinkAttr["Provider type"] = (NetworkProviderType[CommonNetworkRelativeLinkStruct.NetworkProviderType], str) except KeyError: CommonNetworkRelativeLinkAttr["Provider type"] = (CommonNetworkRelativeLinkStruct.NetworkProviderType, int) self.vfile.seek(linkInfoStartOffset + self.linkInfo.CommonPathSuffixOffset) sizeMax = self.linkInfo.StructSize - self.vfile.tell() + linkInfoStartOffset buff = self.vfile.read(sizeMax) pos = buff.find('\x00') if pos != -1: self.linkInfoAttr["Common path suffix"] = (buff[:pos], str) if self.linkInfo.HeaderSize >= 0x24: pass #print "get unicode common suffix " if len(CommonNetworkRelativeLinkAttr): self.linkInfoAttr["Common network relative link"] = (CommonNetworkRelativeLinkAttr, dict) self.vfile.seek(linkInfoStartOffset + self.linkInfo.StructSize) def getLinkTargetIDList(self): self.vfile.seek(self.header.ShellLinkHeader.ssize) idListSize = unpack("H", self.vfile.read(2))[0] count = 0 idcount = 1 self.linkTargetIDList = {} while count < idListSize: ItemIDSize = unpack("H", self.vfile.read(2))[0] if ItemIDSize == 0: break IDdata = self.vfile.read(ItemIDSize - 2) IDtype = unpack("B", IDdata[0:1])[0] try : IDtypeName = ItemType[IDtype] isUnicode = ("IsUnicode", str) in self.shellLink.LinkFlags self.linkTargetIDList["ID(" + str(idcount) + ") " + str(IDtypeName)] = ItemTypeConverter[IDtypeName](IDdata, isUnicode) except : #complkete pass #err_type, err_value, err_traceback = sys.exc_info() #print traceback.format_exception_only(err_type, err_value) #print traceback.format_tb(err_traceback) #print "ID LIST TYPE NOT PARSED " + str(hex(IDtype)) + ' ' + str(self.node.absolute()) + ' ' + str(idcount) + ' offset ' + str(hex(self.vfile.tell() - len(IDdata))) + ' ' + str(len(IDdata)) idcount += 1 count += ItemIDSize def getDataBlock(self): dataBlockHeader = Header(DataBlockHeader) pos = None while (self.vfile.tell() < self.vfile.node().size() - 4) and (pos != self.vfile.tell()): pos = self.vfile.tell() data = self.vfile.read(dataBlockHeader.DataBlockStandard.ssize) standard = Struct(dataBlockHeader, self.vfile, dataBlockHeader.DataBlockStandard, data) try: self.vfile.seek(pos) dataBlockType = ExtraDataBlockMaps[standard.BlockSignature] data = self.vfile.read(standard.BlockSize) try: setattr(self, dataBlockType, Struct(dataBlockHeader, self.vfile, getattr(dataBlockHeader, dataBlockType), data)) if dataBlockType == 'ConsoleDataBlock': self.ConsoleDataBlock.FillAttributes = FlagsList(self.ConsoleDataBlock.FillAttributes, FillAttributesFlags) self.ConsoleDataBlock.PopupFillAttributes = FlagsList(self.ConsoleDataBlock.PopupFillAttributes, FillAttributesFlags) try : self.ConsoleDataBlock.FontFamily = FontFamily[self.ConsoleDataBlock.FontFamily] except KeyError: pass self.ConsoleDataBlock.FaceName = UnicodeBuff(self.ConsoleDataBlock.FaceName) if dataBlockType == 'TrackerDataBlock': self.TrackerDataBlock.DroidVolume = UUID(self.TrackerDataBlock.DroidVolume) self.TrackerDataBlock.DroidFile = UUID(self.TrackerDataBlock.DroidFile) self.TrackerDataBlock.DroidBirthVolume = UUID(self.TrackerDataBlock.DroidBirthVolume) self.TrackerDataBlock.DroidBirthFile = UUID(self.TrackerDataBlock.DroidBirthFile) #elif windowsvsita... #elif shindataBLock elif dataBlockType == 'EnvironmentVariableDataBlock': self.EnvironmentVariableDataBlock.TargetUnicode = UnicodeBuff(self.EnvironmentVariableDataBlock.TargetUnicode) elif dataBlockType == 'IconEnvironmentDataBlock': self.IconEnvironmentDataBlock.Environment.TargetUnicode = UnicodeBuff(self.IconEnvironmentDataBlock.Environment.TargetUnicode) elif dataBlockType == 'DarwinDataBlock': self.DarwinDataBlock.DataUnicode = UnicodeBuff(self.DarwinDataBlock.DataUnicode) elif dataBlockType == 'KnownFolderDataBlock': self.KnownFolderDataBlock.ID = UUID(self.KnownFolderDataBlock.ID) elif dataBlockType == 'PropertyStoreDataBlock': serializedPropertyHeader = Header(SerializedPropertyHeader) self.PropertyStoreSerializedAttr = {} while len(data) >= 32: self.PropertyStoreDataBlock.Property.FormatID = UUID(self.PropertyStoreDataBlock.Property.FormatID) if self.PropertyStoreDataBlock.Property.StorageSize and len(data) > 40: if self.PropertyStoreDataBlock.Property.FormatID != "D5CDD505-2E9C-101B-9397-08002B2CF9AE": serializedPropertyData = data[32:] IntegerName = Struct(serializedPropertyHeader, self.vfile, serializedPropertyHeader.IntegerName, serializedPropertyData) try: value = 'Undef Type' value = PropertyType[IntegerName.TypedValue.Type] value = PropertyTypeConverter[value](serializedPropertyData[13:]) except KeyError: pass self.PropertyStoreSerializedAttr[str(IntegerName.Id)] = (value, str) data = data[self.PropertyStoreDataBlock.Property.StorageSize:] if len(data) >= 32: setattr(self, dataBlockType, Struct(dataBlockHeader, self.vfile, getattr(dataBlockHeader, dataBlockType), data)) else: break else: #StringType break else: break except AttributeError, e: break #avoid infinite loop, possibly skip decodable data block except KeyError, e: if (dataBlockHeader.DataBlockStandard.ssize == 0) or (standard.BlockSize == 0): break def readStringData(self, dataName): if (dataName, str) in self.shellLink.LinkFlags: size = unpack("H", self.vfile.read(2))[0] if size: Name = dataName.replace('Has', '') if ("IsUnicode", str) in self.shellLink.LinkFlags: data = unicode(self.vfile.read(size*2).decode('UTF-16')) else: data = self.vfile.read(size) setattr(self, Name, data) if Name == "RelativePath": n = VFS.Get().GetNode(self.node.parent().absolute() + '/' + data.encode('UTF-8').replace('\\', '/')) if n: #This create a subnode with a link #vl = VLink(n, self.node) #vl.thisown = False setattr(self, "RelativePathLink", n) def attributesMap(self): try: return ResolveAttributesMap(self, LnkAttributesMap) except: pass class LNKHandler(AttributesHandler, ModuleProcessusHandler): def __init__(self): AttributesHandler.__init__(self, "lnk") ModuleProcessusHandler.__init__(self, "lnk") self.__disown__() self.nodeAttributes = {} self.vfs = VFS.Get() def setAttributes(self, node, attributes): self.nodeAttributes[long(node.this)] = attributes def update(self, processus): pass def nodes(self, root): nodes = [] rootAbsolute = root.absolute() for node in self.nodeAttributes.keys(): node = self.vfs.getNodeFromPointer(node) if node.absolute().find(rootAbsolute) == 0: nodes.append(node) return nodes def attributes(self, node): try: attr = self.nodeAttributes[long(node.this)] return AttributesVMap(attr) except KeyError: attr = VMap() return attr class LNK(Script): def __init__(self): Script.__init__(self, "lnk") self.handler = LNKHandler() def start(self, args): try: node = args['file'].value() p = LNKParser(node) arg = p.attributesMap() self.handler.setAttributes(node, arg) node.registerAttributes(self.handler) except (KeyError, Exception): pass class lnk(Module): """This modules generate metadata for lnk files as attributes""" def __init__(self): Module.__init__(self, "lnk", LNK) self.conf.addArgument({"name": "file", "description": "file to extract metadata", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "compatible extension", "values": ["MS Windows shortcut"]}) self.flags = ["single"] self.tags = "Metadata" self.icon = ":lnk" dff-1.3.0+dfsg.1/dff/modules/metadata/lnk/lnkheader.py000066400000000000000000000362421217176075400224330ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from struct import unpack from dff.api.vfs.libvfs import VLink from dff.api.types.libtypes import vtime, TIME_MS_64 class LPWSTR(): def __init__(self, data): size = unpack('I', data[0:4])[0] self.data = unicode(data[4:4+size*2]) self.length = 4 + (size * 2) def __str__(self): return self.data.decode('UTF-16') def __len__(self): return (self.length) FileAttributesFlags = [ "FILE_ATTRIBUTE_READONLY", "FILE_ATTRIBUTE_HIDDEN", "FILE_ATTRIBUTE_SYSTEM", "Reserved1", "FILE_ATTRIBUTE_DIRECTORY", "FILE_ATTRIBUTE_ARCHIVE", "Reserved2", "FILE_ATTRIBUTE_NORMAL", "FILE_ATTRIBUTE_TEMPORARY", "FILE_ATTRIBUTE_SPARSE_FILE", "FILE_ATTRIBUTE_REPARSE_POINT", "FILE_ATTRIBUTE_COMPRESSED", "FILE_ATTRIBUTE_OFFLINE", "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED", "FILE_ATTRIBUTE_ENCRYPTED"] LinkFlags = [ "HasLinkTargetIDList", "HasLinkInfo", "HasName", "HasRelativePath", "HasWorkingDir", "HasArguments", "HasIconLocation", "IsUnicode", "ForceNoLinkInfo", "HasExpString", "RunInSeparateProcess", "Unused1", "HasDarwinID", "RunAsUser", "HasExpIcon", "NoPidlAlias", "Unused2", "RunWithShimLayer", "ForceNoLinkTrack", "EnableTargetMetadata", "DisableLinkPathTracking", "DisableKnownFolderTracking", "DisableKnownFolderAlias", "AllowLinkToLink", "UnaliasOnSave", "PreferEnvironmentPath", "KeepLocalIDListForUNCTarget" ] ShowCommandFlagsMap = { 0x1 : "SW_SHOWNORMAL", 0x3 : "SW_SHOWMAXIMIZED", 0x7 : "SW_SHOWMINNOACTIVE" } HotKeysLowFlagsMap = { 0x30 : "0", 0x31 : "1", 0x32 : "2", 0x33 : "3", 0x34 : "4", 0x35 : "5", 0x36 : "6", 0x37 : "7", 0x38 : "8", 0x39 : "9", 0x41 : "A", 0x42 : "B", 0x43 : "C", 0x44 : "D", 0x45 : "E", 0x46 : "F", 0x47 :"G", 0x48 : "H", 0x49 : "I", 0x4A : "J", 0x4B : "K", 0x4C : "L", 0x4D : "M", 0x4E : "N", 0x4F : "O", 0x50 : "P", 0x51 : "Q", 0x52 : "R", 0x53 : "S", 0x54 : "T", 0x55 : "U", 0x56 : "V", 0x57 : "W", 0x58 : "X", 0x59 : "Y", 0x5A : "Z", 0x70 : "F1", 0x71 : "F2", 0x72 : "F3", 0x73 : "F4", 0x74 : "F5", 0x75 : "F6", 0x76 : "F7", 0x77 : "F8", 0x78 : "F9", 0x79 : "F10", 0x7A : "F11", 0x7B : "F12", 0x7C : "F13", 0x7D : "F14", 0x7E : "F15", 0x7F : "F16", 0x80 : "F17", 0x81 : "F18", 0x82 : "F19", 0x83 : "F20", 0x84 : "F21", 0x85 : "F22", 0x86 : "F23", 0x87 : "F24", 0x90 : "NUM LOCK", 0x91 : "SCROLL LOCK" } HotKeysHighFlagsMap = { 0x1 : "HOTKEYF_SHIFT", 0x2 : "HOTKEYF_CONTROL", 0x4 : "HOTKEYF_ALT" } LinkInfoFlags = [ "VolumeIDAndLocalBasePath", "CommonNetworkRelativeLinkAndPathSuffix"] DriveTypeMaps = { 0x0 : "DRIVE_UNKNOWN", 0x1 : "DRIVE_NO_ROOT_DIR", 0x2 : "DRIVE_REMOVABLE", 0x3 : "DRIVE_FIXED", 0x4 : "DRIVE_REMOTE", 0x5 : "DRIVE_CDROM", 0x6 : "DRIVE_RAMDISK", } NetworkProviderType = { 0x001A0000 : "WNNC_NET_AVID", 0x001B0000 : "WNNC_NET_DOCUSPACE", 0x001C0000 : "WNNC_NET_MANGOSOFT", 0x001D0000 : "WNNC_NET_SERNET", 0X001E0000 : "WNNC_NET_RIVERFRONT1", 0x001F0000 : "WNNC_NET_RIVERFRONT2", 0x00200000 : "WNNC_NET_DECORB", 0x00210000 : "WNNC_NET_PROTSTOR", 0x00220000 : "WNNC_NET_FJ_REDIR", 0x00230000 : "WNNC_NET_DISTINCT", 0x00240000 : "WNNC_NET_TWINS", 0x00250000 : "WNNC_NET_RDR2SAMPLE", 0x00260000 : "WNNC_NET_CSC", 0x00270000 : "WNNC_NET_3IN1", 0x00290000 : "WNNC_NET_EXTENDNET", 0x002A0000 : "WNNC_NET_STAC", 0x002B0000 : "WNNC_NET_FOXBAT", 0x002C0000 : "WNNC_NET_YAHOO", 0x002D0000 : "WNNC_NET_EXIFS", 0x002E0000 : "WNNC_NET_DAV", 0x002F0000 : "WNNC_NET_KNOWARE", 0x00300000 : "WNNC_NET_OBJECT_DIRE", 0x00310000 : "WNNC_NET_MASFAX", 0x00320000 : "WNNC_NET_HOB_NFS", 0x00330000 : "WNNC_NET_SHIVA", 0x00340000 : "WNNC_NET_IBMAL", 0x00350000 : "WNNC_NET_LOCK", 0x00360000 : "WNNC_NET_TERMSRV", 0x00370000 : "WNNC_NET_SRT", 0x00380000 : "WNNC_NET_QUINCY", 0x00390000 : "WNNC_NET_OPENAFS", 0x003A0000 : "WNNC_NET_AVID1", 0x003B0000 : "WNNC_NET_DFS", 0x003C0000 : "WNNC_NET_KWNP", 0x003D0000 : "WNNC_NET_ZENWORKS", 0x003E0000 : "WNNC_NET_DRIVEONWEB", 0x003F0000 : "WNNC_NET_VMWARE", 0x00400000 : "WNNC_NET_RSFX", 0x00410000 : "WNNC_NET_MFILES", 0x00420000 : "WNNC_NET_MS_NFS", 0x00430000 : "WNNC_NET_GOOGLE", } CommonNetworkRelativeLinkFlags = [ "ValidDevice", "ValidNetType"] ExtraDataBlockMaps = { 0xA0000001 : "EnvironmentVariableDataBlock", 0xA0000002 : "ConsoleDataBlock", 0xA0000003 : "TrackerDataBlock", 0xA0000004 : "ConsoleFEDataBlock", 0xA0000005 : "SpecialFolderDataBlock", 0xA0000006 : "DarwinDataBlock", 0xA0000007 : "IconEnvironmentDataBlock", 0xA0000008 : "ShimDataBlock", 0xA0000009 : "PropertyStoreDataBlock", 0xA000000B : "KnownFolderDataBlock", 0xA000000C : "VistaAndAboveIDListDataBlock", } FillAttributesFlags = ["FOREGROUND_BLUE", "FOREGROUND_GREEN", "FOREGROUND_RED", "FOREGROUND_INTENSITY", "BACKGROUND_BLUE", "BACKGROUND_GREEN", "BACKGROUND_RED", "BACKGROUND_INTENSITY"] FontFamily = { 0x0000 : "FF_DONTCARE", 0x0010 : "FF_ROMAN", 0x0020 : "FF_SWISS", 0x0030 : "FF_MODERN", 0x0040 : "FF_SCRIPT", 0x0050 : "FF_DECORATIVE", } PropertyType = { 0x0000 : "VT_EMPTY", 0x0001 : "VT_NULL", 0x0002 : "VT_I2", 0x0003 : "VT_I4", 0x0004 : "VT_R4", 0x0005 : "VT_R8", 0x0006 : "VT_CY", 0x0007 : "VT_DATE", 0x0008 : "VT_BSTR", 0x000A : "VT_ERROR", 0x000B : "VT_BOOL", 0x000E : "VT_DECIMAL", 0x0010 : "VT_I1", 0x0011 : "VT_UI1", 0x0012 : "VT_UI2", 0x0013 : "VT_UI4", 0x0014 : "VT_I8", 0x0015 : "VT_UI8", 0x0016 : "VT_INT", 0x0017 : "VT_UINT", 0x001E : "VT_LPSTR", 0x001F : "VT_LPWSTR", 0x0040 : "VT_FILETIME", 0x0041 : "VT_BLOB", 0x0042 : "VT_STREAM", 0x0043 : "VT_STORAGE", 0x0044 : "VT_STREAMED_OBJECT", 0x0045 : "VT_STORED_OBJECT", 0x0046 : "VT_BLOB_OBJECT", 0x0047 : "VT_CF", 0x0048 : "VT_CLSID", 0x0049 : "VT_VERSIONED_STREAM", 0x1002 : "VT_VECTOR_I2", 0x1000 : "VT_VECTOR", 0x1003 : "VT_VECTOR_I4", 0x1004 : "VT_VECTOR_R4", 0x1005 : "VT_VECTOR_R8", 0x1006 : "VT_VECTOR_CY", 0x1007 : "VT_VECTOR_DATE", 0x1008 : "VT_VECTOR_BSTR", 0x100A : "VT_VECTOR_ERROR", 0x100B : "VT_VECTOR_BOOL", 0x100C : "VT_VECTOR_VARIANT", 0x1010 : "VT_VECTOR_I1", 0x1011 : "VT_VECTOR_U1", 0x1012 : "VT_VECTOR_UI2", 0x1013 : "VT_VECTOR_UI4", 0x1014 : "VT_VECTOR_I8", 0x1015 : "VT_VECTOR_UI8", 0x101E : "VT_VECTOR_LPSTR", 0x101F : "VT_VECTOR_LPWSTR", 0x1040 : "VT_VECTOR_FILETIME", 0x1047 : "VT_VECTOR_CF", 0x1048 : "VT_VECTOR_CLSID", 0x2002 : "VT_ARRAY_I2", 0x2003 : "VT_ARRAY_I4", 0x2004 : "VT_ARRAY_R4", 0x2005 : "VT_ARRAY_R8", 0x2006 : "VT_ARRAY_CY", 0x2007 : "VT_ARRAY_DATA", 0x2008 : "VT_ARRAY_BSTR", 0x200A : "VT_ARRAY_ERROR", 0x200B : "VT_ARRAY_BOOL", 0x200C : "VT_ARRAY_VARIANT", 0x200E : "VT_ARRAY_DECIMAL", 0x2010 : "VT_ARRAY_I1", 0x2011 : "VT_ARRAY_UI1", 0x2012 : "VT_ARRAY_UI2", 0x2013 : "VT_ARRAY_UI4", 0x2016 : "VT_ARRAY_INT", 0x2017 : "VT_ARRAY_UINT" } PropertyTypeConverter = { "VT_LPWSTR" : LPWSTR, "VT_BSTR" : LPWSTR, } SerializedPropertyHeader = ({"info" : { "os":"windows", "arch":"x86", "name":"serialized" }, "descr" : { "IntegerName" : ((13), { "ValueSize" : (4, 0), "Id" : (4, 4), "Reserved" : (1, 8), "TypedValue" : (4, 9, "TypedPropertyValue"), }), "StringName" : ((9), { "ValueSize" : (4, 0), "NameSize" : (4, 4), }), "TypedPropertyValue" : ((4), { "Type" : (2, 0), "Padding" : (2, 2), }), } }) DataBlockHeader = ({"info" : { "os":"windows", "arch":"x86", "name" : "lnkdatablock"}, "descr" : { "DataBlockStandard" : ((8), { "BlockSize" : (4, 0), "BlockSignature" : (4, 4), }), "SpecialFolderDataBlock" : ((0x10), { "Standard" : (8, 0, "DataBlockStandard"), "SpecialFolderID" : (4, 8), "Offset" : (4, 12) }), "TrackerDataBlock" : ((0x60), { "Standard" : (8, 0, "DataBlockStandard"), "Length" : (4, 8), "Version" : (4, 12), "MachineID" : (16, 16), "DroidVolume" : (16, 32), "DroidFile" : (16, 48), "DroidBirthVolume" : (16, 64), "DroidBirthFile" : (16, 80), }), "EnvironmentVariableDataBlock" : ((0x314), { "Standard" : (8, 0, "DataBlockStandard"), "TargetAnsi" : (260, 8), "TargetUnicode" : (520, 268) }), "IconEnvironmentDataBlock" : ((0x314), { "Environment" : (0x314, 0, "EnvironmentVariableDataBlock") }), "DarwinDataBlock" : ((0x314), { "Standard" : (8, 0, "DataBlockStandard"), "DataAnsi" : (260, 8), "DataUnicode" : (520, 268), }), "PropertyStoreDataBlock" : ((32), { "Standard" : (8, 0, "DataBlockStandard"), "Property" : (24, 8, "PropertyStorage"), }), "PropertyStorage" : ((24), { "StorageSize" : (4, 0), "Version" : (4, 4), "FormatID" : (16, 8), }), "KnownFolderDataBlock" : ((28), { "Standard" : (8, 0, "DataBlockStandard"), "ID" : (16, 8), "Offset" : (4, 24), }), "ConsoleDataBlock" : ((0xcc), { "Standard" : (8, 0, "DataBlockStandard"), "FillAttributes" : (2, 8), "PopupFillAttributes" : (2, 10), "ScreenBufferSizeX" : (2, 12), "ScreenBufferSizeY" : (2, 14), "WindowSizeX" : (2, 16), "WindowSizeY" : (2, 18), "WindowOriginX" : (2, 20), "WindowOriginY" : (2, 22), "Unused1" : (4, 24), "Unused2" : (4, 28), "FontSize" : (4, 32), "FontFamily" : (4, 36), "FontWeight" : (4, 40), "FaceName" : (64, 44), "CursorSize" : (4, 108), "FullScreen" : (4, 112), "QuickEdit" : (4, 116), "InsertMode" : (4, 120), "AutoPosition" : (4, 124), "HistoryBufferSize" : (4, 128), "NumberOfHistoryBuffers" : (4, 132), "HistoryNoDup" : (4, 136), "ColorTable" : (64, 140), }), } }) ShellLinkHeader = ({"info" : { "os":"windows", "arch":"x86", "name" : "lnk"}, "descr" : { "ShellLinkHeader" : ((0x4c), { "HeaderSize" : (4, 0), "LinkCLSID" : (16, 4), "LinkFlags" : (4, 20), "FileAttributes" : (4, 24), "CreationTime" : (8, 28), "AccessTime" : (8, 36), "WriteTime" : (8, 44), "FileSize" : (4, 52), "IconIndex" : (4, 56), "ShowCommand" : (4, 60), "HotKey" : (2, 64), "Reserved1" : (2, 66), "Reserved2" : (4, 68), "Reserved3" : (4, 72) }), "LinkInfo" : ((0x1c), { "StructSize" : (4, 0), "HeaderSize" : (4,4), "Flags" : (4, 8), "VolumeIDOffset" : (4, 12), "LocalBasePathOffset" : (4, 16), "CommonNetworkRelativeLinkOffset" : (4, 20), "CommonPathSuffixOffset" : (4, 24) }), "VolumeID" : ((16), { "Size" : (4, 0), "DriveType" : (4, 4), "DriveSerialNumber" : (4, 8), "LabelOffset" : (4, 12), }), "CommonNetworkRelativeLink" : ((20), { "Size" : (4, 0), "LinkFlags" : (4, 4), "NetNameOffset" : (4,8), "DeviceNameOffset" : (4, 12), "NetworkProviderType" : (4, 16), }) } }) LnkAttributesMap = { "Name" : ("Name", str), "RelativePath" : ("RelativePath", str), "RelativePathLink" : ("RelativePathLink", VLink), "WorkingDir" : ("WorkingDir", str), "Arguments" : ("Arguments", str), "IconLocation" : ("IconLocation", str), "HeaderSize": ("shellLink.HeaderSize", int), "LinkCLSID" : ("shellLink.LinkCLSID", str), "LinkFlags" : ("shellLink.LinkFlags", list), "FileAttributes": ("shellLink.FileAttributes", list), "CreationTime" : (("shellLink.CreationTime", TIME_MS_64,), vtime), "AccessTime" : (("shellLink.AccessTime", TIME_MS_64,), vtime), "WriteTime" : (("shellLink.WriteTime", TIME_MS_64,), vtime), "FileSize" : ("shellLink.FileSize", int), "IconIndex" : ("shellLink.IconIndex", int), "ShowCommand" : ("shellLink.ShowCommand", str), "HotKey": ("shellLink.HotKey", int), "Reserved1" : ("shellLink.Reserved1", int), "Reserved2" : ("shellLink.Reserved2", int), "Reserved3" : ("shellLink.Reserved3", int), "LinkTargetID" : ("linkTargetIDList", dict), "Link info" : ("linkInfoAttr", dict), "Special Folder Data Block": { "Special folder id" : ("SpecialFolderDataBlock.SpecialFolderID", int) }, "Tracker Data Block": { "Machine ID" : ("TrackerDataBlock.MachineID", str), "Droid Volume" : ("TrackerDataBlock.DroidVolume", str), "Droid File" : ("TrackerDataBlock.DroidFile", str), "Droid Birth Volume" : ("TrackerDataBlock.DroidBirthVolume", str), "Droid Birth File" : ("TrackerDataBlock.DroidBirthFile", str), }, "Environment Variable Data Block": { "Target Ansi" : ("EnvironmentVariableDataBlock.TargetAnsi", str), "Target Unicode" : ("EnvironmentVariableDataBlock.TargetUnicode", str), }, "Icon Environment Data Block": { "Target Ansi" : ("IconEnvironmentDataBlock.Environment.TargetAnsi", str), "Target Unicode": ("IconEnvironmentDataBlock.Environment.TargetUnicode", str), }, "Dariwn Data Block": { "Darwin Data Ansi" : ("DarwinDataBlock.DataAnsi", str), "Darwin Data Unicode" : ("DarwinDataBlock.DataUnicode", str), }, "Property Store Data Block" : ("PropertyStoreSerializedAttr", dict), "Known Folder Data Block" : { "ID" : ("KnownFolderDataBlock.ID", str) }, "Console Data Block" : { "Fill Attributes" : ("ConsoleDataBlock.FillAttributes", list), "Popup Fill Attributes" : ("ConsoleDataBlock.PopupFillAttributes", list), "Screen Buffer Size X" : ("ConsoleDataBlock.ScreenBufferSizeX", int), "Screen Buffer Size Y": ("ConsoleDataBlock.ScreenBufferSizeY", int), "Window Size X" : ("ConsoleDataBlock.WindowSizeX", int), "Window Size Y" : ("ConsoleDataBlock.WindowSizeY", int), "Window Origin X" : ("ConsoleDataBlock.WindowOriginX", int), "Window Origin Y" : ("ConsoleDataBlock.WindowOriginY", int), "Font Size" : ("ConsoleDataBlock.FontSize", int), "Font Family" : ("ConsoleDataBlock.FontFamily", str), "Font Weight" : ("ConsoleDataBlock.FontWeight", int), "Face Name" : ("ConsoleDataBlock.FaceName", str), "Cursor Size" : ("ConsoleDataBlock.CursorSize", int), "Full Screen" : ("ConsoleDataBlock.FullScreen", int), "Quick Edit" : ("ConsoleDataBlock.QuickEdit", int), "Insert Mode" : ("ConsoleDataBlock.InsertMode", int), "Auto Position" : ("ConsoleDataBlock.AutoPosition", int), "History Buffer Size" : ("ConsoleDataBlock.HistoryBufferSize", int), "Number Of History Buffers" : ("ConsoleDataBlock.NumberOfHistoryBuffers", int), "History No Dup" : ("ConsoleDataBlock.HistoryNoDup", int), }, } dff-1.3.0+dfsg.1/dff/modules/metadata/lnk/lnkitem.py000066400000000000000000000157321217176075400221420ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob from struct import unpack from dff.api.types.libtypes import vtime, TIME_MS_64 from dff.modules.structparser import FlagsList from lnkheader import FileAttributesFlags ItemType = { 0x1F: "GUID", 0x23: "Drive", 0x25: "Drive", 0x29: "Drive", 0x2E: "Shell Extension", 0x2F: "Drive", 0x30: "Directory", 0x31: "Directory", 0x32: "File", 0x34: "File Unicode", 0x35: "File Unicode", 0x36: "File Unicode", 0x41: "Workgroup", 0x42: "Computer", 0x46: "Net Provider", 0x47: "Whole Network", 0x4C: "Web Folder", 0x61: "MSITStore", 0x70: "Printer/RAS Connection", 0xB1: "History/Favorite", 0xC3: "Network Share", } def UnicodeBuff(buff): pos = buff.find('\x00\x00') while pos != -1: if pos % 2: pos = buff.find('\x00\x00',pos+1) else: return unicode(buff[:pos], 'UTF-16') return None def ShortSizeString(data, isUnicode = True): size = unpack("H", data[0:2])[0] if isUnicode: return (unicode(data[2:(size*2 + 2)], 'UTF-16'), size*2 + 4) else: return (data[2:size+1], size + 3) def ItemFileUnicode(data, isUnicode = True): directoryMap = {} #directoryMap["ID type"] = (IDtype, int) size = unpack("I", data[2:6])[0] if size: directoryMap["size"] = (size, int) time, date = unpack("HH", data[6:10]) directoryMap["modified time"] = ((date, time,), vtime) #XXX modified time ? directoryMap["File attributes"] = (FlagsList(unpack("H", data[10:12])[0], FileAttributesFlags), list) data = data[12:] pos = data.find('\x03\x00\x04\x00') #Serves as end of string marker ? if pos: name = unicode(data[:pos-2], 'UTF-16') directoryMap["name"] = (name, str) data = data[pos-2:] if isUnicode: if len(data) % 2: data = data[1:] raw_bytes = unpack("6B", data[2:8]) #ENF OF UNICODE STR ??\03\00\04\00 time, date = unpack("HH", data[8:12]) directoryMap["creation time"] = ((date, time,), vtime) time, date = unpack("HH", data[12:16]) directoryMap["access time"] = ((date, time,), vtime) length_next = unpack("H", data[18:20])[0] unicode_name = UnicodeBuff(data[20:]) directoryMap["unicode name"] = (unicode_name, str) data = data[20+len(unicode_name)*2+2:] if length_next: pos = data.find('\x00') localized_name = data[:pos] ##XXX May have 2 or more strings ? directoryMap["localized name"] = (localized_name, str) else: if len(data) > 1: pos = data.find('\x00') directoryMap["short name"] = (data[:pos], str) return (directoryMap, dict) def ItemDirectory(data, isUnicode = True): directoryMap = {} size = unpack("I", data[2:6])[0] if size: directoryMap["size"] = (size, int) time, date = unpack("HH", data[6:10]) directoryMap["modified time"] = ((date, time,), vtime) #XXX modified time ? directoryMap["File attributes"] = (FlagsList(unpack("H", data[10:12])[0], FileAttributesFlags), list) pos = data[12:].find('\x00') if pos != -1: name = data[12:12+pos] data = data[12+pos+1:] directoryMap["name"] = (name, str) if isUnicode: if len(data) % 2: data = data[1:] raw_bytes = unpack("6B", data[2:8]) #ENF OF UNICODE STR ??\03\00\04\00 time, date = unpack("HH", data[8:12]) directoryMap["creation time"] = ((date, time,), vtime) time, date = unpack("HH", data[12:16]) directoryMap["access time"] = ((date, time,), vtime) length_next = unpack("H", data[18:20])[0] unicode_name = UnicodeBuff(data[20:]) directoryMap["unicode name"] = (unicode_name, str) data = data[20+len(unicode_name)*2+2:] if length_next: pos = data.find('\x00') localized_name = data[:pos] ##XXX May have 2 or more strings ? directoryMap["localized name"] = (localized_name, str) else: if len(data) > 1: pos = data.find('\x00') directoryMap["short name"] = (data[:pos], str) return (directoryMap, dict) def ItemDrive(data, isUnicode = True): #if isUnicode: #return (unicode(data[1:]), str) #else: pos = data[1:].find('\x00') if pos != -1: return (data[1:], str) return ('', str) def ItemWebFolder(data, isUnicode = True): idmap = {} data = data[6:] tm = unpack(" install_file( __init__.py metaexif.py EXIF.py ) dff-1.3.0+dfsg.1/dff/modules/metadata/metaexif/EXIF.py000077500000000000000000001676121217176075400222600ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # Library to extract EXIF information from digital camera image files # http://sourceforge.net/projects/exif-py/ # # VERSION 1.1.0 # # To use this library call with: # f = open(path_name, 'rb') # tags = EXIF.process_file(f) # # To ignore MakerNote tags, pass the -q or --quick # command line arguments, or as # tags = EXIF.process_file(f, details=False) # # To stop processing after a certain tag is retrieved, # pass the -t TAG or --stop-tag TAG argument, or as # tags = EXIF.process_file(f, stop_tag='TAG') # # where TAG is a valid tag name, ex 'DateTimeOriginal' # # These 2 are useful when you are retrieving a large list of images # # # To return an error on invalid tags, # pass the -s or --strict argument, or as # tags = EXIF.process_file(f, strict=True) # # Otherwise these tags will be ignored # # Returned tags will be a dictionary mapping names of EXIF tags to their # values in the file named by path_name. You can process the tags # as you wish. In particular, you can iterate through all the tags with: # for tag in tags.keys(): # if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', # 'EXIF MakerNote'): # print "Key: %s, value %s" % (tag, tags[tag]) # (This code uses the if statement to avoid printing out a few of the # tags that tend to be long or boring.) # # The tags dictionary will include keys for all of the usual EXIF # tags, and will also include keys for Makernotes used by some # cameras, for which we have a good specification. # # Note that the dictionary keys are the IFD name followed by the # tag name. For example: # 'EXIF DateTimeOriginal', 'Image Orientation', 'MakerNote FocusMode' # # Copyright (c) 2002-2007 Gene Cash All rights reserved # Copyright (c) 2007-2008 Ianaré Sévi All rights reserved # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # 3. Neither the name of the authors nor the names of its contributors # may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # ----- See 'changes.txt' file for all contributors and changes ----- # # # Don't throw an exception when given an out of range character. def make_string(seq): str = '' for c in seq: # Screen out non-printing characters if 32 <= c and c < 256: str += chr(c) # If no printing chars if not str: return seq return str # Special version to deal with the code in the first 8 bytes of a user comment. # First 8 bytes gives coding system e.g. ASCII vs. JIS vs Unicode def make_string_uc(seq): code = seq[0:8] seq = seq[8:] # Of course, this is only correct if ASCII, and the standard explicitly # allows JIS and Unicode. return make_string(seq) # field type descriptions as (length, abbreviation, full name) tuples FIELD_TYPES = ( (0, 'X', 'Proprietary'), # no such type (1, 'B', 'Byte'), (1, 'A', 'ASCII'), (2, 'S', 'Short'), (4, 'L', 'Long'), (8, 'R', 'Ratio'), (1, 'SB', 'Signed Byte'), (1, 'U', 'Undefined'), (2, 'SS', 'Signed Short'), (4, 'SL', 'Signed Long'), (8, 'SR', 'Signed Ratio'), ) # dictionary of main EXIF tag names # first element of tuple is tag name, optional second element is # another dictionary giving names to values EXIF_TAGS = { 0x0100: ('ImageWidth', ), 0x0101: ('ImageLength', ), 0x0102: ('BitsPerSample', ), 0x0103: ('Compression', {1: 'Uncompressed', 2: 'CCITT 1D', 3: 'T4/Group 3 Fax', 4: 'T6/Group 4 Fax', 5: 'LZW', 6: 'JPEG (old-style)', 7: 'JPEG', 8: 'Adobe Deflate', 9: 'JBIG B&W', 10: 'JBIG Color', 32766: 'Next', 32769: 'Epson ERF Compressed', 32771: 'CCIRLEW', 32773: 'PackBits', 32809: 'Thunderscan', 32895: 'IT8CTPAD', 32896: 'IT8LW', 32897: 'IT8MP', 32898: 'IT8BL', 32908: 'PixarFilm', 32909: 'PixarLog', 32946: 'Deflate', 32947: 'DCS', 34661: 'JBIG', 34676: 'SGILog', 34677: 'SGILog24', 34712: 'JPEG 2000', 34713: 'Nikon NEF Compressed', 65000: 'Kodak DCR Compressed', 65535: 'Pentax PEF Compressed'}), 0x0106: ('PhotometricInterpretation', ), 0x0107: ('Thresholding', ), 0x010A: ('FillOrder', ), 0x010D: ('DocumentName', ), 0x010E: ('ImageDescription', ), 0x010F: ('Make', ), 0x0110: ('Model', ), 0x0111: ('StripOffsets', ), 0x0112: ('Orientation', {1: 'Horizontal (normal)', 2: 'Mirrored horizontal', 3: 'Rotated 180', 4: 'Mirrored vertical', 5: 'Mirrored horizontal then rotated 90 CCW', 6: 'Rotated 90 CW', 7: 'Mirrored horizontal then rotated 90 CW', 8: 'Rotated 90 CCW'}), 0x0115: ('SamplesPerPixel', ), 0x0116: ('RowsPerStrip', ), 0x0117: ('StripByteCounts', ), 0x011A: ('XResolution', ), 0x011B: ('YResolution', ), 0x011C: ('PlanarConfiguration', ), 0x011D: ('PageName', make_string), 0x0128: ('ResolutionUnit', {1: 'Not Absolute', 2: 'Pixels/Inch', 3: 'Pixels/Centimeter'}), 0x012D: ('TransferFunction', ), 0x0131: ('Software', ), 0x0132: ('DateTime', ), 0x013B: ('Artist', ), 0x013E: ('WhitePoint', ), 0x013F: ('PrimaryChromaticities', ), 0x0156: ('TransferRange', ), 0x0200: ('JPEGProc', ), 0x0201: ('JPEGInterchangeFormat', ), 0x0202: ('JPEGInterchangeFormatLength', ), 0x0211: ('YCbCrCoefficients', ), 0x0212: ('YCbCrSubSampling', ), 0x0213: ('YCbCrPositioning', {1: 'Centered', 2: 'Co-sited'}), 0x0214: ('ReferenceBlackWhite', ), 0x4746: ('Rating', ), 0x828D: ('CFARepeatPatternDim', ), 0x828E: ('CFAPattern', ), 0x828F: ('BatteryLevel', ), 0x8298: ('Copyright', ), 0x829A: ('ExposureTime', ), 0x829D: ('FNumber', ), 0x83BB: ('IPTC/NAA', ), 0x8769: ('ExifOffset', ), 0x8773: ('InterColorProfile', ), 0x8822: ('ExposureProgram', {0: 'Unidentified', 1: 'Manual', 2: 'Program Normal', 3: 'Aperture Priority', 4: 'Shutter Priority', 5: 'Program Creative', 6: 'Program Action', 7: 'Portrait Mode', 8: 'Landscape Mode'}), 0x8824: ('SpectralSensitivity', ), 0x8825: ('GPSInfo', ), 0x8827: ('ISOSpeedRatings', ), 0x8828: ('OECF', ), 0x9000: ('ExifVersion', make_string), 0x9003: ('DateTimeOriginal', ), 0x9004: ('DateTimeDigitized', ), 0x9101: ('ComponentsConfiguration', {0: '', 1: 'Y', 2: 'Cb', 3: 'Cr', 4: 'Red', 5: 'Green', 6: 'Blue'}), 0x9102: ('CompressedBitsPerPixel', ), 0x9201: ('ShutterSpeedValue', ), 0x9202: ('ApertureValue', ), 0x9203: ('BrightnessValue', ), 0x9204: ('ExposureBiasValue', ), 0x9205: ('MaxApertureValue', ), 0x9206: ('SubjectDistance', ), 0x9207: ('MeteringMode', {0: 'Unidentified', 1: 'Average', 2: 'CenterWeightedAverage', 3: 'Spot', 4: 'MultiSpot', 5: 'Pattern'}), 0x9208: ('LightSource', {0: 'Unknown', 1: 'Daylight', 2: 'Fluorescent', 3: 'Tungsten', 9: 'Fine Weather', 10: 'Flash', 11: 'Shade', 12: 'Daylight Fluorescent', 13: 'Day White Fluorescent', 14: 'Cool White Fluorescent', 15: 'White Fluorescent', 17: 'Standard Light A', 18: 'Standard Light B', 19: 'Standard Light C', 20: 'D55', 21: 'D65', 22: 'D75', 255: 'Other'}), 0x9209: ('Flash', {0: 'No', 1: 'Fired', 5: 'Fired (?)', # no return sensed 7: 'Fired (!)', # return sensed 9: 'Fill Fired', 13: 'Fill Fired (?)', 15: 'Fill Fired (!)', 16: 'Off', 24: 'Auto Off', 25: 'Auto Fired', 29: 'Auto Fired (?)', 31: 'Auto Fired (!)', 32: 'Not Available'}), 0x920A: ('FocalLength', ), 0x9214: ('SubjectArea', ), 0x927C: ('MakerNote', ), 0x9286: ('UserComment', make_string_uc), 0x9290: ('SubSecTime', ), 0x9291: ('SubSecTimeOriginal', ), 0x9292: ('SubSecTimeDigitized', ), # used by Windows Explorer 0x9C9B: ('XPTitle', ), 0x9C9C: ('XPComment', ), 0x9C9D: ('XPAuthor', ), #(ignored by Windows Explorer if Artist exists) 0x9C9E: ('XPKeywords', ), 0x9C9F: ('XPSubject', ), 0xA000: ('FlashPixVersion', make_string), 0xA001: ('ColorSpace', {1: 'sRGB', 2: 'Adobe RGB', 65535: 'Uncalibrated'}), 0xA002: ('ExifImageWidth', ), 0xA003: ('ExifImageLength', ), 0xA005: ('InteroperabilityOffset', ), 0xA20B: ('FlashEnergy', ), # 0x920B in TIFF/EP 0xA20C: ('SpatialFrequencyResponse', ), # 0x920C 0xA20E: ('FocalPlaneXResolution', ), # 0x920E 0xA20F: ('FocalPlaneYResolution', ), # 0x920F 0xA210: ('FocalPlaneResolutionUnit', ), # 0x9210 0xA214: ('SubjectLocation', ), # 0x9214 0xA215: ('ExposureIndex', ), # 0x9215 0xA217: ('SensingMethod', # 0x9217 {1: 'Not defined', 2: 'One-chip color area', 3: 'Two-chip color area', 4: 'Three-chip color area', 5: 'Color sequential area', 7: 'Trilinear', 8: 'Color sequential linear'}), 0xA300: ('FileSource', {1: 'Film Scanner', 2: 'Reflection Print Scanner', 3: 'Digital Camera'}), 0xA301: ('SceneType', {1: 'Directly Photographed'}), 0xA302: ('CVAPattern', ), 0xA401: ('CustomRendered', {0: 'Normal', 1: 'Custom'}), 0xA402: ('ExposureMode', {0: 'Auto Exposure', 1: 'Manual Exposure', 2: 'Auto Bracket'}), 0xA403: ('WhiteBalance', {0: 'Auto', 1: 'Manual'}), 0xA404: ('DigitalZoomRatio', ), 0xA405: ('FocalLengthIn35mmFilm', ), 0xA406: ('SceneCaptureType', {0: 'Standard', 1: 'Landscape', 2: 'Portrait', 3: 'Night)'}), 0xA407: ('GainControl', {0: 'None', 1: 'Low gain up', 2: 'High gain up', 3: 'Low gain down', 4: 'High gain down'}), 0xA408: ('Contrast', {0: 'Normal', 1: 'Soft', 2: 'Hard'}), 0xA409: ('Saturation', {0: 'Normal', 1: 'Soft', 2: 'Hard'}), 0xA40A: ('Sharpness', {0: 'Normal', 1: 'Soft', 2: 'Hard'}), 0xA40B: ('DeviceSettingDescription', ), 0xA40C: ('SubjectDistanceRange', ), 0xA500: ('Gamma', ), 0xC4A5: ('PrintIM', ), 0xEA1C: ('Padding', ), } # interoperability tags INTR_TAGS = { 0x0001: ('InteroperabilityIndex', ), 0x0002: ('InteroperabilityVersion', ), 0x1000: ('RelatedImageFileFormat', ), 0x1001: ('RelatedImageWidth', ), 0x1002: ('RelatedImageLength', ), } # GPS tags (not used yet, haven't seen camera with GPS) GPS_TAGS = { 0x0000: ('GPSVersionID', ), 0x0001: ('GPSLatitudeRef', ), 0x0002: ('GPSLatitude', ), 0x0003: ('GPSLongitudeRef', ), 0x0004: ('GPSLongitude', ), 0x0005: ('GPSAltitudeRef', ), 0x0006: ('GPSAltitude', ), 0x0007: ('GPSTimeStamp', ), 0x0008: ('GPSSatellites', ), 0x0009: ('GPSStatus', ), 0x000A: ('GPSMeasureMode', ), 0x000B: ('GPSDOP', ), 0x000C: ('GPSSpeedRef', ), 0x000D: ('GPSSpeed', ), 0x000E: ('GPSTrackRef', ), 0x000F: ('GPSTrack', ), 0x0010: ('GPSImgDirectionRef', ), 0x0011: ('GPSImgDirection', ), 0x0012: ('GPSMapDatum', ), 0x0013: ('GPSDestLatitudeRef', ), 0x0014: ('GPSDestLatitude', ), 0x0015: ('GPSDestLongitudeRef', ), 0x0016: ('GPSDestLongitude', ), 0x0017: ('GPSDestBearingRef', ), 0x0018: ('GPSDestBearing', ), 0x0019: ('GPSDestDistanceRef', ), 0x001A: ('GPSDestDistance', ), 0x001D: ('GPSDate', ), } # Ignore these tags when quick processing # 0x927C is MakerNote Tags # 0x9286 is user comment IGNORE_TAGS=(0x9286, 0x927C) # http://tomtia.plala.jp/DigitalCamera/MakerNote/index.asp def nikon_ev_bias(seq): # First digit seems to be in steps of 1/6 EV. # Does the third value mean the step size? It is usually 6, # but it is 12 for the ExposureDifference. # # Check for an error condition that could cause a crash. # This only happens if something has gone really wrong in # reading the Nikon MakerNote. if len( seq ) < 4 : return "" # if seq == [252, 1, 6, 0]: return "-2/3 EV" if seq == [253, 1, 6, 0]: return "-1/2 EV" if seq == [254, 1, 6, 0]: return "-1/3 EV" if seq == [0, 1, 6, 0]: return "0 EV" if seq == [2, 1, 6, 0]: return "+1/3 EV" if seq == [3, 1, 6, 0]: return "+1/2 EV" if seq == [4, 1, 6, 0]: return "+2/3 EV" # Handle combinations not in the table. a = seq[0] # Causes headaches for the +/- logic, so special case it. if a == 0: return "0 EV" if a > 127: a = 256 - a ret_str = "-" else: ret_str = "+" b = seq[2] # Assume third value means the step size whole = a / b a = a % b if whole != 0: ret_str = ret_str + str(whole) + " " if a == 0: ret_str = ret_str + "EV" else: r = Ratio(a, b) ret_str = ret_str + r.__repr__() + " EV" return ret_str # Nikon E99x MakerNote Tags MAKERNOTE_NIKON_NEWER_TAGS={ 0x0001: ('MakernoteVersion', make_string), # Sometimes binary 0x0002: ('ISOSetting', make_string), 0x0003: ('ColorMode', ), 0x0004: ('Quality', ), 0x0005: ('Whitebalance', ), 0x0006: ('ImageSharpening', ), 0x0007: ('FocusMode', ), 0x0008: ('FlashSetting', ), 0x0009: ('AutoFlashMode', ), 0x000B: ('WhiteBalanceBias', ), 0x000C: ('WhiteBalanceRBCoeff', ), 0x000D: ('ProgramShift', nikon_ev_bias), # Nearly the same as the other EV vals, but step size is 1/12 EV (?) 0x000E: ('ExposureDifference', nikon_ev_bias), 0x000F: ('ISOSelection', ), 0x0011: ('NikonPreview', ), 0x0012: ('FlashCompensation', nikon_ev_bias), 0x0013: ('ISOSpeedRequested', ), 0x0016: ('PhotoCornerCoordinates', ), # 0x0017: Unknown, but most likely an EV value 0x0018: ('FlashBracketCompensationApplied', nikon_ev_bias), 0x0019: ('AEBracketCompensationApplied', ), 0x001A: ('ImageProcessing', ), 0x001B: ('CropHiSpeed', ), 0x001D: ('SerialNumber', ), # Conflict with 0x00A0 ? 0x001E: ('ColorSpace', ), 0x001F: ('VRInfo', ), 0x0020: ('ImageAuthentication', ), 0x0022: ('ActiveDLighting', ), 0x0023: ('PictureControl', ), 0x0024: ('WorldTime', ), 0x0025: ('ISOInfo', ), 0x0080: ('ImageAdjustment', ), 0x0081: ('ToneCompensation', ), 0x0082: ('AuxiliaryLens', ), 0x0083: ('LensType', ), 0x0084: ('LensMinMaxFocalMaxAperture', ), 0x0085: ('ManualFocusDistance', ), 0x0086: ('DigitalZoomFactor', ), 0x0087: ('FlashMode', {0x00: 'Did Not Fire', 0x01: 'Fired, Manual', 0x07: 'Fired, External', 0x08: 'Fired, Commander Mode ', 0x09: 'Fired, TTL Mode'}), 0x0088: ('AFFocusPosition', {0x0000: 'Center', 0x0100: 'Top', 0x0200: 'Bottom', 0x0300: 'Left', 0x0400: 'Right'}), 0x0089: ('BracketingMode', {0x00: 'Single frame, no bracketing', 0x01: 'Continuous, no bracketing', 0x02: 'Timer, no bracketing', 0x10: 'Single frame, exposure bracketing', 0x11: 'Continuous, exposure bracketing', 0x12: 'Timer, exposure bracketing', 0x40: 'Single frame, white balance bracketing', 0x41: 'Continuous, white balance bracketing', 0x42: 'Timer, white balance bracketing'}), 0x008A: ('AutoBracketRelease', ), 0x008B: ('LensFStops', ), 0x008C: ('NEFCurve1', ), # ExifTool calls this 'ContrastCurve' 0x008D: ('ColorMode', ), 0x008F: ('SceneMode', ), 0x0090: ('LightingType', ), 0x0091: ('ShotInfo', ), # First 4 bytes are a version number in ASCII 0x0092: ('HueAdjustment', ), # ExifTool calls this 'NEFCompression', should be 1-4 0x0093: ('Compression', ), 0x0094: ('Saturation', {-3: 'B&W', -2: '-2', -1: '-1', 0: '0', 1: '1', 2: '2'}), 0x0095: ('NoiseReduction', ), 0x0096: ('NEFCurve2', ), # ExifTool calls this 'LinearizationTable' 0x0097: ('ColorBalance', ), # First 4 bytes are a version number in ASCII 0x0098: ('LensData', ), # First 4 bytes are a version number in ASCII 0x0099: ('RawImageCenter', ), 0x009A: ('SensorPixelSize', ), 0x009C: ('Scene Assist', ), 0x009E: ('RetouchHistory', ), 0x00A0: ('SerialNumber', ), 0x00A2: ('ImageDataSize', ), # 00A3: unknown - a single byte 0 # 00A4: In NEF, looks like a 4 byte ASCII version number ('0200') 0x00A5: ('ImageCount', ), 0x00A6: ('DeletedImageCount', ), 0x00A7: ('TotalShutterReleases', ), # First 4 bytes are a version number in ASCII, with version specific # info to follow. Its hard to treat it as a string due to embedded nulls. 0x00A8: ('FlashInfo', ), 0x00A9: ('ImageOptimization', ), 0x00AA: ('Saturation', ), 0x00AB: ('DigitalVariProgram', ), 0x00AC: ('ImageStabilization', ), 0x00AD: ('Responsive AF', ), # 'AFResponse' 0x00B0: ('MultiExposure', ), 0x00B1: ('HighISONoiseReduction', ), 0x00B7: ('AFInfo', ), 0x00B8: ('FileInfo', ), # 00B9: unknown 0x0100: ('DigitalICE', ), 0x0103: ('PreviewCompression', {1: 'Uncompressed', 2: 'CCITT 1D', 3: 'T4/Group 3 Fax', 4: 'T6/Group 4 Fax', 5: 'LZW', 6: 'JPEG (old-style)', 7: 'JPEG', 8: 'Adobe Deflate', 9: 'JBIG B&W', 10: 'JBIG Color', 32766: 'Next', 32769: 'Epson ERF Compressed', 32771: 'CCIRLEW', 32773: 'PackBits', 32809: 'Thunderscan', 32895: 'IT8CTPAD', 32896: 'IT8LW', 32897: 'IT8MP', 32898: 'IT8BL', 32908: 'PixarFilm', 32909: 'PixarLog', 32946: 'Deflate', 32947: 'DCS', 34661: 'JBIG', 34676: 'SGILog', 34677: 'SGILog24', 34712: 'JPEG 2000', 34713: 'Nikon NEF Compressed', 65000: 'Kodak DCR Compressed', 65535: 'Pentax PEF Compressed',}), 0x0201: ('PreviewImageStart', ), 0x0202: ('PreviewImageLength', ), 0x0213: ('PreviewYCbCrPositioning', {1: 'Centered', 2: 'Co-sited'}), 0x0010: ('DataDump', ), } MAKERNOTE_NIKON_OLDER_TAGS = { 0x0003: ('Quality', {1: 'VGA Basic', 2: 'VGA Normal', 3: 'VGA Fine', 4: 'SXGA Basic', 5: 'SXGA Normal', 6: 'SXGA Fine'}), 0x0004: ('ColorMode', {1: 'Color', 2: 'Monochrome'}), 0x0005: ('ImageAdjustment', {0: 'Normal', 1: 'Bright+', 2: 'Bright-', 3: 'Contrast+', 4: 'Contrast-'}), 0x0006: ('CCDSpeed', {0: 'ISO 80', 2: 'ISO 160', 4: 'ISO 320', 5: 'ISO 100'}), 0x0007: ('WhiteBalance', {0: 'Auto', 1: 'Preset', 2: 'Daylight', 3: 'Incandescent', 4: 'Fluorescent', 5: 'Cloudy', 6: 'Speed Light'}), } # decode Olympus SpecialMode tag in MakerNote def olympus_special_mode(v): a={ 0: 'Normal', 1: 'Unknown', 2: 'Fast', 3: 'Panorama'} b={ 0: 'Non-panoramic', 1: 'Left to right', 2: 'Right to left', 3: 'Bottom to top', 4: 'Top to bottom'} if v[0] not in a or v[2] not in b: return v return '%s - sequence %d - %s' % (a[v[0]], v[1], b[v[2]]) MAKERNOTE_OLYMPUS_TAGS={ # ah HAH! those sneeeeeaky bastids! this is how they get past the fact # that a JPEG thumbnail is not allowed in an uncompressed TIFF file 0x0100: ('JPEGThumbnail', ), 0x0200: ('SpecialMode', olympus_special_mode), 0x0201: ('JPEGQual', {1: 'SQ', 2: 'HQ', 3: 'SHQ'}), 0x0202: ('Macro', {0: 'Normal', 1: 'Macro', 2: 'SuperMacro'}), 0x0203: ('BWMode', {0: 'Off', 1: 'On'}), 0x0204: ('DigitalZoom', ), 0x0205: ('FocalPlaneDiagonal', ), 0x0206: ('LensDistortionParams', ), 0x0207: ('SoftwareRelease', ), 0x0208: ('PictureInfo', ), 0x0209: ('CameraID', make_string), # print as string 0x0F00: ('DataDump', ), 0x0300: ('PreCaptureFrames', ), 0x0404: ('SerialNumber', ), 0x1000: ('ShutterSpeedValue', ), 0x1001: ('ISOValue', ), 0x1002: ('ApertureValue', ), 0x1003: ('BrightnessValue', ), 0x1004: ('FlashMode', ), 0x1004: ('FlashMode', {2: 'On', 3: 'Off'}), 0x1005: ('FlashDevice', {0: 'None', 1: 'Internal', 4: 'External', 5: 'Internal + External'}), 0x1006: ('ExposureCompensation', ), 0x1007: ('SensorTemperature', ), 0x1008: ('LensTemperature', ), 0x100b: ('FocusMode', {0: 'Auto', 1: 'Manual'}), 0x1017: ('RedBalance', ), 0x1018: ('BlueBalance', ), 0x101a: ('SerialNumber', ), 0x1023: ('FlashExposureComp', ), 0x1026: ('ExternalFlashBounce', {0: 'No', 1: 'Yes'}), 0x1027: ('ExternalFlashZoom', ), 0x1028: ('ExternalFlashMode', ), 0x1029: ('Contrast int16u', {0: 'High', 1: 'Normal', 2: 'Low'}), 0x102a: ('SharpnessFactor', ), 0x102b: ('ColorControl', ), 0x102c: ('ValidBits', ), 0x102d: ('CoringFilter', ), 0x102e: ('OlympusImageWidth', ), 0x102f: ('OlympusImageHeight', ), 0x1034: ('CompressionRatio', ), 0x1035: ('PreviewImageValid', {0: 'No', 1: 'Yes'}), 0x1036: ('PreviewImageStart', ), 0x1037: ('PreviewImageLength', ), 0x1039: ('CCDScanMode', {0: 'Interlaced', 1: 'Progressive'}), 0x103a: ('NoiseReduction', {0: 'Off', 1: 'On'}), 0x103b: ('InfinityLensStep', ), 0x103c: ('NearLensStep', ), # TODO - these need extra definitions # http://search.cpan.org/src/EXIFTOOL/Image-ExifTool-6.90/html/TagNames/Olympus.html 0x2010: ('Equipment', ), 0x2020: ('CameraSettings', ), 0x2030: ('RawDevelopment', ), 0x2040: ('ImageProcessing', ), 0x2050: ('FocusInfo', ), 0x3000: ('RawInfo ', ), } # 0x2020 CameraSettings MAKERNOTE_OLYMPUS_TAG_0x2020={ 0x0100: ('PreviewImageValid', {0: 'No', 1: 'Yes'}), 0x0101: ('PreviewImageStart', ), 0x0102: ('PreviewImageLength', ), 0x0200: ('ExposureMode', {1: 'Manual', 2: 'Program', 3: 'Aperture-priority AE', 4: 'Shutter speed priority AE', 5: 'Program-shift'}), 0x0201: ('AELock', {0: 'Off', 1: 'On'}), 0x0202: ('MeteringMode', {2: 'Center Weighted', 3: 'Spot', 5: 'ESP', 261: 'Pattern+AF', 515: 'Spot+Highlight control', 1027: 'Spot+Shadow control'}), 0x0300: ('MacroMode', {0: 'Off', 1: 'On'}), 0x0301: ('FocusMode', {0: 'Single AF', 1: 'Sequential shooting AF', 2: 'Continuous AF', 3: 'Multi AF', 10: 'MF'}), 0x0302: ('FocusProcess', {0: 'AF Not Used', 1: 'AF Used'}), 0x0303: ('AFSearch', {0: 'Not Ready', 1: 'Ready'}), 0x0304: ('AFAreas', ), 0x0401: ('FlashExposureCompensation', ), 0x0500: ('WhiteBalance2', {0: 'Auto', 16: '7500K (Fine Weather with Shade)', 17: '6000K (Cloudy)', 18: '5300K (Fine Weather)', 20: '3000K (Tungsten light)', 21: '3600K (Tungsten light-like)', 33: '6600K (Daylight fluorescent)', 34: '4500K (Neutral white fluorescent)', 35: '4000K (Cool white fluorescent)', 48: '3600K (Tungsten light-like)', 256: 'Custom WB 1', 257: 'Custom WB 2', 258: 'Custom WB 3', 259: 'Custom WB 4', 512: 'Custom WB 5400K', 513: 'Custom WB 2900K', 514: 'Custom WB 8000K', }), 0x0501: ('WhiteBalanceTemperature', ), 0x0502: ('WhiteBalanceBracket', ), 0x0503: ('CustomSaturation', ), # (3 numbers: 1. CS Value, 2. Min, 3. Max) 0x0504: ('ModifiedSaturation', {0: 'Off', 1: 'CM1 (Red Enhance)', 2: 'CM2 (Green Enhance)', 3: 'CM3 (Blue Enhance)', 4: 'CM4 (Skin Tones)'}), 0x0505: ('ContrastSetting', ), # (3 numbers: 1. Contrast, 2. Min, 3. Max) 0x0506: ('SharpnessSetting', ), # (3 numbers: 1. Sharpness, 2. Min, 3. Max) 0x0507: ('ColorSpace', {0: 'sRGB', 1: 'Adobe RGB', 2: 'Pro Photo RGB'}), 0x0509: ('SceneMode', {0: 'Standard', 6: 'Auto', 7: 'Sport', 8: 'Portrait', 9: 'Landscape+Portrait', 10: 'Landscape', 11: 'Night scene', 13: 'Panorama', 16: 'Landscape+Portrait', 17: 'Night+Portrait', 19: 'Fireworks', 20: 'Sunset', 22: 'Macro', 25: 'Documents', 26: 'Museum', 28: 'Beach&Snow', 30: 'Candle', 35: 'Underwater Wide1', 36: 'Underwater Macro', 39: 'High Key', 40: 'Digital Image Stabilization', 44: 'Underwater Wide2', 45: 'Low Key', 46: 'Children', 48: 'Nature Macro'}), 0x050a: ('NoiseReduction', {0: 'Off', 1: 'Noise Reduction', 2: 'Noise Filter', 3: 'Noise Reduction + Noise Filter', 4: 'Noise Filter (ISO Boost)', 5: 'Noise Reduction + Noise Filter (ISO Boost)'}), 0x050b: ('DistortionCorrection', {0: 'Off', 1: 'On'}), 0x050c: ('ShadingCompensation', {0: 'Off', 1: 'On'}), 0x050d: ('CompressionFactor', ), 0x050f: ('Gradation', {'-1 -1 1': 'Low Key', '0 -1 1': 'Normal', '1 -1 1': 'High Key'}), 0x0520: ('PictureMode', {1: 'Vivid', 2: 'Natural', 3: 'Muted', 256: 'Monotone', 512: 'Sepia'}), 0x0521: ('PictureModeSaturation', ), 0x0522: ('PictureModeHue?', ), 0x0523: ('PictureModeContrast', ), 0x0524: ('PictureModeSharpness', ), 0x0525: ('PictureModeBWFilter', {0: 'n/a', 1: 'Neutral', 2: 'Yellow', 3: 'Orange', 4: 'Red', 5: 'Green'}), 0x0526: ('PictureModeTone', {0: 'n/a', 1: 'Neutral', 2: 'Sepia', 3: 'Blue', 4: 'Purple', 5: 'Green'}), 0x0600: ('Sequence', ), # 2 or 3 numbers: 1. Mode, 2. Shot number, 3. Mode bits 0x0601: ('PanoramaMode', ), # (2 numbers: 1. Mode, 2. Shot number) 0x0603: ('ImageQuality2', {1: 'SQ', 2: 'HQ', 3: 'SHQ', 4: 'RAW'}), 0x0901: ('ManometerReading', ), } MAKERNOTE_CASIO_TAGS={ 0x0001: ('RecordingMode', {1: 'Single Shutter', 2: 'Panorama', 3: 'Night Scene', 4: 'Portrait', 5: 'Landscape'}), 0x0002: ('Quality', {1: 'Economy', 2: 'Normal', 3: 'Fine'}), 0x0003: ('FocusingMode', {2: 'Macro', 3: 'Auto Focus', 4: 'Manual Focus', 5: 'Infinity'}), 0x0004: ('FlashMode', {1: 'Auto', 2: 'On', 3: 'Off', 4: 'Red Eye Reduction'}), 0x0005: ('FlashIntensity', {11: 'Weak', 13: 'Normal', 15: 'Strong'}), 0x0006: ('Object Distance', ), 0x0007: ('WhiteBalance', {1: 'Auto', 2: 'Tungsten', 3: 'Daylight', 4: 'Fluorescent', 5: 'Shade', 129: 'Manual'}), 0x000B: ('Sharpness', {0: 'Normal', 1: 'Soft', 2: 'Hard'}), 0x000C: ('Contrast', {0: 'Normal', 1: 'Low', 2: 'High'}), 0x000D: ('Saturation', {0: 'Normal', 1: 'Low', 2: 'High'}), 0x0014: ('CCDSpeed', {64: 'Normal', 80: 'Normal', 100: 'High', 125: '+1.0', 244: '+3.0', 250: '+2.0'}), } MAKERNOTE_FUJIFILM_TAGS={ 0x0000: ('NoteVersion', make_string), 0x1000: ('Quality', ), 0x1001: ('Sharpness', {1: 'Soft', 2: 'Soft', 3: 'Normal', 4: 'Hard', 5: 'Hard'}), 0x1002: ('WhiteBalance', {0: 'Auto', 256: 'Daylight', 512: 'Cloudy', 768: 'DaylightColor-Fluorescent', 769: 'DaywhiteColor-Fluorescent', 770: 'White-Fluorescent', 1024: 'Incandescent', 3840: 'Custom'}), 0x1003: ('Color', {0: 'Normal', 256: 'High', 512: 'Low'}), 0x1004: ('Tone', {0: 'Normal', 256: 'High', 512: 'Low'}), 0x1010: ('FlashMode', {0: 'Auto', 1: 'On', 2: 'Off', 3: 'Red Eye Reduction'}), 0x1011: ('FlashStrength', ), 0x1020: ('Macro', {0: 'Off', 1: 'On'}), 0x1021: ('FocusMode', {0: 'Auto', 1: 'Manual'}), 0x1030: ('SlowSync', {0: 'Off', 1: 'On'}), 0x1031: ('PictureMode', {0: 'Auto', 1: 'Portrait', 2: 'Landscape', 4: 'Sports', 5: 'Night', 6: 'Program AE', 256: 'Aperture Priority AE', 512: 'Shutter Priority AE', 768: 'Manual Exposure'}), 0x1100: ('MotorOrBracket', {0: 'Off', 1: 'On'}), 0x1300: ('BlurWarning', {0: 'Off', 1: 'On'}), 0x1301: ('FocusWarning', {0: 'Off', 1: 'On'}), 0x1302: ('AEWarning', {0: 'Off', 1: 'On'}), } MAKERNOTE_CANON_TAGS = { 0x0006: ('ImageType', ), 0x0007: ('FirmwareVersion', ), 0x0008: ('ImageNumber', ), 0x0009: ('OwnerName', ), } # this is in element offset, name, optional value dictionary format MAKERNOTE_CANON_TAG_0x001 = { 1: ('Macromode', {1: 'Macro', 2: 'Normal'}), 2: ('SelfTimer', ), 3: ('Quality', {2: 'Normal', 3: 'Fine', 5: 'Superfine'}), 4: ('FlashMode', {0: 'Flash Not Fired', 1: 'Auto', 2: 'On', 3: 'Red-Eye Reduction', 4: 'Slow Synchro', 5: 'Auto + Red-Eye Reduction', 6: 'On + Red-Eye Reduction', 16: 'external flash'}), 5: ('ContinuousDriveMode', {0: 'Single Or Timer', 1: 'Continuous'}), 7: ('FocusMode', {0: 'One-Shot', 1: 'AI Servo', 2: 'AI Focus', 3: 'MF', 4: 'Single', 5: 'Continuous', 6: 'MF'}), 10: ('ImageSize', {0: 'Large', 1: 'Medium', 2: 'Small'}), 11: ('EasyShootingMode', {0: 'Full Auto', 1: 'Manual', 2: 'Landscape', 3: 'Fast Shutter', 4: 'Slow Shutter', 5: 'Night', 6: 'B&W', 7: 'Sepia', 8: 'Portrait', 9: 'Sports', 10: 'Macro/Close-Up', 11: 'Pan Focus'}), 12: ('DigitalZoom', {0: 'None', 1: '2x', 2: '4x'}), 13: ('Contrast', {0xFFFF: 'Low', 0: 'Normal', 1: 'High'}), 14: ('Saturation', {0xFFFF: 'Low', 0: 'Normal', 1: 'High'}), 15: ('Sharpness', {0xFFFF: 'Low', 0: 'Normal', 1: 'High'}), 16: ('ISO', {0: 'See ISOSpeedRatings Tag', 15: 'Auto', 16: '50', 17: '100', 18: '200', 19: '400'}), 17: ('MeteringMode', {3: 'Evaluative', 4: 'Partial', 5: 'Center-weighted'}), 18: ('FocusType', {0: 'Manual', 1: 'Auto', 3: 'Close-Up (Macro)', 8: 'Locked (Pan Mode)'}), 19: ('AFPointSelected', {0x3000: 'None (MF)', 0x3001: 'Auto-Selected', 0x3002: 'Right', 0x3003: 'Center', 0x3004: 'Left'}), 20: ('ExposureMode', {0: 'Easy Shooting', 1: 'Program', 2: 'Tv-priority', 3: 'Av-priority', 4: 'Manual', 5: 'A-DEP'}), 23: ('LongFocalLengthOfLensInFocalUnits', ), 24: ('ShortFocalLengthOfLensInFocalUnits', ), 25: ('FocalUnitsPerMM', ), 28: ('FlashActivity', {0: 'Did Not Fire', 1: 'Fired'}), 29: ('FlashDetails', {14: 'External E-TTL', 13: 'Internal Flash', 11: 'FP Sync Used', 7: '2nd("Rear")-Curtain Sync Used', 4: 'FP Sync Enabled'}), 32: ('FocusMode', {0: 'Single', 1: 'Continuous'}), } MAKERNOTE_CANON_TAG_0x004 = { 7: ('WhiteBalance', {0: 'Auto', 1: 'Sunny', 2: 'Cloudy', 3: 'Tungsten', 4: 'Fluorescent', 5: 'Flash', 6: 'Custom'}), 9: ('SequenceNumber', ), 14: ('AFPointUsed', ), 15: ('FlashBias', {0xFFC0: '-2 EV', 0xFFCC: '-1.67 EV', 0xFFD0: '-1.50 EV', 0xFFD4: '-1.33 EV', 0xFFE0: '-1 EV', 0xFFEC: '-0.67 EV', 0xFFF0: '-0.50 EV', 0xFFF4: '-0.33 EV', 0x0000: '0 EV', 0x000C: '0.33 EV', 0x0010: '0.50 EV', 0x0014: '0.67 EV', 0x0020: '1 EV', 0x002C: '1.33 EV', 0x0030: '1.50 EV', 0x0034: '1.67 EV', 0x0040: '2 EV'}), 19: ('SubjectDistance', ), } # extract multibyte integer in Motorola format (little endian) def s2n_motorola(str): x = 0 for c in str: x = (x << 8) | ord(c) return x # extract multibyte integer in Intel format (big endian) def s2n_intel(str): x = 0 y = 0L for c in str: x = x | (ord(c) << y) y = y + 8 return x # ratio object that eventually will be able to reduce itself to lowest # common denominator for printing def gcd(a, b): if b == 0: return a else: return gcd(b, a % b) class Ratio: def __init__(self, num, den): self.num = num self.den = den def __repr__(self): self.reduce() if self.den == 1: return str(self.num) return '%d/%d' % (self.num, self.den) def reduce(self): div = gcd(self.num, self.den) if div > 1: self.num = self.num / div self.den = self.den / div # for ease of dealing with tags class IFD_Tag: def __init__(self, printable, tag, field_type, values, field_offset, field_length): # printable version of data self.printable = printable # tag ID number self.tag = tag # field type as index into FIELD_TYPES self.field_type = field_type # offset of start of field in bytes from beginning of IFD self.field_offset = field_offset # length of data field in bytes self.field_length = field_length # either a string or array of data items self.values = values def __str__(self): return self.printable def __repr__(self): return '(0x%04X) %s=%s @ %d' % (self.tag, FIELD_TYPES[self.field_type][2], self.printable, self.field_offset) # class that handles an EXIF header class EXIF_header: def __init__(self, file, endian, offset, fake_exif, strict, debug=0): self.file = file file.seek(0, 2) self.filesize = file.tell() self.endian = endian self.offset = offset self.fake_exif = fake_exif self.strict = strict self.debug = debug self.tags = {} # convert slice to integer, based on sign and endian flags # usually this offset is assumed to be relative to the beginning of the # start of the EXIF information. For some cameras that use relative tags, # this offset may be relative to some other starting point. def s2n(self, offset, length, signed=0): if self.offset + offset > self.filesize: return 0 self.file.seek(self.offset+offset) slice=self.file.read(length) if self.endian == 'I': val=s2n_intel(slice) else: val=s2n_motorola(slice) # Sign extension ? if signed: msb=1L << (8*length-1) if val & msb: val=val-(msb << 1) return val # convert offset to string def n2s(self, offset, length): s = '' for dummy in range(length): if self.endian == 'I': s = s + chr(offset & 0xFF) else: s = chr(offset & 0xFF) + s offset = offset >> 8 return s # return first IFD def first_IFD(self): return self.s2n(4, 4) # return pointer to next IFD def next_IFD(self, ifd): if ifd < self.filesize: entries=self.s2n(ifd, 2) if ifd+2+12*entries < self.filesize: return self.s2n(ifd+2+12*entries, 4) return 0 # return list of IFDs in header def list_IFDs(self): i=self.first_IFD() a=[] while i: a.append(i) i=self.next_IFD(i) return a # return list of entries in this IFD def dump_IFD(self, ifd, ifd_name, dict=EXIF_TAGS, relative=0, stop_tag='UNDEF'): if ifd > self.filesize: return entries=self.s2n(ifd, 2) for i in range(entries): # entry is index of start of this IFD in the file entry = ifd + 2 + 12 * i tag = self.s2n(entry, 2) # get tag name early to avoid errors, help debug tag_entry = dict.get(tag) if tag_entry: tag_name = tag_entry[0] else: tag_name = 'Tag 0x%04X' % tag # ignore certain tags for faster processing if not (not detailed and tag in IGNORE_TAGS): field_type = self.s2n(entry + 2, 2) # unknown field type if not 0 < field_type < len(FIELD_TYPES): if not self.strict: continue else: raise ValueError('unknown type %d in tag 0x%04X' % (field_type, tag)) typelen = FIELD_TYPES[field_type][0] count = self.s2n(entry + 4, 4) # Adjust for tag id/type/count (2+2+4 bytes) # Now we point at either the data or the 2nd level offset offset = entry + 8 # If the value fits in 4 bytes, it is inlined, else we # need to jump ahead again. if count * typelen > 4: # offset is not the value; it's a pointer to the value # if relative we set things up so s2n will seek to the right # place when it adds self.offset. Note that this 'relative' # is for the Nikon type 3 makernote. Other cameras may use # other relative offsets, which would have to be computed here # slightly differently. if relative: tmp_offset = self.s2n(offset, 4) offset = tmp_offset + ifd - 8 if self.fake_exif: offset = offset + 18 else: offset = self.s2n(offset, 4) field_offset = offset if field_type == 2: # special case: null-terminated ASCII string # XXX investigate # sometimes gets too big to fit in int value if count != 0 and count < self.file.node().size(): self.file.seek(self.offset + offset) values = self.file.read(count) #print values # Drop any garbage after a null. values = values.split('\x00', 1)[0] else: values = '' else: values = [] signed = (field_type in [6, 8, 9, 10]) # XXX investigate # some entries get too big to handle could be malformed # file or problem with self.s2n if count < 1000: for dummy in range(count): if field_type in (5, 10): # a ratio value = Ratio(self.s2n(offset, 4, signed), self.s2n(offset + 4, 4, signed)) else: value = self.s2n(offset, typelen, signed) values.append(value) offset = offset + typelen # The test above causes problems with tags that are # supposed to have long values! Fix up one important case. elif tag_name == 'MakerNote' : for dummy in range(count): value = self.s2n(offset, typelen, signed) values.append(value) offset = offset + typelen #else : # print "Warning: dropping large tag:", tag, tag_name # now 'values' is either a string or an array if count == 1 and field_type != 2: printable=str(values[0]) elif count > 50 and len(values) > 20 : printable=str( values[0:20] )[0:-1] + ", ... ]" else: printable=str(values) # compute printable version of values if tag_entry: if len(tag_entry) != 1: # optional 2nd tag element is present if callable(tag_entry[1]): # call mapping function printable = tag_entry[1](values) else: printable = '' for i in values: # use lookup table for this tag printable += tag_entry[1].get(i, repr(i)) self.tags[ifd_name + ' ' + tag_name] = IFD_Tag(printable, tag, field_type, values, field_offset, count * typelen) if self.debug: print ' debug: %s: %s' % (tag_name, repr(self.tags[ifd_name + ' ' + tag_name])) if tag_name == stop_tag: break # extract uncompressed TIFF thumbnail (like pulling teeth) # we take advantage of the pre-existing layout in the thumbnail IFD as # much as possible def extract_TIFF_thumbnail(self, thumb_ifd): entries = self.s2n(thumb_ifd, 2) # this is header plus offset to IFD ... if self.endian == 'M': tiff = 'MM\x00*\x00\x00\x00\x08' else: tiff = 'II*\x00\x08\x00\x00\x00' # ... plus thumbnail IFD data plus a null "next IFD" pointer self.file.seek(self.offset+thumb_ifd) tiff += self.file.read(entries*12+2)+'\x00\x00\x00\x00' # fix up large value offset pointers into data area for i in range(entries): entry = thumb_ifd + 2 + 12 * i tag = self.s2n(entry, 2) field_type = self.s2n(entry+2, 2) typelen = FIELD_TYPES[field_type][0] count = self.s2n(entry+4, 4) oldoff = self.s2n(entry+8, 4) # start of the 4-byte pointer area in entry ptr = i * 12 + 18 # remember strip offsets location if tag == 0x0111: strip_off = ptr strip_len = count * typelen # is it in the data area? if count * typelen > 4: # update offset pointer (nasty "strings are immutable" crap) # should be able to say "tiff[ptr:ptr+4]=newoff" newoff = len(tiff) tiff = tiff[:ptr] + self.n2s(newoff, 4) + tiff[ptr+4:] # remember strip offsets location if tag == 0x0111: strip_off = newoff strip_len = 4 # get original data and store it self.file.seek(self.offset + oldoff) tiff += self.file.read(count * typelen) # add pixel strips and update strip offset info old_offsets = self.tags['Thumbnail StripOffsets'].values old_counts = self.tags['Thumbnail StripByteCounts'].values for i in range(len(old_offsets)): # update offset pointer (more nasty "strings are immutable" crap) offset = self.n2s(len(tiff), strip_len) tiff = tiff[:strip_off] + offset + tiff[strip_off + strip_len:] strip_off += strip_len # add pixel strip to end self.file.seek(self.offset + old_offsets[i]) tiff += self.file.read(old_counts[i]) self.tags['TIFFThumbnail'] = tiff # decode all the camera-specific MakerNote formats # Note is the data that comprises this MakerNote. The MakerNote will # likely have pointers in it that point to other parts of the file. We'll # use self.offset as the starting point for most of those pointers, since # they are relative to the beginning of the file. # # If the MakerNote is in a newer format, it may use relative addressing # within the MakerNote. In that case we'll use relative addresses for the # pointers. # # As an aside: it's not just to be annoying that the manufacturers use # relative offsets. It's so that if the makernote has to be moved by the # picture software all of the offsets don't have to be adjusted. Overall, # this is probably the right strategy for makernotes, though the spec is # ambiguous. (The spec does not appear to imagine that makernotes would # follow EXIF format internally. Once they did, it's ambiguous whether # the offsets should be from the header at the start of all the EXIF info, # or from the header at the start of the makernote.) def decode_maker_note(self): note = self.tags['EXIF MakerNote'] # Some apps use MakerNote tags but do not use a format for which we # have a description, so just do a raw dump for these. #if self.tags.has_key('Image Make'): make = self.tags['Image Make'].printable #else: # make = '' # model = self.tags['Image Model'].printable # unused # Nikon # The maker note usually starts with the word Nikon, followed by the # type of the makernote (1 or 2, as a short). If the word Nikon is # not at the start of the makernote, it's probably type 2, since some # cameras work that way. if 'NIKON' in make: if note.values[0:7] == [78, 105, 107, 111, 110, 0, 1]: if self.debug: print "Looks like a type 1 Nikon MakerNote." self.dump_IFD(note.field_offset+8, 'MakerNote', dict=MAKERNOTE_NIKON_OLDER_TAGS) elif note.values[0:7] == [78, 105, 107, 111, 110, 0, 2]: if self.debug: print "Looks like a labeled type 2 Nikon MakerNote" if note.values[12:14] != [0, 42] and note.values[12:14] != [42L, 0L]: raise ValueError("Missing marker tag '42' in MakerNote.") # skip the Makernote label and the TIFF header self.dump_IFD(note.field_offset+10+8, 'MakerNote', dict=MAKERNOTE_NIKON_NEWER_TAGS, relative=1) else: # E99x or D1 if self.debug: print "Looks like an unlabeled type 2 Nikon MakerNote" self.dump_IFD(note.field_offset, 'MakerNote', dict=MAKERNOTE_NIKON_NEWER_TAGS) return # Olympus if make.startswith('OLYMPUS'): self.dump_IFD(note.field_offset+8, 'MakerNote', dict=MAKERNOTE_OLYMPUS_TAGS) # XXX TODO #for i in (('MakerNote Tag 0x2020', MAKERNOTE_OLYMPUS_TAG_0x2020),): # self.decode_olympus_tag(self.tags[i[0]].values, i[1]) #return # Casio if 'CASIO' in make or 'Casio' in make: self.dump_IFD(note.field_offset, 'MakerNote', dict=MAKERNOTE_CASIO_TAGS) return # Fujifilm if make == 'FUJIFILM': # bug: everything else is "Motorola" endian, but the MakerNote # is "Intel" endian endian = self.endian self.endian = 'I' # bug: IFD offsets are from beginning of MakerNote, not # beginning of file header offset = self.offset self.offset += note.field_offset # process note with bogus values (note is actually at offset 12) self.dump_IFD(12, 'MakerNote', dict=MAKERNOTE_FUJIFILM_TAGS) # reset to correct values self.endian = endian self.offset = offset return # Canon if make == 'Canon': self.dump_IFD(note.field_offset, 'MakerNote', dict=MAKERNOTE_CANON_TAGS) for i in (('MakerNote Tag 0x0001', MAKERNOTE_CANON_TAG_0x001), ('MakerNote Tag 0x0004', MAKERNOTE_CANON_TAG_0x004)): self.canon_decode_tag(self.tags[i[0]].values, i[1]) return # XXX TODO decode Olympus MakerNote tag based on offset within tag def olympus_decode_tag(self, value, dict): pass # decode Canon MakerNote tag based on offset within tag # see http://www.burren.cx/david/canon.html by David Burren def canon_decode_tag(self, value, dict): for i in range(1, len(value)): x=dict.get(i, ('Unknown', )) if self.debug: print i, x name=x[0] if len(x) > 1: val=x[1].get(value[i], 'Unknown') else: val=value[i] # it's not a real IFD Tag but we fake one to make everybody # happy. this will have a "proprietary" type self.tags['MakerNote '+name]=IFD_Tag(str(val), None, 0, None, None, None) # process an image file (expects an open file object) # this is the function that has to deal with all the arbitrary nasty bits # of the EXIF standard def process_file(f, stop_tag='UNDEF', details=True, strict=False, debug=False): # yah it's cheesy... global detailed detailed = details # by default do not fake an EXIF beginning fake_exif = 0 f.seek(0, 2) filesize = f.tell() f.seek(0) # determine whether it's a JPEG or TIFF data = f.read(12) if data[0:4] in ['II*\x00', 'MM\x00*']: # it's a TIFF file f.seek(0) endian = f.read(1) f.read(1) offset = 0 elif data[0:2] == '\xFF\xD8': # it's a JPEG file while data[2] == '\xFF' and data[6:10] in ('JFIF', 'JFXX', 'OLYM', 'Phot'): length = ord(data[4])*256+ord(data[5]) f.read(length-8) # fake an EXIF beginning of file data = '\xFF\x00'+f.read(10) fake_exif = 1 if data[2] == '\xFF' and data[6:10] == 'Exif': # detected EXIF header offset = f.tell() endian = f.read(1) else: # no EXIF information return {} else: # file format not recognized return {} # deal with the EXIF info we found if debug: print {'I': 'Intel', 'M': 'Motorola'}[endian], 'format' hdr = EXIF_header(f, endian, offset, fake_exif, strict, debug) ifd_list = hdr.list_IFDs() ctr = 0 for i in ifd_list: if ctr == 0: IFD_name = 'Image' elif ctr == 1: IFD_name = 'Thumbnail' thumb_ifd = i else: IFD_name = 'IFD %d' % ctr if debug: print ' IFD %d (%s) at offset %d:' % (ctr, IFD_name, i) if i < filesize: hdr.dump_IFD(i, IFD_name, stop_tag=stop_tag) # EXIF IFD exif_off = hdr.tags.get(IFD_name+' ExifOffset') if exif_off: if debug: print ' EXIF SubIFD at offset %d:' % exif_off.values[0] hdr.dump_IFD(exif_off.values[0], 'EXIF', stop_tag=stop_tag) # Interoperability IFD contained in EXIF IFD intr_off = hdr.tags.get('EXIF SubIFD InteroperabilityOffset') if intr_off: if debug: print ' EXIF Interoperability SubSubIFD at offset %d:' \ % intr_off.values[0] hdr.dump_IFD(intr_off.values[0], 'EXIF Interoperability', dict=INTR_TAGS, stop_tag=stop_tag) # GPS IFD gps_off = hdr.tags.get(IFD_name+' GPSInfo') if gps_off: if debug: print ' GPS SubIFD at offset %d:' % gps_off.values[0] hdr.dump_IFD(gps_off.values[0], 'GPS', dict=GPS_TAGS, stop_tag=stop_tag) ctr += 1 # extract uncompressed TIFF thumbnail thumb = hdr.tags.get('Thumbnail Compression') if thumb and thumb.printable == 'Uncompressed TIFF': hdr.extract_TIFF_thumbnail(thumb_ifd) # JPEG thumbnail (thankfully the JPEG data is stored as a unit) thumb_off = hdr.tags.get('Thumbnail JPEGInterchangeFormat') if thumb_off: f.seek(offset+thumb_off.values[0]) size = hdr.tags['Thumbnail JPEGInterchangeFormatLength'].values[0] hdr.tags['JPEGThumbnail'] = f.read(size) # deal with MakerNote contained in EXIF IFD # (Some apps use MakerNote tags but do not use a format for which we # have a description, do not process these). try : if 'EXIF MakerNote' in hdr.tags and 'Image Make' in hdr.tags and detailed: hdr.decode_maker_note() except KeyError: pass # Sometimes in a TIFF file, a JPEG thumbnail is hidden in the MakerNote # since it's not allowed in a uncompressed TIFF IFD if 'JPEGThumbnail' not in hdr.tags: thumb_off=hdr.tags.get('MakerNote JPEGThumbnail') if thumb_off: f.seek(offset+thumb_off.values[0]) hdr.tags['JPEGThumbnail']=file.read(thumb_off.field_length) return hdr.tags # show command line usage def usage(exit_status): msg = 'Usage: EXIF.py [OPTIONS] file1 [file2 ...]\n' msg += 'Extract EXIF information from digital camera image files.\n\nOptions:\n' msg += '-q --quick Do not process MakerNotes.\n' msg += '-t TAG --stop-tag TAG Stop processing when this tag is retrieved.\n' msg += '-s --strict Run in strict mode (stop on errors).\n' msg += '-d --debug Run in debug mode (display extra info).\n' print msg sys.exit(exit_status) # library test/debug function (dump given files) if __name__ == '__main__': import sys import getopt # parse command line options/arguments try: opts, args = getopt.getopt(sys.argv[1:], "hqsdt:v", ["help", "quick", "strict", "debug", "stop-tag="]) except getopt.GetoptError: usage(2) if args == []: usage(2) detailed = True stop_tag = 'UNDEF' debug = False strict = False for o, a in opts: if o in ("-h", "--help"): usage(0) if o in ("-q", "--quick"): detailed = False if o in ("-t", "--stop-tag"): stop_tag = a if o in ("-s", "--strict"): strict = True if o in ("-d", "--debug"): debug = True # output info for each file for filename in args: try: file=open(filename, 'rb') except: print "'%s' is unreadable\n"%filename continue print filename + ':' # get the tags data = process_file(file, stop_tag=stop_tag, details=detailed, strict=strict, debug=debug) if not data: print 'No EXIF information found' continue x=data.keys() x.sort() for i in x: if i in ('JPEGThumbnail', 'TIFFThumbnail'): continue try: print ' %s (%s): %s' % \ (i, FIELD_TYPES[data[i].field_type][2], data[i].printable) except: print 'error', i, '"', data[i], '"' if 'JPEGThumbnail' in data: print 'File has JPEG thumbnail' print dff-1.3.0+dfsg.1/dff/modules/metadata/metaexif/__init__.py000066400000000000000000000010761217176075400232500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['EXIF'] dff-1.3.0+dfsg.1/dff/modules/metadata/metaexif/metaexif.py000066400000000000000000000075011217176075400233120ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Christophe Malinge __dff_module_metaexif_version__ = "1.0.0" from time import strptime from PIL import Image from PIL.ExifTags import TAGS from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.module.manager import ModuleProcessusHandler from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime from dff.api.vfs.libvfs import AttributesHandler, VFS class EXIFHandler(AttributesHandler, ModuleProcessusHandler): dateTimeTags = [0x0132, 0x9003, 0x9004] def __init__(self): AttributesHandler.__init__(self, "exif") ModuleProcessusHandler.__init__(self, "metaexif") self.exifnodes = [] self.vfs = VFS.Get() self.__disown__() def update(self, processus): pass def nodes(self, root): lnodes = [] rootAbsolute = root.absolute() for node in self.exifnodes: node = self.vfs.getNodeFromPointer(node) if node.absolute().find(rootAbsolute) == 0: lnodes.append(node) return lnodes def setAttributes(self, node): self.exifnodes.append(long(node.this)) def haveExif(self, node): vfile = node.open() img = Image.open(vfile) info = img._getexif() vfile.close() if info == None: return False if len(info): return True return False def attributes(self, node): attr = VMap() vfile = node.open() img = Image.open(vfile) info = img._getexif() vfile.close() for tag, values in info.items(): if tag in self.dateTimeTags: try: decoded = str(TAGS.get(tag, tag)) try: dt = strptime(values, "%Y:%m:%d %H:%M:%S") except ValueError: try: dt = strptime(values[:-6], "%Y-%m-%dT%H:%M:%S") except ValueError: dt = strptime(values.rstrip(' '), "%a %b %d %H:%M:%S") vt = vtime(dt.tm_year, dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec, 0) vt.thisown = False attr[decoded] = Variant(vt) except Exception as e: attr[decoded] = Variant(str(values)) else: decoded = str(TAGS.get(tag, tag)) if isinstance(values, tuple): vl = VList() for value in values: vl.push_back(Variant(value)) attr[decoded] = vl else: attr[decoded] = Variant(values) return attr class MetaEXIF(Script): def __init__(self): Script.__init__(self, "metaexif") self.handler = EXIFHandler() def start(self, args): try: node = args['file'].value() attr = self.handler.haveExif(node) if attr == True: self.stateinfo = "Registering node: " + str(node.name()) self.handler.setAttributes(node) node.registerAttributes(self.handler) except KeyError: pass class metaexif(Module): """This modules generate exif metadata in node attributes""" def __init__(self): Module.__init__(self, "metaexif", MetaEXIF) self.conf.addArgument({"name": "file", "description": "file for extracting metadata", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["jpeg", "TIFF"]}) self.flags = ["single"] self.tags = "Metadata" dff-1.3.0+dfsg.1/dff/modules/metadata/prefetch/000077500000000000000000000000001217176075400211315ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/metadata/prefetch/CMakeLists.txt000066400000000000000000000011041217176075400236650ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( prefetch.py ) dff-1.3.0+dfsg.1/dff/modules/metadata/prefetch/prefetch.py000066400000000000000000000164111217176075400233060ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __dff_module_prefetch_version__ = "1.0.0" import sys, traceback from struct import unpack from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.module.manager import ModuleProcessusHandler from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime, TIME_MS_64 from dff.api.vfs.libvfs import AttributesHandler, VFS from dff.modules.structparser import Struct, Header, ResolveAttributesMap, AttributesVMap class PrefetchParser(): PrefetchMagic = [("\x11\x00\x00\x00\x53\x43\x43\x41", "prefetch_XP", "Windowx XP"), ("\x17\x00\x00\x00\x53\x43\x43\x41", "prefetch_Vista", "Windows Vista")] PrefetchHeader = ({ "info" : { "os":"windows" , "arch":"x86", "name" : "prefetch" }, "descr" : { "prefetch_XP" : ((0x98), { "Standard" : (0x98, 0, "prefetch_standard"), "LastExecutionTime" : (8, 0x78), "NumberOfExecution" : (4, 0x90) }), "prefetch_Vista" : ((0xf0), { "Standard" : (0x98, 0, "prefetch_standard"), "LastExecutionTime" : (8, 0x80), "NumberOfExecution" : (4, 0x98) }), "prefetch_standard" : ((0x98), { "Header" : (8, 0), "HeaderSize" : (4, 0x54), #"ApplicationName" : (?, 0x10), "FileSize" : (4, 0xc), "FirstFilePathBlock" : (4, 0x64), "FirstFilePathSize" : (4, 0x68), "VolumeInformationBlock" : (4, 0x6c, "*VolumeInformationBlock"), }), "VolumeInformationBlock" : ((0x28), { "VolumePathOffset" : (4, 0x00), "VolumePathLength" : (4, 0x04), "VolumeCreationDate" : (8, 0x08), "VolumeSerialNumber" : (4, 0x10), "OffsetToBlob1" : (4, 0x14), "LengthOfBlob1" : (4, 0x18), "OffsetToFolderPaths" : (4, 0x1c), "NumberOfFolderPaths" : (4, 0x20), "Unknown1" : (4, 0x24) }) } }) PrefetchAttributesMap = { "Version" : ("version_name", str), "Last execution" : (("prefetch.LastExecutionTime", TIME_MS_64), vtime), "Number of execution" : ("prefetch.NumberOfExecution", int), "Prefetch list" : ("prefetchFileList", list), "Volume creation" : (("prefetch.Standard.VolumeInformationBlock.VolumeCreationDate", TIME_MS_64), vtime), "Number of folder paths" : ("prefetch.Standard.VolumeInformationBlock.NumberOfFolderPaths", int), "Serial number" : ("prefetch.Standard.VolumeInformationBlock.VolumeSerialNumber", int), "Volume path" : ("volumePath", str), "Volume prefetch list" : ("VolumePrefetchList", list) } def __init__(self, node): self.node = node self.vfile = node.open() self.attr = {} try : self.header = Header(self.PrefetchHeader) self.vfile.seek(0) magic_data = self.vfile.read(8) for magic, version, version_name in self.PrefetchMagic: if magic_data == magic: prefetch_version = getattr(self.header, version) self.version_name = version_name if not version: self.vfile.close return self.vfile.seek(0) self.data = self.vfile.read(prefetch_version.ssize) self.prefetch = Struct(self.header, self.vfile, prefetch_version, self.data) self.vfile.seek(self.prefetch.Standard.FirstFilePathBlock) self.data = self.vfile.read(self.prefetch.Standard.FirstFilePathSize) self.prefetchFileList = unicode(self.data.decode('utf-16')).split("\x00") try: self.prefetchFileList.remove('') except ValueError: pass self.prefetchFileList = map(lambda x : (x, str), self.prefetchFileList) self.vfile.seek(self.prefetch.Standard.VolumeInformationBlock.VolumePathOffset + self.prefetch.Standard.VolumeInformationBlock.pointer) self.volumePath = self.vfile.read(self.prefetch.Standard.VolumeInformationBlock.VolumePathLength *2).decode('UTF-16') self.VolumePrefetchList = [] self.vfile.seek(self.prefetch.Standard.VolumeInformationBlock.pointer + self.prefetch.Standard.VolumeInformationBlock.OffsetToFolderPaths) pathSize = unpack('h', self.vfile.read(2))[0] count = 0 while (pathSize > 0 and count < self.prefetch.Standard.VolumeInformationBlock.NumberOfFolderPaths): self.VolumePrefetchList.append((unicode(self.vfile.read(pathSize * 2+2)).decode('UTF-16'), str)) count += 1 pathSize = unpack('h', self.vfile.read(2))[0] self.vfile.close() except : #err_type, err_value, err_traceback = sys.exc_info() #for n in traceback.format_exception_only(err_type, err_value): #print n #for n in traceback.format_tb(err_traceback): #print n self.vfile.close() raise Exception("Init error") def attributesMap(self): try: return ResolveAttributesMap(self, self.PrefetchAttributesMap) except: pass class PrefetchHandler(AttributesHandler, ModuleProcessusHandler): #garder module processus handler ou utiliser autre chose ? car si on le met a chaque fois c un peu redondant de le mettre partout def __init__(self): AttributesHandler.__init__(self, "prefetch") ModuleProcessusHandler.__init__(self, "prefetch") self.__disown__() self.nodeAttributes = {} self.vfs = VFS.Get() def setAttributes(self, node, attributes): self.nodeAttributes[long(node.this)] = attributes def update(self, processus): pass def nodes(self, root): nodes = [] rootAbsolute = root.absolute() for node in self.nodeAttributes.keys(): node = self.vfs.getNodeFromPointer(node) if node.absolute().find(rootAbsolute) == 0: nodes.append(node) return nodes def attributes(self, node): try: attr = self.nodeAttributes[long(node.this)] return AttributesVMap(attr) except KeyError: attr = VMap() return attr class Prefetch(Script): def __init__(self): Script.__init__(self, "prefetch") self.handler = PrefetchHandler() def start(self, args): try: node = args['file'].value() p = PrefetchParser(node) arg = p.attributesMap() self.stateinfo = "Registering node: " + str(node.name()) self.handler.setAttributes(node, arg) node.registerAttributes(self.handler) except (KeyError, Exception): pass class prefetch(Module): """This modules generate metadata for prefetch files""" def __init__(self): Module.__init__(self, "prefetch", Prefetch) self.conf.addArgument({"name": "file", "description": "file to extract metadata", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "extension-type", "type": typeId.String, "description": "compatible extension", "values": ["pf"]}) self.flags = ["single"] self.tags = "Metadata" dff-1.3.0+dfsg.1/dff/modules/metadata/structparser.py000066400000000000000000000161761217176075400224570ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob import sys, traceback from struct import unpack from dff.api.vfs.libvfs import VLink from dff.api.types.libtypes import Variant, VMap, VList, Argument, typeId, vtime, TIME_MS_64 def getRecAttr(parent, attr): for attr in attr.split('.'): parent = getattr(parent, attr) return parent def ResolveAttributesMap(obj, attributesMap): attr = {} for k, v in attributesMap.iteritems(): if type(v) == dict: try: d = {} for kk, vv in v.iteritems(): try: if (type(vv[0]) == str): d[kk] = (getRecAttr(obj, vv[0]), vv[1]) else: d[kk] = ((getRecAttr(obj, vv[0][0]), vv[0][1],), vv[1]) except AttributeError, e: pass if len(d): attr[k] = (d, dict) except: pass else: try: if (type(v[0]) == str): attr[k] = (getRecAttr(obj, v[0]), v[1]) else: attr[k] = ((getRecAttr(obj, v[0][0]), v[0][1],), v[1]) except AttributeError, e: pass return attr def attributesTypes(values, types): if types == vtime: val = vtime(*values) #(X, X) vtime take 2 arguments val.thisown = False elif (types == int) or (types == long): if type(values) == str: #XXX strange ? values = 0 val = types(values) elif (types == dict): val = VMap() for k, v in values.iteritems(): vval = Variant(attributesTypes(*v)) val[k] = vval elif (types == list): val = VList() for v in values: vval = Variant(attributesTypes(*v)) val.append(vval) elif (types == str): if type(values) == unicode: val = values.encode("ascii", "replace") else: val = str(values) elif (types == VLink): #return node is already created val = values else: val = types(values) return val def AttributesVMap(attrib): vattr = VMap() for attr, (values, types) in attrib.iteritems(): try : value = attributesTypes(values, types) try: v = Variant(value) except : err_type, err_value, err_traceback = sys.exc_info() print traceback.format_exception_only(err_type, err_value) print traceback.format_tb(err_traceback) print "invalid variant value : " + str(value) + " type: " + str(type(value)) vattr[attr] = v except : #pass err_type, err_value, err_traceback = sys.exc_info() print traceback.format_exception_only(err_type, err_value) print traceback.format_tb(err_traceback) print "error on attr:" + str(attr) + " val: " + str(type(value)) return vattr def FlagsList(binAttributes, attributesFlags): s = bin(binAttributes).replace('0b','')[::-1] pad = 32 - len(s) s += (32 - len(s))*'0' attributesList = [] for i in xrange(0, len(s)): if int(s[i]): try: attributesList.append((attributesFlags[i], str,)) except IndexError: pass return attributesList class StructDef(object): def __init__(self, size, offset = None, stype = None, sshift = 0): self.ssize = size self.offset = offset ###virer le plus de self possible ca prend de la ram pour rien si ca sert pas apres self.stype = stype self.shift = sshift self.var = {} pointer_count = [] class Struct(StructDef): def __init__(self, arch, file, structdef, data): self.arch = arch self.file = file self.structdef = structdef StructDef.__init__(self, self.structdef.ssize, self.structdef.offset, self.structdef.stype) for varname, var in self.structdef.var.iteritems(): setattr(self, varname, self.getVarValue(varname, data)) def getVarValue(self, varname, data): var = self.structdef.var[varname] intssize = var.ssize / 4 try : if var.stype: if var.stype[0] == "*": pack = "I" (pointer, ) = unpack(pack, data[var.offset:var.offset + var.ssize]) struct_addr = pointer + var.shift struct_type = var.stype[1:] struct_def = getattr(self.arch, struct_type) if struct_addr > 0 and (struct_addr + struct_def.ssize) <= self.file.node().size(): self.file.seek(struct_addr) data = self.file.read(struct_def.ssize) struct_def.stype = struct_type struct_def.offset = 0 try : if pointer in pointer_count: return pointer pointer_count.append(pointer) rstruct = Struct(self.arch, self.file, struct_def, data[0: struct_def.ssize]) rstruct.pointer = pointer except : error = sys.exc_info() print error #print "error pointer to struct" return pointer return rstruct return pointer if len(var.stype) : sdef = getattr(self.arch, var.stype) return Struct(self.arch, self.file, sdef, data[var.offset:var.offset + var.ssize]) elif var.ssize == 2: pack = "H" elif var.ssize == 4: pack = "I" #patch test for Q elif var.ssize == 8: pack = "Q" if var.ssize == 4: pack = "I" elif var.ssize == 2: pack = "H" #patch test for Q elif var.ssize == 8: #Q ==8 en 64 et en 32 bitrs ?? pack = "Q" else: pack = str(var.ssize) + "s" (var_data, ) = unpack(pack, data[var.offset:var.offset + var.ssize]) return var_data except AttributeError: return None def __str__(self): buff = "" for varname, var in self.structdef.var.iteritems(): var = getattr(self, varname) if isinstance(var, int) or isinstance(var, long): buff += varname + ": " + hex(var) + "\n" elif isinstance(var, Struct): buff += varname + ":" + repr(var) + "\n" else: buff += varname + ": " + str(var) + "\n" return buff def rstr(self): buff = "" for varname, var in self.structdef.var.iteritems(): var = getattr(self, varname) if isinstance(var, int) or isinstance(var, long): buff += varname + ": " + hex(var) + "\n" elif isinstance(var, Struct): buff += varname + "\n{\n" + var.rstr() + "}\n" else: buff += varname + ": " + str(var) + "\n" return buff class Header(object): def __init__(self, header_descr): for name, val in header_descr["info"].iteritems(): setattr(self, name, val) self.struct_def = header_descr["descr"] for struct_name, (struct_size, var_map) in self.struct_def.iteritems(): setattr(self, struct_name, StructDef(struct_size, 0, struct_name)) for valname, val in var_map.iteritems(): st = getattr(self, struct_name) st.var[valname] = StructDef(*val) dff-1.3.0+dfsg.1/dff/modules/node/000077500000000000000000000000001217176075400164765ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/node/CMakeLists.txt000066400000000000000000000011261217176075400212360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( cut.py merge.py split.py ) dff-1.3.0+dfsg.1/dff/modules/node/cut.py000066400000000000000000000060751217176075400176530ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_cut_version__ = "1.0.0" from struct import unpack from dff.api.vfs import * from dff.api.module.module import * from dff.api.vfs.libvfs import * from dff.api.types.libtypes import Variant, VMap, Parameter, Argument, typeId from dff.api.vfs.libvfs import AttributesHandler from dff.modules.spare import SpareNode class CutNode(Node): def __init__(self, mfso, parent, name, startOff, size): self.startOff = startOff self.ssize = size self.pparent = parent if self.ssize == None or self.ssize == 0 or self.ssize < 0: self.ssize = parent.size() - startOff Node.__init__(self, name + "-" + hex(startOff), self.ssize, None, mfso) self.__disown__() self.name = name def fileMapping(self, fm): fm.push(0, self.ssize, self.pparent, self.startOff) def _attributes(self): attr = VMap() attr["start offset"] = Variant(self.startOff) return attr class Cut(mfso): def __init__(self): mfso.__init__(self, "Cut") self.name = "Cut" self.__disown__() def start(self, args): self._if = args["input"].value() self._of = args["output"].value() self.start = args["start_offset"].value() self.size = args["size"].value() self.nof = CutNode(self, self._if, self._of, self.start, self.size) self.nof.__disown__() self.registerTree(self._if, self.nof) class cut(Module): """This modules allow you to cut a node from a starting offset""" def __init__(self): Module.__init__(self, "cut", Cut) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "input", "description": "Input node which will be cut" }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.String, "name": "output", "description": "Output name of created node" }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.UInt64, "name": "start_offset", "description": "Address start of the new node" }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.UInt64, "name": "size", "description": "Size readed after start's address. If not specified, read until EOF" }) self.icon = ":editcut" self.tags = "Node" dff-1.3.0+dfsg.1/dff/modules/node/merge.py000066400000000000000000000062571217176075400201610ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon < rbe@arxsys.fr> # __dff_module_merge_version__ = "1.0.0" from struct import unpack from dff.api.vfs import * from dff.api.module.module import * from dff.api.types.libtypes import Variant, VList, VMap, Argument, Parameter, typeId from dff.api.vfs.libvfs import * class MergeNode(Node): def __init__(self, name, size, parent, mfso, files): Node.__init__(self, name, size, parent, mfso) self.files = files self.__disown__() def fileMapping(self, fm): offset = 0 for f in self.files: node = f.value() fm.push(offset, node.size(), node, 0) offset += node.size() def _attributes(self): i = 1 attr = VMap() vlist = VList() for f in self.files: node = f.value() vlist.append(Variant(node.absolute())) attr["concatanated files (ordered)"] = Variant(vlist) return attr class MERGE(mfso): def __init__(self): mfso.__init__(self, "merge") self.__disown__() def start(self, args): self.files = args['files'].value() if args.has_key("output"): name = args["output"].value() else: name = self.files[0].value().name() + "..." + self.files[len(self.files) - 1].value().name() if args.has_key("parent"): parent = args["parent"].value() else: parent = self.files[0].value().parent() size = 0 for f in self.files: size += f.value().size() self.merge_node = MergeNode(name, size, None, self, self.files) self.merge_node.__disown__() self.registerTree(parent, self.merge_node) class merge(Module): """This module is designed to concatenate two files.""" def __init__(self): Module.__init__(self, "merge", MERGE) self.conf.addArgument({"input": Argument.Required|Argument.List|typeId.Node, "name": "files", "description": "these files will be concatenated in the order they are provided", "parameters": {"type": Parameter.Editable, "minimum": 2} }) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.String, "name": "output", "description": "the name of file corresponding to the concatenation" }) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.Node, "name": "parent", "description": "parent of the resulting output file (default will be basefile)" }) self.tags = "Node" dff-1.3.0+dfsg.1/dff/modules/node/split.py000066400000000000000000000121421217176075400202030ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_cut_version__ = "1.0.0" from struct import unpack from dff.api.vfs import * from dff.api.module.module import * from dff.api.vfs.libvfs import * from dff.api.types.libtypes import Variant, VMap, Parameter, Argument, typeId from dff.api.vfs.libvfs import AttributesHandler from dff.modules.spare import SpareNode class SplitNode(Node): def __init__(self, mfso, parent, origin, soffset, size): self.soffset = soffset self.ssize = size self.pparent = parent self.origin = origin if self.ssize == None or self.ssize == 0 or self.ssize < 0: self.ssize = parent.size() - soffset start = hex(soffset) lenstart = len(start[2:]) if lenstart < 16: start = "0x" + ("0" * (16 - lenstart)) + start[2:] end = hex(soffset + size) lenend = len(end[2:]) if lenend < 16: end = "0x" + ("0" * (16 - lenend)) + end[2:] Node.__init__(self, start + "-" + end, self.ssize, parent, mfso) self.__disown__() def fileMapping(self, fm): fm.push(0, self.ssize, self.origin, self.soffset) def _attributes(self): attr = VMap() attr["start offset"] = Variant(self.soffset) return attr class Split(mfso): def __init__(self): mfso.__init__(self, "Split") self.name = "Split" self.__disown__() def __split(self, root, chunksize): nodesize = self.origin.size() chunks = nodesize / chunksize vmap = VMap() vmap["complete chunks"] = Variant(chunks) for idx in xrange(0, chunks*chunksize, chunksize): snode = SplitNode(self, root, self.origin, idx, chunksize) lastchunk = nodesize % chunksize if lastchunk != 0: snode = SplitNode(self, root, self.origin, self.origin.size() - lastchunk, lastchunk) vmap["truncated chunk (size)"] = Variant(lastchunk) self.res[str(chunksize) + " bytes split"] = Variant(vmap) def start(self, args): self.origin = args["file"].value() if args.has_key("start-offset"): self.soffset = args["start-offset"].value() else: self.soffset = 0 self.chunklist = args["chunk-sizes"].value() nodesize = self.origin.size() err = "" if self.soffset < 0: err += "start offset (" + str(self.soffset) + ") must be equal or greater to 0\n" if self.soffset >= nodesize: err += "start offset (" + str(self.soffset) + ") must be lesser than size of provided node\n" if not err: for vchunksize in self.chunklist: cerr = "" chunksize = vchunksize.value() if chunksize <= 0: cerr += "size of chunk (" + str(chunksize) + " bytes) must be positive\n" if chunksize >= nodesize: cerr += "size of chunk (" + str(chunksize) + " bytes) must be lesser than size of provided node\n" if not cerr: root = Node(self.origin.name() + " splitted by " + str(chunksize), 0, None, self) root.__disown__() self.__split(root, chunksize) self.registerTree(self.origin, root) else: err += cerr if err: self.res["error"] = Variant(err) class split(Module): """This modules allow you to cut a node from a starting offset""" def __init__(self): Module.__init__(self, "split", Split) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "file", "description": "Input node which will be splitted" }) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.UInt64, "name": "start-offset", "description": "Offset from start splitting", "parameters": {"type": Parameter.Editable, "predefined": [0]} }) self.conf.addArgument({"input": Argument.Required|Argument.List|typeId.UInt64, "name": "chunk-sizes", "description": "specifies the size for each chunk", "parameters": {"type": Parameter.Editable, "predefined": [512, 1024, 2048, 4096, 8192]} }) self.icon = ":editcut" self.tags = "Node" dff-1.3.0+dfsg.1/dff/modules/ram/000077500000000000000000000000001217176075400163305ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/CMakeLists.txt000066400000000000000000000011511217176075400210660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py ) add_subdirectory (volatility) dff-1.3.0+dfsg.1/dff/modules/ram/__init__.py000066400000000000000000000011161217176075400204400ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['Volatility-1.3_Beta'] dff-1.3.0+dfsg.1/dff/modules/ram/volatility/000077500000000000000000000000001217176075400205305ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/CMakeLists.txt000066400000000000000000000013371217176075400232740ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( dfwrapper.py setup.py vmodules.py volatility.py vsyms.py vtypes.py vutils.py ) add_subdirectory(memory_objects) add_subdirectory(memory_plugins) add_subdirectory(forensics) add_subdirectory(thirdparty) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/dfwrapper.py000066400000000000000000000232011217176075400230720ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from datetime import * from vutils import * from forensics.win32.tasks import * from forensics.win32.handles import * from forensics.win32.executable import rebuild_exe_dsk,rebuild_exe_mem from forensics.win32.network import * from dff.api.vfs import * from dff.api.module.module import * from dff.api.types.libtypes import Variant, VMap, vtime from dff.api.vfs.libvfs import * from dff.api.exceptions import * class NodeProcessus(Node): def __init__(self, name, ssize, mfso, parent, pid = None): self.mfso = mfso self.ssize = 0 self.active_threads = None self.inherited_from = None self.handle_count = None self.create_time = None self.connections = None self.pid = pid Node.__init__(self, name, self.ssize, parent, mfso) self.__disown__() self.setFile() setattr(self, "addMapping", self.addMapping) self.virtMapping = [] setattr(self, "fileMapping", self.fileMapping) def fileMapping(self, fm): noffset = 0 for (offset , size) in self.virtMapping: fm.push(noffset, size, self.mfso.node, offset) noffset += size def addMapping(self, offset, size): self.virtMapping.append((offset, size)) self.ssize += size self.setSize(self.ssize) def _attributes(self): attr = VMap() if self.pid != None: attr["pid"] = Variant(self.pid) if self.active_threads: attr["threads"] = Variant(self.active_threads) if self.inherited_from: attr["ppid"] = Variant(self.inherited_from) if self.handle_count: attr["handle count"] = Variant(self.handle_count) if self.connections: attr["connection"] = Variant(self.connections) if self.create_time: at = vtime() at.thisown = False d = datetime.fromtimestamp(self.create_time).timetuple() at.year = d[0] at.month = d[1] at.day = d[2] at.hour = d[3] at.minute = d[4] at.second = d[5] at.usecond = 0 attr["creation"] = Variant(at) return attr def setMeta(self, active_threads, inherited_from, handle_count, create_time): self.active_threads = active_threads self.inherited_from = inherited_from self.handle_count = handle_count self.create_time = create_time def setConnections(self, connections): self.connections = connections class processus(): def __init__(self, mfso, task, nodename, addr_space, types, symtab): self.mfso = mfso self.nodename = nodename self.task = task self.addr_space = addr_space self.types = types self.symtab = symtab self.image_file_name = process_imagename(self.addr_space, self.types, self.task) self.process_id = process_pid(self.addr_space, self.types, self.task) if self.image_file_name is None: if self.process_id != None: self.image_file_name = "Process-" + str(self.process_id) else: self.image_file_name = "Process-Unknown" if self.process_id != None: self.node = NodeProcessus(self.image_file_name, 0, mfso, mfso.root) else: self.node = NodeProcessus(self.image_file_name, 0, mfso, mfso.root, self.process_id) def getMeta(self): active_threads = process_num_active_threads(self.addr_space, self.types, self.task) inherited_from = process_inherited_from(self.addr_space, self.types, self.task) handle_count = process_handle_count(self.addr_space, self.types, self.task) create_time = process_create_time(self.addr_space, self.types, self.task) self.node.setMeta(active_threads, inherited_from, handle_count, create_time) def getConnections(self): connections = tcb_connections(self.addr_space, self.types, self.symtab) for connection in connections: if not self.addr_space.is_valid_address(connection): continue pid = connection_pid(self.addr_space, self.types, connection) if self.process_id == pid: lport = connection_lport(self.addr_space, self.types, connection) laddr = connection_laddr(self.addr_space, self.types, connection) rport = connection_rport(self.addr_space, self.types, connection) raddr = connection_raddr(self.addr_space, self.types, connection) local = "%s:%d"%(laddr,lport) remote = "%s:%d"%(raddr,rport) cnx = "%-25s---> %-25s"%(local,remote) self.node.setConnections(cnx) def dump(self, mode = "disk"): mode = "disk" if mode == "disk": rebuild_exe = rebuild_exe_dsk elif mode == "mem": rebuild_exe = rebuild_exe_mem directory_table_base = process_dtb(self.addr_space, self.types, self.task) process_address_space = create_addr_space(self.addr_space, directory_table_base) if process_address_space is None: return "Error obtaining address space for process [%d]" % (self.process_id) image_file_name = process_imagename(process_address_space, self.types, self.task) peb = process_peb(process_address_space, self.types, self.task) img_base = read_obj(process_address_space, self.types, ['_PEB', 'ImageBaseAddress'], peb) if img_base == None: return "Error: Image base not memory resident for process [%d]" % (self.process_id) if process_address_space.vtop(img_base) == None: return "Error: Image base not memory resident for process [%d]" % (self.process_id) try: rebuild_exe(process_address_space, self.types, img_base, self.node) except ValueError,ve: return "Unable to dump executable; sanity check failed: " + ve + "You can use -u to disable this check." def addEntryNode(self, entry): if not self.addr_space.is_valid_address(entry): return obj = handle_entry_object(self.addr_space, self.types, entry) if self.addr_space.is_valid_address(obj): if is_object_file(self.addr_space, self.types, obj): file = object_data(self.addr_space, self.types, obj) fname = file_name(self.addr_space, self.types, file) if fname != "": fname = fname.replace("\\", "/") fname = fname.split('/') current_node = self.node for n in fname: if n != '': exist = None children = current_node.children() for c in children: if n == c.name(): exist = c if exist: current_node = exist else: new_node = Node(n) new_node.__disown__() current_node.addChild(new_node) current_node = new_node def getOpenFiles(self): """ Creates node for each open files for each process. """ htables = [] htables = handle_tables(self.addr_space, self.types, self.symtab, self.process_id) for table in htables: process_id = handle_process_id(self.addr_space, self.types, table) if process_id == None: continue table_code = handle_table_code(self.addr_space, self.types, table) if table_code == 0: continue table_levels = handle_table_levels(self.addr_space, self.types, table) if table_levels == 0: num_entries = handle_num_entries(self.addr_space, self.types, table) for counter in range(0, 0x200): entry = handle_table_L1_entry(self.addr_space, self.types, table, counter) if entry != None and entry !=0: self.addEntryNode(entry) elif table_levels == 1: for i in range(0, 0x200): L1_entry = handle_table_L1_entry(self.addr_space, self.types, table, i) if not L1_entry is None: L1_table = handle_entry_object(self.addr_space, self.types, L1_entry) for j in range(0, 0x200): L2_entry = handle_table_L2_entry(self.addr_space, self.types, table, L1_table, j) if not L2_entry is None: self.addEntryNode(L2_entry) elif table_levels == 2: for i in range(0, 0x200): L1_entry = handle_table_L1_entry(self.addr_space, self.types, table, i) if not L1_entry is None: L1_table = handle_entry_object(L1_entry) for j in range(0, 0x200): L2_entry = handle_table_L2_entry(self.addr_space, self.types, table, L1_table, j) if not L2_entry is None: L2_table = handle_entry_object(self.addr_space, self.types, L2_entry) for k in range(0, 0x200): L3_entry = handle_table_L3_entry(self.addr_space, self.types, table, L2_table, j) if not L3_entry is None: self.addEntryNode(self.addr_space, self.types, L3_entry) class op(): def __init__(self, node): self.node = node self.filename = node.absolute() self.base = None self.type = None def error(self, msg): print msg dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/000077500000000000000000000000001217176075400225235ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/CMakeLists.txt000066400000000000000000000013041217176075400252610ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( addrspace.py commands.py __init__.py object2.py object.py registry.py symbols.py x86.py ) add_subdirectory(win32) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/__init__.py000066400000000000000000000000001217176075400246220ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/addrspace.py000077500000000000000000000044041217176075400250300ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Original Source: # Copyright (C) 2004,2005,2006 4tphi Research # Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ """ Alias for all address spaces """ import os import struct from dff.api.vfs import * class FileAddressSpace: def __init__(self, fname, mode='rb', fast=False): self.fname = fname self.name = fname self.vfs = vfs.vfs() #self.fhandle = open(fname, mode) self.fhandle = self.vfs.open(fname) # self.fsize = os.path.getsize(fname) self.fsize = self.fhandle.node().size() if fast == True: #self.fast_fhandle = open(fname, mode) self.fast_fhandle = self.vfs.open(fname) def fread(self,len): return self.fast_fhandle.read(len) def read(self, addr, len): self.fhandle.seek(addr) return self.fhandle.read(len) def zread(self, addr, len): return self.read(addr, len) def read_long(self, addr): string = self.read(addr, 4) (longval, ) = struct.unpack('=L', string) return longval def get_address_range(self): return [0,self.fsize-1] def get_available_addresses(self): return [0,self.get_address_range()] def is_valid_address(self, addr): if addr == None: return False return addr < self.fsize - 1 def close(): self.fhandle.close() dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/commands.py000066400000000000000000000043221217176075400246770ustar00rootroot00000000000000# Volatility # Copyright (C) 2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # import optparse from vutils import * class command: """ Base class for each plugin command """ op = "" opts = "" args = "" cmdname ="" meta_info = {} def __init__(self,args=None): """ Constructor uses args as an initializer. It creates an instance of OptionParser, populates the options, and finally parses the command line. Options are stored in the self.opts attribute. """ if args == None: return self.cmdname = self.__class__.__name__ self.parser() self.opts, self.args = self.op.parse_args(args) def help(self): """ This function returns a string that will be displayed when a user lists available plugins. """ return "" def parser(self): """ This method defines a parser for this plugin command. It is used to create an instance of OptionParser and populate its options. The OptionParser instances in stored in self.op. By default, it simply calls the standard parser. The standard parser provides the following command line options: '-f', '--file', '(required) Image file' '-b', '--base', '(optional) Physical offset (in hex) of DTB' '-t', '--type', '(optional) Identify the image type' A plugin command may override this function in order to extend the standard parser. """ self.op = get_standard_parser(self.cmdname) def execute(self): """ Executes the plugin command.""" dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/object.py000066400000000000000000000146731217176075400243560ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Original Source: # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ import struct builtin_types = { \ 'int' : (4, 'l'), \ 'long': (4, 'l'), \ 'unsigned long' : (4, 'L'), \ 'unsigned int' : (4, 'I'), \ 'address' : (4, 'L'), \ 'char' : (1, 'c'), \ 'unsigned char' : (1, 'B'), \ 'unsigned short' : (2, 'H'), \ 'short' : (2, 'h'), \ 'long long' : (8, 'q'), \ 'unsigned long long' : (8, 'Q'), \ 'pointer' : (4, 'L'),\ } def obj_size(types, objname): if not types.has_key(objname): raise Exception('Invalid type %s not in types' % (objname)) return types[objname][0] def builtin_size(builtin): if not builtin_types.has_key(builtin): raise Exception('Invalid built-in type %s' % (builtin)) return builtin_types[builtin][0] def read_value(addr_space, value_type, vaddr): """ Read the low-level value for a built-in type. """ if not builtin_types.has_key(value_type): raise Exception('Invalid built-in type %s' % (value_type)) type_unpack_char = builtin_types[value_type][1] type_size = builtin_types[value_type][0] buf = addr_space.read(vaddr, type_size) if buf is None: return None (val, ) = struct.unpack('='+type_unpack_char, buf) return val def read_unicode_string(addr_space, types, member_list, vaddr): offset = 0 if len(member_list) > 1: (offset, current_type) = get_obj_offset(types, member_list) buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset) length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset) if length == 0x0: return "" if buf is None or length is None: return None readBuf = read_string(addr_space, types, ['char'], buf, length) if readBuf is None: return None try: readBuf = readBuf.decode('UTF-16').encode('ascii', 'backslashreplace') except: return None return readBuf def read_unicode_string_p(phys_addr_space, virt_addr_space, types, member_list, phys_addr): ''' Reads a unicode string in virtual address space that is indicated by a pointer into physical address space ''' offset = 0 if len(member_list) > 1: (offset, current_type) = get_obj_offset(types, member_list) # read string length and buffer pointer into virtual address space buf = read_obj(phys_addr_space, types, ['_UNICODE_STRING', 'Buffer'], phys_addr + offset) length = read_obj(phys_addr_space, types, ['_UNICODE_STRING', 'Length'], phys_addr + offset) if buf is None or length is None: return None readBuf = read_string(virt_addr_space, types, ['char'], buf, length) if readBuf is None: return None try: readBuf = readBuf.decode('UTF-16').encode('ascii','backslashreplace') except: return None return readBuf def read_string(addr_space, types, member_list, vaddr, max_length=256): offset = 0 if len(member_list) > 1: (offset, current_type) = get_obj_offset(types, member_list) val = addr_space.read(vaddr + offset, max_length) return val def read_null_string(addr_space, types, member_list, vaddr, max_length=256): string = read_string(addr_space, types, member_list, vaddr, max_length) if string is None: return None if (string.find('\0') == -1): return string (string, none) = string.split('\0', 1) return string def get_obj_offset(types, member_list): """ Returns the (offset, type) pair for a given list """ member_list.reverse() current_type = member_list.pop() offset = 0 while (len(member_list) > 0): if current_type == 'array': current_type = member_dict[current_member][1][2][0] if current_type in builtin_types: current_type_size = builtin_size(current_type) else: current_type_size = obj_size(types, current_type) index = member_list.pop() offset += index * current_type_size continue elif not types.has_key(current_type): raise Exception('Invalid type ' + current_type) member_dict = types[current_type][1] current_member = member_list.pop() if not member_dict.has_key(current_member): raise Exception('Invalid member %s in type %s' % (current_member, current_type)) offset += member_dict[current_member][0] current_type = member_dict[current_member][1][0] return (offset, current_type) def read_obj(addr_space, types, member_list, vaddr): """ Read the low-level value for some complex type's member. The type must have members. """ if len(member_list) < 2: raise Exception('Invalid type/member ' + str(member_list)) (offset, current_type) = get_obj_offset(types, member_list) return read_value(addr_space, current_type, vaddr + offset) def read_obj_from_buf(data,data_types,member_list,doffset): (offset, current_type) = get_obj_offset(data_types,member_list) if not builtin_types.has_key(current_type): raise Exception('Invalid built-in type %s' % (current_type)) voffset = doffset + offset type_unpack_char = builtin_types[current_type][1] type_size = builtin_types[current_type][0] if voffset+type_size > len(data): return buf = data[voffset:voffset+type_size] (val, ) = struct.unpack('='+type_unpack_char, buf) return val dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/object2.py000066400000000000000000000361121217176075400244300ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Copyright (C) 2005,2006 4tphi Research # Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ from vtypes import xpsp2types as types from forensics.object import * from forensics.x86 import x86_native_types import forensics.registry as MemoryRegistry import struct class InvalidType(Exception): def __init__(self, typename=None): self.typename = typename def __str__(self): return str(self.typename) class InvalidMember(Exception): def __init__(self, typename=None, membername=None): self.typename = typename self.membername = membername def __str__(self): return str(self.typename) + ":" + str(self.membername) class Object(object): def __new__(pcls, theType, offset, vm, parent=None, profile=None): theTypeName = None if isinstance(theType, str): theTypeName = theType elif isinstance(theType, CType): theTypeName = theType.name # Need to check for any derived object types that may be # found in the global memory registry. if theTypeName: if MemoryRegistry.OBJECT_CLASSES.objects.has_key(theTypeName): return MemoryRegistry.OBJECT_CLASSES[theTypeName](theTypeName, \ offset,vm,parent,profile) obj = object.__new__(pcls) return obj def __init__(self, theType, offset, vm, parent=None, profile=None): self.vm = vm self.members = {} self.parent = parent self.extra_members = {} self.profile = profile self.offset = offset if offset == None: return None if not isinstance(theType, str): self.type = theType elif theType in profile.cstructs: self.type = profile.cstructs[theType] elif theType in builtin_types and theType != 'pointer': self.type = NativeType(profile, theType, \ builtin_types[theType][0], builtin_types[theType][1]) else: raise InvalidType,theType def __getattribute__(self, attr): try: return object.__getattribute__(self, attr) except AttributeError: pass if attr in self.extra_members: return self.extra_members[attr] if isinstance(self.type, Pointer): return self.type.dereference(self) if self.type.name in builtin_types: raise AttributeError("Native types have no dynamic attributes") off = self.get_member_offset(attr, relative=True) ObjectMember = self.get_member(attr) if off == None or ObjectMember == None: raise AttributeError("'%s':no offset or type for attribute '%s'" % \ (self.type.name, attr)) if isinstance(ObjectMember.type, Pointer): cdecl = ObjectMember.type.basetype.cdecl() if cdecl == 'void': return Object(ObjectMember.type.basetype, \ off+self.offset, self.vm,profile=self.profile) base_address = self.get_member(attr).v() if base_address == None: return None return Object(ObjectMember.type.basetype, base_address, \ self.vm,profile=self.profile) elif isinstance(ObjectMember.type, CType): theTypeName = ObjectMember.type.name if MemoryRegistry.OBJECT_CLASSES.objects.has_key(ObjectMember.type.name): offset = self.offset + off return MemoryRegistry.OBJECT_CLASSES[theTypeName](theTypeName,offset,self.vm,self,self.profile) return ObjectMember elif isinstance(ObjectMember.type,Array): array_vals= [] for index in ObjectMember.type.get_member_names(): element = Object(ObjectMember.type.basetype, \ ObjectMember.offset + index * \ ObjectMember.type.basetype.size, \ self.vm,profile=self.profile) if isinstance(element.type, NativeType): array_vals.append(element.v()) else: array_vals.append(element) return array_vals else: return self.get_member(attr).v() def __eq__(self, other): if isinstance(other, Object): return (self.type == other.type) and (self.offset == other.offset) else: return NotImplemented def __ne__(self, other): result = self.__eq__(other) if result is NotImplemented: return result return not result def __hash__(self): return hash(self.type.name) ^ hash(self.offset) def has_member(self, memname): return self.type.hasMembers and self.type.members.has_key(memname) def m(self, memname): return self.get_member(memname) def get_member(self, memname): if not self.type.hasMembers: return None if memname in self.extra_members: return self.extra_members[memname] if self.members.has_key(memname): return self.members[memname] else: thisMember = self.type.get_member(memname) if isinstance(thisMember.type, Pointer) or isinstance(thisMember.type, Array): thisObject = Object(thisMember.type, \ self.offset + thisMember.offset, self.vm, self,self.profile) return thisObject thisObject = Object(thisMember.type.name, \ self.offset + thisMember.offset, self.vm, self,self.profile) return thisObject def get_member_type(self, memname): if self.type.hasMembers: thisMemberType = self.type.get_member(memname) return thisMemberType else: return None def get_member_offset(self, memname, relative=False): if self.type.hasMembers: thisMemberType = self.type.get_member(memname) if thisMemberType == None: return None if relative: return thisMemberType.offset return thisMemberType.offset + self.offset else: return None def is_null(self): if isinstance(self.type, Pointer): return self.v() == 0x00 else: return False def is_valid(self): if isinstance(self.type, Pointer): if self.v() == None: return False return self.vm.is_valid_address(self.v()) elif isinstance(self.type, CType): return self.vm.is_valid_address(self.offset) else: return False def dereference(self): if isinstance(self.type, Pointer): return self.type.dereference(self) return None def dereference_as(self, castType): if isinstance(self.type, Pointer): return self.type.dereference_as(castType, self) elif isinstance(self.type, Void): return self.type.dereference_as(castType, self) else: return None def cast(self, castString): if castString in self.type.profile.native_types: return Object(castString, self.offset, self.vm, None, self.profile) else: return Object(castString, self.offset, self.vm, None, self.profile) def size(self): return self.type.size def v(self): return self.value() def value(self): if self.type.hasValue: return self.type.v(self) elif isinstance(self.type, CType): return self.offset elif isinstance(self.type, Array): array_vals= [] for index in self.type.get_member_names(): element = Object(self.type.basetype, \ self.offset + index * \ self.type.basetype.size, \ self.vm,profile=self.profile) array_vals.append(element.v()) return array_vals else: return None def get_member_names(self): if self.type.hasMembers: return self.type.get_member_names() + self.extra_members.keys() else: return False def get_bytes(self,amount=None): if amount == None: amount = self.type.size return self.vm.read(self.offset, amount) def get_values(self): value_dict = {} for k in self.get_member_names(): value_dict[k] = self.m(k).v() return value_dict def __str__(self): if isinstance(self.type, CType): retval = "[%s] @ %s" % (self.type.cdecl(), hex(self.offset)) return retval elif isinstance(self.type, Void): retval = "[%s] %s" % (self.type.cdecl(), hex(self.v())) return retval return object.__str__(self) def __repr__(self): if isinstance(self.type, NativeType): return str(self.value()) return object.__repr__(self) class VType: def __init__(self, profile, size, hasMembers=False, hasValue=False): self.profile = profile self.hasMembers=hasMembers self.hasValue=hasValue self.size = size def cdecl(self): return "VType" class Void(VType): def __init__(self, profile): VType.__init__(self, profile, 0, False, True) def v(self, theObject): return self.value(theObject) def value(self, theObject): (val, ) = struct.unpack("=L", theObject.vm.read(theObject.offset, 4)) return val def cdecl(self): return "void" def dereference_as(self, derefType, theObject): if isinstance(derefType, str): return Object(derefType, self.v(theObject), \ theObject.vm, None,self.profile) return Object(derefType.name, self.v(theObject), theObject.vm, \ None,self.profile) class NativeType(VType): def __init__(self, profile, name, size, readChar): VType.__init__(self, profile, size, False, True) self.name = name self.size = size self.readChar = readChar def v(self, theObject): return self.value(theObject) def value(self, theObject): (val, ) = struct.unpack('='+self.readChar, \ theObject.vm.read(theObject.offset, self.size)) return val def cdecl(self): return self.name def __getattribute__(self, attr): return self.v() class Pointer(NativeType): def __init__(self, profile, basetype): NativeType.__init__(self, profile, 'pointer', profile.native_types['address'].size, \ profile.native_types['address'].readChar) self.basetype = basetype def dereference(self, theObject): return self.dereference_as(self.basetype, theObject) def dereference_as(self, derefType, theObject): return Object(derefType.name, self.v(theObject), \ theObject.vm, None,self.profile) def cdecl(self): return "%s *" % self.basetype.cdecl() def __repr__(self): return "" % (self.basetype.cdecl()) def __getattribute__(self, attr): try: return super(Pointer,self).__getattribute__(attr) except AttributeError: return getattr(self.value, attr) class CTypeMember: def __init__(self, name, offset, theType): self.name = name self.offset = offset self.type = theType class CType(VType): def __init__(self, profile, name, size, members, isStruct): VType.__init__(self, profile, size, True, False) self.name = name self.members = members self.isStruct = isStruct def add_member(self, name, member): self.members[member.name] = member def set_members(self, members): self.members = members def get_member_names(self): return self.members.keys() def get_member_type(self, memname): return self.members[memname].type def get_member_offset(self, memname): return self.members[memname].offset def get_member(self, memname): return self.members[memname] def is_struct(self): return self.isStruct def cdecl(self): if self.isStruct: return "struct %s" % self.name else: return "union %s" % self.name class Array(VType): def __init__(self, profile, count, basetype): VType.__init__(self, profile, count * basetype.size, True, False) self.count = count self.basetype = basetype def get_member_names(self): return range(0, self.count) def get_member(self, index): return CTypeMember(index, self.basetype.size * index, self.basetype) def cdecl(self): return "%s[%d]" % (self.basetype.cdecl(), self.count) ## Profiles are the interface for creating/interpreting ## objects class Profile: def __init__(self, native_types=x86_native_types): self.native_types = {} self.cstructs = {} globs = {} locs = {} self.voidType = Void(self) # Load the native types for nt in native_types.keys(): self.native_types[nt] = NativeType(self, nt, \ native_types[nt][0], native_types[nt][1]) # Load the abstract data types typeDict = types for ctype in typeDict.keys(): self.import_type(ctype, typeDict) def import_type(self, ctype, typeDict): members = self.convert_members(ctype, typeDict) if self.cstructs.has_key(ctype): self.cstructs[ctype].set_members(members) self.cstructs[ctype].size = typeDict[ctype][0] else: isStruct = (ctype.find('union') == -1) self.cstructs[ctype] = CType(self, ctype, typeDict[ctype][0], members, isStruct) def add_types(self, addDict): for ctype in addDict.keys(): self.import_type(ctype, addDict) def list_to_type(self, typeList, typeDict): if typeList[0] == 'void': return self.voidType if typeList[0] == 'pointer': return Pointer(self, self.list_to_type(typeList[1], typeDict)) if typeList[0] == 'array': return Array(self, typeList[1], self.list_to_type(typeList[2], typeDict)) if self.native_types.has_key(typeList[0]): return self.native_types[typeList[0]] if self.cstructs.has_key(typeList[0]): return self.cstructs[typeList[0]] isStruct = (typeList[0].find('union') == -1) self.cstructs[typeList[0]] = CType(self, typeList[0], 0, {}, isStruct) return self.cstructs[typeList[0]] def convert_members(self, cname, typeDict): ctype = typeDict[cname] members = {} for i in ctype[1].keys(): members[i] = CTypeMember(i, ctype[1][i][0], self.list_to_type(ctype[1][i][1], typeDict)) return members dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/registry.py000066400000000000000000000253301217176075400247500ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Derived from source in PyFlag developed by: # Copyright 2004: Commonwealth of Australia. # Michael Cohen # David Collett # # ****************************************************** # Version: FLAG $Version: 0.84RC4 Date: Wed May 30 20:48:31 EST 2007$ # ****************************************************** # # * This program is free software; you can redistribute it and/or # * modify it under the terms of the GNU General Public License # * as published by the Free Software Foundation; either version 2 # * 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, write to the Free Software # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ***************************************************** """ This module implements a class registry. We scan the memory_plugins directory for all python files and add those classes which should be registered into their own lookup tables. These are then ordered as required. The rest of Volatility will then call onto the registered classes when needed. This mechanism allows us to reorgenise the code according to functionality. For example we may include a Scanner, Report and File classes in the same plugin and have them all automatically loaded. """ import os,sys,imp ## Define the parameters we need: PLUGINS = "memory_plugins:memory_objects" class MemoryRegistry: """ Main class to register classes derived from a given parent class. """ modules = [] module_desc = [] module_paths = [] classes = [] class_names = [] order = [] filenames = {} def __init__(self,ParentClass): """ Search the plugins directory for all classes extending ParentClass. These will be considered as implementations and added to our internal registry. """ ## Create instance variables self.classes = [] self.class_names = [] self.order = [] ## Recurse over all the plugin directories recursively for path in PLUGINS.split(':'): for dirpath, dirnames, filenames in os.walk(path): sys.path.append(dirpath) for filename in filenames: #Lose the extension for the module name module_name = filename[:-3] if filename.endswith(".py"): path = dirpath+'/'+filename try: if path not in self.module_paths: ## If we do not have the module in the ## cache, we load it now try: #open the plugin file fd = open(path ,"r") except Exception,e: print "Unable to open plugin file '%s': %s"% (filename,e) continue #load the module into our namespace try: ## Try to load the module from the ## currently cached copy try: module = sys.modules[module_name] except KeyError: module = imp.load_source(module_name,dirpath+'/'+filename,fd) except Exception,e: print "*** Unable to load module %s: %s" % (module_name,e) continue fd.close() #Is this module active? try: if module.hidden: print "*** Will not load Module %s: Module Hidden"% (module_name) continue except AttributeError: pass try: if not module.active: print "*** Will not load Module %s: Module not active" % (module_name) continue except AttributeError: pass #find the module description try: module_desc = module.description except AttributeError: module_desc = module_name ## Store information about this module here. self.modules.append(module) self.module_desc.append(module_desc) self.module_paths.append(path) else: ## We already have the module in the cache: module = self.modules[self.module_paths.index(path)] module_desc = self.module_desc[self.module_paths.index(path)] #Now we enumerate all the classes in the #module to see which one is a ParentClass: for cls in dir(module): try: Class = module.__dict__[cls] if issubclass(Class,ParentClass) and Class!=ParentClass: ## Check the class for consitancy try: self.check_class(Class) except AttributeError,e: print "Failed to load %s '%s': %s" % (ParentClass,cls,e) continue ## Add the class to ourselves: self.add_class(ParentClass, module_desc, cls, Class, filename) # Oops: it isnt a class... except (TypeError, NameError) , e: continue except TypeError, e: print "Could not compile module %s: %s"% (module_name,e) continue def add_class(self, ParentClass, module_desc, cls, Class, filename): """ Adds the class provided to our self. This is here to be possibly over ridden by derived classes. """ if Class not in self.classes: self.classes.append(Class) self.filenames[self.get_name(Class)] = filename try: self.order.append(Class.order) except: self.order.append(10) def check_class(self,Class): """ Run a set of tests on the class to ensure its ok to use. If there is any problem, we chuck an exception. """ def import_module(self,name=None,load_as=None): """ Loads the named module into the system module name space. After calling this it is possible to do: import load_as in all other modules. Note that to avoid race conditions its best to only attempt to use the module after the registry is initialised (i.e. at run time not load time). @arg load_as: name to use in the systems namespace. @arg name: module name to import @note: If there are several modules of the same name (which should be avoided) the last one encountered during registring should persist. This may lead to indeterminate behaviour. """ if not load_as: load_as=name for module in self.modules: if name==module.__name__: sys.modules[load_as] = module return raise ImportError("No module by name %s" % name) def get_name(self, cls): try: return cls.name except AttributeError: return ("%s" % cls).split(".")[-1] def filename(self, cls_name): return self.filenames.get(cls_name, "Unknown") class VolatilityCommandRegistry(MemoryRegistry): """ A class to manage commands """ commands = {} def __getitem__(self,command_name): """ Return the command objects by name """ return self.commands[command_name] def __init__(self,ParentClass): MemoryRegistry.__init__(self,ParentClass) for cls in self.classes: ## The name of the class is the command name command = ("%s" % cls).split('.')[-1] try: raise Exception("Command %s has already been defined by %s" % (command,self.commands[command])) except KeyError: self.commands[command]=cls class VolatilityObjectRegistry(MemoryRegistry): """ A class to manage objects """ objects = {} def __getitem__(self,object_name): """ Return the objects by name """ return self.objects[object_name] def __init__(self,ParentClass): MemoryRegistry.__init__(self,ParentClass) for cls in self.classes: ## The name of the class is the object name obj = ("%s" % cls).split('.')[-1] obj = obj[:-2] try: raise Exception("Object %s has already been defined by %s" % (obj,self.objects[obj])) except KeyError: self.objects[obj]=cls LOCK = 0 PLUGIN_COMMANDS = None OBJECT_CLASSES = None ## This is required for late initialization to avoid dependency nightmare. def Init(): ## LOCK will ensure that we only initialize once. global LOCK if LOCK: return LOCK=1 ## Register all shell commands: import forensics.commands as commands global PLUGIN_COMMANDS PLUGIN_COMMANDS = VolatilityCommandRegistry(commands.command) ## Register all the derived objects import forensics.object2 as object2 global OBJECT_CLASSES OBJECT_CLASSES = VolatilityObjectRegistry(object2.Object) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/symbols.py000066400000000000000000000026011217176075400245640ustar00rootroot00000000000000# Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Nick Petroni @license: GNU General Public License 2.0 or later @contact: awalters@komoku.com, npetroni@komoku.com @organization: Komoku, Inc. """ from forensics.object import read_value class SymbolTable: def __init__(self, sym_dict): self.dict = sym_dict def lookup(self, sym): if self.dict.has_key(sym): return self.dict[sym] else: return None def sym_value(self, sym, addr_space): if self.dict.has_key(sym): return read_value(addr_space, 'unsigned long', self.lookup(sym)) else: return None dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/000077500000000000000000000000001217176075400234655ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/CMakeLists.txt000066400000000000000000000014461217176075400262320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( crash_addrspace.py datetime.py handles.py info.py meta_info.py network.py scan2.py tasks.py xpress.py crashdump.py executable.py hiber_addrspace.py __init__.py modules.py registry.py scan.py vad.py ) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/__init__.py000066400000000000000000000000001217176075400255640ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/crash_addrspace.py000077500000000000000000000252641217176075400271610ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Copyright (C) 2005,2006,2007 4tphi Research # Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Andreas Schuster @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com """ """Address space: windows crash dump """ from forensics.addrspace import FileAddressSpace import forensics.x86 from forensics.object import * page_shift = 12 debug_types = { \ '_PHYSICAL_MEMORY_RUN' : [ 0x8, { \ 'BasePage' : [ 0x0, ['unsigned long']], \ 'PageCount' : [ 0x4, ['unsigned long']], \ } ], \ '_PHYSICAL_MEMORY_DESCRIPTOR' : [ 0x10, { \ 'NumberOfRuns' : [ 0x0, ['unsigned long']], \ 'NumberOfPages' : [ 0x4, ['unsigned long']], \ 'Run' : [ 0x8, ['array', 1,['_PHYSICAL_MEMORY_RUN']]], \ } ], \ '_DMP_HEADER' : [ 0x1000, { \ 'Signature' : [ 0x0, ['array', 4,['unsigned char']]], \ 'ValidDump' : [ 0x4, ['array', 4,['unsigned char']]], \ 'MajorVersion' : [ 0x8, ['unsigned long']], \ 'MinorVersion' : [ 0xc, ['unsigned long']], \ 'DirectoryTableBase' : [ 0x10, ['unsigned long']], \ 'PfnDataBase' : [ 0x14, ['unsigned long']], \ 'PsLoadedModuleList' : [ 0x18, ['unsigned long']], \ 'PsActiveProcessHead' : [ 0x1c, ['unsigned long']], \ 'MachineImageType' : [ 0x20, ['unsigned long']], \ 'NumberProcessors' : [ 0x24, ['unsigned long']], \ 'BugCheckCode' : [ 0x28, ['unsigned long']], \ 'BugCheckCodeParameter' : [ 0x2c, ['array', 4,['unsigned long']]], \ 'VersionUser' : [ 0x3c, ['array', 32,['unsigned char']]], \ 'PaeEnabled' : [ 0x5c, ['unsigned char']], \ 'KdSecondaryVersion' : [ 0x5d, ['unsigned char']], \ 'VersionUser' : [ 0x5e, ['array', 2,['unsigned char']]], \ 'KdDebuggerDataBlock' : [ 0x60, ['unsigned long']], \ 'PhysicalMemoryBlockBuffer' : [ 0x64, ['_PHYSICAL_MEMORY_DESCRIPTOR']], \ 'ContextRecord' : [ 0x320, ['array', 1200,['unsigned char']]], \ 'Exception' : [ 0x7d0, ['_EXCEPTION_RECORD32']], \ 'Comment' : [ 0x820, ['array', 128,['unsigned char']]], \ 'DumpType' : [ 0xf88, ['unsigned long']], \ 'MiniDumpFields' : [ 0xf8c, ['unsigned long']], \ 'SecondaryDataState' : [ 0xf90, ['unsigned long']], \ 'ProductType' : [ 0xf94, ['unsigned long']], \ 'SuiteMask' : [ 0xf98, ['unsigned long']], \ 'WriterStatus' : [ 0xf9c, ['unsigned long']], \ 'RequiredDumpSpace' : [ 0xfa0, ['unsigned __int64']], \ 'SystemUpTime' : [ 0xfb8, ['unsigned __int64']], \ 'SystemTime' : [ 0xfc0, ['unsigned __int64']], \ 'reserved3' : [ 0xfc8, ['array', 56,['unsigned char']]], \ } ], \ } class WindowsCrashDumpSpace32: def __init__(self, baseAddressSpace,offset,ramsize=0): self.runs = [] self.offset = offset self.base = baseAddressSpace native_types = forensics.x86.x86_native_types self.dump_header = self.base.read(offset,obj_size(debug_types, '_DMP_HEADER')) self.number_of_runs = read_obj(self.base, debug_types, ['_DMP_HEADER', 'PhysicalMemoryBlockBuffer','NumberOfRuns'], offset) self.number_of_pages = read_obj(self.base, debug_types, ['_DMP_HEADER', 'PhysicalMemoryBlockBuffer','NumberOfPages'], offset) (start_run,tmp) = get_obj_offset(debug_types, ['_DMP_HEADER', 'PhysicalMemoryBlockBuffer', 'Run']) for cnt in range(0,self.number_of_runs): BasePage = read_obj(self.base, debug_types, ['_PHYSICAL_MEMORY_RUN', 'BasePage'], start_run+(8*cnt)) PageCount = read_obj(self.base, debug_types, ['_PHYSICAL_MEMORY_RUN', 'PageCount'], start_run+(8*cnt)) self.runs.append([BasePage,PageCount]) def get_header(self): return self.dump_header def get_base(self): return self.base def get_number_of_runs(self): return self.number_of_runs def get_number_of_pages(self): return self.number_of_pages def get_majorversion(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'MajorVersion'], self.offset) def get_minorversion(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'MinorVersion'], self.offset) def get_kdsecondaryversion(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'KdSecondaryVersion'], self.offset) def get_directorytablebase(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'DirectoryTableBase'], self.offset) def get_pfndatabase(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'PfnDataBase'], self.offset) def get_psloadedmodulelist(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'PsLoadedModuleList'], self.offset) def get_psactiveprocesshead(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'PsActiveProcessHead'], self.offset) def get_machineimagetype(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'MachineImageType'], self.offset) def get_numberprocessors(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'NumberProcessors'], self.offset) def get_bugcheckcode(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'BugCheckCode'], self.offset) def get_paeenabled(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'PaeEnabled'], self.offset) def get_kddebuggerdatablock(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'KdDebuggerDataBlock'], self.offset) def get_dumptype(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'DumpType'], self.offset) def get_producttype(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'ProductType'], self.offset) def get_suitemask(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'SuiteMask'], self.offset) def get_writerstatus(self): return read_obj(self.base, debug_types, ['_DMP_HEADER', 'WriterStatus'], self.offset) def get_addr(self, addr): page_offset = (addr & 0x00000FFF) page = addr >> page_shift # This is the offset to account for the header file offset = 1 for run in self.runs: if ((page >= run[0]) and (page < (run[0] + run[1]))): run_offset = page - run[0] offset = offset + run_offset baseoffset = (offset * 0x1000) + page_offset return baseoffset offset += run[1] return None def is_valid_address(self, addr): if self.get_addr(addr) == None: return False return True def read(self, addr, len): first_block = 0x1000 - addr % 0x1000 full_blocks = ((len + (addr % 0x1000)) / 0x1000) - 1 left_over = (len + addr) % 0x1000 baddr = self.get_addr(addr) if baddr == None: return None if len < first_block: return self.base.read(baddr,len) stuff_read = self.base.read(baddr, first_block) new_addr = addr + first_block for i in range(0,full_blocks): baddr = self.get_addr(new_addr) if baddr == None: return None stuff_read = stuff_read + self.base.read(baddr, 0x1000) new_addr = new_addr + 0x1000 if left_over > 0: baddr = self.get_addr(new_addr) if baddr == None: return None stuff_read = stuff_read + self.base.read(baddr, left_over) return stuff_read def zread(self, vaddr, length): first_block = 0x1000 - vaddr % 0x1000 full_blocks = ((length + (vaddr % 0x1000)) / 0x1000) - 1 left_over = (length + vaddr) % 0x1000 self.check_address_range(vaddr) baddr = self.get_addr(vaddr) if baddr == None: if length < first_block: return ('\0' * length) stuff_read = ('\0' * first_block) else: if length < first_block: return self.base.read(baddr, length) stuff_read = self.base.read(baddr, first_block) new_vaddr = vaddr + first_block for i in range(0,full_blocks): baddr = self.get_addr(new_vaddr) if baddr == None: stuff_read = stuff_read + ('\0' * 0x1000) else: stuff_read = stuff_read + self.base.read(baddr, 0x1000) new_vaddr = new_vaddr + 0x1000 if left_over > 0: baddr = self.get_addr(new_vaddr) if baddr == None: stuff_read = stuff_read + ('\0' * left_over) else: stuff_read = stuff_read + self.base.read(baddr, left_over) return stuff_read def read_long(self, addr): baseaddr = self.get_addr(addr) string = self.read(addr, 4) (longval, ) = struct.unpack('=L', string) return longval def get_available_pages(self): page_list = [] for run in self.runs: start = run[0] for page in range(start,start + run[1]): page_list.append([page * 0x1000, 0x1000]) return page_list def get_address_range(self): """ This relates to the logical address range that is indexable """ run = self.runs[-1] size = run[0] * 0x1000 + run[1]*0x1000 return [0,size] def get_available_addresses(self): """ This returns the ranges of valid addresses """ address_list = [] for run in self.runs: address_list.append([run[0] * 0x1000, run[1] * 0x1000]) return address_list def check_address_range(self,addr): memrange = self.get_address_range() if addr < memrange[0] or addr > memrange[1]: raise IOError def close(self): self.base.close() dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/crashdump.py000066400000000000000000000711031217176075400260270ustar00rootroot00000000000000# Volatility # Copyright (c) 2007,2008 Volatile Systems # Copyright (c) 2008 Brendan Dolan-Gavitt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com,bdolangavitt@wesleyan.edu @organization: Volatile Systems """ """Tool: This tool generates a crash dump from a image of ram """ import os,optparse import struct import sha from time import gmtime, strftime from vutils import is_crash_dump from thirdparty.progressbar import * from forensics.object import * from forensics.addrspace import FileAddressSpace from forensics.win32.info import find_psactiveprocesshead from forensics.win32.info import find_psloadedmodulelist from forensics.win32.info import find_mmpfndatabase from forensics.win32.info import find_kddebuggerdatablock from forensics.win32.info import find_kddebuggerdatablock from forensics.win32.info import find_systemtime from forensics.win32.info import find_suitemask from forensics.win32.tasks import process_list from forensics.win32.tasks import process_addr_space from forensics.win32.tasks import peb_number_processors from forensics.win32.tasks import process_peb #from forensics.win32.tasks import * dump_hdr= "" # 0x00 dump_hdr+="\x50\x41\x47\x45\x44\x55\x4D\x50\x0F\x00\x00\x00\x28\x0A\x00\x00" # 0x10 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x20 dump_hdr+="\x4C\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x30 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50\x41\x47\x45" # 0x40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x00\x41\x47\x45" # 0x60 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x70 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x80 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x90 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0xa0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0xb0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0xc0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0xd0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0xe0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0xf0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x100 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x110 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x120 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x130 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x140 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x150 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x160 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x170 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x180 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x190 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x1a0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x1b0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x1c0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x1d0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x1e0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x1f0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x200 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x210 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x220 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x230 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x240 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x250 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x260 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x270 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x280 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x290 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x2a0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x2b0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x2c0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x2d0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x2e0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x2f0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x300 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x310 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x320 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x330 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x340 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x350 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x360 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x370 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x380 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x390 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x3a0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x3b0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x3c0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x3d0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x3e0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x3f0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x400 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x410 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x420 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x430 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x440 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x450 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x460 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x470 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x480 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x490 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x4a0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x4b0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x4c0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x4d0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x4e0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x4f0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x500 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x510 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x520 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x530 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x540 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x550 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x560 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x570 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x580 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x590 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x5a0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x5b0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x5c0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x5d0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x5e0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50\x41\x47\x45" # 0x5f0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x600 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x610 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x620 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x630 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x640 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x650 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x660 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x670 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x680 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x690 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x6a0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x6b0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x6c0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x6d0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x6e0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x6F0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x700 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x710 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x720 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x730 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x740 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x750 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x760 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x770 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x780 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x790 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x7a0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x7b0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x7c0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x00\x41\x47\x45" # 0x7d0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x7e0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x7f0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x800 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x810 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # 0x820 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x830 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x840 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x850 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x860 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x870 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x880 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x890 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x8a0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x8b0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x8c0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x8d0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x8e0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x8f0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x900 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x910 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x920 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x930 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x940 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x950 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x960 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x970 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x980 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x990 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x9a0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x9b0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x9c0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x9d0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x9e0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0x9f0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA00 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA10 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA20 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA30 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA60 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA70 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA80 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xA90 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xAa0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xAb0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xAc0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xAd0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xAe0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xAf0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb00 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb10 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb20 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb30 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb60 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb70 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb80 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xb90 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xba0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xbb0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xbc0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xbd0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xbe0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xbf0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc00 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc10 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc20 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc30 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc60 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc70 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc80 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xc90 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xca0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xcb0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xcc0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xcd0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xce0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xcf0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd00 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd10 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd20 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd30 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd60 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd70 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd80 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xd90 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xda0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xdb0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xdc0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xdd0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xde0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xdf0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe00 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe10 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe20 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe30 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe60 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe70 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe80 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xe90 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xea0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xeb0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xec0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xed0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xee0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xef0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" #0xf00 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" #0xf10 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" #0xf20 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" #0xf30 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" #0xf40 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" #0xf50 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xf60 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xf70 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xf80 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x01\x00\x00\x00\x50\x41\x47\x45" # 0xF90 dump_hdr+="\x50\x41\x47\x45\x01\x00\x00\x00\x10\x01\x00\x00\x00\x00\x00\x00" # 0xFA0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x50\x41\x47\x45\x00\x41\x47\x45" # 0xFB0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x00\x00\x00\x00\x00\x00\x00\x00" # 0xFC0 dump_hdr+="\x00\x00\x00\x00\x00\x00\x00\x00\x50\x41\x47\x45\x50\x41\x47\x45" # 0xFD0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xFE0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" # 0xFF0 dump_hdr+="\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45\x50\x41\x47\x45" num_of_runs = 0x00000001 base_page = 0x00000000 pae_enabled = 0x01 def find_numberprocessors(addr_space, types): NumberOfProcessorsDict = dict() all_tasks = process_list(addr_space, types) for task in all_tasks: if not addr_space.is_valid_address(task): continue process_address_space = process_addr_space(addr_space, types, task, addr_space.base.fname) if process_address_space is None: continue peb = process_peb(addr_space, types, task) try: if not process_address_space.is_valid_address(peb): continue except: continue NumberOfProcessors = peb_number_processors(process_address_space, types, peb) if NumberOfProcessors in NumberOfProcessorsDict: NumberOfProcessorsDict[NumberOfProcessors] +=1 else: NumberOfProcessorsDict[NumberOfProcessors] = 1 MaxNumberOfProcessors =max([ (NumberOfProcessorsDict[x],x) for x in NumberOfProcessorsDict])[1] return MaxNumberOfProcessors def write_char_phys(value,member_list,hdr,types): (offset, current_type) = get_obj_offset(types, member_list) new_hdr = hdr[:offset] + struct.pack('=B',value) + hdr[offset+1:] return new_hdr def write_long_phys(value,member_list,hdr,types): (offset, current_type) = get_obj_offset(types, member_list) new_hdr = hdr[:offset] + struct.pack('=L',value) + hdr[offset+4:] return new_hdr def write_long_long_phys(value,member_list,hdr,types): (offset, current_type) = get_obj_offset(types, member_list) new_hdr = hdr[:offset] + struct.pack('=Q',value) + hdr[offset+8:] return new_hdr def dd_to_crash(addr_space, types, symbol_table, opts): outfile = opts.outfile filename = opts.filename DirectoryTableBaseValue = addr_space.pgd_vaddr PsActiveProcessHead = find_psactiveprocesshead(addr_space, types) PsLoadedModuleList = find_psloadedmodulelist(addr_space,types) MmPfnDatabase = find_mmpfndatabase(addr_space, types) KdDebuggerDataBlock = find_kddebuggerdatablock(addr_space, types) NumberOfProcessors = find_numberprocessors(addr_space, types) SuiteMask = find_suitemask(addr_space, types) SystemTime = find_systemtime(addr_space, types) num_pages = os.path.getsize(filename)/4096 page_count = num_pages new_hdr = write_long_phys(DirectoryTableBaseValue,['_DMP_HEADER', 'DirectoryTableBase'],dump_hdr,types) new_hdr = write_long_phys(PsLoadedModuleList,['_DMP_HEADER', 'PsLoadedModuleList'],new_hdr,types) new_hdr = write_long_phys(PsActiveProcessHead,['_DMP_HEADER', 'PsActiveProcessHead'],new_hdr,types) new_hdr = write_long_phys(KdDebuggerDataBlock,['_DMP_HEADER', 'KdDebuggerDataBlock'],new_hdr,types) new_hdr = write_long_phys(NumberOfProcessors,['_DMP_HEADER', 'NumberProcessors'],new_hdr,types) new_hdr = write_long_phys(MmPfnDatabase,['_DMP_HEADER', 'PfnDataBase'],new_hdr,types) new_hdr = write_long_phys(SuiteMask,['_DMP_HEADER', 'SuiteMask'],new_hdr,types) new_hdr = write_long_long_phys(SystemTime,['_DMP_HEADER', 'SystemTime'],new_hdr,types) if addr_space.pae == True: new_hdr = write_char_phys(pae_enabled,['_DMP_HEADER', 'PaeEnabled'],new_hdr,types) new_hdr = new_hdr[:100] + struct.pack('=L',num_of_runs) +\ struct.pack('=L',num_pages) +\ struct.pack('=L',0x00000000) +\ struct.pack('=L',num_pages) +\ new_hdr[116:] MI=open(outfile,'wb') MI.write("%s"%new_hdr) FILEOPEN = open(filename, 'rb') offset = 0 end = os.path.getsize(filename) widgets = ['Convert: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=end).start() while offset <= end: fdata = FILEOPEN.read(0x1000) if fdata == None: break MI.write("%s"%fdata) pbar.update(offset) offset+=0x1000 pbar.finish() print FILEOPEN.close() MI.close() return def crash_numberofpages(address_space, types, vaddr): return read_obj(address_space, types, ['_DMP_HEADER', 'PhysicalMemoryBlockBuffer', 'NumberOfPages'], vaddr) def crash_to_dd(addr_space, types, output_file): if is_crash_dump(addr_space.fname) == False: print "Error: Crash dump file required as input" return NumberOfPages = crash_numberofpages(addr_space, types, 0) out = open(output_file, "wb") NumberOfRuns = read_obj(addr_space, types, ['_DMP_HEADER', 'PhysicalMemoryBlockBuffer', 'NumberOfRuns'], 0) run_base = ['_DMP_HEADER', 'PhysicalMemoryBlockBuffer', 'Run'] widgets = ['Convert: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=NumberOfPages).start() pages_written = 0 current_file_page = 0x1000 for i in xrange(NumberOfRuns): BasePage = read_obj(addr_space, types, run_base + [i, 'BasePage'], 0) PageCount = read_obj(addr_space, types, run_base + [i, 'PageCount'], 0) out.seek(BasePage * 0x1000) for j in xrange(0, PageCount*0x1000, 0x1000): data = addr_space.read(current_file_page + j, 0x1000) out.write(data) pbar.update(pages_written) pages_written += 1 current_file_page += (PageCount * 0x1000) pbar.finish() print out.close() return dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/datetime.py000066400000000000000000000110041217176075400256270ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ from forensics.object import * from time import gmtime, strftime def windows_to_unix_time(windows_time): """ Converts Windows 64-bit time to UNIX time @type windows_time: Integer @param windows_time: Windows time to convert (64-bit number) @rtype Integer @return UNIX time """ if(windows_time == 0): unix_time =0 else: unix_time = windows_time / 10000000 unix_time = unix_time - 11644473600 if unix_time < 0: unix_time = 0 return unix_time def read_time(addr_space, types, vaddr): low_time = read_obj(addr_space, types, ['_KSYSTEM_TIME', 'LowPart'], vaddr) high_time = read_obj(addr_space, types, ['_KSYSTEM_TIME', 'High1Time'], vaddr) if low_time == None or high_time == None: return None return (high_time << 32) | low_time def read_time_buff(buff, types, vaddr): low_time = read_obj_from_buf(buff, types, ['_KSYSTEM_TIME', 'LowPart'], vaddr) high_time = read_obj_from_buf(buff, types, ['_KSYSTEM_TIME', 'High1Time'], vaddr) if low_time == None or high_time == None: return None return (high_time << 32) | low_time def read_time_buf(buff,data_types,member_list,object_offset): (time_offset, tmp) = get_obj_offset(data_types, \ member_list) low_time = read_obj_from_buf(buff, data_types, \ ['_KSYSTEM_TIME', 'LowPart'], object_offset+time_offset) high_time = read_obj_from_buf(buff, data_types, \ ['_KSYSTEM_TIME', 'High1Time'], object_offset+time_offset ) if low_time == None or high_time == None: return None read_time = (high_time << 32) | low_time read_time = windows_to_unix_time(read_time) return read_time def local_time(addr_space, types, vaddr): """ Returns the 64-bit numerical local time (100ns units) @type addr_space: AddressSpace @param addr_space: the kernel address space @type types: Dictionary @param types: Type (struct) formats dictionary @type vaddr: Integer @param vaddr: virtual address of KUSER_SHARED_DATA @rtype Integer @return returns the 64-bit system time number """ return system_time(addr_space, types, vaddr) - \ time_zone_bias(addr_space, types, vaddr) def system_time(addr_space, types, vaddr): """ Returns the 64-bit numerical system time (100ns units) @type addr_space: AddressSpace @param addr_space: the kernel address space @type types: Dictionary @param types: Type (struct) formats dictionary @type vaddr: Integer @param vaddr: virtual address of @rtype Integer @return returns the 64-bit system time number """ (offset, tmp) = get_obj_offset(types, ['_KUSER_SHARED_DATA', 'SystemTime']) return read_time(addr_space, types, vaddr + offset) def time_zone_bias(addr_space, types, vaddr): """ Returns the 64-bit numerical timezone bias (100ns units) @type addr_space: AddressSpace @param addr_space: the kernel address space @type types: Dictionary @param types: Type (struct) formats dictionary @type vaddr: Integer @param vaddr: virtual address of KUSER_SHARED_DATA @rtype Integer @return returns the 64-bit system time number """ (offset, tmp) = get_obj_offset(types, ['_KUSER_SHARED_DATA', 'TimeZoneBias']) return read_time(addr_space, types, vaddr + offset) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/executable.py000066400000000000000000000312621217176075400261640ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # Copyright (c) 2008 Brendan Dolan-Gavitt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: Brendan Dolan-Gavitt and AAron Walters @license: GNU General Public License 2.0 or later @contact: bdolangavitt@wesleyan.edu,awalters@volatilesystems.com @organization: Volatile Systems LLC """ from forensics.object import * import struct def round_up(addr, align): if addr % align == 0: return addr else: return (addr + (align - (addr % align))) def round_down(addr, align): if addr % align == 0: return addr else: return (addr - (addr % align)) def write_value(of, value_type, addr, data): pack_str = builtin_types[value_type][1] packed_data = struct.pack('='+pack_str, data) #print "write_value called" #of.seek(addr) #of.write(packed_data) def write_obj(of, types, field, addr, data): off, tp = get_obj_offset(types, field) return (tp, addr+off, data) #print "write obj called" #write_value(of, tp, addr+off, data) def read_section(addr_space, sect, img_base, size): section_start = img_base + sect['VirtualAddress'] return addr_space.zread(section_start, sect['SizeOfRawData']) def write_section_header(of, types, orig_header, sect, addr): # Write original header #print "write section header called" #of.seek(addr) #of.write(orig_header) #of.addMapping(addr, # Change some values for f in sect: data = sect[f] f = f.split("_") write_obj(of, types, ['_IMAGE_SECTION_HEADER'] + f, addr, data) def get_sections_start(addr_space, types, header): nt_header = header + read_obj(addr_space, types, ["_IMAGE_DOS_HEADER", "e_lfanew"], header) optional_header_start,_ = get_obj_offset(types, ['_IMAGE_NT_HEADERS', 'OptionalHeader']) optional_header_size = read_obj(addr_space, types, ['_IMAGE_NT_HEADERS', 'FileHeader', 'SizeOfOptionalHeader'], nt_header) sections_start = nt_header + optional_header_start + optional_header_size return sections_start - header def section_list(addr_space, types, header): nt_header = header + read_obj(addr_space, types, ["_IMAGE_DOS_HEADER", "e_lfanew"], header) num_sections = read_obj(addr_space, types, ["_IMAGE_NT_HEADERS", "FileHeader", "NumberOfSections"], nt_header) sections_start = get_sections_start(addr_space, types, header) section_header_size = obj_size(types, '_IMAGE_SECTION_HEADER') return [ header + sections_start + (i*section_header_size) for i in range(num_sections) ] def sanity_check_section(sect, image_size): # Note: all addresses here are RVAs if sect['VirtualAddress'] > image_size: raise ValueError('VirtualAddress %08x is past the end of image.' % sect['VirtualAddress']) if sect['Misc_VirtualSize'] > image_size: raise ValueError('VirtualSize %08x is larger than image size.' % sect['Misc_VirtualSize']) if sect['SizeOfRawData'] > image_size: raise ValueError('SizeOfRawData %08x is larger than image size.' % sect['SizeOfRawData']) def get_file_align(addr_space, types, addr): nt_header = addr + read_obj(addr_space, types, ["_IMAGE_DOS_HEADER", "e_lfanew"], addr) file_align = read_obj(addr_space, types, ["_IMAGE_NT_HEADERS", "OptionalHeader", "FileAlignment"], nt_header) return file_align def get_sect_align(addr_space, types, addr): nt_header = addr + read_obj(addr_space, types, ["_IMAGE_DOS_HEADER", "e_lfanew"], addr) sect_align = read_obj(addr_space, types, ["_IMAGE_NT_HEADERS", "OptionalHeader", "SectionAlignment"], nt_header) return sect_align def get_size_of_image(addr_space, types, addr): nt_header = addr + read_obj(addr_space, types, ["_IMAGE_DOS_HEADER", "e_lfanew"], addr) size = read_obj(addr_space, types, ["_IMAGE_NT_HEADERS", "OptionalHeader", "SizeOfImage"], nt_header) return size def get_size_of_headers(addr_space, types, addr): nt_header = addr + read_obj(addr_space, types, ["_IMAGE_DOS_HEADER", "e_lfanew"], addr) size = read_obj(addr_space, types, ["_IMAGE_NT_HEADERS", "OptionalHeader", "SizeOfHeaders"], nt_header) return size def section_entry(addr_space, types, sect_addr): fields = [ ['VirtualAddress'], ['Misc', 'VirtualSize'], ['SizeOfRawData'], ['PointerToRawData'] ] sect = {} (name_off,_) = get_obj_offset(types, ['_IMAGE_SECTION_HEADER', 'Name']) name_len = 8 sect['Name'] = addr_space.zread(sect_addr + name_off, name_len) for f in fields: val = read_obj(addr_space, types, ['_IMAGE_SECTION_HEADER'] + f, sect_addr) sect["_".join(f)] = val return sect def audit_read_write(addr_space,types,data_start,data_size,ofile, align): first_block = 0x1000 - data_start % 0x1000 full_blocks = ((data_size + (data_start % 0x1000)) / 0x1000) - 1 left_over = (data_size + data_start) % 0x1000 paddr = addr_space.vtop(data_start) # Deal with reads that are smaller than a block if data_size < first_block: data_read = addr_space.zread(data_start,data_size) if paddr == None: print "Memory Not Accessible: Virtual Address: 0x%x File Offset: 0x%x Size: 0x%x"%(data_start, 0,data_size) ofile.addMapping(data_start + align, data_size) #ofile.write(data_read) return data_read = addr_space.zread(data_start + align,first_block) if paddr == None: #XXX 0 remplace file.tell() mais devrait pas print "Memory Not Accessible: Virtual Address: 0x%x File Offset: 0x%x Size: 0x%x"%(data_start,0,first_block) ofile.addMapping(data_start + align, data_size) #ofile.write(data_read) # The middle part of the read new_vaddr = data_start + first_block for i in range(0,full_blocks): data_read = addr_space.zread(new_vaddr, 0x1000) if addr_space.vtop(new_vaddr) == None: print "Memory Not Accessible: Virtual Address: 0x%x File Offset: 0x%x Size: 0x%x"%(new_vaddr,0,0x1000) #ofile.write(data_read) ofile.addMapping(new_vaddr + align, 0x1000) new_vaddr = new_vaddr + 0x1000 # The last part of the read if left_over > 0: data_read = addr_space.zread(new_vaddr, left_over) if addr_space.vtop(new_vaddr) == None: print "Memory Not Accessible: Virtual Address: 0x%x File Offset: 0x%x Size: 0x%x"%(new_vaddr,0,left_over) #ofile.write(data_read) ofile.addMaping(new_vaddr + align, left_over) return def rebuild_exe_dsk(addr_space, types, addr, of, safe=True): file_align = get_file_align(addr_space, types, addr) header_size = get_size_of_headers(addr_space, types, addr) img_size = get_size_of_image(addr_space, types, addr) header = addr_space.zread(addr, header_size) #of.seek(0) of.addMapping(addr, header_size) #of.write(header) sections = section_list(addr_space, types, addr) for s_addr in sections: sect = section_entry(addr_space, types, s_addr) if safe: sanity_check_section(sect, img_size) section_start = addr + sect['VirtualAddress'] file_offset_align = round_down(sect['PointerToRawData'], file_align) if file_offset_align!= sect['PointerToRawData']: print "Warning: section start on disk not aligned to file alignment." print "Warning: adjusted section start from %x to %x." % (sect['PointerToRawData'],file_offset_align) #of.seek(file_offset_align) #XXX audit_read_write(addr_space, types, section_start,sect['SizeOfRawData'],of, file_offset_align) # *********************************************************************** # * OLD -- Do not use! Has many problems: * # * 1. Assumes header is no more than 0x1000 bytes * # * 2. Reads section by section, so data in slack space may be missed. * # *********************************************************************** #def rebuild_exe_mem(addr_space, types, addr, of): # header = addr_space.read(addr, 0x1000) # # of.seek(0) # of.write(header) # # file_align = get_file_align(addr_space, types, addr) # sections = section_list(addr_space, types, addr) # section_header_size = obj_size(types, '_IMAGE_SECTION_HEADER') # orig_sections = [section_entry(addr_space, types, s) for s in sections ] # # # Write out whole image (base through base+sizeofimage) # # Loop over sections, set PointerToRawData = VirtualAddress and # # SizeOfRawData = max(next_section, virtual_size) # # # Calculate new file positions for memory sections # sections_offset = min(s['PointerToRawData'] for s in orig_sections) # modified_sections = [] # for i in range(len(orig_sections)): # new_sect = {} # new_sect['PointerToRawData'] = sections_offset # # modified_sections.append(new_sect) # # # Adjust the size of the section so it goes all # # the way to the beginning of the next section. # # If we're on the last section, make the section # # go until the end of the image. # try: # size = (orig_sections[i+1]['VirtualAddress'] - # orig_sections[i]['VirtualAddress']) # except IndexError: # size = round_up(orig_sections[i]['Misc_VirtualSize'], file_align) # # new_sect['SizeOfRawData'] = size # # sections_offset += size # # # Write modified section headers # sections_start = get_sections_start(addr_space, types, addr) # for i in range(len(sections)): # orig_header = addr_space.read(sections[i], section_header_size) # write_section_header(of, types, orig_header, modified_sections[i], # sections_start + (i*section_header_size)) # # # Write out sections to disk at the calculated positions, # # using their virtual size in memory # for orig_sect,mod_sect in zip(orig_sections, modified_sections): # of.seek(mod_sect['PointerToRawData']) # section_start = addr + orig_sect['VirtualAddress'] # sect_data = addr_space.read(section_start, orig_sect['Misc_VirtualSize']) # of.write(sect_data) def rebuild_exe_mem(addr_space, types, addr, of, safe=True): sect_align = get_sect_align(addr_space, types, addr) img_size = get_size_of_image(addr_space, types, addr) sections = section_list(addr_space, types, addr) section_header_size = obj_size(types, '_IMAGE_SECTION_HEADER') orig_sections = [section_entry(addr_space, types, s) for s in sections ] if safe: for sect in orig_sections: sanity_check_section(sect, img_size) #of = nodeorig.open() #of.seek(0) print 'mem' audit_read_write(addr_space, types, addr,img_size,of, 0) modified_sections = [] for i in range(len(orig_sections)): new_sect = {} new_sect['PointerToRawData'] = orig_sections[i]['VirtualAddress'] # Each section should end where the next section starts. # For the last section, use the in-memory size. try: size = (orig_sections[i+1]['VirtualAddress'] - orig_sections[i]['VirtualAddress']) except IndexError: size = round_up(orig_sections[i]['Misc_VirtualSize'], sect_align) new_sect['SizeOfRawData'] = size new_sect['Misc_VirtualSize'] = size modified_sections.append(new_sect) # Write modified section headers sections_start = get_sections_start(addr_space, types, addr) for i in range(len(sections)): orig_header = addr_space.zread(sections[i], section_header_size) #of.addMapping(sections[i], section_header_size) write_section_header(of, types, orig_header, modified_sections[i], sections_start + (i*section_header_size)) #of.close() dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/handles.py000066400000000000000000000144511217176075400254620ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems LLC """ from forensics.object import * from forensics.win32.datetime import * from forensics.win32.tasks import * LEVEL_MASK = 0xfffffff8 def handle_process_id(addr_space, types, table_vaddr): return read_obj(addr_space, types, ['_HANDLE_TABLE', 'UniqueProcessId'], table_vaddr) def handle_num_entries(addr_space, types, table_vaddr): return read_obj(addr_space, types, ['_HANDLE_TABLE', 'HandleCount'], table_vaddr) def handle_table_code(addr_space, types, table_vaddr): return read_obj(addr_space, types, ['_HANDLE_TABLE', 'TableCode'], table_vaddr) & LEVEL_MASK def handle_table_levels(addr_space, types, table_vaddr): return read_obj(addr_space, types, ['_HANDLE_TABLE', 'TableCode'], table_vaddr) & ~LEVEL_MASK def handle_table_L1_entry(addr_space, types, table_vaddr, entry_num): return handle_table_code(addr_space, types, table_vaddr) + \ obj_size(types, '_HANDLE_TABLE_ENTRY') * entry_num def handle_table_L2_entry(addr_space, types, table_vaddr, L1_table, L2): if L1_table != 0x0: L2_entry = L1_table + obj_size(types, '_HANDLE_TABLE_ENTRY') * L2 return L2_entry return None def handle_table_L3_entry(addr_space, types, table_vaddr, L2_table, L3): if L2_table != 0x0: L3_entry = L2_table = obj_size(types, '_HANDLE_TABLE_ENTRY') * L3 return L3_entry return None def handle_entry_object(addr_space, types, entry_vaddr): return read_obj(addr_space, types, ['_HANDLE_TABLE_ENTRY', 'Object'], entry_vaddr) & ~0x00000007 def is_object_key(addr_space, types, obj_vaddr): type_vaddr = read_obj(addr_space, types, ['_OBJECT_HEADER', 'Type'], obj_vaddr) if not addr_space.is_valid_address(type_vaddr): return False type_name = read_unicode_string(addr_space, types, ['_OBJECT_TYPE', 'Name'], type_vaddr) return not type_name is None and type_name == "Key" def is_object_file(addr_space, types, obj_vaddr): type_vaddr = read_obj(addr_space, types, ['_OBJECT_HEADER', 'Type'], obj_vaddr) if not addr_space.is_valid_address(type_vaddr): return False type_name = read_unicode_string(addr_space, types, ['_OBJECT_TYPE', 'Name'], type_vaddr) return not type_name is None and type_name.find("File") != -1 def object_data(addr_space, types, obj_vaddr): (offset, tmp) = get_obj_offset(types, ['_OBJECT_HEADER', 'Body']) return obj_vaddr + offset def file_name(addr_space, types, file_vaddr): return read_unicode_string(addr_space, types, ['_FILE_OBJECT', 'FileName'], file_vaddr) def handle_tables(addr_space, types, symtab, pid=None): htables = [] all_tasks = process_list(addr_space, types, symtab) for task in all_tasks: if not addr_space.is_valid_address(task): continue ObjectTable = process_handle_table(addr_space, types, task) process_id = process_pid(addr_space, types, task) if addr_space.is_valid_address(ObjectTable): if pid == None: htables.append(ObjectTable) else: if process_id == pid: htables.append(ObjectTable) return htables def handle_entries(addr_space, types, table): all_entries = [] table_code = handle_table_code(addr_space, types, table) if table_code == 0: return all_entries table_levels = handle_table_levels(addr_space, types, table) if table_levels == 0: num_entries = handle_num_entries(addr_space, types, table) for counter in range(0, 0x200): entry = handle_table_L1_entry(addr_space, types, table, counter) if entry != None and entry !=0: all_entries.append(entry) elif table_levels == 1: for i in range(0, 0x200): L1_entry = handle_table_L1_entry(addr_space, types, table, i) if not L1_entry is None: L1_table = handle_entry_object(addr_space, types, L1_entry) for j in range(0, 0x200): L2_entry = handle_table_L2_entry(addr_space, types, table, L1_table, j) if not L2_entry is None: all_entries.append(L2_entry) elif table_levels == 2: for i in range(0, 0x200): L1_entry = handle_table_L1_entry(addr_space, types, table, i) if not L1_entry is None: L1_table = handle_entry_object(addr_space, types, L1_entry) for j in range(0, 0x200): L2_entry = handle_table_L2_entry(addr_space, types, table, L1_table, j) if not L2_entry is None: L2_table = handle_entry_object(addr_space, types, L2_entry) for k in range(0, 0x200): L3_entry = handle_table_L3_entry(addr_space, types, table, L2_table, j) if not L3_entry is None: all_entries.append(L3_entry) return all_entries dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/hiber_addrspace.py000077500000000000000000000407061217176075400271500ustar00rootroot00000000000000# Volatility # Copyright (c) 2008 Volatile Systems # Copyright (c) 2008 Brendan Dolan-Gavitt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Code found in WindowsHiberFileSpace32 for parsing meta information # is inspired by the work of Matthieu Suiche: http://sandman.msuiche.net/. # A special thanks to Matthieu for all his help integrating # this code in Volatility. """ @author: AAron Walters and Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com,bdolangavitt@wesleyan.edu @organization: Volatile Systems LLC """ """Address space: windows hiberfil """ from forensics.addrspace import FileAddressSpace import forensics.x86 from forensics.object import * from forensics.win32.xpress import xpress_decode from thirdparty.progressbar import * from forensics.win32.datetime import * from vtypes import xpsp2types as types from forensics.x86 import IA32PagedMemory page_shift = 12 hiber_types = { \ '_IMAGE_HIBER_HEADER' : [ 0xbc, { \ 'Signature' : [ 0x0, ['array', 4,['unsigned char']]], \ 'SystemTime' : [ 0x20, ['_LARGE_INTEGER']], \ 'FirstTablePage' : [ 0x58, ['unsigned long']], \ } ], \ 'MEMORY_RANGE_ARRAY_LINK' : [ 0x10, { \ 'NextTable' : [ 0x4, ['unsigned long']], \ 'EntryCount' : [ 0xc, ['unsigned long']], \ } ], \ 'MEMORY_RANGE_ARRAY_RANGE' : [ 0x10, { \ 'StartPage' : [ 0x4, ['unsigned long']], \ 'EndPage' : [ 0x8, ['unsigned long']], \ } ], \ '_MEMORY_RANGE_ARRAY' : [ 0x20, { \ 'MemArrayLink' : [ 0x0, ['MEMORY_RANGE_ARRAY_LINK']], \ } ], \ '_KGDTENTRY' : [ 0x8 , { \ 'BaseLow' : [ 0x2 , ['unsigned short']], \ 'BaseMid' : [ 0x4, ['unsigned char']], \ 'BaseHigh' : [ 0x7, ['unsigned char']], \ } ], \ '_IMAGE_XPRESS_HEADER' : [ 0x20 , { \ 'u09' : [ 0x9, ['unsigned char']], \ 'u0A' : [ 0xA, ['unsigned char']], \ 'u0B' : [ 0xB, ['unsigned char']], \ } ], \ } class WindowsHiberFileSpace32: def __init__(self, baseAddressSpace,offset,ramsize=0,fast=False): self.runs = [] self.offset = offset self.base = baseAddressSpace self.PagesListHead = {} self.PageDict = {} self.MemRangeCnt = 1 self.HighestPage = 0 self.PageIndex = 0 self.AddressList = [] self.DataCache = {} self.LookupCache = {} self.CacheHits = 0 self.max_decode_time = 0 # Extract header information self.hiber_header = self.base.read(offset, \ obj_size(hiber_types, '_IMAGE_HIBER_HEADER')) self.Signature = self.base.read(offset,4) FirstTablePage = read_obj(self.base, hiber_types, ['_IMAGE_HIBER_HEADER', 'FirstTablePage'], self.offset) (system_time_offset, tmp) = get_obj_offset(hiber_types, \ ['_IMAGE_HIBER_HEADER', 'SystemTime']) system_time = read_time(self.base, types, 0 + system_time_offset) system_time = windows_to_unix_time(system_time) if system_time is None: self.SystemTime = "UNKNOWN" else: self.SystemTime = self.format_time(system_time) # Extract processor state self.ProcStateOffset = 2 * 4096 self.CR0 = read_obj(self.base, types, ['_KPROCESSOR_STATE', 'SpecialRegisters','Cr0'], \ self.ProcStateOffset) self.CR3 = read_obj(self.base, types, ['_KPROCESSOR_STATE', 'SpecialRegisters','Cr3'], \ self.ProcStateOffset) self.CR4 = read_obj(self.base, types, ['_KPROCESSOR_STATE', 'SpecialRegisters','Cr4'], \ self.ProcStateOffset) if fast == True: return XpressIndex = 0 XpressHeaderOffset = (FirstTablePage+1) * 4096 XpressBlockSize = self.get_xpress_block_size(hiber_types, \ XpressHeaderOffset) MemoryArrayOffset = FirstTablePage * 4096 while MemoryArrayOffset: EntryCount = read_obj(self.base, hiber_types, \ ['_MEMORY_RANGE_ARRAY', 'MemArrayLink','EntryCount'], \ MemoryArrayOffset) for i in range(0,EntryCount): MemoryArrayRangeEntryOffset = MemoryArrayOffset + \ 0x10 + (i*0x10) EndPage = read_obj(self.base, hiber_types, ['MEMORY_RANGE_ARRAY_RANGE', 'EndPage'], \ MemoryArrayRangeEntryOffset) StartPage = read_obj(self.base, hiber_types, ['MEMORY_RANGE_ARRAY_RANGE', 'StartPage'], \ MemoryArrayRangeEntryOffset) if EndPage > self.HighestPage: self.HighestPage = EndPage LocalPageCnt = EndPage - StartPage self.AddressList.append([StartPage * 0x1000, \ LocalPageCnt * 0x1000]) for j in range(0,LocalPageCnt): if (XpressIndex and ((XpressIndex % 0x10) == 0)): XpressHeaderOffset,XpressBlockSize = \ self.next_xpress(hiber_types, \ XpressHeaderOffset) PageNumber = StartPage + j XpressPage = XpressIndex % 0x10 if XpressHeaderOffset not in self.PageDict: self.PageDict[XpressHeaderOffset] = \ [(PageNumber,XpressBlockSize,XpressPage)] self.LookupCache[PageNumber] = (XpressHeaderOffset,XpressBlockSize,XpressPage) else: self.PageDict[XpressHeaderOffset].append((PageNumber, \ XpressBlockSize, XpressPage)) self.LookupCache[PageNumber] = (XpressHeaderOffset,XpressBlockSize,XpressPage) self.PageIndex += 1 XpressIndex += 1 NextTable = read_obj(self.base, hiber_types, ['_MEMORY_RANGE_ARRAY', 'MemArrayLink','NextTable'], \ MemoryArrayOffset) if ((NextTable != 0) and (EntryCount == 0xFF)): MemoryArrayOffset = NextTable * 0x1000 self.MemRangeCnt+=1 XpressHeaderOffset,XpressBlockSize = \ self.next_xpress(hiber_types,XpressHeaderOffset) XpressIndex = 0 else: MemoryArrayOffset = 0 def format_time(self,time): ts=strftime("%a %b %d %H:%M:%S %Y", gmtime(time)) return ts def convert_to_raw(self,ofile): nb = len(self.PageDict) num_pages = self.get_number_of_pages() widgets = ['Convert: ', Percentage(), ' ', \ Bar(marker=RotatingMarker()),' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=num_pages).start() page_count = 0 for i,xb in enumerate(self.PageDict.keys()): nb = len(self.PageDict) size = self.PageDict[xb][0][1] data_z = self.base.read(xb+0x20,size) if size == 0x10000: data_uz = data_z else: data_uz = xpress_decode(data_z) for page,size,offset in self.PageDict[xb]: pbar.update(page_count) ofile.seek(page*0x1000) ofile.write(data_uz[offset*0x1000:offset*0x1000+0x1000]) page_count+=1 del data_z,data_uz pbar.finish() def next_xpress(self, types, XpressHeader): XpressBlockSize = self.get_xpress_block_size(types,XpressHeader) XpressHeader += XpressBlockSize + obj_size(types,'_IMAGE_XPRESS_HEADER') Magic = self.base.read(XpressHeader, 8) while Magic != "\x81\x81xpress": XpressHeader += 8 Magic = self.base.read(XpressHeader, 8) if not Magic: return None,None XpressBlockSize = self.get_xpress_block_size(types,XpressHeader) return XpressHeader,XpressBlockSize def get_xpress_block_size(self,types,offset): u0B = read_obj(self.base, types, ['_IMAGE_XPRESS_HEADER', 'u0B'], offset) << 24 u0A = read_obj(self.base, types, ['_IMAGE_XPRESS_HEADER', 'u0A'], offset) << 16 u09 = read_obj(self.base, types, ['_IMAGE_XPRESS_HEADER', 'u09'], offset) << 8 Size = u0B + u0A + u09 Size = Size >> 10 Size = Size + 1 if ((Size % 8) == 0): return Size return (Size & ~7) + 8 def get_header(self): return self.hiber_header def get_base(self): return self.base def get_signature(self): return self.Signature def get_system_time(self): return self.SystemTime def is_paging(self): return (self.CR0 >> 31) & 1 def is_pse(self): return (self.CR4 >> 4) & 1 def is_pae(self): return (self.CR4 >> 5) & 1 def get_number_of_memranges(self): return self.MemRangeCnt def get_number_of_pages(self): return self.PageIndex def get_addr(self, addr): page_offset = (addr & 0x00000FFF) page = addr >> page_shift if page in self.LookupCache: (hoffset,size,pageoffset) = self.LookupCache[page] return hoffset return None def get_block_offset(self,xb,addr): page = addr >> page_shift if page in self.LookupCache: (hoffset,size,pageoffset) = self.LookupCache[page] return pageoffset return None def is_valid_address(self, addr): if self.get_addr(addr) == None: return False return True def read_xpress(self,baddr,BlockSize): if not baddr in self.DataCache: data_read = self.base.read(baddr,BlockSize) if BlockSize == 0x10000: data_uz = data_read else: data_uz = xpress_decode(data_read) self.DataCache[baddr] = data_uz else: self.CacheHits += 1 data_uz = self.DataCache[baddr] return data_uz def read(self, addr, len): page_offset = (addr & 0x00000FFF) first_block = 0x1000 - addr % 0x1000 full_blocks = ((len + (addr % 0x1000)) / 0x1000) - 1 left_over = (len + addr) % 0x1000 ImageXpressHeader = self.get_addr(addr) if ImageXpressHeader == None: return None BlockSize = self.get_xpress_block_size(hiber_types,ImageXpressHeader) baddr = ImageXpressHeader + \ obj_size(hiber_types,'_IMAGE_XPRESS_HEADER') if len < first_block: data_uz = self.read_xpress(baddr,BlockSize) block_offset = self.get_block_offset(ImageXpressHeader,addr) return data_uz[(block_offset*0x1000+page_offset):(block_offset*0x1000+page_offset+len)] data_uz = self.read_xpress(baddr,BlockSize) block_offset = self.get_block_offset(ImageXpressHeader,addr) stuff_read = data_uz[(block_offset*0x1000+page_offset):(block_offset*0x1000+page_offset+first_block)] new_addr = addr + first_block for i in range(0,full_blocks): ImageXpressHeader = self.get_addr(new_addr) if ImageXpressHeader == None: return None BlockSize = self.get_xpress_block_size(hiber_types, \ ImageXpressHeader) baddr = ImageXpressHeader + \ obj_size(hiber_types,'_IMAGE_XPRESS_HEADER') data_uz = self.read_xpress(baddr,BlockSize) block_offset = self.get_block_offset(ImageXpressHeader,addr) stuff_read = stuff_read + data_uz[(block_offset*0x1000):(block_offset*0x1000+0x1000)] new_addr = new_addr + 0x1000 if left_over > 0: ImageXpressHeader = self.get_addr(new_addr) if ImageXpressHeader == None: return None BlockSize = self.get_xpress_block_size(hiber_types, \ ImageXpressHeader) baddr = ImageXpressHeader + \ obj_size(hiber_types,'_IMAGE_XPRESS_HEADER') data_uz = self.read_xpress(baddr,BlockSize) block_offset = self.get_block_offset(ImageXpressHeader,addr) stuff_read = stuff_read + data_uz[(block_offset*0x1000):(block_offset*0x1000+left_over)] return stuff_read def zread(self, addr, len): page_offset = (addr & 0x00000FFF) first_block = 0x1000 - addr % 0x1000 full_blocks = ((len + (addr % 0x1000)) / 0x1000) - 1 left_over = (len + addr) % 0x1000 self.check_address_range(addr) ImageXpressHeader = self.get_addr(addr) if ImageXpressHeader == None: if len < first_block: return ('\0' * length) stuff_read = ('\0' * first_block) else: if len < first_block: return self.read(addr, len) stuff_read = self.read(addr, first_block) new_addr = addr + first_block for i in range(0,full_blocks): ImageXpressHeader = self.get_addr(new_addr) if ImageXpressHeader == None: stuff_read = stuff_read + ('\0' * 0x1000) else: stuff_read = stuff_read + self.read(new_addr, 0x1000) new_addr = new_addr + 0x1000 if left_over > 0: ImageXpressHeader = self.get_addr(new_addr) if ImageXpressHeader == None: stuff_read = stuff_read + ('\0' * left_over) else: stuff_read = stuff_read + self.read(new_addr, left_over) return stuff_read def read_long(self, addr): baseaddr = self.get_addr(addr) string = self.read(addr, 4) (longval, ) = struct.unpack('=L', string) return longval def get_available_pages(self): page_list = [] for i,xb in enumerate(self.PageDict.keys()): for page,size,offset in self.PageDict[xb]: page_list.append([page*0x1000, 0x1000]) return page_list def get_address_range(self): """ This relates to the logical address range that is indexable """ size = self.HighestPage*0x1000+0x1000 return [0,size] def check_address_range(self,addr): memrange = self.get_address_range() if addr < memrange[0] or addr > memrange[1]: raise IOError def get_available_addresses(self): """ This returns the ranges of valid addresses """ return self.AddressList def close(self): self.base.close() def get_version(self): if self.is_pae() == 1: addr_space = IA32PagedMemoryPae(self,self.CR3) else: addr_space = IA32PagedMemory(self,self.CR3) if addr_space == None: return (None,None,None) GdtIndex = (0x3B >> 3) GdtrBase = read_obj(self.base, types, ['_KPROCESSOR_STATE', 'SpecialRegisters','Gdtr','Base'], \ self.ProcStateOffset) NtTibAddr = GdtrBase + GdtIndex * obj_size(hiber_types,'_KGDTENTRY') BaseLow = read_obj(addr_space, hiber_types, ['_KGDTENTRY','BaseLow'], NtTibAddr) BaseMid = read_obj(addr_space, hiber_types, ['_KGDTENTRY','BaseMid'], NtTibAddr) BaseHigh = read_obj(addr_space, hiber_types, ['_KGDTENTRY','BaseHigh'], NtTibAddr) NtTibAddress = (BaseLow) | (BaseMid << (2 * 8)) | (BaseHigh << (3 * 8)); if ((NtTibAddress == 0) or (NtTibAddress > 0x80000000)): return (None,None,None) ProcessEnvironmentBlock = read_obj(addr_space, types, ['_TEB', 'ProcessEnvironmentBlock'], NtTibAddress) OSMajorVersion = read_obj(addr_space, types, ['_PEB', 'OSMajorVersion'], ProcessEnvironmentBlock) OSMinorVersion = read_obj(addr_space, types, ['_PEB','OSMinorVersion'], ProcessEnvironmentBlock) OSBuildNumber = read_obj(addr_space, types, ['_PEB','OSBuildNumber'],ProcessEnvironmentBlock) return (OSMajorVersion,OSMinorVersion,OSBuildNumber) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/info.py000066400000000000000000000161401217176075400247740ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ # # Details about the techniques used in this file can be found in # the following references: # - Opc0de, "Finding some non-exported kernel variables," # http://www.rootkit.com/vault/Opc0de/GetVarXP.pdf # - Alex Ionescu, "Getting Kernel Variables from KdVersionBlock, Part 2," # http://www.rootkit.com/newsread.php?newsid=153 # from forensics.object import * from forensics.win32.datetime import system_time from struct import unpack kpcr_addr = 0xffdff000 KUSER_SHARED_DATA = 0xFFDF0000 def info_mmpfndatabase64(addr_space, types, addr): return read_obj(addr_space, types, ['_KDDEBUGGER_DATA64', 'MmPfnDatabase'], addr) def info_psactiveprocesshead64(addr_space, types, debug_addr): return read_obj(addr_space, types, ['_KDDEBUGGER_DATA64', 'PsActiveProcessHead'], debug_addr) def info_psactiveprocesshead32(addr_space, types, debug_addr): return read_obj(addr_space, types, ['_KDDEBUGGER_DATA32', 'PsActiveProcessHead'], debug_addr) def info_psloadedmodulelist64(addr_space, types, addr): return read_obj(addr_space, types, ['_KDDEBUGGER_DATA64', 'PsLoadedModuleList'], addr) def info_psloadedmodulelist32(addr_space, types, debug_addr): return read_obj(addr_space, types, ['_KDDEBUGGER_DATA32', 'PsLoadedModuleList'], debug_addr) def info_kdversionblock(addr_space, types, addr): return read_obj(addr_space, types, ['_KPCR', 'KdVersionBlock'], addr) def info_debuggerdatalist(addr_space,types,addr): return read_obj(addr_space, types, ['_DBGKD_GET_VERSION64', 'DebuggerDataList'], addr) def find_psactiveprocesshead(addr_space, types): if not addr_space.is_valid_address(kpcr_addr): print "Unable to find PsActiveProcessHead" return None KdVersionBlock = info_kdversionblock(addr_space, types, kpcr_addr) if not addr_space.is_valid_address(KdVersionBlock): print "Unable to find PsActiveProcessHead" return None DebuggerDataList = info_debuggerdatalist(addr_space, types, KdVersionBlock) if addr_space.is_valid_address(DebuggerDataList): current = read_value(addr_space, 'unsigned long', DebuggerDataList) PsActiveProcessHead = info_psactiveprocesshead64(addr_space, types, current) if not addr_space.is_valid_address(PsActiveProcessHead): PsActiveProcessHead = info_psactiveprocesshead32(addr_space, types, KdVersionBlock) if not addr_space.is_valid_address(PsActiveProcessHead): print "Unable to find PsActiveProcessHead" return None else: PsActiveProcessHead = info_psactiveprocesshead32(addr_space, types, KdVersionBlock) if not addr_space.is_valid_address(PsActiveProcessHead): print "Unable to find PsActiveProcessHead" return None return PsActiveProcessHead def find_psloadedmodulelist(addr_space, types): if not addr_space.is_valid_address(kpcr_addr): print "Unable to find PsLoadedModuleList" return None KdVersionBlock = info_kdversionblock(addr_space, types, kpcr_addr) if not addr_space.is_valid_address(KdVersionBlock): print "Unable to find PsLoadedModuleList" return None DebuggerDataList = info_debuggerdatalist(addr_space, types, KdVersionBlock) if addr_space.is_valid_address(DebuggerDataList): current = read_value(addr_space, 'unsigned long', DebuggerDataList) PsLoadedModuleList = info_psloadedmodulelist64(addr_space, types, current) if not addr_space.is_valid_address(PsLoadedModuleList): PsLoadedModuleList = info_psloadedmodulelist32(addr_space, types, KdVersionBlock) if not addr_space.is_valid_address(PsLoadedModuleList): print "Unable to find PsLoadedModuleList" return None else: PsLoadedModuleList = info_psloadedmodulelist32(addr_space, types, KdVersionBlock) if not addr_space.is_valid_address(PsLoadedModuleList): print "Unable to find PsLoadedModuleList" return None return PsLoadedModuleList def find_mmpfndatabase(addr_space, types): if not addr_space.is_valid_address(kpcr_addr): print "Unable to find MmPfnDatabase" return None KdVersionBlock = info_kdversionblock(addr_space, types, kpcr_addr) if not addr_space.is_valid_address(KdVersionBlock): print "Unable to find MmPfnDatabase" return None DebuggerDataList = info_debuggerdatalist(addr_space, types, KdVersionBlock) if addr_space.is_valid_address(DebuggerDataList): current = read_value(addr_space, 'unsigned long', DebuggerDataList) MmPfnDatabase = info_mmpfndatabase64(addr_space, types, current) if not addr_space.is_valid_address(MmPfnDatabase): print "Unable to find MmPfnDatabase" return None else: MmPfnDatabase = read_value(addr_space, 'pointer', MmPfnDatabase) else: print "Unable to find MmPfnDatabase" return None return MmPfnDatabase def find_kddebuggerdatablock(addr_space, types): if not addr_space.is_valid_address(kpcr_addr): print "Unable to find KdDebuggerDataBlock" return None KdVersionBlock = info_kdversionblock(addr_space, types, kpcr_addr) if not addr_space.is_valid_address(KdVersionBlock): print "Unable to find KdDebuggerDataBlock" return None DebuggerDataList = info_debuggerdatalist(addr_space, types, KdVersionBlock) if addr_space.is_valid_address(DebuggerDataList): KdDebuggerDataBlock = read_value(addr_space, 'pointer', DebuggerDataList) if not addr_space.is_valid_address(KdDebuggerDataBlock): print "Unable to find KdDebuggerDataBlock" return None else: print "Unable to find KdDebuggerDataBlock" return None return KdDebuggerDataBlock def find_suitemask(addr_space, types): return read_obj(addr_space, types, ['_KUSER_SHARED_DATA', 'SuiteMask'],KUSER_SHARED_DATA ) def find_systemtime(addr_space, types): return system_time(addr_space, types, KUSER_SHARED_DATA) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/meta_info.py000066400000000000000000000023231217176075400260000ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems LLC """ # Global Variables DirectoryTableBase = "" KernelAddressSpace = "" def set_dtb(dtb): global DirectoryTableBase DirectoryTableBase = dtb def set_kas(kas): global KernelAddressSpace KernelAddressSpace = kas def set_datatypes(datatypes): global DataTypes DataTypes = datatypes dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/modules.py000066400000000000000000000064001217176075400255070ustar00rootroot00000000000000# Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Nick Petroni @license: GNU General Public License 2.0 or later @contact: awalters@komoku.com, npetroni@komoku.com @organization: Komoku, Inc. """ from forensics.object import * from forensics.win32.info import * def modules_list(addr_space, types, symbol_table): """ Get the virtual addresses of all Windows modules """ modules_list = [] PsLoadedModuleList = find_psloadedmodulelist(addr_space, types) if not PsLoadedModuleList is None: (offset, tmp) = get_obj_offset(types, ['_LDR_MODULE', 'InLoadOrderModuleList']) first_module = PsLoadedModuleList - offset current = read_obj(addr_space, types, ['_LDR_MODULE', 'InLoadOrderModuleList', 'Flink'], first_module) this_module = current - offset next = read_obj(addr_space, types, ['_LDR_MODULE', 'InLoadOrderModuleList', 'Flink'], this_module) while this_module != PsLoadedModuleList: if not addr_space.is_valid_address(this_module): print "Module list truncated, unable to read 0x%x." % (this_module) return modules_list modules_list.append(this_module) current = read_obj(addr_space, types, ['_LDR_MODULE', 'InLoadOrderModuleList', 'Flink'], this_module) this_module = current - offset if not addr_space.is_valid_address(this_module): print "ModuleList Truncated Invalid Module" return modules_list return modules_list def module_imagename(address_space, types, module_vaddr): return read_unicode_string(address_space, types, ['_LDR_MODULE', 'FullDllName'], module_vaddr) def module_modulename(address_space, types, module_vaddr): return read_unicode_string(address_space, types, ['_LDR_MODULE', 'ModuleName'], module_vaddr) def module_imagesize(address_space, types, module_vaddr): return read_obj(address_space, types, ['_LDR_MODULE', 'SizeOfImage'], module_vaddr) def module_baseaddr(address_space, types, module_vaddr): return read_obj(address_space, types, ['_LDR_MODULE', 'BaseAddress'], module_vaddr) def module_find_baseaddr(addr_space, types,modules,name): for module in modules: module_name = module_imagename(addr_space, types, module) if module_name is None: continue if module_name.find(name) != -1: return module_baseaddr(addr_space, types, module) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/network.py000066400000000000000000000173021217176075400255330ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ from forensics.object import * from forensics.win32.datetime import * from forensics.win32.modules import * from socket import ntohs, inet_ntoa module_versions = { \ 'MP' : { \ 'TCBTableOff' : [0x497e8], \ 'SizeOff' : [0x3f7c8], \ 'AddrObjTableOffset' : [0x48760], \ 'AddrObjTableSizeOffset' : [0x48764], \ }, 'UP' : { \ 'TCBTableOff' : [0x495e8], \ 'SizeOff' : [0x3f5bc], \ 'AddrObjTableOffset' : [0x48560], \ 'AddrObjTableSizeOffset' : [0x48564], \ }, '2180' : { \ 'TCBTableOff' : [0x493e8], \ 'SizeOff' : [0x3f3b0], \ 'AddrObjTableOffset' : [0x48360], \ 'AddrObjTableSizeOffset' : [0x48364], \ }, '3244' : { \ 'TCBTableOff' : [0x496E8], \ 'SizeOff' : [0x3F6BC], \ 'AddrObjTableOffset' : [0x48660], \ 'AddrObjTableSizeOffset' : [0x48664], \ }, '2111' : { \ 'TCBTableOff' : [0x49A68], \ 'SizeOff' : [0x3FA48], \ 'AddrObjTableOffset' : [0x489E0], \ 'AddrObjTableSizeOffset' : [0x489E4], \ } } def tcb_connections(addr_space, types, symbol_table): all_modules = modules_list(addr_space, types, symbol_table) base_addr = module_find_baseaddr(addr_space, types, all_modules,"tcpip") if base_addr is None: return [] connection_list = [] connection_list = find_connections(addr_space, types, symbol_table, base_addr) return connection_list def get_tcb_connections(addr_space, types, symbol_table, base_addr, TCBTableOff, SizeOff): TCBTable = base_addr + TCBTableOff MaxHashTableSize = base_addr + SizeOff TCBTableAddr = read_value(addr_space, 'unsigned long', TCBTable) if TCBTableAddr == None: return [] if not addr_space.is_valid_address(TCBTableAddr): return [] TableSize = read_value(addr_space, 'unsigned long', MaxHashTableSize) if TableSize == None: return [] connection_list = [] for cnt in range(0,TableSize): EntryAddress=TCBTableAddr + 4*cnt if not addr_space.is_valid_address(EntryAddress): continue TableEntry = read_value(addr_space, 'unsigned long', EntryAddress) if TableEntry == 0 or TableEntry == None: continue next = read_obj(addr_space, types, ['_TCPT_OBJECT', 'Next'], TableEntry) while next != 0x0: if not addr_space.is_valid_address(next): print "ConnectionList Truncated Invalid 0x%x"%next return connection_list connection_list.append(next) next = read_obj(addr_space, types, ['_TCPT_OBJECT', 'Next'], next) connection_list.append(TableEntry) return connection_list def find_connections(addr_space, types, symbol_table, base_addr): connection_list = [] for offsets in module_versions: offsets = module_versions[offsets] connection_list = get_tcb_connections(addr_space, types, symbol_table, base_addr, offsets['TCBTableOff'][0], offsets['SizeOff'][0]) if len(connection_list) > 0: return connection_list return connection_list def connection_pid(addr_space, types, connection_vaddr): return read_obj(addr_space, types, ['_TCPT_OBJECT', 'Pid'], connection_vaddr) def connection_lport(addr_space, types, connection_vaddr): return ntohs(read_obj(addr_space, types, ['_TCPT_OBJECT', 'LocalPort'], connection_vaddr)) def connection_laddr(addr_space, types, connection_vaddr): laddr = read_obj(addr_space, types, ['_TCPT_OBJECT', 'LocalIpAddress'], connection_vaddr) return inet_ntoa(struct.pack('=L',laddr)) def connection_rport(addr_space, types, connection_vaddr): return ntohs(read_obj(addr_space, types, ['_TCPT_OBJECT', 'RemotePort'], connection_vaddr)) def connection_raddr(addr_space, types, connection_vaddr): raddr = read_obj(addr_space, types, ['_TCPT_OBJECT', 'RemoteIpAddress'], connection_vaddr) return inet_ntoa(struct.pack('=L',raddr)) def open_sockets(addr_space, types, symbol_table): all_modules = modules_list(addr_space, types, symbol_table) base_addr = module_find_baseaddr(addr_space, types, all_modules,"tcpip") if base_addr is None: return [] socket_list = [] socket_list = find_sockets(addr_space, types, symbol_table, base_addr) return socket_list def get_open_sockets(addr_space, types, symbol_table, base_addr, AddrObjTableOffset, AddrObjTableSizeOffset): AddrObjTable = base_addr + AddrObjTableOffset AddrObjTableSize = base_addr + AddrObjTableSizeOffset AddrObjAddr = read_value(addr_space, 'unsigned long', AddrObjTable) AddrTableSize = read_value(addr_space, 'unsigned long', AddrObjTableSize) if AddrObjAddr == None or AddrTableSize == None: return [] socket_list = [] for cnt in range(0,AddrTableSize): EntryAddress=AddrObjAddr + 4*cnt if not addr_space.is_valid_address(EntryAddress): continue TableEntry = read_value(addr_space, 'unsigned long', EntryAddress) if TableEntry == 0 or TableEntry == None: continue socket_list.append(TableEntry) next = read_obj(addr_space, types, ['_ADDRESS_OBJECT', 'Next'], TableEntry) while next != 0x0: if not addr_space.is_valid_address(next): print "SocketList Truncated Invalid 0x%x"%next return socket_list socket_list.append(next) next = read_obj(addr_space, types, ['_ADDRESS_OBJECT', 'Next'], next) return socket_list def find_sockets(addr_space, types, symbol_table, base_addr): socket_list = [] for offsets in module_versions: offsets = module_versions[offsets] socket_list = get_open_sockets(addr_space, types, symbol_table, base_addr, offsets['AddrObjTableOffset'][0], offsets['AddrObjTableSizeOffset'][0]) if len(socket_list) > 0: return socket_list return socket_list def socket_pid(addr_space, types, socket_vaddr): return read_obj(addr_space, types, ['_ADDRESS_OBJECT', 'Pid'], socket_vaddr) def socket_protocol(addr_space, types, socket_vaddr): return read_obj(addr_space, types, ['_ADDRESS_OBJECT', 'Protocol'], socket_vaddr) def socket_local_port(addr_space, types, socket_vaddr): return ntohs(read_obj(addr_space, types, ['_ADDRESS_OBJECT', 'LocalPort'], socket_vaddr)) def socket_create_time(addr_space, types, socket_vaddr): (create_time_offset, tmp) = get_obj_offset(types, ['_ADDRESS_OBJECT', 'CreateTime']) create_time = read_time(addr_space, types, socket_vaddr + create_time_offset) if create_time == None: return None create_time = windows_to_unix_time(create_time) return create_time dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/registry.py000066400000000000000000000055671217176075400257240ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com,bdolangavitt@wesleyan.edu @organization: Volatile Systems LLC """ from forensics.object import * from forensics.win32.info import * from forensics.win32.datetime import windows_to_unix_time from forensics.addrspace import FileAddressSpace from forensics.win32.handles import handle_entry_object,is_object_key,object_data def print_entry_keys(addr_space, types, entry): if not addr_space.is_valid_address(entry): return obj = handle_entry_object(addr_space, types, entry) if addr_space.is_valid_address(obj): if is_object_key(addr_space, types, obj): key = object_data(addr_space, types, obj) KeyControlBlock = read_obj(addr_space, types, ['_CM_KEY_BODY', 'KeyControlBlock'], key) NameBlock = read_obj(addr_space, types, ['_CM_KEY_CONTROL_BLOCK', 'NameBlock'], KeyControlBlock) if addr_space.is_valid_address(NameBlock): NameLength = read_obj(addr_space, types, ['_CM_NAME_CONTROL_BLOCK', 'NameLength'], NameBlock) OutName = read_string(addr_space, types, ['_CM_NAME_CONTROL_BLOCK', 'Name'] , NameBlock , NameLength) ParentKcb = read_obj(addr_space, types, ['_CM_KEY_CONTROL_BLOCK', 'ParentKcb'], KeyControlBlock) while ( ParentKcb != 0 and addr_space.is_valid_address(ParentKcb)): NameBlock = read_obj(addr_space, types, ['_CM_KEY_CONTROL_BLOCK', 'NameBlock'], ParentKcb) if addr_space.is_valid_address(NameBlock): NameLength = read_obj(addr_space, types, ['_CM_NAME_CONTROL_BLOCK', 'NameLength'], NameBlock) Name = read_string(addr_space, types, ['_CM_NAME_CONTROL_BLOCK', 'Name'] , NameBlock , NameLength) OutName = Name + '\\' + OutName ParentKcb = read_obj(addr_space, types, ['_CM_KEY_CONTROL_BLOCK', 'ParentKcb'], ParentKcb) OutName = '\\' + OutName return OutName dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/scan.py000066400000000000000000000575621217176075400250020ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Source code in this file was inspired by the work of Andreas Schuster # and ptfinder """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems. """ from forensics.object import * from forensics.win32.datetime import * import os from struct import unpack from forensics.win32.info import * from forensics.win32.tasks import * from forensics.win32.network import * from forensics.win32.modules import * from forensics.x86 import * import forensics.win32.meta_info as meta_info class Scan: def __init__(self,addr_space,beg,end,collect=False): self.beg = beg self.end = end self.addr_space = addr_space self.scanobjects = [] self.collect = collect def add_object(self,scanobject): self.scanobjects.append(scanobject) def scan(self): offset = self.beg while offset <= self.end: for object in self.scanobjects: object.check_addr(offset) if object.cnt >= object.limit: if self.collect == False: object.matches.append(offset) cnt = len(object.matches) object.dump(offset,cnt,object) elif self.collect == True: object.matches.append(offset) offset+=8 class ScanObject: def __init__(self, addr_space,types,fast=True): self.checks = [] self.cnt = 0 self.addr_space = addr_space self.types = types self.matches = [] self.limit = 0 self.fast = fast if fast == True: try: self.fast_address_space = FileAddressSpace(self.addr_space.fname,fast=True) except: print "Unable to open fast address space %s"%(self.addr_space.fname) return def set_limit(self, limit): self.limit = limit def get_matches(self): return self.matches def add_check(self,func): self.checks.append(func) def check_addr(self,address): self.cnt = 0 for func in self.checks: val = func(address,self) if self.fast ==0: if val == True: self.cnt = self.cnt+1 else: if val == False: break else: self.cnt = self.cnt+1 def set_dump(self,func): self.dump=func def set_header(self,header): self.hdr=header def set_fast_beg(self,offset): self.fast_address_space.fast_fhandle.seek(offset) def format_time(time): ts=strftime("%a %b %d %H:%M:%S %Y", gmtime(time)) return ts def format_dot_time(time): ts=strftime("%H:%M:%S\\n%Y-%m-%d", gmtime(time)) return ts def check_dispatch_header(address,object): if object.fast == True: data = object.addr_space.fread(8) (type,size) = unpack('=HH',data[:4]) if(size == 0x1b and type == 0x03): return True return False else: Type = read_obj(object.addr_space, object.types, ['_EPROCESS', 'Pcb', 'Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_EPROCESS', 'Pcb', 'Header','Size'], address) if Type == None or Size == None: return False if(Size == 0x1b and Type == 0x03): return True return False def check_dtb(address, object): DirectoryTableBase = process_dtb(object.addr_space, object.types, address) if DirectoryTableBase == 0: return False return True def check_dtb_aligned(address, object): # On systems using PAE, EPROCESS.DirectoryTableBase actually # points to the base of the page directory pointer array. DirectoryTableBase = process_dtb(object.addr_space, object.types, address) if DirectoryTableBase == None: return False if (DirectoryTableBase % 0x20 != 0): return False return True def check_thread_list(address, object): kernel = 0x80000000; thread_list_head_flink = read_obj(object.addr_space, object.types, ['_EPROCESS', 'ThreadListHead', 'Flink'], address) if thread_list_head_flink < kernel: return False thread_list_head_blink = read_obj(object.addr_space, object.types, ['_EPROCESS', 'ThreadListHead', 'Blink'], address) if thread_list_head_blink < kernel: return False return True def check_synchronization(address, object): Type = read_obj(object.addr_space, object.types, ['_EPROCESS', 'WorkingSetLock','Event', 'Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_EPROCESS', 'WorkingSetLock','Event','Header','Size'], address) if Type == None or Size == None: return False if(Size != 0x4 and Type != 0x1): return False Type = read_obj(object.addr_space, object.types, ['_EPROCESS', 'AddressCreationLock','Event', 'Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_EPROCESS', 'AddressCreationLock','Event','Header','Size'], address) if Type == None or Size == None: return False if(Size != 0x04 and Type != 0x01): return False return True def eprocess_dump(address, cnt, object): UniqueProcessId = process_pid(object.addr_space, object.types, address) ImageFileName = process_imagename(object.addr_space, object.types, address) DirectoryTableBase = process_dtb(object.addr_space, object.types, address) CreateTime = process_create_time(object.addr_space, object.types, address) ExitTime = process_exit_time(object.addr_space, object.types, address) InheritedFromUniqueProcessId = process_inherited_from(object.addr_space, object.types, address) if CreateTime == 0: CreateTime = "" else: CreateTime = format_time(CreateTime) if ExitTime == 0: ExitTime = "" else: ExitTime = format_time(ExitTime) print "%4d %6d %6d %24s %24s 0x%0.8x 0x%0.8x %-16s"%(cnt,UniqueProcessId,InheritedFromUniqueProcessId,CreateTime,ExitTime,address,DirectoryTableBase,ImageFileName) def eprocess_dump_dot(address, cnt, object): UniqueProcessId = process_pid(object.addr_space, object.types, address) ImageFileName = process_imagename(object.addr_space, object.types, address) CreateTime = process_create_time(object.addr_space, object.types, address) ExitTime = process_exit_time(object.addr_space, object.types, address) InheritedFromUniqueProcessId = process_inherited_from(object.addr_space, object.types, address) ExitStatus = process_exit_status(object.addr_space, object.types, address) if CreateTime == 0: CreateTime = "" else: CreateTime = format_dot_time(CreateTime) CreateTime = " | started\\n%s"%CreateTime if ExitTime == 0: ExitTime = "" else: ExitTime = format_dot_time(ExitTime) if not ExitTime == "": print "pid%u [label = \"{%u | file ofs\\n0x%x | %s%s | exited\\n%s\\n code %d}\" shape = \"record\" style = \"filled\" fillcolor = \"lightgray\"];"%(UniqueProcessId,UniqueProcessId,address, ImageFileName,CreateTime, ExitTime,ExitStatus) else: print "pid%u [label = \"{%u | file ofs\\n0x%x | %s%s | running}\" shape = \"record\"];"%(UniqueProcessId,UniqueProcessId,address,ImageFileName,CreateTime) print "pid%u -> pid%u []"%(InheritedFromUniqueProcessId,UniqueProcessId) def ps_scan(addr_space, types, filename, beg, end, slow): if slow == False: eprocess_object = ScanObject(addr_space,types) eprocess_object.set_fast_beg(beg) else: eprocess_object = ScanObject(addr_space,types,fast=False) eprocess_object.add_check(check_dispatch_header) eprocess_object.add_check(check_dtb) eprocess_object.add_check(check_dtb_aligned) eprocess_object.add_check(check_thread_list) eprocess_object.add_check(check_synchronization) eprocess_object.set_dump(eprocess_dump) eprocess_object.set_limit(5) object_header = \ "No. PID PPID Time created Time exited Offset PDB Remarks\n"+ \ "---- ------ ------ ------------------------ ------------------------ ---------- ---------- ----------------\n"; eprocess_object.set_header(object_header) end = end - obj_size(types,'_EPROCESS') process_scan = Scan(addr_space,beg,end,False) process_scan.add_object(eprocess_object) print object_header process_scan.scan() def ps_scan_dot(addr_space, types, filename, beg, end, slow): if slow == False: eprocess_object = ScanObject(addr_space,types) eprocess_object.set_fast_beg(beg) else: eprocess_object = ScanObject(addr_space,types,fast=False) eprocess_object.add_check(check_dispatch_header) eprocess_object.add_check(check_dtb) eprocess_object.add_check(check_dtb_aligned) eprocess_object.add_check(check_thread_list) eprocess_object.add_check(check_synchronization) eprocess_object.set_dump(eprocess_dump_dot) eprocess_object.set_limit(5) object_header = \ "digraph processtree { \n" + \ "graph [rankdir = \"TB\"];" eprocess_object.set_header(object_header) end = end - obj_size(types,'_EPROCESS') process_scan = Scan(addr_space,beg,end,False) process_scan.add_object(eprocess_object) print object_header process_scan.scan() print "}" def check_thread_thread_process(address,object): kernel = 0x8000000 UniqueProcess = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Cid', 'UniqueProcess'], address) ThreadsProcess = read_obj(object.addr_space, object.types, ['_ETHREAD', 'ThreadsProcess'], address) if UniqueProcess != 0 and ThreadsProcess < kernel: return False return True def check_thread_start_address(address, object): UniqueProcess = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Cid', 'UniqueProcess'], address) StartAddress = read_obj(object.addr_space, object.types, ['_ETHREAD', 'StartAddress'], address) if StartAddress == 0 and UniqueProcess != 0: return False return True def check_thread_dispatch_header(address,object): if object.fast == True: data = object.addr_space.fread(8) (type,size) = unpack('=HH',data[:4]) if(size == 0x70 and type == 0x06): return True return False else: Type = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Tcb', 'Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Tcb', 'Header','Size'], address) if Type == None or Size == None: return False if(Size == 0x70 and Type == 0x06): return True return False def check_thread_notification_timer(address, object): Type = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Tcb', 'Timer','Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Tcb', 'Timer','Header','Size'], address) if Type == None or Size == None: return False if(Size != 0xa and Type != 0x8): return False return True def check_thread_semaphores(address, object): UniqueProcess = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Cid', 'UniqueProcess'], address) Type = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Tcb', 'SuspendSemaphore','Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Tcb', 'SuspendSemaphore','Header','Size'], address) if Type == None or Size == None: return False if(Size != 0x5 and Type != 0x5): return False Type = read_obj(object.addr_space, object.types, ['_ETHREAD', 'LpcReplySemaphore','Header','Type'], address) Size = read_obj(object.addr_space, object.types, ['_ETHREAD', 'LpcReplySemaphore','Header','Size'], address) if Type == None or Size == None: return False if((Size != 0x5 and Type != 0x5) and UniqueProcess != 0): return False return True def ethread_dump(address, cnt, object): UniqueProcess = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Cid', 'UniqueProcess'], address) UniqueThread = read_obj(object.addr_space, object.types, ['_ETHREAD', 'Cid', 'UniqueThread'], address) print "%4d %6d %6d 0x%0.8x"%(cnt,UniqueProcess,UniqueThread,address) def thrd_scan(addr_space, types, filename,beg,end,slow): if slow == False: ethread_object = ScanObject(addr_space,types) ethread_object.set_fast_beg(beg) else: ethread_object = ScanObject(addr_space,types,fast=False) ethread_object.add_check(check_thread_dispatch_header) ethread_object.add_check(check_thread_thread_process) ethread_object.add_check(check_thread_start_address) ethread_object.add_check(check_thread_notification_timer) ethread_object.add_check(check_thread_semaphores) ethread_object.set_dump(ethread_dump) ethread_object.set_limit(5) object_header = \ "No. PID TID Offset \n"+ \ "---- ------ ------ ----------\n"; end = end - obj_size(types,'_ETHREAD') thread_scan = Scan(addr_space,beg,end,False) thread_scan.add_object(ethread_object) print object_header thread_scan.scan() def check_socket_poolindex(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) if pool_hdr_val == None: return False PoolIndex = (pool_hdr_val) & 0xFFFF PoolIndex = (PoolIndex & 0xFE00) >> 9 if PoolIndex == 0: return True return False def check_socket_pooltype(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) if pool_hdr_val == None: return False PoolType = (pool_hdr_val >> 16) & 0xFFFF PoolType = (PoolType & 0xFE00) >> 9 if ((PoolType == 0) or ((PoolType % 2) == 1)): return True return False def check_socket_blocksize(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) if pool_hdr_val == None: return False BlockSize = (pool_hdr_val >> 16) & 0x1FF pool_size = BlockSize * 0x8 if pool_size == 0x170: return True return False def check_socket_create_time(address, object): address = address + obj_size(object.types,'_POOL_HEADER') time = socket_create_time(object.addr_space, object.types, address) if time > 0: return True return False def check_socket_pooltag(address,object): if object.fast == True: data = object.addr_space.fread(8) (PoolTag, ) = unpack('=L',data[4:8]) if(PoolTag == 0x41504354): return True return False else: pool_tag_addr = address PoolTag = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'PoolTag'], pool_tag_addr) if PoolTag == None: return False if PoolTag == 0x41504354: return True return False def socket_dump(address, cnt, object): address = address + obj_size(object.types,'_POOL_HEADER') pid = socket_pid(object.addr_space, object.types, address) proto = socket_protocol(object.addr_space, object.types, address) port = socket_local_port(object.addr_space, object.types, address) time = socket_create_time(object.addr_space, object.types, address) try: print "%-6d %-6d %-6d %-26s 0x%0.8x"%(pid,port,proto,format_time(time),address) except: return def socket_scan(addr_space, types, filename, beg, end, slow): if slow == False: socket_object = ScanObject(addr_space,types) socket_object.set_fast_beg(beg) else: socket_object = ScanObject(addr_space,types,fast=False) socket_object.add_check(check_socket_pooltag) socket_object.add_check(check_socket_blocksize) socket_object.add_check(check_socket_pooltype) socket_object.add_check(check_socket_poolindex) socket_object.add_check(check_socket_create_time) socket_object.set_dump(socket_dump) socket_object.set_limit(5) object_header = \ "PID Port Proto Create Time Offset \n"+ \ "------ ------ ------ -------------------------- ----------\n"; socket_object.set_header(object_header) end = end - (obj_size(types,'_POOL_HEADER') + 0x170) socket_scan = Scan(addr_space,beg,end,False) socket_scan.add_object(socket_object) print object_header socket_scan.scan() def check_connection_poolprevioussize(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) PreviousSize = (pool_hdr_val) & 0x1FF return False def check_connection_poolindex(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) PoolIndex = (pool_hdr_val) & 0xFFFF PoolIndex = (PoolIndex & 0xFE00) >> 9 if PoolIndex == 0: return True return False def check_connection_pooltype(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) if pool_hdr_val == None: return False PoolType = (pool_hdr_val >> 16) & 0xFFFF PoolType = (PoolType & 0xFE00) >> 9 if ((PoolType == 0) or ((PoolType % 2) == 1)): return True return False def check_connection_blocksize(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) if pool_hdr_val == None: return False BlockSize = (pool_hdr_val >> 16) & 0x1FF pool_size = BlockSize * 0x8 if pool_size == 0x198: return True return False def check_connection_pooltag(address,object): if object.fast == True: data = object.addr_space.fread(8) (PoolTag, ) = unpack('=L',data[4:8]) if(PoolTag == 0x54504354): return True return False else: pool_tag_addr = address PoolTag = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'PoolTag'], pool_tag_addr) if PoolTag == None: return False if PoolTag == 0x54504354: return True return False def connection_dump(address, cnt, object): address = address + obj_size(object.types,'_POOL_HEADER') pid = connection_pid(object.addr_space, object.types, address) lport = connection_lport(object.addr_space, object.types, address) laddr = connection_laddr(object.addr_space, object.types, address) rport = connection_rport(object.addr_space, object.types, address) raddr = connection_raddr(object.addr_space, object.types, address) local = "%s:%d"%(laddr,lport) remote = "%s:%d"%(raddr,rport) print "%-25s %-25s %-6d"%(local,remote,pid) def conn_scan(addr_space, types, filename, beg, end, slow): if slow == False: connection_object = ScanObject(addr_space,types) connection_object.set_fast_beg(beg) else: connection_object = ScanObject(addr_space,types,fast=False) connection_object.add_check(check_connection_pooltag) connection_object.add_check(check_connection_blocksize) connection_object.add_check(check_connection_pooltype) connection_object.add_check(check_socket_poolindex) connection_object.set_dump(connection_dump) connection_object.set_limit(4) object_header = \ "Local Address Remote Address Pid \n"+ \ "------------------------- ------------------------- ------ \n"; connection_object.set_header(object_header) end = end - (obj_size(types,'_POOL_HEADER') + 0x198) socket_scan = Scan(addr_space,beg,end,False) socket_scan.add_object(connection_object) print object_header socket_scan.scan() #################################################################### # # Module: modscan # Author: Andreas Schuster # Description: Performs a linear scan of memory looking for modules # #################################################################### def check_module_blocksize(address,object): pool_header_addr = address pool_hdr_val = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'Ulong1'], pool_header_addr) BlockSize = (pool_hdr_val >> 16) & 0x1FF pool_size = BlockSize * 0x8 if pool_size >= 0x76: return True return False def check_module_pooltag(address,object): if object.fast == True: data = object.addr_space.fread(8) (PoolTag, ) = unpack('=L',data[4:8]) if(PoolTag == 0x644c6d4d): return True return False else: # slow scanning mode pool_tag_addr = address PoolTag = read_obj(object.addr_space, object.types, ['_POOL_HEADER', 'PoolTag'], pool_tag_addr) if PoolTag == None: return False if PoolTag == 0x644c6d4d: return True return False def module_pool_imagename(flat_addr_space, types, address): system_addr_space = meta_info.KernelAddressSpace return read_unicode_string_p(flat_addr_space, system_addr_space, types, ['_LDR_MODULE', 'FullDllName'], address) def module_pool_modulename(flat_addr_space, types, address): system_addr_space = meta_info.KernelAddressSpace return read_unicode_string_p(flat_addr_space, system_addr_space, types, ['_LDR_MODULE', 'ModuleName'], address) def module_dump(address, cnt, object): address = address + obj_size(object.types,'_POOL_HEADER') baseaddr = module_baseaddr(object.addr_space, object.types, address) imagesize = module_imagesize(object.addr_space, object.types, address) imagename = module_pool_imagename(object.addr_space, object.types, address) modulename = module_pool_modulename(object.addr_space, object.types, address) print "%-50s 0x%010x 0x%06x %s" % \ (imagename, baseaddr, imagesize, modulename) def module_scan(flat_addr_space, types, filename, beg, end, slow): if slow == False: module_object = ScanObject(flat_addr_space, types) module_object.set_fast_beg(beg) else: module_object = ScanObject(flat_addr_space, types, fast=False) # define checks module_object.add_check(check_module_pooltag) module_object.add_check(check_module_blocksize) module_object.set_limit(1) # define data dumper module_object.set_dump(module_dump) # define output format object_header = "%-50s %-12s %-8s %s" %('File','Base', 'Size', 'Name') module_object.set_header(object_header) # FIXME: account for actual BlockSize end = end - (obj_size(types,'_POOL_HEADER') + 0x76) module_scan = Scan(flat_addr_space,beg,end,False) module_scan.add_object(module_object) print object_header module_scan.scan() dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/scan2.py000066400000000000000000000666171217176075400250650ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Derived from source in PyFlag developed by: # Copyright 2004: Commonwealth of Australia. # Michael Cohen # David Collett # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # Special thanks to Michael Cohen for ideas and comments! # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems. """ import os from struct import unpack from forensics.object import * from forensics.win32.datetime import * from forensics.win32.info import * from forensics.win32.tasks import * from forensics.win32.network import * from forensics.win32.modules import * from forensics.x86 import * import forensics.win32.meta_info as meta_info class BaseMemoryScanner: """ This is the actual scanner class that will be instantiated for each address space to be analyzed. Within Volatility, all scans are performed over an address space, which is used to simulate random access over a logical view of data. """ def __init__(self, poffset, outer): """ @arg poffset: The offset of the data being scanned @arg outer: This references the generator object """ self.poffset = poffset self.ignore = False self.outer = outer def process(self, data, offset, metadata={}): """ process the chunk of data. This function is given a chunk of data from the address space. @arg data: Some limited amount of data from the address space. The size of the data is unspecified. @arg metadata: A dict specifying meta data that was deduced about this data from other scanners. Scanners may add meta data to this dict in order to indicate certain facts to other scanners about this data. """ pass def finish(self): """ all data has been provided to process, finish up. Note that this signals that the chunk has been processed. """ pass class GenMemScanObject: """ Abstract Base class for scanner Factories. The Scanner Object is a specialised class for producing scanner objects. It will be instantiated once at the begining of the run, and destroyed at the end of the run. """ ## Should this scanner be on by default? default=False ## This is a list of scanner names which we depend on. Depending ## on a scanner will force it to be enabled whenever we are ## enabled. depends = [] def __init__(self,addr_space): """ Factory constructor. @arg addr_space: An address space object for the address space we are about scan """ self.addr_space = addr_space def prepare(self): """ This is called before the scanner is used. Generally the constructor should be very brief (because it might be called to reset rather than to actually scan). And most work should be done in this method. """ def destroy(self): """ Final destructor called on the factory to finish the scan operation. This is sometimes used to make indexes etc. """ pass class Scan(BaseMemoryScanner): """ The Scan class must be defined as an inner class to the factory. """ class SlidingMemoryScanner(BaseMemoryScanner): """ A scanner designed to scan buffers of data in memory. This scanner implements a sliding window, i.e. each buffer scanned begins with OVERLAP/BUFFERSIZE from the previous buffer. This allows matches that are broken across a block boundary. """ #windowsize=8 def __init__(self, poffset, outer, window_size=8): BaseMemoryScanner.__init__(self, poffset,outer) self.window = '' self.offset=0 self.outer = outer self.window_size = window_size def process(self, data, offset, metadata=None): buf = self.window + data self.as_offset = self.offset self.process_buffer(buf,self.offset,metadata) self.offset += len(buf) self.window = buf[-self.window_size:] self.offset -= len(self.window) def process_buffer(self,buf,offset): """ This abstract method should implement the actual scanner. @arg buf: The chunk of data to be analyzed. @arg offset: The actual offset within the address space. """ def scan_addr_space(addr_space,scan_objects): """ Given an address space and a list of scan_objects, this function scans the address space using the scan_objects @arg addr_space: The address space to scan @arg scan_objects: A list of scan_objects to search for across the address space """ # BUFFSIZE was chosen so that data would be aligned # on 8 bytes. # # CHUNKSIZE was chosen so that we will process # a 4KB page of memory at a time. This has a number of # advantages. One of which being the common page size on # IA32 machines. BUFFSIZE = 1024 * 1024 * 10 CHUNKSIZE = 0x1000 objs = [] for c in scan_objects: objs.append(c.Scan(addr_space, c)) if len(objs)==0: return as_offset = 0 while 1: try: data = addr_space.zread(as_offset,BLOCKSIZE) if not data: break except IOError,e: break poffset = 0 while poffset < BLOCKSIZE: chunk = data[poffset:poffset+CHUNKSIZE] metadata = {} # call process method of each class # First let's check to see if anyone # is even interested interest = 0 for o in objs: if not o.ignore: interest+=1 if not interest: break for o in objs: try: if not o.ignore: interest+=1 o.process(chunk,as_offset+poffset, metadata=metadata) except Exception,e: print "Scanner (%s) on Offset %d Error: %s" %(o,as_offset,e) raise poffset+=CHUNKSIZE # All the CHUNKS of data from this read have been # processed. At this point we call the finish method # before performing the next read. For example, this may # be a time when you would like to batch database operations. for o in objs: try: o.finish() except Exception,e: print "Scanner (%s) on Offset %d Error: %s" %(o,as_offset,e) as_offset+=len(data) class PoolScanner(SlidingMemoryScanner): def __init__(self, poffset, outer): SlidingMemoryScanner.__init__(self, poffset, outer, outer.pool_size) self.data_types = meta_info.DataTypes self.constraints = [] self.climit = None self.matches = [] def format_time(self,time): ts=strftime("%a %b %d %H:%M:%S %Y",gmtime(time)) return ts def set_limit(self,limit): self.climit = limit def get_limit(self): if self.climit == None: return len(self.constraints) elif self.climit > len(self.constraints): return len(self.constraints) else: return self.climit def check_blocksize_geq(self, buff, found): pool_hdr_val = read_obj_from_buf(buff,self.data_types, \ ['_POOL_HEADER', 'Ulong1'],found-4) if pool_hdr_val == None: return False BlockSize = (pool_hdr_val >> 16) & 0x1FF pool_size = BlockSize * 0x8 if pool_size >= self.outer.pool_size: return True return False def check_blocksize_equal(self, buff, found): pool_hdr_val = read_obj_from_buf(buff,self.data_types, \ ['_POOL_HEADER', 'Ulong1'],found-4) if pool_hdr_val == None: return False BlockSize = (pool_hdr_val >> 16) & 0x1FF pool_size = BlockSize * 0x8 if pool_size == self.outer.pool_size: return True return False def check_pooltype(self, buff, found): data_types = meta_info.DataTypes pool_hdr_val = read_obj_from_buf(buff,self.data_types, \ ['_POOL_HEADER', 'Ulong1'],found-4) if pool_hdr_val == None: return False PoolType = (pool_hdr_val >> 16) & 0xFFFF PoolType = (PoolType & 0xFE00) >> 9 if ((PoolType == 0) or ((PoolType % 2) == 1)): return True return False def check_poolindex(self, buff, found): data_types = meta_info.DataTypes pool_hdr_val = read_obj_from_buf(buff,self.data_types, \ ['_POOL_HEADER', 'Ulong1'],found-4) if pool_hdr_val == None: return False PoolIndex = (pool_hdr_val) & 0xFFFF PoolIndex = (PoolIndex & 0xFE00) >> 9 if PoolIndex == 0: return True return False def check_addr(self,buff,found): cnt = 0 for func in self.constraints: val = func(buff,found) if val == True: cnt = cnt+1 return cnt def add_constraint(self,func): self.constraints.append(func) def object_offset(self,found): return (found - 4) + obj_size(self.data_types,'_POOL_HEADER') def object_action(self,buff,found): """ If constraints are met, perform this action. """ pass def process_buffer(self,buff,poffset,metadata=None): found = 0 while 1: found = buff.find(self.outer.pool_tag, found+1) if found > 0: oaddr = self.object_offset(found)+self.as_offset if oaddr in self.matches: continue match_count = self.check_addr(buff,found) if match_count == self.get_limit(): ooffset = self.object_offset(found) self.object_action(buff,ooffset) self.matches.append(oaddr) else: break class PoolScanConnFast2(GenMemScanObject): """ Scan for pool objects """ def __init__(self,addr_space): GenMemScanObject.__init__(self, addr_space) self.pool_tag = "\x54\x43\x50\x54" self.pool_size = 0x198 class Scan(PoolScanner): def __init__(self, poffset, outer): PoolScanner.__init__(self, poffset, outer) self.add_constraint(self.check_blocksize_equal) self.add_constraint(self.check_pooltype) self.add_constraint(self.check_poolindex) def object_action(self,buff,object_offset): """ In this instance, the object action is to print to stdout """ pid = read_obj_from_buf(buff, self.data_types, \ ['_TCPT_OBJECT', 'Pid'], object_offset) lport = ntohs(read_obj_from_buf(buff, self.data_types, \ ['_TCPT_OBJECT', 'LocalPort'], object_offset)) laddr = read_obj_from_buf(buff, self.data_types, \ ['_TCPT_OBJECT', 'LocalIpAddress'], object_offset) laddr = inet_ntoa(struct.pack('=L',laddr)) rport = ntohs(read_obj_from_buf(buff, self.data_types, \ ['_TCPT_OBJECT', 'RemotePort'], object_offset)) raddr = read_obj_from_buf(buff, self.data_types, \ ['_TCPT_OBJECT', 'RemoteIpAddress'], object_offset) raddr = inet_ntoa(struct.pack('=L',raddr)) local = "%s:%d"%(laddr,lport) remote = "%s:%d"%(raddr,rport) print "%-25s %-25s %-6d"%(local,remote,pid) class PoolScanSockFast2(GenMemScanObject): """ Scan for pool objects """ def __init__(self,addr_space): GenMemScanObject.__init__(self, addr_space) self.pool_tag = "\x54\x43\x50\x41" self.pool_size = 0x170 #self.pool_size = 0x158 class Scan(PoolScanner): def __init__(self, poffset, outer): PoolScanner.__init__(self, poffset, outer) self.add_constraint(self.check_blocksize_equal) self.add_constraint(self.check_pooltype) self.add_constraint(self.check_poolindex) self.add_constraint(self.check_socket_create_time) def check_socket_create_time(self, buff, found): soffset = self.object_offset(found) time = read_time_buf(buff,self.data_types,\ ['_ADDRESS_OBJECT', 'CreateTime'],soffset) if time == None: return False if time > 0: return True return False def object_action(self,buff,object_offset): """ In this instance, the object action is to print to stdout """ pid = read_obj_from_buf(buff, self.data_types, \ ['_ADDRESS_OBJECT', 'Pid'], object_offset) proto = read_obj_from_buf(buff, self.data_types, \ ['_ADDRESS_OBJECT', 'Protocol'], object_offset) port = ntohs(read_obj_from_buf(buff, self.data_types, \ ['_ADDRESS_OBJECT', 'LocalPort'], object_offset)) time = read_time_buf(buff,self.data_types,\ ['_ADDRESS_OBJECT', 'CreateTime'],object_offset) ooffset = self.as_offset + object_offset try: print "%-6d %-6d %-6d %-26s 0x%0.8x"%(pid,port,proto, \ self.format_time(time),ooffset) except: return class PoolScanModuleFast2(GenMemScanObject): """ Scan for pool objects """ def __init__(self,addr_space): GenMemScanObject.__init__(self, addr_space) self.pool_tag = "\x4D\x6D\x4C\x64" self.pool_size = 0x4c class Scan(PoolScanner): def __init__(self, poffset, outer): PoolScanner.__init__(self, poffset, outer) self.add_constraint(self.check_blocksize_geq) self.add_constraint(self.check_pooltype) self.add_constraint(self.check_poolindex) def module_pool_imagename(self, buff, mod_offset): addr_space = meta_info.KernelAddressSpace name_buf = read_obj_from_buf(buff, self.data_types, \ ['_LDR_MODULE', 'FullDllName', 'Buffer'], mod_offset) name_buf_len = read_obj_from_buf(buff, self.data_types, \ ['_LDR_MODULE', 'FullDllName', 'Length'], mod_offset) readBuf = read_string(addr_space, self.data_types, ['char'], \ name_buf, name_buf_len) if readBuf is None: imagename = "" try: imagename = readBuf.decode('UTF-16').encode('ascii', 'backslashreplace') except: imagename = "" return imagename def module_pool_modulename(self, buff, mod_offset): addr_space = meta_info.KernelAddressSpace name_buf = read_obj_from_buf(buff, self.data_types, \ ['_LDR_MODULE', 'ModuleName', 'Buffer'], mod_offset) name_buf_len = read_obj_from_buf(buff, self.data_types, \ ['_LDR_MODULE', 'ModuleName', 'Length'], mod_offset) readBuf = read_string(addr_space, self.data_types, ['char'], \ name_buf, name_buf_len) if readBuf is None: modulename = "" try: modulename = readBuf.decode('UTF-16').encode('ascii', 'backslashreplace') except: modulename = "" return modulename def object_action(self,buff,object_offset): """ In this instance, the object action is to print to stdout """ system_addr_space = meta_info.KernelAddressSpace baseaddr = read_obj_from_buf(buff, self.data_types, \ ['_LDR_MODULE', 'BaseAddress'], object_offset) imagesize = read_obj_from_buf(buff, self.data_types, \ ['_LDR_MODULE', 'SizeOfImage'], object_offset) imagename = self.module_pool_imagename(buff, object_offset) modulename = self.module_pool_modulename(buff, object_offset) print "%-50s 0x%010x 0x%06x %s" % \ (imagename, baseaddr, imagesize, modulename) class PoolScanProcessFast2(GenMemScanObject): """ Scan for pool objects """ def __init__(self,addr_space): GenMemScanObject.__init__(self, addr_space) self.pool_tag = "\x50\x72\x6F\xE3" self.pool_size = 0x280 class Scan(PoolScanner): def __init__(self, poffset, outer): PoolScanner.__init__(self, poffset, outer) self.add_constraint(self.check_blocksize_geq) self.add_constraint(self.check_pooltype) self.add_constraint(self.check_poolindex) self.add_constraint(self.check_dtb) self.add_constraint(self.check_dtb_aligned) self.add_constraint(self.check_thread_list) def check_dtb(self, buff, found): poffset = self.object_offset(found) DirectoryTableBase = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'Pcb', 'DirectoryTableBase', 0], poffset) if DirectoryTableBase == 0: return False if DirectoryTableBase == None: return False return True def check_dtb_aligned(self, buff, found): poffset = self.object_offset(found) DirectoryTableBase = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'Pcb', 'DirectoryTableBase', 0], poffset) if DirectoryTableBase == None: return False if (DirectoryTableBase % 0x20) != 0: return False return True def object_offset(self,found): (offset, tmp) = get_obj_offset(self.data_types, ['_OBJECT_HEADER', 'Body']) return (found - 4) + obj_size(self.data_types,'_POOL_HEADER') + offset def check_thread_list(self, buff, found): kernel = 0x80000000 poffset = self.object_offset(found) thread_list_head_flink = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS','ThreadListHead', 'Flink'], poffset) if thread_list_head_flink < kernel: return False thread_list_head_blink = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'ThreadListHead', 'Blink'], poffset) if thread_list_head_blink < kernel: return False return True def object_action(self,buff,object_offset): """ In this instance, the object action is to print to stdout """ UniqueProcessId = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'UniqueProcessId'], object_offset) InheritedFromUniqueProcessId = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'InheritedFromUniqueProcessId'], object_offset) DirectoryTableBase = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'Pcb', 'DirectoryTableBase', 0], object_offset) address = self.as_offset + object_offset (file_name_offset, current_type) = get_obj_offset(self.data_types,\ ['_EPROCESS', 'ImageFileName']) fnoffset = object_offset+file_name_offset string = buff[fnoffset:fnoffset+256] if (string.find('\0') == -1): ImageFileName = string else: (ImageFileName, none) = string.split('\0', 1) create_time = read_time_buf(buff,self.data_types,\ ['_EPROCESS', 'CreateTime'],object_offset) exit_time = read_time_buf(buff,self.data_types,\ ['_EPROCESS', 'ExitTime'],object_offset) if create_time == 0: CreateTime = "" else: CreateTime = self.format_time(create_time) if exit_time == 0: ExitTime = "" else: ExitTime = self.format_time(exit_time) print "%6d %6d %24s %24s 0x%0.8x 0x%0.8x %-16s"% \ (UniqueProcessId,InheritedFromUniqueProcessId,CreateTime,\ ExitTime,address,DirectoryTableBase,ImageFileName) class PoolScanProcessDot(PoolScanProcessFast2): class Scan(PoolScanProcessFast2.Scan): def format_time(self, time): ts=strftime("%H:%M:%S\\n%Y-%m-%d",gmtime(time)) return ts def object_action(self,buff,object_offset): """ In this instance, the object action is to print to stdout """ UniqueProcessId = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'UniqueProcessId'], object_offset) InheritedFromUniqueProcessId = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'InheritedFromUniqueProcessId'], object_offset) ExitStatus = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'ExitStatus'], object_offset) DirectoryTableBase = read_obj_from_buf(buff, self.data_types, \ ['_EPROCESS', 'Pcb', 'DirectoryTableBase', 0], object_offset) address = self.as_offset + object_offset (file_name_offset, current_type) = get_obj_offset(self.data_types,\ ['_EPROCESS', 'ImageFileName']) fnoffset = object_offset+file_name_offset string = buff[fnoffset:fnoffset+256] if (string.find('\0') == -1): ImageFileName = string else: (ImageFileName, none) = string.split('\0', 1) create_time = read_time_buf(buff,self.data_types,\ ['_EPROCESS', 'CreateTime'],object_offset) exit_time = read_time_buf(buff,self.data_types,\ ['_EPROCESS', 'ExitTime'],object_offset) if create_time == 0: CreateTime = "" else: CreateTime = self.format_time(create_time) CreateTime = " | started\\n%s"%CreateTime if exit_time == 0: ExitTime = "" else: ExitTime = self.format_time(exit_time) if not ExitTime == "": print "pid%u [label = \"{%u | file ofs\\n0x%x | %s%s | exited\\n%s\\n code %d}\" shape = \"record\" style = \"filled\" fillcolor = \"lightgray\"];"%(UniqueProcessId,UniqueProcessId,address, ImageFileName,CreateTime, ExitTime,ExitStatus) else: print "pid%u [label = \"{%u | file ofs\\n0x%x | %s%s | running}\" shape = \"record\"];"%(UniqueProcessId,UniqueProcessId,address,ImageFileName,CreateTime) print "pid%u -> pid%u []"%(InheritedFromUniqueProcessId,UniqueProcessId) class PoolScanThreadFast2(GenMemScanObject): """ Scan for pool objects """ def __init__(self,addr_space): GenMemScanObject.__init__(self, addr_space) self.pool_tag = "\x54\x68\x72\xE5" self.pool_size = 0x278 class Scan(PoolScanner): def __init__(self, poffset, outer): PoolScanner.__init__(self, poffset, outer) self.add_constraint(self.check_blocksize_geq) self.add_constraint(self.check_pooltype) self.add_constraint(self.check_poolindex) self.add_constraint(self.check_threads_process) self.add_constraint(self.check_start_address) self.add_constraint(self.check_semaphores) def check_threads_process(self, buff, found): kernel = 0x80000000 toffset = self.object_offset(found) UniqueProcess = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Cid', 'UniqueProcess'], toffset) ThreadsProcess = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'ThreadsProcess'], toffset) if UniqueProcess != 0 and ThreadsProcess < kernel: return False return True def check_start_address(self, buff, found): kernel = 0x80000000 toffset = self.object_offset(found) UniqueProcess = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Cid', 'UniqueProcess'], toffset) StartAddress = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'StartAddress'], toffset) if UniqueProcess != 0 and StartAddress == 0: return False return True def check_semaphores(self, buff, found): toffset = self.object_offset(found) UniqueProcess = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Cid', 'UniqueProcess'], toffset) Type = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Tcb', 'SuspendSemaphore','Header','Type'], toffset) Size = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Tcb', 'SuspendSemaphore','Header','Size'], toffset) if Type == None or Size == None: return False if(Size != 0x5 and Type != 0x5): return False Type = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'LpcReplySemaphore','Header','Type'], toffset) Size = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'LpcReplySemaphore','Header','Size'], toffset) if Type == None or Size == None: return False if((Size != 0x5 and Type != 0x5) and UniqueProcess != 0): return False return True def object_offset(self,found): (offset, tmp) = get_obj_offset(self.data_types, ['_OBJECT_HEADER', 'Body']) return (found - 4) + obj_size(self.data_types,'_POOL_HEADER') + offset def object_action(self,buff,object_offset): """ In this instance, the object action is to print to stdout """ UniqueProcess = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Cid', 'UniqueProcess'], object_offset) UniqueThread = read_obj_from_buf(buff, self.data_types, \ ['_ETHREAD', 'Cid', 'UniqueThread'], object_offset) address = self.as_offset + object_offset print "%6d %6d 0x%0.8x"%(UniqueProcess, UniqueThread, address) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/tasks.py000066400000000000000000000254241217176075400251730ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ from forensics.object import * from forensics.win32.datetime import * #from forensics.win32.info import * from forensics.win32.info import find_psactiveprocesshead import os from struct import unpack from forensics.addrspace import * def process_list(addr_space, types, symbol_table=None): """ Get the virtual addresses of all Windows processes """ plist = [] PsActiveProcessHead = find_psactiveprocesshead(addr_space,types) if not PsActiveProcessHead is None: (offset, tmp) = get_obj_offset(types, ['_EPROCESS', 'ActiveProcessLinks']) first_process = PsActiveProcessHead - offset current = read_obj(addr_space, types, ['_EPROCESS', 'ActiveProcessLinks', 'Flink'], first_process) if current is None: print "Unable to read beginning of process list 0x%x. Try a different DTB?" % (first_process) return plist this_process = current - offset while current != PsActiveProcessHead: Type = read_obj(addr_space, types, ['_EPROCESS', 'Pcb', 'Header','Type'], this_process) if not Type == 0x03: break plist.append(this_process) current = read_obj(addr_space, types, ['_EPROCESS', 'ActiveProcessLinks', 'Flink'], this_process) if current == None: plist.append(this_process) break this_process = current - offset return plist def process_find_pid(addr_space, types, symbol_table, all_tasks, pid): """ Find process offset with this pid in the task list """ match_tasks = [] for task in all_tasks: process_id = process_pid(addr_space, types, task) if process_id == pid: match_tasks.append(task) return match_tasks # Blocksize was chosen to make it aligned # on 8 bytes # Optimized by Michael Cohen BLOCKSIZE = 1024 * 1024 * 10 def find_dtb(addr_space, types): """ Find the Idle dtb (DTB Feeling lucky) """ try: flat_address_space = FileAddressSpace(addr_space.name,fast=True) except: print "Unable to open image file %s" %filename return None offset = 0 while 1: data = flat_address_space.fread(BLOCKSIZE) found = 0 if not data: break while 1: found = data.find("\x03\x00\x1b\x00", found+1) if found >= 0: (type,size) = unpack('=HH',data[found:found+4]) if process_imagename(addr_space,types,offset+found).find('Idle') != -1: return process_dtb(addr_space, types, offset+found) else: break offset+=len(data) return None def process_imagename(addr_space, types, task_vaddr): return read_null_string(addr_space, types, ['_EPROCESS', 'ImageFileName'], task_vaddr) def process_dtb(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'Pcb', 'DirectoryTableBase', 0], task_vaddr) def process_vadroot(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'VadRoot'], task_vaddr) def process_pid(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'UniqueProcessId'], task_vaddr) def process_num_active_threads(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'ActiveThreads'], task_vaddr) def process_exit_status(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'ExitStatus'], task_vaddr) def process_inherited_from(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'InheritedFromUniqueProcessId'], task_vaddr) def process_handle_table(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'ObjectTable'], task_vaddr) def process_handle_count(addr_space, types, task_vaddr): object_table = read_obj(addr_space, types, ['_EPROCESS', 'ObjectTable'], task_vaddr) if object_table is None or not addr_space.is_valid_address(object_table): return None else: handle_count = read_obj(addr_space, types, ['_HANDLE_TABLE', 'HandleCount'], object_table) return handle_count def process_create_time(addr_space, types, task_vaddr): (create_time_offset, tmp) = get_obj_offset(types, ['_EPROCESS', 'CreateTime']) create_time = read_time(addr_space, types, task_vaddr + create_time_offset) if create_time is None: return None create_time = windows_to_unix_time(create_time) return create_time def process_exit_time(addr_space, types, task_vaddr): (exit_time_offset, tmp) = get_obj_offset(types, ['_EPROCESS', 'ExitTime']) exit_time = read_time(addr_space, types, task_vaddr + exit_time_offset) if exit_time is None: return None exit_time = windows_to_unix_time(exit_time) return exit_time def process_addr_space(kaddr_space, types, task_vaddr, fname): directory_table_base = read_obj(kaddr_space, types, ['_EPROCESS', 'Pcb', 'DirectoryTableBase', 0], task_vaddr) try: #process_address_space = type(kaddr_space)(fname, directory_table_base) process_address_space = kaddr_space.__class__(kaddr_space.base, directory_table_base) except: return None return process_address_space def process_peb(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'Peb'], task_vaddr) def process_threadlisthead(addr_space, types, task_vaddr): return read_obj(addr_space, types, ['_EPROCESS', 'ThreadListHead', 'Flink'], task_vaddr) def create_addr_space(kaddr_space, directory_table_base): try: process_address_space = kaddr_space.__class__(kaddr_space.base, directory_table_base) except: return None return process_address_space def process_command_line(process_address_space, types, peb_vaddr): process_parameters = read_obj(process_address_space, types, ['_PEB', 'ProcessParameters'], peb_vaddr) if process_parameters is None: return None return read_unicode_string(process_address_space, types, ['_RTL_USER_PROCESS_PARAMETERS', 'CommandLine'], process_parameters) def peb_number_processors(process_address_space, types, peb_vaddr): return read_obj(process_address_space, types, ['_PEB', 'NumberOfProcessors'], peb_vaddr) def peb_csdversion(process_address_space, types, peb_vaddr): return read_unicode_string(process_address_space, types, ['_PEB', 'CSDVersion'], peb_vaddr) def module_path(process_address_space, types, module_vaddr): return read_unicode_string(process_address_space, types, ['_LDR_MODULE', 'FullDllName'], module_vaddr) def module_size(process_address_space, types, module_vaddr): return read_obj(process_address_space, types, ['_LDR_MODULE', 'SizeOfImage'], module_vaddr) def module_base(process_address_space, types, module_vaddr): return read_obj(process_address_space, types, ['_LDR_MODULE', 'BaseAddress'], module_vaddr) def process_ldrs(process_address_space, types, peb_vaddr): ldr = read_obj(process_address_space, types, ['_PEB', 'Ldr'], peb_vaddr) module_list = [] if ldr is None: print "Unable to read ldr for peb 0x%x" % (peb_vaddr) return module_list first_module = read_obj(process_address_space, types, ['_PEB_LDR_DATA', 'InLoadOrderModuleList', 'Flink'], ldr) if first_module is None: print "Unable to read first module for ldr 0x%x" % (ldr) return module_list this_module = first_module next_module = read_obj(process_address_space, types, ['_LDR_MODULE', 'InLoadOrderModuleList', 'Flink'], this_module) if next_module is None: print "ModuleList Truncated, unable to read module at 0x%x\n" % (this_module) return module_list while next_module != first_module: module_list.append(this_module) if not process_address_space.is_valid_address(next_module): print "ModuleList Truncated, unable to read module at 0x%x\n" % (next_module) return module_list prev_module = this_module this_module = next_module next_module = read_obj(process_address_space, types, ['_LDR_MODULE', 'InLoadOrderModuleList', 'Flink'], this_module) return module_list def find_csdversion(addr_space, types): CSDVersionDict = dict() all_tasks = process_list(addr_space, types) for task in all_tasks: if not addr_space.is_valid_address(task): continue process_address_space = process_addr_space(addr_space, types, task, addr_space.base.fname) if process_address_space is None: continue peb = process_peb(addr_space, types, task) try: if not process_address_space.is_valid_address(peb): continue except: continue CSDVersion = peb_csdversion(process_address_space, types, peb) if CSDVersion in CSDVersionDict: CSDVersionDict[CSDVersion] +=1 else: CSDVersionDict[CSDVersion] = 1 MaxCSDVersion = max([ (CSDVersionDict[x],x) for x in CSDVersionDict])[1] return MaxCSDVersion dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/vad.py000066400000000000000000000413141217176075400246140ustar00rootroot00000000000000# Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # The source code in this file was inspired by the excellent work of # Brendan Dolan-Gavitt. Background information can be found in # the following reference: # "The VAD Tree: A Process-Eye View of Physical Memory," Brendan Dolan-Gavitt from forensics.win32.handles import * from forensics.win32.info import * from forensics.object import * import os vad_flags = { \ '_MMVAD_FLAGS' : { \ 'CommitCharge' : [0x0, 0x13], \ 'PhysicalMapping' : [0x13, 0x1], \ 'ImageMap' : [0x14, 0x1], \ 'UserPhysicalPages' : [0x15, 0x1], \ 'NoChange' : [0x16, 0x1], \ 'WriteWatch' : [0x17, 0x1], \ 'Protection' : [0x18, 0x5], \ 'LargePages' : [0x1D, 0x1], \ 'MemCommit' : [0x1E, 0x1], \ 'PrivateMemory' : [0x1F, 0x1], \ }, '_MMVAD_FLAGS2' : { \ 'FileOffset' : [0x0, 0x18], \ 'SecNoChange' : [0x18, 0x1], \ 'OneSecured' : [0x19, 0x1], \ 'MultipleSecured' : [0x1a, 0x1], \ 'ReadOnly' : [0x1b, 0x1], \ 'LongVad' : [0x1c, 0x1], \ 'ExtendableFile' : [0x1d, 0x1], \ 'Inherit' : [0x1e, 0x1], \ 'CopyOnWrite' : [0x1f, 0x1], \ }, '_MMSECTION_FLAGS' : { \ 'BeingDeleted' : [0x0, 0x1], \ 'BeingCreated' : [0x1, 0x1], \ 'BeingPurged' : [0x2, 0x1], \ 'NoModifiedWriting' : [ 0x3, 0x1], \ 'FailAllIo' : [0x4, 0x1], \ 'Image' : [0x5, 0x1], \ 'Based' : [0x6, 0x1], \ 'File' : [0x7, 0x1], \ 'Networked' : [0x8, 0x1], \ 'NoCache' : [0x9, 0x1], \ 'PhysicalMemory' : [0xa, 0x1], \ 'CopyOnWrite' : [0xb, 0x1], \ 'Reserve' : [0xc, 0x1], \ 'Commit' : [0xd, 0x1], \ 'FloppyMedia' : [0xe, 0x1], \ 'WasPurged' : [0xf, 0x1], \ 'UserReference' : [0x10, 0x1], \ 'GlobalMemory' : [0x11, 0x1], \ 'DeleteOnClose' : [0x12, 0x1], \ 'FilePointerNull' : [0x13, 0x1], \ 'DebugSymbolsLoaded' : [0x14, 0x1], \ 'SetMappedFileIoComplete' : [0x15, 0x1], \ 'CollidedFlush' : [0x16, 0x1], \ 'NoChange' : [0x17, 0x1], \ 'HadUserReference' : [0x18, 0x1], \ 'ImageMappedInSystemSpace' : [0x19, 0x1], \ 'UserWritable' : [0x1a, 0x1], \ 'Accessed' : [0x1b, 0x1], \ 'GlobalOnlyPerSession' : [0x1c, 0x1], \ 'Rom' : [0x1d, 0x1], \ 'filler' : [0x1e, 0x2], \ } } def get_mask_flag(flags, member): if not vad_flags.has_key(flags): raise Exception('Invalid flags ' + flags) flag_dict = vad_flags[flags] v = flag_dict[member] bits = 2**v[1] - 1 mask = bits << v[0] return mask def get_bit_flags(value, flags): matches = [] if not vad_flags.has_key(flags): raise Exception('Invalid flags ' + flags) bit_dict = vad_flags[flags] for (k,v) in bit_dict.items(): if ((v[1] == 0x1) and ((( 1 << (v[0])) & value) > 0)): matches.append(k) return matches def traverse_vad(parent, addr_space, types, vad_addr, prefix_callback, infix_callback, postfix_callback, level=0, storage = None): if not addr_space.is_valid_address(vad_addr): return Parent = read_obj(addr_space, types, ['_MMVAD_SHORT', 'Parent'], vad_addr) if not parent == None: if not Parent == parent: return LeftChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'LeftChild'], vad_addr) RightChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'RightChild'], vad_addr) if prefix_callback != None: prefix_callback(addr_space, types, vad_addr, level, storage) if LeftChild > 0: traverse_vad(vad_addr, addr_space, types, LeftChild, prefix_callback, infix_callback, postfix_callback, level+1,storage) if infix_callback != None: infix_callback(addr_space, types, vad_addr, level, storage) if RightChild > 0: traverse_vad(vad_addr, addr_space, types, RightChild, prefix_callback, infix_callback, postfix_callback, level+1,storage) if postfix_callback != None: postfix_callback(addr_space, types, vad_addr, level,storage) def parse_vad(parent, addr_space, types, vad_addr, vadlist, level=0): if not addr_space.is_valid_address(vad_addr): return LeftChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'LeftChild'], vad_addr) RightChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'RightChild'], vad_addr) vadlist.append(vad_addr) if LeftChild > 0: parse_vad(vad_addr, addr_space, types, LeftChild, vadlist, level+1) if RightChild > 0: parse_vad(vad_addr, addr_space, types, RightChild, vadlist, level+1) def controlarea_filepointer(addr_space, types, ControlArea): return read_obj(addr_space, types, ['_CONTROL_AREA', 'FilePointer'], ControlArea) def print_vad_short(addr_space, types, vad_entry): tag_addr = vad_entry - 0x4 if not addr_space.is_valid_address(tag_addr): print "Not Valid" tag = addr_space.read(tag_addr,4) StartingVpn = read_obj(addr_space, types, ['_MMVAD_LONG', 'StartingVpn'], vad_entry) StartingVpn = StartingVpn << 12 EndingVpn = read_obj(addr_space, types, ['_MMVAD_LONG', 'EndingVpn'], vad_entry) EndingVpn = ((EndingVpn+1) << 12) - 1 print "VAD node @%08x Start %08x End %08x Tag %4s"%(vad_entry,StartingVpn,EndingVpn,tag) (u_offset, tmp) = get_obj_offset(types, ['_MMVAD_LONG', 'u']) Flags = read_value(addr_space, 'unsigned long', u_offset+vad_entry) flags = "Flags: " + ", ".join(get_bit_flags(Flags,'_MMVAD_FLAGS')) print flags print "Commit Charge: %d Protection: %x" % (Flags & get_mask_flag('_MMVAD_FLAGS', 'CommitCharge'),(Flags & get_mask_flag('_MMVAD_FLAGS', 'Protection')) >> 24) def print_vad_control(addr_space, types, vad_entry): ControlArea = read_obj(addr_space, types, ['_MMVAD_LONG', 'ControlArea'], vad_entry) ControlAreaObject = addr_space.read(ControlArea,obj_size(types,'_CONTROL_AREA')) if addr_space.is_valid_address(ControlArea) and ControlAreaObject != None: Segment = read_obj(addr_space, types, ['_CONTROL_AREA', 'Segment'], ControlArea) print "ControlArea @%08x Segment %08x" % (ControlArea, Segment) Flink = read_obj(addr_space, types, ['_CONTROL_AREA', 'DereferenceList', 'Flink'],ControlArea) Blink = read_obj(addr_space, types, ['_CONTROL_AREA', 'DereferenceList', 'Blink'],ControlArea) print "Dereference list: Flink %08x, Blink %08x"%(Flink,Blink) NumberOfSectionReferences = read_obj(addr_space, types, ['_CONTROL_AREA', 'NumberOfSectionReferences'], ControlArea) NumberOfPfnReferences = read_obj(addr_space, types, ['_CONTROL_AREA', 'NumberOfPfnReferences'], ControlArea) print "NumberOfSectionReferences: %10d NumberOfPfnReferences: %10d"%(NumberOfSectionReferences,NumberOfPfnReferences) NumberOfMappedViews = read_obj(addr_space, types, ['_CONTROL_AREA', 'NumberOfMappedViews'], ControlArea) NumberOfSubsections = read_obj(addr_space, types, ['_CONTROL_AREA', 'NumberOfSubsections'], ControlArea) print "NumberOfMappedViews: %10d NumberOfSubsections: %10d" % (NumberOfMappedViews,NumberOfSubsections) FlushInProgressCount = read_obj(addr_space, types, ['_CONTROL_AREA', 'FlushInProgressCount'], ControlArea) NumberOfUserReferences = read_obj(addr_space, types, ['_CONTROL_AREA', 'NumberOfUserReferences'], ControlArea) print "FlushInProgressCount: %10d NumberOfUserReferences: %10d"%(FlushInProgressCount,NumberOfUserReferences) (u_offset, tmp) = get_obj_offset(types, ['_CONTROL_AREA', 'u']) Flags = read_value(addr_space, 'unsigned long', u_offset+ControlArea) flags = "Flags: " + ", ".join(get_bit_flags(Flags,'_MMSECTION_FLAGS')) print flags FilePointer = controlarea_filepointer(addr_space, types, ControlArea) if FilePointer != None and addr_space.is_valid_address(FilePointer) and FilePointer != 0x0: filename = file_name(addr_space, types, FilePointer) pFilePointer = addr_space.vtop(FilePointer) print "FileObject @%08x (%08x), Name: %s" % (FilePointer, pFilePointer, filename) else: print "FileObject: none" WaitingForDeletion = read_obj(addr_space, types, ['_CONTROL_AREA', 'WaitingForDeletion'], ControlArea) ModifiedWriteCount = read_obj(addr_space, types, ['_CONTROL_AREA', 'ModifiedWriteCount'], ControlArea) NumberOfSystemCacheViews = read_obj(addr_space, types, ['_CONTROL_AREA', 'NumberOfSystemCacheViews'], ControlArea) print "WaitingForDeletion Event: %08x"%WaitingForDeletion print "ModifiedWriteCount: %8d NumberOfSystemCacheViews: %8d"%(ModifiedWriteCount,NumberOfSystemCacheViews) def print_vad_ext(addr_space, types, vad_entry): FirstPrototypePte = read_obj(addr_space, types, ['_MMVAD_LONG', 'FirstPrototypePte'], vad_entry) LastContiguousPte = read_obj(addr_space, types, ['_MMVAD_LONG', 'LastContiguousPte'], vad_entry) print "First prototype PTE: %08x Last contiguous PTE: %08x"%(FirstPrototypePte,LastContiguousPte) (u2_offset, tmp) = get_obj_offset(types, ['_MMVAD_LONG', 'u2']) Flags = read_value(addr_space, 'unsigned long', u2_offset+vad_entry) flags = "Flags2: " + ", ".join(get_bit_flags(Flags,'_MMVAD_FLAGS2')) print flags print "File offset: %08x" % (Flags & get_mask_flag('_MMVAD_FLAGS2','FileOffset')) if (Flags and Flags & get_mask_flag('_MMVAD_FLAGS2','LongVad')): (u3_offset, tmp) = get_obj_offset(types, ['_MMVAD_LONG', 'u3']) StartVpn = read_value(addr_space, 'unsigned long', u3_offset+vad_entry) EndVpn = read_value(addr_space, 'unsigned long', u3_offset+4+vad_entry) (u4_offset, tmp) = get_obj_offset(types, ['_MMVAD_LONG', 'u4']) ExtendedInfo = read_value(addr_space, 'unsigned long', u4_offset+vad_entry) print "Secured: %08x - %08x" %(StartVpn,EndVpn) print "Pointer to _MMEXTEND_INFO (or _MMBANKED_SECTION ?): %08x"%ExtendedInfo def append_entry(addr_space, types, vad_addr, level, storage): storage.append(vad_addr) def vad_info(addr_space, types, VadRoot): vadlist = [] traverse_vad(None, addr_space, types, VadRoot, append_entry, None, None, 0, vadlist) # Use the tag to determine what data type for vad_entry in vadlist: tag_addr = vad_entry - 0x4 if not addr_space.is_valid_address(tag_addr): print "Not Valid" tag = addr_space.read(tag_addr,4) # Let's classify the VADS if tag == "Vadl": print_vad_short(addr_space, types, vad_entry) ControlArea = read_obj(addr_space, types, ['_MMVAD_LONG', 'ControlArea'], vad_entry) if addr_space.is_valid_address(ControlArea): print_vad_control(addr_space, types, vad_entry) print_vad_ext(addr_space, types, vad_entry) print elif tag == "VadS": print_vad_short(addr_space, types, vad_entry) print elif tag == "Vad ": print_vad_short(addr_space, types, vad_entry) ControlArea = read_obj(addr_space, types, ['_MMVAD_LONG', 'ControlArea'], vad_entry) if addr_space.is_valid_address(ControlArea): print_vad_control(addr_space, types, vad_entry) print_vad_ext(addr_space,types, vad_entry) print else: print "ERROR: Unknown tag" def vad_dump(addr_space, types, VadRoot, name, offset, dir): vadlist = [] if not dir == None: if not os.path.exists(dir): os.mkdir(dir) traverse_vad(None, addr_space, types, VadRoot, append_entry, None, None, 0, vadlist) for vad_entry in vadlist: if not addr_space.is_valid_address(vad_entry): continue range_data = "" StartingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'StartingVpn'], vad_entry) if StartingVpn == None: continue StartingVpn = StartingVpn << 12 EndingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'EndingVpn'], vad_entry) if EndingVpn == None: continue if StartingVpn > 0xFFFFFFFF or EndingVpn > 0xFFFFFFFF: continue EndingVpn = ((EndingVpn+1) << 12) - 1 Range = EndingVpn - StartingVpn + 1 NumberOfPages = Range >> 12 for i in range(0,NumberOfPages): page_addr = StartingVpn+i*0x1000 if not addr_space.is_valid_address(page_addr): range_data + ('\0' * 0x1000) continue page_read = addr_space.read(page_addr, 0x1000) if page_read == None: range_data = range_data + ('\0' * 0x1000) else: range_data = range_data + page_read if not dir == None: f = open(dir+"/"+"%s.%x.%08x-%08x.dmp" % (name,offset,StartingVpn,EndingVpn), 'wb') else: f = open("%s.%x.%08x-%08x.dmp" % (name,offset,StartingVpn,EndingVpn), 'wb') f.write(range_data) f.close() def print_vad_table(addr_space, types, vad_addr,level, storage): tag_addr = vad_addr - 0x4 if not addr_space.is_valid_address(tag_addr): return tag = addr_space.read(tag_addr,4) EndingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'EndingVpn'], vad_addr) EndingVpn = ((EndingVpn+1) << 12) - 1 StartingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'StartingVpn'], vad_addr) StartingVpn = StartingVpn << 12 LeftChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'LeftChild'], vad_addr) RightChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'RightChild'], vad_addr) Parent = read_obj(addr_space, types, ['_MMVAD_SHORT', 'Parent'], vad_addr) print "%08x %08x %08x %08x %08x %08x %-4s"%(vad_addr, Parent, LeftChild, RightChild, StartingVpn, EndingVpn,tag) def print_vad_dot_prefix(addr_space, types, vad_addr, level, storage): tag_addr = vad_addr - 0x4 if not addr_space.is_valid_address(tag_addr): return tag = addr_space.read(tag_addr,4) EndingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'EndingVpn'], vad_addr) EndingVpn = ((EndingVpn+1) << 12) - 1 StartingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'StartingVpn'], vad_addr) StartingVpn = StartingVpn << 12 LeftChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'LeftChild'], vad_addr) RightChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'RightChild'], vad_addr) Parent = read_obj(addr_space, types, ['_MMVAD_SHORT', 'Parent'], vad_addr) print 'vad_%x [label = "{ %08x - %08x }" shape = "record" color = "blue"];'%(vad_addr, StartingVpn, EndingVpn) if LeftChild > 0: print "vad_%x -> vad_%x"%(vad_addr, LeftChild) def print_vad_dot_infix(addr_space, types, vad_addr, level, storage): RightChild = read_obj(addr_space, types, ['_MMVAD_SHORT', 'RightChild'], vad_addr) if RightChild > 0: print "vad_%x -> vad_%x"%(vad_addr, RightChild) def print_vad_tree(addr_space, types, vad_addr, level, storage): EndingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'EndingVpn'], vad_addr) EndingVpn = ((EndingVpn+1) << 12) - 1 StartingVpn = read_obj(addr_space, types, ['_MMVAD_SHORT', 'StartingVpn'], vad_addr) StartingVpn = StartingVpn << 12 print " "*level +"%08x - %08x"%(StartingVpn,EndingVpn) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/forensics/win32/xpress.py000066400000000000000000000122761217176075400253730ustar00rootroot00000000000000# Volatility # Copyright (c) 2008 Volatile Systems # Copyright (c) 2008 Brendan Dolan-Gavitt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # The source code in this file was inspired by the work of Matthieu Suiche, # http://sandman.msuiche.net/, and the information presented released as # part of the Microsoft Interoperability Initiative: # http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-DRSR%5D.pdf # A special thanks to Matthieu for all his help! """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: bdolangavitt@wesleyan.edu """ #!/usr/bin/env python from struct import unpack from struct import error as StructError def recombine(outbuf): return "".join(outbuf[k] for k in sorted(outbuf.keys())) def xpress_decode(inputBuffer): outputBuffer = {} outputIndex = 0 inputIndex = 0 indicatorBit = 0 nibbleIndex = 0 # we are decoding the entire input here, so I have changed # the check to see if we're at the end of the output buffer # with a check to see if we still have any input left. while inputIndex < len(inputBuffer): if (indicatorBit == 0): # in pseudocode this was indicatorBit = ..., but that makes no # sense, so I think this was intended... try: indicator = unpack("> pgdir_shift) & (ptrs_per_pgd - 1) def get_pgd(self, vaddr): pgd_entry = self.pgd_vaddr + self.pgd_index(vaddr) * pointer_size return self.read_long_phys(pgd_entry) def pte_pfn(self, pte): return pte >> page_shift def pte_index(self, pte): return (pte >> page_shift) & (ptrs_per_pte - 1) def get_pte(self, vaddr, pgd): pgd_val = pgd & ~((1 << page_shift) - 1) pgd_val = pgd_val + self.pte_index(vaddr) * pointer_size return self.read_long_phys(pgd_val) def get_paddr(self, vaddr, pte): return (self.pte_pfn(pte) << page_shift) | (vaddr & ((1 << page_shift) - 1)) def get_four_meg_paddr(self, vaddr, pgd_entry): return (pgd_entry & ((ptrs_per_pgd-1) << 22)) | (vaddr & ~((ptrs_per_pgd-1) << 22)) def vtop(self, vaddr): retVal = None pgd = self.get_pgd(vaddr) if self.entry_present(pgd): if self.page_size_flag(pgd): retVal = self.get_four_meg_paddr(vaddr, pgd) else: pte = self.get_pte(vaddr, pgd) if not pte: return None if self.entry_present(pte): retVal = self.get_paddr(vaddr, pte) return retVal def read(self, vaddr, length): first_block = 0x1000 - vaddr % 0x1000 full_blocks = ((length + (vaddr % 0x1000)) / 0x1000) - 1 left_over = (length + vaddr) % 0x1000 paddr = self.vtop(vaddr) if paddr == None: return None if length < first_block: stuff_read = self.base.read(paddr, length) if stuff_read == None: return None return stuff_read stuff_read = self.base.read(paddr, first_block) if stuff_read == None: return None new_vaddr = vaddr + first_block for i in range(0,full_blocks): paddr = self.vtop(new_vaddr) if paddr == None: return None new_stuff = self.base.read(paddr, 0x1000) if new_stuff == None: return None stuff_read = stuff_read + new_stuff new_vaddr = new_vaddr + 0x1000 if left_over > 0: paddr = self.vtop(new_vaddr) if paddr == None: return None new_stuff = self.base.read(paddr, left_over) if new_stuff == None: return None stuff_read = stuff_read + new_stuff return stuff_read def zread(self, vaddr, length): first_block = 0x1000 - vaddr % 0x1000 full_blocks = ((length + (vaddr % 0x1000)) / 0x1000) - 1 left_over = (length + vaddr) % 0x1000 paddr = self.vtop(vaddr) if paddr == None: if length < first_block: return ('\0' * length) stuff_read = ('\0' * first_block) else: if length < first_block: return self.base.zread(paddr, length) stuff_read = self.base.zread(paddr, first_block) new_vaddr = vaddr + first_block for i in range(0,full_blocks): paddr = self.vtop(new_vaddr) if paddr == None: stuff_read = stuff_read + ('\0' * 0x1000) else: stuff_read = stuff_read + self.base.zread(paddr, 0x1000) new_vaddr = new_vaddr + 0x1000 if left_over > 0: paddr = self.vtop(new_vaddr) if paddr == None: stuff_read = stuff_read + ('\0' * left_over) else: stuff_read = stuff_read + self.base.zread(paddr, left_over) return stuff_read def read_long_phys(self, addr): string = self.base.read(addr, 4) if not string: return None (longval, ) = struct.unpack('=L', string) return longval def is_valid_address(self, addr): if addr == None: return False try: phyaddr = self.vtop(addr) except: return False if phyaddr == None: return False if not self.base.is_valid_address(phyaddr): return False return True def get_available_pages(self): page_list = [] pgd_curr = self.pgd_vaddr for i in range(0,ptrs_per_pgd): start = (i * ptrs_per_pgd * ptrs_per_pte * 4) entry = self.read_long_phys(pgd_curr) pgd_curr = pgd_curr + 4 if self.entry_present(entry) and self.page_size_flag(entry): page_list.append([start, 0x400000]) elif self.entry_present(entry): pte_curr = entry & ~((1 << page_shift)-1) for j in range(0,ptrs_per_pte): pte_entry = self.read_long_phys(pte_curr) pte_curr = pte_curr + 4 if self.entry_present(pte_entry): page_list.append([start + j * 0x1000, 0x1000]) return page_list class IA32PagedMemoryPae: def __init__(self, baseAddressSpace, pdbr): self.base = baseAddressSpace self.pgd_vaddr = pdbr self.pae = True def entry_present(self, entry): if (entry & (0x00000001)) == 0x00000001: return True return False def page_size_flag(self, entry): if (entry & (1 << 7)) == (1 << 7): return True return False def get_pdptb(self, pdpr): return pdpr & 0xFFFFFFE0 def pgd_index(self, pgd): return (pgd >> pgdir_shift) & (ptrs_per_pgd - 1) def pdpi_index(self, pdpi): return (pdpi >> pdpi_shift) def get_pdpi(self, vaddr): pdpi_entry = self.get_pdptb(self.pgd_vaddr) + self.pdpi_index(vaddr) * entry_size return self.read_long_long_phys(pdpi_entry) def pde_index(self, vaddr): return (vaddr >> pde_shift) & (ptrs_per_pde - 1) def pdba_base(self, pdpe): return pdpe & 0xFFFFFF000 def get_pgd(self, vaddr, pdpe): pgd_entry = self.pdba_base(pdpe) + self.pde_index(vaddr) * entry_size return self.read_long_long_phys(pgd_entry) def pte_pfn(self, pte): return pte & 0xFFFFFF000 def pte_index(self, vaddr): return (vaddr >> page_shift) & (ptrs_per_pde - 1) def ptba_base(self, pde): return pde & 0xFFFFFF000 def get_pte(self, vaddr, pgd): pgd_val = self.ptba_base(pgd) + self.pte_index(vaddr) * entry_size return self.read_long_long_phys(pgd_val) def get_paddr(self, vaddr, pte): return self.pte_pfn(pte) | (vaddr & ((1 << page_shift) - 1)) def get_large_paddr(self, vaddr, pgd_entry): return (pgd_entry & 0xFFE00000) | (vaddr & ~((ptrs_page-1) << 21)) def vtop(self, vaddr): retVal = None pdpe = self.get_pdpi(vaddr) if not self.entry_present(pdpe): return retVal pgd = self.get_pgd(vaddr,pdpe) if self.entry_present(pgd): if self.page_size_flag(pgd): retVal = self.get_large_paddr(vaddr, pgd) else: pte = self.get_pte(vaddr, pgd) if self.entry_present(pte): retVal = self.get_paddr(vaddr, pte) return retVal def read(self, vaddr, length): first_block = 0x1000 - vaddr % 0x1000 full_blocks = ((length + (vaddr % 0x1000)) / 0x1000) - 1 left_over = (length + vaddr) % 0x1000 paddr = self.vtop(vaddr) if paddr == None: return None if length < first_block: stuff_read = self.base.read(paddr, length) if stuff_read == None: return None return stuff_read stuff_read = self.base.read(paddr, first_block) if stuff_read == None: return None new_vaddr = vaddr + first_block for i in range(0,full_blocks): paddr = self.vtop(new_vaddr) if paddr == None: return None new_stuff = self.base.read(paddr, 0x1000) if new_stuff == None: return None stuff_read = stuff_read + new_stuff new_vaddr = new_vaddr + 0x1000 if left_over > 0: paddr = self.vtop(new_vaddr) if paddr == None: return None new_stuff = self.base.read(paddr, left_over) if new_stuff == None: return None stuff_read = stuff_read + new_stuff return stuff_read def zread(self, vaddr, length): first_block = 0x1000 - vaddr % 0x1000 full_blocks = ((length + (vaddr % 0x1000)) / 0x1000) - 1 left_over = (length + vaddr) % 0x1000 paddr = self.vtop(vaddr) if paddr == None: if length < first_block: return ('\0' * length) stuff_read = ('\0' * first_block) else: if length < first_block: return self.base.zread(paddr, length) stuff_read = self.base.zread(paddr, first_block) new_vaddr = vaddr + first_block for i in range(0,full_blocks): paddr = self.vtop(new_vaddr) if paddr == None: stuff_read = stuff_read + ('\0' * 0x1000) else: stuff_read = stuff_read + self.base.zread(paddr, 0x1000) new_vaddr = new_vaddr + 0x1000 if left_over > 0: paddr = self.vtop(new_vaddr) if paddr == None: stuff_read = stuff_read + ('\0' * left_over) else: stuff_read = stuff_read + self.base.zread(paddr, left_over) return stuff_read def read_long_phys(self, addr): string = self.base.read(addr, 4) if string == None: return None (longval, ) = struct.unpack('=L', string) return longval def read_long_long_phys(self, addr): string = self.base.read(addr,8) if string == None: return None (longlongval, ) = struct.unpack('=Q', string) return longlongval def is_valid_address(self, addr): if addr == None: return False try: phyaddr = self.vtop(addr) except: return False if phyaddr == None: return False if not self.base.is_valid_address(phyaddr): return False return True def get_available_pages(self): page_list = [] pdpi_base = self.get_pdptb(self.pgd_vaddr) for i in range(0,ptrs_per_pdpi): start = (i * ptrs_per_pae_pgd * ptrs_per_pae_pgd * ptrs_per_pae_pte * 8) pdpi_entry = pdpi_base + i * entry_size pdpe = self.read_long_long_phys(pdpi_entry) if not self.entry_present(pdpe): continue pgd_curr = self.pdba_base(pdpe) for j in range(0,ptrs_per_pae_pgd): soffset = start + (j * ptrs_per_pae_pgd * ptrs_per_pae_pte * 8) entry = self.read_long_long_phys(pgd_curr) pgd_curr = pgd_curr + 8 if self.entry_present(entry) and self.page_size_flag(entry): page_list.append([soffset, 0x200000]) elif self.entry_present(entry): pte_curr = entry & ~((1 << page_shift)-1) for k in range(0,ptrs_per_pae_pte): pte_entry = self.read_long_long_phys(pte_curr) pte_curr = pte_curr + 8 if self.entry_present(pte_entry): page_list.append([soffset + k * 0x1000, 0x1000]) return page_list dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_objects/000077500000000000000000000000001217176075400235515ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_objects/CMakeLists.txt000066400000000000000000000011451217176075400263120ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin add_subdirectory(Windows) install_file( __init__.py ) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_objects/Windows/000077500000000000000000000000001217176075400252035ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_objects/Windows/CMakeLists.txt000066400000000000000000000011101217176075400277340ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( xp_sp2.py ) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_objects/Windows/xp_sp2.py000066400000000000000000000032001217176075400267630ustar00rootroot00000000000000# Volatility # Copyright (c) 2008 Volatile Systems # Copyright (c) 2008 Brendan Dolan-Gavitt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: bdolangavitt@wesleyan.edu """ from forensics.object2 import Object from forensics.object import * from vtypes import xpsp2types as types class _UNICODE_STRING(Object): """Class representing a _UNICODE_STRING Adds the following behavior: * The Buffer attribute is presented as a Python string rather than a pointer to an unsigned short. * The __str__ method returns the value of the Buffer. """ def __new__(typ, *args, **kwargs): obj = object.__new__(typ) return obj def __str__(self): return self.Buffer # Custom Attributes def getBuffer(self): return read_unicode_string(self.vm, types, [], self.offset) Buffer = property(fget=getBuffer) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_objects/__init__.py000066400000000000000000000007671217176075400256740ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_plugins/000077500000000000000000000000001217176075400236015ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_plugins/CMakeLists.txt000066400000000000000000000010621217176075400263400ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( example1.py example2.py example3.py ) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_plugins/example1.py000066400000000000000000000103731217176075400256730ustar00rootroot00000000000000# Volatility # Copyright (C) 2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ from vutils import * from forensics.win32.tasks import * class pslist_ex_1(forensics.commands.command): # Declare meta information associated with this plugin meta_info = forensics.commands.command.meta_info meta_info['author'] = 'AAron Walters' meta_info['copyright'] = 'Copyright (c) 2007,2008 AAron Walters' meta_info['contact'] = 'awalters@volatilesystems.com' meta_info['license'] = 'GNU General Public License 2.0 or later' meta_info['url'] = 'https://www.volatilesystems.com/default/volatility' meta_info['os'] = 'WIN_32_XP_SP2' meta_info['version'] = '1.0' # This module makes use of the standard parser. Thus it is not # necessary to override the forensics.commands.command.parse() method. # The standard parser provides the following command line options: # '-f', '--file', '(required) Image file' # '-b', '--base', '(optional) Physical offset (in hex) of DTB' # '-t', '--type', '(optional) Identify the image type' # We need to override the forensics.commands.command.help() method to # change the user help message. This function returns a string that # will be displayed when a user lists available plugins. def help(self): return "Print list running processes" # Finally we override the forensics.commands.command.execute() method # which provides the plugins core functionality. Command line options # are accessed as attributes of self.opts. For example, the options # provided by the standard parse would would provide the following # attributes: self.opts.filename, self.opts.base, self.opts.type. def execute(self): (addr_space, symtab, types) = load_and_identify_image(self.op, self.opts) all_tasks = process_list(addr_space,types,symtab) print "%-20s %-6s %-6s %-6s %-6s %-6s"%('Name','Pid','PPid','Thds','Hnds','Time') for task in all_tasks: if not addr_space.is_valid_address(task): continue image_file_name = process_imagename(addr_space, types, task) if image_file_name is None: image_file_name = "UNKNOWN" process_id = process_pid(addr_space, types, task) if process_id is None: process_id = -1 active_threads = process_num_active_threads(addr_space, types, task) if active_threads is None: active_threads = -1 inherited_from = process_inherited_from(addr_space, types,task) if inherited_from is None: inherited_from = -1 handle_count = process_handle_count(addr_space, types, task) if handle_count is None: handle_count = -1 create_time = process_create_time(addr_space, types, task) if create_time is None: create_time = "UNKNOWN" else: create_time=strftime("%a %b %d %H:%M:%S %Y",gmtime(create_time)) print "%-20s %-6d %-6d %-6d %-6d %-26s" % (image_file_name, process_id, inherited_from, active_threads, handle_count, create_time) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_plugins/example2.py000066400000000000000000000240521217176075400256730ustar00rootroot00000000000000# Volatility # Copyright (C) 2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ from vutils import * from forensics.win32.tasks import * class memmap_ex_2(forensics.commands.command): # Declare meta information associated with this plugin meta_info = forensics.commands.command.meta_info meta_info['author'] = 'AAron Walters' meta_info['copyright'] = 'Copyright (c) 2007,2008 AAron Walters' meta_info['contact'] = 'awalters@volatilesystems.com' meta_info['license'] = 'GNU General Public License 2.0 or later' meta_info['url'] = 'https://www.volatilesystems.com/default/volatility' meta_info['os'] = 'WIN_32_XP_SP2' meta_info['version'] = '1.0' # This module extends the standard parser. This is accomplished by # overriding the forensics.commands.command.parse() method. The # overriding method begins by calling the base class method directly # then it further populates the OptionParser instance with two # new options. def parser(self): forensics.commands.command.parser(self) self.op.add_option('-o', '--offset', help='EPROCESS Offset (in hex)', action='store', type='string', dest='offset') self.op.add_option('-p', '--pid', help='Dump the address space for this Pid', action='store', type='int', dest='pid') # We need to override the forensics.commands.command.help() method to # change the user help message. This function returns a string that # will be displayed when a user lists available plugins. def help(self): return "Print the memory map" # Finally we override the forensics.commands.command.execute() method # which provides the plugins core functionality. Command line options # are accessed as attributes of self.opts. For example, the options # provided by the standard parse would would provide the following # attributes: self.opts.filename, self.opts.base, self.opts.type. def execute(self): op = self.op opts = self.opts if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return addr_space = process_address_space else: if opts.pid == None: op.error("Please specify pid or offset: memmap -p -o ") all_tasks = process_list(addr_space, types, symtab) task = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(task) == 0: print "Error process [%d] not found"%opts.pid return if len(task) > 1: print "Multiple processes [%d] found. Please specify offset."%opts.pid return directory_table_base = process_dtb(addr_space, types, task[0]) process_id = process_pid(addr_space, types, task[0]) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return addr_space = process_address_space entries = addr_space.get_available_pages() print "%-12s %-12s %-12s"%('Virtual','Physical','Size') for entry in entries: phy_addr = addr_space.vtop(entry[0]) print "0x%-10x 0x%-10x 0x%-12x"%(entry[0],phy_addr,entry[1]) class usrdmp_ex_2(forensics.commands.command): # Declare meta information associated with this plugin meta_info = forensics.commands.command.meta_info meta_info['author'] = 'AAron Walters' meta_info['copyright'] = 'Copyright (c) 2007,2008 AAron Walters' meta_info['contact'] = 'awalters@volatilesystems.com' meta_info['license'] = 'GNU General Public License 2.0 or later' meta_info['url'] = 'https://www.volatilesystems.com/default/volatility' meta_info['os'] = 'WIN_32_XP_SP2' meta_info['version'] = '1.0' # This module extends the standard parser. This is accomplished by # overriding the forensics.commands.command.parse() method. The # overriding method begins by calling the base class method directly # then it further populates the OptionParser instance with two # new options. def parser(self): forensics.commands.command.parser(self) self.op.add_option('-o', '--offset', help='EPROCESS Offset (in hex)', action='store', type='string', dest='offset') self.op.add_option('-p', '--pid', help='Dump the address space for this Pid', action='store', type='int', dest='pid') # We need to override the forensics.commands.command.help() method to # change the user help message. This function returns a string that # will be displayed when a user lists available plugins. def help(self): return "Dump the address space for a process" # Finally we override the forensics.commands.command.execute() method # which provides the plugins core functionality. Command line options # are accessed as attributes of self.opts. For example, the options # provided by the standard parse would would provide the following # attributes: self.opts.filename, self.opts.base, self.opts.type. def execute(self): if (self.opts.filename is None) or (not os.path.isfile(self.opts.filename)) : self.op.error("File is required") else: filename = self.opts.filename (addr_space, symtab, types) = load_and_identify_image(self.op, self.opts) if not self.opts.offset is None: try: offset = int(self.opts.offset, 16) except: self.op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: self.op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return entries = process_address_space.get_available_pages() ofilename = opts.offset + ".dmp" # Check to make sure file can open ohandle=open(ofilename,'wb') for entry in entries: data = process_address_space.read(entry[0],entry[1]) ohandle.write("%s"%data) ohandle.close() else: if self.opts.pid == None: self.op.error("Please specify pid or offset: usrdmp -p -o ") all_tasks = process_list(addr_space, types, symtab) task = process_find_pid(addr_space,types, symtab, all_tasks, self.opts.pid) if len(task) == 0: print "Error process [%d] not found"%self.opts.pid return if len(task) > 1: print "Multiple processes [%d] found. Please specify offset."%self.opts.pid return directory_table_base = process_dtb(addr_space, types, task[0]) process_id = process_pid(addr_space, types, task[0]) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return image_file_name = process_imagename(process_address_space, types, task[0]) entries = process_address_space.get_available_pages() ofilename = str(self.opts.pid) + ".dmp" # Check to make sure file can open try: ohandle=open(ofilename,'wb') except IOError: print "Error opening file [%s]"% (ofilename) return for entry in entries: data = process_address_space.read(entry[0],entry[1]) ohandle.write("%s"%data) ohandle.close() dff-1.3.0+dfsg.1/dff/modules/ram/volatility/memory_plugins/example3.py000066400000000000000000000123731217176075400256770ustar00rootroot00000000000000# Volatility # Copyright (C) 2008 Volatile Systems # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com,bdolangavitt@wesleyan.edu @organization: Volatile Systems """ from forensics.object2 import * from forensics.object import * from vutils import * from forensics.win32.tasks import * class pslist_ex_3(forensics.commands.command): # Declare meta information associated with this plugin meta_info = forensics.commands.command.meta_info meta_info['author'] = 'AAron Walters' meta_info['copyright'] = 'Copyright (c) 2007,2008 AAron Walters' meta_info['contact'] = 'awalters@volatilesystems.com' meta_info['license'] = 'GNU General Public License 2.0 or later' meta_info['url'] = 'https://www.volatilesystems.com/default/volatility' meta_info['os'] = 'WIN_32_XP_SP2' meta_info['version'] = '1.0' # This module makes use of the standard parser. Thus it is not # necessary to override the forensics.commands.command.parse() method. # The standard parser provides the following command line options: # '-f', '--file', '(required) Image file' # '-b', '--base', '(optional) Physical offset (in hex) of DTB' # '-t', '--type', '(optional) Identify the image type' # We need to override the forensics.commands.command.help() method to # change the user help message. This function returns a string that # will be displayed when a user lists available plugins. def help(self): return "Print list running processes" # Finally we override the forensics.commands.command.execute() method # which provides the plugins core functionality. Command line options # are accessed as attributes of self.opts. For example, the options # provided by the standard parse would would provide the following # attributes: self.opts.filename, self.opts.base, self.opts.type. def execute(self): theProfile = Profile() (addr_space, symtab, types) = load_and_identify_image(self.op, \ self.opts) all_tasks = process_list(addr_space,types,symtab) print "%-20s %-6s %-6s %-6s %-6s %-6s"% \ ('Name','Pid','PPid','Thds','Hnds','Time') for task in all_tasks: if not addr_space.is_valid_address(task): continue eprocess = Object('_EPROCESS', task, addr_space, None, theProfile) image_file_name = eprocess.ImageFileName process_id = eprocess.UniqueProcessId.v() active_threads = eprocess.ActiveThreads inherited_from = eprocess.InheritedFromUniqueProcessId.v() if eprocess.ObjectTable.is_valid(): handle_count = eprocess.ObjectTable.HandleCount else: handle_count = None create_time = eprocess.CreateTime if not create_time is None: create_time=strftime("%a %b %d %H:%M:%S %Y",\ gmtime(create_time)) defaults = {0:"UNKNOWN",1:-1,2:-1,3:-1,4:-1,5:"UNKNOWN"} PrintWithDefaults("%-20s %-6d %-6d %-6d %-6d %-26s", \ (image_file_name, process_id, inherited_from, active_threads, handle_count, create_time),defaults) class _EPROCESS(Object): """Class representing an _EPROCESS. Adds the following special behavior: * Uses self.Pcb.DirectoryTableBase to re-calculate its address space. * Presents ImageFileName as a Python string rather than an array of unsigned chars. """ hasMembers = True name = "EPROCESS" def __new__(typ, *args, **kwargs): obj = object.__new__(typ) return obj def __init__(self, name, address, space, parent=None,profile=None): super(_EPROCESS,self).__init__(name, address, space,parent,profile) new_dtb = self.Pcb.DirectoryTableBase[0] self.vm = create_addr_space(self.vm, new_dtb) # Custom attributes def getImageFileName(self): return read_null_string(self.vm, types, ['_EPROCESS', 'ImageFileName'], self.offset) ImageFileName = property(fget=getImageFileName) def getCreateTime(self): return process_create_time(self.vm, types, self.offset) CreateTime = property(fget=getCreateTime) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/setup.py000066400000000000000000000010741217176075400222440ustar00rootroot00000000000000#/usr/bin/env python from distutils.core import setup from distutils.extension import Extension setup( name = "Volatility", version = "1.3_Beta", description = "Volatility -- Volatile memory framwork", author = "AAron Walters", author_email = "awalters@volatilesystems.com", url = "http://www.volatilesystems.com", license = "GPL", packages = ["forensics", "forensics.win32","memory_plugins","memory_objects","memory_objects.Linux","memory_objects.Windows","thirdparty"], ) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/thirdparty/000077500000000000000000000000001217176075400227225ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/thirdparty/CMakeLists.txt000066400000000000000000000010501217176075400254560ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py progressbar.py ) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/thirdparty/__init__.py000066400000000000000000000000001217176075400250210ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/ram/volatility/thirdparty/progressbar.py000066400000000000000000000305731217176075400256350ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: iso-8859-1 -*- # # progressbar - Text progressbar library for python. # Copyright (c) 2005 Nilton Volpato # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Text progressbar library for python. This library provides a text mode progressbar. This is tipically used to display the progress of a long running operation, providing a visual clue that processing is underway. The ProgressBar class manages the progress, and the format of the line is given by a number of widgets. A widget is an object that may display diferently depending on the state of the progress. There are three types of widget: - a string, which always shows itself; - a ProgressBarWidget, which may return a diferent value every time it's update method is called; and - a ProgressBarWidgetHFill, which is like ProgressBarWidget, except it expands to fill the remaining width of the line. The progressbar module is very easy to use, yet very powerful. And automatically supports features like auto-resizing when available. """ __author__ = "Nilton Volpato" __author_email__ = "first-name dot last-name @ gmail.com" __date__ = "2006-05-07" __version__ = "2.2" # Changelog # # 2006-05-07: v2.2 fixed bug in windows # 2005-12-04: v2.1 autodetect terminal width, added start method # 2005-12-04: v2.0 everything is now a widget (wow!) # 2005-12-03: v1.0 rewrite using widgets # 2005-06-02: v0.5 rewrite # 2004-??-??: v0.1 first version import sys, time from array import array try: from fcntl import ioctl import termios except ImportError: pass import signal class ProgressBarWidget(object): """This is an element of ProgressBar formatting. The ProgressBar object will call it's update value when an update is needed. It's size may change between call, but the results will not be good if the size changes drastically and repeatedly. """ def update(self, pbar): """Returns the string representing the widget. The parameter pbar is a reference to the calling ProgressBar, where one can access attributes of the class for knowing how the update must be made. At least this function must be overriden.""" pass class ProgressBarWidgetHFill(object): """This is a variable width element of ProgressBar formatting. The ProgressBar object will call it's update value, informing the width this object must the made. This is like TeX \\hfill, it will expand to fill the line. You can use more than one in the same line, and they will all have the same width, and together will fill the line. """ def update(self, pbar, width): """Returns the string representing the widget. The parameter pbar is a reference to the calling ProgressBar, where one can access attributes of the class for knowing how the update must be made. The parameter width is the total horizontal width the widget must have. At least this function must be overriden.""" pass class ETA(ProgressBarWidget): "Widget for the Estimated Time of Arrival" def format_time(self, seconds): return time.strftime('%H:%M:%S', time.gmtime(seconds)) def update(self, pbar): if pbar.currval == 0: return 'Time Remaining: --:--:--' elif pbar.finished: return 'Time: %s' % self.format_time(pbar.seconds_elapsed) else: elapsed = pbar.seconds_elapsed eta = elapsed * pbar.maxval / pbar.currval - elapsed return 'Time Remaining: %s' % self.format_time(eta) class FileTransferSpeed(ProgressBarWidget): "Widget for showing the transfer speed (useful for file transfers)." def __init__(self): self.fmt = '%6.2f %s' self.units = ['B','K','M','G','T','P'] def update(self, pbar): if pbar.seconds_elapsed < 2e-6:#== 0: bps = 0.0 else: bps = float(pbar.currval) / pbar.seconds_elapsed spd = bps for u in self.units: if spd < 1000: break spd /= 1000 return self.fmt % (spd, u+'/s') class RotatingMarker(ProgressBarWidget): "A rotating marker for filling the bar of progress." def __init__(self, markers='|/-\\'): self.markers = markers self.curmark = -1 def update(self, pbar): if pbar.finished: return self.markers[0] self.curmark = (self.curmark + 1)%len(self.markers) return self.markers[self.curmark] class Percentage(ProgressBarWidget): "Just the percentage done." def update(self, pbar): return '%3d%%' % pbar.percentage() class Bar(ProgressBarWidgetHFill): "The bar of progress. It will strech to fill the line." def __init__(self, marker='#', left='|', right='|'): self.marker = marker self.left = left self.right = right def _format_marker(self, pbar): if isinstance(self.marker, (str, unicode)): return self.marker else: return self.marker.update(pbar) def update(self, pbar, width): percent = pbar.percentage() cwidth = width - len(self.left) - len(self.right) marked_width = int(percent * cwidth / 100) m = self._format_marker(pbar) bar = (self.left + (m*marked_width).ljust(cwidth) + self.right) return bar class ReverseBar(Bar): "The reverse bar of progress, or bar of regress. :)" def update(self, pbar, width): percent = pbar.percentage() cwidth = width - len(self.left) - len(self.right) marked_width = int(percent * cwidth / 100) m = self._format_marker(pbar) bar = (self.left + (m*marked_width).rjust(cwidth) + self.right) return bar default_widgets = [Percentage(), ' ', Bar()] class ProgressBar(object): """This is the ProgressBar class, it updates and prints the bar. The term_width parameter may be an integer. Or None, in which case it will try to guess it, if it fails it will default to 80 columns. The simple use is like this: >>> pbar = ProgressBar().start() >>> for i in xrange(100): ... # do something ... pbar.update(i+1) ... >>> pbar.finish() But anything you want to do is possible (well, almost anything). You can supply different widgets of any type in any order. And you can even write your own widgets! There are many widgets already shipped and you should experiment with them. When implementing a widget update method you may access any attribute or function of the ProgressBar object calling the widget's update method. The most important attributes you would like to access are: - currval: current value of the progress, 0 <= currval <= maxval - maxval: maximum (and final) value of the progress - finished: True if the bar is have finished (reached 100%), False o/w - start_time: first time update() method of ProgressBar was called - seconds_elapsed: seconds elapsed since start_time - percentage(): percentage of the progress (this is a method) """ def __init__(self, maxval=100, widgets=default_widgets, term_width=None, fd=sys.stderr): assert maxval > 0 self.maxval = maxval self.widgets = widgets self.fd = fd self.signal_set = False if term_width is None: try: self.handle_resize(None,None) signal.signal(signal.SIGWINCH, self.handle_resize) self.signal_set = True except: self.term_width = 79 else: self.term_width = term_width self.currval = 0 self.finished = False self.prev_percentage = -1 self.start_time = None self.seconds_elapsed = 0 def handle_resize(self, signum, frame): h,w=array('h', ioctl(self.fd,termios.TIOCGWINSZ,'\0'*8))[:2] self.term_width = w def percentage(self): "Returns the percentage of the progress." return self.currval*100.0 / self.maxval def _format_widgets(self): r = [] hfill_inds = [] num_hfill = 0 currwidth = 0 for i, w in enumerate(self.widgets): if isinstance(w, ProgressBarWidgetHFill): r.append(w) hfill_inds.append(i) num_hfill += 1 elif isinstance(w, (str, unicode)): r.append(w) currwidth += len(w) else: weval = w.update(self) currwidth += len(weval) r.append(weval) for iw in hfill_inds: r[iw] = r[iw].update(self, (self.term_width-currwidth)/num_hfill) return r def _format_line(self): return ''.join(self._format_widgets()).ljust(self.term_width) def _need_update(self): return int(self.percentage()) != int(self.prev_percentage) def update(self, value): "Updates the progress bar to a new value." assert 0 <= value <= self.maxval self.currval = value if not self._need_update() or self.finished: return if not self.start_time: self.start_time = time.time() self.seconds_elapsed = time.time() - self.start_time self.prev_percentage = self.percentage() if value != self.maxval: self.fd.write(self._format_line() + '\r') else: self.finished = True self.fd.write(self._format_line() + '\n') def start(self): """Start measuring time, and prints the bar at 0%. It returns self so you can use it like this: >>> pbar = ProgressBar().start() >>> for i in xrange(100): ... # do something ... pbar.update(i+1) ... >>> pbar.finish() """ self.update(0) return self def finish(self): """Used to tell the progress is finished.""" self.update(self.maxval) if self.signal_set: signal.signal(signal.SIGWINCH, signal.SIG_DFL) if __name__=='__main__': import os def example1(): widgets = ['Test: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA(), ' ', FileTransferSpeed()] pbar = ProgressBar(widgets=widgets, maxval=10000000).start() for i in range(1000000): # do something pbar.update(10*i+1) pbar.finish() print def example2(): class CrazyFileTransferSpeed(FileTransferSpeed): "It's bigger between 45 and 80 percent" def update(self, pbar): if 45 < pbar.percentage() < 80: return 'Bigger Now ' + FileTransferSpeed.update(self,pbar) else: return FileTransferSpeed.update(self,pbar) widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=10000000) # maybe do something pbar.start() for i in range(2000000): # do something pbar.update(5*i+1) pbar.finish() print def example3(): widgets = [Bar('>'), ' ', ETA(), ' ', ReverseBar('<')] pbar = ProgressBar(widgets=widgets, maxval=10000000).start() for i in range(1000000): # do something pbar.update(10*i+1) pbar.finish() print def example4(): widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'), ' ', ETA(), ' ', FileTransferSpeed()] pbar = ProgressBar(widgets=widgets, maxval=500) pbar.start() for i in range(100,500+1,50): time.sleep(0.2) pbar.update(i) pbar.finish() print example1() example2() example3() example4() dff-1.3.0+dfsg.1/dff/modules/ram/volatility/vmodules.py000066400000000000000000002050031217176075400227400ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Original Source: # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ import sys import os from vutils import * from forensics.win32.datetime import * from forensics.win32.tasks import * from forensics.win32.network import * from forensics.win32.handles import * from forensics.win32.modules import * from forensics.win32.vad import * from forensics.win32.scan import * from forensics.win32.crash_addrspace import * from forensics.win32.hiber_addrspace import * from forensics.win32.crashdump import * import forensics.win32.meta_info as meta_info from forensics.win32.xpress import xpress_decode from forensics.win32.registry import print_entry_keys from forensics.win32.executable import rebuild_exe_dsk,rebuild_exe_mem from forensics.win32.scan2 import * class VolatoolsModule: def __init__(self, cmd_name, cmd_desc, cmd_execute): self.cmd_name = cmd_name self.cmd_desc = cmd_desc self.cmd_execute = cmd_execute def desc(self): return self.cmd_desc def execute(self, module, args): self.cmd_execute(module, args) ################################### # identify ################################### def get_image_info(cmdname, argv): """ Function provides as many characteristics as can be identified for given image. """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) if not opts.base is None: print "Ignoring option -b" opts.base = None if not opts.type is None: print "Ignoring option -t" opts.type = None (addr_space, symtab, types) = load_and_identify_image(op, opts, True) if not addr_space is None and not symtab is None: KUSER_SHARED_DATA = 0xFFDF0000 if not addr_space.is_valid_address(KUSER_SHARED_DATA): print "%25s UNAVAILABLE" % ("Datetime:") return time = windows_to_unix_time(local_time(addr_space, types, KUSER_SHARED_DATA)) ts = format_time(time) print "%25s %s"% ("Datetime:", ts) ################################### # Datetime ################################### def format_time(time): ts=strftime("%a %b %d %H:%M:%S %Y", gmtime(time)) return ts def get_datetime(cmdname, argv): """ Function prints a formatted string of the image local time. """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) (addr_space, symtab, types) = load_and_identify_image(op, opts) KUSER_SHARED_DATA = 0xFFDF0000 if not addr_space.is_valid_address(KUSER_SHARED_DATA): print "ERROR: KUSER_SHARED_DATA Invalid: Try a different Page Directory Base" return time = windows_to_unix_time(local_time(addr_space, types, KUSER_SHARED_DATA)) ts = format_time(time) print "Image local date and time: %s"%ts ################################### # modules list ################################### def get_modules(cmdname, argv): """ Function prints a formatted table of module information """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) (addr_space, symtab, types) = load_and_identify_image(op, opts) all_modules = modules_list(addr_space, types, symtab) print "%-50s %-12s %-8s %s" %('File','Base', 'Size', 'Name') for module in all_modules: if not addr_space.is_valid_address(module): continue module_image = module_imagename(addr_space, types, module) if module_image is None: module_image = "UNKNOWN" module_name = module_modulename(addr_space, types, module) if module_name is None: module_name = "UNKNOWN" module_base = module_baseaddr(addr_space, types, module) if module_base is None: module_base = "UNKNOWN" else: module_base = "0x%010x" % module_base module_size = module_imagesize(addr_space, types, module) print "%-50s %s 0x%06x %s" % (module_image, module_base, module_size, module_name) ################################### # pslist - process list ################################### def get_pslist(cmdname, argv): """ Function prints a formatted table of process information for image """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) (addr_space, symtab, types) = load_and_identify_image(op, opts) all_tasks = process_list(addr_space, types, symtab) print "%-20s %-6s %-6s %-6s %-6s %-6s"%('Name','Pid','PPid','Thds','Hnds','Time') for task in all_tasks: if not addr_space.is_valid_address(task): continue image_file_name = process_imagename(addr_space, types, task) if image_file_name is None: image_file_name = "UNKNOWN" process_id = process_pid(addr_space, types, task) if process_id is None: process_id = -1 active_threads = process_num_active_threads(addr_space, types, task) if active_threads is None: active_threads = -1 inherited_from = process_inherited_from(addr_space, types,task) if inherited_from is None: inherited_from = -1 handle_count = process_handle_count(addr_space, types, task) if handle_count is None: handle_count = -1 create_time = process_create_time(addr_space, types, task) if create_time is None: create_time = "UNKNOWN" else: create_time = format_time(create_time) print "%-20s %-6d %-6d %-6d %-6d %-26s" % (image_file_name, process_id, inherited_from, active_threads, handle_count, create_time) ################################### # dlllist - DLL list ################################### def get_dlllist(cmdname, argv): """ Function prints a list of dlls loaded in each process """ op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex) in physical address space', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Get info for this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) filename = opts.filename (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) print "%s pid: %d"%(image_file_name, process_id) peb = process_peb(flat_address_space, types, offset) if not process_address_space.is_valid_address(peb): print "Unable to read PEB for task." return command_line = process_command_line(process_address_space, types, peb) if command_line is None: command_line = "UNKNOWN" print "Command line : %s" % (command_line) print modules = process_ldrs(process_address_space, types, peb) if len(modules) > 0: print "%-12s %-12s %s"%('Base','Size','Path') for module in modules: if not process_address_space.is_valid_address(module): return path = module_path(process_address_space, types, module) if path is None: path = "%-10s " % ('UNKNOWN') base = module_base(process_address_space, types, module) if base is None: base = "%-10s " % ('UNKNOWN') else: base = "0x%-10x" % (base) size = module_size(process_address_space, types, module) if size is None: size = "%-10s " % ('UNKNOWN') else: size = "0x%-10x" % (size) print "%s %s %s"%(base,size,path) print else: # get list of windows processes all_tasks = process_list(addr_space, types, symtab) if not opts.pid == None: all_tasks = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(all_tasks) == 0: print "Error process [%d] not found"%opts.pid star_line = '*'*72 for task in all_tasks: if not addr_space.is_valid_address(task): continue if len(all_tasks) > 1: print "%s"%star_line image_file_name = process_imagename(addr_space, types, task) process_id = process_pid(addr_space, types, task) print "%s pid: %d"%(image_file_name, process_id) process_address_space = process_addr_space(addr_space, types, task, opts.filename) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) continue peb = process_peb(addr_space, types, task) if not process_address_space.is_valid_address(peb): print "Unable to read PEB for task." continue command_line = process_command_line(process_address_space, types, peb) if command_line is None: command_line = "UNKNOWN" print "Command line : %s" % (command_line) print read_unicode_string(process_address_space, types, ['_PEB', 'CSDVersion'], peb) print modules = process_ldrs(process_address_space, types, peb) if len(modules) > 0: print "%-12s %-12s %s"%('Base','Size','Path') for module in modules: if not process_address_space.is_valid_address(module): continue path = module_path(process_address_space, types, module) if path is None: path = "%-10s " % ('UNKNOWN') base = module_base(process_address_space, types, module) if base is None: base = "%-10s " % ('UNKNOWN') else: base = "0x%-10x" % (base) size = module_size(process_address_space, types, module) if size is None: size = "%-10s " % ('UNKNOWN') else: size = "0x%-10x" % (size) print "%s %s %s"%(base,size,path) print ################################### # connections - List open connections ################################### def get_connections(cmdname, argv): """ Function prints a list of open connections """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) star_line = '*'*72 (addr_space, symtab, types) = load_and_identify_image(op, opts) connections = tcb_connections(addr_space, types, symtab) if len(connections) > 0: print "%-25s %-25s %-6s"%('Local Address','Remote Address','Pid') for connection in connections: if not addr_space.is_valid_address(connection): continue pid = connection_pid(addr_space, types, connection) lport = connection_lport(addr_space, types, connection) laddr = connection_laddr(addr_space, types, connection) rport = connection_rport(addr_space, types, connection) raddr = connection_raddr(addr_space, types, connection) local = "%s:%d"%(laddr,lport) remote = "%s:%d"%(raddr,rport) print "%-25s %-25s %-6d"%(local,remote,pid) ################################### # sockets - List open sockets ################################### def get_sockets(cmdname, argv): """ Function prints a list of open sockets. """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) (addr_space, symtab, types) = load_and_identify_image(op, opts) sockets = open_sockets(addr_space, types, symtab) if len(sockets) > 0: print "%-6s %-6s %-6s %-26s"%('Pid','Port','Proto','Create Time') for socket in sockets: if not addr_space.is_valid_address(socket): continue pid = socket_pid(addr_space, types, socket) proto = socket_protocol(addr_space, types, socket) port = socket_local_port(addr_space, types, socket) time = socket_create_time(addr_space, types, socket) print "%-6d %-6d %-6d %-26s"%(pid,port,proto,format_time(time)) ################################### # files - List open files ################################### def print_entry_file(addr_space, types, entry): if not addr_space.is_valid_address(entry): return obj = handle_entry_object(addr_space, types, entry) if addr_space.is_valid_address(obj): if is_object_file(addr_space, types, obj): file = object_data(addr_space, types, obj) fname = file_name(addr_space, types, file) if fname != "": print "%-6s %-40s"%("File",fname) def get_open_files(cmdname, argv): """ Function prints a list of open files for each process. """ htables = [] op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex) in physical address space', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Get info for this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) filename = opts.filename pid = opts.pid (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) ObjectTable = process_handle_table(flat_address_space, types, offset) if addr_space.is_valid_address(ObjectTable): htables.append(ObjectTable) else: htables = handle_tables(addr_space, types, symtab,pid) star_line = '*'*72 for table in htables: if len(htables) > 1: print "%s"%star_line process_id = handle_process_id(addr_space, types, table) if process_id == None: continue print "Pid: %-6d"%(process_id) table_code = handle_table_code(addr_space, types, table) if table_code == 0: continue table_levels = handle_table_levels(addr_space, types, table) if table_levels == 0: num_entries = handle_num_entries(addr_space, types, table) for counter in range(0, 0x200): entry = handle_table_L1_entry(addr_space, types, table, counter) if entry != None and entry !=0: print_entry_file(addr_space, types, entry) elif table_levels == 1: for i in range(0, 0x200): L1_entry = handle_table_L1_entry(addr_space, types, table, i) if not L1_entry is None: L1_table = handle_entry_object(addr_space, types, L1_entry) for j in range(0, 0x200): L2_entry = handle_table_L2_entry(addr_space, types, table, L1_table, j) if not L2_entry is None: print_entry_file(addr_space, types, L2_entry) elif table_levels == 2: for i in range(0, 0x200): L1_entry = handle_table_L1_entry(addr_space, types, table, i) if not L1_entry is None: L1_table = handle_entry_object(addr_space, types, L1_entry) for j in range(0, 0x200): L2_entry = handle_table_L2_entry(addr_space, types, table, L1_table, j) if not L2_entry is None: L2_table = handle_entry_object(addr_space, types, L2_entry) for k in range(0, 0x200): L3_entry = handle_table_L3_entry(addr_space, types, table, L2_table, j) if not L3_entry is None: print_entry_file(addr_space, types, L3_entry) ################################### # strings - identify pid(s) associated with a string ################################### def print_string(offset, pidlist, string): print "%d " % (offset), print "[%s:%x" % (pidlist[0][0], pidlist[0][1] | (offset & 0xFFF)), for i in pidlist[1:]: print " %s:%x" % (i[0], (i[1] | (offset & 0xFFF))), print "] %s" % string, def get_strings(cmdname, argv): op = get_standard_parser(cmdname) op.add_option('-s', '--strings', help='(required) File of form :', action='store', type='string', dest='stringfile') opts, args = op.parse_args(argv) if opts.stringfile is None: op.error("String file (-s) required") try: strings = open(opts.stringfile, "r") except: op.error("Invalid or inaccessible file %s" % opts.stringfile) (addr_space, symtab, types) = load_and_identify_image(op, opts) all_tasks = process_list(addr_space, types, symtab) # dict of form phys_page -> [isKernel, (pid1, vaddr1), (pid2, vaddr2) ...] # where isKernel is True or False. if isKernel is true, list is of all kernel addresses # ASSUMPTION: no pages mapped in kernel and userland reverse_map = {} vpage = 0 while vpage < 0xFFFFFFFF: kpage = addr_space.vtop(vpage) if not kpage is None: if not reverse_map.has_key(kpage): reverse_map[kpage] = [True] reverse_map[kpage].append(('kernel', vpage)) vpage += 0x1000 for task in all_tasks: process_id = process_pid(addr_space, types, task) process_address_space = process_addr_space(addr_space, types, task, opts.filename) vpage = 0 try: while vpage < 0xFFFFFFFF: physpage = process_address_space.vtop(vpage) if not physpage is None: if not reverse_map.has_key(physpage): reverse_map[physpage] = [False] if not reverse_map[physpage][0]: reverse_map[physpage].append((process_id, vpage)) vpage += 0x1000 except: continue for stringLine in strings: (offsetString, string) = stringLine.split(':', 1) try: offset = int(offsetString) except: op.error("String file format invalid.") if reverse_map.has_key(offset & 0xFFFFF000): print_string(offset, reverse_map[offset & 0xFFFFF000][1:], string) ################################### # vadinfo - Dump the VAD to file ################################### def vadinfo(cmdname, argv): """ This function dumps the vad information """ op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex) in physical address space', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Dump the VAD of the process with this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) if opts.filename is None: op.error("vadinfo -f ") else: filename = opts.filename (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return VadRoot = process_vadroot(flat_address_space, types, offset) if VadRoot == None or not process_address_space.is_valid_address(VadRoot): print "VadRoot is not valid" return vad_info(process_address_space, types, VadRoot) else: all_tasks = process_list(addr_space, types, symtab) if not opts.pid == None: all_tasks = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(all_tasks) == 0: print "Error process [%d] not found"%opts.pid star_line = '*'*72 for task in all_tasks: print "%s"%star_line if not addr_space.is_valid_address(task): print "Task address is not valid" continue directory_table_base = process_dtb(addr_space, types, task) process_id = process_pid(addr_space, types, task) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) continue print "Pid: %-6d"%(process_id) VadRoot = process_vadroot(addr_space, types, task) if VadRoot == None or not process_address_space.is_valid_address(VadRoot): print "VadRoot is not valid" continue vad_info(process_address_space, types, VadRoot) def vaddump(cmdname, argv): """ This function dumps the vad information """ op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex)', action='store', type='string', dest='offset') op.add_option('-d', '--directory', help='Output directory', action='store', type='string', dest='dir') op.add_option('-p', '--pid', help='Dump the VAD of the process with this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) if opts.filename is None: op.error("vaddump -f ") else: filename = opts.filename (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return VadRoot = process_vadroot(flat_address_space, types, offset) if VadRoot == None or not process_address_space.is_valid_address(VadRoot): print "VadRoot is not valid" return vad_dump(process_address_space, types, VadRoot, image_file_name, offset, opts.dir) else: all_tasks = process_list(addr_space, types, symtab) if not opts.pid == None: all_tasks = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(all_tasks) == 0: print "Error process [%d] not found"%opts.pid star_line = '*'*72 for task in all_tasks: print "%s"%star_line if not addr_space.is_valid_address(task): print "Task address is not valid" continue directory_table_base = process_dtb(addr_space, types, task) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(addr_space, types, task) process_id = process_pid(addr_space, types, task) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) continue print "Pid: %-6d"%(process_id) VadRoot = process_vadroot(addr_space, types, task) if VadRoot == None or not process_address_space.is_valid_address(VadRoot): print "VadRoot is not valid" continue offset = process_address_space.vtop(task) vad_dump(process_address_space, types, VadRoot, image_file_name, offset, opts.dir) ################################### # vadwalk - Print the VadTree ################################### def vadwalk(cmdname, argv): """ This function dumps the vad information """ op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex)', action='store', type='string', dest='offset') op.add_option('-e', '--tree', help='print VAD tree in tree format', action='store_true',dest='tree', default=False) op.add_option('-l', '--table', help='print VAD tree in table format', action='store_true',dest='table', default=False) op.add_option('-d', '--dot', help='print VAD tree in Dotfile format', action='store_true',dest='dot', default=False) op.add_option('-p', '--pid', help='Dump the VAD of the process with this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) if opts.filename is None: op.error("vadwalk -f [options]") else: filename = opts.filename tree = opts.tree table = opts.table dot = opts.dot (addr_space, symtab, types) = load_and_identify_image(op, opts) if opts.tree == False and opts.dot == False: opts.table = True if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return VadRoot = process_vadroot(flat_address_space, types, offset) if VadRoot == None or not process_address_space.is_valid_address(VadRoot): print "VadRoot is not valid" return if(opts.table == True): print "Address Parent Left Right Start End Tag Flags" traverse_vad(None, addr_space, types, VadRoot, print_vad_table, None, None, 0, None) elif (opts.tree == True): traverse_vad(None, addr_space, types, VadRoot, print_vad_tree, None, None, 0, None) elif (opts.dot == True): print "digraph processtree {" print "graph [rankdir = \"TB\"];" traverse_vad(None, addr_space, types, VadRoot, print_vad_dot_prefix, print_vad_dot_infix, None, 0, None) print "}" else: op.error("Output type required!") else: all_tasks = process_list(addr_space, types, symtab) if not opts.pid == None: all_tasks = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(all_tasks) == 0: print "Error process [%d] not found"%opts.pid star_line = '*'*72 for task in all_tasks: print "%s"%star_line if not addr_space.is_valid_address(task): print "Task address is not valid" continue directory_table_base = process_dtb(addr_space, types, task) process_id = process_pid(addr_space, types, task) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) continue print "Pid: %-6d"%(process_id) VadRoot = process_vadroot(addr_space, types, task) if VadRoot == None or not process_address_space.is_valid_address(VadRoot): print "VadRoot is not valid" continue if(opts.table == True): print "Address Parent Left Right Start End Tag Flags" traverse_vad(None, addr_space, types, VadRoot, print_vad_table, None, None, 0, None) elif (opts.tree == True): traverse_vad(None, addr_space, types, VadRoot, print_vad_tree, None, None, 0, None) elif (opts.dot == True): print "digraph processtree {" print "graph [rankdir = \"TB\"];" traverse_vad(None, addr_space, types, VadRoot, print_vad_dot_prefix, print_vad_dot_infix, None, 0, None) print "}" else: op.error("Output type required!") ################################### # psscan - Scan for EPROCESS objects ################################### def psscan(cmdname, argv): """ This module scans for EPROCESS objects """ op = get_standard_parser(cmdname) op.add_option('-s', '--start', help='Start of scan (in hex)', action='store', type='string', dest='start') op.add_option('-e', '--end', help='End of scan (in hex)', action='store', type='string', dest='end') op.add_option('-l', '--slow', help='Scan in slow mode', action='store_true',dest='slow', default=False) op.add_option('-d', '--dot', help='Print processes in dot format', action='store_true',dest='dot_format', default=False) opts, args = op.parse_args(argv) slow = opts.slow if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename if not opts.start is None: try: start = int(opts.start, 16) except: op.error("Start of scan must be a hexidecimal number.") else: start = 0 filesize = os.path.getsize(filename) if not opts.end is None: try: end = int(opts.end, 16) except: op.error("End of scan must be a hexidecimal number.") if end > filesize: op.error("End of scan is larger than filesize 0x%x"%(filesize)) else: end = filesize try: if slow == False: flat_address_space = FileAddressSpace(filename,fast=True) else: flat_address_space = FileAddressSpace(filename,fast=False) except: op.error("Unable to open image file %s" % (filename)) if is_hiberfil(filename) == True: flat_address_space = FileAddressSpace(filename,fast=False) flat_address_space = WindowsHiberFileSpace32(flat_address_space,0,0) slow = True if opts.dot_format: ps_scan_dot(flat_address_space, types, filename, start, end, slow) else: ps_scan(flat_address_space, types, filename, start, end, slow) ################################### # thrdscan - Scan for ETHREAD objects ################################### def thrdscan(cmdname, argv): """ This module scans for ETHREAD objects """ op = get_standard_parser(cmdname) op.add_option('-s', '--start', help='Start of scan (in hex)', action='store', type='string', dest='start') op.add_option('-e', '--end', help='End of scan (in hex)', action='store', type='string', dest='end') op.add_option('-l', '--slow', help='Scan in slow mode', action='store_true',dest='slow', default=False) opts, args = op.parse_args(argv) slow = opts.slow if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename if not opts.start is None: try: start = int(opts.start, 16) except: op.error("Start of scan must be a hexidecimal number.") else: start = 0 filesize = os.path.getsize(filename) if not opts.end is None: try: end = int(opts.end, 16) except: op.error("End of scan must be a hexidecimal number.") if end > filesize: op.error("End of scan is larger than filesize 0x%x"% (filesize) ) else: end = filesize try: if slow == False: flat_address_space = FileAddressSpace(filename,fast=True) else: flat_address_space = FileAddressSpace(filename,fast=False) except: op.error("Unable to open image file %s" % (filename)) if is_hiberfil(filename) == True: flat_address_space = FileAddressSpace(filename,fast=False) flat_address_space = WindowsHiberFileSpace32(flat_address_space,0,0) slow = True thrd_scan(flat_address_space, types, filename, start, end, slow) ################################### # sockscan - Scan for socket objects ################################### def sockscan(cmdname, argv): """ This module scans for socket objects """ op = get_standard_parser(cmdname) op.add_option('-s', '--start', help='Start of scan (in hex)', action='store', type='string', dest='start') op.add_option('-e', '--end', help='End of scan (in hex)', action='store', type='string', dest='end') op.add_option('-l', '--slow', help='Scan in slow mode', action='store_true',dest='slow', default=False) opts, args = op.parse_args(argv) slow = opts.slow if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename if not opts.start is None: try: start = int(opts.start, 16) except: op.error("Start of scan must be a hexidecimal number.") else: start = 0 filesize = os.path.getsize(filename) if not opts.end is None: try: end = int(opts.end, 16) except: op.error("End of scan must be a hexidecimal number.") if end > filesize: op.error("End of scan is larger than filesize 0x%x"%(filesize)) else: end = filesize try: if slow == False: flat_address_space = FileAddressSpace(filename,fast=True) else: flat_address_space = FileAddressSpace(filename,fast=False) except: op.error("Unable to open image file %s" % (filename)) if is_hiberfil(filename) == True: flat_address_space = FileAddressSpace(filename,fast=False) flat_address_space = WindowsHiberFileSpace32(flat_address_space,0,0) slow = True socket_scan(flat_address_space, types, filename, start, end, slow) ################################### # connscan - Scan for connection objects ################################### def connscan(cmdname, argv): """ This module scans for connection objects """ op = get_standard_parser(cmdname) op.add_option('-s', '--start', help='Start of scan (in hex)', action='store', type='string', dest='start') op.add_option('-e', '--end', help='End of scan (in hex)', action='store', type='string', dest='end') op.add_option('-l', '--slow', help='Scan in slow mode', action='store_true',dest='slow', default=False) opts, args = op.parse_args(argv) slow = opts.slow if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename if not opts.start is None: try: start = int(opts.start, 16) except: op.error("Start of scan must be a hexidecimal number.") else: start = 0 filesize = os.path.getsize(filename) if not opts.end is None: try: end = int(opts.end, 16) except: op.error("End of scan must be a hexidecimal number.") if end > filesize: sop.error("End of scan is larger than filesize 0x%x"%(filesize)) else: end = filesize try: if slow == False: flat_address_space = FileAddressSpace(filename,fast=True) else: flat_address_space = FileAddressSpace(filename,fast=False) except: op.error("Unable to open image file %s" % (filename)) if is_hiberfil(filename) == True: flat_address_space = FileAddressSpace(filename,fast=False) flat_address_space = WindowsHiberFileSpace32(flat_address_space,0,0) slow = True conn_scan(flat_address_space, types, filename, start, end, slow) ################################### # memory map ################################### def mem_map(cmdname, argv): op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex)', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Print the memory map for this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return addr_space = process_address_space else: if opts.pid == None: op.error("Please specify pid or offset: memmap -p -o ") all_tasks = process_list(addr_space, types, symtab) task = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(task) == 0: print "Error process [%d] not found"%opts.pid return if len(task) > 1: print "Multiple processes [%d] found. Please specify offset."%opts.pid return directory_table_base = process_dtb(addr_space, types, task[0]) process_id = process_pid(addr_space, types, task[0]) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return addr_space = process_address_space entries = addr_space.get_available_pages() print "%-12s %-12s %-12s"%('Virtual','Physical','Size') for entry in entries: phy_addr = addr_space.vtop(entry[0]) print "0x%-10x 0x%-10x 0x%-12x"%(entry[0],phy_addr,entry[1]) ################################### # module scan ################################### def modscan(cmdname, argv): """ This (Volatility) module scans for (Windows) modules """ op = get_standard_parser(cmdname) op.add_option('-s', '--start', help='Start of scan (in hex)', action='store', type='string', dest='start') op.add_option('-e', '--end', help='End of scan (in hex)', action='store', type='string', dest='end') op.add_option('-l', '--slow', help='Scan in slow mode', action='store_true',dest='slow', default=False) opts, args = op.parse_args(argv) slow = opts.slow if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename if not opts.start is None: try: start = int(opts.start, 16) except: op.error("Start of scan must be a hexidecimal number.") else: start = 0 filesize = os.path.getsize(filename) if not opts.end is None: try: end = int(opts.end, 16) except: op.error("End of scan must be a hexidecimal number.") if end > filesize: op.error("End of scan is larger than filesize 0x%x"%(filesize)) else: end = filesize try: flat_address_space = FileAddressSpace(filename,fast=True) except: op.error("Unable to open image file %s" % (filename)) # Find a dtb value if opts.base is None: sysdtb = find_dtb(flat_address_space, types) else: try: sysdtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") if is_crash_dump(filename) == True: sub_addr_space = WindowsCrashDumpSpace32(flat_address_space,0,0) else: sub_addr_space = flat_address_space if is_hiberfil(filename) == True: flat_address_space = FileAddressSpace(filename,fast=False) flat_address_space = WindowsHiberFileSpace32(flat_address_space,0,0) slow = True meta_info.set_dtb(sysdtb) kaddr_space = load_pae_address_space(filename, sysdtb) if kaddr_space is None: kaddr_space = load_nopae_address_space(filename, sysdtb) meta_info.set_kas(kaddr_space) module_scan(flat_address_space, types, filename, start, end, slow) ################################### # dumpchk ################################### def dump_chk(cmdname, argv): """ Print crash dump information """ op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename fileAS = FileAddressSpace(opts.filename) crashAS = WindowsCrashDumpSpace32(fileAS,0,0) print "DUMP_HEADER32:" print "MajorVersion 0x%08x"% \ crashAS.get_majorversion() print "MinorVersion 0x%08x"% \ crashAS.get_minorversion() print "KdSecondaryVersion 0x%08x"% \ crashAS.get_kdsecondaryversion() print "DirectoryTableBase 0x%08x"% \ crashAS.get_directorytablebase() print "PfnDataBase 0x%08x"% \ crashAS.get_pfndatabase() print "PsLoadedModuleList 0x%08x"% \ crashAS.get_psloadedmodulelist() print "PsActiveProcessHead 0x%08x"% \ crashAS.get_psactiveprocesshead() print "MachineImageType 0x%08x"% \ crashAS.get_machineimagetype() print "NumberProcessors 0x%08x"% \ crashAS.get_numberprocessors() print "BugCheckCode 0x%08x"% \ crashAS.get_bugcheckcode() print "PaeEnabled 0x%08x"% \ crashAS.get_paeenabled() print "KdDebuggerDataBlock 0x%08x"% \ crashAS.get_kddebuggerdatablock() print "ProductType 0x%08x"% \ crashAS.get_producttype() print "SuiteMask 0x%08x"% \ crashAS.get_suitemask() print "WriterStatus 0x%08x"% \ crashAS.get_writerstatus() print print "Physical Memory Description:" print "Number of runs: %d"%crashAS.get_number_of_runs() print "FileOffset Start Address Length" foffset=0x1000 for run in crashAS.runs: print "%08x %08x %08x"%(foffset,run[0]*0x1000,run[1]*0x1000) foffset += (run[1] * 0x1000) print "%08x %08x"%(foffset-0x1000,((run[0]+run[1]-1)*0x1000)) ################################### # user dump ################################### def mem_dump(cmdname, argv): op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex)', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Dump the address space for this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return entries = process_address_space.get_available_pages() #ofilename = image_file_name + ".dmp" ofilename = opts.offset + ".dmp" # Check to make sure file can open ohandle=open(ofilename,'wb') for entry in entries: data = process_address_space.read(entry[0],entry[1]) ohandle.write("%s"%data) ohandle.close() else: if opts.pid == None: op.error("Please specify pid or offset: usrdmp -p -o ") all_tasks = process_list(addr_space, types, symtab) task = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(task) == 0: print "Error process [%d] not found"%opts.pid return if len(task) > 1: print "Multiple processes [%d] found. Please specify offset."%opts.pid return directory_table_base = process_dtb(addr_space, types, task[0]) process_id = process_pid(addr_space, types, task[0]) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return image_file_name = process_imagename(process_address_space, types, task[0]) entries = process_address_space.get_available_pages() #ofilename = image_file_name + ".dmp" ofilename = str(opts.pid) + ".dmp" # Check to make sure file can open try: ohandle=open(ofilename,'wb') except IOError: print "Error opening file [%s]"% (ofilename) return for entry in entries: data = process_address_space.read(entry[0],entry[1]) ohandle.write("%s"%data) ohandle.close() ################################### # hibinfo - print hiberfil.sys meta information and convert ################################### def hibinfo(cmdname, argv): """ Print hiberfile.sys meta information and convert to raw image """ PagesListHead = {} op = get_standard_parser(cmdname) op.add_option('-q', '--quick', help='Only dump header information', action='store_true',dest='quick', default=False) op.add_option("-d", "--dump", help="save dd-style dump to FILE", metavar="FILE", dest="dump") opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename if opts.dump is None and opts.quick == False: op.error("Dump file is required") else: dumpfile = opts.dump fileAS = FileAddressSpace(opts.filename) hiberAS = WindowsHiberFileSpace32(fileAS,0,0) if not hiberAS: print "Error: Failed to open file" return print "Signature: %s"%hiberAS.get_signature() print "SystemTime: %s"%hiberAS.get_system_time() print print "Control registers flags" print "CR0: %08x"%hiberAS.CR0 print "CR0[PAGING]: %d"%hiberAS.is_paging() print "CR3: %08x"%hiberAS.CR3 print "CR4: %08x"%hiberAS.CR4 print "CR4[PSE]: %d"%hiberAS.is_pse() print "CR4[PAE]: %d"%hiberAS.is_pae() (major,minor,build) = hiberAS.get_version() print print "Windows Version is %d.%d (%d)"%(major,minor,build) print if opts.quick: return print "Physical Memory dump." try: dmp = open(dumpfile,'wb') except IOError: print "Error opening file [%s]"% (dumpfile) return hiberAS.convert_to_raw(dmp) dmp.close() print "Memory dump successfuly dumped." ################################### # raw2dmp - raw2dump raw image to crash dump ################################### def raw2dmp(cmdname, argv): """ This module generates a crash dump from a image of ram """ op = get_standard_parser(cmdname) op.add_option('-o', '--output', help='Output file', action='store', type='string', dest='outfile') opts, args = op.parse_args(argv) if (opts.outfile is None): op.error("Output file is required") (addr_space, symtab, types) = load_and_identify_image(op, opts) dd_to_crash(addr_space, types, symtab, opts) ################################### # dmp2raw - Convert a crash dump into a flat address space ################################### def dmp2raw(cmdname, argv): """ This function creates a crash dump """ op = get_standard_parser(cmdname) # add extra arg for the output file op.add_option('-o', '--output', help='Output file', action='store', type='string', dest='outfile') opts, args = op.parse_args(argv) if (opts.outfile is None): op.error("Output file is required") filename = opts.filename try: flat_address_space = FileAddressSpace(filename,fast=False) except: op.error("Unable to open image file %s" % (filename)) crash_to_dd(flat_address_space, types, opts.outfile) ################################### # registry keys - List open registry keys ################################### def get_open_keys(cmdname, argv): """ Function prints a list of open keys for each process. """ op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex) in physical address space', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Get info for this Pid', action='store', type='int', dest='pid') opts, args = op.parse_args(argv) filename = opts.filename pid = opts.pid (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexidecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) ObjectTable = process_handle_table(flat_address_space, types, offset) if addr_space.is_valid_address(ObjectTable): htables = [ObjectTable] else: htables = handle_tables(addr_space, types, symtab,pid) star_line = '*'*72 for table in htables: if len(htables) > 1: print "%s"%star_line process_id = handle_process_id(addr_space, types, table) if process_id == None: continue print "Pid: %-6d"%(process_id) entries = handle_entries(addr_space, types, table) for hentry in entries: ek = print_entry_keys(addr_space, types, hentry) if ek != None: print ek ################################### # procdump - Dump a process to an executable image ################################### def procdump(cmdname,argv): """ This function dumps a process to a PE file. """ op = get_standard_parser(cmdname) op.add_option('-o', '--offset', help='EPROCESS Offset (in hex) in physcial address space', action='store', type='string', dest='offset') op.add_option('-p', '--pid', help='Dump the process with this Pid', action='store', type='int', dest='pid') op.add_option('-m', '--mode', help=('strategy to use when saving executable. Use "disk" to ' 'save using disk-based section sizes, "mem" for memory-' 'based sections. (default: "mem")'), action='store', type='string', default="mem", dest='mode') op.add_option('-u', '--unsafe', help='do not perform sanity checks on sections when dumping', action='store_false', default=True, dest='safe') opts, args = op.parse_args(argv) if opts.filename is None: op.error("procdump -f ") else: filename = opts.filename if opts.mode == "disk": rebuild_exe = rebuild_exe_dsk elif opts.mode == "mem": rebuild_exe = rebuild_exe_mem else: op.error('"mode" must be one of "disk" or "mem"') (addr_space, symtab, types) = load_and_identify_image(op, opts) if not opts.offset is None: try: offset = int(opts.offset, 16) except: op.error("EPROCESS offset must be a hexadecimal number.") try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" %(filename)) directory_table_base = process_dtb(flat_address_space, types, offset) process_address_space = create_addr_space(addr_space, directory_table_base) image_file_name = process_imagename(flat_address_space, types, offset) process_id = process_pid(flat_address_space, types, offset) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) return peb = process_peb(flat_address_space, types, offset) img_base = read_obj(process_address_space, types, ['_PEB', 'ImageBaseAddress'], peb) if img_base == None: print "Error: Image base not memory resident for process [%d]" % (process_id) return if process_address_space.vtop(img_base) == None: print "Error: Image base not memory resident for process [%d]" % (process_id) return print "Dumping %s, pid: %-6d output: %s"%(image_file_name,process_id,"executable.%d.exe" % (process_id)) of = open("executable.%d.exe" % (process_id), 'wb') rebuild_exe(process_address_space, types, img_base, of, opts.safe) of.close() else: all_tasks = process_list(addr_space, types, symtab) if not opts.pid == None: all_tasks = process_find_pid(addr_space,types, symtab, all_tasks, opts.pid) if len(all_tasks) == 0: print "Error process [%d] not found"%opts.pid star_line = '*'*72 for task in all_tasks: print star_line directory_table_base = process_dtb(addr_space, types, task) process_id = process_pid(addr_space, types, task) process_address_space = create_addr_space(addr_space, directory_table_base) if process_address_space is None: print "Error obtaining address space for process [%d]" % (process_id) continue image_file_name = process_imagename(process_address_space, types, task) peb = process_peb(process_address_space, types, task) img_base = read_obj(process_address_space, types, ['_PEB', 'ImageBaseAddress'], peb) if img_base == None: print "Error: Image base not memory resident for process [%d]" % (process_id) continue if process_address_space.vtop(img_base) == None: print "Error: Image base not memory resident for process [%d]" % (process_id) continue print "Dumping %s, pid: %-6d output: %s"%(image_file_name,process_id,"executable.%d.exe" % (process_id)) of = open("executable.%d.exe" % (process_id), 'wb') try: rebuild_exe(process_address_space, types, img_base, of, opts.safe) except ValueError,ve: print "Unable to dump executable; sanity check failed:" print " ", ve print "You can use -u to disable this check." finally: of.close() ################################### # The following new scanning modules make use # of the new scanning infrastructure. ################################### def connscan2(cmdname, argv): scanners = [] op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename flat_address_space = FileAddressSpace(filename,fast=True) try: flat_address_space = FileAddressSpace(filename,fast=True) except: op.error("Unable to open image file %s" % (filename)) meta_info.set_datatypes(types) # Determine the applicable address space search_address_space = find_addr_space(flat_address_space, types) # Find a dtb value if opts.base is None: sysdtb = get_dtb(search_address_space, types) else: try: sysdtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") meta_info.set_dtb(sysdtb) kaddr_space = load_pae_address_space(filename, sysdtb) if kaddr_space is None: kaddr_space = load_nopae_address_space(filename, sysdtb) meta_info.set_kas(kaddr_space) print "Local Address Remote Address Pid \n"+ \ "------------------------- ------------------------- ------ \n"; scanners.append(PoolScanConnFast2(search_address_space)) scan_addr_space(search_address_space,scanners) def sockscan2(cmdname, argv): scanners = [] op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename try: flat_address_space = FileAddressSpace(filename,fast=True) except: op.error("Unable to open image file %s" % (filename)) meta_info.set_datatypes(types) # Determine the applicable address space search_address_space = find_addr_space(flat_address_space, types) # Find a dtb value if opts.base is None: sysdtb = get_dtb(search_address_space, types) else: try: sysdtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") meta_info.set_dtb(sysdtb) kaddr_space = load_pae_address_space(filename, sysdtb) if kaddr_space is None: kaddr_space = load_nopae_address_space(filename, sysdtb) meta_info.set_kas(kaddr_space) print "PID Port Proto Create Time Offset \n"+ \ "------ ------ ------ -------------------------- ----------\n"; scanners.append(PoolScanSockFast2(search_address_space)) scan_addr_space(search_address_space,scanners) def modscan2(cmdname, argv): scanners = [] op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename try: flat_address_space = FileAddressSpace(filename,fast=True) except: op.error("Unable to open image file %s" % (filename)) meta_info.set_datatypes(types) # Determine the applicable address space search_address_space = find_addr_space(flat_address_space, types) # Find a dtb value if opts.base is None: sysdtb = get_dtb(search_address_space, types) else: try: sysdtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") meta_info.set_dtb(sysdtb) kaddr_space = load_pae_address_space(filename, sysdtb) if kaddr_space is None: kaddr_space = load_nopae_address_space(filename, sysdtb) meta_info.set_kas(kaddr_space) print "%-50s %-12s %-8s %s \n"%('File','Base', 'Size', 'Name') scanners.append((PoolScanModuleFast2(search_address_space))) scan_addr_space(search_address_space,scanners) def thrdscan2(cmdname, argv): scanners = [] op = get_standard_parser(cmdname) opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename try: flat_address_space = FileAddressSpace(filename,fast=True) except: op.error("Unable to open image file %s" % (filename)) meta_info.set_datatypes(types) # Determine the applicable address space search_address_space = find_addr_space(flat_address_space, types) # Find a dtb value if opts.base is None: sysdtb = get_dtb(search_address_space, types) else: try: sysdtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") meta_info.set_dtb(sysdtb) kaddr_space = load_pae_address_space(filename, sysdtb) if kaddr_space is None: kaddr_space = load_nopae_address_space(filename, sysdtb) meta_info.set_kas(kaddr_space) print "No. PID TID Offset \n"+ \ "---- ------ ------ ----------\n"; scanners.append((PoolScanThreadFast2(search_address_space))) scan_addr_space(search_address_space,scanners) def psscan2(cmdname, argv): scanners = [] op = get_standard_parser(cmdname) op.add_option('-d', '--dot', help='Print processes in dot format', action='store_true',dest='dot_format', default=False) opts, args = op.parse_args(argv) if (opts.filename is None) or (not os.path.isfile(opts.filename)) : op.error("File is required") else: filename = opts.filename try: flat_address_space = FileAddressSpace(filename,fast=True) except: op.error("Unable to open image file %s" % (filename)) meta_info.set_datatypes(types) # Determine the applicable address space search_address_space = find_addr_space(flat_address_space, types) # Find a dtb value if opts.base is None: sysdtb = get_dtb(search_address_space, types) else: try: sysdtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") meta_info.set_dtb(sysdtb) kaddr_space = load_pae_address_space(filename, sysdtb) if kaddr_space is None: kaddr_space = load_nopae_address_space(filename, sysdtb) meta_info.set_kas(kaddr_space) if opts.dot_format: print "digraph processtree { \n" + \ "graph [rankdir = \"TB\"];" scanners.append((PoolScanProcessDot(search_address_space))) else: print "PID PPID Time created Time exited Offset PDB Remarks\n"+ \ "------ ------ ------------------------ ------------------------ ---------- ---------- ----------------\n"; scanners.append((PoolScanProcessFast2(search_address_space))) scan_addr_space(search_address_space,scanners) if opts.dot_format: print "}" dff-1.3.0+dfsg.1/dff/modules/ram/volatility/volatility.py000066400000000000000000000067101217176075400233060ustar00rootroot00000000000000# Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_volatility_version__ = "1.0.0" import sys import os import forensics.registry as MemoryRegistry from vmodules import * from dff.api.vfs import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import typeId, Argument from dfwrapper import * #XXX fix dump options class Volatility(mfso): def __init__(self): mfso.__init__(self, "volatility") self.__disown__() self.name = "volatility" self.vfs = vfs.vfs() def start(self, args): self.node = args["file"].value() self.meta = False self.dump = False self.connections = False self.openfiles = False if args.has_key("meta"): self.meta = True if args.has_key("dump"): self.dump = True if args.has_key("connections"): self.connections = True if args.has_key("openfiles"): self.openfiles = True self.root = Node("volatility") self.root.__disown__() self.op = op(self.node) (self.addr_space, self.symtab, self.types) = load_and_identify_image(self.op, self.op) self.proclist = self.pslist() for proc in self.proclist: if self.meta: proc.getMeta() if self.dump: e = proc.dump() if e: self.res["error"] = Variant(e) if self.openfiles: proc.getOpenFiles() if self.connections: proc.getConnections() #proc.file.close() self.registerTree(self.node, self.root) def pslist(self): self.all_tasks = process_list(self.addr_space,self.types,self.symtab) lproc = [] for task in self.all_tasks: if not self.addr_space.is_valid_address(task): continue lproc.append(processus(self, task, self.op.filename, self.addr_space, self.types, self.symtab)) return lproc class volatility(Module): """Analyse a windows-xp ram dump""" def __init__(self): Module.__init__(self, "windows-XP", Volatility) self.conf.addArgument({"name": "file", "description": "Dump to analyse", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "meta", "description": "Generate meta-data for each processus", "input": Argument.Empty}) self.conf.addArgument({"name": "dump", "description": "Dump processus data content", "input": Argument.Empty}) self.conf.addArgument({"name": "openfiles", "description": "List opened files per processus", "input": Argument.Empty}) self.conf.addArgument({"name": "connections", "description": "List opened connection per processus", "input": Argument.Empty}) self.conf.addConstant({"name": "extension-type", "type" : typeId.String, "description" : "Compatible extension", "values" : ["vmem"]}) self.tags = "RAM" self.icon = ":dev_ram.png" dff-1.3.0+dfsg.1/dff/modules/ram/volatility/vsyms.py000066400000000000000000000025251217176075400222670ustar00rootroot00000000000000# Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters and Nick Petroni @license: GNU General Public License 2.0 or later @contact: awalters@komoku.com, npetroni@komoku.com @organization: Komoku, Inc. """ from forensics.symbols import * nopae_syms = SymbolTable({ 'HandleTableListHead' : 0x805617c8,\ 'PsIdleProcess' : 0x805604d4,\ 'PsActiveProcessHead' : 0x805604d8 ,\ 'PsLoadedModuleList' : 0x8055a420,\ }) pae_syms = SymbolTable({ 'HandleTableListHead' : 0x8055a548,\ 'PsIdleProcess' : 0x80559254,\ 'PsActiveProcessHead' : 0x80559258,\ 'PsLoadedModuleList' : 0x805531a0,\ }) dff-1.3.0+dfsg.1/dff/modules/ram/volatility/vtypes.py000077500000000000000000000322421217176075400224420ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Original Source: # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ xpsp2types = { \ '_LIST_ENTRY' : [ 0x8, { \ 'Flink' : [ 0x0, ['pointer', ['_LIST_ENTRY']]], \ 'Blink' : [ 0x4, ['pointer', ['_LIST_ENTRY']]], \ } ], \ '_KUSER_SHARED_DATA' : [ 0x338, { \ 'SystemTime' : [ 0x14, ['_KSYSTEM_TIME']], \ 'TimeZoneBias' : [ 0x20, ['_KSYSTEM_TIME']], \ 'SuiteMask' : [ 0x2d0, ['unsigned long']], \ 'NumberOfPhysicalPages' : [ 0x2e8, ['unsigned long']], \ } ], \ '_LARGE_INTEGER' : [ 0x8, { \ 'LowPart' : [ 0x0, ['unsigned long']], \ 'HighPart' : [ 0x4, ['long']], \ } ], \ '_KSYSTEM_TIME' : [ 0xc, { \ 'LowPart' : [ 0x0, ['unsigned long']], \ 'High1Time' : [ 0x4, ['long']], \ } ], \ '_EPROCESS' : [ 0x260, { \ 'Pcb' : [ 0x0, ['_KPROCESS']], \ 'CreateTime' : [ 0x70, ['_LARGE_INTEGER']], \ 'ExitTime' : [ 0x78, ['_LARGE_INTEGER']], \ 'UniqueProcessId' : [ 0x84, ['pointer', ['void']]], \ 'ActiveProcessLinks' : [ 0x88, ['_LIST_ENTRY']], \ 'VirtualSize' : [ 0xb0, ['unsigned long']], \ 'ObjectTable' : [ 0xc4, ['pointer', ['_HANDLE_TABLE']]], \ 'WorkingSetLock' : [ 0xcc, ['_FAST_MUTEX']], \ 'AddressCreationLock' : [ 0xf0, ['_FAST_MUTEX']], \ 'VadRoot' : [ 0x11c, ['pointer', ['void']]], \ 'InheritedFromUniqueProcessId' : [ 0x14c, ['pointer', ['void']]], \ 'ImageFileName' : [ 0x174, ['array', 16,['unsigned char']]], \ 'ThreadListHead' : [ 0x190, ['_LIST_ENTRY']], \ 'ActiveThreads' : [ 0x1a0, ['unsigned long']], \ 'Peb' : [ 0x1b0, ['pointer', ['_PEB']]], \ 'ExitStatus' : [ 0x24c, ['long']], \ } ], \ '_KPROCESS' : [ 0x6c, { \ 'Header' : [ 0x0, ['_DISPATCHER_HEADER']], \ 'DirectoryTableBase' : [ 0x18, ['array', 2,['unsigned long']]], \ } ], \ '_PEB' : [ 0x210, { \ 'ImageBaseAddress' : [ 0x8, ['pointer', ['void']]], \ 'Ldr' : [ 0xc, ['pointer', ['_PEB_LDR_DATA']]], \ 'ProcessParameters' : [ 0x10, ['pointer', ['_RTL_USER_PROCESS_PARAMETERS']]], \ 'NumberOfProcessors' : [ 0x64, ['unsigned long']], \ 'OSMajorVersion' : [ 0xa4, ['unsigned long']], \ 'OSMinorVersion' : [ 0xa8, ['unsigned long']], \ 'OSBuildNumber' : [ 0xac, ['unsigned short']], \ 'CSDVersion' : [ 0x1f0, ['_UNICODE_STRING']], \ } ], \ '_RTL_USER_PROCESS_PARAMETERS' : [ 0x290, { \ 'CommandLine' : [ 0x40, ['_UNICODE_STRING']], \ } ], \ '_UNICODE_STRING' : [ 0x8, { \ 'Length' : [ 0x0, ['unsigned short']], \ 'Buffer' : [ 0x4, ['pointer', ['unsigned short']]], \ } ], \ '_PEB_LDR_DATA' : [ 0x28, { \ 'InLoadOrderModuleList' : [ 0xc, ['_LIST_ENTRY']], \ } ], \ '_LDR_MODULE' : [ 0x48, { \ 'InLoadOrderModuleList' : [ 0x0, ['_LIST_ENTRY']], \ 'BaseAddress' : [ 0x18, ['pointer', ['void']]], \ 'SizeOfImage' : [ 0x20, ['unsigned long']], \ 'FullDllName' : [ 0x24, ['_UNICODE_STRING']], \ 'ModuleName' : [ 0x2c, ['_UNICODE_STRING']], \ } ], \ '_ADDRESS_OBJECT' : [ 0x68, { \ 'Next' : [ 0x0, ['pointer', ['_ADDRESS_OBJECT']]], \ 'LocalIpAddress' : [ 0x0c, ['unsigned long']], \ 'LocalPort' : [ 0x30, ['unsigned short']], \ 'Protocol' : [ 0x32, ['unsigned short']], \ 'Pid' : [ 0x148, ['unsigned long']], \ 'CreateTime' : [ 0x158, ['_LARGE_INTEGER']], \ } ], \ '_TCPT_OBJECT' : [ 0x20, { \ 'Next' : [ 0x0, ['pointer', ['_TCPT_OBJECT']]], \ 'RemoteIpAddress' : [ 0xc, ['unsigned long']], \ 'LocalIpAddress' : [ 0x10, ['unsigned long']], \ 'RemotePort' : [ 0x14, ['unsigned short']], \ 'LocalPort' : [ 0x16, ['unsigned short']], \ 'Pid' : [ 0x18, ['unsigned long']], \ } ], \ '_HANDLE_TABLE' : [ 0x44, { \ 'TableCode' : [ 0x0, ['unsigned long']], \ 'UniqueProcessId' : [ 0x8, ['pointer', ['void']]], \ 'HandleTableList' : [ 0x1c, ['_LIST_ENTRY']], \ 'HandleCount' : [ 0x3c, ['long']], \ } ], \ '_HANDLE_TABLE_ENTRY' : [ 0x8, { \ 'Object' : [ 0x0, ['pointer', ['void']]], \ } ], \ '_OBJECT_HEADER' : [ 0x20, { \ 'Type' : [ 0x8, ['pointer', ['_OBJECT_TYPE']]], \ 'Body' : [ 0x18, ['_QUAD']], \ } ], \ '_OBJECT_TYPE' : [ 0x190, { \ 'Name' : [ 0x40, ['_UNICODE_STRING']], \ } ], \ '_FILE_OBJECT' : [ 0x70, { \ 'Type' : [ 0x0, ['short']], \ 'FileName' : [ 0x30, ['_UNICODE_STRING']], \ } ], \ '_KPCR' : [ 0xd70, { \ 'KdVersionBlock' : [ 0x34, ['pointer', ['void']]], \ } ], \ '_KDDEBUGGER_DATA32' : [ 0x44, { \ 'PsLoadedModuleList' : [ 0x70, ['unsigned long']], \ 'PsActiveProcessHead' : [ 0x78, ['unsigned long']], \ } ], \ '_KDDEBUGGER_DATA64' : [ 0x44, { \ 'PsLoadedModuleList' : [ 0x48, ['unsigned long']], \ 'PsActiveProcessHead' : [ 0x50, ['unsigned long']], \ 'MmPfnDatabase' : [ 0xC0, ['unsigned long']], \ } ], \ '_DBGKD_GET_VERSION64' : [ 0x2a, { \ 'DebuggerDataList' : [ 0x20, ['unsigned long']], \ } ], \ '_MMVAD_LONG' : [ 0x34, { \ 'StartingVpn' : [ 0x0, ['unsigned long']], \ 'EndingVpn' : [ 0x4, ['unsigned long']], \ 'Parent' : [ 0x8, ['pointer', ['_MMVAD']]], \ 'LeftChild' : [ 0xc, ['pointer', ['_MMVAD']]], \ 'RightChild' : [ 0x10, ['pointer', ['_MMVAD']]], \ 'u' : [ 0x14, ['__unnamed']], \ 'ControlArea' : [ 0x18, ['pointer', ['_CONTROL_AREA']]], \ 'FirstPrototypePte' : [ 0x1c, ['pointer', ['_MMPTE']]], \ 'LastContiguousPte' : [ 0x20, ['pointer', ['_MMPTE']]], \ 'u2' : [ 0x24, ['__unnamed']], \ 'u3' : [ 0x28, ['__unnamed']], \ 'u4' : [ 0x30, ['__unnamed']], \ } ], \ '_MMVAD' : [ 0x28, { \ 'StartingVpn' : [ 0x0, ['unsigned long']], \ 'EndingVpn' : [ 0x4, ['unsigned long']], \ 'Parent' : [ 0x8, ['pointer', ['_MMVAD']]], \ 'LeftChild' : [ 0xc, ['pointer', ['_MMVAD']]], \ 'RightChild' : [ 0x10, ['pointer', ['_MMVAD']]], \ 'u' : [ 0x14, ['__unnamed']], \ 'ControlArea' : [ 0x18, ['pointer', ['_CONTROL_AREA']]], \ 'FirstPrototypePte' : [ 0x1c, ['pointer', ['_MMPTE']]], \ 'LastContiguousPte' : [ 0x20, ['pointer', ['_MMPTE']]], \ 'u2' : [ 0x24, ['__unnamed']], \ } ], \ '_MMVAD_SHORT' : [ 0x18, { \ 'StartingVpn' : [ 0x0, ['unsigned long']], \ 'EndingVpn' : [ 0x4, ['unsigned long']], \ 'Parent' : [ 0x8, ['pointer', ['_MMVAD']]], \ 'LeftChild' : [ 0xc, ['pointer', ['_MMVAD']]], \ 'RightChild' : [ 0x10, ['pointer', ['_MMVAD']]], \ 'u' : [ 0x14, ['__unnamed']], \ } ], \ '_CONTROL_AREA' : [ 0x30, { \ 'Segment' : [ 0x0, ['pointer', ['_SEGMENT']]], \ 'DereferenceList' : [ 0x4, ['_LIST_ENTRY']], \ 'NumberOfSectionReferences' : [ 0xc, ['unsigned long']], \ 'NumberOfPfnReferences' : [ 0x10, ['unsigned long']], \ 'NumberOfMappedViews' : [ 0x14, ['unsigned long']], \ 'NumberOfSubsections' : [ 0x18, ['unsigned short']], \ 'FlushInProgressCount' : [ 0x1a, ['unsigned short']], \ 'NumberOfUserReferences' : [ 0x1c, ['unsigned long']], \ 'u' : [ 0x20, ['__unnamed']], \ 'FilePointer' : [ 0x24, ['pointer', ['_FILE_OBJECT']]], \ 'WaitingForDeletion' : [ 0x28, ['pointer', ['_EVENT_COUNTER']]], \ 'ModifiedWriteCount' : [ 0x2c, ['unsigned short']], \ 'NumberOfSystemCacheViews' : [ 0x2e, ['unsigned short']], \ } ], \ '_POOL_HEADER' : [ 0x8, { \ 'Ulong1' : [ 0x0, ['unsigned long']], \ 'ProcessBilled' : [ 0x4, ['pointer', ['_EPROCESS']]], \ 'PoolTag' : [ 0x4, ['unsigned long']], \ 'AllocatorBackTraceIndex' : [ 0x4, ['unsigned short']], \ 'PoolTagHash' : [ 0x6, ['unsigned short']], \ } ], \ '_FAST_MUTEX' : [ 0x20, { \ 'Event' : [ 0xc, ['_KEVENT']], \ } ], \ '_KEVENT' : [ 0x10, { \ 'Header' : [ 0x0, ['_DISPATCHER_HEADER']], \ } ], \ '_DISPATCHER_HEADER' : [ 0x10, { \ 'Type' : [ 0x0, ['unsigned char']], \ 'Size' : [ 0x2, ['unsigned char']], \ } ], \ '_ETHREAD' : [ 0x258, { \ 'Tcb' : [ 0x0, ['_KTHREAD']], \ 'Cid' : [ 0x1ec, ['_CLIENT_ID']], \ 'LpcReplySemaphore' : [ 0x1f4, ['_KSEMAPHORE']], \ 'ThreadsProcess' : [ 0x220, ['pointer', ['_EPROCESS']]], \ 'StartAddress' : [ 0x224, ['pointer', ['void']]], \ } ], \ '_CLIENT_ID' : [ 0x8, { \ 'UniqueProcess' : [ 0x0, ['pointer', ['void']]], \ 'UniqueThread' : [ 0x4, ['pointer', ['void']]], \ } ], \ '_KTHREAD' : [ 0x1c0, { \ 'Header' : [ 0x0, ['_DISPATCHER_HEADER']], \ 'Timer' : [ 0xf0, ['_KTIMER']], \ 'SuspendSemaphore' : [ 0x19c, ['_KSEMAPHORE']], \ } ], \ '_KTIMER' : [ 0x28, { \ 'Header' : [ 0x0, ['_DISPATCHER_HEADER']], \ } ], \ '_KSEMAPHORE' : [ 0x14, { \ 'Header' : [ 0x0, ['_DISPATCHER_HEADER']], \ } ], \ '_PHYSICAL_MEMORY_RUN' : [ 0x8, { \ 'BasePage' : [ 0x0, ['unsigned long']], \ 'PageCount' : [ 0x4, ['unsigned long']], \ } ], \ '_PHYSICAL_MEMORY_DESCRIPTOR' : [ 0x10, { \ 'NumberOfRuns' : [ 0x0, ['unsigned long']], \ 'NumberOfPages' : [ 0x4, ['unsigned long']], \ 'Run' : [ 0x8, ['array', 1,['_PHYSICAL_MEMORY_RUN']]], \ } ], \ '_DMP_HEADER' : [ 0x1000, { \ 'Signature' : [ 0x0, ['array', 4,['unsigned char']]], \ 'ValidDump' : [ 0x4, ['array', 4,['unsigned char']]], \ 'MajorVersion' : [ 0x8, ['unsigned long']], \ 'MinorVersion' : [ 0xc, ['unsigned long']], \ 'DirectoryTableBase' : [ 0x10, ['unsigned long']], \ 'PfnDataBase' : [ 0x14, ['unsigned long']], \ 'PsLoadedModuleList' : [ 0x18, ['unsigned long']], \ 'PsActiveProcessHead' : [ 0x1c, ['unsigned long']], \ 'MachineImageType' : [ 0x20, ['unsigned long']], \ 'NumberProcessors' : [ 0x24, ['unsigned long']], \ 'BugCheckCode' : [ 0x28, ['unsigned long']], \ 'BugCheckCodeParameter' : [ 0x2c, ['array', 4,['unsigned long']]], \ 'VersionUser' : [ 0x3c, ['array', 32,['unsigned char']]], \ 'PaeEnabled' : [ 0x5c, ['unsigned char']], \ 'KdSecondaryVersion' : [ 0x5d, ['unsigned char']], \ 'VersionUser' : [ 0x5e, ['array', 2,['unsigned char']]], \ 'KdDebuggerDataBlock' : [ 0x60, ['unsigned long']], \ 'PhysicalMemoryBlockBuffer' : [ 0x64, ['_PHYSICAL_MEMORY_DESCRIPTOR']], \ 'ContextRecord' : [ 0x320, ['array', 1200,['unsigned char']]], \ 'Exception' : [ 0x7d0, ['_EXCEPTION_RECORD32']], \ 'Comment' : [ 0x820, ['array', 128,['unsigned char']]], \ 'DumpType' : [ 0xf88, ['unsigned long']], \ 'MiniDumpFields' : [ 0xf8c, ['unsigned long']], \ 'SecondaryDataState' : [ 0xf90, ['unsigned long']], \ 'ProductType' : [ 0xf94, ['unsigned long']], \ 'SuiteMask' : [ 0xf98, ['unsigned long']], \ 'WriterStatus' : [ 0xf9c, ['unsigned long']], \ 'RequiredDumpSpace' : [ 0xfa0, ['unsigned __int64']], \ 'SystemUpTime' : [ 0xfb8, ['unsigned __int64']], \ 'SystemTime' : [ 0xfc0, ['unsigned __int64']], \ 'reserved3' : [ 0xfc8, ['array', 56,['unsigned char']]], \ } ], \ '_TEB' : [ 0xfb8, { \ 'ProcessEnvironmentBlock' : [ 0x30, ['pointer', ['_PEB']]], \ } ], \ '_KPROCESSOR_STATE' : [ 0x320, { \ 'SpecialRegisters' : [ 0x2cc, ['_KSPECIAL_REGISTERS']], \ } ], \ '_KSPECIAL_REGISTERS' : [ 0x54, { \ 'Cr0' : [ 0x0, ['unsigned long']], \ 'Cr3' : [ 0x8, ['unsigned long']], \ 'Cr4' : [ 0xc, ['unsigned long']], \ 'Gdtr' : [ 0x28, ['_DESCRIPTOR']], \ } ], \ '_DESCRIPTOR' : [ 0x8, { \ 'Pad' : [ 0x0, ['unsigned short']], \ 'Limit' : [ 0x2, ['unsigned short']], \ 'Base' : [ 0x4, ['unsigned long']], \ } ], \ '_CM_KEY_BODY' : [ 0x44, { \ 'Type' : [ 0x0, ['unsigned long']], \ 'KeyControlBlock' : [ 0x4, ['pointer', ['_CM_KEY_CONTROL_BLOCK']]], \ } ], \ '_CM_KEY_CONTROL_BLOCK' : [ 0x48, { \ 'ParentKcb' : [ 0x18, ['pointer', ['_CM_KEY_CONTROL_BLOCK']]], \ 'NameBlock' : [ 0x1c, ['pointer', ['_CM_NAME_CONTROL_BLOCK']]], \ 'KcbLastWriteTime' : [ 0x38, ['_LARGE_INTEGER']], \ } ], \ '_CM_NAME_CONTROL_BLOCK' : [ 0x10, { \ 'NameLength' : [ 0xc, ['unsigned short']], \ 'Name' : [ 0xe, ['array', 1,['unsigned short']]], \ } ], \ '_IMAGE_DOS_HEADER' : [ 0x40, { \ 'e_lfanew' : [ 0x3c, ['long']], \ } ], \ '_IMAGE_NT_HEADERS' : [ 0xf8, { \ 'FileHeader' : [ 0x4, ['_IMAGE_FILE_HEADER']], \ 'OptionalHeader' : [ 0x18, ['_IMAGE_OPTIONAL_HEADER']], \ } ], \ '_IMAGE_OPTIONAL_HEADER' : [ 0xe0, { \ 'SectionAlignment' : [ 0x20, ['unsigned long']], \ 'FileAlignment' : [ 0x24, ['unsigned long']], \ 'SizeOfImage' : [ 0x38, ['unsigned long']], \ 'SizeOfHeaders' : [ 0x3c, ['unsigned long']], \ } ], \ '_IMAGE_FILE_HEADER' : [ 0x14, { \ 'NumberOfSections' : [ 0x2, ['unsigned short']], \ 'SizeOfOptionalHeader' : [ 0x10, ['unsigned short']], \ } ], \ '__misc' : [ 0x4, { 'PhysicalAddress' : [ 0x0, ['unsigned long']], 'VirtualSize' : [ 0x0, ['unsigned long']], } ], '_IMAGE_SECTION_HEADER' : [ 0x28, { \ 'Name' : [ 0x0, ['array', 8,['unsigned char']]], \ 'Misc' : [ 0x8, ['__misc']], 'VirtualAddress' : [ 0xc, ['unsigned long']], \ 'SizeOfRawData' : [ 0x10, ['unsigned long']], \ 'PointerToRawData' : [ 0x14, ['unsigned long']], \ } ], \ } dff-1.3.0+dfsg.1/dff/modules/ram/volatility/vutils.py000066400000000000000000000202101217176075400224230ustar00rootroot00000000000000# Volatility # Copyright (C) 2007,2008 Volatile Systems # # Original Source: # Volatools Basic # Copyright (C) 2007 Komoku, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: AAron Walters @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems """ import optparse from vtypes import xpsp2types as types from vsyms import * from forensics.win32.tasks import find_dtb from forensics.win32.tasks import find_csdversion from forensics.addrspace import * from forensics.x86 import * from forensics.win32.crash_addrspace import * from forensics.win32.hiber_addrspace import * from dff.api.vfs import * ################################### # Helper functions ################################### def get_standard_parser(cmdname): """ Function generates a parser with common options for all tools. """ op = optparse.OptionParser(usage='%s [options] (see --help)' % (cmdname)) op.add_option('-f', '--file', help='(required) XP SP2 Image file', action='store', type='string', dest='filename') op.add_option('-b', '--base', help='(optional, otherwise best guess is made) Physical offset (in hex) of directory table base', action='store', type='string', dest='base') op.add_option('-t', '--type', help='(optional, default="auto") Identify the image type (pae, nopae, auto)', action='store', type='string', dest='type') return op def guess_dtb(filename, op): """ Function performs a linear scan in search of a potential valid XP SP2 DTB """ try: flat_address_space = FileAddressSpace(filename) except: op.error("Unable to open image file %s" % (filename)) addr_space = find_addr_space(flat_address_space, types) sysdtb = get_dtb(addr_space, types) return sysdtb def load_file_address_space(op, opts): """ Function checks the parsed options for a valid image and returns the flat (physical) file address space object. """ filename = None if opts.filename is None: op.error("Image file required") else: filename = opts.filename try: addr_space = FileAddressSpace(filename) except: op.error("Invalid image file %s" % (filename)) return addr_space def load_pae_address_space(filename, dtb): try: if is_crash_dump(filename) == True: linAS = FileAddressSpace(filename) phyAS = WindowsCrashDumpSpace32(linAS,0,0) # Currently we only support full crash dumps if not phyAS.get_dumptype() == 1: return None elif is_hiberfil(filename) == True: linAS = FileAddressSpace(filename) phyAS = WindowsHiberFileSpace32(linAS,0,0) else: phyAS = FileAddressSpace(filename) addr_space = IA32PagedMemoryPae(phyAS, dtb) if not addr_space.is_valid_address(pae_syms.lookup('PsLoadedModuleList')): addr_space = None except: addr_space = None return addr_space def load_nopae_address_space(filename, dtb): try: if is_crash_dump(filename) == True: linAS = FileAddressSpace(filename) phyAS = WindowsCrashDumpSpace32(linAS,0,0) # Currently we only support full crash dumps if not phyAS.get_dumptype() == 1: return None elif is_hiberfil(filename) == True: linAS = FileAddressSpace(filename) phyAS = WindowsHiberFileSpace32(linAS,0,0) else: phyAS = FileAddressSpace(filename) addr_space = IA32PagedMemory(phyAS, dtb) if not addr_space.is_valid_address(nopae_syms.lookup('PsLoadedModuleList')): addr_space = None except: addr_space = None return addr_space def load_and_identify_image(op, opts, verbose=False): """ Function checks the parsed options for a valid image and DTB and returns (address space, symbol table, types) tuple for that image. """ dtb = None filename = None addr_space = None symtab = None if opts.filename is None: op.error("Image file required") else: filename = opts.filename if not opts.base is None: try: dtb = int(opts.base, 16) except: op.error("Directory table base must be a hexidecimal number.") if not opts.type is None: if opts.type == 'nopae': symtab = nopae_syms elif opts.type == 'pae': symtab = pae_syms elif opts.type != 'auto': op.error("-t option must be 'pae', 'nopae', or 'auto'") if dtb is None: dtb = guess_dtb(filename, op) if dtb is None and not verbose: op.error("Unable to locate valid DTB in image.") if symtab == nopae_syms: addr_space = load_nopae_address_space(filename, dtb) elif symtab == pae_syms: addr_space = load_pae_address_space(filename, dtb) else: addr_space = load_pae_address_space(filename, dtb) if not addr_space is None: symtab = pae_syms else: addr_space = load_nopae_address_space(filename, dtb) if not addr_space is None: symtab = nopae_syms if addr_space is None or symtab is None: if verbose: print "%25s %s" % ("Image Name:", filename) print "%25s %s" % ("Image Type:", "UNKNOWN") else: op.error("Unable to load image. Possible causes: invalid dtb, wrong image type, unsupported image type.") elif verbose: ImageType = find_csdversion(addr_space, types) if not ImageType: ImageType = "" print "%25s %s" % ("Image Name:", filename) print "%25s %s" % ("Image Type:", ImageType) if symtab == pae_syms: print "%25s %s" % ("VM Type:", "pae") else: print "%25s %s" % ("VM Type:", "nopae") print "%25s 0x%x" % ("DTB:", dtb) return (addr_space, symtab, types) def is_crash_dump(filename): """ Checks if the file is a Crash Dump """ # fhandle = open(filename, 'rb') fhandle = vfs.vfs().open(filename) buffer = fhandle.read(8) if (buffer == "PAGEDUMP"): return True return False def is_hiberfil(filename): """ Checks if the file is a Hiberfile """ #fhandle = open(filename, 'rb') fhandle = vfs.vfs().open(filename) buffer = fhandle.read(4) if (buffer == "hibr"): return True return False def find_addr_space(addr_space,types): """ Determine what types of address space (if any) needs to be overlayed. """ if is_crash_dump(addr_space.fname) == True: addr_space = WindowsCrashDumpSpace32(addr_space,0,0) elif is_hiberfil(addr_space.fname) == True: addr_space = WindowsHiberFileSpace32(addr_space,0,0) return addr_space def get_dtb(addr_space,types): if isinstance(addr_space, WindowsCrashDumpSpace32): dtb = addr_space.get_directorytablebase() elif isinstance(addr_space, WindowsHiberFileSpace32): dtb = addr_space.CR3 else: dtb = find_dtb(addr_space, types) return dtb def PrintWithDefaults(format,args,defaults={}): argslist = list(args) if len(defaults) > 0: for index, item in enumerate(argslist): if item == None: if index in defaults: argslist[index] = defaults[index] args = tuple(argslist) output = format%args print output dff-1.3.0+dfsg.1/dff/modules/search/000077500000000000000000000000001217176075400170165ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/search/CMakeLists.txt000066400000000000000000000012161217176075400215560ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file( __init__.py ) add_subdirectory(carver) dff-1.3.0+dfsg.1/dff/modules/search/__init__.py000066400000000000000000000011671217176075400211340ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __all__ = ['carver', 'indexer'] dff-1.3.0+dfsg.1/dff/modules/search/carver/000077500000000000000000000000001217176075400203005ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/search/carver/CMakeLists.txt000066400000000000000000000014731217176075400230450ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin dff_cpp_module(CARVER CPP_FILES carver.cpp INCLUDE_DIRS ${CMAKE_HOME_DIRECTORY}/dff/api/search/ LINK_LIBRARIES exceptions types vfs SWIG_FILE carver.i EXTRA_FILES __init__.py carvergui.py carverui.py predef.py userdef.py process.py typeSelection.py utils.py ) dff-1.3.0+dfsg.1/dff/modules/search/carver/__init__.py000066400000000000000000000011001217176075400224010ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['utils'] dff-1.3.0+dfsg.1/dff/modules/search/carver/carver.cpp000066400000000000000000000255351217176075400223000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "carver.hpp" #include #include #include // Next gen: process like scalpel // for each BUFFER // for each (header => footer) // find() // implies to preprocess each shift table // Test if faster or not CarvedNode::CarvedNode(std::string name, uint64_t size, Node* parent, fso* fsobj): Node(name, size, parent, fsobj) { } CarvedNode::~CarvedNode() { } void CarvedNode::setStart(uint64_t start) { this->__start = start; } void CarvedNode::setOrigin(Node* origin) { this->__origin = origin; } void CarvedNode::fileMapping(class FileMapping* fm) { fm->push(0, this->size(), this->__origin, this->__start); } Carver::Carver(): mfso("carver") { //res = new results("empty"); } Carver::~Carver() { // delete this->header; //delete this->footer; } uint64_t Carver::tell() { return this->ifile->tell(); } void Carver::Event(event* e) { if (e != NULL && e->type == Carver::Stop) this->stop = true; } void Carver::start(std::map args) { event* e1; this->inode = args["file"]->value(); this->ifile = this->inode->open(); this->createContexts(args["patterns"]->value< std::list >()); this->root = new Node("carved", 0, NULL, this); this->root->setDir(); this->ifile->seek(args["start-offset"]->value(), 0); this->mapper(); e1 = new event; e1->type = Carver::EndOfProcessing; e1->value = NULL; this->notify(e1); delete e1; } int Carver::Read(char *buffer, unsigned int size) { try { return (this->ifile->read(buffer, size)); } catch (vfsError e) { return -1; } } std::string Carver::needleToHexString(unsigned char* needle, int size) { int i; std::stringstream ss; for (i = 0; i != size; i++) { ss << std::setw(2) << std::setfill('0') << std::hex << static_cast(needle[i]); ss << " "; } return ss.str(); } description* Carver::createDescription(std::map ctx) { description* descr; std::map cpattern; descr = new description; descr->type = ctx["filetype"]->toCArray(); cpattern = ctx["header"]->value >(); descr->header = new pattern; descr->header->needle = (unsigned char*)(cpattern["needle"]->toCArray()); descr->header->size = cpattern["size"]->value(); descr->header->wildcard = '\0';//cpattern["wildcard"]->value(); cpattern = ctx["footer"]->value >(); descr->footer = new pattern; descr->footer->needle = (unsigned char*)(cpattern["needle"]->toCArray()); descr->footer->size = cpattern["size"]->value(); descr->footer->wildcard = '\0';//cpattern["wildcard"]->value(); descr->window = ctx["window"]->value(); descr->aligned = ctx["aligned"]->value(); return descr; } void Carver::createContexts(std::list patterns) { std::list::iterator it; std::map vpattern; context *cctx; unsigned int i; description* descr; unsigned int ctxsize; this->aligned = aligned; ctxsize = this->ctx.size(); if (ctxsize) for (i = 0; i != ctxsize; i++) { free(this->ctx[i]->headerBcs); free(this->ctx[i]->footerBcs); this->ctx[i]->headers.clear(); this->ctx[i]->footers.clear(); delete this->ctx[i]->descr; delete this->ctx[i]; } this->ctx.clear(); if (patterns.size() > 0) { this->stop = false; this->maxNeedle = 0; for (it = patterns.begin(); it != patterns.end(); it++) { cctx = new context; descr = this->createDescription((*it)->value< std::map >()); cctx->descr = descr; cctx->headerBcs = this->bm->generateBcs(descr->header); cctx->footerBcs = this->bm->generateBcs(descr->footer); if (this->maxNeedle < descr->header->size) this->maxNeedle = descr->header->size; if (this->maxNeedle < descr->footer->size) this->maxNeedle = descr->footer->size; this->ctx.push_back(cctx); } } } void Carver::mapper() { unsigned int i; char *buffer; int bytes_read; int offset; event* e; event* e1; uint64_t total_headers; uint64_t offpos; std::stringstream percent; unsigned int ctxsize; e = new event; e1 = new event; buffer = (char*)malloc(sizeof(char) * BUFFSIZE); int seek; e->type = Carver::Position; e1->type = Carver::Matches; total_headers = 0; ctxsize = this->ctx.size(); while (((bytes_read = this->Read(buffer, BUFFSIZE)) > 0) && (!this->stop)) { offpos = this->tell(); percent.str(""); percent << ((offpos * 100) / this->inode->size()) << " %"; this->stateinfo = percent.str(); for (i = 0; i != ctxsize; i++) { offset = this->bm->search((unsigned char*)buffer, bytes_read, this->ctx[i]->descr->header, this->ctx[i]->headerBcs); seek = offset; while (offset != -1) { if (this->ctx[i]->descr->aligned) { if (((this->tell() - bytes_read + seek) % 512) == 0) total_headers += 1; } else total_headers += 1; this->ctx[i]->headers.push_back(this->tell() - bytes_read + seek); seek += ctx[i]->descr->header->size; if (seek + ctx[i]->descr->header->size >= (uint64_t)bytes_read) break; else { offset = this->bm->search((unsigned char*)(buffer+seek), bytes_read - seek, this->ctx[i]->descr->header, this->ctx[i]->headerBcs); seek += offset; } } if (this->ctx[i]->descr->footer->size != 0) { offset = this->bm->search((unsigned char*)buffer, bytes_read, this->ctx[i]->descr->footer, this->ctx[i]->footerBcs); seek = offset; while (offset != -1) { this->ctx[i]->footers.push_back(this->tell() - bytes_read + seek + this->ctx[i]->descr->footer->size); seek += ctx[i]->descr->footer->size; offpos = this->tell(); if (seek + ctx[i]->descr->footer->size >= (uint64_t)bytes_read) break; else { offset = this->bm->search((unsigned char*)(buffer+seek), bytes_read - seek, this->ctx[i]->descr->footer, this->ctx[i]->footerBcs); seek += offset; } } } e1->value = new Variant(total_headers); this->notify(e1); } e->value = new Variant(this->tell()); this->notify(e); if (bytes_read == BUFFSIZE) this->ifile->seek(this->tell() - this->maxNeedle, 0); } free(buffer); this->createTree(); } std::string Carver::generateName(uint64_t start, uint64_t end) { std::ostringstream os; os << start << "-" << end; return os.str(); } void Carver::createNode(Node *parent, uint64_t start, uint64_t end) { CarvedNode* cn; std::stringstream name; name << "0x" << std::setw(2) << std::setfill('0') << std::hex << start; name << "-"; name << "0x" << std::setw(2) << std::setfill('0') << std::hex << end; cn = new CarvedNode(name.str(), end-start, parent, this); cn->setFile(); cn->setStart(start); cn->setOrigin(this->inode); } unsigned int Carver::createWithoutFooter(Node *parent, std::vector *headers, unsigned int max, bool aligned) { unsigned int i; unsigned int hlen; unsigned int total; hlen = headers->size(); total = 0; for (i = 0; i != hlen; i++) { if (aligned) { if (((*headers)[i] % 512) == 0) this->createNode(parent, (*headers)[i], (*headers)[i] + (uint64_t)max); total += 1; } else { this->createNode(parent, (*headers)[i], (*headers)[i] + (uint64_t)max); total += 1; } } return total; } unsigned int Carver::createWithFooter(Node *parent, std::vector *headers, std::vector *footers, unsigned int max, bool aligned) { unsigned int i; unsigned int j; unsigned int flen; unsigned int hlen; bool found; unsigned int total; hlen = headers->size(); flen = footers->size(); j = 0; total = 0; for (i = 0; i != hlen; i++) { found = false; while ((j != flen) && (!found)) { if ((*footers)[j] > (*headers)[i]) found = true; else j++; } if (aligned) { if (((*headers)[i] % 512) == 0) { if (found && ((*footers)[j] > (*headers)[i])) this->createNode(parent, (*headers)[i], (*footers)[j]); else this->createNode(parent, (*headers)[i], (*headers)[i] + (uint64_t)max); total += 1; } } else { if (found && ((*footers)[j] > (*headers)[i])) this->createNode(parent, (*headers)[i], (*footers)[j]); else this->createNode(parent, (*headers)[i], (*headers)[i] + (uint64_t)max); total += 1; } } return total; } void Carver::fillResult(context* ctx) { std::stringstream totalheaders; std::stringstream totalfooters; std::map::iterator mit; std::list vlistptr; totalheaders.str(""); totalheaders << "Header " << ctx->headers.size() << " (pattern " << this->needleToHexString(ctx->descr->header->needle, ctx->descr->header->size) << ") "; if ((mit = this->res.find(std::string(ctx->descr->type))) != this->res.end()) { mit->second->convert(typeId::List, &vlistptr); totalheaders << ctx->headers.size() << " header(s) found"; } else { std::list vlist; vlist.push_back(Variant_p(new Variant(totalheaders.str()))); this->res[std::string(ctx->descr->type)] = Variant_p(new Variant(vlist)); this->res[std::string(ctx->descr->type)]->convert(typeId::List, &vlistptr); vlistptr.push_back(Variant_p(new Variant(totalheaders.str()))); this->res[std::string(ctx->descr->type)] = Variant_p(new Variant(vlistptr)); } std::cout << vlistptr.size() << std::endl; } int Carver::createTree() { context *ctx; Node *parent; unsigned int max; unsigned int clen; unsigned int i; clen = this->ctx.size(); if (clen > 0) this->registerTree(this->inode, this->root); for (i = 0; i != clen; i++) { ctx = this->ctx[i]; if (ctx->headers.size() > 0) { parent = new Node(ctx->descr->type, 0, NULL, this); parent->setDir(); if (ctx->descr->window > 0) max = ctx->descr->window; else max = BUFFSIZE; if (ctx->footers.size() > 0) this->createWithFooter(parent, &(ctx->headers), &(ctx->footers), max, ctx->descr->aligned); else this->createWithoutFooter(parent, &(ctx->headers), max, ctx->descr->aligned); //this->fillResult(ctx); this->registerTree(this->root, parent); } } return 0; } dff-1.3.0+dfsg.1/dff/modules/search/carver/carver.hpp000066400000000000000000000045321217176075400222770ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __CARVER_HPP__ #define __CARVER_HPP__ #include "mfso.hpp" #include "node.hpp" #include "eventhandler.hpp" #include "common.hpp" //Let the possibility to modify the matching footer or to dynamically set the window //representing the carved file. class CarvedNode: public Node { private: uint64_t __start; Node* __origin; public: CarvedNode(std::string name, uint64_t size, Node* parent, fso* fsobj); ~CarvedNode(); void setStart(uint64_t start); void setOrigin(Node* origin); virtual void fileMapping(class FileMapping* fm); }; class Carver: public mfso, public EventHandler { private: Node *inode; Node *root; VFile *ifile; BoyerMoore *bm; std::vector ctx; unsigned int maxNeedle; bool aligned; bool stop; std::string Results; bool createFile(); void createNode(Node *parent, uint64_t start, uint64_t end); unsigned int createWithoutFooter(Node *parent, std::vector *headers, unsigned int max, bool aligned); unsigned int createWithFooter(Node *parent, std::vector *headers, std::vector *footers, uint32_t max, bool aligned); int createTree(); void mapper(); std::string generateName(uint64_t start, uint64_t end); description* createDescription(std::map); void createContexts(std::list patterns); void fillResult(context* ctx); std::string needleToHexString(unsigned char* needle, int size); public: enum EventTypes { Position = 0x01, Matches = 0x02, EndOfProcessing = 0x03, Stop = 0x04 }; Carver(); ~Carver(); uint64_t tell(); virtual void start(std::map args); virtual void Event(event* e); int Read(char *buffer, unsigned int size); }; #endif dff-1.3.0+dfsg.1/dff/modules/search/carver/carver.i000066400000000000000000000131101217176075400217300ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic B. */ #include "pyrun.swg" %module CARVER %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "carver.hpp" #include "common.hpp" #include "rootnode.hpp" #include "../../../api/search/pattern.hpp" %} %import "../../../api/vfs/libvfs.i" %typemap(in) unsigned char * { if (!PyString_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); return NULL; } else { $1 = (unsigned char*)PyString_AsString($input); } } %typemap(in) unsigned char { if (!PyString_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); return NULL; } else { if (PyString_Size($input) == 1) { $1 = (unsigned char)PyString_AsString($input)[0]; } else { $1 = (unsigned char)PyString_AsString($input)[0]; } } } %include "carver.hpp" namespace std { %template(listDescr) list; }; %pythoncode %{ __dff_module_carver_version__ = "1.0.0" from dff.api.module.module import Module from dff.api.types.libtypes import Argument, typeId, Variant class CARVER(Module): """Search for header and footer of a selected mime-type in a node and create the corresponding file. You can use this modules for finding deleted data or data in slack space or in an unknown file system.""" def __init__(self): Module.__init__(self, 'carver', Carver) self.conf.addArgument({"name": "file", "description": "file used by carver", "input": Argument.Required|Argument.Single|typeId.Node}) needle = Argument("needle", Argument.Required|Argument.Single|typeId.String, "represents the needle to search in the haystack") needle.thisown = False wildcard = Argument("wildcard", Argument.Required|Argument.Single|typeId.Char, "represents wildcard character used to match anything") wildcard.thisown = False size = Argument("size", Argument.Required|Argument.Single|typeId.UInt32, "size of the needle. Needed in order to take into account \0") size.thisown = False header = Argument("header", Argument.Required|Argument.Single|typeId.Argument, "represents the header, generally corresponding to the starting magic value") header.addSubArgument(needle) header.addSubArgument(wildcard) header.addSubArgument(size) header.thisown = False needle = Argument("needle", Argument.Required|Argument.Single|typeId.String, "represents the needle to search in the haystack") needle.thisown = False wildcard = Argument("wildcard", Argument.Required|Argument.Single|typeId.Char, "represents wildcard character used to match anything") wildcard.thisown = False size = Argument("size", Argument.Required|Argument.Single|typeId.UInt32, "size of the needle. Needed in order to take into account \0") size.thisown = False footer = Argument("footer", Argument.Optional|Argument.Single|typeId.Argument, "represents the footer, generally corresponding to the ending magic value") footer.addSubArgument(needle) footer.addSubArgument(wildcard) footer.addSubArgument(size) footer.thisown = False filetype = Argument("filetype", Argument.Required|Argument.Single|typeId.String, "name of the filetype corresponding to the current pattern automaton") filetype.thisown = False window = Argument("window", Argument.Required|Argument.Single|typeId.UInt32, "maximum size to associate when no footers found or not defined") window.thisown = False aligned = Argument("aligned", Argument.Empty, "defines if headers have to be aligned to sectors") aligned.thisown = False base64 = Argument("b64", Argument.Empty, "defines if matching base64 encoded files") base64.thisown = False blksize = Argument("blksize", Argument.Optional|Argument.Single|typeId.UInt32) blksize.thisown = False pattern = Argument("pattern", Argument.Required|Argument.Single|typeId.Argument, "defines a matching context for carving files. Associate a header and a footer") pattern.addSubArgument(filetype) pattern.addSubArgument(header) pattern.addSubArgument(footer) pattern.addSubArgument(window) pattern.addSubArgument(aligned) pattern.addSubArgument(base64) pattern.addSubArgument(blksize) pattern.thisown = False patterns = Argument("patterns", Argument.Required|Argument.List|typeId.Argument, "defines a matching context for carving files") patterns.thisown = False patterns.addSubArgument(pattern) self.conf.addArgument(patterns) self.conf.addArgument({"name": "start-offset", "input": Argument.Single|Argument.Optional|typeId.UInt64, "description": "offset where to start carving"}) self.tags = "builtins" %} dff-1.3.0+dfsg.1/dff/modules/search/carver/carvergui.py000066400000000000000000000047241217176075400226500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. __dff_module_carvergui_version__ = "1.0.0" from PyQt4.QtGui import QWidget, QVBoxLayout, QGridLayout, QLabel, QProgressBar, QHBoxLayout, QTabWidget from PyQt4.Qt import SIGNAL from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import typeId, Argument, Parameter from dff.modules.carver.predef import PredefinedPatterns from dff.modules.carver.userdef import UserPatterns class CarverGui(QWidget, Script): def __init__(self): Script.__init__(self, "carver-gui") def start(self, args): self.args = args self.node = args["file"].value() self.name += " <" + self.node.name() + ">" self.filesize = self.node.size() def status(self): return 0 def g_display(self): #define layout QWidget.__init__(self) self.baseLayout = QHBoxLayout() self.setLayout(self.baseLayout) self.tabwidgets = QTabWidget() #define all area self.user = UserPatterns(self.args["file"]) self.pp = PredefinedPatterns(self.args["file"]) self.tabwidgets.addTab(self.pp, "Predefined Patterns") self.tabwidgets.addTab(self.user, "User defined") #add widget and hide progress bars self.baseLayout.addWidget(self.tabwidgets) def updateWidget(self): pass def setStateInfo(self, sinfo): self.stateinfo = str(sinfo) class carvergui(Module): """Search for header and footer of a selected mime-type in a node and create the corresponding file. You can use this modules for finding deleted data or data in slack space or in an unknown file system.""" def __init__(self): Module.__init__(self, 'carvergui', CarverGui) self.conf.addArgument({"name": "file", "input": typeId.Node|Argument.Single|Argument.Required, "description": "Node to search data in"}) self.tags = "Search" dff-1.3.0+dfsg.1/dff/modules/search/carver/carverui.py000066400000000000000000000110601217176075400224700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. __dff_module_carverui_version__ = "1.0.0" import string import time from typeSelection import filetypes from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.events.libevents import EventHandler, event from dff.api.types.libtypes import typeId, Argument, Parameter from dff.api.taskmanager.taskmanager import TaskManager from dff.api.types.libtypes import typeId, Argument, Parameter, VList, VMap, Variant class CarverUi(Script): def __init__(self): Script.__init__(self, "carverui") self.tm = TaskManager() def start(self, args): if args.has_key("start-offset"): startoff = args["start-offset"].value() else: startoff = 0 if args.has_key("block-aligned"): aligned = True else: aligned = False patterns = VList() for mimetype in filetypes.keys(): if mimetype in args: vsubtypes = args[mimetype].value() for subtype in filetypes[mimetype].keys(): if subtype in vsubtypes: pattern = VMap() descr = filetypes[mimetype][subtype] for p in descr: header = VMap() header["needle"] = Variant(p[0], typeId.String) header["size"] = Variant(len(p[0]), typeId.UInt32) footer = VMap() footer["needle"] = Variant(p[1], typeId.String) footer["size"] = Variant(len(p[1]), typeId.UInt32) pattern["filetype"] = Variant(subtype, typeId.String) pattern["header"] = Variant(header) pattern["footer"] = Variant(footer) pattern["window"] = Variant(int(p[2]), typeId.UInt32) if aligned: pattern["aligned"] = Variant(True, typeId.Bool) else: pattern["aligned"] = Variant(False, typeId.Bool) patterns.append(pattern) margs = VMap() margs["patterns"] = Variant(patterns) margs["file"] = args["file"] margs["start-offset"] = Variant(startoff, typeId.UInt64) proc = self.tm.add("carver", margs, ["console"]) if proc: proc.event.wait() def c_display(self): pass class carverui(Module): """Search for header and footer of a selected mime-type in a node and create the corresponding file. You can use this modules for finding deleted data or data in slack space or in an unknown file system.""" def __init__(self): Module.__init__(self, 'carverui', CarverUi) self.conf.addArgument({"name": "file", "input": typeId.Node|Argument.Single|Argument.Required, "description": "Node to search data in"}) self.conf.addArgument({"name": "block-aligned", "input": Argument.Empty, "description": "if setted only search signatures at the begining of blocks (faster but less accurate)"}) self.conf.addArgument({"name": "start-offset", "input": typeId.UInt64|Argument.Single|Argument.Optional, "description": "offset from which to start carving"}) for mimetype in filetypes.keys(): predefined = [] for subtype in filetypes[mimetype].keys(): predefined.append(subtype) self.conf.addArgument({"name": mimetype, "input": typeId.String|Argument.List|Argument.Optional, "description": "managed types", "parameters": {"type": Parameter.NotEditable, "predefined": predefined} }) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/modules/search/carver/common.hpp000066400000000000000000000021371217176075400223040ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __COMMON_HPP__ #define __COMMON_HPP__ #include #include #include #include #include #include "search.hpp" #include "pattern.hpp" #include "boyer_moore.hpp" typedef struct description { pattern *header; pattern *footer; char *type; uint32_t window; bool aligned; } description; typedef struct s_context { description *descr; unsigned char *headerBcs; unsigned char *footerBcs; std::vector headers; std::vector footers; } context; #endif dff-1.3.0+dfsg.1/dff/modules/search/carver/predef.py000066400000000000000000000144351217176075400221260ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. import string import time from typeSelection import filetypes from process import CarvingProcess from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.modules.carver.utils import QFFSpinBox class RootCheckBox(QCheckBox): def __init__(self): QCheckBox.__init__(self) self.children = [] self.connect(self, SIGNAL("clicked()"), self.updateChildren) def addChild(self, child): self.children.append(child) def updateChildren(self): state = self.checkState() for child in self.children: if child.isEnabled(): child.setCheckState(state) def update(self, val): checked = 0 for child in self.children: if child.checkState() == Qt.Checked: checked += 1 if checked == 0: self.setCheckState(Qt.Unchecked) elif self.checkState() == Qt.Unchecked: self.setCheckState(Qt.Checked) class PredefinedTree(QTreeWidget): def __init__(self): QTreeWidget.__init__(self) self.setHeaderLabels(["Predefined patterns", "footer block aligned"]) self.typeItems = [] self.blockAligned = [] self.populate() def populate(self): self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self.clicked) self.connect(self, SIGNAL("itemPressed(QTreeWidgetItem *, int)"), self.clicked) for mimetype, mimecontent in filetypes.iteritems(): mimetypeItem = QTreeWidgetItem(self, [mimetype]) mimetypeItem.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) mimetypeItem.setCheckState(0, Qt.Unchecked) rCheckBox = RootCheckBox() rCheckBox.setEnabled(False) self.setItemWidget(mimetypeItem, 1, rCheckBox) self.typeItems.append(mimetypeItem) for filetype, value in mimecontent.iteritems(): filetypeItem = QTreeWidgetItem(mimetypeItem, [filetype]) filetypeItem.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) filetypeItem.setCheckState(0, Qt.Unchecked) checkBox = QCheckBox() checkBox.setEnabled(False) rCheckBox.addChild(checkBox) rCheckBox.connect(checkBox, SIGNAL("stateChanged(int)"), rCheckBox.update) self.setItemWidget(filetypeItem, 1, checkBox) self.resizeColumnToContents(0) def setCheckStateOfChildren(self, item, column, checked): children = item.childCount() for i in range(0, children): if checked == Qt.Checked: self.itemWidget(item.child(i), 1).setEnabled(True) else: self.itemWidget(item.child(i), 1).setCheckState(False) self.itemWidget(item.child(i), 1).setEnabled(False) item.child(i).setCheckState(0, checked) def isAllChildren(self, item, column): children = item.childCount() checked = 0 for i in range(0, children): if item.child(i).checkState(column) == Qt.Checked: checked += 1 if checked == 0: self.itemWidget(item, 1).setEnabled(False) item.setCheckState(0, Qt.Unchecked) elif item.checkState(column) == Qt.Unchecked: self.itemWidget(item, 1).setEnabled(True) item.setCheckState(0, Qt.Checked) def clicked(self, item, column): if column == 0: if item.childCount() != 0: if item.checkState(0) == Qt.Checked: self.itemWidget(item, 1).setEnabled(True) self.setCheckStateOfChildren(item, column, Qt.Checked) else: self.itemWidget(item, 1).setEnabled(False) self.setCheckStateOfChildren(item, column, Qt.Unchecked) else: parent = item.parent() if parent != None and parent.childCount() != 0: self.isAllChildren(parent, column) if item.checkState(0) == Qt.Checked: self.itemWidget(item, 1).setEnabled(True) else: self.itemWidget(item, 1).setEnabled(False) self.itemWidget(item, 1).setCheckState(False) def createGroupBox(self, items): gb = QGroupBox(items["type"]) gb.setCheckable(True) gb.setChecked(False) vbox = QVBoxLayout() for item in items["value"]: button = QCheckBox(item) vbox.addWidget(button) vbox.addStretch(1) gb.setLayout(vbox) return gb def selectedItems(self): selected = {} for typeItem in self.typeItems: i = 0 if typeItem.checkState(0) == Qt.Checked: mimetype = str(typeItem.text(0)) children = typeItem.childCount() for i in range(0, children): child = typeItem.child(i) if child.checkState(0) == Qt.Checked and not child.isDisabled(): child.setDisabled(True) text = str(child.text(0)) selected[text] = (filetypes[mimetype][text], self.itemWidget(child, 1).isChecked()) i += 1 if i > 0: typeItem.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) return selected class PredefinedPatterns(QWidget): def __init__(self, vnode): QWidget.__init__(self) self.baseLayout = QHBoxLayout(self) self.tree = PredefinedTree() self.cprocess = CarvingProcess(self.tree, vnode) self.baseLayout.addWidget(self.tree) self.baseLayout.addWidget(self.cprocess) dff-1.3.0+dfsg.1/dff/modules/search/carver/process.py000066400000000000000000000230261217176075400223330ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. import string import time from typeSelection import filetypes from PyQt4.QtGui import QWidget, QVBoxLayout, QGridLayout, QLabel, QProgressBar, QHBoxLayout, QCheckBox, QPushButton, QTabWidget, QSplitter, QMessageBox from PyQt4.Qt import SIGNAL from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.events.libevents import EventHandler, event from dff.api.types.libtypes import typeId, Argument, Parameter, VList, VMap, Variant from dff.api.taskmanager.taskmanager import TaskManager from dff.modules.carver.utils import QFFSpinBox from dff.modules.carver.CARVER import Carver class CarvingProcess(QWidget, EventHandler): def __init__(self, selector, vnode): QWidget.__init__(self) EventHandler.__init__(self) self.vnode = vnode.value() self.filesize = self.vnode.size() self.tm = TaskManager() self.selector = selector self.setLayout(QVBoxLayout()) self.factor = 1 self.parsetime = 0 self.time = time.time() self.starttime = time.time() self.createStartOffset() self.createButtons() self.createStateInfo() def createStartOffset(self): self.offsetLayout = QHBoxLayout() self.offsetSpinBox = QFFSpinBox(self) self.offsetSpinBox.setMinimum(0) self.offsetSpinBox.setMaximum(self.filesize) self.offsetLabel = QLabel("start offset:") self.offsetLayout.addWidget(self.offsetLabel) self.offsetLayout.addWidget(self.offsetSpinBox) self.layout().addLayout(self.offsetLayout) def createButtons(self): self.startButton = QPushButton("Start") self.stopButton = QPushButton("Stop") self.stopButton.setEnabled(False) self.connect(self.stopButton, SIGNAL("clicked()"), self.stopCarving) self.connect(self.startButton, SIGNAL("clicked()"), self.startCarving) self.connect(self, SIGNAL("ended"), self.carvingEnded) self.buttonLayout = QHBoxLayout() self.buttonLayout.addWidget(self.startButton) self.buttonLayout.addWidget(self.stopButton) self.layout().addLayout(self.buttonLayout) def createStateInfo(self): self.stateLayout = QVBoxLayout() self.overallLayout = QHBoxLayout() self.currentLabel = QLabel("Overall progress :") self.currentProgress = QProgressBar() self.overallLayout.addWidget(self.currentLabel) self.overallLayout.addWidget(self.currentProgress) self.stateLayout.addLayout(self.overallLayout) self.elapsedLabel = QLabel("elapsed time: 00d00h00m00s") self.stateLayout.addWidget(self.elapsedLabel) self.estimatedLabel = QLabel("estimated time: 00d00h00m00s") self.stateLayout.addWidget(self.estimatedLabel) self.totalLabel = QLabel("total headers found: 0") self.stateLayout.addWidget(self.totalLabel) self.stateLayout.setEnabled(False) self.layout().addLayout(self.stateLayout) def createContext(self, selected): lpatterns = VList() for filetype in selected.iterkeys(): patterns = selected[filetype][0] aligned = selected[filetype][1] for pattern in patterns: vpattern = VMap() vpattern["filetype"] = Variant(filetype, typeId.String) header = VMap() header["needle"] = Variant(pattern[0], typeId.String) header["size"] = Variant(len(pattern[0]), typeId.UInt32) footer = VMap() footer["needle"] = Variant(pattern[1], typeId.String) footer["size"] = Variant(len(pattern[1]), typeId.UInt32) vpattern["header"] = Variant(header) vpattern["footer"] = Variant(footer) vpattern["window"] = Variant(int(pattern[2]), typeId.UInt32) vpattern["aligned"] = Variant(aligned, typeId.Bool) lpatterns.append(vpattern) return lpatterns def startCarving(self): selected = self.selector.selectedItems() if len(selected): try: f = self.vnode.open() f.close() except: mbox = QMessageBox(QMessageBox.Warning, self.tr("Carver bad input"), self.tr("The provided input file seems to be a directory. Please, apply the module on a file"), QMessageBox.Ok, self) mbox.exec_() return patterns = self.createContext(selected) args = VMap() args["patterns"] = Variant(patterns) args["file"] = Variant(self.vnode) args["start-offset"] = Variant(self.offsetSpinBox.value(), typeId.UInt64) factor = round(float(self.filesize) / 2147483647) self.startButton.setEnabled(False) self.stopButton.setEnabled(True) self.stopButton.setDown(False) if factor == 0: factor = 1 proc = self.tm.add("carver", args, ["gui", "thread"]) if proc: self.doJob(self.filesize, factor, self.offsetSpinBox.value()) self.stateLayout.setEnabled(True) self.connection(proc.inst) proc.inst.connection(self) #self.connect(self, SIGNAL("stateInfo(QString)"), self.setStateInfo) else: mbox = QMessageBox(QMessageBox.Warning, self.tr("Carver no items selected"), self.tr("No items have been provided to know what to look for. Please chose types you want to search."), QMessageBox.Ok, self) mbox.exec_() return def carvingEnded(self, res): #results = str(res).split("\n") #print results #for item in results: # begidx = item.find(":") # self.res.add_const(str(item[:begidx]), str(item[begidx+1:] + "\n")) self.startButton.setEnabled(True) self.stopButton.setEnabled(False) self.stateLayout.setEnabled(False) def stopCarving(self): self.killJob() self.stopButton.setDown(True) def strtime(self, day, hour, min, sec): day = str(day) hour = str(hour) min = str(min) sec = str(sec) res = "0" * (2-len(day)) + day + "d" + "0" * (2-len(hour)) + hour + "h" + "0" * (2-len(min)) + min + "m" + "0" * (2-len(sec)) + sec + "s" return res def timesec2str(self, timesec): day = hour = min = sec = 0 if timesec > 3600 * 24: day = timesec / (3600 * 24) timesec = timesec % (3600 * 24) if timesec > 3600: hour = timesec / 3600 timesec = timesec % 3600 if timesec > 60: min = timesec / 60 timesec = timesec % 60 sec = timesec res = self.strtime(int(day), int(hour), int(min), int(sec)) return res def Event(self, e): if e.type == Carver.Position: self.emit(SIGNAL("updatePosition"), e) elif e.type == Carver.Matches: self.emit(SIGNAL("updateMatches"), e) elif e.type == Carver.EndOfProcessing: self.emit(SIGNAL("ended"), "") def updatePosition(self, e): ref = time.time() - self.time self.time = time.time() if not str(ref).startswith("0.0"): ref *= self.parsetime res = self.timesec2str(ref) self.estimatedLabel.setText("estimated time: " + res) res = self.timesec2str(time.time() - self.starttime) self.elapsedLabel.setText("elapsed time: " + res) i = int(e.value.value() / self.factor) if i > 2147483647: i = 2147483647 self.emit(SIGNAL("valueChanged(int)"), i) info = self.currentProgress.text() + " - " + self.totalLabel.text() self.emit(SIGNAL("stateInfo(QString)"), info) def updateMatches(self, e): self.totalLabel.setText("total headers found: " + str(e.value)) def doJob(self, filesize, factor, start): self.factor = factor self.parsetime = filesize / (10*1204*1024) self.elapsedLabel.setText("elapsed time: 00d00h00m00s") self.estimatedLabel.setText("estimated time: 00d00h00m00s") self.totalLabel.setText("total headers found: 0") maxrange = int(filesize / self.factor) if maxrange > 2147483647: maxrange = 2147483647 self.currentProgress.setRange(0, maxrange) self.currentProgress.setValue(0) self.connect(self, SIGNAL("valueChanged(int)"), self.currentProgress.setValue) self.time = time.time() self.starttime = time.time() self.connect(self, SIGNAL("updateMatches"), self.updateMatches) self.connect(self, SIGNAL("updatePosition"), self.updatePosition) def killJob(self): e = event() e.thisown = False e.type = Carver.Stop self.notify(e) dff-1.3.0+dfsg.1/dff/modules/search/carver/typeSelection.py000066400000000000000000000064301217176075400235040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin art = [["\x4a\x47\x04\x0e", "\xcf\xc7\xcb", 150000], ["\x4a\x47\x03\x0e", "\xd0\xcb\x00\x00", 150000]] gif = [["\x47\x49\x46\x38", "\x00\x3b", 5000000]] jpg = [["\xff\xd8\xff", "\xff\xd9", 200000000]] png = [["\x89\x50\x4e\x47", "\xff\xfc\xfd\xfe", 20000000]] bmp = [["BM", "", 100000]] tif = [["\x49\x49\x2a\x00", "", 200000000], ["\x4D\x4D\x00\x2A", "", 200000000]] avi = [["RIFF", "", 50000000]] mov = [["moov", "", 10000000], ["mdat", "", 10000000], ["widev", "", 10000000], ["skip", "", 10000000], ["free", "", 10000000], ["idsc", "", 10000000], ["pckg", "", 10000000]] mpg = [["\x00\x00\x01\xba", "\x00\x00\x01\xb9", 50000000], ["\x00\x00\x01\xb3", "\x00\x00\x01\xb7", 50000000]] fws = [["FWS", "", 4000000]] doc = [["\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00", "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00", 10000000], ["\xd0\xcf\x11\xe0\xa1\xb1", "", 10000000]] pst = [["\x21\x42\x4e\xa5\x6f\xb5\xa6", "", 500000000]] ost = [["\x21\x42\x44\x4e", "", 500000000]] dbx = [["\xcf\xad\x12\xfe\xc5\xfd\x74\x6f", "", 10000000]] idx = [["\x4a\x4d\x46\x39", "", 10000000]] mbx = [["\x4a\x4d\x46\x36", "", 10000000]] wpc = [["WPC", "", 1000000]] htm = [["", 50000]] pdf = [["%PDF", "%EOF\x0d", 5000000], ["%PDF", "%EOF\x0a", 5000000]] mail = [["\x41\x4f\x4c\x56\x4d", "", 500000]] pgd = [["\x50\x47\x50\x64\x4d\x41\x49\x4e\x60\x01", "", 500000]] pgp = [["\x99\x00", "", 100000], ["\x95\x01", "", 100000], ["\x95\x00", "", 100000], ["\xa6\x00", "", 100000]] txt = [["-----BEGIN\040PGP", "", 100000]] rpm = [["\xed\xab", "", 1000000]] wav = [["RIFF", "", 200000]] ra = [["\x2e\x72\x61\xfd", "", 1000000], [".RMF", "", 1000000]] dat = [["regf", "", 4000000], ["CREG", "", 4000000]] zip = [["PK\x03\x04", "\x3c\xac", 10000000]] java = [["\xca\xfe\xba\xbe", "", 1000000]] max = [["\x56\x69\x47\x46\x6b\x1a\x00\x00\x00\x00", "\x00\x00\x05\x80\x00\x00", 1000000]] filetypes = {"application/images": {"art": art, "gif": gif, "jpg": jpg, "png": png, "bmp": bmp, "tif": tif}, "application/videos": {"avi": avi, "mov": mov, "mpg": mpg}, "application/animation": {"fws": fws}, "application/document": {"doc": doc, "pdf": pdf, "txt": txt, "wpc": wpc, "pdf": pdf, "htm": htm}, "application/mail": {"pst": pst, "ost": ost, "dbx": dbx, "idx": idx, "mbx": mbx, "aolmail": mail}, "application/audio": {"wav": wav, "ra": ra}, "application/pgp": {"pgd": pgd, "pgp": pgp, "txt": txt}, "application/package": {"rpm": rpm}, "application/registry": {"dat": dat}, "application/archiver": {"zip": zip}, "application/vm": {"java": java}} dff-1.3.0+dfsg.1/dff/modules/search/carver/userdef.py000066400000000000000000000203431217176075400223110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. import string import time from PyQt4.QtGui import QWidget, QGroupBox, QGridLayout, QLabel, QComboBox, QLineEdit, QPushButton, QTableWidget, QTableWidgetItem, QIcon, QMessageBox, QHBoxLayout, QCheckBox from PyQt4.Qt import SIGNAL from dff.modules.carver.utils import QSpinBox from process import CarvingProcess class PatternsTable(QWidget): def __init__(self): QWidget.__init__(self) self.grid = QGridLayout() self.setLayout(self.grid) self.patternArea() self.patternTable() def createPattern(self, name, x): label = name.lower() + "Label" type = name.lower() + "Type" entry = name.lower() + "Entry" setattr(self, label, QLabel(name)) setattr(self, entry, QLineEdit()) setattr(self, type, QComboBox()) labelobj = getattr(self, label) typeobj = getattr(self, type) entryobj = getattr(self, entry) typeobj.addItem("Hexadecimal") typeobj.addItem("String") self.grid.addWidget(labelobj, x, 0) self.grid.addWidget(entryobj, x, 1) self.grid.addWidget(typeobj, x, 2) def patternArea(self): self.filetypeLabel = QLabel("File type") self.filetype = QLineEdit() self.alignedLabel = QLabel("block aligned") self.aligned = QCheckBox() self.windowLabel = QLabel("Window size") self.window = QSpinBox() self.window.setSuffix(" bytes") self.window.setRange(0, 2500000) self.window.setSingleStep(100) self.addEntry = QPushButton("add") self.connect(self.addEntry, SIGNAL("clicked()"), self.insertPattern) self.grid.addWidget(self.filetypeLabel, 0, 0) self.grid.addWidget(self.filetype, 0, 1, 1, 2) self.createPattern("Header", 2) self.createPattern("Footer", 3) self.grid.addWidget(self.windowLabel, 4, 0) self.grid.addWidget(self.window, 4, 1) self.grid.addWidget(self.alignedLabel, 5, 0) self.grid.addWidget(self.aligned, 5, 1) self.grid.addWidget(self.addEntry, 6, 1) def patternTable(self): self.patterns = QTableWidget() self.patterns.setShowGrid(False) self.patterns.setColumnCount(5) self.patterns.setHorizontalHeaderLabels(["Filetype", "Header", "Footer", "Window", "Block aligned"]) self.patterns.horizontalHeader().setStretchLastSection(True) self.connect(self.patterns.verticalHeader(), SIGNAL("sectionClicked(int)"), self.patterns.removeRow) self.grid.addWidget(self.patterns, 7, 0, 1, 3) def warning(self, msg): msgBox = QMessageBox(self) msgBox.setText(msg) msgBox.setIcon(QMessageBox.Warning) msgBox.exec_() def validate(self, **kwargs): msg = "" if len(kwargs["type"]) == 0: msg = "Type must be defined" else: for i in kwargs["type"]: if i not in string.letters: msg = "Type's characters must be in the following set\n\n" + string.letters break rowCount = self.patterns.rowCount() for row in range(0, rowCount): if str(self.patterns.item(row, 0).text()) == kwargs["type"]: msg = "Type <" + kwargs["type"] + " > already defined" if msg != "": self.warning(msg) return False if kwargs["headerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]): msg = "Header must be an even number of chars" self.warning(msg) return False if len(kwargs["header"]) == 0: msg = "Header must be provided" self.warning(msg) return False if kwargs["footerType"] == "Hexadecimal" and not self.isHex(kwargs["footer"]): msg = "Footer must be an even number of chars" self.warning(msg) return False if kwargs["window"] <= 0: msg = "Window size must be greater than 0" self.warning(msg) return False return True def insertPattern(self): filetype = str(self.filetype.text()) header = str(self.headerEntry.text()) headerType = str(self.headerType.currentText()) footer = str(self.footerEntry.text()) footerType = str(self.footerType.currentText()) window = self.window.text() aligned = self.aligned.isChecked() #Validate most of provided items kwargs = {"type": filetype, "header": header, "headerType": headerType, "footer": footer, "footerType": footerType, "window": int(window.replace(" bytes", ""))} if not self.validate(**kwargs): return filetypeItem = QTableWidgetItem(filetype) headerItem = QTableWidgetItem(header + " (" + headerType[0:3] + ")") footerItem = QTableWidgetItem(footer + " (" + footerType[0:3] + ")") windowItem = QTableWidgetItem(window) alignedItem = QTableWidgetItem(str(aligned)) self.patterns.insertRow(self.patterns.rowCount()) vertHeader = QTableWidgetItem(QIcon(":closetab.png"), "") row = self.patterns.rowCount() - 1 self.patterns.setVerticalHeaderItem(row, vertHeader) self.patterns.setItem(row, 0, filetypeItem) self.patterns.setItem(row, 1, headerItem) self.patterns.setItem(row, 2, footerItem) self.patterns.setItem(row, 3, windowItem) self.patterns.setItem(row, 4, alignedItem) self.patterns.resizeRowToContents(row) def isHex(self, hstr): HEXCHAR = "0123456789abcdefABCDEF" if len(hstr) % 2 != 0: return False even = False for i in range(len(hstr)): if hstr[i] not in HEXCHAR: return False return True def toHex(self, str): HEXCHAR = "0123456789abcdefABCDEF" hexStr = "" evenhex = "" for i in range(len(str)): if str[i] in HEXCHAR: if len(evenhex) == 1: hexStr += chr(int(evenhex+str[i], 16)) evenhex = "" else: evenhex = str[i] else: raise ValueError, "argument 'str' contains not valid characters" if len(evenhex) != 0: raise ValueError, "argument 'str' must be an even number of char" return hexStr def textToPattern(self, text): idx = text.find("(") pattern = "" if idx != -1: type = text[idx+1:idx+4] pattern = text[0:idx-1] if type == "Hex": pattern = self.toHex(pattern) return pattern def selectedItems(self): selected = {} rowCount = self.patterns.rowCount() for row in range(0, rowCount): filetype = str(self.patterns.item(row, 0).text()) selected[filetype] = [] pattern = [] pattern.append(self.textToPattern(str(self.patterns.item(row, 1).text()))) pattern.append(self.textToPattern(str(self.patterns.item(row, 2).text()))) pattern.append(int(self.patterns.item(row, 3).text().replace(" bytes", ""))) selected[filetype].append([pattern]) if self.patterns.item(row, 4).text() == "True": selected[filetype].append(True) else: selected[filetype].append(False) return selected class UserPatterns(QWidget): def __init__(self, vnode): QWidget.__init__(self) self.baseLayout = QHBoxLayout(self) self.table = PatternsTable() self.cprocess = CarvingProcess(self.table, vnode) self.baseLayout.addWidget(self.table) self.baseLayout.addWidget(self.cprocess) dff-1.3.0+dfsg.1/dff/modules/search/carver/utils.py000066400000000000000000000062141217176075400220150ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * class QFFSpinBox(QAbstractSpinBox): def __init__(self, parent=None): QAbstractSpinBox.__init__(self) self.init(parent) self.initEdit() def init(self, parent): #Variables self.parent = parent self.__minimum = 0 self.__maximum = 0 self.__range = 0 self.__value = 0 self.__singleStep = 0 #Functions self.setWrapping(True) # self.setEnabled(True) def initEdit(self): self.__edit = self.lineEdit() self.__edit.connect(self.__edit, SIGNAL("editingFinished()"), self.editChanged) # self.setLineEdit(self.__edit) def stepEnabled(self): if self.wrapping(): if self.__value == self.__minimum: return self.StepEnabled(QAbstractSpinBox.StepUpEnabled) elif self.__value == self.__maximum: return self.StepEnabled(QAbstractSpinBox.StepDownEnabled) else: return self.StepEnabled(QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled) def maximum(self): return self.__maximum def minimum(self): return self.__minimum def setMaximum(self, max): self.__maximum = max def setMinimum(self, min): self.__minimum = min def setSingleStep(self, step): self.__singlStep = step def setRange(self, range): self.__range = range def setValue(self, value): self.__value = value self.refreshEdit(value) def value(self): return self.__value def singleStep(self): return self.__singleStep def maximum(self): return self.__maximum def minimum(self): return self.__minimum def stepBy(self, step): if step < 0: if self.__value > self.__minimum: self.__value -= 1 self.refreshEdit(self.__value) else: if self.__value < self.__maximum: self.__value += 1 self.refreshEdit(self.__value) def refreshEdit(self, value): self.__edit.clear() cvalue = "%.1d" % value self.__edit.insert(cvalue) def editChanged(self): value = self.__edit.text() lvalue = value.toULongLong() if lvalue[1]: if (lvalue[0] <= self.__maximum) and (lvalue[0] >= self.__minimum): self.__value = lvalue[0] self.refreshEdit(lvalue[0]) else: self.refreshEdit(self.__value) else: self.refreshEdit(self.__value) dff-1.3.0+dfsg.1/dff/modules/statistics/000077500000000000000000000000001217176075400177435ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/statistics/CMakeLists.txt000066400000000000000000000011501217176075400225000ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py ) add_subdirectory(fileschart) dff-1.3.0+dfsg.1/dff/modules/statistics/__init__.py000066400000000000000000000011161217176075400220530ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['chart', 'fileschart'] dff-1.3.0+dfsg.1/dff/modules/statistics/fileschart/000077500000000000000000000000001217176075400220675ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/statistics/fileschart/CMakeLists.txt000066400000000000000000000011631217176075400246300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py fileschart.py chart.py chart_rc.py ) dff-1.3.0+dfsg.1/dff/modules/statistics/fileschart/__init__.py000066400000000000000000000000001217176075400241660ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/statistics/fileschart/chart.py000066400000000000000000000523651217176075400235550ustar00rootroot00000000000000#!/usr/bin/env python ############################################################################# ## ## Copyright (C) 2010 Riverbank Computing Limited. ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ## All rights reserved. ## ## This file is part of the examples of PyQt. ## ## $QT_BEGIN_LICENSE:BSD$ ## You may use this file under the terms of the BSD license as follows: ## ## "Redistribution and use in source and binary forms, with or without ## modification, are permitted provided that the following conditions are ## met: ## * Redistributions of source code must retain the above copyright ## notice, this list of conditions and the following disclaimer. ## * Redistributions in binary form must reproduce the above copyright ## notice, this list of conditions and the following disclaimer in ## the documentation and/or other materials provided with the ## distribution. ## * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ## the names of its contributors may be used to endorse or promote ## products derived from this software without specific prior written ## permission. ## ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ## $QT_END_LICENSE$ ## ############################################################################# import math from PyQt4 import QtCore, QtGui import chart_rc class PieView(QtGui.QAbstractItemView): def __init__(self, parent=None): super(PieView, self).__init__(parent) self.horizontalScrollBar().setRange(0, 0) self.verticalScrollBar().setRange(0, 0) self.margin = 8 self.totalSize = 300 self.pieSize = self.totalSize - 2*self.margin self.validItems = 0 self.totalValue = 0.0 self.origin = QtCore.QPoint() self.rubberBand = None def dataChanged(self, topLeft, bottomRight): super(PieView, self).dataChanged(topLeft, bottomRight) self.validItems = 0 self.totalValue = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index).toPyObject() if value is not None and value > 0.0: self.totalValue += value self.validItems += 1 self.viewport().update() def edit(self, index, trigger, event): if index.column() == 0: return super(PieView, self).edit(index, trigger, event) else: return False def indexAt(self, point): if self.validItems == 0: return QtCore.QModelIndex() # Transform the view coordinates into contents widget coordinates. wx = point.x() + self.horizontalScrollBar().value() wy = point.y() + self.verticalScrollBar().value() if wx < self.totalSize: cx = wx - self.totalSize/2 cy = self.totalSize/2 - wy; # positive cy for items above the center # Determine the distance from the center point of the pie chart. d = (cx**2 + cy**2)**0.5 if d == 0 or d > self.pieSize/2: return QtCore.QModelIndex() # Determine the angle of the point. angle = (180 / math.pi) * math.acos(cx/d) if cy < 0: angle = 360 - angle # Find the relevant slice of the pie. startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index).toPyObject() if value > 0.0: sliceAngle = 360*value/self.totalValue if angle >= startAngle and angle < (startAngle + sliceAngle): return self.model().index(row, 1, self.rootIndex()) startAngle += sliceAngle else: itemHeight = QtGui.QFontMetrics(self.viewOptions().font).height() listItem = int((wy - self.margin) / itemHeight) validRow = 0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) if self.model().data(index).toPyObject() > 0.0: if listItem == validRow: return self.model().index(row, 0, self.rootIndex()) # Update the list index that corresponds to the next valid # row. validRow += 1 return QtCore.QModelIndex() def isIndexHidden(self, index): return False def itemRect(self, index): if not index.isValid(): return QtCore.QRect() # Check whether the index's row is in the list of rows represented # by slices. if index.column() != 1: valueIndex = self.model().index(index.row(), 1, self.rootIndex()) else: valueIndex = index if self.model().data(valueIndex) > 0.0: listItem = 0 for row in range(index.row()-1, -1, -1): if self.model().data(self.model().index(row, 1, self.rootIndex())) > 0.0: listItem += 1 if index.column() == 0: itemHeight = QtGui.QFontMetrics(self.viewOptions().font).height() return QtCore.QRect(self.totalSize, int(self.margin + listItem*itemHeight), self.totalSize - self.margin, int(itemHeight)) elif index.column() == 1: return self.viewport().rect() return QtCore.QRect() def itemRegion(self, index): if not index.isValid(): return QtGui.QRegion() if index.column() != 1: return QtGui.QRegion(self.itemRect(index)) if self.model().data(index).toPyObject() <= 0.0: return QtGui.QRegion() startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): sliceIndex = self.model().index(row, 1, self.rootIndex()) value = self.model().data(sliceIndex).toPyObject() if value > 0.0: angle = 360*value/self.totalValue if sliceIndex == index: slicePath = QtGui.QPainterPath() slicePath.moveTo(self.totalSize/2, self.totalSize/2) slicePath.arcTo(self.margin, self.margin, self.margin+self.pieSize, self.margin+self.pieSize, startAngle, angle) slicePath.closeSubpath() return QtGui.QRegion(slicePath.toFillPolygon().toPolygon()) startAngle += angle return QtGui.QRegion() def horizontalOffset(self): return self.horizontalScrollBar().value() def mousePressEvent(self, event): super(PieView, self).mousePressEvent(event) self.origin = event.pos() if not self.rubberBand: self.rubberBand = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QtCore.QRect(self.origin, QtCore.QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if self.rubberBand: self.rubberBand.setGeometry(QtCore.QRect(self.origin, event.pos()).normalized()) super(PieView, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): super(PieView, self).mouseReleaseEvent(event) if self.rubberBand: self.rubberBand.hide() self.viewport().update() def moveCursor(self, cursorAction, modifiers): current = self.currentIndex() if cursorAction == QtGui.QAbstractItemView.MoveLeft or \ cursorAction == QtGui.QAbstractItemView.MoveUp: if current.row() > 0: current = self.model().index(current.row() - 1, current.column(), self.rootIndex()) else: current = self.model().index(0, current.column(), self.rootIndex()) elif cursorAction == QtGui.QAbstractItemView.MoveRight or \ cursorAction == QtGui.QAbstractItemView.MoveDown: if current.row() < rows(current) - 1: current = self.model().index(current.row() + 1, current.column(), self.rootIndex()) else: current = self.model().index(rows(current) - 1, current.column(), self.rootIndex()) self.viewport().update() return current def paintEvent(self, event): selections = self.selectionModel() option = self.viewOptions() state = option.state background = option.palette.base() foreground = QtGui.QPen(option.palette.color(QtGui.QPalette.WindowText)) textPen = QtGui.QPen(option.palette.color(QtGui.QPalette.Text)) highlightedPen = QtGui.QPen(option.palette.color(QtGui.QPalette.HighlightedText)) painter = QtGui.QPainter(self.viewport()) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.fillRect(event.rect(), background) painter.setPen(foreground) # Viewport rectangles pieRect = QtCore.QRect(self.margin, self.margin, self.pieSize, self.pieSize) keyPoint = QtCore.QPoint(self.totalSize - self.horizontalScrollBar().value(), self.margin - self.verticalScrollBar().value()) if self.validItems > 0: painter.save() painter.translate(pieRect.x() - self.horizontalScrollBar().value(), pieRect.y() - self.verticalScrollBar().value()) painter.drawEllipse(0, 0, self.pieSize, self.pieSize) startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index).toPyObject() if value > 0.0: angle = 360*value/self.totalValue colorIndex = self.model().index(row, 0, self.rootIndex()) color = self.model().data(colorIndex, QtCore.Qt.DecorationRole).toPyObject() if self.currentIndex() == index: painter.setBrush(QtGui.QBrush(color, QtCore.Qt.Dense4Pattern)) elif selections.isSelected(index): painter.setBrush(QtGui.QBrush(color, QtCore.Qt.Dense3Pattern)) else: painter.setBrush(QtGui.QBrush(color)) painter.drawPie(0, 0, self.pieSize, self.pieSize, int(startAngle*16), int(angle*16)) startAngle += angle painter.restore() keyNumber = 0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index).toPyObject() if value > 0.0: labelIndex = self.model().index(row, 0, self.rootIndex()) option = self.viewOptions() option.rect = self.visualRect(labelIndex) if selections.isSelected(labelIndex): option.state |= QtGui.QStyle.State_Selected if self.currentIndex() == labelIndex: option.state |= QtGui.QStyle.State_HasFocus self.itemDelegate().paint(painter, option, labelIndex) keyNumber += 1 def resizeEvent(self, event): self.updateGeometries() def rows(self, index): return self.model().rowCount(self.model().parent(index)) def rowsInserted(self, parent, start, end): for row in range(start, end + 1): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index).toPyObject() if value is not None and value > 0.0: self.totalValue += value self.validItems += 1 super(PieView, self).rowsInserted(parent, start, end) def rowsAboutToBeRemoved(self, parent, start, end): for row in range(start, end + 1): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index).toPyObject() if value is not None and value > 0.0: self.totalValue -= value self.validItems -= 1 super(PieView, self).rowsAboutToBeRemoved(parent, start, end) def scrollContentsBy(self, dx, dy): self.viewport().scroll(dx, dy) def scrollTo(self, index, ScrollHint): area = self.viewport().rect() rect = self.visualRect(index) if rect.left() < area.left(): self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + rect.left() - area.left()) elif rect.right() > area.right(): self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + min( rect.right() - area.right(), rect.left() - area.left())) if rect.top() < area.top(): self.verticalScrollBar().setValue( self.verticalScrollBar().value() + rect.top() - area.top()) elif rect.bottom() > area.bottom(): self.verticalScrollBar().setValue( self.verticalScrollBar().value() + min( rect.bottom() - area.bottom(), rect.top() - area.top())) def setSelection(self, rect, command): # Use content widget coordinates because we will use the itemRegion() # function to check for intersections. contentsRect = rect.translated(self.horizontalScrollBar().value(), self.verticalScrollBar().value()).normalized() rows = self.model().rowCount(self.rootIndex()) columns = self.model().columnCount(self.rootIndex()) indexes = [] for row in range(rows): for column in range(columns): index = self.model().index(row, column, self.rootIndex()) region = self.itemRegion(index) if not region.intersect(QtGui.QRegion(contentsRect)).isEmpty(): indexes.append(index) if len(indexes) > 0: firstRow = indexes[0].row() lastRow = indexes[0].row() firstColumn = indexes[0].column() lastColumn = indexes[0].column() for i in range(1, len(indexes)): firstRow = min(firstRow, indexes[i].row()) lastRow = max(lastRow, indexes[i].row()) firstColumn = min(firstColumn, indexes[i].column()) lastColumn = max(lastColumn, indexes[i].column()) selection = QtGui.QItemSelection( self.model().index(firstRow, firstColumn, self.rootIndex()), self.model().index(lastRow, lastColumn, self.rootIndex())) self.selectionModel().select(selection, command) else: noIndex = QtCore.QModelIndex() selection = QtGui.QItemSelection(noIndex, noIndex) self.selectionModel().select(selection, command) self.update() def updateGeometries(self): self.horizontalScrollBar().setPageStep(self.viewport().width()) self.horizontalScrollBar().setRange(0, max(0, 2*self.totalSize - self.viewport().width())) self.verticalScrollBar().setPageStep(self.viewport().height()) self.verticalScrollBar().setRange(0, max(0, self.totalSize - self.viewport().height())) def verticalOffset(self): return self.verticalScrollBar().value() def visualRect(self, index): rect = self.itemRect(index) if rect.isValid(): return QtCore.QRect(rect.left() - self.horizontalScrollBar().value(), rect.top() - self.verticalScrollBar().value(), rect.width(), rect.height()) else: return rect def visualRegionForSelection(self, selection): region = QtGui.QRegion() for span in selection: for row in range(span.top(), span.bottom() + 1): for col in range(span.left(), span.right() + 1): index = self.model().index(row, col, self.rootIndex()) region += self.visualRect(index) return region class MainWindow(QtGui.QMainWindow): def __init__(self): super(MainWindow, self).__init__() fileMenu = QtGui.QMenu("&File", self) openAction = fileMenu.addAction("&Open...") openAction.setShortcut("Ctrl+O") saveAction = fileMenu.addAction("&Save As...") saveAction.setShortcut("Ctrl+S") quitAction = fileMenu.addAction("E&xit") quitAction.setShortcut("Ctrl+Q") self.setupModel() self.setupViews() openAction.triggered.connect(self.openFile) saveAction.triggered.connect(self.saveFile) quitAction.triggered.connect(QtGui.qApp.quit) self.menuBar().addMenu(fileMenu) self.statusBar() self.openFile(':/Charts/qtdata.cht') self.setWindowTitle("Chart") self.resize(870, 550) def setupModel(self): self.model = QtGui.QStandardItemModel(8, 2, self) self.model.setHeaderData(0, QtCore.Qt.Horizontal, "Label") self.model.setHeaderData(1, QtCore.Qt.Horizontal, "Quantity") def setupViews(self): splitter = QtGui.QSplitter() table = QtGui.QTableView() self.pieChart = PieView() splitter.addWidget(table) splitter.addWidget(self.pieChart) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 1) table.setModel(self.model) self.pieChart.setModel(self.model) self.selectionModel = QtGui.QItemSelectionModel(self.model) table.setSelectionModel(self.selectionModel) self.pieChart.setSelectionModel(self.selectionModel) table.horizontalHeader().setStretchLastSection(True) self.setCentralWidget(splitter) def openFile(self, path=None): if not path: path = QtGui.QFileDialog.getOpenFileName(self, "Choose a data file", '', '*.cht') if path: f = QtCore.QFile(path) if f.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text): stream = QtCore.QTextStream(f) self.model.removeRows(0, self.model.rowCount(QtCore.QModelIndex()), QtCore.QModelIndex()) row = 0 line = stream.readLine() while line: self.model.insertRows(row, 1, QtCore.QModelIndex()) pieces = line.split(',') self.model.setData(self.model.index(row, 0, QtCore.QModelIndex()), pieces[0]) self.model.setData(self.model.index(row, 1, QtCore.QModelIndex()), float(pieces[1])) self.model.setData(self.model.index(row, 0, QtCore.QModelIndex()), QtGui.QColor(pieces[2]), QtCore.Qt.DecorationRole) row += 1 line = stream.readLine() f.close() self.statusBar().showMessage("Loaded %s" % path, 2000) def saveFile(self): fileName = QtGui.QFileDialog.getSaveFileName(self, "Save file as", '', '*.cht') if fileName: f = QtCore.QFile(fileName) if f.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text): for row in range(self.model.rowCount(QtCore.QModelIndex())): pieces = [] pieces.append(self.model.data(self.model.index(row, 0, QtCore.QModelIndex()), QtCore.Qt.DisplayRole)) pieces.append(str(self.model.data(self.model.index(row, 1, QtCore.QModelIndex()), QtCore.Qt.DisplayRole))) pieces.append(self.model.data(self.model.index(row, 0, QtCore.QModelIndex()), QtCore.Qt.DecorationRole).name()) f.write(QtCore.QByteArray(','.join(pieces))) f.write('\n') f.close() self.statusBar().showMessage("Saved %s" % fileName, 2000) if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) dff-1.3.0+dfsg.1/dff/modules/statistics/fileschart/chart_rc.py000066400000000000000000000050431217176075400242300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Resource object code # # Created: Thu Jul 29 17:37:01 2010 # by: The Resource Compiler for PyQt (Qt v4.6.3) # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore qt_resource_data = "\ \x00\x00\x01\x90\ \x53\ \x63\x69\x65\x6e\x74\x69\x66\x69\x63\x20\x52\x65\x73\x65\x61\x72\ \x63\x68\x2c\x32\x31\x2c\x23\x39\x39\x65\x36\x30\x30\x0a\x45\x6e\ \x67\x69\x6e\x65\x65\x72\x69\x6e\x67\x20\x26\x20\x44\x65\x73\x69\ \x67\x6e\x2c\x31\x38\x2c\x23\x39\x39\x63\x63\x30\x30\x0a\x41\x75\ \x74\x6f\x6d\x6f\x74\x69\x76\x65\x2c\x31\x34\x2c\x23\x39\x39\x62\ \x33\x30\x30\x0a\x41\x65\x72\x6f\x73\x70\x61\x63\x65\x2c\x31\x33\ \x2c\x23\x39\x66\x39\x39\x31\x61\x0a\x41\x75\x74\x6f\x6d\x61\x74\ \x69\x6f\x6e\x20\x26\x20\x4d\x61\x63\x68\x69\x6e\x65\x20\x54\x6f\ \x6f\x6c\x73\x2c\x31\x33\x2c\x23\x61\x34\x38\x30\x33\x33\x0a\x4d\ \x65\x64\x69\x63\x61\x6c\x20\x26\x20\x42\x69\x6f\x69\x6e\x66\x6f\ \x72\x6d\x61\x74\x69\x63\x73\x2c\x31\x33\x2c\x23\x61\x39\x36\x36\ \x34\x64\x0a\x49\x6d\x61\x67\x69\x6e\x67\x20\x26\x20\x53\x70\x65\ \x63\x69\x61\x6c\x20\x45\x66\x66\x65\x63\x74\x73\x2c\x31\x32\x2c\ \x23\x61\x65\x34\x64\x36\x36\x0a\x44\x65\x66\x65\x6e\x73\x65\x2c\ \x31\x31\x2c\x23\x62\x33\x33\x33\x38\x30\x0a\x54\x65\x73\x74\x20\ \x26\x20\x4d\x65\x61\x73\x75\x72\x65\x6d\x65\x6e\x74\x20\x53\x79\ \x73\x74\x65\x6d\x73\x2c\x39\x2c\x23\x61\x36\x34\x30\x38\x36\x0a\ \x4f\x69\x6c\x20\x26\x20\x47\x61\x73\x2c\x39\x2c\x23\x39\x39\x34\ \x64\x38\x64\x0a\x45\x6e\x74\x65\x72\x74\x61\x69\x6e\x6d\x65\x6e\ \x74\x20\x26\x20\x42\x72\x6f\x61\x64\x63\x61\x73\x74\x69\x6e\x67\ \x2c\x37\x2c\x23\x38\x64\x35\x61\x39\x33\x0a\x46\x69\x6e\x61\x6e\ \x63\x69\x61\x6c\x2c\x36\x2c\x23\x38\x30\x36\x36\x39\x39\x0a\x43\ \x6f\x6e\x73\x75\x6d\x65\x72\x20\x45\x6c\x65\x63\x74\x72\x6f\x6e\ \x69\x63\x73\x2c\x34\x2c\x23\x38\x30\x37\x33\x61\x36\x0a\x4f\x74\ \x68\x65\x72\x2c\x33\x38\x2c\x23\x38\x30\x38\x30\x62\x33\x0a\ " qt_resource_name = "\ \x00\x06\ \x04\x9e\x89\xb3\ \x00\x43\ \x00\x68\x00\x61\x00\x72\x00\x74\x00\x73\ \x00\x0a\ \x08\xaf\x5c\xb4\ \x00\x71\ \x00\x74\x00\x64\x00\x61\x00\x74\x00\x61\x00\x2e\x00\x63\x00\x68\x00\x74\ " qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ \x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ " def qInitResources(): QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) def qCleanupResources(): QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) qInitResources() dff-1.3.0+dfsg.1/dff/modules/statistics/fileschart/fileschart.py000066400000000000000000000116241217176075400245710ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_fileschart_version__ = "1.0.0" import random from PyQt4 import QtCore, QtGui from PyQt4.QtGui import QWidget from PyQt4.QtCore import Qt from dff.api.vfs import * from dff.api.module.script import * from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId, Variant from dff.modules.fileschart.chart import PieView #XXX add sub rep pour les modulse class STATCHART(QWidget): def __init__(self): #super(QWidget, self).__init__() QWidget.__init__(self) self.setupModel() self.setupViews() def setupModel(self): self.model = QtGui.QStandardItemModel(8, 2, self) self.model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Label")) self.model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Quantity")) def setupViews(self): self.vbox = QtGui.QVBoxLayout() self.setLayout(self.vbox) splitter = QtGui.QSplitter() table = QtGui.QTableView() self.pieChart = PieView() splitter.addWidget(table) splitter.addWidget(self.pieChart) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 1) table.setModel(self.model) self.pieChart.setModel(self.model) self.selectionModel = QtGui.QItemSelectionModel(self.model) table.setSelectionModel(self.selectionModel) self.pieChart.setSelectionModel(self.selectionModel) table.horizontalHeader().setStretchLastSection(True) self.vbox.addWidget(splitter) def decode(self, typestat): self.model.removeRows(0, self.model.rowCount(QtCore.QModelIndex()), QtCore.QModelIndex()) row = 0 i = 0 for mtype, count in typestat.iteritems(): color = random.randint(0, 0xffffffff) self.model.insertRows(row, 1, QtCore.QModelIndex()) self.model.setData(self.model.index(row, 0, QtCore.QModelIndex()), QtCore.QVariant(mtype)) self.model.setData(self.model.index(row, 1, QtCore.QModelIndex()), QtCore.QVariant(float(count))) self.model.setData(self.model.index(row, 0, QtCore.QModelIndex()), QtCore.QVariant(QtGui.QColor(color)), QtCore.Qt.DecorationRole) row += 1 class FILESCHART(Script, QWidget): def __init__(self): Script.__init__(self, "fileschart") self.vfs = vfs.vfs() def c_display(self): buff = "" for mtype, count in self.typestat.iteritems(): buff += mtype + ": " + str(count) + "\n" return buff def g_display(self): QWidget.__init__(self) self.chart = STATCHART() self.vbox = QtGui.QVBoxLayout() self.setLayout(self.vbox) self.vbox.addWidget(self.chart) #STATCHART.__init__(self) self.chart.decode(self.typestat) def updateWidget(self): pass def start(self, args): self.typestat = {} try: nodes = args["files"].value() self.processed = 0 self.totalNodes = 0 for vnode in nodes: node = vnode.value() self.totalNodes += node.totalChildrenCount() self.processed += 1 if node.size() > 0: self.addEntry(node) if node.hasChildren(): self.getstat(node.children()) for mtype, count in self.typestat.iteritems(): self.res[str(mtype)] = Variant(count) except KeyError: pass def addEntry(self, node): mtype = node.dataType()["magic"].value() idx = mtype.find(", ") if idx != -1: mtype = mtype[:idx] if mtype not in self.typestat: self.typestat[mtype] = 1 else: self.typestat[mtype] += 1 def getstat(self, lnodes): folders = [] for node in lnodes: self.processed += 1 self.stateinfo = "processing nodes: " + str(self.processed) + " / " + str(self.totalNodes) if node.size() > 0: self.addEntry(node) if node.hasChildren(): folders.append(node) for folder in folders: self.getstat(folder.children()) class fileschart(Module): """Show statistics of filetype used for a file or a directory ex: statistics /mydump/""" def __init__(self): Module.__init__(self, "fileschart", FILESCHART) self.conf.addArgument({"name": "files", "description": "Directory or files used to render chart", "input": Argument.Required|Argument.List|typeId.Node}) self.tags = "Statistics" self.icon = ":chart" dff-1.3.0+dfsg.1/dff/modules/viewer/000077500000000000000000000000001217176075400170525ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/CMakeLists.txt000066400000000000000000000013421217176075400216120ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py ) add_subdirectory(hexedit) add_subdirectory(regedit) add_subdirectory(bindiff) add_subdirectory(timeline) add_subdirectory(web) add_subdirectory(media) dff-1.3.0+dfsg.1/dff/modules/viewer/__init__.py000066400000000000000000000011561217176075400211660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['cat', 'hexedit', 'bindiff', 'player', 'evt', 'media'] dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/000077500000000000000000000000001217176075400204535ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/BDiff.py000077500000000000000000000151221217176075400220030ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string from PyQt4.QtGui import * from PyQt4.QtCore import * from dff.api.vfs import * from dff.api.vfs.libvfs import * from dff.api.exceptions.libexceptions import * from dff.modules.bindiff.hexView import * from dff.modules.bindiff.lfscrollbar import * class BDiff(QWidget): def __init__(self, parent): super(BDiff, self).__init__(parent) self.mainWindow = parent self.vfs = vfs.vfs() def init(self, node1, node2): self.node1 = node1 self.node2 = node2 self.vfile1 = node1.open() self.vfile2 = node2.open() self.initInfos() #Init view and scene self.initShape() #First Read and Sector Shape Creation try: self.vfile1.seek(0) self.vfile2.seek(0) buffer1 = self.vfile1.read(self.pageSize) buffer2 = self.vfile2.read(self.pageSize) self.updateCurrents(0) self.whex.updateItems(0, buffer1) self.whex2.updateItems(0, buffer2) self.processPageDiff(buffer1, buffer2) self.whex.hexitem.initStartBlank() self.whex.asciitem.initStartBlank() self.whex2.hexitem.initStartBlank() self.whex2.asciitem.initStartBlank() except vfsError, e: print e.error def initInfos(self): #Files Size self.file1size = self.node1.size() self.file2size = self.node2.size() #Set Master file if self.file1size > self.file2size: self.masterFile = self.vfile1 self.masterFileSize = self.file1size else: self.masterFile = self.vfile2 self.masterFileSize = self.file2size #Offset self.currentOffset = 0 # Offset Base : 0:HEX 1:DEC 2:BIN self.opt_offsetBase = 0 #Pages self.currentPage = 0 self.pageSize = 256 self.pageHead = 0 self.pageSpare = 0 self.pagesPerBlock = 32 self.bytesPerLine = 16 self.groupBytes = 1 def initShape(self): #General Layout : Header + View + Footer self.vlayout = QVBoxLayout() self.vlayout.setSpacing(0) self.hlayout = QHBoxLayout() self.hlayout.setSpacing(0) self.whex = wHex(self) self.whex2 = wHex(self) self.whex.view.setSyncView(self.whex2.view) self.whex2.view.setSyncView(self.whex.view) self.hexcontainer = QWidget() self.vlayout.addWidget(self.whex) self.vlayout.addWidget(self.whex2) self.hexcontainer.setLayout(self.vlayout) self.hlayout.addWidget(self.hexcontainer) self.scrollbar = LFScrollBar(self) self.hlayout.addWidget(self.scrollbar) self.setLayout(self.hlayout) def processDiffList(self, difflist): cp = 0 tmplen = 0 tmpoffset = difflist[0] diffinfos = {} while cp <= len(difflist): if (cp + 1) < len(difflist): if difflist[cp + 1] == difflist[cp] + 1: tmplen = tmplen + 1 cp = cp + 1 else: cp = cp + 1 diffinfos[tmpoffset] = tmplen + 1 tmpoffset = difflist[cp] tmplen = 0 else: diffinfos[tmpoffset] = tmplen + 1 cp = cp + 1 return diffinfos def processPageDiff(self, buff1, buff2): difflist = self.diffBuffers(buff1, buff2) if len(difflist) > 0: diffinfos = self.processDiffList(difflist) self.whex.hexitem.colorizeDiff(diffinfos) self.whex.asciitem.colorizeDiff(diffinfos) self.whex2.hexitem.colorizeDiff(diffinfos) self.whex2.asciitem.colorizeDiff(diffinfos) def diffBuffers(self, buff1, buff2): cp = 0 difflist = [] buff1len = len(buff1) buff2len = len(buff2) if buff1len != buff2len: if buff1len > buff2len: masterlen = buff1len minorlen = buff2len else: masterlen = buff2len minorlen = buff1len else: minorlen = buff1len masterlen = buff1len while cp < minorlen: if buff1[cp] != buff2[cp]: difflist.append(cp) cp = cp + 1 rangelen = masterlen - minorlen l = 0 while l < rangelen: difflist.append(cp) cp = cp + 1 l = l + 1 return difflist def updateCurrents(self, offset): # print "update offset : ", offset self.currentOffset = offset self.currentPage = offset / self.pageSize self.currentBlock = offset / (self.pageSize * self.pagesPerBlock) ########################################## # READ OPERATIONS # ########################################## def readOffset(self, offset): #Transform offset to start of its line line = offset / self.bytesPerLine readoff = line * self.bytesPerLine buffer1 = "" if readoff >= 0: if readoff < self.file1size: try: self.vfile1.seek(readoff) buffer1 = self.vfile1.read(self.pageSize) self.whex.updateItems(offset, buffer1) except vfsError, e: print "Read Offset: I/O error" else: self.whex.hexitem.dumpEOF() buffer2 = "" if readoff < self.file2size: try: self.vfile2.seek(readoff) buffer2 = self.vfile2.read(self.pageSize) self.whex2.updateItems(offset, buffer2) except vfsError, e: print "Read Offset: I/O error" else: self.whex2.hexitem.dumpEOF() self.processPageDiff(buffer1, buffer2) self.updateCurrents(readoff) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/CMakeLists.txt000077500000000000000000000012531217176075400232170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier install_file( __init__.py binarydiff.py lfscrollbar.py BDiff.py asciiItem.py hexItem.py hexView.py offsetItem.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/__init__.py000077500000000000000000000011311217176075400225630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # __all__ = ["binarydiff", "BDiff", "hexView"] dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/asciiItem.py000077500000000000000000000134641217176075400227470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from PyQt4.QtCore import QString, Qt from PyQt4.QtGui import QWidget, QFont, QColor, QTextCursor, QGraphicsTextItem, QGraphicsItem, QPen, QFontMetrics, QTextCharFormat, QBrush class asciiItem(QGraphicsTextItem): def __init__(self, whex): QGraphicsTextItem.__init__(self) self.initValues(whex) self.initPosition() self.initFont() self.initMetricsValues() # self.initCursor() def initPosition(self): self.setPos(485, 25) # self.setTextInteractionFlags(Qt.TextSelectableByMouse) def initValues(self, whex): self.whex = whex self.bdiff = self.whex.bdiff #Buffer self.buffer = [] self.bufferLines = 0 #Line self.currentLine = 0 #Offset self.startOffset = 0 self.fontPixel = 14 #Current Positions self.currentPos = 0 # def initCursor(self): # self.cursor = asciiCursor(self) # self.bdiff.scene.addItem(self.cursor) def initFont(self): self.setDefaultTextColor(QColor(Qt.darkCyan)) self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(self.fontPixel) self.setFont(self.font) self.sfont = QFont("Gothic") self.sfont.setFixedPitch(1) self.sfont.setBold(False) self.sfont.setPixelSize(self.fontPixel) self.metric = QFontMetrics(self.font) self.metric = QFontMetrics(self.font) def initMetricsValues(self): #Calibrate calibrate = QString("A") self.charsByByte = 1 self.charW = self.metric.width(calibrate) self.charH = self.metric.height() self.byteW = self.charW * self.charsByByte self.byteH = self.charH def initStartBlank(self): self.lineW = self.boundingRect().width() self.startBlank = self.lineW - (self.byteW * 16) # print "start ASCII blank" # print self.startBlank #Print Operations def printBuffer(self, buff): del self.buffer self.buffer = buff count = 0 printer = QString() for char in buff: if char > "\x20" and char < "\x7e": printer.append(char) else: printer.append(".") if count < 15: count += 1 else: printer.append("\n") count = 0 #Clear and set cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText(printer) cursor.movePosition(QTextCursor.Start) def colorizeDiff(self, diffinfos): cursor = self.textCursor() cursor.setPosition(QTextCursor.Start) text = self.toPlainText() keys = diffinfos.keys() keys.sort() for offset in keys: difflen = diffinfos[offset] pos = offset + (offset / 16) # count = offset / 16 # print "offset ", offset, " count ", count count = difflen + (((offset + difflen) / 16) - (offset / 16)) # count = difflen cursor.setPosition(pos, QTextCursor.MoveAnchor) # print "L", l, " len ", pos + difflen cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, count) format = QTextCharFormat() format.setFont(self.sfont) format.setForeground(QBrush(QColor(Qt.red))) cursor.setCharFormat(format) cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor) #Update pixel Informations # def updateCurrentSelection(self, posx, posy): # self.currentSelection = self.bdiff.currentOffset + ((posy * 16) + posx) # def getXPos(self, x): # count = 0 # current = self.byteW + (self.startBlank / 2) # while current < x: # count += 1 # current = current + self.byteW # return count # def getYPos(self, y): # count = 0 # current = self.byteH # while current < y: # count += 1 # current = current + self.byteH # return count # def mouseMoveEvent(self, event): # pos = event.pos() # x = pos.x() # y = pos.y() # xpos = self.getXPos(x) # ypos = self.getYPos(y) # self.bdiff.selection.select(self.bdiff.selection.xstart, self.bdiff.selection.ystart, xpos, ypos) # self.bdiff.infos.update() # self.bdiff.right.decode.update() # def mousePressEvent(self, event): # button = event.button() # pos = event.pos() # # if event.button() == 1: # #Get Clicked coordonates # x = pos.x() # y = pos.y() # #Transform pixel into cursor position # xpos = self.getXPos(x) # ypos = self.getYPos(y) # self.whex.asciicursor.draw(xpos, ypos) # self.whex.hexcursor.draw(xpos, ypos) #Refresh hexadecimal cursor # self.bdiff.selection.select(xpos, ypos, xpos, ypos, True) # self.bdiff.right.decode.update() # self.bdiff.infos.update() # def mouseReleaseEvent(self, event): # pass dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/binarydiff.py000077500000000000000000000045771217176075400231620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # __dff_module_binarydiff_version__ = "1.0.0" import sys from PyQt4.QtCore import QSize, SIGNAL from PyQt4.QtGui import QWidget, QVBoxLayout, QIcon from dff.api.module.script import * from dff.api.vfs import * from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId from BDiff import BDiff class binDiff(QWidget, Script): def __init__(self): Script.__init__(self, "bindiff") self.type = "bindiff" self.icon = "" def start(self, args) : self.args = args def c_display(self): pass # node = self.args.get_node("file") # try: # nceditor.start(node) # except NameError: # print "This functionality is not available on your operating system" def g_display(self): QWidget.__init__(self) self.vlayout = QVBoxLayout(self) self.widget = BDiff(self) self.vlayout.addWidget(self.widget) try: node1 = self.args["file1"].value() node2 = self.args["file2"].value() self.name = "binDiff " + str(node1.name()) + " | " + str(node2.name()) self.widget.init(node1, node2) except: pass def updateWidget(self): pass def initCallback(self): pass def refresh(self): pass class binarydiff(Module): """Display hexadecimal differences of two binary files.""" def __init__(self): Module.__init__(self, "diff", binDiff) self.conf.addArgument({"name": "file1", "description": "first file", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "file2", "description": "second file", "input": Argument.Required|Argument.Single|typeId.Node}) self.tags = "Viewers" dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/cursors.py000077500000000000000000000100641217176075400225310ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, QPointF from PyQt4.QtGui import QWidget, QFont, QColor, QBrush, QPen, QGraphicsRectItem class hexCursor(QGraphicsRectItem): def __init__(self, whex): QGraphicsRectItem.__init__(self) self.init(whex) def init(self, whex): self.whex = whex self.hexitem = self.whex.hexitem self.bdiff = self.whex.bdiff self.w = self.hexitem.byteW self.h = self.w self.xpos = 0 self.ypos = 0 self.brush = QBrush(Qt.NoBrush) self.pen = QPen(QColor(Qt.darkCyan)) self.setBrush(self.brush) self.setPen(self.pen) # self.setParentItem(parent) def draw(self, posx, posy): x = 95 + (posx * self.hexitem.byteW) + (posx * self.hexitem.charW) + (self.hexitem.startBlank / 2) y = 25 + (posy * self.hexitem.byteH) + (self.hexitem.startBlank / 2) self.xpos = posx self.ypos = posy self.setRect(x, y, self.w, self.h) self.setVisible(True) def update(self): x = (self.bdiff.selection.offset - self.bdiff.currentOffset) % self.bdiff.bytesPerLine y = (self.bdiff.selection.offset - self.bdiff.currentOffset) / self.bdiff.bytesPerLine if y >= 0 and y < (self.bdiff.readSize / self.bdiff.bytesPerLine): self.setVisible(True) self.xpos = x self.ypos = y self.draw(x, y) else: self.setVisible(False) # if (self.bdiff.selection.offset >= self.bdiff.currentOffset) and (self.bdiff.selection.offset < (self.bdiff.currentOffset + self.bdiff.pageSize)): #For futur implementations # def moveUp(self, move): # if (self.ypos - move) > 0: # self.ypos -= move # x = 95 + (self.xpos * 20) + (self.xpos * 4) # y = 25 + (self.ypos * 15) + (self.ypos * 4) # self.setRect(x, y, self.w, self.h) # else: # self.setVisible(False) # def moveDown(self, move): # if (self.ypos + move) < 32: # self.ypos += move # x = 95 + (self.xpos * 20) + (self.xpos * 4) # y = 25 + (self.ypos * 15) + (self.ypos * 4) # self.setRect(x, y, self.w, self.h) # else: # self.setVisible(False) class asciiCursor(QGraphicsRectItem): def __init__(self, whex): QGraphicsRectItem.__init__(self) self.init(whex) def init(self, whex): self.whex = whex self.asciitem = self.whex.asciitem self.bdiff = self.whex.bdiff self.w = self.asciitem.byteW self.h = self.w * 2 self.brush = QBrush(Qt.NoBrush) self.pen = QPen(QColor(Qt.black)) self.setBrush(self.brush) self.setPen(self.pen) # self.setParentItem(whex) def draw(self, posx, posy): x = 95 + 390 + (posx * self.asciitem.byteW) + (self.asciitem.startBlank / 2) y = 25 + (posy * self.asciitem.byteH) + (self.asciitem.startBlank / 2) self.xpos = posx self.ypos = posy self.setRect(x, y, self.w, self.h) self.setVisible(True) def update(self): x = (self.bdiff.selection.offset - self.bdiff.currentOffset) % self.bdiff.bytesPerLine y = (self.bdiff.selection.offset - self.bdiff.currentOffset) / self.bdiff.bytesPerLine if y >= 0 and y < (self.bdiff.readSize / self.bdiff.bytesPerLine): self.setVisible(True) self.ypos = y self.xpos = x self.draw(x, y) else: self.setVisible(False) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/goto.py000077500000000000000000000141001217176075400217740ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL, QLineF from PyQt4.QtGui import QWidget, QHBoxLayout, QVBoxLayout, QGroupBox, QLabel, QGridLayout, QComboBox, QLineEdit, QPushButton, QCheckBox from dff.modules.hexedit.messagebox import * class goto(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.bdiff = parent def initShape(self): self.vbox = QVBoxLayout() self.createGoto() self.createOptions() fill = QWidget() self.vbox.addWidget(fill) #Go button self.gobutton = QPushButton("Go") self.connect(self.gobutton, SIGNAL('clicked()'), self.go) self.vbox.addWidget(self.gobutton) self.setLayout(self.vbox) def createGoto(self): self.offbox = QGroupBox("Go to location") self.offgrid = QGridLayout() #Format formatlabel = QLabel("Format :") self.format = QComboBox() self.format.addItem("Hexadecimal") self.format.addItem("Decimal") #Type: Offset, Page, Block typelabel = QLabel("Type :") self.type = QComboBox() self.type.addItem("Offset") self.type.addItem("Page") self.type.addItem("Block") #Place offsetlabel = QLabel("Place :") self.offset = QLineEdit() self.offgrid.addWidget(formatlabel, 0, 0) self.offgrid.addWidget(self.format, 0, 1) self.offgrid.addWidget(typelabel, 1, 0) self.offgrid.addWidget(self.type, 1, 1) self.offgrid.addWidget(offsetlabel, 2, 0) self.offgrid.addWidget(self.offset, 2, 1) self.offbox.setLayout(self.offgrid) self.vbox.addWidget(self.offbox) def createOptions(self): self.optbox = QGroupBox("Options") self.optgrid = QGridLayout() self.fromcursor = QCheckBox("From cursor") self.backwards = QCheckBox("Backwards") self.optgrid.addWidget(self.fromcursor, 0, 0) self.optgrid.addWidget(self.backwards, 1, 0) self.optbox.setLayout(self.optgrid) self.vbox.addWidget(self.optbox) def checkLocation(self, str, base, type): offset = QString(str) off = offset.toULongLong(base) if off[1]: if type == "Offset": if off[0] < self.bdiff.masterFileSize: return off[0] else: msg = MessageBoxError(self.bdiff, "Offset value too high") msg.exec_() return -1 elif type == "Page": if off[0] < self.bdiff.pages: return off[0] else: msg = MessageBoxError(self.bdiff, "Page value too high") msg.exec_() return -1 elif type == "Block": if off[0] < self.bdiff.blocks: return off[0] else: msg = MessageBoxError(self.bdiff, "Block value too high") msg.exec_() return -1 else: return -1 else: msg = MessageBoxError(self.bdiff, "Base conversion Error") msg.exec_() return -1 return -1 def getOffset(self, offset, fromcursor, back, type): #Init position if type == "Offset": if fromcursor: off = self.bdiff.currentOffset if back: off -= offset else: off += offset else: if back: off = self.bdiff.masterFileSize - offset else: off = offset return off elif type == "Page": if fromcursor: off = self.bdiff.currentPage if back: off -= offset else: off += offset else: if back: off = self.bdiff.pages - offset else: off = offset return (off * self.bdiff.pageSize) elif type == "Block": if fromcursor: off = self.bdiff.currentBlock if back: off -= offset else: off += offset else: if back: off = self.bdiff.blocks - offset else: off = offset return (off * (self.bdiff.pageSize * self.bdiff.pagesPerBlock)) else: return -1 return -1 def go(self): format = self.format.currentText() off = self.offset.text() type = self.type.currentText() opt_fromcursor = self.fromcursor.isChecked() opt_backwards = self.backwards.isChecked() if format == "Hexadecimal": offset = self.checkLocation(str(off), 16, type) else: offset = self.checkLocation(str(off), 10, type) print offset if offset != -1: off = self.getOffset(offset, opt_fromcursor, opt_backwards, type) print off if off != -1: self.bdiff.readOffset(off) else: msg = MessageBoxError(self.bdiff, "Problem in offset conversion") msg.exec_() def keyPressEvent(self, kEvent): key = kEvent.key() if key == Qt.Key_Return or key == Qt.Key_Enter: self.go() dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/hexItem.py000077500000000000000000000106521217176075400224370ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from PyQt4.QtCore import QString, Qt, QRegExp from PyQt4.QtGui import QWidget, QFont, QColor, QTextCursor, QGraphicsTextItem, QFontMetrics, QTextDocument, QSyntaxHighlighter, QTextCharFormat, QBrush #from cursors import hexCursor class hexItem(QGraphicsTextItem): def __init__(self, whex): QGraphicsTextItem.__init__(self) self.initValues(whex) self.initPosition() self.initFont() self.initMetricsValues() def initPosition(self): self.setPos(95, 25) def initValues(self, whex): self.whex = whex self.bdiff = self.whex.bdiff self.hexview = self.whex.view #Buffer self.buffer = [] self.fontPixel = 14 #Current Position self.bytesPerLine = self.bdiff.bytesPerLine self.groupBytes = self.bdiff.groupBytes #Selection self.select = False self.xsel = 0 self.ysel = 0 def initDocument(self): self.document = QTextDocument() self.setDocument(self.document) def initFont(self): self.setDefaultTextColor(QColor(Qt.black)) self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(self.fontPixel) # self.setFont(self.font) self.setFont(self.font) #Search Highlight font self.sfont = QFont("Gothic") self.sfont.setFixedPitch(1) self.sfont.setBold(False) self.sfont.setPixelSize(self.fontPixel) self.metric = QFontMetrics(self.font) def initMetricsValues(self): #Calibrate calibrate = QString("A") self.charsByByte = 2 * self.groupBytes self.charW = self.metric.width(calibrate) self.charH = self.metric.height() self.byteW = self.charW * self.charsByByte self.byteH = self.charH def initStartBlank(self): self.lineW = self.boundingRect().width() self.startBlank = self.lineW - (self.byteW * self.bytesPerLine) - (self.charW * (self.bytesPerLine - 1)) #Print Operations def dumpHexBuffer(self, buff): self.printFullBuffer(buff) def dumpEOF(self): cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText("\t\tEnd of file") cursor.movePosition(QTextCursor.Start) def printFullBuffer(self, buff): del self.buffer pos = str(len(buff)) + 'B' self.buffer = struct.unpack(pos, buff) count = 0 fullBuff = QString() for byte in self.buffer: fullBuff.append("%.2x" % byte) if count < 15: fullBuff.append(" ") count += 1 else: fullBuff.append("\n") count = 0 cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText(fullBuff) cursor.movePosition(QTextCursor.Start) def colorizeDiff(self, diffinfos): cursor = self.textCursor() cursor.setPosition(QTextCursor.Start) text = self.toPlainText() keys = diffinfos.keys() keys.sort() for offset in keys: difflen = diffinfos[offset] pos = (offset * 2) + offset count = difflen + (((offset + difflen) / 16) - (offset / 16)) cursor.setPosition(pos, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.NextWord, QTextCursor.KeepAnchor, count) format = QTextCharFormat() format.setFont(self.sfont) format.setForeground(QBrush(QColor(Qt.red))) cursor.setCharFormat(format) cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/hexView.py000077500000000000000000000146001217176075400224500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import Qt, QLineF from PyQt4.QtGui import QGraphicsView, QKeySequence, QHBoxLayout, QWidget, QFont, QGraphicsScene, QGraphicsLineItem, QGraphicsTextItem from dff.modules.bindiff.hexItem import * from dff.modules.bindiff.asciiItem import * from dff.modules.bindiff.offsetItem import * class wHex(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.bdiff = parent self.bytesPerLine = self.bdiff.bytesPerLine def initShape(self): self.hbox = QHBoxLayout() self.view = hexView(self) #Init Items self.hexitem = hexItem(self) self.offsetitem = offsetItem(self) self.asciitem = asciiItem(self) self.view.setItems() self.hbox.addWidget(self.view) self.setLayout(self.hbox) def updateItems(self, offset, buffer): self.offsetitem.printFullOffset(offset, (len(buffer) / self.bytesPerLine)) self.hexitem.dumpHexBuffer(buffer) self.asciitem.printBuffer(buffer) class hexView(QGraphicsView): def __init__(self, parent): QGraphicsView.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.whex = parent self.bdiff = self.whex.bdiff #Init scene self.scene = QGraphicsScene() self.setScene(self.scene) #Get bdiff stuff self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) def setItems(self): self.scene.addItem(self.whex.offsetitem) self.scene.addItem(self.whex.hexitem) self.scene.addItem(self.whex.asciitem) def initShape(self): self.initHeads() #Line decoration offsetLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) asciiLine = QGraphicsLineItem(QLineF(480, 0, 480, 700)) #Add to scene self.scene.addItem(offsetLine) self.scene.addItem(asciiLine) def initHeads(self): self.offHead = QGraphicsTextItem() self.hexHead = QGraphicsTextItem() self.asciiHead = QGraphicsTextItem() #Set Color self.offHead.setDefaultTextColor(QColor(Qt.red)) self.hexHead.setDefaultTextColor(QColor(Qt.black)) self.asciiHead.setDefaultTextColor(QColor(Qt.darkCyan)) #Create Font self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) #Set Font self.offHead.setFont(self.font) self.hexHead.setFont(self.font) self.asciiHead.setFont(self.font) #Set Text self.offHead.setPlainText("Offset") self.hexHead.setPlainText("0 1 2 3 4 5 6 7 8 9 A B C D E F") self.asciiHead.setPlainText("Ascii") #Position self.offHead.setPos(20, 0) self.hexHead.setPos(95, 0) self.asciiHead.setPos(520, 0) #Add to scene self.scene.addItem(self.offHead) self.scene.addItem(self.hexHead) self.scene.addItem(self.asciiHead) headLine = QGraphicsLineItem(QLineF(0, 20, 615, 20)) self.scene.addItem(headLine) def setSyncView(self, whexview): self.whexviewsync = whexview def move(self, step, way): #step: line = 1 * bytesPerLine, page = pagesize, wheel = 3 * bytesPerLine offset = self.bdiff.currentOffset # print offset if way == 0: #UP if (offset - (step * self.bdiff.bytesPerLine)) >= 0: self.bdiff.readOffset(offset - (step * self.bdiff.bytesPerLine)) if self.bdiff.scrollbar.isLFMOD(): self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.offsetToValue(offset - (step * self.bdiff.bytesPerLine))) else: self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.value() - step) else: self.bdiff.readOffset(0) self.bdiff.scrollbar.setValue(0) elif way == 1: #Down if (offset + (step * self.bdiff.bytesPerLine)) <= (self.bdiff.masterFileSize - (step * self.bdiff.bytesPerLine)): self.bdiff.readOffset(offset + (step * self.bdiff.bytesPerLine)) if self.bdiff.scrollbar.isLFMOD(): self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.offsetToValue(offset + (step * self.bdiff.bytesPerLine))) else: self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.value() + step) else: self.bdiff.readOffset(self.bdiff.masterFileSize - 5 * (self.bdiff.bytesPerLine)) self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.max) #################################### # Navigation Operations # #################################### def wheelEvent(self, event): offset = self.bdiff.currentOffset if event.delta() > 0: self.move(3, 0) self.whexviewsync.move(3, 0) else: self.move(3, 1) self.whexviewsync.move(3, 1) def keyPressEvent(self, keyEvent): off = self.bdiff.currentOffset if keyEvent.matches(QKeySequence.MoveToNextPage): self.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 1) self.whexviewsync.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 1) elif keyEvent.matches(QKeySequence.MoveToPreviousPage): self.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 0) self.whexviewsync.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 0) elif keyEvent.matches(QKeySequence.MoveToNextLine): self.move(1, 1) self.whexviewsync.move(1, 1) elif keyEvent.matches(QKeySequence.MoveToPreviousLine): self.move(1, 0) self.whexviewsync.move(1, 0) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/lfscrollbar.py000077500000000000000000000073701217176075400233440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os from PyQt4.QtCore import Qt, SIGNAL from PyQt4.QtGui import QScrollBar, QAbstractSlider class LFScrollBar(QScrollBar): def __init__(self, bdiff): QScrollBar.__init__(self) self.init(bdiff) self.initCallBacks() self.setValues() def init(self, bdiff): self.bdiff = bdiff self.whex = bdiff.whex self.whex2 = bdiff.whex2 self.filesize = self.bdiff.masterFileSize #Initialized in Whex with LFMOD self.page = self.bdiff.pageSize self.max = 0 self.min = 0 self.single = 1 #Long File Mode self.lfmod = False ###### LFMOD ###### ################### self.maxint = 2147483647 self.lines = self.filesize / self.bdiff.bytesPerLine self.restlines = self.filesize % 16 if self.isInt(self.lines): self.max = self.lines - 1 self.page = self.bdiff.pageSize / 16 else: self.lfmod = True self.max = self.maxint - 1 self.page = self.bdiff.pageSize print self.max #################### #################### def initCallBacks(self): self.connect(self, SIGNAL("sliderMoved(int)"), self.moved) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) def setValues(self): self.setMinimum(self.min) self.setMaximum(self.max) self.setSingleStep(self.single) self.setPageStep(self.page) self.setRange(self.min, self.max) def isLFMOD(self): return self.lfmod def isInt(self, val): try: res = int(val) if res < self.maxint: return True else: return False except ValueError, TypeError: return False else: return False # LFMOD # def valueToOffset(self, value): return ((self.filesize * value) / self.maxint) def offsetToValue(self, offset): if self.isLFMOD(): return ((self.maxint * offset) / self.filesize) else: return (offset / self.bdiff.bytesPerLine) ######################################## # Navigation Operations # ######################################## def triggered(self, action): if action == QAbstractSlider.SliderSingleStepAdd: self.whex.view.move(self.singleStep(), 1) elif action == QAbstractSlider.SliderSingleStepSub: self.whex.view.move(self.singleStep(), 0) elif action == QAbstractSlider.SliderPageStepSub: self.whex.view.move(self.pageStep(), 0) elif action == QAbstractSlider.SliderPageStepAdd: self.whex.view.move(self.pageStep(), 1) def moved(self, value): if self.isLFMOD(): if value <= self.max: offset = (self.filesize * value) / self.maxint self.bdiff.readOffset(offset) else: if value <= self.max: if value == self.max: offset = self.filesize - (5 * self.bdiff.bytesPerLine) else: offset = value * self.bdiff.bytesPerLine self.bdiff.readOffset(offset) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/offsetItem.py000077500000000000000000000042471217176075400231440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from PyQt4.QtCore import QString, Qt from PyQt4.QtGui import QWidget, QFont, QColor, QTextCursor, QGraphicsTextItem class offsetItem(QGraphicsTextItem): def __init__(self, whex): QGraphicsTextItem.__init__(self) self.initValues(whex) # self.initShape() self.initPosition() self.initFont() def initPosition(self): self.setPos(0, 25) def initValues(self, whex): self.whex = whex self.bdiff = self.whex.bdiff #Buffer self.buffer = [] self.bufferLines = 0 #Line self.currentLine = 0 #Offset self.startOffset = 0 self.fontPixel = 14 def initFont(self): self.setDefaultTextColor(QColor(Qt.red)) self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(self.fontPixel) self.setFont(self.font) #Print Operations def printFullOffset(self, start, len): count = 0 fullBuff = QString() while count <= len: if self.bdiff.opt_offsetBase == 1: fullBuff.append("%.10d" % start) elif self.bdiff.opt_offsetBase == 0: fullBuff.append("%.10X" % start) fullBuff.append("\n") start += 16 count += 1 #Clear and set cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText(fullBuff) cursor.movePosition(QTextCursor.Start) dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/right.py000077500000000000000000000020651217176075400221500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL from PyQt4.QtGui import QWidget, QFont, QColor, QTabWidget from dff.modules.bindiff.goto import * class righTab(QTabWidget): def __init__(self, parent): QTabWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.bdiff = parent def initShape(self): #Add Value tab self.setTabPosition(QTabWidget.East) self.goto = goto(self.bdiff) self.insertTab(0, self.goto, "Goto") dff-1.3.0+dfsg.1/dff/modules/viewer/bindiff/selection.py000066400000000000000000000131741217176075400230200ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * class selection(): def __init__(self, bdiff, whex): self.init(bdiff, whex) self.initFont() def init(self, bdiff, whex): #Parent widgets and items self.bdiff = bdiff self.whex = whex # self.hexitem = parent.whex.hexitem # self.asciitem = parent.whex.asciitem #Start selection self.xstart = 0 self.ystart = 0 #End Selection self.xend = 0 self.yend = 0 self.length = 0 self.offset = 0 self.startoffset = 0 self.endoffset = 0 self.way = 0 def initFont(self): self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) def setWay(self): if ((self.xend - self.xstart) < 0) or ((self.yend - self.ystart) < 0): self.way = 0 else: self.way = 1 def setData(self): startoff = self.bdiff.currentOffset + ((self.ystart * self.bdiff.bytesPerLine) + self.xstart) endoff = self.bdiff.currentOffset + ((self.yend * self.bdiff.bytesPerLine) + self.xend) selelen = endoff - startoff if selelen < 0: selelen = selelen * -1 self.offset = startoff - selelen self.startoffset = self.offset self.xinit = self.xend self.yinit = self.yend else: self.offset = startoff + selelen self.startoffset = startoff self.xinit = self.xstart self.yinit = self.ystart self.length = selelen def setCount(self): self.ycount = self.length / self.bdiff.bytesPerLine self.xcount = self.length % self.bdiff.bytesPerLine if self.way > 0: self.xcount += 1 def select(self, xstart, ystart, xend, yend, first = False): self.resetSelection() if first: self.xstart = xstart self.ystart = ystart self.xend = xend self.yend = yend else: self.xend = xend self.yend = yend #Set Data selection self.setWay() self.setData() self.setCount() self.whex.hexcursor.update() self.whex.asciicursor.update() #Colorize process if self.length > 0: self.colorize() def update(self): self.initStartPosition() if self.length > 0: self.colorize() def initStartPosition(self): if self.way > 0: startrange = (self.offset - self.length) - self.bdiff.currentOffset else: startrange = self.offset - self.bdiff.currentOffset if startrange < 0: selelen = self.length - (startrange * -1) if selelen < 0: selelen = 0 startrange = 0 else: selelen = self.length self.yinit = startrange / self.bdiff.bytesPerLine self.xinit = startrange % self.bdiff.bytesPerLine self.ycount = selelen / self.bdiff.bytesPerLine self.xcount = selelen % self.bdiff.bytesPerLine def colorize(self): #Get hex cursor hexcur = self.getCursorSelection(0) self.colorizeCursor(hexcur, 0) asciicur = self.getCursorSelection(1) self.colorizeCursor(asciicur, 1) def getCursorSelection(self, item): #Init Position if item == 0: #Hexadecimal cursor = self.whex.hexitem.textCursor() xway = QTextCursor.NextWord else: #Ascii cursor = self.whex.asciitem.textCursor() xway = QTextCursor.NextCharacter cp = 0 while cp < self.yinit: cursor.movePosition(QTextCursor.Down, QTextCursor.MoveAnchor) cp += 1 cp = 0 while cp < self.xinit: cursor.movePosition(xway, QTextCursor.MoveAnchor) cp += 1 #Move Cursor cp = 0 while cp < self.ycount: cursor.movePosition(QTextCursor.Down, QTextCursor.KeepAnchor) cp += 1 cp = 0 while cp < self.xcount: cursor.movePosition(xway, QTextCursor.KeepAnchor) cp += 1 return cursor #Item: 0 hex 1 ascii def colorizeCursor(self, cursor, item): format = QTextCharFormat() format.setFont(self.font) if item == 0: format.setForeground(QBrush(QColor(Qt.blue))) else: format.setForeground(QBrush(QColor(Qt.blue))) cursor.setCharFormat(format) def resetSelection(self): self.resetColorSelection(self.whex.hexitem.textCursor()) self.resetColorSelection(self.whex.asciitem.textCursor()) def resetColorSelection(self, cursor): #Set Format bformat = QTextCharFormat() bformat.setFont(self.font) #Set Black Color cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) cursor.setCharFormat(bformat) cursor.movePosition(QTextCursor.Start) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/000077500000000000000000000000001217176075400205045ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/CMakeLists.txt000077500000000000000000000016641217176075400232560ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier install_file( Heditor.py __init__.py asciiItem.py bookmark.py cursors.py decodeValues.py messagebox.py footer.py goto.py hexItem.py hexView.py hexeditor.py informations.py navigation.py nceditor.py offsetItem.py options.py pageView.py pixelView.py right.py scrollbar.py search.py selection.py textItem.py utils.py lfscrollbar.py string.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/Heditor.py000077500000000000000000000256441217176075400224720ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * import binascii import struct import string from dff.api.vfs import * from dff.api.vfs.libvfs import * from dff.api.exceptions.libexceptions import * from dff.modules.hexedit.hexView import * from dff.modules.hexedit.pageView import * from dff.modules.hexedit.pixelView import * from dff.modules.hexedit.string import stringView from dff.modules.hexedit.bookmark import * from dff.modules.hexedit.informations import * from dff.modules.hexedit.right import * from dff.modules.hexedit.selection import * class Heditor(QWidget): def __init__(self, parent): super(Heditor, self).__init__(parent) self.mainWindow = parent self.vfs = vfs.vfs() def closeEvent(self, event): try: self.file.close() except AttributeError: pass def init(self, node, preview = False): self.node = node self.preview = preview try: self.file = node.open() except IOError as e: print e self.filesize = self.node.size() self.initInfos() #Init view and scene self.initShape() #First Read and Sector Shape Creation try: self.file.seek(0) buffer = self.file.read(self.readSize) self.updateCurrents(0) self.updateHexItems(buffer, 0, True) self.whex.asciicursor.draw(0, 0) self.whex.hexcursor.draw(0, 0) if not self.preview: self.right.decode.update() except vfsError, e: print e.error def initInfos(self): self.initOffsetInfos() self.initPageInfos() #XXX Screen size self.readSize = self.pageSize self.bytesPerLine = 16 self.linkmode = True self.cursorOffset = 0 self.groupBytes = 1 def initOffsetInfos(self): #Offset self.currentOffset = 0 self.decimalview = False def initPageInfos(self): #Sectors self.currentPage = 0 self.startBlockOffset = 0 self.pageSize = 512 if self.filesize < self.pageSize: self.pageSize = self.filesize self.pageHead = 0 self.pageSpare = 0 self.pagesPerBlock = 32 self.pages = self.filesize / self.pageSize if self.filesize % self.pageSize > 0: self.pages += 1 self.blocks = self.pages / self.pagesPerBlock self.currentBlock = 0 #Display offset or Block self.pageOffView = True def initShape(self): #General Layout : Header + View + Footer self.vlayout = QVBoxLayout() self.vlayout.setSpacing(0) self.vlayout.setMargin(0) self.vsplitter = QSplitter() self.lhsplitter = QSplitter() self.whex = wHex(self) self.lhsplitter.addWidget(self.whex) if not self.preview: #Add block and pixel views self.initFooterViews() #INIT SELECTION self.selection = selection(self) if not self.preview: self.pageselection = pageSelection(self) self.lhsplitter.setOrientation(Qt.Vertical) self.vsplitter.addWidget(self.lhsplitter) if not self.preview: self.right = righTab(self) self.infos = informations(self) self.vsplitter.addWidget(self.right) # self.lhsplitter.addWidget(self.infos) # self.vlayout.addWidget(self.toolbars) self.vlayout.addWidget(self.vsplitter) if not self.preview: self.vlayout.addWidget(self.infos) def shapeToolBars(self): self.htoolbox = QHBoxLayout() self.toolbars = QWidget() self.createToolBar() self.htoolbox.addWidget(self.hextoolbar) self.htoolbox.addWidget(self.book.booktool) self.toolbars.setLayout(self.htoolbox) def initFooterViews(self): self.footab = QTabWidget() self.footab.setTabPosition(QTabWidget.South) #Views self.wpage = wPage(self) self.wpixel = wPixel(self) self.wstring = stringView(self) #Bookmark self.book = bookmark(self) self.footab.insertTab(0, self.wpage, QIcon(":hex_page.png"),"Pages") self.footab.insertTab(1, self.wpixel, "Pixel") self.footab.insertTab(2, self.book, QIcon(":bookmark.png"), "Bookmarks") self.footab.insertTab(3, self.wstring, QIcon(":hex_page.png"),"String") self.lhsplitter.addWidget(self.footab) def toLineOffset(self, lineNumber): return (lineNumber * self.bytesPerLine) def toPageOffset(self, lineNumber): startLineOffset = lineNumber * self.bytesPerLine currentPage = startLineOffset / self.pageSize startPageOffset = currentPage * self.pageSize return startPageOffset def refreshPageValues(self, header, size, spare, len): self.pageHead = header self.pageSpare = spare self.pageSize = self.pageHead + size + self.pageSpare self.pagesPerBlock = len self.wpage.view.lines = self.filesize / (self.pagesPerBlock * self.pageSize) def updateHexItems(self, buffer, offset, first = None): self.whex.offsetitem.printFullOffset(offset, (len(buffer) / self.bytesPerLine)) self.whex.hexitem.dumpHexBuffer(buffer) self.whex.asciitem.printBuffer(buffer) if first: self.whex.hexitem.initStartBlank() self.whex.asciitem.initStartBlank() def updateCurrents(self, offset): self.currentOffset = offset self.currentPage = offset / self.pageSize self.currentBlock = offset / (self.pageSize * self.pagesPerBlock) ########################################## # SELECTION # ########################################## def getSelectionPos(self): range = self.currentSelection - self.currentOffset y = (range / self.bytesPerLine) x = range % self.bytesPerLine def createToolBar(self): self.hextoolbar = QToolBar() self.gohome = QAction(QIcon(":gohome_small.png"), "Go to start", self.hextoolbar) self.hextoolbar.addAction(self.gohome) self.goselection = QAction(QIcon(":goselection_small.png"), "Go to selection", self.hextoolbar) self.hextoolbar.addAction(self.goselection) self.gosearch = QAction(QIcon(":hex_search.png"), "Search", self.hextoolbar) self.hextoolbar.addAction(self.gosearch) self.goopt = QAction(QIcon(":hex_opt.png"), "Options", self.hextoolbar) self.hextoolbar.addAction(self.goopt) self.gohome.connect(self.gohome, SIGNAL("triggered()"), self.gohome_act) self.goselection.connect(self.goselection, SIGNAL("triggered()"), self.goselection_act) self.gosearch.connect(self.gosearch, SIGNAL("triggered()"), self.gosearch_act) self.goopt.connect(self.goopt, SIGNAL("triggered()"), self.goopt_act) ########################################## # TOOLBAR CALLBACK # ########################################## def gohome_act(self): pass def goselection_act(self): pass def gosearch_act(self): pass def goopt_act(self): pass ########################################## # READ OPERATIONS # ########################################## def readOffset(self, offset): #Transform offset to start of its line line = offset / self.bytesPerLine readoff = line * self.bytesPerLine if readoff >= 0 and readoff < self.filesize: try: # print "roff: ", readoff self.file.seek(readoff) buffer = self.file.read(self.readSize) self.updateCurrents(readoff) self.updateHexItems(buffer, readoff) if (self.selection.offset >= readoff) and (self.selection.offset < (readoff + self.pageSize)): self.selection.update() if not self.preview: self.infos.update() self.whex.asciicursor.update() self.whex.hexcursor.update() # if self.linkmode: #read pixel # self.wpixel.view.read_image(readoffset) #read page # print "readoff: ", readoffset, " Plus: ", self.startBlockOffset + (self.wpage.view.displayLines * (self.pageSize * self.pagesPerBlock)) # if readoffset > (self.startBlockOffset + (self.wpage.view.displayLines * (self.pageSize * self.pagesPerBlock))): # self.wpage.view.refreshOffsetItems(readoffset) # self.wpage.view.refreshPageItems(readoffset) if not self.preview: self.pageselection.selectPage(self.currentPage * self.pageSize) self.pageselection.update() # value = self.whex.offsetToValue(readoff) # print "value: ", value except vfsError, e: print "Read error" def readHexValue(self, offset, length): buff = [] if (offset >= 0 or offset < self.filesize) and length > 0: try: self.file.seek(offset) buffer = self.file.read(length) pos = str(len(buffer)) + 'B' buff = struct.unpack(pos, buffer) res = QString() for byte in buff: res.append("%.2X" % byte) return res except vfsError, e: print "Read error" def readAsciiValue(self, offset, length): buff = [] if (offset >= 0 or offset < self.filesize) and length > 0: try: self.file.seek(offset) buffer = self.file.read(length) res = QString() for char in buffer: if char > "\x20" and char < "\x7e": res.append(char) else: res.append(".") return res except vfsError, e: print "Read error" # def readPage(self, line): # start = (self.CurrentOffset / self.pageSize) * self.pageSize # offset = self.toPageOffset(line) # try: # self.file.seek(offset) # buffer = self.file.read(self.readSize) # self.updateHexItems(buffer, offset) # self.refreshSectorShape(buffer) # except vfsError, e: # print "Read error" dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/__init__.py000077500000000000000000000011301217176075400226130ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier __all__ = ["ViewerHexa", "Heditor", "search"] dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/asciiItem.py000077500000000000000000000113231217176075400227700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from cursors import * from PyQt4.QtCore import QString, Qt from PyQt4.QtGui import QWidget, QFont, QColor, QTextCursor, QGraphicsTextItem, QGraphicsItem, QPen, QFontMetrics class asciiItem(QGraphicsTextItem): def __init__(self, whex): QGraphicsTextItem.__init__(self) self.initValues(whex) self.initPosition() self.initFont() self.initMetricsValues() # self.initCursor() def initPosition(self): self.setPos(485, 25) # self.setTextInteractionFlags(Qt.TextSelectableByMouse) def initValues(self, whex): self.whex = whex self.heditor = self.whex.heditor #Buffer self.buffer = [] self.bufferLines = 0 #Line self.currentLine = 0 #Offset self.startOffset = 0 self.fontPixel = 14 #Current Positions self.currentPos = 0 # def initCursor(self): # self.cursor = asciiCursor(self) # self.heditor.scene.addItem(self.cursor) def initFont(self): self.setDefaultTextColor(QColor(Qt.darkCyan)) self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(self.fontPixel) self.setFont(self.font) self.metric = QFontMetrics(self.font) def initMetricsValues(self): #Calibrate calibrate = QString("A") self.charsByByte = 1 self.charW = self.metric.width(calibrate) self.charH = self.metric.height() self.byteW = self.charW * self.charsByByte self.byteH = self.charH def initStartBlank(self): self.lineW = self.boundingRect().width() self.startBlank = self.lineW - (self.byteW * 16) # print "start ASCII blank" # print self.startBlank #Print Operations def printBuffer(self, buff): del self.buffer self.buffer = buff count = 0 printer = QString() for char in buff: if char > "\x20" and char < "\x7e": printer.append(char) else: printer.append(".") if count < 15: count += 1 else: printer.append("\n") count = 0 #Clear and set cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText(printer) cursor.movePosition(QTextCursor.Start) #Update pixel Informations def updateCurrentSelection(self, posx, posy): self.currentSelection = self.heditor.currentOffset + ((posy * 16) + posx) def getXPos(self, x): count = 0 current = self.byteW + (self.startBlank / 2) while current < x: count += 1 current = current + self.byteW return count def getYPos(self, y): count = 0 current = self.byteH while current < y: count += 1 current = current + self.byteH return count def mouseMoveEvent(self, event): pos = event.pos() x = pos.x() y = pos.y() xpos = self.getXPos(x) ypos = self.getYPos(y) self.heditor.selection.select(self.heditor.selection.xstart, self.heditor.selection.ystart, xpos, ypos) if not self.heditor.preview: self.heditor.infos.update() self.heditor.right.decode.update() def mousePressEvent(self, event): button = event.button() pos = event.pos() if event.button() == 1: #Get Clicked coordonates x = pos.x() y = pos.y() #Transform pixel into cursor position xpos = self.getXPos(x) ypos = self.getYPos(y) self.whex.asciicursor.draw(xpos, ypos) self.whex.hexcursor.draw(xpos, ypos) #Refresh hexadecimal cursor self.heditor.selection.select(xpos, ypos, xpos, ypos, True) if not self.heditor.preview: self.heditor.right.decode.update() self.heditor.infos.update() def mouseReleaseEvent(self, event): pass dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/bookmark.py000066400000000000000000000216711217176075400226720ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL from PyQt4.QtGui import QWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QApplication, QHBoxLayout, QToolButton, QIcon, QToolBar, QAction, QDialog, QLineEdit, QLabel, QGridLayout, QDialogButtonBox, QLineEdit, QPixmap class bookmark(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent self.items = [] self.selectedItem = -1 def initShape(self): self.vbox = QVBoxLayout() self.vbox.setSpacing(0) self.dialog = bookDiag(self) self.initFunctions() self.initTree() self.setLayout(self.vbox) def initFunctions(self): self.booktool = QToolBar() self.booktool.setObjectName("Hexedit bookmark toolbar") self.add = QAction(QIcon(":bookmark_add.png"), "Add bookmark", self.booktool) self.booktool.addAction(self.add) self.rm = QAction(QIcon(":bookmark_rm.png"), "Remove bookmark", self.booktool) self.booktool.addAction(self.rm) self.edit = QAction(QIcon(":bookmark_toolbar.png"), "Edit bookmark", self.booktool) self.booktool.addAction(self.edit) #Callbacks self.add.connect(self.add, SIGNAL("triggered()"), self.addbook) self.rm.connect(self.rm, SIGNAL("triggered()"), self.rmbook) self.edit.connect(self.edit, SIGNAL("triggered()"), self.editbook) self.vbox.addWidget(self.booktool) def initTree(self): self.tree = QTreeWidget() self.tree.setColumnCount(5) headerLabels = [QApplication.translate("bookmark", "Address", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Length (dec)", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Length (hex)", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Hex value", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Ascii value", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Description", None, QApplication.UnicodeUTF8)] self.tree.setHeaderLabels(headerLabels) self.tree.setAlternatingRowColors(True) self.connect(self.tree, SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.treeClicked) self.connect(self.tree, SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"), self.treeDoubleClicked) self.vbox.addWidget(self.tree) #CALLBACKS def treeClicked(self, item, col): self.selectedItem = item def treeDoubleClicked(self, item, col): self.selectedItem = item add = QString(item.text(0)) off = add.toULongLong(16) if off[1]: self.heditor.readOffset(off[0]) # self.heditor.selection.offset = off[0] # self.heditor.whex.hexcursor.update() # self.heditor.whex.asciicursor.update() def getSelectedItemRow(self, address): cp = 0 for item in self.items: if item.text(0) == address: return cp cp += 1 return -1 def addbook(self): self.dialog.setInformations() ret = self.dialog.exec_() if ret == 1: #XXXCheck if offsetis present item = QTreeWidgetItem(self.tree) address = self.dialog.address.text() declen = self.dialog.lendec.text() hexlen = self.dialog.lenhex.text() hexval = self.dialog.hexvalue.text() asciival = self.dialog.asciivalue.text() description = self.dialog.description.text() item.setText(0, address) item.setText(1, declen) item.setText(2, hexlen) item.setText(3, hexval) item.setText(4, asciival) item.setText(5, description) self.items.append(item) def rmbook(self): if (self.selectedItem != -1) and len(self.items) > 0: row = self.getSelectedItemRow(self.selectedItem.text(0)) self.tree.takeTopLevelItem(row) self.items.remove(self.selectedItem) if len(self.items) > 0: if len(self.items) > row: self.selectedItem = self.items[row] else: self.selectedItem = self.items[row - 1] def editbook(self): print "edit" class bookDiag(QDialog): def __init__(self, parent): QDialog.__init__(self) self.setWindowTitle("Add bookmark entry") self.init(parent) self.initShape() def init(self, parent): self.bookmark = parent self.heditor = self.bookmark.heditor def createButtons(self): self.buttonbox = QDialogButtonBox() self.buttonbox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.connect(self.buttonbox, SIGNAL("accepted()"),self.accept) self.connect(self.buttonbox, SIGNAL("rejected()"),self.reject) return self.buttonbox def initShape(self): self.grid = QGridLayout() decoration = self.createDecoration() wButton = self.createButtons() wInfos = self.createInformations() self.grid.addWidget(decoration, 0, 0) self.grid.addWidget(wInfos, 1, 0) self.grid.addWidget(wButton, 2, 0) self.setLayout(self.grid) def createDecoration(self): self.deco = QWidget() self.hdeco = QHBoxLayout() pixlabel = QLabel() pix = QPixmap(":bookmark.png") pixlabel.setPixmap(pix) booklabel = QLabel("Add a description to this entry") self.hdeco.addWidget(pixlabel) self.hdeco.addWidget(booklabel) self.deco.setLayout(self.hdeco) return self.deco def createInformations(self): self.info = QWidget() self.igrid = QGridLayout() addressLabel = QLabel("Address: ") self.address = QLineEdit() self.address.setReadOnly(True) lend = QLabel("Length (dec): ") self.lendec = QLineEdit() self.lendec.setReadOnly(True) lenh = QLabel("Length (hex): ") self.lenhex = QLineEdit() self.lenhex.setReadOnly(True) deslabel = QLabel("Description: ") self.description = QLineEdit() hvlabel = QLabel("Hex value:") self.hexvalue = QLineEdit() self.hexvalue.setReadOnly(True) avlabel = QLabel("Ascii value:") self.asciivalue = QLineEdit() self.asciivalue.setReadOnly(True) self.igrid.addWidget(addressLabel, 0, 0, Qt.AlignLeft) self.igrid.addWidget(self.address, 0, 1, Qt.AlignLeft) self.igrid.addWidget(lend, 1, 0, Qt.AlignLeft) self.igrid.addWidget(self.lendec, 1, 1, Qt.AlignLeft) self.igrid.addWidget(lenh, 2, 0, Qt.AlignLeft) self.igrid.addWidget(self.lenhex, 2, 1, Qt.AlignLeft) self.igrid.addWidget(hvlabel, 3, 0, Qt.AlignLeft) self.igrid.addWidget(self.hexvalue, 3, 1, Qt.AlignLeft) self.igrid.addWidget(avlabel, 4, 0, Qt.AlignLeft) self.igrid.addWidget(self.asciivalue, 4, 1, Qt.AlignLeft) self.igrid.addWidget(deslabel, 5, 0, Qt.AlignLeft) self.igrid.addWidget(self.description, 5, 1, Qt.AlignLeft) self.info.setLayout(self.igrid) return self.info def cleanInformations(self): self.address.clear() self.lendec.clear() self.lenhex.clear() self.hexvalue.clear() self.asciivalue.clear() self.description.clear() def setInformations(self): self.cleanInformations() if self.heditor.decimalview: add = "%.2d" % self.heditor.selection.startoffset else: add = "0x" add += "%.2x" % self.heditor.selection.startoffset self.address.insert(add) if self.heditor.selection.length > 0: len = self.heditor.selection.length else: len = 1 tolendec = "%.1d" % len self.lendec.insert(tolendec) tolenhex = "0x" tolenhex += "%.1X" % len self.lenhex.insert(tolenhex) hval = self.heditor.readHexValue(self.heditor.selection.offset, len) self.hexvalue.insert(hval) aval = self.heditor.readAsciiValue(self.heditor.selection.offset, len) self.asciivalue.insert(aval) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/cursors.py000077500000000000000000000101471217176075400225640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, QPointF from PyQt4.QtGui import QWidget, QFont, QColor, QBrush, QPen, QGraphicsRectItem class hexCursor(QGraphicsRectItem): def __init__(self, whex): QGraphicsRectItem.__init__(self) self.init(whex) def init(self, whex): self.whex = whex self.hexitem = self.whex.hexitem self.heditor = self.whex.heditor self.w = self.hexitem.byteW self.h = self.w self.xpos = 0 self.ypos = 0 self.brush = QBrush(Qt.NoBrush) self.pen = QPen(QColor(Qt.darkCyan)) self.setBrush(self.brush) self.setPen(self.pen) # self.setParentItem(parent) def draw(self, posx, posy): x = 95 + (posx * self.hexitem.byteW) + (posx * self.hexitem.charW) + (self.hexitem.startBlank / 2) y = 25 + (posy * self.hexitem.byteH) + (self.hexitem.startBlank / 2) self.xpos = posx self.ypos = posy self.setRect(x, y, self.w, self.h) self.setVisible(True) def update(self): x = (self.heditor.selection.offset - self.heditor.currentOffset) % self.heditor.bytesPerLine y = (self.heditor.selection.offset - self.heditor.currentOffset) / self.heditor.bytesPerLine if y >= 0 and y < (self.heditor.readSize / self.heditor.bytesPerLine): self.setVisible(True) self.xpos = x self.ypos = y self.draw(x, y) else: self.setVisible(False) # if (self.heditor.selection.offset >= self.heditor.currentOffset) and (self.heditor.selection.offset < (self.heditor.currentOffset + self.heditor.pageSize)): #For futur implementations # def moveUp(self, move): # if (self.ypos - move) > 0: # self.ypos -= move # x = 95 + (self.xpos * 20) + (self.xpos * 4) # y = 25 + (self.ypos * 15) + (self.ypos * 4) # self.setRect(x, y, self.w, self.h) # else: # self.setVisible(False) # def moveDown(self, move): # if (self.ypos + move) < 32: # self.ypos += move # x = 95 + (self.xpos * 20) + (self.xpos * 4) # y = 25 + (self.ypos * 15) + (self.ypos * 4) # self.setRect(x, y, self.w, self.h) # else: # self.setVisible(False) class asciiCursor(QGraphicsRectItem): def __init__(self, whex): QGraphicsRectItem.__init__(self) self.init(whex) def init(self, whex): self.whex = whex self.asciitem = self.whex.asciitem self.heditor = self.whex.heditor self.w = self.asciitem.byteW self.h = self.w * 2 self.brush = QBrush(Qt.NoBrush) self.pen = QPen(QColor(Qt.black)) self.setBrush(self.brush) self.setPen(self.pen) # self.setParentItem(whex) def draw(self, posx, posy): x = 95 + 390 + (posx * self.asciitem.byteW) + (self.asciitem.startBlank / 2) y = 25 + (posy * self.asciitem.byteH) + (self.asciitem.startBlank / 2) self.xpos = posx self.ypos = posy self.setRect(x, y, self.w, self.h) self.setVisible(True) def update(self): x = (self.heditor.selection.offset - self.heditor.currentOffset) % self.heditor.bytesPerLine y = (self.heditor.selection.offset - self.heditor.currentOffset) / self.heditor.bytesPerLine if y >= 0 and y < (self.heditor.readSize / self.heditor.bytesPerLine): self.setVisible(True) self.ypos = y self.xpos = x self.draw(x, y) else: self.setVisible(False) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/decodeValues.py000077500000000000000000000110331217176075400234620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import struct import binascii from PyQt4.QtGui import * from PyQt4.QtCore import * from dff.api.exceptions.libexceptions import * class decodeValues(QWidget): def __init__(self, parent): QWidget.__init__(self) self.heditor = parent self.selection = self.heditor.selection self.layout = QVBoxLayout() self.createShape() self.layout.addWidget(self.decodeTree) self.setLayout(self.layout) def createShape(self): self.createTreeWidget() self.setTreeTypes() def createTreeWidget(self): self.decodeTree = QTreeWidget() self.decodeTree.setColumnCount(2) headerLabels = [QApplication.translate("decodeValues", "Type", None, QApplication.UnicodeUTF8), QApplication.translate("decodeValues", "Value", None, QApplication.UnicodeUTF8)] self.decodeTree.setHeaderLabels(headerLabels) self.decodeTree.setAlternatingRowColors(True) def setTreeTypes(self): self.byte = QTreeWidgetItem(self.decodeTree) self.byte.setText(0, "char8") self.ubyte = QTreeWidgetItem(self.decodeTree) self.ubyte.setText(0, "u_char8") self.short = QTreeWidgetItem(self.decodeTree) self.short.setText(0, "short16") self.ushort = QTreeWidgetItem(self.decodeTree) self.ushort.setText(0, "u_short16") self.int = QTreeWidgetItem(self.decodeTree) self.int.setText(0, "int32") self.uint = QTreeWidgetItem(self.decodeTree) self.uint.setText(0, "u_int32") self.long = QTreeWidgetItem(self.decodeTree) self.long.setText(0, "long64") self.ulong = QTreeWidgetItem(self.decodeTree) self.ulong.setText(0, "u_long64") self.binary = QTreeWidgetItem(self.decodeTree) self.binary.setText(0, "binary") self.hex = QTreeWidgetItem(self.decodeTree) self.hex.setText(0, "hexadecimal") def update(self): char = self.readConvers(1) short = self.readConvers(2) int = self.readConvers(4) long = self.readConvers(8) if char != -1: bchar = struct.unpack('b', char) charedit = "%.0d" % bchar self.byte.setText(1, charedit) bchar = struct.unpack('B', char) charedit = "0x" charedit += "%.0X" % bchar self.ubyte.setText(1, charedit) if short != -1: bshort = struct.unpack('h', short) shortedit = "%.0d" % bshort self.short.setText(1, shortedit) bshort = struct.unpack('H', short) shortedit = "0x" shortedit += "%.0X" % bshort self.ushort.setText(1, shortedit) if int != -1: bint = struct.unpack('i', int) intedit = "%.0d" % bint self.int.setText(1, intedit) bint = struct.unpack('I', int) intedit = "0x" intedit += "%.0X" % bint self.uint.setText(1, intedit) if long != -1: blong = struct.unpack('q', long) longedit = "%.0d" % blong self.long.setText(1, longedit) blong = struct.unpack('Q', long) longedit = "0x" longedit += "%.0X" % blong self.ulong.setText(1, longedit) if char != -1: bin = self.byte_to_bits_string(bchar[0]) hexa = "%.2X" % bchar[0] self.binary.setText(1, bin) self.hex.setText(1, hexa) def byte_to_bits_string(self, x): return "".join(map(lambda y:str((x>>y)&1), range(7, -1, -1))) def readConvers(self, size): try: offset = self.selection.offset if offset + size < self.heditor.filesize: self.heditor.file.seek(offset) buff = self.heditor.file.read(size) return buff else: return -1 except vfsError, e: print "error Conversion read" dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/footer.py000077500000000000000000000023361217176075400223630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL from PyQt4.QtGui import QWidget, QTabWidget from sectorView import * from bytePresence import * class footer(QTabWidget): def __init__(self, parent): QTabWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent self.setTabPosition(QTabWidget.East) def initShape(self): #Add Value tab self.sectors = sectorDisplay(self.heditor) self.pixel = bytePresence(self.heditor) self.insertTab(0, self.sectors, "Pages") self.insertTab(1, self.pixel, "Pixel") # self.insertTab(1, self.selected, "Values") dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/goto.py000077500000000000000000000141311217176075400220310ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL, QLineF from PyQt4.QtGui import QWidget, QHBoxLayout, QVBoxLayout, QGroupBox, QLabel, QGridLayout, QComboBox, QLineEdit, QPushButton, QCheckBox from dff.modules.hexedit.messagebox import * class goto(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent def initShape(self): self.vbox = QVBoxLayout() self.createGoto() self.createOptions() fill = QWidget() self.vbox.addWidget(fill) #Go button self.gobutton = QPushButton("Go") self.connect(self.gobutton, SIGNAL('clicked()'), self.go) self.vbox.addWidget(self.gobutton) self.setLayout(self.vbox) def createGoto(self): self.offbox = QGroupBox("Go to location") self.offgrid = QGridLayout() #Format formatlabel = QLabel("Format :") self.format = QComboBox() self.format.addItem("Hexadecimal") self.format.addItem("Decimal") #Type: Offset, Page, Block typelabel = QLabel("Type :") self.type = QComboBox() self.type.addItem("Offset") self.type.addItem("Page") self.type.addItem("Block") #Place offsetlabel = QLabel("Place :") self.offset = QLineEdit() self.offgrid.addWidget(formatlabel, 0, 0) self.offgrid.addWidget(self.format, 0, 1) self.offgrid.addWidget(typelabel, 1, 0) self.offgrid.addWidget(self.type, 1, 1) self.offgrid.addWidget(offsetlabel, 2, 0) self.offgrid.addWidget(self.offset, 2, 1) self.offbox.setLayout(self.offgrid) self.vbox.addWidget(self.offbox) def createOptions(self): self.optbox = QGroupBox("Options") self.optgrid = QGridLayout() self.fromcursor = QCheckBox("From cursor") self.backwards = QCheckBox("Backwards") self.optgrid.addWidget(self.fromcursor, 0, 0) self.optgrid.addWidget(self.backwards, 1, 0) self.optbox.setLayout(self.optgrid) self.vbox.addWidget(self.optbox) def checkLocation(self, str, base, type): offset = QString(str) off = offset.toULongLong(base) if off[1]: if type == "Offset": if off[0] < self.heditor.filesize: return off[0] else: msg = MessageBoxError(self.heditor, "Offset value too high") msg.exec_() return -1 elif type == "Page": if off[0] < self.heditor.pages: return off[0] else: msg = MessageBoxError(self.heditor, "Page value too high") msg.exec_() return -1 elif type == "Block": if off[0] < self.heditor.blocks: return off[0] else: msg = MessageBoxError(self.heditor, "Block value too high") msg.exec_() return -1 else: return -1 else: msg = MessageBoxError(self.heditor, "Base conversion Error") msg.exec_() return -1 return -1 def getOffset(self, offset, fromcursor, back, type): #Init position if type == "Offset": if fromcursor: off = self.heditor.currentOffset if back: off -= offset else: off += offset else: if back: off = self.heditor.filesize - offset else: off = offset return off elif type == "Page": if fromcursor: off = self.heditor.currentPage if back: off -= offset else: off += offset else: if back: off = self.heditor.pages - offset else: off = offset return (off * self.heditor.pageSize) elif type == "Block": if fromcursor: off = self.heditor.currentBlock if back: off -= offset else: off += offset else: if back: off = self.heditor.blocks - offset else: off = offset return (off * (self.heditor.pageSize * self.heditor.pagesPerBlock)) else: return -1 return -1 def go(self): format = self.format.currentText() off = self.offset.text() type = self.type.currentText() opt_fromcursor = self.fromcursor.isChecked() opt_backwards = self.backwards.isChecked() if format == "Hexadecimal": offset = self.checkLocation(str(off), 16, type) else: offset = self.checkLocation(str(off), 10, type) print offset if offset != -1: off = self.getOffset(offset, opt_fromcursor, opt_backwards, type) print off if off != -1: self.heditor.readOffset(off) else: msg = MessageBoxError(self.heditor, "Problem in offset conversion") msg.exec_() def keyPressEvent(self, kEvent): key = kEvent.key() if key == Qt.Key_Return or key == Qt.Key_Enter: self.go() dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/hexItem.py000077500000000000000000000154511217176075400224720ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from PyQt4.QtCore import QString, Qt, QRegExp from PyQt4.QtGui import QWidget, QFont, QColor, QTextCursor, QGraphicsTextItem, QFontMetrics, QTextDocument, QSyntaxHighlighter, QTextCharFormat, QBrush from cursors import hexCursor class hexItem(QGraphicsTextItem): def __init__(self, whex): QGraphicsTextItem.__init__(self) self.initValues(whex) self.initPosition() # self.initDocument() self.initFont() self.initMetricsValues() # self.initCursor() def initPosition(self): self.setPos(95, 25) def initValues(self, whex): self.whex = whex self.heditor = self.whex.heditor self.hexview = self.whex.view #Buffer self.buffer = [] self.fontPixel = 14 #Current Position self.bytesPerLine = self.heditor.bytesPerLine self.groupBytes = self.heditor.groupBytes #Selection self.select = False self.xsel = 0 self.ysel = 0 def initDocument(self): self.document = QTextDocument() self.setDocument(self.document) # def initSyntaxHighlighter(self): # self.search = self.heditor.right.search # self.highlighter = highlighter(self) # def initCursor(self): # self.cursor = hexCursor(self) # self.heditor.whex.view.scene.addItem(self.cursor) def initFont(self): self.setDefaultTextColor(QColor(Qt.black)) self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(self.fontPixel) # self.setFont(self.font) self.setFont(self.font) #Search Highlight font self.sfont = QFont("Gothic") self.sfont.setFixedPitch(1) self.sfont.setBold(False) self.sfont.setPixelSize(self.fontPixel) self.metric = QFontMetrics(self.font) def initMetricsValues(self): #Calibrate calibrate = QString("A") self.charsByByte = 2 * self.groupBytes self.charW = self.metric.width(calibrate) self.charH = self.metric.height() self.byteW = self.charW * self.charsByByte self.byteH = self.charH def initStartBlank(self): self.lineW = self.boundingRect().width() self.startBlank = self.lineW - (self.byteW * self.bytesPerLine) - (self.charW * (self.bytesPerLine - 1)) # print "start blank" # print self.startBlank # def getPatternOffsets(self, buff): # plist = self.search.searchedPatterns # startoffset = self.heditor.currentOffset # offlist = {} # for pattern, offsetlist in plist.iteritems(): # for offset in offsetlist: # if offset >= startoffset and offset <= startoffset + self.heditor.readSize: # offlist[offset - self.heditor.currentOffset] = len(pattern) / 2 # return offlist #Print Operations def dumpHexBuffer(self, buff): self.printFullBuffer(buff) # searchofflist = self.getPatternOffsets(buff) # if len(searchofflist) > 0: # highoffsets = searchofflist.keys() # highoffsets.sort() # self.highlighter(searchofflist) def printFullBuffer(self, buff): del self.buffer pos = str(len(buff)) + 'B' self.buffer = struct.unpack(pos, buff) count = 0 fullBuff = QString() for byte in self.buffer: fullBuff.append("%.2x" % byte) if count < 15: fullBuff.append(" ") count += 1 else: fullBuff.append("\n") count = 0 cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText(fullBuff) cursor.movePosition(QTextCursor.Start) # if len(self.search.searchedPatterns) > 0: # self.highlighter.highlightBlock(self.document.toPlainText()) def getXPos(self, x): count = 0 current = self.byteW + (self.charW / 2) + (self.startBlank / 2) while current < x: count += 1 current = current + self.byteW + self.charW return count def getYPos(self, y): count = 0 current = self.byteH while current < y: count += 1 current = current + self.byteH return count def highlighter(self, searchofflist): offsets = searchofflist.keys() cursor = self.textCursor() cursor.setPosition(QTextCursor.Start) for offset in offsets: len = searchofflist[offset] pos = (offset * 2) + offset cursor.setPosition(pos, QTextCursor.MoveAnchor) l = 0 while l < len: cursor.movePosition(QTextCursor.NextWord, QTextCursor.KeepAnchor) l += 1 format = QTextCharFormat() format.setFont(self.sfont) format.setForeground(QBrush(QColor(Qt.red))) cursor.setCharFormat(format) cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor) ############## # # MOUSE EVENTS # ########################### ############## # def mouseMoveEvent(self, event): pos = event.pos() x = pos.x() y = pos.y() xpos = self.getXPos(x) ypos = self.getYPos(y) self.heditor.selection.select(self.heditor.selection.xstart, self.heditor.selection.ystart, xpos, ypos) if not self.heditor.preview: self.heditor.infos.update() self.heditor.right.decode.update() def mousePressEvent(self, event): button = event.button() pos = event.pos() if event.button() == 1: #Get CLicked coordonates x = pos.x() y = pos.y() xpos = self.getXPos(x) ypos = self.getYPos(y) #refresh cursors self.whex.hexcursor.draw(xpos, ypos) self.whex.asciicursor.draw(xpos, ypos) self.heditor.selection.select(xpos, ypos, xpos, ypos, True) if not self.heditor.preview: self.heditor.right.decode.update() self.heditor.infos.update() def mouseReleaseEvent(self, event): pass dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/hexView.py000077500000000000000000000164431217176075400225100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import Qt, QLineF from PyQt4.QtGui import QGraphicsView, QKeySequence, QHBoxLayout, QWidget, QFont, QGraphicsScene, QGraphicsLineItem, QGraphicsTextItem from dff.modules.hexedit.hexItem import * from dff.modules.hexedit.offsetItem import * from dff.modules.hexedit.asciiItem import * from dff.modules.hexedit.scrollbar import hexScrollBar class wHex(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() self.initMode() def init(self, parent): self.heditor = parent def initShape(self): self.hbox = QHBoxLayout() self.hbox.setContentsMargins(0, 0, 0, 0) self.view = hexView(self) self.scroll = hexScrollBar(self) #Init Items self.hexitem = hexItem(self) self.offsetitem = offsetItem(self) self.asciitem = asciiItem(self) self.hexcursor = hexCursor(self) self.asciicursor = asciiCursor(self) self.view.setItems() self.view.setCursors() self.hbox.addWidget(self.view) self.hbox.addWidget(self.scroll) self.setLayout(self.hbox) #Set Long File Mode def initMode(self): self.lfmod = False self.maxint = 2147483647 self.lines = self.heditor.filesize / self.heditor.bytesPerLine if self.isInt(self.lines): self.scroll.max = self.lines - 1 else: self.lfmod = True self.scroll.max = self.maxint - 1 self.scroll.setValues() def offsetToValue(self, offset): if self.isLFMOD(): # print (self.maxint * offset) / self.heditor.filesize return ((self.maxint * offset) / self.heditor.filesize) else: return (offset / self.heditor.bytesPerLine) def isLFMOD(self): return self.lfmod def isInt(self, val): try: res = int(val) if res < 2147483647: return True else: return False except ValueError, TypeError: return False else: return False class hexView(QGraphicsView): def __init__(self, parent): QGraphicsView.__init__(self, None, parent) self.init(parent) self.initShape() def init(self, parent): self.whex = parent self.heditor = self.whex.heditor #Init scene self.__scene = QGraphicsScene(self) self.setScene(self.__scene) #Get heditor stuff self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) def setItems(self): self.__scene.addItem(self.whex.offsetitem) self.__scene.addItem(self.whex.hexitem) self.__scene.addItem(self.whex.asciitem) def initShape(self): self.initHeads() #Line decoration offsetLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) asciiLine = QGraphicsLineItem(QLineF(480, 0, 480, 700)) #Add to scene self.__scene.addItem(offsetLine) self.__scene.addItem(asciiLine) def setCursors(self): self.__scene.addItem(self.whex.hexcursor) self.__scene.addItem(self.whex.asciicursor) def initHeads(self): self.offHead = QGraphicsTextItem() self.hexHead = QGraphicsTextItem() self.asciiHead = QGraphicsTextItem() #Set Color self.offHead.setDefaultTextColor(QColor(Qt.red)) self.hexHead.setDefaultTextColor(QColor(Qt.black)) self.asciiHead.setDefaultTextColor(QColor(Qt.darkCyan)) #Create Font self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) #Set Font self.offHead.setFont(self.font) self.hexHead.setFont(self.font) self.asciiHead.setFont(self.font) #Set Text self.offHead.setPlainText("Offset") self.hexHead.setPlainText("0 1 2 3 4 5 6 7 8 9 A B C D E F") self.asciiHead.setPlainText("Ascii") #Position self.offHead.setPos(20, 0) self.hexHead.setPos(95, 0) self.asciiHead.setPos(520, 0) #Add to scene self.__scene.addItem(self.offHead) self.__scene.addItem(self.hexHead) self.__scene.addItem(self.asciiHead) headLine = QGraphicsLineItem(QLineF(0, 20, 615, 20)) self.__scene.addItem(headLine) def move(self, step, way): #step: line = 1 * bytesPerLine, page = pagesize, wheel = 3 * bytesPerLine offset = self.heditor.currentOffset if way == 0: #UP if (offset - (step * self.heditor.bytesPerLine)) >= 0: self.heditor.readOffset(offset - (step * self.heditor.bytesPerLine)) if self.whex.isLFMOD(): self.whex.scroll.setValue(self.whex.offsetToValue(offset - step * (self.heditor.bytesPerLine))) else: self.whex.scroll.setValue(self.whex.scroll.value() - step) else: self.heditor.readOffset(0) self.whex.scroll.setValue(0) elif way == 1: #Down if (offset + (step * self.heditor.bytesPerLine)) <= (self.heditor.filesize - (step * self.heditor.bytesPerLine)): self.heditor.readOffset(offset + (step * self.heditor.bytesPerLine)) if self.whex.isLFMOD(): self.whex.scroll.setValue(self.whex.offsetToValue(offset + step * (self.heditor.bytesPerLine))) else: self.whex.scroll.setValue(self.whex.scroll.value() + step) else: self.heditor.readOffset(self.heditor.filesize - 5 * (self.heditor.bytesPerLine)) self.whex.scroll.setValue(self.whex.scroll.max) #################################### # Navigation Operations # #################################### def wheelEvent(self, event): offset = self.heditor.currentOffset if event.delta() > 0: self.move(3, 0) else: self.move(3, 1) def keyPressEvent(self, keyEvent): # off = self.heditor.currentOffset if keyEvent.matches(QKeySequence.MoveToNextPage): self.move(self.heditor.pageSize / self.heditor.bytesPerLine, 1) elif keyEvent.matches(QKeySequence.MoveToPreviousPage): self.move(self.heditor.pageSize / self.heditor.bytesPerLine, 0) elif keyEvent.matches(QKeySequence.MoveToNextWord): print "Next Word" elif keyEvent.matches(QKeySequence.MoveToPreviousWord): print "Previous word" elif keyEvent.matches(QKeySequence.MoveToNextLine): print "Next Line" elif keyEvent.matches(QKeySequence.MoveToPreviousLine): print "Previous Line" dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/hexeditor.py000077500000000000000000000051031217176075400230530ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # __dff_module_hexeditor_version__ = "1.0.0" import sys from PyQt4.QtCore import QSize, SIGNAL from PyQt4.QtGui import QWidget, QVBoxLayout, QIcon, QMessageBox from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.types.libtypes import Argument, typeId from dff.ui.gui.utils.utils import Utils from Heditor import Heditor try : import nceditor except ImportError: pass class ViewerHexa(QWidget, Script): def __init__(self): Script.__init__(self, "hexedit") self.type = "hexedit" # self.icon = ":hexedit.png" def start(self, args) : self.node = args["file"].value() try: self.preview = args["preview"].value() except IndexError: self.preview = False def c_display(self): try: nceditor.start(self.node) except NameError: print "This functionality is not available on your operating system" def g_display(self): QWidget.__init__(self) self.widget = Heditor(self) self.name = "hexedit " + str(self.node.name()) if self.node.size() > 0: self.widget.init(self.node, self.preview) self.setLayout(self.widget.vlayout) else: msg = QMessageBox(QMessageBox.Critical, "Hexadecimal viewer", "Error: File is empty", QMessageBox.Ok) msg.exec_() def closeEvent(self, event): self.widget.close() def updateWidget(self): pass def initCallback(self): pass def refresh(self): pass class hexeditor(Module): """Hexadecimal view of a file content""" def __init__(self): Module.__init__(self, "hexadecimal", ViewerHexa) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "file", "description": "File to display as hexadecimal"}) self.conf.addArgument({"name": "preview", "description": "Preview mode", "input": Argument.Empty}) self.tags = "Viewers" self.icon = ":hexedit.png" dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/informations.py000077500000000000000000000076741217176075400236070ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * class informations(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initFont() self.initShape() def init(self, parent): self.heditor = parent def initFont(self): self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) def initShape(self): self.viewLabel = QHBoxLayout() self.viewLabel.setContentsMargins(0, 0, 0, 0) # self.viewLabel.setSpacing(150) self.viewLabel.setAlignment(Qt.AlignLeft) self.createOffsetLabel(self.heditor.selection.offset) self.createPageLabel(self.heditor.currentPage) self.createBlockLabel(self.heditor.currentBlock) self.createSelectionLabel() self.setLayout(self.viewLabel) def createOffsetLabel(self, offset): # Offset labeltext = "Offset: " if self.heditor.decimalview: toint = "%.10d"% offset else: toint = "%.10x"% offset labeltext += toint self.offsetlabel = QLabel(labeltext) self.offsetlabel.setFont(self.font) self.viewLabel.addWidget(self.offsetlabel) def createPageLabel(self, page): #Sector Label labeltext = "| Page: " if self.heditor.decimalview: toint = "%d" % page else: toint = "%x" % page labeltext += toint self.pagelabel = QLabel(labeltext) self.pagelabel.setFont(self.font) self.viewLabel.addWidget(self.pagelabel) def createBlockLabel(self, block): #Sector Label labeltext = "| Block: " if self.heditor.decimalview: toint = "%d" % block else: toint = "%x" % block labeltext += toint self.blocklabel = QLabel(labeltext) self.blocklabel.setFont(self.font) self.viewLabel.addWidget(self.blocklabel) def createSelectionLabel(self): labeltext = "| Selection: -" self.selectlabel = QLabel(labeltext) self.selectlabel.setFont(self.font) self.viewLabel.addWidget(self.selectlabel) def update(self): #Update offset labeltext = "Offset: " if self.heditor.decimalview: toint = "%.10d"% self.heditor.selection.offset else: toint = "0x" toint += "%.10x"% self.heditor.selection.offset labeltext += toint self.offsetlabel.setText(labeltext) labeltext = "| Page: " if self.heditor.decimalview: toint = "%d" % self.heditor.currentPage else: toint = "0x" toint += "%x" % self.heditor.currentPage labeltext += toint self.pagelabel.setText(labeltext) labeltext = "| Block: " if self.heditor.decimalview: toint = "%d" % self.heditor.currentBlock else: toint = "0x" toint += "%x" % self.heditor.currentBlock labeltext += toint self.blocklabel.setText(labeltext) labeltext = "| Selection: " if self.heditor.decimalview: toint = "%d" % self.heditor.selection.length else: toint = "0x" toint += "%x" % self.heditor.selection.length labeltext += toint self.selectlabel.setText(labeltext) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/lfscrollbar.py000077500000000000000000000074651217176075400234020ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os from PyQt4.QtCore import Qt, SIGNAL from PyQt4.QtGui import QScrollBar, QAbstractSlider class stringLFScrollBar(QScrollBar): def __init__(self, filesize, pagesize, bytesperline, parent): QScrollBar.__init__(self) self.init(filesize, pagesize, bytesperline, parent) self.initCallBacks() self.setValues() def init(self, filesize, pagesize, bytesperline, parent): self.filesize = filesize self.parent = parent #Initialized in Whex with LFMOD self.pagesize = pagesize self.bytesperline = bytesperline self.max = 0 self.min = 0 self.single = 1 #Long File Mode self.lfmod = False ###### LFMOD ###### ################### self.maxint = 2147483647 self.lines = self.filesize / self.bytesperline self.restlines = self.filesize % self.bytesperline if self.isInt(self.lines): self.max = self.lines - 1 self.page = self.pagesize / self.bytesperline else: self.lfmod = True self.max = self.maxint - 1 self.page = self.pagesize #################### #################### def initCallBacks(self): self.connect(self, SIGNAL("sliderMoved(int)"), self.moved) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) def setValues(self): self.setMinimum(self.min) self.setMaximum(self.max) self.setSingleStep(self.single) self.setPageStep(self.page) self.setRange(self.min, self.max) def isLFMOD(self): return self.lfmod def isInt(self, val): try: res = int(val) if res < self.maxint: return True else: return False except ValueError, TypeError: return False else: return False # LFMOD # def valueToOffset(self, value): return ((self.filesize * value) / self.maxint) def offsetToValue(self, offset): if self.isLFMOD(): return ((self.maxint * offset) / self.filesize) else: return (offset / self.bytesPerLine) ######################################## # Navigation Operations # ######################################## def triggered(self, action): if action in [QAbstractSlider.SliderSingleStepAdd, QAbstractSlider.SliderPageStepAdd]: add = self.sliderPosition() - self.value() v = self.value() + add self.moved(v) elif action in [QAbstractSlider.SliderSingleStepSub, QAbstractSlider.SliderPageStepSub]: sub = self.value() - self.sliderPosition() v = self.value() - 1 self.moved(v) def moved(self, value): if self.isLFMOD(): if value <= self.max: offset = (self.filesize * value) / self.maxint self.parent.readBuffer(offset) else: if value <= self.max: if value == self.max: offset = self.filesize - (5 * self.bytesperline) else: offset = value * self.bytesperline self.parent.readBuffer(offset) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/messagebox.py000066400000000000000000000051471217176075400232220ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import * from PyQt4.QtGui import * class MessageBoxWarningSave(QMessageBox): def __init__(self, parent, message): super(MessageBoxWarningSave, self).__init__(parent) self.heditor = parent self.message = message self.g_display() self.initCallback() def g_display(self): self.setText(self.message) self.yes = QPushButton("yes") self.addButton(self.yes, QMessageBox.YesRole) self.no = QPushButton("no") self.addButton(self.no, QMessageBox.NoRole) self.setIcon(QMessageBox.Warning) def initCallback(self): self.connect(self.yes, SIGNAL("clicked()"),self.accept) self.connect(self.no, SIGNAL("clicked()"),self.reject) def accept(self): self.destroy() def reject(self): self.destroy() class MessageBoxError(QMessageBox): def __init__(self, parent, message): super(MessageBoxError, self).__init__(parent) self.heditor = parent self.message = message self.g_display() self.initCallback() def g_display(self): self.setText(self.message) self.ok = QPushButton("Ok") self.addButton(self.ok, QMessageBox.AcceptRole) self.setIcon(QMessageBox.Critical) def initCallback(self): self.connect(self.ok, SIGNAL("clicked()"),self.accept) def accept(self): self.destroy() class MessageBoxInfo(QMessageBox): def __init__(self, parent, message): super(MessageBoxInfo, self).__init__(parent) self.heditor = parent self.message = message self.g_display() self.initCallback() def g_display(self): self.setText(self.message) self.ok = QPushButton("Ok") self.addButton(self.ok, QMessageBox.AcceptRole) self.setIcon(QMessageBox.Information) def initCallback(self): self.connect(self.ok, SIGNAL("clicked()"),self.accept) def accept(self): self.destroy() dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/navigation.py000066400000000000000000000067461217176075400232320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import struct import binascii from PyQt4.QtCore import QString, Qt, SIGNAL from PyQt4.QtGui import QWidget, QGroupBox, QVBoxLayout, QSpinBox, QGridLayout, QTreeWidget, QTreeWidgetItem, QApplication from dff.api.exceptions.libexceptions import * from decodeValues import * class navigation(QWidget): def __init__(self, parent): QWidget.__init__(self) self.heditor = parent # self.hexitem = parent.hexitem self.createShape() def createShape(self): self.vbox = QGridLayout() fill = QWidget() # self.createNavTree() # self.createNavTreeItems() self.createDecode() self.vbox.addWidget(fill) self.setLayout(self.vbox) def createNavTree(self): self.navgroup = QGroupBox("Nav Informations") self.layout = QVBoxLayout() self.navtree = QTreeWidget() self.navtree.setColumnCount(2) headerLabels = [QApplication.translate("navigation", "Current", None, QApplication.UnicodeUTF8), QApplication.translate("navigation", "Value", None, QApplication.UnicodeUTF8)] self.navtree.setHeaderLabels(headerLabels) self.navtree.setAlternatingRowColors(True) self.layout.addWidget(self.navtree) self.navgroup.setLayout(self.layout) def createNavTreeItems(self): self.fs = QTreeWidgetItem(self.navtree) self.fs.setText(0, "File size") f = "%.2d" % self.heditor.filesize self.fs.setText(1, f) self.curoff = QTreeWidgetItem(self.navtree) self.curoff.setText(0, "Curr. offset") self.curpage = QTreeWidgetItem(self.navtree) self.curpage.setText(0, "Curr. page") self.curblock = QTreeWidgetItem(self.navtree) self.curblock.setText(0, "Curr. block") self.cursoroff = QTreeWidgetItem(self.navtree) self.cursoroff.setText(0, "Cursor") self.vbox.addWidget(self.navgroup) def createDecode(self): self.vdecode = QVBoxLayout() self.decode = decodeValues(self.heditor) self.vbox.addWidget(self.decode) def updateFs(self): if self.heditor.decimalview: f = "%.2d" % self.heditor.filesize else: f = "%.2x" % self.heditor.filesize self.fs.setText(1, f) def update(self): if self.heditor.decimalview: off = "%.2d" % self.heditor.currentOffset page = "%.2d" % self.heditor.currentPage block = "%.2d" % self.heditor.currentBlock select = "%.2d" % self.heditor.currentSelection else: off = "%.2x" % self.heditor.currentOffset page = "%.2x" % self.heditor.currentPage block = "%.2x" % self.heditor.currentBlock select = "%.2x" % self.heditor.currentSelection self.curoff.setText(1, off) self.curpage.setText(1, page) self.curblock.setText(1, block) self.cursoroff.setText(1, select) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/nceditor.py000077500000000000000000000165551217176075400227040ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # import curses import binascii import string from dff.api.vfs import * from dff.api.module import * from curses import panel bottom_box_height = 5 global nodePath def start(node): global Node Node = node curses.wrapper(main_loop) class HexFF(): global nodePath def __init__(self, scr): # node = Core.getnode(nodePath) # if not node: # return self.node = Node # self.nodePath = nodePath self.vfsFile = self.node.open() self.fileSize = self.node.size() self.scr = scr self.x, self.y = scr.getmaxyx() self.addrWidth = len(hex(self.fileSize)) self.addrView = 0#self.fileSize - 1000 self.readBuffer = [] self.read = 0 #XXX should be userdefined self.bigEndian = 1 def __del__(self): self.vfsFile.close() #TODO self.actual_offset = 0 def loop(stdscr): pass def createPanel(self, h, w, x, y): win = curses.newwin(h, w, x, y) pan = panel.new_panel(win) pan.show() return pan def obtainHex(self, offset): if (offset > 0): self.vfsFile.seek(offset) buff = self.vfsFile.read(1024) #TODO return buff out = [] for i in range(len(buff)): if not i % 2: c = buff[i] out.append(buff[i + 1]) else: out.append(c) return out def debug(self, pan, message): win = pan.window() win.move(3, 26) win.addstr(message) panel.update_panels() def offsetMove(self, move): self.addrView += move def fillToolbar(self, pan): win = pan.window() win.move(1, 3) sizeString = str(self.fileSize)[::-1] vString = "" for i in range(len(sizeString)): if not i % 3 and i: vString = vString + "." + sizeString[i] else: vString = vString + sizeString[i] win.addstr("Dump size : " + vString[::-1] + " bytes (" + hex(self.fileSize) + ")") win.move(2, 13) win.addstr("uit") win.border(0, 0, 0x20, 0, curses.ACS_VLINE, curses.ACS_VLINE, 0, 0) panel.update_panels() curses.doupdate() def fillAddress(self, pan, height): sAddr = self.addrView win = pan.window() for i in range(1, height): win.move(i, 1) startAddr = hex(sAddr) startAddr = startAddr[2:] s = "0x" for i in range(self.addrWidth - len(startAddr) - 2): s = s + "0" startAddr = s + startAddr win.addstr(startAddr[0:self.addrWidth]) sAddr += 16 win.border(0, 0, 0, 0, 0, curses.ACS_TTEE, curses.ACS_LTEE, 0) curses.doupdate() panel.update_panels() def fillHexPan(self, pan): win = pan.window() h, w = win.getmaxyx() y = 1 for j in range(h - 2): win.move(j + 1, 1) disp = "" i = 0 for k in range(16): if k + j * 16 < len(self.readBuffer): disp += str(binascii.b2a_hex(self.readBuffer[k + j * 16])) else: disp += " " i += 1 if i != 8: disp += " " if i == 8: disp += " " win.addstr(disp) y += 1 win.border(0x20, 0x20, 0, 0x20, curses.ACS_HLINE, curses.ACS_HLINE, 0x20, 0x20) panel.update_panels() def fillASCII(self, pan): win = pan.window() h, w = win.getmaxyx() y = 1 for j in range(h - 2): win.move(j + 1, 1) disp = "" i = 0 for k in range(16): if k + j * 16 < len(self.readBuffer): c = self.readBuffer[k + (j * 16)] if c in string.digits or c in string.letters or c in string.punctuation: disp += c else: disp += "." else: disp += " " win.addstr(disp) y += 1 win.border(0, 0, 0, 0, curses.ACS_TTEE, 0, 0, curses.ACS_RTEE) panel.update_panels() curses.doupdate() return def seek(self, offset): self.readBuffer = self.obtainHex(offset) def main_loop(stdscr): stdscr.clear() y, x = stdscr.getmaxyx() subwin = stdscr.subwin(y, x, 0, 0) hexff = HexFF(subwin) w, h = stdscr.getmaxyx() stdscr.clear() x, y = 0, hexff.addrWidth + 2 #XXX stdscr.clear() stdscr.refresh() addr_max = pow(16, hexff.addrWidth - 4) - 1 addr = 0 hexff.seek(hexff.addrView) toolbar_pan = hexff.createPanel(bottom_box_height, hexff.addrWidth + 68, w - bottom_box_height, 0) hexff.fillToolbar(toolbar_pan) address_pan = hexff.createPanel(w - bottom_box_height, hexff.addrWidth + 2, 0, 0) hexff.fillAddress(address_pan, w - bottom_box_height - 1) hex_pan = hexff.createPanel(w - bottom_box_height, 50, 0, hexff.addrWidth + 2) hexff.fillHexPan(hex_pan) ascii_pan = hexff.createPanel(w - bottom_box_height, 16, 0, hexff.addrWidth + 52) hexff.fillASCII(ascii_pan) while (1): stdscr.move(x + 1, y + 1) c = stdscr.getch() c_debug = c if 0 < c < 256: c = chr(c) if c in 'Qq': break else: pass elif c == curses.KEY_UP and x > 0: x -= 1 elif c == curses.KEY_DOWN and x < w - bottom_box_height - 3: x += 1 elif c == curses.KEY_LEFT and y > hexff.addrWidth + 2: y -= 1 elif c == curses.KEY_RIGHT and y < 55: y += 1 #Top or Bottom reached elif c == curses.KEY_UP and x == 0 and hexff.addrView != 0: hexff.offsetMove(-16) hexff.fillAddress(address_pan, w - bottom_box_height - 1) hexff.seek(hexff.addrView) hexff.fillHexPan(hex_pan) hexff.fillASCII(ascii_pan) elif c == curses.KEY_DOWN and x == w - bottom_box_height - 3 and hexff.addrView != hexff.fileSize - (w - bottom_box_height) + 3: hexff.offsetMove(+16) hexff.fillAddress(address_pan, w - bottom_box_height - 1) hexff.seek(hexff.addrView) hexff.fillHexPan(hex_pan) hexff.fillASCII(ascii_pan) #PageUp elif c == 0x153 and hexff.addrView - ((w - bottom_box_height - 2) * 16) >= 0: hexff.offsetMove(-((w - bottom_box_height - 2) * 16)) hexff.fillAddress(address_pan, w - bottom_box_height - 1) hexff.seek(hexff.addrView) hexff.fillHexPan(hex_pan) hexff.fillASCII(ascii_pan) #PageDown elif c == 0x152 and hexff.addrView + ((w - bottom_box_height - 2) * 16) <= hexff.fileSize: hexff.offsetMove((w - bottom_box_height - 2) * 16) hexff.fillAddress(address_pan, w - bottom_box_height - 1) hexff.seek(hexff.addrView) hexff.fillHexPan(hex_pan) hexff.fillASCII(ascii_pan) else: pass hexff.debug(toolbar_pan, "Keycode: " + hex(c_debug) + " View offset: " + str(hexff.addrView) + "(" + hex(hexff.addrView) + ")" ) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/offsetItem.py000077500000000000000000000042061217176075400231700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from PyQt4.QtCore import QString, Qt from PyQt4.QtGui import QWidget, QFont, QColor, QTextCursor, QGraphicsTextItem class offsetItem(QGraphicsTextItem): def __init__(self, whex): QGraphicsTextItem.__init__(self) self.initValues(whex) # self.initShape() self.initPosition() self.initFont() def initPosition(self): self.setPos(0, 25) def initValues(self, whex): self.whex = whex self.heditor = self.whex.heditor #Buffer self.buffer = [] self.bufferLines = 0 #Line self.currentLine = 0 #Offset self.startOffset = 0 self.fontPixel = 14 def initFont(self): self.setDefaultTextColor(QColor(Qt.red)) self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(self.fontPixel) self.setFont(self.font) #Print Operations def printFullOffset(self, start, len): count = 0 fullBuff = QString() while count <= len: if self.heditor.decimalview: fullBuff.append("%.10d" % start) else: fullBuff.append("%.10X" % start) fullBuff.append("\n") start += 16 count += 1 #Clear and set cursor = self.textCursor() cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) self.setPlainText(fullBuff) cursor.movePosition(QTextCursor.Start) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/options.py000077500000000000000000000271731217176075400225660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL, QLineF from PyQt4.QtGui import QWidget, QHBoxLayout, QVBoxLayout, QGroupBox, QGridLayout, QLabel, QLineEdit, QComboBox, QPushButton, QSlider, QTabWidget, QMatrix, QSpinBox from dff.modules.hexedit.utils import * class options(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent def initShape(self): self.vbox = QVBoxLayout() self.optab = QTabWidget() self.fill = QWidget() self.createHexOptions() # self.createPageOptions() self.createPixelOptions() self.vbox.addWidget(self.optab) self.createButtons() self.vbox.addWidget(self.fill) self.setLayout(self.vbox) def createPageOptions(self): self.pagegrid = QGridLayout() self.pagegroup = QWidget() pagelabel = QLabel("Page size : ") self.sizeEdit = QFFSpinBox(self) self.sizeEdit.setMaximum(self.heditor.filesize) self.sizeEdit.setValue(self.heditor.pageSize) # psize = QString("%.2d" % self.heditor.pageSize) # self.sizeEdit.insert(psize) headerlabel = QLabel("Header size : ") self.headEdit = QFFSpinBox(self) self.headEdit.setMaximum(self.heditor.filesize) self.headEdit.setValue(self.heditor.pageHead) # phead = QString("%.2d" % self.heditor.pageHead) # self.headEdit.insert(phead) sparelabel = QLabel("Spare size : ") self.spareEdit = QFFSpinBox(self) self.spareEdit.setMaximum(self.heditor.filesize) self.spareEdit.setValue(self.heditor.pageSpare) # pspare = QString("%.2d" % self.heditor.pageSpare) # self.spareEdit.insert(pspare) ppb = QLabel("Pages per block:") self.pagesperblock = QComboBox() self.pagesperblock.addItem("8") self.pagesperblock.addItem("16") self.pagesperblock.addItem("32") self.pagesperblock.addItem("64") self.pagesperblock.addItem("128") self.pagesperblock.addItem("256") self.pagesperblock.addItem("512") self.pagesperblock.setCurrentIndex(2) lview = QLabel("Left indication: ") self.indic = QComboBox() self.indic.addItem("Offset") self.indic.addItem("Block") # self.pagesperlineEdit = QLineEdit() # ppl = QString("%.2d" % self.heditor.pagesPerBlock) # self.pagesperlineEdit.insert(ppl) self.pagegrid.addWidget(pagelabel, 0, 0) self.pagegrid.addWidget(self.sizeEdit, 0, 1) self.pagegrid.addWidget(headerlabel, 1, 0) self.pagegrid.addWidget(self.headEdit, 1, 1) self.pagegrid.addWidget(sparelabel, 2, 0) self.pagegrid.addWidget(self.spareEdit, 2, 1) self.pagegrid.addWidget(ppb, 3 ,0) self.pagegrid.addWidget(self.pagesperblock, 3, 1) self.pagegrid.addWidget(lview, 4, 0) self.pagegrid.addWidget(self.indic, 4, 1) self.pagegrid.addWidget(self.fill, 5, 0) self.pagegrid.setRowStretch(5, 1) # self.pagegrid.addWidget(self.fill, 6, 0) # self.pagegrid.addWidget(pagesperline, 6, 0) # self.pagegrid.addWidget(self.pagesperlineEdit, 7, 0) self.pagegroup.setLayout(self.pagegrid) self.vvbox.addWidget(self.pagegroup) # self.optab.insertTab(1, self.pagegroup, "Pages" ) # self.vbox.addWidget(self.pagegroup) def createHexOptions(self): self.vvbox = QVBoxLayout() self.vcontainer = QWidget() self.hexgroup = QWidget() self.hexgrid = QGridLayout() groupebylabel = QLabel("Groupe by:") self.groupeby = QComboBox() self.groupeby.addItem("1") self.groupeby.addItem("2") self.groupeby.addItem("4") offsetlabel = QLabel("Offset as") self.offsetas = QComboBox() self.offsetas.addItem("Hexadecimal") self.offsetas.addItem("Decimal") # self.hexgrid.addWidget(groupebylabel, 0, 0) # self.hexgrid.addWidget(self.groupeby, 1, 0) self.hexgrid.addWidget(offsetlabel, 0, 0) self.hexgrid.addWidget(self.offsetas, 0, 1) # self.hexgrid.addWidget(self.fill, 2, 0) # self.hexgrid.setRowStretch(2, 1) self.hexgroup.setLayout(self.hexgrid) self.vvbox.addWidget(self.hexgroup) self.createPageOptions() self.vcontainer.setLayout(self.vvbox) self.optab.insertTab(0, self.vcontainer, "General") # self.vbox.addWidget(self.hexgroup) #Offset as decimal / hexadecimal def createPixelOptions(self): self.pixgroup = QWidget() self.pixgrid = QGridLayout() formatlabel = QLabel("Format :") self.format = QComboBox() self.format.addItem("RGB") self.format.addItem("Alpha RGB") self.format.addItem("Indexed 8bit") self.format.addItem("Mono") self.connect(self.format, SIGNAL("currentIndexChanged(const QString)"), self.formatChanged) colorlabel = QLabel("Indexed Color :") self.icolor = QComboBox() self.icolor.addItem("Green") self.icolor.addItem("Red") self.icolor.addItem("Blue") self.icolor.addItem("Ascii") self.icolor.addItem("256") self.icolor.setEnabled(False) slidelabel = QLabel("Resolution : ") self.sliderspin = QSpinBox(self) self.sliderspin.setMinimum(64) self.sliderspin.setMaximum(1024) self.sliderspin.setValue(self.heditor.wpixel.view.w) self.connect(self.sliderspin, SIGNAL("valueChanged(int)"), self.slidermoved) self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(64) self.slider.setMaximum(1024) self.slider.setValue(self.heditor.wpixel.view.w) self.slider.setSingleStep(1) self.zoomlabel = QLabel("Scale factor : 1") self.zoom = QSlider(Qt.Horizontal) self.zoom.setMinimum(1) self.zoom.setMaximum(5) self.zoom.setValue(1) self.zoom.setSingleStep(1) self.zoom.setTickInterval(1) self.zoom.setTickPosition(QSlider.TicksBelow) self.connect(self.slider, SIGNAL("sliderMoved(int)"), self.slidermoved) self.connect(self.zoom, SIGNAL("sliderMoved(int)"), self.scale) self.pixgrid.addWidget(formatlabel, 0, 0) self.pixgrid.addWidget(self.format, 0, 1) self.pixgrid.addWidget(colorlabel, 1, 0) self.pixgrid.addWidget(self.icolor, 1, 1) self.pixgrid.addWidget(slidelabel, 2, 0) self.pixgrid.addWidget(self.sliderspin, 2, 1, Qt.AlignLeft) self.pixgrid.addWidget(self.slider, 3, 0) self.pixgrid.addWidget(self.zoomlabel, 4, 0, Qt.AlignLeft) self.pixgrid.addWidget(self.zoom, 5, 0) self.pixgrid.addWidget(self.fill, 6, 0) self.pixgrid.setRowStretch(6, 1) self.pixgroup.setLayout(self.pixgrid) self.optab.insertTab(1, self.pixgroup, "Pixel") def setSliderLabel(self, value): cvalue = QString() cvalue = "%2.d" % value self.sliderlabel.setText(cvalue) def setZoomLabel(self, value): zvalue = QString("Scale factor : ") zvalue += "%2.d" % value self.zoomlabel.setText(zvalue) def createButtons(self): self.applyB = QPushButton("Apply") self.connect(self.applyB, SIGNAL('clicked()'), self.apply) self.vbox.addWidget(self.applyB) def checkValue(self, value): try: n = int(value) return n except ValueError: return -1 def apply(self): #PAGE CHECK pagesize = self.sizeEdit.value() headsize = self.headEdit.value() sparesize = self.spareEdit.value() pagesperblock = self.checkValue(self.pagesperblock.currentText()) if (pagesize < 0) or (headsize < 0) or (sparesize < 0) or (pagesperblock < 0): print "Wrong values" else: offas = self.offsetas.currentText() if offas == "Decimal": self.heditor.decimalview = True elif offas == "Hexadecimal": self.heditor.decimalview = False #Hexview refresh self.heditor.readOffset(self.heditor.currentOffset) #Pageview refresh if self.indic.currentText() == "Offset": self.heditor.pageOffView = True else: self.heditor.pageOffView = False self.heditor.refreshPageValues(headsize, pagesize, sparesize, pagesperblock) if self.heditor.wpage.scroll: self.heditor.wpage.scroll.refreshValues(self.heditor.pagesPerBlock, self.heditor.pageSize) self.heditor.wpage.view.refreshAllContent() #PageView scrollbar refres #Pixel View refresh format = self.format.currentText() if format == "Indexed 8bit": self.heditor.wpixel.view.format = 0 elif format == "Mono": self.heditor.wpixel.view.format = 1 elif format == "RGB": self.heditor.wpixel.view.format = 2 elif format == "Alpha RGB": self.heditor.wpixel.view.format = 3 if self.heditor.wpixel.scroll: self.heditor.wpixel.scroll.refreshValues() #Color icolor = self.icolor.currentText() if icolor == "Red": self.heditor.wpixel.view.icolor = 0 elif icolor == "Green": self.heditor.wpixel.view.icolor = 1 elif icolor == "Blue": self.heditor.wpixel.view.icolor = 2 elif icolor == "Ascii": self.heditor.wpixel.view.icolor = 3 elif icolor == "256": self.heditor.wpixel.view.icolor = 4 pixoffset = self.heditor.wpixel.view.currentOffset self.heditor.wpixel.view.read_image(pixoffset) def slidermoved(self, value): pixoffset = self.heditor.wpixel.view.currentOffset self.heditor.wpixel.view.w = value self.sliderspin.setValue(value) # self.setSliderLabel(value) self.heditor.wpixel.view.read_image(pixoffset) if self.heditor.wpixel.scroll: self.heditor.wpixel.scroll.refreshValues() # print value def scale(self, value): self.setZoomLabel(value) self.heditor.wpixel.view.scale = value pixoffset = self.heditor.wpixel.view.currentOffset self.heditor.wpixel.view.read_image(pixoffset) def formatChanged(self, format): if format == "Indexed 8bit": self.icolor.setEnabled(True) else: self.icolor.setEnabled(False) def keyPressEvent(self, kEvent): key = kEvent.key() if key == Qt.Key_Return or key == Qt.Key_Enter: self.apply() # self.heditor.wpixel.view.format = 0 # elif format == "Mono": # self.heditor.wpixel.view.format = 1 # elif format == "RGB": # self.heditor.wpixel.view.format = 2 # elif format == "Alpha RGB": # self.heditor.wpixel.view.format = 3 dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/pageView.py000077500000000000000000000436241217176075400226410ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL, QLineF from PyQt4.QtGui import QWidget, QFont, QBrush, QPen, QColor, QGraphicsView, QGraphicsScene, QResizeEvent, QGraphicsRectItem, QHBoxLayout, QGraphicsTextItem, QGraphicsLineItem, QGraphicsSimpleTextItem, QKeySequence from dff.modules.hexedit.scrollbar import pageScrollBar from dff.modules.hexedit.selection import pageSelection class wPage(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent self.scroll = False def initShape(self): self.layout = QHBoxLayout() self.view = pageView(self) self.layout.addWidget(self.view) self.setLayout(self.layout) def setScrollBar(self): self.scroll = pageScrollBar(self) self.layout.addWidget(self.scroll) class pageView(QGraphicsView): def __init__(self, wpage): QGraphicsView.__init__(self) self.init(wpage) self.initShape() # self.selection = pageSelection(self.heditor) def init(self, wpage): self.wpage = wpage self.heditor = wpage.heditor self.filesize = self.heditor.filesize self.start = True self.pagew = 20 self.pageh = 20 self.pageItems = [] self.offsetItems = [] self.displayLines = 0 def initShape(self): #Scene self.scene = QGraphicsScene() self.setScene(self.scene) #Font self.initFont() #Headers self.setHeads(self.heditor.pagesPerBlock) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) def initFont(self): self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) def setHeads(self, pagesPerBlock): if self.heditor.pageOffView: self.setOffsetHead() else: self.setBlockHead() self.setPageHead(self.heditor.pagesPerBlock) linesize = 95 + (self.heditor.pagesPerBlock * (self.pagew + 2)) #Decoration headLine = QGraphicsLineItem(QLineF(0, 20, linesize, 20)) self.scene.addItem(headLine) headOffLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) self.scene.addItem(headOffLine) def setOffsetHead(self): self.offHead = QGraphicsTextItem() self.offHead.setDefaultTextColor(QColor(Qt.red)) self.offHead.setFont(self.font) self.offHead.setPlainText("Offset(Kb)") self.offHead.setPos(5, 0) self.scene.addItem(self.offHead) def setPageHead(self, len): count = 0 x = 95 while count < len: item = QGraphicsSimpleTextItem() item.setFont(self.font) item.setText("%.2x" % count) item.setPos(x, 3) self.scene.addItem(item) x += self.pagew + 2 count += 1 def setBlockHead(self): self.blockHead = QGraphicsTextItem() self.blockHead.setDefaultTextColor(QColor(Qt.red)) self.blockHead.setFont(self.font) self.blockHead.setPlainText("Block") self.blockHead.setPos(15, 0) self.scene.addItem(self.blockHead) def initOffsetItems(self): count = 0 x = 0 y = 25 while count <= self.displayLines: item = QGraphicsTextItem() item.setDefaultTextColor(QColor(Qt.red)) item.setFont(self.font) item.setPos(x, y) self.offsetItems.append(item) y += self.pageh + 2 count += 1 #Add Items in scene for item in self.offsetItems: self.scene.addItem(item) def initPageItems(self): id = 0 countpage = 0 startx = 95 starty = 25 x = startx y = starty line = 0 while line <= self.displayLines: while countpage < self.heditor.pagesPerBlock: p = page(x, y, id, self) self.pageItems.append(p) id += 1 # self.scene.addItem(sec) x += self.pagew + 2 countpage += 1 x = startx y += self.pageh + 2 countpage = 0 line += 1 #Add items in scene for item in self.pageItems: self.scene.addItem(item) def hidePageItems(self, startid): end = len(self.pageItems) for item in self.pageItems[startid:end]: item.setVisible(False) def setAllPageItemsVisible(self): for item in self.pageItems: item.setVisible(True) def hideOffsetItems(self, startid): end = len(self.offsetItems) for item in self.offsetItems[startid:end]: item.setVisible(False) def setAllOffsetItemsVisible(self): for item in self.offsetItems: item.setVisible(True) def appendOffsetItems(self, linesToAppend): count = 0 x = 0 y = 25 + (len(self.offsetItems) * (self.pageh + 2)) # print "Y append offset ", y while count <= linesToAppend: item = QGraphicsTextItem() item.setDefaultTextColor(QColor(Qt.red)) item.setFont(self.font) item.setPos(x, y) self.offsetItems.append(item) self.scene.addItem(item) y += self.pageh + 2 count += 1 def appendPageItems(self, linesToAppend): count = 0 cp = 0 x = 95 y = 25 + ((len(self.pageItems) / self.heditor.pagesPerBlock) * (self.pageh + 2)) id = len(self.pageItems) while count <= linesToAppend: while cp < self.heditor.pagesPerBlock: item = page(x, y, id, self) self.pageItems.append(item) self.scene.addItem(item) id += 1 x += self.pagew + 2 cp += 1 count += 1 x = 95 y += self.pageh + 2 def refreshOffsetItems(self, offset): #Check if end of pages or if number of pages < display pages self.setAllOffsetItemsVisible() block = (offset / self.heditor.pageSize) / self.heditor.pagesPerBlock startBlockOffset = block * (self.heditor.pagesPerBlock * self.heditor.pageSize) lineToDisplay = ((self.filesize - offset) / self.heditor.pageSize) / self.heditor.pagesPerBlock if ((self.filesize - offset) / self.heditor.pageSize) % self.heditor.pagesPerBlock > 0: lineToDisplay += 1 if lineToDisplay >= self.displayLines: offset = startBlockOffset for item in self.offsetItems[0:self.displayLines]: if self.heditor.decimalview: if self.heditor.pageOffView: offlabel = QString("%.10d" % (offset / 1024)) else: offlabel = QString("%.10d" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) else: if self.heditor.pageOffView: offlabel = QString("%.10x" % (offset / 1024)) else: offlabel = QString("%.10x" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) item.setPlainText(offlabel) offset = offset + (self.heditor.pagesPerBlock * self.heditor.pageSize) self.heditor.startBlockOffset = startBlockOffset else: if lineToDisplay == 0: lineToDisplay = 5 offset = startBlockOffset - (lineToDisplay * self.heditor.pagesPerBlock * self.heditor.pageSize) if ((self.filesize - offset) / self.heditor.pageSize) % self.heditor.pagesPerBlock > 0: lineToDisplay += 1 self.heditor.startBlockOffset = offset for item in self.offsetItems[0:lineToDisplay]: if self.heditor.decimalview: if self.heditor.pageOffView: offlabel = QString("%.10d" % (offset / 1024)) else: offlabel = QString("%.10d" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) else: if self.heditor.pageOffView: offlabel = QString("%.10x" % (offset / 1024)) else: offlabel = QString("%.10x" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) item.setPlainText(offlabel) offset = offset + (self.heditor.pagesPerBlock * self.heditor.pageSize) self.hideOffsetItems(lineToDisplay) def refreshPageItems(self, offset): self.setAllPageItemsVisible() maxpages = self.displayLines * self.heditor.pagesPerBlock displaypages = (self.filesize - offset) / self.heditor.pageSize if displaypages <= maxpages: if displaypages == 0: startline = self.lines - 5 startOffset = startline * (self.heditor.pageSize * self.heditor.pagesPerBlock) rangeOffset = self.filesize - startOffset newdisplaypages = rangeOffset / self.heditor.pageSize if rangeOffset % self.heditor.pageSize > 0: newdisplaypages += 1 self.hidePageItems(newdisplaypages) self.heditor.startBlockOffset = startOffset else: rangeOffset = self.filesize - offset rangePages = rangeOffset / self.heditor.pageSize rangeLines = rangePages / self.heditor.pagesPerBlock newdisplaypages = rangeOffset / self.heditor.pageSize if rangeOffset % self.heditor.pageSize > 0: newdisplaypages += 1 self.hidePageItems(newdisplaypages) self.heditor.startBlockOffset = offset else: self.heditor.startBlockOffset = offset self.heditor.pageselection.update() def refreshAllContent(self): self.scene.clear() del self.offsetItems[:] del self.pageItems[:] self.setHeads(self.heditor.pagesPerBlock) self.initOffsetItems() self.initPageItems() self.refreshOffsetItems(self.heditor.startBlockOffset) self.refreshPageItems(self.heditor.startBlockOffset) def lineToOffset(self, line): offset = (line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) return offset def lineToOffsetKb(self, line): offset = (line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024 return offset def lineToOffsetMb(self, line): offset = ((line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024) / 1024 return offset def lineToOffsetGb(self, line): offset = (((line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024) / 1024) / 1024 return offset ############################ # Colorize Pages # ############################ def refreshPagesColor(self, id): # print "Refresh: ", id self.cleanSelection() self.pageItems[id].setBrush(QBrush(Qt.green, Qt.SolidPattern)) def cleanSelection(self): item = self.pageItems[self.selectedPage] item.setBrush(item.brush) ############################ # Resize Event # ############################ def resizeEvent(self, sizEvent): y = sizEvent.size().height() disline = (y / self.pageh) #Start if self.start == True: if self.height() < self.heditor.mainWindow.height(): if disline > self.displayLines: self.displayLines = (y / self.pageh) #Lines self.lines = self.filesize / (self.heditor.pagesPerBlock * self.heditor.pageSize) #Init self.initOffsetItems() self.initPageItems() #Refresh self.refreshOffsetItems(0) self.refreshPageItems(0) if self.lines > self.displayLines: self.wpage.setScrollBar() else: self.wpage.scroll = False self.start = False else: range = disline - self.displayLines if range > 0: self.displayLines = (y / self.pageh) #Append self.appendOffsetItems(range) self.appendPageItems(range) #Refresh self.refreshOffsetItems(self.heditor.startBlockOffset) self.refreshPageItems(self.heditor.startBlockOffset) # self.heditor.footer.pixel.view.resizeEvent(sizEvent) ############################ # CallBacks # ############################ def wheelEvent(self, event): offset = self.heditor.startBlockOffset # up = False if self.wpage.scroll: if event.delta() > 0: #UP subOffset = 3 * self.heditor.pagesPerBlock * self.heditor.pageSize if offset - subOffset > 0: offset = offset - subOffset else: offset = 0 else: #DOWN addOffset = 3 * self.heditor.pagesPerBlock * self.heditor.pageSize if offset + addOffset < self.filesize: offset = offset + addOffset else: offset = self.filesize - (5 * self.heditor.pagesPerBlock * self.heditor.pageSize) #Set ScrollBar value: if offset < self.filesize - (5 * self.heditor.pagesPerBlock * self.heditor.pageSize): value = self.wpage.scroll.offsetToValue(offset) self.wpage.scroll.setValue(value) self.refreshOffsetItems(offset) self.refreshPageItems(offset) def keyPressEvent(self, keyEvent): pass #if keyEvent.matches(QKeySequence.MoveToNextPage): #print "Next block" #elif keyEvent.matches(QKeySequence.MoveToPreviousPage): #print "Previous block" #elif keyEvent.matches(QKeySequence.MoveToNextLine): #print "Next Line" #elif keyEvent.matches(QKeySequence.MoveToPreviousLine): #print "Previous Line" #else: #pass def resetSelection(self): for item in self.pageItems: item.setBrush(item.brush) def getPageID(self, x, y): startx = 95 starty = 25 #Set scrollbar seek hscroll = self.horizontalScrollBar() if hscroll.value() > 0: startx -= hscroll.value() xrange = x - startx if xrange > 0: xcut = (xrange / (self.pagew + 2)) # print xcut else: xcut = 0 yrange = y - starty if yrange > 0: ycut = yrange / (self.pageh + 2) else: ycut = 0 id = (ycut * self.heditor.pagesPerBlock) + xcut return id def mousePressEvent(self, event): button = event.button() pos = event.pos() if event.button() == 1: #Get CLicked coordonates x = pos.x() y = pos.y() id = self.getPageID(x, y) self.resetSelection() self.heditor.pageselection.select(id, self.heditor.startBlockOffset, 0) def mouseMoveEvent(self, event): pos = event.pos() x = pos.x() y = pos.y() if self.heditor.pageselection.mode == 1: id = self.getPageID(x, y) self.resetSelection() self.heditor.pageselection.select(id, self.heditor.startBlockOffset, 1) # else: # id = self.getPageID(x, y) # self.pageItems[id].setBrush(self) def mouseReleaseEvent(self, event): self.heditor.pageselection.mode = 0 # self.heditor.pageselection class page(QGraphicsRectItem): def __init__(self, x, y, id, view): QGraphicsRectItem.__init__(self) self.initValues(x, y, id, view) self.initShape() def initValues(self, x, y, id, view): self.view = view self.heditor = self.view.heditor self.w = 20 self.h = 20 self.x = x self.y = y self.id = id def initShape(self): self.initBrush() self.initPen() self.setAcceptHoverEvents(True) self.setRect(self.x, self.y, self.w, self.h) def initBrush(self): self.color = QColor(Qt.darkGreen) self.brush = QBrush(self.color, Qt.SolidPattern) self.setBrush(self.brush) def initPen(self): self.pen = QPen(QColor(Qt.black)) self.setPen(self.pen) def hoverEnterEvent(self, hoverEvent): # if self.view.selectedPage != self.id: self.setBrush(self.hbrush) def hoverLeaveEvent(self, hoverEvent): # if self.view.selectedPage != self.id: self.setBrush(self.brush) # def mousePressEvent(self, mousEvent): # button = mousEvent.button() # if button == 1: # offset = self.heditor.startBlockOffset + (self.id * self.heditor.pageSize) # self.heditor.readOffset(offset) # #Update Hexview scrollbar # value = self.heditor.whex.offsetToValue(offset) # self.heditor.whex.scroll.setValue(value) # else: # print "right click" dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/pixelView.py000077500000000000000000000242711217176075400230430ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import sip import time import struct import binascii from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.api.exceptions.libexceptions import * from dff.modules.hexedit.scrollbar import byteScrollBar class wPixel(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent self.scroll = False def initShape(self): self.layout = QHBoxLayout() self.view = pixelView(self) self.layout.addWidget(self.view) if self.view.hmax > self.view.hcur: self.setScroll() self.layout.addWidget(self.scroll) else: self.scroll = False self.setLayout(self.layout) def setScroll(self): self.scroll = byteScrollBar(self) self.scroll.refreshValues() class pixelView(QGraphicsView): def __init__(self, wpixel): QGraphicsView.__init__(self) self.init(wpixel) self.initShape() # self.setColors() # self.read_image(self.currentOffset) def init(self, wpixel): self.wpixel = wpixel self.heditor = wpixel.heditor self.scale = 1 self.file = self.heditor.file self.filesize = self.heditor.filesize self.w = 512 self.h = 512 self.hmax = self.filesize / self.w if self.filesize % self.w > 0: self.hmax += 1 self.hcur = self.height() self.currentOffset = 0 self.mformat = QImage.Format_Mono self.iformat = QImage.Format_Indexed8 self.rformat = QImage.Format_RGB32 self.arformat = QImage.Format_ARGB32_Premultiplied #0 = Red #1 = Green #2 = Blue #3 = Ascii #4 = 256 self.icolor = 1 #Indexed = 0 #Mono = 1 #RGB = 2 #ARGB = 3 self.format = 2 self.wheelpad = 10 self.pagepad = self.hcur - self.wheelpad def initShape(self): self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) # self.setAlignment(Qt.AlignTop) self.scene = QGraphicsScene() self.pixmap = QPixmap() self.pixmapitem = pixItem(self) self.pixmapitem.setPixmap(self.pixmap) self.scene.addItem(self.pixmapitem) self.setScene(self.scene) def setGreenColors(self, image): c = 0 while c <= 255: v = qRgb(0, c, 0) image.setColor(c, v) c += 1 def setRedColors(self, image): c = 0 while c <= 255: v = qRgb(c, 0, 0) image.setColor(c, v) c += 1 def setBlueColors(self, image): c = 0 while c <= 255: v = qRgb(0, 0, c) image.setColor(c, v) c += 1 def setAsciiColors(self, image): #ASCII printable: Dark Grey #CRLF: Yellow #Tab or space: Red #Other ascii grey clair #Other: White c = 0 while c <= 255: if c > 32 and c < 127: v = qRgb(128, 128, 128) image.setColor(c, v) elif c == 10 or c == 13: v = qRgb(255, 255, 0) image.setColor(c, v) elif c == 32 or c == 9: v = qRgb(255, 0, 0) image.setColor(c, v) else: v = qRgb(255, 255, 255) image.setColor(c, v) c += 1 def scalePixmap(self, value): matrix = QMatrix() matrix.scale(value, value) # pixorigin = self.pixmapitem.pixmap() pixorigin = self.pixmapitem.pixmap() zpix = pixorigin.transformed(matrix) self.pixmapitem.setPixmap(zpix) # self.heditor.wpixel.view.pixmapitem.scale(0, 0) # self.heditor.wpixel.view.pixmapitem.scale(value, value) def read_image(self, offset): self.currentOffset = offset self.file.seek(offset) toread = self.filesize - self.currentOffset # print "toread: ", toread, "calcul: ", (self.w * self.hcur), "calcul RGB: ", (self.w * self.hcur * 4) #If not 4Byte (RGB) if self.format < 2: if toread >= self.w * self.hcur: toread = self.w * self.hcur hei = self.hcur else: hei = toread / self.w else: if toread >= self.w * self.hcur * 4: toread = self.w * self.hcur * 4 hei = self.hcur else: hei = (toread / 4) / self.w try: self.buff = self.file.read(self.w * hei * 4) if len(self.buff) < (self.w * hei * 4): leak = (self.w *hei * 4) - len(self.buff) self.buff += leak* '\x00' #Create image with current format if self.format == 0: image = QImage(self.buff, self.w, hei, self.w, self.iformat) if self.icolor == 0: self.setRedColors(image) elif self.icolor == 1: self.setGreenColors(image) elif self.icolor == 2: self.setBlueColors(image) elif self.icolor == 3: self.setAsciiColors(image) elif self.format == 1: image = QImage(self.buff, self.w, hei, self.w, self.mformat) elif self.format == 2: image = QImage(self.buff, self.w, hei, self.w * 4, self.rformat) elif self.format == 3: image = QImage(self.buff, self.w, hei, self.w * 4, self.arformat) self.pixmapitem.setPixmap(QPixmap().fromImage(image)) if self.scale > 1: self.scalePixmap(self.scale) except vfsError, e: pass def move(self, pad, dir): #dir: 0 DOWN | 1 UP offset = self.currentOffset if self.wpixel.scroll: if dir > 0: #UP if self.format < 2: subOffset = pad * self.w else: subOffset = pad * (self.w * 4) if offset - subOffset > 0: offset = offset - subOffset else: offset = 0 else: #DOWN if self.format < 2: addOffset = pad * self.w else: addOffset = pad * (self.w * 4) if offset + addOffset < self.filesize: offset = offset + addOffset else: offset = self.filesize - (pad * self.w) self.read_image(offset) if self.format < 2: self.wpixel.scroll.setValue(offset / self.w) else: self.wpixel.scroll.setValue(offset / (self.w * 4)) def resizeEvent(self, sEvent): self.hcur = sEvent.size().height() self.read_image(self.currentOffset) self.heditor.wpage.view.resizeEvent(sEvent) def wheelEvent(self, event): if event.delta() > 0: self.move(self.wheelpad, 1) else: self.move(self.wheelpad, 0) def keyPressEvent(self, keyEvent): if keyEvent.matches(QKeySequence.MoveToNextPage): self.move(self.pagepad, 0) elif keyEvent.matches(QKeySequence.MoveToPreviousPage): self.move(self.pagepad, 1) elif keyEvent.matches(QKeySequence.MoveToNextLine): self.move(self.wheelpad, 0) elif keyEvent.matches(QKeySequence.MoveToPreviousLine): self.move(self.wheelpad, 1) else: pass class pixItem(QGraphicsPixmapItem): def __init__(self, parent): QGraphicsPixmapItem.__init__(self) self.view = parent self.heditor = parent.heditor self.rect = False self.offsetitem = False self.setAcceptHoverEvents(True) def getOffset(self, x, y): if self.view.format < 2: offset = self.view.currentOffset + (self.view.w * (int(y) / self.view.scale)) + (int(x) / self.view.scale) else: offset = self.view.currentOffset + ((self.view.w * 4) * (int(y) / self.view.scale)) + ((int(x) * 4) / self.view.scale) return int(offset) def hoverMoveEvent(self, hEvent): x = hEvent.pos().x() y = hEvent.pos().y() offset = self.getOffset(x, y) coffset = QString("Off: ") if self.heditor.decimalview: coffset.append("%2.d" % offset) else: coffset.append("%2.x" % offset) cw = 8 #Display Rect background if not self.rect: self.rect = QGraphicsRectItem(x + cw, y, (cw * coffset.length()), cw + 10) self.rect.setPen(QPen(Qt.black)) self.rect.setBrush(QBrush(Qt.white)) self.rect.setZValue(1) self.view.scene.addItem(self.rect) else: self.rect.setRect(x + cw, y, (cw * coffset.length()), cw + 10) #Display Offset if not self.offsetitem: self.offsetitem = QGraphicsSimpleTextItem() self.offsetitem.setText(coffset) self.offsetitem.setPos(x + cw + 5, y) self.offsetitem.setZValue(2) self.view.scene.addItem(self.offsetitem) else: self.offsetitem.setText(coffset) self.offsetitem.setPos(x + cw + 5, y) def mousePressEvent(self, mEvent): x = mEvent.pos().x() y = mEvent.pos().y() offset = self.getOffset(x, y) # print "offset: ", offset self.heditor.readOffset(offset) value = self.heditor.whex.offsetToValue(offset) self.heditor.whex.scroll.setValue(value) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/right.py000077500000000000000000000030671217176075400222040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL from PyQt4.QtGui import QWidget, QFont, QColor, QTabWidget from dff.modules.hexedit.search import * from dff.modules.hexedit.decodeValues import * from dff.modules.hexedit.navigation import * from dff.modules.hexedit.options import * from dff.modules.hexedit.goto import * class righTab(QTabWidget): def __init__(self, parent): QTabWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent def initShape(self): #Add Value tab self.setTabPosition(QTabWidget.East) self.decode = decodeValues(self.heditor) self.search = search(self.heditor) self.goto = goto(self.heditor) self.options = options(self.heditor) self.insertTab(0, self.decode,"Decode") self.insertTab(1, self.search, QIcon(":hex_search.png") ,"Search") self.insertTab(2, self.goto, "Goto") self.insertTab(3, self.options, QIcon(":hex_opt.png"), "Options") dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/scrollbar.py000077500000000000000000000154661217176075400230600ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os from PyQt4.QtCore import Qt, SIGNAL from PyQt4.QtGui import QScrollBar, QAbstractSlider class hexScrollBar(QScrollBar): def __init__(self, whex): QScrollBar.__init__(self) self.init(whex) self.initCallBacks() def init(self, whex): self.whex = whex self.heditor = self.whex.heditor self.filesize = self.heditor.filesize self.min = 0 self.single = 1 self.page = self.heditor.pageSize self.max = 0 def initCallBacks(self): self.connect(self, SIGNAL("sliderMoved(int)"), self.moved) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) def setValues(self): self.setMinimum(self.min) self.setMaximum(self.max) self.setSingleStep(self.single) self.setPageStep(self.page) self.setRange(self.min, self.max) ######################################## # Navigation Operations # ######################################## def triggered(self, action): if action == QAbstractSlider.SliderSingleStepAdd: self.whex.view.move(self.singleStep(), 1) elif action == QAbstractSlider.SliderSingleStepSub: self.whex.view.move(self.singleStep(), 0) elif action == QAbstractSlider.SliderPageStepSub: self.whex.view.move(self.pageStep(), 0) elif action == QAbstractSlider.SliderPageStepAdd: self.whex.view.move(self.pageStep(), 1) def moved(self, value): if self.whex.isLFMOD(): if value <= self.max: offset = (self.filesize * value) / self.whex.maxint self.heditor.readOffset(offset) else: if value <= self.max: if value == self.max: offset = self.filesize - (5 * self.heditor.bytesPerLine) else: offset = value * self.heditor.bytesPerLine self.heditor.readOffset(offset) class pageScrollBar(QScrollBar): def __init__(self, wpage): QScrollBar.__init__(self) self.wpage = wpage self.pageview = wpage.view self.heditor = wpage.heditor self.initCallBacks() self.initValues() self.setValues() def initCallBacks(self): self.connect(self, SIGNAL("sliderMoved(int)"), self.moved) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) def initValues(self): self.min = 0 self.max = self.pageview.lines - 5 self.page = self.pageview.lines / self.heditor.pagesPerBlock def refreshValues(self, len, pagesize): self.pageview.lines = self.heditor.filesize / (len * pagesize) self.min = 0 self.max = self.pageview.lines - 5 self.page = self.pageview.lines / len self.setValues() def setValues(self): self.setMinimum(0) self.setMaximum(self.max) self.setSingleStep(1) self.setPageStep(self.page) self.setRange(0, self.max) def valueToOffset(self, value): return (value * (self.heditor.pagesPerBlock * self.heditor.pageSize)) def offsetToValue(self, offset): return (offset / (self.heditor.pagesPerBlock * self.heditor.pageSize)) def triggered(self, action): if action in [QAbstractSlider.SliderSingleStepAdd, QAbstractSlider.SliderPageStepAdd]: add = self.sliderPosition() - self.value() v = self.value() + add self.moved(v) elif action in [QAbstractSlider.SliderSingleStepSub, QAbstractSlider.SliderPageStepSub]: sub = self.value() - self.sliderPosition() v = self.value() - 1 self.moved(v) def moved(self, value): if value < self.max: offset = self.valueToOffset(value) if offset < self.heditor.filesize and offset >= 0: self.pageview.refreshOffsetItems(offset) self.pageview.refreshPageItems(offset) else: self.pageview.refreshOffsetItems(self.pageview.filesize) self.pageview.refreshPageItems(self.pageview.filesize) #################################### # PIXEL VIEW # #################################### class byteScrollBar(QScrollBar): def __init__(self, wpixel): QScrollBar.__init__(self) self.initCallBacks() self.initValues(wpixel) self.setValues() def initCallBacks(self): self.connect(self, SIGNAL("sliderMoved(int)"), self.moved) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) def initValues(self, wpixel): self.wpixel = wpixel self.bview = wpixel.view self.min = 0 self.max = self.bview.hmax self.page = self.bview.w * 16 def refreshValues(self): #mode: rgb | index | mono if self.bview.format > 1: self.min = 0 self.max = self.bview.filesize / (self.bview.w * 4) self.page = self.bview.w * 16 else: self.min = 0 self.max = self.bview.filesize / self.bview.w self.page = self.bview.w * 16 self.setValues() def setValues(self): self.setMinimum(0) self.setMaximum(self.max) self.setSingleStep(1) self.setPageStep(self.page) self.setRange(0, self.max) def triggered(self, action): if action in [QAbstractSlider.SliderSingleStepAdd, QAbstractSlider.SliderPageStepAdd]: add = self.sliderPosition() - self.value() v = self.value() + add self.moved(v) elif action in [QAbstractSlider.SliderSingleStepSub, QAbstractSlider.SliderPageStepSub]: sub = self.value() - self.sliderPosition() v = self.value() - 1 self.moved(v) def moved(self, value): if value != self.max: if self.bview.format < 2: self.bview.read_image(value * self.bview.w) else: self.bview.read_image(value * (self.bview.w * 4)) else: if self.bview.format < 2: self.bview.read_image((value - 32) * self.bview.w) else: self.bview.read_image((value - 32) * (self.bview.w * 4)) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/search.py000066400000000000000000000272111217176075400223260ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii from PyQt4.QtCore import QString, Qt, SIGNAL, QLineF, QThread from PyQt4.QtGui import QWidget, QVBoxLayout, QCheckBox, QGridLayout, QLabel, QLineEdit, QPushButton, QTabWidget, QComboBox, QTreeWidget, QTreeWidgetItem from dff.api.events.libevents import EventHandler from dff.modules.hexedit.utils import * from dff.modules.hexedit.messagebox import * class search(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent #Open a new instance for I/O self.file = self.heditor.node.open() self.__size = self.heditor.node.size() #Last search type tag [0:hex|1:characters] self.lastSearchType = 0 #Init Thread self.search_th = searchThread(self.file) #tupple of searched patterns [key:hex(pattern)|value:offsetslist] self.searchedPatterns = {} self.connect(self.search_th, SIGNAL("searchDone()"), self.searchdone) self.connect(self.search_th, SIGNAL("currentPos"), self.updatePBar) def initShape(self): self.vbox = QVBoxLayout() self.createValues() self.createOptions() self.createResults() self.createSearching() self.createButtons() #fill fill = QWidget() self.vbox.addWidget(fill) self.setLayout(self.vbox) def createValues(self): self.wvalues = QWidget() self.valuesgrid = QGridLayout() ltype = QLabel("Type:") self.type = QComboBox() self.type.addItem("Hexadecimal") self.type.addItem("Character(s)") self.type.addItem("Unicode") lneedle = QLabel("Pattern:") self.needle = QLineEdit() lwild = QLabel("Wildcard:") self.wildcard = QLineEdit() lstart = QLabel("Start: ") self.start = QFFSpinBox(self) self.start.setMaximum(self.heditor.filesize) self.start.setValue(0) self.valuesgrid.addWidget(ltype, 0, 0) self.valuesgrid.addWidget(self.type, 0, 1) self.valuesgrid.addWidget(lneedle, 1, 0) self.valuesgrid.addWidget(self.needle, 1, 1) self.valuesgrid.addWidget(lwild, 2, 0) self.valuesgrid.addWidget(self.wildcard, 2, 1) self.valuesgrid.addWidget(lstart, 3, 0) self.valuesgrid.addWidget(self.start, 3, 1) self.wvalues.setLayout(self.valuesgrid) self.vbox.addWidget(self.wvalues) def createOptions(self): self.woptions = QWidget() self.optgrid= QGridLayout() lopt = QLabel("Options:") self.fromcursor = QCheckBox("From cursor") self.back = QCheckBox("Backwards") self.optgrid.addWidget(lopt, 0, 0) self.optgrid.addWidget(self.fromcursor, 0, 1) self.woptions.setLayout(self.optgrid) self.vbox.addWidget(self.woptions) def createResults(self): self.wresults = QWidget() self.resgrid= QGridLayout() self.resultab = resultab(self) self.resgrid.addWidget(self.resultab, 0, 0) self.wresults.setLayout(self.resgrid) self.vbox.addWidget(self.wresults) def createSearching(self): self.wsing = QWidget() self.singgrid= QGridLayout() self.searchlabel = QLabel("Launch search") self.singgrid.addWidget(self.searchlabel, 0, 0) self.wsing.setLayout(self.singgrid) self.vbox.addWidget(self.wsing) def createButtons(self): self.applyB = QPushButton("Apply") self.connect(self.applyB, SIGNAL('clicked()'), self.searchit) self.vbox.addWidget(self.applyB) def toHex(self, str, wildcard = None): HEXCHAR = "0123456789abcdefABCDEF" hexStr = "" evenhex = "" for i in range(len(str)): if str[i] in HEXCHAR: if len(evenhex) == 1: hexStr += chr(int(evenhex+str[i], 16)) evenhex = "" else: evenhex = str[i] elif wildcard != None and str[i] == wildcard: if evenhex == "": hexStr += wildcard else: raise ValueError, "argument 'str' must be an even number of char" else: raise ValueError, "argument 'str' contains not valid characters" if len(evenhex) != 0: raise ValueError, "argument 'str' must be an even number of char" return hexStr def toUnicode(self, string): res = string.encode("hex") unires = "" cp = 0 while cp < len(res): unires += res[cp] if (cp - 1) % 2 == 0 and cp != 0 and cp + 1 != len(res): unires += "00" cp = cp + 1 return unires.decode("hex") ##################### # Search IT # ##################### def searchit(self): if self.needle.text() != "": needle = self.needle.text() err = False #check needle type = self.type.currentText() if type == "Hexadecimal": self.lastSearchType = 0 try: pattern = self.toHex(str(needle)) except ValueError: err = True msg = MessageBoxError(self.heditor, "Required Hexadecimal pattern") msg.exec_() return elif type == "Character(s)": self.lastSearchType = 1 pattern = str(needle) elif type == "Unicode": self.lastSearchType = 2 pattern = self.toUnicode(str(needle)) if not err: opt_fromcursor = self.fromcursor.isChecked() spinstart = self.start.value() wild = self.wildcard.text() # XXX if opt_fromcursor: start = self.heditor.selection.offset elif spinstart > 0: start = spinstart else: start = 0 self.search_th.setData(pattern, start, wild) self.searchlabel.setText("Searching ...") self.search_th.start() def searchdone(self): # print "Results found: ", nres res = self.search_th.getResults() if len(res) > 0: label = "%2.d" % len(res) label += " matchs" self.searchlabel.setText(label) self.resultab.buttonCloseTab.setEnabled(True) self.resultab.addResults(res) msg = MessageBoxInfo(self.heditor, label) msg.exec_() else: msg = MessageBoxError(self.heditor, "No results founded") msg.exec_() def updatePBar(self, pos): rpos = self.__size - pos rsize = self.__size - self.search_th.startOffset self.searchlabel.setText(str((rsize - rpos) * 100 / rsize) + " %") def keyPressEvent(self, kEvent): key = kEvent.key() if key == Qt.Key_Return or key == Qt.Key_Enter: self.searchit() class searchThread(QThread, EventHandler): def __init__(self, file): QThread.__init__(self) EventHandler.__init__(self) self.file = file self.file.connection(self) self.pattern = "" self.wild = "" def run(self): wild = self.wild self.res = self.file.search(str(self.pattern), len(self.pattern), str(wild), self.startOffset) self.emit(SIGNAL("searchDone()")) def setData(self, pattern, startOffset, wild): self.pattern = pattern self.startOffset = startOffset self.wild = wild def getResults(self): return self.res def Event(self, e): self.emit(SIGNAL("currentPos"), e.value.value()) class resultab(QTabWidget): def __init__(self, parent): QTabWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.search = parent self.heditor = parent.heditor self.trees = [] def initShape(self): self.buttonCloseTab = QPushButton("") self.buttonCloseTab.setFixedSize(QSize(24, 24)) self.buttonCloseTab.setIcon(QIcon(":cancel.png")) self.buttonCloseTab.setEnabled(False) self.setCornerWidget(self.buttonCloseTab, Qt.TopRightCorner) self.connect(self.buttonCloseTab, SIGNAL("clicked()"), self.closeTabWidget) self.setTabPosition(QTabWidget.North) def closeTabWidget(self): if self.count() > 0: index = self.currentIndex() currentSearch = self.currentWidget() self.removeTab(index) currentSearch.destroy(True, True) if self.count() == 0: self.buttonCloseTab.setEnabled(False) # def formatHighlightPattern(self, pattern): # res = QString("\\b(") # count = 0 # for p in pattern: # print "add Byte" # res.append(binascii.hexlify(p)) # count += 1 # if count == self.heditor.groupBytes: # print "add blank" # res.append(" ") # count = 0 # res.append(")\\b") # print " formater highlight:", res # return res def addResults(self, results): tree = QTreeWidget() tree.setColumnCount(1) header = QString("Offset") tree.setHeaderLabel(header) tree.setAlternatingRowColors(True) self.connect(tree, SIGNAL("itemDoubleClicked(QTreeWidgetItem *, int)"), self.treeClicked) for res in results: # print hex(res) item = QTreeWidgetItem(tree) off = "0x" off += "%.2x" % res item.setText(0, str(off)) self.trees.append(tree) #Add pattern and offsets to tupple key = binascii.hexlify(self.search.search_th.pattern) self.search.searchedPatterns[key] = results if self.search.lastSearchType == 0: p = binascii.hexlify(self.search.search_th.pattern) elif self.search.lastSearchType == 1: p = self.search.search_th.pattern else: p = "u(" p += self.search.needle.text() p += ")" #Add Ascii hex pattern in searched list for syntaxHighliter self.insertTab(len(self.trees), tree, p) #resuts: list of offset def treeClicked(self, item, column): coffset = item.text(column) coffset.remove(0, 2) # print coffset off = coffset.toULongLong(16) if off[1]: offset = off[0] # print offset self.search.heditor.readOffset(offset) value = self.search.heditor.whex.offsetToValue(offset) self.search.heditor.whex.scroll.setValue(value) #Update self.heditor.selection.offset = offset self.heditor.whex.hexcursor.update() self.heditor.whex.asciicursor.update() self.heditor.infos.update() dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/selection.py000066400000000000000000000242041217176075400230450ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * class selection(): def __init__(self, parent): self.init(parent) self.initFont() def init(self, parent): #Parent widgets and items self.heditor = parent self.hexitem = parent.whex.hexitem self.asciitem = parent.whex.asciitem #Start selection self.xstart = 0 self.ystart = 0 #End Selection self.xend = 0 self.yend = 0 self.length = 0 self.offset = 0 self.startoffset = 0 self.endoffset = 0 self.way = 0 def initFont(self): self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) def setWay(self): if ((self.xend - self.xstart) < 0) or ((self.yend - self.ystart) < 0): self.way = 0 else: self.way = 1 def setData(self): startoff = self.heditor.currentOffset + ((self.ystart * self.heditor.bytesPerLine) + self.xstart) endoff = self.heditor.currentOffset + ((self.yend * self.heditor.bytesPerLine) + self.xend) selen = endoff - startoff if selen < 0: selen = selen * -1 self.offset = startoff - selen self.startoffset = self.offset self.xinit = self.xend self.yinit = self.yend else: self.offset = startoff + selen self.startoffset = startoff self.xinit = self.xstart self.yinit = self.ystart self.length = selen def setCount(self): self.ycount = self.length / self.heditor.bytesPerLine self.xcount = self.length % self.heditor.bytesPerLine if self.way > 0: self.xcount += 1 def select(self, xstart, ystart, xend, yend, first = False): self.resetSelection() if first: self.xstart = xstart self.ystart = ystart self.xend = xend self.yend = yend else: self.xend = xend self.yend = yend #Set Data selection self.setWay() self.setData() self.setCount() self.heditor.whex.hexcursor.update() self.heditor.whex.asciicursor.update() #Colorize process if self.length > 0: self.colorize() def update(self): self.initStartPosition() if self.length > 0: self.colorize() def initStartPosition(self): if self.way > 0: startrange = (self.offset - self.length) - self.heditor.currentOffset else: startrange = self.offset - self.heditor.currentOffset if startrange < 0: selen = self.length - (startrange * -1) if selen < 0: selen = 0 startrange = 0 else: selen = self.length self.yinit = startrange / self.heditor.bytesPerLine self.xinit = startrange % self.heditor.bytesPerLine self.ycount = selen / self.heditor.bytesPerLine self.xcount = selen % self.heditor.bytesPerLine def colorize(self): #Get hex cursor hexcur = self.getCursorSelection(0) self.colorizeCursor(hexcur, 0) asciicur = self.getCursorSelection(1) self.colorizeCursor(asciicur, 1) def getCursorSelection(self, item): #Init Position if item == 0: #Hexadecimal cursor = self.hexitem.textCursor() xway = QTextCursor.NextWord else: #Ascii cursor = self.asciitem.textCursor() xway = QTextCursor.NextCharacter cp = 0 while cp < self.yinit: cursor.movePosition(QTextCursor.Down, QTextCursor.MoveAnchor) cp += 1 cp = 0 while cp < self.xinit: cursor.movePosition(xway, QTextCursor.MoveAnchor) cp += 1 #Move Cursor cp = 0 while cp < self.ycount: cursor.movePosition(QTextCursor.Down, QTextCursor.KeepAnchor) cp += 1 cp = 0 while cp < self.xcount: cursor.movePosition(xway, QTextCursor.KeepAnchor) cp += 1 return cursor #Item: 0 hex 1 ascii def colorizeCursor(self, cursor, item): format = QTextCharFormat() format.setFont(self.font) if item == 0: format.setForeground(QBrush(QColor(Qt.blue))) else: format.setForeground(QBrush(QColor(Qt.blue))) cursor.setCharFormat(format) def resetSelection(self): self.resetColorSelection(self.hexitem.textCursor()) self.resetColorSelection(self.asciitem.textCursor()) def resetColorSelection(self, cursor): #Set Format bformat = QTextCharFormat() bformat.setFont(self.font) #Set Black Color cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) cursor.setCharFormat(bformat) cursor.movePosition(QTextCursor.Start) def hexCopy(self): if self.way > 0: off = self.offset - self.length else: off = self.offset buff = self.heditor.readHexValue(off, self.length) # print buff def createToolBar(self): self.toolbar = QToolBar() self.toolbar.setObjectName("hexedit selection toolbar") self.copy = QAction(QIcon(":bookmark_add.png"), "Copy selection", self.toolbar) self.toolbar.addAction(self.copy) class pageSelection(): def __init__(self, parent): self.init(parent) self.initBrush() def init(self, parent): self.heditor = parent self.pview = self.heditor.wpage.view self.items = self.pview.pageItems self.pageoffset = 0 self.blockoffset = 0 self.startid = 0 self.endid = 0 self.startcount = 0 self.endcount = 0 self.length = 0 # 0: click | 1: selection self.mode = 0 self.way = 0 def initBrush(self): self.hcolor = QColor(Qt.green) self.hbrush = QBrush(self.hcolor, Qt.SolidPattern) # self.setBrush(self.brush) def initPen(self): self.pen = QPen(QColor(Qt.black)) self.setPen(self.pen) def selectPage(self, offset): if self.length == 0: self.pageoffset = offset def select(self, id, startBlockOffset, mode): if mode == 0: self.startid = id self.startcount = id self.endid = id self.endcount = id self.length = 0 # inblock = id / self.heditor.pagesPerBlock # startoffset = startBlockOffset + (inblock * (self.heditor.pageSize * self.heditor.pagesPerBlock)) # self.blockoffset = startBlockOffset self.pageoffset = self.heditor.startBlockOffset + (id * self.heditor.pageSize) self.heditor.readOffset(self.pageoffset) # #Update Hexview scrollbar value = self.heditor.whex.offsetToValue(self.pageoffset) self.heditor.whex.scroll.setValue(value) self.colorizePages() self.mode = 1 else: self.endid = id if self.endid < self.startid: self.startcount = self.endid self.endcount = self.startid self.length = self.startid - self.endid self.way = 0 else: self.startcount = self.startid self.endcount = self.endid self.length = self.endid - self.startid self.way = 1 self.pageoffset = self.heditor.startBlockOffset + (self.startcount * self.heditor.pageSize) self.colorizePages() def colorizePages(self): self.pview.resetSelection() if self.length == 0 and (self.startcount < len(self.items)): # print "len items : ", len(self.items), ": ", self.startcount self.items[self.startcount].setBrush(self.hbrush) else: # print "len items : ", len(self.items), ": ", self.startcount if (self.startcount < len(self.items)) or (self.endcount < len(self.items)): for item in self.items[self.startcount:self.endcount + 1]: item.setBrush(self.hbrush) def update(self): ret = self.initStartPosition() if ret == 0: self.pview.resetSelection() return 0 else: self.colorizePages() return 1 def initStartPosition(self): endzone = self.heditor.startBlockOffset + (self.pview.lines * (self.heditor.pageSize * self.heditor.pagesPerBlock)) endoffset = self.pageoffset + (self.length * self.heditor.pageSize) # if (self.pageoffset >= self.heditor.startBlockOffset) and (self.pageoffset < endzone): if (endoffset >= self.heditor.startBlockOffset) and (endoffset < endzone): # print "start page offset: ", self.heditor.startBlockOffset startblockid = (self.pageoffset - self.heditor.startBlockOffset) / self.heditor.pageSize endblockid = ((self.pageoffset - self.heditor.startBlockOffset) + (self.length * self.heditor.pageSize)) / self.heditor.pageSize # print "========" # print "sblockid: ", startblockid # print "eblockid: ", endblockid # print "mode: ", self.mode # print "way: ", self.way self.startcount = startblockid self.endcount = endblockid if self.startcount < 0: self.startcount = 0 else: return 0 dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/string.py000066400000000000000000000051001217176075400223600ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import QString, Qt, SIGNAL from PyQt4.QtGui import QWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QApplication, QHBoxLayout, QToolButton, QIcon, QToolBar, QAction, QDialog, QLineEdit, QLabel, QGridLayout, QDialogButtonBox, QLineEdit, QPixmap, QTextEdit from dff.api.exceptions.libexceptions import * from dff.modules.hexedit.lfscrollbar import * class stringView(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() self.readBuffer(0) def init(self, parent): self.heditor = parent self.file = self.heditor.file #test self.readsize = self.heditor.pageSize * 5 self.stringoffset = 0 def initShape(self): self.hbox = QHBoxLayout() self.stringedit = QTextEdit() self.stringedit.setReadOnly(True) self.stringedit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scrollbar = stringLFScrollBar(self.heditor.filesize, self.heditor.pageSize, self.heditor.bytesPerLine, self) self.hbox.addWidget(self.stringedit) self.hbox.addWidget(self.scrollbar) self.setLayout(self.hbox) def readBuffer(self, offset): try: self.file.seek(offset) buff = self.file.read(self.readsize) stri = self.processBuffer(buff) self.printBuffer(stri) except vfsError, e: print e.error # get only strings and return stringified buffer def processBuffer(self, buff): printer = QString() for char in buff: if (char > "\x20" and char < "\x7e") or (self.isMetaChar(char)): printer.append(char) return printer def isMetaChar(self, char): if char == "\x0a": return True elif char == "\x09": return True else: return False def printBuffer(self, stri): #print stri self.stringedit.clear() self.stringedit.insertPlainText(stri) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/textItem.py000077500000000000000000000132611217176075400226670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct import string import time from PyQt4.QtCore import QString, Qt from PyQt4.QtGui import QTextEdit, QFont, QTextDocument, QBrush, QColor, QTextCharFormat, QTextTable, QTextTableFormat from cursor import * #TODO #Pour la visualisation et son organisation: |offset = widget| hexview = QTextEdit | Ascii QTextEdit ou QGraphics ou Gimp view class textItem(QTextEdit): def __init__(self, parent): QTextEdit.__init__(self) self.initValues(parent) self.initFont() # self.initColors() # self.initTab() def initTab(self): cursor = self.textCursor() # self.tableformat = QTextTableFormat() self.table = cursor.insertTable(1, 3) self.printOffset(0) # print self.table.rows() def initValues(self, parent): self.heditor = parent #Buffer self.buffer = [] self.bufferLines = 0 #Line self.currentLine = 0 #Offset self.startOffset = 0 self.row = {} self.line = [] # self.setAcceptsHoverEvents(True) self.document = QTextDocument() self.setDocument(self.document) self.cursor = self.textCursor() # self.setTextCursor(self.cursor) def initFont(self): #Font self.font = QFont("Courier") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) self.setCurrentFont(self.font) #Cursor #Just after new read def formatBuffer(self, buff, offset): t = time.time() self.startOffset = offset del self.buffer pos = str(len(buff)) + 'B' self.buffer = struct.unpack(pos, buff) self.bufferLines = len(self.buffer) / 16 # for index in block: # byte = "%.2x" % index # if count < 15: # byte += " " # count += 1 # else: # byte += "\n" # count = 0 # self.buffer.append(byte) print time.time() - t def printLine(self, line, offset): count = 0 start = line * 16 dline = self.buffer[start:start+16] #Print Offset self.setTextColor(Qt.black) cell = self.table.cellAt(0,1) cellCursor = cell.firstCursorPosition() cellCursor.insertText(" | ") for byte in dline: if count % 2 == 0: self.setTextColor(Qt.black) cellCursor.insertText("%.2x" % byte) else: self.setTextColor(Qt.blue) cellCursor.insertText("%.2x" % byte) cellCursor.insertText(" ") count += 1 # print count self.setTextColor(Qt.black) cellCursor.insertText("| ") #self.printAscii(dline) cellCursor.insertText("\n") # print self.buffer # self.setPlainText(self.buffer) # self.colorizeText() def printOffset(self, offset): self.setCurrentFont(self.font) self.setTextColor(Qt.red) cell = self.table.cellAt(0,0) cellCursor = cell.firstCursorPosition() # cursor = self.table.cellAt(0, 0).firstCursorPosition() cellCursor.insertText("%.10d" % offset) def printAscii(self, line): for char in line: if str(char) in string.printable: self.insertPlainText(str(char)) else: self.insertPlainText(".") def printBuffer(self): t = time.time() #Clean text self.moveCursor(QTextCursor.Start) self.moveCursor(QTextCursor.End, QTextCursor.KeepAnchor) self.setCurrentFont(self.font) offset = self.startOffset # self.printOffset(offset) l = self.currentLine while l < self.bufferLines: self.printLine(l, offset) l += 1 offset += 16 print "E" self.moveCursor(QTextCursor.Start) print time.time() - t def initColors(self): #Blue Color self.blue = QBrush(QColor(Qt.blue)) self.blueFormat = QTextCharFormat() self.blueFormat.setFont(self.font) self.blueFormat.setForeground(self.blue) def colorizeText(self): self.size = self.buffer.size() cur = self.textCursor() pos = cur.position() # self.moveCursor(QTextCursor.Start) while pos < self.size: self.moveCursor(QTextCursor.NextWord) self.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) cur = self.textCursor() # self.setTextColor(QColor(Qt.blue)) cur.setCharFormat(self.blueFormat) self.moveCursor(QTextCursor.NextWord) cur = self.textCursor() pos = cur.position() # print pos self.moveCursor(QTextCursor.Start) # # self.moveCursor(QTextCursor.NextWord) # self.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) # self.setTextColor(QColor(Qt.blue)) # print self.cursor.position() # self.setCurrentCharFormat(self.blueFormat) dff-1.3.0+dfsg.1/dff/modules/viewer/hexedit/utils.py000066400000000000000000000062121217176075400222170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * class QFFSpinBox(QAbstractSpinBox): def __init__(self, parent): QAbstractSpinBox.__init__(self) self.init(parent) self.initEdit() def init(self, parent): #Variables self.parent = parent self.__minimum = 0 self.__maximum = 0 self.__range = 0 self.__value = 0 self.__singleStep = 0 #Functions self.setWrapping(True) # self.setEnabled(True) def initEdit(self): self.__edit = self.lineEdit() self.__edit.connect(self.__edit, SIGNAL("editingFinished()"), self.editChanged) # self.setLineEdit(self.__edit) def stepEnabled(self): if self.wrapping(): if self.__value == self.__minimum: return self.StepEnabled(QAbstractSpinBox.StepUpEnabled) elif self.__value == self.__maximum: return self.StepEnabled(QAbstractSpinBox.StepDownEnabled) else: return self.StepEnabled(QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled) def maximum(self): return self.__maximum def minimum(self): return self.__minimum def setMaximum(self, max): self.__maximum = max def setMinimum(self, min): self.__minimum = min def setSingleStep(self, step): self.__singlStep = step def setRange(self, range): self.__range = range def setValue(self, value): self.__value = value self.refreshEdit(value) def value(self): return self.__value def singleStep(self): return self.__singleStep def maximum(self): return self.__maximum def minimum(self): return self.__minimum def stepBy(self, step): if step < 0: if self.__value > self.__minimum: self.__value -= 1 self.refreshEdit(self.__value) else: if self.__value < self.__maximum: self.__value += 1 self.refreshEdit(self.__value) def refreshEdit(self, value): self.__edit.clear() cvalue = "%.1d" % value self.__edit.insert(cvalue) def editChanged(self): value = self.__edit.text() lvalue = value.toULongLong() if lvalue[1]: if (lvalue[0] <= self.__maximum) and (lvalue[0] >= self.__minimum): self.__value = lvalue[0] self.refreshEdit(lvalue[0]) else: self.refreshEdit(self.__value) else: self.refreshEdit(self.__value) dff-1.3.0+dfsg.1/dff/modules/viewer/media/000077500000000000000000000000001217176075400201315ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/media/CMakeLists.txt000066400000000000000000000012021217176075400226640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER install_file( player.py videothumbnailviewer.py imageviewer.py textviewer.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/media/imageviewer.py000066400000000000000000000314521217176075400230140ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_viewerimage_version__ = "1.0.0" import re from PyQt4 import QtCore, QtGui from PyQt4.QtCore import Qt, QSize, QString, SIGNAL, QThread from PyQt4.QtGui import QPixmap, QImage, QPushButton, QLabel, QWidget, QHBoxLayout, QVBoxLayout, QScrollArea, QIcon, QMatrix, QToolBar, QAction, QSizePolicy, QTabWidget, QTableWidget, QTableWidgetItem, QAbstractItemView, QLineEdit from dff.api.vfs import vfs from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Argument, typeId from dff.modules.metaexif import EXIF class LoadedImage(QLabel): def __init__(self, parent): QLabel.__init__(self) self.parent = parent self.baseImage = QImage() self.matrix = QMatrix() self.zoomer = 1 self.maxsize = 1024*10*10*10*25 self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored); self.setAlignment(Qt.AlignCenter) def setParent(self, parent): self.parent = parent def load(self, node): self.matrix.reset() self.zoomer = 1 if node.size() < self.maxsize: self.node = node file = self.node.open() buff = file.read() file.close() if self.baseImage.loadFromData(buff): self.emit(SIGNAL("available(bool)"), True) else: self.baseImage.load(":file_broken.png") self.emit(SIGNAL("available(bool)"), False) else: self.baseImage.loadFromData("") self.emit(SIGNAL("available(bool)"), False) self.adjust() def adjust(self): if self.zoomer == 1: if self.baseImage.width() < self.parent.width() - 10: self.curWidth = self.baseImage.width() else: self.curWidth = self.parent.width() - 10 if self.baseImage.height() < self.parent.height() - 10: self.curHeight = self.baseImage.height() else: self.curHeight = self.parent.height() - 10 self.updateTransforms() def updateTransforms(self): if not self.baseImage.isNull(): self.currentImage = self.baseImage.transformed(self.matrix).scaled(QSize(self.curWidth, self.curHeight), Qt.KeepAspectRatio, Qt.FastTransformation) self.setPixmap(QPixmap.fromImage(self.currentImage)) else: self.clear() self.setText("File is too big to be processed") self.adjustSize() def rotateLeft(self): self.matrix.rotate(-90) self.updateTransforms() def rotateRight(self): self.matrix.rotate(90) self.updateTransforms() def enlarge(self): self.zoomer *= 1.25 self.curWidth *= 1.25 self.curHeight *= 1.25 self.updateTransforms() def shrink(self): self.zoomer *= 0.8 self.curWidth *= 0.8 self.curHeight *= 0.8 self.updateTransforms() def fit(self): self.zoomer = 1 self.adjust() def normal(self): self.curWidth = self.baseImage.width() self.curHeight = self.baseImage.height() self.updateTransforms() class Metadata(QWidget): def __init__(self): QWidget.__init__(self) self.tabs = QTabWidget() self.nometa = QLabel("No EXIF metadata found") self.nometa.setAlignment(Qt.AlignCenter) self.box = QHBoxLayout() self.setLayout(self.box) self.box.addWidget(self.tabs) self.box.addWidget(self.nometa) self.nometa.hide() self.tabs.show() self.tabs.setTabPosition(QTabWidget.East) def process(self, node): for idx in xrange(0, self.tabs.count()): widget = self.tabs.widget(idx) del widget self.tabs.clear() self.node = node file = self.node.open() tags = EXIF.process_file(file) if len(tags) == 0: self.nometa.setSizePolicy(self.tabs.sizePolicy()) self.tabs.hide() self.nometa.show() else: self.tabs.show() self.nometa.hide() sortedTags = {} for tag in tags.keys(): if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'): spaceidx = tag.find(" ") ifd = tag[:spaceidx].strip() if ifd == "Image": ifd = "IFD 0 (Image)" if ifd == "Thumbnail": ifd = "IFD 1 (Thumbnail)" key = tag[spaceidx:].strip() try: val = str(tags[tag]) except: val = "cannot be decoded" if ifd not in sortedTags.keys(): sortedTags[ifd] = [] sortedTags[ifd].append((key, val)) for ifd in sortedTags.keys(): table = QTableWidget(len(sortedTags[ifd]), 2) table.setShowGrid(False) table.setAlternatingRowColors(True) table.verticalHeader().hide() table.horizontalHeader().setClickable(False) table.horizontalHeader().setStretchLastSection(True) table.setHorizontalHeaderLabels(["Tag", "Value"]) table.setSelectionBehavior(QAbstractItemView.SelectRows) self.tabs.addTab(table, ifd) row = 0 for res in sortedTags[ifd]: key = QTableWidgetItem(res[0]) key.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) val = QTableWidgetItem(res[1]) val.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) table.setItem(row, 0, key) table.setItem(row, 1, val) row += 1 if 'JPEGThumbnail' in tags.keys(): label = QLabel() img = QImage() img.loadFromData(tags['JPEGThumbnail']) label.setPixmap(QPixmap.fromImage(img)) label.setAlignment(Qt.AlignCenter) self.tabs.addTab(label, "Embedded Thumbnail") if 'TIFFThumbnail' in tags.keys(): label = QLabel() img = QImage() img.loadFromData(tags['TIFFThumbnail']) label.setPixmap(QPixmap.fromImage(img)) label.setAlignment(Qt.AlignCenter) self.tabs.addTab(label, "Embedded Thumbnail") file.close() class ImageView(QWidget, Script): def __init__(self): Script.__init__(self, "viewerimage") self.type = "imageview" self.icon = None self.vfs = vfs.vfs() self.reg_viewer = re.compile(".*(JPEG|JPG|jpg|jpeg|GIF|gif|bmp|png|PNG|pbm|PBM|pgm|PGM|ppm|PPM|xpm|XPM|xbm|XBM|TIFF|tiff).*", re.IGNORECASE) self.sceneWidth = 0 def start(self, args): try : self.preview = args["preview"].value() except IndexError: self.preview = False try: self.node = args["file"].value() self.curIdx = self.node.at() except KeyError: pass def isImage(self, node): if node.size() != 0: try: type = node.dataType() except (IndexError, AttributeError, IOError): return False if self.reg_viewer.search(str(type)): return True return False def next(self): listNodes = self.node.parent().children() newIdx = self.curIdx + 1 if newIdx >= len(listNodes): newIdx = 0 while newIdx != self.curIdx: if self.isImage(listNodes[newIdx]): break newIdx += 1 if newIdx >= len(listNodes): newIdx = 0 self.curIdx = newIdx self.setImage(listNodes[self.curIdx]) def previous(self): listNodes = self.node.parent().children() newIdx = self.curIdx - 1 if newIdx < 0: newIdx = len(listNodes) - 1 while newIdx != self.curIdx: if self.isImage(listNodes[newIdx]): break newIdx -= 1 if newIdx < 0: newIdx = len(listNodes) - 1 self.curIdx = newIdx self.setImage(listNodes[self.curIdx]) def createActions(self): self.actions = QToolBar() self.actions.setObjectName("Image viewer actions") self.nextButton = QAction(QIcon(":next.png"), "Display next image", self.actions) self.previousButton = QAction(QIcon(":previous.png"), "Display previous image", self.actions) self.rotlButton = QAction(QIcon(":rotate-left.png"), "Rotate the image 90 degrees to the left", self.actions) self.rotrButton = QAction(QIcon(":rotate-right.png"), "Rotate the image 90 degrees to the right", self.actions) self.enlargeButton = QAction(QIcon(":viewmag+"), "Enlarge the image", self.actions) self.shrinkButton = QAction(QIcon(":viewmag-"), "Shrink the image", self.actions) self.fitButton = QAction(QIcon(":viewmagfit"), "Fit the image to the window", self.actions) self.normalButton = QAction(QIcon(":viewmag1"), "Show the image at its normal size", self.actions) self.actions.addAction(self.previousButton) self.actions.addAction(self.nextButton) self.actions.addAction(self.rotlButton) self.actions.addAction(self.rotrButton) self.actions.addAction(self.enlargeButton) self.actions.addAction(self.shrinkButton) self.actions.addAction(self.fitButton) self.actions.addAction(self.normalButton) self.connect(self.loadedImage, SIGNAL("available(bool)"), self.enableActions) self.connect(self.previousButton, SIGNAL("triggered()"), self.previous) self.connect(self.nextButton, SIGNAL("triggered()"), self.next) self.connect(self.rotlButton, SIGNAL("triggered()"), self.loadedImage.rotateLeft) self.connect(self.rotrButton, SIGNAL("triggered()"), self.loadedImage.rotateRight) self.connect(self.enlargeButton, SIGNAL("triggered()"), self.loadedImage.enlarge) self.connect(self.shrinkButton, SIGNAL("triggered()"), self.loadedImage.shrink) self.connect(self.fitButton, SIGNAL("triggered()"), self.loadedImage.fit) self.connect(self.normalButton, SIGNAL("triggered()"), self.loadedImage.normal) def enableActions(self, cond): self.rotlButton.setEnabled(cond) self.rotrButton.setEnabled(cond) self.enlargeButton.setEnabled(cond) self.shrinkButton.setEnabled(cond) self.fitButton.setEnabled(cond) self.normalButton.setEnabled(cond) def setImage(self, node): if not self.preview: self.imagelabel.clear() self.imagelabel.insert(QString.fromUtf8(node.absolute())) self.metadata.process(node) self.loadedImage.load(node) def g_display(self): QWidget.__init__(self, None) self.factor = 1 self.box = QHBoxLayout() self.setLayout(self.box) self.imagebox = QVBoxLayout() self.scrollArea = QScrollArea() self.loadedImage = LoadedImage(self.scrollArea) self.scrollArea.setWidget(self.loadedImage) self.scrollArea.setAlignment(Qt.AlignCenter) if not self.preview: self.createActions() self.imagelabelbox = QVBoxLayout() self.imagelabelbox.setSpacing(0) self.imagelabel = QLineEdit() self.imagelabelbox.addWidget(self.imagelabel) self.imagelabel.setReadOnly(True) self.imagebox.addWidget(self.actions) self.imagebox.addWidget(self.scrollArea) if not self.preview: self.imagebox.setAlignment(self.actions, Qt.AlignCenter) self.imagebox.addLayout(self.imagelabelbox) self.databox = QVBoxLayout() self.metadata = Metadata() self.databox.addWidget(self.metadata) if len(self.node.parent().children()) < 2: self.nextButton.setEnabled(False) self.previousButton.setEnabled(False) self.box.addLayout(self.imagebox) if not self.preview: self.box.addLayout(self.databox) self.setImage(self.node.parent().children()[self.curIdx]) def updateWidget(self): if not self.preview: self.metadata.setMaximumSize(self.width() / 4, self.height()) self.loadedImage.adjust() def resizeEvent(self, e): if not self.preview: self.metadata.setMaximumSize(self.width() / 4, self.height()) self.loadedImage.adjust() class imageviewer(Module): """Display content of graphic file""" def __init__(self): Module.__init__(self, "pictures", ImageView) self.conf.addArgument({"name": "file", "description": "Picture file to display", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "preview", "description": "Preview mode", "input": Argument.Empty}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["JPEG", "GIF", "PNG", "PC bitmap", "TIFF", "PBM", "PGM", "PPM", "XBM", "XPM"]}) self.tags = "Viewers" self.icon = ":lphoto" dff-1.3.0+dfsg.1/dff/modules/viewer/media/player.py000066400000000000000000000145011217176075400220000ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_player_version__ = "1.0.0" from PyQt4.QtGui import QWidget, QAction, QStyle, QToolBar, QLabel, QPalette, QPixmap, QLCDNumber, QSizePolicy, QHBoxLayout, QVBoxLayout, QMessageBox from PyQt4.QtCore import SIGNAL, SLOT, QTime, Qt from PyQt4.phonon import Phonon from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.vfs.iodevice import IODevice from dff.api.types.libtypes import Argument, typeId from dff.api.vfs import * #avoid bug in phonon audio = None video = None media = None class PLAYER(QWidget, Script): def __init__(self): Script.__init__(self, "player") self.vfs = vfs.vfs() def start(self, args): try: self.node = args["file"].value() except: pass def closeEvent(self, event): media.stop() media.clearQueue() self.src.close() def updateWidget(self): pass def g_display(self): QWidget.__init__(self) global audio,video,media if media is None: media = Phonon.MediaObject(self) video = Phonon.VideoWidget(self) audio = Phonon.AudioOutput(Phonon.MusicCategory, self) media.setTickInterval(1000) media.tick.connect(self.tick) Phonon.createPath(media, video) Phonon.createPath(media, audio) media.stateChanged.connect(self.stateChanged) self.setupActions() self.setupUi() self.timeLcd.display("00:00") self.play(self.node) def play(self, node): wasPlaying = (media.state() == Phonon.PlayingState) media.stop() media.clearQueue() self.src = IODevice(node) source = Phonon.MediaSource(self.src) if source.type() != -1: media.setCurrentSource(source) if wasPlaying: media.play() else : media.stop() else: print "error can find file" def tick(self, time): displayTime = QTime(0, (time / 60000) % 60, (time / 1000) % 60) self.timeLcd.display(displayTime.toString('mm:ss')) def stateChanged(self, newState, oldState): if newState == Phonon.ErrorState: pass #if media.errorType() == Phonon.FatalError: #QMessageBox.warning(self, "Fatal Error", #media.errorString()) #else: #QMessageBox.warning(self, "Error", #media.errorString()) elif newState == Phonon.PlayingState: self.playAction.setEnabled(False) self.pauseAction.setEnabled(True) self.stopAction.setEnabled(True) elif newState == Phonon.StoppedState: self.stopAction.setEnabled(False) self.playAction.setEnabled(True) self.pauseAction.setEnabled(False) self.timeLcd.display("00:00") elif newState == Phonon.PausedState: self.pauseAction.setEnabled(False) self.stopAction.setEnabled(True) self.playAction.setEnabled(True) def setupActions(self): self.playAction = QAction( self.style().standardIcon(QStyle.SP_MediaPlay), "Play", self, shortcut="Ctrl+P", enabled=False, triggered=media.play) self.pauseAction = QAction( self.style().standardIcon(QStyle.SP_MediaPause), "Pause", self, shortcut="Ctrl+A", enabled=False, triggered=media.pause) self.stopAction = QAction( self.style().standardIcon(QStyle.SP_MediaStop), "Stop", self, shortcut="Ctrl+S", enabled=False, triggered=media.stop) self.nextAction = QAction( self.style().standardIcon(QStyle.SP_MediaSkipForward), "Next", self, shortcut="Ctrl+N") self.previousAction = QAction( self.style().standardIcon(QStyle.SP_MediaSkipBackward), "Previous", self, shortcut="Ctrl+R") def setupUi(self): bar = QToolBar() bar.addAction(self.playAction) bar.addAction(self.pauseAction) bar.addAction(self.stopAction) self.seekSlider = Phonon.SeekSlider(self) self.seekSlider.setMediaObject(media) self.volumeSlider = Phonon.VolumeSlider(self) self.volumeSlider.setAudioOutput(audio) self.volumeSlider.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) volumeLabel = QLabel() volumeLabel.setPixmap(QPixmap('images/volume.png')) palette = QPalette() palette.setBrush(QPalette.Light, Qt.darkGray) self.timeLcd = QLCDNumber() self.timeLcd.setPalette(palette) headers = ("Title", "Artist", "Album", "Year") seekerLayout = QHBoxLayout() seekerLayout.addWidget(self.seekSlider) seekerLayout.addWidget(self.timeLcd) playbackLayout = QHBoxLayout() playbackLayout.addWidget(bar) playbackLayout.addStretch() playbackLayout.addWidget(volumeLabel) playbackLayout.addWidget(self.volumeSlider) mainLayout = QVBoxLayout() mainLayout.addWidget(video) mainLayout.addLayout(seekerLayout) mainLayout.addLayout(playbackLayout) self.setLayout(mainLayout) class player(Module): """Video and Audio player""" def __init__(self): Module.__init__(self, "player", PLAYER) self.conf.addArgument({"name": "file", "description": "multimedia file to play", "input": Argument.Required|Argument.Single|typeId.Node}) self.tags = "Viewers" #for mimeType in Phonon.BackendCapabilities.availableMimeTypes(): #self.conf.add_const("mime-type", str(mimeType)) #self.conf.addConstant({"name": "mime-type", #"type": typeId.String, #"description": "managed mime type", #"values": ["video", "audio"]}) self.icon = ":multimedia" dff-1.3.0+dfsg.1/dff/modules/viewer/media/textviewer.py000066400000000000000000000140501217176075400227110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER __dff_module_cat_version__ = "1.0.0" from PyQt4.QtCore import Qt, QString, SIGNAL, QTextCodec from PyQt4.QtGui import QWidget, QTextCursor, QTextEdit, QTextOption, QScrollBar, QAbstractSlider, QHBoxLayout, QListWidget, QVBoxLayout, QSplitter, QSizePolicy from dff.api.vfs import vfs from dff.api.types.libtypes import Argument, typeId from dff.api.module.module import Module from dff.api.module.script import Script class TextEdit(QTextEdit): def __init__(self, cat): QTextEdit.__init__(self) self.cat = cat self.scroll = self.cat.scroll self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setReadOnly(1) self.setWordWrapMode(QTextOption.NoWrap) def wheelEvent(self, event): v = self.scroll.value() if event.delta() > 0: trig = v - 5 if trig >= self.scroll.min: self.cat.read(trig) self.scroll.setValue(trig) else: trig = v + 5 if trig < self.scroll.max: self.cat.read(trig) self.scroll.setValue(trig) class Scroll(QScrollBar): def __init__(self, parent): QScrollBar.__init__(self, parent) self.cat = parent self.init() self.initCallBacks() self.setValues() def init(self): self.min = 0 self.single = 1 self.page = 32 self.max = self.cat.lines - 1 def initCallBacks(self): self.connect(self, SIGNAL("sliderMoved(int)"), self.moved) self.connect(self, SIGNAL("actionTriggered(int)"), self.triggered) def setValues(self): self.setMinimum(self.min) self.setMaximum(self.max) self.setSingleStep(self.single) self.setPageStep(self.page) self.setRange(self.min, self.max) def triggered(self, action): if action == QAbstractSlider.SliderSingleStepAdd: trig = self.value() + 1 if trig <= self.max: self.cat.read(trig) elif action == QAbstractSlider.SliderSingleStepSub: trig = self.value() - 1 if trig >= self.min: self.cat.read(trig) elif action == QAbstractSlider.SliderPageStepSub: trig = self.value() - 5 if trig >= self.min: self.cat.read(trig) elif action == QAbstractSlider.SliderPageStepAdd: trig = self.value() + 5 if trig <= self.max: self.cat.read(trig) def moved(self, value): if value == self.max: value -= 5 self.cat.read(value) class CAT(QSplitter, Script): def __init__(self): Script.__init__(self, "cat") self.vfs = vfs.vfs() self.type = "cat" self.icon = None self.currentCodec = "UTF-8" def start(self, args): self.args = args try: self.node = args["file"].value() except: pass def g_display(self): QSplitter.__init__(self) self.offsets = self.linecount() self.initShape() self.read(0) def initShape(self): self.hbox = QHBoxLayout() self.hbox.setContentsMargins(0, 0, 0, 0) self.listWidget = QListWidget() self.listWidget.setSortingEnabled(True) for codec in QTextCodec.availableCodecs(): self.listWidget.addItem(str(codec)) item = self.listWidget.findItems('UTF-8', Qt.MatchExactly)[0] self.listWidget.setCurrentItem(item) self.listWidget.scrollToItem(item) textAreaWidget = QWidget() self.hbox.addWidget(self.listWidget) self.connect(self.listWidget, SIGNAL("itemSelectionChanged()"), self.codecChanged) self.scroll = Scroll(self) self.text = TextEdit(self) self.hbox.addWidget(self.text) self.hbox.addWidget(self.scroll) textAreaWidget.setLayout(self.hbox) self.addWidget(self.listWidget) self.addWidget(textAreaWidget) self.setStretchFactor(0, 0) self.setStretchFactor(1, 1) def codecChanged(self): self.currentCodec = self.listWidget.selectedItems()[0].text() self.read(self.scroll.value()) def read(self, line): self.vfile = self.node.open() padd = 0 if line > padd: padd = 1 self.vfile.seek(self.offsets[line]+padd) self.text.clear() codec = QTextCodec.codecForName(self.currentCodec) decoder = codec.makeDecoder() self.text.textCursor().insertText(decoder.toUnicode(self.vfile.read(1024*10))) self.text.moveCursor(QTextCursor.Start) self.vfile.close() def linecount(self): offsets = [0] self.vfile = self.node.open() offsets.extend(self.vfile.indexes('\n')) self.vfile.close() self.lines = len(offsets) return offsets def updateWidget(self): pass def c_display(self): file = self.node.open() fsize = self.node.size() size = 0 self.buff = "" while size < fsize: try: tmp = file.read(4096) except vfsError, e: print self.buff break if len(tmp) == 0: print tmp break size += len(tmp) self.buff += tmp print tmp file.close() if len(self.buff): return self.buff class textviewer(Module): """Show text file content ex:cat /myfile.txt""" def __init__(self): Module.__init__(self, "textviewer", CAT) self.conf.addArgument({"name": "file", "description": "Text file to display", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["HTML", "ASCII", "XML", "text"]}) self.tags = "Viewers" self.flags = ["console", "gui"] self.icon = ":text" dff-1.3.0+dfsg.1/dff/modules/viewer/media/videothumbnailviewer.py000066400000000000000000000065621217176075400247500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_viewerimage_version__ = "1.0.0" from PyQt4 import QtCore, QtGui from PyQt4.QtCore import Qt, QSize, QString, SIGNAL, QThread from PyQt4.QtGui import QPixmap, QImage, QPushButton, QLabel, QWidget, QHBoxLayout, QVBoxLayout, QScrollArea, QIcon, QMatrix, QToolBar, QAction, QSizePolicy, QTabWidget, QTableWidget, QTableWidgetItem, QAbstractItemView, QLineEdit from PyQt4.QtGui import QImageReader, QMovie, QSizePolicy from dff.api.vfs import vfs from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Argument, typeId from dff.api.gui.thumbnail import Thumbnailer class ThumbnailVideoView(QWidget, Script): def __init__(self): Script.__init__(self, "thumbnailvideo") self.icon = None self.vfs = vfs.vfs() def start(self, args): try : self.preview = args["preview"].value() except IndexError: self.preview = False try: self.node = args["file"].value() except KeyError: pass def g_display(self): QWidget.__init__(self) self.hlayout = QHBoxLayout() self.scrollArea = QScrollArea() self.scrollWidget = QWidget() self.hhlayout = QHBoxLayout() self.scrollWidget.setLayout(self.hhlayout) self.setLayout(self.hlayout) self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.updateThumbnail) pixmap = self.thumbnailer.generate(self.node, iconSize = 256, frames = 10) if pixmap: self.updateThumbnail(self.node, pixmap) def updateThumbnail(self, node, pixmap): if pixmap: label = QLabel() label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) label.setWordWrap(True) label.setPixmap(pixmap) else: label = QLabel("Can't render, video is corrupted.") label.setAlignment(Qt.AlignCenter) self.hhlayout.addWidget(label) self.scrollArea.setWidget(self.scrollWidget) self.hlayout.addWidget(self.scrollArea) self.thumbnailer.unregister() def updateWidget(self): pass class videothumbnailviewer(Module): """Create thumbnail from video files.""" def __init__(self): Module.__init__(self, "thumbnailvideo", ThumbnailVideoView) self.conf.addArgument({"name": "file", "description": "Picture file to display", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "preview", "description": "Preview mode", "input": Argument.Empty}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["avi", "video"]}) self.tags = "Viewers" self.icon = ":movie" dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/000077500000000000000000000000001217176075400204755ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/CMakeLists.txt000077500000000000000000000012031217176075400232340ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier install_file( __init__.py regedit.py ) add_subdirectory(model) add_subdirectory(view) dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/__init__.py000066400000000000000000000000001217176075400225740ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/model/000077500000000000000000000000001217176075400215755ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/model/CMakeLists.txt000066400000000000000000000011231217176075400243320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier install_file( __init__.py regtree.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/model/__init__.py000066400000000000000000000000001217176075400236740ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/model/regtree.py000066400000000000000000000164131217176075400236110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import re from PyQt4.QtCore import SIGNAL, QAbstractItemModel, QModelIndex, QVariant, Qt, QDateTime, QSize, QString, Qt from PyQt4.QtGui import QColor, QIcon, QImage, QImageReader, QPixmap, QPixmapCache, QStandardItemModel, QStandardItem, QStyledItemDelegate, QBrush, QPen, QPalette, QPainter from PyQt4 import QtCore from dff.api.module.manager import ModuleProcessusManager # USED FOR DETECT REGISTRY TYPE HKLM = ["^SYSTEM$", "^SOFTWARE$", "^SAM$", "^SECURITY$"] HKU = ["^NTUSER.DAT$", "^DEFAULT$", "^USRCLASS.DAT$"] REPAIR = "WINDOWS/repair/" LOG = ".*.log$" ALT = ".*.alt$" SAVE = ".*.sav$" # USER ROLES class RegTreeModel(QStandardItemModel): def __init__(self, __parent = None): QStandardItemModel.__init__(self, __parent) self.__parent = __parent self.regmap = {} self.indexmap = {} if self.createRegMap(): self.createRootItems() def hasSubKeys(self, key): return len(key.subkeys) def createRegMap(self): processusManager = ModuleProcessusManager() regm = processusManager.get('winreg') if len(regm.registry) > 0: self.hives = regm.registry self.manager = regm for key, values in self.hives.iteritems(): try: h = key.getHive() iterator = h.iterator rtype, sourcenode = values rtype = self.RegType(sourcenode) if rtype != None: try: machine = self.regmap[sourcenode.fsobj().uid()] except: machine = self.regmap[sourcenode.fsobj().uid()] = {} try: regsource = machine[rtype] except: regsource = machine[rtype] = [] regsource.append(key) del(h) except: del(h) pass return True else: return False return False def createRootItems(self): self.root_item = self.invisibleRootItem() for machine_fsobjuid, regmodules in self.regmap.iteritems(): machineitem = regItem("Computer" + str(machine_fsobjuid)) machineitem.root = True machineitem.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.root_item.appendRow(machineitem) for rtype, regmodulist in regmodules.iteritems(): typeitem = regItem(rtype) typeitem.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) machineitem.appendRow(typeitem) for regmodule in regmodulist: try: h = regmodule.getHive() iterator = h.iterator keypath = iterator.current_path() if rtype == "HKEY_USERS": if (re.search("documents and settings", h.node.absolute(), re.IGNORECASE) or\ re.search("users", h.node.absolute(), re.IGNORECASE)) and not \ re.match("usrclass.dat", h.node.name(), re.IGNORECASE): name = h.node.parent().name() else: name = h.node.name() else: name = h.node.name() item = regItem(name, proc=regmodule,path=keypath) item.setChildren(len(iterator.current_key().subkeys)) item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) del(h) typeitem.appendRow(item) except: pass def hasChildren(self, parent): if parent.isValid(): item = self.itemFromIndex(parent) if (item.children > 0) or (item.proc == None): return True elif self.root_item.index().internalId() == parent.internalId(): return True else: return False return False def data(self, index, role): if not index.isValid(): return QVariant() item = self.itemFromIndex(index) if role == Qt.DisplayRole : return QVariant(item.text()) if role == Qt.DecorationRole: if item.root: icon = QPixmap(":dev_desktop.png") return QVariant(QIcon(icon)) else: icon = QPixmap(":folder.png") return QVariant(QIcon(icon)) def columnCount(self, parent = QModelIndex()): return 1 def createItem(self, current_path, module, key): p = current_path[:] p.append(unicode(key.name)) item = regItem(QString.fromUtf8(key.name), proc=module,path=p) item.setChildren(len(key.subkeys)) item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) return item def refreshTree(self, index): item = self.itemFromIndex(index) if not item.expanded: rhive = item.getHive() if rhive != None: hive = rhive.hive path = item.path if len(path) == 1: subkeys = hive.root.subkeys else: subkeys = hive.subtree(path[1:]).current_key().subkeys if len(subkeys) > 0: item_list = [] for key in subkeys: item_list.append(self.createItem(path, item.proc, key)) if len(item_list): self.emit(SIGNAL("layoutAboutToBeChanged()")) item.appendRows(item_list) self.emit(SIGNAL("layoutChanged()")) item.expanded = True item.deleteHive() def selectKey(self, index): if index.isValid(): item = self.itemFromIndex(index) rhive = item.getHive() path = item.path hive = rhive.hive if len(path) == 1: key = hive.root else: key = hive.subtree(path[1:]).current_key() self.emit(SIGNAL("keyItemSelected"), item) self.emit(SIGNAL("keySelected"), rhive, key) def RegType(self, node): try: if re.search(REPAIR, node.absolute(), re.IGNORECASE): return "HKEY_REPAIR" elif re.match(LOG, node.name(), re.IGNORECASE): return "HKEY_LOG" elif re.match(SAVE, node.name(), re.IGNORECASE): return "HKEY_SAVE" elif re.match(ALT, node.name(), re.IGNORECASE): return "HKEY_ALT" else: for hname in HKLM: if re.match(hname, node.name(), re.IGNORECASE): return "HKEY_LOCAL_MACHINE" for hname in HKU: if re.match(hname, node.name(), re.IGNORECASE): return "HKEY_USERS" for hname in HKUCL: if re.match(hname, node.name(), re.IGNORECASE): return "HKEY_CLASSES" return "HKEY_OTHERS" except: return None return None class regItem(QStandardItem): def __init__(self, name, proc=None, path=None): QStandardItem.__init__(self, name) self.proc = proc self.path = path self.hive = None self.children = 0 self.expanded = False self.root = False def setChildren(self, count): self.children = count def getHive(self): if self.proc != None: self.hive = self.proc.getHive() return self.hive else: return None def deleteHive(self): del(self.hive) # self.hive = None dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/regedit.py000066400000000000000000000051261217176075400224760ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # __dff_module_regedit_version__ = "1.0.0" from PyQt4 import QtCore, QtGui from PyQt4.QtCore import Qt, SIGNAL from PyQt4.QtGui import QWidget, QVBoxLayout, QTreeView, QSplitter from dff.api.vfs.vfs import vfs from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Variant, VList, VMap, Argument, Parameter, typeId from dff.modules.regedit.model.regtree import RegTreeModel from dff.modules.regedit.view.regtreeview import RegTreeView from dff.modules.regedit.view.valueview import TableValue from dff.modules.regedit.view.keyinfoview import KeyInfoView class REGEDIT(QWidget, Script): def __init__(self): Script.__init__(self, "Registry viewer") self.name = "Registry viewer" self.vfs = vfs() self.icon = None def start(self, args): self.args = args try: self.mountpoints = args["mountpoints"].value() except: print "No mount points" pass def g_display(self): QWidget.__init__(self, None) vlayout = QVBoxLayout() splitter = QSplitter(Qt.Horizontal) treemodel = RegTreeModel(self) treeview = RegTreeView(self) keyinfo = KeyInfoView(self, treemodel) tablevalue = TableValue(treemodel, self) treeview.setModel(treemodel) splitter.addWidget(treeview) splitter.addWidget(tablevalue) vlayout.addWidget(splitter) vlayout.addWidget(keyinfo) self.setLayout(vlayout) # self.regv = regviewer(self, self.mountpoints) def updateWidget(self): pass class regedit(Module): """Windows registry viewer""" def __init__(self): Module.__init__(self, "Registry viewer", REGEDIT) self.conf.addArgument({"input": Argument.Optional|Argument.List|typeId.Node, "name": "mountpoints", "description": "mountpoints of (NTFS) file systems", "parameters": {"type": Parameter.Editable, "minimum": 1} }) self.tags = "Viewers" self.flags = ["gui"] self.icon = ":text" dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/regviewer.py000066400000000000000000000111161217176075400230460ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import pyregfi from PyQt4.QtGui import * from PyQt4.QtCore import * from dff.api.vfs import * from dff.api.vfs.libvfs import * from dff.api.exceptions.libexceptions import * from dff.modules.winreg.pathmanager import * from dff.modules.winreg.regtype import regtype class regviewer(QVBoxLayout): def __init__(self, mainw, mountpoints): super(regviewer, self).__init__(mainw) self.mainw = mainw self.mountpoints = mountpoints for mp in self.mountpoints: rm = rootManager(mp.value()) self.hives = rm.getHives() self.init() def init(self): self.initViewShape() def initViewShape(self): self.splitter = QSplitter() self.tree = hiveTree(self, self.hives) self.table = tableView(self) self.splitter.addWidget(self.tree) self.splitter.addWidget(self.table) self.addWidget(self.splitter) class hiveTree(QTreeWidget): def __init__(self, parent, hives): super(hiveTree, self).__init__() self.regv = parent self.hivesnodes = hives self.hives = [] self.openHives() self.createTree() self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self.clicked) def openHives(self): for hivenode in self.hivesnodes: # print "fsobj name : ", hivenode.value().fsobj().name self.hives.append(pyregfi.Hive(hivenode.open())) def createTree(self): for hive in self.hives: self.registree(hive.root, QString(""), hive) def registree(self, currentkey, path, hive, parentitem=None): if len(currentkey.subkeys) > 0: i = self.createTreeItem(parentitem, hive, currentkey, path) for key in currentkey.subkeys: v = QVariant(getattr(key, "name")) self.registree(key, QString(path) + "/" + v.toString(), hive, i) else: self.createTreeItem(parentitem, hive, currentkey, path) def createTreeItem(self, parent, hive, currentkey, path): if parent: item = treeItem(parent, path, hive) else: item = treeItem(self, path, hive) v = QVariant(getattr(currentkey, "name")) item.setText(0, v.toString()) item.setIcon(0, QIcon(":password.png")) return item def clicked(self, item, column): self.regv.table.refreshValues(item.hive, str(item.path.toAscii())) class treeItem(QTreeWidgetItem): def __init__(self, parent, path, hive): super(treeItem, self).__init__(parent) self.path = path self.hive = hive class tableView(QTableWidget): def __init__(self, parent): super(tableView, self).__init__() self.parent = parent self.setHeaders() def setHeaders(self): self.setColumnCount(3) self.setHorizontalHeaderItem(0, QTableWidgetItem(QString("Name"))) self.setHorizontalHeaderItem(1, QTableWidgetItem(QString("Type"))) self.setHorizontalHeaderItem(2, QTableWidgetItem(QString("Data"))) self.horizontalHeader().setStretchLastSection(True) self.setAlternatingRowColors(True) self.verticalHeader().hide() def refreshValues(self, hive, path): self.clear() self.setRowCount(0) self.setHeaders() w = pathManager(hive, path) values = w.getValues() if values: i = 1 for value in values: self.setRowCount(i) if value.name: name = QTableWidgetItem(QString(value.name.encode('utf-8', 'replace'))) else: name = QTableWidgetItem(QString("Default")) vtype = QTableWidgetItem(QString(regtype[getattr(value, "type")])) d = QVariant(value.fetch_data()) data = QTableWidgetItem(QString(d.toString())) self.setItem(i - 1, 0, name) self.setItem(i - 1, 1, vtype) self.setItem(i- 1, 2, data) i += 1 dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/view/000077500000000000000000000000001217176075400214475ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/view/CMakeLists.txt000077500000000000000000000011671217176075400242170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier install_file( __init__.py regtreeview.py valueview.py keyinfoview.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/view/__init__.py000066400000000000000000000000001217176075400235460ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/view/keyinfoview.py000066400000000000000000000025651217176075400243700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import SIGNAL from PyQt4.QtGui import QLabel import datetime class KeyInfoView(QLabel): def __init__(self, parent, model): QLabel.__init__(self, parent) self.setMaximumHeight(30) self.__model = model self.connect(self.__model, SIGNAL("keyItemSelected"), self.keyChanged) def keyChanged(self, keyitem): rhive = keyitem.getHive() path = keyitem.path hive = rhive.hive if len(path) == 1: key = hive.root else: key = hive.subtree(path[1:]).current_key() abspath = key.name pitem = keyitem.parent() while pitem != None: abspath = pitem.text() + "\\" + abspath pitem = pitem.parent() modified = str(datetime.datetime.fromtimestamp(key.modified)) self.setText(abspath + "\n" + "Last modified: " + modified) del hive del rhive dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/view/regtreeview.py000066400000000000000000000023621217176075400243540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import QTreeView, QAbstractItemView class RegTreeView(QTreeView): def __init__(self, parent = None): QTreeView.__init__(self) self.setUniformRowHeights(True) self.setItemsExpandable(True) self.setExpandsOnDoubleClick(True) self.connect(self, SIGNAL("expanded(QModelIndex)"), self.indexExpanded) def indexExpanded(self, index): if index.isValid(): self.model().refreshTree(index) def mousePressEvent(self, e): try: index = self.indexAt(e.pos()) if index.isValid(): self.model().selectKey(index) except: pass QTreeView.mousePressEvent(self, e) dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/view/valueview.py000066400000000000000000000141571217176075400240400ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os from PyQt4 import QtCore, QtGui from PyQt4.QtCore import SIGNAL, QString, Qt, QByteArray from PyQt4.QtGui import QTableWidget, QHeaderView, QTableWidgetItem, QAbstractItemView, QMenu, QAction from dff.modules.winreg.regtype import regtype from dff.modules.winreg.decoders import DateDecoder, Rot13decoder, UserAssistDecoder, UTF16LEDecoder, UTF16BEDecoder DECODER = {0: "Date", 1: "Rot13", 2: "UserAssist", 3: "Default", 4: "UTF16-LE", 5: "UTF16-BE" } class TableValue(QTableWidget): def __init__(self, model, parent = None): super(QTableWidget, self).__init__(parent) self.parent = parent self.configure() self.model = model self.connect(self.model, SIGNAL("keySelected"), self.updateTable) self.createDecoderMenu() def configure(self): self.setColumnCount(3) self.setRowCount(0) self.setAlternatingRowColors(True) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.horizontalHeader().setResizeMode(1, QHeaderView.ResizeToContents) self.horizontalHeader().setResizeMode(2, QHeaderView.ResizeToContents) self.horizontalHeader().setResizeMode(3, QHeaderView.Stretch) self.horizontalHeader().setStretchLastSection(True) self.setShowGrid(True) self.verticalHeader().hide() self.setHorizontalHeaderLabels(("Name", "Type", "Data")) def resetTable(self): rows = self.rowCount() if rows > 0: while rows >= 0: self.removeRow(rows) rows = rows - 1 def updateTable(self, rhive, key): self.resetTable() values = key.values for value in values: currow = self.rowCount() self.setRowCount(self.rowCount() + 1) if value.name: name = value.name else: name = "(Default)" # item_name = valueItem(value.fetch_data(), key.name) # item_name = QTableWidgetItem(QString.fromUtf8(name)) # item_name.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) item_name = valueItem(name, key.name) item_type = QTableWidgetItem(QString(regtype[value.type])) item_type.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) item_data = valueItem(value.fetch_data(), key.name) #QTableWidgetItem(self.dataToQString(value.fetch_data())) # item_data.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.setItem(currow, 0, item_name) self.setItem(currow, 1, item_type) self.setItem(currow, 2, item_data) del(rhive) def createDecoderMenu(self): self.menu = QMenu() for decid, decname in DECODER.iteritems(): action = QAction(QString(decname), self.menu) self.menu.addAction(action) self.connect(self.menu, SIGNAL("triggered(QAction*)"), self.menuTriggered) # return menu def menuTriggered(self, action): # print "MENUUUU", action.text() try: item = self.currentItem().decode(action.text()) except: pass # print "Cur" def mousePressEvent(self, event): item = self.itemAt(event.pos()) if item != None: if event.button() == Qt.RightButton: # print item.text() self.setCurrentItem(item) self.menu.popup(event.globalPos()) else: self.setCurrentItem(item) # option = QStyleOptionButton() # option.rect = QRect(3,2,20,20) # element = self.style().subElementRect(QStyle.SE_CheckBoxIndicator, option) # if element.contains(event.pos()): # if self.isOn: # self.isOn = False # self.emit(SIGNAL("headerSelectionClicked"), False) # else: # self.emit(SIGNAL("headerSelectionClicked"), True) # self.isOn = True # self.update() # self.headerDataChanged(Qt.Horizontal, 0, 0) # else: # index = self.logicalIndexAt(event.pos()) # if self.cursor().shape() != Qt.SplitHCursor: # self.view.headerClicked(index) # QHeaderView.mousePressEvent(self, event) class valueItem(QTableWidgetItem): def __init__(self, data, keyname): QTableWidgetItem.__init__(self) self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) self.data = data self.keyname = keyname self.setText(self.dataToQString(self.data)) def dataToQString(self, data): # if keyInfo.valueDataDecoder(): # if type(data) == bytearray and len(data): # data = QString.fromUtf8(keyInfo.valueDataDecode(data, keyName).decode()) # elif type(data) == long or type(data) == int: # data = QString.fromUtf8(keyInfo.valueDataDecode(data, keyName).decode()) if type(data) == bytearray: data = QByteArray(data).toHex() if type(data) == long: data = str(data) if type(data) == int: data = str(data) if type(data) == list: d = unicode() for t in data: d += t d += ", " data = d elif data == None: data = 'None' return QString.fromUtf8(data) def decode(self, decodername): if decodername == "Default": self.setText(self.dataToQString(self.data)) elif decodername == "Date": self.setText(QString(DateDecoder(self.data).decode())) elif decodername == "Rot13": self.setText(QString(Rot13decoder(self.data).decode())) elif decodername == "UserAssist": self.setText(QString(UserAssistDecoder(self.data, self.keyname).decode())) elif decodername == "UTF16-LE": self.setText(QString(UTF16LEDecoder(self.data).decode())) elif decodername == "UTF16-BE": self.setText(QString(UTF16BEDecoder(self.data).decode())) else: self.setText(self.dataToQString(self.data.encode("UTF8"))) dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/widget/000077500000000000000000000000001217176075400217605ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/regedit/widget/regviewer.py000066400000000000000000000111161217176075400243310ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import pyregfi from PyQt4.QtGui import * from PyQt4.QtCore import * from dff.api.vfs import * from dff.api.vfs.libvfs import * from dff.api.exceptions.libexceptions import * from dff.modules.winreg.pathmanager import * from dff.modules.winreg.regtype import regtype class regviewer(QVBoxLayout): def __init__(self, mainw, mountpoints): super(regviewer, self).__init__(mainw) self.mainw = mainw self.mountpoints = mountpoints for mp in self.mountpoints: rm = rootManager(mp.value()) self.hives = rm.getHives() self.init() def init(self): self.initViewShape() def initViewShape(self): self.splitter = QSplitter() self.tree = hiveTree(self, self.hives) self.table = tableView(self) self.splitter.addWidget(self.tree) self.splitter.addWidget(self.table) self.addWidget(self.splitter) class hiveTree(QTreeWidget): def __init__(self, parent, hives): super(hiveTree, self).__init__() self.regv = parent self.hivesnodes = hives self.hives = [] self.openHives() self.createTree() self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self.clicked) def openHives(self): for hivenode in self.hivesnodes: # print "fsobj name : ", hivenode.value().fsobj().name self.hives.append(pyregfi.Hive(hivenode.open())) def createTree(self): for hive in self.hives: self.registree(hive.root, QString(""), hive) def registree(self, currentkey, path, hive, parentitem=None): if len(currentkey.subkeys) > 0: i = self.createTreeItem(parentitem, hive, currentkey, path) for key in currentkey.subkeys: v = QVariant(getattr(key, "name")) self.registree(key, QString(path) + "/" + v.toString(), hive, i) else: self.createTreeItem(parentitem, hive, currentkey, path) def createTreeItem(self, parent, hive, currentkey, path): if parent: item = treeItem(parent, path, hive) else: item = treeItem(self, path, hive) v = QVariant(getattr(currentkey, "name")) item.setText(0, v.toString()) item.setIcon(0, QIcon(":password.png")) return item def clicked(self, item, column): self.regv.table.refreshValues(item.hive, str(item.path.toAscii())) class treeItem(QTreeWidgetItem): def __init__(self, parent, path, hive): super(treeItem, self).__init__(parent) self.path = path self.hive = hive class tableView(QTableWidget): def __init__(self, parent): super(tableView, self).__init__() self.parent = parent self.setHeaders() def setHeaders(self): self.setColumnCount(3) self.setHorizontalHeaderItem(0, QTableWidgetItem(QString("Name"))) self.setHorizontalHeaderItem(1, QTableWidgetItem(QString("Type"))) self.setHorizontalHeaderItem(2, QTableWidgetItem(QString("Data"))) self.horizontalHeader().setStretchLastSection(True) self.setAlternatingRowColors(True) self.verticalHeader().hide() def refreshValues(self, hive, path): self.clear() self.setRowCount(0) self.setHeaders() w = pathManager(hive, path) values = w.getValues() if values: i = 1 for value in values: self.setRowCount(i) if value.name: name = QTableWidgetItem(QString(value.name.encode('utf-8', 'replace'))) else: name = QTableWidgetItem(QString("Default")) vtype = QTableWidgetItem(QString(regtype[getattr(value, "type")])) d = QVariant(value.fetch_data()) data = QTableWidgetItem(QString(d.toString())) self.setItem(i - 1, 0, name) self.setItem(i - 1, 1, vtype) self.setItem(i- 1, 2, data) i += 1 dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/000077500000000000000000000000001217176075400206605ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/CMakeLists.txt000066400000000000000000000012571217176075400234250ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge install_file( __init__.py compute_thread.py drawer.py list_thread.py paint_area.py options_layout.py timeline.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/__init__.py000066400000000000000000000011231217176075400227660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge __all__ = ['timeline', 'dffdatetime'] dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/compute_thread.py000066400000000000000000000145411217176075400242420ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # from datetime import timedelta from PyQt4.QtCore import QString, QThread, SIGNAL, QMutex, QWaitCondition, QMutexLocker from dff.api.types.libtypes import typeId class WorkerThread(QThread): ''' Schedule things to do Wait all time or launch/wake other threads to recompute max amount of node to display with or without zoom, refresh/redraw paint area, etc. . ''' def __init__(self, parent = None): super(WorkerThread, self).__init__(parent) self.mutex = QMutex() self.condition = QWaitCondition() self.restart = False self.abort = False self.timeline = parent self.countThread = parent.countThread self.populateThread = parent.populateThread self.maxOccThread = parent.maxOccThread def __del__(self): self.mutex.lock() self.abort = True self.condition.wakeOne() self.mutex.unlock() self.wait() def render(self): locker = QMutexLocker(self.mutex) if not self.isRunning() and not self.countThread.isRunning() and not self.populateThread.isRunning() and not self.maxOccThread.isRunning(): self.start(QThread.LowPriority) else: self.restart = True self.condition.wakeOne() def run(self): while True: self.mutex.lock() # Fetch value from timeline nodeCount = self.timeline.nodeCount dataListsCreated = self.timeline.dataListsCreated if dataListsCreated: self.timeline.findMaxValue() xHop = self.timeline.xHop maxOcc = self.timeline.maxOcc self.mutex.unlock() if not nodeCount and not self.restart and not self.countThread.isRunning(): self.countThread.start() elif nodeCount and not dataListsCreated and not self.restart and not self.populateThread.isRunning(): self.populateThread.start() elif nodeCount and dataListsCreated and xHop and not maxOcc and not self.restart and not self.maxOccThread.isRunning(): self.maxOccThread.start() elif nodeCount and dataListsCreated and xHop and maxOcc and not self.restart and not self.maxOccThread.isRunning(): self.emit(SIGNAL('refresh'), True) if self.abort: return self.mutex.lock() if not self.restart: self.condition.wait(self.mutex) self.restart = False self.mutex.unlock() class CountThread(QThread): ''' Detects every time attributes in children of a given node. ''' def __init__(self, parent, callback): QThread.__init__(self) self.timeline = parent self.node = self.timeline.node self.nodeCount = 0 self.timesCount = 0 self.timeMap = self.timeline.timeMap self.connect(self, SIGNAL("finished()"), callback) def timeFound(self, timesCount, mod, key): try: if key not in self.timeMap[mod]: self.timeMap[mod].append(key) except KeyError: self.timeMap[mod] = [key] timesCount += 1 return True, timesCount def attrRecCount(self, tab, attr, countMe, timesCount, mod = None, attrPath = []): """ FIXME Use node.attributeByType ? from cpp, to bench ! """ for key in attr.keys(): if attr[key] and attr[key].type() == typeId.Map: if mod: countMe, timesCount = self.attrRecCount(tab + ' ', attr[key].value(), countMe, timesCount, mod, attrPath + [key]) else: countMe, timesCount = self.attrRecCount(tab + ' ', attr[key].value(), countMe, timesCount, key) elif attr[key] and attr[key].type() == typeId.List: for i in xrange(attr[key].value().size()): if attr[key].value()[i].type() == typeId.VTime: countMe, timesCount = self.timeFound(timesCount, mod, attrPath + [key]) elif attr[key] and attr[key].type() == typeId.VTime: countMe, timesCount = self.timeFound(timesCount, mod, attrPath + [key]) return countMe, timesCount def countNode(self, node): nodeList = node.children() for oneNode in nodeList: countMe = False timesCount = 0 countMe, timesCount = self.attrRecCount('', oneNode.attributes(), countMe, timesCount) if countMe: self.nodeCount += 1 self.timesCount += timesCount def recurse(self, node): if node.hasChildren(): self.countNode(node) nodeList = node.children() for oneNode in nodeList: if oneNode.hasChildren(): self.recurse(oneNode) def run(self): self.timeline.setStateInfo('Evaluating nodes amount') self.recurse(self.node) self.timeline.nodeCount = self.nodeCount self.timeline.timesCount = self.timesCount self.timeline.timeMap = self.timeMap class MaxOccThread(QThread): ''' Find maximum amount of node from a given resolution. Usefull for vertical scaling. ''' def __init__(self, parent, callback): QThread.__init__(self) self.timeline = parent parent.connect(self, SIGNAL("finished()"), callback) def run(self): self.xRange = self.timeline.xRange self.xHop = self.timeline.xHop self.baseDateMin = self.timeline.baseDateMin self.baseDateMax = self.timeline.baseDateMax # Find x drawing area newMaxOcc = 0 for family in self.timeline.options.configuration: for time in family[1]: timeChecked = self.baseDateMin if timeChecked == self.baseDateMax: # Every nodes have the same time, setting maxOcc computing time + 100usec occ = self.timeline.elementsInRange(time[1][5][1], timeChecked, timeChecked + 100) if occ > newMaxOcc: newMaxOcc = occ while timeChecked <= self.baseDateMax: occ = self.timeline.elementsInRange(time[1][5][1], timeChecked, timeChecked + self.xHop) if occ > newMaxOcc: newMaxOcc = occ timeChecked += self.xHop self.timeline.maxOcc = newMaxOcc self.timeline.setStateInfo('Done - check max amount of nodes in range is ' + str(newMaxOcc) + ' nodes') dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/drawer.py000066400000000000000000000173611217176075400225260ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # from datetime import datetime from PyQt4.QtCore import Qt, QPoint, QLineF class Drawer(): def __init__(self, timeline): self.timeline = timeline self.ploter = timeline.ploter self.options = timeline.options self.painter = None self.node = None self.m = timeline.m self.paddingYText = 4 self.yLeftMargin = 0 def setDynamicValues(self, timeline): self.painter = timeline.painter self.node = timeline.node self.baseDateMax = timeline.baseDateMax self.baseDateMin = timeline.baseDateMin self.selDateMin = timeline.selDateMin self.selDateMax = timeline.selDateMax self.maxOcc = timeline.maxOcc def drawGrid(self): """ Draw horizontal and vertical lines of grid yLeftMargin must be set, so call drawYInfos first. """ pen = self.painter.pen() pen.setColor(Qt.black) pen.setStyle(Qt.SolidLine) self.painter.setPen(pen) # Draw X line # self.painter.drawLine(self.m, self.painter.drawLine(self.yLeftMargin, self.ploter.height - self.m, self.ploter.width - self.m, self.ploter.height - self.m) # Draw Y line # self.painter.drawLine(self.m, self.painter.drawLine(self.yLeftMargin, self.ploter.height - self.m, # self.m, self.yLeftMargin, self.m / 3) def drawInfos(self): self.drawYInfos() self.drawXInfos() def drawXInfos(self): pen = self.painter.pen() i = 1 scale = 6 x = self.yLeftMargin y = self.ploter.height - self.m if not self.selDateMin: date = self.baseDateMin shift_date = (self.baseDateMax - self.baseDateMin) / scale else: date = self.selDateMin shift_date = (self.selDateMax - self.selDateMin) / scale while i <= scale + 1: pen.setColor(Qt.black) pen.setStyle(Qt.SolidLine) pos = QPoint(x - 40, y + 17) self.painter.setPen(pen) # Draw vertical doted line self.painter.drawLine(x, y - 3, x, y + 3) # Draw date self.painter.drawText(pos, str(self.timeline.fromUSec(date).strftime('%d.%m.%Y'))) # If number of days shown < scale, draw time if shift_date <= (86400 * 1000000): pos.setY(pos.y() + 15) pos.setX(pos.x() + 9) # Draw time self.painter.drawText(pos, str(self.timeline.fromUSec(date).strftime('%H:%M:%S'))) pen.setColor(Qt.gray) pen.setStyle(Qt.DotLine) self.painter.setPen(pen) if i != 1: self.painter.drawLine(x, y + 3, x, self.m / 3) x = self.yLeftMargin + (i * ((self.ploter.width - self.m - self.yLeftMargin) / (scale))) i += 1 date += shift_date pen.setStyle(Qt.SolidLine) self.painter.setPen(pen) def drawYInfos(self): i = 1 scale = 10.0 y = self.m / 3 # Setting max occurence depending of zoom if not self.timeline.maxOccZoom: maxOcc = self.timeline.maxOcc else: maxOcc = self.timeline.maxOccZoom # Draw Y legend i = 1 y = self.m / 3 pen = self.painter.pen() while i <= scale: pen.setColor(Qt.black) pen.setStyle(Qt.SolidLine) self.painter.setPen(pen) self.painter.drawLine(self.yLeftMargin - 3, y, self.yLeftMargin + 3, y) self.painter.drawText(self.paddingYText, y - 8, self.yLeftMargin - self.paddingYText * 2, 50, 0, str(maxOcc - (i - 1.0) * (maxOcc / scale))) pen.setColor(Qt.gray) pen.setStyle(Qt.DotLine) self.painter.setPen(pen) self.painter.drawLine(self.yLeftMargin + 3, y, self.ploter.width - self.m, y) y = (self.m / 3) + i * ((self.ploter.height - (self.m + self.m / 3)) / scale) i += 1 pen.setStyle(Qt.SolidLine) self.painter.setPen(pen) def drawTimeline(self, painter, elements): self.painter = painter # Find x drawing area xRange = (self.ploter.width - self.m - self.yLeftMargin) / self.timeline.lineHeight # Find secs between each x hop if not self.timeline.selDateMin: self.xHop = (self.baseDateMax - self.baseDateMin) / xRange else: # We are in a zoom self.xHop = (self.selDateMax - self.selDateMin) / xRange # FIXME no need to set it for each line ...! self.timeline.xHop = self.xHop self.drawEverythingInX(elements) def drawEverythingInX(self, elements): if not self.timeline.selDateMin: timeChecked = self.baseDateMin limit = self.baseDateMax else: timeChecked = self.selDateMin limit = self.selDateMax while timeChecked <= limit: occ = self.timeline.elementsInRange(elements, timeChecked, timeChecked + self.xHop) if occ: self.drawOneLine(timeChecked, occ) timeChecked += self.xHop if self.xHop <= 0: # FIXME set stateinfo to ("error", "Not enough different date in this node") return # FIXME set stateinfo to ("result", "no problem") return def drawOneLine(self, timeChecked, occ): if not self.timeline.selDateMin: dateMin = self.timeline.baseDateMin dateMax = self.timeline.baseDateMax maxOcc = self.timeline.maxOcc else: dateMin = self.timeline.selDateMin dateMax = self.timeline.selDateMax maxOcc = self.timeline.maxOccZoom if (dateMax - dateMin) > 0: x = ((timeChecked - dateMin) * (self.ploter.width - self.m - self.yLeftMargin)) / (dateMax - dateMin) + self.yLeftMargin y = (((maxOcc - occ) * (self.ploter.height - self.m - (self.m / 3))) / maxOcc) + (self.m / 3) if x <= self.yLeftMargin: x += 3 startY = self.ploter.height - self.m - 1 endY = y if y < self.ploter.height - self.m - 1: # Y level to show is biggest than penWidth startY -= 1 endY -= 1 if endY <= self.m / 3: # Y level is biggest than Y max value endY = self.m / 3 + 2 line = QLineF(x, startY, x, endY) self.painter.drawLines(line) def findXTime(self, x): self.selDateMin = self.timeline.selDateMin self.selDateMax = self.timeline.selDateMax usecX = 0 if not self.selDateMin or not self.selDateMax: # Click from main (original) view usecX = ((x - self.yLeftMargin) * (self.baseDateMax - self.baseDateMin)) / (self.ploter.width - self.m - self.yLeftMargin) usecX += self.baseDateMin if usecX < self.baseDateMin: usecX = self.baseDateMin if usecX > self.baseDateMax: usecX = self.baseDateMax # Avoid microseconds usecStr = str(int(usecX)) usecX = int(usecStr[:-6] + '000000') ret = self.timeline.fromUSec(usecX) return datetime(ret.year, ret.month, ret.day, ret.hour, ret.minute, ret.second, 0) else: # Click already from a zoom view usecX = ((x - self.yLeftMargin) * (self.selDateMax - self.selDateMin)) / (self.ploter.width - self.m - self.yLeftMargin) usecX += self.selDateMin if usecX < self.selDateMin: usecX = self.selDateMin if usecX > self.selDateMax: usecX = self.selDateMax # Avoid microseconds usecStr = str(int(usecX)) usecX = int(usecStr[:-6] + '000000') ret = self.timeline.fromUSec(usecX) return datetime(ret.year, ret.month, ret.day, ret.hour, ret.minute, ret.second, 0) return None dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/list_thread.py000066400000000000000000000141001217176075400235300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # from datetime import datetime from PyQt4.QtCore import QString, QThread, SIGNAL from dff.api.types.libtypes import vtime, typeId class DataThread(QThread): def __init__(self, parent, callback): QThread.__init__(self) self.timeline = parent self.configuration = None self.node = None self.count = 0 parent.connect(self, SIGNAL("finished()"), callback) def insert(self, data, node, root, dateLimits): ''' List insert using dichotomy There is two lists, one for ordered dates, and one other for corresponding nodes. If several nodes have the same timestamp, they are registered in the same list entry in an array. FIXME checks bellow have to be avoided, but we must do it because extfs for exemple returns invalid times. ''' if not data.month: month = 1 else: month = data.month if not data.day: day = 1 else: day = data.day data = self.timeline.toUSec(datetime(data.year, month, day, data.hour, data.minute, data.second, data.usecond)) if not root['dates']: root['dates'] = [data] root['nodes'] = [[node.this]] dateLimits[0] = data dateLimits[1] = data else: iMin, iMax = 0, len(root['dates']) - 1 iCurrent = iMax / 2 while iMin != iMax or not iMax: if data == root['dates'][iCurrent]: root['nodes'][iCurrent].append(node.this) break elif data > root['dates'][iCurrent] and iCurrent == len(root['dates']) - 1: root['dates'].append(data) root['nodes'].append([node.this]) dateLimits[1] = data break elif data > root['dates'][iCurrent] and data < root['dates'][iCurrent + 1]: root['dates'].insert(iCurrent + 1, data) root['nodes'].insert(iCurrent + 1, [node.this]) break elif data < root['dates'][iCurrent] and not iCurrent: root['dates'].insert(0, data) root['nodes'].insert(0, [node.this]) dateLimits[0] = data break elif data < root['dates'][iCurrent] and data > root['dates'][iCurrent - 1]: root['dates'].insert(iCurrent, data) root['nodes'].insert(iCurrent, [node.this]) break elif data > root['dates'][iCurrent]: iMin = iCurrent iCurrent = iCurrent + ((iMax - iCurrent) / 2) if iCurrent == iMin: iCurrent += 1 elif data < root['dates'][iCurrent]: iMax = iCurrent iCurrent = iMin + ((iCurrent - iMin) / 2) return root, dateLimits def addNode(self, node): """ TODO Make it work for VList ! Especially take care of VMap embeded in VList. Also see compute_thread.CountThread.attrRecCount. """ nodeList = node.children() for oneNode in nodeList: countMe = False attr = oneNode.attributes() for family in self.configuration: if family[0] and family[1]: # module name is family[0] for time in family[1]: try: a = attr[family[0]].value() for k in time[0]: try: a = a[k] except IndexError: break except TypeError: break if a.type() == typeId.VTime and a.value() != None: d = a.value().get_time() if d.year == 0 and d.month == 0 and d.day == 0: continue try: time[1][5][1], time[1][6][1] = self.insert(a.value(), oneNode, time[1][5][1], time[1][6][1]) except ValueError: continue countMe = True v = a.value() break else: a = a.value() except IndexError: pass if countMe: self.count += 1 if not self.count % 100: # XXX % 100 realy improve speed ? percent = (self.count * 100) / self.timeline.nodeCount self.timeline.setStateInfo(str(percent) + "% registering nodes dates") def populate(self, node): if node.hasChildren(): self.addNode(node) nodeList = node.children() for oneNode in nodeList: if oneNode.hasChildren(): self.populate(oneNode) def run(self): self.timeline.setStateInfo('Registering nodes dates') self.configuration = self.timeline.options.configuration self.node = self.timeline.node self.populate(self.node) self.timeline.setStateInfo('Done - ' + str(self.timeline.timesCount) + ' dates from ' + str(self.timeline.nodeCount) + ' nodes registered') def dump(self, root, dateLimits): current = root print "min:", dateLimits[0], dateLimits[0].usec, "max:", dateLimits[1], dateLimits[1].usec while current: print len(current.nodeArray), " ", current.data, current.data.usec current = current.next dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/options_layout.py000066400000000000000000000435011217176075400243250ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # from PyQt4.QtCore import Qt, SIGNAL, QString, QRect from PyQt4.QtGui import QWidget, QCheckBox, QHBoxLayout, QVBoxLayout, QComboBox, QLabel, QTabWidget, QGroupBox, QPushButton, QPalette, QScrollArea from dff.api.vfs import vfs, libvfs from dff.api.vfs.libvfs import Node, VLink from dff.api.types.libtypes import Variant, RCVariant from dff.api.events.libevents import event class OptionsLayout(QTabWidget): ''' Manages right panel. Provides general informations, navigation and timestamp selection. Navigation allow user to zoom in timeline. Timestamp selection allow user to select which timestamp to display with which color. ''' def __init__(self, parent): QTabWidget.__init__(self) self.setTabPosition(QTabWidget.East) self.init(parent) self.initShape() def init(self, parent): self.VFS = libvfs.VFS.Get() self.timeline = parent self.swapIndex = -1 self.swapColor = '' self.metricIndex = -1 self.configuration = [] self.zoom = False self.exportedNode = None def initShape(self): self.h = QHBoxLayout() self.vbox = QVBoxLayout() self.vbox.setMargin(0) self.vbox.setSpacing(0) self.vbox.setAlignment(Qt.AlignTop) self.setLayout(self.vbox) self.infoBox = QGroupBox('Global information') # self.infoBox.setFlat(True) self.totalNodes = QLabel('No time found in nodes') self.startTime = QLabel('No start time') self.endTime = QLabel('No end time') self.navBox = QGroupBox('Navigation') self.selStartTime = QLabel('No selection start time') self.selEndTime = QLabel('No selection end time') self.buttonLayout = QHBoxLayout() self.zoomButton = QPushButton('Zoom') self.zoomButton.setEnabled(False) self.zoomButton.connect(self.zoomButton, SIGNAL("clicked(bool)"), self.zoomClick) self.dezoomButton = QPushButton('Original Size') self.dezoomButton.setEnabled(False) self.dezoomButton.connect(self.dezoomButton, SIGNAL("clicked(bool)"), self.dezoomClick) self.exportButton = QPushButton('Export') self.exportButton.setEnabled(False) self.exportButton.connect(self.exportButton, SIGNAL("clicked(bool)"), self.exportClick) self.buttonLayout.setAlignment(Qt.AlignLeft) self.buttonLayout.addWidget(self.zoomButton) self.buttonLayout.addWidget(self.dezoomButton) self.selectedNodes = QLabel('Nothing selected') self.infoLayout = QVBoxLayout() self.infoLayout.setAlignment(Qt.AlignTop) self.infoLayout.addWidget(self.totalNodes) self.infoLayout.addWidget(self.startTime) self.infoLayout.addWidget(self.endTime) self.infoBox.setLayout(self.infoLayout) self.navLayout = QVBoxLayout() self.navLayout.setAlignment(Qt.AlignTop) self.navLayout.addWidget(self.selStartTime) self.navLayout.addWidget(self.selEndTime) self.navLayout.addLayout(self.buttonLayout) self.navLayout.addWidget(self.selectedNodes) self.navLayout.addWidget(self.exportButton) self.navBox.setLayout(self.navLayout) self.familyLayout = QVBoxLayout() self.familyLayout.setMargin(0) self.familyLayout.setSpacing(0) self.familyWidget = QWidget() self.familyWidget.setLayout(self.familyLayout) self.familyScroll = QScrollArea() self.insertTab(0, self.infoBox, 'Global') self.insertTab(1, self.navBox, 'Navigation') self.insertTab(2, self.familyScroll, 'Display') def newInformations(self): if self.timeline.timesCount > 1: sTimes = str(self.timeline.timesCount) + ' time values' else: sTimes = 'One time value' if self.timeline.nodeCount > 1: sNodes = str(self.timeline.nodeCount) + ' nodes' else: sNodes = 'one node' self.totalNodes.setText(sTimes + '\n' + sNodes) if self.timeline.baseDateMin != self.timeline.dateMin: self.startTime.setText('From ' + str(self.timeline.fromUSec(self.timeline.baseDateMin).strftime('%d.%m.%Y %H:%M:%S'))) if self.timeline.selDateMin: self.selStartTime.setText('From ' + str(self.timeline.fromUSec(self.timeline.selDateMin).strftime('%d.%m.%Y %H:%M:%S'))) else: self.selStartTime.setText('No selection start time') if self.timeline.baseDateMax != self.timeline.dateMax: self.endTime.setText('To ' + str(self.timeline.fromUSec(self.timeline.baseDateMax).strftime('%d.%m.%Y %H:%M:%S'))) if self.timeline.selDateMax: self.selEndTime.setText('To ' + str(self.timeline.fromUSec(self.timeline.selDateMax).strftime('%d.%m.%Y %H:%M:%S'))) else: self.selEndTime.setText('No selection end time') def dumpOptionsConf(self): for family in self.configuration: if not family[1]: print family[0] + ': empty' else: print family[0] + ':' for time in family[1]: print '\t' + time[0] + ':' for param in time[1]: print '\t\t' + param[0] + ':', param[1] def createMetricTools(self): ''' Called once countThread is over. ''' if not self.configuration: # First, create configuration dictionary i = 0 for timeFamily, timeList in self.timeline.timeMap.items(): if len(timeList): # One sub dictionary per time family self.configuration.append([timeFamily, []]) for oneMetric in timeList: # One sub sub dictionary per family sub time # checked indicate if item is displayed # color indicate which color to use if i < len(self.timeline.colors): self.configuration[-1][1].append([oneMetric, [['checked', True], ['color', self.timeline.colors[i][0]], ['checkBox', None], ['colorWidget', None], ['colorWidgetIndex', -1], ['orderedNodeList', {'dates':None, 'nodes':None}], ['dateLimits', [long(0), long(0xffffffffffffffff)]], ['mainPixmap', [True, None]], ['zoomPixmap', [True, None]]]]) else: self.configuration[-1][1].append([oneMetric, [['checked', False], ['color', ''], ['checkBox', None], ['colorWidget', None], ['colorWidgetIndex', -1], ['orderedNodeList', {'dates':None, 'nodes':None}], ['dateLimits', [long(0), long(0xffffffffffffffff)]], ['mainPixmap', [True, None]], ['zoomPixmap', [True, None]]]]) i += 1 else: self.configuration.append([timeFamily, []]) # Configuration object created, now create graphical view of it # self.dumpOptionsConf() i = 0 for family in self.configuration: if family[1]: box = QGroupBox(family[0]) oneTime = QVBoxLayout() for time in family[1]: hbox = QHBoxLayout() time[1][2][1] = QCheckBox(':'.join(time[0])) self.connect(time[1][2][1], SIGNAL("stateChanged(int)"), self.checkboxClick) time[1][3][1] = QComboBox() for color in self.timeline.colors: time[1][3][1].addItem(color[0]) palette = time[1][2][1].palette() if i < len(self.timeline.colors): time[1][2][1].setChecked(time[1][0][1]) # Colorize foreground palette.setColor(QPalette.WindowText, self.timeline.colors[i][1]) time[1][3][1].setCurrentIndex(i) time[1][4][1] = i else: # In case every colors are already used, don't check time (default) and don't select any color palette.setColor(QPalette.WindowText, Qt.gray) time[1][0][1] = False time[1][3][1].setEnabled(False) time[1][2][1].setPalette(palette) self.connect(time[1][3][1], SIGNAL("currentIndexChanged(const QString&)"), self.colorChange) hbox.addWidget(time[1][2][1]) hbox.addWidget(time[1][3][1]) oneTime.addLayout(hbox) i += 1 box.setLayout(oneTime) optimum = box.minimumSizeHint() box.setFixedSize(optimum) if optimum.width() > self.familyLayout.sizeHint().width(): geom = QRect(0, 0, optimum.width(), self.familyLayout.sizeHint().height() + optimum.height()) else: geom = QRect(0, 0, self.familyLayout.sizeHint().width(), self.familyLayout.sizeHint().height() + optimum.height()) self.familyLayout.addWidget(box) self.familyLayout.setGeometry(geom) self.familyWidget.setFixedSize(geom.width(), geom.height()) self.familyScroll.setWidget(self.familyWidget) else: # Configuration object already created, we are called because am item has been # unchecked or its color has changed. pass def colorChange(self, colorText): loop = 2 while loop: i = 0 for family in self.configuration: for time in family[1]: if time[1][3][1]: if QString(time[1][1][1]) != time[1][3][1].currentText() and self.swapIndex == -1 and self.metricIndex == -1 and time[1][3][1].isEnabled(): # This selection has just been changed self.swapColor = time[1][1][1] self.swapIndex = time[1][4][1] time[1][1][1] = str(colorText) #Color palette = time[1][2][1].palette() palette.setColor(QPalette.WindowText, self.timeline.colors[time[1][3][1].currentIndex()][1]) time[1][2][1].setPalette(palette) time[1][4][1] = time[1][3][1].currentIndex() time[1][7][1][0] = True time[1][8][1][0] = True self.metricIndex = i if QString(time[1][1][1]) == colorText and self.swapIndex != -1 and self.metricIndex != i and time[1][3][1].isEnabled(): # This selection is impacted because color is the same as the one just selected # Changing color relaunch another signal. time[1][1][1] = self.swapColor time[1][4][1] = self.swapIndex time[1][3][1].setCurrentIndex(self.swapIndex) time[1][7][1][0] = True time[1][8][1][0] = True #Color palette = time[1][2][1].palette() palette.setColor(QPalette.WindowText, self.timeline.colors[time[1][3][1].currentIndex()][1]) time[1][2][1].setPalette(palette) self.metricIndex = -1 i += 1 loop -= 1 # if self.swapColor == '': # Swap already done ; redraw self.timeline.updatePaintingArea() self.swapIndex = -1 self.swapColor = '' self.metricIndex = -1 def checkboxClick(self, newState): self.selectedNodes.setText('Nothing selected') self.zoomButton.setEnabled(False) self.exportButton.setEnabled(False) for family in self.configuration: for time in family[1]: if time[1][2][1]: palette = time[1][2][1].palette() if not time[1][2][1].checkState() and time[1][0][1]: # This box has just been unchecked time[1][0][1] = False time[1][3][1].setEnabled(False) palette.setColor(QPalette.WindowText, Qt.gray) elif time[1][2][1].checkState() and not time[1][0][1]: # This box has just been checked time[1][0][1] = True time[1][3][1].setEnabled(True) # Deactivate color already used palette.setColor(QPalette.WindowText, self.timeline.colors[time[1][3][1].currentIndex()][1]) time[1][1][1] = self.timeline.colors[time[1][3][1].currentIndex()][0] time[1][4][1] = time[1][3][1].currentIndex() time[1][7][1][0] = True time[1][8][1][0] = True for family2 in self.configuration: # sure, 2 is ugly, it is used to search color to remove for time2 in family2[1]: if time2[1][3][1] and time2[1][3][1].isEnabled(): if self.timeline.colors[time2[1][3][1].currentIndex()][0] == self.timeline.colors[time[1][3][1].currentIndex()][0] and time2[1][3][1] != time[1][3][1]: palette2 = time2[1][2][1].palette() time2[1][0][1] = False time2[1][2][1].setChecked(False) time2[1][3][1].setEnabled(False) palette2.setColor(QPalette.WindowText, Qt.gray) time2[1][2][1].setPalette(palette2) time[1][2][1].setPalette(palette) self.timeline.updatePaintingArea() def zoomClick(self, clickState): self.timeline.maxOccZoom = 0 rect = self.timeline.ploter.selectionRect.rect() newSelDateMin = self.timeline.draw.findXTime(rect.x()) newSelDateMax = self.timeline.draw.findXTime(rect.x() + rect.width()) self.timeline.selDateMin = self.timeline.toUSec(newSelDateMin) self.timeline.selDateMax = self.timeline.toUSec(newSelDateMax) self.newInformations() self.dezoomButton.setEnabled(True) self.zoomButton.setEnabled(False) self.exportButton.setEnabled(False) txt = self.selectedNodes.text().__str__() self.selectedNodes.setText(txt[:txt.rfind(' ')] + ' displayed') self.zoom = True self.timeline.updatePaintingArea(True) def dezoomClick(self, clickState): self.dezoomButton.setEnabled(False) self.zoomButton.setEnabled(False) self.exportButton.setEnabled(False) self.zoom = False self.timeline.selDateMin = None self.timeline.selDateMax = None self.timeline.maxOccZoom = 0 self.newInformations() for family in self.configuration: for time in family[1]: if time[1][8][1]: time[1][8][1][0] = True time[1][8][1][1] = None self.timeline.updatePaintingArea() def exportClick(self, clickState): rect = self.timeline.ploter.selectionRect.rect() exportSelDateMin = self.timeline.draw.findXTime(rect.x()) exportSelDateMax = self.timeline.draw.findXTime(rect.x() + rect.width()) for family in self.configuration: for time in family[1]: if time[1][0][1]: nodes = [] everyNodes = self.timeline.elementsInRangeToNodeList(time[1][5][1], self.timeline.toUSec(exportSelDateMin), self.timeline.toUSec(exportSelDateMax)) for oneGroupNode in everyNodes: for node in oneGroupNode: nodes.append(node) if len(nodes): if not self.exportedNode: # Create /timeline if needed root = vfs.vfs().getnode('/Bookmarks') baseNode = Node('timeline', 0, root) baseNode.__disown__() baseNode.setDir() e = event() e.thisown = False e.value = RCVariant(Variant(baseNode)) self.VFS.notify(e) # Create /timeline/ self.exportedNode = Node(self.timeline.node.name(), 0, baseNode) self.exportedNode.__disown__() self.exportedNode.setDir() timeBaseName = self.exportedNode.absolute() + '/' + str(exportSelDateMin.strftime('%d.%m.%Y %H:%M:%S')) + ' to ' + str(exportSelDateMax.strftime('%d.%m.%Y %H:%M:%S')) timeBaseNode = vfs.vfs().getnode(timeBaseName) if not timeBaseNode: # Create /timeline//dateStart to dateEnd// timeBaseNode = Node(str(exportSelDateMin.strftime('%d.%m.%Y %H:%M:%S')) + ' to ' + str(exportSelDateMax.strftime('%d.%m.%Y %H:%M:%S')), 0, self.exportedNode) timeBaseNode.__disown__() timeBaseNode.setDir() baseFamilyName = timeBaseNode.absolute() + '/' + ':'.join([family[0]] + time[0]) baseFamilyNode = vfs.vfs().getnode(baseFamilyName) if not baseFamilyNode: # Create /timeline//dateStart to dateEnd// if needed baseFamilyNode = Node(':'.join([family[0]] + time[0]), 0, timeBaseNode) baseFamilyNode.__disown__() baseFamilyNode.setDir() for node in nodes: # Add each node in array as child l = VLink(node, baseFamilyNode) l.__disown__() dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/paint_area.py000066400000000000000000000117511217176075400233420ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # from datetime import timedelta from PyQt4.QtCore import Qt, QRectF from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QPen class PaintArea(QGraphicsView): def __init__(self, parent): QGraphicsView.__init__(self) self.init(parent) self.initShape() self.initCall = 2 self.minimumWidth = 550 self.setEnabled(False) def init(self, parent): self.timeline = parent self.pixmap = None self.image = None def initShape(self): self.scene = QGraphicsScene() self.setScene(self.scene) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) self.clicStart = None self.selectionRect = None def resizeEvent(self, sizEvent): if self.selectionRect and self.scene: self.scene.removeItem(self.selectionRect) self.selectionRect = None self.clicStart = None self.width = sizEvent.size().width() self.height = sizEvent.size().height() if self.initCall > 0: self.timeline.options.setMaximumWidth(self.timeline.options.minimumSizeHint().width()) self.initCall -= 1 if self.width < self.minimumWidth: self.timeline.setStateInfo('Unable to draw - Not enought width') else: self.timeline.workerThread.render() def mousePressEvent(self, mouseEvent): self.clicStart = mouseEvent.pos() if self.clicStart.x() < self.timeline.draw.yLeftMargin - 1: self.clicStart.setX(self.timeline.draw.yLeftMargin - 1) if self.clicStart.x() > self.timeline.ploter.width - self.timeline.m + 1: self.clicStart.setX(self.timeline.ploter.width - self.timeline.m + 1) if self.selectionRect: for item in self.scene.items(): if str(type(item)) == "": self.scene.removeItem(item) self.selectionRect = None self.timeline.options.zoomButton.setEnabled(False) self.timeline.options.exportButton.setEnabled(False) self.timeline.options.selectedNodes.setText('Nothing selected') if self.timeline.selDateMin: self.timeline.options.selStartTime.setText('From ' + str(self.timeline.fromUSec(self.timeline.baseDateMin).strftime('%d.%m.%Y %H:%M:%S'))) self.timeline.options.selEndTime.setText('To ' + str(self.timeline.fromUSec(self.timeline.baseDateMax).strftime('%d.%m.%Y %H:%M:%S'))) else: self.timeline.options.selStartTime.setText('No selection start time') self.timeline.options.selEndTime.setText('No selection end time') self.timeline.options.selectedNodes.setText('Nothing selected') def mouseMoveEvent(self, dragMoveEvent): if self.clicStart: if self.clicStart.x() < dragMoveEvent.x(): x = self.clicStart.x() w = dragMoveEvent.x() - self.clicStart.x() else: x = dragMoveEvent.x() w = self.clicStart.x() - dragMoveEvent.x() # Limit rectangle to selectable area if x < self.timeline.draw.yLeftMargin - 1: x = self.timeline.draw.yLeftMargin - 1 w = self.clicStart.x() - x if x > self.timeline.ploter.width - self.timeline.m + 1: x = self.timeline.ploter.width - self.timeline.m + 1 w = 0 if x + w > self.timeline.ploter.width - self.timeline.m + 1: w = ((self.timeline.ploter.width - self.timeline.m + 1) - x) y = (self.timeline.m / 3) - 1 h = self.height - self.timeline.m - self.timeline.m / 3 + 2 if self.selectionRect and self.scene: self.scene.removeItem(self.selectionRect) self.selectionRect = self.scene.addRect(QRectF(x, y, w, h), QPen(Qt.DashDotDotLine)) def mouseReleaseEvent(self, mouseEvent): if self.selectionRect: if self.clicStart.x() > mouseEvent.x(): x1 = mouseEvent.x() x2 = self.clicStart.x() else: x1 = self.clicStart.x() x2 = mouseEvent.x() self.timeline.nodesInRange(x1, x2) start = self.timeline.draw.findXTime(x1) if start: self.timeline.options.selStartTime.setText('From ' + str(start.strftime('%d.%m.%Y %H:%M:%S'))) end = self.timeline.draw.findXTime(x2) if end: self.timeline.options.selEndTime.setText('To ' + str(end.strftime('%d.%m.%Y %H:%M:%S'))) dff-1.3.0+dfsg.1/dff/modules/viewer/timeline/timeline.py000066400000000000000000000353031217176075400230440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # __dff_module_timeline_version__ = "1.0.0" from datetime import datetime, timedelta from PyQt4.QtCore import Qt, QPointF, QRectF, SIGNAL, QString from PyQt4.QtGui import QPixmap, QColor, QWidget, QVBoxLayout, QSplitter, QPainter from dff.api.vfs import vfs from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Argument, typeId from paint_area import PaintArea from options_layout import OptionsLayout from compute_thread import WorkerThread, CountThread, MaxOccThread from list_thread import DataThread from drawer import Drawer class Timeline(QWidget, Script): def __init__(self): Script.__init__(self, 'timeline') QWidget.__init__(self, None) self.type = 'timeline' self.nodeCount = 0 self.timesCount = 0 self.timeMap = {} self.m = 40 # Padding self.lineHeight = 4 # Pixel height of line self.metricOk = False self.colors = [['blue', Qt.blue], ['red', Qt.red], ['green', Qt.green], ['yellow', Qt.yellow], ['magenta', Qt.magenta], ['cyan', Qt.cyan]] self.stateinfo = 'Initialized' self.dateMin = long(0xffffffffffffffff) self.dateMax = long(0) self.baseDateMin = self.dateMin self.baseDateMax = self.dateMax self.selDateMin = None self.selDateMax = None self.maxOcc = 0 self.maxOccZoom = 0 self.xHop = 0 self.xRange = 0 self.dataListsCreated = False def start(self, args): self.node = args['file'].value() def status(self): return 0 def updateWidget(self): pass def g_display(self): self.name = 'timeline ' + QString(self.node.name()) if not self.node.hasChildren(): self.setStateInfo(self.node.absolute() + ' doesn\'t have any children.') else: self.vfs = vfs.vfs() self.vlayout = QVBoxLayout() self.vlayout.setMargin(0) self.vlayout.setSpacing(0) self.hsplitter = QSplitter() self.ploter = PaintArea(self) self.options = OptionsLayout(self) self.hsplitter.addWidget(self.ploter) self.hsplitter.addWidget(self.options) self.vlayout.addWidget(self.hsplitter) self.setLayout(self.vlayout) self.draw = Drawer(self) # CountThread compute node amount self.countThread = CountThread(self, self.countThreadOver) self.populateThread = DataThread(self, self.dataThreadOver) self.maxOccThread = MaxOccThread(self, self.maxOccThreadOver) self.workerThread = WorkerThread(self) #comment it to avoid redraw everytime painter is resized self.connect(self.workerThread, SIGNAL('refresh'), self.reDraw) def fromUSec(self, usec2): usec = int(usec2) days = usec / (86400 * 1000000) seconds = (usec - days * 86400 * 1000000) / 1000000 misec = usec - days * 86400 * 1000000 - seconds * 1000000 if days >= 1 and datetime.fromordinal(days) >= datetime.fromordinal(1): return datetime.fromordinal(days) + timedelta(seconds = seconds, microseconds = misec) return None def toUSec(self, dtime): return dtime.toordinal() * 86400 * 1000000 + dtime.hour * 3600 * 1000000 + dtime.minute * 60 * 1000000 + dtime.second * 1000000 + dtime.microsecond def dumpTimeMap(self): print self.timeMap for k in self.timeMap.keys(): print 'module:', k for attr in self.timeMap[k]: sAttrPath = '/' for v in attr[:-1]: sAttrPath += v + '/' print ' ', sAttrPath, ':', attr[-1] def countThreadOver(self): if not self.nodeCount: self.setStateInfo('No timestamp found any subset of ' + self.node.absolute()) # self.disconnect(self.workerThread, SIGNAL('refresh'), self.reDraw) return self.setStateInfo(str(self.nodeCount) + ' nodes found') # self.dumpTimeMap() # Find/virtual draw maximum size of Y text painter = QPainter() nullPixmap = QPixmap(self.ploter.width, self.ploter.height) painter.begin(nullPixmap) rect = painter.drawText(self.draw.paddingYText, 10, 0, 0, 0, str(self.nodeCount) + '.0') painter.end() self.draw.yLeftMargin = self.draw.paddingYText * 2 + rect.width() self.options.newInformations() self.options.createMetricTools() self.metricOk = True # self.createFullTimeLists() self.workerThread.render() def createFullTimeLists(self): self.populateThread = DataThread(self, self.dataThreadOver) self.populateThread.start() def dataThreadOver(self): self.dataListsCreated = True for family in self.options.configuration: # family[0] = extended|static|usual for time in family[1]: if time[1][5][1]: dateMin = time[1][6][1][0] dateMax = time[1][6][1][1] if dateMin != None and dateMin > 0 and dateMin < 18446744073709551615 and dateMin < self.baseDateMin: self.baseDateMin = dateMin if dateMax != None and dateMax > 0 and dateMax < 18446744073709551615 and dateMax > self.baseDateMax: self.baseDateMax = dateMax self.options.newInformations() self.workerThread.render() def findMaxValue(self): self.xRange = (self.ploter.width - self.m - self.draw.yLeftMargin) / self.lineHeight self.xHop = (self.baseDateMax - self.baseDateMin) / self.xRange def maxOccThreadOver(self): self.updatePaintingArea() def zoomMaxOcc(self): self.xRange = (self.ploter.width - self.m - self.draw.yLeftMargin) / self.lineHeight xHop = (self.selDateMax - self.selDateMin) / self.xRange newMaxOcc = 0 for family in self.options.configuration: for time in family[1]: timeChecked = self.selDateMin if timeChecked == self.selDateMax: # Every nodes have the same time, setting maxOcc computing time + 100usec occ = self.elementsInRange(time[1][5][1], timeChecked, timeChecked + 100) if occ > newMaxOcc: newMaxOcc = occ while timeChecked <= self.selDateMax: occ = self.elementsInRange(time[1][5][1], timeChecked, timeChecked + xHop) if occ > newMaxOcc: newMaxOcc = occ timeChecked += xHop self.maxOccZoom = newMaxOcc def reDraw(self, resized = False): if resized: self.updatePaintingArea(True) def updatePaintingArea(self, resized = False): if not self.maxOcc: return self.painter = QPainter() self.mainPixmap = QPixmap(self.ploter.width, self.ploter.height) self.mainPixmap.fill(Qt.white) self.gridPixmap = QPixmap(self.ploter.width, self.ploter.height) self.gridPixmap.fill(Qt.transparent) self.painter.begin(self.gridPixmap) if self.options.zoom and not self.maxOccZoom: self.zoomMaxOcc() self.draw.setDynamicValues(self) self.draw.drawInfos() self.draw.drawGrid() self.painter.end() for family in self.options.configuration: for time in family[1]: if resized: time[1][8][1][0] = True time[1][7][1][0] = True if self.options.zoom and time[1][8][1][0]: # Create zoom pixmaps time[1][8][1][1] = QPixmap(self.ploter.width, self.ploter.height) time[1][8][1][1].fill(Qt.transparent) penColor = None for color in self.colors: if color[0] == time[1][1][1]: penColor = QColor(color[1]) penColor.setAlpha(163) break if penColor: self.painter.begin(time[1][8][1][1]) pen = self.painter.pen() pen.setColor(penColor) pen.setWidth(self.lineHeight) self.painter.setPen(pen) self.draw.drawTimeline(self.painter, time[1][5][1]) self.painter.end() time[1][8][1][0] = False elif not time[1][7][1][1] or time[1][7][1][0]: # Create main (original sized) pixmaps time[1][7][1][1] = QPixmap(self.ploter.width, self.ploter.height) time[1][7][1][1].fill(Qt.transparent) penColor = None for color in self.colors: if color[0] == time[1][1][1]: penColor = QColor(color[1]) penColor.setAlpha(163) break if penColor: self.painter.begin(time[1][7][1][1]) pen = self.painter.pen() pen.setColor(penColor) pen.setWidth(self.lineHeight) self.painter.setPen(pen) self.draw.drawTimeline(self.painter, time[1][5][1]) self.painter.end() time[1][7][1][0] = False self.painter.begin(self.mainPixmap) # Draw grid self.painter.drawImage(QPointF(0, 0), self.gridPixmap.toImage(), QRectF(0, 0, self.ploter.width, self.ploter.height)) for family in self.options.configuration: for time in family[1]: # Draw each time pixmap if not self.options.zoom: # Draw global view, if zoom not enabled if time[1][7][1][1] and time[1][0][1]: self.painter.drawImage(QPointF(0, 0), time[1][7][1][1].toImage(), QRectF(0, 0, self.ploter.width, self.ploter.height)) else: # Draw zoom pixmaps if time[1][8][1][1] and time[1][0][1]: self.painter.drawImage(QPointF(0, 0), time[1][8][1][1].toImage(), QRectF(0, 0, self.ploter.width, self.ploter.height)) self.painter.end() self.ploter.scene.clear() self.ploter.scene.addPixmap(self.mainPixmap) self.ploter.setEnabled(True) self.update() def setStateInfo(self, sinfo): self.stateinfo = str(sinfo) def stateInfo(self): if self.nodeCount: return self.stateinfo + ' - ' + str(self.nodeCount) + ' nodes' else: return self.stateinfo def nodesInRange(self, x1, x2): if not self.selDateMin: timeCheck = self.baseDateMin timeMax = self.baseDateMax else: timeCheck = self.selDateMin timeMax = self.selDateMax count = 0 while timeCheck < timeMax: for family in self.options.configuration: for time in family[1]: occ = self.elementsInRange(time[1][5][1], timeCheck, timeCheck + self.xHop) if occ: if self.lineMatched(timeCheck, occ, x1, x2) and time[1][0][1]: count += occ timeCheck += self.xHop if count: self.options.zoomButton.setEnabled(True) self.options.exportButton.setEnabled(True) if count > 1: self.options.selectedNodes.setText(str(count) + ' time values selected') else: self.options.selectedNodes.setText('One time value selected') else: self.options.zoomButton.setEnabled(False) self.options.exportButton.setEnabled(False) self.options.selectedNodes.setText('Nothing selected') def lineMatched(self, usec, occ, x1, x2): if not self.selDateMin: dateMin = self.baseDateMin dateMax = self.baseDateMax else: dateMin = self.selDateMin dateMax = self.selDateMax if (dateMax - dateMin) > 0: x = ((usec - dateMin) * (self.ploter.width - self.m - self.draw.yLeftMargin)) / (dateMax - dateMin) + self.draw.yLeftMargin if x <= self.draw.yLeftMargin: x += 3 x_min = x - 2 x_max = x + 2 if x_min >= x1 and x_max <= x2: return True return False def elementsInRange(self, root, tMin, tMax): ''' Returns amount of node in a date range, given as long Dichotomic search, but this can be improved because we only search for smaller timestamp and decrease index if greather. ''' if not tMin or not tMax: return 0 nodesCount = 0 if root['dates'] == None: return 0 iMin, iMax = 0, len(root['dates']) - 1 iCurrent = iMax / 2 # Sync cursor in dates list on tMin ; should be improved while iMin != iMax or not iMax: if tMin >= root['dates'][iCurrent] or not iCurrent: while iCurrent and tMin >= root['dates'][iCurrent]: # Should be improved iCurrent -= 1 break elif tMin < root['dates'][iCurrent]: iMax = iCurrent iCurrent = iMin + ((iCurrent - iMin) / 2) # Count amount of nodes between tMin and tMax endOfList = len(root['dates']) while iCurrent < endOfList and tMax >= root['dates'][iCurrent]: if tMin <= root['dates'][iCurrent]: nodesCount += len(root['nodes'][iCurrent]) iCurrent += 1 return nodesCount def elementsInRangeToNodeList(self, root, tMin, tMax): ''' Returns a list of nodes pointer, made of nodes in given date range. Dichotomic search, but this can be improved because we only search for smaller timestamp and decrease index if greather. ''' if not tMin or not tMax: return 0 nodesList = [] iMin, iMax = 0, len(root['dates']) - 1 iCurrent = iMax / 2 # Sync cursor in dates list on tMin ; should be improved while iMin != iMax or not iMax: if tMin >= root['dates'][iCurrent] or not iCurrent: while iCurrent and tMin >= root['dates'][iCurrent]: # Should be improved iCurrent -= 1 break elif tMin < root['dates'][iCurrent]: iMax = iCurrent iCurrent = iMin + ((iCurrent - iMin) / 2) # Count amount of nodes between tMin and tMax endOfList = len(root['dates']) while iCurrent < endOfList and tMax >= root['dates'][iCurrent]: if tMin <= root['dates'][iCurrent]: nodesList.append(root['nodes'][iCurrent]) iCurrent += 1 return nodesList class timeline(Module): """ Fetch all timestamp from children of a node and create a nice view. """ def __init__(self): Module.__init__(self, 'timeline', Timeline) self.conf.addArgument({"name": "file", "description": "Text file to display", "input": Argument.Required|Argument.Single|typeId.Node}) self.tags = 'Statistics' self.icon = ":date" dff-1.3.0+dfsg.1/dff/modules/viewer/web/000077500000000000000000000000001217176075400176275ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/viewer/web/CMakeLists.txt000066400000000000000000000011201217176075400223610ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER install_file( __init__.py web.py ) dff-1.3.0+dfsg.1/dff/modules/viewer/web/__init__.py000066400000000000000000000010501217176075400217340ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER dff-1.3.0+dfsg.1/dff/modules/viewer/web/web.py000066400000000000000000000137171217176075400207670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER __dff_module_webview_version__ = "1.0.0" import re import base64 from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * from PyQt4.QtWebKit import * from dff.api.vfs import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import Argument, typeId class WebView(QWebView): def __init__(self, web): QWebView.__init__(self) self.web = web s = self.page().settings() s.setAttribute(s.JavascriptEnabled, False) s.setAttribute(s.PrivateBrowsingEnabled, True) self.page().setLinkDelegationPolicy(QWebPage.DelegateExternalLinks) def replaceImageElements(self): imgs = self.page().currentFrame().findAllElements("img") for img in imgs: url = img.attribute("src") encodedimg = self.encodeImage(self.getNodeFromURL(url, self.web.node)) if encodedimg: img.setAttribute("src", encodedimg) def encodeImage(self, node): if node: conv = '"data:' conv += node.dataType()["magic mime"].toString().split(';')[0] conv += ";base64," buff = "" vf = node.open() size = 0 while size < node.size(): buff += vf.read(1024*1024) size += len(buff) encoded = base64.encodestring(buff) conv += encoded conv += '"' vf.close() return conv else: return None def getNodeFromURL(self, url, relativenode): if self.checkURL(url): vfspath = relativenode.parent().absolute() + "/" + url node = self.web.vfs.getnode(str(vfspath)) if node: return node else: return None else: return None def checkURL(self, url): local = False if re.match('^http://', url): local = False elif re.match('^data:', url): local = False elif re.match('file://', url): local = False else: local = True return local def getCSSElements(self): elements = [] frame = self.page().currentFrame() styles = frame.findAllElements("style") links = frame.findAllElements("link") for s in styles: if s.attribute("type") == "text/css": elements.append(s) for l in links: if l.attribute("type") == "text/css": elements.append(l) return elements def replaceCSSElements(self, elements): for el in elements: if el.tagName() == "LINK": cssnode = self.getNodeFromURL(el.attribute("href"), self.web.node) if cssnode: ne = QWebElement() ne.setOuterXml("") ne.setPlainText(self.readImportCSS(cssnode)) el.replace(ne) elif el.tagName() == "STYLE": self.importCSS(el) def importCSS(self, style): if style: if re.match('^@import', style.toPlainText()): match = re.search('".*"', style.toPlainText()) path = style.toPlainText()[match.start() + 1 :match.end() - 1] cssnode = self.getNodeFromURL(path, self.web.node) if cssnode: style.setPlainText(self.readImportCSS(cssnode)) def readImportCSS(self, cssnode): cssfile = cssnode.open() ret = "" size = 0 while size < cssnode.size(): buff = cssfile.read(1024*1024) size += len(buff) if len(buff) == 0: break ret += self.detectUrlInCSS(buff, cssnode) cssfile.close() return QString(QByteArray(ret)) def detectUrlInCSS(self, buff, cssnode): urls = re.finditer('url\(.*\)', buff) matchs = {} ret = buff for url in urls: line = buff[url.start():url.end()] # 4 for len "url(" if line[4] in ('"', "'"): path = line[5:len(line)-2] else: path = line[4:len(line)-1] imgnode = self.getNodeFromURL(path, cssnode) if imgnode: encoded = "url(" encoded += self.encodeImage(imgnode) encoded += ")" l = line.replace('(', "\(") li = l.replace(')', "\)") ret = re.sub(li, encoded, ret) return ret class WEB(QWidget, Script): def __init__(self): Script.__init__(self, "web") self.vfs = vfs.vfs() self.type = "web" self.icon = None def start(self, args): self.args = args try: self.node = args["file"].value() except: pass def g_display(self): QWidget.__init__(self) self.vfile = self.node.open() self.initShape() size = 0 self.html = "" while size < self.node.size(): self.buff = self.vfile.read(1024*1024) size += len(self.buff) if len(self.buff) == 0: break self.html += self.buff self.webv.setContent(self.html) self.webv.replaceImageElements() self.webv.replaceCSSElements(self.webv.getCSSElements()) self.vfile.close() def updateWidget(self): pass def initShape(self): self.hbox = QHBoxLayout() self.hbox.setContentsMargins(0, 0, 0, 0) self.webv = WebView(self) self.hbox.addWidget(self.webv) self.setLayout(self.hbox) class web(Module): """Interpret Web pages""" def __init__(self): Module.__init__(self, "web", WEB) self.conf.addArgument({"name": "file", "description": "Web page", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["HTML"]}) self.tags = "Viewers" self.flags = ["gui"] self.icon = ":text" dff-1.3.0+dfsg.1/dff/modules/volumes/000077500000000000000000000000001217176075400172435ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/volumes/CMakeLists.txt000066400000000000000000000012001217176075400217740ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin add_subdirectory(partition) add_subdirectory(vmware) install_file( __init__.py ) dff-1.3.0+dfsg.1/dff/modules/volumes/__init__.py000077500000000000000000000011051217176075400213540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge __all__ = ['partition'] dff-1.3.0+dfsg.1/dff/modules/volumes/partition/000077500000000000000000000000001217176075400212545ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/volumes/partition/CMakeLists.txt000066400000000000000000000012561217176075400240200ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin dff_cpp_module(PARTITION CPP_FILES partition.cpp dos.cpp SWIG_FILE partition.i LINK_LIBRARIES exceptions types vfs tree ) dff-1.3.0+dfsg.1/dff/modules/volumes/partition/dos.cpp000066400000000000000000000500461217176075400225520ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "dos.hpp" #include #include #include #include char partition_types[256][128] = { "Empty", "DOS 12-bit FAT", "XENIX root", "XENIX /usr", "DOS 3.0+ 16-bit FAT (up to 32M)", "DOS 3.3+ Extended Partition", "DOS 3.31+ 16-bit FAT (over 32M)", "QNX2.x pre-1988", "QNX 1.x and 2.x (qny)", "QNX 1.x and 2.x (qnz)", "OPUS", "WIN95 OSR2 FAT32", "WIN95 OSR2 FAT32, LBA-mapped", "Unknown", "WIN95: DOS 16-bit FAT, LBA-mapped", "WIN95: Extended partition, LBA-mapped", "OPUS (?)", "Hidden DOS 12-bit FAT", "Configuration/diagnostics partition", "Unknown", "Hidden DOS 16-bit FAT <32M", "Unknown", "Hidden DOS 16-bit FAT >=32M", "Hidden IFS (e.g., HPFS)", "AST SmartSleep Partition", "Unused", "Unknown", "Hidden WIN95 OSR2 FAT32", "Hidden WIN95 OSR2 FAT32, LBA-mapped", "Unknown", "Hidden WIN95 16-bit FAT, LBA-mapped", "Unknown", "Unused", "Unused", "Unused", "Reserved", "NEC DOS 3.x", "Unknown", "Reserved", "RouterBOOT kernel partition", "Unknown", "Unknown", "AtheOS File System (AFS)", "SyllableSecure (SylStor)", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Reserved", "NOS", "Reserved", "Reserved", "JFS on OS/2 or eCS", "Reserved", "Unknown", "THEOS ver 3.2 2gb partition", "THEOS ver 4 spanned partition", "THEOS ver 4 4gb partition", "THEOS ver 4 extended partition", "PartitionMagic recovery partition", "Hidden NetWare", "Unknown", "Unknown", "PICK", "PPC PReP (Power PC Reference Platform) Boot", "Windows 2000 dynamic extended partition marker", "Linux native (sharing disk with DRDOS)", "GoBack partition", "EUMEL/Elan", "EUMEL/Elan", "EUMEL/Elan", "EUMEL/Elan", "Unknown", "AdaOS Aquila (Withdrawn)", "Unknown", "Oberon partition", "QNX4.x", "QNX4.x 2nd part", "Oberon partition", "Native Oberon (alt)", "Novell", "Microport SysV/AT", "Disk Manager 6.0 Aux3", "Disk Manager 6.0 Dynamic Drive Overlay (DDO)", "EZ-Drive", "DM converted to EZ-BIOS", "VNDI Partition", "Unknown", "Unknown", "Unknown", "Unknown", "Priam EDisk", "Unknown", "Unknown", "Unknown", "Unknown", "SpeedStor", "Unknown", "Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd", "Novell Netware 286, 2.xx", "Novell Netware 386, 3.xx or 4.xx", "Novell Netware SMS Partition", "Novell", "Novell", "Novell Netware 5+, Novell Netware NSS Partition", "Unknown", "Unknown", "Unknown", "Unknown", "??", "Unknown", "DiskSecure Multi-Boot", "Reserved", "V7/x86", "Reserved", "Scramdisk partition", "IBM PC/IX", "Reserved", "VNDI Partition", "XOSL FS", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unused", "Unused", "MINIX until 1.4a", "Mitac disk manager", "Linux swap", "Linux native partition", "Hibernation partition", "Linux extended partition", "FAT16 volume set", "NTFS volume set", "Linux plaintext partition table", "Unknown", "Linux Kernel Partition (used by AiR-BOOT)", "Legacy Fault Tolerant FAT32 volume", "Legacy Fault Tolerant FAT32 volume using BIOS extd INT 13h", "Free FDISK 0.96+ hidden Primary DOS FAT12 partitition", "Linux Logical Volume Manager partition", "Unknown", "Free FDISK 0.96+ hidden Primary DOS FAT16 partitition", "Free FDISK 0.96+ hidden DOS extended partitition", "Free FDISK 0.96+ hidden Primary DOS large FAT16 partitition", "Amoeba", "Amoeba bad block table", "MIT EXOPC native partitions", "CHRP ISO-9660 filesystem", "Free FDISK 0.96+ hidden Primary DOS FAT32 partitition", "Datalight ROM-DOS Super-Boot Partition", "DCE376 logical drive", "Free FDISK 0.96+ hidden Primary DOS FAT16 partitition (LBA)", "Free FDISK 0.96+ hidden DOS extended partitition (LBA)", "Unknown", "Unknown", "ForthOS partition", "BSD/OS", "Laptop hibernation partition", "HP Volume Expansion (SpeedStor variant)", "Unknown", "HP Volume Expansion (SpeedStor variant)", "HP Volume Expansion (SpeedStor variant)", "BSD/386, 386BSD, NetBSD, FreeBSD", "HP Volume Expansion (SpeedStor variant)", "NeXTStep", "Mac OS-X", "NetBSD", "Olivetti Fat 12 1.44MB Service Partition", "GO! partition", "Unknown", "Unknown", "ShagOS filesystem", "MacOS X HFS", "BootStar Dummy", "QNX Neutrino Power-Safe filesystem", "QNX Neutrino Power-Safe filesystem", "QNX Neutrino Power-Safe filesystem", "HP Volume Expansion (SpeedStor variant)", "Unknown", "Corrupted Windows NT mirror set (master), FAT16 file system", "BSDI BSD/386 filesystem", "BSDI BSD/386 swap partition", "Unknown", "Unknown", "Boot Wizard hidden", "Acronis backup partition", "Unknown", "Solaris 8 boot partition", "New Solaris x86 partition", "DR-DOS/Novell DOS secured partition", "DRDOS/secured (FAT-12)", "Hidden Linux", "Hidden Linux swap", "DRDOS/secured (FAT-16, < 32M)", "DRDOS/secured (extended)", "Windows NT corrupted FAT16 volume/stripe set", "Syrinx boot", "Reserved for DR-DOS 8.0+", "Reserved for DR-DOS 8.0+", "Reserved for DR-DOS 8.0+", "DR-DOS 7.04+ secured FAT32 (CHS)/", "DR-DOS 7.04+ secured FAT32 (LBA)/", "CTOS Memdump?", "DR-DOS 7.04+ FAT16X (LBA)/", "DR-DOS 7.04+ secured EXT DOS (LBA)/", "Multiuser DOS secured partition", "Old Multiuser DOS secured FAT12", "Unknown", "Unknown", "Old Multiuser DOS secured FAT16 <32M", "Old Multiuser DOS secured extended partition", "Old Multiuser DOS secured FAT16 >=32M", "Unknown", "CP/M-86", "Unknown", "Powercopy Backup", "KDG Telemetry SCPU boot", "Unknown", "Hidden CTOS Memdump?", "Dell PowerEdge Server utilities (FAT fs)", "BootIt EMBRM", "Unknown", "DOS access or SpeedStor 12-bit FAT extended partition", "Unknown", "DOS R/O or SpeedStor", "SpeedStor 16-bit FAT extended partition < 1024 cyl.", "Unknown", "Storage Dimensions SpeedStor", "Unknown", "LUKS", "Unknown", "Unknown", "BeOS BFS", "SkyOS SkyFS", "Unused", "Indication that this legacy MBR is followed by an EFI header", "Partition that contains an EFI file system", "Linux/PA-RISC boot loader", "Storage Dimensions SpeedStor", "DOS 3.3+ secondary partition", "Reserved", "Prologue single-volume partition", "Prologue multi-volume partition", "Storage Dimensions SpeedStor", "DDRdrive Solid State File System", "Unknown", "pCache", "Bochs", "VMware File System partition", "VMware Swap partition", "Linux raid partition with autodetect using persistent superblock", "Linux Logical Volume Manager partition (old)", "Xenix Bad Block Table" }; DosPartitionNode::DosPartitionNode(std::string name, uint64_t size, Node* parent, Partition* fsobj): Node(name, size, parent, fsobj) { } DosPartitionNode::~DosPartitionNode() { } Attributes DosPartitionNode::dataType() { Attributes dtype; Variant* vptr; if (this->__type == UNALLOCATED) { if ((vptr = new Variant(std::string("unallocated"))) != NULL) dtype["partition"] = Variant_p(vptr); return dtype; } else return Node::dataType(); } void DosPartitionNode::fileMapping(FileMapping* fm) { this->__handler->mapping(fm, this->__entry, this->__type); } Attributes DosPartitionNode::_attributes(void) { return this->__handler->entryAttributes(this->__entry, this->__type); } void DosPartitionNode::setCtx(DosPartition* handler, uint64_t entry, uint8_t type) { this->__handler = handler; this->__entry = entry; this->__type = type; } std::string DosPartitionNode::icon(void) { if (this->__type == UNALLOCATED) return (std::string(":disksfilesystemsdeleted")); else return (std::string(":disksfilesystems")); } /* * --------------------------------------------- * Starting implementation of DosPartition class * --------------------------------------------- */ DosPartition::DosPartition() { this->vfile = NULL; this->root = NULL; this->origin = NULL; this->__logical = 0; this->__primary = 0; this->__hidden = 0; this->__extended = 0; this->__slot = 1; } DosPartition::~DosPartition() { if (this->vfile != NULL) { try { this->vfile->close(); delete this->vfile; } catch(vfsError e) { throw vfsError("Partition error while closing file" + e.error); } } } void DosPartition::mapping(FileMapping* fm, uint64_t entry, uint8_t type) { metaiterator mit; uint64_t offset; uint64_t size; uint64_t tsize; bool process; process = false; if ((type == UNALLOCATED) && ((mit = this->unallocated.find(entry)) != this->unallocated.end())) { offset = this->offset + mit->first * this->sectsize; size = mit->second->entry_offset * this->sectsize; process = true; } else if ((type != UNALLOCATED) && ((mit = this->allocated.find(entry)) != this->allocated.end())) { offset = this->offset + mit->first * this->sectsize; size = (uint64_t)mit->second->pte->total_blocks * this->sectsize; process = true; } if (process) { //XXX NEED CASE DUMP if (offset > this->origin->size()) fm->push(0, size); //XXX NEED CASE DUMP else if (offset + size > this->origin->size()) { tsize = this->origin->size() - offset; fm->push(0, tsize, this->origin, offset); fm->push(tsize, tsize - size); } else fm->push(0, size, this->origin, offset); } } Attributes DosPartition::__entryAttributes(metaiterator mit) { Attributes vmap; std::stringstream ostr; if (mit->second->type == UNALLOCATED) { vmap["starting sector"] = new Variant(mit->first); vmap["ending sector"] = new Variant(mit->second->entry_offset - 1); vmap["total sectors"] = new Variant(mit->second->entry_offset - mit->first); ostr.str(""); ostr << "Unallocated #" << mit->second->sslot; vmap["entry type"] = new Variant(ostr.str()); } else { vmap["starting sector"] = new Variant(mit->first); vmap["ending sector"] = new Variant(mit->first + mit->second->pte->total_blocks - 1); vmap["total sectors"] = new Variant(mit->second->pte->total_blocks); if (mit->second->pte->status == 0x80) vmap["status"] = new Variant(std::string("bootable (0x80)")); else if (mit->second->pte->status == 0x00) vmap["status"] = new Variant(std::string("not bootable (0x00)")); else { ostr << "invalid (0x" << std::setw(2) << std::setfill('0') << std::hex << (int)mit->second->pte->status << ")"; vmap["status"] = new Variant(ostr.str()); ostr.str(""); } ostr.str(""); if ((mit->second->type & PRIMARY) == PRIMARY) ostr << "Primary #"; else if ((mit->second->type & LOGICAL) == LOGICAL) ostr << "Logical #"; else if ((mit->second->type & EXTENDED) == EXTENDED) ostr << "Extended #"; ostr << mit->second->sslot; if ((mit->second->type & HIDDEN) == HIDDEN) ostr << " | Hidden"; vmap["entry type"] = new Variant(ostr.str()); ostr.str(""); ostr << partition_types[mit->second->pte->type] << " (0x" << std::setw(2) << std::setfill('0') << std::hex << (int)mit->second->pte->type << ")"; vmap["partition type"] = new Variant(ostr.str()); vmap["entry offset"] = new Variant(mit->second->entry_offset); } return vmap; } Attributes DosPartition::entryAttributes(uint64_t entry, uint8_t type) { metaiterator mit; Attributes vmap; if ((type == UNALLOCATED) && ((mit = this->unallocated.find(entry)) != this->unallocated.end())) vmap = this->__entryAttributes(mit); else if ((type != UNALLOCATED) && ((mit = this->allocated.find(entry)) != this->allocated.end())) vmap = this->__entryAttributes(mit); return vmap; } void DosPartition::makeResults() { std::stringstream ostr; metaiterator mit; Attributes metares; Attributes rootext; Attributes unallocres; Variant* vptr; for (mit = this->allocated.begin(); mit != this->allocated.end(); mit++) { if ((mit->second->type & EXTENDED) == EXTENDED) { ostr.str(""); ostr << "Extended #" << mit->second->sslot; if (mit->second->sslot > 1) { if ((vptr = new Variant(this->__entryAttributes(mit))) != NULL) metares[ostr.str()] = Variant_p(vptr); } else rootext = this->__entryAttributes(mit); } else if ((mit->second->type & PRIMARY) == PRIMARY) { ostr.str(""); ostr << "Primary #" << mit->second->sslot << " (effective slot #" << mit->second->slot << ")"; if ((vptr = new Variant(this->__entryAttributes(mit))) != NULL) this->res[ostr.str()] = Variant_p(vptr); } else { ostr.str(""); ostr << "Logical #" << mit->second->sslot << " (effective slot #" << mit->second->slot << ")"; if ((vptr = new Variant(this->__entryAttributes(mit))) != NULL) rootext[ostr.str()] = Variant_p(vptr); } } for (mit = this->unallocated.begin(); mit != this->unallocated.end(); mit++) { ostr.str(""); ostr << "Unallocated #" << mit->second->sslot; if ((vptr = new Variant(this->__entryAttributes(mit))) != NULL) unallocres[ostr.str()] = Variant_p(vptr); } if (metares.size() && ((vptr = new Variant(metares)) != NULL)) this->res["Meta"] = Variant_p(vptr); if (unallocres.size() && ((vptr = new Variant(unallocres)) != NULL)) this->res["Unalloc"] = Variant_p(vptr); if (rootext.size() && ((vptr = new Variant(rootext)) != NULL)) this->res["Extended #1"] = Variant_p(vptr); } Attributes DosPartition::result() { return this->res; } void DosPartition::open(Node* origin, uint64_t offset, uint32_t sectsize, Partition* fsobj) throw (vfsError) { this->__slot = 1; this->__primary = 1; this->__hidden = 0; this->__logical = 1; this->__extended = 1; this->origin = origin; this->offset = offset; this->sectsize = sectsize; this->fsobj = fsobj; this->root = fsobj->root; this->vfile = this->origin->open(); try { this->readMbr(); } catch (vfsError err) { } this->makeUnallocated(); this->makeNodes(); this->makeResults(); } dos_pte* DosPartition::toPte(uint8_t* buff) { dos_pte* pte; uint32_t lba; uint32_t total_blocks; memcpy(&lba, buff+8, 4); memcpy(&total_blocks, buff+12, 4); //XXX try to used CHS instead ! Need geometry if ((lba == 0) && (total_blocks == 0)) return NULL; else { pte = new dos_pte; memcpy(pte, buff, 8); pte->lba = lba; pte->total_blocks = total_blocks; return pte; } } // std::cout << mit->first << " -- " << mit->first + mit->second->pte->total_blocks - 1 << " -- " << mit->second->pte->total_blocks // << " -- EXTENDED" << std::endl; void DosPartition::makeNodes() { std::stringstream ostr; metaiterator mit; DosPartitionNode* pnode; Node* root_unalloc; uint64_t size; if (this->allocated.size() > 0) { for (mit = this->allocated.begin(); mit != this->allocated.end(); mit++) { if ((mit->second->type & EXTENDED) != EXTENDED) { ostr << "Partition " << mit->second->slot; size = (uint64_t)mit->second->pte->total_blocks * this->sectsize; pnode = new DosPartitionNode(ostr.str(), size, this->root, this->fsobj); pnode->setCtx(this, mit->first, mit->second->type); ostr.str(""); // std::cout << mit->first << " -- " << mit->first + mit->second->pte->total_blocks - 1 << " -- " << mit->second->pte->total_blocks // << " -- " << partition_types[mit->second->pte->type] << std::endl; } } } if (this->unallocated.size() > 0) { root_unalloc = new Node("Unallocated", 0, this->root, this->fsobj); if (root_unalloc != NULL) { for (mit = this->unallocated.begin(); mit != this->unallocated.end(); mit++) { ostr << mit->first << "s--" << mit->second->entry_offset - 1 << "s"; size = (mit->second->entry_offset - mit->first) * this->sectsize; pnode = new DosPartitionNode(ostr.str(), size, root_unalloc, this->fsobj); pnode->setCtx(this, mit->first, UNALLOCATED); ostr.str(""); } //std::cout << mit->first << " -- " << mit->second->entry_offset - 1 << " -- " << mit->second->entry_offset - mit->first << " -- UNALLOCATED" << std::endl; } } } void DosPartition::makeUnallocated() { std::map::iterator mit; metadatum* meta; uint64_t sidx; uint32_t counter; sidx = 0; counter = 1; for (mit = this->allocated.begin(); mit != this->allocated.end(); mit++) { if ((mit->second->type & EXTENDED) != EXTENDED) { if (mit->first > sidx) { meta = new metadatum; meta->pte = NULL; meta->entry_offset = mit->first; meta->type = UNALLOCATED; meta->slot = (uint32_t)-1; meta->sslot = counter++; this->unallocated[sidx] = meta; } sidx = mit->first + mit->second->pte->total_blocks; } } if ((this->offset + (sidx * this->sectsize)) < this->origin->size()) { meta = new metadatum; meta->pte = NULL; meta->entry_offset = ((this->origin->size() - this->offset) / this->sectsize); meta->type = UNALLOCATED; meta->sslot = counter++; meta->slot = (uint32_t)-1; this->unallocated[sidx] = meta; } } void DosPartition::readMbr() throw (vfsError) { dos_partition_record record; uint8_t i; dos_pte* pte; uint32_t disk_sig; Attributes mbrattr; metadatum* meta; this->vfile->seek(this->offset); if (this->vfile->read(&record, sizeof(dos_partition_record)) > 0) { if (record.signature != 0xAA55) mbrattr["signature"] = new Variant(std::string("Not setted")); else mbrattr["signature"] = new Variant(record.signature); memcpy(&disk_sig, record.a.mbr.disk_signature, 4); mbrattr["disk signature"] = new Variant(disk_sig); this->res["mbr"] = new Variant(mbrattr); for (i = 0; i != 4; i++) { if ((pte = this->toPte(record.partitions+(i*16))) != NULL) { meta = new metadatum; meta->pte = pte; meta->entry_offset = this->offset + 446 + i * 16; if (IS_EXTENDED(pte->type)) { meta->slot = (uint32_t)-1; meta->sslot = this->__extended++; meta->type = EXTENDED; this->ebr_base = pte->lba; this->readEbr(pte->lba); } else { meta->slot = this->__slot++; meta->sslot = this->__primary++; meta->type = PRIMARY; } this->allocated[pte->lba] = meta; } } } } void DosPartition::readEbr(uint64_t csector, uint64_t shift) throw (vfsError) { dos_partition_record record; uint8_t i; dos_pte* pte; uint64_t offset; metadatum* meta; offset = this->offset + csector*this->sectsize; this->vfile->seek(offset); if (this->vfile->read(&record, sizeof(dos_partition_record)) > 0) { for (i = 0; i != 4; i++) { if ((pte = this->toPte(record.partitions+(i*16))) != NULL) { if (IS_EXTENDED(pte->type)) { if ((this->ebr_base + pte->lba) != csector) { meta = new metadatum; meta->pte = pte; meta->entry_offset = offset + 446 + i * 16; meta->slot = (uint32_t)-1; meta->sslot = this->__extended++; if (i > 2) { this->__hidden++; meta->type = EXTENDED|HIDDEN; } else meta->type = EXTENDED; this->allocated[this->ebr_base + pte->lba] = meta; this->readEbr(this->ebr_base + (uint64_t)(pte->lba), pte->lba); } else ; } else { meta = new metadatum; meta->pte = pte; meta->entry_offset = offset + 446 + i * 16; meta->slot = this->__slot++; meta->sslot = this->__logical++; if (i > 2) { this->__hidden++; meta->type = LOGICAL|HIDDEN; } else meta->type = LOGICAL; this->allocated[this->ebr_base + shift + pte->lba] = meta; } } } } } dff-1.3.0+dfsg.1/dff/modules/volumes/partition/dos.hpp000066400000000000000000000074711217176075400225630ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __DOS_HPP__ #define __DOS_HPP__ #include "exceptions.hpp" #include "vfile.hpp" #include "node.hpp" #include "partition.hpp" #include #include #define IS_EXTENDED(t) ((((t) == 0x05) || ((t) == 0x0F) || ((t) == 0x85)) ? 1 : 0) typedef struct { uint8_t status;//0x80 = bootable, 0x00 = non-bootable, other = invalid uint8_t start_head; uint8_t start_sector; //sector in bit 5-0, bits 9-8 of cylinders are in bits 7-6... uint8_t start_cylinder; // bits 7-0 uint8_t type; uint8_t end_head; uint8_t end_sector; //sector in bit 5-0, bits 9-8 of cylinders are in bits 7-6... uint8_t end_cylinder; //bits 7-0 uint32_t lba; uint32_t total_blocks; } dos_pte; // typedef struct // { // uint32_t start; // uint32_t end; // uint32_t meta; // } entry; /* "code" field is usually empty in extended boot record but could contain another boot loader or something volontary hidden... this field could also contain IBM Boot Manager starting at 0x18A. Normally, there are only two partition entries in extended boot records followed by 32 bytes of NULL bytes. It could be used to hide data or even 2 other partition entries. */ typedef struct { uint8_t code[440]; union { struct { uint8_t disk_signature[4]; uint8_t padding[2]; }mbr; struct { uint8_t code[6]; }ebr; } a; uint8_t partitions[64]; short signature; //0xAA55 } dos_partition_record; typedef struct { dos_pte* pte; uint64_t entry_offset; uint8_t type; uint32_t slot; uint32_t sslot; } metadatum; class DosPartition; class DosPartitionNode: public Node { private: uint64_t __entry; uint8_t __type; DosPartition* __handler; public: DosPartitionNode(std::string name, uint64_t size, Node* parent, class Partition* fsobj); ~DosPartitionNode(); void setCtx(DosPartition* handler, uint64_t entry, uint8_t type); virtual void fileMapping(FileMapping* fm); virtual Attributes _attributes(void); virtual Attributes dataType(); virtual std::string icon(); }; #define PRIMARY 0x01 #define EXTENDED 0x02 #define LOGICAL 0x04 #define HIDDEN 0x08 #define UNALLOCATED 0x10 typedef std::map metamap; typedef metamap::iterator metaiterator; class DosPartition { private: uint32_t __logical; uint32_t __primary; uint32_t __extended; uint32_t __hidden; uint32_t __slot; std::map allocated; std::map unallocated; Node* root; Node* origin; class Partition* fsobj; VFile* vfile; uint32_t sectsize; uint64_t offset; bool mbrBadMagic; uint64_t ebr_base; std::map res; dos_pte* toPte(uint8_t* buff); void makeNodes(); void makeUnallocated(); void makeResults(); Attributes __entryAttributes(metaiterator mit); public: DosPartition(); ~DosPartition(); Attributes result(); Attributes entryAttributes(uint64_t entry, uint8_t type); void mapping(FileMapping* fm, uint64_t entry, uint8_t type); void open(Node* origin, uint64_t offset, uint32_t sectsize, Partition* fsobj) throw (vfsError); void readEbr(uint64_t cur, uint64_t shift=0) throw (vfsError); void readMbr() throw (vfsError); }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/partition/partition.cpp000066400000000000000000000144501217176075400237750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "partition.hpp" // bool Partition::isExtended(char type) // { // char ext[] = "\x05\x0F\x85\x91\x9B\xD5"; // unsigned int i; // bool res; // res = false; // for (i = 0; ext[i]; i++) // if (ext[i] == type) // res = true; // return res; // } // Node *Partition::createPart(Node *parent, unsigned int sector_start, unsigned int size) // { // attrib *attr; // FileInfo *fi; // unsigned long long handle; // std::ostringstream os; // attr = new attrib; // fi = new FileInfo(); // fi->start = sector_start * 512; // fi->size = size * 512; // handle = this->filehandler->add(fi); // attr->size = fi->size; // attr->handle = new Handle(handle); // os << "Partition " << this->part_count; // this->part_count += 1; // return CreateNodeFile(parent, os.str(), attr); // } // string Partition::hexilify(char type) // { // std::ostringstream res; // res << std::hex << std::setiosflags(ios_base::showbase | ios_base::uppercase); // res << (int)type; // return res.str(); // } // void Partition::readExtended(Node *parent, unsigned int start, unsigned int next_lba) // { // ebr ebrEntry; // unsigned long long startOffset; // unsigned long long endOffset; // unsigned int i; // bool jumped; // partition_entry *part; // startOffset = start + next_lba; // this->Seek(startOffset * 512); // memset(&ebrEntry, 0, sizeof(ebr)); // if (this->Read(&ebrEntry, sizeof(ebr)) != 0) // { // jumped = false; // part = (partition_entry*)malloc(sizeof(partition_entry)); // for (i = 0; i != 4; i++) // { // if (ebrEntry.part[i].type != 0) // { // memcpy(part, &(ebrEntry.part[i]), sizeof(partition_entry)); // if (((i < 2) && jumped) || (i >= 2)) // this->Result << "Hidden partition !!!" << endl; // if (isExtended(part->type)) // this->readExtended(parent, start, part->lba); // else // { // this->Result << " +- Partition " << this->part_count << endl; // this->Result << " |-- type : " << this->hexilify(part->type) << endl; // this->Result << " |-- start : " << part->lba + startOffset << endl; // this->Result << " |-- end : " << part->lba - 1 + part->total_blocks << endl; // this->Result << " |-- size : " << part->total_blocks << endl; // this->createPart(parent, part->lba + startOffset, part->total_blocks); // } // } // else if (i < 2) // jumped = true; // } // } // } //Only checking the type is not enough !!! //anybody could set type to 0 to fake partition manager... // void Partition::readMbr() // { // unsigned int i; // partition_entry *part; // bool jumped; // Node *node; // memset(&mbrEntry, 0, sizeof(mbr)); // if (this->Read(&mbrEntry, sizeof(mbr)) != 0) // { // jumped = false; // part = (partition_entry*)malloc(sizeof(partition_entry)); // for (i = 0; i != 4; i++) // { // if (mbrEntry.part[i].type != 0) // { // if (jumped) // this->Result << "Hidden primary partition entry" << endl; // memcpy(part, &(mbrEntry.part[i]), sizeof(partition_entry)); // if (this->isExtended(part->type)) // { // this->Result << "+- Partition " << this->part_count << " (extended)" << endl; // this->Result << " |-- type : " << this->hexilify(part->type) << endl; // this->Result << " |-- start : " << part->lba << endl; // this->Result << " |-- end : " << part->lba - 1 + part->total_blocks << endl; // this->Result << " |-- size : " << part->total_blocks << endl; // node = this->createPart(this->ParentNode, part->lba, part->total_blocks); // this->readExtended(node, part->lba, 0); // } // else // { // this->Result << "+- Partition " << this->part_count << " (primary)" << endl; // this->Result << " |-- type : " << this->hexilify(part->type) << endl; // this->Result << " |-- start : " << part->lba << endl; // this->Result << " |-- end : " << part->lba - 1 + part->total_blocks << endl; // this->Result << " |-- size : " << part->total_blocks << endl; // this->createPart(this->ParentNode, part->lba, part->total_blocks); // } // } // else // jumped = true; // } // free(part); // } // } void Partition::start(std::map args) { std::map::iterator it; uint32_t sectsize; uint64_t soffset; if ((it = args.find("sector-size")) != args.end()) sectsize = it->second->value(); else sectsize = 512; if ((it = args.find("offset")) != args.end()) soffset = it->second->value(); else soffset = 0; if ((it = args.find("file")) != args.end()) { try { this->parent = it->second->value(); if (this->parent->size() != 0) { this->root = new PartitionsNode(this); this->dos->open(this->parent, soffset, sectsize, this); this->registerTree(this->parent, this->root); this->res = this->dos->result(); } } catch(vfsError e) { delete this->root; throw vfsError("[PARTITION] error while processing file\n" + e.error); } } else throw envError("[PARTITION] file argument not provided\n"); } // int Partition::SetResult() // { // return (0); // } Partition::Partition(): mfso("partition") { this->dos = new DosPartition(); } Partition::~Partition() { //Free All Memory !!! std::cout << "Dump Closed successfully" << std::endl; } PartitionsNode::PartitionsNode(mfso* fsobj) : Node("Partitions", 0, NULL, fsobj) { } PartitionsNode::~PartitionsNode() { } std::string PartitionsNode::icon() { return std::string(":database"); } dff-1.3.0+dfsg.1/dff/modules/volumes/partition/partition.hpp000066400000000000000000000027171217176075400240050ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #ifndef __PARTITION_HPP__ #define __PARTITION_HPP__ #include #include "variant.hpp" #include "mfso.hpp" #include "vfile.hpp" #include "dos.hpp" #include #include #include class Partition : public mfso { private: std::ostringstream Result; Node *parent; class DosPartition* dos; // int SetResult(); // int getParts(); // Node *createPart(Node *parent, unsigned int sector_start, unsigned int size); // void readMbr(); // void readExtended(Node *parent, unsigned int start, unsigned int next_lba); // bool isExtended(char type); // string hexilify(char type); public: Partition(); ~Partition(); Node *root; virtual void start(std::map args); }; class PartitionsNode : public Node { public: PartitionsNode(mfso* fsobj); ~PartitionsNode(); virtual std::string icon(); }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/partition/partition.i000066400000000000000000000043731217176075400234460ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Frederic Baguelin */ #include "pyrun.swg" %module PARTITION %include "std_list.i" %include "std_map.i" %include "windows.i" %{ #include "node.hpp" #include "vlink.hpp" #include "variant.hpp" #include "vtime.hpp" #include "export.hpp" #include "partition.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "partition.hpp" %pythoncode %{ __dff_module_partition_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId, Parameter class PARTITION(Module): """Reconstruct partitions found in a volume""" def __init__(self): Module.__init__(self, 'partition', Partition) self.conf.addArgument({"name": "file", "description": "file containing one or more partition(s)", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "sector-size", "description": "The size, in bytes, of the underlying device sectors (default is 512)", "input": Argument.Optional|Argument.Single|typeId.UInt32, "parameters": {"type": Parameter.Editable, "predefined": [512, 4096]} }) self.conf.addArgument({"name": "offset", "description": "offset where the volume containing the partition system starts", "input": Argument.Optional|Argument.Single|typeId.UInt64}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["partition"]}) self.tags = "Volumes" self.icon = ":disksfilesystems" %} dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/000077500000000000000000000000001217176075400205445ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/CMakeLists.txt000066400000000000000000000013121217176075400233010ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER dff_cpp_module(VMWARE CPP_FILES vmware.cpp diskDescriptor.cpp extent.cpp link.cpp vmnode.cpp SWIG_FILE vmware.i LINK_LIBRARIES exceptions types vfs tree ) dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/diskDescriptor.cpp000066400000000000000000000130161217176075400242420ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #include "diskDescriptor.hpp" #include "vmdk.hpp" diskDescriptor::diskDescriptor(Node *nodeDesc, int type) { this->_nodeDesc = nodeDesc; this->_type = type; if (type == 0) this->readDiskDescriptor(this->_nodeDesc, 0, this->_nodeDesc->size()); else this->readMonoDiskDescriptor(this->_nodeDesc); this->getLinesDiskDescriptor(this->_data); this->parseLineDiskDescriptor(); this->createExtentNames(); this->setParentFileName(); this->setCID(); this->setPCID(); } diskDescriptor::~diskDescriptor() { } void diskDescriptor::readDiskDescriptor(Node *nodeDesc, unsigned int offset, unsigned int size) { VFile *vmdk = nodeDesc->open(); this->_data = (char*)malloc(size); if (this->_data != NULL) { memset(this->_data, '\0', size); // Read descriptor try { vmdk->seek(offset); vmdk->read(this->_data, size - 1); } catch (envError & e) { vmdk->close(); std::cerr << "Error reading vmdk descriptor : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } } vmdk->close(); } void diskDescriptor::readMonoDiskDescriptor(Node *nodeDesc) { sparseExtentHeader header; VFile *vfile = nodeDesc->open(); try { vfile->seek(0); vfile->read(&header, sizeof(SparseExtentHeader)); } catch (envError & e) { std::cerr << "Error reading vmdk descriptor : arg->get(\"parent\", &_node) failed." << std::endl; vfile->close(); throw e; } vfile->close(); uint32_t descoffset = (header.descriptorOffset * SECTOR_SIZE); uint32_t descsize = (header.descriptorSize * SECTOR_SIZE); this->readDiskDescriptor(nodeDesc, descoffset, descsize); } void diskDescriptor::parseLineDiskDescriptor() { std::list::iterator i; unsigned int cp = 0; unsigned int len; // Is Key Value structure bool isKV = false; // Is Extent structure : 'R'W SPARSE .... bool isEX = false; for (i = this->_lines.begin(); i != this->_lines.end(); i++) { char* pTmp = *i; isKV = false; isEX = false; // clean start of key's line while (*pTmp == ' ' || *pTmp == '\t') pTmp++; char *pStart = pTmp; cp = 0; // If start is R, think that is an extent line if (*pTmp == 'R') isEX = true; // Get key len len = strlen(*i); while (cp != len) { if (*pTmp == '=') { isKV = true; break; } pTmp++; cp++; } // If = is detected if (isKV) { char* key = (char*)malloc(cp + 1); memset(key, '\0', cp + 1); memcpy(key, pStart, cp); // clean start of value's line ( = and others) pTmp++; while (*pTmp == ' ' || *pTmp == '\t') { cp++; pTmp++; } int vsize = len - cp; char* value = (char*)malloc(vsize + 1); memset(value, '\0', vsize + 1); memcpy(value, pTmp, vsize); // create KV string and clean it std::string skey = key; std::string::iterator kend_pos = std::remove(skey.begin(), skey.end(), ' '); skey.erase(kend_pos, skey.end()); std::string svalue = value; std::string::iterator vend_pos = std::remove(svalue.begin(), svalue.end(), '"'); svalue.erase(vend_pos, svalue.end()); this->_map.insert(std::pair(skey, svalue)); } //if = is not detected and line start with 'R' else if (!isKV && isEX) { char* extent = (char*)malloc(cp + 1); memset(extent, '\0', cp + 1); memcpy(extent, pStart, cp); std::string sextent = extent; this->_extents.push_back(sextent); } } } void diskDescriptor::getLinesDiskDescriptor(char *descData) { char* pTmp = descData; int llen = 0; while (*pTmp != '\0') { char *pStart = pTmp; // get Line length while (*pTmp != '\n' && *pTmp != '\0') { pTmp++; llen++; } char* line = (char*)malloc(llen +1); memset(line, '\0', llen + 1); memcpy(line, pStart, llen); this->_lines.push_back(line); if (*pTmp != '\0') { llen = 0; pTmp++; } } } std::string diskDescriptor::parseExtentName(std::string str) { std::string res = str; size_t found; found = res.find("\""); res.erase(0,found + 1); res.erase(res.size() - 1,1); return res; } int diskDescriptor::createExtentNames() { for( std::list::iterator ext=this->_extents.begin(); ext!=this->_extents.end(); ++ext) { std::string extname = parseExtentName((*ext)); this->_extNames.push_back(extname); } return (0); } void diskDescriptor::setParentFileName() { this->_parentFileName = this->_map[PARENT_FILE_NAME]; } void diskDescriptor::setCID() { this->_CID = this->_map[CID]; } void diskDescriptor::setPCID() { this->_PCID = this->_map[PCID]; } std::string diskDescriptor::parentFileName() { return this->_parentFileName; } std::string diskDescriptor::getCID() { return this->_CID; } std::string diskDescriptor::getPCID() { return this->_PCID; } std::list diskDescriptor::getExtentNames() { return this->_extNames; } dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/diskDescriptor.hpp000066400000000000000000000040241217176075400242460ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #ifndef __DISKDESCRIPTOR_HPP__ #define __DISKDESCRIPTOR_HPP__ #include // remove function in string operations #include #include #include #include #include #include "node.hpp" #define CID "CID" #define PCID "parentCID" #define PARENT_FILE_NAME "parentFileNameHint" #define CID_NOPARENT "ffffffff" class diskDescriptor { public: // type: 0=Sparse 2Gb extent text descriptor, 1=descriptor embeded into extent diskDescriptor(Node *nodeDesc, int type); ~diskDescriptor(); /* Read disk descriptor from and fill _descData buffer*/ void readDiskDescriptor(Node *nodeDesc, uint32_t offset, uint32_t size); void readMonoDiskDescriptor(Node *nodeDesc); /* Split _descData into lines*/ void getLinesDiskDescriptor(char *descData); /* Fill _descMap (all key=value system) and _descExtents */ void parseLineDiskDescriptor(); std::string parseExtentName(std::string str); int createExtentNames(); std::list getExtentNames(); void setParentFileName(); void setCID(); void setPCID(); std::string parentFileName(); std::string getCID(); std::string getPCID(); private: Node *_nodeDesc; int _type; // Text Disk Description char* _data; std::list _lines; std::list _extents; std::list _extNames; std::map _map; std::string _CID; std::string _PCID; std::string _parentFileName; }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/extent.cpp000066400000000000000000000070741217176075400225670ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #include "extent.hpp" Extent::Extent(Node *nd, uint32_t id) { this->vmdk = nd; this->id = id; this->vfile = this->vmdk->open(); this->readSparseHeader(); } Extent::~Extent() { } int Extent::readSparseHeader() { sparseExtentHeader header; /** Read VMDK _Header **/ try { this->vfile->seek(0); this->vfile->read(&header, sizeof(SparseExtentHeader)); } catch (envError & e) { std::cerr << "Error reading _Header : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } if ((header.magicNumber == VMDK_SPARSE_MAGICNUMBER) && (header.version == 1)) { // printf("VMDK header founded, version: %x\n",header.version); this->header = header; // this->id = header.id; this->version = header.version; //xxx this->type = HOST_SPARSE; //xxx this->sectors = header.capacity; this->sectorsPerGrain = header.grainSize; this->sectorGD = header.GDOffset; this->sectorRGD = header.RGDOffset; this->overheadSectors = header.overHead; this->descriptorSector = header.descriptorOffset; this->descriptorSize = header.descriptorSize; this->GTEntries = header.GTEsPerGT; //calculate unsigned int sPerGDE = (header.GTEsPerGT * header.grainSize); unsigned int GDEs = (header.capacity + (sPerGDE -1)) / sPerGDE; this->sectorsPerGDE = sPerGDE; this->GDEntries = GDEs; return 1; } return 0; } int Extent::createBackupHeader(int type) { unsigned int GTentry; printf("Reconstruct Extent\n"); // this->id = _extents.size(); this->version = 1; this->type = HOST_SPARSE; this->sectorsPerGrain = GRAIN_SIZE; if (type == 0) { this->sectorGD = GDSTART_MONO; this->sectorRGD = GDSTART_MONO; } else { this->sectorGD = GDSTART_TWO; this->sectorRGD = GDSTART_TWO; } // extent->overheadSectors = header.overHead; this->GTEntries = GTE_PER_GT; //calculate unsigned int sPerGDE = (GTE_PER_GT * GRAIN_SIZE); this->sectorsPerGDE = sPerGDE; try { if (type == 0) vfile->seek(GDSTART_MONO * SECTOR_SIZE); else vfile->seek(GDSTART_TWO * SECTOR_SIZE); vfile->read(>entry, sizeof(unsigned int)); } catch (envError & e) { std::cerr << "Error reading entry : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } //capacity = ((First GT offset - GD offset) / 4) * (GRAIN_SIZE * SECTOR_SIZE) if (type == 0) this->sectors = (((GTentry * SECTOR_SIZE) - (GDSTART_MONO * SECTOR_SIZE)) / 4) * (GRAIN_SIZE * SECTOR_SIZE); else this->sectors = (((GTentry * SECTOR_SIZE) - (GDSTART_TWO * SECTOR_SIZE)) / 4) * (GRAIN_SIZE * SECTOR_SIZE); // printf("gt entry offset: %x\n", GTentry * SECTOR_SIZE); // printf("gd start offset: %x\n", GDSTART_MONO * SECTOR_SIZE); // printf("extent sectors : %llx\n", this->sectors); unsigned int GDEs = (this->sectors + (sPerGDE -1)) / sPerGDE; this->GDEntries = GDEs; return 0; } dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/extent.hpp000066400000000000000000000023011217176075400225600ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #ifndef __EXTENT_HPP__ #define __EXTENT_HPP__ #include "vmdk.hpp" #include "node.hpp" class Extent { public: Extent(Node *nd, uint32_t id); ~Extent(); int readSparseHeader(); int createBackupHeader(int type); sparseExtentHeader header; Node *vmdk; VFile *vfile; uint32_t id; uint32_t version; uint32_t type; uint32_t sectorsPerGDE; uint32_t GDEntries; uint32_t GTEntries; uint64_t sectors; uint64_t sectorsPerGrain; uint64_t sectorGD; uint64_t sectorRGD; uint64_t overheadSectors; uint64_t descriptorSector; uint64_t descriptorSize; bool footer; uint16_t compression; }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/link.cpp000066400000000000000000000043761217176075400222170ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #include "link.hpp" Link::Link(diskDescriptor *desc, int type, Node *vmdkroot) { this->_descriptor = desc; this->_type = type; this->_vmdkroot = vmdkroot; this->_cid = this->_descriptor->getCID(); this->_pcid = this->_descriptor->getPCID(); if (this->_pcid == CID_NOPARENT) { this->_baseLink = true; } else this->_baseLink = false; } Link::~Link() { } void Link::setLinkStorageVolumeSize() { this->_storageVolumeSize = 0; for( std::vector::iterator ext=this->_extents.begin(); ext!=this->_extents.end(); ++ext) { this->_storageVolumeSize += ((*ext)->sectors * SECTOR_SIZE); } } int Link::listExtents() { std::list extnames; extnames = this->_descriptor->getExtentNames(); Node *parent = this->_vmdkroot->parent(); std::vectornext = parent->children(); for( std::list::iterator name=extnames.begin(); name!=extnames.end(); ++name) { for( std::vector::iterator in=next.begin(); in!=next.end(); ++in) { if ((*name) == (*in)->name()) { addExtent((*in)); } } } if (this->_extents.size() == extnames.size()) { this->setLinkStorageVolumeSize(); return 1; } else return -1; } int Link::addExtent(Node *vmdk) { uint32_t id; id = this->_extents.size(); Extent *ext = new Extent(vmdk, id); this->_extents.push_back(ext); return 1; } bool Link::isBase() { return this->_baseLink; } uint64_t Link::volumeSize() { return this->_storageVolumeSize; } std::string Link::getCID() { return this->_cid; } std::string Link::getPCID() { return this->_pcid; } std::vector Link::getExtents() { return this->_extents; } dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/link.hpp000066400000000000000000000025021217176075400222110ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #ifndef __LINK_HPP__ #define __LINK_HPP__ #include "vmdk.hpp" #include "extent.hpp" #include "diskDescriptor.hpp" class Link { public: Link(diskDescriptor *desc, int type, Node *vmdkroot); ~Link(); int listExtents(); // int readSparseHeader(extentInfo *extent); int addExtent(Node *vmdk); bool isBase(); uint64_t volumeSize(); std::vector getExtents(); std::string getCID(); std::string getPCID(); void setLinkStorageVolumeSize(); // int createBackupHeader(int type, extentInfo *extent); private: int _type; uint64_t _storageVolumeSize; Node *_vmdkroot; diskDescriptor *_descriptor; std::string _cid; std::string _pcid; bool _baseLink; std::vector _extents; }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/vmdk.hpp000066400000000000000000000067651217176075400222340ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #ifndef __VMDK_HPP__ #define __VMDK_HPP__ #include #include #include "node.hpp" #include "vfile.hpp" #define VMDK_DISK_DESCRIPTOR 0x69442023 /*"# Di" */ #define VMDK_SPARSE_MAGICNUMBER 0x564d444b /*"VMDK" */ #define VMDK_ESX_SPARSE_MAGICNUMBER 0x44574f43 /* "COWD" */ // Create Type definitions #define CTYPE_MONO_SPARSE "monolithicSparse" #define CTYPE_MONO_FLAT "monolithicFlat" #define CTYPE_EXTENT_SPARSE "twoGbMaxExtentSparse" #define CTYPE_EXTENT_FLAT "twoGbMaxExtentFlat" // Terms that include vmfs indicate that the disk is an ESX Server disk #define CTYPE_VMFS "vmfs" #define CTYPE_VMFS_RAWDEVICEMAP "vmfsRawDeviceMap" #define CTYPE_VMFS_PASSTHROUGT "vmfsPassthroughRawDeviceMap" #define CTYPE_VMFS_SPARSE "vmfsSparse" //The terms fullDevice, vmfsRaw, and partitionedDevice are used //when the virtual machine is configured to make direct use of a physical disk #define CTYPE_FULL "fullDevice" #define CTYPE_PARTITION "partitionedDevice" #define CTYPE_VMFS_RAW "vmfsRaw" // Optimized for stream #define CTYPE_STREAM "streamOptimized" #define SECTOR_SIZE 0x200 #define GDSTART_MONO 0x15 #define GDSTART_TWO 0x1 #define GRAIN_SIZE 0x80 #define GTE_PER_GT 0x200 #pragma pack(1) typedef struct sparseExtentHeader { uint32_t magicNumber; uint32_t version; uint32_t flags; uint64_t capacity; uint64_t grainSize; uint64_t descriptorOffset; uint64_t descriptorSize; uint32_t GTEsPerGT; uint64_t RGDOffset; uint64_t GDOffset; uint64_t overHead; bool uncleanShutdown; char singleEndLineChar; char nonEndLineChar; char doubleEndLineChar1; char doubleEndLineChar2; uint16_t compressAlgorithm; uint8_t pad[433]; } SparseExtentHeader; #pragma pack() #pragma pack(1) typedef struct COWDisk_Header { uint32_t magicNumber; uint32_t version; uint32_t flags; uint32_t numSectors; uint32_t grainSize; uint32_t gdOffset; uint32_t numGDEntries; uint32_t freeSector; /* The spec incompletely documents quite a few further fields, but states * that they are unused by the current format. Replace them by padding. */ char reserved1[1604]; uint32_t savedGeneration; char reserved2[8]; int32_t uncleanShutdown; char padding[396]; } COWDisk_Header; #pragma pack() typedef enum vmdktype { HOST_SPARSE = 1, FLAT, ZERO, VMFS, ESX_SPARSE }vmdktype; typedef struct extentInfo { sparseExtentHeader header; unsigned int id; unsigned int version; vmdktype type; Node *node; VFile *vfile; uint64_t sectors; uint64_t sectorsPerGrain; uint64_t sectorGD; uint64_t sectorRGD; uint64_t overheadSectors; unsigned int sectorsPerGDE; unsigned int GDEntries; unsigned int GTEntries; char *descData; uint64_t descriptorSector; uint64_t descriptorSize; bool footer; unsigned short compression; } extentInfo; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/vmnode.cpp000066400000000000000000000105361217176075400225450ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Jeremy MOUNIER */ #include "vmnode.hpp" VMNode::VMNode(std::string Name, uint64_t size, Node* parent, VMware* vm, Link *lnk): Node(Name, size, parent, vm) { this->_vm = vm; this->_lnk = lnk; this->_cid = this->_lnk->getCID(); this->_links = this->_vm->getLinksFromCID(this->_cid); this->setFile(); this->_baseLink = this->getBaseLink(); } VMNode::~VMNode() { } Link *VMNode::getBaseLink() { for( std::list::iterator lk=this->_links.begin(); lk!=this->_links.end(); ++lk) { if ((*lk)->isBase()) return (*lk); } return NULL; } void VMNode::fileMapping(FileMapping *fmap) { // Get extents from first Link std::vector extents = this->_baseLink->getExtents(); // Get number of extents uint32_t nextents = extents.size(); uint32_t curextent = 0; uint64_t voffset = 0; uint64_t vextoffset = 0; uint64_t currentGDE = 0; int mapcheck; // Parse All extents while (curextent < nextents) { currentGDE = 0; vextoffset = 0; while (currentGDE < extents[curextent]->GDEntries) { mapcheck = this->mapGTGrains(currentGDE, curextent, fmap, &voffset, &vextoffset, extents[curextent]->GTEntries); // if mapcheck currentGDE++; } curextent++; } } Link *VMNode::getDeltaLink(uint64_t currentGDE, uint32_t currentGTE, uint32_t curextent) { uint64_t GTOffset; uint32_t GTEntry; uint64_t GDEOffset; for( std::list::iterator lk=this->_links.begin(); lk!=this->_links.end(); ++lk) { std::vector extents = (*lk)->getExtents(); Extent *ext = extents[curextent]; GDEOffset = (ext->sectorRGD * SECTOR_SIZE) + (currentGDE * 4); GTOffset = this->getGT(GDEOffset, ext); GTEntry = this->readGTEntry(GTOffset, currentGTE, ext); if (GTEntry != 0) { return (*lk); } } return this->_baseLink; } uint32_t VMNode::readGTEntry(uint64_t GTEOffset, uint32_t currentGTE, Extent *ext) { uint32_t GTEntry; try { ext->vfile->seek(GTEOffset + (currentGTE * 4)); ext->vfile->read(>Entry, sizeof(unsigned int)); } catch (envError & e) { std::cerr << "Error reading Entry : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } return GTEntry; } //========================= // Get GT Start Offset from a GD Entry uint64_t VMNode::getGT(uint64_t GDEOffset, Extent* ext) { uint64_t GTOffset; uint32_t GDEntry; // ok try { ext->vfile->seek(GDEOffset); ext->vfile->read(&GDEntry, sizeof(unsigned int)); } catch (envError & e) { std::cerr << "Error reading Entry : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } GTOffset = GDEntry * SECTOR_SIZE; return GTOffset; } int VMNode::mapGTGrains(uint64_t currentGDE, uint32_t curextent, FileMapping *fm, uint64_t *voffset, uint64_t *vextoffset, uint64_t GTEntries) { uint64_t grainOffset; uint32_t GTEntry; uint64_t currentGTE = 0; uint64_t GDEOffset; uint32_t grainSize; uint64_t GTOffset; while (currentGTE < GTEntries) { Link *dlink = this->getDeltaLink(currentGDE, currentGTE, curextent); std::vector extents = dlink->getExtents(); Extent *ext = extents[curextent]; if (*vextoffset < (ext->sectors * SECTOR_SIZE)) { GDEOffset = (ext->sectorRGD * SECTOR_SIZE) + (currentGDE * 4); GTOffset = this->getGT(GDEOffset, ext); GTEntry = this->readGTEntry(GTOffset, currentGTE, ext); grainSize = (ext->sectorsPerGrain * SECTOR_SIZE); grainOffset = (uint64_t)(GTEntry) * SECTOR_SIZE; if (GTEntry != 0) { fm->push(*voffset, grainSize, ext->vmdk, grainOffset); } else fm->push(*voffset, grainSize); *voffset += grainSize; *vextoffset += grainSize; currentGTE += 1; } else { return 0; } } return 1; } dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/vmnode.hpp000066400000000000000000000026071217176075400225520ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Jeremy MOUNIER */ #ifndef __VMNODE_HPP__ #define __VMNODE_HPP__ #include "variant.hpp" #include "node.hpp" #include "vmware.hpp" #include "vmdk.hpp" #include "link.hpp" class VMNode: public Node { public: VMNode(std::string name, uint64_t size, Node* parent, class VMware *vm, Link *lnk); ~VMNode(); virtual void fileMapping(FileMapping *fmap); private: class VMware* _vm; uint64_t getGT(uint64_t GDEOffset, Extent* ext); int mapGTGrains(uint64_t currentGDE, uint32_t curextent, FileMapping *fm, uint64_t *voffset, uint64_t *vextoffset, uint64_t GTEntries); Link *getDeltaLink(uint64_t currentGDE, uint32_t currentGTE, uint32_t curextent); uint32_t readGTEntry(uint64_t GTEOffset, uint32_t currentGTE, Extent *ext); Link *getBaseLink(); Link *_baseLink; Link *_lnk; std::string _cid; std::list _links; }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/vmware.cpp000066400000000000000000000110101217176075400225420ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #include #include #include "vmware.hpp" #include "vmdk.hpp" #include "diskDescriptor.hpp" VMware::VMware() : mfso("vmware") { // _forceVmdkReconstruction = false; // _storageVolumeSize = 0; } VMware::~VMware() { } void VMware::start(std::map args) { int err; std::map::iterator it; it = args.find("vmdkroot"); if (it != args.end()) this->_vmdkroot = it->second->value(); else throw (std::string("Could not load node : arg->get(\"parent\", &_node) failed.")); this->_rootdir = this->_vmdkroot->parent(); err = this->createLinks(_vmdkroot, "0"); if (err != -1) { this->createNodes(); } } Node *VMware::getParentVMDK(std::string parentFileName) { Node *parent = this->_vmdkroot->parent(); std::vectornext = parent->children(); for( std::vector::iterator in=next.begin(); in!=next.end(); ++in) { if ((*in)->name() == parentFileName) { return (*in); } } return NULL; } /* Detect VMDK type: Storage Volume | Text Descriptor*/ int VMware::detectDiskDescriptor(Node *vmdk) { unsigned int flag; VFile *vfile = vmdk->open(); sparseExtentHeader header; try { vfile->seek(0); vfile->read(&flag, sizeof(unsigned int)); } catch (envError & e) { vfile->close(); std::cerr << "Error reading vmdk disk descriptor : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } if (flag == VMDK_DISK_DESCRIPTOR) { vfile->close(); return 0; } else if (flag == VMDK_SPARSE_MAGICNUMBER) { /** Read VMDK _Header and get Disk Descriptor sector if present**/ try { vfile->seek(0); vfile->read(&header, sizeof(SparseExtentHeader)); vfile->close(); } catch (envError & e) { vfile->close(); std::cerr << "Error reading Header : arg->get(\"parent\", &_node) failed." << std::endl; throw e; } if (header.descriptorOffset != 0) { vfile->close(); return 1; } } vfile->close(); return -1; } int VMware::createLinks(Node *vmdkroot, std::string pcid) { int err; int ft; if (pcid != CID_NOPARENT) { ft = this->detectDiskDescriptor(vmdkroot); if (ft >= 0) { diskDescriptor *dd = new diskDescriptor(vmdkroot, ft); std::string parentFileName = dd->parentFileName(); std::string cid = dd->getCID(); std::string npcid = dd->getPCID(); Link *lnk = new Link(dd, ft, vmdkroot); err = lnk->listExtents(); _links[cid] = lnk; if (err != -1 && npcid != CID_NOPARENT) { Node *parent = getParentVMDK(parentFileName); if (parent != NULL) this->createLinks(parent, npcid); else return -1; } } else return -1; } return 1; } // ================================================================ int VMware::createNodes() { this->_baseroot = new Node("Baselink"); if (this->_links.size() > 1) this->_snaproot = new Node("Snapshots", 0, _vmdkroot); for( std::map::iterator ii=_links.begin(); ii!=_links.end(); ++ii) { std::string id = ii->first; Link *lnk = ii->second; uint64_t vs = lnk->volumeSize(); if (!lnk->isBase()) { Node *bnode = new Node(id, 0, this->_snaproot); new VMNode("VirtualHDD", vs, bnode, this, lnk); this->_baseNodes.push_back(bnode); } else { Node *vnode = new VMNode("VirtualHDD", vs, _baseroot, this, lnk); this->_baseNodes.push_back(vnode); } } this->registerTree(_vmdkroot, _baseroot); return (0); } std::list VMware::getLinksFromCID(std::string cid) { Link *tmplnk; std::list res; std::string ccid = cid; std::string pcid = ""; while (pcid != CID_NOPARENT) { tmplnk = this->_links[ccid]; pcid.clear(); pcid = tmplnk->getPCID(); ccid.clear(); ccid = pcid; res.push_back(tmplnk); } return res; } dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/vmware.hpp000066400000000000000000000062061217176075400225620ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #ifndef __VMWARE_HPP__ #define __VMWARE_HPP__ #include #include #include #include #include #include #include //#include // remove function in string operations #include "vfs.hpp" #include "node.hpp" #include "vfile.hpp" #include "vmnode.hpp" #include "link.hpp" #include "variant.hpp" //#include "swap.hpp" #include "mfso.hpp" #include "vlink.hpp" #include "vmdk.hpp" class VMware : public mfso { public: VMware(); ~VMware(); virtual void start(std::map args); // void setResults(); int detectDiskDescriptor(Node *vmdk); int createLinks(Node *vmdkroot, std::string pcid); std::list getLinksFromCID(std::string cid); Node *getParentVMDK(std::string parentFileName); int createNodes(); // ============================== // string getExtentName(string str); // Disk Descriptor operations (class?) // void readDiskDescriptor(VFile *vmdk, unsigned int offset, unsigned int size); // void parseLineDiskDescriptor(); // char* getLinesDiskDescriptor(char* ptr); // ========================================== //string cleanExtentString(string str); // XXXX TODO //Sparse Extents **** //Use template and default VMDK header if not present *** (opt) //getFreeGrains / sectors ** //Use redondant ** //ESX ** //Check if data in free grains / sectors * (opt) //Bypass Grain Directory if not present * // Create a tree for snapshots // Test on different versions 4 5 6 7 // test with broken vmdk (DC3) // test with classical FS (Ext, NTFS, FAT?) private: //Node* _node; Node *_vmdkroot; Node *_rootdir; Node* _root; Node* _baseroot; Node* _snaproot; std::list _baseNodes; //map _links; std::map _links; // ========================================== // Node* _storageVolume; // dff_ui64 _storageVolumeSize; // ========================================== // vector _nodeExtents; VFile* _vfile; // In argument, try to use default values to reconstruct header and access GD // bool _forceVmdkReconstruction; // Header // SparseExtentHeader _backupMonoHeader; // SparseExtentHeader _backupTwoHeader; //=============================================== // Text Disk Description // char* _descData; // list _descLines; // list _descExtents; // map _descMap; // ========================================== }; #endif dff-1.3.0+dfsg.1/dff/modules/volumes/vmware/vmware.i000066400000000000000000000034361217176075400222250ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * MOUNIER Jeremy * */ #include "pyrun.swg" %module VMWARE %include "std_list.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "export.hpp" #include "vmware.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "vmware.hpp" %pythoncode %{ __dff_module_vmware_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId class VMWARE(Module): """Reconstruct vmware volume""" def __init__(self): Module.__init__(self, 'vmware', VMware) self.conf.addArgument({"name": "vmdkroot", "description": "file containing vmdk description", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["vmdk"]}) self.conf.addConstant({"name": "extension-type", "type": typeId.String, "description" : "compatible extension", "values" : ["vmdk"]}) self.tags = "Volumes" self.icon = ":vm" %} dff-1.3.0+dfsg.1/dff/ui/000077500000000000000000000000001217176075400145165ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/CMakeLists.txt000066400000000000000000000014471217176075400172640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ui.py ${CMAKE_CURRENT_BINARY_DIR}/ui.py) install_file( __init__.py history.py redirect.py ui.py conf.py ) add_subdirectory(console) add_subdirectory(gui) dff-1.3.0+dfsg.1/dff/ui/__init__.py000066400000000000000000000012061217176075400166260ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __all__ = [ 'ui', "console", "gui", 'gui_pro'] dff-1.3.0+dfsg.1/dff/ui/conf.py000066400000000000000000000114361217176075400160220ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # import sys import ConfigParser from os import access, R_OK from os.path import exists, expanduser, normpath from PyQt4.QtCore import QDir try: import api.index INDEX_ENABLED = True except ImportError: INDEX_ENABLED = False class Conf(): class __Conf(): def __init__(self, confPath): """ Initial configuration By default ; no footprint ! """ self.initLanguage() self.indexEnabled = INDEX_ENABLED homeDir = normpath(expanduser('~') + '/') # Global settings self.workingDir = normpath(homeDir + '/.dff_conf/') self.noHistoryFile = False # DFF < 1.0 history file was saved in ~/.dff_history if exists(normpath(homeDir + '/.dff_history')): self.historyFileFullPath = normpath(homeDir + '/.dff_history') else: self.historyFileFullPath = normpath(self.workingDir + '/history') self.noFootPrint = True # Indexes configuration if self.indexEnabled: self.root_index = normpath(self.workingDir + '/indexes/') self.index_name = 'default' self.index_path = normpath(self.root_index + '/' + self.index_name) # Help self.docPath = normpath(sys.modules['dff.ui.gui'].__path__[0] + '/help.qhc') # Try reading config file, overwrite default values above if found if confPath: self.configFile = normpath(confPath) else: self.configFile = normpath(self.workingDir + '/config.cfg') if access(self.configFile, R_OK): self.read() def initLanguage(self): self.language = "en" def save(self): if self.noFootPrint: return config = ConfigParser.RawConfigParser() config.add_section('Global') config.set('Global', 'nofootprint', self.noFootPrint) config.set('Global', 'workingdir', self.workingDir) config.set('Global', 'nohistoryfile', self.noHistoryFile) config.set('Global', 'historyfilefullpath', self.historyFileFullPath) config.add_section('Language') config.set('Language', 'use', self.language) if self.indexEnabled: config.add_section('Index') config.set('Index', 'rootindex', self.root_index) config.set('Index', 'indexname', self.index_name) config.set('Index', 'indexpath', self.index_path) config.add_section('Help') config.set('Help', 'helppath', self.docPath) configfile = open(self.configFile, 'wb') if configfile: config.write(configfile) configfile.close() def read(self): config = ConfigParser.RawConfigParser() config.read(self.configFile) self.noFootPrint = config.getboolean('Global', 'nofootprint') self.workingDir = config.get('Global', 'workingdir') self.noHistoryFile = config.getboolean('Global', 'nohistoryfile') self.historyFileFullPath = config.get('Global', 'historyfilefullpath') self.language = config.get('Language', 'use') if self.indexEnabled: try: config.items('Index') self.root_index = config.get('Index', 'rootindex') self.index_name = config.get('Index', 'indexname') self.index_path = config.get('Index', 'indexpath') except ConfigParser.NoSectionError: self.root_index = "" self.index_name = "" self.index_path = "" self.docPath = config.get('Help', 'helppath') __instance = None def __init__(self, confPath = ''): if Conf.__instance is None: Conf.__instance = Conf.__Conf(confPath) def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) def setLanguage(self, lang): self.language = lang def getLanguage(self): return self.language dff-1.3.0+dfsg.1/dff/ui/console/000077500000000000000000000000001217176075400161605ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/console/CMakeLists.txt000066400000000000000000000012421217176075400207170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py complete_raw_input.py completion.py console.py line_to_arguments.py utils.py ) dff-1.3.0+dfsg.1/dff/ui/console/__init__.py000066400000000000000000000011031217176075400202640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ["console"] dff-1.3.0+dfsg.1/dff/ui/console/complete_raw_input.py000066400000000000000000000204221217176075400224320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import sys,os, string, struct if os.name == "posix": import tty, termios, fcntl elif os.name == "nt": import msvcrt from ctypes import windll, create_string_buffer from dff.ui.history import history class complete_raw_input(): class __posix(): eol = "\n" MOVE_LEFT = '\x1b\x5b\x44' MOVE_RIGHT = '\x1b\x5b\x43' MOVE_UP = '\x1b\x5b\x41' MOVE_DOWN = '\x1b\x5b\x42' def __init__(self, parent, console): self.console = console self.completekey = self.console.completekey self.complete_func = self.console.complete self.line = "" self.history = history() self.parent = parent def get_term_size(self): width = 80 s = struct.pack('HHHH', 0, 0, 0, 0) s = fcntl.ioctl(1, termios.TIOCGWINSZ, s) twidth = struct.unpack('HHHH', s)[1] if twidth > 0: width = twidth return width def get_char(self, timeout = 0): ch = '' fd = sys.stdin.fileno() if os.isatty(fd): oldterm = termios.tcgetattr(fd) term = termios.tcgetattr(fd) term[3] = term[3] & ~termios.ICANON & ~termios.ECHO if not timeout: term[6] [termios.VMIN] = 1 term[6] [termios.VTIME] = timeout else: term[6] [termios.VMIN] = 0 term[6] [termios.VTIME] = timeout try : termios.tcsetattr(fd, termios.TCSANOW, term) import platform if platform.system().find('BSD') == -1: # Fix for BSD, avoid sendbreack : termios.error: (25, 'Inappropriate ioctl for device') termios.tcsendbreak(fd, 0) try : ch = os.read(fd, 7) except OSError: pass finally : termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) else: try : ch = os.read(fd, 7) except OSError: pass if len(ch) == 1: if ch in string.printable: return ch elif ch == '\b' or ch == '\x7f': self.delchar() elif ch == self.MOVE_LEFT: #left arrow if self.cursor > 0: self.print_text(ch) self.cursor -= 1 elif ch == self.MOVE_RIGHT: if self.cursor < len(self.line): self.print_text(ch) self.cursor += 1 elif ch == self.MOVE_UP: self.clear_line() cmd = self.history.getnext() if cmd: self.insert_text(cmd) elif ch == self.MOVE_DOWN: self.clear_line() cmd = self.history.getprev() if cmd: self.insert_text(cmd) return None def __getattr__(self, attr): return getattr(self.parent, attr) class __nt(): eol = "\r" CODE_LEFT = '\x4b' MOVE_LEFT = '\x08' MOVE_RIGHT = '\x4d' MOVE_UP = '\x48' MOVE_DOWN = '\x50' def __init__(self, parent, console): self.console = console self.completekey = self.console.completekey self.complete_func = self.console.complete self.line = "" self.history = history() self.parent = parent def get_term_size(self): h = windll.kernel32.GetStdHandle(-12) csbi = create_string_buffer(22) res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) if res: (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) sizex = right - left + 1 else: sizex = 80 return sizex def get_char(self, timeout = None): ch = msvcrt.getch() if len(ch) == 1: if ch in string.printable: return ch elif ch == '\x08': self.delchar() elif ch == '\xe0': ch = msvcrt.getch() if ch == self.CODE_LEFT: if self.cursor > 0: self.print_text(self.MOVE_LEFT) self.cursor -= 1 elif ch == self.MOVE_RIGHT: if self.cursor < len(self.line): pad = len(self.line) - self.cursor self.print_text(self.line[self.cursor:] + (pad - 1) * self.MOVE_LEFT) self.cursor += 1 elif ch == self.MOVE_UP: self.clear_line() cmd = self.history.getnext() if cmd: self.insert_text(cmd) elif ch == self.MOVE_DOWN: self.clear_line() cmd = self.history.getprev() if cmd: self.insert_text(cmd) return None def __getattr__(self, attr): return getattr(self.parent, attr) def __init__(self, console): if os.name == "posix": complete_raw_input.__instance = complete_raw_input.__posix(self, console) elif os.name == "nt": complete_raw_input.__instance = complete_raw_input.__nt(self, console) def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) def wait(self, timeout = None): c = None self.line = "" self.cursor = 0 c = self.get_char() if c == 'z': return "signal get" return "loop" def raw_input(self): c = None self.line = "" self.cursor = 0 sys.__stdout__.write(self.console.prompt) sys.__stdout__.flush() while c != self.eol: if c: if c == self.completekey: spaceidx = self.line[:self.cursor].rfind(" ") if spaceidx != -1: text = self.line[spaceidx+1:self.cursor] else: text = self.line[:self.cursor] i = 0 skey = 0 kshell = False while i != len(text): if text[i] in [";", "<", ">", "&", "|"]: kshell = True skey = i i += 1 if kshell: text = text[skey+1:] matches = self.complete_func(self.line, self.cursor) self.insert_comp(text, matches) else: self.insert_text(c) c = self.get_char() self.print_text('\n') return self.line def insert_text(self, text): lsplit = self.line[:self.cursor] rsplit = self.line[self.cursor:] self.line = lsplit + text + rsplit self.cursor += len(text) sys.__stdout__.write(text + rsplit) sys.__stdout__.write(len(rsplit) * self.MOVE_LEFT) sys.__stdout__.flush() def print_text(self, text): sys.__stdout__.write(text) sys.__stdout__.flush() def clear_line(self): self.print_text(self.cursor * self.MOVE_LEFT + len(self.line) * ' ' + len(self.line) * self.MOVE_LEFT) self.line = '' self.cursor = 0 def delchar(self): if self.cursor > 0: lsplit = self.line[:self.cursor - 1] rsplit = self.line[self.cursor:] self.line = lsplit + rsplit self.cursor -= 1 self.print_text(self.MOVE_LEFT + rsplit + ' ' + (len(rsplit) + 1)*self.MOVE_LEFT) def insert_comp(self, text, matches): #results of completion with lots of information res = "" if isinstance(matches, dict) and matches["matched"] != 0: if matches["matched"] > 1: sys.stdout.write("\n") if "type" in matches: if hasattr(self.console.completion, "insert_" + matches["type"] + "_comp"): func = getattr(self.console.completion, "insert_" + matches["type"] + "_comp") res = func(text, matches) else: pass else: pass if isinstance(matches, str): start = len(text) if start > 0: ins = matches[start:] else: ins = matches self.line = self.line[:self.cursor] + ins + self.line[self.cursor:] self.cursor += len(ins) if res != "" and res != None: self.line = self.line[:self.cursor] + res + self.line[self.cursor:] self.cursor += len(res) n = len(self.line) - self.cursor sys.stdout.write("\n" + self.console.prompt) self.print_text(self.line + n * self.MOVE_LEFT) dff-1.3.0+dfsg.1/dff/ui/console/completion.py000066400000000000000000001044061217176075400207100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Christophe Malinge # import sys, os, dircache, utils, re, types from dff.api.loader.loader import loader from dff.api.vfs.vfs import vfs from dff.api.types.libtypes import typeId, Argument, Parameter, ConfigManager class Context(): def __init__(self, DEBUG = False, VERBOSITY = 0): self.DEBUG = DEBUG self.VERBOSITY = VERBOSITY self.confmanager = ConfigManager.Get() self.config = None self.keylessarg = None self.currentArgument = None self.parsedArgument = None self.providedArguments = {} self.remainingArguments = [] self.threaded = False self.currentStr = "" self.vfs = vfs() self.currentStrScope = 0 self.paramsplit = re.compile('(? 0: print dbg def __makeParameter(self, argument, parameter): if argument.type() == typeId.Node: parameter = parameter.replace("\ ", " ") n = self.vfs.getnode(parameter) if n: return n else: raise ValueError("Node " + str(parameter) + " provided to argument < " + argument.name() + " > does not exist") elif argument.type() == typeId.Path: if parameter[0] != "/": return str(os.getcwd() + "/" + parameter).replace("//", "/") else: return parameter elif argument.type() == typeId.String: return parameter.replace("\ ", " ") else: return parameter def makeArguments(self): command = {} dbg = "\n ==== Context.makeCommand() ====" if len(self.badargs) > 0: raise KeyError("cannot generate config for module < " + self.config.origin() + " > The following arguments do not exist: " + str(self.badargs)) for argname in self.providedArguments.keys(): argument = self.config.argumentByName(argname) parameters = self.providedArguments[argname] if argument.inputType() == Argument.List: l = [] iterator = self.paramsplit.finditer(parameters) itcount = 0 previdx = 0 for match in iterator: itcount += 1 pos = match.span() parameter = parameters[previdx:pos[0]] previdx = pos[1] dbg += "\n adding parameter: < " + str(parameter) + " > to list" try: realparam = self.__makeParameter(argument, parameter) l.append(realparam) except: raise if itcount == 0 or previdx != len(parameters): dbg += "\n adding parameter: < " + parameters[previdx:] + " > to list" try: realparam = self.__makeParameter(argument, parameters[previdx:]) l.append(realparam) except: raise command[argname] = l else: dbg += "\n adding parameter: < " + str(parameters) try: realparam = self.__makeParameter(argument, parameters) command[argname] = realparam except: raise if self.DEBUG and self.VERBOSITY > 0: dbg += "\n resulting command arguments:" for argname in command.keys(): dbg += "\n " + argname + " --> " + str(command[argname]) self.debug(dbg) return command def dump(self): buff = "\n ==== Context.dump() ====" buff += "\n associated config: " if self.config != None: buff += self.config.origin() lparg = len(self.providedArguments) buff += "\n provided arguments: " + str(lparg) if lparg != 0: for argname in self.providedArguments.keys(): buff += "\n " + argname + " --> " + str(self.providedArguments[argname]) lrarg = len(self.remainingArguments) buff += "\n remaining arguments: " + str(lrarg) if lrarg != 0: for argname in self.remainingArguments: buff += "\n " + argname buff += "\n threaded: " + str(self.threaded) else: buff += " None" buff += "\n currentArgumentScope: " if self.currentArgument != None: buff += str(self.currentArgument.name()) else: buff += "None" buff += "\n currentStr: " + self.currentStr buff += "\n currentStrScope: " + str(self.currentStrScope) return buff def disambiguator(self): requirednodes = self.config.argumentsByFlags(typeId.Node|Argument.Required) optionalnodes = self.config.argumentsByFlags(typeId.Node|Argument.Optional) requiredpathes = self.config.argumentsByFlags(typeId.Path|Argument.Required) optionalpathes = self.config.argumentsByFlags(typeId.Path|Argument.Optional) rnodes = len(requirednodes) onodes = len(optionalnodes) rpathes = len(requiredpathes) opathes = len(optionalpathes) dbg = "\n ==== Context.disambiguator() ====" if rnodes == 1 and rpathes == 0: self.keylessarg = requirednodes[0] if onodes == 1 and opathes == 0 and rnodes == 0 and rpathes == 0: self.keylessarg = optionalnodes[0] if rpathes == 1 and rnodes == 0: self.keylessarg = requiredpathes[0] if opathes == 1 and onodes == 0 and rnodes == 0 and rpathes == 0: self.keylessarg = optionalpathes[0] if self.keylessarg != None: dbg += "\n keylessarg exists and has been setted to < " + str(self.keylessarg.name()) + " >" else: dbg += "\n keylessarg does not exist" self.debug(dbg) def setCurrent(self, token, pos): dbg = "\n ==== Context.setCurrent() ====" dbg += "\n token: " + token dbg += "\n pos: " + str(pos) dbg += "\n currentstrscope: " + token[:pos] if len(token.split()) != 0: self.currentStr = token self.currentStrScope = pos else: self.currentStrScope = 0 self.currentStr = "" if self.parsedArgument != None: dbg += "\n parsedArgument != None" if self.providedArguments[self.parsedArgument.name()] in [token, None]: dbg += "\n currentArgument = self.parsedArgument --> " + str(self.parsedArgument.name()) self.currentArgument = self.parsedArgument else: dbg += "\n currentArgument = None" self.currentArgument = None self.debug(dbg) def parameterToken(self, token): dbg = "\n ==== Context.parameterToken() ====" if self.parsedArgument == None: dbg += "\n parsedArgument == None" if self.keylessarg != None and self.keylessarg.name() in self.remainingArguments: dbg += "\n keylessarg exists and not setted yet. " + str(self.keylessarg.name()) + " --> " + token self.providedArguments[self.keylessarg.name()] = token self.remainingArguments.remove(self.keylessarg.name()) self.parsedArgument = self.keylessarg elif self.providedArguments[self.parsedArgument.name()] == None: dbg += "\n parsedArgument exists and not setted yet. " + str(self.parsedArgument.name()) + " --> " + token self.providedArguments[self.parsedArgument.name()] = token self.remainingArguments.remove(self.parsedArgument.name()) else: dbg += "\n parsedArgument already setted" self.parsedArgument = None self.debug(dbg) def __argumentToken(self, token): dbg = "\n ==== Context.__argumentToken() ====" argument = self.config.argumentByName(token[2:]) if argument != None: argname = argument.name() dbg += "\n argument found: " + argname if argname in self.remainingArguments: if argument.inputType() == Argument.Empty: self.providedArguments[argname] = True self.remainingArguments.remove(argname) self.parsedArgument = None else: self.providedArguments[argname] = None self.parsedArgument = argument else: dbg += "\n argument < " + argname + " > already provided" else: self.badargs.append(token) dbg += "\n argument not found" self.parsedArgument = None self.debug(dbg) def argumentToken(self, token): dbg = "\n ==== Context.argumentToken() ====" if self.parsedArgument != None: if self.parsedArgument.inputType() != Argument.Empty: dbg += "\n token starts with -- and parsedArgument != None and is not a switch" argname = self.parsedArgument.name() if self.providedArguments[argname] == None: if token[2:] not in self.remainingArguments: dbg += "\n currentArgument exists and not setted yet. " + str(argname) + " --> " + token self.remainingArguments.remove(argname) self.providedArguments[argname] = token else: self.__argumentToken(token) else: self.__argumentToken(token) else: self.remainingArguments.remove(argname) self.providedArguments[argname] = None self.parsedArgument = None else: self.__argumentToken(token) self.debug(dbg) def configToken(self, token): self.config = self.confmanager.configByName(token) if self.config != None: self.disambiguator() argsname = self.config.argumentsName() for argname in argsname: self.remainingArguments.append(argname) def addToken(self, token, curpos = -1): dbg = "\n ==== Context.addToken() ====" dbg += "\n token: " + token dbg += "\n curpos: " + str(curpos) self.tokens.append(token) self.debug(dbg) if self.config == None: if curpos != -1: self.setCurrent(token, curpos) self.configToken(token[:curpos]) else: self.configToken(token) else: if token.startswith("--"): if curpos != -1: self.setCurrent(token, curpos) self.argumentToken(token[:curpos]) else: self.argumentToken(token) else: self.parameterToken(token) if curpos != -1: self.setCurrent(token, curpos) class LineParser(): def __init__(self, DEBUG = False, VERBOSITY = 0): self.DEBUG = DEBUG self.VERBOSITY = VERBOSITY self.ctxs = [] self.shellKeys = [";", "&"] def debug(self, msg): if self.DEBUG and self.VERBOSITY: print " ", msg def currentContext(self): if self.scopeCtx >= 0: return self.contexts[self.scopeCtx] return None def manageShellKeys(self, key, startidx, endidx): dbg = "\n ==== LineParser.manageShellKeys() ====" if key == "&": dbg += "\n & found" dbg += "\n begidx: " + str(self.begidx) dbg += "\n endidx: " + str(endidx) self.contexts[self.ctxpos].threaded = True dbg += "\n incrementing ctxpos" ctx = Context(self.DEBUG, self.VERBOSITY - 1) self.contexts.append(ctx) self.ctxpos += 1 if self.begidx > endidx: #and endidx != len(self.line): self.scopeCtx = self.ctxpos elif key == "&&": self.contexts.append(Context(self.DEBUG, self.VERBOSITY - 1)) self.ctxpos += 1 if self.begidx == startidx + 1: self.scopeCtx = self.ctxpos self.contexts.append(Context(self.DEBUG, self.VERBOSITY - 1)) self.ctxpos += 1 dbg += "\n key found and begidx in the middle of " + key self.debug(dbg) def makeCommands(self, line): line = line.rstrip() begidx = len(line) self.makeContexts(line, begidx) commands = [] dbg = "\n ==== LineParser.makeCommands() ====" for context in self.contexts: if context.config != None: try: commands.append((context.config.origin(), context.makeArguments(), context.threaded, "")) except KeyError, error: commands.append((context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + str(error))) except ValueError, error: commands.append((context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + str(error))) elif len(context.tokens) != 0: commands.append((None, None, None, str("module < "+ context.tokens[0] + " > does not exist"))) if self.DEBUG and self.VERBOSITY: dbg += "\n stacked commands:" for command in commands: dbg += "\n command name: " + command[0] dbg += "\n arguments: " + str(command[1]) dbg += "\n to thread: " + str(command[2]) + "\n" self.debug(dbg) return commands def makeContexts(self, line, begidx = -1): self.begidx = begidx self.contexts = [] self.scopeCtx = -1 self.line = line self.ctxpos = 0 startidx = 0 i = 0 token = "" dbg = "\n ==== LineParser.makeContext() ====" dbg += "\n line: |" + line + "|" dbg += "\n begidx: " + str(begidx) if len(line) != 0: ctx = Context(self.DEBUG, self.VERBOSITY - 1) self.contexts.append(ctx) while i < len(line): if line[i] == " " and (line[i-1] != "\\") and len(token.split()) != 0: if self.begidx >= startidx and self.begidx <= i: self.scopeCtx = self.ctxpos self.contexts[self.ctxpos].addToken(token, self.begidx-startidx) else: self.contexts[self.ctxpos].addToken(token) token = "" startidx = i elif line[i] in self.shellKeys and (line[i-1] != "\\"): if len (token.split()) != 0: if self.begidx >= startidx and self.begidx <= i: self.contexts[self.ctxpos].addToken(token, self.begidx-startidx) self.scopeCtx = self.ctxpos else: self.contexts[self.ctxpos].addToken(token) token = "" startidx = i key = "" while i < len(line) and line[i] in self.shellKeys: key += line[i] i += 1 self.manageShellKeys(key, startidx, i) startidx = i if i < len(line): token = line[i] else: token = "" startidx = i elif len(token.split()) == 0: startidx = i token = line[i] else: token = token + line[i] i += 1 if len(token.split()) != 0: if self.begidx >= startidx and self.begidx <= i: self.contexts[self.ctxpos].addToken(token, self.begidx-startidx) self.scopeCtx = self.ctxpos else: self.contexts[self.ctxpos].addToken(token) elif self.begidx == len(line): self.contexts[self.ctxpos].addToken(token, self.begidx-startidx) self.scopeCtx = self.ctxpos if self.DEBUG and self.VERBOSITY > 0: dbg += "\n current context: " if self.contexts[self.scopeCtx].config: dbg += str(self.contexts[self.scopeCtx].config.origin()) else: dbg += "None" dbg += "\n scopeCtx: " + str(self.scopeCtx) dbg += "\n ctxpox: " + str(self.ctxpos) print dbg for ctx in self.contexts: print ctx.dump() print class Completion(): def __init__(self, console, DEBUG = False, VERBOSITY = 0): self.DEBUG = DEBUG self.VERBOSITY = VERBOSITY self.console = console self.lp = LineParser(self.DEBUG, self.VERBOSITY - 1) self.confmanager = ConfigManager.Get() self.loader = loader() self.vfs = vfs() def currentParameter(self): dbg = "\n ==== currentParameter() ====" dbg += "\n current str to process: |" + self.context.currentStr + "|" resstr = "" if len(self.context.currentStr) in [0, 1] or self.context.currentArgument.inputType() == Argument.Single: resstr = self.context.currentStr[:self.context.currentStrScope] else: endidx = self.context.currentStrScope dbg += "\n cursor pos in current string " + str(endidx) iterator = re.finditer('(? out["length"]: out["length"] = len(name + "/") out["matches"].append(name + "/") else: if len(name) > out["length"]: out["length"] = len(name) out["matches"].append(name) out["matched"] += 1 self.debug(dbg) return out def completePredefined(self): parameter = self.currentParameter() out = {"type": "predefined", "matches": [], "matched": 0, "supplied": parameter, "length": 1} predefs = self.context.currentArgument.parameters() for predef in predefs: val = str(predef.value()) if parameter == "" or val.startswith(parameter): if len(val) > out["length"]: out["length"] = len(val) out["matches"].append(val) out["matched"] += 1 return out def completeModules(self): out = {"type": "module", "matches": {}, "length": {"tag": 1, "module": 1}, "matched": 0} longest_tag = 1 longest_modname = 1 modnames = self.confmanager.configsName() for modname in modnames: if (self.context == None) or modname.startswith(self.context.currentStr[:self.context.currentStrScope]) or self.context.currentStr[:self.context.currentStrScope] == "": if longest_modname < len(modname): longest_modname = len(modname) tag = self.modules[modname].tags if longest_tag < len(tag): longest_tag = len(tag) if tag not in out["matches"]: out["matches"][tag] = [] out["matches"][tag].append(modname) out["matched"] += 1 out["length"]["tag"] = longest_tag out["length"]["module"] = longest_modname if out["matched"] == 1: out = [out["matches"][i][0] for i in out["matches"].iterkeys()] elif out["matched"] == 0: out = "" return out def completeArguments(self): out = {"type": "key", "required": [], "optional": [], "length": 1, "matched": 0} for argname in self.context.remainingArguments: argument = self.context.config.argumentByName(argname) if self.context.currentStr[:self.context.currentStrScope] in ["", "-"]: match = True elif self.context.currentStr.startswith("--") and argname.startswith(self.context.currentStr[2:self.context.currentStrScope]): match = True else: match = False if match: out["matched"] += 1 if len(argname) > out["length"]: out["length"] = len(argname) if argument.requirementType() in [Argument.Empty, Argument.Optional]: out["optional"].append(argname) else: out["required"].append(argname) if out["matched"] == 0: out = "" elif out["matched"] == 1: if len(out["required"]) == 0: out = out["optional"][0] else: out = out["required"][0] out = "--" + out return out def debug(self, msg): if self.DEBUG and self.VERBOSITY > 0: print " ", msg def dispatch(self): matches = "" dbg = "\n ==== dispatch() ====" compfunc = None if self.context.currentArgument != None: parg = self.context.providedArguments[self.context.currentArgument.name()] dbg += "\n currentArgument exists: " + str(self.context.currentArgument.name()) dbg += "\n associated parameter: " + str(parg) if parg == None or parg == self.context.currentStr: dbg += "\n completing parameters for argument: " + str(self.context.currentArgument.name()) if self.context.currentArgument.type() in [typeId.Node, typeId.Path]: compfunc = getattr(self, "completePathes") else: compfunc = getattr(self, "completePredefined") else: dbg += "\n completing argument for currentStr: " + str(self.context.currentStr) compfunc = getattr(self, "completeArguments") else: dbg += "\n no current argument to complete" if len(self.context.remainingArguments) > 0: dbg += "\n remaining arguments exist --> total: " + str(len(self.context.remainingArguments)) if self.context.keylessarg != None and self.context.keylessarg.name() in self.context.remainingArguments: req = 0 dbg += "\n keylessarg != None and has not been provided yet" if not self.context.currentStr.startswith("--"): dbg += "\n keylessarg < " + str(self.context.keylessarg.name()) + " > can be used as default" self.context.currentArgument = self.context.keylessarg if self.context.currentArgument.type() in [typeId.Node, typeId.Path]: compfunc = getattr(self, "completePathes") else: compfunc = getattr(self, "completePredefined") else: dbg += "\n keylessarg can not be used as default, complete with remaining arguments" compfunc = getattr(self, "completeArguments") else: dbg += "\n either keylessarg is None or keylessarg already used" compfunc = getattr(self, "completeArguments") else: dbg += "\n nothing to complete" #self.debug(dbg) if compfunc != None: matches = compfunc() dbg += "\n matches:" + str(matches) self.debug(dbg) return matches def complete(self, line, begidx): self.modules = self.loader.modules self.lp.makeContexts(line, begidx) self.context = self.lp.currentContext() matches = "" if self.context == None: matches = self.completeModules() elif self.context.config == None: matches = self.completeModules() if len(matches) == 0: print "\nmodule < " + self.context.currentStr + " > does not exist" else: if self.context.currentStr != self.context.config.origin(): matches = self.dispatch() if type(matches) == types.ListType and len(matches) == 1: return matches[0] else: return matches def strdiff(self, str1, str2): i = len(str1) j = 0 while j < len(str1) and j < len(str2) and str1[j] == str2[j]: j += 1 i -= 1 return len(str1) - i def find_longest(self, list): max = 0 for str in list: if len(str) > max: max = len(str) return max def get_max_col(self, start, max): displaywidth = self.console.get_term_size() - start col = (displaywidth - (displaywidth / 6)) / max return col def insert_predefined_comp(self, text, matches): max_predef = matches["length"] col = self.get_max_col(13, max_predef) x = 0 if matches["matched"] == 1: idx = self.strdiff(matches["supplied"], matches["matches"][0]) return matches["matches"][0][idx:] sys.stdout.write("predefined: ") for item in matches["matches"]: if x == col: sys.stdout.write("\n" + " " * 13) x = 0 predef_arg = item + " " * (max_predef + 2 - len(item)) x += 1 sys.stdout.write(predef_arg) def insert_module_comp(self, text, matches): max_tag = matches["length"]["tag"] max_mod = matches["length"]["module"] col = self.get_max_col(max_tag + 4, max_mod) max_ident = 0 prev_mod = "" cur_mod = text res = "" idx = 0 if matches["matched"] == 1: if len(matches["matches"]["required"]) == 1: return self.get_str(text, matches["matches"]["required"][0]) else: return self.get_str(text, matches["matches"]["optional"][0]) for tag in matches["matches"].iterkeys(): if len(matches["matches"][tag]) > 0: tag_arg = tag + " " * (max_tag + 2 - len(tag)) + ": " sys.stdout.write(tag_arg) x = 0 #sys.stdout.write(str(len(matches["modules"][tag]))) for item in matches["matches"][tag]: if cur_mod != "": if prev_mod != "": _len = self.strdiff(prev_mod, item) if max_ident > _len: max_ident = _len else: max_ident = len(item) prev_mod = item[:max_ident] if x == col: sys.stdout.write("\n" + " " * (max_tag + 4)) x = 0 mod_arg = item + " " * (max_mod + 2 - len(item)) x += 1 sys.stdout.write(mod_arg) idx += 1 if idx < len(matches["matches"]): sys.stdout.write("\n") if max_ident > 0: return prev_mod[len(text):max_ident] def insert_path_comp(self, text, matches): max_path = matches["length"] cur_path = matches["supplied"].replace("\ ", " ") col = self.get_max_col(0, max_path) idx = 0 filled = 0 prev_path = "" max_ident = 0 if matches["matched"] == 1: res = self.strdiff(cur_path, matches["matches"][0]) comp = matches["matches"][0][res:] i = 0 while i != len(comp): if comp[i] == " " and comp[i - 1] != "\\": comp = comp[:i] + "\\" + comp[i:] i += 1 return comp else: x = 0 for path in matches["matches"]: if cur_path != "": if prev_path != "": res = self.strdiff(prev_path, path) if max_ident > res: max_ident = res else: max_ident = len(path) prev_path = path[:max_ident] if x == col: sys.stdout.write("\n") x = 0 path_arg = path + " " * (max_path + 2 - len(path)) sys.stdout.write(path_arg) x += 1 if cur_path != "": comp = prev_path[len(cur_path):max_ident] i = 0 while i != len(comp): if comp[i] == " " and comp[i - 1] != "\\": comp = comp[:i] + "\\" + comp[i:] i += 1 return comp #return prev_path[len(cur_path):max_ident] # return self.get_str(cur_path, prev_path[:same]) def get_str(self, text, matches): start = len(text) if start > 0: return matches[start:] else: return matches def longestCommonStr(self, str1, str2): minstr = (len("+" + str1) > len("+" + str2) and ("+" + str2) or ("+" + str1))[1:] maxstr = (len(str1) > len(str2) and str1 or str2) if minstr == maxstr: res = maxstr else: comp = map(lambda x: minstr.startswith(maxstr[:x]), xrange(1, len(maxstr) + 1)) #print comp idx = comp.index(False) res = maxstr[:idx] return res def insert_key_comp(self, text, matches): max_key = matches["length"] col = self.get_max_col(10, max_key) idx = 0 filled = 0 prev_key = text same = 0 common = "" for requirement in ["required", "optional"]: if len(matches[requirement]) > 0: filled += 1 sys.stdout.write(requirement + ": ") x = 0 count = 0 for key in matches[requirement]: if x == col: sys.stdout.write("\n" + (" " * 10)) x = 0 key_arg = key + " " * (max_key + 2 - len(key)) if count == 0: common = self.longestCommonStr(key_arg, key_arg) else: common = self.longestCommonStr(common, key_arg) sys.stdout.write(key_arg) x += 1 count += 1 idx += 1 if idx < filled: sys.stdout.write("\n") if text == "": return "--" + common elif text == "-": return "-" + common elif "--" + common == text: return "" else: return common[len(text)-2:] dff-1.3.0+dfsg.1/dff/ui/console/console.py000066400000000000000000000131001217176075400201670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # Frederic Baguelin # import sys,string, os, traceback, types, completion, signal import line_to_arguments import threading import re from cmd import Cmd from dff.api.manager.manager import ApiManager from dff.api.types.libtypes import ConfigManager from dff.ui.ui import UI from dff.ui.console.complete_raw_input import complete_raw_input from dff.ui.history import history PROMPT = "dff / > " INTRO = "\nWelcome to the Digital Forensic Framework\n" IDENTCHARS = string.ascii_letters + string.digits + '\ _=' class Console(Cmd, UI): def __init__(self, completekey='tab', stdin=None, stdout=None, sigstp=True, debug = False, verbosity = 0): Cmd.__init__(self, completekey, stdin, stdout) UI.__init__(self, debug, verbosity) self.cm = ConfigManager.Get() self.history = history() self.api = ApiManager() self.vfs = self.api.vfs() self.taskmanager = self.api.TaskManager() self.line_to_arguments = line_to_arguments.Line_to_arguments() self.old_completer = "" self.prompt = "dff / > " self.intro = "\n##########################################\n\ # Welcome on Digital Forensics Framework #\n\ ##########################################\n" self.stdin = self self.completekey = '\t' self.comp_raw = complete_raw_input(self) self.completion = completion.Completion(self.comp_raw, self.debug, self.verbosity) self.proc = None if os.name == 'posix' and sigstp: signal.signal(signal.SIGTSTP, self.bg) def launch(self, modulesPaths = None): if modulesPaths: self.loadModules(modulesPaths) self.cmdloop() def bg(self, signum, trace): if self.proc: proc = self.proc proc.event.set() proc.exec_flags += ["thread"] print "\n\n[" + str(proc.pid) + "]" + " background " + proc.name return None def precmd(self, line): return line def postcmd(self, stop, line): self.prompt = "dff " + self.vfs.getcwd().absolute() + " > " return stop def preloop(self): return def postloop(self): print "Exiting..." def onecmd(self, line, wait=False): try: if line == 'exit' or line == 'quit': return 'stop' if len(line.strip()) == 0: return self.emptyline() iterator = re.finditer('(? # import re import utils import dircache import os.path, os from dff.api.manager.manager import ApiManager class Line_to_arguments(): def __init__(self): self.api = ApiManager() self.loader = self.api.loader() self.vfs = self.api.vfs() def generate(self, line): self.args, bopt = utils.split_line(line) cmds = [] cmd = [] generated_arguments = [] #generated_args for a in self.args: if a in [";", "<", ">", "&", "|", "&&"]: pass else: cmd.append(a) cmds.append(cmd) for cmd in cmds: gen_arg = self.argument("input") if (self.string_to_arguments(cmd, gen_arg) != -1): exc = {} exc[cmd[0]] = gen_arg generated_arguments.append(exc) else: pass return generated_arguments def node_to_argument(self, key, value, gen_arg): res = 0 if value == None: node = self.vfs.getnode(value) else: value = value.replace("\ ", " ") node = self.vfs.getnode(value) if node != None: gen_arg.add_node(key, node) else: print "Value error: node <", value, "> doesn't exist" res = -1 return res def path_to_argument(self, key, value, gen_arg): res = 0 if value == None: abs_path = os.getcwd() else: value = value.replace("\ ", " ") abs_path = utils.get_absolute_path(value) if os.path.exists(abs_path): gen_arg.add_path(key, str(abs_path)) else: print "Value error: local path <", value, "> doesn't exist" res = -1 return res def bool_to_argument(self, key, value, gen_arg): if value == None: gen_arg.add_bool(key, int(0)) else: gen_arg.add_bool(key, int(1)) return 0 def string_to_argument(self, key, value, gen_arg): if value == None: gen_arg.add_string(key, str("")) else: gen_arg.add_string(key, str(value)) return 0 def int_to_argument(self, key, value, gen_arg): res = 0 if value == None: gen_arg.add_int(key, int(-1)) else: if utils.is_hex(value): gen_arg.add_int(key, int(value, 16)) elif utils.is_int(value): gen_arg.add_int(key, int(value)) else: print "Value error: value <", value, "> cannot be converted to int" res = -1 return res def get_func_generator(self, cdl): func_name = cdl.type + "_to_argument" func = None if hasattr(self, func_name): func = getattr(self, func_name) else: print "Type error: type <", cdl.type, "> associated to argument <", cdl.name, "> doesn't exist" return func def several_argument(self, cdl, args, gen_arg): res = 0 i = 0 needs_no_key = utils.needs_no_key(cdl) priority = utils.keyPriority(cdl) arg_with_no_key = utils.get_arg_with_no_key(args) while i != (len(cdl)) and res == 0: func = self.get_func_generator(cdl[i]) if func != None: key = "--" + cdl[i].name if key not in args: if cdl[i].optional == False: if needs_no_key != None and arg_with_no_key != -1: value = args[arg_with_no_key] res = func(cdl[i].name, value, gen_arg) arg_with_no_key = -1 else: print "Argument error: the argument <", cdl[i].name, "> is required by command: <", args[0], ">" res = -1 else: if arg_with_no_key != -1 and len(priority[0]) == 0 and len(priority[1]) == 1: if cdl[i].name == priority[1][0].name: value = args[arg_with_no_key] res = func(cdl[i].name, value, gen_arg) else: res = func(cdl[i].name, None, gen_arg) else: res = func(cdl[i].name, None, gen_arg) else: key_idx = args.index(key) if cdl[i].type == "bool": res = func(cdl[i].name, "", gen_arg) else: if (key_idx) == len(args) - 1: print "Key error: the argument <", key, "> needs a value" res = -1 else: value = args[key_idx + 1] res = func(cdl[i].name, value, gen_arg) else: res = -1 i += 1 return res def string_to_arguments(self, args, gen_arg): try: if not self.loader.is_modules(args[0]) : print "dff:" + args[0] + ": command not found" except IndexError: return -1 conf = self.loader.get_conf(args[0]) if conf != None: cdl = conf.descr_l if cdl == None: return gen_arg res = self.several_argument(cdl, args, gen_arg) if res == -1: return -1 else: return gen_arg else: return -1 dff-1.3.0+dfsg.1/dff/ui/console/utils.py000066400000000000000000000135171217176075400177010ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # import sys, os, string, struct, re if os.name == "posix": import tty, termios, fcntl elif os.name == "nt": import msvcrt from ctypes import windll, create_string_buffer from dff.api.types.libtypes import typeId class ConsoleAttributes(): class __posix(): def __init__(self): pass def terminalSize(self): width = 80 s = struct.pack('HHHH', 0, 0, 0, 0) s = fcntl.ioctl(1, termios.TIOCGWINSZ, s) twidth = struct.unpack('HHHH', s)[1] if twidth > 0: width = twidth return width class __nt(): def __init__(self): pass def terminalSize(self): h = windll.kernel32.GetStdHandle(-12) csbi = create_string_buffer(22) res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) if res: (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) sizex = right - left + 1 else: sizex = 80 return sizex def __init__(self): if os.name == "posix": ConsoleAttributes.__instance = ConsoleAttributes.__posix() elif os.name == "nt": ConsoleAttributes.__instance = ConsoleAttributes.__nt() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) class VariantTreePrinter(): def __init__(self): self.consoleAttr = ConsoleAttributes() self.maxitems = -1 self.maxdepth = -1 self.currentdepth = 0 def setMaxItemListToExpand(self, maxitems=-1): self.maxitems = maxitems def setMaxDepth(self, maxdepth=-1): self.maxdepth = maxdepth self.currentdepth = 0 def fillMap(self, spacer, vmap, res=""): self.termsize = self.consoleAttr.terminalSize() for key in vmap.iterkeys(): vval = vmap[key] res += "\n" + ("\t" * spacer) + str(key) if vval.type() == typeId.Map: if (self.maxdepth == -1 or self.currentdepth < self.maxdepth): vvmap = vval.value() self.currentdepth += 1 res += self.fillMap(spacer+1, vvmap) self.currentdepth -= 1 elif vval.type() == typeId.List: vlist = vval.value() size = len(vlist) res += ": total items (" + str(size) + ")\n" res += self.fillList(spacer+1, vlist) else: if vval.type() == typeId.VTime: vtime = vval.value() res += ": " + str(vtime.get_time()) elif vval.type() in [typeId.Char, typeId.Int16, typeId.UInt16, typeId.Int32, typeId.UInt32, typeId.Int64, typeId.UInt64]: res += ": " + str(vval.toString() + " - " + vval.toHexString()) elif vval.type() == typeId.Node: res += ": " + str(vval.value().absolute()) elif vval.type() in [typeId.Path, typeId.String, typeId.Bool]: res += ": " + str(vval.toString()) return res def fillList(self, spacer, vlist, res=""): x = self.consoleAttr.terminalSize() res += "\n" + (spacer * "\t") count = len(vlist) - 1 crop = False if self.maxitems != -1: cropbegidx = self.maxitems / 2 cropendidx = count - self.maxitems / 2 else: cropbegidx = -1 cropendidx = -1 idx = 0 xpos = len("\t" * spacer) for vval in vlist: if vval.type() == typeId.Map: vmap = vval.value() self.currentdepth -= 1 res += self.fillMap(spacer, vmap) self.currentdepth += 1 elif vval.type() == typeId.List: vvlist = vval.value() res += self.fillList(spacer, vvlist) else: vstr = "" if not crop: if vval.type == typeId.VTime: vtime = vval.value() vstr = str(vtime.get_time()) elif vval.type() == typeId.Node: vstr = str(vval.value().absolute()) elif vval.type() in [typeId.Path, typeId.String]: vstr = str(vval.toString()) else: vstr = str(vval.toString() + " - " + vval.toHexString()) if count: vstr += ", " xpos += len(vstr) if xpos > x - 20: res += "\n" + (spacer * "\t") + vstr xpos = len(spacer * "\t") + len(vstr) else: res += vstr if cropbegidx != -1 and idx == cropbegidx: crop = True res += "\n\n" + (spacer * "\t") + (" " * ((x - 20 - len(spacer * "\t")) / 2)) + "[...]" + "\n\n" + (spacer * "\t") xpos = len(spacer * "\t") if cropendidx != -1 and idx == cropendidx: crop = False count -= 1 idx += 1 return res dff-1.3.0+dfsg.1/dff/ui/gui/000077500000000000000000000000001217176075400153025ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/CMakeLists.txt000066400000000000000000000016111217176075400200410ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gui.py ${CMAKE_CURRENT_BINARY_DIR}/gui.py) install_file( __init__.py gui.py mainwindow.py translator.py ) add_subdirectory(resources) add_subdirectory(i18n) add_subdirectory(ide) add_subdirectory(utils) add_subdirectory(widget) add_subdirectory(dialog) dff-1.3.0+dfsg.1/dff/ui/gui/__init__.py000066400000000000000000000012111217176075400174060ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["gui", "widget", "dialog", "vfs", "ide", "utils", "resources", "translator", "wizard"] dff-1.3.0+dfsg.1/dff/ui/gui/dialog/000077500000000000000000000000001217176075400165415ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/dialog/CMakeLists.txt000066400000000000000000000012301217176075400212750ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Christophe Malinge install_file( __init__.py dialog.py preferences.py ) dff-1.3.0+dfsg.1/dff/ui/gui/dialog/__init__.py000066400000000000000000000010741217176075400206540ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["dialog"] dff-1.3.0+dfsg.1/dff/ui/gui/dialog/dialog.py000066400000000000000000000163141217176075400203570ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy Mounier # import os, sys, traceback from PyQt4.QtGui import QFileDialog, QMessageBox, QInputDialog, QDialog, QDialogButtonBox, QComboBox, QPushButton, QFormLayout, QHBoxLayout, QPixmap, QLabel, QApplication from PyQt4.QtCore import QObject, QString, SIGNAL, SLOT, Qt, QEvent, QDir from dff.api.vfs import vfs from dff.api.loader import loader from dff.api.taskmanager.taskmanager import TaskManager from dff.api.types.libtypes import typeId from dff.api.devices.devices import Devices from dff.api.gui.widget.devicesdialog import DevicesDialog from dff.api.gui.widget.layoutmanager import layoutManager from dff.ui.gui.dialog.preferences import Preferences from dff.ui.gui.resources.ui_about import Ui_About from dff.ui.gui.resources.ui_evidencedialog import Ui_evidenceDialog from dff.ui.gui.widget.modulesmanager import modulesManager, browserDialog class Dialog(QObject): def __init__(self, parent): QObject.__init__(self) self.parent = parent self.vfs = vfs.vfs() self.taskmanager = TaskManager() self.loader = loader.loader() def preferences(self): """Open a preferences dialog""" pref = Preferences(self.parent) ret = pref.exec_() if ret: pass def addDevices(self): """Open a device list dialog""" dev = DevicesDialog(self.parent) if dev.exec_(): self.addDevicesCreateProcess(dev) del dev def addDevicesCreateProcess(self, dev): if dev.selectedDevice: args = {} args["path"] = str(dev.selectedDevice.blockDevice()) args["parent"] = self.vfs.getnode("/Local devices") args["size"] = long(dev.selectedDevice.size()) exec_type = ["thread", "gui"] try: if os.name == "nt": args["name"] = str(dev.selectedDevice.model()) conf = self.loader.get_conf(str("devices")) genargs = conf.generate(args) self.taskmanager.add("devices", genargs, exec_type) except RuntimeError: err_type, err_value, err_traceback = sys.exc_info() err_trace = traceback.format_tb(err_traceback) err_typeval = traceback.format_exception_only(err_type, err_value) terr = QString() detailerr = QString() for err in err_trace: detailerr.append(err) for errw in err_typeval: terr.append(errw) detailerr.append(err) self.messageBox(terr, detailerr) def addFiles(self): """ Open a Dialog for select a file and add in VFS """ edialog = evidenceDialog(self.parent) ir = edialog.exec_() if ir > 0: self.addFilesCreateProcess(edialog) def addFilesCreateProcess(self, edialog): args = {} paths = edialog.manager.get("local") if edialog.rawcheck.isChecked(): module = "local" args["path"] = paths args["parent"] = self.vfs.getnode('/Logical files') elif edialog.ewfcheck.isChecked(): module = "ewf" args["files"] = paths args["parent"] = self.vfs.getnode('/Logical files') else: module = "aff" args["path"] = paths args["parent"] = self.vfs.getnode('/Logical files') self.conf = self.loader.get_conf(str(module)) try: genargs = self.conf.generate(args) self.taskmanager.add(str(module), genargs, ["thread", "gui"]) except RuntimeError: err_type, err_value, err_traceback = sys.exc_info() err_trace = traceback.format_tb(err_traceback) err_typeval = traceback.format_exception_only(err_type, err_value) terr = QString() detailerr = QString() for err in err_trace: detailerr.append(err) for errw in err_typeval: terr.append(errw) detailerr.append(err) self.messageBox(terr, detailerr) def messageBox(self, coretxt, detail): msg = QMessageBox() msg.setWindowTitle(self.tr("Error in configuration")) msg.setText(self.tr("An error was detected in the configuration")) msg.setInformativeText(coretxt) msg.setIcon(QMessageBox.Critical) msg.setDetailedText(detail) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def loadDriver(self): sFileName = QFileDialog.getOpenFileName(self.parent, self.parent.actionLoadModule.toolTip(), os.path.expanduser('~'), "Modules(*.py)") if (sFileName) : self.loader.do_load(str(sFileName.toUtf8())) def about(self): """ Open a About Dialog """ about = About() about.exec_() def manager(self): """ Open module browser dialog """ module = browserDialog(self.parent) ir = module.exec_() if ir > 0: module.browser.execute() class About(QDialog, Ui_About): def __init__(self): super(QDialog, self).__init__() self.setupUi(self) self.label.setText(self.label.text().arg(QApplication.instance().applicationVersion())) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.label.setText(self.label.text().arg(QApplication.instance().applicationVersion())) else: QDialog.changeEvent(self, event) class evidenceDialog(QDialog, Ui_evidenceDialog): def __init__(self, parent): super(QDialog, self).__init__() self.setupUi(self) self.loader = loader.loader() self.createShape() def createShape(self): """ Removes EWF if not in modules Set itemData for easy access without taking care of text (can be translated). TODO Futur : Get all DFF connectors """ if "ewf" not in self.loader.modules: self.ewfcheck.setEnabled(False) if "aff" not in self.loader.modules: self.affcheck.setEnabled(False) self.rawcheck.setChecked(True) self.manager = layoutManager() self.manager.addPathList("local", typeId.Path, [], []) self.pathlayout.addWidget(self.manager) def keyPressEvent(self, event): if self.parent(): self.parent().keyPressEvent(event) else: QDialog.keyPressEvent(self, event) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.label.setText(self.label.text().arg(QApplication.instance().applicationVersion())) else: QDialog.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/ui/gui/dialog/preferences.py000066400000000000000000000264011217176075400214170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # import sys from os import listdir, access, makedirs, R_OK, W_OK from os.path import normpath, dirname from PyQt4.QtGui import QDialog, QFileDialog, QMessageBox from PyQt4.QtCore import SIGNAL, QEvent, QString, Qt from dff.ui.gui.resources.ui_preferences import Ui_PreferencesDialog from dff.ui.conf import Conf from dff.ui.gui.translator import Translator class Preferences(QDialog, Ui_PreferencesDialog): def __init__(self, parent = None): """ Drives preferences Dialog TODO - Valide index settings are properly handle by indexer """ super(QDialog, self).__init__() # Set up the user interface from Qt Designer self.setupUi(self) self.translation() # Framework singleton classes self.conf = Conf() self.translator = Translator() # Temporary config, to be validated once submited self.tNoFootPrint = self.conf.noFootPrint self.tNoHistoryFile = self.conf.noHistoryFile self.tWorkPath = self.conf.workingDir self.tHistoryFileFullPath = self.conf.historyFileFullPath if self.conf.indexEnabled: self.tRootIndex = self.conf.root_index self.tIndexName = self.conf.index_name self.tIndexPath = self.conf.index_path else: idx = self.tabWidget.indexOf(self.indexTab) self.tabWidget.removeTab(idx) # Activate preferences from conf values self.noFootPrintCheckBox.setChecked(self.conf.noFootPrint) self.noHistoryCheckBox.setChecked(self.conf.noHistoryFile) self.footprintOrNo() self.workingDirPath.setText(self.conf.workingDir) self.historyLineEdit.setText(self.conf.historyFileFullPath) self.docAndHelpFullPath.setText(self.conf.docPath) # Populate languages comboBox with available languages, also set to current language self.langPopulate() # Signals handling self.connect(self.noFootPrintCheckBox, SIGNAL("stateChanged(int)"), self.noFootPrintChanged) self.connect(self.workingDirBrowse, SIGNAL("clicked()"), self.workDir) self.connect(self.historyToolButton, SIGNAL("clicked()"), self.historyDir) self.connect(self.noHistoryCheckBox, SIGNAL("stateChanged(int)"), self.historyStateChanged) self.connect(self.langComboBox, SIGNAL("currentIndexChanged (const QString&)"), self.langChanged) # Help configuration self.connect(self.docAndHelpBrowse, SIGNAL("clicked()"), self.helpDir) # Show or hide label helpers self.globalValid() self.helpValid() if parent: self.app = parent.app else: self.app = None # Catch submit to create directories if needed self.connect(self.buttonBox, SIGNAL("accepted()"), self.validate) self.connect(self.buttonBox, SIGNAL("rejected()"), self.clear) def validate(self): if not self.tNoFootPrint and not access(self.tWorkPath, R_OK): if QMessageBox.question(self, self.createDirTitle, self.createDirTitle + ':
' + self.tWorkPath + '?', QMessageBox.Yes, QMessageBox.No) == QMessageBox.No: return else: try: makedirs(self.tWorkPath, 0700) except OSError, e: QMessageBox.warning(self, self.createDirFail, self.createDirFail + ':
' + self.tWorkPath + '
' + e.strerror) return self.conf.workingDir = self.tWorkPath if self.tNoFootPrint != self.conf.noFootPrint: self.conf.noFootPrint = self.tNoFootPrint if not self.tNoFootPrint and self.conf.indexEnabled and not access(self.tIndexPath, R_OK): if QMessageBox.question(self, self.createDirTitle, self.createDirTitle + ':
' + self.tIndexPath + '?', QMessageBox.Yes, QMessageBox.No) == QMessageBox.No: return else: try: makedirs(self.tIndexPath, 0700) except OSError, e: QMessageBox.warning(self, self.createDirFail, self.createDirFail + ':
' + self.tIndexPath + '
' + e.strerror) return if self.conf.indexEnabled: self.conf.root_index = self.tRootIndex self.conf.index_name = self.tIndexName self.conf.index_path = self.tIndexPath self.conf.noHistoryFile = self.tNoHistoryFile if (not self.tNoHistoryFile and not self.tNoFootPrint) and self.tHistoryFileFullPath != self.conf.historyFileFullPath and access(dirname(self.tHistoryFileFullPath), W_OK): self.conf.historyFileFullPath = self.tHistoryFileFullPath elif (not self.tNoHistoryFile and not self.tNoFootPrint) and not access(dirname(self.tHistoryFileFullPath), W_OK): QMessageBox.warning(self, self.histWriteFail, self.histWriteFail + ':
' + self.tHistoryFileFullPath) return self.conf.save() self.accept() return def clear(self): self.reject() return def footprintOrNo(self): """ Enable or disable inputs which made changes on the system """ # Working dir related self.workingDirPath.setEnabled(not self.tNoFootPrint) self.workingDirLabel.setEnabled(not self.tNoFootPrint) self.workingDirBrowse.setEnabled(not self.tNoFootPrint) # History related self.noHistoryCheckBox.setEnabled(not self.tNoFootPrint) self.historyLineEdit.setEnabled(not self.tNoFootPrint and not self.tNoHistoryFile) self.historyLabel.setEnabled(not self.tNoFootPrint and not self.tNoHistoryFile) self.historyToolButton.setEnabled(not self.tNoFootPrint and not self.tNoHistoryFile) # Indexes related if self.conf.indexEnabled: self.indexTab.setEnabled(not self.tNoFootPrint) # Refresh label helpers self.globalValid() if self.conf.indexEnabled: self.indexValid() def workDir(self): """ Handle a new working directory """ f_dialog = self.fileDialog(self.conf.workingDir) if f_dialog.exec_(): self.workingDirPath.setText(f_dialog.selectedFiles()[0]) self.tWorkPath = f_dialog.selectedFiles()[0] if not access(self.conf.historyFileFullPath, R_OK): # History file does not exists and working dir has changed, update history path self.conf.historyFileFullPath = normpath(str(self.tWorkPath + '/history')) self.historyLineEdit.setText(self.conf.historyFileFullPath) if self.conf.indexEnabled and not access(self.tRootIndex, R_OK): # Index directory does not exists and working dir has changed, update index path self.tRootIndex = normpath(str(self.tWorkPath) + '/indexes/') self.tIndexPath = normpath(self.tRootIndex + '/' + self.tIndexName) self.root_index_line.setText(self.tRootIndex) self.globalValid() if self.conf.indexEnabled: self.indexValid() def historyDir(self): """ Handle a new history file """ f_dialog = self.fileDialog(self.tHistoryFileFullPath, QFileDialog.ExistingFile) if f_dialog.exec_(): self.historyLineEdit.setText(f_dialog.selectedFiles()[0]) self.tHistoryFileFullPath = f_dialog.selectedFiles()[0] def helpDir(self): """ Handle a new help.qhc file. Be carreful ; an help.qch file must also exists at the same directory level. """ f_dialog = self.fileDialog(self.conf.docPath, QFileDialog.ExistingFile) if f_dialog.exec_(): self.docAndHelpFullPath.setText(f_dialog.selectedFiles()[0]) self.conf.docPath = f_dialog.selectedFiles()[0] self.helpValid() def globalValid(self): """ Set labels 'path exists' or no in global tab. """ # No footprint. hide all help labels in this tab if self.tNoFootPrint: self.workDirWillCreate.setVisible(False) self.workDirOK.setVisible(False) return # Does working dir exists ? if access(self.tWorkPath, R_OK): self.workDirWillCreate.setVisible(False) self.workDirOK.setVisible(True) else: self.workDirWillCreate.setVisible(True) self.workDirOK.setVisible(False) def helpValid(self): """ Set label 'path exists' or no in help tab. """ if access(self.conf.docPath, R_OK): self.helpNOK.setVisible(False) self.helpOK.setVisible(True) else: self.helpNOK.setVisible(True) self.helpOK.setVisible(False) def langPopulate(self): translationPath = normpath(sys.modules['dff.ui.gui'].__path__[0] + '/i18n/') i = 0 selected = 0 for oneFile in listdir(translationPath): if oneFile.startswith('Dff_') and oneFile.endswith('.qm'): self.langComboBox.addItem(oneFile[len('Dff_'):-len('.qm')]) if self.conf.language == oneFile[len('Dff_'):-len('.qm')]: selected = i i += 1 self.langComboBox.setCurrentIndex(selected) def noFootPrintChanged(self, state): self.tNoFootPrint = (state == Qt.Checked) self.footprintOrNo() def historyStateChanged(self, state): self.tNoHistoryFile = (state == Qt.Checked) self.historyLabel.setEnabled((state == Qt.Unchecked)) self.historyLineEdit.setEnabled((state == Qt.Unchecked)) self.historyToolButton.setEnabled((state == Qt.Unchecked)) def langChanged(self, text): """ Change interface language Sets language in configuration singleton. Removes previous translator. Updates translator with new language. Installs translator using new language. """ self.conf.setLanguage(text) self.app.removeTranslator(self.translator.getGeneric()) self.app.removeTranslator(self.translator.getDFF()) self.translator.loadLanguage() self.app.installTranslator(self.translator.getGeneric()) self.app.installTranslator(self.translator.getDFF()) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.translation() self.retranslateUi(self) else: QDialog.changeEvent(self, event) def translation(self): self.createDirTitle = self.tr('Create directory') self.createDirFail =self.tr('Directory creation failure') self.histWriteFail = self.tr('History file is not writable') dff-1.3.0+dfsg.1/dff/ui/gui/gui.py000066400000000000000000000047251217176075400164500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # import sys from PyQt4.QtGui import QApplication, QSplashScreen, QPixmap from PyQt4.QtCore import Qt from dff.api.loader.loader import loader from dff.ui.gui.mainwindow import MainWindow from dff.ui.gui.translator import Translator from dff.ui.gui.resources import gui_rc from dff.ui.ui import UI class SplashScreen(QSplashScreen): def __init__(self, pixmap, windowFlag, versionNumber): QSplashScreen.__init__(self, pixmap, windowFlag) self.versionNumber = versionNumber def drawContents(self, painter): QSplashScreen.drawContents(self, painter) painter.drawText(10, 178, "Version " + str(self.versionNumber)) class GUI(QApplication, UI): def __init__(self, debug = False, verbosity = 0): """Launch GUI""" QApplication.__init__(self, sys.argv) UI.__init__(self, debug, verbosity) self.translator = Translator() self.installTranslator(self.translator.getGeneric()) self.installTranslator(self.translator.getDFF()) self.setApplicationName("Digital Forensics Framework") # Below are macros replaced by CMake using configure_file please don't # commit this file with macros replaced, view those macros definition # in the top level CMakeLists.txt self.setApplicationVersion("1.3.0") pixmap = QPixmap(":splash.png") self.splash = SplashScreen(pixmap, Qt.WindowStaysOnTopHint, self.applicationVersion()) self.splash.setMask(pixmap.mask()) def createMainWindow(self): return MainWindow(self, self.debug) def launch(self, modulesPaths = None): self.splash.show() if modulesPaths: self.loadModules(modulesPaths, self.splash.showMessage) self.mainWindow = self.createMainWindow() self.mainWindow.initDockWidgets() self.translator.loadLanguage() self.mainWindow.show() self.splash.finish(self.mainWindow) sys.exit(self.exec_()) dff-1.3.0+dfsg.1/dff/ui/gui/i18n/000077500000000000000000000000001217176075400160615ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/i18n/CMakeLists.txt000066400000000000000000000024761217176075400206320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Christophe Malinge # please keep the list of supported languages sorted alphabetically set(DFF_SUPPORTED_LANGUAGES "de" "en" "es" "fr" "it" "nl" "zh") # Please also take care of dff.pro file ! # Configure step execute_process(COMMAND ${PYTHON_QT4_LANGUAGE} -verbose "${CMAKE_CURRENT_SOURCE_DIR}/dff.pro") foreach(LANGUAGE ${DFF_SUPPORTED_LANGUAGES}) set(QM_OUTPUT_FILES ${QM_OUTPUT_FILES} "Dff_${LANGUAGE}.qm") # Build step add_custom_target(gui_translation_${LANGUAGE} ALL COMMAND ${QT_LANGUAGE_COMPILER} ${CMAKE_CURRENT_SOURCE_DIR}/Dff_${LANGUAGE}.ts -qm ${CMAKE_CURRENT_BINARY_DIR}/Dff_${LANGUAGE}.qm SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Dff_${LANGUAGE}.ts ) endforeach(LANGUAGE ${DFF_SUPPORTED_LANGUAGES}) install_file(${QM_OUTPUT_FILES}) dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_de.ts000066400000000000000000002635101217176075400176070ustar00rootroot00000000000000 About About Digital Forensics Framework Über Digital Forensics Framework <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> <b>Digital Forensics Framework</b> (version %1)<br><br> Falls Du Probleme hast, besuche bitte unsere <a href="http://wiki.digital-forensic.org/">Support Seiten</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> im Freenode Netzwerk.<br>Weitere Informationen: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software entwickelt von: <a href="http://arxsys.fr/">ArxSys</a> und <a href="https://tracker.digital-forensic.org/">der DFF Gemeinschaft</a>.<br> AddBookmark Add bookmark Lesezeichen hinzufügen Add a bookmark from the Virtual File System Lesezeichen vom virtuellen Dateisystem hinzufügen Create a new category neue Kategorie erstellen Category name: Kategoriename: Add in an existing category einer vorhandenen Kategorie hinzufügen ApplyModule Configuration error Konfigurationsfehler An error was detected in the configuration Es wurde ein Fehler in der Konfiguration gefunden AttributeCopyMenu copy kopiere AttributeSelectorMenu Select Auswählen Unselect Auswahl aufheben Select all alle auswählen Unselect all gesamte Auswahl aufheben AttributesSelectionDialog Dialog Dialog BookmarkManager Bookmark Lesezeichen You must specify at least one node. Mindestens ein Knoten muss ausgewählt sein. BrowserToolBar Tags Kennzeichnungen Search Suche Filter Filter attributes Attribute bookmark Lesezeichen Add nodes to bookmark Knoten zum Lesezeichen hinzufügen factorPlus Plus Icons zoom in Icons vergrößern factorMinus Minus Icons zoom out Icons verkleinern Toolbar Beweismittel Icons Symbole Details Details Edit the columns attributes of the detailed view Spaltenattribute der Dateil-Ansicht bearbeiten Browser Browser DevicesDialog Select Device Gerät auswählen Device Gerät Model Modell Size Größe Select a local device to add in the Virtual File System Wähle ein lokales Gerät zum Hinzufügen zum virtuellen Dateisystem aus Warning : You must run the software with Administrator rights Warnung: Das Programm muss mit Administrator-Rechten ausgeführt werden Block device name Name des Block-Gerätes Serial Seriennummer Dialog Error in configuration Konfigurationsfehler An error was detected in the configuration An error was detected in the configuration DicoManager Select your dictionnary Wörterbuch auswählen DockWidgetTitleBar Undock abkoppeln Close Schließen Disable this window Dieses Fenster deaktivieren Errors Errors Fehler ExtractDialog Extract Extrahiere Recursive mode Rekursiver Modus Destination folder: Ziel-Verzeichnis: Browse Durchsuchen Preserve tree Baumstruktur beibehalten Overwrite existing Bestehende Überschreiben Extractor Extraction path is mandatory Extraktions-Pfad ist erforderlich Choose the destination folder for extraction Zielverzeichnis für die Extraktion wählen Overwrite attempt Überschreibversuch Some selected files or folders already exist in the destination folder Einige der ausgewählten Dateien oder Verzeichnisse existieren bereits im Zielverzeichnis Overwrite with selected ones ? Mit den ausgewählten überschreiben? FileOrFolder File Datei Folder Verzeichnis Filter Error Fehler Please, specify a query name Bitte einen Abfrage-Namen angeben FindFile Find file Datei suchen Pattern: Muster: Syntax: Schreibweise: Regular expression Regulärer Ausdruck Fixed string feststehende Zeichenkette Wildcard Jokerzeichen Attribute: Attribute: Name Name Size Größe Date Datum Case sensitive sorting Groß-/Kleinschreibungs abhängiges Sortieren Case sensitive filter Groß- und Kleinschreibung beachtendes Filtern Form Form Formular OR Oder AND UND NOT NICHT name Name contains beinhaltet date Datum mime MIME-Typ Wildcard Jokerzeichen Regular expression Regulärer Ausdruck Fuzzy unscharf Fixed string feststehende Zeichenkette Help Help Hilfe It might mean that the format of your help file is not correct. Es scheint, dass das Format der Hilfe-Dateien nicht korrekt ist. You can check on-line help at http://wiki.digital-forensic.org Du kannst in der Online-Hilfe unter http://wiki.digital-forensic.org nachschlagen Error while loading help Fehler beim Laden der Hilfe An error occurred while setting help engine up : Ein Fehler trat beim Einrichten der Hilfe auf: Ide IDE IDE IDE toolbar IDE Symbolleiste New empty file Neue leere Datei Generate skeleton Erzeuge Gerüst Open file Datei öffnen Save Speichern Save as Speichern unter Load Laden Undo Rückgängig Redo Wiederherstellen Comment Kommentieren Uncomment Auskommentieren Save document ? Dokument speichern? No file found Keine Datei gefunden Save file as Datei speichern unter IdeWizard Integrated Development Environment Wizard Assistent für die Intergrierte Entwicklungsumgebung General Informations Allgemeine Informationen Fill all script information such as name, type and saving location. Alle Informationen zum Skript wie Name, Typ und Speicherort ausfüllen. Name: Name: Category: Kategorie: Work location: Arbeitsverzeichnis: Browse Durchsuchen Type: Typ: Script Skript Graphical Grafisch Driver Treiber Description Beschreibung Describe here the goal of the module Beschreibe die Funktion des Moduls Module's description Modulbeschreibung Author informations Autor Informationen Fill all author's informations in order to complete header Fülle die Angaben zum Autor zur Vervollständigung der Kopfzeilen aus Author's first name: Vorname des Autors: Author's last name: Nachname des Autors: Author's electronic mail: E-Mail des Autors: Location Standort Interpreter Python interpreter Python interpreter Python Interpreter Python interpreter IsDeleted No Nein Yes Ja ItemValueDialog Attribute value Attribut-Werte Attribute Attribute Value: Wert: MainWindow File Datei Exit Beenden Load Laden Open evidence file(s) Öffne Beweismitteldatei(en) Open local device Öffne lokales Gerät Digital Forensics Framework Digital Forensics Framework Edit Bearbeiten Module Module IDE IDE Preferences Einstellungen ? ? View Ansicht Maximize Maximieren Fullscreen mode Vollbild Modus Shell Shell Browser Browser Python interpreter Python interpreter Load module Modul laden Open Öffnen Toolbar Toolbar About DFF ... Über DFF ... DFF Documentation DFF Dokumentation Error while loading help Fehler beim Laden der Hilfe <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. <br>Du kannst die Online-Hilfe auf <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a> aufsuchen. Not an help file. keine Hilfedatei. Documentation path not found. Pfad zur Dokumentation nicht gefunden. Browse Durchsuchen Preview Vorschau Open evidence Beweismittel öffnen Open device Gerät öffnen Console Konsole Live scripting Live Scripting Documentation Dokumentation Open the IDE IDE öffnen MenuManager Empty files leere Dateien the following nodes could not be opened with Hex viewer because they are either empty or folders Die folgenden Knoten konnten nicht mit dem Hex-Betrachter geöffnet werden, da diese entweder leer oder Verzeichnisse sind Extraction Error Fehler bei der Extraktion An issue occured while extracting Während der Extraktion trat ein Problem auf Module already applied Dieses Modul wurde bereits ausgeführt This module was already applied with the same configuration ! Do you want to apply it again ? Dieses Modul wurde bereits mit dieser Einstellung ausgeführt! Möchtest Du es erneut ausführen? Apply module Modul anwenden Do you want to apply module Modul on this node ? auf diesen Knoten anwenden? Always Immer Modules Modules Module Name Name Key Schlüssel Value Wert Info Info Type Typ NodeFBox Quick search: Schnellsuche: Search recursively Rekursiv suchen Advanced search Erweiterte Suche Index options Index-Optionen Launch quick search Starte Schnellsuche Output Output Ausgabe Preferences Create directory Erstelle Verzeichnis Directory creation failure Erstellung des Verzeichnisses fehlgeschlagen History file is not writable History-Datei ist nicht schreibbar PreferencesDialog Preferences Einstellungen Global Allgemein History Historie History file full path: vollständiger Pfad zum History-Datei: No history file keine History-Datei No footprint Kein Speichern von Daten auf der Festplatte Language Sprache Interface language Sprache der Oberfläche Use interface language: verwende folgende Sprache für die Oberfläche: Indexation Indexierung Index files location Ort der Index-Dateien Root index Stammverzeichnis für den Index Browse Durchsuchen Index name Indexname Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. Bitte Verzeichnis für die Speicherung der Index-Dateien auswählen. Falls das Verzeichnis nicht existiert wird es erstellt, wenn die Änderungen angewandt werden. Working environment Arbeitsumgebung DFF user directory: DFF Benutzerverzeichnis: Help and documentation Hilfe und Dokumentation Full path of the help and documentation file: Vollständiger Pfad zur Hilfe und Dokumentationsdatei: Help and documentation settings Hilfe und Dokumentationseinstellungen Provided path does not exists, will ask for creation on submit. Das angegebene Verzeichnis existiert nicht, es wird nach der Erzeugung gefragt, wenn die Änderungen angewandt werden. Provided path is a readable directory. Das angegebene Verzeichnis ist ein lesbares Verzeichnis. Please provide an help.qhc file along with an help.qch file at same directory level. Bitte die Dateien help.qhc und help.qch in der Verzeichnisebene bereitstellen. Provided path is not a readable file. Das angegebene Verzeichnis ist nicht lesbar. Provided path is a readable file. Das angegebene Verzeichnis ist ein lesbares Verzeichnis. Preview Preview Vorschau Processus Fail Fehlgeschlaggen Finish Beendet Running In Arbeit PropertyTable name Name folder Verzeichnis file Datei generated by erstellt von size Größe relevant module(s) relevante(s) Modul(e) node type Knotentyp attributes Attribute children kind-knoten file(s) Datei(en) bytes Bytes folder(s) Verzeichnis(se) totalizing summiert with module(s) applied on it mit darauf angewanden Modul(en) empty leer deleted gelöscht link path Verknüpfungspfad SearchPanel Error Fehler Please, specify your query Bitte Abfrage spezifizieren SearchThread Error Fehler Error compiling query Fehler bei Erstellung der Abfrage SelectAttributesWiz Select attributes Eigenschaften auswählen Attribute selection location Eigenschaften auswählen Select attributes from Eigenschaften auswählen von Current list Aktuelle Liste Current selected file Aktuell ausgewählte Datei All selected files Alle ausgewählten Dateien Group attributes by Eigenschaften gruppieren nach Types Typen Generated module erstellt durch Modul Generating attribute list Erzeugte Liste der Eigenschaften Shell Shell Shell Welcome to DFF shell Willkommen auf der DFF-Shell TagManagerDialog Warning Warnung No nodes was selected in the browser. Es waren keine Knoten im Browser ausgewählt. No tags was selected in the available tags list. Keine Auswahl aus der Liste der verfügbaren Kennzeichnungen getroffen. No tags was selected in the selected nodes tags list. Keine Kennzeichnung(en) aus der Liste vorhandenen Kennzeichnungen der selektierten Knoten ausgewählt. Are you sure ? This will delete this tag for all nodes in the VFS ! Bist Du sicher? Diese Kennzeichnungen wird für alle Knoten im VFS entfernt! This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Dies ist eine Standard-Kennzeichnung. Sie kann nicht gelöscht werden. Bei den betroffenen VFS-knoten wurde die Kennzeichnung entfernt. Tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Kennzeichnungen von selektierten Knoten hinzufügen und entfernen Neue Kennzeichnungen hinzufügen oder bestehende entfernen (Doppleklick zum Editieren) Tags management Verwaltung der Kennzeichnungen Selected nodes tags Kennzeichnung(en) von selektierten Knoten Available tags Verfügbare Kennzeichnungen TaskManager PID PID Name Name State Status Info Info Exec Time Ausführungsdauer Task Manager Task Manager Duration Dauer TreeModel Name Name VariantTreeWidget Key Schlüssel Value Wert Attribute Attribute applyModule Apply module Modul anwenden Informations Informationen Module Modul Type Typ Arguments Argumente Activate Aktiviert Description Beschreibung dicoManager Form Formular Dictionnary manager Wörterbuch-Manager Add dictionnary Wörterbuch hinzufügen Remove dictionnary Verzeichnis entfernen Location Ablageort Dictionnary's name Bezeichnung des Wörterbuchs edittag Name : Name : Default Standard set color Farbe festlegen Edit tag Kennzeichnung bearbeiten evidenceDialog Select evidence type Wähle Typ des Beweismittels Add evidence directory Füge Beweismittelverzeichnis hinzu Add evidence files Füge Beweismitteldateien hinzu Open local files or directory Öffne lokale Dateien oder Verzeichnisse RAW format RAW-Format EWF format EWF-Format AFF Format filterAdd Dialog Dialog Create your custom filter eigenen Filter erstellen Filter name Name des Filters Add custom filter queries eigene Filter hinzufügen filterAttributes Form Formular filterBar Form Formular filterConjunction Form Formular And Und And not UND NICHT Or Oder Or not ODER NICHT filterDico Form Formular Name Name Content Inhalt Any Irgendein All Alles None keines filterFields Form Formular Name Name Contains Beinhaltet Size Größe Date Datum Mime type MIME-Typ Dictionnary Wörterbuch Is deleted ist gelöscht Is file ist eine Datei Attribute Attribute filterMatchMode Form Formular Wildcard Jokerzeichen Reg-exp Regulärer Ausdruck Fuzzy unscharf Fixed feststehende Zeichenkette Case sensitive Groß- und Kleinschreibung beachten filterMime Form Formular Select ... Auswählen ... filterMimeDialog Dialog Dialog filterMode Form Formular Filter activated Filter aktiviert 11 Found gefunden filterOnly Form Formular True Wahr False Falsch filterOperators Form Formular Is less than ist kleiner als Is less than or equal to ist kleiner als oder gleich Is equal to ist gleich Is not equal to ist ungleich Is greater than or equal to ist größer als oder gleich Is greater than ist größer als filterTagwidget Form Formular Exclude Ausschließen filterWidget Form Formular 0 0 / / Custom query Eigene Abfrage Tags Kennzeichnungen ... ... Stop filter Stopp-Filter Clear filter Filter löschen Clear Löschen Wildcard Jokerzeichen Fuzzy unscharf Reg exp Regulärer Ausdruck Fixed feststehende Zeichenkette layoutManager File Datei Directory Verzeichnis moduleBrowser Module browser Modul-Browser moduleGeneratorWidget Module Module Informations Informationen Arguments Argumente Activate Aktiviert Description Beschreibung moduleShapeGenerator Configuration error Konfigurationsfehler An error was detected in the configuration Es wurde ein Fehler in der Konfiguration gefunden nodeActions Browser Browser Open in new tab In einem neuen Tab öffnen Open Öffnen Open with Öffnen mit Hex viewer Hex-Betrachter Extract Extrahiere Relevant module relevante Module Bookmark Lesezeichen Add nodes to bookmark Knoten zum Lesezeichen hinzufügen Open parent folder übergeordnetes Verzeichnis öffnen Tags Kennzeichnungen Tag nodes Kennzeichnungsknoten procMB Results Ergebnisse No results keine Ergebnisse Provided Arguments übergebene Argumente Processus Information Prozess Information Output Ausgabe Error Fehler searchCustomTable Form Formular ... ... Query name Name der Abfrage Enabled Aktiviert Query Abfrage searchPanel Form Formular Quick search Schnellsuche Wildcard Jokerzeichen Regexp Regulärer Ausdruck Fuzzy unscharf Fixed feststehende Zeichenkette Custom eigene Types : Typen: ... ... Advanced search Erweiterte Suche Options Optionen Search from root Suche vom Wurzelverzeichnis starten 0 0 Start Start Stop Stopp Found gefunden selectionActions Browser Browser Select all alle auswählen Unselect all gesamte Auswahl aufheben Clear selection Lösche Auswahl selectionMenu Selection Auswahl tagMenu Manage tags Kennzeichnungen verwalten dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_en.ts000066400000000000000000002550741217176075400176270ustar00rootroot00000000000000 About About Digital Forensics Framework <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> AddBookmark Add bookmark Add a bookmark from the Virtual File System Create a new category Category name: Add in an existing category ApplyModule Configuration error An error was detected in the configuration AttributeCopyMenu copy AttributeSelectorMenu Select Unselect Select all Unselect all AttributesSelectionDialog Dialog BookmarkManager Bookmark You must specify at least one node. BrowserToolBar Tags Search Filter attributes bookmark Add nodes to bookmark factorPlus Icons zoom in factorMinus Icons zoom out Icons Details Edit the columns attributes of the detailed view Browser DevicesDialog Select Device Device Model Size Select a local device to add in the Virtual File System Warning : You must run the software with Administrator rights Block device name Serial Dialog Error in configuration An error was detected in the configuration DicoManager Select your dictionnary DockWidgetTitleBar Undock Close Disable this window Errors Errors ExtractDialog Extract Recursive mode Destination folder: Browse Preserve tree Overwrite existing Extractor Extraction path is mandatory Choose the destination folder for extraction Overwrite attempt Some selected files or folders already exist in the destination folder Overwrite with selected ones ? FileOrFolder File Folder Filter Error Please, specify a query name FindFile Find file Pattern: Syntax: Regular expression Fixed string Wildcard Attribute: Name Size Date Case sensitive sorting Case sensitive filter Form Form OR AND NOT name contains date mime Wildcard Regular expression Fuzzy Fixed string Help Help It might mean that the format of your help file is not correct. You can check on-line help at http://wiki.digital-forensic.org Error while loading help An error occurred while setting help engine up : Ide IDE IDE toolbar New empty file Generate skeleton Open file Save Save as Load Undo Redo Comment Uncomment Save document ? No file found Save file as IdeWizard Integrated Development Environment Wizard General Informations Fill all script information such as name, type and saving location. Name: Category: Work location: Browse Type: Script Graphical Driver Description Describe here the goal of the module Module's description Author informations Fill all author's informations in order to complete header Author's first name: Author's last name: Author's electronic mail: Location Interpreter Python interpreter Python Interpreter IsDeleted No Yes ItemValueDialog Attribute value Attribute Value: MainWindow File Exit Load Digital Forensics Framework Edit Module IDE Preferences ? View Maximize Fullscreen mode Browser Load module Toolbar About DFF ... Error while loading help <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. Not an help file. Documentation path not found. Browse Open evidence Open device Console Live scripting Documentation Open the IDE MenuManager Empty files the following nodes could not be opened with Hex viewer because they are either empty or folders Extraction Error An issue occured while extracting Module already applied This module was already applied with the same configuration ! Do you want to apply it again ? Apply module Do you want to apply module on this node ? Always Modules Modules Name Key Value Info Type NodeFBox Quick search: Search recursively Advanced search Index options Launch quick search Output Output Preferences Create directory Directory creation failure History file is not writable PreferencesDialog Preferences Global History History file full path: No history file No footprint Language Interface language Use interface language: Indexation Index files location Root index Browse Index name Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. Working environment DFF user directory: Help and documentation Full path of the help and documentation file: Help and documentation settings Provided path does not exists, will ask for creation on submit. Provided path is a readable directory. Please provide an help.qhc file along with an help.qch file at same directory level. Provided path is not a readable file. Provided path is a readable file. Preview Preview Processus Fail Finish Running PropertyTable name folder file generated by size relevant module(s) node type attributes children file(s) bytes folder(s) totalizing with module(s) applied on it empty deleted link path SearchPanel Error Please, specify your query SearchThread Error Error compiling query SelectAttributesWiz Select attributes Attribute selection location Select attributes from Current list Current selected file All selected files Group attributes by Types Generated module Generating attribute list Shell Shell Welcome to DFF shell TagManagerDialog Warning No nodes was selected in the browser. No tags was selected in the available tags list. No tags was selected in the selected nodes tags list. Are you sure ? This will delete this tag for all nodes in the VFS ! This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Tags management Selected nodes tags Available tags TaskManager PID Name State Info Task Manager Duration TreeModel Name VariantTreeWidget Value Attribute applyModule Apply module Informations Module Type Arguments Activate Description dicoManager Form Dictionnary manager Add dictionnary Remove dictionnary Location Dictionnary's name edittag Name : Default set color Edit tag evidenceDialog Select evidence type Add evidence directory Add evidence files Open local files or directory RAW format EWF format AFF Format filterAdd Create your custom filter Filter name Add custom filter queries filterAttributes Form filterBar Form filterConjunction Form And And not Or Or not filterDico Form Name Content Any All None filterFields Form Name Contains Size Date Mime type Dictionnary Is deleted Is file Attribute filterMatchMode Form Wildcard Reg-exp Fuzzy Fixed Case sensitive filterMime Form Select ... filterMimeDialog Dialog filterMode Form Filter activated 11 Found filterOnly Form True False filterOperators Form Is less than Is less than or equal to Is equal to Is not equal to Is greater than or equal to Is greater than filterTagwidget Form Exclude filterWidget Form 0 / Custom query Tags ... Stop filter Clear filter Clear Wildcard Fuzzy Reg exp Fixed layoutManager File Directory moduleBrowser Module browser moduleGeneratorWidget Module Informations Arguments Activate Description moduleShapeGenerator Configuration error An error was detected in the configuration nodeActions Browser Open in new tab Open Open with Hex viewer Extract Relevant module Bookmark Add nodes to bookmark Open parent folder Tags Tag nodes procMB Results No results Provided Arguments Processus Information Output Error searchCustomTable Form ... Query name Enabled Query searchPanel Form Quick search Wildcard Regexp Fuzzy Fixed Custom Types : ... Advanced search Options Search from root 0 Start Stop Found selectionActions Browser Select all Unselect all Clear selection selectionMenu Selection tagMenu Manage tags dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_es.ts000066400000000000000000003542301217176075400176260ustar00rootroot00000000000000 About About Digital Forensics Framework Acerca de Digital Forensics Framework <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> <b>Digital Forensics Framework</b> (version %1)<br><br>Si tiene problemas, por favor visite nuestra <a href="http://wiki.digital-forensic.org/">página de soporte</a>.<br>Canal IRC: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> en la red Freenode.<br>Más información: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software desarrollado por <a href="http://arxsys.fr/">ArxSys</a> y <a href="https://tracker.digital-forensic.org/">la comunidad DFF</a>.<br> AddBookmark Add bookmark Agregar marcador Add a bookmark from the Virtual File System Agregar un marcador desde el Sistema Virtual de Archivos (VFS) Create a new category Crear nueva categoría Category name: Nombre de la categoría: Add in an existing category Agregar a una categoría existente AdvSearch match(s) coincidencia(s) current match(s): coincidencia(s) actual(es): Invalid clause Cláusula no válida Field Campo Clause Cláusula ApplyModule Configuration error An error was detected in the configuration AttributeCopyMenu copy AttributeSelectorMenu Select Unselect Select all Seleccionar todo Unselect all AttributesSelectionDialog Dialog BookmarkManager Bookmark You must specify at least one node. Debe especificar al menos un nodo. BrowserToolBar Tags Search Filter attributes atributos bookmark Add nodes to bookmark factorPlus Icons zoom in factorMinus Icons zoom out Toolbar Barra de herramientas Icons Ãconos Details Edit the columns attributes of the detailed view Browser Navegador BuildSearchClause Contains Contiene Name does not contain Nombre no contiene Name contains Nombre contiene From dictionnary Desde diccionario Does not contain No contiene Size at least Tamaño al menos Size at most Tamaño a lo sumo Date less than Fecha anterior a Date most than Fecha posterior a Deleted Borrado Type Tipo Mime-type Tipo MIME Extended attributes Atributos extendidos Build a search clause Armar una cláusula de búsqueda Add Agregar Add extended attributes Agregar atributos extendidos Clause(s) Cláusula(s) From dictionary Desde diccionario DevicesDialog Select Device Seleccionar dispositivo Device Dispositivo Model Modelo Size Tamaño Select a local device to add in the Virtual File System Seleccione un dispositivo local para agregar al Sistema Virtual de Archivos Warning : You must run the software with Administrator rights Atención: debe correr la aplicación con permisos de Adminitrador Block device name Nombre del dispositivo de bloques Serial Nro. Serie Dialog Error in configuration An error was detected in the configuration DicoManager Select your dictionnary DictListEdit Edit dictionnary Editar diccionario Edit dictionary Editar diccionario DockWidgetTitleBar Undock Close Disable this window Errors Errors Errores ExtractDialog Extract Extraer Recursive mode Modo recursivo Destination folder: Carpeta destino: Browse Navegar Preserve tree Overwrite existing Extractor Extraction path is mandatory El directorio de extracción es obligatorio Choose the destination folder for extraction Elija la carpeta destino para extraer Overwrite attempt Intento de sobre-escritura Some selected files or folders already exist in the destination folder Algunos archivos o directorios seleccionados ya existen en el directorio destino Overwrite with selected ones ? Sobreescribir con los elegidos? FileOrFolder File Archivo Folder Carpeta Filter Error Please, specify a query name FindFile Find file Encontrar archivo Pattern: Patrón: Syntax: Sintaxis: Regular expression Expresión regular Fixed string Cadena fija Wildcard Comodín Attribute: Atributo: Name Nombre Size Tamaño Date Fecha Case sensitive sorting Ordenamiento sensible a mayúsculas y minúsculas Case sensitive filter Filtro sensible a mayúsculas y minúsculas Form Form OR AND NOT name nombre contains date mime Wildcard Comodín Regular expression Expresión regular Fuzzy Fixed string Cadena fija Help Help It might mean that the format of your help file is not correct. You can check on-line help at http://wiki.digital-forensic.org Error while loading help Error al cargar la ayuda An error occurred while setting help engine up : Ide IDE IDE IDE toolbar Barra de herramientas del IDE New empty file Nuevo archivo vacío Generate skeleton Generar esqueleto Open file Abrir archivo Save Guardar Save as Guardar como Load Cargar Undo Deshacer Redo Rehacer Comment Comentar Uncomment Descomentar Save document ? Guardar documento? No file found No se encontró archivo Save file as Guardar archivo como IdeWizard Integrated Development Environment Wizard Asistente del Entorno Integrado de Desarrollo General Informations Información general Fill all script information such as name, type and saving location. Complete toda la información de la secuencia de comandos como nombre, tipo y ubicación de salvado. Name: Nombre: Category: Categoría: Work location: Ubicación de trabajo: Browse Navegar Type: Tipo: Script Secuencia de comandos Graphical Gráfico Driver Controlador Description Descripción Describe here the goal of the module Describa aquí el objetivo del módulo Module's description Descripción del módulo Author informations Información del autor Fill all author's informations in order to complete header Llene toda la información del autor para completar el encabezado Author's first name: Nombre del autor: Author's last name: Apellido del autor: Author's electronic mail: Correo electrónico del Autor: Location Ubicación Interpreter Python interpreter Intérprete Python Python Interpreter Intérprete Python IsDeleted No No Yes Sí ItemValueDialog Attribute value Attribute Value: ListNodeModel Name Nombre Size Tamaño Accessed time Fecha accedido Changed time Fecha cambiado Modified time Fecha modificado Module Módulo Deleted Borrado MainWindow File Archivo Exit Salir Load Cargar Open evidence file(s) Abrir archivo(s) de evidencia Open local device Abrir dispositivo local Digital Forensics Framework Digital Forensics Framework Edit Editar Module Módulo IDE IDE Preferences Preferencias ? ? Shell Línea de comandos View Ver Maximize Maximizar Fullscreen mode Modo pantalla completa Browser Navegador Python interpreter Intérprete Python Load module Cargar Módulos Open Abrir Toolbar Barra de herramientas About DFF ... Acerca de DFF ... DFF Documentation Documentación de DFF Error while loading help Error al cargar la ayuda <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. <br>Puede revisar la ayuda en línea en <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. Not an help file. No es un archivo de ayuda. Documentation path not found. No se encontró la ruta de la ayuda. Browse Navegar Preview Vista previa Open evidence Open device Console Live scripting Documentation Open the IDE MenuManager Empty files Vaciar archivos the following nodes could not be opened with Hex viewer because they are either empty or folders los siguientes nodos no pueden abrirse con el Visor hexadecimal porque están vacíos o son carpetas Extraction Error An issue occured while extracting Module already applied This module was already applied with the same configuration ! Do you want to apply it again ? Apply module Aplicar módulo Do you want to apply module Quiere aplicar el módulo on this node ? en este nodo? Always Siempre MimeType Select Mime type Seleccione el tipo Mime Select one or several mime-types Seleccionar uno o varios tipos Mime ModifIndex Index content Contenido del índice Select the directories you wish to index. Changes will take effect when you click on 'OK' Seleccione los directorios que quiere indexar. Los cambios tendrán efecto al hacer click en OK Select nodes Seleccionar nodos Indexed items Items indexados Advanced Avanzado Attributes list Lista de atributos Select which nodes' attributes you wish to index. Seleccione que atributos de los nodos quiere indexar. File type Tipo de archivo Select what types of nodes you wish to index. Seleccione que tipo de nodos quiere indexar. Mime types Tipos Mime Options Opciones Index file content Contenido del archivo de índice Index attributes Atributos del índice Indexer options Opciones del indexador Modules Modules Módulos Name Nombre Key Clave Value Valor Info Información Type Tipo NodeBrowser Open in new tab Abrir en una nueva pestaña Open Abrir Open with Abrir con Hex viewer Visor hexadecimal Extract Extraer Browser Navegador Relevant module Módulo relevante Apply module Aplicar módulo Do you want to apply module Quiere aplicar el módulo on this node ? en este nodo? Always Siempre Empty files Vaciar archivos the following nodes could not be opened with Hex viewer because they are either empty or folders los siguientes nodos no pueden abrirse con el Visor hexadecimal porque están vacíos o son carpetas NodeFBox Quick search: Búsqueda rápida: Search recursively Buscar recursivamente Advanced search Búsqueda avanzada Index options Opciones de índices Launch quick search Lanzar búsqueda rápida NodeViewBox Previous Previo Return to root Regresar a raíz Add to bookmarks Agregar a marcadores Display search engine Mostrar motor de búsqueda List Lista Icons Ãconos Small Pequeño Medium Mediano Large Grande Attributes Atributos Next Siguiente Move to top Mover al tope Activate thumbnails Activar miniaturas You must specify at least one node. Debe especificar al menos un nodo. Attributes selection Selección de atributos View as Ver como Icon size Tamaño de íconos Show attributes panel Mostrar panel de atributos OptWidget Remove Quitar OrAnd Or O And Y Output Output Salida Preferences Create directory Crear directorio Directory creation failure Error en la creación del directorio History file is not writable No se puede escribir en archivo histórico PreferencesDialog Preferences Preferencias Global Global History Historia History file full path: Ruta completa archivo histórico: No history file No hay archivo histórico No footprint No hay huella Language Idioma Interface language Idioma de la interfase Use interface language: Usar idioma de interfase: Indexation Indexación Index files location Ubicación archivos de índices Root index Ãndice raíz Browse Navegar Index name Nombre índice Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. Por favor seleccione en qué directorio quiere guardar los archivos de índices. Si ese directorio no existe será creado cuando se apliquen los cambios. Working environment Entorno de trabajo DFF user directory: Directorio de usuario DFF: Help and documentation Ayuda y documentación Full path of the help and documentation file: Ruta completa al archivo de ayuda y documentación: Help and documentation settings Configuración de ayuda y documentación Provided path does not exists, will ask for creation on submit. La ruta indicada no existe, se pedirá crearla al confirmar. Provided path is a readable directory. La ruta provista es un directorio de solo lectura. Please provide an help.qhc file along with an help.qch file at same directory level. Por favor provee un archivo help.qhc con un archivo help.qhc en el mismo nivel de directorio. Provided path is not a readable file. La ruta provista no es un archivo que se pueda leer. Provided path is a readable file. La ruta provista es un archivo que se puede leer. Preview Preview Vista previa Processus Fail Finish Running PropertyTable name nombre file archivo folder carpeta generated by generado por size tamaño relevant module(s) módulo(s) relevante(s) with module(s) applied on it con módulo(s) aplicado(s) a él empty vacío deleted borrado children hijos file(s) archivo(s) totalizing totalizando bytes bytes folder(s) carpeta(s) node type tipo de nodo attributes atributos link path SearchClause Or O And Y Remove Quitar SearchDict Edit dictionnary Editar diccionario Edit dictionary Editar diccionario SearchEmpty Empty Vacío Not empty No vacío SearchPanel Error Please, specify your query SearchS Kilo byte(s) Kilobyte(s) Mega byte(s) Megabyte(s) Giga byte(s) Gigabyte(s) SearchSize Byte(s) Byte(s) Kilo byte(s) Kilobyte(s) Mega byte(s) Megabyte(s) Giga byte(s) Gigabyte(s) Exclusive Exclusive Inclusive Inclusive SearchStr Case sensitive Sensible a mayúsculas SearchTab Check all results Marcar todos los resultados Select all Seleccionar todo Export Exportar Attributes Atributos Search options Opciones de búsqueda Path Ruta Name contains Nombre contiene Case sensitive Sensible a mayúsculas Add search clause Agregar cláusula de búsqueda Resulting search clause Cláusula de búsqueda resultante match(s) coincidencia(s) Stop Detener Find Encontrar Advanced search Búsqueda avanzada Search queries Buscar consultas SearchThread Error Error compiling query SelectAttr Select attributes to display Seleccione atributos a mostrar Attributes selection : add an attributes to display in the node browser Selección de atributos: agregar un atributo a mostrar en el navegador de nodos Dynamic attributes Atributos dinámicos Data types Tipos de datos Display module name Mostrar nombre del módulo Sort by deleted Ordenar por borrado Attributes selection : add an attribute to display in the node browser Selección de atributos: agregar un atributo a mostrar en el navegador de nodos SelectAttributesWiz Select attributes Attribute selection location Select attributes from Current list Current selected file All selected files Group attributes by Types Generated module Generating attribute list SelectMimeTypes Select one or several mime-types Seleccionar uno o varios tipos Mime Shell Shell Línea de comandos Welcome to DFF shell Bienvenido a la línea de comandos de DFF TagManagerDialog Warning No nodes was selected in the browser. No tags was selected in the available tags list. No tags was selected in the selected nodes tags list. Are you sure ? This will delete this tag for all nodes in the VFS ! This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Tags management Selected nodes tags Available tags TaskManager PID PID Name Nombre State Estado Info Información Exec Time Tiempo Exec Task Manager Administrador de Tareas Duration TreeModel Name Nombre VFSItemModel Name Nombre Size Tamaño Accessed time Fecha accedido Changed time Fecha cambiado Modified time Fecha modificado Module Módulo Deleted Borrado VariantTreeWidget Key Clave Value Valor Attribute applyModule Apply module Aplicar módulo Informations Información Module Módulo Type Tipo Arguments Argumentos Activate Activar Description Descripción dicoManager Form Dictionnary manager Add dictionnary Remove dictionnary Location Ubicación Dictionnary's name edittag Name : Default set color Edit tag evidenceDialog Select evidence type Seleccione el tipo de evidencia Add evidence directory Agregar directorio de evidencia Add evidence files Agregar archivos de evidencia Open local files or directory Abrir directorio o archivos locales RAW format Formato RAW EWF format Formato EWF AFF Format Formato AFF filterAdd Create your custom filter Filter name Add custom filter queries filterAttributes Form filterBar Form filterConjunction Form And Y And not Or O Or not filterDico Form Name Nombre Content Any All None filterFields Form Name Nombre Contains Contiene Size Tamaño Date Fecha Mime type Dictionnary Is deleted Is file Attribute filterMatchMode Form Wildcard Comodín Reg-exp Fuzzy Fixed Case sensitive Sensible a mayúsculas filterMime Form Select ... filterMimeDialog Dialog filterMode Form Filter activated 11 Found filterOnly Form True False filterOperators Form Is less than Is less than or equal to Is equal to Is not equal to Is greater than or equal to Is greater than filterTagwidget Form Exclude filterWidget Form 0 / Custom query Tags ... Stop filter Clear filter Clear Wildcard Comodín Fuzzy Reg exp Fixed layoutManager File Archivo Directory moduleBrowser Module browser moduleGeneratorWidget Module Módulo Informations Información Arguments Argumentos Activate Activar Description Descripción moduleShapeGenerator Configuration error An error was detected in the configuration nodeActions Browser Navegador Open in new tab Abrir en una nueva pestaña Open Abrir Open with Abrir con Hex viewer Visor hexadecimal Extract Extraer Relevant module Módulo relevante Bookmark Add nodes to bookmark Open parent folder Tags Tag nodes procMB Results Resultados No results Sin resultados Provided Arguments Argumentos provistos Processus Information Información de los procesos Output Salida Error searchCustomTable Form ... Query name Enabled Query searchPanel Form Quick search Wildcard Comodín Regexp Fuzzy Fixed Custom Types : ... Advanced search Búsqueda avanzada Options Opciones Search from root 0 Start Stop Detener Found selectionActions Browser Navegador Select all Seleccionar todo Unselect all Clear selection selectionMenu Selection tagMenu Manage tags dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_fr.ts000066400000000000000000003614521217176075400176320ustar00rootroot00000000000000 About About Digital Forensics Framework À propos de Digital Forensics Framework <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> <b>Digital Forensics Framework</b> (version %1)<br><br>Au moindre problème, veuillez s&apos;il vous plaît visiter notre <a href="http://wiki.digital-forensic.org/">page de support</a>.<br>Salon de discussion IRC : <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> sur le réseau Freenode.<br>Plus d&apos;informations : <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Logiciel développé par <a href="http://arxsys.fr/">ArxSys</a> et <a href="https://tracker.digital-forensic.org/">la communauté DFF</a>.<br> AddBookmark Add bookmark Ajouter un favoris Add a bookmark from the Virtual File System Ajouter un favoris depuis le Système de Fichier Virtuel Create a new category Créer une nouvelle catégorie Category name: Nom de la catégorie : Add in an existing category Ajouter dans une catégorie existante AdvSearch match(s) correspondance(s) current match(s): correspondance(s) trouvée(s) : Invalid clause Clause invalide Field Champ Clause Clause ApplyModule Configuration error Erreur de configuration An error was detected in the configuration Une erreur a été détectée dans la configuration AttributeCopyMenu copy copier AttributeSelectorMenu Select Sélectionner Unselect Désélectionner Select all Sélectionner tout Unselect all Désélectionner tout AttributesSelectionDialog Dialog Dialog BookmarkManager Bookmark Bookmark You must specify at least one node. Vous devez sélectionner au moins un nÅ“ud. BrowserToolBar Tags Tags Search Recherche Filter Filtre attributes attributs bookmark bookmark Add nodes to bookmark Ajouter les noeuds au bookmark factorPlus factorPlus Icons zoom in Agrandir les icônes factorMinus factorMinus Icons zoom out Rétrécir les icônes Toolbar Barre d'outils Icons Icônes Details Détail Edit the columns attributes of the detailed view Modifier les attributs des colonnes de la vue détaillée Nodes browser Navigateur Browser Navigateur BuildSearchClause Contains Contient Name does not contain Nom ne contient pas Name contains Nom contient From dictionnary Depuis dictionnaire Does not contain Ne contient pas Size at least Taille au moins Size at most Taille au plus Date less than Date au moins Date most than Date au plus Deleted Effacé Type Type Mime-type Type Mime Extended attributes Attributs étendus Build a search clause Construction d'une clause de recherche Add Ajouter Add extended attributes Ajout d'attribut étendu Clause(s) Clause(s) From dictionary Depuis dictionnaire DevicesDialog Select Device AJouter un périphérique local Device Périphérique Model Modèle Size Taille Select a local device to add in the Virtual File System Ajoutez un périphérique dans le système de fichier virtuel Warning : You must run the software with Administrator rights Attention : Vous devez avoir les droits Administrateur Block device name Nom Serial Numéro de série Dialog Error in configuration Erreur dans la configuration An error was detected in the configuration Une erreur a été détectée dans la configuration DicoManager Select your dictionnary Sélectionnez votre dictionnaire DictListEdit Edit dictionnary Édition du dictionnaire Edit dictionary Édition du dictionnaire DockWidgetTitleBar Undock Désancrer Close Fermer Disable this window Désactiver cette fenêtre Errors Errors Erreurs ExtractDialog Extract Extraire Recursive mode Mode récursif Destination folder: Répertoire de destination : Browse Parcourir Preserve tree Conserver l'arboresecence Overwrite existing Ecraser les fichiers Extractor Extraction path is mandatory Répertoire d'extraction obligatoire Choose the destination folder for extraction Choisir le répertoire de destination pour l'extraction Overwrite attempt Tentative d'écrasement Some selected files or folders already exist in the destination folder Certains fichiers ou répertoires existent déjà dans le répertoire de destination Overwrite with selected ones ? Écraser avec l'élément sélectionné ? FileOrFolder File Fichier Folder Répertoire Filter Error Erreur Please, specify a query name Veuillez,spécifier un nom de requête FindFile Find file Chercher un élément Pattern: Motif : Syntax: Syntaxe : Regular expression Expression régulière Fixed string Chaîne fixe Wildcard Wildcard Attribute: Attribut : Name Nom Size Taille Date Date Case sensitive sorting Tri sensible à la casse Case sensitive filter Filtre sensible à la casse Form Form Formulaire OR OU AND ET NOT NON name nom contains contient date date mime mime Wildcard Wildcard Regular expression Expression régulière Fuzzy Approximatif Fixed string Chaîne fixe Help Help Aide It might mean that the format of your help file is not correct. Ceci pourrait signifier que le format de votre fichier d'aide n'est pas correct. You can check on-line help at http://wiki.digital-forensic.org Vous pouvez vérifier l'aide en ligne sur http://wiki.digital-forensic.org Error while loading help Erreur durant le chargement de l'aide An error occurred while setting help engine up : Une erreur s'est produite lors de la mise en place du moteur d'aide : Ide IDE IDE IDE toolbar Barre d'outils IDE New empty file Nouveau fichier vide Generate skeleton Générer un squelette Open file Ouvrir un fichier Save Sauvegarder Save as Sauvegarder sous Load Charger Undo Annuler Redo Rétablir Comment Commenter Uncomment Décommenter Save document ? Sauvegarder le document ? No file found Aucun fichier trouvé Save file as Sauvegarder le fichier sous IdeWizard Integrated Development Environment Wizard Assitant de l'Environnement de Développement Intégré General Informations Informations générales Fill all script information such as name, type and saving location. Remplissez tous les champs au sujet du script tels que son nom, son type et sa destination pour l'enregistrement. Name: Nom : Category: Catégorie : Work location: Répertoire de travail : Browse Parcourir Type: Type : Script Script Graphical Graphique Driver Pilote Description Description Describe here the goal of the module Décrire ici l'objectif du module Module's description Description du module Author informations Informations sur l'auteur Fill all author's informations in order to complete header Remplissez tous les champs au sujet de l'auteur afin de compléter l'en-tête Author's first name: Prénom de l'auteur : Author's last name: Nom de l'auteur : Author's electronic mail: Adresse électronique de l'auteur : Location Destination Interpreter Python interpreter Interpréteur Python Python Interpreter Interpréteur Python IsDeleted No Non Yes Oui ItemValueDialog Attribute value Valeur de l'attribut Attribute Attribut Value: Valeur: ListNodeModel Name Nom Size Taille Accessed time Date d'accès Changed time Date de changement Modified time Date de modification Module Module Deleted Effacé MainWindow File Fichier Exit Quitter Load Charger Open evidence file(s) Ouvrir un ou plusieurs fichier(s) Open local device Ouvrir un périphérique local Digital Forensics Framework Digital Forensics Framework Edit Édition Module Module IDE IDE Preferences Préférences ? ? View Vue Maximize Maximizer Fullscreen mode Mode plein écran Shell Ligne de commande Python interpreter Interpréteur Python Browser Navigateur Load module Charger un module Open Ouvrir Toolbar Barre d'outils About DFF ... À propos de DFF ... DFF Documentation Documentation de DFF Error while loading help Erreur durant le chargement de l'aide <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. <br>Vous pouvez consulter l'aide en ligne sur <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. Not an help file. N'est pas un fichier d'aide. Documentation path not found. Chemin non trouvé. Browse Parcourir Preview Prévisualisation Open evidence Ouvrir un conteneur Open device Ouvrir un périphérique Console Console Live scripting Interpreteur python Documentation Documentation Open the IDE Ouvrir l'IDE MenuManager Empty files Fichiers vides the following nodes could not be opened with Hex viewer because they are either empty or folders les nÅ“uds suivants ne peuvent être ouverts avec le visualiseur hexadécimal car ce sont des répertoires ou ils sont vides Extraction Error Erreur d'extraction An issue occured while extracting Un problème s'est produit lors de l'extraction Module already applied Module déjà appliqué This module was already applied with the same configuration ! Do you want to apply it again ? Ce module a déjà été appliquée avec la même configuration ! Voulez-vous l'appliquer à nouveau? Apply module Appliquer le module Do you want to apply module Voulez-vous appliquer le module on this node ? sur ce noeud ? Always Toujours MimeType Select Mime type Sélectionner le type Mime Select one or several mime-types Sélectionner un ou plusieurs types Mimes ModifIndex Index content Contenu de l'index Select the directories you wish to index. Changes will take effect when you click on 'OK' Sélectionner les répertoires devant être indexés. Les changement prennent effet une fois cliqué sur 'OK' Select nodes Sélectionner les nÅ“uds Indexed items Éléments indexés Advanced Avancé Attributes list Liste des attributs Select which nodes' attributes you wish to index. Sélectionner les attributs internes aux nÅ“uds à indexer. File type Type de fichier Select what types of nodes you wish to index. Sélectionner le type de nÅ“ud à indexer. Mime types Type Mime Options Options Index file content Indexer le contenu des fichiers Index attributes Indexer les attributs Indexer options Options de l'indexation Modules Modules Modules Name Nom Key Clé Value Valeur Info Informations Type Type NodeBrowser Open in new tab Ouvrir dans un nouvel onglet Open Ouvrir Open with Ouvrir avec Hex viewer Visualiseur hexadécimal Extract Extraire Browser Navigateur Relevant module Module conseillé Apply module Application de module Do you want to apply module Voulez-vous appliquer le module on this node ? sur ce noeud ? Always Toujours Empty files Fichiers vides the following nodes could not be opened with Hex viewer because they are either empty or folders les nÅ“uds suivants ne peuvent être ouverts avec le Visualiseur hexadécimal car ce sont des répertoires ou ils sont vides NodeFBox Quick search: Recherche rapide : Search recursively Rechercher récursivement Advanced search Recherche avancée Index options Options de l'indexation Launch quick search Lancer la recherche rapide NodeViewBox Previous Précédent Return to root Revenir à la racine Add to bookmarks Ajouter aux favoris Display search engine Afficher le moteur de recherche List Liste Icons Icônes Small Petit Medium Moyen Large Grand Next Suivant Move to top Répertoire parent Activate thumbnails Activer les imagettes You must specify at least one node. Vous devez sélectionner au moins un nÅ“ud. Attributes selection Sélection des attributs View as Type de vue Icon size Taille des icônes Show attributes panel Afficher la fenêtre d'attributs OptWidget Remove Effacer OrAnd Or Ou And Et Output Output Sortie Preferences Create directory Créer un répertoire Directory creation failure Problème lors de la création d'un répertoire History file is not writable Le fichier d'historique n'est pas accessible en écriture PreferencesDialog Preferences Préférences Global Globale History Historique History file full path: Chemin du fichier d'historique : No history file Pas de fichier d'historique No footprint Aucune empreinte Language Langage Interface language Langue de l'interface Use interface language: Langue à utiliser : Indexation Indexation Index files location Emplacement des fichiers d'index Root index Index racine Browse Parcourir Index name Nom de l'index Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. Sélectionner s'il vous plaît l'emplacement dans lequel vous souhaitez sauvegarder les fichier d'index. Si ces répertoires n'existent pas ils seront créés une fois les changements appliqués. Working environment Environement de travail DFF user directory: Répertoire utilisateur DFF : Help and documentation Aide et documentation Full path of the help and documentation file: Chemin complet du fichier d'aide et de documentation : Help and documentation settings Paramètres de l'aide et de la documentation Provided path does not exists, will ask for creation on submit. Le chemin fourni n'existe pas, demande de création une fois validé. Provided path is a readable directory. Le chemin fourni est un répertoire accessible en lecture. Please provide an help.qhc file along with an help.qch file at same directory level. Renseignez, s'il vous plaît, le chemin du fichier help.qhc, un second fichier nommé help.qch doit exister au même endroit. Provided path is not a readable file. Le chemin fourni n'est pas un fichier accessible en lecture. Provided path is a readable file. Le chemin fourni est un fichier accessible en lecture. Preview Preview Prévisualisation Processus Fail Echec Finish Terminé Running En fonctionnement PropertyTable name nom file fichier folder répertoire generated by généré par size taille relevant module(s) module(s) conseillé(s) with module(s) applied on it avec modules appliqué dessus empty vide deleted effacé children fils file(s) fichier(s) totalizing totalisant bytes octets folder(s) répertoire(s) node type type de nÅ“ud attributes attributs link path Chemin du lien SearchClause Or Ou And Et Remove Effacer SearchDict Edit dictionnary Édition du dictionnaire Edit dictionary Édition du dictionnaire SearchEmpty Empty Vide Not empty Non-vide SearchPanel Error Erreur Please, specify your query Veuillez,spécifier un nom de requête SearchS Kilo byte(s) Kilo octet(s) Mega byte(s) Méga octet(s) Giga byte(s) Giga octet(s) SearchSize Byte(s) Octet(s) Kilo byte(s) Kilo octet(s) Mega byte(s) Méga octet(s) Giga byte(s) Giga octet(s) Exclusive Exclure Inclusive Inclure SearchStr Case sensitive Sensible à la casse SearchTab Check all results Sélectionner tous les résultats Select all Sélectionner tout Export Exporter Attributes Attributs Search options Options Path Chemin Name contains Nom contient Case sensitive Sensible à la casse Add search clause Ajouter une clause de recherche Resulting search clause Clause de recherche match(s) correspondance(s) Stop Stopper Find Rechercher Advanced search Recherche avancée Search queries Requêtes de recherche SearchThread Error Erreur Error compiling query Erreur dans la compilation de la requête SelectAttr Select attributes to display Sélectionner les attributs à afficher Attributes selection : add an attributes to display in the node browser Sélection d'attributs : ajouter un attribut à afficher dans le navigateur Dynamic attributes Attributs dynamiques Data types Type de données Display module name Afficher le nom du module Sort by deleted Tri fonction des éléments effacés Attributes selection : add an attribute to display in the node browser Sélection d'attributs : ajouter un attribut à afficher dans le navigateur SelectAttributesWiz Select attributes Sélectionnez les attributs Attribute selection location Sélection de la locatisation des attributs Select attributes from Sélectionnez les attributs de Current list Liste actuelle Current selected file Le fichier sélectionné actuellement All selected files Tous les fichiers sélectionnés Group attributes by Grouper les attributes par Types Types Generated module Généré par les modules Generating attribute list Générer la liste d'attributs SelectMimeTypes Select one or several mime-types Sélectionner un ou plusieurs types Mimes Shell Shell Ligne de commande Welcome to DFF shell Bienvenue dans l'interface en ligne de commande DFF TagManagerDialog Warning Attention No nodes was selected in the browser. Aucun noeud n'a été sélectionné dans le navigateur. No tags was selected in the available tags list. Aucun tags n'a été sélectionné dans la liste de balise disponible. No tags was selected in the selected nodes tags list. Aucun tags n'a été sélectionné dans la liste des tags disponibles. This is a default tags it cannot be deleted. All concerned VFS nodes was untagged. Ceci est une balise par default il ne peut être suprimer.Toutes les autre balises on été detagger. Are you sure ? This will delete this tag for all nodes in the VFS ! Etes-vous sûr? Ceci supprimera tous les tags pour tous les noeuds du VFS ! This is a default tags it cannot be deleted. All tagged VFS nodes was untagged. Ceci est un tag par default il ne peut être suprimer.Toutes les tags des noeuds du VFS on était supprimer. This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Ceci est un tag par défaut, il ne peut être supprimé.Tous les tags des noeuds du VFS ont été supprimé. Tags Tag management Gestion des tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Ajoute et enlève des tags pour les noeuds sélectionnés Créer de nouveaux tags ou supprimer ceux déjà existants. (Double-clickez pour modifier) Tags management Gestion des tags Selected nodes tags Tags des noeuds sélectionnés Available tags Tags disponibles TaskManager PID Processus Name Nom State État Info Informations Exec Time Temps d'execution Task Manager Gestionnaire des tâches Duration Durée TreeModel Name Nom VFSItemModel Name Nom Size Taille Accessed time Date d'accès Changed time Date de changement Modified time Date de modification Module Module Deleted Effacé VariantTreeWidget Key Clé Value Valeur Attribute Attribut applyModule Apply module Appliquer un module Informations Informations Module Module Type Type Arguments Arguments Activate Activer Description Description dicoManager Form Formulaire Dictionnary manager Gestion de dictionnaire Add dictionnary Ajouter un dictionnaire Remove dictionnary Enlever un dictionnaire Location Emplacement Dictionnary's name Nom des dictionnaires edittag Name : Nom : Default Defaut set color Définir la couleur Edit tag Modifier la balise evidenceDialog Select evidence type Sélectionnez le type de données Add evidence directory Ajouter un répertoire Add evidence files Ajouter un ou plusieurs fichiers Open local files or directory Ouvrir des fichiers ou répertoires locaux RAW format Fichiers brut (RAW) EWF format Fichiers EWF AFF Format Fichiers AFF filterAdd Dialog Dialog Create your custom filter Créer un filtre personnalisé Filter name Nom du filtre Add custom filter queries filterAttributes Form Formulaire filterBar Form Formulaire filterConjunction Form Formulaire And Et And not Et non Or Ou Or not Ou non filterDico Form Formulaire Name Nom Content Contenu Any N'importe lequel All Tous None Aucun filterFields Form Formulaire Name Nom Contains Contient Size Taille Date Date Mime type Mime type Dictionnary Dictionnaire Is deleted Est supprimé Is file Est un fichier Attribute Attribut filterMatchMode Form Formulaire Wildcard Joker Reg-exp Reg-exp Fuzzy Fuzzy Fixed Fixe Case sensitive Sensible à la casse filterMime Form Formulaire Select ... Sélectionner ... filterMimeDialog Dialog Dialog filterMode Form Formulaire Filter activated Filtre activé 11 11 Found Trouvé filterOnly Form Formulaire True Vrai False Faux filterOperators Form Formulaire Is less than Est inférieur à Is less than or equal to Est inférieur ou égale à Is equal to Est égal à Is not equal to N'est pas égal à Is greater than or equal to Est supérieur ou égal à Is greater than Est supérieur à filterTagwidget Form Formulaire Exclude Exclure filterWidget Form Formulaire 0 0 / / Quick (wildcard) Rapide (wildcard) Quick (fuzzy) Rapide (fuzzy) Quick (reg exp) Rapide (regex) Quick (fixed) Rapide (fixe) Custom query Requête personnalisée Tags Tags ... ... Stop filter Arrêtez de filtrer Clear filter Supprimer le filtre Clear Supprimer Wildcard Wildcard Fuzzy Fuzzy Reg exp Reg exp Fixed Fixe layoutManager File Fichier Directory Dossier moduleBrowser Module browser Navigateur de modules moduleGeneratorWidget Module Module Informations Informations Arguments Arguments Activate Activer Description Description moduleShapeGenerator Configuration error Erreur de configuration An error was detected in the configuration Une erreur a été détectée dans la configuration nodeActions Browser Navigateur Open in new tab Ouvrir dans un nouvel onglet Open Ouvrir Open with Ouvrir avec Hex viewer Visualiseur hexadécimal Extract Extraire Relevant module Module conseillé Bookmark Bookmark Add nodes to bookmark Ajouter les noeuds au bookmark Open parent folder Ouvrir le dossier parent Tags Tags Tag nodes Tag les noeuds procMB Results Résultats No results Aucun résultat Provided Arguments Arguments fournis Processus Information Information sur le processus Output Sortie Fail Echec Finish Terminer Error Erreur searchCustomTable Form Formulaire ... ... Query name Nom de la requête Enabled Activer Query Requête searchPanel Form Formulaire Quick search Recherche rapide Wildcard Wildcard Regexp Regexp Fuzzy Fuzzy Fixed Fixe Custom Personnalisée Types : Types : ... ... Advanced search Recherche avancée Options Options Search from root Rechercher depuis la racine 0 0 Start Démarrer Stop Arrêter Found Trouvé sel Running En fonctionnement selectionActions Browser Navigateur Select all Sélectionner tout Unselect all Désélectionner tout Clear selection Effacer la sélection selectionMenu Selection Sélection tagMenu Manage tags Gestion des tags dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_it.ts000066400000000000000000003457031217176075400176400ustar00rootroot00000000000000 About About Digital Forensics Framework Informazioni su Digital Forensics Framework <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> <b>Digital Forensics Framework</b> (versione %1)<br><br>Per qualsiasi problema ti invitiamo a visitare la nostra <a href="http://wiki.digital-forensic.org/">pagina di supporto</a>.<br>Canale IRC: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> sulla rete Freenode.<br>Ulteriori informazioni: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software sviluppato da <a href="http://arxsys.fr/">ArxSys</a> e <a href="https://tracker.digital-forensic.org/">La DFF community</a>.<br> AddBookmark Add bookmark Aggiungi Segnalibro Add a bookmark from the Virtual File System Aggiungi un segnalibro da File System Virtuale Create a new category Crea una nuova categoria Category name: Nome Categoria: Add in an existing category Aggiungi a categoria esistente AdvSearch match(s) Corrispondenze Invalid clause Clausola non valida Field Campi Clause Clausola ApplyModule Configuration error An error was detected in the configuration AttributeCopyMenu copy AttributeSelectorMenu Select Unselect Select all Seleziona tutti Unselect all AttributesSelectionDialog Dialog BookmarkManager Bookmark You must specify at least one node. Devi specificare almeno un nodo BrowserToolBar Tags Search Filter attributes attributi bookmark Add nodes to bookmark factorPlus Icons zoom in factorMinus Icons zoom out Toolbar Barra degli strumenti Icons Icone Details Edit the columns attributes of the detailed view Browser Browser BuildSearchClause Contains Contiene Name does not contain Il nome non contiene Name contains Il nome contiene Does not contain Non contiene Size at least La dimensione è almeno di Size at most La dimensione è al massimo di Date less than Data precedente a Date most than Data successiva a Deleted Cancellato Type Tipo Mime-type Mime-Type Extended attributes Attributi estesi Build a search clause Crea un nuovo criterio di ricerca Add Aggiungi Add extended attributes Aggiungi attributi estesi Clause(s) Criteri From dictionary Da dizionario DevicesDialog Select Device Seleziona Dispositivo Select a local device to add in the Virtual File System Seleziona un dispositivo locale da aggiungere nel File System Virtuale Warning : You must run the software with Administrator rights Attenzione: Il software richiede privilegi amministrativi per funzionare correttamente Device Dispositivo Block device name Nome del Block device Model Modello Serial Numero di serie Size Dimensione Dialog Error in configuration An error was detected in the configuration DicoManager Select your dictionnary DictListEdit Edit dictionary Modifica dizionario DockWidgetTitleBar Undock Close Disable this window Errors Errors Errori ExtractDialog Extract Estrai Recursive mode Modo ricorsivo Destination folder: Cartella di destinazione: Browse Sfoglia Preserve tree Overwrite existing Extractor Extraction path is mandatory Il percorso di estrazione è obbligatorio Choose the destination folder for extraction Seleziona il percorso di estrazione Overwrite attempt Tentativo di sovrascrittura Some selected files or folders already exist in the destination folder Alcuni file o cartelle sono già presenti nel percorso di destinazione Overwrite with selected ones ? Sovrascrivere con quelli selezionati ? FileOrFolder File File Folder Directory Filter Error Please, specify a query name FindFile Find file Trova File Pattern: Modello: Syntax: Sintassi: Regular expression Espressione regolare Fixed string Stringa prefissata Wildcard Wildcard Attribute: Attributo: Name Nome Size Dimensione Date Data Case sensitive sorting Ordinamiento case sensitive Case sensitive filter Filtro Case sensitive Form Form OR AND NOT name nome contains date mime Wildcard Wildcard Regular expression Espressione regolare Fuzzy Fixed string Stringa prefissata Help Help It might mean that the format of your help file is not correct. You can check on-line help at http://wiki.digital-forensic.org Error while loading help Errore nel caricamento della guida An error occurred while setting help engine up : Ide IDE IDE IDE toolbar Strumenti IDE New empty file Nuovo file vuoto Generate skeleton Genera Scheletro Open file Apri file Save Salva Save as Salva come Load Apri Undo Annulla Redo Rifai Comment Commenta Uncomment Decommenta Save document ? Salvare il documento ? No file found Nessun file trovato Save file as Salva file come IdeWizard Integrated Development Environment Wizard Wizard Dell'Ambiente di sviluppo General Informations Informazioni generali Fill all script information such as name, type and saving location. Compila tutte le informazioni relative allo script come ad esempio il nome, il tipo e dove vuoi che venga salvato. Name: Nome: Category: Categoria: Work location: Posizione di lavoro: Browse Sfoglia Type: Tipo: Script Script Graphical Graphical Driver Driver Description Descrizione Describe here the goal of the module Descrivi qui lo scopo del modulo Module's description Descrizione del modulo Author informations Informazioni sull'autore Fill all author's informations in order to complete header Inserisci tutte le informazioni relative all'autore per completare l'intestazione Author's first name: Author's first name: Author's last name: Nome dell'autore: Author's electronic mail: Indirizzo Email: Location Luogo Interpreter Python interpreter Interprete Python Python Interpreter Interprete Python IsDeleted No No Yes sì ItemValueDialog Attribute value Attribute Value: ListNodeModel Name Nome Size Dimensione Accessed time Accessed time Changed time Changed time Modified time Modified time Module Modulo Deleted Cancellato MainWindow Digital Forensics Framework Digital Forensics Framework File File Module Modulo IDE IDE ? ? Edit Modifica View Visualizza Toolbar Barra degli strumenti About DFF ... Informazioni su DFF ... Load Apri Load module Apri modulo Open evidence file(s) Apri File Immagine Open local device Apri dispositivo locale Exit Esci Preferences Preferenze Maximize Ingrandisci Fullscreen mode Modalità schermo intero Browser Browser Shell Shell Python interpreter Interprete Python DFF Documentation Documentazione su DFF Open Apri Error while loading help Errore nel caricamento della guida <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. <br>Potete consultare la guida online all'indirizzo <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. Not an help file. Non è un file della guida. Documentation path not found. Percorso contenente la documentazione non trovato. Browse Sfoglia Preview Anteprime Open evidence Open device Console Live scripting Documentation Open the IDE MenuManager Empty files File vuoti the following nodes could not be opened with Hex viewer because they are either empty or folders I seguenti nodi non possono essere visualizzati con l'editor esadecimale perchè sono vuoti o cartelle Extraction Error An issue occured while extracting Module already applied This module was already applied with the same configuration ! Do you want to apply it again ? Apply module Applica modulo Do you want to apply module Vuoi eseguire il modulo on this node ? su questo nodo ? Always Sempre MimeType Select one or several mime-types Seleziona uno o più MIME-types ModifIndex Index content Contenuto dell'indice Select the directories you wish to index. Changes will take effect when you click on 'OK' Seleziona le directory che desideri indicizzare. Le modifiche avranno effetto quando cliccherai su 'OK' Select nodes Seleziona nodi Indexed items Elementi indicizzati Advanced Avanzate Attributes list Lista degli attributi Select which nodes' attributes you wish to index. Seleziona quali nodi degli attributi desideri indicizzare File type Tipo di file Select what types of nodes you wish to index. Seleziona quali tipi di nodi desideri indicizzare Mime types Mime types Options Opzioni Index file content Contenuto del file degli indice Index attributes Attributi dell'indice Indexer options Opzioni di indicizzazione Modules Modules Moduli Name Nome Key Chiave Value Valore Info Informazioni Type Tipo NodeBrowser Browser Browser Open in new tab Apri in una nuova scheda Open Apri Open with Apri con Hex viewer Editor Esadecimale Extract Esporta Relevant module Moduli di interesse Apply module Applica modulo Do you want to apply module Vuoi eseguire il modulo on this node ? su questo nodo ? Always Sempre Empty files File vuoti the following nodes could not be opened with Hex viewer because they are either empty or folders I seguenti nodi non possono essere visualizzati con l'editor esadecimale perchè sono vuoti o cartelle NodeFBox Quick search: Ricerca rapida Search recursively Ricerca ricursivamente Advanced search Ricerca avanzata Index options Opzioni di indicizzazione Launch quick search Avvia ricerca rapida NodeViewBox Previous Precedente Next Successivo Move to top Sposta in cima Return to root Torna alla radice List Lista Icons Icone Attributes Attributi Add to bookmarks Aggiungi ai preferiti Display search engine Visualizza motore di ricerca Activate thumbnails Attiva anteprime Small Piccole Medium Medie Large Grandi You must specify at least one node. Devi specificare almeno un nodo Attributes selection Selezione attributi View as Visualizza come Icon size Dimensione icona Show attributes panel Visualizza pannello attributi OptWidget Remove Rimuovi OrAnd Or Oppure And E Output Output Output Preferences Create directory Crea directory Directory creation failure Creazione della directory fallita History file is not writable Il file della cronologia non è accessibile in scrittura PreferencesDialog Preferences Preferenze Global Generali Working environment Ambiente di lavoro No footprint Nessun footprint DFF user directory: DFF utenti directory: Browse Sfoglia Provided path does not exists, will ask for creation on submit. Il percorso specificato non esiste, vi verrà richiesto di crearlo al termine dell'operazionet. Provided path is a readable directory. Il percorso specificato è una directory accessibile. History Cronologia History file full path: Percorso completo file cronologia: No history file Nessun file cronologia Language Lingua Interface language Lingua Interfaccia Use interface language: Seleziona lingua interfaccia: Indexation Indicizzazione Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. Per cortesia scegli in quale directory vuoi salvare il file degli indici. Se la directory non esiste questa verrà creata automaticamente. Index files location Percorso file degli indici Root index Indice radice Index name Nome Indice Help and documentation Aiuto e documentazione Help and documentation settings Impostazioni per la documentazione Full path of the help and documentation file: Percorso completo per il file della documentazione: Please provide an help.qhc file along with an help.qch file at same directory level. Per cortesia specifica un file help.qhc assieme a un file help.qch e assicurati che si trovino nella stessa directory. Provided path is not a readable file. Il percorso specificato punta ad un file non accessibile. Provided path is a readable file. Il percorso specificato punta ad un file accessibile. Preview Preview Anteprima Processus Fail Finish Running PropertyTable name nome node type tipo nodo file file with module(s) applied on it con i moduli applicati su di esso folder cartella empty vuoto deleted cancellato generated by creato da size dimensione relevant module(s) moduli di interesse children figli file(s) file totalizing totalizzante bytes bytes folder(s) cartella(e) attributes attributi link path SearchClause Or Oppure And E Remove Rimuovi SearchDict Edit dictionary Modifica dizionario SearchEmpty Empty Vuoto Not empty Non vuoto SearchPanel Error Please, specify your query SearchSize Exclusive Escludendo Inclusive Includendo SearchStr Case sensitive Case sensitive SearchTab Check all results Seleziona tutti i risultati Select all Seleziona tutti Export Esporta Attributes Attributi Search options Opzioni di ricerca Path Percorso Name contains Il nome contiene Case sensitive Case sensitive Add search clause Aggiungi criterio di ricerca Resulting search clause Criterio di ricerca risultante match(s) Corrispondenze Stop Ferma Find Trova Advanced search Ricerca avanzata Search queries Query di ricerca SearchThread Error Error compiling query SelectAttr Select attributes to display Seleziona gli attributi da visualizzare Dynamic attributes Attributi dinamici Data types Tipi di dato Display module name Visualizza il nome del modulo Sort by deleted Ordina per cancellati/non cancellati Attributes selection : add an attribute to display in the node browser Selezione attributi : aggiungi un attributo da visualizzare nel browser dei nodi SelectAttributesWiz Select attributes Attribute selection location Select attributes from Current list Current selected file All selected files Group attributes by Types Generated module Generating attribute list Shell Shell Shell Welcome to DFF shell Benvenuti nella DFF shell TagManagerDialog Warning No nodes was selected in the browser. No tags was selected in the available tags list. No tags was selected in the selected nodes tags list. Are you sure ? This will delete this tag for all nodes in the VFS ! This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Tags management Selected nodes tags Available tags TaskManager Task Manager Gestore Attività PID PID Name Nome State Stato Info Info Exec Time Tempo di esecuzione Duration TreeModel Name Nome VFSItemModel Name Nome Size Dimensione Accessed time Accessed time Changed time Changed time Modified time Modified time Module Moduli Deleted Cancellato VariantTreeWidget Key Chiave Value Valore Attribute applyModule Apply module Applica modulo Informations Informazioni Module Modulo Type Tipo Arguments Argomenti Activate Attiva Description Descrizione dicoManager Form Dictionnary manager Add dictionnary Remove dictionnary Location Luogo Dictionnary's name edittag Name : Default set color Edit tag evidenceDialog Select evidence type Seleziona il tipo di evidence Open local files or directory Apri file o directory locali RAW format RAW formato EWF format EWF formato Add evidence directory Aggiungi una evidence directory Add evidence files Aggiungi degli evidence file AFF Format filterAdd Create your custom filter Filter name Add custom filter queries filterAttributes Form filterBar Form filterConjunction Form And E And not Or Oppure Or not filterDico Form Name Nome Content Any All None filterFields Form Name Nome Contains Contiene Size Dimensione Date Data Mime type Dictionnary Is deleted Is file Attribute filterMatchMode Form Wildcard Wildcard Reg-exp Fuzzy Fixed Case sensitive Case sensitive filterMime Form Select ... filterMimeDialog Dialog filterMode Form Filter activated 11 Found filterOnly Form True False filterOperators Form Is less than Is less than or equal to Is equal to Is not equal to Is greater than or equal to Is greater than filterTagwidget Form Exclude filterWidget Form 0 / Custom query Tags ... Stop filter Clear filter Clear Wildcard Wildcard Fuzzy Reg exp Fixed layoutManager File File Directory moduleBrowser Module browser moduleGeneratorWidget Module Informations Informazioni Arguments Argomenti Activate Attiva Description Descrizione moduleShapeGenerator Configuration error An error was detected in the configuration nodeActions Browser Browser Open in new tab Apri in una nuova scheda Open Apri Open with Apri con Hex viewer Editor Esadecimale Extract Relevant module Moduli di interesse Bookmark Add nodes to bookmark Open parent folder Tags Tag nodes procMB Provided Arguments Argomenti forniti Results Risultati Processus Information Informazioni sul processo No results Nessun risultato Output Output Error searchCustomTable Form ... Query name Enabled Query searchPanel Form Quick search Wildcard Wildcard Regexp Fuzzy Fixed Custom Types : ... Advanced search Ricerca avanzata Options Opzioni Search from root 0 Start Stop Ferma Found selectionActions Browser Browser Select all Seleziona tutti Unselect all Clear selection selectionMenu Selection tagMenu Manage tags dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_nl.ts000066400000000000000000003013331217176075400176240ustar00rootroot00000000000000 About About Digital Forensics Framework Informatie over Digital Forensic Framework <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> <b>Digital Forensics Framework</b> (version %1)<br><br>Voor hulp bij problemen, bezoekt u onze support pagina op: <a href="http://wiki.digital-forensic.org/">onze site</a>.<br>IRC kanaal: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> Freenode netwerk.<br>Meer informatie: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software ontwikkeling door <a href="http://arxsys.fr/">ArxSys</a> en <a href="https://tracker.digital-forensic.org/">de DFF gemeenschap</a>.<br> AddBookmark Add bookmark Toevoegen van een bookmark Add a bookmark from the Virtual File System Toevoegen van een bookmark aan een Virtueel Bestands Systeem Create a new category Maak een nieuwe catagorie Category name: Naam van de catagorie: Add in an existing category Voeg aan een bestaande catagorie toe ApplyModule Configuration error An error was detected in the configuration AttributeCopyMenu copy AttributeSelectorMenu Select Unselect Select all Unselect all AttributesSelectionDialog Dialog BookmarkManager Bookmark You must specify at least one node. Specificeer tenminste 1 node BrowserToolBar Tags Search Filter attributes Attributen bookmark Add nodes to bookmark factorPlus Icons zoom in factorMinus Icons zoom out Icons Details Edit the columns attributes of the detailed view Browser BuildSearchClause Deleted verwijderd Type Type DevicesDialog Select Device Selecteer device Device Model Size Grootte Select a local device to add in the Virtual File System Toevoegen van een lokaal device aan het Virtueel Bestands Systeem Warning : You must run the software with Administrator rights Waarschuwing: U dient deze software als administrator uit te voeren Block device name Naam van blokkeer device Serial Serieel Dialog Error in configuration An error was detected in the configuration DicoManager Select your dictionnary DockWidgetTitleBar Undock Close Disable this window Errors Errors Fouten ExtractDialog Extract Uitpakken Recursive mode Omkeren Destination folder: Bestemmings folder: Browse Surf naar Preserve tree Overwrite existing Extractor Extraction path is mandatory Bestands bestemming verplicht invullen Choose the destination folder for extraction Kies de bestemmings folder om uit te pakken Overwrite attempt Probeer te overschijven Some selected files or folders already exist in the destination folder Sommige geselecteerde bestanden bestaan al in de bestemmings folder Overwrite with selected ones ? Het geselecteerde overschijven? FileOrFolder File Bestand Folder Filter Error Please, specify a query name FindFile Find file Zoek bestand Pattern: Patroon: Syntax: Omschrijving: Regular expression Reguliere expressie Fixed string Vaste string Wildcard Attribute: Attribuut: Name Naam Size grootte Date Datum Case sensitive sorting Hoofd/kleine letter gevoelig sorteren Case sensitive filter Hoofd/kleine letter gevoelig filteren Form Form OR AND NOT name Naam contains date mime Wildcard Regular expression Reguliere expressie Fuzzy Fixed string Vaste string Help Help It might mean that the format of your help file is not correct. You can check on-line help at http://wiki.digital-forensic.org Error while loading help fout opgetreden bij het laden van het help bestand An error occurred while setting help engine up : Ide IDE IDE toolbar New empty file Nieuw leeg bestand Generate skeleton Genereer framewerk Open file Open bestand Save Bewaar Save as Bewaren als Load Laad Undo Stap terug Redo Stap vooruit Comment Commentaar Uncomment Verwijder commentaar Save document ? Bewaar document? No file found Geen bestand gevonden Save file as Bewaar bestand als IdeWizard Integrated Development Environment Wizard Intergraal Ontwikkel Omgeving Wizard General Informations Algemene informatie Fill all script information such as name, type and saving location. Vul in: alle script informatie, zoals naam, type en bestemmings lokatie. Name: Naam: Category: Catagorie: Work location: Werk lokatie: Browse Surf naar Type: Type: Script Script Graphical Grafisch Driver Description Omschrijving Describe here the goal of the module Beschrijf het doel van module Module's description Module omschrijving Author informations Auteur informatie Fill all author's informations in order to complete header Vul alle header informatie van de auteur in Author's first name: Voornaam auteur: Author's last name: Achternaam auteur: Author's electronic mail: Email auteur: Location Lokatie Interpreter Python interpreter Python Interpreter IsDeleted No Yes ItemValueDialog Attribute value Attribute Value: ListNodeModel Name Naam Accessed time Toegangs tijd Changed time Veranderende tijd Modified time Gemodificeerde tijd Module Module Deleted verwijderd MainWindow File Bestand Exit Einde Load Laad Open evidence file(s) Bewijs bestand openen Open local device Lokaal device openen Digital Forensics Framework Edit Bewerken Module IDE Preferences Voorkeur instellingen ? View Bekijk Maximize Maximaliseer Fullscreen mode Volledig scherm modus Browser Load module Laad module Toolbar About DFF ... Over DFF ... DFF Documentation DFF documentatie Error while loading help fout opgetreden bij het laden van het help bestand <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. <br>On-line help beschikbaar: <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. Not an help file. Geen help bestand. Documentation path not found. Documentatie bestand niet gevonden. Browse Surf naar Open evidence Open device Console Live scripting Documentation Open the IDE MenuManager Empty files Lege bestanden the following nodes could not be opened with Hex viewer because they are either empty or folders de volgende nodes konden niet geopend worden door de hex viewer, omdat het folders zijn of ze zijn leeg Extraction Error An issue occured while extracting Module already applied This module was already applied with the same configuration ! Do you want to apply it again ? Apply module Module toevoegen Do you want to apply module Wilt u module on this node ? aan deze node toevoegen ? Always Altijd Modules Modules Modulen Name Naam Key Sleutel Value Waarde Info Type NodeBrowser Open in new tab Open in nieuwe tab Open with Open met Extract Uitpakken Relevant module Relevante module Apply module Module toevoegen Do you want to apply module Wilt u module on this node ? aan deze node toevoegen ? Always Altijd Empty files Lege bestanden the following nodes could not be opened with Hex viewer because they are either empty or folders de volgende nodes konden niet geopend worden door de hex viewer, omdat het folders zijn of ze zijn leeg NodeFBox Quick search: Search recursively Advanced search Index options Launch quick search NodeViewBox Previous Vorige Next Volgende Move to top Ga naar boven Return to root Terug naar de root List Lijst Attributes Attributen Add to bookmarks Toevoegen aan bookmarks Display search engine Zoekmachine Small Klein Medium Middelmatig Large Groot Activate thumbnails Activeer thumbnails You must specify at least one node. Specificeer tenminste 1 node Output Output Resultaat Preferences Create directory Maak een directorie Directory creation failure Het maken van de directorie is mislukt History file is not writable Historie bestand is niet beschrijfbaar PreferencesDialog Preferences Voorkeuren Global Globaal History Historie History file full path: Volledig pad naar historie bestand: No history file Geen historie bestand No footprint Geen afdruk Language Taal Interface language Taal menu Use interface language: Taal keuze: Indexation Indexeren Index files location Index bestands lokatie Root index Browse Surf naar Index name Index naam Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. In welke directorie wilt u de index bestanden bewaren? Directorie wordt automatisch aangemaakt, indien niet bestaand. Working environment Werkomgeving DFF user directory: DFF gebruikers directory: Help and documentation Hulp en documentatie Full path of the help and documentation file: Voledig pad naar de help en documentatie bestanden: Help and documentation settings Hulp en documentatie instellingen Provided path does not exists, will ask for creation on submit. Het ingegeven pad bestaat niet; word aangemaakt. Provided path is a readable directory. Het pad bevat een leesbare directorie. Please provide an help.qhc file along with an help.qch file at same directory level. help.qhc en help.qch moeten op hetzelfde directorie niveau. Provided path is not a readable file. Onjuist pad naar het bestand opgegeven. Provided path is a readable file. Het pad wijst naar een bestaand bestand. Preview Preview Processus Fail Finish Running PropertyTable name Naam folder file Bestand generated by Gemaakt door size Grootte relevant module(s) Relevante module(n) node type attributes Attributen children file(s) Bestand(en) bytes folder(s) totalizing Afronden with module(s) applied on it met de navolgende modulen empty leeg deleted verwijderd link path SearchPanel Error Please, specify your query SearchTab Attributes Attributen SearchThread Error Error compiling query SelectAttributesWiz Select attributes Attribute selection location Select attributes from Current list Current selected file All selected files Group attributes by Types Generated module Generating attribute list Shell Shell Welcome to DFF shell Welkom bij de DFF shell TagManagerDialog Warning No nodes was selected in the browser. No tags was selected in the available tags list. No tags was selected in the selected nodes tags list. Are you sure ? This will delete this tag for all nodes in the VFS ! This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Tags management Selected nodes tags Available tags TaskManager PID Name Naam State Provincie Info Exec Time totale tijd Task Manager Opdracht manager Duration TreeModel Name Naam VFSItemModel Name Naam Size Grootte Accessed time Toegangs tijd Changed time Veranderende tijd Modified time Gemodificeerde tijd Deleted verwijderd VariantTreeWidget Key Sleutel Value Waarde Attribute applyModule Apply module Module toevoegen Informations Informatie Module Module Type Type Arguments Argumenten Activate Activeren Description Omschrijving dicoManager Form Dictionnary manager Add dictionnary Remove dictionnary Location Lokatie Dictionnary's name edittag Name : Default set color Edit tag evidenceDialog Select evidence type Selecteer bewijs type Add evidence directory Voeg bewijs directorie toe Add evidence files Voeg bewijs bestanden toe Open local files or directory Open een lokaal bestand of directorie RAW format RAW formaat EWF format EWF formaat AFF Format filterAdd Create your custom filter Filter name Add custom filter queries filterAttributes Form filterBar Form filterConjunction Form And And not Or Or not filterDico Form Name Naam Content Any All None filterFields Form Name Naam Contains Size Date Datum Mime type Dictionnary Is deleted Is file Attribute filterMatchMode Form Wildcard Reg-exp Fuzzy Fixed Case sensitive filterMime Form Select ... filterMimeDialog Dialog filterMode Form Filter activated 11 Found filterOnly Form True False filterOperators Form Is less than Is less than or equal to Is equal to Is not equal to Is greater than or equal to Is greater than filterTagwidget Form Exclude filterWidget Form 0 / Custom query Tags ... Stop filter Clear filter Clear Wildcard Fuzzy Reg exp Fixed layoutManager File Bestand Directory moduleBrowser Module browser moduleGeneratorWidget Module Informations Informatie Arguments Argumenten Activate Activeren Description Omschrijving moduleShapeGenerator Configuration error An error was detected in the configuration nodeActions Browser Open in new tab Open in nieuwe tab Open Open with Open met Hex viewer Extract Uitpakken Relevant module Relevante module Bookmark Add nodes to bookmark Open parent folder Tags Tag nodes procMB Results Resultaten No results Geen resultaten Provided Arguments Geef argumenten Processus Information Verwerking van de informatie Output Resultaat Error searchCustomTable Form ... Query name Enabled Query searchPanel Form Quick search Wildcard Regexp Fuzzy Fixed Custom Types : ... Advanced search Options Search from root 0 Start Stop Found selectionActions Browser Select all Unselect all Clear selection selectionMenu Selection tagMenu Manage tags dff-1.3.0+dfsg.1/dff/ui/gui/i18n/Dff_zh.ts000066400000000000000000003037021217176075400176360ustar00rootroot00000000000000 About About Digital Forensics Framework 关于数字å–è¯æ¡†æž¶ <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> <b>æ•°å­—å–è¯æ¡†æž¶</b> (version %1)<br><br>如果你有任何问题,请访问 <a href="http://wiki.digital-forensic.org/">支æŒé¡µé¢</a><br>IRCè”ç³»: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>更多信æ¯: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>软件开å‘商 <a href="http://arxsys.fr/">ArxSys</a> å’Œ <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> AddBookmark Add bookmark 增加书签 Add a bookmark from the Virtual File System 从VFS增加一个书签 Create a new category 创建一个新的分类 Category name: 分类åç§° : Add in an existing category 增加一个存在的分类 ApplyModule Configuration error An error was detected in the configuration AttributeCopyMenu copy AttributeSelectorMenu Select Unselect Select all Unselect all AttributesSelectionDialog Dialog BookmarkManager Bookmark You must specify at least one node. BrowserToolBar Tags Search Filter attributes 属性 bookmark Add nodes to bookmark factorPlus Icons zoom in factorMinus Icons zoom out Toolbar å·¥å…·æ  Icons 图标 Details Edit the columns attributes of the detailed view Browser æµè§ˆå™¨ BuildSearchClause Deleted 删除的 Type 类型 DevicesDialog Select Device 选择设备 Device 设备 Model åž‹å· Size å¤§å° Select a local device to add in the Virtual File System 选择一个本地设备添加到VFS Warning : You must run the software with Administrator rights 警告:你必须用管ç†å‘˜æƒé™è¿è¡Œæœ¬è½¯ä»¶ Block device name å—设备åç§° Serial ç³»åˆ—å· Dialog Error in configuration An error was detected in the configuration DicoManager Select your dictionnary DockWidgetTitleBar Undock Close Disable this window Errors Errors 错误 ExtractDialog Extract æå– Recursive mode é€’å½’æ¨¡å¼ Destination folder: 目标文件夹: Browse æµè§ˆ Preserve tree Overwrite existing Extractor Extraction path is mandatory æå–路径是强制的 Choose the destination folder for extraction 选择æå–的目标文件夹 Overwrite attempt 覆盖å°è¯• Some selected files or folders already exist in the destination folder 一些选择的文件或文件夹已ç»å­˜åœ¨äºŽç›®æ ‡æ–‡ä»¶å¤¹ Overwrite with selected ones ? ç”¨é€‰æ‹©çš„æ–‡ä»¶è¦†ç›–å— ï¼Ÿ FileOrFolder File 文件 Folder Filter Error Please, specify a query name FindFile Find file 查找文件 Pattern: 类型: Syntax: 语法: Regular expression æ­£åˆ™è¡¨è¾¾å¼ Fixed string 固定的字符串 Wildcard 通é…符 Attribute: 属性: Name åç§° Size å¤§å° Date æ•°æ® Case sensitive sorting 大å°å†™æ•æ„ŸæŽ’åº Case sensitive filter 大å°å†™æ•感筛选 Form Form OR AND NOT name åç§° contains date mime Wildcard 通é…符 Regular expression æ­£åˆ™è¡¨è¾¾å¼ Fuzzy Fixed string 固定的字符串 Help Help It might mean that the format of your help file is not correct. You can check on-line help at http://wiki.digital-forensic.org Error while loading help 加载帮助时的错误 An error occurred while setting help engine up : Ide IDE IDE IDE toolbar IDEå·¥å…·æ  New empty file 新的空文件 Generate skeleton ç”Ÿæˆæçº² Open file 打开文件 Save ä¿å­˜ Save as ä¿å­˜ä¸º Load 加载 Undo 撤销 Redo é‡åš Comment 注释 Uncomment å–æ¶ˆæ³¨é‡Š Save document ? ä¿å­˜æ–‡æ¡£ ? No file found 没有找到文件 Save file as 文件ä¿å­˜ä¸º IdeWizard Integrated Development Environment Wizard 集æˆå¼€å‘环境å‘导 General Informations ä¸€èˆ¬ä¿¡æ¯ Fill all script information such as name, type and saving location. 填写所有的脚本信æ¯ï¼Œä¾‹å¦‚åç§°ã€ç±»åž‹å’Œä¿å­˜çš„ä½ç½®. Name: å称: Category: 分类: Work location: 工作的ä½ç½®ï¼š Browse æµè§ˆ Type: 类型: Script 脚本 Graphical 图形 Driver 驱动器 Description æè¿° Describe here the goal of the module 这里æè¿°æ¨¡å—的目标 Module's description æ¨¡å— æè¿° Author informations ç¼–å†™è€…ä¿¡æ¯ Fill all author's informations in order to complete header å¡«å†™æ‰€æœ‰çš„ç¼–å†™è€…ä¿¡æ¯ ä»¥ä¾¿å®Œæˆå¤´éƒ¨å†…容 Author's first name: 编写者 å: Author's last name: 编写者 å§“: Author's electronic mail: 编写者 电å­é‚®ä»¶: Location ä½ç½® Interpreter Python interpreter Python 解释器 Python Interpreter Python 解释器 IsDeleted No Yes ItemValueDialog Attribute value Attribute Value: ListNodeModel Name åç§° Size å¤§å° Accessed time 访问时间 Changed time æ”¹å˜æ—¶é—´ Modified time 修改时间 Module æ¨¡å— Deleted 删除的 MainWindow File 文件 Exit 退出 Load 加载 Open evidence file(s) æ‰“å¼€è¯æ®æ–‡ä»¶ Open local device 打开本地设备 Digital Forensics Framework æ•°å­—å–è¯æ¡†æž¶ Edit 编辑 Module æ¨¡å— IDE IDE Preferences 首选项 ? ? View 视图 Maximize 最大化 Fullscreen mode 免屿¨¡å¼ Shell Shell Browser æµè§ˆå™¨ Python interpreter Python解释器 Load module åŠ è½½æ¨¡å— Open 打开 Toolbar å·¥å…·æ  About DFF ... 关于DFF... DFF Documentation DFF文档 Error while loading help 加载帮助时的错误 <br>You can check on-line help at <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. <br>ä½ å¯ä»¥æŸ¥é˜…在线帮助 <a href="http://wiki.digital-forensic.org/">http://wiki.digital-forensic.org</a>. Not an help file. 䏿˜¯ä¸€ä¸ªå¸®åŠ©æ–‡ä»¶. Documentation path not found. 文档路径没有找到. Browse æµè§ˆ Open evidence Open device Console Live scripting Documentation Open the IDE MenuManager Empty files 空文件 the following nodes could not be opened with Hex viewer because they are either empty or folders 下é¢èŠ‚ç‚¹ä¸èƒ½ç”¨å六进制打开,因为它们是空的或是文件夹 Extraction Error An issue occured while extracting Module already applied This module was already applied with the same configuration ! Do you want to apply it again ? Apply module åº”ç”¨æ¨¡å— Do you want to apply module ä½ å¸Œæœ›åº”ç”¨æ¨¡å— on this node ? 在这个节点上 ? Always 通常 Modules Modules æ¨¡å— Name åç§° Key é”® Value 值 Info ä¿¡æ¯ Type 类型 NodeBrowser Open in new tab 在新标签中打开 Open 打开 Open with 用...打开 Hex viewer å六进制查看 Extract æå– Browser æµè§ˆå™¨ Relevant module ç›¸å…³æ¨¡å— Apply module åº”ç”¨æ¨¡å— Do you want to apply module ä½ å¸Œæœ›åº”ç”¨æ¨¡å— on this node ? 在这个节点上 ? Always 通常 Empty files 空文件 the following nodes could not be opened with Hex viewer because they are either empty or folders 下é¢èŠ‚ç‚¹ä¸èƒ½ç”¨å六进制打开,因为它们是空的或是文件夹 NodeFBox Quick search: Search recursively Advanced search Index options Launch quick search NodeViewBox Previous å‰ä¸€ä¸ª Next åŽä¸€ä¸ª Move to top 到顶部 Return to root 返回到根 List 列表 Icons 图标 Attributes 属性 Add to bookmarks 添加到书签 Display search engine 显示æœç´¢å¼•擎 Small å° Medium 中等 Large 大 Activate thumbnails 激活缩略图 Output Output 输出 Preferences Create directory 创建目录 Directory creation failure 目录创建失败 History file is not writable åŽ†å²æ–‡ä»¶ä¸å¯å†™ PreferencesDialog Preferences 首选项 Global 全局 History åŽ†å² History file full path: åŽ†å²æ–‡ä»¶å®Œæ•´è·¯å¾„: No history file æ²¡æœ‰åŽ†å²æ–‡ä»¶ No footprint 没有足迹 Language 语言 Interface language 界é¢è¯­è¨€ Use interface language: 使用界é¢è¯­è¨€ï¼š Indexation 索引 Index files location 索引文件ä½ç½® Root index 根索引 Browse æµè§ˆ Index name 索引å Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. 请选择你想ä¿å­˜ç´¢å¼•文件的目录 如果目录ä¸å­˜åœ¨ï¼Œå°†ä¼šåœ¨ä¿®æ”¹åº”用时创建。 Working environment 工作环境 DFF user directory: DFF 用户目录: Help and documentation 帮助和文档 Full path of the help and documentation file: 帮助和文档文件的完整路径: Help and documentation settings 帮助和文档的设定 Provided path does not exists, will ask for creation on submit. æä¾›çš„路径ä¸å­˜åœ¨ï¼Œåœ¨æäº¤æ—¶å°†è¦æ±‚创建. Provided path is a readable directory. æä¾›çš„路径是一个å¯è¯»çš„目录. Please provide an help.qhc file along with an help.qch file at same directory level. 请在åŒä¸€ä¸ªç›®å½•中æä¾›ä¸€ä¸ªhelp.qhc文件和一个help.qch文件. Provided path is not a readable file. æä¾›çš„è·¯å¾„ä¸æ˜¯ä¸€ä¸ªå¯è¯»çš„æ–‡ä»¶. Provided path is a readable file. æä¾›çš„路径是一个å¯è¯»çš„æ–‡ä»¶. Preview Preview Processus Fail Finish Running PropertyTable name åç§° folder 文件夹 file 文件 generated by 产生于 size å¤§å° relevant module(s) å…³è”çš„æ¨¡å— node type 节点类型 attributes 属性 children å­èŠ‚ç‚¹ file(s) 文件 bytes 字节 folder(s) 文件夹 totalizing 总计 with module(s) applied on it 有模å—应用于它 empty 空的 deleted 删除的 link path SearchPanel Error Please, specify your query SearchTab Attributes 属性 SearchThread Error Error compiling query SelectAttributesWiz Select attributes Attribute selection location Select attributes from Current list Current selected file All selected files Group attributes by Types Generated module Generating attribute list Shell Shell Shell Welcome to DFF shell 欢迎使用DFF Shell TagManagerDialog Warning No nodes was selected in the browser. No tags was selected in the available tags list. No tags was selected in the selected nodes tags list. Are you sure ? This will delete this tag for all nodes in the VFS ! This is a default tag it cannot be deleted. All tagged VFS nodes was untagged. Tags Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Tags management Selected nodes tags Available tags TaskManager PID PID Name åç§° State çŠ¶æ€ Info ä¿¡æ¯ Exec Time 执行时间 Task Manager 任务管ç†å™¨ Duration TreeModel Name åç§° VFSItemModel Name åç§° Size å¤§å° Accessed time 访问时间 Changed time æ”¹å˜æ—¶é—´ Modified time 修改时间 Module æ¨¡å— Deleted 删除的 VariantTreeWidget Key é”® Value 值 Attribute applyModule Apply module åº”ç”¨æ¨¡å— Informations ä¿¡æ¯ Module æ¨¡å— Type 类型 Arguments 傿•° Activate 活动的 Description æè¿° dicoManager Form Dictionnary manager Add dictionnary Remove dictionnary Location ä½ç½® Dictionnary's name edittag Name : Default set color Edit tag evidenceDialog Select evidence type é€‰æ‹©è¯æ®ç±»åž‹ Add evidence directory æ·»åŠ è¯æ®ç›®å½• Add evidence files æ·»åŠ è¯æ®æ–‡ä»¶ Open local files or directory 打开本地文件或目录 RAW format RAWæ ¼å¼ EWF format EWFæ ¼å¼ AFF Format filterAdd Create your custom filter Filter name Add custom filter queries filterAttributes Form filterBar Form filterConjunction Form And And not Or Or not filterDico Form Name åç§° Content Any All None filterFields Form Name åç§° Contains Size å¤§å° Date æ•°æ® Mime type Dictionnary Is deleted Is file Attribute filterMatchMode Form Wildcard 通é…符 Reg-exp Fuzzy Fixed Case sensitive filterMime Form Select ... filterMimeDialog Dialog filterMode Form Filter activated 11 Found filterOnly Form True False filterOperators Form Is less than Is less than or equal to Is equal to Is not equal to Is greater than or equal to Is greater than filterTagwidget Form Exclude filterWidget Form 0 / Custom query Tags ... Stop filter Clear filter Clear Wildcard 通é…符 Fuzzy Reg exp Fixed layoutManager File 文件 Directory moduleBrowser Module browser moduleGeneratorWidget Module æ¨¡å— Informations ä¿¡æ¯ Arguments 傿•° Activate 活动的 Description æè¿° moduleShapeGenerator Configuration error An error was detected in the configuration nodeActions Browser æµè§ˆå™¨ Open in new tab 在新标签中打开 Open 打开 Open with 用...打开 Hex viewer å六进制查看 Extract æå– Relevant module ç›¸å…³æ¨¡å— Bookmark Add nodes to bookmark Open parent folder Tags Tag nodes procMB Results 结果 No results 没有结果 Provided Arguments æä¾›çš„傿•° Processus Information 处ç†ä¿¡æ¯ Output 输出 Error searchCustomTable Form ... Query name Enabled Query searchPanel Form Quick search Wildcard 通é…符 Regexp Fuzzy Fixed Custom Types : ... Advanced search Options Search from root 0 Start Stop Found selectionActions Browser æµè§ˆå™¨ Select all Unselect all Clear selection selectionMenu Selection tagMenu Manage tags dff-1.3.0+dfsg.1/dff/ui/gui/i18n/dff.pro000066400000000000000000000120571217176075400173470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge FORMS += ../../../ui/gui/resources/about.ui FORMS += ../../../ui/gui/resources/applymodule.ui FORMS += ../../../ui/gui/resources/attributes_selection_dialog.ui FORMS += ../../../ui/gui/resources/bookmarkdialog.ui FORMS += ../../../ui/gui/resources/browser_toolbar.ui FORMS += ../../../ui/gui/resources/devicesdialog.ui FORMS += ../../../ui/gui/resources/dico_manager.ui FORMS += ../../../ui/gui/resources/errors.ui FORMS += ../../../ui/gui/resources/evidencedialog.ui FORMS += ../../../ui/gui/resources/extractdialog.ui FORMS += ../../../ui/gui/resources/filter_add.ui FORMS += ../../../ui/gui/resources/filter_attributes.ui FORMS += ../../../ui/gui/resources/filter_bar.ui FORMS += ../../../ui/gui/resources/filter_conjunction.ui FORMS += ../../../ui/gui/resources/filter_dico.ui FORMS += ../../../ui/gui/resources/filter_fields.ui FORMS += ../../../ui/gui/resources/filter_matchmode.ui FORMS += ../../../ui/gui/resources/filter_mime.ui FORMS += ../../../ui/gui/resources/filter_mimedialog.ui FORMS += ../../../ui/gui/resources/filter_mode.ui FORMS += ../../../ui/gui/resources/filter_only.ui FORMS += ../../../ui/gui/resources/filter_operators.ui FORMS += ../../../ui/gui/resources/filter_tagwidget.ui FORMS += ../../../ui/gui/resources/filter_widget.ui FORMS += ../../../ui/gui/resources/ide.ui FORMS += ../../../ui/gui/resources/idewizard.ui FORMS += ../../../ui/gui/resources/interpreter.ui FORMS += ../../../ui/gui/resources/is_deleted.ui FORMS += ../../../ui/gui/resources/is_file_or_folder.ui FORMS += ../../../ui/gui/resources/mainwindow.ui FORMS += ../../../ui/gui/resources/modulebrowserdialog.ui FORMS += ../../../ui/gui/resources/modulegeneratorwidget.ui FORMS += ../../../ui/gui/resources/modules.ui FORMS += ../../../ui/gui/resources/node_f_box.ui FORMS += ../../../ui/gui/resources/nodeactions.ui FORMS += ../../../ui/gui/resources/nodefilterbox.ui FORMS += ../../../ui/gui/resources/output.ui FORMS += ../../../ui/gui/resources/preferences.ui FORMS += ../../../ui/gui/resources/search_customtable.ui FORMS += ../../../ui/gui/resources/search_panel.ui FORMS += ../../../ui/gui/resources/search_requests.ui FORMS += ../../../ui/gui/resources/select_attributes.ui FORMS += ../../../ui/gui/resources/selection_actions.ui FORMS += ../../../ui/gui/resources/shell.ui FORMS += ../../../ui/gui/resources/tagedit.ui FORMS += ../../../ui/gui/resources/tags.ui FORMS += ../../../ui/gui/resources/taskmanager.ui FORMS += ../../../ui/gui/resources/varianttreewidget.ui SOURCES += ../../../api/gui/widget/propertytable.py SOURCES += ../../../api/gui/widget/dockwidget.py SOURCES += ../../../api/gui/dialog/tagmanager.py SOURCES += ../../../api/gui/dialog/extractor.py SOURCES += ../../../api/gui/dialog/applymodule.py SOURCES += ../../../api/gui/dialog/selectattributes.py SOURCES += ../../../api/gui/model/tree.py SOURCES += ../../../api/gui/widget/layoutmanager.py SOURCES += ../../../api/gui/widget/generateModuleShape.py SOURCES += ../../../api/gui/widget/varianttreewidget.py SOURCES += ../../../api/gui/widget/search/dico_manager.py SOURCES += ../../../api/gui/widget/search/search_widget.py SOURCES += ../../../api/gui/widget/search/thread.py SOURCES += ../../../ui/gui/ide/ide.py SOURCES += ../../../ui/gui/ide/idewizard.py SOURCES += ../../../ui/gui/mainwindow.py SOURCES += ../../../ui/gui/dialog/preferences.py SOURCES += ../../../ui/gui/dialog/dialog.py SOURCES += ../../../ui/gui/widget/taskmanager.py SOURCES += ../../../ui/gui/widget/preview.py SOURCES += ../../../ui/gui/widget/help.py SOURCES += ../../../ui/gui/utils/menumanager.py SOURCES += ../../../ui/gui/utils/menu.py TRANSLATIONS += ../../../ui/gui/i18n/Dff_de.ts TRANSLATIONS += ../../../ui/gui/i18n/Dff_en.ts TRANSLATIONS += ../../../ui/gui/i18n/Dff_es.ts TRANSLATIONS += ../../../ui/gui/i18n/Dff_fr.ts TRANSLATIONS += ../../../ui/gui/i18n/Dff_it.ts TRANSLATIONS += ../../../ui/gui/i18n/Dff_nl.ts TRANSLATIONS += ../../../ui/gui/i18n/Dff_zh.ts dff-1.3.0+dfsg.1/dff/ui/gui/ide/000077500000000000000000000000001217176075400160435ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/ide/CMakeLists.txt000066400000000000000000000012561217176075400206070ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier install_file( editor.py ide.py highlighter.py explorer.py __init__.py generatecode.py messagebox.py idewizard.py ) dff-1.3.0+dfsg.1/dff/ui/gui/ide/__init__.py000066400000000000000000000012361217176075400201560ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER __all__ = ["ide", "editor", "generatecode", "idewizardpages", "idewizard", "messagebox", "explorer", "highlighter"] dff-1.3.0+dfsg.1/dff/ui/gui/ide/editor.py000066400000000000000000000143441217176075400177110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import QPlainTextEdit, QTextEdit, QColor, QTextFormat, QPainter, QWidget, QFont, QTextCursor from PyQt4.QtCore import Qt, SIGNAL, QRect, QChar, QString, QSize from dff.ui.gui.ide.highlighter import pythonHighlighter class codeEditor(QPlainTextEdit): def __init__(self, buff=None, parent=None): super(codeEditor, self).__init__(parent) self.setTabStopWidth(20) self.lineNumberArea = LineNumberArea(self) self.configureFont() self.connect(self, SIGNAL("blockCountChanged(int)"), self.updateLineNumberAreaWidth) self.connect(self, SIGNAL("updateRequest(const QRect, int)"), self.updateLineNumberArea) self.connect(self, SIGNAL("cursorPositionChanged()"), self.highlightCurrentLine) self.updateLineNumberAreaWidth(0) self.highlighter = pythonHighlighter(self.document()) self.selectionStart = 0 self.selectionEnd = 0 self.highlightCurrentLine() self.__name = QString("") self.__scriptPath = QString("") if buff != None: self.setPlainText(buff) def configureFont(self): font = QFont() font.setFamily('Helvetica') font.setFixedPitch(True) font.setPointSize(11) self.setFont(font) def lineNumberAreaWidth(self): digits = 1 mmax = max(1, self.blockCount()) while (mmax >= 10): mmax /= 10 digits += 1 space = 3 + self.fontMetrics().width(QChar('9')) * digits return space def updateLineNumberAreaWidth(self, blockCount): self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) def updateLineNumberArea(self, rect, dy): if (dy): self.lineNumberArea.scroll(0, dy) else: self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) if rect.contains(self.viewport().rect()): self.updateLineNumberAreaWidth(0) def resizeEvent(self, event): QPlainTextEdit.resizeEvent(self, event) cr = self.contentsRect() self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height())) def highlightCurrentLine(self): selections = [] if (not self.isReadOnly()): selection = QTextEdit.ExtraSelection() lineColor = QColor(240,240,240) selection.format.setBackground(lineColor) selection.format.setProperty(QTextFormat.FullWidthSelection, True) selection.cursor = self.textCursor() selection.cursor.clearSelection() selections.append(selection) self.setExtraSelections(selections) def lineNumberAreaPaintEvent(self, event): painter = QPainter(self.lineNumberArea) painter.fillRect(event.rect(), Qt.lightGray) block = self.firstVisibleBlock() blockNumber = block.blockNumber() top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top() bottom = top + self.blockBoundingRect(block).height() while (block.isValid() and top <= event.rect().bottom()): if (block.isVisible() and bottom >= event.rect().top()): number = QString.number(blockNumber + 1) painter.setPen(Qt.black) painter.drawText(0, top, self.lineNumberArea.width(), self.fontMetrics().height(), Qt.AlignRight, number) block = block.next() top = bottom bottom = top + self.blockBoundingRect(block).height() blockNumber += 1 def setName(self, name): self.__name = name def getName(self): if self.__name: return self.__name else: return None def setScriptPath(self, path): self.__scriptPath = path def getScriptPath(self): if self.__scriptPath: return self.__scriptPath else: return "error" def comment(self): cursor = self.textCursor() start = min([cursor.selectionStart(), cursor.selectionEnd()]) end = max([cursor.selectionStart(), cursor.selectionEnd()]) cursor.beginEditBlock() cursor.setPosition(start) while cursor.position() <= end: cursor.movePosition(QTextCursor.StartOfLine) cursor.setPosition(cursor.position() + 1, QTextCursor.KeepAnchor) if cursor.selectedText() != "#": cursor.movePosition(QTextCursor.StartOfLine) cursor.insertText("#") if not cursor.movePosition(QTextCursor.NextBlock): cursor.movePosition(QTextCursor.EndOfLine) break cursor.endEditBlock() def uncomment(self): cursor = self.textCursor() start = min([cursor.selectionStart(), cursor.selectionEnd()]) end = max([cursor.selectionStart(), cursor.selectionEnd()]) cursor.beginEditBlock() cursor.setPosition(start) while cursor.position() <= end: cursor.movePosition(QTextCursor.StartOfLine) cursor.setPosition(cursor.position() + 1, QTextCursor.KeepAnchor) if cursor.selectedText() == "#": cursor.removeSelectedText() if not cursor.movePosition(QTextCursor.NextBlock): cursor.movePosition(QTextCursor.EndOfLine) break cursor.endEditBlock() class LineNumberArea(QWidget): def __init__(self, codeEditor): super(LineNumberArea, self).__init__(codeEditor) self.codeEditor = codeEditor def sizeHint(self): return QSize(self.codeEditor.lineNumberAreaWidth(), 0) def paintEvent(self, event): self.codeEditor.lineNumberAreaPaintEvent(event) dff-1.3.0+dfsg.1/dff/ui/gui/ide/explorer.py000066400000000000000000000036111217176075400202560ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import os, sys, re import os.path as osp from PyQt4.QtGui import QTreeView, QDirModel from PyQt4.QtCore import Qt, SIGNAL, QString, QStringList, QDir class Explorer(QTreeView): def __init__(self, parent=None, path=None): QTreeView.__init__(self, parent) self.ide = parent self.path = path self.model = explorerModel() self.setModel(self.model) self.setColumnHidden(3, True) self.setColumnHidden(2, True) self.setAnimated(False) self.setSortingEnabled(True) self.sortByColumn(0, Qt.AscendingOrder) def mouseDoubleClickEvent(self, event): index = self.currentIndex() if index: localpath = osp.normpath(unicode(self.model.filePath(index))) if osp.isdir(localpath): self.setExpanded(index, True) else: self.ide.open(localpath) class explorerModel(QDirModel): def __init__(self, parent=None): QDirModel.__init__(self, parent) self.filter = QDir.AllDirs | QDir.Files | QDir.Drives | QDir.NoDotAndDotDot self.sortflags = QDir.Name | QDir.DirsFirst | \ QDir.IgnoreCase | QDir.LocaleAware self.nameFilter = ["*.py", "*.pyw"] self.setNameFilters(self.nameFilter) self.setFilter(self.filter) self.setSorting(self.sortflags) dff-1.3.0+dfsg.1/dff/ui/gui/ide/generatecode.py000066400000000000000000000151261217176075400210470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import sys class GenerateCode(): def __init__(self): pass def set_header(self, fname, lname, mail): self.fname = fname self.lname = lname self.mail = mail def setTag(self, tag): self.tag = tag def setDescription(self, desc): self.description = desc def generate_header(self): buff="# DFF -- An Open Source Digital Forensics Framework\n\ #\n\ # This program is free software, distributed under the terms of\n\ # the GNU General Public License Version 2. See the LICENSE file\n\ # at the top of the source tree.\n\ # \n\ # See http://www.digital-forensic.org for more information about this\n\ # project. Please do not directly contact any of the maintainers of\n\ # DFF for assistance; the project provides a web site, mailing lists\n\ # and IRC channels for your use.\n\ # \n\ # Author(s):\n\ # " + self.fname + " "+ self.lname +" < " + self.mail + ">\n\ #\n\ \n" return buff def generate_script(self, scriptname): buff = self.generate_header() buff += "import sys\n\ from api.module.script import Script\n\ from api.module.module import Module\n\ from api.types.libtypes import Argument, typeId\n\ \n\ from PyQt4.QtCore import QSize, SIGNAL\n\ from PyQt4.QtGui import QWidget\n\ from ui.gui.utils.utils import Utils\n\ \n\ class " + scriptname.upper() + "(Script):\n\ def __init__(self):\n\ #Module initialization goes here\n\ Script.__init__(self, \"" + scriptname + "\")\n\ \n\ def c_display(self):\n\ # You can add console display function here\n\ # such as ncurses func or others display functions.\n\ #ex: print \"something\"\n\ pass\n\ \n\ def start(self, args):\n\ # get your arguments here.\n\ # Do something.\n\ try:\n\ self.parent = args[\"file\"].value()\n\ print \"Hello World\"\n\ except IndexError:\n\ print \"Could not get \'file\' argument.\"\n\ \n\ \n\ class " + scriptname + "(Module):\n\ def __init__(self):\n\ Module.__init__(self, \"" + scriptname + "\", " + scriptname.upper() + ")\n\ \n\ # Add your argument and tags here\n\ self.conf.addArgument({\"input\": Argument.Required|Argument.Single|typeId.Node,\n\ \"name\": \"file\",\n\ \"description\": \"Description of your module\"})\n\ self.tags = \"" + self.tag + "\" \n" return buff def generate_script_gui(self, scriptname): buff = self.generate_header() buff += "import sys\n\ from api.module.script import Script\n\ from api.module.module import Module\n\ from api.types.libtypes import Argument, typeId\n\ \n\ from PyQt4.QtCore import QSize, SIGNAL\n\ from PyQt4.QtGui import QTextEdit\n\ from ui.gui.utils.utils import Utils\n\ \n\ class " + scriptname.upper() + "(Script, QTextEdit):\n\ def __init__(self):\n\ #Module initialization goes here\n\ Script.__init__(self, \"" + scriptname + "\")\n\ \n\ def c_display(self):\n\ # You can add console display function here\n\ # such as ncurses func or others display functions.\n\ #ex: print \"something\"\n\ pass\n\ \n\ def g_display(self):\n\ #This function must init a QWidget\n\ QTextEdit.__init__(self, None)\n\ \n\ def updateWidget(self):\n\ #you can put your refresh on resize func here\n\ pass\n\ \n\ def start(self, args):\n\ # get your arguments here.\n\ # Do soemthing.\n\ try:\n\ self.parent = args[\"file\"].value()\n\ print \"Hello World\"\n\ except IndexError:\n\ print \"Could not get \'parent\' argument.\"\n\ \n\ class " + scriptname + "(Module):\n\ def __init__(self):\n\ Module.__init__(self, \"" + scriptname + "\", " + scriptname.upper() + ")\n\ \n\ # Add your argument and tags here\n\ self.conf.addArgument({\"input\": Argument.Required|Argument.Single|typeId.Node,\n\ \"name\": \"file\",\n\ \"description\": \"Description of your module\"})\n\ self.tags = \"" + self.tag + "\" \n" return buff def generate_drivers(self, drivername): buff = self.generate_header() buff += "from struct import unpack\n\ from api.vfs import * \n\ from api.module.module import *\n\ from api.vfs.libvfs import *\n\ from modules.fs.spare import SpareNode\n\ \n\ from api.types.libtypes import Variant, VMap, Parameter, Argument, typeId\n\ from api.vfs.libvfs import AttributesHandler\n\ from api.vfs.vfs import vfs\n\ \n\ class " + drivername + "(Module):\n\ \"\"\"\n " + self.description + "\n \"\"\"\n\ def __init__(self):\n\ Module.__init__(self, \"" + drivername + "\", " + drivername.capitalize() +")\n\ self.conf.addArgument({\"input\": Argument.Optional|Argument.Single|typeId.Node,\n\ \"name\": \"parent\", \n\ \"description\": \"files or folders will be added as child(ren) of this node or as the root node by default\",\n\ \"parameters\": {\"type\": Parameter.Editable}\n\ })\n\ \n\ # you can add some arguments for your module here by using the self.conf.addArgument method\n\ self.tags = \"" + self.tag + "\" \n\ \n\ \n\ class " + drivername.capitalize() + "(mfso):\n\ def __init__(self):\n\ # initialization of the driver\n\ mfso.__init__(self, \"" + drivername + "\")\n\ \n\ # get the VFS\n\ self.vfs = VFS.Get()\n\ self.name = \"" + drivername + "\"\n\ self.__disown__()\n\ \n\ def start(self, args):\n\ # get the parent Node\n\ print \"Running module...\"\n\ try:\n\ self.parent = args[\"parent\"].value()\n\ print \"Hello World\"\n\ except IndexError:\n\ print \"Could not get \'parent\' argument.\"\n\ \n\ class " + drivername.capitalize() + "Node(Node):\n\ \"\"\"\n\ The type of node your driver will generate.\n\ \"\"\"\n\n\ def __init__(self, name, size, parent, fso): # you might need more parameters\n\ Node.__init__(self, name, size, parent, fso)\n\ self.__disown__()\n\ " return buff dff-1.3.0+dfsg.1/dff/ui/gui/ide/highlighter.py000066400000000000000000000066561217176075400207300ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import QTextCharFormat, QFont, QSyntaxHighlighter from PyQt4.QtCore import Qt, SIGNAL, QRegExp class highlightRule(object): def __init__(self, pattern, format): super(highlightRule, self).__init__() self.__pattern = QRegExp(pattern) self.__format = QTextCharFormat(format) def pattern(self): return self.__pattern def format(self): return self.__format class Highlighter(QSyntaxHighlighter): def __init__(self, parent=None): super(Highlighter, self).__init__(parent) self.highlightingRules = [] def setRule(self, pattern, format): if (pattern != ""): self.highlightingRules.insert(0, highlightRule(pattern,format)) self.rehighlight() def highlightBlock(self, text): for rule in self.highlightingRules: expression = rule.pattern() index = expression.indexIn(text) while index >= 0: length = expression.matchedLength() self.setFormat(index, length, rule.format()) index = expression.indexIn(text, index + length) self.setCurrentBlockState(0) class commentHighlighter(Highlighter): def __init__(self, parent=None): super(commentHighlighter, self).__init__(parent) CommentFormat = QTextCharFormat() CommentFormat.setForeground(Qt.red) self.setRule("#[^\n]*", CommentFormat) class pythonHighlighter(commentHighlighter): def __init__(self, parent=None): super(pythonHighlighter, self).__init__(parent) quotationFormat = QTextCharFormat() quotationFormat.setForeground(Qt.darkGreen) self.setRule("\".*\"", quotationFormat) functionFormat = QTextCharFormat() functionFormat.setFontItalic(True) functionFormat.setForeground(Qt.blue) self.setRule("\\b[A-Za-z0-9_]+(?=\\()", functionFormat) keywordFormat = QTextCharFormat() keywordFormat.setForeground(Qt.darkBlue) keywordFormat.setFontWeight(QFont.Bold) pythonKeywordPatterns = ["\\band\\b", "\\bdel\\b", "\\bfrom\\b", "\\bnot\\b", "\\bwhile\\b", "\\bas\\b", "\\belif\\b", "\\bglobal\\b", "\\bor\\b", "\\bwith\\b", "\\bassert\\b", "\\belse\\b", "\\bif\\b", "\\bpass\\b", "\\byield\\b", "\\bbreak\\b", "\\bexcept\\b", "\\bimport\\b", "\\bprint\\b", "\\bclass\\b", "\\bexec\\b", "\\bin\\b", "\\braise\\b", "\\bcontinue\\b", "\\bfinally\\b", "\\bis\\b", "\\breturn\\b", "\\bdef\\b", "\\bfor\\b", "\\blambda\\b", "\\btry\\b"] for pattern in pythonKeywordPatterns: self.setRule(pattern, keywordFormat) dff-1.3.0+dfsg.1/dff/ui/gui/ide/ide.py000066400000000000000000000252001217176075400171550ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import * from PyQt4.QtGui import * from dff.api.loader import * from dff.ui.gui.ide.idewizard import IdeWizard from dff.ui.gui.ide.generatecode import GenerateCode from dff.ui.gui.ide.messagebox import MessageBoxWarningSave from dff.ui.gui.ide.editor import codeEditor from dff.ui.gui.ide.explorer import Explorer from dff.ui.gui.resources.ui_ide import Ui_Ide class Ide(QWidget, Ui_Ide): def __init__(self, parent): super(Ide, self).__init__(parent) self.setupUi(self) self.loader = loader.loader() self.name = "IDE" self.pages = [] self.mainWindow = parent self.initCallBacks() self.translation() self.addMainMenuActions() self.g_display() def initCallBacks(self): self.newemptyact.connect(self.newemptyact, SIGNAL("triggered()"), self.newempty) self.newact.connect(self.newact, SIGNAL("triggered()"), self.new) self.openact.connect(self.openact, SIGNAL("triggered()"), self.open) self.saveact.connect(self.saveact, SIGNAL("triggered()"), self.save) self.saveasact.connect(self.saveasact, SIGNAL("triggered()"), self.saveAs) self.runact.connect(self.runact, SIGNAL("triggered()"), self.run) self.undoact.connect(self.undoact, SIGNAL("triggered()"), self.undo) self.redoact.connect(self.redoact, SIGNAL("triggered()"), self.redo) self.commentact.connect(self.commentact, SIGNAL("triggered()"), self.comment) self.uncommentact.connect(self.uncommentact, SIGNAL("triggered()"), self.uncomment) # save on CTRL + S self.seq = QKeySequence(Qt.CTRL + Qt.Key_S) self.ctrl_s_save = QShortcut(self) self.ctrl_s_save.setContext(Qt.WindowShortcut) self.ctrl_s_save.setKey(self.seq) self.ctrl_s_save.connect(self.ctrl_s_save, SIGNAL("activated()"), self.save) #self.ctrl_s_save.connect(self.ctrl_s_save, SIGNAL("activatedAmbiguously()"), self.save) def addMainMenuActions(self): self.mainWindow.menuIDE.addSeparator() self.mainWindow.menuIDE.addAction(self.newemptyact) self.mainWindow.menuIDE.addAction(self.newact) self.mainWindow.menuIDE.addAction(self.openact) self.mainWindow.menuIDE.addAction(self.saveact) self.mainWindow.menuIDE.addAction(self.saveasact) self.mainWindow.menuIDE.addAction(self.runact) self.mainWindow.menuIDE.addSeparator() self.mainWindow.menuIDE.addAction(self.undoact) self.mainWindow.menuIDE.addAction(self.redoact) self.mainWindow.menuIDE.addAction(self.commentact) self.mainWindow.menuIDE.addAction(self.uncommentact) def g_display(self): self.splitter = QSplitter() self.createExplorer() self.createTabWidget() self.splitter.setSizes([1, 4]) self.vbox.addWidget(self.splitter) self.refreshToolbar() self.setLayout(self.vbox) def createExplorer(self): self.explorer = Explorer(parent=self) self.splitter.addWidget(self.explorer) def createTabWidget(self): self.scripTab = QTabWidget() self.buttonCloseTab = QPushButton("") self.buttonCloseTab.setFixedSize(QSize(23, 23)) self.buttonCloseTab.setIcon(QIcon(":cancel.png")) self.buttonCloseTab.setEnabled(False) self.buttonCloseTab.setFlat(True) self.scripTab.setCornerWidget(self.buttonCloseTab, Qt.TopRightCorner) self.scripTab.connect(self.buttonCloseTab, SIGNAL("clicked()"), self.closeTabWidget) self.splitter.addWidget(self.scripTab) def createPage(self, buffer): page = codeEditor() page.setPlainText(QString(buffer)) self.pages.append(page) return page def new(self): self.ideWiz = IdeWizard(self) ret = self.ideWiz.exec_() if ret > 0: scriptname = self.ideWiz.field("name").toString() path = self.ideWiz.field("path").toString() stype = self.ideWiz.field("typeS").toBool() gtype = self.ideWiz.field("typeG").toBool() dtype = self.ideWiz.field("typeD").toBool() category = self.ideWiz.category.currentText() description = self.ideWiz.field("description").toString() authfname = self.ideWiz.field("authFName").toString() authlname = self.ideWiz.field("authLName").toString() authmail = self.ideWiz.field("authMail").toString() generate = GenerateCode() generate.set_header(authfname, authlname, authmail) generate.setTag(category) generate.setDescription(description) if stype == True: buffer = generate.generate_script(str(scriptname)) scin = self.createPage(buffer) if dtype == True: buffer = generate.generate_drivers(str(scriptname)) scin = self.createPage(buffer) if gtype == True: buffer = generate.generate_script_gui(str(scriptname)) scin = self.createPage(buffer) filename = scriptname + ".py" scin.setName(filename) if path[-1] != "/": path += "/" lpath = path + filename scin.setScriptPath(lpath) self.scripTab.addTab(scin, filename) self.buttonCloseTab.setEnabled(True) self.refreshToolbar() def newempty(self): page = self.createPage("") name = "Default_" + self.checkTabNames("Default") page.setName(name) self.scripTab.addTab(page, name) self.buttonCloseTab.setEnabled(True) self.refreshToolbar() def checkTabNames(self, name): tab = self.scripTab.tabBar() cp = 0 for i in xrange(tab.count()): if tab.tabText(i).startsWith(name): cp += 1 return str(cp) def open(self, path=None): if path == None: sFileName = QFileDialog.getOpenFileName(self.mainWindow, self.openFile, "/home") else: sFileName = path if sFileName: file = open(sFileName, "r") page = self.createPage("") buffer = QString() buffer = file.read() page.setPlainText(buffer) script = sFileName.split("/") scriptname = script[len(script) - 1] page.setName(scriptname) page.setScriptPath(sFileName) self.scripTab.addTab(page, scriptname) self.buttonCloseTab.setEnabled(True) self.refreshToolbar() file.close def save(self): index = self.scripTab.currentIndex() page = self.pages[index] path = page.getScriptPath() if path != "": file = open(path, "w") file.write(page.toPlainText()) file.close() else: self.saveasactBack() def saveAs(self): index = self.scripTab.currentIndex() title = self.scripTab.tabText(index) if title: sFileName = QFileDialog.getSaveFileName(self, self.saveFileAs, title) page = self.pages[index] file = open(str(sFileName),"w") file.write(page.toPlainText()) file.close() def run(self): if self.scripTab.count() > 0: index = self.scripTab.currentIndex() page = self.pages[index] self.save() path = page.getScriptPath() self.loader.do_load(str(path)) else: print self.noFileFound def undo(self): if self.scripTab.count() > 0: index = self.scripTab.currentIndex() page = self.pages[index] page.undo() def redo(self): if self.scripTab.count() > 0: index = self.scripTab.currentIndex() page = self.pages[index] page.redo() def comment(self): if self.scripTab.count() > 0: index = self.scripTab.currentIndex() page = self.pages[index] page.comment() def uncomment(self): if self.scripTab.count() > 0: index = self.scripTab.currentIndex() page = self.pages[index] page.uncomment() def refreshToolbar(self): if self.scripTab.count() == 0: self.saveact.setEnabled(False) self.saveasact.setEnabled(False) self.runact.setEnabled(False) self.undoact.setEnabled(False) self.redoact.setEnabled(False) self.commentact.setEnabled(False) self.uncommentact.setEnabled(False) else: self.saveact.setEnabled(True) self.saveasact.setEnabled(True) self.runact.setEnabled(True) self.undoact.setEnabled(True) self.redoact.setEnabled(True) self.commentact.setEnabled(True) self.uncommentact.setEnabled(True) def closeTabWidget(self): if self.scripTab.count() > 0: index = self.scripTab.currentIndex() currentPage = self.scripTab.currentWidget() warning = MessageBoxWarningSave(self, self.saveQuestion) warning.exec_() self.scripTab.removeTab(index) page = self.pages[index] self.pages.remove(page) currentPage.destroy(True, True) if self.scripTab.count() == 0: self.buttonCloseTab.setEnabled(False) self.refreshToolbar() def translation(self): self.saveQuestion = self.tr("Save document ?") self.noFileFound = self.tr("No file found") self.openFile = self.tr("Open file") self.saveFileAs = self.tr("Save file as") def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() else: QWidget.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/ui/gui/ide/idewizard.py000066400000000000000000000051641217176075400204050ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import * from PyQt4.QtCore import * from dff.ui.gui.utils.utils import Utils from dff.ui.gui.resources.ui_idewizard import Ui_IdeWizard class IdeWizard(QWizard, Ui_IdeWizard): def __init__(self, mainWindow): super(IdeWizard, self).__init__(mainWindow) self.main = mainWindow self.setupUi(self) self.translation() pix = QPixmap(":script-new.png") self.introPage.setPixmap(QWizard.LogoPixmap, pix) self.introPage.registerField("typeS", self.type_script) self.introPage.registerField("typeG", self.type_graphical) self.introPage.registerField("typeD", self.type_driver) self.introPage.registerField("name*", self.name) self.introPage.registerField("path*", self.path) self.descriptionPage.setPixmap(QWizard.LogoPixmap, pix) self.descriptionPage.registerField("description", self.description, "plainText") self.authorPage.setPixmap(QWizard.LogoPixmap, pix) self.authorPage.registerField("authFName*", self.auth_fname) self.authorPage.registerField("authLName*", self.auth_lname) self.authorPage.registerField("authMail*", self.auth_mail) self.tags = [] setags = Utils.getSetTags() for tag in setags: if not tag == "builtins": self.tags.append(tag) self.category.addItem(QString(tag)) self.connect(self.brwButton, SIGNAL("clicked()"), self.browseBack) def browseBack(self): dirName = QFileDialog.getExistingDirectory(self, self.locationTitle) self.path.setText(dirName) def translation(self): self.locationTitle = self.tr("Location") def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() else: QWizard.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/ui/gui/ide/messagebox.py000066400000000000000000000022031217176075400205470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtCore import * from PyQt4.QtGui import * class MessageBoxWarningSave(QMessageBox): def __init__(self, parent, message): super(MessageBoxWarningSave, self).__init__(parent) self.ide = parent self.message = message self.g_display() def g_display(self): self.setText(self.message) self.setStandardButtons(QMessageBox.Yes | QMessageBox.No) self.setIcon(QMessageBox.Warning) def accept(self): self.ide.saveasactBack() self.destroy() def reject(self): self.destroy() dff-1.3.0+dfsg.1/dff/ui/gui/mainwindow.py000066400000000000000000000411641217176075400200360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER # from Queue import Empty from PyQt4.QtGui import QAction, QApplication, QDockWidget, QFileDialog, QIcon, QMainWindow, QMessageBox, QMenu, QTabWidget, QTextEdit, QTabBar, QPushButton, QCheckBox, QHBoxLayout, QVBoxLayout, QWidget from PyQt4.QtCore import QEvent, Qt, SIGNAL, QModelIndex, QSettings, QFile, QString, QTimer from PyQt4 import QtCore, QtGui from dff.api.vfs import vfs from dff.api.vfs.libvfs import VFS, Node, ModulesRootNode from dff.api.taskmanager import scheduler from dff.api.gui.widget.textedit import TextEdit from dff.api.gui.widget.dockwidget import DockWidget from dff.api.gui.widget.nodelistwidgets import NodeListWidgets from dff.api.gui.dialog.applymodule import ApplyModule from dff.ui.conf import Conf from dff.ui.gui.translator import Translator from dff.ui.gui.ide.ide import Ide from dff.ui.gui.widget.taskmanager import Processus from dff.ui.gui.widget.modules import Modules from dff.ui.gui.widget.stdio import STDErr, STDOut from dff.ui.gui.widget.shell import ShellActions from dff.ui.gui.widget.interpreter import InterpreterActions from dff.ui.gui.widget.preview import Preview from dff.ui.gui.utils.utils import Utils from dff.ui.gui.utils.menu import MenuTags from dff.ui.gui.dialog.dialog import Dialog from dff.ui.gui.resources.ui_mainwindow import Ui_MainWindow from dff.ui.gui.widget.help import Help class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, app, debug = False): super(MainWindow, self).__init__() self.app = app self.debug = debug self.sched = scheduler.sched self.vfs = vfs.vfs() self.allTabs = None self.createRootNodes() self.dialog = Dialog(self) self.initCallback() self.setupUi(self) self.translation() self.setWindowModality(QtCore.Qt.ApplicationModal) self.resize(QtCore.QSize(QtCore.QRect(0,0,1014,693).size()).expandedTo(self.minimumSizeHint())) self.shellActions = ShellActions(self) self.interpreterActions = InterpreterActions(self) self.setCentralWidget(None) self.init() def init(self): self.initConnection() # Set up toolbar self.initToolbarList() self.setupToolBar() # Set up modules menu self.MenuTags = MenuTags(self, self) self.refreshTabifiedDockWidgets() def initConnection(self): ## File menu self.connect(self.actionOpen_evidence, SIGNAL("triggered()"), self.dialog.addFiles) self.connect(self.actionOpen_device, SIGNAL("triggered()"), self.dialog.addDevices) self.connect(self.actionExit, SIGNAL("triggered()"), self.close) ## Edit menu self.connect(self.actionPreferences, SIGNAL("triggered()"), self.dialog.preferences) ## Module menu self.connect(self.actionLoadModule, SIGNAL("triggered()"), self.dialog.loadDriver) self.connect(self.actionBrowse_modules, SIGNAL("triggered()"), self.dialog.manager) ## Ide menu self.connect(self.actionIdeOpen, SIGNAL("triggered()"), self.addIde) ## View menu self.connect(self.actionMaximize, SIGNAL("triggered()"), self.maximizeDockwidget) self.connect(self.actionFullscreen_mode, SIGNAL("triggered()"), self.fullscreenMode) self.connect(self.actionNodeBrowser, SIGNAL("triggered()"), self.addNodeBrowser) self.connect(self.actionShell, SIGNAL("triggered()"), self.shellActions.create) self.connect(self.actionPython_interpreter, SIGNAL("triggered()"), self.interpreterActions.create) ## About menu self.connect(self.actionHelp, SIGNAL("triggered()"), self.addHelpWidget) self.connect(self.actionAbout, SIGNAL("triggered()"), self.dialog.about) def initToolbarList(self): self.toolbarList = [ self.actionOpen_evidence, self.actionOpen_device, None, self.actionNodeBrowser, self.actionShell, self.actionPython_interpreter, self.actionIdeOpen, # self.actionHelp, # None, # self.actionMaximize, # self.actionFullscreen_mode, # self.actionBrowse_modules, ] ############# DOCKWIDGETS FUNCTIONS ############### def createDockWidget(self, widget, widgetName): return DockWidget(self, widget, widgetName) def addDockWidgets(self, widget, internalName, master=True): if widget is None: return if self.last_state is not None: self.maximizeDockwidget() if widget.windowTitle() != "": wname = widget.windowTitle() else: wname = widget.name dockwidget = self.createDockWidget(widget, wname) docIndex, docTitle = self.getWidgetName(wname) dockwidget.setWindowTitle(QString.fromUtf8(docTitle)) self.connect(dockwidget, SIGNAL("resizeEvent"), widget.resize) self.addDockWidget(self.masterArea, dockwidget) if master: self.tabifyDockWidget(self.master, dockwidget) else: self.tabifyDockWidget(self.second, dockwidget) if docIndex: self.dockWidget[internalName + str(docIndex)] = dockwidget else: self.dockWidget[internalName] = dockwidget self.refreshTabifiedDockWidgets() def getWidgetName(self, name): did = 0 for d in self.dockWidget: if self.dockWidget[d].windowTitle().startsWith(QString(name)): did += 1 if did > 0: name = name + ' ' + str(did) return (did, name) def addSingleDock(self, name, cl, master=False): try: self.dockWidget[name].show() self.refreshTabifiedDockWidgets() except KeyError: w = cl(self) self.addDockWidgets(w, name, master) def getNodeBrowser(self, rootpath=None): nb = self.nodeListWidgets() if rootpath == None: root = self.vfs.getnode('/') nb.navigation.rootpathchanged(root) children = root.children() else: children = rootpath.children() nb.navigation.rootpathchanged(rootpath) nb.treeview.expandToNode(rootpath) nb.changeList(children) return nb def addNodeBrowser(self, rootpath=None): nb = self.getNodeBrowser(rootpath) self.addDockWidgets(nb, 'nodeBrowser') def addSearchTab(self, search): self.addDockWidgets(search, 'Searchr') def addHelpWidget(self): conf = Conf() path = conf.docPath file = QFile(path) if not file.exists(path): if path: dialog = QMessageBox.warning(self, self.errorLoadingHelp, QString(path) + ": " + self.notAnHelpFile) else: dialog = QMessageBox.warning(self, self.errorLoadingHelp, self.noSuchHelpFile) return self.addDockWidgets(Help(self, path=path), 'help') def addInterpreter(self): self.addSingleDock("Interpreter", Interpreter) def addIde(self): self.addSingleDock("IDE", Ide, master=True) def initDockWidgets(self): """Init Dock in application and init DockWidgets""" widgetPos = [ ( Qt.TopLeftCorner, Qt.LeftDockWidgetArea, QTabWidget.North), (Qt.BottomLeftCorner, Qt.BottomDockWidgetArea, QTabWidget.North), (Qt.TopLeftCorner, Qt.TopDockWidgetArea, QTabWidget.North), (Qt.BottomRightCorner, Qt.RightDockWidgetArea, QTabWidget.North) ] for corner, area, point in widgetPos: self.setCorner(corner, area) try: self.setTabPosition(area, point) except AttributeError: pass self.dockWidget = {} self.widget = {} self.masterArea = Qt.TopDockWidgetArea self.secondArea = Qt.BottomDockWidgetArea self.last_state = None self.last_dockwidget = None self.last_widget = None self.createFirstWidgets() self.refreshSecondWidgets() self.refreshTabifiedDockWidgets() def nodeListWidgets(self, parent = None): return NodeListWidgets(parent) def createProcessusWidget(self): return Processus(self) def createSTDOutWidget(self): return STDOut(self, self.debug) def createSTDErrWidget(self): return STDErr(self, self.debug) def createFirstWidgets(self): self.nodeBrowser = self.nodeListWidgets(parent=self) root = self.vfs.getnode('/') children = root.children() self.nodeBrowser.changeList(children) self.master = self.createDockWidget(self.nodeBrowser, self.nodeBrowser.name) self.master.setAllowedAreas(Qt.AllDockWidgetAreas) self.master.setWindowTitle(self.nodeBrowser.name) self.dockWidget["nodebrowser"] = self.master self.wprocessus = self.createProcessusWidget() self.second = self.createDockWidget(self.wprocessus, "Task manager") self.second.setAllowedAreas(Qt.AllDockWidgetAreas) self.second.setWindowTitle(self.wprocessus.windowTitle()) self.dockWidget["Task manager"] = self.second self.addDockWidget(self.masterArea, self.master) self.addDockWidget(self.secondArea, self.second) self.timer = QTimer(self) self.connect(self.timer, SIGNAL("timeout()"), self.refreshSecondWidgets) self.timer.start(2000) self.wstdout = self.createSTDOutWidget() self.wstderr = self.createSTDErrWidget() self.addDockWidgets(self.wstdout, 'stdout', master=False) self.addDockWidgets(self.wstderr, 'stderr', master=False) self.wmodules = Modules(self) self.addDockWidgets(self.wmodules, 'modules', master=False) self.preview = Preview(self) self.addDockWidgets(self.preview, 'preview', master=False) self.connect(self, SIGNAL("previewUpdate"), self.preview.update) def maximizeDockwidget(self): if self.last_state is None: self.last_state = self.saveState() focus_widget = QApplication.focusWidget() for key, dock in self.dockWidget.iteritems(): dock.hide() if dock.isAncestorOf(focus_widget): self.last_dockwidget = dock if self.last_dockwidget != None: self.last_widget = self.last_dockwidget.widget() self.last_dockwidget.toggleViewAction().setDisabled(True) self.setCentralWidget(self.last_dockwidget.widget()) self.last_dockwidget.visibility_changed(True) self.actionNodeBrowser.setEnabled(False) self.actionShell.setEnabled(False) self.actionPython_interpreter.setEnabled(False) self.actionIdeOpen.setEnabled(False) self.actionHelp.setEnabled(False) else: self.last_state = None else: self.last_dockwidget.setWidget(self.last_widget) self.last_dockwidget.toggleViewAction().setEnabled(True) self.setCentralWidget(None) self.restoreState(self.last_state) self.last_dockwidget.setFocus() self.last_state = None self.last_widget = None self.last_dockwidget = None self.refreshTabifiedDockWidgets() self.actionNodeBrowser.setEnabled(True) self.actionShell.setEnabled(True) self.actionPython_interpreter.setEnabled(True) self.actionIdeOpen.setEnabled(True) self.actionHelp.setEnabled(True) def fullscreenMode(self): if self.isFullScreen(): self.showNormal() else: self.showFullScreen() def refreshSecondWidgets(self): if self.dockWidget["Task manager"].visibility(): self.wprocessus.LoadInfoProcess() if self.dockWidget["modules"].visibility(): self.wmodules.LoadInfoModules() def refreshTabifiedDockWidgets(self): if not self.allTabs: self.allTabs = self.findChildren(QTabBar) #FIX bug in PyQt ? Qt ? for tabGroup in self.allTabs: for i in range(tabGroup.count()): for v in self.dockWidget.values(): if v.widget() and tabGroup.tabText(i).startsWith(v.windowTitle()) and not v.widget().windowIcon().isNull(): tabGroup.setTabIcon(i, v.widget().windowIcon()) ############# END OF DOCKWIDGETS FUNCTIONS ############### def applyModule(self, modname, modtype, selected): appMod = ApplyModule(self) appMod.openApplyModule(modname, modtype, selected) def initCallback(self): self.sched.set_callback("add_qwidget", self.qwidgetResult) self.connect(self, SIGNAL("qwidgetResultView"), self.qwidgetResultView) self.connect(self, SIGNAL("strResultView"), self.strResultView) def qwidgetResult(self, qwidget): self.emit(SIGNAL("qwidgetResultView"), qwidget) def strResult(self, proc): self.emit(SIGNAL("strResultView"), proc) def qwidgetResultView(self, proc): proc.inst.g_display() self.addDockWidgets(proc.inst, proc.name) proc.inst.updateWidget() def strResultView(self, proc): widget = TextEdit(proc) try : res = '' txt = proc.stream.get(0) res += txt while txt: txt = proc.stream.get(0) res += txt except Empty: pass if res and res != '': widget.emit(SIGNAL("puttext"), res) self.addDockWidgets(widget, proc.name) def addToolBars(self, action): """ Init Toolbar""" if not action: #Add separator self.toolBar.addSeparator() else: action.setText(action.text()) self.toolBar.addAction(action) def addAction(self, name, text, func = None, iconName = None, iconText = None): self.action[name] = QtGui.QAction(self) self.action[name].setObjectName("action" + name) self.action[name].setText(text) if iconName: self.action[name].setIcon(QIcon(iconName)) if iconText: self.action[name].setIconText(iconText) if func: self.connect(self.action[name], SIGNAL("triggered()"), func) def setupToolBar(self): for action in self.toolbarList: self.addToolBars(action) def createRootNodes(self): root = self.vfs.getnode('/') self.devicenode = deviceNode(root, str('Local devices')) self.logicalenode = logicalNode(root, str('Logical files')) self.modulesrootnode = ModulesRootNode(VFS.Get(), root) self.booknode = bookNode(root, str('Bookmarks')) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() else: QMainWindow.changeEvent(self, event) def translation(self): self.errorLoadingHelp = self.tr('Error while loading help') self.onlineHelp = self.tr('
You can check on-line help at http://wiki.digital-forensic.org.') self.notAnHelpFile = self.tr('Not an help file.') + self.onlineHelp self.noSuchHelpFile = self.tr('Documentation path not found.') + self.onlineHelp class deviceNode(Node): def __init__(self, parent, name): Node.__init__(self, name, 0, parent, None) self.__disown__() self.setDir() def icon(self): return (":dev_hd.png") class logicalNode(Node): def __init__(self, parent, name): Node.__init__(self, name, 0, parent, None) self.__disown__() self.setDir() def icon(self): return (":folder_documents_128.png") class bookNode(Node): def __init__(self, parent, name): Node.__init__(self, name, 0, parent, None) self.__disown__() self.setDir() def icon(self): return (":bookmark.png") dff-1.3.0+dfsg.1/dff/ui/gui/resources/000077500000000000000000000000001217176075400173145ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/CMakeLists.txt000066400000000000000000000025451217176075400220620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # gui_resources_files( about.ui applymodule.ui bookmarkdialog.ui devicesdialog.ui errors.ui evidencedialog.ui extractdialog.ui ide.ui interpreter.ui idewizard.ui mainwindow.ui modules.ui modulegeneratorwidget.ui modulebrowserdialog.ui output.ui preferences.ui varianttreewidget.ui shell.ui taskmanager.ui attributes_selection_dialog.ui tags.ui tagedit.ui nodeactions.ui filter_add.ui filter_fields.ui filter_matchmode.ui filter_conjunction.ui filter_mime.ui filter_dico.ui filter_mimedialog.ui filter_only.ui filter_attributes.ui filter_bar.ui search_panel.ui search_customtable.ui filter_widget.ui filter_tagwidget.ui select_attributes.ui browser_toolbar.ui filter_mode.ui selection_actions.ui dico_manager.ui gui.qrc __init__.py ) dff-1.3.0+dfsg.1/dff/ui/gui/resources/__init__.py000066400000000000000000000012361217176075400214270ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # __all__ = ["ui_devicesdialog", "ui_mainwindow", "ui_modules", "ui_preferences", "ui_shell", "ui_taskmanager"] dff-1.3.0+dfsg.1/dff/ui/gui/resources/about.ui000066400000000000000000000100561217176075400207670ustar00rootroot00000000000000 About 0 0 446 189 0 0 About Digital Forensics Framework 0 0 :/info.png Qt::Vertical 20 40 <b>Digital Forensics Framework</b> (version %1)<br><br>If you have any troubles, please visit our <a href="http://wiki.digital-forensic.org/">support page</a>.<br>IRC channel: <a href="https://webchat.freenode.net/?channels=digital-forensic">#digital-forensic</a> on Freenode network.<br>More information: <a href="http://www.digital-forensic.org/">www.digital-forensic.org</a>.<br><br>Software developed by <a href="http://arxsys.fr/">ArxSys</a> and <a href="https://tracker.digital-forensic.org/">the DFF community</a>.<br> true Qt::Horizontal QDialogButtonBox::Ok buttonBox accepted() About accept() 248 254 157 274 buttonBox rejected() About reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/applymodule.ui000066400000000000000000000167641217176075400222240ustar00rootroot00000000000000 applyModule 0 0 519 398 0 0 Apply module Informations true 64 64 :/module2.png 0 1 0 64 16777215 96 true <!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;"> <table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> <tr> <td style="border: none;"> <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;"></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;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></p></td></tr></table></body></html> Module nameModule Type typeModule Arguments Qt::Horizontal Activate Type Description Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox rejected() applyModule reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/attributes_selection_dialog.ui000066400000000000000000000031511217176075400254250ustar00rootroot00000000000000 AttributesSelectionDialog 0 0 518 336 Dialog -1 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() AttributesSelectionDialog accept() 248 254 157 274 buttonBox rejected() AttributesSelectionDialog reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/bookmarkdialog.ui000066400000000000000000000101601217176075400226360ustar00rootroot00000000000000 AddBookmark Add bookmark :/bookmark.png Add a bookmark from the Virtual File System Qt::Vertical 20 40 Create a new category false true Category name: Add in an existing category true false Category name: Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() AddBookmark accept() 248 254 157 274 buttonBox rejected() AddBookmark reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/browser_toolbar.ui000066400000000000000000000121351217176075400230620ustar00rootroot00000000000000 BrowserToolBar 0 0 666 33 Browser 1 3 103 27 Icons :/view_detailed.png:/view_detailed.png Details :/view_icon.png:/view_icon.png 198 1 71 32 Tags :/highlight:/highlight QToolButton::InstantPopup Qt::ToolButtonTextBesideIcon true Qt::NoArrow 275 1 88 32 Search :/search_small.png:/search_small.png true false 120 10 50 24 0 0 80 0 1 4 Qt::Horizontal QSlider::TicksAbove 1 370 0 111 32 Filter :/filter:/filter true false :/menuedit:/menuedit attributes Edit the columns attributes of the detailed view :/bookmark_add.png:/bookmark_add.png bookmark Add nodes to bookmark :/viewmag+:/viewmag+ factorPlus Icons zoom in :/viewmag-:/viewmag- factorMinus Icons zoom out dff-1.3.0+dfsg.1/dff/ui/gui/resources/devicesdialog.ui000066400000000000000000000133611217176075400224610ustar00rootroot00000000000000 DevicesDialog 0 0 500 300 Select Device 127 127 :/add_device.png Select a local device to add in the Virtual File System 75 true Warning : You must run the software with Administrator rights 50 false Device 12 50 false Block device name 50 false Model 50 false Serial 50 false Size Qt::Horizontal 40 20 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() DevicesDialog accept() 227 278 157 274 buttonBox rejected() DevicesDialog reject() 295 284 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/dico_manager.ui000066400000000000000000000063501217176075400222670ustar00rootroot00000000000000 dicoManager 0 0 614 369 Form :/dict.png Dictionnary manager 0 Add dictionnary :/add_dico:/add_dico Qt::ToolButtonTextBesideIcon Remove dictionnary :/del_dump.png:/del_dump.png Qt::ToolButtonTextBesideIcon Qt::Horizontal 40 20 QAbstractItemView::SingleSelection QAbstractItemView::SelectRows true false Location Dictionnary's name dff-1.3.0+dfsg.1/dff/ui/gui/resources/errors.ui000066400000000000000000000024031217176075400211660ustar00rootroot00000000000000 Errors 0 0 400 300 0 0 Errors :/bug.png:/bug.png dff-1.3.0+dfsg.1/dff/ui/gui/resources/evidencedialog.ui000066400000000000000000000107531217176075400226230ustar00rootroot00000000000000 evidenceDialog Qt::NonModal 0 15 400 0 16777215 400 Select evidence type false 1 0 :/fileopen.png 7 0 Open local files or directory 1 0 RAW format true 7 0 EWF format true AFF Format true Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok Add evidence directory Add evidence files buttonBox accepted() evidenceDialog accept() 248 254 157 274 buttonBox rejected() evidenceDialog reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/extractdialog.ui000066400000000000000000000066451217176075400225200ustar00rootroot00000000000000 ExtractDialog 0 0 467 191 Extract :/extract.png Recursive mode Preserve tree Overwrite existing Destination folder: Browse Qt::Horizontal 40 20 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() ExtractDialog accept() 248 254 157 274 buttonBox rejected() ExtractDialog reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_add.ui000066400000000000000000000055071217176075400217570ustar00rootroot00000000000000 filterAdd 0 0 640 480 Add custom filter queries 32 32 32 32 :/filter true Create your custom filter Filter name Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() filterAdd accept() 248 254 157 274 buttonBox rejected() filterAdd reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_attributes.ui000066400000000000000000000014351217176075400234110ustar00rootroot00000000000000 filterAttributes 0 0 640 45 Form 20 10 113 27 160 10 113 27 dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_bar.ui000066400000000000000000000045571217176075400217770ustar00rootroot00000000000000 filterBar 0 0 453 30 Form 0 0 0 16777215 28 QPushButton { color: lightgreen; } QPushButton:checked { color: lightgreen; } :/run.png:/run.png 18 24 false 18 28 :/add.png:/add.png 18 24 true dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_conjunction.ui000066400000000000000000000017151217176075400235550ustar00rootroot00000000000000 filterConjunction 0 0 640 45 Form 9 9 85 31 And And not Or Or not dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_dico.ui000066400000000000000000000036521217176075400221440ustar00rootroot00000000000000 filterDico 0 0 631 50 Form 20 10 341 27 true 370 10 31 31 :/add_dico:/add_dico 410 10 71 27 Name Content 500 10 71 27 Any All None dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_fields.ui000066400000000000000000000026411217176075400224710ustar00rootroot00000000000000 filterFields 0 0 640 45 Form 9 9 124 27 Name Contains Size Date Mime type Dictionnary Is deleted Is file Attribute dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_matchmode.ui000066400000000000000000000023461217176075400231660ustar00rootroot00000000000000 filterMatchMode 0 0 640 45 Form 9 9 124 27 Wildcard Reg-exp Fuzzy Fixed 150 10 131 22 Case sensitive dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_mime.ui000066400000000000000000000015461217176075400221550ustar00rootroot00000000000000 filterMime 0 0 640 45 Form 20 10 113 27 160 10 90 27 Select ... dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_mimedialog.ui000066400000000000000000000032731217176075400233340ustar00rootroot00000000000000 filterMimeDialog 0 0 553 352 Dialog false 1 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() filterMimeDialog accept() 248 254 157 274 buttonBox rejected() filterMimeDialog reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_mode.ui000066400000000000000000000044061217176075400221500ustar00rootroot00000000000000 filterMode 0 0 667 29 Form 0 0 0 QLabel {color : green; } Filter activated 11 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Found 24 24 :/cancel.png:/cancel.png 16 16 true dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_only.ui000066400000000000000000000014011217176075400221750ustar00rootroot00000000000000 filterOnly 0 0 640 45 Form 9 9 85 31 True False dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_operators.ui000066400000000000000000000023121217176075400232340ustar00rootroot00000000000000 filterOperators 0 0 640 45 Form 9 9 85 31 Is less than Is less than or equal to Is equal to Is not equal to Is greater than or equal to Is greater than dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_tagwidget.ui000066400000000000000000000013571217176075400232050ustar00rootroot00000000000000 filterTagwidget 0 0 640 22 Form 0 0 Exclude dff-1.3.0+dfsg.1/dff/ui/gui/resources/filter_widget.ui000066400000000000000000000067371217176075400225200ustar00rootroot00000000000000 filterWidget 0 0 757 34 Form 0 0 0 / 0 Wildcard Fuzzy Reg exp Fixed Custom query Tags true ... :/encrypted:/encrypted true false Stop filter ... :/mail_delete:/mail_delete Clear filter Clear :/previous.png:/previous.png dff-1.3.0+dfsg.1/dff/ui/gui/resources/gui.qrc000066400000000000000000000302171217176075400206120ustar00rootroot00000000000000 DFF - An Open Source Digital Forensics Framework Copyright (C) 2009-2013 ArxSys This program is free software, distributed under the terms of the GNU General Public License Version 2. See the LICENSE file at the top of the source tree. See http://www.digital-forensic.org for more information about this project. Please do not directly contact any of the maintainers of DFF for assistance; the project provides a web site, mailing lists and IRC channels for your use. Author(s): Jeremy Mounier jmo@digital-forensic.org icons/logo.png icons/filefind.png icons/mime/file_broken.png icons/filesystem/file_temporary_128.png icons/actions/view_icon.png icons/actions/view_choose.png icons/actions/view_detailed.png icons/actions/view_tree.png icons/filesystem/folder_128.png icons/filesystem/folder_documents_128.png icons/filesystem/folder_empty_128.png icons/splash.png icons/actions/add.png icons/actions/add_image.png icons/actions/add_device.png icons/anim.gif icons/filesystem/exec.png icons/actions/randr.png icons/actions/maximize.png icons/actions/configure.png icons/devices/harddrive.png icons/filesystem/folder.png icons/actions/exit.png icons/actions/cancel.png icons/actions/fileimport.png icons/actions/filenew.png icons/actions/filesave.png icons/actions/filesaveas.png icons/actions/fileopen.png icons/actions/fileprint.png icons/actions/redo.png icons/actions/undo.png icons/actions/remove.png icons/mime/empty.png icons/filesystem/file.png icons/actions/info.png icons/app/lists.png icons/app/lists_attr.png icons/app/lists_attr_disable.png icons/mime/doc.png icons/mime/pdf.png icons/mime/sound.png icons/mime/video.png icons/mime/presentation.png icons/mime/spreadsheet.png icons/mime/image.png icons/mime/image_disable.png icons/devices/chardevice.png icons/devices/interpreter.png icons/actions/help.png icons/actions/up.png icons/actions/down.png icons/actions/previous.png icons/actions/next.png icons/filesystem/folder_home.png icons/app/imageviewer.png icons/actions/reload.png icons/actions/reload.png icons/actions/viewmag+.png icons/actions/viewmag-.png icons/actions/viewmag1.png icons/actions/viewmag.png icons/actions/viewmagfit.png icons/actions/rotate-right.png icons/actions/rotate-left.png icons/actions/rotate-180.png icons/actions/newscript.png icons/actions/script-save.png icons/actions/script-save-as.png icons/actions/script-open.png icons/actions/exec.png icons/devices/dev_usb.png icons/devices/dev_laptop.png icons/devices/dev_desktop.png icons/devices/dev_pda.png icons/devices/dev_floppy.png icons/devices/dev_smart.png icons/devices/dev_video.png icons/devices/dev_photo.png icons/devices/dev_hd.png icons/devices/dev_cd.png icons/devices/dev_flash.png icons/devices/dev_ram.png icons/actions/add_dev.png icons/actions/del_dev.png icons/actions/configure.png icons/actions/add.png icons/actions/remove.png icons/actions/configure.png icons/app/hexedit.png icons/filesystem/blockdevice.png icons/actions/search.png icons/actions/configure.png icons/actions/bookmark.png icons/actions/bookmark_add.png icons/actions/bookmark_category_add.png icons/actions/bookmark_rm.png icons/actions/bookmark.png icons/actions/man.png icons/actions/editcut.png icons/actions/encrypted.png icons/app/database.png icons/app/krdc.png icons/app/stats.png icons/app/kchart.png icons/app/kedit.png icons/app/multimedia.png icons/app/lphoto.png icons/app/disksfilesystems.png icons/app/disksfilesystemsdeleted.png icons/actions/unlock.png icons/mime/zip.png icons/app/agt_utilities.png icons/app/autostart.png icons/app/bug.png icons/app/ksirtet.png icons/app/locale.png icons/app/magic8ball.png icons/app/parallels.png icons/app/password.png icons/actions/comment.png icons/actions/uncomment.png icons/actions/agt_runit.png icons/app/ksnake.png icons/app/index_search.png icons/app/index_search_64x64.png icons/mailbox/folder_inbox.png icons/mailbox/folder_sent_mail.png icons/mailbox/folder_outbox.png icons/mailbox/mail_find.png icons/mailbox/date.png icons/mailbox/mail_reply.png icons/mailbox/mail_delete.png icons/mailbox/mail_generic.png icons/mailbox/mail_replayall.png icons/mailbox/queue.png icons/mailbox/mail_new.png icons/mailbox/mail_forward.png icons/mailbox/mail_replay.png icons/mailbox/mail_get.png icons/mailbox/mail_post_to.png icons/mailbox/mail_replyall.png icons/mailbox/mail_send.png icons/mailbox/attach.png icons/mailbox/appointment.png icons/mailbox/contact.png icons/mailbox/mailbox.png icons/mailbox/meeting.png icons/mailbox/notes.png icons/mailbox/tasks.png icons/app/firefox.png icons/app/browser_alt.png icons/actions/db_opt.png icons/actions/search_small.png icons/actions/search_advance.png icons/app/chat.png icons/app/toggle_log.png icons/actions/wizard.png icons/app/virus.png icons/actions/network.png icons/app/systemsettings.png icons/app/system.png icons/app/software.png icons/actions/scan.png icons/actions/messagebox_warning.png icons/actions/messagebox_critical.png icons/app/password.png icons/app/password_fail.png icons/actions/info.png icons/filesystem/file_knowngood.png icons/filesystem/file_knownbad.png icons/actions/tag.png icons/actions/menuedit.png icons/report/dff_report.jpg icons/actions/report.png icons/actions/rectree_on.png icons/actions/rectree_off.png icons/app/highlight.png icons/actions/filter.png icons/mime/add_dico.png icons/app/movie.png icons/app/vm.png icons/filesystem/link.png icons/filesystem/filehash.png icons/actions/root.png icons/filesystem/vlink.png dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/000077500000000000000000000000001217176075400204275ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/CMakeLists.txt000066400000000000000000000023321217176075400231670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin set(icons_srcs add.png configure.png dff_partition_old.jpg empty.png folder.png interpreter.png pdf.png script-new.png shell.png top.png anim.gif dff_folder.png document.png exit.png gnome-run.png list.png player_play.png script-open.png sound.png video.png applydriver.png dff_folder_old.jpg edit-redo.png extract.png image.png presentation.png script-save-as.png spreadsheet.png viewer.png cancel.png dff_partition.png edit-undo.png file.png info.png newlogo.jpg reload.png script-save.png taskbar.png ) #XXX it compile in res file launch the res compilation here #catch_python_scripts(icons ${icons_srcs}) dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/000077500000000000000000000000001217176075400220675ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/add.png000066400000000000000000000101261217176075400233250ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœÝ›]¬eIUÇkUí½ÏǽÝ÷öô ÓÓÃ03Ì |%0€Áj0 ‚ô…'M”D^|ñÁ⛾5hP£ $Ĉ$Œò¥ˆˆ0Î íÐÓ·{ºïGŸ½«jùPµÏ9·§[†MêÞJí³ï¹g×ú×Z«Öú¯:bf<ß&¯–[ÝžÔMõ¶.tï!Dúw®»90ªÇ˜)&¶·OtW®~ÆÌo÷|ûÚ÷.ƒÿžÿó»µÄ™_üÙwþÙd<ÚýüWÿ‰{×÷8¼±@ $ ,1÷ÔÁÎt›ûNßGì"ï{çûM&öÁßÿà«û:·Äùùµá0ܵWÚwüä¯põð O‚O^ÌÞõ=,Y>ö#€ œ=}–Æ5]Ä‚`ÁH’PÍ‚'‚c ÄHÛ.Ù;¼ÊbÙb®xÇÚpævP'¬ŽXˆD¬34)–¬¬¾b1EÌ]ê8lçY DA½`RH1"*$± BTÌ •ìÌŒd† h•w‹4àâ@ NÑJ°h˜" bXkhÈ«/&$‹ 0Ä•Ïa¨òÄ+ÎiÁg{O1Ëf³§‹)‘RÂ0xA Å|Ñ_p.}I‘¤HÊ HÌ,‘ Ð 6ËáþÓ+'8çp•â¢b$ %UK„`%k€¥lŽÕ–:P0°ô@ ê² 8ç²&˜’Ì…ä ñ ¬ÄlÊ 1ü |@Ñ€lÿŠA’ &¤$˜«" sIÄ”0IÈ “¬R÷nåÅ+š„d‚DÉZàŒ¤e{$Û²" è_¿ŠS$`b$—@…¤q½ äHyÐ6¨ì5 ›€dÁUòþ!çD†©‘4B’ìR!ä‡CQE\>H6€œ ¤¬~o·A³Aqå ýJJéj¹KŽ óO"‰W^ÀÖï° бTd;W)‚³¼DVÎ;¯þ厰p¨6Lš-ƕߘ"™aÓ†ð‰D$– ZÞvON9ybký´ï ´eì'™s™Œ4­Æ8uÄâØ9ÒËán\]ÇGËq€ª2ž6HðF<:$p|Wø>i…—ïÙ{Ù4>t8? ª=7ºtPæŠýöÌŒ+¶Ýßsмaão*xui:ÚºãåwüȉgæçÖÂ¥¼º«žr)SÞþ=ÐrÏ÷òʳ¯­?uð©Íf³K1D/àžGLà^++b•X8F[wKÐT5¯ÁàÁ—?Äþâà;_úÖ{g~Ù+>ôžŸ{Ï«þê3ãÜåo3¦âÂÑbÔÅ–Ëh¯Ù¼_2?õFÓD¼o9==MCCˆ½KO‘"Ñ ŒQ!Ô9Þöê·ãÔûé=õšV¹tõñ¨Ú’“¤Œe¹×–ë¸ñ·[§G4®æ—Þý>>øë¿ÅoüÎožü;ßú;£þúãÿÞ½îá×ðàÃc/KlO·X¦S£j<¾*½v¸ÊçÈ®vxç©]M¥5^»ÆÛßòó(Ê|9‡bIVÔ:Iòý$X"G˜FekÍ'?ñIÄåmÈ#Ð…À|9çúþ³,/Í£– £ól·Øï²;Ùek´Í¨ÑÔ5uÝÐT µ¯¨|…w^+\ñRɲ=lj1B v‰m×Òu-m8Bê ‚º–§Ï=ÉÓöĆ™5î™ãM9Sê • ŒlŒÊ¨édÊþáu¨ŒÙb– ³Å‚y»àôì4‡Ï^cÑÌ©¶+ŽÚ®-¯ry1áÄd‡S“SœdÇÔ¡¦ª >«¿ârên¹èc$†H‘ÐB×Ñv-m·¤ë]×Ñ…ŽÐh锣‡Üˆ‡ˆêŠ,í>&´®ïijóïºDcàúì:Ož?G¨#œ(Û Oi1?\0[Ìq2§MKÆiD—ZiÁA¸ÎV·ÍN·ÃÉÑã0¡òU&;Ôe¤‹Ý¥hk-è"¡ „.Ðuˆ^ø® ¤Ö¥"KCbZ±\8)I‘9Ã4!N1Íœ"ÚG’ %žÌ¿ù¹é>À¼›ˆ¸:ûÇôûwe+™Cç»,˜ö*GÒÆ%ûÝ>Ûõ6'ê“Lª •VYxú­ÇHZC¡Í+ŠÄeBËBÊ ±©‚3Ìêq.ßS5L”$ù½)Ã…bˆ)¤ €¦Â8§Ì8ÇóÞ°â×´]‹-ÀBÞÞ’O´Ú–R˜å¶dÄi»%ûËëŒý˜-·ÍØO©¥ÊÚd)kALkBXiBè±0d¡°0¤3Ds†V•äÑ)ê­h’4gYã CÉ,“š‘’–Ñ¤X,|cŠ˜ZÞºýÍôÕÚÖ‚ùÜ «¨Ë¬¨uŒxï©BVÿ¥[²/û8ñŒuÌT§ÔÒ IÖ#¡[‘…™+Ì Y(¢Yp©«T)x+]Àå$*û0QL2eœ°5Õ– L‘˜¯%*…¨1luÑ€ÔP±ì,h!Ý-¡g°°>¥ìÍ«ª¢ëºlÿέ´ä}0ðÔLdÂX&¨9RLYåC ¶ yåeF¶}5t¤Hm¤Z¡2¤Î‚‹œ—šSÝpt몘dó³œsH4ÂêˆU)prÁIvdf %âÔ¢!El´$ÆHUU„VÂ«êªÆ×›ILG\‰—!)4Le‹† s°… sC––¹ÂưÆHµ@“ÕßU ÞgRµø¡ì‹Ê3éw€µó-C>wàò¢‰³L·U «la¶›„CošÄ R‰ Äq"[BpUŽÕ•ÕÐub™Ë[‰!®…g±Î¨»†“ìpÂvhºt‚¹˜nd=V†VõºÙm€°@V1@/øjîjX¬ø‹$‰TÌåeïs)ߣUIȃÀš‹7°%Ç2±‹)øé.ÍŒÏ&f†ÅD ¤%,º%³ýK\ž_a*[ìžÜåÄÎ6®QldX“pãU °*ïså<Þ9œú¢þnmܬåøMêçar j¥×hÖõl·9UŸd|²ÁÈÎéæ¶"'ê2ú\ýÅI)jRÞœÊ$ú£/ÆnÄôÚ)®>}‘ÐF®7ûÌ÷™Ô#vêvü.“zÂÖdÊ©éݨ:*çqÎãÕá\¾ßŽU² ÅöûÕ·¼ýVl)›%£ªj¦“Kœ½ëN®]=àh™5 ri ÕNÍÖ#St¡8‘ç’}•FYsöRÈMÖZ“ÊRLt!2f‹—†×réâÓ¤6!5¸)0…_p!]äÚâ*»²Kµå8»u––¦Q9× äf˜¼Š?VXqÜ`)s ¾r<Õó? ìíg‚Ãs|Ü BnÂL·+NížÂ*xä¡7q¼ŸÅ‘Ë´·€ÔÀ¨?m”ªª¨ëœ[4Uƒ8¸|x‘¸¯vü×õ¯ûí –•À+¡û×±q¥[Gö?-츚‘5¼åÁ·òŽ7¿‹o>ñxsñÏŠÇaçžù܇ÿôÃO^Ü{&Q“9¹íãjÞw+ü&©XH*+O~o›Œ½£kI½«¯ÞsõmOì}cëuüt>¤€fÝ}å³Ã«ªMÕ€þûðqî龨ý}ìÒÌÄ+)¬Í‘Ɔúo‚#ã‘u,0>ùøßò…|TgG³=\N‡/ì\þݽ´±ª’¯¡´õCÿ/‚riåþÇžúÏG´‰[Z¸W©Šê×¹»Ê¾ª«Õ ¾âòì—÷/…ÃÿX~˜¡TÏyàí¸ÁçÜ7ºRg?þ8 Ç5o_³9pþö"}÷vì¤èÚGL—Ë…Y ¥’lB}Á´–U*Ý÷ÊWY#\ER¥µ.Ÿ­¸b5—oÇaÿÿ;)šñp³Ù«ŠWÖâGújÑFã½_kA!X‚ó¸èƒ3wû‡=¿6ì)±Xüˆm8ϾbìüJøU´ç] z<æÒç"VmØÚ`(T?”Ý$G›aîñîϙۦߨ yVë3é WÊåºîÏA*ÖXmÃj@ÜØ§7(Q9À&Úg—¢9£ƒAkƒÃБWÝ6"I½‰Â>ÖKz[RëUP †u‚]¼/—C9 ù\áóª ¯¿ŠðlÃ;ÁM!nSï_­öMIÕ ÛX‰ÅoŽ o!Ðm¿¶Ó×÷lƒûëëw¥õéêÍB¯H”Âég2ƒµ#¨ @Ÿ±•—yGX Ø“¬›Ýú“¢©0S›Á°NpÓŽ7SÖt{âÆ5›<å@í¢°Fd-lŒÇ…‘ãŠPµn#Ý}A~c¤? °¡R2Û¼ï!FB ¤˜H=šÀ §Ä¼8¦Í%×èˆdµ¬úlVÊåŠrªÞÍu„!ç8Ø'œ˜lQ™C+^ò ±Dè,à¬EMqæè¬C‚‚$)'ÝÕ¨æÛv™¡Ô`XÆ™{î¥Þsì.¶¸oþNØZƒxsT±¢ê*ü"Ù,¦ÐVT7Æ42bÞ͹AýýjÃÐÁk~ôuòÞw¿O|ìãö%¸ûA|Ñ+í‹üÛpÓðÛã/ëø×–írGU¢¨ä“` ó±ÎúÚ;G²„ªs£f|p¸øOÝîùχ€ÆÏw3á[U ò(@‡ã"ùìÊ­ÿýyð¿úotÿðcIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/add_dev.png000066400000000000000000000235641217176075400241750ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËgAMAÙܲÚ'+IDATxÚí]kŒÕ•¾UÝ=?ÆïØ;$vÀ1~0…$€QX¤Í*i¥hWÉZQ„ˆV Ù?Y6»"ùµdµZC²ÙXX¢2F`ƒa†{l°ñxüž±=cÏ£{fºkÏwëžêÓ·«º«‡ÁîÆ}í«ª®®©®ºç;ïso)ÕhÖhÖhÖhÖhÖh—VsêõÆ¿ÿýïoÎd2jbb¢¨'“IÕÒÒ¢;ö©÷<òÈ#= R×}ôÑv"ÞZ"êæ±±±eÍÍÍsçÎí ýŽ¥K—ª\.§òù¼jooW³fÍRžçérG}øá‡*‘Hè>44¤{6›ÝqîܹT*õ.]»‹þ¾ë;ßùNO5жmÛÖA›ÍDÄ›Óéôæyóæu€°sæÌQDxE(½y§üíaíôéÓêÌ™3j``@õ÷÷ î @¼JàÙqÏ=÷t5pÚÓO?½–¸p qéÄÉk-Z¤ˆðjÚ´i¡DæýJ„/Þ—ÇHª}}}$)ž¡{zök_ûÚ3 L=ÑÛ‰›ï#~/q¶&ú‚ ŠˆÌbüB4VP'ÜΟ?¯>úè#`xœ¾ûÙm·ÝÖÓÀÇh¯¼òJ äC¤·áÛ/^¬44üB½¤ÂÉ“'Št?»å–[ži J¡¢~8:9Z->¬è06Ñ`Dž={€€$ØzÓM7=Ó@y·“+Žÿ{}æÌ™·ƒó±­‡I÷’0<<¬È‘‘‘­›6mêjÀj»wïÞB·mÆŒípÓ@lp;m=6HŽ5 Ô©S§pü§´ÿ#R —<:;;ÛIœoƒžǃàïMMM¾¯÷ Àkà8\IR=ôœ÷ñ‹_ÜqÉàÏþ3\ºWHì·“¯ ¢Ã¯EÿqÛøø8KzttT{Š­7nüé%€îîîû ò~%î×ÇÀõèŸæ)€p4Û m_¿~ýý— öïßm ö5§£CÔ‹‘7F"ç$°oö»hnY·nÝÀ§ >t¾tåÚÚÚ.âË@-0‘g ýšÁ¤-³ÜG:p–¬} Ÿ ¥K­AÝA%À@„ÝCc›h}u×§N:th-Œ~è<Öùˆß׫‹7• *@ÔãAãóÓµk×nýÔ€ˆßN¢­óøñãðñ™øŸ7o*l H’w­Y³æ™Ozzz¶}ôÑG÷AÏãá¸ø¢ÑнHG4dçÏŸ?@Ç–×¢=¬’ûQœqB¡ . tߥ¨óËr• ~!>»¨¯¯¯}Þ¼yÑW[ëZôöö¾òþûïoF”¢núôé Ñ_¦A€9hÌÙð zêR9rd3=Ðfˆ4 š: î/ï y´dÉDJÕUW])p]€Ú½o½õ–úìg?«u@À²F‹\bHJxÆ&ØÒÙÙ¹µ–lØ€îšAtü4P¹ø¡ÔmïÞ½í«V­ÚB‡¯+;v ÈU(ßÑìñãc…`Ù{ï½§®¼òÊ›ëÔÖvwwkCÃÕhñ<.5;wî"„›ëΠ‡¸ÆCà¡x¿Ñ*7Î"IFÒ´£î q±¹ß®+(W&Vþ5OàBÜ7Æ ¥qäMéÚ‰Õ«WwÕ P"ÉxNràB ž=7 Îüù YõûI7p>Æ c‡Ž22úíöº’}}}Á £ ž²^ðu§:ý67€…q¾ ›¸¬‡Ã¤„]>U"ÕB\:Æ û\ETwn «ù0poØÒå  9?€»ýYJ( `s¿$.¾“Á+>W‚a²DÁ1&<.vÃõ!ê¸ñ+V„~ÇypÔÀ7=Fø0⇡Zkœ'2lPUfô8Fq-FM“ÕpgãÁ€ †r·1ÂG JçÛ*[y ƒ}}ž"¯%KÃÑ«%h­qUn`5MŠCž éÀR"J¬W@\0 È òº¬ò ³™Ë?®€p0O©+ îÂÁä©]Ç@bI@1 XBq$@”KhK€(9ŸE¾äl›ï ßcH N×uê Ðý»víÒ"l²–sy¦ïK“u4_žËª!Ì(´¹°X€é<çÉο/·òž&ñ!M0~޳|ó^Í £Ã^¡$ʬD|NK"ÊÏåºí¶•@\¿?Ê[‘ aà7ù^X"TÛŽ?®ÿI¡ZŠ¢Æjþ:vì˜:zôhP ×xd±>Ù.è`­Ó%1¥!´ÀÄ—’@‚€UF\•€s!=!É®¸âŠú4ׯ_¯Nœ8¡>¬Q—ø’xQ„­ô}˜M²À•.ž$¨M|[ìK0ðßðoÄ•ÿâo„ bà]lÄŽÚ|þóŸ @‘Á°Î¢:ÊÕ³‰õ}”÷o£ÀTÎý,§ªìkVè}„Òqþ† ¤ i Ô¶À‚MË—/Ga(*ƒ5’£=x>9U¬‡‡mË}_I„‰~;GÈû–vGØ}”Óé¨äqºêª«XrÔŒPUÜö–[nÑ[÷À‘¨ëÇW ûVëÚ1„¨ý¸÷·³cwè}XÿˆÏ+954]º*@À#€EÉ0í…¥î/'¦+éøjz”xžÌoFIŸr*¥‹º¿µµU~óæÍÁ8vwwÿéæ›ovê =¼s×]wé‰ x0è6D¥Þ—ÜXmd/ÊЋcý‡©¡¨ë•»§¨ßŒs=„Â?øàƒ@ €–“g~þóŸòmÖ fñ¦ƒÍ<´··7A9ч•Äw˜¨¯(ÈjWR9œ¦T†€púœ‚«pAàÆ!>[üv·ß}÷ÝÚ€QÂcb$\ŨØ{¥jݨïÃ’;•®]éüJ÷Ö=ÒÄØ¢Ã̓úC¤/IÀon#©ØªH÷S')æ-z›èéâïq>þîb­§;ßQ-€vCÅð7¾ñ õÚk¯éA‚­€AÂà@- ™ÄËÇ”ãH»jÇ–¶¸‹øUâîJYBû3žë0åÀF¥/Ô"Œ=ü&IÃÓkjö‰©¥@ÒW®PZôOø¢?9nT…럫Üڀé`<8¬ÜeË–•œ®¿á†´ÿ îÇÔq4`%XPa„· ®­FD»šÏàtò€ø <;(dÁg]ë@#‰@_s‹ô¤Œ=ψ?!ˆ‘I$k\€põ  ßÃVV®\©U†ÊÀÍž=[‹Iqá(.X¸ÍñqJ¼+ÙöõÃŽEuH™K¼!ÉÀõ¼F ~c‰7K ·ÎQ7\¾Iµ§Û5Ñ™ûAd?0=¨”‚@?yþ˜:zâ5È›ÚÀêÕ«õÄFHÕA0£‡€ €M ƒÀpøØ¬¨©”‰ÁÆ¢M¤(bG©„J:> r^w.c}sx¨:–‡¸u´oÀQ3V«íkTÊ>iˆëcCpNÓRõZë0µkìÖÁè‘Âvuu©7–•È rÉ4€¿Ea Ô‚­L®–Ä «Öµu%)¥ ˆnײ¨‡:ã5‚Ñy \yýd"¥æ§—©öæyª9Ù¬צ½W²u0<~N §Ëפ  ï„Ú‘Ý‚x‡Q[ƒqíµ×–½§B™Ó8NpÙe—iµ€òqH®Ó³K°d&*Õ[ vi·ä|»6 "à…¸G „ Z.·ï… ¤žï}Y-=vµÚ0AÓ±`ø$ÙýÓù˜¨„ÿØ÷ïêÝ3GjÖÐ÷‹‚ñìc Æ Øñ°Æ+ga ÁQP¨2ñ|-—`3‘8ÛV)¤ÅýaºŸ‰Íǡˡ¶po­Ìì¤0#c ôo‚>N“ß?Ú_Bä`+ã P$é*s‘fÛÇ6×­[§Þxã ­ÿ`åC `ððâ4v£ Àe° N±/u,:‡¿i%•`Q¾–€wüpa(Knˆuã7Æ^5 ’õ¸¸‘EŽ€¡zX $ ûåO^Ewƒ³q])]XôÄ0rìâÄ–=…,:äìiz]ËËA_›û‹>;8ާ=…Z ¢a_ ÒÀÐå,Rñ¢F ܦM›ªž<‚‡¹gÏM4ü=ˆÏï dbðeBªšd½…^Çoâžñû¼´«ìa’&4 „{qP¹®ÜoÙýãÖ° pQåWoß¾=4ˆP^&–ÿÏ>û¬^Jæê«¯žÔ «!~Pb  áwÐ^§®ŒÉ(Uñ âAÚ [ Ûb÷ÎÆ=s#JrÙnix?¦=]"^„M`¶P5.ÐP´mÛ6M|”<á5®àÚÀ¢DÌ!`7|Ü©dh\zÆ.%ÏÕ³;Ô‚Y›7˜®ÎÄ–=®ªŠò:p)ž3Óš1 €EbGËúbãOœ¸I¸1!À' Aà9}pÙHcI€ã0ô^}õUõöÛoWÔÕµÜl[@ƒkøæ›oj¼úÎ-H2'õ¶Ðóæì cQ™ïµ ¨ N@Ip/¸’àòË/×"YÎãcùÇ?þQëtH‹ µ´ÌT59™Ï‚X<~!–.%O¸>µÈ[üoö„°%„VɈõ³O>ùdÀåh 4J¸8D kíÚ6¨0p»wïÖ¹H‡ziàxØ{÷îÕ[|–ÕÀœ.ówóçç„]P¼•À­a  o× d)—A¿ùÍo‚P)8ÄæI#²„š‹F¡à1@°ËWkRϨ…¸çˆ&¸^F yfÿœq½U$t ¡†ÝÀ—pÑÜùûú׿®^zé%í¦a`xe¸oÌýöl«*i š‹Ñ8ùÃ9¾OŽ#pn@†Žñ\:EœËIrJ]ÀÀ pk<kî’#ÒX³fæ D uq„I¡‚{8gÎ>µ€mUËÅ•Ø~°§‡O©î3AÎöñ´04^¹„sQ)dNq»mÆDÐÉ¥|$± @(„}õ‘¯é@Æ6|sDü °*†Áñ;wî ÖÀà°MÀ±Éáq+z@¨ vódRÒkö°'Â*.!~àä©êQË2ÉÃ÷„ó9Á@áLµ6µF /¼BÎωŽ* tkÝ `kÕ@È Ú ÇÜ·oŸ&bû ‹ãï »Ê¶R× €¨aÄ ;Æ6ˆZTÉ^H;[ Ä×6yÉ®S*Îz¦üÛ+N9ü5îbN ‚;ˆ“cÕð›nº)tf0D>"€P!ÙÕÁú•‰)1ÒF«Ü­´¨C!Ãö¥¨—@Çe¦ ÏA¸o<'ž_„Òç¶D›ŸÿwØ¿÷BÕ€bñ/Rþ 0n`ª¡X /‹àÎ5×\:ø .Þ+aWö ¢aÈú@ûâ•Öù ;Vnʶ8¼]ýï{¿R}Ã'‹fã{fß³ôÃöCŸ1Ùƒh¾ P¹î·Õ€´ô}º¾ <”úõO*)šL"o²« xª‹„Ôýêïh[­€Ï|=D:B³ÈÞ•[îâÄå"Jü=W” IH‘&ŽÃl„( €¾ïäŸÔ½õ¨jY¬Ô´E…âLÇÞZû¿^•.áàÈñTFÓ󶇂£Ô€2j@f!9æÏRjæ˜õûb[´¯T±Êpâáá̘Z{`H½¢UËÕV5ÿä•W^©9é[,UÀà(giƒð\éNÇgØ <$„y×nq+­(‹CÊéó÷û÷¨&ض$m\³uåçp!gè€{Bȵî¦}BúRÀ‹TÌýA…6=•nÆr|Öï Ó&ºµJEjóéO©ös9~Gl@ÍEþÿwÞÑõ€¨ €¨GˆÆ«ˆÅ ®@2ào¨ žM;vƒ|'AÙ”A[*èï¼¼J¥ýrm.Á#¤ƒ=øöàzr` R Ÿò@?¾/‰_ðI ô?¸¿D*â÷%Ñm8‚îNV†‹›¨ÞHÑ`j@ìc`‘ƒë‡›ýõ×5Ñâ,‡óAd¨Ž`OÈ~¿€U•#myœ‡sìª^¶#£#A½>ÏÓÓ’ Q*\7\ ”p¿*öšx9 (á~ÛtL ÀHI7¡R@EoËéy•à’Ø„l /t€zèuä×¹8þ?ˆÁkàT²Òùõ)& :<$‹´Omj ¤` ÀêæŠ H Y*¶ø³ŽD*¶N uP¢ âHK÷3²)a8ÅP^©`âcÇq}  '‘„Ù$*â~¢Ô€”^ñ}ÛqµJH¨NaQ#t¨BÄŽÒ0¹D<^)/áú믯êe’ *ì ,ªÀI PƳ‹ÌêšE®~K¦iíj_l;Gvª\=$¦jð §nBÔÍa’ðÜ´~FMOµ `…‚Cá8~Ôÿ6/SMÓ’êX¦Ëü¦S‚TNy)OüìxžàéÅ€»hÑ¢(¥ÌºFàÎÛn»M=ýôÓZ#©ÑϾ2'Èú! w-AIXp4JÍ^*–kž‘$KÑlñ_tŒþ$0¯áµ´uq¾kÐ'€+|p½U¦´Ky…ó çNã•*VèÉD‰ñ5áeKÝ@Ût„d  ·$[Ôü¶%jzS»J9MV¾ `7ðq/°?üãy±¯Ç¥¢gÞï=DLV2ëPéæ$éÚéì7iàõ¬P$„à DÂy~Núà Að‚I$‹&óJy§b YuÀêÒ‚CÁüNCž…ôÎè”Z¥ÔŒ¦ÙjéŒ5ª5ÙZ,R w:y…ãÖ1¹-pY±hÎUãÇÍ÷ÅÉ åª‚q<Ëìäb5¿i¹ ¦ ²‘y&ªÇÇ(Ü@ æ:%’ÁHl³Þ9"â¸jMÌÔŸó¹PD>tß+âtƒÁ08~šÔÀX<°lÙ² ªKé>õÔS»e*bùÎ;ïT¿þõ¯µÁ€S¹âGÎèA!T\¾¸j!Ž„ˆªÜ)žml\-"ÊpîœÚ;øV‘ ľø¬‘ï‚Bûz¸p.s²£ †\ œR±¯l·ÐS¡€ÀmɾÂÙÅ\Ï{ñsy³•ß\ïùÓÑÍöèÈáøAÄý.Ü?êÎŽ;†NŸ>ýª$ÜÀ/ùËšÐ\ÏzXN¼àz|H€W›ŠR­¨¿Á¾¨ÔÉ{¦OÉ­Ÿ¾-ªàq •<Ú§¢{ìâ¶^ð9oŽ™­èŽé…cyá.oqoƒß*ŒrÁoyæ·ƒã%ÏS¨Eä$•3Ùl éúWgÍšu³<†|¬qd‘ nFt a_YÆÄáÉ8Ýd«ÂŒ@û;Û^P¬ ÄGˆ`;hêA|öŠìñwE*!äzªÀí: ìDHq?^˜ÕÄž¨2ö9Ó¨eôDщÌ—‹bà»ßýîó/½ôÒßw/”’Aàxè|Hèb.ªàd̶aŸ§|ñZÕVÅ™®Ü-®ÔÁžkpBl;Ñ» €#ì©ÛùÜ¢ïÉJ‰Y Œ‚Z‘Â2²,Ž M-y Á?cD†¬J©ˆ¨y":¢@º“õÿxع·Þz«.±yV…òMb 68_vöÐí¥\'#‚­#%@Xâш]/¨ì5[sL‹h£8ëÄþ.íÎE¨€|‘hw,ÕPØæQú7⳸ÏêJ>KP†^x}qUqtžŒ: 4Úæxàÿ{þùçÿ’ÜÃÏ„UA¬ïß¿?˜ø ãDXÜËŠZ¹.¿tÙ’ÇßpØW.Ø #W‰ª!ð«|¤Ü&òÓ]ãÿ{ÅÆ â‰¾tpB¾3mÃü¸7R¢<Áý¶H÷¹ÐUÍn›1ì¼//¶ú{×7þ‚ã®oäé­ç/?ç#8¸*0Ã$@9'ŽÍÑçh sD€<)÷»ßýîßï¾ûî ³Ì°P:cPÖð¤ H.³ B¢Ä;×Jâòl¤°>øœÁ‘Sê1D&7¤æ6/Téd›±ðU‰õï…[=Até ˆ}剘‚ÿ÷Cù>uvb¨Äô¿Ñ׎%âÒS š®0ÑEä_^EûögPâ%˜õ ÆòãêàÐ^ý}Q¨·œˆ¥AvÉb'Æ7˜LÒ`'wïÞÝ¿~ýú&ó_ÁœáJ[xï‚`œéc®·ß)ö™«…íï!*¿nÆQoŸy[µ [Õât‡jN´$ uD=E=i¶…N¿é¤´ÄÐß;8§É?ÏIÇô÷Žù{§‰nVõM¼OžÐ«}øàò·ú³2ûZ”{Fl{ÆŠŸÐŸÛ“‹éÚMþoÒ6á¦ÌgÑÝÂ~ʉØw çb¿Ð=Ð¥ºNR§Ï{$¨T¿W™J D-I L#§‰m´m#B¤ipÛž|òÉ#®¶WØàÏ\?‡$O#Öה˿ÈJUÒ÷¼£3JÈþÚÈËê­ÌN"OÆa”VÞ‚½oŸV!dÎß°F©;×Aµ¸3D¸X“rn 1P™“rÇÕ‹ûŽ«7|Âõ_žê¡¾Uý­z¦\ù€ l%ßFÜÛF H@GGÇüŸüä'ÿÇõ¹þŸ9AxÒ.E£QF OG—‰NGAf í$’}¿ NH-^ ˆkyõyÍ]é7”ºîêŽõWj(G¸‹Ò†•ÁA”Žþ N|¤~¿ï„Úµ_ýˆˆóð…¬ ¬T†˜?yò$b‡YzЬÜžùÁ~ðDÄŠK[a0ù5ê x ()C¥ÂÈPQ–ØK$Pâ¼p:,qd† >aË è…‹?Ù~‘sJV4ÓEXè©à¶¦»~×V=Ô‚[°þ/VYxœLMžÂ!ÂÁHø ÛÀ%qž#›àÍM›6m N™YiÍ=ö¸N… ¼¦›\‹Ïåaö\<®)àåÚÊÕ F-Åv< ü¾^ï<|æëƒà\œÂema×?ÖtD¹Kª•‹gku=ÛÅûýÁ¸Vû†Õ‘~õªz¡ö‹†¾Íq4áFŽ€8Ã¥r:Ôÿàƒ>ôðÃ?@6Áª¸I *¢ˆ|H$›@È3w "dAoq¼)’£–„ã‰!ü~ŽIðoHµ€"R õ„sÞ.—w 'µ{ɱ€¤‘WÈÑ¥ CXûÓý'NdˆHH; >À@ƒèôööößÿýÿøÇ?þöÊ•+ÿ"îC"`€Ì=äÜ?@À³‰ø]{aªÁ¥vð·åÖæY>¸¤—Qe„{b‰€À¥Š@ÚG'Ú„À¤Oß?æÖÉ !°FÁ©Ý&õê™I’(õHüç½÷Þ»ï+_ùÊ·éXºšÜ?®‡0©„§`ƒð$¸ÙF™ ä„S¹l¡$¸€ƒÂ>D¼œŸ`×/ÄY„:—˜è'JÏõ99/–|ñ‰ìÊP®ˆèœ0ãÖÏÁ©@à!8”ÏçMøÙó„_ü⯽øâ‹ÝßûÞ÷þšvÃdo Ü Ba:G¹(©eþ €ðºÃèLLÔ HCÎBæãgˆn›¾FªìýÎS{VïYy«îÈ:g‰šY•p’Ú½ráâ:Í&$ÊÁ8L ÷.ÚÛ£&³F5ÔÁYð9ð D ‰9D3°ÍçHÛùÜsÏí#ûàÆ 6ÜND˜;•E âomŸ={öåîîî—GÌÔ&ú~<Ÿð²\cèr™¹=Á$¨ã –ϛʸ3{j ¦åNŸ>}žú‰û,=K@C¬€D1 Š3F Û¶mÛvê¯ë[ßÚDFâõd`­TuÒL2ªŸ\Þ7$á鹆ËÐ÷Ãù&•QNðœc&x"ã((¬-YwÀjYòÆ/¿üò éîQò¥Û A† Åû:zHöÁÅÎk¯½vÉ7Þxë¼yóÖÑçt­ŸlNõ];¥VÀóÒ}Ó³ Ós {Íùæv&~B|BÊ\G’!gïâ* æèÑ£ 6¢§aD§s÷G]˜d%gµmeê ˆ«É6=ÝßÖóà½h¢Ó5`È‚ósˆmеñDô⹄§ßl¢mBzzEUwÅ †Ÿ^–W„\€Ã})À!ËÀ gÌÐ}eÈÏ’g‚(mvïÞ½ãªÊ×Ñ^ŒwU匭€ŽâBsI­*`4ROCe@JÐ>8.®S–ÇDúzÕÆŠ?¸’ËHºŒ÷ñ !oüÝlßB_·Ðß&Bk¼B÷œÂ´,®ß,ÌÞ)ô(rá7À$Æ&À=4 `‹±HÑ=ãx†TCŠTY CL–©F"\¤—• Ù„Ñk ^0-I^á!ÕLJ¢¹•ÔÕ¢¨ C”& àp TG瘫™“ˆx£ô·0âF©CŒ‚莙ý ¢¦tÍDü:†k§Ì¢> ~ԃ𜽼,ÜÍ^¼6Ö+|ö "€€J,GD#±‚™#2¦š1ª¯Qc©g9ôõõC?Éue›ÉHm¥ÁƒÈMÒ`&`ÜaÀ€Ï xÒHŸD¹»fìwËÈcpjø Û ú À@*1ah5¥ï·Kçñ}2]sõ€ 6â"Ï0ïDÞïLƒ¬á;Ø"rQDƒÂV·aU¼ŒL%œ¼"M+"°>“ó.Ö½âþò¼%oAÖ§¸m‚¼ƒqÔ6ø¹›`½NîçaËÇ !Œ..i­Î<5ÇYÄ‚(`˜šp„£ïúR ©FÀ3)TŒ¼qì“t3F«î¼O«ÆM¼Ô€à•Ö—dMëÙä"æZZZtR …OØPÏ€´Ü1wôÐ)O-Ll,Š”DøØp„!ªå3êìðÁPcÕª(Åco kâðV´K844”%:C^OÆ"~žD5š žÍ01UÄn´Fk´Fk´Fk´Fk´Fk´Fk´Fk´Fk´K¸ý?¢½?s©Ë~ÉIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/add_device.png000066400000000000000000000167441217176075400246600ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ (VÆ—ÒdIDATxÚå›i”\Õuïçܡ枻խy@#Hj !$a „ ˜ÉØQâåø-†“8qìäáõbÙ'Á¿;ÁFcágÇ 0`“±J"0Ihž{”z;œ³ß‡ªnZB`IøCÖzw­]÷Ö¹÷ž:ûöÙgOÿŸêtúê=ÿpåÂEÍ ÀŠ(õÎk"Bmm-ÖZ¬µ'½) £~L+Š…Å Äu]@ Jk¤ü~"‘éwtŸVû®î=ßgøG”R zùÉytCËéðæžÎCçÌ8çí¨q…BLeEAP, Ð?Ðσ?ú‰D‚D"YjW Ð(U”R€(bchjjäŠU«aßÞ}ˆ“'O"“ɲåõ×i9z¥5®ëN¥I¥ÓÅ"ÉdÇup´F)µ†ùçŸO¡'Ž ÆZ@ÑÐÐÀ‚ .|äÑ WÿÁHxþ¸L:í·ÞÆ¢E‹øËÏ|† ©¬ªäÖÛoãàÁƒg$v_þÒ:ÖþñŸpá’ èéîa÷ž=Üûµ{ ŠÅ3áûþ×}¬Ys?ücîùÊ=¼ºéU2Ùìä?ظâòËÿöÎ;Û´Ö¤Ói¬µ jjjX÷¥/ñÄOœõúó>ÙlŽî®..X¶œOþåßàç*q|c-AÇ1Q™˜(ŠH:šŽ¶6¾ïèÓ#.ºè"êÓIŸZ­ÉÇîÖN‹!B™÷S&ŽPJG5Mã¸ý¾ïòËo—_~™OúÓä*²S7?0étzŽRZžá…†2{öl2™Ì3/"AÀ¶mÛøâºu|qݺîO˜0›>þG\uÓǨš8•ýmt—{‰aÖø&²ù7üäk_Áó}Ï~ñHø‰)ÅbAõöö¾£9•Âó<â8>Á&8]F” ïóÝï~—öövfΜÉÞ½{ùñÌ×ïýg¾~ï?S[_Ïêk¯ãúOÝFËPüÞL8»Ž¶1Ô߇Îä(æóTUWÍýƒ,T:=­­½ýDÅ¡5ŽãœÀÌY_ª´Î“É$¾ïsß}÷ÑÖÖÊžÝ{¹îº`­ðä“Oòƒü€?ð}²µ Ì]u5Ö˜÷ìÓZ‹—J“­©ãðáÃTärS?0ófÍMg2éäíNh÷<­õ),¿Óc^ë’îÍd2¬]»–¦±cùÒ]OMm\±j%©d’M¯nâ›ÿò Ú{Z`‹µÔ›Èömo1iò”逋/]>­¢¢‚ûOÀqÏXü‡8ŽÑZ“Édèì줶¦–Ûo¿•—_F>Ÿç¢ ±cÛv6>³±d&KüŽí 8®ƒ1ðîeQ×4–·ÞÚÆü…ÍUå]Ξ5cÇNÉd³ìß¿ÿ„ö¡¡!öíÛ÷¶Àºº:Þ|óMâ8&W‘ã¥_daób‚b®ž<Ïcì¸&vî|ßO HÙÖà×_³fÏy—-—«©eë³oS_ßÀ§o»ýœo}ﻻπ1c›ÎM§Ó9z䔳x¶ÇøñãÙ¼y3o¾ù&õõõ4551~š››9zô(«×¬á¢¥KA)\×¥e×^V\3‡[Ûèï ²ªŠb±HFTÕÔ +H#JSŒ 55Õd++&g@EEÅÇuimmáuLŸ>íÛ·sçw²fÍÆÇŽ;Hú¿ù&r¹Cƒƒd²9‚b»vñèƒòäÏÊÇnÿs–_w3mÅIJé‘ûYùÄ/7=rD´ÖR^€ˆfΜ)""×_ýH[uuµ|ç;ß‘B¡ _üâ²î‹ëäâ‹/–†††SösÉGn”O~á.ù«Ïü…twuËáC‡åÐÁƒ'PËÑ£òo}ûûh¶^xþùŽƒʆ ~`æ,X ÖZ¹úê«Oh¿ï¾ûDDdÿþýrÃõ׋뺧՟ï{ò÷wß--G[¤¥¥E>,‡Ëtèð!ioo—G~øåÀæM¯Êýûeïž=²í­·¤¢¢â¬˜_¼x±ˆˆ,_¾|¤í†nB¡ û÷í“Ûn»íŒûL§ÓrõUkdÕå+åGë×Koo¯=rDZ[[åàÁCrìØ1yâ±Çœ5óŸû«ÏNÚöÖ[rüøqä¯?ûY9v옜Þù§=Ȧ¦&ùØÇ>&ÃÇ¡C‡dݺuòꫯJgg§lÞ¼Y~ö³Ÿ‰çy2wî\yì±ÇdýúõòùÏ^V®\)555ïÙw2™”åK/’‹W¬­¸Xn¾ñ&yíµ-òØc Û·o—žA΀¯Ü}÷¥”£GŽJkk«ëì”®®.ù§üÇ÷T*•’µk×Êc=&½½½""²cÇyå•WdçΆ¡ Ê3Ï<#/½ô’,Y²D¦L™"/½ô’ˆˆXkåäãØ±c²aùá†NÐE¾çÉÜ9sdþ¼ódñÂfY¶t©\мH¾ø?ÿNŽ;&½½½ò»×_—ÿù?îV|û[ߺ½£½]Z[Z¤åh‹ôõöÊg>}‡Œolzã«V­’çž{ndÐÖZÉçó²iÓ&Ù¾}»´´´H†òÕ¯~uD±sÎ9òâ‹/Šˆˆ1æ}i40=ö˜,]ºT™2a¢L™8Q¦O;GÎ5[œw¾,nn– šÉÏ~úåСCr÷—îZ~Vñ€úÚº¹®ç¡´&›Íðçwü9¿zæÒéôÈ3ÿøÇimmåÙgŸå’K.!Žc¬µôõõ±eËr¹ lݺ•™3gò…/|úúz^|ñEöìÙÃòåËGÞy?2ÆÇ¥ÈК5kØ´i;vì ¾¡žB¡@ ¯¯—þ¾~ŠÅ"=ô cÆÉ¦gŸ•Éfg8ZK.—Sëþî‹ìÙ½ Ïu)‹L›6§Ÿ~šéÓ§†!aŽ˜Èìܹ“¦¦&†††X»v-7ndÑ¢Eüà?à’K.9᳊$…!S¦Lá£7ßL{[;O<ñ8…B!Žc‚ È®]»H&TUUÏ<+R©ÔT¥µzáùçÙúÆ8Ú!Žc&O™Â³Ï?Ç[»¶òÓg¥°8Ž]Ç»èíí%Hóë—~Í¿oÞÌÌé³øáO~ÈÍ×ÞŒV¥°8JÁ(çæl4•X‹ëº4Ë­·ÝÎ3O?ÅŽ·ßÆó5ö”óûû[ ™LòðC°cÇv®\}%sfÏž½ãí··þ^jkë¤R)DJaè'œ=»÷pãG?:’1V%h_8‚h‹U‹)Í<¥% 4hOÇ.¹„+W¯F+)gy”VhGS,‰ã˜Á¡¡à!”f(Ÿç¡‡`Û¶m¤R)ÖþÑÚ±·î‹§ ryeµ úôà¤ôœžŽwçoþú¯ÙòÚk\¹úJV‡«) #K@!dÝTI䱌°.†XbDJ¤Ò>uu úèêõË"4Š=y·’W€ÖN©ìÆOœ‚É÷dó'ŸøÄÈ÷ýû÷“H$¨«¯»øÕ»˜vÅ´sÎ;ç³m½‡÷æûÿñ½½Ðý<›·lfPúa‰â§Ç6ðö†í4ŽkÂj‹çAä4d±Ö™è²!‘‰XÛˆ¦ú±xŸûC ù"Q`!•Wä0™0žãRWSGó‚ÅTUUÓ7ß|?‘ ¶¶–îîîR1g]-cÆLlïèØ÷îmÐ &°ÈXO(ºÁˆfŒ¡äéIt“öÒ¤œ4I•±6–RùZâBŒô;8ž…¤EŽoÁsÀ‘)AÐ ¬Fc#m !¤siÆ46âyÞHQ…\ßgÒäÉ<õÔSDa„ãhŒL“N§ð˵K]]]#±ÇD"Á'>ñ‰Y÷~ík§ ¬Œ¤Ò ±c(H¡¤á£ˆ (øúÝ~´Ò88xâ“d ˆPˆ‹12ªßAÇ'!Ò¨TÙmöQïaÌ€%LG¥Š´²w˜I¥‰£S×'JB“ŸÒŪ•ãÙ~¨“Ž_eà¸H& ãG¶–îwzkhçïú~wî˜ä˜ó?qåŸ\ÖÖÞæ¿þúëˆ)e_\Ï-mEN)€¤vvp u³l Ê•'©Ëÿ(“Ÿ¤ßtÑÓ×ÔŽYdÝ \×ÅOø¤RI~»ï›šhpëÙûú~®½þ:þã׸dåeüè¹1gι ô“J¥Èòå”]cÍ)pµGWõ“|xÜ÷ÉTÜÏ¿>š%‡Æ÷<†††Â¾¾¾ž“ÝLˆ8LàUA«‰M_MuM}:QÊÒx®‹ë””—ë¸å:]ƒ -ù|±T½åƒJ–¢C¾ïãû>ÉD‚„—À*KÁÑÖÁÅÅ×>.>>Ú–¶=‰KËÂWXH8 ´hÒÉ4}ýTVVRÈ—ô–£]¢(IÂŒ.úòÅùÿ˜ÆÁÅÌ´cR’©}]ÝÝý'—ÍŽˆÖÚò…¡t&]¯”ƒի,VˈZ±ØX°”Ö ÊW#’âyžïã¹>ZéÒÖ$¶ÔŸuÊ] "Åb)î'ÂÀÀ@¹UQ Œ1Dqˆã8ä‹% ˆM„[R 'íÆ–4ÌÇ9¸QŠpÇÑ$|_ú£0 N%#„Qw÷t÷)­°å„¶eJ«‘w‡·@ÂwzÑn©¤ÍuGàºeûŒ±]Js—"1±µäóyL¹än8ÒßßX ƒƒy¢0¢˜Fb'D‹F¹ÊJ)ŒH†5¶´ó8Žêíë;>88¼oD( ‚`ëÖ­Û'N˜p~>Ÿ/›¥…Eéw¢ÖZLl‘2J—BcZë‘:â¹(¥Ké,)‘*[qa1{æ,|ß#•L±êò• ôsñŠ…".YBc}™TºlÐY.¿ô2 ùòV=úÿXj8°¢N¸Â8Ž8tð -mm» …Báý% ûŸzꩇ**+Q"ó¢8Î)”§´RZ—\U¥"¢’™ÄL?‡”¶ÕËTr}J 6qÔy¼³«/î3'‰­*Ï ˆ­mm€ðÊñMXŽmòòAÀX£: °"à J¡ /3‘²Qe qlL"™ܳwßöbXüÅÀÀÀàû0884ôƒCCm@=ÕZ{®ë:¾ï;™LF'Ü„ö=Ïísú×HÀGœSÅðFÄI»Ç.ºlÙú‰¹‰ýžç)­µÒZ+¥Ôȹlb—ØP>[cŒÄql‡ó A¨8Ž% C†¡)“ƒÀ„A`ƒ 0AØb±(Å|>?°ÿÀþö(Šc~_PÔÝ@ßðÊš7ož^±b…nnnvÇŒãUWW»­­­©;¾zÇŒ8Že¸RH¬œ¢¼Å ±à;~xÝM×µ­š¿ªG)å(¥œ’m‰þ/L9+£ÆaK)1"b€XJUÓ±µ6‘XD" 1‘µ62ÆDQEqGA„áÑ£GƒÖÖÖ0™L†·Ür‹9Ýú€‘ßxã 5*ƒ¤µuëV«Ñ[vbâ²#sR=1 ÄŠ¤Ÿ®/R£íS§ÈXÉ{ÜWïQ©6 œ¾^¼xq\þ.·ÜrË™ÿabÔ@d˜¾¾¾ #£Z†[m,#ŒSGH,ÄÅ(îèé,K—.Ͼ:ɨ߳£ÎfÅ£®£QmѨ{Ã×ñ¨>5JÊN¥””}ïxx0‡R6Š£Êd%Žhtä BâÈŒJR¤HƉèpÛþv ý=ç0 „ѳËɳç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÚ &1 $§÷IDATxÚí›{l\Å~Ç?3sÎÙ³ëWlœ§A$Mr¸ Þr;nˆ UQ   ¨ )ÜP)© ôŸHˆç%EH¨UijáUHqȃ\¸·!¼ìàØŽcïî9gfúÇñnìݵ³ëØR{¬Ñž³3;s~ßßo~Ï1üÿõûå ºýöÛÿîÞ{ïýÛ¾¾¾¾3N(Ĩúr—µöŒÏ¹6ø97·µVxžç®^½úöìÙóñ™ÖsÊ`öìÙs,Xð«Ÿ÷ƒaŒÁZ‹ÖšD"Áĉ§•3GYh­‚ $7 9;Ú¾BŽÇíÁÞ礡Pr†»d¥ˆŸéþlúr ä€ÉÝ—z–R–¼<~Ì$ €Aû­ä}9„ŽZi "P)U$•¹6.P(šg"ôÁ¤¥¥…«¯¾:Ï©ÁmþüùìÚµ ¥Žã5¥J©üøáK–,¡¥¥…µkב‚Ü)%Ƙñ àR AÀÎ;Ùµk“&MâÍ7ß,É×uGÜ…Ÿï¼óétš]»v±yóæ"ѯt ŒZœI?DQ”>vìØ°s æT¹ öê)åøP‰RK&“ÜtÓM´´´P[[ËÍ7ß&”z±3Y‡‘Æ566YŽrA<¦!åzc²V®\ÉÂ… Gå'477ÓÒÒR²oáÂ…Ì;·ävX·nóæÍ+ò[Šsf;::Få,577óôÓO³téRî»ï¾!}×^{-·Þz+Ÿ~úiIÚÛÛKú•p~ÌÌà† ÊVŒ…ãæÏŸÏwÜÁ¾}û†ôõöö²xñâa÷â‹/9>…&pÜ]áÜuà 7ðÞ{ïUÂäÉ“¹þúë¹í¶ÛX¾|ù¾5kÖp÷Ýwså•W²lÙ²¢9®¹æ^}õÕ’^à˜+ÁB/òòË/sðàAæÎ[ÒNË¿÷Þ{¬X±‚åË—sÿý÷ùÍÒ¥K¹ë®»øê«¯xâ‰'Šæ[»v-dÁ‚C”ã¸[R€Ì™3‡9sæŒ ÂÛo¿=츕+WÛ×ÜÜLsssYÖiÜ·À¦M›X´hѨ"ÀÍ›7Óßß_²ïóÏ?çƒ>(K—œS%X¸ø /¼À“O>Y„‘ôÀáÇY»v-Ÿ}öYÉq÷ÜsO^Ù• Âh¤à¬ÍàìÙ³¹âŠ+*ަM›–iK[½z5ÕÕÕçÎé°Ö²wï^Z[[G•ضm[Éï·nÝJ[[[YsŒ;Ã%:r¢úØc±uëÖŠ@8tèo½õVÉq;wî`ïÞ½#‚p¶`ŒÊ chû¡}‡öqÊ;É]«ïä•÷_;–,ø^‚d"EÓ”&.ýÅ¥T¥ªòs455å‰,e)víÚuÆXdp,0Z+0*¢(âßÅÖ?¶òýá6ŽèàThâ £©±‰_Ïi¦««‹éÓ¦“J¦Ê6‘àÈ‘#yåZ8î›o¾áâ‹/.’ˆqq„J½pGO;?eÚY|åRÂ($ÈfbMŒ@"q¤ËÄÆ)úöG¶}ÖʲňÌK–,áñÇ窫®Ò×ÑÑ‘Ï<üðÃÜxãCÖž7oBvïÞ}VÜ/[”ÚÏ“¡í§}¸õ ’I’|ªjST×UQ=¡Šê†*ª'Õp¸û0ŽÀ2tÏóŠ4½µ–[n¹… 6ðÉ'Ÿ°~ýú¢µ Ókg£œJ•`>%-´ŒÐQˆ R+$„ Òýašt”-)æƒç.ì;~üø°[eæÌ™ÃÎWé6¨H† í‚ð-2! &eˆü­"´Õh«1Vƒ²´}ß–/Âåæ8~ü8ÖZxà¢u>úè#Ö¬YÃüùóyíµ×ŠÖιÁk×®=k38* ˆ¿‘(W! 0VcEhƒÕ Æ*˜=gv 'NdÛ¶mùªS!·s¢ÔÚ9 q¶`ÔÑ €p@ø \‰tT$1V£M„%"h°UÚŽç²8•Pcme%`ˆ+,- H€òÊ•Gb=ƒö""¡1BçW‹Úp ¯°Ž8æ AXIJ#=p<ÇUÈp@»‘ c= ,([¤Æ „³õ+’€!‹©œHW!‰18Fi´Òh4VXc_L+F "RI„ V‚•# ‘Ñ" Ëþï÷šÐJ@×-PôB„'@Êb¥ÁAüÅæP*ÁŒ?¹pÄ—>ÆÄ Ö]^Wo²=²7÷mí 5Ðöø½œÂÆYdcbñ7Ú"²Y’5Â)Íýçž{Ž7Þxƒ×_=ŸõðŸÆºó¨›QEpi_|ºk<¡â†;ü ;µàà’2 ô÷ôq"ÝAàd9E5T3INbj]““àJOæ¼’NL¾çÁXŒ±yN¥z™2qþ@Þp0{öìá7Þ`ûöí,Z´ˆ;vIHe(_\4ãM»»övi¬21Áj€pG(å()$WªN2¡nÓgÌ"¼Àãr'" ²¨²n–“ôÐ#:pº$½}tg»0†±DYB‚ØÀbCðŒb²7™YMJ]M]Ñþ>räHåÙ«‘ »öûî'&t?A: â!Os}úäéÍ—7ÿæ¢0 @ |Ç£»«““æþÔ†8?˜Q nÊ!™Lâ'}¤'8~¼£míÌ”s¨ª®ÁÄ,üþ÷›i¨o enK\L1 xYó'œÏù ‰ÿ%—\Ï–S1€¾¯û¾û¢ç‹"*Zà¯ÿrÅ¿üöß^ÔÛÛ›¯ ½Þú ÿþí¿ñ 3áH‚ò%‰Dâtó|zt'nÂãá%ÿÈÔúiùà§ãx_þë×ð#<þÄ?—|ñ„—(Ò3fÌà©§žâ¡‡bûöícbC~ k¤Au©ºLC]®Œµ†aˆ°é¾ àÇÙ!Ïóð<?‘ á&°Ò }EMª–úšú<‘ u loÝ~Æ)­?oÞ¼|QõLÖ`ܪÃVƒÉZ„H‘{Çup]7nž‡ëxH!‡û·oßÎJÆû;vìàÍ7ß6ðî»ïŽ˜[·Ú`~ §g‘ŽÈŸò΃àÄæ.'öƒ9õþûïç«>7ndâĉC £«W¯FÁÁƒyôÑG‡üöòË/àºë®;wçЏ`b­ ±¢”êôYÝÜ1w¥„8 ÀàyÖ¯_Ï–-[xþùç¹ãŽ;†ô¯[·ŽgŸ}–ÖÖÖ’Çd>þøã³æ|Å犉€Ì€–@ÁY½8ô=íè æþýû‹Š#©TjÈáˆBðsg Æ"'8êê°Õ`³ ânAoàÙ‹ÕEݼôÒK,Y²€-[¶ ™{ãÆ\qÅ<óÌ3ùƒƒûs'ÈÖ¯_Ï#ˆQ)Á|f× (8 &²yÂs-ŒÂ!p¦Ó…¾@%ýãzDÆq|ß !PJá{>5~ e%2Tˆ@bB‹Ž4Q¨ó‰’$I¤Hð<|ß‘ð‘.÷¹Òÿ(kÔe—]6ÿ /üµÖ:ðÕ¡®ƒ1ýâ™ËÍÅBýp¼žôOÈj›rñ|—D*Áä†IÔ¤ëí¾/÷ò¿›ð»zY¢RI…‰RJ»{÷îÿìììÜ?&”¸ÜÅËÿýÔÉSýâ¿ö8§:è3}ÿt=Aú’ú u´ür>Aýá»/¿þ›ÿy÷Èü̮ѠjU{Y2™lîîé¡ÉƦ^ä:UKu²ú§Cÿ}h{éý¹ð¿Éê|ˆ·IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/agt_runit.png000077500000000000000000001344301217176075400246010ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì}y¼%EyöSK÷9çîwfefØv¢ a#E@ŒF%Á|1.—¸$Ñ I4&. F ùDó1€J" FAM$ ¸Dd¶Ù`f˜õÞ¹Û9ÝUõýQ]ÝÕuªû,÷Þ™ïs}{ï®îÓïþÖ[D)…9Ìa¿š ºs˜ÃÈnÀºÂÁø»Í©’ÏAÌis˜Ã¯0ønÀº’æíœ3“ZÂlI÷9­ácŽ<·PDÔ¾í³m&¸ÄK ¶Ïá Æ88Ñ ¡û¶“’}À3Áô {Ž1„8IÏ't£ª—IóVó²sºræeûŠæ¾sŠÖËÚ0‡YÀœ°ÿÑŠà}Ò»ÐsheDÝ.è„€çˆ}?cN˜LG5/›í£%ëVqññ„’AT6/ ")AhJ–Fö6ªäÀöÑÆ¦oÛ¹ yb6ËÒÚæ[÷Ó“hWK˜c3€903د à_ZrbÀØPÀÏ€&ð3– ¡Fùñ÷ P(V/I.!¥€À)…JA@hzìD<…í{Q¡."lß‹€°M“qcó¶}û”â®jïT$PRí}ø÷·=€9ðœÄèӱщ3™ôvçdŵ W.è«¬é ø ‹úûOï ª+– Í?X‚¾ ‚á"0ª/G A$¥R‚QJ(¤RÉ:…¡jnO ”ž[JBH %c€‚B-£Ï@*‰õ{·Ø9¶ïÁ­c£›'êу“Q|÷ÃëÇÖáoÆFà×ܹr&t0·1Ç:Äè³ÆN¼qù½?ó˜…‹ÎXP8~0ì\Ô?‡õ­HW!J’üå)(a`”RQN‚ÂfkI¯¯ihJL@@ V1¤ˆd ‘ìS2F"w-¥4-OŠqìÜ·Û&vc÷ÔØ¦mãûÜ´wï]ãø‡_¶m]rø8H0ÇZ£‚gÖº;‚g«¿¸xͲþs=dÉé‹{†Ï\Ò¿‡õ¯‚T2!n;ú¦—{X/€“ @@PA%×@NXº¬%‘OþŒUžm1„˜T“ R¡®¦ •”l¦Ä¤~¨äúBÉÄÑû¶íÛƒM£ÛG¶OŒÞõгÛïŠîÙôv¬³nh†à2å3Çfs  5Šìø2[ÝPŸ­ÖüÝàЋV œ÷¢GœqHÏð¹K®ê949@ŸJ‡R1áà”¡Bªà„ƒ£‚0•òÀ&`ߘÂU,FõñBF  –ôvsÁHŽTR H(ÔQ@R‚ŽT Ó ¦Ä$$„j .˜Sé=$LÏS!6nŦ}ÏnÞ2ºëîGvìøÏ‡.ÝöŸÐ+­¹Ý$hÅæ@ Ì1€f´ë¸óJõ¦ù‡ûç7V{ìÂe¯XÜ;ÿ•k†WPJj)M(ª¬ †*é# œ„2¦Vs ÒeZòSºD. À’ãÝe!EBèJÛþP*B¬âä‰y`‚ÍbÕÀ”˜D]D¨ËI4”ñ%HH©—“ذ癑“£ß¾wóS·ÿäu›¿…ŒÂwç>mÈýCh9ÐŒv%¾˜¼ vÑ'þî)‹xåŠÁCÎ]R[fIx–^ªBC$DéMUyN*ÖEIJäEN‘©úÔ íÙ6½”Œ²”0•”ðA%´•1‘2X5@7Ì’6ì«dÇH%¡ @@  0%&PWu4D“rJk2a8ª‡voÙ=9òíŸlÜð­{_¿å›M·K.bsaN#hs  ubŽc·‰Þ,38ç–£NZ{Øq´zÁ¯\.4'™¯ÎHù^2ˆ ‘üœTr71DŸI|Mà”ÒQ“’ŸŽ92_ #xWm)%à8õ´ç_hÛßb€vøIë:®!F½°mJËþ”1L‰ ŒÅãØíÕÚê2‚ÑmžØ»uÓΉ‘/_}ç}7უ[uC #ú"mÀåts ÁÁ¯:hÇÁ—·ãósŠ }ê—Ÿ?¯oè-Gô¾Æ¾§<'åRuBÍRž‚å^7¦¹çv»}¹…C6°µ[ºkY¦w¤J€ Qâ<Ôçk¸ÌÀÜÛ<›q.*HŒÆ{1!êiì‚L¢ „ˆ170:5~û·¬¿ñ›ç=ômhMÀ¿í7ðùæ…˜cÍËe½”¼â¶cW¾ýäW½! áÛúyÿ É¶Ó'0$D?éG…ö¦'빟༔· ž9ž{³O&ö4!4 ÃÙ` M @ÊŒx•GòÚa¨R·Ÿ‚L|Æ'àCþ~4wØ:N¤š€‚D¬"ÄR@@b_¼“b{ë{Ó–:‹q"šÚ¼}l×?{ý/ozðÒ­{‘i.h9p—åð«Æ:±ï}Ž=ò—÷žâi‹OxÛ|¡$U·9 ’Uô B{sÐÔOA¼¯o®Ïb„z%¾ ™¾OÍWRæ¼!Z•‡…lÒ‘Øú$qþù¥¼a,EÈÚ’?F§EÖºB¬b‹Ä:÷ aP ±l`$Þ‡‘hSQ#½N‚Ñã{¯½sÃÃ7ÞùêÇ7"c­†ðÌQ°þ¼Æ¯2( 㹄ÏàŸ×_væ1ƒ‡ÿYHªgpªyœpRÁƒ!vÛi§ µã¤óIy}­r˜ßÄØTŽÈ²á%láxêõõTî…¸96!Ǩƒ%–¹MÄí‚%þQ[hf™`öëP¤É'¨cOcFãMן¨OÝô½'îÿø®ß„f‡¡Ë€ö#Ïk<ß@+‰ïÚ÷¶ÏàS\üâ“÷¾ï9&™u!áЃ>Ú‹€†)Áb²ø{vó¼Dl—èS"Iˆ]{é#hÒ°œq*‚ýý;Z¶ñM o=³ìvíÂtŽ>GböŒ™moƒZÏn:Sÿ5-6T‘tD”œOÒç°p"£S÷<¾÷éO^¿ö§wixÂ5:ñ<¯ÂÈæ9ðO\zöêá£þ¬Âjg0d)µ! QE|¤Pºëå<Á[¾L½7j}$#(ˆTm72ß@8É8vˆN$]{,U9‘¼ùoÙ%äHE`I’‘aeÄ^×ÙWvL¬šI•2"©bý¼V?“HDR BÆØíÆ®Ií'ÂÐ9KyÏúÝ[>öù³tæ@!ž  Ì±çv¸1Ayj¦O=pñÙ§,<î}KâP„$DéA/€NÜÉ{êM,Ñì´Ëãß.U¬¥¹ˆd=‘ëy¢J;åÜ'x[=7 :ÔòÚûBˆ*¥‰™q¶Òpôq*Uû(bH¥éÕ0!$_„ºl`OcöLíCCä“;Ç÷Üü'úø½¯Û² Ú$ÈGlóÀžÿJ˜s aWÜ}öªWù’k´ÄÏTý ÑKúÐÃúSÂ7ª=M¿Ûq§ ‰]A¦6¼”1bË㮿/ãq÷¼0×ðØá ÕÈ­ÇÖy*1²ÎAHÕksOcÆ´c2¸°}ƉG¨ñudû¤QÙMÔ$‘ú€fr齂oÕ!cÄ–¦ól}F&F­ŽKz߮ɑk¿zß/>öäíØ‹9âùÄ|„ïÎàÖv€¿è++†®<óÒ÷‡CoƒT¨°*(( †úø(8 šœw­¼õ¶ÓŽZºÉ(ý8ë²䤼‘|é6+õÖÀØ×®—ޖ䆸•“ØÓـݢ(äh÷_%ª~Žé¨|{Ó{ȼtg”712ÂÎhvíM·ÕE @lßýÉ«ó×B¾D>ŸÈ‡n2Ñó’<@QÊ.`¥ê 7<õÖK—õ,ÿ›€„ƒÊ¢3ðúHjãSKâ“Ä•%¡Õ[c¯SKÕ5žB…€@,ã”pcÈœ ïK±µhL¼\B"Ë”°¾Lš«AXÙñ Ì|~[ê ƒ¡bPÂ2ß=¯áÇà M_„º¬cÛÄvì™Ë]1Vbóºí®øÚ˸ :³ÐÖlÐnèð9‹ç2(sðÙ€Ú à²ÿzáao<î•W×hí N @AÑGú1ȇA´ô"Û^)™dÆå‰^ Fœt•µ%\¬^µÞîvËÀÒ¾øÖÐP ÐÄNN A–‹¶Äm%¡sç%Dk¯Û0ûÜíR"×ó8ÙÆ«(çÍ’ž‚û^!OøÀ“Ÿ±]hm`RÔ±yl¦¢: 29Þ˜¼é“ßùÉ_àÊ}{‘¾á¤nRQQØÐ·þœÁó‰ørös!=áÍ›ßõ§‹*‹Þô°žDÝ1@‡P£µá»É.†¸Yw.ÑûœwFʇ‘ð&7ÞvÒék,!z@3@u@ðÓPXâ/ðåd0½ìyêK½ø-¡5ïÓRlÐ ñÔe(¶OíÀö}»s׈”}dÇ–wüÇo¯»-ÙT:tÍ»ùÏI<€«êÅò þ¡{Ï[³vÙ ¯á$\Ã)CH*©ÔâóZ¾Mô©ÓJ HH#BœsÞ +$Ç’×Í‚‹’cõqšàÔFZ@ð¦ Hõvaž‘ ñÛçXf‡¶ky®,N+2Õß,w)óíŸulÛ†}‰ìúJ 5¾õÉïy7þqbGzÛÌ4( !0ÊQ— ï¾nÑ ñDxzl+žÝ‘Û>×ùç{×ýoxæȈßîlT–Mè.´x^2€¯l|çß-ª.| 'œrÂIˆÒ‡!:ˆ†^â7° ?FŒH6©:L|>‚Ê}¾C‹+åÏa‹$<7v¼÷~q»ÛLéHú+tãÌ+B§„A"Edµa$ÁúÓu¡$b)F·ŒíþÀÍ/½ÿFÌ1€ý _ˆÏéÛ½õ€`á5 çýËoº¾/è?=$(e$$U  òa¤Õ÷œðž«æ“r ‘j$]TóÉ8Í’>sÞ¥]<¿¿” ”H™õ´Ÿ + ÈÖ6|™~vŸÙîç;ð«ý­¤¿Ëïij߄/B„f­=1Þý$F¦ÆÀ)C,"%±¯1yó×þô d©Ä†»»½ Ÿs9ÏpùÝgŸrá/¾…>Ä 'œrôÒ~ô’> °ä"yâ70j¾éN©zág•k²ßÕvà5e³%§ÞL¿+¥»IãíeÄ_„Nylt«Þ‰–yïÙü ‘ˆ±ul;žÙ¦ïkŽQêÁ«oúé«põÔÌ1€YC+¿Ó7ºlåSë.~Ýñ VÿU…ƒ I…UÁÁ0@Q%½)·*èZjÂÏ—ÂFªÓõ겜z Oli‹8ýL»Ž¹¦{+•†è:ݯ”Bo°>„8Ž1O&L@A)÷GaS˜ŒvÏx,ße~‚nvÞBr=#`YâÓ¶‰g±aÏVL ë¾Jþ×cë_ûðeÛŒ_À81Üä¡ç #x®3ú¥§ÞòçËjKßÅi0°ÄÙWÅ`R #LB|Fú›Þp¶s¯žØø±i¼Þ~ •#zÀ±_­Î,³n ÈKìvãôBÆ`”£Ñ øÆ=?Âwïý_lÛµ3¹ Òyz•dáøUGã£o~+8¯cRŒµl[;˜9'þHk-rëwlÄX\·™F6ìÙùß<ï¡1Çf E„Ÿëª‹¼³¯ç† ü‰%ÕC^K 8á´Êz0@úÑKût2/ R»0^¡;æÈ DˆU#ÉÐÓ}»H¥é®šZûÒH~¤i¿û >â/"|W’»„NZt¯4ñG1ŧnþ ~úð#éö•óWáü“.ęǜ• Vá„CO*½ÎÆÉŸáñ±;1ï-=ÐDNiàÝn`¾ëÈkü3—À8"C ÆÛÃX4•Ûÿø®íï¼ý‚GoH.jñ(=[ßF{ ÀøÌ~Û/°nÇzìšÉÒ´ì˜øÊ—_ú‹·'70ÙƒnÑ”Ì(š]âûE À&z ­ö‡‡vÙ¡ÿðÚßýl•õœX£AÒJPe=dˆ " <©Þ£;íBµ›VF‰Š/+ºA!B"#-H ¡Ó|“ßl£Ì¦7ÝiMK¤ò'•^_ÆiF£Ý—Á,_ÑÄO(n½ë>üÇï ö áŽ÷~/]óòŽîë‚‘ëG¿¥d:E` éºÝ6{}zQ ÿ¹eÒŸQêöi.ê]€±h c‘UÄÆ×ý†…+üÒ¶;9à,ç=ŽÚ[b¶aK|3±d Tûÿæå{Ák?Seµã{hPå4 9 P!U}* ,¢‘ˆeCçêC RuÔå$ê*BuD˜B#1t¬¿X&Äß¡Ä*J'³^tœ{Ž ;”h/—I|!ãÂÉ †lò¼û<ñ !¾ô½o¦ŸêÏÿpK¿LÉ}Éh~Iù™“þÖ5[¨þ~dŠòñ ÆK!â¬mýaõ’×ÜqÂg¡¿UŽìÛµ}WEÓÅÁ \âghÿG9ôš×¿úªV9.ï¡„ñZA/íG•t´\3¬¥H>øH5u?Fuĉw¿¡Ph¨:b#Nߤ*n"P›Ð]¢·±Õ÷Ò,»H5ôè:B/sèùà9ÐLèöº­æ1ƒm»÷¦­8áГpùKÞå½w§» O ÚžÛ±z³}z°p9Æ›ˆ?[wß?ÁáÃ+pÒ’#s[û*Õ‹&À1ñT8  Œ+š)\ø·‹–_ó†ßùd_СAoÀXZC8aVz«Jw)á+¡¥¾ŠPWuHĪ¡—=„oªÕHA33ðÁ&ä"Iî;Ç…R*7¹hEø&Îî#òVñ÷ïüüGé÷~ùKÞYzl'ØÝØŒX%yž6‚/&|7ÃÖ}/Ù¶ÈŽÛwàø³1NÀl²;oék.î9Ç/:ŒS !a¤¯R½ä¢ïžøä¥‘`p@™Â`>B÷©ý|`xùß½ö¼««´º†V9(ã$@…U‘½cœ“IÜ"9•:ùŒºo~,õè31„Eø¦'_«-2o—Ø Á·‰ÝGø@³*?ûÍ;v¦ËÝxû‹°§±Á;tYk¸Ntå¥Ê¼YÎæqn*‚{ŒïØX4 e}KpÄÀR@C „„‘Þ ò»ç븫„ÈLŽrFpÀ´ƒƒÍ0 ªŸ¿ìÂÏTÃê   UNå”Ãd"V±Ò¥¤c#Vz@K­ò×õ`á È”èí_™:î“ðí&ฒܷ͵Ýmbw{Íi>“j`˳Y¸•óWÍØuÇâ=]œÕ¾ônG²wk|›ccĘSÎVàðá•8zÞr„„!R±¬Ô.þÛÿL·9`ØŸ  Lò.¨èûäý}¼„kX€2N9(a$L†ÓªïšµDׄ¯‰¾¡t¢q*ñJŸÆù Ð-¡©ð­Ôú""oEôE¹ò¾íEÛ 1¥fØ_-T»Ý~³Ü[—If 9nï®Ï88¤ÈpøðJ¬\„j˜ß˜ÔxxÉ‹o9âíÐßshM®ƒð€ú F €}ì¾ßùè¼Þs#¨œB( ­n«J×äA íÙ¯#BŒz*íe2oÈ(!üRé0m7*{‘3®ˆ¨ÛA™=ß®„—2*$h³Ý,Û±u{_]jû|Á@WÏÑ ™¥È¼Ê›Z­Èy+b÷QT«_Ì–üæÏ8›9€¦Ó ŽÆâžyè B“…I–öýÕÿqØ%88é @V&{6á:<ì)7'€ÊwŸýºE}ÃçFk0„`à”AB"Ãh¿LÑY|Â`ÒôË7•g»!ÕnjÜ™Ì:£¾»Um|˜n½»vzÌb7ÇÛN·ƒ³­Îü+f¹9<>’{:×0-ŠƒGŒ@À´6j’—Ž_x4àéјÐ#“åCŸ^tÍüG·¿}×½È2ìÁ%ò/ÂÍ%˜UìoÀ·-5λíg5ÅG$T2ÌÛ"ºœtRU·.cÔÕbUG¬êh¨)ÔÅ$êb ±Œ’¤­þK%!•„R׿·&)eÎæ6e¹Üxºáø>§œoŠ!Q— ÔeÔë™÷­· ŸÔw½ç>ºY÷u‘ qÌÊéúÈDëÜývÑÇçìéþûn—È[IwŒ8Ý#»‡ta‰cBÔséËZÅñ ÆüZ?ÎÌåÙÙGúe|¤ŠsZ5yÖ0›  o¿±ý+'~iÉ1¯8æÔÏpJ©¤NÁ"<‰Ç6dœ8ü4+)’¾žŒêßP =D¶’ˆ„>&Jªöºêud u&D!#p#Á lU½µ½Â÷¿Kä¶ÊnàÆÕÝíöºKì¾pÛÉGj üàÑ;›öw‹S†.Bö ýLÛííÀˆ[›mÂ7 žD&8§Qš œ´h5Ö €‚>ÿÔ×áh,Pö¸ÑÃö+f3¸,¿ßf¯þÙ%/ÿWÆØRE(å„¢ÆzÀ)…JjËë™®£¯€:`êëÇRB*F2®|«¤Þ¢¸½P"W 'öD ¦,lŒÒ¥AºA‚*¥íw(0¦ûûÚÓIûZÁ/ŸÚ€jXÃù'_8#ÏTeýØmÂx¼³ð˜Ù þ"éï~1bèWümJx…ÑŽA ETn ԅ詆¨GuŒEu=h ! W¼xpÑ_Þu{r˜@³ê¿ßÓ…÷ði:NÊ>ôÅs?1Xë;@H@#=AJt§ MüŠĉJ/•‚P2b%YDRÆÞ®]Ì‘{ïe¾A#7¯ˆØg«WŠÕËŽÅ—¾ ^¶æåX4¸xF®»°rž» E߸ì*O >õžA÷‰TŠ4ùf ¢+ÉG.lÿ¥T©\ºs/ïMMÒñF€œ±c‡_Ý3¾ù«{ï‡fÅDï ÐYÁþ`vñN7Í7xóÿüÆ^òN¥£„P‚J¢Jk ”€+ꯠ$¡MRXP2Öû•ÈIM(¥m8¥¦Å¦ Cä¾É…­¢Ï±·NUX¶h>îì)\}Ç5¨U¼ðˆ_Ÿö ¡xzò!ŒG{Ò7Œ&¾GúÏÄo_#Nô7@<®E-$|…æoÆuJ%)…É~}—áÚ0FûPá {ëé Â3^S¿ß«oMšé'´ Ö%Ïl2×áÑÔÑçô›WtæÊãþ)ä¼F ¡BJTXˆ @ %,óÀ[ˆTÊ’^tPI=Q¥’ñüf·#¤ØÛÅÌäÁy2p·5ç¸á‘'wà‘ÍOà»ÜVœ„c–Ûuk~6r3Öíù&&ãPšÅø¥’`”æ¤ÿt¾zŸ-/!SžëáÛTä•ê.Ф¿ˆfß»!Y¨++S¡†kØWß@a¬1E!äˆ}g¬ßºókØ€)䣾TÔYÅlˆÃvÁ¹Gžô2Ј" ­1ÆAH˜¼ ™þדJ“Š&iïƒq€Åϧ‹v®ëæ¾·Î…w¡Ðü½ø¾ûø¢õŒ!Ø)´ý=µôÈu›îo£MÅØWcѳhÈñœ´'ɽ|Î"Šòg]Wº‰ÛË$CÔ V*7yóÝõVð…ÍýòaÖ 1Àû±thô b^µh%à‡¾ø‡ÿ%€3ù^„>ú¬˜3àÆüͼ)óï}?>ç=½aõ(„BzyˆÀ)J)•M6ÉÒ m( IDATz¦”Tšþ`n4ƒV%ªŒ£®]Ìœt·®)¢‚®¬~fïï®ÐˆžzfFÆÆ±kd [žÝ­{(=ýÌcÏ±j`$Úš®ý‚ÂrÀ"V,Þ8è8x£·çöy@FØù‘ŠEn?%¬T(ÚWä,l¨: €˜V4'¥×©,ÄXm0G˜ˆê¬7¨¼æÈëÿñ˶݊ŒsûxP–81MÌ$(bäéÉrøë_]µviÿüwŠ„*Œ2pÆ`"B*0*!%ö³O”…Ï\FЊ¸ËöÏlvÓÛ-nªZ“»§³Í—›öv‹þõÛÿïÿl]ºoåüU8ÿä qƹ¿8aʼn8kƒ&ÄxRŸ). j[Ý6Ò;$•&ân¨:"%SÝÕK K—mH¥kû€ž[ö|]F¨Ð Ç \Fá2—Ù÷1íCð`œ „ Ê*8|`êÑz,'F¶ƒH»`ÞÇ_µí'Ø€ÈÊŠ™î¨¶:g3‚eû#0 ÙÐkVÿÚß €3€(pBRžºEl › pA+´Ï(|£ÅØCÑyöúôPþl6ñÜêºê‚@vá¾±XÄX¿q+®þ÷Û°o\W·9똵øàÝÕü+Ãc‰çß&7Ë®(áf\N" ”°t9²«YL£.£”¸#ŸS5Ùfï3Äo_«ÌD°™i³ÏO#ƸœÄ ÒPr•Upøð ÔÅXÒ;Œ-£» sÕQó½W?ö¶äÔç\@‘½o$¾ õ™Ž>µËÿåÌËÔÎQWB äFѹšÝíüOL¢·—Ô·÷7³5Êúí&À@ÒX|»E=ÚC>ÞxÊM&£½®Tf ‰dÙ5}ée€Àgo¾ 7ÿ÷]hD1{†ðÙKÿŸxݧ±rÁªi´ßŸïýDb ±ŠRoºLJ´Ùëú $ZŽÊB¹ŒÔ±+¡$ ‘cX/#$w^;pÙ¹}ÿ€ò¦ _‰ÚÄ4ÌhÑœ`T×¥æ$'ŠéÊS’HLF ZalåøÙê©‘Û&6 ϧMˆXóÇþÔÈ)7.?nÕÐâ?Ž¡S¾‹1†rë UÂU–j€6 FIª¸ „$~Ÿ¼°i-_d6LÆv·‹Pdûò’;¶œe@óá‹ÙÞpŽ{} ŸÿƘ¬kmóü“.ĵoºƒ=C3öL6&Å(v×7aJÖsª·‘´©zžHvsŒ-é]i^´ÌPx×\Ï%jŸ?ÀSÔ†±h U–õ^e„áÊ!ØŒbQÏ0F§¦0ZŸ Ž[ºðý›–í¸Oc›s‹YN—«Øç§Ì8™§#÷$ûjú“—ýÛ‚ž¡Ó ÕiS •°Š*×õûÍ+׎@’¾tb)*,Ñ|`Ôfz]HURë­è‘ZåfØÈKëlËS”ùV–½V¤vÚö1Ø]¦cÄ1ð7Ý‚G7>(]ìóÚË®›±L?wã›Û>žöüã ˜…Äi³«ÞÏ6ZµÉÝ_ÄÊ% UVÃp0”=¯ °«± ›F6cÇÔÙñ4 U¼m|ìú{.ÚðQSÐã Ø#ù† ³ç]c¦4_ÇN⯺ý„‹û+}¿(jv…Aà}q‘RˆíÉ5dF5ô0á ËeÖ‹ÑݦQöN۵ϣ¦m±ˆ3Bv¤9€&g—½Íõh¤Ž'4‡²ªJþ÷—OâÿÝö]Dq (mëîM×ÍhÁŸÅ„5ø‡!oKyÀOìQNâ¶#—|Zñô4å2d3]Wò—A*]½ˆqý»r0,`¢gŒqìždzûö²ÅýýoÄGú¿+÷ýÅ¡?W:M[Cè–:A³àt²ðÔE‡¿P!ª¤B…sèÞ‰ÔvžQ2î\@ˆõÑg?‚p´ øç7WvÕj³ÍÀv°ÙRÚÇ8ZÁÜǾ§èÝ0VY4[âÀ#y ¡5TP ÿÒ×ñئ§Ó—ð‰K®ÂåçÌL¡O“bԻݻM,z¹ÕwëûÎ]g¸{<ñÌËá2'Ófб”00DRbŒŒ£Š(%¨€cImöEOâÈ%˜œœ"¢œ³fñŸ}û~/i¼Ž˜ÉoЭÐò3“‰åɼvÙõ/|Ûp­ï BHÈ)¡!P¥!k~Ù¶t7 @,¹S–š™EJL.w¶¤ÿLÆŽ)³Ô±è‡q¸™e•ô70ÛÆ›²×|¾€.OMµSQck R×Uäàr Àã›vàƒ×| »F4Q®œ¿ w¼÷û3ªò»¨±„¬Š=ÑÓˆ­ @~§ÜL|¿¾_±è—mÞnœ†@sY ³‚jÉ0¡ É÷Ç)Q@¯‚‚“UV!zôéþ°‚í#¤ÂùâÆ9ä±Ý_{ ÙÀ"@3˜1̰5€¬‡Ÿ±ý?4pä'¿à¯9¡½ `@•¨°”Úü²ÍS63€䈤,·ßff]%ŒÁ0C>Ìêûç>œ›¡! <ïeHÓR=NDӛх!úb"Êß= !¾ðµÿ¿ÿ÷]éçŸt!¾ñÎoÏŠ‡ß§,®ãƒÁ"Œ‰]˜*Ð fÓsò–E Ê€»ÇéŸ5O‚ ­!¤z Šþ ãbU`¤1F")è¼j¸úážý 2 € ¹ˆˆëóí3Åì ñ‚U„oýè ?0\é=@BHoÀ!BʽÒ߆hέR.”ï0¯ßGˆ®Á¬ ‘°ˆ×Õ.lÄžãZõ4+#üføó÷ ¸ìÁ{®º¶nO÷~â’«ðÉK>jP-x³ƒáp–Õ^€ÇÇ~¡êèŒXÛE'æog‘´"Pdó»Ç+¨œÓ0 ”Ф‹{…TÀ'c˜’u U{ðìøB(í‹^ª¶í¼eìhçEqÏÁi3™pºÚo øèÐÊŽCç"5ônñ”ÁöDÊf‚vH»hÕ¤(ݳÝýe(²‹JEºBl×Î>ôùÏ¥#Xö áŽ÷|FFõé}| .u;gú¾Z¿;N¾Vß^ZdÄRkœÀ€b!_Œñ`À჋ñäȶ`Í!‡¼õalý´€vçF{§…Nƒ§>b7s·³OøÖ3»UsŸ £™æ† JtöQéM|ñà¢Ø±&]6µ:·Ûë»pdyÿÆ¿xx >ôùëRâ?áГðÈÇž: ÄoPンtå™d(~ ¬Ýd;Ç%£UBAaJL(aI€%•%¨}X1´œèaáÒÕ_\üäǰG*n¬#ÌDö„kè¾£gÕ¢þáWr$µµ¡ Fþ«” ØS+(K#°Ó¥ÕŒ%ƒ´"àn˜‡Ö„_þ¡ß~÷ýøÂ׿•ÿO¿ ?¾ò³–ØÓ)ªtvª w‡²w9-3ºé7,Ò.…Õ H@0@‡0Ìû1ÀûpôàbR Âðø¥‹ß mF—38mtK1®Ýß$ýÿ‚ãÞ®CRsJ˜¤EJ ©ÒÛ\^«s­0ZR”T2âjg2(Ú>]´ºoó³´–p·Ýù3ÜúƒŸäˆÿÚË®›±6ÏBZ;ÐMpà¾WŸ ñ­—£ÁÓP LÈ} É9RA@B,ä‹ÐôbÕð pÎQ#Á¡‡_¿øbè.ÃvWa{ÌA›!t…Ù©ð×+WÎ[ôÛ„ ’7Y 88Kâ4Ô¦’pšÒSiŠ~ÜÖ("HÁvÂXÚ#twju<Ûô‹ôðO\rÕAGü0,:ÐMð (”^fROÏäPhvêÖ“ŒIŠ*íEëAÀª8rh ©?yñ!oF樟‰ï¢]à³5léo:û„ªçŸºâ¢XÅ1ç}8£T‡î€¤ŽŸž")ÓºýY\?)Î)DW¾‚ößWgŒbzèŒÐ} 5|î–o¥—8ÿ¤ glß™FÍ–`ºè$7azÙ…>D2¤ÒõeiŠ^:€~VÅÊå¨ð€VY°Œ~jÞË M ´OÀ™_À¬h/X°äõ„Ð R’È$dg«Ii ßZJÞ‘1ƒ|¢¢£Ê±EÖ'qÛ=¶èÃéöÜÎ@@põ­·¦—29ýÝ`db/n»÷ëÓnSæ‡ËÓe!â–¿•Ì’°k®Ðùo–fª&ÉP R&µ­d ¨ÌÜäDRO¢B+˜Gç¡—ÕÐÏzqÄÐô†ö²£^¸þ€ù|¶¿Ñ·zúWW]D8Ðû!à”¦ê¿\¿„ €H™2†ÐÞ‡4»˜Y¢îìÖ¿|rCºúÁó>Ü•Ãodb/^öw/žÁ†ùÑÇ@î÷*úí¦&€+?þe¼ù½Wã-r-6=¢0?8ý|1*´?ͪ›]´ú=ý¿¹[£ ëÞœ9ƒ•Ò•*£¤l= 0‰©t+à4D…öƒ³+–ƒ‚°¡Zï)¸(X…f ÀÕºB§y¾ œÚqâ²o„<†çPÊ¡”‚2­›A%$)C Îó¥™C`kH¬£Þ~Ï=˜gªgÔ`m¨«¼þu›îÛ¿ð&¬Ût߬G ª¬˪ÇaÓx¾¦ qî7«ï ñRèßÿÊKþWœùN õêöŪŸíþ6Nüb÷¬¶¹Ó÷HDˆ(ªÃŒ R „¨¤ýYéFÈn¬Šå 1¹ëivÆë}Û]7?ùahb—È× ˜Z±Õ²÷¦À‚OÏ;a0¨ÓÏ3,¶27¥ûîJiMùð–V`ÃhV3˜y¸Ï” œuôÚŽ¯w÷3_Ã{¿ñ{X·é>ÀYÇv~Nñ²ÅïDöî3Ï÷±º 2é¹yÁ /Ä•—|8%~à$įϿGöŽgté),3@%ƒ±FˆU ‘ŒfeÌ=f€A>Œ>VÁÊ¡EN–ôô¯E±äŸVh°ÛD ûæ©#ð·Ž[y¡ÝF(*I7H3Š®”27ȦpˆYYêµf¦Îo>Fä™Ás)´l7a© j7ÑGAâÑ}?ÄM›ßƒõÛ!Ût¶ûؘ_9´i›y>¢8¶íØ>×ßÿÁU…×9uøôó…³ÒÆrta2PI—ð¤L½ˆ¥@]M¦CÔ¡ 5TÁI€áÊ „=¬Â‚¡…Ÿ]ø*dËÛ%ömzì3`ÂåýóÎ3פŒ:e»TÊÜ!µ]m 9Úñä3 l­ S°×| ªŒQÙÏU«r,_´PÀ½³½û©wn¿ã="Æö]#€ÂŒ×(C?_äý]`Ë3ñŸ¸ê$¬<¤¼]ç,úcä cìEa二R_€‚d¬SUO’„€G?Fõ ‡X1p8¡ì˜åýg¡¹|x«H@K¦0 §þyýâ—2sS!t±LžØíÙ+ðk¶yÐ|£ôØDÃOíMóÑtã3ð}peDÜ-‘—1³H6ð?x=xçÆ]Z¶›“Ë{W§ëÛwŽÎZ½¶å¹3…ápYá¾Ý”.ŸµfmËk K0?X‘ÛÖ)3˜æQî ô1 VºÃX„Ñ#[£%MŽ«¦”TÒ*V ,CÀYÚ7x&Ρ«PLü]¡Œ¸Š& €Ÿ¼dÑZF©é Æ(@(„u™"&`&!Ìh½ÙËk—!è+7› SQSQ#%¦©¨Ñò("Üvˆ¹³£HcqŸÇž&Ä>ø‡¿ xË¿¼©­ûœ¹ð÷+…щ)ìÓU€WÌ_ÙÖ¹3Ó)Á.c‹¤Ä/ PÀÙÇÝÖõVüŒà:[a¶5üåO7©Àq¢Ä*†”‘j`BM¤Ç1 Ò!PÔX kÃ$$Œy颳‘ÕÙ(’ü¡ˆyûí.¿VXbIÿðÙ *WBQaE¦I>Œf›2ù8Œ6À(íˆ è«ûµ›Ø„ˆSf`¦v˜Cʤx;ÒÝ×î" ÏçøŽÁ½W÷Ó-Û6ÀÁ ]†m;÷˜aåÂU]=g70 ÀƾQ…ÿûÿ¾‡ÇŸÔÝ—O<ì$\ð¢ö –ìmìÈåÛ·ëï±™Åli>Øf€vvª$$£¡ˆTuUO©!`¨Ð*ª¬Šr,ê'”5oð|hz« ßA¨k`F‚«'Þ°|mCvø. u© \=òuŽ„[UJ%I?ym óÀ—4dœ.§mn Qf蔘;iS+‚÷áâWžŽCæâ}7½;õê—á(ö l{voúª÷GÀ€Ó $ õàŸþ&þô#×ãáGu¹² ^x!¾û‘ï·u­­SëñÐèíª=öiqî¾™/¹Ì="ƒ@e§¥’ÌÀ‰Üq ƒ¤! ±¢)BÎÑ_­ `9²!Ó‰”éNnèÈ8M:Ê€êÃCŠŠ´7E%©öc3’ó ØhÎÍ6LÀ š‡éê º!M—»%àV÷™ dL0ÆŸýákðž_‡7ÿË›ð?ý~i\ÿ´•¿‰Í7ê÷yŠýÛUøÑÍëqçãÖïü8 ÷šðßqÞ;Û²ý÷Å;±~ßÝøÅîÛÉÉt»Ë´}~Æ8¦¢†÷xsN÷¹$íi¦¨¨€$ ™6 à4„„B]M#LsB]D 5VÂÚmL|rÞoá}»Ÿ@–  ‚QÈ­TÚЙȠéëïéyICê‹S¦+¤‚º‰`µ"ù€I‰´MŽLæ“kDI¼”µ®Ôœpd_9iÃ4 Ù"rEš$Þõ{ç㮿ï»éݸöÿ”§ÿÁoÇ~Ó~uÀÏy_¿ýG€³[‹K_üû¸à…æbý.¤Šqïž[ñèè]¨Ë bU‡p$$e)QÛÄ_vüì Ÿ«#•³* KBC"V1bUǸš@ +¨Ñ*B¨²*&ãq,êÂÓ£;艇öž{?vÿËLµ°°%¿™SdI !>Ô÷òy•^ˆ$ç?–Aê$ BP1*Œ#K`Ò°µáü yònfF3(cEDc3†vØ0‰Ù$övMW#€Å‹ûñ¢—~x=Î?ùU8ÿ”b;ú‚S/Äûnx7ΚÆ`ŸÝàÒµ—éßÂU-Ã|°·± ÿùÌßc4ÚÑÖõ‹ˆz*j  ¥é1ÆdÛL %,I Ò(c(PT"–1"Ò€Ξ%:r•TJ± 6Ê(]Ú×äýÀ “ø14ÙØDfT…jJ¹^E›h@kþhÁ嫆æ¦PÞTu‰Íäl¡$„Òsî{ñzì¯4oÀ¶¦<õVÁ5¦„ér;°óh‹ê¯Èµfæ!œ¤¨¦ýBxó&ÜœŠãY‰Ÿ=ð$¾ñ¿·á¢½C¦@5¨bÑàb¼ì„—ï×:Õ°Š•‡¬*•ø÷ï¹wlû,¦ÄXn»*^'ˆ5ÿnŒ´ßˆ©Ñg¶±d´(¡Dz®} sõ;ùŽÚGÖSÄ–@W ¦ÔT ÒCâ´‚ Œ0(B dŒ)5àɽÏI~yØxÿÓ¸šðãäŘ¹!ü¶¤ŠûÄe¡>·ðG`xYo_Ú«Ätæá沞».⦩ ™e9vGaâ4,›¼×žÛ¿n ´ïÞåm.î€ÅÞÿ‡bljÿã«KÛqé™—4ƒlŒF;ðï›ÿ ÷ìü2„ŠZ:HÝmÆã惩_”Mjc%‹ùœ ±j4uªÐtïŽå ºhIílUäË…Qgê8¨q˜g ç±µ+†ç+»ØA…ˆí—H÷2)j1ðÁŽ"t"™ ™C„Ù-Ú¹f+&U¬8¡Tã­¯{9ÖmºsË_M³åû|7müS<;õD[¦VC0N]Cô «§E}Kìùô {ÌA3•ÝMX*™ iñã ¬ÒUÊÑVŠÅÃárÇÀŸ ÐlÀ—øcnXs†$Ùÿ–áËO]±äPD?jHµãÅÑ5«¸¯¼Ý‚ „’ˆ¥Ðª™eøÐl"tIÍÛ7 šÓ–Ë&cJ•¾YewžÓR틟®à\øL#}ÿ“ Üøß_ÃY«×î×|ÿn0ïÁí[?ƒu{¿Ó¥Åî7âSß³÷HR§y± hS wÇ4"îÂ\È̹ѯ!`„‚‚ƒSJ8BpP0€P(¥³'åbaÞm$  ëݱ[q?²OÂ?@›yOdÓƒwÚÀ6衇T^’áù˜Í–2Ó œ`¾Ý˜iî5;™Ü,?+¡T:'m(*•æ­%½ý eÏY~Þ«^v/ÂÅŸ~5F&öžq ±~ô|ñÉ?Á–‰_ÎÈõ|æ‚Íìíæ]¸ù݆ M‰¸ºŒ T=q÷évè¯ -çûÁÔ ý5UZC%RBð›=¯D{‰@.ÑçÖË2}>€lúurμ¿#)¶ŠsÚŸsÆŒY`ÐL”6èÜ4èv[ ÓT ±Ñ™¡Dvïîß·O)‰wÿÁù˜ŠÇqѧËý“b_Ùø!ܱõÍŠéÕnr•›f§(7÷ÃÈg‘N¯:•Ù¬MÐS2²üõ¤ÓvZê¬GN9úÂ"€àÐꑆÐ\,´k€AY€ìG/ZÔן»)û%â"Ž+X‰Ü£çµ—ä_Z]D‰ JA+†Ð-#È*wþô˜J{ÚGY{Êö#IïÿÃ×à݉«oo*¼¿ðÐȸî‰wâÙ©'½û÷§S¶6¡»™žv>g2„HÙì'Ë”P‰T M}“ú<ö€X13Ñ%á´ê Tæ§-é+÷&ÛŒ {ôŒdËœyÚ„q£­‚=h5ùÏW‰“$#X1C„Ýi{Êàž#ô QôÔ*x�ë6¶Nž DrÊ»}g}®â=øÎÓŸC#žj2±l¸L ­è‰•.>p# M÷ïÒYh†UJ¥õUR8¤‘¼K =(m?0Xë(Eo‡ÑS‘Ñp­¶hƒ­Â€Ã‹Ž©ížÄiÁ€4‰D‰6CfÚ€W+ȯûBˆí𠀡™¸ìmí1‘î ÛÀevös=3!§­^ (ࢫfß°qâ>ܱõsxlßhf°qâ~|}Ë'ñ•§>„½õgšÎiÅŠÚfBÊÜùE ¤ >ÿ@&›;ótãíR™XdƒÂš1ú‚BB°jhf§A§ãU jÉ ºófœ„Sçõ$†· ¬d€ǹ»™=mG!·ù‘ 4EHÊ*–c¦ýtãrtj to.øQÆÐZ1;F8~ðs-ù7îØ€[öu\zÖe3Ù¼ù6ì»þ ½ì_Qáý²Ž‘Æ6çHãc1Ënv§MØŒ1oö§Kئ稯©Y.Jo•k`ú™0lB=¼EœT  C¢¡¨"ª6€@@!ä„2pÂ(–Kh1€ ݶ#í¿ïÌmÉoÚkæNOeU"–„óì©‹(é à1"N:jpžÓÂR€yF`Ã0…”dL¢."Ýä䲯gŒìO”¶­ñø=ëÓÛv¥Û†z†pÁiíuµí{£mØSßžvgwƒÅºx§@Qj·BˆÁ›mæ\w?cL¯Ë|ÁYÃ@Úé7Ò-|)ÅíF „1m•! ‘é{*BL!T!ÑCˆUHˆ€T@1†ya [êu BúñBìÃ3ÈhÙ\†ZszkB7”¡p?e^O•@ì‘{¢Å†D‰³Ð8 sŽBo Šœ‡™ýmËTÔhÛ‰è½Ý4M Ÿ _4Ù(˘4ëö¾zRÓ¸ñk?Ln\þòwÍjöß“ã?î©-¹mn·o{žGóï˜7 š}*Y?æ´øÂ¸v÷òV&AÑ1Ý„Ë`(5çvV qÒ±.V"IÖÌ)MÍ‚`q…âr*ZqÕ±(W°5ÇÖ¬‚ ®)䙀O#°µF3à„y™@“™P’,ä3ÒS; jBiÓñ>­¢SFÑ* Úº²¯U‰ÖÓ|­ÿüÞ}Øþ¬.ýµrá*\ñŠwvÔ®Nñðž{'Ò¿åÄßî÷k›ymÁh­r6Òs¥¯D½F'Eh\§ O#h™7 „¤Iu—÷H ÔˆJi€ƒ£Ê*  è¯ô`Ãè.ôŒì GÊäØ9bn–¯­6§Ëíú2ó`)N'dA߀~À8i gº/€Õ-¸1ÓRûæ¬RÜß Ùi¡ÀÒ—YBw ~ÿ»½Û˜Aþó¶nÅ=?}4Ýúù·\7«ÒûÔãØ9õtÇç2m_A÷åj)ëÖŽpß¡ÿ··‰œQšënn˜@»ÝÊÝÚíøTªë6)(ê›dN Ó™µÉP{‹8öõ³# à-rö幦³îR/ñ°5€3ø‹Èž ôþv¦CÍŒ6ÐÒIh¯#F%¨žÖ§a”ò|þ¢‰P­ïʧI”aƉ¾l!Ý[Çnøït×§.½ g½`m›mè÷츱ÒÒ¿ŸKQ´Șï}ÉtYÒV;(ëFnˆ?=ÖŠ2¸LÀvšuw»íhG 0N@ ‘DŒS97 IDAT\q€’.ÄÐö Â¨64mž àà×JÃ&4ôÒeäÔdúJ@L囓%f,E:énÁíKÎzTO}±•Yè&•ú ÑnM@I9íhŒO °΋5ˆ’Ä,‡øíínȱÌÈß-3І³óÒæïÏ”“É5á©& ””¢XCŽÂ”[Äô~r™BîAmà³Ró#×è‘®B­¤‚ SiOçì¡“Û1qµcí9 Ë`3‡R³¡m&¡ä¢%êz ´2aŠ®Câþ_lÆæ-:æ?Ø3„¯¾ç–Y/øÑSøÚÆü^>Ó¨Âx)C(‹¬Ì„Æ`Ãçtlö)xÎóä´£ ø‡8(d !8$"! ˆ„¤*÷†`à„£7¬‚$“p&Ä)hîàÒ°>`«ÿy à,@{jJ($'Pp?’z‚ØñXgªK¢²uÉ|°Íƒ"À}3-¯é¦Ê˜B¬„×´(sN¶ë«hÅFÒg îøÞºôœ¿xí‡qâÊÙ¯ø{ë¦D]è2Öy(o“Ûù 6l­Áf@¹Ö`Ât˜ƒÏáÈP¤-)í2ƒ¢,B … BÊsç C ŠÄ  Úa+ëÒú’‡x y矙›©éÓj·(¨ž¯áGˆ(%aÀµW’P B¸©Á–¤-¦/6‘”ùâ ~FdÉEÖ^p[3p³ mf €¢5#ðb”†~òÚ„!z›øgŠàfÿÜòõŸ!úg­^‹+fÙéÇÄ£#?IÖŠZî‹Ûd(ò›”in.Æt5„²4ïL3п®ë´Ó•;õ d¦AǨò"q£Óä»1áA©²^F÷ Á¸¹˜Þµšø4€B¸©ÀEN@m_ ÐÅ8#±’i¬Ÿ€ F9$ô`u)d½éJJIcšœ…ÙöÎ5‚&3¡€Åñ$ý¸SøØ¨‰HøÓuüè–è ¶=½Gª“\è o›}§|oëõÈ| ÎÓÙÚ'];ÙÑÖ}Œ£Õ»+®kRØšAîNÓÐ\&Ûg™e£Wµ š‚¥</@@×ÑІµè$ÿÕ5”€°2½8ãø)ü  ÐØÙ[éeK EÌ&èaå Iy£ e¹W–ûŒ•Ýß*ëñ$<ö³y@>ì$„˜Þ;é’lOÓr5 ŠÆƒsƒ‰QR,%.™êQõ¨îm»™nùƽi®8÷]ûm¨¯ËŽü;ÙJòp*ÇJxL&å e6‡>Ýtæ|”%²˜/Ìê´‰¿Ób2­…ýlÛÍ!HÏk>Ôj¾D]æ{µ2¨¤3PF y­ V 0Q `ýè ügÐn"©:Úg¤ ` ¨QF9ÎAõ$ôxàHŠTvúÞ¯“YØ*Ÿ˜ž‰vˆÑõ”I_w?'¬ãó›ÚÓ„Û—¥ÞÎvª¯ F8.9üJ<¸çðÍMŸ…P±?Ja"4nÆfN3ȯáÛȤŸñùŠ‘@^[ðužj › ¸‘€òD£ü•œ^Œ„@ ™R[µ¦{ŸAR<4/ â(<“vÙò¾WH„VOŸ7æzèÑ ”ÝPB ðä9¡`\Ç)³úÿ-”]KBø”h_B‘­t CtF¢ú’ŽÚ','¹Û=:‰Hì~“ð³?ú4X3|6ÞºúŸÐÎÏm!S?Ik¸ú‘«1XÛ’õŒÈóyíæc¸æ@»Õ¥š«Y$Û[uFjÑùHY×®ËÂ’ôÊa*I$Õ#k§¤Ì1€.4—KPg² mè‘¿µó‚€p0ÂÀ‰vapbGÚO€)b®‰à3¦Ã¿¹Ð¤Ñ8ûêQ=ÝÞɵ§»Êúçî?éïb(\„+V'Ì[›#cM™šE…_Z­沸wÍ·ÄǦ¢†·˜L+s¡5[Ï?½[¨ÄÇ lŠ ¬5Ó °c^H4 •B#Š!Ì‹ Úè%KP<>€Hoï«àB¿ù*Nìð¿JwhÛŸA¾b[¤o¬fÖF"Žô´Ä丙…n§£™0\,ãÐÍÊa~e)Þ±úZ5pZºÍcå{Í…8'Îò¾Wkh™_a›^§£ÿ[q‹È¤—óu&O#œûäý±¨0m:gÈw––_@3íH?yF<Üb´ xw›/kÈÌí‰ár$bE€LBhbh$‰ „Xaóèv‡‚ˆe:FÐ’$?¨T² âî%ÈÇKá÷¸ËBÎñÍ[ïÇ/îÛ”nûüÛ¯kk°Íý€†xÃáÂy‡¾èʱj>Bn2†[L¡¨'h±ÏA§ºçÑ7ªÐ .Cð3†fç¡Rºü½LyM/²àTB¡.êÈYã"5–¢¸((è>û„j• Fõ'zè#H•#XBIbË$meÚ—ÀWYÈÿ”×O ÷åWÝn˜>sÁ0“Ž<æB·ŽþõGؼeOºí o¿üÚÁ£þûpÚü—ceïüóÃïD#Q}š¶‚ÜJ¡&Îñe¥ü©ÙewÊ1¡ÇnS‘›û 8Ol²d•9ЂLJ™>c”Š Ulå $×iH­è^wEÄî³Ð: ˜] ¡Ò‹Ȥ%0F! 5òlÌú`Ëò²èAÓàµM "c¾þnmÈv:'QJF@IæÝ¯Pžšu§>•„ëVJ8ÐæêÞ·`»Ë)8†Ù‘zQ‰‰©:"%Áß §Zõg„£‡‡(G@BÀ¨ PBA)…XÈŽAÚf6\†P¢%¤ã³øQŠˆï8­%Ÿ0˜¦°f“äQ ø÷/ýOoÔãû]qÞsËàË—¼Wž|3ÖÌ;ÃhMfJã3P†ts ì¹}L ¯QŽÏPjÔŒ Ù'5=@š.ÈPÚ Ø€ÖˆeŒ8©pû®\±PCJeR¿­D ô…­ÎÌ»“úÁ ¹c®Ó‘ £@P±ü&1˜¥üŒ€mùltÅ\ø˜BÚB+¤D¯œóšJŠ%0Û“‰3Š[nøv=;8qÕI¸òâOÿy„´†7q%Þ±æ,¨.íê®ùà_ÂÀWY(ÖìPbëѬýZ‚ëC°Alu%€¤um­5þêÞ<Ú²ì®ïûì½Ï9÷¾¡ª«5t $ ÔÍŒ0 !$@’’Ø[Ö"q†qðZ^Ë,ÀŽ NãvÀ$¶ˆ‡¬$F† 4ÏCw«ÕB=¨»%uWWuU½égÜ{ç½÷9ûœ{î}÷UW«É¯Ö­óî=Ó>Ãï»óÏ8ñßjj[S˜¦Kg]¼®ù{€aaoSC^74MgùÖL!R”pj@šú"!ÞíÚè"‡@N¤mT¸A 0FÞ¨x]õþ‚A²³>¾Ýèd‰âo»—KO×ãïw~ò_œ}Æé9;_ÃÏ|Ó¿àEç¿yJ×u4¦¬³-ÄÒ@çɧ8³1‚Æê5^ƒmŒ‰Aj4A~7N´ïÞ“àns)Òµ®]‰0Ó`­u•+uðÿÑF÷_ í#^ŽÌ%h+qí¤öqÉ~œÖ’ˆ I*$B($’Dȶv@GvÅÏÞÕF?»j€ ljʦîÙ0<¥RÂ)ÒCoß±¿Gh'K¸ûÃ_æû®´ïίþįqûmÿÿõœF¯úª¿ˆýüFDeŽƒZ0ôBmõš9œUÉ`åÙšÕgÝ~ áÍtî?!… ±÷ûe2kÏW7óuM©5eóanÛø»Gh[pO¡\j)KãQ+ƒß,K&숄T(™bé¬îŽÑ;ÃW AؤœÕFÜXx²´Ås’RðÀ]Wyÿûlß¼ŸúOš×¿ú 7|8Çõ×OÜðã^ݶÿòv"¸Ñy›< 딇¶ƒøÉ %·í_GÖ¬¸›Cb)óÇŒÆV£)š’EåíÇ~lÝ/³åÌßžwËíÜHR_¯PÁåyM®j]¡­éDBc&IJ–¦ìØ”J'ÔÒ‰.bàòèʆ÷Cpc‰ ¬OBŠA ‡6‚@*‘+  ¶Aþ ‘^þà?Ó~ý«ßÀ›~â×6ìq}t\?Á›>÷W¸6¿‚P Ïž<¯½ð­|÷-¯ã…{/ÝçSˆµð¬ÉWó¢ýñm®—2¹Cc*ïaŠ«@ÝèÔît4l:ª;ÅŒßXݺëh»!àh˜Ñë3µ5hmÙóíïºuýf7 m]Ç \WT¶¡Ö =„ùT öÌH¾}³;w"ÇåÚ@c¸4;â–Ý} Ó¸XûÔH$¥±%S•1£À =²5þotúW9R4¢ƒ$ÊF `0C yÃüƒ§‹ðÄ$€ßþͺ ,Ü~ÛüêSÀü¿ußÏpm±v0ÆðøòQ.åò‹oE ˜$;âã—ÞË'.¿—T*ž¿ÿb¾ï«þsêkç¸õüsyÑ­/:Ó¸_ñ6ˆÈÃ(Ê ðã1BoúÛÄ 0ˆ1²ôS›µµL¥l™Jˆ®áNàk¬ï¨™W%y]1¯8¨û½o[ÓöíÁgvNECfSÐX®-kš¦¦ªkò¬dŸ©ßXÉ„‰PLUʼ.˜*In$ZXR¤C6Ÿ)(¥è¡K 3öÀש6Ôª6©±ª q€P6Q€S²ú’µ™ƒPôŶí%ŠXСÊk>O'ÅýÎO=5)¿¿|ÏOððìþÞÆHô=¿ÉZ¨´æ Ç÷óðÉÿÌ?ÿ‡¤Ìóüɯ¾‡WÞþªSQêe+Ä=#¾RtÖhÄaŠMRBL•Õd"aªº € ˜È7#¨LƒÄR›†¼.¨ê eY5p¨¡¶R(Áõ¸ª¶‰tøòQû7ÒpupmÞPé†ÜT4Ú µÁ—Ö(ˆ$c7›²“fî»$È•ømc|µ ÿúA80n CèƒÁ˜ápãáÐv°Î– ZoÃõD&Æî˲©Û¿ßùÖÏ·Û¼ö;þ<¯ýΛòk¬á—>ó†–ùÃXtσòdIZÑ2?.ìob—‹GИÁs÷Ïw¤ ìÓ]äeÌ݈¿‡Oej—%k-µÑH)}9½n⊣ÛPÛŠ¢©Xè’£"g–kçT~;mƒ p9Þ&ïfKgQ Æ ¬ð‘†Åqͼ)y¦i(tEivÐ(+B2)¹JÝ% ¸›” Eå[iTÚzU DI†TëX-3¶W:°Ä6‚@ãml0ÁÛKcÒºýV T-®>>o¿¿é¿º±z©sþÞ§~Œ«Åå•uÛVEõ)ŽûÌû‹·s]–:ý}LXWò+]Ëa¨FuÓ • Ò aæŸ6¯qY²)’ÆXöüû«ÀM°º¢1 ¥©©›š¢4Ž#ã€DvõážBë`ˆýï';Ô†Çf'ÌÏ|ìuk™Û´ì±ÔìqµGp÷'uZxåË_¹õX/- ¤Š»GÅñ.ÆRª‡Õ¡ ŒjùJQ¨‡‡¥‰êCö€•.Èë’….)‚ð$•°áóÐõŒé4`•O*™lc(/”ßZpË^MÝ4Ô™& ‘"#S–L¥ì©Œ™J@׸>.³Ø…>v¦†¡4DT~ ªœŽðmBäES†Ò`\Rˆé4©!I\aÏ44…áów=Á‡?øEÑ´á-/âßý·Ü°Ùÿ¾£OóËŸù\œÝ5dBQÙ¶¶‹7JmçF)V{ààê¼=Ù/Ù>r±4åÚu}U°{Jtåâ×Õ]c¹Ñ.ųRhœ\ã•¢qa6qS½ÚºÂú‹&'¯kºâ`é=!;9PÉ |É`Gñr(´{n–ЇÈÄ×E%J Ô,šÊ5[0µk\`&R*‰5Šýty½$ ©R4‰¢®u˼©`pm’ý ¨mmq¡«*<·áªûpå"¢—'¨ 6½s@8-N“àd¤Ÿ@K>sr,±j(ÄÆBmmÛ_2P, „TÞ±Þ“Ý1L»ßX<¶ÍhÂ(%„Œ€IPkË´{-µÖTº@7FkrÝ0Ó•«ÆUÚ.é7€Àý<@0Öǧ۠ÿÃÙ¼ðxóç“oé·ð¥ËÏÙ[ðU{Ö*[2%kR)ÙI2¦*eª&äMMš$ÔµAãû¤CE þÆDõS)z3¸1.n¾»ÁëŠà”‡cûö‡@cLÔ­ƒ,W¼ù·?Öþvaïõ5oàõ¯ùk_ñÄc ÿìs‡\z7п–ø:%Ñ~9g ®‚¾z¤Š*×gb~جD0–F% " ¿kk{Me†êÃÐËÛÂvÑ ·—*”7D[,Yô.J“Ác1ÔÆPçþ;)sŽÊŠ ãbú4guÒ† Ì}8}ÇÒÎA ®‡Î8oXÖ5³2g^•Ü<1iÛšGRd줻œËJ–uÎ~’2kt+¸f—þÖx†r(¤ŠžDîX‰«5wPè¡T×-´£ðÅ;¯ñ‘÷?ÜÞ¬×}çŸçwÞøôÔë¯LÉßýÄ_åKsg Z—[Nõ“t†¡Öá œU=H3·ÝYÄ€“òÚö¨ýÂ*¬üK]Êúvs›j5ºêÑt±Nªt“–n I¢ýº '. “H‰ÑÎŽÖØšeS2¯rŠœªj`¹R,Ðl€±ß[8m'wª÷Ø{øFk[·ƒµ®‘_i™-JåuIÑTL“†ÜìÈ)S™`lÊN2!•>.ÙJ‰rÑp™±TR¸*)+åÃ;#á€A§ +Îl &‰ Œb©‡à0”p÷åsŸêÜ®oú¯7þÈÓS©çRþE~á¯gQ/Vªý }»ÊðƆц·5&‰<Õn2F›ºèn¤#¯«Êä¶ï¾Š@ÛCúCLJˆžt¶ Å>‚-"€I;÷[‹î]–JúHA·o(® Pë’ES`š†ySR75³ÜÀºñ+L9aNS†¿ã*Àºgg€ ÑÖ ¼OÚpeÑðÜ<ç¸^°ÔçÙ·%ÖºØq)%Òd$IÊn6a^g$¦\K¤`u^ ˜Âû[Þ“¡j㞃! àê™&–ó& À ‰PŠ 7_`Q•äu÷2L‰0оãAù|§¯¾ñG~úicþO_û~åΟ!vÔñ3¬˯߇*O?±­4¤òtËé€J½ìÙs®‹†RÁU!¶# K¾ ¿%„@!˜'Þ.aTÍă€&Bº‚9~;éŸE¼_áƒ~´©™é’y‘3«*®,˜yŽoìP˜…»0X©÷û:@ɇ.…€2jèþ½r­¼­9 IDATâÒ…œç,,vs–Ù.©É”!Š©LÐj‡…š²Ÿ–Tºbn Y’ ýìÛhMTŒS't†B`E*€UϬŸHÉÛÿ÷ÏQ,¬5Ü´{¯Í¸ûá»xß=ïåû_ñ n}Ös¸ûž{¹xð(‹“þ¨œïU¼ñµã)7ê­£_¿ç|ôòÚ¸¬¶ævEêgà;Í@:´ ¥wüqi ü–NÝku×wm}-O_\¤'Eë ®´…ûRƒÁö~ëç£ôkC¶‹BŒˆDPÛ¨³™ DüÀ5΂Ä'b%Hj*j«ÉuŲÊY˜Š“ºÂä#jÉes'mdÎ ÏÚÁ§G¡ãï:W÷ªè°Ð³ „^œ!7,ˆkÅ’Ã|ÎùÉçSß ÜZ¤RH£˜&»Ù„¼žP˜k$ ‚2ˆë)`e@=€mCybÕ@IÁ]ïù"õB#¬cæÿÚ§×úßßþ±·r´8j×ß~ÛOk_¾{ŽÞÃ?úÔߢ°6zÚë™ÛŠÆCæY¬³ \xw„4sÀÑühûsÑ=¥µÆ*5ia@£jDlXŽ Ò¢;V,aX ið¼Wö3“ªÍ—‘Æb|5`) †J7uAY–,š’“<çx¡aÙ8ÀPȿʬò*ƒï£/Al°ôÑcLh8Ð÷s>y1 zÏŒáÊqÍ-ûK–º¤¨ ª’Z—¤2A"Ù‘Sštß%6¤SRKwªL$¢¦Ò† Aµá¥Uƒujôƒ‰»©â¾»QJ€Ÿú‘ŸÞ|s£“rž }êÚ»øåOÿ ¬ÈZFŠÎÃïÆX””„Ú qð”ÁúF.ëih…>ìŸÔ³nÝç¡{œAïh~´•7ฺ‚庾ÒZÆ@áz-[(6#œáY ÐÒö &‘4V›ŠÆÖh[³ÐESq\–Ì–M§ÿw»ºïù›%€!d´£>K ;åŸê/ð|cÛJŸá¢…`–kªºáZ±à“‚seÁŽÜc×X¤ JKT’²£2*#³ :Q.ÀÁ:}¾2Æ©k¤€Þlº¨ÂþË»<ÉAÈ6LøG¾óµg¼ O åzƃ³Orqy?SµÏóv¿®]÷‘KÈŸ|ù-,ub‚cón¶_±ú#-Àx©óM Wc.CwÜ~üÀWÃy>þnÀÂÝÞÅ+ïxÕ©×~\]¡iêÖs4¬ÍÒ¦Ûóÿªà4Fn®wO¨±–Ttú¾PîŸ$iw­VÓØŠe]2«r.Íg. ׫ú÷¨¯+ Ö %€Æ¯¹ŸûøEg ÏD…æ¨h8É—Ìö–T¦¢4K ³Ã®R(‘²«v9—Ö”YÉŽ.ÉuI’$¤¦ÆPÖ.̱’ Ýê1÷=›Uk-'W BrãÍ{ž¶B›-ïã ³OòÈüOùè¥÷p¸¼†E`…+qÍØ½” ü¯Cƒ³ FÚ<Œ±XkPmÛ'<ܱ&¨Ûd]BwsÖ>†»¶w^‰ÃýÛ©I?àhû䤧—®ÞŸ¡¢âxЖþùJábhtMÑÔ,ª‚eS“W%ÇËÆôÿnÞ» Ç£šŽ#×Ùz¶€³…;rIAj0­6*ÃÉ¢æèœC¯EYp!ÛG'%Ø!@*ÅD§LTÆžš°TC“4d•Á*ƒF“k_¶ˆÝîÇÄÃí«B€ž[„uŒðòÛn?Ã-¸~zlyóûxly?-ï㋳ς~½¤"°b tóñœM£³k„ߤH)Z›t"|X«à’SúU›W#ÝÖ¹ƒ‘°ªm×wouŠfYS‹ Ž2Vt«âôg4ŽÁR_?0’‰LHe>PɤUÁJSÓXçþ[Ô%³bɬ©¹vRÃ\Ceû@8¸¾$ @ÁÈ`9f×T³0÷³'¾¶s’âƒ4\=©¹p®àxoÁñtÎÞd‡i²Ëž²X¡‘HvÕ.{iż^²›f”ºt/ pY‚ÂZ”qÆC1Â6á½cíÇc©ÀZxöóž…µ€|ßË^y¶;¶=¶¼Çòû¸¸¼ŸJ×<¾ø—q­¼JÙTÆIÚ¸¬9¹ô´Jfƒ*¯n7´¬kí ¸ÆtÖë¡áËXݾ ë\ˆ±4€à¾í«¸÷cyßïÝx][~aå·u)ÖÃ: cUš†ß¿R  1(dTáÑIL²½‡8•˜Eêcj‚Ê–uEY–ä:ç¨Ì9É+/þ›NìÅÿ{¹›Îÿ¯ÙÌÏ+ž€m³ûoÅ£Í=|CòÒÁ]µ¸  \si1çYç<³:G™å,TÆ9u…ë ¼£2ö’tS³T)UÒ°ƒÁVNȤ ׬Y T9ÆA »Œz¿r¶šQÇÈÙ蠺Ȼû—Üu탗G”F£µm3К(µ9̾á‡3õp»Ó(l7æ> Ñ‹áïPx%þéê.ômA2Rö‘j댅qE€o{Í ¸÷cyäÒ#ͼe¸mØñ&«ñ8Vº-füPüdX²-¬@޶‰¥Î@-ûªcÔëûÒ•HáŽÙØ’²)YèŠYUp\–Ì̲ÜcøK{ xœqȳ£4Lºw‡@@˜#úaÎ'/!d¿¦Ñn¹e¹Ô׊ÏÞ?OÑTìKVƒHÈZ) dÑäLÓm'ÔMC*uè«Íø«†¾p_¶OýýÌ{¾Dã­‚íûßÀ›þ›õµ÷Ž«C2•ð–/ÿ ºøÇ\žÏ¨t7›Ý‹À SãícZÇÔaßuçÒ:¦Ë­u·³‡„}Sé–™’=‰ÄI*Ýñ4]¶åºnÉÝ5H~è/|;ÿç?»¸ëT5àÊòÑöïP¬äzjœF›J·õÔ‰±Z§¬d±®ù¡Á§#‰ë¢mÝ$c5)M©K‹Ïg”9—æ^ü_èÕò_´wÑŸùãµ[ÍC®"ÉðàÝçÑæ®"ÕÑjÃlÙ°Ì5O,,gÌ‹%¹-¼¥Ó5VJTÊn²Ã^ºË95% ;IJš(—)h]Õ„è!¬5]©¯a+©MežÎeS¾ø§]tÚk¿ëuoο}à7ø›þaþ¯Ï¿…/ŸPéX¬v˘ù*m¨¼A¬Ò†ÚØöû&ŠÅõøšÖ18ïðü«Û…÷aìès 4Ú7ö,ÄË@q[·a•ç`ÿ¸ù…ã¾õýo];N7:Ο-®ìWx.ŸN‘÷%4ÁM¾F¦«†m°4F#ýÌ¯èº i[3¯ UÁ¢(( YhXZ˜›ñXÝGù0ëytÌø·ò²œ¥&`ÿ ï2,Úv¢Imž[®ÌkóœÃbÁa5gQ/YÔ9Xƒ±šD$ì%;ì§;mùp)×`ÉN–’HA*:·R¢‚c`Ð{@À÷¶Wpa÷¯{Åæ¿÷\|çþ!®ÿlbÄ0 ׯcâøûhÖ§Ãg¯í}ël$¢½†ZÎ@ØÝÛÀ”ÆX´qj,Σ1>ö]û¹“Æö¤ÒÛÞÿ¶ÑûHû@£P«@@ï3¤1¸ÞÞ‘Ãc^YcÑéî¯ÿÝ©LÛÌ$unÀ,IBb¬%¯—.á§\pT\+ ?©ÝÌÒ8.­üû{[2ú:  ã[:# 3G|k±U%íŽR‹†YÑðØü„óÓ]öÕ„i’±hRö’]ŒPH‘°£&Ì}\@®*ê¤Ac¨+—HTú(3m-ÚXº¾©b,Fmà¯øÜ•öûiÌÿÉÇÉ«Ü Î[ˆá1­êÛ«¯Û§ gIîï3ÔÒ¾›¤ ÏÈfõ½p€Úß.•}o{댅Áˆ7rqGè¯6½à‘Klc— ܬ)T2zD7¬èŒƒà—^f‚Çž·£å7½rãÿÝþwà¼2kŽßkN“¼6s&Â1«ÏNô¶= ìÇÆ=³áú ei þ.„@{5g( tAE¦WT5ÉÜ+öÈãl¸vcM^Â÷±Æ/àT†°®/ëôiÚ¤†ø˜cRGü½ö26-Èè(‰P Ñ–D*!œ„+T+þ/ëŠy‘sX̸V-¸V/kXxã_é­ÿ¶=‹%þ ¡¯ª¯{)†/Hïû:ˆb¤iø`óÞAkú¶€ÆIUÙpq~•åŒY±táÁ4Xë1Y2eª&ìª){^ØI²4! B9;€T% Cè®yøÒwÅ<ú¸©ZÍ»¾ü¯™ÛñòTññ‡ŸÖ´,‚ú²éyÅ×Õ¿FkŒß—µ`tXý{8¦X½ ©."”nï¼+ß¾s~è&§[wŸïöÔ¹¡j7‚˜b 0T#†*Åñù{ ø;ÓÖ°ð¿,]©,MI‘€ K3vTÊ4ÍBR˜œ\××KUÁábÉq^seÖÀQú«€Løæ-} ±0f CÎD¶—Æé"E[Õ:ÂǨ´ b;rÊN¶Çn¶Ã¹É.•¡pU„•Rdb­ù¡3C¬ƒðE«oÿšõðŸþ¥í•¨ˆ†ÌÕÓ~¶Q)V€Ì̺|³„röqû¿FՖذÙÚ]¼TÐÚ°c™]í€ô½¢ö[þ7þÖí¿F*Æcy>c¿¯ûSŠáÕÅý#†Ÿx¿ø·J;;6HX‚©L°¬•ºªT¦>!ÈéþE]SU'Õ’kÅœ‹ÅÒ1ÿÒ×ý[ŽŒ=0³ÑovÝ$Y/³Æ@}êèsÄõ‡[ÀJL€…Æ0›7/k®ÌO¸²<á¤\0of4jëD†i2e¢Rö'S3’%ŠT*'þ'NRt…§ë»I#u`À›fÿŸÿÄ_Æœ5GòIÐ:ib¸Ípûáï7r<ýó¬~bÃf0wg°„cyɹ¯ïûŽ—nNººãYßË×]xùZoÎP­‹Kµ ¥…±¾‘c ­¿ì& d¬€¬Õ–DJ0.¬×X˜ª„L)${Ù”L$d‰B!ilI¥kË˪àòrIQhf¹oüfÿ¡€ØXøý®nNÌ‹›¤µ/Ê“ïŒðöæÃ½‚i18Y *Ë•ãšËó%žp­8á°˜SèœF7muã½d—ýdŸýé离ì'S²$e7MÉTÂ$Q®…²L¼*} XnF’Ò¡ô…Ýñüô¼Yòé'º*6OUãÉ뱟 †¿žsvvŠî{å#Žrüý·|°ÝæÂþ…­êüЋ~ƒ­Åߎicë‡ÛÖÝo¨¬;go½XmI¤‰òõÿ\É{)]ge)•ûU†TÁøgYÖÇÅœ“zÁï÷¿|âuÿb$ê¯+ÞµöâÏH§Ù†’@@—€85ïg§iµ1,òƹ— .Í8)œ”3r³¤²5 áŒ#jÊ^¶Cš¤Î(T¡HUB&eדhpá• ¶ýôÕw9ÆZ^úÝÏÞx3þÛ÷½mì ã?hŸ*K^Gcêˆ[ö÷ ÆÂŸpr­köùÓq»š‰·?ãû˜¨)•mÚqmsÿÏÒ)xŒ™ÇÀaØ8>¶Ó8- &}‚ )\(°Ä¥K$Sß(tQ/™ Ÿñ—s9_p²lX,u7û—¥ã# WÌÃÀE:i|ÝÌ?&¾­Ð& `“j@Á3¾\½]@|—pR@nX. GEÉåå ——‡—3fMA¥kÛ „bWeì«]Î¥»ì© ™HII–$L„"Ë„¤*ñ€ \[ü=–žÿM7qË×ìó޻߻r±Ÿ=ø8W–®ƒÏºY`SÓˆ?Ë4lœ9\·iýÆ@ Ø8üTZSÓF\ž•Þø²_d*wZCâp¬cLúÿ…¥±ë;í·±¿uý KܱN]HðeÖ½Ô“* Ö¢„3bOd‚”)J%oßÈ×ëï œs9ŸsmYò¥£ÊùüÇfMhÿ ŸâéóßiŸC×&h-E´T@Â}¾+}•7wöHºÖ_HR87ÉØIRvÒŒi’¡P.m²Å—]ÕØa]uU!]0ŠPj㛨†4VpÑùÁ7M|ßç¾ôÏ{Á;SÉËnù.·­Õüõ?ù•TØ! á²æ†®/‹Eú¸¹eÆâSIÚ®ºçâeïïAÞA¼ß™¯%„@ŸøÅŒK—\ÇßW}Ë«xÕ7¿j«ÃãO8iÔY÷S•¢¤d7:i6uÆm)Sš¦ä8ŸsXÌ9(f|ñä£EÁ#G¥cü“(ðgȾxÀ|„k¼(èT€Êo]â^óÚﵜµ€ñCÆ>U¼‹Wïþx»çØ»S¨àê¼&›äÜ´8á|ºÃt²ÃN²Kj2—¢Sv2;®È󒵃µK ƒ–©E™¥Ð ¥ 9z‘ý+ÈÙ ÜËÊpçã÷qçã÷ Ú«wƒ_@'%mJèYGÛˆÚcÛÄ OÛ¨#¡[Mo†aüž.l,.ýbLÎDÖòÌ Ï8Û>#ôÍ/ü¾ù…ßÀãˇùð¥?àBz£z»ŠÃ¶Çðî{Hj‚~Ês`t褋ÀøíñŒOO“0õL/X#ØMÝ&|—_™(”JI’0äME®Kê9-Ž9, ^çŸûecÇ…÷ÊÂý¼ƒ>ßmcñßøý´§:4†¿ûA ùï Ž¸mxÚD8[@WNjó’kùœË‹cò‹CæzáŠ^ZC"2©Ø›îsÓdŸ½lB¢R’$a’¦L„ó h#{€e(€¬Ú†6ƒ1£áP³Üo²æ¯Ëþ[ç²ÚD›rÆ\_§Y¶W‚¤¢khƒ‚Fò+Æh­¥ü‹ïè¦ý›6^ã6ôU»·ñ£_ó“ü“ïù¾çÖ|~ˆ¯?¸"{ÌK?NaLj‹·2ˆò‹«á éÕé»]É”½tÂT¥ìÊ ‰ß¼.XV9‡åœ«ù‚kå’ãeÍåyítÿ<ÒýCÙ¯xÚ-íà#¬†þžfücä{KÃ<ËaГlú¥Ä6÷wÍ í‹¹I½`ôˆÚB"0F¥.Ý4U »j‚”‚]•"HI¤Ä™ù XK­k¤”MMe4B8fvª€«ñD“aºêX$Ø0\J¶ˆß}Vãu6ˆÄ‘Ê`CñP æ4Ú&uxYsúy˜ֿB°”ÿ;Œ'Vsb5&0‹cÕDÁ3nºÀ'>ð§üÑ?ú£3]Ó&JdÆwÞúý|ý…oᣗޅ•Áó@®Ü—zºOü=ÔAû>ŒnŒÛ…$J‘J÷÷ŽLIUÂ$›0M&(!©tÃI>ãJ1㸘óèüˆ+‹‚ãšå¼v徎Ï(.ìÞmÿ=ð):q?öƉþqàZÚ”h=0á9žìš;Ãà½æïN ·¯À1þ€›*c TbÉ” S’i⬥‰d2qͼK¥0µËL3Æii„±‰«Œ#@Ø ˆöÿM7f+ˆc=¬9âÆúßÖ©Û0ïÊö#?vü¦?â†Uã@ `¡I†;E7›8æ*?ñ#™rç Ïö ùšg}ýð OŠnÝy¯~ÞëxûÿKeLûœ†6 p.J%ûµ†êPÌôÃ"-Æß‰@Išž E¦Ü{šHéfýl‡½Ì…µgʱÉI½d^ç<‘óØüˆÇ .W\=©àÈ·û*ü³ª£{æs)à~û€c£ç¬Új:#`ÔO¥u0ôŒI7û'þ÷ p•¯ßË®¼¹=J¸CÄIÂ[$(Ã4dR1ISv’Œ4ɰB¢¬é Rºf‹Æ‹Á‹–ЄE!h¬ñ5øDïô§Ñi’Áß¶…ÁcÌÆÁ‚>&MœÆÈ£Û¯¥Ó$ŒØÀè¯5ŸÀ§HÓSŒK _Êd癊/÷pçïåñü 줻”—xÆä9Üsõ#ü¯wýO¼ìÙ߯nrî”±õéÓWßÃÿc kÐ9Ãά­ÅØn>a¿ÚØöûðïDÊNÔNÇŸ¦©W\·ŸLeì'¦é„4IPB’7'Å‚«Ë#®ä3Ys0+yüÈ[ýÆ@xf±ïï;wé?æ„Ðú‚Å?¨à6Zneü ´î5ªÁXDÿ)ÓOüús@Ê”ÿŒŸÜýG'3¤RÁ³nJ¹åæ /¸é<·ÝülžînÝ»™gMoF© »2¥2š\çÌŠªóªà ?aYWh–uEÑÔ,›¬ÁhãòËý=8Ã8 Ø†b[B²fŸa4tv„±u6;²ÍØog¡î}-†´®Ä`·møÃE*‰Ñ¦]ƆÒ1‰D éâŒc± .Ñ+‘^ŸT¼ðü‹ù¡ÛþK^zóËxñù—¯½š\/xë~›w<üï84Ç­ü±þÅ'Û×Å¿‰¶lZ)¤‹IIéÔvTƹl‡½lÇ«³ 0-ç\-޹4?âÙGË’+%WK¸ê-ÿ¹Ss[@ x»þ+À%\Иӹ(t@«@0úto|Ô{Á»Éͱ+o%~‰pξ”øÕYC–J¦é‚4II¤òâ¿âÙÓ›¨¼Ö‘Š “t‡=Û`µ!O&X Ð‚L´…̸’Ì9 hI@ „¨êÁ}X¢}¥VZÚµ¶çuÛŒý.ÖüÞÏY˜>PƒuÍŸC‰îXFk„”=c"¬zGhëªæ†:c"ëŸKcxhñ¿ùÙ_D"˜Ê)ç²}^úŒ¯ç|vÁâž79ŸxüCäºDK·×vsí½é²ºqÇý$œ'Ä««wë.Z"˜øî¾JJ”T(‰píï‚Ò”6næÏ9©—|i~Ì¢¬¸vRqe^;Æ_FÌ€cþÏëOà˜ÿ)¡ÓŠ‚ úD\$àSœ;$úWÅ›ùë»»Ç[1󃓽 ` ³¥!ÉJ¦jÎùl®ÊH“„T Î')©ÌØQdû`\ê¥öX­±>ïÜRë†Ä(jiA;·ŸÆ¶….ââC@ƒ¡¡»A«À0&)œÆ`1.Ql…MçŠ÷´m‡×%°]pš½Ò&~FwŒgÊc@v Тë?æb4X–&gYä\¾xÅñƒUXa1±zÛ;×­)–²)á*èwqZ‹R…$‘Žù³,!”DÉTJê‹ÜÓ0¯\öë¬Îyô䘣²àʼæò¬†“ºËö‹mÞ–Õ»ý÷óV§à—5Ž×âļ ĺÿÆ™?ÐS“÷v̇(ì‚©Ø;Uj­-³eÍ$…'’‚,9&S ÓÌLT» ;ja ©È°ÊR¨Œýl€Ãb†µ†EcØI‚†‚/…ÆhÖÕj¯!•²¸c0p&5!–­•<­S%mÁÏ$cTZ†‘T”l9ö±ktÇrA£ J8fs ÓÅClAûÝZ«"Ǧ IDAT{’»ÎÕ.DÝ@GµgFǹ‰©·%)Èè8+•ÎÊ z&HRŸÑ§¤".ÁgOM@¹È“EUp˜ŸpRç<>;á°X2+jfóæ³úæô‡ú„ù,®ì×SF§•[Ú†ÆÁð·¥ë2”9Us/N_Fü& -gÂ[ÎÁÒ ¦4%,™R-cf*Ã%ò/z%k¨}\—±Þäd]É0+ ‘.Cc©­³Q+á¾; o7ŒØ Áݱ¾-F>ëôС§¡ÁŽzÂïá·ÛÛgÓþëÖÇçŽg“¹8DV ¯/ìÐá%ˆ%Œa©ÂØP¹Òm8„Yûgµ.Ò1Õ‹†|2aØ7dþú”ôÅg¼%_Ÿå§$©r¶ðD*v’ ;©ëÔœ X4%ÇÅŒcÏüù‚£¢äxÞppTÁûƒá/P\ú+Üèw›_Á%þÌýƒõ¿ 3i<ŽÓٚΠ2Z ¿p†é7,—xœoOÿ”¿§ÉÈà ̺ÿÆ$–Ʀ©›£¤À?I"¤{ÐÁ åõ7ç±²(¡\}9•ÖîE´#c{ËøöüÅbÜh¿ 0ŒBücº1f\Ǽ›ö_·~uŒ¶eæ8‡buýؾã×<&!çCCãn¨mŸu|Sc0ˆ= Æÿ¬¼Ç»ðŒOÄ‘‘ZáRqû@Çik°¢SòÜs®ô»’Ñ9œË/I”+S'$©Tì&¦IJ&!˜7%‡ÅŒ“:çÒbÆÁrÁaáêû_>(Ó—ÖEý …%úÍv¯˜Ïðe~×ߥ¥_Æþÿ€½a œIì¹ : Ñßq¢÷Ö|{ú @¬Ìþñw‰Ÿ‹A"SW ášXJ!²Ä%\´]U”BX Ö´ `0Òv: i-5!6ÜŽ@L1ô“e¶—ÖÑi±­DáÖ8曩7³Ëؘ¶¥Të$€®‹CBH첌HC¤Ö­‹‘‘ŠÚXÙ†Q}-Ð0ikݤâ1i"¥·úK”OãM„t¢¿R(é’|÷Ó)“$%“©VsTÌ™×ÏN8*––•cþ£ ޵ÓùKã|ýR¬¢tHÀ»Ì?¾„ÛjAgé¶.ü±Ž¶€á÷Âßq¢&T<È·$?H*öV`8þ*q7D@­­ïd1 %ìÈÄk ¡,Îãй³…Fk_ˆÁÅŒ%KœD`„ ±Q¸—Æ(ƒMÒÁY¤„³ÐiŒ|cÏÖ'ÍjÚ˜Îç>2ÖXEDá瀕{%ú{öVúï=ŽC{½D!¥DkÝ"!D/¨Ç‰µ†DªVrÑøxáÄé~àªg©wùIÅT¥ì¤2™ù{d8Èg• sËœ«EIYhŽOªëŸë(€~äåSÂIÊ÷è÷pßÉü'C{pÿÅÀ™í)OY¿î‹ßÁX€2Àð¹¦äÙ+hl_ ðâV»W(´¬ýl& Z¸—MÊð¸œo!ÁU\q°F»RLÆ`…¥¶†D cÑÂÇìã\Z†.N¼J—¶‰ÖIñ¥}%€á©"íïÃ0Ê1Š›1Ã6c×5PáÎjoÃŒK}é@ÐN‡í lô{tä•E°+ Óœc»ƒéwZtªJHv SaêóúÃÌŸÉ„i2õ¢¿¤ÆpŸ°¨KžXÌ8© ŽŠŠeÑpù°f~R9ƒ_aÝÌ"ýÆ$€@ï78ÂÍø1 £þâ™ÿÌâ?œCS †Ò€"€ŠÇx©¸ƒ]yëŠ0´ Dë ;ªKÏtê­ëO Ò…iFæÐTÆ€p3XƒìòõÂÕÄ7lœëw˜÷^ÁõŒ;”žN`›­ãu›Î3t  6¶ÕÁ-øº bôºÆÎ»[ÃKû–C­ h;”Ç[·~źë$A)•õ`#\Éî8íYHÁDùJ>Jyh®.¥p¥è¦*a'™’*I*rSs\,˜×׿3Ž«’üdV6\9©™/j×Õgî]~õƒÓ‡›·pŸàfú1 ÿÆàÌ´- ÕÆÀìñß± Àâ¢-r—¾ÂŸKÿ£Õ§%â·¦{š¬v6 C•‡žÁ& …DZ‰P‘IËZ¬t#%¼‡ÀløÛÄ« =,Xa)Â÷5õt†Ý±äqšJ3S̤c¢}†Û­?zžm"†×>ˆ*sך|õ:Ç@ Œi,I+Ø0†ž… cúáõt¶þßH´p¼7UÒ‡J[› É”ì%óHÏü.ÒO1‘ I’¸º~É”Ý4s >¦á¤\²ÐOÌgTGeAU5\:©˜Í¢(¿ÂxK™èûú‡R@i|ÂþÃ78†·8 p—×Åûõþ¯¬³ IJ™¤ósªp‰¯¶ÏáÉKÚ=‡`EßýŸ•¶)HKi5Ê~´µmŸué;Õ$B +×$ŒEës µÑîe²Æ14Î ˜!Aøo`ˆ/̽ØÝº³‚ô™dÓºaVZ §Q˜•7m»>ôÏÙe$2ºŒÇ¼î:h„±æW`’-ûÓ.cPˆ!…@ ÁØ×m ôösó¸“ C|‡‹çW­…?QΧŸ ïçÒ‰ýB‘&®¬×DMH•óÔ¦q•­kÇüÇeÁ¬,)ˆ«'5‡'ó×øY„U´Ú~Oÿ3\çíð“ûËÚØè²¯ ®âÙ?–‚;œ.W@r¯ù<ß•þ0Jd+̯èÍþ-YH… o,“Ô%ûëÐÔZ MƒqƒÎÈd­+9nšÖJœûD"ƒEzsDí_åã„pêD¸ƒ†¾Û°Ï¤íW>Û‚Â:‹QXcÌ<”:âmO;çiÛ Õ£±ë‹…–ùã´ÝuÇ‘í‘:ïFx1ºiÏ^ÊqOH—Æ+Z×BJÉ$q±&Ryý^H””LRWÄ#“ЉL™¨I;óÇÌÍÏü³²$¯kæ5OÌWØ£²[W'PÂtK‡æa²ÿ”>ƒW~mh®gú áä)•†[b†ƒðu($‚šÃÚðõÙ·®(È¡.¸÷ÄTkë@ÀXårÿ¥á­±¢³Þ6Æ1¸‚Fkg´ Ú¸®¬FšˆEY7óãO-…¯-(œøëí4ë!¾!7 ÆÎ½ívÛn»‰Bé,è4^C+­ ¯5Vs̈*1ªX…hÞ†¾„°:Æ®¦ƒE°â7øÙI:Ý_ Ïü^äwm礓”"•)‰ì&RéÊÒ 6 ³rÉa¾àh¹àjUPV‹ºæxÞp鸙¯é"ýb&×tz ô%€ß×?<Ž›ýsóU HÁÿ¢m…õt£Œ€‚.((„O¢¥“ ®ò ß ^ÎŽ¸µõ´Q#€§V[PÖ‡’ºüo%%•q¦Bi¬óçZw_¤”º¡±%]!Ñ®‘¥eŽ˜ ÝËìßÖÄKcé%cƒ@`ˆðÛº™î©‰'KñL.·Šöu³wjomg3Ѧ‹æ3t/ý&(üݳ;ÐWÖQl÷1úÖƒ‚ 3ñ}Ry¯’ Q ‰/FëÔIJBª$»É„I’2õáåy]r\-9.–\+V%eUqRUÏŽç†ú¤qÖëÂD²é‡ë„)2üðÁæ˜ñnú xb ,c—ß“šù]/Äßc0—gü±ƒ$`Úm>ÕÜË÷fÁ [D±…«6€˜jã¬-V9Fu/©kH!)½^Hì’Úh„±Æ5ˆAWöDƒ%ëU‰&\‰—‚®_t,ÁøŒ»ÞK0ØnËO¿~Ýv€o;ü}l;mº1ã–Jt³½±ã×_s¸QaéݬÛP‡FFgÔuûcâp>ýF`<HJº-¤tg>²t¢?Ûgì%×¾׫±š£jɬXr-_rRÌËŠ¢n¸2o¸|ÒP×.ȧ0¿»±ãì*,í|Òþ2®Òo‰“JÜQBàOH´ ÀpÀàFH‚- ¨Íi´„®pHAÓ$Ü–~“3函/Æð=±,Î’«,µÑÔMã^V,•Ѹ !x•@»ÌSëò\쀠Ћ¯:äÛY§$H÷ò„ˆ¸}Èôc@° ­†u‹ÙÛœ+ƒM¿¿‡=dÖv xvu"‰v± BAºˆªÝ/ cûž‰N]íŒß©*îÉL4)I}@Y–(”’¤(‰"‘)Så*üdIBˆ]Ö%GåœeYðÄrAÞ”UÍ¢®9š7Ìç†:tò­ü…ú7+“b‘?Ü‚ÿ§ùEàËtÕ}BRˆø³ÑrŒñŸ]¯ ¦1ž—<”=ÊgùõröäsúoãÆÀ@¶‹£°Ú"“ ^zÝ^º™ªÒ Æè6‘£6šLJd\ä˜íüÿà ŒÖºâ˜x»"qn€¥ßC t7W|ª¹‡ïJ~%².†pó·gvC„é@ Æ¢°h­©Ñ`@* .÷¼ñ‘íá}ì¸À‰‡Öº,BåkhëtÑßšÜK‰X¯ĸ%cŒ·ÐµDœ £ÌóÒ6ž€MÇ~”ocÒ†ßF÷!>üéŒN}‚F îwÇä! Aú¬D—²c€_j¸ _)08â±ÄŒ¨Õµ=—Æ× °Ò©×ä é4{J00¦R¶j€›õ…ì“éštZœŠ§”"UЉHØI3éÛÏ‹Ä×þÓ,›’R×—KæEμ*)êŠã²f^6Ïj./4¶­æCßÕëÿén`e]$ þïæoã*ý„&%ân?1Ä*@,GÄË3Ó”b ïrìJ‚†å*ñ^Ìõ|71Î+gÔ2áR7Ãˤ­q•ÇŒïñŽvV8Ýq"•Ó}Á‰TJm(¡1¦•ð³|*]I(wÞ‡,½>k\yèBFà‰ƒD”ˆAb)aì¦>™Ïi‡ßãíÆ$˜Ùö±t3ÿiw‡Â&0Ãö¼T`q÷\¬A m¸¯¾kdIÂT¥¤Hö³ R&ì'™³á¾2 ESq\ææy]qRW•‹ªá‰YÍÁ±¯ætþÚ¿Úᆅ@ø@±d q“Ü¿ªÿ%ð^ºÿ0ûÇ6€XýŸ4ó‡á^ '¯±å°’p'þwÏ1å.ý ¾=y ©Ø[ °zv‡¢êÂU¾ÑÖb­«Ô/töcA(œ$•ÂY©¥ð§wÖak­ƒÛ -xSzaVbKu€çø¦†cŠèc"ßÙ˜¤0&9†Û´Mü@â[hÍx±ŒáC\‡»a¼cLÖ1ze;þ¦uc` ü˜Ç$¦6êL:M(ü’â x>Ò/õ3þ~š‘ Å4IØË¦®Ñ¬”XáBÍ+«)tÍ¢,˜5³¢ h*–MÃIQ²X6\7ÌNj§ë‡Î½­@݃Xˆ%ƒPðã²þ,Ùߢ ïãûãn¿ÁêO´¼!LÓ“5®cÕ0ãoJ{ÒÁ’×òÊ쇶²´Gï@ ¶Î&€q©ªBºÈr! 4–ZB¦ºsù92ôs›$ ­-™—ëÊ@cEg˱®ó«Kut@€÷'¿>žYÛw#bÜʧƒ$ƒÓh›í6Ãp}x³ *ýœs¦qƤ„h½ uý'óXø}¬œw |=pó`pÌ/­+p­¸¥óåOÓ„©LI…boâ‚zö“ )|J 0 uÓ0« ‹œ¼,™7ó¢b^VäK͵¹f¶¨Ý‹Vš(ßß—ø} À°3²j»ä÷õßÄ1ÿŒ.È'T÷ î¿XˆÝ~7TÿÃ}²4fˆ—±Kй s¨.sGöж¦T¬4ŒžÕëW~ûÚ:±P!¨kƒU ´5i‘FÐX—“–I‰õªX*$Ö ï (+ÈTBië+ ç'ï€À‰Í”wGÙṈÑÌï<’h U꺙ìzi“ˆƒAeMûÇ(fìál_…–ã#ïkØ'þ®Fì&ÒÏÒíÌBiq¡¼!|·ÂUŒ’J!„d7MØK'L„b/&;ÞÊ/|:yc5…Ö,Ê‚“¦`^”MMÞÔ”u£9XÔ<>o(ó¦?ó&»…5ÞjÙ»`'1þ›úgqE>,ý*?a¶Û~º£ Ïø¤_š1Eóe»ƒeø=¨ .RsÆýÜj^À-ém+G# ¤²—Dž —ÿ¯„ i,‰ò"º±h«ÑƽxuÉA‰­ÐI™Hÿr ßŒÄøòϮӮ”N¿ÔÖúœ…9è²Â >ŠMÚ ñ^Í€P™0SÚÖo¨ŽfÎÁÏ®O%ÍÞñg¸-t pVН%R:õCtR–µ®•œã?A¦”—ª|wž$!U)¥ØÍ¦¤I®JI”sJkÁJݰ¬ æMɼ(¨´fV•—E­9<©Y憪ð.¾Êô'¥ ®/Õ –à蛫_>IWÓ?, :ý?xÆ~ÝP)àFÀPJ}7 û;T†w‰C÷šÏðò;ØSýÎBcß| {‰lGÑK#º6¯&TF£¤¯'ç¥c-VØÖ& "±?‘«-IârÈ´÷(é@CHïQ°à»úq!M%´ v !:Æ`üåá·àîAŠh3Ùâe=`ÈÓö´mb&Ž£î¶¡1PX»m‡;~R:U Ô}B´±åP‰{VÉŽRéf}%qoO¥NçW>°G$Ψ‹³ 5VSÔ5G•³ðçuż,9,+ʦa–7Ìçš¼4,JíDKmW•ر99ÌþqÀÆpwõ>.ñoý/Å`‹ùq‰¯ug¹¡$<ü×Oú /¹ùÇa½* D¦þ£€]¿Íy¿¼ìó³ûÿS±ꉣ·g/í ]J¦ö2…œ¦‰bš*vUÂ4IÙ™dì¤)»2%õ]^ºaçM0†ºÑ4Âõ(µFµïHÛX'¥5ÆD_ëà•ïA•D†Ãà"‰}é~%ÒÏ|+O}Õ=P¨ozpxºIPktmœ×&²'ò¤x„ìT­$q¤ÄI»IÇø»©/Ì©$;É„DÉ6ÐÇ—–B×äUÅÒTÌŠŠº©)Lͬl¨ê†ƒEÍ2·Ì ߨ3÷†·4ú´ŸŒmô[€D8cÒ~ˆ·éŸÁéüàúûÅË8Ñ'NöÙFàÉððSÓàÉÑœ_œÿ?»ÿ˜Š½[šn YË^ ÂÌ[ŠTb 2‚&±TÚR¥†ó8p®ªšf:!3 ;iÊD¥­s"%JjÒDa%·‚©J©lÒ30Êî-v``q%§œ`dÒ—*‹y#¼èHé@Á/a$”R»÷bi„~é@|ª±_1`v뎠Ò]Ýÿ` Äø8ékñûý:æsˆ`'Q(¡R°ã'*Ù5U.ÛOú®¼Žñ5Ú4,›Š¼®XT%óº¢i4'UMÑyÃ|¡Yžç‚ØÅ·3æÆj®é/ðvýK<…3ø“¥ cz>tž=XO·á™•àsüâüMüýs?¿öl!4ï2µ¡”’ic)µA(¬k'=M]ìwi-ûIJ¥vÇð™òˆ½øm¥e'sÃLjצ¶¸Ýe©W]¨±ôÎD:#Ò" -(º›‡R.a7€ A(å¼ t–s ýÐS,ÄËá6âõg‹!Ó¯_¿ÒôCö" >}oGI¤+;UNMJTÂ4M˜ˆ”4AHå;öRÙµ:iLC¡5ÖhæMIefE…Ñ5 ]³(Šº!/5×–šEe0¥¯Õߨö9^¼ºÙÿÿkïlcm¹Î»þ[kfö>ç;6±â”b§%8n›ôE‰Q >¦  ¢_xU+>ð­|@J‹P@ˆ´NÅ•Š*„H릢¤ I-ì´y³9Ní8~»wŸ½÷ÌzáÃZÏÌ3kÏœÛ÷úÜ{Ï#Ý;ûÌÌž½gözþÏÿyYÏJJSÿˆ§e^à!ÿï€g¢ý¨­Ìñ—>S=þ¯:p¼Ö @‡IJ Ði Llð»ü›Ëÿ’¿ë?œü¤¾î:³Y©Ãj­›`YYEÏDŸ‚ƒu úĺjWÑ- Ÿ:¿.êšeô½çi`i ‡ÛÛ¤r•.¨Fï9’çs@RZTËì²¾I…M¯kkkP+ (ì)åRST–2/Ç`ò܇è‡UwÌ$0LI¯üÆ `&bÇçtŒýâJçÃPõª/Ó å'Š|M)¿–š} Yùkö*‹±‰ܶ\R›Še¶ø•¶øä†#1ÐÅ€sŽëè¢gÝn9tWº–®s\îØl<—· •›ŸÕœéóüŠúkå‡ /ûxÐø:¥Ÿë¥Â_Ź.À\ª¢d0D„ ¤˜ÁÓü&¬îä/|hò“¦bsâä.+Ù%8¨#Ûhm`å=·,x˪¦­=û±¡óžº²,ªºo0QÛÔjü–å"M¡ ‘uÛõîAÄÑ`qAåá ´>¨q5Lauy‚Rš¨4ÜÓÀÌKȇÆ.DLöO×mÁŒ¤JwÇU Ȭ Æ~E\íbtÄ1+Ð<£”(?d«®ö/*›&kZªI>ÿ¾­zÅ_Øše•rûu•\³ý\¾klES¥òß=#Ù€Üs1Ð)Å߸ŽU×rèZZØvƒÕ¿²ñ<Ÿ•¿Wtmíb—º©‡zjÀ–U¸Ìƒþ7HKz2Lé=ÌçiËŸëS`W®U @»:­!Û9t¬¹~•;7oæ{eçª:Ð…ãAØæIË6rÙy¬K±:[à¶©XTž=ïiÛŽƒ½%t°_/XÔ©vÜJÆ ßAm-ûÙyY„Š%5ÑÄTaÖI—„¯’{èCb!¦éÇÉFô§§Ë‡;HûÌ¢ Ã"}z<‹Q4» ƒÕ•ǽ0–6†Ñâ—SÒîFfEú±ËmÚ`"è—¿\•ff «ðÃ"[{kM^N;Ûoûº¥n¨±½âïUCÒÊäÖ亘g]𬻖ÃÎõt_‚|[Xm<‡mL”¿SÊ*SÔÏ-«ð<ÝÃÀÿb öBï§,¿¼ÿš)|)×t, ŒgiÊ*Ö ³áþîWø›À½ˆ9UŠ¿ qDÿ!ÔJÙË!Çj,<­,*OÛ8.T5>Fê*-(ڸ˶î׈‹]Û(¬jÛ+²é˦&zf`€èC?UÙÅ”iX`únD–˜Öù³CSK‘O\` ZêÞfúu)­”*+E—ë´!Œu©˜J˜qƒfù~rzT>}á]ÿÞ˜Š[–9¢Yü*Ï ¨MÕ+þ—Œ§Ë}!.wÛ‘âwïéþjãñ]`½ ¬#c净NZ¡ûyÙùžúCÀÅ–Ux‹îARÿ!CeŸžáÃX/]€Òï¿& p5`êÊ‚yìòp4è&JðñîWøYyÇòÃÕp`Ín& o¥–½‚|åm•AÀFVÛ–u$4†"ë¹µñ4UÅž¬ýå‚Ö¦%È>¥ž ¦ƒ4LŸsaÙô+ÙÔaÙÔ8Òš‡ë. †ÊxĶ»\°A‚D! Íî HÓ_±ïüà%f2}¾–Å`Î[Ûò5ˆ…ÏåÓÀ¾ISr1MÝ÷á_šÔ³²iX&Åj* Ž˜ëàY·-‘È:tn;:×±ò-]—ªüZXoSNÿÐGBXù˜óúÅðA²üei¯ÔúkÊcFP²€k¯W°¼Á9—À‘\ÊT-ø±ö_ð¡Xñν¿<ºšé‡­†” °ÃBαké™@î²õ­êŒuÜÚxªªÂ“ÚOÞº\à­ÇfV|HdìàdÀ2ƒ àUSåøh%µ—!ÝV:_7ÃØS >Ã䕯C`£xÂØ_éƒHL"ûÆÇfñ¦â¹wƒ4êÜË>û0;ϲ¬*Tì/š´Ð[°Ö•¤óóÉ%Å]p†d(·ÞÑyÏÖu\i;‚wÙâ;VÞã]èé¾w‘m—@ätÊïâœòGbåÚÿi ¿²¤Wøè_b*8~ÍåZ€þ:TÉëò!ÖÜß}˜¿m<ߟ™@?ßz¬üý§ñ­ŠÈ<Îz X‘«#µ‚½&­óKÅ-uƒoRn{ô?´‘uð1² ÙÏO7”Êú—RÍŽqĸå0¼”}þÏ’ªü"ƒå× 0f×\É’k,‹„ReL’!T>ˆ0ýP‡ï{÷aî‹/ó®ýŸIgOL˜yÄSAÁ¨|ã ²n­ò×´Á²² |Š„&‚ëXÖlZ82÷˜¯BjCݘ S™>‹r€¯ê‹Ò G±±,K.åÕ‘=[ÓõÖYzø6}àoë}Ï,šy²~*‘GXÙ´ŒÀÂÔ*M3ÌÁOmµ³ãc¨+;²ð@?}W®ïIÏ3÷tƇÀa'yü–ΧÂç‡Þ±éRÇ6DÂ6ŒÆÊ¢›tQ9žq¬ü±?+Ð…–m|‰w—H>ÿ•üÎ5c ›{H @Æz™x]ä,–Ÿ\.ºËg/‹ð†ŸG@¥š‚W(½¯íÀÖ†uÆ@ÐúDQ­µ,|Š8<¸43Í˾µ´U… –Æ%F`04õØ19ˆ˜Žf·£I= $waQ™l-ѧU}N±5¶ø9ûÉHi¬5¦Êk,‚tº¯+ôÊÖݵ1}úÎ*%Çš±U—ëBVxÃT#’>n}¦øÉ·÷¶ÛŽmôtÞqØ9:×á ¶ðÞsè’«d;X‡€wiúÕ¶ä§ÏP÷?¥ü‘[VáY.º_d¨ê»nåZ»åßåèh‹cz’„L wGyš‡øÏ/wü­[ÿirÑÉA ×H Ö?ù¡±­eûXè"-žÐ¤öÓ›ØtžuU±_Y\ðÔ¶¢#-<ÑÔ5.7©¬¥éªÔ€A隺Ϫ³Ã 7òk‰?mkCCè݇Z)±Ä \nBr”TÖ¦cQò>D#Ÿ—$}OKeÅ15øHA¾ñò‘ñò,Ęƒ›QxLˆv­ïðÞ³j[¶¹šï²w B`ã"!Ú6ÍìÃ'—‡0T’Zù#©ú/ļ|7e]sº.lX…ç¸èþ=iý¾Cè‹Oe¢Ï!»{¤×”ï/×gâõ5‘뛈|…KüâåoóÏný'XsT´jBf³ÁÀR|ðš ìÛ#Xæ•c;OÎXöª,¼O”YÀÇÚ&ëklîjÓŸf†"!Òào¤@FÛeöÙM=0Šy1$’ºFbïŸk}j¬¡Q¥¼†\C?mWü6á6›Â)ŽS%ÄT˜“-} C×±õž­syòN¤ó)&°q 0\n«å]ìÛºâwùËê–kpD𯋃åïâØß—·tDº°âÿ-ôÿ xŽÁP]÷òzÀ\LÆ19ÔVk­æÏ5ð¿xùøGþ1·×ß¿s`ç«]zУuîܘ2StVØ@m.ÒÕ!5 °4°võÉßïû•Íî‚L"2ÜÒ4½õmC°Æâ\èýgÍŒ5½ej€Ëuzjd, ¼Ÿ|mLÖ¥1¹Á-ºBŒ9¸˜dOÎR°1 Jœ¤sž6:¶] æçhc`ëkïS%fVú­KWq!P{p~lõ{VRÔ5”ÊßKì²ÒëTßXÒ˜‹qËSî¸þð]ÒØÙÛÆ-¿½ýï|…:ø”Q~ÓzÝÔã$~¯k6ହsŒ@—-4¬Rÿjà{|tóÏù`÷7xï…¿Ž­ȼÞBú ÁœÔn€QáÍ H×Ëçäÿ uŠÚwÙ´ Œ…Mçi¬¡ªò:uÖæ ¢aA•¨I¹ö uþ¹2(tÆõŠÚ+w^î¸1©—!¤Ô^¥€q¶ˆtÈM.SF1Ù¿ÉiÇ ´oÛ9jk9ì\ Òä™–ëH!̈s.6Ù¿î$âRãV`PüÖÒ2Hÿ^3³·“{³œÄò{u<èpl |¬ý5RšO÷í—×SÕ}º›¯Ad gJ^o˜{(sˆ©}û­Ú'àú÷>äïç¡Ë__ýÓ[ÿ.•¹ý ± †qÄ-K_@.fF2ã6¬•eÜÇbmnj¡À¤‹o›¦1–6DpMž8#€¹fßZº¼Òqz ©pÆg`HkÚŒ"ãÐÊŠHª·Ìô3nÐd`Ðk]ZI© ®w;ZÒ2ë›>ÑÉþü]}È“…BÌ,"=Û­RÊø œaü“^ùËàŸX=ÙG‚}SÊŸn:ÐqȳÝS<èø#†Ž=’ÚóÅvà$ÔÿLÂë s¢€ž@¤ÝyèUñOzü>¿tù«üÜþϯÞ\ßCc÷¬©ûpvc6 PÊÈúO€À¾µ)&`­n4ÌtÊ>‚lcªR[Kô)æC¤êÌ÷5 5ÕNØÂš!'m²£RÝ3²æò}ô¯Á¢ž<1D:Õ³ÀçÕ€:ùž1È“ÔÜäòÚ( #AUÚ²›4''ŒìËo¸Sﯭ>L¨^ @GǾºý}>ÿ+ðüÉ2Wšvzµšà£i¿lϬœ8ê!iå×ÃD¾e`Ò°YÀ-Yÿ2¬þï¹ð+Ãmlÿ^Å„ ÈD!˜À\ZPË~Ö|½Ê®fKQî«§øÎ5ôQ~ÑÑrÈ3Ýñßü¾ÍÑ× :§&öÌ•÷žYJÎL=8¡ýò¯œ@$Aã2÷ZŒ£ÄVÀøÈú9î«ßÏ]‹{Ù·ß· ñÖ4T¦>¾ÞYF@@r 4è™ÀIR‰a`d&H…Œ®®¯ä³ý*³VIŠqTkî’Iû#ŽÁ\ºâ²ÒÚY¿99*y¬Ñ÷»Ê¿•ýbõËÆGY}ˆøˆ±ã0<ϧÚOñ4ÿƒÔ¥72”õŠå—­¬ßÔ¶dSA¿3iùEÎ\-J¶¾ÁEw™?åžâ§÷~œÛ뷲Ǜ€ý4šß‹ež‚“¸éý»ûy´º1Lé€ìåiæK€]ÕÒ˜áœfæ«õþÉÒRñK†!nN0ôl§U¾¿=Îò+åŸTü’î;åëËÇèj“Ï&x"-ßî¾–}ßb`Š7œU8Š ”ǤfÀçm }QÚ–d›—HáZÚ¿â)¾Ç¿Þ<Á«÷ñg—ï₽“ư¬önD:šVºŒÀæ)¼š ˆK ãÂJ7˜e©Æh¬)š 4ì2+·¦íSçÊ~}|§u˜±½›2åZhq]ìÁN+¿–ß_*ú åÝ1~>ìvñ•?;Ò:q-/ò±Ío°é›wÈòÜRM,å½:Ò¯‹{$Ùu?¯Ë/rVàjˆüRÈqx’‡üKpø ~vñ>ÞÚܽ‚;€¬Y¨2æ@Ѭ!7·`(–ŠÁæ@@DÀà(WFÐÅ@cìŽr×çOÞÛ)F1w ½ÿ(k?¥üØZôÓÊ”ß Ý?åðÍKdĎǶŸã3ñãÀó$Cq]ùëWCÎ:”?ް}L€lCf@,¾Î×Êß5i\žçcí¼»}7?¹÷çxCõ6.Ø[ q‰55`sÇ!©ý˜Hu o2²„¾© `0W#ÓA8 ¦X(fBŸ#ÇdéVèXƒ~ŸXùò;LÉ”âÃp¯ZßûgrZª?¥øåHé4D6žíËs÷¿À#’ˆ¾öõa˜á§ý|É,InÿL—÷žFÎ:\ Ñ?šP· ðÇ<ÊÝ<Éì{øÁ½á6{ ·“ÚÜ ¨°*ÊŠ¬Ùa%ôq‚JÍ&ÌRÛDŽƒR 53`âõIþžÚ”•ï?{b¨·.Ž—èú”ÅßQz&rùSTÎ)Êþrx‘n$õêë&ϼÉåz€©ŽˆX~ý·ÔÈkí£Á8; °†4¹žâÒáÿå¾ú/ålÁí4æB”ú ÑlÃÑ‚$Öü¤\¾€ÁZ«T`§xè¤î¾éãä¤Vü$R*}éßKšoÊ¿?Ò·/•^u”>~is%ÂßàØ„5l>Å£<ÀСWWðéˆ~YÕ'L@—õе×x8åϼ\/ 2å(èC»ú=:hŠ…,cpé€'¸èž÷üLõ~Þ±¼—}ûF³GˆzßHVRZ*= ¼ç ˜]0Pä„<¼öû~ùéo]AXÊQ °sîÉO=RlÜõëEáEVô²Ò+K¿“ÆËûNØÓ{"›pÈg6ŸâQ&á²Ðùr^†K—ïÂî9MjïºR~¸þ`Jæb:3 "mà¼ÏòùuTûÒ zÐ?‡wq_ý¹kq û'Ø3{H“’4ÂÇ` š• C8ˆ3€y@X›0Ô4fÙ·vT>+¢« K€8 8LÑw‘¹¨}ÍP½·*(}ÿÙs>=3ô¾´ô°kíKþ—ÒM¼ÂgןäK|’Ü•š&½_`˜®[¶êšÊéÏÀ 8¼ਇ/Ö~˜â66eñlÅ*È\‚Š1ʧî/Ý“àÞÆ}õOñ¶Å;hÌm\°P …(⨠)+ fvp*wXçÝðãêÃ&¤Ï0 ë¦N.䨠ëó5•…†±¢÷Çòñc­¼äíû/<ñÓΑ뎀‡üöæ“|‰O yĚπÐ}Wœ{L)þ¸îäz€R´’ke×J^ºS 0…)ÐØ/sÑ}Üù€ý)îYþ·Uw²4K ûêÚ|=޶}ìÀš ÞsàMÀй¨Š,ó·/k‚Ö&+Ú1ÕˆS29•¶( ,ëù{«žÏÕŠEÔ^‹îÀ'¡öÅû‰4À:|—ÿ¸ùu6< ̥RÃàÏo+ûQ.@÷œ‹ô_÷Ê7À<ˆ;05ŸLŸ¯] ZdM²+.…‹\Z?ÌÝüuï}ÜQÝ;]`Ø#Nέ™Íd_ÏÒþ` @pÄTæB¦#PK¯©¾Vô¹…6´reåW£ôuÀã›G¸> ü? Ì¥ô„Äb«îx’îßPÊ7hÑ_þ._—ñý£‹òë^0ôÐ׊À–'ù4Ý<¼•V?É=Ë÷²°o–,M…y¶yŽ-À„´B®Bµ¨=Ep°­Ø"~ü=&ߣ[jÏYwuýHè§+®Ãs<°ù$Oó?"ú0€©ÀŒzab[úøLlOÿí¯#¹‘`*TTÒøò\«þIj°ìâ*‘ÿZýkòû…j¾ÄCþáð×ã¾ú}¼cïÏSáñ¤NÒ”ä¨o¥•pce q ¯µÈGVÊ)¾Ãé­úXÒ“E´¸pÈ7»Ïó ÿ0ðÕ|–¦ó0Xõ2º¯ýy9·¤ûò/2Oý§î↠^™b’Sþ=.º/•_Þˇšç–曆ÖȪ—–2µç"Ô¦x3î&ÒƒýuôßúÜRiK >u½RŽ÷Ù‹zâ¼M Äú&gÅ…C¾Ò~‘KáóÀÿa<Ýö\®’܈pÔ°œ èèÌA¥¶0ø“bík†þƒRG Ã\² õžços÷0t5ð~î«ßß\ü·Ù7³UÄ^\kt9ÝXG4*RÎ|J¦üóã¢îs2uêΜä‰ýcH®UGÄË*|‹¯uó;ñ3À×ϹŸ³æ¥ PÎÕ×î›fqQm5å¿¡ƒ|ÇÉgMô€ Àÿæ¢û=p5p7wónÞßÜÃ]‹¤1ûx"!Z5Ç8m‹æ#CŒ ø4k¦­¸0‚“(ýI†þÔTBÙ/+5û詌gciãŠ'Ú?àRxœÔoï)ùv'øÄs¹ r³ÀT@§,Òµ°ëʹb­¥¡°Ø‚0€º8·|Ï£<Éòdtp7÷ò.~¬ù!ÞÒ¼¥½¨s÷‘¬ØÇ5˜Q~½-e*z2%åüà Œy’”§\cÒÚ]—ÃS<ë¾Éo…ÇÙðð ã”›îª+ºì¼S2½Æ^,Î-ýúr¾“ün Ë/r³À”—:”A£kÊ2ä2`‹÷ÈëPü›+Nú:_æI¾Ü}: Ü ÜÍòü­zwTwò}Í;‹ï'ï;tL‹ù•>ÿÜ]—Çæ¤ËßÛÇ\™Ù€Á‡È³î«¼¾ËÂ7yž'Ç™VÌ)Š^vÓ€2+£kôç@Óû’úßTTNn6˜û±§Ô¢ô lñOõ €ó¶f` š9hÖÐçÊÖ’¦*ÿ1_âs|ɾʗ~ð&îåÏðFsÀÝõÛ¹`/`Ì-Üfßž ¡,it=Ý{RòŠO×O­®ÈsÝ—‰8ž÷ßã»áã6<|“”žåÒÊ' *¯Ëœ»Vî)0uné×ëëkW vÛÞâ—r³ÀQ27déâ =Ø´5ŸòeåxR®] ?_ƒP 0Úêø_æ1ˆ‘ßít ²f!?¬þ¶oá.nã€x”gIK^éë’R½¸×) Z*Y™_? ”,@Ÿ;•Û× ”u?·ö3r³ÀÖÇôVt]G EÇ JÆ  Ð:û Ï—c°«Ìfb«ÿ}N½·êÏyšÏóôäýj¶£·'¡ÐS1ù[þéhU·^wÿÞï½{Ï9÷{¾çÜÓÂ{Ï?fÑÄCöÞói ocŽì7TBÍßÌëÜ{¬i ¥F¨`áoÎÔ<\„Ê5¿S"(L.zv&Ýg>}Øsu»>qšŒZ^déß4ä{[ê‘-µ—ÎY/Tp-pû4 ˜~ò´Þ ¥ë^ÜÊÒÇó?r À{‰³gÝAãÝdüá“ó¹¶îÛtÔ©’êÌÿXüÙ‚ÿPâĤ€0¼%a¡ðÃB׺3êÓ¯}.¿ñþÆâÏŽ xð ›×yÇ:éÛ=ëλ:.?W¦œËçGÎ@€ { ìùû Ww}òuÞ‡Ô&·}­ýÔ§Í[ï9ÂÎ)¬µw’7o[{JûÀš¿ Û7QÚûÄ­g<óÀ;Ýwmš@è±Æ"¯ÿï5=íK»~ܺââbeß#¥FiúÙ½G–)£CºýÐ-«e±-¸©síå«“òåÑ—¿»ìüW†éó>”Y~Xâ=BDàÞ{¼ËÆbÑûNϺs/–a³oÞó\šð§‡zä‘¥NitÛ +.zâÝžvÄ)@šl½ye¾Ðü¨gÃå¦1ÃÌðC&•ß8œçq кeágï=:ðßëY{Æiº¸‚™×êê•äËÇ\1T9¬g}h³<¤øE×Åã0¾é=Jç"B»¦ëèÁ/Ρ´ó.Êû¿¿êÊ7:Ü™|ˆ ðÍ5¹ŒÄ{ß½ º²CÙŽ÷JH ©S!¾î›fÁOà™_Â{ó rH™CÊ“V×-émý³ÎµO½Ììî_²F^÷^fù+Àƒw€_ŽÔ'¥N–*:A†­«…ŽªM€!ð¦Žäñ¼Iði ©‹xoëÞÛ9„Ø#„ÜæLãyHž^1 ZæŠêÆžõgµ{“2µã¡FÒp×®¹j{í^ÞP'"õ%2Š.”*:QÈ MèBçB4k>Cp)±IÇ/°ssxC …DXçóRy!ÄRg“Í¿-£Þ¥cÞÚŸ+-TϪõ§‡­+˜Ù~7¹Ù¯¯ú­×Ÿ}/Y"€x?5Á=w²Oªè*?+dpRÊl!„ÌÐZàñ€\y;º* ´³bRhÌ⪓ĤÈUÇ’\A€­—ð>c~ý ˆëûÉ·ì¦oã…Ô÷oeøÕmÏ­»âÙ“…È ÷a(ÀÓ¬ø‚'oºdåàQ=_òªåw„Œúpï³DKHPafõEÀ&”&Þµ?¼ŸhÉ@Fiã®2)S›ÃÔª$õc!jk¥xò äÛˆ76{–и´ö%N8›¤Œm«NN$â©¡¡Ýן÷Oï¸]‰ÔÑ¥¿p¹çÏÎo_sLßWUÔþÏr¹B‡³)Þ¼w©²…7­îñˆ¦Ò„’˜J‰Ò=?§µg¦:C23JZ™%iT‰cƒõ™…½)À' ´dà‹× ò9¼µà5iãE–mè"W\ÁØkO˜õèüؤuª•¹{vLÿá9_ºï!Rz—¿ Ì#¹gèöO^¹ò˜ÁÿÔÚѹƦ)&®2ïB ç\¶h‘©!s·žòÈÕá½Ô“Îe°`(±hç6` øXà…ç€Ic}Ž|ÇQÌîx–¸Ñ‡Ê÷aÓxç@Th»hÓú¶³ÿÏ÷.øN¥žüçÏ]÷˜—J½7È–åñ~ú'g7­¸¾µ½÷÷›ÆM¤!2w?˜šzübò\¦_büCÔ&f¡Ô ʱ@Åæ£œ‰!Á$°ìœ ¬¼êlLCaMB¨ž¦ÿÄÓ© 39<‡ OÆÛ:žL›PRäCÁØþ‰;ï|äßýêõÏLAxø €Œp\væÀÊ?ÿæ·Š u³så,‘„:"ñ'¦¢bá18\sM^€·oc¼7!ðNRq„t|#û«Œ¿°¬…ÔBÔ›§}åRúN\E÷ñkJãS‰Ÿä¨ã–C0óÚ+ÌŧR Z$(ã½ÂèÆG¤NãqäCÅèØäË¿÷ÍŸ}â‰W¦vªwð„wP€/¸é[9qÓ†·-íë\‘Ä)Ê{ÆñÜ' —GøýöD¹ˆGmƒ>%9Eé—U/ˆ]Šu 0i¶ƒ„ÏÀÑ+vÞ±…ÚÎݬÿÂÇÙ1ÎÞ§‡@8T.¢w]?ý§­%ŸÏ °‰À›„Fí V®%ì?ƒÆöGøÚ}×rßöµÜû©òrc¯Äëˆ$,&Y—ßÇòÂ4^j&"†ŒONnÿâu÷_ôÔÖÉa!Ô¡àÛqÜÿáâû[ZÛúq  :ÇŒõ\¿}+ûËl^³š—V3ØUÞMcv„ÏŠ®-öÑ‹"µ)eïšà­AY"j\œâ\LЦ‚$Ò{,»lk …¢ÎÞRùÕŸá„5’ ÿ7j»–ðàž3yc¦Óu¯È‹É‡jÎPªlcšÑN.íyšÓÛ‡‰½B!{öŒ¾|Í×8÷õ‘úÔbªð6llé»ñ»´·¯wM’Z„Ô(àñlq†±üö(ÏK¦Äx­Î¾Ùa&f'pN†V]༖v>_à#…"u4^ip™g9—àl’ñxqdñ u€”y hP‰=m×pÜI¡רùø·øëW7c:NGiIݤ©Pi$ÔRG#…š…‘Z€õžßè߯¬þ{ Ô ŃOí¼ó®ßrÙTÕ,,ú (ÐUTò~㬿êïï]Smx¤Š@Hr^òƒÚ´v“”¦Ù3·›‰ÊõZ RŸE)@JʦÁí•=ÜîáÖÁ38/×EÉfqÜšgÌây/À;²¸‚T8 Â;êi™ÉÂU¬Ý°™Ä5ݾ…{_îåéé“Xçf.3U1T½E…Qž@ ŠH „Tüdû±ÉÿzÕ]LÌi6Ÿ0𛟽dê+p Jt¾ð›«þùGOY{I%V)›ìÕa…ä©éý<»ÕÙ1\šf–SQ†`ÎdA\4ã™øJgÊ3\ëÁÙgbœkh,èßeØ C@à]3ºø9&Ä©µñctwæxþ•7 'oçøÃ÷ÙÁHÑ¡°€D‡/B ¬”heqZ øÚ“£³Ô–ÕpDTk Ÿ¾pð[›[ï|ygùMXTذ¼0ðÛ—Ÿô͆ð€ó®92*û1ÇîÆ” j‰…8…Ød×4Í®å2¢â87ßEÃ&¤Ik Þ ¼ó8—•²„ ‘*Îeï’®ÊT½ŸÖ•W2ÐÓʾ± s»¤(&9똄yÆÄcSTæ,ibpµ[‹±õß°ÔJ1Ó#UFwî§­üW¬x/$Î{¬õôuå—|áòµ_›\}ɺ¯ô-íí,× ¨o¶?Ë6áŠÞAÎ:³‡G'ÆùÁŽ×xulŠQ¦B!Á&ÐðdÈ)Ý\»z='åZ˜®Ï-bÒM†(%BgÛË5Ò* W²vÍÕFÂŽWŸ¦×=‰ÓyJ±çËgîåÄ¥3üùƒKyfWß‚ CÀáÒ‘˜ä´ÝœrlÂù«÷²¬X£”É’0”ã8ç×z®>~°õ¿¾´³üŠðÞ³¢;ê¾åúO¼Ü××»4Mßvx’¥®ÎRðŽ‡ª3hgÚ7É_¼±ª1¨@rt~ _µšÂÑËè±1—…m¤qô B‡_ *o­ I’R긜 §^J!§xù…×1»þ‚.=‰%ŸFxòA‚7)¿ØáùÙ‹!{§shRzÛk|lÝ4Sù“øùì¹ í©ó¹UsÙº×Il€5›ZZr’þ×ëÿñ†¿ÝñGàäÝ,ëk_ÚHL3o›ŸTFW½ñÎPòžÓ‚£ÊR¢…•Še=ùU­}”n Eþ¿ãÜYtÈàÁ¹gM³‘euRe­,B¼÷»¨–ç=u“dy‚aÁ“„RM”oû—Çš—µkXqÚ5ôtæðαwß8fï87Ž΋lá KRËrh„–H©I>R(%b«À9lb±Ö!H­BµŽ|(»ò‘Z®‹µ´§#¿<5.Cggq&](BÌ‹Ò(•/:šxoqiÜ<¤hÖ(•E|õçôœ5XcPfåËNü}z»™GÚÙÿÆ}´%[iø#Ct´÷ÓÞ]BGIJR™cßȱ´´*ÚÃ[JÕõ¢…C*Ô:ó ç›Äaãi\û©<ضm;ü.]]mÿÑ+iÔvmù!º<Žyœk ¼'ŒBöÏ”¹ýÁ¡­¯î¨ß\ªùI.òÝË»‡/½ücÇ|æœSU'™…¥hZ½y†xPĈ@0:^©–«fV'Æùj¹êÛŠÅÌ…ï5ùB‰¾¥Zº$…–ä0ÓìÅÛ}¨®7(•VQÞ?‹u}(D 2È^*<ÎL£JÚ¨5­.Pa€T#{§™˜H‘pã‘S.xÞ£ƒé'qNã…Aj…5Q¤¸÷ñá'ï~²ö»Ö3$EV¯˜®ÂÞi{Ëtù-«—µþ—eÝ­ÚI‰ u³8sÀûæqÊCêÏ¿§ ëJÝT§çªqÿRWðÞáE@kqšµ«èŽ>hÔ¡:•=¸Æ,õ²!6 ƒ”%¹!’¾VD¼ƒiÓsœ)a]‚iÔ1Ö¤R¨P#•DIµRct÷ ‹õ}=}ìñ‚©QA NK´V¤iÚZ4•FðÓ|¤†Ž_³„|(I£kIÄž±“³ñ¤RÿNª›&@39óÌÓdÍV쟬óø‹÷UŸÖq¾=£¥ñMkÝ B h/N ƒ"Œ¼AZÙCZ/aRGlÁÙ&ý·óU¦[•iÄ[¯‡p3˜ØeI”¨ @ 8ZÃþÑIqŠTšžŽÅ‚'EÈB„@¡E>ʆ”‚Ôx®½|Í—®¾hå«ú‹OÚØd'DJÐHlwÃð'mm¹n“APfuçqÖâŒÅ9‡wž("È¿{쵑{“hkå©­ží¥°^—bÒ7‡Hê µšÃ¸ŒñZ J‚õ™ð°@£.h4*HcpÆ£…Ž„ͤ*sGc³Ó5r¡¦ £fg© (,A+E.RäB…VY­ k‹ó,íʯøGêµägÜ/€TX1¨Ãàü%E5`çÉ•óÙ¢[¨O*­hio%q‚;~ÙÞõØø·æbÿ €®Yo7­~>9W¾¤»+3)“ñjÊ;gâI yG¾"6™‚·õ71LÕ%s¢Ÿ»\ /@G 5¾oi`€ŽÉÉ òùÅŽ%,éî Ÿ×DDËæÂç3C‘Åö46ØÔhïü…Bp¡Pd¹\ššLQƈJ’ËçÈ 8¡Ø¹o‚­tïS3ß™­Êæã½§='Žÿê?YýðeçŸÜ^OVä(ˆ1ZÄvFvˆ÷‘„C8…P-Èb5уt9°1*D‘ÆËw8²‰%©Ç”*ò-E ­E´ÈfÔÍ*É‚PKÜH±Î#¥D*IED¹%%ÞâŒ_h˜pd‰j¹VgïþI^ݾ/}nëÔ#Ûvûï•ÝÝ‹§¥Œ¯ÞýØîÛÎ8qðóm­K°ñ ÕÆ,C¬ŽÂVP×píÔ¡4¶îIhD (\Cß¶~g&ΨvTÈ1ÐÑ‚€ÏØ<‹ÐZãPìexß#csv®Ï&Æ×瓇0a¨0 u.é0æ5.0ÆúJ-iÌUâ™ñ©Æî±iûÂÄœ¸»Z•7ó6»Ì„޼ØüÅËûï»â¼cÛkå iId.Íæ ³`j lâP¡l†¶·}^Lb±‰E*Ž4â<PJ2SNxðéíæÅíÓî›t÷•«â…Ô²×{Ÿ9B (ð­ZÑ#% o÷—Z&œÆ2+'ö—žþ,Ôfê~˺ùýUKþýÚn< A(‘AVLÀ[`bG§à*RèHáY^ÿ’í]‹ 4*Tøù0u°š‡'†»Ù6|ûÃSÿ¦Ë»…u)ôü±0Ûxç^Áу:DF&øÓ[î{ýgc³Š­„xGsx’†!©¥8*T¨Pe'<Î.tle£y-ÅÄ6‹¡jrq÷–ûÀ$†¸–àÃîQûÙ hêZeÑf¡ÚöC¾Ï—ƒ¾^NÜì ÛÍ¿ºõþ¡mÓ•˜ Jcq=%m¼€  µl–±²RÖÁ£yjÑ¡Bo¿×ÖZâzBRO±Æ!”`󱽫q’õËÛô7Ûð[}¾þù›ÿîùá±™QWLbZä²ðæ¬_pǃ‡'©LbQZ"´\8ôîÀ}ilˆk)6±Ù¦NJÎ<©ç“ëW´¬Ž“woƒÿP0UóO=ô‹úgoºã¹mÛvŽêA¨P¡ÌÒaïð¸ìzÐð¤uƒI BŠì~ï³ÏœÃ“õú'µ„´nðΣBESH-±ÎßrùG—]÷«w-| ˜WÂ/™Ïüè®W~öõ]èB Q˜µ©ºæíâ‘YÕ’ÆïÅ>8ç³Ïkq5ÅÄ„@ç42Mâ“aFi6áÔ ל~\çiøÃ÷‚CBÈLݽðÒù©›ïÙ}ÃOîÛ’ŽN×(— •ÆYwÈ<ØÔ-²j³Èp{“8âJŠ3Ht~>c›zâjŠ5)Â| ~ë¼åߎBù¾:XGëm‘Ò…œûäúüÛ³~mùI'»ŠÎÖþ+¯î0ä=u‰ÍÅvð펼¼õµ»®9æ¹ÝŸÞ´¶gíq«úèé¤%ŸÇú”zµF’$XgIêY‚„Hü[HY–-zó¨ 85]í¹S„@üJmr3u· øF{NþõÐÎñ?Ò9~ù`pÚúcú:W¯è§¿¯‹žîÞ¤ÔË5Œ±xé0Íb¨oòšWÑü¯K!Z)¢(‡Ô;öµˆlއìø~?ò€L[¤òöŠ9ÿë­œ»´Kœ0Ð×:0зDõ÷¶ÓÛÕEkk‘Hk´’ÙÂ}D›áÓ:uŽz#a|fŽç^æž'f¾2U’7¨wa{ï>t2šë2’“SÒ/´_Ÿ8¶±±¥ÀÊ–ýmÅ £ …|…¡Ò™áDœ¤TêI:WŠgöOÛ¡ÑIþ¦Z—7IIãÝÞÿÿ…Þ*î;”Ú„ðRÒ)…/(I¿”…@Aà}VT2–}ÆŠqkÅ!˜=\žÿÿ\G²‘ÿ/ðAÊÿ#ß¿w„º@IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/apply.png000066400000000000000000000112051217176075400237210ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞLIDATxœíšy]UÇ?¿sî½oë~½oÙC:a—]YUÀÊrÄa—që åÌü¡ÖTią́ $ Œ: ¡D…™$’nQD [HHÒm:IwBÒéÎÛî»ïÝsÎüñº;‰,&HýÝ:¯úu½ºu>ßßrVqÎñçlêHwàHÛ_8Ò8ÒöŽtŽ´y‡ã%-ÿU{R ÏóÐZãyÞäß"‚skíd3Æ`­%ŽcŒ1˜Ø`« ਹFÆÛ„›&¾3þ›ñ6v½£þfW±ÿâÁmÿ"@¾+ )I ’È~MÚ±othÇÉrŽ·xâg¾¢ýƒ}ÁÕH Ò©´ú»¨âþµ4ì®9½óÌÛÚ3祼d]×þ¸oTV¨N…ž_¬ØÏêÞçÐF3«é˜î“:Oýv çzÊ«¯ûÄËׄ7šdªK;µ Å='7§?4e>O÷?EߺÛ=ÆÖ][Èxéî†d÷ê\Aê3‘—L‡7’ H‹SÊ©ùùJÜsbý<}mçG!t%Œvæv #ÏúŒF»+qõ[‚œ Ô¥?ðâHx£ Ôr¾K#ó QÜ373[_Õq#c#”mˆÅbÆŸÝ…]´øm´&Ú‰"ÛmŒ½'çõ©ËŒ„£_Ap5xåÔ‚Bdvgfëv~„|>GhK 1UbWEia,åG߉±†yísˆ+t;ë¾5.B]ê½û"áh@MÂ{¾;3K_Ûõaò…<¥ xW%v1¢„=álXÎX”góÈŽ9³©Dt;ç¾%È[pÔ¥ÞSáh`<ì¥KD-(D¦§;3K_óðÆU‰‡/ïá¿b,Êá'ÁKÀæ½ý¨ÇI3Å…ºÛDîf '`9J¨Íõ®Ví•èËqOwz–¾zê‡ÉkðKL•ê8üh´‡Þþ_1fsøu )P ìV/ð‘K0UÏ ²“¹ÎÈ\kЉwÉÁÏ™_G«U{Q 5¿PŽ¿0'3K_=íCŠyB[Š/w1ÊWŒUöзmc*GP_{ƒL,¦4¤›XöÀRr¥Q2MÁ½Vâçu q58mIƒ8ç¶]‘{-6's^ù…rÜ3§~–¾fæuäK9Êb½}ð"RƒîÝ?±zˆ=èôZ¹¬á*Nœó&*¥héÚþµ?,–ãí"Då¥Î”]KÒJ‰@?yvÉòáÑá;öp»€*D´Ýˆ§½´MÖ¸ËÃBõìT‡Ó¬Æ‘*‡¾6·Õ‰° X6=ÓS]úªyWS0yBbµÅc©ÁWGY¹»—1•÷¼ " àçzšƒfýõÓo¢;9­ùAŒ5XWv}c wm¾gv:án ´¿áa`/¯\GZDuЏùE[è™Q7S_9ûZÊ6"re”¬s8@‹G!ÎóDîQB I'3ûÀ$šieðžl~‰¬^îŽqøaà%=ÿ¢høg?ð3‰t²³-Û>¿­®mad"ý‰?ÃÌôlFË£g‰]­[,é Ã=ƒw±ä÷?¡.Ðý¾çß JVi­Ç<Ï«¼Dˆµ6ã¬ëtÎ-(UK=SRÓô³®¦l#BvòQâ=JÁäñ•¿/ßEPÐhZè¿{;Û6î Ù¤–s‡íjC@ÞÿÊ;Äâœ#ûUQ¾ï§3ɺιíóæŸ3ã‚…Ö}n×dý,¹(‡qãuØ™ñ…gŒÁ’ñ3ü|ë=Ü;øS2~0xÁ (yØóôd:Œ 0ß…ãúД¶&Úõ•3¯¥JLÙ”p¤¸J) &Ïê±ßQ0…É‚7ÑT dã&6ܶ…mý;ÉL×Ëœq·ÙЮÅ0„ûãð0ž‚$5ºmNS÷G?|òÇ6&uc²‰Š‰Ø[Ý‹UãžÇŒ ±ï5{¸tæß€þ{ðÞÙý@ yØíK$­Du:忇qØÓ‘êÒï›q%F ‘-#ZpØZ§Ä£`òû”3fžÕäi§£5,^AÙæ˜Ûp,  J'µáɉÅʸ Rû^vÇ6G 6Ö7i¥Ï Trdzzæ;/Ÿ~õß·$Ú¼ã›NÂ*Cä"DSÄ¡´¦D‘uáS”%$á'ÐZO6/áÑ M<ñëØºq˜ú·ª>e± íZª S!úÇ÷~ùPùÑÁùâ^¢2¥~êÈÉo:îø†“26Ã.oOŒ®¦¿¸®ÌTZ“mãµÀքد!'Pv!Ý óH耹 £;KçŠïνlÖåžó`ÔŽK\ƒ ”Ö„”X=CYÊÞ‹áU3ÿ¶¬ÛNÃ…z…×,‹ã’]M…!*DÅůŽv|mÅ— PdïОí»óÅü±-´54«V*Ù"[Ë[x6÷J+¦ef ”`ÄÎ~bD®Ìœ†¹xø<²~m²½µYÍn›Å¨ÁŠÙçyU;P ]‰õѳD¾,ü£?|’þ'·Òrq¢×k—EqhÖ¸j ¾pÓ«¿ç39È~Ié¤$³méŽîödçE-^Û'3~Ý 5Õ±©åY†KCˆ(Ž­?žw´¿›æ …È•÷µÇ‹âø§CB’dòMYÍVú1ÎÂd±ˆR„¶Èúh¡+â)ÿE9Ÿ•~}×6>6@Ç…u}^»[\ÎEOÄE3l ®ìò¸ü?¿úùSáì J$²‰æ9M‰æ 6ùiå©SOìb÷”av†Ã8¬Ÿåüæ 9¶îŒ‹‰‰÷GÇŠÃbpX.hºˆmÑVž+==9zˆÔ<¿¡²Ž² ñ”w ¼Wƒ_õ“'Xÿøf¦_ÐÜëwÈâ0®®„•¡¸d"›wÎåá° Pÿy¥<ç7Ô'ê©OeßQ-ÇŸ¬ØÊŒÓÎ9…Ê1%v•w¢DãÄqlæÎÌžMZ§‰\4 ç&bA,W­9Q“ÿ›€ßXYO™Ò‹=?ÿÐ/ã¹5™}NGo²Í[T*”ÖDåh¸R®„qÑ`óŽ?U€­óß´¶j*¹½¥½ý#¥Ý½•DùÖ|57¸¬o jº²SðŸtf ÞÄùûÙoÁÓ^m¢¢ ¢-øãã7Ä­="UfÀn"ö*$ƒ¾ïO¶ Ðä5³êÇY?°‘c/šÞ×4­n±í`ᇺC ðïÎï-UŠ›òÕ½½~“ºU ®xèaâ-Bg¶ hêuD*âÑò¯yº²£b<ííaR At ¾¢ÊüÞm¦êUHøÉIpÏó>M^«V=Æúm9éücV4O©_db»šÚ ¯Lí^Èk+@ág­³¹J\ÙT6aoªÍ»ÕK2¸båJJ+tf;Q¾"$Iø ¶Ø¯<Â(#xž‡hõ𚊊ØB?±®’‡÷<íi‰€¬n¤ï‘ß²nx§¼y^oK{ãbcìj„a ,"‡}#öÏ ßvÈg7W]µ/Õê-òÒ2¸|ùJFŸ,ÒQß4¾_K‰P—xƬeÐõƒrµ•à~ðƒôSÕU~brzëy‰D‚:åW¬â™íë9ãÔûÚZ›¿c¬©…=‡7ìZ€üMÎ9ëì¦*ÕÒþ-Éf5¸ì—²óÑQÚêÛñß÷kóvßc;ƒlä9BUÄÓ>±UýžØ‹'á}ßÇó=‰€ŒªcéÊ•<7ðÈó¿ßÄo>£oz{×â¸æù!j›¯éeæƒ>Ë}iR„ͱ‹{æ%oÍÎI .ýE«†h©oÁó÷…uÒO¢|ňÞIìUüßóñ½€@'Ȩ:²®‘ûúVðÜÀFÞþÖ·ôÍš:mQlâ× ñdhïçœiü®Ê9ç6Å.v-Çס•þÔÿܳb†¨wpÂEs(Ä…ÉmêɆB£Ç?5K²äÁŸ±n`ïºè­½Ó:ºJ…µ"òºÁë¸(9öqkZèïuÎm6ÎÐ~rƒ`å“÷ÝýÀ å+N½à8 ”ðð&Á'àªO’;W.áéþçøÛ¿¾´oFçÔE{Â=k&ªýkÀù²öªGw_Wµ]KÒ9kíf‹•igµ9D>õ‹»—Ïð}Ÿ³Ï>"á~^¯Iàð½•wòTÿ³\É5½s»ŽùÎp8´F`HWÜÀ|-ìUŸ_Y23Ö¸×Z»É‰µsΛ‚JìøÔ½?½†ŸðyÛiçR"œô|‚>>ßyè{<5ð,Ÿ¿äÓ½§tž´h›ÙºFD†y]=?aÒý€-ï³@ÎZÛïÄõwþÌEsš¼äç<üÄ£´ÓAŠõd©#Ëíý€§û×ñ—,ì»°óí‹«®ºFá#áù û“/H<ÉÎÚ<ÁÚM·âÄóæÜÚÞÑ´õî›ïåþ‡–3“Ù´ÐÊ¢‡nã©þu|ñ’ÏöžÕ~æâ"Å×lz{(v¸.HLˆ°Ywæ%'Èc¥uŸùñ½?ÒLe0ÜÂoãã—^×;§}ö¢]¼°6AbȽŽÕþåìp^‘1@γYy²âœ«O¹¥õ¬Æ;ícj7ï¾èm½3:º3´¦L8d±G_LXmí`ìfßWîœóN+ïÊïx{kóp[KË]cvì©z•=jàáð û¥C"áç“™Äoý@Wb¿àp»×@0"’Qe_y;´ÖF”T€˜£^›¨™`•HY)‰”(7±Ýu´ÙËÞùs±£ï¢äëlàHwàHÛ_8Ò8Òöë[ õðù IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/bookmark.png000066400000000000000000000327661217176075400244200ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí}Ù$É}ÞGfVUWuuõ1G÷ܳÇìR¢H.ÅÝÙ]RÔ’’LK0dÀ‚´ Å]A° 䃟ýøI†HèÁ~°HA ¶$[0SEñØ¥¸I¤¸ä{ÌLÏLwÏôQU™—"#32*«§çhqzà]Ù™‘‘ñý$ÆÜ/}î3ä¾ëØ¢ÁÿÄ;F΀`öýó}ú³÷Ž!€íx˜(—Á‚îö™RR"upŽ˜1Ä,ð¤øUA½%Ü+=ª àÈI:A<&²¥Cí¥“'æ^!O¸üî»[_¸vmø£(B€,ʨ¢L“6x$èQd€PÍ;ð#\JdÇ÷žùøÇû£Þ 9É"- ¶og¿õ—_ºð;o¿½õ%ÎÑ Šz*É7xÄ´@“|T(?ÖQÓöùçÿ‡î€Ÿ¤3Hh‡b¦ùð‡Oþ^»ÍµÐ*Ê9óAƒº zd$ ‚ºÚÄJA93øµ……Ö3¬3 Ò:´ÿ)Ð~¬3@¿züñ…ß9 ¦ñêpu>Rô(™€PB)*ð#cÇ1¢§Î-þ+ÞjÒh}¸8-@â7@GÿO>>üä¸ö_„ÐcjkÔrXõï;…„)x5A]D)aŽ›ý…¥EþÓ¬˜ùe€ÚèÐþØàãX\ˆÎ>vvþ×¥„ n9-ð¨0À4ég"Äœ“öÓç'î8éÿ2,¶…co ÒÿXç(yêÉÁ+í6]Ð*`^ÝM÷=tà  Pò­ô ˜cÇz[^n}€öÏñS€4`tñ+vlðóXZˆÏœ=3ø5)!PiP<ô¨1€“P^l-çˆßsnáÕ¤;ÏhÿWãCâ‚ Òÿ%ðî yêñÁ'Ûmº  ¢¢Žf-p éQx?î'¨€â¸À±•ÞK+Ë­÷Ó¹€ø1ÀH[Boâ  n.žØ1ÐÁDZ´Ÿ>{jîŸK…Š¡\ݾ8Ð}x ß@ÎöG°`Eœ#~úÉ…O%½EFç~ ¥óž_Òïù›@ö] ÿ\˜Ì¾Þ]!ç¼ÜnѹB ø!á#ÓoýA|ég¨ÔúøJïçŽ-·ÞOøãÖá“7ñlW¤üå@^³û|lþ%ZŒOŸ95÷«…/£î\úã ¶lÃȇ`œ“è©'^Iz‹Œö_@“âmT©}SW5 @f?6³BžzlîåvBç´ä/pàé ?Än9ÿ–Ð+G»/­MÞGçÎü4¬¤ßÔ¦½Ü˜"Ã_ þ©@®ÚëøQ°ù—°¸Ÿ:y|öŸ(›ˆQ÷Ü}ýö(:öÈâ-í>€ˆÐÇN÷#é-1:÷‹ö”â[Â ÞØ_£mD ¯z@ç~Qw…ÈM@\/4©Û~4l„jöFƒ#OŸíÿf‘Nƒ/@ƒv:Põ(ïç°³}ôá¥ös§ŽÍ<Ëç_ø2i¥¿œà3Åö‡Çòk…8¶ø/¶Ÿ:¹ÜûD¡üÌà#8H ऌ Yúôéǯ´çŽÆtð¢½Dnê&ª9ž`S`o<“€Ê,ÈÛ€\ ;¸Š>uºÔ êaaSûz:l 'ýN ­í_l?µ2ó,_ü9+ýF¶_ ªlUƒ¶ûÚ7È®&ØøÒGqd±sîäÑÞ'¤‚D8þ¿Ø7š6ÞïÇþVú+1;oñ7¬0 *ûoìÄß‚ø(6ㆉ  ¶­ÿ€Î=‡¸† ´ïjÏ4Ðc@¬Úô?€Öà {êÔì§8#n²ˆï (-ðP7. PúmÖOKóÉûN­ô^à‹/Ñ ÓBúº×€Vžtë‚t!Œö4DÁÎ'ȯjDóˆ–>ŠåC³ï_9Ôù¨Ð¨¦ûZà@ÐAb€&é`€s§ú¯ÌÌï°Á éw)_ª¯Ò•e†ZØW¯ùþõÐyRÐþ{Ñ<ÆÎ,µ€ŸtZà@0ÁÃÎál_Ä…ô¿÷ÔJï#|ñY€/Xàó«¶”)l¼“lí€õC{R?qÞ™‡"W¯[§-ÇòR÷ý+K ;Á(ôÄ|‡¶a…Òogç˜s'û¯tNwØàƒ«ì* Ò@ÝëÉ}:<§°¦1tUGi*r[?Úÿi´çŸ`Ožè}г ]hîàÃÜÀiÒo=º4Ÿ¼÷Ôrï#|ñCŸ³8¢Ï/AöTõcdÝt}³@lb³ÐÏcåPÿ}+K—„}]$œ/ðÐÏ|(Õ@~Üosþú܉ÙWº ';lðSV}gïX)­åö}—Þÿx]ý¯CÀ}àw²¾ hÿ)´gù“Ç{¯0ŠÈTZ );øPÒÃÄ4Ø€ºC圬X*`qüÌÉåþGØ¡Búå-@¬ÛRZZÖ%Z›©nÒº^F£®1«Ä-€Í"ZüY,/ößwl±óóª®ü÷ügôŸõ'N?‰F4eÌš¨¶ ê/{ès'g_™?Ñáý§%ì `„”®[&¼¬_æZ"4Ç &ÉV£AûO¢5wš=q¬÷IJJ åk0*˜6`¯ýò@é'Í…þC»rv3tú"Ø7|±ÐŸ>q¸÷¾ð^€õ­äC·u vñ¿çå;OÂî‡BO‚^2¹cý>‡xé8²Ð{ßb?ùT0¨Þ&*‡¨½ ÞsþD@÷i?Þžö0`ÓpŒ6ü?ñŠ€–6Эô^îV:ÑàébòÆ• CŠZHõ­Úb¤Ï‘`h1Xfq›Þuÿ »Ð°þ9t§ãsÇn¿rãvö¢ÝÅÛ'µDƒièÝÐ/¬á˜OzÊñ»¦=1Àç>Cî†C›ž¦ò»ïlg9Ë×ÄJƒ^ôÄ™£³¿-ý ÀvÀGl”ÒL½n.„L›âÿbx šâEã7ÁÙ?VN'+Îë‘Õ>ÑÑÒûpâÈÅg½»}þú­ì«œ!&¶¨)žIû.¹àÎ143£&°ký¹Û"]Ÿþ¬Ù•Y`€‡w ËL üÕ6È`Œ©Êh ­ $ T‘6!$yòØìoõæ—g£ÁSv€&» ë¡;€”'ÉÎöxÿûÄTàOh€!\¾Éo¬ Ö3s'ãs+›¯ÞÞ˜­\š¡6£ ”T•R[ˆÊË6M¬G´ƒ„àN0PˆeÈÄ-7ô;Is“‡ªqŸz«Òim`”†‚jE¤K)™5½A/^YœmŸ#Äœa§ŽÌwV: 9Ônñ•¹Ç?Á£#/Zðóka Xe“ àJ&(Ž;M±ðÝà7 ˆxâú×±õæŸèá8½6X½¹™­¦¹z Ö¶ÒïÝæWÁP³™æf …_À("J*Á(šè̆#Ç(eëQgü&©Ÿ`ŽOÖhbŒ Áo’ÜiÇšþ'þÒƒÚ@)m3ôd‘³ wçºÑá¥~ûIBð#äÄÑ…Îr'¡G)%‹IÂ{­VÂY–´Þ‰» ­£àƒŸHŒ içðˆ5PQg xÇJ& ^÷41BÓqÿZǹ µñèÑUè|#(1†9Ò4™C­Ìz*Ìê•Ñ¥ñ6€ 7·Òï߉„`Gk³• ³ƒ"åÍ(%•ó處PS4ý;ó`BZ½cÌ;gËÆV¨ ŒÖPÆ‚¬bŽ˜3:g º³èÐR¿õ#ä,¥8utÐ^î´ØQFÉ¡8æ³­vÂYS·`ø h< šô@“uAXàm€&VÒQH{vkÅ12 ²¯î'@§ÁÿwRÿáo¨Y ÀghΚ%£,cêc¹ ä;Ðb*Û‚N·@Ô2C‰ÜXæ;Z›µQ®¯®n¦W•2okàÂÚvöÃÍ‘¸N(¶µÖ[©ÄœD”€š£âûIíà´H“©)}g‹kà›o/K+ iŒ:bˆbNûÆ`¶“°…Ãsí3œ’Ç(Á©CýÖ±Ù?J)YŒc>hµZ‹#Ê“À» ‰¹ uA¸Ù˜\S‹¡ZížÐXç+_÷ž#v0‚Ûw&À¸> }‚½‚î~iÕŸbà] T¡')«3 LK¹¨‰ÁÈÒËwb•ïÌ«|kÞdÛOœ;"…B§Y&ó\n)cnŒruíÚfvUsYi\XÛÉ~¼ÉØRZoe N€ˆQ𢥄TQˆcÀ8({Þ@j¤ÿö÷Mþ{Ÿ&QÌé€YF0·<ßy,áì1cpr¾Ë-Î&G)!‡£˜Ï·Z-Åcq $îI,邯=«ºy·™ø »ÛÊÀFOnF3E¸æ’0¹å_ã<ü&G­ÁqsaâÔðÏ÷|ÆÒu¢¬Ä•7@¶´Ûöâ’…†pˆÑ…vP@¢@Šô27\ ÀXæ€È!í‰Xg;‹*ß^ÔÙöÓ§Å2C ¡Ó<¹·´ÆÚv¦®ÜØI¯jC.Km.ÞÜIß ½N`vren}æs&ÿÝC"N‘ŠbìÛ™€.€Hiˆ„“Ö©¥Þ¯2Bž™ë°•¥Ùd™1r„1¶Ðnµ¢(Žoµ¸ÏT '>ÈܹàrþªŽ«I”bÙùžßãÔªYÏ›8`=uî:p¾&˜&Ñ~Ùì0¿€†º ¬`3¶œR%a®Ç¿w‚ºÁ*­Š4¶Ke;sRiÈ1L>„C¨|*ÛÉí&ò1¤:Íó\¹aŒ¹ys$®Ü«+Ú˜ï½u{øÇ©4›Œ" ô¥ºñÊù³‹_Xš›ù@ÔiÏɬ¹Õ;È,ÙiVy “°Óü‡÷‡a…·©ê×åõ‰«ÓsO|é®Ô¤ÎáÝÀÎ_ ¨mâÂý"ì'…U%‘Õ„û¬o¨ tÁÂû{‚c „Ç EŸhwLØó2…Éw Å*ßÊv€l:ÛB–g¸=LßüÆ•[¿}}'û.£à¥ `„¨ŸZîÿû£GŽ<ÓZ~¬sH •M=i,$Z¹4¦Þht0\¾Ý€Jû«ýýBíû3w ì}‰³µ>X#øÞ{4TÚÑ=›WGͤ¸¶xù‚ØMŒàr v‰A§Í¼¬7)ò]Î$–Lâ6æ1H ð¤êVãaá´ƒÎ-A´ÓÌxZc¼ŽöÎ5Dëo?ñ~¥÷KoüŠ4/ŎfÛçã…`y;¦ `2T>ƒ×Ùå¯'ùðÕW°6PÞ¯Sï¥ùp÷Õtqœ@ºëj@yõúLPÖã'‚¼ëšü‚iš$¼vB9ð¦Ê©é:«|â1hÅ ´˜ExeZ«„ƒ%k×ïgŠ{¨10¾ (Ú£3§ÐÝZo7æOofòœ`æ h—¸N Eµ÷è fbóÔviŠP¯ŽšòN^ÈáKÑÞõMà8Fl‚6\Û°?ñØÎÝ´ êç&" ×>¿N_ƒ8Æ-„¨ÔÒ+ã4aáSß¼ê|éG(«ŒTfËPÀ€SÊ{1?|+•?v ÐRÃ,˯Œ×¯Ÿá*A2K@™.ÔŠ¨À.¥Ý“Ì I†'Mî@˜ˆ*¸´æ4]ë¤OUõ×:?L@z § @jàÕ|†­ Œ&€óên82Ä3 ŒãÛö&3…â¸k£ß‡ÆTý¯D¥ÚuÈÜ‚¬ ¬@¬V -kb(ƒÑéÆÄΆy¾qc”]e3¼è‡8—F}÷ÝÛðBûê¿‹†ëÉèæ!tæÑîr€”æ~G§Ö€óm3 À÷ûM‡RÈ8˜¢UšT¯cïx¶ßß/>S¯cš )oM'˸7‹ˆ©ÊùŒáÎû©ùròj±ùŸsò´@5›IU÷uígm»RŒ”‘ Fkk0é;Të®o1Sf›´KÀ)zoÝý½psé¹ÓóÿºEWãáA:`fÐBÜi7.Qáä›w˜„]i¾àú&°ÃSÅèž+ä©þ0æ¯é;u¦nFŒÁ„y(¯óìêó@,“­Îœ©¢ŒçÍSì>1/Áó|fó™Þ™cÞ¢Yk´t™æm d›ë`â"ôw®oÿ×77†B ælÕF9Åìŵá_Hž;½ðj§·çcƒMÑG»£ÓoƒF3–3Uf̓kT)9ðÀpÇ< kfÏwÚöHº(§êl²É5j0U5Ï4Ÿwíõ:ŽJÇp¨®+Á÷¥P¿§ÛŸèïKóÊ»uâÍXFR)Œo§Ìè¸|ú;×·þäÖwþ˜Rô° T©àr|Ä0{qmøWÚ õüé…—gf¯G¹6mö!R…N¿…¤Û¶!‰öm]„:¾ÊóÚZk´ß¿µnl é¢0!“3Q¯;v.óÛj?å×ÿ§ìÿùipqp¯‰úÚà´míE+õ*t1Î0ÚÎ!S“ÝWWAèo_ßúóXßù3F1S€_ P°99lž¿{y}ø×Jiœ?½ð/z³×;` 2ïcxKCd–h”tÞ†jËjS< ¨F³NêÇK¯&˜8¨Æ`?åÛP4Ø©n`¼B ~k#£52kS¨1Ìäóúc¢|Ѷšf1vÜ¡µhO« FæogȆ´’@º&¯b¨¥xcuó^º=ú£H°ƒbd€p àÀϤ’ˆ!yûÖø«BßÌ^<³ôÉ~ïF‡@CcùPC …vO!î$6õÉZ€¸ ÈQ݇Eü‡à‚¦‹'O—Bc‚ÿ.©©Yƒ:°Mîþ8m†Év†R]SÉMuyÇ'˜ÔkCÈ$µcºî[$ ™/C=™fo¥y(’®ƒª«*%^¿vûO/oŽÿoÄ@ 0‚Å7…ÅZ:ÅÁÈû¥1Gou+ûÎW.Üd/žYúÙÙµŽíƒ>´0ÝÖR¡ÝÕ <âE€ìØ)Úá8}£V œ PJÜaÏÉ«½íkP¹³°lÎñ*gÕkãA[œšvsülŠøÛýºlˆw«$wšö(}…†þ Çh Yâù2 ̆Òk÷íìè 0¹Š þŸ½µ5þJÌÀa%ß?G DqÒ_ì€E ³«ÛÙ·¿rñ&yñÌÒ¯Ïήu ú0Æ ÛÖÐB£3«@ãà=ƒf7íx¸ë˜&{?ÅÔN’wa9šæ'¡¼ñ_Ú'$nJõ»Jn$ñŸ¥`Œ0•K]‚&\.ÀÝdF¦3žK¬Ãgr‘c¼B¤™^IlT^ÇŽ”âõk·ÿô­­ñW#  þVŒŒQ0ƒÏcT2ýÑ 1tW·³7¾rñ¦yñôÒoôûë ÃfA !Sƒ¡RhÏðDÛÉÉQ;j'·QŽÔ†n)Ϲ‡vaRŽ2¥¬s”ñoi|ûíWæÝ‡<‘À?Ùí†*ÛX&„À¤£G,ÐØ:i4.ö=íâ?Ã4à4W2($?‡Ê3¤Ûd^€/ÞU7°#dþúÕÛöÖöøo ððCTŒà ÷M@^µ¼F &øÖ—/ÞçO-þúâÜzßÄ }P¡1Þ4hu5¢¶c‚C˜}‹Æ¦ùfµ“î0y•Ê,C­¦Ø<ì<æéw¿.}àKyC8æi´ñŽ\¾Á3(MÊPùÄ2K’xš"ð+Ü,fkçãÙü 2³*_‹ D+h)€t F¬áv.G¯_»õÇ׆Ù…ÛmÛÞ¾35誒ŠyÓ@Äй1Ì¿û•‹7ÓN-¾²4gú¬e 1mg’lk­w4` ^°Udk(Óœ®ÓÊ8Š”¦|b°¨h†©Š–ÍlRë5p½'ªÛt÷ HPh&šüÇ¥ /ÎI;MÌ>µŒÀŠÄžßd¬@°,ZB¦)²a£r@ %AÒ5h±†­\¾vuã‹«£üÛ±­ÂÝI¾~Oø#¦á‘Ë®(ºëcqá«—×>ÿ©ÅW–ú·û¬ hô, mÌê+X0Ó(:&@wø ÒÔ±¨n85q,<<烮½“ ”^»¯ü6j‰;W–7€¢ˆœ·i\Zh­%"!æ0*)ÀGº¯cSÈÑ×®Þúâu ¾†|Tüº}_õ»¨Oú ÏÕüx]QÌ®Åů^^û '?µ„Û}Ú60˜-žWCŒ­[&0ël_)RÉŽÇu¾Wò‹×:¼Øñ-Æ4ÀݱiæÂO2M” Î…8×ìxp¬ÖVŸ!„Ø,3ôNFCŒ†ÈÆDå *‡–$Ý€Ê×±™àóoGAçèM?G1yn>@q{ÿ•¢eäšMKMðÖÚž7‹¿¹ÌYMД­F¦tޤU<$‰,wË‘ç!ß íQ4™—JÞMõ‡>DøM~Pi‰‰² õM0IÑOZQ¼ý.²±À`+$ZÜÆ­Tî¼¶zë¿^çQPTê~»ø£Rý9*ð%p]ã^aòç; à7Ý:†ݱ¸ðåË7ÿÓsjþSËóæ0k+Àô`dZD1âvÛÚ¹äp1¯mTÙ»âÙ§R“Š÷Ég‚ðÚpÿú½:„e;ÆCpn‚êó»ŸI´±ª?Y€H3äà 3i§ÅI5ÆÚ(ßüúêÆ®§òÍBòÄ;ðÔ;»Ÿ£¾Lý‡oùêÞ_„±]l3zÅo@WjðnÌŽœ?¾ðêÊ|çk%…CAY „ňÚ-DíÄ:5F£w`“Ew¡vc„RåOq ›Ê‡6zª©˜&Õ˜üT 2ø’ Ð9eÚÈvFÖá“9´LA”€0 kc±ùõkŸ_Ï䣺ÍßFåø¹xŒÊæûšÞêã5t&pkñvŠ­[lLðü±…W—ç;G¢vT Qsƒòq;k%mÛ׫ÓÕÉPp*MéÐð’&M0qÜL‚¼èÓTú€÷¯ßÍ4”à[Õ¯£%dÃF¤0*‡`„ÒXçü …B%ùCÔíþUƯHVÀÀØtaµc‚€Y©ucväü±…W-ÌŽÚ‘ á)-˜ AÔIÀâ–Uséu˵W³¦ÐnIx,Û?>­ŒÛ™Ê¸ƒ_ÐünfÂ4Ø“BžQè| #3™Ú‚s”m~}õÖ ÉW¨œ=?Ü¿SÁ÷_``‚ ü%ÙcØEg`™Ài€X&èJ ÖÙ‘çVæ_9¾0s$jGÅ(O@XŒd¦Â[€Q– &<¹rÍ /›ædí–f®¼ è!c4…S÷*¨ùS˜HkÞ…0=è<-Á7*G®4®Óõ×oÜþ£T^(’<÷dó§¾’÷¨¿º…ÏM>Á,€ŽÒˆbNç?ttî_ž^ìnÍÄÅV °,JµÖ*ÖÛÙª;„»‘nx|Úõµ²¦~|ª)ØEÚÝ΄.šv¬öëŽ:€–Ú9}J Í%®Óë¯]¿ý;R]夔ü-Ô“=~Ž?”|4¯°—"Ü‹tõè`Z—kFÑÍ•Þxýê­Ïä•Ó¦{ºÝ‹@Œ”€$Q‹ØI ع³ ¨Ý¡øÝ-Ô¶+Û˜ ð.¬I¬ RÄ eÃòîÀnšÃ(“@K #3•Áh4W¸²“®¾vãÖ ¥^-À÷m¾súœ³ç’<¡ÚŸJSÅ.àç8¸Œ¡€µ1.Éà§wì0!´Ù~ýêÆç/­í\oç0n`CeÐù*Kmµ$©œ¤½l~«´ëLƒ‰¡aßÝñËúcëÆ zq%貚´›zO”û^Å&8ïÊÕŽa$  Ld³¢ÊÚüq¦pe{|Ý_bÒáóÕ~†fð 0}¥©&À§ÇÐ_¸©…Êø>A@W$%½g ^=½Ø=ÕéÅ ŒÀ€áa„(@ ïØŽ©´›Í¯kxÖ¦ëÝÎ43Ö5MâÃú›"£!TC@fÐ*Ç8•xw;½þÚÍ[ÿ9•ãçÏMòp¡^øð®ËÄ쉀=å |ǰ‡*Jè*ƒ(¢dîC‡ç>yf±w¦Ý‹À¸­†ò<‰ì´²Ý´Õš9Áf—s˜Õ™Œ»}bßÓ"µºLQÑF% ü<¹±IDAT c DŠQ*qisôηַþh¤ôMF °»Ãçâü]½ýi´gîŠ :°LÐ+ö»Ú !@û™Ãs/?±Ð{O·ƒÇÆÐ8£nØwìßÍûû6Ý/?!½fÒæû:ÑAp³š)²ÿ HI@(ƒvF7G—þv}óóB›MfmþêIçìÝ7øÀ]2pO!¢Ó=mÀ´Ÿ9ÔùÉÅÞ{ºs ¢È®AÁ8 _ ¹5]> œ„7•küÿÒ>M4›bV¤4  Ra{(pikt¹«||?É3ÍÛ¿+ð{`àŽÉ""ú>Ó3Ú~m«õÌ¡þËOÌ÷žî 𘂀Ñ]rwú™Ý3‚ÇLó5»iŒ¦ó¡¦ð/òêÔÊÀ© ¶w.m/ÿíúæ mnï¢öÍßS’g/´Çà»NÅMÜM]¢ÁÍ*J18õµC‰}üÆÍ/þxcçÍáVFìÛg»’êßõq=ìýïO±ºcÔ¢×”e‚küs. p‘ÄÄý\ÙÉ:ÃÇ —6Çïào±º·ßþž“<{¡û])Ô=²j8G‚}7×Qš)äã|•SòDõ†ÙµÑ^òºCéžÐ “{×iá;L!Eû%ØÊÅZ¦ÌF0ž? ¶1*ÉWÞv÷*Ü£{ÒÀDhá7È×.AáÈ=\Ê)ô\Ìç#NPδÝëæHÇ\çצ‰»Í»V7Ô§ýë1™ ðëÖƒÔ4 äêÈŒ I<SBMÕW.ÔóGôÜT.lMxì™î™nêÌóJÝRÂ@j€qDAæ’xžp:©Â÷º¡É$ lÿ8ÞP®ü¿ôZ]‰ð¯™ |ÕnN :ŒÎZЩøÐÓ÷'s”³y¦àpWt_ àÝÜ÷ êL࿌à´Âˆ‚ð£sœ‘Éòi/ÚÀoAãùàÊù÷hÌzõÔËÕÔSó ‚çjð8#H(™éPÚ1Áœ}oóm¾ßÏ~zþžè¾À£ œ6pf¡|möc>×b4aŒ4K  £Ý˜À×5Õß ’C)GP ×Ö@7“õ4¥…˦À»óv-ZŒ±¹(:ªÌ„´;Ð]?†àß7=èåâÝ´2ÈEÀ†‰¥ÝÒ£ç+IDmäw·¡èn—ßqzXp?ƒÉ°/ÌâMÌö¯m¶fÚ^šëþÄŒ’˜’c0Ã."íÂ;¾/íwÙY»Ó~|/À‘Ónµk÷ €Ž9éàÚ‹M4-Dœvý4ïß/‚Vþš;Ì,®iÒ&~M÷0ÁÁ‚Ù8º”.BaßÁóµéÞÑ~1€Û_æ  #ŠÖ|-3îfÁ¢’¼&Úu®rƒ”¹2{š†I)wç&þ÷€ÝKZxOÃÅÖDÑbDÑV›^LäÛøpòÐ~j€i¤)!3]Ζ#•]öÆãÓ&í™ $Ü¿¶f IÏûï§ÜoÐ>~;ŠF Z”,Q³Ùð$ûFÒ ¼• 3 S:Ç­:e¯Ðìõ#¼¶Ø™p ½:ÐP¯ï6抺ý(ÁueÞñR~½rÅ1N Bgf[Ö¦Ôœ.Õ¾¯í7øAPm`æãèX›Ñ–ô=0n˜?@sˆ¯®Zù†k¦î_ÛþÝxÛ6J€„Öcü¬®Öà ׿Û¬öÓ4=ѪCÙIÄì'TœÔÝ…f¡©ºìàØ®ó̤êßKPîZ Ö.Ùp Gõš^Ó‡'ws•ï‰ö‹|8ü‡à4'8ÆÝjö¦¡DH{yäÚø€™,Ó¶+çî~BP›À Ï™†óí7 õÙ”ð,ãËÌŽ¦z«nÕ´Á§ývk/˜1Eo1Š—õeÄÞùúN×Míx48…Á½µ€ûß4Ÿ5ÆÔ64oŸß~úcÀØNI_³Fª•Z…BõP&‚šìO!”Þ £‹œß!¼šªêÑ íÅNS^^çÞ%8Ð'Ì‚;o¦Œ ¢òS !àŒ€S2Ož6PA½Ó`ù=Ó~;Ìû¥@DÈ\LÉ€sRwÖô.[èÀ5:i¨9ç †ÞhÇ'޹k=‡­ñ^f÷( i€ Þ9?-ì"BÚîS¶RDþûû ìø vœÌ´™çüLBYÂ(©¼xí÷tæƒm/C¾@sþ¿¦î÷¯ 'ìxm™òÊO0Œ)##¬KÙcºÊ †ß~àÚ`?|€°åŠcÐ !§’ˆç«•t7¦ iBÈ´:œ*oºß"€ðœû­]ßÀå¾wÃ&àý2HEœ@5¦âϽÜÚo'°ö%2è„Ðc±Kß èMzþÞO¦1ZSИ ÿßtçØúåjûA½æ)_ŽHÖ1@J*ðýˆàÒ~†µ0Æ$"¤·À¢#Œy !=ºS IÚ§IxÓ±p°jèṚsØ þkem$0CÙ™•0)ê*Ÿ¢yêÝ}Ñ?F"ÈiP`®Íèa›ÄýkŸ¦2™<¿'S00¿L8±¤vΫpB í‚­+bÁ<±3¨o¢îîK$°ŸQ@éüÁÚ–P2ˆæ"N*‡h¯Œ`š6SwâÓÂ^ý¡Sx‹ß„u÷õg ¹{ùõøû¾SŽáM4bÇZ„¶æ)?]Ü®œHëµöb¶ à7Òísm ”ŸnQÆ)%^Gø`í²5^[?  !|4ÕoéÁ€ˆLaóVŽ,U…† žœù ¥½ÿ½{ù÷ž”ÕÀ×"[Žh1JÛ„œÕ¦Œ\‹|Gðe¤ sÖÌÛ§PÈ™VDíw©¦ ëÞ ™ðŸ ÿ“2Ô­UlTB#i*q{(Ôº7ç8[è'QG QÌÇ ,bÅ’ø‚«ÊÏÈ«“×ìÿ.Z˜ô 1rÌ;J½íÀ8€þ ”€t)=^ŽÀ{ø°#›(ŒK;jìm-Wä5е”ÈS ‘)ä©@žKdJ™ë2¿úc‘½¾®ä¥>e+‹äÙ#,>F‹%1â$FÔâˆcn_f%ÐÚ~»§X­³ü$Œ›ÚîÖD®µ3l3êÌâþ§vnÀaGb‚ ŒI] ˜ ö3P¦2 @" ?G™u`–Ïœ€òúBÍRj×ä­â Y…FT J všC¤R(h%!ÂM%®ý8O¿~CÉkÅ¢ÛZ]þf:º¼ÈòÓEÉùCF×J<ÍÁv8À[âVŒ¸•€']{?­,#ˆ‘Ý´¨L Ȥ´ï–.-b@ôú°“hýPðÓ~ißy)4é%„.qF'‡1öä6ƒÅöû8Qî;xÐZX°³T@fZJ(%-ðJaM‰Eöú5)¾' RFÀ ^ÌYaOo*ùƒu%ß\bü©³Qòüa¦–¡ %Œ’©À˜gˆ¢QÁ,ž±‹9c×ζ€|öc™µåå'¤>Ц˜&NÈB :?†ö#×—®–îÇ`P8 Ä €¡K1!³'•Ý m;1š’¾ýn1ûáª2³ ‹TBKS€%¥Ý6”X¿$òo¾+ó7„ÁˆngÞf¨³"e7€^•òÛkJþ`™E?sš'ZÔêH¤˜ŽÙºsl$Å9âVžD ñ ÌZ­nã[ÅÒ¯>#ìæ˜bL€DBO þóÂhìƒ)x W–ñ«Ô€ÐÇÚœÚY {ÈtÀdz@k`/V7JBdùX@ -‹Ï±+)r)±)åæe™ýÝ[2-3Øâ´XißoïKÀÀ9Ab€ìm%^»¦Ä÷ޱø™S<úà<• ‘à<3F+äR@d<戒qÛ¯§ÌZ – Fëvé—P#LAlJ˜Ä‚œÔ€bõ9µN”„9òLb[‰áe™û²Ê¿–³Î‘Ú«jþkÕþ|d ï5w$ˆ40º¨ò¿º¢òogчN³äƒsRõ#ÎE”q@s(Í¡s 1–ˆZqðÈ>Ck`™`tÓ~t›”ßû ýÄŒ 1äXÑK5aò¶Âmpsåä\GAÀ¢.èQΊI .‰21˜£€Îa 5g«t %æÖ+a¿B•‚Ö"Ë!òÛB¦—Tþ·Uþõ¡1«Ôz Õ[µnÿÝzz¡‹¤Øb$+`û‚ÿ犖ß:N£gO«ø™¾”31gˆ¢Ð`V+dRB¦Q+B (º‡¬yؾ¤[uGÑ30œ̃‹9l‘úÀÐ¥ýо½¢ÆÞdv@Ùa; 8à|¿Fq˜9\|“0”„y& s £%ˆ0RAä²4ÇŽÙ;*ÿþe%¾¶eô;ÔÞ/Þýº/£í…Zþ~¡’ܘõ©üϯjñ­ã*zßÛ—ªq†(Ž@˜¡ÆpäJBæq,ÀãÈ:°ý@´ì\·Ìÿü®@ 8Ú„,Á »Jˆ 8GðÐ~™€ÚDÒ 9¹I €~ñäíy sÈ2‚ÁH ‘[g ªRõyž!çØÎ…¼¢ó]RùßÜ6ú"±£Q¾”šyÇPsQ­wÔ‚e ÇiñÛ¢@LdlÌêLþ?®ùÆi=LFO÷„L’X"Š"@G ”Á(\pȲ,Ôã].x;‰,#>‚Ö ™ˆâ,ÊA¢Ð?l]²aáØ1 ð9ÍÎnù÷4˜YuŸÕh?4€·2  z¦Å£þBÎå9$]@¦0ÒªLgç‰VyŽñpŒQš›U%Þ¾`ò¿Y7êMc?w¢QÙuÿµjßÞè¿{çˆ×2T yå$E ¬FH(l}éÛÈÞºlÄÙ³"þèQ©Nw¹ -ÇZ*‚T*çˆi¿¼Ú=˜k@>„ÖhQBb‰3†”Ióp, l÷ç>Cîy€ûbÏôå;€Ìškœˆq£lî£Ñ% jb H!a”1"ÏSŒFV•¸zш¯Ü4òûÚ&n€êÃG>à!ðÎpQ€þ…/\ú¦Ë1K\Ô• b‚#tÜ1V8Ž·¡/|ˤoÍöÄ霿°,ä©™HV+B)@sÅ!”XÛ~ÐÈ‹hcM–)­I¿ßÏ]h˜½Âxt¹Z ¦`‚ö`m˜|TÄòÊ:}2Gº“bg8Æ )V/C|cÕÈ¿“À˜ÙdM¼¯æ} Qwø&U¤ð_Êpe8*“á4ƒ3 yñë¶vÁX‡úþÔÞ1ò=§²èü‘\ŸI$: /|©8´àq ÒßÌJÁÅÀÐ#‘%|›Ô…=H=Sôû„.óˆVCŸ±Måš| )ìW@µo±³3ÆšÈ×/C|ã ä7%0dUHçVÐA÷×Ñ ã}‘zmÌ.h?AõzVäÕúî™·9†p«PߺIÔ÷öþcþì¡”é%v Æ#Í!•‹ÐdP€1ˆALÈ1è`Ëk›ÓTU*Ø5*ÌXQ-2ÃìHá@4#2h!ì·îwFØÙa#›— ¿ù.Äë9°?Måû!žûõ×* ¥hî•ý^‹£ÓŽ%axB9Fé©Ñ75Á-àYÁTêÉÿûü}œP·gD6ÄÎÖãtôäwÞ¡òk#˜Ôê'ñÜ&ï¶òˆ¨VÐòÁß ø&¯ÙÏjuMà3‚»Ÿ[úÆg>·ï¢ç0–Œ €­KTýå*ÑßZÖêC'wä3 ©œíµrDq„,×ØØ–ú"—š;|Ÿ†‚ËMªÜ úµ7ýþÙ[Ꟶoµ1òÔÅ·¨úòÑW¨– &Ao’~ßÞú‹&† )9•Þdï÷ú .ë¾êá6wï–ÜØÛ^{ƒXFeV‘˜ Lþ¯kT½~B©lÓsÉâÔ˜ÍË\ýï«LýEñ²è¶wÏJŠü1j¿cÁ€ö*Q½ÆÔw©ÁLX)gÜv²‹ÏÃŽŸÑ›&ñ~HçÝÄþ~:à˜À#]~!*2}L(†¬ £ïû7¡Cë·çžéA3€¯œD¤Å}ÜL—Is×û1v¨ê}à§…t¡ªwô Õ¥«Ë÷|g‘xÇÜ3¹üAŒºÃ£î#¸ô³›,ç÷[Ó÷~ý!´û¦{Z.>$o,ÀÅÎ.^n£þ õ—}ûí{ôMÙ»0‹çKA=p[PhRü,( 6Žj”Ñ¥—9pÿG¨›?½f9ÃÅ¢õ§?{ï>h'Ð…J“ã×nˆ6B=Ìò½÷0s‚>Mý=0›¸GjÒî¸-4%“38sÀPõ EÝÄ…fPy÷x8|€`BˆïˆIÔ;È…M@Ûý¤svÂoÞ…7ÿ˜Ò¾51A‹"œ“è6f¨†ŸÃQ>'D¾ô?åO#qLsOô MPqq¨ý‡têßÓ›B9ΞïÕÃ;ö°Q“iðß‘tZÁI}8Îï;ƾ/ÕdþJ­÷°˜ ®Šý¬™D=U ðÑç”yXéN΢-øOMÓ½|°ý~iê“{¦ÿî¬ e‡‘âIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/bookmark_add.png000066400000000000000000000123731217176075400252200ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞÂIDATxœ½›i¬%GuÇUÕÝw¿÷½7«mÆ3ž}lã±±M†-Ì€E! ã1AŠ)Ÿò!R>DA‚Ø&ÊÇ(‚$$ 9DAÆÄÆÄÁlF`c{Æ3ãÙÞ2ïݵ÷ªÊ‡î¾·ß7öLI­ÛÛí[ÿÿùŸsªNõÖZ®U{øA!¨ƒÙ¸8ÿw%%0€=ø5תOεú¡¼œ4%zô‹³øúýë>?è%§«Uçþ0Lç¥Déµê€¸ (YÞÓÕj:{~÷÷n¢±íöñ ?ùï§¿ùÄ“§?îyÔ€H¯• äµø‘¼) ª5rßÞöŸ5¶~¢Aó¯aæ/Ù»ÿ»g;â7µF. rÒ®z»ê?²Êú§Ýäö›o¿ãý´?T@í¤qã'k·Ü<û§Z#²“¨«Ý¯¢]+dÖOaïžöç:;>Ö‚9H!]†Æ;¸ùŽ7¿k¶Ã\׈„kA€ÿ°Õ¥óúK÷ ¯â0뺼®YU;+µsËÆæ½›v¾mñ9H‡ rë—‹üeéZÞçð,4odÿëï¼Ï¤?öüôPëC~d§†ùT3øÂW&¿ü€B „@å l®–¢É)ˆi-¬’/Ý/”ç0ç)67ªj[½êìh5ª;gÚõ›šÍæ–v§³®Öœ™©5gknmFˆÚ¨l„ðX‰Ë2ð)Œ¹–·@dÒrf³Ø0 ã#½Qôb˜è£~Ì©D³ðà#vXÆðå„”A®žœe+:HõàC6xä ˜u×5*rkÍSÛ;ÍÚÎv³¶£Õj¾®Ýél¨5;³õÖlÍ­ÏHYí€×§² Ò«&`F/e¾/œД姉˜v…1 @íFp;y°L@GúY°ŒzvIüe¢ÑJ⺃ᠷ2Nw‡Ã£0y¡DGÃÔ¼$œH ‹ŸĆž ¾ô9ÜfªÙ·uÃÚ¹ëë­Îl½5S÷ê3JÕÚH·ª’)Z3‰Þå\N &Î:'ä Šï—Ží…ˆÉ7áÓÊ\Ixù§ BMõ'fäÄ}ˆzØ #'ð»q0êõƒÞòB·ûÓ_Îwÿ<ÖvÉq%7¼eÿ®‡¯ÛÏz¼M‹Ùü¡6%Ãûù°uzÓÙVøílѹÔ4kŃ *BC”îËË Â)‘á‚Ì rëàm†–ÊfdVãéÈë$Ãõ›G§ÖïZüùîøÇ?={¶ÿYG 68©Û½Œ½b|Niˆš¹LÉ« _-@»E†²à¶  äëk.H²p“ÉÒA¾i .}§¸TžjkÐIvTj¬vp¥Ü4œHÓûñó/þÛ›lòû•uÛD¥]G:t^ž/:%J@EþKã’z9-OeÉUþ?­†29J°ü7,ã¼;qü¿Åh²Ø×IöL§Â! â¥Sœ9wtéð¹Á?+ÉGI¿šþíØm>‡7‰êl›J½žù“‰&ƒ“Û*!¬Qµ_/’‰(+Ýo§¾[TˆìЂlK>u.7L aË›Õ„Ê 6IñW¤+§XèY~âÔ¹¿ÆæŒ#©8@à*Ü_Íûÿ’šcòÍ»õüäF‘´g¨wšH·q/ówQ²È¸WŸ,»‡)´SÀ¦É(Y||é»f-°%M® o¼Éh„¿2@ Osfåå¥'O-?â'易-ÅE0º®¢úâ‚ÿÆœoÛËû5F ã„úl§²!›Ì¤ÃL®¢lÑ¢Ó%7°yc<¾O'Á²(‚” (,?~–ÌRª(]¾‘ÖUnPzFá•õà¶ »=Âþ'8ÃÉ•cKOœ<÷÷Aj8’è~AÀ9@yêȹà:a޺Ǽßåz5ZJ©Ï´qsYâ•R\(üRç3ÎRQ1©±fµ•‹f§?ËV-î/ƒ+Ò¡¸Ù˜CVòè/'AO¨Ìbe“`e…d0Ä æ9±|üì÷O-ÿC˜ïgs̾zß!ר¬’¸K£ôhoè›--ö¸®'ÓØ °¨Zp2%˜$ËI’^vN%ð%u”ƒZ™Œiù’ƒµSnPct> f›óú‚·…uç{=ôh€ ÎòòÒñ3OžZy$6öˆ’¬äà—€>:d³”bØ(á9p¬~Ûþê”xû>Tílv¢¾à5j]áüj(ÜDaÕ²[¬¥{þq™Òñý?šã'£F£Úä&ËÍVqsõ¼çº­<¸cE8á/-½rúû§V¾’X{\‰1øå|$“Pí—»è)8Ñ ÿó»‡^‰Þ¾Û|¬Ùî¸q(Q·ÙÙ,öJ`VY¶ŒFœ¥ûV©Áž·øÄç?ƒµ–òж° ¥BIÅ£_ù:Ì&æðÊʉœ^y$µö¤,3±üˆ€°ÎÁ‡¬yøAÙˆ¢ÎY@¸ Nõãï|ïð)ûÎ]éÇ[íº› 5Bœêl&ESLs/ÐìÔNð*"¦¢{™kyyñE„xóüÞ%”R7lÝÆ!ÿœ:{µ½ÊáåÞ‰§ÎtÑkƒ(-¿KO 5™;ødr ˜wþéAüøw_˜ÿ×nÏ” I†+˜(ÌÆç&ÏÅÆ–öKÇÖ–®Ç”RVq~ú;¥ëb‘àÕ}úAŸÁpÀ`8`4š”T[ž[êÍÁŸÎÁÏ“¼Böº\#ÏùK$Äd1á°œvƒÓÃø±ÇÏue%ˆ‘ »Ù'œÀmçƒ[EÆ eb¦¾'=JBÍ¢› i-!!!Ñ ©É¼8Ö<}vå“Y~)·ü"Ð#{ñB|hõTUÅg %¬ä8ã)üÅ ~ê±Î~miÉU¢ƒX¹:'Ÿgù2 kÁjk‰˜Ú¯€r$®ç"ª]OI+ ‰IHuba# rbùBöÅ['«ÀŸGÀJ(HXθ’áb˜<õÏþãÙÅ¡/ⓤv¡RZ»L0ª„À­88žƒ¨@ZIœ˜D'X,Vbäj˯)û‹° Ã)ËQú£Ç^ZøêÙÅ‘/Œ.YqÊÊe c¾@¬˜¶¼"¥’…ZÇsPžB:ã´›Úlâf…°LåyÖý% ˜"¡p‡åœ„yW2Z‰ÒŸuý¨'Šœ¿Ê ÊàXmÑUV_ë“ó〵ÈZÖ/å9(W"U–ÄMIeA†IÀ»$ø‹0EBL6dîç¬e±ª„œ­yíó¢üšÑŸ5ˆ)K ôqÀVò;Tz„EË„”‹%Sìe¿$S$¤dþ44Э+Ùlzªv¾ü׳F`¼Ô=SqÀ©ä]U`¥Å ƒš””Ä&ˆlª`˜äùK‚¿,J$²ÑSlaÔpëk®’vö|ù¯iý‹¨!ßox-´MѤ¤6%5 ©IHtŒ‚f£¦˜Œl/«ýZ+CÖbÚ®s£«D6[uqÍo¬9"¼÷™Ý¼Ôý%]ÓGÖ,¶jQ5‰¨¨DU€kè4Ú옻€HGÄiL¬#b§1A2ã¶ÙqÝööWTèûýÛÏ^gŠŠyù2/„S¯Ô¸iç¾gÿë¯}ã• G€;ã9[‚qâ¢L_ËiìT¼ù®``¶9G³Ñ¤^«S¯Õi:M²‰#b"b”rY â€0 “€8މEĬ¿žwÝón´6RX‰D*@"‘Væ{)$­F‹/ë‹wÕ+@RB»ã9×ç°êVVO€¦zþØsì½kGýØämbsãz6:Ñ^‡´:C”Pcˆã˜ÀúCühD…Q€ - KgX>½ˆã88"›#(YlJH”Ê>¥T´’6ieŽË" _6“€² <)6u<§3öï5›-}XÆSãq?f´2ää¹Wè‡=ƒæÚs¬oo`®¾Ž†Û@I£ :I‰Ã„(ˆüÀHF b¨H‡C¤”8®ƒrÊU8J!Q(«P(T¬6;Æ€Îcä•(@ÊXd]É­ WÕÆêrÚX 9Ö’†) ºgñ]%ÖZüÄgi¸HÓkÒtÚT©bSHâ˜0ˆˆÂˆxCW"G)¨+LM *áZ´cAÚ¬Àa-¢XŸM@“Žz¥. ,ÐTj{Õ‘r2P™¢ébe°âÀZÐ`#0 Ùl¯oú¤iJFøžÏ²³ŒDààR±5*¶‚Hi ±]]…r ´ ¶aU‹ô\„«J"Eæ÷Æh¬6˜X“Êxœÿ®„ H ¢í¨®“4µPKV­°k\+ˆ*RÞ2˜â EÏ j®çâ86š$I#M5®3ÍÑŒÚTjÌŒE7M¶[a®5Ë\m–-sÛX×ÚL½R§êUñ”‡«¤ÌÀdà­±¤ZãIº[¿<JPXP f:®Ú88Ýry Ê'{µG'šÄIüˆs~öýç6oÚþ†9¯Ãí»îš•Ê+é€TÇq¨Wëœñú<»ðcú^¸1ïœe˜öh{Mæ6´YŸaYfå]˜P‚Çs.€RSdK›[Ž33µ‰IPËVc<¨´À­a $AL2òI|Ÿn$G£àù#IøäÈÚW>tæ©·ß@#ð6JuÇ·ö–ë½ú¦JµŽªÕñu¼Š‹DsÏIÉÍ¿sëDTªÍ*µZã%¸Êá‡_ûi>;ǂֆÁ k¥»ŒÍôÊ ZÞú_\ YjBnk¸²²zQBƒt ¾¼&Fâa@êûè `øúHä¿ðR}¯oÌa%H\A$$P™7úñÅhøÓë’ð7öÆþ›7‡õuÖ¯Wk¸õ§O/p½¿ŒªJDœº¢V­Q¯×hÕ;X N5Ÿyåðd3×.ý¬Ë% Ð’j{UJ¶«WÚP߀E }Rßǃ`d^FG'Ñã]cžS‚ÐødÓÕÙ,SUZ‚S&ýöÙhøÌ IøÖ}QíÀæ¸Ö‘Q@¿7Âh› ‘kàU*T*ªÕ*µj6WNlŠ)®àuºË!`¼>m-ª#ÕW ²: …ú¨Î Ã4ð1aÀh8ä¨?<~8ÿgÙšg…`è B²ét—¬L5"›\I²Wàš:ÌXˆ›ô›gâÁÿmIÂ{ö†Á]6ôšXÀ³È ¸®‹çyxžGÅËçÊ™ …{û¥'FW¢W@½£Ôë€,Ô׃Û@{èÀÇ yy88s(ž\²æ'úŽW™»9C&Ö×9¹^NJè ˜qaÆ@rÄ&_?%OÛxÝ_`³+W ”Âq\×ÅuÝlcÇ#Ò*î«  ô昲ÙJÜúY¥6‚¯²‚î­0êx¹ß_<ߟG?c=G‘•Ò–sðð€ÌòšÉÈ "«:òû9³.ÌjAbÀäë¥R ¤BJ™û•ßRzwæU·ÉÛ Wë"+€ƒ?¿À±nwùùÈú4úi#8çd`úL¬ÞgR¢ŠÉº:ýºI¡„„I1¶ l `VD¢”ÖÄÔG¶#2{à_½ÊM€J%+ÏÁ·äY÷¾ÐôÒçýá3¯ý”,ªlmÀÄâ&%é˜ÉÊÓš‘9W[ʤú“‘9†6d²Øœ/Yc1&ËoŠl’£²x2œ~þ«! (‰% Ä ‘~íôpùi^*é+0Nöƒ…ÅLêrÅœ¾ð¢×r"ŠøæÏË‹¡&5h­ÑZ“¦š4ÿ—éøíi…½*`RíK¨hÉ1Àu²)ÒZÄÊûùå¾Ë["Jäÿ(Ö‰%!J"¢$ÂM\Â$¤"k˜Ä÷§¼ÎyÑvQò…Ó"ä¯i‰ ¬"³n@&Ó󀿚ÿÿ–ˆ°€i×Z4+Mv^¿­6^ËÉR`¥‚2 !¡¦*°:Ã\²]‰B&…Ñ^é|Âx¦}å¿T+žó¿Ÿþ$Gý9¯kí Æ˜Ãiš.¥iº<+ R ­õw}¯AVqv5lj°ÔoÑkG8ÂC¤vt^]àÁüþãÇýàÁƒÝwCÀ޵qÉ™ÕìŸOé¶c\€ÌmywD¶^w€V«õÃKKKß3ᇹãäÅ Z+öõ[tZõŽç® iä³ÂjMØ´Ö" ÜÓW¥.¶"rÅóWßõŠ'__ç½Gû¤iDågov\I ÂTÞ õ¹] „Ëo5 „ÌèâNíÎ++#,´ˆÓˆ¬Ú|ö«jŠÄTDí À»®§²“±]å3Ù¶.ý®ˆ€x²¢¤ÓŠ)\-Xhd ͇u!ÈÖûÝÒ€wLï=Î9´x|Um 3Uwil~ºó2£S@»kïÚu¼÷”e‰s«§>Ô T ‚¢bêejÿµèÝŒ!„«šÁ;½FUU›Â‹fÆÐƒ4»-[ž_Í„¾­ë̘Æ_˜ªý¬ðÛ>Ÿ@M½½liÂlzçš¿ 5Ú¾ÛÝðÞ¼¿òµfš’í¤‡™0ˆÓ€ôgìÔvÃ|ÊŽf$„ Ô̆ϚÒD€©¦ü ~ eö5êú§!—Øòv€@Âvò³Édë|aú(ª1ƒ]ã›ñ\_?ø)Š“ÿBù]×`„­Øîgb|hœbý^ðAç×<Ï*ð=$Bµ Å™ÈO>ÊúWÿ~ýiÔw[ƒ’úÓhDP¶–‚aÓ”;ð=3¥ ¸œòÔ—P‘%Zú¦“ €ÞU”üê<™á÷‚lº5Ëÿ} Ùô ZvvÎßS*\]ü~ý01­[~Tσøë2Õ\ÿR•—™BF7? [|`×(O qClïñòÁƒ’*œnøúBfíá/YÍ9ïýæ9™yÝ5 !€²„ìîü7PJ‘¾ÓÝ A-çP²èË¡«ƒ"ÍÎʶݟM~¼3çeScvºî»î¼÷ˆ²Tç¿N˜œBÅ=’c?Òd)`A…³ˆé4 ;F’iZ,3;ÛŸ&CScò¡ÞýmÄPn·œ âsª7~…ÃìyÑžê †´ Ø ¨Ðrž –¯è‹²à_øcο}޲,ðÞqêíœÎ\*”@d4±MXÚ{€ååÛYXØ¿é(gy‚ˆWa—PaãYÂúS`bâƒwBx¸ÌÒ%ö2@é DÍ_FUÆÙ˜'^xŒÓNòÊ›/óöÚUY!^Õ¾$hÛ‹Ü~ì=¨ßG§Ýgn~/ºÑ˜ÙbIé…Iµ[ ¿ò”_Åtïí²'ѱݽøfoJ."ªÄ3nÉâ‚â¥s/Ðßßç¸ÑxTóc”a~~Ujþ×Ñ:p;Ë7ng~ Á£2PùÝ Z ¬>ˆ °{ï@ÇHy‘ Ï¡u’÷ƒêˆ ´\$°¤„P 鳬—çÞsû¾;pQ JiŒ1´ÚŒ×&*ž M³û²™)‹@Ø-p€GÚÖ¿‰³=¢}GÁ½Ô‚7 êÛ5ñ Z@Þðå_BF¿‡Ñ–M™K±”f:\ÛA&„2 ƒiÒfGé+2?Aû $TÕø­ ð°ܹHó®p[ïñ ¡B÷Žc;%R @w^#ä´êA|‚ºYãkµuO£ì<¢ûèøV” âÿŽN*Ö¨–àñ%袦¹.8Dˆ §‡“%a[†¸Q*';Ò.{²ÅõñTó/•Ê}$D{N üi$x ¬C`ðP<‡‚ŠPvTÕ Èä!P Õº·&LP±C' t¥qR!‚×HQ“O«pªˆ‡ 6Cc`=ó ²£@ú*¬óš¸jxó'عö/ ¡§¢E¢ÞR­45éªÎÅC#ùS= î HŒ¿aöF°7CÈ@XAÅ YllÑ‘Fâ@ˆ^;œT<¢A$l1À¦°‘{²². Š\_¼ªF„•¿—J¨î&L>%Õðã¦kÙ2…ähuñ´Ýòú KD ìÉšR!ÅŸ€Ý‹J~ ª¬#D,˜Dccƒ©4ÚkŠ;Bp8 êü_ézWK'¬NüfúüN}€ì°óÛêrñ3ÇEÂß’0|?n„„.D7ìC ù+ Lˆ¦¥šæü*’= ’•~h#²âq :ÑØÈ`bƒvå Ø@°‚S/4›)± uì{âÉ«Pg‰×À•ˆ¿òKw.þ•{—ôž/ýmÊñ½²¢Aí{ ÊWP‡âyt²…›š)Ы¦Z/äBýy|˜ƒFÍî—@q@Ç c Új”­ûÜ¢Þx¼rêº÷44†e`}ÒØþŸâÍìÕ„þùŸYÖ?ñ±ÃüÐ]û?¹w1½/1þ–¯ê¢8Tgµå[P¾2lô/®˜lÖpka7«•ª!ða³»¡Bå³`4Z’ƒT(+¨H¡ŒF@ ¢… ^9œr5m}Õ…‘ÂÁ…‘Ã6Ãá5pÏ]mû3Ÿ:vè½·wüè‘öß9¸ÿ!·ˆ!T àT±äÏBXåAÅ £Z¸@ëÆÞ©AQa«š¡¦Õ µÙ‘ò ”$Ø¥†!æX+«ªYx<‡ÃK*"iG£q^¸8v”n6!Ú"Dú¨ý¡Oÿõô $ÝÃH„Ïz(zà ÈÏ@µ‚PÖ«¨±gUÛ6PS¤Öý¢^YñŒŠªvVÚ¢›ïk@­A|F›9FåˆVÔ!1€ nû›˜Ã7äâÆžxöq&e¨CÛŒËA`2Z[äîè¶RÞ÷ž»ÂÊÆÆÙËÞ¾yeÿîÄ÷þÚýËÿ4=|ç‡ ùyð#0¦Zë¦Ö¤¶¿*Ýô«Øöþ¹³Âþ?{y}°Áëk'… ’P“œD¡SS¿&YLli%1I¼À{~€›n¾™ ã7GdãŒl’QKô>ö·qþå³¼vöMÞ¸xŽñ0G*P…ª]I^»—Y¶±þV%Ürìf~ðƒwû×ß<õowŒõ÷ýå¨û™ŸLñcwwYwz½P6Ê2+ôTÈéÎ_i¡xìÅ1¿ñ Kycw¸¢Ýj3×™£ÓêÐjµh¥-Ò8¥mÚ¤ºÑš <¢„(J(tÁùÁŒÆ#ò7ð,¨}Ûw ”I>©‹ ”h´(TÐ(QõB¡ÐDÚbœá¹‡ž¯~ì›ÿr‡)$­^<ãË/~µ|ôµóý/[œ:xÄœPØ­ržì%ÕeîôÔÅŒß}ô ƒ^ÉÆ¾UòN!𳤽„´—ôb⹈¨gÑ ©à"Ç$ŒfFÙ€,“å9EVàÇ7tŒ6†ëäÅ„¢,¨\IåK*©ðTu¤0Ž`=b=Á —óͯ=Ξ;ûG—ù€;n»M­ol(ÀX©ßýòéï<õÒÑ¿ù©üü/ü­äWvQX¶øf[®Ñ!Ë ªÕ£sëØÒ°–¿ÅJ~ŽÅ|‘=s{é·útÒ.±ÑJƒï0Mæo;Æ:•8µCf‡uN_,ùÒ“ë”mKždxë: U¨È|Ƥ“UUUP%y‘‘ç“lÂ83É&dyF1)ðCŒjf-F n’Ë–@ $ ’úž>üÄŸøgïÿɵÏüì}½ŸNºíŽ”afçUC~Øjä7e, uð¹/U ,K’$ÁZ»9)"è`ˆBDb¢2BO,j¤Ñ.`Òƒj :×lÑ‹ÕP;Áš)8O°Bp@*\@¨ƒ‘‚DD"ï\$µÕ¡0­Ä·ß¨ðÿCú¹¥êü­õÇú÷è=ó[]ÍMÊÛŒn„€òµ5}‘a"®¢ªEZÔ”×hjsBÄ—Uh’QB§èѵ]Ò¹º‚éLjI’„8JˆmDd"Œ¶U°)|Ä$|@§ u©¼ðòËòž' ñ^6„ ĈX©‹ø JGV´iÙ,Ÿû‰³¤'JæoÝOðáÊ[#7ßî2<3<¡ÑAMu ×% bJO› >@ehûŒNdçHbæz]ãõŽp ·L+nÛ„ÈFD¦Þ(ƒb“'×Í!ÛœþB—Õ^ër8}ö¬t;“åyKÁa¥TWD,¨p`…¸‘•ª.WM§’õ—Íœ  ÆCŠÎQ}߯qHï¥Êשª6•[ /Q–ws>Ï93~[œ¢þO5kÓµëÕF£uݪ—ÅèÆ¬PV# „@$5Ÿùâëÿüž§¯µ$Æ%Ü «G——_Ìò3'F0±ml=̤ƪ DPÜøëT7ü5”Ÿ@È7[ÖÍqxVký„RêÖªæççÏrû•áCTWÔÊíãô¡Þkbt´ž<ÿ_>ÿÚÿâä;‘ëðÒ«¯ÊâÂÂêx21Î9¯LºØŸKSe-&( µÊO§Ëu|ë£ä'>‡ÌÝŠrÃé¥Ö€ïO_žé÷ûg/o3$uD6'ÃdK[¼'Oð) yÑ+íg¿ðù×¾ö¯ß|§r]SopumM€·sqšøli±mƒVèhZ¬  G>ËäÐ?$èt¤ÜàPO|§ßï¿þާ-¦3ïBÔäÞãše|@*”/G’þý¿{í‘ÿxþZdºžæ¨÷Þ_PÄó=Ý-uhF8ÕdmåË/ßõÛƒ›>¤Ÿ?5ßUO{áÕ……þµ÷¦™œ\:;ç¨\Eå*l£J|1ø¯_9õÈhåZoq½ÝᲓJ>ßûm¼ÃT£Ç¿ùŒýû?þ«ôøøwÝinG1©Á+T¥#8ç©ªŠª¬¨ª’Vè0§[åØ\—×qënÿ³O† ýòÏ»ðO0¡Åpý èð ?ô«ŒÞ­Vûá¥#ì­>3dþÌ\R`»†¨ -Ãä|EÛÂrûÆLîŸþܧÇýºüÞÅo{§?!îW?{·„_ZZâÆc7ò““áK_^­æ«8ëÐÓ’W ¹·ó]ºq0îçá-ž¾®áË?ŸÇ¥å¥OäÕä†Ìe”•« Q4CŒ,$±U7ì=”¿öü©x‰“×z›ÿ ™ÿ[º#‰IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/bookmark_rm.png000066400000000000000000000124611217176075400251040ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ )ì2Ûh±IDATxÚÝ›{¬×}ß?¿sffßËËKŠâC_"EY”¬È•ãG"'vWIå-š>×¶êúoÑúGQÀi-;(Ðÿ´€[¤/ ÚÄ­mµª%ǵáXª$’)¾y{ïîÎÌÎÌ9§ÌÙݹ—K…RH¦î³³3³{~ßß÷÷4Ýí>û™G¾¾rêÃ÷ÜuŒxãÁ·Þ~]k€ýô‡pßx÷ÿ<àucP'OtÿAë¿Ò¢ýO ÿ8qúô/,õäãÆ ÚO>íGÆtÛ<þÈãOöô3ýOVX ?±TmßZt³ÎÉGN?ù‹tžôM°)¥Ÿȯ€µtÿZãıþo{Ô}7Y î•í<|¤ý·—ýj+_'àlÉ›Cz:áÔé§?Ùmó„±w?"¨{¨ýãøà‡~‰ÞÇJí»¼ÜÙr _3¡wä×Z'öÿŽ)°w;"Üm„@½0püpû·v?ü™E^ÒÀ™9Ö–çÉ9è>Å©Ç>ü©^‹'%¼›QÝeíÖ¡›5Ž?öÄS¿Dç)Hß[ì9¸¢dD¾ ù˜þÑÏ4~¨÷·ŒÁN}ÁOf¶ìö_ß}ü—{cÈnx¥Ð¶kæçStã‘ÇžþT§Î£¾F¸+,PwQøÐ:t#â裧ê9:Aòæ-„®€á,ȇì:úËãö>WÜE¨»@íé_+ ì±CíßÜ{â/í"ß„|£¢ý¼"|^Ž™IXˆÏCç>öô/vêSÚ¾^ µ@ðL¨žÏ@‡ ìyg™ƒ™@—Îr² é€<^g2ÞÈãñ`8nnŒÆã˃ÑèÂ8ÍߨL&çÒ¾•ä\È-7¾ô5Òñ"ñÈ„ûûõ_9ùÀÊßëövÝßìô–š~3jöµntK!ÃèZ)ÌT@gçÞ»Ë)ÀfåäD-jú|åÜÝ ?$‚ Sš’Dþ‚èóÉÀ¤%8ÙL6qI N²d¼¹5n®_ ¾ÿ'×ÿ0û?rúØ ûNÿÌn¢½s9ÿ¥® ÌácŸ¶î¦3Sœ «·S_Ô-¨/·ö ³sER¹Ï·$¨€‚ò…MˆîƒŽ.+2gˆÌ$êå£Ý÷/í>vã‡Ç³ïýq „•@‚¦Ë@Ø,Ñ›æçTRÔ²e¿=ˆÜd¡Ü\p7 bë‹„–jdX`&ó¥? Už™^ª–ÚL^Þ£4gB¥öÃæ÷^}óß~Øå­¶ü ÔºMT`À^ ©+‚Šÿ%ç*¸ÅQRh\ÔŽ( Þ%4Nó¿áæqwn†~¾ÓlrúÞäåwM€<ÉÉV/qeíÜêëkÃhEëÿ\ýœë=}Üþå,}HêK]jÍfiOv2ONdA¤•]«Ùu3Å-H#œ,xÎ{ÿª S°¾t®|n™+ÂU‡݆Z—ÄCŠK\œ]ÿÖ¥µ:Êì ðéÑ׊åëÃüÌ(×ö·Ìñ"ÅØ€ ÞF‚Ÿ¦º“²•Q¹>ÀOfv¿©C•À˜y¡äL)è´O`-X7ï̘PS¦÷EKP["Fk›¸­‹\Ù8·ú­Kë/Œsûf H§‰Ð„šú›×ãß·ö‚|ìϬŒ²œæR— ¶R3Ũ¤«ÈŽ|K¶›óŸå÷ÅÜYVÁª ‚lw¢N—ŽT‚ù@ϳśÀf®Ún»¤ƒMÒ­1Ar…‹o¯~ëâÚï&…;(R`P` ÐQ€>»–ü{^»`?ú°}6ä~=^-hö»„­]岊_˜Ú¥ñŽ3+CÑ´¨qm-2‘Ù±JáéýUá¦á0(k ªyï¯æNÏX¨-áT›dcƒ|8"H®qaýüÕï\Zÿ—i)ü¸ ¬MMïZ à´"\ç6G±=Øáá0ŒT‘Y‡ntË º•1ä[o–Ÿ™¤"|…U§ævqU.ÛµkO‚ÈFå0©7)aî"ÝÜÄŒ‡èä*o­ž¿òíK_ͬ;«^øU`k €øJÅNƒ¹VDkIqa0JìÁ¶£P¹ClŽ"ÈÇežnR¯yW°’Æ:¹ÙAmsVîf&l»Ç-x¦ Œ-ÉÆ`2\Ø'Ùc“1Az³«ï\þÎ¥¯åÎ×ÂúTóÀTPe2a#).¬ÇÉþ¦œ¨ëBÉ&bRt­U†3©dbÜb²ÌÚ)Ðìèv<ïn~¿Ó<ìößrÑ2é(Ån^EMÖxcíÚ…/o|¥pî‚ÖªšR ×ßxçAp&Ï„pšwÖ†qz ¥N6"´É DªÖb<§û"¯Ì-<µs·©z¯»ÅµF7ÉŠ6ÞD™„7Ö^¼2øªqîbEó«ÀH€|V .ÚÀ4e`7°/7töµ£g~öØÞÏ.õ5«kÔ:K(•Ãdݳ`g"4GÁLlåL:?©&9ìd7‡× ; YÂL&¸ÉˆWW·Þzåòà_YË•À²¦ ®é”µÚ€­ÆuÒZ´Ç<û½ë±Üœ…l!ÚÀ°ÜŸš{šÑÇþØÞßXÞÕ¨Y]'jµbËA²PþñuÃ¥W„x3Åú O¹jžWv5”sÈ,¯ª˜€â¦ÁÑ¢4àp8k±(œÕ8“qck2\+~  +#©.d¬r•¨BM(œAáv?÷)59wö_ð^z妎Ðó/`¿òÅÙi\ ô‘fß${ñ߸*?wtﯯ,S7 ª¤Ä7Ó¿˜l­.3º:$eX§PÎyÏáçJá­-™`§™¶Å&YÙfªhÛGhºí: 8q8×p¸F»/|TG  Rç¼I5N¢qê˜K7V¿ ¼²°%V!»i©G±ïFš¿ø_Þ¼šýœÝóW÷­Ð´Nûƒ[˜'à «çVÙ{l™•Ý]t·ƒª…8kqYŽdØt‚K3lVಗì$ǬÈ)qnç† kY5†¡shµyp©VšP Z!¨@)Ъl •¥…ø²L€”«¿ÿ »ú£sê]{‚;@°;@`}R¼ò‡g®«O"¿qÿ}­æÍ‹Øsà, ®Çô;šâk8¥Pµ©… ŒÅåòòèr‹+,ä›[&™!Î F…el-ÆYpi0âÂ`DhkEK-%Ô•"R‚öCi)ûd8‚Vƒk)C£ÿô¦ès˜J¥B…Þ˜ÿ{OžÝ/­æ6ØF†2\'˜Íâ'PXOg¥PBJ…ÜAáÈ C’;bcYÇØBˆå 3–š@[)ºM)WRíÊ´Fœx"”Z[EÂmp &h tް®ey©uË m2÷䇛\jqÊç°ÖˆB´òy“£0–¤°$ÆÆ&8ŒA¡p´DÑSÐUІ5¥µø¡´ ”òÕxYɺ@1AÊþßí.Œø¶²ñ9BŒ, šZµÛ‘nÌòÇê˜VeÖá¬+ ´Ìâr™+UY€X…rkÙD'ŠTXÏ„-£Z:G칇àB„%¥è‹¦%ššRÔµÐЊºR„JPJ¼ºA-$Î2ö;0n{…Ń`)§ž9·ÂàþF¨ÕTЛÇ\ûÆ9l!X`¬ÆXMá4™Ó$V3²ŠM+  ŒbÕh®Å;…°f„ÔAáëg[t¼à‘@C .Bäm^t)¬h¥Ê÷AyXêÉþl+CÎa»ap(ôNl±ýÏlå,…̬ÈqžV%­§¨ærçH­ch ŽÄ   ʼn£¯=ºj∴" í5ÌÔ§h­f€ˆ&Ò¤ØY¿üý ¼Ÿ ûQp‘Åö_}ÀYšMM£¢33k 9çp¾¨)ÝH¹ò’©udNq)Í9“YÁŠ¢&ŠŽV4”£×šÍ‘BBïP# F… ÑÚƒ¡ÊE#ôÚ[ Féû@(IÕíEÁ¾RÃî]n­{ޝ0¼1f8Œ½#c–±£ýÉ4f;è*ÍÉHøkZJ>A¸œ‚‹'JYëW;Œø#B!eâ„@©Åþ#û\çŽô=àSdEa$R²·½™7_l(4Z°ûÀ˜U†è]¥–gi°T½± ÛS–Á'¾àœ-ÝŠÏ ­ç ¸¼ž_Y¿¢^2†*ïß­ß'îæÞÀ¢Evfœ^XP½k£D„¶ÖHäþwÖG¹]Þý}ZÑìÁÁrÅêV9€ƸJK»²b ˆ ¯'ëëk‹³Êwýü­orN×*¹ÅÎ÷-­¢¦¨Ý|ÒÛ!Rq€â@kè÷B½çÖÀ / tA¹µÇä†<ÎÈã kq2y=Ž|.›|·¥ÔÊÉZãÃë­ýÍFƒ°Y'¬Gåc6‡<ñën{û½Ò9ª)¡+úÈug”žõÎïüM¹ôx_'ú¾0/a™Ù©-…®u l`-äIF>ŽÉã˜A’äç&É«góôÛcçÞÑB°aÍÛÿ3ýpO–<ñpÒøÈý£æÞZ½‰n4‰Zm¢Æ “-H·Ê^¤¨m¦¡zJ=„!BHvDÕ;@€†¨[¡ªmoQP4wCÔÆK6J(â“$ “ØœÄoœÉ'ÿmËÚ×µ‡B䔡½vÍšoÞ˜Œ¾¿/Oÿ‰,þéûÒæ²‹dõa³E­¹‚ª/C¼^Žé[BOéý ~CMÙ{Û[dnÃ_ht”>\WJ0•¥±Zš+8„|SÄ16I&cûV2>÷z>ùæÀÚk! …ØwfǾÊÔ@=€Žƒä’-þàêdôòþ<ýèÉIãéû²FOM’qƒ Ù"jîFÂl])ÍÃ/Ðô´Z`źܦÞƒö§m;ÝSúH¨eîÜš+PïcÒ”"‰±iÂx4â\<:ÿz–þ÷ug Â(,«ÐM`໳c_\)¿®-Ð  ï ;o‹ÿp%þ¯ƒyú3'Òä§î«7Ú*K˜$ ‚f› {†× ÝQ´•jלˆÅ½!s?`î” ¨ièi} l^¸’òa 3ÚÄ$1ñpÄ[£á•ײäÛ«Îþ1ÂVPj|àÇ&0ªhßLw•{P¶€@?„¾…ü¬Ë¿~q’¿ô`–þì‰0y|o£Ñ,ÅÕ›õ%Ä:˜lÑR*h!‡Ç¸?ºc> ²sL»r%n÷’Ö{ÀBÔUÃln0ÞòÖÖÖ×&Éw®a^vÂf L€ `Ý ?<ñš7•?ñ]§±¿oèX aÉùëä—.dù‹eé'NÆÉö4ãH5›¨ZQ5‰é¡Ž]ÅÊíF‚à=h¿¬_¡².DÕ€€øÚuÞ Ö_Ä/]Ƽd…µ f«¢õ­ÊjLVY|©ÆÐ)rO\lèègBþ*ù;çóüèÑAú̉qrr¥Ý ÂF U:Äh¾„|g£ºPlü Iþ£º>—ÚÍâÕxôò;b^4 yPjn½bçÊàÓ¶Ú¿Æz¶•îSæ™1eÅ–‚ž‚¥Tøñ%?s./>¾ž~â¡°~hÍ«•ùOºô'£Ûun·»÷¿áIöYØX²Š-]Vž£ŠÆ‡~©`F÷ÛÙÎZ5»ÊJUÃÐú@ÏBÍAZÚF¸ê„Ë ®7ü<²;§»‘¶ÔŒâm JOÃÚpÕ³ªßî^Þé}¾;íGæþ{“ ³6U HÍ(®‰*Ù/jç¿/T4øPÕòZhzíä~RãE‚߉WX8]¶«ù¹4ü`о^®ìgN€)-Š=7@7Ò&H‡TúÍ„g‰`×U¸îo8¤ý[]ÄLºod忯À’FIuÃka_`u*PÌJÌPm÷*åŠÈÂ@2–&ÝÒ@Z6«vÉëšMÓ€9-ÉÇ|ظü¹ß±âÙoˆBƒC„nwÍîνaw“1¦oHúXèPZúõ'wßö‹˲`¿~ƒcN[t ±¡4#•oA%᥋™u¨Odîzýc´bN$æã¯©`vjæÒ|ØeÜÀ@ÓÖ?l(Ì-Z³l%"=i ÒB!Ò QBý Ð0= 8]ÐûÀÂ"Û¼\ÝÓrZ˜°aV÷\:OÞg ¸p)ËWÒhÐ(åï Ї ë4¿òvrþè@7È{à~º´aú`™»ÄõÆrµ)`†¬>¤Ýr©ŸýÄâ aÎúµ„õ|Ò Ø’CW/0ka=óÿý%hi…ýïRýÄTÞ~;X®Áî©‚0á{,¯ž ¤Â/¬îþ°z!_þéK0Ø!$æH ov. ö°uå ®by÷dh@ÐäD Ç!jÒr¢Nèôé* L’Iqº>Jjë¸ý…áÔ)´~¤)ñ%… ¤„Ÿ<ñ÷ülÏ.Ò­ùö Ãr'ˆ$0íäÄJ„fÀ¬¾ |¡¶ŽoüËz8ÑA,AWU„aâÓu<ó« ¨°ùÞ;¸*­Ä) ¦ éã HŠ£Ðu(^°ˆÏü:;‰÷õ¢› (BàON†¹å<ûÏßä¹½»È´æÛ3ËÏß(™°!Éfþ¯kñƒ'¿ÇÃõäO€·®Â>6¯º“«¦BêtAËà‘@×E hA-·}û)8ÞAl°Cš£ƒ(‚` •|ýøÁþ=dqØÝ· O`CVGGæ×òüW¾Ç1``3ïŠe”xÿâÅìe˃Ÿ¦Ï°?4è‚&mŠx¯´¼ý% ¨º–} :ŽB7 Då‚ èóÁüžxa=ÿúî>TÀ€=Àòé°X ðÇÕ¼òð— ý(C±(¦üh wî¿„@M-27ƒíý1=1IðÙš¿Aa1‡®Ë@qu ·?òUx¿HdMšH9>áB!ìU¡º–¿}ùg¼ðî>çñnà¶Qš' n#}u7Ã,^PÏóú9hm¥_#Q‰Ð»`„”ø¥IÒü(Ìaëßý½#>@µ2Ʀ‰0­ù‹5[íKªª¹ë Cûû FGÐu)l•Ÿ  kª 55üõ¿æïî –dN1¼ç²­ ã ›>•Z|wVÎ,nÿƒûY½dl|‹¾?D7 P>¢{cüÛ H„„€a*+CŸËÖo=J³æ±/E¤ü!nn²¡ðÞ9µ¯åäϪOO›Ágþì³”d³?ârGšÔAU'ÿ$ ɺIZn‘¢ÙìøÅˆEtbõš}@_´Õ¾ª¬’ûVÞ‡y¨…^-NL‚rÊÌ;ÎÙ#隆oö6KÏ·¥ª¼œ¡+Ýmo5oûýRžð(X¶—dúBÏt¶·=v¼÷ä¢76¾ÎªÏ¬æ[5µdnæR,†æóƒ– ^"iIaH€y²ƒŒáAV~þa6ÿòßIh¨ÐtrôIA—&¡´¤‚û–,ÃÜ»‹nC'&m¿2•ùБø„$E×ñóÓáaþjûo ñ¾«Çn«hXŸ®„Îo„€TªÁ¹óÓòëŽöœ{ô±:€?»e%/-XHü׿â’Íã¡LI"£ÑAHBºFVVƒó*yoï›ÈË=$Ýz?Ñ çø°ýY%sYQÓ@üP#=ºATËè™ïö\/’tC#TXÊ¿y½<²g3•"©}i^ñº½7E»›#Rš£H¬Ô7 ¤BqJý9ÌG àï–ÝÁ+æ}í¿¹ k^G¦BžDbE‡dM#++—‘e+èì8DÙO_fðôIº¾ø07•=ÔD‚ˆ´œÓTÙ—6û^éñ©…żœÆß¾»€h+³îôÖhIzÝ%1Áت¨Nj˜Š kƒðhê~´gYBðäê™ñÊ‹\ŽFѼ„¢LÍ'عC¿)1Ïv’µ_eÞß|mÎ,BIA–Ì[Äàæ ô(Qbz¾ðJÅGHUÄ‹äQæƒÐ.áÙcè‡cТ¨£5A'~J €®ÂS™ð¨ ßÙ½• aðدÿ›#â (Џ¦Î7 Rb œé"çÍ ¨³ QÚÞ'²g—cQ†  ¦k¬ÄI^$!2óry)eÙ¸‡,ÉwÃ3ƒphQpXc£ GòIŒUNÊŠŠÃPŸÇ¡nøÆÒå|mFý¿y•³XYCðdD;þÀ´Æ%Óë%#+—ø`?WèuJ¸N4Ž3–«²\>ƒÿšYÄCmMd[Ì·_…õýÐ8‡°™WT.KãúØÅËâ,N¯Æ¡áðåêz¾™¦oïŽc­´àð;;éYy7µ=BVQUðÑí±©vKê³€²äΰûÔq²d8¢ÀZÅ–|bˆœêî“Ç)LŒ0æ¡gâý=ÓA¨dõ‡õ}©.å/ÿ± ŒÌŒlÊžþ6CX[·Þ ž,ô…±@,ÊÈ$öø“øÎžåÎê:o|õXO,ö¸Î 8êÐ4žÅ]ã9ÏÜߦÂ:mqÍЯîÞâV€¸ C•Wu—woböªûà̘»·Ñ‹µOï¨òDöæÁ‘šÃ@ľ ô“yñ2©YÙ\è8JŠ'Pq5ËÑa“ÃdÔ~?‚u>`Èž;6Î|ý.1ˆ3 —"•þóg‰^:KÀçåòˆFŸ‹ §†çxwÇÁ™@?Ì ÃÙ P>w. fä{w7cX‡¬|ýÚE×x Ðîd)(·ÜÁÆôÄ-È.Á‚48¢Úã{±$êÞWð¸æ ØczüIÜ;bÊ=Æã(ªÊ€¡5!(%W°²'G=½wÇ \!®D@g¨WÍü¤4NØÌØÀ%ÙãxpW'nnÛuÀï³Á,Û·[ï\Ŧ}íëà ‡cРB“#Õfع:Úê,ùM¬Å“Ó”Ó`Ä”Œ˜’–/ˆÙOälŠ5è Ë*k¨NNáDÓN=öû>[‚~["þëtŸë]ŸÝ“lB£À)$ý;6ssý-¤¤8¾¨Ñ€ú‰¢ˆc"nžÜf1‘ïêRÏR + X:¿†ª¤û¸hOè· Odn*ÝoKÊǘZlB‡NC£Ç&V-¾•Šô4g ßhBýõ²Îñ"Ôó燆}8!,©ª¡*¦£y?Ý6ó>›`·ä'ꮵYoÂggLåäº «;6sWíTe¤‘¨.¦Ó¦€Ë;—ªÐ• 4TÕP™æDã>®2¶Hq3ž(]oÂg7£×÷‰À9 $Ù÷QडsiÛÛ,Y¸„òŒ‚@&,úDSa—äK<¶äëçÕ0Ïf¾Ë®&bÂͨS;cšr¢„‡kÁHËÑeÇg ‹Û7ÓP»”âŒ4çYót4aJP¢Bg:°¨²ŠR_ðÉ'2ï„ ñÔÞgOÂr$Xgœå™äwŽv9æ.J“+»¶±dáR*3Ó 3jSÒ„ p©}±:3šÊyÌö8yè€s$c*:áÑnɰÕC¤TΧ «¬¥ðQ?0ŽOP±¢ÖyCçÊÎ-,ªn 4=…tëÙ”4aRLÛæ3€yåä«Nif€1›O”¼Ûþ½öŠ}/ìç³ÙáXó,Ú÷Ÿ!¼h1ÅX›3‰ LäHyU,üÐÐ9¿s e ˜3#…ÅÆu5á#H)G%¯À‰@eeyÞ§ßoaØz6¡ä%æ¼£`9±9@ANÆ­ËèE¸z™Ôé K¯aÊÊR˜žB²ÅR³1‰&|䨬išh–yžÈ***˜©&qÆf^cL’îŒË¹&vp²/ËÖsgbÞz3¯¾‚ÚrOAÑæFÔ{VÖ°ß=Ûë”éa,¹®±M×g{í"M”ý{©^¾åh3'¯ô14øÇY2Û4J¤41M—Å9pbAÐOMÃbr…—³.æÕ)HÇÑç“ëÀUn~!ú¢j:ß|Å:öÓvpõÊÛ ðÁ¦ ú%i SŽ ë$D®Õ·98Kï«tïÝɼòZj ó© '3Û£4Æ¡Á`ìlÀRbê:ÌM‚®…òê¾ý4…†Ê¥£ï1äbÞ­Òž"œ{ÕE`Ðf>³ sQ ïoÜH„ÂÅïù¹ðû_ÞéNï=@$ÕCxÉ2 °ÌÁKuõñ’)‡.gýÐm\Ü»“¼ürfÍ«!?"Æà&C[ø+RJ¤ibÆc‹Jo¿»cùÛ»˜óò‹¤ß¿ŠxË; 3¶ùá¨}b¨rV\n»wl4H›S‚Q¿ãC\‚Ú=°Þìë9ÌP_‹×§<ユàìÎýŒ„ iéròmMHŒ î Òq„nÍXÑ¡èg;Y™ùÌüü#ܺîîxàÁw5S[9€i`:Þ@Ðã$ë¾€Ù7 CÃhXëjá’pbb2^*ë¨}6šSŠY·€ãÿ·¨ >hWkMé:ïaš šxZ@c 8¿u#!oÅ]Ì'Õ•´[ýÆÝðÙÌE_rø}hº†HO!”?“ ÿb×M·!¢äÃC5|¤ñ»i@FYi%å\ؾ…îØÈ5?Ñù9Ù™Ó½X5¼¤9Ř‹Òù«×¶ˆn7֚Ъ™´¤©àÏÍÆ¼ÚÃ@Ô(6õxÜ”ÔyYw­ ¬aÓ[\ÂZ 9K[gÕ§¹îÝ'Õ£@ÆŒlò««¸Ð¸‹+ÃV !4oÁšîãGþó÷t³ @ñ…Sñ§¤¡†Óúé™[S‹J¾;¼ßÑAë¶·È_¾‚‚¤äkt;&7 ŽÈ’Šæ"oªãÌk¯ü mB±J×@KbM@“Šà ¬Q:pzËNúµ(Üu9X>Á‰î0è6K‡¶YY3™]UIûΜ6Q´’ÒõŒ m‰ò¢ËL0M€X¤«½9z¦ë ¾'¡¸ÎÑÝ[ɽùr“B£jè¨Ûé©X/ð–•cÞ´s¯½JÔ¿ ]JÖ­Êä¥ëÓŠuvh­O¡YNoßIOtLpRÝQFÝ 8…—ÂÜfÖ̧sß.m­PÖtuþöôÉ®=VÉÂÞ BUÑL“à ?üSŠétìÛNÞÒ¥d…ÓkŸ›ù,@”—«¨ ë•_ÕÁ#h“ k…f1ɦ…«ZÔ©(0k< ~àƒ½{éŽ Á=«˜eÀnÜQ§ ·€ôùU´mßL¿a}‚µQ“Ýp`úU×¼×d‚öé3­šà7¾ç†£:'öï sñ"rR3®QCK5gÌ-g¸`6ol@<*íRabíÏOyÓBÀ)š°@höï£wdŒ @ÈÏ) y~%m[71"mß$X¼5lUŽÜÄú®¦+Ь6ø'0Õ9µ{éu ™‘:cÔR°Ô’êZ¢sŠ8»m³å Ú¤d­ͶZO« èpxJµ5áÒ®= ™¸{i6Ž 2s ×TqlëF°ÍB°VÀ› 4 诩ŒN§(V·›S@+‚7|Ï#`Pƒ®½Û/i =)•›n½ƒXi W¶¼M2Pi7Ö¡X6#;6v;­(4¡°FUiV€ ›w0$£pç=¤Úó§gd‘² Š[7Ç:o,`½o©–ÓíŸhBXçÿ¼^P=‰µ4CÀ!E „ÀT$OÄáÜžÍ>øjv.$§ EèÿÉwñ* m#°NV9ÍÊñš„“ÖéPÖxT5 êÎoÙAþï=@òòÛIí:yÓÍœÞúôK{ý X¯ÀF[ƒ&ß#„—¡7^áN\·—ĺ´¶›¥"PÉ7͈ÉÀås¤¿øD>ýiP“A·k°Å:“ó1yw·“)xÚ#xL(Ôu¿ù&ò¾Oúò7¸ò‹ç‘Ãq€&XoÀo…¥ö“2à±¼ÿ˜_”XGÔ*¨º°˜L“#{vß} h-‘H›.YgZj?zø“j tJ0Qxʧð¨¡ÑõùðA/Ëé­[jИó0Á?GËávÓ´x-ûR´ÁÈ7÷Û‘BÿàÂQSeÂbþãªýDMZ² Y<î+/«Sór0{¯‚d½Gð–j{û©Ž9å¿ÎÚL™Š EBl|ýë"9å2’ÖÊ«‘VS¥eZ'šo¬4 L%ÀšØ®íÿhž»Xa?”ƒ#58(•©3S@Âè_UVÒf$™ÑXP‘+ÂÐH;½ý]I\[u’ÓªO1›}½åŠ"vhÐh‹ùéÈàúHû@¢´«0‡š0´FãÂiô^Žéýñ&ÁèÑÞßiö‚ÄÔèÐŽ¶zDòÉcñîÞCñIBÝdmrlæëff¢™&¦´þk#¥Ä”2*.Û¯÷F áùI{½Éš°2w­_k—ýÝÇâ1ùÿ(&jÿ¾ÑóŒvd"­IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/comment.png000066400000000000000000000012711217176075400242400ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs m„·tIMEÛ 74.d<»9IDATXÃí–¿kQÇ?³Y/šèÑÿ@ •àåˆ ¯¶°¶[;ÿk[ ñuÖ ! KSˆ¿.ãÝí³¸Y6o7{î67°!f¤i }ÄœhÄûÀž‰– m RçÜ›£>ôÞË<šð$p8¡%í@#¨ž•(Í@€óÀ6pQàm<º_L–ª2à½_6é?ÔU%ØÐn«Þ>çÖÉ†Ú ¦ëóÈÏèûßÀO=C]¯e2Ã9€­Â7-`Å9·uÝðÀø¦€FÚ µðP-´€Ë¹‘R&¬»¥¹|6^¸¼.¼‹Øëç€5 ¦x%Ë)ø£žÃY¯ã6°êœÛ–gy)Mµ®ó¾/d! ™üuß¾u©ó›rIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/compfile.png000066400000000000000000000103421217176075400243730ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ©IDATxœå›{p\Õ}Ç?çœ{wW«•V¶å—žØÆKŒ±‰!5š&ޡ鴙””Nfš´ù§é$õþ*3ù#´IgÒ¤CÓé4¤€mÈ4$)„W*clc°Šß–e,+Ök÷žGÿ¸»«ÕjW•t&ß™íÞsϹç|ÏïþžGÂ9Çï2äo{¿mxõtzâ‰'Þºuë׉D£sΖK‘¢®‰TëWK:s¥ûçºÇ9‡çy±ÁÁÁã>úèžÊûê"À9—¼÷Þ{7644¤êé½áœÃ9‡µÏóx饗ìW¿úUÿÉ'Ÿ Ëï­‹­õ´‡Tb6I¨ÕVëzå.—_/.ºü{åµj¨›€Ù-¶Í¶ b_)å´ëE”÷-ŠråïòëÅq*w¿x­¹,Z ÎEB-ÔšP>Ÿ'—Ë¡µžõþâïââÊ—ßSþ»Ú|®‰(ßÑÊß•­ÜÍjãTŽWÞ·ª‘SNH¹tTbQ¯@%´ÖÄ|¤"òXk‘RN› D |gƬ±(OM›p%™•»Z‰jûÕÒQSóYŠ2Æ`Œ!qòÔ)öî}–l6GC<€µ62G¾ÏèØ8ÿù̳œ9w†X,†”ÓÍY,##¥,M¾\*¬µ¥ñ*Å»\r*_‘kN@å.ùžÇùsç8~ü=6ݺ‰çŸßO†¥…H%Éf2¼ñÆk|ä#wòêk¯pqhåÍÂZ>A¥–/o3ÆÏçÉçó%r®»˜6 ŒŽŽ!q¬Y·–‹CCa€@á Ôš‘+Wéhï'¾\sáµ”^µïEI¬¦oæÂ" kÆBh-MÍ¥øà:Û»Ò#4m@[‡’«V/çôéÓ$â,]Ú:ë¤çKÂÔ|fšÞjÖ¡‹R‚Ö9r¡#§-襫:èÌ…ô{»v>@€"ȇ8¡3¤lÝ~'oþê Û¶m¥½m5a¢”š1éâŽÖRpÕPnÿg»¯u €—dènWdB R"&s¨%ôÝÕÉp6àòå q_!€ç²ÜÛ+iL6±ë]¥wVJ¹à…VÛM)%žçÍ)%•¨_ôdðÒLh‹€¬Áƒ3¤`àÐ@–»oN¢¥Ã¯L–+®rM^Íc,Þ_NœRjš$Í7Ì_”dÃù Øë,ÂFÊÎ0ÁËR˜Ì[ãH%q?†)Äå»T4oÅÅW¶c€ˆŒr禖oP+†¸&LæçÆ-N¢­C:¿:ÊØÕQ–6§‰Åâ„h&CÇdÞb•ÏøØ(ÿý‹×¸åÖM¬Ysà —7 ÃȬúþŒ-`žç¡”šfçã Uâ$`2ÐLNX&X ¹L–ÉÑ,ÊŹxv„¥Ë–òË[2!ŒŽg8ð:Û·ßÁ«¯¾N"ž`uÛªÒÎÎWlçkæƒÅI@Ö02nÉy£¹Iƒ}c ®d2dýT£d$cyËdryøCÚÛ; Cͯ¯^auÛªi ›+| õ°H p\˜t˜8ØÐ¢C‰ÑŠ«“9Bã“Ï8V–«9G,kÈ9X¶|ÏÅ÷=Ò--UÍ]­`¨¼m>Ù"˜û5¨›„Ú2”sxRàr l(ÐЊlÎ’ÕŽLèBƒU l¿û.úþ‚;·„ö¶vÂ0œ6É¢e¨´B|߯Ú6 ×…ˆv!´\ä:ëpNàœÀ8À9Êùh=å' ÌpŠÊT™ô¨LŒ”›ÌjAÑ5&€ÂÀÑëP1ã×€#ZxÎà˜îDÝa¥ì<Ï›aûgƒ1†°|Åb±yK@]±@q1µáf°â )$±Xå«)ºùÄõ þp˜Y8¨Ò xJaMȱ£G™Ÿ˜–€¹•ßBÝÜb¿Ùp] #UÓY@¨C¿ó_â•—_all )ª¿ó ‰Š}ŠÉ’…à7RrBæóœ?w–;w1:6ƹsçrú®ÝÜj™àjß!Z¼RŠX,6C¯”ßS ‹V‚Ó†-DÎEڱⲠzÿÑ€!•&W4uÕc­ßµ‚¡Z¡t5ÔWš«5ZmÅeKcSëûþSôõÝÆº5kÑ­?ׄk‰ve} ZÛl¨‹€Ò T¼XݾŠÏ~ös8!‰LfYo¶w¼ž¶¹PR8DÕÏe6h©qÌL`D÷MèÂ<¼ë 5>ú²R"”(‰™ïn·£&)µh;ÓᙂˆÞ}N‚TaÀX0.êe+Ø¢@ È*–"Rš®¶R+zs…ʳàíùi÷’tluCL&óN ¤HRüÂ}Sófùð…@5¨()Z…âb|ÔL|¨Öd%žT¶¤,=?oiö ]­I’jj‘RÀ2zu‚ÆÆF<Ï›¦¤”hcÈON’lLèŸ3HîùiÏ—è8ðÌÛ# #©„óT¡j#£/%ÿkS|ùg“Þ†ö&0bšÏ!ÊÃà¸%yÙc0püÝÓƒ€!¡¸›B€L\䯖²rÉlàwl¤§³Q°(ÖÁ»ï§¿¿Ÿ®®.>z×]xJaœC‰1†_ýò—ô÷ÿ÷Ý·‹o®Ï ä—ÎŽºí÷o¼åક$Jv¬´Hã8?¡9™ ip›++¹—¹ˆJ >ÔÄ—[R] ¦AE ²@‚’¸¸$vNКno¡·µ‡÷Þ=Joç=@$úããc~»ŸÏ?ö/üh?'èëëÄ!ž§8ñþû _æ/¿ôW<ûܳtvv’N7/¼4f÷Þwå…c£»O¿zúØz ÁæÀæÁ•>ß:’Š™/r‰…1¬†ÑIǤvd´#£!£!kaÒ€¡©KÒÝ3ÌŽ•6¶%ñt62oe£Š‚×(D!d.WÌßä ¦9AÅKRÌü$”Àjà ǧ:ûàG_û1ë×t•™[Gª©™ž½|û¿…’õëoD›(ŸhŒ¡­­ Oy<óÌ3´µµÑL.®. ŸÙyÊÿ£—v÷=÷öþõ{6õ#næIÂ<`¸èÐró2Éc7ûܶb · Lžº»§œ¢(²ç––-[Ê’Ö¥Äâ ŒÖÈB8N³ãž ²ní:³{lÿác7Å‚™qK]0˜Ð²q‰àÏzÜÒêѬënçÆuëf8³øÊ£{M7֚ͩiíÆÒé4½½½Äâqœ_nqÎ`(ü{O¾{>»û×{ÛàçM‚vÐè ŒqܼDòùÞ½­kÒŠ¤/0Z—’"Õâh´6‘ù­€±¶:ŸD8¯h0ø÷'åv¼päØM~ž@-<ˆDÒf_ Ü”V<Þ— w™ÇÚfEÒ‹DÕ÷¼(÷'䌤Tø1?:PÁL‚<%KÁÔ|O˜Ì{%Á÷?vòý¡üî_8vìF/ PÕ5c­7.´ŽtB!…‡â»rlnO²v‰GÒg-Jy6Îþ}Ïqæôi|ÏŸòø Å’³gÎñ_?~‘±±±ª¹ÅjXÐV柺ûä©áìîÑŸ¼s| ä|B ¶Ž–„gir£üíÎ6ÂS‡If‡I7İ΢<Ÿ·âä™3d²9^ý dA „d&3üü¥—¹mÓV޾s”³gÏàùÖ9¤òºÄ¡Ãoó=Þ|ó-rÙÜõ9ùîÝ'ïâåo·Ð2$”jfR ì¹¡u´$Ò VÄ5¦/ðЦ•¤Å™±+ÑM”’œ8þ>Ÿx`{vš'Jã! fðÒ ÝÝg¸:zµäîJ)¹‚Õš;w2:z•\>7¯õÔ•êHå¯<ñÉÖlÛ™ ´‹€PÊŠ$¡@àÐÖ‘ŽK„st6I¾¸¥™S‚¡ó§‘VÓÒ²4*(CdëÓÍüêÀANžú€ÆT¢4žÀáû­­Ë¹2<‚sŽ––4Wp†ñXŒ|2>>Ž”åM%G®9Î:Ù×™O>´Š•/Ñ® ZÊBê+úh Íq ÎÑÞ$yüö$[Ú›ùäÝ·rìð!>öñ³º­ †áȇš|€ËÃÃìÛ÷<»?µ§Ä§±–†D’÷ìà{O}—®®5tuNVuhX»vÖ¯çé§ŸfÛ¶m¤SóÊÖÊä ;šøúC+ùÊÞ±M- ŠèDµŠE‹ïN{üùæ½Ë}ÚS–¦†4ŸÞóÖY‚ "íä‘Gþ$rn ŸŠï±5šå­ËøÊ_ÿ ÎÙ©ŠR!G¯­aóí›Ù¼ùv¬cZßÙPwRTA.°ô¶7ðõ‡V°jb”•¾ÃA2&±ÖÑÝ¢x|s½+bÜÐâ‘ô)U„Â|k§k³Ö¢Mä+Æå¤c óATB¯ôõ]tîЋ5ówYΖ޶¾ñðJÚÃ,K„%Àúåq¾pgšÞ>ÝiIƒ/¢=–Êóð½ž7•ý<;PBì¼,˜(z…JEmÊ÷K¢œ@)%J)Š!|ÝÁÐ|P>x&°ô¬nà>³‚¥Á8î÷i6w¦X·,N*&B‹ù ]¼À¿>õ/:ü6Rzñ§PL’<·wÿo˜Ÿ«L9ç7gfÎÌ5—¸ô¢‹˜<Ïcû¶&Þyç½}}ýk}>ãO“&M~l¤€—^xp$‚¢(­`ÿ§ƒ·Þ¸ü¶Ým½º® …Èå²tvµ3köìquµuŒ÷ÓÚàŸ4iâ•K—žö1]Ñhmm#I‘ËçÉçóX¦…¢h¼¾vmá—wßýôú×߸Æ2­s€Ç¶mÞÌ“∕hÜo¿áÆeßúéÏ~öóP(r<Ýg0iÌNûà‡>*‘7tmƒ¦é 9£Ã_}ìȉ@I2yâüùóÏ­Ÿ87×oáRÈØè]7Ð4'vX¶õ1À˜0~;·¿ƒá×a¨ËÐÉÐXîýùOrò篸üüª±cƒ  k  ¶mÙ|æÀàà {Ô” ÇŸîØ¶s°Šæ vãÍ7,ûS}}Ýu'Ÿ²ðÜœtrtÚqDZiÛ7ئ%uŸþ#À­E•••£M 0¾¬¬¬~Ÿ’šNyeý½}t ôâHÅPÁ•BQÄ™¶ã\çǸ ð€«&7õ‘h´¸P(PÈç°Ls‡ëº½«èàCã¿Ð\~Ý5ßúÑÃ<0P7¾žYóæª —Y–õQä߇ښj<×­Œ)++3’W…H$Heu%á@×vpmI0“&Öù{—9ž·¾8cü„ú›JËJ‹]Ç&ŸÏṞt=94½ ‡ò€}Xùä³ø ßm¸ç^Ïýö¥Ÿÿ|DôukÖ~×2M¤äf)$B @¢ B€)‡žK>ŸA4-_¥áh,²ÿUQ)¯*§§µ‡Žt–Ln¢h„S/âþû¤~âäšDIRô§D!Ÿ'Ÿ/ ¡*o›o«#0 ©(âÇþß„Šò‹.»4$Å¿æåW¿¥¨ŠnM!%¥ ÒÙQÅR%Á€_=ð¡!|̘?“Êl5Û¶l§c ‹Éu“¨L– P04MXvÇq°,‹H8Bÿ`ÿ}ù®Áo£%Àò¤¼óþûî“RðýK.¿Ì¯("ôÊê—¯V4FIÂÚ5¯1Í’%‹“º~Õ„ oåiÚ¾“çÏç™çV2`ÁÉ'ÒÛÛcY¸–C:“#‹"=ù´çys˜±êhÈ;Žó³¿Üw¿R^Ù—ÊB]½jõ74MÀGYÞÁÐ}þ˜ªþ»j¦iòèc+xòŸÓ¶»~ˆæ/`Ëæ·;¶ŽLz#í]Ýd²9¢‘0 ¿¹uWë²\6Ór¸ÊF=ˆí‡¬i™w=üÀƒ7ß{Ï=öØšj-^wmç«À²#e>ãÃKñû}‡“¿a”)ÊPؽw×]ûmN;i ¿ùåÝ4&ÍœÁoîù-ÉâbT`S^QEWw±xŒH$ÒÜÝÕsy>Ÿ_ÏÐÌpL Hçó¹_<ôÀƒ7ÞûÛ{ܪqãX¸dq±¯7)s à?œL/)-=Þs]ž_ù<Ü÷N^²#¤ E(­(cúä©ìnn£­½ƒ3g’Î¥)).&‹R(éèì87›Í½Èptx8¨Ñpä /¦7L*Å@oÿPBU=0ø5mËÚ´ó†L¡_´øÔS•Dq"ØÜÔ4CQU?‚U‚¡AÓ†ZTW/ö—³²³ˆ-ÙÛs ÞNÓ˜ò‘T©®¬üÆ 'Ì;ep #¶¿½™tvE§-¡¼t Ï>û"Õc+ð+:Ù|–77¼Á‡O?ô@ÄÐʞݻo×4íÓ´¤ë:Hyè}þ‚ÿÃ$Ø›vîÜ™5 æ¢E§.QЉ@KcÓ EU}ÀêƒðV—¤=倔$žMZƒK>xò´eF(noo¦ªº–TŠÝ»[XzêBžX±ËvéOõSTTDÙ˜*¦OŸŽipl“P8LÁ4ƒžë>^QQf–””PZZzH©©­ý @ L˲6ílhÈ ……‹—,V‹EÁ–¦–ã…"|±j4ô7›ÑÓ¦Gn_ŸÛ_H ËѨ›PK@õÑØØHMm=ÉÒ2yäªÆVsö™Ÿä£Ÿøý½ýxž‹ªiøü¢Ñèx×±=ÏÛ4üÁ±"À´LsccCC>—/œ²èÔÅj"ž´¶´ÌBñ!Xu8zšeÜÓ|·tˆÊsÛ³ªQî”9rŽG¨´„B*Ë/¾ˆçšT«æêk¯aÖœYø}öîÞeÛ8ŽãZ¦iK)-ÛvÒªª¾ iZ^Ó4%cÇŽ=êiðpÈd³Ù»þúÐÃB\éWøN<唨k/¿r BxÀ-d ÝÓ"KTM½I‰½¬COï¶ÙÖcð©úNf»­ &ªÏGiIãÇ×2uÚqäÍ‚û—XÛÝÕ½¥²ª²UQ”>]ÓóB–¢3Št*Š:ªë±$ ›Ïçî|ø/ ×]rÅåœ|bxÍ˯^g™¦bø|·öHâÞYêj±›Ôø¸+¤mªnûNüUcéÕjøý6´ÓͯƒD]%S'N` =à­øûЧÞ\¿~Å`*óz¡oþÜç>wд8V]`èZÂq]wíö­[=Ó²NX´d‰‹Å´½m{NvG2êÚié¼½ÉNÚ"pËgÛ¦æ·* M»È8qÂ%1ÊÇÄhéRx«¥À„1*QÏaã–o?¿òù;×¼úÚ±xl¥iZŽã˜3gÎDª¨!bh«L"ößãÆÛ.°?LÛ¶oðþ? Eˆo]zÅáymÝš5×›–™ÝÕ¢ý½à¿V=6ò…{ãirk^æC½»¹ªæô¨ÕT ›²bƒ= ~÷RGþÉuÿèlþï¢âäªc­èûáC-R(ÊêM7*ŽU˜½pÉ8QÚ[Û¾Ómçháó_ŸÓŒïƒ pwðR˜3éð€±Õ¤£«@ºí©7¿¨[Á ýýÄâ1LÓÂqþ·zÀþ¸õ÷ü¿Ïó¾qÙ•WVqšêL­Zzn÷:|'}œþ›oå¹ ˜sÉS«™vyŒ§Ò_bO·„ÂÀvUW\R"ºÞ/åIÀj9*gÂðFŽ}¨„À÷ÒÝû®s'~ pµÐËý@ìÄ'žüþ¬çžU'w`Ìü$]_ø:¯nÜÈfË¢¯/Åœh„“üÇþÉGÊþ»Ûµ¹#^-^=r@ûÞ¡•œwë1-°pÊWB ì×5:[d¹}ÜçôÛž¾TþŸk¯ÉßÝÐ@¶mªª°wïf“iÒɲtòq$ûs\Ø~ë]÷ÎúöïFŒÿúßEUU–-^ÌçÿðG~zö9ÇD_1ëk÷“‚F aØÛ"«Pý·/±;/üYu+áó?‰ùæF¤iâåò8­»èÚ¶íÍÍT&“LûÊWÈ®|6Ó°víþ={_È{Au(ˆRUMÓ°ì!T„À´,ºÿö7tMG(E„BFV“‡ÃI'ŸøþŽí-r¬jø~¸4×ø™Û+v<ãv~ójZöîeB]¥ÿ8zm-‰Þ^æ†ÃqVC+_z%œ÷¼ÛbeeŸ(koï9R=±³ÏF¡?rT:¾×åðÑÞ"«uÃwG¬¦þ36=„^3†¦ï|—5­­ x]½½t=ñÂï§èË_¦ò®Ÿá´¶²ú(xNèpœßï(-=ªzÇ\vñÏž5êôï‹´·È*ŸÏ÷ƒ1µÕçõkqžlÝ…ñ«ß±Ý²HK‰ØÓßmYïÝKì«W‘}ô1:V¿D4Àçºd- Íu?îÁC;KJΘÔ×7jŒ¥‹‰”ÄÑÂ~¬Á,^á û"}ýÇÖÚ›¥èh–•€ÿ޳'}Z‹$ixæ%~«.à™T–ˆ:ÈÐçºd=ÛuÑëëé½î{äV®¤ì¤™2cEÑ(!Ÿˆ®£Ã¹–”¯ !Š’Éc©.ŠtŽVÛ¦·Èå,2y“LÁƲ<)+‘À O™~¾ —ðêŠU¸»Þ"=é"~pê?é³J ¿TøýÌ»ðB ëÖñÔý÷³ùùçQb1‚ P5ná@Ÿ¦Ò4œqÝŸhJ&Ùy ‰8fÐÙ"KcáÀòÓ—ž)ãÉûVâ¶l„²)øâ ¿Á·ÏZ…Æhó>ò!œö½¼òÌ3¸RҚɰã¯E D.¤~ÂÑ(ñPˆ’`°ªjŽóxÊ4WhŠôÜcº[dq$¸å¼³æ^¨¬úõ3¸;_‡’ èÐü~43Ǹ"ÂòÕèÕSyá±'x|Å?(x~EÁ';;:Øñ·¿!ÂaŠ.¾˜ºiÓ‡BCâ÷£ g :N¶±´ôóÍG9@ ÿ1Ý-²¸(¼ý’³ç_’W¡ÞõÕ¸›WCQ=Zù$Œ€†¢„Lõ³Jp弟qñ·Z-ë KÊ—¤”ûâøÆ®.:þüg„ßOô‚Ï0nâD EÁP4À“H{Þïz-kÝβ²èÿ7º[d$4–Ÿwæì‹«¦ŒÓ—Ýö…7žD5êØI~?BS1¢~Nœ™ h(¼±±‡l[²0x‡~¯Â‚”OÚž‡&ºlij¢ã'?A‰ÿò—©ž2…H0Hy$BXQp¥ÄCˆ¹)ß)-½ôœ€®ð|7}òŒ¹—MžQg|÷öWI¿ø8W¢TLFPü û|̘el™Êª·èíêÂMw=…ëþ¦2—vÇvvâÂé)WÛž‡ª(¨ªÊÛ[·ÒyÓMhUU$¾u5&ôùHF"ø…‚”¸@P<¸·¡¬ì‘æÄюÎi¨>íû‹NùÒôã'7ßµž®'W@4 e3ÐÃ1TMGÓýÔÖF™Sãµm9:ÚúpRÝ­Ò²¯õ¥»[—]üê;;p¶­¶ë"¡ª¬Û²…¶/~mÜ’·þ€ñÇÏ$h”ƒ„„À–ð )å9­…¦ݱ„8¬òÿ)-RxBþ׬Y¾9ý„iþ»îÛNó£‚/30¢!4Ÿ@3tJ+£ÌŸbCSš¦æœþNGš™«ŠkÄæ¢ñoÛ ººz)¿–—’¼iÒešØRòÖ–-´_|zu‰eË©Ÿ6aðùˆ) ¶”XRâ¿Ó÷ôe·ï‰š¥ ý¼K<S8¨8žÀBâ p]¾VW[ó½ÉógþúÏÝl}ø!PTÌD/Š¡ jÐO¢<ÌÜÉ::]¶ìèÁêíDæSßGºOËý×…aÉy)Wd<ï×Öpï˜Ö¾¹‘ö .@¯®"ù£3aÞ<Š£Q~?qEÁÌá<&vô¦·4$ŠGGÀh™èl‘—•&—×Í>>´vcëzò(›Ž-FÓUtà R`îøŽå±~[/…Þnd¶÷OÒq~U\#ù¥vbw7y)¿žö¼–¸ÏGRUét]àÕµkÙ{î9¨åå$oÿ!µ³f) ‰+ !Î)®·º5vdO5-òìP4ñ“ºÙ³#{MÖ=òw쇊©¨±$zPEók„‹WÅç¼¹c€To72Ûó²ôìeÅ5âˆ;¸“{zÌ~Ï»¶«P "¥TUi²,,)YóÆz:>{JI1ÉÛng‚…BÄÈI‰ hpJ__æ½áøaI]-r±?ýuýœãã9B¼õgqwï‚äDDQ9Z@CõkÂAêj¢”lÜ‘¢³­™íÞ)íü׋kÄ®ƒ•=p€äWÊGZç­ƒƒÔ”•Vö8¶”¬{í5:/ºµ´”âå·P3o‰p˜x @BUQ€Â°'¤=÷üîî›Z¢‡>™rD:[ä_ ôëqÓf$‰%xóŸ+±šv@¬Š*Ðýª_à P=.Nm‰ŸíÍiöìê‚tgÌg®IÔˆwŸS= &÷õ¡À•®›dI}=*ÐdÛä=u/½DÇç.DI&IÜp#5óæQ‹ÛKJ4`°`]ŸËÚ5Æ‹Žž€ÎY¯êÆÝUõ'†ªkØøÜë¤7½ ¡r(©D÷ûÐüF @Õ˜ã+ý´v›4îìÆMud~à¶DXq4Æ`J_ŸéJù©5©ýýýœZW‡šm›Œç±îå—é¼èshåe/¿êys‡ÖÁ 1UÅaè`€8žû[‰w’2„B£üÁjrÞÁ6$Ý»(Q4ãÚSË&No¿²™ÎUσ’ñ¨zȇôQ^cj]˜”Ŧ­]˜}’\ïïpÝe˜'ñ<¤ë"¥ƒt‡DØy~ù§+ðÁAÅdÃáÆÛö2–µ¤>¡>‘ q`€¬”ø… Ï"ëß úÙ ðÍœ‹¯±™ÉàÚ6¸.iÏÙ¢WU”Eùhø‘„i§…"ž$qõÕ÷€®SõæDù˜OÄÇÖ‹;öÒöì3r!^ê×Њá#QabMÓrÙ´½—|w§”Ùž'¥ëÞ”¨‡=qÙ3uÝݨpKƒi>ùâîÝø4%UU(@»ã0躬}éeÚÏ?%"þõoP1c¥ÅÅ…B$TSJ ž‡éØõ®åÞ½+òïK‡wy@W‹Ô…ªüW´¸üÚ²qUÂTƒô5· üˆ¢\ECñë?ñd˜ãjc¼¹­Ÿþ½íˆl×iç¿™¨Uwjø-¬¼§y5‡B< qföàß25ÓdÐï ÛuÏ*¤Óe“+*(RUÚs¹}ž°·­ÄúõD/ü,ƤI{÷B*…p]tÏ£ÛuQ„À@LÖ|ª™ò^ŽLW_š\puŸdä§ÂÑäOÊjÇiº?ˆÏ2ab%KNŸÎI'$é´éË»„bQ¦NŒ÷k¼Ý˜¢³µ‘io–VöûE5Ê BÙcü݆ˆC1[–ìñùþØå8ŸÊ§Rɺd’’@€ÎL†´”C³D[ñ×^#zî¹øŽ?­© /“ÁsÇ¡ÏuQ= ¢ŠÆÚ~ÃßXÕU¨ÉùŸÚ¿õ«ô`øþ²ÚªTiz»ìöΜØÚÐ'|†ñÕ 26”$Œ+õ±½%Í®æHµ÷Éüà‹j”? !ØŸ€Ã~$"„ È²œAŸïWŽóQ;›­¬-*"áóÑŸÏÓïy„…½„×®%¼t1Æ”ièíí¸é4Š”˜¦Ië‡æz޼¿îª« jtÊq-×2É ªß*.sº+R7î¢ãÕí;3ë6/ÏlÞ±&Õäѵž\^ŒI†¨)6hÞ›çwºðR{ äzï‰×(7¬ë…¢0ðÄ÷»_•á‡"ba6 C+>’–å øý÷ô¸î’Ál¶º:! ’Êåèó¥¥eÉB!¿£î+_Ù¸oìi‘³òK‚ѰÒÞÒÍà¶]œü•U×ý‚°X.BÆ"+¤xù”Ì›ìé-°£±§¿Ã¹þRŠ›\Çö]z½ö=~ n)-寸¿™ñ©”Œ¨ê¢]–õÇUØ–Åø¢""ŠB§ã + k6o¦õê«AÓˆ|úÓ”ŒO"¡ÆïgÒøñ„Âáœô¼—490 ¥¤"}qÃÊeÉôdÁ0+ïîê“âÎ×–ÉíY™~ñ¯mY¯½=º«+OÚÆìíô°úžóœÂu±Zc ýÔõÇÄðñ=Ÿ!· ÔôõaÃ%{‰Moô÷ß9Åï§.£ypÇ!©ªlhhÀ»þzÆ~ç;„Ï<“Ï#ÒÐ@ѤIôlÙ²"—ËíP‹&@0&dªÇ[¤üÓЊééF ˜í­‰&5}bÏîitƤÚûÈæ²½žÌõ¿.P®‰Tš[³ÏÞ„¹óùSZUUt]ÿ÷<ÇqB°RÓxJ×yÎ0øt*õZ ðJÊu/Rl›’@€üðô×uÚz{Q6l ä¬³ðÏ›Gò‚Ïàesìyæ™ó*{J¿ým´|pì¿j ʇúw·~"YˆÊ1Q´hh©h;æTKŒ‡üÎ]dóf!ï9Û¶*x×FÚº>óVnTßâŽ5¾ !Mó¹Ë„HJxÚ)æÄ…¬çÑ`š”©*ÝÝ”üð‡ŒY1f®üâµåùüöIé6 uüåËÀÐ1¶O{<_~ù_zåâ¢15>5í'½µ™_îTéÞÓC®Ó’¹¦õo^×ÚÖ¦ Rá_!õ3ßQíÎžÏØwÿX8Ü[ÝÓ3ÿ„@à†¹Áà²qºÎ.ÛÆþ“4pÒI %ëëoZ´{÷OÅp0ôö¦·ÿ¥ ¦©Fȧ鞒ð[á9׉â¹_ò'Æ4©ñ4B·çî~i¥‘^õsÍîÙ û‹Š*¥T„Šb¤<Åó< ‡;©y4BxBW!éy€+„ð¤”Ò"ëîÞ3MÓ>õ¡HäG“Àرc‰Nš„ÛÛË/^xá¢_¤R+OD"¡|.“u]ÏQXD£Ñ`(,“®Ïå¼€g”Íqüº¾²:hÂjÛ«åwlUÍöÖ ßM ÄHWM KQ¤”ê~ׇó‚‘w£aÉ6ؤ”Òcè ¤;üÎq¤´==ƒIE)¹,¿h¬®ÇÖærÿ|8“yºÃu;Õ’R=¤)9:2éLg>—+ìSÎ0 #G4M J)uá9BQu#k*®Ô„p”PP¨ªjè(ª6d0bØHEJ©0ÔâÊ0£q!¥#­:¤”î~éÝa¯@Jé ³â9RZÅ]]…‚”¶€ü`qÒ§HÏS„°Û¶íL&“IÛ¶íh#£´”Ò–Rö „È\>GÁ´ˆt„¢‰lÞSÅaĸ‘ÖþsûÀg£êÿ#EF‹ãGTù#tø9žç!ÁÛåóy"ðœ\V Ø6ª®,‡ÿ2—žçÉý?¦{öö)¹"BðÿÇA¢R†NÄÙIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/db_opt.png000066400000000000000000000122031217176075400240420ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ ðPIDATxÚí›pוï?·»§g¤ÑŒ43ýB$a$;ÚÅŽÁ˜àÅ!müÖõ¼ŽljwS[®TÊ;®ò>ï{‰S®$ÞWEÿ‘8ɦÞڛĎ›ÆÂÆÄ‚%„@¿i¤Ñh¦{¦»ïûcf@–Í:ÈnNÕ­î¹­þq¾÷œï=÷œ+ø“üIþ$ÿEüž§9rä/¥”Z,;²víÚ£€È\û/ €?~ü€×ë]bÛ6étzÚ4Í£–euÚ¶Ýǯ)P®4úm·Ý¶ð§?ýiÇãAˆ ·m˲òm2•JuY–uØ0Œ·ãñøáõëן¸ hW@%w^°~ýúEAJ‰”ôP]×Ñu Øï÷¯ugm:¦¬¬ŒîîîÉd2Ù%¥ó™“9P¸ äïw®”@okkû›@ °JJ)Òé´Ë¶íE¥¥¥ËgŽ>ð>0þ3±,‹L&ƒ”Çqâ–e?T£y¦ã8zMQ'‰ü˽÷Þû`] @‘¦ië—.]ºÁ¶í߇…úUWÄ7uÎÎÎã@;È[Âå ʼnDÂë8–e]ÓÓËåâܹsÀ LÏdí9Ow€Ç²,×ËœŸN§=€g¦ë_. *¶mÿÎ<’ÛÛÛ›låñÇ¿yÞ¼y/ßpà ¿=pàÀ7n¿ýöÂ@Ìl—$ußþ6óþþï™ÿÿxÍ̓ƒƒ d4EQ>?88¨³lÙ²¯?ùä“«üñÞþþþm555_“]]]_zàúûbÈæÑ?>¿üå/³þüÏélk£´´”Ù‘áÕ\tI$éR€­=õÔSÏF£ÑÚx<¾®¾¾žx<¾¦ººzMCCÃç<Ø?66–hiiÙÿòË/ÿõ† þ}v,=[6mÚtí®ý…À0 Ž9r 0[1 #õƒüàÇßÿþ÷ŸûÕ¯~eÅb12™ áp˜O|â ü~?[·n}>ÿlÿþýßιˆàLòë‹d2ioß¾½0[F€ÞÝ»w¿Ößß?ÕÙÙI,cpp·ÛͺuëÖÜyçŸ}î¹çžŒF£ÿæ7¿¹ó‡?üa].ÖlÛVþp!CCCg£ÑèD©ã@/éèèøN*•§··—'N`Y+V¬¨yôÑGÿW$ÙÛÖÖÖÞØØ¸û¿øÅÆ?¦P8ÏAgÏžäü?H5çÓÀŽÅbæ‘#GNhš …BUŽãH$(,,$ iMMM«¦¦¦b?ùÉO¾·råÊÇÖ¬Y³ÀãñT-]º´\J‰‚þþ~‰F£çÛÄÄÞ±1ƶm£ ¶µ àñ'V®\yÕ‚Ÿ¼´µµ½³cÇŽmÀhNÇÀ NÈäØ2 ˜‘Hdøøñãƒeee ~¿ß“J¥°, ¿ßO8¦¨¨ˆT*Åþýû)**b:bº¢qûí{ï=V¯^}U”ž)¯¼òÊ[o¾ùæëÀ¹|^Pýˆ,êû\bll,~àÀãEEE5Á`0”ÉdH&“â÷ûÑut:M2™$™LBu5I྾žššš«¢øÌ¾]»vêèèx=7õÛ¿KF(€• ’ñx|zË–-›6mÚt›eYŠišÔÔÔX·nÑh”P(„ªªWmÄgöå§h!„•ÓIÎLlþNÔl—èîî7«ªª].©T Û¶ñz½‹Åp'_øƒ9#}Ïž=]ííím@|.Ya;§üpŽ@¬²²²uuuÄb1 ÃÀ², પŠ@ €aÄb1‚Áàïmäg+,„øÀèÏé}IÍK|gÞ%Æ€Á•+WúKJJøìg?‹×륿¿Ÿ¡¡!Nž<ÉØØº®ãóùåJ× >Lù|ßÌöQ2—”˜ÌG‹-º.ï_«W¯&‰pèСó5@Ã0(--%3>>Ž×ëÅ“Ë^Žâ¹¢ëùZ„¢ª¸4í¢œ“ÿÆ|ÕèrÈ×\Kòu@Çq¨««# ±k×. à “ÉJ¥(//§¤¤ÇqèêêbÉ’%\Ò ÇÆÆ˜˜˜@QTUÃår¡iY…ó…×LxÛMyyùy³ÿÏ,A›£òZkkkEqqqi*•B×u¤”X–…ÏçcãÆ¼ùæ› Éd0M“ FÙ¶m/¾ø"=ô¥[–Ewwn·Nee% Ujf¿iš œa2>Iuu5~Ÿïâ…9Z€ºaÆò£(„@×uÜn÷ùÐó–[n¡®®Ž¾¾>¢Ñ(/½ô>ø }}}|ë[ߢ½½ý¢/øÿ8BwwË–-eam-º®“J¥H&S$“IRFê}-™J’LeûÇ¡zÞ<š››™N$ØÿöG^Q Ы««—å>ŠªRPP€iš˜¦Éu×]G(â™gžá¹çžctt”÷rQaee%[·n¥··—Í›7ãv»Ï'.^}ukùn]gr2žË? „rþœŸÉå¬C€”¹)ðsCi){öìá¦U«šøÎw> Ì%>PÖÑÑño ,XsîÜ9–/_þ‚±,‹d2‰mÛŒŒŒ°qãFúúúB i,^¼—ËEss3÷Ýwáp˜_¿ð«V­"ÎÌXÌä?V\Ð@Èl‚ü¾ )Å®– sGÝ­ÓÑÞA(\öÏk׬~$×Ì 0ïĉo{½Þp4eùòåƲf›dzzš¯}íklݺ!ªª …hnn¦°°ªª*Z?õ)êêêQ„@(Ê…•œYÌ8—9u3Í"k)AJ)Áív³woŸºcÃmåáÐ€ÚÚÚZéóùÂ6­Ì&¦ÂÂB%K5[¶l¡©©‰ï~÷»Äãq¢Ñ(o¿ý6•••Üu×]ŒQ]]yåÞg–µç™£ó£žµˆMäø &&cènUESUTEÉ)çÂ¥eû4UES44%«¬¦e—Åš¦¡º´,PšŠª*lß¾/ÿÝ—Ù±k7F2ÅääÄÐ¥ dÝÖ½tbbÓ4¯åååTUÍc,:Ìá£Ç¸qå,¨©fÏž=à8x<ž¬òªŠªªçд쨻tªšíS5 UQpë:…:t2<8ÈŸ»“ý25ç†ë›xúéÿÛ{)9ÁùÆÞ½{».Å–]@¨æ¥@ÅüãÿùÀÔ^ŽôôôÐÛ?À²¥KyõÕW¡aqo½ÍüšyÜѺUUˆD" ’2Œ\b$;KØ–…í8hšJ(¢¾¾¿¿„}ûösààA®o¾ž±ñs¸T…͛« iež¸ûî»þéR“¢  /WY  .—˼NR¢( ~Ÿ—ß¼´;Z?Éþýû:K(PÌéÓ¼±·ÊÊ ÊËÂ4._q!›$%Rdó»‰mYŒŒFåXw„îã'(ð¸ILÇ))ö±~ýz^Ûµ_QŠÂ䥯N.!š&s x5MK_.”••!„ “6رóunYu#ÉTŠ£ï¼C¸¬”Ó}D£#,^¼ÝíÆçó16>A&FJ‰ær,)Á¶3 Ñs¼‡Øø8óª*ðû‹ ,ª­gïÞ2–Íu‹ñµGy—Ù¹–ß0MÓøÈÜÛÅ®9ŽC:flìU„B¡·€ÒP)^¯—÷ºóÛWw°xñb,+k-wþÅ_Èö·ÞJÝwï_.+**ºôÖÕ€o.¨ªªTVVÞôÕxtó§?u»|}÷núO±l95• ®®NTUVÈ… 拲ò24U2·ÞBAJÈDÆc1NŸ>ÃÈèˆì?= &bã²¢¢L„‚!Ö®½•ƒ»x£í­gN÷µ°°pôr¶ÊZ9.8D÷\RTT¤666UVTŒöžŠ,á…TÃÆÏ|ZV÷õÊ“'O188HäDÉén·Íå!GGÏaY¤Ð\:¡`‰(ð06ãôé~Ù××'=·ÓÜ´‚@ „æ¦ëiïè“SSÓVÚxþᇶ-˺ì™QrÓ£:× sSS“zÿý÷µ´´”µ¿ùæÍŠËýHmm]XÚ>±v­óαcŒÇb21—Ã##Â4L „¢(B‚P„Ž”†aMSEyy…]PàqˆŋEooŸrüxDº ìÝÇž~ä‘G~ãñxú¤”W"¦\ƾÁ»ï¾[<ñÄUUUAMÓæÿú×[WìíÿüÒ¥Ëk^}·uïÿØì,]Òàħ¦ÄÈè¨L&SØŽ-r~¯ „H¡!„Šîv‹@I‰ òܹs¼ø›mŠÛã¡` ‘ˆOüÛß}ù˯ú|¾ãÀ¨ã8‰kbã”RË‘hØqœùv6¿òÊoo“B]fši­¦¦ÚYTWk×××Éâ’b!@Z–¥æÖ÷)5P‘2LqæÌqª·O ‹‘¡aÊÊ‚ýË_»ãŽ;躑R !â€y­ r®ä•R†„•Éd²vß¾Ž%ííû¦S©òúúEž%Kd0t Ôãã1%·ISŠB±Ï'üþ"WbzZí=Õ«t÷ôXÓ8÷gö±ž5kn= …N9¾šL!„sÍly•R*9.ñH)ýBˆ PšN§ËÏž=[~ôèѲ³ƒƒ%.ÍåõûýºíHÍqlЄP„Ë¥‰DbJš†aƒÁÉÆÆÆÑÚÚÚÁ³À°”2*„˜ÈívI !€ÿÊÓž\<æÝþIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/del_dev.png000066400000000000000000000207631217176075400242070ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËgAMAÙܲÚ!ªIDATxÚíkŒUå¹Ç×ÞsƒÀAĪ ‚w¹jE‚:z±­µIMZ?À©Æ~°iMš~hN¤=_͉=Lí%b›4'­ª¥1m9"”j±rÆ**ÊŒ‚€\.3Ã\ö^çù½¬gûîwÖu3ÀÞ°ßdÍZ³ÖÚëò>ÿçþ¼ïò¼z«·z«·z«·z«·z«·z«·z;‹Z®–þᇞ><<<ýرcæÿ1cÆx¹\®çW¿úÕ›uÒÖ8žx≹…Baº,s§‹Åé3fÌhïïïŸÛÔÔä]pÁž3‹ó|ß÷ÌÒØØè>|Ø;räˆ×ÒÒÒµÿþ®¡¡¡.Ùß-ÇßÌçó]<òH$Õ€•+Wv!;„ ·Nž<¹câĉ޹çžë?Þ»øâ‹Gå»víòŽ=êõõõyŸ~ú©'Àx@ȲN€õÊòåË{ê8EmÕªUpw‡pæÒ &Ü3uêToÒ¤IÞ”)SÊ0—KÜŽjH{ínÓzzz¼x{÷îõ< ^ þáÞ{ïíªà$´Õ«W/Â/ξÎF”#²•¨îr2 pšØÞ¾}û D: *þ[¤`è©àÚÚµk1Ö–I‡~O¸¼ý /4MöB³>MíÖ´BØ güÉm·ÝÖU@F‹H]!FÛ28ýœsÎ)q;Æš¿Úš—Ú{öìñD]=#ûÏ( äNáÛ…ÃWq¿Nooo/q»ZêµÐ¨• ‡2R ˆ„xT€ÐS€ÓÞxãeÒaO··Cxˆ —ãºÕ áÃ$‚m€ R¡µ°páŸÖ ­³³³]tèÊæææ{ <W«دõ„û­p%Å>xE¶—ßtÓM]g-Þ~ûíé”UcÇŽm7n\)(ÓÒÒR•:þD= Dµ6>|i°üúë¯ÿÃY€Í›7/“—_‰U/ÜoöAx8ÿLnH€ D ˜È£¨ˆŸ,X°àÇg ¶mÛ¶RVË ¼Zô"jV×Wb‡PÛi ÛÏÌŸ?ù€÷Þ{Ï_ Ñ[[[Ï8‘ŸF%ZÖœîb[[[Í€ "j½ÿþûOÈêûA;[‰B˨@Ù÷Ìܹs—Ÿqؾ}û2Ñy+±†Uôcø­Ä·AÐÛÛk@À66‚¬3gÎOÏìØ±c®º÷G9âŸ-:? 0Y+ “)€¸mÞ¼y¯œèêêêܹsç\^Œ&ºîŒ·ö+ñH9ÓöïßO†³K@ ˜W•QÃÔšîîîïÝ»w®ÆÉ5²§aÒz;ÞP‰¾pa}ûöM¬CÖ¬Ñß.ÄÞñÎ;ï´ŸþùFô“Ø9Ûõ~’*€9Ä[òÄ ‚x©H®š”‚èïoÙ²¥DÃý}êœß01 ©y¯É›9s&R`yM@8ý{~ø¡7{ölCx^®€D¦)…Ä I.ëìì|´ÚlDìڵ랭[·š"¸·Nüô èïï7¥n¢>½+¯¼òÙýL­I€¥è±«®ºÊ€—²‹%ê-ª2ßzë-ïꫯ^Zswv‹Â&' Ÿe¤°­"l€è( ån8V ¯U>'Ò^V³ ›GW:ÀCÅ=DÖE˦Ծ`[séºV"ÙGaI]¢Ú¶‹mé+!õžö¢b_ÏÑalz~Vû LLž<™ëó€ú~Õ€qû|ð‰ª„ø6‡Ûë°ÅV#®8×°ÄÙ®Ïo/.(Œz®þ¯çês¹£‡³4@üÔœ¸ôÒK½¿ÿýï¦Ü9ë ('Ûú]9Ë%¼ Š(ï M< ®:h <÷7 û¹* †}òÉ'æ^dsUVE“ 4аˆi§%~§ÇI,QHÒý¶Zˆ€r¸ ÛEtƒp±wfΜi«€ªˆU'ÎÊ@"èꫯ6œÜÝÝ=Bw†-êW'qv Â<ƒ8©¦0/#NEI×MÓ¨Ob#HO˜'@Õ´TÓrÌ›7ϼ4ƒPiˆÆÉIÄŠ#H!Ò¸ŒI€JFh5εE…û9wþüù •¶1XÝqŠAòÍ !&L˜9´§íô8bVªÿmŸßÚ!`ûÚ¶‘åÕ†s•ûI‘¸æškô¾µ'h·ß~{)ä»mÛ¶PÄ'Eñ’¸/éü4ŸUÌ"Q¢ÂÒ.¸ÃÜJj(õþ‹-ªÚ\@ºl50}útc $Ù±cGY¤Ìýi€D¨¸XÒ}âîŸõÙÂ~ã>‹Æ4ta>B A1ü–*þUÜzë­U!þ0uêÔ.ûÿ/ùË%ÃݶsçÎâ³ÆòOäœ0U R!Oj蜃 £Ýyçe}ú¯ýë­š‘ ³õuK–,)Í ³g…qhÖÎ G…zãÎ »–«ß£$IZ •› ?` ÆO°ÿ¦›nò.ºè¢²Èäµ×^;»f ׎¨·ÛÂ… ÍHŒ@†*⓸2MÄ0.°c_/¬Ê'ìÿ´¹‚¨{gù2ý d@xúÊn„ˆíà‹Kè×L€( Ûî¸ã3¥+/Šw@°ƒ—³-ì$îMÛña„›>6m8ΣH’î3êE%âçcññûÚ×¾6â¾/½ôR͹­[·züqÙN\›xÀ€€m&uÆø0Ófβœ5ßoT‰W\ý_R`R©˜'kÌhÒåˆ~$Äv£_ª±$,9ËqÂó›ß4vÛDº°z…„“ˆÆÙQN"^\ÀI¥ªÈ}&‚b¼+^ч4¼ï¾ûŒåï6b4‘š~-IÓÈâÖ„àî»ï6⑈ARǤ?äAœþN«ßã$@ÖûDmGI¸¾@íÁñ¶üêW¿Z8C|ôÑG¥ÿŸ}öYµª>œ£]ï¾ûn™?« ®Ç3÷Æ„L¡Ó¥P"Æ6Æ¢æ÷Óˆö4…iÕK\f0ìXÔ5pñx'ÏsAx‚Aüç_qÅ‘űÒú;9§X-`êP0ˆG×ñ"Q•A×]wq ‘D á: Q©S©©…G›èöº’j’­´Ð°mx~}Ä; ײoú0D=Æ!3…0_€“ ðk¤ƒ kÂHF AȰ†* ƒ0µ.@AU‚Î j_D‰qMÇ&Ùi%AÒ¢•?vµ/ÿ#îuÒködŠetÚû°xÞ~ûms]TbÚTzU€’0:€ ^}õUïæ›oŽ,ƒûé%8bŽà\ƒÁ%€‰c\WËÈ•ómño—kÛç¤ñÓãìlZíÃsAp­dŸr<ÏÉ3³Ði¦Å{óÍ7K@¢?`ˆj3“àCL8O€‚,ßÎÎNï†nˆý!œH”x!f4@€H´ .9O+…ìL£›­s3~•ª»ÎOsöǧ¾r¼‘{ò^i>nMD }€Í5GëÛG§ ¦÷(a€(z }G'áÒÐ)n¤+Ê¥Ò9uu:0`#T„[ogWäDÅÞãÆØ×±÷Û„Öuàž‚c°²¨$€ð<¿ MƒAHñ®ü޾ãÝ­Š Ú‘pR€êêê*Ŷ± è âÝiô0"‚ÃA¸JtÎ6O'ÁyJ¼¸h]ý¦ íˆsé*‘4«óÜnMB\ûç?ÿiŒa/ýÆ6ª jÐÍúÕ ÓHc݃dŒ@£‚-^¼8Õ|ü"c ÀŸN¡óY ˆæÚq!YÔï†0#‹{¨çpmΖûbÄÂåšÇ×5 Ä•…ðl‡©¤¸öüÃøûjòü¸ÐZ<{í Âÿùå—K…³fÍ*q¶ÁêÕ«aˆ´HÛè$ ê‚à6"iô³qp¥NAëÆßu^Þ¤¦Zºœo‹~|%Ì<“^Éò+ºaóÖ*hÕS:ümÁ‚^5¶Xhð!ê×®]k:‰2g8W_ÃðÅ_4ç(Ò³4:Žk0¢)£ê!ìÑi'¦v@ýp¤ÖêÁé:R©ÒoÁëׯ/•À«¤P¨2úŽr0uµ dݺuÕ‡íÑÀ Ä}íµ×ÌËáç#ÖàR;D ,úâ¿X*ˆ¨¤¡CéX¦¥:Y'ªÄßj½+1õÓ±ü¡9mÁ7p5MøCäà :¶@%  °ñœÄ<´$ÌmUƒ’Э\’©Zµj•! ÖÐÙ<®YFs;±C]$ÏÀ½ìŠ($$n @Ÿ >íäPµM° y9¶;w®Gz˜……ÛÏ:m¼ê;"HE±û9ØZmp;„× –]®¶ ’KgP!2j{IŽáZ¡`¬R¾Šð¥K—%šA;’ÄóÒºU Ðaå’K.1b»çæ}±îíÏÔ+'k<‚cHE¤ –‚“)µW®!ÒS+‚ª¢%„`ý»¾o|ãfZàE± è{Ø7ÇuQ‹xË–-0Ú‘ÕÜP+p<ßB Û¾»¬}ïóí!Y¼Ž£E}Ý–æÑsèð3fŒHö½Cäm£áò¸RgÓ š 5mÿ9,t|«L7ëç[ݨž;&‘û6‰šš ÄÓXNì4@ðìc!„Ï…ˆ¬&®"ü( 8„AxÏA°4Êr¾ðnÿ1¯#³ ¤÷×Ȝۄ‚±P€ÀúbÉ_ÖÜ¿Xqgèˆ[ÛR#.iÏ+8Ä'láþ¦pb—!øa`Aô p‰ï;:ÁOZGq¿?mò'¬‚l ºŽf!ÍyË-·D†Q XÃEü0ðµεGGÕñ' Šðº.S9fŠ i$@°/—+çú(ñŸËE[U¹(‘'ú]‘&ú½r‚ÇI]*ñ( #ò…KQ#ƒ¢@)¡Ó¢‘3 Ž E v4L½w—M줊^û· 2ÛÐÌ›pÎkj JyGx!RÀEŒ(ãø\²˜VD‰›Ø#`éÿÒ¾"‹¨É¢êó'„:Ž¢Pj˜1 7m„Å ÔBþÇud’)MkøÔ¹RAí…4@½W­ðÒ-çŸëµ]x^pí‘F^¬ø"xѯ¿Ê`G! ¡ˆº¯ Ò{p÷ÎÊ%ÆLT±NR½®óÅÁž;€ÿ‘Ø:wŽV¹žATF” €;h—ÙhnmöÆÏ_€ÂùiˆçØÔ¯ÈŒP#ÔBaÿ–M^þP…*€N#žè'Î ÷³L„Mr2â_ÇË“ç'˜ô£JØ œã–^ÅÍâÎ h=(Õ÷q^Ïnoxó¯al«Q¹Àé7œ¬óÎÿ#¶£ŒFLÞH‰‘†ú¾ïp¿Kà½î«˜wþ/ûŠ"›|ê5¶y™UDi@Ÿ3; C å"Êé`Ò¿¬Ó€€†[ˆ$Q5¡c°à`u9uTñGÒô0v¬›æ;~Çú½|@X^dü_ÌY@Ha*b„ªº"€†ð.ñ!¼½/ø_D WìíÏ €¼pcƒºy™¤é^@¡ù~‚@¸‰D Ó6tµÖâe`$âbrþçÚdÒlãNËÁì!jìÓih5ú‡DÑï„£-͞ϗ\[¤#ZJ!?? ®¯Ò ØöÝ0aHÈзˆî{#mß‚ŸBøqH°ì]xeÆßç¿C"dU9ÑÓ *j¿ò•¯xO>ù¤!@¸òÊ+KÑ:&x HŠ,E\÷’ƒÆ y¤’FÃÄ:ÚVËÎ\  ®ª[öýÑØ–ã`Ðú9Q•ørÖ¾8(§û–$ð½r@”hcú zß%¼ ŒHñoAévf ðõ¯ýµ7šàR­ Bloß¾½ä Ðád_xáïÆo4F^% bÚóí¨€A1" Ü ¤Åö 6A¯iÌq¸É‡èê&ú ß÷¥}ÞÈu (il/ÚÏOãã{ö±âÈDA1+„¸ ¢ó²ì˜ZðŽŽS ‚±´ Dç†@ŒB|S ㎑O#Ü÷  .ì/r¸É!5í4-ëÅ“} kÎÕùrbz6g;ÈÙû¼èµ_aD0̲Se )–Á@& š.Ê‹!¶E¬ö‹´€‚_ÿú×FO£1 )öÐNW=mpÙe—™:¾Ñ,IšÄ ±n$@K¹È%ëù@ðÒƒáÓ€ R „Áñ¼ •*4 ¤ 1Qa‹Ñ÷ÀÚñLG¥ UÀƒXëˆmO͹$ˆ Fc¦ì¬ÓÁ2Tjp츒 ™óut»Kð21ïØЇ²í1a?$äùÑA Ì9cì¡ÂqÇ+d€pû_V¬XQÖñ„‚!.õè`D0µõZ?¡Ñ8@$œ‹—fI%-,bˆhh?Ïkš*RjÒäädPˆ_ïŠÜÈ_Ú¼@$°cò¹°$QTN "<\è=êÄYÊ7da‹kÖ¬9ôÝï~w•c÷ÚÇïºë.³Æ´gQK]cüv çà-4b4‰ïVí S`Ðäùyeë/oJ¶B¢!õQëPß‹®Éeˆæ, q#½…ב@Ðá¿­ñÌó÷d©jÝÞ&@hûÖ·¾uùC=ô¿nEþ95ƒÔÌ᪑†­ œn'{tªuÛ¿×ì Åö²T¹Ÿ²S›dÚžnï– ôš'OñÄ%ÔÀO)h{ÒFcÂÆ¡uI:?*á“Ò÷·×E'Tèð†öíõŽõÑ·ÞOÿ­Ï{4-gΜÙ*Ü&ÙöÜsÏý—¸[w‡€8CÆ ¾Ñ>ƒ§UAöh_7Ù£û5w „†°•@½ÖS|â]Ö½Õߨkh©„’÷#"{¾“*öK¬èK¯S›cŸ×;Ÿ@b¤ž(}ôÐþüÑÏöʵ‹ Òe9¿­ÄÊ.Î ò( .zE‹“ ýfo­h_! x°†¯ n†g¿®å7=Ãï…ÛŽŒüryò¢ÓÇÈ ¶‰;×öÀ\þíoû9!âx¬1öPÚñxGˤu¾7dë Lë'Út‚¶ ãŠ*8ôÓvÜ…ûép/»ÁõÜmM%»ßÒ)aXk´Qk±mP{Q×\»víl‘&×ê•gè•ßõ±–ëôÉûô “ôÊáÁj+ ¥5‰'ÞŠøÅ/~ñЬY³~% ê@ՀΙ¯Æ q»Àþ,KTª7Í$N4ˆ£á⨢’°m»¤Ì.1³ ¯im*F‡³³ÂÛekî}¤?^X½zõÿ¸Äàˆ”„ø}ÃVuÈO™2e¬¼t›<0ª õ÷¿ÿý“òÒ·º°·É 'q0•àöwÃ>7[WP >‹;±T±íGÙác[Ùß D•é41S÷Œ"¡>þÍo~ó#¹nŸ!Ó÷³ŸýìñuëÖ½ÈG÷#òýž’á×ÝÝÍ<8§ý3ã©gDN(ÀÅÂi9y©œ¸~e{“¸Š‹ä¥Æ%Í¿§©³ƒiþžN×ÙAXë+{Ü@ا䓾.wL'„"‹H–‘„ÿ£ÓÕÅx%‚©†eܗȬZö=õÔS;âÂcžÈïúññû„óûªø•”¯0 ¯ºêª {ì±§¤ófÆI€°E‰OÁ(Öµû•.õ,´*ðè—Cm‹?ŒÓíÑÊp·m:dÌ*ûbÏ}lµáæ8Â$À¡C‡>þíoût@|cñkåþ¾j0úN¡ê@^®íç?ÿùŠ~¿3 lKŒE<îã•N« ‡ØNGÙöEìÞ½»óñÇZÖŸ…‰}yO„jû' ÓDô·¢[ # äÅ[øÃÞyà 7üH^~\ØŸew¸U+ƒÐËp±#nt½ŸópA!°Îׇ;JÑ û5Tí–i€Èß°aÃï~ùË_þ ‘¯\¯œññ÷E}öÊ3ôLÅÔ0Ô†=Ú*bÍ„‹ ‰J˜òðÃÿ@Äú’¬ƒúµÿÇ›€€ú;vV÷AlÍLÚŸªwçª{öìéÿwb íVŽ·DþQD¾€Ìü/ÎÀ1¯ŠfMhk¹ä’KZåÅ >øàâ믿þAÇì“wˆš#h4 DÝÿâ‹/®\½zõˆ|‚Ÿª‹ %—+Ȫ ¿Hr!Yeß ky‡A¹Ïü? ‰ˆì°døóÊ¿ê@™±(FáyàVéÜ6é4c0Þ~ûís®½öÚ»ÄN˜#D›~: ×Ù/:»óõ×_uãÆ] àv? ÷ó…@>¿•{Q0Û Ä–ÿóYæ–MÃõ€A ‹ƒâÖÊó³8‹Ýq:ælk[™¡ÆRg€Šj={öe³fͺ±­­í ÄuB°i'ÂA÷õõ}´wïÞ÷ÞyçmÂI{èh:Nt;Ѽb ¡q£Eô¦Ñ&z’„Ûñ|ºF"¨t@RšH0ƒ_mpï èÌ1ª*°Ø^°`ÁìÖÖÖi"9fʾÉ,AAÆÅxIýï#”÷ËöѳD¿î.ߢbb“œ‘kÒÃ,ò¶‡,¢7#âe kÙ×pº: PåY\ÉX„9ŒD¾t0N"Tã¬Z¸Ý8iÒ$ÁCS‹GhÚ2V^Ò€Dþo•m’ñ-,k[ ËaŸŽ2âSvÊqÝXëÆ€ t«1Ð0 r^“t^#ÿËyNo–}ͪßO'ñmiHl’0È; Œ4 DU?@lAt~ô$Þ«EŒÔ±BÔ–D¥JoéX ;3Š:9„EŸ·ô³Zñ9Go‡î;ŒÂs©zÂfiÀ6a QÀat—•ô+ÖN)Ø¤Ó CaÕS}D‡­l¤H•b`ÙsŽ!¬=t]’c¿;œ;"–’Áõƒubà …óQSò,FÒ—[Š"Í|½.«Ž³Îv ãNÁIp-j#øÒã"á(T‚ÇðCBÀIê(a•pA1Š9&¿÷CˆI|ý½%#Áw±(ÏKìÄ-÷ ‹Í3,RT½¿Vl€Óas4Š›Š®ÏŸsÎ9ù@t6ÌAì  :¢•O.Œ¨Bˆ$îõ½„1"/àX%tÎ%¾wE  x©Ñ(îiñСCæ÷,âÒ¸„u”÷…=\”жѡÄh}nÖ'N4E1öÀ”X.§³?I´ó-Aˆc/ǽØÖcJ`~C¤}âŸúÛÄu$÷K.ű´#ýA“#öþ$÷Ò¹uœ‚°y.å¾°x~>0Þ ¯·z«·z«·z«·z«·z«·z«·z«·z«·z;Þþ†@y'·’ÔIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/down.png000066400000000000000000000067421217176075400235550ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ ©IDATxœÕ›_Œ\×]Ç?¿sî¿ûÇk{׎Ih Ð$TˆP"¥®*•W$ÞxéS³M%"µBðÂkÛ¥Bâ)TUÔ;¢T¨ZZ„ÇqIëx½‰Iâ®gíµc{wvæÎ=¿çÞÙõx½fñ•îÎÜÙ;÷žß÷üþŸ3òøŸ_`Ô0@@Z]kT<âAœ`Î ˆ'8' ‚9‡x@GÈ…Éëi=ŒÌƒÕAÊ›ï×ÿìÑ{>KO÷~Ç!0 ¨ò'OÎðÍs·|'G®­YÉŒAx¥)˜ ª à°j’«™7SÃÌLtãæ#FâÜhoh*ÂîJõ]|"µÔ¹ŠÃûœÄ‹Ì°ž¢A!P%ñÆx*T'ÆŽ:Yk›®ë©Ïó\ FŒäòîHohAMV%oÝì¦õ_˜ªt¼8sNÄ9DCÞô 1ÔÁÌ”§á¬¯C½Âêzfˆb¢˜“Ñë@ò~;Œô†jru?$Sɉªú´¦N.qÌ‚a0œi”ÊšU'+móïwóÞáZÒ˃™ªä& 2Ò¡¨–T5f’:9ŒwUs®næRqÎS“Ò(dÖèû 04qyŒN×l% ¨*Yé6FÄdÔ´€÷žiDª8šb’8‡˜±Õ”ûR àÅ\’›vÞQTqÂÁPŒØ¢€€f«˜¸&ª)NF”߶ň@â”j€¶@U ïw HF~Ç8GâDŽ#Î#ÒĹ*†`jýI´h/˜`bˆ\¯njw€:HÿWDx`$ÁIµ*ó\ d>`#Õ6Ð!™€˜Qæ+¶" ÀI¢ä½ç&FQ Ò¯Ÿ*‰ƒ 4‰Q ¥$p/(8ç>o²~yyëõ`FóñãXPDK÷ å´ûØš–qà+[ӦݡÔ65jzÉ= ÅcÚ ËXPGò€!»!aÑuoBÃÆ8-–¦T™ÁòáÕ´6.¾âIí…e$qQ‹G]7Ø”ø¥ðª¤ÓGIMcªEõy/†Ç¡OFâX{ëøÑ’ Ø}µge¦%9Š…Pdß÷W¦íƒ " Þѹ²2rÊÊi$ؘy£òÐJ»=ÉÎ ðŽÎ»+àŠóý|  ÜúñžîX0*MÆðºáa§EFI‚st®Þ.HJNw‰"Æ›éñ(ü6vžn t~'’ÀH╉Ð>0(üÑ Š2»Ñ£Ý%Âαۺ#Å^H¢À鑿€³Ûv_ NPœÐ]¾[´j•ÍY˱ßP4VÓɱ"šî-uß[)T¶°œÝlãœà‘šu{…ˆÿÕ{zƒ} "I!˜ˆ:‰ñ}s²`Ú¬øO 'o—j \²K|ÒNÚ.(Ú4ï— RLÄac­F@Õ3.FÇ*B6ŒõD¶ PÍÈs#Ïõ/oûØ‘fZ±eŸÿM\L*d$ÞpjâÄJmÉq–¹š ‘ü†¤á–-ù ß–”›Nx*+C hT6/(´M¿xî+¿ó¥ç¾ñ&/ÿ÷uj¿4›; zK ”CÔ\ÉŒç/eüà–Pj 9Ô3PV;ƽÓ%¿Veü± õß`¦Ó`&ê–#næðŶšþà— Ù¬_Úç '>CHŒ— ¹íŒ[ÞÝ‚*ªî⿼zƒ¿øÃ_äܯœô‰:•,¶¼7|à½BÈ`} ž{7C\ÊÔd€Þö %N ðÃ7º$3=&þÈã¼: ¾¨> Îo|Aʆ«\]è®í×”éßw<ü ÏÚŠ­ûÄjZEÕxI¶¥-eâùΟþÕ_ùÕÖŸýÝç>É÷WAÚàt‹O+ H€%í bHИ¶{ò2ãþ(!uÑ·´»†âFªhÔwºýçÐ]‡¿íøå'=y$á­·Ãé^› V•[Á±Ð|Ø0Ü@Š&Bêªþ‹ ׳¯ÝýÖ9ž:k..d¨‚…âÐͪˆÞ ÷ Û‚qx·ƒXZVÕ‡G¥£¼¹xù|÷ÔÿÞÊ_ìÕí꺄w:ÞïZªŠCõBÆjÒ8TûÂwÿsiîî ¯ðÔ1X­ì;õ~À“w‡¢ âpÅ!½ÀÕÕ@§mó;½žØµµ:¹]ëõ¬ëî3ÇQæÜ^¨ÏŒÍ~÷ìòÜÚ?¼Â§Ãj-Æé·3w #:ìÃUGÞ ¬tÍDN%ÎNwÔZ½Üóž-‡`mU#ë÷EÛ΃x/4fÆfÿõìõ¹¥¿=˧ŽÂj‡H‚MñpÕz[QøyÁ^Ìrk©ÚeU[k‹Y¨v£¼ÆfÆf¿÷úÊÜÒ ¯ò©cÐùH(Í/78\sh¸Ù 4½Ì£v¦~ÑÔZ¦Ö¶`<ÈíÈEçcÇš³ßýÆ×[/¼Êgf> 2UŽ7+8ó˜Î‚µÌlQÌ–ÄâÌïÄ »õ³Á£xئ4»IcÇšŸÿÞ…s‹ÏŸåä4dUȘ„2úuK°h­ÆS9%f§ó`×Lí²¨µPkvÓFÀ£´%焱£c³?ºt{îÊßåéièUãV®Ý‘°³0ÐÞxt"E‚qu50™Ê¼³hóAí²™-™YÛv8ó%9ÔÜþéÅK¾qôÄÑÆìÞ¼ƒüý+Ï|拺é]鎛Aá?v¤BÈWîäLÕÝ)1;Ó ,«ò– -6FQ¤ínÓâó¦£x3¨ÉMÌÃ'¦ë³?¼xçkÿóW89YÍ“hCï†ðÁxüp ÁX¼ÝãpÍÍ;“;…·7¢Í³Ë™ à~jÏ}uZ0rïPñLL7¿pöíÕ¹Ÿ}ó'B^KÉm;Š¢}›ÁÎü¯IÑ`\\É8Zsó‚YÏÃrP[T³–™­ïg‘uÏ»±Àƒ01ݘ=ûöݯ_üÖ9>= y£B.{Ó„ áó(|ÆÅ3 wJÌæÛ]½r[°`?µ¶„ýõÈöe²e%g&L®þì•Õ¯¾þç8yTie{M(.è ¯||&%¨ñF~^Ìδ{aYÍMmY°;ˆóÂÈš¢ Li<{á½öÜOμÎÉE«2‡>ú6¯<1]!ôŒŸ^Ï8gþt»k­»Ëª²dÐ&ì¡Ú‚‘PšC0áÐTmöÂÕµ¹ ßyƒ“Ç TSr$ÁŠÇGot¸ á?RAÕøéŒ™º›wf/µ{z-]4 -ÑЖF¶GadQ«4‡€cb²6û“k¹Wÿùg<= ZMééM¿AG5†:6?]ãÛbvz½®…¼ðö”Þ~tË/#ß([þøab¢:{q¹;wþßxú8HÍG¶ØCôöʯL¥˜o.g©¹yÁ½Ôîér/¸EEZfEœ1dvœ ÇøDuöÒÎÜùÿ¸ÂÌ8¤šlhBió=…G§R4À¥›GJ›ÏB+ävÉ4,‰æmÙEz»Ø6ôrGÉØXuöÒJ端þø~︇ÄÑ ñ—e=ƒL¥„Þ¾•q¨âæEíL§ZÁlÁ°Ö~’œàÀ€¾skVž}ûVoîµ³Wùäà ¾âYÏáÄdB¯§\¹“1Ys§|°Óë¹µr•QZb´c¯íà–\lr 0ñŒ7eöÝ÷3äµkÏ<ùÄ4ïU®/+À¡†Ÿ³Óë9Ë&,´0Úhì$œ(òšõdöêíœÛç—ŸI+ž»=c¢î^“—;½|EË×ú…MÂAw>  Á µj2›©­u2ý\-qC°—»DUÞhíø…¦Íò}Ÿà/{ãËyåâ&Yá6ñ÷A(>P6PvDÖLh;!ÀÈ»²#|8ôÑ;X÷`ü)~]C˜ŸÆIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/edit.png000066400000000000000000000046471217176075400235350ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ nIDATxœÝ[olçÿÝÙ¾ó¿`'ñŸK`±Û,ÁAÚ:¦ ­°ÑX¿MbÛG4Uš„ÚÊ—mbêšT¢âKµ­Ýë¤ B5 úš;±Ãv ƒ-„Ud¤ÁJ'áαïn.ç:ÇÙ~Ͼ¸¥?ÉÊûò¾~ïùýžç}ÞçÎ…uX,ˆ¢XlK’Y–¡Å¯ÞÀÊr¼ÀC•9ïýú½gæ=/ Lx{ËËY䡬@Ï(µ¡µ­âðáÃo9räÇ««««U¥¨šÆTh…Õ뫟Ҿº¶,ËÃ0¶þþþŸd2™d¥kYI x{¢Tˆôöö~«ªõ F©jTŠ¢–eá÷ûÛ«}_WI’ŠíÁA,-eaw°€µµµâX©7µž­uL%UÚÖóv)am[’-Z1  "›ÍBreÓk×3(¢¨Â¨m½>MÓºíÒùÕP@kÈàÀ;ÈfÕ„·14B5‹ þ5¥aüãëž –Éö¡ZÏj=®¡”S9ÐÚP9qü–²KŽºFmí_Ò èÒ‹þö7(aŸËAŪž¯D "¨mmè«ml˜µút¹µòä(ÍÞ•æUª‹PJ¼¦Ð´9A@¡P ú¢ä6KÒðÖxñkÈårÈ @òµä#󌈠×ÖΩú‘äóD²$ƒ¤ºßlo“Šà™ó_í—û®t¡P€$){žŒ~íY,‘‚%ÉqR#¿ÈbÉP½­5ƒ@#‹¥j IÉ›M`3ë#0ô@DkT#ÁZNÀlr›Y,‘ ¦h$¹zŽHÔµêÛ¬bÉêÚ_æÄH bJCë«$‚)[ày¡f*]¼ËËË‚ 5¯aºO…+A–åg¶Cié©×&ãyüðC° ‹ÉL‡‚$Il®oÄhU&@EVWVðÑÙàó·â7ßÄÂügÈå× Š"¬V«a!Š@,€var•Œ^ZZ‰wßE8Æ^‡ÏãèOâØ[¿4,d9»ª8¨ ›‘ÈAÀ™3Chmõá;Ân·C–eœþóiìúö.¸Ýn0 S󵌠æ(‡JÞò‰Ä(¾ùÒK ) >„Ýn‡ËåÂéÓ¿? –e‹{¿RXW» LÏ• ãy£‰Q¸ÜnȲI¶`"“FNÈá§NáÐ~—Ë–eMI®$0t ’ÖùzsUÏ»Ü.X­Ð4t: †apóÖ-|2{Ñh‡C÷†‘kÙ†ÐS—Ä0A02‡Ëå‚Å¢ÝÕ‰4X–ßïÃÝÙY;v N§ í_I#0zªdÏóˆÇp»Ý°Ú¬eW¯¦á°³à¸ ÆÇSˆÅ¢èìì„×ëÕ}ž¿™"˜r;¬ý·RÏ' ¸Ü.Øl6 d®¥át:äH&NjŰcÇp«ÕZöFDØ´-PíB¥}žç12’€Óåcc°–Ï#“ž„ÓéB @*•B,COO‚Á l6Û3k4â4|7X-씄—C"ž€ÛíË0Èår˜ÌLÂív# `|<‰ýû÷=¯=ókaÓ·I1”rHŒÄát»ag<LNfÐÔÔ„`ÐTj¬H> nHz¤äÌÌ5=(A0WÈ;ì VVŸâzæ:š<^A$Ç’ˆF£èééA[[›nµW Ò±zD0­P³½ÓåË2XZZÁäõhnö€óû‘J%}N¾\Â# ùjc¤0å©° ˆÇp8ì`l6·×Û¬¾Œ™iuÏ+äÕsÞÈÃL­Á$äHæ®JØ‹°X¬^Žkòù}[;_y{÷ôbøâeÌÌL#ïç»»» íy=cÍ¡® ËòzØ[½\[ÛP«ß·5½¯ïUëðÅóáJ>Š®®®"ùZCÚ9#óH +€ÅbÙÒ¾mÛéÖVß¶p¨£³oß>çð¥Ë¸óï„Ã!Œ"û|Ï›‘í’3ÿ\_ƒ¢¨&×{Þått÷ôl¡¯ïçð¥Ë¸95• ‡•s^õ¼6á‘®7׌›£÷*h@}±È B“§Ù{>}u¢o9»øbWW·óoñ8nNM-†Br*™D4º_×óF 7Ú¯µ$­§Áó¼;ÈÏO\¹òÊË»_¶¶4·P'ß™ôµåÎÎιs粯½öÝŠž7bx½}Ó¶EQp8ûîß»—J_xuß¾½Ö@0ˆGþ‡ûss°ÒæìÙ¡»4Mý]-r*y¾ê1¶ÒZµ B¯¿\¼ãÖ?¦º¦ÿù/ ËÚñàþîÍþ­~áÊÄÄÔðð…_´··?)÷ô¶šŠmD"ýèñc,,.þÅÆ²“ 8õ»“˜››Ã¶P¨0sçNúâð…Ÿ˜ñù|OxžÔpmµ¦}íÝÈxM?ŽZhµðèñ§ßkr™å•løÁƒÔSAHüñùŸøÀ#‡Ã!ÚíväóùŠF‘ª4§žµÕ¾‘&)_K+(ŠÂãÏæA6Ã|_–¤­ùBaÀ| ¿sçÎÝ¡Ph—(ŠÀØ ùß[åÖÒ뀢iZ¾víÚ_çççg+Nôµ´‚¦h<~2Y’áp8Àó¼€ @aýcÈàç ÅgÓ(ÈA)/&ˆëŸ¯<þË•Äw §IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/editcase.png000066400000000000000000000136751217176075400243720ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ "¶º ~=IDATxÚå›}õyç?ý6Ó3³3³;ûª]í®VZ¡@B2 YccrNÛIñù‚ƒ»ºpq’K|W€(êÎg§rй·‚º²Mœ ~‰l 0ÈKPHzC/+iµoìj´/óÖ=ýzhߎF/ËÝTÝTMuOwOO?ßß÷yþ?)¦‡yá…rýKúWþê௿úÕ¯Ná½×ã?ž\»vmï¢E‹ÚÓé´©(ŠgYÖ”mÛ'·lÙR×éáüñXÿ—º»»ÿ½¢óúöíÛŸ}ôÑGo¡÷zú駯[¹råW³Ù{Éd®ë¦ëº• özž÷_Â0|CQ”@û°000à?øàƒmmmmw˜‰ÄÛ²Vu÷ôÞ³gÏðBîó­o}kñÍë×?¡)Úoûßå¹nüôààèà‰S?ÌON<O$ö=ÿüóÁÀÀÀ‡ ˲ή[·Nƒp}cSS_[kká®›o~ëG»vU¯‘Eê–-[ìëëû·.\h(W*ø¾_=|äÈö—ñÊš-‡qÝ5Ùtúº[6lð?T=zÔ7 ãÈ’%Ýç Ýh7tã¶²ïW?ñÉOܱc‡{µïoݺ5½öÆYÜÓs‹çùJ¡X@ èìÐáM·n[Ñßÿ[f2ñG†®Ç©Ôë;vìp¯jžyæ™ôm·Ý–ommõ=Ïs‚ ƒ @Ó4EAÓ4TU¶ªª¢(J´/^A¾ïãû>žçÍ{û¾ëº¸®ËèȈ†a¼½½ý;ÉTê©]»v9¾ï‡Žãàº.ÕjÇq¢­mÛ”ËeµlY)]×ծŔJ%Ê¥b¬££íwS÷¦’©Å…¬gùþ³¯Éjšö±©©©˜ªªär¹DKK šöÁˆ†!¾ï†!aFBË€¸®K$“I†ÎžÅ¶«dÓé„]­&’É$®ëâ8†aD[˲PU•0 Éd2sÀk(ªB6פt÷ô4†Ë}ßP”]nürÛ¶mÁ5`ÆÅb‘ÙÙY‰Çãd2²Ù,MMM¤R)b±X´ÒB@EQ"¡Å6‚HøZÁƒ ˆŒÈ573:2Jø$S) ³³ ª8Ž­¾eYhª¢ ©*ýk^ûÅ«LäÏsÇwÐÕÙIþ|>(W*»ÉäÓŸÿÂÎ]³4 㓚¦Í£y¥RÁ²,òù<ñxœT*ECC Äãqt]„®'¸8VOxß÷£saÒÒÚÂØè(¾ï“IgÈ_¸€ü“ªÈê•ÉdÈŸÏ3::J¹\¡0=Ëèð½==d³™IÏõÿ÷Ý÷Ü= Ç×¢k}ßVX輈™žžÆ0 ‰‰D"CQ”Hx† ¿Þó¼qN€“knf|lŒÀhnjâýɉK¾?1ž¢S*H64ÐÞÞ†ç{,î^왦髪–2t}éîÝ»ãÿøÇík`ûöíÝš¦E­( A (Jdä|ßÇ0ŒˆòžçQ*•(•J¨ªŠaÄb1 È®j! /ïËFQìg™xÿ}<Ï£­¥•Ññqªaß÷9›W8ÓLÏ1V*qÛ •–ÖVRé =ö£ás#o™I³ˆçL§Ó¾,ãPåNEQð<MÓð}?^fƒ8/<ƒ¼[¨iº®G,’U£ ¡Œt&ÃØûãøA@ç¢E ãĘ6^¦çô0ûºï⥡ŠÅ!V·ž'?•çg;vœ¾nåÊÿ ðÄO„"¼&4M»[Ð5 CTUôS¬v­•¯Çùœëºó„–UIf…ø‚ã8xžG&›edt„ ðéjY„sa‚æòÊ?КhãàVF&ò48#hª‚‹Ý»mÛ¶?ضmÛ%2^ €;dý@È/ù] €ìD<†!ÕjužmÝeƒpAL¥xçWƒÜÕ‘åÞ¾vÆ÷áÌÐ9ÐB¦õ}* !¾`ÆõW”ñJ'ï»ï¾?T–i_»•A«+{€Z¡„°b_EøyÏóA¬Žãr6%–ŽŸ@!£jdÚÚIÅbXNžJs_bhKKËߎדñ² øæ7¿¹NQ”ÈÇÖ1òC‹`-hõ"ùÞ—3ˆð93¥r`4ΆCŸ9Ìp©ÄºÏ~–®U«8ûòË$Nœ í:Lööâüë~8° ÇùD¥R‰ŠÅbhš†aQ<`†ˆ"…Ûú-ÓZ¨ëz´:ž@mÛŽÀ¾^ÁÑ‚ÎÑJÏL14Ûƒ]ç–DÀìéÓÆÆhÌåXÖÖ†qâþÌ Cíí”MÛ¶?üá‚X³fÍ?ïîîŽ3 #Î4M‚ G_€ ë:AD Éy‚¸‡Xx ¡årMÓ°, Çq¢ãÇG+œ78ùÊY&Æ+–šá¦›h=·›0{øK×®¥gãFâヒ~ú4Š‚¿v-…5kV477+/¾øbxÍlÚ´é–ÊÅt2zhy……°ÙõIQä%ê"¢7q\P_¡ë:ŽãD «ªÊñÑ2Ç )þqïiŽÏïZƲe9†ÌfüκV£½¼ƒáÇIµµ±øÎ;ñƒÓ§NR™œ¤÷öÛI(Êg_„Ÿ\3¶mÕj5ÒG±‚Â+È1€Ø—¤95šg(eƒ(@±E­±çOŽ–yk<Æž·†Ù·o½½—î¾R)£’gË!-]k)(.Öô4§~ùKÔt†¾ûï#øéO9}ü83/½„n¿û?²Ùs¿;;ûÎ5y¯ýë⺮QÏŸ×3nâx­Î AÂ0DD•µn±Öý‰ïœ~¿Â«ƒ*¯ï›à×oCiêdѲE´¶& ‹øÔr››–„a€Ö܌㺎eöäIÒÝ=tmú(Êù󔧦p§OUÕöÏÄãGwØö¤xõ ©«&Œl¥ÅKNjd'^xD¬P­V#«.\\mv(b‹3cv xuÿ4G ã§ZÈu·ÑÞžÄ+NóÑ® ·,Õ9fiñ 0ׯÇñ}ÞùÛ˜aÙƒŸ§Õ*Ò†¡¢(ŸQ ãÐØØ{U<òÈ#¹®«ÉᯮëQ¢cš&étšD"®ëÄãq Ø—& R©¦i¢ª*ñxœÖÖV’É$¦iF¹»œ<Åb1f­G=^;l1ôî9’d»;é]Ò„[.ñ‘Ž2÷®7iH󘥙&ÕX FFP+F¢©§‡®-[PóyJSSªëû+UÃÐ~+{óom»ª_ªLWUU9~ü8ï¾û.K–,AÓ4LÓäСC466òöÛocY†aD«Édؼy3¹\ŽD"ÁÞ½{éééáÖ[oÅqœÈŽ;c¹°ó]‡·Æ›{oËRIõvÐÓÛˆ[)Óâ s}£Åû£~Ī0 q‡B¡€¦ª´oÜHb÷nôR‰õW¬ûâé»ï>àÔÑ£qËu;nšçvûl_àÀN¥R1<ÏÃ0 r¹WÝÆ,ùK®½ó»Ç¹qÓulÿL ÄU¦fB®_¬ ü‡ƒðËQýþ=Œ?ó"¼üÀe~U%µüìßhêÄŸž!_ȶ6`¨>§÷í¢|è/ <4¯±!û¶,ð?¿ÿ}ʯ¿Nò7 \& CÖnÝJkOçvíâä±c¸žw¢#‘øÆeUàá‡~Røa€T*Å÷Ÿù1_zðH–Æœ>º–ÞΧÿèyoì2ð×p°¬pЃƒ®Â9Pné s÷r~°–}i¿8u/á¡÷ ·•XÃFÂÔ­„îGQÛ·Ð|Ó½X…‰C'ˆg3´væPŸ¡#Ç);a;¤7@ãGPÚÖ“\´0{7f’üÁ7þŒ‘÷Þaã]ÃìíeÖu1òyÔj•ÉcÇH66Òqà ¨Å"•B!—M§­+©À¼·çyרÜßÈL©‡'Ïü%K€ øïÃ÷þÕåsŠ'²ÿþÙ~òó‡I?}ôf¾ðƒ×)öœ!R€SFxõÏÐØ×Ì–ý)ÎîžâØ/F Â"çfnøÔoxª•*ø.$\8ëïûs–éEZ3-”J%š››16ndF×ÉîÛá‘;•wÜA÷¦M4õõ¹Áää¹Ë ¬²°¥R‰Æ„N‡Á¯7ÿ {w@|pŠ|6ÇT~¯˜šó+*`1xh#|ìÈSÜÚ| f<¸¾ Ö¾[fú•YÔ 6^e†ÎþV–Ä1ñfˆã• BŸ°ªb«š§aeðîú cÖ+,ëÐ)‹466ª*ÚM7á¶´à~ï{ZµºåøÀ€ž{ä‘°ýþû_ËïÚõwWe€\¨èIÅ9³d vÛ þ×b˜¹.¡O,ô¨¢¡!®¯Ð’Ëñp]ƒœí“눡(0V±­ ‚x ET_eU‰j N–½2Ä¡—§ˆk.ŸZ¡rû†8¡qˆ ðpµÕöñâ`+0í‚9²¸[áÅ ôpêÔ)J¥R”j766òV2ù÷›-«ÐäìûO9òÌWøÃ¡+ V_QÊå2é6“KÚ9sƒ¸*~oª_rnmKü²jrb×z?ÞοؒáΞUä+%âšAÒT ü~Ç÷=|+ HC¡éR 6ûWÂè¾,ùry^†!“Ùìð ##ÿùÓ““é·_ziìõ ˜”+eƒÑꛦÉìì,½=¬¿. € pUpmð}P\p5P‹`…msU_…˜“³1 ¸ ­)p&¡+r×8ÿòoæ+qøÇðF²!•ðâ-u%dÖµ%#ÄË‚®ÀtFžá'Ÿ.A<M|ÔŠóã“7ñöt™þþ~ŠÅ"¾ï“ÍfÙ°iÓ‘ïîßì€eEk|Å\@䢌5==ÍÍk®ƒ˜Îõ? éJ,Gœ¤€ªšuñŽš f3ièð`2Û‚–<œ*4N@± ¹1Øþ7ð{½°ï<Ü«B1® àêਠF^T‚‹†¯êC" Ô~¾òŽ…b”+U6·|qu¯¿ºÿ’ˆÕ0Œ°^»ýª6Àq’É$Åb‘ÏßÒG8:äsÏ-¡®“0 Þ)Ì4>td/.Jʇ„É ´ cN)ª’/CÞ‡´y‘Pà¹õ¦«N‚\<îU!—…ææ•ä-CÀ¿[ÒŽmÛQ-ARƒ`Aõ‘£‹ý™™Úoûe ©”ÈÅ.øqT[C× ¦Æ¡Y‡³³à8 !0ÀsÀ0|šB˜NCÊ…dâ ˜ ,nºxmƒ ùd à&ÀHC«š,ðâàPpÁ ÀT¡ÁGVv‘Íf£g—mÙ‚×u/V}ôNä}rʹ|ˆ¥ûäB•ŠRÅLᜉƒR½h]Ü8Äl(Ä`‘ á4dðš¡Ã%€FsÄÌ%`Ö£ V0cB5O‡V*.¸)°+PrÀ­@¹ e*%ËW¡ÜÙ/Qª›K°”3@1fff°m›o<ö]>ðœ»6%ìFÍ ãRxZ3sÛM=\ã«øÆ0M“dzzõj9Ë\˜ Z­VÑ4'Ÿ|RJÐuX,F†$“Ɉf´k|­/¹FX©T(—˸®K©T²¬y­òÓ§OS©T"C†¡¶ |ß<ÏS«Õ*‰D‚b±HGG©Tª^i^sC€$*J“ضU“lj¾S­Vç͈.”HÅljªGAD ¨'ˆª±(Ê(ŠB<gffQÙ¾\íãJ* á<ÏãÀ‹UåÞÞ^úúúÃ˲"]3 #2.\¸ÀììlÔ˜­V«‹Åye· ”úùçå_„E!N“J¥bÿþýœ?žL&C2™œWÞ%q¹Í->ˆ­èñË+(—ÖäéQ34 #ª=ŠêÓôô4a²yóf¦§§£µÜÆ›ë\ Àu]O6„¢6˜N§q]—ÁÁAû,´´´`Yּߠ-Ôúµz,‘ÄŒ0x¢9299I¹\&•J‘J¥d´ Ä÷j…•AÏT­VÉår455aYV$¼¸WmóvAȽzyJD%ᮄkÓu=zˆJ¥B2™Ä0ŒÈÀ] €­Û”• ¬¼8òÈL-ýëµõ¯ @ª|s!€pc"葇"dËmÛ6–eašfÔ<•õQXATAfƒÌÙHËÇäžÅܹBa­NŠAˆZáľ`„ˆlÛ&‹Ç£Ø\fÎ\ºzÉØ\­ Ö³²×©L.—ö®ÏóY@ÑŒ´B—)ÏT«U~ö³Ÿ199Eò쑱XŒ‡zˆ™™’Éä%^ \.sûí·³zõj^{íµ(M®-¾ ä vbÝq}A …d[[[¤×²/•ÿ$!„¿Ò€dLNNÒßßÏc=v äYAÃ0xûí·ç¥Çµ:.ëz-82åÅ=†‡‡ùÚ×¾füüç?_ÐßæVKEétúsO=õÔoÈz-ôX°@ž’WV€"h(»=¡RÂRËa«®ëór„zÆNÖûÚ “}ûöMïÙ³çi`¤Î€ÔÕFeß›{ó¹Ï}î‚뺿!OƒÉ3A² —s…²á¬ ’ƒÆå|{-µ¼÷Û³gOîZêŒêµ\ôÜsÏýX6l"¿¯MDêåîbη^/ël­pµ…ÚšÁ•ŒÞåRß…2à’Š¬œÈ.L¬¸X}™þµÓ ²]¨72WÏ…Õ&Lµìc…ËL±‹úfø?R;+42‚ÊõÊå²ÐµÃò˜\-ýë©Àå’ŸšªuøÍ9š’ÿ¹»ñæÍ›ßÉ%º a"@J®ëÂu%\éý•® WºÀìÍcŒI’§ÿøæ›¯ëõz­aš¹ ðìÙ³—RJ“bŒz£a&J&“÷766îÞ¾}ûçÃÀë¶-XÁ²,¡Õj£×;½ 3Áà³Ï~ÿ‡Ï?ÿÓßÇ…”¦iNÕ«W­çà€çò»»ÿ-@·{Šn÷–eÁqœ+KlZp "Êf³šiZàüJñ™á|>¯†ÑÚÜܼ)¥œÉ(…ÖqBÓ¿»›Íf¥T*U…3^$Þ%4 Ãà\øÁ™T?à aôe‡¸iBàpá)@§Ó©çóù²¢Ÿè5_ƒñÑ$v%ÄuÒ-àv&“É ¡øDý?0E`!׺ìžÖ Q!¡€õ·ïY–…NçFÝ,•ËÍݬ‹ÅB¡ í—J¥´éãï\›§LËêg‚Q/àÌë EQ@r'‹ Ê¸ðˆ !À9Á4-´Û-ÔjFW× uMÕ*Ùl¦˜Ïç ÅbQ¯Õª‡'''"2ÔèNK|j@Ó´ÂñÑQ÷úõåë® ® `€¢(ð¦N& À'ª( çp‰`öz8>>¦jµÚ) F.—+g3=—Ë©º®ªÕJ±ÛíV4´œ08ýâéõ `F¹R­V¶¶¶’ŽÚ<å_v˜b¸àŠGTQ0Æ`YŽe¥Ri«ªj¤S©ÃƒÔA!›ÉjzQ×jÕê¡iš¢>ÑÁxuÈ~Ã,²¦À²¬fAÓo?NšdúǹàP„eA €í8h·Ûn­T;Ö z-—ËüôSáàà@SU­P.—{½^@³O´×'ê÷æ$¢Ó¾3ÔÉf3ù›·n¾äxÛ¶ÑjµœZµÚT5­–Ëf‹étJK¥Rš®ëz¹T><íÖàÍ0Q ì¥O§ÀÚÝÝýÏ?ß¾ýõ»wïÔt:¥¥ÓiM×u½Z­–LÓ40$jÂsÛ`^:ÑI`ÓŒƘ°Ú/¼h; ê⒉Φð^«é_l¬Â¼ßñ½(>Šÿ¯ø(#Qgõg©IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/editcut.png000066400000000000000000000100711217176075400242350ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœåš{tUžÇ¿·ºýLº;é„$@@„$‚¨0àˆ:#òÁuAÝ=»‚ºgtGF×ã8²ê¢Fw]AÇY]œE@!A O °$M’î<ú™~WWWÕÝ?ªƒYjÀ4av¿çôɹÕ÷{?ý»uïýÝ¡”âÿ³˜Á60ØbûÓˆB8ŽÓ3„P1•Ïóÿwvú!QÜïXñ·+žÛ´iSÃòåËÿÉn·;/ºÇËLß €h?¯ÐÙÕ)WÜ»xñ³ë»®füøñS.¿¬ë{P-¾ø>úè¿Nœ<Ñ!Š"òòóF¯yúéß—_YU§@JE×ïß+ÇrE¶¡¶üU+W®ç8Î’U‡YVH¢{öìùϦ¦&— H$¨¬¬œvßÒ¥¿È´Ü7áEª_2Ó ™N§][ÞÝú„!HÄX¼xñÊÊÊÊ9þ"7²Hˆ×ÕÕýñð‘Ã'^ÕÆÌ>ö裯ØíöÒìXÌ®ú  UUÝ[¶nýwEU@,+6lØðU+Wþ+}ö¬fGº”Ä>©¯¯?"ðDQDUUÕœE ýc6LfS 7 ¸ßÙ²e³”–((À0 $IÂòåËž¬(/¯ÊŽÕ숀E =¾zõê7+**n&„|çö˜Rš?vìØÎššý½UUƒÁøøãO¬3›ÍÙ·>0b /?oøóÏ?ÿ®]»v½Y]½{öm³ï7™L¶ïx.  û-ïlN&’ !”RÈŠ‚qcÇ–­|ä‘ÐÏsÆå @ùœÛç¬=}út”RJãñ8ݾ}{óƒ>øK§Ó9šRŠs?ÌÊ_½ú³uut÷gŸÑý55ô@mm¨o wÌûpæû³¾?8Ÿ¿þ~z 柟Ÿ¿ìµ×^k¤ªJ)¥TUTzôèÑà¯Öüªº¼¼|ò9êäåçå/øðƒ"5ûöÑ}{÷Òuu´¡¾žîÚ¹³gÔèÑ•Ùü `€+Ìœw×¼·¾:~\¤}äv{äêêê?M›:m®Žaô™çôJgÍšõòº:ºwÏZ»?­?x>t˜nþÝïê ÃÐË@f0€@1€kGŒ±ªººú¿ý~?ÇãTQdJ)¥‘H„nÛ¶­~Þ]ó0™L×<÷Üs õÒš}ûèçÐ/èñcÇèªU«6 ËÓ`@ôÁ°Ë0ÌÜ¥K—~øå_(Þîn ¨(j‘NË´¶¶¶yÅŠkl6Û¤ÜÜÜ~ða¨®¶–ÖÕjÓàð¡Côð¡Ct挙K2^³⇠ç˦BhÑ`PPVVvËc>úÀÔ©S 8ž‡Àó0™L0™Í€¦¦¦àÆ?‘eyÈÂù nÑétŒŽeÁq,A@ww·wÉÒ¥ÓÝn÷±l¸Xp6°°ëõú«î[zß‹/®ÊÏσŽe¡×ëa4a±˜Áèthmm•º»ºÙD"Îp½^Žã`0°{÷ž½ÿÝ÷˲½h·ß¢¬8Û€´h(žxõÄÛ–,]2ò¤I%K8žË€0Àd6ƒa„Ãatuv!€eY˜ŒF F¼¸öÅ_oذaõE»ýeðMZ ÚJaÓétWTUUÍ]0þÜŠŠ « èÁóŒ&LF#Œ&xžG"‘€×ëE$Ïs`FYñÐCójjj>¸hÇçQÖœm¬m“Ð@ØÍfóU³gÏžwçwN1b8O˲000[,0šLÓi„B!ÈŠ‚S'O¶-\¸àæ`0Ô|Ñ®ÏÑ%œÚNp(€ü‚‚‚Ê»~v×üY³n½Ááp@Q0„Ѧ‡Á€œœpz=<.rl69r䋵/¼ðËšýû? ^´ûŒúŽÁl6tØì7éõÂXÂH’tÊëõ}EÏ ü‚œ}ð›i‘-" ¯¼òʪE ͯªªc±˜¡¨*B ‚`ïo ¼sìCmXðÞ»ÐÛlعcÇ®—_~ù­cGžŒ'm©TÊ‹‹B)…Éd*=²tå°ÂÂûxA0ÉrªJÁq,"¶µ·müº©é™”$@L„ZDŒœ4iÒ¬{ÝóÓÊÊå›Ìft¹=8°pò‚Aä]ýsæ"Wàóùðî–­j[[›×ëõ¶CÁ¯ü~ÿÑ`0x"‰´$E±KUÕÄ·õo0JŠ ‡-/.öÏñCÁàÉvç£p$|B–eÉ 78 œùÓG•–ÎL&“‡¾8tèÞH$òÕ€È@´³™%Ïócg̘qç=÷ÜsÛèqãLž§ž‚³nœ7_õñ— çÚ …ÅbA]m-ª_ñx9 ½r:EÑF]ÑXôt"‘hMIR§$¥‹Ùé°Ûo4ê ?I&“yÁPHíöy×C¡OxˆÐò”<sÓùÀÄ þ&‹ýyýÁ)Iêh€¶Óc¡-›CØ­VëÄÅ÷Þû×?3çG²¦‘¥H°&è¨ N–ãÀ±,Öþæ7ؾ};Y! 8Ž/ày<ÇADz`u:†€! !ˆÆbðù|ˆD#ˆD£ŸÄâñ'„Ï`Õétã+¯»î-kN®£éä‰_¸Z[ŸþÌN¡%OÃÐ2G‘žžžÐ믽æž0~ÂoS#KKIgNFÐ)ª¢À”kÅýË–AQU5êaü~?b±â±Ã@Ç0`m༠€eY€Øìvâȱcûcñx€Õ’6½JBEQZ’‰d§ÙhrX,–¿"„˜(¥ñl%-(´»„ Q’¤ô«¯nX¿éÍ7ŸK$¼Çã%'½ÉdRÚüÖ[‡>Üì°;F=æŠ1ÄÅH0DO8 QÁêt°Z­Ðë `YV£c@Âbç ¾/jµZsdY†ªª&BH2ÛY›ÞbOccã®uëÖ}5cúŒ‰Ž<ìv;¬V+Z[[#Ï<óÌ«Nˆutt0Gޱ0 ã´Ùl¥…åÎ|gÅè¼¼QPUk4E$EWW8Ž˲`YÇ•!„ž3¯)¥J~^þÕ¹9¹%>Ÿ‰D²™ÕæR¤­(€8€îÝ»w¨ç…‰---(//Ç-·þ>Ÿ¿‹çù¨$IÝÐ^^€ ªj›Ïç;æóùvÁQ+ÏóEyyye%EÅNçx1•*èèè@§»)I‚ªªwëæYQöŸk@„Ò 㟠Œ˜J©>¿ïShnz©òv2€DsKËŸýÀÏÌfóø}ûöÁår!žL†%I f %¡ý2q=Ð~ €^’$—Ûínt»ÝÛ!ÃòóòË œ“KJJ®‡Ã¹þ@ÀƲìÛ„ŸØ J±èá¦Â|ç³i)5.•áéìx5×P(¥t WïÀVXP°`ö¬ÛÖž:yŠ€Å%%hnnÞP÷ùÇ2Îgˆ@[fyhY(sæ3„c¹Q»ýþœœœiRZB2‘DZN»Eñ3 ã4B±Éh‚]^_u$Ù @¥T¹”1=bÆôéMã>Ÿ‚Àcøðá´áË/ÿþøWÇ×÷§;|à @Yqá°MÏÛt,›ÉU˜ Ó±J$iöxÕé cYX´ãó×úøÏ·&“ɶ üN4¸,ÚÀdJé·°£LNÅãÝσÁ)†œ–ÑÓFJËnš:m˲¹ýýBJ© m~w覔Jß5x`ðêSB®3®?ð]-ƒ €RJ“²,§òóòÐÞáy/¿@Äbé¶VCÈ£ee¯ÄãñöήÎíÐ"a@k‘»VXÕ1º”^¯‡(ŠMÐvh-Ú’¢¸ÕÕÖúÒ™3g ×^sÍf«Õ:Y(Äl)E‘Û)¥°ÛíÃÄ -]~‰dòm×™3›}Ý^ç¤Êëß6#ÚÀ`P¤ãÉäþžž />[Ç0½E2´][g8ÙØr¦åãX4ZvCåõosgHƒ €PÄTª¶Ûëu± 3¶¢¢byŸÿËÐN„n0øë—ë TõÆ*¯ƒaÃ@™ô)@)õ„Â=ÿær¹0îʱ?w8}‹°%JééNo÷š—ë„QÐßqíÄk^Á½À€ –H&·uû¼Üííæ›¦LÝ Bß"+@@Uկݿtµžñ8l¶e®¿f 6€Þ”Yg(ÜóRkkk0‹Vü¸êæõøßE—"¿,Ë mîönkk =qå˜1ÿðC 6@Ë"GdYið‡‚/ž4Om.‚´MÜA_Š"E(àu4uÃM,[¶dC–,Ë7ÙºË$—"¹—s›™>œ=Ë%EJ+/ý ÁYîž™ó}ÿóÝg$¬µtK?úÑPJá8Žã ”j )%BˆìömJ© ×u‡}ßïBH­õõ8ޝ$:yW Þ³Ök-ZkŒ1­‘$Ik´óýÕ¯~õCóît!wÇ”$ɈâóÅbñÁƒ[úûû½b±ˆã8AÀüü|R©T>¨T*'«Õê/ã8þàíš·€$IvßÚ8ô'ãÛÇËÃÃÃø¾1†ùùy*•ÊÒ›8åryk±XÜ:33óàµk×¾FáÏ¿^ù¨xüH0ÆHcÌŸŽŽþåÔÔTÿ¦M›¸rå —.]¢V«aŒAJ‰”’8Ž ‚€ ÐZã8Úèž ¾è¹Þ !~üP_o^×­õ ïûÿräÈ‘ÏONNpñâE.\¸€ã8”ËeFGGq§å2{‚€J¥Â¥K—˜žž&I‚Fà{ž÷žçýžâOwÖ“ßu Žã̓ƒƒOæ3Ÿ9<00@†œ>}c £££¸®‹µ–$Ih4$I‚)%…BÞÞ^Êå2ccc\¹r…×_ÙÙYq]÷ÞB¡ðŒâaàÌzñ¼.4…*•Ëå§zè¡Ã½½½,,,pòäI) 4 *• .\à½÷Þcfff®ÑhLI.—+—J¥M›7oSSSLNN²{÷nFFFx饗8{ö,Õj•0 ·—J¥§û€‹ëÁûºEžçýãƒ>ø±ÞÞ^9qâÃÃÃDQÄÓðþ{ïóÊ+¯\ý)ð´µö”µvÐããã=½½½ã Ÿ}ê©§ëëëÛûéOš={öpÿý÷ÓÛÛË /¼Àõë×1ÆLôôôüØóY é–÷u Žã?xà$ŽcŽ?ÎÆ™%Š"^yõÞzë­PR}·P(\5ÆÇ1Ƙ” Ç™ïëë{uÓ¦M¯*¥ž˜žž~üÉ'ŸüÖùóçK÷Ýw‡¦T*ñ‹_ü‚ééi„÷»®û5c̺å]v»À÷¿ÿýÜØØØwöíÛÀÉ“'é)ô0=3MµZ娱cѹsç¾X,¿î8ÎÕµÖi%˜ššúá#>òÀéÓ§ßæ™gX\\drr’Ï}îs8Ž“9Èo&I2”$Ý)A×!=räȳ³³T*¢8bþú<ï¼óŽ9áüc…Báßn'㌢ˆ¾Þ¾—~øáGß~çíÊñãÇ ÃÝ»wóÉO~’……Æ âËÝòß5CCC_àìÙ³äóyνwŽ$I8÷Þ¹¿/•J?s]¥TKåoEB¢(Â÷ý“÷Þsï7N¾v’‹SŸ÷©O}Š¡¡!æææB|.͸+¾÷½ï }BJI­Vkew×>¸vyÇÄŽoONN21>Á®»Ø°aZë5׳ֶ€Š¢ˆF£Áààà¿”~uæÌõù|ž0¿0O’${ÝÝÈÐRÊ=[·ní‡4˸|ù2®ëEÑ=ß»nÅZ‹”’‘‘úûûWÕk-žç‘Ïç‰ã¸UôAÀèèèÓ3ÓTæRpï¸ã¬µ„a¨¤”‡º’¡›É®ëîìïï`ff†8ŽY\\ÄZk•TOÇqLœ¤#Š#Œ5 S*•–UsÆr¹===h­I’­5Zkâ8¦P(<«”šË´k``€\.G»º‘¡+ûq§ìyÕj•F£A†!æzûzÏf¿µÈ¦ö½ÿ~N:ÅÕ«W±ÖR*•¾¡ÌÍH)5íûþ[µZíc¾ïã:.Q!„ìJ†n& !z²ÏQa’ÄÉÌÕ«W•R«ÏCÐ×ßGµZ%ŸÏsçw’$ÉšNÒZ‹ë¸W³¾@ö]ӟ云¡ëD({cYŽEÚè8 #³éý†¡C:x¥Q­y¯” 1Æ`mêS´ÑY“¥«ŽN×´¿5­u&ˆÈºA«‘µc$bËÖa¦?¸†1¦½k´â~‹1Fh­[m°²ûnV×y@“¹–„a–V©»r¤sàÀÁCŒO ”ÆòÖZâ8n9¿ö‘™G»´›Ão€v¦2ZÍŽö‘pàà!&&v´êßÏ10¸`YÌÆÊÞ 1mRmXKk:¥®h@ €Œ±l4m€»öd||‚8Ž[ßeaphãf¬åMÈ4 "3c4 ÁZK¢â8netÙ›öݵŸñññeÂgdŒ!ŸÏ³eëVâÚÕÞšÔ Zó»æâ¤%\»ðSSw1¶}uá3JAèaëÈ(†Öv3haÍïŽÈÞ>4£@- {§ö±mlœä&ÂgdŒ¦§§‡mcÛbI2h ÍªIÓíÒº8Áö(Gñ2ÆöîbÛ¶1’äÖÂg¤µ¦§§Èöñ hV†íšÖþ¹[ê €$IZ:˜…± 0ÆX Þ³wŠÑmc|˜¦…Öšb±ÄŽ»2M0íy@[tèÊn+:uúL p•RA@¹<ÐÓòaˆmæù®ã8wîÙ»iÛ¶±øf6+ÒZS*õ²kל:ýZ.«ã8&ë1är¹üÑ£/–7”H’!„Þ»g÷|§ÏªÑñ¯<–Ïç¿k-yc J)*•J~ff&¯”Cœ¤ñ;ŽcJÅ¢›‘µÇq8þBqaqÁó=°Ôë4 GFFjI’d¹F¼X]|âž#w·“õ;Ö€_?ÿÂ×·lÙ<¼eózz MolÑÆ‚0ÍQ—|.TRÅq\ºNT õ3ÊQxž‡m¦þÅR£ R*?Žc?Iêõ:Ó33ÌÎV¾þÚk§ð•/é–;IP«×Íù ©Tæ(300€’’m£i}åêU1€DEѲ0ØN7e5Lï·(©š‰•Àqi~ñÁô4sss\Ÿ_ ,"ò=§#ä;@Ji³vÕÂÂ"qÓöß5ÅèÈ0žëR¹~¤™[vo{”X.à þRɰiÏ"•R{Š”Š%×!‰®ÏÏÓ¨(¥¨Õj„a„@4Ÿkí ëw @‹Ï&SBJ‚ àôëo`mz6Àu\JÅ"žç53Á¥âge.ß‚Å"¹$´”)D ‘¬þÈ˗/sþüGQ. ›Zña¨«rX)E£Ñ`¶R¡¿¯¯¹×Ok‡7;(á8žë¢š¢©ð–+b»mfzZL[òÓ~8ÂqJu¿¯ó¡W€)–Wz7–¾©` iç"Û 6&4»§ÝöÛë‹öï—=±.¶»–Ë…½­¹"]¡:Ïì2s¹íÇÞ@]e‚B¤ŒüÆI4ÛdÍèÐ u €²C»~$!$ëñäî5 å¦kF:%›>85»ß†XÞéÈfrr;ãÃ<¯ý³Õ4Ön»·êkÓ·Y\êÑ%YgÚZK#ĉÄM$Ž#QJ6I!J¥¡¯åáÛV3låK¡Œx^G,™d|ÙæýE’8VÍVYgÊÝ1žªªF-O†„õ*J)êõ`©W«”Š.ö-ຢ•ĤžZ‚¼zbaä ¥m Y"  ”z¦ö̧‘ íwÛòäé^ª5hjµ:ׯÏ7-'ljغybm”µ¢#:àʹÒÿùËMäsKµ}œ$XkÂA)øÙ?¿ÎÎI áŠÉ.üÍ·ÇøŸçú)ä›»ÃmaP'‚ò†ˆ§~òý›€˜åÒ‡'þn”§ÿ«LOÁ4³BƒG)Œ•r öµÓ”J–jæPðíõ`×D…ê¢O-m`h­±€’‚Ūó¿*²ëÀ<¬Ü/À¡ý×yòi¬¾!rYàíw%ÇNøì#õ”éüŸþ»Ö`LZ‰ J P™Uœ9Ûý«¢ tÚ&é8 Lî éëKÐzEæfSûSÒð¿GóqcÃ=‡ yÎgùКtþj¾+†#JÅt~öÜ–Ohú•×ßÈÓq.դި´Q³c<"NVŸâypêuŸ™ËêF½ŠarWĶ‘„$YÝ;{®åÅãyây+wÔOKˆãlþòuÇòι‹UÁUøªÔñ­žûöKo £¦98ŽåڴÉW}pÀ 1äú-‡öDñx–wϹ¼yÖMX1ßë±¼+X`Eþ¡”efÖåÂEGÒ±&t @À¾;xž]sq­á¹_ nÄðñCÁšë Õšäè y0Ëçêឃ dS;Ëu@ˆcÁ›oæl‡­ÈŽë01±q0Aë¥G·3áy–c'r3‘€–U8xg@¯YÓAI ¿z1µåsm¶ {w„”û5Ú¬®ERÁ›oç`;lDw @@ÁpÇxH|;>÷¾Ë›oºH &\I ¶mŠÙ¹=ZÓ |ÏòÚŸ«çJ/ŸÕaK9açö¨Í,'G._õ™™vëLBÃ]“ ÖÚ’ë’^΃Nçd# ÀSpxO°&€Žc¹6ãp⤰Ëçë|w$z P­+Þ?ïwß;ÎT&€ xª@½.“¦Äm÷…࿟3|åQÉ g$áž;gy"r¨Z»j-³X“<óœááO€hË„ÃÝ»*XíQoX¤ m›AË!F‘äÔ’½Û×€·f_úU…p}~õÀEJ‹’×óPÍ>¡µ’Þ¢åLe߃Ì] !pŒ`ë¤äñÇ{I’6䲆)$°y(áÝùŒmÆxlsGú¶Yþø jµ‹A Ð&;?`ÑÚ’óùö\¸¾]á9÷+x®ï¹<ò‡.ùœß÷(Køž‹R®ë ¥C»i»Le$Òíò- ¾y¯Y*†lÖ Ê¢‹%N ÖÈÖN°Í:«lÐï¬R«×ˆ£c-QÅqëp…ÖË:·Åç*Œïûä|Ÿ°‘§ÏázùœOÅøžë:¸®‹ë¦ Q”$…@"…ÂjAµº¼ß·²ÿg­Ed§å`ú»ÖÄQDµZ¥VM[áqóXNE„aL‡cã8¹ÁŽà²vµ\êˆÖY NWêž„X~ìfy"ýÎ÷½[/Ämàº.vEoíü†{b‚æ!¬Uú‘ééÉÄöÑŽÖê€gŸ}VˆÔ“-g¤Õ­ùÍ"Ðzë«>·µ›´ö!Å6º)Ï?ÿ¼8zô¨´ÖzõzÝ]Ù¶nïÍwTá6iMÌ-õzÃ5Ƹ/¾øâMßÎM H¥sóù¼p”ºtéÒå¥bß÷Éå|r¹¹|ŽœŸk9>ÇI¡£T3(T3 (µôßäÒÐÖÖùiE…¥.5iH?tÛ1ú  €0Œˆ¢tÄqB …ÇuãcÇŽ)–WÝ·@swWJ)sGî>ô×o¿{î‚ÑfÈó=Çu×u]Çu]å8Ž£”TR)¥¤Tk­´Æ(c­´FJ!µH´Ba­MɳÀ4ƒ¡ink1k¬µkµµV kµ’Bû¾§¥”‰ç::É%:iþ‹ãX !'¶ýÄ÷"óÿ•þ:`lË€íIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/exec.png000066400000000000000000000123401217176075400235210ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ§IDATxœíZ{tTÕ¹ÿíóž3“Ìdȃð´ T –‡EJEnyu-*-Ò+…¼Þº]^¯‹rµB)ˆh[EÄ­€zËC[y]‚Õ&¼BB&™Ifæ¼Ï¾œs†ÉëM(é]í·Öɬ5'³÷þ~{¯ß· ¥ÿÈÂtõºZþ @W/ «…ëÌ}>_N~~þÛ¶ÓßBh]$ò™ªiM^ÝW”Îø±N0vìØé .\¨ª*!”RJ$I¢ëÖ­[ûÁ¼Ú™±¯˜PJ;ô Ë–-{Ë´,šH&©¢ªTÓuJ)¥K–,¹¢ÊwTJiÇ}¥”F£Q­±1ŠX,†X,†xS’©õË©àßR¾€ž={^·`Á‚• Ãde~ …оõ­oÝ=uêÔëmÛÃ0`(0sæÌQcÆŒ™é÷ûs3'BÞüùó(((¸úò«ÒA¹ÔÑ(((ºoß¾³¦eÑÕ«W¿#B~~~þÀ‡zhÝñãÇ#ÑXŒF"uôÌÙs´º¦†ÖF"´¾¡Ö74PUÓ¨¢(ôðáÃç—.]úL(êÇ0LÁºuë> ”Ò]»vý9''çš¿µ_å!íyÐÂî݇ýæ·¿}kൃŠëë——‹¥Ÿž wëê×ïª`cCTMÏóÇ‚e‡BX–…$IxÇŽo¨¯«k7n\ß”¢ ;+ »víú|Þ¼yS?»tTÚЫW¯^|ñÅ7 RTWW†q¬$;;†a •J”‚aˆ¢žçÁóX–uÌÀ ÄSòùÀ±,‰DzÁÁ`ïíÞýù=÷ÜsWMMMY‡5@çhãfÏžýÀèoŽ)Šd(ñx©TÊQaB@)…eYÐ4ªªB×uX–å‚pqLUQÒÊ{‹Å1iÒ¤wÜqÇÒ¯þ2H‹<€B »o5jô¨o ZH&ÝÝD‹O˲`YlËÇq„p0M †a ™LAȲ¯ÅdÞNQJáóù°uëÖÊmÛ¶m¹Š^JÚ˜!D…BÓß~ç …=Іad¾ƒ®ëà¢$²,0 ,ûáóI „Ãض EQaš@Ó4½ï i²³øýÐu”"m뺮##³&°m¶«°$ ®òªªâš³gÍž}ß•Sµ}i@8tû”)·¦’©ôw¦i‚ãXøe†i¶ðö¦i#77ǃßïÐòH†UÓŸa[°,–eÁ0L̘9s†$I½®€ž—”6 :tbQ"Ÿ¡ë¥ p”}24]µm@’$0 ÁG‡•o{}ÛcGaǧ:¥¦ëUUsA°J%1pàÀœ’’’[º@ï´ÌäÉ“§•”” ˆF£tâÄ[ 2¤¿¦iœÝÔ4 9¡lŸOBeeeÕ—/ðã?þ€Â²lÞø›ožõü/^X‘_/éºÛ¦°,©”]7•€e™°mÇ£¬¬ôÌ[o¾¹IEýäÉ“e{÷îýÝÿU‰N%B,Ëä¿÷Þû¥£FÎ×u͉b±˜“Ã0`™&²³³á>†mYÉiÓ¦N+++ÛÓÊË“éÓ§ÿtã¦M¥R°m†¡CU5(Š‚ìlÇZ–ãDƒÁ ‚ÁlÈ>;v¼S9}úô!’W  R]]½y¾ºŠS׃0 (œãašà:3]wмp8Œ·ßzsWYYÙžöÖ³cÇŽ ¥¥¥ z÷îÝ;ÇÁ¦64Mq“(Ö͉ü~?"uu¾ÃÚt@8”B‰[ѵцڀÂêêê@mݺåâ/'.5¨aÎ;[YXXØûô©3(,,DN8„0°)—ž‹À™’x©4Å%¢(Šâââk)¥œ÷? à ‰| ¾3¸ŠÒt w¿¼Â†ã ŠŠŠ`Û6LÓ@¯ž½z\jP†aøüü‚ŽãÐ@ÿE!$­!Ë&¹Ô€n»í¶üjãÆ§t÷Bà“eüüé§_ðÝŽÀ ¬€¯[8Œn998ԋ甂e° ŸO‚ßïO‡º›o¾yJ~~~» L™2eò Aƒ®±,Ë­¹4_à)L)…é¾çä 77²ì.µPÓ4»›¦ Ë‚ãyˆ¢˶ !&v8˲š~ýÊ+o–——_g&ÆÞtãµÝºåJ¦i¦íÔts~–u|eY(èÞ½`Æ ¿-))™ ÒpêÔ©ãW?ýô/lÛb8ÎÛyÆÉAÀ0žÏbY ÆûöVÔÕÕE:ô?âí-4<_Dˆ[“Ø6üNÁÁhÃBBxJ©Ñv´ŒÿÀÈ`NŸ>ýÁµÿõܽ‰D"mÉT E= !IRÓ4!R©Tãvž¯ªº0xðàÃGŒ˜¨ëçÕ ž¢MM (ªAp²BŸ,á‹î}f×®Ý?6lØüÇ|Îc=öØÁƒ_ŸÏ—;a„;o½õÖ©7Þxã¸PNØïq ,ë8VEQ¬Ý»vܹsç[»wïÞ‹ÅÎ@ß¾}oظqã/_{íµß­_¿þß/ @ë’——7aï¾};óòò8/Ž»¬/zô(„w2¼2X×u‚Q`&TUÃ0`Ýcê8;Š µuàù‹Å§ 8_U•wÓ7Œ3¦dËË/oÊÊŠõõÚÊ?y€aY,_¾|éׯ½¶·mÛðB*Ïóiî!Ï#++ ”R”——7<ûÌ3Ž?~ì¹çž{ö†nèžJ¥°xñâ'6oÞüàW€|òÉ'ß]òÃŽŽÇã°m ÛvR×ÜÜné ωã4]G¤6‚x<ŽžÅÅà,ãØ)˲}>ÔÕ×§$o¾`0ˆ'Ÿxâ>:´wëëÛÖ‚.‘H@–edgeaœâ+R'ëÞ5Eö"é9Q†O’À0 TE/PçÄ÷-^üÄ‹í€Ð^5_·nÝ UUUºäóç9pžç‘H$À²Œ»—õàóI…BQ'FBÀ‚H]]å9ŽÃŸ={öLÓ¯ý›5 „K¥R`Yªª¢®¡µ‘:ÄâñtâånOæFe°O(…¢(cEHúÔjš›R¼°~ý¿Í›7oUk}ÛmŒœ9}úp$I vãë¢.È¥'çy¢(¥•NWˆ©(!Cy€ÚÚ Ñx<%IÔt½%ñâþ¯§ MišmòB*Ã:щçH’˜N®<ót7Ó-ØLH’„@ 0€ÂRJ­KžY–óž]»vÍðáÃs¼˜ëÙ´gÃMMM¨­­E]}=š›PU šªBÓ4$’IÄbq4'`Y¶ò ¨*¾9fl¿qãÆ]½|Ù6›†a´&M¼ ×u–q±,çy~¿ ¿,CE˜†X,ŽTJi¯yãAX¹r÷úõëE«D« ‹-Z½dÉ’IZ:á`2Žãz_Ç$/,Ø,7pœâÅ]iG/457cùr+ì?Ø÷™Ï×–>ÓT ~YFv–Ã*Ù¶{ÝÌQd³ y(Z+žçQYQ¡®Y³æ?(¥')¥væ€RŠ€ßÇ?‰†‰ëGŽìçUŸp·ÈÐuä†Ãº¡§sUUpâĉ´{$L à‡ä“ B‹R\ÓtôîÓGš0aˆ6;ÑGŽÙ0cÆŒ§NŸ6ü~ÚŸ¯ª²››› [(ã)ÔæØàyápšª"ÑÔdX¶¬¬,TŸ¯J~wÞ¼•CJ†öð{vK®i‡ÃNfZð=ËrJèî……à8®Å|¶m§Añ€qÒv¢(’ùóïY̲L·¿ ¥TÿôÓOŸŸ9cÆŠÓ§O9¡ v¼óN娱cï¾eâÄmøÕ†#ÉD‚v ‡!ðB›#N)…$IÈ …Ð~¹~ÿSn_tûäÛî=vôHMß>}p¾ê\óÜÙ³ÐØØpdÊSoL&ê×#_$ADz0MlFÆó<‚Á zöì‰P(I’Úl€¢¨ÐT †i²lض…d2‰‘£Fö0àê ­õm7 PJ BÈó³gÍbfÏš5í‘U«K${êëë¹åË–íøYA÷ÑãÇŸø¯Kï¿+Êñ™VÚ©BEœª¬Œþâùç¶ÿ÷þ°»¡¡á#Õð½ V®\ù£—¶ly»òԩצN›ú“üü|Ÿið˲Ã;º °, Y–QZZúç×_ßúæÙ3gª{÷îÝ÷Î;§O½iÜMýŽòbÐt¿,»Tœ ÙïÇŒ3fq·€fY–N)¥í¶ÆY†¡i`ÚK~'ͦ–{|EinùžÉìA(Š¢49>`Y,Ë¥vò˜–©3Ë^¬!: €«Y €šv³8†ÙÖr|’’(‚Z–›¼dtŸàxzI’Pн{Ú~¿qÝuCEQd4M³‡ ‚h4Šsçk`Y&»¤¤d¥={õ¼ ›ÁRJA°®òŒ[¨1,˸"ÓA± Cײ“Êzì€t¢C)…(Šçî˲0àêÁsçÌYýúõƒ \$Žî¿é’ÁC÷wÚt$]%R·…ï‰iY$ ¡`²ÏPjÚ65¿4 |U¹Ô hGؼ¼¼o_oY–þï|çÎÙsæ^ŸJ]ìB)ŠŠââ"ð<—.»ÝfŠõñ¡COU×Ôl\¿~}m0ì1gΜïÍ™;wY*¥0Ná㘇išhŒÆ IRÚ™Š’„£Ÿü©zóæÍoE"‘Hmmí_Î;÷ö•p›1좢¢Ù³wï«¢(ÁrM"•JÁ/û‘—Ÿ›Žá¦iÂ4-ð<]7Rñx¬!//?—ã8_¢¹Ùå–™eYÄãq(šÖ¢“eóæÌ~üàÁƒÿ À`°ºâ¦(u@ÏŸ?ÿ‡#‡‘““I!Š"²²³ ½—Y‰2 A2™B,“m›öŒÅb¾h4 ›Ò4‰ë¥è)EŸ‘*‹¢ˆÊŠŠÄ±£Gߥ”&(¥ ¥Ô¤”Ò®¾*[³yóæWmÛJÛ½(ˆe†a€çù´çvzŽLÃ@Mu5 ÃhE¨ó§¡Ñ ƒ™"ÞØöúû)E)m½€®0ÖÒgÛ¶mÞ6ù¶Þ‰D*}ïÀ0LøÜꎺ„ˆ×^súŠœCÙsœÓu²,ÄâM iQ(ñ<Ú ”I·Lœ–H$Þk=y§®Ê^)**êÑ»OŸ,Û¦`Y¶ W 9‘€eZ!Ý2×óî^ƒE×u$“I† ^àÛp–e! ñƒj· ߥ'ફ®ýò+¯l>|xQæ 2ÏñéºîTwšæ-”ºjâ&K„8;ζ*=ñî#Y¦‘š÷Ýó8°5ó}—ž€aÆÍ5rdQs"‘Ñ1rÞe:@–e/kw‡½VšwZó™c*•B¯ž=åñãÇßCÙ–É u©ܾ}ûK<òÈ!Y–ÓIÃAdgg§Ù%– fö3Y&¯r ‡Ãédrss±mÛëÏ>ûìêÖkèj'È(yøá‡×>ôÐC£UM¥›6m*'¦Ýyç×ý²Ñ(Ò”™·³ƒð‚¿ßC×±çý÷+ªªÎ5Î÷Ý6€ì@;ßý}Å}‹/QTu¥´e ­5“Ú‘§“ºjÕ£5M£+V¬xÀ# ôð£>öÇýû$+O¦e'ÊiYùIZV~’žpŸÊS§è'ŸÖV?ýôÑ‘#G>`$€kïºë®—£tË–->Iš@hwíx Œ())yÀupL“…Ó¯$ËòÜ5kÖ”Vž: ¬ü$­¬C—/ÿñ‡Bp¬"óáÈÄ/[{—çb¹O á8޲ ÕA4sss¡jj:Tøýdee‰”ÖÄƨM=Þfü˰𿩨ª†)-+=øÌšŸ—BXÆmL2,Köìyÿ]ö_çRÒÕQà+OÀ މx„1$4·Ç[~¥/£ ÿ¿”®®»\þ @W/ «å€ÿ†Ó<|Gq èIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/exit.png000066400000000000000000000113551217176075400235530ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚ¤IDATxœå›}eÇ?ÏÓ=³ï/, ›„Mˆ!BD b@=Ô’ è‰æ$giUœ%œUXÞiê,­Ò+´@°ÎR<|9ï<,HECˆÊ[r\N!ˆ„$›dÉìfw²³3»;oÝýÜý<=ÏôLO6UZZuOUW÷t?/¿ß÷÷úüzþŸ7q}ä“?`SÖYµêÉ€wBÛ;áÃç\tчW­ººoñâ3ݶ6„ H¢b~ >„”MÏv?Ó)P›·Ù=qjYUçæÈ;v2óâ‹Ï|þù‡Ÿ ‚Gž œp>ã8ïzë%—üëê›o^1´v-N[[H”H›aC¨Åhü·}Ÿ&g4£q@¢göµyfÝÓD—*ß³‡ÿþú×üÏη~Ó÷ŸÖ 4hD¤¾˜NÿýºÍ›ïZuÓMŽH§Bà•Jø•J8À’ Ð ĉ¬†¾q¦-†#-9³ñþ†&)Iuu‘êêŠÀüÝ÷¾çmÿÒ—>{±xàÅA±k÷³R~ü=7ßüÃå›6s'ORÎåPA¨EÒ¨xŒ)ì´Äzf‡ F ¬ûÍžaõQö}ë™L¥è¢wñbd*Åk<Ào½õæ ‚UÇb^þM*µrýúõ\øñ§Ë…¹£G© (ߥJA ”BA¸x€u_ékb}„RuýDìZh€£¾öóÜê« œßzfÖU¾OezšÙ±1œöv¬Yƒœšú oÏžmûà$–O°èøp*õ+n»mÌŒï×´›È&„Dâ[€g 'áw4p"6ŸP |ŸâÄN[ÃëÖ¥oÛ6øäÌÌc¶)œÕéô’÷®Zõ­ÁµkR6[#66iÁ6ƒ Ú¢ûJ«Ïl©D±XÄÕfS§Í4¡£ Å´©œÍÒqöÙ”ÇÆ–ï{é¥ûÆ!g´À1Ò¿Þ÷o¸pÆ´õ÷ƒï·œ4® uDµÐ”¢Z©pàÄ Ú–,¡}x˜ñ\ŽR6KO[[R‚©˜µe•oª –v¢^¡€ìéqß|ì±ý¿ƒ—/p5éNX™ŸšâÌr9rnÊœ“óýš76Ž(»Í3ô… … ŸNó/|tGGäˆîÞMö©§èëèˆÖ´zíø|vÞ5?b1Ô/˜;~œn¸hŠ€Šð¡ýÄo°tÝ:°˜VqF›€âû R†ÒÑs®Þ¼¹Žy€ó.½ïØ18r¤>ØÌÙkéùâ‘¡î0÷4M8þôÓàºíx^›æ[¹šGœÎdPžkÇke/h1j‹k‹Lø~m¬”ô/X@³6´lãÖ´§ ȶfEàZ}Ìe÷3ô)Eî•WHuw;ärQa DP©071A×À@8Ð’œa®á&*oßb¾ \B¬ºëcuÙ¢¦OÄç·Ós‹ÞJ6‹_©à»® Ü×€°/0{ò$]}}5fãH[€DDÆSš0¸º>ÍZ€çÕ‡a^ ÂQŸ’ƒNÒb&jΕlJ%*±e(MM¡–,©¢‰MˆüC\cj|Jæ!ôäÚüêÔ Ûf@q­0‚±µ¨ž<ÅüD$P™›‹$aÛ¹í ÊE×&%8?ìq M(…ð¼ÈWJ%NÌÌPñ}ú::XÔÛ‹ëºuÙæaèŒÔ?槪Ùl=³Í@izºæ-”  êi¦ËeÆÊeÒCCT&'é‚szzU²Y3& %ù<Κ5¬»æÜövr££¼ºmgçó tuÕ1*|¿ŽA^&Ó©åûa̵&T–c©Ó²‚ãù< ¯½–7mÂI¥8ðë_3ò“Ÿ0¤w”-›N]ñ}ú6là¢|$zÔ=8È¢‹/æå­[9úÌ3,¨gÔŠ÷¶9Hí(«™ Å={šVt4 ªM Ð('¤D½êÙ`d*.¹õV–]yeÝä+6l@–JÌþìg­¥¯ž‡‚󯻮á±t.Ù´‰7—/gäG?â-ÝÝ Î/ĦU)f~M}@(ž‡_­†êèû¨j54‰j5DZßú:S,²îsŸk`Þ´á+¯ ǘ#©A8§ïã¶·'v;gÍοåŽäóHÏCêy…ï#4mxÒ÷‘žGñ¿@á@SñB)|›`‹iåydggYsÛm,Zµ*‘`×HG™ØLð}ÊÇŽ%÷κðB–}ò“ŒçóàûH‹yïÕWñví «ÄÒµk[›Ûµ«N2IM(…ð}dµJöþû ŠÅ–ó]|1]7R*C‰ëChé«L†òöí8š'æg(…_­†ªo¤íûѵÆ;÷\Þ~ã-‰œÞ½›Ìý÷×›PR3QÀ÷©:Äñ/~‘â‹/¶œùÆä- 5Àh‚ï£r9Ê=„ãy8",•9Žƒpu Á¤VEe©¼Ðȳ˜-—¹ìÓŸnIÜØÖ­¾ûn“W5MjZŒ=¹“÷ÜCaÇŽÖ ÜtÙ¹¹ÚØBòÖ­P.#\‰H»ˆ´ ié6ЄRFRÚ~•½)ú6l`@g‹ÍZæá‡ðÁhI}þ€• ›¿ðÈ#ô\}ÓaÝ ÒöŽwÀ®]P*Q|t;j¦€LÉ0%uH¬ÂbP­5F¥B•µÕßú]*—YÙBõ§ó2÷ÝÕj$lJjÚ¤¥qfüìCQÞ»7qèàûÞÇÌÔ¥;`v‘r åBÊE¤\„ë"]á6 Ù ZÎÏŽ\ÀçžÛ”of†#ßùNcô°M(¡™T‹qa­[øÁP¥Rӱ݋ága.®×±˜v®ƒLI¤Óè0`ü€aDCW]•ÈÄÄÏNÅS“Bi‚# …†8n¼;Õ*ÁÄÅ;×îºþàÚÒvB0Ò‘vÀqëß#Äpôaª©‘ê[L(ÏcðíoO`ûöºþ¶ó:FçŸ}¶aœò}fž|²æ(cÀIm¥_þ2qíΫ¯G"\YÓ‚”Ãq‘) H¬ENЀր¨H˜÷+ßÇïèàÌåË›PØ»—J&Ó°mŽïÖÆ¾ùMT©Dï5× Òi¼ñq²÷ÞKõõ×RYiåúRÔø8Þë¯ãž~Ãú=ç_ÀTO/éJ!B:àpÂÚ‡ÙDfSb1¡tÞß½paþ0»o_(iÛÛë}D]±¤P`üî»™üÖ·p{zðs¹0üÆ61QMÁ.|HAuïÞ¦´­Xû÷!GG€€p>À Ù`@ŠZ¼.e5Ngg"Å‘‘ÐoØRÔõ@¨/Ž ªXÄ/• ¦ b Tß8@ù©'é°vŠuíŒþóŽD82Ô!ÂÚ)6À¤Œ‘7V*$¢aO P•J¨ñ×àæ:¡T%E½ÚÛ¥6œ?>†wè0"ðÀOŽ$KÎ¥´ûC58R—í@ˆ&`re“(¥¢Ê°a¢šË%.hA½ä N#LÑ2^ò–X& Rù<ÞÈaÔÜl(YGâ·H¦Ôl!”¼´˜—5N ° BŒ4¤DÞÔTââôô ŒÐÀE ØÕ¤f…Ô˜f¨¹9ü#GPù|M’:« “(˜ŽDÊúZe"¦"$Lq2&¹âáÉ‹·¯\†:h¨äÆ_¡'ÌÌ 2ÈçC-ÒL‡Ì„NÐi†ýÑ£u`ð¢õç|S˜ˆWV|ŸÒè(^>ÛÛÛ0Ñàúõ :Li"ݺ—+FÚJ¡r9ülQ,F¥9„ÐáL€*§Rœõ®w7e>Èç NŒEm Èš [¤Â¦`  ! VžÚ¸ç‘ß³§)í¤×¯¯e­ÒaßG x££x¯¾J0: zÿù-ñð!þ5ï!5pfÓõ½—~§ÇHk\x ›™@C&(¥ k‚:ó ¬Œò}Æ·ooJÀ¹Ÿú³:4;‚ÙYü±1ªP!˜šª•Ô¬˜/,3˜?óÙĵ+OìÔšb1«&,Î{_ÞÓ{“;v”ËM‰8ûòËé¼á3¶\ÆÏçñÆÇ©ŽŒàŽ¢¦§Ãª µJtœ¬Pí5B ›?FÿÍ뎪\¦òÔã´š@†f ‰#DÓšXƒ 8PcØ®êsåÄ ÆúÓDI\òµ¯1=8H%“¡šÉd³¨ÙÙè?FÍš‘~ôRÃHPH”œ\qËîúFâøò£Û¦§jæ"¨ИTj›`! ÑÆ'ð}Ï#Ð%² RA•ËŒÜy'AÂÖÔíêâÊG%¿x1fÎfPXG#Æ9†Ä{&/áümÛqººš®§ÊeŠ?¼W‡V9Ì(Ôj)‘B6Ôë^K²¸W,â‹ss³³õç¹9f÷ícäÎ;›Ð9<̆^ xÅÌÅyl „ô )˜òW¬ç¢§ž¦mѢĵæþí^ücG5x5üjk? ™[AqÛLÊ»ŽÜ~;…ßþ6‘°ö ¸ê¹ç8ëŽ;Èö÷Ӫƭ#sÀx_ÿ|;«vþ’ÔÙC‰ã¼WöRüþ=ª–ÊmЈHmV-5Àl†â„5sVÊóØ·iSXIbÌuY±e fàŽ;˜^½šI`˜fô1 Œ Avõj:¾ú5Þöû,þ‡ Óß„Lœ`ú3·„{!5Ö XiLhQ¡ýÇ_Ž4l†š½<°±5¤<2ÂËï~7o{î9R-RÔT?çmÙÂy[¶P£°{7Þä$•±1Ú, 58HÏ¥—’Jø÷HóS'É}â£ÇGC φa[ZÆ¥H–ZàÐZíãMÅýûy媫Xõøã¤‡‡O9¦mÁÚ6nœç ÍÏgúo7ã9\_ç±3X&"âÐ" ¤¨ýe¬¥§nÒŠû÷óòe—1ýħÇÍi¶ÊóÏ2õW×â:X»'4ÆtôP„[Џ Ô…AûaÜ[ŸªUÇÆøý{ßËÈ-·àMNΛ©ù´àd–ü?}ŽÜÇþš`b"Y2Úþãr6¿œVNÐÚšlrâfu*­˜üîwÙ·bc_þ2^ 9ŸæŸgæ®;˜\ÅÿúÏÆ"ö#žêÆv:ºèw­¾~ÏÀäó‰Í×<ü\ޱ¯|…‰¯~•¾ë®£÷ƒ¤ûýïLJ“ ÆÇ(=ñå;(?þ+@EEŽˆˆDÊb-öu@ÐÞ…Œ}7`P‡àØ*×åP_þôtK"çë#”ç‘ß¶™mÛ@zx˜¶·¾•ÔÐîðpX²ö<‚7ß$˜§úÚk™ ¸f/ïêªî©Z‹¯cTøDvv3;>Éq8j?võHï°gó‘#Õ³®¾:5öä“óX4lóu”Þè(Áè(%b!U„opqeÓ¢Eœ¡ÄA «:‚žÅ²åLl®úìÁú·¸Ô•ýÝ_­¾°´R¡wåÊy1t:‘â´Û)?w²ú¨øíã ÃKãM—+/‡,áwDe ·ìÙ³»4|Å:zæ ³)Pú@Í “èSÍ¿³x)þâóÙñ«âáA¿ʗ‰}/ ƒè$ðþròÄÚàý×"ûÏSÝjµÁÆý@«çv¿øŽ0LáMþ^Û½™Š)l˜Ò˜:ÔÉÚ¤}QÕG ;;q×\oYÁ¡oŸMçÿã1x *›þN`1°êÛm7þÝY7Œ¿ó9{ÖÅ×_§|ô(þÔTÄ€½?°™Šo¦šõoÖO˜Â§]Ö®{ÁQ_éÑ›ÒAêñ²¿¹ðäÒe”Þ8È‘¿/øI¾°õnxxE0g4À6aè–+?ÑžÞðõ3{>Ú½ô-gNŸw¥¡E®;/IÛÒ¶µC&ܵLI«±$©“:É3{}OWÕ •ß ðü.¿²/{<°žö#@ˆ^}Õ%‘„>`8¯]²ôó½Ý—oìí¼ä¢Ž¶%í½}Q±Qï¿ÃXl¨wL ë ¥íšÐká=úw^P{æéï–üÚáŠ@sá‰ðìºöÜÉ©âkpô xé°«G€ƒZòy¨ÿ¿t܉º!`¡>€.Â-ÃÍñÿš"üfŽðë° p8Ah÷-¿´›´=À@?!išÿÛìÏ¡)BÇV!,7L–ò„^¿éKÅVÒ„̦ Á0ÆSûS6c D¨ >-²Šù2rº;ä?U³S£y¥ ÿµü´„ÿx+IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/fileimport.png000066400000000000000000000125371217176075400247570ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ&IDATxœ½›y]Õ}ç?g¹÷½×¯[jIhëÖf„„´‚ñ’à€/ãTRΤÊx†ØNM¹¦\¶Sf2q Ç13I![x!®J2'Se»b#@EYŒdŒ±$ljÔ-©—·Ü{Ï9¿ùã¼×ÝêM¯…ñé:uÏ}÷½û;¿ïùý~ç·œV+¾^áõh^yUw¹úýÚʃO?ˆT’ ^yœñx“ãÇéœ`@'`C¡ »jøƒÍ×SìUþè{ê§£ÏûÄ€š…VãKrÎó´Õêë@âEïâÒbWYX©Hg^çxcp6§ÐŠLgˆ£- EZ²T«U<ö¤zæ¹çµ]Í ²¯Ë4Q뿽¼£/îú×ë?tË-·|°V«ÕÎúR¥¨É˜—K«ìZª Zⶺ(AˆŸ‰A)°¤k£§jxl”õç­oL~¿ˆŒ÷É÷J©ö½JÓ4ùøÇ?þß:ôð\sµc½¹ž· 6\´cÇŽ-}ÈøéèOØXz#¯Ž €D* Z“‚x„P ôõ¬`èø0¯ñ–KÞ2+É`„¼÷”J%–.]Úw¶yÚOtÄßéÈó|ü³6âSÇ#Åi~Y?Ê ú¨'h ‚ÐmÐ rœ8Œ± F =]NŒ ptà%Š ã«;á©ã¶4´%dNèêˆÿñ6EÔfŒ#ü²ù"oL6ójs§Ú(D@¥@)²Ð —ŒD§ 5Z{úd)¯ ¿Ì‘ãG(|AÉ–¦ÑÐZB˜6žiAf 9?:¡îk¼Ô|‘±®QNä¯L@yZúus#d4IM ”!5Pc„áã}õ(NeUžè™@PJu.æ£rýØü@öÃü²8BÃ1ìNăR(--ˆ e4'Ý j”¨ ”!ÕŠ¦©ñêðqžåy²¢IwÚ} ˜Xå©€ˆÈ4‰˜€J¡;D`z› „Q?ÂËù/iJFƒ&>`HˆúªТ9)ƒ4¥F)t¡´¥$ŠB7=ÁÑãGiæ T·š¶úíÖég3P~¸Ô·•éLψ&£@´¢ À‘£ˆ[_P &JAb,#Å0u5FÒgb'G†xåÔ+4‹Æ8S3Ñ›,ú“Õ¡#ºÿ2í €Û'†€0NãÅQ6%“T@%Qtµ À(ŒÑ&C”CJ4„DaÐøÀC­¨ŸÁüLôÚ÷mèØ¿*wÀ”6U§N*—ï=Z*i…BÀ  ‰ÎI ©.a­mIJŠ”tÜõmæõqZsp.Íö<6?0±ÉÏòBÀb)Û2 &€‚±Ñó³qÔA£u‰4-1¤‰ÆbQ ÐÈ'œµ¹˜ŸË8Î @Ú5ÿ@b.ôE”à‚ÃyGbÊI¥õy At hÁXð* ÂXK’X”±”RMBŠj1Ô¶SA€ ‘ŸéYG*ÐUvóàl x xqxï1ÊP¶|p`AlÀM¦šèÔR2 I’`LBZ2h4¢$¾oj›kæ£ö”?7Ý™JlêX‚à\Ö†’)S¨lBt¼£)TM’–(Ùʬդ¤gЙk œíYGô”*@@&¹ë³1=Þy çZ6 DRm<ÁÚ„ºª£•"MLbÐVS¦L™*"zNÚ3µùC›T&éO|C$V€ù—3Ñ<!òŒV$&%!!è€ÒàµC´PÒ%4`[úoCYUèaeº˜†þ, LÝæÀÑŸÞk…ÒŠÚýc¬¾k¡.„\ Ì<‘6ñ™@ò”Ò¤&ÅJBÐÑ‚Ò1k,€Qe ÕE=tÓC•î gxÿ\ ̧iSQŒ÷²ÂV5,€_}èEY‘EÎ+?SÇ΀Áš„DÇn1­±Úè„ <Ú**ºD…n*TYÀB*ôÐ’¿q9˜Öd&_;@µV]i…6 eЃŸ=EZkb‡Ï ;Á{9 FiŒ2±ƒÑ­1 bk-eª”©ÐM•.ª”¨Œ³®ÎBk&:`ú$ »`àMŠšŸöµ¹tMDðÎCAôµF6­ Vi´6h­ñÚ‘ª2e*Té¢B•*UR*„ñ÷ÍN{¾:?µÍê* Ê‚.ÃéïLø ³Ÿ:çshJ+ŒX´h´Ò âU+M0B‰2))%J”¨P¡ (Ϻòg£=Ÿ6»¬&@Pe¦Yý¹Ç‚ÏŒ€"æù”ŠïP(tK%”BŠ%!%!¥DBÊÌ™êׄ³Jƒ˜9&3£ (´7%Q&Emª•ý 4 ÛúKIˆ9p—Ù}­ t ÍbWf!’£@ˆ’q -iR³"Mt}5ƒBÓ.t¦n¯„yÐ)qÉF[~U;Lì‚Z#o§ǧ4IÙ:¢5Ó}§­ãXx¾+ `¸}o±/Ã"1@ ã.ºÌ¯q¶Ž˜º¿¶”Ù&¦2 ˜üÛX Ò*`ˆ'''àÇÿ×úáD- óÝgê¼ÎÖæ-©€€x¢„ ''Ž $Ä,±ÄÕw8r r2r22Æ_t6Z3Ìi>­ã’c§Öød±€Ä㤈¢-‚H@‰qä>G&±žÑ LTƒæ¢õZÓbÐi4›÷Þ¼xœÏ !à   ¥4Ê8¼sx#ädÔ¨c°4H)¨M2¾G¢ó‡§}b—V#±™A€™£A£ R” ¹k’ù‚"äQ‚ ZÐA£œ!(ð¾ iê$”1*”hÒˆ¦Ð®޳¦áfË ž­iaâ/HÀyM  .ƒ¢ßò„Ï–uiÇNpÝ¥»IÖÀàØMW§ðž"æ ]$—‚àÁ…VeŒ:uƦÁÍÂËð퇾=+­Ùî;mªòçÕQ‘@ Ö¬í¹· ×;4½¹Ó¡¸‘Ç69VjÂe›/àÇûs¤x¬ñ(c”Žp·’¢Ê(Œ± #I ’V°IŒ ±÷ñnî¿÷þìw>ƒ³kZóHf˜K»i&Î ,€ò"`Ü+ –[Ý>ùÌÔŸØ7Ho‹{ðâÈ«iõÖ‹ÿÇõ7]÷A>÷ÈÆ×ëtÉ[Q6:,´QmïÅ ú:5šE“ÓÍS<5ô#.[r9'ë'©å5*¦D0Ñ÷À)¼*È]©Ž9Àº¦©j|Çù“·ˆ¡ïžæðèalÅ`âƒàUÀãZ›g4ŸÎûhdKžgî;Êñ½§âBUÀ\ÂÇ€éÝN:Î{6V/(nýÖÇŽ™%Gû?¶ûŸÈ‹Àžû¿HEwQJŒ2(T ¤€$ HðÆSR]”}žþ¾7ü(#î4JC¦3”oùÐÊ œP¸%Š"/ 18“ó¤y‚AN°èÚ¼•ëH(ûˆž@h±Ý¤AFFNŽÇÓ¤IÀ±}×›¸ãéÿͺ‹zØqÅ[¹ÿþߘIhlÒò¤å©VKÕòE+¶~ô¦/Ýö¯çý·•lYøœ=EÔ&hÚT*Q­ V6 Æt˞裣w ( ®ð1ÌV*€+ ŠBãNŒ¶šzhð\ò3RR,%Ìø¶Z.tÛ >œÇyϨa]å|þ:¹ƒ­·oà™cGxæ©ç1úrýΞ?´•ÑvgìË?!›ø@‘¬^~ÂUʽGÞÚ÷–Ûoüó?ûÄû¯;À;6ÿO½ø$¥$A)£ºÚC° •x¼ Þ”‘¨Ä ‘B!>®ùù_ŒÍdŒ^ÔÊü´Œ¹,‚æ“‚[Uk¨Ü¦•äÔek7øú£ßص š²mý5㺠oçág¢”&(¯âÖã’Hˆ›“ÄZ JE…!JZ¹ P*AÑB&i’Æz¢‰ S­õxiªÖŽ*}ű¡ëÿüùÁ½O³a÷J>~㧸zÕNzFþùåÑÿçç<×8s, bÕÕZËK'NªÀÓ›V\qäî?ýò•7ïý VY¶o¼†O?HÉ—À ¤ÑJË"ë© ÆGÑòD´ Mô'ò<ÑHˆg{Ú´OL@A P$W/≿?Ì÷ï?̆kûùÄ·reÿ6.X¶‘’/e3òwVˆn¯VŠÄX~uúøð‚e½'·ž{ÿøNnùêG„«×oç០)§¨ à£$ÖÇ­)uˆm[}A´B´GÖB^ãõHc ÖÚÖÁŠ3hÏ©SÈJ›nâðÆ#÷ýˆ vôñÉÿ‚+û¯fÝyçSI;;õî¿âò•[é_´šÄ$ãóüµ0µUÒ.ú­B+Í—nÞÃù‡óž«».¸–ýÏÞCyAå@‰äž¼ËpÖã­'è€(ÁS ½&˜€µö ÆÓç¶Îλúæ0ûö=ÄEW­áÖw}†Ëû¶²jñ¬ž´¡Íç„È|™o'ÊI…•½ýlUнØÃ-w˜®|oÞø6¾ý“§ÒSB—ª$8ë ¹Ã[·ŽÂø$Ç›¬²¦éÿ8óªÎÎ;ÙWçž{¾Ë…W­å¾û6¶ô]ÎÊÞþ Mšß|€8§c¢m"å¤ÌÊÞ~®Z»»þø ì{âêǸáÒ<1Hm¸Fm¤A£Ö 9–ÑËhŽ5ÉkÙˆÇÕ„ÐŒ~|Vd±çyžÑÌšdEÆ©ü[–m¥¹ßsϾ\|õ:>óžÛÙÒw9}‹V“ØŸ3¥ÁE„’-Ñ×ÛÏÕk·³÷wò̓÷q¢yœwlþ]N¼z’ÚéÙpF³Ö$«ÕiŽæ¸±è ¤ÔÁ7EæÈ‹œ¬Èh †ò:[–^†;Ø·ÿ!.ÚºŽO¿ëv¶ô_A_ïª3V~2¯KZ|*‘É÷©MYÙÛǶu;¸ëæ=|ëà} 5OpÃæ·sêx“‘S šÃ9nLbŸ™–èÖ•Z¼J Š1a¸W,¾õX‰|ŸK®xýžÏ±¥ïrV,èÃh3ë|æÓ^“ L¾OLÂÊÞ>¶¯ÛÉ]7íáÞ Aƒwm»žbŠZ«ZÔ˜t­ƒ«Ç«ÔAÕ!Ô`¬Wõ^HùÉ.ÁxÆ lY¶‘îÚB¾û£C\váF>ûŸî`Sß–ö,›Sìc*0Á™&`´aé‚eìX¿›¯Þ|<û5ã}×¼ŸAKƒø š§`KßFzõzê׬æö÷}ž7®ÜÄ’îó:šÇ¹rÎÿ.ÒI‘T+Í’îóØ~þ.þáæ/óÈá2”ò¾knÀ7!«G•¸dýùô.ZÀÃ‡ØØ¿š;~ÿN.Y¹‰ÅÕ%IÜÔñLª2[;g#x6ígFw/aÛvòµ?ù ?sˆcc/ó;Û~‹Åë`Ûöt/,sà©Cl\±†¿ÿ¹lõz»͘™|?õùëZµÖR.—)ŠbÎIÍv_)WxSå-üËŸþïÿ±qÍ:îúÈ_ðãcOñ™/~ƒ }ëØ{ó—Ù´j3 * çõî©÷ó90©ÌÚÖH@yp}À)XöÛ]¸†'øøðü×n_»víVïc¥p>çt&ÿ÷VÓÖ«ƒ=Ç7VÏ}pI¿è,‡bÈ]ØÜx÷âÆ²ce_iþê~Jk-?þøþÁÁÁæüb§8DÑAÈc}?´ *ñЋvÄïµ*b*̵zÉ¡t¯³s¬^|ÒhÒŸugŽ1¾GL¬”Z½Þ·ËpíÞV^ ò­ßÀ‰×ÜZ /@±"œNuØoö+A‿G|l´ý‡e70ñ›‹•k|HqĸrÌîû>ZöëçP5H€bÜ·È Èu€›áȆ#’0 C¶Íª4¨µÂoìƒªê€ ®N}WÆ :¤:àGïT½œ O‚ßqµPÛ9)°Ó€a ŒùJëQHˆ•Ã:9°¦Á”O"&À?ùßÙcç†`Oƒ)Ÿ¦XÂB$ ¦|bItpt@S,å€&€»’:‚Ù¤Á’ì€As%()–0˜¼¬I‘°¤ÁRŸ”X¢`R"’Ùa hü©õ?‘0É M&»!¢EBó4(Ñ¢J°¥X¢(º‹iuŽz- äкs˜zÏ€1”Ž6&Ruµ#¤,€º©Ó A$àþÈÄø¤I €<bš3 ,?‡Ãc­I[¹ ½D¤f€Vb ‹¢,@!!´5g ìBi±$Ju@ÎæŒˆÿ1Ò*;`!º+ŒñK ¶°¾ÒsKI €mK,´çBk íVbÉSy@¢ÖžŒ]”+ ÆÚ.©7&ÔR`}\¾f$RmQÅR³‡C»•Xšt ÐKö¹FW:EŠÆ€š¼¬­0—Â-H @E ·KXöjƒ]©]ª1˜MŒµ=V‘4H9·„°=$Å8f…Ø£²”‘ÇÞxî•:Š¿dßýÞàb±€õz Ïç3yS9{ìaÆÜqŠMy`²Ã®—ý~ÿe»Ýî1¿hKóöÖX[1®ï{{¹\¾ßn·ŸÉŠœAiŽxù·Ç ²Æ;ªZ#IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/fileopen.png000066400000000000000000000061671217176075400244100ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ >IDATxœå[ËÅÿUUOwïÛ»c{×[0f‘@ÈAÈ("7þ€$ŠÄ!åäK@”S‡ÜrÈâ(ù%'¼äˆ€q°­]vñSÞ—½;³Ó]õ}9TUwOïìzvvÆk)ŸÕžžêêêþ~õ=~õÕ¬`fü?‹ÜîØn º5ÐñãÇ×´I)166†¹¹9†††Ç1nܸfÆðð0Â0Ä7###‚sssB`ddRJÌÍÍAJ‰ÑÑQ0sö}ll išúïrçÎ}Ì<´´´ô@†ûïÛrOšÒ¾ù†8pÿ¾ñó;‡~к)Þ-™D­5¤”RkÝ/¥TJMA°_)µ/Žã‰ÁÁÁñ(Š&úúú&¢(º7ŠÂ¾þ8V‰a\»ÙÀÍ[ öîŠö‡—Ÿµ-0sÓ¡µ©µp ŽA°?‚}qOôõõÇq<ÇñD†»Â0Œ£(RRJH)!„hß0ðõÂ*j Âî@EIÜJY”ߥ§x10Æ(­u? (¥Æ¥”û+•Êþ8Ž'öíÛ7ÇñxÇãaëIj—V1·œ`¨/Ä]ƒ‰z¢‘†hóz3Ë ¾EÑÓ»Ã0ÜÇñî(Šöì”-†oÌ &ïnkŸq×à TÒh u³/D®„UÎͪsÿégÈó¿=æE…=BˆŽ`f¤iŠ$M›ÀÍžá|ÚÏ ÛÀÛÍë¹Ëº÷³MoÄ ÈDpÜߘB<(´; €+tnYš²çÀ±S(÷ÿ<õQÓÌû ˜¶@ gt7â—Â;v\XxíÁ £-P"¿…H0V’µA '˜ (l·$³X3 c@Ä! ˜ `%¹ƒЪ"T”­Yg‹¡l @”¥= ÏK‚æZ@™ ¶Taƒ °^Y-»îúPaml´ƒ›!;3`ÜJ ½°žX/´‰ˆ]  ÒyÑCäU¢Lp³NYŸ¢Ü5ËᶈSï’ˆµeD"¿nF!€Z¸•˜–cßµËáV¹QƒH†ÈÀÉs¾'C–*/Ô ŒaÑC °%+‹úF.°UìïÒÚÀh‚tEÁ"~‰,!P7„¥UÓôì¢t !D6ëÎxÃ@Vh_ ù:Akã*< ¸à!JKbÆÜŠAjRÈAAº@š¦™RÕî½e«È²@Þ!뛤) Ãäָ­]pÌpi•°T7…ZáZ·ìÚÎP­Vƒ1q#MÓ ‚6»ë»‘Å3’$µeqY°µA[ùñmLŒFʸ±¢›RjOCJ)”R};vìøñ¡C‡&·:fVØ0Úö¹…-v—†á. ;Ï×W4š ! Ás­t €z­&îݵë'‡~±Z­>Ôßߟ-ˆÖøp¬Ðó­u>€¾Pa(ÐHØ@Kýí¾ð1W3X^5¶à–Cì‹%éš {óÍÁGyä‡~¨¿¿?ÛÁñ oÄîZµk­‘$IÓª’H!pÿH€‰¨†À€œù[°×oiܬkÀ1EË, ¢^0Y­ h4¥Tÿ|§dÈîÿ5 µv›%ëqmƒJƒê‹„}N-1¸v+ÅrCûÄ&[cÇKºVrJû(/=ø )¥Â⬕B EÊâ~G”¥R)%*ahwˆ Ù˜°ñ>5„zb°T'44e¥ñ,ƒäK…쮲´€SØr‹üS¹O wbæ‰Ö¿t!Ÿ{ÿöŒ±ÕòY ü—,Í6÷c,× V%} Å_ßÈ×`²ZõÊW%Åýa˜9Ü‚g‰íÐe‚1¦‰g´R.»VœzÑ2î5ÉF¡Yñâ¬{P2„LÔ@1ðuº[t»þ~û›³ˆo%#?¾&†Ö`l@Œf%Eé\Úˆ 1 ¿Ÿ¿•­±¶ïc¶›#n5˜o ”ò>7FQ6€T\Ÿb P¥ï68èt%ØXì¢|ôn¿î(ËFÔa• aXÏl Ân›÷íîÍþ•gÜ÷Éþk:i’H,Ã*À‚P4ûæàÈ\i'v*k\ªà×­޽X>Ý:;=Ͱ Ü„ÂÀ"·ŠJñ¼@™ýmUù5â òÁùQ|>1oò·Â„Ædµºˆ<ð :…›â[²‚e7¤àš] Ä% e^$©§T+ßß:;=LV« °„GC) €9 ¢­ïûn <›˜)ËvRŠ,!4Rj,.›ù¹}ñêÍôÚRÍ\úå÷šGØ öÏðJ‡®Ýïfæ) füñÕWÁÌb``À¯DQLwùÊÒ×ÅdÈB]ë;}ôO3oÿæÂíÞQä>;=­]Zô LDQ4|ì7^?ùé§ïŽ >yäÈÓ?|î¹gËå1×|à_î˜vmÍ/¸|馦¦†!ú^ø+¾îO†A†@RBE y¹ÿÔ~7óß^oG—ŽS—s‰åÉjõ€%£•0¤ÙÙÙÿœ9s¦vêÔ©Ž<õÔcßzâ‰{t­vÀÇŽ !θt»ñã8Ɖ'pþüyìØ±ÃjkÝpË~5h8Žé/ÎüþµÙ]lW-W… .±€Ã04a mÌÉ_xá;?þx߯^zé›Íþpš™J1ŃÀ$d"Z„q¸rõTÿì±?Ï~ðúòfÞ¿+eñ³ÓÓ4Y­Ã+)ñÍÅ‹squû—¢ @K&æÚ¼ £ X:ÿï‘/~ý—©3'“ÍÖÓ?œ¬T*ˆ¢¨# VJ ýÙ_ߺpþ“Ïî¿úõÔÙSåÞ»òo‡Û!Y$«õÚå³TPéx˜ÿ(pàÏâlÝIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/fileprint.png000066400000000000000000000056031217176075400245750ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ JIDATxœí[[ŒÅ=Uý˜éÇ<öá û~ãµ± Á#b)YÅDå#ˆ?Î'AùŽùÈ R” ˆÂ|å'‰"²É6‚ !™Ä2)1ø×ŽŸóì鮪›îéçîö`{6ÂG;š™îºÕ÷ž{ëÖªZFDø2CïG(ŸÏkü{¥R¹UJ!Zï²5¤YãoõVl=}œsÎ9«>ýôÓ÷¿ÿþû'×hC_0Æx¥RÙ¼{÷îá kÄØ¦°ÈàUŸÙõ:çDð”Rîê=tG_€”RH)ºÇD½Œ‹®¡—õ½ŒnçJ)&„Ш£oÂ8ø*îgŒƒ1Â* ÖeäõDß„zs0€V'a#ã †0c|=¹jâo÷„Æÿ[acÇç ÀM­À q“€A+0hÜ$`Ð 7 ´ƒF¿ä5Õä €ˆ¨P(lîG61w~íŽ_>úè£?3MÃQJõóÌk¥”¾k×®=;¶mÿERÙÄÌÍÍŽ=öØc?1 ÓÞËiD)¥þÐCýxvvvSRùÄA@çÏŸÇFñ~/]„‚Är‰ PŠP­UADXk¡ëÆ€ Ôj5¨>"21D„jµ €6Ä:cáªZ­VC?C2y ÙVƒÿÍð<Dɇeâ!%•ËeÙÁÁ9c •J¥/§ô$ॗ»ëÈ?ÿñ8ó‰Œ1ÔªU3?2¼`ð<W¯^…”ƒ-8ç¨{8×°÷ÛßòžzêG?ç7æû~æ®»î~}ÿ“ì&ÏzyðW/¼ðÁž={væryd2nü°·Þz sssáô#ºO]>õþÒ»Mç®· Ðu Œq‹EÜsÏnH¥€ÈiW._Á;ï¾ûŸ×^{ußÒÒÒ±vñÕ†Àã8H¥Lø¾0 ÃÃÃÊa~~¡Mšf¥vÕ;Ú´Ö«Mø¡•(ji£ë>ùôS”JE¬%*óCy8Ž“Ïç‡Æ¬€×ÿ—ˆr©TJQ¼o¡i§NÂo^ü5ò¹|Ÿã¿ÛÔAßVë›Z¥c¸rå2öíÛ‡{ï»To$C …l6㤭t¡[W] (–Š›LÓ´u]ƒR*ÖE)çvÞq'†‡‡CZ]µb&ã`œ3Ó4ÁÂpÎÁÃ%åh§ÖÆKI·õ}¤”¢öh!ƒ1†K—/A× (©Âz Ú™R¤à¸®eYÖøº (—Êó£#Ã&©ÈÀÈiR XVüàLNMAJV„íá{(‡gNŸc …BžçAÓ4hšÆÃŽI¤ð}©TçÏŸç·ŒÅ}5Ý|Mã–——ñáGGáA¬DCÂu]fæØº hÚqFM…Ûx •Jÿ½p†aF„X`œƒ”ŠC·yŒsMñcÇàÕ=T*eÔ=ÀÀB9"@J !,ËÁé3§áº.2Ùlœh»¥Am­éº©$‚@@)šNáS@Û²a˜F0ë8nÇ—R”ÂÙ3§qáü9H%1>>\~†a@ã\ÓÀY87ƒ1(E¸çÞû ¥ÀòÙe˜)@)¥dTP)¤ÌÌ”Ž´eÃ0M|ãþû¡k|ß×µZ¸¥E¤ Zµ†jµ‚ÏN}†óËËá6]LTè ˶¡iÚWÖMglʲ¬è±ñó!•çRé”R``8uê$èä pÆÁ9Ã;m¥¡k:倆—tÍ€a’ãø‰AŠpûŽH™&”"(¥pòø (%¤’ð}õzÕJårµj•è³W«Áó<Ôj5Æn‰jãfÂäíº®³¸¸è,--UÖŽ†‚cÛh>£Àƒžç¡îÕ!U8þÃ$¥ eèU)eËç†Çˆý‚$ ‡SøNxûÀ(*ÂWø‚ JŠþÃþ¾TøŽæªàÕ<A]Ó:RæP~Ȱ6 lÌvœ–}{Æ8¤A€z½'@R Šd¤7ÈSŠÚ®QL(µ¢”EY=î_†rD„ ðQ­V C“g¹\ΰ¼*‹‹‹ìÁ¿›·-«åÜc€AŠHF†F^nLEÆEÑ •‘j1”$A’Œ‰ìõ"¥ ©A ‚•jB`Ìnq'Ëe³ÙlvÀ¿W%à›{÷æMÓpuÃh)F8ãB¢^¯Ã÷}!Z<G‚Œ¢€äŠÂ’@$!›¢#6>"$ölD@s45Ùç‘‚g +¿ 2Ù¬›Éf;Š¡D Æ2Ù¬Ík.À5!ø~~½È£Â° ¿“lò…¨6£¤êâeŠÈ‘È ˆ¨&âg©xVRJAH ¡æy`œÇ×!œr]ǵlÛžX“€T:5—ÉdÒíûÿœóÐóA˜•…”PrÅ+Þîôh˜#VMù yŒwz¹Ë°¡ˆÄ¦!¨dXH )áÕªÐ4ŽðìÚŠþ®ëê)Ó¼eM8ç“®ãj¼éh Тy¹X¼egÒP:óÔlD“'W ¥V6 j"‘âþھ˕(‰Ÿ)eܶîy¨E•&çÍk= ¶ãÀ0ÖGÀTÚ² •Š#€!Ì¥b þãŸJ¥BbVýÁÒ³z_ý^TÅ­v¿×c«Õ*JW‹aý SnØØ4 h_›6¡i¼¨dmR ¥R “SÓ°m»]¬!¼¬o!±Ÿ®ªÕ Š¥Jå2jµZGs˲íÅÅEkii)¾ÙA@©TÌ‹¥Žå%Ó4qùÊUì¼ûë°m{àKaÝàyJå >ÿül¼†Ñ "Jpô& ZóÒgσ]*µ\O¥R8~â8þõáGH§Ó×^ûkÏó`¦ffP¯×;îWj5³ýZ¶e#—ÉÀÍdZ¯;JW‹8røØ®s-õ¾f¨”+˜›Åèè(ª•JÇ}+Õ鸆G†ªSSi¹n~ø{Øqûvèú8`zÀC˜ž™Áôä8DÛn"ÂÇí] ¡ .‚¤dK¶­K‰ùù9 åQ©Tô± uýÀ`YiØŽƒ¡|uÏk©aX´{R«ÕÖ&àÌ™3ïýðèwlÛÎ7æSÎ8,Û‘#GðìOŸÅþýûÃEÑ BB:Æ›o¾‰ƒ‡âùçŸÇôÔ4êõzT*‡¿"Aðffg^p±Y¶ë²øO>1ùÞ{ïíÍd2y]×]Mלt*m—J%çâ…‹ßæ™gFÆÆÆ:ÂlPH§Ó8tè^zù¥³[¶lù‹ažïû• ÊBˆrµZ-NNN¾ý·¥¿­oUø•ß½rÀ«Ýî=ðÀ_1M†a\cSúƒišØ¼y3\ÇýøíCoÿ0‰lâl&•|£P(ìö}ÃÔº®cll,¸tùÒ ‰e“ ÜvÛmæÈÈJmu ÁÃÌÌŒ11>Ñ9ù¯D0ÆØsÏ=·Õu;L Û¶1;;»à$rI# ³mÛ¶¹X çr9lݺ5ñA©D8®3²}ûö1]×áº}ýÒuÅÎ;çc:­{zJDÀèèèx¡PÂõ†¹ù¹Y9´Íõ«!Ñ ‘™™™YÇq6ÆÜ×3Ó3…\.×u¤°maÛ|2•n,6mÚ”Ÿ˜œèº Ú ‰زeË­ÉTº±0 ƒOMMÍ%‘Y7Œ1kaaaCGlß¶}K’öë&ÀL™#óóóÓÉUº±XXXØÊü³âºgÓ4ÅÁCÿzøðá¼ôɨH§Ó©O>ýä0œ`ìyHêË‚ÿ>Hr˜·3IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/filesave.png000066400000000000000000000072401217176075400243760ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgIDATxœÍ[K‹%ÉuþND>nݪîêê®îöŒ`$·b@ ¦1–7ú ƒ¶ Æxáú^xÐJ ÿ ƒÁ‹YIHà…eŒ!¿ ëÕOzêÕU•™ç-â‘‘y³ºjš®€¬Ì›™çýQ¤ªHíwÞùÚν¿îzç €B¡üöçŽnßÞ…Dáz5 úÁáßÿã¿ww0’…·>÷àÉgÞ|ãÿ߸¿û­÷ßÿÖÏÊ®Õd ªÞÿòW~÷+GGǨª €¢ëz|õ÷¿Šoüá×Q‚µt-éž¿8À·¿ý·8<:‚ˆDÞ{ìß½ƒÃ¿ð7eß ž>{f~ùè ~ñóŸ¢ëα½½ƒýý»899{FÓV¨­ùÔû$ÍCÐ÷qt|"@U!"PUüôg?ÇO~üQ3ï7¡†%gg§hš'ÇÇ[U`¨Ê§CÍ'n QÁV@¸N1 Õ­æ7D_úÒ;¸{ïž=}Šã£cºžRO-¹12"UH_U¡²,¼ ÊT¶m±j[¬V[kPøÊk׈(:B‚!‚ˆŽ„kpäŠ`ó6Ñ€ôüèè}ߣë:…AŠónÀ£ÇÏUéu6…âîþ>räZ’~4‘yÛ0@ᜇsn´!"°ÚÆâÍ7îâúq@áXÀª T"š°4ï©@¡B‡µŠp¢AµÐ5³ ¢á@˜³1Áº'þ`ÁL5@ƒ§Oˆ(pNÃDìåÚ!B”òü“½—°4íÍ(°Ð1|DÑõOŸ¿€¹f& ª¸}çvЀB;“ @—\æC/dé3†ö‚º±xó·îýæ(ùu›ƒg°J6a`*D{Ù.hÀh'"ŽÈ½ÀÑeUz-Ù}¾NìÀD“çmQæj”ç=D5;ÈkÓTáE¢ŸÚ$¾ ‰ó6s‚ˆ!D&0R£8¯888ºŽQ·önMÐø,\ËHp§N0UÌ‚º1¸wï®[>¨P ŽÁÑd—"€ŠNÌ;µ Ð/c”BµÒA¸~8@d3ô¥0®"¡²±0m3(¼$… A5ÃË~p¿iZ~íæ¼‡jú é'Næ PX„¡Ñ¤@àÑã§‹˜úu6UÅÍ›»cÔŒ"8‚†0óFßE ”Häf ƒvww¯ ÁN‰b’U@eÑw-ø€`3dm유qøHÛØkæƒiwÞCEGÕ/œ¡èftHm$ L“ Ô¹ï=Ú¦¾v¹ðÞOŸÔ fÌÛH6”²)`t,•5xôäÙõ3UìîîÂGsE!m-B£.„YUSOŠÀއ%ÂÛ{×Qà/ŒÊ•œ RåGr*,"pÞó ­-ŽOÏpvzú)uõ¦ªØÛ» Ï#(Ã`‚ÂKuŒ Ì+BÌf޶·VØY¯>-Ú®ÔT~ððžáŸž³Bè¢oX@‚SL-Âñ¢6ðµt‚¢Â!û‰¤ká+dƒ¥L>@DП¢n4ESÙ«U…/ˆ»Ÿ¸]á[ªŠJBª~vv6‘<0s¨a,Li# N!êºÁ¿üèŸPUöïîO¥¯Z€"š5 Ë%éé8ëú›Ä•cŽÎ9>/¾óã>ÂÁ‹hÚv±"t)ÐŒúˆÈ™ŒAßwø‡¿ÿ;2!¼˜qÝ͘°΀1k-¬­@ÆÀc,Œ1 C°dòVj!ß}O*a§kf CXòüB <åù FÓ¶¸qã<û '3"¼< JÈ¡Q†µö÷ïGBMð¦D t ä"*âJÍŽ$áù¢ešàR!sþ»„µ,*Â[zŸ™³¤C)œ¢ÜÌ@“0¥¨¹–´ê¢` ߬^&ª,©-Áç‹î¿ª•ŒÉ÷Pf°ÑåÙé_€)×À’ÂÀä0ID F’ÀÒœ˜W]§±©ÐžòÞRMïBâ£*Sø¬-s`·ÀÐ…dˆG áE QõGß§ ýp6)@f6¡OòAKLö1âôŽŽRÓp•$9Ús¸¿Zµan‘("@òSsJgUÁX¹€ÓúúØ‚T¬£Fà _ø<þ辎Ý[»‘žÀ¤l÷„°·h:`Aa:iÂÉŠ5~?yüßýÞwð“ûtý@  ÆÁn­wLýˆˆ²É€ÅýÇSàéà|BɬÜ¿wßüË?ÅýûwÐÔ„¦6hƒÊ(*«¨­¢¶€1UUÀCe€²ÄA¸ûì{ˆ  â@êA`b#°FðÖ[oâ/þüÏpo8==E×a: Cïž?}Œ£ƒhŒ$œò„+,…#м/`.¼ˆ°X°Z5`öxù²a½ÞÂw¿ÿüð‡ÿˆ¶]åÐÔR±½ÞŸüñ7póæÍ\Ÿ›Äù8v)æöÞ¶-nÞºƒ›»»¨ë#âýªºÆË“#ÜÔ½1ô¥BÉù& ãcööcC1!UÁ0x ƒƒ1£3ûøãCüâñs¬·VEÙÚZ¡ë{l3Ã9·hjeS:ÉÔŒ1ÜïºË5¿r?™Œ%R&hE®²:\ã‡sf)ÉD‰ˆyvÜŒà" ®*Ôu=•ž(¬5˜Ù\±ÉX˜0¡<—¨®ì›*ÙK• r¼W2 ï`žÄõ2*$N'P2YF‹Bt#32¢7†÷~b¥Ê—<õOc•)z*ÞÑOŠÆÆE±BLXvìË@È´”ÊÜË5ï}€¹D`Ïã¢Dô#%Jyy9¡²öXÖí'eíH3Kö3ér‚eùq…K!—® ¯1xn‡ãrS"Dó ™H±TM†÷ι¢Þ0J—9hG©öå·€„ó …„ ÈæÈ—;A`òRüOP·Ü0‘%3€@Œw>˜O “9œæ k.²Ì!tÉø\Î’´aƒàÍôþ¼OÒ€°4 "mý½TÆ!ÄP@y ÙÃ$|\“#"ô}~jô##L,`ª=ÏJ³3ÆdÆ§ß °MkR÷,@‰D8I°PY@‚œ¥&d"\H*À[ï=œó¹¿gÞ¨Ë'Â’¹Œåµqý1½37½äæ bïóx¡KÚÌLj¦¸jW`aU‘A—0 O$90 ÀÞŒçGëKš¬Žùü<¼%ð”"@%æÈ³Tÿ¹³ éîoË™¿)šæ¾w…lÙ~3øÑ䌀K¡L e/i>I7ú†Í]&a2Þ¹bÏÑ´†_ª|éÓ{Ö†µÉÒŸhLÓ{ À‹´U>i*,möÞ,ò²'-ØMÕ/¢œ5ª ¼óô]ç†1>*4Â{¡ˆƘ‰-{ï7"A’~fLÎñ9ÎãBIÐlÙPÌ"j|öüìôGªúµ{_ÔX³6BÌŸ?{ôë­êIÛ4¿—$$"èº.þ£EÌ D˜Ô¸´s‘qk~ÉôN&1¨ë*';é#É\Û¶Íë§§§È lü–Šn,j– ,€;ÝùÙBQ¯··÷¼BŸ²÷§†‚åéùÙiûá‡>‹Djš|iÓåï’KYfÙR†9¿ß4 =þ$”Ò\¹?xyrU`½Þ*ü =?ëŽ^¾<ú×9¨P3°ð€/¸ ל*k©ªkªëu]›º®µ–¬µn½^mÛj !d­¥ªªÒsXkÉ„c EiRdÈ@ÕÐ’©¨ª*3cÓu]í½¯DìY¼gxvâ=ƒÙ«÷^‡ÁIŒ6: ½ÃðRXþëö;ÿûÁ<|øP7P0Á¨Þ{ï½æáÇ™õz]µmk뺶MÓØ¦il]×UUUf{{›nܸ¡MÓkmeŒ±Æ˜|&"‰·DdˆÈß14f]sˆ†ÉI¼çœt]G}ß«ˆ3ûpböÞûtöÞ³÷žsÜ÷½wÎuDtúàÁƒîÝwßMÉ‹›8@pßN¡½7“Ei‹0zeõ1,(­š< þlôªÁVŒép­Z&ãyxžƒç:kë GJœ™¢RZ £³›Êâcc£ŒOgiq!Ö ±0?˯߻Į÷ÐÕÝMOOùB)Ä2iïÊGY\–ê•J¥ÉòZë°‡aWS€h)„d2ÇÅu]úú›­omªA*ZoVÓÙÞ†ãfÈçgÙ·çfÆMP*•¨”*ä íüòÝ·9}æú6pæôi …¼l¶©«›¾gœ£%$_ Ξ>Í\±ˆ—Í.ÛZ•Ø„õˆª~!%õz<þ(RȰQ"ûnR†{qá¤8ŽÃà†õìÞu=Ó“–m[7sËíû96~ŒR©ÌÌô õ@á•KüÏ^À ÎÏß 9~ª„Mk6£M²¾°×ùk4^6KGG7J«”f"°†!0a5ˆvYÚhÇ¥¿}$¨ »ÂB âÏ4Q‚þ¾nvŒmÇXضiˆ{£ÇŽQ)W(gQržÇ_ø ÒñhÏepÝ Žã6Y¬Éz±QZÓÆ Ré-¾^k$ð." qdˆ¦4‚Q¸ ´‰w],’ó¡ª1ÐßËöÑmÔê>#Û6s÷ÝwðÓ£G)Wª¡åëžçòÔ3ÏQ«¸LF!¥¿&ŠVLrŽtáX²:ÛD‡W%B­Bb…E"“4)„ÀØ0Hb²d­eýº~>øÁ1mÙ¶™÷ÜÅ‹/¥V­R,©ûÙl†gŸ}žz]áf2d2 Ë͘¯*|„Cé>ñ–VbÇšŠ!ÝÔr2„éÅ "×o`Ÿà×}Œ± n`çõÀ÷#Û¶pï=wò¿/¾H­êS,©Öêä²O?ý,åj ÇÉ LÈà’Š“ÐíñÙ†]ˆ½-—ˆk‹„LrE3ø5 j0«‚ éþzc„V1hÛðXÛ·ò©O~ÇqÈ·0J12ºŸüäEêu×uعs¥¥EÞ~çmúò—èè줧·‡\® ×q®/8Žâ˜ìG_¾t™gŸ{†s¯¾I­î6EÔtÂ`Ûòí@3ŽcÁ¬Òˆ×pe!Ôà:j™Õ}Ÿõëxðûñ<—öŽXÍwÜÎË/Ÿ¡Z­’q%ý}½”J‹¼ýö[\wÝ(º»ÚÉf\a0ºŽV5´ªcŒÑ>Ö«h¤ÐHip¤aóæ!þö¡/³®¿‡¹¹9Êå2µZ߯áûuT0=y‰…¹bèAq&Ñq°†­±0Ålò^@óH–6lØÐO¥Z¥-×Fà8x/•ªO>Ÿg~v„ Xœã¹çŸÇ'O½Â_?ø„É»My>ú;ýzKk¼g³Y:»ûèìê"“ÉÐàÑþ&CiiNÛ“¤>â¦«î ˜Æc‚öwH-hhp#[·’Íæ°ÖpàÀ*UŸ‰ñc¼|ò$ÆB.ëñƒa©TEJ‡@7îwpZ•›.b’÷{RÙAJ‰ø(²»¤ç—~HÈd;<®cÖ²;œj$FN*ÃÐ!\ÏM»oˆ6Q ¤R …?{æ Ê mm<ùôÓTªu<ÏCJ—LÆM6UÒõzZ­ûúi¯hæÍt7îd/× JßoU&3¯ôÖX:+ ²ç¦ÝÔý€á¡ L ÿö[hËçñÅO=E©\Çq7Y ´Ñ(¥ÐZ' K»|ÁãgÆëI—èqó"œ4¤mê4:Ä‚f`_EXU¥5ÖÞÐàzöܼ›@iFF¶ðÙ¿úL"ü…7ßdýú Xk8rä ––*)qR(×åiP•R6 šôõ¹²5ÁòÍÏ(¾CKBØÒ×c1«î Dý¥´àñâ6nbïž›Pʰmd3~ñ†ðçϳný:Jå2?ýéQæ–Èç 8ÒiZˆ1¥‚ HõÖÕ:ôŽ´ÛC ¢zË› Ò”ÙGI¬œU™`Ú:qþß8<ľ½7£”add3‡š„ƒþõ”Ë~þÖ²Ù šº·­m©07×}~Û(ÅÓ5½”%›Ï·þ&ö€p'¨áIñ«¿khŠÆJ0‰ð·îß›¸}Zø'NÐÛ7@¥Ræg¯žcÓ¦8ŽƒÎ|ÂÄ/1Ș̌«¾Vᤔ¸®)T$€Ühv6¸ŠN!¿µ×uqÝ R†Y³–íqº6nbÿ¾½fdt+‡¾ø…Døñcãx¹,Õj…W_}…ááarmmxÙ2!vi&*4ç­ ×z±¥1DV*e$ˆ³W¾"TP.›Cnøœµ¼*Çì¦-›¸mÿ>¥ÙÚóÇÆ1Và¹Î;Ëðð0…B®ÎNG&Õx¤ÉSœâØO Ÿ½´ucO€¸ÜmÐÛtŠLžÒØØ»ÂçY»*l´aÓ¦a>të>¥Ùƒ‡RÂO`´å<ž~憇‡ioo§££7“ÁÚ0¥Ý9qS.FZk‚  ^¯DÇßjñ´B'Ü›LãIìòñ¦ˆé¿*à8n«)`Ë–Üvë>‚@3:º•}±Yx ù¶,~/›#—ÍÒÖֆ뺾OøüÜJ)üTˆã3Z)uE&ˆ­Ÿ¼µ–Ôø:jx´ìX‹—Í>Z+À!ŸogÞ®ÂvŒu~è¶ý¡ÛnåPJøñññPø|–ÇÿofŠsH!) xž—,0ÒÐ2¦Å:kI^²ŠC! hÐøOñù8ÿ+DçÓ¦‘jSĨ^¯&m­¥V­ÀJÅÐÃõ#÷Ü{ϺZ]1: _­Õ™gb|¬ ŸÏqø±Ç)Î΃Ñ9ãyWXsB¬ ]ÐD»~“i>£x´¾óo­h(2%p,4ñýøõ:¹\ž8Dâ7K–UÀÃõ#ÝÝÝ]¼xYFh ?>>޵‚|[ŽÇ{œâlhù˜a¤(A&C½^£Z©F‹‹NÃBJ©Ä¢RÊÄ­c—Oƒcku(¥Ä÷eª9Ú\4¥×hï×ð¼0S…÷W*àŸù—÷õüM[[~zlì|úþOS©ùg"%ü£f¦8‹#„€ÁXÕTíØ±¥Câ‘&8ZÚ yÚÚrIŒÇ“Îå˕ȱpq?NÕëCe7Џðz߯ƒ€ ðñ¼,ZÍ øú׿yPý•WΜ^ëm’Ÿûüçú—ÊŸ-»ý÷¾÷(Ó3³!’Fîì8Ž•RmŒ#"AÀ–ÍÃìMˆP"h,..%ñ›VBú ÀK+!*W¦Me‰æ4\6J"’‰¾þo4ÆüýÉ—Žß²qãpWg{žóçÏóÞ{—9>1d¦-Ÿå{f~~/“Áq¤2²é©‹oçÛÜËYÏ»#¶1†Z­5;BLj’vãVšƒbZ!ñ5iº,¥LJjy]÷"üŸ.ñþD¹\N6°’–‰±9à;ÿúo6_9úâ‹·nÙº¹óö;îàÕsçxãóÌ-,Îg<Ïw§ç»ßý®šœšªU*¥i£õbô@5,ËÕJ9{òäÉ©HH›véÖú½ÐVêþÆÐz €çybzúrØJ ÒïCiik!ŸoKá„­Vj ¥Ò qðÞŸøè}ûʉ—ŽïÜÐyçÝwóúk¯ÑÞÞÁôÔ$KåÊÔÖmÛ‚oë[¯_xë ,¹ŽãGml›Édd&“‘ŽãÇq‚|>ïg³Yëº.™LF8Ž#\׿Çq!ÔRDÖ‘B®Ø °áˆCÅZk­Öß÷e­VË(¥\c4Zi£”FéÀ(¥ÑZY¥”õýÀDÙÆú~Ýú¾_2Ú¼ÑÛ×wAlÞx$›ËýÙ]wßÅGﻳgÎË嘛ãòäd}ÇÎëgŽßPð Df_ç}OüØ?øáOñr(ÓÍ Þ«gr ðÌé—á7îPZµÜ±‰Dy;™ysÇãÀòìo˜}?ÿYú\i@]>|e@a0Z¡•Fé´1ÝûÌþÚ1"€Äˆ ÄÄH!"é4Eˆ1""D"—6qÎÂliÍŸãÜ Óí$ Oˆp"}'hÅ àäÜ.FaC+ˆ"'~ìÇ_¸ä@ìcú¥ŸÿµcÀ1`Ôñ|›¾Iiµ¬”F+u_ºw‰ñÒ{…Vé½µ6}&BQ•¦ÀXR†²(ÐŒNŸ…eey…º®°eAY›¶µ…¡(àû3#çÀ5=® DïpÎã|À;ǸiØÙÞÂ9‡÷<¾ñììîâ}À‡€ðmÄGˆ œsˆD@öD‰œ9 "›Àð Àþ·?üÀ-¾úgÀsH¿òK¿~Ô²R–Eä›Hšù8°ÜÝ­4J)ªºF+Ea-¶(QJQ%Ö”R¶ÄZ½ç~FŒ6U1m (Ca-Új´2(­1ÚàƒC)… 0Ú䉢(JD<ÛÛ£dad\+E÷S"’ö¾2÷ÝÕß_‹ý>Æê)“ï > ¢(Ë$Ô$‚ž¦iPD@ƒÇÏd4Fâì¼\Ób˜.vpÞ¼# xï‰ÑDp­Ã‡H çQÂT€Ìù%"œÐFìþüû?ú·6žÎZx®è@Übú'¿üÇ€cZéû€%à¸Rê˜ÒêØl+M]”(£(Ê¥ UY`LbÚª*1J“¬åˆ© ¢(m±…XƒÖ­!ÁÅžóP bšÖ!Q0Feƒv2f‹A)ß ®MÌe¯ù­ó3SúÚÏN)E¶TˆsëC_ö¼“™~ýÏ´-0Æ^&dÒ11k÷,戢.ÓgZk”VH”ÌÌ>ŸŸÁ;—Ž¡®Mïƒx|ë!oߺdøè“ÕÑ\ðÄàðÞç{·çô6@>¯”:!"'Þý÷ÿæ×¼QÏ!€›Dÿôý\Áuø&à˜Vê>m4 èU%EYP–5…-¨Œ¡¨*Œ1 …" ð1 •ŵ^Ž—UO3€÷nsx×L¿›>çE$ûîæª×¥Œ™î3Ó rÕg6Ï”J)ŒIBÉsCÏøjÌÝQðnÏuÌo½'Šdó~/ÍG‹Ö³ø†1ÅÜwé:[äóÖà|D«tM¶$$‹ DPŠ<®u´ÎáÅÓf+¢m[$λœ‘"òq‰ñ„Ò<ø_¿û¿|ðIoÌ-¤ð4è×?ð[ËιãÀ}1„oŽG‘cIÜëõ)«‚º¬èú”eIQXDRÀ*xE)8cDiMY›„€Ê‹N¢GkCô~ÊÖ•(Ù¤ŸÓ”&%dÔTCïMÐ(k@:M˜˜F©StL”¬€H”ô™÷ä3 1„î×èsó[)6k-EQ`E}…–¿Ô‡÷‰aî›äJÌ 1ò÷J+¼s{£ˆ¤cuÖC²0EÕ:Y$ÚPXÕ*Åa” ­À¹ˆk&m uÚ‰£™4Ù‚D‰ˆÈム?o­yðoÿ½|ք¸úç¿þÛÇœs÷!¼="ÇE8ÞEØêU¯¦®*꺢W—àEhšHˆqÊ4J1µ‚Ä€DÙÃÔJ«™·©L6¥Í,8¯ÔÔ¬ž.è¸Wûu¾ö ¿$&÷¡ªk k“Ð5š²¶TuÊ  ­©°  Ê¡¥´6¹ý< >i5LZøVkŒÎL®5Ñ;Æc—u>ñB‹o<.DÚÆá‚K~»BôHÄ(‰é|%f×AÐ*éßx•ef´ÁZ±–¢°ÖBÚP£ÀhÚÆ1iFéüºcd¢äxFÊ^H¾¯!Hºè|C»ô£„™0†´¿-lŽQé>X‹±ea°Z'`ÒS7À¤miš–Ñî˜I3f4žÐ6’@؈" |ÜýÀÿÝ|à)-ا@à*ô¡ÿéw—'Mû‰áí"r±ÔeIY÷è÷ûôû%½ªÆ…@ë"mÓ0i>3¢Q ­™¦Ê Nƒy"$Ó1FE—ßEÈšf "Xc)ªbÒXeY¦ßц²®PE¿ßÃX‹1ÉRPJÒhQ s) V'݉iµ2Ð-Ô93YÅä’D¢øÌ2Íþ‹«tú ¥0ZVxiÛ ÞÏ"õÎyœ 8—pÞ'¿:I÷"„” !Å;$WˆLyV®&€²*èU5U¯¢WUôêš²,’õUTEAY¥ÅƒsɤÁZ‹sŽ­í]ŒÑxïX]Ý@CÓ4¬­_ÂÓ™J¡ HÌ÷GÂ4Ë’O.?ûËNN)Œ±kÐÆb´¥ª H)Êœ±QLš–fܲ½»Ãh4b2™}H©Sá­øxY–÷ÿÿêûnš…p 2}ð_üîñÖ¹ûDäK$¥Ê†ô}úýÚj&“–íÝ–¦àœKQƒ5« Ú¤:(PŠ8W(Óé$‘HÈ‚Â{ÉLª´Â DŠ¢"eUå@š¡"˜»[<ê²ÏŒ5h­P&Y (Fås+Ð6¥†Âj”-ób¦6iÑ)D<!JbNA &á¦süÝhCJh´I~´ž¦àÃû@ÛzZï mNç—\¡à Aˆ1 ]m@‘nÊ4ªßI™« PhŠÒЫ{T½$˜«º¢Ê©Ì¢,¨Ê‚¢((ª« EaQ*¹)¥íU˜˜LàäéÓl®ï0j&ìlîÒd .ˆĪi5œäû­t4:FTvŒš1i£Ñ:¹J%륓Ka4Çlmí°½»Ëx<&†€ˆl÷—eùñº®ïÿwþÕ§yxA €}ð÷ŽO&“wŠðà˜RŠá`ÀÒâÁpk,£É˜Ýí1[ãMÛb•¡°*™œÚds½;mœ³2³io´žúÚ)"Ý™„¤ýóó©?‰‘³Éi%FW(­ÑZåc›éçÆê©è„59g Z™$° C¡ ”UØ© !Uø©NhEBrÿŸüâΞþ§@™d $y£iOÛ¶´mƒsÉhœÃµs@NÛí±b{,€¹|ýÕ,…¢¨ì^  WSW· [Ì'çî¹I~ûea67[.^\e}s‹É¸e<3Ú³»;bÜ4¸¦aäÚàé*MAY(¬2”u™Üm-V1 4ª|ߌÑXcQhTÎx¤:ŒäÖ„í]6··ÙÙÙ¡u®»/÷×uù᪪ïÿkß÷?%að‚¿õ/?¼<OÞbx7pÜhÃâp¥¥E—qα¹µÃæöMÓb´ÂšdÂ%mš5ÉWÊäÀY2íE"Æš´Pµšú)¿ž£Ös¾{ qʼJ%mJfd­³&WÉ¿V:Y“™ÎâÈù}£òbÒmT `)²–"g¬±¨" R+°ƒÒñ`“y&iwoŒ;‘' ÙÕÉ–?*?ÁÁx ƒý^EÝëQW5U]PWeO^„t5òV/m³¹¾Íh4bs{‡Í]vF»ììŒñmÃh2B¢g<‰„èˆ*"­'ˆ"úH$¤kˆL¥©R*WÝ£W÷Y\2XH1&¥RÇEÊ@D‚w¥1FQ”5Z+ªºL1ehÚ†õKlllÒ´ âƒe]¿ÿ¯}ÿ_þÐõ®í^üÎoýþ±Éxò>…zWYW9²Ä‘#G©ëJ4k›l®_b<žP•u¿OoÐÃ1 ãɘµ‹[llm±;Úe{{ k Œ2hk’©;³=ÛR¥œÎ5›ä:É”Ò(£“Y§MJ+Y›cz*´šixcL6Oõ”±SjÍL­•Î<…2:ýÖTÐdá`56[Je %Gï“°RSUe#@e ÅßOrï[ã±gÒ4LÆŽI;Á5s x¼ xæ€L«ö:!0ý¿Ö:««$ƒš~¯G¯WSU5½^IU—Ôe.e~š4nak}‹õ-¶¶vØÚÜfw2bw<ÂO“vBðžÆE\㈺FpAˆεà=­³j÷,»ç4,0ô8|äKKK9z$WcÀµŽñÎzEEYWÔýš~²0´Î±¾±ÎæÆ6ëk—h;Qö§àõCW»®ohðëøW?ÕëUïî×ýåÛî¸;n?JÝïŠóç.rþü9¼,ôû¬=D8¤, vwÆœ;wÇÏ\àÌ©³\ÚX›2—ä£5E‘Ìik ÖÄä”Of¦Â$†¶º‹Ê¬Uhc°Æ¤yNm±6™òï§³…G­ÏM7Ãîa|²Iêºc~£Í4`æ˜_«¹XBw¼=€yZ[±¶¾ÉÎÖ&Û»vw&ìN&„¦¡uZ\ÄÖãBÊšD‚Éšq‘‰kˆ1bºöÙuî-²ê\F£ ‚pôèQîzɼøÅ·sÛ‹nÃZÃîÎ6Û[»4ãeQ0.pøÈ!êªb<™°¶ºÆ¹³ç8{î;[»T½Þ{þÖßþþ=„›%žQ;ðͦ_øù‰ÿwQÇï|ñ¼òž{X>t[<öè Μ9(^r÷]¼è¶£ †lníðµ‡åË_}„GyçBzP!"J0¨izM[Ka-‚E”ÂbBé̸:ÕÚ›”r*lÚ§«ÙOCÊ[§÷檌ß1¸ÉQb¥F]Éü³¢Ÿ.åÈÍ@7‹æ$ äú“Ò¥Z4&FÄX  9lDAt¡§BÎà ÙõI¯©+2"Þ9bNž<ÉÉ'qÎc Ë+_ù Þøú×rüøë0FsñÂ*ë—.qò±S,--pç]wsôEG¹íŽ£,=vˆ¯|å¡ûNž8ù¹ŸýÇÿì§ßûï§nöÙ7à'ßûóÇwwÆ»ãÎÛ–ßðÆ7ðêW¿’á¢åü¹M¾üÙ‘(ÜóŠWðÒc·#|íá3|ø÷?Æ#ñ'ŸÄ†7½éÍ|÷w¿·|ËëØNŸ<ÍWzˆ#‡ñÊ{ïfeå ƒ>JÁ—¾ôçïûñûÇ/ý¹_ø‰º™÷e_€÷þƒŸ?îÛø±c÷ܾüÖoy3oü ÷ðð×ÎpâÄ)^÷ú×pÇKüÛ?øSþø>ÍÎx„oS.:„–6›s‚€Ò”…Κ\S•%eY䊿Em©‹’ª®rÙk*òèòð]ðÎêÄø]J¯3Á»Èþ~¨ƒ8  §ù˜T—q¹È*ljtvZ±DJIAPçS™°)HÚê׺\2ˆÑѺç<2Ž|ô#á£ù·ßq'?ôÎïãÛ¿í ´íKùâƒ_áO?õE^óÚ×òÆã¯`¸8¤_øÄ'?ñ®ÿÑŸåç~é½7Mì €ðÁ•Ã+Ëßý=ßÉ=÷ÜÀƒŸýÛ›Û|Ï÷¾€ýáøwðq¶·wSßw¦—ÇGÉ]o©›ÎCY”T½š²,©K›þ®+ꪢ¬ËÔ+oS{­µZ«Ôü“ýkklúLíeþg£.þ€ö#% /y¤òî(’j %uÄZ›â!9èg¬Å7m*‹9f£ÐúOˆ1òø©“üãŸýyŽ9Â{ÞónÞü-¯ák_=ͧ>ù)ÞöÖ·ð²—ßÆÊ¡ÿ'OýÉ'ßõ ÿï}¸ÿf\Õs.~æýÊ;€ãÿáô½Sæß¸4æÒê:ßõ½ßÊ©3üîÿöû<òè œkð"HH7¹«+ShJm0eIQ”ÔuúíËdÞ—eAU¦þû¢,)Ljv1Ö¤(½Ñ9÷ÞåôÌ÷zrš*eèZ±µ!(®«Ò̲>&­«®|œ¼x|tÄ8áx>ó™OóßüØÏð²{^Æææˆ­M7ýwü§ï`Ò6ÇnÖy?ç@Q×,,,ìùLYÍŸþÙ¹°v‰³çÏ¥Ú}…5Ö¤Ž-S`Ph …)Ñ¥¥´…±Ø²€\Tc»œ}®{×sé¾Y±Ï äÆè€n€$·5 9ÍKj×Ö`¥ ÄHU¦ï¬µ¸Âá»ôjÛ£G)8{ö?÷‹ÿŒ·}ó_`sk‹Å¥Ã lQÞ´ó}Î@YØõµÕ=Ÿ---röÌ|ˆ¹…UQ•†²êQV–BèÌØ]!†Õ+åÒ„®Í5kùìã+=KÅÁ¬–ažÿSN÷Yºô A—CQjÖžl”"äÔ®5–hQeê6Ôo lá0ÖàZ—+¹ÓLÇÝ]îºëðô¸««« ý›6¾ì9w [~ÈÃg?óÕég¯~õÝôëŠÃK ~ÑÊÂPõú,ôû zɼïUu*­*ʲĖeÊÑ_®á§õù]M®îC͘ÿ2n?ˆîÐÓ¡+&.©y3û\ç´q*&KY¨ºªé÷ú êºä®»ïæ›^ûj^õªWN÷óþøÿ¥Å¥›âÿÃ>°þî»ß¹ñÉO|aãsŸùüòá#‡xéKð¶o{ ŸüÄŸñ†{_N¯¨YÛX£¬Jª² ú²QX9¯Õ\u\WT“ƒ|{ͦï÷Ôú0ÿ= ê˜?Æùvçnm©i/†ÒR{¸(É¥â1’zFÊÈ˽Œ·¼éõ9¼ÂÞøòt|à£ùʺâ?ÿ¾ÿìó7뼟spï«ï}ÿÆæÖû>ñ'ŸÞÂÝ/½ábÉ¿÷¶oæÏ¿ò5:Äù‹—xâÜk¯¨’ëºkÅvj©ÙkWy× ÝMÉ…Ô ÚMöéFòÐ=EÚëÌiþ©ÈŠG+”¤ Ĉ têE~Éwðú×ÝËK^|/¹óî̦¿÷ðG|ŠÕÕ‹|ï_üž¥¥âC7ëœ÷…ðÁýê«^ýª¿röô¹ã_úâWX[Ûà•÷ÞCÝ/yË·¼Žóç69rö÷Üsgάòø¹ ìl¦7˜jr=õûg}÷º{5]›­ž5ШԻßÑp@O‡._7óq$=§ Ò¿ˆè.m˜ÿµ¯y/¾ó(‡áرÛP* ÞÜóПo}Û·rÇ‹o{Rjãªàè‘…/=tò;ëaïcw/Ý}|kcƒ/ñ+¼èŽÛ9rx…£·-rôEC¶·[ZæØÝ·±zi‹sÖ9î"aߟ}þ.Í× Îè´}Wáw@ôLéê ™ÝÐØ)£4¬TMÝ«xùKïâž{ޱ4päèîÎîo0šxΟ½Àú¥Kôû=^vÏË ú?Ô«Ô‡næyï ðúW¿tã¾÷—ßóê×Üó±ão|JÁÆê£­múËK‹,ô î>v;Èíl¬xñÅUš{±zi›‹«ë\\]#fkO&`Ï5ôq@t³èÊ,Àe Ii†K}n¿íwÞ~;++‹ ‡^tÛ†K ðÖ/¥NÁÑî.Jkn¿óš¦ågÞ÷³üÚoþâ‡nöyï°zi•O~r“ÇOŸã;¾ím9zñÝ­Æ;#6ëŠÁâÃ…Šá°bqé%£ÙÚsáü*νŒÝ—ÖwÙÚÞfw2™jü©0÷PP{-€¡p@O—.g~aЯYZ²²¼Äí/:LQ ­,1\®¦ëm4 ¬žß iÆ8çÐJÑ ¨ú=ü̃üÒÏý§?qKÎ{_ €ÅÙ³gùþß?àÞ{ïåÕ¯|9½^MÆ“ MÛ²µa°eÅ fÐ/éõK޽üN¬ÕŒGõõMÆ£!DvÇc&“–QCÛ:BŒ{b"{ct@O‡”R ú,//²0phe‘^˜üð¡V/¤ Í! £O"›ëÛìŽFï»…ˆ­J@sæÌYV/¬ò{¿÷0íܲóÞWÀûˆ‡5–v2ᑯ?Æ¥µ5ŽÝ}7·ß~„ªêaL$DÁ»H3™°~É  èU=† }li8rtcVÐFÓ6­]¶¶wœ÷4£m}çÜ:œ÷Úÿ2¹³à€ftøÐUU2YZ°¼²@Q ‡–ûˆ¼ Ú­q4.²½5Âû„«cªšQá'Žsçg}c“ÃKKŒG#úý>>„ëŸÌ3 }%Bô@Â}ó¡È˜nž'Ξccs‹C‡VXé÷k¬Í€›Ášv¶w‰ZSÃÂpÀB?¡ç—,,õSY°‚ñ8°½½Ãh4žþöx2Ih0Á3·ø2ä×ÍðnNäùùD‡——ÐÖ°80.Ðï×, úÓïZaa¡FÒ ÔP­K@*£Ñ×L‘éÜÄÒ@Õ=!ÀÎö6§NœÂXËâpÀòpÑ.Ο'º…÷}_ €˜]¢ Ýõ),TŒ‘mš¦¡ªkꪤ°ÅTs—•¥WeIŒ[ë›l­'û#Ã…ƒ~Ÿª¶«.Ö —ú65n 0µloíNÁ&šÖE˜´-¡ ¢à_ ¡}õ$¬V,,QJÑï÷±F³°°@¯.éÕ´óÒÒ0µ“׆ÁtÆRˆÄÈ“ ˆ­ª‚~¿ÂJí¿ÎyvGcvwv¹pñât»²,é÷zôû=–ôû=zeAÐ.­­%àÁgºZ'›Ê´$×!ô‰Íâ4. ¢ˆD¶v·0’f?LÆiü{ëcçŒÂÆÆNB4jÇ4MC‘;ð*[¤QñZ§8‡hªªžv‹NÆ »Î±³;bgg—qÓ°»3š^KÛ6LÆ ›››l¬_bksƒ¶iÓùåß“‘¢+ŽÓµIÒZTŠ_¥ _ .0] !C3Í»ÿ]Ï3¡…Á€¥å%ìK4Ö¦y››;LÆcÖ7·8{öç.¬²µ³½g¿#+Ë…eqq‘^]'”áºG½\&@ÎnL™À¸mÙÙÙåÂ…5”V4ΜG$²µ½› §Œfe)K´¦. VV–’ÖWЯKl©2}»Ý±lb2Ue³VÔ¹¹;Ûú¹ö< ˆQ§Æ”éý”Dé|“%cf¨mÕ¡ûu÷<Á¥JÇàJ¥è´@Ô*­QQ1mBŠvà ~mþwCŒÆÛ(QHRàŒIÀ-:œNFŽŸ}ôõ-BLöûöî.­kÑ•M“wÈØ‰Š„›(:™êe‘ƒÆFcI:vvv,$¼ckk›Ñ¤a4že‡&£1Á9œkÙÙÞe´»Cp-~n$xˆO/U×¹ÐÅ fà‘¤ç Ýoí+ ”Î×1âÙÍ`ú‘ÜÔI‡W–0Gó2«0o~6ƒLž?¿Më««—¸pa¦myè«\±ÿ`¡G¿®é÷{9’lXZÐë•, 0&aFR±“ðÑ3™´ ÓÂÞÜØf{s¥;»;ÉÑBããqCŒ 5 ‘8Å\.0\#ISHbd£¡¨j¯,e+bª[©)…dUˆR¨li)¥3V$(A²`ˆ tTˆNÃógÝn ¢ *Ûµž­Í턵'’ŸmL@'(¶·vpMC貺N9Ià(½^Ým_)íÔ( ‹Hr#†ýaºWJeµ„ÞÔL\ˆ„Ö³³³‹ X[[àâêúϰC9ö΂Ã5m†Ckff¼OB>Þ´¼|®1‹_¥¦®dk‘=BûæÓ¾Úè¼Xn˜q¹Ù¯ž¥Ê½Ûnp×K¯Øó]ÛBã[ÑäÜô¬ÅUЉɬ¶š²¨‘ bÞV£ Teç6 ðuD0V爼šžgîØÀ…R†Hd<cLJÙnnmeÆP¬]º”м\`csëª÷_eðT ÙÏΣ¼cL#¼ãmžÆ{‡[\%ùYI8J÷ü$¢$Ëó,ní+`tz¸ÖZ”™°Øef3àf[O‡ÊÊÒ2|Ešdü†<Ôô/å1æ]Ú˜°ººŽOœ>Ëx4F¾| AÑQÉÅL9…¢,XZ\ê<úé<ã‡VXYf'?1yÌXçËËK(¥1Ÿã”q³Ù“Ý|å΃P*£ g§CR{jAgÔ«xìœ J’¨ˆ0q)ˆ×1rê»HEÓ´ŒÆ“$ì³0¿´±ÅÖVfÞl­\¸p¥¦¾œ´ÕÔE‘A] ‹ÃQ«õ,U™ƒ´!D">£§@óµ@KŸ RJ!)ØRÕÕ\dÚØ¡’¾P,€Ù5ï5õ%ðlY7ƒ-×ZNBâÞ,,.§µKãŒ08wîB­sÉì<{î\*„hwÎ]x4å¥3Ýhþýf-t¥“–¾Þ3xª¨HZ©”…©«äýŠ`Œæ¥wß9Åß«ªjOÇ]YÄ\U7{õ‰Éc !úˆÏ(=ûrtäQ’;£Ï50]¦àÖžûþ9heTBõéú©;`…Žöƒp3éð¡Þôý‹Ž.Ò:p.à\Ë+_}í¸¥i&LÚ–f’ªÍ&MK3ÓfØî˜Ê¼‚dÞ;r€ª¶Ð³©4*Ù¡2y|2‡uhLÂ5Ôi†]fµÅV†"C¡'ËuV´µ²²LQÉg–$‰„Y\\ ,Š\'ŸÐbôùï0ÇÄsÌœ¿!›é·°>þÙ ‡…v–¤Ú—³+’£¾ñòHøM¦}%¬5$¦Ï&Ö6>G©ŸCkí9¡Y•Ýõ/¼˜ƒÏMqª…Ë*Ùºá°Ôhdó<]¹°6á'èn`¥ÉX‰–¢*)´¥ª в * ŠÊ«fÈõï©ØæJmý{˜—‘&Yo!ky#>zB(rê3Ý#‰2uönÕyìšMòC]ä&Ç4wOÉTã}£Ò˜~×ÛæZ®AgRK.®ºâ»Ü/ßÿ0ì|Á ‰DRF( æ.7Ÿ…„dK@rpðVѾÓvì^‘@pï…àR“N¼­ø|§kÕ;<™à»œñ;†:÷¬Û÷ÊÏžÒaž”¦ÁÝ}ÚOp+HbDÅ\$¼à\çæDbTˆd…w ­¥}%º ÒjªpB”ÔÀ]ö%Ãt¡tƒßhÖÀ“õ\îtãËïõ­€Éï‚LÓܳīšæó5ù“¿˜'¡½“töÕr¼%4/ˆS¢Æã¼à‚õž›/ÑŠ¢H.¿´/ï¸Ñ©~½‹8çñ.â½Ç‡ˆqÊü’S%]ê ÓõH— ‰³ž É(ÊWZ{Ê^Wì†].t®üíœÆ~Ê4ìk ¢ç3]ËÉnÁãBƒkCN_ +""!x|îVœ×¾"ò °%RuU`­%Íp´.¡¨FïS³G 9*<3sg‹÷O\í’.×ú7bÈ4Â,3Á0exö€[¤cÎ7úÜà¹Ê ‚«¹&ßHcÚæí'‰qºN¹âÏ{‡oCŽäJO¥Ä$£8ÞŠsÛWà7í¿ßPJ½¿[Æ–…A)r_v¤içj°}ÄÇê^aðüÑ&×?Õk3ûåfÞ5š™ù7â.Íï3¯ñcqϨ°'=ÚôždCfšÿÕ˜fubLýþyÝú\.-ÞƒD§x׸±¶¾1 kJ©ÿîVœÓ¾»Ó¿ñŸý©fÒÜŸ¦£Fª²ÂhCˆçZ—,çÎ{‚÷)Íä#1ÆÜµ×ùX¹’Šçc¤ùÚÌÞ ¶«îuSýrŠÒEûg‚A$Îfœßvo1J˜joÜÂz¡Fû!¯ÁŽéE’rý‘€BSTEš1€Âиֳ¶¹yä‘ö̧G1Ê;>ùç'nÅùí«:€Ž{äëÿÅ/¹ë;ª²ZQK…ò9Œóݦ•ùÜh®€U©«ŸÑ€EEDžÙý@×sgöhý¹ ½Y±T*éÕjtçÀPº!*Jnò!Ï$鬨ˆÉCJ.w_»ýŸÂUÜÐVZ+BèÆóÛëžMWÝc„<èFa°…ÁÚ‚Ê”E‰R­oÙÜX—¯}å«ñ‹_øÜØ÷§¾üÀ­:Ç}g|ä#ÿçú™Ó§þæWú²+ #‡VVôzÔE‰Ö–bª€k[š&UÂuëÞ¹ÔÑg‚(’JªŸç êrºœù¯öþjŒ·§`zŒÜ qO€O¢L+Õö¼¿Æ9uûE¹6Ë_Ïè‚ÏoW`–º›ZXäúL­(MIY× ‡C+ê~²®pѱvi¯=òu>ó¹OûÑx³iÆ¿z+ÏtßÞá~äÿúðÅÕµýñ?| ÙÞÙæðÊ2·ßq”C+CúƒE•Ì&ñ༧>g <>vÁAB·p»Í-m®¸ÙÔMêèjYŽk1ÿüðÎ.ýtå|ÅO’Â|2‰¹…ùù)°åŠ7ÐU¸VEIÝ+Xìõ©«S è÷ akk‹G{TüÜgã…Õ‹U ñ‡ÎžlãVžë¾@Œ~bóÒöÙÏî³íÚÖ¦ˆý~å¥!Kƒú=Ê^Aam6q|ª1LëÐ%ç¦òïs|UO•Ì\Äž _~gø¹|þAóÛÄ䋊t3gb”2‹/$?[{Ž0ÓòòdÂT®.°.¿†Ëi¿kþë-!É”J§Vjk …1”EA¯.1EAÕ«1¥ÆÖ½^…ÑŠf4ṋrêä㜿p6ôzƒ÷Ÿ9ÿð·úZöñ.äÓŸø7†ØüçÎ_ÿâç¿NœxœM‚ c©«Œ4¨éÕ=Ê^­J cPÊ€JÃ%æX¹Ž»)\y®]íÃÞÏ.OÝå¨zH(¢LMûĸk4›¹ØÕ$ÆŒ³÷{jàf˜Pá*×5-ÏË:Sƒ±Xm°E) ʪ¢¬«äï—ƒB[ƒÁç;»»²¶¾&'N>Ò–e=~úÙ8å}Läh½ñŸýÌÿ‹ãoúöïxìäÉ·K»£±:zøKKC†ý>e¯¦ìT¶Â[XŒ1c°Ö¦®µBcÉF £òªkÑ>±®e.Ï‚x]†#WFŠ UœŽõŽ¢ÐjnÑy@.AÕÝ•}…Š€ŽHÔSfs~l œ¯fë†_Ë ¸¶Ù}?56íÇ®¿Üm©Z b‹%b’ÈîV Ù %¥ûòT#ë ÖdÜ ‰llmqêñS~ÒŒ× [ý'Îuú¡ûŸ­ëÚßNÇ/<øñ¯¼á ßñ?omn¾{õâEk‹Bk4Á;šÉ˜Ñöˆª×cei‘áŠg1 •€5”¶Àm5V0`”Mƒ3ÉÕ¤ÙñiÖ>¥y^¸ Žz~£îã4öKòXp™kº‘ipOu8 JÐQ‰¢1yzŽ3—£ yTåõ‚}7)~×¥ã\MÇM§+ølž*1|ŒiÝ "ƒ E'A$Á}ù<ßÀGŸf8LšÉ˜qÓ2žŒI¨Á}ªAŸA¯Y½x1º¬‹z:ûo6cuÖleT' "" [ ‹ìÍ‚‹s!ÀéÈ*®Ïýs¿EWñU,„ëEûgÁHE†VyÒß½1š™ñJTž‘†·Zm*&ЖˆFA¢¥è¦ôF•zöCÄÅ€÷ x¶uަ37Œ'#&“ MÓÐ6Ž ²®é/.røðªªÏÚúj\][mG£Ý‹Z©Ÿ9uúÙ1ý;z€(!Ä Šw·®ýøã§N™ºî«ºªÒHˆ‚É8ÏÞ÷¸‰c{{‡þ&ƒ…>Ãáƒ~ŸÁBŸº,±eIY¤‘Úv_Þ…YŽ~jŽwÏiÂYt¿cÒüw·S. ŠiúÝ•!C«åBrµšÑSacœŽÕ&Ç’Ù+fç÷Ô ö'½Oµ€0AªD+Œ€d&×J!Êbˆ ±´2ˆIóµ5 ‰& 눒‡›x!iûˆK]¼1âœKš¾iÃ'ŒÛ mÛà&©zÕÇH¡- ƒ>G–ÑôOƲvéb¸xáÜŽ1æÔÉSþ¡§|ûž!íË¥ ŠŸù³|öMoþ®_ÜÝÞúÉógÏ`­¢WÕÉçŠà ºÑ(Òlw‰]¤õ‘ÑnÃîö6e]S×%uÙ£×/©ë’¢²f¯Ý74=§Nûtfy6é§_Ïå7òׯO…ä  ÎÖAÎ(ÁD“ „²+@4ÓƒI”éñÃÜÙìáø«F¯î¦\NWúúIãk’Èã!5óزé³ÎoÓ ðD“®YEAtvg¼àcÂ)ˆÁ$«IÈC4W°>M_ïÑѧòÝˆÚæy}àC*GoÛ„8i™´Æãç&´MCëÚ´MHˆÁEU—Z>ÂÒ‘CXeY_½Î~òÄ©wl¬o¾])}Ü”fÙ‹Pfò察áÅ·ÝÎâPNŒ[>>µ^©øÔ'ÿÍÇ^úÒ×þ*ð#ë—֨ʂ¢(Ò,ûèó8%‹k=F;¬Vxk±Öá}š2lÅ?Õ~Ó&ZƒÓK0 ”B<Äè20 [Š'C*}šTPµBQ“ 4ÚS´M–m,Þ8| aº32î µÊ:ß L̃Bm:–ÒR#•Õ]X ‚¥A—†¢((Š* ­,e j/“Šȧ’ ‚"ŠMhÏ¡HÐ^/"!·Ã†Fxû˜J¸}ÂÛ&‡o-b>$¡¡Bªw¢ÐÓè{òÕ½8ð¾¥q1÷‡¸)È«ó>µ’»Ääiâp‚Ÿ¾—€óqYØF—·xïp! ‡ÓkrC3öcŒxŸ,QBYôXY^æðᬵœÛ¼Ÿ8}ªvFUÕNLÿŽž5 "ËÀ»F#Þ}òôùcîÀjæIÏJALjÜ'‘÷=zr}cwwûþÝÑèýÿþw¾ý§—ßqúÔ‰c‹Ã!u]±Ð_¥"J%xh .h´s˜Œ7­Á9X4§:«!¥½×ٴΠ¤9€á76Ö·{uÿ7yì ·dÐÇÒ³"DäG€÷˘Úße!ÐசJØ—Ëä]!È»þ×uÿÿè}ï½?„ð#gÏœ¦¨*겦(,!”RXkðÎãFk-Lž¾Ð:`”"èTýcÚOk…szêFLÛŒIÙS mDM $Ø*Ù ¿iéÄRPÓyOpy!’n‚Wøh±BŽÜ«d–kcÑZ%œ½®ISv$ Lx6Wv7Y+˜„µ§ˆD)ĤC¾è+dö \Pºw!€‹Bp>ûÊ>iÖài]‹omxçq>3“Eïð"iœ#ùë1ІÜ÷Ñ1bðIkKÈÛ|Æö‹âSitè°Ò$^ç Á$æôžLËÆS9uÈÁ˜ñ R† ½w³CL@²ß_ú>t˜ÅÅ!1Î?Î>q¦±Öž}ø‘ÏÿÔMY,Ï€n©‘cÀû.û†«tU+7rÄýEA¡ºïûßù®û~ï·‡ÕÕU†Ë‡)mÁÊò2 ²Ð:i~m ÞéÐ ÖˆN….JðÁ§qäZçý ÆDL{â»óMq‘ˆ"ªZ’BT7O„@êjlíÄѺ†Ö‚÷ÉÜm=®ÉcÒ$&ío“F7.&0•èœû3”13ôî ⌂JR÷ P«™KP•uUP”_–”eI¨-¨”9y2ò!ý !¼à§ÉC]¼óÉ—Î4R„Ý»HïCBIÂ'Föé"9Ó¤¢¤©“€ Ò57åêÃ\| ¡‹úg‹nÏ8´xíWÈæ}.í)²ï½Gd/ˆ!˜SL¥êU¬¬âð¡#TEÉÙsgåÔ‰ÇÜöîθ_Wï¹ ËäÓ-}àsï 1ÿò_ÎGŽHZéºL£™âXkd˜‚W½âå¼î›ßăŸøcNŸ|˜…ŒÎÛ«SjÐ97ÕäÆ80ÆaŒÆz‹W£<ÑXˆÊ'”Ù4Þ+ •üçY)Mâ Ád˜k° FãÞ !‚ަ»=ˆÌŠ`tŽÊk- €#(0 œ ñiÛ®×1UgŠî—sä!NSz©0F¥ÐVS˜‚”eH×®T*«.¼AR/Ëu)„ÄÑK2±cÀMgà§2Ù·I=ø¬}cö·C§U}Š äNǵsŠ3t¯³l…䯦<• ½™â9¹¢!㬫qž¾Æ‘<[‚˜¬bvÂtŒwŠ̺0u¡Y\ZâÈ¡Ã,,ØÚÚåìÙ³a}}c»ß«çë?øÀ3\"7…n‰ø§øwF“^o›ä‚v~÷eß]ÖjTª]×E_¥±Ê µáÛÞüN}ýkl¬_âìÙä ”9 ^œ¦mãFŠçZ‚èž¾ž‚Gj”öho’Ù¬tÊŸw8îùÿ2#é€ ‰Y 7O@¢æ?È©±d­(c0’X©ÄÔ:ù¦ÅÝõÀ´˜§û/H¼²°núwÊFçêøS««¾Á’I1¼¬Ëü 5{Ms‚tÿºÝü‚Æhu‹ñr ŒÎ]LùÊ®ÃqZ°0ŸÃœcëç³×ÜÔræ!JȈ$´¾$úd!„T³`¬¦¿0`yù+‡!(.^8Ož<51ÖìŠÄŸ~Ò›÷,ÑMÿð'å]“Ñäƒ×ü0ÍI+˜4 ÍvCã< ý‹»»Dmmó’»î¤ßïSUd<: «t€ÿÿÙ{Ó(»®ëLìÛçÜá½W…ª -S¢@É–e§fÚI»ãîeSíd¥“±Õ+‰W–ӱȱړÄöÐJ¬hÅQ·e†¤lY–ì6)k05Q°LE’-‰¬™@R$C €¨jzýgʽϹ÷ „Â@›«X…7ÞûÞ=ûìáû¾­3`zzÿÙñ“Øý·ŸÆÂÂ<¶lÝÆsã'y´·µDJÕÈrÚæ Ê€H¥®‘à•c¥6硬‡×Þ+(AÄ‘EŠø‹ÛTä@!*¯ˆN±í$›ÏM!(&.çR …w<üìŠOZü‚#Œ°Þø€‡;"ܧ§0þJ ð ë?f2°#p–çóo-f‰’p‹2³¡.7ÊÅ>9”öû„Öãâ¹:A+†Hk–‚nÂî{¤ßMø 3i&¸” xÉ÷ãîïDžž£–õæ‘l@–ç˜Þ´×\³ ²ƒùÓ'pøðáz0\9SïßsQá¾Ogê~ã ¿ÿó¦vwF9®sÙcïÇ÷Þ‡Ó§ç¡u޲,Q”y®1ŽpÍ\ƒ‰‰ŒqX^©1õ11Ñ`' 3G3Âÿèâ±Çöáøáƒ8|xÝî$Ê¢D§S¤že¦¶ÈtÅmÁˆ’c{:Ô¤!çÁ³ –§Þú8ý&´5 œäç •¶Q2âH+Œ-ü0&® Îú IDATi…GBú$'ŽÀ˜“ K¿“s"-G$ŸTh´©uÈs:ÃXA+ÂôÔ4®¹v¦7Mb0臹CGý©…£nÙýü£}k÷3}ïÓ6̼î×ÞºÝZs§ËuS|Ycy ýÕÕÅÅååÝËËË_Ô*ÛS–åÜÿï¯ÍµûÐ#Çn2ÖÁXs£óö¥Á†ñ7=1Ëà —û˜Þ2ƒš T®ñOÿñOa×S'Q 8qüò\£(fA`­EU  %ÓÈ2mrÍì@¯•D $PSöòŠ<¬r Œ[e¼šó rÅçá‰[ltZøÀ÷çÚl¾ØšlgEñ}!Ñ¿E€ç´a¬›’ÿØ;­ûž½”’ÝW*ÒH”g(œËÇ×8ï!»¼OÎ(DlÙYy`¨‡mI—·%Ý×kv¶´Y9Á@@§S`zj[·mE¯×Áâ™3áÀý¶ –òn÷u>ö­Ë&ô¶!ൿò{79çn¸jÚ8xð$^ö²kç&&¦wÑîó}¯WýôïOI¹åÏþüžíCc^c¬û¥£O<¹ý®Ù†#[f±´0'ž8‚n·‹n§ ­¹^×J)ä¹fà†Q0!Ï3x¯aœG¡9‚qÞq‘Íy8ka2…2ÒédQ6z÷ă¤òäICàUÜ7›¼U?‡P@Ëz ØñN‘ÿ»–üí}`m ¹Þ[u²öïsëõ9h€¢6 œÄ3h%¤T íWžz¬m9ÙieŸõpåc­"®Èµ»|s¼¤h݉yqÁ·Ov,´y?°&j„Uâ/) G(6€œäüÞs4€ë›0»u+6o™A]×áàÜ!?êä èö¾¶÷Ñû/šÈÇs± Ñtν5„„à‡Žàe/»öv"ºa#ÿZûå×þ˹ß}ýÿrË›Þø¿ß˜ =÷Š—ÿ0~è¯@u'NœÀr¿ŸBO€Ó#sù7· c„σ‹e­0Õru:¬sa¦]%¶Ü¬OZjMùö#ŸÞâuÉõ=N]2Í’"h‡ç¤TH(*)b9Œôz¦w=û | (xqb\DPˆzjk‹>pé¡)¶sèlÓ™·víVŽ$âJ ½Ög¥îг»h[±šp82’{S=·%s"'ãåb”â<ƒ‰"0¢ؤ H£Óëbff3¶m›…Ò 'ŽŸÓ3e'çÝß¡®k–q’( ¶ybKÍ rÌ;îWçc*, Š/½´Ø¤U‰"¢3ŒE'D'€õ}ÀXÄ.Å*ÞåYðI(øOE±Ö¡Ó€c&{z­±×Ëû›¿cëm­)~ÿ¤Ô@Ž„BˆÎGœZrl²°¯‘¦'Òã1AçHÀ¥Üß;/<ãõ=d;Òªµòå˜×ÍO(¹Ã³>˜ˆëH…G—¢[‘ÞÁ:ç­à*|ST”7˜èavËlžÙ‚Úš;ìŸ:ñä¨×™x葽_¿dL¿gcá~¦©îXoWþ×_úW¿òÒë¦ÿj#ðûµ?{ïÿs nX8³€Áh„´`&ì}`Æ—0ÀbŽg°V[DRKŠ€VUšdLYZC­Ïbm8›úÏ­Ôà,kmˆñ·’¢ŸÎ×%$ ®2Ç3Að.¬›«?—A>8Àalwl ”®œT^ˆ»¾?ÂðóžïŒ©A`¦ŸO­ÉøA߃Ú(»÷Þ÷/f™ÞGÄRUî I<Ä{‡*;äË7ÞF0SÚûÄôMŸ>Zì+Gøj c„ë>4•òø Ž­3’TCÞ„/=–³j"蜠‰R}híÊëþ”Š»èÓÔó%ä—gÀÉ®‰“AéÈ]ñÇÇmìlœ· ¹Àrn°ãåÕ˜‹§¸ƒ¨I]¢ÇiŸW<®gkíÓ»~jOrÐÙˆðsÉ™E|„ÖÀD¯‡ÙÙ­Ø2;ë]8|ø0?~ÜLNN~ðÁ/ßòìæÒÙùF3{Ï'ŽÍí¾ÿ럽ìò¿ÿÒ'wp×êò ÎÌÏcu0·¸y¤¸©™'ÎŒ4Vt ޤi‹UjÛˆ=0A¿’š( DÞ¸oååÂDk9‚ÖJÃr|ój±ç@ LªþŠZe®øÈx[ˆKí‘*ÜÏz¬·Ìç™1¥X%Hk©®·k éM€=ÜîCÓz Íòn€bì IÇe¬¯çSÆâ3‹¦¤ežƪ"’…ÔÀzqUHQZó'ʯu‚þó­û]¢™)EÓÓ˜Ù2—XX˜û÷ï7¦Ux„þÑÎËÄŽH-ºÚ\¶'½yË–›¡hñÉ'bue…‰ øÀüñvøoŒóumà#v7N¸e@šËI;|©Åü—{É>qÒ0¶@ëòlµ Û›YòÈb(,…G¥‰JJ4E,¤q9±Vͽv'ÿò€Pü»u[¼Ý­)°­k1’±M4“Î.'|„OÐÝXD !ð ’VÔ¼[®qA) xIµð̧Ÿæâ^ƒ†t’Þy’γýLêpÞÏÇœ+B¯7‰™ÙYÌLoÆ`0ľG Ë+§3›·Þ±ç/]R‘çbçåb8yìØá;¾ú•OÍmÄ]ûÔ½ï_Ìó|‡1O;Š¥Õ¾\ð¢7Þµ³Þ •Õ¥ËGH«cÞy;ÄŽ—#o˜*U·®!$,~hjiwluÚuºvΚ}€ŽÕpâXCÅEÂs.Œ0Þ+'qÎ$½~ÚᬗBêŠpÿ_`¸RˆŒp‹¾i.úØhÍ$Á54gOˆºVfŠ<$E:—®b+Njy´võßGÚ´ƒa›@?¶,×xPIÑíbzf×lÝŠàž<öŽ=y¬žÚ´åÌ·¿sß-ëÑåiç—n$¢EkÌeú¯µ/Þ÷‰]D´ëÌéy,,, ªìP ßÜ‹ª20µc%gR4áºóžÅ)„ÿM!´¢‰ÄYxI’½õÍE Œµ£»s­«Ý+ÅÅ9…H(.&-%y’´PZ+dšÀz·KÔÏ›Ñ1¬3®»}ܼԛjÂûHÕ¤è(y»ÈÑçÁÙá:Ïs$ù;¹:5¾ Ï~âÚ¤aÛ‚ò²œ—M­^ç\*¶ù ¼ÙdY^w¶ÍÎ"ï(,-®†}{5®6«ô< ý£_@ê*­îúò—>yÙaœ×³é©Í;jñè‘9,//3Ñà©."ø姸3`1é %(B–^ C¼@ZÕj°fˆ®(´0­¿þiñ¥"Îý¾ø>±ÈE¥)µ V§Âƒ‡b¦3“'hññí”þŽ?éà4x^ZÒPÓɈ£D‡ÑÎe8·˜`ï€o¸yðc';vQ*©þ¯u çÊPا´ë#㘆Í%Ä'þë"Ï¿Aüñqós÷ФÑëu±uëfLÍÌb4rØ÷Ø#aeu±?½yó¿õí/ì^ç.k;/ µÞ>91±´Qs¡íÞ{ß·¨µÚi­Å±'a0€¤Ìùž…3FX„•ä€ÍEíàE*šáÁ ``ŽRIG0>Öû!'v¬Ö–tí0ntqÑk­Z¡24«éD{Új? ÎiícðŠ@›aÜAÖ B‚kZ~ ÀmA² u Vðù|ǽžGhà¾*ê4âçqÖ‘«ñÏ7D‡$G$ùD_’ývÜùa}¿&zaD()¢,1;;‹­Û¶‚päèìØ‘ÊTfiœ÷FÛy9ïýMJ«—nÔÁ\ »ï¾{n‡Âîù§Žc~~u]IÀQ€1ÆY‰¼óÜûO¸ðMÕG»OEk¦äÆÒCpƒœgê œK2Tí( õÃ×/ÿ›sa"ÅÊH*kö8 ¼8ˆ«ô!*þŠPxõw.;‹j‹¥Á97±@(´†Ö@’Лà /jŸ±@J(^|±ý'»|ƒŠlòõˆ!B}IÉq¨ä ×{|câÄ9‘LCÌU$¿a<ˆìö"Ma¿N€q;÷SÓ˜™žAÑé`yu9ìlŸ«FÕê¶k®½ùþo}þy¯µór²slß#¹ˆ691¹D‹GÍa¥?h*ÖÞ ÄÊÀÇ8ô¡’ #†"iåDÖùDAUR4k×Ö¼oà³!°¨VZ1bn­þ´4|Ò“ìôŠ:ÓR ð¼ï¤€Ä–$Yw±Ðüçû“ÊuüĈœx^¢ô_³ß: Šè ™ÞF ¨(žKÓ åW§»&úo,þ”¸Òàšt{22ýJÆ I)¬Æ >$¿¼•fá×0þâ¹p6A€RèvsÌlÆÌÌ \eÃÜaiii8;»õ+_ÿÆß^–L¿gcç$¨›Îû(.²}êÞ÷ÏiEw3‘£sèÜÚƒçðß:ë¤.`ZÐah-<œs¤Ô¯"pq,‰,µÏ[»¾{"L*2°‡ÈCe Ziv JA)@‘µ‚jKüòZ"‘¯íà‰ ?ªÕPmú"ëÂH½<Ž×M¬ô;ØXô¢Ô+¨è\â «6ˆ¿UüO…Õä¢&@6$b dì\ÇMŽ&âoŸœ7iµ}}lSzòLcjzÓ3Ó R8ñÔIš;XYWÏãyXøkÛyFf¾áwÞ~ãÏE³Ï}îã·`Ïüü),.á…íâ…a¤ `dT{¾œs±šÌh1µ™‚ÍÅKùu'‘p-RIÜù[Äšµ°}.ÄÇ‚œ•« …?^ $S~˜·ß¬|Ü×íj¤ 3‰üƶeg_"ɵøF·ÏKß-H!#x0þ_×x“û§Â”asÆ©û×Zè±°6máô ­Ô¢9Øæ³ˆ€‡„øˆö‹ióûãwœe½IÌÌLcbb«ËËØÿØ^; W¶m»ö·¾öõÏ>/CÿhçWŽóÀnڠ㹨ÖíövçqhîV}Äá¡ r©(çásœÿ#íb^÷6ž@ ‚|Áú´š˜Ÿ¥ÄëZª@…,SÐãÿ½´è…xøßšZÂúÍ¢õÜAk %—ïžu¥¸x\|ÁqR!i¿œO$S…´Öž¨O@ùp³~3}Æc÷ÅD ÌXóÙEudçBš.¼ƒ±ÎȼÞƒ‰O‘w°yólÙ²Á{>rØ/œ^lÛzí#_ýê§Ÿ·¡´óO<@ ŸÙˆƒ¹Øö©{ß¿‡@;‡ƒ>ž8rUUCAÉŒ8Ù) wØ HAÐq{ˆ'Òr¯ßØ8¸2nÝ‘¹ÇÒ\ÄBI:ú\À”Ù®ûÍ4Û VÈÊ·Z„PÂðkžÕ,Šví\"!¬Ü:("dPü€o9-‰|"ý™ïKt‰Ž<>u¬ì@Ђ|_ àE/uK1‡ì|.1¶Ì63.­Œ§1fŠBÒÙˆÇÀõ uÖãÇ^C5Ç‹8¡Üý6&ÕuXß¿y^–eèu{Ø<³“=Œ†ÃpèÐSUÕk¯ù?úÒ—ï{æòò·óŽ|ppÖÎüæoýþMp<—Ä>÷¹]‹>89Ì©!•&¿ðüºšaEÒN!à ï¤ÿÝZ੧ͲQ€t›­µ0SÉg9´eí*ð„¤ày¿çÅÂoT³ôŸÎÖŤMVKî캌”ƒ÷ X/l.RGƒ¤hÚbðÅs_SÈ!üÔšû1®VÔ’&h½·tDö›"»Ä×ð~¬øÇE\Bž˜šžÂÌìfXçÂÁCsá©§NÕ¦ªùâ—þæ²G¾>[;ß6àž(êþåFÔÅ´í?ü“Û½¯nܳç›XY^ÂS'NðJ7.i¬ç:€³pUÔ h„?¸nàä¢"bôŸV™Lâ…[Q }EÓG>s4ÁÇ×^ÂŒŠS,¦yR’R€Š;µ"(ŵ€¸ð4à¤ø# +pŒ~R¤ÐÚE…‡'ï°ör‰\:3.6øÎ>‘6dº9¹xSsLëÅ* jü8ÚoÁ_ã ¼µ‰™zÄ1^‘Ç’¥÷€ÆÄä$¶ÌÎ"× ó8÷gC€ ä“Ô`êD¯ ¨¾Ð:îøºŒ ¢Z*p®9¶¦Ê;1‚iÿ ´–ûZDúS“D\F¢ûúˆêd5h¾»±Z”96ÏLcÓ¦MðÎâñ}eyõ_üâ{þös}Þˆ|<;/ðÑ¿z÷¢&ìѹ‚Î4t©Ñíûý·¿÷¦Æ_zëu;oíõ:3“ÓS˜ššBYtÑ-{Pù¾ùÍûP*Ì™Ã`8L}ä†(%Ä"¦¼’HÁØ'0‘F+-zž¾µ36?ízãèÛe-ùÃaÒš ²J¤/)‰„xÒ¨†dÈiÔ´Ó‰gÕ„’¯gÅ€¸ùr°ìõD½„ôJü•kot >!¸fé·ÚúAo’;k-ü1ÜÂÚAºCR!{‘ðŽ-?+“|Stp àr@^˜Ü´ [f7C8zô˜?uâä°ªª•ðN“Æï )Öï¸öA .jNRv©gè¦0FµŽ,¿Û(KŸf9È Ùý­µ‰óŸ"¶àAÐëö033ƒnoË+«áàáÇêa5X¼þ%Ûw|ö³y^Ã}ŸÎÎÛ¨ vY†LçÈŠ yQ ìfox÷Ÿ}ü¿ÝˆÜh{Ë[ßyc·[ÜY”:.&&&°yz ““èv'Ðét±íE?ŠƒY4¦^Q™nÙE¯×ÃÔ¦M˜˜˜Ä¦‰)LOO£({è–%B0;¿ùÍ¿ß9 pèàAÔÆiA" jméhˆf€O` &Um&×mž+è ÉðkÆÝ]nñ­H@»`KxžoÊ•ñ¶Ù„ÎE:…îñ6Žš±",'®  Á¿ãíÁ[>¨³qR+{In"´òøqÉðÄ„¤,)é\P,f*J!MŠIT@C°Šœ EMð,'æD†ÍKî5ΑþŠã¼9]É´ÂÔ¦IlÙ<ƒ"/0bÁòÉÊÔõ<]Á¡´óv°ÿñ}ï+²n k,:²StòükŸú»û¯Ýˆ÷8_ûƒ?¼óƲÓ9Ô-'¶E²[bbb˜Ú4‰ÉM›Pöº˜ØÔѹ=»ܾ¸xüv¥ôî'Ža~~ÎIg@æÄ{ËD¡ N x§²Å:œäœqUJ «‹c"•—ªØgÛø¾MJÁ{$ôŸV¬fèHnˆ¼ÍbmÑŸ+IøMñoæ4·´Wì´AâÚ>¢Ýl|îÊ#§-Jä­ÚC@RÒD¡ÝLd,v ÆmmbüÙV x‡Œ€¢ÛÅÔÔ4z½ƒ>ö=úˆ¯ëzéúëox㽟þàúGÛà}¸+/òÅ\<Š<‡Î5ÊNq]™«Ç¿rÿcÿl#Þçûµwÿé‡ßP–å}eYÌtº¾ IDATвƒ^we§ƒ²[¢×ëa²×C¯ÓÃ×¾ü…9¨éWÇç–b‘ÆþÇG¿?HÀ–Ȉí%+}ü¨%‡oF²‰sÒR¨k0¶¼>ZÓFoâ<¸ È7Š“PB–¾~Ìû!¯Ÿk+ì‘Z›£³ñjß&‹KEç@©Dnb×2–(t‚7Çh‹°æ¹Í?cSúþëø¿+¥çó-¼xÃ8t†½ý‘øŽh¿4˜@^”˜Þ4…-[¶€áñýÜj¥oùúßÜûþç=ÓïÙØ†8€»?ðG‹<øÀ]y®±yzÃáEV"Ï2Y¹©“•_zdßñ?؈÷z.v×_~ê¦;ïÚu_^·õº™²S¢×)1Ù+Ñ)sLNôØ”tº%¾úÕÝ‹/ºîů†_Jžÿ£yï€#Saîð\k¼X¡Ú2@ÈyÏmAé/³¿Â ˜¿wkjõÔCk}¶#òkZv©. !æÉƒeÁ(UüZzë Ô¿F„…Bd«o‰lÜä®Á9.“è›âÇ›Sk0F kŸ¨R°¡bSƒ› ¢l,ge˜Ï²ÒÈçk×\¬‹³„Ì•„\|"ï ¡×íbvv3:eŽ……S8rô°­ŒY¸á†º"{þëÙ†8>Ü‘9ò5-Á6M ýpvR9I!„ôÁ‹´— ð´F°¼ØÛZ9Ü):˜œšF¯7…Ѩ {÷îuÖØþ /{ùíÚu×úGË6ê…Þ÷·Î•EyûOÿÌO¿!Ó –û˜œ˜”T¡SèkËNg®_…_ž(é?nÔ{쟟™ìmºÉ;ÿsPx Ãå2xÇ+ÆÞ‰söú,ÀX‡% çpï½³¸eËÖW}ùïwìA;|ÀwØÙ-[ÐËtâ°#p‰=˜ç1P ГÆOIJLZB@Ès}ÀÐH ÿ ;tÔÑ_¾C|FÐ^Á;‚V„@ Ž4´òp¤$IÏ—0Àù©yo8©È @jp”®~ÅÀè@" €A ‹ƒ$xˆJŒ+^ÎGSÒíøšiË#7ó$MñQŸÑ.ÀšÈñ0Oõ1÷5Φ×Éó½ÉIÌnžE–Ÿ ó§†Öú?ñ‰¿¸b˜~ÏÆ6,°syqe%/ LLôP–VÁ±VDÝnC0öŸX¼ãûy¯¿û·oúð‡¿ð†þÕgîSDgLpŸP¹z ”Bžk”E†¢ÓAÑé S”è%ÊN‰¢(¸e) ˜}ìžÅ‰É™§]üð‘¿{|ØÙ_]ÁÜ‘9Ë:¼³D!“„Ø)ćw~kYn*j×+’š¼â‘å±Áõðâ¿£sùy)¥˜C{ÿD%H›0i²b°"ˆ´xl¿„TpI˜µÞ‡s†x<ÖJàãý`Ç‘ÖX[€Ã)¦ˆGÉù$p’V ¸ß7xH2îø¢$Xl¡Æ…ïƒ[ôÞÛÄd7¶Ýn‰­[·¢Û+°0¿|Ÿ !œúá—¿pBÿhÀŸÿéÛí7nyËõÛÿëÛ´Ê÷2t;Lm¡6ñcbeYYžáåN÷·_þ7 ‹Kü_ãîïLv«™©)ôÊP@FjûÐVÛG«ÕK—–o\ZÜXVyç0Î*”àJz ¥5ry3g¸ o¼‚x’Søø=[œ˜œxÕ'wýų‚y*E·ôKGŽÙ~Ͷášm›¼|k=”âÝßZƒ<Ïä"äü;x œóÈ2 R`•!\;“b}[¯?( V„ؤc'R¥D)˜Aegðµ‘d+O_ $ ^d “Y-XI:C8¾?I”ßZö!¾fûó‹Jbü|M<0Ò™¦Ä(@r¶€sMO?ª2Y~-¼³¢„[Dh* ÈËÓÓ3˜žž†±.<òð#Þ?ü¡—ýð;?ü‘÷Ì=›ëàJ² uð®?ºåöü“?ñ¯_rýõ¯PZ!ÏJtÊ[4.¥À[ÀƒÚ¥®{[©2t4!Ë@!#pËsëK+ ­‚,,^»¦ЏÏ¥d’,ïŒJ§L@PAyÜóÉ{˲ûª~ø]Ïãý¡½kññ×wî{lߣ˜žþÏ¡»JzË*)Íd™†µJ1OÂ/^J©É´_4¼ ÐP›K!rƒ ã)ZC9 /y¿r²» VËk(­¦¡ ­I)bVàå»Iwpÿ^9 c<ƸÊ[?"ÀA|”Pwh…oÍ5lt…ZN$Q‹åß!ˆ‹€dÖB]†ýJ€y6¦eÎÃú€,˱ir›§§¡IãàÜ~,œ^¨Œ7‡>ü‘÷¼ BÿhšDÛóÀC¿pøÈôÊE‘!× y^ /4‡Íà Àx/›=¿V :<È)@ó.gåê ñU”ÆR•ç êÈsh!×\ˆ,r"SÈt.Ò\„ùS§ðÙÏ~~Oobò†ç²ø£}ðƒ¼·/-ÁÑ£G9¼T‘ (QP4‚N$„fÀÀK¸=†µm(qgM˜yC÷ñ¢f€Tý¥ðGÄ’Z£Ž“·¢Tzonƒâ¥R24=ATƒ×@q,N<’kOºÈ×ç#—iéé$µ…؆L·G"К+³p’#ÀlïaDÁÙ»&Km?o¡ètKLMÏ Û›ÄéÅSá±}ûŒs®ÿ#?òÊ\èí‚8€ÛÞñíÙûУ;öï?ˆ"Ï‘å9TÆí$­ ê\q1L‘‚Ê2*¡uóô"C¦dXÒ Zóî§r‚Ö|žtò…*‘—%ò"G^jdYŽ,ÓÈ2 ¥4eøòW¾‡Ý¿»(‹Wýù{ÿý÷_é%ì$­8ˆÕþ ‘NœÌ—3ImƶœI‹7L9! e´†àÒ¶‘ŠèkÊïa¼2N¤›Š¾ì¬D$˜þ8jKÆzÉ %Xê ñ\›Þ•ɯ)"†H8t¢9ø°ÎcÅï´Ð}ë³ä÷Øk!¥Æ8˜ÚˆFCÃñ·Ö5ù?€"Ï19± [¶lA0ûÝçªÁh ò¡½ûŠdú=» þà?üÎ]{{ü®}?Ž¢ÈQæ9Ke«Ö.ñ®]zE‰¼KÈs [ôkÎN”æ|^“B™åÈ‹²2C·ÓCÑë¢,»È´BÙËQè:g^Bž)(•#ŽÓúúýßEQä·¿ãßÿö«î¸íÍçÕæùÀûß¹„ïL„CâÌ€o,¼u© ƒ\dbu`•Šn4¶í­¹žij&÷ei! mW˜uLÿ—¶ŸjЀ¤$Üæ5/ZS*"L!†‚wÐÀx`,çOø&b‰ŽKµ£–øþÒ X+Rê¥>! ~¼MÊnÃÙ8ÃÑÀEÑçQ×u‚ÿ¦áž. W½‰¶l™aîø±pâä‰ãþÏÝòÌŸô•kÌÀÛÞò;Ûøæ½{÷%-û¬µ“äòœÐétë ½Ý^Ô Ð] è:t P®á5!ïº:GÙÕè–%º½^N¢TȳJgÜfÓßyà{¸ÿÛ.ï^ý¦ß{ÝÍunï߻Ԯ§NÎãØ“ÇD \€•q¨½…5F”ƒXb܉Jn¢Œ¥ Ò:a|H‹_&µa´"µéô Ù™Ó€Mç‚H_¶’‰E-).ÞЃϩ½M‹Ogg³»×Ž £µa|ÑÇ›céÒ7lƒµ‘OëWëÜ›Ï-Ó±¥òo ¬w¨a\†eQ(¢Sbfj=ô—û8tà€Að«?òÊW¼éì#|aÙuðoÿÍknŸ;öä«?û·÷-î?pk¯¥"ã¾lÑ)‘ R¯S(ID& Q"tó9èõrô:9вƒBçè2•C+€»ß÷þ?Þý _ñoÜÀëv¼zWÞéÞpìèS»vùa?¹’îË(KB·änA–ktZu+) ”Ô¡,JçÐY‚ ³’«éšóýû¾ø5|ùËß@mÍncÌ«~õWþǯÿÕ_¸ È®;ïüÃE¥èfSUØà ¬€Vâ‰``Z¸€¶häh ™ö£¥ä"CGÍJØ÷¸¸ã}Y–‰>`“(M\_ŽˆÖ,HBʃO¿QºéýóŽÌ{tð!=‚8Ù÷3J`Á9 ΆCrYðŠ4¼iÜ·ç¾Üùݤۖ Ô’^1C2ÒÛ‹zTI¾/Ž7Â~}`²×ä²2ÃÉã'ý‰SÇ>øC¯|åíÜ€Kàyot®é0ÏêÉëÅxÏ`_ÿö¾›º½î[5e7UÆbzSÛ¯ŸEm(  ^ ÑâÑ -`*À‡ºaЯ0®`yu„þ`ó§Îàĉ“Ð:ßgj篾îvß'öí{íïܧ€›þÑOü#¼äÅ×Wß‹¢@YètreE§@'Ï‘çò<ã´HgÈò Üq–Uj¸“æ5pea‚«÷<ÔS¡({ ãL-ú޹ ÆX˜º†µ£ÚB´"q,±îæraBçzE²,Ñé”ÈóLÆ’{m@ \˜t rjÒç(À¹€HôGŽSKi(²õ¼ó˜:Vó=Œ©QÕu5B¿_a8`0ƒÕþ*ýªj„ªªàd kQ”زy ¶lÝŒªªýw¾ówzaá€_üê×>}Ñ® aç³nÛ¶á8€g²ò?²ÀîG÷Øn€×Ÿ<¹ðó‡æŽnŒ*dpýu×áE×_‹ÙMEzŽ\“X\XÄ¡£GðèÞ9¬œ93KgPW5z½¹²Sìšèõîxý¯ÿÏsûœÑßÝ÷è¾™­³³èv»pšõ¸. ‘çp¬r‚pR´î? qG+Î]ƒ—a—²×¶ „qJ®3àZ¼ !Õ”d AZ„+xФëÏ팳†ø5%”G«J/»}@@–±¬CŠEEC÷ÇR^Òáçï’#•–H>ÇqÂp3k $œ¿©mRbrÞa8‰ ‹Ú/§Y¦Ðëu19= ïC8|ø°_ZZ\ ðßüÚ×>»û<¿ò+Æ.ºˆöÊù97¸ù ÷=pc–ç7ç~æÄñùígNŸ¹Q•%‚7j@ªzgVWpð»;ÝÎVôón¹ûm;sîRüùŸýÁÜ/ÿòïîG·=ºï1üÃÿô@9… <9Ôd‘eˆ ”B¦È€Œ«&-’Ø’S’w{œÕ‡ òBH‹Ò‰”?‰´idäQó¶ÏãÅ€ôºYÎCQ£ñ Q¤.€À(@DgB°Ö1Æ"‚¼b{“C ¨ÐÌàã‘ò@+ztkÔF Ú øÇKZÅé€tLÍ­Vøo¹PÒÜóŸ™FžeX85N²Âq­Õ ¶ç¿ž]ôà¹Ø—¾üÈvkFÛ4Œíù?û“—5Këÿø•7ÞGŠnú©òS˜ÝŒ,Ë 5¡Ì;(»ºÝEQ"Ï5ºÒÎäÚ§‘pǦ°&$€XIœùí„èb…±`Z¬­™X[T¦brŒd´'*=-¼./P,ÏP–9:E^ ˸X$˜² u ‚Tê½Läâè4Æí{„@ Pq­¡=®ËZÏ;½³pÆ¡2ÎŒF#TµAuˆÁ`UUa8`0a8¢ªFj8cPäffg0;»®®Ã=lNŸ>uÒ[û›LôžÇ)Às±Ÿþg?6`îÆs0ºYA}÷{?ŒŸú/ TlePkæ)m¡/$o=¼ÐZÒ€î¿0Óî,îmÛÆïÓ ã1â©XH•)øš ªÞǪâ Ag¼ø¢¦Gæ–¦sM¥É÷øU@Mè›X‚k‚XŒZ?>Ê É!5·Ã}ˆ‚ DáÉ3X>xv’Æ´Ú}ÔõP8Œ“Py†Ééi¨B¡ß„……ù¡qö˜ÒÙ».Äwz¥ÙUp-Àß R‹ûöîE¿¿Êwã` Y"a(ÊŒÛ4k‹b$‹'ÓŠó}ÅvïÖ¾S{ ˜è„DZZApÛb \ÜcŒBG d_–º„sŒ<Š ?–øš´$ÖÄñH-B+•Iñv'’^@œ¤ Ô•Cm,¬±U5¼¨k1ÕuÕþ¼…õJ)fúõJh°°pºôû§úëÏ|ößÛà¯òŠ´«àÛ·ß²ˆ€µ±Ø·ï@B½9X°ŒF¾ÕØ;@„¶†mÍ>BÜ.õdWöã¸Á8¶ž@Aöof ‰³šP= Íýs²ßó›KʰFLô,Dš8( ‘é葆|¥ŸVzLNÄ8ï8B&2 ‡C ‡êºF]P×#..2v:tË.i,ŸYµKK++ا ÛØoñʵ«à"Øw¼e—v}÷ÃïÛ}~ÛUp‘L)º9„°øÈ÷eðó2YÈJNËW°F¤ÄDëhank0M€O“ƒˆàƒc}ñMUUc4èËçÀŽÀû€,/ÐëöP” uËËKCkGOä:ûø'ÿæý^¨ïîJµ«à"v(…Ňy®vÖ#Xæ³;S˾½±¦bå`+„Ïr1Ÿwn'SpxþwäADQϺ®1ô1S-`0ÈâwPZ£(:èv:@p~uiɇÃSøÆÇ?qçû.Î7xeÙUp‘í¶ÛÞ<ç=î¬öñÐ#"(‚“é6Ö£Q [X[ÁXÎ…½÷¨k ã‚°îx²PÒȺ,&y/`•vf'ÌBc÷CšAyìpàˆÓß*Äq.R{p ˆE¿HzŠ¡½“?M÷ ÞI¾ï¹tÞÝ™Ó_×Ã!Ëz ŒFjc`-§=ÝN‰^…¢0]eeјzººø¿O»ê.ÝvÛ›n°çĉãXZZ„÷Ä“‚…€1Ák¢H†ÈŽ“"ä*g¿o¤4cþO„ØÑ _KÅ/'ÍÑ)Áè³¥"]pˆ@ž "ÒPfÆÝÞ{hÞ[À;.zA;Ëu 4ƒM℞ØôŽ#•ªªQ×uU£®mÚù‡CnùYË À"%ò\Áx„Õ•¥ae̱Lçûø=qÿ…þήT»ê.™ùÎY<øàÃðÞƒ+ïÆ8Xoa*¶4ÖÀÖÜ#÷ÆpyxE ¢¬7Å=Z ¶ ˆ£eÂ9dgBWé}h ÅQ DÉ÷ ù8ÙÈ"·í‚@œçŽEh!}P$Ñ?îCmÐŒàœÃh4Âp4°ªXÑÇ1ègXUÜ÷w>Lt{(Фµ_ZY®ûƒÁBá;ùè{D_ãóÜ®:€Kd·Ýö–=·K+K8p`.ƒÉB0Ì4.XT•‡ñuU!­¥ÒÞê®eˆ»>€@š‚Ër1nˆÑ€HdÝHáõI8¢‚n0ýPžÁHj`aešœ˜Ày)(ͨ”Nt3¯/„ÔÚ3ÆaX±¬×Êʈ?£Ƴ¼xžèö:ȳ2ŒC7X¬Xëöû€\Ð/é`WÀ%´Ûo{ó- Ì8xu5‡¼Ì4<ñVþ¶Öøë,óø”âE.Ü þ‡ÿGä4 ._ðþŠ2 çÊéÝ{/ >°ª¯/.Q…Š.ï¸èò¢/„`D’ó3ø1ì7¼Øu¨MdôÕ¨ª £áÃQ…ª³Ðd­ IDATZÅ`0”4È"Ó„²ÌQä¼µX^^ «úh€úÿ>úÑ÷~éb~_W¢]u—ØtÀŽà-öìyˆlàœßT•ÁÈ0¦ªj8rsâ,C€yÀ.´Eܰ³Âðóê§Y¿$cÁÒd YÇ!Àƒà]H€[}>0'ß8+sAˆóåeww<DI7 J°ÄD > ˆ¨¿85™gTÃ|WW¨CT¢øc­ñ,ž’ºÝ.ˆƒþª ú§ƒ7ßýðGÞ}Uäc쪸Äö‡·¾i7Ý~zaGŽ=X/.³­µ€u0Æ£¶•¤#QÞu\¼³! °¡!…àA!" !X(Åtß!0@žÅC”f R5?$91o9·7†+ù §^˜}2á¿Òuð:MDrÎch,ªºÂh4bŠo„û¶pÿä¼ÌÐ-J”ª‹Á``V‡ýUcìa­²«âždWÀe`ÖùÖ‡¹½ìÅÈVð–§ýy`B3÷Þ;n‹YÃbáDÄ*¾–?9=çBžF §åo™;ÕýNì=¼÷¨‡Æ¦æí=G,;îw" AäË9Æ÷  ÎÙ#ч…ƒAîâãø/I7‚¤¡ ‡ÀãɜȈ›‘Ã@vü••ƒ†Ã>F£ Ã!ýžŸXäyk¿Úï›åþ`Ñ[¿/ϲ«»ÿ°«à2³wÜú{» °ûØÑ'0ê)Ѽ÷<Ëy˜Ú£6ˉ¹ÁÔÎAkBí<Ýð@–‘Hnq³Þ{Àðäéû·9ÄàzOÒÒ>´†‘β)…?³@Ä¢¦Îr;ÒZ/‘ŠOÓ{뺘﫫C ‡5úýUT£êQà8ú({=ä“]ÔÆ„Ñh8 ¶: …¿ÿïúî%ø:®x»ê.C#E; hqàÈœGœ¨ârQÐÕµ«ak‹€ŽÊ` uãáœB Î1(Ëtš5B„¼Ð†Y™ ­çœMÑC0N,œ#Éÿw)L͂퀜cšo]W²øk)ö Ú¯æ IÆY8dYŽ<×(?X^©Gõè)‡ð•»ï~ÏÝ—ø+¹bíª¸ íïø½9‡°suu{÷íãb ˜ã‚AÙ®*ƒÁ ‚'–„¨#3ƒ@|ú±A'=?öÁa½Žê ÁIÏŒY·ÁÀ°Á' ÷,>‰x§Çpd0 1Œ°ººŠápˆÁ Â`СòY®QNL¢Ì²°º:ðÃápÙ[̲ü*Ü÷ÚUp™Úí·¾ùöÔîC‡æ°¸¼Ìýtð"­À`d*aÑ`¬ƒñÈ”8^^ÅPßAË !ÎñC 8*x(” ²kÈцa˜föy8ë™2\[¨À˜cÁpckÝÍTßÑh ?êšUÏEÌRåèåYðÆ„¥¥•AU×G5ÑÝüàÕÐÿBÚUp›.ô¥<~x¯„í¼“ãDH”s|cL]¡®™ökjH$@ ìÇÎÃÂ¥”ˆ‚(‘Ã8£Ø¨ÖlÄ÷‡‚R"Þ ÀRÈÁâ?Á† C·-]…à Œçðe¥BUEGÀ:ÿy¦‘wrk0V¦®í)¾ñÁ»ÿä®Köá¿@쪸ŒíÖ?ø?çàiçÊÊ2ææCkîãgy” ¼û ÉÆ¹E‘!„‚•‚Nì4A‚1šKÿ*‹—JòÝ,6Ê5ˆ†;PÎq‹Ñxh¼¼‚µuí0ŽPGè÷¨ªUŒF ÿ5¦Fek8ïPvŠNZ•¨ªÚôûƒeÒîP–eWi¾Á®:€ËÜn½íM·ÇžÇ?€••”S0ÆuàÊzÍúzvTØ€ÚŒ@Š`UÍ3LÀÿßÞùýJ–]wý³ÖÚûÜÛmGž?<ò€d#EXâ…'Ä oy!ÁH”— #Hlì  ‘¥‘ÇÀˆ9ãXD'ö;‘x3¼ÀtLÆv,ž`ãxìOßî{«êœýcñ°vÕw÷ üãvUŸÔêî{«îsj¯Ú{ýø~K–ÕãÌîÐܸž î#Y¸?÷‡'¡÷Ž—Î2QŽQTh Jm´Þ©Mh xíÔe ¼°›ËAÑw·›ÙlvÔÚ˜ç™^”Âô$gªÏm·Ýì6óåÿñÚïßþæ¿üï7xÙŸÖpH¶§[ëÜùÒ—¨RŠ´È¾{a·«”7Í×»&›è&ô^¹¶7QTÃTº’Ôè=ŽªûêÀø¾â‡Rb ÙÐe( Ùò6 O*½Ç¢¿¼¼b™g®.w\Ü»Çf™™ËÌÕfƒª2e!§ÌùÙOaз›]YvËk"öÅßú÷ÿzôû ±€#à¹}莈?ÿâ‚oûOpñ‘˜«£?Jnî£ß~)$qz…²éÎý˜÷WWÄœÝ\pohŠ9$…ioT¾„æÐK¨Ù¨*lk¥kÌ'̵Pé̵Rzhn®ÂÔ³”rh]vo,eYC|;oÚn³½WJù_.ò7y­Ÿ4Öp$ˆ¤gzç•/ùË/ÁتwjuJw–¥2÷½ÅX%gFCNr•^•Îé,N’Œ ‡IàÒÛ HÔô-dÄ–FaÍÚeÞÒkÅk¥w¥´†×0™7y^Øn¯X–-Û%Je··ó>ÃLIùÝ,mÛ–ÍvSúö[NÿýOÿÖ¯ý§›¾ÖOk8ž{îƒwÕôéR;_üâÿa…€nPG»®jgòhòé½£Ú‡q,V=ÈŽå.£5xn£ZÐé½ µŸ09 ©¯óçm¸•†tД¤¯u»Ý^´Þ¾öÙϼðìM_×'•5!Ï=÷áEìÅo~ó›¼~qÿÚÒK€–^©U–^˜ËBmrŽ0¤V°°STÁгa8ÚpOˆwŠWàú ßÝPíC›°ÒÚ–ÞT›M4ú”²³ÿ ½$Á­œÈ¢ÞÚÒ·W»«eYþX•OßèÅ|ÂYÀ‘bÈÓî~÷¥—þ¥ í=Œ.ÐZa3&«;"†uÁ$Êw>tzqÜÓ˜hx2|Xz2ÜÂ,$áˆN£+¨4jSŠJ’Hbn«yfi•ÝnaY–i WïA¤õ>×:/e÷ªã_xñÅOýöM_Ë'™5)Ï>÷Á»)MÏ\n.ùæ+¯F¶kñèH¼©°} °D]bžß²R#'UÌA\ÚÑ9²ïPÃ4ã¥QÆÏ:ì ôZð²ÐæBÙí†tyhº9OX2RÒ¾£”Íåîž7¾6åiµó¾aÖpÄ<ûì/>o¢_xùåW¸ººÔŽY|öZiSƒ¾T’)1訆‡_H† ÉÑD3 ñÐæônÌ=,ËrÎø²ÐjÅTÉ4z­ÔVÙlêÁå7$Æ@†LØd“/»¹ß¿¸ZŠ×ïì7>óÙ_é†/áÏŽU}¸ûÕ¯þ»”#hÒ]•*NíqG±Ñâ c¡;ª‰lNJ _Aÿ"®ôÞ™¦ pæ¹²ÝF)лB -ÂÐhˆt¦dÜš²»yß•e©myÝÿúùÏ}ò37uÍV®YÀ‘ó쳿ôÊ4Ù3üÉ7^Ž…› õvPùYæ©ádY€&ãzé|ŠwóœÃBL3‚b8­)fý4T£UøìÌÈ9qv_gñŠ9Ô#Ã"!+†ØÔMÛÍóUkõ“Ú?»Ù«¶²g 'ÀG?ú‹ÏCºóõ—¿ÁfsÇÀ:d»(T ÕÌùdhÊ€PÂ$ì ç›³`±n#g¢ç·Ù/C5F€ÍÎ ‚{ÁLQíäI9;»í½yß],Ë\Ú«)OŸxñsŸüÊ \¦•°€!gyZþྠިÒp‹ùþ¦Pº¹>%ŸgrDŒ,Ð[Ŭ£YÉyBó„Ù9q¢H ‰l‰Ô›®Š§„kfIÃkP)ᨠfÆ­œ™¦,»«¹ÏËöBñÿò¹Ï}êS7}­V®YÀ‰ð«¿úwïˆè3÷ßxo}ë›ämØx7í¡ ÐµU8ô Ä>2¡šQ]Š`¾ƒš Í -Úƒa ‚¢L¹3ÕŠJx¨†?Y"ݾ¾;³Yv¾ÙÞß‚~GÐu£iåXÀ ñÑþ½_é"w¾þÕ—}×7Ôº 5&1»ÍB'dÃ{sLÇ\ÿغ#`*ˆ¤¨8´N¨ý& ôŠ×BkN÷…ÖJ˜z. µT°,Õ¯.Þh‰v¦_ûìg?±fýSÖp‚|ü㹫jß‘^ú⯽úßý ®.ïQ–mLý¹â(¦çxWš·è"Æéb½„a«NëÑå·Ù-l¶6W3óý%¼þ–9>¿}³Ý´ÒÚ–”_þÝßýõtÓ×cåá¬àDyþùø"ø—Ú®Ô¹Ìܽw—ÍvÇnÞ@«X6ÄŒ””JóN¯…ReqÑ¥8Í;Kilveü™¹ÿ‚{wïsqï‚»Wopïò’e·PZgYf¶»ÍÒZ{U³­½þ9馀•ÿû[ßûÈ»nñÛµù”Ô¸{ÿ‚§Þóvg…‰[$ ’pœ27Z/@§×ŽšQ[ ‡â=þ»º£í ÷¸¼Úpyµa»Ù°+[œÈ\m®úÕýËmiüçÏî…q×`åXÀ ³›7õîÅF[ÞõS·¹ºZ˜—Šန¦á˜(l(KÇzeY:’”Ò:uŽ3þ¼Ý1ûÌ|¹ãrwÅåý-W—÷Ùn®Ø.UçüüœW_ýž}÷»ßQSûÖMÿþ+ïÌN1¥•⻲0÷JÊ€ ’ §„¨0OÌóŽ´…&¥…„¸(mÇn)ìæ…y®ÌˆÝÕ–««Kîov\mwl73ón*˜Mlç…RJη'ÇpåÆYÀ s–Ä/:Íi.su\éÖ9iJœM‰ŽRæ g f AWºW¼Ãï¡î³)l6;6»Â²ì(µRjhþ¡eE¯n&Y¢mpå1gMž0j¢Ö\¥‹BwrŠ™ÿœ3çç™É”|6aj1.K)vfäLØÿÀƒÁkœ[¨X˜‡¸b¹ƒ(¥µª ôNÈCÎ$|º·è X_ZGÁz—NS!åsR24% z~²aí};¸³©ƒ&R"4[C²ÑKŤ#šhÝo¨)­÷½œ )¦~ƒ+=ëà„q g %¥)Ä?4ñ ü\R&Ã$Ê}Ôæ ‚—ŠšRjÇic¤84RR¼'¼·° SEm}iëà„1Q$ɯÖ#©gáöûvĈ·Óhÿ5UnŸÓJ%l>±:B©“€£éG fzg­k8aΦ3Îl»‡˜@N~wNÄ1@Eu'‹Òš“Ò9µÕ0 éã‚•œ:f Ù†™(Ïβ¿ìÊÿk8i¤c9ãIA@m 'ß`SŠZŸ…Qh÷ $D:ÉÎè¥#‹¢­ÁËÑ#ДH0¬<¶¬à„®}˜Ly…töêNJÑ5(@Ê0Eß$ZA©­c D3ˆ†´øøŽ–ÆB×$à1°€S&%’Mh2²*xC½>ô|ž¢7r6‚Ù”é<‘ƶ>‡k() gç)gÔ•K"¥õ¥u ¬wé„I" Ðû8ŸO‘ ý!O9Ü=ÌCM“(ùW1LË)yRÀÂMÈ£íXè(ÃMèaßdå±b §ŒBV#ÇÞ.1½÷öiÀ=9¦yй€(¢˜“%C‰Nˆ±aRNFÒµ x ¬à„ ‹‡2Žâô¾ª *$;?þ7åÄN›2Ô»wzwržˆE?¤ÁÖÀQ°îNÅ1KÈðú“Q׈*Ø[òƒÐTâýÝ+½9*‚ú~Î „uT,IŒÿxµ•k8aT ï‘øwPCÒÿc“nóý°ýPAɯîW CQaÈ †#º;°&5œ0.‚˜G¿à¸ð@E tìÆÄ4Ú~è× @ª14= "‘$Œdá:|¬à”q?”ãÜ[üß‘dˆ‚ ä¤û¦¿øîhL”Þ;Þ*9üÛF@ßÀ¶Ž„5œ0"ÑÍ×{´ù>L|ϘÏUÞTå;ØE«/¨eEUÉy¢öö–7}]wGÁN¶^ï>´ú±0‡µ×^ÌCuŸ0t4_'öRʸ7ÔB0´öù†qþw_‹KÇÂNGðÑ‘£éÿGvèï?94¾½[5¨N3­T4v}&ÒaÙÂLtÝk8aîÈðñùü#‘Ø÷ûXÄ €ö1ûo÷ŽY”£ªp½âm}U ë­:a:àâTo£-ð'ôaä 9ä $)qeE1Ü=Ú~Ç«È=tÜû!¸òx³Þ¦f¯Öoj‡íý£,ûðÞi­Á› ¼všÄ<ô!.Q6ìÐÆØqsXWÿñ°Þ©¦»Ýü‚·Ž¨PÚ#ß÷==‘Ü;t Ùèï—‘_›ÑY¸]¾#a½K'̾õ—!ò‰ é’s1ÕFŸ‡=@̱ÞÞ´®5F€Ù¯õøFÞbwÀ#fVÖpˆ8uœÓQ÷wʾeç Û£«·¨ֵޒa|MZ‚˜=ºÔ¸òX±€Æ=$º¢!Hß± ðÖuë¨_Ðj¿>?ôq>hÝ¡ûðˆ]@©-‚ÃÊcÏz—Nâ=cïÐ÷ʽÁ#™·g_4С„¦±+Pp¡ÕF2aÿéBNÕú:<',°½@!Ð$ºï6dkðѰ€F¹îÿï’àòˆ³ù¡Æß*oQõÔñÇÇPQHýE‚tYƒƒTøÚ x,¬·é„é8É£ü§€Œqà‡ºCóóÿýZ÷ŸÎõ){ßOì»!½©\¸òx³€ÆLy?½ûOÆÀ †xˆÚÂáUR½GI†óϵhˆï;ÙO ®/­c`½K'LÃÇÖ} ½Ã@`RÆ P´õ쇮ëãɘ\O':€ ?¾v k8ućuW ïhzø¬~©ñÞ;ôÖñ>:‡þ?ÙP$v ÇhPïáÌ^{ÀÖF #a½K'ŒÂa §÷xû÷G ‰ 1`qjÙ· û›^%B‹~?Ý7§õ†{[Ž„5œ4Ñžë‡þ}øÂÜ{‡ÖÈõvÿ°aðá0~6C|ÿ nOë$à±Þ©“gx:„?ÀÃéµÅ{|]JìA’ôQˆí~ÁÝöÿ‹£¿{œÿ× p¬wé„QÑ!Ï¥‡lþ;õèt‡^ÈDWè-¼“ ÒS9´(Ô€Aš "iM k8qœò&cGÜñBÔýÅ„ÖövbŒŒÿ(ôytºQZôˆÐ[<ß½­;€#a½K'Œ#˜fºGòΫ?TÐÆ.¡Öxv0œåÍ–BŠ$ÿè/h>\ûÁ dåñg 'ŒàaÛ%£¼Wm”ùÄn«¹ã$Gý_$‚8*~ý£½*# N6[›€ŽˆõN0Y9hµ1—B/ ¥<äí¹‚iÝ6ƒGcÓIDAT;‰òJøýšˆ4ªid¯;bÀTáîñW[ù±€æ~þ¯|ÑzwJk´ÒØnwl¶»>~»Ýâe!{ã,Ù0Ýû°}û.AËLyâö»oóÔSïáö­[ü©Ÿþé>üÁŸ{þ'ñ;®üp¬àÄù•ð·ž~×­ó¨*K™¹Ú,ì¶[vo‹K…e)cä×ttî»ú Ȉ£‘ù? v§Ôå…_þÐß~ú'ö ®üP¬à àçþæÏ>ïøû–âwvµ°[:ËRÞò˜¥A©s8þ¤F-ÃfC` ûéhþÑýn@P‘»?ó3öC¿üáŸ_ÿ±€'„¿ú³ñÎ_þKïŸôút¯õŽ¿m*¨uÅ­!ëíÒBÈ#³/İD0pMˆ8¦zW•4¥÷½ÿÏýégÒ¿×ÊÇjãú„ñçßÿg^^¸¼¬ïþ:ð€÷Šwzo¡NOxßgC©‡6`ô½¨äÿ ¦/~àïüµ5áw¤¬à åÝïNw€;Ýý)}¯àïEÒS* ¡ëÈò›€AÊrDz¼òK¿ð7îÜäϾò£CÞ¾\YYyrXs++O0kXYy‚ù¿~pmHޤ¨IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/find.png000066400000000000000000000133301217176075400235150ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞŸIDATxœíšyeW}ß?çî÷íK¿×¯{¦gé™Ñlš‘2c)`T,ŽS6JEqPX0I‰¤âØ»\Eì$8ÿ$U@ÂbÇ„`³›’pÐ0‹fFi¤™îžéíu¿~ûrßÝÎ=ù£YH 0(éJ2ߪ÷êÝWoùþ>÷wÎïžß¹B)ÅÿÏÒ¶ÚÀVë:€­6°Õº`« lµ®Øj[­ë¶ÚÀVë:€­6°Õº`« üÍôÒ/ÜŒ—âGÞûO>ȶé)²ÙLE¡ÿF¿×}Ã铦.<~öé$Žÿ£@|!H¤¤í^‡”ëR,–( LÖ&)dÒœ>}†f«AÆÍÈÿÅ7çòù$J…!šÈ8&I.]&Š#2ù†ÐÈf\,Ó@Hb¤R„ã1«+ËDQÀxì#e„R ¦¡SÈçýK_ùÚ¡Ÿ€”òŽm½Üu\”°ˆ¤Bè£q@àÇ”«Óã€8R$±`Ø2…ô‡=,ÃA34 Ë$I6M¥,‹+sÏpñ™§Éæ²ÄRâCjSÓ MÎ=öôŒ‹¦ıB·lt L]§?è3êµ»xà ‰¦KÒ¹ ¶m1èô1,›(V(š®cº«kúÛ_,ÆJýcИ»|™‹—æ¨/]¥ÛëÒmu14‰@Å#í!†!Ð-Ã0ðS-V15“N«Å Ó"Ž‘Rçâ… ôšMÞþŽw‘Ï:‰Ü¼VH€H†LNÔH¥3 ª•*±ŠØ>»—»ï¹! „nqèÈM¬Î_¢7l“.•©•«Tk5rÅ"ý~I¢($ð7ë¼ JI6š ÖÖê¨$azªFer‚B¡H…¬¬,³xu‘Ju2k;öÊ­¯zÕ‰ç­øGÿþ¿ ú½¿kÛ6³³{ÐuQBK¼pD«ÞàôÉÜ÷à·‚£{RÞVf8cj€ÆMÙdS)¦jÛiz-î¸ýo19=ËêüòÅ ÝV‹ RLN”Yë¶÷8®Éé“â8i:­6cH&„~@„qÄØX_Y¦29Å+^þ f÷ÍR.•I¥R¶…¡é$I‰ï~—••Un{íë.9sò–Oê“í+>ð¼+íºÒ„†ãºøAH¯? 7Ðñ‡>R*ªÕ2SS5.Ïsem PÛ1I0ÑU‚®ëD¡D"q'¾ý-¢Ñ˜§ç.SÌ8tàN&M½Qçò¥Ëè±âñóçÐu‡0ŽÆ>a>A XilP¯¯räÈMÜü³ÇÈæKhšN,%~2ò|<ß'Šc,ËæÒåKX†^ž™Ù‘»í¶×|íù±¾`¼óÎ;Íb¡ð/Â(&V`§2¦…nÙhššF(MÇNe9pãQþö¯¼•”鲺¶ÊâÓs¤Ü"^8&Š|Œkš–õ™Ù¹—ùÅyöïŸåÄé“É™§Ï®6›cYjff+K‹”&‹XŽñ׋-?$Š"³¾¶J«¾Æ¡}ûÉdR\~z¡7ÄvtÓBˆÍp¤Lðƒˆl.Ͼ²´²*¹çî»ÿþ * &Áryâ¶biâ¦(–xÞˆõU†ý†i2=UcÏ®lÝ ïû,Ì_%‘³~†ƒ‡/pöü9æ–—¨îÚ…£;xdtÈyc„ צP.³på ÷}ùKòøñ¯|ʰ4ôXû•Û^ós{‹“3h1ÑÞz“Ñxˆ’MøÃ€åµ5j• ‚0dáòJÕ"aãyI¿O*¢X,QÈç0,%ª• ž¹ô ±Â©MM½ øÝ àwÞéüüëîøT ç;ÅÊÒÃᢅᘘšÎÌÎn}õ«¹ýnc0ðøË/|^¯Í¡}û¹pñ"O?ÏÑGPqÀ¶ÉIÊ©‹ý&y;¦¥È:%öÌîfœ$‡\Û6[­Nª¶c‘ôi¶6h®,Ÿš¡ä—™_™GŽBWWqÓ.;ÅpØÅ²]tMg£±Ìúê"¾7¾¶’L0-“JµÂîÙÝLoŸ¦”˰V¯sô¦›Þó«o»ëÏ>÷ß?{ñP¼þõwþËf³ñêG¾ðÝ^—aoD·ÝÇó=b£P@ÂwÏœä _ø"™\š—¿ê(á‡e§èGLU+Ô7ÈR¥–‘&Sždoa‚nséL–Hĸ¥‰¨1ÿôØË¤5Ã6G–n‘Ä1ñ0 PÛNej†Îê*ÙR ¿;$™¬Öðãô)ò(¥X\Xf£Þd8ʈum\ 44ŠÅ"S;«hèÈÊ«n}õG_|€ßÿƒ;Ýl¬¿÷¡ûî#V ë«Mz½ 05‹œ™''ò¸I #Ö‘Jâõ}ê÷õÈNc”¯‘/ï`£Û&&f÷¶iR¦‘6°„àkP± dlK‡A!56íĵ$’hiEh†¼üà­d«9ή¯ã•V(år‰ÑØ#—M“HÅå¹96ÚmL ¢HÞ(µr8†E‚Î8m^Ï;Dµ1?ôý^ï ¿?½ñ·ÿÕ?ÿú³¥Øh¬¿ý¡ûFcqn¯k9Lh5&Í)²v”‘B‚0ˆ6ksFû k¿Ã 5"Wͳo¼SW”³9|?&òl„­aš&é‰ I’Q7Ö|Íq]¦¥‘1shÔKÔÛ Ý±¹ñ9{ö“SÛ©U«¬®Õ ‚˜KÏÌ û¬¨ÙÛI[LÃÄÀ AfªJªœ£±°†ðÖJKœ9s Ó²Þ—$êëš&0PðÎø.÷âSîš ×éÓë÷˜ÉÌp´|Œ¬ž'–fà&1eÄ„Ò'¶ú^å+&V¶áoP_»Jmz;íNÝ4)'û#ÍÂ4lr…2ŠhÕ×Ï¢ë¿+‚^·ÿþΰû¾=åäÜ"J)ÒŽE±\¡Zžâþ•ûÙ3³î°GE,-ÖÉE%ö§OÑ5Ó00u )cÌ”I©R¢Õh2Q™¤\,³²¸Œ»ËåÜéSoø¿öö—}æO>õ˜‘ XZºzG¿ÛÝëf2´6Zì2öñºÙÛI C×)f ’X¢&ƒ±‡” C˜H=¢R®¡LÅ Þ'»1E»¸Ž‡ºÅÙ“g˜Ù;‹m9t“.y7M.ŸáÉ ™_ZxÄÐŒ…8ŠÂq0>½pyÎÛ¹{Oj¢R Ùi “ZwÌÙGEJÝÎÓYZ£ÛP &9R¹ „†é8f Û´ºN*›ÂIÙ‹š ,×eï‘®<±À43,ùsèúüüÜÛ€Ç TÂåKÏ.ä ½>;Ä.jÑNŒÄ"W)Òíö†ë:è¶›vÐ öú~ÀhàµÔ4õdž¦×¥Z®¡éë««d3Y&k5Š“—xø›ß¸ú~Ó”PRˆ“§=W™ªÝ|ðÀ~Ã@gqy‘V·ƒ7SªTñú}¼($;*³#5‹%Rn+k`§lÜ\DzHe]4ÛE%’b©ÌžÃZ ¶؆Ý5™›‚\-ÏÚêê~Maì2Áë9¸û{÷ïåò3— 5Ÿ™¦0, IB’$ŽJƒTÈH¡%‚|¹ÌŽvRž,0aOà{¦i`ZŽí¢„ Ýí¨o?ôðð/>ûÙ õµõ+­EaEQ¬”Ü{ƒæWÿüÏÏ|ãø½z«©Ré4¥R‘jµ€kºŒ+NQÊdí,®•Â0t ׯrl,ÓB˜šÐ1…N¹4Áá[aeuƒo½ûNL ,Ó& Â(˜0T¢áÁS™H©‘ß–a_v? ç.ÎîäÐÏÞÀp1îЕ†0M*ÛkLì¨aY:­&GoÞϨrî“aŸ?÷øÅ(Š"¥)A"EË ôƒ¡ÒÔÐ2¬óq?*„ø^OûœRúÃ#Ï{åÃ?8p'cÛi×Ð…J*]¸sÕ™¶vMíÄÄÂÉ:¤Ó) ÛÆ6mLÛÚìGTË”ª%ªSy.œ½ÀÕ'æQ®à+z/fÆ@) ß÷Ñ®õÊ ”"î+LÇ$ÔûŒ6|ÆbÄŽ£;é¯ 9qßIŠ•*·¿å$0wé*¦aÑoõh·<†ÃÍz¯9BKé$^2^ÛX?%`!„¥iÚ@ÑJ\‘R^Ðu} øÞþÀr’$ŸQBÖÐöúž_ô¼qA(L%HPÊ™PŲ=mM;‰ƒe›($q’¶]r.†áR©ràà.¾ôùã4ÿr‘€åš´›ÄnHC[E˜1†®$ªËC ïCc ]Ñe½¿JV+Pï®2½k;“Ûkx}ÇO]¢¾¼N¿×ÂÔtL×A…7òXž_¥Ñ^Åž2 ÑPIr¯¦ëpmëH)åc!›Ë‰çJ !Ö•R ¥Ôw˜B‘A  ±”{c©^näÌéQ€dº"ôC†ýK ‹()pR ç·¡E&ûïcýJ¥…Uð¸B«¸„¦idriºýþºi˜¶a™fNšcÛ©@ÉÐŽ‰YÒH­8:{ŒŒ] ÄdRY åAŒ©¯®‘¬·@ÓДΰ>Gg¦A6çÒ ¯W”R+/èʾx“VþµÇàÚr=7{«º©èf;„s](‘ è”kUJÕ*…É*£Á^ËÃ1ÓÔÊ5έ£W^Á´-4©‘Ieèt:1PÔ„$*‘ÍÖÆâ¶™ítÇ-Ü’Co¢Á…ÖãX¦Îþƒ7±ëÀ^ÀÆÖ,â¢~À¨ãáµF=EkŽâž ½þÐë÷ú@¢Pü4·â*µ¹M†ÊóÆ­n·ßNOÙ4²ËŒ¼!ã¾71…¨kén*‹]{pôÈM¤ Y.u.Òž\#WËѵ™Ý»‡zc}1Œ¢HaèB̆ƒ©je²°sÏîÔòê"³{n 5i2¿q™•úU ÙI £Þ€asÀÚF~ÒGdZå5Êû Ì웑Ç"‚sBˆÞ³'^ˆgš¦¡iÚ³Çßìsô½c±™»{ƒnåÆ#‡kÊPz+Ù@Ó <ß$ùt™B¡€f$"à¡3÷òäÆ9R;,Jµ2+ëWØ{xAõNœüîSÀY!ÄÃz’$òÃþpL¯¬¬df÷ìI8|Ð]ZY +qàÈ~̲ÁØè³°q‰Åþ<½‡V‘˜;t†é.³‡vrô–cüÏîÉõõõSBˆ¯Oò{Á<7àÀó`Bˆ £|}½^~íë^[6l]´U‹Òž©I›8íÓ :FÊ1zÉ`ÛîiFþzk‘CÇn$–ñðÞã÷>Ëøq!Ä—‘(…®ip£Rêç…wÜvÛm_ós¯ÙÝj·Ek½A:•ãàþCt6Úô†A§u8tÓ!Â8ÿ—Oþ×שּׁ®ü•â›À‰kãøY=7h]×Ñuýûlî4ÇÏ‚Rò<À¥Ôù|þMwÝu×Ë ™Bváé‘O6_¤P(`§l¦k5æçi´×)•K+%uâÑïÎ?ô­o’‰|Bq8Ÿ$I(”Ú§º®   ”Úüf*vé­¿T>|øÐá\.Ÿ­NL°¼¼JèûX¶ë¦TwÔm<øÍyà®H)ïB\êÏ=ó/!€k£ŠRj—âÛ·o?ü«o»k{©TÚ¾º®±k×nºƒÍf«÷Ì¥§/Þ÷ûæ{½Þø´â2ÐH®¥Ø³MÑM I¢°,ËVJÝ Üùæ7¿y÷‘#G¶ !Òº®€J’$8{îìê×¾úµ9¥Ô“Àg„>¼ ¼½Ôž«ïy|ó›Þô¦=GB8B=Id,„6üü%;¼4€±±±ñn¸áÀûmìjc3a"¥$LÓ¤»»{àjô¡A€ëºolžÍsgöJËà3þn³½YàsÓgµá\͹R(Ü…Òï§ Îr–˜³é åE¹`zsý«åÜ À“pöþhÀ¥¸Ú$lƹ3{KB†—lórpAÎô¹ν_îuµð®6àb|$œMŸ«úgÓW µ`³õ¾X½K•Á¥IØ,ø‡fÞ¯p WSýáKàÝÊ®´Þ{!áBésë\ \¶¼XÙa€óüÿÙü»ýöJðžÜàÅÊ>Ì`éjâ=»Á‹•}ÁÒªWC€3XºP.5_4 ”êŸÅ/…¼ïpµðF‚d°tµð ß‹¼Z¸¤¼Ò²*XºÚøÐ6D>Hïð~ À;Uëÿ7>ô ‘_6~!"¿L$üÂ6D®´«+Ž‘ÁÒÕÄyFðlg–pﵯ«M„¶¹#)åyaó¿¯ ¥7ç;ÇO¼Éää)޽vßíð»¿÷{ÜpèÐe·qn{ß~è!žÿéólÙ6Æ5rpÿ^víÜqu ¸ÜëbÔë {ò)¦&§X˜ŸáÔÔÅužxü þÓŸþ ·}ö³—lc3:÷Ü}7Ï<ý4¦a²´²J~}Çñë¿vw|ñNdàóз¼2éy6àÝêNOÏòÍæÄë'(6ˆ'RìÛE,–@U5¾÷Ýï“Ëå.ÚÆ¹éGþúÿ099‰¢(lÛÉÖmÛñ]‡ÂzŽÇ{Œ‘-[ÿ9ñ~„‡M^àr×å¹ùç~òSþìNne…FµÊ©7^çð‹/â×^÷OH$’4j5Þ8yò]Û¸PúõãÇqÚ®™ØOWO““opâÄqêõa(ÈÏ®ûƒÏÿ‹ÛÕ«BÀådnF†,..òý¿úk„0tz£†ëù@Hi#ºŒnÛF©RÆqœw´177ÇW¿úUî»ï>Ž=z^_Íf“D:M*ÝE©TÄé8È@R­”ÑT•X* (Ÿ ÿËwÝurÿøWtX mîôBkró³Žã0;;Ç'ßdjjЕՄ¢¦šÊz>O«Q'Oʤñ:žï‘L§Þ>Ê:ÛÞ×¾ö56Š'OžäÁIJ,„T*J• ¶¡Ñ¬±lbñ¥b‰µÜ*[¶Œ’Jwá%b8…Îí´;÷·Íå?ýÏ_ÿ»T:ýÍ;¿xÇ;Õír¸À›Ÿ--/óÂó?£R­P(X^YÁ2MÒé éTŠÞ¾^R±(¯¾z„Bq˜Ç :í6ðàƒßbphˆ°¶¶ÆúÆŠª£(‚V«I­Vò,ŠÅ"÷þÛ{Y^Z"B’ŠJ,“ ÚŠ²9xðzÆvï¦XØ@âáx®V¯Ö2Žëd\ϨVJÿæÏÿç_Wå¿ü¥/vÞ3g†Ÿ/‹7Þx“cÇ_GÓ5MÅó}!Ðtõü 3³]'“I3¾w7¾³“õrÖFU¨´;Mòù5þÛ7þ;]™.Š¥©dŠt&Mªµ ÷ÝÿUvŒmcvz–Ù™Y*•2‰dòÌ8\³;¡²QäñGÃó<ÑÑdÛ¶h·ÛhºF4W-ÓüJ³ÙÜóÿñ¿>sÏÝ_¾( ïpƒòÍ…"³ó Db1<×E‘‚À÷ Ãùé<ß#–LU-ªõù54S'“Î x¾‡DÒª68==Cú` ? Ñ5ƒ„ á¶è4ê´›-–M‹Å…r««ØÑ¤À²£¬­åh´\LMG3 ×!·²L˜ƒîî.TMÃiwPi Ó"Oü¦ã:÷t1Îó磅ÅE,ÛÆ¶,%m§ëº¬åרÖê¶ Á |,Ã$‘ˆb™6¥b4‰¢<×C( §WW8~ì5ð*µ*˜! Õn†’¹ÙY^?|]SÑ5P¨vŒF«†&â1C×PBŸ@JÜv›Õ•e<Ï¡ÝîR†èšJ*™¼ç‡=±ç’¼[0R(ñ\Û²‘ÂÀ $BÕh¶œŽO¶g§íà{’Ð4j M—Z£Š¡Y(š‚fè„á™AE ƒ…ÙSLžš"žˆã­¶K_ÿõzc¯ý#jÌFQ5|_¢&ªºªR«×hV‹4Z*’E ˆ&b˜¦A½\C3L<_"(ªŠ¦©¶ª¨_¸ïð禗—V…Ù™&§gÉ-¦R­P)VÐ-Ž@úM꥚&P MÓèЦ'݃®è”‹Eêå"N£M¨Lžr˜ÉÅS”JE,Ã`xx•¥E2½i KÃ|‚ Àï¸xžG(|òk«skìÛE,afjžF«iY¨ºÊ[2„tx"ÉØÎÝ,­¬€ ÿÕí·ÿþyá<0;;KB4ž¤Õj²‘_¥Q«£é:ý}lÆT5jós§ …mãؽ÷$Gcvy‰žÑQ,Õ¢åÔÃ2‰V¡CÊ6Ie³Ì/,ðì3ºeEüøÉ§"Ý;Œâƒã5¨æ 4Û d ¨‚NÃaym¾î.×e~fLO×ñiµZ„µ‘h„t:C*™@3L¤ééîâÔô)|‰Õ×ßÿ9àß¿+žç195C CŽ¿v˜•¥%¦‹ %š¥£+*Ã[†9tã|âW?F½ÞâÉG¡Z-±gl'''yóøq&Æ÷!}‡ÁÞ^²‘‹µI3Š¢Dˆ[¶oÛJ¥TF ª¢Ó72†t(7(¬Ì“ì&ÓÉ2·2GÐtY\]ÅŽÚÄÌFôQ•õeò«‹tZm|?$BtC§»§›­Û¶204@&c-—cbÿþ»çsŸÿËïﻓ´'O¾É©SS<ÿì³TªÕ&•RV§…/}$yùÈ+<òÈßKDùÈ 4- 3B­Ñ¤¿§›ÜÆ:A‘L C‹Ëö²#ÕE¥°Æ@,Ž'|bݽ„OI,ÇP BßÇo8¤ú†èºJ<“¡Sià4ôöôÑñ=4Ý$•J"¥dq~™\F³Žx„È·Öµ@A!NÓ¿¥ û†C7~øóh4<óÌ3üíˆ/Cò«ªÕ2Ѓ„ž$!’ØaÍW d@«Ö!÷t•äÞ(fÊAv’Ù6*%||¶ÑM´¨†!,ê‡n3…­«Ê%¡âIŸÐ P¢WwùÈîCÄ{Í籄ŒJ$’l6C³Ý"’™ÙY6J%t4R"MRK7XšAˆJÛkž ç,¼¾6?ýɳԪÕOÞßhþæÿ»{ÿö¼ôÒË<ùè£Ua}1O¥ZÃ6,º”>zõ~âfŠˆA×ñ¼Ïqq½ó„±Ë¢i’èI2ÖÞ®J²ñŽ× 1-¦‚®ëD»bxÒvUÓ(–Šè†BLO  ‘[_"W’¨–É5×íæèÑ“ôöÑ×ÓÃêZÇñ™>5‡ï„Œ;é3‡ˆ1tMGC#$Às<ôH‘l‚õù5D+d-³Ä‘#‡Ñ ã_?' Cí›üBTË5ªµ*ña&²‰«IGb(–¦ã#štðZ«‚ìHºVé ÕÉ­¦o`ˆR¹„ªëdÓ]´;M,Å@×L©瑎ƹûž{0M‹‡¿ýÊ Û³#$ì4RJ¢–A:ÛMO¶ŸgVžaûð•FÇóXZÌ‘ð2슎“Œ¤Q ]ÓÐU … ðÑ#:™î Åõ]ݽdÓYV—±Gm޽zø“¿û×>üío½¦är¹á7OœÄŽÅ(nÕÆ¸iÛ'MUIÇ5B?@ÕtêíA Ñ„N ztgûº¤ž«ß觔δ]4Õàè+GÞ± Ó°¨„’v”D2Æ''dpp]×ÛÎc>É–­ÛéêNQ(¯„”J›£Ï¿HtPÍ$å¥5*å:ÝN/ûº÷ƒPP=K`ê&BU‰Ä#X“t:Eacöٱo˜…ó 0ÌRgUA››ýp†€…¹¹Œn4Z5FÄ(}Þ´Ð ѦR©"4 Û¶PM ;j¡h*ŽãÒ¨Öp:Íz è‹ ç(´*ôdûPT…üê*ñXœÞ¾>Ò½Ý,..±0=É5»ÇÞö>a iµê¼ùÆ víCCeqy‘b¥L«Ý&ÓÝC«V£å¹Ä›YF"Û0„EÄŽaÄ5̈‰ˆa‘¸bÚÈ0 ɲ}o7Åõ †Æ1+:³s'Hô%Y[]Ýõv T­VãAÒªµÙ½u;ví`æÔ ®Òaxg?ša†!š¥aF¢HO¢„‚d6ËÈÎ-d{St™]tZ-t]C7 ,ÓF A¹ZáðK/süÕÃXv„T*¦i¨ªJ6›!±8==ÍÏ^øÖJE"Ñ(™Lšžž¶nÓtZ~„”“%nƱš¦¢Ù&†ebèB7P„Š.T²™.ö:ˆW©×Ë|úößBGÃÐM\×Áõœ·m@„šã´Ñ¥N($cŒÅw1lwÛöüÊNuvµ‰*„®Ó=ÔG×H†¡RÜ(0qý.š—cϾ‚´[Ð D†BÕ0uƒd:Åľ ®½öZTõ̆îîÝ»ùèGqø•Ô*%*•"A P Q¤B³Ý mu3Ú¿+nFÐLS7ÑMãÌ~DO–LO†žþ$'žäô‰9¤-xì;O¡Ç4¤Tèt:(oýë;³#¤'tKÇUk47:´E“‘‰-ÔÖ¼ôô+¤»{øÄ-%f§O£kµb•R±E£Q¦+Ó*4Q"*FÛ`xt˜®l (BÇÉf³ŒŒŒ0>>ÎàààÛñG__·Ývûöíc~~žr¹L¥ZÅ÷<U¥ÓnSþé¦j`…†©# ðC—¨i“è²Ñ4›žáÆwòÃüˆÂ“ˆ [§´XÀ·]Ö•U„*N(+?wƒRxš®CQ!_[%®¤ÈUV¢w¨V­Å뇧É-ç©U‹èŠŠn[!i5[,Ï­²^ZÅì×ÈÖ³üêM7qèС·ßì¶m›H$‚®ëç½î.„ ««‹®®.®¿þz<Ï£Ùl†!Š¢077ÇÌÌ ^Û§Y«#ê1Uâv\µ&Kó‹È@`E,æ¢x:c{ÇÈ/äXš_…VÈ< ÓK(ŠB,¥R«å…¦&„HìݳWÇ“8í&>>KÊ<‘|Љm‰™)üºO,'•Màx>¹Õ5Â|Eª4r³”‡×‰'l02ŒŒŒÐßßž ƒÓ41M“X,övýz½N:¦è¯S‰—qgT¡!Eˆ” *íë!ÓÓCª·‡f½AµØÂÒ£ôeû8¶vŒjvÝ4P…X$F¹\öô™¥ †i08ÓÝÝ=5888¯ëºw¡u~¥o~A äóùÁõõõÝRÊ}·Þzë@:žŽÎOÍã6;Ä“iR©fÄd ¯¹Å9ÖKy2Ù éîŒ|éÅ—ç~òÜs‡ƒ08!„øp< CWœ€¢(HI)Ç€?ŠD£ö­Ÿ¾5»wïž½‰D2ÞÓÕÅòò*n§ƒašØvDVš•õ¿ÿ»gŸöÙg‚ xJ1 ä€à\6*ªª¾C̓ À÷}¤<ó¥èÙ¯YϺ¥”£Bˆ?Úû;ŸûüP&“ôŽæ:ªª0:º•J½J¡P¬žšžš|úÇOÏU«ÕðbXß:¬›D¤ C‰a¦”òð[7ß|óÖ}ûö !¢ªªj€ ÃÐ9zìèê?1+¥|xXÑÞõc¾‹P­V/K ÎiïìoþÔ§>µ}bb¢_a !Ô0 |!”ƱcÇÖüñ%à !Äó€†á;TN\J…i $7=®E)eÎ|s¬**ªö¾Žê/ aâ!¡ ‘~€/ñø%Çøn¸$ÿ¯ãÿÿ#4öþíÇ‚IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/folder.png000066400000000000000000000061731217176075400240570ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ BIDATxœå[ÍÅÿUUOwï·w1Æö® ¶`Ì"ƒQDnüI‰CÊ!É!— þ€(§$¹åˆ£HäC”œð%GŒƒmyÙ5kÌÚ^k?íÝ™îª÷r¨ªîžñÌîìÎ쮥<«=3ÕÝÕó~õ>~ïÕ¬`fü?‹Üí/°Ûtc’Ó§Oß1&¥ÄÈÈæççAD@ǘ››3cppabnn044„ 0??!††† ¥Äüü<¤”3gŸGFF¦©ÿ,÷îÝÛÃÌËËË„axøž‘‘ÃA ¤)Z¨‰#÷Û;ðƒm ›â]’™ADÐZCJ)µÖ½RÊ~¥ÔX‡•R‡â8ëïï¢h¬§§g,Š¢{£(ìéc•Æì­nÝNpp_„°7|¸Ùóvf®;´Ö µÖ}NÁÑ Ap(Žã±žžžÑ8ŽÇâ8 Ãp_†qEJJ )%„uó¾^\Ãb%A_àÈ}}()‰Û)‹fßgÛð c`ŒQZë^"êSJJ)—J¥Ãq:th4ŽãÑ8ŽGÃ0Ü¿‘‚­$5„™Å5̯$è qd_?‚@¢šh$†!ZÄ»m€™eߢèé±±±ýaˆãxE=GQ$•Rl¬èD´a|³XÅÒjŠÁ¾åÑ!¨@ Ñ@bf{˜É®ë03J¥ÒÏ}ôÑWÛ^ÁÍJ-%\]¨b¹šb¸?‘ƒJ 5@šÚk¬ò`€v "Âððð3CCCÝž€Uhêæ*VjC}!Ž‚Vqh«tv­;ü}ͤ+É3CJ©‹cͬ€™·dŸL/¢(90Ã@B€¤†‹D®81j @WˆPcdod—ãÅ×fL´;]K æW<° ÔœT<8÷}âzKh”m±€õèu» × aµº†’`an¥ç 6ÚTˆf²ãlVˆFkcP«­ÙÔÊv¥»@‡\q†ýàÇ;×è%^ºÕ½ïž ¦iŠ4I,Ƹg†œÿ:e‹áÄ[3ƒÉ»[óçÜ•x•ÔjHÝê ‘+a•s«ê\Á¿ú•òü/Å6ó€¢Â !Ä–`f¤iŠ$MëÀÍžá|Ú¯Ù˜°+.Ðôëw „§¶@æ¤'sŒ¡œ3¸lÁÛ™¶’· „ð.`#¼W>ç CÆ_jŸ…]`‚ífVîÒò~¶é˜yAÇý)ăAÛI\£³c©Ë"œCÄN¡ÜÿóÔGu+ïƒ`Úm »¿!¼ÃQaÇ……× 2Ú%ò[€c5iº€Y‡ÂvK2K€5s2Dœ" €™V“´€f¡¢tf!œCY @”¥= ÏK‚jf- ‘ 6Ua Ъ­–w×P¡66Ú€ÁuŒ°n'ŒšÞE h%E Zeƒf ±‹D:ozˆ¼K”‰nU)»¦QîŠr¸-âTà»ä2am‘ÈÏÛÂÈB PI·Órþ»²n&œ5˜Ôhˆ œ<ç{2a©òbÕÀ†Ûh¶eeQ_Ï:¥Áþ.­ Œ&H×,áKd ª!,¯™ºg7JWBd«î,€× d…ñV`øûÏ3´6®ÃÀ ~¢¡$f̯¤†!E4HWHÓ4SÊ Ú½·Ñ*²,_]›¤) Ãäj\á*A—3\^#,WM¡WØÜ-»²3T©T`ŒAÇHÓ4‚àÍîú®g1ÄŒ$Im[œE–loÐv~ü£–2æVu]JÝÖbH)"‚RªgÏž=?>vìØx§sf c MaŸ[Øf'1 |kî”°ë|sU£¦ ¢<›KW¨V*âÞ}û~rüøñËåòC½½½YAt‡·Á =/ÐZçóè „ ´±TÐßîóƒ•5c{®bßDh"]qSo¾ÙÿÈ#üâøñãõööf;8^áõØ]³q­5’$©«*€÷‹*è È™¿‹pó¶Æ­ªS´|Á’ ÚÆËeµZ­¤”ªù/¿U2d÷ÿjÐZ»MëqcýJƒªK„}N%1˜½b¥¦}b“m±ã%]ë9¥}”—Ç|”RaqÕ‹J¡‰"â~G”¥R)%Jahwˆ Ùœ°ñ>5„jb°\%Ô4e­ñ,ƒä¥BvW3Ù§°åù«r¯6îÄÌ--ê9½÷oÏ›•ÏBAà?di¶þ:ÆJÕ`µFPÒ§PÜáëÙaSÆËe¯\QqÕ ¸? 3‡ëàAð,±ºìA0ÆÔñŒfÊeçŠK/Zƽ:ieê/®º%@ÈDußVw‹6ºÞosñ­däÇ÷ÄÐŒVĨWR4¼W…1b DÌÂïçw²5Öö}ÌvsÄUƒùÆ@CÞçzÃh”V0€’;_Œªá³Î¶Z n ,vQ> z×ͤUXeCX ZY‚@ØmóÞèÞì_ãŠûk²ÿêÞÜ!­H¬À*À‚P4ûúàÈ\j'nUîp©‚_·"8E¹q  M‰Ðʼn †á,ˆ¹U”Šï‹4²¿N•¿C<Ôxp~ŸO Á›ü­°¡6^./!|ýNẸÀ€¬aÙ i¸zhà2o’TSª4›cC"tqb"/—a 0‚†,怈:ß÷Ýx6 0S–í¤YB¨¥T[Z1 ó«úê[éìrÅÌüò{wÎÒ.öÏðJ‡nÜïfæKÌøã«¯‚™E__Ÿ¯DQLwyeéûb2d¡f{ΟüÓäÛ¿¹ÒŽN›ŽÞ'&´K‹„±(ŠO½ñÆëg?ýôÝ‘‘‘þ'Oœxú‡Ï=÷lc{ À,€ÏüËn¬þK®ÍÌàÒ¥KÃa]/ ü%ß÷'à C )¡"†¼Ö{î¿›üÇoo¶«Ï–Ò—s‰•ñrù €eÃ¥0¤©©©ÿ\¸p¡rîܹN<õÔcßzâ‰{t¥rÀÇN !.˜Ùhþ8ŽqæÌLOOcÏž=V[ëv€+{XøjÐp Ò_ö]øýkSÿ<¹´]:ê \b‡ahÂ0Ú˜³/¾ðÂwüñž_½ôÒ7›ýá43#4ĈXhÆáês½S§þ<õÁë+›Õ¡ã¶øÅ‰ /—‹aˆ•”øæêÕù8ŠºýKQ %seqA…Q,Oÿ{è‹_ÿåÒ…³ÉV&ܶ?œ,•Jˆ¢hf¬”ú³¿¾ueú“Ïî]¸ñõ¥‹ç¶œ{ﺿnK„d‘¬U+×.^QA©£©þœàϽFϳIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/folder_new.png000066400000000000000000000103331217176075400247210ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ¢IDATxœå›YŒÇyÇUÕç{sÉ%)‰4%Z„>[p%È…œˆƒØ1à'?ÉC×ÀN`ä!‡œÀ‚I^Ã9€Àc=(²€öƒdËeê°Ú%Þ܃»Üczº»ª¾I’011Áââ"ý~Ÿv»Íøø8 ι¹N§sp||ü`–e÷EQt¢Óik¥ÉÑ^!ó=&§ÇÛa4>öñ{Rõ•»À[5¡‰AÞ{¬µh­qÎ!"ãÀaàpx||üðÔÔÔ±4MïKÓô¾ÙÙÙÉ$IÆÂ0ìcˆ¢€ÂÁ…ëk¾àÈlÄX+äÅ5wüžt{Wï*ÊHãÎ9í½ï(¥k­ç€#ÝnwnllìX’$÷¶Z­û<8$ÉXE­5A õÎ3v­o9¿”áfÆbŽwp"^h+º;wWpÎá½WJ1ÆRJNÓôðÜÜܽI’Ü›¦é}QÍFQÔ‰ã¸cŒAk1fÏ}­f%—–û”N˜K˜ìFx¢ôxñ(@µÓùwAkýèììì_LOO¿ûøñãí8Ž[ÍèÁ½ÚjVry¹Oá…ã)cí'»ú^‘êåG\çŽà½:ô'Ožüé;yÝa[éÕŽ;av"¥Û ±ýP †ºq^7; €R*ív»Õ Jíȼ=›¼xi88Ù"M¬‡¾ÛtšÚa¨FÝË yG»#œl‚Tf·ißîØ=õñÃkë¬f–GÆÐa@ß‚õ5Åë×𨠛í~DWw„Ñ~'ǶkoÚ¦ s+{VûÌMwX/ÁûjÔõèÖ‡Îðà½àë6÷N`7çßÚ&"xïÑâ(Ë¥5Þ×N HãøÕüüÝŽ¾îÁêiÖ8n­¥,K ï"õh ¨zø,¨­À‰Ðàz×§@ãx“èìÇš„©( ʲ¬®m*‡|=ïUñ‡gŠR›`ˆßüü¶Æ€ýš÷ž<Ï7šqm[ó }['<ž÷o¼÷û¡ý:“Üú=uRSSUÍÿa ª¯=~è>Þ«Ànmˆ·Æ%ܔ㠿™)?–ApÛvjš èáU€›ß÷7O‡}½£¦Àh“A¢ÓÌÿ[ßà–3eç¹kSàÖ$g¿¦ r¼¡©)0ˆ€÷?p¸*Gø÷p'/‚ª×xUg@ÒCçª{îm+ß¶)p'€hò€á4xÀŒú_ó8>øwí¡.¤hFXÝ4ÿsCêŒH!uà¼Ë¼•Dh§Bèv×ðu…S±@6Ó`\3úHýz{b€s¥Þ{œµèlµ]•ÊÒÔ‚S% Õ ‚ý¡s4UEèGdBw€ÈDôËþÉne„Rõ8«MyKÕ¥ PBqõÜßLo¹Š’ÐD..'â=þnì&†P±@¼à¤Š7Þ ÖY¼4í2øìE蕞~y—ø»'ÿ–s×^'’¡5xÓ;‘"W׺Yåñ"Xçp®úßI5ß} „ˆ°–û‘‚È`im‘Ïý÷çxsþÜêTwÊxXê¾£¾o–=Á#•ÃÎcëuß^U!$"äNXÏýÈjh_1àçþð#¿vùÚ…‡ª¼¾¸,é/Ó +ç§f¦ê‰Îz߇yÿ{ßÖzÛH¯”Ú6yÚNTm(¯4 uÀ­#aS5W2ÖsOn…Q+˜ÿè{8õØ‹¯½Àõ \ayê…§\˜êLðЩ1ÞãÔÉStÛ]œl·cDõ¡I*jkçqÞm–ÅM"4$‹ãa%óu渳ûà¯üoö©ß}ŒOýÂc,-\£Úá1h³ss\þÁU¾üÄññßùÄ~ºiÒ™ZñåI)@ TµDnä5ý‡s…ml_¬JÁ|±H/Þ`Und!F(b‚‹‹—¸vcU§%ûÙ+¨¡, Bᚥ’MiL x ×3‡ó¾énå- Z‚³Ðé XpÎ╯{Ø”mn— a#üÕ.Šk=ÎU#¬Ø\÷ª¢¹£ª¹¿Ú¯¦Û(5ö @ &Ñ„Q€JÀ)‹x …uÑÂíO݈­`‚x-m%™yꈧ6Ÿª2@%P ëïe ²}ÐKÛ:Ö„QH‡””XW ¹¢°nÀ€ívùs±ñ›Ë(T“ö­ZÁRÏ‘å¥G×í €cGL«‚Ð`"õ :\$XJ¼’·ÜƒÎZ¬sD¦Ž!TjÒ2(…ÕPà[í ˽Šúr;î×¶Ïà1‘&ˆCLdÐV!ب¤Ô%‡Ò;S|§8ཧ(ŠAma=L¦†²@a¯ã ªl®WJEý!¡T†‹‚l_ØÌ£[hTPG -XmqÊâñˆÚ9ÃÛ®$.Ëò&çœæÆbú>Ç(Í|¦pC´_/=×{WÏû ¼Y+ßÜU/:U(­#ˆr8åpª¤””„ŠÀh£·ŽøPõæ¼ÃZ‹÷~[fÐm±)A˜PzÇ̳–ûÁ¢1Ȇß >ñéÅ/]üKv‰²]оإu¶‹}uË (•+›|2 càÄÑüYo)}Iá ¢Ä05=Εū„aHs榤–°œ­6BŒ1´ÛíêXÜ-åu<ý¼²Ò+)}½(U«Æ[µ„Q¶€ƒ3‡^?¿2ÎêÚ*Î9òûú' T *QJÇ !ŽB90=75É4}—QÚ‚ÂU¯Ò–dªÏ=‡Ž#ןüûqýú ¾/¨BA’ô_ Z4ÇÜËGã÷xôÑŸçÈá#ô”¢(ŠA‰-Š¢o=½¢Ä¹z©Sµî7¤ïÆùmøþ¹—O?2ÉÓL·¦ïŽÓê´h¥-Zq‹®'V1^;rß'R–²%²2#+2úeFžçäEŸ±£NüÌÌ<´h-ÕKy…RŠ@ºÉ_ýÂ×xðÁS?vœ²,±e‰Ý;nÖš}‚›ÌNGðÒ^fℼÓã@4Ëau˜CÁ*™F§‚йŠë€U°]£·Þ£×ß`#ïÑË{¸Ü³¼ºÈ·æ¿I„:À˜€ ®m0Ê`Lõ®ƒ€ÞÆϽú…+ªÔYvvbðì@“ @ÚÜDkTª±[x6®e,™%6f×Yι´~™±ÌtfOLju ¶´”¹%Ïrú½>½,£è¨5M¹æé«>AdС©r 0óbÐxQyÐbÕ®âp·¥nS‹“ü CT>_öX ˆõ¸uà:äIÁºÙ@¡±Ör#[¡·é]Úºƒñ[8ò~N?ËÈ{²¬Ð«F ªep© |P%1 P¾øœ5`«ÝR¨Ý<*(‚Hó ´ ¬Ù+𽡽8ëà´Ðó=¼u”EI¿×g5Xåš¾ŠFJLâ"¹àW@]טÀ#cikHCL¤!0£1Zc¨kï8/aBÊHªÙh”¡AÑ´åÀ¦y»q”­“ü?:ö‘`Â@LK“&-Ò4¥›v)Š‚åþ ¿}ÿǘlUN=Çss–V¥+G3@$D8/²œÙ¥•ž›¿¶Zž_\·×V2·Ô/}$ ž3F?½ÓåFCž¸_)£;À=À PÅi¥µVý¬0¶ô¨T QÇ1I’&)vÍÓ÷%½r¸ (]9ª»M)EED!ìYúe~ãÜB~íòJþæüZyõFæ–²Šæ …ÒJZIáJ«¯œ}üa»ÓµGðêk?”S'OZ Gµ-g†Î (•‚ @E†!aEQõ ]"^‚è®M„ h·ÛdYF?ÏϽü⋯^¹ðÆ7Ÿ|éêæþ_úÍçÏ«+yYjÖJ­ˆ€êñ!/Fàë¯þ‘'n×ÕnÊá>p°À`ˆQ„”(Êê*:¤Jm!Â0Ä*Ù•,u«™0¼pùÒ¥¾óì³Ï>ÿÝï~çÌ™3ÿwåòå««KóåúчŽþâ‰_ùU£$2JPHµ , ÅÄFóäóÐ×vÓ×mxåìY²S'O^r*ÝqPª@WU™VzsKLëz®n£lµyàyùðU­Ô«þÙÏ.|õ©§èt:¡Öº†a»ÓíZ‡)ˆòÞ711Áµ3ÿyîßþà™Ý8¿+†€(N<¹@†bš‘¶PEù*±Úb7€ç€o_^‘+i«Å³ßúÏ<ý4333Z©¡ä¸ù5ˆÎK-žT~HæÑ›§¿tîËŸ~n·>Á¡WΞu§Nž\¦bÂŽ>–jëÊWªŽ÷¾9¼ÃÛj×è àyàà4p¸´m'"<óÌ3XkI’ÄS1n€¢¢¦¼«úQZ…>H²äÜ×þýÜŸ}i/þì€6€™c3«ÕZ®k-ÖZв ´¾´ØÌç…+‰LtÆywÛJÝ9Ç7OŸ&·æ¨‡*Ë@I£ãéŸüÂÿóׯïÕØçö¸AÛ04`4â T%…ä”RKA¨BL©ýŸ<ñ™sOŸ{ÆÇaŒÑ·/÷â8¾µÉ9"9:pJUA"ÅÆÕöË_üç7ߢó°OQôà=‡‚Cn†7ž_eêÂLOa: ®eX[îqÔÏp´s4\¾±ýÕ“óÈý?Ëÿò¹-¶2£Í£Œ7 ÅúÂb\r)xῘ.~o~?>ì €=üÈòò™ù¥‹ß¿@ $C¢‹íUÒ÷LñÁãgKkË^€ï_<Ë¿|ã_ù­÷ý:s±nÇüd[Ð^¿²üÚüégB‘"(Ö­vüMä®Lݽg{<ìÿ÷¨m2qoèIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/help.png000066400000000000000000000527221217176075400235350ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½w¼¥UuÿÿÞ{?í´Û¦÷a`€af:4Q@Á’ØF±$5jª‰_Kªñ¿‰þ’è/J4¦¨D±€)CïCq:Óç–Óžº÷þý±Ÿsï¹3wPøþ²^¯gÎ9sÏyÊ^ŸµöÚ«ma­åèÿ¿$Ù7ð?ôË%ïé:Ñ:!ž®SýÂÉÑ)/¥rö¯).^ð·—Ú¬[Q³%ÈØZû¸Íãk­57Zc+$&nÒþò‡Aå ‰¬6À¤!$B „@"pCTŽ“è¸Éø¿|›ÅOùÖÿœšüiÀs™,@X;UHõŽìÑ[;fÿÖ[‹í}µØ³©­9/Bù+‘êŒ`ÕÙï´aýw­ò¯¶ø"0úK¾õ§Lÿ·àpjI„™}Ù{^&—¬}õè×>ö™bë½ëEߺw|à§ÀÕí[¿Éб§œžô’ËZeÿfrýûº(î’ò¹;“þ߀iÌ6€-…;+?÷¨T–ÖÏ}óKãyÇ^PûÁgßÊŽROJº¦ÿÛn àØUGþög>ö‹nýáÃíù»wÉß{xöÈ›ÇZ™NrsJ¤Â…Ê—[ìDëû±¦õŒ=íÓDÏeL2Ü‚°` /ÿoÈóPJV¥ÁI+—ÌiT ag +jBغ6Ü%GêcëÎ~ûQ[på‚7½î“rÙGçuöíxìÖŸì×Zï·Fï5ÚnÛzßÝ›ölÛV |ŒÖ…&/Š¢96ÚŒ'ÆwEµÊ*%B ð”Ä÷}‚0$O¶º£û¯þÒGþèm÷ÜyO+ª6ÂÕçeÅüKÖ.{ñH=:6ˆ¢[©á Ž g£ƒÈJ FßGHåÎ$$RJ¤'¸ãîÌo¬\6B84]­âÜ"¬ÅÆ:+ÂXC¡ E¡É²œ8MétÚݘv·K·Ó!Kc&öï«-Z~LcÓæ;Zq7ó@´éÞö­&÷]÷£Æyo}SxôÿdùG¬ùá/s`{ôlzŒ'«€ãÏwòŠœ³öˆ_Y2gðt/ªÌ§ÖÀ›=od.ª>„Œªå!&r‹ œ,Ð`-h§†?»~œç{¼jM„˜Y~ Xû…3-“€°X¬±kÐÚeš8Kiwbš­­™±ùÎo¼÷Ú«ÿõ§·ÝòÝÇݰK6XqÒªÁ—üΟÖ\ŒïüÜø¿|›'OyÀ~Þ)àÙ€I‰OÀHàyG,Xù²SŽyõ)+¼jp ºÆTjJŽÌß³h¢RExŽqã˜m 0t>ý³5HiÙ1axÿ5šŸ£8zØ`ç=êÌ(“«¦>Øiÿg­‚Ó­-yžÑî$4Û&: Ý\³o÷žŸ>ôãþåÎï}ó_·=xßO%(:X´ªV=ýWþ·š{Ä–±/þÎ'mÒ~Ê÷\À䟀Àó–/8êëŽy˺£¼¾Z«,·µ¼ÙóñG框Q¡d)á…› tQ2]#¬S.û/¤àî–O¯·|î"I]eØ%'Á§”ߟ";ýŸÉ3YkŠÅZ7UXkÑÆMÝ8¥Ùj3ÖêÐI FÇ'vÞÿ+>õƒ/|î³ci–†€çÞðoþ?_‰ïüÞvoùÆOU|žËF DQ²ñØEsg½êŒU¿qæÊùo«U£•¦6è?{ªÖ@ø!B DÞ,s 7E)ýåÙÜ)ð ØIŽ&‚cæúTUÚ€”w2 ¢ÿkô_‚ußWÂM6R ”xJRU&Ú1•J¸àè“ü›‹¹ô’+×oø³kn{àún‘ÞUÿÑÚù¿ù‰äîï×&íôÝ' _&zê^¦ ë/ßtîI¯»híÒߨzkmµœ3px.ªÞ@¾ƒI–€N ÈV—á,é˜'zLïóÌÙ¾W§³Ù¼×ƒ$Gä¡‚CÞä¤\•à½÷Ö"„Ó °Æ`„@)…”)%J)¨ ڇÍÇ0s‡Îû­ËÎ>뤕Kÿé7Þý·÷mºkƒ¿wÛ†èÄ‹/ìÞüµ+Ë»ÿ…†gYèI=èuG,\õöóOüèÑsª¯Æó³Ì™‡j4P~€9Äm„ŽªÇ Dé’i¢Þc4€±¥KÐNÊ€aqÕÂÄhrf €4üïIÍ0©¤DZ@X¬• ,B ¤’„E f“Ø”tÿþðÌã–¾gÍòg]}Ë]¿âÎo}ݾðíw|÷j›us~Á øE 7Â2] |~óÜß|ÉñË>YóÌ"j5‚ùKñ‡†¾$C$MDž€Î@Ú’ñ%ó{§+%cA—¯Æ¸×Þßm¹"–f§Î²JcX ‚è0w;3(lù¢ïsë¤aÒ0¾ TŽÂ÷=âñQjFŸôªsNùâª#vÿóW¼böCë^ózqã¿$@1éÉ~æé€É¡± » OX%‘B …D*÷ú„4¾~ò-è¤`›P ¡!‚<XdÞÁjsðDõ*Bâv—Á°râ‡^wÑ¿ýõW¯~ý[&AàÖÀO#ž @@Éü½ø¸^Äm ¡éŸŒ!l^z„œëV¤6N¡›@šM1¿Çx©–üBb…À °H c k§4@!µAEÐMHÚb|Ò$G¦'ýýIœR–N” %e ‰RO©Ck†õß…›¡Z‡N yឥ¢! ¾çÌ@\ tÑ0¢!t›1A´æC¯»è«ýoW½áÎ-;ª> xº0ið )õ/=ý®^øEÒ’ÑÀþðžo!Ùï€F”ktŠ‘fŽñqÉ|­Ýz¾÷¨¢_í ¬PeH¢X+JæS‚Aa¤åT)éòè(ø*%—29"Ë™ò‹é½¥PJá)‰”îU)ÏS(åÀ1IFþæîÓXÈó28¥§¦²j„ðm9%XH'PˆpêÐmuˆªk~÷µ}ñÏ¿üW=¸cïöhÊ0|Z@ðt`2’'„Ôï¹ðÔ7]xÜ‚OqK†õ:þàÊ3ˆdܘrR¶Î­§Ð‰±Iê|üýŽœY Vc­ÆÚ8†kÆ€Fb¤^ˆõC¬ò1BQXKQXÐ9±ÌŸÒÞ• º)ÍnF²óqDš ”“z¥<<ßwŒõ|¤”ˆÜ9¡”t’¯<…ï9xÊÃ+ß+)á‘Û±ÝA8ußZ—÷ßóWh¨„ˆ0t¥€´…´àUfA-£é´º Uj'½ïÕ|ác_úöëwŒ·ÆÊ%b/ûí)àé€lAñŠãWœwé K?£ã‰(¬Exu”g‘É"m:æS:oòÑM ÓÅ&‰3üŒžñ‡‹žÏG[ƒÖ …Äx!ø´òÈ%sò"ÅZ‹!<”€Žô˜h¥fh-ÈñIµa†žïS2—dJáû¾ç•`ðñ+þ¾ iªé7¯ Ø|ÊSY8£VD8»ÀZHÛH,^0Œ­ØÂÒévX8Ü8÷·_ù¢¿ù_—_ù®\›Ì›¾Dü¹Að´`›e ÅËçý›ç­ùg_a¬{/ô_ Ç?‹óþ\Zà) d¾0 |¥ô[Î}Þï/¬ŠóM’Ž ãE>BwYË­³{ÌÏóRòcl’ù=©/ äÚ¢­@ûuLX§›k:­k^PÁÓ–"މãhë¾o¬pžbAaÙ\ŒÐÝ7†I r«hÇÍvOÁ“ª4üÔ¤µï)EàûOF v‡N«M½^§:4‚Ûƒýñ¤2À+mW)Q€iqvA:= @€‘·QBBÐÀT#t3&MºÁ.<óS[vïßðÀã{‰\ðÈ®¬ÿ9²{~n¬›ZÿÈÛ­-þô䕟w̼÷ÝqÂz¯"L‚Èš[ô1¿pV~çð’ßc|a /,Z˜Ú©4›1IT0…&˜ O2 cÐFL2¾ ÒG^H¶xsY2¶Íù–´!mµhf*ËéE¤H@)y€&pŸïÇ„a@5ªàíN‡¶¶ÌùéíÐ#« £ó.F'ž*ãXÒL °Eà¹éËäm¤øa¨ê£Û1C•Á¥oyÉóÿâOþù[¿–k¨rY'?+~nô]¨xÕÜÁùþú~Ê$­Šxø5Ñ“Y a2D/‹¿( N«ö{*_kÈŒu6aPGGuZÝ„8Õøae ñD“f¼«;E‘ÜùÁsO¹tA§ó ¯>‚ô¥›÷MR® ?_$9tÏüž«?Ó–Â*LuDxLL´Aú„Q•¬Ý&ét\\ÈŠSZà ƒ S;š­íÝlïÎfkçøÉ/\fwíóî~xó Ý$Í­ÅÈm÷ZÖß nÕ®„’ª†µÙ³†jó ,[>2°âÈ9ÁüEWo?Ë },ÈóœX(fo¿ƒúîÍQƒ}-jjõ٘ζÈÀJ¬o¦ù`™s[KÊ97•‡0*oc½‚ЧÈ’¤ÃùëVèæûÁ}Û÷<Ô7ˆŸE <é¤Ð—¾÷Kg7•?J´Zg²8Ÿ?¨ôÃ{ted¤V [ûüSÌO9¯±—”AÙÂæ½LWgðˆ$‡vÛíºIòµ[æÚ’ S¢]Xší„0¬‚.èNLg¹‘“1¢¼4­äÚ²;Λ7“­[Éö½i>[۬̚_­½â#¯ì\õ¹«óÇØXNÍ=‰é9  Ë’€ ªúÞÀÜ%‹,Z½vÙÈñ',ô-U* „ ¨ÂW|š¡-÷Ìš_©¦1Q ¬D¨x/ñ=‰w(P^Ýó±•Q¯B-ÂúH‰ÁÃxurY#5n­Œpÿ–]W|ô‹W¾Å£¥ó ë­}Ò£'€×ÿþ—ÿ /|ï¾nÿšÝùК÷þè~kŠ¢>2gÖo½î¥Wß— ¯Ú:x»cŸS+{xcãŽ2› 4ÀD–;ƒ¯Ý™rïÎÄ|¹6ä"ÄT‡™H2:IA%ª’u;Ä­¶“z#J ¸ß`YaÙØJwß=Öytc;Ù[ÛRPHH tŽ}ó¿ARt¼ü/./Õž.ÃT Pâ$É+ÀºÃ×à{P©s–ÿ¼• Î>ïÈÊŠ•õ>t+˯ýTèãKKT© ¾´ ×+xI•u <ñ øØjQ¯AÕ9´¬Tá£UƒÂDĄޠ:h>ûõk^wõÝ|Ûù]-ì“Áà¥ïýÒï¡þ¨’_òϽçÇà ÀõÖÚ?;ùˆ7¼ÿ…+.7iWµ†ñßæHîŽæÑVÄùâ>Þܸ‹b?t5¶;ã¯(š¥œ•™62BW‡oÇ$Z’‰qâ8!ÓbRâs Z ´¶lngûnÝ×z`c;Ù–CÛƒLB ÄFÃS_ñâêIŸÝùÏ|4Û½»oý|àò©>–GT,D" áP æ}êº5GŸxâÑÇÜûC/쌢|@/-aàQ&G#tƬ¡^ÜÄË;øJà+Ú‘¤Ä†Óõ*„!Vy$VD^ƒ,´Ûy8ÌöÑöíð_¿¬›å-UjO(݇Àïþâ± gEw7_uù§ÞñÝ’ù*±pÖÐÈ>ñÑiFWo¿›Z¨ñTLÛHþ£µŠ›ªë0q—·èëxAztlÖ—®ÕÇ|ê·äøèúã˜,AHw|Œ$ÎÉ­ +󳬌Å:½ioëþ{ÆÚ2hú èm ¥aßòs^v~töߺñËñ‡ùæ;n”SnÔž?}2¨€ì@P2?*@¨uí€-ä’-\wÌHmTO¯ –À“Ô‡‡Ð¬N™5ØÀKšøyß“ø‡Z”s?•ê5¨U°žÒs®m¯FA¤Ñ.ÌD7!-aÒ%Nrr#É ÈLi;jÁ£ÍxÏu»š·îÎò>¤AÉô’ùãvUNºä%Åozk~וŸÊ7ßq…œJ³ê?&CM} èi •ò¨ @}[fâ¯lÛuz'?ñÜù'×C©¬µX%°§6<ŒVû›mæ Ph:F ñ½Q&«„RˆªÄJ‰@ u‚R~à)YžráikßñûúN'ÍÇUiß<ƒðxã|YÌ NˆÛÿQ2_BçTÂáßùÂåoó”¤îIüáùØ¥GbO~1zçCÈ®cáÿÍ'ǾÌ÷v¯á³Ñeì[¾’×núN(AÈm{Fœ%7S¦™æÄ™! «tF÷“¤9™‘äÒ2(/àÖ}퇴gâöÜÚ‰ÐI|˜šöY[òâ7üª>ñWÞ7vëUÝùÁåŸVSÙ¶ýŒ?pÙÔ¯úmþ© ^­ ø0h »aoûÆÝ|ïË–¿`~Íkd})(ŒRž…–>c­ÃAhH] ¤À“3ÀEHI3çò”ËPA41ž_'ð K;,™;rü¹'{é7n¹ïKUwÏýî!é™ ÛG³pÛþ|h¼oíœ;¬Í×½ð/›½rÕñ_R‰aQ:uH]~\ò»Øwÿ¼æ¼dYÁ统ÅìÙÁÎ~ßý´6H]¸¹ß€‰Ä:qNV‰'ÆI“‚\—Ì/CéÝÌÚÿÞ1qÇu»Çb¬õaØ ì´ð¸…GüáùíêKÞ÷{ƒç¼á}Ã[ø±ö¾ð1IÉ´ž†èà€÷IùÚ-ÿÞîÖ°ØW^oGÿ!awãvÒû¿¼qßw6N¤û¬îª‚´°tÇÇð¤Gj$ÍnŠ­‘[gÃ"ü1/±I ©+}Ö"¬AèI†ç+rLžrþ©«ß4ä{CÚ÷€‚‰Ÿóýlñ¼úùèý ðOÖÖ]úò7ûQ…JúR¹X»D”E˜Q³^x% ?ðiþôyÞT}¿Ñçò±73êãe1ZUȼñvLUI[-’nBnÜœŸN껩µWeýXûšÒ5hÚ ì6 !7ÇžµúÄ÷þÅWFÖœyúÆo}á5þÇß\¹DR)n~Ì™²zGÞ÷š—ßë¢S‚gwݽÀ`WyýÀîÆ÷¤Å¦Ý4z冱d§Ñ=»EæšdlŒŠÑN5±˜Ê€3fgˆ|;P.rlš¸ì(£0Hâ)‹¯,6OX2wø”ÓV­8+u¿ô±î rÙ €ÿ«7™}-½·›™5彈ôšç­9uÎړΔ øžç2e„˜9wN8îÔÞõ7¼öwÞÎ\´Œ‰ÕçðÆÛ¸iàdÂ(¤Ójãt’wºnÎ/Õ~^@’[¾¿sâ–{':÷†ÐNwØbà§µ¥Ç4ŽÿíO~²ú’÷ýÓ®ýÝÇ:W|ü¼î­Wüga¬3»·ôë÷œõŽÞÿé¾ï–L¤%zša §z@Øì`¬Uè_Û2ú½MÙ^[.Y +H²œ¤Õ¤VkwÑ^„ö"rmЇÔQ8{ —ç´€EØ% <%ðt†°V>ÿ„£5tK×I-p8ÖŒ"uc}Ýy¯>v›µÀß}à}¿êލÈ÷}ߥHI1Uªu8­3w\¶‚£¶íæo¾&øJk·m»™¶od~Ña³å$Ò!ä¦Á÷´î¹g¢s¯ï¤p¯†ÇAŒÎYqÌœÙç¼ê­û{éðÒJsÓ÷¾ûÁ-×åïÉã´œó\æý¬Á’ÞDSþ‚ž q ¶˜Ô">˜Vaì×·Ž^ýkGÎzÙ‚š7“$Ý/ ð¼ˆñV̬FÝÉ0Æ …˜yih ¢(°Y ¡ï²ˆ ÂäÎ y–pÌÒù/Z1ÖŠGwí$˜n÷ÌH‡ÀøÿýëfÍ…¿÷§ÿû??µ0}lâþ›n}ø¢7ýúÅJ¢0Àó\°DHY¦r»ß pÖZ’4cÎp?~ÃI\uóc|q¯fçq«9qÓ5,ÙAÚAP¡áÎÝ­GnMnô` ![Ô†Ó«O>1Yrêi³;ñùó‡}³ùš>ó×¾÷×Ùö ?•S\O¦žjÚÔê×= }ÿgÁu Û•¿¹eìš_;jöËê¡ðrã–}I³E}ö,âÌÒ- ÔÉÓ&R2s¹—Ÿææà»,%#J-€ÂSnu0И=rÒÑË^üЮý‚©¤q¨qxBGй/ý×¾õ¯ù·#F`ÏX“jm˜sF˜=žç!•,/ €¼(H’”nœPhMsll原Npýý£¬0{9ºýáîmÔL—ÝÍ"»3ã¶ý6l‡Cs«³W®š³0<Œâ IDATG-^ðz ¹)@»~I‚”…֮§@a4Y’0¾yãV¦Â±½mùýÙ;Ïvê.õ…] ݶ6{·w²Má´‚"ËPB‘å¹kW<Œ`§BˆÆº0m¯‚pSVS¯D³–ÏÑS"úĵÁ%i˜>pÃÍ' (%ªÕù‹\¹” ü0ÙDf:íc0¥I›¥B©r9è|FkŒ±¤­VÞܶu‡rƒÕ-^ø¶½ÿ\þõkˆt3hmíd[­qÚÜâê¤eYö78 YK¯ÿ1e!ko6„Ñ„žô.[±²˜žù<€jU±íM·ÆM-@Z¥*¢60OI¢ üö‘{ï÷ým7¢|ðfÏA-9¹h%bþ‘°ðX˜3c³E+\ÇL„òºB”SƒueÛ¥‘X$q[L%W˜¶ý\dc, ü¡ ¢6|ÂýÖêm{›Í8ÓZQ¶¹3“ˆ=ˆM3ܧ€EJ§A  ð„U%k3pýÉyœžýtàs@‰¡ªc<}6èmFÝëY|h?{ïÕ9~0[dn'Ò´ ENž¤±1Æyf‹¼ÞŠ=xÃzµtÍ‘§Õ­{FÇã¬(èïk{Ï0-äO-¬q.dk±½Ö«½‹ PR)Y·S÷Ô;ž(Ôð\¢þ´)!¤ ‚Z}DPzXËö³ÖX”riöŽ÷â`¡9ˆÜÈMíŒS–›YKÚi5­Ö¹•>ø£]j`îá=ë„·´F÷˜îÄ~õyJmÇ㇠ù ˜jÓ>ýt½Àj÷0•@*èu|E ð½á2ɳ?rÕÒç:zÏ" ˆ¡j4ì4$ ”kG«¤ÂbPž‡@Le]ÍXCÓG}~·¯¡ÁJÁè¶-­›XShþŠ‘þ32 ½õÿœ|É[¼¥«Û,Ýa{]¸RûÂå¾Ê™J\K”ŽÊ*¢^>‰ÂÙ•ó*þ\ß5aèÕç÷âׇN6xîP?˜= b`áÂEÞàˆ§eóiך žò&Ëì¤|ù·Óß;ïªu]T¥µwÏX ÔÑšó¦[îëÿùAXo­]'„¸yû†Góû®ýg}þ»>±%\2,ËnWîB½íU{gé… xê¾ÿ””XÛC¸EMþÝ2xó#%Öåø÷ʲ™Êô¡~÷ŠH< ª±pÑ ¯¡ÊíådYû¯¤kI'¤D*UN‡ç.%¿L¾1Æ’g9y–í.Y … £õ´ æCj€uBxÅú+¾1öã¯ÿŸ{º•\)5™ŒÒÓ6“¦ÀdzØtLê< ÒäøžBk—^¦„¥g u_ÕæGÁâÂý¤‚']æü,¦iÒoÁ``ÞQG¯DyS½=WÒ/Ë÷½´»'y5“s¿u &Z“&‰'Æw”LÎPÁR”¿¯ÿw‡Í jÅ£?ºJløÑ×mPÁ"óû]“íÛgîwâ¶ïPžÂXòU9繟H ¡'X\ VŠ©Þ<=ôÛÏE ô˜¯€À€j4êó«G¬\¡°®Ó¸R„‡5†0 œ‘,„K½Ÿ±N¬¤ìÔÜïRðµSÿããí]Ø hT"ù‰§f[î¹¥ÿO+ gùæÂJkK€s0¸ÉŒy$(!&#ð¤3•òœ ¤ër(„eE=Z 1l\­]?ž‹SAÿ FážÅ× s̉ќ¹‘'¥k7ï¹fÓFk¢Èí¢”‡ʵŠì¤3ÎöYþNýZ“kCwš~FQÅášó.Àš?Ùt×ýýç9\e¬êmûk¦:iH¯‚É{ÑÆé~ŠÉ}{ý–bOÂEQàYƒ§Ü.žï£òUj!`VÅŸ³¸¬|´“n\;–)<¥®Ø¿$êo:X#Z|òº3e¸,kÏí5 ¥Ûõ$Œ¢²LÀ=”ŒNùb¦¶µwª¿(4I’"„Yðò?üƒ¯´ÆZß½vS%h_óOï>èGV;F›{š©Þ$¤ÂXY&/ôn£ÔpJNE©´H,RçDOn ‚0D•@ 䊑ÇT<‰+A4¥ür*¨Ò;sÎÀ+<1egNz«‚g«˜\ó[Ü^ÉH¡8¥fÏ;aþÀ™µjHDaHàûX­i J@oƒŠ™h÷JÇ5ÆÕVY^ÐÐ9•J•Nstgºsã=‡jõD ", %˜fQŒÝ±yÏOŽ£»kŽzÒQ]¶zhþ½etpÕÛ¹hUg|ÜìÛ²ùæw|犓‹±ÓΈÆOoè6¡ÔÈ0¢ Òfß/ŽàÊíËÙKÎ?e'­ZˆR Ít=ÛÿÞ9~liüeYNšfd¹æ‘Û×ßz÷úŸÜ2{άê–|QcÎ¥¿û³NºäÕë­½æÀs>™C,N ÍD^Œßô讫Wž¶l­ÉcWöUàÜ‚ò‚ÀŸÚ!³O €¯&íP­W=Aª ¢FƒblÂåJ•‹‹Ë¢š¿ôÅ ‡ßyåöѿʭÕêà.ßpp³¦g”zª'¬5Äì¿å­éò3?zô±#‹ïºíÁ[·|ë Ð[ï½mßöMûN‰Š /8räm•ÂÇ¡„i›å~l?'æ?bwýT¾rlj|äQÞsÙ*.^w$ªR=ô•Ë@\¯®¢Ð®¼>Ér’¼`lÿ¾æMÿüO¾{lÿ}Ãè=ÖŽŸûòßûË‘³^þ×g4FN¹¹5:Í¡öd0™Î¬ øñƒ[¯}Ù‰ËßÙP~C9R¤)=F¢Œÿ+é¶W8@ €û“ÚįU"L7Æ*ÙËt"µ°j¨rR\ ½ó{;ÇþV;S¡Ç+")ÍÐãÑ3FR)¼.9eî/ù»ãÖqú-7Þû½÷}õ=Í›®»)îvÈ`è¤ðå/?b¨‰r÷Z¥,^bÃŒ¥æÖ#ŽÚ3«Ò›ùÞ¢—òÏßÍøÉõwðáÓ|f=ïdXpìä5{CØKÍ›\úš4/ˆ“”$×üôöÛnjŽí¼Q®DNB W~:Xù‘7T^óñµÀ]ÓžåpÚç°¸˜ú±=cܵuÿu2¬ ñz»¹NnÐLžWnvðŠ@ Pž@é¥SF5:q›hp€0ôð¤ÅW*<ÊrâìÚ9—,~¯/ÅüÜ…ƒ¼D|Fs `‚G¾ö}ZpÙ»kUÝ|Å?¼ªûµ?yå†k¯¼.év9Ì9y¨òòW1ëOj¨y²|é4_u`¤H©ù‘'Èò‚¹*æ-ûþƒ÷ïü"8æCWíç†|þÏ[áΫ] ¸€^n¦‹ø•ª¿(HÒŒ8Í™˜h꯽êjë æ ÐÔOdwkßÞ;ªƒÃgøLOvÓ([ž¬( »ö¾Íÿuæ‘§^¦Ô”1(,eч.“?ÕŒ¶”¦‚(Íå¤E½6‹4ðè¤ •ÁaÌèþ© —l̰œ4»v^EÉú÷wŽÿíx¡7ÓÓÇ&š©)BôÝÿS¦ÆŠãGäyïüqÕãc»5Én÷ËÅgù,1Sý{û÷è×? Dùð6\¶vÙIïú“ïlÞoùÚg^l¸öaöaQA ÄÈE ÞqƼƯûÊ:SÈsÒïKK¥Ñ€ Û,jàe”Îð|×Ð"@FÌ)öó—ÅùntŸ¸Œ- Næ×vþ;Ë®øüèrÌÊ3°Ç_ˆ^´†DVˆ‹.$£Ùér÷w¿ùíÌšf0U[99-KOñvîíô€Oè ìw ã6aÊcc:ߺýÑ/g22Z:Ç.¦:[ÙžgÐ÷œAèy3¦Œ)ž'ðL†LšÌh`ò-¡><ä¶]Q¨²Åªʳ,ªû+^½|Ö'ΚÕxCTo,- fÝ”0€s÷I3e‰'yô<Ž6Z¶vyåÒ_÷趦î|ó¯ÎKî»öú°ÈÀpѲjpò¯9ûoÏžßøuϳx“-aÝÖ1µzU©Ð鶘;X#° *ï੃ÛÂZáã ÃËö‡Ït?Ï[ç]ÑosÃðùظwÏUˆ¯~ù…÷#®½œ|û£üí]ytœÕuÿ½÷¾eö$Ë’-/`pÍ’˜%l@Ã!KHš††¤íiš¤iÚ&§MNi¶6tÉÚ6 % mZ'4Á6¡€±±ñ ^À`,[ò.ËZG³~Ë[úÇ{ßÌH–Á66%œÜstfôi4ßr×wß½¿[ ö=»cg߯uël­õuˆ¶íÚ:;ÎïʱaL"öÙÏ~öådßýÜçš/“2À92Vº°»sñŒ\¢[ò®¬©|ƒ( ÞÃ6Å8xãÖtÒC„€RH$R/—Á\®ëB¾þ^IC‰¶4®ângw÷R÷·ÿE(->x„+À!]Cs…1™ôþ¥˜Ï$Àç,h¿øcŸ]=^(W‡þûKo/|q”`gqmGúŽ·ÍÌ}¦+eϧLÁ±´æ;Æì'Ò)°dåZm™’T€Öа™ž6u B@,loä»QKäðCu%žãX”¬"§ªK%„‡zÁŽì=Æ—ýà?¿~l``§Õ@Wñð-JÉ›ÞýéùÕD×]åŠ×n¹¸™N¶ÉÃ$´f%j@üй×}îÖ+¾ãø×lÆaÙ0(—T¦û¡ž:A4é”REðð"–A@ã(ŒÃ‰¥` …Êx—%AÈÍá€ãÐM·cdÁzU íݳcßêU <·ý©€ócÌX+Lt ÍÙ鲈u!Ð)n&Ó·ßýß]ùyCËî¹íؾžaé$%í‹s‰¯˜–º½+i/ Ô˜ühOƒj@èX: £R)¢-“DÊR Õ1ØDÁ²^¢Ø“R(ˉÇ@b:–z<\ˆŸ§nÀ¡šƒ[Ô³x«»¶D¢kŸÝóØ=Ëžø"Óº#ÐØJÞf¥|ø;xDñ üÉ=xÛäSêäÐ(ÄwsßÑ«wüâæEmïáe*„®ü%ºÑAƒyk3JŠ‚ÁIÓtn Š"ðJp\`zKƒ…2”å"™ÏƒÆAƒÔÖÃÊs—¼ )?DàØp.ZÒ>oþ’уûwÚ¼iåà ;×”í@™.5ýx¤±¬ h²žÇ·)ü®w~ø“ÃÉü%;ïû»wБ¾J‡c]|a.~ýâ–øÛº’Îù”)Pª›YTû{Ç¢HdsC¥R´L KVÆ`QöRÌ'Êʶ ™BnˆõâR>ŒïûKðTþ¬©,Äeô.ª •—­Ûù@ 2 ÊŠ[”RWuÿFKÇõ¿ýÍjfîEà|é”§;•YÃf;±î‰9­ÙE_¾ýºûZi­“…ØaÙ&›˜ù6Òà¢z>fô×ñmRé?…RB:ip'‰¡B!(’±‚r ^¥p ¾ï/1~Þ¥KãBŽ ð¡©Œ)ŽFöõnÞýâ3…k¨ 7IDATû·û”aX •ªÀìT@{Ô{*¨Ô?AbÚÜ ßøÉ¯,+¯øî¿ÙÛXÔž{ë9I粌Ër„èN§ˆñuæCÁ‰Ùˆe²ð•„ð«hϦ#´Z€EµæŸ0ð2jʱAb.”ã@Y6$eнJìaçàÇ•EÌwc¸¢0~¸o›sø™_”öî\ÞÞÙQam]­ó¾…w]t[6É c…êï­üƇvNyÊS€ÈDÚÐ[µÉ ÿe‹>ð‘7/ºKUƈ#=ØThè¦+‚a ÎÍü ð ÒåñçÖè™ÆÌÛ1ˆX…²’"™L‚‹?ç| ßq‚Z A CøA€0ä89B!Ì&†‚W.µñÂÁÊðpïÈÞžÃÜ÷dŒò0(‡µj‘ ;‘ÌÆû÷Ët¹q)Ú÷.ýà ó3±7ܸëGE‹YfQ€(]ÁDE,6É[ÄÒ)°D•j 6•hϦ`…UP¯ô2>ßúe”g]¯0¦µ>ätÚl‡†\Ss3›@i7@©A&B))9¡„1fÍZù*ß»ƒ„s±âÂ;pí¦ô`ʲuÍ«žÚ¦Ë ã-¸±Üt j^¹¤‹\ÌñаÂ,Fu™ÄK=XÆ l Äu¡\[‹µ,(¢µŸK†@Z¨‘üX‚9ü+÷?ô·ûúv,7´º/juZ¦wÄãv­¸o׳ëö›f†¼ÔyÀ5DÚ1AT`D«W¾lÑ¥HV*ˆÏœ‰J¥ŠñÂüjÔv‘N¥ ¤Dpa §“>ù‘L,j¥ "@’I G˜iÃy#G 8¶¾vÛ¶a¹.ˆcƒ+…jà)‰l2†”›å5r ­I“¯ûÀµæ;¶ øŒæjæP­ý°áÓd<‹B©6öí‡Öük)Ýv¬uÊ2§ë€ûBh Y#J±ûVmûîìiÙî%ékšÉC nî×X"FA38×'†)„€JšÉ‚¾÷ÏÁ\ahƒs–N!™LÀ«y(•ЍVkPJ¶¸n ÔX®sçR@ Y/¥®[JA¸¤CP%ÐÑâbú1ÀgÛ±„”ðxåUàPŠÖ”‹¸er¤2 &,¦{û_RëF´oÙ ®6ùÊÖŸ" RjÍ`ã p7ƒ@‘ð_\õ­ÝÇFŸOjH½4u2Ûé´` WP³Vôƒá¯-ßôûÞ«;f%S ¯d’ÈŒ)=] z‰¨ó  H`¥ ̈¼*ÈÍ6o ¨XÌçVÝ×3JOÄ ä|ÕJ¾)0ѳyܘ B;–| ´PŠé–މ$ÆFô>,p€p ‹Q¤]I7ýÅ¿ú­+þ.íÚ9½2ÓÚO A"tK)!…åC=GJ Z¹ö½ÀŒó&œ”¢§—0 [ZÒ†zÞT»®•ˆÊ×õº4+Ùla *hIǰÇnEÚaèlË"0H×('  v¼ŽÞñ²¦¾q±QY4”e–w6ƒ¢L”€hV÷ù‰! .uðئ+þý‘õß§À8Õ3ˆ"í¯£¨Ÿªéè À$W!Htc_]ùôÿôæKÿ&“ŒgµêsXD 5Ý@QŠ˜@A “5ä}txˇNx~ÝG§{é,Åt '¥®—3íRÞyU÷ÿQú@HáÉ«°m©lPˈc:à› ð±«h§ ` ’é´¡²¢Ñ¯zJ‘&Í—ó]Ê”†í=«ïûåS÷J¥Fì†æ7ÐxE•ÑgÂLèÝmÐ'víR‘?¹e鹜›ƒ¨#\¯ÂY”26†D)©µ•2ÈâëA§Ï9©òBˆi6¥õ¶)i‚=Y˜óDOMÔ‘.O"C“ $ ›8'ƒ‰=‘¢B5S ¥¨f¾²ˆÙW„BQƒ¸©8„² A Ö>½ë±ï,_ûm/䃆ùE4ü~sáËiÓC‘+ˆ Ñk q€¬Ù}à±çÁÇoYú]Óò3á$  ÀÁ¨2Ýdêˆ …b)¨Ëß¡"E3çdˆ€ Z4:ÙZ¢÷pS)T«0 —‘ö©?B4ƒ …bD›yKk¼2X õ¿+¡8,ÊFÈ‚ *Y·í¡ï=¼þûR©á)˜¡©¾b:“4 N 1€¬ï=²¦²lmõo»âÏæÎž~Jg; E$$(Q FHàó.…šq D½¤ <é”ÕÓ\ÓTÿW+¶™ÌÂÜ NæñHÚ486!´©[:BÁ€ÎƒHB¡'ûPItžŸX$…_ P+VV®}úÁVmY¦€aKÌ+bâȼè¿âR·³! ¬×䥵³xË—~úäçÿè7ßøÑ‹ι--‰Qzb(U JBÙ1`áUÚšJalj6çB¦¥y|Ý+¦X Š9ÈZ ˆ§t1|¦þ~iü¼~mÚ)Š ÐL…Œ"D7Ö‚˜¯^ïsÅp ðJ::pìG¯ýáª=3=fn*æŸÑÁYgZ€†DÀÏõãq@ß}÷OŸüÒû®- \~ù¥ïëjb¹œé†1õ2:º¡Ú»Aü@+Ru&+BtÀ(UÝN˜ch>wJBAO¢X0 è„;Òžƒh´Üº©‡îˆ2­qª”Dðy MÌWú½Pšù~͇_U{{zwß¿bíŸ=8ð´ ‰f~49­ÙìŸ1ægG€Æ6_° \@Vü@Ýû¿›¾ùhmº|÷•¼ÿº`©éÓaÇRzæä¬%a`2„ Š6F£j³:gTCêý ÀDë@H=6˜@„èA,;›AÖ')X½*Y™ÏÕa Ü¡MÇ@5kuÆëã‘ækŸOµ¯/•P:6è­Û´uÍ­Úüà±Ru¬1-µ„¦Ò.œægO€ãÝAtLZfZÚþuç{—,…¡io©öäã3çØNKH¶A® Ì÷J@©‚¤‘D¯¢/;Qî%ÚúÅ_šþɲ@ËMâPA"ÕBxBhæÕáZ £µU’ýÑ«€&+¥]–¥×ú\AµtGzûýü‰MËf׌æAk}4=¥¹ÂùŒ28»/Q-ž$€°UP«íxôß0ç¢÷m~ø…w^3þÁ™sº§aé[Ë…â’R]FÅ"£ ÑZ· H½´§AdâeLøu’Ä(”‚»)¤s LÏs aiëyËRg²9OÖK ¡5ߘ{mò ÂÀG06Šâ‘#Õ [¶oüź­+{Ç^tŠ­™_Äñë|Þt•gœÎ¶D­šÝ$@Líݸç_{õCû‚mÛ<òìm—/úàÜ̼ëãmçÑié⎥ CÕ{ Jê ZFb|4½y^Rã†Î½ š^›{÷)/Éý[Ùò¦[o<°â«_þÚÊÍG/èY}ù‹}ï9÷úß\Ò1wò™⎠p¥ M)1гԴ­TQöMŸ¢y, QS]Rô«Cè$0\­!•pt^ภiúÏHÔ̱ÈÔ©”T}Aa µÁÜ»÷Àãë·=±fûî§ ~pÔ*LûùÈ×Ož”eøÎÀòæÄôjY€ˆ"!h¶Ì~õÿÄ.zë»2‹®¾ªºkíª»{+{¾ü•í<¼üM—Þòö·Ï¹ê† ;æÎGkK)×Ö[ÂLÉ”¤©k„@÷ª›©æ+˜bu@•ÀXh#—èÈ% ¬æ©]õœñÄ›©3]k=Ñ0-µ2±QTŠ{÷Ú¼ý…Ík¶ï^w¤PÞïµXc&rdî›ÛÚ&w:Ÿ5í^}7Tw 2¨V¿÷¯Ó7üŸUP+û½O?á–çv­ØùÜ® þìÒÅ7ÜxÓ¼+¯»¤sáùN¾­-©8\Ë2]ÄR5æ7–ƒh¸ÿºGSôhÈ©ô€Ñ’€‹CÙ´©Ó©þAó;1BE¡ ¡Ùy€Çá ÷cüh¿ß×Ó»oýÖç7nÙÕ·e¨â¡@%>õXÜ©½³Êô ·~š›HÇÑÒ)´êåÎÝôJÀÝÙK§oþã{ü]ë)¯¹ÿ' È* ê*ÂÔŒi­ Î_ºôês¯¾î²ÄìùÓ»f°®®éhÉeàØ¶UTuW1> àQ· “¯€"1z?~ìyô s|æ¦.Jo%MfžDQ½™zêûà•"‚‘aTâØÁƒ#/ôô½°eWï3;÷z®$äÔ,­åÓ'3¾yCç´™¿ù4ùøÿ)õk0¯TÂjŸÝ–¾îƒŸ!¬üä¿ì=J€V¤8àJÀnKÆ»oþÌ]ÿÈRé¼ë¸Èæò˜6­mímhÉe‘J&aÛhQó]Õ‘MUóÚÑ”PXÇðùŸlüΠ>te'®·#>Á9d@xe„Åqðñ”‡‡ÄàáÃc½ûï}v÷¾»ö÷??X¬ö‡@É:‘ñ‘onÜœŒvrÚÌ8]øÿp“©ž9$åC† ˾ð±Äeïº5ûöOÞé÷mÛPyê'?W^iÈZ|Ài[táœK–ä}ßG¥\F¥8†žÑ!ôì&°É$òù<ÚÚÚ̵ÀµmÄ ®cט jÖø„J kxá˜7/ ¨ *5„ž^­@yå"Ê££þØà`ydxtàžƒ}Fúö>¶w¬â ù@ÑÖ ~L3¾yþq¤ñѲNbâNÞ«fò'ÓkÁ4SýK$ œŽy­ñ¥ï¼¶Îº$èÙ°Åßñ¿•±ÁZ*vÉ-w|è—_sÍõ™–Ö”Z¬æy¨V«ð=B=;¶ïܶuëüçu¦§wåã¹|ÞI¦Rn*m¹É¥Œ2'µ,Äü"žßºÏ Ü‘ÜS&a­Zõüªïù•R±\>Ølp¨P-–*Çö9Ròü±šT% xŽîAôÉÄ™ÇQ4ßlæ§b8\9Üï[tz¾£ý¢™]—ÌÉÉÂܹ³Ú§µæóñdÚ.Kø—O}òSGûz·¦€,âÄbqPêä³™L"îÆX,AS™„”JÄ©Lÿâ÷ÿ®Ú¼ìÇùí/ö•Ë^(<(Å¥TÔ¸ú,,i£ ;šu™öèg*¦ŸqÆGôz€ˆ&%ö‚7]D“ùEJð6ιçzʽ{¹Üì®ënýèÌîÙWgÃáõOÝûí¿}_°Ucð“¦ùÓ„D•ŽëïøX,×Òräg_û'&PÅ Ú=E q<£'3¼¹X£9ÿançÌÓëU":.ýßôB[QÛJüá·×T·®xoùé= È3ܻۚy~‹ò*žß³þ¨¬w;W­–ÕññÁdšœ”™*IóšÑð_ ÀÔ”òq“€¡W?ý 'ÏÈ× Ã'Óë=8-jIéW¢cS”œ^³ ?StÆ,À¯éW“N¦ñ×ô:¦ÿ–ÂZj‘IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/inbox.png000066400000000000000000000105731217176075400237220ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞBIDATxœå›[seGuÇݽ/gŸ»Žn#it™Ñ@á@Â%Æ ØP…ÃÅI€˜2¤òòÄ U$ù!߀—¤R©J¥l.± I€@T031…Çž<Òh4ºÌÑýÜϾtçao9’ÎÑH» a©öh¤Ó»{­¯õ_Ý«[ÂÃo³È·[·[¬Ã¿xöÙg§^zé»mc´g@¼J=”öja¤­§Ÿ~Ú~î¹çîtr€×¯];_.—캮õÿ%<„´ÛíàÑGýÀáÏŽ ¤ÊkclËRhmøMA”‚J¥íLáðçGØÞÞfwg‡lÛ&Š¢·^Ó·@¤”h­ÙÙÙ¡Z«ù=Ûþ…B»®K½^çúõkìîîbYBüfÑeY4 æææ¨V«d2¤úp»žYÀu]ÆÇÆ(ŠÌÏϳ´´„!åzùuCâòJ±ººÊÜÜ™L†ññq¼T GèR×åܹsxžÇòò]ööö˜Åó<Â0|Ë9‹(¥‚€ÅÅšÍ&‹E\×%‚ž)­'#iY8ŽÃÚÚ*W¯^eff†¡¡!¢HcŒá×%2”Rìììrûö"žçqñâ,ét)_êô`_¤”d³Y¦§gØØØàöÒm*•*““ç;$óvʾw–—Ù(—addÇqNÄ[=0Œ9˜ÇattÏK³²r—ׯ]ãÂ… d3™·-K(¥hµÛÜ^\$¦§§) X–•Øa|ï%½À`ÀB!ë^ŒIæÆ ÆÇ'ÁÝÕþ­Œ “ävÅÖö6w––Èd3\œ¼ØqùÃzcú’wè ÄÜày)&''I§Ó¬­­R­V™œšÄ¶¬$$޾gýp\6Ù÷ÜÃ0@ ‰6†»w–ØÚÚbtt”áááŽË÷ÒÙÄ.Ýs¬>`’¯¾*bÛ6ÃÃÃxžÇêÊ 7çæ˜œœ$—Ëéƒ!a hm5ô†ç¾ÁR€%Rp„`•”´Ú-–n/ééé Å–R€z[Ó_z`ݵŽBJ‘Ë嘾pr™…ņ‡G….Òša·¥ ÄÛqf’a, Žä]IÚêŠ]!PR²µµÍÊÊ]r¹ccSxé4Rt±|?}OÍÇ„ÀaBr]ÆÆÆð<µµ5êõçÏOâØ6Q¤ÑZfµÑD€Œm6Ú€Ö1B@ʆ”%±%x–ÀhÇ´6ܹ»ÌÞÞ££çìbyó y:Ö–¾Y@Ÿ€NG–E©T"•J±¾¾ÎóóLLLP( ý†±ZÕT¤!âÓB QržÂ³4. ¸ •E«Ùdyy!Ó3Èçr¨}—?¡~Ƙ؞Ð' ¾ïcLNNQ«VY[[£Ùl2P*áØö© 4ûY —ôÜ+vo†ú?÷Û…QÄ^¥ÂæÖ…Bééi„´Z-¤H)ûï)&¸_Ôh6šx^šK—.á8å{÷¨Öjíx·Ç>§Ê ý?ÿñÈA°»»‡R‚©ÉIlÛ¦ÝjÅè*•“\O願"yâ˜Â)$ããÔë5Ö×ïÑjµ( ØVœŽÛâ,pâu@òƱ$¨µ¡ÙjR«Õ(ò”J„a„ïûŠB€”qŠ¢)¦ÓMün»ÝÂó<.\˜¡\.³¹¹I!Ÿ'•òò˜Ž ¾ ½$:ŸAEÔªU@01>Žëºø~\tÝwÝûƀɬöÖíˆt<à׈dl!ãããÔj5Êå2ív;&ÈÄãöõì¼·Ïg']˜}ÿïz!þÑà·}¹\–Ò:ÒAØ·ô$D\cìOZ=B:{€ž~Îd˜™™¦\Þ`g{›\.‡ãº ]ãNǽҠ6šF£1†Ñs£x©abŒAªþu·nè©BŸšƒ”}LØzßÆÆ©T+llnb·}2ÙÌ]bœN±0]_aÐlµÈ¤Ó –0Ft\ñAéHNÔ®{t)ãío¿¸;îüC…äóy2™4÷Êìíí‘Íd°lû¾=§*ˆ$h´¦Ýn£µfdx˜L&“̺~`µµ[¤0ôK½ÛK¤”ÈS¬C¢(BJÅù‰ öööØÚÞÆR)ä6CaÑl6H¥<††QRöœucöãü@mã`@¨M¯Œwà!ÀR#…”º"ÝÕF™xU™Î{û:EQD¡P NS.oP«UÉd³§ÉqnG@©T"—Ë¡µ&êQþ6üP³Xn±S Q‚È`öÝ3Á©á‡¡”¬PGzŠE)PUøÙ/|~§ ,ƒÆƒA ( ©”$‹dÈØ–Á±–Ï¢(B)ÅÄÄ8»»»T*Úí6¦ÇjáZa;6ÃCCÈdÖ{ɾk;>/\Þáû¯W˜Ž­@Æe/¡$FÄ5O¿§ˆWt1 8z@/‡7ëçžÍwî5ù‘ߎÉUÆV‹ä;FИ˜Å×ÿÚ⣗ZIÔ!Óö÷%Åb‘\.Ç­…t=˶ÔÔäù.4ãxïÇa£ƒ†=Fß9ÆÊô"< ³hþ«€qU€é©°²!soHÑÒ‰[ 0‰Ä Ò)›÷~Ôf´ØÆq2é‡)iÿh_%êÒ쬣”uÄùŽö¼æßíþµÑ¨çÒ^ú‰ÑÑÑB¥R¡V­ö$>% keÃÍÝ‹Ì|ö3¬Óhÿ Ælq|EèT‚ƒÈ dìòtU‡•€”çàN•¼ýC~xk“Kƒ’ò/EQÄÐðR*Ö××çÂ(º©”ªÖjÕµ#À÷K®ë>þ‰?õƒÇÿPú;/¾H£ÑèËüŽø™Ú—¾ÀÐ3Ÿc9ïµé0¿ "Œ¢ýÓîÿ߉ö˜H#, R"Tü B©Øj%QJ’J¹„•-†®ü#îâÏ ë{è08Bpa2qþxýÆôj×sJŸ}æóÓ#ÃÑËåxåÊ”„aHpÜ2þ]ì7žgõ›ßfªÒÄr{nöNg¼€´ëî–)]ùgR˯ ë»íV_]¢(" C®\¾ÌÄù ñè{~÷oûÑ€0 ¿<4<”]]]ã^¹ aô}‚ Ä"¼ÆòÆ¿±òÍoq~„3oIȧ\Ú;eŠ/ÿöÒ¢ê6a«y¬.a"•b~~žvÛ'ŸÏ?õì3Ÿ¬×8GBàÏ?óÙ!­õ_•Jƒüâå—;kø|>bÕ TÙ[ÿ¶_J1ù'Ÿf9åá·û\ªè"Ú€-Ï¥¹·ÉùëÏ“©ÝB¦Òîïöûýi­©×êø¾ÏkW¯2{iVÞûÅúW/n~€0¾TÚÙÞf}m ¥Žmã¥Ó'® cH±½ú=¶¾+˜ùä'YtÚ~øÀª€6à(H»4v7™¸ù- »7Q2B:ˆã¯4ˆäÈ­Õl¡¤äæÜ³—fÉ䲟ý³§Ÿ~äÅ—^ºÞÝþ@üé§> £èË…b¹¹¹»º®K†DÁÉž0Œü—â—Xýþ2Þlâ8ªG8\VÛ J‰ñc7¾AvãuhV0~óD:„A€Ž"Ü”‹6†F³ÁüÍyÆÆÆß¾rxô„aøEÏKMÕkuÖ×Ö€eÛH¥£(YŸì1h‘÷—)Þy‰òþ›ñV ÛV‰q?U°• ”IQÛÙdtßøV¶‰ttò±£Û¶ã •TÌß¼‰eY¸®ûÅO=õÇSÝ6wüéÊÑZ%ÎpûöíÎzÚu]té¤!¾˜Uh.b–^`CÀÄ~„UGÑì “Ä|1ãRÛÙäÜÍoÙº~ tpj5Ä;J×uñÛmjµw–î084˜½³tçËÀßí·íx@†Ÿ³”z¤ÙlR.—øøÛêÌ~têG'³¦£|c‘â⿳õóŸ2!4®-ãÒ8"fû´K}g“‘Ï‘Þx ÑÚÄ­8¥eÜ(ıíd%)X¸u Û²QR~éãýØÐøØOJ0_MYkk«¾T7åi}ŠÙç¼—²õôßæž‘ßÿ÷lI[B:åÒØÛbäæó¤·®_CëàÔc)ŽãR÷kT*Ö××ÈåóC_¾ÉRøÉ?úð'A|ϲõz=¹þ&p]÷„†ƒHjÿÇÝŒPT³Ù}ççɽûƒTê­ÍuFßø™­×Q~¡úí”RèNŠ­5~¼Æq²Ù,õF㎀wÿäg?­Y‘Ö_ˆÚ!¶ã ’áµî]K?,ÆR–…¿Ù8¦ü%ÆÇ«¼¹ù<[Q@˜fxá¼3ß{Tc )/E»ÕŽ·é'(³ ÀI&RC¥ZA 9¥á‹À×ÅcïÿÀã~Æ)¯vuπњ|¡€’’jµz‚úŸÁH›vz”ƒÕÚA† dÔßøý1‹Ôëõ#›³¸>q*® x¯å8ÎßxnJœx‘“\Q‹SŒH¾KÂ(¢Ùlv*µè¢vå.F*„Ö£y¿Å^‘ÏåDGZëø #Òh¡õƒÏ´y¤Ñl>kÍÎÎ^ðR©xûÙ½(ÙïäP_B&ˆäÌ/`aajµJx:¢~d×C„ ‡˜šš" ÃѦF\¨Üwéþº´Ú­ß³ÖÖ×. Äûd’ò¤R(¥:3+“*Åp* A³ÙL*0ý*~/BJt¤i4êܽ»œèqÿR¡èªCž„„—­z½ñ¿t.ÅîÇS÷,« ©drp`ìg[–Å»yׯÖ<@]!£»ËËø~@£Ñ<š Žœ‘ C(¯Y­VëÕ^w~ÓMv]]vêu PQ1P*%·5ßü ÔÆ\Ž´[­§Bè"È$4CVAܶZÍæ¼1f:¶—~Š%Ú`dd„0ŒWbo…H‡çööö‰Bí@¦êÛø0ãú/_ýUúzýÚö;.\œçŒtKÛ÷©ìí¤õ"¥$ *•Ê›ñ'<¯ÀýÍЯ€Ç¶Ç;KKÛÅ$öÝÓË#Wà>¯¼=vÎàzrú @|,üð×àþnðÕ7£Wà­3þÍíûpî{Àð?@‘³ÞFüÍüt~q¡ÇŒü¶Èoý_ÿ ÎY…b%JIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/info.png000066400000000000000000000132261217176075400235340ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ]IDATxœÕ›k×uß÷Þ~Íswvgß "HŸ&™!JTlJV"+®$$¢¶œÊÃå/2+V$9¶lG–S.«Ëy˜²d¥’TL³è4IÇ´E‘& Š ø ‰7ö½;;3ý¼7æ±=³3‹H}È­ºÓ=ÝÓ}ÏÿþçÜîÓ=ÂÃmqàr“]ßõåŽ_1]î¡X—}䦛q zÐŒôÈQ0CéB CË}Ì ˆ³5#Pó ‚§u?&L^ï„äZi{·Ø¥òÕÎpy‡=\.;E×Éå±=¥$HℨîVkË+A´07-̽Ÿ,.Ö‘P _ØÇAT>lK?L¤!™Ô„·Znî¾üŽ+þNnçîmCÛ·211ÌT9ËDÉa¤`3˜Ud]…% ˆM-ˆY®'̬Dî™ù`êÔLuêÜÙ…[Nž¦~âØ©àäûÏ&~íQý¬@>xìâÃÈyqÿ6MøY¯<úùâu×Þ0¶oŸµûŠQ®Ù’eÏx†‰’K>ë`YmÀ4; ˆæzVkg}Žœ©qè½UŽŸaæÈÛIíõW†ó3"°¨“ðÁrÀ"  (i‚O¹Ãå_þ‰[oÛvý~®ß=ÄMÓ¶åñ<‹8(‚DƒÙdš”Ë[D¼w®ÂóÇ*¼ðö"§^}“•Ÿ{!\œû‰ûpÅ|gùr1\q@¢ë„¥~©|û­?;ýñÛ[ö”¹mWžÉržÄ@€Ö€éÔª¸d AJpPÎÍ®ðÌ‹üàyN?ÿB´òÒóÿÝÄñ8‡+æ¡KžI.™€‚8ÑŸÉNM~eë}ŸÞsíµ»¸{OžíE¢°áéîÓŠöÇ ¹‹9!ÀqÀ±àÄ™;´ÈÁWÞcöéÇÞÎþw‚ÌŸVÌCõKÁsIÄ’&øâð×?¸ë¾Ÿ.ܱgˆŸ¸riÙÔ}0ÉšÌEÚÕââžOïßÈ"Ó<·—’ˆ¾~ÇÍóþÓOU+‡^þ†ÀùVÅ|g~³˜6M@^<°’'ï½ë‹û>q·¼çÊ;· Ró!ŽšÀ ë¼¼xq1VLo2ZÉSYËÀñ“³<|pž·þæyþê/þØ_[5ß½°\›"  L¢_ßöÙŸúÂþ»ïàž+‹”sÔj ã5¹wê%û¾†tÿ ø®ýRB6KK+<üÒ?û2sOüÙ·ÑöW*› á¢×q `ˆ¾4ýÙŸþµ÷ÜÁ]»ñ<…%Hb:¬i°}€ јݘú 1- ÑÈøýZ/?™æG=€L®È§oP` ¯ó 3?¢ â/_,6$  ¸šà¶Ü{÷¿¸úî;¸}û (…eH¢N€iŠaÐjQ … ìÛ“Ã`)X©Á±³ðÞ…F¦ï¦Ç—Ö6cÀ!“Ëñ‰k§HŒ$©×¾8ÿÌSg âÀ7+æ!ÿ²Є÷Ž\í¿ÙûÉOªë'Š <—!£wƒî÷i5D1lOݹµc§†á#[áÕðô+mRl »Â£¥Žz“„ï¥Þ.¢…ù_Y>ü£ãqàö›"ûÿd_vlä«»ÿáÏ ^5RÀÉdYX6Ä!-Öɽ#é÷ð ÖPÌÂOÝÜP@¯¶¬Tá/c·±vL›=C!µÍ W(róŽêß»'œ?ó•`fîmà•^cvß’PòBñ¯®øÜgöï-3Tȱ´Q] ñë!Aà‡!AâGAá7{%øaŒ&ÑZ_õ>¶Ëôßj7í¬§©úšz¤ñCM=L¨‡Éºs¶Æj¬ÇøaDÝX\Œ(•†¹jë0c÷üý½Bñ¯ âb¯ñz* !¸kêÖ[þñôUûÏ;¬TBüjL™æIÃ'BŒ1!ÚÛZÛ;›@Ø>êr±ùÀµa|0æì|‚»A€¦g¯uëDIÌôè ö\Aåú›?¿ðâsÄÿU1uhhÝñÀ°W,þâô=wçÆ\E”@u¥Fä'`DÝ`û­¶¸¶»!øVsTLà‡`¯‘Ü|?2ÂLÑeÇP†Ù[nõ*G^ÿçq¥þà܆$„wmûÉ;ï)â)ÉòR ’ĺ§§{î^‚ ž+ÆJÎE ¸°E!"…³È‹ÅÙ‚ÇäX‰ùo¹}æÿ>qOAøã´ :È‹ûK^±xÿä-7Ù£©ù!µŠOX7˜^öÛW4/¾Yeï¶ ˜]Jxë½*:6„º?àÍl B0ÒcØ“Œ|t¿Z<øâ?Wj3= ÐD7ŒÞxËßS©ø•:q¯×½~Qr <õÒ×ïñØ·£&üî_Ì2¿TÇu:sE?À­Þo_œÄd .C¥W_sÛÜssðçë(ˆ–Rö§ÆnøXÖ cêIHµR%X]»¹Jƒíº×öÖz~û{'ùùûƹ}ÿ@ÀÙ¥ˆï>~g-“q$aØøFËn2Œ1„aˆQ‚œ0”®Úç-¼ð·÷ÄOUÌw‚4ÉÔÀ¶É;‹S$õ€z½Nme•ÈB ¥ìëùÔÑMÄÂbÀ×:ÎÞí9®Üš%ë)ÎÍ>¶ÊüJ„çH‚ üf€w“Ðîap3.…‘2S[î¨<¹8ÞA€!Þ?|õž= › ¨Q­T©U*˜Dw€O”Rö$£øôú¡·^~sc74Ž%QJàûë¯tú±x­u3 4FJÛ¥°k×îêÉû;(ˆR u}i÷.7¬†„5Ÿje•zµ†èØ‹Œ~!Эˆn"$4. L£lE›Þˆ~]FØ62ùéi[Hëú‚ügWô«á}²î@áêìÈõåþjje• VëÝü¥$Äz`´Y±$@kƒç(,KnèõôöÍtcY¸¼Òv±øÑh©š*Mô`v|ø 鿍׿¨×êT««Dõ:RÊà—BB7a¤ùÄm[øøÇÆPªónGÁÜ’Ï?zŒ¹¥:–z¼°&ûVo|­,Œrpry¼‘òŽpiµÔ&@cF2cå1maú>¡ï“Äq‡÷¥”h­×ì— ÒøaÂu{Ë|ó—oìy³Ôj“å ÿò·žÃز}x)òï&AkÑšÀ÷±2¶§<4fÞyw8ÙJ‚ålyh 5qEQatÒˆ!)Û'ì²5ðFŠ‚ˆ½Û ‚س½Ø˜ ¢¤]0Ùt÷¶~ˆ("Žctœà–† FP‚Ö, …ç n’4*5q”7 }ZËuÞo©¢Ûû½”Ðúž$ qrñªuœ’$A' ¦‹€nh­û*aMþ%M’8ÁÊå\¤˜l ¤±²,Îâ/ž& ê4lUH &Ñh½6¦Ã ßzš  êâÓ I’¶ZúÅ··[Û[Ä´ HŠ8NHâåy)óV>÷ó%KÊÍT+çß ºpŒêÊVnVnË@*§Y1 BôŽù~3BÇ$z`ˆã˜8Nr-^Îô×&ÀІÄ4! ȆaR€PBYøÄËG‰—]Dºe¬ì8VfË+¡ì,R9)q*L“z‚o…€ÞÚ 0FôÞòp' ¡y¬Dë„$0q`)$.ÚXJµËVÖjåÛ&“ùÂ…$ Œr B(¡\„r0ZƒÐõ „þ<¡tÁÊ""Ê)¢Ü,§ˆr2(ËC*!ÕÚƒÎVÙL’Dc6ùp°'ÍÓ,¶ÊcÆ€Ñc4Z'è$DG5’h•$X" ÑõY,Ç vbÆÆ0ÙŒº¡ÀQ‰ƒ qsž%¤ƒ´3åbL(²Ù¡Ãet¸JT›aƒrÒCZ­žAYR9(e#,‹°žw_êõ@3DqŒ’"å]ÑIdÜì:Ðq½Ùk˜¸†Ij Ðèá”ÊAe²$¡oŒ`¡MˆzP©Ôó[¼‚PÒÊ"UkV“EGyRÚÕPcðIˆ$ª²ñ{a5— ª1«+[7áýˆ…ÙÓ„~ظV6cbŒŽA'“4@™tÒXšL$©õV9µ!Ee¹HËÅÊä¨.Ÿ¯#åù5”œ©Í/-NäÜ‚²s('‡trÖ?ªA„h©¡CŒn¬·–Èö¸M¡ºið&’ ÖDA•$Œ@¶Žm-“Æ’&ÀtɨqðZo]f ÒA:9”ÃΖ,!ä"´îGlk¾:;V¹+S@9y,o éA«^6=)ì5ϦIiÝÕ ›ÆêN´¿xm­ó¤—Ís™8uîÔËípµ@Ú RyXNåQ^aᜰÔÌ–Z¬.,¿eân±Ô Så6€Ë­“ ›Fh4×…ᤶ˦Racº<ÖWÉ0LJÞiE lÊÆ¶“TÓiÊÉ£¼"Na„¡¾¸xLXj¹M@mæ÷ƒ ZÿQmîù±Q¤SÀÎ £œ|Jò­\òº´×öI§Ë€Ô¾ö²çcˆH‡™Hßk<+•§¬µqZöJË@9E²å •EÂZíJÕÛÃf[*Ž—PÎvv;;Ôô¢µ¶LƒlzÝêad:\¬K$ E¤L“)×ÎIŠhÒáØ™|¥íaeKXî¹ñI–O½·jŒ8X;÷{¦ƒiÛïÌ9~ØÉW,cgq‹ã0@¤H $Ô¶ôöTžhïk‚¸(x‘ú}T‹Œ´äSãÑe›P€ÄrÎt #89–Þ=ñš´í7Û¸×HWs•™¥'«3§œÞ‚rp cØ™ÁÆÉQ'o+ ›ù–ZÒD4“hï'qÝ tÄoxsŒ¶×ÓŠ\“z§ƒ$Âò°sÃØ^‰ÂÔ4þòÕÙ¹§„¥Úï ´-ªú]­O¾ÿÒË3åé!ìÌ0Nno`*%¿´Ìe§Gú* +46E@—ZÞíöz{=EHûšEayEœ|;[bpz+³o¼6¯OÖNþn²ŽåÚož}ýØ£I4Gië¬Ì™ÁIìÜ0Çb©dÖË ½ÖÛÓè%䀎YÇêR€Õ5vSY-šKay¸…œì0…‰í Bfß>ú„´í×:†J©ŸøjÄß;þÃç–Æ?2‰“-ãÊ䆷!”ËÚeqwR”]ÞI)BZÙ:î"Õ¶HÙ8NZdvä€î0hÙeãä†p £8ÙaÊ{vröÐÁÕ8ˆþ¤~âwVú`yÎKï¿ôÆÿŽêg)_±;;L¦4I¦4Õ4N¥À·äßÊ)I…j­øÙ£:ܼLÝI !ÖˆHÏõ¨.Z9Fbyy¼qÜì0¥éhªœ{õµ‡¥ë<×=Ü:êïüûjœ˜ÿòúãOž¸jˆÌÀ8n~„üÈt#4ës)#º€·+EBlê%IÑ$®Ê“¢“à^Ž@"mo`¯0‚78Nù#ÓœøÁ_Ÿ£ä?Öþöº7J{¥t­ƒçÞ>ù{g^ÑLß°'[Æ£0vÊÍ5óAkДaR!Dg‰¬Còâ´ -íïéJ4§(2jíäB9x£dÇpse&ö_ÅÂÉ#̾óî·¤ë¼Ük¯þ›¿KÇþîáÇþúiÍ1¾·AB¶4Aq|'ÒvÁ´.u­5ϧÀ¯/‹‰ÍÜ ¡dã¾¢o… ãÈÔÔLã†Ç+6ltse†wíÆÊFýËgþ\Øöùo|½ç½xß´¼ñõ QÿÆ‹ÿã‘·Fw;”¶mÃ-Œž¤8qE“„¦º$ßm¼R w Ç ¯ÍpvvuCù«ãh,2¯£ÈºžØ5Ù i‘!;4‰[e`jšòžÞxüÿ‚ðׂ7¾~¾ßxÖFÆHKýháôì¯üÓ‡ÿðÆÏ}~4‰4ËÍŒ/”ËÊÌY’0ê[Bà8N»Ï,F|î—ŸàÖk'±mEKè­;÷ss«<ýÜû —H’˜0 èG!¥]Š·2…²ƒCxù…‘q¦nØÎ‘§]X:7ó rìžÒoµ‹¾)ê]÷oU'?·ó–«¿µÿÞÏ ÿÛ ,_8GX]¦¾²ÀÊìyÂÚ RHDW¹Üó<\×m`Û6ÚHÝP…heûvSãØ‚¤ùl¢E€ïû„a˜ª6ªÔÊöÈ ‘) âæŠäË£l½išwž}²vòàk_R¶õŸƒ—¿¶á_n6õª¬{ãWí$Ö÷_qãG¾±ÿÞûJ'_YfñÔ9Â`… ²Luáõ¥yt#•DJ…çyíî8®ëbÛ6¶m£”B)Õ–x«ì•$ÉÚƒ™("‚v÷}ß÷ÑI‚;›'SÂÍ`gŠ NŒ1±œ£Ï>¹zòàá/+Ëþvpð«}s|Ó/K»7}ÍŽcý¦ömÿæMŸùôäÜ{‚óGÏ×— ëü•%j‹3„µU\Ç!›Ë­#¡¥˲Ú´ž,i­µÀ&ø0 ;À×k5ê¾/?Øž-`{Ê;§(íÈðúÓ_8w䨝ZJ}?xá+µÍ຤×åÝ[~MÅZrp¢ü7ÿ̧ö+1Á©Ãçñ—ˆýUÂú*‰_EDu×qðzÇm»ò…m,½¿J8_Á!ÄV[‚%Á–KJl¥°-K5B@I‚Žˆ“˜(‰‰’„HkâDiˆbC`,D!Of*O­~·žûỳïù}KÊï‡Ï<8sq«?Dì»~KiÃÕBŠû·^µë]yÃu“…ÜÉr‚XñqM„gcK%±m…m),ea)…T²áÿ&q’Å QG A¤ñ#CÍH⬋.X¬¬^àÄáC³g¾û}%ÿMJñfôô—6-ù•€6Ÿü†›Äz¿tìŸÝ>yßö«öîßBVåq#A&Ñä¤!k ²ŽÂuŽ%±”@Òø¿@‚¸ñNp5Ô¬&†U#¨)XMªÌ^8Íé·Ž›=uæQŦ„x ­ëhCôô—.Ûö /„.¡ʱ^4’Cçß?ó_ϽîÎì@îîò–ñF¦¦¶ –G)xErŽKÖRd„ÄC t#h n .«Â°*CVê+,ÍÍ2wöÌéù³çú+«OcÌ3Rˆw¤%Ctëòéƒ9ðÃ" ÕBiÉ#HyÄ÷ýï|çÄŽ“ÇÞû¨rk¼\vo¦˜ßêår#n6›QŽ“±,ËLÅq…µ V¯ûÕÕÙzeõTP­I‚ð0†×¤à]i« ZCb6uW¹ÙöaÐnBˆe©ä!¤8d„VµZ5W­U€¤È‚(#É7³`˜Ç˜Æ, òÔ¤m%h½öWÓ‡Føÿ¹ý?TÄÜûŽÃIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/man.png000077500000000000000000000163441217176075400233630ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÿIDATxÚì›Ks×u€¿~÷ô¼o¤DR”mY4岦,g!{ãJ6Y¸¼J•+[—«’]þÞdëØ«¤¼ðÂKË.;%•,Ñz‘¦L‰ ÏÁ`0Ï~wß›ÅpP BI‰aRqºª Ýè®;÷~çÜsÏ9÷´"¥ä/ùPþÀ|ÿûßÿÇüàÿຮû… *Êc=‡ûó¨ûáyð~ض”R1MÓøùÏþo?ûÙÏþõ‹~O? ¥åååg^zé¥/ýo“ÞAB¤”¤iŠeY¼õÖ[8JG¦)Q=Rš‡%û¸ÏKü³¤}pÀ‡¯‡Ú0ìóêq‰Ñõ“<B‚^?ê^UÕG^|ÿÄ<-µã¸†GàiBø,Í8 âQF àiN‡ÏÒ†/:Gà¨x†×‡Uäp'è(ü©Ù€'ܨ gðO<ǨÅqÌ;ï¼Ãw¾ó¾vå —_y…ùñÙi4ŽáQ×Gõ6íè·ó¡<üLA³Ùäîݻܼy“ëׯ³ººŠ¢(|õòeÎÏϳúÓŸòÎü;ÿúëŒONrþüy.\¸Àòò2SSS”Ëet]h€C8ªª>ê೑.Žc|ß§ÛíÒjµh6›Ôëu¶··ÙÜܤÑhÐëõHÓ”l6Ëää$sss\½z•¥¥%æççéþêW,ü —vê¼=5…ú­o±×lòË_þ’N§ƒ”Ã0( ‹EÆÆÆ¨ÕjŒS«Õ(‹‹E …–eaYÖ± à±AÀ~ô#666p]—$IÐ4 ˲¨T*T«UÆÇÇ9wîßøÆ7¨V« òù<Ùl+›!cX„^€çyt·¶ÈüÕ+ƒ×þîo9ÿÝïÒíõè÷zôû}ºÝ.ý~Ÿv»M·Û¥Óé°²²Âõë×q]—N§Cš¦!P…ÅÅE~ò“ŸŒ€”’û÷ïsåÊ.]ºD>Ÿß—ŽmÛØ¶®ë躾o‘uÍÂ)©¡‡)Ýn›f³…et6·ðñ ÜÙYþùŸˆ¢ˆJ±L!_D*(1è*i”¢ q,HŸ@¼À#ñ\¯ƒ*¿þõ¯¹qãÆhlÀp^†A’$|õ…øæ7¿Iú T!°t©h %hRG*! 1 8ˆãUHL–ŠÄ@´¶FÜj¡( A ë:Іn¡)*ÂPÑu !$äó„n€iDVJ¡PÆÉY\»víØÞå±5@Ó4 àÓíâûwïÝÇ´5ÓÁÉeQU Rªk4AEÓ-LMÁ‹BEGQT4ÍDÓ4D¾€ô–ÆÊ …ÅEN£©ˆâMÓk<€ªÔ:ý„v{Ïí37;Oض=ÚU@J‰®ë„aºBª€"54ÃÀ²M4ÓÄT5¤T‘š‚Œ‰×ã›7©”ËÌÍ/!¥¤Ûëø>±e! (¾O§Óamm¹¹9lÛæT­†Ô*Aa)&h`Š”hš¡š„aˆeY£_UU%ŠB*:„¾K;év{=bæÔïð^˜*>ãù /2 H ¹\‘Z¹ˆ¦¨¶‚Põ>õ•»$B037Ϲ ϲ[ߣ±»F&ïW³ø¾ObÛ¨q¯Çøø8Õj•8 ¹sûSúÁŸQ“;›!*†šræÌY|ßek§ÍX¥ˆFŒ”ß÷Éf³£·¶mãyR „¢’ˆˆN£M¿ß!ñGeª½¿JÞ6(—+lnnE1 2™ÁRèylmmÑjµ˜™™áìòÙ|%‰0²y4Ú­ˆ(íc* ³º] ƒ4M‰ãxôFPJ‰iš4›M$ “"‰Éq,ÕÄÉZH!èG÷7·YÝܤš¯0óÌ,§&OóÉ'Ó­×›C*«ÛÛ¤¶D¿ÏÔÔcccDAÀ;·éû7ISAÞvjLß YZ8C(îN‹r©J" IÂ0<èUe³Y‚ MT‚¤»Ý$W*ÓØK°•‰ÊµgÏcÙ woßç£ëFC/–™=M³ÑF’"‘Í"°×ã·¿ý- äò9¦æÎ0Y­¢è:ºiÄ>º™AST‚¾O«Pf¯ÕB×uÒ4%r¹Üh<Áƒe° DIŒ¢*Xª…,˜(T*9‚¾Ëý º;;ÈJžóKË<[:…´¹ñþ½SI’‰‚ÌfÎPrþüyŠÅ"ëë|øáMJ…m¦§–Øëﱸ°Äå¯]¢ëûDI@"¦6È1DQ„mÛû!ù‰ÁƒCI8ÈCÕ(•‰Ó”\ÉbaòJºDÀ»ï½Í»IB!—G³5t#OuÁ0‘H¤ã ÜÞ~Ÿ>ø€©©)Šå2¯þõ+˜™…l‘J±Âò³‹ØšIÐîqëúvÚT 54ÝBQ%i*0 ã¡ ”‘åt]GÓ´Áž *‘ˆpû.žÛ%v]6RÁÖNLÆ$£Ùd«e*ù</ã3cx½6ºþ=ߥX*¢ë:±âºî>€‘:BÃ@Ã0 â89ØMÒ]×ÉZ&åÂ<šªâõÚ(F–RΤP,’ËP0öÙÛkqíÚÛœ?{–ñ\ŽÆÞÕV‹¥—_&‰#æ牃˜îÞA”`™*wï~ÂÄØ$Só46wÐm“4NDˆïû¨ªJÇÇ6†Ç04„½^‰TÀÉd(Š2F.m¨š JJœH|¯ÇV}›z}‡­­M,ËäùçŸÇ¶mªÕ*³¾ÏÊÊ wïÜA×uòù<årÇ1˜]˜#ŸËqéÒs$ªŠš*äryê[›¸qLÆt»]r¹Ü~ÅèHƒ¡0 yõÕWyóÍ7ùèæG\¸øaâ{Ÿî6h·[DÑ@-5M#MSlÛÆq …/^Ø¿&0<Ï£X,î'7ƒ`P?°µÕáÞ½u‚ @Qt}°¡R©TÈ T3¿ÿÝï)•J\½z•4MG«0¨~íµ×øú׿έ[·ØÚÚ¨6K.—£T*bš&–e¡iÚþ©ªêþ:|>¬æXÃôv’$û÷išîA'I‚ïû´ÛmîÝ»÷ hñÃþR©´¿wùT‚!MÓxñÅ÷µc¸<=ÅÃ?x®è¾7lÿpQôÁJð(Š8uêišî·gš&ŽãŒ.:èkš†ã8ضM’$!äázÝÏ«âz”ÛzX‚ ŸEÙ"„Øÿßúq·Æ•<\uPjŸÕñ£T–§òì°¶|^¹ýQá× %|”/=>¯“.¶I¡äqö?adN¢úQïžDaõ£Ú9QOªâOrܺäãæN¬\þ8? (O} œ„á9ÉoO È2s’6à$´bdåòÇ‘üQ;þEŸÔçùã8AGv„t]Ƕmâ8þÜNePŸ÷Γ´}ÊQƒ¢#}:û /\™››{!MÓä¸S`è²> 3“ªª²^¯øî»ïþáDü_>þâü×€ñ8q²èiIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/maximize.png000066400000000000000000000233401217176075400244220ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ6(kcl IDATxÚíy´eEuÿ?»Î¹ã{¯º_w# ÍèŒaj1¸\ƒ’`°e’DL$.£ *BѸTŒ 8@@¥è/Q‰•¥¡%hÓô ôH¿~ÓNÕþýQçž{îô¦î†¦ûnÖå¾®S§Î¹U»öðÝ»ª G=êQzÔ£õ¨G=êQzÔ£õ¨G=êQzÔ£õ¨G»-I· }Õg–zÀ¾Ï÷ºh÷¢gV­Ýÿ›ŸüÀêú¿Ãn=`ßç:ì /œï 4ý¥ŠÚô¯¤PÛ õ´cK>£­.€j‡g“z¶Òá‘-Íjj6HÇé!] ¥ÛŒ’Îw=ö?ÿË9§þ餃ôë•kxÍAûµ•éžpé9oíZ7}½õïÓÞx¿ß¸àùôË…½Èâ…óÙÿU‹Ð¸£U5p?ÀÿÒTGµÁõrZ®·ß×¹N§ò¤íÔ3êŒØý]¤CÛñ·Hj`ųB½LDú€§®%·Äek-õâk/nM¤]zÎ[Yý‡ m PÐV&¨×ýÒ=?àC½n¿ ù»^w¿E `ÅoV6µö„âKK[†Æ8û-'ñí=ć.z{R~Ãí÷rö[NbËÐãå*[†Æ’kéºõ=û-'$uÏ~ËIÜpû½I½t{Q^bÚºÍÈ)'Ï ·ßË{ÏÿK>×÷9å„ã“kåJ-ùû‡I4MßþÑCœrÂñIÝ~¤£8å„ã{ °+Ñ@_>ùûÌ7½‘Ïßõ}Î|Ó›êd³aR¯õZ+Õëžù¦7rÃí÷òg',ÅZÇ ·ß;é½=xè{?ùÏ—M¥Íøñiµ1%C`LÃpëd…× »”®©ÊšúŸ6yÍmjÊ}ЖúiË=íeÔï™ê3:½«ÍÞ€´[õõ*ºÒr_ã¢4y þ÷œõçïKy îK=.y irH¤Ýc‘ÆûÖ¢¨£W6e¸óŽ;X»vM›Ÿ¥ü¼NW:»„í¾v¸©û3ZܼnÏЉ\ÑÖ'Hׯ}:»~Í¥Òmi¯&]Ê[ëKë-t|bOvŸÅûrÞùïœ9¬[»†+?x#£ctŽLŽ0IW¯zÂz2!„5½z;¦­Ž¨A·î:¸;¤­õÒµ²¹,Ÿ¸îÛoŒŒŽñ ëþ2EØÄeî•.|$Ój¿û}—I7h­'í=>•2é4ˆ3,›Jÿµ–Íb`Âq5=³lϦìá4eP©TX³z5 ¬³YøuÆÑ§¢:è^™‚Šéj]m¿Z˜\UÐ]´[;Wt2üRÿ~ÍkþhÇ0À‚ÁAÞð†»WèG‘Éž–ÁשH¦Ð~·Êï›ØRŸ¸H`§Þ7q½l&³c X,P,v+ñ÷øŠÇYñÔ .~×Å=°§Ñ† øØç¯aã6 r\pÁ=#pO¡M[6qÑ5a°,Y¶?×Ür5Ë—/ï1Àž@ë7­ç´+ÿ»w­ÑÏ­yž#Î9’÷úýÜ}÷Ý=°;ÓÆ­yÇg2œ‘Íë7³×À|T-kÖ¯æäKOâï?~ªÊùçŸß“»ØÞÄß~㶘Í<óäspàœâjðèSpúGOçº[¯Ý£ÔÁ!Ö­çì[Ï¢Ô_âÙñ•°/ 9œ(bÀØ'ž^ÁagÊ5ÿ|5¥R‰óÎ;¯'^ñbd#ï¸û,ÏóØøÈ …A°³,.oQë?8Eœ°rÍsõWGrùMà®»îêI€W´ØßÄßþäò¯VúÃ̚PË;j¢8«8ë² gc >þ(§\ù&>óÍ›)‹,[¶¬'^i´y|3gܺo™•²’y³æÐ7«H¡/KfØÙUlÑâf9\Þá¬Ã9‡s–9~ùØãì}ê"®ûÊÇwkï`·”[+[9÷Ó9æOç¡ÍR¬åÉšr©Š†ˆcÁeV£Š8ƒTAâTn굫XzáR®ÿÜuD6j¶ Òlœ(""˜WØœÚí`¸6ÌÇŸú0ü'Īà·Ìé›CÕT©åª˜À`Œà4ÂT .²ÐoQgPëm‚DŠ‚ÁXÃÏþsŽýûc¹åÎ/RÈ8ãÌ3:2L%îÑc€KcÑWÿ÷åìØ6 ¼@e65(‡!•0L`PããP§¸>‹XÁÔ : âÄÏh#L'’%§.á‹ßüëׯçÒË.í©€]Fí(ŸYu=ç}>ëXÕˆ±ì0å¹c™€ âÕ<‚SK-KVШ­Y¤"˜r€Š‹Á¸€U+Ÿç°óåkŸ» `·a‚Ý‚ªZ忞}s_u>s™GŽ<³e6Ìb@f³iÖzÆ ãlØJ´ÙQÀakeœs(NмCóå¦l(H“ Œ óžyá7qëá<ðÉsô‘Góº_×fôàe  •xøžùÝ;Ÿ%¬åYWzžß—×Q±eÆìò·¾ÈIµ×3tØÏÙuŒ•q5‹8ƒfA4 ’­±÷ìù¬_»™u[ÿ@DY°€…ý·ñ†9oà¦oÞÄ}'Þד»í›_ÂG?þYTqh¼HT +9 8óÈ8ø[²eÞ6 mÃÕÊ'PóR –s æùÀ%âì7žC¹ZN²Æ­³ÉbÖjµJ±¯ØS»Ö ›-ór¹ðÅÈ!Er¥a\Åa¬As¬`B¥L•ùÅAòÙ|ç‡õõp€W$‰8ܹ\É d,D*ày%4‚Åî1}²G1@àfë\2Ù“\Æ¡5‡Ëxÿ_Õ!ÊE{˜Ð0›Ùä)"9A‡ BÞ^ìn4^®ò̪õˆDí}²GIÐ' ÐYÅgšS4thÖAƽ²ýºd­cd¬LdÝKÏÿìaÞvñÛ¨Õj»rè£ À õƒžÍÄÒ`¢µåÕTµºó¤âÎ|ù[n¹…ë¿ðIÊC%ÆÇÇ_öÎT2äÈõnB hF½*ä»ÎàGDÜþ©ÏðÏüQ;úÊb€[n¹…Ûîø*…«²ütè§d³Ù—½CqJ†ÐCÂ&üÔ·„»Žp8ß¹/¼ê`>óÜõŒEcÛç½T ð½ï}ïüðÛì÷¾ýxê'O“1aÇeM/½è?ƒŠÃÅ5ê?Ew%7@•pnž¹³çqÊ!oæ#Oÿõá¼1ÒqcÎwÝu7Ýv#ùSrüæϯw)±jq([EÅ#†NÔƒ²k1€CYWzžµ¬f«Ùÿ%\³âƒl­læø ¦ËÜ¡ p÷Ýwó©/~‚.ØŸÕ«W“!D˱^Ý,k U"ªXNÕK,Š—» ªü¾¼ŽÍ¬gµ®bÃÀ ˜ïøáilß=H¶L—f±Õ¯bÙÕgðèS`l˜è{µŠfAûWth‡\.C.#h`}Ü=£×~Å3BŒÄ9ã¼ñhÕÏ|À…§Î#wfæôg(Û*¥Ñ1\É¡ãPS…2ÆáÞÜNZ»áúúÈæsd 9²ÙMdÉSÔ>fý„dB Ž5ªŒ1Ê£”§V‹¨”*TæUØ62Du¤ì%À¸ÿ-SµÔ†€-À˯Ÿ|–CŒ8ýÃoåÿÝøo ÎlS6Ó 'ƒÎÒÆÃwÞÉ5·\ÍçÉ¿zã2ÞYQ?`šWtÀAQÑ>…‚"¡ Y !hÎ"Fqõ ç1 kb €E Þ:W?(6ò@Mäf® ï8$Þqûàø³“èg/üS0ä œ!Èdó!b &+rAQos«Þ-­ ZQ\MѲ•À•#´ ®RÊR¨æÈYÇlAEú °ÌRª‘c¯Å{qáG.äökogáÂ…M@›® ^vÂm߸[¿õeŽ}×1<·æy$‰Å¦ºxðg)®èwH$šWÿU$#ñx»àŒBÈÄQD‘úþ¿‚TD !`Â]?c£4^F€² ¦¦b1ÁŠ„ÆO*ŒŸ“hãŒ5ˆ5˜šZ€©šø@% [ !2¾nÙØãHÞ€!·¹ûÌáâ½›½÷Z–µ4Á™¶  uÄQ,øÏ…Œn%†D5Áˆ÷­]QpŠ-ZdÀár@Öa3’S\Ö%2Ögâ.ŽÇ[gbÝ/Š:o!Ù4T/þq]Ÿ BFŦ1ñ‚,j0ê³ú—šOL5Î VÈ@Í@Mª 5AÊ‚­9¤¢¸QÆ:ìJGDÕ••qJŒ{ЦꨖÊÞzoK§(¼TŽ @Ÿ•.vLÍ ¡_m$Îø•GÖø_Á—ýŒ÷ê €š¢EÊ^0.ȨAªñà‹Çòœ©qÌkçÁ/=Äg¯ü§–%íG§­Ú¤ÁyƒÜÿ©ðŽÏļ>äÙñ•ÈÍ;ok3S$0mj‹98g/¿ûVÞþÕ3ø‹ÃOæ¡ dò…,…þ¼üþórsy(ósV<¹‰-{µJ|âˆ$X¯¨×‘0&õöõsÂJUÔw¢¬J`ãØâÕx¿]MÆ»}l#¤0E[ðéæZ2åæ˜›Ç7qÅ­—Ì 1ˆñ*Ù‡v…²+qÜÒãXqÇ“\ÿÞO±lÙ²¶qJz±K0(œÏVª5ïvâ ³ðíK¾Ë;î>‹_ýzVÊJÂ|H&Ÿ%WÈ‘ïËÑ—)²×ܽpj $ˆ÷KÌ!©^E´¹LëLr¸ ‰o›Þ :i²~¼‹¤‡×_ÿ÷Gàã›®àQ}š‚ÉPsBïY‹NÜûö[ô*F^° Ì`Bý’’2©Òz¬¢3{L.¹é=,ÞëU8uˆ˜d ­X^wìñχ.»ŠsÏ;/aêÉ>EÍTp€ngHúܺ˜æäæríQ7òüo×°˜%ìËö'h›’š—í~hG_¿õgµšd)÷U;Ì>õ/Æ`09ƒB6’%Ïæ$ P¿G&Qá‰úmR[R÷N¤!á´IÜ·f˜œe¨ ©f¡œç°×Jù —_t…×ùÉéÝÉ)ÞÊ4ùý23 `lcú'–ÑIÃu×DT˜•™Íõ‡ÿüöÇlݶ…hk¹ý|¼Ь­µË¹~iþÑ6‡¬U(€6yõÑ0>#bC$0é£]£ÓlJKý”ûÚ8¾œîídžhÌø¤ ƺÍ(-¿GPUj.âˆ7Κϭá¬7¿3Ï8«åÐȉû©>!Œ™aV°j¦ˆ¿§ ·¾°ðžûÃïØô/kLÇWÔ†ÓŽ¶©ËæSCÛM|mêŒhÓÁ“ªÚ"¹ü¬¯#dAè§HV ü-ÚÌiÓE“YÞ.Z%ÖB³9¢)VWi=½T[ğ߉ä sÞ@é“UÞý΋¹ì²Ëè|’êì€.blR ( ™0œ<éPÔöó§ÿçTþèÃGø5Ò2‚iãRRmh+Š’òµ;(fIûû]Ž •T{Fãô,D#^*„dÉ‘íÚ«ZUÇîÝú@[_Ûà¤Õ«IZ‡Cü…B‘üœü«òºO`æË‚Ó‘ ‰Ú†ºDTm9Á+™ÒT$q¸"d%þ¹%s‡»•š£Úê(Ä¢¡cH[â÷ª}ÚCÐ4ziT\ LŠOÐ ôx} 㸺¹—<‹&fö*^ÐTB©´`õx¼´¨†´öh…@2Ùû¾z_;wMwø¥óÉkS †0È€:„«n‚T¥ùåë¿¶ëZ€ºØ“ɵ‰Òq¥Nk74ŒQ™ %V¤Ù¦H‚0q¯Ô3D —¶›RÓ3x Scº‰af©‹ú†*QiKh¢µÉÒ®ÓøÝ!ýiJ!0‚É„(¦£Õß@d5%Õ' jÊCÖýÝ ’·N`¬É'H‰PÕV¬HZt©¦¹ÃE’„añ;„±ÁE„¯4Å„þý],Æü–ƒ©ë,"’2ô™N“Ð͸…Ïh f´žIÆÔô —†ù8r6 ãk# ÙTÏÕÝéêÖuÒãi,¿5`ÐÙÓ„±ê¾¸4YèmƀŇ_£T6ŽõO¯Q¥Fŧ¥%ƒß€y”.hdÚ+ÑÔ;¯ŽRI^]»H;m¬ê¿Iš¤˜¶ÛA2u˜¾èÁ8Â0ÄáÚ<³†¸ÔÔûI‹[ë2ÑËJžÖ†·w`÷v~–0EÚ1m|ØUj’´+ãÔ£T(aKÉ®×LRˆOÝ7rMJ¼Yl'5ÓÒJ3E;„Ú`*U&…a§0øÆÌ4-ÈfóX§„’žÚÍnt¼XK$¡¤-û´ÑŽñKÄÓÐÉ:¾ºhm3ĺ:°¡ T gã¿)” }ö Ua„QÆtëlss(N$a‚ôë¸DËø•PißQµžŽ­ —US­à¤36"íÒnŽÂŒW B.—iš^ªM›k³‡,SŒÜI»¹Ø iëlbFóK´R#…ªÏ¸ÁÆI˜Ö ¥Ì8ÛØ†\³zSiòlpéØE Èáòô«¹N^i¡§$œvžÕ­Ø§Îà“ÓUu÷!›ÉúÔï¶L+Ê–²¹ZŦ³”Ѫ޵"ê*NÍøVI_·­µ=f¬€Öð)W5ÁÔ|Ê–©\M©Õ"¶ÉVŸ©œF,ESbÛ5ùrÚäÿ¦™‚š‚ñ9÷Æ\9bÛÈ›öêgÉçæ¨ÿ:ˆ½æîÅ,M_ÐG.ȳO~1ûä—PÛZbÓ¿¬å½Ÿ}sû¥|XI\)…Ù–7 ‰kتt'ø´@Dƒ—¯1ÈDn]‚kיܧÕ-â´roÂñS¢®.h¤[$° ñ"œƒ+þêrn¼åFþâ³o᩟YT’.õuõ^{Þú“OäÍO?Éí—ÜÆ¡ï;Œßüâ€Rb0Fý‹–-¡"e?HÎD”2%C©6Ζ~e¬oŒ¡þ!FØÆ0Ã,‘ý©h™oü1ï;øƒdɶ&7µXðÚãÒ‰ûZ;bk/ÔÁJ1© i±xÛ 9mâðú¬–zÞ~¬/Û‚%Ï꺇ûÏuDPqÚ”TœH‡‘ù»Ë.àÞ»îå€SüNe~³*ã½£˜Šqâõ‰þyAP¥JV1$™N6²ØZŽ¡þaú² F~ú¿?ãº×ÞLŸéó‡SHÊUÔ´„'P‘vTOuW’i|ÛiÊDmM»Œ¥‚k b§å8LlÅ:ÅgÅmh*TêÐG¯3ˆ7Œ\k* "f„ÄÇWÀ —]úw,\¸ˆ›¿öi޼àH{ä1 ÆÇøý†PŠŽƒ©¯Hƒ:¡¤%Äœõ'D‘¥E„Rdõsk¹öˆ›Èôw…Å%A4É æ~!mÑŠ“§^ì N™Ü\äE(4Hó~½€ƒJ‚{‹Ðœœ~<hì}ªºxÖÄ"¾ÅçñÛ·k=95žiõmdÒ‹=4e…3Î<“r¹Ì_¸ž×¿ïõ<þØã6DâýÔ5¦TIDAT*:ooŒ p5ÇxµŒoï8ë+UŒ3]XÊ?ükîyóýÌÊÌšb>¶ôU'ç3û„qç2€ÿ‘µÉz}ÏX¸ú`¨‰wÝ”F¨WÙ:N½I¢hqK’B÷4¾Ïàâœ:^7],_cy¯ÄŸú黡a¤žwÞyˆŸýúÍpê~3ÿž(ZUtÄ ¢1¸<”œ%¤ŒZGT­‘u9ÏÁ/ÿãi¾{Ú÷™››;#vGÎØMf* fkqJ—‹ oc.G ©[ƒ.ñ±ê¨Û~‰÷âjĽâ`‹ÄñøæO':’üƳۢåÒH9÷Üó¸êâòÂ×s̱K©PÁÄÇ&0˜²Á ‚ñ€`[–Ú”ƪŒ ³exˆƒô X“çÞÓ¾ÏüâüíÆâ™Æ~ÉS‚w¦ÐÞ$¡¤©íXª©,F×ÐýN›qjõb]ë¢Ï5ôUªm±@ ¦ qmÿ ­Û®µ†F;À¾ ¼mÙ2þáü÷óÀ?ḥÇáÄy&À3AÅ`F6B´YÞf9iáÉ”ž…/üe·sð›Œê‰Ã¢­¨öT¸`rØ>#œµI`Ãà·WõÂZõ³Ù¤lÞ´[§M¡ZíÃÖ‰Þ^&ý]M™±*m°q]ÜxÇ |ÚA¬Zû|lµ^”‚(€A]À± Ž`øé2÷¼û;,è_0·šª4xé­ýí’•RH:'!掺pFu‚ñÔÆÓè9×(v-޶´LiÎÚMù×çžs.ÿøžñ›ûžáèÑßË%\ ¯.Ä>¥}øÎÅßeÑœE£t;bQùT¶Ï—©‹‹€)1Àx­œD“T›söµ®æ¥ÆTš!N©;ºÚÐßͲ·m“@œ&ÒDã[]½8uŠˆtIÜÇ_KðõËÞ¶Œ\ôîÿÄýwÄñ˜L¼¾'Ê¡GÈ^n_¼àË Ì# ©ß,;™ŸìÜ].¦¤¢JÅ[úñtoFíâAÓÉ’4Ð[w -`5&ž½‚UæùCÁ8%H<Ie`8uÞê7±;¨ OÁÄÒÅYM–¡Y§F’½‹Áqî¹ïD¸úKåÈwɺëÀW÷½š-k·p÷‡¿ÃàÜAlã©~¡ˆj*À3-{î%qçv2DñIŠi ŹØÄ:¬c5£v&A kˆ#´‚5ømßDüŒWÏ|;¦Ž*:ÔÕ¡”x§+çR9ö^dØK5¨Z7¦–ÝP£ÊÙçœM®çƒ7_Îqï:†Ñ£È:ÃòOÞÏ‚½ÑWãwú[ÿ’‘‘¾zÏ-Ìß{ÿ|íW˜7gH• FñëR#yf,Œ#µøÆöú:!¨4c)±#¼€M›73«¯ŸÝ.ºðBT,Gqûí·/»+mÚ>èëïãꫯÙm;hõÊ5üßûîßmßܹs·®üðUMÖpÚ¤2rë˜wú$uRyû©ëí÷u®Ó©££=Ó%Ò¦öhÍ#”ÞÚ¶äM›!–æEF ?WºA¸bJ;l‰t.èÜ®t_QÕÚx§gü~ã–úŸÙºuÛ•žxêW¿[ñ›•½i²Ñ¿ÿøG ä¨îIOD³bn©çI ?þÌæ³ãFøžIùm©0^[9“\ëTw:טÂógÒN·v·÷}§Ò'­ï“.×x`ËÀ6`+0 ŒÆŸ`<åhW'c€bê&f†\\^H}çðy¸ao޽ì/Jñ€×¿+@5ÅD“J€°…ã»}zå®E.õÝíÓÕÞ˜ÌKè ô+Ÿ1zÔ£õ¨G=êQzÔ£õ¨G=êQzÔ£õ¨G=êQz´'Ðÿ¶¿UÅ$´ 5IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/menuedit.png000066400000000000000000000076411217176075400244170ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞhIDATxœÝ›]l×uÇ÷ÎÌ.I‰¢øi‘’“”"Фì‘- vܤF\ÄMÓ¢éK¸@kÙ†ë‚".‚iÂ/®!çÅ~ ÕEÝ&r[Ø’a´•ÕX”,’Rb7–¥4),Q¢Hñk?fvfî½}˜áìr—\ŠTâæÃ™;óÿŸsÿçÜ;CÁöÌ3ϰcÇ”RcÖ:}C¶Zû™L†ãÇcÛ6BˆŠcB¤”\¼x)%RÊUï#„ T*‘ÏçYýÌîewâìµNÐZ'˶Õj­1Æl: kp†¿[*•zÃ0T¿Œ.PwXaþ«âûBˆ¤Äá»¶Û_|ñÅçš››oû›i…B¡-›Í~?,„À²,lÛæùçŸÇ²¬ú°–­E€¨òú—n‹‹‹¥¦¦&¤” xÇqx饗pgÝà5EPÄo~~!„ŽCÞ¶í¼mÛ )ëµÛï<¿ [XX ‚äwš€üí„~lŸjòù<¾ïW€B`Û6GŽÙ0xøP,q])e’bϧÁߎ¥»õšuÀȽm |Ÿb¡€¢"÷+¥‚^x¦¦&Œ1(¥j^¿VD!’ºfM$éÆbæ ËëͰ´Ð†Xî"í¼?9I>Ô¡fëÖ­\¿~}ðyÏó,6™„–1&ÆD½>P®û^*¼9N‹U\ í4Z+”6h£0j¹BÓF9Ë`LDOE•›RH´¥B0QhúA€6šÐÀìåÿæ[_{c RJ‚0D)å[–eI)E\Å: „0éY]0”¯“GýÁã?þ{¶]‡­!æxéèœ2Q#Ž—0MŒÓD4šr ÅûMjk¹‰¢|ØÓs´wtT?Z¦ö¯Ï¤”]°JH0ƒtA”<¨[˜¡,ÿ\éþeK*ÊþA•4o0˜Œë6†f¦µFJ‰ïû442,.)DÑc"³¼ª§¦ük>0ÚDç%'Š¡ÁvKk#Z‡i­YXX ££SVV{5Á€R†Å%áÖ `ùyËGÖ_5VðLY< ¦¹°¹,--%™#¾çš Œa~ÉÃò*Ã1剧׉?ŸŽ è· (”¬vùº,ŸÏWT”±Ùõr¦¡A+ÍÂRÛ÷¢LžžºqmR'H"),·iŠm–½°’#ÊcŒZ£¬X :/kÌòñø€T.nÞÄ%ÀƒïûÉØ;öN&“¡X,òw¯¾ÊÌô4}õ«|þàA„üÃk¯±¸˜£³³ƒ›Ó7É|–\TF¦pW)lj ¡MDDš ]Pm 2´ð ~Y€ï Uƒ°, c ““LOßdxh˜{îéGÁÿþüçŒãË¿ù([·laVHrù~¾Ä|F¦^ÌA”ZL¹?¥²2@ªv„>|  ¸]ÓZ'ãòx&„ C.\¸H¶©‰/?ú(Zk&''8tèÿüúëôöör÷ÝwÓ¼e Z®Ï¹0]DgQ»3e…7IAÚår”XÉZ°Z eÄaMˆ”_“Åáœ\¤¦®Ã0!HÞÞ\úè~à8¶ÝÂäÅ‹´µ¶rôèQÞ}÷4øÇD,-åÈò|ëP?³‹NTš›rY]Vv)¢± ÚT¥Äh\Í—…žÍÑZsáÂE(‘Éd™œœÄ+ºìèéáßþå >ðwõôÍf U$hßù­½Tº=í~ Æ¥Rµ…¥AëhÖJG3XÆÄŽƒ-]½¶pýøë" ‘wpa’Éd’\/¥DÃ…ÉI2Ù&ŒV8ÍMLŒOâ¹.ýýÌÎÎòÐÃsï½÷ÒÕÕE&“A+E&ÛÄòÄu²GƒRJIT92•ѴѨP¡”Ak‰RºÌ‘¡½I±DSÊ›¦ÆÂhÎnEDLLLZk2™ çÏSòJôô333Cø ÓÕÕ…mÛh­ ÂpÕ$î’ñ}c•RuÖË]Wëåt¹iïâÅÏçONLÍ>iÇ)ƒ÷èᅦٙ´⮻µXÖz¯äÓ¯ëÓz´ °2íVO¸¤÷mJÄ^˲PJ199I)¤´8wþ<*dfæ&Zköîý,}}}lÛ¶­t=ïÇÂ[K‡ÒKµX§ J_·áHßHÄobb‚R)@Bröýq‚’ÏÀÀ337Q*dß¾eðé— «}Q ¢ðZ„Ôk{ÃSÇqÃññq|?@D@¼þ}|ÏgÏžffg0F344Doo/­­­H)“.´ ÕBœŽ€øX씸èŠßT}T!×M@úfBˆ$cµWJqþü¥RôBS£9wnåûìÝ»‡ù…yŒÖìÛ·;w&àÓ…R¼m¯|¼¸¸Zí½`º (¥*­5ííí´´´l]¥R)Qy¥A$ýQJI|ðÁ‡(­°¤E6›åìÙsèP±k÷.ffgpÝ"ƒƒƒ´´´†! +HAxžÇ±cÇ’nuêÔ© ããã¯Ú¶m !â6ªç7«5¢­Âq{zzú'ÀÚ•`Üh6›%›ÍV47Æpöì92™&0 ¼wf ´f`p‹KóX–ÅÁƒéëëcûöí^Š=U-`£££ø¾O.—cÛ¶m;vìÇãããÛ¨Ó±5E°V?ŒC)®íÏœ#—Ëš-­­œC«ÁAæÀ˜ ÁKƒN§´Zbå8ìܹ“žžžÍÄÞÕ–V{¥gÏž#ŸÏ£”bßÐRH0°g` ó `hÿ;wî¬Pûz¹ºz;W”ëÉ'ŸÜ,ìÀm««Öš±±³ ´Ö Œ0;{‹S§þ“Ï|f7‹¹E„€¡¡!úz#ÏÇÅQ½ñD="âûÆãŒ§žzj“àß‘úÆÎŒU€¿57ÏÉoÑÝÝM>ŸG=§¤F@×ÚŸ®òÂ0äé§ŸþåðÞ{cä y´V ø·O¼Å]==‹E¤ íb×®]‰çë0µˆˆ÷¥¥÷ÇYh3HX7cï!—Ï•=?Ê­¹yÞ9q’;và•JX–ÅÈÈ»wïfûöíÉÇÍqßVt…4ÐF–8 |ßg£š°.~ø_g˜_\ÂhÍÈÈ(ssóœ|óM:»;YZZ"|’!mxžG©TÂ÷}‚ H–tH—Ò1kYZ 7¢ ×ïž>M>©ý}Ÿû\Ùó'èêîŒú¼€ÁÁA:::°mÏóVäöZÞŒ#C)µâ£¨ô9qáU/j>ÌË/¿¼écŒ¹rå žë!¥äÀû˜»ÅÛ'Þ¢§§×uijÊ222’^âñ8=]ÜT Zõ±ô˜ ½¿^é_Ü öïüö×øâ#¿-èc% ¹¹™¿úëïrõêUsüøAÿ@¿m”fxt¤ þ===‹.Žc±ÿþrm¿µ"4k×;V üZ]b#$Hß÷ñK>¥RÔW½ò»tÏóøú×ÿÁ®®®f·è²ÿÀh¢ö==Ý‹EG222ÌîÝ»immE¹®"§–¯–)!! C>Ü8i¶ÓçžûöŸ=ô…‡¿°°°3w«öÝÝ‹.™ŒÃèèvîÜ•Œêš¼FÒ`¼½Ö<@:;AÀO<ÑËwY¾YÉ/}³µuëC[ZZ¶ýÚƒÚ7¦g8‡½ë’ÉXŒŽÓ××G[[[Í ¯šˆZ Ö“µõFÂ2å‘d6›ýÓ}½d³Ù¾ÇûÊýs·æxûä[t÷ôà‹d³FG°kW”çcqJ+újªVÿzdTƒj”„8ki­ ‚`M’, ØŽóì•Ë—¿¹ß±‹ðoìšžæí·OÒÛÛKt´w0zïh…ÚW«{úEI-!¬'rñ‹”ê,¯›ššÈd2v6›mø#éxòäÙgŸåÈ‘#µ ˆ¿¿w²™?¹09ñéhmÝÊéS§¹üÓË^{{GS\Ð `Û6®ëR,+Š™jP±êõýFC?n×q”Rþ+¯¼ÒøFͶ, '“ùó?øñ_¢ÂŽ_ä®]ý„K}„íd®†a˜ýÞ÷^ú©©©Ÿó@ú_ Ý)“–e ¥ÔÄf7,úïÞý•Îή7Üw€/~éK\¹ü1a ¸zõ*w÷÷ßxíï_{þg?ûéÀ4Plnn®™Ÿ×#T+¢ÆGÍÕÿ$!¥L¦å6ÓlÛ²‚kW?akëzº{‚€©ëS îÙ;ýúëÿƒŸŠ ‡ÓªÛF ¨Þ®Þ·Ñ«gVÑ-þOûöö'oÍÞÚ:55Eó–ö~vßÌëÿôúß|üñÇ1ø¥ø‚l6»!°µ¬¤”ɤìfš´¤Åµ×Y–õ£¹ÙYfgoù?8þÆw/]ºtœ¨Ï/±òü¯ŒUÌ#gç>?2À'D!Ÿ£ |kkëÑ€êíZày¾ïßö}jYÅhЂ‹©ýŠ_aÏÇ&6»?ÿ³ÿrY裪†‡‡IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/messagebox_critical.png000066400000000000000000000147551217176075400266200ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ´IDATxœå›y˜Uç?ç¼ÛÝëÖ–J* dÁ„aGAmǶ»mµÄn•VèÑÙ”!ÍéÅmtìV\°ÅV!@ !d%„T¥öºK½û9óÇûÞ[7II4=ÓÏÓçyN½÷¾÷Ö¹çûý}¿ó;Ë+´ÖüG.æ‰häK"€Hß‹C>Ub ”-ÑmQ²1ÊQh©h´V¨j€1®U…á)$­æÑS\5p¥®ÿÞ}?!4Êdg¡“9m¢mE©§çÌÂÌÎÓ23»äKÅN»­­b>#B P~ ÕXůWÆ+þÀÐPµ¿oåààÖº[yÊ#Þaì0=u";›–F€ ",¢yíVñ♋O{SïYgW^¾lž3·#c#âA+aÀ] ŠzcÏ_Ꮍ¥ºo?ƒÛ¶ضýñ‘¾‡]âGCì½â„9®81à‹Â9⥳;f½ý¤Õ«þ¼çŒåK²'σŽ2”Ûíe„ç#FÇ ZEh2 AÐ:}«Iú¤Aiˆ#‚J•Ñ»Ø÷øïv½²uÛwê±÷U빡ás?˜€û…9onÇÌ÷½æ‚5WÌ8sù£­†D Èr;²« :Ú¡îBŒŽÂ„ j A 1Y¥Zkâ8¥ÐÏøÞ—Ùóدú÷<óì?ÖutO€µóÿ?ø‚°3]¦ó'+VŸwÝÜóÏY!ËV6‹!@6 …|r #¨T`¼žº•qxäLo§D’8މ£íû ïÜÃÖŸ<úbßþ½|Ìoü•v'þŸp¯°fŸ2sî+.yÝû³ófÚ0pò )Á Š’/f2ËeB¬àõäõñ)À4Á´ˆUD„µ»ý[õ›˜ˆÃO^¡ýÝÇÛìqðwÂ9{åi§vÁÅç¯Ñ9;—Çq20á$–m´)%XVÒq¥bTËçÇTÒX!Ä¡mÚ&A>ƒ;÷òÔ¶yt|ô#Wèà_ŽÏ1p—ÈÊN¸dÕêóîî9{ÅeŠ%ÌXA­qLê´LÆ÷†?§WͤôÅTšŸ¢è柖6uâ™ ‘?¨ ðä~Úp ÿÃÖ?}H× Ø1p‡ÈÊN!þøüóÎÿRyÙ¢騔òEdÝMšV“à„ éÐb Ç ¾µ4û© 'jp,”m1†TÇFùÝ£xeÿ•!Ö7?| $SÐ.ø£sÏ:û‹……sz„´¢|RÒ6IF³LuïpÀ€!Á0)•äê0…ÕÒ²Èç²è|Ž3×œÓæÿ<úâðÀÁøÎѰU_™³Ö,]þÍÎ¥ 9…íN1<¾Ÿ$°éÿ·¦ÁM\¢å®h½ = h'¤Q˜ÑéM–D3.èbªV äñ_þ¦¿V©¾ãƒÚ{Õ˜ðªÜ!œÞU³OúƼÓO½È*™‘- ‚­Ñ˜R", âEiR#ŽP½x5  \Q(@6Aãã¨z ‚‰±°mt[‰1±ç•Wxò·›Ÿ ƒðm£ÝiG‡i Ø$2Îk åÛ—Ÿ±ä#F{‰ÞR;fß Ú› ¢4¦É8Ž” ù>ïï£d›\8»7 ‡©äð×GöJ€ã ò9D[Ïìx™þÁΜ;“¶I8á6]N Ф´mâö6#-;w³}Û®¯iįҵ©~jÚÐiXo\4¯÷ƒ‘-™áä0_îCUªø†$‰µEƒ­q ƒýµ:ÿ¸u AG7þȃ£#üÉ)¯Ainø­Ö-Š™žƘBðè³/ðTß²\ä™yŒÿºl)óòYü8¦5Di[¶ça†å¶'÷tsphô]#ƒÃ÷Mõ;rª›Ÿ™Ù ;»>&òN¶”É‘!ÆBêa€„AH„~ˆˆböŒqÿÖÍœò×ÍÇ^ÜÂÕ¿ýWvvwñžÛ‚Bb?$ôÂ`²FÁ¡ï[ïkßå¡'Ÿä‰z…?ÿù÷¸rÇïXöÑ«¹ÿù'Ù=4ŒŒbB?$Jû!~âÁØ8™‘ ]†Ãɳf€m_{‡Èž2%ÑS¹À×ö.›×û©LO‹ì<ì{…:š à  Së ¶Œù>ßÜûK>øaÞö…»P)³Ã»÷pߥo⤗öñæ“æ£ÐG¸C«.e É_y™gò9®xøAæ¬:«ÙæÃ×ÜÀoçsЛÏá«ÉÑG¥Ú²•"˜]ìÕ¿´—þþáõ yãÿÐqËOIÀ§EvþÊŽŽ‡K3ËKæ÷ôRÞwêDºi0!E³ÓBk,Õ0ä»örê•WñÖÏ߉R '¿aYû÷ð•ËÞ̼»ySïl šÀõaqA`"xd ŸgÛŠ\þðƒÌ]ua&ŸK‰i|ÿÚù݆ÛxÛŒ9ÌÊfð•F§QV!h²±¢hÙ3:yrô OíëïW~téGµûL+ÞC\à6‘]†õVÇK²N†òHwx˜ZR \ßÇOk Öê|ïÀ^–\yõàÂ0¤sÁ|®øÁCì_´‡÷ïK†2Ï%ö\”ç§UyÂóx¤o?[Ê%Þ{x­QóÆõkYuÍ üÓÀ~öUª¨ À÷¼´o®ïS Cª•*™Ñ*³ì ¥œ=3„wl9cZ$Ìê0wDRÓmØD/÷Q B*AH-îù>ï3RŸà‘á,ù›«ù/Ÿ¿ãð‡“ðÞ<È+‹󃡾”„IðÚóžÇO‡²µ³“ËJdß þp.[¿–s¯¹‘‡GÒ_«>žàû!®Róªa€;4LWÝ–6øSà¤i È#ε‰WÚ¶Ei¬Nmt„JR |&üßó =åzì¬WXü¡ÿÆ[îž|+  æsù÷àÀ©KùQmíúàzh×C¸?«²µg&ïyèæ¬Z9%øÃIxÃú[YyíMló'ЮK躉< ß§Œ×ª8ãufJËЧÄè‹[ÛjÆ€[DΜwͰõO9i½ƒ5Ž0"$cÐ05ÚG/;ƒsž{ įÒÙÖbY#»÷òÕ7¿…žm[¸ üŠ€3çò®¿Ëì³_|k‘¦‰‚;ñËGÑÂ!F „ ¤Ö´iMO¶@­hññ!ù-yù zÂ…HèµPDJ!ŒTë #ÖŠZã*…«Z1I¸ýy^¾î¦$ Ê)GÓ#J¢„“y÷C0xêr~AÀ¿°{æÞýÀñGJ„ôݾø‰_ãaájôOÅL¨˜ŠV C¾KÖ)kˆPçé7höÜ„%!ñ"iÙh/`(ŽA3‚¦‚¦Š¦†¦†¢T£˜çׯeÇ5×aÆq“ð®‡`hÑvwôðοGïQd8xÓ0ØwÛ:^¸áZ*¾Ÿô)ícEE%íÿŠ ƒ€¢”D"ž­`y îzY]èL¯iR÷|†IØ#ÉâLÀ@`‘¤œ&‰ÉÓ×iXºq]’ÃjO†´/8™·?øÏ„µ:½ÇaùÆP¸sí:¶Ýt=ÉÞBqZ£´i®ØÆ” I,” µ>øv“€ÿ)²F–Õ$ØZRõ}ÆPŒµ4‰5+%ÂLß’'6­'Öšå›Ö*ŠG™óA@ç©‹›¯Åtë‚iÑZ# Ó0Ø~ëm<óñÑH1Ĉ&ø™LºFcEN$->jÉ'D6û íº&€†¼B-”Bà ©G€‹ÆE#©T2Tú^¡1HàÉOm`ù¦õøB7Ö_¥Ä®{Ôï4Š0 2†Áö[Ö²ùæ›Ð©å³Ò¤j¢& ‰"¨SÂÀAPznVS܆ 5Ì2„ÀÒ0+BÀgRF‘²œ0ÚÈæ’ ‘DO}j8mãzÜ8&‚ßoõ§µh´,r¶Íö[neóÍ' ]²™U6ú7_ëCAjAÁºKC 8Ø ë£ó¶4P$Ò‰?½Š´!Ù¯Qéx’ŒD ›7m@Á² ë¨Å1¡ï#…àÈÇ«A"{òÉe³¼xË­<}óÇÓD·¾¡ÈIð׉ˆ¦+hBŽÄZ—5tÀd,í*×n(\4^Úˆ‚ôGtÓú2eY´(C´’°q=X²a5) &&ÐSm„¼*+“¡X(°ã–µNÞo¸‡ \­×ØJSlCރ̸Ð(a0¢5ƒ(†ÓwAæð“–ou… زq=y3KÛïÁB¬öòÔ»AÓ€W¾íìüô<}óML%û©,hÕIbDbÌšÖÄé6\£'ÍaP§kLm†§“qE€&€pš„hŒtyªQEš^üìöOýïosÁ}wSn/£Ž!0ËÄçG¸ŠÚã¿`…<l£6~ópë7ÞG@€Æ'Ɇ¸Lºd#{© "¡ÉJ‰ÂHýÇjÀšA4Ä©:£h*$C¥GâkÉ PŒtÏæì;6жl)¡ë&[[ÇP#ÏÇ™1ƒs6ÝŽ^´”¨ÃÀ6âÐ$È$ع@¨ÃiŸGи("4ÃBÊÉ•$“¤ÁŠ¥©»J—‚‚,š ÉHÐ`©QI;¥ï-ÀFc6!gÎåµ_þ]«V⧦=ö!ªÕ(,˜Ïþû/óè{ßOÿ‹ÏQÂlJ;L‡¼0}¤ÆòRcx-F‘©s:b Ráë„£›×BÖ¼8&—’ #‘º•ÖF6Ø h±Hà 5bè™Ë÷|ö3VàŽŒEQ'×ã¨Þø8Ù¹³¹ðË_À\²‚"j¨4åL}ë©Õ'RГÉÌ4†™"1¨…¨hm% b#ú‚8ÉŸÛ¤A( pR«&U¤Dè#Èh4ŠìŒÙœÿù»h[± w´>"ŠÂ#k˜Ö©>‹$TÈÎîeõçï$wÊ2&P‡Ä›Ö…QhÍM’ê È#( A$ Ð1¬a¼I€†º…Ø­4T!eË$GørM‰‹¦Ô´a;U…•v#Ó=›s?w'åÓ—áŽEqjù#kÅ„aH†ÄS|Þú¿^¥B¶wçÞýYò —4Wÿœ¤ç:UlÒ¿$€CIHê" †–fï!|J»JÂ[ÁÞ( d;Ó¦o¥Àí4ÈtÏæì;?MÛò¥¸MðÓËÛ÷}lÇ!“Ëáùþô®GM2sz9çsŸ!·ðTB&*Uc¢H§©XÝ4Z1% ,CB£4˜ˆ­›´ë7 HËæ<2Üø˜ŽE[óŸe*Z=ù‘ š,ÉØiwÏæ¬Ïl¤í´¥¸ccÄQLGÄÑÔ5ð<ìL†…‹³hñbò…¾çMûý¤­o¼‚Ó;‹³>»‘ÎE§ÓI–9hº€L‹R“šô¯„  AAJöéG ln€n á…rçßgÔÐ̰,Šé?gÐM4r€l*=§{+7­£´l îXbù0ŠÃ#kExž‡“˱dÅ ^ºù“ìøÛpêÒ¥ÚÚðÇì ßÊŒü)ÌzZ¶º@!% KH" ¯(EA˶4p7!äc~-ÙœŸËq`ܧ xˆ4zÒ´~¿ç$NÝøIŠKOÅ?ê~gÅJ%N;óLö¯½ç×þ¯$JÛ6K7®ç¹gžedhÓœ~ÓZk„æÏfñÝ7P¹ÿ‡øßüaßÔÒL‘Ô8%`–a²E]i:¿RðÒ ¸S{±D|¿€POLTqrY:„¤Œ œÊÞjVÍœ…KxËß"¿dqbù8" §©©å³ù§¯:›WÖÞÎó7݈ÄÁ`Û¦ ¼ô±ë8íô”ÚÛñ\7ñÿiÚÒZÖ'°;Ê,¹ý*f]|1v‹ŒTþe: ÉS* ƒÄ@<|§öü#HUð«ææ}®Ç."æds”€ŽTN“‹!‚ w”®¬Å¢S^CEA0Eõ<\¡À™«WÓ¿öv¶Ýt6 ‰… ƒdû¦õì»æ:ÎX¹’¶Î΄„©Ú‹"\ÏÃu]Jí˜#£ mý >ÝtÓÄh%`®4•‚íQD›6viøY+æCøœö-ä×L-x´6N±­D»´¥LfRð&’Êý<òº×“ß±ƒÓÎ9‡(Œ’}½Ã,æ¹ ø³Ö¬apí:^ho6I•8Hvn\Ïþk®gåªU”;»p'Ü)UP«V™9>Ù¡!ý±÷Ù§©¥9‰‰ ÐÌs‹}”ØÈoÜ¥½}Óªà;%ŒÏ×jì fN¡@Ф ‰™Žù&’êà^öFÊ»vsÆk£ˆ L“˜8Æó=ò¥"ç^|1÷­ãÅ›®Ç9|#—ØHvm\Gߵ׳ê¼ÕtÌèÆõ&•F!A°ìì³é¬Õxì’KÙ¿õ9<’ͳEúE`¾i3dÀoŸ2FŸ†oŽ÷¾ ½}&Æç¥|tˆL[‘nÃJIHÒcƒä@Bwh€_^v»÷°ò “aÎð\—B©Äy¯}-#·­cÇ×§ÀßXcl°{Ã:ú¯½žÕkÖÐ5£Ïu ‚08}õjf!¿¾äRƶoÃÁH³ÓDþ%  è’žl–ü  ã+ ^8*© ¾^ÀúÍ.ÏãÞs:;(§ —dš‰8Ô‡ùõeo¤{ï>V½ö?aÙí]\ðú×1vûvÞx=v ÞhxhmÜ3SölXÇÁk¯ç¼‹.¤§·ì\³†9QÌo.¹”Ê‹/ÁH‰Kj1•}ÁÜL–ÇcŸçÀ"æ6 ÷~QyÞzÚ"ï™7Dß±¤Ê\Õ;™ã5^®ŽSGPCã“ìì6Ô ‰hëžÁY?„½jè[{;»oº!]8mÌÉ=GÔ8(‡æö EŒâä]Ëì ë’Õ©Ý{xê²71öâ6’I{c!4éGA赪ŽÍWêcŒ+g0ÿòKÚûúT8§%à¯DÆp«GpíÉŽÃûgÌB0èNàÒ˜y%Ë «BD¡Üɼ¿¯Ÿ¾ûîA"1RðFËw“¨šCWs’ù~BBÏ;ßMvÉ©ì¿ç^ªû_B4§Å“k•ÉÌUÐišXù_›¨²= q°ï®¾W{Þq’Ðú«!áVм«½“àà#‡`"]6‡I?†¨99±RèF:1™œRkŒ) Í 0­Šˆ¸™àèÃÀ›$–w€²aÏçùžïòkßÅÄú@üÙ½ÚÛ?Æ£“{Ÿp–‚þ¶&\z~©·—Ûqû \dsï ±yÒÖ°²Ÿv:a±i™F 1I€Ö-‹qØJSòÝ(½Z)x(&ÙR{.?wëĘ{âí_Öþ¯†ï˜NоO8çjô×%á‚ ÚÚùÓŽ.¢þAÆÝ:>‚ u‡ÆŠ_c×(C’67gB`H‰”™‹o%@+E¬±Ö„:‰3>I*îµÐ ¶±NQ4-ŒRŸúÕk¸Èa|Ï}ÚÿÁѰóYá÷ gµ@Í"\pf±ÌŸuÏ ?:Æøè(>47R‚T ™–e5ei•) Íí3MóÐ¥Šã„„("T K²4U49  n±ÀOÜ:OÔkÔ1†4âÀwï×þQ—¡ë´øåÂ9WÀ—¢Óf²üñ¬Y, BÜ!Ü0 $ñãÄ’µGH,ÃÀ4M ÓLv’M39+¡P'GèãǨ–%´0Šš› Ac£Ö’\±ÈŒÃ#•q¶z.uäøðÿÓþ‰;,ÝZþR8Ë%lÊ_Ò-%õÌ`M¡„3:ÆÄØ8*Š0iŒé$Ï X†i"- l;¹× d¾yœ>Hž+Raˆ#tédT!°s9ÂR‘g¢€ÇÆFy9Šp1~©à#¯ýßžßë‰÷§øïYÔßQ™E¹Ïìa‘4°Ç«POÏØ)hÛN^[Öä3†ÑB@œ†à‡ÉñØ ½Æ ‡¸Tb—Ð<>6ÊÖZ=ä=ÀºÐþ´Ñþ„ðná˜ÀL¸¡€:¿ ,.•8½£“l‡’ֈƹ!)Áj!ÁvÏ5pè0LîÏ4ÙF<=<̶ñq´¢Š|2†uúªö§çÿÍh”¿N€¿pÐ(¡w"™[È3¿\f^¹DO±HÎIO|K™â[þx‘ä¬4ÿ^häôÝÀy.ËÁEôk h³€¤$MÚ³yÚs†&ÂOT/ ñü€zRcÆãˆq”W‡>â—üx\Ã8tNñÃc0HÖ*— 8Àe6,°Ñ³2P0 /“¡\G‰ð'¨p0„1<¯Ïêd ÛG’j$æÄpBŸn”ÆÈNb­ ~ƒ ¢¤!+ $’m¡ÁÕ0.`B${vu ñ1?_ð‡ôõ?úãóÿú¬–ƒFÐ35IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/messagebox_info.png000066400000000000000000000111061217176075400257440ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ IDATxœí›kp]WuÇûqÎ=÷Ü«·®$K²,ÙÄNLžP `JÚ&NiH2С3åCû2ýÀôù¡ùÐÎt`†–G_PÚ´ ’I“!@ðè!$8ÄŽ±,¿®dYÏ+Ý×yíÝç^ùÊ’lÙq0 ,ÏÖ¹Ú>wŸõÿïµÖ^{í#a­åYäÕVàjË/ ¸Ú \m[{úûûwAàb?g¯Zàq3nxöìÙñÉbqv3÷ë½{÷¾÷“ŸüÔ?Öj5ñó…ø¾o?üáøôf¾£ëõÀs´Ön{;I’ðóJ‚¥RJ ð6û= 0;;KµR¡¯¿ÇqH’äÕÓôU!RJŠÅ"®ë^’I)¥ñs9ªµ* T*¡µFü4¢Á)%Æ>Ììì ¾ï£”2—ð}I6›ehh˜ŽŽ>ĉ'B"„ø™u k-J)jµû÷ï'Š"FF¶‘Ïç—0{@ çylÙ²ß÷9uê¥R‰;vÍf‰ãøUr¹¢µfvv–cããtuw388ˆçy—4Åqº»»ñû¹𤦖éfëè;ߨË[ûÛènÏÍ(°P–NM—9<>ÓNâ}é(o½¾wÞ±‹ëoÜT›çಃ ¤VlC¹\faaž|>ÏÈÈNc¨V«lÛ¶ùùyŽŽ¿LWg…B)%µ  X,¢Å@w}ù'<¾¯FûènîxÏvnÜÑMWN!-$&mMÕDFzrܼ½ûæJÕÙ7>Ï“ß?Êã÷ïûÕ“”çâM/DºÕÿ7?]jÂ8baa0&—ËQ«Õ0ÆàhÖŠÌ::;YXXàäÉ“cÐŽ¦¿¿—âÄ"{ð9:Æx×ÞÆÍÛ;Q‚f€/¢‰RŠ[¯)pËÎûŽ]Ë#OàÀÁá{3âOö|qc ÖšMX@ªŽµ†jµÆââ"¾Ÿ¦ÉÆXªÕB€”jån©ºM“ósi]AX<×á;O½Ä'+²ë¶·ðÁÛÆÈ*ÁüØ–\ªuë½ šÞ»sKòþ7ñäîm·>úŸ_ýª/îýãª}à‘‹`/¾ ¬l³ I’°´´L…lÙ2@.—#ŒµHµþ1ƒ ­Ù9Ž&“Ñ<úг|âë3Üþ®;yó5=T+P €Å¹Çµ.}M7P T ¶åÃr5µˆÛoÜJo÷{þ§3ÿ_¾¼÷CUóÀ6$À® sÝ@c»\–—–ð}ŸÁÁ-Xk ‚kõ…Džçð½§öó©oÌqû»÷²g¸ƒ©³`Ì9°¢I@ã'  ö€«a¦óËéçVmmSO T….îùà;r_0öß|qïrÕ>ð•u h2|! 0ÆP©”‰¢ˆ¾þ~r¾OEXkWÌýÂbq]ÍÄ‘I>þÐ87Ü~£=Ϥàe àV"mYØûzêIûk!|k¼x¢…„½›JèË·³÷î»r-,ü“/î¯Ún@ÀÆ«@E”+e¼L†þþ~„DQº¦K!6µÞH™&5Ÿ¾ÿy¼k_ÏŽ¾^&§c’„l™oæ ÇpÇ-r<@Ö…_¿ - ehzݪ¢Hƒˆåše ½‹Û~÷ÃOž:õ±œ¸÷Ýû@°–€õ! µZ0 èéé¡­­8Š0Æ å9_ßÌzãy.ý~Rïå-¯anf™z5Iͽ1墚}Æ‚ç ¶õùkžâ:Ðß21ã9M+h­ Ù•¾jM0¶¥wݹ÷ÅÏýû=À¬%à< H’„jµŠë8 £”"Žãt–.±**•¤¼PæáïO1|ím¥*K µFU¬³õw „uAyÀZ7[\®S«$Î9ЭXVÈ0/Ôì¼~'¯íG|q÷#Uû`iÍ`%ŒB¢0¤«³“ŽŽ’Ĥ³~™åàŒëðígÆ9i{¹ÎËpvz°"¤Xx½V-OýHsÏíÝ«Æ<~&äùƒ‹D‰%ŽVƒ¶Ö®n›ý•šÀkÏ2òÆ7ܰtàÀ]À«0c¨×êh­Äu]’¤i¦—wŠ.„ ‰"¾ýÜ~ßn–æYšoO¹r¤µÖ—¾Y%ŠBÞ~k^Frèx…û¿v–ùÅ­šyÉj 6Ƭê³ÖD!=ƒƒäFFÞ›÷>X±˜â8"¨´µçéêìL×ÝWx>˜7$Åcg94'q¶f˜=3Eµ´„”rUkÝŒ/­®ðùÇÊ<ôÍS8ZR*Ç ŽÔÏ÷û–Ö$Á˜Ô‚+µ*ÙÞ^:w^s[yb|8 “$A7³é=üÅÀ§I‹äåc3,©vœ¥ ³sĵ²qŠ{>ëYC¢Ø°¸˜Ž+…@Jð=½Æï/DR)M~h¨Wjï¦\×Õ}+Ê»8¯˜€V)ÎÖuŽÊ|‰ÒÂ"&ŠPZ­¿‘;D±åÚ±î¹s'Ž–+sß¡9~ê8J®u°Ö I¶§§³}ð0€žŸ››þÎw¾;^«Õs’é¹Ú 1çoýݘ4…·å ™ÞNgǘ/~_VíýF?öØ£_~ì±GŸº`Õô¿’ÚfãÚ÷íº÷ov½ç¶wÖ— ëËX#0ÊÁƒhVR ÄÚxÄ1zøƒÀ¦ ™•™}‹1IêA@’€Îçú­$,kkm8Õh—%kr ÚÙƒŽ^O¶m[–g¨=@}q Kíu¡ÜJgÒ!‘­ÖÐâaL’¬=‹´&ÍP×`,†ôjmzreŒÅ$ &‰°JÇ!R+-TšÃ¯9½¢Ô62î[H°" °Tg çE!ÂiGyÝèLÊmC¹ù” å •FJ…ŠÄX„X?ÙŽã˜(б¶Q._eòItˆ‰ëÄá2&\Âõ²Äån¬Ö*e_¤êÃõoO#‰†8 ç•ã ,ÖÄØ¨‚M"L´LTEh¡sE6›rR'’8ŽÖyŠ%¬W(—qØ$Ášc"L`¢&©a¢ 6ZƆe Du 1Ƙ%¤¨_q„ðÈ´ý&BæÁ†¥«µ3Rk¿ á¶At҆ŚYˆYé‚pA(¨ÅÕòZøÆRš-R™E8L 6šLÐhá¹k ”@:>ÚËõb­òÙàŠ „K¦ó·ºl(’ R= ·­íuÖ«)8é€p@èFKÏüÒMM XHâÆiï H’’:V ° ØL”~Æ6 j…h鸸¹ÊÍV–4Gºbè¶7!½Q¬©ÑRÓ!¨/Ë‹¥\a¸Ã=ÕG½R˜¤1Óú ²A*U ò§K–Æ^º¥„$ØÆJne:†• *ÓN¶{„$Ž“ ZÝ×押*«²× ÛnÅŠ0Ý ·4+ı…“Ç_hß²·m :ÛÙ0q'½JdD£É̹>ém ¢h¹'Ó2N£‰f_jeBy8~¶ÁíTgÏ6‰ÙE pºÞž²/H¹ª©ŒÍx,“×ä ÛqóýM hú{3&H§XЧVÀMšm…ˆtLåuíÜJ¶ÐÇ≉¯3ŸY¼¢éÆ*‹ÕrMÃÕT—^,ŽŸ)\³‹lçÖ†´€nZÃ*ËhÎî*J§…(§åºzL¡³dòýtî&¬.Uʳ³®æŠ ã´T»A“®{üÄžÿ|Û@m»Èv#Ý<é *ç+ï‚r@éÆì¯©Òÿ_ßJ ³2®ãw“ë£slŒé/|98ùϵue‚ Zù±>?Z±4³ø™éC?~ßО[¶×Ë%âÄP+Íc­< ¥B¥ÅÀ4²ÃµøUèÆþÁZ‘ŽƒhWÒ¢,~çý×ÝLy¾8³89õ÷kt»ø­’X%6nR =÷ôÑ<÷B/˜ën _ØN¦½€PÕ@:©²yž—r-®«Ò7ûEËÞAÊs+‰Ð(7‡ß=LÏŽ=dû²œøá3÷…G?¾~Uø‹¾xi\qœ|ñÅ'žxí¿w÷ŸFÁ 4KªHP©`mk}P µÂéôøâ㌠õà¹é‰§ðÝf¹.ñó>Q¦›®ýVj´›Áïè¡{ø5ô]?Ê‘§¿?ª‡ÿ¼®^Wâ]`Þô½qy½Û‡ÿõuwþΦ/qvüeÊsSÔË%l’^]×%ŸÏ“Ëù \×I_–@`¬¡Vêõ•J…jµJ¥Çn:ã“í,Ð=8ÊÀžaŽ=ûÔ7fŽLÜ¿ø·sëéóªl†.$ÊËÔgNžù£}O<ï¹ýÎ?È´ßÈô‘v*³“ÔË‹H›àg=Úòyr¹~ÖÇ͸7؉1ÄQD½^§ZuQJ!„ „h/‡ßÕOÏèvºFÛ8úÃo}ef|â“ ÀÃU°«%HAl›ëíø«ëßö¶zîPfæè4•™3hSÇUàg|/‹ïûx^·ñºL’$a@­V£Z©P©×©Ç ¡QH¿‹Þk¶b3ËöÈÿ=ýé¥33ž<{ßÚÍÄU'@¥9‚¤«÷ŽÜpÝ}#;o¼EYÌB'®ãi‹çh<Ç%“Éàh!%&I£ ¨‡!õØX‡8—#ö S§>±ï…û§þì‹*ÃU&%±Jc»üÎü¶^w퇆G¯ymw¶‹v¡iׂ6Wá»ÏQH!ˆŒ¡Æ”ƒ„R”0%ÌÖKO¿|úðÁÿ.Ï.ü‹ýö_NoVŸ«NZa‰‚Ûåä¼ßèèÿ­¾¡¡7öööô´·»¾ïjP‹b«5æ––£³³gOÏLM>»xæÌãQ¹ú„ýÚG7 ¼)?34û¬J]IW‰LfLg2áèB`¢x. ‚„„ÑÆNÛG>rÙºÿÜÿ©Ü+•_ø¿ý%W[«-ÿõÍ+°J^­IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/messagebox_warning.png000066400000000000000000000122641217176075400264640ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ{IDATxœ½›{ÝU}À?ßsÎïwïÝM6›’@IG€ˆˆ@Áò²j­µ*VÛjÛQëØéPýCg´­­uÔ¾glµÎØékÔB©ED!Fy™l’Íc_÷ùûsúÇ9¿»wwïÝÝä;ó{ïïqÎù¾ç\ùðM-&Á37ø®_g€!úJ³|Ýç_¹…C»~È®§«o~—¦›Ç¼€Äµz?õ÷©Âg¿-¨0Âé sï»Üs;Ÿó8mX‘Ó'¾5ƒøSþœÄÏ{?ø/ƒ;Þá½ hON»“ød’à—Kt'€æpúÊ8HòÖy7çÍÆ¥6kÏjûþ³>¬ŽÎ×^9ð¯2ô§%ó­-ÛoÛ´vÓ6Nì^NíÀÏ8:Üzð/¯öbŒµÛWqÆŒ^{Å9›6\±öþ5Ë—ðЯÝÌñ½_ùêÎã¬ö¼Š«éâ~±°þÌ ¸îûal|c£”7^ËíwžO)çý¨ÛÙ±ñ !€òÎàr^ô Û¼}=éÙkàÄÞ°ç`x'ßs/WÉ#À¥sq±K`8mPpâf^péY‹¸÷º‡?ûŸép?cÃèEK¸ýÞTr>v*ƒ¾\F(% “_,ZªÅgo¸ï*’ öļs`[à(̆;àâså×Ë´°7N“ózPÈ’—Á¿yÃM«—±ùÊûßÝóMPe¼ux›ÛBúû¸û¾Ë>~:“œŽ&¨Ó™èTA×ùü–·Ý2ãä£'qÎGX°øаç)V︫×Èf•q—³0ÝÜh;p®g”cçù… õÐlò+ç®Õk/Úñ[äÏïS¼s8gñÎá]¨Ó&Ž îxóU,Ö|r'OÑàçóè/VÀÛø;2!ËÂÊÆŽCu˜;¾‰ÅÂcÀ²Ó’Ê<›·L«LÛ×zÌ}–q|ð–ßþÙ¾Çi5«àëÎZœ³“šÐö.øÛѰïû,yÝ6®¿LSqü^YCO4³ÜÓPéÀÎëÊ:Èóî˜åA(Y¶Ëõ¼ÖFøÔ¦­ËX¾ñ:ŽýôÛ ÊXëp.Ç:‡mâ[`‚ÇY&ÂÁÄ(LæÎ‡¶3`ø°æ”D;ÏÛ=‹!?íÍSˆ>kú ÜúÈÇhìüwhfU½8’€1¤`J K *2%¢‡—ž¦ÿº-ÜtE‚r|B3K\Ÿ#_è–£ éÑð3¾DèÑEjäñ·¯¿w-‹Ï^ÃÐý3:MÁyQAýOîû R¯áp¨fŽSŽ3VÒÖ:¼k">å¡~Žï掷ÝÅã?øÊ}ãp9ðÌœ"ð]ÖØãVφȼˆŸ©×TÊ\¿íÄÄs_— ˆùžúÈÏ©\öÒ•W ΂IÉ3ÏÁ'?Ǻáýè%+ðÒB¼¥á¥§)_}7oþ7¾ö?õOa¸iNt£´ÌÞšMï»ÜkŽðÅío¿šÊà†žú1J¥1Á Á¨92ÆàU÷²ø†™©þ™W¾‡Ö6@VÃkA” Ëk´`ègìxëÝ<þ½Ür"ck¾9'eÒ{ý|QÞsëDçC‘6ýº/®w¹×lpï‹Ù¸õí2þÌWP9!¨XP¾†ÒýÝW¥4Þ\#›Z'à`ïH.¼€7lYˆX>3'á§Ðä™§;¿)Ï1¾¸ã7n!qMj?•*ðE–çñbƒóÉ›]ß÷žÐ)v60¸“%—Cs <˶·¼‘•6V4¿¬ââg ïq½ ¨’ï…½4ÂC³Î»W­Q 6=ð^N>ó5HxxÑ¢œCy‡¸îz)Î’«2ÞÇ)>0/ËÂÂöý˜ä¼s¹eû™˜Ÿ’žÒ8…53:¢ºYåÏî~äÍȉÈŽ@+8‡¸`/Òæ Ez¤^žÀ€<¤ÈÎy|ÛZ-Ø÷47Þ»•KXZQ¼çÔW:^v5بóÑó/J¸dëýŒ<ÿ_(¥CÎB¢J%ﺷ °¢°YŽÇã"Èëðƒob*#Üqó’œOKOgÍ2~¹]á[çßøÞwb=M62Š"(4 Hß8‹ê¡bÞ äM¬|îƒx…Ïsüèa> õìz–ës—C¿áwË]‘i(PéÀrQRî‚ÉuvTæÂê(Ÿ¹òu¬»b3£»¾2ªM¬àÚRÇ;‡UDÆtK†Ây‹õÂÕFðÃGñ#­ ‰ÀдÛo]N¬{94/CV)ÅÃÛÞñÙ‹ßÁ×'PÆà½í°ùɘ©¨,£W8ñuô¢±­*ŒG7-¢Á›˜×8XØõ}.¿mëÿç?ÙuÔ8ÏyëÉîÁ%À,4*˜½ÁÑ ë£üýë·¬bÕÚ5Lìe à&‰ïÐÞ¡ÉP&Gãð*ï¾F!Ô ÇŽcÅÖ,^â|EîîâƒÇN Ý8wl]IjùUàêYÈŸ&MòÔ¼ÿU•27Þú›ï¤õâ¸V¬à¼GœCáPX´8”ähñ(ëÐÆczúÈî'?–ƒ­¦ ι‚7v=ËE7]Ì…g ©á±S'=€2 Š3cÀèÙÑ{¨ò7¿i#ƒK ‡vGÛ÷(ïPâÐØ@4‘xq¾kÝ# çHýh¯ÎK¡‚'Ç‘æîܾ†¶.NÙn¹ý|@ùS÷w/]Ìú->Du瓈w¨à²PbQX”ø¶äµ¸   •õv‚‰Z­mH EÖÏvqÞµk¹d¦”ôЂ9è;å< 1Æßm»ýR%;6„Ö‚R‘pJš€ ŒP9b™å(Bj Q¡c+Òa3Ehµ2¾Ÿ;o_KY¸l ÌÃómïµSa!GTP;Q¡%ª;¶š¼ëìsTÿ5wÜEõ…ï i(x¥¡Fr4--5 I4%Z¨êñž ÐâI£¦I¾SLŒH ì>Àª+Vréù†Tóq Ô›Å3á”4 5ÁŸo{ð&ÒÚ!\}# pQ̓” S0â#´ B&ŽÃ¾*Ô~ÞulÑSSû‰R0!ŠkÊјNµÈ3dx¿t×T„Kúy¯ò±(ê:~(ë Å!‰¢%W´ê;±:Ο¬Û˜òÚë7S;ð4JT›x…GœVE2‚jÕPG÷ CÇÃÄåò‚R‚è`ZM%~ á`4bñ…‹¸ê¢2Úñ àŒù u¾°È¶xô®‡nGØ…o5Ð:x÷`óYÛÞ•8”92z†"ÕUÝ2q´û Yå,:•„ ã¶9N‘¾Lµ‘Ðô?´›7Ýs¥ðh;ªu`11“m@£:‡®”Ú(yŦl¸hµß j -9B(}P"PAFŽ!u&ô@QÀ ðÜsP¾o ½)Šƒ¿-‰™$ˆ› ûS½Ø4UH¡ÿÒÕl¾¬Çÿ¯öàsÀ sIºÝ›¥ƒ´Nk¸ýþø#Ï"âÐ"1Ù ™ŸàPZ «##G‰FXt‰® ©)ÄÞýdœ. ` ÖšŠõ„ë ¼ ¾“ >†‹»¹çÎ øî3?d‘áG«Ü?g4ú©‚RÄT‡ßÊB}œ/l¾þ Î>w!Í“GÚÄkqQ‚£‡‘¡}x¤Ò‘AEÓ ”Êø’ahvî~ºF%(%` Ôá£CXP2Mý§%J`¤Jº¤ÅÖk±÷1ã6sC›ûJÜpË=·à†~‚òÂ6̯4ªqŽA5òIµ„¸ªTèìAÝ(l­ÆK'4ïúëÖÝŽË-¾ñ(#ÿúν¼LZi^µµ Ýì/:½méŒða®ƒû¹í–uü÷SÏ`R>l”MGññ.´v5‚ÁãüÓ·­æŒAK66R!ãCk”m¢ŽîCQÍ<ع‰î[ë m7@L6AD3îû8ç£GX¾ñ—IÓAÊ}K9ÿ®ÏSyôë´†êP©@ŸO’Éqt“•覘@Ç–¤o„í7-ÁÕ¹xÃlVš aÓÑZ\q&+·Üz þÈ‹mŠ€Œ†»a´` ⣺ëdò3)°­œ¾Û>L¹40c!ËÖݬ¿²zLJáý´ØEÒ ÍdVÖ¹ÉßɆ‡¹qÓ,=– ò·³2 Çu±uþæ†[׳ÀŒe-”ÖHs¾€>ŠXJB¨BGâµ™dBA¸Ž[_&þ2É9·ö\LrÉŽt”Í$Ót4¨`ªÑ޵XmñU!s$éÛoXŒm±âÌ o,Á` K:bÔšŽYÆ£«VJríup'O =øc{ñû÷ Õf@ŒÑSˆ7Qõ ‡gÒ@x’D(#µƒ½ÅQ? å… Êqß0¾ÛÇÄ¡[g™ÁÇë'ÇÙ|y?«– ËøR/iw»¶B{{ÝÍ(K|dˆ|ïóÈÑ‘0]‡âÕ4É› µâŒœ‰ ¦å>xáèpë‡àð³°`)èJÜ4í”|Ô„$™ä~A¿ïø,êeÚqûæÅX‹^1È[²PIGLJV¯)óšµÔžûùžCHË¡L‡hï.DâŠÒ7“„&`Ê”A}ƒ0ü<û1h‹s0ò<|÷wwKý‘Ø2$•¨þi`‚2AÒÈð’/º&S3^{‰°z™PR< 턦ï ^’j¹òü÷â÷ñ5¡™,H:¥¯tЉWIÀÂŽL™èÀ $}°÷›0ü ,\¶¿F÷BÞ„¾%a'Èæ¹ÖFoŸMz}K ÒøÉ^YaûmMðm*•¯sçæ>þô«UV/åãÇGyWµÕÃ|äœeÂj3†­ûÐéHâÚÑGU>†<Óá¦_H¯0‰Rí_>²ƇÂõÊâp/)C5F'ñýø©’©ÌÖz’1E»¬8£WleU-oÔ\°R0Šwë§Ð\¨Cn¹15Üwé Oª€¢*+ˆ.¤/ÄwJMV/…¤U‡èôI%Ø·®@Ú•¥P³(ø]Žö}@£GtçÑ‘Éd(,ÚííT:^se›üÒõ†fÎX8õüaÛÒ’|hÃrXµÈã|n‡ÔÛi¸†)IA±¥ƒDT2é LԄ¡IÁK=MÛiy2>Ïß´;1…m›“ñSÇ–»6‘PŠ®i‡3ŒŸuaõ:Ïeë…—Npçâ 5ð€r~?Öñš —¯yÃæKË¡ cjáUh@û„b!y]ý€êðÜ…ššrTã¨þi ’þèà*`ú¢VôÇg;œ¦î›Ì™šk´#Aô-"Ñø¶äÛ˜;$ËyÛöÅ\ÿæY¶D½M@ä¯#.Úºƒ‹*XGìуï(E@b÷'aàŒO¼…ÌgE#žÿù{fÃ6>ãc×ÅIÐÑa")vĆÓX6 ZÑpÐô@Îeñì@Ö5ò°µ5žÃXU 5 MŸu0•ÖI¶ÿÊ»YÍÆmÀÂ`êh©”—®BYHÅŸ ¿Þv‚è‹ZP‰Î(éƒeHé•*Á–Ë2ô- /•+, Òu M¿EA$!¸õÈÝ<?-®®YlZ5Èj@ª `$ìgãaã4¯C£Ri\`Nç~Õð'eg]xÙ¢Uÿ»w)0nð xFöÄ×ðç]L-9AóÀÊ(­ ¢IB‘¦Õ4¯ŽQ¼š@œÂ$І’Qä^£48B¥ ¸$§¡ä‘\ãAçëå-Î ÎçhçÈmØ^÷XlölËáT¼Í,b-™µAYòÎyÄép"Õk°àU`@)5,;k!Í'¾Íá矋µ%¦ž_L³æv>÷äþãÈžÁmõ1¨3ŠE» í!— ,£Æ‚oPAsuô=ʧY8_b$16¼kŠ+] ÿW@lzx ÎÄ­°¢â‚ÅØbˆ(TqÁœY Šeõä3®ÖàbÃÉ”„ýµ”Úó_eçóc_>x$‡w8†¿«X¾HmL”.Ì2kZµ8²hû­+E^@Vët̾]ìC¬ cŽ’û°傯òD4žàÀ•÷(3XJÃûpl qAbÚ#"áÔýÊ \t&+úSÊâ[ñ^ð"hïá§'ÕÑï¼äžxv„Gré(«wFœ ³íÎÑnzEa–¹þâ‡Ð§&÷N'[híW%jŽ 5œ;·oò]p济¾Ñ‡YsÝ8J´5jwҚ؋µcøf‡ErðbñdàÊÕñÿ—,¤6Á…&Ác@Y”R8‚ŠIÕZ/À"¨…ý$RAlUi€?—Ü, ,,§!Çк†q`­¦Ô k‘F™5G.K\Ï&¤odç!â߃õyþâ ûؼeaM2 ti¾¥·ÐwÎïc’Ø&d%0 KÀ•A5€¾QüñZidv =aÐJ ª¹ÏPÍUªbo€4Sò:i‘“¢Ê Ò!ÃúK•M†¡Ÿ’´RJƒ!8¨ZðA­c5‘@•`c:¾w6‘Šÿ öR+™ÖzöÝþ >uÉ«§9ÏÿG°˜ØÕQwIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/network.png000066400000000000000000000164711217176075400242770ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœÅ›yg×Uß?çÞû¶ßÒ¿î_Ït÷hf44ÖhÁÎh‹m0Š7Lâ2 ØEUPIB *aIBHÊ¡Lᔉ“K ¢ ¶±cdGÆ––±…,˲µ4Í¢Yz¦÷þ-ï÷–{oþ¸¯[#I#[&¯êöïõo}ç{Ï=ßï9ç>ñÞóÍñÛ>BU×àDÀûð(8ðœÌûö#jADúáuð‹wÀÅó È)„Pá+ÐÍ÷zižsà…¬Ýfü‰ïù†¯Ý|ÓÖ¿àáÁùkÁß¡£èŽVbþ^·eövÓ¨ÓJ ±”pŠÊ2Ìk†y½:WÏŒ û׸êœÜ,ƒ|K®ò[€oãý÷ˆÒ?23•|çÂL–.ôvL'L·cÚ™&4‘Q¨Æ&ë¹åÜêä_ž_Ÿ,Ç“OáÜÿùËWúj_¼¼o?®”ù©¹Ùì྅6{wdÌϤÌt#º­ˆvbHbMl­.òç±ÎSTŽIiMj6Ç%+‹kù©¥üÇN-Ž~lm4ù,Öý¨?%®^!ÒT¿½¬ä½Yb^½W‡ý mvõSvô¦;1Ìņ4¢Ha” ” M pÞ㜧¶Á&…e¦3Ó©ØÑ‹™›N¹¢Ÿr|qôæSçGoOŠÿw O³×þM oúƒn–ÅïOcýϯÛÛãº+§HcE·eØÑK—7´šY"…ÑaöEd{U_ì‘"%Ä‘&Ž4i¬IM–hÚ™aªñÌ™á;—7ò7!îç€ÿõÿ€ìí¿ñw–µ=¬¸iÿ4ßÿí{˜ï¥x@”à}ˆöÖ… W;Oeè›ÙwÞã±ÌÒfɹ•œ“çGXàÜÙÕýŸúÚæ»þé-½ß~Ùç‘㬠+ò¢Æ‹G<£0"L*ÛÐbÉ·¥S=;b˜Æ9¾8æüFÁùµ ›Ã þô¯ÿÙîýN¢°/ €O?ºñ®³‹kQÈÛ—oÙ¦(U;"íÑ"(¥P⃠ïpÒHÑkGDF1×K(kO¯UÓŽ_}vÈž\åÙó9V ‰„-ðóDQˆ ƒ¼¦¨,“Ês˵Ó=;â™s#Œ‚õQÉ™å +eHÑãþ‡ÏÞüÈÙý7ß¾'~ð²(,ê¾GWßáÊ‚( n¯• JáeKÓ{J ¢<Þ{rmQJá¬C7ë^)Ö­ÄÑmEÌMÇ´ÖB ǰ4¨XÞ(©-¤‰¦¬¶ö”>Ða; Ú"/-¶vlŽ7Þ0˨°ÜóÈ‘Q”•e4®X—ä¥ÅÆ–—7䯟¼ãö=³—à’Jðør}í‘“k7å·g^éç¢:[ËÀy*•óŒË†¦ê0&•c3·TµãU{:¼ñ¦Yz1kÚÕaÅÚ°&¯£²f\XòÚ2)yå(¬§¨õÅ‘b0ñ Æ–²v¬ ¯}UŸénÄ]_º@壊õaÅ ¨)+‡k²Ë8Ò¸ªä O®¾eq³¾¤(º¤|ýByûêú(Ò²åÎ!F‘"Žz› BðN°x”òTµ§¨k¦;†×^7Ã5»Ú¬ Jî}|•4RÜpe—ó-Æ…'žXžpn¥dsRSÔžÒZ"¥H´°9ª)kÖÆ–×];ÍÁÝ-~ëîSàåÖÎQ;sÁKE9Œœ((J¾~fpÙu»{aÊœ¾,>óØðf_Wh­BÞ®…8RMqÂV =Py-µ…SwœfÏlʉ 9ùü9Ö†5ÝL³c*&6#Æ…¥×ްֳ.ãÂFÁÉå1É£¨,±V(-¬k*çÁÁú°æ–k§xí¡>¿þ‰ãÔuOÖ»&Y¤YzZ ‘(Æc‹Ò°²1n?³\ºùÊäò8µZò¶Féàò‘£è¤†~7¢›E(%µc׌JϾï|ý.nÜÛå/Ÿ\åC÷Ÿe;²¦¢ã¬kê 9+Ú,VØÚqlqÌÕó÷<ºŠ²H£4 &çëlLJ_Óãß¶‹_ýø1ÊÚ¡PW@ó>ÛÄù,1ŒÇÐ(ÆyŹõê:à3—€³v—·aýkè'‰43ˆ«ZìÞÑB ¬ *jdî?ºyŽÓ+9¿õ™S|õøÈÝTÝ/ œƒÑÄQT%ª) ?µ8a÷l‹kÚœZšEÂ(/Ñïz^óꫦøá7ìâý?ÁhbIµo‡ByOi×ííPÕ–§Ÿàl·تæüf½ïR¶^çfßÈØ@Gq¬˜éD\·gŠ÷u±ÎÓïÆÜݦ“>ôùsüþ½ÏR”ÐÍ4•-[ÅÏ †Áz°6è#ðŧ×xÛá|ø¯Î…%ÇTÎ3—¼zï?òÆ]üú'N²6ªè¤ºÑ å@aÁ ¯Ùßãû^¿‹O>p–ÇžÙ@iP¶Q¡Þ3œ¸KK. € -Q œÝÎö´@bÓˆÝ;2fÚ;{1kÊ~òw=´„s¨3 âai³j  lƒÙâG𯅣*k^}e—g.Œ0¢Xݬ¸æêi~ô,ðk;ÉâzE'‹°Þáë@_ž :_ÓãÐÞºï4_'‰UÊIJÀhauLç²ÐJ¼V +‚"\°sžQQ3Wä…emPòÈ3<úì/Û$ÑŠZ<(aG7¦›ÖGP‚n* ªyÜ@º-QÂñå‚7ÝØgúdD>±dûo¹i†Þ}šóÚn[°NÀI“B{zíˆ};;ðñ/žgu0A+Á ˆ ‰Æè /€HkL¬ñu˜.ïa”[:™!5ñè2•õŒ Ç…2äèäUJxv¹`~Z©¡¨Ýsepy.1„N¦Q3©aG7fn*âM‡f•–½³ úÂ"kƒ’™–¦´ÞáEÐFØÙÖ´RÃÙ•‚óu툵¢´@ –Œ¾tñëÒ$zGQ¿–aRZ¾í곘?{`‘,5d©¡v>—Êa½k-”u¨u2M=âoe…J„vr£…ý„k2ÒXqå\xž89" óÓ1ç7*jïñ^H#!Ö¤p<{!§¬F)¼òØ­9vy³ÖÌÏd$F.€$6kiïɇAåÝrÍ4iløó¯,ÑmÅ´+G”×H°*̨RMÔ Ñ»´žÈQ$Ûàl±ÁTf˜Tg!mZ©¢Ú­ÐC(-ı0Ó1˜È€ªIc’ˆªªN,emÑZa€º üç·*)°=0;•ÒïµÐZ-^ÊÖKúE–è³ívŠõ«vwP¢øâ‘œs”¥%ŸXòÊQ6Ui(K7 õVä€Vã~ZB=aºQº0[&/Â`ìieBiÆEÐüÉcRzŒöôÚ†8Rµ%·4MdúÖE;ß”—|S…ò´Í|¿E’ÄʼnË 6O´³„Ý;;´RÃ׎o7³žªèWU¨!¡ñ¡¶Gˆ(¡jRXÕ¬Ûn¦C`ëy¥XVìÝ™ÐÍ òøé›¹ciX³1±TV•ž¢l*Â*в4Ê/ÈQw®Ù—Ð&ÂÎ~F«“d1‰VO]ÊÖK/T=ÔŸnÓ‘œ'¯4F„×<ÃCÑÒ×Áµ›‚Iðµøª:P]+*çq@lÎÃ0w¼õ¦>Wôcîü«%æº1D1ÌkJÇÎŒ&q`"…XÀ…¨¬c«àèlÈH}(0â<ô:1SYDš¥¤Y²)F?qÙ D=¸g®]æNcÝEY 4e[·W?÷£Û^ð\õ(´¶n;ÐeÇT‚"ô µR”•ã{o›a~&áÃ,3)=ËÚ£KŸ}b@¬=£Ê¢ØRtMQ5UíEµÂƼ÷h#Ìvcâ$¢ÕIÑQüÕ_}Gûòc€ŽuÚñWM’’f1lýðÖ–÷\K{« úxÏ]¨Ñ!XTxjzˆ,5#üàëv’ew=²NË(J +ƒš‘åüFÅÚÐre?£LæÅeçÂÌ;çpÎmW“=ÐkÅ´2Cš%ÄiÊë¯I>w);_€÷~WÛþdfºM·Ûjê€SŸó„P³·Ömí˜(vªñÊ3;®Yèr㞌ù^Ì»në³>¶üß/¯ax¥ð"Û3'š¯/•ìŸKš,/¼¶å΅ꓳç}³A#°ŸRŠþTLGì]èrÅŽŽÝ3“üñ ð‚%±«ûñnýÒòt;-òWUÏ“²žànn»“*BF ¡“*´RôRÍMW¶¸ý@›¼€µQÉWOOxôô„,&4:÷ñ Šó57îiÓK5ã¢ÆÕÁðªvÔ•  7M#NcºÝ6­N‡Zì}“ñâ‡+_Ô¾—l޼ãg?ñ¯Ýñ–ÿzâÄY66†Œ‡Ö–´±c= šëö¶Ù»#ák§rF“š4‰š=BÎŒR¤±¢(=^ÙZ;à‰ôų{§Svt5Z+–7 M,Yå'WYW\1³g6CE†v;cº×Áe3ùGþóOßväó¿ù˜¨™þËñé¾S¢½7|p×ÁCß½{׎7‹€QÂdRl{BleíÈÃõW¶©,|îñ Œ ;½hz 8 ]FAY‡ njBM¯¬a8.›Yo´!#T¢vyi:Ä… å±=3 7îNØ3²1)yf¥à©gG 'ŽéÌpÅŒ¡*º‰"/,‹ëòÂS”5b"â8¢•Æ´§{<õÔég~ïw~  Î'Ë`O£ã%–Oæ~åÎK6F_€Þ(®8”R•;€½àw³ä…ÞwýC?ùžwÿ°ÉZ½g×©Ê [×Xxíù‚I!:äýq¤™›Š¸v.e߬A”âäRÁ‘Å K˰¨H”x´QíH˜íhR#œ^.qÊ#ÊE†4‰iMwyø¡£GþÏÿøðï”ãÑI4Ásüi”9O>ØôÏþ÷úåÐý>ÅîWµ¨Üž+Q,= E^¨{wíy÷O¼óû÷\½gïÚÚ&eQaÃ[‡÷a·H¬5óý˜~;bo?æàBŒBqnPqä|ÅÓç ÊFE¶¢ÐN,Ú‡ ‰ J/…V¬XX”ÖDF“f)ÇÜóé¸ëλþØÙjLUÀü ÈY³Tõ§>\yú’†¾4µ›ÃË^ÄÏS@’R–&n·¦¾çÝo}Óß¿ãÖ[ÊÊÊhœãc¼fOÊ[nèka}lyôlÉÓË–a~#l­ ÉŒµ–Hy4žÊZ”¬·ÔÖ“E+ÖÇž8Ö$í+«ƒñŸüÁ§?õð}>ˆ65F•À$ÀpäEµÁéUÞŸ¼üª0ª;˜Ôˆ/ª¼&ItYÖùGÿSwýÉ'þá÷Ýñ{¯ZXоF» GVñЉ 熎µÜQ:!I4³-ƒQa+¬s`ÃZÁ£pTVSëÞ…º¾1Š^Q:üƒ_xü±»>ú™{—O9K’‚êfT@‰P!b‰Œ!ã_€ñ9­-"Þd“æ3 ï•2J%qdŽ<þÌÑ¥ÅåÅ;Þøšß~ÃMí™™¥³ G5ç‡5FC–(Z‘&ޱ æ¨ÙüPV.”³mh°FÄRÕt€ZiÄpâüSOœyæó÷üõ—ä©£eQWªÝVι Þ£Ã(€1ž¥*Æ«îmä%ið=†vÚÂW;ð²Ì²µ D%F«4Ž£$Í’4Í’ØDZ÷g{S×ßxõþënÜp~WWšFq臸°ãC‡ža(ëÐöM†ç|hm{ k›£Á‰cçN|ù¡§Ÿ8~ôÔ³£A>©jk‹¼˜”EUÔÖà‹Æð°þè%"³ÉÉ ?þô7à+_¶´¾£µ >iþH(w{¥”7F»V+MÇŽžzâü¹åcó ýþ{wîÚµ«¿«×k÷Ó,êx¥#çº;>!Tˆ½WÔ몪&£ádóÂÒæ…³§—Μ9uáÜòÒúú$/ª8ŽlÙÊŽŠ%%B!Háñ“fÖ7¿²Rc6×ë3þ%ð“û¼ø…aŒ—µÆnX‹ˆ/Jœ(qJ‰ÕFÅiGql\>.Ο9uaimeãÉn·•NõÚ­n'k%YœÆ±‰•ˆXﱕµù¤,òñd¼±>ml GÃÁd’'µµÖ¥Y\9çʪ¶¥)EQ*‘BD „ NFÀXÅË*°‰÷"/Èÿ—燧hþql(Dè"R‰H¦Dj©”¨JDE¢Te"m’$Šâ8ªŒQ…wnPVµˆñQJpÎûª¬|1)}YTÞ{ï"£m’DÖÖ¶ª*[)‘J”TÁx)E¤d’Ü~X6 &8gýé¾d¦÷’øcïóràça9B¤-ôD˜¡HKDRQ+%‘R‰ˆQJi­µÖFë(2*Ž#‰ãH”›ªDðÖ9W×ÖS;¥U-J¬(©EãE¤DI)H¡Dr„±ƒÆøA3ÆÍäXì}/ü.€-+~Þ–@3c„!È&"Ú"ÒF$HI‰%aDD+¥”ÒJk­ÅD: k×Jy¥”UJ9 ÞdE¤¡ 3N!0A¬ ¡ˆ =>o ¯ã/ûnЗuÏ?ö>×€°µ&ÀP Z@K„LD2„´"&0[$J´ 88 T’¼(eEp6t‡ Áð‰¹„YÎƄ׶ 7ï½ ã_6 °úà/: ¡rA1‰@’ Ä"ĈCsÿÈEý±açØP% ‚¦ùî-nC(©@¶„¿\wEØ:ìÓ¿â?}Ë{Ÿ[ƒh]Óü†!Ô35 ¼GWÞ‹ò~«Ã€c‹ažUc¤¨ ͱ­÷mmRû¦ŽoúÆÉõ‡þ½ßõ†÷o]ÈÖìI3Ôß:o¶uy¿=ðáŠcÏ3Î]ô¯Ñߊ›§/¾HËóo[‘‹Þ%ã3ó;.õü+~| ïß>ü%ÎyA£ÿNÿ]©ôsçWÌÍIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/newcase.png000066400000000000000000000126601217176075400242270ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ ‡£…¡0IDATxÚÝ›{Œ\×}ß?çœûšÇîr‡-ŧ$Š¢)‰Š,[Š-Û1'vS¡p$!ɪœê?ÄpÚ$u[×p…µÿ1T(l * »›ìÔ–"'±cµ²dÑPj[RHV”L®(ŠËåîÎî<îã<úÇì¹:3RZÉýÃY`pgï½sæþ¾ç÷øþ#øiøÛMó]¿tÇ?9uîÔ|w£‹.,XÀ,lßÉ-‡oqݼ÷ø“òä¶²tôÓ ÿu·_·}÷ž…ß?pݾ[þïÙ“ 9ÎŒHH9¸pƒ¶ßþá“<ùÜ&4ÿp8·rs¦Ï¯ÿÊ?•ÇÞu Õ0G"B©˜;øËÿñ0ßùÛooymùÓ@¬Ø5†ñÓÔè¨B£1þ¥,‹Ë/±Ô[ÝòÚ?àR š­+ÄÐ"K ¬Óe æ( MP©De ´Ãˆ k%T ­åÑÈ7þDøÂ¾0óÞ÷¾wyçÎFk]Zkµ£¯QJ!„@)…”²>J)BÔïýŸµk-ÆŒ1h­Ç^ƪªBk]˲ä¥å—äø»O·TªˆÓY*Œ-1•ÅiÐV㔓8ö‹ÿîö»îø7ÖÚ´×ëu|ðÁ…· €RêçVVV)%N§±cÇ”RoNÃsç\-tHUUXkÇ€X¯Ö‰›1Qªˆ…J$Úlªq…C;SŽ,Ëív»aŒA)•Ýwß}Ǿô¥/ýð-Çñû766èv»œ>}š4M™ennŽùùyZ­I’Ô;íBÔBû£µ¶~RpkíØÎû÷ÆʪÄ%•*T¡…¨62¸È Ñ8á°ÎÖDQtð–ø€RjL̓ÃáååeÒ4¥ÕjÑn·i·Û¤iJEµÐÓ÷ç¦ oŒ©¯ùóÆH@Æ „'VXŒ´¡A:¯®ëœ#˲»ÿVMàcL½ÃÞæ= @ Èêê*qÓh4h45BˆZx†W/¤ÖºÆ_«ï1–(‘H%pÊa¥Å ƒe´ûÚi¢D¡J1z’$·½%ðùÏ~ŸRª~h!ÖZ„µ“3ÆÇq­òZkz½½^)%q“$ q×÷9ç œ~éyº½5r]b±g0Πíh×3XkèWh¥M¤£ëN£­¦²•Õhg¸j×.„†3k?¦,*¬¶èJ³ïû>ºøÊâi4 !Ë"n:rBÅËÇ=þìBü¼­5J)Œ1µð¡6øë>2„Ǫª(Š¢P)EEœ8ó÷|õ»ÆKæ —ÊULlP ‰Ê"¢L!3IGD±"i+vµvÑŠÛ:§Ð…½te0Fsãá›9›ü˜ç_>Á@ 'Ø~í¶;»çúh°’¹ö wÜü.wqyùôøoG¯£þôêêœCJYÛ˜ßíI/?MSÂkUUáœãåW^æ¹³Ï î°lÛßbÇì¶Ïî`®5K»Ù¦·h©6‰HÑh ›cœc©·Ê°0,äeŽ+`Øï3?7Ïá›p俣# QH!‘È–²¥Ä&u';åùö×·sñz¼?´Dø‚¾&#‚µm gÏ--Yª4g›ÞÆN»‹]\Źƒ9K¦2bá,èJSäýþ€þ°Ç P KÜ,^|‘sâ,J¨Ú?EJ!¥" )¢ÑQ*bsòì –—^ß(¥vWUU«í䎇‚)¥jçã‰ÞèÓsk,e®Ñ«ýÆ•,)lκ^ãR±Ä¶V‡Ùt–†j ¬ÀhK™—Â|“r̆Cô%Ú:¢X¡b5r†q„U )…rc"”UXcÉ]ŽV£”ú²|ò“Ÿ¼UQÇÕI2;¿ã^poÿáîO%DÚaû»y\‚XÇZKY–t]²8£¡¤"#±)®ryI9,1ëV%Ò(¢ÌBSA#B&ƒ• $XÂ:0WEPK-"W]€²,a0Ô%I‚RŠ8Žk>Ç±ç µÀ>ìm²±1"äýIE¬w×q¤¸u°8rS`+KQ¤ý”(Þ ¡Ö"¬"61I•’ær=B‰jYäŒÅ5A¤2–D*"–R($¬ÀY°ZcJp™…äuÂà±cÇ~eß¾}µ`q×ÂeY†µ–4MkïAÙd`>¿&Oðkˆ¦ ýmòfbpÌ¢¢2ƒlˆŠ$BŽª­,&·Äë)ÉjÊL:ËÜÎYšsM’Ù6¬A–d$qB¢"œ “8 Ό̎ ¢¶B4À] €w¿ûÝï c^}è`‡½°„0ô,ò5æRUÕ(<–WíºŠÕë¶£D"=™P€)$8É\²ÀÆß­s©÷ ½t5Ñ`—ÚÉîù«YH÷«˜HED*B‰@X³îU"ÇÞ«ºt:³,Ÿ[¿<yžÛ¢(jfæwÐG…ø÷!AÚ4£Zƒ¼ƒôæP·_Cr\’_Ò”è‘Àñ¦àP£xnn†«÷íaûíûù^ô¢ blC3P}ºr™òå‚Õ k¬ëTFƒàhÓçù†Ëi¹G:GÝ͇~¦ÿí=vyœsÆ?t(€ßÑÐÃûë^ÂPé¯y ñâÀÕøÇ¸‹uŒ{u]ã ˆMŸÁ(Áé—=þvñ¯Yï®#Rœ¨¥h44›MÒ4æüÆËìï^ËÏÊ÷cŒÅ:‡5«-I’ò§ÿ§ÿö…åÎ*¯4–©úö"g¨®€ò‰Šßy¿Ë>ëó„'ä Þþ½éøóJ)Š¢¨×ŸkÏqÛÛnCJ9aüý>ü:ç8é<_z‘ŽŠ#q“¥Fƒ,iÐ×̧;yçÎ;Æ2Mc Íf“äRò7ü÷ž1ÀEVÙî²Xk¥·]/¼”’F£A’$!jû×ZׂdYVsïüŒ1µ9ÌÎÎŽ 8Ç@³9_sØÄ–#­ ¨L’¦é«¯$I#F,4Iò<¯5pÓ‰[¦Œ®¤ÒÛ¬Wõ“'OòÃþƒ¢”"Ë2~ô£Q~Û¶m<õÔS ‡Câ8¦( ´ÖÌÎÎrçwÒéth4<ñÄìß¿ŸÛo¿²,k?âµD)E¯×Óž +È7òÑãG£´8Š¢Q¢'Äq‚p‚ų‹Ñïæ¯þþó6xf:‰ mA©Ÿþƒ[xú£·ð¯ƒGî¹›qßqÌ—?ÛHh,vMB«‘™‚IÀ  pú{`Fìñªj )6Ãä®_ºŸ3‹ß¥,˱ô<¤á[Ñ€±—ÖRҶ±ÖÛÏg^ü¯.•`^ÿöÑËoà§çþ5ü£ƒ|íáßbø‹¿ƒ_ûÒcllÖü7Ã=Åæå@¹YX9·È×~ç^œ'Åõͨd­Å:‹ÕŽí fwÐëõHÓ´æ›ÎÜnUj§ÐëõØÖˆ8´óîü—<ñuHO¯°<×ae~w;°²¿å(ž“Àý? ?÷ìÜÞ†?|Ö4ÜXÀðø2sy‡fÛPô%Ê8h–P4˜Gµžî0aèJ–—À­»ºhÍxeÙh-`C48´;¦ßïÓétÆB÷–kxÞIío¥¼xð=ä»nà¿ì…µÃ-p†Äi ‘uTF°£ÃRSU1ÜÐYHλ‚¼aYØÙÀ¦;Ø0 ämجQk…bg*¸„`¦—rn Nþ±»™HU#FYUeYRV%‘Qt^†Ï~÷¿wIØH@Øž¥„ƒó¹ »˜r[çm”ÎǰTÀÚPS”1Kýí_º†~DóØ·ŸK¾6C¡xS> ,KšÍ&üê;¯axîŒá—ß©qQD#†´ - Ù Äæ mAË@Ã@sv`aÓ(ŠÀ€Îß\„e3ÙH¡ +È@‡…·ßÇ¡÷@nGç5£¬QD0èÁ¥!¬¨˜=iü‘¼öAObkNÐ#ç߯­­qÕ{>Ð=:©à’I±HÊ\E1+ça{?îBYBÓA—Ç@¦„y«3£°ßœT@&`ïüèÞ¶„åæÖ¡j@<;ç2Ö#H† -”1¬WPYPzdiVGö077W?{è˶¬>ÔTU5ªúD œZ6t¬äì²c:N2Y bób ¢íL•B’Ãz»%¸U˜ ·Ã‚©ù¶ ›­Ó€îây8ba-ƒÂ‚Ž`gƒ ªäè•P  _À>ƒ^ÄÐHè·kÿÚ¿ÖZlY¼­­­‘ç9¿÷©øU€ÿÍÍ{[ÞoL,èU|nSý†›ÇÅÿ]ô6ð{_‡,Ëxæ™g8zôh½‰\¦s~YŠ¢ÀCQ(¥øÌg>ã %DQD’$8çh6›µš½Ù®ñýóv­µf0Ðï÷©ªŠ^¯Çp8¤( ʲ$Ïs^xáƒAíÈsj«LÐj­eQ4 666XXX ÕjMë  ’¯(ùH’çy]@)˲þLQcó>…ö$¦,˱†©ï4ùlϧ;)ãSõµµ5|eûrã@W2á…ÓZóôÓO*9pÍ5×àœc8Ö¶Çqíx¼ðao ,j­i4uÀgn>…öÕè<ÏÇ H))˲¾ßZË¥K—èv»uc¶( 666ëÖZ±Õ!)뉂™™Z­gΜáûßÿ>/^dvv–f³9–oû’xXܘ|ðµ/ˆ¿îïät‰¯<Åq\W¥|–·ººŠsŽ;3ÕÕÕºC¶ñ6;WvKTU¥CGèkƒ333TUÅéÓ§ùÁ~@¯×#˲º–¢¼Í†ÿ{ʲœ:áÿÏó|ìº2Ïsʲ¬×Z\\$Žc9vìÏ?ÿ9 ¾ÿ÷ZŽÖìÙ³‡'Ÿ|’n¸'žx‚Ý»wצãï›,Ô¾Q༚…MQÏ|gHÁòò2½^ùùyæææÆ ¿8œ óùpj$ÜípxbXÿ¹¹¹9n¸á¾øÅ/²°°ÀŽ;‡cßåAÛª4“vì‹—¾^çž/Ž.--Ñï÷iµZ´Z­0m ÿ¹IaCPý3EA§Óa~~žápX ï× Ëò[À/â ÃŒûa£$Š¢ú!ƒÍf“8Žk÷zLØìÔ¦lè`ÃÍ Gn&ÕZ[ÿdƒ2\Ü àÃXØ™æ¹óõ ðëú”÷©§žK'm<´õIpB•÷k,..ò±},~øá‡_[̹‚C>\ ìž™™¹÷øPh×ÞŽÃ6õäq¨-^ ðçMÊ{ê¶FQ4–#Lsv¡Ý‡v®µæøñã«?þøºÀiàk[?±ùâÞ{ï½TUÕ‡Âi0¯b!u 'D§M‡z0ÂÌr2sô`\.¶O‚0ùà ¿Þã?Þù‰ýlújèØ|~?™ˆLËÝ‹¢sfÓlxšp“…ÉšÁ•œÞåRß·ô«1?Ó–­ÂÂp÷'g„§… P3ÂÚÝ´6™0MjGÈ.3Åîë›îMà¿dr$6$4!^•§•ËC¡'‡1¼¡ÝO =yœ–üLT­Ý[Ö€M…?žðÂùë~×ÃP4íw“@LÖ &w?\sÚ C®TyÓ´Z­ºì™[gCï?Y Ï…´yšœ¼ßó0ñ÷ûˆjÀp8üÉpÝu×ýÚG>ò‘·åyþvçÜþMêuÍm†T/y^SJ !„B¥”Û47- šàŒ1>Ôó݈)Ÿóç$pᦛnzäÊõÿð•laÀùIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/newfont.png000066400000000000000000000101261217176075400242550ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœå›{ŒÕå™Ç?ïûþnç2g†ËÀ* )©ÜEDEm´Ý²»6lbµ«M$»¶fÕlÒ?šìn²m·mšl¶]Ðê¥Ý¬e«n[³‚T(¸Ã”KW)0Ü‘rfæÜ~çwyßýãÌæªÇ™Q°}&oÎ93ç}ïó}ŸûóŽ0ÆðAtËßÞd·ž<<­­£]ú‡"-;…—U?Á’–r,›‰MW‘N¥©e­ËMJ)ùÎ;ÿ·ÿôéÓ­V-“’ÉĤå·þÅ[ïžx§þWgC©¥L;i§ÎJ3÷Só¹ïó_bñ‚¹Òù¢òúðÃ_ýGàÛP#{Ž¿%B7°¿ñÃo(@õýû¯ÿõW,^p#¾ïÜn?Bày.Q¹Ý¿« €N+àœ€onGm¤‘Œ?Ž©ó¦Ð–oøD¨€Ñý¾&d£ê¤ˆ31±ÐÈœ" C„#Þwþ•L5@FÖa¬„"ÐqÄå³ÊI²¦/¥A¤„°]á ÂD@ „>Òßj@ÔLVl¨rÒh;&P] þØU "Q9ca Œ2Ä""¤K @ Ùüô&cÌi${àÜ'„ªƒÒOzïtT]ÏsÐ"&2¡ )ë ©º&‚0éz®`ŒAJ…e©+ëoþùÁ•íÁÅGÿ÷äîRÆË 9ÑûTjf@9ö â2å¸ A€²ô¹÷ûEg[ÊŠ@I B¦]=•¿\¾‚%7.Áqœ+ kËÎÍ×\wÇìy?zjMM å<… @©\Âä+1Ñäë§2™©ï;oݳϱhá"\רxØ)²Nž9–ø¬\wé±i®{W5^Íøúñd’õØÒAë˜r©L)çÓ™ÏÑYì¤\,dcž~j –ecÙ6¶mc+ %-”°°„¶ü‹eŽ]hE)5˜‰¸ldƒztœÎQÖY"Ò´s¦ó£ScÈØõØÆ!cüb‰b¾D)W´ T!Fy&a0‰cGhUa^i‹8¶ˆc–1®Ô@^N²L*–ˆ6ˆ!Giü¢Ï÷¶²ppqu*´¯ÑYèPX)]#Rå:`+*ŽÀ`LLkL¨‰‹$.7«“%‰’HAt"b‚ “|:åZH)ˆã˜²aû™özô(ÒcÒØ*­H$$œ$®åb+‰ :£5"—\áå4‚•G_z¾Õ”gO™5µÌäÊ!0¶A8 l@€1š&'ƒÈ&9|àwdÇœ'c¥˜–žÎ‚IK01¥±¤@ ŒmБ#ðêËä‹€Á\a!£µhÁǼsÎÞÿt°TФ' ¶©=ñz"P1/—†ãØ:ô§ND©J9Š¢ªlÙòZ—Hšqô¦š¼À¼y7œn=~hÙÁe![2SgN]úôÓÏ<•J§¤²ÇN$ˆÂ~èÚ¶ÃöíoEGŽaܸqh­‰ãÏóhnnæÔ©Ó466EQ-[6õÝcMüøßŸCÝŸgÏþô¸9Óç‘N¥ˆ¢ˆ(Ñ}Œ‹‚|>Çž=»7n<ÅbÛ¶‰ãc mmmìØñ÷Þ{/ù|8LÖj¥Þ’P›컄1®úø¡O9*ÝOÐ×åàÁƒ;v c _ÿú×q‡ ˆã˜(а,‹W_}•(Ž?^%è!C  …÷¶e±}ûvr¹W_}5wÜq³gϦ³³³"5Q„ã8´´ì¥õèQlË’Eë*HW|ùà}õÕ¡Ðý¼†’ŽŽvíÚIE,½ù¤Üñ™Ïàû~Õchoogë¶m¸žWó *e‘J¥ð¼R)„”H©p‡T:ëº5›Á¡7µó+€c;ìii¡µµ•T*ÅÍK—R,–¸aÑbÆO{{;J)´ÖX–ÅæM›xàþð©r2™äÌ™3lݺ•#GŽÍf«=Êd2Á¤IWqûí·3wî\|ßï¿^ŸÏIW϶-¶lyÎÎN–,Yµ×^‹ïû46ŽeÉM7ñÂóÏSWW‡ÖÛ¶Ù·ï·:ô.3fÌ \Ÿ¯JeÙìß¿Ÿû÷*Zr¹<¥R‰¶¶6Òé4š&P,+S¦L©æBÀ©S§è÷Z}ø¦ è¨RŠ ²ìxëMR©$'Nç±ÇþŽ J®`YгgÏV"­uõD7nÜÈâÅ‹ñýþzÇ+V¬`Õª“”J%î¹ç‹Œ=¿ìsö̶ly—_þ¤”„aX »ûŸúÁÊq]vìØÁ‰'°,‹}ûö±{÷î^é¨Ö)%©T ¥TÕضͦM›xôÑÇJö+”øå2sæÎeÕê'plÇqX¿a=›7o¢eo 'NGJIccc—„ÕïÅ~†ô·*JJ6oÞD.—cÉ’›X±bÅVÝàyÛ¶m㥗^Âó<´Ö(¥øÝï²wo3K—ÞL©Tì5KaPŸÉ°}Ûvžzú'¼ûî»ø¾ã8Ü}÷p]‡—_~Û¶ ðb_Ë7Rn°¯(¥8wîlß¾c ÷?ð÷ÿõ—(û‹³çyÌ_° 6T}¸1†B¡ÀúõëYvÛm˜þÓð<µk×°víZR©$sæÌå±Ççæ¥KyñÅyþùçI&“A€î¢÷ÜwOF(Ü{$¼$[·¾ÁÑ£GijjbÑÂE\¸p‘|.ßo\È^`ÚµÓX´è†ª1ìÎ ^yeçÿp%U¯õ“‰$Ö¯gõêÕd2‚ äšk®aÕªÕÌ3—B¡H©Tªê†èXWJwô•ûÀ0,7Øý#„ ˬ[÷s‚ `Ö¬Y4Mh"ŒÂêwzrcŒÆql–ÿùrÂ0¬z¥‡fë¶7H¦’—æŠJÐóóŸ?‡çy„aH.—ãþû “É/ä‘Râ¸nÕ A¥>¡1Xv¥{]‘ˆ‘ʺøql›1£Góâ /°sçN,Ë"™L‘L$±- èX÷BH@0Þ|ÇéÀÚ5k(ûe<×ërq’óçÏsüøq€je)‘Hàº.™º å ÌÖ7Þ Š¢RÑ©ã¿Ö­ãk_}KY#zéÁÐ`WÏðôé³<÷Üs|ï{ßŲ,„lÛ¶•µk×°pá"F…ã8ènãc ¹\ŽB±È‹/¾@X–Uõo¾ù&<ò5úÊCLhš@]&CGÄqL†ÕŽÒøü²Ï³Ï<æM›Èd2Õïìß¿_üây~ðƒcêÔ©¸®C¿öP*«³f]wçéÓgãææ3aâD#¤0ÉdÒd2SWWg‰„B¥”ùÎw¾k~ÿû#¦¥eŸÙ¿ÿ Ù¹ó7fÚ´iµ&~fåÊ•¦µõ˜9tè°¹çž/š††z3yòd3yòdÓØØhR©”L:6ßüæ·Ìõ×Ï1€q]×(¥ªë<ûìÏLggÞ´wä̃®üvµj=Tè./7ž†††JWYë.ß[q=ù|ƒ!—ÏQ*•JQ*Édê™4i¶ítí¯»áÐûù\Ûvèèè Š"~øaòù<»wÿ¦z/9Nsçwñ裲lÙ2,\È#|•ãÇ*êbÛ?þ÷Üý…»)ò$’É^ÏCéÔ^wÝì;×oذÑqYÈçñ}ŸrEZë. *K%»t¾8S ~º?w‹´‚¾ýR!$JUl†ëºH)9|ø0çÞ{t:Íô3˜1cRHŠ¥"Éd’l6Kss3¾_bæÌYLŸ>²_FM2•âñÇû—Ÿ>ûÌ?À°ê•À'™Lv²¨‹±Jh[y¥Ê¬¸4 !.©^7I!Rôëw·³+E  ,Àu],ËÆCÙ¯[A©X¢>“áÏ>÷¹Šw BJ]±ˆ½ à°0•B , )eWo ÷莼L™•fªþ@ªï„@ R )‰µF‡RöwdaReî뇗 UP¨lNIÝbÝ-ÚŒ.‰ÍT{t˜zþþ>¢Ç>ìž/Ñðr«l•M^Òëf~1¢ö+Þv 4oD³Á‘ ‘^ïƒÖ–üHø¨i$UàRœÿÉ¡‘3‚ê`>ÑpiÏš0Ù RTsùïúÕJBTöÜÓ7 )¥Bt…¼ŸèŽL{F:BˆT*5iúŒŸ1Æ$¹"/ÁJF)¥O<ùö¹sçZŒ1zHPù÷Y\·?U›C ›Ä•pÑwˆdz0=dþXèÿ5êuèôIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/newscript.png000066400000000000000000000163341217176075400246220ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÚ ''T¤5IDATxÚí›ùoœÇyÇ?3ó^{s¹$EŠ’(É:­Ø‘|ÈVb;µæB›6?m"Z0š¢@ÿ†mQ è ý¥@ ÿ”)Z$mÓ¸uìȵ|ÊÖi[ÔMŠ7—Ü{ßkfú%•V$“”H¡@3À,gv†ó¾Ïwžy®y~^þ±šIßúÖ·~÷…^øv»Ý^qA!îjìF±Ö®Ø¿Q—÷o¬m­žç¹/¾øâß¿øâ‹³ÒóœÕ°{÷î}GŽ9øm÷–ƒaŒÁZ‹Öß÷yã7Þ\Í«@k @Ç·ÝÍ[wönÇnÝñ;íör‚omßà†ï¼R‘kE|¥ö½ŒÝå07Ú·ëK)oÛ^>ݸ_ ,玵‚pãï†p?A¸gÜ Äí@ØPîçq¸7¬T7€Õp?@¸Ñ¾•õ7œÖÂz´–~ßdÀ½·Q ¬…ø{>w#ÔÖ „ÛµWkm®Ùºõ%—™{àÆV;ïNc:M06!ŒÛ8JR›Ÿ¡Þœ¢Ü»žžaÇ¿Iüj4Ê=p?@HÓ„(îÒh×h5«„ÍYBÝ Öéb¤ÀMÒpšjÃ¥T:ÀæþC”zF~f `½AˆÃ.µÅY§¨6æ¨5C"mò¼|ŽºNHô’I¨s”ró”‹»Q‰‰écœzëyôào±cïS(7Ø8î••—·«Õ)ªÕYÚQHËJTÖ§·ÒǶ-»x(ß R mLbbZ“oáû>íx˜‹“'ñÃ]QG‡“dZçÑ­)^{é;ø^À¶½O¯?· §{avê2ÆÎ0=+‘AÅL‹ÜH¬½‚k,QºHÆŒGãx Ùæêëß¡õ0øÅo :2[b!­’«WÉD³ô1ã SLŒÞ`µ²à®eÀr‰»Zõ9Ξz•«‹5><7Á³O}‰©§^þ¾ùí_æJµF§0DmâãE’\6Kg¾Cœ?ÄàŽƒÒÁ S@Õ&‰g®±yDCÎu"½¿jp5:ÞÃù³Çxõè÷©e<²;µæÌ¹QÆç\8?Ê?ï{ly`'¡“Ã×Ùr–|ûÛ‡Ê9|„=:ñ_´ªxé­ó$h&ÓŒ_ÍйZ…(aÏAM9“£ÑÞÌ»çØ¹û2‰éå£fB¯[%ZY»BéaZûTéÈÜvнÛ×ÌÍ÷¬ï4‡m~òڿЩTøÂoÿ>ÝfÈbk–M½œ=Ö$×#˜©¦x9Þâ±sO•ñªCL“Ôat‡K5© |švm‚ÅéÓ˜LÊôdƒ†)B"(÷yøABÜ ñ2’$6€Õª·(îrìÌ+”?ƾþýtML4?A2Õ¤d.‹gÚ-˜›3lbºîñþ‰ižúR?©ÎS2x§Îâ-J´p™¿4EätÊ#lî÷‰›WH¢EtT@'-²¹ ÙlacX‹zÓ:áÌØ1ŠŸ:L.äýwNóщczp'•b‘´o€ç·~×ÿé-Úó-}Úgç~CíÚUT½IýŠCZ†0IyxÏg_y™kͲûÈüaKpe”V½‹G„‡Á$›¶lyˆl¾¼f“x]-A­5Çß{™³)r-wá4?æ7¿þƒ=½ŒŽÍ¡»[™i¶Øy°Ÿ'yŒ§OÑvŠŒl3ò>¯¼4Ê“ÏìEúTlX¨6Ùýô^¦&.b¯-Pñ* ‘Z"È‘ˆù`3Û÷>‡k÷íÖ5 riö³:G©3€Ÿã©çqøÙ}èž6³áyÞ~÷‡”7/ðØc»a†7ÿó"í¶&—-Q«ZÜœ \ÈpùÃI:—æø‡H~g/Åá*[穘Nµ M ¦¶ˆ›Ó<òM2Ùž5ûëj ž»ú.39—=ŸÛË eÞ<ñ:² s¨¸ÅÔå3˜$$¬O")P)/°ùЃ|têC²ºA³­Ñ:ä¡=[øÑ^çR`ÙóÙML^¥äÔIçÇ„‡ç¤i‹$ì!êNñ©ƒßàÀá߸ëк¼ÛÝ^ÞovªŒ%å> Ö,rõÊ9fÆÎ`šUÂVHm¶C1[ 9ÞbìÔIZ 2ù%cÞþñ{‘ YH8ùÞ3S­räÙ=<þØ ³¦;3OXi-6iÔ[%©×«ì;ðK<û«ˆrÅ •u‚·³'æßCR! çèæ¶Óê΢¢«/c.H¥˜f¾­ J¡" =.½Å6Í©i,åRÂë§gøÚ׳u¤‡3'¯ðþÑ{w.R)FäGrØÐÃÉjmžùì <þì HéÞÑ&Y-È»á€ååRm '›%Õ³lەïO3ñÞ‡ÌÏÌ¡ü,~o™]oÇõ;8±¢ z·Æ{G'1õ6 ç»d¬%#²~—RoHÎÙÿØ |ú3߯q3+ú"k ®€[MM‹ùV›pæíñ*Lj㜙¬á4©ð©9E¦ƒ.ûŸ‡#»ŽµC %¥R™ÇNrò£Sç h§Ë`¥‡žl™wOü;B•IrÓˆLž”éÅ¥:fI x¾Ä5d'A›.ž‘¸R‚×Ââ“Jƒ6]rrŠÝŸæ3ÏÿÕÇôûmc "¡ëvÑù”TǘPaµCjSQ“®×ß²Öb…¥FÂèÕÉç äû÷Ó\˜£“:äü6¾0?ë ˆÄä32N°‰Æ"0Ê'± …ë#ƒ,&4èî›ìæñÏý9ž—_ÑôƵ(!Y‰Ñ)é`”AºlŒè¦]fº†ž]Ôkg¨d%Mb¼\?™^ÔÄó|?Àt[4j ®´XR¸(W`}ió$¡C«v•ÁŠÇá/þÙlß'Jö›ÚÈå9¸ƒH$Z'˜Ä˜+ͪݼ5›ÂÂK‰»m<¬ôyÿøèµ6È9KÄ-6R¢°ŸDe1¾D¤òƒãäHC»ÞÅêž®qà³@_eÿª£Nx•Q¸¾‹+’4Fû ‰H0bõȵrÀ|m4¬Scnü2)š˜ž\B¢4¸e1Ú’*p,”Tó\? R‘F) žiáå=¶ïþòšî …*8¾BzH„DÄi@m;\«·™©-²i0 ­€éÆÛ´B‰Õ¤€84HÛ¥ °V‚Ip¬‹+ ­¢ÛnAÜA롆6?ŠëåÖt.H_ ]Êb¥!•)©M°Â°Z[hÍZ ·ÔG°y §þ-íÆe´)«&¢Ý%ÓŽH Û¡ÓN×G*…5†$N0­AŒ—²Ãl}àyLa­Ívƒ›ˆeÇðz[Tà: # ZhRRR›àe\ ŬâIJR–p£Ý »zw­]úZòáèIÚ­.3)Q{aRH|"¥Å65¡)<”R¹DiŠICÒ(ÏÅÏnÅ úÙ¹ÿØóðç r%’$æòäU~üö¿q±v‘]pAú €ðÒ•8®¥aÙ¾éb§1±Ž‰ÒßÄŒl!žwì4Û¾6ck€È.Pa[6 ñ©]5ÖÌ¥|}F±h\ŠG³iˆ;uLâå$ž ñ,áã8) B*¼LŽr™byéÙ4´‡=“/”QŽ‹”Šñé1ŽŽ¾B{O“L%C¥T¡P(‘ÏåÉy²N%$V\×§/Ò‰Ût¢a蘾ò=ñpyÏ¡}_Eƒ´ i$Ò^¯HTª=v~aÍ2ÀQlÙ…Ç©ç7ö…,Ì]# Ç »Ê ²Y‡LÖÇu}2Ù2ÒÍãú\/O-ã¸ÅR?›6ï$“+á(q=µ%NÎ]$ná•\:b‰7„ÌmÂË*”'PB’&š°[¥ÙlÒì4h‡mâvÊ|}†æL ¥”R8ÊAI…#”pp¤BI“ZŽŸ?~w¦p¾ÐÏÖá‡(æk$‰fdçÒ°Kتâ(‰ïø™Žç£¤ƒr„pÒE*?È‘/”q=!$âzRÓcwbZÓ-Œ“Úõ´Æ\8C9ßKÑ/È ¤‡1a'¤Ûî5"l]t5‰›à8 Çu–ªZ"^…£Tê`bK×tïÖ†Jß^zJm´±¡Pʹ›3¤i„kõ’@H… )®ã~Œð›’ÞXL¶ ɬ¦%ÛXc‰¢ˆZ«†ïúøÒdzþ!¡!i¥ØEì*ß@^#².ÒXGb•Á 5¦“Lj±s÷ BH\¿€c4ÆØëq8@(×_Žn¦® !?9fgA F`kM3i†^àâ8Îõ;1øa@¦™#góø9Ù"ïà¾çá9Žt‘H„X ¤c4"gï5,B:HaØ%Üš%/üFæøxþÞô½ŠRO‘hO릠@`2†ÈIT¬¶¸^–ÖlÈüä"¹¾ åJÛÊÛêÙFÆËà9žòPR!‘ Áh‹I ¡éíï]ÏÛau3ö >þq“ð;…­–:™ ÃîÞ}pÙR ––UK–jÉr ²•J…ÊÞ­\ÈŽ2™¹@'×WSvKt¢ ³×¦t#i†ÚX„• 6[ˆ%Q`S©¿»ê˜àíÌÒŸµÐÄšîo7>2<¯}éש.Γš%›^H±d´ß0Š”å+o29WEx ‹à²¹,nÆanqŠ…3ͱ3W>øS“b–ÂH àz ´ËþM’û’#´¶mexÓð'þÎ@kÍø÷Çm!2 ó’ ÍfÉf²4ÚˆDÍGÇwïêpœ— q/ ü¯À¼=Ætb°X„N ð}ß÷ ü€Ž1V_ß÷ë°^ÞàZ3ÌÌrI‘/K9@z„»3£™9çÿs¾ÿ93+÷¾ð/üúüÝ¿ÏrñFÆ|;âî¸ʲ8€¤< "(ís3h±½ q@†kB4¥k8šPETŠk+ ‚¨ˆ;¤A@Ô  ²ò;š â¼ÐóÚ_<²ÂÆŸIù©À?†{€jî`î˜9Ñ¿Pìwܽaz{i|–;­n|¾ÝŸÏ£ã· ƒàÅÔÑ|èlcæ¼ü;6œ3û³ÿüË_üÚŸÿÁ‘WºWÚ_ëv‹d¼Û²3(gÝ£áÑÀ¼˜ÒÍ*îEòÆ@R}ð+û?üê'›ÜßÐóùRöõ}×AØqô¼àÁC¸9^-IÕç­†Š„TØßLkßùÁ,¿}~”ŸûÓÏòôñC'Ú³‹'c¾» ”“žG†?5Ùã(Å|«EÏcZ¿o‚ôèo,ÀØ=ÆÓOšj_]8¹›ž0 U LZ¹1|d1꟬?´ðÉ27I‚PëÀÈ"¼1 £Ïã×?8Õš]8i»Âàx@{÷á.ºÁ*D1 $ishv <{Œ§=0µpuqW@,ª@ˆFã®}à‚»dAAUMVå@(€é«Ópð ÇyòL-̶¾aÑqƒg‚æ4îG¼4hpP´âè}µD„|gîøâ§yêщ//Ì-žŒ±H<;&a»C…û@¨[ ,P®ƒ•ñ«j© „á¼> ŸxöÓ|æ¡}S ×Ú'HRÙ1gܽZ „ÚÁ±b¥¨,ì¹ûòJ ªÅ¾UŒR(pjtà•i¸ïOŽóËOÍϵ’v·*i²G§~`DqUP Âͼ` éá»WáÞ/çWŸšŸëœ È2߆ì~5èËd©¾oÁËaËv)¸C€Ü¥›ºæ¢#5}ü­ŽþÎ7ßÍøÊÿvib„Mø²á£È+±Æ3¿û(œykêíK‹Œ7N¸¯›SW$¨ðÀá†tjéè݉ìMUö%“*rÈa"î‹pX‘ã[î–nPö$q ËÌøëï_ã_® ¢Iá%›Hi_XâµNg~óaü8õÃ+KŒŽ• Ü € 3ÿÖ›×ðX˜¹ÖI—ÆÆê$ZG¤Žx Ñ’ Aºî²è T¡ídé[µ\Àpþé­œú¾aöEÔlSËZe\E^»œòÌ3“¿úã©wf:ŒŽÕOø-Â!®'t"Ò%$Cwî«YH®:$JÓD›ˆ4Qi" #Ò@¥†(.’÷2ùND‡C8’†l‡ÜÀ×.¥<ý¹±>;uv¶ÃÈHmCOH0½…z¢K55u×T\ÜRDë˜×†‹×qMѼ¨d¶ù`-¸9ánQà ‘ïf)¿ñää_ß›z÷ê’ŽÔžw÷5ÕM4W»ŽÖ¦*¢‰ŠjÁÚE´ä¯‚ƒk¹P甼u‹ËÁmØ¢ñú¥ÀÓ¿t7ù÷ßî'×3m¦Ïž°…2”Dƒ xô芙¨¯öô ¨¼évt,·!$ÙBäõ,á©'îÆðÁ‰‹fÒNn ‡D‚ ‰‚ êàÑËš$²‚¬úº)Ê%ëm ;YµU’-„¬Õå{•Ï»þûÊÔ¥ùœF-9ÑJÒ«ÊÜÁârw“ž¾6¦õ.wl† -å¼qÑøÌÑÜxsvªë¾(ÈW—WU*í™l°ºBÕqRé¡D¿wË 9¶¬ëŠóÖ0 ÚµîÛw@VîRt…ªA„öB—Kõ”ZMYêÚ—R÷¯z™U7<3LK ª‹–õü ƒÍŠ]æàýFàa}J­¦³»™5Ê{ÆþÛ9d8wŽ¥\½Üf>s‰þMÌã¬,dŽºaUìW¶Üvâ*@VkÑ?ka ®^qr¶ •³õ}f÷ìMÉ2ãêRdlHÿÞ£¿–‹Ž#´  7ƒ‘Òý{ë¥PP5-î PV:ðÝ,_S*ðÊyéšqd"%æp©Ù3N‹Ë«¢ ÒÖÒY €Q¬v"ËÍÆJ))¶”•ý7é»é ÄL r¹Íë:ˆ3îß_Ãrx¾ËžF8%î/-eùœ™|  *\„D! NT—žçW-ºj‡W4BVߦ¬XX\r²Xè³U zÆGã‰:nÎùù.{†Âi5?ÓΘ1çœW€Nï¾”M…ɽáºJ-‘ŠH¢*!@¢’ $ФA¤–蚊n”*—ŠBsþãýÿö£©®}Ý ¯å…Û¬£óîÕŒýÃᔘŸiW\¸€p§Ý^sE—úxÂpP¹ÖòàÄš`ÔÑlHÐaš £.>¢FÓ•!(bn³Æ®ª$ÐŒM§äWê$“7/¹_·šù£“u,:ï^Ϙ §ÅýÌRnÓfrÎaZ(ß \Y>2¡ÒjÇ<‹ÎRîÖ‰Ðróy³X7'5Hb„hÝ=#•›S÷&DëäÝ«žæßì0ú`±? ´–œ°‰+.ï«v‘ ¹¡¹tÕËÇd\±ßø‡&jäÑyg.ã`1ó//æ>£œs¡4~cIð"‘劉KA¤¤·ÒõKW[±½ý•ÐpRM­Išw‹Ä-œß¡ëÎûkXtÞ¹–19N‰û™V—+1rÁ…iÜ[›Q¯Ç뜂ÛÙò9»ÇÜ+r‚çšjBP—ê­‘5î\ÒqçÈž17ÎßèÅü‹­Üf£koæ7;3É­ÿË€¥´DjiEÜËgä^4¡4¬ÛkèšqÏxŠEç½ùœ‰¡ä´àgZ]›1— ›uû~¹}TSè CµñEð’f®ÃƒÝ!7Sò¹´Ù;¤§Äy±Û¬9gݘa¥n#¹=”Æ»CÒ¬é¿WsÅ–Š=Ǿ¨üÀ &JŒ‘é¶±·®ɉ6½ˆy ,IÜzÜî>Õc wÂØPÙJìóâ{TGË7Ãû­È ö)–Gæ–Œ±šž÷—"³æT ¯½ÝþìîPoNºgde¥ÙóôbTÕ•HïT&†”Ø\ë#µbæ;‘s.P¿Ù=úßß,Ëm_;Á9‚HNòqyQ$í«)y¹žÍTOƒ¿Ô5¦#¬Ëí·*»@ùÜÍI'Æú:è¾6!¥«© CB§ {’bæ¯wK㣟é3ñ°ôhU›§?ñõIyHн 9çÎ'”´c\*Œ?…û‹]cÚáüF…Ívdàï Ba|íŽqÄ‘juÿêQ) 5‘öÛÂÂ+Æ‘Th) %zZ…3™1ãÂOm< øMQFíŽ=E›­âÕ„üª¤­7…Ÿ ÜsWBlû©ºòbVÌü9à26nFzp˼ J¹âI¤¯ûeöw=¸ð^|©a¼ÜN˜Á8Ï.Ì|%ƒ |.<€ÇŠl’’sFCoþ-â✵³Ey›a½lÑκ13¨„·–ì€êÑŠöúê牞 $bât¤ÆµÄx9$4¼ÁõÌý¢±ßÚlÛm;²3ªeÝœÚ'âûêË-\EùH•Üå†Õ±¨,ä·Þ×½Ý-Ù¡4î,~2#l¾KÚ!C˜S¸îA‰Xn+Ÿríš $¼÷˱múª÷^‡\³³›2 $ÈÎÛ'»çÉOÕ/G?ù>n>nù™àÿ‡ Râ‹4IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/no.png000066400000000000000000000147271217176075400232240ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞžIDATxœ­›{tUÕ¹ös]öÞ¹„ DîA." ö¤Ô‚‚Z+¢¥ˆ_Dk­V=Ÿ£ç˱§Ž¶ãT+úå¤Þ­((á. B¸ !1„ ä¾³/k­ùý±ÖÚY :ÇxÇœ{%Y™Ïó^æ;ß9·Rò]Û /¼€ªiEѤ¢Ä!„B „@Q”Øï !.û.w>RÊ Å4R¶X†išNÿÜsÏ]õܵ«þKï¤a}š‚¿L‡34E‘Šª¢( ªªÚDP” ©x@[–”X–…eš˜v/ U•çüþƒõ~ÿ @í÷1÷ï…¢Ñ ×44®ŸÐ7-KS¬Ú3¨ªFŒE‰WáБ‚šö`Y˜†Ô}èC®áü™33¶93ú›>}Èï„ïLÀsÏ>;1¯ºzýÈp(3ùÇóÐSR±N×.PGë^ÐB8ÃÎîç~¶<Ÿ%X&ˆôtØ´‰ëÞªišëÊz÷¾Ã4Íšï2ÿïDÀSO=5qØéÓE#ÎËHºåBƒ#ÇQCPT@œþðôi÷.hL»H‡úz¤W~>cKJnˆÆÚ²””ùÀ™«Å ®6þêñÇ'äÕÔ=>3õ–[è3ø8ò5„ Puª#. ‹Žà…8F€WLbÖ %Xôê…•ÞÚÏ>£vÿ>veem)KIYð¿ÿýU¹ÃU°rÅŠ‰y§O¯{þ|fú¬Y¤  ‡CÔ\hN¯xÀ·¯ 17pIpw C¶`г'V¿~œÞ¼™š}ûØ••µµ,%åŽÿzñÅ+v‡+&àáåË'æ×Ôœ?Ÿ‘5{6éÂÁƒöÄTµ]ó1¼8®à‚ÅA/ŽÙ ËíŸ;6MHNÆÊ̤²¸˜ê¯¾bWfæ¶²Þ½ç¿üÇ?^‘;\¿XºtÂÐêꢱõõ™ýçÌ!3'§xŠ Ø%Âýì Žõ^ðtÔºkÄH5$'cfgS±e •{÷òyfæ–òÞ½üõÏî¶;t›€%÷ß?qhUÕú‚úúÌ·ÝFvv6””Ø~©iíA.&]i_q€{¡‡Wë]5)/ì ’’0û÷§lëV*öìáóÌÌ­å}úÜñ÷¿ý­[îÐ-îýéO'©¬,[_Ÿ1ø¶¹äfgÁþý6xUu´.Úû®7¸Ÿé .Ò,«}ì%ÀKBNǶo§l÷nvgem«HK›ÿÆk¯]Ö.KÀ¢;ïœ0øÔ©¢±õõ™CçÍc`F²¤aš/xW.Jí@G.È =íbqÀóÜ2Í G·mãøçŸ³;+kË©¾}¬ýßÿ½¤;\’€Ÿüä'P^¾~l}}æðÛoçýúa–” ¤DQ;½„×4Ͷ Ólêíý›E'R:u‰6M[ðîaI‰iš˜ˆ0€CÛ¶qtǾÈÎÞZÙ¯ßo]Ô.JÀÜÛn›˜{âDÑØúúŒÑóðƒ~éD]ðªj§7B؆ínz4#55œinæú¶ùvé\HDWMÓ¨=žUUä÷ëGFJ Ò0.È,KHLDËÉáÀÖ­ؾ/³³·ÕdeÍÿÝw»t‡. ˜õ¯ÿ:!ëØ±¢‚úúÌñwÞÉ Œ ÚJJP, UUmàBÄHP…@Õ4>:z”u`©*y½z±|Ú4â}>[c^°—"À}&%è:•ß~Ë6nä\4Jð‹éÓ–M$µ5O{¶`¦i"ðçæ²ËöóUnî–³ýû/øèŸÿ¼À”ÎfΘ11eÿþ¢¼Ó§3 æÍ#·w¿ü#Æ´,ŒhÓ‘¨Ó«Rò~I œ<ɯ¾Êó;v °zÂ--B8 ‘Èå%¶Å²8U]Í‹60néRþm×.n~òIþ¼u+ûËÊÐ¥ì0—ØØ²ˆ46Ò\ZJþøñ Ÿ8‘k™šxìØº3gö»¤Üxà ã.špþ|ÆÍ‹1(=æÃ‡QÕñyÅÕºó, il8vŒOΜaÙÚµä͘@$ä¿.$¼u+OJ‚χtÝ7öÙcé± (šÆÉóçù¯-[˜ôØcüø·¿ýü³¿ü…·}”ŸM˜À°ÌL‚Ñh‡¤Ù›¦ qq$æä°góf6oßξììm‘çÇÜ!FÀäqã&D¿þºhDssæ¢ÛogH¿~4:„êø·ê‚v ªÄ©*ËÊØ\WÇ/Ö®eèôéØƒüiÑ"B[¶°|Ò$uÃ²Ú #.ÎXº¦ñÍùóü÷ÎL^µŠ=óLg¥±ù¯å­GeQAyHp]Á ÓÞE&åäðyq1ìÞͱ´´-rÀ€;?ÿ¼6FÀõ×]7ʨ¨xp0˜µhæLòÒÓipÀkxWûª> ëó [ëëYú曀÷’ðò¢E´³lüxâuCJD'Íø5òÆF^Þ½û¢àÝVì0Ô(†¤§ÓæFÓL)1- ü~zää°}Ç6—•s¬Gr±Ñ§Ïü]»w«nøè#=zîÜ ³§Þ8åÎ[o%½­3‡Û¥))±œ…´¬ØŽL¶VT°£©‰¥]hÞÛT]gÌœ9Ø·Û·3,5ŸDMišvÁòЅ ¼¾ž¿îÙÔÇgî%À䟚Ê[kÖÐ;.Ž^qqD ÓyŸaY˜¦‰)%‘p˜`c#óòÈ™x=Í-¹ågÏVümÍšýjßôôx£¾þçyÉɹùññœÞ÷U¬*,d`¯^èŠBÔ)¡™¦i“`Y1Â--Èpˆ]{¾¤ìTÓÒÓ}F]Ý‚¸òò9qq´µ´ØÁÄѾåáZƒaP«(Ì|å†Þxc·&ê%áÐþýìÞ¹“k{÷FT)9ÙÔÄšC‡˜üÄÝï%ÁŸšJpÇâu=F€ Þp‰pV¦º:ö;F]Ïž[¤ß¿]1L3ЦI›iÒf$dš„œqS$Bvr2ƒ²³¯h¢¾øxxýuzÌœÉëŒD8ÕÔÄGŽ0ù‰'˜ó›ß\ñ;FfgÓS× …ÃDå9‰Øb8c#Aš&ñŠ–…a(†a H‰ˆZV tÐ!"hš>dš„… ©¶–½?ý)-G^ KÖ¬¡çÌ™¼vð ëJK™ò«_1û*ÁŸûðCJŸxÂmD#"ðˆCDÄC ¦‰OpÒgÍ4 „”è@дh¶,ØÅBWtìè{¦ª„«ªøêþûý?ÿCÒСW4i=>žÅkÖðÊ¢Ed Ƭ§žº*ðuï½Ç‰'Ÿ´3AMÃ4Íöœ Ójàu©ªøË²ˆšašX›eÒlšDB|ˆÐÍ%Âç#\YÉî{ïeÜ«¯’œ—wÅ$ö?'Ý5„ÀÀ6÷à¼ÐsØ…ê<´»‡? ±ªŠíwÜÁ¨?þ«Oü©©¨ºNw+ÐBÌp˜H]gwíâÐcÅÌÞ´¬Û_ÃÉP½.ê[Î.Ó%CÊö¹º«Ÿý@JÚš›ihjÂPUt!ˆSâ… ^|B` a› Hgìsê‚v°Q_ @Me%[gÍbâªULZ¾ÜŒÝ%@Q0-‹>ó '×­cDJ º¦ÅÀzµoYQ)‰8«@ći³,Ú,‹V) Y9ññö.Ô™‹&\sÂÞ0„B1ÍF€VÚaà?"6ö9i@œ ªÔ( c—/gâCuRÐnÕ E×™ùüó¼ÛÜLɦMäèºmŽéZÎÚnYË"ììYÂ@Xʘé»A1 ´a/õnN`àhÒÀ.Fôp€ª]ˆ}Ž!c¦ç‘1… AU·lSV®$ÜÖfƒ¿Òf¨qqÌþÃxÿ‘G8¾ai€p‚Ÿt«ÂŽù{ !î\ ýèÁcaUµçîÔ94UU‘BÅŽúñNïÍþ:&B^Q<ÿ0ªª´ùý\·l“þÏ/ µ´8à¯n14ŒVT¿Ÿ[þý?ø¨úøcRaY±bŠ›Hy•à%Àm öR® a¯6x4MÓlßèh. A{ƒ¡ ªý~Æ.]Ê„åË [¯NóIÑ|>~øÂ |$%ÕŸ|BšS˜‰ о‚M·J{ S±]ØÍmÂNV©ª*š®iH‡€ – v¥ñ΢¦ªÒä÷3úÁ·l™­yïqÖEšå¸Ñå.OQÍïcæï~Ç'RR½q#}°ÝÁ¶2 ç³—”X²„ma!Ð5 MULì$!$b›Jg ðZ×¢šF“ßÏÈûï纥K µvCóB`™&@¦i‰F탕K¬fÐ@õù˜þüól’’šM›Hû¬‚öKVÞ7v?kØÁ°Ý…(’6ðxÚMÅ Ü-‡»'A*QUÎù| _¼˜‚$ÜÚŠeš—Õ¨i˜Ä'&0dèµ´E£;xˆ¨ép¥®«fƒ¨>?Óžù-ŸJIígŸ‘!%ÂÝíÉö‹VnU+¶Opz:5ªBÚ¤½´%à ¸Sv¯ºá<¨*guü{ïeÌâÅÍ_¼`‰II ÉË£bÝ:’äš‘#9²o?†CÂ¥ÒÃhEõù˜ú›ßP,%5ÅÅd îäàY!œ¤)VÎÃVlЙŒ®ªhšªb h•&~)IÀöÅ+θš7…*!È¿ûFÝwá`°[>o&‰IIä NÕ›o²uáB22¸yÆŽÉ¡½{‰D.o f° ÕçcÊ“¿f³eQ]\ÌUµ{,g‰w ºÂÙôµt°{]mŠ‚bvĹÜ(¸ÐËBKLdêÐoέ­øËk>)9™£GQóæ›|ñ³Ÿ‘`ÕÖ²õÖ[™úÁ䌡ä‹/‰D"¨ªziKh ¢è:Sž|’“©©´¼óŽÊã‰nUÛÅ`YD ƒf{š}Q‘~@\;õF²&^;ýÑqŧªhŠ‚’^©©Ì{úi222hk b†#Ñ.Ä Ô".>ž‘œ]»–}÷Ýg§Ù>I Èêj>Ÿ=¥ôÃÇ^‡”‡/ùÎh4J¨µ•áãÆsëÊ•TÕMlÐMQì¹kš=w!@×I6œÁ&ÄŽ÷Ýçkë™”¸·ª¡#ªBßAƒRâs€»/Sââh++£ø®»ÈMK#wð B¡†µ":I8ÔF|bcÆçܺuZ¼8ÞM§’’àôi¾š3_Ù FMœ@$îòÑhÃ0>v,35ì¼ûn|Ñ(qš†ß·3w]QЄÀRUz Â1]£ ARBÂÝç )%SÆO«*/ÿßÖÕÝtßàÁLÖ4êÊËñézûEK¨B`440ðG?âúÂBŽŸ:Åñ#GÐ5½ƒ'Qƒ½z2~ÊšÖ­ãðâÅö;|>„cß±_£µV#ß{¶Ü|±u ¦a¢¨í1Á²ì<¯àúëéÙØÈ¶Y³h,-EIL´7Kt\ÿ¥iÒ $_s œ>Íg55¤õïÿ‡éé¿Ú¹{w8v8:còä´“¥¥… gÏÎøÙ!Löû9WV†®ëvôwüÈ›X dÏ›GÁop´¢‚c¢ëº &¥G¯^Lš6Öõë9¾x±Du½#ð \_f&Cß}—æœ>ß¼Ã0PUË ´c'O¦Os3_ΞMsi)"11–ìt¨X-@â!|\YÉ'§O“š›»:¹_¿•Ûvî4¡ÓñøÍ7ÞØ·êøñÂæššé÷äå1)à܉øtUQb‰‘*¥m Rb541oÃ_Cåå))AJIï>}˜rÓM„Ö¯§|É;ˆê:ÂICXµ¨C³µ-+‹Áï¼Ccv6;6}J(Ô†®ëŒŸ:•¾--˜3‡|‡QWûRÒ$þk¯å“Š >­®&eР—’23ý¬¸8–©]pCdÖÍ7§U9RØZ]=ã®ü|&ÅÇÓxâ~]¿ v¦ÕÐ@ß¹sôÚkTÔÖR_WGÞ˜1D‹Š¨xà'ØØàq\é¢k†”v­¡µ-3“o¿McvÊ¿>JΠA¤44pü¶Û––"’’욀¸él‹_^Ÿ”—³©ºš^C‡®NÌÌ\ùÉÆÒÔ.¯ÈÌ5+­êСÂÖS§f,>œ©qñ´œ(ŧëhN.àî]‘ ¤ÌË€¿ü’“i^·ŽêeËì\Ý1ûX>aÿã‹Q»/`¶¶¢fe‘]Xˆ6bÆ×_S±p!m®Ù{–½˜X €ÈËãã²2>­ª¢ç°a«“³²V|ðÑG$+½$5Þ¼¾•%%…ÍååÓï1‚™ññ´––¢û|ö}§¼ì½7@0H`Ð |ýúÞ³ašífO»Ö/i´oe%`…B())èùù„Ž!ZWqq±Ì®Ã=!Ó¤ùù|pâŸVV’2räKIýû?úÎ{ïu¹A¹ä5¹{ïº+­|ÏžÂúcÇfÜ=b³’’––¢éºM‚Ük "A8Å ¡((ž_"KèœíxÁ»bV$>RÓ:lzb©®eÑ,%F^o—–òie%}¯»nuÜÜ•o®[wÑÝÙe/JþbÉ’´£;vž=ztƽ£Fñãäd‚Ç£ú|]#Âó\t¸¸Äè¢Èá½îì,[h^…ÇŽñé©SäLš´:eР¯üýï—ÌÑ»uUö‘åËûܲ¥°êàÁé‹GfQr2ÁÒã(>û…)<»E/¸¸H'º)mg¼"M“ eÑ–ŸÏ«G²éÔ)†LúRZ^Þ£zùåËVdº}Yú׫V¥}¹qcaÙþý3=šÅ={*-EêÁ_Ž/Íß{´ƒ¸½sŽÑ’—ÇŸfã©SŒ¹é¦Õ#F¬ü÷ÿüÏn•£®èºü¿=ýtÚ¶?,<ôÕW3–ÃC½z.=~_ûºÎâYö.о§<íŽ;½uÖ¾Ç÷¥e²Lš‡æñûÇùøäI&ÿË¿¬0fÌŠg÷»ËoM¦þÖsïrí†iÓZkêê>nmj³~ïÞ"%…éÙYˆºoQuÝÙDy÷ªöC÷›cªjß-vïÿº½3žo˜ wÃâü½â¾ {½ošÏ³‡ñáɓ̘5ë¥!'®xúÙg» ®âKS«~ýëÚ@ p§T”Âç¿øbF´ €g¯Jôøñ˜;Äê|nÆç­uõÌmN¢ÔÕwÜÓÄBÒ’—ϪƒøçÉ“Ü>wîêüI“V>ºråWa¯ê[c¯Xq6Îï_ˆª>·k×ŒÈØ±üß!C ´|¾öo¸@½Ò¹u~&e— eì4¸>?ß·÷+*¸ïöÛWÜpÊŸ/_~EšwÛ¹€·Œ×*-ëã¶óçǼ¶{÷€æ=˜™›‹hjº°'÷ïÐ<àc%¿¥¸Þ^ש4ˆ{öí㣊 –ÜqÇKnºiÅ’¥K¯ <|Çï Þ³dI­ßï¿SQøâöí3r—.ejv6Fu5>EEΞÁÙEz¥7 Æ‹öÜÞpN}¢R•߀¬)=Á¶Š –.Z´zò¸ò|SÓw:|øÎß]pÏ=g5M[˜ðú?öí¿y]C=Õ_MO 'ÐÑdì’»{òä^¾ð¯»'¼!ìÂe«#-ÎçÜI“©3 ¾ï¾ÇÝ|óc ­­–®}7ßËw‡£ªzö®%Kî(;|xþ™3g²•éÓ;¬±èí©/šNÁÒ=œ…öZž.%‰RoYôØÍOM×­¡ýûHÍÎ~«µ­Í¢…ØËµï…˲ŠRŸWPð·A†§¨ªt«È(Š}Dådv]Bo.»Îæ †î]eiYèªÚ »u±ª;íÿešõ­"%¤qIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/ok.png000066400000000000000000000112051217176075400232050ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞLIDATxœíšy]UÇ?¿sî½oë~½oÙC:a—]YUÀÊrÄa—që åÌü¡ÖTią́ $ Œ: ¡D…™$’nQD [HHÒm:IwBÒéÎÛî»ïÝsÎüñº;‰,&HýÝ:¯úu½ºu>ßßrVqÎñçlêHwàHÛ_8Ò8ÒöŽtŽ´y‡ã%-ÿU{R ÏóÐZãyÞäß"‚skíd3Æ`­%ŽcŒ1˜Ø`« ਹFÆÛ„›&¾3þ›ñ6v½£þfW±ÿâÁmÿ"@¾+ )I ’È~MÚ±othÇÉrŽ·xâg¾¢ýƒ}ÁÕH Ò©´ú»¨âþµ4ì®9½óÌÛÚ3祼d]×þ¸oTV¨N…ž_¬ØÏêÞçÐF3«é˜î“:Oýv çzÊ«¯ûÄËׄ7šdªK;µ Å='7§?4e>O÷?EߺÛ=ÆÖ][Èxéî†d÷ê\Aê3‘—L‡7’ H‹SÊ©ùùJÜsbý<}mçG!t%Œvæv #ÏúŒF»+qõ[‚œ Ô¥?ðâHx£ Ôr¾K#ó QÜ373[_Õq#c#”mˆÅbÆŸÝ…]´øm´&Ú‰"ÛmŒ½'çõ©ËŒ„£_Ap5xåÔ‚Bdvgfëv~„|>GhK 1UbWEia,åG߉±†yísˆ+t;ë¾5.B]ê½û"áh@MÂ{¾;3K_Ûõaò…<¥ xW%v1¢„=álXÎX”góÈŽ9³©Dt;ç¾%È[pÔ¥ÞSáh`<ì¥KD-(D¦§;3K_óðÆU‰‡/ïá¿b,Êá'ÁKÀæ½ý¨ÇI3Å…ºÛDîf '`9J¨Íõ®Ví•èËqOwz–¾zê‡ÉkðKL•ê8üh´‡Þþ_1fsøu )P ìV/ð‘K0UÏ ²“¹ÎÈ\kЉwÉÁÏ™_G«U{Q 5¿PŽ¿0'3K_=íCŠyB[Š/w1ÊWŒUöзmc*GP_{ƒL,¦4¤›XöÀRr¥Q2MÁ½Vâçu q58mIƒ8ç¶]‘{-6's^ù…rÜ3§~–¾fæuäK9Êb½}ð"RƒîÝ?±zˆ=èôZ¹¬á*Nœó&*¥héÚþµ?,–ãí"Då¥Î”]KÒJ‰@?yvÉòáÑá;öp»€*D´Ýˆ§½´MÖ¸ËÃBõìT‡Ó¬Æ‘*‡¾6·Õ‰° X6=ÓS]úªyWS0yBbµÅc©ÁWGY¹»—1•÷¼ " àçzšƒfýõÓo¢;9­ùAŒ5XWv}c wm¾gv:án ´¿áa`/¯\GZDuЏùE[è™Q7S_9ûZÊ6"re”¬s8@‹G!ÎóDîQB I'3ûÀ$šieðžl~‰¬^îŽqøaà%=ÿ¢høg?ð3‰t²³-Û>¿­®mad"ý‰?ÃÌôlFË£g‰]­[,é Ã=ƒw±ä÷?¡.Ðý¾çß JVi­Ç<Ï«¼Dˆµ6ã¬ëtÎ-(UK=SRÓô³®¦l#BvòQâ=JÁäñ•¿/ßEPÐhZè¿{;Û6î Ù¤–s‡íjC@ÞÿÊ;Äâœ#ûUQ¾ï§3ɺιíóæŸ3ã‚…Ö}n×dý,¹(‡qãuØ™ñ…gŒÁ’ñ3ü|ë=Ü;øS2~0xÁ (yØóôd:Œ 0ß…ãúД¶&Úõ•3¯¥JLÙ”p¤¸J) &Ïê±ßQ0…É‚7ÑT dã&6ܶ…mý;ÉL×Ëœq·ÙЮÅ0„ûãð0ž‚$5ºmNS÷G?|òÇ6&uc²‰Š‰Ø[Ý‹UãžÇŒ ±ï5{¸tæß€þ{ðÞÙý@ yØíK$­Du:忇qØÓ‘êÒï›q%F ‘-#ZpØZ§Ä£`òû”3fžÕäi§£5,^AÙæ˜Ûp,  J'µáɉÅʸ Rû^vÇ6G 6Ö7i¥Ï Trdzzæ;/Ÿ~õß·$Ú¼ã›NÂ*Cä"DSÄ¡´¦D‘uáS”%$á'ÐZO6/áÑ M<ñëØºq˜ú·ª>e± íZª S!úÇ÷~ùPùÑÁùâ^¢2¥~êÈÉo:îø†“26Ã.oOŒ®¦¿¸®ÌTZ“mãµÀքد!'Pv!Ý óH耹 £;KçŠïνlÖåžó`ÔŽK\ƒ ”Ö„”X=CYÊÞ‹áU3ÿ¶¬ÛNÃ…z…×,‹ã’]M…!*DÅůŽv|mÅ— PdïОí»óÅü±-´54«V*Ù"[Ë[x6÷J+¦ef ”`ÄÎ~bD®Ìœ†¹xø<²~m²½µYÍn›Å¨ÁŠÙçyU;P ]‰õѳD¾,ü£?|’þ'·Òrq¢×k—EqhÖ¸j ¾pÓ«¿ç39È~Ié¤$³méŽîödçE-^Û'3~Ý 5Õ±©åY†KCˆ(Ž­?žw´¿›æ …È•÷µÇ‹âø§CB’dòMYÍVú1ÎÂd±ˆR„¶Èúh¡+â)ÿE9Ÿ•~}×6>6@Ç…u}^»[\ÎEOÄE3l ®ìò¸ü?¿úùSáì J$²‰æ9M‰æ 6ùiå©SOìb÷”av†Ã8¬Ÿåüæ 9¶îŒ‹‰‰÷GÇŠÃbpX.hºˆmÑVž+==9zˆÔ<¿¡²Ž² ñ”w ¼Wƒ_õ“'Xÿøf¦_ÐÜëwÈâ0®®„•¡¸d"›wÎåá° Pÿy¥<ç7Ô'ê©OeßQ-ÇŸ¬ØÊŒÓÎ9…Ê1%v•w¢DãÄqlæÎÌžMZ§‰\4 ç&bA,W­9Q“ÿ›€ßXYO™Ò‹=?ÿÐ/ã¹5™}NGo²Í[T*”ÖDåh¸R®„qÑ`óŽ?U€­óß´¶j*¹½¥½ý#¥Ý½•DùÖ|57¸¬o jº²SðŸtf ÞÄùûÙoÁÓ^m¢¢ ¢-øãã7Ä­="UfÀn"ö*$ƒ¾ïO¶ Ðä5³êÇY?°‘c/šÞ×4­n±í`ᇺC ðïÎï-UŠ›òÕ½½~“ºU ®xèaâ-Bg¶ hêuD*âÑò¯yº²£b<ííaR At ¾¢ÊüÞm¦êUHøÉIpÏó>M^«V=Æúm9éücV4O©_db»šÚ ¯Lí^Èk+@ág­³¹J\ÙT6aoªÍ»ÕK2¸båJJ+tf;Q¾"$Iø ¶Ø¯<Â(#xž‡hõ𚊊ØB?±®’‡÷<íi‰€¬n¤ï‘ß²nx§¼y^oK{ãbcìj„a ,"‡}#öÏ ßvÈg7W]µ/Õê-òÒ2¸|ùJFŸ,ÒQß4¾_K‰P—xƬeÐõƒrµ•à~ðƒôSÕU~brzëy‰D‚:åW¬â™íë9ãÔûÚZ›¿c¬©…=‡7ìZ€üMÎ9ëì¦*ÕÒþ-Éf5¸ì—²óÑQÚêÛñß÷kóvßc;ƒlä9BUÄÓ>±UýžØ‹'á}ßÇó=‰€ŒªcéÊ•<7ðÈó¿ßÄo>£oz{×â¸æù!j›¯éeæƒ>Ë}iR„ͱ‹{æ%oÍÎI .ýE«†h©oÁó÷…uÒO¢|ňÞIìUüßóñ½€@'Ȩ:²®‘ûúVðÜÀFÞþÖ·ôÍš:mQlâ× ñdhïçœiü®Ê9ç6Å.v-Çס•þÔÿܳb†¨wpÂEs(Ä…ÉmêɆB£Ç?5K²äÁŸ±n`ïºè­½Ó:ºJ…µ"òºÁë¸(9öqkZèïuÎm6ÎÐ~rƒ`å“÷ÝýÀ å+N½à8 ”ðð&Á'àªO’;W.áéþçøÛ¿¾´oFçÔE{Â=k&ªýkÀù²öªGw_Wµ]KÒ9kíf‹•igµ9D>õ‹»—Ïð}Ÿ³Ï>"á~^¯Iàð½•wòTÿ³\É5½s»ŽùÎp8´F`HWÜÀ|-ìUŸ_Y23Ö¸×Z»É‰µsΛ‚JìøÔ½?½†ŸðyÛiçR"œô|‚>>ßyè{<5ð,Ÿ¿äÓ½§tž´h›ÙºFD†y]=?aÒý€-ï³@ÎZÛïÄõwþÌEsš¼äç<üÄ£´ÓAŠõd©#Ëíý€§û×ñ—,ì»°óí‹«®ºFá#áù û“/H<ÉÎÚ<ÁÚM·âÄóæÜÚÞÑ´õî›ïåþ‡–3“Ù´ÐÊ¢‡nã©þu|ñ’ÏöžÕ~æâ"Å×lz{(v¸.HLˆ°Ywæ%'Èc¥uŸùñ½?ÒLe0ÜÂoãã—^×;§}ö¢]¼°6AbȽŽÕþåìp^‘1@γYy²âœ«O¹¥õ¬Æ;ícj7ï¾èm½3:º3´¦L8d±G_LXmí`ìfßWîœóN+ïÊïx{kóp[KË]cvì©z•=jàáð û¥C"áç“™Äoý@Wb¿àp»×@0"’Qe_y;´ÖF”T€˜£^›¨™`•HY)‰”(7±Ýu´ÙËÞùs±£ï¢äëlàHwàHÛ_8Ò8Òöë[ õðù IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/previous.png000066400000000000000000000066731217176075400244650ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ ‚IDATxœí›Yl%Çu†¿SÕÝ÷^’Cj†œEcy4I£™1´–ÈÙ!ÄA6ÄÁÈ€¡DB?åE ‘‡ ·8/%ÂO~Ë[^DC‘dÞ ÄNÈ%Y«%hr¸ ·»tw“‡êK^rÈáNPdßêÛuëüuΩ³TËá¿ÿ_–I ‚a& %˜€faõµ ˜a!q`j` f?«¢E„Ì9¼Sš¹aÂÎÈÌ T÷ƒRãgÀð€®[1CDlxN ¥<ÿÕ£üó¯áv8‡ÿ7tàØAÿà&”ÔFP 5CØ…Ä÷„DÌ  F+ÚÌÃßeÁvÂDÄ0êýŽXMû€™‘çüzë»ßyöÌk?ù—§¾ ý§Á¾„(Û5úψFy—¢°¯*`f„`”íâ¥ûîi|û÷îíçïþõHê@A¤ZÄ­¨BwµÕ° XÐeiØ ífF(Ö¥±¯ýæÉÑC߼ȟ¿ÓbâÇ7éË|*PŠ b›Pd¦Jÿ'°2ìzõaŸT »ò­©Å±¯ýƉÑÁ¿ºÈÛ‹žoP»g+CDp[i`"˜}÷‹ÌïÁêÃ>H€™¡ÁhÞXûÃ'<÷8oOÀ@ i‰ Sqˆˆc è2©FãÌHåø°'ö€.ó‹SKcO?ztôèóóúuÈÁ¹èh&A™ë±s"¨â<¸æÖ7‚=[]ý®#öžyØ-VI¨E'gqziìéGG^8þüc¼95ÌC4ý^pb˜¬çÙÊàµ/ U1{Î<ìÒ¤‚gZc¿uîÈè—ŸŒ·& o=æ!vT Äÿg±Ü œabÔNî+ó°K 03TùéÖØoŸ=ý×OðÚÔ;‘¯UÌw­¶Î9–w€ª¯«ö»ìøþ3; ÒO0?Ýû C£w?÷8?œÚ€ù^Yݺ``•ÎCíhº>ïÎÛ*m[â´ qÂüLë¥'î=4z_Å|Ö‰áxWµoiÄ›&‚xYÁE0£v¤oÅÅ=€Ðq[Ðu>œ3æfÚß{âþÁÎÿåE^»Y«bþvTî¯øÈ.®ú¶f 5”yØ $Î1;Ó|ñÉ{½ðÀ7/òú$d­€«öó ç­BÈ=¹B»ÐÐW'˜ˆŠD;d+[ßÒ–°jåoζÇ>50zþùë¶ \e¨n7uuB¹äã}åGóA3’ZŠ!hTj#¦²¶CÖ}¨7%&+»êzo 31ææ:c}ðëóÚu%i曯|EÁ„fÓxñÙ{ùÖÙôë'þñg›ý±æ¥VÏŠôèσD©þ P“RCJb¿Y¼V/bœªb]³´)‘yaa¾=öàÉÆèƒr7®|‘ãm;½ f¼ñÁ"Í)ãâýƒÿ†s¤‰¬ØÇîPÛ4Í•mZPìªW«¥qE`JÍ® L–…ÚL^ÚìÙ¿àXâ7 ÆêÆÂ|>vîxcô¡?>Ï×ßél!Ší%'Ð'Ž7kŒÖäpÿNÑ.<=R¶1°X µ91–D,'˜b$`Ó “f5J­ÕççÓùz-ù÷ŸÎ†';aC¬RœÅ¥bìì‰ÆèCOßÏW×)ð[û[HŒ#ý)64´’Ü­Í3@­”˜,ÈP«cÖ‡ÑZ³¦3mš²(ªõÆ¡$»Y´ô¯–¬/fqŸ_XÌ_<{¼1úÈïžæÍ«ß)ðn‡Ì÷ä»xx=2ó•Ñš˜ÔPÃ4U$1³TL][q×K ¬§f†XX*_:3\ûöÃ_=Å[WJ¤"óú«—Ú®’kgU¢ˆ!ˆs'NI\Û•’›Góçe5]ƒ·Ô,ÇN©>üä]¼u¥Ä:%©XŒÍ5ÉP™%Gw• ‰›´¢æ3ç­ô !¦™V &´‹0vj8}äÑüçg(•ÔÅÒÒò¦³æ·÷ŽzǶu/7~tåÙÕ £M!¦Ôœ ‰Cz% òñ¿3PKF/œ?ÊÛŸåX^’ú¸Ën<‡ÝT7ÖÒF"vº·zˆµ %=_éMEKÎŒBäo²Ìqe®¤µXÐHˆÅÒîÚdw®«æ¶Ýîu÷÷žNYérôdŠºÌu£æµ ¯]©~Ôª½÷—0pޤrSþzâ¾?_Ø?$׿ùR&\)H‘Uà.Ó~ZBYã ¸eΣ8‹€TÀ9ⵋ)Ƙ|¬é>Û¿UÙe50Å9!©¸C†¼ãÔšjés'Ó„»Ôùt¶ˆ6 WŒzÆßYïÅN¬ü†è£Tb zSAóRy”²b +@œ­À«T@D誷Jîõ¡>é»Ò —NzÎŒd|<[Psn}¸ÝùÛÊâíuõsÕç®tûcvI,`&˜*8·¬€A`.”|Þ.ÊiWî¨û—?/0îÎhc¨lK…Œõ›UáÕ9À=hR‰vÕ¨ N*‘éå:jW24ZYãuD¸®†´ h¤Œ6¼|4_\:;œqv¤ÆûS9µÄ­›ÈÝŒ (¤‰Ñ_w”åê{;¥®Tõ$’‘•‹U÷01¼%B)r‹'ØB¸n‚´k8^nx{ªxæ£çÕxo:ê°U(Tyê\§î®±´÷k· 07²Åy©R“Rc>(” ! ¥ª”ŠCòÒ¤ÙQ&g …XÇh\SE;¥J½æÇG¼¼?[\:7Axw2J‚lG’ÌQþ¨Æ}˜?^ yOl·|}Kdñ‹ QT¥˜ m3š†6PWÑ€zÁù#™—Z!,Ìúo•€e&JZ…Ñ—¹WGêbïNÏ\ÉøÊ‰?Ÿ,¨%²euPÁºã'?j±ð‹œä[B6"…vHvQæªìXô"óÞ1ë=³n:aÎ9æÅiÓC'Ú^´¨‡”ÔÉô¢7·É8šÀ„´‚J_êÆõ‹¼3S\º0’ñ•cïLÔe?aípÞ9úþH‘;³ÉûFäûôl°Ê¥îlw¢ls ‹D)^ªú[@G ]É‹\;­¦×^Ü în¸‚4M˜ê\+¨ö§~üX¿×w¦‹o\ɸ0A¨9ÙTÐl6‡烙9~VæeŸ5D«wºÁ P`4vOëÄf…AÇãòÔ“'AŠ ”¥¨…uŒàz£7M¸‚è’˜ô¥òƒãýÞ½;m¹‘Œ÷f"›©ƒHÔù¢´¼SêÏ5%åÍlÇÄ‘Vš®ü—‡i®AÕ¼„2ÙRRT‹’pM°¾¯ðöÞLñ̹ጳÃÎÔ6S‡Ê ·LsíçsI\À¬Àí*¢êæ•zíÈ-¾¦•VE…ëß-e…+o)J‚‰6K•¾Ô¿r¬ßËû7‹K÷¥œ¹#ããù†’ÐÝ—o¾¡mCËè˜([¶¦»!‰Ža<·ºŠ·-?ß4aBM>j6)"ã#äò'ó%ªÆÝC)…€8·A«jG‰©ñ^Ä;$K9ˆ:àz´¯¼iÊ55>h•z]àòá†{ù—‹%ePNö§”U¥ï–BhÕÄDDIº§D@êÙŠÏz€@lˆ§eÂD0>j?\s—¯5•”‘†G%Æ kcq‚ó¾ qRõ‰ß_[ÎF;‹Ëbe¥ep-¶—3÷òd[Ñ ixÒÃ`l8!¸Ê3_,9ðƒõª|µ÷î+í*0•èdL¨ñQ'0)0>¹Ë3EËJÖQ'‚,7±9éÐ@LZÀ¾ƒ°ÛCRF;Ð\‘Äójê˜)õÒa/ixfr­T]âÑ“grKÕ¹!H‡û)¦—¢ÔÄtõ.§º>íÉ)±*€š†SE2Çxê˜ÍõÒ„¡šçf©Ô‚¶U—sÛM/žH‡)¦æ#ì{–›©¨kïçÊUàr_ê^žÎ•º(Ã޹ÿ6òëàê•Þû ’'ž*鉡*‡Ç¾¨Ã^'§š&|R(“No$îrÓÁ™TX|MiýL,.e7ŸyK±ØÌÈîÚ7›°g…›DIø°P&jŽWBË^¾û®„£àiþT(§$­*W•û·qëzÈî¼#ž‡=a¿N‹7 À’|üËàïzÒÿÅÿ „Y®¹aWSOLŒmÂUX¥ÇG(&§·wë¶/Të×õ™³«7laËgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<%IDATxÚbüÿÿ?Ã(¹ €˜Fƒ`d€M#Ðhá €FÀ4šF8 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €FÀ4šF8 Ñ0Â@&€ˆÆ`ddÄ«°²²RH@± Œß €øOhooHŠFÐZ€b„-Á•€Ï2ˆFÃzH$†`B¸Hl ¼ ùþ@jrnçáác—Wc””c`ggGÑ 3avqd»°éAv „͈EÑfc3Y ·z\v3ŠØ~ÿþ=Ã÷®_¿ÎðãÇd©`"h$&ÎŒüxh䃸¸,ƒ5ƒ„„,ÃׯŸÞ½{tÀ+¬‘ñ¸#Ž‘€jÙK;AñÂÄÄ„U¨¸ÿ>çOŸ€qdÌÀÁÁÁ°}û6†óçÏ•@fFF¾>´Q¦¦n 22* L@Z“““ª©˜’E©¡w0º$Št&&fccc†uëÖ"'P›`".}„­ˆ”ó]E¾ƒÐ?UU)ªF>ÈrJ"ÜK©ÞÁèWPæ522beضm+CPP0ƒ¡¡!¼=íÁaÄ„¥Þuñ€¹]“AZZùÿ”•å†EÄ÷’«T-ëéé1œ9sœÀmwÑ€K@¡—à® °Î·aø÷ºü€Füp͵´ò«„„Ãóçσ`ÒÐî< &´þ¾ˆ-*ªÈð÷ï?YY^ªDúhäÑ×½êêê 'NœÆŸ<??¤øøñ£7¶î @!—0†„„:0÷a““öÅæpL¨ÌÌÌ@Ì쪿gÐ××è RÁH ¡« $¶b°G’APðÛh«|ˆê©QPPÉÈ@ªpVVVÄ bý3L-@aôøø$þüùÇðëקцÝ*¡Õ€0hLàÅ‹ ÂÂâèJ¹AŒ@,˜1À†Ÿ?¿à´ìíÛÀ:æ%Êh®á`LqLuØõ2àg6!uÄ›M®Èõ/auÂÂ,ðDž8@ Á?«6lQÈÄï@ €bÁ–’@%¾”öïB ‘ÿq8þ?šÃÿcUƒéAtuøôávªYĘ S÷K$çâÍ&6\°»[©ãóóóƒÙÿb-5@©‚ˆÿŽàÞº9‘°³3ƒ1¾ˆ>ÔLnÆ4N!Å.dwbw?~sHu)%²°‡$l¹Y W\Bh&ï@a-S ö1l¸#@j Í´ò(’É0ÝD‘c7ƒì>Bf#ü…n(ࡌp7ÌLdÕ\$ó°ùã?<ì­½@ØñðÒ[@üÿðÄ‚€s-@ÆÌ`„¡ýÿ{YíÍ*ð˜F̧¥$ÿnMÇ"Á½·i.&t(”tŠÃD¶¿ñ˜{ðA#“Hݱ]×fˆ˜òq$Äò¡EŒëhþR^ €+"^à‹À†ÂÑøO0…Ârôû÷?¸¹YÀUö€þ£TÀUzüÇSzàN„zb/±þãL ³ð%lFŰøÇ?Á ” @¥Å÷ïp´FK|¥0“Ã㽋‡-!@2*n@dvðŒ0‚ÁöíázøùÙÁXY2)õíÛop‚€aÝ,ì¹d𕨠–¶¥¤øŸ¨áabJs€Â[àïüÇ;¨òèÑg† Þ0ˆ`5ƒ‹‹•AN„!3Ž_¿B¬¤øðáÞÁ¥ÁUzüÇÚ¤Eé©`Ý@Fœ•ˆq0 Üõ;1½üÜ¿ÿ)ƒ”7ƒ˜á•DÜܬ` ™«ucþ‚Âë×ß11#s””¨]5Â¥B=íKP±{fã5„Df/à?R7ÿìöíâã5Hž5"A‰„a”^¿þ¥¿ãˆxìHx bh”€:Œ{bˆp\ –èÅ5~Œµˆ}ìðÏŸcØ³ç ƒ‹‹ ¥@T”ŒÁüW¯ T:€èß¿ÿá‚ý%B‡fé wX m˜”=Ùã G`6¤°Oºœ8ñ‚AU•ŸA^ž—šTµ W/ )PB% %ü¹op”øFÑÝk`iãêâÏÌ„c(wã6 SCìÌÖŠ·òóõ88XhÙÁXMMÞ°„%†W¯¾ùˆlLÞÒV@æ,þã°#&3QãØ,Âìâóë×ÿ ë×ßcˆŒTc 5*A˜áÝ»à®)fŽÇ>eK¸îÆ]z`ßVFÒQàïb›ØÃo€¿ùg½kþÊ•w çνf02%;RŸ=ûÊ ,ÌŸ‚&¼{÷%0p¯!@áÃ=<0¥(÷£O3^ƒ ÎÉ B) s€¸…›6ÝgPPàeâ +€"ÿÀg _¾üb”õ¸À4¡ñüùW=œ3w¸'pp-ø Ô°#¿ô@íî jÎé`âÇIZ-óùó?†•+ï0dfê•@íî.Ëpÿþ'ð8Ã¥KoÁâ||¬ÐI¼¼¨K¡ž<ù ]»ðëì¾ 3 \éb$j¿!¡¸ 2§ƒÿ£Lã‹xl‰ãæÍ ;vþ·46štÂŒtücóØgîpôxè_z Æ t‰«ˆ¤é`dñMÎ%¨êf̸ÊPUe ]C@>%"Ðì#h¥òùó¯1î1÷ÿhĈw¡Ê`(=§ƒ©Qžn ƒÿ3PºRÔ7ß¼ù>Cx¸*VÇ}ûö‡èÄ* ìí¥ÀÓÏ;w>‚ù¤¬ÎÁÞ l¥¤ð`Øy€ÂS0\HJ½+wî|Ì ª*€µkxëÖNNfuuA¢KYY†˜u†cÇž3œ=ûï¤ îµø´*=З”‘^z ‚ˆÂ_9sÈ05°. ¬e ã£âÿXø¨b³g_Ú¡ÐTòÆ–/¿ ^/@,àà`fpr’–,*àÙ°Ñ>BY ¡?Æ4 ÁG¶Y h$#ä  >b°%`Èf.z—ûP0þ €˜È›&©ÿ±F4®Ä*®ûû±l•”¤ÁpèÐ3†ÚÚSà>)´Ö +K—A__<¥üùóoðüöÈDø(F\aÀ‘@°'d1XDƒ–xaK@a¸ù°ðÃñ˜û7ðgf€¢p€øzyX[C4J¸mÛC//ÔóDD8’“5&L¸ÈÐÚzØu”e T‚® €º›ÚÚ‚ óçß`xðàxª™‰•• >7r(q€¶ø2»È—CÞ'€î?yLLŒÐ%òL`>ÈÐry\m|s)¸æ`‰‚¸ Â%@‘<€ØFÜt0q£…®\y›ASSÜÇG&&b ÖÖ’ >v28ð”!=]‡ÁÔTŒ„¶/C])°J¹Æß¿Sg!ò ¶6(1prBVKƒª&JÛ°ÜOÜP0áÒ €°6±‰Ù3_Ôý}?þf˜<ù2C_Ÿ5†ýqqê —/¿/ùôé7Cw÷ypÈÊÒ!©4ð÷W·-æÌ¹ÆðèÑ‚%ùþƒ Ýþ¯”I€JV0fff$zt} –ØMÓž ‚@ìˆnàánüÃÀ ݾýÜ(Ä6³Šldõ ~fæA†S§^’Ô6­Khn6&”ú³AK‰ÿ0ýøãÇ_ðªèÇ¿À'§ðµ=pµQ`fãÚ½EÊŠ €bÂÕÀÿ5Œè2W £ö ÓÆ°1~d £#̦Œb6(gµµcho?‹µ')3´´X0¨©ñãñ˲6ºÿ`jOÀh¶Æ#zÏfr{¤ÿ'i: €˜È Æîqü¹éI *â¿|ÁŒPÐz99´@þì÷¿6÷ƒW‘@ÃÈ ¶hì4˜„«t"Ý¿„KP‰ðôéWðZÌÿkOÔЄ‰ã.¡‰ïy“A XS6%Å#º>PÀtuðûîÝ(„¬T45âÓ /_’vÄ··<Ð>+ %fD#ÛÏÎÎNœ ö©¥¨‹úòåw´~>jIÙö£ˆ­ e. €Èìþ'{:W+›Y V?hU±§'¤k¸fÍ]†E‹nK†?xGyÎpáÂ[`®VóJD'Ðú¦&s†Í›‘ŸûÔkÉÎÖ–&| vv’ ååÇÁkñõÐý Ú wÈ¢Wü›Z»à„×âK€"©ˆœº(™&¾UÍÀ0qâ%~†I“.ƒ7š{¨(@§M»Ìpôès†ÒRC .¢‚¯¯ƒ™™Ä —À=|þ©S 7VAkêëO‘ÜkÍ`‚r8(àÆÜŒ«7@L ¢¦ƒ±LÙt0±¥(Pbc÷bxbh> 5u?xoBHˆ2щ@\œ ذ´`ذáÃÒ¥· ¥¦ÿ@ hk íZ±âɳ¥ 5 6bÅæÜ1Ý@b«€ÂÛ Ä×Í ¼Þ§^¯Y D*Iòòƒ—†‘”&O¶¯]Àfvoï¬ÕˆU”Æ*)½P›d&®ác|Ý@Ôvá €(š "¯¿O›^1n8sæCBÂ>ð’4R¨úèî¶ë¦àѾ¡Fd‹4¦cˆ+¢ÿøQóžžrà†Üñã/Àë ž<ù×ûàÁgpO4ñSTdÀÀÏÏFQ"hm5·5@+¢qWIˆ°úúõ¸[ZJFÌš@b爅˜È'ÔÝ  [â ´ô ½ÞÇUz¸»Ë÷€0€Vì\¹òœ@øêÕw 3g^41a‚ x €\ÚÎVYiÄPVvœèÒ”X@U òt0þvá €–ØÕuJê\Tam-¶’˜Œaë@SÌGBCW×yðQi©øLr@p°2¸j¬JLM¦›qM“³ €HJ ©˜Ié!/Ï?´E4hßòÞÐz]]v²ý×Óc ,y6£T7¸J0P Ú'o ŽÔé`€b"¦ˆ9À0(È Ú5ƒ¼‹†œaaÐÆr€®®0E~µ%@Ëàñ-"…ñA%²ð Ô;@LÄ6q%†Á  ä?FAä}ûž2í¯­<¢'µ%’“µdýü i¿5Œp@,¤ÿ°I†¡ÐÛ uú åè  ãæ@ÛÍA‹ü º wÏ´ôÐaÑÈ•Ð8@±RÛ ŠÔïÞ°á>#Æü! ÁÁ6 bÊ;oï-ð“M°uA»ŒpuÉ™  ¼%h)2öÈ UÊ ÜØˆH – Ø)2_OO@DOFq€B^rÆûŰk× ¸Ã‰_üŸ¨¤ø746ŸXuô#Ö¯ôOŸ>fbNp\BÖ„œÀººßÎûÃpïÞsªE±6‘GŽºÁñ ðë×/†ãÇß«p\BªôX÷ÁrøKºº}î3fܤZäÑ*âéy”øu ÀíÛ·öïçÿââ¿AîùxêÔ©ØÔúšÀ ‚ƒã?ƒÍ'†Õ«¿2lÝzkÀ#Õ ½ê@÷ïß3Ìœù˜áÑ#vgç°aǹsç>aS@è `!¬-`jú…AUõ;CIÉ-†Ã‡ïhä tÛ€¿täOž|ŠáÈ>päÃrÿµk×z°µA@a[œcx{¿càçÿÞ~aÑ¢ ?þ¤zä …¶Á`ªßq[·n1´´œcذ\…ƒ20|þü¹wÇŽO°hOô#Ì#UUU`š‘Qè¹7ñ°ê4°w¯ÃåËÜ ZZ CE†K1 ‹î)óƒ-Ò¿~ýÊðêÕ+†uëž2lÙòÜèå|Xä3ìʾ¾¾Ú_ýó €X° ^°²ú/üý{#¸Mjx{¿·&AEKnîo`©ð\=HI 2°±‘7]IÍÀ¤vÄ …QÏׯ_ƒznÝâF40~¾Ûm¯qó—˜Èõ Á £``–V ŽŽ_öíÛç- `:Aƒ  þ%¨‘1 °³ÿ·ôÕÔ¾Ã#Z2ôLš4©Öw DŠ{€ÂqX4$Q´´´l¬©©12`mPÄGÁàþü9öòåËžE‹ÇWs@K0 <G2ÀÁC Xbmm-(@±Ãhpð÷ïß+ÀnÞ±§OŸ®Z½z5¡CA²¾ €ð\677?RA˜€4\\œÝh ¸råÊU\}{àt°Îãâñ5„nÜxûGCCø°¨ÙärFÇ  Üü¥´´ô[ww7†$@‘}o`vöÁÿŒŒ Ÿ§L± 6ƒãoÎ<Þƒ€jßA¸²²ò?l}': ’ï Dn'€¶-edø J ºeútÐ"ÖѰXðàÁƒ_Ïž=cس烴´+Ã;Kpª ÆÑ•>#ÓhŒl@£ `„€M#Ðhá €FÀ4šF8 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €FÀU¨¤^Æ«ÉIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/rebuild.png000066400000000000000000000061771217176075400242360ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ FIDATxœí›kl×uÇ÷ÎÙ宸EÚz"åªvƒº…RÇµãØµÚ4n(,2- )Ü4 "£ý‚ ¸@ÚÂ..ôK›I›ºò0‚&@üˆáU"Ù±T˦L=hJ”øÜ×ìÎ̽·föAk-KKÒ$ `13÷yîÿž{ï™3ÿÖZ®g‘›­ÀfË»l¶›-×= àûÏþôºÜ ï»ûv¡Úˆ"ƒŒµX X›Üc±ÆbÓô$ßb,éÕ¶Ê6òÍêº<ÛÈKû„‰!B $@Ê4 )à'O²l /“¡Ðã3¿TäÕéiö1Ø¿ù¥"@3 h¦¿:=Í­·ÜLÎWüäèË@ja¤©Õö¦ÊZ‹n δc¬Å˜Iºiæµm1ºuo­E›¼‹ÉÀe‘à4Þ „ öoczv¾9›¥ ¤Ì3¶s°™^ ÂUÏ¥J %½æs!J9“Ì ¶5ã’6ƒ·`/Àhp«B ÍÁ6, ‘pþœ¿ðÆ*sn<·§w*Wèñqçr¢°N.—½|¡l1Ù·gÇšÛ¸¸°Ü¼o udùñó/4Q)쫯é}j“ÉåÍå’4±*¯SZÒži^‡r™ï”&‰õ4:jTièÓðxÇÇöR¯MÚŽAÁõ"¢…è»~@s 4Lä®÷ß±iÊl†l¹%pìØQ¾þõ¯½cým¹%0uòÿ8~ì(Ï<ý£ ë£ÝíÝr86æð§dêÄQž}úé ïoËà»[œáÁ'9þÂ÷ùñZlA2è…30ý"Ÿ™¼—ÿç›<ÿÜÆ Þ¾È;+ÙŒB/ž¥îÕ‰ÃOøWyâÉÆÂ]·Ü‹m¬`»ú<ïVÖ€ Z&(—€Ä‹oºBëŒ1q¸ªncC²’¸ùUÆÇvÍM¡p¤Å) Ž´Hi‘Â&:[h0ktë-2ÒÔk1ûvÿ …ì~VŽ|—(2hm(š˜‰÷xüû—¿ˆþÜÃÜs ÍÖ(ë@möeÞó7€  *Ç€´ lrÅXÚ€®A@TƒzãjêÎQ.V°å%ÂÀš(Ö`"~oÇ·þê0™‡ÿ‰;n½{ ·ÀS¯UDéú? ´¼‚1®“ñb”k’¤'NDú*jâdðá Ô–!¬@XÇ©…dCXDE— Ų¡´Žù@oŽïýåŸ}éqî>ðÁ®ô½Xì@÷‹J™•ùsËK¨ŒFfcŒCFƒ+ÁÍA¦¬Ç'±„ ÂO ¦‚«K„Ð`ub(¡åÂ2Q™[z+¼tä…®#Ý €îEÆJsóĵ%DV³°“Wuús§§zvA Ù<Èm ² ( nnœ%à"">K¶ržº6 !ÔPÕ°Ábò™¼âSú…îõ•­É^t•òÊ,ÆÔˆ TË0¸íc¥‡Ê!È ‚?X„“I*ë¢*Ô–°ÙâÛp½ŸÒ7s„PjJ"Ù>´O !'ñÙO>ŠXƒÅJÑrV…ĺ% é$K|‡ù}¿ÎëçFéÛ5¶>e 8NrÞEAò³ŒÁXƒ=„Ù^–Μe8?‚;¸È¦‰mLlÀ•ƒ,Ü?É'þèq,¶k:Z@EÝàX„( Yú{$vi‰á}ï¥ç¾/¾½BéÏœcÿ‰<õØ~3*¬²C½A53À¥}œ‰ƒÃr´Œ61¾ãÓ£ò]éÛ€é™K ôwÕ ŸïEÕ d\C>žß …]d}ÿšÛr©#ûF’“!¸HÍw˜ýI¼ï!ÎÕÏP«Õ‘¼®h·ö&A=ìXøj$?¸›L="«,¾¢°ú ‘àgµŸñÔóÿÊŸ|˜mbÛÛr¤„Âí%\8ËËsïû³v†KÁ%Â@ãXAlCvçFºÒWt²G: _dûv’ 5žå;P‡ÞQtï8S¥Ÿó¿ñOè&²õ·?mU¶ï…™ã\êÅýµû™¸žç|õÕrLÆJºÓWv²¹ßÚï¿U¥@úlÂ8/U_â‘à(Ÿú^˽rU¾–5åcÏRè…ý ÏÅßÄØ23á,§Ëg©®ÄxÆ¡ º3x Ä<ÁLaå98Žσ޽¼f.ò·þSìÚÅkœàbm{:‹¾}ôäOÃG¾XÎSÄÙ2SÕÓœ\™¢ºhð#‡d÷ß:n‚ÊéÞÜü N¨P`º|–Ãá¿aÆN}ŽioŠÀÔ“/No'#·!Gn@[Í…à UQäDñ8¯,œ"X°lóœ÷g»Ö·#®ê~póƒˆÐÇÍ87w„?ž{‚Å%Š=xJ0çÍR¯G¨üµù]A¥T¦**¬”W¨!aˆA×M×ú¶»õ “?œ©Á3ôž#pUé;Œ-ïâ‘“_¹9‡'<\éâH)dòrhc´Õh£‰lHl#–^¸ÈøðnŽøG)•Êè*Ø2 D¸Îž «ºŽe·ròèwyà¿ÿšÓrFT¬¨%„+ —vø¨± Ï!K^úÉу‹‹ÁP¥J™–X d)ÕŠTT]ä…Y*ÅS–“ƒÄvj¿Å»ÀNã/þˆÃß~ŒÜ¶An }Œˆ‰k1²b0BQÑ!SáYN×gq|žD))“ïzMd#j& …„Õˆz1¢^Ž–CâeM}AðÖ@§S`-rø«OïAÜJãöG1Q%"ÎDh¡MLG˜ Žö"Œ¡ÝãÆhËÄüÖD˜LL1¹êØEàPzÁÖ»×·} 4ï®j‡~ ùò~†ÙãÈø>Fˆ,¢1[+[SPrEQ̠ʪ꣪>n5‹ø¨š‡ ¤NI†Äw°`£4š&^k müë³î88É£Vðùo?Jÿþ>ª•2Nì`– 6´ØÐâõùh Vh¬jÄ5†-4Fh´ˆ‰Ð„*Fû1¡Ž“[vðÁ” ?ßO½Ô=²ífÑÜýÛü6|þ©¯ÐwSžjµŒ£ô²&{Ü·÷ƒœ/ϰ\+¡ª2$!•Æ Ó0§±LdСA„!%&o±Êb²‚› ãØ~{׺v|ZS˜Ù&Êßó»ã1åð¹ï=Fn,G¥RÆÁÁT ?|î|ãSÿÅžþ‘kŠè®ub:IûPe§Äµ4ú›ñÈG¢üzl>¤+Y\YÁw²)çG^õo£e}zb•{uûÁIþâÞ‡ˆ_ÉõäJ pб¾B#›#M´Y_å&ïŸà³÷Æž²dû}Œ¶Ð½÷ºaÒÜÌ(7ñû á?^ùnŸÂê­GHmDœî_†®$0xŽž8†«Ü éc-²áz`‚CLlXûk‘æp½þs¤mÜ‚;Ô†I‡£¾ŸåÙçž'“ñ†wJ–Æ&>šIùÃ0mÌq›:A²›òŒ[VÕdŸÓV¯­NBöL‚Wx5{T¤œƒ”%*ÚÒ“bé}‹mÞbš'÷XƒR7íÿåËÚ±þ÷§D…ôXOö„Ÿœ -—Õ´Qç XkZäéUìðóÜÒ`§Î¯µ‰sôfb4 ²tcði^c€B „$eÔ·Ú@ ›¤±ƒÔº­5Iä«S<à‰¯}ë™\¡w Z.W‚j%(­,W–ç£Z˜(¬ë&çÛ€Ó6f§‘.ÒЪH¬qm™ÝjÓ¦ƒoÔ²rV¬.Úd„\þ1¬ÑþªâX„t„—ñ•ã*±kÏÞ|.Ÿw²~Öu”Sˆ¢¸6²søv!DV4Ìth×Hÿ;>0…amvf¦2sfªR^œ¯ÑÙ}iúµxЗ#põe®¦î›Ë ’=N íô‡opwìËJ%{§_=Ìž9µP«V‹«LµÛÀÈÈê ÕÑÑÑËŽÚÑÑÑ$*tb||œlö­©ü]è+a“ÿ+\ŸÇ_C¶Oð–wØl6[Þ`³Øl¹îøg4x½ÊhÐIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/rectree_off.png000066400000000000000000000011221217176075400250540ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ ÀçvÒIDAT8Ë•’OkQÅÏ›ûf¦LºL– ‚c “ò ]DÄBÀ¯ n]‰ ÷vãRÜdÑ•» Ê@Hí".Úh‚‹ d•0LçÍßçÆ” Ó6=Ë{ÏýÝsá2¤hû áÙïöq!¢(b¶m_X–uñ¿—§î~¹Çõ=ý1CJ)‰ˆÂ0<p¶€ˆT"Ú¢hKJ "âþl  Ñ“0 ý$I ëºàkšñ*cŒ‘”ÒR®jZšQÁ5bŒá&)7Ölp]7I)'©) ^¯ï˜¦ùÑqœDQ–ÏçïÄqüHÅbL&ƒÙlv¢ªê9çq+A|êõzß8 ƒe¹\NªÕês)%‚ €ã8—[<ÏC.—ÛUUuWÓ4ض=–RN.OÐ^Ng2™|fŒ]{÷t:/—ËÖáÃß@÷ý50üpÚ- •l6kú¾0 !„€¢(àœÃ¶í_žçµŽ|EÿžnEŽú[`xpÒ-‹Ã0Lß÷!„çóù|ìºn˲¬Q4XûÚõxñ°ý¾?í–J¥ çÜ ‚`5ü´ßïpµÛín³Ù<«Õj÷@{‰Û«ÑhèÆ‹«ûÒ-É輓IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/rectree_on.png000066400000000000000000000010501217176075400247160ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ *GŽŽ¨IDAT8Ë’?hSAÇ?¿»{÷òÒ¤… "D‡ÐÕÕM‡&“ƒ£BÅAé "Nnuqq°iÐÅYÑAœœtHZªX ¯¡æ‘ä½;‡`‡öõŸßå7Üç>Ç}ï„‚D4'çlœL§Æ%Pí[}e,»YS$H;¹^_C·Zëí,ý´$À¨@ä”p E½£ Ժʘ!:°Îó¦,xDO¢¶UüÄ!þW°ó{nß‚[Ÿ¯{Þj; ÙéÙʺêí@ÃÀ¡ÎèÑÓü’”`ü'T&Í^¤‹ù;0~æ·’åŸn¦®ê9Ží.nèO¿|‚™£F™š®@éK¾ê®›þ»‚½½F¿!­+…¸½]âAyÈß³:ø‘Í'[þûN£%ïÃÚµÍ:oã­Ô®Ý DÏz-ûͼlò'E¿çádžmÅÍSí+ñÑK|¥¥|üÈtJw¹pè«E'óôrµR~ê•øê¢é„ \丙y5£{Ò¶7''ÛÛ?z°|}ÿõ¿W†² {µGIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/redo.png000066400000000000000000000112171217176075400235300ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞVIDATxœí›y¬]WuÆkïsν÷ÙNì788™šPšÆDdhBŠ )¥ ¥¢ZDÒTPZQŠ*!eP±Tµ•¨¢0j!¢JIŠŠ Є’‰B&œÁŽgûù½{ï9{ïµúÇ>÷¾÷\ÇxjU]ÖöÞ™Ö·¿5ìµö•Õ×M°ýO†hGáàxà8  ô@&@–-9Š Êž£ê–”Ý‚ªSRNÈ„pÆÉgÒì’v:M`H€x¡¨<Üò(¾òˆކ¨*E._s)ì¼ ›% B]ÓÔù'iÐ;áŒkè\Ðáž«   $ C \ûª€•g}FŠ[¢œ.òXñ‘8ŽŸbûy‡-ûáüÙ+O•ú¶š‡f7Ã$P_ k=UURv+Ê^É9kNá9«žËWž¼‰‡.|"Ž.rÎm§Ùƒ«‘šÄ©LŠŠµ~/Hõwúø©’j²ËC>ˆõÐ4u #;Þ68ä{Šä™/ð¥Ëö¾ è]°:½_tº%E¯¢;Ñ¡* ªªX›¢*Ž@{0³ö•l~O£T ¬ÓÞ¼:ùe§¤( ÊNEÑ-)« ï \á–\Äþ°ÀÌШœ|þI¤æi̜֞#+A:`%P@Qzʪ ¨ : €+<Þ/UØ{·¿kÿlͺ€FÃÔ2žF)Vh•7¾ô”‚²[PT%UYàŠ£ÈMÊÔ9ÓÙöA¼-ĵ¡ ³`€ƒ¢(ðef@Y”…xÄ- r8 PÃáPµc–ob ®u‚ ð ef@QøÖx|ë ü¾ 8\¶ÿ‰Ó&°dÇdö¡õˆeøìG&€—¬t;|QÐM=Ü> p‡“Ö*X"+¯v̲M'ó*ₜþúv8À •wÙTeé[e÷1q‡6òÅéœÔ=æ©v Þ²Â#ÆCðe‰÷_8¼/qAbŸw‡È!Ûý±¢þHr#Î(È»ˆâ„¢ð¸Òã ÇSPîK€ÃʦýLqL©?’ÌÁ|Ï÷(]øŒ]¿Äë-ëvþŽ ˜0 FŽâBäïaSï§Ü9w?ƒ¹í7lÚº…ûîyŸ€¤98}Åú£'ÆçrØgñ7kÓÆÙÍæ—<<笵œrâZ¤òtŽïrnï,Ö Nòj¦ÀÖÑEz¯2rÒwEï}ùÍòvœœàóZœ0Äa82§$S¼xÌgO_àEp1cš^1ax\ƒ¨súÃV!Ì#ØHy<À "‚§@ð¥â“V^‚àDÚ(ð О1¶Çì¢âF–šÜ)‹¶dÊvúnˆ8¼÷ܳáÇœqÁ˜dê;ŠN#'}”¥0eð"­ ´’’"©­(* ::^°œ‚÷Žß÷EáñNˆN@|q€¬'ÏI=ÓÒ6©·£ŠCfZÅóµy@2ÅÌò’]EIÛÇäcˆìO„l:®ðq»ïO?–ÊŠï-’}€Ù4Â0O2Ùñ$M` êP…DÄ–Å—p`_ˆHöÞ±ñÑG(Š0×ßó0Ókf°Ôú‚ýhdb„]QÏ|Ë/¬ºîOo´{¹»Ùð ïÛw|Ü™ûîÑð£À3S“Àäè5†4™¢N¦d“šÒd$Nš³L/¾HJ:ªŠ&ÅÔxô±Çñ>+ŸAi_]6‹íOnG5¡)‘b$î;B¤ eyZ9ã©Všå¼èCa+?Ñ„ðK#=rTOÀZÅ•I"““)ÚdŠiÒRšLÑ&•4Ù0œÒ˜–)&4긨¹yó“xçÇÊ/–1^صc÷’j¼ŽmÑH¦Ädn0ì¯~’'¦6²qåfï^ùÊ+SÅä?„^©û:¤ÃX-‰)4S¦D™RÕ©:Å©ÓTŠq*‘¦’Æéu M ScËÖ­ˆw9„>…ÃÊß Î9voÛƒEÅb¢Ñ(4‰ {Ø==ÏìôV¶LÞË=½7_þ¦þêræ‹1¤×1–˜"1L™Z˜ҠS© S1¦©u*¦8SZ­Ig– FÒLÿm[·ãœk#Ào.N@r–¹{÷,))1h1‘“Òê]ì˜ÙËìÔ^öNíd×ä½rwõ†W¿~öYÝ™/UçÞrDAfˆL£LcL™N‰éâ´†8cœ1M«Æéؤ%ÄI!±}û®q½@ºHÔ2As³s¤”Ф­Y)IU4E¶³mf»§÷²{ZSšêïLþ |¯óÚ—¿6Ø[ýy¿ÎýÖá£@« "H ©k\éaˆ¡!©’4-QO“²wnçý8öŠH›}ŠÀülŸîD.”˜)$³à#;ÙÞÝÅÎnŸ>q±ý¹†[Ã-¼ê’WpÃ7¿¾Þ}Ä¡ïÓÏʽ€C#Ú.Ò¨aaXB‰M 6#©IK.²wÏ^œ¸±—?¢ÄüÞª‰dŠši‘íla»ò³Ô‘ØD,a.òÍmßàåç_Ìšå«×»??4&8‰à¹…Üd `†u6‘¦‰Ô!0Œ5îsiÿ1N ôoÉ£Ë t˜#XÝ” O²‰¡Õ„~ †ýš0 Ä:¢sÊ×~ú5.~ñ¹œtֻܳ?8xZ,(M“skM¡iÐ š¦FKef0ÅÚkV,4E-gf)ÇwK¨)©:£¿i"Y;ÓI³yŽqÆÖÛ·±ýÓ;t÷æÝôÒôša ©RÈyBj©IȾºñF^ðâ³yöÊ5ëÝ;„Ð÷ Xè4P÷kB7Ê\žSž½–÷Ï~€ßùàUÍñÝ ËÞ}üè9¶‹oágãÚ¾տQ²„ÚV‡I´áðh­ºç쯞|éÙ>Ÿ!}æ‡} Р†ƒšºßÐÔrø•Üpÿ7xÅó/…¬worèì2q5Ðo;E@=H4uÈÖ‘ï#êÄ ^ý»/q«®œy]÷¤ üÀá½Ã¹Š.:RQXEéK -ð¾Äã|.†¦ìb–u–£¢5ÔˆÒgPÖì:k;g>Öcí̳¹^oe¸·& #M„z4"¡Ž4ýˆ*ø>|ýŽ›xÙ©‘æâz÷‡ÞøÔ Œ–ÃXȳo¹1ÂèA$°¡ã+fçkö<ü½N0ýªÕt›Š2y:3%ס ¤G— Vp+YÁ2z,§¢KE‡’×F^Åj Cúô™c–YæÈ5Ú.«Ùô·{¹;l`vÓ<: 4-ša 6 4‘476€oßúÎ=åØœ®w;ôæýƒ°`Ò*Ýo¿­òk êˆu•m{f){%Í#Ê`k [u©Ê’N¯GÕ)(«E§¢¬¶â)©¨èÒc‚.¾-9{Œ€¢D"!úô0$P“R¢i! ud~0Gš¯izPS7 M¿f8h¨Mfél7°˜öÂ7ßÅs_t:ý]õz÷|‡nøŸ †AW¶¦0Ÿ÷HÛ%2»w Ù;lp]¡èz\åð]GÕ­ð×qô:%EURt®ttª ßqˆäˆà(ñTE1Áİd¨kPÑòhòzBEëHSqØ M"%ÕŠº¢Š.V”.!V⼇Žá—eÿl«”=ý9~ù²ËøÆ¿Þ´ÞêÐG–‚P`™:jø´>€’Ü*ómnµ “ é û9\vÀU U6)ÀµJÛgaç bšß;õ¸$Hœ9$:\ôK_ƒÇG‡4:¡G7xu¸Â#1·ì]åq=²¯™È»K6Íná ¿ùë|ñºYïVºBwë§–ú€ÀB7ˆÌ‚Å¥1èdçÞÖHÁ·ŸMç—k†HrmñSò±& ‰’åu‚SÉ•&$åsE’ Q ºñ{ÚÏA°h¨.Dš(HyÁÕ‚ë;d ¸ÚAáÔ¦ä ~´íG\þî_eÃWîúG·ÆdOÚ5…S—ã…•Z[¢eBË’q-_A‚´^ð–•ÈyŒË ø<»Dƒ!Ö–ÈÌåÒP\ÌÇ ¹\$Iä°(¸$X,H¦a©‹£áÁú ÖµýlÆæGéµWEY‘4R¥ §rÒ˜¡ŽØ¨À3 Ô-¦‹šmSÃÚÏH2ˆ+I Þ“•iZ0EPÉ jbÖö-2VÚš¬¤™ ‘|=3hA´U¾X~(0Üd H?›øœä{;LŒîñ]ž·æ,>óÏ0ÜTÿµýãònÎQCÄ2Ý­Û†ÃÔŽöO¢  Î SpÎ JF½eцV—·ßØâȸ+”ém Ö’È3ò{1 :$Y>.J^ ðC` Ð éƒÅ¬C»¢Sµ:®ÃÙkÏbý_¬g¸­^§A¯f‘d¢ËEK/¸®@7m}ôôÒî'—mKJ¡ÀÏ)&8u8/ %°”kƒÙ8<¢ P4ÓdˆºÌœ$ZSPAÔg'ÝÄ­jCÁêE³Ÿïü˜q£•egEÅy§Ç§>øiO×i©ò`8ßПÛZX¶û6 ËÂî‘­[“p‚—²ç—Ô:8G¶ÿ¬2¨›€XžyQ@4-åÕç]ö/C4 ¾:©È3Þ€ ×dÈ;\s–m»0óžsÏx ÿü¡b~Óü~•0ÙYź?»–}ác”ËJ¤dÄ‚6¼!y+†ïäØ_”_:œ|ápÎåV:‚smm`´ÐÕEްu€DiMlÁËö,§lÞ¨÷˜Ý»‡}”2z¤d˜ý…ÐîUÕ`nÂsþÏŸÇç>|=;º{ö¯ü€UËW?þÞ+®|xÓÃMÙmwr/Ú(!#ÿàôñw£Wi=okï2jÿ-2Ikÿ[ð‹>ŒìhÓ¤i¨5súÙ3Ö‡4¥”MöÙžJn£…bHOxÙ ~‘Ï]s=;7îZ§Ã§V>Ÿ; ºõÈ*«3ï_‘·µŽ€“6Ú€‘Σï-µ¨µ`éž¡¹Ù«âÊŸ“Ýþ¡Ît—Žë.Tš]›kŒpáó.äKý2[îÛºî¸Ë{W[»Ì×F™ßYóšó^Ã/û5Þùæw Ýá#ç\»Áj€Ü–E´¿X À8ìfê’Z/^Î9âm°MvÿÄã9óÄ3r‰,ý˜m#Ø„qÉ‹.æ‹þ2[îݺîøßè]M^Åç¼Å/8ÇÅÝíÃÜâ¹ÈŒE×/H%øžcûìÍX]/‚ïùìƒÍz>ǰ®rÉ‹.á†ÞÈæ{ž\·òm½Ò~±ŽPÆ£|ϱõ {v]@HàJ×*-m›Í/ÄR9ÿ…çó•kÿG~øèº•¿=qÐÊÃ3€Ö\¤¿Â³åº=H$gúäu‰‚[ÖÎ¸ÉØéÅ2rÙK/囟¸‰Çî||ÝÊ+My8J>à°e4ó¸®có_î†Þ¢ª4@„XFèæã¨Á¼‘ÊÄ%ç^·>vodݪß_võ:ÍO%Çq‚t¿Ü±é½»rÒ•rº ­Û @ Ò“¼YBŒè{ÿù‘›¹ÿû¬›üÃeW[zêûHŽ yFýñžMWí„ ²ÆMÐ~@'›ˆt  —^p)·ÿÕÜÿýÖá8dÚ/–§!¯&9αé;óR\É©öâÈ ä‚Kèa¢áü¾”|ü‡ÜùÝ»> \}¤<­ä[VÞOyóŽ…Ÿæ5£ƒ!6„fªæ‚Ó.à®÷làÎïmø,ð{GcãÔÓÚ On™àgZåïþ%HºÏHl·Ú[¹ùª[GÊ¿}q ~¤õ¿/í2\Oð«=¿qGþ>’CÝÜSŒy âåÊ×òŽSßÅÆ»6~x;°ÿdê0äi2o¸eÂoØq¨'ïúö-ߺåu·]þ5àÚñ·‹ 5GôdªOÿ/µž 2êbûLðËÿp¬àXËäÃlœÜcù×IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/reload.png000066400000000000000000000142061217176075400240460ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞMIDATxœÍ›y´]W}ß?¿½Ï¹ãô4Xƒ%[žd[ƒqCÀÆÔP Ö2CiCi“”!kA†•Ú`9Ì´4 .-3qƒ‹„ñ¤ØB’I–e=é zw8g¿þ±Ï}ïYïÙRƒ²ßú­}Þ¹çÞ{~ßóÝ¿q_QU~Ýñþç ™+`«Ù0€‘tÈÜõ¹…ÏÝ ÿ8Íì‰?»,Éžó¼Kþ:«5ÿû?xßp—[È d•<0ñäu0Oú¿ÆP… Ë[éÿÜ>¾XX}ʺßxé%ÏþÀgC|jïù¸à#œ:o9'he‹Ëp¹õ~Ì›ßüfþÓ_|pséøÂS Âq ïaݼv#,k¥§ÝÌJ.pÚ©k9qý)üÑ>ć>ðžÍ½þSÂQVà?Ý"À‰ÃðŠ pÃ.(|²!ó‡ñPÃÁô>>ð'ïCËþæ|ôSäC¼Cüuîã¸0E€•CðÛ§ÂOw/A4ŒG»“Ä”?yï¿CÔmþø_}ž¬Å[áɃpÜÀXцKÖÁ­ûÀÅ9ïa#ÔL t'Љ!`fñw¿Pt7_ý©k9µ%oÝÕÕ'Âq³G`¬ ¬†‘Ômr‘Í êâ ÝI|g’Ф<|þ£ñþw¾‘w^ù»›»=¾pÚsó'¥ËqgÀüá#ŒÖáìpÿ$„™B]¾3†Hˆ4âbLLxÛåHé6áÆëX÷·ÃoÝý¦ÃqÙµ™xˆ}ÈCΆrÛn¼éoºÃ?+ ÐÎaýØ?…BMóÒ—µË™ƒ¨ 1&¥Ag£FÌáƒüÁ¿z&1¸+¾ü?N»+;ŸÔؾÒJQlŸ¹—Ý£ 1¼|Õª_}ÓÇÿsm|ÇmdV0F1¢+sÇR[F4ýo@PËÒ''Ñt󪚞h5G…•”PÍÎy#'pÒ)ëèíº_BPbˆIy¨& bŒ˜éƒ¼ãåg\qÅW¾r;ù´½Òý×Oûƒ5¢R_ȶ„’óŠÖÎ;m–= ¢§zF•óŽMQ8'hrÞao´R^D•1#ÄôØC$z%„Hôï"Á+®œ¤Ø¹•X8Ô^S¼„Љ ™:Èæß^÷îŠo\7·gWö?çã3?¹A[ð N5sl«nлéŒ@5€Dd ¸("±1±zò!Í&¦×ˆˆ(`@Ìcù®Ô'`c‰†Jñ”ö.à]:BL–ÑyÔEÔ%B)]ÄûÇڃĄC¼áâ•8·áŠënØÎéïY}åŽÿ²/Ž|v~Nú8420Zâ»S¸™Ch @z¢"•Ò6¦ea#*lDM¥´T³1éãÅÌ.‚´t€P"¡@BÞCPÔ)ÆGì@ñ ¨‹ˆˆ‹PFpé\,\f0™:Èå篢(Nºâç×=Êygœråôï/ –PÏ Ã㺓¸Î$B¡RÞf›)j’âØˆ1¬Î^ƒ± 9˜ äT«eà! Äa||> A1^1!".¢>)\Äø˜BÅR¡H ”E¤t烠ÈÔA^½iáöeWlýÔ,’{è}Ú9*¬zÊî®3Iô¾ZеÍ"š)YV-;„˜ˆX¦žÎ©&W –ê b 2wNƒb(Qí£Ã‡€DE‚BÉF¸ˆqšØà4±Á+®PJ§É«(DÒqïáxÉÆixö·}úžý¼ÿxTXEgõ%`­¢6¢6B1yÄd)T!ÐF•ÍdÌK­ IDªÃX1ES j±¦ÄÒ#Ó’RuÖ¦ªhrµ¼k%¹ã ÊÎUߪBT%3†é²ÆøäÃÝÎîæcZ†@Ù™¢8;¥w8ÐlÔ©7´òÈH²ÖäcÐ\ õQ¨/úH@òæ¦b‚È<ƒè ”úàºPv*™?‡‡á`N]!t¡Šƒ&GQxèg©Ê”4Ã’5g±{>câ5;?­ß{Î×6Év·¯/Ÿ8¨[0)Ë!ô°&€*"ɸ4¬0’GFÇšŒ 7é÷†)ÜCKG0õ!$o!y òbsÄZÄfóÊÂU05XÓ( ¨ µ 4­bˆ‰ý†z6Ì許Ôä#tçB2M±TÐäI}ݲlÝÙìÛ½¿sã³Æ_³óãú½Ó¾°ZV-G†‹0À&¦R=(#HuMuºviç`×^À=[sv~ãËû.~‰}pdcQò*?ÈŒ"Æ‚­\¡ÌKb¥B ¨Ffãys¯W†]<}õêó/X?zòʤ)JM0¬½& ®àë†öš<ðÀ#ï\|àòm¡×ì|ë¾Ç­›?!Hºgk’ø”ªåJ½ÑbfªÃrsïCíߊ×mÜ+¡ºV!¯Œ?*BeôæÝGE‰‰>aQyÔÁ„´W·îzZ¾ÿÀíœý’ïgßWÒRG)†B¡…`VmdÇv¿sé¡×ÝþÇz}ëZ›Ó3¬±+X5¶œ_õ·Çý¯ë‡'`ÐpJySÉ á©eЬY¨"Î1ÔÛµct {C¥[=@3¨‘Þ|$É‘hõZœõ’HÂÍK—2e—˜‚ÚhN«¬(‡ø‚L&ÉrK£fè57°}×þîí—/yËýønó[²ÔT)i‡ ЃǦ„‹1@+D‘yH¦•ƒ­7¡6Š¥f5ÔTŸ"n^;Ê ç¬£?ÜäÜ}“¼ôž½ŒÌ”×þ¿ª¹IMÆä¹ÐZ–”÷E%}bæ¨)P?“»öõî|íªwø­Õ?´÷þâ$©ÂY&ƒÑÔ{b2CÏJ„™Á‡ØŠuu“AmêÃØ í†eÆd;øÎKùËçŸE½U§ÕhpÇÉ+¸~ãZ^ºía.»÷F:eŠXÚ¢Çð"·U\DºyÍ,4–Î*ŽïCÙÁ5‡ëkØþÐdÛkOùÃCç¯üi6>qr$&›;>4(Å} oé[á BGª§`+© ØZ#a)ûYÆ´XK™Á—Ï^‰ÑÈÒNv¾ìîo`]þµÉVÝñY§ñMkyýmñâ{FÌBÖ¡nSŸqî%æ4FÁw+79­1&ë˹oßbïïžÿÁ‰M­›Í¡ëU•Hœ+÷–dª:sT2ÃŒ1è"Uµ'³’›Zò6Fé“Ù¤Áõ' ³m´Á c.9ë¦S¯»uë£í?;ù¼,Æ;²"2ÕÈù«çmàÁ¥-Þñ“s77ÿ»óöÈΈج–⋲ù4´–â}ζÝ[‹Ý/~áǦwQܵ>Å8›ôÉ\ªÔTuâX˜0"‡úƒî®ÈD±¶VEv-ÈšBAÖš)kM¾tò1—Œ…¿½,,•ç¡BCCº#mçùúÙ«‰QyçßïH®P“14µ’5æqa0L ¤êCP´¡½WöØÓ—'~é’OpæšÖP¬×˜ªCA«t8…ó>M몺ïX(Œ0Aµ^„dÐ- 6OÝ@|ÑÇÔg¾³ªÅí­pÉzûöËN|ÕØ…ozû÷OsG÷V­Q‡jô_;{%#›o¹Ÿ¨BKÛH½]•˵ԇ¡½‚0ý03?þo=C½y×9›ä¼^ÿ…¾ž)„ˆZyºVШãðQ°B)Â$PÈ€€S[¯¤˜zYo<úùåá¢1³ä[—þò±áö3LƒBðž`šþf/òõSÆøþŠb„·oïòÒ3©Òzä“ :±›bëG;ÙÔ¡Ë·¾âì§3ó¦ÊU^}?„T"óÁ‚&ÅU<UmŨ#GÀ}#L¨RPLEN“âx[‰ÉAšîºa÷ôÝÃË>ô;g>g©E&8È(K(b‘J\Žü BÓõ Œácç,ALÆKîïUAȼ‹ë 9tÏ}ìßùIÎXþ‹Nsjüò{Ö¶¯ÿÙ+È{Åh¨…Õ!†nžàÎ;b*ÌVሠQÛ=6ÀT7X@ÉbãAîYïݘ:ókÛo~þ™7ºÃ3LbiÑä0Ó”¡H5½#!57Œ1dQ1‰ÖðñMCldüÞÎ"ÕVw–ÑÙ¿·VÖN›Ê2·ûr ×_wΦ3Áöü(Q×ï;Þ{BHhˆsµÛ*BÓ ÃøcÀ%èTÕ}š ÖTæ¢9ÛîÞ0yë¦÷Ë]ozúÙÏnLeãäýœ¬‘1-ÓL1I ‚÷x3GëX*3ï"Øb”ÏnhpçÒŒ7î*8ç` Ê“ÆO¹pì%Vîœf¦sïŽåM¶ž2FÖ+pÞ/ !¬ ÁÏ8ïðÎQ:G AЪð¬ F,9*’0ŸÍ•ñgËV˜Z÷{ÅösÿXv¿cÓ† ›u/µ~¶iÓÏúLå 3B?ôð. ÖÏ*`­=ò+«0 Ú^¹iYÆ-K-Ï÷¼þ’óun¢ãˆÆò7›V1e å>ø%>øÎûï<Î;JW& è©«?FLj”ìS;NALç»ýÝüûz÷Ýg®=·µÏ?HÞÏ1ÖP–%6³ÌØÃL˜qŠÐ'„€TÝY\ù#F3¤ùgË3~>&\4îyÁ#Žqš|Å)l®ÑìöpFpÎgÞ{œsõÒ9\é(Ê|*L˜ë[X•Ãÿ§ð¢÷4Ûï[»êôöÝû¨ÅCfˆ¢(°Ö&1–‰æØÁõKU£HvlÊÏÞÐ JŒðË,?^*Í0.Rwž²ã…^Þ5…+hø W”ÎQ”Eª"{A}*4!@½ᨤÊût DS&;åð7 ñµÇþtÙª5C;ßC£ÑÀC™•³Êcjµn² ÿËÎIùºú͵›mш¨$[R™gUMµ»ÊìÏ/X()¤­‡HçÚaA”Ðñ¾{ÛÔÊ“O?㢥«—Ñ)')Š’²((Ê’èH ÆR $ùq•_{b§ÊŒ‡h#´aúK}}î_Ž­øèز•ÃÛÝI­•“™lVyc̬òdEƳ{²g× _¼ký}ʆŒUƒµÙìõV 2ÿ}¥µêþ¢©´M$J¢cÐ@$b‡vo_ròĪÑÕ/8;ï¡,Kв (êu¤P®HhCÓ¹£¯J7*±©L}©/ûÌèŠ-ˆNþÕÃÛ`$â3Oßö1ÖÅáE¿Ä—Ž^¿OY„DõÞJˆ~^Ç8\À9O(- ‘X@ì)¡šµ )ßí&ÄW õÇÈ€MÏÌ^W­¿ö¹—œÛêÓÃ{?KmU…~²Ö‰úE1é5è ‰:‰ùÔ0šS^Q“öD£¨¤.óÕX5:•”èAƒ Á !¢A‘hª- ƒÞaõÄg@;ižu¦Š úÇÀý3fÅéf¨]³ΔˆHRN$«(H_ÑjÕKªí:ß³n.µ±¤jŠ5ˆUÔ¤²±XPbu¶š“Ôœ×9“‘ HÙ7u@u6ÙIq?‰3,TöqlÀ‚ü³óå—ì½ã]ßûæ Ëy­6ÛÏLYQºé̓öA]ò»ZH¢g0ƒöÓÿZ®q)PQW½o ^’Åö€(;k‰U~æÂôù 6©YmÒ8GàG·è– âÞõݯÝÀ¨&ÏóÄ$‘ª±+ˆ¤›„.³³II)) ¥A«Y¼ogÀYÄ$io‘`gÿ7ÁVt7ˆDmš+ÚˆV̤:¶‚i Ò$—ÊSUÌ9V~ñã‰-ë&Æßõƒoýˆ¥µ±y TµöùLè Àè}ÐÒ&) Ú·¨7©¥ë“¨7•¢e-D[m3³•¢6u–c†hŽÑ £#"©jUBu½µHË"m‹i§Yj%pL6à‹ÿútÙü™zÇݺåü§ ?øö®~ñ«žÇÇ{C”˜˜0° AP/ˆÔ ¦!´Úm²Ü¢•' S4¯¶ bµÛD%Ã9ïRy…Ó®±R8œ%¯à³@°‘h5áVShWë¼”‰…ô ë—ŸÄ䯦𽅛ª Føàï*zí.½ý.Ýrá9Âþî'W¿è•Ïew?Á‡Ä€Á_Lt/h)„}SÚZzáÓåªGÖœ|õ _y t!¸PÅîi‡V¬6,Fxã9kÍéì™zè#?zð_ªÕh’%E¥ª°Ê|¥F¶³·täμ0ORÊ«ºêI|™ï’»i¾þºôŒ®¿I·¬{dçUÿí›9qd ’U sv!«üy´aÄqàØk"¿±±¨üÈí ÷ÕÏ?½]¯‘•BSdËù/¿€=Ó{RRý‘WN7y1¯€v- ›?Çq<éíòº?`ŒÙrîËÎc÷Ôn¤eQKIHì¥=Qé àï&p*sÅÊã<~­ß è~½F– Ví–§½|SA@ò*¬íù¼ëÜ-$ÎdÑÅozüÚ?˜Ðq½FFõlÙøª³ÙSìE2™[µ#Þ¡ü)ÔØMwž’_Œ˜×Üù“»‘-g¿á,öš½D¯h¯r]GŽÅ¡!?oñ$å75žDÀ4¹æŽÞ…ªnyÆ/dÛþ{)E‰ ßäÏ`ÑjÍob<µ?DnpÍß¿ûªöm#\uùU0ƒjå H‘Räâ›à~ÆqûõÒSÿµ–k¶Þxãt{¸}.ʶÅjñÊë!ÛHÚ"ü8[þ©Æÿà?k”MÌ,£IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/remove.png000066400000000000000000000043571217176075400241030ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ¶IDATxœíš;¬$G†¿sªzîc×^‹‡lÞâ!$– 9D"CC "#…˜B$È  eYæa ³ì.w÷Þ™îªóTõÌÜÝkhaæHsçvuUõ©ÿ<þSÕc?|ûSÌbÉ9»; ™À3ÀÔîHîXoÿw¢>ÖQ›Ó ·ùŽõïùóŸHx¡Nâø-O0Ü8æ?úù¥^þÎþª‘K+°´XZ¥åÀÒ ,-–V`i9°´KË€¥XZ,­ÀÒr`i––K+°´XZÿš¼ÂùjŽØµºV©Ïç¿ÿó"CÔ¨ÜÊÔØ^€Û·%¯"Ö€„YŸˆ~v#õ1šoŠ]vónežg¾ì§ï³‰}ô+‹_Õf]B"„i=ëØðÙK¼é™÷><ÓgÖwÖ<÷ÓçHë(¸yïƒ9UA2ßúÈ„HÔvÎo†c—u2ì÷{bnðÌJÁàLˆM)}ó$sïˋו‹÷-F†H)øÐ¯Ì‹ßüð×ß½´7[PC|ðKŸdºw†1%¦õD20©YQÂLHí).uWع˜iÚ`º}$œAŶÞóL ¦¬kp²xÏÛnQCTiç*Èmæ H{ÿïcS§€•“¨\ûèû‘ÎyþëßáÉ/|õTù¥çÿ¾½ p¦/‹÷}þc” «[7Y=ñZl•©S q„Z¨SE›•]l(ë¦BLÆŠJ¡n Tµ„éö5`]á|ª¬KpVÅËQ¹§à,*“êu¬Þüî×`0Ç ,c˜·wOæ 3C¶¦v»fdMÂÆ ?{ÇG8¿àÉáûDЬ{¿ Üÿý_(/ßi)";Ãé vã?Z¡RÐTˆ±B™ÐX J” E(Š ‘ÍPóuᢊ©T6ç5â(d™gÿt›_<÷›qœŒ#ƒ‰csŽÜX™“»Ç'KÞù HÓ7ÜD$&8T —}&”(aÈq÷ÓßÎ ÷Ö^ÏÚ„G;^á'C{÷V…Š  j@ ¢ P©Xió®k ¯q ÆR™$ÎBl˜9ƒŒ8+/¯G&‰³nYëþn 2§&ãB{Ë-9Vëî£õ0”8‘¸=®8+&漉ú³Ì ­ :/Û $xPAk0#gì$Cv(J·zÕ„S .J0†cÀÁ8ÇlT NÍI×»õ1®[âÈ1§”¶VÌðì}1FrHæ{iQ 9ñ x4Wy?§î“ަ¾˜ÞàØÞ‹[£” îŽpw$ Vƒ5Ô«°*¨°©ÁºV&“œ1êvñÂ(rD1FÔXÅà1§æ\Ã8õDF f˜;ÉÚÛäd0äԮݱ™xæ¤Ùßf{n wºªÚo ™Z""Rìwhf ð-ç'bø¦ek¹À…%X—`SƒQ°‘Qç!.º)61ó½m“{<æÆã朘qlÎ aÞ9[yHÖèÙíš7ëÈènÜb bL²Çí°ÍZ,¶LÞÝÞ.u€hÛr½g§F0–Ä$Q¨ÍaÌ#(Ày2cŒÚŽƒu81qÃ''ÝÒÙl"ƒ7WϽ®µù˜\2Ì|Îç¤~oT°¹¢€º €Ô×Û›Ùи?xÍvC›*b”QL%Æp*à&6*¬Õʘ- …m Àãn\÷DêS6‘dsVn¹c©RæÞ\Ç€ä  ÃZ?ƒ”ŒsçW•¡˨TÚà:™ J襯QgO b Ä$˜heòÁ„³Qð Š;nΩ‰avÍ>Oí–¹æ™S뉎À-áÀÊ•ƒ·P‘iWíjé>Ÿ¶5fx¯ÎB<¸ €z)_¶lŸã(ÎÂp»¼a Jÿ„úw_l‹šh.§à¾‚» JTŽüé§9{îEþ>BÝ´_‹m÷"{ƒs=w{ÃÆçæFÆ™$ªõ4?øþ/à©÷=±» !‚Ów¾•Ÿ|÷W›ãûá6çž¼­»¯(µú¸UJ±Û k©).ë›1(Q…@ÛLó#A`"ÔúĤè &5ï;6cõ¾øµÏñîß¼ðˆnö½w=ùpÛ·§µêK÷êú4'md»<3+c¶6ré\-±·+ÝÃãap„:÷ïØî×=ÙînÉ¶Õ £æ#£Ð¨µvÀ[:6‰‹˜ìÍ7?¾(‘¾òâó—Ïök{ûlvᎳ¦é̱ÞÑ÷­zí®Xè¿Û±Ø,û`ìw4Œ,11Wº¶í•€èeï|Ï.Ã] r†œ˜êUGb{ÇTó6Ò:w¾de»M~HþN…_A,­ÀÒr`i––K+°´XZ¥åÀÒ ,-–V`i9°´KË€¥XZ,­ÀÒr`i––g}{~úØ@IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/report.png000066400000000000000000000234511217176075400241150ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËgAMAÙܲÚ IDATxœíyœ$Guç¿‘G]Gß=ÓÝÓshÍŒfF÷èBi6IÛH€m [k¼ëë³¶±×»°^ï¯ÁÆ Œ§%aI–GÒ c¤¹¯îé9ú¾»ºÎÌŒý#+«²º«««º«Z-ÜïóÉOfFFÅù‹÷^¼x«ôš„ó0~÷– uªÿ~Ú:n¦c=E0ƒ±±gÌÑ‘W}_zöÛ€Ì^«ôSB`âí›7FB/qç=QvìÝš4 Rixø¯™<{öCѯüøaÀÊ^«@ø) Pü ‘‡¹å¶(k; 6 C=0pÆ.€bÁû~…H׺Ïõýµ¿x÷X¥7.)€*ë¢ MÍ0=C½09 ± 3`&à—îgMW×gÏÝ}ÍYÁO ©€çwoÞyŸ©[Gl ¤ È,“—`š™†íÛ X⎟ý㿼¢¾¾þéçž{.ɪ(xC“ xïÚKîó¨J'ñ8†-û‘6$öÝ0°ü!Ư{ýƒC›¯¼òÊÛƒÁà·žþùD6­U ¼I+d2LA,cãös*mß“iRøj¹–S=çc|||ç;ßùÎ'î½÷Þ6@˦µJo0Rßï^~Ÿ·µµËéXVžH˜Ñ기îf ÍH)'‹µÜ~ûí·éºþí_|1Áê4ñ G*àý¹àx¦ÃˆÝÉš.0,È8`˜ð„xµù*:7n& áõzH$d2„-{öì¹-‹}çèÑ£qVAð†"ð~þ¢yñOlz‰›iéÓ„ŒÁ°©ñïuÛX»i+ªª"„ÀçóQWW‡ªª9N°oß¾ÛEùÎK/½´ ‚7©€x¿ÔožßnM$v¨‰½´tЗ|]¶Ñºi+ªîAA:frr’††|>ç@ËÞ½{o›œœ\åo R³—x².n4Çãõºrõ_û·Ó¼iŠ®#„ ÓßßO[[ªªå“““-oyË[nÓ4m•¼AÈ1æ(ÙgõÛÃò™õWßÞÔº&èÈûX,Fww7›7oFÓ4R©SSSE9¢(-×_ýmBˆU¼ÈmÍ“Ùg‘N§»=ÏÍÁ`PÅb:tˆ={ö iÚNƒhš–›–ëv×ïýÜßãkä× VA°IÍޥ듉DâD"‘¸éøñãú7Þˆ®ëœ@UU¤”Œ‰Dðûýøý~¶oí¤ÃøßÝ~tÓ§¾Ê㬂`ÅÒl8%&''§OìØ±ãÆúúú9œÀ4MÎ;GSS‡`0ˆªªÔ‡U"Ê Dè üÚÐŽ‡ÞvfÓ§¾Ê÷€¬y•V©®ç9#4“ÉL'“É“‰Dâ7'0 ƒ£GÒÙÙ‰ÏçCA*•"6ú#ÖÔý/„Øe'¾Ÿ:¸ã¡;º7~ê+|ÕeäGj‘°‚Nšœœœ8¹cÇŽëëëëu˲8pà[·n¥®®€T*Åø¹gØ>ùTïkàq­@èz|êÐÎ,gU¬(š éºç:*“ÉL&“É“Àõ¯¼òŠ~ùå—‰DH§ÓÌô?ËMÞ?@g&oø‡@\c§ºŸ:¸ó¡;º7­‚`eQ1y}À¹˜œœœ¼páÂÉ7^ßÞÞ®;ÓÁØùŸðö¦OðÅó¿ž<=² _çp‚U¬ šP™LfÒ0Œ“º®_¯išÎÄî|™øP’`Ôö"s~)'@xfs‚½ø´áU¬ *˜‡ÌÌÌœÜÒ»üÝO|j iÁÄ6tW:  ‚@ÚùÐÛ{VA°h!À< ˜>wà=7˜WýD€'á9 !WÛÉ…öâS‡WA°h!'§ó3@˜Æ€Ñ}œ¿ã¿ó“IÎ{à Øá$g\¿d0¼¬ÿk#Eš°öA¢]o¾wüQ>x±×# | ÷ïß=vìØ-û÷ïV£²‡Þó /ì©FZû÷ï_ìØ±[ª‘@¶žë«•^µIu€.àràg¶­å¾îÏÒ;òyäÅ¿Dvyê‘ñFZ^ò(Rß"åÈ#RŽ|CÊ‘oIyèÍrüQþ ¨Ã^™TñÔSOm<{öì¸eYrbbbüÉ'Ÿ¼ŠÅ{‰ƒ~1•JÉT*%:ô—Ù¼ãØ*~øÃ¾sttTZ–%~úÓŸn^dZ<úè£õ‡>hš¦œšš’¸‹|=kît[ncã£ÀÈñ>Îßñ§üש4çN zàâq'È’Õ rø…m4aÍLjvÝêæ* vvv¾?“ÉDc±Š¢D/¹ä’?"Ï)*xúé§7û’É$Éd’5kÖ<ˆ æÅ€@©¯¯hbb‚X,F0Ü}óÍ7;žÒ•–MéêêzW Ø‹ÅX»víºÊVs7»J2˜OŒ¿¸0¤#r ø ó€ÀègÏžU{{{ x½^Òét#¤r—tEÓ´M/¼ð>Ÿ`0脇Ȯܴ ?~\d2Š¢033Ópq°rËfšæÆðù|X–u67tÊVSTš¸Äîµ À¥”‚\"Ý ‡¿ò³¶> MXóQñy 888¨K)QÅñ9Ðৈ¾PªŽ†ahÉdUUQ”\•£vZYiÚøø¸*„@Qt]'û)T9$Õ²,5Nçê™­k»ž:5‹E—à À4 €àÂqHÁP8 x€èº[î~”¿™žžöf}B`†F¾‘ËeµPâñ¸–L&ÂnËì=Lå,-•J )%‰„ÂQ[NzPMÓTS©Ô|e«¹·õR·ƒ2@ yà‰Y 'øÈ¿ÆmÐÔuË]oíúÂýÉd2=N;JhÅ" ‘H¨ñxÞRiYØ£ßCe,[ÊÌÌŒ’uƒ {(”Ûå@I&“e3 Ã]¶šï¾Z*º׌ßÊào°¥‹mfËúpèÍ_l7ôt:-¨\i€˜™™Q% p|ΪTÛVâñ8ét)%RJ‰„ãVW©ÌVâñ¸H$¹€t: ùÎ_ñ€JAp2Ï Xg@eAàèm&âƒS÷cYÉdRoŒJEÌÌ̈D"eY˜œ4Üi–Mñx\dÓÀ4M²œÊN¹€x<.’Éd®lÙ´`Öœª•Iù Ð᩹Æ"«äÐÏÙÉIZ?©³ˆÓ •J9yUÜaét˲0MÓÓÒ*kYd2,ËÂ0 §l‹©©T )e®|nn°Ø4+¡j¢¬"\<5W1Ì@fA€ ­¿†fœcSêÁ‹lg´:¶TH)1 Ó4Éd2KJ/‘H8J.†aÌ@Í©Úl¦2œ„T|Vg@ÿäß’ãm¿Æ¦õmëO~•ßf¬ÛiäD"A<§¯¯oÉM&“ÄãqzzzÜÜ©br—mzzš‰‰‰%—­ª…œ)ºw²âÀÌàïÈMÛ~•Í;nºý·ùy…«,¤ÓiZZZrÍ###Kª ‚¦¦&†††èíí]2Ö®]Ëøø8½½½Ë€ZÊ»£#Iи­ÎÇŸ? {X—ŠC:™´o¶AyåPÝ¢ùàƒäô¢Á¿cäü9èyê‹)Çcy½Þ¢+‰ñx\÷ž9sæšæææ?¼üòËyñÅ9sæ ###¿ÓÖÖ6ÔÙÙ9ÑÖÖoiiI/T¡ééimppÐ?88øÉ;ï¼óÒ£Gòƒü]×÷§ÓéovttŒ¶··O·¶¶&ý~¿Y*­D"¡úzzzîß½{÷]õõõ<óÌ3$“Iúúú~§½½}¨³³sbÍš5ñ†††‚²I)'¶lÙr–¾‚ª-5äæ9:~>sèî/üþmG>áåh.üâ)Xë€yTžE4|ÐúAšïÞk|îÝ#õV²áp˜p8L0dbbÓ4éë룿¿Ÿ}ìcŸtŒ/åRCC H)  säÈÞ÷¾÷ݺmÛ¶[çû]±|<‘H˲…B¤R)zzzðûý<ðÀŸ,£8^f-Ó/†j=Õ˜-Æxá¡#;þüS—}¥q;Þxü¶8è;UDœ9ü,ðrv‚ÖR§ Ð4þŸs–ÂR—”27]›ššbrr²h§ÌGÅÒK¥RÄb1†‡‡1M³dþ¥ÈQ&‰ãããÌÌÌ”U§È½/§Bwþð‹,~UXž¹¦‚TÇžû9­aí;¶6 Ð"L_öOÅA0kv`ž9ôÈ¿ÏÚ ,hýuÚã¿U2s!Ï>†‡‡C×u¼^/ÏûëÊjèÙØcyèŽ%èééÁ4Mššš8¦jÄ¥ìôœ+ŽÊiCåâÅ‹LNN …Rr\÷–¬‚k¶zQüÁ_ôÝø¹½,Áj¸\§zHÀÑÖ}B×ìl¥.‚Ó³fÒ5üð÷äÌÆ-ï§Ní§iü·æmä×>;5ÌÈÈgÏžÅï÷‡ùŸ'ûè‘¶ëR%öß.8×{Ž—_~€ 6ðüÑãÚnïfvì‡[Ÿü&•LÅ¢àýg¹´)Šiš˜¦‰ßï§ã\WM TÄIÞ‰q×ú,Ë"N£gwb¿í[»`ZWoÒ5Ò~ ùeòŠHj©ºI4ÕëY't•- ù…”vº×îÅ;’W ûNÃÚMà™¥ÂQšî$´ÜOpèaý8c^qj±gËF.ߺ©*YßÚÀú·¾uÞï•*¤J®¾úêE•C¨ BW"íÃ@Hc‹Û²i¹8€TÅçí¡ÌR‹ÛõÏh‘-…œàÌ\c‘y ¬¡_Ìû¶ÜOP½8/'(«Êð×3Ÿ«»4„®¢FÖ^A~Y»b=`Ùà½éãB·åÖ•MŵfôêÌo 7€ ÿLñÙ5ô<ˆ g,j¾€¸HÃèoÖ¬ó`éXR„­¨ŠÀfÿ•z#ÙÉT§4 ’¨»ö»„ÇQ\ŠDpÇô‘Üú¨M;æ‚ ÈìÀÁ?’× ÞG@\ ~ä7KæóºwàËvu§‚дHëN —¢W$„%„®²6¼@£J‰ÔÂÄ÷|}.º ÅŒS` ½âKä8AË/ç©™Ë jE¯‹øÐUÐUÔÖQV0 ôÆöË„®²¶N–n)±ÂaÐ#$.d^Hȉƒ<¾LnŠØüKÄ9¢Ãÿ©¼B.W¨f>W¯SšŠ¾õç¶²8ç–e›áñD…¦’™ŒóÊÁÉ¢‘TË`ëP’£G\Ã\|ݾûðs"Ôß mÁëÏG3NÆ (-¬_Ã_fæüoð’ñg¶Ü”ü•{!§‘¥½ì‹”ö™‰¤%mpY -+ž²eÙß\—t~W^ë”þ®qT 6Ë,Dÿº™ßd²å/æ/èœV®ÔË«<ª–.Ò ЃA w• €eÓ„¦ ¸"’ž_¾ Ô´ârO‹¼â›hÍ.ÀÝr­7Jl˜C?ñ•¼ ù½ø9Kdø¡%Ç—’϶&šŠZß²‰¼iE}º\PŸo{·)Ë’­pxþ†Ó#¤®üZóÎÅp ÇAòÒå+ä<‹š~¿ì!<ôË«­×(ŸW 4áñ9 b=`ÙìBUÃ(°ÆgÍ[Yef¦dÉs ¸ê›EAvÎ+Ï’ ‚A|•œ éð[=„½d>Ë1Ê—šÇ¶z‰ÐÔPÓò¿â šüÊz¡Ø2ví<B Äã çŸ&æH‹.åAð5òÃ÷೺ çeWl™DÁ|ò`sMÁ·ëݬP ôÎmëÒÐK¤D”@¡8ˆ’¹ºˆ88[ Îúu”שç£JʰµÑúºÝkY©@±„P`KÐ(]!@ƒ 'X‚o£—Av†–9 æÐK ü394݃nœ!2ô ÕêÏåaŸ@¨ jC—e÷k­`[›Úo"Ÿ[©ŠË`°²Ò#d®)‚œÅ0Ks@€Mw£eN|0kZ¶^­|¶ÕKP”HëæN¤eX[FÉFRòÆ” Hj2×|½¥ƒ½³Ä„Ì 0‡^åëy÷²,ÂC¿^'XîQ^ê y³ ÜÐÊ"fËaRTŸ¿ša0>‘)I‘ƒLÌ >OœÒ½@ly„ºä»p{öBkx\Æ¢Ì €—Q[ó.ÛÂ×øn´Ñ¯|þ†¿"ãøÙJ²–?ç]BQËŸÌϱRE3Ò¬6h×Õ‡ðGZ)´¬ØŒ_ót ç§x¹wjÞÈ›ÏÏ›š¦?]bsD‰j EA×ÿ‘k‚¿Œc¹ðÁ^h]gs‡2'ù2j‹ë.@Bã»QG!Ôÿ1žÕ?Cư×;¿4­¼­ß²Àt¾9Ï®03»>°G[ª2Ùoùj5na"`9 PÕ0ÞzUˆ+Bþy#ûR!2;6±³«u Y6#ŒÇQ_x Ê…ž+”>^±9õ.lÜEdônW>Êt×grþv¬åL Ü|¦3‚Ï>® B-,‚,‹ zm+à‚eJ&ÁãYº|Õ#˜{¿‹ÞrY¡NpÎÖ Üƒ2}Ì¡W@ù¹ÙAã]¨é„ú?†¢Ô^Ž/E_é¡Ú+š¾«îi§BsðrL‡!].= TGFÊÛX_NÃéQ¬ëþ¥8fmæµAp”o‘37¾ 5}œº¾®e¯Ôµ-*ª‚wýån¬ Ðö©¿ Q¨»ÌÛXÙåÓj4*€Ð£ÈëÅÓZ‚¡Ù >æàAP] hx'jêuý)©.ÇŒ T>!ÍôŽ›©ÐPshžp½°%`.\aËOå›5J6¬Á*‚YâÀpƒ5ÝC°ï#󊃲¢†¢ = mOk_]ˆÂ£e,\Í |¾(@H[ØÄ‹”Èææê7ªE^÷Ø‚œ@bscðUP¿Mnßeý>T.>PóQ^) !hHPÔú5©ÐPKØ `´q'ÂÀœ®R¦§Ë^XëôDáú" 8oƒÀ]º<¾“õ'° ¸•8Á‹”•R5¸‚ Ð}uä§‚+ Ò¶˜» Xyjªèœ¹ª¬SÂõÏ ‚qà€@û¹ÙA`7 3.Ø ¨%[¯¤ Ú!@ 5:ËÂ+‡(¾Ðç­PsÖ©Gà†Çñ´î*Áðù"³ƒã` ¾êwÉé](2–ÁB´ i÷Û@Ñ=;†ÔZP„¢Dpe¨ä¶ü…ÊNxIªGÅ@p¡ÈìàC.H‚6ü>\ÒNP±˜ZäÕ°Y—Puoû-ÇE¼,%°––@»º§c·" #B¡ªŽúRiŬ0Æ•áyá¼ä-†Ã ¹<Ù-úH8„Ö˜?k‹ªàe(3¯á;ÿa†>ƒaʼs{ /¥ü FÈÇhõxH Ôº¦p€Z@Qt½C8õl?£%BÚŽ¿JpxŠ3ÿ6`ÿ¸RP[R»EA(Ôì½à9ˆ¾þ_ØmÝ9í »RÇy­0î°A¸ %þ¾Þ_å¹øÿ!± Ö rë²öfãéa@èx6ïÝÌdlI`\ µ$fo}9€âõv\)}ŒÑߟ®Á/;mOýæ§ð¶ížYÊ@û–Œ%öbÐLjü"ÒZ`Ú»˜²•¸:¹„ [@-9€@Õ¹—…:° Ï™åèô›Ÿ, ‚Ù§Â&Aº¿—‘‰NÂ]o"¼f3F*N&6Z}1U .gêÐÝŸº‚2ÍÁµÞàN€µÞ2”;@dÿŠ~9Yg)Nà¹åI¼k A0Úi, Žÿ¾È(ŠŠ7Üˆî ’ëÃr±ŒåpX·]Ð_¸l[@m9@vP·ûJƵɲm¥§ŠE3ªe£êQ<7?UI°ð3ü(õdF/èÆ˜™$ܾËÈ»P15Ïui$[ìÖ-—Pæ¢P-íŠðø¶#‹¯BáœWŒÛï5íKâ ž(Þ[žB<óVè5<:è#ÓvòB/V£È¤°Œ4–‘Æ×ÒE°±øx?™ØžPcj‘§ùêÖ±Nš§Ž2gµ€-ö5,muNP -žP ÙÙùxêñÞúo°ÿ-Ðÿ*RxOßF|ÿ¿â‰¶b¥ãÈlçK#ƒ4Òx[ºB>‡Œ"µæõÙ•<ˆºÖM”y`D͹û÷£N–åTZH™?±c1Ö(zï­O“~úçé_OÆÐ±„ 9p™íxé,2øB Äcã$FÎlÝPQv‹©O؃­hz2—…k€ÀwíØä5_ð(~B)‹Aäxzq›(„ÈW3Ûx¢hXþ9'ßEQ߬’x¢„ßö /?Áð±£½ådº_&uüùûw:ßÊØ¢@ѽ$'ñFšÑýå¯v–WåÂòí¨$(þ† ¼Î:€ cÙ™Æ3øÉÂÿбc0Á‘3œ)wÁ¡Š9‹A(Ù0UdÜ B®øÙC¢ÙgÈïüqo qò܈غƒºÞGñ]¢àéÜNòÕ§IôBfl8œÀÓ܉髣ÿô)Žô¹,5`Xx@†@JÔµ»¢fßkƒ¼€P[.“.k÷ò¶íí¥;ðÌ”®:ºöÍY9®<óeÓBpÍG˜8ŒóÏ—àM÷`öŸ!uì¹Y¢ ÖÒ…¿NáÖk5üõ•Ít*­ÏýÍ HIàŠ»·L÷½vš¬5ãŠP£H{ ¸P%ò\z(|R´óRB­<òÆ„‚gí%¤N¼@¢ïTV,dð´uÛ™:‹7Ô€Zâÿ–J!&¼aç踒3ZqEèþÎ\ÀB ^Áôo%‚Dóúi¿âv¢—Òh?Ê®7#g&Hþ2+¼ŠŠØ¸‡Ø@7‘ÎKkVî ‚g'$zã¦Ù{ŠÎj&„âéDµ ³>ÎÓ°¢½½ª6€åŠ›‚-ë¸ägîcøøï=LÝ›ÞC¦÷0É,70ñŒD ¯!‰Ö¤ a¶žâº·‹ÏëR3X€"í·;#™~ÓèëÑyÕ¤æm×]·ƒCÏ ”]ˆŽ­$=GÏKÏò¢>Ê–¾öíÛ‡®ë 'V!moTøž%Q¼Ag»xÉ™@ÍD€ê îEÚ;‚2ÙÍöΟ-ÏyîîF¦ÓÈì<;᪪ÄŸ}—®¤Rñjßëõ¨êÜÐõ@˜ÎkßAl¨—¡cÏr¡i7öÅGYÓžf:gÍš5\uÕUe6iùñ¤%ZÐÙ.^ÒP+%P‘DÖ ¼ˆC?ûµŠ&û\ªÓ¾o³ÃfffEJ‰®ëƒAÁ`'j]K†5üÿ}‚_~… ã$“I’É$—\r ÑhuEÁŽf,‰Ðe ‹A"òàWºì5€ ~å+gÅheR&“a||œ .pâÄ Ž9ÂÙ³g&‹¡h>ñ'Êw¿û]‡æðáÃ<üðÃU/KØ+rö }Û;Ü.^xÛ6v!a[¨‚¡¿vm ŠòúišLMMÑ××ÇéÓ§9xð §NbË–-<ñļ÷½ïåÂ… <öØcœ={¶ªyïhÑì•UÓBmÙ±àvñšèBñG£tÊ¢ñq¨¯¯AQVÅb1b±RJÞþö·sÍ5×ðÌ3ÏÔDᕦÍ´ºŽ5,à!\m@(u ;±$×4–‰€ÿ¨««Ãï÷ã÷ûÙ²e ûöí«I>ׯÓùѱÂßè@Ñ©`- 1…4-q“±±tî”-IV‰šõì˜Óùæ=lÔIDATÒãN\™;mKJòa¹g×ïq)i8÷ì[¶ªrö™˧çüf–—S)xÇ¥4Ú¯ÙÍ ÙM —`0ˆßçÇïó(†™ ŒÙ®E¡°Ž®UQg«R½ÍŶ‹×Bh¾Ò´àâ†ùÆf72@ǹ“˜|iÄîŽWø»€ØÛn@é,æ y £"\c@ ž»-åRD,ÒY’öi_Ò9,{B˜t䬢¡ktÍ‹ÏëG×¼(dJ22)ÁÌ ­ô‚>Õ¤fÃ.›Dw;†Õj¤%"o¾®…½­vžržRÂùf¸mlÚT>_üŠÄ|ýéÈ¿ŽÃ‘a„r/ ]ª‰€%ÂÒ´ˆxòþp%•înPUûZ¥%Óõ›|HÃB :ÛÅÝ&áªö4Ð^úviXloxc›tß°$¥}P¥)Ñ·ÝWr»xMìÒ´À(½d•jG7l Ø:€i!Ôú’.âUçÑ÷ó2 ‹½mŽþŸ"CÐJ i؃P or\Ä‹n«:¤î­—Y-´,JdóöÏ„ì*UN7l M×9:ny8€ªE×Iä³®LÐ×Wå"¬`놅Ð[wQb*XMØìEøÖÉŒEG¹X¥šÐ —Á°í”X¬6+Ò0mÏ”ri•ýWŸ²GÕ(JÔÙ.^Ô1¤ê@ñ_‡a±³µo—öö*c•nÜB¦­ .#–s^‹Ú«bV)GdÆÖ´ö]Á2@StHÃdçÚ2eÀ*jB»6euÃÄ23ó*Õ4Û"ÀR:dÆ$33ÆÈÌÂ?Ò''Q§§IŽ,¼{h•*#i˜ÈŒ…¢oÛcÙGÇÍq¯úZ€Ì˜´7jtww—õƒÈÀj:ÍX™ñW©|ÚÐ*9sÆÄ²Tçé9ëUåþ[þá&™±hÐSe{º!°¢Ñ7¼+øJ¤°Wضvþ]¼¦@ÊØ `J çüyRå+«T6]Ò/½d‚a æ™ T ö* V™Ì˜¼z:Ã[ÿGáÑ5wWf½ ]E´|!UÄK*BS*84b?“}λ˜Ç娑ûî®RfïÂý^‚ Îÿu=;>9ßGw˜•—Ùÿœ˜ýLöo .ÓB¦íDÚÄÊ}·Ò†ýÍu·Ò&¤Œü·Ü³LÈŒ†44g*XôŸDªÊ¬TF¹ë¶(;ƒM±ÏäÕDöŽj?ã„©N‘ûfoÙ.Òó=ã ÃõÍõì<tx¹GÎ}–îp9$Ò.gű\¿wƒÅù¯Áì2.¦‰4²çgWW¾Ü³³æ’ïç¾Í ÿþ÷MñìSÅw U“cð™'^|ÉóGÇŽeìѬ) ©]ɽ MÍ È{îYäݸĬÎwF¹»£ €(®wwása²°Ï°Ü£œæîhŠtz1 XîoÒþ³Él‡æ;×Ì¿îw³àݞ뛹)ŸÌ8áf6® çÌð Ëá&µæÈžK7"4гëêx¡)àƒšˆ¦¸Þ³ß¿çcéEîóŽþ""ÀM³àº¾ÌB‘Nw¿/$r'‹;£Ùp?@ag»íðÌ\ Ã|u¨°ºUwhš==Cs³tË–ñº´;T—Ùw²±ïh¡Éì;  „FöRì#ßgúY²¿((ìø¢£¿1PL¸;ætr±Ñ_ÐñÛÉÔ´ÀHC ‘6ëw.w‡f² mºÂŠ\i÷»Eÿ@|ÞêUkî¥> ª¬ýàMŠ&Ößs{×»,!5¤TPRJ‘;ºçÈØ(3¾1U7&…b8ßlû¤°9@V>'çyj¦¸ž«JY X®ç94Ÿ;Dp¤½•;Ûû8§(Hlñà Dzl X++>²þò6ʬ\º _ä•§1_;}Ý@?0 Ä€ T8Å5¬¾/ŠÔ×OöÝÞjš¦Ï², rž?áíÈdZ5mê¼ÉbßWiq$„B ó…W Ì‚fµÆ†<@ˆMÙ{(^L;¾½ÇlT:´jX:Iì?4HSØ#4ûœÄCU™£x Æîü 6Šù{ @\ ¡—ò?KZ¥%€$vûNe¯86û· ºP°AàüØ:Йsâ,µmU¤ìÿÜ‘ÁæΕɆK¨.œŽT± “ß”P`}šßý-«+¯  ”Õ&s È`³ý\çCõõc'M…B«S±|f`öè_ÁÒÉsÍ\ÿ‘ÆÙØ×U&ÙIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/root.png000066400000000000000000000101141217176075400235550ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ $­ÊXÌIDATxÚÕ[]Œ$×Uþι÷VUOÏÌÎìÚëµ±¯íd ‰-c+a“HÛˆ„DA ùŸ‡ä ÄR¤H¼‘¤ˆ%‰Â B,a¢@°•`[^ƒI¬ÄN6kïwg秪î½çðpï­®ÙÙ}!nã©TÝÕ=Ýuþ¿óÓ¤ªøqÿè:pmÃ?¸bšæ‘èý [ ß-Þ û¿WU€¡1B%¢Þ¸É·W.=uÕ½°{£ï×ÿï2X,éO%ÜzïoüÞ—Ýxmóõù$Ì/œƒß½ UD¡*P‰IØ!¾Cµ¾‰Õ;ï…t-Þÿé?À‘¦Òø£O=ÅK ·þ>—¦¦ÝºÜ}òCáo·Ncû;/¢Z]ÇôÂëÀPpUhŒ€DHðß~ì*l¾÷aüáéSøì“Ï·Ñ{ƒz97¹4[½òÂ7õËÝÿÒDZú؇±ÛÌC<¨)&p¶îØ9ܽ±‚.àw¾ð×xãë_Sãœ.ë>y9þŸ?¼j0ùÑ«"X¯Dó(˜Gæ·)€(Ú§Ë„¦Ânpñ[_ˆA¼qó½õÄjá¡Ú3Í* ®›>}ð4Âîöv_ýŸ¿²­GøÀg~ùc½ÿ«ÿü4ö^{<Ú­K ã`ª ä*W¥¬î®ÿœ­Yã*˜•Uçp|\ÃòÚ,¢ *à£ôB'E¤¶˜ ðÙ~úý?Ãd_¿õÎß’c-&¯ÿ0yQŒˆ] ß »ê[Ķ…tm&\¥WÊʉ; Dø©ßþc|é×>†ßüü_œÛ~å¥',[[]~î›þ…‡OãÎÂÖ]ïÁêêó 0LX±ŒÚÔ&eÔÆ ± Û7ÖÀfl_Ά‚$Dc·­0ñAm”dyIìIœ@L׈Ctçú º(¸2ëððG>˜úduÉ¡%aÍÕ#jj¤DM© ˆkM…µÚáÝ›cüþ߯ëOuÆÖ: @ÃtO_ø›/á¶G>ûOÝ‹±38ÚT8:ª°ZYŒ¬ÁÈ™t¶5¨ g67 žšJ7¨è…UÌBÄnÐÅ“ÀóÑÅÄÿIŠð11E^D„SÇÖz2¥$ÒÒààû†P{½vØÝÞ» ~çjJ‚DŒ8›`6ŸÁïncòæLÙ`o}{]Ànpef±Ù8Ü4ª±Þ8¬‰ÅÌ jË}8æ}e¬x€Ï ˜ùˆ6[¿ ‚‰˜GA"&>bž•´×y?X*¡U:d“A•ÔX›Yç¢0îñGzDÑmoaû»g`ênu#•ÁTŽâ;tW¯YYYE”ºì®±Ñºì.…‚¹×_¸`©÷!Òg´A0 IxŸgmˆ˜ú€‰QÀùû£(À9Áp²Àêbéá÷2-eyœòFz»yò*Wp€  •ˆØÎ@l¦{`ë07†k˜a™p@{>`­²;‹ÕʦFgb¶~E7ð‚n ô<_›ú^ëºÞƒˆv^†J;ÍÙí^p­àCOÔA\z˜º³(@@„´sÄù D v‚«@̘æÄSÈŠ˜ëô‡t-ˆ¦ÁYƒË ›Åa™û1šÍVwÌšÅÒjˆ*"g % ÖÄ;‚ìªÞèY ‘˜YJ¹`>|¨Â ÚŒà]ç,æQúŸhÁé/‰’’aRR²`ˆ‚YÌ|@œM»6ó5jk²À g¸|ÔœÆj: „a ’¼€`J(R Eg\%ë‚ïŠ"4xhVDbÄÙª 'Òu0] õ« W!Ö5º<ù%á†!æ€b;ú|Ÿ¡ >qZ;æd]k}“ÁVQ¶˜Þð‚F+Íø(D ¢äµ©gY´Ø}L/XpÕ€›•#ˆ ¶óž ôLU§Êaˆd,ü€½QY,@HÐèç3ˆïàw®"ÎgÉâGoFsó ˜ªNÛ2Vœé¯IBNÄ õÔZ>¸†XQ¤°«Í:ÔÆÀ®¬‚ë’‡-VUàÆk¨Ö7Q=޵“§&»˜*“W­K|›Ab¢@(ŠBE Á£Þ¼a²‹É¹@}ÊûBªŠæØqŒ76QÆÑQ…£Mò†2R³¹üY‚¡È†@Á ¥?ðƒÄ=²«ãŒï¸³ógáw¶’˜ªAœÏà6Žâô½wb»õ¹¡¹ÁÌo‰‡Y˜ý§9_*—†+Îâ™ï\M» n¼3§žM±M„vmGj‡ÍÔƒÔ¶T‚4@)É–38ºcV.ú†iÑzWÌ; S'ï›?› ¾Ãí¿ø«8rò¾ñü„éb;ë-Òûõ(‘8=OÔ5í£Âíx-›Þud?{×ÍøÞÖ4¦òjª¦n`šÜêL=× Bìt;G?Øž`âcŽñ„'Šå÷ñ/ZÆi acßd¥Ç•IŸ78ñá_ÀÙ'¾’C FZ»ç¾êC?÷(ž}öY¼ú•¿DÑ^}3åë€Ln&%p¦»Í@ pJ0Õú&F·üÈZ?ý(æã“.ôSvU¢Éšl3‚©˜ºAUUh c”KëåY‹‹“péÜY1ÂlÒ¯Ú©D¨hZ­ËäGÙ4Ó ÁçÜB¼×5ˆÇ?øè>|ñ¥“õÖ™o“%ctváÜ¿ýÓŸýÉ÷÷Î~OÒÔVàÆë “=7ÏÔ*4Æ>ë(S¥dRDBè'LÛß=ƒÏ½™»­KdX-¿Ñ^¾ð¹ù¥ó «ƒ2X8b!*7&Ù¦{PÑ@LwmùÖLݬö}¹«`ª\åsNª£œùGÖôµ¿2ŒöÊ%¼qч­ÿúÏ? ³éËDä.¾Ñl89÷ØZ%¶[vëåçgÎýXô÷µ›¢ l„Çaº§â;„¨)véé4ÊxÀ9 ÇÔƒ 2GtÌ}eW½¹GÏ_¼‡ýÎÛÍ ÍOva²'-f…dl²¾u.4&So9ó&Dß•˜_Úˆh©ãqBM¸‹Ìu“ª„]›ùƲMbyÙ«o‡‚‡òþi¯qUnym?&/«3åpúb°@}H=ÀCºLpdÆ(Í SétŒ_Z_C©·+6Ùÿ_ Q@Òå´ Ël}Ê­¬ÍÌOzœº¼ò¼/µ‡Ö| °…BÐ9oˆ•iîóæ€èíÃø‡VÑ{0Kߣ3-€Ô°¥å~Ij±4a(å€e{ÁÒ“`Ôv_,_ϲ×^ã<`Q9Ä9@UzÜ>”ãz‰í†É® :¯„Ä7^ƒÙ¯'ô°Ø•¶ 6¯$ìsã0X–q¸dტ¤Â~àYhº%†/=Èt°,š¼"„Þ‚Hâó@ÕGx@jiíŽÆE/„E?·—D‘GIÓ›2E*tšAô¾g«—µ4¼\”_‡iV$&Xcf‹s.ðyrÜå1yÙÑ®KÇáðr·ÄØÀŒVî$&š\c€]L‚‡(ý8Ýg²Ã®®A¢?¤IPÕú& Î“ž¾AŠX"¢ÚEÌçPÈMÓŒPéÆ!î|‡µ{îÃåi‡½.Dp«GÀu“!c3“¬hC"<·[îL1õd\Ïß:H¸åƒ?OýõOáÉü;\ýïç@Æ`~é|Næ…*,W êÍc¨ŽÅñÓâ“y ÿÔ×I%.-X—éÔ¿Ï<÷<.?÷ï cнya²S× ë eÓÌZˆqi+4/5]ø§pö¦_ÁúÝ÷-Ó=þ.ó»ÒÎ7ˆ)’uÐà{züzLs¿ì`m×ÓŒvº­Ë~Õ½ðê ÓÍ;ñ×ã.hð_༉ÑëÿVª¾p©éR^c@a²ã‰íùeÝäÿ»ž~˜¼³téIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/rotate-180.png000066400000000000000000000051321217176075400244020ustar00rootroot00000000000000‰PNG  IHDR'/`ðÓXsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î< ×IDATX…Í™{pTÕÇ¿çœ{ïn’Í ²Ù< åe€ð(†‚ aJAê´ ¢V¨ý§ZË ;>ìPKÛé`mQ¢¦N))h±Ht°ä<YòÚìfß÷ÞóëÙ ›ìC'T3¿¹“=çÞó™ßëüÎ #"|U…Ù·e0“Æ“æ`‡ýÇLˆpHò€W‡ûªË¨­wSmW:‡Ž Æ­/~ݺmís?~’sGLêzÀãó»Ï×^:wæ³OÏ7:;®h2ÞkðPÝ]‡;²2¹yÁgNÀ Æ“” Ó@ÐÕ&=u¦ëÆwÕ¾ª'/6Uºbìö†Éó¿À Ê­ # Ì0¨«uõdà*×”šÆ“§ÌæÙ¥s²²FM\õÐçÇæUî)ÊOe[›»©þ®À’: @êñÃf¨çêY‡Ã>a²š>zRÞº,ûºÌ×_³çØØ§—šîœî“áÄpýÅß ´BM+f…‹×Z× ñ”¾ù•p†•ýüN’ept?`ꃃëyp]Ó}È[ø=u­§uM»ÿ¯-~5Ø%]çÈðQË ZÃ€ç ˜÷ ¿ñœuUYÑ÷ïÍä%C '‰¤€¤l u$: H+ÒF÷©Ì:·èÐÐÁÝN|aêЭpVQZ}ºltYÍcà ìáî¸¹ä¿ KfŠÓ1a0ß²®ÄdV7›ÿtÕ 3ÆgoÈ ®(HUÌaÿ8M0-ÝÂ2Ó-,(a?##˜Îð‚C‡ Ójú\ë£ï©‚©‰¾= [ëIwºMg0"ݳv_mÕxÛÌû ûèÞÄÅÚz7çÞ_¼°¦T±@ ,ý¹6¶½ÅK}­cèv€ß'žÿÙ·Æþ&eêJ‚"a†5kV6¥(àÔx8þ%|ÔR8«@±&!d²˜ÂÜmÁOöÞxfÿe¹³ÏôÀx.ú›Œ0öôéðH0™·ài WTÈ–’ †oË@aÓfq¬p¡ÅpÕÃu|KÀoÀÛzŸ˜‹‹ªˆÑ¸ªþa“|ç­£w]ßû’nvÕ÷løï‚® æ| †ƒ ¦÷@!Œ›§Ñô÷ á·Ž·l;ÙBïǺ¿á"…ëu-bŒQŒÛ;¶nnR·nµ>et?–?g…‚äÀu!ÞjQÑM°¬RHžŠëû^Öw¼±×ö3òewˆ\ƒ‹ZŒ÷û¢€±Ö½áEsÅiãwjånëãR8wÖC »î†d È©9póè_P¹ûàžmgä¦V?œŒ1ND2!\4;Ñ×­±–ãpü;ÈÖ4u‰IÈ0¸~hÎ.Ô7u£±¢ÆøƒEìMz”ÂK²§Ìà,Ü nö³BjYh=±-ÕQqÚüí /š"Æ@Ô3ˆ]0FŠ7@ücŠ…¦¾˜\tÏæ”£_↲²z’ˆ«]¸<Á¡om®>ÜØzê8H(É·âMK)ih;y>Ÿ@ÈäÁF®õ[“Ç)ÎuÁ‰ŠÅ¸7'Eûiîü5«‹ž­²¤Ly” ˆ$CEJä]¦Ij ÛuW.˶s5"à , nEkM5wη¶Ï_­@ÑÀd˜±H,Þü&øY¦Í±N,±æqwíQpÇa#³ptœ?‡îv?l³Wƒg:À¿ ™ØòÔ§T ”­½åcóCÊ„é¹ê ç,+Ïzàa…\§`ú›p@£px ,:öX-SLQ2/cÜŒaÉYáËN¸k?é^€— ÛýËa;Þ ÇuÒýUL2Vcc.‘åz-øÊB1mzžölaYù<ûŒ ë:ékRPŽd»Cf›k k™’fçÉE÷iÉ…%BðÈßµ  gð_¿"†ÔÒ©Hš°![¶ÿk‡Î¥ÜÀ¬.&{á¶-³Jr´ç fΛm/½_a®Ïß pÕH?†*™©Ë…É n$ ÒëA¦ p–QãažpZþd@µÂ}þmµ_>ôÀnÔF  vŸD–¶g©˜[œmy>ÚÌéöñãæ¾„:®öœQ¯ã*WÀ™ÄW®‚TL( &®@ËÎS’À2FÀ}ùœ¨=v€·k*€~¥Ä°w‹ÆäZÖN.™žuOÊ|õýêU_a àœADT¼÷Ù£"c4H 5œl Ý8bê[tñ‹Àâà¶,ŘìtuyÎØ‘“‡ÊVy¨ »¿è €YD9Xjœ‡Žê¿…:>¬Ü øwö;±pD $¥ˆzî@XÜyæ9”>mìÔÛÞ¯¨”†ëÌ7©Ã{¨zLüÈ~\lóšo;/\û¬ãr³N;`ÍB‚†ä6P¬Y`ysaªÙpîÿuðæ{z=rm(Ýqg—9½Í&cLÐho/ŽÌTÖåN™þµì)³fx¿³§ÚsPR%©ÇºŠPl€%,Ù¤ƒ˜÷gÂí¾y3ØÚðšBþ?O¨¸ó ÅþpjTw•‹YãÊòg”ͳÏX¤ðp;Ð]¨6°¢%`ZÈuPS!¡BB®vx.T»ÎUtoW7ä¦I»Bgï**±¥„p«îÈ'™Ÿl_Ä6Ò'ǃÄ,厲 ·d€ºp8«ÀYµ € äBédœ‡IU0BU¥»Pß¼ÿ»ô‡‹Jxú°Qóú"c#>>S—9æ?¡ò”|0®@X,!aµlfþÐÆ‰•F\£8Ò›­‘¤èÙï¢{žùÌaœ½Ôi¼ÔòñÁ=ÎÞÔeêX°Â…€°Ü ž¨ü€³?k¹(¤¹ú.5yô m'öítúcØpÕƒ î …ïXlý»’>n¹b/®~¼Ê|±ãß»ƒºckÒ0ý¦-þÔ4Twn4ýÏÑ®AžYÅ2 UÌg› óƒi;û„‡H^°D§¸ÕÓ)‘'K4ï.ê DD ¯#"Ç?û÷]°ÎÊ€w%_P¬|¥ÿ1÷_·ö{.9IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/rotate-left.png000066400000000000000000000024471217176075400250320ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“tIME×;( –e ÉIDATX…å—mlSUÇÿçÞÞÛW¶ÎNº­Ûpd˜à !Q4*jB²Í-Æ?è h4À/: 1Q!c@ãF²ñ²dñh¢Äeudt2Ɔ[ÛmЗ{Û{ï9~èŠ]{»¶ƒ&>ɓ۞ÞûüÏóœsî)ð7r7‚ô½ˆÂãÞš×À4­ŠRÅÁ”¨-5>a¼Åº{åÁà wVÿÞf9sñ­ É{r¿À´—1EbéÌÝjˆ$Æ0,DølòÌ&Ë7FçÒÇËÛ˜M®:°Ðº69ªI€IyŽ«nÓTñŽúšPÃM']/µ;íõm›õ¨²\r8ߌ*N4ŸYöþ)»©x9èðq@ f@•ðK ¼ÁtzÙö£ùÆÂÒ˜8U³¿S“ɺϵy‡Óäª#tøhîâ˜Z€»ˆ‹OÙ×¼ÌÓ¿zt3ÉÊ”ðVËÁŠ–ó™ÿ@ö§¹‹€äU¶2@Ì0 0möJÁ"3á4€fð[3Šc5F×*°‘^ýÙNx¢G ùþ†·ww0èq#zÓoØÜˆpªA4îþ­`FŽp› zš‡ì“gôs/¬ÁtÿieôØžQ•ßEm5FÉ®„TÄ2ŸÛ¾ŒѸÞVy¿‰¯LgâñFh0Ö³7 äWuãf¦˜90‚rƒÉ H~@‹¦Þ Ú: ªF{rÏ€ÒbÞ(‚)·ô+ÀTDý£**—s×øa ¶¸nÇW¢ha€JúPÂÐäe–þÚˆ¥`1U{úf>€¾F”s"ßÇ ÂíqE’¢„.ª¿ù¨aå ë&«i hŠ*¸[è¶Ú¯éþœÁóâÅbuû¸ yoÿF/“})¸ªÕ½Çµò`¾Soãj×gÍ€œ€Ùˆ^iÒûqàt»eÑÚí½ô%XxdÀXJ:p0XpË[MÅȉ/$E“?È$蜈ú›PÊDÞ]¹õÇ¢º­„^øˆdn'©|ÌZ‰Á^ÂÓÓo¬îÐÅÈç7.y`eƦ‚Zýpgû­ÐùÆU5œÛÓ8q> &80¸g“ðOíXÝ¡u«pŠF¢ñ:@†¯þÄÍ eì»òscž³PÊ뙘àì¾wrÏ 0Û}ÜÿzØçóRß©}>‡C¬Âóž;¸Ùï<¾kSëÊØO¼çܦüÒbQp®#±•·¹@m•ðÚ)ù'&­íÔÚ“¯YÄÀÂÄceÌM®ömÌ_â„‚R |#ö†3ÖxºöIã“Çס;Óh°’æE:€xù¸cC}ÂÅ.ãÚ¥ ö%…o-ˆíˆ¢ýݒwÌûÝ“G´mjìMòt]€Ä~͹v âʳ.Œ«×=ëí%'qõû%ÿ ß™'´×*TÄÒ9Kø<Ç’û3§É~²{¥ÈÆïmfœ »Û¾U·ôûIÈ,€–2/@|L·HïóxÔb€ëݳè>7†øé$±¼Éëf>@rEâ­‰¯ç䥕8¹’!2nD ùo˜î™ŒbÿIû Ü>p×;`IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/rotate-right.png000066400000000000000000000025111217176075400252050ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆIDATX…å–klU†ß3gf;ívi-Pä"År‰…š¡Q)Åh A1i+¡‘_†ÅD—‚1š4B ij°¶PnAê%j„z©(—¥Ø—Ji©-ȶtÛîÌ™3ÇÛm¦»Sv[øa⛼™3“s¾ïù¾³çdÿ»Hxp¾D-&+‚»"'I²+@¨Ò IjãFà¨àÖ±Eå¸rOIê6¹ÿ²XP8Š‚k>aÜl=5»¦·ê6%6+Âê»Í;Ôo‰zkÁ®öñâæ)@¿=|–¤r"ˆâÜSA’§ùZÑþÙËZÿåßÓÖfïCÇX¤ao€ÅËnsvCô]ƒèª…Õr2üÈ|íˤY¯î_H\IõÞbäÝ%€aj€eÄ6Bø.Àj©BbF¶”õ7•Ž›P}n½«¦‹îÀHfDk5(‚˜»µÆM<_Ÿ-Ƭ1€i7!âµÑq4AÅœ-å)Šê><ö˜Á6`¢õ8ÔŒÅÄ3wñƒç7Ðçã‡H$i@:ÈÄE¡‘Ma¬ü áo µ?RƒèüÓÖoóÜnX¹SlåÉVXqXœ¿Û°­`°¢/"Ùª¹gcù­Ÿ+ÛôÚ—f´ûÛ‘4eËâ‰@XóÂàLßÕS 4!tb",‚=\ ç“î9 M¿ÑnÀr¨^˜óƒR cãâ‰'Çž4<‡dMA:Žé\ë%‚õ‡ªŽ"Ô³ÈéBd}NFWî^h£8»† GÅ$ÂÔõdJ… Öï|¹~€êV½ 7õñüœ/ðë¨(”µ“óV«é½áª]‚ùaÞî°@…ôP rö–À8¸<Uѱ#—ß¼à-¬ÑÎvvþôMaZþœ2¼îãPå\Ý‚‘Ò»ÁÏl‘!徃`ÓQܪ¯ëçÌ*‹Š 9Uˆa˜OfWàÑHvÿ,VMLU+³^)M¤”A\=†Ð§•2¤9E0|×Ѽ{K@ÓØš%ûqˆ¾š©SŃß)B[DÐÏqmm¦yE¯ûvõøœÇe)y"à¿ê„Ý ¬ëéÄÅ=oj¾>öŠ*üh‹=ŒÚ €:X —7¢åé ÞÅšNæ¥Í_¦Ð„d@ë²ô\°€ËÞèìÕ7çBµ-yXž,²úpÛ©í¶TÑ,šŸÊ0Ì+¿/N››£HTô@p”™0õ .UìèôoUI…m@é½²IÔ­É4)»Ú˜6{¶"I83qñPåÀnãÃU‡­R„ö\Œà·€Øž$âÛP5å âÔú™,ÕhoÍJ1U¦ŽË_}§ùzõ=OTY;“Û-"ÆŽí`ömˆtŽÔÓR<®u¤7À*––ó×#’q‡qTµN Ÿ§mêÎ}9°ÏXVÁ·%·CDU€]ŽÉáüËï±âŽUŽUNkG¸™þÃú«QÆ %“RIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/scan.png000066400000000000000000000215221217176075400235230ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ IDATxœí›y|UÕ¹÷¿{:sÆ“™@bHH˜D@f­€SQ,V;\k'ÛÒ^;ÙZk«¶êµ­íÕ«­R[m«­E©ˆ€ 2 "˜ ™Èt2œùìyï÷“Îjé{½oÿ¸ïþ|ÖçìýÉÎÞë÷]ϳö³žµ–àº.ÿ›ñ_]õñÿü«+ð¯>þ×߇\{íµ˜¦‰a˜¦ùWç†a iš7NSUu‚aU–eUaÓ4=¦i⺮Œ=@W 8:€îñxPEQx·óM›6ýk¼ÓaÛ¶/“ÉÌ1 ãŸÏ7¯²²²~ìØ±%Bqq1ùùùH’„ã8hšÆÈÈtwwÓÑÑéïïoI§Ó{ ÃØ–““³_Q”ÌÿD=ßwº®OQUu}AAÁ .¬›3gS§N¥²²¯×{¶Ï(éìì,9räÈ‚]»v}ùðáÃmƒƒƒÏ'eY>ö~ÖWx?â€k¯½–t:=KÓ´ uuuW,[¶Ì3þ|Š‹‹ß‡*B$aÇŽlÞ¼Ù8~üøóçþQ«øo»ÀÀºuë*2™Ì7Æ÷‘Ë/¿\™?>~¿ÿ¯îI¤4l¢ùd3§º[éô2PS^Ã`b˜L&AAA1eáRê«ë™Ú0I&ôÿê9š¦±sçNž~úi»µµõñ`0x§Ïçëþ—X¿~ýuŠ¢|oÑ¢E•K–,¡´´ôOfOÆy鵗ض{mmXŽE(Âà‘}¸ŽÍäº:ÎtÑé!­ª¤3Iâ‰8¦iS›Ï¹SÎcÕÒU,[p 9Á†a000À–-[زeKŸ¦i·mÙ²åÉÿ§>ýéOûTU} ¬¬ì–… ÒÐÐ@ii)>Ÿî¾n}úQ^=ð*!_ˆÚsj)/-GQ<˜Ž‰h øü^’±8õuSèì:M$:Œë˜ô ö¢š¦KDéèc$¥¼´‚kW]ÇÍ×ßLYQº®‰DhlläÅ_¤««ëÑ@ pëÓO?­þøüç?_fÆSUUUK¦NJ}}=555¨šÊ}?½Í;6S[UËÌ©3 Cd´ 5ƒa†€€Ï륣¿Ëç/çHÓ"#q\ËâÌp/†®cY&†e`Ù¦i ÓÓÛGq¸„Ï~ôVnýÈ­x/œ8q‚½{÷ÒÒÒ²Ëëõ^÷óŸÿ¼÷ Àm·ÝVeYÖ eeeS«««™;g.•c+yíàk|ãÁoP”fÙ‚Køü$RIt]ð ŒÑØÀ4MtSG×MÝÅoºGžyWUñæû‘mcôÃ41-Ó21mË6‰ÇâŒDÌœ9“}ëGÌ=o.½½½ìÝ»—ÆÆFÚÛÛ›E¹ô±Çë<[Mg Þ~ûí¢(nÉËË›ZPPÀ¢E‹¨[É=Ü;ûV,\Á/[‹(Ä“qt#+þ/#ÃÌ^ç)2ª`0ú"ŠŠòÈ çâÅ‹a[Ù–w-lÁÄpMt[G7 4KGòÈä”9|ì0KÖ.á'þƒŠŠ /^̸q㨨¨˜$–[n¹eÜû àŽ;îÈ‘$é9A`¢Ç£°fÍŠŠ‹øØ×?Êö½ÛùüMŸc\ùX¢ñ4=[aÝ00 s´dÅk†Ž®éÄRº›l—3í-Œ$cè–žµÛÄ´Ml¯…Tb¡‹é1Q ÕQQ1ótYgÃ7¾À-ßú$EEE¬Y½†üü||>ßDQ÷™Ï|&ï} (Ê£™Læ‚D"ɇ>´žÂp!7üûzbñ·¬»Û¶I¦’£buLÃÌÓÌúþh1 ÕÈ`K‚â0˜F÷xñ¸ºmdÿ×2ÐuLB#È`çXø¦Kxk2¦m[à"b¡ÀÃÿ'×l¸–‚p7Üp`YÖLY–z6Ú¤;î¸ã=o¸÷Þ{?›N§¿ØÔÜÄç>÷9øð—oÀ4L®»|±DUÓ0L˲p]÷O~ü· Ë@7 ¦ÖLbܸ ¬»ì*1A0THÿà0‰xK°011ÃÕIk¤G4”z‰üi^ÔA;e#úDD¯ˆè‡Æ7éîbýªQ9¦’矞@ 0i×®]éeË–íý¿pÿý÷Oq]÷Wû÷ïW®¾æj.]y)_ý¯pºë4ë׬'–Œ£éº¡ Šª–A5T¬¿oüùW7tNwœæ÷Ï>‹˜ëã¾G¥¥ý¸Žcc–ba)6¦bb*™´FêTÙ/R~YfÒBï5½‚,@Pà­ÃGpk/[‹(Šlß¾òòò…¯¼òÊæ¥K—¼›Æ÷tEQ•ãϵ1÷æóƒ"Žà€_D*xbËÏx«íºþz$I"žˆ7È’|Å?à“'Nœ`Ñ¢Eäæårÿ£÷3æ|ÛÂt t3CaN!Z&…æqιsÐ ÝJ£Ù:~%Eò02%1"=’!ÞŸb¸'Šf¤9ÙúŸøðZþåOùÂ'>Î6|ÓÔPE‹ :vÐÀ_ 0¸£ƒ_Þ~}l§äÂ"H.xE¤ …CÃÄûœ¿n2–ê‚ì"%,ÉàÎ_~—`0ÈÒeKéììB’¥Ož€Ç{l¢¦i ¢Ñ(×\} ÇÛŽsª½•)õSH¨ 2¶Ž")äqªû9¡| *Šü.éT‚ŠÊ Âå¹ Ã(9"¾°‚?Çm[˜#Ñ®89ùyH²BmÃdd%„žq°R"R©‹P(`§tMÀS/âÄmN?ÓøéŒ½°˵dÙ/"”ÀÁgš¨:w,ùãs0<bXdóáç9ÕÛÊUW\…®ihšvá½÷Þ;íPeuOOR]]MŘ žøí4ÔNÀ¶mTC'O3¦ œÈp?j:Ι¶FÞ:°´:Lqi˜\Ç[02:¦fa6¶c’W”CNy,èlîGÉñ±±L lÝUq \ŠÎ{A.¶fbÇÀWáAÊS8øËãÔÏKy}1–aãˆJ®ŒeX4í:ÁŒÕSp5Ù/`Z*½¼‘’Òê&Ô100 I’ôwnðwDQ¼¬»»›yóæá¸ûßÚOCíDR™zJCB"äqúÌI” #"‘ÀuÆ•MäÔÉfL,dÁÁÄĶô!'m"È"’G ··]Oâ=¯q²€ëuqrmLÃ&Ö©âËU˜xÃ8R´FNp´£‰ g_ˆeÛ†1UÅÊw IÒÔx< …BTTVðÚþ×(.*Ær²£8ݶ(‡iíjCñ ˜–†aéà*Œ).ç­–cH^ ]SIê&ç”M ëh?½ý½ùq;‰g¨ðqÉ­ËØøµÜõÝ;™¸bE =j%®k²ýíW()/¡° Ÿd2EqÚ»EqêÈÈå;qŒ’ÂÒ•Œ¡#‹"Šâ¥ïL¢†c‘Éd(*,&­gèô¡¸Q5NyN!ÂH€=»÷(ñª  ”È”M*£îüñl?ú ßzæ~zôQºgð•Iˆy @R ñök-䇼T,(Åð,Û>²ƒ‚i¹è²‰ä1“|~G6±’&‰´N ÖOPÎU Waw9(!Á+ ¸"/„4D¨_ý0µ`<~DÚÌ0’NPRZŠ¬È¸Ž›÷^Š¢——G"Çut×Ä4u¢±!TK ¹émN¾ÝLÌ;@ÛÐiV+£Ó¾'Beù9œÙ?ˆ–ŸæèÑ7H &èMŸajõy•“ MJVQs NLkBø\ðÒ>ï׈^°d[°YX8ŸÚP=¶ëàÆNö'«awG©/œ.‰`»˜ºŠŒ›81xšã¾fèhNt ¹àÚª™!7'¯×‹‹øKÍ;5¦ø|>¼^/ŽàÐPÓÀ˜¢1„ù„¼>Ÿ? UÌŸts̤X(Âë Ì«ŸÏÌ¥SY³òJ®Zû~üÍD£Ib#Þâõ5µFrH&~_.N…EßæA®xv5“;§²¡ùÛ¬.¸š"5ŸV¡•ù¡ÅÔÒGuI%~ו¯%R9„“6Y5o ^ø_|%ïkÔTUѯŸ¼ú Ò³4>1é߸(w1ËV_Åwf|‡ÇìÒ(w# ²$àóùøÛ$ð_p]Wóù|8Ž4·5QwN-±DŒ–“Çñ‚ìo|‹#=¸Z_Á¯w>Gà£òÜYôMÏQÛà·On%é[Ã̺åü×ÏA+ó /ç”xœaïRÐe$•@tTn+¾Ò›+ù‚t+¶ô)$Ujo5™&ö ì‡.=W7ñÚžCH›=ÄfƉìàaéQžnÿ5àP\bÛÞ­¼–»ƒ ¬9¼±i7ß½ðvvö½Ž3âÅpmdQÆçóü¿3~¿Ó4É å`š&š¦£é†ä Y:Õy%)x á@Žä!¯¨ŠÏ…¢ŒX%1ØãÂY³‘|"eåa:3­twö'•3¥f59Ëy@„Wnäù /ò±ýW!xCBVd6'^ä„Ù‚às!ßeAÕb„¨DÙܱœLFX$P.•‚ÏAÎQp¥n©Ëôº)Lµª`†ËØ`¢WÄõÉäzƒ˜†Ž×ëH½W0ìóùPU•üœ|</C±!TMCt† „‰Û1öuBQlC£ù­²î{#€ö¶N4Ã$<.Éɘ)*ŠJ¨?²âéŒ N§¼x1©!•Ÿmþ Žj³ 4ÕÖ8!¬!¨–„\ç[İéö·òðþ_ O÷0”‰# âà™Á§ jJ«h>t&@K¬]rÈ)."?GFSñz<¸®;ò^ÐåõzIgÒx/áüB:δOÆp]›¾3æø1’#Ž!ÁÉ“‡H½¹ƒ“Ïl¢¬¬˜¤žápã.Vλ”ØPAPÄ9¾0´K¹&  ¯žyÊâû‡ÈM97"Ê2š™&€$áÄ\f-9Ÿc}o#ȹáBð”ISé=ÓŽpQ‚ )IEŠ„ó‹hîkA¬9hÀmªËjQ‰t&¬ÈàÒù®\×=îñxÈd²kj«jŽcÛ–ãÐ@ôÓ©Tõq\““]-4Ôž‡rQ%›¼ü/lû=ç·Òü"’}1´á4Zd€ˆeq2£áÊP¬¨ Œ£õµãèq‹åùcX¶zJÅ0súví;‚[*`*‚GbâÄ:Nuu!„< J8¢ŒVE/qu%Ç$‰ Á¤Š)¤ÒidIÆÅmy/G%IB׳YÞÙçÎf0:ˆa›X–I,1ÂHtÚªZúûF°L —¦ÓÈ®LMU##øó´÷÷°çÍ—YÿÁ›04-âð¦Müö?ÄáÍ¿¦ðd?3 g°¼ö ”/ߨt;_™øÄ@&ÇE`í«y»½…h*‚¯ CÐ)WŠßë§{¸oÀ‡ìUplƒªqç0˜HàØ"^Ň(Kà÷3oì¨jæOß @³ëºƒ–e¡© g-ĶmÒ™4¦e¢[GNaæä™$»â¤ã)ÛA35^iÜÎU‹®ÁÖ]I¢¤(ŸÝG^a06ȧ׉€’Kçë}è¯u“ÜÖÆ«Oîæ÷¯?ÇöÔã½Oô2Ð3Àš1k3×_v-ÉTšÝoïÇãó#‰.®årÉŒy=uWp%iT€Ãôºé´õGð‰²ˆ+/§Œ%•`dt4MöíàØ»¸ñÆ£®ë4M“¡¡!êªë¨«®#28€eÙˆ®ÃÑ“GÉ- ..f0:B&máñIì=rY‘Y¼t!ÝMŒœNÒßšàÛbß®}|õÖ¯3oÉlpH&”{+q"€ë>ö!>]þyf_=‹¾hÏï}Q’ÕHÒpNo#§›ðú hz†P(‡¢Ü´aÆá÷ê6kšF<àšK¯áL¤Ó2±]›X4Ê[MX6ïR2CQDE@P\~öâ#\}ñr=!¢mI2*¶k±éÙç¹ëËßåÒ¥+ùö—¿Åu¸Q’P¢Þ´—²¼ –-¼„åç^Š(¨Ô÷4°ãÀ«È‚‚Wö’QU rŠY6cØ÷""2QÊf’4ƒyçÒÚÙŽª'p1]‘V­Bb‰ÉD`óߊ}'/d2™d"‘À¶mÖ]¾Ž¼PñD ˲@yyï+TK ÄîrPã699>z"#üü÷?ç‹ÿ¶Y ó³Y Sí§¹ûÙyøÙ([Éç6|žÇù÷Ý÷ÙðQŠk‹xíwÛYyý•\]úA%~LA'¥§ÉÍ qÍ’Õ¼üÆNFâQ‚!/"ªš¢°¤”ʲ1¼Ñö9嚎A8PúêËpl‡ááaâñxZÅ¿[KówSc3gÎLîß¿š,ËS***„éô±m×6 –e’ŒÅIqV-]Í{bx,Â¥!d¯D[k=í}Ü´æ#Då!ÔÜŽ ð™GŸ`ù‡?ÅŽ—g÷Ö=ìß½—­[øÙ½²{Çë{뚥cöéLºx*Êë9гêò±\³ðJv¾½‹æÖF$ˆë¨ZÛr¹úÂË9ÚÑÄ™¡^<Š—¤ipóÄÏpuåRÒéo¼qˆH$òüí·ßþØÙX¢(>ÔÛÛëÆãY7øÒǾDaA!ñD Ã4p%7÷½I"gùµ+qÛáLkG)¯Ñ.Ÿâ…ößð©Ï~Š‹'-Ã09øÆ1v¿¾Ä± çL¨æÏnfÓ}[yêé_ð¹Û>• Ê€ßúÆ7Yº˜)ç7°xÖl~»çyšãsÞ´1uÂ-Hr.³§L$ei4uœÀ'yÃ1( Žç õ704<Ìé¶ÓH’ôãwÒú®+Dî¿ÿþ§Nºò’K.É^ÿô~¾øµ/"çËÙqµíâõxøìM·²mÏVÞÚz ¡J TâÅQmÔ¨EÉÄXx%c¼¼¾s{vîCOš`gßá )8†‹-8(¥Q  SZYÂ]?ü&ðSßF¶d ss™}Þ]\ZµS9ÝM&ù8ÏìÛ‚é€,Š€KÜT¹{ÖøòİiÓ&öíÛ÷Ê=÷Üsñ?àÁœíºîžµk×J˜–É¢ë±o÷>„P6±ê.ùEù|jýgxîågiÞurGíJ\T—úK*™Qy!¥J ¥EA"ƒqšœ“ܸà*^=¼x"A®7„OÉÁ£8œníä¸Üƒÿö}nþñL”¹ˆ‹ÿOj©a»›âŽ­+hÃï !I+ŬÒKymé¯ñŠ2===<üðÃ®ëº ïºë®Ýï¤ó]§Çç̙ӳsçÎ1‘Hdfuu5Á@yçÏãÏÿ-­e§¥%-¦q¼µ™uW®Ç͇îc]ÙDe`‚ ÛàÄ@#ûv½ÎÞ 7”£ˆÌžpmD“ýôö÷ÓÜzŒÇÑÒÕÊ`c?Åó*XV¶˜—/‘L¦°È¥¾bª¿èø5o¶oBAD [%àËï=A…¿ˆD"Áo~ó"‘ÈÆ{ï½÷Gï(ò½,૪úæ´iÓÆÍŸ?Ÿ‚‚~·õw\õñ«@" W‡`(ÀMë>J<“à©'ŸÄN9PÈY LÊD*t0ƒr)™UÈHG$ Ϙ<²‚ ‚€6bbO5ÙöÝ\ѼŠÁá!.›¹’šây<ÝJKßNL-‚ *ØŽIÆ•yjá/Y;n9ñDœm/oãõ×_ï 3ï¾ûîw]ðž $æÎ«nÛ¶­eddäz×u),,dÆÔ„Ãa¶¼´% AÌ.R02&o¼yˆÊ²1¬¿r ;E_K?¤\\ ÓÂr¡@à…§~MÍÜé<òµ‡È-õQYSO&#©&‘E Û¶±0ILaO³¸vÌQ'ÇPcIž?ø+úFÁÑEÛ5I9÷]ð||üÕÄb1öîÙË®]»Påú{ï½÷È» üG.ºè¢ÖïÿûøýþÅš¦‡Y #>úL Ц^Ó@Ó–8–€‚.®×Ýùs˜¦Ã¢[1ïÜy<Øû®/½ï-¼‡ü@.ûöícÇŽtuuÑÖÖ¶k÷îÝ7†ÑX®ëÚï(*DQ¬Y°`Á'§M›v‘¢(Lž<™5«×P.d÷¡Ý|ûwòò«ÛÀü£èþÃÉäüó¦ñÆ–ƒ<ôíðð&ªÆ) qüd3Žå`hæèËkÜ$¸ûö»YÚ°Œó«f޲é…M:tˆ‘‘N:õÊ‘#G¾gÛv+0¤ÏÀÙîqßDZvîÜùÔÐÐÐðù矿jß¾}Þ¦¦&–.]ÊÊ•ò¿Y IDAT+Ùúä˼ºÿU~òóŸ°e×VÒýÉlKz Â>Åþb&Ι@þ¸fν¾þvl ô¸Žë€¡â ËW,çæuŸ`Ù‚e`ö—·ñÒÖ—èéé!NÇßÔÖÖ¶‰,vpÎR×Y÷2Ê€±@à‡Ãu3gÎ\SRR2Þ0 ÆŒÃòK–³lé2DY¤o°Ÿ_y‘-;·pðíôtöàÄœ¬Ky !m\#›†GÁ/®.äÂóæ±ê’˹lÉ(+.Ãu\¶oßÎK[_¢µµÓ49ÝÒÒò\,k"›e8t“Ý€¥»®ûAœ-‘l|W0 ¡(¼‚ kkkçÔÖÖ^¬(J¡a”””0wî\.Zrê'üé9=´wuÐÖwŠîþ>* Âô GE‡ŠòrêÇN fÜxÆ”üy ¿µµ•W_}•Ý»wÓÕÕ…çöôô¼ÒÓÓ³ÛuÝ$ÙïÎÙ]gƒ£0,÷,ÄõW€?× €’Qd-Cðx<᪪ª9åååsdY.VUEQ3f S¦LaÊ”)44LbLE9ÁPðߣ&Uú#´oæÈÑ#¼ÝØHgGétQ±,k(î‹D"ûMÓ$ë–)`xÀ ÛúÿÐÿÏÀ(‘lgòFÅŒžÎë"Ȳœ‡'Íðù|µ¶m5MÃq<@Üœ ¡œDQ,Ç&™L‘HÄI&“¨ªŠã8H’„(Ši˲ÚR©Ôád2ÙdÛv”¬ëd[:DG!$É~oì³iý€ÀŸc>ÿ¨èÜÑ’3zí'ÛÝx<OQ0<ÇçóÕʲ<–ìfÉeYž?î#°, Ã0EY– EQÒ¢(ݶm·†ÑnYVdT°K¶£Ëmù$ÙOéÑ{ÎÊôÿiáîàáÏã¾àèo`‚—?õû0úëE1(ŠbH„ëº>Çq×u­°.B Hº®›cóç/У u´¤G‹:ú7pΦãûËãÿF·Ø-kIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/script-open.png000066400000000000000000000127331217176075400250460ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ 7ÿ¦:[IDATxÚíš[Œ]×yßkí}öÞç6gÎÌsçIQ’%ŠºRŽ$G•cǵÃHR4q 0úRyl¢úÒö%iƒ¤p€´èCª´–ì8…ãX‘\E¶,*4%ñ"RâmHqf8÷™3ç~öe]úpÎ gÈ!5¤(6m²‚œË>ß}ßÿûÿµàïùÿ?ñ§¯ýžìKcm~¹2¿3ðÓ£ýÅÑQ×ñ‡ŽV“ÙÝ÷>þÁXßg~ëÚϺÿ/øg¯ýGÑ×=q?WªÌ¤\o´·Ð?êyÁˆ6f8tdÓùÑŒŸÝ¤²™|ºè$:b¾v‘RkŠ{3ðSÎÎ;ûï/¾úû¢;ß›Íeº³Ëå¹aGº; ùÞÑ\º0jŒÎúùá ñSé´— 2~Þq¤‹’”“Úð]ÊÄÌVÎPçH§ ŒàIz²(ÿ¯ðßÿú÷d.Ó•é- æJ•ùkíX>×½£;×7ª´ÊøÙáL:?x™Áv=™N{9Çu]í…¸¾R­µþŽ’3Õ³”šWÈ}ììy)¨‚Òò®rÀ·ÿ曟Øó‚ë¤|7ʤóý— RéLàådÊõBàJ÷º¯ îÚ¿¤lÇ©ÙÊ*­yºÒÛèËíÀeb¬Õ$*$±®­ ôÜ• xùoþóÏ=ºÿg_Ù±}Ÿã8ΦïY”1fë¬-BZIÙòY*á…t?;ûÂmšèõÏi?ÃæÏøTÈe‹Ïô÷Ž9RÊ[ n+K[Íå¥÷¨Ç%ºÓýìÞv)ÊDÛNé«ÐJè¾Y}jHáha-Új¬µHä¦inEûµ-¯”œ˜zWºìê=€¶‰nA'+’a4¬ÀÞÍ 0Vƒë~†élKû‡¶wÂF±m Bp8­¸I©1Ícc_"Re,²Mb)¶ó!ÆZ¬QïLîÖÚÔœÝ4­µhô:N¶Ø8«ImŒ¡–ñÝR‚Õfƒ[ ÊJ@¯²~çõ»W·ÝuÀ(“`tB”D4Ã*Æj”M°˜ëZ˜Øü«¿ÃlÚF?ݸÄgAE”´ˆ’Ú(¯•Xbb¤p~q@‘«™h5¨»ÌŸ°„ЊëÄI„¹¦~íj[³ Ð+1B¹n·5( …ƒÒún`?)‰«(ia7Sb˜NÁ´wÞvÀ0V®e6ªý↛òw²”Q(£à@j …ÄE`֘߃étm5¶C„ú®·Á5Z²·Í³PÛì.ÐZ£´Æ‘¢Cp¦Íkïkg‡0ªót¼›`íÕ^«JO+Œ1X«oØMÚiÝ&IÑy— ;¢ÈCÜ©{!ÚÜEÔÆ´ÑM¸ 6h6+H,µÆ ¥y4i'A˜^àQ(>„ã›`5R\íïÆvÊ ÃJ·[%V´IònJaÓ©½ÕlhTËÌÎ^b©2O3²á R7P·Š(i·*øÞ9 ÙEŠ©½DÍ—V¾‹izì¹ïË8~úê÷kÑdg×;šuð±÷´_³a7%ÓO €}ƒÍNMÐJbZ8è” P,2:´‹B®¤@Û˜ÄÄÔg~ŠïçhÄý\œ9Öi‰ :œÁ­^`zj‘¨ñàÓ¿ºAZÂ:€D¬ÍrmV`[97,Æ; À•‰sÍñÉÓÕsg– N³’®“Ë“±óHc‰Ô~"3Má5Zƒ‰ÃD1êfà‹¿ŠhzÈL’Z&[Y&-PðZ,L!¬} ™é”ƒÕX«1B°žiÄZR˜Ž(jw±6~*,/\yäƒ÷ôÞGÈ™sÓéçžþ¦g›¼ÿú_óµoü——Ë4󃔧ǙúðMt Éf24—šÄ¹ƒ ìz˜@ºxKbò8åâù+”"¨i±!…µk<#0´Út4J'kä%Ú“é•íuúØöGo~ç½rÚ#³}¡Öœ>wž©¥*ãÎóßú#÷ì&t³Øà c#kœcç`‘§žxŠ}÷:3CóÒ"/ýé_’ÛÝC×ð2£Kôšær jAL#¬“’{ý¥ë¼A­2½N:¦ÇÕ!ÖimÂdå†n)Ž}øã™W°ïs÷2@‘#'3-+PZĉëÌ~t“„„•$yz‹%†ÞÏÙ÷ÏÑUj Ö!îá•ïæR`Ù÷3ýÌL,Pp+¨¥IááyJÕIÂ"Ž«yôùä×|ÄõÿËŽ]¦:íÍÊ«’Gu”¡­¤BK76˜´·”³ ßšL¦»ƒbŸkV˜¸|ŽùÉÓ˜Ú2a=¤¼Ð¤+“§6Ugòý“ÔKUÒ¹GÆ}õA$HJ '½Åüò2O=·Ç`a|ŽÉÓK„•˜úJj¥Žq¬ôyú…KaðÞM޲$Ú&D*$ÖQ[b:–™"1c ¢ÓûkáÚ¨Û7D¦—ŽÝ/éM«p‘Vv'õÖN2ñúÛ, ²#©Ö zr¨Ú¸Y~öÿ%]CŸ!ŒÃM'ÁD'(£Âi;Ƕ½—BXl‡ ­d…–ª¶{Bhqéü¿øÉâÙ~‘ÏráÍw˜è;Ž®K¶øtùƒ¨F‰KαÔЉp"òÝ)zºÔfç°D ‡OÍóÕ¯>ÁèX7§O^æø›uîݽBoWDn,‹ =ÜŒ¦Ø7Àç¿ú]}T[+¼ÝU¥k´Euê~}V€^;0BQ ÖºÅm9Ø—Ê“ßp3™¥ر'‹_™cúØ–æqü ~O‘=ï$å7qc‡¼ã!Ê+ȼsì"u§ÅÃÏßOßè0)˜#·(Ï” —³Ô³|\G0¸ë¾ükÿ\÷Ðæg‚ÖÒŠ›mŸÏÚµ´nŸA¨Ž#l°(„°T£EBU¿j¢ÞN Ljöôfç\3?ÍbÓcÛ<9¶“ó{RÐ×_Ài…bŹwNàÒ….Þ½¤yúòèÓçcçšL}8ƒZšÃ ›ììÉ.ZòÝ?HxèÐ×8øÙŽò.QB¬BLÇÕY ܺ#zÚ¶˜#%-U¥.a±7=»)'gÇí‡õy–?'¯«D•A²¹YLõ»úòœzû8G ½£9¼‚îûw ’~Þÿ=½gß-sìÍL¥AéB‹´µ¤E@ÆoQè Ù¹ëažü Û5´é)°µ¥ZW§;d»šmŒ°8Vb;–§‹ ©šTÃÙ¶_°æÛŽl ÀòÊô—N,-ÎÓ˜Z¦š®ByŠÓ3eRy>e·‹¹ Å}‡ž¢'p¿x‘ÒáØz7Ñü §_›Ãцtì0¶MCÖOaµ ÄìÚwˆg^ø¤“êø¸wßhݶÅ×MqžMmÚF;å;Æ©)Û¢Úš'ÑñjÝ\×B·À’©¾œÜ»|žj%¤kl•Zè²ìô2Ôí²·f¸’eáí“,¦ŽHö,™¡E†Ó†f©EʄȬ‹É»¸Ž‹ÕRæÞŸæs_ùà ÚnU¶Z QÒ"Œ›‚_]½Ù1”‰iÄeb[kkáÐÒuÉ2ÊÄk¤g­½aà7`ªV+M_Ïe2R©„ÖÅ%.§ Û[Èù& K.ýÛ}z‹5Jµaè74q¢)ÅM„±¸ÂÃëd–nàˆ<þs<óÅ?¼®·«Ñ&Bé­RNŠDG׫ÆjRÒ#lƈ´DÙ&qÜê´;:.àÕÏ8Óæ¯`¡1ñ» &Êtgм{â§H’CÔaæ‚ ¸}…R,OZ”Ï—¤LÙLЦ…g$))Á«cñQÒ M‹®Ô2žùM|öwׂ^­ÏD‡WYÂÁMùâ8ÜÈàÖblûsQ\¦¡JXkq¯)¡UW éèÞ á]@™ä7ÎOœéÎeóä¶ÝG­´HS¹dý¾°´àâ!‰É¥=dœ`Ý>~r|Û– Xd0¡Á1%ÿâ7ØÿØ?[7ÎFí Í&×W$¸"…#Úû׊kZ¿M«Ý!‚ΜtäïŽßã­x‚ÓKÓ_ª6ú·wïq+åÓôf$5b¼ì6ªóM¼¨†çø~€iÕ©–›RÒbq"…“XßCÚIèÖçøÜ¿Æ¾G¾Ž6í4_½9òñw¤tÛVß&ï×_`Sk~‹“Þ„§úãV#ñH°Òçø{¯Ðc-2¬’uÛÁ­TQØÀO"„c1¾D(ƒV†\àâºY”qiTZX]§·;ÃÞÇÿ)±ŠnxQézÑÓ¹Eb-b³bÐ4…Áì5ÃÎú¼r½–Ê¥>UÜZ}‰•…ÓȤ@(èÎ&,†ÇqI; [”#ð\ÖàH‡l.ƒãXé B…K‚0uzGÂIe¶¼µa¯êö»Ã·*ˆvÍù¿6Pg|,åJch¾¼"û2P˜«¥J¬n"Ä¡AÚùl€µL‚kS¤d€ëhëÐjÔ!n¢u„Ð cûžßRÐkýz 牺sìf×AªM_O‚[ §Ð÷ƒ`hä7N½ùÇÝêGhS vjˆF‹t#"È{¤m“f#AXpS>Òq°ÆÄ ¦"ˆñ2‚ìÀà ïý™ëÒÛ`n9èk/ÑØÎ| ×î±ÆöH¶Xnðµ¼ræüÉR£Þb~Z5VFAââË)-¶¦ -HáḠ‘R¢¢¼~fÝÛörè ¿…Ÿ)¬±RÛÒ¾õ Ûzþê…'g]w·œ5Nhÿ}-ù©›dÁöîÚ·ôÆáïO¬˜Ô]çÔj†¸YÁ$.QVâ™Ï‚>®+ÂÅà"¤ƒ—ÎRÜV¤«8ˆ—ÙÆgý<ÅþA„q·~Tn::ÁÞধµemGú´O‚o´ïémIÜ3²çßèpj´’úlØŠÒâ¢pаáXA&ã’Îø¤R>éL™Ê‘òóÖIem¾k»t½4}ƒc¶õßôv79û¿¶ÝŒ?Œ¶³·ÌdGCh›˜DGz\=¿%vŒí?wö­¯wåÊ_O]Ûý@A…­ÝêÂv]BJdÊ‹­M)Í€=×GJ‰ãJšÍæÒbyneA_©MVÎGª¹¨¸i1J!ÒBH)œn`Bñ_^üõ…•Or0¢€ ø€×eÕ‚·öc®¤Þnà¹\C¸rqââÙ‰é‹o9räØ•Ù‰wS;瞸ÿÐÈÏ/7¦\饄8κ›)ià ðâ·~}¡|ËŽÐú5s¼e†¦+ B`èî|^ÆAÞÉËe!Ä™8‰Þü£oþþÑ —OŸ=qêäL³ÞŒM¢­ñÔè ”R¦42åZ!×u:!]érBñâ‹ÿd¡uË~ÀM@¨W€¶ ¨µÚd0Z«øcžu« Œ[ko 86Ø;¶FZÝûAÚïJy^á !Īӽî9Âzõ%sdò­øžz¹®nIm ´†¦g:™C)ß÷_yõÕ—FGþ}ã‰Ï<û`¾+—ëïÚ.…s#šÀ%àððÞPïØ¹=7“M‹èp¬¹ÚVg@H¿µd_ÿàåð{—ßjª-•ÙíæèÐÁ´òÀЯµ‰Š«ÂФ¸¸ë?ý»?~éÙG¿ì—«%°6±0^ާ‡zÇìŸ%:Áû€¯”ѼÐó•žýÇgæÏMùÒu¥‡Ó\´?üð»á_M¼ÕÜrêÝvÝÎo 2t0óŽã8Ž“­µzîJiüåÿõ?~›Äjÿ=üÄ÷‚ãÖê†úvÆ·ù, 衃é°B®Û8+¤õõó½Wgåõ[&Ú;ÁXZý¡Ÿê:˜v´1<ù•Þ_»ï³;~ùù³ç玚o¿óÍêÑÛù>çNü¨Úœ¢6§¸«6§lc^Û̶”MçƒÜ…£Ë/û“úqþ>­ÕŒû‡õ듯ÿ[t*|?ÏIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/script-save-as.png000066400000000000000000000153441217176075400254450ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ -3øa˜ÂdIDATxÚÍ›Yp\×™ßçn½bˆ•$ˆI‘EJ”4ÖfÑöxÆeÏØ‰—ÌØ²””§ÊN^R©Šó:yI%Vì8~™{²”­Åv,ÉV$yÑh$’).E‘"EJE€X@ï}—sNî½Ý·€§ò0]uy—·ûžoÿÿï´à&¯½{÷ÊwôüdžëÐh40±m¼ØÛÛ…!@ðOë¥Ã\Ïçí³ç»JÅå|x-|mŸ¸>:2üÁð`×¶núEÂúOûïü£;‹Å–ešFÃå¾ûïãë_û –!0MñOR~%a¾°Ä÷¿ÿC–‹E”R(¥‚€þA–– ×nª€Ù¹9ãÚôu>ºz…F£N.—§¿€r¹Œ $NÊÂ6ÿ ׺M ­Ak‰a˜ñ‡='@Ạ–——)–Ê~¿R ­5W>¼Ê[§O:7U€-€Z­J:¦\*Ñß?€iYH¥ÐZæ?Z`%ª•" ßEiAïá.u¯ÈÌÜ k™Û#ŸêehðN:²C¤3]ò¥5BLËtSB´ÖÃ@°Ö]¤’ìÙs›617;K©XÂÿx«k07w 7€J.¦acY”iˆZWéèî¡Pú Y:X.-2ûþ3ìà¾OþìTvOŠ h„0ÐZ·Y_kŽBÂZß-!•J‘N¥H§3,//c˜mÞº—ï¹\xï Þ{¿ˆg;T‡5ÙeÆ2Ýû™¶æeÊå7¨z‘-úWØ3ÊºŽ¹8C¾vf.1{ë¿ýæ©Kˆ( !PJ#„n å ­õÍ Y,q]—F£á—j4õ†ÇôÌ<âfYP4E®\=Å«'Ïs÷?ç¹kd¦?¤c_Ew€ÙKÏàë=£Ô*ŠÁÝß £| Ã@-{¸]¥°E›š¥Å%czÐ ô÷Ó¬\kY? k#ñäû¾ï#„µ+R)RŽÉÈð7Ò@­´Ä‹Ï‡Ô6åÂGø×ª˜]]ØK04)c©nsêíY:ÇFq†RÇÏ"æ5Å+3T|…Ú2ÅPºD£8ö³ôŽ aZi©ÖU€T*Šó–ë¯ô±‘$¨Öø`ì 7`v¾€‘éÕ¹¸t{ó®ýˆÅÙsì›Ú†91†=zÇ_„þ¼Åà-xÓô‰¦s°›}· ðÊ3Ï“ÛÔOzK@zþ^±AJYh2¹)ff7„'zûzCHxKlÈX.µ^ŒÕ[ß0Z%E Û1Ú”x@À© —X¸¢pßæã÷í…}㤕ÇÅcgÙ¹o7—Oôa«¤:ÐŽÍæI‹“¯_g§kòâÏ_aǃ¤Ô4Ëç xž¤;®4éèÍqëþÏaÙÙ AA/H­š!¼Òˆf¤˜ x€J`‘öBêf¼;s kjŸ?pWN¿Ìu§‚µPâê»oШ»åú; ôÝ‚ï^§^Ø~@‡Öüæÿ¾ÂȾ<Ó—>d$w™C!…Cà °üì÷0Í ZéÈßÌú Ûâ>©ˆ )Í*7Š?PZcš&ž7Ë´ZdKv—y.¿ó&²þùtŠåëeººr|tú4 ×ÛVåÍ—Ø2²‰†WáýkpÛ=Ûî÷yâo.“Ú\'ëƒ]ýc<øgaç‡q¹QLM T”§V Ÿ,‰Öú«fÑ*%Jkü@³´TÄq,>ô.¢t'çŽæ’e3<`#–¯òÁÌ‹eI&ïÒ‘õ0u…ê•+ô8/¾ðŸ|x·m™âôá÷ñ‡fùØf‰tóØ9ƒÎÞíìºçßR:©ÏÍÿ=t÷t7…_iÀd5³Öu¥DLz€” Û1Ø´©Rý#<' wš3¿ý€±½C o¦s(Çü˧pd/iw‰¬Tyý>õç·rn! «3ÍÜùe¦ÏèWp}2¶``Ë}þoÐ7è5kµAÐÑÑÑ4L²|{¾DF!»VÐJ£´ÚŽê%Q T ׊+$e¾;;LùÜÿÅAÎýÃ\÷–Èf :}—wΜ¡klWÞÓ|ù[w£p¹þQ…‹¯]Bf˜ìKã<6d™Üûvø&RÅ µõªT*¼ðüs\<÷÷âtï}MmÏ«K_\ƵR!³¡Y¡#/Ð:Z7á¥ëù`)*õ"‹—ß%+ŠÔ+UpfHåx饷ÙvÇc·OAµHàv#üi®¹Äì¥2ù Lýª"oeÁ,±ùc£ÜýÉÇÈtN¬ZK©X䕸{úzºøìg>Å÷Ïžeëø6<ÏŶսGDíth´¾·Â7ìÅÆºAi8®142.†e3?]"•-’..rÕêe´×b÷®^j‹5f«e„ªÑ‘›áž[Ë4.Ì2 %}›-˦áVؼóVn¹ã¯Yª¥XªÍ5Ÿ_­T8ûÖ)z:óüÅW¿D&›åä‰ô±T*ãI…ã¤Ú=@k:;»ZUK)0 ˆÀQŒd¥”BÍ$i3.ƒ¶— ÑðjØŽbù|ü@@WyšùE‡MƒE*U Y¨^­c(…m:h#ƒ0r4üE6O qÇ¡Ç0Ì\󹋅N¿q -=>û§Âæ-[X˜_àñÇŸäþCŸ&ŸÏÓÓÓƒeÙ«¬šõßî èhXÔÊ>ÚÀM_FÌØ©%f.kRŽTð¼S+R† ŽDncÝ»oc÷ýiu4Ÿyîì~ñÄO¹}ÿí<òè#d²-ðóâ ÏÓÙÓKOw¹)ÇY# B#BÌè› ‘ õ„2A3›ÆÉÅfý·áÓ‘“älì>ªžK½’Æó³(_R+—qu¤ÒhÃBfÒ`n¢V Ø6y·>ð_ÀìFjÔšÙÙë|ñ+_eÏÞ=\¼pÏõxÿòe~û»ßsû1+•BAó³ñ¡”&‚6Á›`h…2¬Ààd7ǘa*ê^ËÔ¼óö1Ço`¥M–+>n£DZzè4h BA&Ÿ' Ee±„­—Þõ¯¸>Wj%ºåEêÕÙ\z•‘áMÔ*Þ=ž;wð¿ÿçÿ¢oh3u×§T®á´­+¹¾®®.‚(\Iö0‰Ò¨Y Ú2i ¤R4ü¥êBÏ¡K%Ê•2¹ŒKY ²F€P¤$ÇL“Îu …_«a© ½Ãã ŒbZ sèÀ¥¯¯Ÿâò"·îØÎÉ“§),8xÇ~~ü£sú­3<òÍoÓÓÓKwOOÄT¯_ü@FVW͵·'÷aA‚m¢Ù zzÆ(]?‡¬ÎQ­TðËE¬j#­èíX(RÂ&eç@™4ŠuTea5žü4†™F s,/.ÍwP\^dçÔ-¼qâ …°Ç¸p™g~ùKÜýq2Ù,élÃ4[ÔÖÊCƒ”ªÉ $Ájz€ÚH7Ø.t˜l4J*¤,Í\eæÃYæ¯-ƒß@ø‚´å#ê W),ÓÆ²mÜ @ºU¥Étoahü>Æw‘@* ó”– äò— ìܱãÇO°¸´„@008ÂÂÜ,[·O1µc–í`š6ò&œ€Ö‘Dùk’ÀëCáHƒq+¬”©ØdvQÈt#òuJ ×ðE`d8©.ÛÆ°³8"Mj —žþ1Òù1:†ï`~©B¥ô^½B&›c±°ÀÞÝS;vœå¥e¤Òôô 07{÷.ÀÞýwQkx8Õ^ Veþ•9 §§—@¶p@² ÆPØXŸc#$¥BJ*Åég÷®?£¶e‰z­L£r ·Z&›J“Íw`§rXNËÊb:]N+Õ…6K…yLúú¨•—Ù³{Š×gy¹ˆãÃ,/˜ž¹Î;ÒÝÝCOO/ÙlÃ4×m†\/ $´W¸+$|¿$ØŽ©•’Ñ5Rb;Ãä{‡É÷´ ²e‘뉈¦©@ Àòâ,åÒ"¹\•Ò2;§náèk¯S*–@ ±TXàý?bjçn²Ù<¹|'–"¡äú|€V !A›Äï•T+ƒÉ$ÃáF½Ší88މc™Üœ_V¤ÄÅ…9j•"ÝÔJE¦¦&9rô5Ê¥B˜l¡¸¼ÈÕk3ì¹m?]ÝÝôôô‘ÍeÙal ÖX*lÕkµZ›å!4œišë7CšP2þÛ¶^;ü*–eÑ?ÐßÞ¬j HÅʯ-éÌg0-›lv‘;÷ßΑÃG©T*Ô*5Ò¹~ÃGS©TY˜_Àõœj…ßüö÷x¾Â|ïýã'ZØ8¡I)‘J¢¤j®/¤Àã>_£•ÄI¥èèè&A[WÝœ­_UØ F´„F •Ä4-úû#A¿ÆS†a€ô÷u³cj;JöÍ#<øÀ}¼zø0µjBa‘@AÚqøÝï_Â0òi˲1Mk‡×–Éc¾Bk¤RˆDy‹ï—R6‹¡Ž%„¹lœ h+#h…»@ªxꢑмªºåý½lŸÜFÃõ˜Ø¶…¸—W^}•j­ZÞõq‹_=÷†e;Øv€ax7-u+)®6Ú‹d屿êt^­´€! ´ÐÍ2)„@é0Hb°¤µfpS?·Þ:…/Û¶ðЃ÷óò˯Ҩ×) ¸žO*eóüó/⺖mcÛ-Ë'ÇÙkí!XSø(%[øÖ@TÿƒMTöZÀC–-ˆ\¿•û´ÏõPJ3<4ÀÎ]Ãó&¶måÞÇß¿ü2ºG¡P ÞpI§~ýëç©Ö˜¦P!‚k’™‰DG4ãÓm™.¼žN§šm®ˆ¼Qµqj ^S¡ØT+vnÄVQHÝòNÒØ¾}’/}ñs˜¦I6ŸC“Ûx饗q]Ë2Ù¹s•r‰K—/ñío}“ŽÎNzz{H§3X¦ÕrýĪ)¸n’u\Ÿ¹Îó/<Ç[gÞ¥áz€N5ÙD°™l¾é•-<£A­ÃÄkXÙ%yuQf®ç1¸i€Gþ Žc‘ïÈ–Ü{ïÇyãSÔëulË ¿¯—J¥Ä¥K¹å–I:;stwåIÙ¦P(é"ƒ2pQÊCI­|„H !1 …i(¶lá_û[lêïaii‰jµJ£QÃóxžKàûÌÏÎP\*„W÷ z#$BVX7÷°†7„ ÒÐP?µzL:ƒïù£#CJéâ2Ù,žð̯~E¥êbš&¦e7÷H% ‚)e ¬$\>™ÁãgÆëI¶è1yÛ,JaFCC,V$vcý^@­Þ½dÿí{ñÉÄÄVþâ_|µ)ü…wßepp­O?ý år a˜‰,¯u;c££áKRÐ&¯ÏjjÎ÷ýµÉÏ(¾CK°%ïQJ£Ö hÚ Å„ÆÆF8°A Ø6±…G¿ñpKøóçÙ4¸‰JµÊ+¯¼ÊR±L6›Ã4̶…(% ß÷|C˺R†Þ‘tûU9@ˆ0«¯Ø ’,c-Ȭˆ£$VκH0i¸þŽpçÛ ÅÄÄiþýƒT«5Þ»xT*nWK´±+i©°~ËUSèd¶Ã!ÙÓ† 0Ú¯¯üLìá$¨åIñÖß ¢ºI"ÆÂßuð@Óí“Â;vŒÞ¾jµ*oŸy‹Í›Ç0Ma˜«ð„Š71Åæ Ò2Î=+…3 ˲"…ŠfBVIº;º_&2¿Ö ˲°,;Ü~§¨ŒÇ•l¶Ãcc#¼ó¾/™˜ç‘o|½)ü‘ÃGpÒ)êõgμÉèè(éL'•Æ«±{¬Ôdœ¯Lz+C/ö¢dB ƒ a¤Võj†¯”N¥‘J"„>Glh§h³›·næîƒwâ’ɉñ¶˜?zøJ Ëæ­·N3::J.—£«³Ó4šÄêZà)®qì¯jyW¸3{GÊÛ]Ú¦V«UdH¥cï Ÿ·îh,ÜЬؼy”{îº?˜œØÊ£$„?r… “vøõsÏ1::J>Ÿ§££˶ÃMJZ·¹skL.&ð}¤”ø¾ëºøÑßq†_iñ¤BLÓ Lä“&I ¬Ó0›[åLÓ Ãb=lÝ:ÆÝw݉ïK&'Çyô‘o´ ¯!›IñÄ“Oá¤Ò¤S)2™ –eá{¾ïµêóŠ‚/QâøŒ…‚`U%ˆ­ßܵÖìñeDx¨U•ÀI¥ñ})À$›Í³¬×Á;¦¦:ï¹û`èö“ã<’þÈ‘#¡ðÙO=õs K —Ëá8NËM››¬t¢TÅÖ‘hMsj jj‹-_ëøÑõäÀCµJm¹n½éÑZkõܬúîwûôìÜü¦†09 _o¸=r„£GŽ‚d³iž|â) ‹Ë Âìl;ΪÇœ­‚ÖFŨu]¾}þ ›ÀheoÐ ÑRdBàÖ¯f¢ïCà¹.ét¶"žçÞ˜ûîwûtww÷·§§¯“Q¶…?räZ ²™4O<ñ…ÅÐò4Z«žû¶ë6¨×êÑâD«¿AÓ¢†a4Ý:vùdr\Ù†ç r´½iJ&^%%ž×ÀqÂJ~‡±Zßÿ¯ÿíS]½=•Éd秦>Æ—¿òej ׎áhBøÇŸx’…Â"fóç, ¥Á÷ƒ¶nlÇŽ2I€#¥"ŸË’ɤ›1¾²¨ M²Æ8Á4Íf©nݯZ¥0fˆ” ­.À÷='…”~»~ðƒò<ï;ož:9x×Ý÷ùµ¿ì/•«¼v4´|ìö?ýéãÌ/,†™4rgÓ4µaJ*eŠHã¾ï³uË(;¦&›@¨)h˜(•ÊÍøM*a%×{FR ÉPY]6eT%ÚËp=”DyÈh*àÿý‡‡”Tÿþøë¯Ý166ÚÕ™Ïrþüy®]»ÎkGúÃÎdSüôñ'Y^.âØ6¦ib˜!"›Ÿ›¾”ÍX×SŽsoÑ5ˆì mßnÒWÂä8)&ß“„ˆa4[êxÿ3îEøK—x>Q­V›,ÑêvÓÀ~üw‡*åÊw^}ùå»¶Žoéüø½÷ræ­·8wî;ëîØ¹káégžþÙ… ï>=<<\Þ¾}ûâÁƒÝ¡¡!r¹œá8Žé8ŽiÛ¶eY–‘ËåDGG‡vÇ0MÓ2 Ã4 £yB˜‘ð¦ÂB˜‘ÐFØÝŠÕƒÅPJ‡æUÑ{åû¾j4Âu]­”RRÊ ÅÝÀu!DÛµÿMð9=ÉIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/script-save.png000066400000000000000000000126541217176075400250450ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ .%'˜~P,IDATxÚÍ›YŒd×YÇçÜ­¶^§{ö™žÅËxìlNb‡° ¡+ŠB‹ÄE‰'žKÈKyEBB<€@y°P'Ä!ŽãQbO¼ÌâYz¦{zïªîªºËYx¸KÝ[]=Ý“)%Ý©ªÛuï=ç;ß÷ÿþßÿ;#(½Þýîw?Ó›ú³0J”, œ9}ª===D€ øézÙôŸ(N¸ô÷&:íÍVz.}Íf‹™™Y¶¶¶ÐJã.ž#ùi|) Q²¹¹I»³…`­Åƒµ–›·æyíûýáë*`Ðëu©Õjlu:ÌÌÌâ¸.Ú¬5€ó“_Ak¢êWqÑënbTŵyúJQ—!®›0wò£Ô‚ÉŠ˜ìŽë!Ò…B¤÷—1ÂuÝáÆhÞõ®÷0{ð ËKKtÚ¤øÿYõ|…‚­Í5nÍ¿Éj{X;85ê>[ªGØëà:™ÛfëÉeš·¸ykiZ\øØo§ÞcS–B`ŒE;˜|†vÄ$ÜáÉ´Ûm¢(" C„Hoj±ôØ…Å•‘®´_7×ÑwßâÒ•«œž{š·®Ïsú‰iúÝëÔÄ +Ë‹lym|!èÌßA.Íóàìø4H´&\y¯Û¦¡$Kó¯qýÆ~‡Cb“ÞJÑMˆ’.ãóøÏ|®xž)¡>ØÑ<`Œô€a7ÊD)Œµ@îxw7ÞänÃá=yˆxe‹kýÛ„Ëvk“Û×o3}|†Å·^çСmÆÌÑ»s‡ñã3ô»!Ñúo,/ò³Ï=ÄË/\æüÉEœ^M“Ð{€â/H¬ Jù[“á”­¸þ°!öA²b)0¿‰µ$ʲ±Ñ¾g"d%^Å›žD!XÚ¼Åõ—_¢Ó²8­:$ ³¹Íjÿ*+··9r¤ÍÍ«‹´o¬¢ý>²•pâ`YÑÙfþZÄ‘f€ ÀoâÜ…Ïš)Âå• ™œš,&?¼€ål¶G¬‚`Ù´6x¾äàÁì^Z6ãE¶¢Kÿó}nNÙ‡³gÇÑoÿà-t- hõ˜œ4œ Ú7“µ˜¿w•ÏüÉÓDkšÿþ·+D§îòЉ„°3Žëk&¦óñOþ^m|ÄS-q¢ÑYÈŽÊi¨˜½1Àfù2wSr­ÁaFÚhÂ;³ÎÑÓîê î¼q™8ÑÔLóÐN@´…B²²ÊÖšâòâ|ô,Ó'ŽoöY½ºHoyîB‹þfƒÀó8<÷Ï~úŸqüÖ.ϸþ0úçLÐbÁ²7Âf^`mJ&¬-èe'¾·«ûwmÈš Ûz[Ëãœ}(bjBpç×i×ëH'BDmæÛ†æÔq®v¯ó©Ïœåú;›Ü½±ÉÕïl#;kœšòa#'fyà=ŸæÌ£¿62…Uø†RX;˜|Jßá›V„û ÂÆhl†yÈI°°¸4šS»þ6›ó7émßFw,·VçqÉÒfÀÛo,ðñ_ý³GqgéÝ%…ÚXãÒ =ÖæcÕúèUKÍm 6GÏãÁ'þÇŸaáîÊžiw||¢âH 9Ê™¬ÖzD¨‘< 2+ºB0111Ò¶Þ¦W;AòvÂÒRÈQw…¥ ¦8vB1VŸfùÕËH/¦é&ŒµÖ;ß'^Xç¨k1Ç<<Ç# ·8ñÈc|ð羌ûÓ,cd§ÌbmæÍX3»v–Ã&á8ÙŦÈÿÆ@à;#!ðnœp}éejveƒwÅáÙî­6ݱ:­>¶»E´í±ÝKh‡=žãaœ&VÔ‰Ì*sÎñÁg¾ˆãx÷%‰…JedPà\@O>C‚MË©%Š’Ô•lõ5]æ¦Ð #¢Fa«·]Œè°½²ÈÒÍmذøÝmd²M€¥é€€õâx™sç?Àû?ö· Çv<ã^‡1¥Teâ2Æž< ¡¼š*£ªëHî.ïoÆ'–5zÝ+™díÆmµB÷1´ðlˆJºhã0xW kuSô:ëÌy?3ýK« °rßåöÄÄ* WÊ5L)5Zö"B‚ ’æBg‡#¦§*! ¥ ínãh˵7¿§"êÂGÖºltbZº‹#56ÈX8¿>N¬=Âö:ÜæýÏü)®?þ#«Â‰ÒÙª›‘¤Ç˜ýTƒvPNSac, ‹O5j£éw7é$KlÜ~ yîmWáY—š1ŽÄs5X¨M|¿…F û}<³Í̉‘^‹Uu³´6ƒÚ Äd .cÍ~ªA[­ŸE*2Þ$R߯MƒM’Þ"Þ î,E]‚8$I¦ÁÓHà»M´qèou@oc8úÀ'ÐÚÀhk3(9ùpAdöS ØBù1E)lŒ!Q ¥ çÐéöèu»Õ»4 K·.sçÚmâ^ ‰!Ð!ž0¥ÌÒu$ŽãÒOB’0DkC­y„ƒsÂ|/w—W,uyj*Gò/§Áœ ˽%1v(BZ´ÖÙÍzV£VmJ¨.‹: åtúk$½>a]ÈOK\·Ž#=Œð®ÏÔÁi¦Îј8Í©ó?ôj?¦¼Q¬PJ£UÍ9%ÆŽÄwXT9µÎΑyƒ&5:û4³ã'éïÒÙ¸Fok Ǧ«7êÔ›S¸þ8~m¯~ÏkR?ŠÂC'úÇoY”VÈ?mö—ËšZ"a¿‹çûø¾ƒï:#ÕU¿vŽÆØ),k4:ê"„Åu=¤ãg $Áé`L ª÷VT÷'¿¹&-Õ{½^eå´Ö©†±W1„  ’ùwÏóùÎKßÂu]ffgª«omI ;„‘b»HÒÕûˆL×ß9¹ò=‡Ûh¶ôœï_¼ÈÆÚ~ì¬÷ÃlÁú dÌYHI…|å_þ )dº’RiFÊ´—¾§¼ÀqÇEH‰#%R:H)RàY´°*Ò›.ÁKe¶Öh£1ÚãK%ð$fÆÆÆ&QZU,Yt‡öNƒ&­±Ùj´Ñ8ŽËÌÌ¡l¢2ES!ùç¬ )¥„¬“$†Ž|…+çF¨·;Ôh;ÔâÊÒš6QJoùïµÖÅJÛ¼QBŠeûÐE%`Eæ¹mò®‹E¡™;íèI•%µ‘ä.ç÷Š÷áÐÈõРޣ³:¼'*[@ ‰‰,Ò¤cÓ ÉÉÒðdîõ9¿·(yOùÜ(Mo×Ég8T.á Q{ŸK–öL18Cš^¬ sýöYqÝX„¬ KzMŽy&È1&G6™“–БõøléÒóµZP”¹"óFSÑÌ]Ó`ØÜé*骴x„H;i<øàY~ã3Ÿbbr"›Oj¤"îéÞ¢áÔVÌ¿:¥.T1q[ˆuÜ]¼Ë×þý«¼öúÛ„Q ØQÓƒ­7Z…W0Æ‚±ûEíð éê:“Ì¢8æÐÁY>ÿ‡¿Ã¡Cð=ïI|_âJ‹ëX<Çâ9 ¥ÁÚk@aMŒÕ ˜£#´ Ñ*˜£c¬IV!ÐH¡‘ÒàHÃÉ“Gùƒßÿ=ÎL±±±A·Û% {ÄqHG¨$aei‘öÆZêAy&Ñy°ÖXšb ¶ØÀoH ¤ZÍGkÅöv„‚F£Î×þã¿xá… ‚Z‘úS·´4u~ë7?Ëøøx¡ÏUò|¾¥”)†ã=Æ'0>1çy%Æ‘^çzÛ[mÆíÔ õÊ𞪰4 ´¤1J²ÖÇŠ8Nrfëë›Ü^\¡Q¯•²@:z½FE4µ&I’‘¡V.bÊ 9Ð$q£TÊî ͯ”…„—È+Aǘýt‡E%äTXJ™…b)µ˜Êf„$N<×Åó¼êê‹ãÈ™ÙÙ±)¸D)•½¢Ê ªt×–ÛùCJÐpf»'Ì™W9¯—³Bni[zÈÀKÒÅ0vpÂ{ÓF£”ª„@ÙåËž_Ÿß«\¢çâm‘$Œé¤çÄ@!»û=j32.‡ÉK.—+¥Rš+Z¥H\ÄÜPÑ–z Ï(ieݾ"kçҜփ–ýÐê¦ ¨sZ6ØTT…³g_ÀRGÄa1°b"&5¾”©ÙÑ–”¦¥’$)é ƒÕÕ:õ޲ÛïÀ!RT·»t|+”9[ÑðÙª)/Ïÿ9Õ-o˜(€RëL©aL!¡íЋÛBd¦ÐÃ^V®é¥(Y=?|Mîi'h°ùÖß}èùs®/R–‡z`:•õä„DQ”~/ÔG² ¹€Yríáš¡vRÊÂðùw[Ú¼QÆ)„(õL6iÎDÌ~ÚãF«žHfÔ¥•Jé­RŠ$QiLëº|u“BY^3;@o8ôr|6Vª¸ŸµƒìU<7 ÅZPCnf }í-¤´·àóÈÛáFë´Î:É•åò”g€r–fže÷Ë´Ü¥Òµj‘-¤±ùXÒçÙýl’Êã· ?6-r„ËbEyõ’@å«›aÃÎ]&é`T’”öU5ü²Ë—0ÿ㤽É2žØ¬ÎgG:ÅVùT¤q‹ßÜ{ iY()Ô¯l_n**Q7ˆÂ$‰ùyĆ¥q) H)+±¬”Ú‘ òÕ/ SÔø:<ÌŽLà5’$Fk84-6÷Ü QæÌÖe¬ÒíòßHž ,ß´\Þ­•Ö[yËJc-8ŽSäõ2ë,¯v©R ”[ô.*:_E (ê#¥ƒÑ©W…ýÞÞY ß dŒÎ¬n ÃQ¢D¶›D !ysB¬QƒŠYéš$I1ù2°ù®”¡Ú`po10äÐÖW[ÚÏ ÄQD­Ö("Ž£½™ YmŒ¤®ÔR¬ÐÙDi0ñ<¢(¤ßëgƒƒú>pš9’‚AÊ’÷ØvŒª¥”ÄqµžƉ–iâ8Ä÷úý^I–¿‡â$úvSØÇËà2HC¢"!¤Ú€%Ž“J5vîÜ9”N‰G™àhmh5Ôëµ"Ƈ3€*hª<Âú~Ž?ƒßÒvSƘtÕ$IŒïhÜÛI}~«³n[cSŸSÙ&ÄÁ€rÀJÏ;Ž´RJ£qDfñ$I˜;yŒsŸ-Jàb¢)8ÐélUb|7­¯L~Ê‘‡Êδ™žwY`@?k”¤žmä½ àsý^÷%kí3­±©ó6“À'£˜¥x\Y^¸Ö¨»wߺ¼­6 Ãì?ZPÙ·[vãrœ—·æ— ’ÿ¦œ&¥”xž[;ùCòp ‚ èOt»ÝBƒj·v/ØìDû½7°xfsJYìÆÆæ’Vª[ÐÂT°ìö{Ýà•W^YÎ&iGÕñåï¢"Zì®þæ0üß÷ÅÊÊÝTJKL… lomb-4õ¤ÿÃ¡ß ÛÛÛíïŽÊúåÏ àp˜ ÍÉuázžð<Ïó¤çyÒqá8NÒh4â ¬› !ÂqáºnþwÇ2}!¥ÙjŠÌ bµ%-ÒZk­Öš8Že†žRÊ5F£•6Ji”NŒR­•UJÙ8NL–mlG6Žãm£Í›Ó\~þùç7žzê);º¡—~—€ûÜsÏù.\p…²Ñh¸A8žç9¾ï;¾ï;žç¹®ëÊf³)ÆÆÆ¬ïûÒqWJéH)‹w!„“MÞBH!„“MZ¦Õ­5k­56]^“}6I’˜0 EEÖc´Ö*}ÓZ)¥òw¥”VJé$ItE*I’PÑ=sæLøä“OªÌí¨êÄÈ̼,dÜÒw/ÃŽòûð‘ÿÞÉ>;Ù!KÇFž×f€ÎU:’}qöfï*¿wnwÉç+U΃bT{~èХɉ¡krµ¿ü÷ V¸§:ʳ÷8F¹˜üžBX›&YU´*­¢3beËçä.+.Ká¶›Qí'˜Òäõ.‡Úåœ*]»+îå ÃÞ0ꜼÇïFMx„í.†e»‹¡v;oÊ+_ØÅ û½×~Ÿ!îc›˜ÝïùQ“.¿þûP/–V”ùIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/search.png000066400000000000000000000300221217176075400240370ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½}|Tå™ÿÿ>çÌ93™É$“™Ìd’!!‚…" « ‰E(Bu]­][tû}m·[«öûÝvÛn«n»ý¹ÝÝÚn[k¿¶hëÚm¿Öj¥TäÁº ø€!&3™d’!“y:çüþ¸Ï$“@@Á ù¼^×ë>sfæÌ™s}®ë¾î§ë–LÓd^Èï÷ LàýÅ>ä˜ À‡øc‚rØF{C’¤³y#bÙòU`.€¢(sUUõÈ’„ašd³Yt]oš6¬_·õ}»Ñs£µö¤Qß8ËX¶|•G–¤:§t©ß˜ëózæ‚AϤP§»]C’LL²™4=‰ÑŽNÚŽ¶ÓþN‘ÎÎæXg¬>ï6Lsë)1. °lù*ÃáX] ­š<¹zõ%—\¬Y3ñz=ŸÑud_©TŠL6 †€ªªh.— UU>Ÿèëã`Ãvì|…7÷5ÄÃáð3©Tj݆õëž9ãhc\`ÙòUs«‚Á;§]0mͲe×0wÎl2© ííF¢tuuÓÛÛCâX‚TŠl6‡iH² €ÃáÀérQâ.Åë-ÃWî' PU5 —Û@ccÏ?¿‘×vÕ7G::~i˜æ£Ö¯k>cnœb\`ùŠÕuÕÕ¡{ìcu«V® ¤ÄM²¯ÆÆFÞ>|˜#--´µ¾C}}}¸á@CWk[[ H½ViÃoØØ}^_Umíä’‹æÎ«œ~ÁtwÍäjÏ«eÚ´ix¼^2™,úÓFž[¿ÖÖÖG Ó¼ïÃD„÷•Ë–¯ª ƒ\qÅe«oºñ/Ñ4Ö–ö½ù&Ø·o_æÅ_l9ØÔtxèÒ@H:ƒÊÏ €h€¨€Ã:ö“>~å•S.¿êªóf̘ÁÌÌbÚôi<÷Üž^·.ÞÖvô‡À6¬_Ïþì8ÅûF€ëo¸ùÞE‹Þ¹fÍ­Ÿ×KóáÃìzã öîÞͦM›Ã/mß¶hŽI A€”õ:g½ÎÀ°.­ Z12`·Ä¸€"«t.OIɬ[ÿúÖ¹ ]ZrѼy̘9“L&Ë#¿|Œ75÷õõÝöAÏ:–-_U[]zúÖ[?=wÉâEÄ¢Qvìx…×^ÝÉÿûíMû6ìŽÝ–$€N«ì³$ÅPPè@X½ŠP¶f•. (Ü–”šŒ|áßáó—.½¬®ä’KP]SÃþ†<øàC45½ýྪ78«X¹êúÕÍ›÷È]w~Éãñ”ðêÎlß¶gžù}xëK/¾4 ”ŽZÇ=¥g Dç8÷ï0ÁiýRHåoTfДe”ZÇy)r¨Úœ¯ýk—_VWgÿØâÅ +üèÇ?eó–-õÙlî“ÄØà¬àún¾ëš«¯zàoÿöoèÇÙ¼y3/lÜ”ùÉCîv ~h:´ôŒ%Y@7M³¨ηÎÕ¼ŸAÄÝ@$v?ù*½‡[øÑý_’Z÷®Ë“¡(ú¿% tá‚—Ýñ÷w̯»¢ŽªPˆgžy–Çþë×ñdÿåÖ¯«?­0NqVp÷<ò©›ÿjÍ ×¯¢ùða6mÜÈSO?ݵþOz8¼ƒò"óÍ{ kšæ"`&0áºû $5LÒeáñQ,büv™ßÿö1~ýƒÏ¨"ø´Ê`Ö÷î¿ÿË–-·Ïž3›mÛvð£?HOoïmÖ¯{ô”Â8Å'À7}ú‘5kn]³|ÙÇÙ·w/6làg?ûÙÁƦ¦u@+"Ðkc0ØëÒ¦i€À ˆÀ.ÿ^¡âÇB€á’!O„¤søëË$ƒ¨*¤ÞuÇ7Þtó_U,\´ˆ]õ»ù·{€x<þ!Á%Àõ7ÜüÈí·}vÍŠ˨ߵ‹?<÷÷Þ{ï6Ý06€&„2ú°lšfð÷Àr„‚‡+þt¬?¯ø|zžÝM6›ƒl2iøLä&ÀdÊo¹éæO~þï>Á’¥Ky}W=ÿú½'‘8ö Á#ÀªÕ7ÜõW7ÞøÀ-·ÜÄîúz~ÿÌ:¾uß½›€çýëO0hù)Ó4ï>ƒˆàóŠ£)4ëÏ Êö[Èé9Ðu¡ülrYHg îåî¿, "ˆB¡tõÊU×ùß=gÉÒ¥lÝú?üÑOâ©Têœ FÓó¨£cÁò«W_¶dÉ·Ür ûøãÖó­ûî}ØÔQD€v Hš¦9øO`*ƒ / þ2Ã${Éðº8²+NŸ®ƒÃ¹œE’S@R ²²„G·˜á5—KǬï倚gž]÷;EUp8sêê–î{{ì×[–-_uÞ±‰xÚX¶|UíŒÓ¹ë®;hokcãóâÛßþöV`°èb° ·ß4ÍOßA´×“¯ì±(~$¥çå(о?…®ªBÙº²Š ô,ȲÉ*‘áW[ÍcŸ©“Y×HSŸ|ê©'ª‚•¥n·»öæ›näðÛÍž—^Úö4pùé>¯ñŠÓžâ-ó<}Ç¿àÉerlzá~þó_ìKfR¿ö"”߃ @Ò4ÍBôÐEñ§B„pà0´6Bùšª vMkØòÇv°;À¡ ápÀ¯¶šiļ‚àÿу?yìwO>ŽF£Üù¥¿' Õ-[¾êÞÓ}^ã§E€+¯¿wõªëæÖÖÖðâ‹[xö÷ÏFöìÛû †*?PþÈ`ox€v2" ·ö‘Hм٠Ý6@‘AUÀ¦‚ªY¥%v;¨öR84ûA4U›è7¿õ­ßmz~cÊåtò¹Û× ª¶{–-_5÷tžÙxÅ)`îE ¦M›6íîo¼ž lݲ%ýÄSOþQçw3´Îÿ9p+§çî ½A!!òe؆¾ü €Êà¨*@ÕfyË ¨vñ:OÍ¿Ú2à šÁëáÿï_ïß´sÇ.¼˜Å—^ ðÀ©>³ñŒS&@(z`Ígn-Éf³¼¼m;?_ûÈ&`'Q¾œª»áž¬išwŸåx—^¨Èᢠù Âq€cÀ¾¨¨â5›%Ê0QAS4UA³©hª*J› M³^k*šª¡Ùí¢|d“iB0‚ @lÏÞ½/ý~ݺ·cÑ(·n §nÙòUkNïq?œ,\üñ‹/ž¿bΜY¼þÊ«lÞ¼¹#ü7Âò“àOüÓßÍnùݽ+G(u¤ú}¤@Nçx#Hx³Kó6l Ø$«´Ye^T°)26›ŠMQ°©ª8¶Ù°©vlª†ÍnǦ©Ø4»_<4 UD•øîý÷?¹}Ûö”ßçãê«/¸çôùøÂ©@.÷ùï¹åæ›èK$xýµ×yü׿yœnÝêÔ’ÕŸÏlø¯¯V?CXꉚvcñCƒz ØÝ ¦,ª|EE²Jy°µ§ØF:§¢(*ŠªŠcÕVp¬ •‡þØÖ¾ÐD~ùد^nmiåÆþoYYíÅ Œ™µS¦}lîܹ—N›6•úúz¶¿¼ý¾ H"W§æ^±:síw€1wª®$ë/ôà@·vÙÛ0O ”Ê0±)ÂØTlŠ ›¢bSmÂ3¨ªå TlvÛß~ó¿càŒ=O>õÔ¶×_{5åv»Xò±Eðñc%€ ÿaåÊOÍdØ»g/7oþ-D©ÊL™{Yöã+?«WUûäçöòð%FòND‚á 7‡IC¤äÅKRx~¸Ò‡Ÿ³©‚yÅ+ê Tu°j˜¿èj.\ò©.PÛ€Þß=ùÔŽH$Âu«Wâ,*ª]¶|Õê÷D ï#ÆJ€)3f̸bÁ‚ùìßÿ»wï9FêQ骩ó3—,¾VŸ5o¾¤ª¨ŠŠºµ™§€µœ\ñ£¹üáß;}"êW¥ÁI ª\ ’%ÃÏY-Ã2/²‚ªØPÕ¦X¥j³‰cUEýÔß|§/4mq7Ðóø¯ù­7÷S rÁôé ‚Üsc"@¨ºöÓ /Yà8t ú={_Bñd“?’½`ö"ý/_cÞº” U+ÈRl;£|ØÌñÊ)Ò/ ò†+?‘„·ó–Î0ËÏŸî _Ë ­2d+0”¬ê _جûWmÂK¨¶²Š ¼ôš[{=Q o럷î6 ƒ+ê.X½lùªÚ÷FïÆBw0\YWw]]]466õïØùÚ‹ª)ÙªšY¹™sÁ*¿ <¼b6_Vál jþ1àDßð(øÄÏF†Yv^°D*ð rÁ¹áž Ð Ø÷([ÖŸ¿ï`SÔ+WÞžš>óâ„¢–$ŸßøÂîæ·ßfᔺ‹Îéj`,˜:{öœùÓ§O£¥¹™Co~Üœ«MÕ«§Ì6§^p¡ôé%,CŒ¨ým]-W*–{$IwÁ}ˆI Õ>å·¥ ]¨ìBN†Âj€H ;V@Ud¡hYFU$¡x›U(–duÔK–¬JL¹`v×k»öi:t(ív»¨© °ô½PÄû…±àš©ç@kK+ÍGÞ©¯VëàT£ºv–éó{àz]ý?^ìgº$¡I6´nƒ\¾èX9‘Û®|]M0m,"K¯óÇyþZV„(V)YÇy±)h²Œ6wáÊtÍ”™ý^¯ßØû澃³gÍ‚¸p‚¡ÅýèLÚÛÛˆÄzüÕFypŠª™*©vT ŽÁ€Ï.ÃwünJ U’Q{!× ÿ1#h$«ÏOõ.$@8+îï8k^~†aÖÏç ½€„¸GY²¼Œ*)¨’TP5(¨²ªÙæ\´´×¥ö¾¹ïP¼«‹‹.š‹,I,[¾ªî]êá}ÃÉPq^í”é³fÍ$‰DÛ\nOÒ¨1=þÉ[^¡Ü²˜+9>·WÁ?–©”äö1Ðûà¿AGr÷…‹=ô¬˜)<ª²G{o¤×ÇWCÈ$¡J6¡xYAµÉV5¯Ôlµú¼æj§\pìèÑp´#¡¶¶W±¬Ìç"NF€PeUUuUU%±XŒ®xü×4K¼A<¾I’£HQyŒÜÌ« Àn(É»Û$}b¾@'ÇÏñ/DDCö§ìþæþ‡vø9áâei°”ò"‹sŠ‚f€Vsþœ\Uõù©d*‡;z].'`Îi<ûq“ à-+sº\Nâ]]ô§2Ýe¾ ©´,(—xü6EF¦0z3¯Â·»ÀWJH ˆv=‹§àØÈB÷X•ÏIH?.Œ ãB‘ ”.ËVL`#£!¡N½`vÚWÔãñ¬  ö´žþ8À‰fÙùn·€D"A.g´—zü’Ëí“ÅÅŠ,!AŒñ6ã÷ÀM½ðTVô ’R°Ý!¾°~O²$nŠQ]åTÿŒÌ`0‘‡ÄP#[7wÜw­BùR’A’Äp£$ƒ,A& Õ“/Èz½åzg4Ö„|ååpW'#€Rl-³NöõcSí·Ç§¹¼6ÍáÐfLÁÇÉq ÀW+ð'Ý"µì§Á%æãU!t#éb’‡v&þly¦åÉ º4芤üòŸ“¬Ïèà+«Ê|AÓÀJJJ@,49'q"”ÎbW1™L ÍQÜár•Èv»KQY z rråçëú27\™í)¡t’pÔ)^OBò» ÀH^àdŸ× ^HÒà3Yf2äL(r•ÈÁÊl*ÙÛ ÷ç*N8ÁPª Ždu’ÒRÅå*µi§*KhºŽÑ‡nGŠðK5¨s‰Ã:: I]tÅNµî?‘ŒŒå³ÃÏç¿ghî2dWq±M±)Y»&¸jå3:çp" HyŽPìrÛÎ"Í¡Ê çŒ!8QçN¢nõA8ÿ†Õ‰ Ë¢ê_(4JK‘yv¿'Úxp2ÐßÜüöç”û¼®t*^æ, ÅÝNrÑ8x›ÞÚ9ǹü‘¬]B´÷ó¥ Ⱥèqõƒ–y*1Àðz=îDÖŸ¯ëuSÜ„®ƒž·üüëät(ö@©Qr¹l%²Ì»ô¾õnu\áDè‰Þ®†£Gƨ­­eCc7ø‘”»HÎÙU̶9 åx˜J)T¾HVs[¶žÿ@ýŸ'Œë€Ñ”?ÒC¡hÓÊ"¢ëBÙ…Š×s¢yâqC‰ €³¸¸¸Ô0àPc@ó¹œVîd­€Ðëêêܶm{ùêÕ+ih8èwhf‹»˜œÛ‰ÙÙ‡¢ôNñ8"–'E¡ò spÌÆÈ‰ ÐQ8ˆ#|ŽWòHÞ¶Iù£YNŸ‘S‘ô,du«Ì‰àÏãHJ^æ)))Û»w±œÃÖ'¯ºìÑpûÿùA‡C dúb·;pÌçÁèJ@C3Éj?Þ%HRÂ<®Ó^  ½ÁÀG¸Á“µñ‡+ÿ¸qkËÂu](<«çI`èPV^+Ìííí­*))aÓ¦ÐuÄ §s'ëêú6ìÛvhÆÌÅ-­m̘1“'M›8â+AA$á89o *²°zy°:ÈëÓFðÄ&(ÃIC­~8 1ZÝ?’òÍ‚s…®~ Ìx€äÒ¢ãÇç[.›­He2ìªß?×÷!8Yœu ‘èé@<ï|ö÷ÏâóûÐsé —†Ã[ŠÃïÁc_ý™J&‹-«cKØÒ`Ë Q‡‰¦[’Õù_8rViˆqísfA™³JÝ:ÖuzG.‹CÏYÇ9ÙìPÉé8|e8œ"ñt¹×çsnÜø1áþÏiåÃÉ=@>{wö­†ýÛ·¿\uÝg>s+µçMÑZ7U†ÎŸ ”cvÆ¡= à)Å&+Ș’„‰‚!ËÂødË%«Ê0Áfõ¿ q…íÿ±ÃÝÿpW3°üX*9+`.+¼@6™Œ°~‡‚>xRÉd•ÃédßÏÿüOú„Ç9Næ Äúÿx$ܶ±#M>ñä郞©&i¸Š*Êpý8làØÿ6¹L[*ƒšN£f²Ø2ÔLV¬®ÉC¼€]-'ÊkÕ-Éç½Âhb ûn¡õ×°|}˜•g²82iÙŒ°þŠ2Áòë/q8îÍ›_¤¹ùÀÖsu°cI׋¨|{÷î~aÓFÿu«W¯bÚôéjSÓáòÚ©Sz«üO@8‡Û0CØd‘Ï”LtQJ2È ¦,a"cZiZÕwÞêóÓ´òßX<ÀhõÿÀd…‚à./¹¬•@2 é4dÓ"‰d:-¢þªDÝO²/Yát9yâɧ1DÒÅûÆðìÆ=ÆB€|0)nÛØ^õèÚÇœ_þò´9âQ¦NÉUùŸ@_?4·Ë‰ê,ɲd)ß&”/å@¶aÊ H‚`õäû‹‡„c™È1R³.œ+pùYKù+sh:m¹üŒ(3Và7)¡ŠÞ,Íér:žxòZŽ XÿÖ1<»q±&ŠìBLß*Þ»w÷ n·ûº+®¬cÞEI{wïöÌž3'Y€dšZ¡±éüZ‘ SR@Ö-`Y·ÎÙI`“À=@átîõœ°ãgx§Ž>Xß畟Ë@&iK0…åWW€WL÷“ ]/ŽuÅyæég0L“Þžø?œÊCÏ+z«yÊ#á¶uÝ]]‹~øåÿùÃïãõzÕd2ã 853U©,´…æV˜T‰$[Ézd+Ql¨P¬aY¢¤ %B¾¿NÜPèòúºQ@}0ÀÓ \~ƲútRq~’jª f°[K‘EþɃ?¥«;NoO|íöm/¾vªz¼b¬0Õ@ à~qëÆµENçW~üàCÜyÇhØ¿_1s&5H[mè¶(´EÀïT¾¢ O (ÕÃ@*WCf~j¶ådydå瑆èåoä :xòm|ËÕ(?%êÿ /ÔVÁy¡¿ñÔSëxíÕ×ɤÓÛ·½xï)?åqŒSÉC,€èìßÿæFUµ]=ý‚i,ûøÕ48À´éÓ™â?o‹ŠöžÇc@ôVL€ªX–j!'‰¡W)¿Rk¡ÆH‘ a ¯ü¼õëCI {zV4Sàú³Y±|é¼Ô††.JØ»w?¿þÍÿC7Mvï©ÿ2b™û§š,ú(b§»¥¹é7“BÕ3Ö>òËêPUˆÙ³gÒÔØÈÔiÓ˜bY, /AI±ð6k^d%õÓUAEõ´Md =u­áÈw$Z~>è3 wr9Qïçrƒ‘~.-ܾ‘… W(þüøsyD"Q~ðƒÿ¤¯¯¦C‡‰EÃOžêï8ýªû÷L*¯¼zù=“B•ξïj&…ˆÆbøý~t 9 ÍíÐur‘TÕª ql³ É'ó“­ä~’E‚á`ÈÊcpÒæ ò]»ÖlžÂžœUϧ-ë—J?ÔV ×ï,ø“Éd’¯ý[h<„§¤˜ßüæñ+9ÎI¼—FÈÀy–L&_yõò¯ÔÖÖ8ï»ç›„BUtuuáõŠî³Ö^hi‡ÖèéI›Iœm^a€ù€ÐŠ$=A!òA_át.='ˆË~ùÞ¾4¤-/à´C(“ƒPã·VÁXH¥2üÓ·îcß¾}Ô]QÇœ /ä·?þë/o„ÏÉΟ÷zÇ;ÂT#¶]™¿lùª/VUVòÍúµµ54>Lí”)ÄR ´u@G—ÊT;Øm¨…°bEh&(€µôàT.kB‡nâå²V2‚?e%¢_€ªaKûz î»ï»ìë->÷7·Qæ-§7уÃáà7?߸~ÃåíÑsgb˘«‚2YÑ_óñko÷û}Üõ¥/qÑEshkm#TÄä‚öŠî„°`U)»ò¹]mÊ`Œ0°ÁÃH$0Ç“1 gX fÁovÐú1Àí‚`¹èßDÒ‚B´¶¶qÿýÿÆáæf¾ùͯ±há‘û÷7ЛHàphüæ±Çâ_ºëÎg‚UU«u=·ÕY中Üç÷«‚ÎÔžAùÝ·&#VO¿òêå_ôxJœ·~ú¯Yµj½½½ù%Ôte"1ˆÆ¡7!”gS^(¶ÁU8-áýÇÖŸŸÅ«Z¾,ƒ»HDùå^¨ôA °²·°}ûN|èÿ‹Å¸å–OQW·„êPÀ¬^¹lÈ÷š[Zã®"çå@ù¸ö gr×°B”“—Ö]ýÅb·»|ÉâEÜqÇßátŠ #+.ˆe Ú±8tõ@ü˜èD2ŒÁ@°09ƒ ÇÍÏO/˜ÓoõøÉ€¦ ‹÷–Šñ|¿®‘[“ÿâQÖ¯_O*•¡?yìÀ½÷Ü㬠…ªNÇxË<$ûûH%Sƒƒ‡›[âN§ãîÊŠŠGÇúÐÎ6Îô¾yTXR<ÿâE_ôûýÓ«*+YóÙ¿fÉ’Å$z{qx€^}=Ç ·ú’¢‰¦ëÂ;œ ²,2?ivpÛ ¥n1 SæèÒ=ûö5ððÃ?§ñP†iR¿k×3ápëS@é–-þŠ “êP€‡±–¶ö0’³gÏæúU+®Õcü`R¨òîSypg gcçÐ bwÎIˆÍÕ@0´ê¢‹þâ:EQø‹ùóXóÙÏP[[C²/‰Ó5Ô@,ŽÍIDAToý‚Éô[möL¶€ Öíæ;‘TE(Þ¡Ó!”_ì·64²/D¬«‹_þêq^zi©TŠþd²óÅ­†È]$#’^ ÈagóÖ­´·µÓ—ì#›ÍÓ§OãoÖ|vàº}}Ib]±­.—ë“ã-.8[{—!6a XR TÏ¿xѧü~ÿtgQ /]ÀMu#5Õ!2™ š6²yX[‹æoôAwƒ›¨*8lb^ùh Ï£«+ÎO>ÅÖ­[‰ÇÅr†ýûßÜØÒÜô_ˆ ­ßFì1\…E‚W^{ã_ô\¶$Ú¥áÀAâñ’É~2™4’,ã-+ã«ÿðe\ÎAB76®÷z<·•—ûÆM\p6ww" QxEV´ÅK–,½®Èé,w:Ìš=‹×.gÁ‚ùd3ÔQÈðn±Ï>·ž7^ßEOâÑhôÀë¯nÿðbi×aÄr¸ëþ«.¾xÁ•O>ýÔ×ãñ8½=½¼ÓÖFÃÄã½ôõ#›Í!Ëšfç}î6.š;˜-îpsK¼ØUt[E 0.¦Õíãn4ˆP~¹%Å€\HY’VTpáÜ Yºd13gÎDÓ„†räÛ •Å»ãÄãql¤éðaâñ8ÙlÅ6¸þeåʬZ±|àu8ƒ»+++~pZä=ÄÙ&@Å"” HPb“y³/œ¿84iÒ<Y’ðx<„&U1õ¼)LŸ1ƒÚÉÕø|>\nר³‚ú’Iººã´µ¶Òpà‡ÑòN+]]ÝJÏf³ÉÖÖ#olØ—ßζ1®ÑŠ˜÷8¦K–.]:ó‰'Ÿ¼³·'a‹Ç ^{£žÖÖVú“ITUEQÄT–l6ÇÔóÏç«ÿû®‹D¢QrYýÑP¨ò¶w÷(ßÞ/€Õù†¨[=XCÊ"¨€SV´y³fÍž—'CŠ¢àp8,ÑPUYR0L=›%•I‘L¦ÈdÒù5zèO&;†ÛlØ÷ÂÚ!Ö9t"6ˆëÁáx @2Bùeå;-)fyÉóW#ç †îMÔ°ðB齜ÜâGºÏjDk p¾ð ÷‘Y³þ"뢫«›ææf^Þ±I’q:‹Ð4»ˆ ƒL6K*ÕÏêU×qEÝÒ‹¶µµÇÝn÷'KKK¶žâý¼+Œ'BE(¾±¯°Ã ¡£„âó[Ñæ÷(L"2v³d,Ö> Ipà~íõ×ïT/ˆuÆèêîâ­†ި߃³¨—«»Ý†¢Ø0 ÈfÒô§R\Q·”Ë»›[ZñxJo++-}ô]ÜÛ)a¼`8œ ®çWÜVæøì¡)„ò ë8‡P~ú=¾'•Á¡ïPúæ¾}_q»«c1:»»xõÕWi9ÒJI©›â"šÝŽ¢(˜˜¤ÓYúû“TƒÜyÇ.‰ÆÐìê}e¥¥÷¾Ç÷;"ÎŒWØcyTí踧ïXÒÙ‹ëêâÏ~‰D"AII)®bEš†¤ØÀ4Ȥ3ëOâv¹øê?|yࢱ®.$Y~ÔWVvÆ[£éùÝäaú0!¿³x;"¦ˆÌŸ7ï{¾r/^¯Oi /Y€¦ÙI¥’äÒi L›„Ý¡ár»(ó”Ig¸ïÛ߸¨ÏëÅép®éˆt>¢›æû’jv‚cGA€6 £½½½õÛÿüÏk½eexË<øÊËøØ¢KÉd²$S)Ò™, (6Å.7ž2vÍÎ×¾ñ-Úà —³hM,Öµ%“ËuLàÔЋèChº¿ÿÿ±íwO<ñ{¯·o™Ÿ¿œK.¾8?ÀD&“Á0 Yôg¸‹]x¼Êý>|èg„#Q\.'~Ÿwn,ÛÒŸNŸULħ‡üð÷ dÃóÏß>gΜÅQb±Nš´P_¿¯×‹ÇSŠÛUŒÃ!CÝ4H§2$ â=q®¾êJ-\0pá¶öözÇsy±Ëõžv¦çS>0¢u µË®¹fí‘––šrŸ¯Ú4 t]'Ñ› åH 6UESmb7j›†CÑÐTk_ZUeëÖ?ÓŸìçÊ+êUUÍmimÛ’ÉänÓ4Ûï0š¨NmˆÞÆ ;¹¦æ{©þd«¯Ü‹·ÌËô ¦Ss^ ½==$úúɤ2˜9E²áp8q—¸ñú¼øý~^{c›·¾8pášêÐÜp$¼¥?>ã[ÑLx€Ó‡ íˆ+Î?ê{zzï1 Ãi˜ç›S‘‘ wt`·©¨šŠj×Кæ@Sm¨ªØ¦´¾~²$S·t Õ¡§¹¥uK__ÿå.WÑóxwÈ"š‡ ªeÞ¼¹ß{õõ׿’ÓM§nèºIO¢‡xo7Š¥pMµc×욆]³[U‚Âî={Ql K/ ¶¦Ús¸¹y˱c}—»Î &ª€w!ÍÃǹñ†~ ðû|ø|eÌžõQ4­ˆxðíûî[¨¨Àï/§ÜçcæŒ Ðìvâñ8½‰ýÉ$ºžCQœÎ"<~Ÿ` ‚½ûö±}Ç΋O2Åuné舼ç$˜¨Þ;ô"¶ÅÕÛý÷ß¿Í4M¾þoÜn9Sgš o7¦«+ŽM­»fG³khšUU±©*Šª²oß[È’ÌÂ0sÆô¹ûö7l9z´ãòÊÊŠ÷¬‰8ÑðÞcÈb™?üá7/^¼äêpø(áh„X¬‹Ö#ï¨(Çç+ÇãñPì,B±)d39}Çèîê¦#eÖ¬™,¸xþÀÅ÷íÛ__æó^ª¬<%Lôœ=„U« °âŸøÍŸÿügç¬Y³˜º~§­XW7ŠªŠ–€jÃ¥Ùqºì¨š60Õ¬¡á²,qñü‹˜5kæÜ½ûöoi;zô”I0&pfï(²5—]vÙÚ­[·òÑÎ^l¦•A£½=L¬3&¶(·ª»]C³ ¨6ŦÐpà À f¿‡$˜ À™ÁÐL"5uuuk7mÙÂìY³¦‰aPáÑX EQQm"p»\¸‹]hvÅ&rÙ,‘Ž¢Ñ(ñ®.ú’IdI¢¤ÄM0dRUÕ“ªyný’© `‘ÀW~Z$˜ ÀÙÃq$¸vÙ²µ{öìÞV¨ XáG³køÊÊIg3„Ã:¢tÅbôõ‰ýùœNÁÊ ¡I!ªC!þ¸~ý ª«C(ŠmÍõ{N‰8»($A;¼öÚekwï©ßVP¬@³Ûðz½˜mŽtÆH&…Ë×T•PeÕÕÕLª®B‚9³g‘ÎdÖìxåµ5c½¡ œ}’ H®¸öÚµ»ë÷l úT*D§«EUho‡‰tFÉdÄÖʲ ¡ªàä±àâùȲôÈk¯¿±f,73ÑüþÁŽXtÀZyôÜsÏÝ>{ÎÜÅ‘Ž0áH„\V'—Íb˜¡PˆI¡I„ª*Q”A» ‡#im¥3ÚÉŠå8ÿú®z$Yºmþ¼¹Âĺ€ñŠãHð‡çž»ýÂ!$Ëä3Ù4¡Ê*B“B„BUC\w{8Bkk+ÑèH›6oÅårÍ»tá%õëÆ'Òˆ&bVuð‰+ÖîÙ]¿-P$`Se Ã@Óì„ÃÚÞiãh[û‹TTW‡ðù|<ûÜ`upåuôõ%·ìxåµÚÑn`‚ï?F$Áw¿óíµCH 8::£´¾ÓF[ûpˆ˜Àçó±mÛà„’ çÌö¼}¸yõh?>A€ñ|·ñ zè¡mßýο¬ V ‚ØT…t&…C“JZ[Ûhæ BUAªC“00xõõ]ø}^öîÛ;êD’‰±€ñƒác=ôà6dø§o|ãv€ŽHý©E‰c Ž´¶b` …,¹*T‰®ëi¸T¼«+þèh?:áÆ =A+ÐýЃnûî¿üËÚ@E€`°MµÑŸJa&©TŠÖÖwx§¥•¬•G‘e‚UAªª*xìñ_ÿãC?ùaóh?8Ñ ŸÈç%ðaÍ,úü¾°ø®»¾|s__ÂGɤ38œŠTÕF0XIUU‡•i-‘èãÑ_=úø—¾øÅÛ€ìD3ðÜC>ÓZ‹~¿¿zÛË/%‘8æŒtDH¥R9”øÊ}ƒ¸].¶mß¾õc‹‘m¢àF~ŽaðÉÛ_Þù•D"á ‡#¤RI4‡§EÇCSSÓÖO¬¸öÿ r ŠU&pN#ï *Š@ 0ùå;¿’Hô9Ãá0}É$»†¬Øxâ·¿ýÕÚ_<ü°“‚ô88÷‘ÏŜߤ£xÇ+¯|ÅétV‡ÃllL>ðýïÿ´©ñà“À.†¥Ê™ Àeˆª A†Ò;î¼sq2™rþâáŸmv a—'i‚äwj H "¥Þb”¬hø`!ŸÐ:Ÿv7?¿`Ô”xøà!Ÿc1‹X›xBœ2&ðáÀDWð‡øc‚rLàCŽÿWìžMŒ€ýIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/search_advance.png000066400000000000000000000034161217176075400255270ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ ÉÈŽIDATXÃÅ—{pTgÆçì-»›l»Ù,l $&(¤K™bÆj;Ä‚-‚ZäªUZ¬ÖÇÒQÿ©…¡…QR  %jD¼t.á– HÂ- Á´!!ä¾ÉfÏ~çõn+SiǤAŸ™wΙùÎùžç;ïû}Ï{àÿ íÓ'<09cÃúu ãܹ]¡‚)žOMMݵC ¾ñ­7B¡ÖÞUMù|jyyÅñ×óò̯͞}X¼üøíâE‹Nì–ƒ‡Š‹ï€’¯[¿a~Ѿ"l²ÑCMÓ|°áFcnk[Çøö¶ö‡;É|qòÄI»‹‹«¹O-xd@ÈWÿzí‚Â? 0cÞ¼%ÎÎÎ7Eä°išy"òcyÒ4Í/ˆH2@B¢ß|ÿЃòØŒYÓ>yêˆÌŒwö 0eÛïwäŠHÈ4ÍbÙ""/ŠÈBÉëÇ^Õ¥‡`P¿í?P6:3ó§ûžœ "†ˆ”ŠÈŸDd­ˆ<'"³ÚD7EÜkLq—µ‹ûÀeåþæŠW=óç=•ÿÆö{úʫǮą̃1²ê½A»îËý\p h:€ C©¼HtB¢Hô Öç?ó׎Ûäq}Hî³€Õ«_^~¾²ª°êbñÄ]vVG˜#ïLj<:x-ೀϮásjø\.|º.þm:ÛoݺuúéÅËæôY€ÇãÎ=S^W–œè˜¡¡¥°óüMXD#½VX Y °€Ï>‡ŸÛ¥ùâ\ø:»ÍÒœq÷Mï‹+€Åb ¦ »¿'ÎAª¦Ñ¤ÃX/<‚cNð M‹\Úm§˜¦ƒÅJ!ÁáYí×/äôY€©”–1*3ÙP6"ô©npöÀe ;Í QS$+##þÚ¥SfŸ4777?ð°÷ÞöNŒDš¦aÑÀxî1o[± U‰€ih’–š”ÞÐØTßç(¯8w~Bv §¶…°¦'àð¤ (±0c!4 `¸—`O7A§ƒ¡V‰Œ9yòìþþ˜Ñ¼ššÚüËm#OÈf˜ÕNØ¢aD"¶Xþ%¶z„Ž(´Ü„š«0i$êÊÙ¿O]ðíÅÉí-7šû” èµë~µæåì½'ˆæŒ#A³£l”E»| à£ÏtG¡£š›À*HæâWí((ì ùÇñô‰’Sò~‡¨?¼+æ‘1KšD ‰ºdˆºªD]Q¢.FDUtˆ:Þ jo¹¨ÍûE™"ê7¯¬ õÇ?êìv»+>Þ³öÌÙSË’i²÷(šÃ¾dpÄÍúAµQèAóM°kðõ©ðç={9SZVW}¡rò®=oÝèwCb³ÙüN—û¥‚»¾÷è£HEhÿ¸¦6@2Áㆉ#!=yeíz±ÙìW–.Y”YS[Köȩ̀ÍùÊÙw U¿ò`±XïÌš=÷ò‰%ò!º•HOì^aùË_ß–ÉS¦–cìS§ÏÊ’åϘ›6o¹^Yy9å³´d0 Èþøøñã²}^o¼i*­¡¡±µüܹҖæÆÀ!—Ëåš1sƺ+´ôõ¼Í’‘‘Æ Ï¯ŒFtÚìU/×­Ú$Í´0XyËó×<ù_÷„1ÄÅv‹5¶zãÏù_\õRÞøœœY¥¥ØíVùá³+´ÙgVNÿRnv\·“í¿Ë?V‘_ñðìøÓºböÜõ äM¿üÅÏŸ¥JS‡ñû’µM[¶ÈðôÔl«W§ÍÒŠæ–Oì usç<±0{tÖõ°a‘–®uD:°Å[鱇Peô©-ï¦>÷àîðÞ)Y£²›Óâ½'»ÏFýÕ÷ðw 3.^¸xÍÚeѵn‡rTXZ@yMyÀ5Y Nw’–’NÑEmý ºj{h‰¶Ú\ÎQN«·–ÀÑÂ’¦ ™:¡†Î8NsáÖ9zCQUûHNô3blþD?݉.zÊ¿½`À7æXåÛ£..;êþ܇¾\FI’&p3@[m»5JÙŲãNq½ëÿ~#WÞûNð­$É-/½9]"‘ˆ\¹Zm*SÉÝØÿ‰t«Ó‚3Î…ŠªÈ¡â#ŒÌH×¶mÛžw»ß5H(SÑ«ÂÔ××WÕöTÇ-,È/Ù¶uë²ÿ‰¿x˪6ÕçýW“2®ê»?[¶høpü_R2ÿÙ÷IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/search_small.png000066400000000000000000000033151217176075400252340ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ *!{ÇöMIDATXÃÅ–{pTgÆg7Ù$»ËnÒÝ@Bä’¦ ¥ÒZDÓŽâ´M)PlP(ÐËLŶ8ãLñ[.RA†«TšJÈJ $…‹ÜKÒr!Ù¤¹íæœÇ?º8Œƒ£Kiüͼs¾sæÌyžï}¾ïœÿ)Sžå¿1qb._ OGÄG“Q\\ò›ŠÊª#ÅGJþqäÈÑ+•ÕE;ów/r¹’dç|çî ?‘;€oŽ}lpEEå±uk×ZS&O.V _«çÍ[ºeË:x¨¨ðäŒûî7áû,_±rFÁ¾¥¦¤l2±% ´,ëÑúk×sZZÛF[ƒâ\‰~`ü˜‡ù ¨è°9í¹™ß»+Xü»e3·¸]@îôé/¤´··¿+é°eYk%½.éY˲ÆIJèçíï~|¨ð Ï4á ‰:,ãÀ¾c7ý9/GR‡eYE’6HzCÒó’r$żÞ&ÊÅÖ#µ6àÅÇ?4ö[ãîÌ@ÁþÂS÷öË}KGI K*—´CÒ2I?“4©UŠk”\ŸJ®K–\§‚rÖ˜®ÎÛ3cúsïýé¼ÑêÚ"ÇVoø¾³Ÿ$m}0ç­Ày h:€P7”Ç€/¼ àu·_?¼ž{lÞ¯üÄ™÷þž•‰çÓ@rÔ/~ëåê3g·Ÿ=Wôð›Þ„x*"Þ X‚€øìà·ƒßaàO0ð;øm6õßTØlnnþxö¼—ž‰Ú€ÇãÊ9QQw*Ù—k`¤uðj#¼ „€pzb Åɶˆ;øcÁçÀïrþx'þöN«8ñÞúë W£^•UÕ£2S²joÐmÄ œOMHS¤¬H Ò‚´îÒº:IKˆc`ŒB_/-=¹?7ãœ~éRí{5­CÊdPŒƒn»AX„b#ù+2{èÚzáF#\º܇yáä_³gΚ—¼q­)ª€‚?¬ZU÷Û7ßÊÌ/¡7ký fl¦Ý‡>w𯶽ÐÖM #4,÷¢¼-Û£ÿwf—/Ó§m27ÿMÖG—doYÕ!ó|XæESæSæ¹ÌÊ6™ÇêeæWÈ\¿_¦%™K–.ï|99Ñ}oF€ÃápºÝže'N–½”˜’®übŒ8'ø“!.bc>_íá^è쀦FpðƒløËÎ|N”Ÿª œ>3fëÎm×µud¤‰¾±±±ý=ÞÄU{÷H’UqÙÒ»EÒúÒÆBiãi]´µX \“$YK–þÞ\ñöÏuuõèô™s’t`ôø©ö«Wëï,»ÝîæLš<­¦¤ä¸nÒiJ]‘±îÖ®Ý{5flvðYöñI½ðò+Öšõ$éÊ™35ššþ·ns}30mÈ“#GŽÈôû|nË2úúë-UUå7š®ç‡œN§3÷©Üåó¼ö⺵땑‘ÎÂWô†Ã½ÜnWqKK¤$oTn%>²[b" ßæ¾þo,úÕÚ‘YY“ÊË+q8bôóŸÎ7l6ãGn·{sÛgŸáq»ïÈ@4 ÙöáöÍ7Z²L‹ŽîNÍ5ËHHHx-!!~iss >_ÒmÿîuÓž™ú|æýït‡Ãd¤ßkìÌߥîžî%]¿öù’ÔÖÒdWUW5®X¹ZG•h×î½ ƒjim]p±6ðåªKx¼¢²²eÍú º¨Uñ±«­­] ú¤©©©ðdé‰-ïlÎSK0¨êê¿[]]º\wevŸ˜ðù|6à‰Ò²²àÖm;ÔÓRÍ…€ÕÕÕ­ššÀ¤¾Y ÙL,8p°aמ½ …Bºp1`™–)úФ¤{ `|~þžOöí/”$mظq }‰×ãxtõê5çfÏ™³ 6ÞÁÿƒÔ[Oþ ä|/©ùþi¦IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/server.png000066400000000000000000000052441217176075400241100ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ kIDATxœå›ËoÕÇ?g¿§©mu§!Èc"•B+µÝtK¶A´)t“V¨ªÔ bSQ¡ò¨Äš¦í¢Ýuºi Q@Œ $Ä!1Æþ9ù½fæÞÛÅÌÏïiÇ™¤=Éõü|ïùósÎ=çÜk1ÆðÿL^yûí·ÿP­VzÐÀƒ1¥Ô¿€×'Dä×u{æ !çúõëçŸ~úé_Ü*ï¹ìì±Ç~àyJ©ŽÁq¬€Zk/^ü‘ã8G”RO ¦§§©T*@,¼Ö:m {­V‹Ó§O×ó`<jµõz;vt¼9ûY)…R*0Z­A<©”bbb×uñ}?Þqœ¾ßåû>FƒZ­–ëù`Œa~~žR©„Rª¯úг³³ìܹ¥år™W_}•B¡ÀÉ“'QJ¡µ¶æÑó kvN^”— pøðaÊå2A¤}–iˆA:sæ SSS©+++”J¥t¼»eï·¦·ÓÎ €A6 1Y¬I8Žƒˆ¤¿÷¡›¶-ƒ˜‘ž~k癡ç¾A‚f«”ÐË\÷›·W­uÇÏÚ¿Õ¢aäI·€¬Ãê: tû’<)W,õSSû»¶Ÿtƒ2èÙyRî°Æ-¶¿[#†iÒ ço•rÀ¾Å¬ÊB§#æ w9ì¦m­–ú9Â~6Ÿ |²Kè0á·­cÃ(ŠÒõÝöw_³‚dzVîûEš[¥ÜX]]¥T*EQ*|öjŒ!Š"¢(¢Ùl†a*H³Ù¤Õj¥QE>Â’amm­Ç̶J¹Ðjµ( @ï[‡uǧ”¢Ýnwh@«Õ¢ÝnEQ Ô U×ZÓn·ób;°•Æf~YÛÏ®ý2̼è¶F‚Ýc0|»«sèotÿF¡p^ö9P,Sg½Œöó ÃhØ<ëkò Ü(•Jk} ØøívgˆYSÉú¡X,æf ·Å v oû³×~÷m¤»Âdéf2¹NØ[µ­·q$›«l˜ë›ä9ö>Ip0;Ù­ÐmÀ ß½0,[ŒHæ†#ˆlãePDú†ÀÙñ¬“ëG&#¼V mAGpD0Z#®»ýBáz½N†AЗ¹+W®0333”ñÔþµAuX b´Jk·ÿžÁV(D„K—.¥Ù`?!çææ'‚¾vÜjÓY[Ð:NŽ´Rà{Ûo|øá‡©×ë´Ûí¾ø¾O†› …1`²_Hœ (­QJS,sá;×}›íõÀuÝ>öo’Ö¥d '&AÄAˆ—B¥5år9¾ïh2ÔQÜÀà1‚G BÖæI@@ŒÆ NFr¢;@Qe?¾8Ö‹é²I,gú41IŸF!Š¢\x¾mõ€î€¨'H2!­â^tÁ „©VÄÿ%þ'†,¨‚çxܸq#~s­ ª Ûñlœ/JѾwãG Vâ9Ú€‚-’"á¹ › Fò‹ok$h©»* @¤à¡û€ ¿J£@dý|ÀåÅE/_fzzš™™™80„» î— vTzBà;~œè4’9€˜õêïÔä÷ïÞÍêêjÆwpwäƒÆÒqhŸ*J¼¼ÖqÜÔTª• âßš˜ Ú‰g¼‹²Á9¾À ’ÔÍ J+Â(Š£¾„Ö“ª<9¾ƒØñõov‘¿@üÅl­Q€ŠFé¾÷¦µ‚œèŽì fÇR[v<*«ŸR(€‘éd¬ÃÌ,~b HüöãÈð.„Öçx8Ñ'ˆãaäþtN|íÚ H~ØE†´Z­tΰçl{ ôƒzvm*=0Ñ]UÞ–ˆˆçû>Åb±§ "ø¾ÏÈÈår™V«…1†b±ˆëº¸I}odd„ññq<ÏKçY€²…ÕB¡€çyn¼çuTöÒ;ï¼ó÷………£aNeÏùZ¬Àöœp½^O³Daaab±ˆçyh­ Ã0 ;_ë¸rîÀŸ‹Èr¼çÀ©S§~}áÂ…ßÔjµj¹\& CD„B¡@¥R¡\.S*•¨T*T*ªÕ*Õj•r¹Œ1†F£A½^§^¯Óh4h6›ik4éó’ƒÒ#ûöíûÇÜÜÜ[Ç¿eÞ%›=922òËGy¤ºoß¾Âòò²oßl¿fÐdU{Ð9AÛ<ÏcÇŽí³gϪÅÅÅ«ívû¹«W¯þóVyÏE¢(ú³ïûŸ4›Í]kkkS£££cƘ‚1f:W€(ŠØyÏ=ÇJ¥óóó4 « «Ú˜¿Ý€i¹¡”j_»v­&"Kžç]ª×ëçòà=Žýî§õzýS„üçãy ºX*166Ö±=æûþ3ÑäÔ±G=Êù³çørq‘]33ŒŽ.¾öæ›ÏäÁÏÍP.¸žÇÒÒ’õÎ)ÉÚÆÆÇÇ7µ©ùÂóÏûƘÐu]Úí6gß;ËÊÊJÇO(¥˜˜œäÈ‘#ñ3áµ?½¹eÞóÀqp’–%c _--0>>Þóç4û»R¼÷î{¬¬¬ô‚šø»ZÜ*å³ è·ËœalllèSÇ!Þ=ón_á×§>Ct³”Ï&ÛF¬§ÿji‰Z­†ˆôì8Ž ‚Àl(|ΔϷÄoz—1æ~ ¯žc¸võj½X(ìí.ˆQ¤*¼îñåååÀ÷}gÀÛcL µ>oŒ‰òЀž;þ¬ ˜¹úÉg?i‰ö¸®ËèèhË÷ýß‹È÷7úÂF³Éƒtôcøúë¯çjµÚéöüŒ1LLN>kŒù·Öº”ð qu1" H>@Û^E$üã¯w Ö ÀÏ~ê‹È}À0 ìNÚ.àÛÀ½ÀT ¾ï³°°À¡Ã‡¨V«Úe†T«UW¯ðÅ¥/eÿþ˜Ý³'9ý±ñýZkxðA<Ø=dùíæ;Ûß³lôðÊ+¯è(ŠBb²-È4Ûgñ}ŸÏ?ûŒ¿úËM9.›+ ‡>Üô’EÍV‹Ù={R 0Æh:Õ>Ëg*ƒˆ¨_|q8'NœÐ§N E$²B§ž>±Ú—€rÜ'(Q119¹uÏ]­nzjELïÚÅîÝ»³&àÖý–Ÿô ñ[W"9޳±|ôÑÇuc¸Ôˆmg,i£@5ieÀs‡Úêj¸kzúYÇuç6-ÉIkÍâå+o5ší´RöÈhH¼¿TOÚu`-i5 æ8N㥗~Õcd¹dƒ??ñA«ñÇq~L—“É™cLË ¿­ŽŽ}icŒ—_þÝ–ø_. JÊTzËIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/tab_new.png000066400000000000000000000065531217176075400242250ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ 2IDATxœå›ÛG^Ç?¿ªê>—9sf ™ä¤”dƒ; °#‡Ã!››wðx|TýõûÀ`Z`¬Žz9j)C¡Ë–Â/ìChu†$M¶ðhTØ|È ðÿŸ ša†IËáRG®9ÞgèXÈCŽ¢Ë£=0NvaÞ.uØÔbœÓHHr¼ú¢Í>í L·ø´©Ã&q‚Z%O<Þü ­âÓ8 j@E &Çã øÜS "‹ 9‚k—se)"€D‚<ž\sDÀ8´r‚‹ô­ªzÏ/>×âKOÝ3s‹€áÔJ«o‚z¯s|ÌÉC†ˆÐ[êXœâ O/ Û:–/>÷Ñž”LZÀŠÈKιµ3gÎ|j1˜;w{ºKïÉ—ýòONÞŽLG¡ ¦-H¤%H[ô»}ž^ý0 2Ÿ‘… YÈÈ|Æ(³šôyêá'Wœ½ôOÃáH ªxPä 9™*t[žxú3ß}÷¿ø»P‚ok¯¼òÊ~å+o¼úä“Oçœ]¥Öæ®käâÿ•×ÿö÷ì£ç_„Gzkô–zt;]º.=×cÉôpâȘ“amÂõÍ;Œ²ã|Ì8‘e™L82<Ưü¯B´¢ƒA £¦ü&1,/-ó÷ÖÏ‚´÷Ò€8òÚk¯}õ­·ÞúõñxÂd2!„¬7E·{í¥6E13OøþÅïñéóÏðÞð'Òœ\:Åqwœ®àÛcÆn+–#Y–1ŽÙn0œl2šŒMFıríÆn~pçNÖÅQq8¬¬->±,ç}ü¨ˆ;P©þ¹sç~þOß|ó×Ö×xf5ëìŸìü=4*yž“ 26ompù£÷Œ×¹>ºÆZcý‡Xëe)YÂG ‘{²qÎd4a43ŽÈ7sdÃâ760Æà‡M,6±8k1X¬Z,›YŒçDv' ”äÙgŸý¥4IÝh8ÚôÌž! ,iýØÃ†Ö•a2Ä‹ª2Ì‡ÜØ¸N/íÑs}Ú´Qy–1M˜Œ'd›Ü6Ȉ³º–ؤ¥H¢§`D‰@é¾™»P9?ã´ßmf÷KtñZQí âï=“ñ„a:䦻‰Ap$´´CK[H.øQ@oƒÜ¶X¡Ñ¥ˆ´“&Hb1Ö`¤°{€"1 x“ÕQb/ j°ºð¬/@ZœÇòúMˆ9d#OX½Ã¨3"Iœ+ÊݹÏð“@;ërd²FoÒ§ÕiW•Ћ˜6˜VŠK‰KHl‚[;C …éEð¦¨&!€jغ°)öÅ5 ÿð ×O|ˆ=_êcÚU|;'¤9bËÙ J>›@øÀðã —èi±¶|„µÎY{œ£Ë'鶺´Ó6©MI¬Ã˜‚b^£âC 5)ݤ l,˜ nÑ€Øt³–&uòÄIÖÒžæü45åQž+8çè¶»\I|÷Ú¿3H×Éú®ºÙðëôÓkõÙÔ!͸Û,+ƒ6 bpi}1 ÐFû¸4XP”Ô%—ÇøÁ×ÿ“@ N·dö0Î`K¯Óáìç?‡&éƒ]v¯M§Ó%¦9‰u|ûkßÁû·‚÷!Þ†Qâ&Õx°*,§Çþ t¼ •|гϭvúüþËÀØOª&S]i<7ñ9o\æÏÿþuN obÛéëZ:íÝn‡åî d>ðG/ü-¯áœãæ­›×ÿøÍ?ùÚ÷—>úk–“lÕhLlï WÃWóck xžŒ½ï%ÖñPïÈеƒ,¿_»ó×ïÜb°¾A Z¤ÈH[-Z­ív›N»@®ž‡zkœ^=Nâ–4ñËãä6ß¼t˜lÁµh1ThÀÖÎÏôÎ÷¶i·›HÙV•Ižq{8@Çeß©bZ$ iš’¦)­´U“XLÖìðK¬Ûþ莨j‘MUÍ °e–w'c¯YÞé^Ô)ùš•mØD°Öâœ#I’$)’…XŽµÄ«Æ˜\U·Ì~MÀ;ïþãÙ[7o¾tíÚµ38ë¸råÊ¥wß}çÎ;·ô™³g—²,#Ɔ(ÜPîmmXgîͶÝ|ó\cýœŽ€bAŒ`ÅSäýÖÖlAˆcl»ÕjÝzá…~ùèÑ£ù+¿ùùOu»]|î1FleåŸÀï¾üò˯Zkc¥%ív›7Þx£HW½ï=««+;‘xh¢ªLl`y¹‡L¤Ödî£ø"b8yâ§„Ǿñw¾*ƨ)*Çã¬EQ¬j%¸ê‡Tgý„jÑ9€ˆ "ìàG•¥=76C£„!à}À‡€ð 1ã.ÇCDE„fBW˜ô6NPU l‡¢1 "bDÈó¼p6U»™‡¶½Ê¶MöÑ^U¹zû:ƒÁÂÆ+>ƒI>a’OHò„q>¦e:Ä ÙĬʇȲŒÄ%±NÞj»/h]z/ìˆUq¤ŽÝQ‰4“fˆð>c¬V¢*F”êÙª bºgÐiy5s;€¯O”â 2Š7IµNƒgµÝ¡h¢ýXïžì¥ö³&0ͨƒ¢Ì…?j‚0»Í¬ˆ¨ˆ¨Q1EUx7eà§3LÃWR)ÍŒÄ}À<"¢Ö˜`Ī1Æ”«D‡.;Už3àgîH¡ï‚ŠE¤ÚyÔj‘T"qJ¦.àED1j¬Ñv»­‡]WýWÛgõ̕ίø§¡°\¬­Š›b¥(ª£ªe°,õ¡XÙêr˜}DSÊAšÔjl¦(ÅTÈTTŠk¦ B£•¥N󃩙R_c§‘½¤pŒ/SíÒí:Ý“)9Õmiø¾ÊΪ^i‚RT†q‘Txfp‰t»þwÉØfÒ]Uš6=5“8wÞ4‘¦ïF(eÝ뇌mO9ðå–ðÔÛOC_ù#Ôg7^0¸7°«q øiXœ½ß´Um&F(|à€«³#z0Á7MÛ¯Lƒ*G(Û›Nár9ž»úâôaµªmbºì‘Ê4NC§Q¯#`ãA?=bmÿ±Žý͈Úp’Q7ÜÓÏ[·‘’m·*¾C½ûö ƒ/7R}Æ:*6DEŠ~cñvÌUÜ~@½û~ðaàî¯|]³V-*.--Q‘£ªl‡ô––Á9›ÜÏ1ûìô¨ù쮩1D¼÷8çÊö…êç¹ÇÔûJŒÊh<ÆU¢Á‡H–çBBñÞ“e9‹ø…rkš©ýmKÆœjÏìÚì¬öÚÈö¦¾´û 1Bµ_(G0¦xQ¤NáÿŒˆz>Ù!ÎIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/tab_remove.png000066400000000000000000000056571217176075400247350ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ vIDATxœí›Mˆd×uÇçÜûªjºGÓ3=Šg[’åÈD ˆÁã8 %de¯#¬AÈR Þd£Mb#ÛïdÈ&#² [N&qÄ䀣èã™LO÷ôGU½wÏÉ⾯ꮪéùìò×U÷ëÕýÿïùºï¾–Ë/ý ÷[.ÿél5CÌPq„|áù3ˆƒ(Øõ-¼¬@¢8I ªœÑCCžøùµÛž‹ÞE\JùG=£–<ñf>öW'@‚ˆ|6Ƹ~öìÙOÝÙÏ€ªW–úZ4Ëõù3<þxSão¿ýö›)¥kÀ¿æîiÙL–PƒëÏ=÷ÜŸ¿ôÒ_~åñÇÓcX6®Mûgnˉø’ƒÄd2™\ºôÖ/žþ«ûÆo¼*"cw/ÝçfP§^|ñÅW^~ùå?'L&RšÖàº_÷¥˜¼×Ç»šúÏüïËï7oŒã¨j8‹@ ‘÷ßÿ^{íÂÏÏŸ?¿ú›O?½:N1ëù€ý?Ü–ç€YÐw!øCŽ_F@2C5Œ†ÃáÆ3Ï<ó¹Ó§O—ÏýÑjee…ª¬P•pbmí_äÂ…×¾ýì³Ï~%„`M¨F­ã«ªJªª:D¶ð`‰“SÙ¢(\T]E˜N§L˪”ô?üÁw¢;)„@aÜP–92˜™1ÆX;O)MÄ̪zAc8Np_ÁIÚ0ç MY¶{ADè·?è’‹cÉÁóN²Kè¬Î8Awgkk‹Ý]q3ADT„²,)Šbæt/û÷kÝœd‰"îFJ&¢"+++~âÄ ¤!¢Þ(Çý7uwT•³gÎxJ ÀE„ÍÍ-ÖÖN,œðQÉ~nRJÜØ¾ÁÚÚf†¥äªê×77±dhÐZò ¹a°QŸY•ß_>:™¯¹`f9u7Ë—;VçòmBç~ˆ‡¢Š,=[ê¶ïí"6i¼;îÒÖ98·äj@ûÁ÷ÁöëÌ8Á£–ù8—›^ º]ë µYì'†€€ÃªöÂñ}PЭø ²À,Žˆ€;ÝöޯƒÐû4oýž·ÞKgèîäLâÎännGͱõÎÎ9¸Ú½Ð×:Jn¢"‚™™¸»,=»š3ÁÃnKæ‚wf R²ä¸k¤ë‡<­ª*¹»7)ñM'x¸Â-Ió»Nh[Þîpªª²”*ÛïnË º»—ei;;;rî•Ì1«ò)%¦Ó)E,¬MÞZ»7pm“"¸'耙ݹþÞ¦´±Û£ŸÜ0CDU¥œ ÖÏ̧"5à˜Ž0 žMhƒ÷z¢9ôç’4ÚÑF†Ùû-Ѐ­ˆø-ú¿»*7SûYèòÚ (ûÂ-A貕Í»Âû)·¾[az¾’Fif4Àû€ý|ˆˆÕ¤\Uµ~JtÏeÑÎsüLK}&.¸¨8"F0¬oXG¦Â Šˆ«ªkPF~¯·ÄÍýÝšd¥þ¬_þn](¬Ö6››”)™«¨»×Á²Ö‡üd[h·ÃÜBÐLDª'yÏ´ Ucí28pPG¤Ó—\§™7KíòƒÎLië`¡\.Ù1Þ}é´Ëç_mº'9M³ô|_cç=Uo4ÁÉ;C;L*<3¹»‰tÞý—dl3é®;}›îÌÄö•û&Ò÷Ò ¥lF`óc»©Üð­ÓoÆX—ñ59„CÎ {>`kþ´îÜ-ð]XœmïÛ¿»÷£÷Þ‹ÀåÙ}8Á÷}ÛoLƒ&G¨ûšƒûNtx§žÏ}}mö^·VÕsk@×÷A¤1ßv£›_ö€í¥3~ÀÁw—µöomìïGÔž“4ߎO<ùäàbMÂ’Y?àà‡·¯okÏßË!Ž}ⓟEà:ðïÀdùÔ?Dà›×Ûö‘š ÿÁìëÛRðVïÚ­M€ò¨H¾¯¹Gàr®’߇©_&¾ûaàþo|<øþS`œödWǯ60î#ïŸ/«{À[OýCdï@ !;ÁƘ .cùÉ瞺T8pêÓqé»ÿDUGƒ´/< Äë½Ûœ¨U•b(J½7£"¿fž_‚JÍ8¦•; ¨P¦æÆ^˜ÜàÙ?ý¿õ­¼­ÅŸþì’œ=s¦e­y¨¸ººZ«Jfvgw—ã««·ÀQmƒûlòV®Ù±uŒïî¶WO3,UUc¬ûgÕ/Ë mÏ73go<&6¢eD„*Ó²ìm$œªª˜NKã#ê£i:û›KÆ>Õž9µY¬öÞËö¼õðµÝ›‘Ì ¥Ö/dÀš_ŸïRç9»AUe4`iö_mò‹SsÿébøâÕ§¶ç)>w5é%,mÞzÀ¼çëštzí¹N¨ÁÓE‹˜ßÖTµee4r;B[5l^©sÃz€[ IêŸâÎ?ѯºÀ¡Îß\K43vww3s—tnaøÙPԷݦܙ@_ z“ܯAôVŸDÛÞ|ß×>Ó¶ø7>òQà#ÿ“¿"à¨'pÔòÿMjê7ï{5IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/tag.png000066400000000000000000000060621217176075400233540ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ ùIDATxœåšyl\Ç}€¿yoßî’ËCËk©cIJµbÓ±ªØZÕQ Kp[v-#íRÓ¢EM.âT 46Z±(òG¨Û (šºn¢Ø®•4Bb§)R+¶)Røà†SÏâ{6RÊVÇqÞmðp›Æìq¯‚ ¯»óäqOFŽÎ$<¨/ìáÍ$¼žé}û·‘¬©à…ð½‹þ ç.^m‰LŽâ8¹\U‹’ªKåáwÁwl{èOî0 i׺ ì™X¶€¡¬<çH!MGŠÇÏÃ¥žIC­fÀà`ŽÉ즫Vü¡ûUì›°rd(B ‰ ”‘áß>ð=Ç¢&•æÐÓGøì³‡ÙÖFúF.KDýXüËð[±'ÞÌÞÇ%/E­ (ulÊ|‡ ÅóùÙp–ÌMƒ¬aÉÜÌHL÷óĵ—QÍ!|¥¼ÐRˆå%[…¾R¢åR,Ø_x¸¶Eu*ÍÁ'pààa¶lKC<ªAtv3–•~ðÝ“ÒwÚF3fÝ«™GQ"i~NÞ :nG¸Ö;ÆÍILÖ$“1Èdrd29&26Žqƒmeo!ƒ1¤Ô0ÝŠV'(;V¢e‰kú<Aàá9ÉÚ4{?Âgž<Ìæ­ù3®â€aZ@D…{Ó•‹ŒüÖqK‡ßyóÍH„ÿ¢ëv­OòœxƒÝ|šHMšMÊ(ƘÌ̇Ïd³è™ ®ë3è=Ì–ò6qâ mÛGu]G( ¥ JË’(˜Ô8'h»ØL´dÇ¢ðB¸ n«Ì_îf»~–D²‡9ÂîGS›J# Û̯qõc&¸åÄ¢¾ùê¤=ßûš®ëBA¢4AEe¶apa Ÿþ˗ɽ‹© V‰œ†Ïu¨¨«f×§›æ_úuªRi”бòS]¹ƒî,ØÕ¿¿òJ<‚¯†±y¼e3Ð™Þ ½ ]Çu²™o`¨O`x›É̓w[A‘·s”UÕóó¿ðdhhd6|èA`ýƒTâ/(Õ{Íò-iòö‰MI6ïÜMeuªtðlsÃOÅôž?ͧ¿Ûéžìµ/©öA©Â•¡ÿxâ>voý ®9Ž®{¸æ$Èp$Œ7üá¥Þ÷Oìú¢I,§Róˆi QU¢àâ9&Be½ÄY2¦o…þÆm¿úí¾‡ÕKcQò{_@Ä(‹°-þ·H§§rï5wó^›ö´Eu‰hÄ6шÌߢŠ6u˪æo[µ¢úh¡~ºN+:N-ºÕUgþ§©³ÚÎF5¼hQø2ä:…;òê' ¯‘ByoºÒ0=®¾Öç«ý³áTaaÈ{œË©—ß(-¿&)}p ¢UUEósø¹ügïÀ KQH`p˜5À,fF% Ÿ‹ŠB^Ö|êÀøk¨Ê/Æ EleÇ–W‚Šªs¶¸W…Ž&‚œ‚À^CÈÅB° ¯S\ (*SùY! ¯þžŽâÕùŸ…ò†Ó,vlÿ¥åDà” iÆ Xï-™ !ŠÞ‹9Ÿ ŠêüÞ= ã?ÚGLmGÊ<|€·óŽì¹p©Þ¢NEÏ 45'4…·½Ú•ÊwÂÁ¸ÒmÕ°Y0`4Éu,Àé2Ñ—(˜`¨¼Ñÿ:Œ^Ž)¹°:Q? ³¸Ðøœ–g9IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/undo.png000066400000000000000000000112451217176075400235450ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞlIDATxœå›k¬eÉu×kUÕÞç¾ú5{¦g°Ý3ŽÇãÁ6RŒÀŒüñ! ¡È‘r>ÄR'RB,EQ$ Br¤ù€€!Qß 8à€£ÈÂdˆíhHÛÓñx<ÓOOw»ïô½·ï¹çìªZ‹µÏ¹·ÇÝí~¹Û@]UïÝçìÚû¬ýתõ¨-ÜGkÐ8ûÍt{}ÃÑö/ï{ßC­•¯~õkÜL“\‡¿£8ŽÏñƒÏ.Žeü|Ïóãâ|º¡ãÇ?òøõßüMü¬£7õ+o ™fõæú÷¿äÑî8óÙì¿ ó᜙}ÿ‹¶ÌLº[íö¸ræ~íç?ñ‰¿QtxÓÍÜB~Ø£Ñù.3áö¸òÇ>³qôÐ?|ÛSoÙÿd¬\¥O€Ð.‘O›Àü{îwWZ¼å‘#<³~týc[/¿~Iœ¥ñÒ___ø¿ Xèì3++Û¾¸½üXû‘X‰+9f,­µþS` ˜qÈ»ÞnM³ϬYûØîÖ.ߟÀÒ(MôcïX­¿lïÑ@¹GÂí0`!¼ñtwhò±K›™s‰ožû!Dxà8šÆkWhïAØÏì .·-Ç-·›`!Háé¸ÑüÖ™¯r3¼ðÒ‹x5bèðfX?®g ÇjtVä£ÀÎèÌ,„¾‡ÂÃͰÐß9O÷G''Ÿ{éY.w[¼tê%jqpèRb“ x7Ðc¦?\ÂÃà´Yœñ´Ò“_>õû\à;œþ³ï`¤’¸tù5ž`Èië<üP 7À‚ö£ðŸÿãÏðš¿Â鯽Œx•åe]L\¼´‰…€ЧÀçã½tì?$ÂÃ÷à ð‡ÃÉÏÿÏOs¹;Ïéç^mÂ´à³ØÜzi–ãm6~µõFô«}gŽ7Òë5>÷ýïÍ w_þîë0ê<ëœüw¿ÿ¯8+/rúë¯ pk!›Â·ß,|û»§yòGàØûרüÎn"Ò¼?=Ђp5öbé½1= .b‰aülŒ÷ ÔB)eù˜k°~•“¿ö»Ÿä"/óòsçÁ;7¤âQÙÚ¹ÄoýÜoðÓÿþã¾uq×=²†& Ѝ4Á# ꨮ . Dh÷wñ‘i˜-Ãa/¾ÀªCõ¦Žƒµïó¸Ô‡A¨Cåþ[ì?ß›?ogí ç7æ`ið˜pò™ßùevWÏóíÎãH»ùHŸ¥„6V¢S¢ñÈqìÈ1m¥_í˜Ä ‘:b„ˆQ"€ ‚ ãYk½ÂjúÈ\ǨN¥PqÜ Ì1@¨‚¸ .h ˜mçQ#¼S©§LDä XèÊœ§é8ùÉOý¯é7yù¹ï"HS§<^:²À{ z›ÙàÔ |cçyt‹(‘®ï 1B$ňj@S@UÑ DMˆ¢MPAiLÓt\À}4¼ŽUÃqj+•š V ²#EQH(J¨à%°Þ­ð—ßñ^ÂʾÎ] ÀBø('ÿÉo}œ éÎüù&‚mŸŽ^ÇYïÁµ oÉ :>QRìPN Ž™ˆ$:*†$OàJt%[F$4ã„£‹Pq1ñc˜ìÜ«ŽWÃjÓiËF5§äßõ¾¤B¨aÌ )e2pyo ™`aÅ›1yåäÏÿêGymõyÎ~ónÏF‘€Œ:è±QÞÂ8óÑðNШ¨À2AJh³k‰¢Á"A#™ESD[ÇÅÆ¥U|iÝÁݱâX1¨F)F­•š+u¨”Zðê0 È.Hm HVÔ…œ÷¸4}éxÍzþ z~êãÿòÇ8¿zŠs§6Sª7#c˜4//( àCQ€¦ˆh˜!Z£¼BV£#% hPD´©‚D…ê˜*¨á&¸)Þf_œâÞ¬€UjÉkçC°¡"ƒÀ\‘€ÔѾH 0°»{éÐM:¬Ö¯¿ý‰w<ù¡ôæo>ÍùS—À•R*Å 7§Ç‚7'' DÇREz!x‡‰“B@ÔA¨#TÁº¦6.Ž«¡! !âÁ(:¹ØØ("ÍÌ©@6ªÔ¦jÖÌ_öL¥RÄņ9eȘ 2WPAUÉÞ±µ»…ôûNI,!cø>óú«O¾rúaþÂ[W‘p © Ä…bNˆŽ®¶µw|RÑ^šI I$GÇ;k«c4JtB'¸´eИ4ûaÁQDFu}„6ÇæÔF¡šáZ©Á©Õ(žÉµ=“se¨sr- @W$5&°'ˆ‹\ÞÛÞVFPD>±}ñÒ'þã¿þ¯þ÷ûóø{åÜÙóé)ÜŒÒ;61jW©ƒ^КuŠÄöÐcS“Ôþ/Ш ‚¤¡Í´ãx0œŒ¹â₹àÅ@„j†ÂQ½RrÁ0L*s/äZ(e`ðæà©Ô.c t.~E!PJäòÞå¦/hú58l ÿöW?çþÈy5¿Î™³ç ±G@]©Ôu#l!EBH“Dß'bŸH} X"I"…Ž.tÄéºfBט´­ýJ""@B‚S1*•j¯N-›E Å+¹ ²² –É¥ý¿Za>Ð"„.)A¢à—óØn#^Éh´#ëÈç>ûßýïÿ‹lž=ƒs8ξ»º Ý :©ô}‹"!@çÄþjÿÝoSÛ#i¡„Š„¶ !ʰÛ»;hº–m}_EN}ë«þ÷ý¾òÚŸrY÷ˆÇ@AZUºIb²ÖûD¿Ú3Yéè&ÝJb^2ÝZÇáµ B Ä.&":&¬²Â ‘@Zz~F¡PÈÌtÊLgì¥)e’©sc˜erê(©°—fä¨Ä¤Ì£¢{B!Û@¯‰:sJ_±˜›MQE vvw ¿²øGÀ;äú#ÿkø«üÉî³lË“ ¤éW:b—è'ý$ÑM:ú•Ž´–H$=ú‡×ð¨4ïu’—ŠúêÁÐh‘IÈÿøß_ð~ð¯ó'áKìÎfľ´ÔGR¿/üdmB\‰àM|ágÿŒÝíÙ…ÍËNw‡Ò:Œ,õ ‰îûùKðá{k“p½Çêpj®=øÐ¿ô3¿ÈËï|–Ï}ãé÷È. ÑS[-Ö ÌÉ4#¯§™Ð#ðå?ôÿ­ñüѯ°¹w‰õ>Ñõ‰~µ£ë©O¤.±²2aÂ*ÛéçþÍækÏDŽœèÁG/Q íÆ1)šnŠŒÐ"\ í£ìK¸ÖÚb16e—üã;ïûÇ/ÿìò±¿ÇêÚ ÝtJSíF µ¯øª7z®ð¯oµdŒZ'Èç¾ôyÞÝý(o}ørÌÄ.S$M:&«úÕ¦ël0I:q?8Íâ‹ "hÐæ"‹¢¢×íª2ú ã9-Êc€ã¿ðéðäYÖœU™ºž®t]$u‘Øb×VŸej~tÈna¤êÂï|ù÷x¼¾‹½ÚUÒâA)&™ð&ŽGbiRVú•ý Œ u¯• ¹v[ÃVCëDW:â¡NzBšÐu‘8鈓ˆ†@ŒÔ5oSzÁ;oú€÷7´n-TWW‘ßþòg9¾ó(½ùµ¯ÞuÉã$zê¢â¨?ÀƒKÝmÞáÚêʘAò+õû¦¤w°æ >|hŒ#ј1(i’<¥à1&}𘢇<ôÁ5©Ë÷š I [E~ûKŸõ£çïãñ‡Þî6q‹“`k¬ÛQŽÚ1î· c¡WtЉ²zxµÉo7€FÁÜ9zô•C[fSPU!Jô˜: ]²ØG I-¤`! ª¦Q^ u»%dU…~CõÓô™š^èõ±#™©‡8Rs¤>ȃ¦Úhú®cÐX;¼¶æF©àÖ®­Õ8z¬ ¯¡õÕbQ“Ö˜R)Ô˜b jè´†jP%Q¥s;¸¹Ú ¢ ¢Luñ?|é3óá…ŸàɺÎzYg£â¾¢ !D%DAƒ QØ8ºÖ277 ¿»·€÷?x!*15ÝÞï‰Õ5j !•BÖ²Í!jVѬA²FÉ5{ Hð[`9H„ ÊêáÉäÓ_üÌtó¥­ôOå Ç82Q(Z—ÐR^¢Âáû×1óQÀëO Ä|S³+¢ŠÆ€ÆÐÔ 1¢& Cê¢!†!Ä0hÐ!„8hÔA¢*2H”A‚,Ó·\—„CGÖ×?õ•O]\ïÖV>zü'/?ÈqMš h~øU0v…õû6ØÝÜAchÙ_Ù_–3_*3f†¨~XŽ>F(ÉW‘P4-AAHh¹BUET‚„ý…ð¶öˆ(AG6ß÷ëþgŽæûÖ?\ëå Ãw+Àêêê2½uŸÑéY}x…×^} IÇ‘}á«qü‘‡›ºŒéryíp—¢*ƒºÎ£„ƒzÖÐJc"¤Õæp«GYÎÊím%rdãÐñßÝúO/üñ/=wìâê%X?²vÝO*ÊcÇNðâ×^DR\ººµVÞöÖ·PjmLópÕñŽ0†8̵Æ=Uͨ¸Š 1 RšàQUQ½€;¿ B'‘é±Ë?üwï;w˜õË0f†ôÚ½j¥JåÄ_:§ºQKåm'ÞBÅö}%½n7UÙSSE§At*"SŸJ”i¦˜L]dJ` 2E–¥ÚÛgÀq!æÈþæçŸ|êïœX ,ôô k5«áí?ò¥Ö–$ ´zÀ5‡;FÔ]1¦4·4ý˜ òІWDÀ1U鎴JLQdP|O¦lÀ9úE>´ù¾ëóV°,¹òÎw?A­ =Nÿu¼åeýHär@·Ùßg:¶7<‘¥bÞ9h T«±ûõ÷pz®ÝÇ+<ñ®w`u‡é Þ5Ÿ‰˜ˆîTµ]Ãç,ŒnmwÆL´·ú¡Utüî0·Ô¼Uú Y„FÕm  ²å”m£Î} —GÜ[[AŒ’ãï9.ÎJîp©£Û{³ÍLײcÔÁ¬yŽ­pb#Nãs´bpX†··$ZãÌæ\ê–aÕÌp³V@Å0·qOãÕqwqñÅø{ËÉÐãâWx‚7w ÇÍ*óíê¥Z®­^h†gÃÌ(fËj²WW\†Åø{ÀÂVUkæ[l†™;›ÕëN-µÖjÔêX­ÔZ°22¢Œªa(Îbãνe@œ6øVr‹Öü ?W«íÕ¡z)+…ZŒRœZŒZZR\\|Y»7ŒK¼¹µøm4ÃÌófCÎ%[É™’[ÉÜjÁjmÝ Ëƒ(æK¹ï>cz¼¾^Ç49·µmÎÜŠ[=›K)%«¹ÕK®­›Qs«/2€gÔÝï\0t³Mh¹ù|8P¸õfÙë·ÈC¦ ™2ʼ煚½ 掹ÂA»«ÈèßO_ÙkIÍ;°iÒQõ™uµä’‡BëuÜW±ìmçH6t&øQšÛ|õ^UÇ—ªä޼#ä4«_¬hžgòl äL™j.”YÛRãÓ¶]N¨z° þæó¯£q,nÜfø¸K̘Ï£ ˜Uj5lf0S|æøÁí€Ü%dQŠJ­µyow@ÿ¡Ù«•!gò0GÝÏóÂ3>8ì >ß·ùx«ï®1@£òê³gÑN[šì½"×ö %gò43Ÿeê)óB*2ØdñÝ$¿»ˆ4ꇤ”Z eáöÞ 4¿šQJn%óéœ:Œp:m[e|ÌZ1Ö è/hôæå À(cÊ7þàR±Ì‘1)Š1Ë{̆9Ã^f¾7àÕÈ{»à;NÝ6l ÂÙ‡¶$ŽÑÀ˜£î«²7ß#{l%ñ;ÔZõ¼òî£ïááô0¯¼öefmsåÈøضcÓ¶;-×ùȆv»³©gôþ–åí;ô§ÑvæÜ+öü‹ß²í]³aÀ†m¬lcùÒx¾…Ù€•)ö®·¼Ë>òŸX¾ò-7ýŽïÿCMäje›ÿÏÚÿÝ z MÛIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/unlock.png000066400000000000000000000100511217176075400240650ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞðIDATxœÍ›yl×}Ç?]r—K‘¢HÙ¢LÉ’mÅ¡|Ä–Ô1¤-Û)P HS4n\Ä0µ6Ðmƒ(Z×iÿHÐJQ€ÖmÒ?$u”1ÒNe¸q“8b5ŽYG$GŒš\’Kî5Ç{¯ÌîryÙ‘´ùÃ>ÌÎμ÷{¿ï¼ßùf…sŽõJßüæ7±Ö¶Zww·t¸­ôß÷¯–RöcÂ0 '£(:åyÞ‰x |1<ô;5ùN’çyCžç=Ëå>Üßßkÿ`oo¯ò}Ÿ0 ™››£X,ÎONNÿÆ7¾ñlÇ_BüßG>òóvc‹õ¼<8€à<í=²iÓ¦MƒƒƒAhL[)E>Ÿ§»»çÅb‘Ÿžú©ÿN½Vy—µö[³³³ÆFGGyÿûßO.—ã7Þà™gžabbâØÀÀÀ•RÿyáÂ…7ÆÇÇkRJ_1äœ{_íÚµëžÑÝ£²·ÐK&“áܹsÜxãô÷÷sîܹäàÁƒŸ}ôÑGÿ¤Éw]°ÿþ>Ïó>?33óÑJ¥Â]wÝÅ?øA‚ àðáÃ<ûì³vddäo‡‡‡ÿîž{î™kö;pà{÷îmõɽŸüÍ?{çž;‡ûúúÈçó‹EöìÙƒïûŒM>÷Üs÷úÓŸWZØUhO¹\þh±Xä†nàø@Køï~÷»õ÷þÒ{§P(üy»ð ž$É¢¾pà _/‹¿:66öÒ›o¾IqºH&Èpôµ£H)Ù½{÷ÀÐÐÐ5ï_söíÛWpÎ}tff†B¡À½÷ÞK6›åäÉ“>|˜Ûn¿mï½ï»÷«÷ÝwŸýEÇ<°ÿÀÑÉ©ÉOœ0Z«×è)ô°uëV¬µœ=–\.÷tOOÏËõzý²xDQô”ötmbbc d26mÚtõã?>¸¦!|kí¶8Š)ôÈf³”ËeªÕ*Ùlö}ß/Åqüö½I!ᨖËåV´(„ P(ä´Ö[Ö lH’$Mr€0 qÖÕµ§O'IB’$Œ]2Boá”Rj2 Cjµ•Jšø¾ïi­{ÖÚHç\ÐLhŒ1xžW*Í–ÊÆŒ1Ë\ÝÅЃ{0ŠÂh* Cêõ:m+J !2k]p€³Öb]ê嬵8ç,`›‚7cüK¥Ä$qG$IÒºy\k€t2Ö,`ŒÖZaŒi]¿Bˆ8ŠiŽ×>æšàœk•¼–ž7'ܼvéLRÛÒ®jë!BˆTX» l³uJâ8^dKš©ôš¯ë,Î.AcLgWEËm€sn`¯€æäš!.kü#GŽäN:…s®UL9vìXîСCÃkÀRÐ|òÆ¢(BJyÙìÛ·ïö¥¿Ýÿý|êSŸZ¹@úÔWP!q¼ØzwšÖ€v}l_Î9¢0ddÛv‚(ŠÞ±9¬)££7DZk>u ©§vËðV—Ëå¹öÚ—­oEkf^?v¢ „ØÉd‚f‰»V«†!BJ%¥ìq/—ËåoºùÖ ¯¼zÔ•k­…böúëv¬ªCâÅy0›Í>áYk-J)¦§§³SSSY¥4q’úÏ8ŽÉçrfÛ¶m¥Ë–Z›gÎŒçææçüÀGµZÃ9ËÀÀ@¸eË–J’$MCÏ—ç÷ÝqûmOt‚“ô÷ðÃG7oºzóÐfº»»R}tcˆ­=²™,RIÇq\¾k‚Tß•Vø¾kìuåò9¬±H©‚8Žƒæ>ÀäÔÅâô£/¿üêßâ÷~·zṲ̀+Õª=3þs¦§gèï¿%%[‡¯&ŸÏsþÂæçæ±€D¶\ÓJôV ¬ϧ÷;”LU@JÖoNN233Ãliް^Ç!¢À×5ZJé”RXk™››'Žbjõ:7í~7Ã[®Æ÷<¦gg1‰ií͵‡«Kcëtç²]JÀ¥5…N…•(¥ÈuçÈçòhO“Ä ³¥µj¥•J…0Œˆ_ç–¹´æÙ˜”’z½Î«¯½Žs龜§=ò¹¾ï£”BJÑzqìÞ@È¡¥”H!Zˆ,ìíEœ;wŽ3gÆÑZÑ××l¬Šw’VôJ)jµÅéiz ´ÖÔëi¢µFkݰ ßóPZ#¥lïhaÐiÂÛf–g± ×眣YùI £B©+眖q€)ä¢0´¹tEÛ“³Ö’V5š;µÖ¦‚6ïi×ýæùÒßñ@¼£~)­us—2‘´Ëâ~¿xA£©.Íö’iEs.D:‘+N¢‘û‹¶W@ÞaZ)d‡ííÛ“„\IΫ¯€t6Wl".eœªÝZØ€v#'¥@6‚“‹iCí}Z|…@5T`ÙØm÷v’´séÓnj\jÑeƒ_j­kuIœH¼D¢µD)Ùd$]YP*u}- ß6šµP«ËV\°àÁZï§~ÄÑ\žqœƒ(’ıj”Î;›Àj_•U­’% CÂj¥Õj Òý$ò9›Gçð<Ñ bRK-Á ~|da¤‘Ò5„„f `,ä»Þý®Rê Ú®»†?yµ‡rE†J¥Êìl©lqbÐ:⪡Lb‰UΉŽ" ÏŸþGóß$›Y¨˜ÆI‚s)4JÁ¿}ñ5v\g \ÒÛƒÏ<~ Ï>ßKW¶‘q¶¹A“ú6D|ë+¯Ó;Ä,öìûÜ0ß~¦î.Ûˆ -B ´RX'éÊ$üáï¿J>ï(×Ó ï;·OSžˆ#ÛÒ/c PR0_Öü÷÷rì¼¹K³ê.¸õ¦YþýÛ8³Ìs9àä)ÉØ‘.~åêreÚÿ«}pkÓLT PR€€é¢âè±nîÜSÆXè@xñ®ÛR($³$rs©þ)iùŸ²±<‰áŽ÷ÔéÊš´?‹€1¤ýW²]1Ü~K|.íßäÛ² »òÚëY~áXê"In2\»-"NVV-߇W^ ˜:§–Ç1\·3bë–„$YÙ:ûžãð²Ä%jÉŶmKØvMB7û/GkÇOOg˜/ :°?²Œ¤¯aô]u–^ê µcbRsäÇhH·--†L¯ãÖ›êDñ*øŽS§=ŽóR–ô÷»·ì®/°$þPÊ1Uôÿy€–t|%Ȥ£××ð}·êàÆÀóßï‚l¦­Ã]·®þ‡P®H^øaìâ¾&B¸ã–²±:‹×€Ç‚ãdz îòÞ—XF2¬Âö-›6&³Àº}¾ï;’¡>% ¸h¡Q†[vÕéí±«()á{‡³PYÜ×EàÊpãµ!}½cW^ERÁñ“¸KU`å±ã:ôvY®ß¿…Ÿþ™ÇñãÒ ZR­ƒ1;F¢UÕ ð/ ¸pF¡ÌâþQ6÷%ì‰ÚìÀbÒÊrîBÀÔ¤FvÚ Ø„Ý×Õ°«¨€0_•üðÅ,˜T š-©ƒ¯à=絛  Öމ)Í‘Ÿ·¸¿ !pË u³Ê P®*~v&èx_«lnÞ>‡¯º¨V`Ó¸íÆ°.ø¯ç-Ÿø0Èd‰1’pÇ®"û"MÙ¹s™ùŠäÐó–Ý ¢-l ·íœÆŸjÍ!iÙ Z1Š$¯¼.¹q¤Ãœ(þ² Ê á)~í¾ TëR:””x¾jÔ “ôäG§ç |hš+!Ú ®ºNòÈ#=$ È5 ¦@’ÀÐ@©ÒÖ5|<gÆBa«ã·~»‹J%ÁaŒ5Z£ÃG&HäÉ™°³Uáïø^@à{<ðÙL€’ ðÉåò¾‡RÏÓH©©Ç^Z.k$DR*¤”lVð§wÚ…dÈ5+AMï∨ÔÒ9l#òkTVÙ`"ÙQ¦R­G1Ö9¢0"ŠãÖË Æ8.‹ÏLÛ Èa-KW6ƒçûd3Qøž§JH ¢(H D …3‚ryq½oiýÏ9‡hž§é`zÝâ(¢\.S)§¥ð8IÃ(ŠØ8±ÖY­uGÍ \T®– õÑ(ˆ^Éúœ²5—åõ‰ô· Õ¿Ž‘ô<·Ä·ö®pML@cob9cçJI¶ w”gšs-‘t¡Zseh=õù¶v“–f—E²Z­zKËÖíµù+þ’U1wT«5ÏZë>|¸#OGk¥Îž={îæ|.Gd2™L†L6C&È´ ŸÖ©!ÔJ5<€B5¼€R²µ1’º¶¶ÊOË+,TœM½@úÝb¬%Š"jµõzH=¬†Q”¶8Nëuººº¦´çÅcccŠÅY÷¥pûm·þÕÉS§Ç­±~àkOkÏó<íyžÒZk¥¤’J)%¥ sÒY«¬sÒY)…4"1B!„sN4$o†¶á mc»È:‡u8뜳8gœsF8g”&|#¥L|O›$“˜¤ñ‰ãØ!æ·\ó•À÷­µÖBtä½Ý××{æ®ÛþÆ9rBÐ"‹sYË›¿ptš4ÁUÎ!I«•-Ã!Ú_ABZOJÒ&bÒY#\|é÷!ê8:¨ç¬I#¥”ÓL bÚZ§¤”³B)„P¤îQ¶ Dj– »r%#¥¥¢ösÛ<6_Žn|O¯9g]óšsÖZkÃ!š÷t„uñ·¹µ¤ÿQõçÓúWàIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/up.png000066400000000000000000000054651217176075400232330ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ üIDATxœÕ›kŒ]WuÇkí}î½sg<Ôf:ÇÁ6„5•(mEHpEªÔ–~h%÷  ¢(JÒ¨å,U¥JQ[ø`‰ý€@€ñJÔªBxêG<¹ãÇÌx<¯û_O¸ðÂ"£…ò7Fa¸¤Ôæ3ž›L9vxÐŒÑze ]" ðx­l|TÚO<ýû|rÉqáÅf>æ70{Âú Wóž;ŸòÈá!\‡Ã­°ìî[éøîØ™xêÄ<ÓTfεÙEÄdsM(à v–”sóž\=¤ë–pk,+ßÌÆöùtâéÏ<È?´`êl`Š­ók°‘ äç«ÂHI©-žL9öª!Ê*4Cw-aëÄ«Ê%iíñÏ>ȉ:LŸ5F5¢[÷[ ÉR[èðýó)o¿kˆ’ënœ°5–{¾‘íóií‰Ï½K0svQb>Uí‚p®pŒ;|o2å-wT)‹u„Í`@¡‘½¼’Õžúü1>Ö‚¥ pÄ÷¼ÀÈ¿i†šS…^¹¸”òÜt‡ûî¨0 BÚ… Ôæˆ–+ßÌÆT²Ú“_8ÆÓ X:#&q“Í/3p‚* yárÝøÑtƽã%¼æ¨M6ºö¾7}æŠÃKÇÚþåaž¼ g`„<¡£²aGvªPu0Û üôJäÕ·—qDFŸ¹°åfoŽRƒz:öÊA­½ï ó‘EÈÎæÊoìé»U¨ªg¾•rj^84Zð™‹[áÆزÙwÆŽŒjíC'æ£ó¹ò;½ŠR7„ŠQñŽ…,0ÑŠ-“ÙóO—6MÂõ 0+z¾3~ôv­ÿâ1ž¸¼VyÛªòD¶Lž…¥L¶"÷”"{>7µ)6&À 2ƒFgüè^?qüßÞ·§€Byå”ïH4O`O¶…;w•!FªŸ¾i®%À(z>B#¿çàÀÄñ“ðwÓà^€AYu‘­Ú¸º—U[¯¡€÷°ÐÊx±#ÚSæÈ>;ys$¬C@aö쳉?ø›·ò·¸K0XŸ€–VmI±•@EOP¥-JÈC¢M)*j¤‚®+å8 I„z œ€ÑrÂ{îੳK7$Á_ã¾#Ð<þØkùñ?;È;¾¾Äâ®!î¼ \'çç*YW;_²´êÂì\B³.”52"!÷×DB„fi™àØ·Óã<,-˜C5/ ˆ¸•‚ šoN?(¤3Âw޾s¨Ã=–øêÙ‹?yptï†íò‡ßX{$4ÃþS_yË ÿõü4úÎoÂÝcÈm%|œ„<{!šWoyd'BèDÚ‹^ñÊ<û‰{9øéSØáW0’µ‘NF´€5#H@Ú3‹X3EËSãdÎqìÍâ׆ùÚÉEnû`¤>IÚ$`à¼`&à%¯Bá?¨X+0÷#Gý[ÀÿFÞï9ü€Þ?7¿÷ó?ßuM¤æwï­®5€ÍN8w×»¿ÿuCŽüË»‰!2—)©(ê æ£O‰ ÔÈÌh/ï{ç^öíð¼.4øÁb›‘ª²µ-+¦#8ñD‹ì¨ï8RåÛ¿hЙ^bòÓ =äi· Æœ(q’{àåò™ÙJ$¦Á ƒ÷ÁÈŸÜÅ®,5N‡ßÅÉÏ©kXc˜"Fâ(½öÀŽ¿¿ïèèByçà~X·òÿ6KY¢¸¼^(R\#ˆAŠ,|ô ö¥OýêζúùÈ»,’]‰I¨G.78«ÃÒ’![wîígNÞ¿ÞñðÝbÛ^âÒ•jÙ$ª¨Å›Šœ4…t¸ ²©pþù¿½õêç гº€çT›Š•Ë ¥hí¡xºG"=$`¾êI²ÁŸ1çÃÉúóàå ‘LIn·+½’zH@šÞbœX®ÌfçØ›BïJc˜s+ß·ˆX¾£Wè]qô†ZO“>£·åñë% ^úoó™— z÷,öñzhÿùï¿/œB°j.°m ÅuÐg ØÎtêÆôy$ØO rô·y}‰ˆÐ? Æž»×G_Pl•Îýõ„ý³€åòù²}²‚¾Ç]¨¢ßúN@¿Eè?}žõ’€ë¨¶’ó¹™1ÐÓNê]BDX jEIDÖ‰ú,ª’‰¿ZiÁž‡ÈojB$ÊE‹† )ÑÂÕç}‰âuò‹F]É›@«SX‡ ‘8Ù3é!»&\´¼ÎØ$Q!Ã)4så Á,â#•1 ¦ fÍÌÀ1X*.ôJFè%ØL0p1Ìcˆýú“~¥X´¶|ª†µ3TAKÊëTsº‰žŒ3™„pYYíȃ @^ÒRrµh#ëä.!õžªÁl¯d„ ÆlÐxZ3II‚¬Ñr5 ¿h²²èÂÒ,Œ†wZŽ0×+¡—CÀ˜Æ)É=ýr¿GŠeßÿë3èdˆ Ã%Åa¿©ÓõWK|4MU¢‹Î¢Ä¼œ-ù*Ð,*âÁ%3ËÒ¨U,Fæ{%#€ßÿÄ»~S3ðÙf'}>ú¬BÕ;Ð/>°«~ ’/ ïä×é[È¢z/•²‡NŒK]pü•ÅîOÊ×f.†¬’Áùj¨”¼&™¨¡xB'®Œ…8bša‚1×0Ù¿Û¹òà€ýl²Uﺀ«àoî~,dfX”ðÈÝ#—¿ø? ³•¥:1ÑXr`Þ¡ÌAóX€ûÇÄÁpÕÑ®§Oü-õûGÊí® ¸ þm¯ÞÑõ›ëˆâ{+íÅúŒ”§æ-Y"+ùbm`‚JþŽ‘Yþ ™3G35^XìΨØºÖѿبÄÜøŸN¦Ý¿k¾xDNO-¸]ÞŤ3HÅ‹`f¹KPƒˆæë |I±Jµ‚8¯Ù[?uA0³&Nßúо-‹ê{Q˜È ãf©‘U+ŽèEÁ)¢Ób]Ïò2³hùºBÉÉÀW%6Ûñb¶üêy—ñÿZ8#=>IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/view_choose.png000066400000000000000000000051531217176075400251130ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ 2IDATxœí›K$GÇ™UÕÕ¯yì¼Ö»ãÝÙõƒ‹—‡%[²‘àp# !YH¸#Ž|„Ä !N.ˆâdNpì XÛbG»;~wuWf‡zvOïÌôxk¯Cêéê̬ÌÈEDFDÅ(ái&}Ù \6} Àe3pÙôÔàÿà'¿üöæróû±±D@H¯S£™)úE²Æä†‰vòIŠ!é…Réwö7ÿ­òŸ*DqR*“ök]Ì«tÒSôížVʉЙŸù;÷î}ù›ßýÎÝV‡à¬Ã:‡µ‚scÎ%ë\Ú/XçW\;'ÉG’6±'’Þ'ˆ\ `Ö.Î%›Ð ¥4Z©d#*ÛBë¤]k…Ò­A+´'›A¡xf}‰kË<Øm³{ÐeuyÕ+MZ!½~ÄòRÕå÷º€bu¹Î/~ýÛW}‘î`H«ÓGtóɆò KŒså¾tÃ’^§8—Œw’ü–Iæ—´+Jëtãjò['àh ¼J“|‹¢Rñ¸y}…½vƒv'޵&»†Ñ˜Q<æêÊö:„O-ôèv{¡pum‘Zèc­-6çë$úN$ÆI&ÅÓÌÆ‹Ò e @Gˆý¹(§'{ò©X«LRIÉ$@iUHŠF=¤Ûr}m‘•fz½‚5Žg¯.a­#¬ø £1Û›+T+Õj¥À×ZÙyÿ]¬ç\¦e%+;K“º¨™aIàÍh;‚ÔQƒÔŒËŒM›|EmˆZ™m€îºé Å{ZsëÎ h­ðQŠñxÌ;ïüÕµUœu%#TZR¥ÔPjQ…1S¥1ÅЉ{âØ+Œz{,„€Ò‡ÇN.Å$c%n”*7“÷–¯Ó>­5N—k7¶…ŸÜ¯¸{÷.7omÇãÔâª\4“3Ú“É•§@t*²ä:\Œgj.…s–_ýîO<³¶Á«Ÿû ƒa4Ñ™U/¯¯§øÐ(%(­Až7{½r[£ÑàÍ7ŸŸ*>$GÕ`0ààà€ñx|ˆÙÔ6›ŠÕ$£ÅJV}z>DˆÇcö÷÷S Ýž €—ÍDï§ùÒe>taLËc5OÏ`½_ZZ䯳›Xk‹3·,ö×*·Ùm…,& L«€b4ŠpNÐžÇææubcÓs}JÄ'®g­û8q/©dI*• J©ÜªùYG£Qgmm•‹"­ÉÓJ±ºzqëBÙF•pîtaqîYËx<À Bªa}„åRÂpÿø!“dŒ¡×ëƒBa­Áóš¦*}$H2GIHëÑÇ^Ì) 9YôÅféæÀCÇ“â h±ôzºÚà`d9èŧrt’|„;~ 6à„c•ÖAp¨ëX²(¥¸¿³Ãææõ‹Áý!^PÁW‡Ë“ÐÖö67Sp"A²lç1tj €ñhD§Û¥Õjqíú­Õ!Qmø Å¡œ¡oÔ©ü€$Ñy±6àØÕ´çQo4´ZT*a’ˆLcí ‚€aÑvš7ª¬/Ö·'‘NdÃ0dm}Z­Æ»ïþƒÅÅEêõ:Æúý>Q4¤#‹ÔjM>Íñ•W7Ï›ï3£ ”b}}……––—‰¢ˆ0 ñ}ŸÍÍM*• íN—0Üåõ»ÛçÍó™Ò\Ç`µZ¥Z­Îì[^Z䋟]<¦.’žúwƒO=s»ÂP8)ƬµÄƧé0e ß#\]9SFÏ‹RN¶Žã˜N§Ãh4B§ÙÕÀ¨>æÃ‰?¸OÇ)V_{½º|>\Ÿ!åPv;¢~¿Ï•ådc™Ó"qLëÏoãµz4®>Ãhœ}ì\IZz2œ¾¨$iÁ¿ç¶"䎈`­¥Ûj1zïß,Tëøã1z8„“5—L©œ})mL)•¤Ãã1˜ ÐÎà ú +N®Ó1@^=b- G`,juG«ÀT° "Ðëvóy‹²*•¼,e¢bE&Æ•Âd)¢Áz½Á›7Ò ¨X{þ”˜L¥Ä²MÑkÔ Ÿüž“övwi·Ûù¼gAÀ›7ŠÅP꣥Är欃N*ªÕ:Ï=ÿüÜ÷œšÒ—³ù1˜=È㌱5“Ý#ãâ©×P;ëŽ4-ÙP.ºº(*¯U’™ú>LNk'Ó]ⱉq‹ pµ÷öR#ø¸¹dFŸÐjµèu»ÕgK2ÙžÙ)ìÂdÅZ±S¡V¯sãFIðVSÒZóèá#nmoa­ÍówƼ Btçæ¯#Øß‡8>Õ1xî6à(§ÆXú½tºý•J€µ…£ã…!ÞÊèv`µˆµ€4™|¨íöçæl^š¥fǪ€Ö Çþþ>íV k "ÞD²4Âf%†=´ö0@Í©GsƒZkê>¤ÝnS­Vñ}c"Œ1DQÄÎî.nç>a½†ÛÚÂ}ãë¬m<#‡˜%&APáÚµë ‡CÞúË[lmoáyõz­5/Þ¹Ãhã*æ¤ÿÕ¯qóå—´ê*pÂÓç¼h†Ìæda¡ÉK/½„RŠápHµZÈàŠ1´ßxƒ›·o?vŽÉ5dêúr˜ËÊ6\¯×õÕ›MêÍæÙpu4í žÔ:“µSÈŸûŒSá<ÉXÃ0 ÎÎçÍ:.Oû4Â&JyY¡d)Ä=ª´ëŒ()/×ê Y7£¤d?ñT}Dh.,°ûpwŠ÷úó’J½8HÞ!JZz!䃱–ZµŠ ø"èÅ…&ÿü×{¼÷Ÿ{¹‡—èiojË®™jËÝÕ¬¿pc]æ®*ˆÇ1KWoóß÷ÿÇüÓ¤ÞòjЬ¹¸¿ À÷‘¤(ÝKÊÒÏË3UVLZ&KR –Ï¢’°¨ÕTÃF£1VßûÑÏ¿Tó­v«¼Ì;öAÿ^þ¬žeÀ<ã+„6f4]¬?9N+U«×ªÖøzR*6/‹žú#ŸpÙ \6} Àe3pÙôÔð¢7»uãxŸ-IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/view_detailed.png000066400000000000000000000047641217176075400254150ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ »IDATxœí›K\GÇU÷ÕïÏxìØ“LÆq“EŒ`Á@‚°Œ²ŠXðX²ä À$6ˆbÁGÈB6ˆÁFJHœHlÏŒûÝ·ûVÕaq_Ý==ãÇöxl©ûÞ[uªî9ÿ{êuꔞeÒ'-ÀIÓsNZ€“¦gÿ—¿ùãO7W¿HŒAp€ˆ€€ ‚BvŸušK™/‚'¦fÒ)*)Y²¥²kþ_<«âQåL”e”R)O–¯uY¯ÒiN™_¦{Z)'Bgl~çï|þùÞûùÏ.ï¶û8gÖ9¬œsëp.ýYç²|Á:‡¸òÞ9I’¦‰u8‘¬œ Np€yº8—*¡Ji´R©"*WH¡uš®µBiÖ •NÓSeP(^ØXá¹Unïvؽ×c}µÉú™íîˆþ fu¥Êúj;{=@±¾ZãúË5_D¤7Ñî$S>U¨PXJ`œ›ÎË–ì>À¹”ßIú,8 ’Ö'.MW ”Ö™âjöªSp4%ÞJ“^E†[רëô¹×àÄqîlƒÝ{]Fñ„q2áüZ“Û{]¢À§yôzýÈ8¶E5ò±Ö–Ê9Á:)¾¾)€q’[@ù5s~‘ÒdÚÄ‘"e~aÊ™âä_>3k•[@f)¹(­JË@Q¯Eô#.žm±Ö¨R«…Xãxñü Ö:¢ÐgO¸´¹F% ¨TB”_k6açæ ¬ç\ÞʦZÜôdi¶-jô¤ ð¤Aê(&µà6Ó¦—¸q;ï 7„^V@¡"@ b_k^¾ü:Z+|”b2™P«Õi­¬bmZãt§“ß/N+ÅÒ ÒòûÃÓæò¤M¿÷è´£óÓEŸ|ò)“ÉPø9³±/ëd²b”TÔz$³iÌäÏ|áÕMåO ®K>5ÃÓâm\³Ö;OÒÑ {éPU¯×YYmaŒ™ÕÁg”å0¶¹ò‡‚2]vQÚ\êÂ4uàö°2Aàyºƒ}HÛ}½Våü¹s< ¤µ.ìâùLðA !k³¼ ¢…èûôøO- €1†~¿Ob …µÏóh·Û  FCbÇ|ûÕu"ïô °"B·×c¥ÕBë²ÕLŒã£/&¼õzÑÂn{Œ;eþ•¥pΑ$IÚy‹!¡?Шxöª‰•§™ÓÌZËpGlØ<ÍLù•RˆsÅòxl@œ#N\Æ÷”õP®Š&¥['Œ‡3 kqsNÖ›7o²¿·w ¾W_{f³ ÀÎÎÿÛÙyù%Ï÷¹zõê}ùŽmé N¥Žœ†qÎЋ‰ ßë±»»{ ¾—··‹ûáp¸ç«ï/§Ú5Ôc”.eÂ0žàãØL˜3¾öƼ~åÊ‘noo³µµµ¬(•–ÀC’$ÅW‡´ h±ôû1ºRçÞØr¯Ÿ0¿Ïàyž7¿6æØ<Š WD)Å­67/ÎÁƒ.®Uø¼=¢3ª¾>À“N‡àœc4¡”¢×íræÌa`Œ),!|ZÁˆý^⫃Ãå“N‡.†0¹{÷.ív›$™`Œ), §ºZÊc{êæ‡ =Z½Îh8ä^»MF©2óßA@Œâ˜îа;Ô\9Wa£.¹ €RŠ šÍ&+««ÄqLEø¾Ïææ&aÒéöˆ¢]¾wõÒã’ù¡ÒRÃ`¥R¡R©,Ì[]iñý¯·ªP“žyÐ3À±\bùøoŒÁZKb IæSÆQ÷=¢õµG"裢 UÌá›É%IB·Ûe<£”>æË/I¾¸E×)Ö¾û-ôÚê±™ßý}¤4¥ãÒ09sæ @á“$¡ý·ðÚ}êç_`¼¿*¶ÖN-݈PL„Dk-½v›ñ'ŸÒ¬Ôð'ôh§ €Ìdf½¿ˆÜ”bJ©ÔžLÀ$¨xˆvo8@œåÀšx zœ‹¨é7Ã'8ûe‹¨ka4cQ£uÊË»ÄdÎ%–1c "Òç)JcJðòr¾ï}‰µ6Ý•žs·‡TV®ÜëÓZsçÎ]¶/m_Ï9‡1/‰/_Æüó_ûû$ˆuÖˆOˆ¦,`¶ XkôûÐëu†„a€µ¶°/ŠðÖÎ@¯ ã8œá‰G`™™`¾¸¿¿O§ÝΚ€7ã, ‚€¨Ñ@‰Q­=$ OѾÐ4s£€Ršj­NrûN‡J¥‚ïûcŒ!ŽcvîîbwnÕªØímÜ»ïrvû҃̃NŒX@)}\¸xQ<âï~Èö¥KxžG­VCkÍ•W/3>óÁ Þù [ß|‹'Þü9æL°Ùlòæ›o¢”b4Q©TfbÄ:ï¿ÏÖ+¯< Y9ÍL„òß<©,^­Z­¼9Uë ª—§ÊìÎËÙý)Òä©3h£*âìjê÷”S«¶J=j ”—J:&ã f’$ ³!­izÁ±(Ï:9,{©ò9Í×3¾àAëãuq€à#B£Ù俟}Æ_?úGž…·;ÉcýËHñ<"\$õàSçÄ•³Iç\vx";½æó÷ô|*;à u«µ"1öHþZæ®ü€(ý€±ŒŠsŹƒ<²<«ûÅJAðEЭfƒk×Þ&±kc-ÎNŸÈFØò ER/ùù—…×g¡ðEØ}.ï°.]Cä 8'å¹€<\^k´" ™Ï¼OS¡õ hÕkãÐ ª•* ¨W*„¾ïyŒÜßÓxZe‡*¼ô>K ÃkêõúÄ_½pá·¿úõïÇv'ÝÔ»o(÷eyXݨB-ñ¶YþÈ&Œ 6PZ©j­6ÔÕúŸÕiÛÏØôÌoŒ<à¤8izÀI pÒôÌðs¢æçÈb«´IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/view_icon.png000066400000000000000000000061461217176075400245660ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ -IDATxœí›ËdÉU‡¿ˆ{3ïÍ›YYîªê—{º§ÚóðLÂ`˜aĆ¥…XXHHð°´wÞ#„BbƒX°gãÅØ3€¼aÁHnc»ÛtMwWwåû¾"â°¸|TÖ#«j¦±¦”™‘'"ΉøÝ8'âžPÎ9~ÝI)uîºúÛñkI¯xÙ xÙô¥ÀÿþßüÓŸÞÜèüenl‚DDÊ´erÊ+볨0ǧ2-R&ª9LUßõUÿ]œè”*xªª¥ZOå*]äLó§|O+åDè§æïüý_üâ÷þø/þlï 7Â!8ë°Îa­àœÃX‡sÅÇ:Wæ Ö9ÄMÓÎIñ‘‚'ÖáDÊz‚8Á•V|q®è„V(¥ÑJQU‡Z|­Jk´­tÁ/:ƒBqm{ë;<9èsp8äÊÆW6;ô1£qÂÆz‹+mž>Š+ÿøÏÿú¾/"2œÄôc);_t¨î°Lqn6¯ì°”éçŠòNŠÿRƒ"… hø´ápø»W»´kí´sN°Nê§ïDj`œT#`ú4«ò"ÓÑ ³#A 2ͯ‡rÙqª'_kU€r¤T#@i5(ÚQÀpsãj—­N‹(jbãÖî:Ö:‚¦Oœdܽ¹EØl†M”_k6gÿ—ŸbL£Y›“™ô¼-j–̤ ð–ðN uR!µ$Y5Ó?I’^57Àpò‚B1A€đּ¶÷Z+|”"Ë2¢¨Mw}k ‰³“N•^Λ6K/áUéãy ùGx³zOæœ_<Ä xðàgdY(üª°±¯œdÊjL©–z"ó<æòçžðq3ù³ ×Órj®Ì6ïäÁ5?z³4+VƒRÅRÕn·YßèbŒYTu¤áså¸b õe¶î2Þw)OIW§Ñhàyº^ƒ}(ì¾µØÝÙá"T/Ö–C ¼F@4Ñç߯!çZësëÓZ×ã¿HCŒ1ŒF#rcP(¬5xžG¯×cÜÜ&Î ¹Mùæ½+ÞÅpÎÑ °Æ–Ö¢HÈùéð £d@[··¯³¾~f™ç@D ‡¬w»h=]2ãøäaÆ×ßè Z8è¥89AÐ 4ŽØX_ŸãýÃOÿq|ȵ ƒà“cV’ynœsäy^ §Ú=Fã1ÐÃèÂÎr+—€WëpÆÑvŠÝu|ÕàqÜ#W_²Ð3k-“8!1ŽÄ‰¹<fõ9ç˜LbÇÏ [!™2LTBöE˜> (ìQœ«7L©qŽ$we¹‹Ï³ú¤t³AHUŠÆº'v%™ òk(ùÖ iîp&'³'—3*7ºú8„Lrp†\r2y # ðéUÝ0g…IR4j˜8r{9,š\±å— b& d´’ÌK3â ¡ØÜ8„I’áãx>θ¤0¸ˆÚDç1ž48t=R—®$óÜ'BÖò<Ÿ’h±ŒF Ynx6Ê9ås@—‡Å9B)Ï:Cž[rgèKŸgîÅÊæ¶³¶÷xŸ›7oÔÛec Æpc+ä óY?¥åësPÕKÓ”^¯ÏÞÞëÅöÚZò<'·9o´^£çüÒ="µnÅ%g%pÎÇ1J)†ƒ››[4› Œ158†O·³ÿ"Æk4ñÕÛ=£®$I°Æ0žLÈó k-išÖÀ„~H×k1Ê&Ä&AœfÕ÷+ €,M ‡ôz=®ßÈÐZQÚöA‹C9ÃØ¨sùJ)¬µ¼8=âÖ­[$IBÇdYF¿×#Œ"ž˜g¬^ã¯Þøïlì­¤ce”Rloo³¶¶ÆúÆI’¾ïsóæMšÍ&ýÁ 8àÃ÷î®*þu»]¾öÎ;cxøð!ív›N§Cܹs‡Ìæ|ë'¿Ï·ßú7®î®,ÿÜ~@†„a¸4oc½ËïþF÷¼¢PAÀÛo¿}$¯Ñhðçüɹe¿z3tÞŠ?úè£3—ýàÃÏ«æs×wn.£Sÿô]h/SïÐSxhÆ—çsÊ8Ú¾Gpeë ý¼h%]Ú<Ï ¤iŠR4ü͆yôˆüácN±õÁ7Ð['Ê>-Ê#Ës’$!I<­q"ø¾_Ÿ?L&œslmmÑétÎܧUïØVñÛÇ“ ›››õ¹ ä9½}‚×ÑÞ½FúâêÂpƒ[››´£¨æ‰<À÷}‚ ˜s“O¤™2ZD¨½3ÁZ˰×#}ð3ÖÂ?ËÐq —@š–fUz‚³O½ÙlÖfø¹îÑUVùîYžÉQÉí ÞdŒ8Ëi‡§=9ç¦G]µ®,«w¢jf¯0Û®ÙëeT0øpv´ë@ k!NÁXTœ .áTtÙŽrvžý¥e#b¶ÄÅÎŽ©kåÆ@2A2šŒ‹ÿ¤ãtUÇó"Bžçõ«½³ÒŠ&°Ð(7ߘêTë`0„fÕë!¹™‡ý´8IÏP¬BŠ8Ž1ÆÎµsÙ⢔*Ú£Ô€©‚›1÷Ï•¯ÒçÏA²ò‰Z¨ý'à쑺«R4ëÉoª«xêÖZ´Öå‘Ù¼.‘bD¦Ëà\tÓh0`í¼Í‰sä&Çu×àñêù38|~êx]‹ö] }(ü‘ÊG8:‡¬{¥eй"LFž>}ÆîµkXkëÙƒ×h’ííaž~†úÕ¯ K²Î*kÝœ®ÝÝ#º´Ö¬­u  ‡Ãr„ÌË9¦&PýžPÉZÃx4B€ápÀd<¡Ùl`­­‘÷‚ok†H“bEp†UMÀZÃd<>Y—ç¡´"MÓ)ßÕý:Î8‹ T/B_¼xA¿×+MÀ«T‹J Ä#´ö ¹ò‹1ÏóNÔÔ 5ž·œ´¤?³2Vi”RšVÔ&ò”~¿O†ø¾1 Æ’$aÿÙvÿ1AÔÂÞ¹ƒûÎw¸zçîÊÓÀqºœËŠ7QZÓ;8à÷?ÃXƒö4ï¾sŸÝSWYšpÆU ÙlpýÆuâ$æãÿ˜;wïâyQ¡µæÍ{{¤»;˜þñþ·ëë¬:ü+šÕõÉÇsçî]Œ1ø~ÒE_½wƒƒîí½Î[o½9ßV2i'O£µµ5îß¿_¯½aιœb ýï~—Û¯Ÿ=RãD]ヒö<’$9r 7yï½ûÜþÊWŽ‘°ÄƒœIŸÛReW«Ékµ;´îv.í Ò"á™QÔ&ŠÚÇê:³ œm鸤}´Ì–z‚Ó­Ì œ‘õŸÿþgnÄoóg.»ŒVÑuDß’'Ú÷Pa€8;€šù¬ªäs¦ éZÒŸn´A;è ”WJ:²4Ãdyé^ø\*sIE!r‘ú-Ê©æEå&IL»t˜|D謭ñ??ÿ9}ò“itxÞõŸFŠWá"ÅaO.Óûâ¦ûuç\yy¢»ø­Î Šû¨ò‚ƒÖuh¬ÖмÜÝW>*W…Ào44ý©Äõ=ƒúÞAY^ʾ†‚/‚î®uxÿýß!·kc-ÎÎÞ(/FØéEŠ:¤^ªû® ¯/Cáë°û*\Þa]±aª@qN¦÷ªpy­ÑŠ2d¾Çâ¥Í‡mŸúB™Åz•½ X¬Wøè7\‘ÖQ‡ƒfAâÉGJ',c¬ÍçÅ–83ÀÚ¨¼•迤Ì‘¨=±])PZÇWýw1G“1ÀÉ1@i¢»(ŠE‡›Ë—Ùk²ßhcÅru©Æî~“ŽÐí\»<Çö^¯àRöZ­Cϸ¶4OÙs1Æd“³‚±’>}+’2ÆJ"ÙÓLÊ‹dÒ y @KÄÉòSQŽ'Nòäc±V‰Ä’’H€Ò*“ ÕŠG«ÝayižËµ2•JZV®-`ŒÅ+ºtü€¯Þ¸L©X T*¢¸Z+0=^üç ÖÚDËr—ß+ôë¢fˆ%U€3„6jT!5$™ ÓD7¿þAb u­¸‚Bq„µfõÖ:Z+\”"*•*ó uŒ‰ZÌ$=œ– K¡%é“iÇòhù~GÓFçGÑó<>ûìßA(ܤph NldâjdH[É€~}ù}Ox ¹\~~à:+§úÊA~x£…«_zƒn­q?.DKUµZe¡>O†Ç»xßd9©Ø±ú'2%_wíu(M $OªS(p®Á.Dz_­”¹võ*ÃÐ8hÐl5YYYXßFh­S¹k'xÔ9âÅ‹g8¤‹Ãø[áõÏÌ­ÐíYB;ÝŒsÇ*•ó†g Íf“ÇáŸ;_•)—J¬]ñøúòܤÆ;qŒ%‰Ssb¾ÏŸ?çöíÛ¬Þ¼‰u+|ãî ·VØ>èLj¬g‚ñ$` $ êúv›>‹>¨ž¥àL·Ç=È/X‡„øæMÇx¦‹éû€°µµE¥RI™ä(øo£M«Ýå²;Ý ˜ˆ|îïï³¶¶–zŽ×ª†íÝ6Ûû>~0C X7·ëûXk º]|ßÇÃyag¯E·ЙrŒ¥ZkzA'OžD/3D0¡á[÷ïqtt€ã88å2®vØm´©•˯LÌΞ ÆµÇѼóÍw€ˆJkÚ‡mJžG­Vcss“b±ˆ5†Öa›;õ ‹K.woÔÎtoŠñŒ`ì>...öYü¥¥%6Þ}w Î÷&4À³Æ˜6@úü—¾À$™y_à4Wxæ}ä ÐÈ23í 0Úœy_à´§?ó¾Àiv||•>äü~?¹BŒ1ˆÝ¾ÀQ`†Öèã<‘ëo,PZôz<ùøc:¾€£5½^¼÷ÞH_À[š_@DÐJ³~w¥ÖZ´ÖìíîP«VÙÜܤP(`­¥Õ:äN½ú6ùùÀ‡AqL&¼¼¼Ügñ———ll Ôùn.=ŽˆŸ§ä{s#êTSøvbì]Ê,M_)MH©Ìd«À`!±ÖãwZÁÁq®žBOR" }ÑMCéèÉy­V‹W¯^á8ÿzecgÈcu±Èúõé5„q†^¾|Éúú:k««9g¨Îöÿ¦c`” ÈHÈ¿,êw†ºˆoN¬waø¢;ÁÓ†ÿìÙ³¡KNøÚã<d µ ä¢C‡aŸÄav‘3ô÷Ý6M?¤4¯¦Z†A¼D†æG\ :CAúadH›xåŸÇX*à8½ ÇÖÓ§Q´¦ã`­5«kkt†9C‡TËeŠ‹Ç§ }¡ä:ŽJµÆÜÂ<ŸþljÂZ{aˆWô¸¹ºF¥9C®ëbBC³uÈת,-9ܹ^:ºì“~\ºTçÞ½{'4'Üp€úce¦ öªä!Öä r׌c¾R§êÕPÊI%-A7 zôz=úCZ‘EkP€‰?†¼nýÇÛ9~¾àuÛõýU±€à"Bmnާ[[üåoŸfÑáqx»•$Ö?‹O"ÂEÀæ#ÀsçÄf¯×¬µqœQÄìèžl®¢ó¨ø€ƒÖih¬ÖŠ^hF–¯”Jxn¯P èèJ'=gž;H"Ëã¶WJ%ÁAÏÏÕØØø6=bŒƒ5ùóñÁ“¤HCê%9_`ãðú8> »OÂå-ÆfŸÖ&§ç’py­ÑŠ8d^Eïs¡õ ˜¯VC‹VP.•Q@µT¢èº¸ŽCǶq£U|¨Â‰Ò1­X,`ÂÕj5pëׯÿæ×ïØm4 ‘œ ¯ rj‘I™<…£·þòE<Ó£;ríUZ©r¥r¤ËÕGj¯¢~õð÷£mçkÖ_ü䇯;œ/„‰¼²-¸Ó½Ù…©üpW.Ÿß ”©c@¹Rã“??>·þ¦Š^©Ì'|Ì£ž[ŸSÀ¢WâÓ¿þ‰G>LB&² ¼Í˜ ¸(üF‰(ólYIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/viewmag+.png000077500000000000000000001462331217176075400243230ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½x×yßû™sff»ØÅKü @€(ˆ)JeZ2eY´dE¦Ùe'ÍMûXiâ&·i¯]§í“ºíMÚ´÷ɽ½©“çö6inzíöé}jGŽLG¦¥Ú‰LYþAYM‰&E¸ÀbÅîÎÌýãÌìÎvñƒ¿$Gû>ÏyæÌ™3ûcfÞïû}ßóÎ9šëºÔ¥.uywŠx»@]êR—·OêP—º¼‹E»Àß9xh è‘R& )û¥a Km›&D”BhÍÇZÇ»hcÛ6ÅBÛuG\»xa¹PñËóG¼ÿ§.MÓÞÖï¿7^«ÇÖ/ $ô›–u Úа­!í1 ã@<#ј 1ÞH¬1F´ÁŠX˜–‰¡H]"=pÇv(Ø ËEòùer¹ÙÅ%²Ù2™ ™Ì™…² Y–s¹¹|~Ķí×£À‰çN¿—¡.!©ÀßP9xh iúX¬ñáX,v ÷·µ¶ÐÒ’"•j!Õ¼‰ds’d¢‰¦¦1„¸v¯*Ÿ/Éd˜Ë,N_%={•™™Y¦gf˜¾<Íôô4WÓi—–När¹ÀKÀá: ¼½R€¿ArðÐ@¿Röاš75÷wní¤³³“ŽŽvÚÛÛiom#­ûóÛÁÅÅqÀ ºÔ4ØXÌÌÌ299Åää$'&gââWffXÈfOضýuœØØ?®ËõJ~Æå࡞X,öt2™øT{{{Ïí½½tww³m[]][1M³êy…|ž\.G.—#¿¼Ìr>O~¹@¡PÀ¶ ÊÇ·\ÇœÒyšMC iHti ›:ÃÀŒDˆ˜–eaE-¤”U¿;žgllŒÑÑ1F.\`xx„‰K—Èd2#¶mþ¨C¸5R€ŸQxòžÞÔÜü©ööÖ}}}ômï¥wûv:;ÚWô- d3²Ù, ÙE–³ä–r,æ–Èç–É-çXÎç).( ØÅÛÆ±m\× MHM¢{`SÇŒD0-,‹hCÑh#±X±xœx,¶‚9ضÃððy††‡<7Äйs\¿ÄR6{Â?¢î&ÜT©ÀÏ<4ÐÓ”HsGßíÉ;w²cG==Ý+úΧÓÌÍÏ«ÀÜ\†…l†…l–l6ËÒÂ"‹¹ErKŠ,/çÈû À€bÑÆv\\§®âÐ4)¥*†AÄ00L3baY¢D£ 4Ä¢4ÆbÄb1âñ8ñ8M‰‰¦&¢±Jw¤P(pöì gÞ:Ë›§ßâÜÐWffÒ¶m‰:+¸)R€Ÿùù>ÕÓ”HüΖŽö§÷쾋]wÝÉî;wZåNŽÃìÕ«¤ÓiÒé´€¹ óós*2ŸÉÍ.ÍfY\\biq‘¹ùt~llüêÔôå…ËSS ùB!, þ³@Þ«ØÅš½z<‹5¶··ÇÛÛÚ»»»RÉdÒŒFcÄbÄã1bñ8Mñ8ñD‚D"I2™ ¹iÉd’x"QñÁSSÓüôôiN<ÅéÓg¸ti‚åBñKÀyþÈá£7ðò¾«¥ï`ùù>Õ“L&§««óéþ»ïaÏ=w±k玊>™ùyf®\aöêU®ÎÎ’žUžO3—ž#37ÏüB†Ù+3ù‘Ñ WOŸ>5™·íI`XÆÝó¶Õ T*°®U©k6'‰-;úúRwîÜÕ‘jI™MMMeH6“lNÒ¼iÍ›7“J¥°¬2°-.æ8yòo¼ñ:¯¿~’‹ãã,çóGT^¿Ôà( ô$“ÉßÙÖ½õé{÷ÞËÞþ~úú¶—ŽÛ¶ÍÌ´Z»23ÃÌÌ W¯Ì2{uÖ‚S púÌ›—Oœ|cðÞ 7P÷-}°©°’øF騀`Þ¶Å4ÌŽ÷ïßß³g÷îŽä¦$Éæf657³ySŠTKŠT*Eª¥…æææÒٶÉ'8~üÇO¼ÁøøE Šü«ºkpíR€w<4ŒÅbŸíêêúÌÞ½ýÉ}÷ÝË΀ÅÏçò\žºÌôôÓ—§¹2=Í•™ifff˜™™evv†ãÇFJ¡}E_F){Á+y*Á`½, ,þS¤£€Àôêþ6ÁmpÛþû¸í½ïÝw[ssŠTËfZR›iii¡¥µ…–¶6Z[[K_T(ؼvü8¯þø5N?ÁäåË8®û¯€?¬ 7.ux‡ÈÀ“¿p µ­å‹ýwßÝsÿý÷sß}ý¥cù\ŽÉÉI.O^fêò$—§®0=}Y1€éÞ:wvöØ+¯ ç(+}¥ð9ÊŠï„ʲ×7ïõ÷Û  ¾„ âmJÑý-TZ~éõxÇý¾A ðÁ`ûÇŸøØÝ;wîÜÜÒÖBKk+­­­´¶µÑÖÚN{`„c>“åÕ½Ê_y…Ÿž<ÅÜü|ø•ç>¼¡ ÿ.—:¼ÍrðÐ@2™L~qçw ìß?ì@ —v¡ÀÄ¥KL^ºÄä¥I&/OryrŠ©©ËL_žâåï¿<4>9y¸B™Ê/yÅWn ü6 ÂÖÿz€ÿ$­¿…R|IYÙ¥×Þà*hÝ{wÿƒïð¶®®®H{{­í*™©££ƒ–#ç?8ƽÂðùa …âQŒ¬÷¼›¥o£ <ù [:Ú¿øÀ{ïO¾ÿýïcûöÞÒ±ÉÉI&ÆÇ¹41ÁäÄ$—&'T&ÝèXþ›/¼ðfÁ±Ïs(å΋”•¾€Rø,e¥÷ÁÀñúQìÀßú1€e*Á€Ð6BùML¥°Jé£T}+A)½¯ø’²²GY þñhgGǽ¸gÛ¶îHÇ–vÚ;:ØÒÑAGg'Éd²t½^}õ5^þþxíǯ1{5F ¿´¡ò.”:¼ rðÐ@²)Ñø…;w>ý‡â¡ßa¨Ú|:ÍÅñqÆ/^,ÀÄ¥KŒ^¸ÿÆóÏ¿i;Î)”Â.¡†ì–PŠ›G)¼¾Âûmþ9¾‚‡K­8U¶AÑB[“²ÂG½z0 €˜w,F9€hÚ}7Á?ÖÐÕѹ÷ãOô÷Üv[dË–N::·Ð¹u+[»ºJÙŽSSÓ¼ôò÷yùåï1<|/«ðWê±ÚR€[,‡~þÉþööö/¾wß{úø;vôàØ6ÇÆS06ÎÄøEÆ'.ñÏ~õõ‚mŸB)ð"0O™Æg e¥_ôö}Å·CåF*¿/á!À`] @ ÄQ ¤ü±À±`[œ²ûPb =]Ý{Ÿzê÷öÞÞéì줫«‹­]´¶—Ý‚ïÿàß9ú?9~‚Å¥¥àÉúau©À-”'áéÛzz¾ððÃ%yä‰D€ôlš±± Œ^dÌññ1^{íµÉ“§O¸Š²ö (¥Ï¡èÿŠîÏ£”~Ê `XñƒàVÙzE¸˜Ý˜ñ„Û»c±XÝ ¨Â0[\`fú‹Ù9Ξþ‰ædçÀ¯~]G)·_|¥7¼ý&Ê  HPvü²é±G9pàÀí]]tuuѵU½ÿ`z9CÃ#¼ø£¼üò÷˜ž¾Ê%øÃÞ³¿éR€[$ŸøÄ/}a×]»>ûØ£òÐCûKíc£cŒ^altŒ FãÌ™Ó }ôè«Ày”bgPŠžÒ”)ý,Jù}_ÞWú ò‡?Ò1S»Ýýžàoúóî¦ÍQ/ß? Õ^úsBUï6ø¯ 8þÖ…“ÇOðÝo?£;ú…ôÉ àƒAØD%3hDAÏ’”ôÎÝöëŸþôã»wíNtuwѽmÛº{Hµ¤˜Ïdø«o¿È‹/åüÈŽë~éù#‡e•Ûô®“:ÜdQþ~âkûöÝwàç{Œ={vËå¸02ÂÈÈ£#¸pa„ÑÑ1ž{î/ßLg2?A)úÊg_@±€%¯ÝgÊŠ€”?êôí{ÂýåOÿ3÷žûî¡´ðcý¤€ÐòÝ(¬Æ |€ñ?÷" æ½ß”>|œ‚ ®ã„£ÁuàØw_ä¿üñ¿ÖÒ£/…sšQŠ^ zm>4z¿­ú¶oðéO}ê}Ûº{èîé¦ç¶Ûèê.¿ñâ‹/ñ­o›ŸžzÛ¶O¬Ç”Ôà&ÊÁCÉ––Ôw|ßþþÇþ=Ý]¤gg9?ÂÈÈyFFF9Ó§N-|ûè‹ßG%ð¤Q¾¼oñç½r~"ÏjʯÔèrþÖoüKçŸþ4è§Øt[>ïÜàç(+z˜YBßUíû—P u•¸ðìqŠ%@€cÃüwÿLûþsÿ·ßhöŠAy¤Àƒ2@ÙÀ–ßü¿?°gÏîDOO/=½=ÜÖÓ‹i©á«¯¾Æ ÿãÛ¼öÚq–óù¨àà»>.P€›$ ô···íÀô|äÃÓâÑÒɉI†Ï32|ž‘‘aF†G8úÝ££ƒÃÃ/£”eE鯠¨ÿ¬×ž£¶â‡(Üþð/ÿ¶ûëŸû¼;°—Fànà~”â7³RÙƒJþü°’‡ÛªÕ«m}»zø8‹N l» ÿæ·E;óƒ/i(EOQ  oßehö¶>Ä<üð‡>öÄ»{n»Ûz{éíí-½htêô¾ùü ûá1—rixWƒ@n‚<4Ðß±¥ý;=öhòÐG>Rš…glt”¡sç>ž‘áa†‡‡ùÿ¾üå'Ps‘2Å÷-è"•é»aÅ-)~Kïûó¿ÿ_ÝÛúºøX?¨TòjŠ_ µ¯fýÃÊ jûá¸DÉ•yö8Ë®]f¶­€àäñ×øßÿùßdÏè( h¡<\˜D)¿Žb¾Û z<»û·>÷¹GwîÜéݾÞÞ^R-- óo¼ÀËß™lvé]u¸ÁrðÐ@gç–ï<þØcÉCO|„¨•R“] 1<4ÌÙ3gò_ÿ摳”ýç+(ŸÄJůfýmÀÞ÷øo:Ÿÿßþƒ;°—àÓ(Å·X¿â¯Æ*n„õ¯6*vÿâ5§‚"]ø'¿vP›z!´£X€lõ¶ $,Êï#t|î3ŸýxÓöí·ÓÛ·öv•J<22ÊsG¾ÉK/½L6›}Wƒ@n ø–ÿÃÿ\ò‰'~Ë2q‡¡ÁA†Î 1tnsCC¼ú£Wg¿ÿʱ¿Bùû~€o¥ø~àÏW~»Â?øÄo9ÿøwÿOw`/û€ßúY©àµ˜C­z5Ë>¶Që Öž,Ó‡S°]pŠ*>`»`{õýO~I>þåFT°ÒO0òã&j4!îµë@ì×õWù½ï{_ëöíÛéë룣³€ÑÑ1¾þÜŽ~ç%—Þ½L 7Hèokmý·?üXò£{‚¨eá8ƒgÏrnpsƒC òòË/Ož8uòÔ+º À4ÊòORÎÔ[Uù÷=ö›Îçÿ?¸{¹øMà^V*{­íjôÿfYÿ` Å+Jñ¹#§°/0èú±okÛ Øð+Ò$Êú§( ÛQ ÷ÚK ðáÇÿ¹O<ùäží}}ôõõÑÙ¥‚±##£þús¼ôÝ—ÉåÞ1:Ü9xh ™JmúÉc=ÖóñÇÊÊÿÖ ƒçÎ288ÈsÏ}ãÜØÄø·P¥üÞ~ð%0õ/v¼ãþâ}î˜;°—€ÿx+-ýµ(~-ë_Mù¯Åú×j›®þõEÇ ºžÕ÷À ýzQÕÏ ñ¯þÞí1 “ò›†­(ðÝÿãñÇûèSjO__}w”Aà­Á!þ:?üÁXÎßu P€ë”ƒ‡’ñxãw}ô‘þ|¬í|ë-Ξ=ËàÙ³ ¾5È×Ï }f­<îÖ8ž&_™fÙuA ¼è¿æYÉ!”¢k^šf£²h^±5øâ_»¶]`â×>¬eQlÀŸê¬SiC1÷|ûÛ‡5Ÿxê©»¥”èRÒÚÞΞ=»ÉfÉd³¼yúL¿ãºßA¹UuyËÛøÄöö÷<öøct{I>£ÞPßйA†íŸ˜øÊêM¢þXøýü ·ÿàË£öç~±«ø¨qüÒ1ª+x­R Ö Õ€aµsª•0vûèc°g·J`Øê;74ÄsG¾qvlbü/QÊ?ŠÊíO£hŽJ(A¼ãþÂ_¼æÚŸûÅ®_¾‹Ë_MÁkQîZ Q Âí.Õ`­ì?¼u2KFJ:H¤T@ ýâ·é}#°/Õ¾4@7ÀÐËmºWþó·Üˆs¨àê"åQ–IT¼¡ä¿ù _{ökϾ~þÜ0燇Éf2<öè£|ð‘‡iÞ´ à郇ž¾†G£.·HÞ68xh ¿µ¥å >ø0=¨^ìIÏÎ2|þ<ÃCçæÕW_ýK”µ÷çèËPVü°òçÂÇ~õ Åùñc‰ïå?ÿ•ÿ^-ÈVM¡×Kÿ×cÙ«)õF¬ç*ðæ[6 Rá)¬Px!ªXÿÒ—¬~€ ’ f`H0|V?}Þ½DÆQŒ`ÆÛ€â³_?üü+¯ühÒ¿w©T3+¸>0}þôywF>X@aýª2ð‡ÿþKgßz+722ÂøØ;wîàÀ‡èÞÖÐ|ñ•ºÜd¹åðè‡>²µ³ó³?ôPižþ±Ñ1.ŒŽ2:2ÂèðÏ<ûìa”Õ?Šö>¨øªˆŽÂWœw~õñè§€¿¢’ò¯G¹k¹ë‡iý—€7Fà²?}&”ò `ø#š×d>;ze»\þ¤Æ)Ç–½k¼ðOû·¿422Â…‘QÒ³³<ô‡xÿþýÄã \Ã#S—›(·î½ïæMÍÉ/=¸ÿzèA@ùý£F¼WzÏó•gžù!pfmå/¿£øÕ;OÝǧ€ÿ•IJë^-›n#ô¿š’×RøõÃðÆ,ú/ò‡§ù ‚A jPÐgúÊc¥s«ÄŒÀöOޏ“¨à«Ï–PÁIäåâïýÞïáÂè(v¡€‚‡>ð ýý÷¨åÐU< î ¼ƒä–@ó¦MÿvÏž=]>¸)¶msat” ££Œ]¸À+?úñØ|6ó×(Úï+u««uoá«ßyËWþ/²1E_ËʯÖw=´#ÖrNŒC18Õ¿ @ 4@ U2M¯Îtß}ÐWº+F  PÚ PðîO•‚]Šcãã?þúן;qñÂÆÒë§K4i¨}]÷úå6Ã?æµ:Z´ýÁË(`^D ús,…ßþçÿìYÿÞ:¶”‚xop‰¶/Ô]w†Ü¸ÿ‡þi_ßöÝï}à½ÄbQÆÇƹè1€£Gþx ¥ü~`)˜ï@ÔIt>èþÝßþ*ÿú _Oíc/ðッ¨E÷W‹È×RÒ ²j«¶O¨¾–øýì4\ÑTlO×¼\{Q£ø}jí Ð5.ºÐT]jèR  ©Ú5 ]èª]uL“èºPýµ@»ðŽi*ÛW—Bm5ý¿ø=qèé?¹ä]#6å™Àuþ‹¿xöØøø8ãããìÜÑÇ{ïßç'õŸÝÀ5«ËM’›š¦míììü§ï¹ï>ööߨl¿‰ñ‹Œ3r~dùÔ™3Ï£‚~Yª¾Å×^ìØõ¨ý±¿õì<ÅSûèAEû“ԦߵÚjA8\o5«¾–…ƒ„_ÎÌÀ´—®_bûZ PN篨ûǃû2¼/º†¡ij_J„.Õ¾ÐRC©ŽiÞ1©«~Bzýuï\]õñK‰xâ“¿Nç®§&¼ÿ6ƒbm³þu|öë‡_•'@ïEª¯­q<¸_qÜw šæo…¢üš†&‚î€(» Òw¼¢¯²ýÿÇW XwLy×tšò‚*ý—ÿâ=<1~‰‰‹hooeß{­xÿÎ5=Xu¹arS ÙÜrWOïmŸÙ»w/;¼1ÿK—¸tq‚‰ñ Nœx}ÌÁyI½Zk1ûìí÷>dïÿà·ý’1‘ÀŸ¢&è„êJ_duK¿ZÔ~=Ö>¬ØµÜƒj«™UCgÒ/Z•‚ǸžˆïU;&ª×RHU4 )„jÓý})5u\ ¯îµ ¡úhÞùRªó¤¿¯«úÿù[Yˆúk*ÎPrg1·8ôò÷_>3qi²”pß}{Ù³gRJPï ôl䙪˕›š¦»îÜý»}·ßÎÞ{U*xn1Ç¥É &&'˜˜¸Ä‹/=‚ ü…^ã5‹˜ÝÅξÝÅ»ú´zôI'ÚSûøMà罯¨eñÔ~=côë V¨Í‚mÓ*Á§ªEA€ õ't¼k Àª2Va~ðPøÖ_ ½ ¢ &‰ŸýýïN£€×_i骽ÿðþèùɉKLNNL&ØÛßO›7Á(uð¶ÊMÃŒÞݹµóÉþ{îf»7ì799©Ê¥IŽ;vx…òTݞ厉Þ^ìê»ÇÞ³÷!÷‡?â¶´&´OÞÏ=Àï¾âZ†êªí‡•·Z{­Âm~}r†DÀWûÿÔh¯¨Öæ·×¬ „Д//BÊ××4åÛ Í‹ è^»,÷Ò‹·^Ñ%bÇ]÷±ÿÐ篨¯*ÅüÕ’gÿü™g^šœœdvF±€þþ{صûN?Pgo£ÜÐ4Íè¿÷ÞØÓ³»ïÞ¨U|.OM–@àµÇÿ’òë¥í1·ÚÝ}ööýÎ=÷=ìôlïAð÷_Tà å¯fÍ×cÕƒ.€_‚ûµâÕ@"Ì 2óð+óyV(pµ Ÿ¿¿Ï ¶Õ/@(E9PX¡‹rðPÊ@ÐPó†^ѼáßùŸÿír²ëÁyˆ(OËîγ‡ŸýáØèXnêr™Ü}ÏR›Sþý¬³€·InèéØÒñäžÝ»K+÷NMM15y™©ÉË?þ“Ÿ§¨Pþx³£ØÒu»ÓÝ{§³ó®}î{îsý øO(Š üùÓc­ý¯éߨŸ¿ÀJPtàõ`t¿Z¡(TÛ!E·UYáYy)=ðØ&ËÇ„·_Rzôòè >ûÏ¿”&Úbc´¦Q `Þ»V‹G¾yä•ËSS¤Ój–°={öpÇ}uð6Ë MÓŒ;vîùµÎÎÎÄî=»]A_ IDAT° ¦/_fêò—/OqìÕWžAùûËßj'ÚºìÎmwؽwìqvÞý^ÇŠ–‡ Žœâ4ð/YßpßF,ÿz}ýZ€°Zû‰¬j¯jý )uj±¨ÕúÔ å×Êm¾¥÷Ù‚¯ôþñ’ à×ÃŒ-½<õËÿäŠ0¢¢³¨x€ 8_y晎ç¦/_ ½µ…»ví"Þó§7þ´Õåzåf0€¶mÛº?µóÎìÚu'ÓÓÓLOM3=}™3gÎü•ëï)´ˆÙbÇ7wØ]Ûm·ípúvîuÛÚ›5]–N)ßäÏQ£«ÀF-ÿjþ~5뿚ïl?—…Åjµ8k€!+w¸oMÐÊJ¬]½\—F =Ö iåXBÐðAãàÇ#ßÙ½s)–êö3¼ë±ô;ùÊô•+,f¸s÷.¶voó¯Ûg6ú Õåú冀¦i"‘LýR{{[ÛÎw`™jQÉ陦¯L3}e†¿>úâaÊ?«Õ‰7w8-­ÝNWwŸÛ}ûn·»÷´•¢LYŽòoP“}lÄÇ_¯õ®T©¯¶½’Uyò«Z~XiéÀP `¥’Pn­Êñ T~Øzmºýµ2Xø‰AB/ƒƒ”•, P@üÝðû³+¦E“½s¨ä.p¿ü•g^Ÿžžffæ ;ú¶sçÎ;0  YŸ>ìÖËf-½½·²»»›w¨¼ïùtš™éif®\adäüOPŠaƒUÑ”H¶ØÉÔ»µ³ÇíèêsznÛéFcBY©Dߺh^j>¼Éµ[úõFûÙ`@ÎýÖòùÃe- ¨ÅÂûáÏ ƒ¡ `ÐÐ|WÀ´ù[é1´ @ º¶ßãÜwÿãs©ÖÎ<"±„×¶ W;öúÌ•+¥PéÎ}´lÞì??ŸZ÷“V—"7ú·uwïëë룫KÍef†Ù™«\¹r…ŸþôÍï¡’|la5۱ƔO¶:ÉÍnûÖ^§sÛv7ÕÖ¢ië£V¾Õš$ëÀo¡‚‚ë}Ég½þ~µ1ýZÔŸÀÖ¯ŸYg5…¿Ö` ¡~k@ð3jýŽjñ€ GDÀêYƒ Ä4‰(؈_þ­Œ‰ÑÞÝ7V)ðåÿþ•ÍLÏ0ã½)Ø××G϶ÿú¨o­Ü0Ð4-ašÑT*Eßv•õçØ6Wgg™™¹ÂÔÔôÌÙ¡³¯´…™´›œxS‹ojsZÛ·9í[zÜŽ­½D „Ð÷l'© •‘&„—¦yÙiùÚ —H9Ò¼Q…¯æ@u&°ž±~_T©°òZJ00X„W‚ý‚Ç‚Û`&a8«°ZÆ †º®ˆr¦ ¿Õ×_x×½”Qèeú™‚š®êº¦¾3oÖî¹ï‘LKËÖ|¬¹ÕÏ `dtdòÜù¡Ë³³Ê hmma{ßmþ¢õW…o¡ÜH°mÇÎ;ïïîê¢÷ö^®ÎÎ2;;ËììU†‡Ïÿ°…Ùä46m²ãÍNc²ÅI¦¶¸m[ºÝ¶öNɘ¦IÄ'ïç“Û“ü?%Ú°6%ªª!NÌ3 ü;6®øë @¥…'t,(9[M\º.¿µR‹ˆ*}‚íµb„ö×ã ° mý{¢éªÿrñ‘OüÆ‚iÅØÖÝ—1c-~0þàoÌ^½J¡P`ûm·“J•rênÀ-”𦠠¿··÷ÞžÞm´·ª4Ït:MúêUÒ³³üäŸ~Oq;Ö˜°c›œX<å4Æ[œæT‡“jép[Ú»\?# ¾ÿ#»ùLÉ <ˆ\„S‹¾ÀQüj a-ëïïŸ] ù‰ V)Õ@ Ú à×Wûž +@00¨­Þ±¿-a;«!Î]ýe’©ŽBssëÂÊÎWŸ=ü†ÿlôÞÞSrþºpëäF1€V!Íɦ=Ý=€¢ÿétšt:ÍôÌôÅÙ¹ùéX,áÄ“N,±É7¥ÜĦv7ÕÚAªm‹–hŠ ¡!?y?ïC-Oð÷ëãCþË)>Zy<“ç%à+\¿Å¯6œ–jŒ`v2¢ ]_OYë¼j®A5— š;®¯æ  ymÞu&P÷]¯àµß“°ÛË#{âé¬4,ÑÑÙ“M$SKBZd—sož:=˜¾:@K*EOÏ6"Þ¨u7à–É€ÛvïÞsok{ÛÔ4ÐÌÏÍy0ÇÈèØ¢Ñ¸Ókrbñ¤‹7;±ÆÍnSS Í›[Ù¼¹?ÒL™úJû»ºÙ† dý…æQa 1èð5Ô @µ{k)þZ–¿ ¸¨56ײäë-«±‚µ\‚`›¨ÑÏß»Ôb„X€wý 02- ¤ûm^0ЊZôöíYliëÊ7oj[2#–kšŽÿäøÙùù4Ž£†¶uu“hŠû×õcëyèêrýrÝ išÜÞ±¥}GWg']][˜ŸŸgn~ž¹¹y††GOÄbq»1žpbI7Ú˜t£ñ”›Ø´ÙMnj#jš@<ÔOð(J±üÈ~ø]›IǤ…(?´õ«Y¿Oõ¨~­È~-Ë_Ë÷·_*¨ÿ*µ€`5¨ÖŽÔÿ8¨úq´Ê‘„ ð)Ð^Ýq¹eÄZÐM‹–¶-KñDs.bZîÑï~÷ìÜü<óóótuuÒ²¹Õ¿¦êS†Ý¹  ¸«1vvv"¥úȹ¹ ™¹ étz&“]¼‹%ÜX¬É6&ÝX¢…XSŠds‹–ÜÜ‚7ž,;,>ä}f˜Ê÷v›ü^):íÑSM(Ú*ð¢Ø Gá¿ÇXŸ5_oà/(Z ¾œS“˜^SÔ=¥š[PËØH{Ø(ó)§‘ÖÜ«UV;?üYá¶jùµÊZ, دĨ¼ëJPñý>¡ ¡ÿYZ ¯H×Aæ Ƚû]FD´ln_ŽÅ› ÓÒßzk,“YÀ¶mÚÛÛ‰ÅJ/Xå>ÔåÉõ2€f ÞÜœìjkk¡½µ €l6Kv!ËB6ÃÔôìY+w£±¸k5ÄÝhC¦'OÐØ˜Ä?îŽóAVOçõÛ~}OŒàù£hµ}áIøKàuÖ~`½£Áýñð÷ù¿£–ÿ~½ý׊ ˆP›¨rž`eÁ?§ÔÏ‹©”‚ÁóÁØR,&œ à5„#…"B·Ð¶tÞ–kiëÌ5%›ófÄâõ“§Æ²Ù…Ò¤¡­í­$“%׿¾¢ð-ë€6 Ë²¢›7·`Yj'»°  “G‹ÑhÌF›ˆ5&°¢ ¢±¤‹7i–e ß×>@e°. A…ý¥Û|ÿ3l ƒÃ[Óð<ðSª+x-q)OÑåKp>§òÛ«SèHõ¯¥¬t‚mk}~Ø­ º%6P¾oÊ]!ëï» (P, {zwåã‰fwSs*oš XѨvibâââ‚z˜ZZØœÚTºà XåÕåÈõ@'°Ù²,6·”2¹X\Zbqi‘ÌÂÒx4¥!§¡¡«¡ +Ú¤@ žÔ¤¡œ®Vš€{XiíkKÂ?º]ÒMˆþS¥Ì¨)Äßdí!½ð~-À¸DHiª}ïµ”õIøøz\jç¬ $ä„úk¾¯ïÓÿ ï/Êçk²è dßÎ=ËR𢥵s)9 “±±±‹‹KK€ZV¼eóæ` °În²\3hššZÛ;»c±(©f¹\Ž¥ÅE—È,dÏY 1ײbD¢D¬˜fX1Íjˆi–-1ïïå^VWüjÃw–„ßì­ë¡Ï³ðÔ[zµ‚kþeo›ñ¬MZ~#ÊZŸ»žï­õæájçÖt|âï»]Þñà0lÅçÞ.t]• M´Ä¦Ív"Ù\ŒÅEÝ´´ËSSÓK‹‹¥‹¼)µ Ã0üÝ{Öq_êr¢_ǹQ ÞÕµmG<'¹Iùn¹Å¹\Ž\n‘|±0Ûű¬¦Ã4cše5 Ó45ÂÜÎúߨ n#>ƒ?[‚œ r]½ HÃ÷’ê¼ÛÖùµÐÔü÷®Ÿ>­%õG×#e ŸÜö[í{m¯s5HxŸa{…Põr²@yºb4p(Ø`Û°µ{û²½œ.6%› 89&'/_Éår¥LŠæd3–e±œÏƒZA¨.7Q®çnˆ˜f4žˆ“lj —÷ ÇÂâò°e۬¬†¸±âš‰jV´A3 /’¬¢Éw³¶â׃öø•˜¤5©oZå üõX_ò9ïm¿IûW+«}ÏFÃzÜ€à±R_¸W~^¡8•ÇJç¡ÜÛFldwÏμm$™ÜTˆ˜––ÎÌgr¹¹|€D2|3°îÜd¹hH45u%š$ ò¹<˹<¹\þjÄŠbYQL+ª™‘̈¥fƒfZQE")¥ÿö°Òÿ¯•ÁW-zßš‚¿Ý ¬#R>¯Ö ôó‚R ‚Fð2aªû*µ¢ûÕúÖú+FÄʾ~»?©Èôû¡Fl‘j±l¡é"¹©%oD,Í2-mzff<ŸSДh*­‰Z=¨.7Q® 4M3€F`³Ð4â±ѨBíåå%òùe …ÂÕ†hËŠj+¦™VTfT“¦%"¦%jÊ]=lA)îj©»k½Áç-Íð‹QÅôp¡ýŒÆû.jz²Ò_ ÕƒûNAÍo·â³ov ÿök9'¸¯­÷\ª{-° ©úÜÀ>ZyÑQ×E·UR-íÅd²ÙnŒÇ‹‘ˆ©-çrùå¼z58Þ£!ÚPºèõ‘€›+׈1 %uI,ÖX:P(Y.äÉ —,«A‹DcšiZZÄŒjF¤Aè†%¤.…¯Z)ÚXý-¾`½Ö¸½¿Ýœ„§áë5ëðª’l\1]Þÿñ%¨ü~=mM¾åR+°‘8ÁFú—â°"à·û ¶×æ/K´.Ž£b¶ ©–-ÅLú¢cYQò´tzn¦PÈß‹ÅhŒÅ¨Ë­‘ë @J+€Ø…Bb¡€ã’‹XQÍ2--‰jFÄR݈)‘ê!I즶¿¿šâ×T~Ɇo¦Õjµ+Ę…EN˜°ˆ³Rù4[-tñ¶(ÿFd=A¾p_QÃÀàñV(¿/Á  ]ÑTÚÞÖ±847·83ñ¤ÓktœeQ´‹ù¢79HCC”+ü–ÀÑ ü¥ºl@®"­í;¥”Á  Å‚M±`ä,ÓÒtÓÒLÓÒtÃÒ„n i˜"ôDiÔ¶þë}E7\ 'á[sj• ¶¿S·?ªÑ?¡!‹è~Ç@P|k_ ª± ‹V^œ°Z?72r¤ü¾®«JrSÜ1ŒˆhˆÅíÂò‚6777SPÏ –eaY„¦á¸²º\‹\+”^ÜÖ¥Ä2Õ ŽíP´‹Øv“†i‰˜š1…®›š¦G4Ã0„o<ÙAíèÿµ_ 6Ã÷fÕÐÝš²ÃQ5Çà¶Ð¡9®1^r#åzÝ€º á“…ãï[~C:¨h`XG-•ÔЈ+ CkŠ7sÙMJ©mŠ"-H+êrÓäZ áW¤†2Œ¶cã:6¶í K©™S¦% ÃÒ ÃèºÐ4¶«)ózÁ€*Ÿ`h†×Òjâªü1‹p5ª&°ìAY|· ¸ø™²þkÉj®BðzÔ âöƒÕ`.ÏqædÊž'ìÙSÓu]s²²å™ ž tSeÃà½hX–Õ  ‰ô2·\×ű]ÇE“R3͈fa˜! C" G—†‹PÏžg%šY=k+þZÙ|÷&¡i^¥¯)9ÈK2 5ãü € ‰a¯âTv­ÞÏ×Q.˜–¥5&“ŽiFÄìììå Ý—Þä¨ÞD¹`áÑá––¶n50ìC¼ƒ‹ƒë:†™X–0"¦Ð SèÒEM /q$ȧ7Q^‰w½Ôß—jûáºoÐz`-›våÐ_Uñ^I¼d”‡Çêr%žHºº”2bššc;ÂuÊšÉdÉf‰Å¢˜‘f$‚.…¥¢¼BJ ×Ö5WAh*¾ãPa9ÖJ쩵|¨Tôð9µú—^ž³Õ;+ò¢è×â»‡Ï î¯Å‚¾~EÝ)+z醸•ˆ¾‹~ú¯OýýùÇ …. C ˲Zü2™…0HS—›&€ýø˜†²Žþý€›ÉÌissóÄbQ"¦‰eZ Cjº!…«éÒEÕ:š¸¶Ï9)½|ÓøšjÏçj¾ðñà[°a®aWY+(÷ æµy§±_ª]¸øÿáþ>}¯ & ³ë…[$4tÏúKÐ¥b†!¥iF¤išÂ_|~~ž¥lœ¨ñSërdCðíþÊW˜%Ô-Ÿµh:¦££Ý{ŸÛBƒ„Ô$®´A—¸Ûó=]ÈÙ¢Šl¯Eù«I5K¦úÁ¶ðqß O¿WSô[«Yÿë¥ÿaÿ¿&Kðºâ*Ü¥J_€éI©ÞÏÖ=@/˜†!EĈ4™Þœé¹4‹¹zJÆ­’ ÀKG¿í+UÑÛæ];›ÍèWÓŠ©YV+já⤤®K©+åG€šnà89ïaqàüWš»®9Êëö£Ê± Ò·ëÌý¿Ù °å¯6vïV點 ]êòý+0À»R~½´ïªÌB)¿” ëªHÛ4 CX–YšR*}5M~¹<›ÛóG]ÇO®Ë5ʆ`dbÜW"å ÉÌ]LÆ=³3jö-Ó2‰64`™¦©KMJ)\¡ Wh[ éGJו4Ëtmè7¯¥ðá}ïÛ€J­š`ä‘“ŠTçÕ”üfÀÍLƒY°øÔß-Óú`Žf‰1øÇ‡!à8Êÿ7 ¥ø>º†cJ)…iY Ûq¸2;[J,£îÿßtY7hš¤ÔE¯0—™¿ÒRXÜ6=3SòÉ¢Q¢¤g¦;Û·6_Ô¤ã¢á‚!Ñ4­ü€LÍ®™tS-‚Ï*û~=<ÕÝjV¿¶úY2`¸• °Å¿ë¿ú_Õÿ ñ•úù@àûþzàúñ/è+¾axE¢ëBèRʦƨšpæÊ 3Ó3Á$ ºÿ“åZ†ýyû‹€;=uyb[W÷½Ó—§¤?Ћ‹ÅÈ.eSRgRÓ„‹é E ]¨•büņ©æWµï÷·á€ðq»šÒ•ßD±ÆuY°FŸµäZ”#²^úŽî;ž¢»>Í÷ØëûÿÅÀ4@7ÔÖÞl2` Ë–aÑoàËÓÓÌÌÎNn²\K"(öÔäø„ã¾Çžžæâå)vôö¨©ã1Òós))5]è $šk£é6Žià.{0â80™%Ý«€ ‚Ýyð£ü~ßõ(y…¥mýï°]O‡×“dPM‚ º0؈BWë»Që_-àG¸-Lÿƒç¨ƒ.AÿßÛ¨€ˆ¯ü¥eÿÐÁ5 )›cLMN‘NÏV= è&ËFÀ¿ý6e7à +3i®\šTÓ‹cò­R-íj®T4P3u?‹P}àä,ÙÎòTðÕ¢ún¨Nè¡ÊvUKÏJðÝ\=$»þ¯Gn¤¿^å¯%Õ¬50ûöu7p±¼ôó|FPÁuýL#å'ÎtÇ4#‘F’ˆÉÉÉŠ¤2êÓßtY7¸®ë¦š69³óiŸþ/£XÀ\6—_Èe3Í'&0 ƒxSÃ0cv1×`XÎ’ÔÁuÐ 'ÁÕ²åedœÌ}*XËǯEóÃJÜÂêÊ¿‚xÓÞUŒTc7+ðWK6¢ü×býýc%e÷)¿÷>ýZzß¿wuŸ5›žâ›˜ˆ”/\Ô0 aH# Í.rqbÂ_€ç®»7Y6Ä6µ´à@•lÎÌäôpsClÓ¥ñq-—Ïc™&ñxœD¢‰Ù+Sm]‰¶‹H]S`¸ryp‹° ÖÛž•§_MñÃ.@°-¬ða%Öƒ.†ÏX5@+øÛµ¬z-_¾–òWSú5ƒþÖ‚|íUêA°ˆ`šê-«ˆ^òÿYÌåcŽãlJ4«[>vqœKžñäh¿Y—(Òðl€üØäØùîžm÷Ž]œccéÛÞKS"ISS‚ËÓÓ½’IG€+†‹1qMr¹²µ™bnwkieVÙúõ U‡êÊÞ÷¿¯ô`PôV*x-€›ëUþ°ß¿Zÿµ¬)zïut‚u'`é½ö ¿ßUÓøûHêØ*í׊(å7#þ¿æÚ…Š{‹ÊŽ]czº"øR¿T—(rÔH`) ï•BfvfÄÅq.ÏLÉÑ £ômï%‘LH61>1¾Y GJÍ­ƒf8– é=D6œc~wkIÇVóíÃõåwTÎIÉ¢S©ü+¬¾o_¸!Àõ€€ßn ¬æË×RþjmaêîSËú#üþ <æ¾ à[ü¢Rüb€þRY3  ðD_^^ŽºQZ_bô™…Š0®r)êrƒäZ‚€6Jñ—ÛéBnqa)MŽŒ\(éH2™Ä2­†«3SÍ-[š®"ÐlpLÇŠ(z˜Ë«&Áž‡\£šp¤øqC4O±Ý*VÞ®ÒV«80ðö% ¿´Àê@àËXKñ×Cýì½BùWµþ|~ß껬ý÷Ö´À2U1Í2ýŠÅbc4¦Æ'&9?2B¡Pž­½žxkdCຮ£iš?P@Í£g…±‹ão˜·7>t~xDŸ ³³ƒdrÉæ$Ƕ¶wnÏ Ð"à<`™ Wiîð8s{:ió¿ÏY©gÕô.ì ÛÖ,n î-tã'*V€€ÿ¡¥kQãÇe=ʽšT£õÕ~Áöj.A-ê>¾Âú»•þ|Ð °ÝÀ6è÷{!XD#žìo*r IDAT©¸~±b±˜ÜœRË0Žœa|üRð'^åçÖåʆX«¦iÚÎ;¡ì,£@ ?<:vûâø8çΠ9Õ̦æf² ™6)m]—ŽnHôˆµ 5… í 92AÖVÑxÍV–X¸j«¹ªM¸•E m×Sd`+é ­œP;ãá>7¢Ôú\'Ô'ÜþÝN•~nhë€ÄA:.Òu‘n îTiwœ@)ê.Ò±‘nQõ˜êþZ&2j"£2ð;'æºnJx9Á熇¹:[±sÝÿ¿E²QàÞy×] @¥ü`ÙÎeÏæÛž½šÖÏ Ó~øAšS),˲f§/'[ÚãóHl+‚kY5a.«–Lgp'æYlM\ºÂ‡,™,èû»¢ÒÊ+,0ú<^ú°6 Ôo£RÍÚûR‹ò…-¿ª×¤þ”é{0’OЪ{´¾´Á@[ÿì¢jógˆo0!j)`Yô_ær¹ÆXCCÀøøCƒCÃÔÀ-“ gž9uÊ~|XF¹ —'ÆNvuõí”ÃÃ#ôööJ¥HmN1>6º¥}ëm‹ 5ËÄZÐ`©a@ÿ!¾ÈBj—š",”Ì/ÄJEÒ÷ / ®æQ|me|ꯕÝ^ÛÝ&‚€×]IA«)òFe5ů¦üÁ>á`_ðó*&ùøû%¥÷JÐ÷·½ ŸŠØŽêkHOùMhˆ(HCn)·©9Õ À[ƒƒŒŽV$üxþÈᑵ¯N]n„l¼8€K9˜ó¶ÅÁ7‡Ooíè¹oltœ3gߢ··‡x±·q\dÑUû¶4 d,p_£–šÌû?F>ŸßÔ”HgΜáÌ[ƒØvÅJ@_Úè3Y—k— €ëºîÖŽVoñÜRpócc£o8¶kžâÔéÓ´nÞLKk S““-†À0t KLjšèQ ½ÁB·LtÛF·ôó,gqma;ÛEضª»ŽR`»²HdÑSæ¢W÷Ѝ¦d6è¶÷`ÚÊ÷×]o‹WÇÛwªÔý>n o°8ë,áóª}n¸¯êç¯Öߥò¿•ê.ºã¨­ëo]t§X®ÛzÑQ[ÛVm®nû[Ý.ªºc£ã¨{m@5¨zƒ¬øoÑ………”?ûÏOOŸáâøxðñ:üü‘Ãõ9n¡\s=uêMŸIú.À*X:{úÇ`rzšS§Nyß"hikÃqÜøì•ɸ!Ñ ÝŠ Ç,õ°4FÑ¥P’c£ޱhÛh¶í)¿pm„ízm8x ]!ë/ƒ á”A@÷¢+e=@•J[ V+µÎ­¦øÕ*¼¿¦ò;ª¸å÷Ûl×»Eµu½â8j¿èomﻘ™m?=uFœŸ?Ç`qåkŸVzú=W¼çLP’ þ÷“‹RÍHX–•€Þþ4¿ÔŒ¡Á²Ê¿Ëο7HΛˆêÀ(ÀkúÝþÞžv©´@ú@s3®]¾×/¿³fa``öïË­]·®_XBì˜%€mÃc|tË'{áÎn€æ‰8ˆ°ÿ#¬ÀãCóe€Ï£¼h˜QðÄvÄ/ ÑOú @e7Q)Q´œŒ)T“jÙS½¿ò{«±€©F}y<(ÍÐæóçʘÍÉ=¿Jìß cýžñƒµ`š¤“b‘£ù°B<Ï«O§¹í¿ÿÅý8ÔÚZ9ûïŸNñ8.Ëk(49¨$ 0Á¿ænÙ¶rå;îéhïÄþ}/âÚeWCQ(ššf£¥ååÄÈÈH2›ÍZ€dÌ*v°¾ŒPàD/üL$‘àºDWxʵ•+½Tx”rzæ‹îÔ  ¡âGÌZ™üT‚jJYù)gsN—úG·+}r;x]Eù½¨°BùY…b{?¥ú^ÅàN¿tÈ$8¤ ·ó'©( :OváÅ}*óþŸ¸œù÷ÆÉ'°m¾m³ÐP‹ ÀïïíÞî8¥‚mYØà%ìÙ·kÈaöìÙ8ØÜœ 5I¡¦SPS)¨é$ÔT’ç0kîè†ï:œ–:‚~ʵë@ñ\¨NH_U׃âò¤URUé¸rW8À|ð|/â0óª8Т¯'sÐUsNg©vŽÉÞ[y¼ò½ÒÙçŠ8¾ÇB§ªï…±þÀ™çógìzN?ªë†±~¯Êñ¤Qþ7K'¡åŽ?ͱíZ÷ß³gŽ´]ý/%¹  ¢^ÃŒ™öÀP¿ >˯ÀxËÁ–-+ßñŽ{ºNvaïž±dñ"Ô×ÕáŠÙ³qfxX;Ùy25wþ\‹,­¥8ý—;žGù¨4>œêkÌA!Lxõ(à3AçÅèÏxÈ—À£`ðBn r 2À@b%˜ŒTÊù jµsVŽö•ûÊè¾Ø¨Fù£û¤Ã/:ò»‘b_Œø¾Hï Y<žçŸI5bI'ÔÄù”âšÎ'ýk>Ø‚}{öatl<8èyîÿ÷«§žì<ÇuY.’\ ýƒ}.!DÖŒHŠ…ô÷w?[0—ÝœL$r_:€EW-Ä]wÝd:9sæàøñãɹóçz|`5Iþƒ´ÀËHïëây™$ˆG…ÒSð(÷òù„ç P?ØÇí~|Úa6pE Ñv#ƒ°$¦¨®øÓƒéÊtìþI½ÿ¾¸^ Õ”¿²]W5åwEO™]¤SBé…ò×€š¦™L$(LìÞ½¯´·=Ï|üŸÜe¹¹(@!º®¹¶íŒƒW~šà,  ¿kçóOÞvÛm÷c׮ݸòÊùX¶l)fÏ™ƒÑ±1²g÷îÔê5kL,IR(Iðø’7P «d~¨¡s ,´ý%+ Œ‰}ÁÈ/_î'Dú Ågü°HfU05 Ê±éH5_åxU þ§õ£a?¯Òþ*…Âö¾Sn÷×$ÅèŸ·Ë þß÷‰D‚Às»^À¾}ûÊJ~GFF¾ùÒþÝø,o¨\H&  – (!dqªç™{zûnÊ5ͼºµ­î|~æÍ›‹d29sç¢õða¥·§Çhljr FÜdøCtÄÈdZ<äÐÝrÅLPUƒ"Ò÷<^MHÂÑŸQ¡è²ö7Èî/„)ʈÏÍ®ôžž3 Q™,"PíøÙd:£t{‚â#2úW*¿TvéèlÀgáH/÷yàE”ÝuÊA€1áðKÙ4WüLHO¼Y…RªÀÑ£Çñüó»ÐÛÛ,ÆÛ÷íyþ¯Ïá]–×H. Œ™H–iÁ8ÄÄw(û›wÿçí3ï\d[ÐwïÞ‹ysæàŽ;nC:Ƽ¹sÑÞÞ®565SdüÇçx€É,0‹@÷HS Òu/ê| ¶=|a“R¹gÿ"@á9(ã¡Ã2FnVDÓ„¥Tê@E„¡ªœmä¾l|ñB*>Î6ê‹‘žE¢ ¨Ö F~'\;â3Iƒ+|6ÅGþlšƒu…Û¶5]×Q0-<ûÜó8|èp™ã¯µõð3ÆŠS<šËò:ÉE È `«%ÄÀ-ðÞ—|êúï¸{ o€ìع³f5âúë—£±© …B{vïÑV¯YÍN)kÒü‡çEF(–ç?ÈBè£ÀŒ¬ óŠPNÁ( »{2ŽêR±)ãà$H¶ €"ÉÀ„T²„`LtžTeQ¥¯Yt;¢ø@$ÓE€Ó¼öÊGýɔ߉°ÏáuýY1òפÅÚÀÄyÔ}Ÿ¿v<»»ví†Y´‚Ã'OœøÑÐ@ï.à1]–‹( „øà,ÝWü8¬þÞîù±«®Éf³Wim£Û·?‹Y³ÑÐÃüùóaš&Nvž$sçÏÀm?‰_‹/å?LéPÎfDù €€÷@ {= 4âôPÎ&‘G_h|%HÍ?_§`0>ú‘UTÑ+_û!ƒ™Ôþ—Še2— …wCP¨¦üŽðøgÓåK5»€ cÀæƒxvÇNô÷…Ôß.•úZ71v¶¡/Ëë$³‘ '×21HfÊ¥ÀܽkÇO™ãz%ÛÆî½ûðÌÖíð<Цaþ‚èë; 3R"š¦âG—áë:1 )„\cyàÌH¹Ã0øË±Ú²ÁÝŒp‡—WA}¡(LzÈE"¬Šó=^ 'Ãgž.¬rÁÄ}ò½òó. ÏTßEvÑ\ü¨íîVÜGtqÂûuÝðùHÇŸãñççVS~u¢ògÓ(kÚX)]ÝÝØ¶u;Z´•Qÿ­[žús/æoî²\˜\T"Y@œ Œƒ€ìØõRKó/™ïºc£#xvû<³u NcÁ‚8r¨µì„Y…ÿèjÓå` þCÍ+pẨü°ƒýb‘ ß#cÞW·òXÄžÒe#ŠUæ`©ÜçMŽhúm¥Òû,TpÙž«ªâKe¯g2Œ8þ‚çç„Ê_Wyþ)ÎÌ&üÑ=P0Mlyf;öìÝWÖ翳óÕŸø“e\—å’‹mª-p–¨ƒ›:¸Éhö÷voèoºª¡¡qYשnlÙ²Ùl«W݈ú\%ÇÁî]»°fíÚà¤u€tH•%í“>"?–Jp£œÊ3 x‘è@ÐPPyJùU1á`Âwà ?A` 4‚HDÄA\K™ÃOšSˆ?aAÙ¢4€âËmiœÍé'Íé ˆVóyr¿‚…ôü{oä™­ Güº Þ*~»¢Å÷ÓOoÁŽgw Ÿ~ …ñö¶Ö—ÿ’1Ö]ýÓ—å’‹Â(Ë„‹àŠ?‘ò Öû¾së¦Í_J©ÚÖÖ6dRO#NaÙÒ%hjj‚çºh9x˯¿>8wVŠ&írŒæyÑ88ÝO'E„©vúÉCDD ¤À÷EåÇ$@@@:ù}òµô H@Ĺ%0LCÊ”=øor¥—ŽÁ©ìþ ÿ?b*LHŠ2ÌãÞþ(ÓªÛ™*Êïû>äôÞ[·îÀ3[¶¢··?8îyîøÎ[þ Àái>ŽËò:ÊkÁ¢ `!T|¹ŽA¸ØvnÝòÄíwÜýYPöï?@R©4R‰æÎƒ9sçÂs]lnÆõ+VâCuxz‘PdE,#y>ÙhIŒ|É *¡#H… Ü„ð•ˆ"ê†#‰E„ ¥’  Y¹=³p;ðèK6P¡ôðË•<Ú×?ØñWø¢ÒãÏ„Äl=)Â{Y¹®á´Ò‘_(ÿî=ûð«_=W;:ËŽoߺå[žbŒOüôey£å5! œ ú타Ž0öý…]ÏÿhíÍë~ݲmå¹]»`Ä ¼ï½w£±±ó,@G{ÚÚÚ f$ÀA€ÖpÅUW8…#(X¼œ˜ù|B Uãï F~/Üö…Â31IiÔt Txú£5 @3w‰PY¦->Â(@ÄÓ/™AŒF¦PüÀq(ýÂ$üîDÿ!¼š/›jR"ä'@5›?*Í[ðÔ/ÿ ‡Z”9ýÎ ô 8޵@×9>‘Ëò:É´€V^Á5a@0‘h\ù%hú366¼£ýDûì… Ý\(”íÛw@×T¼÷½w£¾¾ rèíéHÀƒJ†þ”*å4^çNAÇü" ¹|bJɤ٠¨By^FGh$#€ÌHꡬ€È“v¾Ì”æ€'ï®\ÄGËÅ/[•+¼XOPzyü,Š„ý"Ñ‚¨#S‚@L ³úd‚OF°€©¼ýpøp+~ñó§p ¹¹¬½÷¦MÑwº;ç{Þ_wuØÞõç²\b2-8å—•‚xô÷~Ïýö·¾%{È2Q\õx[ë3Él].—[:š£[¶nUTÜs÷]¨«ËbÁÂèììDûñãX¸hQði*@@á³Ñ¨_k*0:.&õù]Õ„?Qä(Œç á+PDý=‚£\Á"fÀ |•ÊQv 4äH/÷•)}…#0P|Aýe¤Âs#Ê/€›JAn“Äù#ÒÚÚ†ÿ|ò—Ø»¯Üãÿ®Û6ãÆoD>¿`Xñìö­Ûf5ÌÜxº¿ï2\bB¦£ÜD6Ü; Ÿ§à‘€ €Y±®¯Ðd׬^ÿ©lmv>(PW[‹Ûn{îzÏ»‘ÓHuìBa<¥Ë–•ß0jñˆÀh+p/ðiǤ}¯*Âg p0ˆ: •ˆ™@•r¿\&0™w)‰è:~|µ2 “{¢ ”+½ž¨ÓO‚D ø‘üW†*å¨ÏpgiFTõjô*~røpþóÉŸc÷î=eE>ë7lÀÂ… ‘H$LÆQÈç±uËìØ¾µ¹»«ë- R?Þ(9_½¦ C! 8£Ì"‚ŒXà@]³îÖߪ©©›GRW›Å¦Mp×w¢±±ÐÛÓƒB¡PÆ>ºæ¡ü ?ηóE¾m‹JQ"@+€€T~ñ´ € ‚ =ú÷§š?™?@2‡¨D•=úº2 X•D€ jóG–ä¨7xQO:):ù$¹ÝŸ™ÂÙ•æƒ-øÅ/ŸÂÞ=å~÷Ý÷!ÌŸ¿CCCð|ÿmoyøÌ#ŸÁÏžü)ºNv_ à#}\ùÓA ‹0u¸vÍÚ5¿•ÍÌœ R“ÉàëoÅwÜŽù"Exxh§{zpÍòå¾§ÞDD@¾Èçt¼* ÖD²©ìQV ¹ ”+%L%ÑVÄUA 2â`Pá”^þ@ñýrÊïûÜÖOÅE-<¬é—-½&vóš({öìÇ/Ÿú%¼Ô\Fû{ì X±b0004òù<¶oy;¶noîî~kÀ[.† àJž€J& ‹ã5«×®ÿtm&;$cÝÚ5¸ýöÛqÍ5<P(ÐÓÓƒELàiˆy›× HÅÏxOB0KaRO%¨„û¢ŠH6„T¿Ò ¨dÁ£•]Íë/×@Dé£<«ñÅZSD³Îxظ3‚Œ6=“eûöx꿞ơÃGÊ~ßüÆŸcùrn– Ld2Db"üàG?Î&ñ?I&“óS‰Äˆ7¾Ó˽é&y3À´œ€½½=ؽk7žÙ²ÏîØ‰–Ã-çü¥"7@– ‹vŸeÎ@ ÀÈž];þnõÚõŸ®ÍfæšÅ"}vçóÈ Èç7cÍšÕH&“X¸`!:Ú;ÐØ8‰d¬ÒÔé@¬0 ¼˜Åˆñ°`B€À¸Åó[äxd&àd, j÷K'¡èT\Ö`$²ª®]U€]~…—#Ê/ ~¢£>|ÎfÒÉp¦ž¤˜µ'-hÚ˜Þ¨oZž~z+¶lÙ‚öW:ÊB}Ÿýì#ò@®>½+ ¡P0ðTï ›o€}½½ÛæÍ›;¿®6›Âh>ì}ýýO¨ªöh]]ö-Ã.eyÝPÆðßžd’ ¤Ä:®Çé5k7<’ÍÖÌ@EÁ’Å‹°ù]ñ®M› ë¼½¿·–eCVFEú EÁ,`ÜŠ–`gž'ò ”rg`U€òmI÷{ŸTèülNâü‹*¼<^9½W´Û/Àï!¡se@Ê€ý“ÓtTöôôâé-[ñìögÑÓÛ[vìîǺukÑÔÔC/o 004Œ! aph~„ Ä «W­œð]­mG¡i’ÉD³¦hs¹ú7¼™À9ÀÐК›`×Î]Øþ̳عÿ9ØÅs¯ìA îøK" I„½Ò+W¬úh®©iUf56aýúuØ´qf75ÌBý}}˜¿`AÕï´ÁÍ‚‚É•>X[|]´xØÐñä5–'•E"€”ƒߨ¢\Ñ•οȟ 2û/°ýåëŠô_©ü”º $b\éb @ .X€Æ‘u:rð` ¶mÛŽÝ{ö”5ó¸òßtÓ*|—é‚À‚ùóqãʉ¾)'OÂ*–L%Gb𶱡!×<ÍË}ÃämSDhPÚü¤c0‰Ð' P.^öÀUW-ZK„5]“MaÕ«°aÃzܸrEpÞÞžPJÑÐØXõ{-…Hå—LÀ²¹i`‹¢Ðr0€dˆ$ìÿsÉ ²#´ß—û¥Âc¢Ý/‹¡ óFçë¸$„Â'õOhgëK±mÛ¶íÄögwàHk[™§Çyé[ßú«%†ayBghš†µkVõûGÆòèêêB:†aÄnlhxbš—þ†ÈÛ:::ñüó[ðÃÿûøÙ“?;¿/&AÛ(Dƒ „æ€@Ïdën¹yõ­$êK ˆ‚€í„ `;¼[±ç•¿¾¦38«þs‰(:€ å—èd …ð)¸t‡òtÐc|» t®ôq0èô©>X¶]Ͻ€Ï?––ÌbˆN>àxfaËÓO?à%ˆ#>øÑu_ù“?žì?ÐŒ_þê¿À|)%Pï¾ã\¿üšª×Õr¸º®!•Hn×tíÞ†\î’ó ¼- ³½[¶nÃ'>ù‰óþr ŒÑãH/ IDAT hà Gr‘†¶°üƵkœQ¿˜*T!bºŽ«-ÄÚ5k°fÍj45…&@o/âÉ$äütÕă˜ßlPr KìHÓ Ùq(Úƒ@Hç«8Û¢ÊBg£LV’iͪÊ×1UŒüå×õÐ0´³çîW“ímØýÂnìÙ·ݧ&ŒúþØÈðÉ]»vþO¯ˆ}i~g <øÐÍ_ù“Ç&ÒS »÷ìÃögŸ…ã8ð<®ÇÏÏï—@QT¬Y}nÛ¼©êõµwtrÆNw1ýÞKÍ/𶀋)& !4ä’ŽlG™@¬¡qöæ®Yy;ѠʺÔl6‹ë¯[Ž5«oÂM7­B"!]¾ÞÞ^Ô͘Ù´r2qX>¯*´¤òÛ\ám/Ò~̉tÙ‰ôÙ Êq£1ÿ¨ã/F$ˆDh¨øŠPþhCLãÛ1Á ˆé5Ï–º[Mº{z±gï>ìݳG½˲ʎ3ÏuŽ=²õdgÇôƒ×sñ·ÈB¸Bxð¡›«™ æÏ½Ÿƒe—P*Ùð<žçÁó¢(Š¢`áU ñѨz­'»0::†t:=’0Œ‡.™|·-ôõ£¡~rz}N†%$úäZ¦ ëb0kõº ÷eÓ5s ¦8!˜ÕÔ„•+WàÆWâ+o€¢„ãp?jkk¡ig'Éx3;ÂJnXCm³%{82›>*¾L*’ IŠ"ª£,@©0”°¦ú|dxxûöïÇþýÐÒr##嬚ùðÆ‹æÀó;žþ>€CúÀ«ùƲ³$€ZˆŽ9@Àu  â•öW`а, VÉBÉvà:|¿:ÔÔdñ…Ï~†1¤óùŽ·¿‚šLñDâO›?ÏGpQåm ¯…D¢¸ÂK ˆ²€"ÎAp6°qÙÊwPUÝÐ4s®˜ƒ•7\nX믿® F†‡¡i1$«8¡&G,r΂(È”\7’¼3Y<æA0ú‹2e…ð‘^•Ê/ìùóå£222†Í/á¥Íhi9Œ€î3qM ¾äPë3'O¶? À(€pPÀŸ· Ùʼ n<ôÐÍü•Ç?Î|†Ñ±X–…ñÂ8NuB¡`´,Ø% ¶ísÀƒïGA@…¢hª†ßþ­ObþÜ9Uïã`ËaÄtétò§z,öp®þ͸ Q">™6œ@9D_Ë^ƒ²×Àì+Ö¾·±©~Yèçþ+æÌÁõ˯Áu×]å˯ M¶e!ŸÏ£>—;¯köÄâ"R‘'@æôGÞø #áE…rí’ËùŽîÕ¤¿[ZðòÁ:|ý}}v¾ÏËçÇNì~~ÇÁÛw €øCÎ ìé ÿ²žCnSäO¾úÕ{>øÞcYJv vÉÆÈȺNuÃ4M- ¥ ^‹¢*Pª¦àÝ¿v;6oÚPõž·¶2étsÌÐïmÈå:/Þ;7¹ ¯& Ù@\,•`G8ï€*Þk(zrÅÚÕ«nK¤Ó³H¥bºŠYMX¶l)®¹f–-[TJ) pÙlov9~¼‡[Ûpèð!;vCƒCÂzP,™ùû÷ÿ_@ÿÀúz{qº·=§O£ûÔ)ôõ÷cddlBü^cð<Øããùžã‡[÷õôA¨èCà¹Oy„6|Ô÷À ؤ?ŽH´& à*‹¨‹.^ð“Ÿýø¡YM³çM‹p°aYÌ"ŒŽåÑÚÖ†ÂxÅ¢ð ”ì€öSJS€‰òG—1x®EU°ìêexìóT½®£ÇÛá:²5™NÃ0î­¯¯{Í“†.Àk(”¬W”ÕYP3j†BÉ€’FYŠP7E¨—¢”¦=;¶,VK eÏkà §oõ 0€>x&¡E7c©†9J<¦CQU ¡ ªâCUˆâ#SIÇQ[Wƒ†30sfêsu¨««G]6‹l6ƒtº©T©Tò¼ÀÁ4ùè˜Ïç166Š‘‘1 chè †‡0Ð?€á‘aäGó(ZVUg0ßg>à8fg×ÉÇ·¾ ¡mŸñMpÅ—s7ŽƒgF{@`~M)„Ü0Àµà¾ú¾¼Å·¾ù­Õd39³hÁ²Š0Mî 0- ¶e¡¿oÇÛÛaš˜E EÓ„ï3hÏéRÄLC„ÊhÆ|¸7-æÌ™Ç¿òGU¯«§§CC¨ÍfG’‰øÃõõu¯iÒÐex „’õq@Ijš@­!Ĩ¡ªZKUµVQ:Æ”&gܽÁ…³0çPbËAR.²‹WAMx¾ «AnÙMÑ:Úu¥þWB Ò^z”daíÐ]×X2A‘͉´OÅ…ªøÐ4@UÐu]W‘HˆÇ $“)$“I¤ÓI¤ Äãq†X,UÕ ª ˆøAÃ÷á1žã¡ä8°m1:Ž›(9 &L³€¢É½åÑî;ÕÅ÷áƒyÌóºNõì:~¼­`ç;ÀGu©øÑ [M„J/§swxÓQ| 0Tp°À\S¶€<ò;Üòå¯üÑtMKM EËDÑ´S d[hïè@Ï鯋(M”J6U¦( Š"r6HÐNÝ,€1Žã NãwûæÌnšp}cù<^iï@]]-’ñ䣹\ý·§s_ç#—à"‰B~MñÁH´†½NÑŒŠ«‡ž¨wóÎZÇ-®ò 463n\ƒÌòåHÎΡfÁ>í•Ësò‹§záÉZž'âñÂg¥ÆŒF˜4-ö÷b¼ýŒw´cøà>8CG ¨u¨«QXà *u‰ª0¨ª\T•E¥PÂmYUá:›‡„?Ÿ10߇Ï|>²ùþ¤#zUñ(ð™ï{¥¢9:tæÌ«Ço³¬üQ„#¹¤ór’V3²]‹-öþÙ$Òã±@ÀL„¹ýÔ#¬ýú×¾öë8ªY´`M˜E[øxˆ°µ­ ýý}/Q4yç MÓ (Ês@À<׃ç¹ð<¿õÉßÄêU7V½Î}û ®¶™tú‰\®þ5q^€ •¼[e`i¥ YBõ:%¦åT=Ñà•È*Ë*Þ˜ õׯCö†k1ëÖÛAb ÜPèíÃøÉ¬\ÆÌÐhؘsE-æÍ®ƒÏ|Xq]ÁÊŸÝ?îh+¢åHzF}œÎûxåŒ ;V £± ñlTúŸß†¡-}iÅfu5”åš(4Õæ™z:£šÆ j ªZ(29€Ïàóê`ËqÆ^ìï=ÕßÛÝ `\]„£»®ØrÔ—‹í­Èg<œ£ò@LÙŠ:±dÁ‚†¸öø?üã?¼çý÷~à]ŽëªÒ1X4C§ Y4q°¥g†GP(P*ÙÐ45jàäÂó<®ÃŠîºëN¼ÿ½wW½Öæƒ-ˆ'¨­Élר½ÙLæ¢:/ÀyŠFî% ^ u¨'Š1SÑõ™ªa4Xg¬÷¹¾9½à˜µþ&Ìy÷]pÀ<=·ó(®›¥à†+“Xûޏv‘Äò¬» h½Íèh]±»«xî…vìmíGó)gŒY¨¹j1T:p½Û~Žü‘ƒP(Šu9o4•€–ÊL"æC×mª*ÓJ|âƒ0ê3…*>á5¾ðáSÊFøô$¼¡êQÇW|…yÌ'¾RÕ,9vo÷‰cý½§{_æä»âŽ\”+¶ƒPÁåè}m# › ztîÊ/%âeƒ×:„sAÆò“Ÿ~hæ·˜¦Tþr&022‚–C‡122ŠB¡À Bô4M¢hPTJQ9Iyú0cð|ÎǃcÛX°p!¾ôÅǪ^ëñöx®ƒlMms"8“I_4çàe8ÑÈ} À«! 9(êL%¦]¡¨Æ¢âXþ~öü™·¼ ï¿úŒÆOå‘>›}¼k핸yeZØ„‘™^yó ©ôòW.…Dעݗ° „i>KÈÓ?Üfaï˧ðÝí§0b4¡fÑbÀµpúW?F÷“?`Ûšf¿ÄØÀˆï» cfm]¼–ª¾M5ÇÕèÌlÝŠ¢»u¸P‰F}xg†{K¶pá;Ìëê鑇ÁtޏÜh„Tb¹ŽnG•]nGßÃPË¿å&iEû8ÈÄ ð0!{a÷ÞÏ,^²hiÑ4u J&ÐÛ߇ÇZ‘Ïò,hš =¦AU4¨šU! D °p ðá{׃ãò"#Ã0ðío}³ê5wžìBa¼€Úºìˆaë²Ù‹—à$Fîךa õ”ÒFÓfkÉøæàØG<Œ_3÷Î÷aá‡Ó)†^~+2¼gÍ,lÞÐö““\B´í@ «îdn¨v›JȨ"<4ìö#çíôYøÎOöc÷)ê¢w žQÑ·õ)¼úýÀÆc±ü^Ï:í{gò £y†b(–*&‹òIÅåœÅrT}}áAÄãRv¹DÛF8ÂW.~ä¼>c“•'»3@AyG'Édª°¬Ó¨=räÐ#¹Ü¬9fDù‹"+в,œ8Õ…¶#ÇP(ŒÃó<èz,04a•§ƒHÇ ó}xžWfèz ~þÌ3±˜hhh§zNcF}-’‰ÔÃÙl手ð.ô$o ÐÉý„€¦ ”:@›It}¶–ˆÏqŠÅwY¥ãï™ÿžaá}÷Ãõ[àÖ&¾÷:45‚Oo-j왬¼‹ôÆcL(=ãÛÁ-Muk²u ÙH¤°–éÓŠ)ü=fø§ÿó~ÕjÞ»‰\§ÿëç8ñïê)ÅzÎµÏ 1l(äÌ<ï88ÁBÅ—J_™í(;(gÑ¥’ÞËe‚et¾#~ÕGÈùѯq„ŠŸAØ7@ kºž;öÊñÏ'Éú¢i `Chk;†Î'P( ( ô˜Må@À«¨Ñ¹ÚÀ©žçÁs\8žËKŽK%|ìcÅšÕÕ{6lA]]RéäŸÖe³_às¸_°\ò “ût€f ´J&5iÌ%jlYþ̉ÏÅgf”Õ_ýÔº z÷Æ®1pÿû"e„6üȬ¶ÁÔWŒï“i0&9m¸OJ5 Ø&a;/"·#]~Q¦K¢SŠ©áöw¾{ßÝk"¶hTÕAçwÿ7öþªªn†Z˜›dfÈ0äÇy'ಢ‹_±–Ê,Sž+G¹¶#û££=í:öü¡#f@eG§h±œüE ÝvÛm‹¾ÿƒûŒç91³hÁ  hØ·ÿúúúaÛ%èšMסÇbÐTŠªAU”ò´aŸÁgœ DÍRÉÆí·Ý†÷½÷®ª×ßr¸ét ™T扺ºìyG.À¢“ûâA¡7Q->WK¥®´ …{,ûÔº~ï˘¹îfœye ÌWñèÇVafƒ˜ÄÒtÚ‘”_Žür”gÅ—ýô0õÀ*Ç BÅ—Û–H«®`>Aѵ§P¾ûoÍøÁ 7®EþäQÿö_÷†O«ÆøOüRþ4cã} £ƒ ƒ# f”šG  à  üÈëÊsM™Åw1¥b®ÙŸ!Ѓ)yü½ï{ß²ùÎw>kY%Œ›ÅÀ L ?^À—šƒ²å˜®C×cˆi*÷h  "ÀéžG˜¥’ Û.aþüyøâc_¨zý[#•L¢6›Ý3ô{“‰Ä9G.À$¢“߈Й€>GÅ’˜±ÜüTrVMbÝßüw¸®kÿ^<ú¡e¸ayŠ7ÓM7¡ü‘.; å¶¾1XWN²Q)ò')²§ò=‘þ|$òþ`v ѽÂ$؀Ơ·øó¿ß®äÕH66 ãŸÿ÷nO~Ç·óÇ|o¬‹áL¯ž†Q™´_9òG•_Úþ~äµáå]IÃ9õ.T"åÛ²£Så¤/r­PÿìÏþlÓç>ó¹™–Exu wš‚ cÿ‹û126 EQ`F™9 )*Mä ˆö̼á¨Ïóቂ£’ëÀ.•0oÞüî>_õÚÛ;:á3uÙÚf݈mL'“ç— Šèä¾W~u¾jÄQM_7žïøÈ¢ûÂÒ߇ÁcƒX¥ôá#¿q 11⻀ïð™|}7Bõ…ÒÙhSNž!¿Ì5ã|%è@"¯%`0Ñ6^#M;UM´òÒïÿ ?nŒ¥+0º'Žý¯¿‚¡Õ|χç{<<èr€eÛÐ5 ßüÆ×«^?z¨ŸQ?’0ŒÉdbÚ‚ËP!1ò@ ³(ÔùJ<±˜Üf»Þó׿Úå×`è¹—ñ‰M³±vM=\›ú®+æésË|ÑI2Å|ü?¿|´—‰þQõ˜†°".È…F6¨×ó`:bºš"L¨)Ѝ"¤ÂÓéà ÌnÉAÉqaÛ,«„/ýÁ«¦ ·¿3êëFâFbc:œ\€ˆÄÈýq@E‰6OM%–¸ùÂÇ‘N¬Zóõ/˜9þñ{Ÿxrµ¼«®k ›ßm¶…·Ÿ…šj2€0À>ë¨å>”¿mÚõH‘l€±ÈD ’Ð0r Š®½Š`%ø‡Ú‰ƒÊ"$ê2xùÏþöÀ`G"S÷-Ï,óÜ ã=~nНa¢ñ¹T•|:"Ì CB€,ÂfÆ™¶¶cÎÈÕÏ1‹E˜ã¼m˜Y4ÇàÑcÇÑÚÖJ ÀaÄ ÇtÄÔÏÔdÚ°ÎÈäC$ ùð%Çcs&`Y>óéOaé’‰3K £··õ3ê‘N&N&OLã~/Æc;o¹d€Ó~¥‘ÒØ<=•Zb>ޤ³jóO 8bca¡¾g!b1À³9ÕwK¢±¦qòeÝt}„žz¹Ò«fS¾Œ²z.Süí¤Â³¨i gÿÉÖÞ2@Q…)í¼uà?žlÃOZê–]#ûG8ÓÒ>šªiú’gŽúNñƒ{Úbß­ZÈÿf”H_Gаe[tÈð”á˜xObhhè/C¢`ašã¢B°(’†L4lAgg't=& ­¤9ãMZTE„#É>xÝ€ÏMÇq`—Ø–˶°yÓ&Ü}×Uïá`ËaärõH'Ó§ÓÉ'Îr¿á©¿\ “ûâ´‘’Ø•j:µØ/~œ$íU·}ç Δ0ût>ýÉàØ\é]Ñkßu¸Ã/Jõ9+wòJ_ñ¬ååÓÈvpl²›F…³„§ð·ŒœD€*œ†£asO™@$M-Æ[zoÝr ß}±€†n@ÛßþF[^MÖÎþ’“?껾÷VÉ¢mÞeÑP8FçÏŸ?çÅýûÏ÷X¢P4yQ³³(óŠØ½{ú L@7‹iÐ4Ud Š¡@^&Ö ”—3’˲ñ®Mp×wT½‡æƒ-Èåê‘I×üi:||Š{½hÏí|ä ܧ 3)Q¯Ô’é%¶Yü¸’rWm~â ÎØ¸96‚_ÛÐÈÞœRÄæV/#§Äޤ®H à0îÜDðß9Ê€Øûç| T¬$#ˆ¬å¢ÊY}b€nÛ·Å“¯0$®ZŠ#ûGiiMfg~ÉËu½R'{ºÈ¾_µ»Ç›Q*æzÐQ>Ù‹Œ Ôƒƒ}ì±ÇnþêWÿìã…B¦YDÁ4Q4-äÇóØõÂnÆó0âqF FÌ€nèˆi1hºÆ£"c0 ¼zP:KA³R˲0gÎøÂg«79ÜÚ†LMÙLö‰t:Y5Wàm 1r¿F@ ÔùZ2q5(½‘Òû7ýË?¶°)kaõ;²pJbv§ÿN)Lçõ…¿; ú_ðl«(>PÅ™V¶:/©æX‡dL8ú¤£÷”ŸÍçXÛüݯ:‘[qŽþí_`üÐ+ûÔxâŸ\sü¨ÏJ¯~ŸÅ~ðVeÑD¡4¸A8ÁˆòßüƦG>õ™û Å‚è‘ €Ï+ÏcÛÖíÃ07 Ä †ƒÓyâH’eÙ€æ®èÃ8m›3¢…ÙsfãóüNÕ{à CiÔe³Od2é ð6€s ´J<±w™…S|÷w¿ ÏÕQ{â(>òÐup,Àµ¸S̵ÅÈï‡1}9⢓ϧÛe£³xO 8Ëßà\„“ #Ü(wTe$Ü8c@,Æ}Ï={?;4Žì’%8ðûŸ1É^ňýoÏ20¸ë³ØÊ;z¾‰¥bþGåNÁºÈ¶ €>óÔ3ÝxóM·pŇYlÀ²P,šÄîÝ{@E"8 Ät º¦CÑøü áý¸?‰ç„æ€ Û²aÙEX– E¡øúW¯z[#NcF]ívÃ0îÕu-ÈxÛ€AÌhs5#±T‰Ço9sô±Ûÿþï`4ÎEüåCxðkaÛâŠoÛ!íg>WÚ(플…^vo—7% ¨&UÎ9í§@8P1R:Œ…@¢æ€ jTƒ3‚ÝϵcKñú,^üÜ' «É2æý³í#€ÓÁ€A‹ýàM ¨”Š™ e[÷hª°ÌTàðË/?Ö4oÞÒ€ŒP´LŠÂà´Ø÷ÇÎå>/e©¨ P™$$…(€tû‰f3™9Å‚ÉS† ¦È(b¼hâÕŽWqèp+ñ8 †‘à~Ý€Ó…O€G¨BDs1€Atr<plØV EËBѲ (û¢µx IDAT >õÉß,›aZJ{{|õõu͆alLÆÈÛ>Ü@il–É,wÆòŸ¯½qÞ5·~ó+Øy½g(œ"` Å·-îA0_žÌðã7!”´ÊåLåä«°&ì›îßfÒÂÙüÒ7A# EE”ú HŸ€4ƒfÿø¿ž³l#ú¶ü_týø§~<3ãËN¡Øì{ö1Àëy+™@ÀdGáÊç”9qŠ®%ûþÐq„d…b(˜Ettt ­í(’‰Œx ÀŽA=]ÓƒÆ"TiÃ`b 7®ã–L $úˆ"¥Ç{tÂ<p¼½¾̨¯m6 ccêS‡/¶¼î'¦ ´¹j*µL1ŒÛ¬±ÓŸ¼ë§ßÅðÑ^¼çÚFÔ7v(Y€c†Ê/Ã{2¾/W$Ø”X(î$˜0΄Ïõ¶+ßý¼LT JŠÅ~‰0ÂÍ™.,AÀõÿñÄÔ­[C_ÿ”N =O4å Ï´18¯Ù÷ÏíJ/m©R<$ý•5qÚÒ‹g½°ß=Ïå9…q‚ð w:Ò†îSÝH$âˆ'ŒÀ9È™@ º®AÕT¨Š ZV@äÓæ€Í™@I0Ëä©É}þó¦xûqæûÜ0Œ™Tê × r¿F ÎVb‰%Fmöº3½mßÜôí¿@jÞ2Ìè>…›×^Û¬¢`ÂþgQï¾Ìí'婸ŽéÒªJ‡àÈéf tî!$<7 `¹ùkQÛ´bÂù&{S=§à˜”1±&2o@,ºð  «c¿84Œš+çá¹O}™šyãÍç|Û:ÌàwÙ÷Ìi=Œ7‘Dz Ê)ß* ‡²â˜ò¥/ýáê?ýêãŽn˜( A%¡Y´p ¹g†‡O$¸I`ă|ÀÐdÚpÈð c‹iÌì :±X´p×wàÖuk'ÜCÛÑãð™™¹ÜH<™Ø˜ŒÇ_ó9ªÉë<5˜RCˆ6S3âsÌþÁ.¾ëN4¬\†ÁgÚ°æ}KQ,òQ¿$€[bðãi¼‘nr»š¢O¦üSc '›¿‡þÖÅ>ð¤Ó骆‚|>ýè÷Ñp͇1oŃUÏ5ÙwL)ñÀå)Œ1Q·N@)# ”P¸. ‰'Móg`Aëqôy ±è£¿‰Žï|ï·âéÌuá;ræž·¢È2çhæ \ä4ïìßøó}žçÇ¿öµ‡ù´ëŒWþàQ~7\w¾ü2†GF …R•€¸„çx UàS…÷wZ (QAŠBA…÷T_(Å/~ù+Ì"î¸msÙÅ/]²H¦gr¹mã…ÂÆTrzõ—Šœ0ÈI uŽO.SSé[òGýõ§þǰ~A-²µ*œ"P2Ëôá=xŒ{ö|ߨg~§ž.D÷± ð°Í!¼ðÝ÷ãÉ'ŸÄŒ3Îz/ƒƒƒxÏ{Þƒ›ü1ôD}pÎéJå{Ë^y}O„B4± š®BOq® ÿþ³H­¾/ýÁgà —þ„ü«oY- î ó­Ë¤?@N/™@4B@¨Û·ohÕªÕëÆ yÞF¼0°€BÑ„Y(bß‹/¶-Äã $‰r&`Äxž€¦BQ4¨ŠÓȆ".)Ã2QÈ‚)f4*š&Þyë-¸½>Ai_/r¹ÜH2‘ܘJ½¾ ðº1š¢ŠÚ ÆŒ+ÌþÜøØçÀ(0‡9¨Éª° €mVÑE©èÀ-y „ð.®d^ß„{…²Ë׌y D‰|¶òsa{ßñ3'±zõêi)?̘1«W¯Æø™“Èè5Á~Æ&›„ƒV9^¹/Òp@€ Ltµ¥”€Àõ]xLóTè)`ÕÒÙØÛÙÅ¿ó(|å w§kços»yä Þ‚,@>÷7 à]ŒEãµ ÕlذáÿlÛ¶«V­Yë3Fø|((›caÅõ×cÿ°,[) …¢P¾¦ ¨Â (üGHU(øPŠJ (T4!”÷ „bçó»@)Ám›7•ÝG®¾ðzûû²¹¶oÌdRo &0mˆ“ê ª³¡+¨V¨¿úƒ›qbë ܾz,“Ûý%³„’éÀ¶y7&“çá 0¨ÀD ùÊ•+p°ùeX–…R¨„+>¡Š òÙ‡4@¤ +ÜPTn(.Jx¯ %ØùÜó(nÛ¼¡ì&r¹z0§{{³3s¹m£cck2™KÎ4UÔzÕˆÏ?3ð«~ÿa†Eµ10EÓ‡]´Q*ðì*Ïõ…² êñ ¥?Wê_ÝÀÂuó_t•žr—ï› Âm¤$(pˆ0‰|À'V^¿;Á‚| »|xm¾ä߉åôÂóߪ,€BdãÓHŽ%€dP˜=ëŠoŸêî~,NÏñÅŒ)œ ˆ>Ãõ+®CËÁ˜–ÅsT®ÌªX<ª@ñ(|ÊA€ B ð(BT\ñJ@ ÷ <¿k(6oÚPv/ ¹z€ùè9Ý›m˜™Û6::¶±¦æÒi€AH(Ðj©kp¢%ÿúèÞr+WÏ…•g°Š6l³Ë,Á)9òKÅ'"É¿úH^.S)ôûH æ‹Ébx‘‰ï3ø×.¿­‡Ž€X&Ÿ~‘ÍéžžlÃLl:sC}}mçkÿ$ÏMÎ $A¡fCŸáŒoX|ï(Y0X¦Ëkª‹%”Š%”Ì"WDó(~p¾ EŸ ª½žœT·ã§ɦ2¦ë¨Ü7å{ }”W­;„ðæb”¹rá\tt àŠ»oÇ‘oÿÝ&#]û+jÛu¾OðôD„!ì†,% øï6 €lݺõØ—¿üåúú×ÿâãÑùâ¸[€Á÷¬,[¶ mGÛ`ZB)ï¤(D, <÷äíß¹j>UáÌ 0‚––¤SIlXkÙÈ4âÓ==Ùúõ?éëïß8³¡á M®”é@œªj‹Õž¼aù'¾…3Çò˜;«VÑ^Þ¾É.Z"Û/ôìG¼šbO¦ìçê+𼪠ÁÏ*žçŸÕ¨Ü7ÍŸj»Äè0Dèz.jr3áî?ŒÆõ·àøÿüÇ$¡Ê<¢¨¯Â÷’ òÀ“}ïünøáBáA ùƒÈÀ7¾ñ瀯íëç†TĸI†¥K—âØ±£0M®Äªè (Q¡( ÷#(”\U¸ž'L)P¹o€rÇàîÝ{J±áÖue÷ÓÔØË4100°"—›±­¯¯ãÌ™—L r¿J ¥hL«…%™†ÈÌN`¬¥ Êüó Ê-0ÈÀ_~ã/Ü}÷ÝKnZµz]qa'&¦–.¾‡Ž´ŠØ¾è&,(½B —À'~ ‘‘^UxóQ¢* ”ò\Bxë+@`Á‚ù8s`ƒ+êëgl;Ý×·qÖÌ™—L $®%­¨j]ilì–åŸþÌaÀ V±„¢Y‚U´P*ð¬)ÞßkzÊ>Ù¾é0‚Êcàº^ùÏcšâºW¼ 9Ÿ`5û?úÞêkÂk"x&ÄD„*ꛚÐÙÑ9ï¾½[wݨƳ5¤DSðÃ[€ªL€ Üô‘m9E9»eݺ'ž}ö9¬^}Ó:_DS€I^êãÊùsqâD—ÁeœŸûž§« o2 ð´aR^º.Ì•pg¢a Àî½ûLW®ÀþÍ‚ ä¶>Ý·qÖ¬7ÎbƒhjšF¶4Ú³ôÊ;6â̱Q4ä²°,a÷[%Nÿ­"„ûˆ@M`j»:þ²+šdŸçx x6öp6&p!kÆXw\ŒR0ª žNƒœ@úº5P E!º–BRäÿµ÷æÑ“\Õçç½¹D.¿¥•JUÚ¨( ´€lÖv ÔžnƒÁjŸ3>öœÓcÓ¶zz`ðnZ`–nºÛ†ÁÓ˜EˆExŒQ©(-”J*ITi©}ÿýrÏŒxïÍï½Ìø-%•ŠZøÝsâDddddDdÞïÝï5¦Œþœ¦„<03!øB¶ ¸vcògö•ŸþÇÛn³/}ùË_F¬ŒMkX³z5Éc{ö8†öÿU§x§Ÿòê¾ÎÎ)X4\ÞÀB-AÉ[·"¥XR@tå—±m[Ùgœ*âЏ""YR¬OgWÓX_fnG‹,ªÐïôûôÚ}Ý6&×>õÕ1µðMòN—ùoŸì˜@yžc£Ópæ¾'ùã³xûTÁ lŸ”éïdž#”DÄnÜPIhŒÙ_‰»|ˆ¸ŸÌV+âí²o¿øœôi7æ ‡Nãj ÄϾúÕŸ>tøðÆZ½¾ÑŽ=Rvl ã2÷°gÏ>7^L "áÒ†I P¹š˜Êç¨0²Ü‡H)¹c‹Ó–€À•—±uÛ9rì²Õ³|g߯Y¿nÝÓ£è©Ê"–õ¬Ý½ü¼7ý £>ä­ÃD2ìè÷‡Œ†}ƒ!Öh¤/Á•Â#¢ràüD&Á“ ž ~' y¾`ß©%÷œšàñ˜ß×mÁ1B`¤ÄF1"N¨4¦èïŸcö¯áè–í/Šê²¡…®`ÍsÚP$"Ä' iœS0ÄS‹ŽÁÿZ®]³æC‡º>­Õ6Œ3 såÚXV¯šE"Ù³oï˜q…tùc“À;U$Q6B)é}vì>*àʌݘ2àŽ­ÛH®¾úe îç¥W^ÁÖmwrØ›O'<ÄBÚ’ŠduØîl>çê+i?I½J¿ïl×=¥Ïhè:Y/aæ ”ï‡%”|\-àɆ¿6§ Æ/¦ ˜“h§’ôDÒ?¬—¤‘5>?ÂY¬ÖZrcQ„ˆKT¦šŒ`úâç£éŸ©FEJþÜ÷,&¯ „M¨rÂÔ¡ÁÚµko8pàÀõõFccðàS‡5t Ì®š)Ø»oŸ—àAŠ“ ¨æ+„ÂÕÄT4ÖdÈð@"¥d˶‚€«_± l½sl<] pR#EEFªš›îš5/}Gw´!J¶ÜܶQÀ Û#e,g÷ !Èq ¬oÊh@)qRÉ_|m°y‚° Õ§—”k\¤ÀKw­5RÊq1l?ÑzYM °O‰ÐÚ™I1(“uæ©®ÙDRk £¨.e”Z~:ü‹Ék¹p‚0R­ ÃIzëÖ­ûо}®o6`Rw"íŽavv!aßÞýN 'ú(ï ˆ¼)MÌP'I"jœ¹  yغu° ¼ô ¶lÝÆ‘#Ç.›]eoÞö”>¼eèq4U*©Š$IaHmöë"”dÐ9…³û¥\À่Ü9VŒqqoc¬=) RJ^; /gyæ/ Àèôв,¹¼ =éþDÛËIÿpÝËEBdÀF%( ƒ Óí`-4.:Öƒ{~FF¥ûmF9¿$ºö O;P;€LÀÀâÌôÖ¯_÷£<ÿýÔØjøËg‚1–n·ÇÌô ɾýûÇE?!å7¨ù‘šDÎaJ(”Œ(‚OÀ}$‚­Û¶\ý²«ÜÄU/½’-[·qìèñkv>ø£/~þóþíSýàŠ´,TÄ/ %Ke•Tjdò‚µ—\Œµ0êkl”3 GÞ8 tùᦅöÑ…’>Ï—®†òN^ú»Øi¸äØ“Tô=¹<í&”°¼¿xÿ“…Sö,9NgCòQN6•S†Ç5‹žÏü{Ï‘ªTR'V ÅÂŒ¹Ÿòæ@',ÕÃYÿúè¦M›n¸oÇŽÿ`1Uÿo:Ý3ÓSì?°ß3²—äJRÌü ‘×c@M: )E$ÑØ'à5b¿ýƒ­Û¨Uª¼øÅ—.¸—«^z%·|ý[×í|ðGü$Aà$@¢¤,%JU«Öˆsκꕮ·_îâ*:Ëe:Ï'ê¿”. (8GL`\5N„ C=€ñ’Þ­…!ƒc¬ÿ  ŒU(ÆŒs·Ïÿ>(þ_˜•=1fü:l;)îþZ[B)AkëLJ;Ÿ1.«Lû(‰;~y פG9:ÏÈsM'd­6Íç_Æ£æÛgÉDÅ®¿•9ÀçsŽ„îBá û¦€h×Cí}áæM7Üwï½×cÓ4ô§ ƒÖºý3³SHû÷ô=—è£d0 ”7"¤V(¡ˆ"¾ý¸’™Á'"¾,ü¶úÿ8ÿüóh4ê nâMo|·|ýVø ƒÀ² E$‰b%ârÅèØadÍ`GùzªBY‘EVŒ–:C~Ѝ" ^ÜÅÙ‚áù4x×C»ölÚ´ùC;¶ß}µf«vü‘ÉoÙíö˜šq“Ê<rÒ0D¶Æ&h¥\3)ˆ½Ï@Œ»OBƒàê?$ðéÏ|–_}×;—7pË×oÅØŸ,¯!¤ˆ"¡”‘ç^ý²y°I‚ô0¾„6Ï2,‰i¬ cÜ4áÞjìñBPl#íßÎUW]uRu¸¸^nßâÏ]|ñÅOêæÝñ;âðsåTB“ÅÏ!زe V¥œ˜úUŒ•'½ÞÉùÜkc]“K÷¾WKµÆÎrŒÎ³/z![9Vô±bøS 0v sÀ²Ð1ZLšäîݻۼù…7l¿ß—{U ô0ÖÐï ˜ž™)9pð ›õHAý—“@Eã¤!!%1Òi*$IÂ͈¤|Bâ'Ë€FX¡JЬÛ;Û2Ç ÝÀ"ÈA‹Ñ®’Îø†NÂúÆŸJµ(#0«ý>Ã1 $z?ëâûøë/œZÏ§Š®¿þú3z¾£GòŽw¼;÷YŽÖ]·á… Ò¾à³(€@8Öjí&Ú‹Î ¹éIÐæ‘­ KÍsfð™ bC‘¶ß^l4¹û‘]{/ݼùƒÛ·o¿ÞP­ú2'é÷LO5<èÚ¸ ÆÎ=éÃ*Ddð7„$ íÇTÁàLA§³ >óÿþ5ïz×;hÔ—àº{wÜÿÝK6oúÔSóÈNš<;™aÄHX«ãRsXérªµÁhßJ+ËÑFû†ŒÎ|7Æ lðô3^,+œvPÊåÚk¯}Z™ÿ© U«Vqíµ×"õü‚{×ÚúµÆã.vÒ£Þ-hsí@ h°²¡‡¡óÓXBÖQè#0À9»80˜:L2íîÝ»»tóæÆ*饕*i-%MSji…4­Q®–±Æ255ÅÙgE·Ó¥ÛíÑëúu¯O¿×g00ŽÈ¼9Œ©q“”KTªeÒ´F=M©×ëÔkuêõ&õFZ½Îg>ó×´Úí%÷ó¦7¾ýÒn·oÜqÿÎ랪ç¶,XÑň–(X{é46ŠÑ&ÔX›q .‹ÀÇøŸÞ`l(ÎtNû?³±P_„zÏ ÷z N>,v¼X˜Æ?4ájLæžu® 6®€„ÙͯÇ2ŠVüTå…<\¢P‹ ÷ëxA¿û‘Gö^vù‹nˆKq¯Z©’Öª¤Õ”jµBZ©R.—±ZÓ˜šâ¬³Î¢ÝíÒívèô=ôÝ2  dCç´Å‚’’8Ž)'ejÕ µZJ½^£^¯ÓhÔiÖë4ujÍ:Ÿùìò ðÖ7¿‰ƒÒšo=e °¬ `XKŒeèÔv ³çÝÝ÷22#F™ðŒìÕ~(0%Æwë„ f€VÁ3þdvÏ ÷æü ¾z¸gwÄ8ão¢ò»Å€Àƒªv@¡ Y§ @EX¡]ó²çæCüñÉ28Ò)ì&8Ÿ€Ù½k×þ˯xñ wm½çz*•qt HƒÁ€©©H8tø3`‘I ”DFnJ‹URD‘ò‘W6t„p¡Â²r#ËdäÇÉqˆN¾pã½;îä’Í›ÎH“Ñ“„« *HY™Mþt*‚Ûÿ ˜Ì=@>¿‹<*CTG6Î%J7TWÕÖ ^¤WŸëäÀWúI?vúõR ¨Å˜!£ö^Lÿ fp,ÔfÎ%š9ŸèÜ+ý¨qé€Yİ|\ò Š„ Â@Åî¬ €Ý»wï½òò+>´më¿K¹œºj ÃlºŒ²qRbÃ9Ø·×-go¸á?†r9ñyÂ×θK’^Ëî´[']º™í;vLß¹wÇý¯9 °¼ kBÊÔ]ÐóY®{×B¸à‚óèüh×®)!åå3e!Ë J `ï=óÑtRGÅ d䛨ëA〿ó`I¿ÏäΗÐ?J>˜#ŸSd«óe+úž 4N&²Ö%LZèQ—<뢇óØl„éísLn´N39ð 6ƒ- å%…pÙ•'º‹ÒYeU¤zîkRg‚<X&CGla)šM@îÚµkïË_~Ň·|ÿŽ÷P©ÖŸ¯m ×I³aýÙìÝ·œx\ìZ…)?šL©‰ë‹Î¨ IDAT¢”$MSÿ;ã„&<Ñ™oñµ›oá-o^Øn|ó ]²Ûvíž:묵߹wÇý—œî³9‰ ±@(«J•¶éµê"j¢¢¡JYB¨²ÔÄ ÚîÎU˜Ü4>‰ûC“¸ÞÊÖÙ¯íeÂÏ ÷uì¡[î(ŒgìÜ¡·' Ñ*ëÍSá=~Rƒ¶ #×@ÄHŸX‚U*!eŒ„ÏM} È.D:`aÍ@‘š>¸ë±—¼üeÙòÏÿô;åJµb ÇY,v\gDqÌ9ëÏæÈ±ctÛí%'› ’VÚ êiÕ§‹ñ{Âksss »Þ=Åšµ·}Ç}¯¹tó O«—À²yi‘ÎͬJåãÖÎP[ R•Q2AÄ%dTFF dD ½m*#Æ(}LËj·’ùžâ¦›nâèÑ£§sÍÏX:zô(7ÝtÃ<r9.¥ýã Œ{Z¸B(~—ÅEKT‚ B•‘ªDeÝò¨h%êVÈB5~ò7ù,&Ÿ#’…º,Ì(& iÀìz𡽯xÅ«þ\XÑ­Vʤ5—(T«¤ÔÒ*‘ŠÈuNǬ?{¹ÖtÚ—/ÐéÒívét»tz]z>ih9J«Uj:õF“f£I½^£ÑhÒh6˜››ã+.°€6¿ðb’¤ÄáÃG.ëõúßپ㾩Óy&'IÆJÈ­59Jv÷ný¿í­Žñã QTBÉ*Q©A.¼äÒ3¿/É–‘÷„m5VÓêIî{xÀ[ßúÖ3^ ðdÒ{?øÁ²sçÎ%9ýpúµ¹‰øáÞÕþÒƒ_ú>oá@ Œ·$…ÿL£¢2*® â2"*¡¢„¹]!"™!+dŠrÅxòTÿ  ÀB3 ¸üê€xðÁ÷¾ì•Wô¶o}ã7ª•Òªñ°¸”Z~a‘&ðÆ7¼Ž¯ßú-Ž9zÙšµ«¿³ã¾¯Ùü‹Ÿ”&°¼Œ5ZeQ%}8ëˆÖׂRe„*#¢2"‰Q¥Ú„ée<ñP£ÜkD€§1 Ù7s¸pß¾{ÁJìHD¨»sŸ¡Ù‹Ä†sXüñ>žŽ ¢:¼OæÞÙ¹s'÷Ý}Ý@„ÿ…°îG°aÛLu¼ß}«Ûo|­£em ˽:´i@K¯¹ãÝ{8Ÿ‰ÅkLx DŒŒ*n‰+È(¥ºnŠÖcmDRÞ'ˆ´¥ÜÊŸ‚pÊ&¯„þ‚Á'0‡“ú‚©0ĻڹwãÆzÿý;ß333½1 @xøínå;8rôív×GÌŠ6†Ô:•Ë Èú½ÜàÌ{¶oçÅ—.ì%ðÆ7¼Ž[¿õmŽ9rÙììªy’]…NÒÀh0#£u/©¨½‡vÜC\~ •©ý¹Äý1U•!©:–¿9ˆ¼?@@Tp"|è*¼6dF‘ •w†cT®úmë¶ÎŽõÚ… N9Æô'ëXBÐ75¦ê¾^;¦‡B*ˆ1“}Ö÷¤4^¥G˜:÷ œxv"ýE8ÞJ¡!‘„T³Ö®áÈ‘c´[í…6¿ éRÆcµ4£œ$Ⱥ3íÿ›¸}ÖÀe‹мáu¯åï¿r3ÇŽ¿fËÖm7^õÒ+O¹‚pY@·õ_­±v`lÖI²ëðƒ $”gȤŒˆ+È¤ŠŠ«ˆò ˜_xi4‚0ÊM$iÀ ™h xbüÚNœgÖ@Á3]P¡mhŸxôäÀ}Â3« Œ|º Íø{µLVì¸û²…ÏböEŒ\$’Bùü åM¦¢WªŠJRâ´NÜ„C÷lAÄj5¦b„,ª&+ôcP†k°ÚÁµk3ñÌû÷G@gÓ¦‹o8~üØž$J¨§µqQ=M‘*rr:gõêÕ”’„ùv›N»M»Ý¡ÝîÒn·é¶»tÛÝ“v²N’˜f£A½Ù`Êûšµ:zƒí÷îàî{¶/ùÌ¿ü…7Ón·8q|Ûî¼ñToü¤ef`µîÚ,kÛ¬B{Ìn¬"£ Q\&Š*îÏYnºÓX5aþ±ä=dH@%Œ3Ù„QrpOD~_â÷3a®±}Ñ5Ÿ8±ëÏ9¶Ó…4¾‚„GOlùpÖöÅ“eئWn[ùç‚pŒ_xv*NQq•¨TAÅU*kÎF*˜Ûý²ßk°m¬ôŽþÅŠ ðcRè'€Sùt™8»8!óÇõ7mÚôÁVkî±$YDD–åh1=3C³Þ @ Ó¦ÝöK×9 ÍIt¸$Ži6êÔ› šÞ!Øl¸B¢í÷ngϾýK>ó¯éZæ;ó?~âº-[·ýö©ÜÿIÀX†Ó5&kǵڮǶüƈ’2®UÔ¸:»ˆùƒÄÃÿñ j¼ï¨Jˆ‡Já€@ÅnŸ%PHx))’(ó9ìiU=¨øA‚‡ÝXÃY”ïîQ–—‚—òNHÙCá~ðÏÆŠÉý©Uª!“:*©"ã2õõçÐ;Ø 6·mcl×ÊŸ®–àO%¢Cœc°SXZ~@À0=ñb¨ÈÐ:£R­Ro6èô{´æ´Ú ètÚKŠh,F“oû6zËDþõµoçàÁC´ZóÙ²uÛuOtï×S.³Æö6­8­ß³çö»™:T©JW‘IÕ@©ÕÆDÝŸô+¨üÆK¹h!,‘” ¢’ „ H‘_ó¦ÔøØž;þÄ P®²jz†N¿ë˜¿L‚öX;8M@ î@ ^§^wÚÀ¾ðEz½¥ƒõök8xð vûÆ­Ûî¼æñîû¤Ð;ö_Œ±¶§uÖNêÍ-n¹¥`õEg¡J¢¸J׉“Uõ ¢)Eæ޹dÁáL¡Ü³›%&RTžDÚ  ÑÂEÊÓÔÄäIøvMŽq½/²©L›d\1Ù4— y­HŸGAý‡ XZ,¥Ä¥q)%JR’ÆÕ5pxû‰Ê¥»­Õó;°Òž|žÙ Y;VùBS‘`´qæ@Á÷ÒÛ´yó ìÜy×€ŠÕ«V3ŒhµÛ´Zó´ÛæÛmÚ­ö²ý%qL³Þ Q¯Ó ¦€_ÿíM7-9>M«¼ým׌{ |ïŸo?iŽÀãiXtßäyGçÃÖ°§ôáû‡¬º(F%)ª\C–ST©F©¶¦ÀбÚn,c¯¾)ÚÓÞ„É‹L„…yc¡(­‹LtšIqLÂuŠ¢†!–ÿÞïmþ‚v#„Cƒ¢œhÖ?·¨D”TQå²\C•Rš\H$aß–-¨jõûÚ˜–µtû>¶x ȃ@p ™ø:¸f"à(N°@ïu¯{Íÿ½eëíß[âXX˜™!Ïò¥ Ðn»ÐáI(IbšÍõ±)ФÞlШ7øü–j•+¯¸œC‡MµÛí“ú°vduÞÉGƒV©ÖØöð÷ïaöˆKuIŠ*׉+SPª1–nøG3þÓûš‹±ú[ðˆ/`by’}j"5O ®ýøéD––°®cÌ´‘Ë|‡4ýck5‹,h5EÉ/}Kã%qÇ‹$E•›.¨Ô .5h^°ž=·ÿ(µ­ÖÇŒÎ[`žûÕTO#º …¢zLƒÇ(Ô\{ÍÛ>uÇÖ-OFff¦Á°ZmZíù'FÓujø¥Ù¨ÅŸûüR¸øâÐnw9~bî·NvÎ'ÐÈ´Õ}=Í•êSßýáo¡TƒÕ/8›8©—êDIƒ¨\#i¬ójlðœ{¦5þkÆ&‚ïÜ\´…D ä¢}¦ï—…ã`œnm|Á Wt,:÷87!' û‹ZJaÿõ¾¡…ÿXòÎåàQ©F\j—›ÄIJÒ˜¦qì»} ª\¹ÝdÙœµ¦m­Yq>ÅTp è39¿}‚É|Fû¶k®ùäê‹@@M@ Ë4frR¢5¿Zå$¡ÖhRoÖiÔ\_ÁF½N+¾ô•¯-9þ²+.ãð‘çgô~ÌXc:&Ïæ¬1{ºG:æðý#f/RDÕ:ªÜ *§¨¤N©±ÖÅþmqƒslømYžEf^"õŸˆñ Lyº&ÀâÐå £(݊׹hŸÎ¹é‡ Œ¿Ï®Ý›Un©£Êuf6½€(‚ýwl#®¥ßÈuvÂb:ý}ý©œô4Ó†ƒ9˜¿ƒó ý±¼íškn\Ò d’RBšVi·»´Zó´æ[Ì{­àñ|ÕrB£Ö ÞlŽ£µfƒl”±ã¾…Ù°/¸è"*à…uv?¼{ÁqõZÊÑcÇ>u²{|BèïûèÀ輕F‡Ë3³_yèw÷`ã•3Ä¥:q¹ŽªÔ‰’•é  ÊÞ  ã³ã“„Ö·‹%üiË9ÐÆïíñ'IÂgŽMpîx(³ù,+ùd.:&d7 qÙùU* TyЍR£±ñ\*MØýíÛHê/“36oYlŸú‰Ñ"ÈXØr¼ƒcþ>°€ø·×½ûóôxc¬”k ^K©Õ(Ÿ1˜éœ,Ë@ jiJ>1ßjÑšwË|«E«Õ>i²PšVÀŒ—q´°ÆàŸ¿û\¹\~ÏÉîçÆê®É‡'ô wXFµÇ~øÅ-_üKWñè¶i²a‡¬Ò!4Ðù€¨yù‰½†5ÖyÙm„Ë©/¨Ü‹}‰º/í+2©ïWHH\}Ç©“SKDĤ™‰7ýBóÎàÄ´¾Èg\PÈ )ÀØ…÷esoöDþœ¹‹†„k·® ®L“Tœ&•T›$å&g½äï8ı‡öPÝ‘òcÖÚÖ౯¨ÿ?a*€Bˆb·áb¯ÁpL¨âŸøø÷Ò¾ÿýïûµTÖ&Ê$¾Š0+ü”qL¥Za”åÌ·Z¾!ã‰EõzmAC‘@i=E[ƒõSB§i€»ïÙÎí[¶¾í/>úç'­<%°ÖvužÏgÃÁ‘êªÕ7ýào¾öžŸùÕ«8÷%«Øùí9’Q=ì¤Óë™ïλk|¥›ÿãcøB9`'ƒ …¥o‘ñƒVáÞ§©„iE!ãÏŽó|NCH?Â݇;GQƒ0‹öþAõÇ×þ‹D¥”¨ÚtK¥NTiÐ8ï\ëaûço£ÒœùŠÉô!«õQ°Vèé¦'Â…v™ð‰ÿåíÃÿõþßÿµ´V‡Ð™\B§íAÀ‡b ‰#¬±cG ñª³l‘êiêZÈ[3w~ìø ¶ß»ý¯ÿ÷¿uÛãÝÌ)qÍ`ÏGrcò–ΆÇL6z8Eû~øåûY9T¦¦IÊS$•&I¥A\mRYµÑ?*ÄÞ$`©º-X†ù—ñ ’‚ N4éò\»,/ÈO»(„òßµÈG¸Âu.2 lPÿ frò<¢ª“ø•)’ê4IµI©Ü`ý•çÓ=ûîØŠ,—¿­óÑ!kÍ\÷‡V²ÿžf*hg,"œÇ™ÐÿøÇ¿÷'ü‡ŸL¢Ø7I©¥NeTL®sò,'÷ÎA¤ ”Ät»}Zí¶w ¶iÍÏ3-ÍÿRJR«¦~úPÊC?ÚÅÍ7ßüwÿÊ;?öD÷sÊbÓbzZgDzAÿ`uzæ‹ÿôß>‡ÍáÜ+g‰«M¢ÊQuЍ:íƒjÓÞÖ¥ N ŸäÓ^í2Ùq ¢Űš)0cä5˜ftO DX/l2_c0Žÿ«ÂõÊÉ2¾æÈ+váqþœ“ÔbªL‘Tg‰* ÿü¦™:o#µsàöÿòa*S«¿¢GÃýZ›#Ób…žTC–3é.¢Åáo~üãÿþÛß~Í :×½iZ£^O‰âdy–£µ&Nb†ƒóÌ·˜ou˜o· W0»JZ¥–¦´;íGó7~ýÏX8(uY:e<òáž1ù¼Î†‡L–ÿ(DûîøÌ·ÙpÔ×Î’T^ŠM‘T›Ôf/„¸R`~é5 ¶ =}3À;4„(Hü"ã™÷ôÀ.a|–Sµ°åY±#’û4Ø 1„ûõ&E˜B)"(Õ¼Æ4M©:C©Z§T­³áç6rì¾ã}ø²TþŽÎ†‡¬ÍNôºaÅù÷Ì#ˤ”8”æmÆzx)µeË–~öåW}ÐäºW¯¥ÔÓš–¦$²±6 ÑY†R‘o5æ4€Ö¼Kêö–ƒÊå2Çß󳯼úÿöYûÄéâOÊp¶ÖÎçyvd4èï­NÏ|á®›¾Eï8<ïÕ5Jžùãj“$¦\_Eyvƒçé5`«‚„\F›b.f|üžÅL|*$„@ØÉ°Nk'€`ŠÇ,÷äŠÚJášMh(¢¼&>""¢2¥Ú ImšRµA©6ERaýU—NÃ÷>ñ?HW¯»1v÷k1Ö>7;¨>ËÉkÁÒ†CѼ_æp’Øì?|xÏ«^~Õ yn{µzÍk._ ‰cô22­ÉýD(c Ýn—ùÖ<ó­6íŽ+'Ö…Áýû÷lÚtñÆOBO »?Ô³VÑÙp>ÊwDéÌ÷nýà_±öBXû³ˆÓ)é QÚ¤Ú\K4}ãAj­ ¤ Ù.R©}üXú²”ñ­+èë [¶l9åF£GeË–- mm¡VáÁ@x0XÆŽC!'ENVú¼‡B¸p,ùƒ—ÇEi“R:C\m§ÓDé4µu«Y{i•»ÿæ› [Ý£V›»óÑh¿1ù±Á8yjØ =¨ØO ¨ æCIsÀî?|xÿ«^õÒ¶ÛóG«ÕªºÉÁå¤äB„Yæò2:w‚§ßë{“ M{¾M·Óe”eìÙ³oÏ9ë׿Ø Ükí‚Æ'¥']C«­i‰<;˜ ûÊÔÌ—½ë‘—ïºm¯|ÁkÏáÄÞiŒÎ°¹Áè›jV07 ãÂúç%,ËFBÑPäk¹¦œc‰o 4ðÈm™½ƒM¼ãïàÚk¯¥^¯/;‚L×’ü¦›nbOÿbFº4©`.ØÿÖZçv@:ÆZg½‹É4Ÿ0í¹(¹@çî>P ´k ŽDÕš”kÓÄiƒRu–R:E9­sÁë/bÔßøGʵæ§Gýþ£óÃÖ®ØþÏ ´+°˜ùŠªi`ÿþÃ{/Ù¼ùn¿ãŽë×­=kÃbI< ÌŸÈŒ×*ŽކÐk Ú~ô±=—½è’ßÇ1ÿÖžz´HœÎœ¾ò þcC%•åzãâ$m¾¢uè÷ü»/ÿ'Z'à®ÿy”þü1ú­# ZÇtŽ1ìœ`~ÿC0Ê&RS†f!žùU¨²Sc©*ÔDâ‚ç1%üã5 Þ‡% u”©øèø‘ÒuΔ¾Ùh8z>_M+›^Ò8DMžœ¼–¸þ“ƒüø¦1¡ÿ¿öc6£QiR}†rmÊ-Y*Y6¼b3^Râï~ë†={³0öo³~ï>“ç»÷ýÙ±'ý­ÐO”™ž!y%Æ…ë~âFÕp „oíŽüàw×®Y³¡×¸Vâí6nÁ PŠ8ŽQJGŠ8ŠQ‘B)…RÖüž×¿þu¿ìvZk÷>©k?ÝA•Íï[—*ç•Ó—äyö®æõšwÿ÷Ç®-ðàwÐkgÐ>ƨ}œA÷ƒÖ Úû­Ï€ òõøÇ_qYVÜ(nð­—Ý8féû,uè9ZÜRÜC®5Fëç+¿t[2iíí÷å´ V ªUÊu'ý˵iÊi“JcšUm䢷œÅ=Ÿ¿ûn¾íH©Rûãa¯óC“e»ÉZK¶ð9„Í'çïX¡§ŽF÷}`ñ./Ɉ Žé«L˜¿ Lã@@ÕÛ°íw×­Y»¡×ëMæ t; z„’Ä‘B©˜8V¨(fÐïqçw}ïýïû?ÿWžü(°ëTUÿ@§×FÐZŸù¨2ì÷ª•ÆôMG;tÉ?~⻫_ù¿þí£ëدw†Ùð<$AçÀ# C·\5ÉpqœÞB…n½ qEÀ‚R )qùmÇüa­„Â`P>‰Bk”­õ˜ù1D~ùÆŽc ÀÍ{[¨úÛɵ†Ôg«ö’gÞöw"Ò*åú åZrµA9¢Ô˜¦¹ñ,ÎÃYìýÁ^îùÒ-ÔWŸýáa§½Ë½ÏbƒÈ&Ú¥¿÷ÓýÁVè'MÁXøçeÝ—½äÊ?úìß|îºW½ê•W 9ù€ú½™˜ûæ¾úÕ/þsŸý4ÎÇpZÌ?Œv~ /o~ï=ì'ƒ®Jk«ÏþÐ÷>{óZõ¼ ØôÚ Ú«9ú°·À·!@Ætöïv28ý¬ñ’ßxF°Hýo;N“”R’ÄÉX%’RúuD-å(0¿µ“rãâ¯Q¡µf4¡ƒF`Â/éÆç#ózÃçÓÈsU­Sª5œ­_k§ âtŠtfšó^³î!ßýËÓX»þ#Y¿·Ëä£=Öê#;qü‰+V`àOÅôàÅýà›Ãã4‚°ïüåsãß|îoxÅ+^u5…9ƒÝ~AoÀö]»zŸù̧>÷à}÷}ç\SP.d~ë·Ã• !ˆ¢ˆXEDIìí!g+(2ÿ™A0c CkÖš|4b”çcm¡p‚ɶñµíŒC‹¨Z'©5)§)¥´A9m§Mj3S<ÿ/¤\…¯þÁGÑ]ñ›g_ z÷ëlô°Õúˆ;÷M„èÃøW[€g-còa/$PJ~]ÃùêLÌ‚ñ¨ç|àÿò—ù¿ØŽèûîÁ»y„Û¾sÛcŸú«ÿþWÀ=¸ã£À£§Ëüp ô¢ß[•Jç'Õt“Pê-ƒîÁ_z÷Çþ€r3æÎ¿ïÑ=z‚AwެÓbÐcØk1êui9€îÌ;S@z½'ØÝûÛ qL&•"Šc’("J¢(3ÿB-@>iÒ^gšLgäžñä£ÑØ,ð'™l‡ø¿± qmФ’RJk”ÓqµN)mR©×yÁ/<Ê|íýfÐåŽ8ŠÿjÔi߯GýGŒÖ¬ÅU‰œÄç±BÏ,ýðOŸè…Ó¶¿T KÓþ½@«?pà ¯;gý† ûìç¶ïÜöàÍ_ûÊM¸þ<óæÇáá3›ß«uQR>/©Ö6‰H½17½·ÿÚ'þh¸ëïûtŽÍ1ìÌ1è¶Èºm†ý.YwžNë£ã‡3ëó¡à?þ噿”$ ˜?I’±Pdþ"?LœxËIÿ¢äÏ´&÷Œï c4b‹ ª¯¼ô¥2åº+éMªuÊ•*¥j“$­‘Î4Ùxõy4×ÃWï# {rk’”>9ì´wæƒÞ#VZc¶Ø(/ùWàK§Á)ƒAÑ:m ÊÂüœðÃ÷p¹-àžùa¡ƒúÉÒiûŠd1¹È9š3T%i*#•Šÿçßÿ×·ýòŸþ&/{g…»þ>áÄc.ܧT‚P BÅ4JeåÃ{!2®“7oQDÇDqâ×1Q5"ˆ¤gö)ŸF\d~m5 r“/`~­5‰Ò#)Ý8'1DX÷¹,as=ùi¼C3Në”juâJ¸’’Tk”*5’jƒt¶Æó~#¥|å÷>Êhm-UÒOŽºsè|ø¨5ùAkí`bð™ÿLüJ+ô4R(*V šE¯Ã1¡"Î0™MpØbi®ÁiÑ!ÀbúVëCy6ô„HÒ‘ nüÍ?xÛ¯|ä}\~MÌÝ_Y͉=1#!#…Lò~‚ŒJ$åc‡µŽûä 1)½E$qì ŠIâˆ8.¡b5ÖÂI‰”Ñ3`L¬ž¨ÿ‘‘Îö_yîŽÂôÞPØd #c\4I•¤V§T©Wª”*)Q¥N’ÖIªuª3U^ðÆõÄ)|ù÷>Æh¨¶–*µOŽ:ód£á£&ÏZk<óOÐ|Åé÷œ¢IûÂí"´qš‚À9sà0Nòã 1?œ!€q*mßäÎÅ@Ð$"•åÆZû™ßù³·¿ó†÷ñ’k#øî {¨*AFmFQŒŒb²(&ø'Ð× IDATŠË Ó´Àô}2“tö}XÆÇ$‰‚(‰@¬&þ-0öü;ˆÑZ£t6)&ãœ]“kaÉ0”êuÊ•:ª\%©V]K¯J¨â¤óœÏÓ,Y¾ò‡ÿ™aŸ­¥¤üÉQwþl0xÔäÙkLó¯¨ûÏUZX¾êJ†g³ DÂ@’#8-àÇ·Ù t†€ÁtM®i1°#!l,Ò¼Ò\ß¹ñ·ÿøÝoýß…Kþ"šë›<ôݘÞ\ŒŒKÄqÂ(JÅeT)!.Wv[ôŽ3rÿ("‰b"å¤}) š@D¤b¢Ø™  <È Xk±Æb#‹ÑEÛ_¢tN–ç+Æ®7ŠÐõõ3Æ ¤ T­#â«b’RŠªTIÊ)I%%*§ÄiʺËÖ±ñ¥søÒŸÜ@)þ‡8޾<èu4#ÇüÆè¾Xø)'^ƒç-Vû‡LºgLz °èãj Lfœ1:ƒ @X,¦«µ>dFk…Љ£Ù³Î;úÿíþö#?Ü,ÿÅÿö‹\ö¶*ÜVfnoBG¨$A ºè~‰Q\&*U¨Ö§ùˆ¬ßBZã€ Ž‰=óÇ‘ó $qLœDDÑ"_@ìLI$À™UN‚O’€²,¨þ ­#¤9¾aˆ¯9ˆTL¹ÖÀF1!ÆHéf$–S’JÕÙýÍ*çÿìZfÏ…»¿v·áK¤5_°Ö|sØo=d†Ù#Fg‡¬Ñý꽈3úó®Ð3˜ƒ» …žƒ¡ÞÔ9þIV¤ÿ³‚†÷üÉIß»oÇnýî7ùÚ×ná[·Ü²\ƒÏ)œ~!oÀ¬Y½ÆDq¬÷ïß´S ^ÿÚ×ó–7¿…W¿úÕ\pá§}ígÆ ˆ+˼cÇ 1úP–v@× [q¥ú±aŸŸû«ßý³w^}íø¹w¿œ5¦ìü§”ÇD¥ Ñ  Ùis$Êh$% J€4a-Vk”JIì}Î/ ¥$'Mn5Hk­‹ýG£,Gç)GèHaJ!%ÚZ·0B¸™Q6ò€aD‚‰â™ ç_=Cs<²í ßüŸ¢T™ú^­>ûåQ¯ûp>ì?¦³Ñ~kôQlÁæÂ+N‹x…ùŸ ôÂÍ›©NUXU_ÅêÆjnþÆ×™;~¸xHÑð'vjfÆ>rxYéË%Ê À‡Î˜ 0±+œ`ÍÈŽäùphûº«u>—*s³«7Þ³õ–-¿qï?ß}Á[ã\þ–Ç÷5ÙuGî¾6Rv„Ô’…ñ‹EI‹%%±r<¥q¯¥DJ!åÄEËkë›)ZÊÆ¸¦ŠÒ¢3‹Æ A[‹1mA#œô· ##‘Åg]9ê ¡{þî?Å‘Gt³¹þ?gÙè¾a¯ó˜ öë|tÈ=µ£q'ÂÅöþâºBÏ :oýTßP¢V¯0=Óà¶ï~‹;v.>¬vîøñ“žïì³Ö±þœ³Y=;Kš¦?Öµ |é{ÇÉ;Ú+41ž¶k¤ÄbJ$BÊ)Å«’¤tNTªnIråüüÁ߸àE/àçýí¤«àààȃ0:Ô¥DŽD£l޲Ú3¿u3=DDB¢"I,*’¨q6 ó8¥wêI‰ÀºVÊE3À´6äaÛX÷á¶XÚF ´¢ˆæ j¬:×Õýàæ­ÜyË7h4Ö~U©ä›Ù°·G†ût>ú öCi3S‘Ôë¬#áÀ@B¢$‘¥0( ±ôe>Ëp¿¬Ÿ. ]aâÈçõhíÖ¹^f8ÜÉ9®-£F‰ÕBe ZᎯÞÂCwï¤Tªü $K·š,ÿQž öä£á!kõcÜ/R…µÿbí^Œ“ŠÄXä\¡g­À‹Þ祻ð½&`¸o,í‡dD¤ÊRFM%3QR^£ÊÕµq¹zöˆìµýQëµI"Ó—¼ñ5lþ™Í4VC·ÇBv’žaUI2›ÂtÕ1~,]71¥ ‰óÇr©`¬kê“{¦Ï tp°:†V"•Óç@ZƒávÝù0Û¾ùZGN$é÷+Qú%çÙà ­Y“ÇÒ±X‹¨ÐP{ÿ޶^å÷‚X¨¬À³ŽVàEïkÆAQ0cÀknÁ:ž!dEFISÆñ´,•W«rym””Ï’qr^g0ÿóY¿½ijí4/¸òÅ<ÿбæ¼m ×†öq蜀Z%iî°fý4ÔË®µ€ µE8æßyÐ]OWAgݨ@u êSNƒh†]ÛïgÏ»Ø{ï(W§ªþwBsŸÎ†‡Î˜|tÌØ|Îæù¼5¦m1¹VXWÜh|¯ˆ‚ ˘+ð¬£X,këÝÝÂbÑ®Ö_(¥3 T„ªB7dOɤ´JÆÉŒŒâUQœLkìóGfpE6ê_D­Z¿–ó.º³Ÿw!³k¦h¬™ØõÆB–AïøÂì ”ªP®ÂØO)`ЃÃ{O°÷ö?¼›Ã÷az#dTº7É]±‰îÎGÃã:7ùè˜Éóc`æ…ÑkMÏ£Ã7)a½CWz `ìÈ—:WàÙM+p*„´:†oZñ€5¡"×m'RØ8®ˆ(J‘q](Ñ*nJ7d5d5T×3²Kr›=?×£sÑÙ:ú#ÊçEY–(×*¬½ðl-R‰€²àè¾ãtž@¤’¹»wC½*j!ãGb™l›Ñ°¥ó|ÞdY›<›7:o¡ó6¹é"èƒK ¶n°—s`}|o9@M€xÖÓ³Îp*ðÉI6lP>ç^x¡O#D€Ñ}kècí¼µ¢lŒ.“ª"S¡TMD*•*Þ¡”J#Y/#(Ùº,s\¤=9:¿=?8çØ‘v¢T¤d”ÐZ[£MnFy†¶Ç“ãÉŽÒôú.ÒöŒ¬5“åÝžžë“wE–wl®û˜¼G®û;Àh?öWMBž‹ûv-Ið_¡zæÑO &$BÖ¡v`Œµ‡I$ÌfX“¡m)¥5&¶V—0²¬å(Aʲo-œ`eDUÄj‡H¢Š•¦d„‰0Ò¥'Y‹5X››ŒÜŒÌ(ïõ³aLiû 2„ÉÐf€1#ŒXm†“¹æa¸I¸vŸìTàÿPeý®0ÿ =ƒéi€…,aKÏP‹ðéÅ…t9Áê!ÖѦ…•«Vº–K–!J–¨lE–T„–ŠHNN¤­%7Ú b3#´`Íis9 qö¼õÃÙ'ÞC Ø©HŒof1£/ž:¼B+ô̤§€EÌî‚Åùñ^ÊN€ HÛ‰z"“cìÐÕS°¹À¨k\ÕN^(T°¸Z`cóIQ€÷I[’1aô‰¶2íþ—‘ð+œ¿BÏ"úÿ³H¾q'\ £IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/viewmag-.png000077500000000000000000001464501217176075400243260ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½x×yßû™sff»ØÅKü @€(ˆ)JeZ2eY´dE¦Ùe'ÍMûXiâ&·i¯]§í“ºíMÚ´÷ɽ½©“çö6inzíöé}jGŽLG¦¥Ú‰LYþAYM‰&E¸ÀbÅîÎÌýãÌìÎvñƒ¿$Gû>ÏyæÌ™3ûcfÞïû}ßóÎ9šëºÔ¥.uywŠx»@]êR—·OêP—º¼‹E»Àß9xh è‘R& )û¥a Km›&D”BhÍÇZÇ»hcÛ6ÅBÛuG\»xa¹PñËóG¼ÿ§.MÓÞÖï¿7^«ÇÖ/ $ô›–u Úа­!í1 ã@<#ј 1ÞH¬1F´ÁŠX˜–‰¡H]"=pÇv(Ø ËEòùer¹ÙÅ%²Ù2™ ™Ì™…² Y–s¹¹|~Ķí×£À‰çN¿—¡.!©ÀßP9xh iúX¬ñáX,v ÷·µ¶ÐÒ’"•j!Õ¼‰ds’d¢‰¦¦1„¸v¯*Ÿ/Éd˜Ë,N_%={•™™Y¦gf˜¾<Íôô4WÓi—–När¹ÀKÀá: ¼½R€¿ArðÐ@¿Röاš75÷wní¤³³“ŽŽvÚÛÛiom#­ûóÛÁÅÅqÀ ºÔ4ØXÌÌÌ299Åää$'&gââWffXÈfOضýuœØØ?®ËõJ~Æå࡞X,öt2™øT{{{Ïí½½tww³m[]][1M³êy…|ž\.G.—#¿¼Ìr>O~¹@¡PÀ¶ ÊÇ·\ÇœÒyšMC iHti ›:ÃÀŒDˆ˜–eaE-¤”U¿;žgllŒÑÑ1F.\`xx„‰K—Èd2#¶mþ¨C¸5R€ŸQxòžÞÔÜü©ööÖ}}}ômï¥wûv:;ÚWô- d3²Ù, ÙE–³ä–r,æ–Èç–É-çXÎç).( ØÅÛÆ±m\× MHM¢{`SÇŒD0-,‹hCÑh#±X±xœx,¶‚9ضÃððy††‡<7Äйs\¿ÄR6{Â?¢î&ÜT©ÀÏ<4ÐÓ”HsGßíÉ;w²cG==Ý+úΧÓÌÍÏ«ÀÜ\†…l†…l–l6ËÒÂ"‹¹ErKŠ,/çÈû À€bÑÆv\\§®âÐ4)¥*†AÄ00L3baY¢D£ 4Ä¢4ÆbÄb1âñ8ñ8M‰‰¦&¢±Jw¤P(pöì gÞ:Ë›§ßâÜÐWffÒ¶m‰:+¸)R€Ÿùù>ÕÓ”HüΖŽö§÷쾋]wÝÉî;wZåNŽÃìÕ«¤ÓiÒé´€¹ óós*2ŸÉÍ.ÍfY\\biq‘¹ùt~llüêÔôå…ËSS ùB!, þ³@Þ«ØÅš½z<‹5¶··ÇÛÛÚ»»»RÉdÒŒFcÄbÄã1bñ8Mñ8ñD‚D"I2™ ¹iÉd’x"QñÁSSÓüôôiN<ÅéÓg¸ti‚åBñKÀyþÈá£7ðò¾«¥ï`ùù>Õ“L&§««óéþ»ïaÏ=w±k玊>™ùyf®\aöêU®ÎÎ’žUžO3—ž#37ÏüB†Ù+3ù‘Ñ WOŸ>5™·íI`XÆÝó¶Õ T*°®U©k6'‰-;úúRwîÜÕ‘jI™MMMeH6“lNÒ¼iÍ›7“J¥°¬2°-.æ8yòo¼ñ:¯¿~’‹ãã,çóGT^¿Ôà( ô$“ÉßÙÖ½õé{÷ÞËÞþ~úú¶—ŽÛ¶ÍÌ´Z»23ÃÌÌ W¯Ì2{uÖ‚S púÌ›—Oœ|cðÞ 7P÷-}°©°’øF騀`Þ¶Å4ÌŽ÷ïßß³g÷îŽä¦$Éæf657³ySŠTKŠT*Eª¥…æææÒٶÉ'8~üÇO¼ÁøøE Šü«ºkpíR€w<4ŒÅbŸíêêúÌÞ½ýÉ}÷ÝË΀ÅÏçò\žºÌôôÓ—§¹2=Í•™ifff˜™™evv†ãÇFJ¡}E_F){Á+y*Á`½, ,þS¤£€Àôêþ6ÁmpÛþû¸í½ïÝw[ssŠTËfZR›iii¡¥µ…–¶6Z[[K_T(ؼvü8¯þø5N?ÁäåË8®û¯€?¬ 7.ux‡ÈÀ“¿p µ­å‹ýwßÝsÿý÷sß}ý¥cù\ŽÉÉI.O^fêò$—§®0=}Y1€éÞ:wvöØ+¯ ç(+}¥ð9ÊŠï„ʲ×7ïõ÷Û  ¾„ âmJÑý-TZ~éõxÇý¾A ðÁ`ûÇŸøØÝ;wîÜÜÒÖBKk+­­­´¶µÑÖÚN{`„c>“åÕ½Ê_y…Ÿž<ÅÜü|ø•ç>¼¡ ÿ.—:¼ÍrðÐ@2™L~qçw ìß?ì@ —v¡ÀÄ¥KL^ºÄä¥I&/OryrŠ©©ËL_žâåï¿<4>9y¸B™Ê/yÅWn ü6 ÂÖÿz€ÿ$­¿…R|IYÙ¥×Þà*hÝ{wÿƒïð¶®®®H{{­í*™©££ƒ–#ç?8ƽÂðùa …âQŒ¬÷¼›¥o£ <ù [:Ú¿øÀ{ïO¾ÿýïcûöÞÒ±ÉÉI&ÆÇ¹41ÁäÄ$—&'T&ÝèXþ›/¼ðfÁ±Ïs(å΋”•¾€Rø,e¥÷ÁÀñúQìÀßú1€e*Á€Ð6BùML¥°Jé£T}+A)½¯ø’²²GY þñhgGǽ¸gÛ¶îHÇ–vÚ;:ØÒÑAGg'Éd²t½^}õ5^þþxíǯ1{5F ¿´¡ò.”:¼ rðÐ@²)Ñø…;w>ý‡â¡ßa¨Ú|:ÍÅñqÆ/^,ÀÄ¥KŒ^¸ÿÆóÏ¿i;Î)”Â.¡†ì–PŠ›G)¼¾Âûmþ9¾‚‡K­8U¶AÑB[“²ÂG½z0 €˜w,F9€hÚ}7Á?ÖÐÕѹ÷ãOô÷Üv[dË–N::·Ð¹u+[»ºJÙŽSSÓ¼ôò÷yùåï1<|/«ðWê±ÚR€[,‡~þÉþööö/¾wß{úø;vôàØ6ÇÆS06ÎÄøEÆ'.ñÏ~õõ‚mŸB)ð"0O™Æg e¥_ôö}Å·CåF*¿/á!À`] @ ÄQ ¤ü±À±`[œ²ûPb =]Ý{Ÿzê÷öÞÞéì줫«‹­]´¶—Ý‚ïÿàß9ú?9~‚Å¥¥àÉúau©À-”'áéÛzz¾ððÃ%yä‰D€ôlš±± Œ^dÌññ1^{íµÉ“§O¸Š²ö (¥Ï¡èÿŠîÏ£”~Ê `XñƒàVÙzE¸˜Ý˜ñ„Û»c±XÝ ¨Â0[\`fú‹Ù9Ξþ‰ædçÀ¯~]G)·_|¥7¼ý&Ê  HPvü²é±G9pàÀí]]tuuѵU½ÿ`z9CÃ#¼ø£¼üò÷˜ž¾Ê%øÃÞ³¿éR€[$ŸøÄ/}a×]»>ûØ£òÐCûKíc£cŒ^altŒ FãÌ™Ó }ôè«Ày”bgPŠžÒ”)ý,Jù}_ÞWú ò‡?Ò1S»Ýýžàoúóî¦ÍQ/ß? Õ^úsBUï6ø¯ 8þÖ…“ÇOðÝo?£;ú…ôÉ àƒAØD%3hDAÏ’”ôÎÝöëŸþôã»wíNtuwѽmÛº{Hµ¤˜Ïdø«o¿È‹/åüÈŽë~éù#‡e•Ûô®“:ÜdQþ~âkûöÝwàç{Œ={vËå¸02ÂÈÈ£#¸pa„ÑÑ1ž{î/ßLg2?A)úÊg_@±€%¯ÝgÊŠ€”?êôí{ÂýåOÿ3÷žûî¡´ðcý¤€ÐòÝ(¬Æ |€ñ?÷" æ½ß”>|œ‚ ®ã„£ÁuàØw_ä¿üñ¿ÖÒ£/…sšQŠ^ zm>4z¿­ú¶oðéO}ê}Ûº{èîé¦ç¶Ûèê.¿ñâ‹/ñ­o›ŸžzÛ¶O¬Ç”Ôà&ÊÁCÉ––Ôw|ßþþÇþ=Ý]¤gg9?ÂÈÈyFFF9Ó§N-|ûè‹ßG%ð¤Q¾¼oñç½r~"ÏjʯÔèrþÖoüKçŸþ4è§Øt[>ïÜàç(+z˜YBßUíû—P u•¸ðìqŠ%@€cÃüwÿLûþsÿ·ßhöŠAy¤Àƒ2@ÙÀ–ßü¿?°gÏîDOO/=½=ÜÖÓ‹i©á«¯¾Æ ÿãÛ¼öÚq–óù¨àà»>.P€›$ ô···íÀô|äÃÓâÑÒɉI†Ï32|ž‘‘aF†G8úÝ££ƒÃÃ/£”eE鯠¨ÿ¬×ž£¶â‡(Üþð/ÿ¶ûëŸû¼;°—Fànà~”â7³RÙƒJþü°’‡ÛªÕ«m}»zø8‹N l» ÿæ·E;óƒ/i(EOQ  oßehö¶>Ä<üð‡>öÄ»{n»Ûz{éíí-½htêô¾ùü ûá1—rixWƒ@n‚<4Ðß±¥ý;=öhòÐG>Rš…glt”¡sç>ž‘áa†‡‡ùÿ¾üå'Ps‘2Å÷-è"•é»aÅ-)~Kïûó¿ÿ_ÝÛúºøX?¨TòjŠ_ µ¯fýÃÊ jûá¸DÉ•yö8Ë®]f¶­€àäñ×øßÿùßdÏè( h¡<\˜D)¿Žb¾Û z<»û·>÷¹GwîÜéݾÞÞ^R-- óo¼ÀËß™lvé]u¸ÁrðÐ@gç–ï<þØcÉCO|„¨•R“] 1<4ÌÙ3gò_ÿ摳”ýç+(ŸÄJůfýmÀÞ÷øo:Ÿÿßþƒ;°—àÓ(Å·X¿â¯Æ*n„õ¯6*vÿâ5§‚"]ø'¿vP›z!´£X€lõ¶ $,Êï#t|î3ŸýxÓöí·ÓÛ·öv•J<22ÊsG¾ÉK/½L6›}Wƒ@n ø–ÿÃÿ\ò‰'~Ë2q‡¡ÁA†Î 1tnsCC¼ú£Wg¿ÿʱ¿Bùû~€o¥ø~àÏW~»Â?øÄo9ÿøwÿOw`/û€ßúY©àµ˜C­z5Ë>¶Që Öž,Ó‡S°]pŠ*>`»`{õýO~I>þåFT°ÒO0òã&j4!îµë@ì×õWù½ï{_ëöíÛéë룣³€ÑÑ1¾þÜŽ~ç%—Þ½L 7Hèokmý·?üXò£{‚¨eá8ƒgÏrnpsƒC òòË/Ož8uòÔ+º À4ÊòORÎÔ[Uù÷=ö›Îçÿ?¸{¹øMà^V*{­íjôÿfYÿ` Å+Jñ¹#§°/0èú±okÛ Øð+Ò$Êú§( ÛQ ÷ÚK ðáÇÿ¹O<ùäží}}ôõõÑÙ¥‚±##£þús¼ôÝ—ÉåÞ1:Ü9xh ™JmúÉc=ÖóñÇÊÊÿÖ ƒçÎ288ÈsÏ}ãÜØÄø·P¥üÞ~ð%0õ/v¼ãþâ}î˜;°—€ÿx+-ýµ(~-ë_Mù¯Åú×j›®þõEÇ ºžÕ÷À ýzQÕÏ ñ¯þÞí1 “ò›†­(ðÝÿãñÇûèSjO__}w”Aà­Á!þ:?üÁXÎßu P€ë”ƒ‡’ñxãw}ô‘þ|¬í|ë-Ξ=ËàÙ³ ¾5È×Ï }f­<îÖ8ž&_™fÙuA ¼è¿æYÉ!”¢k^šf£²h^±5øâ_»¶]`â×>¬eQlÀŸê¬SiC1÷|ûÛ‡5Ÿxê©»¥”èRÒÚÞΞ=»ÉfÉd³¼yúL¿ãºßA¹UuyËÛøÄöö÷<öøct{I>£ÞPßйA†íŸ˜øÊêM¢þXøýü ·ÿàË£öç~±«ø¨qüÒ1ª+x­R Ö Õ€aµsª•0vûèc°g·J`Øê;74ÄsG¾qvlbü/QÊ?ŠÊíO£hŽJ(A¼ãþÂ_¼æÚŸûÅ®_¾‹Ë_MÁkQîZ Q Âí.Õ`­ì?¼u2KFJ:H¤T@ ýâ·é}#°/Õ¾4@7ÀÐËmºWþó·Üˆs¨àê"åQ–IT¼¡ä¿ù _{ökϾ~þÜ0燇Éf2<öè£|ð‘‡iÞ´ à郇ž¾†G£.·HÞ68xh ¿µ¥å >ø0=¨^ìIÏÎ2|þ<ÃCçæÕW_ýK”µ÷çèËPVü°òçÂÇ~õ Åùñc‰ïå?ÿ•ÿ^-ÈVM¡×Kÿ×cÙ«)õF¬ç*ðæ[6 Rá)¬Px!ªXÿÒ—¬~€ ’ f`H0|V?}Þ½DÆQŒ`ÆÛ€â³_?üü+¯ühÒ¿w©T3+¸>0}þôywF>X@aýª2ð‡ÿþKgßz+722ÂøØ;wîàÀ‡èÞÖÐ|ñ•ºÜd¹åðè‡>²µ³ó³?ôPižþ±Ñ1.ŒŽ2:2ÂèðÏ<ûìa”Õ?Šö>¨øªˆŽÂWœw~õñè§€¿¢’ò¯G¹k¹ë‡iý—€7Fà²?}&”ò `ø#š×d>;ze»\þ¤Æ)Ç–½k¼ðOû·¿422Â…‘QÒ³³<ô‡xÿþýÄã \Ã#S—›(·î½ïæMÍÉ/=¸ÿzèA@ùý£F¼WzÏó•gžù!pfmå/¿£øÕ;OÝǧ€ÿ•IJë^-›n#ô¿š’×RøõÃðÆ,ú/ò‡§ù ‚A jPÐgúÊc¥s«ÄŒÀöOޏ“¨à«Ï–PÁIäåâïýÞïáÂè(v¡€‚‡>ð ýý÷¨åÐU< î ¼ƒä–@ó¦MÿvÏž=]>¸)¶msat” ££Œ]¸À+?úñØ|6ó×(Úï+u««uoá«ßyËWþ/²1E_ËʯÖw=´#ÖrNŒC18Õ¿ @ 4@ U2M¯Îtß}ÐWº+F  PÚ PðîO•‚]Šcãã?þúן;qñÂÆÒë§K4i¨}]÷úå6Ã?æµ:Z´ýÁË(`^D ús,…ßþçÿìYÿÞ:¶”‚xop‰¶/Ô]w†Ü¸ÿ‡þi_ßöÝï}à½ÄbQÆÇƹè1€£Gþx ¥ü~`)˜ï@ÔIt>èþÝßþ*ÿú _Oíc/ðッ¨E÷W‹È×RÒ ²j«¶O¨¾–øýì4\ÑTlO×¼\{Q£ø}jí Ð5.ºÐT]jèR  ©Ú5 ]èª]uL“èºPýµ@»ðŽi*ÛW—Bm5ý¿ø=qèé?¹ä]#6å™Àuþ‹¿xöØøø8ãããìÜÑÇ{ïßç'õŸÝÀ5«ËM’›š¦míììü§ï¹ï>ööߨl¿‰ñ‹Œ3r~dùÔ™3Ï£‚~Yª¾Å×^ìØõ¨ý±¿õì<ÅSûèAEû“ԦߵÚjA8\o5«¾–…ƒ„_ÎÌÀ´—®_bûZ PN篨ûǃû2¼/º†¡ij_J„.Õ¾ÐRC©ŽiÞ1©«~Bzýuï\]õñK‰xâ“¿Nç®§&¼ÿ6ƒbm³þu|öë‡_•'@ïEª¯­q<¸_qÜw šæo…¢üš†&‚î€(» Òw¼¢¯²ýÿÇW XwLy×tšò‚*ý—ÿâ=<1~‰‰‹hooeß{­xÿÎ5=Xu¹arS ÙÜrWOïmŸÙ»w/;¼1ÿK—¸tq‚‰ñ Nœx}ÌÁyI½Zk1ûìí÷>dïÿà·ý’1‘ÀŸ¢&è„êJ_duK¿ZÔ~=Ö>¬ØµÜƒj«™UCgÒ/Z•‚ǸžˆïU;&ª×RHU4 )„jÓý})5u\ ¯îµ ¡úhÞùRªó¤¿¯«úÿù[Yˆúk*ÎPrg1·8ôò÷_>3qi²”pß}{Ù³gRJPï ôl䙪˕›š¦»îÜý»}·ßÎÞ{U*xn1Ç¥É &&'˜˜¸Ä‹/=‚ ü…^ã5‹˜ÝÅξÝÅ»ú´zôI'ÚSûøMà罯¨eñÔ~=côë V¨Í‚mÓ*Á§ªEA€ õ't¼k Àª2Va~ðPøÖ_ ½ ¢ &‰ŸýýïN£€×_i骽ÿðþèùɉKLNNL&ØÛßO›7Á(uð¶ÊMÃŒÞݹµóÉþ{îf»7ì799©Ê¥IŽ;vx…òTݞ厉Þ^ìê»ÇÞ³÷!÷‡?â¶´&´OÞÏ=Àï¾âZ†êªí‡•·Z{­Âm~}r†DÀWûÿÔh¯¨Öæ·×¬ „Д//BÊ××4åÛ Í‹ è^»,÷Ò‹·^Ñ%bÇ]÷±ÿÐ篨¯*ÅüÕ’gÿü™g^šœœdvF±€þþ{صûN?Pgo£ÜÐ4Íè¿÷ÞØÓ³»ïÞ¨U|.OM–@àµÇÿ’òë¥í1·ÚÝ}ööýÎ=÷=ìôlïAð÷_Tà å¯fÍ×cÕƒ.€_‚ûµâÕ@"Ì 2óð+óyV(pµ Ÿ¿¿Ï ¶Õ/@(E9PX¡‹rðPÊ@ÐPó†^ѼáßùŸÿír²ëÁyˆ(OËîγ‡ŸýáØèXnêr™Ü}ÏR›Sþý¬³€·InèéØÒñäžÝ»K+÷NMM15y™©ÉË?þ“Ÿ§¨Pþx³£ØÒu»ÓÝ{§³ó®}î{îsý øO(Š üùÓc­ý¯éߨŸ¿ÀJPtàõ`t¿Z¡(TÛ!E·UYáYy)=ðØ&ËÇ„·_Rzôòè >ûÏ¿”&Úbc´¦Q `Þ»V‹G¾yä•ËSS¤Ój–°={öpÇ}uð6Ë MÓŒ;vîùµÎÎÎÄî=»]A_ IDAT° ¦/_fêò—/OqìÕWžAùûËßj'ÚºìÎmwؽwìqvÞý^ÇŠ–‡ Žœâ4ð/YßpßF,ÿz}ýZ€°Zû‰¬j¯jý )uj±¨ÕúÔ å×Êm¾¥÷Ù‚¯ôþñ’ à×ÃŒ-½<õËÿäŠ0¢¢³¨x€ 8_y晎ç¦/_ ½µ…»ví"Þó§7þ´Õåzåf0€¶mÛº?µóÎìÚu'ÓÓÓLOM3=}™3gÎü•ëï)´ˆÙbÇ7wØ]Ûm·ípúvîuÛÚ›5]–N)ßäÏQ£«ÀF-ÿjþ~5뿚ïl?—…Åjµ8k€!+w¸oMÐÊJ¬]½\—F =Ö iåXBÐðAãàÇ#ßÙ½s)–êö3¼ë±ô;ùÊô•+,f¸s÷.¶voó¯Ûg6ú Õåú冀¦i"‘LýR{{[ÛÎw`™jQÉ陦¯L3}e†¿>úâaÊ?«Õ‰7w8-­ÝNWwŸÛ}ûn·»÷´•¢LYŽòoP“}lÄÇ_¯õ®T©¯¶½’Uyò«Z~XiéÀP `¥’Pn­Êñ T~Øzmºýµ2Xø‰AB/ƒƒ”•, P@üÝðû³+¦E“½s¨ä.p¿ü•g^Ÿžžffæ ;ú¶sçÎ;0  YŸ>ìÖËf-½½·²»»›w¨¼ïùtš™éif®\adäüOPŠaƒUÑ”H¶ØÉÔ»µ³ÇíèêsznÛéFcBY©Dߺh^j>¼Éµ[úõFûÙ`@ÎýÖòùÃe- ¨ÅÂûáÏ ƒ¡ `ÐÐ|WÀ´ù[é1´ @ º¶ßãÜwÿãs©ÖÎ<"±„×¶ W;öúÌ•+¥PéÎ}´lÞì??ŸZ÷“V—"7ú·uwïëë룫KÍef†Ù™«\¹r…ŸþôÍï¡’|la5۱ƔO¶:ÉÍnûÖ^§sÛv7ÕÖ¢ië£V¾Õš$ëÀo¡‚‚ë}Ég½þ~µ1ýZÔŸÀÖ¯ŸYg5…¿Ö` ¡~k@ð3jýŽjñ€ GDÀêYƒ Ä4‰(؈_þ­Œ‰ÑÞÝ7V)ðåÿþ•ÍLÏ0ã½)Ø××G϶ÿú¨o­Ü0Ð4-ašÑT*Eßv•õçØ6Wgg™™¹ÂÔÔôÌÙ¡³¯´…™´›œxS‹ojsZÛ·9í[zÜŽ­½D „Ð÷l'© •‘&„—¦yÙiùÚ —H9Ò¼Q…¯æ@u&°ž±~_T©°òZJ00X„W‚ý‚Ç‚Û`&a8«°ZÆ †º®ˆr¦ ¿Õ×_x×½”Qèeú™‚š®êº¦¾3oÖî¹ï‘LKËÖ|¬¹ÕÏ `dtdòÜù¡Ë³³Ê hmma{ßmþ¢õW…o¡ÜH°mÇÎ;ïïîê¢÷ö^®ÎÎ2;;ËììU†‡Ïÿ°…Ùä46m²ãÍNc²ÅI¦¶¸m[ºÝ¶öNɘ¦IÄ'ïç“Û“ü?%Ú°6%ªª!NÌ3 ü;6®øë @¥…'t,(9[M\º.¿µR‹ˆ*}‚íµb„ö×ã ° mý{¢éªÿrñ‘OüÆ‚iÅØÖÝ—1c-~0þàoÌ^½J¡P`ûm·“J•rênÀ-”𦠠¿··÷ÞžÞm´·ª4Ït:MúêUÒ³³üäŸ~Oq;Ö˜°c›œX<å4Æ[œæT‡“jép[Ú»\?# ¾ÿ#»ùLÉ <ˆ\„S‹¾ÀQüj a-ëïïŸ] ù‰ V)Õ@ Ú à×Wûž +@00¨­Þ±¿-a;«!Î]ýe’©ŽBssëÂÊÎWŸ=ü†ÿlôÞÞSrþºpëäF1€V!Íɦ=Ý=€¢ÿétšt:ÍôÌôÅÙ¹ùéX,áÄ“N,±É7¥ÜĦv7ÕÚAªm‹–hŠ ¡!?y?ïC-Oð÷ëãCþË)>Zy<“ç%à+\¿Å¯6œ–jŒ`v2¢ ]_OYë¼j®A5— š;®¯æ  ymÞu&P÷]¯àµß“°ÛË#{âé¬4,ÑÑÙ“M$SKBZd—sož:=˜¾:@K*EOÏ6"Þ¨u7à–É€ÛvïÞsok{ÛÔ4ÐÌÏÍy0ÇÈèØ¢Ñ¸Ókrbñ¤‹7;±ÆÍnSS Í›[Ù¼¹?ÒL™úJû»ºÙ† dý…æQa 1èð5Ô @µ{k)þZ–¿ ¸¨56ײäë-«±‚µ\‚`›¨ÑÏß»Ôb„X€wý 02- ¤ûm^0ЊZôöíYliëÊ7oj[2#–kšŽÿäøÙùù4Ž£†¶uu“hŠû×õcëyèêrýrÝ išÜÞ±¥}GWg']][˜ŸŸgn~ž¹¹y††GOÄbq»1žpbI7Ú˜t£ñ”›Ø´ÙMnj#jš@<ÔOð(J±üÈ~ø]›IǤ…(?´õ«Y¿Oõ¨~­È~-Ë_Ë÷·_*¨ÿ*µ€`5¨ÖŽÔÿ8¨úq´Ê‘„ ð)Ð^Ýq¹eÄZÐM‹–¶-KñDs.bZîÑï~÷ìÜü<óóótuuÒ²¹Õ¿¦êS†Ý¹  ¸«1vvv"¥úȹ¹ ™¹ étz&“]¼‹%ÜX¬É6&ÝX¢…XSŠds‹–ÜÜ‚7ž,;,>ä}f˜Ê÷v›ü^):íÑSM(Ú*ð¢Ø Gá¿ÇXŸ5_oà/(Z ¾œS“˜^SÔ=¥š[PËØH{Ø(ó)§‘ÖÜ«UV;?üYá¶jùµÊZ, دĨ¼ëJPñý>¡ ¡ÿYZ ¯H×Aæ Ƚû]FD´ln_ŽÅ› ÓÒßzk,“YÀ¶mÚÛÛ‰ÅJ/Xå>ÔåÉõ2€f ÞÜœìjkk¡½µ €l6Kv!ËB6ÃÔôìY+w£±¸k5ÄÝhC¦'OÐØ˜Ä?îŽóAVOçõÛ~}OŒàù£hµ}áIøKàuÖ~`½£Áýñð÷ù¿£–ÿ~½ý׊ ˆP›¨rž`eÁ?§ÔÏ‹©”‚ÁóÁØR,&œ à5„#…"B·Ð¶tÞ–kiëÌ5%›ófÄâõ“§Æ²Ù…Ò¤¡­í­$“%׿¾¢ð-ë€6 Ë²¢›7·`Yj'»°  “G‹ÑhÌF›ˆ5&°¢ ¢±¤‹7i–e ß×>@e°. A…ý¥Û|ÿ3l ƒÃ[Óð<ðSª+x-q)OÑåKp>§òÛ«SèHõ¯¥¬t‚mk}~Ø­ º%6P¾oÊ]!ëï» (P, {zwåã‰fwSs*oš XѨvibâââ‚z˜ZZØœÚTºà XåÕåÈõ@'°Ù²,6·”2¹X\Zbqi‘ÌÂÒx4¥!§¡¡«¡ +Ú¤@ žÔ¤¡œ®Vš€{XiíkKÂ?º]ÒMˆþS¥Ì¨)Äßdí!½ð~-À¸DHiª}ïµ”õIøøz\jç¬ $ä„úk¾¯ïÓÿ ï/Êçk²è dßÎ=ËR𢥵s)9 “±±±‹‹KK€ZV¼eóæ` °În²\3hššZÛ;»c±(©f¹\Ž¥ÅE—È,dÏY 1ײbD¢D¬˜fX1Íjˆi–-1ïïå^VWüjÃw–„ßì­ë¡Ï³ðÔ[zµ‚kþeo›ñ¬MZ~#ÊZŸ»žï­õæájçÖt|âï»]Þñà0lÅçÞ.t]• M´Ä¦Ív"Ù\ŒÅEÝ´´ËSSÓK‹‹¥‹¼)µ Ã0üÝ{Öq_êr¢_ǹQ ÞÕµmG<'¹Iùn¹Å¹\Ž\n‘|±0Ûű¬¦Ã4cše5 Ó45ÂÜÎúߨ n#>ƒ?[‚œ r]½ HÃ÷’ê¼ÛÖùµÐÔü÷®Ÿ>­%õG×#e ŸÜö[í{m¯s5HxŸa{…Põr²@yºb4p(Ø`Û°µ{û²½œ.6%› 89&'/_Éår¥LŠæd3–e±œÏƒZA¨.7Q®çnˆ˜f4žˆ“lj —÷ ÇÂâò°e۬¬†¸±âš‰jV´A3 /’¬¢Éw³¶â׃öø•˜¤5©oZå üõX_ò9ïm¿IûW+«}ÏFÃzÜ€à±R_¸W~^¡8•ÇJç¡ÜÛFldwÏμm$™ÜTˆ˜––ÎÌgr¹¹|€D2|3°îÜd¹hH45u%š$ ò¹<˹<¹\þjÄŠbYQL+ª™‘̈¥fƒfZQE")¥ÿö°Òÿ¯•ÁW-zßš‚¿Ý ¬#R>¯Ö ôó‚R ‚Fð2aªû*µ¢ûÕúÖú+FÄʾ~»?©Èôû¡Fl‘j±l¡é"¹©%oD,Í2-mzff<ŸSДh*­‰Z=¨.7Q® 4M3€F`³Ð4â±ѨBíåå%òùe …ÂÕ†hËŠj+¦™VTfT“¦%"¦%jÊ]=lA)îj©»k½Áç-Íð‹QÅôp¡ýŒÆû.jz²Ò_ ÕƒûNAÍo·â³ov ÿök9'¸¯­÷\ª{-° ©úÜÀ>ZyÑQ×E·UR-íÅd²ÙnŒÇ‹‘ˆ©-çrùå¼z58Þ£!ÚPºèõ‘€›+׈1 %uI,ÖX:P(Y.äÉ —,«A‹DcšiZZÄŒjF¤Aè†%¤.…¯Z)ÚXý-¾`½Ö¸½¿Ýœ„§áë5ëðª’l\1]Þÿñ%¨ü~=mM¾åR+°‘8ÁFú—â°"à·û ¶×æ/K´.Ž£b¶ ©–-ÅLú¢cYQò´tzn¦PÈß‹ÅhŒÅ¨Ë­‘ë @J+€Ø…Bb¡€ã’‹XQÍ2--‰jFÄR݈)‘ê!I즶¿¿šâ×T~Ɇo¦Õjµ+Ę…EN˜°ˆ³Rù4[-tñ¶(ÿFd=A¾p_QÃÀàñV(¿/Á  ]ÑTÚÞÖ±847·83ñ¤ÓktœeQ´‹ù¢79HCC”+ü–ÀÑ ü¥ºl@®"­í;¥”Á  Å‚M±`ä,ÓÒtÓÒLÓÒtÃÒ„n i˜"ôDiÔ¶þë}E7\ 'á[sj• ¶¿S·?ªÑ?¡!‹è~Ç@P|k_ ª± ‹V^œ°Z?72r¤ü¾®«JrSÜ1ŒˆhˆÅíÂò‚6777SPÏ –eaY„¦á¸²º\‹\+”^ÜÖ¥Ä2Õ ŽíP´‹Øv“†i‰˜š1…®›š¦G4Ã0„o<ÙAíèÿµ_ 6Ã÷fÕÐÝš²ÃQ5Çà¶Ð¡9®1^r#åzÝ€º á“…ãï[~C:¨h`XG-•ÔЈ+ CkŠ7sÙMJ©mŠ"-H+êrÓäZ áW¤†2Œ¶cã:6¶í K©™S¦% ÃÒ ÃèºÐ4¶«)ózÁ€*Ÿ`h†×Òjâªü1‹p5ª&°ìAY|· ¸ø™²þkÉj®BðzÔ âöƒÕ`.ÏqædÊž'ìÙSÓu]s²²å™ ž tSeÃà½hX–Õ  ‰ô2·\×ű]ÇE“R3͈fa˜! C" G—†‹PÏžg%šY=k+þZÙ|÷&¡i^¥¯)9ÈK2 5ãü € ‰a¯âTv­ÞÏ×Q.˜–¥5&“ŽiFÄìììå Ý—Þä¨ÞD¹`áÑá––¶n50ìC¼ƒ‹ƒë:†™X–0"¦Ð SèÒEM /q$ȧ7Q^‰w½Ôß—jûáºoÐz`-›våÐ_Uñ^I¼d”‡Çêr%žHºº”2bššc;ÂuÊšÉdÉf‰Å¢˜‘f$‚.…¥¢¼BJ ×Ö5WAh*¾ãPa9ÖJ쩵|¨Tôð9µú—^ž³Õ;+ò¢è×â»‡Ï î¯Å‚¾~EÝ)+z醸•ˆ¾‹~ú¯OýýùÇ …. C ˲Zü2™…0HS—›&€ýø˜†²Žþý€›ÉÌissóÄbQ"¦‰eZ Cjº!…«éÒEÕ:š¸¶Ï9)½|ÓøšjÏçj¾ðñà[°a®aWY+(÷ æµy§±_ª]¸øÿáþ>}¯ & ³ë…[$4tÏúKÐ¥b†!¥iF¤išÂ_|~~ž¥lœ¨ñSërdCðíþÊW˜%Ô-Ÿµh:¦££Ý{ŸÛBƒ„Ô$®´A—¸Ûó=]ÈÙ¢Šl¯Eù«I5K¦úÁ¶ðqß O¿WSô[«Yÿë¥ÿaÿ¿&Kðºâ*Ü¥J_€éI©ÞÏÖ=@/˜†!EĈ4™Þœé¹4‹¹zJÆ­’ ÀKG¿í+UÑÛæ];›ÍèWÓŠ©YV+já⤤®K©+åG€šnà89ïaqàüWš»®9Êëö£Ê± Ò·ëÌý¿Ù °å¯6vïV點 ]êòý+0À»R~½´ïªÌB)¿” ëªHÛ4 CX–YšR*}5M~¹<›ÛóG]ÇO®Ë5ʆ`dbÜW"å ÉÌ]LÆ=³3jö-Ó2‰64`™¦©KMJ)\¡ Wh[ éGJו4Ëtmè7¯¥ðá}ïÛ€J­š`ä‘“ŠTçÕ”üfÀÍLƒY°øÔß-Óú`Žf‰1øÇ‡!à8Êÿ7 ¥ø>º†cJ)…iY Ûq¸2;[J,£îÿßtY7hš¤ÔE¯0—™¿ÒRXÜ6=3SòÉ¢Q¢¤g¦;Û·6_Ô¤ã¢á‚!Ñ4­ü€LÍ®™tS-‚Ï*û~=<ÕÝjV¿¶úY2`¸• °Å¿ë¿ú_Õÿ ñ•úù@àûþzàúñ/è+¾axE¢ëBèRʦƨšpæÊ 3Ó3Á$ ºÿ“åZ†ýyû‹€;=uyb[W÷½Ó—§¤?Ћ‹ÅÈ.eSRgRÓ„‹é E ]¨•büņ©æWµï÷·á€ðq»šÒ•ßD±ÆuY°FŸµäZ”#²^úŽî;ž¢»>Í÷ØëûÿÅÀ4@7ÔÖÞl2` Ë–aÑoàËÓÓÌÌÎNn²\K"(öÔäø„ã¾Çžžæâå)vôö¨©ã1Òós))5]è $šk£é6Žià.{0â80™%Ý«€ ‚Ýyð£ü~ßõ(y…¥mýï°]O‡×“dPM‚ º0؈BWë»Që_-àG¸-Lÿƒç¨ƒ.AÿßÛ¨€ˆ¯ü¥eÿÐÁ5 )›cLMN‘NÏV= è&ËFÀ¿ý6e7à +3i®\šTÓ‹cò­R-íj®T4P3u?‹P}àä,ÙÎòTðÕ¢ún¨Nè¡ÊvUKÏJðÝ\=$»þ¯Gn¤¿^å¯%Õ¬50ûöu7p±¼ôó|FPÁuýL#å'ÎtÇ4#‘F’ˆÉÉÉŠ¤2êÓßtY7¸®ë¦š69³óiŸþ/£XÀ\6—_Èe3Í'&0 ƒxSÃ0cv1×`XÎ’ÔÁuÐ 'ÁÕ²åedœÌ}*XËǯEóÃJÜÂêÊ¿‚xÓÞUŒTc7+ðWK6¢ü×býýc%e÷)¿÷>ýZzß¿wuŸ5›žâ›˜ˆ”/\Ô0 aH# Í.rqbÂ_€ç®»7Y6Ä6µ´à@•lÎÌäôpsClÓ¥ñq-—Ïc™&ñxœD¢‰Ù+Sm]‰¶‹H]S`¸ryp‹° ÖÛž•§_MñÃ.@°-¬ða%Öƒ.†ÏX5@+øÛµ¬z-_¾–òWSú5ƒþÖ‚|íUêA°ˆ`šê-«ˆ^òÿYÌåcŽãlJ4«[>vqœKžñäh¿Y—(Òðl€üØäØùîžm÷Ž]œccéÛÞKS"ISS‚ËÓÓ½’IG€+†‹1qMr¹²µ™bnwkieVÙúõ U‡êÊÞ÷¿¯ô`PôV*x-€›ëUþ°ß¿Zÿµ¬)zïut‚u'`é½ö ¿ßUÓøûHêØ*í׊(å7#þ¿æÚ…Š{‹ÊŽ]czº"øR¿T—(rÔH`) ï•BfvfÄÅq.ÏLÉÑ £ômï%‘LH61>1¾Y GJÍ­ƒf8– é=D6œc~wkIÇVóíÃõåwTÎIÉ¢S©ü+¬¾o_¸!Àõ€€ßn ¬æË×RþjmaêîSËú#üþ <æ¾ à[ü¢Rüb€þRY3  ðD_^^ŽºQZ_bô™…Š0®r)êrƒäZ‚€6Jñ—ÛéBnqa)MŽŒ\(éH2™Ä2­†«3SÍ-[š®"ÐlpLÇŠ(z˜Ë«&Áž‡\£šp¤øqC4O±Ý*VÞ®ÒV«80ðö% ¿´Àê@àËXKñ×Cýì½BùWµþ|~ß껬ý÷Ö´À2U1Í2ýŠÅbc4¦Æ'&9?2B¡Pž­½žxkdCຮ£iš?P@Í£g…±‹ão˜·7>t~xDŸ ³³ƒdrÉæ$Ƕ¶wnÏ Ð"à<`™ Wiîð8s{:ió¿ÏY©gÕô.ì ÛÖ,n î-tã'*V€€ÿ¡¥kQãÇe=ʽšT£õÕ~Áöj.A-ê>¾Âú»•þ|Ð °ÝÀ6è÷{!XD#žìo*r IDAT©¸~±b±˜ÜœRË0Žœa|üRð'^åçÖåʆX«¦iÚÎ;¡ì,£@ ?<:vûâø8çΠ9Õ̦æf² ™6)m]—ŽnHôˆµ 5… í 92AÖVÑxÍV–X¸j«¹ªM¸•E m×Sd`+é ­œP;ãá>7¢Ôú\'Ô'ÜþÝN•~nhë€ÄA:.Òu‘n îTiwœ@)ê.Ò±‘nQõ˜êþZ&2j"£2ð;'æºnJx9Á熇¹:[±sÝÿ¿E²QàÞy×] @¥ü`ÙÎeÏæÛž½šÖÏ Ó~øAšS),˲f§/'[ÚãóHl+‚kY5a.«–Lgp'æYlM\ºÂ‡,™,èû»¢ÒÊ+,0ú<^ú°6 Ôo£RÍÚûR‹ò…-¿ª×¤þ”é{0’OЪ{´¾´Á@[ÿì¢jógˆo0!j)`Yô_ær¹ÆXCCÀøøCƒCÃÔÀ-“ gž9uÊ~|XF¹ —'ÆNvuõí”ÃÃ#ôööJ¥HmN1>6º¥}ëm‹ 5ËÄZÐ`©a@ÿ!¾ÈBj—š",”Ì/ÄJEÒ÷ / ®æQ|me|ꯕÝ^ÛÝ&‚€×]IA«)òFe5ů¦üÁ>á`_ðó*&ùøû%¥÷JÐ÷·½ ŸŠØŽêkHOùMhˆ(HCn)·©9Õ À[ƒƒŒŽV$üxþÈᑵ¯N]n„l¼8€K9˜ó¶ÅÁ7‡Ooíè¹oltœ3gߢ··‡x±·q\dÑUû¶4 d,p_£–šÌû?F>ŸßÔ”HgΜáÌ[ƒØvÅJ@_Úè3Y—k— €ëºîÖŽVoñÜRpócc£o8¶kžâÔéÓ´nÞLKk S““-†À0t KLjšèQ ½ÁB·LtÛF·ôó,gqma;ÛEضª»ŽR`»²HdÑSæ¢W÷Ѝ¦d6è¶÷`ÚÊ÷×]o‹WÇÛwªÔý>n o°8ë,áóª}n¸¯êç¯Öߥò¿•ê.ºã¨­ëo]t§X®ÛzÑQ[ÛVm®nû[Ý.ªºc£ã¨{m@5¨zƒ¬øoÑ………”?ûÏOOŸáâøxðñ:üü‘Ãõ9n¡\s=uêMŸIú.À*X:{úÇ`rzšS§Nyß"hikÃqÜøì•ɸ!Ñ ÝŠ Ç,õ°4FÑ¥P’c£ޱhÛh¶í)¿pm„ízm8x ]!ë/ƒ á”A@÷¢+e=@•J[ V+µÎ­¦øÕ*¼¿¦ò;ª¸å÷Ûl×»Eµu½â8j¿èomﻘ™m?=uFœºŒå½pg6@óDœDØÿVàñ!ù2ÀçQ^4̨xb;âè'}  ²›¨”(ZNƪIµìÀ3_ù½ÕXÀ™F}y<(ÍÐæóçʘÍÉ=¿Jìß cýžñƒµ`š¤“b‘£ù°B<Ï«O§¹í¿ï¥}8ØÚZ9ûïŸáq\–×Q.hrP!.8H`‚7~Í<Ô²eùò›îíhïľ½/áÚ%WCQ(ššf¢¥å•ÄÈÈH2›ÍZ€dÌ*v°¾ŒPàx/üL$‘àºDWxʵ•+½Tx”rzæ‹îÔ  ¡âGÌZ™üT‚jJYyŽ”³9§Jý£Û•Ž>¹¼®¢ü^ÔX¡ü¬B±=R}¯b p§_:dÒÆ„[‰yŽ“T'ºðÒÞý•yÿO]Îü{ó䂨6Þ¾ÑGè(ˆÅà÷÷vouœRÁ¶,ìÛÿ2vïÝ È5ä0sæLhn΂ƒ…š¤PÓ)¨©Ôtj*És˜ˆ5wtÃwNKA?åÚu x.T'¤¯ªëAqyÒŠ*©ªt\¹ Š+`>x>€q˜yUhÑד9èª9 §²TûŒÉέ<^y®tö¹"Žï±Ð©ê{a¬?pæùü»^…Óσêºa¬ß«r°Æ„W>t^ŒþŒ‡ yy < /äö‘Ð!÷ú!`ü$V2€ÉA¥œªVûÌÊѾr_ÝÕ(tŸtøEG~7RÌã‹ßé½#p#‹Çóü3I F,é$š8ŸR\Óù¤ÍZ°w÷^ŒŽ=Ïýo¿~æéÎóx\—å"ÉÅ0Ð?ØçBdMÀ8€¤XH÷ósÉ-ÉD"wàåýXpÕ|Ü}÷H¦Ó˜5kŽ;–œ=w¶À×V“ä?HÛ±Œø¾Þ!žI‚xT(=år/ŸOx®õƒ}ÜîWÀ§ýfWm70;@ÒiŠêŠ?U0˜ªLÅîŸÔûï‹ë¨PMù+ÛuUS~Wø”™ÑE!@:%”^(1ø¨išÉD"BÁÄ®]{ðj{{pÐóÜñÁ'.üÉ]– ‘‹„¢ëškÛÎ8xå§ Î2ò;·ïxúöÛo¤p;wî•WÎÅ’%‹1sÖ,ŒŽ‘Ý»v¥V®Ze`I ”’@I€Ç—¼ €]} s›@ ƒa¡í/Ya`Lì F~¡ør?!ÒW(Þ㇅@2¨€3ƒª›ŠTóøUŽWuŠáÿL£~4ìçUÚÿQå¯PøÀÞwÊíþš¤ýÓávyÁàû~"‘Hxaç‹Ø»woYÉïÈÈÈ·_Þ·k—åM•‹ɤBÁrÀ#%„, @õñB˜¢ŒøÜ àJïùágF *“Eª?›LeônOP|DFÿJå—Ê.}‚ ø,éå>ϼˆ²»N90&~) ›æŠŸIé‰7«PJU8rävìØ‰ÞÞ¾à`¡0Þ¾w÷Ž¿>‡GtY^'¹(0>^d"=X¦à ß¡ìkÞõwL¿kmAßµkæÌš…;ï¼étsfÏF{{»ÖØÔLMðŸãnd$³\À,Ý M9€H×½¨ó%TØöð…MJå>~œEü\ˆ„ŸA–1p³"š&,¥R*" Uål#ôu`ã‹Rñq¶Q_Œô,X@•°^0ò;áÚïI\á³)>ògÓ¬+„ض­éºŽ‚iáùvàÐÁCeŽ¿ÖÖCÂ+žáÑ\–7H. A^CX( n÷¾|àÀ3×/»éž¾²mûv̘шë¯_ŠÆ¦& ìÞµ[[¹j%8¥¬Ióž¡Xžÿ  Ó²‚Î+B9 4ìîÉX8ªKŦŒƒG Ù‚Š$#wRÉ ‚0ÑQx>R• D•^¼fÑíˆâ‘L?N7òÚ+õ'S~'Â<‡×õgÅÈ_“kçQ÷}"ü~Øöü6ìܹ fÑ Ÿ8~üÇC½?¾€ÇtY.¢\4⃳t\ñcà `°ú{»·çÇ®º&›Í^y¸µnÝúMÃÜyóÐ×w f¤D4MÅ.Ã×ubR¹ÆòÀé‘r‡að–?b7´eƒºá"/¯‚ûBQ˜ô‹DYç{¼N†Ï[äLÙƒÿ&Wzé<“ÝäÿGL… @Q¦#@€yÜÛeZµb;SEù}߇œÞ{óæmxnÓfôööÇ=Ïß¾mÓ_84ÅÇqYÞ@y=@,„Š/×1ÛöÍ›žºãÎ{>çʾ}ûI*•F*‘ÀìÙ³0kölx®‹Í͸~Ù2@¼©NO/Ьˆe$Ï'-‰‘/™T%t©ð"#”›¾QDÝp$±ˆP¡T4"áB`" !K8·gn}É*”~¹’Gûúû"þ ?bBTzü™ð‘x‚­'Ex/+×5œöO:ò åßµ{/~ýëgñZGgÙñ­›7}À3Œ±ñ‰ï¾,o¶¼. „³€D¿=pÐfض¿¸sÇWß²æ7-ÛV^عFÜÀûßw0wÞÞžˆD!Ü1¨døèO) RNãµqît\À/šË'¦”,@š Š*”Gáet„F€@2ÁŒ¤Ê ˆ·õSqQËkúeK¯‰Ý¼&ÊîÝûð«g~…ý/7—ÑþÇÿ"–-[† M|>­›žÅ¶Í[›»»ß^ 𶀋!¸’§À ’ èâxÍÊÕk?S›ÉÎIÄãX³zî¸ã\s  ôôô`AxbÞæµRñóÞS PÌR˜ÔS *á>‚¨âGÁ’ !Õ¯4*Y@ð¨AåEWóúËuQúä(Ï*F|±ÖѬ36îLG€ £MÍdÙºužùÏgqðÐá2‡ß·¿ùXº”›eC#@ ™L ‘˜?üñO²‰DüO“ÉäÜT"1bÄï5äro¹ÉAÞÊ0%'`oovíÜ…ç6mÂóÛ¶£åPË9©È %âÝg™3€ƒ0²{ç¶¿]¹zígj³™Ùf±HŸß¾ùBùüF¬ZµÉdóçÍGG{§#‘ ƒU€:ˆÕF³1L·xÞ€c‹\ƒ€ÌœŒDí~é$ŠËŒDVÕµ«ŠP€ ËO ðòù:¢ü²à':êÃçl& gêIŠY{Ò‚ö§©ú¦eáÙg7cÓ¦Mhµ£,Ô÷¹Ï=(?äê³Ñ»ÂÐÐ Oõ^·ñvXÖ×Û»eΜÙsëj³ÙÁ!ŒæóðÁÞßß?ð”ªjÕÕeß6 áR–7Œe,@ÿíI& Ù@J¬càzœ^µzÝ£ÙlÍDQ,Z¸ß½ïÞ°ºÎ‹Ñû{{aY6daT¤o P ÀÆM h 6`qFày"¯@)wVe(ß–t?°÷I…Ο‚ÍIœQ…—Ç+§÷Švûø=$t®ìqH!£rŠŽÊžž^<»i3žßúÑw#¥óÄ XÅ’©äHLÓÖ74äš§x¹oš¼càbŠ J›_‚€t &ú4Êü…K¼êª«‰°¦k²)¬¸qÖ­[‹—/ >··§”R446Vý^ @!Rù%°lnØ¢(´ ™"‰EÀûÿ\²ƒ,Âí÷å~©ð˜h÷KÆbh¼Ñù:® ¡ð AýÚÙãúRlÛÆ–-Û±õùm8ÜÚVæéÇq^þÎwþj‘aAžÐÙA`š¦aõªgýþ‘±<ºººN§a±Gžšâ¥¿)òŽ€ŽŽNìØ± ?ú¿ÿŽŸ?ýóóûb´Ýˆ‚@Ô9˜@hèôL¶îÖ[VÞö!ƒÔDÓt,\8·Ýv+ÖÞv²Y>÷œešĬÙM)ø\„’X¥X¥p]²°0K°Œ (6 ¿èL@à#tFR€'`t_äû5Ð5žáø7Ä:!€ `ç øÐÞÞíÛwà…»pª§§²‡?öïéçý½ÝÿþàC¯ù“?}âÑcgÇñÐԘÎ]»ðÒ¾ý°, éT?ø Òé‰ÉÆŽçáÐÁV¤ÓiÄÆw›;‡ÛxCåK àÎH!@ˆ¬e!Ñüµ7~<KeåçärÓ°rÅMX³f –- éåðÐ0\ÇEƒÈ!¨&6Ó㣾‚(ØN¶Ã»{^9 ð{ák1€³ê?—ˆ¢Z~‰NÆPŸ‚K×x(OW=Æ·Ë@çJ7ƒNê€eÛØù‹ؾcZZZP0‹!:ù€ã™…MÏ>û€—!Ž<ôÐÇÖ|íOÿdJ °o3~õëÿóY¤”@UT¼çÎ;qýÒkª^WË¡V躆T"¹UÓµûr¹KÎ/ðŽ€ÎölÚ¼ŸüÔ'ÏûË2¢úð@ IDAT& ƒ@!ÈEvØÂÒW¼qZýBªP…ˆé:®Z0«W­ÂªU+ÑÔšý½½ˆ'“óÓUb~³I@É ',±#M3dÇ¡h>!¯âl‹*{ 2YI¦5«*_ÇT1òG”_×CÀÐΞ»_Mµ¶a׋»°{ï^tŸœ0êûc#Ã'vîÜþ?¼*ö¥ù>øÐ÷|íOŸx„DHO%ìÚ½[ŸŽãÀó\¸ÿ|~¿Š¢bÕÊ›qûÆ U¯¯½£“3†tºÓˆé÷]j~w$\L‰0 ¡9 —td;Êb 37ÞpÍò;ˆUÖ¥f³Y\ÝR¬Zy3n¾y èò}ôöö¢nÚ4Ȧ•“‰ÀòyU¡%•ßæ o{‘öcN¤ËN¤Ï^PŽùG‘0"A$ú@CÅW„òGkbߎ `h@Lç¨y¶ÔÝjÒÝÓ‹Ý{öbÏîÝ8rôUX–Uvœy®søÈáÍ':;~  ¼žƒˆ¿EÂòàCßR͘7w–è ø,»„RɆç9ð<ž>E¡Pó¯š=ô`Õkí<Ñ…ÑÑ1¤Óé‘„a<ÒØØpÉä ¼c ¨ õ“Óësº0D(A Ð/ ×2eXë€+׬»?›®™M¨0Å ÁŒ¦&,_¾ 7Þ¸7-¿ŠŽÃýýý¨­­…¦${à}Ìì(¹a }´Í–ì4âÊlú@h¨ø2©H&$)ЍjŒ²¥ÂPšêó‘ááìÝ·ûöíGKË!ŒŒ”³jæÃ/š;¶=ûôWó!dgIµ9q&€€ë8Ä«í¯Â,aY¬’…’íÀuø~u¨©É⋟û, c"Hçók5™4â‰ÄŸ556>qžà¢Ê;^‰D4p…—@e Dœƒàl`ý’åËî4 ªº¡i*f]1 Ëo¸7ܰ ×_]Œ CÓbHVqBM&ŽXäœQ)¹n$yg²x̃`ôeÊ á#½*•_Øóç3ÊGedd û›_ÆËû›ÑÒrÝgâš|ÿðÁÖçNœh@7€Qà €?o²•yÜxøá[þäkO|‚ù £c#°, ã…qœì:‰BÁ„iY°KlÛæ€ß‚€ E%ÐT ¿û;ŸÂÜÙ³ªÞÇ–Cˆé:ÒéäÏôXì‘\ý››/p.¢D|2m8r ˆ¾–½e¯™Ë–­~_cSý’ÐÏýWÌš…ë—^ƒë®»K—^šlËB>ŸG}.w^×ì‰ÅE¤"O€Ìéœø #áE…rí’ËùŽîÕ¤¿ZZðÊŸŸ¨øžãÚ®c<ܺµ¿§ûypEéO‹ípåwc>!D²-ax6+¶3¿ÿøã÷þö§?}wÂHÔX–Û.Á²,tŸìF_ÿ@¶m£T²á¸<×c>ˆH¨àÑ𦡶®ßxâkUïw`h]]]Èfk‘HoJÒÐ[^Ïž€,¢«#„8@01‡rÖ픯‰Á#èÔëïíßÒß»å¥ÜôÆ•×,Z|«nÄj@)|ßéÞAô÷ â@Ë465áª+çaÁUóqåü+1oî•0 †Q^*cš&bše ÎÃ7R†‡GðÚkxµ£Ç޽ŠÎÎN  MÈàãþßõ=°ŽŽWwµ·ý%¸²÷ƒ+þ¸x-Y@ ü¹ËB.ùw¿8 Ð@®` èÛž¥×èð™æûÁâ© (M8ŽÇqAˆ Je³®ü4´Üà8®XúðÙ/þ>þè+ˆ¦ Æ–«¯C®¾{÷í‡çeÿ >Ö666³Xf7(% ”‚ʯaŒ#¾ëRnÜ{ÏݸëÎ;ª>—ý͈'©I7Ç4}}}}Ýâ|+3€·òÇwFK4 øÂþô’€›¼ ï¨g(1R”Æ„*åQÆTÀ§€“ š×8ëŠú…‰­Qb¾¢*>¡ 7 (%ÐK&Ð0­M31gîl\1sÑ8½¹\.¨D|#$Ÿ/ `}½½8ÕÛ‡žS§Ð}ò$úúû1226!~/„1ø ìññ|ϱC­{ûGú#Tô!ðܧê{àlÒG$Z“p€ÔóÎûéÏòðŒ¦™³Š¦E8ذ, f‘GFÇòhmkCa¼€bQøJv@û)¥)ÀDù£Ë<׃¢*Xrõ<þ…G«^בcípÙšL§a÷Õ××½îIC—àuJÖª JŒê, ¨ 5C¡d@I £,E¨›"ÔKQJÓž[«%Ð2Žç5ð„S€·ú@ <“Т‹±TÃ,%Ó‰¡(„ª„€PUñ¡ª Dñ‹)Ȥ㨭«Aôi˜>½õ¹:ÔÕÕ£.›E6›A:]ƒT*‰T*y^à`š|tÌçóÅÈȆG†14tCƒCèÀðÈ0ò£y-«ª3˜ï3Ÿp³³ëÄþcÇZ_Ѓжσø&¸â˹ÇÁ3£= 0¿Î(„Ü0Àµà¾úþ~`Ùw¾ý×d39³hÁ²Š0Mî 0- ¶e¡¿oÇÚÛaš˜E EÓ„ï3hÏéRÄLC„ÊhÆ|¸7-fÍš‰'¾öÇU¯«§§CC¨ÍfG’‰ø#õõu¯kÒÐex„’µq@Ijš@­!Ĩ¡ªZKUµVQ:Æ”&gܽÁ…30gPbKAR.² W@Mx¾ «AnÉÍÑ:Úu ¥þ×B Ò^~”damÐ]×X2A‘͉´OÅ…ªøÐ4@UÐu]W‘HˆÇ $“)$“I¤ÓI¤ Äãq†X,UÕ ª ˆøAÃ÷á1žã¡ä8°m1:Ž›(9 &L³€¢É½åÑî;ÕÅ÷áƒyÌóºNöè:v¬­`ç;ÀGu©øÑ [M„J/§swxSQ| 0Tp0ÀlS¶€<ú{ÞúÕ¯ýñuMKM EËDÑ´S d[hïè@ϩƋ(M”J6U¦( Š"r6HÐNÝ,€1Žã Nã÷ÿ"fÍlšp}cù<^mï@]]-’ñäc¹\ýw§r_ç#—à"‰B~CñÁH´†½NÑŒiŠ«‡ž¨wóÎjÇ-®ò 46 Ón\…ÌÒ¥HÎÌ¡fÞ">í•Ësò‹'{áÉZž'âñÂg¥Æ´F˜4-ö÷b¼ýUŒw´cøÀ^8C‡¡¨u¨«QXà *u‰ª0¨ª\T•E¥PÂmYUá:›‡„?Ÿ10߇Ï|>²ùþ¤#zUñ(ð™ï{¥¢9:túôkÇŽk³¬ü„#¹¤ór’V3²]‹-öþÙ$Òã±@Àt„¹ýô£®~òßxØuÕ,Z°Š&Ì¢-|ŒŠ(š¼s¦iPe‚9 `žëÁó\xž‡ßùÔoc劫^çÞ}ûQW[‡L:ýT.Wÿº8/ÀŠJÞ£2°4R,¡zÓrªžhðJd…eï̆úë× {õ˜qÛ 1n(ôöaüD–ÏKcz h4l̺¢sfÖÁg ¾,».‹Œ`åÏïw4Ñr¸ =£>Nå}¼zZ…«…ÑØ„x6 ªý;¶`h F_Þ E±Y] e¹& Mµy¦žÎ¨¦1¨ƒª–ÁŠLÎà3ø¼:Ørœñ×û{Oö÷v·W`áèn+¶õå"G{+òç¨ü@àS¶¢N,Yp§ !®=þ÷ÿð÷ïýÀ}|·ãºªt ÍÐ)hMhiÁéá ”J64M€€8ù£ðÁ|Oëð„¢»ï¾ xß=U¯µù@ â‰jk2[u#v_6“¹¨ÎÁËpž¢‘ûƒ—Hê‰bLWt}ºj Öiëý.†oIÏ» 3ÖÞŒY﹎˜§ÆàvÁu3Üpe«oš‡khAŒ(Ϻ ‚VÑÛŒŽÖ»»ú^lÇžÖ~4Ÿ´qÚ˜š«BÕ¡ýûÑ»åÈ>…¢X—óFS h© É$b>tÝ¦Š¡2]¡„À' >£>S¨Bà^ã >¥ `„OOÂûú u|ÅW˜Ç|â+ …‘ñ×Ì’c÷v?Úß{ªðeN¾+îÈE¹b;\ŽþÑ×6°© Gç®üR">ÙÙY6x­C8dü§?ýÙ‡×mX«iJå/g###h9x##£( ¼ DAÓ(ŠE% D•“”§3Ïç,Àq<8¶yóçã+_~¼êµkï€ç:ÈÖÔ6'ñG2™ôEs^€óÜŸ¼’ƒ¢NWbÚŠj,(ŽåðaÏ~ë»0ÿ OËaüdÉá㸹ÑÇ»W_‰[–§…Mié•7ÏJ/åRHt-Ú} «@˜à³‰<ýCmö¼rßßz#Fj,\ §~ýt?ý ¶­iöËŒ Œøî°Ë0fÖÖÅk©êÛTs|PNÏÖ]¡(ºëQG •hÔ‡Gqzx°·d ¾Ã¼þ¡ž.ðyÜAçˆËæ@H%–ëèvTÙåvô†ŠXþ(4I+ÚÇA&Õ€‡ )€Ø‹»ö|vᢋ‹¦‰¨cP2Þþ>:ØŠ|~–eAÓTè1 ª¢AÕ4¨ !jЀ…c€ßóท†ï~çÛU¯¹óD ãÔÖeG ÃX_—Í^¸ ç 1ò€Ð ­§”6’˜6SKƯ0Ç>êaüšÙw½ó?ü˜N1ôÊ«X–)ཫf`㺆°žœä¢m—Yu'Ëp˨@µÛTB@á! a·9€l~¸ÍÂ÷~º»N*PÜ„xFEßægðÚþ Åò{ŠBažçA×c9  s€¨<D:™ïÃó¼2s@×cxì bö¬‰ÅDCCÃ8Ùs Óêk‘L¤Éf3O]„çp¡qAò–<@hš@©´éD×gj‰ø,§X|·U:öÞ¹ïý8æßÿ\_A±õ0nkrð‘û®CS#øô֢ƞÉÊ»Ho<Æ„Ò3¾ÜÒ™nM¶î"!‰tVÂ2Ý`Z1…Ÿcüß/â×­6ìÙˑȥqê?ãÿöwP žTŒ¡\ûôódž€BžÁÌ󎃌 T|©ô•ÙŽò¸ƒr]*é½\&XFç;âW}„ü—mðG¨ø„}tº¦ë¹£¯ûB2‘¬/šff1¶¶£è<~…BŠ¢@iÐT¼ZP« Ü‘êy<Ç…ã¹¼ä¸TÂÇ?þ1¬ZY½aóÔÕÕ!•NþY]6ûÄ>‡ yûË%:¹_h–@k ÔhR“Æl¢Æ–äOÿ||zFYùõï@­Ë wÏ!|ð¼>RFØhÃÌjL}Åø>9‘c’Ó†û¤T3‚m¶ó"r;ÒåWeº$:¥˜nïûðý=&b V@Ut~ÿa`Ï/¡ªêV`¨…¹ùA†±a†üC~œw.+ºøk©Ì2å¹rô—k;²?:ÚÑ®c¯Ã:bTvtŠ ÉÉ_TÚí·ß¾à?ü×Ïzž3‹LÁŠf1½ûö£¯¯¶]‚®iÐtz,MU ¨TE)Oö|Æ™@Ô(•lÜqûíxÿûî®zý-‡Z‘N§Iežª«Ëžw„à2œAtr Ó(ô&ªÅgk©Ô•v¡p¯eŸ\s×¾ŠéknÁéW1Ï| }|¦7ˆI,ÝH§IùåÈ/GyQ|ÙOgøQå8A¨ør{ÂiÕÌ'(ºöŠÀ÷ÿµ?Üo¢áÆÕÈŸ8‚cßýkøÖð)Õÿ©_ÊŸbl¼atap„ÁŒRó(Tc”ƒy]ùYgÌ⻘R1׃ìÏ@hÈŠÁ”<þ¾÷¿É?ï{Ÿ³¬ÆÍb`H&/`ÿËÍAÙrLסë1Ä4•û4aP àáTσ#ÌRɆm—0wî|ùñ/V½þ-‡J&Q›Ínú}ÉDâœ#—`ÑÉoÅ èt@Ÿ¥ÆâóIÌXjŽ ~:9£&±æ¿þ¿p]Ö¾=xìÃKpÃÒo¦!›n:Bù#]vÊm}b°®œd£Rä-NRdOå9‘þ|$r~0;èÞal@ã@ÐÛüÅßmCWòj$ÐñOÿƒ{6Áˆ'¿çÛù£¾7ÖÅpº×GÏèLÚ¯ù£Ê/m?òZŽðò®¤ƒá‚œz*‘òmÙÑ©rÒ¹V¨þç¾áóŸýü‡MË"¼:;MÁ†††±ï¥}…¢(0 £ÌЊ&òD{fÞpÔ‡çùðDÁQÉu`—J˜3g~ÿ‹_¨zíí𙇺lm³nÄÖ§“ÉsËPEtr‚+¿:W5â ¨¦¯Ïw|tÁýcñGîÇàÑA¬PúðÑߺ‰˜ñ]ÀwøL¾¾¡úBé‰l´)'Ï_懚q¾t ‘×0h¯€ˆ¦ª&ZyéÀ~ØŒŸ´ÆâeÝ·Gÿç_ÁÐjž&нÝ-åÛ;Ýåãx¿SE”+p”Dý•f‚”7l¤?›T0iDç{l aüøß~ú[6nXkš&)MHç dCCÃØ¹k,Ëâ ¦ÃÐu¨T‘,¤PÈbo ¾çÃó=t¹?À²m蚆oóɪ×ÏÄê§Õ$ c}2™˜r„à2THŒ<È u®O,d ·›Å®Üòä7Q»ô ½ð >¹a&V¯ª‡kóQßuÅ<}n¹“/:I¦˜‚ÿç—ö2Ñ?ªSðVĹÐÈ•ŸqS… ëW¡t:ÐÑaá¿þó.ŒÏ[VFë_|(zûÔ¤ö<+ŒycÇ=ïõp¸€0é'ªð•·l_*J_)P¶zÎõ A ?úçY³æ¶5Å‚ Ó,‰BÒ8qü$š_9×ó`:bºš"L¨)Ѝ"¤ÂÓéà ÌnÉAÉqaÛ,«„¯üá—«¦ ·¿ÓêëFâFb}:œ\€ˆÄÈq@A‰6GM%¹ùÂ'N¬Xõä—aLŸ ÿKøÒ'oB®–wÕumaó;¢Í¶ðö¡ðASMøÑgõ ÜÁ‡òÓ¦,Q€É‹L"Y #ªèÚ«6P²¿ÿÇí8 ,@¢.ƒWþü` v$2ußñÌÂQÏ-÷1Þãà¦ø&oKUɧ"Â:4!ôHÈ"lfœik;úØ´\ý,³X„9ÎÛ†™E3p 9z ­mm „À0 F zLGLñŒAM¦ +áŒL>D¢ÏqQr86g–e᳟ù4/š8³ôÐð0z{ûQ?­édò‘d2ñÔî÷b<¶ó–K8íW)ÍÑS©EöxáH:+6>õŠ#6æºñ‘{ç#<›S}·$k:'PÖM×Gè©—û'½jvÆ—QVÏå ;©ð,jȀIJµ·ÌPTa ÄD;oø÷§ÛðÓV†º%Wãðßü1N·´¦jš¾â™…#¾S<Îàž²Ø÷«ò¿%Òב"lÙ²u›+½+zí»wøE©>§qåN¾@é+žµ¼|ÙŽMvÓ¨p’ðc'ü-#Ÿ"ÀNC €Ñ°¹§L ’¦€ã-½7o:Šï¿T@à 7 íoþ£-¯Ž&kg~ÅÉñ] ÿòvÉ¢mÞeÑP8FçÎ;ë¥}û¾ä{,Q(š¼¨Y„Y”ùEìÚµý‚& ˆÅ4hš*²EˆP /“ ëJŽË™@É‚eÙx÷†u¸û®;«ÞCóärõȤkþ,N>q†{½hÏí|äM<§ Ó)Q¯Ô’éE¶Yü„’rWl|ê)NÛ¸%6‚ßX×ÈÞœRÄæV/#§Äޤ®H à0îÜDðß9Ê#°÷+>;ð5P±’Œ ²–‹*gõ‰ºlÝtO¿Ê¸j1ÿÍc¤¥}4™þ/?~ÄõJî©"ûAÕîoE©˜ëAGùd/22PôñÇ¿åë_ÿóO ˜fÓPDÑ´Ïcç‹»PÏÈÇa11º¡#¦Å éˆŒÁ(ðêAé,ÍJ-ˬYWà‹Ÿ«Þ`äPk25id3Ù§ÒédÕ\w4ÄÈm$PçjÉÄÕ ôFJØðÏÿsØÂ†¬…•7eá”Äì:%NÿR˜Îë w@õ#¾àÙVQ| Š3/*¬lu^RÍ'°É˜p "ô HG!ï(1>›ÏÑ¶ÓøÛ_w"·ìù›¿ÄøÁW÷ªñÄ?ºæøŸ•^ü>‹ýðíÊ¢‰Bip3 ƒp‚å/¿ýÍ ~ú³÷ŠÑ#AŸW ?žÇ–Í[†a nˆ =-¦óÄ!‘0$˲Ì\ч!p Ú6gE 3gÍÄý½ª÷À†Ò¨ËfŸÊdÒ@àåhó”xb1(î6 '?ôžïž«£öø|ôáëàX€kq§˜k‹‘ßcúrÄ'þD'ŸN·ËFgqN 8Ëßà\„“ #Ü(wTe$Ü8c@,Æ}/< ??8Žì¢EØÿŸ1Éňý/Ï23¸ë³ØË;z¾…¥bþGåNÁºÈ¶ €>÷ÌsßxËÍ·rŇYlÀ²P,šÄ®]»AE"8 Ät º¦CÑøü áý¸?‰ç„æ€ Û²aÙEX– E¡xòëOT½‡-‡N§1­®v«a÷éºä ¼cÀ e´Ùš‘X¬Äã·Œœ>òø÷·0g#þÊA<ô൰‹€mqÅ·íö3Ÿ+m”öJÆB/»7…Ë;# ¨&U>sÊOp b¤t €DÍ*Ô8¨g»^hǦþ$âõY¼ôùOBW“?bÌû¥gÛ‡§ƒƒûá[6P)3A˶îÑTa™1¨À¡W^y¼iΜÅ / h™(y®À@ÿöìÝ UÓ`†Ý07tQD$ÌM…BIðGñ™æ28w :¶˶`m˜–EU&mAÞÑÑ  ~Z]³¡ë C÷öº>»³É›qò Î ÎTµÄÂXMÍÒ±Áãߺá±Ó+6Þ‰±­ûðèïÞ»8§û¥Ÿ‰‘^|mTñÁÂý•Ê\ÆÂÏñy3vv† Ï›ôØ„ q) D „ƒÒTˆ|­À¿ÿèE¼Zs-X¡ûžø<Ò©9ÿÅ+Ú»|Ï>Ìà°ØÆÎå>/e©¨ P™$$…(€tûñãe3™YÅ‚ÉS† ¦È(b¼hⵎ×pðP+ñ8 †‘à~Ý€Ó…O€G¨BDs1€Atr<plØV EËBѲ (sÇrä IDAT >ý©ß.›aZJ{{|õõu͆a¬OÆÈ;>Ò@ilž–É,uÆò_¨½qÎ5·}ûkØ~ »w(œ"` Å·-îA0_žÌðã7!”´ÊåœÉÉWa1LØ7տͤ„³ù¤o‚F@ŠŠ(ô>-hÍþá>gÉzômú¿èúÉÏüxfÚWB±Ù÷죀×óv2€€ ÈŽÂ ”Ï1(sâ]K6 öý‘ã: É Å0:P0‹èèè@[Û$ ñ†#.ƒz º¦E¨"Ò†ÁÄn.\Ç…-™@Iô'EJ?þØ„yàX{;|˜V_ÛlÆúÔ9¦_lyà NJh³ÕTj‰b·[c§>u÷Ͼá#½xﵨoì"P²Ç •_†÷d|_®H$°(±PÜI0aœ+ŸëmWž}¿LT JŠÅ~‰0ÂÍ™.,AÀõÿï©m¨[³ŸüC”Ží šò”gZœW‹ì_ÏíJ/m©R<$ý•5qÚây g¼¸oï—=Ïå9…q‚ð w<܆î“ÝH$âˆ'ŒÀ9È™@ º®AÕT¨Š ZV@äÓæ€Í™@I0Ëä©Éá ¦xûqæûÜ0Œõ™TêM €IÊc&ƒ< ´žÆbWè©äܱÁcŸºõÛÿ¼0_s‘­Š PŠã€i–Ø¢ÐÇá?[̪+gÙu<Çcpƒ%<æVYyÌç‹í†Ÿ]&Û/ßW¹Tž,.+[Ü赺>\O.á5Û¢ŠÑÅMŽËý E°Ä3"¸gí5m;Šk¿ôu5ª[Bu­‰€ÖÇɃoÜŒ#o€0.ÑJÆ"x#ÓqðF¦rmpÛ:Žö|ë[ßúa:“fñ„D"x"ÎGz±,Y¼õÓêE9± »äÀ)ñY…xøO4_…HÜ¢öÛèøÞ¿üN<=­“¹î |GÎÜóvYæÍ”‹œæ}ó›±×óòÄ7¾ñŸvñÊ?<Êïã†ë®ÃW^ÁðÈTB P ¢—ðœB¡ |ªðþÂC«@%*¨âBQ(¨¢ðþƒ á ¥øå¯~‚YÄ·o,»øÅ‹ÈÔálC.·e¼PXŸJN­~àR‘s2 ò`’B¥Æ“KÔTúÖüÀ‘Ç~ó™ÇÀѬW‹l­ §”LÀ2}8Eãž=ß÷…ô™_Æ©§ Ñ}lð¸9—gQynÙk"¯¡ã‰0Pˆ&”€€@ÓUèI#Î5áß~¾©•·áå?ü,¼áÒ€ÿã[V ƒ{Üdÿò¶ €œ ^:£ @ݺuëÃ+V¬\3^Èó6â…ñ Ÿ@¡hÂ,±÷¥—`Ûâñ‰F<` ºãyš EÑ *"L#ЏL¤ ËD! ¦˜Ñ¨hšx×m·âŽ ø¥ý}½Èår#ÉDr}*õÆ‚À69(MQEmPcÆæ@ÿGo|üó`˜ÅÔdUXÀ6«è¢Ttà–<BxW2¯oBŒ½B‘åkÆ<¢DÞ[ù¾j=¸Ïµå]¹ÄØd“pÐ*Ç+÷E>K€€´7#AW[J \ß…Ç40O…žV,ž‰=ÝXø{aÿ×¾xOºvîDZû˜GNãmÈdá¸)@ÁÍÑx-h5FÀëÖ­ûß[¶lŠ«VûŒ> ÊæXXvýõØ·?,ËÅA ˆB¡(”¯©ª0(Šd‰T¡PàCQ|(*¢PÑp„PÞs€Ší;v‚R‚Û7n(»\}à3ôö÷es9l_ŸÉ¤ÞL`Ê'%(ÔiT7fB—Q­Põ‡6âøæã¸cåX&`’YBÉt`Û¼›“ÉóðT~r5ÅŽ‚;a_¸íMÉøÜ匣ü¤û¨¸†°jˆçÑ@)<×… ‰áŠ…ópð—/@]~+–߆їÿ¦šÐ{XÁïOÇÞŽ,a¶·ì€\DhD†qX¿~ãºO¼"ÎÎá5"\ñÁ&jÈ—/_†ͯÀ²,(”B%\ñ UPx”Ï>¤"mXáæ€¢r3@q¡PÂ{ àP(Áöv ¸}㺲›ÈåêÁœêíÍNÏå¶ŒŽ­¯Éd.y8@ÒTQëU#>cüôÀo­øƒGPÔÆÀMvÑF©À³«<×Ê.¨4Æ/”þ\©uÊïVÙwîöÿÔ”»|ß™"ÜæñAJBˆ2‡“È|¢aùõ‹°íÐaÌûèDZsÿGV×è‹þXN/<ÿíÊ!D6>äX@&Q…™3®øîÉîîÇÓéô,_̘ÂÙ€øç3\¿ì:´hiY<@åʬŠÅ£ §(¡ ”@Q(DÀ_¡”pŸÀŽ;A °qú²{iÈÕÌGÏ©ÞlÃôÜ–Ñѱõ55—6L ò`BVKõX#€ë},±ð7ïB÷¦X¾r6¬<ƒU´a›%Xf NÉ ”_*>IþÕGòr9“ŸÍÉw>~©ØP“)¾Ü>0H¥‚M¸9à¹ð‰øÈÔÖ£Á9·îj̸q-Fš_ýM%¦wû¦ßŸ$ŽÞFƒRH*(ó$ P"KÜW×»ÖýãáÖƒ_öKðÆ1L´ŒcA¨yñ’%8ÐÜ Ës %`DQ (ª¢À÷)wø4 Í ¡ÜQHÔ`úòvî(ÁÆukË!@ï©Þ,ËaËéÑÑõµ55—,L H‚R­^‰Ó­á¡{oþêc0‡€™©Ì`K(-Ø…,Ó†çò?"F}R;ÿLÛS=~¦ýç#SÙ'g“CE_1ÉáùÃÔ!pÁàƒ¸úúkðÂá6\õñGñâç>º:¦Ïý‘Srz}ϧÈoWa)]tô—¯)¸c0ÖÑ~ìÄ¢«¯ýöáCÿ $À|1Y /2ñ}?ããÚ¥× õàaËäÓ Nù¶¢‚( Tá ”€*|æóiÉE(¾Â£ 4Š;_„Y(Lè)ÐØÀÐÓs*;å¶œ>=º¾¶öÒ³@œ<¨(ª©õTU®ô0X¿ðCkÑù\7-‰bÞ†e–`J(š<§šùéò—£wµþl£~µí3w>r6å®À²XríÕ8ÜÚ‹ZBéyˆRÞEH¡nÙ”ä<<È;@s H‚DÞO(´´ ¸çîòž |"›S==Ù†éØ24tú†úúÚÎ×ÿIž›œH‚BÍ(†>Í_·ð¾»P²`°L—×TK(K(™E>ú˘DñƒÏ«Pô3Aµ×¯˜Š²O¶o2àŒçú(¯ZwáÍ+Ä(såüÙèèÀ÷ÜÃßýÛ Fºö×Ô¶ë|Ÿàmè ˆCØ YJðßmÙ¼yóѯ~õ«ÿøä“ù‰è|qÜ-Ààû@Ö–,Y‚¶#m0-¡À”wR"žÇ{ òöï\5Ÿ€ªpæ@ ˜AKK Ò©$Ö­½­ìFdñ©žžlý´úŸöõ÷¯ŸÞÐ𦦠WÊT NUµFÅêÆGOܰô“ßÁé£yÌžQ«h ¯?oßd-QËzö£ ^M±'Sö õ\ˆLEé§bLöž2aˆÐõ\0 0Ôä¦ÃÝwkoűÿñIB•9DQ_ƒï%äÁÓ&û—sw¾%Dø€dx@þÁ³ðÍo~sðä7žü7¤"æÀM0,^¼Gir%VE¿™D‰ EQ¸AA äª¢Àõ"P8³Ý?ÿ@Ù½£?pöPàÙ˜À…¬cAÜq]0JÁ¨‚x: 6réëVA5…èZ Iß7À§[Kdž€œ3Aúd¶ ÀÛÑw½ëÖï=¿u+[qË-·Ê)VS˜†\'ºº¸B‹ß*gÂ駺O(7w FÍž7PΡسw/(%¸mÍê²û¹qù2ìÛ'A þ’I N>Lüÿí½y¼$Wuçù½÷FD.‘Ë[jUI¥ •J-€›uÀ`»·»ÛÆÆ²?3þØ3Ó`ŒñLÃØíûC Ìf·ÜmÃ`ƒ06 Ä"<ƨTh£TÚ«´Ô¾¿—{fĽwþ¸÷fF¾zµH Éï|>·2#2^TDdžßùåžWD$ëBŠ éüjÊ,lo‘Eúýƒ~Ÿ^»Ï ÛÆäÚ—¾:¥¾IÞ“Uþ¥ïOtÌrŸ§=Wà‰(þ‰¢ÿ§Cû—~¾ì~@æ9BIDì–* 10ÿÜË8vçƒ/÷‘ÙjE¼Qöí矑q€¢,ááFÀbáÐYÜœñã/}é'<¸±V¯o´ãˆ”»ƸÊ=ìÚµÇ-/&‘peÃÎ%P¨\MÜå&ר°d¹O- RrÛÇŽ«¯`ëíwpèБ+VÏóÍ=ûö½lÃúõ?28 ÐR•E,ëY»{åy¯y£>ä­ÃD2ìè÷‡Œ†}ƒ!Öh¤~Ê¥GDåÀùT.ÁI žnJp©œèØS¥òN總?•ò[ãú¢M#FJl#â„Jc†þÞæ_ü2oÙöœ¨.Zè Ö<£ãEñ)B|±ÆC>µœóÛríš5ï;pàÀ;ÒZíœq¥`a]¹6–Õ«æ‘HvíÙ=V\!]}ÀØ%ðA@I”PJúØ€Ç¤Ï ¸ÅJÝ2eÁm[oG"¹öÚNÝÏ󯾊­·ßÁAïü(Aàd iK*’Õa»³ùìk¯¦ý8$õ*ý¾óý]÷”>£¡ëd}œ2g |?,¡äIYÀM.·}²ýŠ¢<‘8ÀéûõÇsÜqÁYã¯Íy¬ÖZrcQ„ˆKTfšŒìcö’‹ÑôÏŠT£Ž"%æÇ–Šga²G˜3$Ô „U‡k×®½~ß¾}ï¨7C<_:l¬¡k`~ÕýÔ9 Ûá½ã[MÍøû ç+nc&Ÿ»û2…ge]ãJïe:'eè\#Ê5FG"SƒåFY‘EV ¿ÿˆ§±øx€Å5àŠvý8æ_üçvÇC;vmÚ´ù}ITêUkUjiJšVݨ¥¤•*ÁÌÜ,gµžN·C·×£ï[}zü†è,Cû#!q¤HÊ%Êe׎,MSÒ4¥^¯S¯ÕiÖë4ku>ñÉOÑjµ»Ÿ×¼úU,,,päÈÑëîðá~Ïpy „"Š„RJDJœ{í«ÈÁ& fÐÃxEɳ ËÄbëÒÆ·Ž`F„P㈷lÎ\çs¨üð‰óâ§HÃý0åTKaèh‹Í‡±ò„´r·m¬kré>÷à¢5Æht–ct”˜Î¥Xllå@XÑç_;À¼;`™Œ †f¹sçÎÇ7o¾ôúm÷ùiÄž „žÆú½³s3 %ûöïwk=R ÿ²à¨h\4$¤$F:V B‘s‹A¸5"¤)ùÄ'?Å/ÿÒ›–a¯â¦¯ÜŒ?&°,a„¡¤Èº½³, Ú ,‚Ü´±mɵ³öÖ7þT ¬Ežöû:§$–Õ½Ïqù³×ð–·¼›+®xZvT>NvîÜÉ»ßýn¶=ø·©ý;`)˜I—î³ÎeƒA±Vk×ÒÚXtfÈM—H‚6ˆlMX:hž1 Ÿ )6 æu©[ÐäÎGwì¾|óæ÷nÛ¶í†jÕO˜:I¿7`v¦°ÿ~ׯM0îIŸT!# C,@¸EH¢Ð~LâÎt Á'ÿŸ¿æ—~éhÔ—àº{¶ß÷­Ë6oúøæ‘p]€!È #FÂZ—š«ÀJGSµÁh§ì:Ëå·žÊZG… ‘þ‰+`XOÏ­µDú0oyË[ž1ÊpÁð–·¼•žºw­­ÕׂéásÓÁ ÑÚm®f`+ûz:ÿZ3ljuú ˜¸mœÐaR9hwîÜùøå›7¿7VI/­x M©¥Ò´F¹ZÆËÌÌ g­[G·Ó¥ÛíÑëú×^Ÿ~¯Ï`0`8‘yw R ·æ@¹D¥Z&MkÔ ®@½Þ¤Þ¨S«×ùä'ÿšV{yw`ï¾ý´Ûí¶ßwÿu?¨ç¶,XÑň–(X{ù,6ŠÑc_Õ­²j­uŠm¼l‹?zƒ±ar¦³pÚÿ˜µ·|õ%È÷LpOÅÀô°¿[Ïoü 5&sÏ:×W@ÂüæWbaÅ+þUÕ–„:\¡P‹ õ¯Çð†~ç£î¾âÊç\—â^µR%­UI«)Õj…´R¥\.cµ¦13úuëhw»t»:}}7ƒ£Á€lè‚¶XPRÇ1å¤L­Z¡VK©×kÔëu hÔ©5ë|òS˃ÀO½ö5ìß¿ŸÖbë˺–µÄX†Ž¶]è‘1Ê„síG€cQB`|^X&¸Né…c÷™*Ö?¤oâ?TüM(¿&ÄTµ mÈ:]¢( 횇=sâ÷'!0(p–?Hp ÀÅÌÎ;ö^yÕs¯¿sëÝï RgŠ2 ˜™i€„@p–¸BIdä†P’XĨ’"Š”Ï ¸iÃãb9¿t´DòùÏë~ù—¦þß$‰yík_Ã7ÞpÃöûîgó¦K>~&Ôò F¯½Vç´Ã6ƒÃÒ;ºƒ~ë(ƒ‘E–6’Ì^€ Š®,¸ô«lÃQ„m<{&‚À¸Ø°Úö‰©4¸µŒƒ¬±Up“ù®Ù*ítÆ{EÆâk`ÒVì¸Cük`ǃ;v_qåsßwçw¾£Z¥²ôÉ £á™FƒX)<äÕv’ëÿH7X E$Ý«ˆb¯üÊ€1@«ÝæãŸø×ýò›¦.4‰…Í›.ù™zVË€®""\D_ø.iÁf‹è÷ ³›Édf.$j\DÒ8‡¸²! B(oýœ“ëØ„7wÏp1K¬;ÁêO½/d>ŒõéTƒµa$VÀ¨ i;H• Æ±*/·0ÊŠÀq PÌ‹Â{ð]…vîܱûÊ+¯xßíwÞùöJµ’ãú7Ø0f¤õ”sJ »vïñzÿ>< %ÁRø€ B*ܺeå–,“‘_8.d)95|à†{¶ß÷èe›7‘&£'HVAT²2›üèTaÚ#0Îã›,<@¾¸ƒ<*CTG6Î%JÏ!©®&ª­Ox‘ãIÏlqૃ¥ýýŸT)jc1fȨ½Óßì'Kµ¹s‰æÎ':÷j¿Ô¸tÀ,bXIžT<„†"aabwÖÀÎ;w_}åUï»}ë¿M¹œºÙ(ã² Ë('%Î9ûöìvˆ–s „w \‰p‚_†r9ñk ?wÆ]’ô,»Ónžsùf¶mß>|óží÷½ìL€Àò @Ö„”©º( yö<û¶y:#K b 7;3«ÝÓæ »˜c÷3jíd¤Jî[^ETYC\™'*Ï@|òúü§«Œ'2sún™P³Dùõp3j‘õõBA>;#f7â*%qc » b¤Œ¢ô#»Ï§‹,0¡ø.7ë¤ °sçŽ]Ï{ÁUzÛmw¼½R®¦K­•éB>‘$1ÎÙÀž={½;àš»]\%Hâx|Ž$v…œÊå§ò”Hè,¶øø'?Åu¿4 \pýÁ€‡wì˜RžX¤¬ dD ì¾{!šÎê¨T‚Œ¼b{4Nø»–ôûLîb ýÃäƒòåXÄÅÏ<åâ ¬+˜µÐ£.yÖE±ÙÓÛã”ÜhœfäÖ·ùÄgð¹e¡¼¥BÀ±‡î¤´® ²ŠTÿ¸Ô÷/,“EGla]‚& wìØ±ûE/ºêý[¾sÛÛ¨TkKÏ×6ëŒ$Ž9gÃYìÞ³w\x\ìZ…)¿4™R¢”$MSÿ=ã „&:ÑYlñåoâu¯n7¾ùÒKxxÇΙuëÖ~óží÷] <údŸÍ \€ˆBYUª´M¯UQ%UBÈB•¥&fÐvw®ÂÊM㓸4‰ë­,p@`'¾k{™ÔÇÓ]Â=-"¨Õ IDATyèfÇ…ñŠ;0ôþ$![e½{*|ÄOjÐdäzˆé K J%¤Œr€ò™‹¢gXìôB¤¦ç ¥ ðàƒ;Þ‹^ø-ÿòÏo/WªS8Îbé´{ä:#ŠcÎÞp‡Ž¡Ûnw² *iuÚ‘PO«N÷™ÌKž,,,œv>²s†5kÿnÛö{_vùæKŸT/åç -Ò…™U©|ÔÚ9j«Aª2J&ˆ¸„ŒÊȨBL€¤÷MeÄ¥ÏiYíñV‚°ôGŠøÃìܹóÉ\÷SRîºë.>üáÓÏ ‘ã²QÚ? ÒÀ¸§…›åÂﲸl‰J2A¨2R•¨¬?‡¼*šE‰º²PþM>Åׄb¡.ÓuÅb! ˜>´ûÅ/~ÉŸ +ºÕJ™´æ …j•”ZZ%R¹Î‰â˜ g­'ךN»ãê:]ºÝ.n—N¯KÏ -'iµJ­Q§ÞhÒl4©×k4MÍ |Ñe¦dó¥—$%pèÁC(Ï&ÇM^Ã9ÂÜâËaægˆC,ewâä9s;e~ û¼Á°¡¥(ì·Þr»u'!~ó¬GÐÒ3 p¬ñ§ó÷*ý×`ýÇȨâF\AF)Õõ3´o#’òA¤¥(åVb+3ÿ3æX„gS¼÷)Jeö×,@ÿØ_&1œÕ\… ÞùÐý»7nÜøÇ÷ÝwÿÛææf7†ßHøÕ´»]t–Cì@àÐá#´Û]Ÿ1+~>cPŸ )—õãx¹Á¹woÛÆs/Ÿî%ðêW½‚›¿þ :tÅüüªx‚]…NÐÀh0#£u/©¨Ý¶ßM\~•™ý…Äý0U•!©º–¿9ˆ|<@@T"¼’‡mS` ~ë·}†f¬Ë^Á„ëÙE1~ëªg|/ÿGÖ?vY¦³ÁaG8Dûÿ;9·ar=ÖÓwã)½…ÿÏ+¸A<;±þ›(…fl‘„\·eëíw_óü«?xªû?aK)cZLט¬×j;ßò=ç@”ÔqmLQãê¼Sþ`ùÇÆ~}P~ßQ••Tâk ¤¿šWPòŠ€Ä[I‘ø3¥ÐãšÛ Œþ±ÿK@aò<'TÝÆ>¿Õ¥ gI½C¸GYž¾ž`åEâ÷)ÿ,â0€SžUøûS ªTC&uTREÆeêΦw°lnÛÆØ®•…–à¶ðæ¸`éR6°2–ŽÊš·xëÁIg¡0Zþ5t2xhµvÅÉ&PO‘"òÓƒ3*Õ*õfƒN¿Gk±M»Ó¦ÕnÓö£Ói7ù(HF³AÓgšF“o|ãzËdþýϾ‘ýûÐj-~`ËÖÛ¯;Á©Çr²žr™5¶o´iÅiýî]·ÞÅÌÙ JU¢¸ŠLªJ5¨6&tÜ0(~ð÷ÕäGLÊYƒâx‹•H |Azˆük±nJMŸ' àP*€Dä‡Z2ü~Ü“¤ ¤Ee-4•á’É5ÁÈ¢²¯ô÷£”?.Üs!Ø9µᘄØ?×8E&5â¤Níü&Gî¹Y.í°Ö¶Át° ÆÝV$LÞ{¶WÆiÊÚ·äဠÍÚ8wà(Ž) ·iÓ¦÷¶ŽžÊUVÍÎÑéwòw‚KàAà$õ0¨;¨×©×4u>ûÙÏÓëÿö¯gÿþýtÚí¶Þ~ÇëO¢ã'€Þ‘?3ÆÚžÖY;©7·<¶å.”‚Õ­C•*Dq•8®')ª:ï>°¦¢ò §\²ð„bL‰Eɱ•,oí……hÉðÊ*Eá®Äd(9=ŠŸ…'áÛ59ÅõV|½M›7_ÿÀý÷ßy*R±zÕj†ƒ­v›Vk‘v»Ãb»M»Õ^¶@$ŽiÖ4êušÍFÔùÛÏ}î¸ãÓ´Êßðúq/oÿË­'¬8À¢û&Ï;:¶†=¥Þ7dÕE1*IQ岜¢J5Jµ5%7›Jx÷À„\øñ‹‚’•( ë=Œ-}ÑZ”(Ðôƒ–W%ž¨éE…c¢Éuc!h·ôÿú¼ÀŠîŠ @] Š!ʼn×QÇ~¢¤Š*7媔ҼàB" {¶lAU«ßÑÆ´¬¥ ˜àN‰¨lÑ  .×Ê8­Q9ëmÞ»]&îÀ1ÿzÇ,Ð{Å+^ö_·l½õÛÉ)@ sósäY~<´Û.uxI’˜f³A}ì 4©74ê >óÙe@ Zåê«®äÀÁ3ívû7OtÞ“ÖŽ¬Î;ùhÐ*Õ·?ò»™¿âRÝ@’¢ÊuâÊ ”jŒ­[øQô–I”¿¨aÊqÑê/·/(n1¢NáEÚ5øÝÁwŽc ¾XÂX`"Wù8>·ŒcV³È«)Z~éc†’1h IŠ*7]P©A\jм`»n}(µ­ÖGŒÎ[`z“ÀãÒ¸ÇÒaVÆ•³Þjq &õp@ÐÃ1.p„ÂÜ‚Ÿ}ý>~ÛÖ-§£ ss³`˜V›V{ñ” ÐhºnB ?š:QñéÏ—\òlÚí.G-¼õDç< ÓV÷õh´PªÏ|ë{Ÿ¿‰R V?û,â¤N\ª% ¢r¤±ÞÓØˆòJkü3v Ó`SÊ1¥@jZiÆûeáø¢;±¦XÁ FÑ -sî)à‘…ýE–RØ?EïKZø-á\> •jÄ¥q¹Iœ¤$YçÁž[· Ê•[M–-XkÚÖš¡•®Ç¢®ë²]gt”7üf è3&­ÇC0Ö¾áõ¯ÿØêK@@M@ Ë4frR¢µ¸Z'r’Pk4©7ë4j®¯`£^'Ž_øâ—;þŠ«®àࡃOÎèïÿ±ÆtLž-XcvuuÌÁûFÌ_¤ˆªuT¹ATNQIRc­ËýÛ‚âŽSzÁ ðïeÁz•ù8«*Å_ÊŠl!\ƒ:~ßø39¹¶ñþåÎy:@P¼Î%û„tÁÍæ ÿ_(V¼[åFU®3·éÙDì½ívâZúÕ\gÇ,¦Ã’Õ€DqcÅå?“(T(î@Pþ.&0ôÇò†×¿þ†eA €@æA )%¤i•v»K«µHk±Å¢g'‹ TË Zƒz³9Î Ôš ²QÆö{ïŸ:öÙ]ÄþýNx®“»€EwÉæùàPRmlùîÇ?ÅúK¡\Ÿ%*;HÊMâr“¨¹žqY®5Îê-sö…ÔÓŠçv¼¸O.Ù ¥/Zç± °Ì˜:>ZæhFÃ#VëEkLÏJ@ùÀf$ü{áÞ·WÆ÷5ÊßVô£FLX@(ZÄCp ž |õ+7ßì@ Ný¸b¡ŒL»NÂ*R¤i•^¯Ïb§=E~"ý>%ô÷|p`tÞÊG£ƒå¹ù/>ôOÛÉ{°ñê9âR¸\GUêDIÊì9 ÊÞ  #% ­o—ZøS1åhãÏ–¦ìŠÔ?šLLš!ÄäïÆÀ/$áÜK–µüS•€KŽ ÕBB\vq•JUž!ªÔhl<—Jv~ã’zãóÆäGŒÍ[šZv¥Ìç,K@ ¬@ZŽwpÊßg¿rÝ›?ó‡¿ÿ7ÄJ¹¶àµ”ZÝ€òƒ™Îɲ ¤ –¦äË­­E7[-Z­v¡#Ñ´¤iÕÌxÔˆ£é9ÿò[ÊåòÛNt'¬,бºkòá1=è”Qíñï}~ËÆçþÜ5ÐfõAi\¥X¸/ë«ýDäÏ™»lH¸vëæÄ•Y’ŠcRIµIRn²îyppûŽ<´‹êüüö|±Ö¶€|\:& ê/V à%åóÞ>ΧýÓb·áBÅÙ8êÚª€øèG?òm„´¿û»ïúÕTÖ(¢u§Û%Ï ž\S©Ve9‹­–ïCÈxÅ¢z½6ÕP$HZOÑÖ`ýªF¡Ó4À]woãÖ-[ßðçüÓÎ<-°Övuž/fÃÁ¡êªÕŸûîß|ùm/øåk8÷y«¸ÿ $£&zØ' Hg7°Ø]t\¬ñ3Ýüc×. ?ŠÊïÏ ÄIÇ´øÎÅcBà-º\òˆE·€%. ô¿àö 'Ï#ª:‹_™!©Î’T›”Ê 6\}>Ýý°ç¶­Èrù:°Ö,XVÖûQKùü1Ð8—`¹á"Î-0€þÈG>òíwÿÑ|,‰bßT$¥–:Ê©˜\çäYNHA)‰évû´ÚmlÓZ\d4ÊŽ»&¥$µjêWJyèáÜxã_}ó/¾éC§ºŸÓbÓÓ:;’ úû«³sŸÿç¿üô¼øeÀ¹WÏóà-²QŸhÔ'Ò¥QF¿vº]¯–±VágÝ)Ü‚%~ýº ‹ïÀA,µ°ã}ËËR0VÓeþ&,:;‰%òD#Ì,d9³‘‘›Z<†¢±˜Ue†¤:OTiUfˆª³Ìœ·‘ÚÙðµÿô~*3«¿¨GýZ›CÓrÝÔˆ†ÿ³"?$)=ëÐÇßë¿ä)«c ûf2 >ò‘|çÎ;ï<ü©¿þôÿžÖÒjñ|ín—<¬û`pªq3 hV“2ÖROë®w@A’$¦’VÑF³gÏÞÇ~ã×íO˜^(uY9-0xôý=còE ˜,8D{nûä78ç*¨¯'©6¼›!©6©Í_q¥àKKÏ,n&_!FpB7À4„(X|ëïhüGÓÖÜöóºÂN©Ï–°ãBa páˆS.IˆWàöÛ„)×$]X…RDPªyÆ4K©:G©Z§T­sÎOläȽG9üÈ>d©üM X›³“޶Ӳ’öûQŠe2•8L#)ÂÐf¬‡·T[¶lyàÇ_tÍ{M®{õZJ=­¹åÂÒ”$vL ³Î2”Š|«1ÇZ‹®`¨Ûëw1år™£GŽîúñ»öÿöXk§ Kä´ÀZ»˜çÙ¡Ñ ¿»:;÷Ù;?÷uzGáY/­QòÊW›$é,åú*ÊóçxÞ; þ±Œa9*íƒo¡ZÏ+áR҉ÒEw+ê¦Vß\ZñUø,,Öií‚m_Ü“+Îz,\³_L±ãÆqk!*SªÍ‘Ôf)U”j3$Õ96\sé,|û£ÿƒtõú²aw¯Öù!cmÛbý¤# ~Šq*0t”]?ÔQºøwléâß ô.” ‡ID‹~,à,±Ø{ðà®—¼èšëóÜöjõšËøz$ŽÑcÈÈ´3c Ýn—ÅÖ"‹­6íŽë=¨ )‚}{÷îÚ´é’ÿx ˜Îž@ž v¾¯g­>¤³áÞ|”oÒ¹oßüÞ¿bí…°öÒuÄéŒtŽ(mRm®%š=›q`5+åÂÁG¶!(è/K:Ÿzl}9^ñ'J?Qôpü\<–°Œ—9’ñ$'+}ÝC!]8¶ü!Êã&Ei“R:G\m§³Dé,µõ«Y{y•»þæk [ÝÃV›»òÑh¯1ù‹* s•ëÿT‘P:¼” å‹’æ€Ý{ðàÞ—¼äùïm·W«UŸ&t+—“’Kf™«ÈèÜ}Ùý^ߥÛ´Ût;]FYÆ®]{v½aÃ;ÝÀ=6,'} 9í@mMKäÙþlØoTfæ¾ðؾhÇ-»å³_~6ÇvÏbt†Í FçØÜP³‚…á§㘀eÙl@˜4}}¦Þi¾ÁËò¾¼3Æ'›'&ʰY¸þñ>¿¯÷WiƒRmž$sϧîžÕ†k.¥±¾öÇ×#KéyžmÓùh·µæðtáX±þO] þi˜?˜@ç ñÀ Ð}á ^ð¾‡UÇêujiJ¹\FkíK‡ýkîXÖšáhÈb«Åƒ÷ß”ð°µöÄu¿ËÈfƒÞÓªl~×lЭ¨$©—ë¿ù™ßú³—½ù¿ÿG.¼v~+#×9Ú/tiúº‹hï}´ö1¯\!5f‚oå-¨W2‚•õÊÖØ*Z|ãý )%RÅD‘BJyÒ”_±y€\kŒÖS盬d˜®ØBà®Ûú†ŸÖºkÏ3?þcÀ*DZ'©78Öf)¥MÊi“ù ÎbÃÕ%îüô-ôŽõ•*µ›†ƒÎ£Öèýí"ÿ“¼¤Ã–ëÿT–bjªÇŠû .C½<ïyï»õ»·ÿöú5kÏŸEºZAo@†¯©±“?n·ÛÜqÇßþÝwý§?ÇMO~ ØûD/öI€Öú˜ÈG•a¿W­4f?wøñ—ýÓG¿µúÇþ—Ÿ }x={ïñÔ;Xy$Agߣ ½ùjb-]boú§Çé¸e\ã@A)…”Š8Žü{§¸áU …Á |…Ö)%Zë)ëù×Ì7vn½·iêo'×JŸ­ž€€ã€"­R®ÏQ®Õ)W”ÓJYš×qþ«Ö±û»»¹û 7Q_}Öû‡öcô‹= "[jêWÔþi#Á˜þñN$¤ # ûÂç]ý‡Ÿú›O_÷’—üصBNþ@ýÞ€ÌNÜ€½ûò_úÒ?|æÓŸúŽU<ì8]¿¿(OF÷¿'/o~ç!=ì'ƒ®Jk«Ïzß·?uãYõ¬ Øôòs´Wsø=.ÊmeLgïÎ Bg 7Ô„þ ”IJ)I⩱â»×ˆ(šå$(¿µ“r“£µ&Š"´ÖŒF#t`&|“n¹óñúÈãŽÀžþãÐ;ÏAHTµN©Öp¾~­Iœ6ˆÓÒ¹YÎ{Ù9t÷ ùÖ_|„ÆÚ Èú½&í²Vš ü‰©V`à)/ÅòàÅýà›Ã3i6jßôóÿᆿùôßðâ¿äZ€ñ¢"BÒí÷ôlÛ±£÷ÉO~üÓÞ{ï—p.Æ“V~ñý®¸S¾üw*)mLªé¦$M_Ô[Ø÷¶_üà;ižsÇçGyü ƒÎ1²n‹Aw‘A{ö¡½0ð+6Ëȸø"9­üÖ¿ø AEÄ*"Jb”rÇñŠÊ*ÀŒS8?KkM>1Êó1[(œ`òÞXÆkX|@¢j¤Ö¤œ¦”Òå´Iœ6©ÍÍpñÏ\H¹ _úý¢»â³6Ͼ<ôîÓÙè«õ!wŒ ±ñ·¶O%Ýûž}äÓ^H\APɿր·úP 㥞ßóž÷ü›Ÿÿù_ø™þpD¿ëÒ};}”[¾yËãÿ«ÿþWÀݸ¸ÂcÀcOVùá @é9¿·:*•ÎOªé&¡ÔëÝý?÷æý>åfÌߣ{øƒîY§Å »À°×bÔëÒ>´ÝYt®€ô¼'Lt)öJ–¡|Ö"•"Šc’("J¢(+ÿ4 O‚µ×™&Ó¹Wüùh4v üI&ïCþßø*®Ú I%¥”Ö(§ âjRÚ¤R¯óìŸ~•øò゚A—Ûâ(þ«Q§}Ÿõ5Zï³ÖÏ÷_&²"O=}ïOuˆÂ±íÄja4q`0ë? ²ú=×_ÿг7œsÎÞ}{¹å›·# ; º-²n›a¿KÖ]¤Ó:Æèè§LBxÀ$ðUøá+¯ü¥$™Rþ$IÆ, ¨üEq`lÉ—³þEËŸiMîß@Æh4ÄA ̾òÖ_”Ê”ënJoR­S®T)U›$it®ÉÆkÏ£¹¾ô{`Ø“[“¤ô±a§}>è=jõh¿5f`‹B¿xªÊi€O{¡€˜ ¨2a T™ÎÎ…/¾Ç$“°¯üß?é@Q,&9‡s† !¢$Me¤RñÿÖ{ÃÏÿñoðÂ7U¸óïŽ=.AÅ(• T‚P1R™A¹Fçànȇ“šúñZ{>ðE>¥—ŒS{Q™@DRŽ+û”/#.*¿¶a¹É§”_kD¢tÆHJ·œ“úU¿,Y6ÂæzòÕø€fœÖ)ÕêÄ•:q%%©Ö(Uj$Õé|‹r#¥|ñ÷>Èhm-UÒº è|ø˜5ù~kí`âð•ÿL|K+ò#”0yȆY²Ž183â “µ Ž{€œxšë’3B€Åô­Öòl è ‘¤)"Üð¿ÿ†_üÀ»¸òõ1w}q5ÇvÅŒT„Œ2IÈû 2*‘”KtŽdÔ:ꋃĤtþ~‘ı€(&‰#⸄ŠÕ˜ „I‰”Ñ”0 VOèd¤óý—@žûz€°zo(,²†‘1.›lè®~ §IDATȤJR«SªÔ‰+UJ•”¨R'Ië$Õ:Õ¹*Ï~õâþá÷>Äh¨¶–*µ:‹d£ác&Ï÷[k¼òOÐ|%è÷Œ’Iûôû"´qLAà‚ˆ9pgùp†”θŠ: ˜¾É9˜‹ /HD*˵ö“oÿ“7¾éúwñ¼Ÿxà[sìþžB¨µE12ŠÉ¢˜(.3lÌÒ>¼Ó÷ÅLÒù÷aŒ ŽIQM@¬&ñ-0Žü;ˆÑZ£t6)&Ë9‡š…ÀÂÈ0”êuÊ•:ª\%©V]K¯J¨â¬óì¿fž¬ _üƒ3ì³µ””?6ê.> ™<ÛgéO)ÿ ݦJÑòƒ+ZZEÜ‚= ’±€3Zv†ð * ¦kr}@‹ ac‘æ•æ†Î ¿ùGoþ©·ü"—ÿäE474yè[1½…—ˆã„Q”0ŠË¨RB\®0ì¶è= fä"þQDÅDÊYûR˜@D¤b¢Ø¹  <È Xk±Æb#‹ÑEß_¢tN–çnÖ ^/2Ž1)(Uëˆ8Áª˜¤”¢*U’rJRI‰Ê)qš²þŠõl|~ÄÂã#¾ðîë)¥³ÿÇÑ? zÍÈ)¿1º/¦£‹%Œ·WÀà&KiÿIõ`ƤÇ@‹>nNÁ€ÉZgLÎ ‹éj­˜ÑÀZ!t"Äh~Ýy‡ÿñ/ÿßß|ô{›åÿô¿þ W¼¡Ê·”YØÇ*IPƒ.º_b—‰JªõD>"ë·Ö8 ˆcb¯üqäbI'Q´$;W`’ pn•³à“" , Ô_¡u„”#—Þú9‘Š)ר(Æ 0Ä)݉唤Ru~³Êù?¾–ùsá®/ßÍ­ŸýicÍg­5_ö[™aö¨ÑÙktŠÞ 8£_ïŠ<…%(x±»Pè9曇†¡tøŒÿ:ÎLàòw*÷Œ¯ãPª"âxU—Ί+Õ¥´~no°x]m&Úü3oû5Öœñè]ðÈm]ònŸÑ CÖï“ ºäÃÂŽäĬÎ!!tŽB' qSJJŽÄQœŒƒ*Š‘J—ŽOÿòþ£<'ÏGäYN6Êȵvß”RNé-hF ŒˆÄè(&*¥Ä• sÏZÅy×–nþ‹¿eïC÷ªéìGô°¿-öwäÃá.‘ëÖ˜~°§…OuŽ¿’ëÿ´áÝï>ág÷nßÎÍßú_þòM|ý¦›–kð*CÐ/Ô ˜5«×˜(ŽõÞ½{¦f´5f¼òå¯äu¯}/}éK¹à žôµŸ™ n‚Ìd[ŒƒÆèY>Ø]ƒnŕꇆ}~â¯~ûOÞtíÏ¾ŠŸxó‹XsaÊýÿœr쑘¨T!”! mŽ$CÄ „A F#¬ÅjÒ@B)‰},ÀŤ”Ä㢠ɭëo­u¹ÿ(b”åè\#å)LÉ"¤D[ë†#„[3ÊF"ŒH0QB‹Õóó¤iú}]ÛqÊ—¿s\¼£=¡ø’^)1Rb±%!匌âUIR:;*U7Š$¹zqqÿ¯_ðœgó“¿öFÒU°ÿa8ô Œt)‘#Ñ(›£¬öÊoÝZŽ¢"!Q‘$ IÔ¸ÐÅ`âÏ )X×J¹èƒÖ†<¼7Öm#Ü{¶­(¢ùì«Îus€¾{ãVî¸é«4k¿¤TòµlØÛ¥GÃ=:0yvÔf¶-pH"B7$ßTšPF\±O#9™ ðT—xk+)±BºÄ¥ð¾®”u©Ô¼Œ“5I¹º!)§çä¼rqaÿO_ö’çñÿáÕÔæáØ^8´†»†Ì– Æz¼ŽŠ ’X ”’(©ˆ”W à&èÉBQaX¾04Ê­Sþ‰â[2cÑÆ’[‹¶mû;ÃZ‰ê9 «Ï‡¼w~í»Üù"–ÕÛËIíoóAo·ÎG{ò|¸_çúˆÐYË;†1Xá}~€€yÚÈ œ°R:Ê-a°V#„Œ…”M•棤¼&.W×Ç•tC?ëüÛþ ýâó.¿½ö•l¼¬Á †Á^( ræ*’Zb]u$HH”t«c+ JB,ý4_e ¸ÖOÒÖnbâÈ×õhí^s½Ìp°“sT[F«/„Ê ´öÃm_º‰‡îºŸR©òÝ’,Ýl²üá<ìÊGÃÖêCƸe¼T(Öþ?ÖN៨HL€%AÀyZÈ <ç]Þº ßÑk6€ûß‹AûŽ>©²”QSFÉ\””רrum\®ž5"{yÔzy’Èôy¯~›_°™Æjè¶àè~ÈAÒ3¬*IæS˜­:Å¥ë&¦$‘SþXÏŒu»s¯ô¹Îö·`_ÇÐJ£’`ölHk0ÂŽ;áö¯}“Ö¡c$IúJ”~A磃y68 GÃFë#ÖdG±t,Ö"*ôÔ>¾£­§üþBÓ `žv²ÏyטE`Æ€gn`]OH‰²"£¤)ãxV–Ê«U¹¼6JÊëdœœ×,þdÖoošY;˳¯~._õÖœ£ ôÚÐ> cPË ¤ ÍÖl˜…zy²Þ£¸c,Ü¿ß]OWAgݨ@uê3ŽA´ÂŽm÷±ëì¾g;”«SUÿ;¡¹WgÃFç‡L>:bl¾`ó|ÑÓ¶˜\Š+ܺ}Òøžˆ‚ ˸+𴓘–uŒõána±h7×? PJç¨!U…(nÈ$ž‘Ii•Œ“9Å«¢8™ÕØ‹GfpU6ê_…D­Ú°–ó.º³žu!ókfh¬)tû¶eÐ;:]=apí ËUÇ) zpp÷1öîÜÇÞGvrpÿLo„ŒJ÷Ä"¹36Ñ]ùhxTg££&1y~Ì¢0ºc­éYctøŸ”Œ°> +=Çòダ+ðô–8BY ‹oZñ ÀƒP‘ë¶)lWD¥È¸.”hH7¥Š2Š2Š*ŠëÙe¹Í.Îõè\t¶žþˆòyë(ËåZ…µž#°£ÂÅF@YpxÏQº‡!RÉÂ];¡^µñ£±L,Éêm:¶ÍhØÒy¾h²¬Mž-·Ðy›ÜtôÁ•[·°Ws`}~o9@]€xÚËÓÎp)ð‰EÞØ@¾æ^0n~i}Ñè¾5ô±vÑZQ6F—ÉGU‘©ŠPª&"•JoWJ¥‘¬—”l]–9*Òžß^œ}äP;Q*R2 ä´ÖÖh“›Qž¡íÑäh²½4»¡‹´}#kÍÀdy·§ºÆä]‘å›ë>&ï‘ë>Æ0Ú/û«&)Ï¥}»Ž+ð_‘yêÉ &"BÕaîÀ³‡I&ÌfX“¡m)¥5&¶V—0²¬å(Aʲk((¬,ƒ¨ŠXmIT±Ò”Œ0Fºò$k±ks“‘›‘å½~6ìé!mD†0Ú 0f„Ñ«Íc2×<Ð.ÇCøb§‚þ‡IQ6ÜëŠò¯ÈSX~0­v©õ 3b¾¼¸P.'0X=ÄÚ!Ú´°R`µÂJ×rÉ!DÉ•­ÈƒŠÐRÉɉ´µäF»…ØÌmX3DÚAhœ?oýâì“è!PìT$Æ7³TÑÅŠÚ¯ÈÓB~$,QvO–ÖÇ{+;‚`m'ôD&ÇØ¡›OaÀæ£"¬q³vòÂD‹› ll>™àcÅ–dL}ÂVƦÝ_ø2~EóWäi$ÿ?&¦ÁñÖ{ùyIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/viewmag.png000077500000000000000000001125711217176075400242460ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½x×yßû™sff»ØÅKü @€(ˆ4)JeZ2eY´E ]…´=InÚÇJ7¹M{í:mŸÔmoÒ¦½OîíM<··MsÓk§OïS;rd)²dÕNdʲdʲhJ2)’ @ @ À ,vwfîgfwv°‹%AÖ¾Ïs0gÎ93»˜÷û~ß÷¼sFs]—ºÔ¥.Lïõ¨K]êòÞIêR—°Ô .uùKêR—°Ô .uùKêR—°Ô .uù‹~#N¢iÚ8ͦ”C‡ô½Rʤ!å€4 t©mׄè•Ò@ ¡ù8êà¸`mlÛ¦X(`»îˆk/.Š#~yîÙ§FÞ‹ÿ§.?}òvry´‘ôÓ‡I 0-ë`´¡a{C4ÚkÆÁx’4 ý`,Öx_,;ÇÚÛZimM‘Jµ’ji&Ù’$™h¢©)Acc !®ßcÊç d2æ2 ¤Ó×HÏ^cff–陦¯L3==͵tšÅ¥¥“¹\î$ððdê²–Ô`rèð‘¥ì±Ï´4· tm뢫«‹ÎÎ:::èhk'­û|Žíàââ8àT„@jl,fff™œœbrr’KŒ3qi‚«33,d³'mÛ~ '7ö×åƒ uXE>Ò‹ÅK&Ÿéèèè½¹¯žž¶o僚{¦iV=®Ï“ËåÈårä——YÎçÉ/( ØvAùø¶ƒë¸€S:N¡iH¡# ‰. tS'b˜‘Ó²,¬¨…”²êg§ÓóŒ1::ÆÈÅ‹ 0qù2™LfĶí'?®ÇêâKªÈ‘£>ÖÜÒò™ŽŽ¶ƒýýýôïè£oǺ:;VŒ- d3²Ù, ÙE–³ä–r,æ–Èç–É-çXÎç).( ØÅÛÆ±m\× MHM¢{`SÇŒD0-,‹hCÑh#±X±xœx,¶‚9ضÃðð††‡¿65}eáÊÔÔB¾PÈ ¨€ÿ,÷ê¶A1¯ÇbñŽöŽÆžžîT2™4£Ñ±X#ñxŒX}†Ë—'X.¿üùsÏ>uì^ÞºlrùÀÀ'þto2™üÝîî®Çn»½·ßÊî];+Ædæç™¹z•Ùk׸6;KzV@z>Í\zŽÌÜ<ó f¯ÎäGF/^;}úÔdÞ¶'`ovÏÛV+P©üÁºV¥®JØ’L$¶îìïO}h×îÎTkÊljj*@²…dK’–æfZ¶l!•JaYe`[\Ìñæ›§xã×yýõ7¹4>Îr> øGõ áC>ppèð‘Þd2ù»Û{¶=vǾ;Ø70@ÿŽR¿mÛÌL«©µ«33ÌÌÌpíê,³×f½)8§Ï¼uåä›oŒ¾Â;âê¾¥/6ÕAV²?Â(½•,ÂÛ¶š†Ùù±z÷îÙÓ™lN’li¡¹¥…-Í)R­)R©©ÖVZZZJdÛ'Ožäĉ“œ8ùãã—((Fð¯ê®ÁO·|`àÐá#ÉX,öùîîîÏíÛ7Üçì Xü|.Ï•©+LOO1}eš«ÓÓ\™fff†™™Yfgg8qâÄØ¹¡¡Q`È¡ÚWôe”²¼’§ ÖËÂâ_ ¦W÷·An€›Üu÷MùÈþ›ZZR¤Z·ÐšÚBkk+­m­´¶·ÓÖÖVú BÁæµ'xõG¯qòÄI&¯\ÁqÝüQ=XøÓ)8rôуmí­_¸í¶Þ»îº‹;ï(õås9&''¹2y…©+“\™ºÊôôŦg8{þÜìñW^ÎSVú"Jás”ß •eolÞï·A| AÄÛ ”¢û[¨´üÒñúý±A ðÁ`ǧ>rÛ®]»¶´¶·ÒÚÖF[[míí´·uИá˜Ïdyõ‡¯òƒW^á'ožbn~> üêsÏ>õä†.|]6½üTÀ¡ÃG’ÉdòË»n¹åèwq÷»Õt` L\¾ÌäåËL^ždòÊ$W&§˜šºÂô•)^|éÅ¡ñÉÉÓÀUÊT~É+¾rû`à·ù`¶þo—ø)hý-”âKÊÊ.½ö¯ˆP‘@Û¾ÛîùØ=7uwwG::ÚiëPÉL´ÁØØ8/¿|œ…á à Åc( YïoP—Í-?µpäè£G·vv|ùîÜ•üØÇ>ÊŽ}¥¾ÉÉI&ÆÇ¹<1ÁäÄ$—''T&ÝèXþÙçž{«àØç9”rgEÊJ_@)|–²Òû`àxc‹(vàoýÀ2•`@h¡ü”¥‰RX¥ôQ*ƒ¾• ”ÞW|IYÙ£¬¿?ÚÕÙyÇÑŸ?zûöí=‘έttv²µ³“ή.’Édéz½úêk¼øÒ˼ö£×˜½–N£‚„_ÙÐR—M)?upèð‘dS¢ñK»vízìã÷Ý˽÷| ÃP1´ùtšKããŒ_ºT€‰Ë—½x1ÿÍo}ë-ÛqN¡v 5e·„RÜêÕƒqļ¾å¢h÷Ý¿¯¡»³kß§?ut ÷¦›"[·vÑÙµ•®mÛØÖÝ]Êvœššæ…_âÅ¿Ïðð¼¬Â_­ÇÞßòS‡?yt ££ãËÙÿáƒ?ÎÎý8¶Í¥±1ÆÆÆŒ31~‰ñ‰Ëüå_½`Û§P ¼ÌS¦ñY CYé½}_ñíP¹‘ÊïKx 0X(ˆq”‚),Ðl‹SvJl¡·»gß#üÂ}7÷Eºººèîîf[W7me·à¥—óÝc/ðã'Y\Z>UŸ2|ÿÊO 9úèc7õö~é¾ûîMÞÿA‰8éÙ4cc½Ä˜ããc¼öÚk“ož>ýp eíPJŸCÑÿÝŸG)ý•AÀ°âÀ­²õŠp1{0ã ·oç^b±&:{P…a ·¸ÀÌôe³sœ;ýcÍÉÎ=^ üºŽRn¿øJoxûM”@ ì6ø¥ùÁûï?xðàÁ]ÝÝtwwÓ½M=ÿ`z9CÃ#<ÿÝc¼øâ÷™ž¾ Ê%ø£þfuyïå§yä—¾´ûÖÝŸð¸÷Þ¥ö±Ñ1F/Ž06:ÆÅ‹£ŒqæÌé…¿9vìUàJ±3(EÏiÊ”~¥ü¾/ï+}PùÊ阩=îƒó·?ûE·yKÔË÷Hµ‡þœPÕ»Äþ#Ž¿uáÍ'ùÞw׎{šBúÍ àƒAh¦’4¢€ ŠçIÊŒ@zÇnÿÏ~ö¡=»÷$º{ºéÙ¾í=½¤ZSÌg2üõwžçùçqadÇu¿òܳOýê*?S]6¡¼¯@ùû‰oìßçÁŸ}ðAöîÝ @.—ãâÈ###ŒŽ\äâÅFGÇxúé¿z+Éü¥ès(Ÿ}Å–¼vŸ(+~jPþ¨Ó¿ÿa÷W>ûÏÜÛ$ÒÂ#¤€ЉòÝ(¬Æ |€ñÏ{ óÞwJ?y‚‚ ®ã„£Áuàø÷žçÏÿÓ¿ÖÒ£/„sZPŠ^ zm>4zß­úwì¸ç±Ï|æ£Û{zééí¡÷¦›èî)?ñüó/ðíï|‡Ÿœz Û¶OŸ¨ÇÞ?ò¾€C‡$[[Sß½ç£ú¹Ÿ¥·§€ôì,#F¹ÀÈÈ#.rúÔ©…ï{þ%TOåËûÞ+WQ à'ò¬¦üJAnç—~ó_:¿øØgAÀÑÚ€Ý@7° è÷Ž ž¯@YÑÃÌ¢ú¬jŸ¿„©«¨ Ä…'NP,B þã¿ûgÚKOÿßd|W Å+å™ Êd[ë7ÿþѽ{÷$z{ûèíëå¦Þ>LK_}õ5žûßáµ×N°œÏŸDëq÷¼/àÐá#ß8xð㽇=D«GK''&¾0ÌÈðFF†áØ÷Ž¿ˆR–9¥¿Š¢þ³^{ŽÚŠ¢üqûЯüŽû_ø¢{tÀmÀ](Åoa¥²•>|þ°’‡ÛªÕ«m}»öä ØvþÍïüªvæå¯h(EOQ  oߟehñ¶>ÄÞwßÏyøá=½7ÝÄM}}ôõõ•4:uú Ï~ë9Žÿà8‹K¹4Š ÔA`“Ëû>2йµã»>ø@ò“‡—Váeèüy†/\`dx˜ááaþ¿¯~õ‡ÀI”Å\¤Lñ} ºHeúnXqKŠßÚwÐþâüW÷¦þnŽ ðsÀ=ÀÝT*y5Å/†ÚW³þaåPµýp\¢äÊR­­ óÍo>Ç‹/½H6»T÷¼¯àÐá#]][¿ûЃ&?ùða¢^TzxH-v144ÄðÐ0çΜÉ?õì3Ïç(ûÏWQŠq™•Š_ÍúÛ€½ÿ¡ßr¾ø¿ý÷è>:Ï¢ßbýŠ¿«¸Ö¿Ú¬DØ]XüË×pœbŠPtáŸüúÏiÓCÏE€ ðƒmÞÖB„Eùy„Î/|îóŸhÚ±ãfúúwÐÑ¡R‰GFFyú™gyá…Éf³uØäò¾ßòzèg“?ü·°,ÇqdèüCç9?4Ä«?|uö¥WŽÿ5Êß÷|³(Å÷¾òûÛøž‡ÛùÇ¿÷ºG÷±øM`€• ^‹9ÔªW³ìá¾Zÿ`à°Öôd˜~òÛ§¨â¶ ¶Wÿ×ÿä—µá_mD+ý#?^`¢fâ^»Ä~ã×~íW>òÑ¶íØ±ƒþþ~:»ºã©§ŸáØw_`q©Î6³¼/àÐá#ímmß=tèÁäÏy˜¨eá8ƒçÎq~póƒC òâ‹/Nž<õæs¨Gt€i”埤œ©·ªòïð·œ/þÁpîã.à·€;X©ìµ¶«ÑÿwÊúK(^QŠÌ=s Ûñƒ®ð¶¶í‚ ¿ú3šDYÿå a â^{ =ôÐÏþ§>µwG?ýýýtu«`ìÈÈ(O>õ4/|ïEr¹zL`³Ê¦€C‡$S©æ?øàƒ½Ÿ>z„x}ôH)Ú?xö,çÎcðÜ9ÏòÔ3OŸŸ˜øeÅ¿ŒSiõÃà)•,þÞŸ¾æüîgoï¾|Šê¿lÔï+¹Ï<Ö£øë±þ ðf^£œ p}Å÷¬¾ë¹þ,],³¢­ÀÂcí(ú¯{ÛVÊ€àÇô‡|ðÈ#Ÿ~ä¶þ[ú¹eçÎ’;ðæ›§xâ‰oðêk?®ç lBy;:|C^ ¶šD¬/ßý‘ý?÷Ѓ%åW¿!Î188ÈSÏ<=8>1ñ Jù¯ ¬þjj/Ouë_Š»üûßþ_ÿÕ=º¿‡Rþ(•J¤ÒÁºÃJ «¶>Î ³V ö»5ú³Àä+Ó,».H„ý×<ëï¿r@¥èš—&¤Ù¨,EšWl ¾ü7®m˜øõCZÅü¥Î:P1•v#pÿÇw¾ó¤†àyä6)%º”´ut°wï²ÙE2Ù,o>3à¸îwQnU]ÞçòŽÀÃGùÒÞ[o=úàCÒã%ùŒzS}CçR´p|bâ›(«7‰ üùsýáçóƒ4ÞþïŽÚ_øÅîà? æñK}TWðZ¥@¬ªÃjÇT+`ìDš èÒSz \¡”_hàxŠî:EOém¢¨> P` •sŠÿìÛîܯÿ¬¶ ôP~´y«wÍÛPÀé>÷ÿñ¤þ£·I]G7 ZR)î¾{?s™y2Y.ŽŽ:|äËõ´á÷¿¼co>üÉ£õõö~þïgï•Þ;91Á°7Õw~hˆ§Ÿùæ¹±‰ñ¿B)ÿ(*·?¢ý9*A ñλ ùšká»øj.5¯E¹kD-·»T‚µJpüpöÍ,)Aè uRô‹ß¦öÀ¾TûÒÝC/·é^ù/ßvs Σ‚«‹”gY&Qñ†ö¹ç¾ñÄ7žxýÂùa. “ÍdxðøÄý÷ÑÒÜ ðØ¡ÃG»Ž[£.›HÞ8tøÈ@[kë—~â>î½G=Ø“žeøÂ†‡.0<4Ì«¯¾:;26úW(kï¯Ñ—¡¬øaåÏ…#¿ö¥âüøñħ÷ñŸÿˆÊ¯d«¦Ðë¥ÿë±ìÕ”z#Ö? žÎ3q:‡-´²ÂkZHéÃ@`„Ú$º'@›ÿåÛ¶b”ò²æ—P®Ç4 Š@áégžùÆßxâõá!•U(~æþOpÏ»ý•‰¿|èð‘òÚluyßÉ oáÎ/8pwòþûï ·˜«Èî{õÕ;tüøWQ7áJù³”-ÿ «þð«£Å'ÿìó=À·ÿ‰õ[ôÐÿÁz¬ø˜kÀ[gm¤ÂSX- ðBT±þ!¥/Yý0$ÌÀ`ø¬ ú-÷2eG1‚o[ŠO<õä·^y凓þoJµpÿý¹}ï­üýÆ¡ÃGÊKÕå}%7¤”¿»wï#á¥øŽŒ 322ÂðÈçÎÉ{ñ…o¢P#¨›Ï|×_¤3¸PgŒÂŸ=—µ¿ð‹Ý·¯{ظ¢oÄï_MÉß®õ¿8 ç‡ÀÖ}å I‚”ž/T{xà À Ág÷ÀgF`ÌŸ~ËD‘ÏPAXÿªÌþÑ¿ÿʹ³gs###Œ°k×N¼—žíݽÀ—¯ãV©Ë& ÷?pèþm]]Ÿ¿ïÞ{KëôŽqqt”Ñ‘F‡Gxü‰'žDYý ¨hP჊¯Šè,|ýGyç׊~øk*)ÿz”»–°p¸‘Ö xc®øË÷hB)¿Pa ð? ymA&ೡW¶Ë5@àO*A`œrL`Ù»Æ ÿôw~ç+###\%=; À½¿—8@<ÞpôÐá#G¯ã–©Ë{,7 öÝÕÒÜ’üÊ=îæÞ{ï”ß?zqÄ{¤÷_{üñ§aÖVþñ[Š_ÿá¸óÈ|øQI,ë±îÕ²é6Bÿ«)y-…_0,oŒÁ¢ÿ x™ß YAª}ö ¯ì+[%`¶òŒ;‰ ¾úL` œôg^.ýþïÿþ“££#\Å.BpïÇïa`àvõ:t¨»ï3¹aÐÒÜüo÷îÝÛ}Ï=R`Û6GG¹8:ÊØÅ‹¼òÃÍg3ƒ¢ý¾òW·úP°Úö¾þݳ¾ò™)úZV~µ±ë¡ý±þ“ãprŠÁ¥~ü„Á@#Z%#Ðôêl@÷Ý}¥±b– ¥­Qï÷É¢R°‹@ql|üGO=õôÉK/2æ¹=ÝÝÜ{ϺUÖ`’º+ð¾“wÝ}ÏC½½½¿ù±èëëP‹wŽ1vqŒ¡Á¡å㯾ò(ë´üÁDŸ’Ïo´ì-ü·o¾æ”£Á½·3íW¾×r Ö²þ—&aP²ò`µÀ@§ xŒ@z€fš¸A¶ + ÐÃnAàx=PþÓ7]:pÉûü±Š@ñ«홟œz+}qt”Ù™ø(wÝ}ц¨»ï;yÛ iš±¥µý÷xwßýÒé4ãÞâccùê_>þM` ¸Hå 8Âôwßóû¿?÷ìç1”òßÉ·^_=Ñøj¥V†^­>¿½ÚËCÎNÁ?1O/'èiR饦yu¿Ýo Ž×@“MhhB¢iÒÛêj+š”hRG“ÞéÓ%š4Ô¾®{ãŒr›á÷ym†Ží¸ç ˜QSƒþ‹E`áwþù?{ÂÿmÛFJÁÝw$øŠ¶/Õ]÷¼m¸ëî{ÿiÿŽ=¹û#ÄbQÆÇƹä1€cÇŽýx ¥ü~`)˜ï@ÔItÝãþÝßù:ÿúK_ìgðィE÷W‹È×RÒ ²j«¶O¨¾–øýÜ4\ÕTlO×¼\{Q£øcjí Ð5.ºÐT]jèR  ©Ú5 ]èª]Õ§It]¨ñZ ]x}šÊöÕ¥P[MGÿ£/_|ò±?¹ì]#5å™ÀuþË¿|âøøø8ãããìÚÙÏGîÚï'õŸßÀ5«Ë{(o 4MÛÖÕÕõO?|çì¸PÙ~ã—gäÂÈò©3g¾… úe©ú_G±s÷ö‘_úö¡£ðÈ~zQÑþ$µéw­¶Z@×Û_ͪ¯eáà á—330í¥ë—ؾ(”Óù+ê~p_†÷B×B 4MíK‰Ð¥Ú:Bj!UŸæõI]Ò¯{ÇêjŒß/%âáGƒ®ÝLxÿÛ ŠµÍú×ñ‰§ž|þÌ™3éñK—Èf³Üµ?{˹Ÿ;tøHïÆî¦º¼rÝ išØ¿ÿÀ?¾egâÃû? @!¯ÞÕ7>¡¬ÃÿÚ_ü5p†ò‹:*ßÝvÏm÷ØŸ8ô‹Î¡Oý’ûè]4£–±ò•´–ò¯V£öµ”ºÚûü-¡ýà9ÎΔOå Ð{Q…êkkô÷+ú}—@ iþV(ʯih"èˆ²Û }7À+ú*Ûñ|½€uË”wM§)¿PŲÿò_ü¯ONŒ_fâÒ%::ÚØÿá;ikoÞ¿{]7V]ÞU¹nH¶´ÞÚÛwÓçöíÛÇNoÎÿòÄe._š`b|‚“'_spžGE’CÖEÌ~{Ç÷Ú>ñ°ó3Ÿüe7b"?E-Ð Õ•¾Èê–~µ¨ýz¬}X±k¹ÕÞtfVMI¿hU ^OâzZ ¾W­OTé×RHU4 )„jÓý})5Õ/…W÷Ú…Pc4ïx)ÕqÒß×Uý?ýÅÙ,Dýw*ÎPrg1·8ôâK/ž™¸U-ºL­?¡þj¬¨Ê D 8X… øÁCá[-ô‚ˆZ0˜$~þ¾7^ÿMK×üëýGüÇßšœ¸Ìää$Éd‚}´{ ŒRg›^® 3z[×¶®O Ü~;¼i¿ÉÉIU.Orüøñ7W(/ÕíYîh‘èÍÅîþÛí½ûîuï¾ï°Ûږн‹Û?|ÄõLÕUÛ+oµöZ…5Úüúä< ‰€¯öÿ©Ñ^-&P­Ío¯Y¡)_^„&”¯¯iÊ·šнvY+¤7n½¢KÄÎ[ïäÀ'¿xU}T)à¿-yö/ü…ÉÉIfg ¸Ý{>äÇê,`“ˆ@Ó4càŽ;þaoïvn»m/ Þâsej²¯<ñW”/õh¬ˆ¹Íîìé·wìpn¿ó>§wG/B €¿øˆ )5k¾«tüܯ¨aV™‡³¬ÌçY¡ÀÕ‚~þþj@<&ØV¼¡å@a „.ÊÁC)ACÍ zEó„çþ·ËÉî{æ!^ ¼,»8O<ùÄÆFÇrSWÊ,à¶Û÷’Ú’òÏ: ØÄr=  ·skç§öîÙSzsïÔÔS“W˜š¼Â‰?þ1pŠ å1;‹­Ý7;=}rvݺßýÐÞ;]ÿFþ3ŠbþòXkEÿkEú7ê篰’x=ݯV¨ ÕöÃ@@HÑÃmUA@–A@xV^JâXÑòÔ3§8 üKÖ7Ý·Ë¿^_¿ ¬Ö~2«Ú«ZBJ„Z¬ªƒ@µ15A hùµr›oé}¶à+½ß_r¼~=0ÍØÚÙÇ#¿òO® #* :‹ŠØ€óµÇÿÁøØxnúÊ:ÚZ¹u÷nâ1ÿÖyl#÷Y]Þ=Ù(hß¾½ç3»>´“Ý»?Àôô4ÓSÓLO_áÌ™3?@åú{Ê-b¶Úñ-vg÷gûM;þ]ûÜöŽM—å›SJÄwù Ô,Àj °QË¿š¿_Íú¯æûÛÏga±Å_-À`@HÁÃÊ[´²kA×@/×e€H5hZ9–t|Ðø¹Oÿf¾«g×R,Õãg .x×céÙçž}eúêU³‹|hÏn¶õl÷¯Ûç6xŸÕå]’u€¦i"‘LýrGG{û®]·`™ê¥’Ó33L_fúê sìù')ül¬6'ÞÒé´¶õ8Ý=ýnÏÍ{Üž¾[ÐTTŠ2e=6Ê¿A-ö±½Ö» P¥¾ÚöjVåɯjùa¥¥B5 €•JN@¹µ*ý+@ ¨ü"°õÚtÿúke°ðƒ„^)+Y@¡€ø»ÿàf#VL‹&ûæPÉ]6à~õk¿>==ÍÌÌUvöïàC»nÁ0t€d}ù°Í)a­}}7?ÚÓÓî[TÞ÷|:ÍÌô43W¯22ráÇ(ŰÁ*ŠhÊN$[ídj«ÝÖÕëvv÷;½7ír£1¡¬¿T7¢o]4/5 _Þâú-ýz£ýl° g‡‚~kùüá²Ôbáýðy @((t4ßðgmþVz -Ȉî·;wÞõÐ\ª­+H,¡@ÀµíµãÇ¿>sõj)Tºkg?­[¶ø÷ÏgÖ}§Õå]“ÀÀöžžýýýýtw«õâ¯ÎÌ0;s«W¯ò“Ÿ¼õ}T’-¬;Ö˜râÉ6'¹¥ÓíØÖçtmßá¦Ú[5-`}´@ÀÊ·:C“dømTPp½ù¬×߯6§_‹úØúõ3Ëଦð× $4n-ž£Ö÷¨Bp†@¬~5È@,@“ˆ‚8ú+¿1#1:zúçÁ*žúß¿öÙéf¼'ûûûéÝÞë_¿ƒõ`àæ“u€¦i ÓŒM¥RôïPYŽmsmv–™™«LMMÏœ:÷H[˜I»1ÑìÄ›ZxS»ÓÖ±ÝéØÚëvnë#b „†¼}I]¨Œ4!¼ 4ÍËNÈ×f¸üCÊ‘æ*|5·ª3õÌõ»Àø¢J…•×S‚™€Á"¼ì nƒ™„á¬Âjƒêº"Ê™‚þV \á]÷RF¡—Aèg jºªëšúÌh¼E»ýÎû3­­Ûò±–6?/€‘Ñ‘Éó†®ÌÎ*7 ­­•ý7ù ˆÔÞd²^°}ç®ÝÕÓÝMßÍ}\›evv–ÙÙk _x°…Ùä465Ûñ§1Ùê$S[Ýö­=n{G‰dLÓ$âÑ»xtG’ÿ§D;Ö¦DU5ÄÉy†Çƽ±¨´ð„ú‚’³ÕÂ¥ëòûW+µX¨2&Ø^+&@h=®k±€ÐÖÿM4]_Î#ÿÂo.˜VŒí=ý3ÖêùÁË/¿1{í…B€7ÝL*UÊ ¨»›LÖMÓ0Ð××wGoßv:ÚTšg:&}íéÙY~üÆO¾/Œ¸kLرf'O9ñV§%Õé¤Z;ÝÖŽn×ÏHCE„ï:¼‡Ï•üÑÀHÀE8µÈqàKÜůÆÖ²þþþ¹åÀ”ŸØ@a•R Â@@ - ~}µÏ ºƒÚJà] ðÛ‚@ ¶ƒ°âÜ:po&™ê,´´´-!¬<à|ý‰'ßðï €¾›{K.#0Pw6—¬‡´ iL6%èíéýO§Ó¤Ói¦g¦/ÍÎÍOÇb 'Ö˜tb‰f7Þ”rÍnª­“TûV-ÑBC>zE½ž àï?ØÏÏø§øTThå}òLž€¯ñö-~µé¼°Tc³‹UèúzÊZÇUs ª¹ÕÜp}5WÍkó®3ºïz¯}ø7 » ¹<òÁ‡ËJÃ]½ÙD2µ$¤Evi1÷Ö©Óƒéks´¦Rôön'âÍQw6•¬nÚ³gïmílWË@3?7çÀ#£c/G£q§!ÖäÄâI'oqb[ܦ¦VZ¶´±eK~¤™2ô•ö÷ö° AÈú Í£ÂbÐá¨7Õ ì­¥økYþj€à¢Þ±9¸–%_oY¬åÛDqþ~Ø  ļëO€‘i!Ýoó‚VÔ¢¯ïbk{w¾¥¹}ÉŒX®iF8ñãçæçÓ8ŽšØÞÝC¢)î_×#ë¸çêò.ɪ išÜܹµcgwWÝÝÛ˜ŸŸgn~ž¹¹y††GOÆbq»1žpbI7Ú˜t£ñ”›hÞâ&›Û‰Å£š&÷Ð <€R,?²þE÷Á9i!Ê7-BÝÄÃjUà—¨Õ¯Ù¯eùkùþáöË…õ¿Q¥¬ÕÚÂñ€Zàâ÷ãª@«œIoòÝéÕ‘[FÜ}ï'tÓ¢µ}ëR<Ñ’‹˜–{ì{ß;77?Ïüü<ÝÝ]´nió¯éÁú’a›GÖbmÀ­‰x´«« )Õð¹¹ ™¹ étz&“]¼‹%ÜX¬É6&ÝX¢•XSŠdK«–ÜÒŠ7Ÿ,;-~Æ;g˜Ê÷õ˜ü~):íÑSM(Ú*ð¢Ø Gá¿ÇYŸ5_oà/(Z ¾œS‹˜^WÔ=¥š[PËØH{Ø(õùž2Ç»Îx³h¾ÝE¨Ý/ËdwoŸÝÒº­ØÕsób2Ùœ·¬m1—Ë_º4•ñ «k]ˆòkä®òÔå]”µ`{[G×®¦Däóy2 2s\ž~#‹;ÑXÜ6&Ühc’h4áÆb)âÉb ÍWlàç©Lè Îïߺ?ÅðoT:*à»ú}c*ð*µ-ýzýþZVß—X© 7º¬Âíáx€_¯u\E B+ƒl…ÿ_eJP Mú@á·Š úw ,ÅãÍNª½sѲbŽe5¸gÎ;Ÿñ^*jY&˜‘ˆmï«qÍëò.KMð¢ÿÛº»·ïLµ¤èèì`!“!»!“ÉrõZz0‹» ·!–¤!–t­X ±D ‰¦ÍŒ¨›å£{ØÜBõ(¾÷%¹?eK²jðp‚Ú¾¾/×kýçs*i]Á½ZeµãÃç ·U˨UÖbÁq%Få]W‚Šï  ýsi±B ]™/ ÷í`IѺ¥c9o*DLK<{v,“YÀ¶m:::ˆÅJ\åw¨Ë»(«1€ ÞÒ’ìnoo¥£­€l6Kv!ËB6ÃÔôì9+w£±¸k5ÄÝhC¦'OÐØ˜ÄŸ?î‰ó VOçõÛ~coŒãù£hµ}áIø+àuÖ~`½³Áýñðçùߣ–ÿþvǯ¡6Qå8ÁÊ8‚LiœS)ƒÇ‚±¥XL8À jG E„n¡míº)×ÚÞ•kJ¶ä͈ÅëožËfJ‹†¶u´‘L–\ÿú…7‰¬í@·e5D·liŲÔ4NvaA@&3Ž4£Ñ˜6kL`EDcI-oÒ,˾¯ |œÊ`]‚ ûË;-¶ûþgا·¦á[ÀO¨®àµÄ¥¼D—/ÁýùœÊo¯N¡o Õ¿ž1°Ò¶­uþ°[tJl ü»)wA„¬¿ï6 @±€ìíÛ'ZÜæ–TÞ4°¢QíòÄĥŅu3µ¶²%Õ\ºà‡9¸ÊoT—wIV€.`‹eYli-er±¸´ÄâÒ"™…¥ñh4JC,NCC#VCV´I@<©ICÝ8Ým4·³ÒÚ×*–„t³¤‡ý§J™QKˆ¿ÅÚSzáýZ€q™ÒTûÜë)ë’pÿz\jǬ $䄯k¾¯ïÓÿ ï/ÊÇk²è dÿ®½ËR𢵭k)9 “±±±K‹KK€z­xë–-Á@`l© š¦E€¦¶Ž®žX,JªE@.—ciq‘ÅÅ%2 ÙóVC̵¬‘h#+¦VL³bšeEKsÌú¸ƒÕ¿Úô%á·zaÛzèó,|õ”^­`àZâß•Ïúפå7¢¬uÞõ|n­'W;¶¦àßíòúƒÓ°ç <]èº*'@šh‰æ-v"ÙRŒÅEÝ´´+SSÓK‹‹¥‹ÜœjÆ0 ÷öuü.uy‡E¯ÑâÝÝÛwÆcq’ÍÊwË-æÈårär‹ä‹…Ù†hŒh,ŽeÅ0­¦Ó,«Q˜¦©yàfÖÿÄ^p‘ðh þl r‚Ê÷êù;@¾ŸTÇÝ´Îÿ] mA­/aujt#D þÑõˆFÅÂÇ÷ƒãVû\Û\ÍÞ9lo ª^N(/WŒŽl¶õìX¶—ÓŦdK'Çää•«¹\®”IÑ’lÁ²,–óyPoªË{,µîó6€ˆiFã‰8ɦ&ryr,,.[V ËjÀjˆk+®‘¨fE4Ãð"É*š|k+~-0èh…_)@Z“ú¦UŽÀñÀÿ±ëïK>ç=íw#iÿjeµÏÙèwXì+ßÊÏ  ²¯tʰmdÁFöôîÊ[ÑF’ÉæBÄ´´tf>“ËåÈås$’‰à“u`H-hH45u'š$ ò¹<˹<¹\þZÄŠbYQL+ª™‘̈¥fƒfZQE")¥ÿö²Òÿ¯•ÁW-zß–‚¿Ý ¬#R>¯ÞAèç ¥àÂTw•ZÑýjcký+fÄʱ~»?œ©ÈôÇ¡fl‘jµl¡é"ÙÜš7"–f™–6=33žÏ)hJ4•Þ‰z{P]ÞcYš¦@#°EhñXŒhT¡öòòùü2…BáZC4ŠeEµˆÓL+* 3ªIÓÓ’õÊݽlE)îj©»k=Áç­-ð‹QÅôp¡ýŒšÆûjy²Ò¿ª÷‚ZßnŹßéþî×sLp_[ï±"T÷ Zà…¦Zè¼}´òKG]ÝvTIµv“É»1/F"¦¶œËå—óêÑàxcŒ†hCé¢×gÞ{©ˆ1 %uI,ÖXê(‹,òä …Ë–Õ E¢1Í4--bF5#Ò tÃR—ÂW­Îí¬þ_°^kÞÞßnI§ÓðTA­:¼ªd WL`·÷ÿøT~¿ž¶&¿ëR+°‘8ÁFÆ—â°"à·Ç ¶×æ¿–(h9GÅlR­[‹™ô%Dz¢ä)héôÜL¡¿ ‹Ñ‹Q—Í#µÀRÇ v¡P X(à¸ä"VT³LK‹D¢š±„Ô#B7"BJ¤†ºIR{¨íﯦøµ@ •„_¶áÙ´z[í ñofdaÑ€“&ìâ¬T~ÍV/ºxO”#²ž _x¼¯¨a`ðƒx+”ß—`Юh*íoëØ ZZZ™xÒiŒ5º β(ÚÅ|Ñ[¤¡!Jƒ ~ÊAàØþ¥ºÜ`©‘¶Ž®]RÊ`ІbÁ¦X°r–iiºii¦iiºaiB7…4Lº£4j[ÿõ>¢.†„‡’ðí9õ– v0£n~U³~BC *нé (¾µ¯ ÕØ@…‡E+¿œ°Ú873r¤ü±®«J²9îFD4ÄâvayA››››)¨{˲°¬BÓpÜ@Y]Þ)©¥·u)±Lõ‡c;í"¶]ĤaZD"¦fDL¡ë¦¦éÍ0 á[OvR;ú=ÅCÂ-ðýY5u·¦,ÂpT­1¸=Ô5Gmüx×äíºu Ç;Þ·ü¦uPÑÀ°8ŽzURC#®4 ­)ÞTÌeg4)¥V´U(FˆDL´ ­¨Ë{*Õ áW¤†2Œ¶cã:6¶í K©™S¦% ÃÒ ÃèºÐ4¶«)ózÁ€*ç0€·Àkiõâªü2‹p-ª°ìEY|· ^pñ¾²þkÉj®BðzÔ âöƒÕ`.ó¸@K2eÏÇö쌩麮¹NYÙòÊ@POzÏ¥¼'M˲4!‘^æ–ëº8¶‹ã¸hRj¦ÑL#" 3"¤aH¤áèÒpêÞó¬D «Ç`mÅ_+›ïŽ$4Í«tà5%y Ct¢VüŸ2Øö*®AåÐêãpåà€iYZc2é˜fDÌÎÎ^ Ò}é-é€úTà{,a`áÑáÖÖö51ìC¼ƒ‹ƒë:†™X–0"¦Ð SèÒEM /q$ȧ›)¿‰w½Ôß—jûáºoÐz`-Â[våÔ_UñI¼l”§Çêr%žHºº”2bššc;ÂuÊA¤ì 45á6%šÓ2„Ô,MÊr˜e¹PÀ­û›FÂPòÿÇÆ.žíííݹœSi÷B¤®#¥DņˆaHÝRº£Ò•Ž„¼w¯”ßÕhþj¤÷>T+Ôhº¥~€0^€)–×ùÞU©¥oÛ:¯ó`'P/mœÊ1¥j•_1ø‚MÝÐeD7¥£9–ÔÕmfÛùå|= pI*"âÅB\®Ìž¥”†ÌÛBJ)¤GÂñž9_‹¬åûoDÂù.a`¶Xl3`.§rÿ+Ä[³â}#ÁÄ›Õú×j+‰«æñÝãJ€ŠÔøéÈš§øÒ)¤1„Ôd³.U.‰¿–D@FVûJuy祦 ÇuXZ*/éd&†¡cšº†& ]:š.!5G÷ç ½›ÈUwÑ<å'ñÖŠî¯kÑý õ·©dN`?ŠZøcÓÈz­÷F‘ÒWæ°Þ–Îå®rNŸ T¡ÿþŽ "¨øÞj#¦a¨@ ”B7Ôm¶¸¨Ö“ ÈÅ þKu¹ÁßRæÁŸ°KË:DLÃ4(¤çÛ ©J]Úš”ÂÕ„”4_ïËwU¥pkÍõ‡e-ßßÿ¾ÕJÐeŽó§¿ Ô˜ûßl,`£´þºÜ…j àVŽsâzYÁs(‹R‚ÔÕŵíeS€n†1ð—”¯Ëæ`vz[ýÀ%šš?ã¸þùL&K6»H,ÅŒD0#t),åRj¸¶®¹²BSñ‡ ˱VbO50¨åûC¥¢‡©5¾ô𜭞Y‘›EѯÇwÜ_‹%}ýŠºSVôÒâV"vøWôÓ}êï¯?&)tiRX–Õê¿(“Y3€4uyOEøÞKßÇ0u eýß_n&3§ÍÍÍ‹E‰˜&–i$ ©é†®¦K WêhBàÚ>ç¤ôðM[àóªÝŸ«øÂýÁ§`Ã:\ ®²VPîAM×g³±_ª]¸øÿáñ>}¯ & ³ë…[$4tÏúKÐ¥b†!¥iF¤išÂ5øüüC4óf õ“O€zh:¦³³Ã{žÛBƒ„šÔ$®´A—¸Ûó=]ÈÙ¢Šl¯Eù«I5K¦úÁ¶p¿¿ïƒ† ާ߫)ú»«Yÿ·KÿÃþM–à)tÅT*¸K• ¾Ó“R=Ÿ­{.€ê/˜†!EĈ4™Þšé¹4‹¹zJÆfàÔ§XÌÍùJUô¶y×ÁÎf3úµ´bj–ÅŠZ¸8)©ëRêJù`€¦8NλY¸0ÁÕ–îëŽòÃú¦ý¨ÒTúàÖa¹ÿï4lDù«ÍÝ»UÆ®çB—Ƈ|ÿ ð®”_/í»ªs„PÊ/%躪ÒÅ6 Öe––”J_K“_.¯æöܳO[ÇW®Ë;(:À˯¾L2•ô•ÈE¹d2s—’ñDïìŒZ}Ë´L¢ X¦iêR“R WèšÀhºÄ‚ÒÍu5Í2Ýú>k)|xßû4 Rg«&yä¤"Õy5%§@àLƒY°øÔß-Óú`Žf‰1ø}n¸Žòÿ C)¾€®á˜RJaZVÀv®ÎΖ˨ûÿ›B|eÐÒ3iÿ÷-z…¹ÌüÕÖÂâöé™™’OÞÒm$=3ÝÕ±­å’&  ‰¦iådjvͤ›j|VÙ÷ëá¥îV³ú%°Õ×’Áû ëQüë±þë¡ÿUýÿÐ_iœ¾ï ®ð€¾â†WÔ!º.„.¥ljŒª5g®Î03=Lªûÿ›@ÂÓ€þºýEÀžº2±½»çŽé+SÒŸ hŒÅˆÅbd—²)©3©iÂE€tÐ"Ž.Ô›büņ©Ö ôYa *xx ÜïoWSú ò;€(®üŸõkŒYK®Gù7"ë¥ÿáè¾ã)ºëÓ|¸¾ÿPüpÐLtCm é­&f¡°l†mðV¾2=ÍÌìLðëÔ`HXü@°§&Ç'÷Ãîôô4—®L±³¯W-푞ŸKI©éB!Ñ\M·qLwÙƒÇÉ,é®X<¨èþ̃å÷Ç®GÉ+,}hë†íz:¼ž$ƒjTÐõ€ÁFºÚØZÿj?Âmaú<>@œp úÿÞ¾@ÍD|å/½ö\ò%æÀÔäéô\ðkÕ“€6ÀÿùmÊnÀU(:WgÒ\½<© §1Ç.äÛ¤zU´«i¸RÑ@ÍÔý,BuÂÉY²]å¥à«EõÝP=œÐC•íª–ž•໹z0Hvü¯Gn¤¿^å¯%Õ¬50ûöu7p±¼úy>#¨`Žº~¦òÝd:Žcš‘H£¿HÄäädERõåÀ7…ø?™Û’H:³óiŸþ/£XÀ\6—_Èe3-—&&0 ƒxSÃ0cv1×`XÎ’ÔÁuÐ 'ÁÕ²åedœÌ*XËǯEóÃJÜÂêÊ¿‚xËÞUÌTcïT௖lDù¯Çúû}%e÷)¿wBŸþ-½ïß»ºÏ‚ý¦§ø¦f"å 5 CÒHd³‹\š˜ð_ ÀsÏ>Uw6”0»¹µ ¨t`pf&§‡[bÍ—Çǵ\>ešÄãq‰&f¯Nµw'Ú/!tM€iàF ÈåÁ-‚zßö|¬¼ÜøjŠv‚ma…+y°t1|ƪzXÁß+¨eÕkùòµ”¿šÒ¯üó·~ 0ä«h¯R‚EÄÓTOYEô’ÿÏb.s§9Ñ¢~ò±Kã\ö ˆ'Çjü›uy—¥4 022â'Ù((ù±É± =½Ûï»4!ÇÆ.Ñ¿£¦D’¦¦W¦§»ú$“ŽW ;bâšärek12ÅÜž¶Ò›yXeë׃Vª+xßÿþ¾ÒW€AÑX©àµ@Þ X¯ò‡ýþÕÆ¯eýKÑ{o ¬;KïµWøý®ZÆßGRÇVi¿VD)¿©ðÿ5×.D€TÜ{©ìØ¥1¦§+€/Ôø—êò.KÉðVþq)3€,¬gÕô.ì ÛÖ,n î½èÆOT¬ÿ¤¾ÔbAYr¯&Õh}µ€_°½šKP‹ú‡ûWeŠªl IDATX·ÒŸº¶Øý~ ¤Ë‚hÄs"×/V,“[Rê5Œ#F¿üJO®òuëò.‹(ým×®]Pv–Q »Ž}i|œóç/Ð’j¡¹¥…ìB¦]J[×¥£=b G-dCD-!h;HÇAŽLµU4^³•%®Új®jneÑBÛõØJ@:B`ë÷j'Ðs#J­ó:¡1áöð÷vªŒsC[$Òq‘®‹tu§J»ãJ1Pw‘Žt‹j|ÄT¿¯e"£&2*ßÃqb®ë¦„—|~x˜k³/r®ûÿ›Ht€æ–ffg]/‘»ˆ¢ÿ9< °sÙsyǶg¯¥õóCçµû–T ˲¬Ùé+ÉÖŽø<ÛÇŠàZDM˜ËªK¦3¸ó,¶%¾ºÂ‡,™ßôý]Qiåa¥åFÿƒý¥€ k³Bã6*Õ¬½/µ(°/lùP½&õ§L߃‘|‚VÝ£õ¥  Ú*øgU›¿B|ƒ QK±Ëª ÿ2—Ë5ÆÆÇ'ª˜þ£Î6•è©-[˜™åÌ©SþýãƒÀ2Ê X¸21öfwwÿ¾ÁÁA9< ¹¥\sKª€³ƒƒŒŽV$ü|îÙ§FÖ¾:uy·DlÙºÕß÷ï'?˜ó¶ÅÁ·†O»vAç̹³ÄãqR[¶¾6Ûn(Àˆ–rô¨…nEÐmÝvÐG'Égs8®ƒ°)—Ê}¿8ªTÐx¿=°•~q½m`¬O›u@÷·N`ëúü~ªôߨRíœn~‡êßÛ­r'Üî ;.ºë¢;^ÝqT±ÝÊ}×QãlÛ¶·_TuÇVçlð~×ÒVTü/¶]lµð¹3ç¸:[±þꟿ›µ.7^@[*…—²©%’->XF-’–ó…ì¹åB!“Τyëô2•Ö¹¥µ•d2©ž9Ý!%RW/Ö,dƒ…l´R(Ò±‘gGÈ]´¢­Šã¨9ú@ñß?fP-N ƒûïÿò}á@¥M ÿ»Z| KXO ·Zœ!§¨åó»UúÃ~É×÷|øÒ6Ôæºeß¿èûüÅrÜÆq‘EWíÛ6Ò0±ÀïµÔ*`Þÿcäóùæ¦DÂ8sæ gÎbÛoúÊ»uër#Dt´uÐÜœp·u¶y/Ï-—Q€0?66ú†c»öà¹!N> @Û–-´¶µ259Ùj CǰtŒ¨Y¶–Yf&XÎ.âÚÂv¶‹°mUw¥À!& EO™‹^Ý++‚gùußúÛ!ëHÈ¢Vcþ˜j¬ 8v­>®Úy«Yòà8¿¿ÚxVX~—€uw•u/1b¹n;èEGm}ËïÚŠøÖß®fýÐc ªÞ +þ·èÂÂBÊ_ýç'§Ïpi|ÓO¨Üÿ7Þ|“¡óÃÁþ‘çž}ªýß„¢‚€Íítv´!M åûʦXÄ{Døø?ç€6zqŒ7Þ|PO¶µw0?ŸnÎf² ¦@7uEcÑ20d™r³l;eP´vÑc.²ÄÔ´pœýNÀòûÁ¿#ðiÙ'VÛÖ?lQW£åë¥ø«S­¯ÚgÛ‚ÌÄ ÕWXþ@ÐÏ3ßâûÔß³ì¶]f¥m(hêê÷‹EÑ­ªÖ?îâ6LMMóúo’NW°ýºõߤ¢lim£g[­Œ+¿Í¥2` 0 …ÅS…ÅÅÌ"$~|òMîØw»wí¤cëÿÏÞ»GÉQ÷¢¿ªÝU]]ÕÕÝóèÑ<4’èaÉ„ÌØÇ Ø7ƒ¯o 7'q®?–s’{CL;ÇÁCV+ɺ+ÆÇ77NrlçÆÆÆÁ !IHHŒf4HÌ 4šÑ<4£™î®êê®×ýcï]µ»§õ@ !‰þ±Šª®ªî©*Õ÷Ûß÷íïщ©ÉNô÷êØ¼y󩤌ÐW:ýí* ,OF§àç[f „Y pˆ!›Àٲ没Ì4äX `#dÈFêh€fÚm¯)l[_L°~Ÿ¨ˆßÑhD?68^Mâþúíš‘?dSzl皀Ïâøýúé?á³ÇFû€ú>ÛÏÔ-SŒ4ýuÀ¨ý%×uÛ2,ñçÀ+¯bhè5±ô×€'Þ£jâ2‚ú:ZÑÕÕÎ|·xŒ›œx`Õ?4°@øÆÈ^9ð ªtuw£07—qœªF€„F0R ¦b¦@Œˆª‚„,ªìØ(ª>ù™@ö}×‡ì… žÙó˜6ÀµÄ!>ˆÔø¢é@îðPë¬÷¸ <íâ¾úàm,õ¿báµÕÏPuçÖ/óÖûô™rï¾ç3¿Gñô9F‹Ç?ô»ÜÓï{ì3ûMC1túïÇR;›¡;Ž“€‰©i|å fN×dþ5W0dhkÏ¡kÉ,]¾ DQD‰AœÊ,¶Ï›š¾Z©”ìrÄ¡~êììêBWw7ìß—¨š¨+PL 3„©ÓEu4ŠNLÀó}È®ÙsA< 75HÈ…ÞƒìtZÊã/l½¼‰úù¦B‹Û Õÿz³ þ8òÎç<×¹çSÿ믩Ñv€X­üXíú\¹Ç?RéÍýû‚·ßUÿÀ¯uü™[tfÎÕÎû+¾ï·™&µý÷¿¼‡ë»ÿþÑ¥{}›x» µ¥Ëz»±zõrܸb…xÜ%®Ø $P<<пF†cÿ¾—áûdYFwwÇÑçææ Ô~4SHdÙË”NÑÌó‘xsAÑ¢¾ù\ª_Ð?¡ä0F2F Í‚XðýX`H#jD84²ýÏG óûç",Ÿ ?zÁæ?›ð‡u‚Íí~Ͻþ~Ý ÿNf ‰ #nS[@vºïº?1Š—÷¨û²ùweC"ËXܹ+¯¿+׬iPFßvï¶±Àb‹ ˜šÛẫê8ØàìÙ·ïÈ£§§‡ÌV‰N2ÕÒiF ÙK92†€þÄe‚Íמ â{H¸±úšð˜àô…æ*+}yCrL`D" tDp¶Ñg9÷lK£ß8Û¹õÇŒú ÷å…ñ¨ÎªÁ9„ß«~ ®_³ÅÐjÿÍLƒ’9„Ñß­V[ø¼ÿž=ûpd¨9ú_m =ö ¥§á86Ê¥r ããc~}$Ì·u„vÙ’As>ø’àY¥²ÒÙÝ}c©X„ª&±ò†ë¡§RH%“˜™™!"›Ë† 'xf uV®ÐµïABHzŠEò…qF`ÆŸÆ™R9” …!ä0¤Ñ~èv²múÂöH±-¡6"¯þsˆÆv»Tkÿ^pD`½O¡Þî¯ß ÖÞ‡©Eóù¾Úï¨ ùÌ\ò„ãÌ~Ï£Çøç¤Òb‚´f@Z2 ¹ HN]pï!$õãéÿ£cqÙ/ß÷þâߟþá?^ª·‰\†/‘c[U V¬\‰uë×áÖ ·`íªµ€ Ü{ßVnT”kþÔÔØN˶§]ßÇ¡W ï¥½Ã4ÑÛÛ‹‘‘× 0-@HÖ ‹i€d ¬N_&Ï™˜4W€ì» ®â»Ñèk Í÷Ô)9°|æóø1z<°V.T^ü œtïäÒèo4Êe »Æ‚‘Ûæ÷~.á÷سñëœÑÂH@’@Ì4ý7J³«lmÈ/ Ø¶m´àg_ß^¼><½T¾ï•¦§O_ü[ÙÄeÙ#m¤„U8%ÇB¹TÆÎ/HªªH¾ðšzIP¡Vøc£öŠå+n±®ë¡««ù|;2Ù,lÛ–FFF”Å‹ûdU‚ì:§Ï"ýdσìTéˆm9Œd"Ñc! â#ù‚}ÑÈÔíd‰%È4 ðãt?ý¾ðŸë÷Õ»%hðý îqŸx,Ø=Ò0i9 ó˜ŸæÇXÜDà±ø >»ÒgE]zµqžË>{ô:riÈ9rkr‹ ¹%Y—ê®? U¥A#۟߉gþýÌÍÇ5ÿÏœ™ýò—_úé¥zi›¨ÅÛÑõ;–,¾+WœÁÄø(ÆÇ§099Ër\Й€ ¨`HHø¾½wzbò¶|÷¢ÕƒCCò »vcéÒ%0 ½K–`p`€LŒkÝÝ.dÀ3Xž¹¸,õÔvè”ÃØ$¤Å‹ 'B¾ç2a•AÀ—iL€Ä2ÿCÑ}ì3EC) h¢Ä¿ ‰î êž8ß_¬þøùPÿýð,ÇáxT?ˆsú£~¾?dóöü³õ„q$ßçû€ïÆóüžK×>ÛCÀL™43ŒdLÀ\x³D–å¼öÚ1ìÚµ“ÑAË* ïÛ³ëëoá5ñ.b˜K—-Áè©•Xvì8Žk -k\B¬’@’}Ÿì?Ø÷Ãû}xeÕÚ×·K{{qÿý÷Â4M,]²ÃÃÃJgw7„@N§/Ÿë^¥8`—±iHÝy@ ¨€B¦/¿$³h X0ŠÌ÷Ñã4ˆHFÔÜ#Ä¿!‡€/±Œ0dÐÂ%b˜0G½ ðü¶s ì«'Qè°Ï‚àGÛõ‚/îca¾~@·}N L¸?&.ü¾¯]öC£ŸKYƒ’@VA=¤jµª¨ª Ëv°óÅ]8êA ©*­òüÎç±{wì²>ñæ›ß›™žøÞÛxLM\f4$€LÆDK[íù, #ªà€jé6¨à'AI@àLMŒ½P,\¿6—Ë]wdpHÞ±c'ºº:ÑёDzeË`Û6N?!-Y¶µ!‚tšñÖ/X¸ŸË¿ï…ñïEÙwü³Ç®ƒÇâ‹¶»WwââÆ÷ëyñóáñý®OŸŸ×Hø …?g¢¦hc=FÇÆ°ý¹<2T£ú?÷ìÓ àÐE½…M¼k8+´9ä3èèlOâZ@TàÓ‚¼~àè+ýžW˜ŸÃÎÏãgÏm@ˇ-_¾GÖü¡/]‹YKD¢/jÑbZ`®ðbGûÙ €Ÿ°Q0âDàÕìé¨0¦ È¢0GKý>!qð|¢zÎ…>cçx >ö:"pÏF‚‚ã/z~n,ü­Yáù§©fVÀ÷–mãÙŸíÀž½ûjêü?þÆ|¯$5ñ.¡¡ fk=˺ÐÓ» =½â,AqPÆÖ€=51¶czªûúŽŽÎ5£'Çðì³Ï!—ËaÓÆ[Ñ–Ï£âºèÛ½·oÞý­V€«Ê\í.pŸ@™KëÔÊT•eÀfB–ÎDz©ÆJ˜êÏ¿RU_L 6¢™°v-5?n"œÁ‚8m‘›@¬âómnœÏéÇÍî ˆÔN\Ã`dÁ=ÿ¾O yæ²ñˆßš¡ÄÛÀãOo—•ø~æ™gñüÎçQ,–¢c–U|õÏŒ5þvW2ȹæà D¡`afr ¯¼ífk T虘ÑÒ©SãGº–ô¾_I¨©™™YTíyäÛÛaš&Â0ĉãDZ¨³3ú[IH ^)^{Pué íz@‚ 4ïn9Θ@×çýâBá@ܱàIa¼?Ï c[<Α™u ÏׯËGP×Ùó\УÔ]®upS‹?Al*xñ=n¶pð⑟ût hÉÄ þLá‚cÓçž{Oýä'åÜ÷½Òögú€gAµÀ&Þ¼8€s@6kÂØ%Ó§1=3] ›”‹ˆ@eŸÝo¼qrÅŠ6†€4=5%ù^€îî.d³Yd³Y”mo¾ù&: H UfBF’LÍI¢/¿W¥k×CÔÞG,s-Ž¨Ñ¼9»Èȳz^(®…—ŸËËh7"þw/t…ÂvÍH.}Ô~K0¢ÏAìð<ö™ 0ðâuÀ}$L[7t %KÕý3Þn$ü"áïÛ³O=õc¼öÚ±šéÍíÏ>óß‚ÀûŸ¼M\>\2$äÒiàzULLŽ£0_¤Õ£à$`Û PB(LO¶z{zW{a OLNÂ÷,^¼é´\K lËÆäÔ$ÚÛÛ£¿˜"€¤2` ‘¨0U¹Šë!ÒÉ£þö¡àœ„œŸƒ:²à €:mB<u„ ¿àÅ›×àœ‚†çE#~°PðÅšý¾W«xì¸H¾OŸaÆ £}‹ÉFÿ,]§ÏÓíäà¡~üè‡Oáà«ýÕêÌôäô‰Ñãßuü…gý&.9.!j2‰t: 5LÀ“Bœ™9¹ù ° ÏI€›¨TÊ£’’himiëq]Wž85 ð±dÉèz -­-(ÌPqÊHdz Ðd€¨T $K˜jÁÌ>ß-I±`saâô Vïx-nG£ïçí‡#Bàö· YÔ º$Œø¢ð‡!öz¯#.ô~!Ô ¾ÏŸ;£Š>~?~ÏÔuîñѾ5Cíÿ–³8üD âG?ü öíß—pÏ=[ÑÖÖbx÷¦Àó¾[²-ç?ÓÄ%Æ%%H§Óȵgah)$Ží`jz Ÿý¾—^âZW$k’FfOO¿–Í´-3t£­âV¤‰SðüK–,A*¥¡¥µ§gf03=VÖP’ $©à™­Yè.÷ ÔÁä…XˆX˜ùHÎ}‘}.œ°ókÌ„ºÑÿlÚÀ¹„¿Fà×˱ç¿f¦BX‚zÁgÛÜîG|® €žl}Aåo5¨çö\ÂôcìÙ»U×öèÞmxÿÆ÷£«§Ãι3³÷žÿOMx÷pÉ Òi­™6è)I%‰P ñÃïý ô€‹–˜0"!öàÔ©Ñ×ÚÛ:WjI-W®885~ žç£§w1 =…\.˲qjl íù|ô7ILø @%Ì$!T}@PíEçë´Ñ4ˆbñÖQ{-ÄçÓX'ü\أؾFy1>Û÷°?|_P÷…)EBB²éØÁ':ýZ4ú\Ï…!üðGO¡¯oOM_¿»î¾×]·€„tÚ@OO‚³gfï›$ð®á²mù6f É„ ¿ œœ ÏçÆ!7x}MNÁɱ7Úu¬Hj©¬ã8Ò©ñqT«twu#6Ífá¹.&'&j4:gMT&üHÈt›X øˆŠÂÉ7òÄ3Ó ^ˆBmƒx;2ÂÚýbSMN$õ‹‘vQøÃXð#3F ƒ(¨.œW,äÉ}"Ѩ¯Åñ-éxš¯%äçg>x¨?zêÇØ³goðÿʯüÖ½oÇAµZ ÁHXÜÓƒ°Iï*.€®ëh5óñP­–qzzÓ§#'0z Öø€ãž=1˜Ï·\¯©él¹âHccã°2òíyärÙÈ02<ŒŽE‹¢¿) UFc-@‘D‚’Ħ ]¯Ž{Ý…Q<ú\O„=¬v v[Øú%rD†± /n/Ð"ðýØ\Daj?T~ß§¶~Ö`£#ÅÊwë4­×L³ô^åÂ’˜vìxOÿô8RÓÏïñ¯þ)Ö­[³àü™™ض I¢Qžwo»Ö?ÿÜŽí¶~÷{ßÏézêK†a,Këúœ–Ò¾½¨££Ùä ÃE,^Ü%Ý×cå˧¢”ü*hh0'®HL¶žÛ³ûù¿Þ´ù®ßjÉe–Øå²¼ó…](ZŠÅm¸ýöM0 +–¯ÀÈð:;A7bµ U’­±àkIÚ§^·) ”Àq· „FíÉQ$`½à‹dÀ>"q† IS$T¤+¨YÕPçK¨'ƒ:áç ?øô\BÓˆ;õ¬k©Óý¦v~GØŽƒgžyÏ>û,†_©‰ïÿíßþtðçÛrâ]aff–e¨%ɉ‰íK—.YÖÚ’ËžžÁ|±ˆá““SO&ÊçÚÚZše¯Ha¸`¼º`Á³ÏmǯÿƯ± Ðw/ *ô&€ ûœA\Qȼ}óÝŸÎå²KH„ÜxÃJlûÐV|èž{ ªÔr˜š˜€ãTÁ³EøŠ.ú¢ XP²²Ã´‡i>nB'µ v›%ÀE!ÃQ† Ç9 ÚL Aàùñš™ éù?!4”×Д¤5F©xô7ä õÇÇ'ð̳Ïa玟˜¨9öÐCÿ [¶lFww'4µÖm8=3‹ééLOÏàôÌ ‚ €aèÐõRš†M7,ø[ƒC¯AQ†~P!ÊÖŽŽö& ¼Cx;2ü¶Àu]ôõíÄ?ø!q7ùS Z;'NâZæ†õ5ßݽF$™HèêìÆ]wmÁ=[ïAO7´- S““X¶|yÃë¨(V˦B­º.;´+‘Ë4[‰ }Dr¼!µ¤@7—¸#¨=7?Š@ Pããþ¹ðË2µñõ$z- ¤˜ œßÃÏqèP?¶oß¾={0_(Õ{è¡ÿ„ÛnÛ€6|¹PX¾lnݰî¬óø‰pÊic.©([-ê8x—ÛÄ9ð®LÍLaQû¢úÝ<,8‰˜LYö9ÃŽ+ÈŠÖ¹å¿ôد‰ÇÎE®ë£»3]}}xyÿ8Ž3mâ“=Ó\oèú>Â4M¤t퉞®®Ï½…Ûh¢W"µ9bM€.¬yµáwmÛöp*™ÎñÉçÛ±iãû±eˬ_«—³3³ð\g½®*Û§£>'‘ªnLU¨ð""‚@Òûc7$˜üφÈ@”˜$ôˆ( ú¤BU}5I·k@¥BŸÒh¨ô…ªúàT«ØýâKxa×.ô÷÷òË1;€ëÛÖ³Ï<ó$€WÀŽ|⿺åÑ/ýá‘Àþñ“ÿ) Œ‰T– üÜý÷ãæuk^WÿÀ TUAZ7v(ªòà¢ŽŽ¦_à"p¥k ( ¤“_x…áH[Xwëæ‡;ÛÛn‰L$IUÅõ+W`óí·ãöÛ7¡»;6¦&&2 ˜B.A=|°þfgÑ*Œ\bñãØžw Vç8ÛDa±³‘0)P4–AI°iM¥VøU564åÜ•zΆÁ!ô½Ô‡=ûöaìä‚Q?(Ì͞ؽû…¿ð:Ûg‚p=ô‰OÞñè—{D”žzèÛ³;vî„ëºð}žOŸÞ¯B¸}Óm¸wÛ= ¯oxä8ÕLó¸–TlúÞ:®dj‚¸9ÀSØ5dGg϶[Ön¸OR€LE)—Ëáæ›ÖáöM·á¶Û6B×ÙDW`bb­ííàE+Ï€Õ*àpá¯R¯úBù1W¨²#ÔÙ‹¢õÄ9Ññ'L#JfäXð ~… …®“ ÝŽâ­¡AqÎ ÀØøöì݇½{öൣ¯ÃqjcsBßs¼vä¹ÇG¾` ´Â“Äþ-r`ÿn}â“w42–/ëeµ_„S­ R©Â÷]ø¾ß!2!Xqý üê'jx­ÇOŒb~¾Ó4çtM{¤«kQ3^à-àJ' ž"ä$ #ö ðµŽXH±óº6m¹ûWrfv‰$3S\’ÐÕÝ ÖãÖ[7àýn!ñ8<55…––(Êù•d´ŽYUÐ*,¢—« Ëæåëmúr,ø<¨ˆ'4„@|MBÀ[ð3Ö`vvûöïÇþýÐß?€¹¹Z­: à—Êöô®çŸùG‡L˜P@¬ZÀþÝ>A5ˆ<×Åé™Óx}øuØVŽãÀ©8¨T]x®‹ hLÙlŸýíÏ@Ó’t±háØðëÈfL¤týzºº»ÈGðžÃÕ@Ü1¨€ <'Q Ð!8Aµ­k6¬¿_C‚GBQè]Ü‹ ·ÜŒ[nY›o¾©†æfg¡(I œPgƒËÞ³@$¨‡¼Gbw*Cý%*üD¢#}‚ ?³ç/f”17WÀƒ¯à•Ñß?€éééHÝçQZ!‚àÈáÁŸ81ü4h ¯yÐbsìTÄS¶õ ©ª0Mã_Õdò‘Žöf¼Àùp5÷ Hˆ5‘Äϼ֠–žõë7ÿBgwÛšØOý‹{{q󺵸馛±nÝÚØ4Pu‹E´ Y†o>[< ¶\bŸ@@oT˜^¬o¬w±£{#LMMãP?^=ÔÃG059Ygçð„Åbá;]ÏÀ¨ÐÌ8½ÉIÙ®5…m€ô¥?þãŸÿÅÿâÏ;ŽƒJµ‚j¥Š¹¹9ŒžƒmÛ(;* H ¾’ H‚„Bðsÿá>l»çî†÷408ȘæÁ¤¦>¸¨£ãø;÷Ä®=\MÀÁ³¹ºŸÂB2H!î;`çjD5ÖoÞ´ñ^Ý4»¤h–Hª tuvcÍšUX»v Ö¬YƒÎº˲àº.r¹®v;6ŒÁ!8Œ£GaæôÌ‚i=(WìâýûŸ*ÎÍîöèÈ?Ö2(‡‰œiPÁçæ@+€¶—ö¾üÛm­-‹Ç¡ A•*§‚Ó3§166˶AÉ¡Šj¥×õàû^ÍuÉ’EQ ( VÝp#>õ›ÿ{Ãû{íµcpªUd³™9]Ó\´¨cÇ;ôè®9\Ä~Þd„“€Hš°æ­È’Ò=·¯^ó¾mš¢ 2sSK!2ÚÛZ°bùõXµêܰêFܸrå»Óqø¾øpáÝÆÌÌ,^{톎ÅÐÐN¼9Šb±¸Pð}׫z®}øÈàŽ©ñ± ‚> :ÒŸaÛs Âï‚×¶4ÄÓ³9¶ùÂç?ÿó¿þ©O}D×ô–2#šXã8;9†É©éˆªÕ**•*\Ï…ïùà ¨ ³Š¢ ¥µ_~ìц÷;=3‹ÑÑQär-Ðu­4t¼¾èd w,A.[ˆ5n®u»uë$[W¦&Æž™šëëèì¹ã}«ÖÜ©jZ² ß÷19uÓS§q¨ÿ:»»qýu˱òú¸nÅuX¾ì:hš M«M•±mIE¹çáåÄììÞxã8^Ʊc¯ãøñã8==³ ‚ú#/ðŽŒ¼Þ7<|ôÇ Â>*ø%ö™kÄÿâþ6q‚–䧦§ËAÕwÔ¬Š ôA´ø‰°Ê6\×…ëz$2³Ô¸ð˱å×õØ2‰Ï|ö ø?ï¿¢»NcË·µ"ßÖŠ}ûÀ÷sß:ujò®®®E¼sO·‰wSàà>µÚH¡Öà¾n¨ŒŽÎž;Ö­Y·Y&rŽ…@Žç® ‘6Ltvv`ÙÒ¥X¶lz—ô¢··çð T*‚Àƒ¦_Ì üÅÁ÷Œatt Çß|o?£obzzv¹aÏÍÀ<×qJG_Ÿ=à€"è(oƒ ý¨ê/Žúâ?>^¼¼{ t&  À ‹¾ûÝþØ}?wß¶íÀql8N%ÒÇeY8úÚ1Ì‹°Ëef&PS@–%H² ™¿+aHßó!ËÔ,øù~¾ÿ¾†ÏåÀÁCÐS:2Yó`RQ·¶··5ƒ W« Pó¨ ªï=؈4vn±£0«™Un¾åN3etÊI’ 3q²Ä÷ªn ½5‡Î®Nô,^Œî®Ntvv¢sQòù|”‰x9P,Z˜šžÆäÄNMLbüÔ)Œ<‰É©)ÌÍÌß3„!‚>ª¥RqüØÀྩ¹©#ˆ}4ö©ˆØæ/‚Žú>jGúFàþÀõVH¬\qÃòüÛ÷?ÙÕÝÓ[¶‰’@ŽãÀ.ÓY€ùBƒCC°JÊeæ¨T#µ_–åÈYú£†ð=$A°fõ|þw>Ýð¢^;6 Ïu‘ËfŽkšö`{{[3h×ñÄk p"¨z# K‹úò.Y±|Íͽ½«4MÍÉDN°4 !K4Ÿ‚´‘B&›E[Kòù<Úò­hmmCk.‡\.ÓÌ"6NE¶MGÇb±ˆBassÌÎÍbfæ fNÏ`zj³s³(ÎQvœ†Î<ƒ€V`t]ûøè‰ÇŽ ¾`±m_ñmPÁç½K ‘ѼÒÇ…ü£óg¹ Àû@Ÿ³üÀÇ?¶þã—²¹LÞ.;pœ2l›úlÇAÕq059cÃðm vÙAÙ¶!…ÆtÖiH’y tˆ0 àùÔ´èííÁcþAËŸÀôÌ Zr¹9CO=ÒÞÞöžºV ú9ÄÚݹ°‹B/îãÎ+Ñ4ˆ‹DÓ¯_¹â†•=Ý«YÑB ²$Ë §Þe"Èš¦AÓ4F†aÀ4 ¤u©T š¦!™L"‘PHHì…FÀ}ø®Šë¢Ze£cɆU¦`Y6lÛBÙ¦Þr±úNc„~èû£'';6dU‹# £:|±a«Xèy;wñÈ¡ÿ P `€% 1éÓÿǧ?ðûþÁÇUE1˶ƒ²c£lW#S Ru0<2‚ñSã°Je”Ë6*•*H‚@!2!,fCâš0- ¸® Ó4ñ…Ͻ=Ý .®P,âõá´¶¶ÀHŸëèhâïëšÄµF"8 ˆ™…âè/®yð‚Ø7M²µNT}éŠe×]—_¼x­¦&2 ÈD¢Þ© º Y¢¶l‚P¡ÅCâ¯aˆ0„Ù‚à¬#zCø‚0üJÙžŸ9sæcG 9Nñ5Ä#9Wçy“V[Ø.³¥Ê íýóA}^­ò!Ž ÈŸúô§7åË_þ¤çº »ìÀ)Û°ËUæ S„ƒCC˜ššDÉ*£lÓÊAŠ¢€²Ài¾çÃ÷=ø¾ßøÏ¿ŽMomx‘ûö@kK+2¦ùdGGû{Ö9x-°P#›’ŠÂ/©¨ "â$µ“³(ך_ÚÓÓ»´5×vƒ¦‘H2Ad´¸öÛÐ;¸ç@" ÙÁŽë–¦§§ß8=5qrjblÀiPöî¨`óQŸ/|´w„ï°bo¹s÷Ř $Ð :%Øúœ%©¿û¿ÿî?~ìÁÈõ¼w –íØ)h—mêïÇ™Ù9X–…J¥ EI$ˆœƒôQƒ>#Ï¥Eùȇñ±_øhà =x¨)]GK6³CÕ’¶d³ï9çàµN@íè,j" pÁ¯×DH¢¶^aÔLMîŽÎžEíùÎŒžk׳F*ÉRºr@È,! $H¤PB" Ds| å%! Ó:„d_vÐ) ¬¹ÒvÅ­NŒ½ytjâÔ8ð˜|ˆº0‹‚í"p>ú‹Ÿ«ˆ§K¹Ð_Œð‹Ï™×mÈjP2àÏ3õƒüë/Ý}ÏÖØ6þZM`nný‡077˲hBˆš„¢¢€$$Èa™“2 CøÕ\ׇ[­bùŠø½/~¾á…ï¹Èe[êzê‘l6óžr¾`ÁŸD,Äâ¬Hg#¾æ ~Ÿ'ŽüèÈ— wtt/¥Ù= Y‘åZ¢z¾ìxHHŠÀ—qföôD¥Ê\ønèOÍŒ‚ŽÈ³ :^w[ŒàBÌ×â¶(ì|[\χëÑ$#MÓðÄ7oxÁÇOŒÂ*YhiÍÍiš¶µ­¥å=CïE!†Ùs­@|‘D" €`a9sqV‚ÛÄ<£Ql€"’…(|\'ˆp¢Zî#ž÷êQ°«ˆGøú%~7À‚Š„o üÞÄŠN\à¡Âüy¶9røÓù|W¯-™E:Žƒ7OŽbèÈQXV ¾ïCU“‘9 0s@JÐGʃaÀ÷ýs@U“øÜï|Kz&ÍÌÌâäø)´·µÀÐÓ´´dŸ|ŸÇ‹÷:q~ ×êGüzH 1 ˆÂ_¿ Ô >À“ìuBª˜\ð¹Ð×G;òãÜK/Žü|©WïùÂ5ë·ÿCÔ²xü âº*UQÕüÑ×ýŽ¡meÛŽHÀ.Ç$04tÇß|–e5©@IP" Ù‚‰¨&½­ i׃ë{4å¸RÁÃÿ*nßÔ¸áÁCýhmmEÚ4þ¨­¥å±wð™\‘hFQxùÈ^¯þó5?^OÜ? f/ò5êÖ|[|aÝRo“saæ!Ïõ£?_W…ýâhÔŽöï¤àsÔgñ 1Y(ÃÖ Ê½÷Þ»ò¿ûÏŸñ}7i—ØL(Ûåˆöí?€ÉÉ)T«¨ŠEU¡&“P$¡ AHmØp"©& š•J÷Ý{/ø…4¼øþA˜f™tæÉ¶¶–kz† I !Õ-¢°‹ê¾8#P¿ÈÂÒˆê§ksp@# €“€‹Z2„Ïõ¿u¾(¾wü¹y¥‚:¹9À3Óüø/<ðÀšÿñíoÿ¶ãTP²Ë‘À5bÉÂWFiËIU…ª&‘TÔ 0s@&8€N§ú>\fT*UT«,[¶_üüg^ü¡þ¤ -¹Üޤ¦>˜6Œkr† IgG½VP¿æDPoûóý4Ñ7 Bt¼‰ª¹8ò‹ÂÏmÿµÓužð[õ‘{—KðëÁŸw¸Ö7}ák ñ'ò'÷ü—Ïü—_²G¢ÙÔ9h3M`ffû_Þ¹Â<¡AW¢9 ˆÂâXyfZp4€ïðYÂQÅsQ­T°ti/¾ðÙßixáÃ#Ç„>Zs-U-¹5“N_s$Ð$€ CýˆÍºÞé×ÈÎ?pˆ£²h‹,j¢_ ÞLhô›ï6DM€›b¿® `æÀ÷þç~ùžm÷ÜeÛ¶T.ÛàÎA®ÌÌÌbw_Ç¡@R…¦ªHp"H°`!"Gy]B~?ðéô GýNµ UQðøW¿Òðâé4¡¶ö¶9]Ó¶¦ÓÆ55CÐ$€‹G½ÐsmA$q¤µ¾ˆÏ£^°0(§^Øm_IÍ)^ê]ìõÀI@#ŠûÑ¿ý¯[¶Ü¹¥lÙ°í2l(ÄÍožÄÁWÁó}hšŠ¤ªÅæ›&TaY„2k¬ÀÌ^ÅEÅõP­:pœ ~ï¿~±aøðìì&¦&ÑÞÖ:—Òô­™Lúš!&¼}ˆÂÔŽîõž~Nâ6„}aݶøÝ@ø½«bD¦XAˆ“@q1ãÌÐÐÑϵçÛzírv‰– ³Ëvä|íè1  A–$–‘„šT‘L$iÄ ÂÆIÜ‘)  à»*® ·J5Çqð™ßúVݸrÁ…ÏÌÎbbb mím0 ã‘tÚxòÒ?®K&\:ˆþz•¿Ñ €¨\«àÚ‘Œ8Sì™ œâQ—úÌÌÌ Cè–]†m—X†`™ Ù8x¨Ç‡ª&Y¢7’´HK‚°)BSnš7PSÀu]T+.ªŽ§ê`Û=÷à£ùpÃ8Ô?€|¾ ¦a>’ɤŸ¼¤Oë2àíÈð;YŸòZÄÙFtþY´éEÕÿZ†xßbN‚š¤TÍPäJö­·ÞúuH°Sš-¥G™–š¦BU5Ü´î}èÈçQ­VP­VhU!ߣIAÏꀖ\—d‰Æ (ª‚¤¢BS5¤T š–BJבJéxnûN<õã§ÞÀÍëÖbjr…âü· …Òc—ü‰]Áh@Nyë·}À¶Ë(Û%ØV–M‹”Ë6¦§O£¯o$I†®§Ç †¤ª@UT…ö ­Ç´‹§WÜ*ªNNµ Ç©‚_ùãÇÞÀ¡þ˜¦‰öÖ–š¦=˜LªWU¬@Ó ØÄ» >=ÊÓ«uÔ† óˆÁ ¼úêç»—.]E+%Ù°KÊŽ «Lc¦§¦±wß>$…èTMCJSY‘‚… ²>=„B/„ëSíÁ­ºpªªå*lÇI³– 9Ž@[{ëAMÕ¶¦RÉ«†šNÀ&Þmps€7b®7x­B@¸ö¦›þnvnnTÓ©pkº-©#¥QA[¾ «VÝU®º– èÁw}~€ ê»NóˆL J2ÁÌj^è)ê0ô ÀþÑ—1>>±à–/_„¦§O¯·{»U._ýÝc.Mhâ€83àf0rÇ 'â.D¥Õׯù[EVìÐT*ö 蚆eË–aÍêU´Æ ÃšŒT\:åǺ!ý“dȬi‚$L$‘ÔThÌ1˜Òuèõ ñÍ'þãS nbÅŠåBLOϬ/Ûöö’e]ó$Ð$€&ÞIˆ³b½B^˜“€_u­Ó·Ý²ák²,Û:RÁ1˜Ò4,_¶ K–.…Ã*^¦ ø®õ °ŽÌ2„@QTEARHE×aètÃ@Ú0ðÄŸÿ9&ÀÊ+ÓÓ3ëíry{¡Tº¦I IM¼“«ñ’f%ÄZ_WxC#GÇÿìÏþì»fÆ Slú.Ŧ ¹à®Yµ mím,¸ŠjÅ…[¡]…¢Ù ¤á– É4rPI(P“‰hf ¥iÐuΤi¥ç'þâ/ñÂ®Ý nâÆ•œN¯¯:•7¬ryýåxxïÞÍÖ`M\ÛàiÎbä _x¶eøÕ¯þé>ßw¥Ç¾üåGh¼OH3ÿ¸å¦›pèÕW1;7‡„$È4@ò$H ²/ƒÈL@$Ð"£²YJ@&‘!Bë‰.²ŒÿäßaÙeÜï¶š‹_uãJ:œëÈç·—,kkÚ¸¶’ˆ€æ,@—bhÞ žgŠ32€ÄŽ;>¹qã¦-%«Hˈ[¥¨ž€U¶a[eì{ùeT«¨ß@¯ (Rµ$-0¢$@ˆ‚a½ÙyA/d!ÃÖÕØÍ:•m¼ó¸¯ŽÚ tjrù|~ÎÐ+2“ðjmÚĵ žøä yµµøÔ¡ wß}÷w¶o7Þ¾9C‰öCAM…õ7ߌýÀqª,9ˆ@"2‘éZ&IB¨@Hs"!HB!dVpD’iÍY’ñ®Ýe ÷n»§æ&òm­@bbj2—Ïc{¡Pº¦2 ›ÐÄ¥'^¹Œ…ÅUhì¶nÝö/c§N.6ÍÜR@Èj"¤Aذa=|Žã€È2|I&Œdø2í>¤ÔD¡æIP3€x ²Dk 0â ²„^Ü@ƽÛ‰|¾ !€S¹EùüöùBak6sm”o@—<6€Ç Ô§Y‹5dVO×â'NŽ}Þ4ÍÞ€uL¡Úû/qóú›Ð¨¶ã@&Ì@d$ØâËÄ—È”dI†$K ðe‰&ÉmQ&Kt[¢>]»wC–€m÷Ü]s#ù6 0~j"×±(¿}~¾°õZè?Ð$€&.5Ä,É*[‹%Õù’õ?øÁ»ÿþÈàá/a¨Ó©~êå¹6`Õš58tð ›õH¤ H„€ B2uøIrTX$6ˆ$SG¡”ˆÚ—¿¸{7 KØv÷]57ÒÑ‘G`âÔD.Ìcû™ùù­-ÙìUMMhârA¬h\_T•B@rdøØ‰W¿ïñ#‡:t„k Ìd¼oÝZ >ɱY4 p™n“$B`>Y– Aжd„0Á'tVAމb÷î—`[Ö‚šy!ÆÇOå…ùígÎÌomi¹zI IM\ˆ•‘xÿ±ôšX‚­@âøÈ±Ñ|äçþòÙgŸý]ªüS‡ ØaˆsXó¾Õ828Gv˜ÐÓ)BY¦U„ˆ,Á«iIN§ 5$™¶'#ÔŸ}_’q¨¿€Œ~äþš›éìè@§ÆÇs‹°}fæÌ-mm-Ç/ùS¼h5q9ÁÍ.Ì£y”  (ÀsÏ=wô÷ÿ÷ÿ>—ÉÁHé0Xž¿žÒ‘Òth)¹LkÖ¬ëÒ„Ÿ8`¨×¥ÅEx§á  š!´ ˆª(4o€…§XÎ@Ú0`˜LÃD?v<ÿ‚éîì@Ww7¦&§r…Rñ“SSWeÄ`ShârB¬œ,N±O€›9øêW¿º+ð•/å×BZ86j ĪU«pôèk°mªÊ'Xw$K B¨0s@¢¡Ãžï3ÓÏ$¨o@¦ŽÁ¾¾½€,ãî;·ÔÜLwgÛÆôôôú|¾}ûääÔÖE‹:®š,B ÔÄ»ƒú®C*h<€êàÍX3ì|ùÅ]»¾mã¦-…Â<Š–»dÁ*Û°J,Ë‚]v`•,>2HGpàƒQ^¬ªI$U•Ö$„Vi[r×ui¯$䨴VAÙ²Q´,Üqû&ÜUG°ÿÀAa€¶¶öƒº®míZ´è²’@3¨‰« õš€ªþspÓ”·(?°eË“;w¾ˆM›nÛ0—!¤‘~KÀFÐ)D‚s€Æ af@‚$ÉØ»odYÂ[6×ÜÌ­Öcÿ~NmW 4  ‰wõ$À?'Ì çµ€µgÿàÝw{rjjIÚ4—p" Ö>ŒFîAFGÇh{1YBB¢aÃÔËO@<Úp„š ÈQüá-ËÙÔ"'Y–±wÕÀ­ë±oÿLOϬϷaûØ©S[{ºº®hh@ï6DsÀu ŠMX¸c°•}–ut|}rrò‹F:ÝE ü'€"BäÛÛ CÆèØÉHp%™ÆD&s’„ &@ˆ È’Ò_æ&€Äš•Ò6e$ìÝ·2dlÙr{ÍÍl¼uöí?€)f\é$Ð$€&®ˆ½yÎwò®C΢E‹?uêÔÍLf ÷€…a+ÚÚÛYÂɱ16‚óQœ›¢šO ÐÜ…IDÚ€Ìc‘ȲŒ=/ï$`Ëæ$°ï@d\É$Ð$€&®$ðhAäÍIÀîêêúúØØ©/f³™^€ùXè0KÚÚZ!ÉÀØÉqªD>„ùÌHÄæÏHÈHž+@ÍÂ4Y’ Ø·o?€$°qöìÛéé™õmíá· C¾ýûY–Û7ÕÜĦ·bϾý˜9=ûÀÐÑ׿µê†ë¹Ôî­¢IM\‰5 {1@û|zõêÕ ünˆ@gS€0;P²Jhm¡zã§Æ™ ³‘œÈшNí~)š) IElú$d ‰È'@ÏÛ~yß~¤S:n¾y]ÍlÚx+žþé³ððÐÑ×q¥‘@“š¸’ÁI€WªOÊH ;vrÍÚÕ>üE„†n €õ Xe­m9È0>>Áz2í5(s“€Da²O@$‚DBkP*KÔ„à>>3jìxñ\wÝ2d2fÍMÜß6<ýÓg€+š¹M\©àš¼ Úk „¸ºð¶žcÇÃácã«W¯ýºšHÚzZgÑ€´¸‘6`¤t kmAwwJV‰Fù•mXvŽSŽr ªÕ |×…ÏŒ$Y‚’ ¬ÿ -Gf°hCÓ4a¦MdMÙ´‰oçP(ÜÌý÷Ý‹¹¹9ÌÌÌ>;À[s˜eë3`á€#ÇŸ\ËM+IÅÖS:Œ4ë ¤§`¤thš†Ð÷‘ÉåÐÙÙ‰¢eÁ²J(• ”éâ8ªŽ·âÂó( Y†¢(ÐT i=…tšš¦i"“aþ€Œ‰tÖÄwþ¡1 üÇ߉‰ æ ï* 4  ‰« Ü1XA­cp^X‡‚‘ááñ[6Üü¸šP,=•Šlv®pÈå2èì\DI dÁ²éºÌLÛqh—a¯ ×÷ ‘”$í^œ2tæ ˆý™lÙt3‹ïÿ_Ü„ª*øð@ÍzM\à1IÐÐà4h-tj0 ZK€–/_ÑûÊ+¯|ÑuÝ”e—¥’U‚Å„½X²P­T@ˆ ˲095 =¥3A¦¶½a¤#{ŸV#ÒLÒšdø¡jÅ…ãØ°ËeX¥Š% ÅbÅb …b¾ëãá_ýÄ‚©º.~üã§ÑÙÙ‰L6óàÚÕ«²ÅyÐlÞÄ{ |аЏŒoG~†­ ü¼‘‘ᓷܲþëDIØ)=…´‘¦%ÆÒ: #5©À÷¦ÞÞØŽ¢U‚e•˜iÀLæ ¬V+p=—úd@!)Mƒ¡§aÌ6‘ÍdašdLD!xòÛÿ°àFT…kS(̾uxàÈeíCØ$€&®VˆS„eÄÀÍî ô###'o½eÃ×)a¥4 iÓ€ž2"³€’€EM¢wq/ÛihØÌ$¨TÙ4!»Y4M¥ŽFÓDƤŽÀlÆD6“AÆÌ@9 Ü´n-&§¦rÅbqûå$&4q5£ pÇ ÷ Ø9þÈÈðèûoÛð B+¥é0Ó ¢$PTø® UUÐÓÛƒ²MËŒYE:UX²,¦ ”áØœ*mU.BU”xV€A&r 2øÎBX¾|®_±“SS¹’e]6h@W;Ds ŒÚ6äâa >yǾ©©”JÕ’€ÉHÀó=¨Š‚Þžnض¢UŒf ,ËŠ–:v§ ßj.ˆ9 2³4@ˆ: ‚§~üô‚Y»f®_±“œ–]Ê4  ‰k<ôßÃÂ8,ÄIÀ?ztøÄûï¸ý¿Ë²ok)=4H›:Dç{H( ÷tÃ÷}XÌ¡W,Q,™i@C‰ÇAPwA² ˜†3¦Ó‚lf —É"“Í`nnî$°SS“¹’eýàÕ×´Üx“š¸V  qÕ¿Q° >zìäæÍw~C %KOi4¢ÏH!26t$H""žî.x¾R±û˜IP²-j8NË2téŒ 3“eNÁ42 üð,$ ªILMM¯·íòöKIMhâZ‚èp@žÏÌ’B÷=zòöly¢â8§õTFÚDšiiÈH @ˆîî.x¾‡ÓŠE‹&Y6¬²…²eéV^”®i‚/ – g!ûîÝUUpzúôzÇq¶8rIH IM\Kˆj æ£TøyÄ`€7rlèä’%K¾2;sæ„®%a˜i¤£Ða„$à»1 H’ŒbÑBÑ*R€›–«d£ZçäÐ4fÖD&[Ki¦ Ð6dµ¸ïÞmP“ ¦§§×—,ë’$5  ‰k¢cÐAì, Ö æA# ]åÕ«W}svǫ̈®¥`˜é(ZÐ4 È t.ê!ÅB‘jŒ¬R12 \ßoxQšª"kfÉšÈ1à>WûpðÐB¸wÛ=p]33³ôí}ù'&4q­C ææ÷p¨(­^½êñÙÙ™Q5¡Â4“€ï{ÈçóHª*æ‹" ÐÈ?«H§ ëg8TUA6“É‚¦™F6m"cfи1 üÂG?Œb±€3³sï}yÿ;JMhâZ×x=(Ä‚5EE”W¯^ýµBa6 )×õàû.ZZ[‘53(r(™9PD‘E9ª¢ ›¡ÓƒY¦d34‘¨ÿp?FÇÆ|ç—ñã˜/ÍcvöÌÃ}{_þì;õ€šÐĵ>;PA\Yˆ/Äõ\Pß'Q¥žLN.|ßEJ×af3(•mæ) Š1”JÅÓƒœ25$A&“ÅsÏí€Ý`Vá—?þ1LLL¢P˜ÿï}{_~øx8Mh⽞-S%Ñ'ÀófA5…€½zõê¯çfÏOšŽö–V”Êþ’/À´ƒ³!&ê̘&L“jÿò/߇m/$ÿåc`bb¥bñ[{_ÞÿÀÛ}0Mhâ½Þ{;¹9Àƒ…lPà<{õÚµ¿64ôÊùH@’ òíyTœ* Å" …y‹%Ì‹(Š ëp¨ŠBƒ¦‰,7ØúŸ¿÷½ç†Ž=ø@”Füâ®—ÞÖô`“šx/—ã&÷ˆY„§A5€½mÛÖ¿Ú³¯oן@ ZÛZá¹ÞB(Ò¸³AUd³˜‘)¥áÃfÿô/ H@×që†[095™+‹oËÐ$€&ÞkàNAž@dƒŸ´Ì€j ~üŸÜ»oÏyI ð´¶¶jI PD¡8^ÈdYȰ@”Pøî?-$U«nD±haöÌÜ'Ñ$€&Þ‹àŽAN<“ÐuòÒã~þƒ<ð÷ ˜u$@bp]™¬ MM¢0_G…s“€¦ªHg²4`(MÓ‰3¦ E!ø×>µàüõÖcjzªi4ÑÄE >lX¬'ÀÍYPàÁøVC0bp ¨I†¡£X´P(Ì£0_À<Ó ÎåÐ5™tf6Í ¤³¸UƒC5çÞ¸r%&&&ßÖChvjâ½ ±-yT#…ý¼ûÐ €vPY‘|à¿ÿÖ“ÿÃþ÷Ý{¯iš5#hѲà»<¤ EQ`:l»\3È·ÓußçÐu aж笳‚#oŒ`íšUÑyfÚÀé™™'ßÎCh@ïeˆ$û$ÄB ( ´€Ö ”yøû§ßüÍO|ôÑG1Œ4@b’\²,ø.ïm EAÚ0à8æƒýå™ 2ir0 A„Aˆ P˜¯*ØýRßœ¦iŸ{; IM¼×!Žú.¨ð—OŠçd褿ýÛ¿ÙI}ôÿú5CN×´--Y< (Hé)T]ó…mcÖ¿4aši² Ó¨!€0ˆ‹<Ô¾=ûü«?ÿæÜ_>ñ‹¾ù&4ÑD 'À§ à @Iû7Ý'!À<ú¥_3Ò&¢¦2P*2Ø—@Uƒ0raðÿ·w.±QUaÿÍœ{çqgny¶@[ˆÁ˜ˆã%jˆÔ$ºÆ…ÑèÂD!Æ„°pÓ w$†Cºp£€H%”¤V\B¡H­mC['ÌÌçžÞÛ4µC»è÷Knî<îLfç¿ï|ç|¨zxx¸®‹­Ô¸ÜT Ï«àU½1»ó;Ã#\¸xáã]ï¿×9Û?, f€-òϦ yئ<°oß¾³»wïyƒtjì‹"DÈdr”+ã·[¶"®lr¹Â¸ü£êy¸i—XÌw½RQÒNŠjÅÃó*\»ÞKWW׉·ßzó³Züañ„©‰¶¤Ð^Iô\€ãŸøÞ7n|ìЗíï*K9¹¬ÞlÚŠ—K%,eéö°”BÙ6^¥L<ׯ¢®«ER.‰DlÒÉ‹d3®ö\ë{nËæWÑ)ˬ|DajÌ^¡z-)´éˆ9Rh±¨664¬9sî§–¥œl6O®%“ÑDï•J(ea‡DÀ²õÝÞR*°wui1å8ã~Œô\¹Ú¿nÝã;_€ëæ=AxxDÑ©²ãBT‡v"rÑ“ƒ‘Ɔ†æ3ç~ÞeÙÊÉs‘l–\6,:°}ˆF#D#Q’NÒݦÜI&Q~‰àÖÀ@sSÓ‡À  › j1+9Ax0fé°© ŒKÝC]Àhiyæ“§ÞI¥ÝåúíQ´õX±x—±FþI)›¨ …|AÏø{U¼²Gµâ‘H&øû¯Áþ5kš?þ.Â}wωazÂé€"ð!L¢½]ÿµEŒ•Hvuwï\µbåjí-t.µ¡‰ÂgÅÇLL‡‡GúŸ~êÉ=ÀïÀoÀ¤¥’ÂÜ`·žtý³I Òh0‘uºûüùV44¬Î狺g`&C6—§X,Q Û¶QJa[ Û²Q–B)…RÙÿéomݶè® #€Iˆ9¨ Ì f}@ ]"4…Â$#è” ÿì† ŸÞêwm!žv]Ònš„“¤Zñô&¢²Þ?P*—(•+ŒŽŽÒÑÑq¶µuÛ.ôàï&÷ «ÂÌ0é@ˆT‚À” -ÿºÈ¡Ãí¯µ´lÙœÏçÉercVc…|‘H”±4`èÎß9òÍW퇾@ LÐËò~Ian1`D A ¤ýÃTLQ?r¸ýðë›6µl.óÚPÄÌ ò”K®õöæ<ÐÞsùòtT1íàA˜Â"@oJ” ]‚ˆ n>ÔÖÖöòޝ¼T¸{‚¿PèÆÍ›tžêüãÀþÏ÷¿¢Ó‰>ÿ˜vÆ_@æ…õcþᄎEh1XB Ô·íÝ»­¹iõêÛtžêì9vôÛ¯Ñý²Ì`ðƒ€ Ì'áò M ˜”À,Jû¯E'|ô„â:ç¿Í ?ÈB A˜OL{±ðŽAÉ»+þëZ,ðŸ›JÂp ]ç¯ÙBŸé„ÙcýÄÇa!ˆ E ƒŽ"èrbDßùï0‡ƒD¡V„ïü †— —ÒÓxÄ’ ¡£€Ùçã3D@jÇİÿ.A÷aãDœ'‹º q‘À‹`N„Úcx¸»P =Ð-ôÝß“„7Í95©ÂBäò¥Ktœþ£Gsòøñ©Ü€Ã›ˆ X7à5Ô7x–mWn…wR·¸ŽÖç[Ùþâv¶nÝÊÚG×>Ôÿ € üOžX¿gq’åîrêëê9vâ{F‡ׄÓþ~ñÒ¥ÕÁ¡Á)ï¼vÔBE*fŧº¤¦ˆÂ,x¤i-Î qÒn’%Këè<}’K—®L¼,,ÕÑááû~_ãÊU457R¿l©Tê¾×Õ Ia#Ûa#  AXÀˆÂF@0ÿÛ’ÎÿÌ‹q‘IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/viewmag1.png000077500000000000000000001464311217176075400243310ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½tוßù©÷ªª ÝèFMü @€(ˆ´(JeZ2eY´dLsdC–=“ÙIŽ5™qf6“¬Ï&gâ$;“L²gv³ÏœÍæÇìdíädOì‘G¦G¦¥Ø32eY2eY4%™E  `Ý]UûÇ«ê®.tãE‘Ôºï9õê½Wݪºßû½÷Ýz¥¹®K]êR—ŸO7úÔ¥.u¹qR€ºÔåçXêP—ºüKêR—Ÿc©@]êòs,u¨K]~Ž¥u©Ëϱè7úÜìrðÐ`/Ð+¥LRHÃ@—ÚvMˆ^) „К£Ž vÑÆ¶mŠ…¶ëŽºvñüJ¡0ê—g½ÿO]®½hšvC¿ÿäòhõD % & ˜–u Úа½!í5 ã@<#ј 1ÞH¬1F´ÁŠX˜–‰¡H]"=pÇv(Ø +Eòùr¹Ù¥e²ÙE2™ ™Ì"™ÅE²‹YVr¹¹|~Ô¶í×£À‰gNßÀÓP—«:¼åà¡Á¤aèb±Æc±Øx<>ÐÞÖJkkŠTª•TK3É–$ÉDMM cqõS>_ “É0ŸY$¾Bzî ³³sÌÌÎ2si†™™®¤Ó,-/ŸÈår'€€Ãu@¸ù¥ï9xhp@){ì³-Í-]Ûºèêꢳ³ƒŽŽ:ÚÚ‰Çcþ<Çvpqqð*B 5 6³³sLMM355Å…ÉI&&&˜¼0ÉåÙY³Ù¶m '6÷×åzHnb9xh°7‹=™L&>ÛÑÑÑ{k_===lßÞMw÷6LÓ¬z\!Ÿ'—Ë‘Ëåȯ¬°’Ï“_)P(°í‚òñm×q§tœ&BÓBG]è¦NÄ00#"¦…eYXQ )eÕïN§gllœÑóçeòâE2™Ì¨mÛ‡?©Çn©ÀM(ƒÿÒ“Í--Ÿíèh;ÐßßOÿŽ>úvì «³cÕØB¡@6“!›Í²˜]by)Kn9ÇRn™|n…ÜJŽ•|žâJB±€],P°mÛÆuÀq=Ð@ ÐtÔ$º†a1uÌHÓòÀ²ˆ646‹5‹Ç‰Çb«˜ƒm;ŒŒœcxd„¡³Ã Ÿ=Ë…‰‹,g³'øên —:Ü$rðÐ`oS"ñd*•úümý·&wíÚÅÎýôöö¬»N3¿° só³³Y²Ù,Ë‹K,å–È-+°²’#ï3ŠEÛqq"¸Š@ÓB¤”ªÃÀ0ü…eE<ˆ6Ћҋ‹ÅˆÇã4Æã4%$ššˆÆ*Ý‘B¡À™3Cœ~û oz›³ÃÃ\žMÛ¶ýUê¬à†In°üâ'žèmJ$~okgÇ“{vßÁíw¼Ýï»hÔ*ræ®\!N“N§ÌgXX˜W‘ùL†lv‘l6ËÒÒ2ËKKÌ/¤óããW¦g.-^šž^Ì `ðŸò^À6(&ÐâÕãñX¬±££#ÞÑÞÑØÓÓJ&“f4#k$‹ÇiŠÇ‰'$I’ÉÉæf’É$ñD¢âƒ§§gøÙ©Sœ|ó$§NæâÅIV ůÿùÙ#‡^ÃÓ[—u¤7H~ñOô&“ÉßëîîzràλØs×ܾkgŘ̳—/3wå WææHÏ)H/¤™OÏ“™_`a1ÃÜåÙüèØù+§NœÊÛö0 ¬àÍîyÛj*•?XתԵ@‰[’‰ÄÖýý©÷íº½3Õš2›ššÊl!Ù’¤¥¹™–-[H¥RXVØ––r¼ùæIÞxãu^ýM.LL°’ÏþA=hx}¤×YìM&“¿·½gÛ“wï½›½ô÷ï(õÛ¶Í쌚Z»<;Ëìì,W.Ï1weΛ‚S pêô[—N¼ùÆà+¼(n î[ú"`S`5 ð#ŒÒ+P Á"¼m«i˜Ú¿¿wÏîÝÉæ$É–š[ZØÒœ"Õš"•J‘jm¥¥¥¥ôE¶ípâÄ Ž?Áño01q‚bÿ¼î¼»R€ë$ &c±Øº»»?¿wï@rß=w³+`ñó¹<—¦/133ÍÌ¥.ÏÌpyv†ÙÙYfg瘛›åøñããg†‡Ç€1 ‡Rh_ÑWPÊ^ðJžJ0Ø( ‹‡è( 0½º¿ @pÛܲÿÞûnùÀöÝÒÒ’"Õº…ÖÔZ[[imk¥µ½¶¶¶Ò 6¯?Ϋ?yÇO0uéŽëþsàëÁÂwGêpdðñ_:ÐÖÞú•;ïì½÷Þ{¹çžR_>—cjjŠKS—˜¾4Å¥éËÌÌ\R `f–·Ïž™;öÊ+ÃÀYÊJ_D)|޲â;¡²âÍ{ãý6(‚/a ˆx[Rt •–_zc#^¿?6>ìøÔcŸ¼s×®][ZÛ[imk£­­¶övÚÛ:èÌp,d²¼úãWùÑ+¯ð³7O2¿°~íÙ#‡oêÄ×e]©À»( &“ÉäWvÝvÛàþý÷rßþûÔt` L^¼ÈÔÅ‹L]œbêÒ—¦¦™ž¾ÄÌ¥i^|éÅቩ©SÀeÊT~Ù+¾rû`à·ù`¶þï”øwIÐú[(Å—”•]zí ^¡"¶½w Üÿ¡ûoéîîŽtt´ÓÖ¡’™:;;i 0‚ññ ^~ù?:ö #çF(ŠGQ@0ºÑkP—µ¥ï’ >þKƒ[;;¾rßîM~èCdÇŽ¾RßÔÔ“\œœdjrŠ‹S“*“nl<ÿçž{«àØgy”rg%ÊJ_@)|–²Òû`àxc‹(vàoýÀ •`@h¡ü”¥‰RX¥ôQ*ƒ¾• ”ÞW|IYÙ£¬¿?ÚÕÙy÷à'ïÚ¾½'Ò¹µƒŽÎN¶vvÒÙÕE2™,¯W_}_z™×~òsWÒiT𫛺 u©*u¸ÆrðÐ`²)Ñøå]»v=ùáàû?„a¨ÚB:Í…‰ &.\(ÀäÅ‹Œ?Ÿÿö³Ï¾e;ÎI”Â.£¦ì–QŠ›G)¼¾Âûmþ1¾‚‡K­8U¶AÑB[“²ÂG½z0 €˜×£@4í¾›à÷5twvíýÔヽ·ÜÙºµ‹Î®­tmÛÆ¶îîR¶ãôô /¼ø/¾øCFFÎáeþZ=6ðΤ×Pýâã_ùÀ¾÷8ðavîìÀ±m.Œ3>>®`|‚ɉ LL^ä/žþÆëÛ>‰Rà%`2ÏÊJ¿äíûŠo‡ÊµT~_ÂS€Áº@@ ˆ£Æ÷¾ÀOŸ`iyyx¼>exõR€k$ƒÿÒ“·ôö~ùÁH>ôЉ8é¹4ããç»À¸ã¼öÚkSož:õpeíQJŸCÑÿEÝ_@)ý"•AÀ°âÀ­²õŠp1{0ã ·oçb±&:{P…a ·´ÈìÌE–²óœ9õSÍÉ΃=Q üºŽRn¿øJoxûM”@ ì6ø¥ù‘‡:pàÀ]ÝÝtwwÓ½M=ÿ`z9Ã#£<ÿý£¼øâ™™¹ Ê%øãÍ^³ºÔàšÈ§?ý+_¾ýŽÛ¿ðÈÃóÀûKíãcãŒe|lœóçÇçôéS‹}ôè«À9”bgPŠžÒ”)ýJù}_ÞWú ò‡?Ò1S»Ýýão~îKnó–¨—ïjý9¡ªwŠýGë›ÇOðƒï=¥;ú …ô›A7ÀƒÐL%3hDAÏ’”ôŽÝþ›ŸûÜ£»oßèîé¦gûv¶÷ô’jM°ÉðWß{žçŸ?ʹÑQ×ýê³GÿÚ—©.U¤ï@”¿Ÿøæ¾}÷ø…GaÏžÛÈårœett”±Ñóœ??ÊØØ8Ï<ó—o¥3™Ÿ¢}å³/¢XÀ²×î3‚eÅ@ Êuú÷=æþêçþ±{×=wPZøÉR@ èDùî ”Vc>ÀøŸ{ ÞoJ>NÁ×ñ@ÂQ€à:pìÏóŸÿý¿ÐÒc/„sZPŠ^ zm>4z¿­úwì¸ÿÉÏ~öƒÛ{zééí¡÷–[èî)?ñüó/ðÝï}Ÿ| Û¶O©Ç6.u¸J9xh0ÙÚšúþýÜ?ðèÁ_ ·§€ôÜ£çF=Çèè(£çÎsêäÉÅï}þ%TOåËûÁ+—Q à'ò¬¥üJAnçoüÖ?s~ùÉÏ€ÁÚ€Ûn`Ðïü¼eE3‹B軪}ÿ2 ¤.£2Ÿ>N±0pløwÿúk/=óiñ]¯”g | 0(T lýíßú»ƒ{öìNôööÑÛ×Ë-½}˜– ¾úêk<÷ß¿Çk¯g%Ÿ? Öã:\…<48ÐÑÑñÍ>Üûñ=J«GK§&§97ÂèÈ9FGGå莎 Œ¼ˆR–y¥¿Œ¢þs^{ŽÚŠ¢üqûc¿ú»îo~ñKîà^;{QŠßÂje*}øóÃJn«V¯¶õìÊáã,90°í2 üËßý5íôË_ÕPŠž¢Þ¾?ËÐâm}ˆxðÁ~ò±Çv÷Þr ·ôõÑ××WzÐèä©Ó|çÙç8ö£c,-çÒ(&Pu¤›”ƒ‡:·v|ÿ‘GNúøÇK«ðŒ1|ö,#çÎ1:2ÂÈÈÿï×¾öcàÊb.Q¦ø¾]¢2}7¬¸%Åoí;`éÿ‹{K7Ÿà p?p•J^Mñ‹¡öµ¬X¹ÃTm?—(¹2OgŵˬÀ¶¼yü5þ·ò7ÙÓ: Z)O&Qʯ£˜€ï6è€Åîü/~ñá]»vEúvì ¯¯Tk+ÃÃ#|ûÛÏñâK/’Í.×A`R€MÈÁCƒ]][¿ÿè#$=öq¢^TzdX-v1<<ÌÈðgNŸÎë;GžÎPöŸ/£ã"«¿šõ·{ߣ¿í|éý·îà^:Ï¡ßb㊿«¸Ö¿Ú¬DØ]Xú‹×pœbŠPtáþÆAmfø¹Ðb~`°ÍÛZ(°(?ÐùÅÏáSM;vÜJ_ÿ::T*ñèèÏù/¼ð"Ùl¶ëH6(¾åÿØ£¿|ì±_IJLÇaxhˆá³Ã Ÿâìð0¯þøÕ¹—^9öW(ßðÍ¡ßüùÊïoWYàûûçþýÿÃÜË>à·€V+x-æP«^Ͳ‡û6kýƒÃZÓ“`æðq ¶ NQÅll¯þ/þá¯h#ǿֈ Vú F~¼ÀDÍ&Ľvˆýæ¯ÿú¯~àƒlÛ±cýýýtvu066ηž9ÂÑï¿ÀÒr ¬%uØ€<48ÐÞÖöý}ì‘ä'>ùQËÂq†ÎœáìÐg‡†âÅ_œ:qòÍçPè.3(Ë?E9SoMåß÷Èo;_úÃëîå^à·»Y­ìµ¶kÑÿwËúK(^QŠÌ9‰íxA× x[ÛöÁ†_û¨&QÖ?E9HØ…¸×^=úè/|úñÇ÷ìèï§¿¿Ÿ®nŒãð·žá…¼H.W Ô’:¬# &S©æŸ>òÈ#½Ÿü$ñx¬¬üo1tö CCC<óÌ·ÏŽON|eñçQÊ?éíÒ Sÿ"`Ç;ï-þ—g޹ƒ{¹øŸ€÷³ÚÒ_âײþÕ”ÿj¬­¶àÊ_St¼€ ëY}ü˜@ѯUýÜð0ÿüïܺ(?i؆ß=ðŸQ0}ä‘O<ñ©'öô÷÷Ó[Þæðáoñ£—_f%_¬ƒ@©ÀrðÐ`2oüþÃ?4ð©ÁO–¢ýCo¿Í™3g:s†¡·‡øÖ‘gÎNLN>KYñ/TZý0xJ%‹¿ÿ§¯9¿÷¹»º/SâW€Íúýa%÷™ÇF#ÖßAÞì‹ãƒ³®¯øžÕw=WÀŸ%°‹e6P´Xxl EÿuoÛJü¸€þè#|ò‰O=qgÿmýܶsgÉxóÍ“<ýô7yõµŸÖóªÈ{ÞõWƒE¬¯Ü÷}}¤¤ü*à7ÌÙ¡a†††øÖ‘g†&&' ”ÿÊêO£¦öòT·þE xûþ¿eÿ«ÿ󿸃{ù;(åR©”A*¬;¬VÀð¸jûáãœÐgÖ*Á~·F˜ze†×i€ð¢ÿšgýýW¡]óÒ„4•¥(@óŠ­ÁWþڵ퓿ñ1-‹bþRg¨˜J;Џÿý{ß;¬!øôOÜ)¥D—’¶ŽöìÙM6»D&›å­S§×ý>Ê­ªË{\ÞUøÄà§¿¼w``ð‘G¡ÇKòó¦ú†Ï1¬hÿÐÄää·QVo øóçúÃÏçi¼ýG_³¿øËÝ=À¿EÍã—ú¨®àµJ5€Ø(T†µŽ©V Àøñ4Ð¥§ô¸B)¿ÐÀñÝu< ŠžÒÛDQ} À@+çÿÙwÝùßømè¡ühóV¡€Ó}î{ÿý°ŸùôgŽn´¤RÜwß>æ3 ,f²œ8xhð+õ´á÷¾¼ko>ô‹?Ù×Ûû…‡yˆ=»UzïÔä$#ÞTßÙáaž9òí3㓉Rþ1TnEûsT‚@ â÷þâ5×þâ/wÿ*ðÔ\þZ ^‹r׉Z nw©ë•àøiàí7³d¤¡ƒÔAJÒ/~›Ø7ûRíKt ½Ü¦{å?}×Í8‹ ®.Qže™BÅ @þ;Ï=÷ͧ¿ùôëçÎŽpnd„l&À#?ÌGz–æf€'|ò*nºÜDò®ÀÁCƒm­­_>ð‘yà~õ`OznŽ‘sç>ÇÈð¯¾úêÜèøØ_¢¬½¿F_†²â‡•?>ùë_..LK|j/ÿøw¨ü÷jA¶j ½Qú¿Ë^M©7cýsÀЩ<“§rØB++¼¦…”> F¨M‚¨ëqÒ´ðŸ¾k; Æ(/k~åzÌ @ ž9rä›Oóé×G†UBV¡P@øèCáþý÷ù+åà¡ÁòÚluyÏÉ5oáίìß_ò¡‡ ·”«Èî{õ՟̽tìØ×P7á0Jù³”-ÿ*«þèkcÅÃö…à»ÀÿÀÆ-úfèÿf`#Ö?|Ìà­·m¥ÂSX- ðBT±þ!¥/Yý0$ÌÀ`ø¬ ú¬{‘2L Á¬·-ŧ¿uøÙW^ùñ”íR©zèwí¹¡‚_ßXF'ý™— ðpxll”óccØ…Røðý Ü¥^‡®âuWà=&× Zš›ÿÕž={ºï¿?R lÛæüØçÇÆ?žW~ü“ñ…læ¯Q´ßWþêV VÛÞÂ7¾ÿ¶¯ü_asоž•_kìFhÿf¬ÿÔœ˜€bp©ÿ…a0ÐVÉ4½:Ð}÷A_íF¬š%€@ikT€@Á»>YT v(ŽOLüä[ßzæÄ…óç÷\žîn¸?Ý*k0IÝxÏÉ5€û>ø¡G{{{ëCû÷Ó××  ïgüü8ÃCÃ+Ç^}åÏQÖ%hùƒ‰>%ŸßhÙSø¯ß~Í (ÿfƒ{ïdÚ¯}¯å¬gý/LÁdõ;ÀjN ðô!Ì4p ‚lAW@¡‡Ý‚Àñz üûo»þtà²wü±Š@ñkO}ýÈÏN¾•>?6ÆÜì,û÷{ï»—hCÔ]÷œ¼cÐ4ÍØÒÚþGûÞ¿—ûîûétš oñÎññó|í/žú60œ§òázŠ·ßÿYû¿=÷OìãI”òßÉ·Q_#Ñøj¥V†^­>¿½ÚËCÞž†s~bž^NÐÓ¤ÒKMóê~»ß¯&šÐЄDÓ¤·ÕÕV4)ѤŽ&½1Ò§K4i¨}]÷Æå6ÃïóÚ -Úqÿ%0/¡¦ý5‹Àâïþ“ü´mÛFJÁ}÷} øŠ¶/×]÷޼c¸÷¾þQÿŽÝ¸ïÄbQ&Æ'¸à1€£Gþ x ¥ü~`)˜ï@ÔItÝïþíßýÿâË_Oìc/ðo¼¯¨E÷׊È×RÒ ²j«¶O¨¾žøýÌ \ÖTlO×¼\{Q£øcjí Ð5.ºÐT]jèR  ©Ú5 ]èª]Õ§It]¨ñZ ]x}šÊöÕ¥P[MGÿã¯üPzò?\ôΑ¿šòl༎üÅ_<}lbb‚‰‰ víìç÷îó„z/lâœÕåÊ;MÓ¶uuuý£÷ßs{îT¶ßäÄ&&&=7ºròôégQA¿,UŸâë(vÞþ°ýÉ¿ñ÷ì >ÁûèEEû“ԦߵÚjA8\o-«¾ž…ƒ„_NÏÂŒ—®_bûZ PN篨ûýÁ}Þ]CÐ4µ/%B—j_è©!„T}š×'u5NHo¼î««1~¿”ˆÇ>ó›tÝþĤ÷¿Í¢XÛœŸþÖáçOŸ>ž¸pl6 À½ûö±§œðùƒ‡{7w7ÕåFÈU€¦ibß¾ýÿóm;ûïß÷~ yõ®¾‰IeþÛ×ÿü¯€Ó”_ÔQ¹ø†è¶{î¼ßþÈÇ~ÙùØãÃý̽4O¡–±ò•´–òoÖ¢öµ”ºÚûü-¡ýàg¼=Ó>•'@ïEª¯­Óܯè÷]¦ù[¡(¿¦¡‰ ; ÊnƒôݯèklÿéÿþÖmÓÞ9¡üBÈþ³ú¿žœ¸Èä… tt´±ïý÷ÐÖÞ ¼ïªn¬º\W¹jH¶´ÞÑÛwËç÷îÝËNoÎÿâäE.^˜drb’'^wpžGE’CÖEÌ~{ÇÝØû?ò˜óÑC¿âFL$ð§¨:¡ºÒYÛÒ¯µßˆµ+v-÷ ÚÛ€NÏ©©3é­JÁ‹ã‰@\O Ä÷ªõ‰*ýš@ ©Š¦!…Pmº¿¯#¥¦ú¥ðê^»jŒæ/¥:Núûºªÿû?; Qÿг”ÜYÊ- ¿øÒ‹§'/N•rî¹g/{öìAJ êYÞÍÜSu¹þrU išqûûvÿ~ÿ­·²÷n• ž[Êqqj’É©I&'/òü G ¡ÇxÍ"fO±«wñŽûí~܉ńöÄ>~øEï+jYü0¥ßÈýF€ÕÀj3`Û…´Jð©jÑE` hý õWc @Uf ÁÁ*LÀ ßúk¡  DÔ‚ÁÄ@ ñ øƒðúoZºâŸï?þ“?yvjò"SSS$“ ö Ðî-0JÜôrU`˜Ñ;»¶u=>p×ìð¦ý¦¦¦T¹8űcÇÞ^¡¼T·g¹£E¢·»ûï²÷ì}À½ïÁ»­m í3÷rð‡¯¸š©ºjûaå­Ö^«°N›_ŸZ€aðÕÃþ?5ګŪµùí5ë!4åË Ð„òõ5MùöBóâº×.Ëc…ôâÁ­Wt‰ØyÇ=ì?ô¥Ëê«JñÿmÉsþÔS/LMM17«XÀÀÀ]ܾû}~, ÎnrÙ4hšf Ü}÷ßïíÝÎwîÔ[|.MO•@àµÇÿ’òã¥í1·Ù=ýöŽ]Î]÷<èôîèEðw_Tà å¯fÍ7bÕƒ.€_‚ûµâÕ@"Ì 2 ð6«óyV)pµ Ÿ¿¿ ¶Õ/@(E9PX¡‹rðPÊ@ÐPó†^ѼáßúÿÕJ²ûþˆ(/ËîÎÓ‡ŸþÑøØxnúR™Üy×R[Rþõ¬³€›X®†ôvní||ÏîÝ¥7÷NOO3=u‰é©K?þÓŸ'©Pþx³³ØÚ}«ÓÓ÷>g×ûÜ÷í¹Çõo4à?¢(f0ðç/µ^ô¿V¤³~þZ`«@Ñ׃Ñýj… Pm? „=ÜVd„gå¥ô@Àcš,÷ o¿¤ô>0èåÙ@|áŸ|5M´ÕÆhK£À‚w®–[¼SB IDATŽ|çÈ+—¦§I§Õ*a{öìá¶Ûúë,à= ›MÓŒÛvíù®®®Äî=»° f.]búÒ4—.MsìÕWžBùûËßf'Ú»í®í·Ù}·íqvÝùÇŠ–§ ŽœäðÏØØtßf,ÿF}ýZ€°Vû‰¬j¯jý )uj±¨ÕÆÔ å×Êm¾¥÷Ù‚¯ô~ÉðúõÀ4ckgOüê?¼,Œ¨€è*`ÎןzêGã¹™K—èhkåŽÛo'Þóo'7sŸÕåúÉf@ûöí=ŸÝõ¾Ü~ûû˜™™afz†™™Kœ>}úG¨\Où£EÌV;¾¥ÓîìÞál¿e§Ó¿k¯ÛÞÑ¢é²|sJ‰øÞŽšX 6kù×ò÷«Yÿµ|ÿ`ûÙ,,U£økÅX )xX¹Ãck‚€VVb-èèåº 0é±M+Ç‚.€?õ[ù®ž]˱TŸ)¸èåï<÷Wf._f)»Àûvßζžíþyûü&ﳺ\'Ù0hš&ÉÔ¯tt´·ïÚu–©^*93;ËÌåf.Ïò×GŸ?L9àgcµ9ñ–N§µ­Çéîéw{nÝíöô݆ ¢R”)ëÑ1þ%j±ÍøøµÞµ*õµ¶—³*O~MË«-}ª¬VrÊ­Ué_Aå­×¦ûç_+ƒ…Ÿ$ô28HYÉ Äßþ{8±bZ4Ù7Jî²÷k_êõ™™fg/°³ïÛu†¡$ëˇݜ²ÐÚ×wëgzzzØu›Êû^H§™™aöòeFGÏý¥6XEMÙ‰d«LmµÛºzÝÎî~§÷–]n4&”õ—êFô­‹æ¡fàKÀ[\½¥ßh´ŸM¶äìPÐo=Ÿ?\Ö‚Zl ¼þœ0 ]ÍwüY@›¿•C ²¢{Ç]Î=÷>:ŸjëÊ#Ë(pm»p娱c¯Ï^¾\ •îÚÙOë–-þýóÙ ßiu¹n²ØÞÓ³¯¿¿Ÿînµ^üåÙYæf¯pùòe~ö³·~ˆJò±…ÕbÇSN<Ùæ$·tºÛúœ®í;ÜT{«¦¬XùVgxЬ¿ƒ nô!ŸúûÕæôkQ[¿~zœµþjƒ„Æ­ÁϨõ;ªÅ‚€œ!«d 2 Ð$¢`#õw2f$FGOÿX¥XÀ×þÛ×<;3ˬ÷¤`?½Û{ýów  ¼ùdC iZÂ4£ƒ©TŠþ*ëϱm®ÌÍ1;{™éé™Ù3Ãg^i 3i7&šxS«ojwÚ:¶;[{ÝÎm}D „Ðwí © •‘&„—¦yÙiùÚ,—€¿O9Ò¼Y…¯æ@u&°‘¹~˜XR©°òjJ00X„W‚ã‚}Ám0“0œUX-cPCWD9SÐßjó/¼ó^Ê(ô2ýLAMWu]Sß·hwÝóP¦µu[>ÖÒæç0:6:uöÜð¥¹9å´µµ²£ÿQ€ú£Â7™l”lß¹ë}÷ötwÓwkWææ˜››cnî ##ç^la69MÍvc¼ÅiL¶:ÉÔV·}kÛÞÑE"Ó4‰øÌ½|fG’ÿ»D;Ö¦DU5ĉF€Í棱¨´ð„ú‚’³ÕÂ¥òû×*µX¨2&Ø^+&@h#®ë±€ÐÖ¿&𮯝äÿôo-šVŒí=ý3ÖêùÑË/¿1wå …B€·ÜJ*UÊ ¨»7™¬ š¦ ` ¯¯ïîÞ¾ít´©4Ït:MúÊÒssüôŸýPq;Ö˜°cÍN,žrã­NKªÓIµvº­Ý®Ÿ‘†ŠßûñÝ|¾änD.ÂÉ%Ž_æÚ(~5†°žõ÷÷Ϭ¦üÄ& k”j maðëk}OÐ ÔVïªX€ß‰°„ÕçŽ2ÉTg¡¥¥maåçO~ÿ7úní-¹ŒÀ@Ý ¸¹d#  MHó@²)AoO/ è:&N33;san~a&K8±Æ¤K4»ñ¦”›hîpSm¤Ú·j‰¦¨ò3÷òAÔë©þî#ý|Ô8ŧ¢B+ï#§ó¼|wnñ«Mç…¥#˜[‚Œ¨B×7RÖ;®škPÍ%¨æ„ëk¹h^›wž Ô}×+xîÃ×$ì6äòÈG{2+ KtvõfÉÔ²Ùå¥Ü['O ¥¯ÌКJÑÛ»ˆ7kDÝ ¸©d#pËîÝ{înëhg»Zš…ùyæ9; ±&'O:±x‹kÜâ65µÒ²¥-[:ð#Í”) ¯´¿ ‡hBÖ_hÖCßD½¨V`o=Å_ÏòWõŽÍ¡õ,ùFËZ¬`=— Ø&jŒó÷îµX!àŒL $é~› ´¢}ý{–ZÛ»ó-ÍíËfÄrM3ÂñŸ?³°ÆqÔtÀöîMqÿ¼~r÷\]®“¬ š¦éÀ­[;vvwuÑݽ €……星_`xdìD,·ã 'Ö˜t£I7O¹‰æ-n²¹X<ªiñÀÝÀÃ(Åò#ûQàŸvo!œ“¢|Ó"ÔM<¢V~‰êQýZ‘ýZ–¿–ïn¿XPÿkUjÁZ P­-¨.~?¨úq´Ê™„ ð)Ð^Ýq¹Ä}ZÔM‹Öö­ËñDK.bZîÑüàÌü twwѺ¥Í?§êK†Ý<²hîhLÄ£]]]H©†ÏÏgÈÌgH§Ó³™ìÒåX,áÆbMn´1éÆ­ÄšR$[Zµä–V¼ùdÙiñQï3ÃT¾¯ÇäJÑižjBÑVÅ9ÿ8ÆÆ¬ùFAÑõ•œZÄôª¢þ)ÕÜ‚ZîÀfÚî@©Ï§ð”é<ÞyÆ›- @óýó.Bí~Y) »{ûì–ÖmÅ®ž[—’Éæ¼e5hK¹\~âÂ…éŒ]]Ûèêì@”_£}`kP—ë(ëÀö¶Ž®]M‰&:;;Èçód3,fæ¹<3óF4w¢±¸mL¸ÑÆ$ÑhÂÅRÄ“-Äš¯ØÀ'¨Lè Îïß±/ÅñoT:*à»ú}ã*ð*µ-ýFýþZVß—QX­ ×ºlÂíáx€_¯u\E B+ƒl…ÿ_eJP Mú@á·Š úw ,ÇãÍNª½sɲbŽe5¸§Ïœ9›ñ^*jY&˜‘ˆn¬qÎër¥&xÑÿmÝÝÛw¦ZRttv°˜É]ÌÉd¹|%=‹Å݆ƄÛKÒKºV¬…X¢…DS‹fFÔÍòÁÝln£zß{“<Œ²% YµIx8Nm_ß—«µþ 9•ˆ´¡à^­²ÖñáÏ ·U˨UÖcÁq%FåW‚Šï  ýÏÒc…@º2_@îÝ÷ð²0"¢uKÇJ,ÞTˆ˜–6ôöÛã™Ì"¶mÐÑÑA,Vz8èÀס.×QÖb-@¼¥%ÙÝÞÞJG[;Ùl–ìb–Ål†é™¹3V4îFcq×jˆ»Ñ†&L+N<ž ±1‰?Üç#¬Îë·ýæžÆóGÑjûÂSð—Àë¬ÿ ÀFg‚ûáïóG-ÿýŽ_/& Bm¢Êq‚Õqÿ˜Ò8/¦R cK±˜p.€ÔŽ@ŠÝBÛÚuK®µ½+×”lÉ›‹×ß<9žÍ.– mëh#™,¹þõ7 ß$²´Ý–Õݲ¥ËRÓ8ÙÅE™ÌÒXŠFcn4ÚD¬1M%µX¼I³,Sø¾&ða*ƒua*ì¯ì´ØîûŸaKœÞšgŸQ]Ák‰Ky‰._‚û 9•ß^B_Cª5c`µ+l[ïóÃnUÐ (±òuSî‚Yßm@1€bÙÛw{>žhq›[RyÓlÀŠFµ‹““–ÕÍÔÚÊ–Tsé„<4x`kT—ë$k@°Å²,¶´–2¹XZ^fiy‰ÌâòD4¥!§¡¡«¡ +Ú¤@ žÔ¤¡nœî6š€»XmíkKÂ?¸UÒCˆþS¥Ìª%Äßbý)½ð~-À¸HHiª}ïÕ”I¸#®@µcÖ rBã5ß×÷éÐ÷åã5 Yt…²מ)MÑÚֵƜ†ˆÉøøø…¥åe@½V¼uË–` °În© š¦E€¦¶Ž®žX,JªE@.—cyi‰¥¥e2‹Ù³VC̵¬‘h#+¦VL³bšeEKsÌûû¸›µ¿Úô%á·{aÛFèó|õ”^­`àzâß•Ïúפå×¢¬÷¹ùÞZO®ulM7À'þ¾Ûåõ§a+>7ðt¡ëªœi¢%𷨉dK1OuÓÒ.MOÏ,/-•NrsªÃ0üÝ»6p]êò.‹^£= Ä»»·ïŒÇâ$›•ï–[Ê‘ËåÈå–È s ÑÑXËŠaZ1L3¦YV£0MSó(<À­lü‰½à6"á31ø³eÈ *ß«äïiøaRwËÿw-´µþ½„µ©ÑµúG7"e ÜŽ[ë{mop5HxŸa{…Põr²@y¹b4p(Ø`Û°­gÇŠ½’.6%[ 89¦¦.]Îår¥LŠ–d –e±’σzƒP]n°ÔºÏÛ"¦'â$›šÈå}ȱ¸´2bY1,««!®E¬¸fD¢šmРË$«hò¬¯øµÀ £~-¦i]ê›V9ÇÿÇF¬¿/ùœ÷´ßµ¤ýk•µ¾g³¿a#n@°¯4V®•Ÿ@(@e_é8”aÛÈ‚ìéÝ•·¢$“Í…ˆiiéÌB&—Ë‘ËçH$Á'ë.ÀM µ  ÑÔÔhJH$Èçò¬äòärù++ŠeE1­¨fF0#–f˜ šiE‰¤”þÛËjÿ¿V_µè}[ þf4°Hù‚z¡Ÿ'”j`4‚—SÝ›¨ÔŠîW[ëX5« VõÛý˜àlLE† ?5`ÛˆT«e MÉæÖ¼±4Ë´´™ÙÙ‰|N@S¢©ôþHÔÛƒêrƒehšfÀ¡iÄc1¢Q…Ú++Ëäó+ …+ Ñ(–Õ"VL3­¨0̨&MKDLK Ô (oïe+Jq×JÝ]ï >hm_Ž*& ‡‹ígÔ4ÞPË“•þµP=¸ïÔúv«>ûÝ.áß~5Ç÷µ+Bu¯ ^hª…>7°V~é¨ë¢ÛŽ*©ÖŽb2Ùb7ÆãÅHÄÔVr¹üJ^=oŒÑm(ôúLÀ—j1€RR—Äb¥ŽB±ÈJ!O¾P¸hY Z$ÓLÓÒ"fT3" B7,!u)|ÕêLÑÎÚOñëµæíýí–$|* ß*¨U‡×” d㊠Üîý?¾•߯§mÀ£É×]jÅ6'ØÌøRVÅü¶à8!ÀöÚü×-‡ã¨€mCªuk1“¾àXV”<-žŸ-ò·Äb1c1êróH-°¤Ô±ˆ](( 8.¹ˆÕ,ÓÒ"‘¨fD,!õˆÐˆ©¡n’”Ánjûûk)~-H%áWløNZ½­v•ø7³²°dÀ vqV+?€f«]Üåߌl$Èï+jü Þ*å÷%´+šJ;ÂÛ:¶Ç––Vg6žtc"Šv1_ôihˆÒ`Eƒßr8º‰©.×Xj@¤­£k—”2´¡X°)l€œeZšnZšiZšnXšÐM! S„î(Ú֣膋!áÑ$|w^½¥¨Ì(€[„ŸEÕl„ŸÐ¥‚ tßôßÚ×…jl Bâ•_NXmœÀ›9RþX×U%Ùw #"bq»°²¨ÍÏÏÏÔ=ƒeYXV¡i8îf ¬.ï–T€ÒƒÛº”X¦z€Ã±ŠvÛ.bÊ0-"S3"¦ÐuSÓôˆf†ð­‚';©ý¿šâ‹!ááøáœšº[W–`$ªÖÜêš§6~\7y§nÀfÝ…ðÁÂñŽ÷-?©À@T40,Ž£^•ÔЈ+ CkŠ7sÙYMJ©mŠ"-H+êrC¥$üŠ”ÃP†Ñvl\ÇÆ¶t)53b ô„aXša˜]š&Ã6b-eÞ(Påó àÃ-ðZZ½…¸ªÌ\‰ª,{Qß-¨\¼§¬ÿz²–«<5A#¨øý`5˜ @às\ %™²â {nÖÔt]×\§¬ìFye ¨'Ýp©ï @À²¬MH¤—¹åº.Žíâ8.š”šiF4ӈÌii8º4\„º÷<+ÑÂÚ1X_ñ×Ëæ»; M *x]ÉA^°¨àÿg°) ì5\ƒÊ¡ÕÇ9à:ÊÀÓ²´ÆdÒ1͈˜››»¤ûÒ[Ò#õ©À,a`áÑáÖÖö51ìC¼ƒ‹ƒë:†™X–0"¦Ð SèÒEM /q$ȧ›)¿‰w£Ôß—jûáºoÐz`-Á[våÔ_UñI¼h”§Çêr %žHºº”2bššc;ÂuÊX[ñk‰ ´EÁ²áí%•Ï¿®Ôq?wÖCñ‚Ò ëÒƒðg™†©%IÛ0 îVÞ@7<ÚR— „ 5  Ä§Ê­Ñ#ša˜Â0L! C ð¤«/n-E¯¥ðÕ¦þÂuX={廽öÄá\.¯þwë :¡í¾ìMɨ3=¡‹XcÜɯd*î1çª#•uy7dMàvÑÓ=!Є@Ó†¡IÓ0„î¤&….žb®ñZÖ¾Ö\?5ÚÂûád_vÄ ‘ƒ ÎÆÜÛº\CÑRJ) Ó8†Ð–!¬Ë—5ý_õWIÒ´Ô0Ð5)¥¦K©IM½oÖBØPÒ~G©j­ÔÞÍLûm ªí§,匯x¯®ªKq6ÈXcœ—¨yO :š”RH!5GJ-°vÑÆqê97‹¬ ¶í”^ñ¤Ié½ÄO§˜/tHø K]êR:ޔ޿ÜUÔ|#”¿Ú6xüZQ#m•Ð…饟#—`-õ öÕTh§²?HÛKÓ}Ž÷Y>A¤ì 45á6%šÓ2„Ô,MÊr˜e¥PÀ­û7„ äÿŸ»··wçJN¥Ý !ºŽ”]"†!uCJièŽfHW:òÞ½R¾¾kÑüµ$Hï}¨V¨ÑtKýa¼Ó6¬lð7\W©¥ïØ:oð`'P/mœÊ1¥j•«|Á€¦nè2¢›ÒÑKêê6³m‡üJ¾žxI*"âÅB\®Ìž¥”†ÌÛBJ)¤GÂñž9_¬çûoFÂù.a`¶Xl3`>§rÿ+Ä[³â=#ÁÄ›µú×k+‰«æñÝãJ€ŠÔøéÈš§øÒ)¤1„Ôd³.U.‰¿–D@F×úIuy÷¥¦ ÇuX^./éd&†¡cšº†& ]:š.!5G÷ç ½›ÈUwÑå'ñÖ‹î¯ëÑý õ·©dN`?ŠZøã¦‘ZïÍ"¥¯Ìa½-}–»ÆgúL  ý÷w|PAÅ÷V1 C¥º¡n³¥%µžd@Îoò_ªË5– ø–2þ €]ZÖ b¦A!½ÐfH}LêÒÖ¤®&¤” ùz_¾«2(…[o®?,ëùþþï­V‚.Cpœ?ý] ÆÜÿÍÆ6Kë¯Ê]¨nå8'€ ®—õü eñAJº:¹¶½b Ð ÃÐ"¦bþ’òu¹yD˜›™ÅV¸¤@ÓS§÷ýŸÈd²d³KÄbQÌH3A—ÂRQ^!¥†këš+‹ 4ßq¨°ë%öTƒZ¾?T*zø˜ZãKÏÙê™y³(úÕøîác‚û뱄 ¯_QwÊŠ^º n%b‡¯¢ŸþëSý1H¡Kò¬Vÿ@™Ìb˜¤©Ë à/ýÃÔ5”uô¯¿ÜLf^›Ÿ_ ‹1M,ÓHRÓ )\M—.®ÔÑ„Àµ}ÎIéá›¶À÷U»?× ð…ûƒOÁ†u¸ „]e­ Üƒš®ÏÍÆ|©vâ6ãÿ‡Çûô½*˜€ Ï®neÐÐ=ë/A—І”¦‘¦i ÿÕà ,g+àDŸZ—ë$:Àw¾}„h4æ+Ì2ê’O‚zh:¦³³Ã{žÛBƒ„šÔ$®´A—¸Ûó=]ÈÙ¢Šl¯Gù«I5K¦úÁ¶p¿¿ïƒ† ާßk)úõµ¬ÿ;¥ÿaÿ¿&Kðºâ*Ü¥J_€éI©žÏÖ=@õLÃ"bDšLoM‰ô|š¥\=%ãfàä'YÊÍûJUô¶y×ÁÎf3ú•´bj–ÅŠZ¸8)©ëRêJù`€¦8NλY87Éå–òÃÆ¦ý¨ÒTúàÖaƒ¹ÿï6lFù«ÍÝ»UÆnäD—Ƈ|ÿ ðΔ_/í»ªs„PÊ/%躪ÒÅ6 Öe––”J_I“_)¯æöì‘ÃG7ð“ëò.Šðò«/“L%}%rQ®™Ìü…d<Ñ;7«Vß2-“hC–išºÔ¤”ºp…&°š.q„ ts]N³B÷¦~Ïz Þ÷¾ ¨ÔÙª F9©Hu^KÉß-x7Ó`6,>õwË´>˜£Yb ~_ n€£üÃPŠï k8¦”R˜–•°‡Ëss¥Ä2êþÿM!¾2héÙ´}‹^a>³p¹µ°´}fv¶ä“7D£4DIÏÎtulk¹ IÇEÃC¢iZù™ž[7é¦ZŸ5öýzx©»µ¬~ $lõ³d0Àp=A`#Š5Ö#ô¿ªÿšâ+óÀ÷ýôÀõã^ÐW|ÃðŠ:D×…Ð¥”MQµàìåYfgfƒI@uÿÿ&ð4 ¿npg¦/Mnïî¹{æÒ´ôgc1b±ÙålJêLišp ´ˆ£ õ¦ÿF±aVªu}WX‚ ž÷ûÛµ”>¨ü Š«ÿg`c À:cÖ“«QþÍÈFé8ºïxŠîú4ßc®ïÿ?tÓÝP[Cz«É€Y(¬X†aD¼U€/ÍÌ0;7ü9u¸ $¬ ~  ØÓS“Žû~wff† —¦ÙÙ׫–vŽÇH/̧¤Ôt¡ƒh®¦Û8¦»âÁˆãÀT–tW¬‚ TtæÁòûc7¢ä–>´õ¿Ãv=ÞH’A5 *èFÀ`3 ]mìf­µ€á¶0ý N¸ýo_ f"¾ò—^û‡®aHÙó`zjštz>ø³êI@7À¿ü6e7à2˳i._œRÓ‹còmR½*ÚÕ4\©h fê~¡úÀ©9²]å¥à«EõÝP=œÐC•íš–žÕ໹z0HvüÞˆ\K?~£Ê_KªYÿj`öí+ênàdyèçøŒ ‚8êü™FÊw“é8ŽiF"þ"SSSIeÔ—¿)Ä¿dnK"éÌ-¤}ú¿‚bóÙ\~1—Í´\˜œÀ0 âMq ÃŒÙÅ\ƒa9ËR×A3œHWË–o”Ñ 2÷¨@`-¿Í+up k+ÿ*à-{W1P ¼[¿Z²å¿ëï÷•”ݧüÞúô?hé}ÿÞ Ô}Öì7=Å7 0#)Ÿ¸¨aÂF ›]âÂä¤ÿRPž=r¸îÜRÂìæÖV<( ÒmÀ™šiiˆ5_œ˜Ðrù<–iÇI$š˜»<ÝÞh¿€tÐ5¦1 —·‹ê}Û ±òrãk)~ض…>¬äÁzÐÅð«èa¿Q P˪×òåk)5¥_7øçoý@` ÈWÑ^¥‹ˆ¦©ž²Šè%ÿŸ¥\>æ8Ns¢E]òñ \ô ˆ'Gkü›u¹ÎRšõl€üøÔø¹žÞíw_˜”ããèßÑGS"ISS‚K33]}’)G€+†‹1qMr¹²µf~w[éÍ<¬±õëA«Õ•?¼ïÿ~_é+À è¬VðZ ïlTùÃ~ÿZã׳þ¥è½7Ð Ö€¥÷Ú+ü~W-ãï#©c«´_+¢”ߌTøÿšk"@*î½TvüÂ833ÀjüKu¹ÎRr¼•\Ê 2s³£.ŽsivZŽ£G‰d‚D²‰‰É‰-R8Rj.l4ËÀ±LÈHï&²áì8 »ÛJ:¶–o®—(¿£rNJJå_eõÝxû Lnüqpm€`-_¾–òWk Sÿð˜ZÖ?á÷§Ý`Ÿø.€oñ‹Jñ‹úoHeýÍ4x,À}ee%bèFéýcçÇÉ,V<€ytSQ—ë(á  Rü•Àv¦[Z\Ng“££çK:’L&±L«áÊìtKëÖ¦+4Óı"Šæòê†Ig° ר©~ÜÍSl·Š•·«´Õ*N ¼} hÁ/­°6ør­fÖSüPÿ{¯Pþ5­?Ÿß·ú.ëGÿ½÷Z `™ª˜f™þ Åb±1S “Sœ¥P(¯Ö^ϼy$>ý÷§sÞ~aüÂÄæ­œÕ&&&éêê$™l&Ù’dòÂø¶Ž®Zœ‚Ç,S€ã*Í™`~Oí/ ëY5½ »Á¶u‹¨{/ºñ+@ÀÿP_j± lD¹×’j´¾ZÀ/Ø^€xÞ IDATÍ%¨EýÃý«¬¿[éÏÝÛ lƒ~¿R€eA4⹑Šó+‹É-)õÆÑs£LL\ þ¤Ãküܺ\g¥? íÚµ ÊnÀ ò#cãçÁ±/LLpöì9ZR-4·´]Ì´KiëºttC¢G ô¨…lˆ¨%mé8ÈÑI²¶ŠÆk¶²ÄÂU[ÍUm­,Zh»‘"[ H'Plý~BíúÃc®E©õ¹NhL¸=ü»*ãÜÐÖ‰ƒt\¤ë"Ý@Ý©Òî8R Ô]¤c#Ý¢1ÕõµLdÔDFeàw8NÌuÝ”ðr‚ÏŽŒpe®âEÎuÿÿ& ¹¥…Ù¹9×Kä.¢èì\öLÞ±í¹+iýìðYíÁï %•²,knæR²µ#¾€Ä6À±"¸–Qæ³êÅ’é îäKm ‚°ð!Kæ÷}WTZyXmùƒÑÿ`i èCÀúl€Ð¸ÍJ5kïK-Êì [~'T¯Iý)Ó÷`$Ÿ U÷h})h‚¶ þÙEÕæ¯ß`BÔR,À²*è¿Ìår±††€‰‰I†‡†+¦ÿ¨3€›Jt€Ô–-ÌÎÍqúäIÿþñA`å,^š³»»ïÐÐ¥¯¯—T*EjKЉñ±­ÛnY©ÙàX&nÔ‚KMú7ÙÈS·«%ÂBÉüB¬Vä }úò¸àjÅ×VǧþZÙíµ]Ðýi‚ xã7”´–"oVÖRü`5åŽ û‚ŸW±ÈGÀß/)½W‚¾¿íýìP ÀvÔXCzÊoBCD|@r˹æ–T o 16V‘ðwâÙ#‡G×?;u¹^"¶lÝêïû÷“ÌyÛâÐ[#§\» MpúÌÛÄãqR[¶¾2×n(Àˆ–rô¨…nEÐmÝvÐǦÈgs8®ƒ°)—Ê}¿8ªTÐx¿=°•~q½m`¬O›u@÷·N`ëúü~ªô_«Rí3ÝýÕ·[åsœp»ƒî¸è®‹îxuÇQÅv+÷]G³mo¼‹îÚÞ~QÕ[}fƒw]K[Qñ¿4Úv±Ô ÀgNŸáò\Åú«ÿùܬu¹ö"ÚR)¼”M-‘lñÀ jq°’/dϬ ™t&Í[§N“ɨ´Î-­­$“I}èô©)‘ºz¡°Þ`!,d£…”BùŽ|{”LÑE+Úª8Žš£_ñ} ðcÕâ2¸ï€ðþ/ß. TúÐÔð¿«Å±„”ðqkÅÂqŠZ>¿[¥?ì÷—|}χ/mCm®[öý‹¾Ï_,ÇmYtÕ¾m#  \ר¥Vóþ#ŸÏ77%ÀéÓ§9ýö¶]ñ& ¯^»[·.×B@G[ÍÍIw[g›÷òÜRp ããco8¶kæä©S´mÙBk[+ÓSS­†À0t KLjšeKa™epn’•ì®í la»ÛVu×Q bÒYô”¹èÕ½²Š!x–_÷­¿²Ž„,j56à©Æ ‚c×+áãª}n5Kç÷WïÂ*Ëï°î®²î%&P,×m½è¨­où][±ßúÛÕ¬z¬AÕdÅÿ]\\Lù«ÿüìÔi.LLïµÃÏ9\_à&ÐÞÑFªEMÛœ:uÚø.À2*X>sê'`jf†“'OzŸ hmoÇqÜøÜ婸!Ñ CQÿ˜¥n–Æ(ºêFrlô¡q–lͶ=å·®°]¯ÍO¡+À dýe$.ƒ€†oEW)ÊF€*•¶ ¬Uj[Mñ×¢üÕÆTU~ŸÖ”¿‚úÛØJ¹]Ûë· 86zÑöŽsضº¦1K•¨wMÊÿ5aF `||‚“'O†þ©Óÿ›Pt€­Û:híìäÌД×ð3—P@Îe—2Ó ýg'O‹7ß<Åž=·ÓÖÖF{GÃCCmÐp·1Š»œƒåXÊAfIEûƦ(lï+‚ÀÁEx©»*简ë/9†7àJ× Ú…g•m â_Â-˜à°z&ÀñêÁ'Žüý \m0ÐY§­Z Ï¥2 ž p‚u'ÅwÊI;¥4^Ç æ¹•?×.ùlGµ‹ê8?ò³ ±bQUo¨\XMf2íñ„ÊýãÍ7>;ì}öÈázôÿ&ln§³£ iJ(ßW6åÀÞ#ÂÇ~|ì9´±óã¼ñæ€zB°­½ƒ……ts6“m0º©+š‹–™€!Ë”sd‚Û)³€¢°‹p‘%& æ …ã”è¿p–ßþOûË>±Ú®²þa‹º-ß(Å_ë˜j}Õ¾;Ød&n¨¾Êò‚~v˜ øß§þže·í23(mC@SW×/Eo´ªZÿ¸‹Û0==Ãëo¼I:]ÁöëÖÿ&`Kk=Ûºèhí`Bùm.•ùK¨X€Y(,,,-e–øÿØ{óø6îûÎûý›’"EQÖaɲdÙ²d)²e9®-)^;v.§Mê#—“¶›®“&v·×¾’Ö=Ò#ivg÷é³í³»uºOÚˆ¤¾¯ö+u+›†L“’þiÈÔJáºn[NþìzõÇôöˆ·þž¾ŒGu•ÞF’>€ŽVfÌ袳½+~,2"ˆƒ ݽû6ákGòê®W©Ìèêblt4ç8eKÃÒ12)ôl=›BϤÐ ôPe•ê§ì+ɯ|šï£»>š¢{>šç)m Ò |t?D |t?¨ñ T‘À£Ö9XïqxÚãûê#ÁXêÏ2ùÚê#AÝ{ë?¢¼õ¾|¦‘wßó•‡ß«fñò9V/zÈÏFž~ßS¯Õ93z&-ÿÑ¢×F3ÒŽã䇨ýên†ÏÖTþ]uþ]Á¤´MË3cölæÌ›‹nš@¥0(€"PPû¼ÁS›Ë¥Ò„],²k÷nötK‡`çŒÌèêb×Îí ÕÄ´‰™Mcd›0²i¹¤£ilq|Ï÷Ñ\ÍsÑ=O1·4ô0bzÍ dXÊ‹~°aåÇkÔÇÿ• ßn¨þ×›õÇhàÈ»˜CðBxú_M¶ªj}àWÕþ0Ï5òøWTúF±?æí÷«ªà×:þ²µ¤•9W÷7}ßoËf¥í¿ó•ìí驟þû»oÝÏ÷*½QÒZ[:˜;«‹n˜ÇÂùóãÇ=$DZ€ñ½ûº7=ÒÇίàûš¦ÑÕ5ÇqÒ£££À°öc6…Ѭ~LM)ùó|Œcãé ð”?À•ZîÇ4À¯H(- b’LBI³ Êø~•aôF Õ¸4²ý/ ¯çü,?bþˆéc6ÿTÌÖ1vd÷{~Õëï×­AþŸ²)Œœî¬5 ìÒ¾ëfúŽ÷óÊŽ]õyÿÏ\Íü»²IÐ5k:ç°àºëY°x1ÙŒDôu÷¬ ¨ú jñ€`pàä&×-ÊŽÃÎ]¯²}ÇÚ;Ú™9s&{vïÎ#»DMjMM 227 T?Ê£' ”ô×]ÅØÑÚsÑ}íª¯†§??èHe•?ÞÝSRN1L$]L%ý™â½S-Î1Õ{ëO’úÈûòªTœªÁ˜ß«g~Ë^ׯՒ±jÿgÙŒsbÒß-—[¢¸ÿöí;Øß{Uú¿ÓȈ6:»frÝ‚ÜrãÍ `û¶máúçÖûímå¡áA9å7˜èÞÓ½~ù»Þõþãý¼¼ý^¿€¶ÖV®™9“s##æñ¾ãM³çÎv4³ (¥ ì‚ëIÇÓÙóÒI51'Îv¶£‹Pyõ4BÚSå=¡ Êò@¾Fˆr|¡©Z_:”Á ’ã/kb^¼úÁõ¯§¢×Ó¤Ñ9ã½Fû‚ؾȓ…î"^X·/rø±°ž+æ ”s/ðTÈÏ«ûT_æùç2Ь–lš&ÏSJ™ 9ôo÷žnvlßÁù±‰ÊAß÷þóŸý^ßëx\Wém¤Êï9‘Й¿`K–-aÅò[¸qÑ Á=÷®‰Ì€20AU ðO>_°í!×÷Ùóê.¶½ô2™l–Y³fqôèá J H€Þœ‘K6ƒžË 7§¥#Éóц£ch¾‹îzè¾[‘þUm@-ñ}t VX¾rŠyÑ1yÜTJkäDó¦p¬ù ö½ÙK£ïhTËPMÝõÂj:o%½WmG÷ÄM¡Ø³ Cåô Ô3ò,ž\„@Ï6ÉÿQ“ú_5צüê€iÛvdÃÏmÛ^æð‘#••ï{CCgŸz~¿Wé ’ÑÙÑÉÂEófpx˜‰¢Í_ÿõÿ/ Ó+—Ý då§0¾uˋ߻çž{<;ÂÖ­Û¸öÚ¹,^¼ˆ™³fq~lLlß¶­é¶U«l ÌhPÊ@ÉוD\_&¡AÿÄÜ.4+ð¥¤cÒ%ýÃPí«H~¹®ìª­ "©¨diZ5”¡`#-à„þ¢¯«§ Áñ n…÷¸ˆÔ‡ýüP…ò"- *ã$}lñ¢µ[} Râç2М­n×üAét:-^Øú;vì¨)ùýê«;·p•®x2êw̾æ:Ì?ÇÀ©~NäÌ™“ Ž‹Œ”Z@H†ïÛ/ œ¹µ½kú =½½Ú–·2gÎl2™4³fϦgß>}àÔ)«³«Ëh6ÁËTˆ®*=µr8yqÍt4C'DWé{>hºRý©úkŠÑ£ÚßJvŸz¡LÑPÒH¦÷ƒê9ã@§8Ó7bøË1ê?ßHåoOb|¨ ì˜Äü³Õ_•÷Fê|´Ï÷Á1»çÖ‚@B6¹&Èg%ãç²|³º¦iÀ‡xñÅ­ œ©,&ŽìØþâŸ^Æ#ºJ?AšÙ\†9sgÓzsõqèPkX(œTÓ‚-$$Õçõ»·ýó½Óï_PvHlÛö2sfÍâ¾ûî!›Í2gölŽ9bvvu„:O˟냓dŽvN!ºÚAÊ®×ä_hʶ(›T‹öÉãaÌ I(P z-_ÔiÈÆ%ñ4áˆêy ªo»Pƒ‹IþøëН^DŒÏŤ¾’ôa ê÷ãZ€bîH¨‘ünuíªÏd,Éðù&)ùóY Öu$Êå²™H$(ØÏ¿ð"ûöî«qüõôìûí0 ‹x4Wé ¢IÐ>­k:fÒÑÙA>›c€S!ò7UF@DÚ„¯îÙóìÒeïzÿЙ!±yËfÌèdéÒ%tvuQ(ؾm»yÛªÛB*esVþðü˜„ Çå²P€3LË+u^WÌ©4M«v÷ êT[ %xDœFÚ‚Š DÒA¨EZU0€ÉŽÂ×C 58Ó«×a|;ÆøËô cÀéÅ^ûµR*æwcÚ€ïÊy%ù›³jm1yŽzå÷cóó›ÙºuvÑ©>~ìØw†‡¾óÓUz›©!ärYZÚòLko&“©tð Zºdü$,À8¹e|ìºóùüµû{zµM›žgÆŒN::Ú™;w.¶ms¼ï¸˜=w6 mˆ ©*¹"Ï÷èyùÃŒÊùœ*ÿJÈþã "ã>Š%ýµ¨¤)®=L(æÇ׃AÄù—kÿGT‘Algôú×AUƒ™Òþ=®D鼡bx¯ ˜ßUÿ|¶vid÷Jƒ]»÷ðüæ- ž©ªþåRéLϾÝ_ Ãðb¡¯ÒDS µiíÓh™ÖNs6èSiÏ Œ–`oÛºùC×óKå2Û^ÞÁ6lÂ÷tÓdî¼yœ9s;V"šÕÔ.'×­J éBJ®±q87Zë0¬ü€£±Wµe+?t/&áb/¿N5£„^U ÃjU\àËj¸(|æÕ%¬_˜¼/zoôy/¬ž¯R}wØÅsñã¶»WwñÅ­Þ¯çUŸOäøs}ùü¼FÌoLfþ|–š¦õÔò$7l¢goê¿aý³ìy]¿Â«ô£) %“§=×IGç´ø›"- ˆÔ¢°`Ô?°ÿÕîÝ?Ï;?Êó›6ó£ Ù>lÞ¼yìßÛSó=y]þèZ²µ`  ùC/(­À­J07öîìWKÑ{¢˜w…‰W,fOWcÆ9ÎÌ•¥~Ÿ?8¢|qõJU_‹™ P5*‘TÄA]KÃ/2.@Á¤ *e‹‘ U?ÚŽL‚‹9ý"3 òTÔÿ" CEäù÷}ÙÈ3ß\•ø­9 ¼ <þòvU‹ïçž[Ïæç73>^Mø)&ŽôöüøOÂ0<ÙøÓWéJ¦) «³‹ÝÄÍ‹w×@©$Z€©Î¥ή];¾yçÚu¿™±šZzzzÉ5=G6ÛÄâE éêêÂ÷<º÷ìaÉÒ¥•ïÊ'€œb´È.p~\–O ÕýltÔôj§_«ú ¢ð^Ä<º!E@@tLFÕ‘1†Œ€$îÒ1`¸ªaöÊŸ©™>r ^ÈîŽMrøE P¯é(}éíkZ-j;×€ùƒ ˆzE²aÃf~´~ƒ•ã¾ïMlÙ¼þkÀ¾K|Wé £ À¬Y3¹yÙúûVsüØizö@­1~´N¢\l[6¬æÞûÞÿyô;w‰¦¦,Mé4³gÏbÖìÙøžÇžÝ»Yºl¨µšÈô"ÅȺZFÇå°Ñ’’|™4zÕ("†×©8þt*Œ€@è2Õ.žX$T‹¡ X¸&Tµ„Ë¡øç+ýH¨cú¨w|@gX¿/æ¯b&D½Ç?T>_iëÞËGëf©öO)ùóoÛ¾ƒþð9^;ÚWs|Ó†õ_ž Ãpbò§¯Ò;. ±xÁ†WßÁÙáÆóô¯4 )#í*$¨Èo޼´õÅמּýŽŸsÊeý…­[±Rúàûéìì`î¼y=r”ÞÞ^ÔD"@‚€Ö,W’át£(«yƒ–†)ßW‘ü~u;P ê’a⦃¦)O¼f@šÒ ¢»¤Ê¬P…K¦€j æé4ƒJ80 ¸ãW‡‘ŸB™ÿ7Ù? „lê‘ÏBs“ ù)  ‘ͧÝ{ºyöÿÊÞžý5N¿sCg†\×Ùô_æ¹JW] “ͱlÙRœÑήç~Hßñþ*ƒD HæÀDñÏØØÈæ#ÇŽÌœ?oÁí…BAß´i3 Óàƒ|?mm­Ì›/A`àÔ)T¢ ƒzNJMC“j¼9!‚®ALO¦Œ´€ÈlÐ Å<º,£Z "@Be"©OM‘ÙùQ¦`døÑÝÕ’úh-5«Z†WëIL¿ãWÂ~±hAÜ‘@Ò¬fõE >9¥\ÈÛ°o_ßÿ—gÙµ{wM{ïµk×pæôÉöÀ÷ÿ´¿ÿØdן«ô¤‹@gg'«î^ H%“<¿yKؽ¯›/þê¯zOýëQ¯€¨LTGòƒŒC½=—Ëä[ÛÛÛÓÖo؈¦|àýÐÚšgÞüyôõõqäÐ!æ/XPùά¦@@—Óh S®MÎO¨Á£ü±¦ò ’ ‡2o@(_®ò"éïkUð5É`‚˜™@yW!T1 ˜ä¨gþ³CÕˆ$}´¯†éëÆWª©ð½ó«¤©TÉíƒ@zŠ8Œzzzùçïý€—wÔzüßsÏ:V¬XÁøø"Yöü¦ gtL_szðÌUx’kë·/Hƒ'Ùñʶ<¿…-Û¶°kûßÕ‘€Ð äÕºY/ò«n»ë³ù–ü\4hmiáž{ÞÃï{/íjŒTÿñ~ ã,Z¼¸æ;ËÀyGFÎ`¬ `¢ ÇŽEö½¡+Ÿ.Á î(Ôcf‚¦×ú ¢5Ä4 ª)Ȫ AÈ}—jÔG¢äž8ÃC-ÓGÀwúE QaüXþ‚…*#©‚)¤³4פÖ4As¢A†_íÛ×Ë?ï_ضm{M‘Ï]wßÍüùóI§Ód2) ããlX¿žÍ›6ì>ÙßÿS Bˆ‹¿é-¤Ëáázº,f÷î]lݲ•M?zž-;_ÀuÊ:R£ÌS‚œZÒH ȯºãÎ_jnn#@´¶äY»ön¸ÿ~:;;8uŠB¡P£ €”®ã®bþŒOÈíñ¢Ü.+¥ë1Ðê€@€f(¿‚zVP‰ DŒÿßjuœ?•? Òâgöøëú0`C q›?ž°Iý”%‹z²ȥ庹IÁ% ×î=Ý|ÿÏòòöÚ ¿‡ú(sçÎcxx?®‚@ŒÞÉpI&@œÚÚÚXqómxn™ÂÄÃôôöTûD&@´HÞ:·íÅ-±jõª_Êç¦Ï97*ž{n¥²Ëý÷ÝËܹ³éìêbdx˜}ÝÝܸdIå;u o‚™—ê~”¶­•” -ãE(Ø2Á%røšZû„&M‚ bv“Ìõõ¶¿Ve² \B,0ÞŠ¸!Ä$~ ꜀‘—¿Âø1¦üISöíÏ6)PÒ?›’@`]ÂÿvûöüàÙ°ëÕÝ5jÿ“O~‘eË–144H!`Û6 {?ܽn,Û¼aÓUsàF— ùö ®¿‘Á¡zzÑÓÛÕ¢’ñã $"ˆ<·më¶ÿzÛê»~¹%—Ÿ}~lL¬ÿÑÛæÞ{ïåÆÑÚÖFÒ²8tè ê4 È€eBÒ€DRæ²[¹.Á.)›XÔФÊ,Œ˜9P~¤  *f€« ˆùÃ*ZPÔ?°F^ÿhbL_€Hʇu_­M]Úö™”jߎ@ r楙,›6mæÙ}޽ûö×8ü¾úÇÈ’%‹'½?!d–çÝëÀ·¿óùt:õ;™LfnS:=j¥¬ov´·_r…Ñë€k®é`v×u,X8ð{a(¤E"ˆœȪõèö­›ÿì¶ÕwýrK>7Û.µç·¼Èx¡Àøø:V­ºL&Ãüyó9zä(ÓIgªÁ*hM@²µÊøVR†Ó¶ Gæ ¸e ДeÖ3~ "†¯‚OµB*Ü÷ L¢À@1¶zÖƒAóG?q©O M›l¦:©'£¦öd•ÚŸµ.MêÛŽÃsÏm`ýúõ9|´&Ô÷ùÏ?^Ãüímùø]1<ß<º®³ðú¬{ÏÞ³v-‰„,FÀqÊDU„qŠ|…¢ì*Tp`†¢£´Gi¾Ê+Ðk´¨ÝŽÔýн/êxþPÙœÂùgøèxýx/?öä=¤’ÙS4Y RU韹DGå©S<·~ÏozžS5Çyäaî¸c5]]X‰ÚÆCÃ# 344ÌÙáa‚ “I“N§HY·­\>é»zz`š&™Lz·©›kÚÛÛþw²à €ëºlÛöt®: IDATœ=çØ6CgÏ2köd“ "9‹0ÒœRU pJÕu©¬À@1â$M* 1m ú¢ A@ÕK®8ãûbßoê2Ê‘HÄüjV@PÑ.ƒñŽ9Ê–-/òÂÖmœ>uª¾‡?»v½òOƒ'ÿ×#~üŽßþ§>?v!p]Ÿ®Îv^ܶWvîÂq²MY>þÈ#d³““]ßgßÞ²Ù,©´õtWgç—qW]€F'Q]Rå4Ò±uTH4ÿ®uë>•J6å£ó´·Oã¶•ïâŽ;î`Ù²ªz92<‚çzttÖjq*¶/¥~q(»U(»²[±ïׂ¼¹Öbf\”ÿ%Ũ´üRŒÑ˜±ÐfBE7’f$$Ó§,°´KWõœr™­/¼Ä–_¤»»›‚]¬¢S®oÖ?÷Ü3À«¨#>úÉ;¾ü;¿}I °s×n~ðÃ% Â*jC7xï}÷±tÉ ¯«{_‰„IS:³ÉL˜v´·¿#ýW`ª“W5 )ª -Q‡áж°dÅêOuNk»^Ó5]ÉD‚ëÌgõªU¬Zu]]U`p`€T&C¶Ú¹hù¨ùfSh%·:°¤kšuŠ÷àªê|g[œÙ+BÕÙ%+Ei͆!×ICIþó'UÀ2/ž»ßˆöõô²í¥mlß±ƒ“'&Iý`ltäøÖ­[þ+pXíË¢r8yôã·ùwžzLÄ”žzض}›ž×uñ}Ï—ç—÷+ÐuƒU·ÝÊ=ëÖ6¼¾#Gû¤ÆÍöYÉăïD¿ÀU¸ÐT5“ª9-ÙØv\HvtÎ\wËËï&FT—šÏçYzóVÝv+·Þº’tZº‚€Z§M#jZ9¹€ȪB'bþ²dø²k?æÆºìÄúìUÊqã1ÿ¸ã/FÄ¢Z•ñuÅüñ‡¤)·+ù &$5/–ºÛˆNž`ûË;xyûv<Œã85ÇCßs÷Ø¿áxßÑïƒÈz¡þy”+ä‘G?~{#s`ÞÜYª7à 8å¥Rßwñ}߯>]×Ðuù×Íç“>ÒðZûŽ÷sþüÙlv4mYuvv¼£ò®Àž¤"Œ@ MÕ/­£”á„Z'·Ýq÷Cùlól¡)S\ftu±|ù2V¬Xλ–ß‚®Wåð™3gÈåšÑuƒ0 it{BÈZ¨ <]ÃõDE(yÕúx›­¨g`¥'ÔØôÒªŒ%E©Éº®ªãZ€^gèÕšê×C##£ìع“;wÑݽÑÑZ­: ð'ŠöЋ›Ÿû`/pYÍ7FU;Ë-ê&•š@<×åìðY9Œ](â8NÉ¡Tvñ\— h ÍÍy¾øùÏaY“Az|¼À¡#‡iÎeI¥Ó¿ÛÕÙùÔë|o;]€Ký²jtÀD2|q- MÌ9ˆÔÖ,^¾ì> #Ê2Ä4 fv]ò¥7sÓM7qà 7àyŽãR.ûŒŽŒ¢ +"BÉðaˆ¦ Õj\ ë‚DBDzL’É¡¡ËÀˆRr½XòÎTðT̃ŠôWeʺ’Þˆ˜_Ùó¯GÊÇittŒ]»_åÕ]»éîÞÇÐÐPEÝWÏ„Áþ½=?:~üȳÀIà<0„]=ï(dåmHsàã¿ý·¿üÔ§Ã äüØ(Žã0Q˜àDÿ Ûq(—ÊeW™>Aݘ†É¿ý¥_dîìY ïcO÷>’‰ÙlæÉäcímW~¾ÀU¸Ô/«úUM ñ×Q¯Á¨×ÀÌ¥KW¨£³íßBvõºI{GóæÎeÖ5sé켆0Ô)—Büܲ‡ã8dš²Ê™"Dˆ®C"!°,TÚ$N`YI Ó4H$ R©‰TÓJ€¡W+ò"ˆrúc÷XñÆÂ‹õƒõ^¯toDƒƒCìéîæÇ{ºÙ»o?ƒgÎÔÙù~@8>>vlÛ‹›ÿÙ¾k)ñ‡sT{:Dÿ‡fªæY³ºdñ;¿÷{øÈÏ~äŽãP*—(—ÊŒŽŽÒâ$¶mStJ“@ z-º¡cè:†©óÞs/ëÖÞÝðžöõôËfw'­Äƒíí}oÞ{óé*\î—Š¨EÝO1 R€z M`æ4#½ô¦Ýž°2m¯„B!èš “Éã¹MZ–0´8yj˜0Õ¡¨ë‚Ži9fÌÈ‘L n]=tJjÉD‚dÒ¤©)A¦)I6k‘Ë¥Éd,2 ËJ`oT^¿q:tèûzzÙ»o/bøìð¤°@±dïÚ¹ó_ÆGG6!™} )ù‡ÕRDbX<ƒ³ Éø‘9Ð ´½ôò+Ÿokm¹ÆqÇ¡\*ã8%ΟåäÉSl eÊ¥®ëáû^ÍuiB`š&¦i²èú…|öß~¦áý8p§\¦¹97š¶¬;:Ú7½IîM§«ðz¾¸êˆ†ŒD  ÖV $›!Ù*H¶€Õ¬é©¬Ð’ÍšžÊ[VÓBS䯵P/`=¹Ñä‘¿~%FFàe´d3í‹o­D½Î÷¢4ø¡µ3ôêsh"Oyx3ÐEggó¯Áò×2A-ù͹--šóiššRd³)2‹dÒ|[Á`xx„Ñ{ð ½½½?ÖÏøøødÆ÷]¯ì¹öÞý=›O|Éè#HINm"™ß Ã0BDÚ–E5<›WÛ¹_}òÉüÂg?û@ÚJ·8ŽC¹\ÂqNž8É™Á¡ ”ËeJ¥2®çâ{>a TB…Œ蘦IKk+ðÔ—ÞïÐðýýýäó-¤ÓÖ›4ôN€×] ôF)”W !\ˆY@Ö$,Hf„°Z5=Ý®é©i˜™Ö ˜¾Ásµ¸vÎ §1mÅ*f.YBff;ÍóÊ®¸ž ÙO à«»À÷•º.È^w3Ù…7£!°¦u2ó#©ô (0qä0‡áå¿Ù;¼Ÿlv&«W-æ¾÷-¥%Ÿ¢¥9M>Ÿ¡¹9M®9C6›"NN'ß’ç422Êk¯õqøè:L__g‡†'eðIDà>áÑ£‡·9rðûHfD2þ„zi%õÜ£B®èÿýš"€Ö€öÁ¡¡bPöDs‚ ô ƒ ²øFHgg'…¢ëº¸®‡šÊœŠ˜?z ພZÎð¹/þ*ÿá7ƒ®ºœŽö¶VÚÛZÙ±s¾ŸÿKîêììxìM|¼?õôÓ* „¦qƒ ¹fÓ@´ ÍèÔÌD§af:×ZZ*± œ–¶¥w¿å&fÜy/"©ã 0p†‰ãGY>/Ëô&è´Ê̺¦…93[ ÂÀ‡e7çɩܕçwƒÐЄ`l¬H÷þ~N8=pøœA9Ù‚ÕÙE*ŸA3aðÅ ïêæü«ÛÉf V¯º÷>p‹ƒ–&ÚÚšhmk¢¹9Essú ïœt'sf·2½=ËôÎYZÛ²47§1ÍKS®ÆÇ  qf`€Óg8uú4'OœàÌà ££c“â÷Ñ]…!>剉ñS‡öõìÜO•ч‘¹OãTmþq¤Ô÷‘ Ø”ÿøX´& \,Œó¯Ÿ÷Ýú‡Ïèš9«h;B‚@Çq°‹2 p~lœžÞ^ ŠEå(•+j¿¦iS Tå^â{>º¡³ø†Å<ù…Ç^×CGð\—|s®Ï²¬ÛÚZ¯ˆ¤¡«ð:È¥Áoˆvtcºž4féFêºâØøÃå¹Óßý3ÌøaÓÚ™81Nfä·v¼gõµÜ¾Á·6`Ôê¢yÁõà9œþá?pò{ÿB&£óè£ë¸ùæ.fÎhfFW3Ó;ó´¶fÉådîžmKé8>>ÎØØyFGÇaxøÃg‡bdt„ñóã§¡3 ‚0×µûúï:t¨çUàUÛ~)ñm$ãG³'™Ñ>T̯ ’Â@úæ7!í3íC?ûáe_ÿê×?ڜϵÛEÇ)bÛÒ`;eÇað̇ŽÁ¶ ØE‡¢m!¦)sºt5iHhQ tHx¾4-fÍšÉS_þRÃë:uj€¡áaZòùÑL:õX[[ëOçîþ¥0>TÌ©ÌfSÙ‚xüß=þîßúò—~6ašÙ¢íPtlŠv¹b ”ÊGŽåÔéS&Š‹6¥RÝÐ1uM×Uò–¨´S”†®ë’ÍfùÕ'¿È¬™]“®ol|œÃGŽÒÚÚB&•y¢½½íéK¹¯·Š®À%PB<,ZV ·‚9]$3Ítj–[,¾Ç)zßÜ÷}Šù=Œè{ösg—ËǼ™®Näô•‚[®+ CÅô¡Ü®ÜÒ…n-ªìUmk¢W³ø*]‡Us3»ÿã¾Ä{Ê”g/'Ýžåô¿þ ÇþþÏÉçÒÌžÉD™D"$a†è¦Ìù¿$ò ¿T´ÏŸ;÷Ú¡ƒ‡zgüUI©óÑV;¶]TKY-uöþÅH@þk¦SÍ €öÙÇ_ý•?øƒ{®kØE§hcËÊ7 C„=½½ ža¢P¤¨z𦉮ë“Ì ¢øžï{ø¾Ï/ýâ/pÛÊ ¯sÇÎ]´¶´’ËfŸiooû‰9¯ÀE(!J€–˜šfuk¶0’‹ÇÏû•Ôôœ~Ûï}£5ÇÀËûøÙ-þÐ|š¬j~|²o¥3n(÷E}öBµŽTÿø]52*Û¢Zí'¢íX]eñ‰xÇa£ºýÍoíá[/Û$¬Ä0\ú¾õßzùûÌš¥¥Å%™HZ!‰¤À4+ßV¿% du°ãºCCC¯818p²8‹d`ªtwŒIýh‰¤½ûŒÏe2¿|"*àÊ"A lAšHýÅû‹÷}øÁŸ}ëyFä,ÚU§ ]´ÙÓÝ͹‘Q …¥RÓ4b `TœƒòQ„Aˆ¯€ÀseBÑÜχ?øþ†×º{O7©tš–æÜ¦„•|0ŸË½íÎÁ«pJˆ‡R MÓHtifj¶ÙÔtm¹Pø€S>qÇ-ÿþ·˜~Çíœ;|–yök<ñ©•LïP=î½*Dùøa$ù#)Æ?*·å‚ŸÇUƶ'-±J¾J»qUÔS(·þv7ßÞeÓ±b5ãÇpèé?%)F™s¡eøÂL¹A*¡…ºé LDatâ5»ä–N;88púQN¾§.Ñ£–±]ª Iÿøë²zGÕõqÙÌ_y&U@Žê¬‡ ¢Y©ï~÷?z÷Ú5ï¶íˆùk5ÑÑQº÷îctô<…BA„$’˜¦Ž®›è†@ºªœÔdúpâR p]·\fÞüùüæ¯=ÙðZ9Šï¹ä›[v§Ó©Çr¹ìÛê¼ SPBü|J M‡Ä,#™š/’Ö{ììg33šÓwü§ÿ ÏÓqv¾Ì]Ì-Kšd®}T“ï*æá„ÔÚúJŒÖ÷à«§è§ÈÁÕ¢÷ÄÊwEìý•æ¡Q“eT´SÁÀ üáŸo¦?s™ÎŽþåäìËëÉeýÃva /Ο ™è; e;vuÕQknlߎ3{´OH],ÿ 0΢=ÄÙƒgY©Ÿá?#餒ø®ôM½­ôÉD¬ƒnlUƒ7r'Q믚f`„âU~@Õô¦ªôKÀß|{7ÿÐÖ¢eœß¹…ƒÿï×Hú®P;×ã—‡O…Œœ  q ê6¼º%ÎØeª¾~‰n;²ó§(Oº|Rf€NmG§HˆR…£:–ýû÷>ÞÞ>c–cþ¢Ê t‡c'úéÝBaß÷I$’sÀTæ€0dÞQä ƒß÷kÌD"É_xœÙ³& pâÔi¦µµI7=–Ïçžy³žÇEžÕÛñ5SÒIñH Ä c®žJ_"ý¾ý+LË’~áÇ|fíLV¯jÃ+K©ïyª·Wëä‹÷ÐWºåŸ VÚ«:Ÿ¸`]\P’ÛТóÄœ…ñ±b(?a€‘P€€£GþÓ_mcbÞ„…zþð· hÖ¬±yå³ýa0404R¨xé©•üÑR¯ÞGˤԇ×+ñ>ù«Ž7xMQeüÕ¾ a&íúB&i+Úvìbz{Òwì…B]×I$MLC¬Ô1â³Ú‚Pöp=\ß“%Ç¥ŸúÔ'Yu[ã„»÷tÓÚÚJS6ó»­ùüSoÖ3™Š®@Œ’âá34aÎ1šÒ ½ñ§ɦW®úʯaMŸK°ëþýgÞE{‹lºá••Íïª.<ÊÛ/ÃLJjŠ‚ø³Žû¨uðQû¶K¦¸? ¢HÃXŸÀH+Ъ‘C5õЕ6P*Ã_ü-ìÑnÍñãßÿ”‡N%ÓîßxÎÙ×ü`ðTÀ©±µÒ?Z—cûãÒ^=uoŠÇÌ€úŽNñb¡h œ˜÷ÜsÏ‚¿ùöß~Î÷ݤ]t°•P´‹رsgÎ R.—H˜&f"A"™Ä4ttÃÄÐõÚ´á $¥&7J¥2÷Þsúà ¯¿{_Ùl¹¦Ü3­­ù·4BpIµ_ïÔ´äœDSÓÂòDáÓdÜ•ëžy†âh™ù…“|ìóI&Á/KUßS“|\7æäƒÚšT=õÑþ)¯:¼à˸V/éÿ»ˆáøi5U¢Î?Qþ€n(S ©ºý$à}¯—ïö„´.¾ýßøçº§›_÷œáþ7ØÐ2àL"Ÿ@œñ+Ë[Áð¨nÖCÔŸ!MÕˆ*›¢ãüЇÿÕ7¿ùyÇ)1a+f@¤ ŒOØõêîJÙr2‘ ‘H’4 é0•9 éÄ0€0P>e”JeÊåsçÎáמübÃëßÓ½¦L†–|~SÒJ<˜I§ß’ÁU@zû5´NM$¯5²M×»ÅO‹Lyå=ß|†Â¹3O÷òË¿x nY2½§Zqy®tøÕŒË‚J_ää«0}ݳŽ._‹mWŽMuÓÔ9 Eõ´“þ—±ó#šrj@¨ÅZ‹‹˜o !À4aÃúƒ|ë•·ÜBï7¾ÄùîÃcéæüï•'Î üÑ>Ÿã§}zmªê=T§¾!§Þ¥XùvÔÑ©~èK´Öã÷ÿ÷×þÊç~壶ãY(ƒ¶Ò†‡GØùÊNFÇΣë:–eÕ˜¦n ›*O@µg– G|?ÀWG%Ï¥\*1gÎ,~õ‹_hxíGŽö„>­ù–Ý +¹&›É¼é ðS ñpJCLׄq­™É.,ÛÅOëMÞÊuÏr>ÓÜö%obì€ç_ƒ±Se~%ÿ¿m’þbT§ Dæ@|ÞC¤ dPæÀwþþ»?¿vÝÚ»lÛÅ¢MäŒ4‚áá¶nÛ†ã8RH&° Œ •,¤khêø~àËð 'ýN¹LÂ4ùê¥áõË0¡OÛ´¶Ñ´e­ÉdÒoj„à§’âaS u Œ¹f&}švo(J^ûWÿ {ÄamÞá¶wåqKªùfIªÿn©šÎ„€Sõc¾Ê³mÀøÐÀ™§°fõº¨‘O ¢uDAHe²päˆ|Yº!»ûêIÙìó`ï9þì‡}´/»…ßø#&öÞa¤RéÙã‚Ðy Ä€~»aÙßO’b `PmõŸõ@ÿô½úØwÜyG±`cÛEl•(™Ç`÷÷àù>–• ™°ªæ€ šº®ª5¥øsÀÅ+¹”\rÙÁqJüæoüZÃôá‘‘QÏ0­­u4e¥×d³™7 ~ÊàÑvsžžJ/Bã»pâ#ïýÖ·ð½-Çð‰ßŒë€çH§˜WV’?¨Æô#‰/‚ÉN¾©n×Hgõž-à"ÿƒËuN4¡ÀhGC-@T÷WœƒIH&¥Oà…çñO{'È/\È®_ÿe„-^Ö­ä÷{ˆ×á'üvmÁÿBÊ06¼ƒPyªÍŒs½½Ÿ˜ÖÞ6Ë.±'dÛ0»hWƒ¢§·M,Ë’mÙ’ ’FRf šQÚ°^È …|ף亸e© 8ŽÃç~ù³,Z¸`ÒµŒ000HÛ´6²™Ìc™Lú™7陼§yÝôK<š˜³M+½HO¥n=wàÉ{ÿüϰ:g“úñ^}ä&ÊE(;’ñËåªÚ’iãj…ɪ—Ý¿„Ë» Јœó’Ÿ‚@ŠZÐ ÃØ€¸9… M †%5‚m/aý`†T[žW~å3$ŒÌß…¡ÿ}¿\ÞîÑÎ:á·¯ N±¾Ž’Ñãæ@¤´ }þ£0$]°‹Øö„ª,ª¤!›Ý{ºéëë#‘HbYVÌH’4MtCW!ÂXõV€¬¤)àº.å’KÙqpÊëÖ®åýÜßðöt½l&ûX6›yæMx&oôoˆ~"Râ‘mºiÍ4›²sÇÎûâÊ'>GzælÆ6íä“ÿv…¸ŽT÷K% A¨$½ºæ8ãV÷#¨ºÀ¨Éѹl{? /®!Dï›òؤ u)Ê ~,j „•A£ªíxRÍXqû|NüÝK¶obÉ—ŸbçS¿ò‘lÓœþÐ À/!Kz¯( Ã0BDZ¤¥D€È”á`¯X±âO_Ù¹óß§,+„òêËð^ܼä&9vhMªw€†ð |]C :˜È!²ËªÐ5 _G×$8hÂ@×4„®±aãóhBãûï›tK—ÜÈî=Ý„íÁ_s³ÙÌSoéC»‚é 4¨ÕòºfN72©ÙÎÈ𧦯¼Q›ÿûÛuˆO~l¶ E[VÎl° \5ŒÃõÔdÕ‹ßq¡ä«¡j"O´xªG9Z¼ê_£}žêéïù^¢÷V^7¸׋íWKYE3œè>ðßbäÀﻩ“¶(¡ä€kKÉï{Õð^ßV"د(Jb×Dâ^ÿúuh—õþ |>JTª”«ýZ,R Õ"\¥ ›$-Ù¿ðÿyf3­wÜÅÞ¯ü¥cÃ/ SÆ·½!îábø×g/ïJß>Š™‘S0JÊ"Í€Õ#ú}õ×>þÙÏ=T(°'l Eé,Úr®ÀøÄ87lÀ²,R–EÒ²°IÌdB&©„!MDU„a^èã»1Ç`¹ŒSrpŠ3gÍä ÿ»†÷ †²´æóÏärÙו0ôN6.,ñ°)0fêÉôB«%ó¹Þ¯®}úhš³˜i'Opûêk(;àÁÙÿaÜ»åö‹óÔ]Ç¥>Ôz‡`ýǦÚ?Mõ8.ôœ*ÇT b®hµ™ƒÄB„ å°ÒÐô,ßß;Bóµsxá³%×<ç?¹Eû… ìì ú‹á_ÛS|õOœêæ?&¨u ¶Æ¶ @ûѳ?úøŠÛo}·dü ìB‘‚€bÑfhè,Û¶mGt:s Z$>‹U² IDAT& 3nÊùº0dW!•#Õ ”Ü2e§ŒS.â8et]ã+¿÷TÃ{ØÓ½l6Ë´Ö–M–e=˜H˜—•+ðN€×aèÍB˜ÓM+5Ë<ûÉ븟Žå‹±_íeÕêk(Á)@© M€R1¤ìx倲ëã•=<ÏSN›2ž'åy^eñ}¿æu|ýâyѽϯtœõ¼Fï»ðr¡ïn´òu¹¸^×óðÊ¥’‹[ò(—}¼rH©Pr¤IT´¡8]s§1OÆó |ò(œú%=™ºFhÆt˜zêé@Qwgªu 6Ò( »EÛ>¾ç¾÷üÕ©c}½é´EÊJc¥S¤,‹´%³´µµqëÊ•„a@©\¦T.ãVxøOÍVת-ÆuSšÉD²b¤Ò)Ré4™Tš €/=õû ïaé’!:;|·í7:N9ßðÿÒei–x$£aÌ2R™ÅFSöÝãCžø¹gÿC‡¸k^ ù·%;À-úø¡ôìAPAÊ RÓ«.¢‚^l_†o:ò^γ¨oÍk]ªé„"DCå¸kÀL$2+%¹ãïÿi M·ÝÉ«¿ñ9ü‘Ò?#Äÿ8Nwˆw̾òµ€¸9MŽG¢D! È9vì‰|.7«X°eÊpÁVyE&Š6¯}½ûzH§R¤Ó–•Ʋ’X ‹D2™01u!ÐtQ}Ψ®B®/…Œ[¦ì”(:EÇA×u>û‹¿P3a:¢#GŽmm­»-ËZ“¶¬KÒÞÉÀeEZ“¦FÒºÆüÄŠ'…PƒY¡KsÞÀ)È*w§èQ*ºx%!DlFœÌë›c¯{€Ñë0ôB}¶þs†r\nEl­†SõèÓ¯ß;—­b¢ˆJÓ M„¼ÀÃMBß Ñ+Íä従\ÿïž`×—¿øþlËÜ®[>úâR²^‘›ñÒñW¢vZ1iÁüùó8täCCÃ˦µµl ƒ`Í[U?p¥Ð%@J<šÖ0¦i k†Ú2Í,´Ýð‘uÛpŒ{o›ƒcK»¿d—(Ù.å²ìæFÉó êÏ܈±ã€àMÚWÝö'ÀÔ |ùtA)?å>M]CµjH«¼O‹i€¦á{>&¾HrÍõóØûý0–¿›ŽåwrþÕý?g¤§ÂB0˜Œ]ÉZ€¢xt HêÇ"¦Ênáì­·,ÿÚK;wüZÚ²Ò¡ê \ †Ì›;»(§iºŽn„+Ðt!t|MWL ÐÐ4M®z(Ð…!?§é Ð4MžþÆ7xò _ ³ÌŸÏCÚ¦µn Âð-©¸Rè24‘Õt£Í°R3&Î ýüÊ_ŒÂ,hIE; \,S*Hç‹ïŠÙ•êñ+¦¿\Õ¿±ªå5ØwùjÙ¥1wí¾ Du[æk¢ qMÀÊ$ &Ë—.dó¾ýÌûħغëc«› ÿ^8î~pEkÐPˆRšEÝ¢¢÷èÁSò'òíßý½§ aPI÷ ‚0X¼hŽãpndD¥ëÂ@ºnàë:šêª2SUêèèz€î ©)èº&d[r•+ðôþ/½14tvÙôöö×l]_“¶¬+bÁ›M—–x$­c¶h‰d'p³žK_ÿs÷srýq–ß6g<Ä)–)Û%»„[r+Ì1¾PIþ%y-]ˆá£1ß:~¹t)6ÔTŒm_"¦ƒ‚|-“^Bß#¾ȵ´ÑáÀk½+îbt÷áŸÓ“‰“ fÄ#ç á__quSÔ♃Ñyÿøÿp‡ï»â©?øƒÇ$†R @š·Ü|3{~ücFFG1„ l„'jÌ@ÓeW•‚©#“ƒ´Š9 ËþƒºÔ"4Mãû?ø!»È}÷¬«¹øE D©ÃùŽööÈø?. "­if›ž²¦;#øõ·žÀ†™MI씋%ŠE‡r¡„c—ñ=Yâ'JêSÚùñí•7dxüÁö†×ÐÓçð§ß¼(h¼ti’Þµ(=åõî{­ÈŸ|ëtÍû5ÕW,Ò„ùÚ+ð AÀ Koä…ý½\÷©ÇyéóŸXLÌý;·ä¾?BUª^±¤†Bj 2š÷k_ûÚöxàú•+o»Cv"¦ÈÐì’%KØñÊ+8e§bÏBÇ2 Ð×uô@C¥‚aT9†Us@ÓÑU–¡.dKr¡élÙò¸·ÚZ[ B<3o§}#!oz%áOš. )ñˆ!Ðsši´i†~­ÏÙ¶ë?r}?:ÉÂ%3)Ž—qìåB‰¢íP.–å»"ù!rùGÒ»‘„B0»cêË ÃÏó.Èèo.,Å'¿ïb×ëºî¤sÉZšª&€ø„aH  R™É‘“$oZD~þRœSgÖj¦q*ð½Á´xdüà ˆ@@ MªO 2"Ç`àî»ïþŸ7®gåÊU«ƒ0Ò)ˆl¢À`ÙÒ¥ìܵ Ç)«â éÜÓu©ÒK[?DףߛrHsÀèº@S G„¦+¿Æ–·¢i‚{Ö­­¹ö¶VBÏäÛÛÙá›ZIø“¦‹€@¤5Œœn%¦¹cw_ÿàý”& Oˆc{r@d±D©X¢d¥ôQã­&«êõÌ_¯]ž›ò:.o„ù/)ɧÁ¾ ]o ®7þþjÂVõ h² ¦+„ô‚¡ ®?›£ýC\óþ{ÙÿôŸ­µ²-?ÔÊåÖ Ð†¸Â}1ŠÚ9¸êu‘ªI÷¤Ö¬Y÷w'OŸ¸&›Íϑ֣d|TíaÀòåËØ³ûÇ8Žƒ®iQd@«:û|MN2AšÒ#€¦K§ ¦{Ò‹èš`Ë /÷¬»»æ&ÚÛÛÓùéííC‚5¹ìÛÛzü­¢K€”fÍF2Ù:qþø-K>óuÎgöŒVœbYyýeuW¹è¨l¿ªg?ÎàÌ€h߃wµ“I5 ëI c ÕèÜo&]Šóïƒ?3í‚×KÝõ†aXJúS z¾G¨Aˆ ¹}:ÞÎ}tÞõný×ÿ–š>GèÆk~&-9g‡ý¦u~«H©ñ-ña(@­S0ò fθæé'O>™ÍfgjbJ"  ,]v3Ý{º±Gæ’™ µøšŽîkšMhM ëàkÒ LM  éxqëV4ëÖÞ]s/ímœ:=ï˜.Í·{þÀ[A€´xؘMZÒl!`a®c¹™iƺûÑçvP/P,88¶Mq¼ˆW.פܯ|ª5À»—¶ð±û&'fÄ)o–ó¯þü—²? CVßœçc÷N¿àù‚ Àó¼IÀQš¦U5×MjB×É'BÜ ˜¶z%g·ìúÝ0v®H‡2í¶ô†nøm¢)ª#-@-yd ñøÏüÌÝÿcÏÞ_ Â0-;C‡j&DX©%Y´x1{vïÆ±ÕL¡W4¡ëèºÀÐu‚@“?¡U‹TÍ]hÒQ(ŒÊøò¶nM°îî»j£8=ÛÙ®Éçrïh¸ DJzV7ŒÖÒØØ»—üòÏb€¥ œb‰¢]Â):” ²ƒìïuafïkJ|úý³xïê.FÒ^û%ÂåªþKã“ﻆûVM»¤s×û¯…¬‰P àÛ¨A„m]]ô=ʬ÷~€ [W©|³(iM$y‡@ŒBª1Û¸ô^kȬÁäÑ#‡Ž/¼á¦¯îß·÷×I“ŽÂƒ2ƒTjA.à¦%7Ò³w?±eJp…Áe¨OÓ „®c(Ÿ€¦ 4Ý$9–L×ãËä"¡UbëÖ—° …I=:;ÚS§N秇í X¼cAà"&€°„id5ËʗΟZtí}k8wð<íyGÙýNIªÿN*á¾PyXk —1yàÝÓB°`vw-¿8#Erjì[!ý¡1Ã7¥ Þ{»ôò_7+ÃËZ/ë|q àBë0 +ú±ëy„šF¨é¤²YÂÑcdo^…aéºH˜9tÑ$‚Àâ ì0Åò4ªóâéÃÑdõ ÑwôPÿ¼÷¿¬_¿þתATˆ0$€0Ïâ›n`O/Žæ(¦—!BM%ýèšÀ«I.TŽÒšO¦KBåóBcOw7 ñþj{ tvÈIÕ§OÊwLgãðð¹[ÚÚZúÞú'ùæÓ”:fJZVhbf¦­ÜL‹Ñ}c¸FŠbÑÁ)±Ç‹8…qÏW©¯RíªIÞßþÉtµ§Þð…^̨ߩµõŒÿͧ–3cšõ®´zÞ¦dúúý€æy]C˜rÜPRø´-½‰s¯\# öã†é”ø°V ÿáŠ÷ÔQ”)ø¿Û{ó8I®êÎ÷{ï%÷¬¥µZÝhAK«%!$@@³‰Å`llÀögƃ1ïóü<ãñ3¶°ÁÛã1Ÿ³Ìx<03Fbl0Æ€±X, lŒ¤Vko©Õ¢[KoUÕ[Uî˽ï{#2²–îÒjèóùDedVddäÍ8¿ó;Ë=·H加°÷ä nºé¦ÝïyÏ{>ùþ÷ÿ§w: F»6r­aBÃÅ_Ì®‡vÑ8v B”nS¤©í-h×w´·}ð”eÒ±€œ î»ï>êµ*¯zåËǾHVF|èàÁ‰é5Ó3;7wõúuëN¹ŠÁ0€ÔCª’ðe=nwŸö^DÔ‡¤ÕcH†½ˆ~H4ì3 1:E aobáPɧ4Q¡(¥^M!Ñr²Ò±ÏTãÝìzO¤üFÛ¾hcÇ–ãù? Ü˜ pžé—^Í‘Ûî»Ì«ËF*Ò2FŸ2q€L\<F ¥aÙ5píµ×~×ïÿ“÷¿ÓVJܰ.†‹.ºˆÝ»¢×³Jì9#”Iá¡”²qE®äžR$iê\‡,S`çHW9xë­·ƒ”¼êåÛÆ¾Ï™g¬cÐëqøðáË×®]sóììÜÕëןZ p"ð…4¡òdeØîl=kÛ•´‡ ^¡ß·¾ÿ``Y@4´¬—ý²¥*Ÿ)¦Õ2y")ÁbaQVSïÿdD/Š,=ª{·×{\¢ Âó~Hy¢I4{ˆÉ‹. ¥¦§uU’S2°²EMÝäÞ\20h|àÚk¿÷¦7½é½ðªmyI¹G \tÁîð—ÛwÝ„¥WR áX€]ÙU,½§lóQᩜ i‹…¤¶GðÊE pî¹gsüÎy>rùôôš›ÍÎ^½aýúSV>R”¥§*‰î®[÷ÂË8²³ ^À°eÛ:Gýƒn$²š¾ØïBØVNOƒƒj«‰,vVý9Oòú–œGk†Ã!RJÒ4Í—e…ׄˆ4µ.@PB JÄ*ë¶ÔHÏ«KéU §V (Ë0ÁxmCÙåæeÛ¶ÝðïüW]õ¢mÚesW ›C€æœ³7óØcûœÏòüÂù÷¶ØS¶É(زa_JÛ›Ò¹ž°ÁD¯ÀpëíÛ¥ på—³ãλX{ó¡C³WoØpj€À € … *"ª0¤6 ûvJ2è ›Kû¸Zìž.À)T¦ØJ©Â4ã“ˉ܅±k|ÀJ1€ìºÿoô\`¼Âr£»ŒÆùgÓÚ½ïEÒ 41¥ªøÑ5Ÿf|˜gX Õ dK e1âìÁ _ñŠ—}ê;·Üb^ø’—¼ŒláØâ‚ÈF³níZ’Ç÷í³ íŒ’e.è§Ý¶¹¨6(Xt„k4Rd BHnß¾)Å’ DW^q9;vd 0}Ê€À²P¿ ” K*(׈å¹ë/¹c ê§/aEDÃÈ`²Ù}9…HÝ€=}:ÚØUb3Y) X|þâËÖñ‰÷£õbù?ßz”ÿø‰»€q…|ªR Zž,¸ø5$ñ$Jˆ‡C¼R•á±”Æù°ðÐþ³¤ +B¦I…b¥é§€,Ùà{ØnB™LbÛ‰W¼êUŸš›Û\«×7›¼äÌŒ\*m+÷°oß»¼˜´Ó‡³9ÂS¨DÜe'ÌëT¶d¹K-f@ ¥äöÛ,XW^ÎöwrøðÑË×NsóC‡®Þ¸aóV`’2 ”ªTŒgqÕËlo¿ÄÂnÇDqLš$#ú/¥-’Æ*¿[áãåoÿâx5  ÇÓ… ¹é/~–MgÔNx±¥@ë<µ³˜ d¯?QBðSÿö9e/~nö<Ûÿû?ÃI¯7c@ZÛ Sê²$iº¼å/@%¶+n’âùq«Mó‚ËyLßt† ”o§¿é§ÐÕùÙ!.Eˆ+J±AÁlÂD108åžËõëÖ}hvvöšj­¶)¯ÌfŸm k×L#‘ì;°?W\á¦ç. *O¢Œ‡RÒÅLÈÚ”ÛiÆv™2àöí;H¶m{ñØ÷yá•W°}ÇÌ9wàÙË€žÄó•ðKþ°ÝÞ*‚6ý# =EÇDqj•?Ž­B¸èª’šTƒÄË+…Ò(PˆÂÒ?Ùã*i¼)Ì+p Ÿ¦é² „U¹ÆŒQòL¿·ø|µç1ãf¸™Üb!M3·þÆâ4AE1A’â×'ˆŽÎ!k%©eDì=½5Ð?D)” ÃhÎ@&YÍ@¶êÐ`ýúõ×:tèšz£±™<ÒdK‡µÑt5L¯™)Øà€³à™Ï\‚"ÍW…[à;`P^ÎdV#à€DJÉmwlÛ^º l¿3wžÍ °<BHáyB)%<%ž³íuÄ `‚=衳F›qŒadµ±è¨µ¶«á«ðZ„PyÄ»8+pµ”Ûýx#‘åz,.½=éy °øõ“í¯ö¼K)>îšísmìxûw-iŠÖ)iœ Ó™¾ìb Æ7r ŒècÄðG g‰›EØcij0[œ ·aÆ8pèšf³± FU² A»£™žžBH8°ÿ ey¡kâh¾RÞÈÈæ xOes¬»  uؾ}° ¼ð nÛ¾Ãu2×oyFïIʲ …F¤%EÜíi˜gÐn`$Z“jƒN Ij‹T Ü /”cPZ …œ¹yVùÁRÿl_¯–DË—¾g1X¥^N–.|" 0îûË‚µe(€@þ¾4%MRRmHcM¢»xR=‹gjÂÐ!e°Â'Ÿò’Å52€¬; €ÞÆþ,J’?¬jSÉ~Æ,˜ µ¡Ûí159…DrààÁ|ÒOVò›Ñ|O² 0ô%JzYLÀ¾$‚í;v€l{ñUc_âª^ÉmÛwpôȱ7ïÚýýë/ºà¹¿úLÜ•bC>ZD˜Ô›kˆç¤M¹¤ºµÚcÛ¦ÙúüvñF¡5JHŒkþ™€vÇh½Är¯&V¸XQ—+ZÌVÑ_ [¼¢×V>§[ÕÏŸæç±¯Ž5õÄËÒ©6ný;ƒ' ΃ì£é¡é’€“‰s²ô`ŠË®ä2ížÙ²eËuìÜùnƒ®¸Ô@˜èt;LMÚNßtŠì,¹’c•YæÀöÈzÚéÅžxyLÀ¥¼ÝþÛwP+WxÞó.û.W½ðJnüú?¼c×îïóleÀˆ.ZH P°þÒIÚß¶Kli×â;Mµ½‘®ŸF…ÐŒ,»´Ê-À.Œ‘ÚavùlëË/7Mxyy G5¢Ê¬œâKŸXI¹—kÉO¦{£Àø9Ä"fà>ÛöÞ:EÇöÚ’T”Ë azëkiÏ}#qÊÕ=QÉ@ ØY˜Âk€·çá‡÷_¼uËuÜÿ5˜j5[€&«4ZÓí÷˜šž@ 8xpÆôl¡’™K œ+à!S… ÏàÚ+)¬ ‘Ų̀ëûxË?ý#çœs6ÆøRoxýk¸ñëß„g!, ŒÁÇ`óîè웥»÷~"źíG€mPB ]^r@Èæ¾ !0ÚäϳòᓉqA5«ì£à_VE7 î Vu^Ë,–oñ=:wÑåX °€îýŽñ8•Ï+þF”?c. ,hÚ¶X©&îtð<#RÛ<„øG’ÀXŠ0k&²¸Z0ûq›€¿çá=û¶lÙú¡÷=xM¥f*&ËhˆºÝSv¥²C33 G½³ÒõÜ%Â6Å*¾ïbBy®³ð(5¶Á‹>õéÏð+¿ü¶e@àuÜøõo¢Í³ V`-´Ó^ÜP ̰ÍàÈnzÇöÐocd¸™`ò\t¦èÊ ´¥°–Ê:‹o›á90ÓÔþH'½“a•g¬Â0Ŧ¡ —V‰ÿqÇAÎ}Ãÿ^ÝHH[‹Ü2‹~¹=ŽEÇ­,ö»-gùí Z€uæhƒP6µ¥3kæª Qð™ÕàÛ)-.(˜¹†ñÊÇbÁÐ ÷îÝûøÖ­_w߃n±£YOm4ýހɩ ’C33îÞ,ÐYp ”— )ñ‘–¨¬ÀH:vh)@Ê“‚€ÏX„[já‘)‚p+\*$Ò€‰Hgï'¿I,0q^ã|‚Æ&üòz„t–XkÕ´ üar“'•t  8cÜïi°¥ö 6Ó`–µÉâ hˆ‰Í’…ÒÆ]Œ®a5å͆‘e·Ø‘Eù‹ûW@[wʺ#¡%F@Ô?Ž4¤ Pù¼¹ •Ÿ\½Ã)(ņ"m·¿Ø-hrï£{ö_ºuëï»ï¾k4•Š›&0v’~oÀäD!`ffÆ®Ó Èƒ{ùrcYF _@ ”ô²öcª°µö—|úÿ%¿üËÿŠF}yÞqÿο}ÉÖ-7<3C¶:Y! XQFÊ2ÈxtÓ)2êUpêÌ?D²°‡Ä+WG6žƒWÝDPY‹WÛSuéÔÇ*½õ{Õjœ3ŠêÇXWÃîÛ ã(öûă€ö=öí©19Dá¹ípìðþäWlŒ šà „2*,·u¯U^å"dˆP!2l¢mlÙ_ÖØ5?‰½¡ lë“ù®¢6:ê2ìÍaÒ@é÷Û€AJEZP¹þZ0Xšž3.õh¯M§Ë¬(ò?£w¤6 ËIÜ;Êü÷¿å¾sb7d)çždÏ]ºDk)¤¤g{éüN$¨0DJ!ˆìnû1’Bv k+¶ä÷ØØ³{ÏþËŸÿ¼Ýu×]×T*”‡Nµh8d¢ÑÀWŠÙ¹ÃNmG¹þÜ%v:qfù•pŒXÙþ¹!l<¬­kµÛÜð©ÏðŽ_yÛØ…þ˜ßºå¢/=­vYž Ò†™UX:fÌT½¶¤*¡d€ðC¤WBze´P }{*©,+Yõ¦[%Wç ;òB“ˆŽû,ì»×± 5Æ:DPAx>yÊ€”ñ<[”}Îbh°E‰ã¬"5.íÛF5Â]»NLÔ!§’ÉÏžäŠ ˆë"¹lŠt.’IÝm*± Œn[=*@È¡JHRÞ°‰¤Ê›D a™ ”¿üGÿˆË"(ÒQØ×UhïÞ=ûŸÿüË?´ã®»~»\)WW.lœû¨‰†1Õz•MaÀ¾ýF®|fɳvaYÝ€kÜÿIC IDAT5&6UXRvÉ2é!ݽŸÇX |àúûw>øè%[·üÀšŒ®P Œ‘£”ìîß~3½å§­âûeä  -Bº¸£ÐØ»wïþ+ŸŇvl¿ów(•ªYiT+Ö%Š#ü dÓY›8°ÿ€«^]êçØáÀúJ¥ÀÕ8·Í±NéîõN»µ"\véVîÛ¹s¸ùþ^ýƒe#c´ÑiªÓ8öÊÕG⎠¾”*!T á• kNé=Ëòµ{ŽÏ·îòì(¹vL(œ²­:Zïи´ðX0N8÷BŒÿÏSŒãþ~.cù:yO:²ÚÙ)V›^4 HW¿bŒ³ü©,` ãçÙ1!Ò+ÛÍ/#½*• DmJA*E˜Yþ±ȳE躭í'ÐÅÖh Ý»wϾ¼èŠ?UÊï–Kêµ*µj•jµFµZÅóÒ8&|6nÚH¿7 ÛéÒmwév»tº]zý½^ŸAoÀ ’Äã®kàûÔ«Uêõ:õz†Ûš:µfßWÜðéÏ,ù.çž{6Ï=ïÓ›+H¯Œç—ð¼²½9KM{£FÊ/T¨‘[@¨€\ñs`8‰dV=¢ýkù—ÙŠ4>lËC‘!Ï™±ÌÜ H³òŽƒ]¦ôÎò+7.<ò«(¿‚–Q~…òº3‘ æ÷>Ž ýû5¦ÑƒÞ‘?û±vŠ’ a™@Fý3(2Ð{v?¼ÿ¥/}ùŸ #º•r ejå*µjOy9l|!0, ïg™}ÃÈ-0Žþ}õŒVäÝB½Ã /WÚëÌJv3ÈÆ"÷÷•cލÖAT~‰úƳèͦŒIL[kÓ5òÔk þbL`€Uø#h¹-ÒÝ»wïñ˶}t8©”Cªµ:5ÇjÕjÙgn I:Ž´Û]:ÝÝnn¿K¿ÛcEË^T¥T*ÄÆA µ¼þu¯!|Ž>rù`0¸ùþ># p"ç;6Úôuª[~µ~Ͼ[ïfâ,Paϯ ƒŠ°•ƈ›Yv=J ·Œ™µ<ˆ ,Šåßjü<^a$œo=¶¥½.2÷$((iQY sN„ç®!X(åŽÏ¾³\Ùs²yÒ¾W¿Š jøAÚ9MŽÞÿ²î1Æ´Awì\íÓRãò5Œ¬«ümà¸û²÷á]û7oÞüþcG?^)…Të5jµ*UJy¶+“!$ív—v·mAæt»t;=¢xùz–R) Þ¬ÓhŽƒ@Í1» Ù¸¼þu¯!}>|y§Û½þ™³Û‚÷Žþ]ÝðÛ½4Û•‰©Û»íî·*õvÖžƒÖ ž_Á÷ëøAU™&gÈÓs•ßQàB“Í‘KàÀA¨Õ)”}³›W´Æ…÷f£áµ/»ˆo~æ7Nx¶ÿþ—ÿÌÿóž¿rï[ D‹XE¾ÿêo2æ °ý 06nå” ,µA†Uü°†Vñ‚*Ac‚Ê:xð¾{ñJáÝF§ 30Òœ¸rêÇX F›äbµ…À– °eËE~ðÁ]¿=55eÛ‹ÞÔîvIã|3Ö¯ãðᣴ[íñ¼£K õz™Æ´¥ @ÖÀÒ;èÞûvb4\¾¨¡Èë^ójþö+_ãèÑco¾õö;®ñ‹^𫫇ÕÈ Ã¯“¤“&ÃÖ°§Ò¹‡¬9ßGUT©†,UQa°¶nDûs ‹-¶È²ºègÊŸe‚U\j1p,:OöÿB Bã ³âiÅ(—½ìœÞÒÏ]8ëžÎbP”#&`À¦LC¼ ‚*5¥*¬Ò<÷<< n» U©|/Õºe Ýþ¡ýØgV)1v¥#w ‹,¸ÿG@gË–‹®;vìè¾À ¨WkT¨W«HÇÒ4aíÚµ„AÀB»m]‚vDz‚vÛ¦ ÛÝ%™L‚À§ÙhPwÁz½F³V§Qopßý;¹ûž¥LàgßôFÚíÇÍ¿ãö;v<­LàÄbLdÒ¤“DƒVXkìxä{÷0}.øaÝ‚@PE•êøå kä~:8ŒÍnú,"î/R‚"8‰ˆìø•Ô_¤¨Yídç•,–l[`<'¿æ °ÂÂ÷Í®IZ“gIìñ"¨¢JM[6ðÃÍs7²ïÖïaÛ¤éQ&-н>ô´¤"L@—Q@°‹u²Eìú[¶lù`«5ÿx,Â#ŽÒ4frjŠf½A;NÛ¹mÚ]ë¬Ô*ð}š ›lºX@³Q§Ñ¨sßý÷±ïÀÁ%ïù¿ðs,t8vìø;n½ýŽßzºÆè$ €85i?¢ù°>ñí{¿x#a Ö^x&~PÇëxA¯T#hl°7xŒËh­û˜œæ»Â˜¢/üD(uÑzf’ÇêÏ[|Ï çžâþÉNm {ÈZøç–¿x.{í^XÃø¥&~P%hLÒ8ÜzªT¾UÇñ¼1ºmŒ>\¥²ClL SØZî1Íöù‹A ž@LšÆ”+êÍ~Ö‚V{N{ÅšÑ c РÑhrÓM·Ð[&«ð/~î­ÌÌÌÒj-|äÖÛïxÇÓ1>'€þÌǴѺ£“xÞh½¯{¸£çŒ˜>_áUê¨R¯TEuÂÆz›û7™¥SŒêý37Àíç5,£+ÉrŠ¿˜ R¹ÒžL¿o¹s®':­ÿŽ^èžëÑç1:Ö¹Uv«£Ju¦¶\ˆçÁÁÛwàתßHÒø¸Awú>zÊ®ôÃ3šÅa +Ê‚‚]à–)h ·eË–¶çJÖLNÑéw­òw õެ$#°ÁF½N½nÙÀç?ÿEz½¥ ðóo}3333tÚíëo¿cÇ›ŸêØœTC iWëäX’ •ÆmwÜð6\ ¥ú$^É‚@Pjâ—šxÍ ÎÊ»x)wvã»4^>A§X3° É-ý‰”¾˜mX ,VðÅRü¬E™Œ“^o|ÚÅCëÑzDÿ`ªr“ 4IPªá—å:k/™â‘¸DiNGã&MlÐiy¢âŠ…²ŠÁŒ ‹…zXÈŠ«z[¶n½î¡]»î:©X»f-ÃAD«Ý¦ÕZ Ýî°ÐnÓnYV°’¾O³Þ°)ÂÌpý…/,9¾Z­ðÖ·Xh-´®ÿ§ï~ï)¥Oª!ýè4i%Q4WššþÊÃßÙIÒƒÍWNá‡uüRU®ã5Ê“›@•È;bf´ßè‘òØ¥[ÆýáUI±°¦¨ôKSvÙ1«±Ô0Ê$](Ï­Vé,ª‹Ècʉ :ú%W)7P¥ ¼rÆæçPnÂÞ›n!¨7¾¨urT›¤e0ýUØiY$²Ê¯!£x@›ìG°LÀ½×¼æêÿzÛö[¿»$&°005=E'KA mëV’ ði6ÔsW iˇë >÷ùe@ RáÊ+žÏìÜìD»Ý~Jñ€UiŸ6iW'Ããé 7'½Úã÷~ñ66>Ê“ø¥ ¼r Ü (7ðšg§¶ì´"wû\÷X¼ÀV#y”>+ZtáÛ,ÎA8éIÉ'/É,XTØŒ¡³Œ>÷DçÍzÔç¬ÁØlHVd4H¿33³OiV‘(·bн4ƃþLerê‹ÿôß?û›\ýxΕÓì¾¥Cõñ¢>^F1ýÚ1èvÉûõeZ¥…›u§Ü‚Å…1E0Èè2Œ‚ˆDžR)ü‰VZ2[ëïÉÒÇ#@‘ü²« p n2Z]PvmNà¸J:! _¸U…´û׸5×…×Laf|ûß"6°”!h„p€ ”›»_tIÅLÀ˜k’]Ö¤^xÖcš$¬LVê„•:›^¹™£ãÈ#‡aéæ4Î7Ö_]*§ç>i Ÿ{MqöXÌøTâVùûŒb¿úŽ·îÿè?\ï+eûÔªÔê– dsâ4!Žc‚ZµJ2ŒXhµh-Øm¡Õ¢Õj¯X,T­Vò¦"v«á{ã“æþù{·Î—J¥w=•1X50Æ,$I|8ô÷W&§>×þá·ž÷–WóÜWÕ¸÷ “¤qD’Ñq„ÖDs{­Â°VëD¢ï:…•v/[`|áQ[ÎÀ‚@6c0ŸÑ' uäÌò§Ù5+©Mú%ÂÚ$Am’°Ò ¬MT¦ØxÕ%T'áëïûŸT×n¸>v¦irXÓ6[pž-‰6þç´ñ‰!ÍûÞ÷ûï¬ÊÚØÏÐévIâB¬Ö÷)WÊDqÂB«•·±ÏV,ª×k¨ešâTëUR·`¬v™Ü}Ï}ÜzÛö·ü×}xþÏ>ú§Oúû?!ìýP¯|þïNãa3‰’^uê»ßüà_lûùü_¬¿ø öß;$H‡è$%ÑšJ“ÄÉüa§(ÎZ§Ø×Ê„²ØLö¿Ì⻑â !œÒ4Z,ž ´*1…Õ‡$ÛÑ,ù~Ö D§#r4 „MÂ%ñªMÂê~¥‰_Ä«NRÛ°–õ—V¸û¯¾Å°Õ=–ëw'QtPëä¨ÁŒ…óoöç%–“JV'PôÙo`A€O|üÏohþ¿÷ýá;«µ:y‹* ¶=²}ïa´É³Úƒ5zÙ D¨W«vH£óåÎ;Î}÷ß÷ßýÛ¿uËSýÂOR£["‰gâa¿Qž˜úÒcw=ú’=·ì—¾ú,ŽïŸD§1&Ñè4Á$ššÌ‡0èX…Ècf)j4iÈ+úúŒí?S¶å|yÛøµø»-–ŒêŸ¿¹Šk ˜ ÄŠÅ=à˜€`dù@¢jMJµIüjƒ°2MX T­sîkÏ'êÀ®o|‡R­ù©¨ßß§ÓdÎÝ"·þ0r“ û§åi‘ð¢ß5Ã]€B1{,¤…òýÀÇ?þñï¼ï}øNj£è¾@ÐnwIµ»÷|E¨|ºÝ~~WÚÛXS¯Õ ‚q𝔤V©bRÖ)·Þzë7þõ¯ÿÚÇžŽï¼ª4àb)]ø{ ”7—ê‹‚jó¥­Ù‡Þõ›_þ­ãp×ÿ9Bá(ýÖa­c :Gv޳pðaˆ\jPfåÀ…ÜzÖG•÷üjÜêkí^ÓPŒdb^ç¯ !PÊÃ`PRŽEwRmƒ+‹×è˲ ™ŒÆGŽž[¡x»Êúÿgî€I@§¨j°>E©6a·Æ4åÆ4›^º•M/ù›wÞùšÐæ¯ã~ï${Næç‹V;<ú{Æd¸ëðÝVjØTá$–LbA@⪫®:ÿ3ùÙ«ø0¤]vQü,5¦…›Tí,¨®‹v¶Ô—SìÂò`™dkJ)‘ÊÇóRʦüŠŠŸ-ž¤):MÇÎ7¢þà`}1½n“:Û`ìµ'±û>î­Á(DµNPoÖ&íVmRª6™>÷L6^r×go¡w¼w8,×n:ÎRùå%óf§­ÿ3.†Ñ¡Ìúg¾\ê^k`ÁAÞvÛm½â%W}ð¿wÛ5õZµ"ùlôn·KÇKx¨çû®ÕXÛ#·¥ºJµR;¶T*ñø£í{Å˶ý.p€Ñ²éOIž¤iz\$QyØïUÊÉ/y|ö’ï|âÛk_ö¿’ö‘ ¼ßQoYÄÜ èzÔúÄyðŒQÀWä3Ö÷?ó¹—q´vV^!¥Â÷=·o7{TB¡Ñ(çc¥iŠ”’4Mså×Zã¹ÇØÍûÎÛ ~œú›Ñµf¥Ï&€ù @Q­PªOQªÕ)U”ª„Iš›Ïàœ×Áþ;ösÏ—n¤¾öÌ;í=Z§ æˆxI]ÓýÁNË’àâß3€‰¸l-@Öx´ÈbM€ƒssû^þ’«®ûÇïmw­^«Œ-GÑéºÖ—ö|m4Ýn×úùF£ÝRñ•råPäÐÁƒû¶l¹è÷€Ç€½O×÷|Òíº6)m}ïátØ]U­­=óCßýÌ×>°æ¹ç²åÕ›´×rä‘4oopVLútî1,h&}lÄDØmýÏ÷µÉ~RJ?@y*W|ûèáyã °œdÊoŒA'šD'¤iŠçy¤iJE¤#Йóg«óõ‘ó*AçjmcIB¢*uÂZÃúúµ&~µ_ :5ÉÙWo¢{hÈ·ÿüã4ÖoüHÜïíÑI´Ï˜ôðXàOŒ=p~ bÍ,”ô¢ý:àœ›;øò—¿ðƒßøæÍ¿Q­Õר $’n·Ë`0$Ïý¹¥|¤ý^ßFüµ½Mª)•KÌÎÌíÛ¼ù¬÷ûûGï|êò¤bE)]ú¾† ÂÍA¥º%¨V_Ò›?ô®_úè{ižåsç#Ž>>Ç sœAgž¸ÛbÐ]`О§}ø Ü‚.Òs..ª.Ǖ߸ý܇Ïóð•‡øùZî¾ïç PTþ“¹Ð9ˆIÓ”4MI¢ˆ(Ir¶P8Áh_ÇÚi‹^¥NPkRªV « JÕ&~µImj‚ ~æo’øï¢AïÁ4Ž1izØžÇÅ&Š©?;Oé7;-OL¢®Í(¨+÷¤ŠUø2¶\¸î^s-²‘@ùÖÛo¿fÃú36ÙµFÝ„ƒ¡]aØ÷ñ]< {TR!Õj•j­Ê±cÇ÷]~Ù%<<,)ý{*:ü” ¼ìÖzaxNP©nJýÔ ;ó oÿØQjúÜù·=ºGŽ3èÎwZ ºó {-¢^—öáC¤…QúO0jãUlç%³òYƒT Ï÷ </ðSâ4&qŠŸ@E¹[àN2ÚwkÍ¡ (…_› (W «5JÕ~¥NXmR®×¹ðMÏ¥<÷¾3èr»ïùuÚ¦QÿQ¦‡ŒÁ&‘—É€œ–žD÷¾?Sn¬»Ç*6PÂ@Ƭk·ßqÇï¬_·nS¯7°­ÄÛm:݃AQ¸o}Oá{~Îf•òè´ö½öµ¯ùC`° ˖ȶ¾×ÃW¼ tvP©mžz}¢{o}ç'Þ )Üõ·}:Gçvæt[ÄÝ6Ã~—¸»@§uœèج« p…@ÅÀWáÆWNùà Sþ rPTþ"dq ØrÖ¿hùã4%qŠo &І¶43“¬8ÃY–(Õí”Þ R§T®VšÕÕ©&›·Ms#|õ>°'·AøÉa§½+ô5i4c´˜b£²Œßix6Htïû3&àc@ ™òg‚l®{åÖ;vüΆuë7õz½Ñz݃ޡ$¾§òIDÊóô{Üyç]ß}ßï¿çϰӓö°õÿg–\: G† !¼ Z•žªŠÿõïÿÛ[~ñýÿš¿­Ì]püq›îS*@¨¡|a‰A©Fgn?$CòšúìKe7ÏÖV{~à}<ÏË™@2ð¤ÌK}•+#.*jR„$:Sþ4M‘HT¹¥¡…"Œ}_G˜$qrÐô«uÂZ¿\Ç/W *5Âr Ò :]ゟÜLXƒ¯üÁG‰"o{X®~2êÎ?”&ÃÇŒNfŒ1ƒ‘ÿ¸âï´<‹$+^©âÌ0î‹_p忝>ûŽ—¿üeÛ2û†{c¿7 6™iÒœ™ãï¿úÕ/ù¶cÑ •ÿ©ÊÓÃ.ù=ª,}u†”Ï ªÕ „ïýÄ =÷–_úÈï3¹Ñçî¯hŽï›'ê¶öZ û=’~‡a¿KÒoÓ9:GÔ:æRj…q•’  ÂÀ>ßÃ÷C”¯r6mž”Hé¹£óI‹ôß@\€$JH’ˆ$Iˆ¢„8G1QEC¢(Ê+üdP&¨Õ Ëuür…°\µ=ªu‚JÊT… _¿¿ _þƒ äö°TûdÔYx(î÷ÓÑðIc[bŒ›>!NûüÏRq, sl=@æ ÔÜVÇ2‚,©/þê³õ«/}éË·õ=» Hè÷H┇÷ìé}úÓ7|v÷|Û©hUÊÿÃw.yƒA`„¬Jß[ï…峃Jõ"á{¯éwæÞú¶ë~ŸõÏõxèÛ°ÿÞ†Ý.Q¿MÔï÷;Äý.ɠǰצ}äºß±'— ?Sü0 B|aàãy^à€¯Fñé-Gþ3°Šç Ä I“$1Ñ0&Ї$QÌ0ŠrˆcMX¯ôÖš ˜IDATS*×Q¥ A¥b[z•kxeký›g5¸à ÓÄ]øÚþ3ƒŽÙ•OƃîCq𘎣C&IúùúƒÆŽ#œú=›e”°}JXåÏ‚„™[fï»öÚköñ_ýLÑw…B{}”[n¾åñþâüp¶1Écn;©å– \…„PUå{ëTX>Û¯TÏ—aiÛÂá}oÿéÿ÷—¸ô'ÏçÐCðð·{ôæ» û]Ò~›¨×!ôI¢q¿Ç°Û¢wìèˆ ƒ0 ñ}? ý?ôñ<·Ö° På@Ž@Àƒqv}›ÿ“„8JH ñ0f ‰ò': ü£|‚°Š*WJU‚r¯TůVÙpù6¿Ðcþñˆ/ýÉu„ÕÉ¿WÆûrÔïíÖÑàQLJtšö…Î26hÌiëªHtïû–ên«¶& &1€µ×^wÝkÎÚ¸iÓÁC¹åæ[víï¾òlÿO@ùáY‚ÔMÜRU„ç­óÂòæ R=7(W.ŸŸù­-/Þ*âßü à B8H˜*KjAž',H”Ä“ ”%Á—nš«2òõ:4¶›WšB¤m]OšÚÇDC/ÖÌuŽ¥†¨²ö<(O@knÿê<|÷.°|G(Ãoê8ù~ö%ÑpÖ˜ô°Öv/•• §îƒSœÏO>x”X<-§„¼ò¬üÃ7.×à³èÀ(F ×­]§=ßO‰SúDCg3-8ÔÑ´AJ&Ï ØPƒáöÜù;¾u3­ÃÇ ‚ê÷åé/¥I47vgÓh8«Óô¨Ññ1 ƒ1ù¸dA=×Wb̾‹åë´œJò+ÿò—XÛXË×¾ñuæÍÿUì p–~bjÊÌž[ö×ö¥‡ å2\Ï´<=Í÷fñ«ÅÎý LÞ–#ÐI:0Ò tš¶tš—I4ǃU*¨…“ß”~pö­ÿÝŸüÇ/Þ¸ebý$^ù<.¸â2Î|©Oª%½6ì:ãP‹!TPMìelœ„zɶPÙåa•׌½œ®‚N](Cå ¨OHÖzКƒ‡îx}íaÿý;¡T™«ªúßÔÂéÒx87¶ë$:ªM2o’dÁhÝ6èD oQ…½ñÁ9-§¨¼îu¯¢V/39Õà–oÿ;wîZ|HÌü±c+žëÌ36°ñ¬3Y;=Mµºò BO—<=.Àe¿Ÿ»£4ภ qÇ ©ëŽ›(¥u ”‡ªŒç7dàOÈ \#ý`JzþÏ&SÌ‘\Gý+¨5×söùçqæsÏczÝu#¿^ˆcè×1 „(U S ô`nÿqî=ÄÁGö27sÝ‹^x¿/‚»|íÝDÃciÓItT'ÉQÐ B§ctÏhfŸ¤¤çz¾¤v³³@²4(–Ëœ–SF†÷üÉûž´üàœùÓœÿ«mP£5By¶Ûާ0¾_žWEúu¡DC*¿)•ߞמ×Pž_‰/IL|A’FÏ!7Ð(}%Rª•YÞ™‰ ë%Á‘Çè9ލJæïÞ õ”×Búú2ØÊÊíi2lëhØJ“dAÇq›$^ÐiÒ"MÚ$º‹ Ú¶ ÓVm/8”)9 ?"r*ÀÓèœXDaÇd+ ìJ=òæ—Æ9Å:íMcŒ%­ÓIT±* ¥jÂSU©üJ©ª'ë%¡©ËÇDµ'£sÚ ƒ³ŽnJyJz"'äišêDGILjŽÇ‚áäÆ.ÒôDÆèŽ“n/ïjtEœtL’öÑI$í£Í&n9’QÊsqß®%Žþi9-Ï>ùÀH2ß7+(9{eÂLŒÑ1©i#¥4ZûƤ!Z–RHYr=ÆŒ,¨_íW6R‡Zh-mdŒƘDÇ$:ÒQÒëÇÃèÒôAÄ“êZGèt`R=DëØ6ÌÄf×nÁk|V¸«‚̾ëiå?-Ïbù!À¸J˜ÅÖÓd».P˜½hw5&bÌT·l™aª0ÒÎÈ2x¼’q Q©Txrt¢Ô’¤ ±ŽHÍ£‡H“ H€ëÏ›|Éï Ø©Hä_f±¢‹ÓjZN ù¡°HÙ!È•]Œ¨µ(AfmGôD:A›¡M·j0‰@+£í¬¤PWk0n±µd4)ÀÅ$Š-É)úˆ­ä¦Ý]ø2þ´æŸ–SHþy?é?%½IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/viewmagfit.png000077500000000000000000001444721217176075400247560ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½x×yßû™sff»ØÅKü @€(ˆ)JeZ2eY´dE¦Ùe'ÍMûXiâ&·i¯]§í“ºíMÚ´÷ɽ½©“çö6inzíöé}jGŽLG¦¥Ú‰LYþAYM‰&E¸ÀbÅîÎÌýãÌìÎvñƒ¿$Gû>ÏyæÌ™3ûcfÞïû}ßóÎ9šëºÔ¥.uywŠx»@]êR—·OêP—º¼‹E»Àß9xh è‘R& )û¥a Km›&D”BhÍÇZÇ»hcÛ6ÅBÛuG\»xa¹PñËóG¼ÿ§.MÓÞÖï¿7^«ÇÖ/ $ô›–u Úа­!í1 ã@<#ј 1ÞH¬1F´ÁŠX˜–‰¡H]"=pÇv(Ø ËEòùer¹ÙÅ%²Ù2™ ™Ì™…² Y–s¹¹|~Ķí×£À‰çN¿—¡.!©ÀßP9xh iúX¬ñáX,v ÷·µ¶ÐÒ’"•j!Õ¼‰ds’d¢‰¦¦1„¸v¯*Ÿ/Éd˜Ë,N_%={•™™Y¦gf˜¾<Íôô4WÓi—–När¹ÀKÀá: ¼½R€¿ArðÐ@¿Röاš75÷wní¤³³“ŽŽvÚÛÛiom#­ûóÛÁÅÅqÀ ºÔ4ØXÌÌÌ299Åää$'&gââWffXÈfOضýuœØØ?®ËõJ~Æå࡞X,öt2™øT{{{Ïí½½tww³m[]][1M³êy…|ž\.G.—#¿¼Ìr>O~¹@¡PÀ¶ ÊÇ·\ÇœÒyšMC iHti ›:ÃÀŒDˆ˜–eaE-¤”U¿;žgllŒÑÑ1F.\`xx„‰K—Èd2#¶mþ¨C¸5R€ŸQxòžÞÔÜü©ööÖ}}}ômï¥wûv:;ÚWô- d3²Ù, ÙE–³ä–r,æ–Èç–É-çXÎç).( ØÅÛÆ±m\× MHM¢{`SÇŒD0-,‹hCÑh#±X±xœx,¶‚9ضÃððy††‡<7Äйs\¿ÄR6{Â?¢î&ÜT©ÀÏ<4ÐÓ”HsGßíÉ;w²cG==Ý+úΧÓÌÍÏ«ÀÜ\†…l†…l–l6ËÒÂ"‹¹ErKŠ,/çÈû À€bÑÆv\\§®âÐ4)¥*†AÄ00L3baY¢D£ 4Ä¢4ÆbÄb1âñ8ñ8M‰‰¦&¢±Jw¤P(pöì gÞ:Ë›§ßâÜÐWffÒ¶m‰:+¸)R€Ÿùù>ÕÓ”HüΖŽö§÷쾋]wÝÉî;wZåNŽÃìÕ«¤ÓiÒé´€¹ óós*2ŸÉÍ.ÍfY\\biq‘¹ùt~llüêÔôå…ËSS ùB!, þ³@Þ«ØÅš½z<‹5¶··ÇÛÛÚ»»»RÉdÒŒFcÄbÄã1bñ8Mñ8ñD‚D"I2™ ¹iÉd’x"QñÁSSÓüôôiN<ÅéÓg¸ti‚åBñKÀyþÈá£7ðò¾«¥ï`ùù>Õ“L&§««óéþ»ïaÏ=w±k玊>™ùyf®\aöêU®ÎÎ’žUžO3—ž#37ÏüB†Ù+3ù‘Ñ WOŸ>5™·íI`XÆÝó¶Õ T*°®U©k6'‰-;úúRwîÜÕ‘jI™MMMeH6“lNÒ¼iÍ›7“J¥°¬2°-.æ8yòo¼ñ:¯¿~’‹ãã,çóGT^¿Ôà( ô$“ÉßÙÖ½õé{÷ÞËÞþ~úú¶—ŽÛ¶ÍÌ´Z»23ÃÌÌ W¯Ì2{uÖ‚S púÌ›—Oœ|cðÞ 7P÷-}°©°’øF騀`Þ¶Å4ÌŽ÷ïßß³g÷îŽä¦$Éæf657³ySŠTKŠT*Eª¥…æææÒٶÉ'8~üÇO¼ÁøøE Šü«ºkpíR€w<4ŒÅbŸíêêúÌÞ½ýÉ}÷ÝË΀ÅÏçò\žºÌôôÓ—§¹2=Í•™ifff˜™™evv†ãÇFJ¡}E_F){Á+y*Á`½, ,þS¤£€Àôêþ6ÁmpÛþû¸í½ïÝw[ssŠTËfZR›iii¡¥µ…–¶6Z[[K_T(ؼvü8¯þø5N?ÁäåË8®û¯€?¬ 7.ux‡ÈÀ“¿p µ­å‹ýwßÝsÿý÷sß}ý¥cù\ŽÉÉI.O^fêò$—§®0=}Y1€éÞ:wvöØ+¯ ç(+}¥ð9ÊŠï„ʲ×7ïõ÷Û  ¾„ âmJÑý-TZ~éõxÇý¾A ðÁ`ûÇŸøØÝ;wîÜÜÒÖBKk+­­­´¶µÑÖÚN{`„c>“åÕ½Ê_y…Ÿž<ÅÜü|ø•ç>¼¡ ÿ.—:¼ÍrðÐ@2™L~qçw ìß?ì@ —v¡ÀÄ¥KL^ºÄä¥I&/OryrŠ©©ËL_žâåï¿<4>9y¸B™Ê/yÅWn ü6 ÂÖÿz€ÿ$­¿…R|IYÙ¥×Þà*hÝ{wÿƒïð¶®®®H{{­í*™©££ƒ–#ç?8ƽÂðùa …âQŒ¬÷¼›¥o£ <ù [:Ú¿øÀ{ïO¾ÿýïcûöÞÒ±ÉÉI&ÆÇ¹41ÁäÄ$—&'T&ÝèXþ›/¼ðfÁ±Ïs(å΋”•¾€Rø,e¥÷ÁÀñúQìÀßú1€e*Á€Ð6BùML¥°Jé£T}+A)½¯ø’²²GY þñhgGǽ¸gÛ¶îHÇ–vÚ;:ØÒÑAGg'Éd²t½^}õ5^þþxíǯ1{5F ¿´¡ò.”:¼ rðÐ@²)Ñø…;w>ý‡â¡ßa¨Ú|:ÍÅñqÆ/^,ÀÄ¥KŒ^¸ÿÆóÏ¿i;Î)”Â.¡†ì–PŠ›G)¼¾Âûmþ9¾‚‡K­8U¶AÑB[“²ÂG½z0 €˜w,F9€hÚ}7Á?ÖÐÕѹ÷ãOô÷Üv[dË–N::·Ð¹u+[»ºJÙŽSSÓ¼ôò÷yùåï1<|/«ðWê±ÚR€[,‡~þÉþööö/¾wß{úø;vôàØ6ÇÆS06ÎÄøEÆ'.ñÏ~õõ‚mŸB)ð"0O™Æg e¥_ôö}Å·CåF*¿/á!À`] @ ÄQ ¤ü±À±`[œ²ûPb =]Ý{Ÿzê÷öÞÞéì줫«‹­]´¶—Ý‚ïÿàß9ú?9~‚Å¥¥àÉúau©À-”'áéÛzz¾ððÃ%yä‰D€ôlš±± Œ^dÌññ1^{íµÉ“§O¸Š²ö (¥Ï¡èÿŠîÏ£”~Ê `XñƒàVÙzE¸˜Ý˜ñ„Û»c±XÝ ¨Â0[\`fú‹Ù9Ξþ‰ædçÀ¯~]G)·_|¥7¼ý&Ê  HPvü²é±G9pàÀí]]tuuѵU½ÿ`z9CÃ#¼ø£¼üò÷˜ž¾Ê%øÃÞ³¿éR€[$ŸøÄ/}a×]»>ûØ£òÐCûKíc£cŒ^altŒ FãÌ™Ó }ôè«Ày”bgPŠžÒ”)ý,Jù}_ÞWú ò‡?Ò1S»Ýýžàoúóî¦ÍQ/ß? Õ^úsBUï6ø¯ 8þÖ…“ÇOðÝo?£;ú…ôÉ àƒAØD%3hDAÏ’”ôÎÝöëŸþôã»wíNtuwѽmÛº{Hµ¤˜Ïdø«o¿È‹/åüÈŽë~éù#‡e•Ûô®“:ÜdQþ~âkûöÝwàç{Œ={vËå¸02ÂÈÈ£#¸pa„ÑÑ1ž{î/ßLg2?A)úÊg_@±€%¯ÝgÊŠ€”?êôí{ÂýåOÿ3÷žûî¡´ðcý¤€ÐòÝ(¬Æ |€ñ?÷" æ½ß”>|œ‚ ®ã„£ÁuàØw_ä¿üñ¿ÖÒ£/…sšQŠ^ zm>4z¿­ú¶oðéO}ê}Ûº{èîé¦ç¶Ûèê.¿ñâ‹/ñ­o›ŸžzÛ¶O¬Ç”Ôà&ÊÁCÉ––Ôw|ßþþÇþ=Ý]¤gg9?ÂÈÈyFFF9Ó§N-|ûè‹ßG%ð¤Q¾¼oñç½r~"ÏjʯÔèrþÖoüKçŸþ4è§Øt[>ïÜàç(+z˜YBßUíû—P u•¸ðìqŠ%@€cÃüwÿLûþsÿ·ßhöŠAy¤Àƒ2@ÙÀ–ßü¿?°gÏîDOO/=½=ÜÖÓ‹i©á«¯¾Æ ÿãÛ¼öÚq–óù¨àà»>.P€›$ ô···íÀô|äÃÓâÑÒɉI†Ï32|ž‘‘aF†G8úÝ££ƒÃÃ/£”eE鯠¨ÿ¬×ž£¶â‡(Üþð/ÿ¶ûëŸû¼;°—Fànà~”â7³RÙƒJþü°’‡ÛªÕ«m}»zø8‹N l» ÿæ·E;óƒ/i(EOQ  oßehö¶>Ä<üð‡>öÄ»{n»Ûz{éíí-½htêô¾ùü ûá1—rixWƒ@n‚<4Ðß±¥ý;=öhòÐG>Rš…glt”¡sç>ž‘áa†‡‡ùÿ¾üå'Ps‘2Å÷-è"•é»aÅ-)~Kïûó¿ÿ_ÝÛúºøX?¨TòjŠ_ µ¯fýÃÊ jûá¸DÉ•yö8Ë®]f¶­€àäñ×øßÿùßdÏè( h¡<\˜D)¿Žb¾Û z<»û·>÷¹GwîÜéݾÞÞ^R-- óo¼ÀËß™lvé]u¸ÁrðÐ@gç–ï<þØcÉCO|„¨•R“] 1<4ÌÙ3gò_ÿ摳”ýç+(ŸÄJůfýmÀÞ÷øo:Ÿÿßþƒ;°—àÓ(Å·X¿â¯Æ*n„õ¯6*vÿâ5§‚"]ø'¿vP›z!´£X€lõ¶ $,Êï#t|î3ŸýxÓöí·ÓÛ·öv•J<22ÊsG¾ÉK/½L6›}Wƒ@n ø–ÿÃÿ\ò‰'~Ë2q‡¡ÁA†Î 1tnsCC¼ú£Wg¿ÿʱ¿Bùû~€o¥ø~àÏW~»Â?øÄo9ÿøwÿOw`/û€ßúY©àµ˜C­z5Ë>¶Që Öž,Ó‡S°]pŠ*>`»`{õýO~I>þåFT°ÒO0òã&j4!îµë@ì×õWù½ï{_ëöíÛéë룣³€ÑÑ1¾þÜŽ~ç%—Þ½L 7Hèokmý·?üXò£{‚¨eá8ƒgÏrnpsƒC òòË/Ož8uòÔ+º À4ÊòORÎÔ[Uù÷=ö›Îçÿ?¸{¹øMà^V*{­íjôÿfYÿ` Å+Jñ¹#§°/0èú±okÛ Øð+Ò$Êú§( ÛQ ÷ÚK ðáÇÿ¹O<ùäží}}ôõõÑÙ¥‚±##£þús¼ôÝ—ÉåÞ1:Ü9xh ™JmúÉc=ÖóñÇÊÊÿÖ ƒçÎ288ÈsÏ}ãÜØÄø·P¥üÞ~ð%0õ/v¼ãþâ}î˜;°—€ÿx+-ýµ(~-ë_Mù¯Åú×j›®þõEÇ ºžÕ÷À ýzQÕÏ ñ¯þÞí1 “ò›†­(ðÝÿãñÇûèSjO__}w”Aà­Á!þ:?üÁXÎßu P€ë”ƒ‡’ñxãw}ô‘þ|¬í|ë-Ξ=ËàÙ³ ¾5È×Ï }f­<îÖ8ž&_™fÙuA ¼è¿æYÉ!”¢k^šf£²h^±5øâ_»¶]`â×>¬eQlÀŸê¬SiC1÷|ûÛ‡5Ÿxê©»¥”èRÒÚÞΞ=»ÉfÉd³¼yúL¿ãºßA¹UuyËÛøÄöö÷<öøct{I>£ÞPßйA†íŸ˜øÊêM¢þXøýü ·ÿàË£öç~±«ø¨qüÒ1ª+x­R Ö Õ€aµsª•0vûèc°g·J`Øê;74ÄsG¾qvlbü/QÊ?ŠÊíO£hŽJ(A¼ãþÂ_¼æÚŸûÅ®_¾‹Ë_MÁkQîZ Q Âí.Õ`­ì?¼u2KFJ:H¤T@ ýâ·é}#°/Õ¾4@7ÀÐËmºWþó·Üˆs¨àê"åQ–IT¼¡ä¿ù _{ökϾ~þÜ0燇Éf2<öè£|ð‘‡iÞ´ à郇ž¾†G£.·HÞ68xh ¿µ¥å >ø0=¨^ìIÏÎ2|þ<ÃCçæÕW_ýK”µ÷çèËPVü°òçÂÇ~õ Åùñc‰ïå?ÿ•ÿ^-ÈVM¡×Kÿ×cÙ«)õF¬ç*ðæ[6 Rá)¬Px!ªXÿÒ—¬~€ ’ f`H0|V?}Þ½DÆQŒ`ÆÛ€â³_?üü+¯ühÒ¿w©T3+¸>0}þôywF>X@aýª2ð‡ÿþKgßz+722ÂøØ;wîàÀ‡èÞÖÐ|ñ•ºÜd¹åðè‡>²µ³ó³?ôPižþ±Ñ1.ŒŽ2:2ÂèðÏ<ûìa”Õ?Šö>¨øªˆŽÂWœw~õñè§€¿¢’ò¯G¹k¹ë‡iý—€7Fà²?}&”ò `ø#š×d>;ze»\þ¤Æ)Ç–½k¼ðOû·¿422Â…‘QÒ³³<ô‡xÿþýÄã \Ã#S—›(·î½ïæMÍÉ/=¸ÿzèA@ùý£F¼WzÏó•gžù!pfmå/¿£øÕ;OÝǧ€ÿ•IJë^-›n#ô¿š’×RøõÃðÆ,ú/ò‡§ù ‚A jPÐgúÊc¥s«ÄŒÀöOޏ“¨à«Ï–PÁIäåâïýÞïáÂè(v¡€‚‡>ð ýý÷¨åÐU< î ¼ƒä–@ó¦MÿvÏž=]>¸)¶msat” ££Œ]¸À+?úñØ|6ó×(Úï+u««uoá«ßyËWþ/²1E_ËʯÖw=´#ÖrNŒC18Õ¿ @ 4@ U2M¯Îtß}ÐWº+F  PÚ PðîO•‚]Šcãã?þúן;qñÂÆÒë§K4i¨}]÷úå6Ã?æµ:Z´ýÁË(`^D ús,…ßþçÿìYÿÞ:¶”‚xop‰¶/Ô]w†Ü¸ÿ‡þi_ßöÝï}à½ÄbQÆÇƹè1€£Gþx ¥ü~`)˜ï@ÔIt>èþÝßþ*ÿú _Oíc/ðッ¨E÷W‹È×RÒ ²j«¶O¨¾–øýì4\ÑTlO×¼\{Q£ø}jí Ð5.ºÐT]jèR  ©Ú5 ]èª]uL“èºPýµ@»ðŽi*ÛW—Bm5ý¿ø=qèé?¹ä]#6å™Àuþ‹¿xöØøø8ãããìÜÑÇ{ïßç'õŸÝÀ5«ËM’›š¦míììü§ï¹ï>ööߨl¿‰ñ‹Œ3r~dùÔ™3Ï£‚~Yª¾Å×^ìØõ¨ý±¿õì<ÅSûèAEû“ԦߵÚjA8\o5«¾–…ƒ„_ÎÌÀ´—®_bûZ PN篨ûǃû2¼/º†¡ij_J„.Õ¾ÐRC©ŽiÞ1©«~Bzýuï\]õñK‰xâ“¿Nç®§&¼ÿ6ƒbm³þu|öë‡_•'@ïEª¯­q<¸_qÜw šæo…¢üš†&‚î€(» Òw¼¢¯²ýÿÇW XwLy×tšò‚*ý—ÿâ=<1~‰‰‹hooeß{­xÿÎ5=Xu¹arS ÙÜrWOïmŸÙ»w/;¼1ÿK—¸tq‚‰ñ Nœx}ÌÁyI½Zk1ûìí÷>dïÿà·ý’1‘ÀŸ¢&è„êJ_duK¿ZÔ~=Ö>¬ØµÜƒj«™UCgÒ/Z•‚ǸžˆïU;&ª×RHU4 )„jÓý})5u\ ¯îµ ¡úhÞùRªó¤¿¯«úÿù[Yˆúk*ÎPrg1·8ôò÷_>3qi²”pß}{Ù³gRJPï ôl䙪˕›š¦»îÜý»}·ßÎÞ{U*xn1Ç¥É &&'˜˜¸Ä‹/=‚ ü…^ã5‹˜ÝÅξÝÅ»ú´zôI'ÚSûøMà罯¨eñÔ~=côë V¨Í‚mÓ*Á§ªEA€ õ't¼k Àª2Va~ðPøÖ_ ½ ¢ &‰ŸýýïN£€×_i骽ÿðþèùɉKLNNL&ØÛßO›7Á(uð¶ÊMÃŒÞݹµóÉþ{îf»7ì799©Ê¥IŽ;vx…òTݞ厉Þ^ìê»ÇÞ³÷!÷‡?â¶´&´OÞÏ=Àï¾âZ†êªí‡•·Z{­Âm~}r†DÀWûÿÔh¯¨Öæ·×¬ „Д//BÊ××4åÛ Í‹ è^»,÷Ò‹·^Ñ%bÇ]÷±ÿÐ篨¯*ÅüÕ’gÿü™g^šœœdvF±€þþ{صûN?Pgo£ÜÐ4Íè¿÷ÞØÓ³»ïÞ¨U|.OM–@àµÇÿ’òë¥í1·ÚÝ}ööýÎ=÷=ìôlïAð÷_Tà å¯fÍ×cÕƒ.€_‚ûµâÕ@"Ì 2óð+óyV(pµ Ÿ¿¿Ï ¶Õ/@(E9PX¡‹rðPÊ@ÐPó†^ѼáßùŸÿír²ëÁyˆ(OËîγ‡ŸýáØèXnêr™Ü}ÏR›Sþý¬³€·InèéØÒñäžÝ»K+÷NMM15y™©ÉË?þ“Ÿ§¨Pþx³£ØÒu»ÓÝ{§³ó®}î{îsý øO(Š üùÓc­ý¯éߨŸ¿ÀJPtàõ`t¿Z¡(TÛ!E·UYáYy)=ðØ&ËÇ„·_Rzôòè >ûÏ¿”&Úbc´¦Q `Þ»V‹G¾yä•ËSS¤Ój–°={öpÇ}uð6Ë MÓŒ;vîùµÎÎÎÄî=»]A_ IDAT° ¦/_fêò—/OqìÕWžAùûËßj'ÚºìÎmwؽwìqvÞý^ÇŠ–‡ Žœâ4ð/YßpßF,ÿz}ýZ€°Zû‰¬j¯jý )uj±¨ÕúÔ å×Êm¾¥÷Ù‚¯ôþñ’ à×ÃŒ-½<õËÿäŠ0¢¢³¨x€ 8_y晎ç¦/_ ½µ…»ví"Þó§7þ´Õåzåf0€¶mÛº?µóÎìÚu'ÓÓÓLOM3=}™3gÎü•ëï)´ˆÙbÇ7wØ]Ûm·ípúvîuÛÚ›5]–N)ßäÏQ£«ÀF-ÿjþ~5뿚ïl?—…Åjµ8k€!+w¸oMÐÊJ¬]½\—F =Ö iåXBÐðAãàÇ#ßÙ½s)–êö3¼ë±ô;ùÊô•+,f¸s÷.¶voó¯Ûg6ú Õåú冀¦i"‘LýR{{[ÛÎw`™jQÉ陦¯L3}e†¿>úâaÊ?«Õ‰7w8-­ÝNWwŸÛ}ûn·»÷´•¢LYŽòoP“}lÄÇ_¯õ®T©¯¶½’Uyò«Z~XiéÀP `¥’Pn­Êñ T~Øzmºýµ2Xø‰AB/ƒƒ”•, P@üÝðû³+¦E“½s¨ä.p¿ü•g^Ÿžžffæ ;ú¶sçÎ;0  YŸ>ìÖËf-½½·²»»›w¨¼ïùtš™éif®\adäüOPŠaƒUÑ”H¶ØÉÔ»µ³ÇíèêsznÛéFcBY©Dߺh^j>¼Éµ[úõFûÙ`@ÎýÖòùÃe- ¨ÅÂûáÏ ƒ¡ `ÐÐ|WÀ´ù[é1´ @ º¶ßãÜwÿãs©ÖÎ<"±„×¶ W;öúÌ•+¥PéÎ}´lÞì??ŸZ÷“V—"7ú·uwïëë룫KÍef†Ù™«\¹r…ŸþôÍï¡’|la5۱ƔO¶:ÉÍnûÖ^§sÛv7ÕÖ¢ië£V¾Õš$ëÀo¡‚‚ë}Ég½þ~µ1ýZÔŸÀÖ¯ŸYg5…¿Ö` ¡~k@ð3jýŽjñ€ GDÀêYƒ Ä4‰(؈_þ­Œ‰ÑÞÝ7V)ðåÿþ•ÍLÏ0ã½)Ø××G϶ÿú¨o­Ü0Ð4-ašÑT*Eßv•õçØ6Wgg™™¹ÂÔÔôÌÙ¡³¯´…™´›œxS‹ojsZÛ·9í[zÜŽ­½D „Ð÷l'© •‘&„—¦yÙiùÚ —H9Ò¼Q…¯æ@u&°ž±~_T©°òZJ00X„W‚ý‚Ç‚Û`&a8«°ZÆ †º®ˆr¦ ¿Õ×_x×½”Qèeú™‚š®êº¦¾3oÖî¹ï‘LKËÖ|¬¹ÕÏ `dtdòÜù¡Ë³³Ê hmma{ßmþ¢õW…o¡ÜH°mÇÎ;ïïîê¢÷ö^®ÎÎ2;;ËììU†‡Ïÿ°…Ùä46m²ãÍNc²ÅI¦¶¸m[ºÝ¶öNɘ¦IÄ'ïç“Û“ü?%Ú°6%ªª!NÌ3 ü;6®øë @¥…'t,(9[M\º.¿µR‹ˆ*}‚íµb„ö×ã ° mý{¢éªÿrñ‘OüÆ‚iÅØÖÝ—1c-~0þàoÌ^½J¡P`ûm·“J•rênÀ-”𦠠¿··÷ÞžÞm´·ª4Ït:MúêUÒ³³üäŸ~Oq;Ö˜°c›œX<å4Æ[œæT‡“jép[Ú»\?# ¾ÿ#»ùLÉ <ˆ\„S‹¾ÀQüj a-ëïïŸ] ù‰ V)Õ@ Ú à×Wûž +@00¨­Þ±¿-a;«!Î]ýe’©ŽBssëÂÊÎWŸ=ü†ÿlôÞÞSrþºpëäF1€V!Íɦ=Ý=€¢ÿétšt:ÍôÌôÅÙ¹ùéX,áÄ“N,±É7¥ÜĦv7ÕÚAªm‹–hŠ ¡!?y?ïC-Oð÷ëãCþË)>Zy<“ç%à+\¿Å¯6œ–jŒ`v2¢ ]_OYë¼j®A5— š;®¯æ  ymÞu&P÷]¯àµß“°ÛË#{âé¬4,ÑÑÙ“M$SKBZd—sož:=˜¾:@K*EOÏ6"Þ¨u7à–É€ÛvïÞsok{ÛÔ4ÐÌÏÍy0ÇÈèØ¢Ñ¸Ókrbñ¤‹7;±ÆÍnSS Í›[Ù¼¹?ÒL™úJû»ºÙ† dý…æQa 1èð5Ô @µ{k)þZ–¿ ¸¨56ײäë-«±‚µ\‚`›¨ÑÏß»Ôb„X€wý 02- ¤ûm^0ЊZôöíYliëÊ7oj[2#–kšŽÿäøÙùù4Ž£†¶uu“hŠû×õcëyèêrýrÝ išÜÞ±¥}GWg']][˜ŸŸgn~ž¹¹y††GOÄbq»1žpbI7Ú˜t£ñ”›Ø´ÙMnj#jš@<ÔOð(J±üÈ~ø]›IǤ…(?´õ«Y¿Oõ¨~­È~-Ë_Ë÷·_*¨ÿ*µ€`5¨ÖŽÔÿ8¨úq´Ê‘„ ð)Ð^Ýq¹eÄZÐM‹–¶-KñDs.bZîÑï~÷ìÜü<óóótuuÒ²¹Õ¿¦êS†Ý¹  ¸«1vvv"¥úȹ¹ ™¹ étz&“]¼‹%ÜX¬É6&ÝX¢…XSŠds‹–ÜÜ‚7ž,;,>ä}f˜Ê÷v›ü^):íÑSM(Ú*ð¢Ø Gá¿ÇXŸ5_oà/(Z ¾œS“˜^SÔ=¥š[PËØH{Ø(ó)§‘ÖÜ«UV;?üYá¶jùµÊZ, دĨ¼ëJPñý>¡ ¡ÿYZ ¯H×Aæ Ƚû]FD´ln_ŽÅ› ÓÒßzk,“YÀ¶mÚÛÛ‰ÅJ/Xå>ÔåÉõ2€f ÞÜœìjkk¡½µ €l6Kv!ËB6ÃÔôìY+w£±¸k5ÄÝhC¦'OÐØ˜Ä?îŽóAVOçõÛ~}OŒàù£hµ}áIøKàuÖ~`½£Áýñð÷ù¿£–ÿ~½ý׊ ˆP›¨rž`eÁ?§ÔÏ‹©”‚ÁóÁØR,&œ à5„#…"B·Ð¶tÞ–kiëÌ5%›ófÄâõ“§Æ²Ù…Ò¤¡­í­$“%׿¾¢ð-ë€6 Ë²¢›7·`Yj'»°  “G‹ÑhÌF›ˆ5&°¢ ¢±¤‹7i–e ß×>@e°. A…ý¥Û|ÿ3l ƒÃ[Óð<ðSª+x-q)OÑåKp>§òÛ«SèHõ¯¥¬t‚mk}~Ø­ º%6P¾oÊ]!ëï» (P, {zwåã‰fwSs*oš XѨvibâââ‚z˜ZZØœÚTºà XåÕåÈõ@'°Ù²,6·”2¹X\Zbqi‘ÌÂÒx4¥!§¡¡«¡ +Ú¤@ žÔ¤¡œ®Vš€{XiíkKÂ?º]ÒMˆþS¥Ì¨)Äßdí!½ð~-À¸DHiª}ïµ”õIøøz\jç¬ $ä„úk¾¯ïÓÿ ï/Êçk²è dßÎ=ËR𢥵s)9 “±±±‹‹KK€ZV¼eóæ` °În²\3hššZÛ;»c±(©f¹\Ž¥ÅE—È,dÏY 1ײbD¢D¬˜fX1Íjˆi–-1ïïå^VWüjÃw–„ßì­ë¡Ï³ðÔ[zµ‚kþeo›ñ¬MZ~#ÊZŸ»žï­õæájçÖt|âï»]Þñà0lÅçÞ.t]• M´Ä¦Ív"Ù\ŒÅEÝ´´ËSSÓK‹‹¥‹¼)µ Ã0üÝ{Öq_êr¢_ǹQ ÞÕµmG<'¹Iùn¹Å¹\Ž\n‘|±0Ûű¬¦Ã4cše5 Ó45ÂÜÎúߨ n#>ƒ?[‚œ r]½ HÃ÷’ê¼ÛÖùµÐÔü÷®Ÿ>­%õG×#e ŸÜö[í{m¯s5HxŸa{…Põr²@yºb4p(Ø`Û°µ{û²½œ.6%› 89&'/_Éår¥LŠæd3–e±œÏƒZA¨.7Q®çnˆ˜f4žˆ“lj —÷ ÇÂâò°e۬¬†¸±âš‰jV´A3 /’¬¢Éw³¶â׃öø•˜¤5©oZå üõX_ò9ïm¿IûW+«}ÏFÃzÜ€à±R_¸W~^¡8•ÇJç¡ÜÛFldwÏμm$™ÜTˆ˜––ÎÌgr¹¹|€D2|3°îÜd¹hH45u%š$ ò¹<˹<¹\þjÄŠbYQL+ª™‘̈¥fƒfZQE")¥ÿö°Òÿ¯•ÁW-zßš‚¿Ý ¬#R>¯Ö ôó‚R ‚Fð2aªû*µ¢ûÕúÖú+FÄʾ~»?©Èôû¡Fl‘j±l¡é"¹©%oD,Í2-mzff<ŸSДh*­‰Z=¨.7Q® 4M3€F`³Ð4â±ѨBíåå%òùe …ÂÕ†hËŠj+¦™VTfT“¦%"¦%jÊ]=lA)îj©»k½Áç-Íð‹QÅôp¡ýŒÆû.jz²Ò_ ÕƒûNAÍo·â³ov ÿök9'¸¯­÷\ª{-° ©úÜÀ>ZyÑQ×E·UR-íÅd²ÙnŒÇ‹‘ˆ©-çrùå¼z58Þ£!ÚPºèõ‘€›+׈1 %uI,ÖX:P(Y.äÉ —,«A‹DcšiZZÄŒjF¤Aè†%¤.…¯Z)ÚXý-¾`½Ö¸½¿Ýœ„§áë5ëðª’l\1]Þÿñ%¨ü~=mM¾åR+°‘8ÁFú—â°"à·û ¶×æ/K´.Ž£b¶ ©–-ÅLú¢cYQò´tzn¦PÈß‹ÅhŒÅ¨Ë­‘ë @J+€Ø…Bb¡€ã’‹XQÍ2--‰jFÄR݈)‘ê!I즶¿¿šâ×T~Ɇo¦Õjµ+Ę…EN˜°ˆ³Rù4[-tñ¶(ÿFd=A¾p_QÃÀàñV(¿/Á  ]ÑTÚÞÖ±847·83ñ¤ÓktœeQ´‹ù¢79HCC”+ü–ÀÑ ü¥ºl@®"­í;¥”Á  Å‚M±`ä,ÓÒtÓÒLÓÒtÃÒ„n i˜"ôDiÔ¶þë}E7\ 'á[sj• ¶¿S·?ªÑ?¡!‹è~Ç@P|k_ ª± ‹V^œ°Z?72r¤ü¾®«JrSÜ1ŒˆhˆÅíÂò‚6777SPÏ –eaY„¦á¸²º\‹\+”^ÜÖ¥Ä2Õ ŽíP´‹Øv“†i‰˜š1…®›š¦G4Ã0„o<ÙAíèÿµ_ 6Ã÷fÕÐÝš²ÃQ5Çà¶Ð¡9®1^r#åzÝ€º á“…ãï[~C:¨h`XG-•ÔЈ+ CkŠ7sÙMJ©mŠ"-H+êrÓäZ áW¤†2Œ¶cã:6¶í K©™S¦% ÃÒ ÃèºÐ4¶«)ózÁ€*Ÿ`h†×Òjâªü1‹p5ª&°ìAY|· ¸ø™²þkÉj®BðzÔ âöƒÕ`.ÏqædÊž'ìÙSÓu]s²²å™ ž tSeÃà½hX–Õ  ‰ô2·\×ű]ÇE“R3͈fa˜! C" G—†‹PÏžg%šY=k+þZÙ|÷&¡i^¥¯)9ÈK2 5ãü € ‰a¯âTv­ÞÏ×Q.˜–¥5&“ŽiFÄìììå Ý—Þä¨ÞD¹`áÑá––¶n50ìC¼ƒ‹ƒë:†™X–0"¦Ð SèÒEM /q$ȧ7Q^‰w½Ôß—jûáºoÐz`-›våÐ_Uñ^I¼d”‡Çêr%žHºº”2bššc;ÂuÊšÉdÉf‰Å¢˜‘f$‚.…¥¢¼BJ ×Ö5WAh*¾ãPa9ÖJ쩵|¨Tôð9µú—^ž³Õ;+ò¢è×â»‡Ï î¯Å‚¾~EÝ)+z醸•ˆ¾‹~ú¯OýýùÇ …. C ˲Zü2™…0HS—›&€ýø˜†²Žþý€›ÉÌissóÄbQ"¦‰eZ Cjº!…«éÒEÕ:š¸¶Ï9)½|ÓøšjÏçj¾ðñà[°a®aWY+(÷ æµy§±_ª]¸øÿáþ>}¯ & ³ë…[$4tÏúKÐ¥b†!¥iF¤išÂ_|~~ž¥lœ¨ñSërdCðíþÊW˜%Ô-Ÿµh:¦££Ý{ŸÛBƒ„Ô$®´A—¸Ûó=]ÈÙ¢Šl¯Eù«I5K¦úÁ¶ðqß O¿WSô[«Yÿë¥ÿaÿ¿&Kðºâ*Ü¥J_€éI©ÞÏÖ=@/˜†!EĈ4™Þœé¹4‹¹zJÆ­’ ÀKG¿í+UÑÛæ];›ÍèWÓŠ©YV+já⤤®K©+åG€šnà89ïaqàüWš»®9Êëö£Ê± Ò·ëÌý¿Ù °å¯6vïV點 ]êòý+0À»R~½´ïªÌB)¿” ëªHÛ4 CX–YšR*}5M~¹<›ÛóG]ÇO®Ë5ʆ`dbÜW"å ÉÌ]LÆ=³3jö-Ó2‰64`™¦©KMJ)\¡ Wh[ éGJו4Ëtmè7¯¥ðá}ïÛ€J­š`ä‘“ŠTçÕ”üfÀÍLƒY°øÔß-Óú`Žf‰1øÇ‡!à8Êÿ7 ¥ø>º†cJ)…iY Ûq¸2;[J,£îÿßtY7hš¤ÔE¯0—™¿ÒRXÜ6=3SòÉ¢Q¢¤g¦;Û·6_Ô¤ã¢á‚!Ñ4­ü€LÍ®™tS-‚Ï*û~=<ÕÝjV¿¶úY2`¸• °Å¿ë¿ú_Õÿ ñ•úù@àûþzàúñ/è+¾axE¢ëBèRʦƨšpæÊ 3Ó3Á$ ºÿ“åZ†ýyû‹€;=uyb[W÷½Ó—§¤?Ћ‹ÅÈ.eSRgRÓ„‹é E ]¨•büņ©æWµï÷·á€ðq»šÒ•ßD±ÆuY°FŸµäZ”#²^úŽî;ž¢»>Í÷ØëûÿÅÀ4@7ÔÖÞl2` Ë–aÑoàËÓÓÌÌÎNn²\K"(öÔäø„ã¾Çžžæâå)vôö¨©ã1Òós))5]è $šk£é6Žià.{0â80™%Ý«€ ‚Ýyð£ü~ßõ(y…¥mýï°]O‡×“dPM‚ º0؈BWë»Që_-àG¸-Lÿƒç¨ƒ.AÿßÛ¨€ˆ¯ü¥eÿÐÁ5 )›cLMN‘NÏV= è&ËFÀ¿ý6e7à +3i®\šTÓ‹cò­R-íj®T4P3u?‹P}àä,ÙÎòTðÕ¢ún¨Nè¡ÊvUKÏJðÝ\=$»þ¯Gn¤¿^å¯%Õ¬50ûöu7p±¼ôó|FPÁuýL#å'ÎtÇ4#‘F’ˆÉÉÉŠ¤2êÓßtY7¸®ë¦š69³óiŸþ/£XÀ\6—_Èe3Í'&0 ƒxSÃ0cv1×`XÎ’ÔÁuÐ 'ÁÕ²åedœÌ}*XËǯEóÃJÜÂêÊ¿‚xÓÞUŒTc7+ðWK6¢ü×býýc%e÷)¿÷>ýZzß¿wuŸ5›žâ›˜ˆ”/\Ô0 aH# Í.rqbÂ_€ç®»7Y6Ä6µ´à@•lÎÌäôpsClÓ¥ñq-—Ïc™&ñxœD¢‰Ù+Sm]‰¶‹H]S`¸ryp‹° ÖÛž•§_MñÃ.@°-¬ða%Öƒ.†ÏX5@+øÛµ¬z-_¾–òWSú5ƒþÖ‚|íUêA°ˆ`šê-«ˆ^òÿYÌåcŽãlJ4«[>vqœKžñäh¿Y—(Òðl€üØäØùîžm÷Ž]œccéÛÞKS"ISS‚ËÓÓ½’IG€+†‹1qMr¹²µ™bnwkieVÙúõ U‡êÊÞ÷¿¯ô`PôV*x-€›ëUþ°ß¿Zÿµ¬)zïut‚u'`é½ö ¿ßUÓøûHêØ*í׊(å7#þ¿æÚ…Š{‹ÊŽ]czº"øR¿T—(rÔH`) ï•BfvfÄÅq.ÏLÉÑ £ômï%‘LH61>1¾Y GJÍ­ƒf8– é=D6œc~wkIÇVóíÃõåwTÎIÉ¢S©ü+¬¾o_¸!Àõ€€ßn ¬æË×RþjmaêîSËú#üþ <æ¾ à[ü¢Rüb€þRY3  ðD_^^ŽºQZ_bô™…Š0®r)êrƒäZ‚€6Jñ—ÛéBnqa)MŽŒ\(éH2™Ä2­†«3SÍ-[š®"ÐlpLÇŠ(z˜Ë«&Áž‡\£šp¤øqC4O±Ý*VÞ®ÒV«80ðö% ¿´Àê@àËXKñ×Cýì½BùWµþ|~ß껬ý÷Ö´À2U1Í2ýŠÅbc4¦Æ'&9?2B¡Pž­½žxkdCຮ£iš?P@Í£g…±‹ão˜·7>t~xDŸ ³³ƒdrÉæ$Ƕ¶wnÏ Ð"à<`™ Wiîð8s{:ió¿ÏY©gÕô.ì ÛÖ,n î-tã'*V€€ÿ¡¥kQãÇe=ʽšT£õÕ~Áöj.A-ê>¾Âú»•þ|Ð °ÝÀ6è÷{!XD#žìo*r IDAT©¸~±b±˜ÜœRË0Žœa|üRð'^åçÖåʆX«¦iÚÎ;¡ì,£@ ?<:vûâø8çΠ9Õ̦æf² ™6)m]—ŽnHôˆµ 5… í 92AÖVÑxÍV–X¸j«¹ªM¸•E m×Sd`+é ­œP;ãá>7¢Ôú\'Ô'ÜþÝN•~nhë€ÄA:.Òu‘n îTiwœ@)ê.Ò±‘nQõ˜êþZ&2j"£2ð;'æºnJx9Á熇¹:[±sÝÿ¿E²QàÞy×] @¥ü`ÙÎeÏæÛž½šÖÏ Ó~øAšS),˲f§/'[ÚãóHl+‚kY5a.«–Lgp'æYlM\ºÂ‡,™,èû»¢ÒÊ+,0ú<^ú°6 Ôo£RÍÚûR‹ò…-¿ª×¤þ”é{0’OЪ{´¾´Á@[ÿì¢jógˆo0!j)`Yô_ær¹ÆXCCÀøøCƒCÃÔÀ-“ gž9uÊ~|XF¹ —'ÆNvuõí”ÃÃ#ôööJ¥HmN1>6º¥}ëm‹ 5ËÄZÐ`©a@ÿ!¾ÈBj—š",”Ì/ÄJEÒ÷ / ®æQ|me|ꯕÝ^ÛÝ&‚€×]IA«)òFe5ů¦üÁ>á`_ðó*&ùøû%¥÷JÐ÷·½ ŸŠØŽêkHOùMhˆ(HCn)·©9Õ À[ƒƒŒŽV$üxþÈᑵ¯N]n„l¼8€K9˜ó¶ÅÁ7‡Ooíè¹oltœ3gߢ··‡x±·q\dÑUû¶4 d,p_£–šÌû?F>ŸßÔ”HgΜáÌ[ƒØvÅJ@_Úè3Y—k— €ëºîÖŽVoñÜRpócc£o8¶kžâÔéÓ´nÞLKk S““-†À0t KLjšèQ ½ÁB·LtÛF·ôó,gqma;ÛEضª»ŽR`»²HdÑSæ¢W÷Ѝ¦d6è¶÷`ÚÊ÷×]o‹WÇÛwªÔý>n o°8ë,áóª}n¸¯êç¯Öߥò¿•ê.ºã¨­ëo]t§X®ÛzÑQ[ÛVm®nû[Ý.ªºc£ã¨{m@5¨zƒ¬øoÑ………”?ûÏOOŸáâøxðñ:üü‘Ãõ9n¡\s=uêMŸIú.À*X:{úÇ`rzšS§Nyß"hikÃqÜøì•ɸ!Ñ ÝŠ Ç,õ°4FÑ¥P’c£ޱhÛh¶í)¿pm„ízm8x ]!ë/ƒ á”A@÷¢+e=@•J[ V+µÎ­¦øÕ*¼¿¦ò;ª¸å÷Ûl×»Eµu½â8j¿èomﻘ™m?=uFœ- ö¿øÚÛD[øÎ9<ªËr‘äB£WÒ ƒò­í‡¶`¯tvâÅý/à,`VSÆGGÓ¶í   ÔDJ*%‡’ˆCÑu(Ld•ë†ã‹‘_ø¨ïCq}PAñ|PÏl@²ŠÏ@Š”ùäè_òx(wVz܃*žöè±Êˆ@pKåg2L¾¶ÊEPñÚÊ÷1o½ÏŸ©ôî{¾ðð{a_ÀŸciñä~Àß+=ý¾'öÅg& ( “ÿý䢔G3LÛ¶ÓÐ70ˆ–[0òX |>åEÃŒú€/¶#~‰~ÒgÉ*»‰J‰¢åTL¡šTË<Óë+¿· 8Ó¨/Ï—Js#ô†ü¹2&FsÆGr?¨û÷ÃX¿/FüÒZ0MR ±ÈÑ¿|X!¾ï×§RÜöß÷Â>lk«œý÷ÏÏð8.Ë«(49¨$ °À¿æjݺråÛîíìè¾½/àÚeWCQ(ššf£µõ%stt4‘Édl@"f'8._Æò(p¼A:bš\—á O¹¶r¥— /€€RNOÀÀÑ=€ú%Àh¨ø3V&ÿÕ šRV¾FÊÙ‚Ó¥þÑíJGŸÜ.íWQ~?ê¬P~V¡Ø¾ÏÏG©¾_±¸Ó/Ò&€”1éVb¾ë&EA׉n¼°weÞÿ“—3ÿ^?¹à¶M·o úòbñ}=Û\·˜wlûö¿ˆÝ{÷² YÌž=ZZ2à`¡&(ÔTj2 5•€šLðÜ&bÍ=<—ÓRWÐO¹ö\(¾Õ é«êùP<ž´¢Jª*Wƒâ XžàGf~Zt*]5'át–jŸ1Õk+ÏW¾V:û<Ç÷YèT ü0Ö_ræü{~…Óχêya¬ß¯r>a”ÿÍR ¨F¹ãOs§VÆýwïÞ‹Ãí—Gÿ7’\Ñ¿aÆLgpxÀŸåW‚€ `¢õ@ëæ•o{Û½Ý'º±g÷ X²xêëêpÅìÙ8=2¢è:‘œ;®M–Òbœþ®ÇOCc|Tš˜Nöƒ5f¡&¼z˜ óbôg¯&$áèϨPtYû[Êî;Âe$àæWz??3 Q™*"PíüÙd:£t{’â#2úW*¿Tvéèl `áH/ù>àG”ÝsËA€1áðK™Wüt HM¾Y…RªÀ‘#ǰsç.ôõõ—Næó{wïü›sxD—åU’‹&ÒƒeZ°1ñʾ–æÿ¸cæ]‹zsóÌ›3wÞy;R©æÍ‹ŽŽ­±© ˜ còŸë^d$³=À*=ƒ MY€H×½¨ó%TØö„MJå1~žEü\ˆ„ŸA–1p³"š&,¥R*" Uål#t¿dã‹©ø8Û¨/Fz‰”X@•°^iäwõ+Þ“0¸Âg’|äϤ8XWqGÓuyËÆ³ÏíÄ¡ƒ‡Êmm‡þŒ1V8ã¹,¯‘\Jy au ‚¸Þ÷âO]¿âm÷ ö’í;v`Ö¬F\ýr465!ŸÏcwónmõšÕ à”²&Åx~d„b9þƒÌç~ ÌÈ:¯å €Ò°»'cá¨.›2¥dÉP”€@2p!•¬!“…ç#U™@TéÅ>‹nGˆdú±pz‘}¿|ÔŸJùÝð]^ן#MJ¬ LžG=ˆðûaû³Û±kW3¬‚]:}âøñ öýèÓe¹ˆrÑ@HÎÒ-pŃ€ÀèëÙ‘¿êšL&såá¶vºmÛ³˜5« YÌŸ?–eáD× 2wþ\܆’‘øµø‚Ñ1þÔåLZ”ÿÁxÿqÒ¸—ÑB#@åìa y„ÆW‚Ôüóu –ÆÇ ²Š*zå~2˜)í©èQ Óy™Px/…jÊï &U¾T³û:ìo9€g·ïÀ@Hýb±¿íPË×cg›ú²¼Fr1Ù€qr-ƒdf \Ьæ]ÛÊ\Ï/:š÷ìÅ3[¶Á÷(š†ù  ¿ÿ¬H‰hŠŠ]š¯ëÄ(¤>rç€Ó£åÃÒXþˆ½Ð–-ýнÈqxùÔ8ŠÂ¤‡\$ÒȪ¸ÀçÕp2|æáÂ*L>&_+ßï±ðóJÕwQ‡]4?j»{÷]Üð~=/|>ÒñçúüùyÕ”_¬ü™Êš6VJwO¶nÙ†¶ÃíeÔËæ§þÀ‹ù›»,&„HPgà ûv¿ØÚòkxÞøØ(žÝ¶ÏlÙ H¥RX°`l+ûÀŒÂtµ©r0Pÿ¡æò‚¸áæF~Ø¥ãb‘ _#cÞ%%®^幈=]J—(rT™KKå12pDÓo+•>`¡‚Ëö\U_*{¸S`ÄñWz~n¨üu5‘çŸäÌlÒÝ÷yËÂæg¶a÷ž½e}þ»º^ù €1YÆuYÞr±M¥*Aœ%êà&€n2Z}=Ûš®jhh\Ö}²›7oA&“ÁêU7¢>›EÑuѼkÖ¬][úÐ: @*¤Ê’vKŸ@ŸKšÜÀ(§òŒ~$:Pj(¨<¥üª˜ð 0á;„Ÿ d 4J‘ˆˆƒ¸–2‡Ÿ4Î Á¤ ”Ê¥ „_nK“àlN?iH_@´šÏ—Çý,¤çß÷y#ÏLM8â×¥9ðVñøóÛ-¾Ÿ~z3¶?»¹\˜ð“ÏOt´·½ôMÆXOõw_–×K.:g ,.€+þDÊ/8Øû÷ïýî­7}1a$kÛÚÚ‘N>T*‰eK— ©© ¾ç¡õÀ,¿þúÒggti¡hÒ.'ÀXŽM€ÓýTPDx*a§™ ìÛ·Ÿ$“)$MsçÎÁœ¹sá{´´àú+ñ¦: <½H(²"–ÑŸl´(F¾„ ¨Jè$RáEF (7!%¢ˆºáHb¡B©$hDÂ…Àd@B–pnÏ,Ü.yô%¨PzåJíë_:ñW¢ÒãÏ„Äl=!Â{¹®á´Ê‘_(óî½øÍožÆ+]eç·mÙümO1Æ&&¿û²¼Þòª€ÎòýöÀA@G˜aÛñü®?Z{óºß¶Gyn×.qïy÷=hllÀü ÐÙщöövˆ‰p 5\qÂN!À(ò6/'fŸBÕøëJ#¿nBᙘ¤4j:P*<ýÑš ‚È»D¨¬@ Ó–a âé—Ì ŒFΠø%Ç¡ôS“ ä?ð&ûáÕ|™P“!?ÁªÙüQi9Њ§~ýŸ8Øv¸Ìéwz°ÐuíºÏñ‰\–×H¦„°ò ®éJ‰æÁ•_€¡?ãã#Û;ŽwÌ^¸`ÑÍù|^Ù¶m;tMÅ»ß}êëë°`!¾Þ^ˆD!Ü1¨¤ùèO) RNãµ ît= (šÇ'¦”,@š Š*”Gáet„F€@2¥I}”ùÒΗ™‚ÒðåÝ•‹xk¹e«r…ëIJ/ÏŸEñKa¿H´ êÈ” Ó¬>™à“,àLÞ~8t¨ ¿úåSØßÒRÖÞ{ãÆ è?Õ“ |ÿoº»oïúsYÞ`2-8å—•‚xìóŸ÷¾óíoË^²LT×@=ÖÞöÃt"S—Íf—ŽåÆéæ-[A÷Þs7êê2X°pºººÐqì.ZTúŽ  ðÙhT¯5›üÇ®j€¨(å(Œç á+PDý}‚£\Á"fP€ßB@&ù*•?¢ì@h È‘^+Sú G`Iñõ—‘ ß‹(¿Xn*•rû£ `NçH[[;þã¿Æž½åÿwܾ 7Þx#r¹¥ÃŠg·mÙ:«aæ†Sý—Aà &d:ÊMdýóñ~  H¨ë:ðz@fÍêõŸÈÔfæƒuµµ¸ýöwàîw½Y1T÷‰nä'rXºlYÙç;ÆlËãyy>혴ïUEø QG¡1¨Rî7k Â$¦ ó.%]§Ó¯VFdrOTár¥—ÀuúI()~$Á“¡J9ê3@#ÜYšU}%H5z• ¿ 9t¨ÿñ‹_¢¹ywY‘ÏúÛnÃÂ… aš&‰8ò¹¶lÞŒíÛ¶´ôtw¿)A@êÇë%ç«—À4àb!Dg”„@‹ ™5ëný½ššºy uµlÜxî¾ë.466úz{‘Ïç˘ÀGל+”?ä&øv®À·1@)Jh€ªÂ¯ öA+À(E¤¢Gÿþ´Bó§òH敨²G÷+ÀU@¢64aIŽúqƒõ¤¢“O‚Ûýé38û¢Òr ¿úõSس»¼Âïþû?€ùó`xx~¼e@àMŸzôSøù/~Šî=ÂøHo‚+ !d¦×®Y»æ÷2é™ó@AjÒi¼}ý­¸ëÎ;0_¤ ãTo/®Y¾|Ò÷ä! Ï›ˆHÈøüƒ®_ÄšHv •=Ê ¢`”@@nåÊ_ g’h+⪠ñK`Pá”^þ’âå”?¸­ŸŒ‹ZþxXÓ/[zMîæ5YvïÞ‡_?õkì±¥Œö?þøç°bÅ bppxär9lÛü4¶oÙÖÒÓóæ7=\ @À•< •L@çkV¯]ÿÉÚtf.(ˆcÝÚ5¸ãŽ;pÍ5<ÏçÑÛÛ‹ELàiˆ9‡× HÅÏåyO|°ŠaRO%¨„û¢ŠH6„T¿Ò ¨d¥ÿF */ºš×_®#€ˆÒ—@Žò¬bÄkMÍ:ãaãÎTÒÚôL–mÛ¶ã©ÿ|.sø}ë‰å˹Y68<:  ¦9~ð£gL3þ•D"1?iš£FÜønC6{ÉMr)À´œ€}}½hÞÕŒg6oƳÛw õPë9©È %âÝg™3€ƒ0º{×ö¿[½vý'k3é¹V¡@ŸÝ±¹|¹Ü&¬Y³‰D ,DgG'gÂL„Á* @Äê#Ï‹YŒ š&lž7à:"Àç 3§bQ»_: E§â²#‘Uuíªâ” Ô姤ðò5r?¢ü²à':ê#àl&•gêIˆY{R‚ö§Œéú–mãé§·`óæÍèx¹³,Ô÷éO?ZR~ÈÖg¢w…ááaäóžê}Û¦Û`E_ßÖyóæÎ¯«Íd†‡1–Ë!{ÏÀÀà“ªª=VW—yÓ0„7²¼f (c øoO2É’b×ãÔšµ·=šÉÔÌ@EÁ’Å‹°éðŽ¡ë¼} ¯¶í@VFEúòÁl` ¶`6g¾/ò ”rg`U€òmI÷Kö>©Ðù3@is ç_TáåùÊé½¢Ý~~¦Î•=nI#drôOLÓQÙÛÛ‡§7oÁ³ÛžEo__Ù¹|ëÖ­ESS# ½¼1Ààð‡188Œ¡áa&7 ¬^µrÒwµµ¦iH$ÌMÑ6d³õ—\Ê àœ`xx--û±kÇ.l{æYìØ÷œÂ¹Wv ‡ wü%€ƒÂ^©•+V}8ÛÔ´Œ„*³›°~ý:lܰ³›V>þ~Ì_° êw:àfAÞâJ_ZÛ|]°yØÐõå5–'•E"€”ƒߨ¢\Ñ•οȟ 2û¯dûËýŠô_©ü”º ˜1®ô¦XJ ,@ãÈ:9p [·nCóîÝeÍ<®ü7Ý´ Ÿðeº °`þ|ܸr²ïFJ׉° E$’‰Ñ˜¦mhhȶLór_7yËÀÅ”6¿éL ô h”…‹—=xÕU‹ÖaM×d’Xuã*ÜvÛzܸrEésûz{A)ECccÕïµä#@ •_2Ûá¦#Šb@ËÁ’ ’XL²ÿÏ%°”E¡ý<.“í~ÉX M˜7:_ÇuÀ o êojgëKq[·îÀ¶g·ãp[{™§\×}ñÛßþë%†a”ò„΃Ð4 k׬:ë÷ŽçÐÝÝT*È=ÒØÐðä4/ýu‘·tvvaçÎÍøáÿý~þ‹ŸŸß“RÛ(Dƒ&Bs@ §3u·Ü¼úÖ÷¤&š¦cñâ…¸õÖ[°þÖ[‘Éð¹çlËÂàÐæÌlH±Áç"” À.†,À.†ë¢#À€…Y‚eL(aò‹ÎBg`$¸äŒ‹|¿¦ºÆ3Kþ ±6”XÀ9(>tttbÇŽxnW3NõöVöðÇþý/ü| ¯çg>ôðº?ûÊž;¸®¦Æ,v67ã…}ûaÛ6RÉ~ðA¤R““]ßÇ¡ƒmH¥Rˆ›Æwš;‡ÛxMå-K àÎH!@`FÖ²háúM›>%3òs²ÙX½êmX·nV¬éåÈð<×CƒÈ!¨&Ë磾‚(8nŽË»û~9 ð{ák1€³ê?—ˆ¢(µüŒ¡>—®ñPž®zŒo—€Î•>n>ÕÛq°ë¹ç±cçN´¶¶"oBt ×·ò›Ÿ~úI/Bœy衯ûòWþlZ °o ~ý›ÿ X¤”@UT¼óÎ;qýòkª^Wë¡6躆¤™Ø¦éÚ} ÙìÎ/ð–€®ŽNlÞ²ûøÇÎûË ´®â IDAT2& ƒ@!ÈEv.±…å7®ýHãŒúÅT¡ Óu\µh!Ö®Yƒ5kV£©)4úúO$ ç§«&>ÄüfS0€¢NXâDšfÈŽCÑ|B:_ÅÙUö€ t6Êd%™Ö¬ª|SÅÈQ~]MC;{î~59ÔÖŽæç›±{ï^ôœœ4êã£#'víÚñ?¼,Ž¥ø>øÐÃ7ù+OÔ͘Ù´r*qد*´¥ò;\á?Ò~ÌtÙ‰ôÙ+•ãFcþQÇ_$ŒH‰>ÐPñ¡üч˜Æ·c‚Ó9jž-u·šôôöa÷ž½Ø³{7Ž}¶m—g¾ç>rxˉ®Î¯ç âo‘p…<øÐÃ7W3ÌŸ#z>Û)¢Xtàû.|߇ï‡DQ(EÁ«âÃ=XõZ»Ntcll©TjÔ4ŒGÞ0ùoY@CýÔôúœ.$ J0úäZ¦ ëb0kõºÛîϤjæ*LqB0«© +W®À7®ÄÛVÞE ÇáÔÖÖBÓÎN’}ð>fN„½°†>ÚfKö ,5âÊlú’ÐPñeR‘LHRQÕeJ…  „5Õç###£Ø»oöíÛÖÖC-gÕ,€?Q°wnúûè¯æGÈÎj!r8âL žëbhx/w¼ +_€mÛ°‹6ŠŽ ÏuÕA ¦&ƒÏ}úS0ŒÉ Ëåq¬ãeÔ¤Sˆ›æŸ756>qžà¢Ê[^ ‰D4p…—@e&"ÎAp6°aÙÊwPUÝÐ4s®˜ƒ•7\nX믿® FGF i1$ª8¡¦W,r΂(È”\/’¼3U<”̃Òè/Ê”ÂGzU*¿°çÏg”Êèè8ö·¼ˆ÷· µõKtŸ‰kb‚ÃÛž9q¢ã)=Æ ‚€þ¼eÈVæmpsàá‡oþ³/?ñQ0ŒÂ¶mLä'p²û$òy –mÃ)ÚpW˜>‚ *•@S5üþï}óçΩzZ!¦ëH¥?Õc±G²õ¯o¾Àe¸ˆñ È´aå@Ý—½e¯Ù+V¬}wcSý²ÐÏýWÌ™ƒë—_ƒë®»Ë—_šÛF.—C}6{^×ì‹ÅC¤"O€Ìé¼¾ä'Œ„ʵK.ç;ºW“AhmÅKZqðÐa ô÷WØùü,—?Þ¼sûÁÛw ‚øÃN#ìé ÿ²žCnSä+_ýê½ïßûïµmE§§è`ttÝ'{`Y ¶â$¯EQ¨ŠUSðÎߺ›6ÞVõžµµÒ©TKÌÐïkÈf».Þ;7¹ ¯‚& Ù@\,•`G8ï€*^k(zbÅÚÕ«n7S©Y¤¥bºŠYMX¶l)®¹f–-[Vª2”’Ïçáº.2™ .u9v¬‡ÚÚqðÐA=z ÃCÓÂzP(Z¹ýûöý27:² \ÙÇÁGþa±À1,šÁ™W|iÔ¨~Ï Ÿ®¯«½Â¶mض §èÀ¶‹BOO/ò–œb®ëÁ÷½²ë¢„@Ó4hš†¥‹—à¿_ÝÑ|äÈ1ØŽƒššô¨i÷54d·]¤GwNr^%©( Š!(‘µœŠ, ÙÐ8{ÍÕË®Ýdhz njB…bF}-.¸ K—.Æâ¥K°dÑ¢Iv§mÛð}‰ÄôM„×[†‡GpäÈ1´=Šöövœ8Þ\.7Yñ}×s<×:x¸mÛ@oϳàŠ>>ÒŸÛ£àÊï2ÆBˆd[ÂðlFl§ÿðñÇïýÝO|ânÓ0k lÛ†ãaÛ6zNö `°Žã Xtàz.|ÏcˆH¨àÑ𦡶®_{âËUïwpxÝÝÝÈdjašÆë’4t)À«Ùð‚Etb„(M 䣜u»åkbð:õú¶ôm}!;³qõ5K–Þ¢±PŠ ðqªoýC8ÐzMM¸êÊXtÕB\¹ðJ,˜% C‡a”—ÊX–…˜¦A™†ó𵔑‘Q¼òJ^îìÀ±c/£«« CƒÃ“2ø¸?"ð¬³óåæŽŽ£¿WöpÅŸû’ÁŸ»,ä’ù‹“Md ãÛzŽ€ù`APZ|•¡±±ù‚×uáºñ@©l6ÕŸ†–\×K?>õ¹?ÄŸ|ñÑTÁزõuÈÖ×aï¾ýðýÌ?#ÀúÆÆ†G.âã}SËšH‰„ )Jl@1Õ”$@’Ij ÐRZPbŠèAHtÀ72u鋯š=UHZQJF(a  ƒ¦R$“)ÌšÕ€+çÏÕW^‰¹óæ`ΜÙh8ƒoÀ±Ã<Ÿüù‰ïèééAwwºŽÇñ®8Ñ}ƒƒÃ° UçÜ |Àsm{âh[Ûs½}Ý-NÈò¸Ò‚Sÿ¸²,ò!áP§€38x$ ÀB3ðƒ{ïï¼ãV˲aÛl»Xb¶m#ŸÏãè‘cËå` ÂLথ„RPù5ŒqÄ÷|PÊÍ‚{ï¹wÝyGÕ粿å̸‰tMª%¦éêëë^çà¥Ì. äï f4Âþô€—ü4﨧)1’”ÆLB„ò¨c*PÀ5©æ7ι¢~±£5J,PT% Tᦥb  3jÐ4»óæÏųg¡±±3ÍfK•ˆ¯…äry ¢¿¯§úúÑ{êzNžDÿÀFGÇ'Åï…0†€Á‡31‘ë=v¨mïÀèÀa„Š> žû”ChóçÀG}œ€MùãˆDkR®°€ºháâ?ùùžÕ4{NÁ² ¶mÃ*ð(ÀØxmííÈOäQ(Ÿ@Ñ)Ñ~JiÉ`¢üÑc ¾çCQ,»zÿì£U¯ëȱx®‹LMºË0Œûêëë^õ¤¡Ëð* %ëU%ÆGu–Ô4…š¦PÒ ¤†Q–$ÔKê')¥)߉-‹Õhi×÷xÂ)À[} @¾EhÁ‹ÅX²aŽéÄPBUB@(ˆªPU¢ˆÅ¤SqÔÖÕ aÆ ÌœÙ€úlêêêQ—É “I#•ªA2™@2™8/p°,>:ær9Œatt#£#>á¡a  bdt¹± ¶]Õ™,XÀ¸®ÕÕ}bÿ±cm/èEhÛçÀG| \ñåÜà™Ñ>P2¿Î(„Ü0Àµà¾úž÷½wÅ·¿õíÔdÒY«`ö °,î °lŽmc Ç::`YyXËB0hÏéRÄLC„ÊhÆx>7-æÌ™'¾ü§U¯«··ƒÃèÍdFfü‘úúºW5iè2¼ BÉú8 $5E ÖbÔPU­¥ªZ«¨FcJ“;áÝàÁ]XsA(±å I™Å« &üÀÕ »ì¦’Ñ:Ö} ÅWB Ò,_|”dà oÐ]×X¤Èd3Eñ *4 PUEt@×U˜¦xÜ@"‘D"‘@*•@Ò4Çab±TUƒª* â €Ï|ø®¢ëÂqÄè8a!_àÏ[°¬< ÷–G»ïT— @æ3ßï>Ùw ûرö¼“ëÕ¥âG'lµ*½œÎÝàOGñ’9 ‚3€…æ¢4e È£ðè-_úòŸ¾O×´TÁ²Q°-,§d è=Õ‹üD…‚…bÑ¢*ÐTQDÎ)µS `,€ëºH¥RøÃÇ?‡9³›&]ßx.‡—;:QWW‹D<ñX6[ÿéÜ×ùÈe¸H¢ßR0“I€Ö¢×)š1CÑbõÐÍz/ç®u½Â: ×@c30ãÆ5H/_ŽÄì,j,áÓ^y<'¿p²¾ì¡åû"/|V @A`Ìh‰)¥¦ …>Lt¼Œ‰ÎŒØ wø0µu5 k¸‚A¥QU• ª²RcQ)”p[VU¸Žðæ!á$` ,°€lA0åˆ^U| ~±` Ÿ>ýʱ£ÇÚm;wáH.鼜¤ÕŠlÄâˆÅC…½6‰ôx¬0an@?ñè£k¿þµ¯=ì¹®jlØ VÁ¾"lkoÇÀ@?&ò,Þ9HÓ4(Š2ÉPb¾çÃ÷=ø¾ßûøïbõª«^çÞ}ûQW[‡t*õd6[ÿª8/ÀŠJÞ©2°R ¡zÓ²ªn6øE²Ê¶ wVCýõë¹áZ̺õ˜/äûú1q¢+¤03 4æ\Q‹y³ë0†ÀV\—AZ°òg÷ „;šÆÇ h=ÜÞ±§r^>­Â‰ÕÂhlB<“Õ€[1¼¿c/8¬®†²l…¦:S5Œû´ý#7§¼ ³Öß„9ï¼® X§ÆáuÁu³Üpekß¶×.ÒJ1B <ë®´ŠÞft´®8Ü=<÷|ö´  å¤ƒÓÆ,Ô\µª ïß¾­¿Dîð(…º¬?–4¡%Ó$mÆèºCCeºB A@@F¦P… ¼ÆJÀŸž„÷! @}êJ 0Ÿ$P@ò£¯XE×éë9~t ïT/Èœ|OÜ‘‡rÅv*¸ý£û°© Gç®üR">ÙÙY6x­C8dü'?ùénÛ¸áË’Ê_ÎFGGÑzðFGÇÏçyAˆƒ¦)P ŠJ@‰"*')Of ~ÀY€ëúp .Ä¿ðxÕk=ÖÑ ßs‘©©m1Íø#étê¢9/ÀyˆFî7¿†€d¡¨3•˜v…¢‹ ã¹8ógÞòv,|àè3²˜8™Cbä8nj ð޵Wâæ•)aFdúåÍ3¤ÒË_¹]‹v_Â*¦ø,A"OÿP»=/Ä÷¶Ä¨Ñ„šE‹ÏÆ©ßü=¿ø%ÇÑ4çEÆGoÄc·jëâµT ª¹¨Fgfê®PÝó©«ÀƒJ4À§8=2ÔWt„ ßeþÀpo7øˆ<î sÅåFs ¤Ëut;ªìr;ú†ŠXþ(4I+ÚÇA&Õ€‡ )€ØóÍ{>µxÉ¢¥ËBÔ1(™@ß@?lC.7Û¶¡i*ô˜UÑ jT…€µÔ€…c@€À÷áz>\†ï|û[U¯¹ëD7òyÔÖeF ÃØP—É\¸ ç 1ò€Ð4­§”6’˜6[Kį°†Æ?äcâš¹w½ ?ð˜N1üÒËX‘Îã]kfaÓm a/<9É%DÛ.²êN–á–Qj·©„ €*ÂC@Ãn?rþÙ>üp»ïþdšO*P½ ñ´Šþ-Oá•ïÿ36‹åöøÞð©À?cË1ò@¡X1)X”H*.ç,–£ºèë "²Ë%ªØÂ¾r "Ÿ06UyÒ¹‹0”wt’l@¦ Ë:ÚÇ>šÍΚcE”¿ ²mÛÆñ“Ýh?|ùü|߇®ÇJæ€&Ì¢òtédAß÷ËÌ]á±Ï>йs& àdï)̨¯EÂL>’ɤŸ¼ÏáB?â‚ä’<@hŠ@©´™D×gkf|Ž[(¼Ã.{×üw} ï^  Ðv·6¹øà}ס©|zkQcÏdå]¤7cBéß.ÝÒ™nM¶î"!‰tVÂ2ÝÒ´b Uþé?ß´9p殄™MáÔþÇÿýï¡@=©ÃÏyÎéaŒùƒ•ã'#@¨øRé+³åyå ºTÒ{¹L²ŒÎwįúù/?Úà5ŽPñÓûètM׳G_>öÙ„™¨/XV ¬BííGÑuü8òù<EÓ ©xµ 5:W¸#Õ÷}ø®×÷xÉq±ˆ|äÃX³ºz–­¨««C2•øóºLæ‰ |òö –7<èä~ ­R£IMs‰[–;}ü3ñ™ieõW¿ µ.¾=‡ð¾k <ðž…Ha£ 2«miê+ÆÉ‰4“œ6<&¥š PÚ&a;/"·#]~Q¦K¢SŠ©áöw¿wßÛc!¶hTÕE×÷þ÷ü ªªn†[™—baÈ2ä&x'ÒeE— b-•Y¦° 7,Oòf²é¦+”?Òe‡¡ÜÖ ëÊI6*EÞâEöT¾&ÒŸD^_šHtï0 Jl@ã@Ð7üåßoGwâj$ÐùÏÿC{6È'¾8¹£?ÞÍpº/@ï ØLÚ¯ù£Ê/mÿ ²/GxyWÒÁpAN½ •Hù¶ìèT9é‹\+Ô¿ø‹¿Øø™O}æ–m^ȃ–`ÃÃ#Ø÷Â>ŒŽAQ†QfhŠ Ey¢=3o8À÷ø¢à¨è¹pŠEÌ›7ø¹ÏV½öŽÎ.ÌG]¦¶E7bR‰Ä9Àe¨":¹ßäʯÎWø"ªéë&rZtÿÃXúÁû1tt«”~|èw®#¾.ŸÉ7ð"T_(=‘6åäòË‚P3ÎWJ]Hd_ã mãUb¢i§ª‰V^:ðý´àÇm€±tÆöíÀÑÿù×0´š_ÅÙásŒîp| À©Ê8Ê¢~J3AÊk6ÒŸM*˜€4¢ó=H6€0~ôï?ù›6®·,‹ ¤sP2‚ááìjn†mÛœÄtºU*’… Yì€!ðøÏÃ÷ØŽ]Óð­o|½êõó0¡úõ£¦alH$ÌiG.@…Äȃq€Ì¢Pç+qs1¹Ý*t¿÷毵˯Áðs/ácgcíšzxõ=OÌÓç•;ù¢“dŠ)øøAùh/ý£ê1 `E\ lPù9gaiªpaý*T€€.A:;mü×iÆÄ‚u`ù´ýå—€‚¿OMhÿÇ·sǘ?~ÜÇñ>‡ó“~¢ _y ¥í7ŠÒWJT„­Þ£s=H0!€âç¿øù×­»u]!oÁ² °D¢4N?‰–—Àó}†Ž˜n„æ€jŠ"ª©ðtðKæ€ ¯è¢èzp¶]Äÿø UÓ‡GFFÑ7Ðõu£qÃÜJ%¦— "1ò@PgQ¢ÍS“æ/—ÿ(Ræª5_ÿŒ™óìŸÿØÛ­å]u=GØü®h³-¼ýD(|©©&‚賎úPîàCù˦-Q€É‹L"Y #ªèÚ«6Pt€ø§8 ,‚Y—ÆKñ'p‡:ÍtÝ·}+Ô÷òÇLôºø¥%¾†‰ÆäªäÓa”:4!ôHÈ lfœno?úØŒlý«P€5ÁÛ†Y«äù ,]2yféá‘ôõ  ~F=R‰Ä#‰„ùä4î÷b<¶ó–7 pÚ¯4R›§'“Kœ‰üG‘pWmzòIF,Ì÷àƒ÷.D,ø§ú^Q4Öt#N> ¬›n€ÐS/OyÕ쌻QVÏå ;©ð,jȀIJµ·ÌPTa ÄD;oøÙ/Úñ“6†ºeWãðßþ)N·vŒ%kš¾è[ù#[8Îà²Ù÷ªò_ŠéëH¶l‹ÎYž2¯1‡‡‡ÿŠ1˜y«Ëš‚‘4d¡å@+ººº ë1Qh%ÍoÒ¢*"DIîÀën ¸® §è±mØŽM7âž»ïªzZ!›­G*‘z$•JD€*œ†£asO™@$M-Æ[zoÙ|ß{!†n@ûßþ)ÆZ_KÔÎþ¢››8xþõÍ’ Dۼˢ¡:qŽÎŸ?Î ûö}>ð™™/X¼¨U€Uù47ïÆÀà `‚ èb1 š¦Š¬A"(ÀË$ú¢ëq&P´aÛÞ±ñ6Ü}×Uï¡å@+²Ùz¤S5žJ%ž8ý^´çv>òº€NˆS™”¨Wj‰ÔÇ*|TIz«6=ù$ò§ÜÅoÝÖÈÞÜbÄæV/#§Äޤ®H à0î_º‰Òç(gŒ’½_ñÙ%_+É"k¹¨rVŸ À¶ÍGð‹—Ì«–âðßþ)F[;Æ™™_ôsG<¿ØEà*°ïWíîq)JÅ\:Ê'{‘‘zp ?þøÍ_ýê_|4ŸÏò È[–€ –ÜD»žoF~"#‡aÄ`Ä è†Ž˜ƒ¦k<: 2£ À«¥c°XjVjÛ6æÌ¹Ÿûtõ#‡ÚÚ‘®I!“Î<™J%ªæ ¼¥ FÐh#:_K˜WƒÒ;)¾wã¿ü#¬36V¿-·(f×)rúïÃtÞ@ø»KT?âà+=Û*ŠTqæE…•­ÎKªùJ¬C2&œ‚ýÒQÈûJŒÏæs´ý4þî7]È®¸Gþö¯0qðå½jÜü'Ïš8°â+@Ðo³¼Y™@4Q(n¤N0¢üÕ·¾±ñÑO|êþ|!/z$Hàó ä&rغeÀ0 Ä 1À¡Ç Åtž8$†dY6€€'ú0”ƒŽÃ™@ÁÆì9³ñÙGÿ ê=ð„¡ê2™'ÓéÔ$x‹ÀCYÚ%n.ÅÝVþäûßù½ïÁ÷tÔ?‚=|\ðlîó1òaL_Žø$˜ìä ÀévÙè,^SÆÎò78WáT@ÃwÊUY —œƒ1 ã>çž=†Ÿœ@fÉìÿ£O‚XdbÄþ—o[‡¼.€õÛìå=/a©˜ÿQG¹S°.²­ Ï<õÌÃ7Þ|Ó-\ñ'`å°m ‡Ðܼ„P˜f<â4Ó5èšEãó („÷càþ$ž#šÛí`Û…âë_}¢ê=h=„T*…uµÛ øO×µR®À[ òPš@›«æR%¿yôô‘Çïøû¿ƒÑ8ñ—⡯…S›+¾ã„´Ÿ\i£´¿¤d,ô²ûÓ¸¼3²€jRå3§ý*FÊA‡±HÔ¡B€jpFÐü\6$¯Ïà…Ï| ºšø!cþ¯|Ç9 ¸ ²Ù.ÙH@¥TÌ-ÛºGS…eÆ  ‡^zéñ¦yó––XÀDÛB¾Às±gï^¨šÃ0`tÃ@ÜÐE‘04 %¥?JÀ0Áõ¹SÐu\ØŽ §àÀ²m(ª2e òÎÎ.0õ3êZ ÝØ`ú¨¸·WõÙM^ˆ“uu¶ª™‹c55ËLJŽó†Ç>B¯Øt'Æ·íã¿#œàÚœî‹&FzñµQÅ W*s ?ÇçÍØÙ‚|Ý”ç&mˆKf€üøRÔ@8) AÕ˜Á׺üì‡ÏãåškÁò}Ø÷ÄgJÎû/~Ái|ç0ƒÂfß?—û|#KEÝ€Ê$!™(D¤:Ž,“NÏ)ä-ž2œ·Dž@ ¯t¾‚ƒ‡Ú`Æã0M†ar¿€n@éÂ'À#T!¢¹À º ¹> ¸»ˆ‚m£`ÛP$:p5 IDATŸøøï–Í0-¥££€úúºÃ06˜†1ú€6P[ ¥ÓËÝñÜgkoœwÍ­ßú2wÇï]J·8Bñ›‡û@Pš/Oføñ›JZårÎää«°&›îßfÊÂÙüÒ7A# EE”(õ>-hÍþñ>wÙôoþ¿èþñOƒxzÆ—Ü|¡%ð£€ßûf2€…M”Ï1(sâ]K4 õÿ‰ë¹¦dùBÈ[tvv¢½ý¦ #nÂ4 qáÔcÐ5½ÔX„*"mLLáæÁs=8’ EQ¤ôøãMš‡Žut €õµ-†alHžcêðÅ–×âä¡6WM&—)†q»=~êãwÿô{9Ò‡w]ÛˆúÀ)Ep­PùexOÆ÷åŠDû%%Š;&Lƒsás½íÊ—Gß/•J%Åâ8D áæ€L– àÀÿ÷ävÔ­[ƒ_ÿcï$šò¤oÙÜ— ì_‡ÎíJߨR¥xHú*kâ´¥ Ïz~ßÞ/ø¾ÇsòȗƒÜ9xðp;zNöÀ4㈛FÉ9È™@ º®AÕT¨Š ZV@À—æ€Ã™@Q0Ûâ©Éö³“¦xûqÜ0Œ édòu €)Êc¦ƒ< ´žÆbWèÉÄüñ¡c¿å[ÿü"°Pó© y Ÿ €e¶ 8¢ÐÇá?G̪+gÙu}×gðJKxΫ²¸ò\ÀÇ ?3ºLu\¾¯r©|]iñXÙâE¯Õ àùr ¯ÙUŒ®(nr=î)X€-ž!À=ë¯ÁXûQ\ûù¯¢à®SµØ2ªkM´>N|ífy „q‰V2À™N€72•k€×Þy´÷›ßüæRé‹›LÓDÜŒó‘^,Ë–.EýŒzQNìÀ)ºp‹|V!þÍW!·(ÏÔT zL…ÓK aš¦‰D’wzþÎûïØ±sפûX²h!`pph…c_É +^“x‘å<¦SjÑfjF|Ž50ôáÅwß…†•Ë0ôL;Ö¼g) >êðŠ >c<7Ò­CnW³Ÿ¦²©ÎdkI$„”mŸL…¨gEZ€ø`ŒˆòƘ¨[' ”‚J(<ÐDƒ“¦ù3° íúý…XôáßEçwÿõ÷â©]Ìó†¸ræž7£È2çhæ \ä4ïìßøË½¾ï’'¾öµGø´ëŒWþàQþ7\w¼ôFFG¡…R•€x„çø UP…÷wZ (QAŠBA…÷T_(ů~ýä­î¼}SÙÅ/]²H¦g²Ù­ùü†dbzõo9'À &(Ô9j<±LM¦nÉ yì·Ÿúbý‚ZdjU¸ h¶À-øð÷ìAPRÈ€eœzº =Ʀ ‘sy•¯-Û'òú:ž…hbA 4]…ž 0â\þýç;\}+^üãOÁ)þù?m·2xÇ-ö¯o:¨ðÈ©à¥c0! ÔmÛ¶=¼jÕêuùo#žŸ(õÈ,Xùö¾ðÇFc>Q"ï­|_µÜçÚò®Ü blªI8h•ó•Ç"Ÿ%@@Ú›Œ‘RW[J ¼ÀƒÏ40_…žV-=]=Xüaÿ—?wOªvþV×uú™ONãMÈdá¸)@ÁÍÑx­ÔjŒ€n»í¶ÿ½uëf¬ZµfmÀáó¡ lŽ…×_}û÷öQ¤€(ŠBùš*  ƒ¢H–HA %€¢(  Gå=(¡Ø±s(%¸}ÓÆ²ûÈÖ×Cß@&›ÅÖññ‰ étò’`Ó€8yȤPgPݘE]Aµ|ýÕïß„ã[ŽãŽÕó`[€]ŠVEË…ãðnL&Ï#`PùÉåü‘=pŽÿpòLE˧{ç(Sr‹*¬CŸ÷~(u7‰=*!¬e~ü\‰  ¾çÁ‡ŸÄpÅâ8ø«ç ®¼ +oÅØ‹‡[5õ^–Lòàø›‘ Ìö– M‚¨Ã06lúaÏ©“W¤R™y¼F„+>ÀD ùÊ•+p å%ض …R¨„+>¡Š ŸòÙ‡4@¤ +ÜPTn(Jx¯ %ØñÜN·oº­ì&²Ùz0§úú23³Ù­cããjÒé7<œ )ª¨õªŸ5qzðwVýÑ#È‹jc` V§à ˜çÙU¾eÔ?ãJ_Â/ŒĽ_ü"Ìø¥áû² ~þÓŸ¡Ã[YFÅÂm¤$(p‰0‰ V^¿ÛÆ‚}»öpm¾ä߉íöÁÞ¬,€BdãÓHŽ%€dŸ=ëŠïœìéy<•JÍ ÄŒ)œ ˆÃõ+®CëVX¶ÍsT®ÌªX|ª@ñ)ÊA€ B ð)BT\ñJ@ ÷ ìܵ ”›6ÞVv/ Ùz€è=Õ—i˜™Ý:66¾¡¦æ Óƒ•«çÂÎ1ØŽU„máÝ’òKÅ'"É?ªôÕàÓŸý ø8w÷ɧ?û<ú·ƒ¥ýÉ6Wú((ð}ÂÍßC@ø$@º¶ îxuWcÖë1Úòòo+1½'°‚yp,ÿ&ª”"@@RA™÷ Y€Y2ྂÜÛß~Û?n;ø…€1“7Ža¢e+…š—.[†--°-1§QJL€( …@Uå?BKEBs@B(wµ4}ùs»v”`ÓmëË!‹@ß©¾ Ëbëé±± µ55oX˜“R­^‰3í‘á{oúÒc°†Ùɬ<àŠ(l8ù"lËïñ?"Fý`J;¿rûRS~€_³œÀ“16࣠"L€ž?L] @€«¯¿ÏnÇUyÏúCkcúüºE·/ðýpŠüf†°£qtô—ûÜ1ëì8vbÉÕ×~ëð¡ƒ&X &‹áE&AÀ¤\»ü´< b[|úñ’‚S¾­¨ ŠUø(% Š†€|Z2EНð¨ b×®çaåó“z 46d0ôöžÊÌdÙ­§Om¨­}c‚ÀY NT ”4ÕÔzª*Wúª_üþõèz¦K–ÏF!çÀ¶ŠpòE,žSM‹Œü€´ÔeˆN*üÙØÀ¥$žÇ·Rá£@îø™€/àáÀÄqÄFz»v)2 ¯‡ÝÛ¿‘jjoà{&y0÷fôˆHLDäüÑôa¹xõ ÚÕy¬ûî»ßùß7oÞüGœüs‡ Dˆ!XË®½‡ÛÚaS[(=RÊ»)”À+›’œ‡yhÎiBÈû ÅÖV÷Ü]ÞS ±Odsª·7Ó0[‡‡OßP__Ûõê?És“³&“BM+†>߸mñ}w¡8dÀ`[¯©.Q(Q´ ð<®ÃK-]·Ç)ò¢ 1¶çyp]·l].U‘÷(ï«Ú½ñgP„ãÊý"σ'ÚT -žŠz幘èÄ÷Ü·0±‘jZ¥´Ž€Æ_ï{}•…!ì†Ý8>]šž(Ä`Ë–-G¿ô¥/ýS&A"n"aš0Í8̸‰¸ÁÓƒ3é –-[×å?aÂP®ËŸr¦á@8ªÑW@×4è"QÈ4 ÄÍ8fÉD‰T©D ­­­Ø¶}ǤijlÀ¬¦& ôdÆ'r?éȼð\ä¬ €€Ä©ªÖ¨±XÝÄØ‰–ìÛ8}4‡¹³ê`áõç훜‚-jùCÏ~t´¯f\ê#¿”JPm»œˆÑaˆÐó=0 0ÔdgÂÛwëoÁ±ÿñ B•yDQ_Aà'Lòài‹ýë¹Æ;/ þ BŸ€üÑdàßøÆNàë_ûúG¹!1n€aéÒ¥8zô,‹SyUô ‰@”¨P…ûa UQàù¾0d¤@å¾ÊƒÍÍ{JqÛ­ëÊî§©±¶eapppE6;ckÿÀ†™3^×Ú¨œLò€J %iL«E€%é†HÏ61ÞÚ e~ ¹< yž7]Èà9NY”,ªàS­+·/U©fD×r»(¥|ŸRP×(£DQÑÜ `ÆÚUÚ±ÿ튪î\b2^W_|mï𵓠“š(g¬ ÒðÍo|ãù{î¹gÉM«V¯+EœÄhÎÄ”â`ÀÒÅWãàá6ÛÝ„¥W(âqPPÄ 0¡ÍÏ†Š¢€¨Ül bÚr"¦›onÞ `},X0§÷bpphE}ýŒ­§úû7Ìš9ó gWˆ’RTµ®8>~ËòO¾Ö`PÂi¿U„]°QÌs Ëû{MOÙÏvìRÏóªÚÿrê5á%Å| b"BõMMèêìÄœwÞ‹¾-»nTã™R¤IˆáM @U&@P•` §(g·¬[÷ä³Ï>‡Õ«oZˆ¨"òL?™:|åü¹8~¼[Œà2ÎO„}ÏSU…7xÚ°F)/]§D4åÎD5Â@æ={LW®À¾ý-‚ d·ž:Õ¿aÖ¬×ÎbƒhjŠF¦8Ö»ôÊ;7àôÑ14d3°í"Š…"¯ž² pìP ÷1šÀÔ€Pi\Êàº<åÌÊ^}Í+À]Ï£Œ*ˆ§R`£Ç‘ºn TCQÈÿßÞ›GYrÕwžŸ{olïÅ[r©½¤Ò†„Š’@ ›û2`°Ý·§Ûƒ«=Ç>öœ3ÓÞðÌÀàÝ>´YÚ7tÛ†a ¦ÁØ€,FÂmŒJEiA*íU’j_³2ßþ"âÞ;Üï½ÌÊÒæÒ’"çÄy[äˈxñûÞßòýý~QØ@‰š0&ÁùÃ/h™’'PÎL(ƒ‚%[\»1ùú׿ö³ÿxË-öW]õÚrÄŠ™ˆl ëÖ®E Ù»oŸSh¯:‹Àý”7÷…tî€pAÁIwÀñ[ BHnÛ±)¯»ú5‹ÎçÊ+.cçÎfŸ pZ¨ˆÿQ(Šd]H±9]KcsÂü®yP¡ß0è÷éµû ºmL¡=õÕ)µðMò~”NµJY.°œ+þÎ. „’ˆÐŠ…Æ˜}Ù%œ¼ãÁ7‰€ûÈmµ"Þ#ûö+/È8À¤,åÅ €…‰]§q5âõo|ãg=º¥V¯o±£ˆ”¹Æ8æöí;àÆ‹IA mع U¨±; \È@•#Ë}j±)%·mw–À) påeìØy;ÇŽ¸lí,78tèM›7n|Î@àq, U"BYÏÛÝËÏ}Ç+ÉúP´z #ɰ—ÑïɆ}ƒ!Öh¤¾äÒ#¢ràüD.Á Á(-xüTà¤ò[ãú¢-ÚGŒ”Ø D„•Æýƒó̾æMß~÷Kƒºlh¡+Xó‚ŽLJ9$Å“…4.(XæS'ƒ3þµ\¿nÝõGŽyZ«=b NÌ•kcY»f‰dßý#ÅÒñF.ª@¢l€RÒÇì(à\ᇕº1eÁm;v"‘\}õ«Ï+®¼‚;oç¨wžKx<…´± duØîl;ëê+iï…¨^¥ßw¾¿ëžÒ'ºNÖ§(sÊ÷ÃJ>®°’•Nu&Ÿ/ åjdçG8ÕZKa,"aLeªIväÓ_„¦¿)P:Š”â…X*´a× ”RrÊ©Cƒõë×_wèС÷×-e<O6ÖÐ50»f¤`ÿ~/WñÒ%˜4óBáj B *Y²äx ‘R²ý;@ÀÕ¯YvÜ>rž+8-‘¢"U-LwݺW¼”ã»ÚD [nn[Ö0èö(²œåü~!„õM (%^PÊÎÐZ#¥|ÜÇe-‰÷„­ %ˆABÞY ºn+Q­ ‚º”Ajùш,o ¾Š°©6™,‡“ô6nÜxý‡Þßl6ΆqÝE™!hw ³³3 ötVÀˆè£|, ð®@0vÊ:@¨²VÀ¹ Ê[%ósÇŽÀ2 ðŠ+ؾc'ÇŽ¸lv½x÷3zñ–‘DZT,TTQ”ÂÚ,ì?ÑE(É ?œØ8äÎï—r‘‚B X1Æå½±þõ¸0¨db­DÝbüDi?`tÎK?¿Ø †x€ä˜nk¡qá¹´Ü÷JÄ÷Ùœ$?-ºöKÏTAäó]JÖX 0‹sÐÛ¼yãŸfEñÛ©±Õ²µ &cév{ÌLÏ ‘8xpTôSR~K3?Pãì€Â C@ …’ÂEpÁŽ;A ®~õ«Ä«^q%ÛwìäÄñ¹kîðá.¾èEÿþ™¾p“²,TÄO %ãDE•¹<ý%c-d} †YF6Ì| p@ÙåS”'-´ˆ.^é‹âÔÇÉÕ%3'WwX^¹Ëç“ï-¿Ÿ È‡YA>$)Ã9Mã‹Xx`ÿYRÅU!udµPŒáGJ¼;P¦'',Oš“³þõñ­[·^wï®]¿i1UŸÝ·n‡™iGÔ;xè Wd¿’+9ZÑ…Ïÿ—™WTäÓ‡JHA0Š x‹Ø?ÿÁŽÔ*U^ö²KË«^q%7ýý?\{ÿƒól‚Ài,€HIGJU«Öˆ³6¼êµ®·áò*:ÏÉò]có_JG*ƒ#¦4ïÕ¸Á§¡è²Àxn¼{j庮ÈUùimýøpà3Ʊʴϒh½üÊ? :+ÐENQh‚0"oµi^t™ïl‘ ]+ó”{:¾¥²»ÐÒâ¡) ØýÐCû_²mëu÷ÞsÏû±iZNŸ*ƒÖºý3³SHö=GôQ²t Ôˆ&,µB EðíǕ΅(cefÀ—…ßòOÿóÎ;—F£¾è$Þñö·pÓß žeXö’"¡a;½m"jÓ?2P¹&˵Sþû¹ÏÓjµO9Ÿw¼ýmÌÏÏsâÄܵ÷?øð ÏÆ5\~BHB)%%ιúmä `££ F»A‹Ežc›¿Æ–þ½A[?õÓßô¿oŒñ«âøqòý•*KÏcòõäV‚‚ ø9,ÛYcGŸ­1F£ó£%~ö¥/ÁbC+Š>Vô~¤X×e¸,j1²¡jï"ìÙ³gï¶m/¹.Š¢^Zõ PI©úB¢J5Ó3SlÜ´‰N·K§Û¥×íÑé÷ô{¾˜hÀ`˜‘ç¦dÀJI¨B’(¢ZñÝ…Óšµzz³A½ñø ÐZ˜çäܳË€FX¡JмÛÛd™gÐbÆ ÅhK¡ýjoßôàNXc—ÏíÄg‹f¥Êémñ£ðé®ÇÈB°%Œ÷ÕZ»–ÖÆ¢sCÑíHÐæÖö…¥ƒæÔèGXJŽ@†«,A`óþsö<º{ÿ¥Û¶}$Š‚^¥Z¥Zs+u5MIÓ•j‚50=Õ`ÓÆ t;]ºÝ.ýN—®oB: fC²á,ËGý ¤„aH'T˪ÁZJ­^£^¯Ñ¨×iÔk4 >÷ÿþ´Ú§·NÎÍ]{Ï®û®}&/Úi|È!È#2a­ãæ°Ò­RÚ`´¿Ió™üÖŒ€À­öŒnôr³¬o:y“›%@±Re¬ôâ”s*o´ºsÊ>enº­ÐÚ€µ%Ÿ ¬ìcèaè¬\“é ‹·J0€6Nù;Œ™ƒvÏž={/ݶí#¡ŠziÅ»iJ-­¦5’j‚5–©©)6m(A G¯ë{}ú½¾‚aæKŠÝ¸k©„›9ÄTª iZ£>á ÔëMê:µzÏ}îô pðÐaÚíö »î»ÿÚgêº- Vt1¢‡e Ö_: BôÈWuSV‡]`ýJî ¼é Æ–Å™cy«›`Xl6¯| €S”|±Â—›ð÷Ç×€òú®¡ÆäîZÚ`à H˜ÝöV,V °âGŠô¤¤ä àˆB¥;ÐæüãI|àiÏ£î¿ìò—^Æa¯Z©’Öª¤Õ”jµBZ©’$ VkSSlذv·K·Û¡Ó÷ ÐwÛ`0  ȇ.h‹%%a’D µj…Z͹õzFÃÇujÍ:Ÿûüò ðãï|‡¦µÐzÆ@`Ù,€e`-!–¡Kã}GèÌdd¹pn€_É”@‹ãÓù‚0>ú/&º;z]Ò‡ÆÏVžLæö‘¸òSé[ ûl@Éø/¶,Wµn3Ö¯ôª®A…Õ†¼Ó ¬Ð¸ ÷|å^°gVÊÀ À­ü¥”™pÙ³g÷_ñ²ëîØq×û©TFÙI LM5@‘£G@”y~Fù~é£ÿ2p›P’P„¨XÊg\Ùðˆ,çGGK$_ùÊW¹öçþÝ¢ÿE!ï|ç;¸ñÆ›nØußýlÛzñgÎä…Z„ÁãµÊéœvØfpüAzs»é·ædo!š>S*º²ãm.ÐŽ% |=ÑLk_éÍAL9ó ÆA™Õ €X”æ7 DuV5¡&ÜÀ”µªL¯ÚÅïUÉDQÙVì”]üc`÷ƒ»÷_vùË®¿ãŽ;Þ_­RYze…l8dªÑ TŠ#GyµçúGäéʉ•PÒ=Š ôʯ<xð´Úm>óÙÏsíϽwÑFá) 0¿mëÅ_=S×jYÂ5BD€q­ý„K…DZ°ùúÈ=èü[ä²S4.$jœMXYÆ î­jÆ+9v´äI%=(¸•²´ V¢8 Tp§È0^ÝËÏ?ŸàëÓ©k ÂH¬€¬i;H¡FñJT^¹ÌÉgZ–€@™sN™7;°gÏîý—_~Ùõ;ï¸ã×+ÕJ xº°õåĆl˜“ÖSÎŽ#öí?àõÿ{x+ ¤K7ZÌuÂÍH”Y&?8ÎFi”<1|à†{vÝ÷è%Û¶ž‘&£ËDD)+ óñM§(ËQßt`þŠ…ÝAAÙ8‡ =›¨º– ¶q¤äÒe¸Y.u¨ð+xE3Æ kGåª_vƒBiþ+µ±3$kïÇôc‡É#Amæ‚™óιÒ—˜E?â<€'eа¬ ,e²;k`Ïž=û¯¼üŠëwî¸ý7H’×§y"8Ý%Ë3Â(æì³ÎæÀ~W@´œK ¼Kà(Â~ Iù™ƒÂ×θC’ÞÊî´[§—^º»wíšn¾g×}o: °¼ kBÊÔ]Ѓtm«…ò+…N>tñ†d©V®ËôlŠËxèˆØ&]‚& wïÞ½ÿª«®øèöïßö«Tªµ¥ß×6Pèœ( 9{ó&ö88"ê&Z…)?šL©±¢”$MSÿ;ƒ7FŸwZ|ãÆ›x×;·ßö’‹xx÷ž© Öß|Ï®û.}º×æ4.@„¡¬Š+mÓkÕEÐDBÅ#TŒŒ›˜AÛ¹*'7¾ÄÝÐD ”{°¥ï* kc².ÃÞQâiL+žHëä^LÖG=L‘ÁpÁÙŽÂxÅ.z’2[e½{*|ÄOjÐdàzˆ©Bd ÜeŽc¤ r€rÕx’b"°¸f`Rš>¸{ï˯zõǶÿó?ýzR©VÌÄ~K§Ý£Ð9ArÖæM;q‚n»}Ê$3 IDAT—@PI«‹} õ´êt4GÚY˜ŸŸ\ØóÈž)Ö­ÿë»wÝû¦K·½äiõX¾i‘.̬âdÎÚjkAª%#D#ƒTœâÊ@zßTŒ Qúœ–Õo¥Ë–õe4{ÔõieÊðøÃäíý˜þd- Qà²QÚ_ ÒÀ¨§…+„ráß²¸À¨Š2B¨©b*Ï¦è ¦Q¢n…l TãÙ?Ñ,ž#P’…Ê9Ë‘…4`v?øÐþ×¼æu,¬èV+‰cô¥j•”ZZ%P….ÂÍ›6RhM§Ýq|Ïìt»tz]zž4´œ¤Õ*µFz£I³ÑtŒÁF“F³Áüü<_s€E²í%E1G»¬×ëß|÷®{Ÿ–ù|*0ÖBa­)P²»Çͨ§øa… ˆQ²J7üªíᢌ (Þ]X4Þ ¾N ¼ë­öJ°rÀÅ?ìø\G˜@Íí„fxå>ÂO¢‚VPa‚bT1¿{/"92¶B¦™®úO]ÊÕ§´™Ç‚Gpôƒ>¸ÿÕ¯½úãÃÁàxµ“ÖêÔj)µÔm%,›6m¤Ðv›v§M»ÝuEÝÝ~—~·Ç Ë–=¨j’xšpýhÞþ¶·E!Ç¿l0ܼëÞûŸ2, Œ5ZçA%}$ïêëA©¡D ¢ׯ+¾ '"Ôþ5 ‚й*p+ ï·îÈÖ‚-b…J©Ü>êïΩp+>“à = àcL\¿P bdPq[XA)ÕSdmˆ’‚HKBVVà)Ч — PÒ†ËÕ¿Sþ’1˜Åž‡îß¿eË–?œ;qro5‰Ië5j#êpŠR+Úò „¤ÝîÒî¶EÐnÓY=²‰þ‘“’$õfFs1Ô¼%àÆ-–·¿í-DqȱcÇ.ët»O¹xè4µFƒÉŒÖ=ªýGvÝE˜@eª "wcª*2H ª:7Ïø!ð+¿pÊ/ÔD0òé+ïëK T¥i¼‚{[H"÷ oAZ÷Üúó’xð+›#(w-‚ç*87JB £V*"+ÄMèì}ˆ бV䥱ъNœ<—2%´q Ðbl,à|¸èoÝzñGçæNî«&ÒzmT?POSälX¿¥íVÛYºöÈ-ÈOSúžDÍzƒF³Î”)o üðî]Üyש ð¶·¼™<ל81wÍö;Ÿ, ÝÖ¶ÆÚ±y[DÑî£>ŠÌ6Q‚+È¨Š «ˆdŠEÊ/¼;PZ(ÿ~4 „‚h¼êá]ˆ-KÍýÒ"*=½V!.þ*<>–âÛÙ)*¬ T¥„i° GîÚŽÕ>kLD†\É>ÓóJr\)q‡±;PÆJÈ€ÎÖ­_77wb_DÔÓåA@낵k×G íIè: hwé¶»ž{ªDQH³Ñ ÞlŒ@ Y«Ó¨7¸ûžåAà_ýÄ;i·[œœ›¿vÇÎÛŸ4œ¶£ŒÀ ¬Ö]›çm›Wh€Ù-UdP!‚ ânÎ¤é¾Æª±ò 5a¨±[@ ¨ˆ‘É/œÙ»¢Àçü°ùmØ•JïW~Uf=„Sü‰k§ÂV â *¬RY· ©`~Ï^dÞc°m¬ôŽÿéª ð/”‰¦"e?²©H\ÔTèoݺõ#­ÖüÞ(ZD@žh3=3C³Þ ]‚@§íÝ6í®s NWÿ…!͆ëÐô@³á ‰î¾çnö8xÊßü›Ÿþ): ÌͼvûŽ¿òdÎÿ´`,C‹é“·ÃZm÷Þí?¤q6Q ÖF&jX]¢ü劇¿ñK0ÀÝôÊ›üàÙ…‘çÈÇ9š #…g¼Ê‹È¿§&€A÷Á_ë-¡@E¨¸†Œê¨¨Š ê›Ï¢w°laÛÆØ®•?Z-ÁŸI™È w*·ã~9.vP‚À¾p)ÔKÈÑ:§R­Ro6èô{´´Úc ètÚ§%À• ÐX &ßùÎ-ô–É*ü›Ÿz‡¡ÕZøØö;¯}¢s<•Ë­±}£M+Lëwí»õN¦ÎW Â*2ª:ˆkPmŒÍ}1éã–&¿ñ«\°XNY)WpPE$ž!éÏG)på9Ë% P¾p\ ¡¿®aŠŒj„QÚyMNÜs/2‰w[kÛ`:®V{UΔ”ÃGp¦þÅ1²ÁÈÎR0@oëÖ­iÏÏ=1$UÖLÏÐéwòwÆqÒ:8ŒAÀõ:õº³¾ô¥¯Ðëzüë÷\ÃáÇé´Û7ìØyû5wÞ§€Þ‰?1ÆÚžÖy;ª7·?¶ýN”‚µn@Å‚°JÖ £Uõ _’ª&•ßÿä„r—.PîZŽ\€•Nm®Liy«HM^ óÆ`i2N ãaœD)QcŠê:8z÷ ’øNkõ‚Ŭ´Ë‡’Wåi‹o-6,Ý6ãÀàcÂJoë¶m×=pÿýw<©X»f-ÃAF«Ý¦ÕZ Ýî°ÐnÓnµ—íPJ†.0X¯Ó,]ÿøW_þò)û§i•÷¼ûšQ/ïýó­§M>®ÑmÑ}S] [ÞÒGï²æÂ¥¨¤†LRT\#®­›ý“9cÇY3é—7™ˆ&þ~…ŠðiOpç'—Ä4ÄRP”cKÀâþ6ˆ ¢**i “*Niž„Û·£ªÕïkcZÖÒíúÄjà%IcÈ8ÐÁ¥;Àqœ%`Þ[Þò¦ÿ{ûŽ[¿wJL` `afv†"/N¶ã œN¢(¤ÙlP¹MêÍzƒ/~i¨V¹òŠË9rôÈT»Ý>m<àñµÎÚÌê¢SdƒV\kì|äûw1{>„qÝ@”¢’:ae â‹ÌxËÄMïk.FæïDD|ÑJ¸‚A`dÕŒþ|cN]ù%¾•,cîƒ@D)*i:PÜ Œ4Ïß̾[â¶Õú„ÑE LïÔX•3%]…Ê¢ÊÔ`8ÁDmÁO]óîÏܶcû‚€Ñ†™™i0,V›V{á A Ñt݄Ƥ¡:Að…/ž _übÚí.s'çÿÃé¾ó ,rmu_gÙ|\Ÿúî¿rq Ö¾xaT'ŒëQƒ ©56z3¶,€÷Êoü¿¹ž3é /RŽ,£ èĤªÒ½1“.Áä$«$A\#Œ„I“0J‰Ó4Î…·nG%•[MžÏ[kÚÖšÕà3,ÁúŒA`žqëñò·°ï¾æšO@ ¾Ôò\ÓhÖI¢˜ÖÂh=>$QD­Ñt„¡šë+Ø¨× CÅW¿öSö¿ìŠË8zìèÓsú‡?a¬1SäóÖ˜}Ýcsô¾ŒÙ AµŽJIŠŠêÄõ.÷oKeöþ=L¸þùˆ#ÀX!&-•(‹Vþ`|ÎågAì_›ñ9Û$x·ÊmuTRgfë‹ 8xÛNÂZúÍBç'-¦Ó?ðñ̘ZQ²”6\º¥òwp1¡ß—w_sÍ Ë‚@:܃@G¤i•v»K«µ@k¡Å‚· /&PM"µõfs”¨5äYή{ï_´ï‹/¼Ã‡œö»žÐæ¶è®1Å\Q ŽEÕÆö|æól| $õi‚Ä@”4 “&As£_å¥Ë‹›rµ+o|Å85‹9°²`¹•¿>ßö·´zŒ›ÿ0U¥I”L%5¤AT©³ö’ù‡»A$GM6sºs|BèøøÀè¢UdÙÑdfökýã.Šl¹r†0®&uT¥NÕ¨LŸ *ñn@i ”….~•/[ßNúð8(¶"e™•pÉ>¶´$„‰‹«T¨dŠ R£±å*MØó[ˆê¯Sœ0¶hYlÿtG°*g^–€@9¨l9ÞÁ)Ÿ1X@üûkß÷Åßûß½!Tʵ¯¥ÔêÊÚ\n¬¼ÔÒ”b˜±ÐjÑZpÛB«E«Õ>-Y(M«`F[0XL¦ûçïß:Ÿ$ɯžîüž”Óm¬îšbxRzGePÛûïlßò²Ÿ~íœ&vÈ+¢A] š(NÆ:ª« peÀlÁ¥–ÀÊfárùçe ïö¸¢§ÂeCÊ^‹6V¦‰*Î’ŠªM¢¤É†—ŸÏÑ]G8ñÐ>ª³³»ŠAqÂZÛìýèªùÿ,Ë „˜ì6<Ùk°Ü§ Tñ©O}ò{i?ô¡þ|*k‹ ÜN·K‘Oü”aH¥Z!Ë Z-߇°la©×k‹Š”’ÖS´5XcýŒÃ19ôλîæÖí;Þý§ÿãÓö xR`­íê¢XȇƒcÕ5k¿üƒ¿üƯ¾òç^Å9/_Ãýß™'ÊšèaŸ Nof¡»Eî;ãc„cü å€A.+Uʘ‡-ƒœeÀÓŽ?7Þ´xK €8%¨6ÝV©T4Î=‡Æf¸û‹·PiÎ|ÍäúˆÕú8ØÎéþýª­Õu&—Ði{ðÅ¡ˆÂkì(h¬»§ †z½N¨[ɨ§©k!ïGÌu»=NÌäî{îþý÷ÿÚ¸åñNæI-¹ƒ}+Œ)Z:ž0yöHž~ø·÷±ùr¨LM%SD•&Q¥AXmRY³Å_*„Þ%À+{ÙýCø‡%–ÀJáù“æ¾-Íÿ ·gT U·âW¦ˆªÓDÕ&qÒ`ó•çÑ= nÛL’ïè";b­™ïï¹~•ý÷Ë„5 q.Ár)œ[`ýÉO~ò{ðû¿ûé(}S‘”ZêLö@…º È D â(¤ÛíÓj·}`°Mka,;•ÿ¥”¤VMýô¡”‡ÞÍ7ÞøÍ÷ýì{?ñDçó¤5ÎbzZç'òAÿpuzæ+ÿô_¾€-àœ+g «M‚ÊAuŠ :íˆAµiïëâÓ‚¾g )Me_@´$Gþ øoOöž7ò ð9ØQßRº<¯ò2—=(Ý9«ÊQu– Òð×oš©s·P; ný“R™Zû5 jmŽYLë¹8·U9U&ÆŒ» •ÙÉáï~ò“Ÿüþ{ÞsÍuºÐ½Ò´F½ž„ çyÖš0 .°Ðb¡Õa¡Ýb08µ©H…TR7ì´Ýi?öË¿ô‹„£1?®<éÄûàÑö*¼AçÃ#&/ÎÁÛ>÷ÍWýÏoæÐ}³YÙ!R›½€NösÊ`—.`ËÒ×2F0fÉýùoãÏÿêŒhXžU'F¦5¯Çb5ê6¼äƒI‘§>]n:ñâ÷$£^¦´þ`ÜÙWÚDθÿŸa\¯¿Òübo1MWgˆ«uâj³ß°…÷Îqü‘CÔÖžusÖ^8bm~ÒB?¾à7Ê“vã‹pê¶*φXÆB%¾¼ÓÊöO äöíÛxýU¯úÈÿþö÷×kiUà‚Ýn—ÌOÛžšN»5f´i“’V«‹öM’„½>¶ïõ¯½úXûÄtñ§ds[kŠ"?– úû«Ó3_ºãËÿ@o^ôÆquš¨:EXm¥Ó$õ5$³gûË"½%PúÇjb…\ÆÕxKA„€ÓM2þµÂ!g4ooì7*S3_}ìŽG¯Ú}Ë~ùâ7ŸÅÉýÓc ƒÑ¶0Ô¬`~8„AÇ)„õ×KØå³eÑPàkÒÄ_ºâ ƒ–S](ãÉÀìRce^ô~d—tŒµÎ{ãi>å´#är€.Üy @h׉ª5IjÓ„iƒ¸:KœN‘¤uÎë…d¸ÿ›ÿHRk~6ë÷÷]µÖ´(Wã€éÄóUy®¥¼ÁJ®ÀRå›ü¡šÝɶm¿wëm·½ãú g/]‰ƒ!û/2£G† ³!´q®€5<òØÞ}—½ô’߯)ÿÖ>ùlÑS»g$3VÏÙð`Þï>ÚÜxÞ'þæ÷þià’w5HjSĵiâÔmQÚ¤¹ñˆ½¿2ŽY‚ÁK ìc8eÕ7f¼âWû ‹Àâgë9–Â0$Câ8&ò[ÇaˆRÒ[åv4¦»tùÇßë¬aÖŽÁ–?+hɉã/3Æûüžï¯Òqm–(q×§î®ÕæW½„Æzøö^‡ŒÓ‹"¿[Ù~kÍñÅıºú?¥ôOËà`i ôq®ÀIœ5PZè¾ú•¯¼þȱ£ûªiÕYõ:µ4%I´Öž:ì gh­fCZ-¼ÿþRù÷[kOÏû]FžVõÍà·*Û>x$t+*ŠêqcãÍ_üµ?yÓûþëÿÊW¯áÁïæº@ûA—¨o¸öÁ‡@kðÊU¦ÆLé[•%µÂ{ ~•õÊ^ÎØš\ñËÑÜRJ¤ …”ò3R&‡s–PhÑzÑ÷•gG–Žl!pÇm}Ïkݱ¹?¿qA@‘Ö‰êM޵iâ´I’6™=›¯Œ¹ã ·Ð;Ù;Wj7 G­Ñ‡-ºe…ÿ§åqP>]]ýŸ§2Iê1†É÷ 0Ó¿Þ+_þòëoýÁÎߨ¸nýÙ£o‘Ž+0è Èñe;þãv»Íí·ßñ½}ðÿüS\yòcÀ©}ž@žvùÖú¤(²Ê°ß«VÓ_>¾÷È%ÿø©ï®}í/¼öñ¼Ç›Þå*Ä"èztÙ-WWK—Ç/ýŒ¢ÿ”þÿ2®€q  ”BJEþ¹SÜòQ …Á <‰Bk”­õ¢Õ?ð¹oì8ܼ·Å¦¿kI}¶z BŒ*EZ%©ÏÔê$ÕI:Eܘ¦¹eç½mû°Ÿ»¾zõµ›>:ì´w£XìœO%,ºî«j¿b¤tß¼c±ŒA ûê—_ù{ŸÿË/\ûº×½öj!Ç €~o@nÇnÀÁÃGù»¯ýo¿ø…ÏgU<ì~²~ÿ¤÷™/gX­¹ïñÁÈÕ¼ÿóZ²{?|º|Ú $@ìk8n@Ý?oúÏøð‡?ü¯~ægþ§Ÿì3ú¾{ðžGå–›oÙû™¿ø¯Ü…‹+<<öt•ÎÄ/ý­µAŸUÓ­B©w º‡ú}Ÿø’fÈíÓ£{ü$ƒîN–;âJúé¬;ÿ€.†YS¶ÖÆÿ¤òŸ‰_iUžC)‹‡ìÄf–¼.÷18(Ëþ ãÙ'ÀNå<-9#àf\š¾ÕúH‘=!¢4Eä‚~ùwÞý³û —_rç×Örr_H¦d QDÑAL”ÄtN%kÍyrƒ€”Îߢ0t„Da@ƨP¬r ¤DÊ`‘0 VÍÿÀHçû/€¢ð|€Ñ„_F¾~fŒËf2ªÕêÄ•:a¥J\I *u¢´NT­S©òâ·o&LáoëdCµ#®Ô>uȳác¦([k¼òÑ|5è÷‚’É:Éç“@ p ÐÆY D,€£¸•ÿgHùá €cÔYÀôMÁÑB }A$R™4ÖÛÏýú½ç½×}—ÿTÀßaÿBEÈ M„È $B‚0aؘ¦}ü¦ïÉLÒù÷å6€0$ŠQ°B5ŽÈ`€Qäß@ˆÖ¥óH!]VŽ9 ¥Pn9†¸^'©ÔQI•¨Zu-½*5‚Š[ý›g5¸è³ä]øÚïþ'†}vÄQò鬻ð@>JK P!AèÜ <È1Xk±Æb‹Ñ“¾¿D邼(VŒBO2ÎbRWëˆ0ª(NQ•*Q’UR‚$%LS6^¶‘-¯˜ß›ñÕ?¸Ž8þ»0 þvÐë…(2ò~ i‚0$ôÊ.&…!aKb¡sÆ™çV¹|LÊóÒôWh eæ@xê­¯9THRk`ƒƒÀb¤t3“”¨Ru~³Êy¯_Ïì9pç7îâÖ/}•´±îKÖšoû­‡Ì0Ôèüˆ5º¿È¼qFÞUyK©à“Ý…Êžƒe‹ì²Â°¤Ÿñ»ãÌd.ý%sÏx@€R†k‚0ÞVª[â´~No°pmm*Øö“¿ú‹¬;/àÑ;á‘ÛºÝ>Ù CÞÃÂfH B VPd] „QD…ÄQ쬀0 £Q`P!RÉSÒÀ©é¿‰¼VEF‘äYN¡µû¥”rJoA£0R`Dˆ D!AœV*̼h ç^ ,|ëÏþŠƒííUÓéOêaÿîbØß] ‡ûD¡Xcúå | QøTçè'Y]ýW„ ïúƒÓ~vï®]|ë»ßæ߸‰¸é¦å|–LÁ2èWò̺µëL†úàÁ‹*Ú8èII¹IDATS Þúæ·ò®w¾‹7¾ñœÁùOûØÏLW 3~-FAcô‘¼쀮A·ÂJõÃ>oø‹ßø£÷^ýSoã ﻊu¤ÜÿO)' â Á |€´’e4ƒ%@°«5JHqúX€‹ H) G¤ ñ©–«¿µÖåþƒ€,/Ð…FÊ (LlR¢­u›#„›eFD˜ "œ©pÞÕ347£;óí?ÿ qeê{µúìßf½î#Ű¿WçÙAkôqì„Ï/„7œ–ñªò¿ä%Û¶Qª°¦¾†µµÜøÍ¿g~îèä.“î€w8±S33ö豣ˮΡ PB¡üø/‘3æŒ@`dà gX“Yñ¢m_wµ.æÃ¸2?»vË];nÚþK÷üóçÿø/½—ËßÕ`î@“Ý·Õéh#u†´RçH Æo%-J””„J`±Hã^K! ”BÊq –·,Ö7S´$Ƹ¦ŠÒ¢s‹Æ A[‹1mA#ÜêoF*2‡®œaÍЃ¿þýÏpìÐ1ÝlnþOyžÝ;ìuöêlpPÙcôÖf£š¾¥þþÒ º*/9wóùTßS«W˜žipËwÿ]»î_ºÛ$Øù¹¹Ó~ߦ Ù|Ö&ÖÎÎ’¦é¿èØÎˆ \úyG{ƒFà)½Rb¤ÄbJDBÊ)„k¢(>+ˆ«[D]¹°pø—Îé‹ù±_|é8ü0{²#]b $e ”Õ^ù-J‚B‰ $¡P¨@¢Fl@€±?/¤D`]+åI7À´6åscÝk„{ŽÀ"Ð6`` 4_\cÍ9®è7îàö›¾I£±þëJEß·½}:ÐÅðˆ)ò9›Û¶À!‰(»!ùæ Ò”4âÒ«°‚äñ\€ç»¬/ÒÖ®01ó¼­Ýca —Žv æ´%kĬ½*SÐ: ·}ý&ºó~â¸òƒXÆß2yñp‘öÙðˆµú˜1nŒ—*©ÂÚÿcí^ŒHEb , ®ÊŠUxéýê.|G¯1ØÜ,í;úD )ƒ¦ ¢™ JÖ©¤º>Lª›2ò7÷³Ö›£H¦/û›ØöÊm4ÖB·s‡!?Qϰ&–̦0]uŠJ×ML)ˆ§ü¡<Õ0Ö5é-¼Ò:8Ü‚CC+d±`ú,Hk0ÂîÛaç·o¦uì$Q”~¿¤_ÕEv´ÈGt6aM>‡¥c±!Pe?@íã;Úz“ßb±° +NVà¥YÆÁ¤`F€·Ü†uö=°›ý÷삤z4Uõ¿š{u>²‡£‡`z2ˆï EtGh‚;‹l8§ólÎÙ S'À,£;Öšž5F—ÿIÉëºÒ[£@qjpV¶¬À“ ¤ÕYôÈÿ5Þ°Æ Tàºí †)2¬ %R…M©Â† ‚† ‚† ÂzN~Iaó‹ ƒÎ7ÒÏHÎÝ@"c’Z…õl‚ ìä •HÇÌÑ=~‘JæïÜõTÐB††2z0–ÕÛt1l›lØÒE±`ò¼M‘/]´ÐE›ÂtôÁQƒ­,€öà@°¬ &]€UXñ²’à SO/bâ‰-Í_çÜ FÍ/­Ï#Ý·†>Ö.X+ctB‘UE®*B©šT*U¸K)•²ž ˆm]&̉´'³óÚ ƒ³NkGJJ¥ñZkk´)LVäh;ÍE»âéÍ]¤í#Ȭ5“ÝžžïStE^tl¡û˜¢G¡û;Àh?öWSžKûvBð_•Uyþɳc%kˆ²v` Œ¬‡q&ÌæX“£m)¥5&´VÇ™h™EH™¸†‚"ÂÊDU„j—ˆ‚Š•&6ÂéèIÖb Ö&§0™ÉŠ^?öÀô¶"G˜m“aôÀj3ĘÜ5tËÑ&<ÙiBÿË¢([žëªò¯ÊóXžX¬véêYVÄ"<½x‚.'0X=ÄÚ!Ú´°R`µÂJ×rÉ Dl +òÈ ´TrüEÚZ £)tAn2´`Íi  qþ¼ÍöLv*£“YªèbUíWeEÈsÀe÷ÁR~¼_eÇ@P®¶cóD¦ÀØ¡«§0` QÖ¸ªb¢PÁâj-ÆE>&1Ù’Œ±¢­•ÑÒî|™~UóWeÉÿ8>^eØžÅIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/actions/wizard.png000066400000000000000000000136111217176075400240770ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞPIDATxœå{i]ÇuÞ×Û½}ï{÷Í>Ì`È`H`°‰¤Z”en’ W±lgqI*—(åJÅN .W)Ñâ$´è”e›Ž%ÿPÙŽ¼Ð²Š q‘#“@ÁD ŠˆmË,Ìò–»ö’÷Þ÷Þ€0§â35u—yÓÝçëîs¾sN?b­Å?f¡ÿÐø‡–ôðw¢‘?úÚ×AHç¹ÜUƘü°ÖZc`mù·üÙ˜ò½i?[c`Êg·Ó [xú©§Ñl6A ¬Åé³g®8¾C/vÜM ½÷د¿vçwüÁÐÐ}ÇøUž?txœ1ú/¤”¿P©xµ †ÞÞ@}ö³ŸýîÃ?|x‡ „x„ PàˆÄ„@d­M߉~V#7Ýp#ùì¯üû{î¾çÎ_èûéj¥Rë©p\§NÂÔÔÔ£>øà‰òó×À×þðûÈG!?a­½Ù3n­°Æ¸„€"Y"À<€iBÈ)BèiÀ'„L8 ùv.½Øp_ÿÈÐÈÈ}wüžOmØ0ö¡F£Žm[Ï?háÐ ‡ž¬×ë_ßý¹Ïíïþÿkà~ÿÁ‚Ïh­?‘¥ÙXš¥È² J)h­‹}ÜÙZ„¥t„Rz#c ”2pÆ@c4¥”Î8Eù%ôˆ}…rç\Ñ?c¤)8cºóc?ù©ÿ¸{÷}»n¹yäâÂþâ¯þÃCX¸¸ðÒ#>òpÿÀ7øÊoM¿U;d5<àwç«?a­ý|–eãI#M;ŠçÊw°Ö¶‡os Û,J((£ ”1Î9ç`<¿§”5(¥'ðŠ±æ‡Æ˜6G\£=úzúû?ùÁÛnûÌwÝuÇÐÈ0Ž9‚§Ÿ~ ‡ž¾Þl4¿óOÿÙ½R­û­‡þ⊠^€ÿþ•z %¿•¦é¿ ÃÄqŒ4M¡”†V ê-Ï›+AÈŸs/ðæ)%%90”‚1΄ààB@p!c3•½>77·rrŠ~ø¶Û~öÖ~`Cœ$xî¹}xöÙgí‰7ŽÑZ?à!kíé«ÎêÕøÊý÷ï2ÆþY†ÛÂV iš/÷LePªTÜÂZÓV]3L!$×¹»*]€ÂÝhcr—g ¬±0Ö Œ‚,KB06¶[·M`Íè(N>…gŸ}/<ÿ<æfçð=ÿÁVØj¬Vñ+ð_ó¿Ü®µz¤Ùl„aØV^eŬkûtk@@òÙ„Ñ\©ö¶ÈïË>.í+ߤà”X dIŠF£Çq°mûvl˜€!ÀáÃ/bÿsßÇñão ÙÈm'¥ÔŒ®mܼk×ÙñMã‡T¦þNký÷i’ýãoþéU÷÷›øÍ/}éæ,˾×h4û¢(Bš$H³ Y–AkÕYîÆÂq¸R"S ¹mHV(Ü-—¾kƒ’[ £‘$ (¡Ø°~Þÿþ÷cdt-fff°ÿ÷ñòK/cqaFÖZαfÍŒŽa ¿?Ÿ8Ž ÁyJ=b¿1Ú<©”úû¿úö_««ðŸ?ÿŸkÍÆÖ0 ‘$ ²4Cš¥Ð*ŸÕrØ•JÊh,×—‘¥@²¢qÛe Ë{k-Hû9+À *UÜ´e &¶mƒ~ôÚ«8pàÎLMÆ‘"K3h­144„þ~$Q ¥@PØÎrûáº\×…#PJ^5Æ~[+õç?úȉî1®pƒÆèχ­ÖÖ°¢4xi–¶­½5ù ýjKeÔëõö2¾tV Èeg݃4MA ÁØè:ìØ¹ëÖ¯ÇâÒ"öìÝ‹W¼‚¥¥%HWbppRJ,..B)AéÀÀ¢Z °¼´œScJA:Þ…1pÁá:\)'¤+'(¥Ÿû™{ï}H+óßê‰É+à7vÿúæLe/×ëu/Š¢\ù4E–)h¥ M¾´¥ôÆ–ëË ôͱTé Y €µ6R)T«n¼ñ&lÝ6ÏópêÔ)¼øâ‹˜:}išBz¾ïƒsÞþ¿f£ ¥„‚ZkPJ148„¥Å%4õöDPJÁhç‚sHéÂ÷+`ŒÁZ;£µú×O~÷»Ï´W€ÖúWÃVè%qÒV>wy Ziä/Nc,,.¼¥’ݳ\Þce8cÃöíÛ±nãF´Z-¼ôÒKxýµ×0?ÖZ¸®‹žÞB ”Ê—7¥T;°¢”"MÓ60f„ „PØb…Y–Û Ë´Öœ£Ñj®™œ:ó%9¿ö~µßhýóQ#IdY†4Í –×±ú„DInì.]ö—®€rе †‰-Ø21Jµ‚sçÏá»O?…©Ó“h4s¯å8„°Ö¶•ënOk S¸[c â8!žç!c´šÍö–#„€Q–s Î „€ï{ðý ¬1˜:{Ó33aš¤Ô¶Fë¥i:¨ÒÂÕe Ju3=“ûyƒöÌcV³rpJ)αnl=¶íØuÖ#Žcœ8y'Ž¿¹Ù9„a@Ji[©Ë­¤Ò³Xk‘e„pVi´Â  Å9/þîÀ÷=xž¥4æææ0{aQ=NùâÅÅ…ÛXØ–Æ®ü-×ZÃhS ˆX@:.ê­&t„)ÈLooví|?&¶oC¥ZÅìì öÿû8wæ E€sB²,{K¥»iixcp Å¥0ÅöàB€1šSjáÀ“¹ýp„@Ç8wî<..\Ìâ$y’ò{ó ÿ®»Oõåå ”1h£¡6…ÒÅUÉŠÒ9\@rÍ4…àýýý¸õÖ`üÇÞ‡$Ipzò4¦NžÂìÜ,–—Å!m£–eÙ›–y{ûä7oRÚŒR”;[§ Í®ëÂ÷}H)aÁr½ŽÉ‹óhÔë3JéoŠ?½0?o!Ξ=GÇÇÇs´Kþ^<+“/ÁL)$I×q°cÇÜqç]ضc;¬1øÎÓOâà`æü4æ.Ìaaa!wu”‚R û¦/¥t¥Œ2žûrÇqàœ³œ_tùzÁGÀó}ø~”„aˆóçÏaqqÉFqü€oRB½0wá-;í`©¾|Z Ê(Ú\¦¼ZÀƒ0ŒÐ?0€»îº?yÇØµk'†G†áI‰3gÏbÿ¾}˜šœBØjAk )]ôµ6s4ÆtÈ! E”»¬":,ž;Ÿë"8\ÀÒ“ªU¸®Dš¦˜»p‹‹ hµÂ“J©G(%MÏÎ<%¥ßÀÂÅ…§g¦g~cddi’BQMó *'¿ôo~ÿÄOall ==50ư¸¸„g¾÷ ¾þõ¯áÕWŽÀ“µ €ë¸à‚9»Å΢›w¿'!Œ‘!ç‚ÓÕ @µR,..âìÙh4ž—Ì^¸ðË”ÿ5ñbkµŠ¯À¾ã'ŽOzÞÝÕ ÚÞYšalÝ:üü¿üW„ÇÞ8ާŸz O|ç;øÑ«G`­ÅÈðp›²¶CcSjwI8líŠY.•Îs¢½¯ƒZ€žZ Œs4ê L™ÂÂâüJë6nÄðÈH|núüãóó×®<ÐÅ7mܸ‰3öÌæn@EÃqœ°ø…O}›6mÂSO>‰½{÷`fzœ3xžW°+¡q[Ë÷Ewyb„’ü]8RJA€Þž^8Žƒf³‰™ÙY,..„ ··A±úâ$A–¦ ÷íÛ»cêôä ŽÍÀø†ÿÄZóçCƒC[7ßóóÔS’ Œò°¸ÙlB8Œ²öÞîÄòdH'&éº<_ïw!r¥«Õ*jµÂq¶BœŸžÆòò2×ÁÐð0‡†à8.’4AØj!Тܠ‚¡Á¡ðoŸùÞ¶3“S§Þ6žÖú×c¿ÕÑZ­† @J .8c­4”V®P&HŒYáÊ:ÙÁyB».\)!„€ÖõFççQo4!¥Ä¦M›°q|~ÅGœÄhÖ›h¶šH’ưbÅ8ÂpDëÛý­mg¦Îœ~Gè±aÐZ{·1æc„ÐPJ6+¥{jå¾d¹2Žpr*ëä~™1–/oRZt‚rU¨L!IDa¾½’4c }ýýظq#Æ7mBÿÀ Õl¡Þ¨£Õ ‘e)¡p¥›!ÎÛ¥RY6==½ã¿ñ×ßQ.•ucckwïþõ÷8ðƒ_:|øðgE!Ò4ƒ1(BR’§Ã(g,÷ïŒÁq]Hé¡·§†Á¡!¬ÅÚµkÑ×××u‘eÂ0D…H’´‹à‚Ã÷+p]™ç²Q!IóDÍ^}U;zô惼|=¬:-~öܹiÓ¿ýÛÉ­ÿûÑG±nýz|ðÃB__?(£‰á`œCº.<ßC¥Rà®t!„×uÀ%9ÿOâ¤0´y€•e¬A;ä­V«ðý NbDaN¥µ1˜»0‡}{ö`ÿþý,Ë2ÿz”¿&JiµZkâ(ÂÞ½{qìèQìØ¹ÛwîÄÆÑSë”><Ï…ï{Ž“ÛÛ©÷%qÒv“Zé.—1ŽÞ¾ ÑÛÛ R„¾eô¶BLMžÆƒqøÅ0áŒ1 ”Vß3^ýõ>p„ÀÒÒöíÙƒC‡a||Û¶mÃ7mÁÆ!=™»GB`-PÇNäH¡Žã¢Z­¢§·‚F,.-a~~Çßx‡_:Œ#/¿‚ÉÉI„a €ëJ˜8‚Öº÷= ^¯÷•÷eaC)…7Žé'°wϬY³ë7lÀ† 022‚ÞÞ^T*•œ!:ù(ó žô ¥[䀩É)ÌÍÎbêÌœ8~'OžÄùóçQ¯/·!וH³¼ÜX0öÁ÷ €4MûóžsNoPB ФSÕf³‰“ÇCzyLîù><¿’ß{>*•*8çŒRˆ¢ÍFFQ" CDQ„8ŽÁXN¸òÌ´^©€PZ¿'œ&„`ÍVkE¦·­üõy¡k–<¥Û§M’$A’$ð¤·ÁÂÞB)å„¶ù†Í«Ð ”2Ƙd” :¹Çƒ°Ùì:ôî[ÿ·cmQ­ÎÏ4 ¸ŽCÜÍ«J$!dUÛû²Ú|Ãfê8Žp]×cŒmB|¨äæ¥t'AÞ @'W!mRe­E½Ñ(¥OpÎÇƘزuËUA¸,ö}Ÿ”R/K³k¢kËËËPJ2–+_d*õn cLç… s9Š¢2*Ý›ð}ÿ‡°ˆ(W4P—  ÀaŒùÍFshii QåÑ¥ ï/ËšÀ»"”´ %Jk0Î¥`(1ÖX4 céÊÁ ö‹ÓÓÓï3¾ß.RtŸ1mÆÖ9-ª”S”)P¦Úé-¥TQaÊÏ!j¥¡L~:ÅhݦÛÝß(ÑJµ+E7Ý´åà'ÿù½Ò×Û7Fa‹rA+]7Ö¤výŠ…‘/|á ”â2ÎG8ƒ¾ïûqìݳ÷{öîùé¥Å¥¡Z §§ÕJ¥“E&È•Žãæ‡]Ù¾:®„1išä§QÓi#MÒü]š"MÄqŒ(ŠÐ CÔëu,,, CŒ­;~Ï=÷<~óÍ7?g­ ã(n$ir!‰“…,˚Ƙô¸*G¿jeèË_þ2圻®ëV¤'{Çéw'ð>>ÌÌÌééé!ÿ NETSCAPE2.0!ù,J@ÿP™I«½8Ï$µÿŽcBžšˆ®•Ê²î‹Æ2I_K¡ïÇ1üÀ pø;ìˆÈ¤²x\:ÆÂsšŒJ©Ø 5Ël»Ø/xZX˜{½ºlHø€„¸`N§îx¼(Èûÿ€~{?}‚‡ˆy„†‰„ŒŽ“z|”—w’˜šœ”ž™usqZ›y¬­®®±²³´µ°µ¸¹º»¼´·½À²¿ÁÄÃÅÀÇȼʽŠf9jhÕkר: ÓÙßàØÛÝáåæÛÞæê×ãéëïeÜîðêíôôö÷ï ÝÒã¸!hS Ú›¥*\ÇK„ #JœèÐÇÄ‹>ÌÈ1bEˆÿCjÜ(RäÇ’&Ñ€D™ñdB-Ö$€8JÕVæ4[æK'Of}~îÊTh.¢;¶BªÓ¦=‹úzFǪš£üû„i+×I8¿‚KÉ+ÙDfÏJ«6[±s¢°®Ý»fúýÃË·/^½~ ^ào°á¿…+–xñâÆŽCŽ˜›^˜¹M0sMeƒ CVP´éÓ¢I£^Íš3ëצUÞ]M6mÚ¶oÃέ›µÀtw'ðð §d‹,9_™|¢äÍ/.Žq:uç: _gh};÷&@¬©ióPH)¬èçIϾ}Íõîã³ç#¿þ{úöóCФ??üþõý`ÿ|’Ò=ÈôƒBu8"€m ò`*>Ba…LhS…b˜!„*bˆ™ŒH/ S*YiÕSRPåcSw@e‹T6Æ"c޳ìÈ£Ž8þhLNQE: Ò£Â0é¤-O.%NSSåŒÎä¤@{‘Pf`†)æeb–if™dž©¦šþ¬é¦™i¾)§@qÎ)gvº‰gžl¶æf¤Q£Ï5ü 0è>þº7ŠªSh£æ< i8’NúM¥–ªÁX? ¨;½V€<¡Â6j7¥¾6ꩲv*«­¢öj¬²’J«i³Þ*Ú¨‰–q×@ÌC¾^1ÆÅKFÊ"ËYÿ³N$ ­ÒN‹DµÖq*i¬pk”w,Ù^›]¹Dœ‹®ä®D»îþo¼óº«FxÝ®APiıä’w ý ðK$ LpÁ¤]Â3¬RÂ#;ÈTM Êg ~¶·q!»÷qÈ"HrMów2z)¯œ^Ë.c³B'èÆrä7rÌ2sÌsU ÿŒ¢ÏBï,4ÐAý Ñ?òá)¸`B 6r‰x\u&†¨5Ö_“¶×]{8¶U•„‚'™H‡[ÃõƒF(7‰w‡˜·‡{cØw†i[•@ÎU¯B‹OO"î$‘<*ΤãBBþ£ä3. Ú®hh 7N™“çž úèQ~^ºèÁ|ˆä†N]Y¥ë Ç^:ì?e¢€no}IX[/¥;ソå!ðXO¢ñnébûíÌ7ï<ó÷æ{~úÒG!ù,@@ÿÐÈI«½7)Ì»×^(JÉhrà©R麶î Çã¼x~CïÿÀß!,Á!Élú”ÎèQYZÔ«vÝZ»Þ¨rÁ{îåa-h»Ýx\àÈïø¼~?¯óÿ€xtv†|ƒ„‡‹y‰…ŒŽ“’“Œ•‚o y ¡¡¤¥¦§¨¦©¬­®¯°©«±´§³µ¸ ·¹µ»¼±¾µ Ä98;È;ÆËÌ 7ÍÓÔÕÎÐÒÖÚÖÏÙÛßÌÏÑàäËâÞåàçééëìäÐ 9Ä Éikúûük\;ú Hß?*ôp¡Ã>œ¨/"Å‹/N̨Ñ!Ç~ÿHÔäIO§`¿dµA™Ò––¯¬„éJæKš¬l²Ä©k&OT:aÉáDRÓ*KH ¤k)#¥NŸF•:õÔª®FF¬X¸®`Ê%Æ@ÞØ³hÓv-M­Û·fßÊEËv®]±uïê]w¯Ý¾~ß"` WfÈÌà[Œ¬ë=Æ#K>àx²åËÅ.kŽ\y³çd?-z3éÒ˜¡=¦b@Gâ• ìèP¶DÚ ‡ÌÆÐ6ïÜÇnÿè{8ÁâÆú.‚&}EIþˆN½:õéÖ³g¯£½{tìÞû/><ùòÝÏ£ßÎ=ú‘Â;ÁAÄëõíïÁ_R¿ü'ù×Hÿ~Þ`X  "@ò½ñ )2íôS…?Éb!OfèÒ†8uèa)"ŽJ‰±(°'šh‹‹0¶"‡1RXc‹7*“måLW…)äAFä‘H&Y£ŠJ ¥–NZ3à ?VF¡ŽJê ¦:QjªL¬ÊꮾZD¬²êb´ö§sVèP«¾þDpÂÚJl±>‹lÊ.Û,ÿ²Ïöp€=«}_B%·O¶Ú2´[·%®AâŽnCæzûí¸ÜúМµñYG€zëQ7o{õÊ‹o¾öÒ˯&÷öð¯¾û °¿ã§?hÁ†v'ܯÀuoÅŒqÄLqÇnp r"W_¼óíÝ‚w¬Ìr .èòË3³\³Ì1x³mˆÄ„ôø²‚/Ë$4ËDs‚Kû—4ÒMïa„)ËQŠO1b ãMYs½µ×.j6Ø&Š]„UßA"Ù#Ê”ãŒ4¹}£Ü5Ò£Ý0âM‹ŠwÜ9®ãÛÿ “á-!n ßE?¥Ë'6Þ”äC^ù‚“¹1U‹+àùç {®A褗nú韎ú꬧®zë°›þzì´ƒ>{íµßŽ{ìºïÞzï»G!ù, A@ÿÐÈI«5IÝÍ;Í^(JÉhrà©~Úꦮ Çæ<C®ïüQü¼ pHø€Å¤2w\:‰ÇÂsÚûI©Ø(6kÝRµÃƒØJ., ‚´Zè¸|N¯ÛíîüÎïãõ~y{‚‡u„†ˆŒmoŠ’}kj™; rm¢£¤¥¦§¨¢¡©¬­®¯°¨«±´¦³µ¸Ÿ¹»·»±½¾£si bÆceÉ  ÉÏÐÑÊÌÎÒÖ×?ËÕØÜÏËÍÝáeßÛâáäææèéçÔÞ ððÌó™÷ø÷Fböùþÿîð Á|ûú\(ИB†õ9ŒHQÓÄŠ>ÄxPãÂMÇÿ $X$'Óž`®ÚÀAù Ë”i€½,¥RæLa1o¦ª©SVÎZt.Ð @ÌI>!Mªt)¢¦NAh*Õ>V¯Þɪu˜€dâ‰;–ƒfdÓª]KÖ,Z¶pãÂ;+·.[·v󶥫·ï¼~õlwð¼Ãˆ™pÈä˜c1ñ <žL¹òãÈ–3k6OòæÏ”1ƒ}L4iÒ¦OƒN­z³<ÏŽÇ‘­§Ãà‚ÞÞ˜; ܽmÿÜ÷pÞÅóíN^p9s€Îõ IÆÀ½Kkv`ßν;víÞËOóf¼yîàÏ«W“~½úöîÍÃ/~>wé Gf²+ýù‡ÿ$ €˜H€ Ê`>Ø  R‚‰tÌaÔJ=âR‡¶ØÔÓ‡ ’Bb‰ªpˆbŠ"êtb.A¥A@†m¬H“8z˜£*;ê²c‹#®x b%f$bn©ä’K&Éä“Pžå”MJIå•HZ‰å–Nn‰e—^R æ“Hfg±#š¨3nvÃfœÜÌIç5vÞ)MžzBƒ&Ù¥äb¤@Mk£Ú ¢ º£Ÿ)ú(¤šIJi¥‡^j™¥šV¦(Ô…•„>a†3^Lqê©.a«­&±j¬®vF«³ÞZD®ºÁë@Æ(mNXC¯¾‡¬Ê.˃ÿ±Îm´;LKmÖ^›­Á&C[G=çGâŽËO¹æž‹.>ä®k‘ºî®»íþR·"å³ÝPåÑ7¿zøûo¿{p!‡wp ÛÇ0&? `Äâ,'v°ÄÌñü~¼¯Ç"OpÉŸŒ²É¯Ìòz¡ß~%18áuÖ ¡€8ç@Ï9}³Í =È…šä ß‚æ,¡ÏîìßÓN­ ÕbÝ ÖŒ€¬ žäL?Ù¨âŠe£}6Ši³½v‰mÓ╌3jøóØ/Õ˜#Þy ð£ß{Ž£Þƒ ŽÒ‚Šb¸|÷˜w³ùá£8¤Ïu¨‚¹A0›se æcè>“IKm(¬·îúë°Ç.;ë«Ïnûí°'P;î¼Û¾{ïÀçüðÂo¼êÇÿ{ò¼g!ù,G@ÿÐÈI«5IÝÍ;Í^(JÉhrà©~Úꦮ Çæ8~Cïû‡ÜoH,‰AÜqÉD*›Ðe²­§Ö,P¨Íb»Ö/t7Íáa-h·}‚€|N¯ÛïwÏïãõq~ƒ~€„ˆ{‰Œs†‚Œ‘“’nnk? tz‚¢£¤¥¦§¨¨«¬­®¯°ª±´§³µ¸¢·¹µ»¼±¾¿«t fdËÉ ÈÍÓÔÕÉÏÑÖÚÛ9ÏÒÜàÓØßáågÐäæáãêêìíåïÚ ôõÐ÷Ëjškdü H0 ¿ *\Èï`B† ä±¢À‰-ZĨ±#ÇŽÿÿäÄ,Lnz@ª#ÌT€6ÁZÚŠ#ÓÕKš5YÝŒ™sÔΞÃ`M%´e”›¨Bé†Ò YNéŠÊ*ÕDV¯ʪÕ×®|¾‚µ3õæ1zâê©­Ç€A´µpãÊ» í[ºxóÒs«·/]»~Ã,¸p]¾†Nìw1Ü{#C3Ðì_e;ê)Ã̹³çÏš?‹Í-éÓ£C£^]Ú4ë×™]Ãf­zöêÚ¢¯Á¥¬ïGÀ$AVžQøÂ Á3$®"óæÇu‡.ð9u‚Ö%"!“,ÍM)á0O¾<ÊæÓ«h½{òèßËÇþüúößãÏ¿~ÿ{MÛ™Äÿ&›2ÖlˆàJ :’`ƒG=¡ƒ'Mø‰„ €¡S8@( ’C¹„S‰¥ˆbŠ'®¨K‹.¾ÄÓP2ºHJ@ÕFJÉÁàŒ2i£Bæ8äGú”¤.KZ%ÀYš©%™dvMiå•XÞSe–\véV—`b¹e˜dB6f™ež‰f˜j®éå—n"`Zf”A nÁcžèY4~†Ãg à Jè6†jM¢ŠÞ™gZk]9g2¤€Žm¬Y ¦«Yº§¨iú)¨•^Jêh¢žŠª©ªz–êgÍÈ%'¥á 2`Xq+¹Fá ¯½6±k°P K,Æ{D²ÊÁìÿvÌèFe9Ôj«tÍ^«L¶×òÀ-Õ~ .¶âún¹æ’‹î¹Up×L>½M÷ÑuÍK¯AÝ[¯Húâ›o¿ ñ p?l/C$¹[@Ö§¡ü•W J¯7qÅCŒ1RoœIÇ?,^ÈãMÜž{±Lßô1Å$—>ÇçM6iù媷^y“q<é6Kb5è“ÛeM»Ó»[Øû„¿GõŠ d ÀñÈ'¯üòÌ7¼ñÎG/ýò @?ýõÑ[ýöÔsï}÷߇_¼øákOþõæ+!ù,I@ÿÐÈI+MÊêÍ7î`X%b ~fj¡jk°n ÇåLOK¡ïÇ1üƒÃH,H P—l:˧Թ,L¯Ç*v«r·Ú/6ÌíUwº…Á$…A@§îø¼~Ï¿ €}‚ƒ}„‰„†‡ŠŽ…€’yŒˆ“’•—“™š~uuno? s–y«¬­®¯°¬±´µ¶·¸¹³º½°¼¾Á«À¾ÄźÇȸ” Ñhqff 9ÓÜÝÞߨÚßãäÜØÛåéàÙèêîháíïïñóö×ì÷óõûÑþÙ P3Ó&H¡*\Ȱ¡ƒ>Jœ¨Ð BŠB¼˜±cÂÿC>$(2$È’O¢|¨¤Z`’ªÏ²]vnâ Hç-ž=}ÖªLh+¢Fi!Mú+gR=tfæ`Χ«5;ÍÒ:i×G»¾‚;–¬¢°f ¡M+h­3hþ䥉»€mtóêÝË·îݾ€Çý+¸0_»x +Lx±cÄŽ#C޼xr`€˜3g3 mÁQþVMº´i3¡O«^MZë׫SÞÝÚ5íÛ=d㦭{7ìÞ°§é¨£Z‘%WbDÎQ¹D!É?/Þ\:CæÖ§Ç©ž=!öîש{Ìb Í6DÄʾ½{¬DÞËŸ_ýûíããßÿI?þþý‡_ÿ€ÒG`¡@q€?xÇlñ!„î!SVNˆa„Vh¡²Õ¡‡”€È!(n€@)VÁA¡*LñTSaÑØÔŒ1eãQ:î8L>Êè#ZAXEL!â(Œ’CÉäSM¥,SSå/<)Xhqi¶â]^†)æ˜!Fæ™h®˜æšbšÉæ›e‚ 'œnÎÉfv¦‰gž›ÅåY7jê3O ‚º“M¡†Þ…¨:„.JN£Ž~i¤€*ZŽ^brÖ¤©¨o´yº¨³©8*©¯‰Šjªì¬Êšª®ªk¬¦Íúªp˜rÆÍg? !×Lõë×X1¬Á{¬É.ûDÿ³Î6m´HLûD§¸FCÁµI| îÔk„¸æz[nº@ Ë.ë¾ën=tCÜhmC*í›àAþVDRÀÿLðHÜoÀ ×Ry/WÐzÞ'Ê[l_Æò]|ÇòUü^É&·‡²€=ÜCèåkFÊî]L³Êߌ•Í:“¼qÏQý 4Ï@³É ƒ †RÜ‹$†’¤Y&’ˆ‡ÔV_]uÖXg@×\o-Ö'­ÈàG4y=bÖzÍ“Ø$®mµÜqÃí!Ýi}r;UY%D#zÐèT“@î8ø‡û˜¸á…Û¸¸P”üíFUÐÌ4òTåj“ °¹çSj:èQŠÞ$O€Ë”À6e~啜Cûì›ÓîÕ3vxí•î»gÝ»ïnYý»ðÁ“8|Z;e©ÀòÌ7ïüóÐG¯ÒWo=ô PýöÖkÏý÷؃/þóÞ/~ùæ~úÛ¯ï|!ù,J@ÿÐÈIkR5ëÍçí`h‰$ø•hv¦¬±¶è “òÌ-E®Å‚À pH,y9£r©D2ŸPdJmêªØ¡4Ël»Ø/8x(ëΆ"qð"Þ‚`N§îø¼~Ÿ|‚ƒ~€„‰„†‡ŠŽŒˆ“w‘”—–—“™š{utoSr‚ª«¬­®­¯²³´µ¶·²±¸»³º¼¿¬¾ÀÀÂÃ¼ÅÆ¸Å}>8ge£o.ÒÓââH° Áƒz)3 ¡Ã‡ 6„HâÂ63F”6Q£Çÿ;~ÔräÇ’& )³€K  8ðIRª_…%ÛUÙÎ\s|þt•SèÐ`AÖ*ª”Ó¦Dïx9jÀ©šŸ:ÅÒJI×I¾‚û(,YEfÏJ«6•¢9ÎòYk)3ŸÝ»xóâu)N¯ß¿wëü—/áÃy #^üL1ãÅŽŽ|xŸeË|T3£ùŸçÏ C~æO´éÓž;£^mš4ë× ]ÞÍR5mزo¿Î­{Ý] ;¤q›’R#ŒÅ+ò@žâq‘Í>î<sê§c—nºÇ"ÿt¼dÓF5‚XÓ«W/d½û÷tþÀŸŸ¾=ýûuìãǯ?ýþþÁ`ÿ€ŸÄ>$ÀçTG[• d„x€ …zXx!†JÈa~á†j8!„s Ѓ@@\@SVzÕT½ÕŒ4¾‚cްèÄc66µã^á\ÔMÉIä“N ù$,SSå*Q*ec%ô%W>oðuÙ˜d–9¦˜f¦©æ(2­é¦™h¾)ç>qÎ9gv¾‰gžkîÉçe™‘M£Ü“2Z5Š‚ƒ()~óh¤’&Ji6“^ŠM¦õÜUf íHóŒn°À ©¯™ºª¬™«¨¹º*¬§ÉJk­§Þ*š­·™ƒ™mv€fSŒA>ÅûDÉ*»ÿ²Î.«Y´L@K­Ö^[D¶Y|æ«l¦jÚnÛ]¹Dœ‹®;¬;D»îo¼*ªï¼ÎJ³Ž X'*:ÞmG#$QÁ ŒpA(-<0C¨pÄ 7·Ò?ˆòëÙp¸^(òyìÈT‰üñ€&ˆrÊU…ÌrM$—ü²Ê.{lÐJ3 `y®"ÐÐÌ0× 4’@ tÑF×ArÒJ =ôÒL´Ñõì‚@Œâ ¢'â!Šèõ×c‹ö‡e£}v[ „SžUýÂ!!×l¯¡…'Rhâ×…Ø­·ß(^7‰ÀÃ!^0SM{•T•>Nù¸ä‘?9¹å•y9y‘¡¢t’ ȱdãCreX§›~¥êU²>¥ëP p::yúè1Ê8ûìYêž:ïÀÿžK!0á®–W|c™<[""¿<ßw8ÿµôÍÛÂ%LØg¯ýöÜoA÷à‡¾‚â—o>Lߟ¯~÷é¯ï>öí¿ï~üò«Oýæß~!ù,J@ÿÐÈI“¢8ë½-ÿ`Ž£GžÝ…®•Ê²æ»Æò™KQ L_ƒ pH,‹]áÈl2“K§T N¯Æ*vKÔr¿Þï6,>ÎJ^±0(V‚\@¯×ø¼~¿|‚ƒ}A€„ˆ‰~†ŠŽ‚Œ‡”x‘“•—™•›œ‰vIrC˜{¬­®¯°°³´µ¶·¸¹¬²º½µ¼¾Á®ÀÂÂÄžÇȺÊÃyt Òi?ghJÚÛÜÝÛ Õ9ÞãäÞàâåéåàlêîãìèïó:ñô÷öøóúûÜÒÙõ` €‘ð¡Ã‡Š:C*¢Å‹'VÄÈñâD ÿCFü¸Q¤I$OªL©Ò$Ë–EU«†­@ÁŠvè$ʵв^‹šýœÕSèÐWEâJªÔÓ¦´žBuç™”¨rj¥àS¦]^¹†­Ôu죲f¡M‹h-ÛAnAÃZŽ€xóêÝ›w ß¿€õ" L8°ßˆNÌàáÆŒCF,yòÌ˘yD·`Í5!ØB‹Mz4Àk¥S«&=mµë×§_ËN{¶íеoßέ{6ïÞ¢¿IÈ@‚Ž ‰À¼äòŽIœ?ÇØ¼äôˆÕ¯S×!];ÄìÞ±s·¾<˃JܬQ¸pŽÖ÷ðµ‰O¿¾|CöóÓŸ¯¿ÿ}üþ‰ÿ$È_ýˆ }$!)§(ÐCv¤%Ào r¡*>ƒa‡|\˜ ˆ!~H¢‡#žˆ"‡ ¢DJ PP*9ñLPSýbÔT8æH”O>Rµ#T=9 F¶R¤[0Z \Á ™ä”R9%RW“¥’[îÔ"°×ƒefæ™hš¹Fšl¶yBnÆ™æšrÖ‰væ‰gžuîÉgœ~þÉ&›M£C8þÌÃ5‰ºSM£Ž"©:‹NšN¥–’ƒi¦Þlº^jDgpgÛl˜:Û ¨*ª­ºê¬²ÎN­«ÑŠkjººúO@I€r•1E>9‹E>V(ëÿ²Í:Ë´ÒJAmµM\‹íÚ*;Ú6ĵa@=ÄnËíxænºD(Á»B¸ o»ëÎ;€¼ö/»5§ƒ ÙC«B„'6äŒE ?ôRÃ¥ ñÁ OqÅ?Þàx¦CAÈ áЂ9¹ Éô™Œ2ƒ ®üžÉº Ì2ÇGsÍ/·,³Dì$š=¼ë^Í*ãœsÌF_õGÒ%/Í4ŒN?}aÔO-µ"aÁÍb&ª˜‡‰*†-vf‹vÙdŸ¸¶Û¢H£Œ XW¡Y"~á†g/Ò6‰y÷øÙƒ‹]¸Šƒ_UÊŒ4Þ­2:m‰ä”‘gYù•—S>y’™s¤ŠÏX•Å,Òe•J™¾¥êY²~¥ëT pºì±ôA€“_/ƒz—Mí~”ïCÿ“ðºóŽº% (ð¤Y`­dßÍ;׉ы]½Š×SO`&ïý÷à‡/¾Œoþùç„þúì'_~ûðÿ~üô{?ýôß?üúïÏ~ÿð‹!ù,J@ÿÐH™Ô¼8ë+ÿà–„$镨h¥ìu¶í §ò\Ê Ã,E_‡pH,ƒƒÉl2•§t N¯È*v[Ôr¿Þï6,¦.:ž¯°0$‚C‚\@¯×ø¼~/ ö€‚ƒ}ƒˆ‰z…†ŠŽˆŒ‡“‹~”—x‘˜—š›“ŒvrD¡ƒª«¬­®±²³´µ¶·ª°¸»³º¼¿¬¾ÀÀÂÃ¼ÅÆ¸È½yt : >@Õ@kØÙÚkgjÛàáÚgßâæáÝåçëØéìïíÞðôlòêõæîùú ÐÑòäPðÃZœQ*\˜È€…#J$åp¢E‹ ƒ\Ü1ãCŽ ÿGy Ir$I&OnL²Dˆ5% |´CG‘¬5“í¹Lg,œ|ÞÚSh°œFiMª)ÓŸN_-5àÍ«‰¤z¢”k+W¯—´‚u$vlV³Ê¢¤–“€gþÒdóG·®Ý»xëê𖷯߾Òþ ü/áÃw÷"^¬70cÆŠ/Ž,oÀËh¤”pMµ!/C‹M·àèÓ¨Eû3º5êÒ®cŸ†-»¶5Ú¶mãÎ-{7oÔ>ÚÈ ‡A"*Bјü¢æÍ'.ÿ]âôêÒSǾð:wˆÞ¿Ë!bA5lnuµ½{:DÞËŸÕýûòããß_ß>ÿÿŒàÿú ¸_Þ×uF“ Ùá‰s¬E*B!†òQa‡rb&ŽH¢ˆ#n( Pt $DL¡ÐÈNA=uSQOñdãM5îØŠŽ>þØc¹ I$?MEa5¥b ŽDFùŠ”ÁP¹ ”9Z™‹–S“‰|¡1O]˜•iæ™eî…æšlš©Y›p²©fœtºùfxÊ3gžxîÉ'~þÙ&@—žñ#Ž˜Š²#O£ë0 ©9’NN¥–nƒi¦ÙlÚ¨e™Ý)A¨žý–Z÷˜*ª ¨ªÞ¸ê¬­Êzjª¶‡k®£ÑÊëyØ„J&qˆR£^G°Á²X°aÿ³R(û,´MHKm´«]넵Ú2Ám·UCª²þ[*¸BPƒn²?¬k„ºî’§]¼CÀKïöÒ›¯»\¦Í@Ó¼tPu)‰çbE'TpÂ!ÌðxŸ=,RÄ7 ÝÃJ¬ö’1!B ’â_‚ó‰, É%#ˆ²{&Ÿ¼2Ë*¿LSË2¿GsÍí`MË/ulÄ(›Œ3Ì.]‡ÐFÏJ^9å;Zž9xåJn#ÝŒ+#€–X&…é£[yºê©S¹ºë­3³L®¨Ç1\rYºéº÷Nºï¿|©@“›tEö•w|[ *ÿµó&B?¢ô¥ ¯ÀõØg¯ýö TÀý÷à‡}Lâ—oþõÞŸ¯þ÷é¯ïþøïǾüñ·Oÿùöß!ù,F@ÿИ¤¤½8ëm)ÿà–„$镨X¥ìu¶í §ò\¾ÉRìüq À pHxŤr <˜Ð¨ó­&§Ö¬©íb»Ú/ØZ@˜yèÄ/Hh Þpx`N¯ÏA}Ïïûñz~ƒ„u€…‰ƒ‡‚ŠŽ†y’w‘“Œ–—yqpm@ {¥¦§¦¨«¬­®¯°±¯ª²µ°´¶¹«¸º½¼¾¹ÀÁµÃ±t :h>Î>hÑÒÓ fÌÔÙÚÓÖØÛßÚÖËàäÙâÞåéÕ×êíëãîéçñé Ê â Ïkž 8ÀÙ¿*,øC¡Ã‡m6„Hq Äƒ3F4¨±ãÅŽÿ?‚¬(Rˆ³9êƒ*ÀcÄZ¹„s×Ëš²\êÁyì&ÏY>Ê *ÔæÎ]†à„Rɉe¦I¥žJú%õÕªŠ®b-¤uë ®^b5poºùÒª]˶킲nãÊ•‹o®Ý»pïê›w¯_µ}ÿþ ,x/áÂnÍ(.«X¼f>‚ô›L¹_Z~•3k®œóæÏ›/ƒY4éÓÏL£F­z5éÖ®?—)[-­…Œlãdâî‡G|ÿVØãð„Å;L®ùáÍ2NMg;Ôøcㆩ÷8B¾‹¯rùóßã__Þ<û÷êßÃw/}üúöÙ¼ñ4¥qQr\âFÿXˆB` xà ¸  ®ô`„B¨`…w\˜Ô~m$`¤ÜrTQ¬ÌAâP45Ó‰%ŽÈb*.¾øKŒ/®x‹! ¼äÇ,2öx‹§¤H¢*™Š‘QÕd€= ¨U[>ŠE)å”TFÉX•Xf‰¥2Zvé%“_†¹%—b–¹™f–yešb®É¦—÷™À=5C5ö pg9gì Nž~þ©L ßJ¨6†Šç Š¢µVœQ&S'n±QVÆ2•’VÆ™Žv)§ÊvM¨¢bJªfŸžŠê¨ªöÃÃ[tª¥ÀY¹!DmTØE5¹êÊ®¾îÚY°PKìÆ›D²ÊJæƒÿ8z¢±ÀmÑDvlÍ.ËO¶E`ËíÞ~D¸â@®¸ç~«v<ì㙵ÿyÄu1/½"Ñ P¾únY¿ûÎ ð'<…?ýhïò}B~â9ÄçI<1ÅãYŒ1yoñ}«ÔqÈL,œI¨ADwõILòw¿ìË2‹üpÍ4×GÎ:ïw³Ìç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFµIDATxÚÄ{w˜UÕ¹þ»Ön§Ÿ)0 0 ]T¦ ƒ± ‚ 5‰¦`‰%F%7^*ú‹z£¢×k¼ÐÄÄ.š cb‰šÐ¦Óg˜r¦¾ÛZë÷ÇÙçLq0*àÝϳž}æ”9ë{×WÞï]ë!¾©KUUm´çMÓ4ðt‘o€Gydò¸qãê#‘ˆMöšÁ`P>°áwÞyèG@qL‡¦ižO>ù4É8ñxB$“I¡ë†0 C¦)LËBñÁô+Š"ëùŒò7€1=XcóòÀ9¥$‰‚P J(¥PMÍÍ#|㛹è7ðI’2ÆSJA‰s§„PBñ|Ós“  ©%&Òù€R¯Ç£*Š2þµ+§E?Ÿ©€PÈT "ØQ†SŸ?ðÍ{@eeåëׯ߽páÂ+¿è}ãÇ?ñì³Ï¾ëÎ;ïüݬY³Æl’6< DêbŒaÑ¢Ež»ï¾ûÕ‡Žûù•¯…¦~Ñÿ¾»¹ð֚ŷì*--ýÖ7šËËËo©ªª²…¢ººÚ,--½~XB‘e­²²òÆuëÖíÞ·oŸ‹Å„a¢­½]45·ˆ¶övq¨£Stvu‰îPH„zzDOo¯èéí‘hT0ÆD8[·nMÜsÏ=Λ7ïrdÓ•ÅxÿÊéøè{Å8ûì³×644p!„ؾ}{bîܹ—Iü*Æß\UUe÷ôõ‰½Õ5¢¯@|öÙgÆòåçÝ@.//¿á¹çžkîéé¦iŠžÞ^ÑÔÜ"Ö7ˆú†&ÑÒÚ*ÚÚ‰ŽÎNÑÙÕí2¾·¯Oôõ÷‹þO$ã\!D[[›xâ‰'jæÎ{ÙûWNDzeËîkhhà¦e‰þpXض-¶nÝš,))ùÚ |)PQQqËÆ5nüéPG'Òéz\^‰8¯®®˜3gNV^^íéíE8mÛeŠ"C’dÈò`$„‚Râ„–Ò—$IpiTUE}}=«®®î›[R’3~üx)‘HdÞç÷ù°sÇŽäu×_ÿÃÝ»w?wÔ‰PÚø`0KÚ¹s'ЧOÏLVÜœøý>„#„ÃÎAÀ¹€$QȲI’F@œìO†T¢$ÓR ·Û UQ`ºžÉBBR ìÜ©_ýõWíÚµëù£À)§œróúõëfeIn·9ÙÙxç/ï€H&8烕ÒÌä8ç™/I’3((•@éáHWˆ‘yŠ’¹}>Smü~ìÚµK¿îºë®úä“Ož?bÀq¯¼òÊÞ²Š _G{;fÍš•ymß޽سwN˜;²,.»‚8 CQ$H’<$à 5‡AÃÉ—¤Dé¹§ïÁ@/¼ðBÇÊ•+gض=¢2Ç£555–iaï¾*ضy­¨¨¥'Ÿ„wþügº~h @¨Sæl$ID"ô÷ ··½½½èëëÃÀ@†a¯ø2yiè{„HåŒD2‰ªªªVƘyÄDˆ1Öë÷û.s»Ý¯^¸bÅäM›^÷¾uiÆ8ƦM+ÆgŸíAiYùÛSF$’IpÆ ©*4Mƒ¦©eŠ"ƒ€€qfÛˆÅâè*ƒpic£zÃHpRåW‚D)Ö­[·÷¡‡ú¶Â8*L0íôù|xõßN;mòûï¿Å‹ƒ3€ ¤¤5µµÃ]ŠR$IX–‰€ß·Û Á9lç3„8+&S(ªIò ‹RpΑˆ'Ð×ÛJ)rss IÒzC:'X–…ÿúÍ“{ïºkÍrÛ¶[Žz;sÞþË;xø¡ÿ„ÛãÁIó磫½A¿±Xìs|?U$„B!ÔÕ@]mÝaÝ›1Ó4!„€×ë,K£°¸×°m9¹¹X¹r媪zŽ:Ë–-»uöì99‰DbØ*LŸ1³çÎůî»þ ¥åh:؀ΎPJ!Äðzžš0‡ÛíÏïGVvö¿œœn0 n·{”¾…à\À²,,\¸°°¬¬ì†£ €ªªþ /¼p…$I™¬<ô:®¨å••¸ÿžµðûý˜_^ж¦D@ˆ€ÃI‹m3x½^Ìœ9……“?WÇ?_I‰‚ J)8O?xç‚ò,äåçcù²eWUJJJ.ž[R2>©ë£’Û¶‘—Ÿ‹.¹÷¯½>¿¥å¥hknFd œáø„L|’$ƒP 8ÏQW ºnÀ²,†žYýÔÿKÁc ++gNœ8qÉQ ²²ò"Ÿ×fÛ)2(!HÄãÈÎÊBÞ¸q8gùrü¿{×Âë÷£´¼ í-­ˆ„Ãã4MC @2©'jïèêèì!BØÁ@Š¢ŒZßÓƒsÎ8b±LËb<ç œs¦ãŠŠ¤Šòò‹Ž š¦-///·Gqýt¢bŒCUUØ–… &àì! ”U”¡£µÑH¹¹¹hookúɪï¬\xʧ,XPQVVZyê©§®¸{Íšç««ª’Š¢d¼dp É8!ñXÜ…¥žgŒqØ– I’±ü¼ó.PUuÒWâ>Ÿ/oõêÕÆŽ[`š¦mÛ6+((˜°°²rr,=6uŒ1äæä€Y½Cmmx{ËÜzûíˆÇbؾu+ú£‘ªk¯½öŒ×6mê–…€düà{ß½àÙgŸ}ªòÔSó“ÉdÆR±Î#’É$’IcÆä8ñç.2÷ì¬ ¶oÛÖSS[Û Ë2Ñ4Mikk«ýõ¯}µ®ë‰Q8ãŒ3~ºeË–GUU…Í!°- íí‡0ZüSJ10†æÒà÷ù2îKœz×î€pÛ·#‹cû¶mœPzµ$KÏŒ€Ô×Uw¯=oË–·^ fݶmº>OoÛ©ÒÆ“› ‰J£…HåÎSY0a<\.„$ ===X°`Áмv¸pWUU£¶n?êêö£¶¶êÐu€ 3œÙò-H”OZ™™PP€¥çž‹ûï]+<>/Ê*Ê)8ßÀlvØ,ýR‰²ùÏýþ%UÕ`Y,Ë‚m3ض Ó4aY¦ó͆n8!höSƒsž¡ÅMÍ-¨ÛÖã`Cœðò|A<%Ö’ÌÞ£IN˜›Ôáðé•Huu)¦NŠÂ)EÕ¿¼eu³Çûå@xmÓkOG#Û²lX–D<ŽD<ƸÓñ¥ätÓ4ÃY¦Š¤ç›–ÚÓí6%tèÔÞ¾€R‹ ³³­--uwƒYQÐ~èЧ۷m;ç—·¬nv{½(«¨ ‚ó Œ±+0 ¸ÍÍÍ5=½½ýŒ1Äb1465¡¡¡–e!µ¯@A% ÆÅ°þ!uO/ØÐÅ#ÿR[øú@ +]é¤d³ÁU1 C÷z½5<”/¨ ‚ñ ̶¯¥É‰ Á´2Æ Ë2¤!(”ÔbŽðTgseXß1Ê1 -w©ª Y–1iÒ$L™:ãÆåƒsÓ41mÚ´I0Â-ÀÅÆødXßáÏ÷(r„€ËåÂŒ30µx*4—–‘ÑÄ@¦”×¾šŒ"ã 2[[ªª:CI‰—Îß–ea~iéIûêjƒ¶o?çßo¾¥Ùív£lA…lÆ®˜‘À†ïŸ¾nüŽÍ>ãåGfgÚãÔê:jÃHƒN‚#Ö/€$ËÔívÃ¥i™ñEb!’”J€Š’’¾eYvdpªª€‚‚‚‚¼¥K—þ2ý9¯×[³cûösþý–ÕÍ.·;å x4ö½À)ÝvÆ÷WŸçÙ˜Z½ æïÂíLBK«É\pH’ô¹9q!`9Õ@QhššQ¢R zXZZZ"á—% ‰H4%5§kéh‚„âÈÔƒŠïБE× ü즟Ýd ¾b$¿¼yu³âõ`~I ,x¶xÙײgžÂ×þ'vn«Ç”†¿½°u„Áº¸ÅISnŸÏ Û UU G(²#‘HÓa™ !D-((¸ Ìàœs˲Œ“N<±üö;î¸Xs¹éh`š™M™R4lŸ Íà8ç°mªª‚Ù–þغu¯ß°á¾Ù³ç$@bñøÌSfÏyåÑÕÿ1G™:xõeè/>…kjð^c7–Ï™ˆùKNBÉ à9ëû „"‹!Â7„| Swd±HØ|ñÅ?­««ÛÞÞÞÞ‹ÅÐßß ««ë/B{TEHaxy„›“y'žøéÊ•WÌ‹ÅãŸkREF4š!€1î´À©îÔ¿7M„P×=÷®ýW­ºúÿøÇ¶}ûö6gee¹K¢É1rŒ;v·öÁ",<žÂ%Kää@.;îxÈóK3ÿ|è^Œ¹çäÌ?]]ðûý£®>•$0ËÄå—]víž={þ÷¨]öÚ믿?kÖl·išÃH×úP(„‚‚ HwŽ£ñøT?o€sŽø§Ÿ`ÎŽf´ÿý¯¨Þû!ÆeEÑì“U~*Ô9Å ¹>˜ÍhyêAtô„ËÉFöÚGážT UUGÀãvcû¶­¡Ë/¿üDÛ¶ÛŠÐßß¿ý­-[¶«ª’"$Î_:óK’„ÜÜ\Ø6ƒ$ËÃJÎP‚’®á²,#™L¢¿·oÿáI¼³ïc´J]‰0šjvÁnÚ2÷Í‹Èï^‡—i˜“ÜD‘»~ÒÕ|ØÊ$Io¾ùæ»_Åø/E„^~ùå'[[[„Ë¥e²|j“35TUX¦UQ>W.‡ªB’D‘L$`¡û´è}Œ£Í¶‹FA½ôýùÏèæäVœÙ;^) y>/ÆÄ£è»m’;ßM»@Sc£þÖ[o=ùU ´fÍš/|ÃM7ÝTϪ¬¬œ4H0èÒ! ë4M˨;Cõ¾tH0fCU5‚A·d ˜i ¶{7 N®X ;o ¶>ù:;º0®¨YÓfCoë…Ì ¸\Iˆ~ð70³JñlÕBYÆ£>òÆÇüÀ19'X\\|éæÍ›_šPP€t¯>R°°m œ§dlUUA å´ªŒ1XVº­µ†í ×=ükøÞߎqSf`ÏG[ IP*Ã; ν¾‰“ûç‡É&09ξÔµvÃüqȹîÇðž|úûzÙ%_¼¤µµõïÇäŒÐ¼yó–deeÒv¶Ÿ²“ÂẻCè õ@×ÌNðç65àgݲãŸyá§#šD‚J Hô4aÇÛ¯ƒ«2ü¬€ä/††ˆIîÕú´·ÝŽî'î„—'¥âââ;&'E-ZtÛÆï-(( †ifÄœ´&ŸVhÓ²•m[0M º®Ã0M(²‚tþH«6ƒÇãH¦\†‰x[šî¹ Ø»~‰@!*ÆO;%+¯ ‘øÓk°û÷£®¥5­Ý€¦"gŒJa.²¯ù[õønܶmÛoŽË–-»ç‘G¹½hÊwÈÐ`lÀ 4Í9Ë(8iE'-[– Æ8OéJN+ëèh”RÈ’ UUÀ¢Q|vã {÷!W–á’\È™v"N¸ú:P_É×_…ÝWƒÚÆzÔ¶…`ÊcÆú!¹Àeñ»Þٳ꽷þ÷ ‹7mÚ´gÉé§{ÂŽ¼=¼÷#4¹4ùI`šÖ0µf¨,“þN:¢["Õç]Øqùåô÷c¬,R cg•aÎ5?ñ ¿ò"¬î*Ô6Õ£®=„8€Ü1~x2’3§ïo˜ùèMG”"‘Hhûöíº®®ûÊý™³Â¶mÁ¶-ÇÍ£ñàb„þŸ)kùã0ãŽ;ÐmÛhµlt˜qôÔì@ÝÓÿ ˜:\—}êø¹˜U43 ÆÂG€žPý&|uÚYL<¿÷¶rލ ®Y³Æ8ýôÓÿðûÏ®(/Ïêþ#{lBÓ4aLÇý-ËLvé•¥7'£,à=®Ñ®Nصµ0d&¤Þn˜‡º‘{ÒÉO.ƒh!G6 ˜X,H„ŀ ¤M ·ÇÊ{·mxuâù7šG”UU-¾ÿþû·üøÇ?žf3–Ù#LŸàRd9ã,uÒc †®'ašVúð$Åa’N¥H˜à<¥Å,š@k ¿ôR  Ã²à£“4? æ/Fñ?<^ÏþVÛ.Ô4ÄþC!D¹€'àÁ¤ >ð1Ø «ýSÔ6ÄþöÂ(çGád¿sÜ+æýOõëGx<žâ‰'.miiyS×õ¦Ãi†Î•{þùç?öóŸß|yw(„x<ž¢ÆŽÑiãS²"â±Ç{) ½  @ @@@gÈòóéé+§N¢ý¡0ªÂQe„Ò%˜òÓ›Í ã·ÏÀ:´µP×BÀ´ÉY˜x\ ßš£-8~ݾº#`¨b4¤Œ¦½€éñx>ùäoÞÉËÏWúR¹`H¥°m 55Õ‰õë×ß'„ 9”Á`HÍV^àÖ¾{õŒB´µö :E–L1ÉåGÁüÓ0õ†Ÿn7Œß? «c7jëQ×Ö(Nœ9cŠý;ãÅò©sü,ù•Ib¸ä*9C 8Uç®àœ±I¢~!çVMã WOi%¨ˆ¤ÒÆž€ß0̸ò¸.ºÉW8f`x¯± Õ-a”M˜¶n`åIËúí§±¯”H¯ºªªªê÷û½@Àë÷û½Ç«iš_Q¿ªª~UU……… ŠŠŠ !Dr.J)áœ˲„ešØ½gOG}}}G<—£Ñ(Õu–eÙ¶m[Œ1˹3ÆãœÛœs£8ù|·VúýãÆ#Š`_8†€D1ÑåÃØ'cÖ®Î4PVo êÚ0qÆŒ™’ºö÷¦>ÝØý:¤ã_ž0a‚RTTä.**òæççû€ßãñTU :# iZ–eYιGUU¯,ËEQ\²,k¶mÃ0 Ó4Ms®ëºn:tH477Ëmmmr?ÅbB×ufš&3 ö,˶,‹3Æl!„UÌZ*ÓS¿“—«(Iµñ$|4BNq f_~dú‡ï@²Û¡ŒÇæÖúÎ{éí˾Vp@€$ItÉ’%òÂ… ÕââbÏØ±c}>ŸÏ§ªª_–å¥4(I’_’¤€$I>I’¼”R¥ÔM)uB!„àœ›Œ1ݶí¤eYñh4jµ¶¶ZµµµRmm­ÚÒÒâ …Bj4•‰1 C˜¦)cB¤Îá™9À¤%Àiú<ÁlP4›&ÁÂ9˜³ò*(³§íÍ VqÛ/NÛÚÑóá•AxüñÇÉ™gž©(Š¢z½^M’$Rêq¡›¤~è&„¸(¥.'YjBu¾ÛvbÝBè ]×õÎÎN¶gϲsçNϾ}û|---YÑh4+‘HxmÛvÛ¶NÄsJ`á2E™œ'Ëh±,xPâÍBIå^ÿ#à´…xè»+žþÅëZÀBØGô»ÁU«V¥k5`H!"B•s. )“!D qΉ‚Ž(s£”2v àyyyvAArssaš¦ÒÕÕåëëëËáœçsÎóäðp%ýàýep>çó&J‰pÁ%:»°îGWmþåëzÐIäâˆ=`´Q-Fjä Ï\ Ñ\†>·fÍñÆoHmmmjWW—@6€±òä9³0èx`ü ‰.<ÏåËžœ=ÆÕ¯kªùÝ»»þ ä+[!ŽÉ¯ÇɱýðÐ2ìàwáíó9{²áêf#VŸþùÙJÒN{°¾òþ Ž›¸üÞ¼´8`ÏráÞ{(§Ôy£ ¦›[äk=†7v^ß!”ùϼþÐåŸ}`¡Çæ…-ú¥¦§WŒ—ie³>uŒ!GAJ…Da‹Â[î[ò˜xæé§ÙoræîYzeÊ\{/÷OqìdÊÑÓ-¶— ±³Yü£¸.âwÞ»¨Ãäû`O¼ÜíÜÐÁnÏÄd„ÖÒ,¥Ypü³öÂýŸÐí…èêåíc‡qIÉt}™¹…cÄÙÝ™%VŠ.vD’h²$Á;ÃÙ#žG¨ˆ/<þ.]¾ÄÉãs90ÇûÃMouH~ñ?1è ÊA@<×Nˆ/ýÆeþöç¦z;^‚œ³¥n½€P—¿ü‡4EE9S {àýÏ-œ<ó3Ÿ%Nb^õöâÄÃgØÙXE5#’ÖÆi4¯:X=K„DA@œdÂÒŠáèbÄñ“§8zôÝÙ6ö™O3×Y@êˆõÕçx~>óÜ÷æIlX8ŽŽ¹DwþÝNB«ÇâAEyJ”Ψl^}íW^ÛzÙ¡ý_ @ÈÝžOB’¬EuHÓ.IÜ%ŽR6–¿¢Ò…““™9꯳½¶Î±ÓwQörz«k$~Än‡¹™9¨§d‘¡DE3´[IÆ-ÒС€Có-æšóè¤C:{†³gá çWøÔÿ|Š×->Ç£÷×èp‰#GŽS–àd¸åŽr²v{&›sÿò¯ @]N¸ùÜÿÁ5–¯æw(‹ùh›|°Ae¿9wüÞ&gõ™eæŽ,à‚šÁ8gu´Á³SËŠc§Q +Ašµ©eJíj¼ÐHÑî,0ßXZ<È;_·Èß<ô G:©jæ›süóŸñž‡ëEÈÕ‰`ÝFØd‘ÑÈqð°¤ÞlT(Þ÷ó¤í—à¯t­C„("T€w`kƒ·–þÆ…àø™7~ Ž6®­0Ùésøìb2¤×¢7¯pr±Kœ¤>¤ßÔTeÁÚVÍx<"—#ÊÊ Â!+[›ÌÌGôV'È&¥N‡Ü|“ N[äæFÁ—V*²L@ ézg[ôW·€)*J²™=;Þù0ðk· À³îVÕ˜ ȸ~á ÒlžóŸý(:H0Ö€«hÊéûû;[Jf1;k=Nœ¹ ‰¤¨Ö7ÖpÕ¥îQ²ND–j6{:2Ãc½€qoH¡ rW3Ýìqz1ááŽ&NÁLŠZ ñ@€t¨0ç°ôtvï4L&.Ê0*¤. ºgظYg)ùå¿u4üŸZ­›—à;›À^hí=)ñ΀’8[âl5¶WŸóÇ^óOÓl†õ§¿ÂÊ×þœI±ÊhýU•³¹³FÖ§j¡4–ÒÑ$ ›“†^> ®K\éØéo¡B ‘Ä‹ÁR”‚qíWžI#QÂN¿dÔTŒjÇØy¢P’A1€Ph'1¹¥µØ çºâ-/Õ¾€»_Ä N»è "Šg ÂAÔÆ6Ó“éìá0=²@0s‚ù»N¶ÚŒ·ÖYyö7¾ñ4Ýù¤ñG›†PiÚqJQŠQŸ|2%ŸŒYße «Q>Â*†øÚ ‚pHB”V„Bë?u ú Ã 0¼€8ÿ¥ø–&à½GA1Ù&ˆ;\úòÒj-ð…Çþ:Œ(¬)Qq÷_ë4¡®sýÉKÌë ¤dîè!r :ƒ4i!Hjk:DIÅæ¨¡œZÊFSž|Ø£)’ ¤ ZK¤µ ®©” ZH¤kP^R»’H'¨Ù S” nkv¶*ÚiLk†wüô]1Ÿ¼Z¾<Øÿõu˜¡tHšÌ“µ:ELL`%[›—E»³ø¨rž:/÷6é,FììlÃxÈõÕ0ßh¨¡` ¾.Qº!¢ÁÉ„›k#Š&UEÜJilƒ'õ‹]^€ó çÖy´ 0Á9ÉxãÉ„¤Æ„òˆ(k«ÀÅ/žû0è=®FjG Qè ´CMê0™?˜rLkƒr\EŠ’q½ÍöÚ f桽´€l…¨V›0Ž1*@;Aí$›7&,OÑmé­ZJ¢„FyT€ŠBî¦Y4X ÒìuNJÐ!hIœîº}UÄQˆi,UmP•Dò% ‡ßuôÞsŒò?ɹ¸“å g³w§A*œ+Üì¡»1m˜ÖRÃqA§å5*ÐÌ-bFa3mÊö]œ>v™w¿íÞõèiÎþBµ:àh2E&Q(w/Ê©ÆáCO¤”“SäL#\YÒŒJªLéqÎâ¥ÀZPJ aü°u[¸…­KN};ןæÕ'OPöÖñÂñÙËÕ-å5'f-ÕVŸ(jllÀÔPyoÈÒtî:J5²ã|yÁ¹'nò'Á=};Z'„.bjiK°}£‡Û#ÏB;f:ñtJWf·Ó4ge•£ÃjœcLM‘”M…´[[F\ËaeèÙ‘’¶7´]Iì8 cÎÿé¿û`Ü=l_¹L£sz#ñ(¤[åN a§àìh¬Çº†ÂV˜©d<­ñÞRâQçÒ15È,f²3!mKêPS5c,q4Æ5E]` Ñ9“iCUÖԕဖƒºhPIÀdÇ¡3É¥oœÿŦ.þq&Žÿ×¾#…ü݆A±·É=@>mÏrî³{ÏŸ|ü·ÞLèç=¶×{Ô²&/{¬ Ç\/r®ß˜°˜ÀB4Ç|$H¤'u%ÎL¨&}ª¢ t5Ãþ”þ$g­7b<Í)z5½AÍpXÑNér¦“†ÑxL5ÉƘÒ1çÔy¯<ÞY¼q ô§0.-óçñ:äÚs£¹ßÿ7øåo³uÛ·ñ[<@ðbþœó^JaVW׃•óÿÝkçþä—ŽÝû k7¯ÓšY»0$iIÆÃ’rÒ`µ¦ö’2O_ê!ÄϱùŒfX³Ø2„ÊÓñšZ6ãdªA™1‘(Ɉ‰/ ŽÝŒ1%LÇdZÓOÙªkƒ Umõ S ˜@˜Z¤hH[’éÀÒ“üñø·µ¶ÌîûÑ_üH»Û6sY¨Û3³>ËbE©bwnPx飼ÚGyåÊ•`s«gŸ½¸,2wí'ÈçþKˆÉBÂD±ú œÿÂê œzÝM©(§9:Ò(çxìóüÝŸ<ÁÈ6¬ -•s¬_Ÿ ZuUã½ÂIr@€%ÐëÛ3¿íÕžª80D€Äa+K»¢KK a<.¹|î…CD1Ã4÷$R³80)¦DÝÅóé=ïüõ sâÉùÙLÏÍtìCëC‡9½±±!¾øÅ/É«W®Ä7×nFÏ]]/¦£Í¥Gj}ìUÌ=:-RʲÄ5æks3]úñ˜Õ«;$‘V9úk#rë§´“˜0µdaÂÀZZ³“ª'1Òã—ÆÄèØ¢‡ŠÙP"U„HcÄ8*´˜ÊSkA * JzúCÈ•@ãUm•âÔ‰ŒV+d´ièD!Â_[?û_ßJîúÏÏE÷|$ÈfntÝ £hª¢( ¿vî«Ù¥ç_h_|îz3LÞùKoŸûL·¸ñ€É:4eM>°úô ú;¨–céX‡V3VlîLÈók-ÓaÍå>œšWT^±Ó¯5 këc¬‡ª¦ÎFÓ’ª2(éhŒAxËpâˆCA]×L½¥.EÝPYÏ´vLKǨöx0mªÊQ˜:ÏY Š˜k…\Jˆ BÐîh<`«¬ª¸Þ|mTßü骴ÅN<7ô…^]¹• ¦µ½î.ñk?õÖ#ÔQ¢6›œ Ï`ÉØ^u=íyM1©ØÞ¬¨*Ãâ|Fk®oLYY)Ø™€t ¤d<ª)ª _ *#ÙTxï)PTÎìf—¼Ç¥g8°TNîN‡;Àû½œh<Æ:lå)h0fwzΖ»-DYXŒ 3í˜@J¤RH!h<´fCÂÌS-R¶‰(–š§>œšúp5óªê£'î¶EÅàUå×ÿÉß×ýUY0™LJ¶WJp}fΠ[cjÖ8œÛV`6 PMAÕÀl%¸¶>¦iyðÄ}—Û­N%òé8ø½ß|ÓJ·Œ‡ŽíÕ’Ž$J%ùdBQyšIAQ”TÆ1ž” 7eI'rÇΞ؞?û¶güÌÝ“rT¦ØA§*먨LT7UPTµ.Ê*lŒ låDÙTÒ8ë•3Uí>ðV!¥b«2 cGá$Œ#™aEA•DQ'Q†a¥UXDI4 ƒpzªCÇA<£pFé0L²~¥ƒ( &qçIšæIMã$):YdÇÇa€ ”ÑQˆ ×.|ñ3[LІ›c&#C3q”§)I+ô‡ž¼ùÑ×?}Ï<úù£÷>ò¤Lçʺ¨ºe¾=gš&vIóÞk×Ôqã]à¬Õ®vÊ+§­³J§ Î"´Þ9%%¡ZX%q l"¤QQdíéu#ƒ Ö*,•¹…E‡…–LR5^É" ¢BhQZU:j)UA­µtƒVî&,·ÛаÂ{Ïêó“sŸþo2¾ò~f4,[µnñðÝ[ KG_¸çµo¼tøÄ=yü¾‡žÒÎ ¥´ïYpζ=^ !¤w„xxv—sXí^8O$…·Þ)-„^zœõ^* ÎHðV¤ 8¥DíýnŸ)V U{ᜲò^!°Bˆj·×À|Û¶×›¼Xîï{ÀÇ"©º,’@xï‚(5ß)* ö椽ޣì…˜jo?ôÔ{/R·DšÑžbûa¸Ú+÷•jn Wë[¢Ss‹û†úo+Ù¯çœEé„nïºsÎyg,: üÞ¹ÿï*1iŒ•Z+ï½ßWTÂ;‡±^*-’RrïYBa½÷Z±jË=¥÷ ¾5ì6ûç¼÷ðb79¹¯¤÷»v{×Ü-:Û½<¦¿usÎ:ï½PJïW|Ñà[Žy)ö Þ¿I:ëR¼˜@½µŽ÷^ !„÷~?Ã,„–oýæð{u½Bí•ûsû™é½r¿.·Ê>LëJÊ}·{«ü•ÞÖ:Á[ïØÜÚf~n–ª6¤Iôâynù¸ºeÿÖs|—z·ÊÞº´½G8çèmXXš»õÞÛ7à•?Nþ€Ë+î´wZ^p§¸ÓòàÿÏ%ºÉf¨ÉIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/agt_utilities.png000077500000000000000000000416711217176075400245770ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœìw€•Õ™ÿ?ç¼å–¹s§3L¡ M@ElQLLQS5Å˜âÆ˜d5«é»›üv³IT,ÑhLÄTM]Kì†D (ÒËÓ{o·¼õüþxï }w÷«/fî}ï9ïùž§ç£ªªjæ»Þõ®ü‚‚ÂH4•š¦!¥Ä÷}<ÏÃqúûû¬tOOOSiiéöd2¹¥¦¦æeÏóÖ%“É^Ó4ßèîÇH€)S¦\üøãO<¸fÍ‹cÑè—‡“É '»ao$”R¤R)rrr,Y²äÚ .xËå³fÍ,ÏËË'Ë:Ìg@ˆý2)„€`îÀÀЕ}}½ìÙ³»ýå—_~rëÖ­?q]w8ðC¯;ÄÑÄé”)S.~ìÑG?{Μ\€'|ðŽÛïøös«þz§ïû£²þŠ ÈÏÏ'N—yæ™ÿþ¾÷½ÿcsæÌ ›¦‘ù}@Žãý~!RвzõšÁ»îºó"Ïó^‘òÄM±?üácúÜ%Àk_)Ų‹/ŽOŸ1ãÖýð‡ï,ÌÏ¿©»·÷Œ4ð<!ÄyŸýìgú¶·]2#2ñ}p]ÿ„î«”ÂóÒ!Ñ4ÈËË‹çææL³mg\0V–3««ßñø_þò›™³fåîÿs×qÈÉÉásÿüù·Ìš={Õ’Å‹¿ýÒºußÏŽÅl)ÇÇ y#àº.Ñhtþç>÷¹‡—-[–§Ô‰ük!¥DJxå•WÒ·ß~ûµ ÉTJq²UÄa PYY¹ðµƒ/„@H €bÑâÅñ’’’[û›ß¾ç/ÿåf;m­=©­=If¨»òÊ+W.[¶,Ï÷u0žR"¬ZµªóÎ;ïühww÷3ápøˆmÒuÏóƵµëp¿xæÙgoû÷ý×'^ûsM“HM ò øèG¯Zzà 7üuFuõ·|Ï;|¯NQX–Å‚óo¼âŠ+Ï€ñ|M“ø¾ÇÃÿyÏÏþóKŸ …B‡}¿çyäääpÆg ¥l]—¤Ó6¿ùÍ/×?öØ_®ŒÇãõ†aÖPB`áp˜×ÃU<¢õa9vÓçþùs×íÙ½ÇÙ¿.“ ¤@× Çexx˜3.ü¸¢ÈÆëò÷$ÍÛ¶9óÌ3¯_¼xIŽÊ¨¶ñ‚®K†‡Ü{ï=ýìg?‡¦iõGÒùBâñ8¦iâûþIù#8ªùÙØÔôÄ_øÂw’ÉDÐH)д}RÀÐ lË¢µ­•¢â"Î;ïüÂêéÓ?h¦iŽÛ2Cûˆ7NWf¶]|ñʼnFÃøþø~ww·ÝvëŠ?þñ0 £çhŸ”’H$2î*èˆí<–7ýå©'ÿë?ÿãÛ‹¾û½ï¾Cˆ€RJ ]Çó=z{z(.*&à8ïxÇ;?ñç?üé~ÝÐÝñpq”RhšF8W«Ø¶m¦NöÞÙ³çLH&SI/+‚ç#¨««çÇ?þÑw·lÙòu]×9Öçðz/Ï”RŽi×-:káê÷¾ÿýšÔ Õ÷éï룸d‘H4’ X¶ì¢3Ÿxüñe;w×<5ž5"!&Mš4n&×u™?Þ¥BHz{ûÈËË#1Ö1ümÛ¶»·ÞzËûûûF:âgb±ÃÃÃcìʼná˜×lÇiª,¯¸nFuõÃsæÎ5†††())%’•…Rþ¨ú,™0O}úÚO=ûì³OvÆçCÖ4T:E2™) ”Â0Œœ)S¦žÝÛ×aèHMCˆ\B!ó¸g∿víÚÛo¿ýÓmmm¿«¨¨8¢8÷}ŸÜÜ\ŽF’“‰ãZ llnzâ—\ò+W~3™LRRRB^n.^Æ`‰‡;¶Í¬ê™ïÏ‹çܤëÚíÝHÁñª[]ש«¯ã™¿>‡®Ÿø"¦çyÄb±99¹9½}½D£Q„H!ÈÉÉÁ4š¸jÏ<ólÓÝwßýñÞÞÞUGóñG „xÝÅþþ8î'ùäÓOÿׇ>ô¡üë®»îÓ—_~y(tˆŽþcã&¶oÚ,ÂÑèrÍÐAp c³ŠŠ)--¥¡¡á„IàyJ‘ëûÈÁÁa”¯B®­ääæ`èG_wRbÛ6?üß[{ìÑ«‰Ä–ùoB|ß'++ Û¶I&“'Ô‡ñÀq?E¥”\Ÿ“ý‹¿­Zõ•Ï|ös8sᙼ§ °ˆ²Š ÚZ[1áÐ$ „à´9sÈËË;aø¾O<÷Ç!‘Î,Ö„£®n<G׵Ò5x¿âøýŽxàÒ²²²FÓ4±,ëïUJÑÞÞN,;ª¥ïûþ¨+ø†‚ކ¡¡—+¦Oööâã7½ç=ﹸfûNÞúŽK˜V=ÝÐXûâÚZZÆ®ë2¡xy8ŽsB¶€ïûÄbYá‘¥_]ÓbdP%D<ž¦šR ºººxê©§¾mF£ã8„n_;x‰D‚ááab±ØQû©ëú²p8|†®ë+t]ïsG‚V¦»÷îyx²¢¤ô+nÚþÞ 7}‘o¾‰ÉS¦ðÒ‹«im?IàyV*E{WW°¼:ÆÉH€œÂ‰e•Xi C7`”™+C‚ìx6š}•Ð××ëtvvlµm‡T*•ùy0Û»»»@M$RGu-Ëbâĉ7~êSŸºµ¬¬ÌhkksÚÚÚî»çP·»&“É[Ü”å~ÿŽ;—Üp Öк¿$`ì$PJD‰†#$ÓI¤[œad¦û¾GÚ²ÐrâŸý@ ²³c‡ŒËG"D¡ëº¥wù¾]׉F³°¬ôû•N§õ9sæÜöáøÆ3Ï<“ÁÁA"‘Hu{{;G2*OãFMÓ¦q{*™äû·ß¹7|i„‚—V¯¦µ¹S°\j'F!9ñ8ÉTOyŽ_ŒèX×uq˶œý™K"ï@ŠL6Ðߥëº0M3t(Œ´u„Gj‹ëºùK—.]ñ‰O|â=S§NE)5ò9s$ry20îrÅ0ŒÛS©$ß¿ãÎå ¸ñK71yJ/­l‚PH,'xXc"ïû„C! òóñÇh )¥ˆF£$“i\×Á¶ ‘Dæ 3=R=0%LÓtN?ýôÜL2Ék~§ÑÝÝÍÎ;ÛÏóð›îžžcÞkgY–^_×ÚÑ=úÀƒ­’Ð) ×w©ž1’âbž|êjkkco½xÙ¬~qÍ7/YÚ2þü«ŸŸÏ?ýÓ§¾Q__¿½©©é7±X ǶɎÇ/9mÞü•žëOÔu ßó‘Úáçž”’D"ÁŽ;þî8Î`$9¦>¯+` ~p×]ËAñ/_þÒkHpüêÀ÷…ù¦yÌÖ²çy†®ëE#>7d¢Ê¾"ÈETŽB!˜7wYÑ»÷Ö¡—¼uÙÙ1šÛ:«ÿíë_ÿí­Ëo;æ¬Ù“¤TWÏàú믿ï–ïݲÃuÝWË++¯=çœóîB @Æ¿—‡–G ¥¤¶¶–;vö±Üš]{Ú~rÿýÿ648è 'ð}Å{ßûž3Ï?ÿ¼[×­} ÇqФš®¡Á¥Ó4ššþö·¿Ý"„8üâÁ8á ‘#Ø_(¥¸é+_$ñš…X.ŽaíÀu]ÊJK™3{6ÉT*óÀ ß÷‰ggOÔ4Íp™Y©;à=™kºÖ™N&jZê¿‘©~¢¯¯ŸáÖæŸ6‡ÂÂûË"þቿ<þ÷§Ÿ~ë’¥ç| ¹¹Ù|òšâ–ï~‡ ë×Q9yJk %ºvèÇ®ë:}}}üéOzº­­í×㑤z4¼áBF$Á½ß¿›Ûo¹5“'³äœ¥”W”cYÖ±K!˜3sFC?쥔¢°¨pší¸(Y8¾ïŽ„QÐY_[ÇŽÍ›v6Ô××>¿z µ{wS5¹’öÎ.‘0×~úíÒw¿{Ú¶»¾U[»÷g‰ÄƒƒCð©k¯¥··‡¦¦ÆQïCÓåk÷’£iŽãðÔSOµ­[·î³º®¿.¹áo¨Áˆ$¸÷®»—£à¦¯|‰Êɓ֮~‘æ¦fB!–KMÀòÃÝg$ôÚÔÔD"‘8¬ïœJ¥¨ªªšîyÞ¾D‚Y?"|ß§¨°€¡ÁÁ-sçÆ“?^ŸL[ó»:;W”\ÙÙÕCgwç³”P(BSK{e(ú/¿¼ásñxö…9YIõÌ™|ôccåŠääæcèšÔðÔ¾ñ).±jÕ*û¡‡ú'˲jÇ«rÈÑpJ2$H§úïýþÝ÷2oúÊ—©˜<  Ãæ@Ü&¥‘|ýP÷‰¾-Zxµõu‡]žM¥RbòäÉsÓé4†®á¾çR@)ü ‘&–”xCƒƒçåå1¹ªŠþa˲ž…CWö SQVÆY æ±qËVñ<ÿKg/^8Õ0BEýýýxž‡Ô$çž{mm­<üçÿfp`©iønB?5\»v­ýóŸÿüšþþþ“nøíS††a¬H§Sé{¿ÏJPæM_ýÊÁ$€¯IÃ0›uß÷)-)aóÖ-j‰Ö÷}4M›——?¯½£Ã0q=Pø^ÆÿW 3Âv¯``( ñöw¼ƒŸÜ?=]î/òòóûR®·bÖ´)ñÎî|%™7ï4&UVhóævE{Gר'"¥@“’K/7m-­¬~áyN›7—¢¢" °]^xágŊ׼^zhßúÖ·ÆåF·Ýr xþAºí¸¤i[lÛª{õ• —:®£-\´ˆÂâ"â9qèëíCb©Ð´làéÃ܃ֶ6zzzF“>F®t:Í„ .\²ôÜOv÷ô¢P¤•)Ä ™H)4Ó ]è8ö#J& ”–Mdû–­ÞàÐÐöôððù¹ùùÓšZ˜0a‹žNv<ÎÞÚú`ææ« |_‘‹Q=s&ëÖýƒ¦ÆFfTW344Äc=Öð‹_üâ“8‘ÁÿøÇ?>¦Ïr€Øu¯¾²áR×q´…‹QX”!Áàý½}È#`d¦¥µe$©bô²m›¥K—~¥jê´ÓŠ  ày>Ñh”ò²R²c14MÏ÷|ÿ\×qþ0±¼,]^QIÈ4éììØàK½h„â9g-<“–Ö6öì­Ý—DŒpK$‡1uêT^xþygçÎ]µ«V­úå‹/¾øéÁÁÁõš¦Ð‚ÏX pJ©€ýaƯÓé4÷Þ}ÏJæÍ_ý “uð«inlÆPܤõ{PŽãPYQÁÖíÛÈö}Ÿh4:yÉÒ¥ïó}¤x)Äÿ]PXRTTHaAáp¥À¶-r¡¯Ü‡Ò©ôå3gÍL/8}¶e G²²:³cÙlÞ²®®n‚m*0Fu Ó0p×óð•Oww'ýýýÉþÁ­Ù]s¿‚”išèº>šòzã”%$°Ò÷ÝØ7õ«TLš,%³†æÆ&àÐ$8T§eY\|ñÅߨž13·¹µ•ü¼<¢Ñ(©tßõÈŽE G#)3É&ÖÈb ž¯Þê)ÿGÂJ¹°°ðó‘ââÏ75µænظ•Äp‚ÜÜ ò‰Ç³ÉŠFDZmk ¿×íéîè\õ׆­mmmë7oÞü¨ïûÛJKJ±lë¤%z+Ni†ž!ÁV*…ù¥¯~•òI“X‘I`š&E…E´´¶ŒúØ\ùÁ~¢¨¨ˆD2I8d‰F‚ÄPÛ ^]Û¶qÔHvЈXXŽý±I•oI¦¬ÊçW¿Dß……Ì›7—ìXÔnkm}©fgÓšîîî7nܳ`Á‚ŽiÓ¦ 555Ù/¾øbª¸¸x´ôË©‚S§%GÀ ~xÏVÂ~$’µ/¾x Tfݾ¸¨ˆÆ¦Æ?;~ÅWÜsÚܹ:@DÍ‹ 4A*5þ Sœé5mBà8.[wÔT67·¢ë žAV44P»wÏÏžÙ²õM±ìl••••q =Fê$D£Q Ã8iëúcÅ›‚À!ÂüÒ×¾JyeKÎ;—µ/¬¦¹±^C‚ñjY\pÁw?ðþ+Nظ{;š·qZÅ\òbû6hQÁLRXfö 46Ý]= '’±`Þ¶oÛúà®];ÿÃqܶ㠇GùDº× oèû“€ **XrÞ9¬}ƒH i®ëPY9é£×}êºÏÉ0üû 7òÈîßÐÑ1„ÿ¤Á5g|ŠÏ,º[º8\W ëºtu÷¶,¦M­breyꑇÿü庺ú”””‡ß0#îDñ¦"dH`í' ¾þ•Q¼ô4eHà AeEùÍís¾ðÙîΟ˜Ï·_ýi‘âó/f‡óûz‡kO&ÞÔòË0Œ_;–uÍðûÖÿú.‰Ä0e,=ÿ¦LžA"™äþÚïP b’—­§©mªgÏ.ê=zÈ\ÐJáG;É}[oE×$RèøžON<›¹sfñç?ÿñµµµï¿IóÍ`ä oZ 0Ý0~íØ$P`~õß¾NYyÎB—_ÜËÅ‹/&KðRêQ:il¡NÐ:‚Ìm"„Âà™à˜°²ñ·H¡¸vö—ð•bòäI<÷ìÓ+6mÚ|ÛÈàløL$äææ¹§8ÆžçáÙv&“fÄÇuq99¹ 0¥Žç{¿NÛi–ï»÷kJÆ>ùùkù½7ó¶…—0)<™u©gé÷Úéióð„«ÀîjÀQ Ê@‚™¥9ðd÷ƒÌéžËûg]Ë“Ï=ºþÑG½idMaÿþ)çàÍ‚q#@iYÙYYäææŽT\×eÒ¤IãZÚmBÇaÇÎÒÑÙùká3yåøö‹Ñ§¸âÝ`~x »íØj­‡¬\˜`AŸ€Ä9`½ìÛ1*  (þÉÎÔ‹ìÞ{n÷ÿ§OH¡ H¡ñÚ4^¡®íÛÒ|8IzÇ+ÿÎ[œË£”WÒÏ¡k=$ ®œH6deõ¡µ€!`øb^rʳ¡ r'f1#¶˜öÚÎô½?½çÓCöÀv=ª£8xû–¦IjÛö2yòdD°ÒÕ–ij|PbLµ ^OŒŸ p]ÛÆJ§Gg»mY$ úûI§Ç7ÁUJI2™$™HàÛ”UUWýñWwÍ\¸xе‰ÇHÊ~,×&Ò9‡)þbö˜ fÕSZÖƒÞ†ò\(ÖaB6䔇9#ò¢ª€5mÿt§%ÿaŸ>„P#b^à{ÊW„æœU¶lFaô„À­Uxº¤ÐÏÁ—. …°å)+!ÞÔF ¯|ðÈË)Žÿò¾ÛO+‰MÀv<ïäK7Èôy9UW e‘BOy †!8­#l2mQ öP7Û‡_&Î… LpÓ.BI„#Q®By å+|OG*ÅqãMK¥!#dž±èŒ_ü¤í{–Má°>ù$Íõt¶CXƒò™6=‘ݬß‹&ÍdNh>Û{Á/³™>Û&í[„ô8sBRéžÎãCÐÐßJ8œÊ”ù¼ÐÜû„åúäå"JVŸ ~&™$³‰Ty m D™ ô©.¨P„# e$)ÞR@Vvý„ú£h}¦m Lñ†¸•oZ¡˜_ñ÷Äs—v¨¦èe¬MÊ;Jå–ÌCékG‚ ~ħüâRâ¥Ùücs#åY™Z4=H:yƒð¦$@Æ¿¯©³åªõuÿÀ›ÑÆëYj›ê¨o'´$mèLÑæ1iÑvú¶ÀŽAŸ÷Ì™z 7I™˜‰ð%¿ê¼—tq;Ù†£§hH)²¼Añ+3߸TËÖ6IÞXêel/íá&=„+A€ÖÁt'ÁJÀц¥l D}²‹§ê~KloÓ"qºÛÓìÞ• Oå ȸ̱yžnU¦z“ø¾:û÷ìŽ o!°¼±±å¦®î”R §øà¼òîsÎ'Ñ* "„~+ô÷€‘ –‚,¼V˜©b m˜kî¡|w% ÔBf¥æPŽÓÕžb×ÎArT.ÓDf»Èœ42×…SÙÙÝúxr0u•”ÿ3Xð¦ ÀÈà×76ßÔÖÙ…ÂS64 IDAT ßwˆd…ɉðí¥÷ñ¾ .Àë HÀÄàs^S &ÅŸ_ËL7—§”o¾ž½»èxÂašš•!Aí)¶í$®â„tsIàG¬¼¡îÁ_Ù ÷Ùoö¡Sž™ÊÝËë›ojji¥P¾GV$JV4 Û·Ð|“ÿZr?Wœ÷ÜðS &– e9Õ¡ Tpné[™­Îãî=w³±¾žî”M¶•&RùL÷g1;5‡ªHœîö$Ûw£b„´ZÔ Hë¢e» 'ú¿ØÒÔòœï³D¼‰¥Á)O)åò¦æÖ›š›[ƒš}>³b±QÃÉV6Ò3ùÎÙ?æCç_ˆ×2eU›…¥gO\Æ ÞÂ]Ûïçï{k…0†¶Á!ävýíHßgš`J$NG{’­;ú‰©(ai¢G•ã ò\?}Vs}Ã_‡z‡¿%4}3JƒSš#ƒ_Wß4Z›?š!+ãµ§N8ÊFxß=k9o A8ÊC,)»Iât~¸õ'¼¸»]Á@ R¹Ð HP¯í mHå1͛ɜÔ\æD‹H±§q| ÉS¹ÄÍ‘A(ô|GK‡û:»¿Ù¸§þyßUocíê7 §ls5M[ÞÖÞyS]}c&Dê‘•ã5ÛùFá(<ƒï.\ÁÕ‹ÞÍpÒÄO4´µ³üï÷°fC†Âå@’9ÐgB{ÿ ruj+RH„–p–·”9¡ º»lÜÝN˜0QBd1²²5Võƒ-$õA<'ufíî½Ïô ~_JYøzmï>Qœ’qMÓ–wttÝT[×€ç»Ä²"A)Ö£îè(Ó ñóïçcÓwÐîî¥s¸Õ{VÀ`Jß·×Cy ú€aˆï$Ç,&_ŸÀT5aK„)Ø:ØÈ†Ý­œ>}"BxØZ#š&;-‰. #6…‘b-Ñã]ï ù—0EûZaVáŸmñÆîü9N9Œ þî½u™Â‘H„hÖ‘OÙØžrq<ÅÌØ<æé‹ét»©~Û9<Ðp¿Ýü0(,ßr T/ÈÄ0íY5DÜ,ÊôéL³‘ŽD†$[‡êÙPÓÆÂé‰ÈlrK]$ýˆè %\*òJpRÕ{_Ýý'«Üz ;?þﺮ7žŒg58•T€¡IyO0øõø¾c[˜¦9:ó'«P¸Â¡¹«‰†Î:ª&LåݱüXÒÞëÑG p7P)HæC" É:´Í´y{‘¦Ê9,°Îæ4} ƒCì¯i'¢"Ä´rJóÉ/Âè'ÁŽî:¼pšœü(Í MoØÑ¸ª»§û}§ªJ8U`êšö³îÞ¾Ïï©­Çó\l+2ˆÎüã?Ç/‘HÑÒÚFV4ŠnRóš¿j§ÜÿïTƒ4¾–ýIHÅaHzÔ'÷P/7Óæ×"LÑf²À>›Æ4†yig 1?J¶–G^I>yEPÏðÙÜYK›j!¿4Ší¥¦l{ió“ÝÉ{¥y§šËx*ÀÔ4meO_ÿU»÷Öáº.©tÝЃïpß „Àó|š›[Q¾¢° ÏÞºmëg&Lì«.œïó’r¸\ Ѱ? pa0 ©( (ÚÔnêÅÚ½Z4 Sµ™,pÎf¡YÍÀð/mo!Ç‹‘¥å“7±€üâ ¥,œ»:;¨éÙKNQˆ¬œ0}íÝŸkßÞö´ïy O%iðFÀÔu}eo_ÿU»jöb¥-’‰! Ý :±?!íô÷RZRLSSã­Û¶o[UUÀÌx5Ê›°¸B Ò¿? <-HDaÐw©Mï¤^n¦Ý­GJÉT} ܳYžEïP//no&ÛÏ"ª’SZH~dCN>4%úy¥m;2/Mnq6éTráËÿXÿtcsÃU§Êá7²¦¦i+»º{®Ú½·˲H a†ŒÑƒƲB¦IÉÀà-­mL(.Ä÷œî¼óÎo'“ILboI L\A`=i>üž MW€§A $öZÛ‘! éj”šS™ÂL¤#Тë’ÛX½]±dvRËE+@W&" ¯+ÉKuÛ9«tE¥ùôvämY³ñW9󦹯·ÞèàÑ%LMÓVvtt3?•fppÝN×zmÝžcÅH¦p}]š¦Q\TØßÑÑñ¥”uÀÁKûß[ñ°JòT \/xM¸È‚^Ça·½5NšLÑf³À_ÄâÈ\ý¬ÝÑ@–&¢ç’SZ@a!äeAn!8šÏ‹µÛérZ)šÇÈô4v³©¹ùG®òÌ72µü¦®i+Û;º®ÚS[m; ôc˜&ÑH„±8Rß¿©¥•d2ÉœÙ3iooûÆðððö«¯¾¥1#ÆÊ]?e÷ž½0R‰-øºï¨ç ¸P °$¤j@jàŸ Ä@ Ûìf 2"‘¾F©1•Iþlð4dT²6¹…—v6±hV9BÏG+S(™9ïQÀ€P¬«ßËi“ÒT•NAêivîÚöißñ²Î_tÁ5RJûDʾ¯7LMÊ•­íWÕÕ7`Yiúûû0 “H$2æcÛ!°úûúúéèèdReŽmý¹¶¶ö>`´^`J¥˜JH3p|gŸøØØ|ÅKBk·É$ªü`ˆHS#6!"éHJ©TÉj¤+‘a5©M¬ÝÕÄYÕåDµ|üR ª{4ð4lªoÁ*·™]4 M“ì®ßy•‚sžw”ÒV™Sµ_¯‘ד¦¦É•MÍmW546cY=½=„Báè‰Õ×B’¶lš[Z‰Ç³)ÈÏiyùå—¿ÐÞÞ~@9Mh« ˜JÇrœ×fáîRÿ.án,qPX-0ð ˆ·ƒ†ÓÀ&dD"\³Š*£\‰ ^Jndý®ͨ$¦åA) ºG›v6tá¥|N«˜‹Ð${êw^eFLžvÖ'|ßwAŸ^=¯ „M“?mjnûÈÈàwwua„L"áhÆÓ£èаÑÖÖŽã¸,ÿ¡'—¯\®ŠuDÈÆ‘Z XÍ0øp)¨t '€W!‰DRbLaŠ^ô°6õ*ëkZX4£¡ J‚îÑâÔ{:{°¬­œU}B@WKûõ2*Ñœ¬¯¿éU€çy„B¡Üâââ‡vï­[CS ©T*|à ”©Ãw"R’J¥éè袰 Ÿx,VóëgžùêŽ;ˆÇã•m\ÝE¹G45wâòŸBq+1  ˜œé&àQï&pSÃñ*"lô(1§P¥ÍG …k’X_ÓÌYÓ+ZªPûÔš:û»·²hæ|Ð,ºë;¾‹ewËò’;^D'…žç!¥Ì}ÛÛÞöûhVüↆ zw{{¡PˆP(<¶Ï~<_ÑÙÙ”’ò²RgÛ¶­Ÿ)((è[ºté! E‡´0kûVc÷»È#ã”âû*Á{¥` qÀ H •gÔÁà.™DŠ—! ®d¢9…*1 a Áêô+¬ßÝÄÙÓ+ cº÷û2hìê%\¿•yÓæ2ŒECMí­…‘ÂÖ‚¢¢}×?©á¸`ÿÁçä_\ߨÄpb˜Ö–¡0!34.BÐ×ßO"‘dú´)ÔÕí]^SS³*;;›¹sçò3Q#Ê®; đⱕÏjˆ¿ 01dJʤšG€Ë@D@¥‡@¼ ¦@Z’’ÐTªÌ™;øÜêÔþQÓÄY3*ÈÒóa"ø¢;h€€šö.„¾…ùUsè²µmÛ7þ(ëô¬Ž¼Xþ*å«“fŽ+2Õ¹ü¡!š› …˜ãTZEHI2•¢§§’’ (ß[÷ÃÞÿÿ,Ë:â~}]Ôh»@ã¨5…binQý|-h $AªÔ# .€5âe„!6”†¦QeΔ)Xm½Âúš&ΚQŽØOˆÎ})»Zº eïbÆ„ uXñ ;_úeÙi•›j UÑI1ǵ@{É%—b?3ø ˜fÓ °Ø@€çzôôôDÈÏ'|ð·ŸM$–Rêˆûë<ÏÇËõ ‡cÛ©ës½¼“^΢”HŽXMÐÿ0¨w!é~¤Xl´ 4<*1 lÀ¬I¿ÌºÝ$ˆiyˆR¢ •‘ ØRÓF؈PYRÉpWª¬½®ù7Å3&\¬ ½ßWã¯ÆRʼK/½ôwÙñÜ‹këH&46Ô£ëfÈŸfgƶ¿Û¶9mî,Ö¼øÂ¿=óÌ3"‘ÈQ7W %QéLKŽ¥AŠ„²ù¼pù;’0ùÄÌ #²"ð.Bà'û!²,±OX€éóRêÖílfñÌrЂ¦ˆndGæ+¼²£–È|ƒ¢ %$º’g¶´4üT•ºWDeL…+ Æ¥\ü\`^{íµΜ5çíuuM$SIöÖîEJp8Aj72ó*äÈ« NäÁ«Ì¼ )3ß÷)º¦‘N[ô÷PYQN_ÏÓ^}õó¦i’››K^^¹¹¹‡½ Šèsziïé@X@ú(—(Z„Àå"dPQ €z œðÚ@›l+MZö¢ ‰á‡È1Šˆ‹|L7„aøÔZtö'™”Ÿ‹¦EY I"lð5p}ho루4J,;›þ¾¾Ùi=©åfç¯2•‰ŸqŸ÷ý·´ðü1Ý K€sÏ=7tõÕW¯˜¿àôKkv×b;6µuµ(_a†ƒo<Ì!ŽëÒ?0H<'6ºŸzòoŸK¥Rª¼¼ü˜îÖÃÔX;¡ã깂[„ÇùôñV%@ä°Oì§ ¼B@²YF0«KBS˜lÎ[!Bе© ¬ßÕ¢ê‰Äµü}Á¢)×í³nçÎY¨ÉËc¸wø_“Y‰-±HöïÆS œ0ÞûÞ÷Þ³øì%WÕìrøjkk±,›Ø~yû' •††’ jr¿ýõ¯¾ø·¿ÿ}ïþeÛŽC´YmcYu”Çu"Áó@¹/‚P1û¼ƒŠ N ‘± Hõ#XÌQKeÂÆ3Á¨¬Noà5ÍœU]N¶V€*UÑ;:aú»¶ìfé™óÐDˆÝ;ï÷ÊímÅÚÄmžƒð„ð½ï}ï;oû;¯Ý[Û(êë$6ŽU4GNôJ¦,R©4S§NfÝ?ÖþêåW^ù•ÈÔñ=ö{ <×,óãKuÀ§<,$† ² H‰`d¼?=€Ïz@¡lŸ£ŠIÆ ”ã㙊¤_e]M#gL¯ . Ð7:yz;SlÚ¶‹…§ÏÁî±ò:{;QXTr‘@¨qˆÙøÌg>ó™+®¸ò{Í­ø¾¢µµ…¶ÖV¢Ñ¬QÝ-¤ 0SvUˬÉ— %žï3<œ ¨ ŸhĬyà®ìììLš¦yÄó_{éR§Ûë¦ßík9–=Ê%!\.AZ` 3º•\DÀil9=° œ´EZt£Iî‡ÉÖr‰‹|Ân]÷hH·Ð1œdb~6¦ŒB–B’F8Á½;ºÒȘÅIJb†‡¥®p‹â¡œG„%Ź©Cc"Àûßÿ¾·}êS×>Ð70¤Û¶Coo{÷î!ŽeÒ¥ ¬d)…LÂ!ÃÐGƒr”G&€–!P2™Â4 &:=ôàUÍÍÍ[}ß?®’*ZætP˱èQ=Œ5ïÅZ|ò„ËÙ‘@€Ðö‘Àmm*;m“’=è "[æ˜4¥[èJ$™˜Ç”QD†ÒOBc}‚¢0yù9 $ÏëÑæˆy5Šó –©;Ç­.¼ðŠ믿á§>2”H$I¥RìÞ³Ý0FïÊW“¢‚¼ºH8´B6(EÄ÷ÕE¶í|ÊrÜÐ1=~iËÆõ|¦T•³úÅç—¿ð‹φB¡c.Ð(„À0 ººº¨¯¯gxp*"`Qhl¸Y¥)pdVøbê`ÄE,«ž.ÒC࿌oúø¾Ï½ŠÉúô`mÂP¼<¼‰Ww·púô2²eb@°\X·±†eËB„ssiLÕ.Wºz).âÛND—Xºt©¸üòË6gÎüÅ­íí(¥Ø¶};Ží‡‚B¦Iyé„¿G¡K•Rö;„†öw!Ä»<_eÉ#I€Œè·Ò6eeikiþÇ<ð ]×½£ þ¨ÊÑ4,Ë¢¾¾ž;w’J¥ð|ÕO°Èe¬‚ÀÃc óP ! dœVp:AV&Xi›Ýèh~ˆ˜Ì%Wäaº&Rs©·ZéN01?=# itÚ“ŠþAfT”ãI?ìzî™9ZÞ/ï‚‚KÆÔ‘ã"À3Ï<ýž+?ø¡oµµw"… ¶¶–žîn"Ñhf AqQ~,+z©ïû ‡¸M£¦É~ås¹RÁÉ™‡"€m»dÇbIJ"ƒ?[¹â}ýýý­GJ©Ö4mô| €®®.6mÚDOOÏÁoÂ'DýIàs:@· ¼® ©c9¤T7RSèžILË%W`º!¤æÐ”j£w8IIÆ&Y M¤Q.´v»H™dJi /Q®@‹ŠØso#ŽY¼ë]ï’—^vÙuž”€M¥R´µ¶r@étš®‘>ª”¿÷p÷𠦋oúŽ*?äÃWàzš””—•ð³•?ýZmmíæh4zÈûH„®®.úûûikkC)uäS<¨úL{ò`ŒavÅ5X(ù¨Ê¤±ºˆd¼ƒÒŒwð4ˆ·CG*‰ÏTÈG9>%ZUÚtp}”î³qp›v·0z)YuPâôa{°­¹“’x+E“Ix}7Gˆ> ‘Õ/>ÿ‡W_ÝxßAÙ=#–}æÌ½Í›7³iÓ&‚S¿Žå— TÁ€i‡¹‡K Ò5ËzA ì3ЂûŠh@» úŸ†!’QèJ§Ùim¤Nl ÕÛ§J›Á|g!óŒ™ [lÚÛ Ê#* È/É¥4òBðâ®- Ù‹"#ÍÐo®¹æÐ³ã(8f °k×.{Ö¬Y{æÍ?cfo_?999IJ³I[š&xBJ©’CÛ7¦RªäP³_©`Ѧ¨¨€¡¾Ú?þñO_°øGîmÛ6---477ýÌžIäЃ,@äLIðÄ<VŠ/a1€à?•åç"œI`·ÀÀS$ ºi|µ Ïôñ]Ÿ‰úT&i3ðm_WlÚÉæÚVN›RJ–Y@NyÏO“D–&!€˜å¡*€]ÇÛýc–=ö˜úÛßþöÛ¬hÃ00 ƒI“&e*wí{Xžç‘J§/Ó4-ï€\üq©ë©ª‘ÏŒBˆF#dEBÎï÷»Ï¸®Û>¢÷_;ã×®]K]]݉ؤ@u€j?ÄÕþ𷃪 þ=:»nû·±¸Ž}AV1(@ÂdÒËìæ€C6¤² 7m³+½…Z^¥ÅÙÀ¥J«f³ÓÄ ƒ6[ëÛÐ}E(œEþ¤(çLGŽÌÃV ´¤lK×+(Z[[ûûõëÿ±fRe¶m“ŸŸOII ¾·O*ƒÃ•BpÁJùBÌp}u›ãº¯Éq¼”—•òôÓOݲeëÖgF_×u|ßgÏž=¬]»–îîî‘%è“ð@ jWðŠËj"³¤ûcl® I2ÀHHȨ«Ÿ„! ’1è³mjRÛØ+^¥Å­AáR¥Í`}&s˜Âp¿ESOa¡1Á¬D—!Ò &LB ®ºgƇÇҵ㊬Y³Æ¹ôÒK¿8kÖìç B}½}T”—“N§BA”/•²N}(';Vª”Ÿïû›D„” ©ýK2, ¤†͆Ф†ïäÊR^yeý_Ÿyæ™o‡ÃáÑØBww7 ôööŽ¥Ÿã 7#º3êAQÀèf —‹Iò+sP r òGÖ2$xÄ% ²A :ìöwàG<<×e¢6ƒÉb&¾­HûÉt/…¢WùX “¯&¢£ÑOë_ÆÚq8=}$|ö³Ÿ½þúnüþž½u¤ÓÁù·{÷î!J£RjH)Èɉ“Ã4ô4Íu]#•²ð•B×5¤¦¡Ia˜èšAAa>øNÛwÞyîððpm$¡««‹†††C»r§t…@1ÉhE:?%ÂÛÉÊxY™÷» à·A¨rÞ ±0D‡ .4¦dMc²·€2}¾#iŠìAŸå4ûT½DÉ£Rͧ‰ÝÛêÄö³þ{úÞ1È0&Üvë­÷\þž÷}~ÇÎÇ öäÕדJ¥0LMJÈcŒRœ›«é¿.5‰®i„B¢ÑEyê¾ûî}Ossó#®ëÒÒÒB}}ýaÉS#DÈ5CÀ-„¹Èû£*~;˜es1d‡!’!AUÖ&Û§QŸEAu)Íæ.züftBÄ)4Vɇ®!æÿì‘’¶±6wlxø‘Gþ%ç½÷}¸ê• A)ªªªhjn=KGËDú‚ úŠ$Î0CèºNÙÄ{ô‘[öìÙóHGGljYöo$2êv D™°D\ݨ\¶‘àv²%Þ RÌdQà >,â §<ê{¹‚¼ê c "n-ü …òCCX2: &SÙµë…/Ÿ9sæoèÌŽ‚Ž«¥ûiþ &\2#›÷q£Ö &®SB¢W7¾#™½(båК:ª€¹Òz,}ùW€áÈ)àÁ59µÝ±Ü|“ˆßýõÝ»¿ù9Žr˜ø>t“ÀÓ#ôbå$”\g±² 9»°³ó¼K‚f ï’¿kZŒ¢¨ID:Š"=<oJ¥’)‹²iÓ&344Ô1kµÍÏÏóåË—)IŠã˜¢(â+W®3sÇLDdŒi+¤µ¶7ÍÆåÔeI`ÉaAbfw3U¬2"b¢(2ÆmZ'IŒRJc€Î£µÖ¢”Òq›¬q€X² c.Š—ïkÌÎÎbëÖ­˜˜è=X³mÛ68pišR’$tîÜ9RJqÇ”$ U*®×ëœ$ )¥,.¬”"c Q»i­ÛyK–LÚ(ÃÉÖ­‹Ú«xfÖD¤›Í¦ÅLŒ1FD´RÊ0ZkafËå,FFD$«·X×àš4¾Iè›<Ê+Wè5”W2îiÀ]Í»å~Þ7 ]Ó'd&†ÈÐ#عs'jµÎ9nÞ¼lýCx/.!“Ùâá㦼ò~8ùÓ¯,6ÆK‡0 a4 BßþdçúJ…”ô[é@ð³¦KÈÖu¯ô*iËoH¨T*]ÇØŠÅ¢[ݯáCþ»A!Tæbä~!x…ü)A„\Á>8¡CçâÔ™ìÆm¬ÑKŸî2¿Ñ) |?G‡ûÝÝ•‘…?Öæ’*t˜Œ½ëìµ.VnÇiÊÜ;!|üŽêín¹—ø°7JNl•s½`¾WÌÏ»7ÏkÉù  —P¡9¼ßP>¨Ìo€¡¸ßábdõôÓìåûáæºnðÛ’:ä´îñë@üÝÀ>Ç"{ênf¯ ä+ï'!?ÿBöúú½ð·*7Â#TÞï3ýöÄ+ xF¡¸«þ#m{2¨ao§Ünÿ–;Ó‚1º/‰ú¤7Ì’ÿ)œnêTð=ùÿ“{¸Ëåîr¹G€»\þ 5@Ýôžœ»IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/autostart.png000077500000000000000000000305201217176075400237460ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½I%É™˜÷¹Çòâí[î[íkïÝèn4– 1ë£ÑŒ‰:ÐŒf<ð ‹L"eue†“ÌÄÍtÀA¤ÑlÆ@Šœ!g0ƒÁÂÝèFoU½Ö’µgeå¾½="Üuðˆxïe¾¬ÊZºª•¿Õ«|ÏÝÃÃÃÿßÿÝ=„Öš}xrA>êìãûQàAÁ>'»7ØçO8ìÀûð„Ã><á ö•§Ç„å>J©}ð¤Ã><á°OO8ìÀûð„îVÀ?úßþ¯ÒÉCÓky<ûð9Ãg—¯—ÿßÿó\cì 8yhzí…SG˜2º÷OÑè¾_Iá ºÒ}_vôtÛ{ìh  õ€{Ósïn­îÿ9ð>‚mæ—èû³£p±&úÿë+ÿÕÇçø“ßþÍWõÃ'³×8}dfGù¿þÓÿÌ?ý“ßßµmoýöï¿÷W˜[\XëÜmƒAS£CœCG­µŽn¬£ïhúÚèh¶uO9Ûêw^7¸Í ò¤ïž{Ä„¸ûX5ˆ}GÛ[˜ï‚n™#¼§.¹$*ëÖmkÕ­nÔ„ìÿôO~Ÿ«7v@ŒÐíD·ý×úŸùçÿøøî÷¾|ÛÎŒ €÷?íë÷×&øE•õ:üoògýþù?þ£¤ü»ßû>üo²²^§Ñê°²^OêzÛÆˆýãï| iûÇßù&ßýÞ÷“v½ýÝö à!ÃÚ†AÈ·_{•ï~ïûüÿðøWÿî/øök¯&u­¶Ÿ|ÿá›o$+;†?ûëŸðí×^MÚþðÍ·r€o¿öêmdzOòY/ùþ‡ßúÿêßýø­oôµq];i·½n;Ämÿð[ßà»ßû>ïµ—CÅw¿÷ý;^ ûðÐá?üèõ{.ÛKŸûæ»wÕÇžÀ²$–”]Å-®èÕÂcÅŽ®®{ëžÿtÒ¾ûE']öhîÛÚwÿô[ñ5{½Ç ±öÆ_DŠß«ÕÇMºmŶ뺕ñuÉ/ÿä¿ùÁ×õX ƒ®ë¹]2Š^CcÇx£Nãï~ ´Ê`ðoÿÍ¿áúõkÝ‚Þ ï…Þ gGómMwÚvý&áîÑ_»ë=š~¿À ‰d{õΚV}-·I_3±Kùöö=ßv Š>jé^595Í÷ÿû×ì‰n\¿Æ?ûŸÿ'¶jõÁƒ0ªÝ&p«ú¶ívos÷íL_æÇÛìÒn/mî£]o+7åò/ÿ9è*à.t€­Zùù[cÕbb– ºvÐuý×î¥ÿݯ»}Y7·i· ù{-ÛùÈ÷^¶—ùÛ^V ¿£¾öcO8ìÀ{ív›kW¯ÒõuvA0@:íY,ô— R¨^Ƕ²{{-Û}\»Žˆ~¾[ö@EÀ ůç÷éÓOí¸¦öL#ÃÃ|ýë_Û½Á üVY4¼åk{Ñî1p\{¸öŽÈ½Ó¸îªÑ}\wûv®ãì¬ï=@&“&“Iïµù>|A`_xÂá×ÊÜñ./¬Ñjûý‘Wìèä™ÔíYâ“¿VðÖ[osò…WhÔkˆ(þ+S–í0·°Ì±™ñG=ÌÇ ¾0"@kÍÒzåÝãÛJ˜xE 4¾‚PƒÂ|ºî#Ç–\¾¹Ì¥Mr—‰á2Ji¶Z´†tÊfµÖdcs×ËráÒªÓxž ZãX)$IôNÒŽàÚZ‡w>ü9Ïœ>‰eI!@´ýKÂH9O%Ÿa~u‹³—æ™.13RzÔÓñ¹ÁcK¿zç}^ýêWhµ[4Ú~”¸ –%hû!™”ƒR6µ:§OõÀuÌãXB`‰.s µFi@SÈxbymOJÆÇÆiw:XÒxOü IJ$‡Æ+lÖ3¬ÔZA€m?¶Su_ðØ>Õôô2I–H¹B5¸–Ķ¥‚‡kåB ´Fkmd¿Ö„:!ÐD ²RŽMFJãB¥hûRÆž>”š )æÓ¬mlþÚ"c(¦mêÍ6¶”Qʆ@ I>íO;Ø–…ü0L®‰ Ä TÄœEOº¸RÄ! ëØ(¥•©—Q¬Ã²$µV€jß>«ö‹¥¨”¢Z.qéâ%R©B2®Íp!M!í?T¡BkŒ&„DH‰Ö=yý‘È’[JËJ8F*B¥ â¥0„µw]‡÷Î|LµTÀ÷ýÛŽ÷‹ %RÒéth´Úh­(g<2);ZñʰjK˜¼t“j)G.—FÍ6K[šñÉIªùZk|¥@ʱñCeLB@ ‘hö±ÃGb˜A1ŸæÖÊ\˜c¨”¥”Ëô¥ˆHA´Ì&¾ˆX$™”C³ÐŒ‚I–%-¤p¦J†J.vѬúvÇçãËó|õÙà q}á‘Àg×R’Ëx´;B%,ãZdR)T¨ð…”à8 ?4«^¬dc¦@F+_ "¶.ñO Óññ\×±ÐJj"+!ήéñjPJ“ñ\$°Õì uˆ¦†Kd<"ÅQÆ*Ü\ÙàÊü*‡'ªjï ¬m5¸8·Ìñ!´&B¢ñØIÀï( »vl‡¦4k7vï iÀ±Œ©ØjûÌ­×hµ|š~ˆl žëPÈ¥+çñR¶% #D !qú•h¥Èx.Jk¶m„€µZDϱQZ£”Ʊ,O sîê-Æ«Ò_Ð0óC'€PiÞ?b.CÊuQÊ(d±©&ÊlèH{@aÄf{/¶%ÑZsci+ó«¬l4XZÛ¤¶±ßÜB·7 UÆË(‹T‹YƇ Ÿfr¸„­tÏvnÓ¿ò™A ¨5ÛH)XÝlP-fÒ#¥,7—<>¹r‹O=´ãÝ$Iµíš–‘hˆÝHå|š¶ïÓöC›õ…ŒG¨4¡6ºÉ±*^¾E­V#Ÿ¿}þㆫܹK8^¡Â0@`„!:2õ¤má‡! :b™/Ò’\_åÃKó\½t•Öâ,Ñ"çÙ³bÃÒžMl¬åU‹Îò§\[¾Âúê V7¼rjš#Ã*Lœ@ñJ¶,I)Ÿa~e´ ÞòqlË–(¥H9.Ò“¤u\.÷°§rÏÐhuøìò-„vÔ=tH¥R|éÄ$þã_rì©g¨< D…!A¤ñ{®e¸‘~ÐÃö-[ren™³³ \úäÜÆ•´Öžç‘ÏçÉd28Žƒ­5ív›F£A­VCˆžð©_Ÿ³õ šmŸPkŽO B•Ü ®c“ñ\¶êmB õV›\&…c;\¸¾Èì¹OùÝßúêÞƻ‚0TlÕ[dÒ;¿”R´Ûm §ùÉ_þ|íïý.£¥0DŽX–E TÄú!æ¶#™[XãÓ«Ë\þä}r%ÜŒK.—£R©0<i/ÅÙs—ùåë?â·¾þ FÇq¾ÇNB\×%ŸÏ3\È0·°F)ë*…ÒštÆ#Ôº{¶N$ó-[P«·˜½¹Îì'gÈùˤ3i†‡‡™™™a||œJ¥B6›Åq¤” ˆ‰®V«±²²ÂÜÜ×®]cmm ê7¸xΣ”ÍP-dH§\#ЭŒWPZϵ٪·±,Éz­ÅÅ«·˜™%Nãº.R>–a•;ÂC')%™L†Ã‡ó鵪å¡2öµÛ²"–ßoê ×6¸|åVíùRމ‰ Ž;ÆÄÄÅb1AÄvm\këºd2 …¥R‰|>Ï¥K—XXX`yñ"³WGød8Ï‹Ç&»È|MÊuت·ÂW+&g¦ð—:”p›Çð‘ø\×Åu]:O.ã¡”Iäô KÆþ¼n>Ÿ%%kµó+[¬_ÿ”ÉJžññqNž<ÉÌÌ ¹\î¶1û9¶m“Ífq]Ïóp]7Ê!XâÖåO¹<=Æ¡ñ*¹´K¨u$Ji\Û!CE»ãSÌy,¯Xd2_W° ‰tn‡G hZí6×®_ÇËW±„¦Ó PhlËBÊ8™3ZýѬnÔ¹ukž’R­V9~ü8 ŸÏßûBà8år!¾ïãû>7¸¹°ÊÜR…“3#‰©§”B+P˦ÝiÑ’à”ÆY\Y£Ëîó˜rØtæW6¸<¿‚í8X¶‹&Ës§*ÔMÚAs¬$õ+JéaÌÃF;`íæUTËLMM111A6›½'Ù+„À¶m …SSS¬®®Òl6Y¼vŽSè*ñøé8½\k,;J/óC²™‡'+,4‹:­ú"J‡œ˜¥øF »:U?<4Íå/ú͆+EŠ—r!e™ók”V(­°-i‚\î vü€[Ë›4Úûƒx®C×Ä3Ù:FÑÒ´:Jkòé)ÛâÝs×I{Ï™D¢ñR)\å’N§¸ÓEJI6›ÅÎVÈ*h“¦vþÚ"R˜ø¿Äx•êŽ;DjÔ­L8ùqƒ®ØYwYXÙDí²§în@E«Ü–­Tbš¨Èá¢@ƒãXa¤’ÇsŠù4[õãã#l]]ø\œ.1•&›3iha¨*fñŽN µ!Àz«¬ÀBhÕ]ùBÐhÖ(OŽDÝãeÆáôíp[è¦Vßÿ†ªeVkmFªEÒi Û´Ú&Ö*@ÑñRŽkÛŒV ˆ(ƒÇsªÅ íÐËç°ƒWJI§Ý¢\( „ Öd¼Tä¨2r?UbŸJ)±mÛø6‚€‹¼÷àÄÓƒH š¶ÛûÄîÊÃÝ€Öš¿ÿÊi~úó7ù·?[ÇW‚b¹ÌÉSÇI9Žñý‡šfÛ§˜KGþ{³IC®m‘u-¬l•F£A±X¼ÏõƒRŠ¥å2C“d]%~$ãý8.t:&rhDæ“Ù9®Î^dkk‹BÊâÔ¡1^ûúW;pÛu·¦‰ìx, R)óÒs§9=]b"ÓÁ­ÝàÍ_¾KÓ7éÞARk´B"tE–Q³i‡ñ©)æ–¢—><. "™=·°Ì©S§Zhƒ|êDÓWJÓêøèÐÔ5Ûï½{†œ¿ÄÁ¢æ™#£<ûô)ÒéÇÏ -@`žÀáÞQˆ·Z­râÄ FGGQJñÆÇ×i¶|l)ýîF ÇŠâ’òi—©ñ>9sƒ§:f h­ÙÜÚ¢cg(¤lThj³ÑDiM*­¡ÖXR°ÙÍi^xþ„T«UŠÅâÀ`Ô£“W! ÔÝAЗ q?`Û6år™l6‹ïû!XoÁÂVR.6ê-jÍCÅ,¡êMýϱÉ9Ž=ý¹À×^}ñ¾Y­Ö˲x÷£YŽ=† ¡edêE+_kPšF«MÇ75¡R¬®nðÊ OóÔéI|ÁuÝÇ3' ò æ{` ‘ÿ=É ž;uФ£Hu:·V¶HQ²&˜]¾å|–BJà”Æ¸|õzD˜÷. „¼ûþL<‚Æ–=ȧÇÔÓŠ­z“ 4& eÙˆ°ÅË/4Qåêü [õ6Í0äÃÙ9*ùŒ9 &Î]–k[ 34Z>Þä4JÃrÍçÊù3rYJ%“"Öj·Y[[£ÙQ8|ŒéƒGèøõFݬòØÔðýXæ+À÷C–V6éøf‹X:k½04L„`}s“z›_»‰Àì]˜”r ¼|r†\:uws׳mmÐ[RöŒ î1 0iØwfijì,)ó 9MÞ=w“™±*Ù´‹Vš|Æãä1Þþä BÃÂÊï¿ÎkOJÎïénÚèB:å`‡!NBñì /‚eÜ x(Œ£Âz½ÎVÛDí´î5õ”i¯º" TŠ¥• 6ë-`Û’|6?c¬ß¹:·ÈÔX…J1ƒëØØR$[ÎB¥˜_^çØôègl÷yŒPÅNî zý*ýp{ìF³}·¡—„e%ÄbÁüþ/=ÃÚÊg.ÜÀ‘f·âðÔ3c•Äß~áÚggç’‚ÝÀ`ätâ›·-R®ßnÑj4h7›tZMƒôÍ-6·êt|…tU—íëù¡2+?Šì-¯n²´^#Œâ Å|Û¶ ¢ó@pkq•”m3RÎÓ BÖj,¬×YÙj²^o¡µ ±ýØÚ“<èýHº[½­ò®Õ͘sÞµ @"ÐBÜ–ól{íRâÁ‹IÁ4êê##C¼|°Äûçorku×qÒ¢Nñê³G(²f7oræüuÞ;wƒPéhs¨0J$UQºVÇè•q uŸ¥õ?ˆ9º'~O©g?!&@)ÍòêóËëahR®çyI?B¶êMn.¬òÔTǶPJBµ%žcc[渚F«½cå*¥¸p}‘‹7º'—êm#-¶‡A æ{ØœtõƒA‘ô®^ˆwÏMt—bÖ MHõë_ùýéßðÆGWøý¯=ƒBòó7Ïrö£ó¨táRžV»ƒï‡¼óéšmŸ—OÍI9IL^k¢Ômƒ™õf‡Ë7W°¤äÖJÈÄp×1»tgR»PªÇÛ§YZÙàæò:at4Œk[\Ÿ_a}«Ápµˆù,nÜZ%¥}¥¨²LñËœQ(*Ò{m*ü—ÿ¯¼ô<•B–•kµ&…ŒÇ‡³7iû>Oïò()R÷r€Ä˜¹wMàž¢±`éD±HÁï8¦S¡{®DÚyW–§½ ßzù$ÿñçù¿/ÎR_ºFŠ#•×oÝDyšj!M­Ñ¥ùðâu6k ^<9Ãp)@$jE.`ˆT°¼Þ Tšƒe.ÝXb³Ñ¢ZÌt‘JL½XT~ÀÜâ:·VÖH‘Ƕ¸¾° Œ‘Ë¥YYÛ¢ÖhQo49qìÏ=sŒ‰ÊîûgFËÌŒ~Ë·V¹~ñ#•ǧG{;“æoÞú„j!ËXµ\£µN½ñŒêdž«=”2¨v<Þ1hYZ»j‘qqÂ` ˆ¦ßúˆ­¥CŽ>À? äü…YÚÅ1<×£X*ð|ÊãggYÑST‹Y6ëMT¨˜[bu«Á©ƒcž"å:h-ИqlFæ2.×Wyëã+x®Ãp¥Ð˜•¯ãó„µfc£Áõ…6jM3)–$í¥¸¹°Œ@sâÈ4Cå<ëåRž±á¿ñÂ1Æ*y\Û" •1 ýv¢•ÆsmÛJ’[U84V‰DBIA>ãòÊSyýƒY~ÿ«ÏöºèˆÑye„idŠŠØÏ¡{Ñ~;äÓ³Íîn³)C‹=f¹lS]âM†WK)I¥R8p€l&C£Ñ ›Í‘Ífpl›JµÊ/>[äw¾ú4oœ™åòü hÍÒÚ&ë› fç–9>3Âh¥@Úu Z ñRG§†YÛ¬“Ϧqm;:ÙÃL«%`£ÖàÆâ‹«›F±&ô\-(ä3,­n0V-11Rf³ÙÆ‘4Œ³ —²„*d½Öa³Ù¡Ù6ñ­F‹ .çÈ¥S8–ÄüÝ]ǴÀñj£“ÃüôÝÏøö—OcG÷è:4¶«ƒÞ¤zg¸çh mKœ»n($ƒt”®`3t+zƒ´,²™,©I7J w°l‰%$ë›5ž;u˜±ržï|ù4ovOfçh´;tŸ·VXX^§ZÌ1=Z¡\ÈÏeÈzhAµ¥ZÌEI§Fëo´}š­«[5n.­³¾Ù0ÇÐCèÙ´ÇP%O!—A*31R¦Õ ’tõáb–RΣÕöiv6m´†”k‘v]:€F³CÊqÈDg Ì 4 %!ÂŽ¸:~‡ÃSC¬4ÖWשWÌ»´èY?š;±øÛƒ9dsÜ–$DÚl„¶„÷°û(lÛ'"ÏŸîcP:’i]![V¿1¢ë «¼ò¥çPZã:6¯=uˆ©‘2g.\çæâZƒ›‹ëÌ-¬á¥]ò\Ú%›ö°-IìJ6ŽŸ6ÍŽÏf£E«Ý‰jšN¥¨”r” ÙHÉS"—K³Vk2Tʃ†¬g“O;´Ú0¤Þö±¥…cK¶š>¾¼Äòò ¾ßâÒ%&LJyúàÃÅLBdm?4§–Is‰%%@b5—ª2l^$Ù³úï—þ]+¤%±-´B kRôÈümnŸÈ Òãþݱ9¸»I†!ç®-ò/›èœ˜­ã“C†Š'¹vk•k k,¬nÑlµét|ÚŸF³Í|dŽ™‘E®àÈ…*-3éžëàºi/E!“"—K“r4ƺP¡ñòi¥¹qk…Ñj Kh²)— P„:¤(sò¨-¸¶¸É/ßýˆ…+ŸB»«[´¥ÇnŽO>Çoí9NLÇ–4Z@£›Í@ñãýˆÿö÷¾eÎD½îŸíþ^9À=n ‘˜œtl42QîúÔ‰dñLˆØwÝmÕû=q ˆ· €µ–àßÿ×XZ¯á8hwB”ÒžâÄÁ .Ï^bqy×Ë0T)EbÀ#)`¶-±mIÚs)æ=Ê…,år a¹ÜZXáòå«”J2‰å Áf½Éµ[+\»r•÷Ï~D®iùÀ+—r,æWëüôço²9û.Cn›rÒi—JªNƒ¹ÁúÛ78cÅø(0œ§Õ ñ•ä/þê‡(Ón·ºf`@GE]GŽ”Ã¨PïáC׋ºîlJkÛ[ßfKöz©z´~S§û˜€î»h0òãnÇåÕÃyþË/?Wͳÿ IDATâƒÏ®óµŽñÂñ)²™JkÚÊâOÿýŸ3n7i5Ï_¡æ[|ýß`|¸H½Ù&4&wϱ%©”˵[«¼óÆÏ©dlªY¿xãWüÖoý" BÐhv¸±°Æ•›‹Èv׎U¸1w¥µCL åB…ç¥H9­NÈ™OfñÎQ.fH¥Rär9¤eáû>µ­M§ÃÒìYÞúpŒ¡ÂÓ Û÷ÃáûضÍèØ8)Ï3Œ³GpŠ(¢EŒÌms|RáÞÌ@@H“Í£P¬>§T<Ø\ѽ¨ì”èÑncÃÆÿk­xé¹§Ég<þë[ò?ü;Þûì_yö G¦ÇøO?xÑtȱ£')WÊ„¡âêÕ4›M¦FÑh·«7Œ>Zã8.gÏ~Äoù$Õ¡!,)Y_ßàÌGŸðæÛïsòÄ׸zs…•yŽ ¥øÊkÏpàÀ4?øÉøAH«ÿ@tðôV³ÉÙs • ŒŽŒ0sàÕJi |?`iqËW®`Ûk\>÷ Ïe¢”Aab ÍF“GO°²±Åѣ鞅d¾h¡ £À-Ø#òãÔ·Ã<àºæd,[ô]ÿwcÂÅ"Ñ"î¦ûɶ/èAd"º)Ž:ÈÈÐ/]ægï|ÌŸýÕMÇb&µÅó/=ÃÁƒ(•ÊOÚKóÖùEšvÇ„xͦÓhO‚eãûŽšb©ˆmÛ¬­®‚ÖüâÝøÛ›«hãžÏ7¿zœÓ'OR*•¸|ý&va˜JÞ£Þl“ϦYݪ›<Æ@ãtÖ˜8p'N0=5C6—‰‡¦Z©Jy\¼x‘Õù-­sË~rÊyË÷)eV‰üìmN9ÄÁ‰¡hzú•çû…{FÞ§R¡RØV¢ôövÛ~iB÷Õ÷X¶}­·ùŽ Ê±ËE©V™L†éÉ Î_¸@½Ñd|ì 333 ‘r=B0<2Dí½K´ü”ëó/r¡5­v@Úq’cd¤4æmåù-¯®Q,8vä•¡*Þyû*#c|ù…SÌ/­Òìøri:_R©¥¼ÇÁƒ™ž™¡/$ÛØ*Õ*JC§ÓáÆúltu¥M\»í#=I)kQŸ'¨¯ð—?ÿ”Ÿ¼ADGßê(æRn*IáJ¹)ÆÇÇÉd2„aˆå+..­ðæÅUž;:MÊ–t|ŸŽo’<Â@sdz¡aµÞ&]add„l&‹e[Æé>¶eQ,§tu™tÊ¥œuñUÈÒZ-z[‰¤Ùö ¢)ç–6X¼µÀäôT¿oå>Alrß5ˆÓ±R©„!‚ÝCMˆ€ž P/l‹g÷‰»íØÇH ¡£Ì`Û²Òxi04ŽiYQŸ „IÅ~í…ÓüèØØ¶E[JÉèp…_y)%RXfœ– IãFžD)-„%ñ}ŸÕÕ T8†ŠßE$íŽÏF½Á»jN)•ùê8^´_1F~WGÓ8ŽC&›a|bœ¬çÐñÛ¨j6?ÄK‘ì4®5Zx®M©RÃîÍ€ãÚÑ+Uâs¶·+y.ܽ²‡ç“Gô=WŸW!"‘Ðm¿Z$—_·ääñcŒŽÐ¨×•JæËvr™,ÅR!"Ýí£ävŸ ¦''àí ÔM ™"–äÒ)n†ŠÕ­:­N@)ëQô,^zéy._¹ÈÈÈH4˜®2+´á¯-ñÒ ÏÓét•At½Ù6­¤ C”†õ­&[“ÍdºlqÇÄ=XØÃ1˶!Ú1§lßkÖƒŽh‚ >C±³#QžÑO\ ·ÍAl6ÙÒ"—Íâ¥Rh=dÒÈ4h ½hÂ馹'ÚµèëI`’KªÑ‘ó3£@3\Êqî*Ôêm®Î¯2zjÎcq˜OÏ]àÔ‰c=.Ó÷Ù?åȑàM® F³¼±E«Õ&í#¢£j×ë>e]ë{ºÏî¬ m™¸XÐïÎVb%0fã(q$jº|²ëBJBʱ,@«äV$ѱžo"I21í,["-w‡£J Ñ!]‹ïë6’^-g¢äðáüòiÏgR«ðÑìŸ]gf´Äxµ€%“Cüá*s‹KÔÖ—ñ;ª#ãAÀñ§žam}“ZÓ$®¬×XXÙD#…,™tšÀi¶ÛllÕyåéÃwÆÚ„;Š„D`™…Â`$Öë g!уp­ËÈ\0¸îQû(#2ãÞ´Àpé†`zÅ@ÌúLϨÏ^h­Ð2¡$Ì‹¦ ™·LDqö„½ižê4o\xƒÍ¶b¢’c}«Ž˜;Öë-^ïÿµÓäÓ©è$±•r™Ñ‘a˼ǨÙòY\Z£!YYßböú¢‰5hÍ/ÞþÂÛ±qÓY\ísôðËɳ= ؃@#d´Nzg<Æï6™M2IVµñÄœA÷ù6ÌœG»W# Ñ=R&0"zµ[ìSH¸C­6; uÔ^Ç*F÷&=„£´Éë ´4u’ÑÑ‘;><–ûƒÁ×Ç;‡÷D ¿•D“̦‘ð(™YrǪ‰&TÇJY¬Éw•0m(‡Ø (¢òP€…á$±Æ‘Æ."3 ŒA#râ>E;„„Œ$‹I£-BP÷‘U¥ŽÌØèÞFïZó²ª\.Ç—^|ŽÓ|ôéÞ{ÿW¼ûÞŽW%'O¼l"ƒÙ,žçß ·–V9øµãLNŒQ*•( Éq2wBðƒÒöõ«”Úí¶Ñô£åžÈÆÈž7NÙçxÄÄ` …bVš”ÆÁ„ Ôæaæ}| •&>iE ‘Øó`œ7RkT콋õ9r…Ùç'„é?TZXejeô-­ˆ¨T$ÆÌ±o:ÔH©ÌiŸR¿¯ Ì)á±#!•JQ.WÈd2T‡†xæô ‹EFGGÉårQ¦³Åää$…‚Ùñãºnßëebóy!x¯°G¬›Z@lz)"T„dhœ)Æk'/¢DJBa‡‚PbŽãœ^¥© Å ŒW1BJÄCB€èíb*Òø !Œy½hmŠÑëåóÇp+©£WÌ#’ø†!šøÀʈŠ5 y Í„e[˱IÛYRžG.—'LnŸëºæžBà¥Ó¸)s6@Œt‘˜µ{‡û!;]»7%0‘jŒ—.°Z£„B(ƒôŽK DZ*„2"´D AĆAêƒ,Œzût5çX«0D#?¶ɨµq' ªJX’•@IZ›Ɉ¬¡±"säž¡yd½×Ö–6vÆBétÚu4h)$rÛž‡Á»UDµ÷Á%„°´¼L!ûø¾qnëë»Ö퉲¹,ÿâ_üïl@ûðp¡\.ïZ·'øgÿËÿjü‘§&qÚÄòU“äß%NŸ¤M¼™±¿~çuƒÛ *Oúî¹G,.zÇÁö6ƒúŽþ&9s¢û½WQKr*{êb®ß½6®ÛÖ.®‹úèëw@û¨9ñy}ýÒ=9mG=uɳÐg ½nç/æÛ÷áÁm9À…åîÝûG÷•tü P>tß—=Ýö;ÚBÂo¿cï-'º»’{Ðê@ h÷|üÞ¶wRÕ¶ªž´£Î늒ìë¨è`ðÔ‰þúQ™9úÌÀ9@/BÅm>ÐOÍûðhA÷üÝíÜÙ Ô¾ï#ú‹ ;Vûm9À>|qa/)fJ©}™ý¤Ã>üÂÝ$˜îÀûðkw›^¾O¿Fp/{ ö ܇ÇîgSÉ>x án¶‡Ý}ð˜B’;¸ÍOó ·íÀcŸ÷žÁ_Oà¯Ësç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFU÷vKH΂®ç¹ÏMçž{NU­ô]ßõ]¢ªœ(µ‘ªÂ³›ß´+|¾pãóÜ?_ðØ^ðñå.¤çzÑàÛñsÙ0ú ¡ØÇŸõ€,¾ñ"þM>,Ggp þ¿­µ#8y«Ÿtÿ† ýÆ Vù |]¼cõˆ„¿Ý¬Ãáb#öÎR–+ëžEdG#¨ïßµ…¢˜ÇôŠÎl°d&7)þ!xÀ)Çûˆ…‡ÂÏ×ö«À$ÐY@¸§«˜“VrSOŸ«Æß–À0~íѱS(c6qe[t WœÌN:€'œÁ7 ýAøà.è‘t0f£‘ ,{˜“”£>ÎY¶I›²FCn㺥¨‚˜_•ã<{ªñß–ãÿ¶Øt„±`Vs]ƶ@ûäy=ÜÃÚ6"k|s>Ypã|_g`g4öQ4ü C¡j#¶šÂÇï«ÆÏ]ÃðÓ÷DƒÎ€¥?ŠŸ5þÌ+Àpg'ÀIðØ ò û»ÇsZ×}2ø}ðÁݰvXþ~”£:Ëh´Šs[a¾28U5¤êÑÊ0áÁ·+œñ%£ÕB¼«Ô+">T íãÔ˜úç`* 0EDa( ¬b$ƒA¥Æ¨ôM¦fb=Æ(‹¶À¬)ʈ<ËàÛM&bnß ®¢´¦„,— ‚àꚬùMÃè%þÜĈïÙEo8³©˜ l.;éN:€ÇkìÍÓtC¼›X›—¬ÃÇÇqS]K¿ó°üÝ0§ª eiq›„ùJ(KÁMTÒ©@;BQ ®pâÐ* ,yf@3œ©$÷‚Cð^¸±ˆ¨Eç&!Öª"*ã÷^¢`³ 8S¡# â”Jæ }väÔXCß(2RLFf4ÔôšñCíÅs—Λ4Γ„clÔàSØo|6¶þ¶rY¥Zw}¯èØ!$'°lŽN` pùI'ð%sò…†É“ïyÏa3†CËhÆ2Ù‰NNШrC^9ñyFžyŒ1x_I–eãñb0 Fƒ1"‡ñÖ„´ÚÔ‘T4|߸h¦áÇ<Þƒ¦ƒsññœ Þ{¼ŠVÁOàŒB e:¾áKþm8“àñ×Ǩ¾²!mo¶›$Fútƒ©™i£hj‰´’¾v#0T%onƒ:D<Ìúœ¡c…æb´¢°FÔxZ""(Ö ™ #FT¬ˆ#b$=ªbDƒAtì®®¿vùêÁˆ™åea9ÔéùrvîôOk¾õÙ3ÚL¶ïÂËÞgÍËS$„qÞ['úýç©Þ¸Çë'·¬º;GоIPÅÄL@ŒŽ!;· 3«c/VwØ„ðªˆ!ü.&æcÃè*qèß@)pÒ<ÖãZVñBZNÕÓ1hd-;-~ª) EÈàMeÉHa›EœS:EåÅ(ŒÐƋɫ"VTr#b#F2UkÄQ1bŒ8Ü3swãj=0¤p=9vÔ_pÿ~ÿ´§=sj‹…Ù®erR+±uÁ ¥}m,1›V ƒ×˜û:Ë;ŸºuáyÊJqÞ3(aTÂáU¥•óq¹Ùö™LnZ>µuð6+/8‚œÞ„Iâ¿9¶ÙûíéûëfJ]óNutññÆôoUÔ(Ö+ÆhHQŒb4Eýºƒ €‹!9ÃůÂó{(û¨€aÌV#ðÏN:€Çjø“„|”èýi äh¤m g¡‹2‰0‹aó†gì 쎷ܽg¡¾¤çîœÏ ¥*^ …‹¡åcTr„L¼`"”Æb Æ$ ©¿c¹ç>¿gßO?*rõÃj.xÞäèIÍ`,ÌOY¦¦l¨ù÷ÆkHï•h°¡®"lïâÏþq´Hc’Ñל'ÔcL@@* !3x.¢…•w K8ªÂw·s( X^f9Œ5¥ààfу»œþóé=w½óªÎ¡}Å{E‡?P|îÑ%œ´ôÞøX„7”Å2îq†L!¶&¬ )™ÉCf–ѾÏßÐgߘ5˜þÅ'À¿]p]Díû@(c\te4õÂ0C‰|c7Û´€lúpFÎv=ÏèÑÏ;ñw½`ä>ŸĪŠÉ "‚ƒd1µ7F%3¡ä7¢rÛÍkíßïž¶cOçé-ìÁYs†ÝÛò€©Ù@æñ•✎kxoÀ{IH=Y&dYºd¬D×P_C8ÞCåc”WŹðž’ œ#à’›ÀÀÁ§ Ãÿ“›º¶÷liiÄ÷,¸[º–OL.¾åüKNùëÊ«SE‡N}åÕ;¯¾òøeEŠWE­â‰1¶¯dªx”Ì(ÆBîÁæ!30ŒŸØBÑ”ä¼x?=Š 8ùÄv'À#Eý`&~?Bb ¢~ L"\Œr:†Ïw“±2®÷ÓQõA; „ªÍïÚ%"%0ã½´QÉMÄ7Oäg?,rqOäb”ÎôÆ3Doz²ú3ñÆÄúÝ€+Æäú/½èða}ÚYçMü‡ñ9m¶Í[6OÙ16a’á™@ÎiçÁè;…ÅÚ`Øy­ìøé]wÃÔÆì_£Ä˜ +ÖúJå`±§Œ¼²Ôü›˜ÃWñï*Uz™á'LˆÈé ã?|Yßó«”Êj©<ØS®(oì2­låÁ=üáŸ{Ò“®~רTç?ðøžW_¨ø%UUÁçú‹‚ÆqQ(D)ŒU&mpÅÁ(°ƒ—1àÈ€"fkOìRà¤8QÔ_޵y7–aj,8€‚À ?8ˆðq2VE¨•îÜ5.ŒúPù_ø‘PfȬzɬ’[+Æä¢X“‰Jø8ò@nw?(\¹Œ¹"Sl7zó™ÂG¶g~ñ–Ï,?ýî»ôÕç_Òy5ÀÊÈsþ©³Ó™X’k梀΄¥È!Ï¡eëà:¶p‚›c]ÛqÚî?L¶ª/ZÓîS9 ñqË=ÇÚ0d k#ÏÁžò­¹…&»×HH3Dy§÷´Uñ#¥yªRÑÊ3ÂËžŸê+ܧ+üäÑåïþõÙŸ;ëTóÎééb±RêñmУï<¾#è/zõ¨*.:kB)вŠõáMØ\ÇeÞT† ”çÒçc' ±ü›|b:“ õSû.  \œ†~¹e;ð, ÊõdÜJ#AI ý|eOØ4CøÃÁ¡T2#†–±¨ˆ)@ŒÅd™ˆ“Œµˆ&Œ±kÄܦö)÷/s̓kúÜc&¿q“îZx.>§ÍDË`3FG¢U@»mé´¡“?Â…ßèÆyúú/Ó¯¼¯@8×f) —>8eÌ2ÿÏøußÃgz𠣘æûúÿÿ¹wì—1eP‚¥¥‚¯f ¶×õÆh¾S_ œ-p±xC¥7ª@üa¥”.ܸ© Q…ËŽï;ê`ÁAO`¨ðÓ ×¸¯¹Rÿà’s²¿˜šÈ{à3Åqê 'þ7Õ{*‰@•O„´,àݘ֘<`AÅ«ð¼ËƒxÝ5:~tO>éžàZGãÏì8’Jcøät W#ŒÞ ,Œ¹dCBÏ£ÿQ ²üqFCaÚ8i¡ÒÊŒc$·^ĈÉlˆð™ÁØÚø­±˜‡èï½ëŽêÕ§œÖù±ô2Ï9½En»gÜ¥†·ˆð#¸l¶µ¾€‹ÿà‘J©¼gÃg¿Þ4[‚M§àn¯—á÷;¶IxÜKZ°·‘±8¯¬ŠÁá> TmÃÔP¤/Rx Qc­DM‘!XcŠL6³b2Á`±?8Ø{Ý £ÿ|ÁE¯úìAÏןŸ37êz"µ¯(`zÒ2ÙIÇíkpãN+àÉS0e¿@°!%Ðe€®þÖµûü†çkdMP:¸nXÕÏÿà-ž×YÿßF§2*=GVC qT*k¥²6R •6BaíÌ„¿V°Ú÷üã‚ã=wWðSÜê'®yžùÍKöv>ºäðxuo ˜€gˆ'£vÎxº€Ñà&¬b3Øœ}è'X“;h5¦ ——”Í=>龯ÀuèïædqüŒÏ‹ÎáV<×o}Åé°Åüñ°OU™¢"¤mä¢"&ˬ±¡Æ7™`­Á‹5ûð¾þ©ŸùÌè?Ÿ{Q÷U+Cå¢3 ŠBÈl$à[abB˜î&&8Žy¼PÁÍ«p ç·á’©¦VÆc,6¤ÿküqú®'è÷7 VµQ&4~·äàã=ø er:¾¸z"¼ÞÜüo£PÎ{ú¥ÒmY†¥ãØš²oÉsûŠò“.€ ¿P{[¡Í)¾"G ¾‚ÑjÅqðm±¯ø\ÿàs/7¿¹ý²Î_Î:ïÞâðT8Tƒ@<¨Ç¢äFé X«t÷gð¤Vz~Er#Ø ™€z‡Whç†<*§,­yî8äø¦¥ÄB ƒßm¦òqTî*•Ýy8§U¥ø!]¨øùo‰£HÏåA.“ßü–‹[ù^•¦œœ€U‰Ôâ®xD SeW÷[ñ|‚åêŽ0EQ@ÙS˜Ð p¼ð´“àk։ͦOŠ˜(‚åiÀéÁÂü¿€9ý‘â ÈÑß[ N˜4•´DéäÆõÒ*Ä#ÆZ1ÖŠ5‚ÍsŒìƒû§ÝpÃèÇØœ¿ê)ç´Ø±ÍRØ9d ¹aªk™Ÿ†BFÞ1œX;ÄwöàºUØ™ÃÓÇ—îQj~6f@¿H¿6:4¢zއFðVÿ@4ÿaàç[°=kb <„W²ÌPD <Œœ2ù1 ÙJÈ*ý†¥rÏ‚çµKu ó_ÚÂEà*áÿYõ`„k áùq¨yÞ}Äñþו!#xŽÞòœg˜ŸÿÀ­àð¸ÏE=‚Lj'CiÅ.ÁîÖ™Xó"Žöß‚ƒ SPF•²T–ûpÚö¯i ¿à]*cÔ¿ ?ÕþÛçEðn„#ÀˆÀ óèï”Á@fF%#"ÞIn063¡—oÄæÆ“c­›gØå5ʵï÷`ÂüÀSÎ*ؾ5#Ë‚¾…ÍÁe†‰Ž°mÚPdõ˜Ác5þæ±âàÓËp_ Wuáœî›?A@OPûKôÓ†ChfºÁ$çñ¹| „A€×€ Ôñõ“0™ÆŒÇe…ŽgŒBÆÎj­çC±žÓ§°‚W¥?Šê_•r÷QÏ·-ú±Ô×ïu„ÂÀ± Þ°ìëvc.PÀ¯æBo¤üܽ%ü@~ù\÷I¾>ÿÏlÎïÇQ! G&ž\k~»€­3–‰Vˆncã?A®¢ôÿ‘Ž{ú¡,˜±pÅL̃ñ7ÓÿÔºk‚zÄŸêú² 9€Ïöà£eˆÒÃh´—xr¦d=^°ÎH¸)';ò•к€ô7: íV`;­c;Ð…¿u†#åïZT°ð»“Á“<üȲ2ö&>€«´„7´à7–=ÜPÁ/E^ò«üŸ<çJÿ¦Ìu8¼:¬z,>:ÏY“¯@EÙ7ø›¾Hà˜‘bçaå€òšíÉ•žt_ ô&bÝ/1Á7lÇðüøÈƒ¨{/ÎÆQRôW=ìf+‘y«"FÅ€i˜\Ä+™µÆd†,˰wßµzÑÇ?á~vóYÅUϼ°ÃÌ´` H¼ñ¼Ûg-›&×ë >Rôßèô18ƒ¾ƒk—á®<µ çL>zýßDþ×µþNÔHeA º%ðÁ¸9Êk­E]'xæD=5ÝdŽ[ˆñ~ò^1Vp¼óA‹°ñÔC§ŠÖ†à}í|‚ ,öáŇ+*¿ÞÚJ?¶3ÕZÙ‰ÿŸ°Z§ÔÍç9xÿ ÜRÅ(é3£ñ7ËiDþ® ÕºüHR…jÂtn²MCÀO|Ýïä2„¦áûº¼¡,ÃóT ;f„m“†ûyJç l±ÑÒ°“ŽøÐ{<=‡ß2ðiö~úgì_ò­Çþè©Ïèüö'ò}lm3Cr¼,É{ KÏDË©ÐhÐÿ¸ÀÓžÐb"O¼ õþ7¦ÿA]‹Ì¾:Ýyÿ¡tÓúÑ ëœL9oÚ¨ˆÉÚÜJ–ed6#ûÜu«¯YÉ‹_=OÁæY!Ï…,7H×b&[pÊf;ž,•dT1â?Ò){30 ÄޞȠš-?Yÿ˜2†âÅ>¾²ÜçÏÁ–¼®³ÓæX_û§Ôzäà½Kµñ—ñ5=³—N¬o¨ÿ40€ãR†Ð§kàͲ¡•…l©ˆÚ‡—Bɲ‹É–%Ë ¬`XyF¥2r‡ˆÂ{r/;îXTJ¯ ür¥|;ðV§!i˜%pœÄšÂf]»G¡[ðäcwó¤÷þ?ðý³¬–Å«w ¾b¤® ‚K•§WyºêùÅQt¥íȈøê:_%@rC„ "ÿ‚Pø=ˆy6.=öܾ{ÏÜÈÑEeÒ#U“ãL+36²<#[[©æ¯ýxÿgížö7>uoÎÌ”`2ƒt Ya0󓆭³c‘Ý0dh­>Yßr“F-œàó#äü€o ëÄÿÙô ÍT|¤ðñ%¸©ÏŸ3;úü)[‘úg#ÿt î®ÂXoRK{N.Ÿ8ÁÖœ†ao¤'oŒ4ŒÔùš]è½Æs*ëÈý‹Ž² ¥Á\7Èœ»‘âå¾ÒÔ'Ó{yåÎCŽÅV+e&¯Êl2#CåW {XðİÕÀª‡wà]‹ð÷Ï=õ—¸cùJ¼–”®¢rŽŽ¡w¬Ž<Ý¡ò+©¨jE'ðt=é¾G"ÿ8„nR‰«É„\Ÿr.¢r±÷w¼tÕÝÐu^¦=R€iámË`s£Y‘™ìÈþÞûŽš2gÙ6o™š4ØÜ`&,b¯}ÛŒeªÃ˜½¶.ê?BÄoöþåD)¿}äR gR»NkðÄÖqîø¹üñfÁøÐjˆÞOª£ýÆš¤”`üwÆšßÇ^ÿ3ÚpÅä†×­ëwr6[y>þ­‹í#t¥ù©=–}ž Sí@žr k8¶ê˜(„™®©Ÿ³Á1ð––+}eaE)l<›l‡SzË~ÇëªÆ/þ[3¸¬k™.„‘BY*¹èøØHë~§‰žðîþÛÎ^º—Üü_ØùôÏãµÄûà„Š^åðÞ³8pt½ò åÀ égèIðeþ× /¢ 9†áHÈ !Çà› ² Qù&õŸ¹ðXyÇ´ñÒª0m«¶%Ø\ÈZ™d÷ܶvõùŸ½=gzJ˜h Ò±˜¶ÅJÖÚµÉÒÊ£¸©£þ‰r|ÙØÎ{$`OQY¿ÿrük·ÞðÇè¾[ßÂkFcö àý‹AãšÙ ÖLÏðO‹p[µ>ø² On ý¾V¼O \ƒY_k³Û  -Açþ(2–ŽÆµc«£°]dÓ” RfÍ£5Â\d.Iì0ÔÙ…Ò*ïឃžWÞ?"nÿï¼Ð6ÔĽ0T¸¯¯Üâ”O%.Aì¯à§†À]+¼î³¿È%¯ü+œ–”¾¤rRUôq”¥cÅyÚxÞl5š›ÏÔ'’0O,ÈâòðŠ'“°g±€J¢Øç6DUé8–2Í*É 4ÏTr+RdÖŸ»~å›—Èÿì´­–©.t:¦ò`ü@‘Þ͖" FŸEÕ\‘xóÇÿÝ#žls‚>ÊœÈø«ª!ÛÕt0çÛÝ‚—n‚‡¿;ÇFøä Ü6 ¿È—ãâ"f z|w ,C-^I¿uŒ¾ØD;"çkƒEÒÏ…Ü&[q>ÀÁJϳ:ð´¬°sÎ2QÄ÷*ëÁEÓøÆÄ âÉI˜qù% ‡áë½Û ï<«ÅOÍÇi¤ Z"ô*åPOùÜšò¶UåúʧJx©À…)ÛžÁ›ÚÀ™Süù3~…÷ýîP)€‚Lrª,''±´­aU ?P l |ð µ$ã æã™} ×Üÿav4‹ »¹H1»×ÜJËûLTs 7ª…Å»þañ×ýdë—OÝd™™ÌÈ»Ì0V‚„\;ç-™…,«oJâ8ª64¶ä‘ Ø<Šñ'ÒÊ ÿ(oÛS÷Æ}#ò‹lÐü‹s¼b3´þ~)ða,ð‘Eød/Ž×j¨ýw \9ÆU|ŸqqˆÆË{ý†ž¿oÔûcÞAü\X€3Ä]ó°e*|ô‡a7áܤeûœY§Ð|?©AÌȈBÃGÀš‹ ¨[f…Ó¦BÚóêÉ0*Ò¡c ›Î5QauUùÇ£žWt¼#i ¿3—l‡÷|ûñö·ýý¶ ¦ #›Sä9ÖdL–‰Ìò• £-ñ]6úég/ß»Å07m™˜µd #¡hÁ©Û,yâM7\³í%ÔÙ@Ò𓸈o|›ãÁ?³1Ç7ëËó¯8€Ê5Æy›œÖ×ùy¥ƒ-‡Y‚³ øÜ°NÝ çZxé\ÝÖ -HÛ˜¨ªQ]†øЧ g^Æúßá”ù0»ã¯„®JfkaìTš|€†³‘¨84p5MØJ„PT.(%£Â½‡+î:ìéäÂÈ+Ã2d3«¥ÒWåH Ó÷u‡`[†RozºkoZ†Ùºï¾äuÌî^`àFx_â´B´b©rt*OÏ;þç@¡Kžó)þý”‡€e„Fmè•‚ƒ+ÍÙÂüY`Ô«ÙäYΜË)}aD‹þr¹éoþ¼÷§Oº¤õò½ó†é®¥3k1­,Þ¬J‘é[ƒñ'£J@TBªeC­=lkôέ×ïý¿Ò'<ÑÅu!*§’cFÐxMÒÑXù'Òd¯ž„-¾y~9²îªù_:ø1°^Ìù°lPF#‹ï3ËkŒCŽ' ó¤çNÎÀº5«}X¨‚¹Éhü ç7>'àRXSŸc+uæUùÀ#HÊoV`Pj±gm5ìž3´£>At³Ð<Úb„ol›ÚóÙØJ9â`ɇuf ~n_v.x÷ŸóЧOC¤@¥ÀHÎHs&ÉXµ†%±|O.Й€ÿò5Ÿ <±€Æô¿šˆûùœ0r‚ñŽ6^Wì¤G½#G(ú+妿ý³ÁŸ¾à%ç¶shOÍRdrª0‘ gî°c½º$}ÕŒhu¶Ã#òúO4+–ˆ0M½=}¤^㢤.ÀЭÆiŽ~Ì8l8§D¥­b”LšýGJ8PÅ7‚_ ÄÍ…¨œ"p“ƒŸ¤Ã}œæ”áyUCIÛÕ8M-7jš±Ö©W¬™Ê*#ëÓ|i*K½àÇnÈt`½dzÙ ]ó§•C»c™ÚÖÆÄ0¢ ³`ü’ZR}Xé5ZP†Ómœ³—õŽ`Œ_ùÇ÷V=¡¹ ƾá_Ñx]?öK£?RÂß †ý–G°+ƒM¶N»×ñûµ!!! çƒ#èc¤÷!2wòà ÆëÃ#r¿k¶ÏB§¢~ZZ2æH=o Í÷'q§Gì¸Ø,‚‰¶á£SH¯¯R°‡—Ãâ’QÛg-ÖÊX}hÇlÐghÙê&íØ§´$¢¼Ä•Iõ]–}xaÓ¼´—|ã6÷§<øþ‹ñ¦@$“3Ì2<]k8f,ßá l8 °íkÚ <±2€Âòš0Dè9Cå NͰR+Ê4ŠqЍ­.V›ÿì/ú|å×·Î9¸¤ T˜Ù^ 6ÎyaÓ¤°gk¸³z#X\U#¥¬`¥ PõxÊ«žˆß«'ìî­+Nà;NèTÊ2f¥É0buæRÜàßk$˜F)2ò¡¸ÿÖ?nà­ópo ÿ²X¤;ALbÿ9m(øTuªo ´¢ šSØ4zó“Ø4 ½R›MˆuçN#~¢ÌÆÚcoY×[ñ¬|êrîÚd˜ê§mµTUø›VF·Û9l›1ahÔ@ÇBa -kxEò°¦‘jå@’^>øÿ%04š*/ôÕ¼rDVVa/ÌQ²ìoÿå_¯ýïç<»8{0ô”S–ζ‚Üšq›©Ý hÿ°‚c«ÊJ߇hÚmí #Ðõm>}¤þŸ<®m…Ì6Z{ñÃyÌ ¬ÝÀ£Ø°®TmˆäyßkÌZ&Û†½[2¬½ÁRv‹ðDí6O 6Ö- »ÍmÃU©§h¥î/fÀ0¾Ø¶À«:ÀESüÅö?áá÷^Œ˜$GÈiiÖ2a ‹˜Ðƒ1kVRÿ“œt_б>"tVS Þzjpjû¥·›¼Ïf½æêÉÊU&?öÉÕ_¼úé­³{\7ƒiKn„…µ· 8e‹e©§,®zF^ÁËñ­-JmÔž' ãÊúv\û?Z¿ñØtÓ¢>~J¹ão£³8!Qjg`>º û‡áwYL«/™€K'Ãc6xíf¸oy$;„w5…×7ECYAÊH†%¬ŒjÌÄ ¬ aaî<7?Ë#¥Hm< ü±õÝ—œB"[Ñè¢øœ#˜Ùà4Æå€©ùi6˜°@uäâb¨<½H` n™ c&: B•Ó3Õé5¥ KñäØè5~¶\0Å_îx+÷¾çbŒiáMŽ39J†Í2¦Œå¥Æ' ¬ UƒúÄ8]“mƒµŠˆ’Ó9Ì‹p©Mõ†Ö  <Ûb@×Âv §ø[÷Vîûç‹1Ò›“™• k-G­á¥j`$|½ x·œtùøx8Yo꽡°¨Ôà°TØ¡—|R$§¹_bê_>ºò=ì̶c ìZ³9¹ÂTKp±}ê6K¯ï©ªÚØÇ=ë†#HÆT9Xí­È)¤‹9qI¸)žô«*Žãõ«#Œ5/äøŒÂD2>±X§Ø&ά½`.D»¦0¨zØšÁwÌÃÃ%üù‘€ök#ò'é½ñçF© ÕÏ¢ñW,  ?ÿ«S„’ Ï`²ˆÑÚ4¨d=ñGïÏ4ðÕä`´æC¤tLŒð£(nR˜Ð’4F°V˜›„–µ¡‰YÅæváòÔ›LA^ÝÁ%å<Î'[2xMxÉo?òÇ­CןN.-ŒädR@–±9Ë8ZY^Ò6Б$xà]rÒ<ÖÔŸÃÂÒPh©©aä,TÙóÐlÕ¹¼?"ÏÑâþ, ;²í¡À7øÙ‚mœ=cÇC*ÛçìXŠ:iйØ`oöÙ½×qÄ#ŽÌ®öëú·?„£k¡^—–oØÈ‘ªÔ3÷ËOàHJ·>eÐ ½AÝù7ÖJhct±n³eñê>.(è4ùNët~Kß6–’ü鬹Ñ÷¾FýÇ}þ8Ç_¤% ÎE[ºpî)pêv˜šoa¢ÅØøY€jÝgM6`Ê,LíN(´jjG›º BM#˜ß)ÛÓ#ˆ¶Ï‚èÞ +°-®2BK‹CM¬¡úÊg†p¦…vlµøÖ©áÛ¾¹µtïfÔ´¨lŽ#ÇËL˲b /ö±½°#¶ß!'À£wÌ Œ„oèaðÞâ4£2Ù Ò|ÖS´E[ü¿‡ù¾Ýö ŠØÊ™ÊÙUÀÞéú{ӆ鎌#{j}y' Õ™ø¡ëÕs¼†UØÇVàÀ18¶œÀ±Õ ZiN0ò·nö?Ã6™<þ¦ò°Ð£É?hDúqùШ®]„6Û(Q®Š’a•nPÛaýªðÍ9|ïì+á^©Ç͉¿øøÂ@^Äsã`µ ÆßÊa×–°¾ÂÌ¿óÁŒÛwÉš: ÐF·C7”9•k7„N©³3b^lÍÙVáç­¼vF}hËŒ„ÕNbhg0iwaÆÀÅ"´¢4yxÓ+aᙢAehÒ«;0ü†s†óÞÚêß·™\ 09Ý,§¥“&cU£$Ü ü£œtV÷“ oPÃJñÁ‹!{Ž'W´ðžü¦-|ç>_¼”©,ÈáLZèX¶uÍxš¬Ý6ìÙbk`­™$©ob2n‡•¾wíÎ!ÚrØgMƒ5HïÝúá6DrO‡õ®!¯Ð~s¼Ñë ÀDníò Kb¬9£ MÆÔ»©Û×Þt)¿-9|צ üþBh¦öŸsÁ·¶òðüÞÃ`ËC¨b§a±»'}8´(¿ÃÖFëÙŠcU³åo8K\ÒpF篡ÇF¨Ujæ`ÂY’SG ]ÈX½ÉŠÐÊ 3áÉ2Ä]ÛíL˜3pZcˆðÏox6é36dö-/ìÀðÇϾÿC?5ƒ´ÈLAIYNËfÌt,ÏÆÂ N0¬ Üw28þø¨À>™]VŒ¡k-n”áÈŸSJ>ÄÓžâþ—^xë›ÿžK‹pÆñ€gå˜p1Úž»ÃŽ{Ö J¿wÍÞ·_T©çî×èT-µ(b:ØHñS¬áŒ¯BôlfÍÑâ&&ÐÊ¡›ÃD㣛‡éÅ¥2½D¢Ët&T\gŒökMàIÔÚ-þã|Üt´–=k¼L*Bký`ØÎÕNÒ+|ö¸u?ì;‡VÃßO¶r}Ô‰±a›:ËIzu·?ìÇmØä$´!Ä’p‚q6¡`â6ÀDôÒè Ga]\ #ÅÙµAèuºmè¶B©_d!õï ´aÖ“,Ì{]Ø”´c„Sm)€Í<¸æ–>ô ÿiÆšF r“ÁZ¦Åòì– N ØüƒœtããCêþVHý e˜ƒq•ìYÞç=OÑuR»·wÑ-ÿX½ñ”ÿÔâ ÌŽvdø¥^áìmy ¹‘WZ§¸¥Y@gØKD(Çä˜F œRÉ<"Îí¼Qúë#}äxg`€Yotüã›óý&fŸù#/ Íço†Ó§Ã™›0pÕtøy‘ú,«Á;ip |£ HF¼9ƒÿ8·÷áKQ¾+žƒ^˜’£ªÎ R¦´1ƒÉœ½vmjüÏFæ’™†|ŸYßû¿i_xÞ~Y{ŽDV©[)í—8µ8.)¨ÀÔV%ä”´,hDS¦0דE–`Üô”…¦DØ•C‘x…„íaOo LEÁÅÍÎ>îzí÷-}òͯžÏl˜ŸåˆÉXm[VÄòus±5xŠÀ)ÀÛå¤m²'0~H kzÞÙ3ŒÍ—|(’Ymþä»û¿ÀTkꡞ²cORÿ(ìðáa¸ 7u-³“‚zÁ{×þMÂOé¿o¤ë‰SïÈ·É¢á›ú÷"0Õ®1ÙØ=*€W~ÃÊ® [|2 ð±Ož€Ó&áI¡†m6oª{©±$ª[Å9˜Ýøñð©5ø‹CÁ—0Ô˜Å8‹ŠeUnkœ`² —œÛ&7àuº~©é¬lÔ9b Û‚J…ÕA]˜ ŽÑ4†ƒ$ÕSæxÒDÂʈ'´cGŠŒ;™5L‚‘¸cÖ®@7fÓb8# ?»ª€Ü ]¡ž6gêA‹3Øy!Üré¯Ý÷΋PÓBlާÀjƬXVÕò‚<¾ìÕØüwï>(asFø! «bè:Ë´±ÏÍÉÊJsTŠYh}柖‘;‹³¹Ì°ã̯ۜ×|ÖÕÐüάaû¬ÄH¯(‚suä×F¸r ‘”úG£Émà»'d¹òýæLu«¶dƒ:Çæn<Û¾Aå[¿b«>ÚS·ùòIØÙfÀ`騣Ùþ7°Cé,òY·ðý›á·—à/ŽÄs[ƒc Å×£‹QwÏV¸hOPË£ÑMk:äø’gÙ€]›#;±mÝò“ø¿¯½ÞuƒçÞC Œ Yò4ºÁÀÈ$Lü± Qeh²c˜(i( t2aZ„Ý"ÌZC.pÛ Œ;Ÿ’ l¶!U+®.€¯›~þè/´÷n¢%-²,gÂ Ú ™ýè9&þNxüêðÿ&€ãßJð†*¬a˜‹Å>­’¼_™¼oM>‰oÝþ‰¥ïâ:ûl^ÃY-^µ-Ç)<­TX­‘ 3¶ e9Þëjú誨1•#d™Á¡8ñVU¼6¨q¶aôÍôÝlHÿ)°RóÆtÝ Ñÿ 9ÚE¤ç6ZmUl3f¦N‰«Ôê4¡¥—E²Né‚úÏRΙ†¿½>8‚/7Œ>Q”}C§À…çÙ=×háÕ]ÑZñ'ûx’Zu)u &òp=S®½'œ{„›†û;F•2×­Û‹¦©3 ‰ÙFéÂ×­V|¼›ž$ÎLuct<”Å©ÇÐaS|Œ¡WÂgzÊD—LE[N×´`éµg?òû¿4íL +T›a¬e¦myFš>Z‰…Ëßñ•væ«oüSÿ¹p¾ÃDeȼ}¶h6´’¯RLBké¡ÞEûßUþg.+à”‚ïßÝUÖ†ðñ£1¦3ÛhC¦ò¸_Õer‘×ѶŒÂK}Ž‚‘Mv`û\@ú¬Â 6Ã/l‡Ÿ>Ÿ]«hÂH„šG±¸Z×óæ7Ù˜ÜhÙ•Mùs"õE»…çœ/¼òJa8Rnz@yû§”OÝ&6ÏÜa9uóÒ•Ö™€Êúv Ñð^½‹ƒH¶±Ø%¾2+0Ý1ä60­h,‹ƒ¹NŠï `.¶2î^SÚ"\:ÿQ+"ˆ3\zìæ÷å¾ã"Œø¬@lF&Ó’Ñ+LÉ%ì\~Û¿›@‚ño‹©¿VF†ik1dOQòžøbÖ›ÖÀкõã+ÿ˲ƒ×tøö˦P”Ã}å¯\˜dèEC¿‚µJBšZy¥ÈÃeNÌ6ñÐ) 6ÀÑU”¨^\UÖÊHAŒoôTV;kqƽ¬àž0à„šõŒ¶FÐÊk5Ý”l\¿õŸÖñ<Ì€r³~ì·Œ½ü•!¬EâÏ0‚{î³·#9pN™‡×ì‚okÁ¯…‡†ÁØË两..6J"ÓPú1'ÎŽÒP™øÃ0}Ñ^Ø:Ÿ¹/–jÀ`¤ôFÊŽyÕg7ôbÝ•"~j‡J£ä N–ñõyí<$± c Ñm›H]tþ¶L…mQý¶ØfáÞ‘RUÂ<4…^eÀ®Ü×O–7ÞúÆNf[RÙ‚ŽÍÈeÚ[®š‰gg%¶ÿæ+–˜¯žñ§Ô¿’°× SbÉÔ^Ý1Ù 'ŸV-zÆ·î¿uùË×»C›×^Þ G‡Êß/¸ÆÝ´ »&M î:Å;ÅUÐxúƒL´%\|+tÚ‘ 4;…A¡µ¾§r±}V…›²Œhwn¢0†ƒÓ·Á©[Âã%ÜràøäM¥ ¦·UéÜz¹mïj§òx2%paë6\R Ò†Ò÷ÁU1c(=ܽ?ünç,ì_ ÙÁÂ*¼d^PÀO‚û‡5…Z«è´^bÝ¥uçÿ¤ ]´¤‹xïA8¼¾/KØ4 6.Ý+¼ärÃw<Çðü‹×3!-a¤89„1Ò4´c'ÄBvPä¡»£$«¹V„n!ä´ÔY³™®PÄÆk +lB80TLf¸lÚÔOYÌ^ØþœÕÿäOþäÄTrD2¬d,;ËS³Èa\¸‡/>üšÏþ…1êÿ]]¡ŸYz™A5_¬|ÞW-V zÕæýï«~2^ñ SHDz0TþöPCÓÚ¥òйP÷¯TÊ B¥‚#ìÒ”.,—˜È YÔ‘ïCÈgŒ-¥uûû×~že&ù¶iŠ)Ë‘ãûchv€¨”WÍ&s¡WEÄÞ…º= ßBV„ôÎ;©#l¥¬õ5DûHþIl¿Ò+C­7Þñ¦9¶²~¢/i|僊’ò‘éxL´×kê§ñÚ&3ññ:mÔú.Ž2÷!š§ú·Œ©~r内.fËýpþJW—^ƒÁßløúw×üu53ðÐÒñ›‘ï9 ×ÞÇ¡ <›ZŠËC8²AK§méi‘¾ÿÆ4ˆ@Òèõ§Y³q¦šºK’äÆÓß'PqÙ®¡(_d­§´b礋0e m„ƒkžÂ çM™õýÍÜ„i¬S^…»é–ŸG£¦`a ¦|N‘eÌN–l8@`÷Wü*8€ÔZèÂ7‹aÊŒ5t4_5’·1E ­ûîõUXæ¿K‹ŽÀk¦áÿçX˜D¥²b­QxøÔpípÏþ,&}ø¬nãÝy ì¶Ixæ95."QÒmÌhdê&ÞØº2Ô†ÄXF†UÍ{H¼»AfÌí–!·†¹®Áа´ªXŽr:…êð±ø¾vN%;65Ñ(\RÀà‡ÏâúŸüADZhVP™CF®–žZ®*LX~1-ðÿæJ"È#uJCO‚À‡Hþdç³—–«~îá÷Ž~rÎýñ.UnyçA4¦hèX{å…›2æ»õ°: /Øv@ö]•WŽõ= «ÊâŠçðšcP†=öƈNË`b7noÙPºá F¿ï(ÜpO蔾–Èzè(Üp/|þ¾P7w ¤ÈÕ8ÇÖRÉ ®Š›wšË6Tà=á ûG:ÖJØ· ý~0²AjªMªuIЋ­¾V¥Eç2³ˆ²ldeýØ­?1{þî [A [èÇç×çBI¡Ñ?}ß“hµ¢pÇCÁpŸz~í@ÆLÆè ©…?Ò䣵!µg‘"ÆùE£Â ݤk–¬²±lè´…ùIƒÍdìDÕ]#Am¨°BÇdõ·NÚ0#ý»ÝÞ=—^ÃêEÛyåOÙÝâ–5mÃYYĘ5†}¥ãÞeå¢íåê8¥_ Ó¹0ц!ç=ýaX(!)4ñb­zZC¥Ó2´¢WÏD0™Œ#]’µÆ:]Š;öÕ¥€5±v$öį„úõ”Yؾ)z[³~¸èðjøÞ6†ÍÆŒØx~zÁáî^…­-xò ìäµa˜F¬)¸‹‰Øâ«¨÷ì•Qs°ÔLÄÿUä¡XQ{ÊÈ®tR3+03Z}N þ]Sð¿—¡«pY&»áqŸ¾/” õ¼SáÆ„߱5˜¬¤xxp9d-ÛçaëtÝΤ±¸'ÍFŒbIbbäw1b»DúqPÙz†!]û¦ˆhéë ÇÁ¨!H–éNøùr{ŠX¡ˆ•2®Ô &ÂÐ*KØÒÎè¡Lk]øDtØújøüþÏ~ÆwcÄ‘«ÇŠcPx çYJïz­±‹Yžð@à=À 3…U1¨±LQ‘÷l–wUŠÞí÷?ƒÃßþã<·Å+¯œdÌxù” 2ÔEf.0†SJ·-TN˜oÁ9a²@5CÙ÷,÷à ´)ÕKm=ý‘2y¬… +C‘ôçâîúª ©¢4vÞ™¶ ñ$naL¸¡ÂÃÇààJT›NÂñyMF؉'µÔ5 8Ò‡²Û&Ôöm…‰ŒûþnŒ3uÒòÍñ¼Cc£o?;‚ÁMäõâ2ßlJ Å­3ð‹à?P·./)à%mø»58cfâkÚw´&æ\°.Þ w “~Ÿ¹žsa-êi Üö`8gçIëDO48#1qÐ)q¤AÁtuÛÏ$ÇaÂ{KNÌØš™¥µcR÷éœEÐ2EÂøÀ©ªõíǶ(•ŽV†ÊÎIa¶%˜ÜàßÜÈãŹ¼ïúÖ'sÛ›ŸÏÙ?øŒTT¦ÂäžUãè;åé^ùè0žõÿ£'b–?Á@zíàïbX2†iÍPÉ,÷ÅÊ¡örø[s 8»ÍDËpϲg2—pëc +Cåô͆m3{¶g €ûWë^v?ƒ³NÉP k°Ö÷]ô”>ŒkC5áf[ªAa…鮬©lŒ¹©}²É­&]ßëN„sl¢Úú¸r«ŠÑÕ£Ç5d½þj!ˆÒЧ‘IPõí•ëéÆcåjAÏÊ5œDl!¥ÿ‰ÚœˆBã¡#Jˆª!Òty×\x.»7ý‡jgóü.ô üÍ"üÀ–„§sºŒàÉ{ác·ÖÑÛ‹kpëCpïa˜Ÿ‚ vE²ŽÔ˜Õ~ƒÄ©>b6cµ&c‰FnýQϵ«Ö;v›0Ôyp68ïÌ„YÊÇ}‰>^çJÈRYAc†ˆ…Ž(¢PyauäÈ/œ>7Œÿ<‹Þ+#€%—=>û?ÆŽ»¯§}ú” [: EæY^R˜óá§øreÙW.ú¿ xãÕªfÅ’—l†¡ 2ÅòÉ+a/œ“ñÌ]-î^r1mDÃPO¥p×ÇÙs†+Îh15eÈ¢6ÃÈƒŽ‚—_r5³lç,äóÙmX\ ªµ‡Ž9†ªŸÀ0¡Š»îŒ©çúב°‹>‹“Ôc·Y{Óà§h”jÊ4e׊7Ü µÝ\äcÒɇÖ`ÿ(ü,:‹‹¦ÃÒÏdìÍàüñN)Ímí¸¸@3õýÕ‡,`25p–‡‰?×4þøñâhüŸ½T£Û^³þhÞz¾ok­çõ95ö±g3\›…ZúÚ»áÃáœíš‡W=%8¥ŽÒ&NðeÔtß´eI$ž;S«-Ù˜í8Ç{«Ú *Áœ|,묭§: [«›<,4q el¶ (+ÁXÅ{¡¥Ú‰²\0£ð|-§ ]ÉžëÄ4!‹3Ì6¦1™À¶ÜlçöŸy—ýÚÿÀ‹£4©k¹c8í¹jhøä¸×ý_–, ûÊFÿ}!úCf8–朥grº’S™|5—¢÷ù¯fG{Ú,VÁw‹4ä!¬ •¿Zp¼þ”‚«Î-èDj¦Zf³ŽÄ}9F‡4•Vűíù)Ø<çï± Fpp >¢¬ÂÈpnƒ¯"S®râ® ¥„FD¿¬jߪÂDÔù[¦Þ3ö ^uìš®¯è®ص î; pÓDxY¯œ…?[‚w®ÁK»©Ì鄿뜷;°gºðÒÝA0Ôo H%”hd–†ZsÚKX…÷šS·Çõ{Œ%q÷@|?#m_ϤóÐÉÀOƒ7y¸ïªa„Å„Ò] X*ž¿ÈâpQ$‰UŒQVGÊæ)C§-LžeŠ"¥{‘;ý¬=ð‘§½šÕ{þ‚ÖÞ’<ËñUE[yéY³¤Hr¾\Y@ö•‰þï^ÂXl}¥2Ìz‹×ŒNžQiN!…ÿÌÚËY-Îäi9 áóGCØÜÞ6ìjyÜtÄóúó Î?%cË´׊6¢Þ-Skxh§ukŠm*#O¼Û‚3·ÁÙ»„ª,†ì Œ¨üj?d’øî£àÒVž\k ÀWqÐ&F¾´//­×N½þJ"÷]ãüRÄ J ™‡??@¿ÜÄq`¯ˆë»›Œ:š‹BÃ0>2½„÷  ÁŽô»”V§Œ`5¶vÍÁÓÏ ˆþ{o¬[i'K¾æø³ÖÑ…9¼fÞ¾wtàŠÉ`ìÍãòÝÜŽJCANjiµfØó üÂ7¸IÚ¬)íVÅ'‹ÀD‡7æ4°±¡lqY8?£¨4Û…V C²–•ACÔÉR¦RBîŸ ~•‘3aOG¸i@=¦˜Ð^Uh[˜|Í$·|Ï÷rùïþ ®ª(² W:ŠÜ1¡žË+Ãõ_¾, ûÊEÿºÂ5™¡%Á2Ð ñAKÝIÑ»C¾“g¶àœ¬¸€z‰p@"±â;.lsê¶Œ¹)Cå¡7òÌN„"¼¬‚(Ëý1Š…#N¥èÆÆOMþH,µV§n…óN éü¾¸îamJ$"ÎÃz!Å(©ÊD½§m$NIc LD=½A(ŒÆÈ!!ÝýXîX 5è( Få4ìȶ1s÷5½W|-ëå²e>87º¾¤% Þ†Ç.`ïfØÒ àdß›WxÿMaÌwº¨¯lxÅUðÑÛ)yæÚFmøä18k2Œ?ÖÃ5A¢ §×LÃø]’6Km¾Xã'žƒ#:º¸å8e@UÄE*²h›`È£ÆrS[–Y:9d-˜Ž²ç+}Xe^df$,›ÑÐA«ó]KwÕ±6¢&$†’*\6xÆ«XøÐ_²ééwQVmSQQ±–9FÎð¬yχràÈ—< 0_þèp}ˆþ/z¥¡¯­2Œd¨ÉñÒš¸¹÷rvåÛÙ]@χb×ʺ͛¯>¯Å)›3” êC_¶!¹5“5"¢´Üèúùü¦2M“”3¾.ñç;æà’ÓS ­cœ²1U–6ù¤”´Š7œ«B?Üùy(çÒß'rNú}Ë#øûCáÆÄž9å0´é†£€JªN G¡ 8,ƒ¿ìG¿YÆå¢C_ÿ/—V}G–dq€ª„m³ð¬saOœåïZ˜ïÆmEñ½½ûÆã/ð¦6\uV¸émVŸÛ«:pJï<Þ×c¼QÆö‘€»„áX[÷“ÂpúQñcCçÆF§h›\ºFì”ôœÉ¹Ä,(ñ–˜<¶ +«!ê÷Ëùoµ`n&´w÷l3ì˜5Ìt›§½aE¹ LOYÜI1^h˜§ž$+0ûípçÿÔXÉñyޱ…³L› ŒÅÈÀiÀIyæ+ý§ÂÃÚP˜ñ†–¡É›µJÑ»ïd· hT/ÂÕƒ”#®Ú•sê–l\ëöFAÊ‹¨æ’jÕÙ¬ž#÷×cÅ6ÄÍz§ÑœÃÏM ª ?›&¥^•åë(Tº`'Ö*û—¢ÆA|m—Ÿ;'áÞsΛ†Mà Œu ¥^oNdû¥…%ã¥!±ÔI>¼¹ÃÆZñÄ 4&ào[µiK4Ò¢‡á<_“…\ìê[¯BKáÊZp´bBµW¦9|óC7´ó¥ªAG´ñk\<zÁ Y½û¿ÓÞ[bóå0G¬c ÇphxNÏóÿû‰^ l^&ÂáÒÒÍ *CM†’c´Èoí¿¬<=߯¥mX6pQИ9»ÚïàîU‹ñ¶›68s0?k¸ðÔ‚,ƒ\„•^Éâš2YyúÚ=’ÁÁJ8ºì8²âé´ ölŽåXYN×G4PÂuwú0 fkŸ;rôíb›¯t!:¤ô¾°5Òï£@…Dö™«Ût®À]½šo€χÆOšÄ“†!ˆnØèÖF„„¯4›‡›6q œë©B²¼Z“¸rßýò¨ˆßïö‰ã¯ô=‚aåÑ(OÛŒÂVâ½{aöq‚GÍÎ@Ú¡$j4B¹ÞÕÛ‡[-(ûuÝŸÚ·íVMž–ÁÁ'…¤Œõ%C¢T£ˆ¯,¶™3ã<,/‡ò<:Qv¬ÝÎßfyxÙãŽzV}\uwXðÀÖPÇ„ÿ³wˉ/øùÛáÌí°8àÙ9›7”_ ‚lš†žÀ<[{†ðj£-š&8…N;`ÉN¶ëÁ¦AM±µ9åy0tãêNQÒ,°±¼ÈhÙ`{fu˜› 8)K+°s>* e ˜Ê-·ö,Ž|ôXn€ 7ÁGOý¦ª×_´ŠÓFCësü¨Äfë© v Þ-p÷—¤%øeré5Ý6 Œf„²² –ÂdÆæîÁ~B.bSöZæ s™¡ç`í@ =j¢üȳkª5Vv­´‚P…}‡ý‘ÇŠaSå9(AܱWÁQo˜Í•óRošµu{0‹ÏS5n¸ùnÁ°i¿\ÄoÄ× ‘1udLx„7Œ«¢–\ü2Sw 4’Tþz!ݤ.ðõó!ôÔC=ãˆgÖ¯ÙJ¼ˆ‚šyCs@jÑ‘þ ‚“¬¨KÇßýx×§× “nÎÃûoeÁaìÞüÈW½¶¶ÃÇ—òH `R:2v%øõñ°tÁ˜Mº¢¨Kâbô‡µ(ˆõõ^‡,‹s¶$]Ìîœ “%í÷`ÂŒ«eJ‚Èh©Á)ô*Å«0Ñ‚ó·ZîÏá¡£qâ(#L7þºî¾_®9çgÞ†¸ÞæJòÌÒ^u\^z®ß,pøKR|AÀO†[âma©2 ½Åh®ÀPLz)|Ï¿”Y K`n[@s–*eíáù%^ù‘‡¹õ2©Ø7ÿ¦m1wï¯B N•Y|ì‡"ý€®:»à‚= ®~|ú,¯3éÄ F5n멆6ZUÊø¨ä«úH4iLÎù*dIï.éêK¸·Ÿ[e€ßž\ØowûتÅn@Bò„~ýìTˆlyÞX©°;º…å^Ð ãldVÑQ[•ÑI ‡á¯ôÂ{íAé”y¾ªÇºÅ¨Ñ«Ôª?ÆÖ2ÎL´ŠˆôGêï ¶%Ç«ÇãÔ¤ÍâÐVÚd,õ„à¸$15ý{ÌýˆOb¢1Q,DLE`T ÷UެÎÁ®ÃÙ[md¨½È§á_é2É[&+ÈM†HFÞ2 ' ý)CÓ¿$`à—Á¨À_ÅÖߢ°RsÎÐÊlèûg•½cÃ=쫾ŽmmX…îÎÛZðÌ]§ä$–'M0þYáéOð#Ïê°w³E5(·&U—J‚ÌÕÃG¥ª ¦Gw€:›,—ž©eIÒœÚ`M®ÀžM¡žEÌÁ«Ž‚åhýhí(vÊQ=‹ŸZl‰«?ŠƒÔExû±ø"ªº˜ý¦™z1‰¤Ñ^ uzyê07 n¸iƒ¦a£–âãå ú‘F…GÑTñ ¹ÈHmÌG®Î`¼‡åÕðÿ‹6O…ñææ1ú2¼l¼Yí[ÛølÞÁØÆ¾ÁFëл¸ÔEkÎGÚ,”¥)¿Èî#f…IBihl âK0ö¤ìOì,¤6*úUø}§‰iËʃ Šª0ÑÎÝž…•v6"] ÃçÁ}¿w–±j,â-m1 Uxz7ÿókx po¨\GÀüw52*Í@ ÿÐè¥ôãåÛåÙQ„“vÓBŶŽpÅ–‚ÖŽ@ø) ´rC·0lÝk˜ž4lš6øhÉFà®ý> ñDcëš@´W`ïlÙ Ç"SPõ¥ÚZN:ŸJCʧŠÊCFÂ4bfêYñ”‚Ži¾é¦«ÂóRÕiZLâcêÿ™ìï­¯gŸ:¶#¸(°™&ÓZyˆ¾¹­Û–)b÷FÁé$é²æì¼¦¡¡Æ5¤“6‚k®/o0ðPºÜ -ÁénÛFcW×B ìÜ]𜳿üQßoøøÚøË2i6jý4P”:™©q\ø¿OmL[B) gºirRçÕûzïD+sx ôo·Â±,ƒ^©ÜyØsÊŒ¡•ÃÞm÷UU½ âœWã>ïEœúýŸjŠaîFxS²j,³“Ž¥¡ëîø¢俌]€¶ð g8f„io`i“=4_pP¿žóZвœ¹et·.T˜ŽeH¼ £Z{\Úea(ç´m6wgê¹ßw ¢Œ—jò#G9e9sW¸Ø÷—°©¨ÛlÛA£a¢•&£üðmÁX‰uµŽ€h=ôSiÍìß`±nj/†›"ï;—Ò„RÆžÞ iw:ZEò|4Ö*²þÊ2f±'×ÔÆÞ¿¤/¨.f=ROø­Ç…'"éVøØ%0>ÕåZ`:J˜ã_…èwö¶/¿ñoÄšXÈ:îp#C°Y=1XE¶¥: £˜q%ì@]ÝZ-5ãÂÖôî"èV…v  ³©ç/WÈ ×™¦DyCWÕ³)B‚£U*…{<»ç íNÙ–ñ«BÙ»-Çßùœ§™µ;æuâŒ!•ÉðEFî+z«†jJàÂxEOE~@TU¿@s/K½ž0[†b)$C¬ÅùÜ©®ðk~3Û )÷<¼¿RÉ'Þ”Þ¨†½mq¯;yUìÑšHp¹ïH¤ÝFƒeÚ{N=ÍŽ£Úkp^·ßwìÒa;gÉBʼkt'`÷<Üsn@јêœb ŽÉ§É¿†²©S×hó:q õkát<¦Züë´j¾ @ý2DúDM½vi°¥Óóic—k,,ñ15HGÖÈepqˆ))5· %`òhòˆ ›˜]ôF_9ã7†ÆCB¶fx&ஊwà ¬K°$Þ*êÉÉñ92Ô˜"ȧ>ü.qªä„BN[¯‹†o³†ó· òøÜEf²I« ¢Ü½àØ3cie0³%c©å`ü+ºþßy¶9çgßVˆ#õ%FJºmƒ — =7l8ôµÖøpªá뺆…A2K§´h+Ãi!÷ûÝ5lÊ`*t]ý#X ã’2mÇSE!+L¼‘e¼÷=¹šÛ¨ÂRñV‚r‹yõ|ü¸ò\XZ…ÏÞ 7-”V± Ý®ÅW/pà¨çއ’¢Œ%¤_r…áÔÍðÞOÃýGÃfM=(“§éNÛ‹d Bb«7ÖŽ#fË?²rðp3µ ¸f[½©G«P[†Qá××7[³ñ3žp4µúOªOÇKKc6@Js}cª‘¸˜»*þ‹4ˆ“8+(`ËL+½î]†Ó¦¿ü8ÀFÒ8 ˆÃ²&Û# 7rë;åeÿÈM=1ª™kcÛ54¥‘55éËÆYǸMü¦kœ»²Z&‹àp+-Õ‚óB•)hßsijwÞ0ÛV¶Yü>àò‹ñ·,|½ÏÌÿ5*’[¼XÔYúÞ1ÄMBS_T'0ûÒ^§?¾Ø+=a>3xo°y†w9ž¡`Ù?•sÚáÌ?\Â!˜gLf2®Á³Ö™\ö0Ñ Ñßš Í”"ÔþÞ…E?îíªÑ_}ñ+Ê{?-ctx^ ›+‡áü­–<9œ¾ßúÇ :âS«Ç ³]á…¿;wWЫÿçàþ#±Ætu‰`\ˆ.^ï5q"ÍG]È·Æ•Õáæ[¶Ö7éÐ…ú:욬ŽT~ƒH}jW5HBÑÈ}ÔF¡œJ€ñ$as™ ½í$ý•v鉆›wº^ÓÔDœbŒ¼‡÷ÝWœ2°í³°kò‹¿‘„IÕ®q·­Qÿ”$*¶iTW&’yFqn¿Èã“©¯oÌ $>@öJÆí,dª¼Ö´‘”Z~6Ža›*J$^I#³KËG4òC†F¹ï˜ç´9ö aÿd\Ð{Î…æÐv3ûŒ;ƒj–˰-CÛúV¸:ƒ}^à.ùÁ/¨ ø:€ô¿ï2<·f ”†‰rÃç£ÔDçì‚ËŸ*¼ö9aü5í©w WŸßt•ÅUaØ–YÃÓŸ´þY`ó\wˆÃ7Ñ ’nþ0öؘæb™°i >Öh÷–<ÕÂÒr¨ñ«[€N"a§Œûb¯Þ5y"ÉK½ˆkÍ$ª%ðÒEn|•H5y‘ÖêÁirѦ]ÜXúÀ (}¬qwbT›¾˜è¿¼åáð|À“wÂK.CPÿøiøÿ 7=Òý|M¸j øIŠê‰[këÝ„U”Ë"œÚÀ6Ç>~ŸÇçHÛS—8ãÞ¿Ô‡´Ÿ0µ Ç ÍL´jÐHÐ(DÈc¡²¶<|·˜7pÚ^ü±ç{ȱYŽÏ2ŒXZ¹a؆C‡nýjóTœò¬ÐË—µYŒÚÑl2'sÖo6ЫØ^À¾*ðCOB{é‚©·ò4B×…‘ñðŸnU¸í¾2P[‡a!ˆ!.ó¨$ÖÄBË)›Úð¼Káì=¡¶¾e%^à†Z3À3.€§^`ñ^þÔ¤¹á„mŸi¬s ½ýÈðKSiS-Ø:D1tpçJ#YêÃζEñˆ²ªuù}cG_Òp›=¾–¾YU­…‰—PFýÿ$¡—þ&鸆RPåëùn+‚]¾VâÆ5k•B·]O.ô¿¸;h¥ûWàm ë™…¯º¾åê@xzÛµ*jÎp¤ž¾©!•ºeX¯ý32›ú­¼Þ¤¶6`%8’‹Æ-¾ÆpÒ˜™5&#`ŒÔá¤L%qº0-BÍ N8&ÜéȪ"F0S& Æ£nŽ|p7bò–‘ É2,†®3T“pÕ4AmK¿ÚÀwÀ·´…µBèåöëìÖ®µjlV‰ä8Í÷u/"7ü3¶guá…ÐÁDZ_š”T¶%qö¿æ}/ö”Ï?PÕÖRSχ”l|ãGÂŽ[ô¬¹šáwS¯öè.‚q Q~ݳáÅO5\°§!HëæÑúUðºçÂ9§Ô‘²ŒmÜØ4 [g¸ÈûÛ‡‚Ñ7×]Ý®<«F$O‹7¼®gލ' ˘æYo쩹 ‘å—Ô†ô}äëA¥2…Ò‚Œ‰æ¦`çæPïWÔcÍ>f.½AÜbk8Û°ü¯¬4^U¸e>{>tì[m4 L‚w?·nè.\±Þøê (ú?ßÓêÜÀ?û6¸ù¡:Û l")|r¦Ö@;õ}"UÔ#ûÖÖd 1õú±,eÑ©SH#5õ²‘$4f}šÙ]¬ï“lXÊRÔEt9YI`¤j¬/w ìKúÿRÓ|Ô3¾±+a ¹]_K§óç‹2*¶þìÞO=^x |ç³àuO91jß<Þqcpý¸_q8 \‹fa´ø¿^üsìhÃä$¼ïøç[7ð„-\º7üè­ÿ ?úÖ°ÍÇÆú<×ZJ,9w=z§ØPî%aS¼MQ‰÷„M™B4èæd©±õmn´~©E’–×$³1ËM"$F‚Ú•FöY×ÀêÅWÍTl†%CÉÈ4£Ó6 û†gΜý9óEGÿßG¸Ø{Ž5˜¡N;*|Ve&ËEòs¶Ú‰nsçÓµ³­Ѻ†<« (rGë!  Ÿ‰†*ãqÖO|>œ¡ª ë¾—ûm8_ ƒŠ°ØK»„ÁO¿‰1®[ªU|³ß,ÇŸ õ'H‘z^¼žé2øÎçFÅ…{úÁ¸›štN†%1i5¸o‚ziñ±ÖƒHiæ -ólª¥H$Ëʪ©KBš„˜–ný*0•F9Óýä”¶ÎÂo¾ þ/‚|&<ï8gLÚý>¹îÁ °RX¸h/|ãå¡ÔèWë·y.´¯hÁÛoÿ÷#Ç÷˜ÎØÞò® úÔ¼‹ÏÙU¿—Ïßßõf¸ñ¡ú1﹩6\· ÙXïçy-ÒãÙPû›8î‚B¢§¿EÖo$NÚ£œ¦=„&kà RŒH˜W˜nǺHÚÏ¢|à-—…7Ö¢b1…aè ó]X^¸øïòxËóEÿmÀ4ÂaÉdZ[¹Êzc³®1™ÏL~þivö³wöÏeGŽñ}mXO0ôÔfÉ$f*ãÝ.LìO ƒÜø@Ié$È^ÂÀN¤c6F> ùÎ+ÎÁTéÂho¼À·-‡.äÆìQÇ«l]šõ4þuåÁ9›`z2áõƒ†ñû<½n¸½›©ªß}ãÒ×Éà“L«ºÓrÑÔÓOŽÃ7²hÜÉèÇ"¦®±.Ë„4?ñ— ˜^ùÂî“ð/7 ÃW] Wm>ºþ±»çÔääæKøÝÏþÑúkrÏþ¨Â³ ¿üöåSfvñž03‘Z¢«øá·À__øA¸k½–\ãõ¬¢íØz¢0]®vV/ µ¶.Æ _¼R´OeZ¯#K{S qÅœ$¢­¥Íl#c0Ú¯d—¾ èÃO³dZdd­0!w,gÌ ÏÛ*ð£ 4_ˆá¯3þ³1dG "vÔ1ÆgÕ[ªÍwn6³./dºÚHM¦÷õ4¤HÐéUŠÆË`Œ„©¿È©½ö¶28<8'‘ó&Õ…ŒÁÀ»ÐBLiv·ôx ¢½ñ½Ü¸#¼il™e}á¨Ñ3g ïMƒ†îX/eŽ'Ÿ7ënAúåyÓáfsUÒ§)DM“{™ý&˜¢¿ohß{×h9ºz²xlìÑAŒªõeL Žú÷^ó>Ž S;„Þð sü18ÚQím×…ŸÝ·¶Ï p×"\wWØtp .°pÖÙðæ{ëǼís°ïPÍŒ|è|çïÀç¬[q×\ ßv üÎÀ?¿Î:Þòvø“®Ž7>Ÿ¼>qgèj¤Z¾7îóˆ0Ö_hŒ7ËÓè8iŒ SO J5È“ƒ°õ@‘iþ ×%­.O«4üÚ)aLŽjÞ‚ ™°5tç…M†þS„ÿðÎ4;󘳀ìqG}€ÿÿLà6 @–­)Ë¡õYÛºªÊŒ~ÎγXÎy9¾jäFqܬ%ŠS#©Éç§vüI¯‚ëoâ´^·ÁA,õBTmå¡Uä"ESâP†zÐcž~ßÐí0ð#ÇàêÍ uY9žÚ4Ùhü~üÅõÞïá‚Óà¶{ÃëÿûÂß}¨ÖóS…wÿBܳ€õò×<‹Ü}{¼®¢mÈ…Ùˆ¹d¶fý%‡äãõUЕ°pÔdõì‚ø´£z*Ø&À1 Fçíuý»fhŸ¹¦Îæä•¥(,ƒÊ0Ù:G„ÃóðoxìŒ@ó¸ÿ÷Æ;†‚Çâ§ ÅÈ.-[9—+ZxÑ|tnçÌÿv­y5Ó9YÇãš&f@Œ ©ïuuc€¢qìú›Fô†qn½”±wå ý^hfVâœÄZXpeø¼E•ýëþý‘Ö5¾„‰P'«©¦D©é}Ó;áŸZßòÃí°[ÏoÐðóU]»»*šêI2×@þÇä¾þ]Ú+à˜‚J£ŒðuGÁQw\cºªj'“f€ÒBŽ„#ÜsäñEÿëì»x/œ» ¾óÊÖ–œùáøûOÁÝûãšóˆÜ}~å°ú µajÐÀåg6Ê/»áΗà¨]YǤÔÖLÞšòSúH[ Q¼1H4&!Ic\8Füq¦ uå›Q— qf§ lÒçŸ?üÞsPÉ5‹ºL²iCÖ1,u…Í› ·¿þ2¶×/E0~²· Ü œÛ0~‡afY8–*1TÎ"b]žMÏœx5Sæ"ÿéÅæ2r4NjE´ŒšXS¹Ô‹œ†’ ŠõT¤\wGPsÐÈÙOž\úeðY.TN±I¨/v¬VÛÁà÷ÖL±OƒoØÞ`{Å=p¶ÚÓbÏóDÞóO?½îïBw3´»0èÒ×L†7‹´ÐÞ°î/‹ÔÛo¨õbŒæÒh³~AæØúõù€æ÷)­—èTЬÄÚÆ7ž3uG/>>ð¤SàÆûáeç×?›ì_ë7J§ÆÎ§¡úÄíð±›ÃLþ§¦à¶cpº¯×­¥LFãëà·Þ·ïƒŸù&ØwþêSð¾ÏÖifEñ .Ç~ãÐÚq·ˆ m 4Ä=${]G_«9%.8‰RCÿ3k”MÒPÒ{0ˆL“E½îlÜËÜsúЯ^ìOË>i¼Í°š‘2Zb±â˜ÚbXÞ¤\ÜzvÒŠ ût¿°Îøo5¿ÇÐ&pK„ÊT ÞX¼·ÃÝ ª)ûSjß, þÞ?°úCì죰N´.1´²TÅœI½Ô£Ÿ>NüêÜ[Ê,m]öôG†QÖ(™‘0WïÁgõžøÜ Û¨·>»ß°3Îàgõ q‰$äkgÒº*ÉüÓmðÇÿ˜Þw*´&àg¯‚Þ ¹þüCu4/©h6EÒ N¬ÑÇK/u=b©ˆ=®št}æ1¾ßµ1›F—Mƒ³Þl…¹Fá5Œ]?žãÂ-ðwüÞ'áÀÑ`”ýQeÎÛþÇŧGsÑ–p{|ÃoÔli*Ørò°•°À´y´1¡À»®ƒOÜ4ûS'c|N¢§ëßjG òŒèP#bŸ¶4û¨ Q?ÒøÆêñ˜ú[×XÓžf¨g5¬ Ï#‘”¤É$.05‰/àBP(]øÿë¶tgð«ç]`±9¸ ›Y¼Œ·XX5t7ynÁpÞK=¿ a öÑœ@ö˜Œÿw¢ñŸÕˆü‚Áà– vÚ K7ë²§xeeä ³ì>io[ýÜ•;ÍÖ.V§›s,’¸V㩃¬¿qT5&‚w0ðчõ(‘Îå$^¤0ü³ÚW¦»†V!ôûá]gU­úS´„Sº‘3A˜ånìÁUó5˜“øâ'2øGªo|~ëïc]:·GƒÜÚ ÆðŒ½ð7„!š´:¿öœõ¿ê,Øw8ʉI}ˆ´^#áæÓFï9Õ¬#þø²º;§B!Ò`>ªAÑqsƒ$X³ P |ýÇ«FöxÍx¬Ç·<>ðÙ?8_àÛ#EHAÆ=Ô±°EôH§b9g¥ÈC”¼w¿rïÃt^„µÈhµ$èúàþ ÐÍ ^a®»fa_£uó"<°Û;µ´·m"ñö‘ëþá Z ,ì]ƒdDí þÓéõãï[†‰uiZБºé&ðºÞÀ›ÆÙœIh¦øúÚÚ4l[‘ºØ‰õëËÆú¿¹†üöE8wöF€›ÃGÃnóð®zü²µçΆéÌ•~(.;þþ:¸ÿspÀÃ|Œôš+àç_~<ç!-EI`ibWº ¦©Ç&®“ŒwX.IZ’ð™$6jªz tÂçR¯?ÉŇ´.\ÃÔm§(亩âqøL7Îj$I’ ¿à•·YÛÿß®ÔKØÑúV&Í_sÀÝ€¯ j Þl¦l¡ ÛPnþÂ}€›ÆaK4|?wFÀd÷J„odàÿ»–od¤-JÛE+“WjGG†²³5^^L¦6þ80nÆ‘óõ­“nÒ´‡¾Õ‚'Ÿ)\u^NfsF®¿#¤ŒòdF©¼í; †˜øßÏÞï=ƒÔƒ·ð±EøÆN´w¿ž8~\ Aç·ß ï½®Fœ º~ Æ7Ÿ6º¯ç/ümH5¦²ÆÕ}ç¦”×Ø)fu´†:3 1¹¦< Çõø 7Ú£~Ãø‹¨hs¸áFpí½pûA¸õ°JmºO=^ÿ48sö g™þòËÖÿŒÝ°Ðƒ?¹îìÊð˵ûGësùFo¿aøIë¡J%aRï¡uNˆ’ sÒ ŠGàO¢ÃHd›®eUó ¤™Ä{êðQxà hcð!×dØË˹ mÉå¿°7ßÃlñZ /ì·Ç{CÛKF(1´ð Ϋ@, õQÀ8õOsë¶­ÛŽFGPèë‹éù·pïC †Þ¼¯^è¹S©ÂÃÇýý]‡å2¦MÐ>}˜<`¥†tÃëúþtªï|$xwsxÁ“anÚ-Ç ®½>x½ãà‚ åð¹»áõÏ‚ §áÚ#ŒõÜoX„Wî¨Û9é.I“\©¸Ø‡?þ¼ë“¡Å•<¾jÉàá°ál4)pöÍï ³)šìÙ¢Œ¯B©C³O½ËN Û‡š Ó8ÚûGˆüºÁ4.œ§?Ý<³ÁèS‰ÓpYíàl“Ñ\{7\{ÜtX®‘Š.9^õ4øºÓ¿”Ûë×o}=¼j^óðu;àÔb½JPOidn®vãÑoÓÐQŒHìçî’çÝvŒ¾¦Ú@Muºk¬.O›ƒÒÊq½‡idP³ “†ÀÎÍAÞýè2:ƒµÐ©RB¹Õtòi¥/ívrV¸ÏßÌv½ŸÙ·pzq*†‚ÃÄœ'?"d›CÞò0E©;DëJì„Æÿßu?H°J ‡ì¢Ð™”×£²‹~ùk©–ix®Ѱaà X?ð[0&Ú¼ÀD=)D÷^it I¹6É~WªäI)¸¡l“Ô\©€"jl¸ 0´k lƒk.³üÏwZ,„ Ã;ï÷|êNÃÓOO©oÖ¥ܰWÌäKQþ‡îz°¡£ÁˆW“5Ž`twn-<Ø`Š¥5V®¾žãÍ2P+ §ôTMüý˜ˆ°>ª77e5gÒM/u°§™´Šþk3!КõØmÂJêklÏ­õÃξ«=Ç+®‚×]òå3úÇKfᙧõ~ý™ÇúäN”$i°±14ìë´Íð†?‚_x]ÈbŠd ¦6ú4y˜H<” !¢‘«'Sô×F»È6c`üY+‡-ó°2ö[x¬Dël^¸ „µ1w#j8â"þwØn^ÃöÖk9,J¡»ÙÓnô¶£Ü ü2ÂO®Ç AÎAØp a aa0; ^¿8…Š7³2Z`ÿjX ZI\Ø!T#»_§>Û6eÀ/nQàXd:nk[g‘ÎhÔáiE—Ó YÒN×…ûªñûDj{Pç››µqQì_«ú÷ã… 0Ð)ÌL6úî> ÝÓíÀÏß6Pè”/÷5÷áXìEãÏ77 ¯ÿ ÿ˜hõ¸õ0üö¾o*~ÄÒͬ+¿Ãûˆx¶ §n¬Âckµã4,@Ê?i"pL²™©—v f æåh+XZ ‘¾×¼ÏLÄa •à\RGŒä‘œÙ‹ZÁ[A­pÔ.ñû}„l㵌€^´×嘭?Œp^|ëúÀºè+0lG¢S‘ç ²“’7³´Úg€¡§Êe”)ƒ Ô…™†cÃíÛ}F…ÂÂÎM–ý‹>.¹¬r$ЍĒA̘1œ†S 'Hs“HZïy¼¸êà_ gì4\~6l› ò²9xpÔò¸`GQ×€–õ“Wžßÿƒpt þäÃðáÏÁÂF¦âæfáÂ)8sgx ïüdâ9„vS;ÞL•6‹¸Æä™]×]µx4àϬã¹÷“µ:íDzζ¡7ò!µ_ÔSŒMEÞÔAÀÃ3/à«rœ[À·? ~ýÓðš]Aï‘0k×ót£“ðu·äõO‡ïºÞð‡ð¦ï Ú‰§¢,P×£ÙÔ"Rxã6ºFg .€šýaŒª|ÃYÄÖ_«z Xk¾#€y´VÏ$D2²@s]Ñ>G²ße ßÇ<ÏÞO§ ÂÃ(‹À¯¬o ®w’o3ý‚á/D/¢À&á"üspÚ3 µ¦Î„ù'ÁÎËàÚ…?ý^øîgÃgï‘y¼Ô×Shiv¿Òºô3Ý\CB°ñûÄåßHˆñXuÍ< ­±³wI³ùɸK0ªå.Åôþá8º"R*Çrâ¾–WàåóU;~êÜ€ûüê£ÈáùôÚmc~¢ñ¬[-æáÔ­pÁYa.á'Þt&’XǸäk8`ckÄ 2n`ˆIÔrX\‹ HS¡5WCLc¡¿Ò˜IǰÁßV9àÊÆLý }ÖøW`¸h]p$>æ<„›_ª“6³.ú7Ýã6„T¯"”ìBy1Žßfµ¿F¥XR^é) 4NRTB)¢Î¿æ¶Ñ g¯7 EÇ¡£avj:cçÖŒ,²mÄ®ï‘&j‚SYÇ|cöUfƒaNäµ18ÂÄ™mõ5”ŽKf‘ÓÀKÐ÷À×FèݘVU¸7ƒí»`fLtàëö™n< ßò°o4œ8gß/c¥`7´ª´†4O?éó%gÞ—o– )Ýo8‰$C=? §lZþ{·£w‘?lö/¬7ú4‚íN&ušMœ'ŸÓòÕs›Ÿ¼ þäV¸}´áºlÈó‰½Ù|hzÐ+¯Ž´çø¥·Ã] q>@}ü4á×̺¤¡*$µaCØÑ˜@î1­¸¡ 4Ý¢$>ÖþM lðfš^¶ ÓJ¨,°€r †]ã ¶©‘ÍoÀüêsóñ¡ö‡£ñ_¯ÆŸ;^‰ðgtè1Y3åŒÒSE4„ZF"ªŠaè·2aWaä”}+T•v!ìÞi™ìÊØ“¦úªöªR£ÿÚà¶Çï"¥sf"°ïª8>Vg³Ú'ày[â6×,x{çáý‡ê9ïf¯ØÔåýøø“ƒ‘fr ßv:¼ë6ø¿¶úŒûÓ1-iâ:©®o ƒ4køæ×.*«;þÃRÈ™.lŸ =ø¹©îÁÑ‹q~ðp Ê®ôâ½#h~jŽÓÿøý×_ÈWýøŽmpþxÃuÇó4ÌWBáÉ)¤ãigÂåúöExó?^CSblÜ“Â߸gM/°a/`Zþ;¶ëøE£?À¾ë»8¾[>od<"ëòÀè÷îÖ£äÏQ^¼O|ÜB´ëó¢=ÿbL†ÖM ÝÚˆþ ,!„A™£|‚ûXEYEY:¬,/@Kƒ©JxacáÿÏÞÇËšõèw­õ¾oUíœN>ÔQÝ-©%µ²Ô€,d²˜ñ`À¯™±Ç3×ãñß;£Æaüñx0ŽÆá‚ -’@$I4 HÝJÝ}Ô9ž|vÞ•Þ°Öº<ë­wUíÚ§B:âª>Ÿ:g‡ªÚÖ“~Ïïù=ÞÍ2›Ô¬ÿÞ*Ê ž9oÉ+6Š#+†£«†v&õÿ¨oZë¾OpÔk@Û2<ÒçßÙ“ÿ‹Å3Ó¬²n¼žv½}™‘î›Ñpÿnôç&$¦'ýÈo<Ù¨¾àekp³†wÿ¢¤uä®Ë˜ Iõ\˜Ã¯l³€bÔýˆÓ÷ÈÔ†jÃBŒv çáÈ [1ÒÙ™fEU7’É™u8sN_€3‘2ÙDQÅFîÆK-‘–çà '¿ºÆ_Úòj¸÷<üæsД/7Ìÿ¯€ü½ðs ~àN‰Úÿæ·àÙ 2~ܳÕˆÔ K”oð˜™Nó|kÕŸzî`mQ¾àûÓR“ ÄNEOÕ÷ ð˜Žgˆ§'ç4ŠO‘ðm¶Ã½Ž…ÿOíÄà_Šâlø”ë=ð+(–iñ)fñìâ©pä‡ÃUÇŽóì:ϰåqJáêÄÆk\[Ï:æ¥GyÍ\K…ÕÓž3Û;²Õg¦¥9¾–plÅ0ÓÑ£,g´×®6€Ø™TêØV&?ë %¢Õ6^OteI$ǧö¿·øÆ5‰à©–‰°ÜÁg÷Úæ4ù/ üú%xüð…¬›Jøïn„õ»ã[fF}yררšG‚#9®‘QÃKµw®,ÀñCpd–åpé°§`XÊŽÃsëðä9!šìttD‰ž^»ÓŽ)fœöí5,dðçnƒÛ®•Òè_¿/Éh­³Ä`ԵƟŠt´dgJ³^;0;+Ÿ÷úv„´N©9F­ Ž„Eì6,3ƒ'ÃÓóÃãY!–\S±ÏFYÀ(iùgÁ+8àöØQý›Ð¼7dž#86ñtžñ¬Ÿõl×kXs…/ÂÓµ b¢jÖ·èºçd…P°¹ã8sÁÑÊã´ÛŠCˆãG4 m…6ªaÁ¸¼IR‰ä­®ŒÖÆeRQ¯Ž ÒÒ«n4Ú¯mÁµó’¾§A´ñ¾ˆÈ1q`z~þSðwß »[PöE¸ôè,¼¶ QwQQ¡nwæ¡l’¨µGÓ/Nß\^qŒ‡áКDûv+d3•d[]8¿OŸ—Z~«+m¥ø1½‡Å¹ÿhÿ kô&fŽFQbøPe‡¸¢.ÿèvØè¿yê¹,½!P™Ér0NåiÁ¾á¥áfI¹£7¥n Ö,¿8“¨·4iÄy×YºËËòÙìôàâFhýM¦þñ÷ÙèuÆ£XRä{a¢ªƒÇðß4ú7P¼*Êþ$üÓðƒ—†~!Hûi)«(žå"}fð,âY®ÁóéJ‘âq¨9=ð™¨wz£ð(ïôìê k“:mM?·B A–xZ—¶<Ý¡åвay^‘¤0³(F/g˜ïãW"ä°[=¶xj*´P +뵉?ü àÍ«ðþs’ h#S‚OöáÆ™ýª??õa¸çaè¶DFjk]7~øÕðÓ¿ß”.õ,CÍ6µÒ|3û?Û’:°Õ -¹lÿsóA5¸ýâ",¿Kqõtr¾Cæl{¿¸©ŸüúÄzß¡÷\‘—›3x×Mðï€ï¿ VLD ŠˆQ1#p²<°Óè0Z4 ga·'gc½ß:¨&ëimBÓ° UP|JS(r9GVäýðù/!»×'^~PQ  Ð‘×V P,%½=<%žãôqõ»2‹nL p±ÁüœÐ<,Á±µ&Ò./Âü¼0ï”–çÛË¥m´¾+(ýçàÌ%QØÙ6-ºøZ+åL^5°º°?»çHÿë*¥ŠêÿšÕvtáÊsÿÛÍ¢2üOOMx°–)­ÀÊï·¿R¦&ïú}” Ô3ñÔh ZAèã𒜑ný ²M3¶Éhì‰G ³Ñ×RÿëèÖO?;¼ú3@‹?Æp[! 8îó $2k¢ÿ±Pûï ˜aÇ.gnm}2Î…'öäÍàŸ€ós`º¡öG‘ qhï"MWZx¼‡4U<’Í*Ðð<Ðzª E»˳0ßnPê‰øË ¥T[kÐO!y…oT^ÝÄ`‡®iQÊ÷¶Cðñ zÑÖ°UÀéB8çõýÖ é2T3ò¶8+€ãª•V[–Šã©uö½©+¥D†z¤ËŒª¬äñ¬ b ÕÄáR“§v ¸1Uâ›{%N'Ñ—þ“ïÝømbö%À_rå9€5ç•ðŸ‡ÿõfXM£9 h&à9–"¸Â[o’Ïó½=+†|h¾áðšëh¦õh–ºÖN¡.;³TÒ”Öî>ôq`g‚Õ¥§¤f!ò»†×}Š‹4V ‚¢î3;rŠUvé0Ë6=VÂÏC Gµÿ1Ëö;¢ä T<Ʊðû `% <‚gOv n…U™TxïôØ&§FºUSïâeŸ£ýMjŒ½æ ¤Ô"»}!­ô‡ ÐWë­Ïe²€qqFôå—f›÷t&‘7~¶%év»%?«wƧ^·$ûüÚiˆîž)š@ç¶ sT"÷ʼÐjgáŽX[¦ÝL+ìˆÓÑYH¹½'ËBê¾»E(¡Û{¢%P”QËÐ6|&£=|n‚#P_ÓÀ¸\„iþ¹ýh¿Ÿè@€Œæ.™+ÃèÕDkîo]+Ÿéÿû =ÑŒ­{ÆD`o¼þöwI—¥,¤£òK‚'×›±ßºõëþÕx]* [xßG€ÝÐ~ 8@:¢É]Ö•ãÆpp<†ãõ,û^i²Í-ó¿<Ä>¤÷#–Í1ȃ(Žáñ‹¤{Ãÿ% nªÑ *†ñô‡B0©Œð“¤‡€¦d‰¤ËY&)ÿÅm1¤þ@ÁÆ®ô³7w…¿Ý-„jYD 4kÜqÄÛÖ⪠†ŸÔ= ¯Y2QÇÈnÆÓYéW_úlwÄÙtŒ¤ÿ‡èBž×^WŒû¦ôÛϯK?yc¶úVæE3°R+Çsì1o 6nsûý¸¾_͈-{uQ€»Ñ•¦4ˆSÿø#ö1!N Âãÿå×sE_~ìVøÍÇà‘Þs÷õ­Eh–ÇÖG³tpíü¯ïÞ‰ÖêýòGäÜÕ·Žï–“¤°—Ããà·þ Ð}õ$±`Ê“‰œ€Š=že@:­F­Ñê‡gÏMô‚}?‰bC²~=ꮋÁøS®6™ ßO^Vßâ™ÐžKK%¨‰@5ç6ÃBÊ—NKRsLÒʇ—øçáâNñqMO¿ $—¢ ­ÀÐÜÙ­è½,Ë •ao­±±_9/Ûnê,àpk\Jï•WÁwÝ7®uÖÀaßlõ©‚¸µ£I&Ê»`°ÃàF-ÊX¸" ªgFLÀ˜/0q¾8É¡O*òLÁ&‘?;N³¾ùjxÅê•íþÖuðÒÃð㌿÷|H—¹Ø€æßvþö_F¥1âØßóqqþ&Ê$TÔmšiÁê ª£ê¨X÷bk¡„fº° ‡¢¤!¹p›[djùm‡à  ¡Ãòý'áÿ~5ü“o©Âµ¨ÄäŽ9nHVN¾ÏZÑÆ~|¤’k#& ·MV0µ#€O§Òòóºæ ,ã›lÔJõñA3ð×߯×ÄåïÜø |© :™éÝŸi¤ 3%#¨—˜d)Üx,8 “ðÐSð¿ülÔ" Ü -ëO> Ï^‚ŸqÐ|.G}íku ‚ç¤ëòÀ0zÚÇ‚ýöÏ&–ÛQ!¨ï ØÍÑPûë0aÔA¡¸ xÐÌ{ÑÓ™”a݇,…• ¥›e&{]Ukwt#…E4´ÅáUùÊöÇ1ÇÂc`‰žºàNbm—c&l^6ß¾*åÓå./mÃOÞ K3ÐéHÉ’%õÓ$tÔ1%wQ4©;Œô(¢spí^ÏØZ»?ÊVšŸÙ)†>RžˆðcççùæWfôŸfþùCpÓaøGLI÷õø×Eÿº­jÝ…@Òy#‘ÿûï9~…à| þÕûೇe§™”¿óYxú‚œ…´…L÷Å‘^?‡#ˆ¿7¡ ØÜOˆ|DQ¿ }v„<Šâ*fÂw‹‚è0ñ'wê ØFãY… þ;RˆŸXqñ£ ÿÖýïZ*J[·È¦V¥t:-5&Vû“µUE&¨.n?d±G›k#ëöÁFù ÕæšÔº.ª‰¶Ï¾<úÅÜDVu¹Ëª~K£÷®'gm´#bŽm"p(Á¦Yø1–úGÔ`ëÆK€±k0dkë,™>/0våùm‘+*Á-®Äèï§t0ê£ñ?Ý÷<¿}îò™þ4Í€1ÝŘ+J¶4t®;ë»`m¥™céöá#÷Â/ Þ÷)øà§á©³AóOI¼=RÉɺ_Oÿôb~s™x (æ‚ývF´Ê6šÑìÔ/7†í‘FÇÒ„-4ƒp›šÌ[ÇO¸Ÿ†cª¦Gc샰þ¨• ÕWÖŒ1Š£«š,‘´ÿÂöø\Äh(*jQY5¥üDúš™&ó(B›&Kšèo¦|øé‹8ˆWÍɘmšÙç$Ò{Ÿè ÇoYRy“LDbÛDtËøÚ¯Qi0-ªI¶Yén,­ŸæãÇ»°)3WríïbGæþÜܼ?yêy>È„'0ƒ³¦ÿÚ@ÆÉ¢ÛÎeðcß*¬>ƒtÖ–¥ÓTXé ]sÞñøž·ÀÕ‡åOµç'2˵7b\¡¶&3áJ4‹À<0¢€¾m4;£¹QÁ¦góÓ¬†E ¤„ ^ç7IÈ1o«OðãjŸK}*Ÿèþ8+BÞÅaîñ^Ón™1 ñÈš¦•‰±nl7©ñ´4oLÞ6ˆõä||,„Qºh6×ÔjÖCË£‰ò¯VgžÚïÒ`˜Ë—ív=¬-kaÓ98·9®DÃ\ ?>ªü~HBM`>ú³tzÚ÷'¹\½Ò´GߎåCã‹>*iÄ:öõù}ÔÖ›èÿñü'œ]–ìÿù¾$í¹Ø0áï ¸ýzxËÉ+ϸ§ý’è°àÏ—‚ý¥fçž®[ÀIØÚÀõ×Y´%¸^kTC"«òÀJKxg ·›oÁßù.¸ê°<…Í]xÕ Í5J2“Õù¦§™’¨ð³ÖxôG5™å¤ ÉXä†l~&äf4)pãHÛ³n×GIzpåÍê/y0Ñ*›ùº¡ ØDñêW[CR\§âÓÎV!ÂA(è´ s³š…ù“ëÛkT_MëùyâÖ•oêëÑ}Ü8ï;/#€GïÏ#õŸÒ!eR›/|]GV2ŽäOvX'³ˆÉH^…i*í)ÏôÔÒO÷bÞÀ$>0;ÿà/^¹^Eö‘†¯3¤uœ„UÜÿóËà¡ ø‹ð@¼4ôúuØÓت9!A"­&ݵR!u2ÑMtHßÊ„p6“ &°<#4õïxL`.-ÀK7ïµF†·v Ìa Ùþ¶CÒÝ5?ލ°PdÄHñimo¤]5Rü¦œ¯ÿ_EE°ó!ŠCñ™_ é =CÙÿ+¾g¶è€  b¡þzQahEM8Žë–ûwUiÅ ëÏÏ)ÖV éÙr?®Øj¦¤EM·plU³@$8;Å€¢Ÿ'—©%_Ìå™Í Hh¾1€ç‚XgMº©q [KM›ñÕäÏÁ§Á.š^^¦IÓÁÀØ1Õ¸åÄ•]ûûˤóõgùŽ5¸iþùýRÖ#×e( ‹°¶+ßWU“)ZšÛùpŸ*œŸLËpÐL+e8«KøËßßþú†–®‚xlÎŸŠ‚Û(­s;©jðr£9ÝÈ‘‘¢ZÙÔ~¦&â•ð7àÊBT½¼BÚÃpM„ñ ,Ò`ý ò@ÍJÀ ®z8,Ó€ºM(ûh2:¢áPö{òѵC'`0€í=éìkñ].DsÇTsç•e£ÆSsíGTЉ,Á¾ÈÃøÅÓãí¼øºRðºPו“5û(›±SNýDïyY¢¿ã`Ðqê52xoÆËí×^Ù5¾‹€Ð2ºÖ/<û7_ ]‚û7Cw4ƒNe Bn|ʲt¢±0(„í×-d€§>sõªxïšÀb4\®Y“vì‘E™û¯?“šÛ1ŠèQŠOqkg¢ã®@, kÄ¢ÓáãÊB©¾7²ÔÆø%o_ΑF@Ÿp÷™}ïí™ðg_AЦÂPFYÀY4G®{I¼‰4ÝHe×2¨9w‹&¸$!ìåpf.ôdcÔÞ (üûí´¥,ig2Î^ä‘ìÕjLD'Ñ@‘Ùú}Ó…‡ÆE½êz H´FÓ v›¢Q¼"ÜæÌØ›4ƒÒ,2¾,¨‰+o‚ixÐM‚&E3wNã…WÚ‘=\²…W³É# Ð8ƒ¬%뿬—´ßºéˆ§3ìÛþªTÔ÷7‡ÂO!ÕL9øEÙ¬…šV _àÁü™{šH2òtMÿTßO€—1.‘Lzîû@¿L8ÿ1}åÉ®¾à4N=óü2±+¥ x¹Ÿÿ·À†'Qt/Ä Jáé÷ó&@ä¡4(B'¤_Èí3Þ±ÙÈ}s¨K‘ýÞÀÅ-ár:™d ósp⸨)9¨®óõx¦—fã@µ÷ÍrQTø}À((ƒ¨"ã—{¾‚]WãÈæ) ‹§…˜+§Â“XÆq=)† MCÍ|pKÇ‚rð‚d> 9EÈŠ€¬9=RAÔ?½â™¶Â˜ˆhè':Šj¢’ˆe…ôã#&¡óÂ(ãöÑn1a.ä ½äây¼‡ûð¿½Ot÷z¹¤‹Ã ÚQ–B-}3Õg#ºoíò<ì̈x~zYQ_Ö–š¿LSøQ”úˆ7`Fÿ/nB¿V±5ð±ÓWnê_M{9‘äŸ;7®Âÿý¥© ý#š7©ÏV§#@`}ûV>ëQÉPI‰à£¤· ²nݨÿa­øê œ8"z#µ¡èÌ×S„u¤OLX3žp©)·CٮѴ1´Ð´0”h,ËËCú.Rl‹¶gÂܨwUp–Šñ¼ Ï·`ùéCfF‚+ Å1‡¢ØÓaC‚ÇáQ}_:UaÅ‘œÂ…yIB-nMí´eEøpzÕÄÉuó§¡ä“ëàêч‚u/½¬?¸¤™•õBë9ò³Þ^µ'Ú¢/0ÀÓÛðÙ3ðÀhçâyó Ø[…þ¯sAÊ=d£¥žQŠîC6‚•tu_sâµÅœ"Dþ,‰Ö~3½©¦9»ÿwý°¤;„™<þ‡†·^AmÀº f§Dù*òë1T ß~5üäçà‰›ášÎœÓ06GíÅTô!jÜ ®ýÓ ’— x“/$Ý·a§`ÝmöáÔ“pÁ‡×ÄñY‘¨¾~‰ ÑÛ‰Qb-¥Än’GoP^Šsô$[—¢ü-| K|jN«xÎâ9ŽG³ :^\çuX>M‰*³Tl‚ÃŽÄÎ,¼3o糇½ j·° ÅÍæ–£=«™k+fgak;jñ5þBþ÷ûÞ®ö4„dJ}<.£ÞD_cÅäe3˜a£hQ×èÎÀï_€Gvá±]©á¶vaûY(+,/Åè熲Ë÷µêoYaÏ †äÂn¿Q–SɘnxÚ z|•w‡¸¨¥ÔjÁülSyÆS¨ P=~úz7"Ë¡ þèaà›¯Œúr,¾ŒúÿUäX+Æ£w}ùá«á?>¿ð üý›÷¬>‡ËðF·SAûK$è‚"Ó|&2òÓ.…ƒ¼ÒòÔör¡¾\_—2d¾ ó¢8”&0 ãîõçnú_”ÍrY£qÖK°îàQ´0¡vTa{ÐkÑ\Ç£y¤Â2 Ãs¯ƒñ‹ýøÀ,*ñ܇ˆ|;š¹PS˜Ð H˜ £Li2X1xò2­EQæžÞ†}Á ÛY¨Œ…¸¨Ç=Šp5Šj'˜Ñh-ÑT³‘¤UŒÌ»F3 îûŽÑk=|~W>ÌÓ2àqþIÐaž?£ÅC+¢.EZHŠZúq©oÓzkJo0ô¢ÙKÚ 2Å“|“õ¿ ¨þ2¥êò-³¸ àWÊ`Q3-Ù)püÔ¶öʈü“—”†º­híÖÞ­~ýí&øà“°VÅOR?ãoç2…q!SÛ Æ_+5«¨Ô:,uÝÈ{:,Äyä…8ú|—¹ÈØŸ¿$C«‡ 6@´[PHgF¼„G1¨$Å' •hTæÐ>ÁcÐaaÂ,Šo/|‹’û¨ð!ZŠ€è1œæXÐúë"ºâ>`²™ôCáÝï`y ƒ# Z$†Ã3§h+A÷žÒNÍ&ÏĪ˜ 3ònmíx”£é†zs~f‚)7qø+ÿܽúI±Ç‘ ”mjüzÖÞYAcëõbuK¨²R"<ÒƒG6àSÉJñ3›oBC>´=Ié¶p®ÈÐéó0—, zíêqÎO+B›2Ëö÷ñ§Ž>‡ àr}’U}ºÃJ sWžßÚ2\s­JTJ‚Gýû¯Ìþ¿›àAŒTŸoŽo÷aÄóžfl?Dl¼u> ‹ÿºìÚáN©Ú¯9Y;ðÊ c°îö\Ø„înãÑjB\YÁ… ¢ ¥´¼ÿ³³¡E˜rRP˜äxmðZ<žB¡}†ö:¿Ø¥Æó½Ô|@ø¶|°s'v//wÅQ…*ž°SÜr/ž­ô߆å­#'`Ip$¤f1Ì¢IƒB‰6ŽO¢º£¾Z[£Åpyîjå0º{rP;3ã«­Ü6œ"U‚j°¯òͲšÿoÃRÒ–N¼s­3`htïƒß9¶Dr{/‡|EW„FÔnhå’Òõs¸˜}eÑŽT6lü µùꡜ¤}5“Ï»éÑÚÑ,8°F:îõëéЏœÚØ…'Îó—àü¦8ß™¶H§­- ã U!‡ñÂ6¬d²Qߟ¦N–ò¿Ò2þx6÷$ª÷sð»b0½>{P #'PÂŽƒnÕ°ÍŠ Ö…:õwÕÄÊ/ús+šQðjzß¿N¨öz@W¤üÃd êqÏwd0åªÃ²d¤ž˜Tâ NoÀéuqƒ@zùㇾvZΜÒ×Yâÿp¬:ÿ/Ï4Q¿•Š\}–¹|ž¸ñlb„/Õ{Ì”ÏÇ5ï}–I™ø©ûáˆõ§äu£òëÒ†¬ WJÊ$° ³l¤0Ü×eR”ÒAa|‚Î Ç <ß%+ï >7ÊïmPù>‹×Üçå0Ž6–4Ä÷xøxã·øQ'icÈòT†VKÓÁ$­J‹T/ƒ£pZš,“âv¸ëF“j‚t*vö𝹉š^5^ Gdš âŒ?ÀAØHsÛ´âêuØõJ¬ÚˆØs]IçûAgÐì=¡ôyÓIáU“îo¨òp°Žþ®ŠJ)¤CÞGXˆŸJþc~^r®=>žîºìÜŒ£Úó3pdYZ†+‹Í¶¤n.šŠO_„ r¿‘*q4Kà=|ø iîûl§pbë·SJ¥¼ñ$üîé€ð§¡EþZ~î ø£ˆð£±çV3û‚n)ø£as§ñöÉ{E(§³ˆ¥œ…åÐæïÈçí§uÒ1í¥˜Ú„“(~$zÔ3Ñ?ÅÒÆr8¿ãõ^€: ÇÅà% K…Eñ!d©x:áœDµ:-©TÚEB[24­D©Dcµñʨӄ}!½ž u.B·•´Çz9¬­°%uD¢™¨SŠ> ?‘ò¹‰Å–qÏ×׎‰Öƒ² .¼ïœd;ÛbÜÕÊ®¤ûƒ þY @uå÷5a¤çe*¢æÛ*êû»ñE D€ž§Yß•µö³cfäÂ\“Íø‰)H§e÷ßÞ@ÒÇ#+p|Yæ*8 ½¾¤öO^€KÛâäœßO2ò±ØŠ‚_ÿâ•ù§ñ°ÓÙ~8øáëáÉøân“¹Iép7ñwì~¥©Dïo¯ú0Id Üûdr›˜ 9X3^TePÞ•ÏwÄIÕ[¤²6›ˆ¤¦òã!Á`wðCÈXB„¿?DØEÈ.;?‹çA¼æÝø±, …¥²Åà0ôB)0Þ«ƒçG0œÄ‘‘`²„,5¤Ê }¢Ú*e8£:aêxX÷¿.Zùí¼8‡€O“l;í´•o"þèvv?¯ÞÌ㜠±uðñsBòHdl·½9öê, `ÃÔðÅPjº-¿Ÿ`]3$¿–ú4y%§Ÿ&výš[í&e~Š2‰Å91üùñörxì Üÿ$O_‚ÇÏI€‰©¿DjùZO8‚ºÍí$ãÔˆÓï´ ,fsljöcÙÃQÁ1«ù«^Œ¿fõ¼CƒÃ{îai…îøq±{y=ÿ‡xÎâÈá°Øà*g€_ 8¢8Í#i‡!)²*¡hL¥I´ ¬ŠÍ¬­E¾gà˜Ò¯[r{{òu;v{ЏG„Š×Ÿ°õÓÛ`õA) Qf?F`ÝøÖ A0ÀÓ9¬Ę–Ö,h‡ Du'a4õg¡=d\û ØK鯣|¬ñ7™Õ óŒ^C|ùÙh€'”ÔHËîÄšô‘gŽòði¸ï øÜ£ðìzh?E=5¥.ß6œ¼<}þþ=/œ&ýåLù§1kPU×ÿ®1Ô±@÷mGã¾ï8ŸxÖóý/'JµbB·/ŽÑÇoÒÏç‘÷9Ï£³J=³ó°´$£Áz¢,p!îäû#Ëa}Æ9­BúodõeG+Å_ADÆê·ìH8@}`?K GìüA<ïÆkïCßþV` GŽcKGÜ€£¢E…âQ<ï‰KÍ‘qC®­DxÈ¥Ž¤glyåǦà\Æ#ÎB·+¿[˜fû'Ôt'=¼³ãÆb'˜a1+ÐEmÁ‘͆» ÃBó_ùFݸÓjv ôrxðIٸ׀¼ÉâW…Ö¡šÎ²™*ï8¡C¿¾ó?Ã7ÿ,<;üÊD.ý÷7€¶Œü_³=óÀ¨/ßx>vfJj9&’n>E4Ò=¡ÒÁê²dg s0ÛiÝŽôýT³Ænv¶ù~´P+‘Ò¤Õ–×QÁ9áú9ö<·žïôãÆÿk8î 8¿% öë¨ØOý¹ ï} Ö—»Bjàq”xfp,ÃÏ©0£ z/*¬ q(ùæý÷úÔΠI´Æ Ž®é–ö~½zš?ל¸È*K– Ô=D¬<×ÿ.ªíCÒt£9Õæ—váïÿWxëÿ½Ì-|ëMpí5‚e¸௠»ütHv<ïêha‡kx“䔺U——ÍhplYá[ QE Cïü†¤úOkR|?%UõS€3G˜PSÈUÏC0ôgàm?!eÁ—óÒ~ú‹ãY†ã¹¿®³¿:h×2_#ð7¿e|–à{NÂ^ \Ì1ñ)Kô4Ò€G.HÛJä3­Ù|Ó°•_ ‘϶–þб˜™Îˆó|¶‚tÇëo*áÍqÈÑŠ_Ãó™Ñ,`A…Dzˆe&¤þàx0ûˆF]GG¯Š—…®ÀŽ D%HcG u ûÜ äh¾ÍLhcÜäÍqeܰÃ6 ,žD³Q8Öb‡á¼šZoueï^+iZ3Hb1Lzê&’ „·ABÜI½å¦”õÐÐF~ú÷àþ(¼¶9 {OBö2iá|ûQH¾þÖ?GÅ• S½ýu~†ñ½Ô‰d *²f¥Æq µ€¹ÈJµSØS2%¶8'¯£^kÝ/ Û“lA©fœ8ŽT#Æšw2—+ùkµ`ýH{ü½þÃGà}÷¿ü~xûŸ`hèá>ü¿ ŸxHoæüý ~ì›à/¿–ÃkùÔYxÃñ‰çæCÔa„¼.ërÛ°<§]®ƒWùðw®…€ÁøtádyY;ÒITOÍøïϬ‹° má¾jd¥¸ Ã=ÊVY6A Ä9y=Êâv*†}ø'Lþ…WžŠ÷& _(ª`ü>üï°tCYŸã¿ ¸;dýŽL~øîP láâ¸À@e%%p?Öþ<ž>RÞ+Üœþ»ª^ƒÑžD1¿ Î627ªiN´²ê,`·'_/Î7[}Æ”r#>€@ÂúC¶Ñ<}QoÒÍãT~ÿAø¾ÿüÁïB<!Æاàö~ëËanA`g®.¬* þ¢6¥#á4TIã¤bgW_¾ùµCæM'àêc²|T1ÉÍ]Iñ·¶#ÝDš]S£ÿåÒkup[mòªŸ£C°¾ ÿÍÏÀwý<õË‚ß~¾ï½ð澿i‡¶Z²"ýý:Üñá›~Žý}øž¿õÄ}WÀˆ‘’—Ÿ øÉRÌ·Ÿ„G6á©A0Ò¢§IEÊ®¬^Z tÒÁ*Y‡Ãn_–Ù´˜;,C˜­ïm¤FO8ãPï׃kÁw¬ƒ4;=x‹ƒ™ˆ,Û7†ÿl|ùUQ¿$Æo±¬OÔý!õŸ†­0†Üœ@†c>¼2qHaNŸÐÏùêd7Ô3—Yþ¡ößv_º»SϯM÷ÉGàΟ€ÿ×=ÏÏðßú³ðƒ?ù|‚ùÕè0þªŒÑCϰÍÀ?ü­(Õ>¾šsß/ƒD×óTyýŽc°Ô†ß83á 'Hþn"ª"±¶ ä¢Íž|vÖNdcj¼ï¯â¶  ÁKI0°z-øå‹0Ø#«ÞçÛ ÿ&…g•JËÂdŽ’,`vË–ì`ãç²oQíÞŽãL@í¬°”d”xJ,{äå¿ÅñIÅHØ£™-­zÃgW9FÆÖûÈø}Äì++)@–RŒŒÜ7œ‰öšuMçÀ…¯mhº€Ô½ÿ?¿õ‰‰×ÛŠšÆaFÿ÷ þÒ¿„·½~ý&9Æ7sxï}LµG¿^ûNøà?€öÄ ú÷½Eþÿî›á_ÿ`sàQ¢,{~CB2OÓŽ“?”’ž÷e¯@½°þ||éçðó×þüÞöàO}ný ø«?Œ:ê‰×Ûud‰lS«èj’Ð}™0üÊ7é~ý3åö·Tø¥  Sùú[NÂç6¥ Œ£„w‘…ÂèkÒô`ü£ìÃÀSayVÎÂv_Çœ eœŠv~˜‰eÀ*ì~¬«H—x 'gMÁn=Tj4÷Κê?Ø­4…2x*f(DÆÇÛãŸöN áwá¹ ÅÛq|(DƵ@"¾< •BÅ=êqR¾ß+5å¨(ÕanIsNÓ¦ï'àLJcâÿwº"H‘f2#Päbs&âŒ6çFY&ŠôIä,¶ûð›Ÿßý[‹þõ§Ò“ÖZOÁù³ÍIŸ_‘©¹ÚÐêš~}vvà¦káÈ­PÌÉCÍãoÎÂ÷~#ü—ß–?±º ?ò¦æ=¿ï4líÉZœ™(ß&£ÃáÙ§ž¦FÎÕ$&0Yü¿À-(SGÜô0òôEø+?ßüJøÇï„_þ<üÂ'¥‹ð¡‡¼G0Ójt² Ã=0ï+›™c]ÅiÏ×Np&¤õÛñ­Gà7ž€{7áö¥æÓ†ÒˆHd1ÕØZÑfÔIÎå=î šûèFC/õ­²’Òg«ÎÚáÿ>^UìÒo+÷©ñ_ªt2t¶Ì•O ]P`0þSñOFÿÀT'°…c9D¸9<] ÁÓ "âÒ PäŽgí&5ùJØÝ”/o¾þ¿wÁ?ûþ¨«àFa܆rRø¡k&¢Z ¿}n»VŒüâ|óÿå—àæÿ>ó%F³á΋TT¢'Œb±š6T2A)Uj¿?ïþ»ÞGÜ܇Ä݃®úy\i6Æ“a¥®ÅOö2ë°±÷>ÓtÆJs{ÿ€ŸFß¿i ÝÂêȱGœœ‡ž"š¦Õwëq9«½^øYø ‹Š0 /×^_°®Þ¶¬°GG} VÊþg—3÷»‰ö;;ô CcÈ ÚP0GI²T±ÿmÏmü—Í&€RÀ](Äq[)ñ,FL8q½ª"Q‰Æ¨!éœ_tŠ·ùYÞÂCvÃËÌÄÔ½õå`LÆ‚—6¡uDÚcyÊñBXaë ¸HðÞzž=j´l¢—£&Òÿɦ²‚׿ þÅ_ FìdûpÍöŠõ±ã£¡oZß›‡'÷Ìç?~v/„ò¢'¨é©§B=X‚'&ÒÿïÆÓ÷ºä"pIM¦©ñÀ‰ßŸöXd(ê2¼5ŽÆ_–Ccv6!7Ͷƒ.ÁD—a0ïÑß÷ Ø7íoÓñòu3Vÿye&6fàÎ5ø½ pÞ¼M” h%çÜ¥•žf*d±f»ïÖðȳrVjm¿›©áŠ,pÂq“ÉŠó—TðÔã§¿¸7{ÃÀÀ ò~ˆó¹‚§~Ш9,»—ü^”˜( j'à¹-p*vBY¹¡(CWD‘h˶ºÄ=·]í{_è)íû¼bŒà‰çÛÒ J8æÆ×^÷s1‚Ô9h§1ùTZÕ8ÍZy§;€÷Z‹Ì„¿5˜0~Åø^u€ð=¡oà·¿÷?+‹~ðMpx^^Çù!üÒ'á÷>·¼þÝ÷ÃÜuJPìÇÏÀã_”÷*+‚s×M«T*˜ iå`0¶¶IõÍx§úJí猾˃IÛžfô~ºÐ9óÜÎ"~>‰–ºy~¦Ù¿2ª<Á°_‡‡ÎÀÖ ,Ýpã<üçÅcÑßhÁŒ†Ù^½wá-a¶Ó 6\¿>íö!Œ,fM€“‹‚_Û¿m©úsé§ì_a4±ðMGá•ËðàƒÅ X9tjüÐ+† µ%WŠbOQ¶\  Ÿ}áÆÿ‚À˜¸-<ý^ vñT£¾ŒV•(”¨ŠE¦.¨'_Óá¾ÏôxÅÈèÌ8â[p6¸ékùÇyª˜™‚L»%œÖ„«¯ë_£…Ï?&WärÕŸïGÒ÷€¼1³ ÿäƒpvSÀ«­m8w¾yÎ?ùKpzO0þ ñF E˜ñ®‰$&l®­‰? ©};YÓfJLX ŸŒ²5¥KhÈð}t[½Ÿš:­vu=â+Sj~Æ[z*Â-Z-X]‚«ŽÀ¡¥Æø{9\ØÝÅÝ~¨¾ôÃù¨‡jâÇBËíð%°v¤wS2{ T!€¹è64`^O½ª+~ߤ[1ß’å•|fË3°4å ljØM'­Ãó œLນ†ïQÑÝóŸÎ´ÍCÞQä-ïËLSΔTÙÚ²]\ÄqîÿbŒÿgv ‚:šöPÚQzG®<‰‚ Gëãìì<”–×”›À¡­¸2‚)Oý¬‡³¬ìÁ[fa5‘vÐî jïxQ!³V ÅÛ¦v»þVxü”|`í6ô§­bŽ/'ào ¼ê:økÿ !nlï@ç°D®þŒ ¶£^[C–Ša|äsðÞÁ3ç"þx›±I²"ƒù*°ØêuPõî·š˜˜ §¼±ëÜÄdš¶ M8>ìc*êò®_PÇOFùɯ.F&8îs­Ô¬[}½\"¾?#È Pu– ¦$/ÎìÀÿ üÜ÷ÁB ­ž þF„~ßJBeÖàðÞͦð·n…™`ÕµÓ¸`áü^ô§• è¤Áé塆σÂÔƒ<<®aOÕt¬ép*‘¿3#ûçÃtgµKa¾y†Žª0™.(}©*ªþ`ËuX¶í³÷yŽßé_Œñ¿hp 8¸Œä9Õ ;)Æ—$Ö2ÔŠá3ØZçP¼&Yê’Ðp'ª;,D)’‹„‡M ï; ‹pã,\—„ÁÝ%d yL¼óuðo¥•4è¾um58€¾^¾ûåè1.”®„]™á^]‚s—¤n\YP³¸¶7áôYFËuø¿ðÑ»RȽª$P î¼Þy¼óføâ9™)|>ú° ,mîF DC-oƒUXÕ›ì—ÎòÓZÐS ŸÑ?ƒŸp0I"Žr¾5.÷^9Átzƒñ%œê9ø™–ÎI-Ä9‰)œÙ†½~ú]°”Œ??w÷I™†Ó_Èä!L‘ ?nàø’Ì,läµ ËqCþè|ú<<¶¸ ÍßñY.aÆ ¹(M¤TXœ‘s7“I€+·.œ6WßpZûªðJå ¾,”/gÖw*øû¶îpÿqàÝ/ÊŽ_´8'°%þNW”NS(E®C,ƒm>_œI[œHCµ6ƒ,‡lG¶ªôf¦Dæp`v÷à¾î \Û†W$aª-Rý©¬àØ Ìd=Ë@·Ä˜G‡¼nÿÍKT}Ùb@| ; gži>¼nWtÒÖêɼ`$Û»r°½køä5ï[+X´°Sgá:+‡áo¾¾çvX‰€®·Ö/7Àßy}`þ2<ðt8C!_\„¿þ6øæá=_€_ÿ<}aºÁ×ìI5¥®W—3úç0xŒäÙŽaqÏÞ…XÈÿú9:Óœ@;•,`o0NߨöÎnû?ÿüSŒ" íQ¹˜h8™=¿çsóŒ$®—0ýÅ=¸Ø”l¤(Ãl†_[W·ôNH-ô€¡“uc‰Ù6…Šº„­.=ñ‰tu%7ÊÞSb|ÙVΦŶ3 ‡lñP=Úûîý¿,`wîòâî ä 5l¯KÕq”>¡°Ž\{†h†ªÏÇ Å÷f-˜Ymd—½‡¬‚™¡¼y›í5%…];|a¾Ð…C³pÓ ¼2ÔÑÞ ‚kÜqüá§eB«Ý~7:@õc‡æ5 Mòòëà̳ãEâò¼á‰nöàžÏŠñW¶ÙÞG~”,üPÀ²sBþæÑU¸ý:8¶?p3Ì>w¹•5£Âw\ ?ü¸3šŒû_^/×'úp÷ýðþ/ÀSçÇ€VûÓèÉôþ9>ܧHö3Ój&âêϱ_4Ë6c çÏ4–€ão·ÄLæ^7ë‹ÏÂÿþøñošÞÕ5½&ÿg/ì´_7#ÙèoȾ€A™O #…kÌ®R°À±DO½Í´ƒÞÒH²—• ~ÊÍr –—îK•/”2¹ó¶ly*­íu*»”àÇïñpçŸÈr¿L`Ì ÀÂÎÀ;èQµ<¥‚Â)rU2T-þ˜‹|o±íE‰ÊY&D 륮Í,œ(%@oëI$–‡š:Ú u©—úðñ-X››çàÖ8¡àí¯€–ƒÔ7M¯µvȨ́p²Ó° _üÎ6Æÿ–×ÁÏÿhCùå{á=ŽØrÑ´X½ÕE)ø{ ~ìÍr¿ß»¿>D!#¯÷?†;ù܈ìʼã•ð7ßtùˆuÝ ü½×Ëõ‰¡8ƒ_ü”tSö ºLz?aôF‰±·29°±3q4#öÓø/ÄUPÅIas¢Ì™>µ‚O??³?rǸÑÇ­Í?(³Ÿö|.GçAmHæS¸ Ô&Ó®™…ëZψԺµ‚w̶¥4PVC˳,¬¤Ì»é˜diÅ3?®¯¹î¬Q6W¨RiWêJU¶Ü±³iâŸÙ<åo}ðNÏݼèèÿevárð.™ÅàŽeª¼¢Ì,…÷äÎëŒÓÎð¿Îí»æ–ÄÌÏË(p½ÔÓ†é‡UGÃɹ`àb ç&ì[å»>ëÇ7¤Õtõ ,_vS&µHƒãÈÂÁX †³8ÁÀ>ýø•Áõ×À?ûFÐ#.îJF°µ=5kªp"‡òÿñ¦&kyÇ!x¢§û¡­àâ>Ñ…o˜»ü[û/ÞñÂ?ŽëÚð÷^ Ëmø8Àø"£ŸmÃ;^ßuKó³ûÎËÓŸ ØE·„'KòÞ§Ãn„| ûpZñýB@øœÓ´YÜ©ì. ëîãýJ^W¼!¸þÜt”þ¯™wÌ_¿&¹kˆ{+™ž«ÂÂÙ^g‚¾e7Ê^#šk Â( ©ùAfz°¶¡ñ¾ÐŠÂV¾TÚ[[”®ßö®}vàï³ýWHPûf·¡øž ˆUa(RKá9†¡nñ1Ûçv6E¦tpüˆpÿûCa~ùze·àæ%¸þ*¸9É­6›IŠwËÑ€Ú+Õ’@|!„‡V…'0ýðÇk¯oŒ­>ùkÞy>|QŒ¿ÀÂnÀ÷¯þé8€%à×þܸ$_¹.ßù ø©?|F®†&s„ïfÒ0*¬¦c *Z¨ù¡'àUGÇ|ÝÈ? -<1€'wáæxCûŽöºJŽUQÁÙ=xz(ϯ {*àѳÙ/·ks°:#çî· É«WÅ!\xàs/½ùm—Œ¯ …7ªÊŒ­\¥¬_ZsÏœ»èo}ð’çîw{¸Ë_A@”€âbhÕw°TT¥¦L,¹5ÒÔ)¿ïJ¾ š2< ¯ÃòÕ‚À/ÎA²½0/põIxè³ð™ûàÖ— ˆ²µ' Ê;ÖàŽ–¬èz¬„ól¢OÞŽG'4ÿ%ÄQç_Ü¿8WÍÃkÁË–àUKâœÃwF8=)¢ÐSâÇÚ²°ëYïšå÷/‹"®i¾¼cžÀ3½@W°›ÃÇûðæ™?'ðÚ¥/ÿcþÐËáß}tº«IA›¼ß°’‰ÐV[¤×tdð5.4" …6Á瞆×Èï‡öä}~¼'cÄ{¥à=™–nÊ‹qX0òX¡o×SƒÀ-¸´+Ñ=1 «riV&AwûRînôåõ\w,”ƒ^¢È×?•`s…Ï+O¡óa¥ÀZ·íövÜ!nuwßvëŸ8ýÿÓ˵ÉP`iQá(+(GîCÕâÔ|'ŽÎÐËaëQØ: ‡®‚«O&M¤VZ½6ž€S÷B÷f¸åzi?Õ££ìÁg$eL¸?‡ÓC‘{*líH¦2es½CøBàq{×.Â5 p|nY€;Wå¶ÿøûá3OãçeDœèÀë?´ /Y¾gÊÿŽCð e£e×Òð슙L}¥.qÈYQðÒ“ððÙ鮿 ¯´6žÖû‡9cãß²ÒŸ/¿z”‰€­™#YÝl&%§Ý޼ðç´î%0y$ëÌÃŽÉzlœÛ ¯ÆGÚpõaÉhwp©Û¨ Ÿ ÃGg?ñ¡ßú]Ÿv¸O•/µNË>KÞu6cî-7xÞ…ç.u¥:€Ná9cK›C#G3ÔŠ gøœw¼i¡CúD.=—ÎÂÊqÐ0 Ž¡…þžyZv®}Ó$ g™DŠ^HÔ‡Û;ðÚy9›ž´pºÇ0v¢p»à.5d3xä‡ÖàÄ ¬­ÈÁ8¹&#ÂN5=úÕLˆÇ–áÿ(à´b$ÿÅ2XŠEô.@¹"’ úo;=áj?x~3ô|S-YÈá7ÀI à þp](½ß°ÂÔI¹ã îX†µ N~… X=ã>èâ&HO»zLàù8€õÀ!Ø.àŒƒ¾?ˆÀÜi\+çh到-2Ðc=¼ð2uÚnÃusBüº.›h>Çå‰!ìä!£4{yܪ¼bw¦VÃS:¶$ÆÞÊDãb§/gÂ9É® œãsŸþT÷úoû¾xï†J©¡r*wÆ”Ú[»P`wÉÝü¹=/žù÷•u×áøš“ÁIV”hŠ rczͳ*á“ÞóÆZ39«æ°ýt·9H:BêIáoúðxž8#}ÔìÉ<ýÒB@9,idªá✾ËPœÀZØM¸¹K3ñmêõO7ŽÀØž |[¹D%…|èŸþ,Ì…|~©- Ür·.Ãl×tà53/Xë˽ý‹5ø‰Ë k¢…ÚŸžO–õÏvy¦rÐ Àm‘Gx² Èi8ß—»´`ù|Ö#É8×/ ¦sí,Ü4'C¦Uï8[À¡¬Ñä8èòØP ¼é~jŸÊ«fåüùmy¡i"êNµvC7—Ö  »ÿºC ZY;°uú?X~ý«w´õCÍñ®L [ºÔWà ü¥¹$ÿ”¿Â@(îFqG˜laQT8 Cëø„÷PòFªÐ—Lœ¢±>dÕºJ|•BkFh•u=½´"·pæ"€ âÓCù¬39†3á÷á3›ðÆ%y=›¹à y½º°¯(%õï—RŠÎ·›­ÃÀÔç¤f5^w88–÷ÿŽ=ñ¦oü=£ÜÀª2×ZÎP¤NW¥Nì`®²‡¸öËþ}å2é³{Nã9‰ÅPQH€chÚðŒ¯ø$–7Žtžýe>øX¡þá €úmIÿL ©å¦:-9JÁFœYDÈürp¶j´öuÔßîlÁO|—Dú3Ü» —†°1UÓð´Ç†nâß)ἘË#ü×'áb8HëƒB]® ‹Ds­5s; ŸÇ>úwÝNïL¿ÍÖ«x¾FübӘɽÁ9Ï$âLç tøï¯ƒ—­5@n_D“ÃJ¨ÌzbÕP‰0JkútéàTØÐ+'ÌÒ(X9D¿áø²’ƒ¶ëŽÊ‹xä·~Ï{ë7¿7ñnè•hU唕ž/{vï¬w½¿ï¶Ñûå¿¶2€: èàØ ``JI%Ý`€áŸ àMÌ…ÚÜMäÔ±Ñ_†³N{»./Á¥R”€Šü,㬠¬ÃÅáOS©ßêÛ¨È1|~¾íŸ6·­GyU=Ö©$Ýüö×Á¿5‚,«Ó›¹K'Ž¥B>ÓÑøˆÌQi`\ ~/;!1pjnj‡º¿߆m¥ò³…‡.ïÀ…òËEÏÏ;Xœ•ôßýÚow½ã¿¢|9ðN œªrc’¢ÕÓ%.±‡¼}âìiýÝõ'gþ}õ2€8 ,@SR ²€§ñ|ˆœïHV‚Hˆç¹5ìè1í¬CzLÚA«‡›m/">4â84ëy“YL3þ1”Tê`ÔûŸnú«pÃJ3È2Ê6'à…´ŸâËIàŸÜzÙÀ©~³°2>Թ̪ÛhÎ|¤™§÷cuZ]_n_…•dzKàu+ðÃïk¶8MÝwÇ~U`õ"]YÉí$°}¦¡2ðàxÕ±¦ÜÉ]4MªÇ¥ZÕ¹võ»v*ÎcXÂb"ïcYIPDKD+¤$ØèŠfAʮ噠¿@‹­üÓQùÙ¥§†ý³Ð3ß°¥­íÛ¤¦¥êª*«W%ë—\÷Læ¯{ûî®S_¾ÖßWÁDÄ 'pd¡#P†}Ž!:è'¼Ÿ’·WC:jüÎóˆþ°_×¯ÞØ³‡F$ OC.%í´%•íqSã@݈ÖZù2ÎCWK5êû øßß¿ðß6݉r}¯!?IkoxõÌtDßñи0æ—«ìøWÂO}âòZ„ú9Jõ|Z”ÑÂÌN„§ß÷(ܲ&ÙFá"§G#SGï©W̵R)*ëCái¬÷àÑ>ËÄ9ô 1öÝÎíŠBá…§2í´TQ¶vÕ*^¿³wê O\õÎïø]”ïk£Æ©!©.œê—Éž³,,Ø‹Çâè¯ü—Û25_ÉËÝ! X ÎÖP‘…2@‡2@³NÂ/1ȽOhš#0—q ¥0ÇêKRˆ´l”uÆè«ÑßQÓºµá›ƒ€Ëˆ›R“Öš†Å |ŸõN®>¿¾ÜÏ^ÈïºÀ÷\7 óaªÕ*lÕ™e⪧\'o£"a¨T¦Öóõµ›Ã¯œÆ`ŒßÙfÜÛÚ†º[/t© :ÿÖÁæP"þ±D²¨ ¹ð:*׬‡¼ÐGP†NËê|#q^gEùÙ-GåñûËn6ßúU3;»e´£‡h•':)*ŸVm3k»ÉÐ_·|‡âÏŸÎå+è”8Á;ñ\œP®³ÅEŸ„ßCñh1„ÖÂóþ¦~ø~fIpÚHU›‘&*dJtéšHý¯ûU´llùFLD¥,ƒ¿ñfI)‡n¼mí\Ó:*^€øxþh¾T4N¤¼ŒA?_çð|£þ´ûÿàË0öƒŒ{â:¹y\p?¼DKm?r “ŠÄÀJKÚ³ï}0ðôm³yªrñá:È~i¥30¨`{zü•|hk-x¶'Ÿg·Àv!÷+B½¯õxôÕþn¿&ð€îÃ_úœ½î¦Ï&‰îì@9;4ƺ*«שÌÚÀ^ÕÚq·Þý§ý¿òļDz€ZtBÐÇð_èÚ}~ÀߤcБêVÀÆ–wøy®À0¨Ï"³ý—«û÷Õþæò©ë-'eÎÞªnÕï|I³Ør0σ>åSÞ»ú‡/Â3öÅEðç2êz¿×›M7ܱm¸ÑÕ¼€k}mÑ×N6=kP„]™Dñ/œ‡_|°©øª(ÚW!¨l#@Ó Ì¾A)Ó™éH´S89Ït…'°Ý—û ù ‹P>¶áL´³$Ž.ÀÕ‹ò³ίæ:¿•(ßK½$‰´“'Æ”v¡]éü´ë=Ý÷[uôWêÏBewqX2*,š²M”/)Æ}˜[˜‚V\._¯¿.àX†ß×™€‡½=1æ…ùhOãuÿè ›òwë,ÁO ó »"Wa]y¼·Î5D’*zýàâ+v+áäVøç¿y6üø`ãse<ã~>Î!¾Xà;nn ^O3r5~ÕÏóª&îçÆdÂ1ÔÙšÖ²($ÑR£[ _:­Gu>¡•gúnå'²0Ü+¤%9Ÿ6kæRQiÞ ›£Jºá3\›“Ì ö9ÔG%QpÇI9ceb°yéwÕ‰«1ZõQn ½Í•¶…±eÙ–•Y[°·q«Dÿ»Þí¿œ}ÿ¯~PÛÈu8.áIÂ’QO9ê8ÆÓW)ï§ÏFYB¶ð<€¿È1Ì, ê_9Ùº;úÝ€& ·DœqK g˜›ßŸú×€Ž~âoë‰ À#ËŸÚ )g8xÃJPåXÇ¿tãi|µõêÿ¯ÍàhGRÕ^p= ¿ò4ôüø}\„qÖ²jñ´Z|å:xŒùÖ~c3ä:a«wò=Ï«‰®Š°,6´ZÇœJøÛi"Üzê®Vº÷B$5GÈ´aƒt-Êb­ysA‚ÌZ)Îwa1pøŸ„³…Ð~•e06d©‘ÏÔ‡ssûÕag°û¹vW_ý‘$ѽ4ñý,3“™Ü¸ªôª]%UézO÷ýƒ·Þíïzw½Âþ 9€PËÜ  ìÀmªÑ¨p:âô”â¢Jù¹|W¦GMóçªÿô 67'Z‰ #i¦ÙYÙ<²V›ýuüw”ÙÏû¿‰#íç ‚+/<‘ƒàê‡.ÃA,}“ªVáÍ "B1,%JåÎe•Umè¥7Ìm5Äç÷oÊy¡×iYBÕÆn0âi€Ýe¯‘Ÿ7ºÞB/辉KŒ-,uä5ºn >| .öÂÒ•^Ø|©i2‚$´g‡¥t6úòxË©ÐÄw+!- CF6Ó‘ce”{UÀ œX‚k–ÄÒg‡;e–¼×Ì´7µªúZ¹a¢\Þ²U‘ºV93[ÚVÞs·qÑÝvê]_vÖß•”È ;F…cP00G1°š> =•r/žw{°¼ÊØvƒÁü’ˆAU1‘1Ô¯8g”;¯­È‡^ƒ8óóý~šÒ@ÅíA¦o¾W•ÿáÃ!Ê„WgÃpÁ0ÊP—ºÈL|þ˜L?x*|iWœÀÈñ#¯üÀ_´y´hdÚÕ?w§ ~,Ü„±`èvºª`4 kô7¢Œ"32„cLØ!ÿ]D'°Žü5IÇ d%g›Ÿç^jüK¬ÃÊÂjG~Ž D.#W‹8ƒ4|ßN`¥¯<ÎHŽÝ}èÔ‡¹öºû|ß(Ýo=ЕÍ]++µ)«¹Í[;ŽwßYGÿ§m„_%eó¡4ÓXr*”ìD3P²É«—¶øù²Ëi¥aîðs´ýŒDt…¬ó õ„3mS)YíUÐŹ¨Ï¯'ê~3áö­‰¿Â\ãL¦ác+¾F¿s~ük7™MèqC;cµztMžãª&êüúþ¥k€Àøo.‡iÐ2Ìåuœ:/µ}mü™Яβ¬~ÿzOhÚehÖÆ_Z‰'ðªaIІÝû:寿á}Úønšèžñnèu’Ó*K5°U¾¸b9é¶–ïpüøÿigþWBÁ{ð\ €`+d ††>)=]ðï7×ÃB…Ù‰žQäZ³òa‹@ø`Âè' ûmXßl„< Qky逺šÓ}+xêaoá¾Gáýnh9…UVò}¯’ ±"6lC1-­pÊî×_¯¥ðÇÅyáq*¿òÜ¿Óde„=¸`ñÖí/^,`²,¨}alìõBÓ$´ïâësÕÿ“·¯w«Æí¿úïdF$·´~2;¨ë©MùÙ|D9HÛ-d·D·h ÞÙÆ×*Ñs™´ýêµ’5ŽÐ Š¿>œ‘[ŽÂJ8§ƒ'w.æ­ä½ª“m¦Ê÷•vƒ–wÃĺ¼Õk•GŽ/V-ƒãî¶SpןbÛïJ*ÆK›p´°´©¨È\9JÑS†®I9¥+~¥?­½Ñ8Ø„1·è¿×=€(;‚@ íE–ÙûùŸïÎø´Ô_E´×øñh ¾òZø{ßÔ0ÍʨµNpšä’˜¦¨bí¥®a_2 ßr¼1è*´ÿÓðä^³yj ïÆ±{½u?ÅÈãh¬Õ”ÍÂjúvâIn@­±8›5Na©#·-œ”G:*9jg0ßÒN>£Zbk(N¸ž–´¶Y/WN5s㢨¥aÆÀèFæ O.ÃÕKáoì2Ø;wî·¹æäñ=£|?Á ”N†ºÓ)“¤ªv.¶ù³¸/!©¿úÊÿà¢Rà<]<;!H)´b¨|ãÒ~­·Íç=°v˜ýB!©oœ—¶ß¾}é^!ŠBÖeš6âdê_¿sj ?)ΪëzóÑó¢OgCº_Gí:¢Ûírx++=wMÉ»ñò ,á•ópǪstKø7Ã^ ´V¶Yª9™ÝÇÎ`ò:òëŸM½}xk“ c׬׿^ZUN3„µÐcÜŒ—ÆãÄž‘ç{z¯áýï ÿÊ•Ÿðµ ¯­ ‚õò>. úé=¹mKdá0,¶¤î¯˜ÝMQ½7Pf˜g™+’r§²Ã"¤þý¿R©ÿ”D Á–¢Át‹\i†ZÓWžžRt[mþí…Kl´Û°|xÜ@³Ðþû‰B£ˆm&rØÈ‚Ëί7ƒ4vh N¤þ£Ä#r*uê;éY<"ýþŽÐJKÛ̙צNÙë’ î´t@1 –á`~÷q¸ui¼”:ø‰G`»ŠV¨Ûèz™’j[0jYX¥åS =®ícún¢§_Çn3 ¸Pgw2ù;˳òó¢PWÚprÏ »¯ÞøôȆ|Ö;uâµÅ-S•rs ¼6œ„÷:ÚR”xó5a¹¬‚îÃ篖æßkRµ§”ï™Ä÷톙¯rŸØ²=»X]½vÄ6©?_±ÔÿJ*j†àx)PQ RJmD5Hiú:¡« 3Í¿ØÙe°ÐÙÅÆÈ³°ê«,óü8æúW.®‡2²s`m©auM¦þ:~;þûѶbàü&üäJô©‚ÑÛJ¢vQÊáÍex·,¡rœxÄTÖ* Ïñ8ê„(®çúðÏ9Á·ûB­fëŸãzàôÞ~c\éçÉùç` ± ÎÁ‡÷9ÑBÞYh‰CØ+t[›ƒ R¤Z>‡íaÃÖÛÊá—‚'¶ÅáºÈð«èklÓµQÀ‰yy,­E:ÞLÇ„æo¾:j2lôªâ¿ªÃ«Oï{©1½–2ƒ¤ªò”¬leµsé´} ¤þï–Ôÿ+nvWˆˆJ­pN‡TJP¨Š¡†¾†žÖt³§†]~)/àÈšè¢ÔITp“Ñÿ þÀ4º¯—Y÷º6Û†ãkƒKý/CLÒ1p¨áÙ ¸ëðsŸi@¾º¯kþš£ÞzsÖÉAOÃ,¹À=ʉ¶†¿}j‹qŒœÎþÃx…; [ò¤SØwnSÿðÎÂï?õì§yÈ’çq5S~wL½vÝÀjÈú¼—¶ÛñÅàÂÒÎK=©û;™” (XóCëpßøÂÅFãßE i× #ãi­_jÁVߣÛ7ÁZð» vŸ|â7ÔÉã_L”ï¶´é›*7Èi§9YUbõ{HýÕW çegu)pp G…£‡íçºEa2N10)]mØëÌó;[»|Àz8~T&uHñ•žÒ*„†ÿ_k§Ó}ëÔ}s»ùÞdâç÷ã SçüxZI½0§…ÿý·e¤V—±FP”’VJ!œ BÄG˘éÈî\ƒþçÁ üèuAˆÂŠN¢/á¾ ø¹§šûÄÎÀM°'³„©×‰ÛýÑøÀÃFÏc¯qÛ)m=u@Ë/þý¨“dÞ-­¶N JTh¹!c¹ç»2 TZÑݯٻ¹¼~eš±pûíaþù€ü{'»2#]ƒzÀhqm r½ì°¬§wTÝüâ©?p·Þô;iâ÷Œw=T1Àº¡§*Èm9[,Uõ?õUJý¯@0Q \…c–Šyª¤¤¨ ¹n1ðž¾1tMÂîÜ ¿¸µË' '‹ŒÈ€º™ÝŸúJ'{ø“tßÀëçã÷Y^Ù@:ÞPŒZT1h¨š¬áÒ.üÄHZ£Ñe$ÚiíµW ³¬f ÖÓdeTŸçÁgð#×'PGx_¸¿~6ª×£LÃN8„rýÄøÍ‡ÀoÒàãv ‰F…ãÝs^ëÛGÎ`&‹œB( ÒÂ;ß”¾f š“ŒÀ F>,›£s _¢nãÙh,¸Š¨‡QЪ—Í–R^œÙ•Ǽq®óýXÜÎO~*ÉÕ¿b”ߣò=“˜^b’A’–yª³¢“U/{ÊæÏÞç¼t÷Wõ¿ÂÀD)áØÃ¦šÒT”‰g˜$ôÑôèÍžÑüüÖ.§³N’«ÓÄ”pè‚⥒“ @ºoì4‚´e)Q!Ëàøª†ÔDê¯&0ø]öÈVášqvnþ¯?€‡7 ˆý:å”’r+Á 2-ÉLÍ0¬±ƒ¸nþ»ëå€Ç`ßGÎÀG/Mò&ÂØõ€Oê‘-ø­‡ŸÃà#CW†=‰ì4$Tß>3ÂÂ;±Gæ#ÐÕ]÷RW˜Ÿ&8ßTÉígÃPÎöPæ(jG]wò°š­pÂë¯ß“v*Yˆ ©3rÿšp|®_j¤Ïû_|¼7?{·igëÚùnjL/qùÀy—k•tÊ2=4´Çæ¯u[Ëw¸ÛNúŠ£þW~O <`s›ÊR‘ÛÃ4 ³ ÝV‹óÀ?ì 8m4\{’´©ýµ ßOµüƒ£Ž—¥Ÿ(Q¾¸-«É d‡å°(ö¯Áª[U*êHLfë;ðӃǷš=sµñÇYµ²¸ †i´¤ý£l%D-­áª|ë Æ¸ÿ¸û)qeÜî{.°ïÇðÔv¨Í‰Œ~Jd×ìÀIŽÿ¾Œ`¢C0ß‚# RÛ/v±Ö$Ü~/”Qq†AþÛò™n¤ÍZwâå­.H©_êŠØ Õz1kLq¾=]Âÿ¿}%èGZÏ£ÐJ£H<ÆN³ årWÝn.ƒµYAÝW:Ò1­¾dDõ<€·ã“h82+N¨lÓYPºqÊ4NÀjõB[^`¯ç’ÿ½°z’IܲÆ€+‘//æÛùð—‹¥…'½õ{Êû®R¶¯½Êº¬ªÙ"¯VLû¿@pw~À*öÂ6STíYŠV‡\yÚÐ3F@Á,ã‰Í]þÉ g°¶7];嵊؃xëAÑ?î lî†áF"ÿ0‡³°Ý“ÛÌuXš e‡iRÍúy¨¸m¨ÇÿV^ÁO} ~; ö…kX6Ò´³T/ÅtN ¤¥¥Uèhä¬Þ°"NÀ3nÕï}Rœ€Ÿ†òO8ƒi`›=ØèkCVžL|±^Àl0ú“ °6Æq•¼Æ½\¶6ï äg ­ˆ‹aš¿8:×,áX„žiJ•Ø$4Ù@–È,A=PïSVâ ·C[øª¸aY°€r=ß9wáÒÏv½×;¿§µî:LßUÉÐ{›w’ªÈ«¢jÙ#v³sƒåN¾êu|I¸Ò/wáy°Œ›-¨z‡!ËQ³)ªr(å›Ï4™áïøxþŸ7§5ÈáìÅ¡£ ûçý#ÆŸ³pqŽ­Àܬ¨ Ji' rXY†N Ëó²Àbs¯Ù‹†: …²À* ý¿ >tJæË/‰E8¹‡;p]MøÑU¨›É³úM˜œñÝŠä÷Ÿ©ï}R^Ó[﯌lü}ÿúíYl54]}€#Õæ€Š+|ÑNÅo«æ¶ XÈ0¨òT‘³6& ü„û[Ú¾á}X ¨…“´¿¦ {'5<¹gëÇÔ²H¥•Á‘9¹ïNØÜë‘ÇSÈçë<\µ$û?6HçëùÎéó—~nûÈñOkç÷´ö]‹ï;í”nhÛ¶ ,*8Tµž½Ï=¸ü„ÿUÞåïRêŠ1¯+Ü(^q7ð.ÜSËp-T- ¾@éy0ŠeÊZôÅ>{Õ!~ngÈÜp’V’À³¦ä<þùGÿº~/ ‰ø+ bð—6ÃÀŽƒ ›2¨´6/˜Ãá%‰^;½°ÎŒ7âqâI9m¥Ã"É‹ðÔz³yWiÀŽ.ÀuçKÀ¦b0T¸:8’z^ o ô±øµgäçoYkÞýªX\Èd©I¯Úoôc¯ÆG%Ú©”-ídÜ×ѶŸuÍõµÈKKî묠÷iøŒf3qH*”B=1úz=œ ï‹ O$±ò˜ÖÃÒ¬†¼¯–D_j‡3aPè¦eYß^…,‹!åùsëÿqë°¿w¾[YßwÆTáó$éÅÆfµÐÚ¥ëpËËw¸ÛNýæW­ßÿµ›Ô’â·¡x· \˜Å¶)çsT9‹RÊiTjPÖ£.nñÇW!1š¿vÍaZÚÀ³ç÷Ÿê´&Ÿ#úǤŸÝžúL ­À¹Íæãäp¦âÐÚ‚€Gk‹°äd츛³$YEz%zâ÷»ðBbÙê7݇o»>t r¯Úa &!õ.œü™7®Áf)}ûøôýú3òÿ›×öGüø¹èý4^²§Ö÷½QãíØN*¥ÓL:îPjÍýaãŒß–Ñú1MæÒIåïηdi‡ XÊæ0ˆ®ÖF×ÍÎËc+°a˜Á„â ©d åÇËÃáVp*\Á⯯û´²¾[zÓÅW=*?йËÝ.ÕVudi¥Úížw'Ÿuÿú} aSð€Ûྷãq‡¨²Eª)²6Ö¡¯=mØ{rƒ Ã>Ÿ[›ã?¯Ì“_{n½~‚¬¢dÚšX¤«Òß—v$eެŒ Qìôl…H”&â®^Á =±AGéý˜@<7š„SÍÝ”Ï>ÓWz„Ͷ›7(ª…FÀ¾íܶ´ßíøèzcp“Sƒ¸èûè÷­´a婈Å×I%ª‡cóMç³&ýî¥Ðó¬ Pckí ºJ„$¼o³™¼—C/S}£ÎÇTÔV\HáÚ%Q•Ã{ÚŽ&1âPnY‚£AË]åF±÷ęͤž‹Îù=[ÒõŽ~^úai²aáÚy•QÚs…Ý=ãÐÅ+ ôûu‘8‡Àíîâ*°ZS¶ E»ÃÐÌ'°÷ÇÏòT^ð…¥þËÒùáE`e?!@kh·Eãm2çÝGù­ky—BÛ®“ŠqסKEúõ»=8³%ŽÀz9È+‹2.º:#ï"P:2þ‰’ ¦ÁÆYIéàN7À]½h76×"íÂN`þå«áï÷Þ÷ |ôâeôÝþéÁ­a`à…H¼2#Ã7k9Wk÷—AhãÒ qlT~éƒyÿ5÷> #¼ïŸ™@û5~¯’)ÀšB¬£ödÜH´ÌL_åRTÖtëÕ™f“ùË–D{¡þ|ìF±wáâÖJ³åO;çKoéZezyU(Óao0(sCyæ6C>Üyçú} ;€Æ Üþ¸!X–©f(lBÞ2 [ =‰øØ“<9ðÅ9ü^0t³` aÑL8‚4D¨É%¤Ñ¿þ¾¬`cW¾žŸ…¹™ý¥C]3ïà̦¬Ž²¥8‚ùY8±"=î™Öt<ÀDlÆ‘ƒ¨ 7Á!|鸶@Íe/&05’ dÞyTEpãQÿ}§á.NlÇr­ &ÓåÎ '6 ÷õDâNaêÎ6%Ás]MôuKÃr&ÆÞ-ÄHÌ6¤¡^)¥—Ñm¾:⇎ÃL×,H6RgY&r¶FËô`‚Üö¥óÍNTÛåÞúæöÏo/úãªò=ëTY–¾ŸÊAQ¦ÃÁ`X ¶<»Ž…h¾<êʵ¨„¯¹‹òÜå¹ç.¸\'G%-ªÊ£uoÑJ£”Æ|ì)ž¼nM×$=ï«Ùÿ–3`7t"_`’°"Ì Ø3mˆ(¦üö†öù?øƒ|¼tˆ¿ÞPÄGff$Íl·¡Ó‘õÑè ‚Ê¬_=6&Ša" Q ÀxßE¸#H¥ùªJHZRwkú¬†·ôÿý§§ã€ß@á›ÖƳ¤4Òà‹Á4RÛ©%ËÇ4X§ì µeŸÇe­#¯wP ްš5b'µ_½…§LqºY•®‚TXÍå¯Û©>zê]‘‹-1†•˜ )@­sŸïžYÏ«Ÿß^X{HYß-*e¬óUé|¿ æE¿j:§JÖ° NºGÎáï97BBý•jMš¯É‹ò¼[2Á&¶ÊqYE•fT~†Üë|XÙ/à ÝGÖ9ßÎ콦òV}rR`n8ÑÔã±âO–B;Ôêšñ–÷Nºa‹ñá%hµ&û䦡0„raÎnÃ^¯™o_™ƒ«–áè’ÐP“(Ò+Ýðƶà¸ït£-P‹[Nœ@ݺëær­™…FÃ7…¿xm³0´FÀßZfZ‰DÃvÈâÓr.Ègm eQÆNѤöq4¯AA=)J3Ñ·ï~·T«2½Á•Àì«(X¾Ž8IDC^èˆ"ïr«Áhê ¡~/ Â÷ÏRQñY©óÿ•çwŸÙpþ_ æÐøkÙ–ôµætQúá°OÑRöJì%‡Ý[Ç=±…¿çV<_Yïÿ?ÌFéñž;îy9¶s?$esH;-mè—Ɠ§lr±§6M¡žLàªË~Ž…×Þ/9 < ;ýÀì †•(HÃ*èz‰ääÀO}ÙìÉ;¹Ô'pa»¥ÔŒScòQåD}vg(?À²vX.©!e`…w0"M8„^!#­/_k¶ÐdÁˆ1¥-iy‘Gȼ†·®Émý™ñÖçg.‰ù¡kÅ1DÃJÎôå¹8z|:^Û]—NmAV $FýÙ¤é $-1Èn%iÿ‘Yù>ÑMWÃ:yý-"!-ӤƂU C[Єð¾Ð–NÀKf ›}C·ÀU§7>·3?ÿ3–dƒÒ÷\IßY?”fÆ9ßÝëù¢ï)ºU¿”jk{ÿàÓxFÑÿuð§æà.×ÝðD 7ŸQmvÁ;´5èʧÆZŒó&qŠbé¥Ù‚—ôº¬žG¿á&xô"tóJ†DH·NÅxbG0¹|§+SjY*d¡óÛš«Çë{5±L¤þúyÆ?ß–õR3Ì*Hf$ÂæA‹ÞÚ&xl^¶ñûƒ#ÈKyþñ$^jÆ ?o^§óëOËc׸À}ëò÷¾ë„Ô÷ñe£¿ßðõ$·ÁŒsÆ–¯^Ƥ –&¶;+YFîÄ`ëL þ›ÎK–²ØaýX#àÒ4NÀ@v¡%\†c-ùì]ø¹íST›[¿¿»0÷ÞJ›MWù¾/éWÖz¥ÏŸÙô'¬¥*l«(rªÍ=lUâz)þ4xn°úk#—öþËŒ¿šiŽWxx×ݨ'¶Ðz˜¬ õ–¬ŸÑö³ÞVsZ'ó½‚ÛóŠïV*åÓÃ[ÚW½ô%w¬HÛóxjÎï6­·¢”(WY‰ ¹lÀú¨õg¢ 3#ÆßÊäð]Ø ¢"* RMÛOG ð€?%ØLGuÛ4¥J¢]ØŠÃ*½¤Èßv³LËe!3ÈjPÍŒ;9¥xDáB?ûHãjPñPþÆB“­Ÿ÷‡ŸŽ²œ8ÚO1z=ÑV5—qÚP7¶B½ #¾až¡èÀyØÞk€ÙЉ­AwãJ?uÃÛ0é6-͆®IýØ~Ûu‹Áî/î-,|ÄYßTô‹Ò÷û†Ûe’ïôŠâ—?Ÿ½­tØÛõ?Øß³ÕV5_õ öB Ë8¶püj þýé×ÿþÚÎj<@yu÷]ò^ܰ‚ß³Ø4£ªúTÊ纕W¶J•×;UÖ1ª:rýÇž~ô¡‡ýk¾kîÄÜêòŒpÂOoÖZK€º¸-W9Þò  ÂBNÛù8¶,™ÃÑ¡—öòÑ?îùǰ Àà L`¡sí†÷ÞÉ-|4œÛƒ›WÇ©¹e ¡·í˦[`" oQþþóã²Ë„Ú{«€ÿü…«àšŨ|CøQ‘áï3ú & Q'eZ&P×ùuäʵ 7°!+KŒ8€•¶°5Û¨UA££ È9Ó‚• Ž·„ ?tƒ˨31ÍðÕ„:špýXÿBÖt\ÐF¬\óZBãí¤’º/fòÚjÅ¥:¥­n³'MR˜7pdæ-ìõV•SÙíÝûóŸqfv]yÝ5¶8•ô-óáÀ{=_mT¾ºXµ«ÒúÅ4áã—*lOá2?½;­ÖWþëà+ˆppzÏ.n>Ö*©²R+JcÜEàTx<¹eFÁ^uèÄS›eÿçìg>ó­¼ìÕß0{È´_v• õœU_ÂNúĈ3ЉD¢,,ƒ†©½v6Î&ÔgÆÁ;m0ÑDØ€ ·Wz‚‘d¾Ü+G©_#V’&œ=¹-­3«›Ì eEÝÖÊt#JRÇŽ £á¯] ¿ø œí…ÑÛÐrûé‡áukpõl$ Ë4÷¾OýÍíÀg™ê‚ ¯î(ÄV4ׂ«Ãê¶<£Ð¬Wq|p®H¦´Ø‚Ã)T9ì” žcúôËîö¯«KïWÐ5–.®”ÊJ˰´iÑ-‡UÏz»¹éݦÃZ§Žfšõî.>éã.Ì„§xÏVcçëÀW' ø^à69ß{»ø+tnZ¥¶”àÏz¯Ž£Öá<¾ëñ¹ow†ý^õKÕ©{°G¯y×âKž8¾(DÇ.ÂÙÍF_§ßÌ’Œ9ÊíKÛ¤öó³!mõh½ŠlTó›fëíèûðûÒ6 7ZÿÞD-6eÀkØ9Çç¤ÎTèý§‘KPò8*;;.Ur›¹~õYøÒvLó >ø4ܺîè–XuY««)F¯'@@mÄ𳔬%Òj™/ºÿ&ŒNB vªî™Ø¸À4â µÀT0ÈÜApšÎïäO|ù³vuáaƒíkºÎUƒÊ%åÈ}N±=¤êú¶Ýêã¶þ© ö§íSÏÆ68f€üØŽö¯)«ùš'Áw¡XF3‹!#¥CÖ.i9E;Q´‡•ÿQà% eíÏœœq¿ž%.É’ —%©Î²‹‡fw.ý……—¿ò³+dFËÎc‚0ˆŠê÷(š×)¾-³¼UQ«sÒ“VZ2…½¨U¦§ðýuDú‰gØMÃ^3z|÷^-ãxÅ1a½éèq’à :ièéÇõ¿™n¨õï?¾¿úd(e\㼎ÏÁ÷¼fT0†/ 'Q¸¢!ݤ¦AíSÝ õ5à¸YŒš`ôY44—6Sz½ ÑÏ0éÀ4Hÿ6´>{yt»‚¡Ýëþ~±Ðù5§ØÀÑS˜®Ó ʼ–.ËûžbcƒêÌwfcÏ]ÜÄŸ/æýc›ÜPT¼Ó{þ‡Ã37’$èÝ_9ðë àäå¶Q óôeýøÐ`[¶²T õ„ƒkÀcZ.=C¬×Z¡³L%8›²¼6ì/¯ýŒ{à³÷W+‡¾cáeW]stŽ-ÁéMxä|³RM¢ÙÁ0;a#M@É´ôLÉ’pl5Î €‰ýzŒz Xˆ/#”³»Ò СOn­´Á|]éÈý·ƒ–2!S@°í#0¡MØÒðŸi´õ1²%÷‡ï: 'ÚŒQ ;é~l`ìӥÄ_ ë´&ºõ%–¸ÔÎÆÄzšs6Æw‘Ë4ŸodŽœê–Ï–>ÿOÅâÌýÝÕÎö•6½Ò•CUù¡"ºbPõzêb±gÏ®Ïûsżß.¡· ¥u7xô£t¢õ©+@+ôþ›>±ÿZ0—?{`Ô¨9a ‡Áç6ó…õ*9ƒÒΣpõJ˜Íô µ¨ª²Úh—8Ÿ 2ãÚÕ ·ýÁÞÖ¥SåG?óoyù掶ç®]ÿ2ñçžã€·©A=°7¶_+c‹°Ù„{Œ<£'¸‘CÃÔ8ØXÿÜ„4z£'šA@DM´0»¹ŒæÎhÙ‚[ïqŠqã27þÇnŸXäÌup»øÕ§àŽÀ«—lK'Õ¤ÁÇv]‹q.¶Äðk1SÜxI2ДUí`t(|([f‘:/d+£¹Š‚>½½æ ³¿žÛ5Îö´«úúÊ1,qC[´ ß¡ìtì…×-æ]wˆ?\Ú ‰××£ù5úx‹gY7ÿ5VÿÿÙ,îBñ p†. ÉNŠMRŒi¡tf\vØ*þ—Ú~ÚÆýÂrÇ=ÕFÔ„gt[åIš&I¦UÛk×ÖJ͘ǿøê¹ÙùïYzåK¯ow0*s_„g¶"=ü:5&ÚTTÇ#s ¨JØÎEê ‚Èf §Õþ:þ^5·ÓºÁ#êï—[pû±¨ ˆºÊH+Ì€m7o"ëHä3ïâ¶â“{ðgà©ÝñJ¤²¾ñpCÒåWi):”ÌŒDùv2>O_\ô…Ö?£‘ñîhh;1ü<ßwߊîðþ\»_fvæ±ÊÙžöôq¾ohç‡Îûܵ[E> ¬úØGzØK=ü/Àù p®‡ò}X—×ûã8ÞM8<¶UÌñ þ+Ùÿÿr”ö€¾ÅmÎbX&Á’Ñ"¥ EJªÿ«‡eÊ(ÿ‡‹-õY‚Ÿ1¥ŸIa>)U[Ù$MT¦Œn%&i;ífô ¿Ü:óØ7Í>úŽÅ—_}, Q¨W£—`}/ЏÑtQÝ^Oò­Ì áE)YLq±/=ÿº&¯·é¼Ú?1Íx«Qpëá°572äÚ dF؆µ$öHhsН›¶á¥¡´?·÷nŒ¯UÓHyñŽ“p¼Ý~ýšV[°0g¦ðô4ãŸø~$’º3ü ,O±ccÌNì¹¢ür97sÊïzoú¸ªo=ƒ,I†ä ‡P(EQ ¨Ö÷°®ƒû\wúSpxzu¶‹bEÎ+€Ùá½Ìà±8*<9Žã¡ì¼k¤5õupEÕfB¶’Ò&£È3œÊH³ï^%çÓ?Ôn«ÿšiܼÁ¶L×Ï‹³JÏ&Ê$‰Ê”V-¯\G“tÀÍÐÛ<:söÙïZ¼ñæ×Î]¿´š†ë<º)8uQ Æ¹Ú°;YX\™4×[=aØ•QZ~òŸýUÐé_hÃ-k‘C‰ÁÆPž,†™×a)Ž •þØÈƒ€†‹üîq`1Po>&ÃF­<.dRhÝl;JBGbòôÔ-J1‚BÇVâDR ‚šÍ.? $¥¿d‹Áo3­8Å–ñ¦ï<}ëê„/É ò¼­ZE™PVª­á%ÇÎ!{~ÿècðð¥MxjÅ"Š. Ëã<Ïbq,FûD éÿ]_yá¯;€ie@SÊ&ìÐ! «FR4¯þR^ÃDó[¶¶cr·ÔÂ-´a6C'”IšèTiÛJÐm‡ê¨Dw”R3úìÓ7¶{;߸týM¯™»~qµžÞ+<œÛ…Ç7¤ ¢H£ú:hØ/Ï„9õÐ+ÜFc®aÖßù0ŒcLàrÑ¿6úWÅøFÝ"D óIà5 Y@á¢Ç‰€µ:šïäBЩ_ÃÐÁ3½ ²êt œ˜ƒ¿|\ÓnœO­x§õ°R2úÕÐÔ¿´½Ø‹÷j˶+‹©ú}²ô´‡¾·v¨¼é{ÏÐðD˜¡eÞ+[f¶Rª­.Î,â>ý9üÙëðÿMñI® xEÅq`ÈÿDÅ¿dÏq\¨ý›èÿî¯|úÿõ.Às-<‹x \€m<žÇ‘bAyh;˱Âò¬ªpU ›õ½ÕÞ» HubHŠ2C—U¸ÄÞù\%:W'®¾?7ê±gÿdï±SïX¼åÖ›®[\mxÉܰ& 'žÜ”ÿcÁÝ7L敬±Ê”LºåV2«…ÁWGþ·¶9üe­Žë›èSZ˜µPG½ °nU*'òâh!uR 8Wg¶YÉݦ©ïSÝôÙo^Ïn‡Ï4«¶@tôÿýÃðÍÇáGš~4PåüUÈ ´ŸÈBŸ¦‚Á@¦}}ßð˜’míŠO þ ŸËÎàé{ËÀÃÀ㇆J“W¥R­¢¥( ?kû-læ°‹ßÚ‘•tìAûÜwÅ£ÀjHéû¼ø$»xfð· ¿ŽþêkÏDþ f€÷Šï ÀI4‹$ädØAŠî¤82”ÿQêX¸Ç'Q| e¨TE5k¨æÓž]˜õ‡Ò‹¥ y‚1i’èÔkÛFµZZ«6ÆuœWm¯ÜLçéÇ_•y{ÇÒ ×½fö% «I„„NïÂ3›bìu)§íiO]l‰DY•{EÃâÓ¦)’X¬3‹$’¯oh¦Y‘•D@àHÏ™3hL£¢!!ÕãÄeÀ *×ÌÞ´þƒ³Ù.áî§E+ ™ ý\=ßw­¨ûŒÓ0DûÔA9 è%‚r8S±…+?eõ¹IžÔšw *˪aB2¬Ê¢0dy©)Û ¥RmÏb[9v{ˆvwnÏÊcßpÅq(V-þ:9?í¿ÏÙÀýÿ*¦ÿ_/.WœEsMŸ„ŠP(oCñmáçðÅ¿Fûªí[•nSÎӵ˙·Ëmï`¡¯M«54º3—T¦ÈŒÑ©Ãµ•µ­²m¥t¯ÚhÕI/œ¹¡Óß»sñØ‘Ûgo8zØt$p×Tٞݒ¬ ·QÝnäëL‰\õ| 'Z¦þz¶©MTJ$FDåAMψ°‡6ÑZ®“¨ëû¹ *¬hvšmìT‘ Æã¯)Çm ¿}þðL"yŒ,7ÞÀXJ“¶†´ùõ¢Fó£rÁÆQiÇ%MyOnÌÇJô` ° ˜ WŠaUQ&šÂå”.¥ÚbÏbïÏq³}üÖà>nïÿà%‰òwŸBqÅÀ¹ÈäÜ@‹GG‘ªñuúÿ_w—Ã60´0Ì‘P¢H±dx¡ø»4² ÿšuJ*ZTsy·2«sÕªÚr‡f¼_a…ådÇø%­5IK©muR\•áTfRÝv^µ”rmÓÆùŽéïnŸ~êÍóG¿nîêãÇÛ«znDç F´[À³Û2Ö:(š6b"ïR³ª »´r»2DâÄ4åA¢pp$¸©àªÙƒHCá}è¤ãJÂà0 Žg<†ÇRšÛI"¡Màé>üƳðL/ dQZ²˜Á÷^¯X”²"u`s¡êư¿o <¢\õG=£?oцX;4Æ ¬%GŒ¾ÐP$†Â%”¾ Úͱ[C;ØóÛøÖá)Q¿ŽüÀ(ú¬C¾óüóÿW©öÿºx>íÀº ¨HÈôß IÑü wðãT|€”GÉ ÕâÊ´7íÉÙ8zä'Ëuåtb²–1´Lb)ÒÄwRïªÌ›y“µ´·-eÒضJ’–³‹goi—å毽ú¶ù«VM†µóB4ì{ØìÃÅž€m5#/M`¹-;ój½Ö‚×+ªjƒÖÑ’N¥eÒpm¶)5ê² QãÚ&rõÆžz¢p§Cí_–ÊŸêñÚ]шŽüæYøÈÙ¦ì1JÌDY¸yþšhîOöü‡§ÒŽu…ÿ|ŽÿLÏëÇœ§ëC­Ô Q?×PT%E©(SCérªÝÖfTº‹[ßÃ=}v€dÏ`ø‚5ÆŸóRJN“Ójü|u£ÿ×Àó) 4׆n@BŠ™€çF?î0ÀñÑTøàÉŽtq©=ínX<é-œV˳'U•¬k·’˜,1†Â$)EZy*­S•éÌh•y¥Z8ÕRÚµ”JZhZ­­õ«Òõõ—/¬¬ÜÑ9´rUëXgÙtÇtßÝBZn[¹DýÊËÏ\+bmØ”SU¡ Í$Jº­ˆ9§ƒÁ_®0¡}W;!MƒÞ·’fE9ÆŸÔÞ(¤ì™rÎ/?Ÿ¿$™ÀdÿM«ðG¡R–=<œûLOéGz%—´gà`h4_‘+ð,«Â$ɰ()B+ÊrHµÝÇv öÒîRÇnã~8ÿÄ–ë}ŒŠ?ÆáäœÄNï3~Bèø*ÿ×ÀókJWk0Šü)*”š¿,‡Èó ŸÁS‘SѦd@EBuÒžvíjè_µzƒï®<¦ŽÌ'dEK'ËÇt–n›~bL¢µI]‘–Τ&Õ)è4EeN©L)ÕÒ‰Êp¶¥LÒÒŠV²½y"½´þòùµ•×tV–N¶w–Ó¬!À4QÛÐ{¯ sÁˆmýU´3¯rÍtJ6BIQ¯×J§8þ4☨ƒ“‹êÛi¤“€W5µ<À©=øà%) Æû}8£È_µÈù·-ÙO{mÜÈ9Ÿxr…D{œzo†8r4¹u6§°–Â9ª¡§ÂS Õ…®“àÎvq[ü¥þtÀzl?2t€Íè¹Ê/–ñ\G—{YÅó °|åÔý_w/¤ XŽÀÀr" €×ï wÚÂñOÑT‘H©(±Tø;^†ƒû¸ƒ;ØZ>¥ŽÎݪ’.*ç’™_Ntw/1‰Ñ¦•ê¤tEššvâ¨2m²T)›yC¦P™6*L뺘–ÙÙ>žml¼¼ÓiÝÒY\¾!;¼´-ЊÕtâi»šhŒ ö‰’"3ÍrKk¥LÐÈH°<ƒù¯;5û¯^ ‘šÐz Ñݺ¦Æ7¡-‰k¦îp2Ø4Ì:¯‰Út“Œ¿nÂ¸4 ×/ØØðì|ÁzVÒOaxtž3/?ÎS‡fØñŽB)rïÈK[Î&…Sä岬¨††²ßÇ:Gµe±zw!Å vð›}üz¯ð§Ÿ=à˜,N4ïÎËœ@q ÷°Cq%Öý_w/ \Ee–K‚áoÇÃî>ƒ¡¢¤Â†RÀbã±Ï;CyçÛîäì<ªuñ1tÛÊ,žÔs½£wQ:ÑJ›Ô褰Ešèv¢ŒJŒ¯2çUfŒJµ!ëLi“Ëð´Ì ¿šîî^›–å íù¹›Ûó³Ç’¹™™Ö‚j‰pFÎa4¼S+ i™ì«‡y’ún¿#‰[o1í×hÊ£5äEµß´>¦ôÃþöžw mÅNQ¹s»•}x½ôOüêSéðôYµ6,I½Çyóç•uصž½j‘§oZå|¥­( KiKª½ŠjXR–ª×Ãí¹®«ìœìá{ ·=Äë>^ÍÀ¥ú‰tG=}Åá‰'Yÿ.åå8Nbù}Öɧ¶û¸r¢ÿ×À‹Í:$¡#„Dð¯‡s¼…â_âéŽe–U,¸ûëV|:ÜvuöT+L¯¾üºÅ£g(½½“´g…÷WybI­“DµŒJ­«2ãUêŒÊ´'U:9¯M ®•û+Ùpx4ë÷®Yœ»63æ:·°8§çM{!kvl˜‰±á8ÕûõàM<ʬ' ׎õÝšLŠ‹îÓô«PRhG^ZÁÛêÂÀV_êy}v}~Ë¥›ƒÊÙ¼Ò¶tؼÂÞÿ G?ï¯)*Õr2aï­Ã9µ§`o©Ã£‡ç8½Ðf·ìSíVX熮W´m1ÀnÐÃíåñUŽßÞFˆ`õ¥s€DwOÂ<¯Æãéó!V޵ü¢Ð•”úÝüI²€Š„VÈ †ï¾!ÜéCX~‡ÅPa¨F£%–Egñ¼ÇÝÝõnxðn¸têuÓ±yu|ùÅ¡§Ý–î»T«£µJLË*ƒÒ¦4:±¥J’ŽJ”U)šÄ•6SY’j¯RçÉ´&ó*ï2ibL¢4ÉÇU/p7Ì-ÑûÛ+çÏÏgÉI“˜¹,m]¯¦NKtÒ&Ey3‘-0¾ôdßÒâ)›Mt]RN[òʺ Êb£ÎÙ*?íRs¶Pú"Y¶;T¦W8ªnaíЙª_Z;tÆöJk%®´Æ K\UVîóO%ÇÏos¢_°ìÞyœóxçpÖãœÃkÅfbxr&)Ï`Ò=5Äå2ä(ðÊã»-ÖÓ@=ÅZµ[_±&­b3©4²ÌÕ³ÍìØ¢IÖ·^sÖvŽõI:gãì¥èã=8È]­oú‡Ði v:DŽbDG ¤‰»žâú XÜ'+%"h“/<[z¥ƒÐ!d˜˜¡ÛzÒÚËž§¸¿&€7 €°‡ÏfL)†”[¿qáÀ# ¿úÄX2X ãªTW–åsÏf9‚L1V1-E4DNú,÷FüÒ*{†»—æøÃKD„ñ@¢(?¡V;Ò(ʋ֢<ƒÌ™¡x™‰r÷Þ˜¦dÉȘ&bh`rÏ@ŒÄ" †!i†Ó§ëæž´†ª!”bpËHƒ°a­5°M X;hÖˆ´¡XÛëkÍj’a£ ç°éStÐFc‹Æ;èöî.ݥ˺ãE¾<ì’!¶d ¡‰0š1Bèˆ ®,±$»1Jˆ2Di¸äßE]KïÞùM/Ky,7h“?LÜà‘àb ïaøÔ%;¿CxÈKàú D.X$Ž`²†¦ËKËÝe  ÂA0¡Çb’ñ+àçbø§oøÛâ _µZùnæ€v…cšsº¡óóÐæˆy€ùyæÛôÀ;߈ø2;Û*ñ%#AÌðD<ˆhFS+p\²¼éÚŸ °Q¤M‹Ú”~ŸF4«™#„ÙqS„ð'þB>ê¬G‘-îºæ#OK‡+êÊO)tG˜A>Ö÷€»xüq> GHc€…jš¨™A/΢ÁÞŸË•ó _v ¢à‰\ä"]_VXáȃÀë,˜(¾ûÇ]i´Û“óívi͵à˜³ùþÓ (|\PØÛßgqiE‹^ÌЇì0J¯è•âk(÷ï3\×ã5”;°¿žÏ–llÀVq¬­|Ö€{EÎÄ-É-¼¦c`¡Ô•§¸~'n»‚ˆÜ}(æþ зЩû´ôîúÔð]æn”Â# KF®Ö¥árÅÊ"Ê'LVþŸð  c‹2딋ð)ðùå§·ÈÛÏ}AÊ]Rc «Öte‚ËXÓGýÔ?Î+—Z—òß,ü]s‡[¾Žî \çð_ç.?ñáªûÍþ.råý»R£tò_®¤ð%ðãkùã¯×ÝwÛP}}½ pû69Ø·`ss²ŸgjË–ûêž{ÑA5Œ*®kA 8b¨J˳ëÆöT'Î\Ü3žê;௠àM“@Qä6pa@8.ÕÉ„4›(·€kÀàK”"Œ•m‹.¢,ãñ!9nóœ|AÌWÌmc‹53VêIfzè \FÙE×À“Ãm·oßf¼¼Á ÷ï ¿(~´ž¶·emLcGœµµ5½SþîÍÜ@aÍKÆüÐÇ`—’Né³3È H¨„P±ÊÞÀ\Ü4ùn’ŸYucÙâŸCà×ðæ’‚¹®>Fh`ÜÄ Ç釚%E+Ç”ðX²€°„ÒGù0° œñHø—³ê§kÑ À–ëYnj>»PF¼rÆÜ×)㺵%9=0*/+Æøô‹ÍÍÍg*‹úóNáås5U2(B™ÊÄp:«¥m'–žóüw†Î³ˆ¸Ùã­©)ÂaË IDATxœì½y˜,YYçÿyωˆÌÚoݺ{ßÛ+MïÐlÝЬÒÍŽB³È.‚ ¨¨ƒèŒ ΈË(¿dFtTpƒíFF ±éfé}¿}oß}©[{åçœwþ8™YÕÛ] Æç'çy¢2+3"22Þïû¾ßw9'EUA•ï›Ãü¿¾€ïÿ·ãûø7>¾€ããûø7>¾€ã#Y«=ë̉Gz{ð àSÀ÷,äÒÄÒh$diBšUiBš¥$iJ–&ˆ1¸²¤(®()KGQ:ÊÂQ”%yá(JOðáD>1uc%~fb°ÖX‹afv]£ì«,œÔqß+ ð*àgù ÿûãøÆ÷ _6UÛ÷Ç¿¢ñ½À-À^àjˆ¦ùT¶ïµßKøwÀψH@UOjûþXÛ±f$ð8Æg~/MÌ;ç[Åûg—s¬91m679Áþ?a¬¬}Tcò"ß4Öüº5ò஢„ÿ?ºœH`18*%hÃÀìÉ^Ã÷ˆÈuƘ§LM }púáç‹Èq}èv¼<¥ëü×2Œ¦Öqçîi Nتe‰aj´ñbà™À»Nö:Ö Æ>ú7dwb 61W¦‰ýióÁã=¿xèä§t™«Ç(`þoß3„‰@áÝ2<ª;LVéW§ &(¿hÜq*×°fHÌqñÉû¬5ˆ‘_7F> ì{Ô£hwËSõÿSDy&ð8à<…qQEÁ»;€oÿ Ü øSúÄG"†³¶ŒãÃ#BïG:ø à&GÒ÷al¡]¼ûT®aÍpœrùšÙcœa­Yo}ŽŸxÔs‹Ðéä¸N&lIW«òB`KP!¼Ç‰ Äÿ5„)U}rÐðfTs…ïŸþØuâýðC5ºÓ¶LB³¢ô¬¢(}ÌJîuVä=‡»¯êäáäR€ÕX3ä…{Ô}‚²ä•_ŸhfbÅ`óTkÌ')¶WU‚*Ëí Ê ˜€ à~Ì}‚Wņ€  ïÁ÷BKUÅ;÷ TÂÓBài(¿Šò7À›÷ŽgøŠ>’AI¬Áû€5ò¦,µŸ^ì~v©ã¿–‡ë}¤±fØudéQ÷©ä÷ɋβo˜¹JÄ\1;¿lÛÝÂ?T•¡fJ"†¼pÇ• Qžo0¯ªêªŠ%ø€7ãíº*¤ú,â>Þã|‚Õ@PP o^|øuàðñÞ›µ¨ú+ÖÈow‹pd¦U~¬‘ÈÌ©†Gk€ò8ù|îÕ8ºø±u#W¥Ö\¼°Ô9oß±å;³‡Ðl¯°iÝ“£MŽ38â|øïôÇÒÔb$ 5!Á{ ˆ@@ ÁTÙEª¨W\xçqÎã½â|ÀùPwÍ5Ÿžü(ðãûÖ§<0b~ÒZ˜YÊÿ¸Ù9e~²f8^S”Z˜mßÎsw¨ÙlnMRûÂcîDAÓ×v olÏ£ÄÖHŇP ?à¼Ç¹Ð«J]áƒó4„¿x¢óáèÔÔ8ËËmŠÂŸ4I5"„‡Ît6D䉨«M­åòðL«üÒhÃάEBlÍRÁ¹ ǹ)¹Ó™N^ÜÊP3½2SÁkoÓ XcŽËì‹… 8n¼óÖÛ[ÛÎ>Ÿwÿâ;8}ë:ZyÉb« /¥š]:Gá<®Œ¥ßzË«ÿã>¾Ç @0Öb³Œ´Ù$Í2Ddv¡]´ÆF›ì8c;Þ\FG’$¡ÑÌH“„ÄÚ›5æÍÆpµ1˱…öµVäN EШ'á2äkf«ÕG¹Óå…¥Î=›¦&ž52ÔxbÇ…'m&×lÚ:Vi§R†@2Ò8Þo÷ƒ]æï;Ö}Åm_¸­qý·_˯|¯{óëQ”›¿q=ÿrãÌÌwJi6RkñFz®¥¶ª}³¼‚1kH³ c,¾,X\îpÇáeÛö\²cóø·ÒĪªž´9V"ˆ“4!¬$ƒ›‚÷ÿQ‚XËGç®Û;—qýPr‘5ÑÞ5ÀhãøOÕH‚ª·8çÉÒdóPfŸ´~ÃèÁm§o9”çÅŒ†@»›ã Ç£´4€ÿ¦ªïo&áüCfºUðÀl—?ø«¯³íÚoñìËÏ㪗¼”ýð¸ÿΛ¹ñëßàž˜žoÓÌ,¦²£YjQ1BLÏš„$5Ø$ònÁÜÂæ»ÌÊY£öÂ-ëG®šÚt÷’KðïP½ñxÉÊC cLïzBÿ>9ÍîƒÇþá†}K_Ú˜ÉQZã.NxÈZÍ ¸tËÈq﫪4R{ÁÙ;¦¾¦É]L’$1Vîö^¯R snApçÞÚy±ÚÇN ¼´÷e*B×-< í’ù®c®O…ËÏÛÈ3ŸñdιàB@8vä 켟 ½ÈõXv॑& e`,ÝÒ“¦ 4%­6c ‰M1iJj-ÆfØ4>fÙ¾hsô¾['_ný ð¨. MlbÞ’‡>³Žú”åV÷îkoÞ÷áGsSÓÜ=šš6F”qîížÌ-Y;üü«žŠ*ÜrÇNö]¢™ÚØ?©E„NéϽo®¸rØP^²}lçiSãÏAøñàö˜‰Sõ>\ßé–ß:ÿÉW¼=¸|è¶¾A’œ¸‰}¨Ïó]Ï’W²Äb­Å&–$IH“$>·“$¤Iеñ5kS’$Á$)Ö¦˜$!ˆÐà8rïÍ[žù™4MŠGÀéIbÿ»ˆ¼¼" Ç‚êÂÝ»üöû—g¦2™™J®ñA>ø;ÀÔHÆ–O꬙ ðÞ“$ žw:ÃÃì>4GéôËœFU]µ¸®gjf¡{#>¼w¨™þAjí;ÓÄüœ:ÖéäWœyÞyWüìïý=ßùÊÿæî›¿ƒ+ÊãêAx¤ñà3ÅyÅš€ƒ >xăGãqÞD²Ä#Á ÞD ®ÌIM¶žÿ¤?x×7³|qñg‰9—íÀfbsìiÀ† áµÎé™=0*hwò/ížnÝ—›×¤÷dVŽ:¿òzE`¼‘ÐÌN^ŒkÚBÀˆá¬3¶ÐhXîÜu,f᪠"¡T–—½nj—á̰Ð=–¶K7:œþÚøPö·Aå#yé/w¥c¢ ç_úL.ºìÜüµÿƒw1#«Óˆ§ò%”Ò+HÀ ˆ‚N ÆÔ”˜^PñøP]CÄ[¼8¤(H›ÃLn?ëGÜ}ë³UÃdP3$†—ÓÏ€jlt5"ˆ‘%„ ·î9<ÿ?¦s={2•ùáÌî±F”sPh&B#±§Ô+¹æ=ªŠsŽ©É ž|AƒÝ1·˜“<|ª¸Ý-Ì4ø3f:þl+lMgÜV ןÙ4W´•Ï|ý[wüеõa^ù?ÅÕ?þ[ ü.÷|ç_Xœ_ (\/)Ò³ê=LÄ'æÑâs­¯?<¥ˆ$OªÒ±x0à<u-!¾—AÅ¡APñ„à EŽózV ¡R«€qªz_bõ;VìÝ‚ì)Jwd¹“‘¼“—óûçºW##™¹aV«¯RÌ {j‡ïbShk-gl^Oð3Ì-ç<+6à©9ÿ \õO㜳?Ä7ÝÀ=7•ý»îfæÈ!Ú­EÊ"§Ì‹ˆ5ç<ÝV;–“T¥gTI¼¢“B¦z/AqÆÅj¢ÄHåâ Á$ø¼Å¾Ý÷3?ßaëX¦©‘ï,Ãg'Œùœ¹è.,u(JÏ|«À…0ÖHlî|ض\„ÓB{(³{œ ú"Y[]N kFîê§`ŒÁ9×˱…Ã;OQ–8²Àr·ì1ñÁ¡Êèl«xúlÇŸWšŠWŽ³ã£—Ë[Ö0iSõ·Ãýê4îÚÄß|þ_¸äâ³Xj•›žfæÐ>ŽÙËìÑÃÌ=Èüì4³Ç¦™›™¦ÓZbqv–Å…å‡-Ö…¥¼äXËDH­™@kÉKR‘Àš&6Á$IE #´ÕkIš‘eMöÞw;ß¾ëðægð¸[ýì®}Çm%ô7s%Áæ–r¦[%G3¼êcæÛååÄä.¨=Ü gmÌäà–ñÆçÅÊlL ˆ‚Q¢„¡F‚.^|ð«,´ŽWnßõ¶ð Š l˜!YlÓÊ^WU¡„å‘Fr]Ù}°¦®×'~è)æÍë×ÉdnÀ‰ÚÇïPûçSʯþóQÞþ†çññOÿç.c#)c#Û8ëÌmÀå8çX^X`ïýw°ó¶ïð­o\ÇÞÝ»¥,J:ü!A`\Õ?`D0¡4Tn úy|@Ä#^P ±¹$¾ùÀ¾½÷±ó®üåÛŸÃKßý[<ð¾wÙ4“÷YvýÑBþåE…ù©¿å‚'\¶ò % 릦ðþ\òv‹ÖÒ<­¥E*¦,Jœˆ.Üê” !`¼`$ ^ñ3Þð8 "Ap!€8†D`úØaöܼ‹?zõãùÁ_û ÷þÚ›Yºm'v(7þüÒa{õ—ݦ ¯£ÇZåcæJÝBä…vذ<Ô°{­ˆÓXº]øPú|Çà¹yéÿøû—ˆl¾—C¢¯¡i-xÙ&xÒ¥tB‚pÕaÒêûMÆebKÏ7K.Ð6üÞó¯þÜA~ì WóñO}†swÙƒ>k|r·ngaö(çÌL³¼¼ŒwÍá&ËK퇼>J#†B"Û÷Rùz|¤>àÄc‚ ÞG%°¸¼Äíß¼›\y?ø_þŒûû´oÛI2Ò$„@fdËlm|òÆ»Šì,Ô͵ hf( 8?Ù´÷ ¥f_tó‚J–&† Çó^ÿ@ákx†.kçîE'*“àYgN$À‰ ´TõV¹ùº= 'Wmxˆ¡@¡ÂS6?| U<”¼Ñ[y‡Ïb¢D  Š†gP˜@á““Â\Uòâ/âoz%øéÏrúùOZñiš2µå4–ægYœ;ÆÌôQÚ­CÃŽ¼›ãKÿ`BX%®¼*.(&Ê Uˆ-‚*âç+âçI€`-<玛ïáÿ{ê^ñûÊÿã—Y¼þìøPôÝFpªlNÎù¹Óšoú™]O6 KŽ$²4œ™vjÍ’5ÒM¬9”vPÅHœpƶ)ÆG›´»Þyò¼dçþ¹áÔÊO9ö/æîΕÅCY ¼¸ÊŒ1 Ü}ùޱÎ.Ÿºo>_“^¸©Þw·22lyÉùŸëcâÚH1‰Ek ¼G­/”¥ã1ÛáŸ]rÕ?à—ßþZ>ò™¯0¾aÛŠÏ›dã¶,ÎÍpú±£ÌÎÌp¸(n²¼Š'Õ±xPÅ{ðhôí¢”0¡òõ•É7"xb—‘µäEÉ­w=Ào<~oþÃO±ïßÇìÿ™dÝpäF°Vzxö–¡Ë±ÿ_޹?™aÉÉ›©õYbœ1¢ÎÇzÆäXƒ-'jV’¥ …Bš†ßÊââ"®,èv Šb`žFvª Ý»ˆñ±¹”èó£É—*î÷`-Ëí.7ݘß{Ê~꿘½ý-f¯ùz%|¢ö‹€#ø ¼nÇÈ›gµýá/Ï— Nû³¦Ö™[&Ø05µ–´×:^5ˆ¾å=UmCs®;Qá?$êq÷\¾|~Ó½þÐRqÖøBþô-ëš/Ûºqì5cÃCñÆÈ¯cn‘¯w÷‡€3žŒwÿHœÒÊh×MòüH6f_J£¤A"¿õñõl®kÀ¼w¼âÉʧÉyÍoå;W>“ßùÏïṯéÏ”j4‡Ø°u;‹sÇØ1sŒ™cÓt:]šÃ]ŠbÕ$ A— ÐõʰhdÜ>PJ$…PÕúŽÎ/°ûðzÉ…¼í=¿ÍÞþ ߸ƒtýplî0&f+m® ˆ¼ ˜À9?sÖèo¼Ù…Ÿþ̓¹µ 5RÒÄ’e± B@ĬŽõß|"hTµ]ú°çäÞJvü̆†íº°óÞ#­/^è>ë‚“oÛ85v©µÖXksî"cÍ“†š˜ ,uæÊÔw3N»º Ø æ½Âú¦ÙlÖ­ë2­n˜© UÄ9Ô;ð ø2–í¼Ä¢Î<üðÓg¯/ù÷_žãÊ×½›Ÿÿë¿ä¿ü[œûÄ+˜X¿‰M§ÉÒü1æŽanv–2ï’f]ÊÂõ:…WSˆ„0(N| kÈKÇG8/÷|ö/æ¯~3»þÓ»iíŒ(ú5è[U•Ô/·‹;Ͷ¾€r什c¹W`˜_Ÿ™=7ížùæÔôÒ•cÍä¬4±û˜n]³n8éîØ<±y(KÎX?9þTkÌëŒÔüNã,ÖËA/¯ÑÜ*¯¸t #gT¥ýÐߎ~U ŒWÄG‰6$ÁCbP¡ô<ùÇÿÞ¢|üFø…¿¹O\óR~é-/âU?ñKœ~Áel9ã\–f˜Ÿ® µÜ"o·)&´(žVxÅH %ÎäAàh«ËÂRÉOlÊø…ßþe¶nØÌÝïú)Ü\‹d¢‰±I ¦¼¤“ØxÝQckk0Þg-ü§:>Ü>’Ø9 T‡Uu³á|ãÂÔÈ»Uµáßà| ÏË}÷î›ý³æò)ì[7lOÈ×ã¤2§¥‚²a®ð_v<†ÈãçcgŒ&wmošZ7|ɺѡw‡ Ï×&Kç—º…û«²p7‡6N·Ýs/Ú8ü´ýì †×mÞ¾·ùÊØ¤é¸u9øu.Zà¨C|eÉ—1΃ƒ{÷ÁǾ ïÎß:ÆO¾þE¼ü­ïbbë¹ì¾ófn»áÿðí®gïî=ÌNO‚"",´ îŸéÒ­¢ñúŽŽZN)b©ä* oíe<û'~‘¥¿Ä¾Á7°™ÌbÒjK,’V[ÝJ5Q¥tà<ê<ÿíþ%¾ÝU¦š)ijÉÒ˜}4ÖÆy—Rå"¼âßw×Ç~óÎÙ¼ŒnÌä¶±¦½öþùâ„#µSJŸ=ž6ËÀ%ó¹ʲgÖ¥©¡dpSbäðú±l|ýXsK·[É»n^|` ágOð–—\úÑKžú¬ª·E×]=®—£e\à¢ð Ñ\)ТD*cAnØÿóø“i8}Ó0o~éÓyʳ_@2´Ž{︙ïÜp{wí¦Óîb­a®•sÛ±8ý8ÆRa¤aÉ»ìxö¨áM/zOåk°y‡Cÿë,ߺ3Þ@Ò$šúÔb3Ûûߤf¥ˆc#¿u_:²à¹}¶«ï½oé€IìüäPJ’Z2k6ZkG5C(FQÔëÑýÇñ¶K¾ØÈd*7dæÚ}Kå [S®œ³.#röbî/[ÈÃ6¯¤MËbjdÿ¦±lÏèP²o¹Súà5ÉDò;ÊåO¼tÛÔäÊ›hìØA#ß׆²…†è÷ÕåPv"Ê.¸<’Ààb¡GhP.B™£(@sHJpËpë~ø_÷ÁÇ@g8áù—ìàÜsΠ“{vÞ}ËK-œÂ¾™6í20œH-yؘ;®ÜÚäåÏ2—^ñ dþǾô%–oÙ‡¤3œBbÁØLj°™¥ÑȰ‰¡4‚·R¹j?‘Xy,ê©ÏB÷åŸ9عæ¶VñÒÑJLf»®Õ)OOSs±Ùè|¸~çt«y´.®€ZLfòÍfj¾±÷ÿêqñ¦á©ÜùÇú S¹S]Ì}Ú°²²F¼ôŠZyি~ù–×¾à—þ£[`h$²EŸC(Q,ê‹(ø¢ƒ–m(spÑà=„2Z€P ¡ÝG™£p ÐnÜ’BvMÃç÷Â'Á-¶§Œ'+°œ;ZN)`rÏe™ðÂó&ù+.fÇöí÷2ÿ[È,Af¡‘"³'1¨±ˆf?Ë, >pÃL›E§\¾mœ³7Œà­@’`Ò¸/g(çÀ9&2ù‹?»}ú ÿõžE.1°Ç^$™m•cãM;'"¶ôá-ûK˜‰„# +÷fÆÜ½¯UÎŒÜÖn…#3#äUšc œ£ÙÆnΞm•g.ºÝE1»32Nò&}KÓUÙv,†vêA H³PBÅ"C5ƒ3D à<\|<â„,Küvš@×N_?= ¯> ¾x>p°äÎUØ¿:ƒ7^<ΓÎÛÂèø0­{îâð?^‡ïLÓ’Œ§`-JEH­AÅ ÄÂPb`ßbκgޝµãÉ·íZæ=­ã¥ÝHéjM¬q˜˜D²-З/–þÒ<è]S»®ða¼ëÂÙ.èi˹ŸÒÅBw8HG¦×5ívj8ùE-Ö´ ‘ öíibö&ÖìÏsëd韸o±|\«·š‹§²ò –fÀËf`3Ôf(IxEøâÀ{Œ Ut p%¡t1f«Â^IE b!$P–‘åÁÏ€§OÀ{÷À_WIÁ÷­ƒW­ƒÌµÉoßÅô¢CRÄŒ%¨´ê>ªUÚë{ŒábYx>°s¡'ü8èágog²ayÆYS.f—ÔÚ*“( #axCÓþüLþ 69¯-Ljƒ§’XrbXè¬kØÛ¬5÷ÿ Çø®ƒT!¨+2»~4ûJ€é]óåy/=3¹£h™#ù‘Þ ÅdGô ¾ } ¾$QÇrÛqÇÞ’éù.ã‰ã’ŽÉ¡òÐkîYºŒj¢aÁÆG¶Á{7Ùë›ðúI(Ú­h«ÌPLáÆŠ¼E§«§”!4D¹i¾Ëçb‰³wsbDñŸoåO׳~bˆàã%ò¬àMÍüHfw­L[ž|GìwNáp!¼sÜóÖs†^KF°AžWúXß.¡¬4Þ80–Ú¨úÙË»%·txïèŽvéh \án®ä. l!F IDATÕ)µâ+k!VÏ{"輩“Ž5×ÓJú"Wõ¾Â¨*ª±Š˜YyYÜÙöÌ´ ¶7,Þ R·õÁ¡ÊÓÏZñ»µüùîVìŸÈ 4©vñDÜ®ÉX»yUÃ¥ °9…?>Oyý™%¤¿bˆ‡gÆ,^Uã/K@*í¯œt­nA"ÁãsÇô²£—,åŽVîY.s•ÆÝ0íŒ6è‘35Õ´©Ð"<ÄUHd@ȵö+K¡Î=¡^c Zc÷PZ¹åÌÌ÷07·£—¼¢âѪ¡4~\´4‰5—_±mäœÌÊýóEàksŽRcbò$ו|رf DL7Ù0Þ¤1>ÌÛϲ¼ål% eÀúN¯ÛA/éÙeç tP1Î/º[)ºH‘#yŽ”±|»Ð-Yê:滞¹ÂW-e°ƒ(cnˆ">j ê¢àðô(UjÚÁC ¿êŒÚ¯×ÿ¿÷Ü+…W.nZÎ}„IKgeÂÆ¦‹BõÂÚ±Á34Ÿû×UNMxöTÊ…åSO×o(t‹(ü:F!Ú€€+Bz~|@˜ÕÅRq€P]Ø w1¸ÿ`Nð^ÚÞ† ¼/ýÁ|C/!K„M cûž}}ÁB×3× Ìåù¢¿-”ÊÌ䯓–ÓwÃ<ø]D®…`v¿zjé%¯Þç9cB]£ãÑ8 ·ŠŠV{Ð T2 lïûÏ Š2ú[O›7"“\jEƒô"€š+è €¨¯Oú¬ï ³þ@ø/ÕûÊ ÷©¦üdÖ25dPdtoHþçgž›5’{“4¡QýôM㺂&ËNZXki&‰?\ðª‡j{ËŽ·®ü¥s–î6œë"Vz¥P©ï𠀫â_ý ‚õûê{UàžðëÿC ’­ç• Z„0¸Ï€Æ²}A¯ÞjkÒóÝÕ¨e¯ÔÚ=`ëeåÍ}~/ëH<Ј0ÑH|bÀsšóWÙI„‰ (Ö"6‰<é$Ç)Y€Ÿ|ñãwk~Eƒž¥ªç©ê™ZÙP¾ºØj¿aïüòþ¿ Ây‰n>{Å\pÛtÚ 'Ú×fµfϼjî@ŒOˆûÖÙd­O_x½}kHßBôÜEý¹ÕÝ$xÑ ÉJÁð‡•Ú^=YMjŠ÷Xáÿ!.g*TÆ­ÞJŒm<Éyœþô ó=?µ: 9ÁqÜøáËÏh¤Irf’Ø‹mb&Œ±kå? ±qltŒY]ýË}‡æÞvt¡Óþã‚3~¿™úðÿ¸ó¶£›Ï‚°L8|q>6~8`Û ÏCùßAazV J Ô&¹º759¬…Ï€ö÷ˆâj†/ñdaÀrôr±ºÒ¬÷„ZWøzч¬ ùÔë È æK=«a£ª{u>½~´1ÒmžoŒù#òWÀ+ÅãóÃGÀ /Ü4•¦ö]ib·&‰}jP='„ÐgÉ8¿UÕ펪sóKÙsdá}³ËÅÙÝ2œSº¥açH³‰ú’ehš¡¾ç"ùÓ¾àkáÖcP`unŸ«rü=_ `½f¢ÚU„"×ó@’Uœ¡ÞyEÍ ®a¥¶‹ô“šÕô|}eú¥Î|z ¨7E™N'Ç:²ô±±¡ìçLšœ!"W‰ðQ…·'<lõx¨É¡Mslb/OSû6 ú4°{!èR(Ê…`íú$±CªÁ9çöÍ-´®?:׺aÏLçþ…<¼Ô+“.žß‡†ÌÉâ4/ ˆK©„¸š&Zùwú­oö`&®ǯÖúb6à9*MîûüžÅðàPbÉw@ÈÑ$H¿”\©0¸H¯€ÓS_Mþ Ý¯Õ³BÓûï D ÌfC–û—ý}fÿÜ.8gó{¬1Œ˜×a=ðZà¤zWàŠcOpAŸ7œ%O4F®@Ùof,t,µ»»ç—‹’DnWå¦c‹y’Z¹`|$Ýîʰp`!ß¿‡n®ŒdXhO¤r`YÙÿòí;Ÿpš¿´([ R€ eL®à*í­–ÔøAö¾ºšWkzOëCÕ"S›õJhu±±GÉbµïàÊÛFé%ƒ}?zšý ^£ ÚL/ËIßìWF=­7}@qŠ ªVÉLÞ9_NÛ½Ç>pÉc¶þªˆ ƒ<øàÇ€ÛO ‰5oá²ÅN1Ó.ü×â" 4S+%ÈâÑåâÞ9Ç"qqæóˆ¿Ã˜+vWßw±•Ã$ÌŒ¤öP33{‹ ûOJæÞ÷ãW…ñ›¾>—wV Z%tBlÉ)52þb6‚¯…[ãbÀPgùêÃŽ©cûjÀÃ@G#!ì)*•2 zÍ×¼Uª¯ôŸ‹©Ê¿•¦×¯ÕÇÕœÀXa®íŠ<`Ó˜ÿÚxÛtwßPcú#矵ùçM@/Sô+À§ßùƒO¼öCŸûÎgN ÀXî–þ–£±“q]jÆ+ëS#yîµ;9’Žú`»~Òˆ<6¨n(}ÏùkjXʬ,Ž6ìþáF²ÇŠL»ºEîùàϼ”3.:›™[¾Ùö­‚¤Õ‰)¼B#¼Æ6îA“¼Úï ]j‰VÂpaPè«€Ó ß|_ð~ÀŠÔB×ÕŸ[eûT¥Faõ•º¦{­d•–÷8B¯Å¬/à8j—`Ì k€Œˆ$Bš(F,˜oúÎþå[‡É'ÏÞ±éGãÒò²øIùÉw¼èqoýƒ/Þú'' €¯>°°bBÁ|YÉ2k?³ûüõÍ;ÅÊú¼ôIPÔ€ÏãD¤ÝH¤m­ .(³]Ï?aOÆÓ(§àƒ,úVIÈ”Í=t}A[Ѿµê±þ—‡l'«R½½ÌÞ€)ïÅÿuÆP*wÇç ª÷ڃƀ¶S›ò•$AíîY€ 9¶x/'"ͧqRéb·p+;eÕÁ†oÜ?ÿÀž½cÓkÍœó5ýøý»êÂ'zïw{¾ô‰¯ÝwëqàDÆÝ³Ý.ppõëmZAÈÖe–7=ýbÜáà ¸Ž?Z9n9Çš{B®1ß_%rü@ë`bæx€®ä¡âƒL¾æaÐÒпnµQÓ¥ÒüÁóA¥Í«ýym¾é¿×óç"ñG'€P›~z€ ˆÚwˆÀ\ÛË “Õ‘Iuù9L~åþù¯Î.vw>öŒ /š}jìQÔQU}g ¡|íÓκÆ9÷±²ôÿø¿o>ø?¹ù])yU6 'œ•A÷޻㬧ÊVYØ¥vfÕE9" eõMLQÖ¾è5ù²Jð+2t½~½¾`kp †‹ƒyÿÁ2„º5Aúç®ä×wõrw2à d…©!®sT+F}} Uܘj퀪}]Dq¥g¹ãºÍþ×QÀYÁY¾mº{ôàüŸ·môÚÓ6­»4K“̇àŒÈãQ¶^¢A_¢Êí/¹xó‡þþö#]-«ï #”¹çèßü#ÃRÁ¶ {ºnf6ÓL ð1Í›˜Xí¹Ä%rzcPp^«v-¸AÀ5`HžW¥ý¾¹ÜBõ¦èƒØ~­ÍµðçÔ ŸÁÄÔ‚ƒ±µÀ±} Æ Fq…g®ãºIï[Ç’™W:™¡›ZlŸ)uã¿ìYÚ»íhëæ±¡äFb÷ 5’ ëÇšÏIûr#`*`ÄÜ‚’çN÷Î-Û7ÎA´¬g®‘HÑH·^·¶“;a}£[ìH ÝÔHgj±ûÚeø»í“Í×®mþ*ª“¨~ø¥g9ñàÏÿy×ÜÁ5À<ð®´ä2X +Þ*$pOp\h|”TÍÂ5ô}¾Öµú¨Z‚õûf¿~ÿ¡?ÈM<ôIà «¢€‚J• ˆ‚V*¾Bxb!³±B)-VÏÿך 1f¥¦["ó·ƒ`¨9AT€Ör^<°èÚ™:±bâhå0oƒÎ¯ËÌáÔÊbZ†³[ž©\Î=#xei¡Üâ <Ún›†:N͖̚ɑfrfšØ÷%F~áÎYÿ×k €8噯±ìWDkÕc§÷ ^ªÅ™tEò â—è³è {`§^è6ð^€áã Ö¯ïzɽžÐ^J¹îP ¡Ölzö^ˆí^F­‹FE—`c[\ï76v^^œ-4CE•)‰:–W·7Ÿ+´cÄ/ÉìÔPºÓ9mø CYb¼W]¸ûX·8w²Ñ\t²S„ÒÄœ¿k¶ÛUÕµãó/Âs)"#»ÞôÀ qÍÀÚì'U.@lÐÜ“8Çíû—fŽÚM-E=´™@jàT¦ ¬oKoúÇW‚g>Y]€ö¬@/4p’Ta·µüi6Ì¢4+ÂÐø´3ÜY¿Ë<Û*À€é•…©ÎÕ›‚§ñõø¨}×ÑËî Œê˜L`}# ´iËF Y–0‘¬u+Q«MEòj¡''¨"::$@Ô£¥§Û.øÖöt€2Äu,r_Áš†" 2ýQÇšà—ã]®âhSùÒ¸ãUjêÕ6teÉ·†(Ôë³]# {(D°¢$¾àC]ï4 *Ç•f÷Ï9:VØèY àö 7ƒá_00)©°Æ2ÃH# ´™0’¥$„©DHÄ÷–‹ÚoªUIjßo0‰‰‹I%qј0R(=Æ9Ì´;7-f†-®ȃR–†Ò‡žˆæt}ó8ÔíQÆšàïŠãk0.žðÙ˼¾Ê×-`n Žõ¤EW„ýIBÃW?Ûu·7Öø²ƒ'ÂË2pAûÚ­ôSÅPÕù\í¹!1Ò_\¢"©A„1+<{Äòù£i4û#(üáFJÚÌØ!i_ùú¾™¯ˆL⼿øÿ€e04.™8ÏM{ÉC+5äe,˜çh/0HCüu³S“Ûšµ…Žk3!°· ×,—ò%x/U}^V4i„ ½š½cÀ5HÿÂcâMþÉÁ²ž@û<@ªz¾ôA6 d­Ï% dê"Y½r,e{}ýP–Ä­‘Ðl¦lL-g¨#$6j»í›ùÞ’±¶bÿImªKEþįk4lˆ€ÊªyU.ÞXz™¹8q5nÞOÍ„ûhZÏ(%;Š.ÄGPXÁ$¦¿h2ä©,©Ã¾šzdœçš»çö-”Ún&´K¥Ðr«t‰èEk%¸5€žµÀ´rãžR¯;ÇòG¥uÕû‚Æb P\Ðq<ΖÜX’ºÖO¼s*œ!ÊëÓ˜Ô(V¾ï/zx+á÷ž‰I *¾P#¤‚©Á`oà±F8/‰äÅAµëÍ$¦ç ¢àãk5I4F@•P8lðì™nµ®ÝÓ:4”HQm9h!tŒÐñô.YÉ•Oi¬\8±kRXúV©ŸÞf̳Á„•­Î¼ûêyP°(/^î’53n´¦úöÊ:…g ¼ÀÀVbÀ-@?œ;øbC¨êÌuB¨·Jôjú½P-v±#Æàb{µ&®l£f÷–‰Ôúj‘èz¡hc¢‹EK‡–”/Þ:½ç@;,¤´ËÀ²BÛ˜(xßìV}þT‰ßàX; p‚ûgÀáÀ?ßãôÛ%æ)¾²Ùqu•þ­Îêª8üÅí‚'a ATÙ 0YÅîô&g_Šf_+í¯b¾~³Æ@¸Ú¿.þÔ¯}yLáVq|ÒÏÞÕ!$R- _å÷“ ‰­@÷é­-, Þò’D=÷XXúÌ=‹{‡ŠBY*a ¡-BÇ:6N©ýX;ý_C$'xQŒ û¿Zè_ŸnôÒ!‘Ô×Í©ËÿÕ´ I€-AÙJü1Ê UÜ/ƒÉ#é™{~ÇNýBݬQ_¯ ð…:þA]½«:$‘•žÔ«€×ñ}ôÿ½‹àX‰­fÞ ‡æ>(ù̓÷l‡¥¡T–s¯‹–ÅÐ21 ݦòÿUOÀŠ5‡Nu¬Yœàf ¡µ¨\÷R¿žT¬}±š³<ÀØ}ÕWÚ¸®T¯Á²*¨˜^"§nÃ4åUWŽô[¸ªŸþ¥ç|j&šô5~%‰3½Mz¤o@óoz@~ ¥#tsU¾½sfúïîoïJ¥“](•–+íD¤å”–ë]—@hÉîêíTä¶&ãdâºÑ°çšR?w~ÊE;6öÑ-½¹uR'å 25Ô/yðóÚ: j7Pí÷$Ô@«}¼é ¿®Ý×Ö 6ÿ5ãïƒ"6z˜4þÆp ÆV?%”%Ú-Ò³Ð*ÜÝpäžNЖ5,vóS+­†‘A[†žp§O®åX3,ŸdNÚÂQ”Ûþ*÷ÿðÎ4y½…¿¸ š ˜q€—@ÿ¥•%ä^‹.«ÒºÝ="*„~Ü_ûü^žönÿObÏtfÞ$vßüY>Ñ™)+ø¢AâÿýÓÑèëoL. -Õè¤L…0K,•‰¡Ü0æ¢(=иÕ^û·`e`ýU‰ô ®þ¢àÒ_—òýÏ&ôØé”Ÿlch&Ý)^~Eqé¤/þ¹#fâ¶k +ôt^8¢^1EËO0K$M^:é]^Ÿº¬^4û§O–£ð)†}ñ¹HnP/ºŸ× Öãú^Yÿéí¼‘‹æ aZ&˜³A™1å}Æœæ¥CUnÀû‹TW•Y½Ã`€ê”Á9(Þûó¹ÿç]ÅÔšn9CdÜF>Ý¢ù¢k¸X:ñËaÙî¹ýÓ¿—ó~*6þdž¥ÅßY1)Dö-1~ìš$º1¢³ˆÛöÿÁt×/^MÒ-‚âTU@N¡â u WÔ2ÌEþ›×Fo¿t­Þ*JÑq%˜8`žä©¡Ì>Ö-Ú²…ñç1?ÿµ+õ[ :;ŒK`ÚyÆ(–晥‰eLPH±ãÑÜ0ðCÛe¾î-V¦´ Ðá¡«Ï%8;­õÀHqøæþö|]|ùxö;?Ÿòz£‘öÿ¦I%›IDAT ^ ±F€Î"ÄÜÁ"|»ùG ‡vŽ&Å\=-ßëÑ£Wˆ'4 ”Š ¶Òz$¢˜ÔÒ~ãíù[ßÜn/'„¢UQø'Œ|˜`>°<é3&ìd¾Û¢º¸f•%¿Á }€Õ}aô¸¥7Ÿ]?Ûâ×bø/…¼½}½šùXöÛÏÍI}(Ef/GN7«ÆYþƒâu­B4ÿº˜­¡Ð¯Îrë ¡j§ûB§È+'•ð;GepÁ*¤\˜4Ó?;—ÿïìùí!£lT'…ÇdÌ~‘ÅAƒYßð$3³ÓI[h±«höQ,Q˜ï-î+'°C¼êëS Òá« ž€s^ýÊõêÛ¿·a_øÂFúù5CYïIÒ ˆÐÙK`Tb"¹Äð¢(„.¢‹rp7Æ](„äZ;8˜•€ ]×W(f¸0<*! q¢/½[nþÅ¥òíZg ÊÒë¤ð˜ÎYÌ{@~Àb6HhÒK°kH&e«ùuE=!ˆ¥p»øîø0¬î XYJ)À8š=Ëô£Z%;ÛâYVH!ØûÚÈýèÕB®}q#ùÕ3ó„E   Ù= ƒuHÄy^p¼óÕEã°ˆ û|‰Ôîס˜4f ƒ¥PéˆC„ó£fòw‹óßÛi¯3PYFQx–³90¯€ÂyßbÖOh/³4bÕ½y©³÷TÁ>« îK Ä@Ÿi÷LÐ@Ìë-ž®Ú'è«¥\<_×;/Íé/¬ÛçOôø0!Ò»¼B… ²ÄdYÏN˜xE«s½_Z &^½ìSÄIi㨠Að \/\ùÒ•âÊ·¯5›7Z÷U+šW‚y%ÈK ¨€ÜÅA‹Ù„ƃ„Fº›—:¹Ö¢,—}Âîcè †DÛÏ÷ùß™DßlðôT¡Ÿ Ü·æþ'/—rõ7‡üÔo¬Ù§Ne|<ƒžTu¾kÐ…‰‡ˆ¦¥‹²ó"š„ÂÄò±1¡V0Á)peÚÎp½¾öÝ­æÚÅB¦}ƒ:eä¥è¬ô(ê°Ã¢j€²GÈûÓ5Kã¾¥‘QÝ)êÛ„¿\êþqß+4ÜËC¦íÏÌ÷’ú•ZiÈPá2 {mÿqêgÿšË¥Ïõùñ_š'ŸšŸÛHxRàPI'á®ÅŠ"Gú8Ä’/‚MIʰ–‘pèÑÞ«}sn\_¾Qßøá®ÛÙn4ï1š¾AѨ†/(j ®…«êòÓABã!ÓŽUÝ-l5( Àg±Æ~ˆû_"À€0:™Ò¿ÕŠòJ«¿¼¥dŠr p£-¼¶?Ì}þãBÞ;>vëgú|ìtŸþÂÀ:–òÚÐP’¢¤ ñ4=ƒÆáÔzŠAŸ@™÷ ÔDîzåŠwFõäܸ™¼6vãw+)A“¸žAÙJ|½$x4¨zNþ ¡Ý!ó(%Ý-kn5¨Z2}+ßù3‚t1;åîðGë÷J—CX"Mÿf«¨ˆz¢úÜ를pÉãêœÒèe„¾aô}àž¦‡ õ2õNf´v<åáFƽŒ)YO9•V¸˜{ÚH0uR;"?ST7k)®ä®ÕÚî¶ÚÁ÷BÒ©¢j¢òš×вUÔuØ^Ó¨S êäý„&=C»™ÅètÜ4š_.Q¿nCß$PÒºv„;EîîL“ ÐAÊÇÇS~…™v7ò+*=5²VQõBú¼2‚Å÷žÁ³j< °pó$Ô6²&™õƒ}¼ðÔ“ÕáÇŽR~s›nlíÀ]Øåky«“yXô[HèÀ1WãçvM±÷«“÷Qx8à6(Â’Ë®ÑÎZ‹#'>«F¼Î¶æ˜L5Ð ð¾›ù€Þòƒ†•¥‚áÁÄý˜›x„à!Ç#xÈñHr`±Ç#E™±-Ì,‹‡Åâ}xï} "ÂO¹È‹žÀE——\ô.º¼à¢'pÑå%=‹./¸è \tùÉÚÊoÿ××€ñ‘àM)¤0u@S·—p¿ðî¥0Ï ”²²nÛ½¾Rh"&h"hm." ´<9 ËvÞ¿ª#¸'hE ZÓ“/>ûèS€¿üé£|üÇ?ÿíå@ˆê’RB2@š.B"¥ÇÞW€I$’ «Ér´&(U*ª4”§¨ðŸÓQ^¤ ZW+­5 ¤“g_Ô,ÀšŒÆ @AñU¿Â{à„ßïKÆêDSämS Qk £i“û¾? ”P€/á;ΰӯ@ìBä7Ööÿ´Â³ÈXŸÓ[À´¦ÏYß{RÛI² ½bŸWÙiE§#(„œé¥ü È…m7'd|16Ö ’ M 24@“ØØ¢Éf‰TõsýQ“|ËùÇýÞ·õ™Äð•åEp¦•sû¨,ÊÉZEEDMνj² ÞÎÛ„Hj¶™$²=¿PìEk±‰†mM+n÷ €_¯ä¶eÍBÈ)1@J,,,Ô&tŠÆJ“’M²FÓG ¬?LàM’Ľ# Àüü¼7ðó­5”Rµöj¢ñ·Sžf vü°@ånV‚H;W•Ò´ÙR I’s€ˆðàÁWÈó,ˆæf4Ck¹¹¹¨+ôz=´ZseL*U#LQF˜ŸŸ¯@¹ =ðöÛo!Ï[Ðel' ¥D«ÕznÅm)ŠI’àý÷•ckk ëë·Ëý½oÖ|…»w×Ë•¬B`0¢×ëãÊ•ËîYëR <|¸4M17×rÀy—Ðÿù !¼‰ÇL¼¬ï<ÞÁåËKî㈡=´`l]²GÄ c¼°ÐßLUqå,Çäî—ì8LyÆýde–^‰ýE€Ñh´¯µÖ’ÛÉ9¾šÕo<Úû÷ðîþžò.õµ`T€N&5÷ ¢‚^P0¾B…x{ ü1C岨¬ÀÊ&ÒZöù˜ DI›ˆïJÂ'„7q^”R "(¥rWJƒ—¿sZä{»àÀ(¥ IC) ¥•UÐÄ*ã‹$,NÇ™‚àd2Áßþ~WW×¢òb2Á¥Å¶—`؉*¥°½ÝA«Õª3!ÇÇØùïÐÛùÖÉÙøö»ÇФ+_g47ÑétʯŦ7÷~à§Ñ¼Ì€*^yu ×o¼]åA¿‡7®½Š,ËêÏ*…ñx‚÷Þ{·å…@ÿÙSÐѬ­þ¬îÓdvzï¾óüÌÎl¶†Ãò¹wî܆VÚÉ)66þí>·‡{‹S@¨vw±´6Ü8q%Ù“— º¾Žpy̘ D`Àñܾl/·ÁÊZ—u)*k¦=¶Á;÷<€O.Ö£B{ðŽ!|:ÂïÕ7ψª^ž@ÖßûB¡Ð×›¢}Ø'F}±v ë:î>qÆDèLÅùl”çãTÇÝ©‰ þëÓ y¾òvµY_ H8ö̈òH«™ …»8…Y%¹²õôذ*Ùö2ª™!"!x"PߌßÛyXŹ;žÉ„zÇ="Æ%ƒ~­ Ȳ¬fþJ) ‡#<~¼¡A‰þQ“œã¿åÖ 0Ø{²03¶+=Oð¬ÛÅÞ“}Ãl•!ÌF rpf€hÏ·±´¼´›A“Dàòå%äyÎ67@( …<ϰ²² ¥4ÂD'Mô~~ ¯Ý~«ü(êûðþXº´èíí #,.,`yyÉzÂÏööÚžKI)‘¦éé°ÈñíAeæ•Ìʹ?Kiê\Vq¹ý0Îý¾ârköflCçÂY‚”ÂÈ…’ò½ºW–îÈæšÈ¤æ~g ‚>Õ WoŠæ¾âa˜Ù‘_ÔóÇó‚`\ x°•B"Ë2(­Pn+pú£±çgQ¸éÞMÖ}éE]b@Ê»˜Àë æ i’"ËRdyŸ£œiËëSÝ47ò©àãp¯®¨MTй•w4ïxγgöI‚4K‘eò,V8U ˆÕíû¥”‘Ãá^Æ+·ôÊë¦tí@yŒVfrÆ÷mŒ°¿ ª"%’$A–¦ÈÒI’"ÏsEq– HØ|ôãq5÷ѰãgO¦‰ç³6 ít¾C–e•Œåèƒþ»»»(Š¢<âªvuß|óZë*g4>žŒ±³³Sž&ù”¥vï`ýöm¤i†45VÐív½E˜‘ k¯½†ëo¼ýn7è÷ðúꊯd)³yÀÍ›7¼@iK¯×Gš¥¸qã†ûvÀåƒÁׯ_‡´ѼØõ¹uó&¥ò)Ò4Å»ë˜o·K媇‡‡³[§:‹ Àö™¤)ò»ð@gO^}™?‰p•uà*ê#AåA§6_„ìG ĈZiÈ„%B̽xß41+Ÿ–>o•OS£æÓ§O1 Ü=ÐÀœêø„Õ•ob¿«œk{9@©d°ÕmŠö©§p†,ËœòÖäwww1™LNv®¨¯HÀáÔç?SLy8³$9Tð<Ê@§ÓÁâ⢗Ñ6Z@}E„¨w·m<¶”f겪KQžÌpêchevoýŸÓ`( ‹7Üò¦)~•îv»ØÜÜÄÆÆ¶¶¶Cœbê*N½o°”ðÓT¸±A½^SÞåö9òùý{÷NøWÇfùòË/éÃ?tº‰˜¿þ”ÊÿëK¾yÔãóIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/calc.png000066400000000000000000000150101217176075400226140ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞÏIDATxœÅ›yÅç?™u¼ûu·Ôj]íÖÕj5âBH Ä=x öÚÆ‹Ÿ{ÀÇ"<Þ3^Û1ao ÞØÙqÏÄìlؘÛk ¶9^# HèjÝR_’úTï~U•™ûGÕkÀòìf«ô^ÕûUVæ¯~ù;¾¿_Š[?öqêiZkÊå26\Êg?û).XȮݻ©V«X–…1¦®~Þªyï¹ý„熷ê>Çaýúu çùçŸGJÉ}÷ýûºŸm×;ð3èþ!¶#":¤”ÿ_ ¥œƒB !î”Rþ´‘gÛñ¸[¡Ö0_Øí…|žl:Íää) …"ŽãÌ ´ž&D­O4(£ '+jOÅó¶ RÊ'‹S(”(•JÖä©S?Y¼hQø×ºØZ‹w¦´ÃJk’É4óç·²lY•JåŒ%P¯4=­k%êãô÷­Ö!}yÆ@øØ¶M&“!‘HP*•8v¬ÿa€eÕÇ!Ò’V&“¢)›f``€¾¾^,iaYV½ÏÃ`ˆþuõô5ˆs®¿5c•¯PFè€T*E:•¡êUd݃ì˜[ÿ0Æè¦¦ò³y¾öÿ333¤R©P„ß©9‡úx>G(Î>=kLSSSŒŒœäÎ;?A2•@È:Å0j¶×E¨µF A:¦âyT*ššš1FT•jpö2xG¥øf.â-¹#æD_ –$–t°mI:fdä$nÜ%×» çZC€1$’ \×%îºKE&Æ&±“†ù ›Q¾i!Qû¬\ k“« ©D$à4ct´îÆ€ˆt€1`”&##ƒ9Rñ&2Mi\7†k‡ hÔÙN¬>(­Qñ¶m£À×äóyþÛ{ØrùUÌ–rh£¢;N+2]û¿6ac"0 FèGˆè7@ Æ @ªÕ¯Šp©–ë—¼üÓ£¤›RáDl›x,ŽVº1ÄÜX]„Zk„d2AMqj¥B’MµP©TòAô FkŒBiƒ”á=J©Ð~#N—2\b*@‹/ð¨•hòŠ“ÃcÌ[ØB*gbxŠÅË0oþ|ÿµ¥ä¸ñx<2¥ 0À­s (N,‹!¥ÚmD?Bà+ÏG Q*@`hU“cÑi,Ð# ï(-|JÕ2Jû¡ ‚T*ÆžG˜™Ì‘Êž¢cÕRíígüø) §J)0Z‡zpc.~ þ¯óxê%Ú„z£6¶Fµ`Ý 8Ý­ \Ì ‰xœLe[ZHË =D)–…D"- DèïEkIGŠSéPy­Q:|“–%©–« íŸâ¹'_§ZõØõÜ’Ö|>}÷'yöÙßÌ™>q†E©›õ®˜ÚêÒFãùU*• mm­ŒMŒ²woS3sÖAœs_½ËRœu³ÀDŽ‘µ.P*`Ùò–´/"™LR.—ÑÊ Ñ(Ý h$ÖÚà{ Z[±¥dddŒññIb±ófx+ïîŒΜæ;¶³™qúªŒLç&™xc”ÙÜ,7ß|3ÂJ5îÕKŽÅP,Éd³<öøã<óÌ3¡˜Ë· †ÎíϹö–C=CdÌ›®ƒˆ¾hÀ÷}2é4wÜy'¹Ùçû`4wÞy7Þø~v¼ðÆh,Ëb°7£R)sÇ!MïJˆo|ó[uj­©T*o\¾iãÅ[·ÝL2ž ÷È‘ÐY±-„ ÃÝήÕs÷•Ê%Žöö¬¾›®î5h­‘RR*•‰¢GDZXµj•j×1;=ÍÉÑQ¤A€V ÇuYÕÙI<ãÄÉ“<óëgðÿ‰{þô ·ÕË»nŽ…0 ç\«»ºÞ†Ü „ ™Hrá…¼%M¥R i’IÖ¬é~ÓïžçS­xT½€y­­Ìkm}ÍÌLǶÁh”Ðë€ÆÈáÌÙÏNOóòÎWH&â@J‹|>Ç›7ÓÒjïÞ#‡é9px"6§á•pÝŸ\O2¢9öïãÀƒ$“ñŸ <«¯¿–l&‹”6¯ýñU††‡H%’Zc” <®ºú,;‹1¡DÃ:@Ö±xˆ"ýÛ}„Ÿþô úŽ£¯ï¿ýÍïøÉOžàÖß À@ÿýÈÇØ ‡±Ñq¦¦¦›äÿéò§wßÀ¡C‡øømwpüøq&'§(W=Œ1üä‰'ùâîÁu]^}åe¾øÅ/±sçÙõƆ†‡yíõ]<þØ?ð¯#œˆ-1¢q%(k]÷a – ôãøÈIbÉCÇOÎdPbɃÇsjòû÷‡>ÍrÑúõt­YƒÂ`¹.{öî`ßž=”*¡X·~= ,`Þ‚,X´ý=1Ú°wÏ^´TÅü¶V–,mG8.©¦&öìÙ,%gv„p…CG#\›ËW¬ä¦¼ŸÙ|™JÕãøÉ“¤ÒJƒCl»ùÌoÏWnfýº‹bê_~I æµÌ#‹óñÛC=uÕÕWqÙ†õìÙ»£ý`4Zò¹<·}ìV„\}íÕ<·ãE´6í`b|’é™YŒQÜú±[¡Žè·O¢¼]þùª‹pÎ l¼ìâmÛ¶’I§8tè I |0¡–?oíÚ98<ŸËÑÛ׋$ôƒ w9ÿ‚‹¨V+¸®ËÌô }Gû¢H/ô:Ç¥û¼n<ÏùLNLrbxi;! HÛ¢»»›l6ËððqžzêiüÀ{â+_þÒ{gjy¼Zëî>ïM¤~àã{>Æ’©ë×_z3ÅB?ð)WÊ$ .»ì²³ôL(J¥"¾ïS­VÉdš¸ø’VB¸=„Óƒ  P(H†&Ù„"ÐP³ëý ¼9¦7Ú "èÛ±?@J˲ÐJ¨¥¶e‡~2IËaÛ6‰dÏóð=Ÿ@X–Äq\’ñ$9?‡eYÄb1|¯ŠŠb~ƒ û‰2[5'¨Ñ%`7à†‰J2B~žþõÓ¼öê«,]º”yó[Èå í;Âå—oæ7ßÀßýèQÆ''YØÖ†ã8är9ÆÇÆØzË66nÚDµZåï}ŒÉÉIZ, ›Í216ÆØè87ü›ؼùJ …"ýè‡TªÍÍÍè e‡‡‡ÙvË66oÙCÿ/Ì 0$“Iò³³lß¾¡áãô<‚6Åb‰£Ç†¹oûý y^Üñ"õWßgx虦,Ýk×2:6Ξý=sAÌ‹;^ä{ßÿ/?1J"ž ££a;ì?ØÃC|Û¶ùÍ3¿æ±Ç~ÌèØ8Žípé¦K>9žC|ë/Bì04ƒ ÍÙ˜ oBP*—ˆÅâ8ñ¾6”ªUõö‘nÊ’H$¨T<*å2é–&pl„eáÖ¤²M˜Š(—J45ÏC:.dž†°\‡SÓ3¤›š–ïû”Je²ÍÍ(ÅŠÇìL/P¤³Ía„éÜbŠzšµyË–º# ~Ï’%‹u®ê¤eÞ<’±S,hO!—C ïù|øCdó•›YÚÞNnj_ù(¥Ÿ§R®bTÀg>ó):Ww²hñb ¹Y|ß'™H0<|œb¡€ÑšÛo¿î5Ý,\¼„éÉI,Û¢R-Ó´Ÿx"Nà{|òwÒµf ÓÓS>t¥ô+®¸üÉzиÀà)I>}×gùwå2Z)´Ñ@H‹T*E.—Ƕ,øúƒäfg…2 ),œ˜C<grò¶m±ý«÷“ËåÐZEùB ǶˆÇ“ŒŽãÚ6Ûÿl;¹Ù|¨Š£7íØñDœŠWE©7WžÔÅ€F­€ #b 4C‰Dâ4Mhæóy‚ÀÇ÷}”Ö¤³ÙóW #Z)òù<*P*Ì&¥ÓéÓ‹ž¡•b6?‹VŠJ”ËdÓa6ƒ6ø>…B‘L&¥RÞMj¬A?mæÀAiI>„-m<ßÃum”oX¾r9RJlÛ¦X*2Ø3€a&ªêZ¾lEJ¸ŽK¹Rfp`€(Pƒÿyß²eTË×%_È148ã„CVJ!öe˰m+„éÎDlêe@£ó7\' "ïûÒWð•bñâÅtv®¤`˜á¡AlËâoþö¿3zr”û·ßÇ’öv.ºè"b±½}}êéaíyçóÐ7bh`¾öK:ÚéZ½šT&EÿÑ~z{{Yµb~ã!<Ìw¾ý0ÝkÏÇqlt ˆÅãìÙ³‡u_̃}°ÐÌP'Ä9פ¡Á?!H¤Rô=ÊSO?ƒçk:–-gÃe›˜™™Á xú7¿ep Ÿÿýû—Ø×sŠ06:N˼yäóŒeó³Ÿ=A¥Rá÷/ýž½{(W=:W¯fÉâ÷Q,•1ÒâŸþKÊ¥2;^xŽcýC”ËUæÍk¥½£ƒb©ŒÂâç¿øïcYv芿—„1xŽŽÖ¬YÒâäÈÂvbÊеz5-óçÓ±r9‹Ú"„…¯5Ó33acŒà‹/±V¬\Î’ÅKÒ¦·¯Ÿ…m­HÛ#¸è‚óq\‡•«:immÅ‹é™Ð{ ŒÀ’’ Ö®ÅvœÐCœÓõ7ëò+®¬oúg˜ÁÕ«H¦Rlܸ­|â®K©X`~K íKøÜÝŸcAk ZÐÕµ A&• X,1¯¥‰®•+ùÌg?’¶¶6ºVw"ŒÆ(Ÿb±H:™dÕÊå|âSŸÀ’K–.¥£½£\ÇÁµ-2™+–wðñÛo§uÁ¦¦¦8t84ƒ[®Ü܈l02Ì$¬X¹‚U«BÎexkÉŒééi„€u—¬cÃÆ seµ,p©P Ëa„à‚ /`ýúõQP xJųù<Â.¹ä.ݸ!T¤„EA ¨VªT*eÞªª´.Ô[Rctx„k¬VïcБÓÑu!Ä\9 „Ñ£R „i5UŽ)}_0ÆàÏ™D "¬PJa´BH w 0Ê`„&¬pÕQ…#æü”Æ ð¤™+ŽàõW_#ÛÜM< /rÁE²lÙ2@°g÷n†“ÍdR†©®R‰Wl"“Íb[û÷ìcxx˜¦–´VøUŸR©ÈúË6mjÆ’’;w233C2™Œ®™žáÊ-›I$âˆÖh0Ôh,`LX*§µâî»îæ·Ï¾ÀÞ½(—«¼üòküîwÏqï=÷¢Ÿƒ==|õþ¯òê«»y}×n4†Á¡ažü—ŸóЃ‘I7q°ç<ð`ˆõ “É6q çO=õ ßúæ_ÐÒÔÄË/¿Ì·¿ó]&OM16~ŠÑ±I¦gó<¿ã%¾ûíï"¥ ·0è“£ Cb`p—c}G›œä‚K’œ89Êâö%Ìò¸‰$“§¦9yr”ÞÞ^´øZ“ËHFFÇIg›éÙ¿‡J¥Dï‘ÃFàk81:ÆEë.¦P.ÏfÙ·ë5Ê¥ýýÇ–ÍððqdTR'eX«848D±XÂr¬¹hµ!4 (–‹tvuqãŸÜ€çùd²YNœ8I<'73Ãõ×^C{{;–mqÞš.´Ö´-ZÈôôthÅ-Û¶á86nâüç_B AKSö@Fõ…[·m¥¥¥!$©d’X"1§×%™LÄ_˜Ð`‘T£±Úà{>?ü0}½G°"œNJIà+Þ·¼R¹DKK ùðÃŒŒŒaAÃòXH:–/gròÍÍÍ|ýÏdlt4ôäE÷š®Ð]^¾œB©„V–ãà:Ò’¸ŽKµZ%æÆ¢JõÈ2 ïe‰L(b§1Aƒ¡«»{nLjѡr*Kx~cÀMÄXsޚȄ a!d1_ÄW>^µJ,£sõê¹>¥©”JÄâ±0ò³,¤”\¸v-+W®àÙçw019‚­:Ä1]OåúÙ ¨p.8#àŠÇ⌡¢0ֶᥥUTQ¥˜ÅÄÄDÈ$ &ʦ3TAaÛá~ƒ©©©9m– › ­‹6`Y6±XŒÑñ Êå*Ú\×J<"“kL£2ئNG ¬]M˹üƒGatlŒ®Õ¤3YFGÇ9ÉüÖù|ñË_!—›åûßû>™L†¦¦,A p—¾#‡Y·nú臙Éñßþë_“ΤI¥Ò!l‹Ñì(kמϧ?ûi¤˶I$AÀØÄ8ñX ×q"é¹Ú ¥+““AÐÈá{>®§ÿØQÿñßS,”inžÏ¼Öh¥È•*üãÿø'úû±ã…xöÙç(+ÌLçQ FFFÉ+<úèc” ¥æ¹ÈåËÌo]ÀÆM—cŒd&Wâñÿc£ãø^€ëº$ Òé MMM$“)â‰ÂâÉ8Édœ±±*^ÕÃ÷ý†”€µöüóQ*xÇ#|<¯ú•¶…m Îë½D,ÎÔÔ$¥b‘ÜÌ4¹éiËâÆo cÙûhjn!s©”K£¨V<,Kâ:7Ýt©d’–Ö’ñåb‘Ùéi†‡‡ñ«1׿ýï¿‘T*MÛÂ6ßgxxB~–™©)Nš@¢ùèG?Êyçu311Á®]»Éå Gn¹ekÝ[çìšâz§Y6kk€Èú è^{^)j,KÎALÏäÀUW]Møsµ93Š™ÙB 6]qAàÍÁ]Fi¤Ö ÏÌÎbIÉÖmÛ0A€®m¼bn'™ïû„ES%–u´¿ØˆØ1§Ž 0à:î½åJõz¥U@µZ¥Zõ¢ì"ðý(ø ”£Ã·@+=§á•Öá ­À@.—GˆÓEÚ˜ð‘:Ü7 Œ \*‡™'#Àц‹Pa —ËÑÕÕùã뮻ᑆP—#dÂ*¬¸ç?çá5ÿü³ŸlwØ—'&'ê Zƒ6ÊDÛ]ŒaŽBXV`I FJ)li„@Ha„ˆ¹½PBŒ0QjG‡þ„ÑJ[J)Ëh%”1 ti #´1Â÷}áHË»æúëzz{{·ßÿW_Ó:Bõ !p\>|äà7@à`e2«¥¥ÅÎf³NKK³Ê65‘N¥íD"a§R)+ÙñXÜr]WÚ¶-m[J!,QË$‡°¸VAh¥”®V«¦P(ˆr¹lJ¥’_.—u>Ÿ÷ …‚ÎçóÁä䤚˜˜(üêW¿: ¿÷Þ{صë÷†sLp|ßèzî»ï>n¸á:::hjjŠe2™x"‘H¸®›°m;$€xtÄ¢O7z¶ÍéjÕÚN ø@T2à¥Ú¹çyåjµZ. ÞÐÐP©··W'“I<Ïã7^ç’K.~ïpî&ÉGy¤ÖOm’‰h¢‰s&_;w ¥Æ&/9».<ˆï ºJôY&Üç亮ëf2™ÊâŋŦM›ŠÌe+kvMñ¼›Å‚p Ôïq3©½Å 'dŒÃé·/8›µ´K@( ¡4xg|zQŸµk&ê+à]0áÿ¥Ú#»³WýIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/chat.png000066400000000000000000000107671217176075400226470ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ¾IDATxœíZyÅyÿ}Ýóæ{ïjWÒê@R@Q`ÀÄ€c\ 1ئb;¡Rqœ“T\œJQ !NªBÙ|ÄvÙÅ‘8q(ã6&&G@¸´Bè^íJ{¾{Îî/tϼyË t,ÙJ™®ê÷öÍL÷ï÷Ýß 13~ž‡Xì ,öx€ÅÞÀb÷Xì ,öx€ÅÞÀb÷Xì ,öø¹'ÀYˆ›\xí·1µÙEôà fO)ÃCˆP½ˆŽWCxp„„38°Ä©Gk ¥uyåžB]…¡‚.ôA#Ï ŽH{³ºÜ8â»ñ^„þnîÖ{½Ñ=µ\g?ºäYh20›{]=PØ7w&ÊS{Àÿü·‹K@2X14"¸:ãöU‡Îذêò•KK¯ìؼl°c¨¿K¢³ÃAAšJŠ0b4=YOcr&ÆØ´§Æ'£“âÔmõæäiU}T Ð`ÀzAö¼ 03´f8=ýÅÓ6®Y²æSgnXû‰3Övž¾vy½%A@¨~¤á…~DŠ*†bP,k—æ!DAFªï”™š>eïøÊßÙW öšÙŠÊi÷PXý~“Š5ä ÀÉs Cf–œ½ùWÏûÜEg¬øÄYk‹]¥jc²¡0š¡! Œ¡6ıF¤(bÍÐ H\‡ÐézKçmÊã¼_(äÇfú?¸m×ʾ:2ó×ÓÓƒ_Ñþô·¡½“Ù;l9|á_ýxhÍÒ7\vÎê?8{]©Øé2¡ÆlS£âk4CP±³­€˜8fDZ#R@š @³ÚìÍ•„Þ¢ÀÒn‰Î¢ÀxYã^ó±mûá—êõ=7ŒÿËGY~ýæ'¯¾tËÆ[/ÜÜ·®¯ÄhúÓMŠÏbXÓɈ#Ò@¬’Ï ¥ `°QhN ¶dÄš!ôVõ9(åvŒÅxâ…ö½­VÛ~CùÞÏúÿ'\øw:ù޳n¹àÜ ×_snòBc¢n¤(@i¶à‘”"f(+ýˆ4”]ž³è, ƒS­ˆ•!bY·Äêf›?}ÙÇ‹/Œ?^sŸ»v꛿?ú®pá?þ¨w³\w÷’õÃWn$¸Pp‚¡”ÒF½#Öhi·¤¯+ ‡‰ìwn¡¹E³%4ftæ §.u¶îðôsGvL¹zú¾¼+|àë?ê¿jÕé÷Ÿ{öÊKê~ˆÝSÌÆp$°ª7‡ž¢hSsÅŒÐjƒYÒ¶pY©'Z¡- ÚšF¤‚€MK]äs„§v†xò…©7*ž»|üû¿½A ¸øÖG:?ºñ´\°eÅe]®F-`¼4àP5 è*ôÑ’|¨AlT¿µª=rëÀܲùôˆØdjmÉ€9/ÖkƦ¥.rð߯xêÙƒO×:¦?<ñåÕÞ ×1§Â—-ßðµ_:kø²RÎ$+Gj +z¬_â¢ä HIðc`²¡1ë1|ÅhFf* ‘™dg滀”) Žp$AŠÖLΕÒNAxc"8gƒ‹37¯¼À.þñà:& ¸î®gÿô×Þ÷‹_]ÖÅð#ÆD]C³Éà˜b”=fÄ© µÏ–سƒÛ_Öþ“£6k(m#Bb*ÖÄ´6ÿ‹ààÌa{¦b<öLû÷m¿rôî+|;lï¨tÛ§mÙ¸ñ‹ý%ãØ&êÆs+šBmvÛ]è)H 8p‚#íFRoæwéP*ý6­ DâÔÒ2— dr.!'Hûgb¬îwpú©%K+¾8|í]'LÀÅ·ÜMƒË‡ÿ~õPG$ÆDÝzqÓ³qt0*ï)N7ëˆÌ†ÅÑgrNJRV”š‹%IPªþÂ’ - ®¦ AÌX»Lâ”ÕýgJ±á·N˜€Uþð%Ö _•w4ª£143b­¡ØƒÄ@3bŒtƒm¶›»Ö–›w„Ñ¢„ˆ– H)̵0ëPz/CÞx5Æ@I`ͪ"ÜBÇg—_yWḠxÿuÒŠ+ÿd ;'X3f›Ú‚çTý•Âðc† vg%²ª.çSû»ùd¶®O4-ÓH´A¢E™DözG ¹ÃKú{Ï‘ƒƒç çQ‹¡¾n±iÙÒ¡»£0üØ”ŸÊ:"“ž2›Mœ]²Ió¬DêçDÀV(Ì„»$ë3ß Ä€&@‘©„6¢#¤©¤0ûlH©x=E¡¡’ÍÀÇ¥=}—÷u»üH¡¯3#f£JAl¦ì›)— ‚HCš0’“Â|¶¿‰ÌÑø–f´bK(цÄ$¬$&çH jú{8¹®÷ }ìë¹cÖ€-7>@¿¼rý¥y—Pö”f(X©ÀH&ÔFœ"Q]2`)#}A‚ýžÜ¼M(“ù˜8-Š$†lM&Ü &€Í-”2'HÉ i4ÛÔè.\·°>rºŒ½B‹]§›øÊÐȤ¡@JFêIJà­íYõJóû9‹?[Á¨»Q‚fƒTj@°€b@h³Àf#´¬ ZSð#F.Gȹ¹'ï;EQXžË»ËbmSM %AÛ}·œV®¬Ìø€pê2$¼¥°“) ¦mÆÚ\APÂjƒ0T²2`A °ØhM$\Vªs>¬ó ½DH§CiÓ¸à pF»§&ë‰³à‘˜D⡳Zj³óvçÇ`mˆ &L Ld¥.¬DAæw °À©íÿ$@ R”’ÇL9èV2ÊhƒA ¶˜›/ ö·Ä)Èn>ß cÓÖ´!˜¡5Y›7'•OÌNX‚XBÙkA±! ‚L’ ³YEÅÝÏJqšíV…ER„$“R°”ÑŠ¬OHÀ·kA†„l¥g ÌPDÐdT´ þLlÌAh§•" £9‚ Bi0Çž[¢y{‡ó Dì…±R‘‚TŒ–t3À‰Z`Ó,Í&BD”•¤³ók@; B'~Æ€²^ iUž-l[(Ì­Œ™!ÛµM æ`Æu0{ÌäÊQ5ÂÝŽÓJh@°Î:¼$7OÀKL.Ÿ ‡s05¿m­ #mRÉÉ M”J‰º“ ›,­Ì>4ˆ8Õ£\ÕÜÜÆzú˜ p 4…ÞD÷vç]ëæJß:8$6?¼´çéoÙÈ•~bûÄ€¦¦ m£\òOcl#³õš ­)›úÂó4jµÕ·E^cÞæÈ¼®!ª7§ »¼ÀªáN¤ŸM}_oÊÙ$´Ù"™™³Ç¤¡!¥ÍôÈf…2ão ² Qšhe£LÖäI˜*kÄ¡ЏñÔ›ßýãø˜ ˆEwâ™g|/B¬¬‘](ÓSÕO¢øD3$%)²­üœ¤ i¥ÐÒ‚”Ò„¶ôÚLÁ“Ô ÈO÷bÛsQ̘˜V€šzUƒ_œçQ xø¦hÒþVÖËu[‰]±ŒdáŒÍ£|¢I)ë'© i'Æ‘Ü/­Å<Ò¶šF{ã û!T8ñ`³P9j«ü¨Å7éoõÓÔÙEæ~Æ<ΰ àØâ§­÷gËWG[ µ®‘ÖR°È$_"R³°òÉIB¥¡03ÃPáÄNæòƒÛoý½è¸ ð—;Samò^G5üJ[,qÎ@ûÈ88"£Æi¥HÂÖñIW§ÕêJìÝ!j«ûI´Gž¹™eê ²Ú(LÛîÀÁB{:hì¿Û ¯ ãÛð½ß½œ…ÖEÕý?–L(×My™Ž9!í-Ú‘ñ)xjo´!8(6«æo½¿ÝBÊ~rî®}õÙÝ?ôï}þök‚"¦ú»ÆÂêÄ·rÑ‘Ca$P÷´)B(¸I[œ¼eƒ­°Ù²çÄR¬Ä“gKòÔ–IsžcoìóAJ Q=¸W…åÛ}5¶çíð½#ÿþ;—r_îgå#{¾Ñ‰zèùMŽ&dÇHËß ¨|³Ò”ø\Ìž]ˆ`ÌH30²×‡P~c¢ìUv9(u>¾õæëßñ-Š·%nüäGêQ\»{öÐëÿÚëðBÝSóvù:¨íЖHµù‘ÌùslëúVv$¡ékìØ OüæT£<9r»¨;ÿöØ —Ó{ïHÜö‡?¨Ãé/Mî{é~dzƒjSCkÄiV7÷QW’À!)x}˜¹î8G’?ŒMEØ»?@_1‡je¼R{ý¶šßxàKWÏ›öÎ7Žëáè_~ë¾-ÝÝ7¬ÞpöU\ꕊQÊ \ûˆJš°–„¸ì÷ÔûS+”ÁÖÿÊ>kPöº†R¦¤ì{ÉCUÅÀlEaÿx© Ø`Ïèìä¾;b7w÷ýŸÿ‰ã!ó¸ÿÝwî?ÝÉ—®[µfÓ§»†Vv7¤QÈ'Œ´·/ìC’$Nܽ_ÒVЊÓw ´2]gm_›QŠ1[Ó84!ò5zK9T«u8°ó™fcæ+²®¼ç ¯˜!nþÎ}Ã"ï^308ü™á5ëÏÅ.JB#g’íÖ$ñ>í[’‘v‚´it(û•fó¨Ëó5fª 3•º â8Äу“åÉ?ÂøNFïs÷|þGMvœ¸åž{K9‘;?_êüô²«®^1œË§ÝZ"#U$ÞŸZýìÓcm±EšF~À¨zŒzC!y)PÌIAˆC‡צ'>úïÕ?Z®L?tÓgNÃIŒ;î{xi.ï¾ßuÜ+‡~ephéêΞnḠ~¤PiêLRDiñÅ /Ôˆc ŒQd^£! äH '”R¨Të8<111;}ø9?lþÐóð“H«=@_¼«ö(žºé‹‹GÜrçC4´$?¤±Å¸¤£«ó‚þ¾¾CË— :%9^‰FZ5‚Lž_`‚b‚V-Å ž Zkè™ry¦RžÝí5jÏûaø3ExNÕœƒQ£#Éb­¿ »äbëß|á„÷¾ ï êý3Üïܱý?ª•òÍ*–/Ö#7ìp é£0yýk–£àô Y ‘#Dì‚aœü½mS&øNã¾Mƒx¼« c¯ìǶúj¯DDz5Ÿ‹©°Ì÷µmWúJ.t³í|uÛw½À»QFågº},ögJXÕQ@3Ç~ *LÓFch%>w,ˆ<½ª[¢W¬\‹‹/ºåÞeŸ¤â’?¯7cHó:\Byb¬2¶÷]J…_î(¼^‚„‰ÿ&Ç·žòÝÃÜ6æuùXÀJäG{VÿÙ²áU7GŠœœ#wa£¬¼9úJ½n·›Î]: …9YT„ªª„#T5FbR"½{3nÜ8®½n,¹yyg+¿x ˜{¡.”€t`>0áÌÛ¿ÛÎß^y…V¬DFÈÏ˧mÛ¶¤¥¥¡( x¨(/ç®{ïáèá#lür©éi„ÃabªŠa𔕖QXxœ¢¢"}\?~<üözœ­>ïÓ€Êó"Ÿol“ÿœ3ÀsïÝw3xà@Vð=z0îºqŒ=Šœœ:têÈeC†`˜·Ýu‡ ‡Cx½Ürû®Ÿp#‡nÝ»1rÔHÆŽK®ÝXþþû èן¦M£äÔ©3ë4!^§N¿4}Ï€FÍðÎÛ è߯/Ÿ|´†¯¿ž‘ÃGpé¯.Åçó2èÒK:ü ¡—ô¾„˜ªRøÃqdI²LLËàð¡Ã$%%’Ó2‡h8ÌíSï")1‘ìì, Ĩ#™tã,{)ýûõã½wß=³nñºõý¥(VõQUU¦Ýûî¸ý62ü©Üs÷Tþ8gªªÒºm[nºõV¾Ûö-–' Oðæ?ÞÀ0Lþµàjƒµ¸\nœN%§JXþþÊËËymî|œ.»vìàøñB¦Üu'IÉɸxáÏÿÍM'’–ìçö[§ðÀ´iÄTµaóâu_·ŽË.¿œ…‹’‘™Ù°¾Ç€!À‰‹A€X üªî²²2®½êj8À__Ž¢(L¹óvíØÁÉâ“ü笙ÌzêiN:…×çµ]©q¦š¦!Ër=ø‰¡P-½ûôåžûïãñ‡aôUWáIð°pÁ»8_¬_O§®]øpõjZ´hÑ0õF` þ8ãÓÒœ.ðBCð@€q×\Ëáƒ6d(Ý{t'³E&;·o§ W/¾?r„­›63æš«±LË0O_¨i8dIÓ4~ô¼.ápÍucY±d)‘p„´ôt6µ‘+¯½šö:2ôò!>pq×\K hXï_Åë~Nù) |\wcZÆ]Ï'̨£PÕ(— ¹œëoÏ̧žF·¨Ëå")9™Êò $Yj2sI²Ÿý”fggSRR@$¦gA“n½™9Ͻ€eY]cͧŸ0úÊ+yÅrd©Q™WkšÊÛ1sæÌ¦žù€å@FÝÏ=;›Wÿþ*C/û5-ór¹åöÛøbíZöîÞC4ÁI’ÐuP(„,KMº ‘p„ñ“&жm;vîØawƒ³¼‡eQ]]]߃ŠB(⳯¥Oß¾L˜<‰­›6“•ÅGŸ®A‘\>dHCý7ýl ÏÕ~ t®»Ù²y3³gÍbÀ%}ÈÉÍ¥ººšh$BßþýÙ¿?ªª‚$aX&–’lÿ6›P!éddf „hò=Ã2‘2&F|ÊŒF£hš†?5…e‹—àt»ÉoÕŠþ—ôaö¬YlÙ¼¹!ŽÎq,g•¦ÈfÔÝèºÎc?‚Ïc»²;uäégf²bé2>_û>Ÿ×žÓMÃîïÍQËÀ¡ëXV3Ó˜v`át:Y¾d Á`€gž{–ŒÌ ’“’ðû™þÈ£èz£ŸÇÔl¦ÒÀô¼õ6;¾ý–¿¼ü2»váÓ×ðÞ‚8]NLÓÄ4.P-ËÖ JoàrººÎŸŸÿ[7oaÜø˜ýüólúz+ï¼½ !ž à®æàî®»‰F£¼8g¹¹¹D£Qy|ϘÎÞ={9q¼Y–1Ló‚´®ŸÆ…¥—$‰ã?Çérñâ__aॗrpÿ~Úåæóâœ9D£Ñ†¸î‰c;7& · }ݸ¼bù >D»¶mYðæ›<ø›û‹WæÏcÀ ¨ÑˆmÂç©¶ \7Ø”G4去§òèãÓùdõjºo;wì C‡ö:tËW¶bA{†Ÿ‰÷G!1aX“²„gçÍ7Þ 3=—ÓÍ}¿û-GáÅççУ '¦a"!cæÙ¬ëœb&––yº œ¯(ßlùš•K–Q^^ν÷O#%%…¿ÿm-Ò3yó7˜4y2&¶f˜Lt9XÝ$aU÷ɲt…eJ(Šƒ½{÷óõæ-téÔ‰ÚPW®¤GÏžø’|<°I–q:ñé< ¨011Lã‚ò‰=»w!Ë2¾$Gáàþý An^._oÞÂÞ½ûéÖ½+B˜¦5,¬[>ŸÇ®Ë¡QÐu½À0Œ<]ב$Xûé'ÄÔ(.—›«ÇŽ¥g¯^|¸b%B(Їì°[Ï´Î_ Ëöý-.,½iaš&Š¢ Ë2jTeû·ßqïý÷3rÌhœŠ“˜eí§Ÿ IöLÇÖh¡Ôˆ¡‹þ†0ˆi:jL°aÝ:ü~?²,±g×n¼^~¿Ó0.B<΄x¸(±=IB–$–,\ÄŠ¥Ëp»Ýøý~6¬[‡Ä4Ã0ºèô^º¦cƒÊò ìßORb™-Z×*ŸK—RQQ H†ñ³µn¼yY”••ƒ$ñÀ#“Ù¢‰¾DìßOey†0Ð5¡ë½š$@¢ƒwLŠ‹‹¨(+#1ч¦ÅèÞ£½ûôA×5LÓ°çÿŸ©öÀÄ0 B¡Z„б,ëó3$ EqðÝ7ßP^VJRReeaY&º®£ Ñ¡I !²4MÃ4­xä¶–p$Š?%…¯¾ÜÀÖÍ›Q¥I·µ¹jYš®c]hšÆä[§Ð";MÓ.8_I’Ù»{Â0iӮТ‰D8Y\ŒiZhš†!D‹& Ðt=EÓ5„”——£›G  ªÆ¸bÄpRÓÒˆÅbv¿m¦ Ë"$É„$)®2µB––FzzNEá‰?<ÉÈk®¢*DºÕ<5Î(+¦ª¤¦¥1pÐ œN''Nœ@åå!Ðt M×íN5š…Ð]NÅI P@VZŸ¯]ËÆ/7ЦmRRRˆD"Xfܽ8‡I"C&W”ãÂ&Y’XãOaüË/1rÌ¡;¾ý–g¦Þƒ³ºšn7èâœùÚb•e² {LMK'2{æLªª«¦‰5BÔ­\M kš ;D£Q’}‰ümþ|RÓRB ( ' 3ç/àõz‘eùô²õ,•eº†BÜVÒ8Š;Ò4Ñ»uC’%““ˆ•–ñìî]$›&–Ôtü 1~‹ÓÓ™Ÿ™…Ç0HIIá?þð{ˆª*YfÏîÝ<2ý1´˜†.ttM³™k’]—âWE¡6æÁi÷£ UUñ%&bápŸ×‹?%…DŸEq"aLì¹Í.Åmlõú˜Ñº ^ÓÄBB3 öy}L?r„î5ÕÕlܵ“u¹ù(ÍÁ/I’$–e-FM(Dá‰Ü~Ë­˜¦I$ÁãñàÈØKs]×ë, Q g hZ ¯× X”V•sÙ¥—qÍØkyãµ×8òýQ_".‡Ã2‰F#lÜðåeå¸'r¼²Bjjj¨©©AQÜ.n˃ÓåDQ<²\ß2ÿóç9tíÖ…‰ã®ç©YÏàöx¨ IIMëôz .Bl˜†=€i:±X 5#Ó0 QON]]\’“ŠŠJ6¬_O8F‘e’ESë ¨n’¡ë%`uS- Š_¢ÚÚZî?@nn.ý `ݺ/§[ªÎ à ŽDêIr86àÿù&ùù­{͵T”–±{ç.T5F(®_ñ9]ˆ¸“#Dü?³®@¤ ШM“!W ¥}‡lݲ˲ð%ùð§øQU!t@j4 i‡€aÂ0IJJ&3³UZfdÐà@>^½Ã4q:~Töi2╬5C· þk!­Z·aô¨QÔÖñ(.þòâÿÔ ‡Ïš_Ýõl€ô¾e±ýÛïðûýx¼TVW“™Ù‚¤¤dÔX Ë&±Ñnò™‹¡íº®£Åb¸\.Ú´k‡Wqq²¸˜Ù3ŸÁáPÈÍÉÁhæÊÍ0ML,-\D›¶m=j$áÚZœn$IÂápàp8eù¬Úк~J„aÛ2—¡Ã®àÓ5k(:YL‚â¤M»v¸\.´X¬n Ü~.¾ÑuÝÔu!;wÆår,1nüxnžr 1M‹öç˲00y{ÁÚ´mè‘# ׆ð8OOÃç°9R]UE~«|††¢(¸\.:u邈ûqlÛ¦9c ûÀ: tŒ„ÃtéÒÕžê„`ùÒ¥lûúkFŽŪ•Ž„‘‘PœÎ&+äQ\lúj#Ó~´üÅ>ÓcHH$ú6r¯Í{•²ª ò³r…Î]º ‡¶#v¤} Ó7²€ oˆéB_« ¨%=3“n¸Ýn¼ &Ý<™ÔÔTª#!òróhסC}¨úL‘$ Ó4ùë«ó¨ªªüEÀ–É€þÈÎΡ*\Kçιçþûð{q»\tëÙ“ôŒL¢jÔv„„¾vÂÄb óøQHL×Å",kØûw ¢ðûïÉuçðÜŸÃ}èa¦Þ}7ÏΜÉÁ£‡IP\gfS/‰N7ðSNó…‰f Ìü×ïbÞ¼¹<÷§p]:vIfÀ A]G×â!rIZtf?Z…®oBìB‰DÈËϧK÷î†Á·Naýºõ ¾ôRÆË¢eKñžü/-^ÅÅ_^y™[&Of̘+ùlígL¸qº¦Ó¥{wòòó‰D"!B캾éÌ<~DÀÔ»ïÔu]Ÿ§ëº®! ƒÞ}û‘Û’ádzøw™xÓ$ZåçÓ­C'4£9 —_FtÓ k»D#ÆÝp=«–/§  é-2éÓ¯?Â0¨Ã¡ëú¼©wßù£í±³N®Âïéº8®ë5ª’œ’BÿAƒy~ös|²jS&Nâ‡" ¢_P0óâHÌx¼ üuþ<®6‚UËW°à­·¸lÈP’ü~Ô¨Š® t]ü ñÞÙòhrwø//¾4Õ²¬€í¨$x<ìÙµƒ/>ý7éééTUUÑ¥ YYÙÌýû«xÎf9+CLÓ$bèõä6Ã4žÖ5Í^™¦wÝûºtëJ4Ååñ0÷åW(èÙ“yóæ#Iðô33¹yÊ"ñ ç…ŠišDu_~‰ÑcƘ˜È¯½N¢×Çü¿þ §ËªªtïÙ“&N¤¸ø$±¸ËkÓ4Ÿ~ò©'·«Œs`ÈÐ!W}¸º§ËéìVr'x6|ååe|÷Í6JKJ9z4ßmû–¼–-ydÆtžæYB ‡Ã&®> |úDˆ*4,ÓlYjøž¢(Hø< <ùô²ö£éܵ+™-²øô£)--eèðaLž2…={÷Ú›¡¦‹ªêÒgŸ›õðO‘ܬSbÙYÙÉÆOXÛ¾CûþYÙY¸]nRRSÈÍiÉÛÿü'+–,Áãñ`sÿñ:_­_Ͽ׬aÔ˜+Y¼p!±X MÓ¨­­Å´@UÓ:t(¥¥¥8p·Ë…_%%&âp8ÈÎÉfðàKùhÕ*^š7—Û·óù¯âóù¨ …˜pÓMüúŠ+X÷Å:"ч§â$Xüfñ’Å#KJJ?…­Yß ””–³²²n¸þºë×*N¥s«üVhšFEe%=ö(}úõåOÏΦo¿~$%'±ø½…Ü<åV²²³ÈËËcâÍ“y}Þ«älÅÉ“'1„ &PÃSïbÏÎ]XÂÀëM Á“@FfeeeÜvç,]ü>ãnÏ÷ßÏÜ—_áùÿ›Åï-Ä¡8xö©?˜”̪U«êß)…ªêªƒK—/½¡´´ô'ÁC3JJ’$•––-^²xò¦›/¬t2lÄ®XF‡.™ñÐ#†`ÓÆüóÿ¥[èšNbR"N”””~|:I‰IÄb1bšFÏ‚žÜ>u*.›ÇžøLÓ$ÉŸL˼\þüŸˆ©*‡àwÓgpõ¸±¼4.5ÁZ–,Y‚³Ç'Y’)..:°hñ¢É¥¥¥ER3—™ÍýbD’$)8µ|åòÇ«««Ÿ‹D#Àï÷sªø$™-2yìñǹlÈåüëíwزq#–i²më×|÷Í6ÒÒÓøô£ì€,cÖ·šÃ¤§§ …Yÿù¤øý¼>w>Bè”––‘àM`äUW2úª+1L‹w¼Gee%nÓ4q8©ªê)I’¼Ø±¿ŸìßÍ$I’±OWdy’$u¸¤ ×”áW ¿b؈atíÚ—ËÛí&=3€ýûö±úƒÙøåJNDè,ð§øQ…h8Âc¿‚{÷ñéÇãñxPÕÁ`Ù!£¸œäç·bðe¿¢ß€þ„#6¬ßÀ±ïár»pÈŠ˲رsÇß|»ím˲ŽE@) ZÖOÏÃÍ%@ÜØÇä[cMÉn‘5pÐÀAcG•>|ÄpZ·nÓå²c†X–I àØ±cìÛ·£‡Pt¼` @Ue%í;v¤6¤¢¢‚´ôtRSSÉm•Oë¶mÈm™‹,Ë;vŒo·}GiI N§d•d §â¤²ªªrë7[?(>Y¼`-Ä>6³šî|pIØVdnEQZth×~Ä ƒ]uõUî#GšžF4¥²²‚`°Ó4{_Ñ4G"Ôƒ˜–…SQ$‰`0Huu E……üðÔ—W`šN—Ýâ²,áp(¨j4vðС-{ì[«ëzÅnõñk- .6uÝÀ'! Û"¼€’àIhݦUë_÷éݧ÷¡Cz]Ò‹””T4=F :@eU%5UÕB‘0áÚ0ÁÚ Á@€pØ>d©ÇÝgGœ¬º¸ C–‘d™H$-,*Üqèðá/CáÐq@ "¼ÛšeþÍ&  JÒ⚊ý]  p8Μ™}Ú¶nÓ«sç.ùíÚ·“322p:èºN8¦¶¶–@ @0 ¢ë aïHH²T¿¹¢éºY¨9Q|òä΢“Eß©ªz 0°O~Öb6S× ¶5Íiýó"à ÜqÐÉ 4ûx­‚½ãKðxòRü)322Ú§§¥·ôûý©Þ„·ÃáÀ4ÍøRÕÞŽ«î¿˜‹V×Ö†NVUW­¬ª<\ aìQ]ƒ Åâ×£™¦A4 Á=&x°»€/®Þ¸z°-¢®ë8Ÿ¢() OŠ¢(>—ÓåSÅ$aaèB a„¢j4 iZ X‹ƒ6ã¿£qÄ5¿WãÏ›ÝòL@á¶ OuÇÿwÆÕOc5ÐFÙ6P‹Óf®c·¬† Tß« ž À:_ðð3>›kàiÉqu`›¿³* ® §IhÊK«#Æ 1u þ6°-Ãýáø¹N6 ¢XCBþ®»¯{·)©3y£‰«Ic ºPìvE.—£ ww¤³\Ϧç« å,Wûæg`ø?j`Ú‘‰qIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/database.png000066400000000000000000000172541217176075400234720ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsIDATxœí{ip\×uæwîÛº_£htX(‚ ‚ Hq‘(‹-‹Z,ïÊØN%•*OÍØU)—]SÏTâªT2ÊÄU“?ÖL’JÙ;±Ç¶dË’-Û’(Yc.¢DpwbGcénô†Þ_÷{ïÞùñº ”d3©š™WuñÖ¾ï~ßùî9çÞû@Ë‘6Ú10Æêçœs0‰C*•‚ßïG4E(B2™D0„aH§Óèèè€eY0 ¶mÃ4Íz±, \p.À9‡$ËI’ Ë2E†ª¨eŒ1†UÓÏ£¥ÅŸÏ‹ùù0:;: ¹\µ·mˆáýlì½ù¿{ûÿüK7à_zûžùÿÀ;štèР@ z½q+X°P=¶ÿ¹÷ÏE€ ÀvûWVVö†±Ý²Ì!ÐÀ#Ë’BŒAb œsÀ0- ‚sÁ…(B Ë$¶¬ªê¬Ûí¾¢»õ Æáò;Ý~—´8àñÉɉûL˺ǣëðz½hmí„ÇãÛí®‡¶»ldÛ¶§\.{J¥Rg.—Û—Éd>™ˆÇaÙvN×õq¯ø€K¿‹Fÿ.8à¯]»öaÎíP0Äàà Z[[!IÒo\™$IÐuº®#Ô¯ o<?²¼9Ïÿ™×ë{Àwü@ü·m<ýo$BG£Ñ/-.-~ÐãñàžÍ›ÑÙÙ "!~Û6mÜÐj½P(0;;‹Å¥%¸ÝîHo_ÿ7]n÷³ím±ß¸Þß‚€½©TêÏoÞ¼ù„ÏçÃŽáàœÃ¶¬ßÚo¾1Æ Ë2*• fggqëÖ-´ø[£[¶nýÏþ[wGÈ|¿uý&HLbÿþÊå+’^M»÷íÛ‡®Î.X– ›s§²;«×Óßh»CP ‚ª(¨T*ÇÂâFvï>´þqG[ÛÅ÷Síû% »\.óÔéSƒAìß¿DÔ`ñ*²šL×íD­­Î•ߦgTëBTë5B€ˆ ©"‘Μ9ƒ¾Â¶¡m_ ƒß|Ϫßù\î…7Þx}p÷ž=Ø28ˆŠa¬oÙ]7¾ÿ[o© á²,˰L ¯¿þ:š[ýØ¿ÿÞ?_{·*ß‹€ù|þÄ/~ù‹ÎÇ£«» årŒÈy)9¸h½É«‡ïuþÈS0+Ünõ:PZ»N)ã¶óFüïå6´þ$8Ï ±æ!dUAxnW®]ÿúôgnšFeoow¡±Æà\üÙ©“'±gt•r¶m¯ïïunÛ`êuJh|¾z*è½5 ÄíWÖHpî‹u×ÄmÇVɦÞ>\Çõë׆v mÿ7þzÝ]ë^ýß¿ýíÏîݳ·«bšhoo‡aUÙˆ­«^ªÃªu‰FnãgØ÷î.ù†¿"„s»Œ2¶oߎñ‹188øÇO<ùäß½ü³ŸÕUp»h÷î=¿ñÒEtwwÃ,›°l Ý&y"j8®_‹kÄÜîé}ƒ_ƒ¾N÷U ‹úõºì«$ÔÎ…LËD{{gß: Û²ûeY> àå:»víj|Wooïî—^|£ûöÁ¨”!Àëà×€­¾“”w'áýÑÐ(éu×AÞ¾¯ûƒ5‚4Mƒ®»±¸Æ'>ñÉãëYGÀÛæ®B±USQ©Tê}¹Ø)¯12ܘêT»Ì»… ëOêàP P|] ë”P}Æ´àiòbaaÛ¶mÛÝø¹·¯·ñ¼×²LØ– "˲@D`Ì^³òídКӣ¥¬w˜k~AÐûÔÀíßÀ 6‚5ðÕâ¤Ê€¢(Èf³…Ú;Zý­®T:e€ÌùºÙ¦&"‚eY°L«îè8ˆD] ¬±Ï7Q³t˜ú9¨®âø*¼÷±‰Û¢ÁzR¸¨]kj·ààÈf0MŠ,ƒsá€ëšQÒT6·Q,¡i.c¼ne"ß@Àzu ÷owŽB¬…Ä dP÷êÐhåZ¼wîñjPÍÄš*8qärYôtwCp^â\Ô­.ÏLO7¾;ª{thªŠÕt mí!gõ†1ÇòlÍÙmØDcd ˆ†¾¿.h@Oµôë÷k^½JÅ:K×HYë5ÐÒ¯3‰!™LâàÁƒX\ZLŠ…Úhò¥Kë¦Öæ’aô÷÷»æÃa´‡:`q $ŸÀ¹C1ªv…5©3"€œ®BD ê0UÇÊõÄa}’ônÉptæºÔw 4ª€yý.x• #—C.›Å¶­Ûðüž¿e™f}æF^XXl|s6g¾Ïõì³Ïb×®ÝÎ "DD ÄDM$À5ð5bDõXÀ¹ªš™ns$¬÷ Skëä ÜimT}‚\@pY‘1;=¶¶6„::péÒx”ˆHT+a.— ÅO$\ÃÃÃhñ·`rrŒ,Û†Å9lÎÁ¹ .lض nY°-–Åa ç…‚spÛ·E}ñ³f ^m(|\xCY»^{Ž [ðj}õzkïÎû-[€[ܲÁm BpX–…ËW.ãá‡F±T¯h`Uj$¼×´l_&›Å§>õ)<ûo ¿o’"×;hÕ˜ëÕü|£3D=stl¼Þa6ütÍkãˆÆ®Òà(@ŽªjÏr'8 [õžªªC¨½÷8€©éY mgŒI¼þä;v4¶§GU\¸t |øF÷Á©S'ñ¡Gò̆GNrÌHrÒd¶¡cl}Gfؘ­ïT'»ÇA$áì… µ/‚ @’¶IA<¾‚7®ãOÿäO‘Íæ±¸´„m[·v{<@XS“ Åßìóay)‚«×®â _øçÇÎÁív9ýUð’&¤xæÂêeÇOHÎ}I1 $10YrŠÄŠs$Ƥêó¬ú{rfªª‰UßÙXš¦¢T6ðË_üŸýÌgÑÝÓƒ«×¯CŽææf¯,Ë®ÝL’e4îÒ4o} ‹øÚ×¾†hdcçÎÁír1Ù_kL0sX^#¥¢Nb$‚Ì$"HlƒBÕû’²þ{&­]G9ï'‚¦i(‹øÉ„'žxGŽÁ‰¯#•Nƒ[ܺn7:V–N¥ÑPR>ŸÙÌ*Ü.7^xáED–#xæ™gYŽàWoü Šª@Uä5Ä€ªÅ%j“LrÀW ª“È!n,vgaT·¶TûmMYu"ªdTë“$‚®ëˆÅVðÃü=ö>ò‘â¹çžCÁ0°šJU×ÊÃ0Êu¾óo£V®\¹¼¤¹4îviÈdWÑÙÕ…½ð"Âóa|ýë]wãGÏÿ¹ln·ŒI«¢zcêr¯7œÖ€k´t‡„"UIr”U³¶T%™Iä”êsŠª@S5¼óöÛøùË?ÅçþõçðØñãxáÇ/ lqèn7¢‘eô÷÷cjj*\.—+uðääd4gFvíBtyŒzûúqòô[;7†¯~õ«xòÉ'ñÓ—^ęӧFÐ]®j¨säZ³Õ-ÎîPE]’T/õë Ç5ßRëfŽ’àn±h ßûî?!㙿ü+lêéÅK/ý  ¡Žfg¦ÑÜìæž\¸pq gÝ„ˆiš<OŠááh 09q ƒ[‡à‰ÅñßùG<öØqÜwø0¾ù­oáûßý'ìÚ½##» {<°lBðjât—¨Ð0¼n …õ ¨áøÎ„‡Á™ÿK‹K8}ú4VÓ)|üŸÀƒøNœxSS3ؼe ÅV¢Q$â+8öð1H’„T*eßÑÛ××V®TZ$I½à•W_Åìì4º{6ÁÓ쇪iøÆ³ÿ£{÷àK_ü" ‹xî¹âûÿã{èÀÈÈ:Be¹š4ñz˜[—!¢aÛ¶z^P {¨Ê_ˆÏçpóêU\G¹làèчðè£baañÏ€I2Ž<ðÒé4ñ‰8º:»°sçNDb1lêíío|ü±¼ñ¼›˜œÂž={15=pxós³(µ—pÏæÍØ3º¯½þξ3†§>ü¾üå/#•Jãĉ×ðæoÀæ›6mÂÀÀf„:;àõx!ÉêšZîÞ8IDkù±5ç*„@¥\F*Âüü<¦§¦‘N%ÑÞÞŽ§žz £££ˆÇãøî÷¾‡³gÏ¡-ÔŽ£÷A6›Åìì 8·áÒT:|²¢`nnÃ;¶hš¦¨}þó_h$à?üáýÑ37oNàØCGÁÇ /üårÙl>_ Fv ‰âÜØyzzºqï¾}Ý»^o¦gf066†‰‰ d³Y(ª ¿ß@ ¿¿^¯ºG‡"+ÕHÀÀm‚ e…BÙlÉd‰D¹lŒIèììÀ®Ý»02² Þ&/æææpîܦ¦§±šÉÂíÖqðàÀ•+ãðz½ lÛº GÅÕë7Åàqi ¿÷{Oï_]]]YVÖ¹ÕãÖ!Ç›¿>‰'Ÿx<ò^yå—hµ#‘Hâ­3§12²;vlÇÔä ÅÎ_¼ˆÉ©)tuuâžÍ›ñÔSOA×uäóy,//ca!ŒååÂóÈçó¨T*°m DŽ4M³¾äív»áóùjoǾÑQtww#‚1B"‘Ä­›·°°¸ˆTj%ÀËåÂààdVW^˜G[° mmAyà\½váÅ%èn n]—ªƒ® ñß~þóð¥¯|å+ý«_½ Ó·ñô§>H$Š×Nœ€¦iÈåóH§Shiö£T2^]Ekk+¼^/Ünt·^oZš›á÷;_vº\nH’ãÍmÛ†U_Yμ²ì|QÂ9‡Y1‘/Éf°šÎ ›Ë¡T*Á0Ê(–ŠX]Í O —ËÁßâsB®,£³³¥bÁ@Ç?†±±s˜ /BÓ4ø›}Z§?ôÈ#‡óù||üÛ¿ù;v,ÒÔÔEQÏ•ñÿðüÁü>>òÔSxíµWáóyÑZýL¶TÊÃ2+ˆF£ÎŒAÓT0I@(•+0 $’)ض £\çDN~P3 pÛÕ€¢Èpi8ÎTH² "B¥RÁj&ƒX,†t: ·Kc„P(¯Ï‹T2‰þ~<ðàüØy\¸t[1?;í[1ž‹ÅµD¨A ìÆáB¾PÀJ4‚öP;H’ñÜsÏxúé§ P.—ÑÛÛ‹-ƒ[±iS7<º ñx 3ÓS‡ÃH¦’(†3—ehš ]סi*€JÅB¡XB>_@>_D¡P„Q®À®>¯ë¸\n(ŠZŸœÍçóˆÆb˜™Axne£ˆî®††¶ahh;\.²™ :Œ#GÀ©“'qkb }ýýH$â`DØÔÛ‹‹/ÝB˜DĈˆd¬ \Y"™,DWb¥­[·zÆÇ/c!<‡îž^¥Þ|ó×èëÛ„?ù$&&&pnl Œ€ÍèÙÔ‹ÕtÉd+±(bѼ^/B¡B¡´µáóù »u*¬âŒå«bY†Ûí‚"Ë(òH§ÓXYYA4C*•‚Y©ÀåraSo‚ ¼^/Êå2VWS…BxâÉ'‘ËdðƒïÿÍþVø[(‹ˆ,/cßÞ½ðè„Ãá Ö×BnT€mYÆìì|~×Αàððœ>}ËK‹…:àóù095ƒ .ácû>óéOãÂ… ˜˜˜ˆÐÑÑ®î.”Š%d2¬fV±°°€ééi\š·Û EUë9¼\•µmÙ _Û0 †aÀ²ÌúWc¡ööª?ñA’e‹$“ ø¼>|è‘GÐÖÖ†W^yïœÃþ{@QÄqD–—hõchû2Ù b±Øj o€š$Û¶‹/^\:rä¾þ##XZŽ`nn¦YAWW6o¾×®_Çzæë8rÿ!<ùÄسgnML`rbù|.— Ý=Ýèíëuú½a T*U˜³RY®Ô“¤ÿ· 2EA0€Û톮ëp¹u¨ª " l”‘Ïç`™ÚÛÛpèÀ´¶¶âòøeüíßý=É~è!x½^LMM"N¡I×±sx§óÜÕ똙™^ªú>€× Ë2³,‹_»våÚµë7ï?|à^ìÛ7вQÂJ<©É X–%†wì £\Æ›'O‹k7nÒÁ{÷ãð¡Cþè¤R)ÌÎΈH$*ò¹cL‚Ë¥‰¦¦&Rdeý’Ô0çSŸ5¯Î5rÛ¶Q©TP*‘ÏeADhnnÆ®‘ôôô€ ×oâ¹çŒ©ép.pàÀ‚\¾<Žb±‹=Ý]F"™Âõë×S‘ååEY–U!„eÛ6É’$Q(",—ͲkW¯^ χ-E–å#÷¹\W¯\Ãjv7Q,ÄŽíÛQ)—±‹KãW137/z{z04´Û¶ attŒR‰Ç Äãqd²YQ,ä©bšõÞ×€º>é/.ˆ1‚ªªðx<èè@[0ˆæfçÓâx<Ž·ß~33sH¦Ó(‹Pýý}h páülÛFGG|Þ&8xùBsóa\¼pþr¹\NƒA©jp’<I’H’$Êår˜Ÿ››ºuëÆ&É{ÍJG|ܶ119îÁr$‚lfU´·µ‘a”…aðÁ‹t&‹ñË×0=3'Z[ýÔÞÖ†` À;F:™ª*·-›*¦I•J–e !œ¯„B’$rþ[DŠ¢€‘Í9ŠÅ’H§Ó´¸x©tªš°«¤b±ˆ––f@ظ|ù|Í-hõ·@UUÜÿ ¼}n ªËÅß9{öäÀÀ@¥³³’$‘eY$ïܹº®“¢(T,yKssö­3§_ݵ{ÏÈøå«’axìøqár¹póæM躎d2‰¹ù9.¸@¹l`e%"—KÄ*¦%ÉesyRY(ŠR qI–¡È2dY†Ä9ë›¶UfuIÎæ6ˆHX– Ë2aš*³ºîÀP©˜”N¯be%fÅFY¡M½}PÝ…ƒ‡Á(•ðòÏþÍ÷àÔÉÿyW:d‡B!†ù€mÛPUœsÑ××güú׿¾ôÖ™Óoûà‡î¿|å„ÍñèñGÑâ÷‹K/AUU‘L&@‘Éd±°†a”ȶ¹$‰4Uå’,AUÕêèP ŸÏ Ã0`š69!Йӭ-§JŠUQ„ǣå¹À#"‚esX¶“ ¬¬Ä‹FE6—ª¢P0ØŽ¶övx½^a[&Ú‚íØ·ËKKtòäiÛBH%ÅkW.ÿòرcé;wšº®ƒsŽr¹ š˜˜8ç²išš$Iz>Ÿo¹pá¦'NÞ=ºïs÷Ü3Ø™N&ð·àÈG„ÏçÃù çE,%A$LÓ¢Ìê*O$Èe²$47·ˆŽŽtuu"lƒÏç…ªj¢\©P¾P@¥l‚ó U÷Ç)ŠLºÛÅ=º‡„à(–JH§Ó´[¡åÈ2’‰Œ²An— @@Ax<p›ƒ1¢¡íCèííǙӧ°‰@s{~ù³Ÿþ¼³3ôÂûÑÓÓ#¢缤ëz…²Ù¬dY–ÄÓ¸…Þh4(b±qýú5‘Íå‰1IpÁQ,‘ͬŠt:-òù Á¡i.ÑÜì--~æó5ƒIŒj ²Œ9 /ˆ˜@Œ•ŠE'—X]E¡P ÎmÒ4š[šE«¿•¼>4U…e™àœ£«³ ÃÃ;X"‘ÄO~ò"ܺ›z{‘L%ñÎÙ3c]éñÇ¿<44´èr¹ÒòBƒˆ*$„`¶mK¶m«Dä""ç¼9wœzäG?:²nåŠåô ô¿ºuëÖŒŽOpâä‰ÛþÇWÿ˲ä}÷w2æBc™óÙèMJ) ÃðÉ„ö•¿tÍš5lùÅ3ÃÏlþÅΡ¡a„!ׯãñÀI aÀ¹û*)%†aø±x\»ž»lõE«yö¹gOÿòÙg_­/éììÄõ¼ï»ï¼+jÞìu‚øÕ Ï·ôγ ŒÔ;„6 C ! BF0„Â4 ñãþ˲²¶ãO&ÌbiztÇŽí vš¦Í ÛÓò–=ú(†eÙ–íÔ*¥òȫ۶Q.•»›¼ÿ\ÞFúW/<¯ ÃÀ0¢Ÿç“iDjÚ’ß÷¨×jHCBHK¢-VÔ©ÐJÛ¦9V«V*Žm³fÕªÜ3ÿô3ljÅXµjµaJ‰rÝœ4sO¡ ­µmcž_—–erÑš5‹ÞÜùÛŽ±Ñ *Õ Bká{^F ì¦H£ƒ¹Ö pªÏþê— Æesdt´€‚r¹$¦¦‹º\*öÙŽýÓ+×\¸Þt+Êwë¥Ñh­µÊÔ˵#oìHžÚ{3K²‰{+“㯺ý.2¦¾¨6üñé¸mǤRœ‡ h­u¦V®ÚùJâøî\Е¾óäÁÖ_ùé d,±¬ÊŸ?ñ"™”ƒü¤^ZLOŒâOO’¸€ÊÁwüÇoóëC#<øØsd’q 9Ÿ·-$±XŒÏèLŽ óO=ýr¹ìã+–­¬¾³çYa‹ÅFCÃ0ÐJ;Ê÷ÿ ³»kíÅK±ï†{99œQgÆ „¦£ƒðÑÛäJGX½¤¿Tà…‚Cqã¿£h-+Œø5?ΩiÃÄz›Žâ.îïDÔJ¼8.)mø÷”, BÏ´iæ©@æ³üáø?15š#fÛë«Õê3õz}xNg˜*´w¨2€5®=OM)P†²]š?~;î4ý;Ÿà¿Ý~×ÿñýì>ð[ßš€¥)¨Uæö7G~\ž<‹!g²G;µ"=oü=ÿ冋ذé~Þ;x”v‚þ¨òü6)‰eÖ>…[.øUÓF«y*#•R(¥ÐZ£µFJ)¡…ÖÕj…Z­ ­uà_f]ÁïæÄ)ÌTšKÖ^Ê/þþqF?úb0÷ù9—¯ÈÅL®\œæÂ®8¨9¼…™Ĉ§¸ìòËyæ'O0ôÁû\¸¼“ë—çXœ‹ß‚¯íû‹Ejµ:„ÂheŒ2—Í]®ï¢´€ÔZˆºë⻈6 ‡öÁv¼âs|ëÛpÍê<ú»#°æjpk N~¤ý)‹[–eÉÇÌ@/×i2xÕ&¾÷ÃsíªeüÍöý°æ:®í6¹ei†E) ê^𼯬5õZ ßwÑ¡µžš¯¦ÖÚö5:@­µòžïÍd ð}¨…iAÜ·†¿jÇ–_˱jœÄ“P©@Õ ´Ç”`µPUCðÁD•C“§° A*icI!Ò´)ÊÔV_ÏÇ«®æãJ,žÜ3ˆÀÇëH ´Æ”-4ce¿ÁÞuÝÐ¥h!´‘¹_{ÅUb×;oi³îÖUð%J©†;ÑZ£”?SÐ:@[ >»®—Çä7'Š —XÝcÑÓ»+ž 2|œ]§}w%¹´ÃÆõ/;¥:Ä-höÜž¦3k²,í`HÖ¤-É»e‹š[ƒLòý0z4,J; ÄÁ”C@Í×t9Cåcåò {_!¥FiPZá+_Ô}wF”¯³«”B«P`!Ð:ð HÀWHËä𿽂ƒ“Uj¾OÂ2xtdŠ=_ºš_™¤PS ';Ù56Å\ÊkÇ ª./mº˜‹ßÇCEˆÍÎÊ–gzâeWájŸ¡¢J“KØt$cL›6ÔÊIIÀŠqËÒ£ÓU {F+dl¸%1„ÄoÌ™Bû4B+M$k”è˜Ñ—`ÆU”N5œbÃŽëŠO¯É±"ã°ò¯ÿ\YrI|'ÉŸ<µ†K´`éR´¯¹gˇTßÂú«øÎËø£¿ÛŽ1+j.¹$MÉ©¢K>f²8e1QUØB0Q÷!‘„z9‡iƒíðþX Kkj VålF+¶)ÈØ~}*0•H¦ +F }DcÒ Ú|… 2?@€-Ù~ô ‡ÎÔ8öÐMlºy9ø@Õ%•ÉòÔ×ð·ÿézþâ‹×€Ô=Åå½ º®èå³+ó¼t¼0[ýCrµÆ6‹B¸j Rh\OA, ±d |:Ò¤î*â¶AÖ–¸ ‚’§pU´d´å !к‘Ä5W­L5Çs6f<´›j«¿ÿ_X×Ëãw¯bÓE]üÙOö°cR0<%©ùàû¡ù‡»Vqºèò_ÿùc¾ÿÚqHØs’bЂ¸as$#¥:¾Ö¬êpHZO©Àq&2Á$hÀs1„¦#fb 9T¨±(i“°äœ £Rv…Ðlhw³Ì ,‡õü0fJ¨ÔøÙó‡ùÕ‰3”þüþ,åàkø›Çˆ™¶0…àÖŸàã&À6!iÏ× )[âkÍp©NÞ1± Á©RþT’˜!)y.hÙ4³°8ãPu%×çêî$Ã¥5‹’6èæU¼ÆožÄÔ€Hm¸>×-Ïñ½›–³óXMÐÅc{‡¡\Çð˵–‰Š‹§àß¼x˜”m[|·æ{ÿˆÄ É@Êa‰ÐLÖ}¶+pz²Âk'¦ƒ~›sÀœÉØ&¶ÁHÅå±·Nm„‰“˜nAh_h)Ö^´F£ð¢TU vžœâ¯wžd cóyˆ]ûOƒcpÅ?îc eáÁlâ).}bÆ*éø:ðs!VšýceŽNU1„ÀUšéJ¢|Àí7­?Bž?z!4® 'ÈóC¡uÐF*\_ãi@ûAÜ&—k¯:HÆJ® Só¡äñëßÊ#à˜P÷Ù½gˆÝÍëÛäÀDl R‚ðÚt"ðÊ¥g•áE‹™ÓA“ÓÓ3Ï›sS"ÄÍð¨ù é)u;Ú ”f°T㯮_ÂÚO_†WqƒÄ(ˆ˜=/Íe–"ú³`J¬gÝ!ãy²ëùmšz™i/@VLò¿”œ©¹,D øM©®Xž²Ybi 8¿âÎÿoò5Ô}Ÿ…œÀ‚NÐWŠ©úŒñj5ÏÌv‹|¿™š­ÙíDûWËÁ©ÐGµ‡Ìp•Æ÷ý@{Ú «á“:H‚¢˜,›Ûë²¢Q¡yâ‰'xá…H¥R”ŠE¾ýïÐßßß”h5÷f˜3éñáÇٺõe:ÌÔÔ™L†Õ«Wsë­·²råʰ‘ i-Ð4êœhüFrÔö> AÏ$Í Ä\Šjô¾ïóÀ̺÷—_ûýýýºCc°á Àþýûùò—¿Ì®]»Úöqã7òä“O200€iš3³s¨yµ¡ýöZ ´ 4-üÞ€æ­,€û®®.|ßgrrÛ¶<šíoÙ²…{î¹€\.”æÂµI´[¯×yõÕWY¶l»wïæÒK/UÁn-ƒµnÆ1Ÿ3JëkÝ”?·DÛ0‚|å+_áç?ÿ9]]]X–5ïùfQ rpp{î¹˲Èårh­Àqjµ–e‘Ïçq‡ÑÑQn»í6†††Z0—´Öáæ,(Ïg¡0ÔÂóDT æ›@4‹RJâñ8–eQ(¸å–[øÑ~D>Ÿvm›œa+Ñý‡zf`llŒÏþóìÛ·ãdzmÛ6.¾øbFGGBÐÕÕÅÈÈßýîw@6ómÖTÀW~XÈŸñ›ïü°H[׫³fl.sÇqð}Ÿüà °mÛ6:;;[†ˆÔ´™‡eY(¥xöÙg&211Áµ×^ËæÍ›¹ä’Kèééᦛnâõ×_'›ÍR­V»<[¶l9+È Ÿ!H´ZªAÛ( ”šeÍŒÓé4ƒƒƒ¬[·Žññqb±]]]”J% à •JÍâØÌ#RO)%o¾ù&£áÆLôù¥/} €r¹ŒR ÇqH&“ÜtÓMlÞ¼¹¡u###³˜×_8ÝZù †æö> ZÍñ‘ê–J%ÆÇÇI&“˜¦ÉØØ—_~9÷Þ{/ßúÖ·f0×h­q]—¾¾>~øa …§Nbß¾}\vÙe /¥Ä²,âñø¬ñEQ§o*–Jx®‹w‹‚dþƒ-h® êPà ¡˜ €/|á <ýôÓìØ±ƒ¯ýë$“É0›r‰h°Åb‘žž¾úÕ¯Îê»^¯S(ð}¿q`Ïž=Äb±8ýýýÿçj€‚r©„ïùQ(×Zk_·@ªµˆPx_#ZD­5ÓÓÓ¬_¿žo~ó›Üzë­ ¶dÙŠG¹\¦R©4v¥ç‚Íþ–-[8pà aï¸#8ÜåyÞ¼ÜSSS a´¢…¦,t>šg¿ÓÓÓtwwóÚk¯ñ©O} 4!™L¶ K­4`!Š|D6›epp|Çq0 ƒb±ˆã8Üÿýø¾ß!$ããcX¦AXTZ+5844/‘Y`9”©£Yk|µZ%•JqõÕW399‰V ™L¶°…È4Mòù œZøáî—ž§¾µZz½>K]£{íhç°ý†3ßÙÙÉàà 6làèÑ£ôôô4¤«®ºŠo|ã”J¥†_j& ¸žÇØØ©Tí+4h¥uË”q>3åÏ”ËÏuöZ=ãûþYyD™aww7dãÆ ÓÓÓÀéÓ§éëëã™gžA)E±Xl™›¦Iar‚ééiÒÙld~J«ÖKÙy4ÉóhOy¿s³ÈVÂK)éîîfïÞ½lذB¡@oo/J)FGGéëëãµ×^c``€ááa<¯õjЉ;:x$“©¨®Ôù˜„Sk„Ðhuvõm6v÷[ñˆ"@__ï¾û.7nœ'üŠ+غu++V¬àÔ©Só€ŒRkÛ¶±L‹ïÊãzn¸ÀoQãÚ¦ÂaH APþüT³ÝÕNšÍ`îó½½½ìß¿–ð¾ï3::ÊÚµkyýõ×Yºt)'OžÄó¼Y¼šó…t&ÍèéQN ž¢¯wŽãDÕhE X° #Lá\…o€b–™›¯wtt022Âg>ó™†ð‘ûîºëرcù|žáááYç¢öÑÑ]ÇqH&’ìÙ½Û²éèÈcÛv”ÇhZÔ¥á¬yÀÌ鹘@óÀZÝ›»¶, Û¶¹ÿþû9qâ===!˜ššâÎ;ïäùçŸo´L"Ò×u©ÕjA-²‚êS©Ä{û÷ÓÛ7œRwœ¦í”Ö&° ái°sŽ ™À\¦iÒÕÕÅ£>ʶmÛèêêj¬ô,ËâŠ+®àÉ'Ÿddd¥õz¥‰D‚d2I?6l :—lÛ6oìÚEÝõéíí&“NaV¤mKYóˆÊg Í_ùç@«¸ óAŒfÿÌ™3<üðÃ8ÎÌÁg­5‰D‚Gy„rÓ^?5ƒåË—ÓÓÓÃúõë¹ãŽ;Îàí·Þ¦··—L6KpRUFzß¶8¿°ˆp+¹)jGs3½¹µ„œ€T*ÅsÏ=ÇÉ“'éììl´À<Òé4±X ¥,Y²„eË–ÑßßOoo/kÖ¬ œ\Hoÿîw”ËeV¬¼€T&‹‹cHÙXË´£… ØkŒ¼îÙðúúúèïï'N7ú~ó7¨V«,_qéL†˜,›%Ì:ØÙ€èŒà<¡„F5E‚¶XiÍ™3g¸ù曹ûî»1M³¡¥R©!0U(xä‘GˆÇãH)ÉL´¶ÂWrÎvØù·ßæ]o°dñºººI¥S Ÿp.o¬˜Ñ"FDg‚Ä|!ÏÅ (NxžGµZm¬ïµÖöÍiUäèšß‰h¾¢²{Dƒ'yùå—8=|š%Ké_²„L.KÌv0Â"Šà4`òÌÕ϶§¢˜)D¸Õe‚ç²Úæés)rŒ†a‹Å‚w„ÂË4MLÓÄqœY/FLMMñʶ­¼ÿÞû$RV¬\Eߢ>r¤’I,ÇnÚ vÑ`Ö[A%H‡kg-Œàí u6.Ÿ¢T*Õ˜y'|)ÍÚÌ(‹lß¾½{ÞEýKC§×A&›%K³m s¦*­ÿ,“a6‡LµhÓ0ˆÅÒhØUTr:Ÿ3à-õ&L±óù<Ùl¶¥š×k5ŽŸ8λ»wsðàa„”ôõöÓÕÓM>—#Í‘HƉÅâØ¦aH!1x~}aü­Ãa­5x€N$Äbq‡£^¯á¹^P+h‚ Iáf~hÚzÐsï‡$´Æ‰Ç1 #ˆZãúA(-‹Tj5´Ò¤Ri.¹d-ä²9Òé4ñd‚D,Žm‚·ò“±D,<&·^S OB)T"çøñcTŠeÆ'Ç©Õj¸®Gsq¥Ù· t¸©‚~Z¢¥¢±ï%é*Ü2× eP±M“x}ý§(•ËÑ U¦‰cYX¶eÙØvô²l Ëje&–iaZ&¦iaÃ0o’¨F˜ôñ<åyÔ=åyxž‹çù¸ž‡ïyÔ]—º[ǯ»Ôë.õzzÝ¥V«ÎÚ*WJáÄ⤳Yþ÷ãÿ`šsÈz”…H!6efÂâÙ/}Š ¦*„F-¤ÔB-¥\ðB2hòù=¯÷€M@ïÜe¹Öº¥Z˜À"`9Ì.&œO8_jç±ô9<3—"W<Œ'´žÿÚËBÂH¢Yœ{ã÷|a¹E¥­Vt¶ì,k ÑæÐ|ú$i¶êÎIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/disksfilesystems.png000066400000000000000000000114301217176075400253210ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞßIDATxœí[kŒT×}ÿÝçÜ;÷ÞÙ™ÙÙv ì»^Ã.˜°°à†µ’ª8re;rå8ɇª­óÁùP©¥®ú!oµ¦R"ÙµKÜ*•KJì¸DNˆ¡&æw)o{ Ë>Øevvž÷}o?À¹½3ì,` ¶¥þ¥£™¹sÎÿwþïs†züñÇÑŒÇA{{;Ç˲¸pᆇ‡ñÓŸþÇŽÉ'044„±±1lݺårÕjÇ¡X,BÓ4Ð4 Y–qñâEhš˲`Û6 Àªª iÁ`@<ÏC¤R)¨ª Š¢Íf‘ÏçAQB¡4MC[[N:š¦ñ“Ÿü©T kÖ¬$Ie†a`zz𦢍:¾~üã{ßé¦Üß%r]÷cÝ»[ÄÞí\×…ëºp§î»mÛ°mÛûMîûŸ»tWp4MömX–E†‘0 #mYV»®ë²ªª"Ã0.MÓªëºs®ëN0 3ƲlÁÄÝã€L’¬¢eY0Ms€m4Mo^µjUO4] … ( AË^Þ²,hš†J¥‚r¹¬ÎÎÎŽ”Ëåc†aü–a˜ß8Ž3MÀü¤éŽð¯Òõ•Þá8Î72™Ì—3™Œ˜N§‰Dn§KÀJ×uWæóù§&&&0>>~Þ²¬eæeÇqf>I‰¸#ˆîZ–%š¦ù¬(ŠßîîîŽ.]ºŠ¢Ô=ë—…ˆXlŠ¢‹Å‹ÅÐ×××U(¾wñâÅïMNN¾iÛöß9ŽsüVû\ˆnÿj›¦ ]×ÿ~ûöí{V¬XT*žçÀ3pw2A?‘H‘H]]]_ºxñâ—òùüÛ¶mÿ€swb+n¿µ¶, º®ïzöÙg_^¾|yk2™Ïóp†axÏ’dÛ6  §§åry{8>ûÎ;ïü³®ëeYÖÝ€0š¦ýû“O>ùD<G4…ëºwñFr zzzL&ÿ²··÷Ož{î¹!˲NÞîø7À¿òªª¶¿õÖ[G$IêŒÇã$ ù{ÄPÇq Ë2z{{Ó{÷îÞ·oߟٶýÊíÌç¦~…¬¼¦i]/¼ðÂÏó–ey¡-é^5HÙ¶ žç‘H$ðôÓOÿÌ0Œ¿!Rr+ÔTüÆÎ0ŒåßùÎwN«ªÊd2°,[gä>M"†’ã8´µµa×®]ÿpðàAÞuÝ=·2¿Uລo}æ™gNæóyfùòåó·ƒò½ š¦ÁqÚÛÛ±~ýú¿=|øðŒã8ÿìºî ÉPÝ{E¡±óøæ7¿y¸P(©T Ç‘`çž‹üͱE¢("£¯¯o¯mÛ[ˆ$7òGˆ-‹uˆØ÷ôô ··÷ ÃèŽD"Eñ3¹ò~²m Ã@–e´µµ¡¿¿ÿ­C‡…išÖçcXÿE¢3×í{à¾=99‰ÎÎN€iš÷†“; ÂC,C>Ÿººº^9uêÔŸŽŽŽ‚¦é%`¾lÛÆ#<ò/}ôºººîyŠz'D’&š¦±hÑ"”ËåGOž<ùOŽÌ Ã0ÞÂä}÷Ý÷Çq_¢(¸–±}^ˆ€ ( ‚Á Ö¬Yóüèèhÿ|‘%!&EQÞêþõåË—ÑÝÝ]çã?ODÓ4\×E,C.—[‡û†9Ú˜R³,Ë‚¢(O?†YÜÒÒò°ªª®ë~®VŸmÛ i’$AE¬X±âÏ?øàƒ£7HÀ3Ï<š¦Á²,öìÙƒuëÖ}9ŸÏ#‹yîåó¶ú„ˆÍRápxw>Ÿ²,[ó?ÆቋmÛH¥RÛ‹Å"R©T]­îóFþxFQð<Vå étúÿsu^À0Œ Ã0}¤ þY³þ EtDxê̲,xž÷JïÁ`pƒmÛõLMMy* Â"˲:A¨K8îù­ò|Ì‘k„!âÞüŒ’~Çiš0M†a V«AUU¨ªŠ¹¹9LNN‚a˜ž±±±º1Ø\.ç¡EÓt¬V«I±X †a€a˜»êHüîgŒ¨#àdSš¦yŒU«UT«UT*T«UÔj5hšUUa†—©AÇq)]×tâX–…eYÁ¹¹9d³YT*T*ˆ¢èUooGüå0î_MÇqËå¼+•J(—Ë(—Ëc„âŽMÓô¤ÒuÝÀcYÇ!Ü -333!˲‚uøÑ¦(ŠSU®ëzâT«Õ¼‰>‘çoÀu·ZÇ4kQqæÌüèG?B Ã0u¦éºOŽã A¨c˜Ìƒ¨,Ùr3MÓÖ4ÍÒ4ͪV«–aÇqާÓi @Á€ì]—Ê0 ¯3Ò¹¦iÞ>Ïóày Ãx«êƒ0β¬ÇaÜßlÛÆòåË‘L&177‡X,ŽãÀ²,QÇ:ÝÖu¥RɱmÛ2 ÃÒ4ͨÕjšªªfµZUu]W ÃÐt]W]×Õ(ŠÒ˜ÇY¢(" jmmmï¦R)>b9ŽóÛŠaoÕ I‘«Õª§¿þ û‚©˜nüí8"‘¶lÙ‚—^zI+‹&˶mò,]×uÍ0 Ͳ,U×uÍq € À`YÖ V0t‰+Ë2§( ‰DDI’¤p8SEƒŠ¢(R0 9rä¿ÓéôL6 V«A’¤=€eY^!xžG € žtøÅØÑ]Ó4±aÃìÛ·oüìÙ³‡ZZZ,QQ‡©ÖÖVN–e.¢Ñ¨$B$J@@ R08Ž“xžç†aüÅ¿ïèº.xžÇøøx¦P(ÔñáÅdRáp³³³ˆÅb·»® –e½@J×uضíIÇqu  \×…¦i‡Ãؽ{w¢£££·½½]–®˲AŽãxŠ¢(â ®—ã¡it]÷ ¤iš î#`ŠÅâ’Ó§OÓÀ´…$€aày>*Š¢  ä@ü0Ã0Ð4ÍL¥Rî»ï¾KU«Õ \#5ê?iÖ¼qõý¢êº.R©Ο?x<MÓn0ÂÔ?d!®óÇq8Y–yÿ=ZE\·’(—ËZ0,ɲŒ\.çe‚T†óó1: ׈„,Z´–e¡\.ß’çˆamÖOjš5UUÁó¼Ä²,W€,ËeŠ¢PŽãT …Âtoo/.]º4o žØ…f ÍÇü|¡¬ÿ7ÏóˆÇ㘜œôb‚Æ>ßo¼OlÐ|ÍqT*H’$Ù¶ÍÔL&‘L&‘J¥œP(T¾øÅ/~ù|¥Réý#…Ç…V¼³ó}×Ük&“A>ŸŸ7º»•FÔ¡Y+‹ƒ¬mÛõ@v]£Ñ(ÒétõøÃ©t:%K–`ddÄ› _ךéõ­\o¨A4Ã0˜››óÔ`¡8¢˜ó©‚mÛ(—ˈD"¶mÛuÆ‚N$ R°téRmllìä¹sç̯~õ«˜˜˜ÀÜÜ\]ÝÝ62¸ÐdjÀµX=‘HàÊ•+^¤9_0µ˜$ykÿjµJ¶Ð ®ëÖYu:¢¥¥‚ `Íš5ª¢(#¯¾úê‰twwãܹsž+º“7‹þj–e¡££¥R –e-p3 ß Ã¨s¡333ˆF£Ðu}R£¿Ÿ_¹r¥ÑÓÓsåí·ßþíøø8¾þõ¯CÓ4ŒßòJ.tÜ÷";½‚ `vvÖË@ß½•qIþ@ÔvffÙl£££ÆãñzjµªÕ*TUE6›Åºuëò Ã{á…Nuwwã+_ù ._¾ŒJ¥R'–þA'ØŒšÝ#ñ€ã8H$˜žžö\l3çcÜÿ›„À…B<ÏcÑ¢E=½dÉ’ºdˆ–$É«œ@eíÚµ~õ«_ýòرcxôÑG±~ýzLOOÃ0Œ¦¡æBŒ72ßìY˲ÐÖÖæÕnw?$lÇÆ122rÞqœ‘û^;éîî¶&’Éä‘ï~÷»t]ÇSO=…eË–¡T*ÝrQ¤q¢þÉ|Üãy²,#ŸÏ{jðq)—ËA–elܸ¿þõ¯.[¶ìÊý÷ß¿0Ça`` ¼eË–Ó¿üÁ~0ÒÖÖ†Gyž1¼Y©¬‘±Fæç{žx›x<î©A³>o6f­VÃÕ«WñøããüãôÔÔÔ¡Õ«WÏd³Ùºæ=!’ÉdœM›6MÝ¿ÿ¼òÊ+s‰D[·nE,óV €·oÐ81¥i>@šIeY‡ÃÐuº®ÏËx3pÉx$ðIJeËðÒK/í_µjÕÙ²$Iuól*c<ð€^©T.”J¥wöîÝâyþé;wJ011á44MÙ[ !ic=°ÙŠÏGŽã€çy(Š‚™™´··{¹Ç|@Oâÿ†®ëèëëÃ×¾ö5ìÙ³ç8MÓooذa¬¯¯ï†ü¾)@Àݶm[Ñ4Ía˲Äþð‡¬aO ÉŽãx[4õ'y9©úS`šþ¿öBD X[[FGG‘H$ê6h›ÿÀ9·ÔÝÝ;wâç?ÿùÌ‘#G^Ûµk×ÿlÞ¼¹@ ý- ø›7oÎÛ¶}Œ¦iêùçŸ7¦¦¦{â‰'âŽã T*AUUÄb1Äãq¨ªŠB¡€jµ ˲¼úƒ€ÐÌ’ûWT’$躎Z­š¦o8ˆåÏQˆJªªŠd2‰õë×ãÀê‹/¾ø³íÛ·ÿ×Ã?|yÅŠóVw˜çž{nÁáyÞM$ª¢(E–ekû÷ïŸ:sæL¤¯¯/ÞÒÒ‚¹¹9‹Eï|N2™Dkk+Apcl¾Ð¸ŒÓ¶mÔj5„Ãaj5©:†–eÑÚÚ EQ@Ó4’É$V®\‰hßÿþ÷_Þ¸qã;woݺµØŒ?ê6jýô‰'¢¿ÿýï{ÞxãÕ•Jå¡Ç{lûƒ>¨T«U ‚€T*…Å‹# y/’ R]&@š#Éó¯ïN! " çy¼ùæ›H¥RÈår^b#Âá0AðvB¡Z[[ñ‹_ü¢°oß¾Û´iÓÛCCCGz衜(ŠMÝÕíôÈȈ|ìØ±¥ì~ï½÷Vg2™‡†††¾°lÙ2FUUï¯-­­­H§ÓH§Óu`ÜÕj5¼ñÆH¥RÞ¨ÖÖVˆ¢ˆJ¥‚«W¯z^Ã4M¼øâ‹ç:ôêŽ;Þ<¹aÆiEQÜÛ»]¥R‰?þ|û‘#G²‡ÎŽŒŒô¦R©M›6­Êf³"EQžjضëU^Ä+ Õý_€lf”J%”J%ÌÍÍ¡Z­Âq¨ªŠÎÎNìÞ½š¦áêÕ«˜ššB¥R …B8yò¤ýòË/ÿF×õ·†††Þß¶mÛ™¾¾¾Y–eoº§÷± ïær9ùÔ©S‹ÞÿýÅ'NœHŒŒ,¡7›ÍÞŸÍf3Ñh”¦iÕjÕcŽˆ¬ªªž#GY$IB(òš  ( ªªb``¹\µZ Á`ápÓÓÓxýõ×O?~ü?W­Zu|ÇŽç6nÜøQ&“)SuKšw!&—Ë).\h={ölüôéÓ‹>øàƒäììl†a˜%---K"‘H" Exžˆ!#™4}í_edëÍu]¨ªZ)•JWGFF¦ï_»v­¬iZZZ Ë2¦§§ñ»ßýîãG¾‹ÅŽnݺõƒ>x©··wR’$ýæSþd D—ËåàèèhèÒ¥K‘ÑÑÑèøøxxbb"2;;­T*Ó4£¶m+4MK®ë ŽãpE9EYE©®ë–iš. ‚0‡ º®Ç }ë[ßÚeš&.]º¤=zôì‡~ø^kkëpÿGýýýc½½½“Éd²_½ÿÓÀë×` ¹\.8==ÌårÁB¡,‹ÁJ¥ÂéºÐ4µm›¦(ÊaÆ –$Iº,Ëz4U‰D-ŸÏ3¯¿þú:Q¿166–«V«§/^üa__ßøêÕ«§V®\9•J¥J>öÆ»@]ÿ×[­V™Z­ÆU*¶V«1†aЦiÒAlI’lI’,I’Lžç­+W®°¯½öÚâ3gÎ, …Blww÷lWW×L6›-Äãñ2î€qo‚Ÿ•ã/ÍhrrR‰¶··›©Tª&I’à;¶ò™€$7¸–µÞ•c*ŸiîÝóÿÖèÿø´'ðiÓÿ%&Öð ¼7”IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/disksfilesystemsdeleted.png000066400000000000000000000117311217176075400266540ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜÒ@gÆYIDATxÚí›{tTÕ½Ç?ûÌ™÷0$CHB !‚ PÄx- Ôzk[¥-¢kYmEDèãZWk}]«.Qn)Šm}wÝò°õqµ¢¨´E±i ˆ‚¼BÂc’ÇdÞ³ï{Næ$¼,ÞÞ½Ö^çÌœ3çìß÷÷ýýöï÷Û{Ä·¾õ-Ž× à°°Ã0Ðu;w²eËüq6mÚć~ÈŒ3¨¯¯gòäÉttt‰D°Ûí´··ÇÑ4 ŸÏÇÞ½{‰Çã¤Ói2™ Éd’X,†¦ix<œN'‡—Ë…Ó餬¬ŒX,†‚räÈ„øý~âñ8½{÷fÛ¶mhšÆ²eË(++cÔ¨Qx½^|>Éd’`0H<GÑE®Gy¤ó\ãsnRÊ3ºv®šþy,¥Ä0Œ.ç™L†L&ÓùÙ¼n½ï €ahšF&“á®… E3”„¡o ÛÀ× nÈÄò Í  þW÷ßßjâ\‚¡Ÿmj›ZL§ÓÌ¿ï¾1@µ&Q]]Ù{ðàþ”–Bi)øýàtª' Á¡Cpà@ìg|°[¬^½‰Hätý­·–. š`žwXµ”Éd˜½lÙìö[¨¨˜ÎÒ¥nƇNç‘nÃ0Œaò“On55\µråöí{ZºÝO­¹ýö¦³Éý³RÜ0 îX´È] þ¸‹9sTWCII÷›Õ1•:ñCíö¬{Ö••PY 7Þ8˜={±ví¢©/¾øºìèøùûsçÖXY÷¹`Õv*•bÎCÝ/æÌ¹—éÓá²ËµMZ›BŸÎ3™Ü¹9}i €¸õV8tèjñî»WOX³æí «Wßñä]w}òY|…~:‚›O§Óܾpá5ÿ9gÎSÌŸß‹±cÁëU‡B]5~¶Z"¡ŽyypÝu ^É€ßúàƒ¿|Ìé¼3NŸ{Ìæßó›ijÏ~[†¨¨€t"‘s#x÷–N«£ß_ÿ:rôè¹ÛW®¼ög>8#=rdíé‚ ŸŽæ/~ë­Â5K–lÅÅ䈈‚ˆFOͶÏv³Û!FÃ7ö}°¢bKý¬Y³_X¸ð¹Ó1íT5òeƒ^µª^øý¨ªBôèñ8$“ªKùùv󽉸ÝÈÑ£é»bųwßsÏOÓ`¡v*Înæòå~iÕªds³CŽ.—rVéô?¿g2É <ä!ˆå˼cÑ¢Ì@êdÍ6|øð˜[šï=÷\¯‰O?ý){÷:˜™T”ϾüŸÚM a·ƒÏ……—[¸°å­K.Ù˜ÉdŽJ†¦L™’óÝ/ZiŸJ¥÷è£ëÙµËEu5Âçƒd™Lr>6árA¯^0b⦛þëÎ_ü¢öáyóþ,¥Ã€x<'TK 45!ÛÛpè2$ÝÞN#Жí! $#ìø”Mzå'Ð9¥éº®wO¨µ¿ËÁ B1ÈQêô †¹r˜Z“NgN›†[·B(¤4U_¯*Ãõõ4‡hV˜8¶Fö³#kÇZöÜ¡%Ïòñ}þ(xº` u°·eÑ"Q½±Q•»ü~u4iw²„È0”Y¥Ý®4mÒ;@®^Ím/¿ŒpY„qeì²áËŽ+`ùNËj˜,(é¬öaÈ„ ÝéFHG!œ„šñàZ;0×Ît582m*‘@šZloW]ÓT:Ü£GŽ²Ý«A¦ànwNxS릭뺪æ\}5ã^~™=@eV`JEzV¸dVë! Œ¤&ÝÉfˆ·Aªbm‹B<±4Äu¥å”Ò â•ðþ8‹öt»Ýnõˆæf(/WSH÷\!‡¦&Ðu„Ç£„t:3Lª›ŸMÍ›”7 iŠAƒqsß¾\__o€ÎÖ˜!ˆ‡!…Xâ†Â!$]òAºŒ<  ô°—€£?¸‹ÁÛ (-õôee^QP×ôüóÿXñË_6±`fHš¦á0éߨˆ,,èùõ¯5ž|Òèâ…Ì}ì1±„¨ªbï{ïÑ?=±£3mÝá‡C™ƒ×›3 §S ›É¨ô4•R¾ ;@i e³a¿ürãÇ_"¾ô%%`,¦Ì/Gd…$SZM$”sŽÇá°ºv k†2ÂåOC]|€–uZ!H1v¬l|ï=qA0˜£ëqWñÜJû‡º×nWç¦ðÝ 9ƒ˜1º¦)šŽ¯¼#G"[[;ë|ÂÌ@­>$‘è4+ér!’Iȉ@p:¡ieRŽ.äp»Ý¸Ýn(,¤â„ŠùñÇj ±ØÑ=K¹Níëz'µ;¡éM0L? ë‡CÕïňª*5ë<¨˜”}–t:Õlc‚i³åÀ51A ‡=V³77㯺5šÏçÃçóAq±HC˜={‚ý&L`c,¦—Juí¦V¬ƒÓuw›Úw8ÀfË oÚ}°.hšò_ŒØ¸|>¨@s&±<[˜!±9 »ÕÒec#àƒ­ ¥¥¥”––²iþ|£ :äï~·—Ÿü„Oyà@Nh³§RG7ݵoþ¬Â[…¶R6™T¥·;ºÆþÖ©Ô*°Å¤:r:»Ž³[Oƒ€žî΀üü|òóó Œ‡È“±Ø6&L øGSSgµUZ¼m§­;ÊŽ­4ÍjÈ*¨0µnÆ6›ê&# 1hò)ûö)›µNæ;¬ÀYÏÍw2Vcµt  “„.51­¤¤“ÿñ÷¡–W^I•=ü0êꔆ¢QE3sWG.›P€˜©¨©±ì5aÔ¬)|wl6=jjÔlâruõ-&3Lðm6õl“v{çz¡9ƒ˜Kw²¹™8ÐZ\ô¬†èÙ³'.— Û¬Y±bØÝ1{ö‡bÁ®þjÊI¥rÇÌÞ¬‘ù½Å ºPÞ*|wÐ4eZUUˆ†x·ÈQ:¹g ¡„5¯[÷è:¢£‰¨`-™d_,FÐór¹”ú‰µF¶ûç?O~ýÞaÃú¬ZEP‹!­·Ùº†¸V,‚¥ý5’IèÝÀ§Ÿ*§Úýþc™€ ‚å(”aÉ–É·¶+®`=ìÖ€h4J$!‹1pà@Æ\zélJLœ¸¯}›««ù Ћ)[6ï> ë NT¦:Éî1z4rË–ÎÙBtgÑñ@±˜ °Ôöf3IFb|TÝ-Ò¼^/^¯WÅsç†o߃WåÒ¥ðâ‹Ì¶e£©c†š¦ø,ÂgMÊJUì8Þ*Ô‰@¶cf—WUÁš5; Øí˜6-y•¡Ôõ×g*¾ò•—†gæÍ{“pÖ¯g¢ÛM¸½ýÌ ¤æïNV]r»¡¸¸«œaÛüǰü£Ö}‰n81v»±`AÇ÷z÷þh#¼éÛw7]„øýïé1hò²º®ÂÔ“,”JkiËÁ,´+·0cŽáѵµÇàDï´p›Uˆ+,€å˃ÿ€¿N)-mŠ\w<ù‰É“ ~üニ`ã-ðß\uUUUðÀÈÁƒ‘ÚìhÒ6>z‹Œ9PkBe²ÀZm6»y-‘€­­¹ WÝë’Ç:7ŸL’ö·õëÓ¦ñ³wÞyù;ð±\° ÃëõvµÌûî»ïØùþ!W:¹hÆôÜC‡bߨ¼y·Ýæ½{«D×ååÊ&Ãá\,`BÙéJX¥¹-.ÝWr¬ß;ª6˜H¨ý†‘H©¦âT*·3$‡TJ¥ÉÑhgŽÒ‰0¬´Ö®e륗Ö| /|§ªjKüñÇÃön¾ê¸àväI‰Â––ŽA55©;ëêÂß|ÿý‹ä¬Y‘­K¯Wí+*Ê%™ ÂŒ²ŽO˜©³Y$=Q״΂‰Ü¸1f ´µåV§“I%|*¥Î#•Çbàñ@8ŒgäHäêÕˆ3šîniùí#ðWñÄìÆ§·KÌí–ÜsÏ‘Qñø¦Ÿ>ý´øÆæÍÉUcÇÎäõ׋H§ ÈæfÄàÁ0|8´´ ëê‡+­¸ÝH·[•× CM£'ŠL:§ÓЧ"B67çî·nÍɆ¹"Aúýj%¸¹YM£óæÁ‚±™»v=»Þ îçškŽé<Ä)m'kh°ñè£EG/yŒý\;}áÂôí Û·«{ªª`äHUkiýûáàAP,¦”oFoÖÆY}‡Çƒ¨©QŽpôhØ·O‹Ak+2U€)ó …@u5âG?ŠÏ\»ö·?†×FÍŸ¿‘Å‹·´wÊ C“O<à* G„+ïÛ÷Jy÷Ý=ÄáÃj€~?Œ“&AYYî·Ù  )pÌz)´™¹\à÷# eeêywÜ¡ž¹eK.»ËËC^p"?_­'´´¨÷]x!\}ëÌž¿Þ¾øûßßÈ}÷5RXh|v² ð§?ùäòåÔ¼úê¥0r"\ñݪªÑL›f£­ >þXixð`˜0Au+§Ó𛑷ßæBm¯^PQ ÈíÛ!™DôïÑ(Íž½c!¬| Þï½`A-óç)+;aà"Îh§õþýùÒK…bñâ+êê¾#ÆÁe·öì9œ©SÝbÿ~Ø¿™L"zö„þý(¥¥Ð·¯Úóëñäª9--ÐР²Ï}û ¹YÙ{[›Ú£ôÌ3êž;[¶ T@”•!_x!³èÕWß Ãåçÿ‡Ú.fÏnÁë=éšž8ã­æ†!dm­O¬\Y,Ÿzªü¥`°ï›paF|†^îpôcà@ ]G66bƒ4-Ù ¥-{Ô€2µpAaö\/*B”–BÏžjêlkƒùó•¿ijRISy9bÛ6þö«_}ô¬¹j¾1sæAJKOk/8kÿ¾0 ƒ=¬[ççÏÎgݺÀ‘]»ò6Bþ.4B~qèᯮ$Ø50tHk3 C‡P´”Ck’>˜qóœ9×úu‰×êê>~þV[î„=bΜz¾ý탌BÓN{[œõ?$†töïwQ[ëaëVܺÕ#öîõȺ:ííà ž-{>HûÝî„(,L0p`Œ±c£rçNÛK/¾8¦nYͰm<ìúš×Û nºé03gæ²ËBhÚoUçôïi È¡C6yäˆ]46ê45ÙèèÐd4ªˆ¼<¿?CQQ†¢¢4)üþ´¬©ÑÅÌ™åß³§è½'Lhaúô&9eJ«9²ã³þùp6Ú† .Þ~;@eeбc£ôéGÓÎÚ¦¥ó€L&ƒÍfSþå ìûÿÎõÖ$þÅÛÿð¯ÀÿvA·’á’yIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/firefox.png000066400000000000000000000175641217176075400233740ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ;IDATxœå›wœUÕÕ÷¿ûœsÏísçNïÃ0ôŽ  °"ØAF5–Ä5‰ñµ=‰½¤K|lQE»""MD¤ÌP¦1}æörÊûÇ>㌈Q“¼<Ÿw}>ûsïœ{fß³úo­µ¯°W_ÂaAG±|6Ø6¸]ò@p{`ËF¨­mëaüLHÚÜîà‚¾9`t€jBW'ÔÖ‚Ë —\A ¥#N¦õÑerß­Û¡/©:Yea Ì/—Öqûi·aÛoð(³ôjxú98ûLyíâŸÁ5?…µ_¹]ùn»ÎrÞ l LÀ,Pú…  i ¸ä}âÿÁã|ý ßè0%¼®š\ŠÃ”¦ƒâ…¬ÏM ˆ)p€/ø.þà,Ü^*Ùø?@âk…û- –ª€¢‚ªyAÕ@•­h ê <€Dh¡Ñ(á_°ô×ù˽SÙl„‘Ó/&4ø[o¸øHW€7o2º)Äÿ0i‚ýèŸ@á … Š[.Õ+O={=VŽ^À_ÎŽ’ïóQü Xk“óK›¦›mž¼q+/üöN†.[É_ê?ìß5d¤)p Ę+Y NÂï/ƒ{mÄŸ;H!ü»î0È’‚¹PZ0žSÙÀE$㸨*¨>Ç,‘Zþô£ålZ:–Ž: åböÿí—Û&à·¡èŽ Cka¨7Íœêö±×ïRÿüÑÆX~ç½.¯ˆA—Ý«ù=uÓ¯ß`k©.Ö½ŸÏ“«`bå§|jÌc5®Ót×Àû¢!w!ÄÕÔ7ÕÒÖÉ`!͹õQhÜ¥G‚îÕd—.dñŒq½¹åM˜9‚‹€nøèH–À+¤¢PžpÓm^[“¦&“Ëü¤‹·Î¿‘߯IñÖmUèÝË U3Y4òN`¨Sa¡ö!¯Øs =øÎ¿dšÃxN€‹ª »iü¬‚ë àÎNìHB¥7©Ø_@¿¿+ 4À4€ü"ʹ‹B š^Ä쩜 ÑO¡mìj îC“ž¦fº<-t»<¤÷´Ïl*ýIªÚaXNÌ<ω“‡²|øþ¸m+ëB|ŸÃ¢gï„GÁº:Ðjàí²·#î5€~¥ÍÆ|ˆ³r‡Ý¬“’¬¼<ùZ\ó#„x„™ÀÚsà±§$‡½SÃXýè’ª4}¡pn°€ÄÒVë7Læ9?ìZO*væÀCÑitåWáeÐ'ÂX¶ExPM7šéÂSjãQ*Zê¹b+¹¾÷˜W*èœPÊëP¸x> g~ S¾óžá]1ýãW®èް%?‡qò9wYÀ aŸ¯nV‚çN;öY–þ£œß,€_ O^G8wVoG¤ •lÂI[¹ :9˜Þóñp%“ÉeÚtèÞ;€ª8ÖøGÏqlØê£[ ÒcÒÚ•î  zrð¸¨Þ݃¡{H…ú|Áç“ÝØI7ÑÉ0#N´Ì z-¬ÚgþÖ¯ñ œýç½V¼8ÞB‚ˆƒQ90{:Ì[Aýr˜´À{Ãì¹°sªô¤Ãy k¨),M^UAñÆëÀ ¸µpžŽÇ™ Œ+…¦5°¶…¼×3îµx q$Oî˜Ïþ¦R¢z±œ #—“ŽÂî>K%öðj5>‚îÒði:šj E`YP.:ØwøáŒ{åϨ–LM] ó1Ûæ0æGÂiÇhÉ:° ïÜóäóÿ ûÛ ®WÊñ—À‘ç,9PŽĤÏ[$(½â^F=p2Þ,¨µ\¶d6+?)¥¯¯˜„'#äÅ_â‡`!¯ïѹ`J9û2ОÊâñè誂â²šŠ¢ÚË…­€Šõ…ú„¦âOõÐ2ºŠq;Ïh¸hLužã=àq$4(Â@0(DÂnà&$ÔÆç^Üé °iË@Èü=°üú¿°t $zÁ2úà[[W0°°€sËaWýœ€ºøwG³î“½½åôz+ œ A7vÀO $ò°¢)ÁÆäRƒž´Oµ°-° ÃX°ÀVÈ‚)TlLbæ—ÀŸ–ÀëÀàOÀ Hø< (q´pþ LvŸôëÓ ¬–ÁνÐÙ ç8–Ò |¦`v ‚°H#Í%“ÿç È…÷Ïbó† ñt½f  !@Ýh>·ÛWSÑuÁ²Ý.û])"i‹ ­‘¶, lŠ@Ŷ …¶d¥Á<˜æ– ›€ûæ¶;n`8« è¢À~G€ƒ¿þ»vZŽöÝpOJç6hþRž[¾ðÎ@f™ØèaTl}õ«×°ym 3޾áÊŸ‚4¯‚K×PT »Q°xfOŒsj<ßDz-4hN…-P° lÒº—Ñ[—rÖ/n¤õÍ-°y¯ÔäàiGcý”Zýý¾#ˆÉ!â¬ó߃%À‡ÈLÉhHm‚©GlâØ³ ÕfvúÉv˜·JfÓ¢ç6—óøÓ~B™a4öŽ% 9ðºpû44—‚Š‚eÚMpÖX?u=&K>ëã•ÆóË|<±3J¡[AA€ `"X6˜•&5LU) yûr©Á4Pï0üM´èÄA™êz€ë€Jà1®¿Ø×LJsÿ³±_¡“ þRÛü¤õœKÿq-v·Jƒ9 ÌäjàV@Wd}¤ØXXÒYƒ?lˆÉš(ŠÍ–Î >Ù…^kJRàQ‘ˆN „!{.V”ŽhÆÕ 'ßœAÚþ6”Eb’ÁÕs½#nÛü0: ùOŽ…ß•ûÉàMP¨7`§õ=7 ÷‰gí8yLÏÞz3µ`æKHð¥»@Ud¶ ¦ &6©44´'éŒdɤÀ-àÅ]qJu…"/´& b†EÌ4ˆelâÉ}i¦‹ûÐÃÀ±Àß’ñiPk>¾ZMŸñ&p Ll‡WÿþC¦N¯\ ȪBk·Vüð…º£ ¦y ˜ò3·ËH6¦)%ŸÍXd³6†aa6™ŒMÂ0IdLTËâ[£œR@EàÖl|ª@Ç„lœd[+#‡¸a±£>džÿWé`0ã€ëŸí„5¥ÃE Ž'¨]5øcÍ—íÀ–Wýgm?ï$ö@ ɾž*¤æ5$`B%“‘öcfm2†E*m“ÎÚ¤2é”E*ibf,zïw¦ùÉÄ•ù^Æ—éÔÚ„”>†x“œê#Ÿb32ïÇùr¹ómɼÜt:× ‘˜à§wÀÌ_È3eμÁÿªáÊ‚jC3|$jÇíÞ1Sü‚^§'¢:Ìq6ÓÄÎŒ¬eÙ¤S&.ÕÂ0E‚)E±Ñ4ù\´a3¾@eb‰—&­‘>Võv2Öå‡ÚNø»Üi¸·þÚ +YÈtþm)ŽTP#°‰¼À/ìK n¸ ZÎ÷ ¿$€—7OÀ­˜”‡cœ–zäç4G@ñÈž€¢‚ËtúH³€¬M:c ©™Œ­0-Åt„°0t…ü<Á¸´&ÝT:sBŒ;dÃQ!z4¦á^ય êÖZ66(f\Al̬-ãj¡fT,5‹"À°,JöÀŠå2¿Æ@[¤y €¼¨.€CÇC¢n_7^uá`ÛÞXŒy-øÌ¶'\gѰr\ )2ò«ŠÌkè<hN\èÒ5,KHl…‰ãœ?1HOVays%OãäQ¾—g])^õ8Þ À›H·Ú‹ôý2à$Àë‡sÛÿw Àä(È¡e0¶&¡T…Sþ÷¯ƒªq3ÕHƒI‚¶½MÇ“)r¢½ šãô*R*2 öˆf¥u$ ;,— &åñi{š_ë Ù•B>V ¨Ï³1³=çË%úF„1ÿP™uéP´±÷­pæõpw·„¯·xùrø4ÆC `H5TTBeŠ )ÝeƒûÿWÞü6x„mï6ŒÑoñ}žÝX]1úœ‡€€ ¼*øuÐ9*3Ä H›L™UÌ&çòAS‚gÖtC<  tU Î+ð4¼> W:JÕÍ÷Ççñâ=eúÞ8¶¶„“žY<\áñ°è³¯gЋÔÙ×ÑH༠0~Œ5:Px 2šй&]#8Âr&]Ò÷µš s 3¤ØÃž¶“fë1¹îï­Ði@¹º>à&`’&@±ËÒðå„Y±v7ϙćMk03E4¼ð0%Çù ”cvI÷ê¶ €Óù´Ù:³œkÝÎç» nR‡×Bº.>®~øžxõAÎ;á ®û‰Ë &£KJY•¸šOVømq¶ŸJa‰‡“Çû¹Dƒ®2?§¯îãÝ·Úå»'8Ú¶ü_Ívw2 *`"\n, /¦²+%1f ];H$[Éè§£W$áÜvYÔ¼q€† ™ FåÃð0¸âðV3LA6ŒýÈL¥ÐÚ‡•CA¼õ1\ùÛ$ÓWÈÍlÜåÓö•‘L”†Ì^¼j”¬4_á<|ÜDW-:EÆSQØÝk@ŽÅaR‘éQÐ-ùÞ%c€P5„ª"T  x<äT”òöçMŒ6w…ÿÈQèž[AŸáÉÒÏC äÎ3‘)sÖ<˜}"Œû!tWÃÈfYDíQa)2UnKC´·@[|²BÆ…mO\ÏK§Ëý¼aP½€Ìåa¢…EdéPÒDllÑMég”y¹pC„‚<û»ÓDº3`ZQq§š¨E‘^€‚PlÛÕãB÷x1>\A…¸×fÖIÕä¹—9ÄjiYp.p¼†CéT e øéááAçŽ1Þ_€Äü»€h&ƒ«Ž†ÞÉG0WȽ§ü¬_¿ß› Ûö¹’D„JÊÊB¦]NU™—ß>ѵrò)ƒDÌ›(ŽŸ»,T— Ó°QT! ,„P°—WA×T²ñ,Þ€ŸE‚˜rÌHtcR?'xÊKáÂT†‚@µtþ]ëà!’–ÖéE¢Ö™ágH°;±ºöÀÝ¿„U=Ðk´Q*g•÷½÷ +†_x*i¢^Ñ)R‘óNHoÄâù¡Ô I"݆ ŒB šâ˜¿‚6šK€°Š‚ª(Ø6¸<—ËE"šFwëø}*¥y*•Å1ôàí'ƒÂ)  A"£É@,¹Ý o­FÖÅHki9jv¨W@,{: Ì F*Ìš2ÜÒIÄ<FÁ}¸ò&Ÿag<ËÜãÇÒØ‘¤nm/{Á4!iJУ+àQ%ãB8Ì»P…Ô¾æl·OÃ¥«Äª®  ðéK%Qp ð2Ÿ¼}k!üÊ üúT¸o sná|l"{…]|™Zmh‰Ëôøóip{l©3Ñûƒ» – šf3Ô¤‡ë®p¬c¦eowu›»¡°TKÞœAö „n§ £ƒpIÍËc—[`#¿Dw¹ðxâIp©JÖHMÇ8yôt6Õ­Äj¿•¡¡ÃHi³¨]¾£ÁÞâ(Øø Üy¶ìLò Ù4íFæý]|•Ú]¬SWÃá‡Ô‘IïÁr‚v?ÉÙ`º†·W¬ÀDOù1Þ~u+®’dÕ Øn™1ÁT¤ù˜NÔWÓWŠK :©SUUTEàöh$Ó†„Š •6а¸mÎ(V®} 62K+'Ð÷£Îœ ¼¯@ã]°'&Ó`…cò>df°>߇>_ž ‰fT@›ö7,dà¶¾|›&kÌ‘õ• Ôµ“×[s©ðИé¢[÷Ë‚š– [¦;\U jElºWàs»H$-4·¬¢)ƒ€î›QÆßVLjw=s4£Ó"¶.Š=W…!?‚`<õ0¤ò; …T ²¶¬ {Õç"væU ¤@ŸkãP]Å”ñ=Û¤Èp^¸Î3c,áÆML.MPªuQœm'htâS“ÒZ¶\ Ëጆ–d¼ÿ¬®» z]¨ºBN®NNP#i›T†Uþ8/ŸÇ6ÖÑÞµázoOZgo_9P Vä€× ù ÈÓ¤ïšÈÞõS|hlY Nf€žøNzâÐ…ž//EFŠ®7˜zy ‹IU1&äw2„&r"ÍTªJI¹¡m8]XË颛X¦iÙ`˜( Ó†_¥²@ ¸`N­ÿ35È-«ê‰t41Ôì¤ ÕJÑE~²ƒ`ĸ£€`&ÀŽƒèw D Ušni©AB°" 9JÓ€Z7Ä¢Í$cL|e)2„¶¿‹º+j ¿mó¦e™YÒFu¼‘¾ý{8¥¸¿7†!3‚eK+ÈZÌb¤,²¸uA*câõ)„|‚±e.ÎíãÔr›VíÀÛÏu?UV3åV%F'9‘^òÆ~°?…L'd»¤g2ø&l¹âÓqGó6_ô÷ ð¥Ä‚Œ¥µÛIeÓd È~u)r— Pò²ç謷1ov†©E,ÑFqKÛvîæì¢ù`fì4Ã9Uj!ø½*™´‰eØÄãiötÆ¡‚VŠß}´J£™áÆ.ª“uT%(M6Sëćœi° Rû!½è-YÒš> ç1£ ºŒb¸ø‚À¡ŽpÆûÁð®Å2e4̯,Mº€´?ÌÜkXxߥ¨"Bq0ËÂI: -lo1èÖ“ŒÓ´*ù¤ bÄÄièxÈ’ìT°±±0 ¨sã¼2>ßµ—uM­ ÍvQ˜h¦,¹‹òø^Ê#û(êm'°¿‡¢ àôM¯‡t˜=MIRë1g dko7ÃÓ"°Ô)Î=MÀóáÿÃÉ3doBùê¡+1p×Lþ”û}páÔ<"oºÙoMæÞۛ諨 ’WJ›+ˆ'—„+LÚíEä° SRÉ4µUa~8­˜W7ÔÑÒÝÎpOœ ÚÉ‹6Sšn¡*ÑBao¹M]ŒG¹`6T ®4¬ƒì~Hwƒ•†v zm™Ó{ÍS ™ÿ×;fÞŽ¬ÓH]ž„ì„û~áô¿„ð:ÛA¡j“"7qù]/sæÕpéqä”=OÎT8yy€Oêé2ºSU@}¯Ÿ¸'Œ¡I÷yI™*I;ÍŒ©c_ÒDz% f¸„º{)Q:)ÉvQi§ ÒEN®^#B°ý/ôÜákaËõ¸Í0e‹GòÌmEWÉø£ÇÒÕ°›Ï·v’ëw¡¥³Í~;C ›%HâIÔG©@Ñi@tnºM f!? íqˆ)c´#çH7¸¢®é„KÜ“–­±&Çή€íüb?¼p,è}„ë^½ÕÁÿâà¶½æ€KÅÀ‡iXt)×.1xáI îǺ{¢Äé? ýº—(:ËÁ!ÔßÚLãŽnü9wÀ‘6ç+¸<´Äñ¨?Ô)È 6ûdŸ*UÚðìØ~¦ÖB² êšål t …Ð\ `þ0䤸} |î<î‰5`àÎÏ`ÖB¸ù§¯²ç®sAëEÑþéta·Üðå+  ùòéMurëm çO?òc=·D°² Üv¯c-Ë`ÕRÏEI‚d·FÐò<øÃ:ž«&CõáòvÈc/“…†ã¡5]6”WÂäÅÀNøh9|ž•5~;ÒãÈ(ë…ò;›¶Â«dfãGAKþ¼Ž?νh+^6–ÃC`«|Óq[a·ÝrÀ%çWÑåÃi±Žõ?†NR,*÷¨„‡ÖÈâäü_—Ë¡ïX» ¢Q¨‹ÃøB˜>ò hùÚÜ0d¤l¡íÜ$ý9 2† ‘ °â%éËAä ¤™ûÀ×Béá¿GÂ{¦lqÍ(“0·p8Üø4œè`X8ŸÓÍá¹`}óYcí+¹ÑìÐUOх󙟳‚5gyøI³Åy ¿ŽÀÞ³áõ[À} L›Ý])SO®•°¢ ü%R«@OCv tX²I{`è0°ûà…›$³ad~߇ŒòrHR^ž\6Ljý8?Œ¬€ï àŒç$bìí…C¦Bi7—ÉÀ¹çNÂî¸õX`% äûò ð/„÷—óèBxxl1T_\Û>–3‡‘þm 8“PÒ)Øœ–ÚÎq´»‰èú‡R’yé÷MÎ^ó<°!£Ê`u z  †—ÂáÓ¡Ó†)¿‡ù£Á/ wÌ\Ńh…ÎÆƒŽYÿú±nÈý°C¹ðU8FÀÏû§I.ÃEr´Ý冋‡Áa™³ë€†>hËB~5”V@²öäJ‘>žEæõ#”$¢«ÞNAB½)˜1 fŒ…ãfÀá‹àÕ(þ=œ1 ¦ÌYʲ­¿&äyÍ‹ŒM–³yæ××X@J;*ë?º«Ô6Ý w¿.)žS%¹°¢6§`˜Ž™v9´‡ § ÚÞ…õQéךcTa‡q7ø>ãȽÏy­ÉƒâR_ e%à V.\z7ü©–\³70dÆÌ,y‡hÚ"ÐЌ̙ýþsú?Ëè/¹¬NêçW³ûÄ{¸ãGÃyó¹ <Õs`Öb˜ŸD,£¹2¤Ì3áØm¥´è^ m»`›5p¤%ãÈ{lÔŒ†ªJ¨.J îƒ'Þ…%/9=• Mû3ÇŽû1rrmêà޲¾Ùô¿ƒݪ¹÷ñÒËgð27qeÕâ1˜‘€—Ÿ‡îJ˜~Œ1Ay Ø÷@Ÿ ‘|¨ž&d›mÐã†NKzXÈwÉ X>*†‚R"o^ƒg_QÀçÃ171³±ì3 j±óÝ~eò-àl¬¨ b2†›™0ì¯$¦:æ N][ÈÎ5ðÌcðpÄHpûåý™8²Ð¾D^ƒ.ð•¤a0-ù5ÈŽ§H@],] K߇ž”t•ê0üϺ>¨½Öÿ†@6 8#¸¯AyÿA8ÔÿE`d÷IÜ S í1lÞ•ülÍp–½Ÿî1Ô‘ù÷Bn.–€Q-# 0 ’ÐÛuOÁg› Þé>(RàW'Á‚ßÁ /ígÑÅ?ž“¨(d~ÑúoÒ¿öÓ,§·né ˜Óðèà ©=‹œq -õÃøè-8ZQ É(˜­ï†H =ÐÜ.žÒÕ)8bŒ ¡±pØj(zº_fذnâíàw^Ù–ÿæÿu|Aý¢€æ†ç_}ƒg™˜ Ç× è“éÎà­,£ÓÔ¨¬Iª°8äÈ,ŒU¡Û†Î$ÚaH=øv»Oæñn ÒqȤÁ¯òm¢úw%aÿ‡Lé+ý»?Ïü_Oÿß àÿé‚ðÐoL €IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/flash.png000066400000000000000000000135051217176075400230160ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚüIDATxœí›keWußçì}^÷Ýéž@òØÖI!" A,H$bŒe("ÂXŽ’¸bCp¨œˆË1v•)ã@ŒÁ6¯¸b!‰„Ð)Â!ÍH3-4Í£»§§Ÿ÷}Þ{çÃ>÷ö™îQÏ0r>$«j×é{ûÞ³Ïÿ¿Ö^{­µ×…ÿÇÅz©'ø©·¼«A"~˾ڂ«-Kï´àå–e¦×Z °V4jÍ¡\é'‘êñ§ïþüìKý|/ ׿ù®ËµVï´,ëÚ¾޶mlÀ¶-,ËÆ²6&ÖZ£±PZ¡r…”Räy¾¨_×yö•}ñ‘oóÀÙ…~Ö FÀM7}H¶+ÇÁ¶ì÷ !nÂFs•[ ¥Qa[Jë¬"W9Ji²,'U9y–‘åæ™R‹:WšXù'ÜóùÅ õÜ„€ënùå_²¥üwŽ{¤°q\‰#%¾çâ9®ë˜á8H)¶e[XXh4hÈ”"Ï2’45#Iˆ¢˜(MHâ”4ËH3E’æ‘ÊÕf~êÏ7ÿ¯ðª·üÊ+µâSŽtnpëJ7 Tö)ù>ïá{ïãûžëâ¹.Rì‚4C H²x’†1ý(¤× Ã>½0"Œbâ8!Îr²4kf™ú·û¾ùgŸú['ছ>$»õã¶û!×ÒwJå€J¹D¥T¦T*ej••R ?ð \!RØØV~D”2K!Ër’,#Šz½>í^—v§G·k®^n?"Ž’,#I³”ŠÞ¹ÿ>÷·BÀõoºkÆòô]G¾ÁwJ~@­Z¦\.S«–«5h4ªTË%J‡çÀm Û¶±m°°°¬ÓÐ ­ ¹Òd¹"ËRâ$¥Óiµ:¬7›¬6[¬7Ûtº=úaHœd„q²’éüOßû¹o½¤\{ËW8R~Íu=%ߥV«P¯T(WÊLŒ5˜c¬V%(yxŽƒ:Aa[ÛÆ¶Û™ZZ+”‚¼¸*ãøÈ”"Mq’Ð톬6×YZ^cim•õõ6Ý~Ÿ~˜§I–¦Ù¯ïûÆgÿè\0‰sï9ò~Ïw..—<ÆÇŒ×ëì˜g÷Î\´sãujå€Àóð=‰ïn Ï•¸®Äu®#q‰ãˆâµÀæê¹GØHiÈsŠá¹’ äS«V˜žCزØN-@¡smk˺uÇ¥×´Ozò_P®½åÎ+<×¹ßóÜér0Þ¨3Þh035Éî‹v2=9N½Z¦ä{XAàJ|×1À ¥@QX†0–!ll{`%fHiB¤ç:LŽÕ˜«Ç}Ú­&i11^áuï:æO®¡uC¨¥­7 /º®ë]3RYú¾óò²ï3Ö¨31Þ`×ô43Ó;hÔ*ÅvWhS ¤#pl»XóvYÃëf“j m®Z!lA­Zâ‘ìçkýÿÍ“ÄIZN`YpÇ/ÜÊ+¯ºŠ¿yj–…Å%–WWiu{ô£”8KÞ±ÿžÏþ·Ã'Ï þú»©­¯øžóò²Ð¨×Ø11Æ®™vMMR¯•‡à=Gâ9GÚi4iYF³˜mÏÂ8¿ E(hÀ£ÌµV©ñÀcOð±?ù ŽÎŸØx ǯ ®Â廳'¸íÖ7²ÚêaÛ¶a ¥: Ô§/ýíÏÎ~çÏŸ8_,¹Kÿ¶çº7žG­^ebbŒ]ÅzoT*ø¾cÀ»ðf—rTû¼MüXgîX¶q~ïû­óG/žjPn`I÷”¯Ì­·±,‹ã T®ÐZ¡µ&W ¥¨”µúÒe7þìµÏ>òWs&àútçÒuÞ¸•j™ñF]S;Ø5½ƒz¥Là;x…£óYx{±±–…Àn}vúZX`œ×Û–ÅÒê*¿üþßfnqɼézP›ÆrÜMž´‚åV—²ï±c¼N®rQæY–£µÚã×'øÕ­pnê¯|ÛÛÜ’Uùz)p§+å“ccÌLO±{×NÆUJžGàK×Ás)R"¥ñæÂ8B"…D 1BØi®¶\Í{‹ËËÜþž³¸¼j¢2†Õ؉%Îî§o¸j×À²¶À²,L¥ qœ ´~Uãe—}{ùðþã›}3 °êqã_¸¾¼²R*3Þh0Ñcç”qxçâ¹f/¥ñîÂØÒFžâ ŸPhÞ,âÚîty×ûþ#Ëkëæýú¬Rý¬ÀÁ¸Õv—Ê¥»ÈÓœ¼°#'ŒÂÈ„Îiž“9þÇ€W3ô8bŸþÆ57¿³d;òƒ¾ëR¯W¨V+LM3Þ¨ø.®Ã=~^À–à YX„Ä-†#ŽìÿÅfkü7ý$'š¯Mn <÷F ïø%סZ.151ÎÔäãõ:ïá¸Îß}ÅÍwܶÙ=N·Ë÷ü_u¤œªTË”ƒcõ:“ãcEXköxß1é­Y󯔥4æ.ì 3—¶1uÛ2Žp3ùï÷ÞÏw)^PÁ*7Î zçDŸû×qýe—pÑdªï“' ž#)y9Y®H*e&ÇÇhwºtz]¢8%qó_ÔÙÒ•wy®K­R¡Z)39Þ Zð‰ãØø®[˜¼= uk]Žb¸n Ýéñ;Ÿüü`f¬úÔ–Ÿ­•|Þû-ÜzÃÕôº!Q£³œ°Û3š³Àw%i¦Hñz•V£Áz«M»Û'I’k¯xÝÛ_sðþ/=¸%¯zÓ?yƒ#åWJ%ß§^«Ð¨Uñ\)íá>?ˆÜì¡+"8!†KB{óínDþä/þеV»@¸Ã샛Ȟ];ø/¿q¾+Ëë[ÞO ïJâ,§R.16Vc¬Yc}½EÆø^éNà!F|Á茶ð‚Û¥#)—Ë”Ê%µ¥À†±®#OqjÒH["maÌþÀ·;=>ûå»Í /ÀòËg~Hk.™™äs¼™gÄqrÖ{8Rà;ßu¨–+Ôk5ªÕ2®+®ós333ÁèçG Â7žG)ð)>ÕrÉhß¶q¥zöAÌn‹ 3—ÅØx€/~õ^zah^T'Ξ$ *Ïøƒ_ÿE’~Hž«3o²‰HaãI“TJ>õJ™j¥Œç¹H!kc—¿æg6%àê›~ö)åβïã¹.•rß÷qd‘œ8E@cƒ°­ ó§.‡í€Ïòœ/|õ^ó °ãYF§Òc~ó]oa"ð· ~H‚´q¥À+‚¸ZÅi)p¼à £¸XAuüµR\ßÃ÷=*A€ï¹š-’™áÞnÙkÜF€Û‘o=ôý=¿åí}÷Ÿ•`h¹Žøž‹ï{8R"„(í~Åk/ÛÿàþQ\[Ø3Ò1ñ¼ëº¸E‚ã…L€.2;ËVvím‚ø`Aêô»ý¡ÖóùÅ/Å²Ò ËÕ†ÖQCmo©u¥8-yq Å «ÇÃY=|ä3PzP ÜÄïhˆÃ4¸ÉŸÚTî¾ïá½ß«¢²ж´®Ì<çhgÈ&_ ”Š_kRÙ°¾¶Ùtq“¥)år Y+£ÙÚ Ìý4ŸøÂW°¤N‰Mµ>¸™ÖÏØç7ó›Sè äiÚ=ƒ€,ËV”R»µRä rU0¨CŸ1Ïív—N§‡ç9&Ö–!l”R¤iNš¦DQÂZ·Ãí5õ `#ZßsÑ·ßòÚAÃÀˆ¦Gþ>í.µ9e*ê„yžƒÖDÝæÒéäYÏç¹Úå9Yš‘çæg;?ÑZE Q´y¦ÖhTù÷øiÞ²°¼£ÚhýŸýüyûë_E§/ niiml€Oóœ$ÉH³ ¥5­…£G(¨įiš%‡³,ÃŒ”,ËÉ”¹Éù®:Û¶™;¹Ì_~ÍœYZ~Í8&¥Ì!H±Æ}Gò‹oºq[à·+¹Ö¦B¬´)¦ I–“¥éj{mn…bm HºÍ•§¢$)Îés’4%ËM™Y©ó£`|¼Æoü§“å™Ù-ýš1ùÁ:/ÆÏ¿þœs¦¶#ª8XÍòœ8N‰¢ˆ4ÍH“ø‡@Äé°|ôÀãY–&1qÅ i®È2E>ôÛ— ðøò½÷qß÷¾€í×AÈ¡ÖРrÞsû›étú <`ž;WÄqJEô£˜,˻ͽÌs×|uáØñ°×}. CÒ4# #’4%-bôsY®ëphnž_ûðï`ÙÂhDëÅ8oyý \:39컢”&ÉIžÅ1½^Ÿ~¿Ošå¬Í=÷žAÐî´Ö £˜~Ô§E„EFš™a;R«•™=rŒ[ßý¯ˆâ,°+“Ź׆ÖÍ. ùÍú6Z­î‹Ýöœ$ÍM—Iœdtû!^^GáÂÉ#P¤Â£t=yw¯×SQ”†¦?'N3ã<òüŒe`2G“oÕ±›üç?å–w¿—n¿oÀ—v€ðNÑzÑÄ;n½‰‹wLœ·ÙL´Ö$iN’åDQL§Û§ÕîE1½õ“ßÖ )G#ÁhùØ¡Ù^»ùT«3vm£V£ÓëÑ*”<ÏÉ‹’÷†³šžžà£Ÿú+ë-ß½û‡‡1{»4 Ò5‘œÒ ´ŽÖL4j|ô½ï¢Ý¾°ÚÏrE”fÄqN»Òì´i¶ÛDqšÎ=ûƒ¯FÖó(9°²xôÙ/ML]Ûí÷évût»!eß7çÿR ;3”Ö|äãŸÞÀ²–˜á•œÙsj„÷Çþ—äÉ…í{ÔZ%QšÑ"Z­kkMºýˆnkåÑÖòü,pŠ·]hÞ÷èw›ÍµÙµV“n¯O³Ý¡Û‹‡hŒÑ%!&/ÅnìÆ®Nà€UaFûZ)Þ÷Koå5?uIráö}€$Í “Œ0Ni¶»¬5[¬¬7 £(ŸŸ}ü‹À2p ë§òb`þøì>×nwiw»´;]Zí.½0!L2â4/Ö¬E’$8²0¢Ñím0P§¼¯µæ¶›oä¿òvZ­-ìÏK²\ÓORÂ8£Ó‹Xk¶8¹²B»Ó¥¹²øÝ•¹ç÷g4VžN€VŽÍî}`ùäüÃ+kMZk­í¢õ¤?BB–å\¼kj„µ¥ÖµRÜvó|ú#ïa}­uAÁ+ ý8¡et£ˆµõK«k,­®Ñív»?|ü¾ÏóŒxÿlv<Ç|ªÕ'®.—‚†çzž‹ãÈ¢ãÃ4>gYÎËvÍpøØäYQ9u­k@Úÿá×îàŸ¿ýVW¶>Ú:Ñ@Çô¢„^”ÐluYZYcaq‰N»ÇÂáµ×°‰öaó,GI‡9¶•UƦþ¾ë¸æ”×¶RbYÛ²p¤Íì GØ»Ûñ7ƒ6IN%ðy÷[†ÏþοæÆk~’N»wáÁG)0¡¥´{=æO.sôø< KË,-döÑ{ÿxØtò­Zdàè û»§>1s¹#œ,Áñ·@k‹\)„¼îÕ×óÜáãà•«7˜žhpù¥»yÅO\Â5?y YšÑíöéõ¢-¦:OðúqL'Li÷cºýù«Ÿ_äÄÉešÍµ¹ß»çÀs@{«ûlE€Æì—Ï=yÿÿüŒ_ªÌHWü)‹NOËÂäs×^õ þëÇ®ÃqZiò<7IGšÑ\ßrÞIò\Ñ‹SºQB7Êã„…ÅeŽ˜çøÂ š­fûàÃ÷þ^õöKœ¥–v¶‰™ó…ç©O_¼áÌ8B¢´IuG¥Æëö„<ËPyQá} DqšÑ‹3Â,'ÍqšräØ<Çæ8:·ÀÚÚjû™G¾ùÑæòñCŒÄý›É‹uŠ* §µJç8ܘ¾h¶åNÛŠ:xž‡ç9X¶¶-(ªÊgkŒ8±, K´e“äjÈ´&ÏÝ^Ègstn£ó‹¬­­´Ÿ~ô›¿»¶ðÂC˜uÿ¢&¸VÙèj­âùC—ÓÓZ¸/³°ÈUN%ضM¥äGO¦]F8AÉÇó}<ÏÅubÅAÊ©)¶ã˜ž"¯8Æò|?𑮇¶lr,ò¢0ËrŽÍ/ñÔ3Ïr|a‘¹'X]]9¹ÿ¡{~¯¹xìa`K¯>€‰žºZ«xáù§XÒK„\™+mç¹¢ÛéõcÇ¡xÅOd¬aç˜ç;”ŸZ­L£^¡^¯26Vc|¼>õz•z½B¹àº.–´ÑÚtgùàg59'Wš<±ÿ‡<ûüQŽŸXdñä2‹‹ÇŸØ{ßW?l­ìbžmeXÛî/H轕ùÃKëË‹‡œÊØ%iNC)E'¬­·huCl! ‹æ½h“7g ö–ç(ƒ ržg…™Ÿe9ó‹«|ß,ûfq|þs'N°²²>øÄ_>óÐ׿ ²d?0 ´¶ þ\ %¡Õï4;Çf÷?”qn{?–¤©“)E·×cie¹Åzq‚e[¾‡(N›‡§Ÿ&Á+ãÜ’,ãär“‡Žñ½Ç÷óÔì!æN2·p’¥•N̽°÷ÉïþÄÒ žžÎ9µ<ßBœ Ô€—{‚jý’Ë®ÿé7μlÏMµZ=¨×ª”˾ã™zßgjrœéÉ:*•²iÁ‘R˜ÞÞ\›h®±Òlsâä‹+kt»}úQŸf§G«Õ¦Ûë±¶trÿá}}åØsû£Àa`8¯ÌêG©DZ˜Fƒ àåÀn7(_ôã×ÜxãôÅ?öêúØäÅAàQ)ø~P4X‰ÂÙ ¤½a|m~–¤dÊÄ^Ÿ°ß§Ûé÷zíµ“s{_xfåã‡à°ˆ‰ðλ¢r!J±`ˆØUŒ‰‰é‹/ž¹ôÊ«ê;v^VmŒíñýR åFG¹²ø­è,'ËÍoã$!IÓ¼ßiϵחž_ž;òÌÂáý³(µŽ< n:˜êG~ø %àc–Æ` ª€ß˜Ú=ݘœÚéUãAP9¥T¡Éã¤ßï¶šõÕ¥µ“GO¨,éb´»Ž1ñe` SÐø‘>ô… ã\}  Ô1¤TàaΗG°Æ8عõ0Þ¼Ñt³Æ/\ñpäa_j±19‡ÄøŒøÓ«Q CBRŒŒ ¨éÿ/[Èÿhjf²o¥jIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/gpgsm.png000066400000000000000000000124071217176075400230360ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞÎIDATxœå›k]Õuçkïsî½}ïíV·¤–ºA¢‘²„0dìQÆ›$x’¨Êeì±M\`\gƆ˜$¶‡ÁØ®¤â<$Æ›JœØžIádŒ&3E ÁqΑ$É•¾ï_Ñßßáàà`¡¯¯Ue÷îÝ4 Œ1¨*ÖZ6nÜH?A055õóñññÿ=;;ûßTõqùçæÒ ªÅ >Y­V¯ß²eËêóÏ?Ÿþþ~Z­ãããLLL044„ª""8çh4”J%úûûY½z5Ã0ÜøóŸÿüÏ>ûì®ÑÑÑ/ˆÈ—z¬°Ä$I²EUï¾è¢‹þõŽ;èïïgzzšÉÉID„5kÖ°aà …«êÖëu&''eïÞ½¬ZµŠ­[·²uëÖûÌ3Ï\öÐCýa’$_–Ôi- "B†¿º|ùòo¿ç=ïY±yóæÎÌ–Ëe^·jµJµZ嬳Î"MSÆÆÆxá…X½z5_|qaÍš5·|ç;ßÙrìØ±«ÆRŒ–€ Þµnݺï^uÕUÕÁÁAœs¨*ÕjµS¦Ñlòò‘—;v,™©M‡aØp.UR¹\^6¸reéÌ3‡Y³æ ¬µ ±víZŽ?αcÇæšk®¹âž{î©=zô½¾ï7—"‚ÉmäcûØÆuëÖ=yÝu×­¨V«$I€çeØ:tˆxô_|ñ¥]³õú#‚üTÕU%H]Bš¤^E+ã89Û÷ o]öú_{×;/ùå·½õ—0ÆÐjµ¨×ë 266Æí·ßþÍF£q•µÙï·ß~û¿ ýèGm__ßC7ÝtÓ%år™V«EµZÅ÷}ýýßOÝÿÀƒŸO’ä/z{«Ó¾_ àÅ©â\Jš¤DQD„DQL¸4ݱ}ÛÖßÿЇ>ø›6lÀ9G†Ôj5V¯^ÍÓO?Í]wÝu•ïûßî¼óÎEë`]h6›þÀ>p À¾}û¨T*Xk9|ø0÷Ýwßüãÿ›z½ñ§åryÚ³¯ÎDc ¥R‰žRéñ§žþÑίÜñÕŸ|ò‰$MS<Ï£\.³oß>.¾øb6oÞüõz} Š¢7¢ÂâxßûÞWüL©Tâûßÿ>ëÖ­àèÑ£ÜÿÀ?­×ïîííÝmÌ"ºÁ/hµ‚ÛžxâÉk}ôQuÎu¢ÇîÝ»¹ì²Ë†Ã0¼:‚Ū¼â8Þ966¶éÎ;ïä-oy ÖZ‚ àoþæoA\9rÎ9ÇŠÅ" œ®™©*Åb+‘¿|òÉ'¿¼gÏT•ááaöïßÏC=„ª^†á«cêiÈ¢X¾|ùo­\¹’íÛ·344„sާžzŠ£G~µÑh>ûÔÓO155Í9çŒà{Þ‚APU¬ç1¼v žõŸ`zfæ‹ßøá#­V‹0 ¹ð ùÙÏ~ƦM›¶$I²}±:À"¸ä’KÖlܸñ—‡††Ø±cAP«ÕxôM)ü™1c,"BOO‰BÁ_ŠâYKoµL†LNN233C³ÙšyñÅ—îÝ»w/ªJ?;vì`íÚµ \²rYÔ:@D¶c–9çX³f išòâ‹/1::ºËZ{ä•ãÇO*oŒÁz¦¶æçh@ÅDz²s Z­~òÜsÿiÓ¦M& C6nÜȃ>ÈàààE‹Ñ!—EàûþŠ$IØ´iÅb‘(Š8räªî‰J¹wÞÙV”‚ qá—&$IJÅ”J%ó“E_Ü·oßËÍfs¸P(022Âôô4ëׯ_¿sçNsÿý÷»Åè²(nþÜ-nxx˜´½U¢ˆ3Ï<“|ä·úŒ3H“tþŠ“Ôj5²EŒ¢.§§§Lš¦¯*k33Ó¯A0œ‡ÄmÛ¶100P®ÕjøÅ044L¥Rarb¢³W·ÖR*–¤\®¦¯@ÕQîéáÜçàû¯vÜF“çžßMÇXkæeAêœ#O6l¤^ŸÕE…Ú¶,ªf†ÙA…KQUœs¤iJšÄó¦8Š(ú>½•2Q“{ó8Ž;û†J¥Ì–7mÆZ!Š"œKçMiz" J¥¥Ré ("àR×QÞ©C5 cÝ)M¥R‘ÞÞêëîc{{«l}óü¶¯˜Û–SÍúj÷i¬¥T*Í»½^¨, €ÌÉÉIƒq®=@w"%©£X*Ò[­,xÐÛÛËÖ­[ð½y@pJÒîÓ9h‡‹•E@¦°ëb@êP§”¦ŽR¡@o¥|Úí÷õö²më›Ob‚ë0*í/¾ïÿâÈèîNf€ffàÔ‘º”bÁ§Ré9íep.}}½\°ukÆ„$=a]}Š1‹Å¸L©Ô9´Ëò|j¥gуʥ¯¯—íl¥àû¤IÚ=MSRçß÷;g‹‘Å€ºœŽNO˜€sÎ >•òâg~®ôõõ±}ûV ¾G'š¤IfzišO„.[¶,Ylû§Ýã?^1Ƥ•joOE¸4;ÐÈCYÁóJ¥b±œzÍ»É@¸€éG±(Å’çû”Ëe»cÇŽ> B >¶t"ôð×K¥ÒW‹Åâ;€Ô÷ý¾B±¸JÃZÛöÈàûþ¸ïûÓÖZ#"Xk³}Àœ|n‘×<,É%‚!)æõTÏó"àˆsNÕ€NÆkÕ[¬t³pÉPÕyÈÃ_÷†en½ù”Ÿ[þ€’/È<ÏëDžÓ9XpIß÷;kp ãÍóAth!&Ñ]vîûÓ•4M;& "KÏÈ|À\ºÃÚ\™»—Ÿ«ì©Øp:’;OçÜIk¼§RôTùk•_ˆt×Ép: XpÉüÔ%·{ç\íSÍðë±`nYXÜ 1gÀ©ÂôkÉf@¾ÂƒùmúõÌ`)b· ä¡p¡² ¨*¾ïw:ë¦}þÏëÍzç@£Íœ¼­ù gBÞf°ô> ƒÀI§²yçÝùBf|¾ð9Ÿ?YèØòñ-ÆÄ€ÄùÎx=¤Î'N I i*8…‚Éü€ïû'}˜:Cê<ƒ8 D,ªcß7’'çç ýaª`NA„¼¿ÎÛ–Û¦”¥¥àÀÃWÈpù-Ë×ÌP­´¨˜3 9†Ñ¢Âôtñ‰iÄóÚ4Ëúá”JP‹QƒUƒ8ƒ±ÂËG Ôê>¥¢mGŠaõÊ„•Ë•40ˆHE0fj–£Š~ÆŒýû÷3::J±X¢Ù˜æœÁªº—BØ`™Þ±48 ö¼è|Ç·qšP\ýfzÒJ6@ 0y´‡»ïú'víºŸb13“ 4üú;ü×?©˜ìÒJ(ÁW<þýµƒD±¥àg3'–ó7´øó?§·× -@ˆQ‚1á†Ï®âàX‘r &&&˜žžæŒ3Ö0zø0ïùÛÓoÂAŸÕ­¸zA¼®¹ôÛú­l{àјþªb5×D\ ¢#›f¹àÜffãÎy€5ßý_¾ú5)…ˆÆˆ&YÞŠÙþ¯š|úãǘ ˜8ŽAžþ‰å–[Ë@ˆHŒ¸qD g¬‰øÂ8Šh‹F3êœ5ÄqÄL­É_öŠÀ‹0ºÄ»Á4íõ_ñxî%(ø’Ò\­˜_1Ë¥…4‹5™WÊ­w ðÈß¡G HL–jü`ÄÕް˜¶©Vá¾]ËøÆŸW pÔdLhX.¾ØñÙ«§ãÌD:g ±wLøä=½¤‘‰£@ÑSÆg,¿s›avÖmå“¢ˆr)áöḬ̈v0¦e^ˈâTøÔû}IÀWHÈŽ.c…@¸éúo» ÁlÊ==Ê—¾6ÀãxÐÓUÇ)Ì Wîlò¡wMSkž¥AR-9ûY/_úë^& _K,ŒÎQ* O¾àó¹{<°­Œi¥FºõŽÿò»SŽür¸Xp9æóÉÏõÖL—B-(•„?¹iŠÕ+#‚HPU¬q8~ÿÖå¼¼_¡ mÈêF–Ï^Sã—ÎmÑ ª®sF±¬÷>ÒË;o^¹´¨jû6ÃOyê‡)x¤QÛ¨.}̝™¢ÞÌ>èU…jÙñO—ùâmUì+Ò6uX?âøãOMdÀ9A5îб¿wëqÃeÀ¹6”{àŽÏ²º?¥*a¶Ç(XÇkþÒ "xÖà{Ê·ÿβ÷¥lÐöq¦Ð¬ð‰+[¼ïWëÔêÒ©Û[q|ã¾>¾óß‹Prt)T.½$â†OÑhæýAµ'å‘ÿ[æÖ¯WÁ¸ÌòÔ„sÏvÜþÑIâhag¬"P8ÛŽÓb€ƒÇl#æîïzÌLD`H’ÎìþèºÛ6¶h’E?”bQ¹ùŽ~žýG EÍ@HÈÒ¬á?^Ù`çÛkà cÏÝÿ³ÿ±«—ƒæ mW¼Ýñ© ƧãÎ$e ,|Cµ ºOt*êZì?šr÷} 1šÓ:P–õÁWnœfY%!jG$Ï:šå“_êgj¬ÝsÚ6‡H ð‰Î=+ (F à 7ß;ÀO_(¤ºN½8€ßÝÙä훦¨5…\ï% _cç— ñ$䱟À_ïL)hÚ¦vÎßœò‡¿=E)N3Z÷Svï/òéÛzÑÔeŽ"ÑL¡& ,‡/_7AŸÅó<ë˜ixÜpÇrf&Ú#n›Bš€A¹ùŠW8gUH[L{s¶¤4›Íîÿÿ! CÂ0ÄHÈ·þáŸvH¡MÑœ 5á½ïù5j !ûbzË)ûH™;¾Y?=QÞ)ÔaÛÖ”Ï_3™×¾q.SžÛWâ?½\¸¶)DcŲ¯\U£RT'¼òÊ+K ÀÑ£GŹ,Ü´Z-fgg©×ë4ê³4šu>û5óÏ9„¢ ãf@#䦫'¸të8“Ó!AÐ"Œ´øâ7Š|oW ¦QšhØ„©ÿîW&ùȯ¼ÌÔL‹V«E³Ù—õÏ—¿.­#I„IA’žaÇyŸÿ—i4Dqb¤-¯¥Û«î»*`U5¾þúëÿlÕªU×¶·Z.—1ÆàYËT-Ðå¥q¶Œ8Q F Æ5bð‹"¯LYžý§|O´mN’8Ê>ÇÅçE Átz¶V4Œà‡{*¢d¶-"êT°ÆÉŽóBŽ娨q5b8oóf™…ááµúºçà'=š›šÉ6e™ššB’Š„òéÍ´³æÁ?§7Ù‚¯|‡Å Ñ€X@ LüV,âØÓoç^}yìRüJ:‡=zÍ‚Åÿ¸cÎbœk ãpÎam<®Ã¡€¤—dpxˆ|­øª~oVù¼Ñ ¼Ñò{o€ß"«üFù7€û×> ŽÏ¿óøMÓûWó[ˆÞ»w/D‚d&AFqIù=ˆã ‚ßyøMâÇ=ƒß¼Þ: Âß~Ëo¿ñañz8a{¥)B)įdT!%B$!JÈã.9Ç#¯wo‡DÈãÓJK­œö¾Öhí¡”B*%””h©HyI<™Ââ ŒÇk )Ž3¦'§>ºeóænÛö®¡¡]³ÝTËêµG"”œ·ö#dI¤ÇuÿmÅ¡Ž×žö~èyÞýDâ¡©™â ¥R¨nuGÊz\òØgéL¶’‰ã¾Ù¿µ8g‘R×ZÒšÀBP.f„St¨4­*ËûÖ_GG²•”J  ,Î Þ–:ÀýšC¸_{Àÿm qzwqŒ#,p‡hŒÕØ ‰’ò5ãÿê½í±×‡müýê7thC*µ2¦\ ª×iª'øÚówñœÞCo¢-4Ƭsà ñ.ßak(AàB6ð‰Â!08àd#xœ|5˜Å s„B:‹µ6NƬ¬‹7ÿ„±X!áÆFf«h©pDö(`qG±`„""²ÖXô®í»‘B¡´DZ1±{rŸ7ét UW5§b…” ãd$ÖŒPxXœé)0”(ÀÄS—A „‹”cn#N„u8%“m€.^1„ X„8:!{ƒ³Ðø-\#MZoœ3XsqH$i¿N)¨Dµ0¸JX{c¯|ý›ß:÷Œ·]~k'…r™zmœd& $Z%q:MB€Ò "0Âa0H£C4V[*ðD Ñ@e¢á€ÖÚØkœCX‰§å&Öÿ¨›GÎàLØð®Ø{¬øÒC;R7&ëE†!ÎŒ¹ØÀVàËJ*<)I',LÍåûžåê[¯¯kc ‡VÚýÙGþ˜Í[9=»²ßõ Ï=ô(çœwÙài¾>¶Šš_¥‚c*L3¯=Ū…8¡„8 £#6ÉÓ¢C²Ô …b*LÒ–MqÊ¢.¤rårç÷Ž£0´¨2Çl˜bÆx¬œßʼ®&¤Žó‚3I6íá`¾Lª¡©c­dÚ¤©ÉÙK{hkI@¡tk‰‚ˆ ;'PN³´U±sÿ ë_àü•oÃS"Ô·Þò=„TxRؼmËüs.Xs,­éîw3ïm§’]1—ŸoÍ3Nsbz9Mj’÷,y€H^Î~8J¦)@Iu’™©€ ×,翞|?î>‘õ%t‹<±èa2-ïâ·!už RgÑÀ n|×0Û_9ÄÃÁ…X<ÎoÞÌy' qpø“¬½éEº»Ó(,‘ƒB>ÁµË`§ï⎑Ëm‚²ñùh×#,]ÒÉsO®`óæ—ÈåÒ$„¢V©‘ÉÌç¦yÆžeà»;˜˜ØKk*ËùË"ý§ŸøøÑùS“S£cãtww!ý+Nž Àšú ëL/[+èÑ–iÓÅÄX‘¿ýöwèêp$}ÐÀð ¬%‹—t1 Q +,c&‡ŸùÖ7“ÌÌRÈWyë™òö‹Oæ°™`¦nQT9,¡êâO¿Â×¾ùe/êE*GP‹ 9çEK¶ƒC%‹öÊBÞÙ‹e/·Þy/ÕR åijÕ µr@K®¿ÑkŸ¯FØè-!M3•™{¨Ÿüx‚JqšB9Eè˜ÈP(8”Ù>ÙÏóeËT8B±nxôÐB’®‰Êì BÖ(”*Låg8P8Çgƃ0‚'­¦yf C“µr‘B©ˆ–Šj- Zšáé#)²á‰l+MÑ䇢îŸÇ;æ.e&ÿKÊÅ2…b‹c¶R$ŠføÞ‹¼°¿—m ¡1ÔÂ*ÎDB¯{üq”ÖxžÇ³ëŸgÅi§PÌ—Qž„Yèlkàg•66L²¬s«Ó>ç Œ°s¼™ñÙiÒSi‚Jc-ÓÅ4Ä qTƒ2íre%ù(IÑkeeV±fÞrè Îì\ɋ۰‡k|þÑ;©M¡’!^Æb¤>僫ðçï¹‚Š›!™ðñ¤dëèÎê8…oÿÃØÈEYT@„–¨Ñú‡ =”ø57kñøÚ" /ÏD`""¡±‘Åᨅ5¬s螎.„Ö …ø»ï}ïîk¯¿þý9= ¤aäz.XÒùnîݸž­…,c&`~º•­S»©†eœô´/¡…„.¾QZ§ióZh"EˆAK…¯|ê$IymÉfƃa½Ž³–Hj’ž¤V· ÜÃÎÃ{™<ÂI8€Ì4‘Ëä ×5Q£ "ˆ7_Âj¤c ²F)#|éãB ÎEŽÐF`$BÄÐDHzÍ¥—‘NeÐJQw²|êòŘ _@¥³ôH%{„erŒ3ç¯A£´7/á„&Éôl…Êl@w¦‹RPFƒE‚KÑFK{sºrìÆ«´§,­^ {fG˜ªä^‚ѪŤ„“ì:´‹ P£œ¯ e‚ÖL”Á!ã=|$ÎT c³yL8N"T Wš¡j«BpÆFk°¡E¸x­¤Ä:ÀY*a ã@¯\¾ì»T.©|1dõ¥ëHu/$át†ÛîøCöî}å1ÚZóßÎͲmŠ Wµ³¶~îŽÈø°‚#å1z›VqÉâ9%s>·}?Áu_,ñ‰ûîç…É^VåÚ™ÓÚͼl7öñÞþMüÍ9Wqûm§ÐÙy6ísNæmŸ¿Ÿ%ÿýV¦ŠW·(ëˆC$$Q ÆfgY¹b1ý}«ÁöÙÊÖŸcAÓ"LÁ† 0œ §±1’zãZûBJpŽTéL€¨¢?Ù‚†Ýµˆeþéd›ëÔ+eÚxdG·ðÕkïà‹kÎåÒoöò“u)Z´äpi”3{NäÙ‘ 'õ´Sæ·ÞÍׯ»ŒæD’  )@ËðøAÎh;“z&(Mîç»·Ë›kô6å8kÁiŒåÇHYÁÍ/ÿ#i<¬´h<"™æƒ?2Ÿì¹§óλ¶³mªŠÎiŠLÊCIHd_ý§:w§JüÑUŸ Ý¡ùçM¯pÁ-{›ôèÈİ–’´‹q¡”dß.ÜÃåp¬üÙS ›ÑiW‹ª$œl@xñd¥p¯qýÀ}÷°ohžT\|éû*ëžü9—]q ­¸îGçÙÚ/W¶±ð!ËþÃì¡îR‚zÈß?q32•!Ò¡‘ÒD†`v3]€”„þ4›öhEÑY!ÁF’ °15ÍòKNÆK&˜äð°‡´š”n@dÎ5VϱH;ß|ð|ºz×`£0µï­}e9Ê—ZˆÊ,lyÖjÌ_°åù\{õUݳc#ühà\ÎÕðåOn&S-ávm ¶âB>ïà#_Zêþ?àm O¦ÖXÒ³m¡ (ÔªÌg0Ú‘é¸N;‰µ‡EJb°Ó9,‰#†¬ŸáðÔ(Æè‚!“LR ãØp µ5h¹åÝoçsì¢n#n|ä\žxé^vìl¦Â"ˆP„hkÝë…ÀÎ¥éëëq+çäˆÊ%¾r#4å§‘+rzç¨C±Jxä<Æwžÿ1ÇÕϼŸ’TPÉc\WÜ‹4Â÷_°Ç\£á€N65¡µæÐȘÿÔsž8ñ´ÓÏ>ç$xWkŽ‚ÿ±U2½Þ‘¨À—/KÐ;¶”«Îü÷ÿÜòè7°qf+;Æ»™Û»k<cö8…µu¬1àbÌ÷hF–"vl‹ XÎóÇo½”–T ͉,_¼çKØÆ’9+°H¦KüÅ‹¸ëÊëxiûÒ#<±m„›.û=ÎñÍ1oÐÈ„1"°8„qľëáœE÷÷÷Åúë'®¸žµ·ÝF×IpË£àQ£R¬2SjãòÐrߎ-|Þû)_úâlüÊǹ'ñ}^¸%€ž†Ã ãâÉ£6ö@;°²¡”{•rBG"™æ;÷~‡ë>ôס±˜¤n2Fr:ZZøÚOeýžÝ\~ÏßP·e>ùËghùþœ1§Ÿ=c°Æ`ë!µš¡Ô¨‰pH)ðµDIŸÈ:ôð˜(báÀbuZ[’ C%„ TÇ75&ff©’˜|–›>òNž¹m'–*w?ú07üðîmî 3U–(¤nju‡u†ÈÄ,"B8‰P`¬C —(#I¥SÜp÷×ÐF‚r”Ã".2Qg åzW(ÊA™´ª¢«&‡(Ú 'H¤:(Tf KEÊÕ õÈ4ØnGKS+­JõS$ü$íS¨W™FO<Œ”’u2´î§¬ºèíŒn‚#Ôóe¨–`¢cš ß½gnÎÙÌùÆ{¹)_çÝôÉ0“¥1p#0DØÈEkB"k ±Ô±ë¬!,¹æ=Ÿ!ÙÚŠå%pTÒ#¨´N °¨d_Z²šü2-sÈ55“1Nèé§»¥ƒm}L¸ËúSsQú:ûX2»€º«!„†šjTùm;wP7!ÿ§‹póçÒ’ib¦uGÜ|Ò šÍ^’.z7UÿÒÃÙÕ‰ ,8‰r+cžÏ9Pž‡ ìŽqÔ­an['»þvzsÝ,_ù÷-bÅ)§³¸wKVžÁ óqâÊ3˜7Ài…3Y6ÿ*IXÒ6Ÿ“§¿kå°FàBr™&²É4¹LÒ“HãÂÚª \„H)° …’g…ÒA¥Œö4×ßðU*G¶ñå³ÏÆx {Áº TÏAØÎH¹BÑŸ¢h'6’1êDL‘Å}'NÄ%‰Ð4jÐÑ,0Ö²jŒE'’Ÿ‘l;Xfrܰs¸ÊøŒaûp™)Ãàþ£!Û98Qc‹ª²g¶JX,±w<"§CœŒØ9ЙNÒ‘™Š8’”U±’æÐ˜`Nn!Ýíͤ´ÃÑ”Ê08¼›}£Ãž¾âSŸBàø(ˆÛÿî¯ÿ´–o®î0œ”)Ž}‡êùUeú]ìž|¼®RG|\ªAd:œTñÙ¯°r§hpw*æ ¥;ʺ™Ât}þ‚·&¸~5ºy_ø£,G~ÜÃ5haûm=|áCͨ¡ïê)°q{ÚÜÞ»LeNy9}ûØ©P¨ÇÂ|µy 3‘ð,Z!ö¨{;‡hœàhûŠC(³N „ŸP3±þ%ë˜êéáսˡ<ÌI —B~'Í] SÏñ–þ(þ’“æôCa+«ºæ£ÂQ–çæà™"ËÚûðL‰¥¹¹$£ šziSx~2æ5ëš©9PØÉÓ/m€DbRxxtËF–öuÅžÖ)¬ °2Ùºa¨ÈÉ…ç(Føgÿí  $ \H‡*Õ:³UM¢6†!!D|^¯aˆøˆ‹@z_y¸Ý%†Öm‚¬ýóÐVÝõØ•1˜ûØÍÛjù÷-JØ츟M'&ùûÁbçŠß~å­ÊpÓàÃíEÓŒ2e 4‰ $dªL5¥RI*5WyzÏ;í}?T¯ WM">Øw=ÏùvÞµ÷ú½g­½÷¯C8çøïlô¯=¿¶ýí üµí¿=ñJ8¹›¼ YQÞ€ú©Uq)Žäe3-vg†‹*\ø••ƒyDBî|bÕp’¯P`\òø—Sȯ€¢ÐäÆWO‚òT[žÐ¢“ìg4—–Þ>­n,3ŒLËâó†$l¦¬p`8‘2Nôvψ¶Äa囯Ä4.ÉÈe-ƒøÙr—¬0Æ­)”x[<«VMsjzÃG"©¢Y¦G*ŠŠã8snè݇Nß—Î+¢«ÄæHD"Û[ŽÉgz~ €]Ú4.#†KðÔíÚb™ßXì–n  gz Ã^Û[‹ƒÖT\_3„ôä °¼åpr:2Ù,r¹R©$Š^8{a`[wË©mC9·œw×ø‘‘§íy.‘޶B`âÏCñxêŽ`M¥Kø\uQè¡Ú)ÅÚ˜yŠêA5/r\Co†`¼Ï€S5DF0pÆa3]×Më0_½Ç>÷Ö/ví’®ïê§í´»w<¿çÀv|ÔàxÀù?cN€Gÿ®P*.ïh(vß[:nv¥V;Ĩ jéÐ ‚ž¬ã”>XK>Êpn„  ã ˜'^Å@óvìíwíëKëŸ2‡/œö·êøa èù3‚ø‹xþ3U%>áÁ†Úš{j—@pùAô(H:b1À´€t ‰¤7£å¸µä<â_} ¢ž¡! ”€R "É Ù8„#σ»°Í,2G_D×ÑÝ]m |笭O4±+ñÁø£«ÀsŸ)¯ŸX¨=V7aæB¹|=ráH&¤ó@:žÎØy(9ÃùXGž0ȦP”qA¡œ?éän°P D!|3nÁ¸Â±uÚžM/œÈ~iÍTþ˜Ñlaê’ãºLœxîÓåc'ªÏÖÖOŸ%N„¹‘8΃Xžƒ !H,1;\Ñǘ"PppÛ‡ÚüÐÑZ/ð]p•Ô£jñ:ݳé‘f–ÖMaÝGlË}8¿øsâØ´>\2¡TÝX3nú,¥°t°4") gÀ±°¼ &¨0ý…Ð +g¢$ƒaÛƒL^‡‰‚Šˆ(@EȪb.tÓm‘(H2Á«€Ÿƒì+F锥Ò$ëÍ6;ˆ¬œd¼|ú(ÃûÀ9g6žXRj‹\߬­­]ªÆ‚öv€ŒÉ˜!‚9‹Àôc$Ë0pè b}CNh¦ç±ßÛen0Ð IVàRd¸4J!ƒ6Ü a$·è…`˜£éáè²ð¡(ÅÕ(›0Û•Õ÷}?Çä3·ŽÍŸüqûèÒøÀƒm[0t*]3>¨}VqUBèkíí² ŒÉàƒ OΞêCÛÉNôæ,$ãgµRÉl;{¡/ðÒ :㦤Ér‘¬¨Â€_.[¸îŸ?‰Ä[ÇQwÉŒ)X3›Ô8O=É¡ÿÎ9çXó©/'²û¶ \˜Sã¥S}?ä¢1µÄPÃ+¡^´nEg ByÔ²vÅUÿëfÓ͡LrÈ8¿Q&ÉaµX²ËJ›HYXd‰(ãžTë‰ ©}»?Z¨çî¨×D‚ŠYãPYê†ì¤AeHläóx‘¢"Nµœ:Ô1â¬~±ÙÜ“|ï .{\~ûý>ù:)Ú¼w}èÍ•32ÃHE5lÓ®Ã&ß×±V<ˆ)¹=p\.´í9‰¶îŠ`Žp<‘.¯ßGf­¾6G´Ãˆô?ž‘‚ÃíG¶›6Ïcê´tt¶9uuåæ`o&Ü×õfs9‰¶ KôÛjÖô ÍæLBU@·u*BUHÙ$Ô@Ê‚¾Ù=™ä5 ÃäÉ£IŽì%‡úÞ&¼Ùn)ªä[,Û™ääZbÏþôýw]ÿy*ê09òµ¿‚ÑÞ(ºm§»1ØÒ‰¡è”í3f¬ŠÚS¯›•´¬íùl|“IÈH[óÃÈÜ®r$§‘J&p®·\Óœ:…¤E*´äóz»Èùš1¼¾t®Ê¨Ä@(àÀ&ÉH%‚e“×/Œ0cÈùà î½÷ÞK ªåôŽ9³&®½jVÉÑí)ª@¶¤æ‚C4t¬?þ:vÂW^@—Tƒ@ã4Ý3¦\‡õhÿãH—eÒä©ý;\¢ @€ÎžÝ ·Ë¹M30އ¢yHÖ#…Ê ‚u^fišžÞÆZmèI$¨1ÄR™ñd ’¡CQÜ(tIsû5ŒŸ²uõƒ È%‡ü{ÆÜŽË'DÌ(+öü* &,Ãá6²Ôüœ[¨_އ3ÏþÂÜr⼠‰üF,ª&6Iw÷ΟiÝëØÙèE·A àÂÜyK!HŠ/ð¯Y²xñºpeÕ\—[õYŒÂ$Bâ9]#1Ø‚oïItîFiî4TÑ€$+ð¸”"—b5ÕÉñP?7.àÊIY„sŽŸn|¬qѼyoš¶]^^F× Ã0a[8wà0‚æ#G0àHl;±÷ôoÞÖ‘ÕFzS1«ýðëÜ­¹ÀñÛB MÇS‹k®-”ššýccÄ{òy½tïž=Ù½»÷¶¶¶ž:LJrºž© \Sèý2ó”êÙMXxýj”ÕÔAëoEàÐ(4º0bØ8Ù—|r fýËæ#öÈv¿Sõ.«n|ôqœç::;׿Ze0›s.*ÈÅ#Èå’lŽt2öJaumô_îú²YVQ Q~'øÉ“'’ —ó‚‚’†kV6=)PaöÆŸ>röÅ—_þ_Édr€6B¥¨Ï4ÃÅaÓâÄZ"¥¦T±Øum¶¢§}7:K«P{èZó} |'žBhWf]¬ äA¿àrLf¢¤D©@NMR¤Õ²8„;(T‘#šË°E˜ù¬é0~$J,sBÃØ?p6gÎ\{í*N(Y±ú†«_|gÿå¾ûïd`pðYJ¥c —¬To½õï&,]´xfEu¹Ë£)6—ÄS±gïÉ?ñ#4‰€ZêB_d»‡Æ7aÆ'ÿýž02¯}G2$Ó¶…4€÷¨„— àʿÿÐ,UñyˆÇ(Úè, Ô¤°s:˜e"éF>ÛO’æo›‹ï¢¸¸kÖ¬E6«¯¸ù¦›^þù熾û½ï}›1öËÅW­”þý¾ÿùù¦¹³–SÀ€>ÃÊÔ«¢ÃḗDžñ"G8“Â;‡`ÿk›ÐtÃz›sæíÝÝ­ç0Ø Q® 0;¤ˆ®ÊÝn8ê,— ¶"»dØ‘oh„¥A;¸Ç6»ZÌ›û­ÜpãMðy}ˆ'Rõkoºñù—^üåà¿?øà%IÝòàw¿»âŸÿù‹S‚ €6]F s E€„£¸“_²ÏÝãÜn¨’Œå3W pø¶mÝŠåW¯5ø·vZ][çʈâ•)ƒ" µïà’3¥ãBðø ŠA¸´R8Ü Ê  ›ÐŽw`(T,Rݦ„þî"¤**ãdΜÙ?mooÕîà”Uïæçžyö“k×~ä?$.?   G€<†¢‰DÄJ'M†ÈU3DZ HfNŸŽD,†_½²9³ææ5Ëêjýwžnß÷€¢(W!Ðúó|@KØå"‚;yÐè„ìY «žó)¸Â%•—…¢#ƒgCE¥ï:ùå/6aõk>U[]µìŸøæ·Â5S~ól\·zåìbÎs @GŽæ¨Rˆd¿Ž¶hܼU ‚ „ŒfÆá0'MÆŽí;Ïn~å•äúÛ×Ý£ÊÚs²¢œ£”^v*PÀ¶ǰ쑼ÅÁ¨.*€¢ÞH°ÚŒ©phpûdÅMM¸+&£s-‚ ªën¿íî­¿ùÍqÝR^¸ókßg«VÌþpŽAΡsŽçÈ1 Œ#ß“åï¤M&ÚN|µ,»@©B•Qñ„pJà09=[?zÛ”ÈH,Æè˜ºº;5Mç:Ïœ¾<„Äuæ8Œ÷d-nXÌÀ°QÓ¶à9DŸ†B ‹ô¦bEÒ’±8þkù6}Úõ5µÕc÷8òÌÕ7~<;}N“kGfã|ˆxá€Î8LÆa# ìÒ4õ¹ÙHMW=.p‘ƒR à °,†\6¢âî/¬~ùÐáÃû'L¨¿C×õ@<Å©“'.A>ë0‹±î¤áôÚpÂÊÀà@´t«ŠPÈN>"+d’5Ô‡ÚÊb˜6æÍ·np`0.»J\uõ uK§º¤rùè¡ ú<>*Œ»‡I( ‘"–±ØðÎæù/ïëýÊæ­›ÚÕZQ]ƒŠpˆ¿\òŒJÈD³˜¶‰xÎÎV4^;80ß,ð‡$Q\BÈåoˆ)|§ÃáŽÉ£yv.ŠbÞ0y™ääíî³ýÅáhM¤†Õxœx'O÷{ ˆ40pH`0zö´aq†i ™›ÿ?vÙÅa+Û›n0mƸ͹K¹ªJ\N „ØŽsy£?¸ê4ã2as{³=’q#%94¢@ "•AˆƒiôcÒô&ÄEE…A¤EH¥lùáØÛ2@LM\•0ƒEd Hp`€ÒÑÐ8°àÀ´d NùŒŒk΂]ƈ5ž9\tNÀ ¼’ÀòNq*•ÞCéåŸþÀ÷ۘƒœq6šg?n9Çr’ 9Õ ]Va»\à.ðºA\PTŒº[î€ÏÃçuÁ£‰ˆ¤,pJ Q²¬B-p ¸ßÁëƒèqƒhXž0–Û Ëå…©yaÈ>äE––9Ë7• Z&`™Œºƒp±jyTŒ9sæ¬ÃÛqÙÑã}¥5‚/íHÅ™ÄwžŽ±{š;º»Lo¼r2ô`ò…%pÜn83V¢(èG Bç™3ðJ64… wÄ„îpè6‡#JÈ‹nª†ËÓUÓå‡éÀr…`ºC°<…°´ l­ÔÆ.;"Íd~¬e#hN0—µC” 4&ì.‰DÇuž9»KŶ+à}®Ç ˜=œŽ­Ñ¶v¥XF?ðÎ=óæ-h*0¦a Äš)PŠY3§ãׯmE|b%!Úº ˆBn° #7ê í £ªîèÎá8 AÁP³ÌÇóªm80òtÝF.k£6ìâ%Aê~aûA’Ï?TyôéËÇÞ!Á’Ct¦›ZãÙÕŸõ =³·ÿ³†ùªsÇSyÆG@Dà ãp¬ù(:ŠU×— ²Ø‹3½Yý$I€ SP‘B(! 8œ)p8צۖiÉ–Å,Ãp¨ž³Y:i¡À'bêx?º:O©{ö¾½uhhp‹mÛ „@’¤+à"€T9¾¾¬¢²zAyeÅx·ÛC9Œã'NaÙ’E˜2m&ºú:»3à„@u‰PU’D@ JÉ»iÀ9c¶ ˜†¬nÃÔHhš‚à$ñØãOáØñã­ïì{ÎO7þ,[_?yÝ€ÍlŒ[Éþh‹ À …()8ٗ͆«BÛr#™ž˜S¶àÂiËõÙZ7˜V”úŠ©¨‘óçϧ~vºCþô§uæ¬9úh;—A,e"—%P¢4š „ŒÀlÀ¶LÃi2(2AC“ê}HŒôá©g6aÉ’%¨Ÿ0¾qü¸q»««jöÆâ‰Ÿ8ŽÝ!ÐËK?¹KŒcô-5.ûªPR^¨ˆNÎ#©6p­.–*Š ¸?kÊU‡Ož-î9s\++ñmøè꺫W¬ܾB Dlô æO›0,~QM"à` BáQ”iSáWsÐÚÒ‚>–ܹ}ÇæG}ìæ±õuîÝûÞBÓ¬&„þôéÓg×pʶO2å/à"ð‹bXãâ/‰…~äw«R¸Ò#—¨Ò×-èL¸›ïJwŸ* ‡+V¯Y{óúÕ7|¤lÊ”ÉðaØÒY¹¼Ûf PT^—¯‹‚;:ºÏŸÇ[»÷âW[¶4¿µkÇW3™Ì‰¦¹sïzøßÿÚ[·#–Šáº˱lé v¾»û+µÕÕ? ¢ù âåµÊ^´ªYKQå•aXn1±ø¹®l]PI)Y?nüª .ŸÛÔT5aÂ8RRR¯×Y–Á8‡žÓÇÑÝ}ÇOœ´ŸÏŽ  ´ ôí×u}?€ÞߦvþüyŸyêég¾z`ÿAñW¯ÿz6Ëï=üH‚¸·o`覉 QIüÓ!\9’U@¼ß×DŒÂððЀѭ€€øÅÏûõÍ kÖ¬¹ó¡‡¾÷Ù_¾ô2‡† ©*bÃüÓ¿€òòò³z/\3yâ¤3‚ð§Aø \ £¦|ñÎ;ÿí _øÜšÇžz>—Å…E8yê$n_· ãã½½½×4N˜pˆþ w¶Œ0-?þÑÞòêëûn»åŒD#Èê9,\´/¼ü¼s0P]Y±£µ£}™Ãþ¸Vða€æ¯ãžï´·µ·Ýzó-èéëE,Ãò%Wáí}{°m×.OuEõk­-m+û7Þ@Î0Œ}Ÿû§Ïß—I'zV¯ºçÏŸC"Å5×^‡öŽNlÛ¾M«®ªxõØñW;ìýÓüà ÉX|Ûgþþ3÷ɲ]²dZ[ۉ↕+Ñ?4„{öh5U¯>rx%Ÿ¿`|˜ÀHOoï–O~òc÷•Ó šæáøÉ“èÂÕË—#IàÈñ“®šªê—÷îÝ¿ä½ô;è8Ýùò†m¸¯´¸(3kú ?~ }ýýX¾|â‘:;O»ª«*7ïÜùּ߇ð·–m_hki{~ýÇÖßW f§LŸ‚ÇO ¿ —,F,‘ÀÐðHAumõ+;ßzkÚÿýìßQ 0MóB{[û¦Oܱá›A(ÛÐ8 ÇÃ@ΟH$ŠT2Y\o~ãÍmÿ&‚(BÏÚ:OÿbÝúõÿêq)éñãëqªµÑh ÎÅàà0òù|UUUÕæ;w•3JdQ@VÏôt>ý‹ÛÖ¯û:OVWV¡½ý4ñÌoBw÷¼!ð?ÿL;(Vx[¿åIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/hexedit.png000066400000000000000000000136511217176075400233550ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞpIDATxœå›i”\WuïçÜ{ëÞšõ$©Û–°&"Æ’–C<ÏF'D1ÄðL²ˆx+É‚„`e‘ÅøÖ² 8Ï6± `ò06ØxÀ#ز,Y=VOÕÝUÕ5WÝéœ÷¡º[²-ÙøðN÷Y]ëvÝ{öþŸsöÙÿ½÷ZkþnæñxÈ=wßÍðîøÞílÜ´‘w^õ.?@Є€º…HiÐétøñ~Ä›w\@ÿJ…N»Ýù«…ùù7þê3ÚÕJõÑÛ¿÷½;† Çâ1”R‡x|ìË~\8MJ‘®×[7.¿ô²KyóŽ;·Ÿ³ýÓ_ÿÚ×¾õÐþc† †aßqëÓ^ASJ V«ÕŸ¶šÍËßóç»xóŽ(¥˜™žAk»ôÒËþê‚ wìŽF£—ï-û;@ãD­ûöí»ï™=ÏlK$h¥ñ<âB‘žcï3{yfÏ|Ï_›N§ \<%øniZnݺõ¶5k×®ú³]»€{î¾›;ôCV#¥dll”‘áFF†)KBJù­uøìñâw€¥ÔÕÅbñÆ-§Ÿ½êêwcY3Ó3œvÚß瑇¡V«†##£”ŠÅ•{…ŸÑZׯ«,'!$a~´0WøüÖ3Ïä;w†!ÓSÓÌ͘¥Z­:<÷ÜsÌÍÎÒît–î,Ù/û»Ež“j¤xž÷ùé™éÏŸwÞy\õîwã>³³³,.–i6›tÚõ:…µj• —gXQº“÷U {L2“F/g )£­Vûæù¹ÂG/½ì2Þú¶·Ñjµ˜™ž¡T*Ñl¶ð<Ïóh44ëu¤”˜¦‰”­5‡96Ÿ8&¹Žåæ£DŠUõZýÎÅÅòÕ;¯ºŠ vì Q¯3™Ï3W(P­Th5´Û-õ:­fÓ´ˆD,¤ü­"^»aÝúS^©l'Ðt=?)Åi‹åÅ;|ßßzÍ{ßÇÆM©V«Læó êµ:¾ï†!õzr©„ C„h7óGÑ:kÆNàó¯DÊã€a–! ÀÓZƒ^±ÖÛn·m{ð×^Çš5k¨T*Œ1==ÍüÜ<õZŽÛ¡ÓéÐiµñ}Ÿf«…Ûéàù>J…GWkiš$’É‹ø]ð¯}-›H$þczz*¦µþãH$²(¥$¸¼P˜½¹··7ýçï}/™L†r¹ÌÄø8ÌÎÌP((—ÊT«UÏ#‰ ”¦Ñ¨S«Õq;.¡ »´ÖX–E2•"N¯»ôâKìÿ{×OÜ“ À—¾ð…MNç{{ŸÙ»uaaàO7nÞô­Õ_ÌLO}ÃÆ 柼ç=D£QJ¥ãccäóy&óy¦¦¦˜™î‚Ðj6ql‡HÄB)E§Ó¡Õnãz.Aðb´ÖDl›T*M:"•δ-Ëò_‰¯€ü×½¥X,Þ<=5Ý7™ÏS,gÎ|íkoß´iÓÇÇFÇ?wÖÎâïÚ‰”’b±ØU~"Ïäd~„ÉÉ)ª• ¦iâv\¤(­ ÃÀ÷ Â¥Ô‹0M“D"A6—%•JOÄoû×oÿëá©â‰à>ù©÷yžûõ‡xÐj4h­i5[¹l&sk©T:ï‚ /à²Ë/`a~žñññ®òù<ùÉ<ù‰<ãã”J%¤”ø¾OK·R²Ìö”R/R^kM4%‹FÉærÄãñÏßxÓÿôJôxE|çÛßþl~büSSÓ”J%lÛÆu]‡†œžÞÞ7žÿÆ7rñ%—0?7ÇøØ8ùüùüdwö'&˜Ÿ X,’ËåPZ“J&Éær4 ¦§¦ð=q˜ã/‹“ÎdˆÆ¢X¦¥“ÉÔG@ñ•*ÿ²øøßÜDˆ›æçæÞ¹ûÉ'ÑZ“Íf©7  qée—òŽ+®@ ¸ÿ¾_`;†!ÉçóL,ÍþÄÄù‰ Š E~ïÌ­ >½½}(¥ð<¾þ>~½{7^ÇCHÖ)å’òi2Ù,¾ï7Xt—4äía‹þGÀõúЩžëÝ655µm2Ÿ§T*Èd2¦ë7lØÀÅ—\Ì»®z7ÉTÏ󘟟ãç÷üŒR©D&›a®0·´ º3?88Èõù‹å»ŸÜM³ÙÀ÷|ß'O088ÄÈð0h0 ƒx"A*&N“Í妇Ÿ;ðNÇq>&Í€üŵçt:Û&''‡ ³³T*•·mßvQ&›ýË´þñ’K/á­o{¶mÓl6ejj 'e~~žÇ}Ûq˜+¨T*D£QÎ:ûlÇ&•NÓq;´Û\×%ðý¥cO±"(­H¦R+Ê'Sé=¶í¼Ck5|<”ÿ­üÛw¿û'•Êâ7GGÇâÕJ…V«õïoý£·îú£·¿ý­ô'kµ*¯Ã°mß÷åÀsettŒBa–B¡€ëºH)BJ¥˜ÌOðͯƒþ~jÕ®ë:,Î/Òl6q¢¦e‘ÎdH§3$SÉ{-ËÚ©µ./å_€ë?ô×«ç …/?»÷Ùx³ÙÄó¼˜*Ì~êÁ8¿^¯ß¸X^¤T*ó“ÿ7oÚq¥b‘Âléééncx˜üä$¾ç­Ã0°,‹z½»äMÓÄ÷}ª• ;¯ºŽùù9þ÷—¿‚,Ë"»j©TšD2y‹aïÕZ·—Há‰à‹_þÒìüŽoµZ­ëLÎÎ|  0[Ø!„ ’J¥(—K|û¦ou —ç188H±T$ŸÏãûB´æétšD2Ûq L×óð\­5·ÿçRY,ãû>ÐJá8©tú³BŠ¿ÕJëeåÃ¥ãñx`ñ’[À¶#ÿË4ÍÙ7| °|íé§ŸÒý«yôᇩÕj$ 2Ù,©tŠ_ïþ5SSSX–E+Ê/ŸåÕj Ø‘­f“X,†ïût\—§ŸzŠV³‰‚ °â |ÏS^§}W4ÓŠ.ÇÐ*¤¿¿h4Jè#„Ê ÿqë­P8ôÚÏî½÷©3o+õZz½N>?çzlܸ‘k®¹†Ç{Œ§ž~zÅ¡9Ô‘QJQY\Äqœî±çûè%××÷ý®ãj”R8¶MIJ¤aÈ[l'r¡c;Ïv}MOOO÷»Ç¨üo`¹}øCmî{öÙm¯ÃYûß" ƒZ4KùA€ï%¨øöìÙC:æ´ §^¯s¤~»Ý (—Búûûqçˆ<~9¼µê ÄG±B259I¡PàñÇM»Õ¾9•J9Ùl–ö Àþ}ûϽªR©ðä“O¾ýsŸùìÎX<öň!bG°,ËŠpÑÅóûoú}jÕ*³³³dÒiÂðÅ|~™Ç§2O9…µƒCÏühBÐ××G2™d±\æÞ{þ!øF"‘èòCú àÿÜzËîýû÷ߨn·™žš¦^¯}9“Éì5Ló¿-Ó"³}ûv2™4óóó€ ÝnS©TèéYÕõ÷Ù«Ë<>•ÎÍdéíícÓ–-7Çã‰Ï(¥@k”ÖA@:“áÕ¯y «㮟ܵË0OÇqâñƒý„`ÆÇ•RÃóóóLOM÷G"ö?­^½úCétºtÚ†x¾Ç?ÎØèBt­x,çMo¾€5k×®°ÌãÓ™ Ù\–Þ¾^Š¥båþûïûçz£ö·Rʯ!* ‚ÏóˆÇãœvÚúúûùÕOpÏÝwÿ]$ùÀ²c%ŽÑ18*Œ–U¨>V«T™ššbq±|õÆßïDúÄø8»õ$#Ã#Kç¾`ݺul?çöí{–áVŒ¡ãDÉd³ds«èéée"Ÿç±GÉÌÎÌ|½¼¸ Ãð/Û”R¦ëº´Ûm2Ù [¶l&—ËqÏOïæÁûøŠi™—û~7Š|›Êßvì›f¦§Ùý«'ùé]?ùXe±²n||œÙÙYr¹¹Ü*¢Ñ(½½½ìÞý$Ïìy´ÆZkR©¹Ü*zz{å©ßìFJ‰eYçi­¿XkÔÑZïò<ïç Èår4›MZ­ýýl9ýtâñ8wÜ~»õÔ¯ó]˲^ïû' €OÜð±Ø¶íÛÖÇ jµ¾`Y«W¸ëÖ­»ipp°±m Ã`n~žV«”Ö)°"R™4Ù\–ýû÷³÷™=†yè‰p]†¨7)廦ò“»… QY¬Ðl6:eˆÍ[6c·ÞrKntdä6×õ†Žq´çêÇo¸!®•~ç{ë ³…Wu:5Zë!!ÄâƒBÐj6[ÿ^«UO¯Vªø¾h´†d*E2•bppPɧŸ~ ˲·;ZëK¢Žó‹x,¾>‚Ÿ½ãŠÿ±^ccãôõõá8»wïfdx˜¾¾>®¸òÊ_:Qç’ÞpCý„p¤vñ[þPÒqœÀó¼x³Ñ¸¶^¯_Ûl6OWJ‰D2IÿÀ™LfÞ¶íkìßÿ‰áÑ‘s}ß?RÒcRk½#ØûuZëŸîºæšžâÂÓÓSôôôâz.>ü±xœ ÿàBâñøíÕJuç¾ü¥—í3—üáEضçy4› õ†©´Þ–N§/Ëds›â‰xÉq¢ßp;íß,ÌÍmªÖj÷>°Fk}$+þ+)ÄEéTº¬µ¾Ð4Í;¯¸òÊh7qZ%“IÓé¸$’ bÑØò=_üÒW¿òá—+û Ii )i;ÎßY–µÓ0Œë€ßxž‡Rê¹\6÷žSO=µóBž ”" CÂ0ðn§C£Þ T*±X.SY¬P­T§T,]ùrå<©õZÓÜß>õ”S×¹®ûÉB¡À¹çœ‹‚D"ÁŽ;øþ÷¿b+°º±Aß÷&‹aš&¦eaaR.—Aëý/W¦“€ÖšÀw1 yÈÑǧ6œvÚ)Ž{ÍÈȦa`Û6çž]t1>òJ©•ï/G–šÍ&RÊ¥0›$ ”Ö˜Ëy¹rô")qÈ,˺nËæÍw—Ë”i·Zì{v§œ2Äù矷²EVî_ÚFz%ƒä¡–¶X„ל¶þUï{9òœT„+3·ÜѸ‰xüêלñê_‡JQ­×˜™aß³ûؼåtÎ=ï<¢Ñè‘ë–¸‡øø¾GøŸ>ep°ÿhe:I¤”„A—ä¼°»®[L&“oí™g>µjUžï366ÆC>hN=õT2Ùìa«D:ž‹ëyøž¿ÜWû~ðgG+ÙI°Ó0˜™šbtdøˆìMJ™Çãööö¾võêÏLŒOl+‹LOM­,{Ó0º®õÒhw:¸ž /n>ZéŽW¦i†awoÃJ‘„iš‹ <·ÀPJ}¸!?76‘è]µŠj­JµVÃ|š&Éd’3Îx5fƒÑ‘:®{¤ç=y´²ÆÆÇiw:ô÷öbš&Æ’µît:ŒŽ²¸Xþ­Ü]Ñç8κÅjuÝÌÌ óÉÙLz%ÿ„Š5k× …dn¶@g)Ù²ì@-Ç€yàŽ£•ý¸ðìÒìNä'ˆD"X¦EO.G½^ﮊ#(ès™Eºm⎃DÐñ=l!‹Ò›ë#J2ž£R­0´v-=½½¸®K¡P`¡X\ã+År©ð¢ÁŽÐŽ« ÐZãº.®ë’J$ˆ,•¸©…J¡´F çyÔš ;‚ah©!Ž#j;Ì/,P(Ìa.e˜ÇFkÍÕW¿›F³É­·ÜºGHù//Gæf»“±üžÀᛦ›èø^´Þ¨_"…‰R˜ÒÄ4 ÐËA›ÉéIB¥°L“ h4šxžKnU«Võ0448hÛöÙÀýG-çñ`ƒ‡[ÞkˆGã(ýÒ 5ŠåÒ7ý x̉a;ŽÁ‰Dq ;%bG˜ÊOQ«Õ»asÓdýºu¼þ¬×³wï³¾F#»‘§1­Õöûzháhd?a~€ò0§Ó ¿#¨Ökïw]÷ý¦a ±b̤-$–a0?·@µZ_ÙNAÐÓÛËÿüà_"¥X©$ ƒ€0Ö‡AxÔ¬ð„­€T"Ioïá’#W4”R¤ÓéWÇñøÓ{žÁ² §ë·#61'J»Óav®ð¼Záˆe1ÐßÏÚÁAÊ¥ÒŠƒ¤—"PZë§µÖ¯{ìWO¹Èp©0PkÔ1M“žä€5Àhã8Äbqr™  1 4x¾‡ ÖÒ{GÝ›—á ‚€¹¹9¤hÝ'° „Ö›µÖèV“¿d;¡ž`¹²ˆidÒéCA8”Ùàû>ívÛ3M3@똆nuh÷Ë2q´½cKÊQÓ4­õ€p©ŽP)uè ˆ¨0ÜÌï€ùR· #›É\ª‡Hü ÀÃݦiþ²Ñl~¸ÕnqÐxè¥Bw†MÃ|,‘Hn—R|/ Ã+à @i…ꢶòl!óÅ…W|'%°P.áù>r©°"®€®ç–eµ|?XÑÿPû!¸ÛÈת¬é‘H„ ÑKŠ\]¿B Ùw4²´ÖTjUú#–0 ƒ`©¼- CšÍ¦PJaÛ6J«•XÁóžFi%—d7Àâ/)­@usZk”H)W!"€¯`í_€]»v‰x@ŒŽŽ*Ã0„RJpÐÃY~èQ%ÉDRÆbQê¨.®×­ tl)ºÕ¢RJ¤?w«H·õärÙûUê%hîqIi )7Ù‘Èv`¨ !*ZëÎQpãM7‰õë×˽{÷J!7n´ãñ¸ãù¾í{žÃ0´Ö:T] ”Rw‹¡¤Bˆ –_Uí¡©Çãq+‹!ív¥†”[”Öý¾ç±*›=”ؼ°Å€³h” ðñÜçźWq¾”²¦µžÔZ!&µÖÏ«(?"[6oßýÎwD»Ý¦0WpÚ­N.÷†‘UaÓJGèžNB¡„Z²B|ÄRRTH!C…šz£q^—-‚±ÑÝWisJ©Ü‹òb…\¯0¿ °íp;–ÒZ‡a¨<ß Ã0<ð ÓˆªP•”R3/Ôó°ø¾/î¼óNQ­V(‹ªU©dr]£Þ8¥í¶{Â0L6!&`Ðõ(Ï/†€RH‰05D»R­ôI!j†aR0„”†è¶•4¤$bÛX Ó0AA£!»ñ­u ”òCvü hz¾_õ}¿î~Ë÷‚Z¨Â¨aí¨ít:®[WJ½hÉ€_>ôxâ‰Ç…ëzÒuýh2™XU¯×ífZ§é.Ek©/ƒ°l–•×€ÐJ˽ ’\¬T¦­æœ! KJiH)LÃ0#†–Ò2LÑRZBÃ0Li™†!¥!Ã0PŽÛ |¿Óît„B‹f£Ñò<¯„a+ C7T¡«5àmÃ0ʶ™Ñ°?‚2]×âÈ|æsŸW_ý§ò®{~HàWD£Þ´‚À‹6êA¬Qo˜h-À[RhYùƒ«à Ëmùº ëz Ïõýÿó>‹nmXú,„R )E×´Ö¨V†*Ô]™Â¥î !;†!›h*Bˆ?ðç¿SÐZ×wü?ä–£0ýjIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/highlight.png000066400000000000000000000060621217176075400236700ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ ùIDATxœåšyl\Ç}€¿yoßî’ËCËk©cIJµbÓ±ªØZÕQ Kp[v-#íRÓ¢EM.âT 46Z±(òG¨Û (šºn¢Ø®•4Bb§)R+¶)Røà†SÏâ{6RÊVÇqÞmðp›Æìq¯‚ ¯»óäqOFŽÎ$<¨/ìáÍ$¼žé}û·‘¬©à…ð½‹þ ç.^m‰LŽâ8¹\U‹’ªKåáwÁwl{èOî0 i׺ ì™X¶€¡¬<çH!MGŠÇÏÃ¥žIC­fÀà`ŽÉ즫Vü¡ûUì›°rd(B ‰ ”‘áß>ð=Ç¢&•æÐÓGøì³‡ÙÖFúF.KDýXüËð[±'ÞÌÞÇ%/E­ (ulÊ|‡ ÅóùÙp–ÌMƒ¬aÉÜÌHL÷óĵ—QÍ!|¥¼ÐRˆå%[…¾R¢åR,Ø_x¸¶Eu*ÍÁ'pààa¶lKC<ªAtv3–•~ðÝ“ÒwÚF3fÝ«™GQ"i~NÞ :nG¸Ö;ÆÍILÖ$“1Èdrd29&26Žqƒmeo!ƒ1¤Ô0ÝŠV'(;V¢e‰kú<Aàá9ÉÚ4{?Âgž<Ìæ­ù3®â€aZ@D…{Ó•‹ŒüÖqK‡ßyóÍH„ÿ¢ëv­OòœxƒÝ|šHMšMÊ(ƘÌ̇Ïd³è™ ®ë3è=Ì–ò6qâ mÛGu]G( ¥ JË’(˜Ô8'h»ØL´dÇ¢ðB¸ n«Ì_îf»~–D²‡9ÂîGS›J# Û̯qõc&¸åÄ¢¾ùê¤=ßûš®ëBA¢4AEe¶apa Ÿþ˗ɽ‹© V‰œ†Ïu¨¨«f×§›æ_úuªRi”бòS]¹ƒî,ØÕ¿¿òJ<‚¯†±y¼e3Ð™Þ ½ ]Çu²™o`¨O`x›É̓w[A‘·s”UÕóó¿ðdhhd6|èA`ýƒTâ/(Õ{Íò-iòö‰MI6ïÜMeuªtðlsÃOÅôž?ͧ¿Ûéžìµ/©öA©Â•¡ÿxâ>voý ®9Ž®{¸æ$Èp$Œ7üá¥Þ÷Oìú¢I,§Róˆi QU¢àâ9&Be½ÄY2¦o…þÆm¿úí¾‡ÕKcQò{_@Ä(‹°-þ·H§§rï5wó^›ö´Eu‰hÄ6шÌߢŠ6u˪æo[µ¢úh¡~ºN+:N-ºÕUgþ§©³ÚÎF5¼hQø2ä:…;òê' ¯‘ByoºÒ0=®¾Öç«ý³áTaaÈ{œË©—ß(-¿&)}p ¢UUEósø¹ügïÀ KQH`p˜5À,fF% Ÿ‹ŠB^Ö|êÀøk¨Ê/Æ EleÇ–W‚Šªs¶¸W…Ž&‚œ‚À^CÈÅB° ¯S\ (*SùY! ¯þžŽâÕùŸ…ò†Ó,vlÿ¥åDà” iÆ Xï-™ !ŠÞ‹9Ÿ ŠêüÞ= ã?ÚGLmGÊ<|ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF¶IDATxÚä›yœU™÷¿çœªºûí½ÓéΞtö„ [FDAÁQçåupFÅŽúŠŠ¸¼‚¯ƒŠ¢ÉÂ"a Kd! Ù×N'ÝI:ÝéîÛ}ת:gþ¨ºÝ€¯¯ïèÇ©þœ¾·êÖrÎóüžß³œSÂÃçÍúS/¼òÊkÅùóϽ½½©õë7Κ:mÊt[É‘©TÅðT2YéißtíîÖ¾n?ÒÕÕ²uË–·.^páÆö‡ ›6m6cÆŽ2;wî&U‘¢·'ƒÑzàþJ©?ª/üþ鿌ŠÅâ¬ÞÞÞ«Ïš7oÁG¯½f\2w …¢ÊårÊ-zRJˆF‹Æ}˶½öÇ‹[¶nÙ¶{×Þe®ë>lûk@€ø¿5]yíÙï[xé­½wþ‰h$²jåJëáÇë}yùò¶=--G€ à…êt€Š9³g7\rÉ% —]vYjÒä©þ–mÛû—>¼tÙê5kn¯®©Þú—DÀ-€…¸rø9gÏûƵ¹æzéyöïº+÷ýýh°Ø z€ì‘D€P Ôc§ÞþÍoÍþЇ¯°ßxcMß½÷Ý÷£Cíw¹¿ˆ±lÙ2ýN'>ÜAMm-óÏ?ŸÜu7-}˜™3g2fÌêë멨¨ ¢µÆ÷}„”H!‘Rß÷Éd2tuuÑÙÙÉþýûÙßÒÊ7¿þu&ϘÁo-bDãpªª*ÿKá¿páBaI)ã—^z©ç{R‚1 xžÏ›o®Ã›T*ãšk®6sO;ÍÜù½;Lss³©ªª¢»»ß F!D:¸Â{ùÚŒ¡··‡–}-bÇŽ<ñÌSâå×^7Ýôyñø²'͈#ôÌÓÁM†¢³üýdÇÊmèþ1¿|ú¾!ò /X–Â>!ú¾Ï›ë6O¦Èõgø—›¿ÈßúSbÞ¼y¢®®Ž#G:I$“$’©cÆ+Á¨‡b PR‚êêjªkª5j4MMM¬]»–[ÿõ¾ýío‹Ç—=­¤”̘>íÿ‹Æm;‚m¿Ý ôVY |×eÛö$…lß½ã¾rÛmÌ:õTò¹<}}yFó6M ¨ü¸c'2¼ªêΘw•UÕ¤+*¹ùæ[øá¿ÏƒK–P[[K}}=Ƙ@ýéx²ÞXe¸öÚÆ-sÕìóÏ8…³.û8ãæ]Í·žèÂ[¼„;¿p9§N¬£­3Ë‘ž<ýy—þ|‰¾œK®àÑ_(‘+zä Ù‚Ë¡®‡»³ø¾AŠc±R]¡·Hï‘J®¾áYúÀO¹ñKwÒáÌea˜!–%Žû/þh„@R^ì‡CdÙwÞÿîq@>Ÿ§¹²ÄÕ—]ÊÂkþS~ºQ3È÷´ñã¯|€‘5Ú»Kd]Vl¡}Ki"–†¨Æøtx%¼„Gm„0#]ˆÁŽi’iô Ï¡í¯ñ“Ÿ/â+7}œ[ï~ŽÄ˜‹F. ,Ø1À€ÊÄ“Êç„›"¼o#(†Þ£ uëÖsÓGÏå×.E4Måðf”Ÿã»Ÿ}#k"tfp=ƒç|Ÿ 6eêÍúd †xDÐ3eûŠ´@ò¾a3@ƒŠJêÇœÂö[ÙßÚ™“*ØTÌ`ŪŽñ(eOS6 )F{eNàp8 ˆEkÍÊ•oÐP_ÇïW·PQ;ŽêŠ4c†GYµ«Àof(¹!®ž6h#ÈV … ¿¨Éä5[5„ÍQÄÂHœð˜c+¢¶Â¶¶mQY3Œº±³ùÍÒg™îéd÷¯E…pVC4®”¶B ÿû€¨â]ÐÝÝM4¥õÀ>Lr4éªNTÉf%øùËݼ¾»@<"™6"Š?ÔœF ¤¡äC_^#•$f ÊÊ?^òfˆzÊ.Jk3ÒàKÍÈñ3Ù¹f3•é8q}8ðPÂGpCÕ*\‚0b€ïDùO›œH«W¯æôÓÏ`ëÖTG2™æô±QêÒ:5Íâ5^Û“G[AJ B ÜÀâQÀΘ~é!‚0Ç C:$Rí „$+jH×7³oo+GVÑêf±£©û™!®aÀ=Š!ŽrˆWB„1Á»àš5k3f¹\‰tºŽªŠU®o^esé´$•q‹ mEvw”0F $H)ðtÀü–­ˆ9Gq» q+ @[u,¢¶£~F,"Ž…íHlÛ‰D6b";fÜÈ& G÷!­æBI¤%PJû–DZ*ü ›(K¢” HS}}G´ìkŶ-¢ñ81?EeÚ"‘d‹†‚kUcsnsœÕ­öõ0BP“P(%pö¥8yÖ54"Ð~Ø<”hRéšJÞAÒé^¾¥Â°F”%މŽ‚c‚†—€@æ]L ‰R,I&+ˆy1ê+Tiƒ¯ßPe3ÁŽ#.‡sÁQ‰6Ç‘(!(Ž}9ºÓ P<F8Úà$“XùÛBøE¤RA"Ñ2ËòCÙL(ñvÛ;‘„í‹'q²‰XÀö:$;߀§¡6¥RОñés ^Aƒ„XD!ßF{f Ç(Çå"paƒÀ7¿ìÞ´ÁhIÔŠSI¤(!Œ;ˆ€!‘à@DyŒTÊ”ÇÅ#ß÷B‰DˆØ6Zþ]›¡’ŽÐïÉkúÝ€’œc£óc®)w΄1a\à— ƒ’´gð%D#ŠÊx ¯Ô,5¨MSfxQŽÄq&B1´ï,€R©„ ¥Û 1æXb•"t1bvmÙCÞ7Xâxk/w!°Ù²X;ó´ "|%ð$"PHеÏEZ*d±¡N¹cC/¼“ !‡d„'@9 ìïË`K "¶ Ÿg@û‚ ’Ò ÂÇø,Ž ¨àAr` b K D` Æèûá5´2¸Bà(HÇ¡:cw_?–ÃR2ÒìPˆÁ§ 1˜7ŠÁc8y0uu5tí$™ˆ‘ÌJ Å ®bbßAˆÀOˆ“®"@‡p}áõãkŒ&)gi!<´ƒÐÇ‚ê4¤bp ý0éÚ¹(K"Ìq1í1`0.`â“ǘ0a›6næüùÎhŽ,º\¨s¾0”ý›P”by'$"uL œë#É÷…ž6#çE°FÏ)Ñ„Aè×KÚ@E†¥²àÑÚÖÁˆ‹&c -’çöÄPT`@ÈÀšAæ:ƒI'òú«HÄ"TÅKDmÁ¾ƒÁ`aVÆ@J ,Aƨ-°ÃæØ YŽB¹â¹vªƒíDéëËбoÊ–X¶DY¤`Z „/h¨TFÚÚè+ÙÄ“i,ð“e©ð»Ä²dð9æ– ³A%°”óñÎ=z{[öГégx2§à`§ w4Ø\T\ÊÄhL€- @9ÀÒUÈb—ºpߌ¯©o¬aOÛQ2GP=¼|ƒ’ñÁ-BÌ6Œ®TDo¬]GÕèé(5TÛÁ³í|H £-C>%Œz «¯gîœY<ÿ‹Œ¥!hwG h%px*°U£BÌÛ`Û!,mc ,]À)õbEl¬DmGpRqUIG×cüZ›ÐÕ Œ” ¯$Õ ¨Žúº±êÍ­Œ™=¥*ÌüÊššhBDx?'&HW j† **!Q ºÐ÷ÎH§ÓÌ›w:?½ç—\~ÙûhH;ä-¶ì†Ê4T¦.Ë ®¦L9fÀ~…£5Âä1±&œ'0HdÌÁ3†”£/oð= žÂ/A±¹,¤"pÊXAʆEO=K¤¾™deõ lˆÅ‡AZ< u£ …¾¬fç–>íÙΊ§&×ÓNçþiíò·¥¥nж,&Nhfêä <¸äanúìgP¶ ÓÛvÁ” `Ež–e(R O`0Æ…H4,X„ÖHmÀ’AÐâ£5¥¬‹ŠbúzAø0{:¤m8rh?Ͻ¼’3®û:Êâ˜ÂfÙ¿¶ éj¨«Ï7¬x¥›¾ûEömz| …Œ*šj*‰©È±"ÇU…†oà¼sÏåÖoý„÷Ì;‹Ùsf1w"ü¡vì†#Áq@كͲAØ0ŒáØŽ ¸:@KÑS£Ãb¨oÈç §7@À©Í0©>øíž{~IÅØ¹TÖ{[d-D¢à$ äk6®ÚÞø«ß…WÌ“HD˜>m E!±„kà(¾ Æ ‰®Ú È.Û½½PÈÂôqpú¸ ?¿÷W¼¶e7|õf”Í`AA×>ìÙ¾™Õ/,¥}ÓJìƒ{™0z£ß;†ÑÓ¸`æély}®òHU*žY³’N¿È{¦Ïxçyri«¡¡É3ÏàíÜñÝðÕ¯ÝBMe5σåë`¤RH‚ˆD¡ä&!Uá™@ó^1 EK <ð‹P(@¦7ð"s'Üpðÿ±x /¿ü*^ÉcÇÆ·h7Ƕ‰Æcú²lÛ±žÝ¯üžÌÖuTÇcœY=‚XÓx.|ÿy¬_µ“¨cضö ^Ø´Žxe’ñ~#ÓGåñõ¯Òr’‚È”1a;6#FŽ¢8ï|^{þQ¾÷½póþ™ššÎU;aóèëƒx É¡„ ïºPò«=øà¸{E¨©„9“a\MðÜ%K—²{O Ÿþô§x}Õë<òï_¡iÜ8ö·!ïið LJEiЧ©kh$‘L‹)b)Á–M󯧼›q£‡ÑÒqˆ^'‡ð9"c¸"OÔQôû‡ÞEC"¥XÌfLód¼âŬ~ùn½íëüëÍŸg„ñÌk†q#aÃ6Øw8€²…X4¼A‚㺠ü”B3jS0a,œ6~ðy?¿÷>¶nÙÎ׿ù5Rñ(•\sõ5ÔÕT±aãîøÎí KÔ1±q$ùþ=9òù~ºŽö1bd#=]„ttõ`[ .9—b¶HL[˜¸KÕ„(‡sïìÍ1‹jsÑ,èöaW ´wBo J& ;ãƒPv ® Æ5Áä†A:°¿{ﻟÞó32™ MMÃùân¢¾¦š'Ÿy–Ó§ræsùÙ=ÿ‡%¿¸?ßM_ÆG—<ò”h¨¯!×çâ²$’6ŽŒâFûQÊ¥ç`–¼‰Ó§»Ùлa¿K68”•烤i&4O%™ˆ±gÛf¾úðÌs/ò±k®âœsæQ¥d ÉñÖ{JП¯ Áv "Ç=¢·»‡‡y„¥?Æšµ¯aW¦HÊ ¾uÇ·˜5k&¹|­Û¶°æÍ5lÛµ“O|ì£|üsÿÀ“-eÏîWP ì(%OÓ{´“žRVÆÊëÑ}Ô#ÍÐæïölƦšÞXõÎ$¨Í`µÎ²,”²¨O)ú;û8â°a L¾üå/ñá>Fº¢šßÞûñˆBç‹dK%žo]ϹÞtƦ†“)è/䉌†±V‘îV\1¶®ö\$%àÀ¾-<÷Ü3ii¥ÔÝÁžÖ6dµO1“Á”4B–<ú.~€ºêz¦žz ³¦ÌdÒÔfêëj°,c|Šù<­­ílÞ´ Û7ppï>ð}ê†%XpA#ùÞ¹D5*[$ŸñÉ{Eþb玭œ1ï :Žt±ÿZZð/ÿz+ÿôùϳðêËIÕTñêï§uw ¾›Åö4/·n¤#–¡&šDÔú4GÆ¢òšÍ‡ÚH¦#T´O&€@õ¶=)½þì"òG3èþ‡¦X,2ҙīSŒmƒ›Í©LóÐâß2itUiÅ£ÜO×ÏúˆÅ ùF{$ãIú‹Ej*ùÄÕ×Ñw°ƒÆiãYüÌÃŒ›t&7¼ïýôGÓìÞ°U«Ö°¯{/ÝíG¸öÃWñȲ'9çÜ÷ðÔ“Oáº.ø‚;ïü>×]÷Qνð\FnâÞ»~Æ„ uì[’c_g+G8Ä3ç3}üxœtí]XºˆØÙ|ád‹\C"®¤ªaÊ)ÓÙÙ‹r=Þ;k*5ItÎgÏî}ôt÷qÆÜÓh¨¬eîÄœùÞs8ÿ¬ói3‘a£šxäþÇ™Ü\Ç3/¿Ê£?ÇçþÇ lx} »Ú»¹lÂ(þþêk˜ÃYgF¹îú«Ù¼î›v3ldSÏ>›=í­Ô¦ë¹²{-íGÈ›<;·—ˆ(‡¹Sư«íºú‰9 lÜù*‹¼«¯úýÙ­ûö3nìš››Ùµ{÷Ý¿ˆO|ü:¾të-¼þÚÃ,õ)úzŠD'ÇÕ[¨¬.1rJË~‡‚ˆÔwøÛçï' &+2ºA$ n/$ãPS#ˆÚïĬû(؉l-°­¹û A¡hH¥![|Œþ£PQÄóHÖBÊÊ • (äáÅ­¯W‹S+ ?ýͪk\õ¡+xàÁßÒ~ðÍãÇÑÜÜLÛ6~ñËßðéO^Ïéó®`×Þ7yzË/é3}$Ó‚BÁEKI©¤1ñ·D‚Ê-ÍÁ"I"P491ÆÖÛÔ¥-¦MŠ0¬ÖÆIJ\m¡D°HÆ#’iª°±„b IÞSQê”ä)†×9Œ&©MÁ°a’¹§ÚŒk°I+ Ë“ÍJrBRÈK2=GHl£HÛŠª É7nÿ{[·óÁ~D"É¡Ž$0yÒd|¿Ä½¿ü5–å†ë¿Ç'¯úc« g#ý(5ñ$Žg!ò'. ÉòÌ’ƒ-ÛçÓ™)R*Iúº T6:ŒHH’EŸŠä:}ŠyIJBÎòÉör 8Io—¡¿C“{L¯Pòm%F’:ÊðLŠ7è5Tt;(Ï¢¯× ²A™Ýà‰€ïJCET7Âß}æBÈ5¼L6Ó/üŒ®ž<¾‚¢wÒÉÑ`Më¹ÁêçûÂB£ ½¤F„¥fs\…BšÁ¹>aD`Ô&\0R%&¨â R€ MP7áL‚ ÂocÊçšÁI =½=¬ß°_ýâ7üóÍ_Àõ4+V¼FëþýL<‘§Lg÷Î=<þÄ“\~ÙB>sý\õþ/cYA½Êhs2'XÅEkß÷ðµÖ>¾ï¡ý"ÚwÃæájßõ0ºˆÆÅø>F{ø^ í—¾‹1ƒ‡1­]´ñѾm0ÚÇ7:xf°ä¤Üƒ¹e# Ìœ1ƒ¹§ÍæÇ?üßLÔÌYgÍ£««‹=--øžfÖìYTT¦yê™gAMu5®ë½míÐ H0Ôf¨p%ƒ\À²mlËÆVJÙX–…¥¢XÊFYá¾å ìÊŠb))m¤´QVe9HËAJ+8¦,”rP–4e÷Q6JÙÇ·Â>(e ô§¦¦–¹sNcΜÙüäî»™8a<§6—#‡Ž°{÷nÜb‰Ù³fS]UͳϿjkê(\¤<1 Z–ei€çžþ¸zY°„Ë„Õ^!$B|)°Œ gŽ%–0x¡Ki0&\Œ /dP —̘0ìÊ`üp†W ŒÔ`Âëpâ­§§_k¾öµ¯òåÛ¾ŠÞzkNÄaÖ¬Yœ~Æ6®‹å/½ÂùçCee%+^[I.ÛÿöÔ'‹)¥Tܲ¬H|"ì®(ϵ íköüÁ)ÔÑ4Æ-ŒH¡µö´–"\Ê+Ä)ãò¼™A2RaÂuMÁÜ©1ò„õïãëû~­1fúyçŸ÷‘_ß¿è’ýûöG·lÛÆÄæfæÎ™C"eÛöíôeóœ6{ZëŽÇâK×^sÕït°åŒ1Åc6Öí{x®‡[*áº.¥b‘b±ˆëºKŠ……Bþ¸:«8îm„㇠NÀ:Ò&aÀ‚ùó/|°õÀü«+_7¿ºo‘Y±òuãûÆcÌŽ»ÌšµëŒ1Æ”<¿åõUk³¸úÄøã›ïûÑW~Â7Q.ž?ÿÂh+®\µÆ,z`±Yµj)o»vï5›7o5Æ“Íæ·½ºbåÙ6ü¼v'€à¢yóæ-Ú´ykßÊUkÍâ‡Ð|Y;ví2ÆÓz míߌ†ô¡˜ßÜ<ñžuë7fÖ®[o^ú¨Y»ný€6mÚl|ãcŒû·( áÜæ‰ÿ}ݺ½kÖ®7>ö;³nýF3tû·ûÆwþæ0D•À¹éTúXþrçú›Ìc¿[f6oÝfŒ1æË·Ýö¤uÿ&0¤?•ÀÀw–-{òà¾ÖfÝÆæò+®x ˜ôgõû”N¾ñ™ÏÜøj]]ÝÝÀøãÏŽœ,Îþ¯À;ô+ L*€Æ˜#ÿϯÎþ­m’ÿæÛ&°›MÒè IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/index_search.png000066400000000000000000000527241217176075400243630ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 0éml@ IDATxÚì½yx\õ}ïÿ:Ûì3,ɲ,y·e[6 ‚m¾oI›„@–64¹ IÓ_ÓÜÛfiÒå¹iIZr¹!ím“p)P öâ[ÀŽWY¶µFÍhö™³ÿþ8gF#YÞ¡ýýÊ÷yÎ3«Fgæóþ~–÷g9ðþz½¿Þ_ï¯÷×ûëýõþz½¿Þ_ï¯ÿBKxÿ'8¥%>ÀïÞ¸·^÷ùú¥:P&Õ=ÞÀÿÇB@ЄÝÃ(î{:Ü÷ÑÜ:oeýoš‹¹ 0€·€q`Šïà?ç ¹»»Å|sÀ;‘X×Â…‹V„Ãá9ÍÍMþ@ˆ†H„P8H8Æçó¡H 6ºnP((ä‹äóyÒ““¥Ñx|¨¯ÿhÏxbäà9àÿñ»½ˆ¹o¢®ÐW,ïZ½©mî¼M±Øœ¶¶6V¬XÆš5kX¶| -Í­(ŠtJÿ¤X,²oß~öîÝÏ‘¾>öìÙ½#‘H<12Ô?p°ÞÀ{»š\ÏÚ\ nnwÉÊ®Uç5666-]²„ .8ŸM›Î§¹¹É1òšFrlŒt*M&›¡X,R*—ÑUÓ´AE’ðx|‚~Âá0ÑXŒ¦¦&š››kÿ¼§§—_|™×õFéàÁƒÛ‰Äwúöþò½ÂU]ÏÚ«6¾¹uÞ×®]wqkK³÷üóÎåšk¯¡³£€‘¡!úûûILd(j&š-£ ^4SÀô1-Í0ÐuM×I*ìé£]í UF÷FÂAÿœXlQKKsû¼yíttvйp!±X €7ÞØÁOüœ]»v½6‘J~ó×_yö}¼»ßQdWð-@ÇòåË×755-Ê¨ÂæyÍMm­M1ñâK¶pËM7I%S<¸ŸlÙDEAµ`Ë!TÃF3l4S@7,4ÓB7-tÃÄ0 ÝD7tžïÍÐXUÅýOý¥¦V2Åb¦R.æ½-M ] Ì_·tÑâõË–-ñ/]ÑŪU+Q<z{ð/>Ä›oîxrddäK»v¾Ñû>Þ™°ÅºCºãŽ;VȲ|ÍHE^/˜« É¿¼odŒUžsB.Ü´‰Û?y+±h”¡Á!Ž=Š.ðÏY€©„)kPÖʺí@Õ°ÑMô0,Ã21- Ë21Mƒ]ñ"ñtŽîÄÓŸÍ«o[†VÈN&̉ña,1$¥ò¹ϺhÝÚ5vw¯]±fíÖ­[G0f÷î}üè'÷åz{{¿ûä~ã}ÿü…:K€øÕ¯~uñüùó×= k‡¬è‡ Ò=ãÅp¡PD.¥ Š&ÞÁ·˜¯”Y¼h!¿÷{Ÿb]÷ÆÇÇé9؃¿©ÈÜò*+6ùŠM±lSPmJ*T4Ýö±m°°çÖ¶m3:;FŠtvðZ¥yM¿ÙpFÊÌOY,ÙGƒš¢ÑÊ(&(OŽSšœÀ;ºˆ.¾x+ÿí³w `³sÇNüÑ&šÛ;Éè)ÚLæl&‹6™‚Í´±¯s›p`×NÖlF3&÷¿•§Cر@M~¯qÎâqI åÇqs¨Ÿ0ttÜ'P0ǽ@@DÚôÑüÎG·nÝÚzÞ¦óYÑÕEÿ wÿžÌÁƒ=ŸxêÉÇû¯€za Õ H÷ÜsÏæp8ܽÇhZ3hE7%mÿüÝOV2/(Ñä™’ðŠ¥ôÅT‚ÂøZ!G~|ˆÆT/‘ ŸüÄm\~Ù%Œ ‘L¥Y²r eË&Y´ÏØ$ÓÊÛUÓQ²ij€Em "Y@ëlŽ  â<¶€£É’Þæ)¿`Ûö›ížòz›Ê©dÚCêÈÚí­M|ùÿ5kVqpÿ~Ú;— y²Œ$mâ6ãi›\ÙÙÅÑ,™'°´Y@À¶g±ABb]0ˆX¶ózHAAEQ^½;Ï$âIë­Wž~õÊÓÒÑ]/+XC>ÀÆ[n¼éÓ×\{MËÅü óÚÛù—yˆG}ìG>òà'Þ_þÏb·ÿâ/þbqggçºaiÎ…VhMI÷¥iÕOاóŠDý d°ÜŸ\Ç&ç’ò'§”£”£06ŒVÈ<°“%R–öùm|íOÿ;ôöôеj†e3R°‡áq˜È‚nÜt-i‰¸'hƒe9ÊÞf: Wà¢`»šÀ9GÓ´ñ¶å‘EÃ¥†/¶|ôBF ù÷î›ûÑ·,Ƥ]Û«ÀP¨ÿþð£LôôúTf2³ú’K/ã#ù0 ·K²ÄÃÝÿ‰ÿì˜)l>ÿùÏÇÎ;ï¼ÍEotmŸÝpÁ#¸úi##HHQˆx|²ÀŠ˜P3«Õ ‹6CiYh€iƒiÛØù •LŠbzµ˜#;t˜%R–ymm|óëF{Û\Žôö²lÅ 3pt†’+C8 Ë;Dæ4‚$ÙXUá۸߱ZÀù¢Ž#(BMø¢`#  š6²`‹Šd—-ËEQ4]¦ñ‘'÷°?Ü6m0Ú:jD¢êöÇ~ B² ‚oïÛ£ýÉWþäæb¡¸ù íJ®ºêrI¸Ý²lyø_>ñŸ³:i_úÒ—7lذ>‹}à…rìÌQ"gì#Ôú ¦ !‹aŸ@“"Є€9åRQ²mª.–}‹e ¥J # ’ŒSžLR¢­4LsKö§_¥½}Éd’%Ë–aG“pd† Ú°`,˜+ {ÀÀœÝmÚ6ØŽà-÷ä Øu_Þ9SQ\“`×Ì€iA^C)–&‚`YVVÅ¿z±Ÿ|tP$¸óƦÕwÞøçéË?zöþÿ®‚¥¹¬àÛ%­bõÏþ‡¦ú¥¶eqåå—Q.Un·-k÷£<ø½ÿ̸È<ðÀfCôÌ·´Æu‡Ìð=ø—m3dòY/­‘"â—ü3>¨^ð5OÚÙW§´lË¢”N`d&в)´r‘9“Gˆ†||ñ _`áÂNÒé4ÍÍÍèÀÑq82#ã (°ªBdÇŽØ‚]¸à"°úØÆžÒöÔÙ"€à‚¶ê ˜–nÚ’jX¶O²…RéÏö|û<>/¦’›»ø0ð÷@ö™ÿû•Ïl©”Ÿxñ‘oV`oÞ¯}ó’ ‰+ŠÂM7^ÇDr⻺¡õ?ñø£ýGh PîzòÕ¯÷š¡«3øWÿMÅÃhÖOÌ+Q"^‘Îi»xá½ êGCÏg¨d&° ïÀN‚ ÜúÑqæ™Ýô=ÊÂÅ‹_~|>˜?_Àçµ¥jGMõÛ¶Øî}«vêšG+‚Õ´éŸ(—öõìø³Àœƒm E0$ØØÌŸt-]xðÿö?„oþÝŒŸg |ãßðù}¾MÁ`Ï|æSŒ&FÿY×Í]ï„'Ã,š øßR®yöÕs[[X×áÌ&™A‰F¯ˆTáßÖ2Êôü$j&‰^.Rìù¢Æ…›Îçºë®bdh„…‹П„¾aGøÁ ´·,ƒPõôÄé °Ü]oÚ6¦Eí0lÃr|ÃrÝÝt 4Óa uÓf(kðÇÏŒT†âc†®%]-Š1B›ù6p3PvŠë(þmÛÿˆSSr@ØoZÖ ÷Þ{ž\&ÃïüB´££ý§ïTˆ¿ <Àœ…¥ÁᎠÄâ°„Ogu’~[˶,Ôô8Z6–KSNްX*2¯­ÏþÈår´» ¡ôǵðAs DÙqöÁ-€%:6ßrw¼U~u ËvÁ`£»‡á¨|,<’€_i Ëܾ´Ô¨keE+ååŸl†?ή~É=Ê8UD·º (×`èé=räñGúÓô¶mÛˆF#ÜzëG×ÝxÓï|ã½ö 9–Ø7Ö:‡ š%t×S~¯½Á(åÑr),Ó$šîCR$n¿ícÚûRŒÃÐ8H D£ J ‰Žà«Â%GWÕ<Ó|»¦,Û®3Îëa¯HP("E èÝPÚÕæy÷”#‚]X~ÁML•Ýßјåð±m{R„¯Tý,œB’¦§ž}öÉE‹–|¸½½Ýsá¦óùÕoÞY*—t:¦@þ „_cêÞ~ûíÑð¢"EÝCA·Þ3áÛ–…–K£åRÈj‘±ý;˜/kœµá,.¼p™tšh,FGðCcŽúnŒ8Ž—$9]Öú UÉÚö4'дáûd€,âW‚Š@ƒoöÂÝ5ÐÚÚJK0¸þüµk/µm»ÙU÷²+lÅõ…ºÛêq‡mÛ»AxÈ}¿ ô ÿë÷ì\¶lɹ‹/æöÛoîÝwà»À ï… ¨…â?ùÉO-÷iŒ”MJú{§þõB½!¤çYY*øýÜ~ÛÇÉçrDÝ\{<#c-‚?àh€Ú!9Â%GJ‚KìØuB—yZËb gÏó±¦ÅË’˜Â¼°ôð‘¿þ5‡M\°ùò+¯[÷Û€]§T ;84¦9†ì]Uó, Kt„DÂ2” ‹‰²Eo<ű,c™<©ÃoMV¯YMgG; ãü¥4OA:Š»ûEWè‚ìEÀëð*’$LûalËÂ4ŒšÀK¥ªªbš&¢(âõzñù|x<dYF,ËÂEtM«}N½w(‹QÃ0t˲´˜ „Ò,ÇÇmÛn­{}˜ØèàÛ{vïfhp뮹ŠysçÞù^™(ïÝ»·Ïo• ½‹Œn±#m°}ÜàhÑ¢`@QÓ)•JT t]§ÕÈ# W]q%šûÃ$ÓÌ8ªÊ+;P'î%‡©“\3 N¶ÇvUºªª¨ªŠn`ÛH’„×ëÅãñ ( ’$Õ´Bý¡Û6²$a¸`¦kè÷ûÑ4-¦ëúñÌÀÉøœ»ñÊ8})`à…¶%öíÝK$fÙòe·_~åuÑß¶h¹(>÷ÜsGçØUT¼ïRP0mÊ&¨¨&hh–M©T R.£VJèj‰vYenk+7nÀãñ3!•\ÞºäÚ~Ù5ŠkÊ׬–sÙ¶“Û—eDWÈH‚(ž”Ì2\D–e4U=nˆåóùšTU5]- ¾-p¥mÛ-.Š®˜Üþê+ûz¤T,rùå—âóù®/`¸'¥¶æ†Æ ¶@sèÔ>Ö{‚·©–MÁÕÐmÐlYd¥Oåê¹Y q‘y€µëÖNûûtÖ9 yÊù“eGø’äøU“ I¢("ˆ"ŽÝ·DÕ²0\޶bÛ¨î.·f°]ÕL!€,IàF³-¿ß_í~À‰Ž«ª§Là´¡õîÛ·Oëííe]÷:ÚÛ¯{¯P*ÒÐþà Õfn@&잀eÐm(XP0™9è–MÁ´™4lò†Íú&™-ññB<²µ7®Žñk.™c°¢è ¾Nø3"±Îžë–Ucý,ÓÄ4M ]ÇvC>Qñ„ëBC€R±ˆ¡ëÈŠr ¶mËå°mŠ¥’ Š"²$áõxjæ¡ÞÔDz¢ ¹¨÷š ‹Q.—;Ëår¦iºÏç3êŠlꫬªõƒÖ,ÀÄ™Q0PGëC##©tz€–¹s£—_y]ô™§ϼS3 @11Á7¿ùMžzê),ËbË–-üõ_ÿ5 ,˜Š¯ ƒþð‡<ðÀê jNø'»?cMèU{/ÖÝÖÕøY–å°–…àú¢ ÔBD,×-œBe“Çã¡\.ãT½g]×cétº‹ÅLÓ45I’ì:ÁW1ižäXŠÓZ^-$©ù\.‹išÌoŸ°§ý´POeËó>ü7ÍÝ—~ü çý³–(óƒ^ÇË.Ö ?yá_ïàw÷winnæµ×^ãÞ{ïåî»ï>î?ùÃ?üCžyæ™ÚãŸÿüçìܹ“×^{X,†®ëÜ|óÍlÛ¶mÚß>|˜¥ËWãóù†ƒS`ÑAs3’b]•î1%[næÏv)ߪPEQDE§œ«êØV]\_ëš±ûÉc( årù¸ß½¥µuÙï¿¿çÓ·Ýæ ‡ÃÑ:? þ°Nâè3ò2&Ëò”ŠEZš[N›¨Wó¾å_xxÕ-Nþèÿô‹{ÿøææ?º°K™/ ή¯ÿÎj¹Ì‹<€ÇçgËWsË-·ÐÔÔÄ}÷ÝG©T:î 8p€mÛ¶111Á /¼À‚ ˆÇãÜu×]ضÍ=÷ÜömÛ…BÜ}÷Ý<õÔSÜ{ï½|îsŸsY5Ï´/¡›SŒXÍðUw{U#ÔÅ{¢+ôê!ˆ"B%µO¡–â=r'Y–O€ööv¿ßë]ýÐOšØ½{÷Ál6«çr9»\.årÙÐ4M7MS5Móxlaj%—VÝ‘¯”+T*¢Ñ$IZw*>@½c'¯ÿöž‹×Ÿ1ÿcguE?´®Ê:¨'Èö½ôÓ‡(æ²\píMTDŸÏÇm·ÝÆ]wÝÅC=Ä'>1{ùúŸÿùŸsÖYgpöÙgs×]wqÓM7ñôÓOó­o}‹|Ð ¿û]>üá³wï^’É$íííéFQ¦s–[£Woñ7¤»$I¶¬i¡àÉV6›¥P(0<<Ìðð0“““N¢È²K$(–JX¦IcCÃßjšväɧžÊnÛ¶Íîèè(D"‘L ˜ƒË–-ëõù|¦$I‚¢(¶(Š`I’TÕZªÖŪÎ)ðz=(Š=¦9vþjÿgw/¸ã¢5óæ7:j>W9ù~òG?`ËÍe²âèà;ï~÷»Ü{ï½ÇÀÚµÓ)ÜM›6000PSõW]uÕ4Û:88èªyiFÀ c<ÃŧX% Ë²Žƒ¦ôä$©‰ &&&Ã4ÍZ‡‰F£(²L4¥««k&–äóy²Ù,¢ ÔBßx<Α#Gðx<áP¨7‹Y°`ÁáH$¢º`°EQ4¦E›Û²SjJÇ€ÜñÉln[}é[Ï™û•Í«”ù~ãLOq¸Ùѽ»éÙñßúøÇ¼þÆo°{÷nº»»yMÓ´Zw²e•J…B¡€ÏçswüiT Xï|öŠ(Š˜¦9 étšd2ÉØØj¥B¤¡P(ļyóhll¬…¶–iR,•°Ýd“eYd&'1M“H$RK@544Fñy½´µµ!™L†d29?›ÍÎÇã[†††{c±Ø¾%K–ìõù|–[Ó,Ô»'UÓgcŸð7’eîê­7éC×uT}Y;½çÉÝ{Ò÷Ü{ï½ÜsÏ=³ú‹-ª ô•W^qyìT*/^Ìþýû¹ï¾û¸òJ'Ý+Š"---<Ô‡©ë3Ô5µúþÚ~x&îH’„®i¢H:•">2B©T"‰°`Á£Q'4Õut]'•J¡ª*†aÔÈ"½îÖÐu à ™LbºûØ4Íš©™?>sæÌ¡¡¡U«Vqþùç399Iÿ£££g¼úê«×Y–õòå—oÝ÷Ì3O'\šX¨: Š¢P)–j+Ç€÷Í//~ú…E‰OÞ~Yk÷é–t— ~ño÷#"?ÙÝOcs+¹Ék«´344ÄÂ… ¹ÿþûùÎw¾C0œö÷ßøÆ7ˆÅblܸ‘·Þz‹/~ñ‹œþù¤R)®¿þzöïßÏ·¿ýmB¡ÝÝÝøý~âñ8mº}’D'Û7SþVu÷×Ý"¼_¡ZÐiY©TŠt: –ESS ,p4ƒaP®T0t³JÆq?ïxa#3XÆÁÁAŠÅ"‡C‡áu5C{{;ëׯgddÄ·sçÎK»»×^ÚÞ>ï±'Ÿ|ò…D"!¢ÏçÃãó‘MŒašfÿ MÐøð×oýñ™«ž»kÅ\Ç“>Õõâ£PÊçØ°õršÛ;°mg»MÁtttpÉ%—ðì³ÏòÀðéOzÚßwuuqíµ×N{®­­¯ýë455ñå/™W^y…—^z©æùW×åW^G©T¡X*tcmE©€+ý*¨mkª„»¾SÉ®#hª,ÕâË4) ¤SNÙySS¡PÈѵ–åÜuÑ¢ˆ (x=Qtˆ£™9ۮŦ†®“Íf)—Ë‹EÆ 2™ ±X I’¨T* 044D0dÑ¢E\vÙetuuñøã_ŸN§/Ý¿ÿ¯{zz’``0Hrl ÿdQ@9»çùä?ÿÃÿøŸ_»e‹ œz´SUÿ—}ì“n|-"É ù²S?'IŸúÔ§xöÙgùÁ~p î»ï>~ÿ÷Ÿ_üâhšÆæÍ›ùë¿þë¹£( >ú(÷Üs>ø ½½½‚@gg'º¦¡)2éÉL ><^Çó·?h Õšþ:Õ` ¹Éž*„e9!¤m“ÉdÈçr¡*ºÂŸÍ¶ ‚€$˵1¡Ê'¸B®N—sÝð³­­Íá ܰt"™drr’\.G¡P¨%¦ …ûöíãµ×^cÙ²e\wÝu˜¦Èd2›*•J>n@QFFãX–%œÕz‡ô›û¡gÿàø†.hŽœªðýmoû¡ŠŒª*–(Nà IDAT‹E"‘·ÜrË1;¤þñ_þå_ÒÜÜŸï¸Å3W ¨Õåù¼p°çðXpÚ¾<^° §}Ë6 T;-kJ;Øu»MElAÀ¶m’©¦mmlÄãñàñx¦E*¶m£é:U­%†Þ‰€O$¶M `ùòå\|ñÅtww׊NlÛfllŒíÛ·3>>Î’Å‹išã ¤KŽá ´–™¥aK¬K%Nƒc/ÿÓ¯zì­ÃAÏ;?YYvSåN¶ü~ÿ ³ied^/@EQj5‡{OOµ èÃÓp›;-÷¾á ¿ÚÖeMwmËb2“Á¶,"‘’$á©#›l@×4ŠÅ"º+øãu>¿›-õólÛ¦££ƒK/½”³Ï>QÑ4 MÓèïï§­u.sç¶/)—ÊMúЇÎu#i&D—Mªà4N#Oí†}aOQó¾Ãd±ìªòñÒ©íêP(tÊÀM¥âóùX²xƒÃCXÖT¬ 8 qv¾i8ô°m;·†KWÍ@=‡Z(1-‹@(„ Š(¶k¿-ÛvHWý¯DÊþ …Ü6z›cþïYgmࢋ.Âëõ¢ë:år™Å‹3oÞ|ìaîÜyéÒ¥?^»vm» ‚ip‘é…Y`DzäŸïÛ®SÉ“Ó]ŠÇCÉk¥['ZÁ`ð¤°,‹R©D&“¡P(P(ˆ‚@:=É¡Þ#SÀ að(uÂ6Á¨7 –ó¼iM Ì0 *ºŽ×çsj\áÛ€nš 47¦>]!Û§ùøTQaY‚ °råJ“““t.è$òú¿âúë®eΜ9ó6oÞü?p†OM3Ò,ÿB¤ÄŽ'óöÊ­Y檫¯¦}þ|þïýò©OÞN[[‡êEñç}}}볶ûdÙÕcÀèÓwõÉÃcSqõé:‚†(“«œšjƒLNN2::J__ŸC¯ª*^¯—ÖÖV-ZD[[Ñh”P(Dkk+¡PˆhC€;wNû¼Æ0ÄœpÐ4M Nº¸¦\Óàh òdj·–m“/Hcùƒã™€S%ìßÈo°™˜˜ ›Í’Ïç)‹l8ç–-[Foï ]CUU.\H4eéÒ¥×â\ÿ@ž™®ú@ZC8”Þù³}?ùñ;Þ‰ç$ §æÜùý~ à¡¡ŽŽ:::hnn&‰Ì†ÃáZØ044Âþýk¯Ç<Ð…°tݼi¸`0ÀÔÝԱ몚‰]ßàÞ–*'Äcú¤“áDàx7œ‚ê\‚*å\å úúèêê"‹ñÜsÏÓkdbb€uëÖÑÐÐðA× T¯x2-9fÏpSÀð«ÿësOÿû›Éœßsú@Ä#x*À²,@Í œhE",›â$jžxò©iïiŽ:–]ŸÒºîî~ ÓFÓLD§«·j÷- Õ-ì¬ßÝÖ)8~§ã Úï0j˜˜˜¨@Ó4V¯Zͪ•«Ñ4=‡˜;·¥F™/\¸P(´Î€g6Ìf FÕÔÐÀ}w}ç¹tÁµ•§©*²bñä—Èñx<‚p\}¶5g΢Ñ( ;çðë;I§§JßZ‚ÎÀÇpt  ÍÑÓaؘfFp…\QÕZ›·=KÒýT…nŸ"`NÇù3 d2IÒe ÷¼½‡ug®gÙŠe<ûìót¯9£ö»Ö³”.' œÕ"ƒ|Õ =õ×ôoo yO7ô¢IžVÍÔ•Jå”?¿±±‘¦¦&§)D‘Éæ <üÈ£Óbܶ&˜;ǹ¯V¯:;¿v˜"†!`ÕhÁ)ÓM³k† °fÄl>YhøNÍÂøø8ããã$“IÊå2kV¯âÌõëzþ©g¸öÚ«j›d¦ñÇãûªÅ…YœÉTñ¾÷ù'^9PÔ<Òé˜KO‹:•°±>G?þ|ZZZhmv¨Ï_|‘T:=¥0·É £«NÁ¨ª9õº6åXFÕˆ˜躅jšÓ„?Ö „Î)cVØÓGζ*•2‰D‚„›,Ú¿wÏ9—®U«xòÉgX±|iÍqnooŸ €j¹¹x<T¿[•!ÌÃ…#o~à¾Ç߬UØž#xª~@(:e `…BUUñûý¬\¹Y’Èdrüø'÷O{o{ ´·BÀ ZÅ1šš ªj£kN!©a€i hš‚|\X'0 §²óq íc﯆‡‡‰Ç㌓Íf9wã9œsÞF4Mç™çžã#ù0ªªq§¤ÌÂþ 3£Nb ÒÀÐοûèÏÿå¹Á¤ÿgˆ’„(I§¬NDU*2™ ccc 022B±XDQV­ZEkk+ÝkK÷mßþ ûöMEa:Z ˆ8M#ZÅ. ª¶Š5¨ª×ãDzDgà,B?(ìÓ…]·ëí“›†jgT"‘¨q$›.¼ŽÎNþùÇ÷±ñœ³immå—¿üe-BسgÏT±k½–>EµZnäN¬MW]ÛòžZÊØÐ4,C§Ýï X8B¨Jåóy&''I¥Rhš†$Iøý~b±±XŒP(„Ïç«…’$100H±Xb ¿ŸË/¿t ^°DÇÈåܰn…°–‰m™x= –ib™^ŸUU±-çÊ ö,ÙÌþ õuèÕÛúq•ä©'}˜å9A T*ÒßßO__£££ìÙ³‡k®¼š+¯¼‚ƒ½‡ùÙÏ~ÎþÛpàÀ:;;kei<ýôÓ‚À /¼ð#×´—ýt(Š;­tèÌ–Í›V´™§Pješ&â]Ò ‡Ã'}¿ªª¤ÓilÛFQ"‘H¨fg«ôxg3päp©4¥r¥Æ‚ X8>@®XÇÞÙ6¶mbY&‚  H2Ø6–›5ò*ÔŠê V[à̶OÎÍ€»—Üê÷Þtዳ€BÓÔZ1ÈÐÐ###t¯YÃÕ×^C(á[ßþKîøýOQ,‘e™ÅîdÔl6Ë“O>ÉÄIJ,Ÿ6„ßIäÑ=¿,,ºì3ç.™ë‘ ëä VÊ„“–hä”l»®ë´¶¶âóùN‰˜™.žœœ`,™¢¯ï(tt̯|0ìì~Uƒ|ÑéÌtÈÓ0ðxœ0–iašN—ÏïG­hŽ&°« ™á¸ÙÇþ`µêûøpéÝ: ˆuÐ4•ÁÁA`||œp ĵ×^ÇÒeKùû»ï¡½}ÑHÍù« ÿå—_fÿþýD£QLÓäßÿýß§@<Pu«CU'‡ÿÏßÞý\E?97 ¹ŒàéB§ Ö×tvv²eËæÄ¢T*÷üà‡ LXÚK: 5æF*T*6–!a"étM/¶-£j6å²N A–¼NFј¢“-kªÞÀ´g¤šë‡K[Óo©›4Z?q´ÞIPÕJmÇ ‘Íf1uƒ«®¾’5Ýkxì±'è=ÜËòe‹Y³f óæ9…1©TŠíÛ·³wï^dYfþüùïȘÍÌ €Ùÿ‚j­úðÊó×6G4ãD&P@SU,µÌ’9 '-ÿ–$‰d2I0<¥Rñ™ÌX6›¥T*‹E#ΰoï~.üÀ¦šâ Üàt [&äË.(Šxd†®£–Ëx=^<Š ¶€i˜˜†‰,Êx<^ Ýp*ƒNâå U;ájÁžÒõê¿^ÝWïëºÊÐÐñxœ¾¾>&''ÉNf¹é¦Øtá…¼òÊëüø'ÿ—Ï~ö÷9ÿüókßïСCìØ±ƒ}ûöQ,Y¿~=ÃÃØ¦ÉóÏ?ÿŽ|€úë6TI|}{ÞÌ­½ú÷6¶D¦.¤0{fPÃ4 :ò)9‚Uâèx%bÇs‡‡‡ebb‚L&Ã7ÜDGg'/oÿ%û÷ä¢|Yv¾²ˆF@TœÑ|ÑÄм3íK×)K ˆ|~dYª•~Y¦…×ãE% LÜÚå3‚Ûž2ÓÕ¾s_Äq«& *üB>G"1Zsú2™ …|ž›n¼ /ºˆ»vóÝïþ=ßþÖ×Y½z•Sý36Æ›o¾ÉÑ£GÙ¿?¥R‰•+Wb###(ŠòŽ0 "€69¢ŒJË#—o]Óy"X¦IE7hF%‰œ’#X©TŽ;]£šO¥RÄãqÒé4ñxœx<ÎÀÀÉd’Í›·Ò2·eË–°nÝZyä§ìÝ·Ÿ 6Wk'“€¦È^01-ÝT ˶0 “Š;Òçõ£È ’;VÔ0L°@–ddYqkÁ²ìiªãøS`¦Ó—#‘ˆ×œ¾T*…,ˆÜtÓMœ·i;vîâoþæ{|ê笳6Ç9pà‡¢¿¿ŸC‡NוeY:tÈénöxÞL«}ãÑlãEŸ;{Í¢ ×0ÿj¥LÈÖ˜‹ža‚@:>‘¦i9r„ÞÞ^öíÛÇ®]»8rä¥R™|>ÇUW]CËÜ6íóè˜?¿ßϳÏ>Çî]»9óÌõÓú|¾€‰,˜ø¼4S[ËuJUÃ)ý²@–dIFQœd—cÓmDABQ<(n¬ªú§ZÕfº}Lsúªy¡~‰:D2™¤¿¿Ÿ… pã7Ò½~=/¾¸ïýÝÝÜvëGX¾|){÷îe``€ÁÁAöîÝK:&²víZÊår ‡|>ß³}ûöŸ¹äÞo €*7èJi›®ºníñ¸Q’( Øj™%­M§”ŠÇãµ8¶:1$“É0>>Noo/###Ózð>zë­¬[¿žŽÎE4Æšt´·9äÉxŠB¡„ÇçaÇŽüê7Y¼x1­­SWòö‰ôj„dü^I˱,]7¨¨*–+pY’]0xÑUè‚óš,ãQ<ø¼>DI£xÜáNÑKõV‘DA •š`tx€DÂqöJ¥ñ‘¶nÞÂu7ÜÀ‚… y𡇹ÿ‡øàÅÑÒ<‡x¯Œ,*Xˆ˜†eXN5p¹‚®.œŠbI$¹f*dÉ15ŠìA%YAQŸ—Ÿ=ú(7Ýt=Åb‘x|”Ý»vs¨÷0kÖ¬!¡VT,ËÂ'ËDü"áˆSbô ý2ÅÙáN=¡®™hªMÕ0 Ë´§B@Ó¶p&šÎ“6¶e’ɤè?BØ÷kúúŽ:žºa°uó®½îZ–­XÁ믿É_þÕwH$¬Y½‚‰d’D"A©TÂï÷³hÑ"–/_N8fȽÄ}}/  „B!:::0 cγÏ>ûn½Gù7ÕÓò f%ç›”:B[¶œµx¶d‘eY¨šÆÑ 1rrF°ZêUddd„ÑÑQâñ8Åb‘sÎ9‡µk×’žÌ’ËåÈårŒ&9ÚG6“å`Oç{.{÷Àçóðø£ÿÆ'nÿ8g}6ç·‘@ÀÇ¡Þ#ô òÒK/cÙpæún|>Å|ÅãA DÎõ…‘pH"”xE¼It®mV½b¸¦ihjCW)òŒÆ‡(æ3T*ÆÇFOŒ°oßnØËî];8|hÃÃÃü¶lÞÌ 7ÜÈÙÏ¡X©ðý»ÿ7ÿòàƒ„‚.hÇ4M¼^/---,Z´ˆE‹aF-Lœ-í …hkkcÆ >|˜gžyæŸ\PŒw:%¬~Rx5Y4¼ëÞ?xþ¾s?ÐuÇ-«Úg¶–Ëu„ÐâiåMö1`•ØÑ4­ÞÅãq’É$¹\ŽK/»Œ9ÍÍL¤Ò䲊Å<‡%1–@ÓœË4hqR¹Èõ×\Î|æ³|â“·±r•.y½^®¹ú*V­ìâ‘Gcç¯ßæGÿüc¶m{‘[nº­[/ J¡x<ƒA’M ±€€jK膈¦Y¨ªŒ¦;ª¦ÛÝkZ&ZÅ¢P)“§Xȓ˦Ée3¤&ÆÉf') 4DB¬ìZÁ…›.då«hii!Ÿ/òO?ú1Ï?ÿ °-6œÙͼ¶¹NkZ8\›:211A__ß Óç¡Pˆp8ÌÅ_\Ÿd«†ú]Ý¥ÆQ`°2væµ›þöáÇ¿³éØ&ÓÉñ1"¥W¬_Yô‰:j^zé%$Iª?LLLpˇ>D0&“ÉËæÈæ²ìÙw€Ôĺî8 Š" ù̧?Íܹ-ôö!‹Ö&ŒV* è%’‡ø‡ÿó#ÆÆÆ… pù—rÉ%ÄçñPÌçÉæó”J%</¢ìÔX¶„eÛhšŽ¡ëhºA!Ÿ£\)£©*éTб±8ù\ŽB!‹¡ëø|>ÚçµÑµb9K—-cá¢Eˆ¢H<‘àg=Áö_¾Š¦kœ·ñlV­êBEJ¥Ríú¹\MÓ¦µ’Oø^¯—[n¹…ææfFGGùéOÊwÞùœ©b@é7{ÜBÒ¯}ùš '* …B'Tÿ###5'°\.“Ífù½Ï|†JE%5‘"›Ë1žL²gÏ^Ò““hîNpú⃬Y³†¹sIþ`±±1|>^¯—†††i$S4åª+.aÿƒ>ÜÇѾ~î¹ç‡<ôÐ#œ¹n-_üAÖ¬Y팚±,‰qJ¥ùbMÕ(Wʆ‰¦©50º"YÌkm"¼t‘Hsç¶ÒÚÒR»”M>_ä…^dÛ‹/s¨§I–Øpæ:–-]L¥Ratt´v}‚ªÀMÓ>N:f^{;½õVRi2™ Ù\–¡¡aÞÞ³—l.çtêºL”ÇëeÅŠeÜxÝ5Sô²èxÉ'ûáVv­`nk Ù\ž£GûŸàù~Á¶_fNSK—-a}w7kÖ¬¦cÁ"”Ùêå-ë¸C‰ŠÅýýý<ñä3ìÙ·Áþ²ù trÞyçÐ1¦Û€r¢'ʇ„B!æÏŸÏ•W^9íµþþþYsïÆ¨ØÙ Ic÷ÝõçÎþ?ÿóæ wŠ&®/k©ës«'x˜˜˜`pp]×Y²d [¶n%™L’NgÈä²îíeÏž}¦é4oH†ib[±ÆF>uûmµÏ¢±¡á”¾H¹\fÅŠ:tˆ³6¬#‰ »ÞÞÃáÃGxå•×xå•×P™p0Dcc#±91šc„"ý¯ŒmêÖ3är9R¤''Éd2 %,ÛfÉâ…¬í^Â΂Á@m‡¿“¥( Á`P(Ä9çœCwwwmôŽ $ ^zé%¢Ñèo Ç)$½eýW>yö’ê©ú±u;¯ÚïÇfdd]×9ó¬³X¼h‰#üÉ ™lŽ¿ÞIÿ Ьàó9$Šiš¦‰Çãå+ÿÏÖNìhÿ ±hà ͙tµÐtrr’B¡@8æö”p8Ìص{éô$™L–L6Ë‘¾¾“ìJ/s[[‰56²bù2šç4ÑÞ>ošJ§‚¯š4ÇCWW\p^¯UUkÂWU•‡~ø¸ßùݼzø¬…¤œ÷Âg7, z4³®D¬ ×z髤Ïàà ###µ:·›n¾I–]á§IMLòú¯Þ Nðû*Ö-81MGUþÞ§?QO$ðyÄãä«gD0d÷îÝ\z饼öÚkLNNR,Ù¿?6l ««‹å˗׆CéºîhXŒ`0ÈÐðÅB‘ùóçÕ \3™Ì´±1¿‰À«dXµ=ÞëõÒÕÕEwww­Ø¦â6²ˆ¢Ó—yÿý÷399éj³wž>]PK¥ü«c—_¼¦Ó´§—ˆµy|>Éd²–ë®=7Ýt3’¤LNšœdb|‚í¯¼B¹\"âó$¹Vq¤ª*W_s[>paÍÖ–ËŽ'~¢„Rý:zô¨seq]g``€Ë.»¬æuWµCõ"QÁ`–––ZëØØcccȲDCCdÚ¤TU­Mõ°ÜQ23ïï5«nôŒ(ŠnK¼‡¥K—²~ýz.»ì2:;;ñz½˜¦é\®ÎtªšÆÇÇyôÑGI$H’ĪU«( <ùä“Ó’Aò»,øÙ I/¼`ùÇ.ël.i ) eÅO¡P R©ÔÔ~*•"—ËñÙÏ~Žl>WÛùCC#üêÍ7ñx"‘¼Š ¢ÓÍcšNõÐ’¥K¹îª)§'›ÍàQdò¹ì©Ç´®÷ÜÞÞΛo¾ÉË/¿ÌÆimm¥§§]×$ÒÒÒ‚Çã©ÅÙõE«ÕëT¯'˜Édj»,˪EÕ¡‘¦ibY–3ZÞ}Î0ŒiÂokk£©©‰yóæ±páÂZò¨úz6›Å¶íÚ‹·Þz‹W^y¥ö™«W¯&™LÎ^¹ý[ØýzC˜ÿûo=³eã?Ü:'Šâ¡hY¥Ñ#288H:Æ4M>~ûíd²’É”#üávíÚí1>²×ë 4°L ]E×5Çîù‹µèë ÖuK©´ã†™š¦Q©TMáÞXºt)étš¾¾>~ñ‹_pþùçsñÅsäȧ ÃmÄŒF£Äb1¼^/‚àh³êl¿êÿ.•J "B­Goæ9U…VŠb±§VôÚÔÔ4-cXz5Z¨×ããã¼ôÒK ÕÀ´r¥Ã¹ÄãqZ[[ßÌä†Ç^þÇ?üá5«ÿì®=SDR£q2ãƒÌõ:ƒ£Ñ(W^}5‰Ä8©Ô©‰IzõpäèQÂá0þ@¯GADÀ0MtÃt2• ÿûû?%ü¡šð«IJ¥R› Q¶¦iÓÆÒ{<>ì x’$º»»¾¾>^zé%–.]ÊÊ•+kŽj&“©ÁçóÑàˆT¥æÛT ZW¬X ÎtÐÓl¯x¸º®£iº®×À“J¥Ø½{7û÷ïŸf:ººº‡Ã¼ýöÛnúZø­ –û9†øþçžÞ~Å–3VDÒžl*Iv`¥É ¥.»â Fãq’©©TšÃGŽ080è8Wn%0"˜†mèšJ¥Ræ«_ùÊT½üø8ÑHÛ¶§±}£££NjÖãÁï÷‡kõƒõ«±±‘T*UK®Y³Q¨Uä,]º”åË—×ì~.—£R© i©TªÆ,úý~¼^¯3cØ~ç³Bª&¢:DÒ0ŒšÐ«¾ÊÁƒ©iÓ4ñûýœqƈ¢ÈÛo¿]c=óùüÐÌ¢eù·äÎVHÚ|ï7¾¶ý¾tËÅ™ñQʺÁªU«XÛÝM"‘p¾Ô$ýýýŒ ÇiœÓD(8Un𦮡ª:åJ…믻–Χíi<™D-WHOL i~¿ÇC À²¬YUßl5½½½hšVûÛîîn"‘CCC¨ªÊèë룳³“ÖÖVÚÚÚju •J¥†|>_-[ÕÁ`°6ä¡êÌUwxU°õͱÕH¡~’y¹\&™L288H___ͨú ‚ ÐÞÞ΢E‹˜˜˜à¨{õ°*¨óù|if_ÊoKÔ;„×)TãÏ}¯ç_ÿßö®46®ë:³qÞ¬ÎΙá"’Zl-Ü,‰kiÜÊ2 ÃU  D ŠŠ— AÒÀN‚¤hªp€¦±ã4hZ9µ¬ÆUUJÙð"X‹%ÙÚ¸HÖb‰äpfÞìÛ›}ëwïÕãh(Q¶ä ‰.p1Ã!9oæ}çž{î9ß9§ÝÞ¿n¹ÙüglIJ#À󈄣ˆD£›G.›‡Åj…A§º‰{öTÅUP,‘Ëe±iÃzlÚ°ž¹SsÙ€,ˬÕM¹pÒU(›#¯-‘³ŠÇÇÇ100ÀŽ\]]]¬xE4E&“Á¥K— T*YzºÍfc«v-—ˬŒ=’Í*KO„a®I·*jw$QÄz¼Œr©›Å ^‡&® J™å Ý÷ rY´:xlËfvAHÃdjìé£Ä“r¹Ìž×æ(îX.—!“É011E‹Í¢ŒÙl6477Ã`ƒP‰DÙl–© +XA«˜Ñýšj‚R©Ä^£Z£™ÉdP,oòPíR(Øïår9\.<Ôj5‚Á ¼^oÃíÍh4Bí§eP- ÐJ¢…F™_þó?v­^Ü>Ä##MàÊG¡R)Ãb±Á`Ѓkj‚L©@­\aFOVÈÁ Óá™§v² L{gÐ|nÇqÈçó· >Q¡ çö7ß|?þøMÂDÁd2!•J±²îÙl–Õ1¢ï¥Õj¡P(Ëå ÑhXEt¹\~£Û˜ÄH+¡ÓýžM >* 2™ V«f³‹¥R Á`‘H¤aì ¥¥…¹ˆI×);õž €b7  v‰;pàZÓÅyCaÄ LNN¢V­Àf³Šàs2%*5±bW¾XDFÈ Z«Îróú|þÛ‚OÕ_¡P¸¥P-@;ƒÄb19rk×®m¨UL&]QÈårÈårÌð¤!g4¶N§Ó >õŽŸF?W*(•JF  hµZ”J"ýíâÅ‹·,¾¡×ëa4±yóf”J¥{ ¼ø„#à yýsýý|ˆG(F"•„wjÕ*`³Ya4ˆ‡O&Ò­òòEd2’©$výðonD¶¦½hi6ÎëƒpǬû9÷)bD±#L¥‚>ËÎ Ìâ0J‹5Rkß`0ÌZ±eÒr¾X,Ò.¡Œ¸A=vR¡ ~ú¾Ô{I ÇZ­†L&AÀó<A¸mðÈh4Âl6cÍš5hiiA(úÔ@ ±•™“LÍ¡7ÞøRooßP B(D*Æ 9ºØm64ų¾’DõŠ¥<òy’œHá©§ždo Gaš'øRf‘tHWj>Ÿg+ßjµ" ±U855…X,†uëÖÍâ1Öê:‡Öj5(•JfáS•^*• V«gÕ¦S*lÒßQC²\.#‰Ì2*ç"–Ëå,{zõêÕhoogáàOÃHÁ·“Õ¯9thûòå½Ã|€G0‚à÷óËä°8ZÐll†F«B¡D­ZE¡(‚’N§‘H&ðäÎpÚEúv4cð’þ|²ÛT« `0d.Wz^7›Íà8Çaff™L˜ššb= kµ^ýu,]ºÝÝÝ7/Õõ«ZNjÒ•J5M½Wÿ³ì; q›Í»ÝŽþþ~Øl6vÂ9yò$£Ùß+‚ß@;2rhûŠå½Ã¡`ÁP™LA>…B‹Õ“±z …B´tKâ?J#‘Hà‘Ïþ?Ÿ-`HTd#«žZËô‘©#õó9ŽƒBÑ8&.\AÇ‘N§át:a±X011ÉÉI,[¶ fÂèi$ õñi ¥R ‹ÅN‡xË–-c £P(àµ×^cšî^ €œ¨{þÁ‘‘íËWôó¡ BÁ²¹#¶GI¤RˆDcèïÆõŸaG£h6˜u¬×ë™*ŸO‚‰ð¹4ݳ)™rbbï¾û.6nÜÈ’.³Ù,ÆÇÇáñxÐÞÞŽŽŽÄb1D£Qœ>}DZÿ§Å.ï†ÐFÙ4¶@=]]]hkkc'd2ÉìŽééiŒŒŒ ‘H°ˆ`*•j˜n¯¼›àÿöàÁíË{û†ù`ÁPÅBÑx Juv,æ1¦¯nB¥\A6Ÿ‡É ‘H `` Ÿ¾qöæƒÁYªK¡PÌ*{ÖèÓ/Y¿ÂiƒZ­†x<ŽP(ÄÎÓ>ø âñ8|>+´är¹pþüy¤ÓiVËétÂápÀn·³Låd2‰@ ÀBË:ŽÀ–:¨¿þ9õPÐi³J¥bÆÇã{º-§CÝLJÆÄÄ;Q´¶¶Â`0àìÙ³³ŒØO* Á_ÑÛ7 òàCa”JeÄ1pMìlV ŒÍÍàššP©U‘Ïå‘Έ'G£è[Ñ‹áµCìþ‹¹å¶‰ õáÓ[],‘H$àóùŠ.\ˆ¿ÿþû3gÎðï½÷¿k×®G{zzMMMèïïG¥RadÊ%K–`Ó¦M˜ššÂ•+We; ²j¥v»‡ƒ)3™ 2™ Êå2‰;ËÏÕC¥R1aonnf SãUê¨J§ÓìhK#ƒçÏŸÇÙ³g¼V«Áãñ «« §NGJàß  àÛˆ—O»cÇŽáà‡P*UÉàÔœN;l6›Ø‘ãP«TòH iÄcq„Ca¬X¾Œ|0ã÷Ãf±Üì[©s:³Ù,e hÿ•+WB£££ˆYM«G"‘™x<îÄ<¾¾>\½zׯ_Çèè(ü~?-Z„õë׃çyÄb1Äb1Æú¡ !NÇ\Ƈ 4EŽú(è4…~ll ×®]cDPê=ìééÑhdá`’bç½Ñ@' ‚–;v?ûç¶SðË%ѯ)ÑêrÂa³Âd6C«áP­ÔÎçN'D …±|ÙR ­^)¡qÏÀé°‹›çXÝõYEpª†Ïœ9>yòdàÒ¥KÁ'NL%‰ á'dëf‘´öÚµkB¡Ð [,Æœœœd…™[ZZÐÓÓƒ¥K—2@<G6›e%Ûé^¬×ë¡T*¡Ñh “ÉļF}hQÚˆª>$‡áõzqýúuF“MikÚR©„±±1æ82 ˜žžþ³KÞqj˜“8x:´ìعsø;Ï>·gàWQ.Q®Tár9á´;`¶X ÓjQ©–‘„Ãð<¿ŸÇ’%‹±zå „Ñ3Ë}K&/¹\ét‘”€¼\…É´ Þ½þßý‡SÉ oOALΑp´@ 'y,h¥@3çîÝ»_|øá‡¹ °[*•Àó<«ÔAݸmmmŒÂEU3õ0R'Î\áÞÛ…ƒ)­Œ6͈D"ˆÅbÈår¨T*,2H£˜&“ 0,—Rz\ìììÄ®]»¾666vÀ ál”ü;w?ûÜsÛy>ÄÀ—Ëå¨Öªð¸]p:°ÙDçDµVC&) ‹#ƒ†ðàƒK°rp€½ù¥Ë—ËJ)øRÀiÑÈD¡ŒH¾ JÈtèl]8v©TÜÿ‹ŸŸßýõãBü4Yåô¼DíɬB,” ;l06{<æÿW(hmm…^¯G(B4e‚pùòeÔj5èt:˜ÍfÆYÝL¤l©ÑGWz½Ã(GÊÑÐ ’Ô;X*•Øñ—²jµÌf3<, "‘Ο?S¨Ãá€×ë›"÷¡D¾û¼·ê×wÓ•ÿíg)øA|…Åbn·.— v« Z­è„ɤ҈Å’Õ¿dñ¢YàŸ8õþµßüú×g¿÷½ïn•ÉÄô0AÌdÍWLePRëPæô)äP™”0è9D :ìÞóÞÔßßz°˜ LCLxŒBª ¿D/‘UOgx0@û£ýè?ºººúNž<é¤]Ì¥Œšööv˜ÍfX­VÆ jhHÙ`00&°V«e4-*·r—ב …ÂMB¤Ñh`µZÙ6Ç™X?Ìf3”Jeþå—_~•Pô²ៗ´°’¸¾Åf³µ}ík_ÿ\8,õÊ¥2ÔMbÌÝÝê‚Ëå‚Óag-ݲÙ<"±¨h8ùy,^´xVõÎsçF'vîøÊ·e2Ùòuë†ý~îèÑ£áÑÑѼþÿºëÛßø‹žª6ƒ&¥ º¦&1ÙCì?^ýáWÞ ß3 @ÀJV®ô n.ù ò¨"B{å•Wþ}ÇŽO«T*õààMù­Ìc2™ÉdؾO³w³Ù,A¸‰÷/ÝÛ)5œþL#‡ÂÁÕj•%´êõ"‡R©T²ºÉ”QÝh˜L&8NŒŒŒ¸páÂUi>ýþ·³Œä˜×Àa·Û;Ž?þ­t:­åù Š¥24‡|±‡Õ·Ç —Ó é:Y,•ÀxÌøýðzg°paún´?ÿÒK/m}饟6è!§ =Ä”su“Éiýî¡«_øÌƒº¦bY¬ö=êþå'ÿvúÌ‹Ûß"´óÄL¤˜ü<Ÿ‚~« í ˆ}t,DÃu®Zµjõ“O>ù•E‹©ûûûg!]µôgJ—†„éMeT…7 :Õ4ÔÃI¹‰Ôí-Òé4b±cÍål2™Lp»Ý8pàÀþ={ö€Ø?ØKJ†j@Ù€ü½“ßJ¦’Zž¡X*BÃq¨U«0™Lhó¸Ñêv±òãÕ*à øá›ñÁ;ãEww÷lð'.œóÍxytóæ"Ñ2v2µ”Öέ»îg?ns®ü硉À|ñ0yæ ÄÆV2cõ–—PÑæÓEFì9Úz´¯\¹ò¡§Ÿ~úËêÞÞÞYNœz¨Ÿt¯§5Ú÷¥ÏéÿR#·\.3ÂI=MìVõìv;ìv;öïßàÕW_0MÀ’ûĶ€¹RÃTÄØ£{¿qt|üûéTZ+vó*B£á —ËÐllF[›n·k–:ñxÌÌÌÀëóá±ÇE»ÇÃHœ—¯^=§R)7­JJ*M€™K\|;É›7Ù÷þbÏ™#»þü¿‹‰ÀU>2y²úãK¿üÛz[ѠƧßïÏú|>Þåru& ÑhdááÛMzT•ù¤4oÄ¢|Ú-<“ɰ-„¾.¢¹ÒÆ¤ÌæŽŽh4šÂ¯~õ«ÿÚ·oß›ä>Ñ-R‚+h–}–§N}«Z…•‘ÏçÀi5hR)EèÍ7iÜÌÀçCb–ïÌ ¶lÙ-§&>‚¡à9‹Å¼±«³3Q—G@“K3d25~íÍ݉ oOÀy~"Í1ܨwS’¨ûOBggeÿ}>Ÿpâĉ+6›M_­V]”[Hùþw:?nn`£×¤ P(˜›8Ï<ÿüó/?~ü4ßOIŠÜÓY÷h.P•l{ê™g>;444ðÈç²,£V7¡­ÍÄ7<´׋¯nÙ-×ÄÀO¦’ç,óFwkk¢Áê«¥G5š[ `GÈž!ÀgÈßV0»™×Ç€šDË*¹\®xôèÑkׯ_÷Z,{2™4æóyèáw)r¹6› ííí¨Õjé}ûöüñü›X,6Y~R¢ç•"vd³y-Ï‘ÉfY|]¥RÂãrÍ ÌЕïüp8¼û¡Áþm nºL²ò¤îfúZ‘|™d›ÈIŒ¼OÚªWúYÊuÚ L¯÷Ád?øàƒë6lXöøã?Ìó¼[ÚË@&“áÓ4âHØÉéýû÷Û»wï{d+ŒíH ã´ä(\k´ÿÝÊçÿ€‡_xégÏ/èìÔj5ZpœÜiksC%‰½ûy^¯‘pmùöº×ëC8Ù=Øß·íN¢ äúJÜhr‰U§û<îðÚ bj‰1ÜBN Vò¼¹»»Û½uëÖ5K–,é1ÊÀ¥îãFÆa#Ú×|(a4g‘¾w±X,^¾|ù£#GŽœçw.’—hÉX†,Ïu¯n'¶r½Ý }þ…ú “ыՂ¶68I‘%Ÿÿ†«Tš´q~l•JùNÁ—~6YÝg¼]Ãλ)T9rB0’ü†*ôÄ288رvíÚºººƒjµ¶mhÕC»ñÿPm —‚†®k0µä~©Éß«$Û˜€lppЩ×ë9髽óÎ;Ó›Gj„–$vkPð3’)uyßÑöx'–‹@ÿÑcÇž_±¼w Âï@«ÕÌòëŸ>s¶=4Øÿûþ\AIl ´F"œd6‘©"ÿ£D]¥N‰m#¿Tw"Ê×E3ëƒ[åú0ï|©;%ƒ,ø§^øÁS_ýêçëùÖÛ‡ÑbnÙ6Øß÷û~£{&5RU ›æžvëœÕ¹³nåW%`ÒÕ\”ÌRÝ”‚^û$_æN‡ê—¯ìÙþ…Ïÿåß0…£1ŒžKètÚk†VÃÎ ƒ\¢u'yݬ÷¿Ô÷Ÿ¬4ؤÁ¬OúÝÀޝ>Ói6›¾´|éòÄ‚®ÎýC«šÄö „LòXÿ¼þt#´:—gò^Â2Ü¿ ‘>ŸWùûãþ¸?îûãþ¸?î»9þT†ïÎq€p;IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/index_search_64x64.png000066400000000000000000000177331217176075400252370ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ (#™¸H®[IDATxÚí›w”\Õ•îç†ÊÕ9w+«…R+KH¡$0ˆ=“„M0ðü0c°ÁÛcóllðÌ`›0`›°À–!’”‘P PG©»¥ÎÝÕ¡rº÷žù£-™$¿õæù½ç»ÖY}WuUݳ¿³÷·÷þÎ)øÛõ·ëÿëKü•ÎKl#† $5MFÒü€\`PL-)­œ]\\46'Çë.,*.×5]„B_(î÷ùkª{xóÿvPL¦N˜8yõâÅ‹—\¶n{ö¬Š‹ e$ápÓ´pØlÒ•“+lv'Ov²oÿ~^yeË^}ýÕŽGBðöïÛý× ÀæÍ›¹ôÒK¼.8»`ìø5^·÷œ¯›õ—7€4ilë¦s(AÈ´‘6b¦B$ãð‰dã¶9‰Þæ±£+Ïš?Þ‚åË—Ùûúyæ¹ç?öøo¯êél«ÿ«`Ó¿Ü;÷ÆŒó>8Ñ¿L„':‹VTñ½ï~KFÂQÑ21=£ðý“`LMXÒİ,|Ḭ«¯«+í¬ýa_wsøÝן·&ŸU¶xÝÚ5×Þòµ[ÆFIxà_ù÷Ç~ýµÕk.ãÕ-/þŸ`ﯾ3õ kþ¢&Y¸ÈétŸ'Þê¨p¡ö6¢t×ÉÄGo‰Û6n`õÅ«èbåVp´5I[ŸE$)_.ÈwB¡75KE€%ᆡØBÿ[¿Úæy#ÖµÛ±ëõÇ}-[õ‚ ¿qûÿ¸óλ¾åúí“ÿqâÖ[ožzù"›þøÜÿ~ZïÛPòxñúeµ”/‰jžyn§s¡OÏÁé°Q¨#½XÂ2Lú›Ð[ÿ>öc»ø×Ÿý„ªŠ2f̘cÓ¦MëB$5MÓ€$ èªZv Þ¯lwß?\¸«f´VKJ)e p!R©í؇Íôžlå¦UK¸)ý¡¦¦&&MJ¹v"‘È6JÏ& ¢ªZvO¯¡äçÔ¦iÒÖÖ†x—Ó‰ÛífâĉD"B¡‰D¤ª¦a³Û œGAeeåh›Í6`÷îÝV(:‹ÅjVÀRUA¹rÅÒ»—.]:U×u%€ øJݽ_Ùøïv»Ÿ” ^¢‘ðŸ×Ë–…ßïÇçóÑßßßï'''‡É“'£ë*»vïEE2¶ ¢QˆÇ ‡dŒ$„b1t‡U×Iþ`0«5X§µ®r„Áò3³²zõEìÝw@|ãöÛå¬Y³~žL&õ‘u@iµ~iËþ¸«Nÿ”úP·;èF9ÝITU%77—ââbŠŠŠÈËËCÓ4ªªª˜>m*›7oÊÀ¡A, ±ÄãH@:ZÏ‚óBàt:¼# ],ôBòàý?úÅ‹g:7Â:ý‘Äi¢ÀãñI§»ÓA˜:mU•åüæ‘GÁÌqàu@0‘0DÂDâ A$nb¦E3=Fzƒü0äˆ#´Éh4Ê¡C‡hjläwÜÁáÚÃÌ›7¯×‹ªªöÓˆm‡ž¸û©Ú}œÆŠªà7d:‰|9âñ8±XŒááá,„B!&L˜ÀÅÏŽoÓÔØŒK“,®3‘!’D"‚dB%™T0¤J2 ‚1ŒS€#@8Åí?^€ÚÚÃ|˜ÒÒR†††>W—@¡˜Gê»õõW¯›k©2YUT†ú™\ZpªgØíø|>Ñh”ÁÁAvïÞÍo¼A~A•£˜^SÃâ…ó9|ä^zñe.¸`%ùN(+H‚f'ž°34Â2Llº‡Ý‰¢hhªŽ¦ê””|†ÈÞëºN(àçð¡¼ûî»TVTpã7qÏwîåš«7ðÚk¯ñöÛoãv»)((àØ±cX–Õ³sçÎ'!õ³õ@™ô·ÏY·pÒ„ò|™ò2Bá(SóõÔ÷ööbš) »¾¾ž®în®X¿—ËM4efÍ4Þ~w¦iÐÚÚ“OýžE‹R˜ë¥$'IE‰ŽÃé$žüQ‚ÒUѰéöôp`Óí¸N’É8MuñÎÛ[éîêdãu×QV9Šï}ÿÌœ1•;wb³Ù˜8q"}}}ôööb³Ù(**ò¼öÚk¿üŸ'vëÀœå—½ÐÜq¿Ç¡ ø‡‡X™/(ÌÏ;%Þ;::BpèÐ!º»»YsÉ%ôôôóÑÑhimeåŠå øñº,_±‚-¯¾ÆC¿z„/]¶–믻ݦSh„¢&þ`‚@0F"‘À2 Ìd’ÖãD#N´6ÓÚÒDey W\q“ΚÌ¿ü7ú©™>·Û@OO~¿UUB0yòd XµjÕX ãóv†, ‰JRVqþùó'fŠyl‰0%¹žShooçÀ pñšKh;q’·ßy‡úú‰$5Ó¦qÎâÅ8ü~?••\sÕãÜÄ¿ýêa†AJ ‹Èñ¸HF‚„ý>báA¢A¾žôtg°¿M,Z8›o¼q«ùÓK›yý7™7{&£GWÆèííÅçóÇS “¢PZZÊÆiiiá÷¿ÿýCÀðÙåR€2àÜŸïézdÚ¤²\Ó4…ÇßÍÒêQX–…‚¶¶6víÚ…ËífÁÙ ©«¯ç7¶0L“sÏYÌ ×_‡o`§Ã‘­u]gÓ¦MX–Åñã­tv÷ÒÓÓ˳0£f:ee¥äåçc·éÄâ èììâÀƒôõõQYYÁôi“1 ƒX,å-ñx<;LÓÄn·³lÙ2Î9çLÓäÑGåÖ[o´}UØ¢î_¹ö±M{·Þ%„vJ*¬««cÏž=Ì_°—Ëþ}ؾcv»—ˉÍîà†ë¯£»·Ó…a§¤Éx<δiÓˆF£œ}ö|æÎÃþýilj¤¾¡UU‰D"x<EPTTȪ W`šfz÷(~Jõ™¹·ÛíÔÔÔ°téRl6†að»ßý.ûþ/*‹§›%ÙnØöæsÏn=ÿš«.˜m8<„~gÿþýœ·t)¦)Ùµ{‡¦¨¨Ó´ä§÷ý„h4J4Áãr1r{UQÊÊÊhooç‚ .ààÁƒÔ×70sf gŸ=Ÿþþ~ÂáP¶ÊDUU’É$‰DÓ4³«‹ÅB0vìX&NœÈ”)SP…p8L(â…^Àçó1zôè3 Ó,ûí­>²ì‚ÈC6USßÚ{@ô´Ÿà¢‹W388ÄÞ}ûh;ÙÎ¨Ê LKÒÑÑξ÷„P†‚)¥×²ˆÅbD£Q,ËBM¿¶zõjþô§?1{ölt]§±±‘ÜÜ\ )--Ííñx‡Ã(Š’m!999äåå‘———õª@ €”’ÚÚZvî܉¢(Lš4‰žžž3 ³QÚ¼ÿ³{~ø‡›¾ºfÃñ†®Yÿ%ºººØ·ÿ=†††3:Å ==½\sÕU”–ÓÙÙ…i†A<Çëõ’ŸŸŸ’µ…D"ËåâÒK/åwÞÁáp0yòdLÓd``€žžÜn7N§EQ())AUUl62­$[éý„L*îïï§©©‰£GÇ©¬¬¤¨¨ˆ£GRTTÉg@¦Yê;ú‡Ÿy»Âuþ¯¿skѱãÇØ½w/B*Œ3 K úûû˜3k&‹MOO/.§‡Ã”2[,e„EQƒ4773~üxV¬XA{{;uuu†Aqq1ÅÅŨªJ<ghhŸÏwÊÑ!‰D‚X,Æàà ÝÝÝ„Ãa"‘EEELŸ>ÎÎNp:äåå¹Ò zÆ8E™4aÂï¿ÞùÕü†ÆÞ?\‹Û妤¸‰Ä×?@~^>W®¿œþ~NçÇÆfHOœ¦‘ !R"jEªªRUUEQQôõõqüøq"‘º®‡3í,Éd2»«ljD"˜¦‰Ç㡤¤MÓàÃ?DUUEaòäÉ”••eÏFœ NEQΞ:uê´W_{ý®Ææf¥®®Üœ\ÊËË@_?±xœoÞrýƒØí¶¬á#µUU1 ƒH$B"‘ȶiÓ&V®\I^^Š¢ŸŸ×ë%‹eycxx8µžL¢ë:¦ifãÀ0 †††èîî&g½,ÿk×®eçÎg €SQ”yS§N¹ù•-?«olÒŽ;. ‹ ¨,¯@AO_>¾yÇíøAdÖx!ñxœh4J2™Äçó¡ë:‡ŠŠ öîÝËØ±céééáàÁƒäææ2cÆ ¤”ÙÖ5ó^¯7»G82ïŸþ7ó\)%^¯—Å‹3gκ»»ihh8#ÔE™3eÊÔ9/o~åþ†¦f­ýd»(--aô¨*U¥»»›žžnýÚMÄbq,Ëdxxøã‡hZJ®.*Ân·§N·Û¢(TTTÐÓÓCII »wïÆårQYY™å̆ÈÈÐ9}dO<ñDvWë‹ +Šrö”)Sæ¾¼yóýMÍZww—¨¨(gü¸q¨ªBgg]]Üø•ëQU…¤aàv¹@ʬa#=!cxjËŽlVðz½æÌ™Ã¡C‡¨ªª¢¼¼<«2K)±Ûíhš–•Þ3@Z–•GÓ4ÆÏøñã™0aBj[Ý4Ù½{7Û¶m£ººšp8ü…Ð…s-Ëš²ù•-¿hhlT|¢ªjÕÕÕØ4öŽvN´·síU_N»y›MÏê#=@QRÒÃÀÀGŽñ:t¨sÛ¶m'ß|óÍcÏ>ûìW—/_ž³sçNX¾|9½½½|ðÁäååQYYI^^¦i‡³Ä—Øápàr¹ÈÉÉÁëõbÉd’P(DCC{öìaxx˜êêj@FýLP„3Lÿàƒ~^ߨ „‚a1ªrÓ¦NÁî°ÑÚÖÆñ–66\¹^‚ɤÃaÿ¸8âÑC¡¬÷Yâ¥':üúËü¨©©©aÄ‘–a@?räȼõë×/Y²d ìÝ»·ÛMMM ªª288HV]r:Yq33„º»»¢½½¦¦&âñ8yyyÌž=›¶¶6Âá°ÌËËûà³öhU`†Ýá˜ðàÁûO¶wz㉄(*,`ÖÌ™¸\NŽ;Α?dÝ%k¤”’ãÇ[ú§M›Z†é薽фðEM) ŠÅëï6Ÿ|øæµÏîþèNHïÙGœªªª•O?ýôçwžL$" ÒÒÒÂÉ“' ƒ““ƒ®ëÙPʤ@Ã0H$ƒA†††R%w4J,#//ŠŠ Âá0ííí!¨¨¨à©§žºsß¾}Ï]Ÿä“©[·mû^{G§×´,QZ\ÌÜ9³±Ûm´8I]]ë.Y#-Ë÷Üóu-­ÇÏñû+Þ©ëÓ_¬«ÿ{o®…¯+füèš›_èxç÷oÍ@{ú,Ol„Ð+xGGÇ÷ßÿ£ç¦3fH›Í&&NœHUUUVe"‰‹Å²éM‘­.m6º®S\\ŒÍ–2»»»©¯¯Ï†_II GŽyqß¾}»Ósù3˜ÔìÙ»ïa°RbQ—ϼ¹sÐ4•ήêX²x‘Œ'’âàûïÏ\¹léI`4P”­¿ïùÛP4Ûî¾üi„¨GÊc©ý"§ítl· €™«W¯¾úî»ïÞ8{öl™H$D¦áÉüͤ=#]V™s…Á`0[_dš%)¥3fŒØ·oßË?þøÃ@mzN–8MýYùÔï~÷ݲҊsMË$??ùsæ j*=½}|t´ŽóW,“]¢Ï×_3wÖ¬Ò!cOóI!0)ýZ'БFÚøœl£ÅÀô1cÆ,ùÖ·¾uÃÒ¥KËKJJd<™ü>rdª¿ÓóÿÈFeaa¡°ÙlÃ=öØ“ï¿ÿþVàC '½t &ÆÖÖ6waQ‰,,ÈsfÏBÕTº{zijjΟ¨««¯ò8LùXR'¾¤Ý]~ÁF«¨=qâDð¶ÛnkZ¼xñyk×®]±xñâ ¹¹¹èº.EâSŽëfR¢”R:NQPPÀÀÀ@×¶mÛvnÞ¼y+p8ø2ÆÚY᯽±uÇ9ç,ryÝnÑÑÙEkk+KÎ=GÖ74CþÁ*‡ÝÙ7wö¬Ïú ‚ä/»”ôyß’tXU_|ñœšššIãÆ«,...ÈÉÉÑ¥”†eYùÝ þîîîöºººc¯¼òJm"‘8 t'Ò.N/Øg–¾ä’µËŸþ¹ím';ˆE#bö¬™²®¾¡o(ªr;ìÆìY3þ+~7èòÒüP ä§B;ÓçÝeeež¾¾¾ˆeY¡ô¹ÀhÚȡ̹áô}äÓÂðS5ÁI“'WP[û¶Ýn¯8xèp}ÕØª9':cóæÎþ¯þY–ÞÊv¦A±§ùJO•ÙOM¤G$ Dæ°ä_æ™îêŽo~{ÀÞ}þ~\™9I«¥°¥ÿjé×þvýí:£ë?­Ô-_#ú&IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/irc_protocol.png000066400000000000000000000120631217176075400244150ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞúIDATxœíš{”_UuÇ?çÜû{Îû‘LÞ! !‘„< ‚@…Š"¢¥¶¾Z–._µRER^⳺\]ÚÖ¶V[µÔVj ²@¡ˆ  7™„db’ÉL2ïù=î½çœÝ?îýýæ7™ GS—îµÎº¿™ùͽgÎÞ߽ϽW‰¿Ë¦OöN¶ýÀÉžÀÉ6ÿ•þ£Zµ!Gdæãä4P³ñu;žnë†qîÂ~xÞ>•òÊZ«‰çÑ¥Jk´R(ÏC©‰ß°&MëôNN[ûÏ ¬slÞðÊu섨³nj"4kñ½õÙ–ú³:¦4,˜ÒÞÐÖܘÏÔåÓ¾FQ(fx¤\:Ú?z´÷èÈžáÁÂF)…XO?©ÒþÐñ@œ,{ÙÔò/Ã÷®Ÿ³ ãÍç»pÚ¹«ç³hASÛëɧ|¼šïŠÃ# ¥bØ08Tœ÷Âþ¾×lܺÿco|¡gÛŽw‡#寑ñæùÞ‹^ï7eê¥Ê Zyã©:åß¾fÝâ·\ýæ5©óVÍ£%ë£@ÉAY¬¨ çð¤PäúÐÏÝôô¶«•V?ÔÞoNÆP«7øùÆü·ßÃU_zöö-09Ò)…ïi"íJR€€§€;‚µgc>àIì¼ø Ž– »Ž”)‡–µs¸â×µüË÷Zþûw=~eZëê㦠¢©æßdÐZß~Í»/{Ã+ç±§w”AãHûk@œCk…Öª  "1€øh¬«¦C9ŒuˆW?«Ö ƒEÃÑш tLÉyIdXÞùæsêJ¹ó;÷>}Q.›ÞzìdÙü0J»É VÞ¸îüËϽᒵ‹éî/p¸hȤ4F9Dâ¼WZÅJ­ˆS@’1Ö9¬k]5""#ã²B9‚БR0½9ÍÔ¼O!°ì<\d~[ŽëÞ¸¦}÷Àן|vϹlºT;Y§=š§î/«“lýÎMžHj€|sÃuK–Îc´2P4ˆ¿âÕÏÑ1Ÿk#¡‚I ™c"Á˜DŒP([º‡B†Š1„‘²¥X¶t-3Z Y¹dNs{kûE$YýaæþΦ&Íy­Î¼qú”S^=µ¥Þá ÉÙŠÉ âØU£c Ô cb± މ¤³B1°ô ‡  #%ËHÙ0TŒ8Ø_¢¹>Ëü9osެH–KB¾¡g'·Dú(µ¤½£m^ä„á¢AtÜái‡öZI"€LèÒ*"(’T‰« M>WJ£MÀZ—Îr’VõiMJAZ ‡Œ!2i¦w´.ܸ¹ïÌ9 7?1gáӔà (3¹”çͯk¨ó{†BŒqøžÂ‰Ã%%O;’ÒW)*éA%•@pICäDª­ñ8V0ÕÏ Ã*K*ržGZûZQ žŸcêÌ®u§.»û‰ÈD-‘!2ÖNl4Y·ò|Ï÷Ú½Tš ´ˆKJžS1/.{ZƒRR0f2>Db¬«D‚ç¼I4  Æ‚³YFǨ;„Ò[I§Ÿ§!ßM¾µÀůëûD>×ô¤#W ÊÅ‘r¡pt¤¿w4w—yF„'ߪ¶ì¼UÂW ¡±N#.qDƒ§A;Wûãú_‰€¤KÕÕ¯ôÕH°IoàjŬˆ%†K?Ärs¦ý‚Õ ¦pÆì…Ìn;“Öº2~S¤›”JZ×Y¡”é{õþ¾®wm?¸E¶ýbKçÒOª{Ê!ßÚýIÙ|"ÔÜ·}õú¹‹æuÆÂy(qc›Øñ$üu €qV ÿjCtã@ÖúDF30ú :ýuÖ, ¸lùù,›µšæT+Ž2eF¤@èBŒãNR i´Ê‘ÒdtžÊQŠì:¼GwüÐütÇ82B <9ÝÊi3–°lÎ9þ•kö½þ¾Mw]¶êsùoŒK7î¼MŽüÒ˜ñ–¿Ÿ³hÁÌGÓÓf’Ëçb‡“ܯU~¥“ `m Ä90€PÝ9;vt®Ž¡Âãdnáš‹²~Ñ[±.d8Ú‹£€¯5žòŸÁ8Käl¼åç<œøˆx8I!x >Š4YÕB[fõévõnå«?úôþ]/ì}çÎÛäá "\ü±{¾Mcëu¹Ö64µ›ž@eÄ1) ‚@U*) nL* ®ŽÁÂ}L›ýiÞuéë9µõŽ”ž'^RÚ'¥|´òÛJâ´‹!ˆ!rç4q±ó")Šà£ÉÐâÏ$íçy¤ÿ?øÑ3÷™£Ûƒ÷mù+óOÇM€þÑà»ó[íu}£eòÙJÅ7>ÆE$iP¹‡%ÆUÓ€Hž‘â#L;åÞyÙ›èÈÎóÃ!”Èè,àpÊ •E_ËN6‘3ɰœø(2(IÇHá‘Bvîeoq;ss˹þÕ7û{gíýÇŸJg6Ý~å¸z‹÷¯X”z®o`dyà·à)Æ (Æ4 0¶¤'bçS”‚=4N»ƒ«.¹æÔv<†R!$ŠÃS ­4º¦ËpIXq‰S!r†ÐE„Î`DP’ÅWu(2”l=Á~zƒCXQ8¦y ˜³d)¡ ¿¼ôv}tëÍî;RàâÛ|íiÙ;7Œ¨ol@!c¡¯jR`¼ÿ50Ö J "ù˜ÌG¹üC¬švû ?G(“ñ2¤”‡§5žòbèj†‰€ÃáD0â°Î‰­FAä ‹]„Mä#Ñ0eÑÌÈ,¦ÉŸhææNÇOe¸ûÉo=üäÎßy›l™à}ßzþ{Åþ¾+·ôA}]–¸êUåÂc$¡¶ˆ"ˆ‹—£>È«Öý5W¬ú#úKq‡Éé¾ÖøÊKœ×x*þJŠUD°6 L‚%r¡XBkm˜À°Ôym4úÓФQøx*MJå9µn9Cf€;ïÿÛ‡ïÏž‹Ç¥@Ŷ.äüùS×8udæ–Þ"õ¹ô˜ê+…MŽc¤:ÙZ’D dÚïâôSSÊôûÈz9B¢¸œi‡§\Íêo²œŒ`çXšHˆ’r‰e êÃ8EZסHã« š£[˜S¿ˆU+/X¿ìïÚÍì¿Oˆ€õ_Üüš×.j¸÷…ƒ}™§öÈ¥}´§'V€ÊÊW#DÜ—"Œ¶0wíM¼îì×ÓWôÍ8mêâ[šÒm š~²d°ÊVC¿²ú:Qÿñîo„¤ê¼LÐJ8y™Ï 5èQT”Þ¨ÒÎI›‡V>»uWÏiÝ3§¬øÊ‘á}5žÓIí¯]}5®®XåNSU¨8>¾›ë/e‚íÏ¡Ñ1“ @Öm'pÚ¾h.öž6sxáG^Èí"«}<Ž¿ú›æØ–Xj4 vopÂæ‚¦ÑVFÜàÝÏm°åI Ã`ønŒÛŽH„{½/Ÿßré;ºû»[Km#ø®r—¹VÇn¸c÷‰÷®ÚÊ‹æøKšŠûŠÌ, ~Ó#þe×S•YOŠ)2· 㞢äF „ÆîÛudÛgÖ¹×`Áz’41É~À&û%{(îû««ôø/.p/Ë<ˆöÁ)îTƒþÏU~=‰oäxî¡ SLyÐ5°ïK}C½]âÞ@8Róx¯¶ß‚ð+¬ö±–‚ð 0³6ùlý·ôáTþ4IbÜ„—:ÈøØ§ö?þnJjïåò¢#`5LP¾É6ø퇶_´±hêÒÝ;z6ÝPû•IàáèÃÊÞõ)í³ÿÁçï¹*,‡¯Ë^Oö`žrüºÞ‡òÁ˜vh:kæ^0°éÐS×m¼±t¸ök“—âøžÑqM)ŸgØñý×uölÙóžŽX~t¥ÃI2á_5"Tr æ„a™YÎÙó/xªë‘+ÿhßÓþer:ÁmˆôѾ‘¡—ü~)bÚ¬æé_¿béÛ/‹ÄðPÏ]¼Ún…t.áP©r/gzx˜>0a†™ÊÙ§¬'p¥çÜùÀµÏ|¢ôìñþõ¤0ñû”ï]=çÜÛÏŸÿm¥¨ÈS½±#ØÄH.B׃ŸíS})Çx *~Q3êÛ™a˜žÇòçPŸo’Ÿïô;{v|tç-2ðbó8i*V6LOyê†3W¿ãœS.iiζsx¸‹Î­t;é7=)c¸éjŒß9 ÙýYæŸÆœ¶…LkšM(e¶zúáíÝÏݺyƒy쥮Ò@¼¨¡¡C„«§6¶¾mqÇŠ³¶/Ͷ×OÇW>ÆF”‚"4Áÿ¸oq ÔEZAè`EïY¬lZ'{ú·ÜÝ»õÝÃ=ߨq‹<ñr¯ýÿ@­9¡cžsœöYÕ©[Ümš–ñsͧOY5÷ôegú_è¾¥Zƒì„°‹ŸˆÏú]·Jt¢×û5l†~5Ó²š½À^à;…°ÀhPPN‡÷¼ßŠýòµsþŒ;‡¾Š4€72=,BhºOøz“îÁ$›Vài$åA>ÃWîÝ~×;^عӼ>z+uGòDÀ\¦àx×+:ÿ$Ï÷×j Ȧø×Ÿtýï;xUÿ™ÌÚ7ÝìáZùË3nS+Oôœ¿U*–õ¹ïð衳Ÿ9øÄ÷ÂÃEÛºg*-ÒÚ˜N§¿Æê¼9×o%_Ó©”»êh¹oå‘‘îÛ‹£#‹HJÁç—Ý¡ò/÷<“R~›í·6&Ë~àdOàdÛï<€ÿ•*­ìl¢–IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/kaboodle.png000066400000000000000000000067701217176075400235070ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚ ¯IDATxœíšlçyÇ¿ïûÞI‘”H™¤Y?LÛò¯¤v»^“8¶‘¡u‚tÀ0 Ù†8C-0#ëÖèŠ °»6XŠ`N†!h‹¬h×¥X¥m̨ál‰Óزę£À±-Q–¨_ÔOŠy¼ãݽï»?¤»P¿lË–¬ Ó DR/Ÿ{žÏû¾Ï=wÏkZÓšÖ´¦5­éÿ«È>Þv¬O$ RJ„æÄÄÄ0€)½wÊ¡•po"‘øj<?ä÷û§ºº:‰D ¡( ™>¼œs  äóù\©Tjÿ¯±±±70 eE´bõõõO%‰?‹ÇãÛ"‘EªªPUÕ z1I)aYlÛ†ã8Èf³Èf³ûúú~œÍf  ¸œÎ.'€õ›7oþëX,v4‘Hø !`ŒÍ$¥œõ×sdÌ\@RJ! „ÀØØXnttô{zz^[§—€²iÓ¦oÖÕÕ}+‰D(¥t©"„xP\[cccã™LæÛÿ|[Æq›¢Ñè=¯ÆãñÝËø\Í!¥ÄèèèÙT*õ¤a·l÷V˜L&$‰ø|¾!Äsj! !z…)˲ºlÛ¶,+M1J¥Ò(ƒÁz)¥_UÕMÓšcUUÝA©_È^%lÃ0Æ3™Ì“§o%Ž[ÐÒÒr"gŒ-8ãRÊ’ã8gK¥Òo'''ÏŽŒŒô0f^Î Ì+ªT%‰‰Dâ°¦i‡E¹Ÿ¢U¤”BJ Çqœ\.÷l*•úáRcY2€–––—B¡Ð×€éeY8çüÃ0þ=N·Z–•PXªýD„ƒÁ`cccãkšö8clKåB„˜ššú«k×®½´ãKL&OãsB\,‹ÿ400p À8¾»K ÞÜÜüxUUÕ1BˆÂ…`šæ3===7o@2™<Âû×Ê॔¹R©ôýL&ó3ÃÄÍÇr[b>Ÿ¯)õù|A ¸ÿR:¾ÜÝÝ}öf Ý€–––{…müîw¶m·}Ý0Œ‹Ì¥ù¿l ÔÔÔ<FO2ƾà~)¥çœ1N÷ÞȽ™£444ü%*‚7MóÇ}}}hF;V/x0òùü;™LælÛ~Óý’Ûºuë±›10¿T›£çž{îžÃ_ùÊ˃ƒý4›„aÿ088øw2·áørJrγù|þ|(Z¯iêîÞ¹Gž<²kË––;þüu+Æë®€ÎÎÎ/íÛ·ï‡Rijl*Eª«Ÿü€Ñe ayÔßßßÿl8\ý ê¹¢¨¡‡:ôâÕ«Wï½Þ ëzC$RÓV__ÿ@¹\ÆÈðÈßpáÂkX¦|…4qáÂ…™š*¼d%$u¿ …þçz?X€eYÊÕ«WpåÊd³gõÆ?0µÜ¯€&^ýùÏ_Îf'/\»ÖƒåÁE¼öÚk étEAwwwË|ºÂ* >Ÿ†ÎÎ.œ:ujïb•ÅþñàƒæÊe>Ÿmmçû±rÅÍJH†Ãá¡­-[Q—ȃPÚ»ØÀEW@2™,Æã ¼óÎYôô¤³Ê+áé Éͽuæ bñöîÝ;¾ØÀE|úé§û»S)¤Ó=¥ÉÉÉ.ܹ*o9d^îI÷òt:¶¶¶ý‹ \À‡~øÕ\nò'ïûmùÒ¥Ë~æÌ™_bú*î^LßÔü¼j €{˜¯¿þú+]]©o?wŽ‹Åß¼÷Þ{ B˜—úûû”J¥tw§ðñÇŸüí©S§þsÛ¶m´wïÞý—/_þÓÚÚZ³¦¦fǹÔÞÞþôÈÈȪÔ;vìhÞ¶mÛÏcMRJäóù†|>Í›7ÿ¨½½ýÜ›o¾ùj$f›·´|÷î]¿éëë{¦©©é•6権©ù®ÂÿþûÿýíÖÖÖÿ8qâÄ¥§Ÿ~:bŽ=ŠP(äwg£¢(PeãöíÛŸyñÎ…ý™6lØð5ÆØ°m555€^xá˜mÛÇ^yå•áçŸþ‹›6nN:tèUUUß0 À¼-`š&ŠÅâÇ'Ož|ýرc‡žxâ‰H8F{{;B¡!àœWÞòϵqtýR‚EQÐÑÑh4Чžzjý£>ú¥ãßùÎ+†adLÓœ7áó‹Eèºصk×ÃRJ˜¦‰ÎÎN¨ª:ë.­«›+ýB@J‰@ €ŽŽض B>ü»n\…Âüû3³<òÈ#/ × ìØ·oߟD"‘RJ‹EôôôÌ ~µ!,äô÷÷C×u!FÚ¿ÿ3ããã±áááú‡~øo*mx,Ëš• <…B>ŸÏK‚œs•sÃ0ÐßßÆÇ™·>[À}ï ”bhhµµµ`ŒÁ4M¸+À4Mo²9+ ¦¦º®Ã0 pÎaš&r¹LÓçÜ»ó*¥ôš«ÝY¯ÜŠ”RŒŒŒ ¹¹–eA]×aYÊåò …ü~? ÀeY^'×0 äóyض=«ûóyà8Î,®/ŽãÀ²,˜¦ BÜ­Ú¶ Ƙç?!ÝÝÝp ‹¯€\.‡ŽŽPJF=±X Žã@Qï`.€ÕN‚îvtOÑ3Ýb¬[·Îóß0 ¤R)PJàóùfåî#ˆD"žq÷`•ïWKs“ ðÙ©±¶¶š¦ÍòÏ,7. âZ ŸÏ{D)¥BèRJhš††††«®ÊSÏj¨ÒÊ\À9Gcc#4Mƒ„{¦"„mÛÈçóž Àµk×rº®{Ùsbb¢Ïq¨ªŠõë×{×®®÷DÈ”¬¼àÎ~,C0„ªªp“““î“j“““èëëóú™Þxûí·¯±±ñÕÚÚÚfBzJ¥ÒŽX,UUQ__¡¡!—èõœ"¨è:?öØcFGGI±X¼a7: IH$²µµu.áYËM!ç|†”MMMÐ4 RJ …òÐÐP_$IBÐÖÖv1“É™À9Bȯóùüƒà8ί»ºº¶Æb±-Œ1$“Id2pΡªªW`ø|¾Øý÷ß¿Y×u³\.‹`0ˆ™ßSèìì¼Q̳”Ë弿»wïPJ%¥T†!ÝÏ„U×õj÷ŠÕ-Ö!hllD¹\†mÛèêêºàt¡Pcì —€¾¾¾¯ïÙ³G Z–åkooÿr]]݈ÇãÕÊgE 9ŽWE×4Í›¡ÊD³\ráJ)‰ÂÇ ºÕžeYPRJÄãq¤R)H)ÑÖÖö~UUÕËÉdòÅÓ§O;˜ÓàQŽ?N[[[•@  ”(¥~¶¶¶OvìØñx(B]]·ü9ç^² ÇQ)¥a!°Ò‰H) çœBðY⣔‚sŽD"þþ~d³Y|ðÁ—×­[—Ìår¥}ûö™œs@) Yï¾û®ÃÆÆÆ‚Žã !AÎyHJœy„£ÝÝÝ{B¡FÅG}äw—ÛÌ~ã~¿ÿGŒ±¬”’búye…_ £”!·,ëpå•`4ÅÝwß=ÑÓÓc¾õÖ[Œ±_Bçœ9ŽÃ8çÔ²,fÛ6 ‡Ã’ìÙ³§Ê0 ¿Ïçó»+€RêBhB ù|~½¢(ål6û¬¦i¹@ p4MKUUU­ØƒÌ7#]×wÙ¶½J¥Ò.Û¶µººº“¦i†«««G !’1Æ¥”&ç¼,„08çF©T25M3ݬ̚››ÕX,æÓ4Í—Ïçýš¦ùc~Çq[UU‡"¥”DJIÇa„©( '„xË^Jy§ÁB¤iNÇ£( ¥”*”RaÛ¶E±E)°§¦¦¬«W¯š˜ît-è,9xð ëííUêêê4Î9aŒIÃ0˜aJ(‚ã8ÔçóÑ™ºSJ¥›õçžnG”ÒæÃ0¤¢(BUUa𦠔JEQ$ضíäóyžN§LŸBçUmK™­Ê±nptçÎIJ,bÛö<[wÝu™qä–W…ªª2“ÉÌ‘N§Ý€Ü *Ǭz…¶¦5­iMkú¿ ÿ¬;WÎáˆGIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/kchart.png000066400000000000000000000172271217176075400232020ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<)IDATxÚbüÿÿ?ÃHÄ8Ò €F|Р6NNVIAU~CÞ¯_´Ïù¶çÁÛwÇ©e>@± *Ïòð°ê«ªˆˆ±±j²¿ymb!/§3ËÂPGœ›[]RH˜‹áá}†‰ž©1²°žýÿç÷/jØ @lüüL: ‚R|¼Ú¯^èY(Êé,°42baV“äåæåÔRedæáf`ääbøÏÁÉ🋇á##ƒÖÃÇŒLŒR@#PÃD·àæââ7×ÕQýþÕP—Kw¹­©žÀßßZR<<"œŠâLŒ\ Œ\@ϲs2üeccøÔó÷ï_†ÿþ3üûù“á×/&AA9fNj@Ñ$„„…¹}~>¸g ÅË©k$À«¿ÕÁDWš—GŒ‡U’•‰èQ†¿@üá0fÿýýÇðXýÿý›á?гÿ@lFp@0Ù š‘™™AR@€Cãõ{FFƃÿ©P€ÅÀÉËË¡"%)i )n¬ÆÂ c,!ª»ÙB[OòßY1vVvGÙÅþÙÿ˜˜~ÿýôì?†ÿ@OÿÿöèY !þzô?˜ýï?#˜û“geeà`PþýS÷0##Ð`†”º €H NAVU 1 #Y)ž·¯tb`Ñ1dø÷éßÇ~¿|Îðûé†ogN2|9yr¬ ,| ¬²ò ìª@ª1°+)3°HÉ«Gv†?@þøþƒáã÷o ?¦‘/àTñƒƒƒAXXì6mmMnnnJ €ÖW?~=ÿõë÷ßÜB"¬ÿÞ¼d`ÒÐeø,Äyù˜\íØÀÀLâ\ ÙÀ@ØÅðû†?Ï3üzäñÀšá?³cU 8’U^‰CS›ENÒVm?ÿaø Ì??~dø lp=Ê V æ¦<û7Ю?µžŠŠ ¿¦¦¦°8MI9@àʃG÷Ÿ}ûþRõäA™Üü Ì 9à”ðÿË'†o… ¯\`ø L?îÖÀ¥5“Œ<›†W@›º+0Yÿˆÿ€ž5à?cõ÷÷ïàØ™ö,PŽˆAfððð…ÿÁÝb3k PË„Aê9 ý3g΀üð›Ü ‚ðƒ…õåõ×o/©šÊ0ÜÍð”ÔÅ$Áíó?çN20)ª2° ;f`¹À¬¢ÎÀ ô8°üªú¿cí=°†øûö-Ðs%ü?pl ›µLÀ&/Ècð,ŒÈoß¾åAžwWAU*4‚k›_ ô<8::,^¼XÈ|InÁûþýÃíû,ÍÁ&IY g™Tµ8'C\Hý°ÿøù3ÃÏ×o~ 9V`‰ŠY lS0°p³€=óþý{°Ç‘=bƒ< ¢ƒj ýhÞŸ6¨À , X8¡n304Òaae“¤$g12Ê$ëhGÏJOdÖÖÒüíãÃÀšRÄÀ Ì·0ðáë7†ÀêÔ3ýMš`ϲ03üzŒì!XìÂ’2ˆ Še`^‰’õ §ÿiP3ù÷w`Fùü•áûû× _ž?døùþ93$ù?а´ƒ€”ƒ”ˆ„¦(É1\ 7#âXYu­MŒ÷W•GòëhJ£áÅ—ï ßEÍz”|ùîå `I êéÁcä9ýå˰'ÙØØà1 “HT¨Ô€+È V†oÏo3Ü;´X“œc`üp™Aí3+0° .%†/§^übgøÎ Î(ð¹ÄAœQøÖ'†5ϾÿJj|D(ŠŸÏ.ÍÂ<ÍÒÉ!ˆ]IXécîç/°•o…Õ?'7QU5ÍOž<Ç"È“È1(0>|øö(0p@ù„Až©Å6(6Ø€e ;'7Ãó«g®®îcøÿh'ƒ¼Ðg%`Ç+4 ØÚd`ç¶€M``øó˜×€íŠÀf7 bxôœ…á̵ÏöÞþ·pß †É/¿ÿNlc®”dx¬­u²©•3ƒ¤$¨TUo 0cíó§Ï _õ Ä-­‘4¿zõ ìP© ò¬”yô+°àZ° T€ ”E@à#°Ê—’aø ¬ROÎocø|j:ƒòwe`-",gÄ$€XØþàU =l™{U@÷[”_î30¼=L {9ÈðûÝ;†ë7™œú{{ÞSÆÚ ÷ÿ®$&ˆñ’§ûݬt{`ñ ñ8† Fp•õBBŠAÊÛIê30ø_¿~ N ÏÂR(€b”ÄEDDà%:¤ÓQóéÛ†_ož1œžœÍ Çx‚ÁÜØ>‘c`PLâ(>ÐÄÃÿþ@?ÌMÀ€`dÐÿ€n~w‘áþb`RXÆpîþ†üï ÷.ý™ðbÃÏš¿¿ÿ}ÅÄ»ÿ@ûA+s~5UìÍÁÿÀ†+Ð’· €ždfgGt± JÚ Ø%u\€ä >X9ÀÎÍÇðàâi†ó“lµŸ1¨hÍ”ðb`Ð.g`жÁ@’91í`šäSV Í 2> »ÿ´0yvˆAž½@–—C•)å÷§oqé æ—þ>àxþBÒÁÆÊÛ XU GÿÆæ`kŽXè!‹ƒb”@žG.ñA’×  !®úÿ7°ç÷øòi†ËS\MŸ2Èkò00(eÛ¶U QQ`Gé=0¾‚úÐ@üJãÃ@5€êÿ~aøÀ*É $çÂðößk†Óï/3°‹1ið °h–×n«¯oÀÚi  cÿò22öøíÙçjèã¥Î 胬ÿëw`¬ˆ‰¡È£Èȳ ‚VçƒÊ3°Óóûëg†S“2œt3H©›ÓòéÀˆf¿÷äÎÈHÆà>°Hæ’{¿>0üfeb¨4¨`u›VÝ^Å bÀê+ü†µ‘‰1ÿÿ¿ÿе¸Dúüÿÿ=Ž úsXÄŰ–ì@‡}öÿCìCÉ *  *a P §n^†ƒÝm ú×u±- L¶~ÀäjÇüC5˜Ù"|l7ûÕ7¾ÿcxÉ t`;‚Xv¤h¦0¼ùù†aßÃ} bÖ¬é\÷™Ž/E× @ðvèÖW,_µf38°Ä¨þö xЂ->{} ò8¨@äççg€°’Ÿ‹—áÞ‘ ?¯Îf0¶¦siO``¿&áÀ$ ¬Ïþ|†Ð0ü&ö Uü/L "~ãËG†»¿Þ1¼¦¢??2¼ùñ–á=0+E«F3È È1¼áýÍÌíÌÔÈÌèˆî/€bAj‡U`blq47³–±²b–ü¨! #°êúçxð€zÔÕé°ÂVÀÊÐ`Ç_`kñÖÆ “Àž$°N—ôç[†ÿ¿ 1̈ãŒØRJÄ3€îsì…o¿¾0ÿ*c„§#‡…“!@ÁŸaÊ—© ßåÿ)sé3ÅÝÔôÔ!€bB6óÁ¿ÿ§ZV¯ŒNðØjZaf`zâ°¾E-˜àÝUäÆH&÷ý÷_†»Çw3p;Ê ­lÔ˜CHÿ~ ‰ÍP ‹Ý0HÍÿÏ ï¿f8öéÃËÿo€eÀG8þ ¿)áûk`uj bÀð…ó«c,#+ƒ²û£)<çÑãé¡›·ú8GGš¢¤`l²“8¸ ”‘A-@ƒÀB”À%=ƒÄ@ô¿_YÉ §TÌì¼ñª“ö{И4æ1ÍM È…Í̲á÷_F†ïÿ0Üc°à®$ö™€mF`‡é÷ß_ }fxùíÃ?ß…ã?Yf%V¥¿N@Å÷`FFüùÿÿµ{³…©Éjne%vÐŒ p0Ûð r-é€Ú?W{°¶>(0@âŒÀ”óúÙSæw¤€ÍZ6 HêúûâAP“û?(Éÿ‡Ð ƒÿC³ÀX€üGÍ @êÄÛ¿ ~;L¬?ÿS°àõ?þúÈðèËC†ûŸ=ÿ˜€‘ñ<ÀËÀ$ÈÆÀªðÇ ˜ –Ý ®îkoðäÏ_;¦,[±¤¼²,T‚›Ç@±±ûøoÞÀ7È)Ô~È !pV`egøðà:7Û V`µÇLÿ¾€‚ê¤B—‘5¶‘)ÓކݞO_Þr}e`ùÏ vÏÛŸ¯î¾Çðôë §d'° Çò0•°€zTJ,Æ_™æ ì¿ÿ¿E»¼÷tÖñpS€e&f`i¬Ç›À<@Ï“´±ƒÜS„·ØØ??cº‚¨Øãcøûh´ 31"ùÍÃÈÙhÄ{`»gãë Ï8€å°,{ ,ñû¯-Çßÿ žæf…Ì'üý|fæð¸#“› ó/QXÎñ€7ÿÿßòìX¯¯;ƒYTÒ6%í?¿¾Sr€< P~¥X§T|jûö惘Ð*fPû˜ÿ‚´8‘‹~t6j”E@žY÷äÃ5¦ _ÿ¿gxõé)Û_¯ž†-(¦ÿA<ýêqf˜ç! Ôcdç`ÿ" t3¨'ü €˜ð5°6ø°tÕºÛÀ1- Ø@ƒÀrcÚ Ú z¬%Þ¾} î¦F`,1þöéù9¡þ €/à’ÌGÇŒ@qÆ/Hø3ÃæŸ {_þ`Øÿë!Ãc¦K ÷¾]`ølò²=Åô<ˆfƒafÍ ¤Y¡4 ˜öC8Y™¹DaÅ@áÿÿÿ‹2°m`j%ab$Àðã'ФÀšTî2£(€Z}°‘!&PyÀl1ývéy ±ÿª–ß™ê~D@£Òÿ¾}åf¸þŠèQ&–¯€e +Ã/–ß)³†ä? QÌÐØå0P¼1ýE”§ €`Ì \P‹ÿÁ1Á»ÿþ/PR˜6A]­ŠRØý{ÿ<ƒÃ dÃ< qP € DX!nÿk&†_?¡Á ªÇaÀˆ†™ Cä`•›_¾0Ø›2Ü|}œáúû“ ÝfxÃô„á ë†_À†Ðïÿ0•ÏLH…°@þóõÿÿŸ Ÿaù €ˆšžrÿá” -Û½ì¢Â cóÇw†oÀ$Î* ­>XÃ6 Æ-Ñÿëef~†Ÿ?`!øû¤ŸÏédA<ŽÆ†¬XE+3Èœ Ò¢f Jº V_CÊpóí9†'¿¯3<úuØxÌðX8þbùÁð \"ü n`|ü l~fx b ¢Ø6xnÍÅÕ¼ËØp·Š2++h<ï5°  xu­ûAmPáêhfö ÿ€Ußàé1pûêAtš ÉãÈÀòÜ“ü ܯž‚AX|c7ÍO– iD†W_2\y~–áâ«ã ÷¾^føÁ÷áˆÀ×÷?À*h/+7ÃËwï?½ÿÖ¸ &b{œÇ¾ßquc†Ï@Í4`óä`¶€Ó0ÌÃŒ(06›âœ\ Âââ lŸ?1œHŒc8U_Íðôì)†Ÿ_0¨Iê1%2Ô{Ìd¹fsúÁL†eB—u«~¶aPfÖaâ’`àaæcøôâë`Ü¿ €Ü @D/µ DmßCGœ5l¬dßKú? N4¿ƒ0(ÿƒ:F IX[à?° Î+£¬¯yþüä 00þƒ$yfhqŠx*@Ž}&hYlÞ2±Bæ€Åú·/ߨÏîg¾¹Ÿáñ‚^†›ü2 ’þ! ò¾þ r– †šöÿ;ªzªÏm¸Ë,§-a#¡!â e¢c÷]ü‡ÂÇ[_.cîÌ_DÒ ‘×ÿÿ_é^£¥1‰Yà?x¬´° êYX+”`lP5È!Œ5`‡äÍÛ º" ?_Bê%P)Å M ÈYÖêa„†XˆÈe’<Œ úÝ úŠú ŸÖ/f¸¿mÃÍù½ —¤Tþèë22{^ýù{õý³u,då`WäRb3ùñüïSä¥5ÄDêàËú·o®Y¿i00ÖŒHÓZ dkB v¨=ðúÕ+[†W7 h²ç²9©îyp]Ä ±Gfä&.p©õéÓg†ÀÞêPýjäë[3ðUô0èo8Àà>k*ƒ““6ƒÁõÝœÝBÿ¦u20œ‹adœkÈÈÄøó×ç×>¯þûþÿ1X?ˆäERÿþÿÿ¤ÁÌÜl¬¥i.`aÍ ó<Œ ˆ¼|ùœ@#xÒXgó›º3Ü¿¾†áÃÃÿ J’¡mq ç€Ýk¦/Ðdr+ƒÙ0>(p¸€æ±0p{uÂBB ŸAêß¼``¸u¼ ÜÁRÖcàQÑcÐ Kbкs…ÁáüqÙ§Î$ݹó"é«¿3÷Ÿa`Ø lï{ÿÿ?xZ €ÈZ%vãïßCù’âÓ[|ýÊþªk ô`% Ñ äÀaVA"VÉ 70ð«³Æqˆ£™Aƒ4À,ùÿ#Ô9 gC f`¶egàáåeäãeø ¤A‹*>SÔÓ{€÷›!å‹°$³k0ƒ´+ƒôÓû 6×/Ë>¿t5îÉý—q>þ]ȼkýßÍDö2¹i/^MvX½Æ7ÐÕ]ó/hÁÓß¿ð Pþ‡ Âgxÿü`ÒvdxqÓ#d] ¾_úM¨@Ò@úlùõ8'$üg—ŒLìÀ®+dNòãðò†ï@=/µü€ôX ´]vnf#+]C™W,N]uôeô†Ï +ˆìøýÿÿKM͉n?Nçâçgl8”ôa$àIOèÀÈߟ¸¬2^o/aà•fdÐUzâ.0â¡ñ8{†ʠ!°L`åâc8uùò«žæàÕ_®]gmâäJzœ‘áÕ c~×'LÿEÞGêX Ñ/>~ÿÇpüë¿3€ €(Z(yöÁƒŸ>}«ÅÏ/‚<+Êÿ ápPj€ ‹²ËÊ2üœÌðd}>+·0¦¿_‚п² QF¤^Æ_èhñ'&`Wöùós6mX×­ÉÎiÄe¡œŽù·/ =Õ¿ 4‹ôÆþ‡È úã[°™çÿbØûïÿ: ç@Q¿üxvïÞ½ËZZZŽð…UÀ”Å>Èðõ°Y!ð@ª¤*ƒFì\†û+Ó$ÿi1p¨I´ T˜éB°24×ùØÐâðƒ——ç;ŸÄã€=S`Ìþó ÂþóʇÈó jÀFÙ[&1†MŸ]¼ÊÀ° ´~ €˜( `¬>zôèX>‡z O Kj.`£ˆ º $ZýqãÆ¯›6mº^Þ9ksþâ‡Ý«›§œø~ ˜÷ÙÜ€X5þ– o ú - @3Q¼àV$3dbXþ±1²Ö(ÊX’y@Ïÿ¦ŒŸß eÄW`áúî=høšá/0àw^xùký߿Ӏiã!Э¿ˆâµÂÀpVøÁr(Ì‚¦Ãíf`‹ñæý_ç:¼ÿôõëG¯_¿~íóçÏ (áO»xo<™Rm®àÂË côì !@é@SÅv°W ubvöYùø½È(¶Y@žf^Ã; ;o |Àl¦cÊpüøc†9ÏÞÎæýÐÁ€¢8Î;w4)ª¢>>{Æðýí†ß¯_1°ýÌÀtë6ÃêÕkvž:=ç1ÃaPcÚ ûƒ46ÿ ˜:Ê7_;º9yûéÌ@[_9 nY-`÷Z%r€û,ì\à¶1¨#Ä J ¶ À…à/¨çac• 2 ”Ĥ4 Ξ¼Ï0ñÜ-û¨Þýÿ2M@ÔH233Û^¾zõÕäÍ+£ÖÌ´`Ð ò™}žÔlÞ:oçûk¡kû¿Â: X²(0–¼Í8´×ÄQm¯§‡¹¤¥º–¶ž„¢?¨330¦ßßU ¿YØ ÀÉi'üþnƒöþ‚ò?P½ºÃ5†;Ï0ô¼¸y C=ÈÉ@ûàMa€¢xÏÐÑ,°Æ;0§*¯uwYtòõÛGçÎÏæâó j”×H4"ÜL ÒÒ Š2‚ 2|\ ¢÷ß3ÜÛu“aY€‘¡Ó¼ØÀm‚œ@c) Üú´í+°«ýý xÕ)ƒ¼*Ã×ïL –oû;ùÒ͹;¦@=²^ €¨ºi äp`"Tü Y·ªs¾Qº˜™Rº2Á†‘€Æý ³´ðœ›¾—´˜ê#¤!ÊÀZ‡ADX&21<8p’aú·g½ÿ4õ&ÃFP•‡ó0@TÝ1MÊwa#®T2ó?´AÏ>¬Ll ¼-- ñ8¨ºv¿Ÿ¿dxvø8ÃñûŸ¯ºÿd#°¤[LW!àÿ±.¦ šl™ùOã½x¬ï^gºz™áÛ#†¯¯_3¼ôøïƒ+×>¹yçüÏ?žvv€T;}:å;>³hHnœTgf¶eaHùö‹AèÑwÀnÝ`3ê!ЧO Y蘆NØs4¤wŽ2Bö 1B8ÿBzë¤y €FüÖY€ñ@#> …‡ˆ•š<™IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/kedit.png000066400000000000000000000133771217176075400230300ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF IDATxÚä›Ûo×}Ç?çììÌÞx%^Eš»+ ¶¢XäR\Ò$´}PÓ'AÛ Їºé  RôË?Çiƒ$/±% ZYC‘»¤$‹&%AßؤìÊ-í…;sú°rö>K.™9ÀbgöÌœ9çûû}·3+”Rü17QÃë%›Ë ë:Ùlv»o|$ÎñÏ8öìÙ¿{øðáÚbW}v+ž_¹sûã<·ÇVJ ]×½/¼ðÂ?////¯U˜YÙŽÄÉår?~ü‰ñññ¡?4i:Á°, ¥¦ibííí=åî) Àæ–ôØ‹7- Ó4 4Ã)ÍbÉX•¤í\pñ±­ •¨.k©g.—c">JÎ41·®497j[OŸ={.öq¹s)eÙcçõuàœŒišX¦Uv‚‚S õ‚`×¥΋Ÿ‰cZ–²\ªý¡’fQË*?­ÚClÞWºÙnëëë( «³3ÿÃÆŸy „¦*°©¥¼GT4Àå4wÛà´ ;vA Ð=¢¦·©ÀD|ŒÍÜf ï‹¥&„à7ÞàùçŸÏ?,—#¨yºÜWÃXl óÇ;Ò¶¿¥”õ`š¹mkZËõ\¸p¡À¤R€(˜¬Ã?—=®ÕgëÚ[•TÅD¨±.2ï†v0œ={¶p™–EPšàÕö¬ÊëëëL½ôó•¯Çë£Z²ÖP7Xr.–£JcYj«ZSz^©ïãÿo~ãüæ½÷0¼:--­ï«4ƾـZ‘ §À¦bÇè«"}.O‡O<àG¯¿ÆŸýéŸðê·¿™Ëñ£ÿ„æ¶v6R›hš§& Ißðì¿´#A€Î­HPAžš{ Ü_¿Ï?ýÃßsæÏ¿Ä¿¼ø­‚DëÙgŸÅ§AsÀ[—ç(®B5ŒÅ5¹Ë—/sùòå]çÿ™L†+WÞbâ _$>ºÃó™k×Hg2 vU‰> (6‚X--O§(°òù¯L:ÍÜì =½}>~·±Áß½ËãO<Áw^y•¯ëE”ÔÉš’¬iºòJ×#ñéò÷d„ M„æ)I†œÇ™L†Äì5B¡ †¡aøt’‰œxü8ÿúú #Üw”¶–š&ëö"nšl„p–¥wWU6²3™4ÓÓÓøƒü~€‹·Ð<‚Õµuæó<÷Üs„BÁ-ÃW’T<¯†ÆN¤ßyç0ç#0à3˃Ì”n·ïÉdRÌýâ~~?†ácñæM°Ý==,ÞXäüWÿ‘–ÃH=À£¬Uw°¤yäþÖœU×ÕÕÕÂß¿0OIU&¯ö3Áº®sóæM‚žž’ Ç‹Ÿ&ÜÛƒ¡{J66Üæûf‹xæ™g ÊÒXRY¨"ɧÓi¦§¯„x5/7oÝB ÉÑ£=$“ùŇ1 cëÞÝ¥Ën3MSS-­­¤R)––– ø}tww3??Ï“ƒC ž¥»7Œ)¼¤œ)´Øm*ÍvUxßÜ sà§Ÿ~ºD+<ÙGÌ_Ÿ¥¹©‰ÖC­’ó ÆbŒŽŽÒßß¿-ùêª\!™ªâà‘{ðõFT«««X–Åûï€?à§£½‰É/rõê4wï,GYL&ˆÅbŒŒŒ ÷£ë^v¼jÎþTƒ«J¥êRÿ3gÎpåÊ|þíLLN2=íXüâƒCC Äéëãñ˜ Ls›v’EåHPmÅN-¨NyÒiצR©mµïìp.þ‘H”……ž"vz„¾¾~<šÓ¢âBKÔ¾¢„+m–äÁRB¸¢AY4Ms%ýt:Í[om-¾³«hñaˆÅ†J8_KåµYâ&(»Òÿýõ=×’7üɯÜ!‰°˜L04œç|__º®7|ª–Grcvë|—.]F7tzºz ?eq~žOrjx”Σ} ùHçêqmåÜ[‘šSn“uç>Þ]Ú€jí¥—¦kš÷˺Ϡ»«›‰‰­Åß½CøX„ÅD‚Ø3<¬ëú\¨¹¥uàX´{brRØÖ>=ÆõÙYictt”Ç{ _6‹ÉfÞ‹Z<¯D‡Úµ€ÊtnÞrÀ+¯¼Ú¦iúÜ¡¶ÖCÑh´ë©§&<×ìÅG¢$“ tÃK{{;½½½ykŸNç}qMõ/¥C9¿:ä•jÉÐw¾û½C›™ìâÂâ܉¿üë¿brr’k×fXY^¶ŽÈdbžÁÁAÆÆÆèííÝæ¼òxx¤4„)J·]ÅÕ“ŸÊÁR^‹ì\ÀØK24õò+­Rzo,$OLNN`æ²¼þÚk<øäÓÍH$*“IN:Åððð¶äm?lƒøòÕÑ*j[„FKuoŒ žüü‰O<øåÊÒíÏM~a‚£½}¬¯®óËwß% ʹ¹ÙÌH|„x"ÑcÜ»÷+îÝû5-mmÜ^zûþ¼Ã6x¶äÝLÆÍFénï­ôÜZ/K— “™mnmfþúuþó?~ÎúÚ:mí‡ùpuõ·oüìg/D"‘µz$ïvâµT¼žþ=•Ä~óÁûÓííÿ~¤íð—o¿ý6g¾ô|üñƒßþô§?ùºeYïôõõµ´´°±±Q3övÃÛJ×ìeìbP*"ª½ƒ ¿æ÷ûÎ~߯êÚú‹¹ÍÍÿÞŽõ÷÷Ÿ6M3çVíVï¿Pji›"¶”R---Í|ôÑG÷ê@lù ø€ð)Åùú>¶ƒh¢Ö¿0JòZößLíÿ ŸåƒZÅéüIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/kfind.png000066400000000000000000000167631217176075400230250ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚä›yt[ÕÇ?÷i—,y‘å'ŽÛÂŽí$ÆŽI„0¬t [èœ9Ì™Lgè¦ÐBèié”=…vÚk‡´L\ñ„ YÊd3N/ÁK$Ë’µ=é½7ÈrdY6Y”¶çôžsÏ{×z˽ßß÷÷½¿û{×BÓ4þš‹Ð4[o½õ«V­ú‡P(ú„8¥ßR%ðlíTMo§ž­iš0†Õ«Wßåš1ë=€77®?eôn·»î¼óÎk:™S”e™ÎÎCC!FƒA IH¨šJ"‘Àfµa2›(,ȧ¦¦NwR`¥ªªªhš†¢(˜L&\.W™‹±ù7O‹zEQƓ͚™BpèÐaº{z±çÙ))qárÆ…BÄc $ Ìf#V‹ ½Á@ÿÐí[¶ *õsk)//ŸÒÚéΕ•sñS__ϼyóøÃ›ÉßúwÜñMÚ6läœóill˜VΨ ¤[^QvîÜMžÝNx4À?Þu'·ß~;‹/¦¸¸˜c^/yyyØíöz‘NJ>·¨¨ˆ¢¢"ÊËË)++Ããñpßê{yä‘GhÛð&’$ÑÐP?Þ—tê§»Ã×€ŽŽÏ$ÑPûÉOxàhjj"‰ E™SY™õ¾”¢§ëHf[Aqq1ç-9§ÓIAA÷Üs/?þ/¯ûÝØ¬â¿6uoÊÒßsº%+”ƒƒôööRRTÈ~ücV¯^Mkk+Ÿ÷pÖY¥œuVɤ¹:3¨™.àIëuõõõ\xá…\rÙ¥|ÿûßçk7¯äåµëåøH¯¹,Rf'#‘[ß߯ùç-æá¬á®»î¢±±‘ÎÃ]ÔÏ­·Â‰”ô©+©VUU‹-¢¾±‘W^y…«®\έo›0ølâ¨æ€“ص{7ç4·ðÚúõ\zÅÔÖÖ2tÌÏü1qÊ Z¦‹àÒšªjZ[U5T 4 *ç$A8ØÑNhÄb2ƒƒ,/IÒ$×Ê)áp˜O<;q;ð|ìañâÅ TÌ.ûBËgºAú@3ïËAÑ@ ÷Ù ,[¶Œÿxê)®\~ëÛ6N¢þuÇÊWñzÛë\qÕLyXmV”±PtJ*güT~¯¥€M$Ï*MFæ64ãÈÏçho½¯×›U4MCÊRº¿~üñJK\éécfy:£ M/+$‰óûÔ ³Pu*&¨(c ¸Jf°àœE´oùÎ=w!íí[&ø:tz]nÐ4ááal6GzŽP^Q…#߉ÍaÁn4 è$䄊¢(SjÀøbebÄBLЀIšÀX[ƒ„ª¨«ŸOTV°çYèêîž’úªšCܾ};‹-f߾̮¬Bg´’oJŠNžA* ¢Š2IÙ³Y_›J¤Ò.„¸¢áÈw2gN-}Ý=Øòò‚YˆÇsÀŽ;¨¬œÍèh”‚'’Þ<q !°êuh";ü[Ó©eJ–0ö›–@JT@Ñ¡£ªºŽAï³Î*ãÀÁƒYEPä "Bבn =&³ƒ1¤É‘œelŠ©êø=UMËja1Íü¯Ž±BC "PTPH¨Pàta0˜°Ú,|þyV70¹Àd2‹Å°åå#éŒbÒœ+I¦1äŒdÆØ…¨„ŒŽOAÓÐDÊ’ƒO(`6ça³ÙÑIz"áHÖÎM9@ MQ°XóЄ.»Ð !0 ^âc–W§òïLÊ –ESÏPÔd'@§7a³çÑX,ûK§Ï B%$L&šÐOLÌB BMŸú²X_›ø‰±@:cQBY$ ‡ÝŽªÊS ¯¢$rÇYŽ¡:ôzªª#®ˆÊëSV&û«¦ ^*Xâ8í“q$¸’d€$Àfµ‰Ä1™ŒYg•x<‡Œƒh€A'€Ñ°ö…I1Æ€t«NŠØ&¨}¬t()¿WqE Ç“Bh4€Ùl&0Äb6g ¤¢Ñhîp¹Š9æ;†=Ï‚^’G¦âÆi˜áßjʪWÓÄ/5ðÔ´—P!žÐˆ' *ƒª‚Ù :Fÿ ³fÍʾþ˜&&9éH°¦¦†O÷üvt"A"ÏjF¯“‘$èù\¨26Xuì˜DºŸ§[<ò)1LgF €DBCNhÄâ‘!…|G²c=}} FòÆò™³R.ÖúÔƒ+**èììÄÅf°’ÐCï ”Ï£8.d”ÜØ¦Oÿ{(RºÒ§æú”õU,C4‘(ŒŽ‚N@iQÒ(ž;™?¿ajë )w ˜1cMMóx{s;……ò-’Y"Dˆ¥!Hd±pŠ .q!PÆŽ !ˆ*‚ˆÇá®ÃܼòÆi÷$³É•¹Í !())aÑ¢E¸Š yìÑÇðù}8pùbp@Oô‚ßAr£Á¤ˆ…‚É«¡ÐØo!@FüàóÁà(QXXç×%ßÿÊÚulݺ–sÎÁf³M¹yâx(¬äþÈÁ` ¦¦†K.¹ŸoG}¯×‹]‚-° ¢£Ð߃àóÂÈp²ü $ðCÐ £~ø’mß±ã÷XᢅÐ2fùu¿ÿ=‡º¸í¶Û°9¼óö;$‰i3P9û4–ùÙÊf³ÑØØH4eÓ¦M<ð½5ÜùoávW³Ø Uå°{?ô ÀPôf°˜@§½n Vu,à‰CL9–\ôä[ Á ­Õi¾üÌóìßw€‡Ö<ˆÝf&ßQÀŒÅX,E#&G1èõ9O‰OÒ€ôcaa!ÍÍÍ\}õÕØ¬Fîº{5ëÛ^GU㔘á²&¸æRh®…b(±$ýý^ð %/„CÉy}ö XÖ7.;>øîîÖüàG¼ºv-³Ž·ßz+¹.).bÃoòáGÛÑé³™h4vF¦Být+=§ÓÉüùó±Z­”•í቟=ÉÛ›·pÃu×pѲó)ÒIUÕÉyÞ/'….IƒV(ȈX}^/¿_ᒒ ›°Zôüð‡c4iooçÃv0tìû÷ïÃãñ°ÿ³nûêW°Û“ÉQ«Õ’{¦Êß !(,,¤±±‘üü|fÍš…ÇãᡇÖP[[DzeKiin¢ÖíÆ I¸Œàš"K ‡ñìÜÅÖmÛùàý­C#ÜtÃu¬X±§ÓI,cîܹD"£ÔÏ­£««‹OvîbÓ›è=ÒÍw¿{‡@ ˆÝžwæ÷¤·- n·§ÓIYY---ìÝ»—µ/¿ÈsÏ=³¸wM ³gáta0PU•H4Ê@ÿ‡¡óp'ápga>Ë—_ÌÒ¥K©¨¨_Ñ™L&JJJxõÕW¹ûî»i=·•¡cÇèî»‡{îûW¾ýÍ;(/+#ÑÔÔTœ‘`>¥"4Mãá‡~âþûï¿#d]ú¦·UUÅçó1<<Œßïg``€£GÒÕÕÅÀÀ±X Y–B ×ëÉÏϧ¬¬Œššª««™3gÅÅÅ32ºB†‡‡Ùµk[?ø€;﹇íÛw°éMÈñ8f£E‹óÕ¯ÜLkK ~¿ÿ,ÇW ô‰ËéTrîÙ˜Ê »\É ‘H„êêj"‘²,ÇQ”äg4N‡ÕjÅh4bµZÇk¶ X©vÊÝdYæO<ÁÿòM#¶ly£Ù„Ùdgí+¿ÃçósÅe—T¯ ý“ßx§ À‘8m8wÈt ‹Å2ÁŠé)ôl,šjZªír¹X°`ñxœß¾ø·Ür€ŸOvý‘üü™ÌtØÙ²å]ü~?7Ýp]e‰ËõŸ@ð[¡pô5›Õ;íý'Úζ? }Kˉì™êcii) ,Àž—ÇæwÞæËûeÎvW344„É`ÄívÓÑùÏ¿ð"€Ëá°?¦Þ …̧ ž ' ÒÉl¡™5kÍÍÍôööðé§äúkÿŽÒ.Žö÷# p»Ýø|>žyö«Íf}T't«B¡pÞiB_Ôñ\€r¢÷UVV²dɶmÝʰÏÇ5×\ƒÍ–Gÿà PW[GB‘yæÙß ‚Åj5?.„t·Ïç·Ÿ2¾hH.ʉd›S9Šêêj.¾øb^zé·˜LV|éJªÊÑþä÷Âú†¹Í&Ö®}@X­æõzÝÝ}}G­R 8S¬0™L¸Ýn–/_ÎÓO=Å̳J¸âÒ‹‰†£ôíCU4æÕÏÅl4³îµõ8ö>ÔÕeú“jÀ-_O«ÕJmm-K/XÊ/žüsëjYzáRüþº{zPT…y ±[m´½¾@_âr®1›Í«uO‚4Ýn\€p²â7Õu‡ƒyóæÑÒÒ“?{’:wµ¼dÉb¼^/‡ººP*MÍMä8xcÓ[–²ÒÒô†U]‡ §í äççÓÜÜLËÂV®\¹Ã]]im]ÈPÿÄc2ÍMÍñÖÛ›Ìåe3QãÚßï?p@œ¶ ü%€PTTDSS|÷æ›W¶Í©œijn¢·¯ý“cœ»¨…®b¶¼û€Åí®þaLN|í¤¦Á\pªÏšî9ÅÅŸ\®#í›Ûóõ¯Ýü‡òÙ呯†ºŽt³wï>"a™¦¦”––°ý“]Îó~òáGÛo˜òÃÈéŠÝŸ*XJý¿€Ãáv¶onßÒ6»¢Ô…ÇãÀí®¦  €½{÷cÐIóÛúÁ‡çŸò4øç–2Þ¡C€§½}ó³×_Ý:»Í6Zívs¨«+eyª«*1™ÍttvbµškgWÌ~bÚHðLi@.X‘¹qKK/àùðß½öš«_2 A·»&™UÚµ{9CE¥|fÙüiEð‹¬y¢Ÿ.±’mïÿt¿Ÿ@FxØÕÑqðÅo¼þ% )PY9‡î#ÝìÚýGê‘X³æMÈèõzÌf3ñx|ÚNÈ ¦»ætž Š˜¼õNB {:dÙ…„Û^ßpËœª*gWWF“‘úºZîà7}ìÑ'|ð{ÇSb---‹+**Z”±mW'ã'ûáât4&…ƒ$IÚÇü¶×ë=”í~!DP \»aÃÆ[çÍ_Pêóûx衇ÚÚ^{mµ¦i&ùééÔ?g™¦Ov xxÕªo¼ïr¹~Tg^'r1€3ñÅ&3"¨ò=š¦ eÍ ÿ5—ÿå¼À ÔœIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/knotes.png000066400000000000000000000136001217176075400232200ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞGIDATxœå›i¬%Çu˜¿sªºïö¶y3CŽf4Ãe¸“b¨Ž¶@Q`ÇFV+°à‰[ˆc'rb±œÊ‚À1‚l Žõ3?”† òÁvl )’%ŠKH ÉáìË›·Ü÷îÚ]çäGõ}sßpf8Ú Å*àÞî®®ª®sêÔÙKÜä=¯qjð HàŒ„à8šëAÜÑ€»€„\ ( ¸ ˆç{pÇš±ÌAAÌqõ<# –p ˆîšÛ‹’G Íx‘æ!ß‹H3™Í+fà‘4úÝ_Ž' ‰„ƒoG¢º(HPw HðP¨z îâP †8… ’¯.*X‚zÜÄM!G7Hޏ‚%w31«jn¦S£Æ]¦†;Be޹y%xª¡vÄO LðÚp’á¾exe ®Àqñ—>ÝŽý4Îýye\ðúJC$³-"s÷š)¥šÕxóòG›öÞ4¥©k(a·íîoÖÆòÊ8Í›ùîißÔ7Ͼû޹vóóžÕÍæµûn øLÄ^M+®-{XƒÍUêžÁ}÷yö¡k–Ò W‘gÍxêM7m®Ô×™´^sµ¹y̾æÚÌ7Ëc@tKx]Ùµ¯o\®múV]çw ]ÅSš¯Ÿ]ç)×ÔÏëV¦œnüÊó*D,áU¥7nùçµdñÇëÚ¯¡ùkʵ+ò–ƒ_§íüÖ¸¶Ýõø ×´¿ÞþþvŠ+@KXµƒH˜Û‡rõ;3=áZxfsu¹º—­é€Z ˜Îõoö®É÷î4‹Aiih˜žÏaÃTÝš~zu>7!¹a7bµ÷0$‚5T{žvš-çLØ›çt=Ná»Ö pÌÅ¿ IøV<èföŵï®ÎèþfÛ¾õ8qÄhhë¨XÊŠP~ò›¯ÚŸÇ"Ípnîÿ_Q@2§~÷§?{ ʱ㾟½‡…cKx€zX#· ‡[£ c¸ïê“ßáâYºK$î‹hY¨Õί-¡Xla±jÊÎ+[\úÒ:—¾x…ç7míð‘Ï|˜z’xòŸ|-[¼ýoá|/e¯ÔF5œ"1K§žÚÌÒ}+4ƧlŸËÌäüÖŠÁÓ›e|ë@O‘í×¶œÚ‡ömVîZ ±À¿}†3Ÿ=Ëèü„ñÖ Ê÷.qßÇï \i³xW›á¹)Vîü;‡yä—Þ§2˜@·Mì´Ø9Ógº9aßñej¿‰|Dw#{5¾u&¨%í$B/`cËt®B±ÚbûÄ€oü“¬¿ØÇ*ТbéÑEÞõ/î§ux[¯í0ܨYx ËÑGñÆïœá¾p'ûÞs'¤°)݃%*º 4–5“É6§ÿ%ÎþïÓ 7Æÿ‰{X}hª[XH›W…÷hc×A3£‡7Xªàƒš§þåk<þ_îB Å'ÐZmsáÿ\àkŸz‰9ûÞ)ï(èm±~rÀÚÓ|é¾Êþç»yÇ'ïçÏÎKÑ—ž¹Ì™?9Ïê;²}~@ÙŠ¥‹G—8ùg¨G‰ Oœçò³k,Yæ¾x/G~ø0e§Å¤?ÎFáM`ϦÌ`Šûõ4é½]t!5`bT; K†˜"@µQ±óRŸê’Ó»[‘¶³ub‡g>ù<ûÛÇñŸ9Âê£û mEBIÚó¥O<Ã¥gûœú½sÜõwïbxv€F§}(°t¤ÅæW×q/‰!a)@tŽ•\~ú2ÏýÆË,ò¾ÿúCþÈ1$Rvò²žp¨(£þ&íàî)»¿³4¸î/´”í<õ©×9ÿG”+‘P(fFªk´'Há\yn/#_ÿO/³ïñeÞ÷›qð/ÀêDµ1f|q“°¤<þë:5k'¶ÁXT¨O*V^åÊ«[˜O³Ÿ"%D+Ç©ÖÇü¥OùräG”ñÙMNîužú7OR¯M2Ü0´(ÙY?K¦Kà3Wìõé%”0¯½1`xjÈñ!ö„´‘ÐÅ@ØWž¼Â;ÆäÌ&—ŸYç‡ï•éé ˆE6g+'mLˆ‹=¤§0¨q)†ˆ§1+÷-2¾´U4u<±p¼Í¤?¥µÜbûåÓœþó\|ò—¾|þ•ø±{èn‘vª›Hõ„L‡ë3§hÝX­7Fuͽm|%RÞ¦œÿã+l}cÀ£¿|”âö˜²||‘‹Ooá–Øzc@=Q.¬?ÌN qꉣAˆûºœûÃSlŸXçøG 2Í! s|§¢w|‰ÚœÑ¹> oëR¦ødÄòñÊžò…_øSú'w¨F°úÐ*øµpäGïÆCRòkÄ®õtÚèZ‘×G€õ4Ð]RJ­©«=gó…->ÿ‰áï`ÿrü'Vyã³oPmM0ÏqŠÑNÍòm=ªÍ)¥íý-´×apâ _ýµѶrÛ_9 UŽ@¹:Ó±ÑZ*E`ó¥ î^Æë u•èÞ¶Èh8"]0–޶X}ïQîþ[wsðñ·¡¡Å¸ßLJ)‹ä³3a<f=À=WÅ5ºÝ"€+ÂJD…ñÙÞ»H¸“Ÿ»È¿üwþíµÜ6–l=w‰Å#*‡“¿}–Gÿù>Þ¾O ¯F¼ö¿^ák¿ùã³Sîùñcì¿ïã‹[M@Æñäˆ(íEãÌŸåè_»ÔHƒD¹ ¼ëß¾‹·½ç«݆”Š[Eµ>¢ž PuD妖m¥%6/o7Þb n‰Ð*‰K.}ò^BÞþWWyâ_?Ï«¿–å»z,¼ .}e‹‡Þwˆ…áÌç.°õBŸâ@`tnÌäܘíµ>: þÐm¼ç?>Žû˜Wè,8’ÀÇ>ø¢èÒ`}UM=ùéA"Óõmªi‚J4ÈÌÙyC8 ‹63™Ö1äzS-ÐòêtW#£^ gr¦Ïò;–øËŸ~Œ/ÿ»¹ø•>£õ>+÷÷ÐV›Û?r€“p–éÅU•¨j#´„Þ¡÷ÿ½ãÜ÷SDZɈÉF•C®“R&WFì¿w‰äPoM³_R;£ÓÙÉTØ(uµãUïA-u¥®ÍÐAb`2â)åÀH²)î¦7³£Í¨éïrñ™M ¡v°sCʃ?ôësñ‰ ȰæÀãû°jÌ{õQ}à¾|™î¾‹G»ìp……V2R]3O ×î¼':Ù®ö†gæpž„T;Rä¥P]R$D€™1]‘ª ‰Ÿ®£2ÜØ!ÙÌ'¨1/±ßLqplGY:¶ÀÖ‰-|8¢(„TÓ‹´¬8üþ}Y“تŸÙ"v„có0Ç~üX¶ôR]1YâÓD"׃ÌTÍ”CóŠ@¼b²P 4H3&¨FSúÏoråùm®|ùgŸÝdz~ȇëý¬¾s©20Ð"0ÜÜ$Š4š`ªÀ<¼UÐgºS±òŽ6÷|ìã cB¯l(°Ibx:rà£;ÓÓÛ¨É 9h!¢Y,̳kLã4s³C¹ÐBZJèv÷;Ø&;c6Ÿ½Äå¯orñ©u®<¿Im›: ‰1²|l…£¸ûÿþ»Y¼{…ÉÆ$šqHÎÖÆebG5`ÚDŠn\¤Íš?qŒz\]¼4kB[h¸Ot"s|Ë<Ù¢Qôívv×&LG5Óó5¯žeí+\úòÛ/¬±ÙŸlJ·Y8Úåöâï¾›ƒïØO玊….࣠ӵqƒg'ÆÀx8`°¹E( ðj3@\¹)#ªqLöY®[vÃfà»Ù5 ˆ]%öZHW3b*dž['Çl¾8àòÓkl¼ÐgíDŸá ¸P.¶Ù¼Í;ÊÁÇ–Y}d…î¡´[@ à5>ª©vŒÑÙujW‚åÜ õ¬m–ÖO½Žù”P´ hÝŽ¤‰ á-0ã“7óŸ¦ÆµeÄe(–#Cv=։頢ÿ|ŸµÖŸê³öÒ€õ“ëØp‚EX\l³ò`›G~æ«>ľ‡—iè ­Ñ£?ƒŠñ΄zm„Ö† XL(Tr°M EP¢¡ÀcäÒ¹“”E›‡HšàÉTÂ7iÌ~‚#HK({Š.Åœ3¤NªÛ®YûÊ›Ïí°öÌ€Ë/^Þf8P„‚Îþ‚ÛZ䎿~'[`éø2åJI,KÅmJ½]“ÖÇŒ'ƒ,ÊÔ‘F\(òªèÌçæd'f/”‰ÓéuÙl±µ±I··H(˼ŒH!K› Ár@W¢¢¢1;‚.¢›ÔLÎÖ“SÖ_ØbýkCÖ¿ÚggmȨžÒ.•å#ß¹ÈþG³ÿá}tïïRvÛ„"d?ý$Qïõå cB5Kˆ´Ýežs¼f¦øì¡JG´@Š€„@Tðîç¿þ,%%vZ3 ‘£³7p‰hZŠœue9R\OŒÑ¹ ý“SÎq›³²ÍÎÅ!©®)Ú°p¤ÃÁµyðXy´Åò±Âbg7À™*Gû5ãs;XÝDÆ‹¬Æª6™d­Æ‰êþ›³A„€¨"¡@4o;B hõ°ñ€õs'iu;ÄVI+„ư1¸5ÁÑ7FJ¥^¯ùƧû .N^ªØ9?b²QS'¨8C%·°Ç£ï9ÆêC‘Þ±Uh*-œ†ê¾1Zàž2÷OQs=fýgו3[Õ·ríí† Ñ¬Ihª1?/.qî¹§©k({e;"õ,M.U`• íë" X‚n VŒ·G½š#l±tç ûè±ôp‹b¥ :E]™+&SÒt‚UC\…h Š€Ùí€fµ¿e?ìŒ`Õ•Ø\54WA»m̦\xõÿRv:Äi—m¦3MÐm‚Doà¬Ç =ç]Ÿ:Ef<.9%Ï&‰4¬ŸÜ ¶€Lgþ}AUMìÙU÷)ߎ~N÷@ ­¬þED3ó“Ýe®¼ü“Ñ„Þò e»€¨¸9¨F“1r™)¤abkæM2‚åÅÓlB(ŠªC—,­í;iØ%wÇ$C %›Ÿ­~ˆHPD•Ðî€GN¾üUŠNPDZe+'agNѺÉj¸ù†‹ 2šüÕ7§2Ì\npSaò­•™Vå9ÚÐСÙ÷yÌ¡µÌæé—nm²´ï E»DÊì'PD·)"(³T—ïËâHÖ¬Ð]ÃÕW™ŸYAKܯåi:½E4Ê¢“Ç’€625 5o/2ô]+"ˆ8ÒŽs«|=ÄL 1‚ÕP–lzÑVŸ…ýû)Ú¡h¾U•Æ)Z B/ø~@€Ïþ­ ””‰efpó€7÷»«.±1¡kè,aI8õìó´zËHŒ”í2/šÝfbÑ OÁ ·Oû®¿zA ÐPf@ãÞÕžqû ¼Ð]µ˜v ¤ËøÊI¾ñù''´z=ʲ †ŽåÕ'"¡‘6á>¡ó½'EZÚhqãàsL.FÐæ¼@4ûð4âõgþˆ />OXX¦½ØEc¤lw2ÓÖcyªhjx@±únª­/˜h#þGE¤œßÏanõ̶@Q4€r¨Y{õk¼öŧ™¤)K«¢EÙ*hµÛ¨æ„U‘,¶EqIûß/ÿªð=#¤—É}—qOÆlêâHÉôÒë<÷§_`Ðß ·¸ÈbûZF:½eQd?ŒÌö~sÅËÐH¸Œ¹e×óœ¶6ž¯ã:õóïnôþzíð:åYf…¦XªHÑ}™ImCÑ)˜lœå•'¿È•WOWXÚV»¤Õm¡šì“]®ŸWEó˜)B BR$[ÄâWó¥wÓZòyQpóì|€]ψ.ÍAUÅ,kÆ ¸Xž–OÒXBB XêCÄ53¶P–xÙBZ„ÙNOSÆOqâ™g¹ræ±ÝeáÐ!h¸|¯Û!´Ê]CŠ|nHÐ]û Ì|’E—]xÚn’€,UÈg= Ú ŠI¢¨„ºˆh]á p*†JÄ-¡.Žºãx4b-¤@æÆ&¨qq™¢ÓÃC) ™@“¶GŒv6Ù¾´Nÿòe¶.\`k8¦ÛZ`ᶃ¨–”íŽR¶:ÙLGPÕHÐ@-¡ñ#\=¥ˆN»»xã•—þUoÿ¿5œt©R…y>ù¼F$Lvýzæ jÔvU=¶* …Q×ÙY’Ø0¯¢FGRÈzŠƒHBܘZ$XvŠçóiXîTã) X ¶E«ÃÁÅ’(}êɘ3ÝqFîy÷ZÂ%^M§¡H—Lî,öe{R¿òüæ¿ÿÑÇ@fçöÇ:ÿìS?¿òß´Xh²¸<{u% Ép•”ÝT@ ;’Å›ÃY¥ µcÑ1œè ë- ¯œ€b"ˆæŽ{ãqËÛ+€ZÀ%÷ª$œrR†¨#“L}"‚¸çñR£Ý¹e€g¬¬9[eÍê;Éakg˜>þ®|äó_ŸþYÞÅsŒïžcKG•`æžÌZæÞróÂ\J<µ-ï‚—fɽˆf."âæ^(bž!4pA]Üq±†Å¨ºc.¨Ü=¨à†Xj²nÜ AÓS‰Kjrû “©ˆO͘¸øÈÝ“ÂÀ܆•»ŒÌ¬6«&ãñ¸šVÉ._^³¤¾ãØ]¾°´àrƒ³Ãbî¨ìž3ÐQ Ó\Pf±A«a¨ó?mÞKÓVæÆbnŒ™'¡9¹«RÔ»›7ß7çz÷ÜOšŸ5uÓ¹ûÙ¸î˜Yúä€o„€7•¹vó1´ùØíµ€Íô¡pMŸpMß™>rö W‘2;:2C smgíwu0‘[K¿eܬ|cÌEEßô,×\o¹È­§È¿¹ïúñùÿ±?ÈtŒ…IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/krdc.png000066400000000000000000000265611217176075400226520ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF"ŒIDATxÚä›iŒd×yžŸsîRKWUWuõ:Ý³ï ‡äp(Š”LŠµÑ¢¬Ø‰Dp$Ãb!2l'6ÿ±Àˆ…$DŽaÙˆ¥H–lIÔFŠIQ·!gáì3=½OoÕµWÝ휓÷Vu9tœ_ùá Ýuk¹ç{¿÷{¿åÜ+Œ1üc~ؽ~ôß•÷¼ó®/îž,¿C ”BK i„‘¶D Œ´¤` …@Â, ƒèa© Æ€ÑñSk1€ø#Ľ£èä?Þ?uïÿä¸Òè-çÐÆ “cJǵ2h­QJ¡UüA¥´YX\vñâ…ÏN¿úùÖ-¤‹…?8q|÷?-¥Q/LXGJ– ¶”!¤1Ø„%°0ØRb °¤@ ú`#0 iZ¤!þ}ÚÄ0Q—¨´FC¤4JéØPµùZiƒ6†0ŠA0Ú)…Ö´A!0J“²,„„ô@êSËÓ×ÏŸ»Ç–{„-¸YíF)ãÆKaK0±Á˜䙀‘ uìÂHitdˆ"…Q TÏ› 2&f‘6! h@Äà)¥°düžÖ1`JiDœ“°%PÄ ÒÐ&f' -I&e)Åù‹ ¬-UQQpì-!"R‘ƃm ’®„Ò`,‰­!-)KàŽQ#® h£cC5è(^¸R •Á$ž4J'K#6NÆl1I SZ©^4id$½0ÀÄÆö€Ô€0 ’· 18é´‹mÁõ¹5n\Z@wd&½)Q¨ñüPÚÚp2ë Ò0$%;SÎû!ž¤,‰-PÊ€Š£LBÙH£z ©MvÓ[yò]-’ã¦gel€é£3Q'¯“˜Ú$oô„H¼.!NQ«w¸|e ½ˆŒÖf¸Ý€åX؇”IChH¡ùÍCÃÌ_[d£ÝE¦\î:>ÅêåU^®t` ÑÑ-e0F`,‰1± Lìc@IŒŽ™&¶0G$¢hLÓ}ëD&ß>Æh„4RH)é”EjÎ]˜§¾\ÇhƒHÙ EÌÛg¯ëS­µñ›]ÚÇFò̆ØQ øÈBž¡ôÚµÐ"¦œRÅ1¯UìíØDÕû&1º5í ‘%ê&öõ’Dë}1MÞìEAO@àXKJ–ë,Ï­cüa[!0*ƒ!Fë·`´Á÷"ºAÈF³ËŽ¡n9Ç#˜˜(ñÒËW ÔŒ²Ô/­cå\¬[R›@ ‰–£’Å÷R’Žc[ bÏšXà¤!%Úè[ÀR µ‰o%©b 8F´È$ëX®E³é±0_Aµƒø7R6}•$ =ó÷0aqj9:5‚Ȳ§0ˆ~ðN p—ëà?w…FáXVâí$S˜d­ZÇbgz+fõ„æBD’i¤‰é©šI}Ëú6_ÆßµlAi–f+tjí8#¤¬8uìq£âBôETl‰…Md·Â±È¦óUÈê÷_à[§.296•éyìÝ,uÚ • m„@ƒ #T 0‘êÓ^H BÆ'7›¢f´‡ JǯEÂ[ ¥è§Ã˜%bS µAJ‰´$Zh*µ.µ•&&Ò`[=qè§T„Fѯ6q$ÉÉHH9¼¾Rã•×Þàû?y‰½;·suúçüˆ‘=Û°‹Ûñêü À¨¸:R‚ëÄ^%Öm BÇt5½Å ¬žêÇ2Bû!ºat¼h0KÆ^•±Ú[Ž…eKº^DµÚÆ„ !%•›ìÒI>„[ªL!d|NÍV*ÝQ¨Q¡"Š:,¥3¨ÞÁ=<ŒÑ†{"Í|­ÍJÂr¤ÀÊ¥cÊI‡—2‰ *Lÿ’p0}£Ñ`dœ„ˆ´LÛ¥A)”¡ý&± –„­FµMØöú¬í³#¡yÏh“DFkŒVIy®º}Ć *”áw Ö! Ç”8) ™vù¤%ã4¼…RÂXÄe²V™xׄFhO¡U„Ö q$’Hê##K ²nLy¥!2´Û^Ç$V.ŸSŒŠÓ*ŒS°V£úNî‹_b´ o@G¯íuü8f„@§]H9hÇB¦mÇÂѨ¤˜›ž0›TëQQG±ØaÉøTB ”VˆòøIéՀƀR±&˜X,GâGŠn;À aÅáCRwôY¥5BÙ1Ó”F‡Æ(t`t´¥ÀÒio)ƶ¦A J´-Q¶À¸.a»‹®Õ›¦¹R£í…¸#e¤%±,´,¤%ÚĆ÷ÀÐIa.“t(Á–±ˆ”‹ŒP~€ñZŪ-m‰t$Z:íÇU«p­ÍN3JÄÓl7BÈX[H™ÂD !$: 1‘Šè¾¥Ù,…R6Z+"¥‰Œá÷ŽŒP;{Ža'ËÔÝã,^ºÁ—;-VIé¸Í"ÉÙ½Øë•µ*N‡ô*@’Ï0$Ú` $Ʋ0aBÝzˆ Bé:$mb¿(BÆYÃ(WzÓ«=Ó$츰$FIL›+,ë6`É~Ý  øˆ‡Þ{‚ÁÜÃÿúæ |ì£sâCïäóÿáë˜A‰Šû¥¤dÏ„(A”,.ic…£T"J½r6©’^>T #âEšP¡}/>‘›¢®uû&.>6Å5É&aÉ ¡w\€BÚo@ÚØ¤4B ¢Ziૈµj#n\Z0î³ãÎ/1¤Z3$¹½'PÉ"¢$åõh«@…alDNä‡1c’ßê±À„1˜“M FÄÆ*%CuË{ñyãø®tÝÛˆ 6„˜Xü¤À‚0 ÉdR`dì•m¶A‘I¯/’!†"~­Lœ’ªP‡*)ˆt’šâfA+ a¯jÜlç„1qa%%ù뫸ðÑñ±8¿oªzOá{ ÒBXŠEؘèöY jzÆ[nu„‘xíˆ P䯳H;Žpa9øØí%B”IH&HÚÄ‘ J*¦z{ß$tÕ„j“Éo iÅÃq™¸êy™£Ú cí0=Ã7ó{\›´bVú¦ÿÛFGoAÝõ 7:˜(#6|"?Ä-åHÅCHY¨ÀC6;K£ tB7sk5¦“‚§—Úèu‰º¿XáÈxœ¤ D"ð‰¤JaÜê K&Zc¶@h 9àbLŸ'Rè(ˆë?ã©¥Æ Òlacp›4Eh/À¨(î݃€íå4Òuùð½âŒã: ÝZœ-ÃÍ7?z1¬z èþÉ{í£1 •I²… ,„½¥ûÓÉ{ÆÄLI˜ôæ>[š.ct:[—…I%ªâ–XE±¸*Õg€ÜR ôfù˜rà¿>yž(ŒØy|/B@e©Âz«‹‰BLbÂ*L”ü URù©ø=•¼§T²P½ÉФ<Ží͸6‡BJ„-Ž*êsЃ° FËÞÄŒk…¤G0ñŒþm禇(ɤ·4š¥<šÅ"sÙ T£½ÅÆÅ¼¥g½Ù@niNzïoæç>uñb#•`Ÿ’I•'úÍÁôæo·Ò K&£'—^RÆ,³¬$œ@yôÇ-¦?“2­€ÀWt:­–P†L1Kfllѯûãqžî‡s2 ãV± %lÒ.™ˆ¤ 2:¦ºØBMᢴAñh\`°z êD_LÔ¿~h’æHë¸fÈÛuƒI¹Wi‘Òj´º2Ÿfòîüú£ÇAJ¾ðùgH³Ä310"îî”!5ï;’áàPÄÏ~ò}^»pƒÔ® §âtdèï ™~Ë&Þ”“ÏFÌÿ·q™|7£»pæZÄå/°7i°ÑºÏœ¸(2·†h¯|¼m$h¡ þF›ç¾ñ;ì™(Þ"öÚÀûãï‘*¤¶ O†Ò–ŧïsÙX½Æ3?8Ã+¯Ÿ¢ÝªáÌ^`ää'±FîèSÚh“Äø›:É­ƒwù+Tg^G`ñÒO=Nø5îݵ“±|‘Ÿœï}÷ÖüJÒ¥ «6·àÌ›DPnAΘ(VgiŒïõwLoB \X«¡#/®óu×ÿZS’]î[`ye†ùÕ*‡î>ɇýåò6d*ä˜ÁÍþhË,ý­Jœ$7Þ ìvÐÂåþw?ÄCïûBØÌÏ/R²æÙUÚØ¬¿ ’}}KÛÛ×>ÐoMƒqü„F…iVÖ»}Â4¼H6j>¶´’Ô¢Q †å*wä®2]ª•:?{ú‡üåÿø3š^—÷½ÿ#”ŠeŒê`u×6ÇTÆlÉé[À~¾/ˆ*­f‡Þõ.F'·óÃï—§žü>õF­-ÆÜYöäf’%³Ùô¼ö¦‡ØÂ¶ÛçÖž‡D±^kõ§4J*QÈÒJ„ê¼³t˜´gÑ(rƒ´ÛÒ…"ÅB†Åkiy ö:Èj¥VQ’b+]Ó`¯{‘ƒé‹dEe“ пۢX¥Tcnv…ä²êµ Rn†üÐE§AÑYëïn½)Ö7;Å7IÅíö :¦ V>Ãûîݽ¹s„ÌT#®/­qòhñrD·µDµºŠÄÊÓQŠŸ½ð•uvïÚÏèä~³Eú”Ê%6nÙ™Ñ8•—eƒ ]Ÿ¡3ø„t’¾¢ƒmi²©,µz…Á<År™Ó7X[_err;Ã#ãƒyÆÃvë –ÇiY®.ø¬U¢­Òðf.ð6i0ÎcQ«En²HfKÛXÊÛ,ž½Nvõ÷²X«TY©-SÈf™˜`jb‚ã'Orüè^¾ö×ßdéæ y7‡gºx•*б¯RW%{¡<²n€i„¤m0¡¶…ÐòQ¦H‹ÂÄ©µû÷íæ£ý Çî:ÁÕ«—2ÂCšõi»ÈäxŽ;ö¸4—å…SkD‘Àô‡¥"Þ™!1*Dúí[°9óÆÖ¯¾Fa ÍFØ% #¤åÊXœãÕŸþ”o~ý[ì=°—ßûÚMŸ™›7–›X¦ëu v\'Tó¤S™Â8å‘a¢PPØ` {…Z¦àvX÷«lÔjÆ€oxè}38\böò5žyö9Œ6”KEr¥<™Lšn·‹íØäòyÞ}"E)'ùöÓó„Jmö[Zá[I×%%Î`‰F³É™K \[nðäOñÐa—l.GH$*Š3Àù×_§ÛmS¥b­Ycþß#Ï3>6†@F!C§Öbyf†“ï¸åJ¤C1S¢.›tu,ËáøÎa®\žãæÒ™‰@’Íf¸zé ëõùlšüP‘V£Áââ",FFF°l¿ë! %ÜTšûîÙG˃üx:iÈT’ 6wFl“Ìê„eÅ£' V6‹ð,>þ©/` ‹õÇHgÒ­ =?öfpcnŽf¥Á¶=ÛÆ&ˆÊ¥tÚ&Tëk«`ƒ”‚0–äÆÂÒ²˜Ú>Ee£É¾»´;2®_¿Æ¹W^c ˜Ã±m´°HeóÔÚ5\—ñ±!„2DQ„ÐZ¢ÀciqÝ™½t»J…£ql‹>t˜3*Ü\­ƒ1[ óD8{{ðÒJÐŽ‡2“Æ)qøÄ{wɤ3 Rh#pÓxÁ÷}ö»“N¥J °\jÔ>V×N#í:h‚ÑäÒ)¦¯]âÂÅ Ž*M«ã1µs­v…3§~Ž•Ë -‡(2Xn )À±mªõ­ ZÍ*…å( yR)—fµí¦£Ø­Ò²Èd\Þyr'Òq±Ò¤›B:)¶0 )ÃmÛÇÞÌ—IròP\¿v W®±8}õZ…ÊjÁrÁÒ º’#PMê UDÊÆuSضG—ÑÒ(ΨCµRa£ZÁovP‘Å…óçY^Xà·~ûw)æÓ<ý£9wæuF†F‘‘" ™4¥ÂéF­ J)¢ÀGõš)%1REŠ™Ùjõ¹|‘mÛ¶±ïÀ~:Ä»Nîä{Ï^"Š6÷nÛÓÛ«—qXR>¦r<÷ãgè´: rï8B¥R᜹ș×^áµ—_brb'GÞy «êÑòšh¥p¥5ëõ5&ƶ!If®`osX\^frÿÿÕ_!ò nºÀ/â“t6*¬l¬04:Éhqˆâp™BqZ­š\’*аˆ‡£ëë«´Z- …Û¶m£X.‘Éä ü.§_;Åôµk<ôðØt9}n5Ñ:Þ& ¾éqçN‡³g^#ŸÏq×wb9© Rº¼ÿ£¤³Þ≿û¾ñï2ÿÍœ…ÈX¼ÿ‘0>¹—¥é7(G¨®¯ã‡†ñ‘aþåïÿ!zƒtÆáÔ+/’NP­l •OjÏ' }‚(¤ëù¬,.026ÁC¾‡=û÷P*“Íf±S.¶´ÐZóÒË/ó7_û*'î~€óW‰ôÛ\Пê$ƒmÅ¥ *J‘JgXY_½ }|_#µ!Š,|ð~FÆ·ó?ÿüK¼rå4cc½ëj7è¢I³ÑÆrVȦ‡øÚ—ÿŠ»ï~+«œü{÷ÝÿÎíÿ)+ùÆß>Mµ^§UmQ«4iuÔ–«§Ÿœã‰'¿‹e;Üûžc„mE&›§Öh31:Â͵U”†ìP× Wc_q˜Úú2ÛryB‘.EKWÎ-ˆŒkKº–›×QDÔò)ŽO12±êÒù¡!¼Z ¿Õblt/ ±Ü4Åò HÁüE–VhzM"l^ÝŠ@") LíGt$=ú›‡¾÷ÛŽ›6öùÓ?–%ÅwŸxÑyïCcÕÕåÙw>÷ÔSDF³²°Fµ¹w B2`R2eòÑ iÒ„t¨E ªÏ„”ŽçI5Á –w²VÛ "b÷ä6²N {ÀÆiš5ÍHªH>í7­)ÛØ-S:Ty9`œ€{?@~´Àé•Ò"ƒˆ‡¤Ãå2ÍN‹R1Zr勬ÖêX@‘%9L1]fÀqQÆ¢Öñ¼òz†`¢ËóÏ>C£^ÿà§~ýÃÞ{ò½ß³{ì~ àû¡~êé¯úÇ?úѰ´,–gW¨6ë8VšQkŒî^Š#äì¶¥i¶šèP3ê{¡!}&…{0M#Û¢0Z`wŽe(ç x^DØÑ¤Ò RÇqÎcR–Uu)L¤‡W’s Hln®ÎssÃ`¥S;y˜Ó§Ï3:>ÅÄø(z)Â÷ çÞx­4ìýìÍ$“) eðE¯Ýa4=Daj˜… ³8XšåÔ©Wp\÷3øoÿ‰¾|æ7?“¾tñü§¥Ô«uêÍ*ÛsS¼sôtËÔk>6‚A×¢‹My GWth+6Úß0¼8‰·½ÉÍåYÆ·M±QÝÀrÊ¥aº^›´tqì…b†Tn®¼n9ÎﺩŒ¿´<ûÙj«ö™½å2%Œ1 ¤]JåFËühñ)öïÜNµYÃS!W®]&«ywö††G ÂaCZæ1¼¶E±0ÊÎC;˜¿4ÇðÈ(#SÌ^Ÿ#³'Ë™S¯~ðŸÿÚ§îî0??ûH£VÝ—ÍåY[[e‡u€_:ü1:õ[vìÉáÕ<¬Tšj¥Ž Ú)‰¤aldí*š uò«l”VPÝÛr9ýÊklß·‡”›¦¦k f( æ¸pþ×f¯?gKû’"èúÝ—o\»þ©»÷f‡GЬWWQ:‹¬u9ýü‹DÊÃJ±6s“JµÊH0Á‡¶˜ Ý ¾V% “ 5C“FvŒ²{ïn.Ÿ=‹2†žäòÏ/0av°à]Ç–XÓÓ×?ÑàÚÕ+G‹ƒEš;õÆ¢]Ø‘aû® ®^›Az™Ò N1îLšTÎÅ Bª+ëxžG·ÖÁ¸†mÙInêiÖ;5FËãHK²²´D>—gl|œÒØssó<ÿô“WÏ[ÅIF%Ä+¯¾xfdbüÞÇÚ6s sTjU:^—òèíznäQ¨phàA2\#›·œ"WÁq ÃåM§ÖÜ ›)pòãqýòUvÛA¦–aúú92E–—–ög‚ïïPZÓnt¸cß1Ž:ÆsgN×îpÿ‡O‚€f­†¿^G¦AØ:•:ÍZÕÈËì8°‹Òh‘áÔ0^§ƒãØ8®K:•ÁÁF­j^xîùÖ7¿úÕó7—Wf²†A†adŒZëvšëO|ã¯=ùƒVoVÖMv`€¡¡££E²v–¶ßÁ ³”Ã!²™ –å ¢.][ EÔ ¨W#j 7n2’á—>ó«8%XYžå7þð×°±°— ð BÛÖû²¾×ÅÑ¡²)íàâ»ùÙ“ÏppÏ >öÛ2{~™¹éÒ~¼?3up?{îd²Ì\æÞ‡î¤¶ÚáÌ“/ãAtö̹Ka†FV"ˆ”x~ËHÓrm÷lE/ !ÂÞÐÉëùv§sßóÏÿ¸™N§s©Ô@ƶ„PFi,‘ÎÛǶ¹û'#$‹R¥<ÆÊàêxGÉ ‡Žp߉ÃÜùÐ$ÿû Ë¥gÎà–øòþ NÁAÏóBˆ>~T3*q¬*­¹uYå¾Gbæg3üé¿þå‘]üûÿþ[tuÄ©Ÿ¼L¡8ÌìÅY6n¬QY_âæÜ6:+ 䀅îjoymåUkˆx -¥l !Ö…3J©ó–eÍoÙû[ÐZÿ•æ”Dîó:^©Óé…‰ïÏÀ˜ô0Å‘Ôdj<:؇® ‘^—±m¶íÁˆ!öåäÃwðÙÇ~‡?ùƒ ¥c»ÇYŸYÄÍ[Ü”ó'Ķ,|mj›—Ë{~Ëv ª¢ÊBcAQâŸfÿ‡yäÞ‡¹zú:_ÿ³ïpêÅ×h´×ËSšÃr$nÀÂõ%–׿Hms«bÅhýCiY?éïGÓº$·ôeõzÝ+étzÕósŽ0äXT¤ÔÞHqÒ):ãZ|¥@hEøí€jÓ?•Fǻػ3”ÝÎýŸ~7^¿ÄÕ˳8žÅÕÚ5ÖËóXR’-ä¨5+vâ‚2Je£7B1#®^ä]‡ÞKÚÎ2ûÊ \Ûåà‰}àº4Woráâ ¼k3र"ÁµÅËlìZ¦XÈÓh·fcÌ¢âí¦ÒýÇàà *¾OÆ^òl&±ºÎ’% ÕÂþÕK:¡”À&d×ÔvJSãì9²ƒÕÅ%f.,àXìßÍ©³§¨Ìã¦Ò%ÉesT«ÕHö(¨V땵٩SÔºk °1v“fŸ¥˜KñKýuÞÿ+¥Ó€L¤i¶lxt›>ÁFD§é3í^bhÿ Õf³Û¨7V“kEø‡Ü›X¯×iµZxž‡ïûA܆aHE „ét»ëÕZc#·-ÃJav§I·áÓi·©zŠHW¢;’CÇïåþû _.qqýK·YoWØ»o7WWæ‚0 {!à³K7—fvíÜ9tøøåKo\æÈáãH_¿ø~tî‡|ì‘OàèA,•g°‘á Mº´tC*¥e¶íclÇ„úá_>u˜B¬`6‡oaÂmEÑæý‚ÆôX€uÓ.¿²oÿ¾{ŠûòΪs“B³„_óq´MØÈÀ¦Ýñ`m‘ŸŸ~ž•î ¹#öË\½zŽ#wÆóýúå«W¦9ÑóŽ”ò¸1æÓRˆw=ú‹îŸØ6Qºpú;Fv±ÿÐaš^¬æÆ•9ªë,‘A(Ÿ ­X¯,sðà>Ýuþ_zcfvîE!Ä×€ç€þI–e%÷ ,˺åu½^ÿ{"¥”À cÌãåá¡G?ùÏ>ypyvYÎÏ-QÎa‡6.VÚf`h€©ÝSttÊe~~–ùåì9¸—F£Ùúö·¾sÊý³Bˆ¯lÀŽcÞ#„xäÁ<üž_xh÷úFEÜ\X$ëæ¸ëÎT–×h4Ôªk«ä† Üsß º~ÛûâŸ}ég7o.þTñ4ðR¬­F “›/ß @<ÄØd@ï®ÏÛÜár‡1æ‘ÁÁÁ<þøãw—r¥üôåi‚–G¾X¢X,’ʦØ6>ÎôÜ4«+ •‡( ™—^|yú¹gŸ}Uiõ†âÀÙ>Æ,Ë@ѳøýlv ûO~ùcCÇŽ96˜/åÆFF˜_Àïzd²r¹¼©¶j•'¿ÿƒgŸyú™¥Õ…—€›€ºß€ÿ¶ü†FŒ1»„¿155uôãŸx|jhhh2ò=;ðC,K²k×njÍ:ëë•ú•«—/=õäSÓõz½ü¥â°ª”ÖâíJJ™2Æ<<úØGÛ}üŽãS‘³ÛÐJ¯~mé»O|÷ª1æ<ðWBoË-ü¿ðdÀ›½5>ö‘|dïñãÇ'„i!„¥µŠ„­3gÎ,?ñÄóÀw…?|¥6w†Þ€InyÓZ%÷jR™t (ƒ[…Xo4Û5ÛXRbY6–mý¹ \ñvk¬hmªoû½ì·ÏÿŸ" )¥›|D6IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/ksirtet.png000077500000000000000000000543461217176075400234210ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœìw”dWuîûœªªsšé š MÒh$²„F $I€éåà[À«ÖŸB¿±´Žîãq­¸sjš-ÀA`]­Æà}¸×+>ƒãºa{G»ªœ3Ñäa !p''±³ÿH®ƒ#ðå6ˆ×À}¡ëfÈþ€ôÄdöN¤çøG¡ço`ìïPk·ãº¾Œ:öJÜÌŸB|L®Bmønf j|×ý0þVàVÔfƒÛ½tõÝÀ.døy¨kq{wãǾjtmï`ntoƒ¥Sðˆ‚Ú28iì8z>«À+xôœ|!ÜU‡Y8õ\8ðìúD] ¾÷@¯ò¢äS´<8¾|½ú>¿õìzF—ê—üŒÖ³ø‰/.ÜÏúB¾çz?ÑåÁ{p® ?‘àY<ÓËÎ0xgñÞá p6€âç Ïà™\m/wÈé>ë5Pd8[œˆÉIN=ƒu?7áY<ƒË{ÖCa:û ŠVFW–Vÿ£rÂIÿj³&]gœ y@ÐN?Ãõ,ž‘BºwŒeäŒ~òf«7›\²óì3×½øªËñfàz[,Ÿ1­Öŵ³—Q=Í.¤‹Ÿ!žÀ»:¶sPjg/"kf[fçN:vÉ+Ö½öꮼh˜_yÝ2z‡ª=Y¾ú«y3û€måôl;r[r~&´àYüË{BÈÇ‘,=%KW’5Z¯™)NÚñŠëV&/Þ0Ó³†Ç2V-ïâܰ‚­göb²‘·åjó!ÛÊNîÙÖ yI -?unð,~Ôå=Þ:(,ê̇^*[ò'$+ÿù¿¿n%líáèTA=³Æg ¼W¼æ…£\Í"tšŽ6Šõ÷­üw+Cô=7@°í÷ÿé|Œgð#¬Žç[Ë’³^IN8X_úùáÑÞñî7.gíª*c“™u^p¡ž&æ,gœÜÃÛ_½Œ•+ZÅ¢ß+ºÏ}È4ͪþ«€lA4ø)€àYü+=ÏÈEsäÍæ¢é©¯ßx ßñºeôôEŒMNp^PH) x,BnǦ =µˆ®YÂeÏéÇ’n¨Ë¦=E«ø•êhJÿÕû!³¡Rð?Ùœðs €Ÿ©¤\^À {º6u“5ósÇgO:rѶ¥+ñe‹1¦æ °øðrO(úTDZg›†FËsÙ™}Üpõ"††4õ|ô/¨­ýºmf}ý×\yÆ”@øÉÜŸ[xÀxÿ³_Xß Éª¯0º|%Y#ãL±ú¶—^½œk/ Þ(˜kZ¬ó¡²#€ÅˆQx<à<8„–…‰YËÒá ¿pÕ"¶nªÒ4]Ûš²eÊdÍëõÒ5tmØE[7(ð Þ”Ÿ[ÀÏA(•=o=䎑‹§<Ñq¸µü/¥vÂßÿò+–rÁéÝLÌE ð^‡”/Áàí¯"áç"Xç=…õL7-Å‹Ïïç%÷’T`Î.ù×Úàºÿ0Y#xù5ÌsƒgîÎDÏØ;ý„Ö3 ø§÷·ñÁó ÃÒK_G£9˱éS¿:²dðâ®ZÄ`¿b|Ê,ðzÁËü5ÏW | ˆ²] 8< qÐÊ-+l\YcñPÊÍÛgxìh×5µê™uÛÜ}UtBö¥ÊiýÌÝ8û#‚ Ä$ïK –WøsBE]êjÞâ䆟)>þzœc>}š¢ÕZ25½îІ £¿íå‹éí&f Æõ‚ žo„ùH€x ¯0R JDãE°â) MGµªyÙ…ƒ\¼¥J¡HŠê¦/öö¯ý¨mæô?)›À ø§xX¤ …wäÞ“{ÿó€¶ñ-`Ã9±vCn /ß°‰‚6ð‚0˜¿Waå–®å¯"oµ.;ÖZsð9ç¾ñÅ# ÂTÓ•×Bº X<^‚û;# ¸c ¯0   DãÊÔa¹ÌS/çnêæµ—Ð×í(ªËÞP>kÒ[·Qõî €²Jðö< ø|Îg³ëx~Ìeý]\Ú×Ã¥}=?ðÞc ¸nÙR²ÂÐʲ?èzèäÑyÆi'o"¬u?1²ç wDÛngtí²fö¶Yÿåk¯XÌ‹/`®Y0Ó´¡ÅïåI~¦1Nùù(P׊ñ@ù",‚—ïÃWëãQ8Œxtâ(Ƴ~;[}]âç`qî˜k€«—_¿ß£n\˜ØQÄž<ö?{àÃ9pñÐõþAܾƒÿ¶bݺëV]r |ê__OOÝ7#ç¼tóÆÆ}=‚•ò²ŸI´ûøÖ0tÑ›‰™àèÔÆ¿Žk‹éµ—°qe…ÉYKnJ^"!†¨Âq'*£ç9@ÉüQVTpØöÏ67Ð!/+E¢…4îy¼Å7v7Hb…šÂNTl*ÊZuµ´}ON¬˜~à ßG̈0 ˜þLà} O…1\±u+Íz=‰÷íÿöªS·œvá›ßŒîëcñÊeÜþÁmVûŸ8Ú=ïÌõkï«ï|hó‚Þû`ü²äÊ”¹f3o­¿uxtä¬×]1Èp¿âØŒÁ¹PÏ‹x,ªÃW¶¡C@‹B°8Ñ _–‚D¾|-àT'zàE‘ÆB¤„oîjð©V° ;ÛBuuãôê¦ DiO=ÏÇC*PO€°¤$¨²Tý™ ½sXëØ¼qÍVkU|àÀwÖ_|qß¹ox=yž3µï ú/âòßùmnû›w¸ûÎ{[‹F_Z_~§/x3ë~<”wß—ž?¼<£hæ'Κ Û×­ëí{Å%ýÄZ˜œ±¡ç#R²hÂc˜w¾ŽÓîçx »Q)Ò†Zœð^ÕD0N¸ùþN[jâ±û'ð¹Aº*¨JŒ£ft¹L5Èîã)y; ’ö(ˆ·ð³@›ìAðüEë×1Ójm«=üõS_ú¶\s ÙÜy½ŽÍ2šãcÔz{¹ðm¿ÊŽO|Œ=7ßtc<0øÛV/þÉc3ØCõà‰O»**ë¡\néÛx5y}üù3vÃMçŸÑÇ Îî%7–é–Ãáq¥µ¼,Œ:ÁëC©ê…WP àðd™Å{âDƒò¸vÊ ¼Ÿ–ˆj¬˜Î,_~pŽ£ME-+°‡¦ÂðvWŠÖ’ÈYù8S°íûOƒ×J@†±¡ö7¸¢?åå UÌsWôÑÕ=H«Þ|Mïôì?Ÿ{Û8ñâ‹iLNb³ o p¬"›!Ê3NÕkX¶„þåß›dËÑ¡¥×/Ô<èˆÆkEîõÜ¡cMœF¡,‚DšJ¡#!7PîÜÛbÒ)6ŽÆä{'p³MT-A¥k$ÑH!±B*):Mc"íI5Ôjå£ë>¤VƒZjŠ÷¬xˆŠž¯å§<8ï(<\{êæZ-5xäð+Ö¬9ãŒ7ý"Io7ñ£à\»`B­/Ö‚Õˆ8° ¯®0´Ž¥Ú7ÀÙoûMüØG»¢»ïØ9=<ü¢ÞåK>dâXG5œɤwB'o蔄¼9³yžrûI«ºº®ÛÖC)¦çË­À[Wó¡½ý~^(¼n3ø@ê²Ü`¬§šjT>‰-#Ÿˆ,¿¢IQL×-ßz¢Á)«ºèò–›¾|zËQé®”!_qT!üKRÅ›®5ö§ IâaO ¡?äÆÜOí›åœÃ:Ï¥×ÑȲ%}ß³ò¬3oýo¯ yrr qAÑ™ÿ,ž\"ñ p( ‡÷šlz’¸ZcË›ÞBÏ¢Eìýâç?×ìé{—_=úÇ~üö -Ë4ƃô%wR­AÞÌ_2k×ÝxîæžV7™ñÌ4 Þ  bñ^Ò¨Pº ú^•iŠÙkåo¡R‰Q8<>pÃ2ji¤™lyžô\~Z/3‡ëüûÍGpZ¨ö&h¥! V•…ÆÏgÉ÷Ý}#E¾S§šN<Ó‚O~ \âA2Þ3ø_¼kêJŒÿ `¡šjåñ +ÈZÙÙýÇŽ|{ýå—³þê—`› òf“"\§Qêa×î– ÞWe㤈/@4¦1¦`ÍÕ×ѵh1ýÛÿyb²S ¾úôÅ×vÁ` ³¨‹gªÂ¬Ùô[ÍhÙû^p~•s×Õ˜Ëyî°¾Mì|0¼¯<^‡ ó% <ŠR„E”ÂzGÖrˆx*U "Þ#¢çãB©žD¾)ËþYÇuçtóàS|êÿ#JÕj„ÒITx±¨ Ò.\cœü‰»¿æ½y@’ʤD霎f­éYqôCê„»'1H?•ÉÀžqøàsàêŠþÚ dÍÖ+æ¦?~Ê+®gå…“ÍÎ`²&8ßa¢^y´ áU{°Þ¢¬Ák…xÓ¡båÇoPx\Ëв9£gŸGmh˜ÝÿôÁWŇ­›8÷‚Ó–Ù9·ž}ýR«æL'6©Ž¼øÕt±~YÂTÃblÐàð"%ƒ²·ë´  À8Gž9TIáQ8ï‘6y,­#EÁîqÃT&\{z_½å·ì˜¢ EER…×!ìG"$5ÜÌ!ŸïÝq‹¿]GµG¼Vû½b&‹sZ¿6}ŠÝÁO^ T…÷ _Ï;Ç?ùÌ Íô Ë{X9<ˆ:2÷Î!Ÿÿñ–׿‘E[N§91Ž/Š zPm&]ã·ßCJ¨¼ íª{ÛþnfÉ&ŽÒ»b%›åÝ<þñœÙ»÷ññÇ•>³ZÓ»—vG½O¸-w ¥ë^qAáވɹÐe¤là´½:žv®BM ¢ÊÖ­Å.7!rÄ‘&IÚc_. ´W,¢4q¤¸ÿhNÃiÎ]®ø·/`×ÁŒ¾¡*Q¤PZiÆÈ¨8FÒ fjnößw J¶«8Ý¡E´žõd¢Áž¤@ D? +µE¡PÄ>3ð°Û’éW±ghC‡ÿn¸«ú¦S^û ôž°’æÄ1¼ bº@ÐΠW¡¾÷„Þ½µ–4ÕÄZ‡©€ÈÎy¡5l?l˜³ŠµUÃg¾4ÎtÃ18"‘F´àµ "Eªž¥c{šæÐC_“(ÚÄ;B»u­gì}« úêÁóE/¸?ÌšgÂ3€P·¥t®:åDòBÑwà‰oŽ.]öœSþÛHûûÈ&Æ:CŽm²çË›ti{gÃ÷œB¤cæ²võ€x”37 ­vÞNôøn>2ðœä3KßóO§l¬ñâS<¹sÌfal«-Ãz)¼2a;å±Z£ËŒcÅ£QŽç¡'P©&ˆxŠRÓm“<x¯PÚQà¹åñ‚c XF“[wÌa•¦«7A"…Ä„*ÒxQ¨8!J*˜ƒMçGv}S'éwÐzÈÃÖë©ÌØí-CäÃM;.ê? °`ýØ$Ça=¼`ãf³Ö¢áñcw/ß´yùºë^‰Šbò‰Ipß1¼CÐ.äýÎeÍV$Tâ\Ù1£5 BJQè$¡ÚSÃÜz#;?ùuÞ·ø|ëŒ?áÂÓ…‹W4Z–– 3u¡13ox¡¬ÕKÒ&>ää ’hœ ‘ªÕ2(ÒJ Êc}ÐUPxlhð(Á+ Þ‘¦ Û„ýÇ,J)Òª‚X…¯$?W$fî‰{åÇžø¦J*÷ŠV;œó;¶úÌœ}°fÑÓϨzóãÀ9œ…C›VÒʲ-‹ÆŽÞµòÜ â“^t-6oQÌL†pî}'øh^LGœ×Ú‰ÎX”#SPrösñˆ„#m¢JJ5†ü??È7ïáÝëßÏÞSÞÊÕg¶,Ιi ãñNðÑñlÞ–ù?Ày–áu(E …óä-Ké çSÖ÷bR0>A *?ƒõ‚ÒŠsV¤ öx¬ "3M˜®#ZPZ@—2oZAÌ=þƒÅÄþ[tRÙá#µÃKü’nöèº}d…Cí{Úÿ·~DÌw½¬±œ°jyÖ¸zdvò3k®x'l»„¢9‡k¶ðâBù‰C¼)Ë9_r€’øEenW"à=Y–“×›T¨TÒðûöø+ˆDWkÔŠYf?þ'|î>Ï»ÎøÜÉWðÚ­u–÷X&ë&Š¢Ê’.ÀÍJÉæ%„ýÀöÕ¼Ä+È OaI¬‰’0Ùë¼UÒ×Òè^dÁ¡3ÚtÂÚ!¡ZqìH»1µ„hºV!ÕD¨?zçãfêè·T¥r¯H´ewyíŽÕ›ssvç_{¢?[˜¾¿‡9~X-àø×>}øy"–,– .%™™þþVëO×\ûrFOÝJ>=…±9â|rЄ[Ò—D…Ý´bƒØ%mÂåEžã¬%­$8SP4 I%Ü(. „Óî.Òñ=þ§òÆ—ñW~îëxÝ©stG–é†Ã¹°3G$Œ[I™¯EÀ¶ ïóÃåuˆ ëHSŽtP t)ðtz*ˆGelöí²²ŒmsƳ¸KsvìÙ1žÒLbt£‰Ò1ˆav×ÝÛ¹©ÛuÚu¯Wê>O±›¸8VŸ^Õ°Ÿþšçò¸$|² _ y3¯Ÿ²à÷DR(÷4зÀ¡áÕáAFÇfþf0qÝË^GߪiMŽã¬AyÊ'ƒ0_ò €m§D ÞzŠV†jµ*^ X‡m6ÈæêTj)¢‚@RííBïº]ÿrÿ;¹„ÿ¼øŸ9qS7/Ù4‡³–™¦íŒ^Ùvi·øy…÷ •>Á‹BT ´­VЫ•«½x:õˆ“ —Ü$ð‰2üËÂê" … аГ*ÎX¬¸wÌ1]뇙Yê÷Ýr§mÕïÔµîE©û½Ø=񣂾é–ùôrOäC¸tc[ >AK OÂ÷ÛÜ †þ;*ªD¿JIò§€²Ô+,\Úf›–þ#Gnº|ÝË^Iepˆlj ïâýqÆÖ~þ¹H›èµò¸/ Y+GÇš´’âKéW DÕ”¬Õ"o6¨övÓÓ]Á}ëß¹õ?ïã–ÿ÷o}çm†‹Vå4[†Ü„¡ ‡ïȤV@‹cYèrLÛƒ’’xD Ož;”†$ Êžóàœ„@iàÎ(Wièvö €FG_½†ƒ$Vœ6ªØ9%MúI×®ëií|àïŠ{L\=¢úÔÔÜT++>Ý09´r0ê ê] úƒá§{€.Øû¯À’ß‚æuAá;µoÁ½øeXò7мâŽe€†ß‰~Xx˜¶…çn\A#ËûFÆÞ=râª5k®~)qZ!›G9´2_6t”oA+ßÉý?Ÿó•à%Ë ¢8"©ÄxïÀ¹P÷‹ ÊS©VP"TM“¹Ïþ#_¼eœßßòaÆ6¿žmi°qÄ2Û((ÜÔF<Ϋ@Ö:a°ìáK¨K¼RëÈ ‡ÖB’DàËŽ (P¶óúNºyúº0…´S(–öüÈœ •°aÒºâàº-âá%¿Þ|dû‹s3u¤•ôSüûbàÜ17\oz)µÌSf¬ÿ—éýн˜_‚“ øGáÞ1 nìLP2M5<ÇÓa&Ô7C§h{æSÀÏ—yXËý–“çù¦Åcw-ÙrZuÕ•/ÂC>3íMÞ#˜vfÄÛò« y_‚d†(A\a(òœ8Mˆ£¬-#F ˆÊwªÔRºí,ÿãoù·4rîg1§\Á«O®³´Û0Û4X Nt0¼‚ÂzUz|Çxäu¼T¹µä…#‰4IYŸÏ¿—/ç’½6È‚‡ tÆÃÛ£a§f>æ82‘ƒUÝf–½ÑÈ–®¾ËîÇî¼ppÙŠG¼púôA²YrGSã[ _××ðup³` ðs@“ðËs¨<„IpS~¯|x[ÂÈ÷÷·}GÓ/ŒcÝúÅLfùKg§þkùy²ô‹p­¶Õ áSÚ†§e”}ÊØ„m6/0Æ’¤"­ð>/#D)û:A)Eµ»Fel»?ý)þ¾y6ÿpåGX´|ˆ—l<@¥«›é– <%[z\;ü»Pw–[èµ Q¬0ƒË[æÖžÁÁ k®½ÇdÓS(oq´*Ƕ ãá‚GÚõ½”G\PÜœ/°YŽb¢4 sé~Wp ¢$BµfyðK7ñÕƒ5>øœ¯­<ƒ×¯Ÿeq—c®ÙÓ.o²W¨´ Q„ËêhE¥§˜ç+2_çÖb :²®“'óƒàõ±Òx%<<±k*fYoÁ–G$P¸ö½*ed/øÐa[»ÉØý÷àòœ$ƒ ç-[¶km¨Þ"í<î]xn=‹ÉsŠz†Òš4V(gÀ” Ç ho1(¥ k0ýùqÛ‘”?xî]È)sÃéMFj†¹V˜fKÂ&‹rqŠtÕ›¡³é†µÆy :äì,SÚ¸IT†jÁ©ù}û¢…$Ò±}¬Ê#cªÙ1ö‰¹{2%÷š8V¸RPñJá¢r³‡Rø¸lÉñuÁóµ¢°Ž– }«éD Î3RÅqø™¬[ÿõ,ø½ÆÿL>Aa¢roâ3 €н:Î3T©«´Œãð7¿ÄãŸû­‰q’®*‘Ö!ü·ûõ…í p´¯°h,6ÏðE‹$‰"…·)ùƒˆA‹Á1e Eôžr:Wwâµ{ßGf-ÓÒ¶bI8wÇ—*¨‹$>¶h£"T­ í-º5…#L9YÖ{Òé© IDAT4B"UáRI4èH“FŠsëÑ„]ÛaEõ׸èŠEœPýK샻'#ê6"Ö¡—ï´`U0¶“ùƒ œ.‰a"”BGŠfŒï•ÚHI‚æ 4bÚ† ;þ£'ýòïŽlý‡;›Y—œ÷†  ÍŸIð àÀ”éÖV1 ë•%ºq]}d‡÷³÷³Ÿ`â;ßFÅq¥‚– vœE9 Îb² S$iB¤A9ƒXF¼Ä„²°ýÞá\K¼é\/½ˆ?ÿ+Þ}ó…üËM)†H+1…n£ „ö×v½®®."%¤Í)œ·4óðº´CÈ^hÙ ®¬ ”D$‘b_žð­‡î‚ ›^‹®ÿ.ÛÌY/xFñý°}R˜´š8ŽŽÛçïµt6޶9 ò ‹! Z…ÁâÑmi¿ýЂ‹J -§x"ƒi` ö&Öô¿•ÕQ/y3k›wŒµZ²ä"Îøq£Àqàk R§L¦º$u]1.¦¸F¤5q6ͱÛo¥¹ÿQŸ½êð¶YGLâ,å5¦•P©¦afÑšrGtØ@!ŽP>ºpŸ„R¦ö9vn5zù•½üú×?GòÅKxÇÜ×Ùvþ0§vMàrƒ÷å䮨ps¥,Ë´€³aRW%4 !ÖBœ«¦_9 Ï#Ú¾7zBÈšâ¬Ë.äÊç=È…Éèe •žF]ü¿©nßÅý}ŽÀº!IÂgq”~j:ú¿óàlØú®²ÂâUàDã½àu¸P/à@VÁâž³YÝs'¯\ò묪Ïgÿ5_ûò`²!?˜íäœU£rÇãOøNqÐN#Ogf-TÄ+ð±ÂêˆÉ©jP]}¸î!*Ý1ù¡#¼éSLß{*ŠPi¥l€­¡h6ÁCœ&³ZD"_ E%OP8”ÎyÎ#>Ç5æ0]ƒÌ\q¿rÂüÃ76óͯ<ÎW§FQ•­ã’´•å¥Òx­±¶ È2êTiè>âX'e®G!eÈ:b!ßk¾SO¹o§àw=ÌeׯæåÏ?ʶøC˜¼Æ‘l/'%/â¹]oæ´³?Ï9[7ãÇá¡1ØŸ…][JB¯À—@n¿ØòyQ‚Cüü,“P!(”Sö ±aå@?gÝÉ–ÿ#é)ŒçG¹|ä ¼réëÐ~ßÎrÿŠÑ~aÉ]á½;û!žŽ‹=@¢‘(H\8ë>k/êíÇ"9Œ69wÜE¶oÃgžO2¼ßh`[ D©kÛež„q­T· rh7ˆŽ¯p¥Ô2}Ó`Ò”Ù‹_Åëû>Κ»×smã+üÇó.åE#SÄ& »xÚoPä“Óˆz(t•$ ¥[{g/ežnWq¤˜qÍiöݽ3_â¹7\ÎåNcµy+Í¢EfgÏ´o²8:›Kd€Ú†?¢«§Æ÷ìg—¤‚å5P^J’–Ó‰%¶ãu¨¢EJá¬üäÇ28f VÙÏÊþ8sž7ø¿pÔ˜,añ4í›û¶1/æÆÃÁ‘ÑÖ'ªÚ¯Y¶Ký᪎û;àúáAp\hÑN" áˆÄÊCc š3$½}èÑ•H’T¡86Α›?ÇÌö[±&'éî&­$ažß™y#·½|·×£paÓ£óø¢IQXÆ·¾Š /âö]—ÑûÿÈÇô3—T‰ÒÀ¢\Þ"³–™xW©¦µçòU`èŽ"$âHq8Ø>¥yâ.XTü=×½ýr®ÝôBVoaÎL“ùz˜\ƒ•‚Y7Fo´Šméû9ey“‹.b$þ{ÆaO#ÜxU‚«Û­êlî DQ …›"es¨Gôw“ŸÀå‹—rÅð(¼bÎŽc}s†Â7˜Ì1’¬à '¼Mµi.â}•îãiÍy/O(Ìün¤§ *ø24CŒ#G¤±üÜ~ì iW7ɪHµJ”$OÝ÷S·} 7u •VÑ:ì¡d¯4®”våsž#ói@Špz²7E–1¹öJÖ>w wN¼žóoü}þeO/Gu7±/hùˆÙdâ”4Ðaª·ÍôÃa[”Ö<š¥ì˜Ô½Ö ¾“×üÆ \¹äõ e/`ÚŽQ¸&Ž/ƒó9Ö·˜³ÇÐRãœÊŸ°yxˆmgžÎªþϰ«—•T)k¶½ÑJ¸Ó‘.Ui¥­(¬p(‡IKú>Ìé‹/áùÃgsvïo2WÌPwÓ8g°8)pX,ÓöÞ{^:úv.îÛ†âµv£½¥•Y¶I„wóí§Zú½ï}oç_xÿï1Ø•$Mç{ú#¹l8ò›|Øà„× yט£:4B2² ל…<#íѨ¬EkßcÕI†¡+U” giR\ ?â˦P9OS>W>ô„r†PÏ¿F;‡³†l`%ý'TxíþsôÞ]|,¹št´®Z‚RB…›í0¶¥"¯!Ñ#Ї›1Áô·‡-g†Â·°>ç¤êV†¢³÷¯È{ý æ˜ÿ—õI¥>£ v?Œ;àLè¾Ìèn>í~w/€Œ ¥1ºüðºœ~A4’ÍÑzô~j«ÖSYþÐc0¶•¯ÏöìÆŽ {ý*KW·D&ßn…”ÊŸêŸ.Ñrâ|4æ.ÎA³Át÷‰ô='áC·}œE7íã÷ì7X^ÄiNaŠR2mÌèK`³Nx¤sô´îç¹×^΋¯z€µöÝäy¹ŸÊ`û/úöˆ( $¬8š~–Â%¬ßHU}ždí»èéÚÉÝ{ÿÇ€=P-'‰¼oŸ2+h–…ƒyP7,z!g-º‰s»^KU­gÚÅúPÅ´¯¤]QÈ‚{á=d® wMÖum¥?àÿŽtùÑ ­ÃÙn³uI¯þÎk;¡àûEY()¾¥WX5¢»&ódéòTþhmê_–ökI»Ô†±é¢€H3°ñTÒEËÉöïÂî}˜(¥#¤(ðª‹ÓµþT¢ž~(2Ä…]A ”–nƒ¡C=H)’„þI˜ÐâÁX¥ÐZÑÿÐÿåã{6ðê ocù…ýœ›X°¦ ÑZˆ´âX¡ØkÆw‚켟Ýp9Ï¿@mü-¹Ïß9½§b[rž×ü•Ÿ?á$L3ÅÔ¤—#ö6²Ÿæ±cçqûž[q*HºÝqØtRžÀtc­6lbKßCœÚõjQBÃ6°„9F!ÇN{|Á×6ü‚ðRS½>ãËãcg}•ƒ¼LÊ»[žƒWÁàG¡Ø iÆŠ…÷yÞÜ+¬‰ºfótÉòÔüñÚ*/ͽ/B!EyD­XG÷‰ë©ž¸sx/f÷Ý(qãPá „•먭ڀŽ"|‘ÍGi×ðO@û³"áÜ %_ädNÈâtZ¥·jéÞõ9îx Â%'ߎ\±K»!1¡Q®´g_+â‰B3¹jG¿Èõo¿†K6¯£oîZꦉ±OþŸ¼¤cäv ðšRÖ;Þ›¼‘פÒˬßÍÎâØ;;È·ÛÇLQcI úÓ@®§rË ·r„ÓŸÄ齚“·Q7 CŠj€ró9¼¤ópÙkèlŸ#ð )§–R©©*wLßÄöúøÃ¼;z¬ö~;ØàÞï€}ª5/æ£íqøÅ^aí°înÑèÒŠû³uU÷âÜjÀ”Þ.Lë˜(‰Â¤³ø¢ ¶âDºN> ;y”â¡[QE†N´ç,ÊXTOÚêMD‹N@9‹·9‹.£^P?k|gzW+opENæcò¤­„TƒŽ#’DÓuðë½ççð%{ásyþ¤Æñh]q4‡ñoÀù(¯}÷›8kéÅ$3Ï¡a›81¯_¿;V–ˆ˜OG àâ‚Vt7¹g§ù pÛÞ‡92·žájxíx‹º¶sö²38½¶žÅú4mNî2Œ ™¾·ˆ¤À9dïèhOúžé\”û”jÔËcÍ{ùÆÌRå#Éþ®_²Q[?]Ý0Yvkƒã= §,¡k&‹—ŽFüöæšym惆þ¨ ãˆ(Š |ðNï,>7¤K–Ò{æ6|Ö"Ûñ5dv ]‰Påöee â¡!*«NF÷ö#6ü_zø•JáÏWJ¡¼Áf9-]Áèn¢’ˆp *L EiL÷ä}øíó¼Þ¿å+WßÀŠhŒÁÄM°qÍoóÆßüCÖ§WãëhúÎÏï;<~ù'=S¸¨sHœÂ«Ài¼^è]ΣæÃ.šÜyà ìœzœØÿIÎ_ò 6UϧKh¸ÎZ¯0¥ç'ºI¢ áÔ°ãÒÀ÷H Ç}AÑ­‡˜³|yúcLMÎ}-: /­këø'˜ êu™zà/‡;LÍf¬1Dç,MÜÛ×UÝ&ë ’&Då.˜'9óŸâáAzÎz.*©Ýóeüу¨ŠBEZÊcP ¢%'.[‡Jkˆiá¼-û ”7l5™®QD5R qäîi|z"¥ÐiL­¹vlç-Ñoñá ß÷Z.?ãM\÷KŸ`™½ž¬>DæZåo͇ü§\²ÇEƒ0ý×öF&’ aŸù$Ý~î:ô·x&Ù¶øpRr ›h¹:åÂ|@[ 2^a«‚D×ñå9 Ö-Ø‹àŽ€ë $Oí#*ª‡cÅ^ Si2=Ás÷²YÁ]Äß#|A„ûO M–;£·f^Î[›k6õ¨Õqœb5¥×”ú}›ÀA‡@ù¬@wUé=ïùD‹É¾óÿpOì$JI"a’ ʸÐXZv"ÑâP:Á› G”C²œÜy²¸%$º-î„ÆJ{ ëÂ>;%è(¡âÆa÷7ùãÇw³‰?zÿ/r>¯gvf˜¦ÁañªÍm~0Ú,˼­‚„ PVHqaÆ@“Såù{Š»Tš5É«Á‘¹ž`xJã[WRM/64©)H¢:ÀüÑ´nAÉ„¯Î«p¨†UD’«”‡æ¾Íý³Ûé­Àq¸c¬o²Ìf||&”ƒêɸI„»7Õ,ƒº`-^ÎÌ=§$rþiÃñºJ:Pí-¼Ç5‚a´÷ؼ@i¡ç¼+IVn${èV܃·Å I@Pþ’òb<ª–-YC4¼4lÄhÕ1Ö“E= 5•x~¤ ¢ççUÛ€Z@EHQU<~ÿ<5Â뮹Ÿ·¿`—&—cêýAáså@‹š÷åù¥:Æ7H0Ž Ã­Ê-8!”vã§}Z¯ ˆDhŸ0ãöP“E —ãJ2”pò®}ö0 /X«PXÝ@+‹õÒ™°Ê”åe9žQÃbØ1ýeöç‡èOa÷ØþHÈQkZœæ +h©8 :Wøl ›–PSšakqœZxNéŠÙzÚPzj_*ävAðü. ”¡µóÉ][·QÙt汘{þ èJDTþB0 G¼ªV%X‚í_J½2Œö–Š*JU±¤¡eM¬ e uJƒ)§¢"ÔÁÇøâ‘'¸â¼#¼üe ¯¸ÝXMf[8ß?¡î†w^›uwû.~@Ø)¤;—Bu(•ðe©èÅŠÅ•MüvdùãÛ\« çÎ+Œ Ã&©šF)‡wAVëü“>ÄãTz˜6‡Ù1óf]Î@ ÷>–²ãQ:lZrŒË2¸g²Â´¿Gü$!È…†´E‹cNá•ÆÄåŽìuêprÎ’š"ótÆ’Ž/ÙJD RädÛ¿dsTϹ’¨·{ûHV@EE ñaxB5°h¡LjÇöP]|fx-*IQ6/§ÊfkT>”î(~j[ÉÞ!^±‰Ëk£ÆyaOó.o=AW©ëâÖxðp˜Ù,œ Kò×äžÛYÊ…¥ú$Ü¢CÉ{øv´æ o©Žè׊eDlòŽÍ…eËÚ}þƨÏz±ó„½GÍÁ; -‡^4BåÒ× :Æßþ¯ÈÁ½¨*¨${ý}„þ€sèÂÒ2Pïê%\„ZÝ„.Tsç{«á"t€ǶE:!Í=ìŒçÆ÷ñÈUÇx×ÖFíùSø&Æ•»‰­!ŠgHKDu-Œ41¦Š5ý aÛ[9ù¿4*2oìïÅÚÛN³°žo ´±â0®`ºc,ÛË´9J^Þà*dÓ«øÆ½ýìš~c'ioA€'@¸eóøþ;ƒJö ô£ØÖF¦•`SCiZ‘¢u°á³âX~öY#ɉ]‰ÛàA *`Atx#ß+07GþÅ¿¦rá+‰/|®çfäþ¯¡” çál¦”b'x­I]ŽÂ0uQˆÔâóI¨ö@÷pøšÔ Šç- Ê7#¤ «ÍXS]½’¿ëå¤[zyçì½üÆUwpru ÝXC¥2¢$àL96ÞG‰[ÅÇ P‡)ÌÎG Ñ“ˆd› t–’y’H9ÖN>t/Dh1(=C„*d~š9;AÝLP·S—Sx“PôŒT³ã'óõûkìšyë¦7þS¬¸9´3}«à¤ØÇ71 Ö( -äÝB6™ÓºýhÞ¹”#¨pDAODÖr´n³Í3‡í™‹k1áÿÄ[Xau®É5 Æâoû®5…œq¦»ÿÿ·wæ1–×yÿªº÷¾×¯—ÎÃeH IqEqµ(’±, ’wËV#1"68€ƒ°;Hç¶Ä‰!v¬Ø@¤(–·H"µ Erf8ÃY8Ý={–žž­§÷×ý–»UUþ¨zÝCšÖb“â¦<Ì ÷^÷­SUç|ç;ßA¿ð¿‘ºÂgiPÆÖ&,¾ áu†J=c.g•ŒÊ ƒQhEHjµ ŽP¶!Í‚¤Cá•d7¨ N„ ¶nâãéßcï\ÆOþÙS”?áøøè–ÛHä*j ,;‡ÛÐZ%—¢¤Ù¿~ >ÌCØåº†w¡zKðØ?¦úÐ?'=ø9¤?‡W°ƒµAt8‚‚¦A”gÌtlBžŽ‘f ­ÌŸdãè÷”Tm0 bRœiR'ž ïkd“ãþ«ïâèìV>ô¿ÄâG–øùOQ‘cÔu8zäS8#àe%&mSU#X? 8ªpžrT¾ V¥ïS»>¥®Àz‡—Õ %+‚! Y€‹¬bOhžÅc]Eb<[Õœ>u/»¦/1Õ}ÑŽD´Ð˜¡Ó)ðŠŸ{Aqxßr‘Üog¡WS«„R{r Åáúµwݾ٠{¥©Ñ뤈øîð#Ttt;u éýòÁ'¨yuä/Ñ«çPª×&8BbÂ6Ña‘‡]ñ=:²™Ä„ÖîЬ Õñô ØÀ€…ë\/Jœ]%I;èÚl¢µ¹Å ýŸàcO}•ßþÀ ¿r÷"žœ…8Žñqyb^EiOíKlz†ÊSÙV`íH…75ÖUÔÔëÈc-.hx…–.‰%)>âýBHdÄmkâK†°Ù}GNÜÅžóÇ8ÑÙÉ2¼ƒJ•T*deë3§¯\ðÈJbTÙo×dåcó”÷ÝÈÒj榚2Q”ÇÖÈ áÑ{®²W'„Vk¯ååÇ¢8“Æk‡››E}ùð=÷þÜK_E­ž FbB, Ã‰àh:£á<ÚwY•«pIBj$6i¦(RáQ4®&k­‘&)BF% MmðÍç—ö?ÃèLðëg ¡éR`Åá¼Ëa#HãB‚8¬TXéà*7‚³*Ô3D0N¼qÕšÀ‡XŽt»Þ‡9Ãnãñ¢”Ç9•’Í„¡î÷qø¥ìžÝÇTwœÌ‰¤1ËRi"¶O± ÷ÀËnâPC¾]¸ÂD…E›¡^¥­8'”‰!O4ùt—¢ð<üеɻÄxÄ*|’Äü0žm„ôãЩÅ÷:¨§ÿ>ðSÔ·wa i¿Â]lœ¢ãÉ ­I°lvVü “‘èÆ$×ÖXQaQ(Éš}“!Ò da ˜÷ 3Ïmþ ¿?}ÿ1ßÿþÞ¸Jµ(xåâ¿Ü ÀQKÕ=´Z£ö›p®ˆÅvteƒj‰ö5Z/‡`݇ÅlØ(¾K,^Õ\“µ€ƒ/]Å3—žf¦?E+Ñ1át‹®òešXW¢lM¥"Ül€Ëö–aÏýð× à¿#xr€zÓ#´WR,ŽJ)ÊE±Pï™sÏö¡;ÌFê0+¨nHh˜‹‰¶8‡$5¾èÁ¾Ï ïýaÜöû‘tº'â78 âu²…ð3…e³[eÕm¡È†HŒ 5aáEã¬B›ŠF+Gë!4dï‘sæq›Z[~qËÐ=Pñå^>ñÑ»IðÔÔq¡j5AQã <å Ž­:Tf…ÒRÛ ¥\”ªQh_ Õj ¹¸ ç}}‹ïQ¼ªñÊqCr5Ìÿ{O¾~ù¯¸\\b$S¨8ºF|L(bj(¢ JZ—ÔòiNùE>‹ ñ9†0òÌ¿ÀïÇef­vÔ:‡eÓ¨¢SÙbÏù^÷›Çh4¡´QîNC"ñ° ä}ÿ"ªèÀ-€¤ù4*YwQ:œ Z i Ê2æz¬ú„ÒŒàu(Ý8«0IŸl8G«ú„ÌàDR*ü1i­Mð'û¨«I~ñ‰;14©©IÐÔÝCO—K¦ÖA|zí×(pÔ¾‰ò‚¢‹Ö]´hpI™&†)nƒ£_«ÑŽ›’[è]üqvY晹?e¥n3–%¨ØOpîN¢|®tC¡ª”þÉò¬_æiI™÷BCÁ Ð o|mÔÂUp‚ô9|ú!úÖ2ç,µˆ/šFå¥WÅóg׺÷Ýœ>¶eˈ¢ , OSõ6c}®KC Wå0ý<”¸íû@§àÏAâÃý¯§AÎW­@7Ï(}º>£¯F´=Ô'ªQë‹ël‘ÀÓÁ¤)ÒaîSOò?«¯sãoßÏ ŒÐ§BÇÇzêð»ÇÝï0(‚ô4z{$2‚ ‰’ ½ÙÚµOÙÝÞñ¢É˜@qÔÁ45 4(x"Þÿîµv€W88êJ¶m\ÊU…QºP ߟ^èõs¯¹çö«·KÈkÄ9¼¯C$¦ƒH£$:Ši½.L} nyÜ´»°- {AÝኗèÈU$Ê3æ¡íÀež†1È€® É–ÍprŽý¿õ;úgWsç÷˜ŒKB¡•;‚è…Ä|@°±Î*ëb1!,¾ˆ ÚÌâ‚”1 U!mÙ¦[´:?ÍäÔv¾téÿðÒÚ­ ä½u‰× lñ‘5@ï\¯±»´â0)(ŽX˜ñ ‡)¸—@ú(yN€W:ÁÀŽå5¦ktG¬¬R*o)/uÊ2ŸZzè¡;·Ý!›š‡¯cw#œ ¥1á•÷àÌspÃPo†º€[Æ ËÂ{´Ù8 t`a Âf,+¼ò4S˜fëxf‚½Ÿú=¦~ý^n¿ó!4=< Æ›@ÝZÇþbʇGQÆC>,£¥Ä¡±”¨õNE˜ Zn1QØÂ•ÊQÞb5\Ë5˜å'8x:ã‹—þ˜™þ9FRÐb¨¬Eå»—‹OxÁ$A £}º^ê^°{t¸ã(Ž;Åy[°Ê,ÕzixP—xÝN€+`ÉžXµÜ1ÔÁ])JÄ”CB±Ú·ùžãóýûïÜv_sÓ0ôƒBH˜=U]Œt’ðå=¸t¶Þ nœX„{n€‘”.°FµZ׃òÂUÞ³‚ÐoF7mÃÿÕÓìþüqáwŒ[ï@ÑŤé½Èù×á3¯Ñ„=Š} 5EED±âb«x6„S·$„i B¸žÛ¨æg×é6OÍý7Ê%F3A‹f0–>òW×w¾a¿JÀyKû¸»Ø_t»MÆ$0Žðp±è²f föŠ5y…½þƒ#Ut]f=C¦G¹iN”­)²Dò~mó}'ú÷Ýuíƶ ý"ð ­©EUAkCÚ¨‡dù$ŒöÁ]gà¡[àê1(¢þ¼ºâJ0±c41lÊRÊM£¬üñ§Ÿø´?õOÙ¡oÀÓǹڰޙ'q‡ÅWHÂ8›à5·TÐQÆ2®Šš©]ºá²ˆ(‚¤X®åQ/þ0ÏMOó•…ÿEßUŒe*Fú²±cc¶*vÀ{IÀ–ö{¢\e¿É˜Pš k™"e®ëéØg±<ø—çõwd½,ÌçÎ;¾WzܼÙJß×"ªl¤¦(kWï¿×ÊcÛnË‚Ôàêä¥u褴68G3Ã;—Àæ0tì:¸n½Š"œ•F…x ‚EŒAÒ"ýÿÄîÞaV~÷_r-${áZ-"ÍG²~ü×X‚‰H û_ÂÎA™b0!aã ¦ÄâÈBq5çìÌûÙ9³—ÝKŸÇ Œ¥a×ëX·ð*Öu‡ð(qHâ)×+Ç9\÷8 ›L(ϤuœT–…Ž£kÿÏæ—}ý«ÚwÀ`Ý…=æ+KéæeRmE©*M¥¬­-ÆÏ,æ·yÛ±cËetÝL<ôà_T’‰w}¿´ß†®‡ûÃÿ|äEpáãM›¡ï¨ÿͯ2q³£ùë¿J(lŸLk’8DmÀúu1dsÑ ð¯Z?úm,«˜úUQ5ÊËÇO!^!N,žšMŒ0â~’§oæ+Ÿä@{'‰†!­ÖA—Tàü»0ÀÒ¤H¥/@û8Ïc9hLà9j=ÓXº7×û‰ýü|SnÀwÈØ ‘p‰Ý{¾àÄ5+¤[kq®2&É%qåÔ¹vÞ¯ü#wݹí:Òú%V×aÑkHñeÌ‹>tÎ@v |y¬õà?ÀZh] ³sÔÿþW™øèÍÔÿè †©ÐuEYkVë“A‚ŠqÚ€ =Šx<%>îü€ÖqŸ \ÏÂߪ6®/pbº\͵$å9xºÅWg?ÍñîdÔBAùÀ?Áž[o;SI¨tw/R¶§Ø¥„ÃdLGPœõË+S”õÏàyáÊçýí;çë3ÑðìKYŵ¬ØºÔÎäM­ós Ý"Ÿ¼üþûï¾þVÆèçPhPÕFt?¨ôU„]^t!Ÿ…t<½ÚËð3[àÄAìoþ'~þ£¸þ(-º¨”k0¤„ÄÁZQ¡R‘½"~¿ž°é¸ëëxÑ,GÃ=Oƒõ0P †>[¸•¼ûÏMwØ9÷ÇœïŸc4[œ|d”ºA”ªõaáѰzšvg†ÝÚ0.ŠIËRÝa¸Aœžú ñÈ´2GL~t” ]>Îlï2{TʤÆ-œHR.¬Õ´Û×`‹W¬ý·áoŒÀ: ‹h8ú‚ç¾vi++ÊV ÊFKçý².wŸÏxÏõᆰª ï³ñ‚[C—)z0Ö€ý(§qþw~’m´\± Ú‡ bULÔš”- Ñ.+JSÓˆðª‹|†P ¨©ðñ„ @áÖ3|/ÞÁm®Fx§æÇØsîö¬ü9=çCŽOàZª¸X~£0¹®7˜™01fi’Óe›çMƒIN1Õ¨™íätÚ÷`™ûÛ/Ãç°±{ÆýøN§>ûC}ªj^Œ«EÛ¢¡tQV6ß;y©wïÛÝzíXŠê(åžJ²áéIÓ_¸qž#nŠ_`=9$oÄÇíñøV(¶Ò`µ®(\E3!"û6¾‘ÜÁuEÆïHòÑ¡¦EƒŒ;8tαçòN¯>‹Æb¦)l;øˆÍÈt¢R¨º°4ΑºË ªÁ$ž N¦Â\'£·øwÇGÉ·}úo´@Ìo‚àµç¥ƒ9÷¿g‘JY1T©¡¬j)»œßUØÇ¶¿kË:Æ*^/û<)0Šº>ÏŸÿ?zçpãÈVútp>EùÐ+1­ Ÿ®’ͪA×Õô«œfú°o…ES"ëÐ®Š¹¿ŽqÍ(›±îZvÍ̲wþiŽw&0Z‘n€!wû@áSo³ú °0É>g9h†8â“§)Xì_Mïòs1Òÿ½odo¼ëÄ$8ç•\ûÐôkñR%)¹’ªVgPÐy ì›…o”Å“@øý/:Ò~mfÅËqÑr 9Ô<°Ö¯žÛýâÌÞj#4’H"1ÕCcÐÚ lÉ4ç‹yþpæ_q¾‚N¿I]ÐÔ#†HtMéƒj‘Ñ@È2 4 &ДR Œq‡–.óôÅé|ž/N Õ—hbâ ‘Ù¡‚­ mfs¶w‘IÆ~¥yA)Æ•pNõiŸÚN­áe ¸¯•½I€4Q¸q§§p= sY$=!ZȲtmÝîç_xvi®[ÓjÄn¢Á+‚D‡¦‘T¶6Úu—Oœù9NôvãªU5DS‘0}°IJÒ%c‰‹.dh "©›!Z´¸ž½—O°wîëLv¿LIɰ!èÆ~B3(K(Y_üD‡†%Û‡Ùœ(—xF7د4´æpÑkÚSi\|ÿš¯=ðfv`{îSÜCOyVmNC¤ò§”‘Ciš¼ Zí;xdöé çÚ]šiHžÓJ W £@iÁ(ͦ4!þË™_`ß꟡¥(AåÉZdé&h2 )І$V÷Sf„Í£<3{€Û»8Úý ¥¯ijH´Â Q(‚’YܽFc k†¶K8Xuy&ÉØ¯ûç˜vÌ.hÖN}§#wåõX|xÓÆWZŒ|Èß9õbÉö÷-RVµ(U¥J—uâŠ#'çz½Îð£·íؼ5 9®C—¸ jbŠÐ<¡6kÅš-øä¹_¦¨—ùÈÈ/Ðn–l6×5%9–¥óû>Z“-tl—½óû8¾¶—‰ÞSTâJñ2fb“‡÷qâ¹´÷A7V/z7;É.<‡“&ÞsT)Î$5‹JŠËïÅ·b“Ókóý5{ 81èô5i¸ídÍ¡»Û莭J£T®¼)Μ_)úÝüá÷½{ëMdèz]=L….î€û)Í&Ó¤ßëóÉ©ß`þÝ—øé±ßb¹žc‹¹– MEšôÒD¥ÅVf«E^\ÜÏK½ç9ÔûxÒ;t\”©¨X S¾t"hãY8CổæEÑŒ‹æ93&eùÒfÊó·s¼\'ùu²·†¬Û Òœ©é¯1¦­ôT¥””C$¿¼Ø+öæçßÿð­[o§‘aL˜ý'j0==ÞzeACàªÍð™¹?¢ëùÙ~—¹ê,›’khÐ"S–ƒÛ%$ 3Sœáhû'º_çàÚWP m¬"‚ô›ŠJa¶ h<: ²¸—³¸8í÷˜Œ -Œ;Çqï8§†Y[:F©`c˿ޫϛ=xU‹ø¿Nà3;-V:tÓY±ê¨R²¨‘î_Y­žyòØ…CäcIh3D£•)úàkÔHƒá4c[ _\ø<ŸœyœÊÌ•Ót}›”Ð=¤IHiq¦wš©Õ Ž®}™Ck_!UÐT ¢…D Çñâ6@š…âü‹þÜÒŒÿZÖ`¿Ö¼  ‡“ŒigiÏßH¹^¾ÿ->¼åN€Å--î}γ뇺HiEªïŠF&ùB]Ÿ»8Õ_¼©øÀpj”©eÁ÷{¡Ž4Ô ªNh¨ŒkÓŠ½+»X«þ>?¿ýSä¶Ïh2ÂUfŒljîQ.åÓXûS&zûh&’†…0¸ÚøH0q‚¹I=E.¼XŸè¯²/kpDiÆå”Q\êVôöoÇÞñ:EùßÌÞ¢ëWMp?ð¤WŸ¹ºÏUïZÀUV”«ŒòÅié—ÇÚíV soš¾ÛÅ¥ÉÒëxzB/ÛtÍKùI>qáòĶOÐw›(Ü&Ê Ìægyvõ0Õ;ʨMŠˆŠ›5ÌMv˜NBð™4ãJsÓ»‹¤°kº¬»­Ú³ ª·Û&Ù{ò÷è1ƒ'EEµÓЖNP(®Qйj‰?¼øOøåíÉÕæj§øtû—™é_`Ì( 5“ý@ LÂÀl(É`é‚u&ìn<ã¦É¸Ào™Î*ý5‡¾z[kõÆì~x«;ÀºÉ ’çåÖ‰júÔØò|ZøùF_­5ˤ½T$íq±7¾?½§9U»j½€¾BVGBIg³ªèYÏ¥ò(cfóõÖç´ ¤*ì|‡ݼ a'‚ñÆcRaþdÕ½tÌîÖ “Ê0îGE˜ñ†å©ÅÜ=ÐúRìì}£VŸ·¯«i}dº>2£Wfku¾—ÖÆ+L™{5ý|·¼åþ惭«ª2è´éHítK.†¦¥=–‚ÉÞÐ’1œl¢ãà @¹è<. "“†ðÂdµ¸pÖîJR&½bBǵæ|ChOž£Öï %á× šûw¶·•࣭âÈJQ»›X2ýГ™jœ+¨N¿ÐïÝø>ÿÈUÛSS¡ãÂùWÑW¡¦D£#Ì$C³hâCC³OÒPXë8{¨8מõÏgÍÀÞA8î5—t‡ît‹jð=òŒô¿‘½½BÇ sßsŠêÁw³¤ ¼jÛ p5åÌ‹ya ÷Èuïn¶ªÒ£êÁ]™5+°¾ú€&&:J½9/¨hª!T=ÇôâD·í÷%CWŠS:åRßÑk߀Õ+oüŽ¥½ý€õü€DðÇg)¸‰¥ºK¥•JȽP\:^öʾ{tÇ{[[ÑP•Ô:Ù`Ôä‘(¦Pâ‚HY ô´ø ãÖ:+Óó‹>ÒF(åRs*3,,]¤ûÌþ‘á7&Êÿfö¶tØ( hàäµ”w¾D;Š«¥$äJQ,ž­ —w¾åþᛲ!EUXŒ\@õ*ßðnT:S*„ëúŠ4oùRå§_ÌŸ¯³&““µgºáX¬ÅÞ)¼~èÍqß¿š½m6€cåáü0õ­k=õšJ ¥Qä«ó¶˜Ú·öл¹shÈPåqŒˆsXÕÇyâ q¡´«JCÒfOÅ…£å.àp–1!Ž#3Œå¦¢øüH¾þ¦¸êÿF{[;¬SKÐÀ3}ìÝ : 7 –B4EÑqùÔóíþ-÷Þ?²Õàú5¾VX߃Xûñ$²DPF˜9Ú]ž;]ïQ†qm˜á¨6œwŽÕcSíàeÝYoÆÝï€+bàÉÿ±-tÍ,¶Î¨•¥PMúUN>µwµ{ë}ÃŽm7ªÎƒ>Ÿò6¤yÚÓHÄ Ó‡:—ÎÛ=I¸ïÇ•pÂy.è„Îá”*“7÷¢_iï€ 'H=<•â?}çY £ö5UÚ¤tå™Ãb{ÑzôêwÓ\³gq7Ð÷ËÐ\E Íé½Skóv_Ö`B`Å”J˜îÓ=P`uú-õd¾iìã›.Ž`ö£¼ï>–’Ðæ_Ú„«ŠËÇë>EúˆÜ}nK_]Æé’º-Lï÷ãýN} iLŸšSºf¾ÔtÎ݂ק¯˜0ö±·`9øïfWÏ1àŒRÙ+NqÖ*ñ/˜û—¦eçì¡ì¼2–rÉ0³O=_öíóYSö+Íã&e¶s3ÝÏïÄ'¼µvþÀÞQ'À•6pãáäfꔬvRê:÷¥1¨:_gõ̳rG‘ûk«—’†;*Z&ñœµ9ËUEñW[ðYL ߊöŽuØHµ‡#Û°×ÌÓ2\W×^¹\¥v)Ï9Ž'ÆŸ÷ÚN‰²tͲ֔EÞûfô¿‘½ã®€W3 ¤Ÿý*~e=µfç¼µ'œ”ûÐÅŸä{tRkÏ–K/ì£ÔjcÑߊ ?°wô 00!áFÁŸ7q?7F7Ñ®èxñoµ+3E¾w”:Ö‡’½Õí»MI„k}ФžJ³JµÜ@¥À(¸Çñ­ëߺ÷ý«Ùwà6OnÃwR,#Ðø ìØJœnþö±ï:À«˜‚»$ˆ†#˜7˜½ózØwƒÀo`êÊ×Ûlçì»ð·ï:À;Üþ?¿CÜK­l5gIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/ksnake.png000077500000000000000000002227011217176075400232000ustar00rootroot00000000000000‰PNG  IHDR\r¨f pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÜIDATxÚìýy°eÛvÖþ末_k·§ÍÌ›yóæm^«§÷žž$$„„@!dÓ»(À`¹*ÜØQ€M˜WØ(Û8pi ƒíØ„ X¨ƒ§I¯¿mö§Ýýê×ìê}%P¹\Ø÷éå{äˆ<çÌŒ}Nì½Æ7Çãß'¼÷<çñ<þÙ ñžÇóxÏdü[ßwHžÍ Tˆ_ôoQ°^ —àEO •«Ñ³š p¨@Ç!ÞyD!‰s)%Îz„€(Šèû)%JJœ3hk b…÷ã5Ök>ûý%ƒµ=>ŒQÆt’¡TÈr¹FJ‰ôŽ$Oxíµ{üôþµù†_öQÞ~û>Qr÷î„üàþ·oßâêêŠÃÉ”X9ÆGs–› úŽXyˆ ί–L§#^{ÿ+|æ'>ÉñÉ)»ÝŽ¢óøìŒ,IéUŒ3¼ ïÂ0Â{OEÄqÂ0t¤iLU6”uÍû?ð ý¶|q·ÝÞÉG…¿u÷E$`œåsŸ{‹®ë(Šï½B<òÞ?”Râ½GkM–el·[Ò4%MS„\^^E\-VL#óšx|ÀõÕ‚¯ÿeãêüŠÍbGã £õ%˱à9þ“pB $„/$ŸýoJ¼r¨X€x/pbGB|éeÿî—Àã=EAY–w„7‘òŽCæÞû÷yççAÚÆÚ“(Ц“éÔÕeIš$¨è‡Ö¥”´Ön‚ ¸D%…XyxÝyjçü#àLJùèüü)ÕWÆÇ/R*’8>øâ|9Åsx÷ƒR B QüOÿå#'y,ðBà 8Ï»Èýl„ß+ð|È{>ä½ÿ¨÷þ%)å©1æ°íº‰šY&=YÓšÇOÎyù¥›ì®×lWT¨°cC¿­5Qç9CßcC(w%Y’K’DkkÝv»Ý.œ÷8ß{ÿ³ÀgßýªžƒÀsø²8ñ廉„’(–|ÿöA(c‰ŠRyœÿ_Ü@~é“ÝÿÂyßâ=¿Ò{ÿõã4¸Ó”íáô`:Ó&eW÷ ƒa: iûž@„è¡'Tš³³)5‘„º¬(Æ‹ó ggQ¢é±´iiZ Â"ÊZ”K'jf9kï¾ðʬ—,—ʲ\GÊ/¼<|ÏžƒÀsxÆN|R‚ ’ˆ@ñ?ü©wA”*¤/ÞýâYøàý‹Àoôž_•¦éú¾;=:˜$UYzÍ$9?;g‚~ð˜Æù‚]í™L2æ't]Ïk£’|L=8d É“)³É!MÝâ?æIÓ”aè°Æ²Þ.Ù5+ÒtßGhª§è¡a½ÙÅàHQ,,Œ'uÝÍ‚HÍüнš§£_µªÊß›eÙ…‡ÏUÀß>çð¥8ìÿqâåA$ø+òu‚P' !ÿÉß©ïø'Ào~û0 /ŸœÌëºÂ{OHš¶"OÎÖ̧wî¼Ædz“Û'·IdD$nœ¾@DX£¢@÷†8Šhúž(a{Íx2¡*òQŽ³ŽªiRbœFYMÓ¶´Ö‘Ç’ùdÌr³d·»f±yÊõõ"ƒÏ¼ùs\]­QJp'x;°ÙÒÑ4‰Âà®ÖÃ]Û›ï*Ûf-ãè÷üyïùo€Ë/'øðw >óþ9|ùøûæžR…$J$ÿýŸ|âô'þ?™ð¿äÿÿ™~=ð»õ`>æ£Ak´èÝ@]oYïàã_ýîݾÁk/v˜ÜÀË« §GŒÇ9 ڶ§ª+ò,ÇZ‹ ‚ $V(²T!¼!‰õnC’eŠ"ÅÛ«-óÙMg¨êgCŽg·¹}ㆡe[–DiÄ׸æá“w¸^=a³z›‹«7¹º*¡½âÃ~…¦ªØíJZ=ÌnÌú¾ÿØhTüïýÏxÏŸñW¿@@ÊŽÿ:AÕÀ×?€/‹ä—ùn©…’ÿþO¾ƒ Qòÿ=ñ¿D­<<þ?öøÙZw:Î3v«aðälÅñ鯾üµ¼ö+>Lιqó&ëå†(N±H²,' Bpš¡ïxòä a ¢$¡ëw¡¨ÛŽq8)°º§÷–õ²æà`N*„3”Û% ¨ ¶5ã‡P mGµÚ¨ˆÓ7ŒÃjÅ«w?ÌK/¼†7ßDš¥,ªŸóg(‡G<|ð70™Nèûžª*™ÍF7nÌ¿¹,wß,¥º@ð—<þ÷áýÏ¿%Ï(E,R‚À…ü5‚ÏýmÿžÕz_H@ ˆbÉ_ÿÕðÀ¿â½¿À{¼÷ˆgâûÿÝ”Bâ9ü’v÷)R¼;Ò‹<ÿàûk¤ª c”{æÎ—2ñßm.ž:çÿÌG?úÁï~øðŒ0Žðê¡¥ßò±‘qv›0Rx=PîÖÔ½FšÃ£ õnMSnñhê^3XÁ‹/Ýb<.°B $´}‹ rʺÂjKEÔeIÓ´m(ˆXkyãõ×ɲ )y^pqy…Ö]×Óu-³ùŒ$É躆Ñ|J82<}|F–gLo¼ÀÓ'O ÷ŽÕjÅÃ1Ýб©5§·nDŠ·¿ðyœ0[(òŠŒ_ÿíß‹q-—»×ù±§?ˆ”Â$HñJ±«;0ýw¶J{ïÿ†÷þwþ™9hþ×›ƒaçðÅ?íß-Ìö³|% ¤ä'þf’‚0~÷¤ÿ'þ»%µ6¾©»ßÅ!I’ç1«õi¾öƒßÊ7íwSŒ £Y¯·¬/žr8›Ð4š¶ëèûŠ~ì«@ÂÕõ5õÅ’"¼pë˜ÕjŶ¬ P,×K´6ŒÆcú¾GHd°ÞìðÞañÈPRn;â8¥ZvU‰z’(!I$’³Çg¤yŠ1†*®…°ÛnyûmCž%8ïñΑ¥aR¶ q'vè™Í¸X®ˆ’œmµfèÞz»äk¾æ«99ù6^ºõ þò_ýϹ\~Š"ÏY/J&§Ü}éý CGßtß-=çRð-üvÀ‰gà„ýÅÍÁžO|À9øöo;ݧ•6˜¢_‘ ÞMj)H©ø;Ÿ|sáÏ@%&ïÿ5)åŸr­ Â)ƒn˜Žù5ßø›xùÅa‡Ž·?÷n½ò"žÎ‹k V(¢HñøéC’$åújC %ÖiÞ~çMÛ0ôƒî‰¢˜éÁ”ºÜTÌg3¶›54ÍŠ@Jb™!½G KYmpÂ#¨0 Êcv»’ñxLÁÐDYDxgAX‚@༥®*Œ58g™fè0Î2=: g<}ã-ºÞ$ FwdiBEL§Œí¹¼¾ T)ÿ‡ïùÝÜð)~ô“ÿ“{4Zñ©Oñ¨ KRP0™M~«ëÍoõ¸ÿ‚ÿò™jÊ”0t8çùñ/ù–o>ÄZ‡ø2¸ <Ó $ÈŸ'äüü›)ö(EzþÎ?ø<„¡ú…ÿû%=kïUcÌÿ|y¹¼uûöM?>£ª*ªº$Ïcî½ø}õ×pïÎ9»xD[îÈ¢€írI6ã¥"És\]² UÝmC®.Wl«ŠÙdBœ&ôCÇv·CJ˜Ç(bh¸}z€î[”o™ÏØì¶Ìó1A¨Øõ1”¼p<%‹ëó£cê¶Ã G‘ÇTM‰1†Q1¦n*®Êk&£aƒ±3Ç1ÒI¶U…í¶Œ²„(I BAEH¡Ð®ghºç,2 q~ í[ŠQÁåù¶oyõ¥pûÆË|êáðCŸü[l·[„sꮣ);Ú¶Ã8ó§„ÿ&ˆÄÛÏDsP¤’xéq~øG–|Ë7€¿°ôó¬†|– ÂP…Š0”„á~”EŠÿ×ßx¿÷ÉwˆE äþÔÿR'ÿžm¤<þ÷ݼq룃٭³ó+šªa4Ðw=BÄüÊOüóé!?ûéŸâíû÷ÙU ^Ô› VkæSV»’ùtÂÉñ ã4׋*¸q|@+ÚrÃ8 ¸}4ayB×2ÊB8.®.qAˆ–—+JíhQ\×-—«kJïy´Ør¶Ú¡Š1›ÝŽ8‰PN#û†£<â …!À1û‹°H%°ÞÅ!y“&ùx JpxxÀòò‚Þ ¨( iFEN7´x;0ŸÏH“ŒºªY¯×l·W\œ¿M…üòÿz>òò72äÝãmG$4±Ô®G:M†_U—Û·¼³¿zVƆûk $?ü#K‚P¢Ô¾ù,žÑûÀ3]üº$K6Hü¢7PösëŸç=+ÍHÏ+v°k»ÝÝ‹‹œ¤íqqÂÙÅ’{/ÝâüòŠ8 ¸wëC¼r÷«øéŸû)êºd:#…¤î:Ò Àóù)`·Y¦)B ¬Hc‰=´Dú¶d°–|:C[ǪnñR2š âo4Y¼¯Ž1àmÇÉ|ŒÐšp”°+K´¶(TÈ<£é4RH´ë¥1XISµŒgS¶eóë<ƒµ2@kMà5›J1™"¥§m*Ò4£kZFãk "PÏqïnVÕ]‹6i%ëå5a’Ñjˇî}è-?÷ÖÏÑZO,$Â{ò,!6zh¹}<¥ëúÿH(ù¯{ë¾xëY¹žî#ÉýÈ[8ýª›Hµç£üüc,Ä—€löåïû®ý›Pda"„üEU”øùâëUoÍï¼þ³›ªA‚›7O°ÃS´…¶7œ+ž,žrrp—m¹AM–%»ßMwV‰˜ó³§¼ò‘b¼¡l;FÞ“Æ •ÄT›kŠÙœ0#Ko “ƒœÖ‘Ä0ÊSt7`Û˜¡!K c(F×› %,í¦ÀÚƒã1]»#E"(²ˆµè¼ÃF)á,fÐw5y–à¥#DÎæèºdÕ4~ kv8kYï*»j³ß­p‚ñäU””,WKðázÖÛ’ùÑ1>tCÃtrÈ ÇàÉÕcž..9¾{‰e[îÀG§iû<Ïz}ÏIõ¦ðÿ"àÏ=;=ª=H ŸúìNÃ'þù%2/xÚTÏLÇÉ»oÞ¾Ëú‹îÿÏf§b†áïËÕo͉3Çr[q÷å9ºu›í믓0V‘$ž(‰AÀf³d:c TU ï. •]OìÕvCGF,Ë’Éá!£"£×š ‰IÓ˜$ Þ±Y®‘ÞÒU%½Ö4eÈl6ÃZKÓ5ôý@†¨ `ðŽÙáÛµTÕ(¤éú–¶oJM’$´¥CŽÙt AÀ m×B)Å$ Ù•%O/.PR0™Í˜ÌǬž< cp–,/P¡ˆõš$ ÑCÄõzɃ ùhŒ‹®®”«òÃÉÉm®õuÛãÛ€³‡—ŒóãH…ŽN÷´¶»4KèÕo‹ãèãý ÿ9àÑ35µ’ï‚”ü½¿ð«ßù½/ã½xÿŸ]Õg ¾óììê¿Èq–¦ž3Ô-]g0fYõÜ8¸s÷‹ë«z¡(Ë-*4{JïzMžGÔuˆÇÇ9uÓ0/F´Í†§Ÿ0Î&£‰¡Úíøìý×™Ïæt}Ïx:¡ï5R -Qœ«€²ªhmE§ÄY¦£³ž"O(«ŠrW(ÅxìQR’Å1u×QW%Ú±]…ŒGc–»5 #@hÚ¶!Œ#šªáÅ»·É²”¦ª°Ö³Zn‰• ptÛ’ºÜ0 ÎYÖ»kª¦ÅtF(¼Ê:ަSšº" <žÞ8Š$bœd£›õŽ1J¤û›~—÷üWÏXá¸Wìu(¿Ä(Ÿ§ô?Eò{Tê÷O‹ôÏ€'‹$¶¯e)î_"dBQ× “4c³ª¸ºZ2™ÏÈÈ¡xó­K~ægƒÆYÃf³Ázƒ·f/P"ÅþÁöžiš±ÙÔ ^’N鑨 ¤³–'×géq ZT¨(›’¦)ñÞ±«*V› »j‹1†vh÷"šÓɾw @Hž@IÎ.ÎèL %Úh.–WôVãOb<“!J…{†ßN1¿@]Uœœд-Ca#‰Ìг^.O–çìv%qœ† UW³Ûîˆã˜qQàÃK‹q’°Y®xøä«{«ëã,­é£é‹ ú˜8’$¡˜Žrv­EÆ)¦×h!¨š7n£‡ï=Xvµ!ÌrlÓGêik…ê=¢ŸÀÿœþƒÖèï»^õlêãùˆ4ô^EUÙ„‚Õ¶gµ,A…è¾gRŒÎQm[¬À[ÄÐc„çÍopëôeNOiû’ùÁ„¶ki»£5ã鈺iI³„õfÍ|>ÅZM1“ŒGÔMs– ðŒ‘HT¨*d°†®©qv›-BHºa@ AÞiʲ¦ªjÂ0$NbŒÖ̧3Ò,d61?˜“å!ÎX] …5–ºi‰cÅt^P—5ÎCå´ƒæzuM–fDĮ(°ÎìéhF’ìuéh¿®Ü45V(?=£o[Ò@‡ã<çáùCœ­yñVŽÑ€°k,}×ãD€C€ëQ"¤ÞuÈÐ㴣מzð8a†Èô8m £øû”’t­yÏàŸâ ü»y‘ýѫ劫UEމ•¢ÜUHå}«é›$ iêÓµ Ũ ®jvÛ-›Ý)Ö:Œ5$iLYÕAˆÜÞð#ôCOÕÔŒŠ1RIò,¥ªv q̦Ü"Éòíû{†_ž2KâlŒs Zk´1¬W;¬ÕÌ Äž$”Diœ‚ÙÁˆªì@ŒÑÔÎ!MÛíݘtÏ`²tÄ®+9šNØ,W´ý–¸€4ŽéëÆaÂv[ÓÖ=QœîßÓA1ë]‹1=‡éŒ ôgh꺣×Ý»¨k=ÚZÚNÿÑ8 ð’ï{öžºçÀ$øÒ|B€6e{áŒ]õ=I”üQ!%}Û§9H’X(«ž8 ÷ëÈÆyAÓYº¶çÖÍ›ÔÛ51з6 IÂ0Üsâx¿Z»i–4ý†“ä”¶l(ò„(€A!Ùl+Pž0†H'L&®¯®ÙT%” ¼§:¼ 8œÏØn7à`І]Óp43çl6š¶­™ŒÇ¸¾¡Ú®M',VkúnÀž<ˉ£¼§ë5Ëå„LÆ£=(¥1(Á䈾ëÙ• hûß:Üx‚ŠqïAÃd6eqµd<9¡m;D((¦SF£”l:¦·-A&8sí/kæ‡s\ª eÄf]¡'ŠS”Pxë)ÒtoX²Ù1šŒ¶€f6›SÖ%¹J°Îᇎ¢ÈéÖ-I3/â?j›ê³SÿCÓYnNY—Ý—åyðÅûÁ?¯Géá¦ßzƒP‚£[s¢x¿Øry¹fWv¤É˜Ý¶ÄªÓ x!ù('pmO$r2¦{gÝTuŒGùþíVX10;s½¸æ3?ñ„õ¥áðÅ×ë„°Ì'Ö;Cg”MÍâòšO1qÖ¢‡*Ú®æz1Ç1IbõÀqÊ(V¨ÀÍ †Á¢pLG9#cç gÛ%§Ó%,Ð}CÛ ô}KÛ4$INU•l7{'!ãÖ­SŽŽfdY‚÷ðèÁcT°Ùl˜Ogt]±š$MÐ]޾ëÒ±Þ,ñNSé7~ú Ÿü± òXq㥒ìPctHšçlw úªFQ¨"B!t Q“å9J…ôÍ–JkT–ÑÖ]k™ÍÆîy‘t4ë a”p0cš ßïácà?ý.·„ÿ¬wü½ç®Gü­ÍzÌ‹ˆ4ÉPQÂüôv±¡Ù´¬UyMžöz{R1@†ŒG#šÕ]ö´©ÄJÁÁÁŒ¦Ü ¢c&Ř$‰¸^ŸÑè¿ÎÕ[Ž¿÷WÑïR*n¾p̧ôŠßõ¿•u¹¢*5—+º¾e0=Aà<8ï麖ƒdÄ­›4»˜ÇÈ ÀyÈ‹1ÓédOÒŽÍ®$#Â@¢µá«nÞÀƒÑuuNžØ­7¨0¡RÛª¤ÓR d/ð=:ãújA‡ÌfÞÿ¡W8¿¼¢©ZúAcu‹WžM¹E:899bµX!ƒÉÁˆ§÷Ÿò©¿_óÎç—ì¶-ËÅ‚¦+yß×)¾ý7¾A÷ÔMCâ%2‘¢MÇ  J÷ŒŠÍn`¢0c[•Ì’”é8C[Gg «fÓo†½KãÅ: Ãð‡›Î| üƒçW€çÉ NFÉ_ÒÆ[Û§ «ó3–çç$AÌ`A”R7%MÓ¡„BhGÓ {Gá:'1 gF’¦)z¨¹¾¼ lJˆcâ$FÍx<'ÉŸúäC>ù×J¶Ëö:×ç!‘ºÍßþs¸ýõ q Y>F ïŠ4¥k¶œÎéÓ‚<ßwß_¼÷2›r‡ó ;MU—”Í’óë5JJêº% #œÕŒŠ1q³.+„ƒé|Â_$MbŽoß÷#=ÛeÇÁíïݬßlwkî¿¥htÄ7þÆSvëys˜FDr 81>£’c𲡬{_xƒ@†XgÉ’ou½ÃhÍ´;Ãf[òÂÑØë§+d[V(%©ê†4ŽPQÀ(Ï(F³ÓŽn#œ`µ^²Û•¬¢8!Îc..¯X®Ÿœsóæ NNŽ9;;'ŒBŠQ†6–d”}úÇyü°^Œ²|“ªÞrpOóÍß:áñ›ž·ºá¯ÿ…7ø6wHhQŒ3¬IìÖ[¬J)›Žnp åyÃè Š#êmM–EôuÍÑlD­5›Ò‘¥C×’§!Þz´q§É/ ðxKÿ‡Àãœ^|)cQ»_âîŸd”¥Ä²ûåJÿÞn[' Â;„T¤r_‚ R—+Æã«Õ†Q”²\W„qÀh2ÆÖ£8EûKº®Á’Q’1›X]5lª^zùwîÜ" ~ì¯=æÉ›[^ú:Å'~Í1F´ëqȇ¯±[÷Ð4/Þž’äuÛd UYñ¹7rëômô»„žq‡© °G¥2Ïx” ™gº®f”¦®GxI† I3Ò°`»Ùb†Œ§ÜÖ”Õ†8͘Œr’4a~óâ½»¨@ñôÉc„°l6[Úºåàð€»wOXo¶tí@1*Ø,jÔçÿÉþ?zù 6«kn½pÌûÅmÞª~é(böRÎü%ÃO~ÿÀãO>ôícž.®˜ä#"¡Ðñž°Ô„ë,a“v)‘•ì¶-Rzâ,£\4%9éé‘„QÄ(pm‹ŒR: ‡ÇS„·\-6ÿÞ`ÅߺyëèG…T{BÑsøÊ¯ÞµâBÀmHIE1+Øn·ÄQD’F ý€ŠºjÑaÑïhÚ–,UÌçcŽ_:bw1Ð+M)v}À%)ÚZ‚T¡Ûë *PŸL ´]C0¤¼ñvcøêo=¤oúýn€0ü‰ÿëߦßDük¿ãßbf=Oß*ˆ:ô¶Â9[EV$DaÀzy‰ôžPB‘g8méšž8ˆ¢~ÐQÈ  "XoׄÞ!‘äňr»c<‘D{BPß4œN¨ºŽÕºÄXC9Œñ<}zN„ÔyCšE¬ÖGGs^¸uÌ›o?âéù9qr÷î >óÙ·X¬ÓƒéÏü}z“%wH¢'|Ïoøµü;¿÷ßá7ýþ—¸¼~„’ wß?Ç}—áìÓ‚ÕM>Nˆ$Háh»Ž¦ë(Fó1ƒèÎágu½!Læ÷F4}Çü `q½$)RjÝ£BϦÝ2%û-ÊMÓmêNã„ø!ïÝÜ;±{^ü3Æù?}½î•aÁÓÕšQ'Èòœ¾×3¬ñL³ MÛqðÒ1¦w”5××ÒiBœh ùxD,J ÝÓi„g~4Ç ËÃÏmñ8>ø )m_‚ ØYÃïú®ßÍ×¼ú«xùk26a2㜥íjе¦zkÅýñw’G’x–òµßrü‘ý/ó[ÿÐ7r8ôýÀÑ«š7~¢å­OK>òmc"Sí4N jW3”-Î)êMM’¦´u‡B¡‹yP!&pï}Ç«¸ÞV¨P€•(Q×ÐV0T »ºFÁáñD…aø§µq¿ù9| ã—ô&ÀZó=›Íö7¥yÂh<Áûý¸êÖ­¤QD*“bÂúz‹5е§·™ä9Ëëh˨ˆY,ÖD#ðÞ±Þn™LGdyÄPUø "M$Q0hËì ç鞣TËé"ŠiÄõbɯüºOðoü‹ÿÑ/üŠ¿âW}ßÿ_ü$çÌÎ^~ߌͲe¹8£È3F£Ñ¾áçëJ…èØ©' *Iã„ãƒ9GGs¢8áÉÓK¤ð¼øÂ ^JªmM§¼ô½áðäk Ûº#O Ú¡ÃͶéÈãLB<ɹ^ïðxÆ“1Æj2qp8¥j´1”uÍ ·ðÊãþÁO±°ðùEÂåå^úp¯üšßÀûï|ð{ÿþä_û½$AÌt–pêò`ÊÑ«3¶‹†¶˜Í2ÊMƒ·w0¡o óùŒíÃ’N÷t¥a^LÙn[n¿rÌùúÚ;(ͧAÑí:Â$"MC‚`B¹(I’)ÄoÂû_±^í~$/Àó•~xæààÝÒó‹žù@¤ÛÈýç‹ñMÛ*KÝ4ÌÒ˜¾ªèãÞ{úÎsmÎN±¸.¹û¾[ÌGŠåãk®Þ¾Æ0áJWH9&)2Z£‘ÊÑì*‚poÌ‘¥ãéˆ4Ï Êžõ£r&¹ñRFUuäðoÿæ¿€ àþÕOs±¾Ï?ü"£ùÏÐm=Q¯8˜~<þ8ÎW¬ÛŽ$)ÐÎᇞ¼(Øî¶„mC%Ü<=äÆÉ)u]ÒÕ ]µæêiͶõ`5™p %‡cœ(EUVHcÙív $Zk:m¨›–<‰pV°YoH“˜(?´, ÛmHþ—pn m7°8›oúº—Y,¼ýÖç9wˆY.¹ù¾ˆÊ,ø±O}?ßññÿ3ßñ‰ßÁO¼óßñöùÏdG¾l¹|gÅùë®[sñdE’LH“”T VuE‘H&C§)© JúªÇÝÔ|àC'|êÇß„@PïjÂãiqbö6Œ§9JŠBlÓýu‡Àð¬éN>¯ÞÃÞ¿‹ø½&›íÞ=7 ÙÓUë„2B÷ž¦n1Ú3Ôšt’2;,H£ŒåýG\_–Læc¢HrãäˆéØ5=7oñâ½S¾õN¤(i–0žŒèÍ@õ`E»]sóã‡{é,½å;¿é7pëð|îáóûëßÃÙõ†÷ßü]Ø’¥aq!iÍçIÒÇhÊÒ’ê’£ÃC$’Ñ$åæí¼ql×rÿóŸgèZâ,ÇhC„ ¦Áh‡5{£³·ÒC\Lѽ¦”R)ŽŽX,¤AÈäøˆºoÑV3žL–ë§ã”¥ìö^„·oÞàñÓwożv/Ày‹Øtø eÅ“<¥®ìOðïÿå_ÅŠ«î ü¿ñó[¾íðïÿ×߃TŽã»_#Ö×=“I·÷G°ƒ£)K¤k¡m‚Jâß•@[/× ÃPñUßv‡w'\Ÿí³„å¦D Ál”ÑÔ5—>ò±W˜ÍÇ´MƒõŒ„ÿ!‚ÿË? ãÀgO4’¿$çÿF‹+«~´Ð´=Au_“¤ AZìË?ÒÚ§Há(Š1·_:%ˆ">û3©:A2-PyˆU á%"Pω¤ÀZM $gW ŽŽfе=é$¥- ÂC$£˜‘€¯»÷/pQÿ,òïývâTrçôˆËÝ[„£9Ý¢cy6ájÛ0Jññ÷œŸ}k`~x@JŽOØ­6{Q޾§«Âd¯<*2Ò4ÂÆz²,ch5»º!ÎRÄhBâ=mÝ`œ%1Q¼oN'6Û-««5Y‘Æ‚p¿C ƒy¦èª]Eš§Ü>-xᤧª4o?ù IÇ!δÚbUˆQ˜劸3tÆ …$É"vç%B‚RQ–ašž~íÑ[Åí÷ŸR·šÝ¦£­[N_<"K#.®–Œ¦)Y‘Q7 ×+â$ÂawþOÄaðà׋Ïà+(I"þSÓïgÓa"…"ŠCª]D¥Ù(¥wZC ŽOÆÜ»}Šo®ƒ’éÝ1A$ÉÒ„õz… '3ž®«yüà1RJÆ“)Å8£,+4§ú%? ™Ý1Æ2›œð?î/²ü‡Êq¾À®Þ€´è»†Åý=Ï}4›“)ã¹ä›>~ƒ™Po¶œ¿ýïxPRíÕ‡½'Í÷3s ƒ%Ërâ ‚T²ë{&($ž¾í)F9qû}õzÃ(ËèõÞþKâúg-Cïè­£Umzò,¦Ú58¹à/ïùûUgQRð™ý$ËLà‹Jk¬÷x¯HeA\düðgÿ4Ÿ~òÌÆ§\­Ï cKXgÇG0To="±ƒGÄ“,c·kЃG¦1aÓkC’ä(ï©woÿÌ‚p®¸ûá[<üì5* ±½f½Þ§)£dOŠJâ„Ó“#Ö›-aEá*¼ÿuRÊ_ñz¿±ì¾¸<! Á~ž_7ÉBv»’$™ÎFtÝ@‘(ŒÖ06Wí^K¯m¹}{Îá4cè>ÿòô+´í‰ÃhÝqx:åÁåcâ0À˽å¶LŽæŒŠ”¶˜ŸL+Ϻ-)KÀá|‚ïB6õcâ0£H'ôC‹µà…g6=`-’$¡Z&øÂpµỹ„·ß»åc¿ö.'·; GU5œ/+‚$áôæ1aSnK„Tt]Ïá᜼H~m]5ïÿ‡Ÿ|ó J}Åæÿ³Xø/⹿ÿþöãËÿ稡ûɨ ÓŽ×ßxŒwû•Öaöê7Q¢¯‘Œæ#Šéˆ7>uƃwÖlÛ¯ÓqÆfµ%CÚË =8!™̰v ËRœu´M¡dè5dV¨Pà€¶jç9¡LˆUJS5xY”‡‚Ë󖪩ˆâŒþzB”\qÿÑ#ÊMM‘rvíéÅyX× ˆ€jWá­c>™¡‡ž<•d:-Î"…à 8  B…lÖ;â0¤ê„Ôí…`2ž’ ]×RëX*Úï B­ştßáŒaw ¶ H3VÝ–³Ÿý9œ1uchLa6ž«œ,b¬c6š’%9«ík5qªˆ³”Ëó+²‡5Õ¦#Š4Ëéúž@ÅÔeËôpʰ¶ØÒ!%‰"ʪE zºJ³~hY¼¹äèvÂúbÅÐ’P ÆQu=?» =Üþ؈£;)«Åvï5GèÁ"¤B8IœE´U‡sŽÕrÇÁtôOGñwò•™ÿÏ(¥ÞûÜ÷ûÔwÎK%¿q»-÷I’¼úÚíý|8ÑΰZïÉfÝ0žÇ¼ïÕ[œœ°^v,’3 Hi‘¦1‹Ç}ßÑï:˜+Ún`T$ÔuG„ÌÆ<¼ÿ„( ;‹Žr=àÏàð^„ˆ ëkº®!+r†VïéÃ2bùt ë;Fã‚ÒGlÞ¸"¹3¦éi")²žÓƒŒ‹u º#” ð8!)Æ#Žæ3¶ë ]Uå®f2›$ÎhÂ0@ 8<ÓKßiú®!NBò8@ÅÚ˜ýRN["œ!Ÿä b¥ñ2àå@¸)cš¾F<~mYv–²éM t?Ã.`è-i<"ŒuÙ UHŒ¤é’aÑ·‡'#NnTëžv90›NðÞ£­C"pƒÃö!,ƒ•8ãñx†ÆÅÞWr4.h«–òr`”„/)Ly\PÖ{•#Yï*‡Çº~@’PøïðÞŸ8ï/ýó à‹÷ê‹Ä/€¯ûº÷ý‰ÁŒ5Œ&#²8¦ëŒ÷´MM‡L'I3›¹qû€›ó½¬÷úaCž†p”£ „„ºØí¯¾oB1JØm$‹MÇÐ÷J±YïC'iª†\LÚO—Tw¿Z!eÄà{â$ÂzK½i… ý2Ä‹±%‹mÉ(a”%$(šªÃÚ%£,`µÎCàÞ8l«¹Æ`Iš¥„R1 =Å|¦nIÓ½“-qDD$yÆåÓKL7žQPW%a¤0ÖÑv‚²(Éä0$RªmO’8ì°Aáh;MXb÷!ɨ€ö¯ãB²!«‹ŽåYË|^ "‰JbÚ²Æo<¾w«xûçJ”¼öU'œÜÌYG5£Ñˆ4‘2`µÚ"”Zn~hÆv3ðèaÃÁaŠÖšÑH0›æx¹7a)·-¾‡ ñ­)óÉœw>³ í,Ù8§ÞÖxçQR‚ð¬êª&vŠÚø?þÂñô_úJÜ|+€/ÎëJ‰zôèâ·H¡P¡d³­å žb”`cוÌfcúNsç•ܹyL³ny²^pùx…3Àxš¢„Ä M#xóó ¼°ŒÒ+«ŠÕÐPÛýib´CIÁ™ŒÆÞxj­™&ŠP(Ê+ÏåÖ$Õéi"Çh¤¨w–@ ÂXòø³-iØq#sh’gSÊeE%$¸yók6¤²§öSÝ!UÀ$ ÷†›$š«ªÆ£ö›8tZÐ ¥$Çó ›ÅšÁ:¶»Š§sìÐ2¸éÓ}¥ ‰4Îq±Ø5†£YÇd²«%ËÝ#nÝfñø =(jcÉ’‚nh¹{£åÏêªãêu…ú@ÉØMúmýnÀZO>‰xò… ¸ 쵌±{Z¶ß?#ãq†&ܾsÊÐíH3G$ó¯~pŠ’ºêˆ£ˆñ(cµªXݯ9¸qÈh"LK]õ8'pŒ¶Üž2XËjQ’E!Y³m†ßâ_â+üìæ“÷¾÷¿ÿóÛ`œcµØ€ƒºÈÀz"ËSŒµ”ÛŽ(QœÞ™±ÙTÄIÀîaËêrÇhœZ‰î5×ë’Ý®¤m ëÕ†ôK^x1¢×Ýþ? R2ÉF ZSU I¢„qÈõ¶áø…ˆí#ÍâíÓW8 uŽÝeC6)X>0Ø>AÅ âI>eQu± ;ˆã £A qÖ°ësâp¯Ýo…"ÂRDŠD:éÑbßÌ´£x¯ixƒE3J"¬+X­wœÎs" „' m× ‹ŠBš®gÕí£ÛUè¾àru‰v† Œ¨/+¶ÚÒiKšç¸Á䆦_3´ÐžMˆ?â¸~´AFaÐw* v‚Å;ŽÉ‘Á‡‹Ë½ p\yé!̰Öe13à J1˜~°Û`ƒ "VÛ’#J"¶‹kÁŽñ¬ JÚÞpþ…E”ryY'Ýn@(@:Þx㌺ÑtU6šað,®·<ºX@nyñ£Sò‰ÀkÅÅÃ5ÃÐS•=“INܹ{Âxœ±\–8ñöý‹ûÖ½öàŸÀ-¬}o‰@{vy¬õj¹*)& X§EF4mK«{@‘M3nÜš£´€\ðΧ/ùÙŸ¸sžfˆ‰Ö-IÑt%$qâÛÛ;LíèQHL=Ê  †¾Ñ f< é¬Â'‚ñ\ñö:.^k9|) Zvtæäöˆû?Srvàh6ar´ev±XTûí»êТÃÁéˆÁ B¡èšÃ9¦3ôÝ@ 6 ¡ë¨Ûžp2&N#¬uTUK’Z¶å€ÕšÉlFKvƒa½ÝÁ8¢)«ðﶋ(BG$FDY„£d€!"Œª%%KçàcߘóðžÍù’Ïþ㫾#Á¶¶v„IHµîyëj¬´¨¢§\ƒòQL^ =ÝYO·ÓÔÚ“$Ž®ëÑæ]óVZÖ«ƒñtmOxë‰Ã€¶ÖøN¸„Yž2º«±cqYR×O¯8:§ÓY†ó޼8æÑý§óÎxÏ¥ÿ B€gâø½ç!¾÷ÕWïð~òsxï‰$ Và„%ˆf³)Æh’4b2¹}*ŸÄÄqÈì8àðtă7¯ˆ„du~ÅÐô„‘b<ÏO3¦“‚¾›s|tø¯‚ÿ¾çW€/bô}ÿÞÿ^)%£IŽ@Ñö-óiBÝ[ã0ºÙ·îÓlG§ÇˆA †Çܹ•£;’4¦³"&Ž#F³ŠCËÓG[t? hKQ(B2¹U°ºØ’ä{yìÍ¦Æ ÏÁQŽ“*r¼ð±ˆÍ·¼ó޳¬E(A_U8¿¯†æ7JŽn&4²®jÂZ­å^4ˆn½ôã>fSIæó*Êhv5åz‡{AͺnAxÆãœ£Ù„nÐÄaÀn]áuÇb±D8K%X i¢$ §¤³ —×kÊ] yIßjŠô€aÐlÊŽx2Åv–Þ‡Ôá"â8B%̺$;^ühÇëoî?›'ŸoX<ì‘ úÖc ¼ò‘1¯|MA¹®éì€ôm Íf/¼Š¸~PR– 0ØÞpã8'ˆº¸!'xº¦Eª'ï£GÌ£/¬xù«Op=´=äÓ©»]Ã$‰¤c·kq¶«g GÇs¼ðß»Zo¿¯ –²<{1NcŽŽ'\_•qú®™fD]uX»7Ý4õÀn3Åî"•<üôšëó–Ó—N98Ó65 °R ”bq±¡[ötÃÀn×!…¥×–ÞHæ)CgÐ=ŒÆ)W—%é8C D€7 "¨¶†[ïOhÖŽw>]Ò5¿ø—O2ɇ~Åã I¨pRqÕõœŸ¯P“ñÑ1ù4ǘj€Ç`ÚNqy¶fÐׄ*$ #Ö‹KÂw B¥„®HÓ˜¾×¤iH×ܺ}Ìü†g½Ú€¸ºX2 %ñ"òÝtèÞ‘F9¤YÌj]Ñ×±\Ute϶iÁ+œõÜxñˆí²$¨ë–âTðò‡ ÞþL@×üãÑO>ÖÜ|ÿ¾ZˆòÙ4@÷=¾5È `½^Q^Zêaè7nŽÑƒ¥ï ÝP3™ÆìÊŽ~¨©ë”l–5Wg[NoΘžÎÉҔˋkÆYAßèïöø¿ø•Bxæ@7õ{Ùüc±í¾ez0â¸(Ðf`½Úrt:áóŸ{ˆ@ÑT5i‘徃$ hås?ý««–Û÷89“¤1KúÞ¦1‡G‹ÅŽé4ï8}!dyÝ Ißi¢@ÐwŠbᤠûí{ç°Úrõdý÷Çm5P¯[&‡9O—!Ù¬+ÈBŽîðè O CV2›)Â[„³ŒG1Q IDH€C¤1;ã9˜Nèjƒ“‚ÑxDß[úÖ¢‚ŒÁí»ùxåæ¡ʲ¢iöž|D!]§‘*£ÙB’x²l‚í£$£é–+‡–!©È)¯;6KMo#ŽNo!e@V„䓜Õu̓7HÒé…\Ÿ?%ŒB²IJSõ8#(Šœ,ß¿¯CíX¯+d ½bqÖÒ7IâX0™ŽˆÂ„í®a»Û2Ÿ%t]O>Îñƨý‚WÆDŠQÌéé^ 6—áܱºÜ19p¼üU·xó ;¬0Šxôàš£Ó 'Ç3æv@{*ü–ñ8Æû¯ŒYÀ³ç ø!«Ø—/¤œ^/9½yˆë=aÑvóYÁÕåàø8gvZ°9oñ RS0, Ÿ®1^ÓM $a¨PJ²Zî8?Ó8ï4„À9ÕŽ@ŠýV^Ñ7†¦1ĉ„µcr3£z²8ï)7 ëë BÛÆ£ %#æ‡sΞ.QyLÇÔËŠ¸9}õ&fÕe••ˆ¶# câ$BAš%ÄÁ»üýNaMÀb9ìïµ#¢$!ì®×¤yJšeÔÛŠí¶f %"²Dkˆc R’ÝÈÙìV›’¦6ï8žÎÀ[dsx:¦˜ôU˶± Â@Ç7oá…aÐ=×—kŒ³NÇ8/¨»~7Ð6]§q¶'Ž#ìг®w¤yÎ(ψ˜Ì=isù™õÎ U@ =IÓÖ¥Ó ÝÀ­Û36Û’,KéËn¿Ë¥lÝ@ßkêRszcJ\DT»ž·>wÆíNP>Ät 'wNøôÏ^ŠzWá¼çêlÍÑñ”ñdÊÃÇ—Œ&SçÜ ÞóäyðEˆã»7Þù…àëý“‹t¹­yý yÿîàœ& ´ÍÀj[sç•)EVP»'4O®˜Œ&œœ6ïÀ ª¶%Œ”hçÉ“k )Ž"¨¶k…ðmºa@” Ú4¤6aå *ÚûÈ0dОÕuÅWÐCÍòrK6Ž89r}.h«–p” Ù ¦7Gl·Ž¾sM)" BÚjà`V "EÕ x•ä1'‡#ãñHÊUE×hÒ$Á–NÅœÜ:áø†@÷†õbÍh~ÈhWçW$‰ÄõG b† é aèQJÓÇx–Ñ–-›Eæò´5¤YÎtV ¥¤×’réèê£é˜z[stë‡,]’¦ƒ6¤IÄÐ ©ˆ¢Px—+†ÁgõyÏò² e»ñ«…ä¯Á—½`à3ÿÅïûÉ÷ìµ¾û_}ÿ½›wr¦£Me¹ÿàŠÛ·OR¤¬VnÜ=`±(‰ëœéÉ¿v,_q½.™G9q¡œÁ{GÝ Äq„÷£xOrÖÓÆŠª­ñVÑkKEhcÈò”¾5Læ1º1XÅi@ßj¤qH]¤Eˆ@"•D÷–ÃÓ1›eK”€•!Ú8êeÍñé!—KFiŒ—’{ï{("%¹¾Xcv’7Ï׌'¼ ©Ê–ÉdDß$QÄDaŠí eo[ö®ßA+4Ú[¦‡⃄ÅbÇéé ÖvÛ’Ïn£1ÃÍÇ(+ˆE€ 2œPDIJÌodxP•–ÕbMID˜à\±™–-}70 †ÃÃ9ÞÃfYâ{ Ô^´dðÞ“äWowt•¤Õ!4Ù( x—ŽÆ Ö:šª&„L§ £$äÓO{ûf×1?¼I:ºm˽ó3?uNF{aÔƒY°¸Ø’ä1¯ÿÜÕ½¿÷—½gÏéöû¾tù&ù %ì= ÄQLxB!(ËŽÑ|„”’4‹yéÕ#NNi+KÀ(àz˜Ís”Thc±Ö‘HA*%ÆZã¸Ú¶t½år;°©zšÎP qì»×f@kC8Œö\_Öûj¡´ôK‹ž¶íñBÐÔ=¦÷$I@ßi¬õ¬.¶Lf)Úx†Îâ½$ "Î\!‘ˆ8 Œ$×O—ìÎW¼þ“ï`[ƒ’¦q,/K–Ë ”¢i¶Õ€ !×Ë£ºÎr~¾E÷‚(I™N&ɘ§o>áâÁã8Bz Šñ^£ .r&šÊpùpEÙ8´Ü'm^ÄÌsÜàhšž²ìÙ\oHÂ,$IÌñË·¸z²¦);²JV0\zL/èK”„ä™@‰ýÎ IšÄ)CG[wÜ}å&à©wFHŒÁÉé„ã1Ã`Ùlj¶›š@ÀÁ¼ É .Ï7ŒòTì¯k“·_r|îçÎ!Š0ÃÀìà˜Goq0‘&‹'u*ÕóÀ{Û§ÿûyï6¿¹¶3ĤEÊä`Âõå’›ÇcÖ­ãêbÇ¿nÂv;pÖqv^²x}Gìhªªc6/˜LR„ðtÖÑ9wš$qNbzM÷®P„”Š"l"‰"œwhmªc:Ÿ°\”è­e:MÐÚ¥CŒ=D œ¤Z÷Dy@’(g|”Ðì4»]…1–Q‘ru½Ã I¿)ÑÖáš8Ê0$%ß)}ÛžÑ,£mºË)$(Á(K âˆjW3›g,®W{Àê[:ÝÆî?f¯ˆë1Ö•õn¯œEÚXÂHÅ‚åyƒ áXp½\ãô@9š¦¢ijŠã ]¥é;Ín[3=ÇWO·¤QÀ =ž~Ð ‹¿hʽbq âÐ2ÊCšf!°@Yu¼x÷„Ýæ’bZ0hK"<Æí×°·Û–4 ˜Ïs¬íÐNP×`I¦c®–õSˆcA"C’$±—IÏbÅ ºVÓ6I¶'&;ÌÞúÜõ7KÉ_ùr— ~ö*€>*Èò˜ÞHºõÀäp„c/Ô¹YnQaˆÖ–Íf‡u§=óÙ¯ö÷¤åƒ3F“œ¶­qºº!JÆzú®Gˆ}?¢®;êªA ^ A A…NÑz`ÝvÄQÂæéŠ]µ&Q p´MCÅ Oî/pNHI ‹‹o=]oу! W÷{º­Æ9ASõdy„ó–m«÷Þ! hÛŠ(‰HÖË’T 4žapD¡äÖ ‡Lfx¨75uÛ†’éáí—×[¦.  Rm[âX1™¥”Ûí@= hci»ž´È2B2µ×šxïaôÃðžô¼óï?-RÙe«ù§ó¡Ýcr2¡]×äRã1$Y5t£Ùí:¶Ë†Ù<&Ëc¢@0›g¸8Û Œf:ЉBÁuÙ¢X+yëÍkB '1M¯ñrOgbE‘Dhëè{M(„´!Ë%Þ;¼˜µÃ䎨{ÿÁ<¢Zvd“ã=£iBßÒQŠ5£ƒŒd~«À÷ŽnëÑF³]•TU…£qF”FH%iª–¡ë©v%"EÊÐÚ®§\í˜ÎÆk¢€¡ðÆSÌ di.iO”Æ Côž¡ï±®g·‘ÈPÒÔ-ç›KV«šÉL’Œ¡*ëý ž§œ?ZaÃy¹×|²&Ë’pOœriÀ08š¸N"ÅÞ9(Œ-i QbŒÇY»`±Ž££9ÆVLg9ÂyîÜ;äÁ§á…$Š£"ãødŒ{wÙk¹*±ýÀ¬Ȧ#=Ý+OªBŒ6l7£bÌ»–c½HBˆ£€¶êPJÐuÂñ¤¸+•x>|¯Ckýž€sþ$Næ„Á³ï_IœÆ„* |Ò ‰”ž¶i1fÀyO†dYHÛï©ÕÞ;´ÖTeK»+±mˆÓ*ÐÆ¾; Ø‘Çé­CªMÄaƒ—%$ÛKÃÕÃŽ41VÒuÓùžÄã½' *ŒÙÖ a˜2›gœŸ¯hš€ãÃͦf0àeH îÜ9$J"toYmÊUÃ4—Ü~鈫mÏf¹c–†4«˜%ÐÕšÑ$¦·†É8åò¢$Ž#m‰¢€4KöÍSë^sð¼x¯# £÷äuœE×MC£a ˆ‚ñ,Ã{ÇújJ£E·H²˜®íX\Ô ¡ô`zò×çóþ¼—Àý—Ϲ½9cþEiPRòìþVPÚìÚã‚dµÊ”ßÑGŽ>Ñ…'1\œ/9()ñÎsÿÑ où}|8ç¸8oØl¦Ñ±Ûõ¼ÿÎ2î?:ã¶ó<~|Ãù¦¤H°ï) æ9¢uIŒ°=ô˜EÁöÍ[ÀÑnZÔ`pΡ´f¿?NR}ûLJË€oVE•q8:li9\íX.[ŠRp8ôÜ^ùáy•ÍiË×Þ¾eû´Ç®Tf~y8ô‹Óš‹ûkú~æÙ³ xøpŸBF¿%,¤$Ìþ®Í÷ŒãŒÔÝ‘F3Çb]a­$˜FÏ¡ÛáæSH¼‡ˆGHT æ˜1†ZÐg¤Q$ !"¤¤fŒRí¨kÃþÒQ––è#>¤h4R ¢—$¶ª(l¶2‡‰ó”J`¤fN ‘UÕîÚkRÄÝö€2S7áµ¢, ÃÃ8¢ï”ÕøúÎwØ¢da–ô;GµÖزÀ–›ë]6÷T†‡/]°ÛõŒýÄí“‘y«¾ŽîÎÓ֊ͪ&…ì¸?ô¸ÇÉÙ7Ï„8!„äÅ—/ˆ!|àú0ñòËg%xùµ ’|ðæ3ºc Ú€Gˆôû‰ÍiÃpô¨F!”fœ=/â1E–«†ãîÀrSÓ{ʪêùðÍ?ÑûoÊß“"he˜"ÔuMÓV(cøèKfxñ•sºÃ„’0§Ì)?L)8 Þ»äá+²»íPRó›_úåªAÁælÁ_rž‚–‘~žñ^r¶)I20L#¥VÄyF˜|âô|AY®/;ª6²\Ul6ïÿæ‡{Çê¤æ•Wω11Ž'oÙíf>lyøÂ)ûýÈz]£TÏq ÝÇ[ÏêB1zϪ¨xx¾¦ßx'øà§|ø^‚¦)ÐF¡”@>¿ù'iýM+I+nï)ë’óK¤€¦-Ð6bº9Â,XžÔèVñxÚBJøÝ8\8}tJ½,™œçòÙž¡Ÿ99©"7F¦ã„- Á«¯nÆ)3ýÆ‘›«bÂùÀbÙ L¢nKÂìI1R•]71N©F)TÌO…’”g!%Óì( ƒ59o PL׳0Te‰R™áÖrªsŽÊ*†Þ3Ïu]‚„)2ø çU°uj "IúnF*ÁÔ{” Ä౺@¢˜|Oïrè‰Q–8K”´ufõ }`§Ì¦|ISšúÞ†qÌHÿqÛã'G×E®ßvL׎²6DÁRj¨[ÃþèèÇÀ$ó4£ Kè$ÉõÕ@³Ò´…àþ 't×GúcÀ ŧ^»‡T‚Ã~äí·Ÿq{Ó±^ÜùÍ7£­á…N!±ÝLÓÌöº'`9ŒžgK.î­)ŒÆí;®/\>ÝrþðŒº¶¤U]2Œ—(-ŸßìãÅ7©è§ÈbUsv¾f<ôÜ\íæÈ§àB –«‚gÁáBà¤mhå_!¥bi=÷ï¯ÐRrùìÈ4Í,WM›÷ü‹Ö’B%¨ ËØ;†>òô£+𢤰’ÅºÂØÌUÞsÜv9gÏH’€©O›gJ[æÙ1ï@ÏæÕšnï)kƒÑ<åÒ` ËtÓ‘„d·H"¼'ø@]5 D¶:…±ŒÎ1v#Á$бËÃ0e~üÍzQAŒ´‹%U¹`Ó0#µB" Ÿ<ýÝqÓͼðê9F$†Ñ“|bFöûžª¶TÆ0Ï lN*Ö§5ZÂþfd<ÎÄó@iêÆRÖÙ@*‰”ÙC™Ç !—oÜ<¹÷Ê’b C7q¼žqÉ¡ª@¹Žô;ƒÀE‡®5 Á<ÎÄÞ±l ŒÐTúnÆ(Á<ð¡ »}ó°<ÕÓ0à†ÄQNÌ)±>‰øÙQVUeA(‚Ÿ±Ò¢¤Û™y8:Î^¨Ð«™²Ò´ËŠª>evާïßò콉goð“Ä6†iö f—žˆÜ]Ô•&ÊÄ<ÌH¡˜ƒ§*Jæa"%¨†³{ †mGß;ö½ãáKkšª`‘Œ‘l¯R*–Ë’ÕòûÝ‘àÕW/&Ïq?r}³ç°9†‰Õ'ôÇÛe7¦×>ù7úí Ͳ%‘f$”eŸcß\@øæü@cà ²¨Ò½+áƒg½©1Ú0Ízu"ˆ!p²©¹¾Ý£´çúéœr›‚î83ˈ0‰4*£)‚§¨ ›å‚c7Ò´šcï˜g‡›¶²œn Æ™C?3ôžý~­¨JCQÈÌ@”9¹¡rr)9l4¥ˆ)A&”2ŒãŒ>Þûõ+–ç-ƒ) ‘•p&Q4Šb©˜ŽžíÓÄt •71xvóÄ<H+:±¸¿DŒðè•SP‚óW["0Ï3uSp¸íY®—\xàöÙ‘ùØ»Èáv ßßmA”`µh N t Š#¯×ÔKMÙHδŒ½cuZ2wš·ÏÞ݃D çÑ%bŠRöZ`L¦û2ן¼"”Æ6†ÍÉ‚‹sÃõÕézËn,—5ž1ÏŽàò¦àØyž>»A]+la8?ÛPÚ’Ù9¬5eÁɦåìlÉÍÍDDIÃý—îáåŽ×^9§iÜ>ÝgÃQ‘B°Ûí 12þóÏ·ÿÎý—ÎþÉ_ÿ1¤ùô¾ iŒÜÞprâpœ0÷wyðÙ‰&øHÝÜ\_ÑO3ue!ÂèÞeVßzQq{ÓQö!…A$hÈõ#°¨Ú'ãÐÍh«é{) ¶4T•¡(4 p£Ëë?ˆQ@ŒÄ˜©TžåI„Ù!X«zG;S€%©Dˆá,~©dâäÓKª¶bìÂÍŽå¦ÆV [j„LŒ£gõ¨aêfo¸èèªÄwnŒ\?9 5aJ¼ðjMÙhʦ$„€²’"ËUÉãwo8<žxëW¯¹}21)1Š$ÆØ»tÇ‘)Ò4ÆD®O³´,š )Ef8Ni{ÍÍ1J&4¶•|＀цÇÝpØ—²)i[£ìûl£þ1¡!(Š£%m LÊÚðàÞ)SœYŸ®˜}@vó|{ Ŭë>áR¢ÖcnÊl=íR¾w@Z¢ÀÍ”EkPI2 ßet¿´ ÂLU(Ö–´›ša©ÎkÚZ¡ UV²¸·ÄÊHlm©W Æa¢=«{-nplNK7mU HÄ¥¢YX”*˜Æ‘ïù=k–ë‚èàæê@Š1”ºDIÊÊòî¯lùÍŸÙsýQOß{º~BUU2¸áA …±Š9&ùÒŽƒ¦© V…"wx/èÆ‘¡ 8Ι¨„Ö|Ï'R”%Ýaàæêˆ€€E[qr¶@ÊĉËb¯c—£Ñ$‚‡Ý}’bœ=ÛÑÒjî?:åöú€Ö[\¾ùŒþ0Ò4%ÚhJ«]Ù˜gÚæUà·sð-W~òÇÞý¦ü=¿û<|;¸ÐÏó´´¦àxµG• ×{NÎÏÐVÒïf¼Tuös FÇbÓìoLÎcf&Œ()q."´$È„s ò¥* Mò‰„@êȧ>uŠ.óèi–šà2SÎT‚"eÚ®›"B(|ÊŠ;­£Tw(ó0N”¥ÅÍ3 Íà&в`r!zH"ðð“+d%(ZA±(‘L­P Î^\Òž–\^ïyðRÃð̳}›yï7޼óågŒ[èn<Û§{‚ ƒCQ‚(ÒlÒøÙ…~(%1Ú°\fJöõ­)‰)‘Æ@H‰ÉÁÅ£^¨)mÎ3hÚŠº)¸¹Ü2 žª.ˆ!bËË/Ýc³ˆgÑûŽ““–‡Õ=’ÈãÎÍõ…aè'¶‡-—OJÖ-—ϲTùÉÍžÃabž<'§knw[JY°ÛOS»¨Þþ©{Ÿo÷#¾Õ⎿™ÄŠüýÍDåÀê„9ððÕ^{ýYF·#r¬Ù>8°ä«_xÊ»_¸¡Y—¤èA ¶×Gvû‘º6X£˜& !‡MVšD޳²F¡­Äž—_Û`u–æŽ#R$†>ñìéHYi”̃cðžyöˆ'îÈ4adVÞIˆ.Q–†~˜¨«"ó¼Çhdž”=ñë¦@ÁêAÉ«?¸¡j5ÇÛ™yvø10 šÝ³žqï2)é˜ ‰fliØíG„•ï8ªÐ¬Vek0•fftaúž¦mØ>;⇀‘išQI0Žä,+‹RŠ¡wžSËeÅ4{Bð™‡àC~´¦©+Ü臉{W,Wšýn ( hª’ý®çåWOX¬²;P]—ì÷#‡cÇõMG˜EQÐ÷óbŸ(¬¥n HÙ¯±n+ª²À–ÙFlê&вäÉ“kêÖ²~XPŸ .>YqÜ\~tšî˜*á} ^¤É¾ýgþèß4W –wð;8L“ú•Uc~`èý8R—5OÞß¡%Ü{qMYö‡‘A)ɽûÞøüâ.°\Tœœ7F³Ý?!D¨ª‚¬Ú–¶.ò\š`š¶Ð´mÁýóIç2ΑõIMßOØè©«‚¡9ïdÅ2!„@IE ž#B £€D`TòHIVë) Bá½GM -»ÝˆV‚©O|ôÕ=ã¨JƒLg´YW–à²ùHµ¨ˆ1¡JÃè듆irÌóŒÑš©ólÝ„ÚyðnœY´É>nJÒ&””eÉñ0Rµ1Ål6z—T$¤è ‰,RJJK¢(%˜üÄì<>D„€ª²)R£´dš'¤ÒÄ83M‘à(M?ÎLcdB¶VÛpSÀ¹™¦iÇ88ÆiÆÔ†i!²Z­8¿XÓ?¾†›‹†º*yéÕºtÈ$(_ÊÑqã´CiMÕ–TµäfïßûN¹%ß±à‡ÿ@Ë4Ä¿ŸÿµÚÆArÜ÷´›†ËË.̼ðÊ)§÷ºôÃÈfÚ¶b˜fçNÏWüŽe‰±bäØ TU^ù­7'X«PFsØñ.¯;úÎQÖ’ÍiÍíå‘Óû+dêé»-»ýŒÑ‚²ÌŒ>¥.x´‘D@ÄÄ<:„VD0eÊ]L S@ש*eÀS+“51# ýpWдDQÚà¢GÛ„P)%)RŠ$Z bRÌÎQÕEÖ ô#ÒšÖâcŒ™üä½ÃZiæq¹[›Æ‰ù[Ñ{„ʤ¦i0Ò0NŽÕ² xEL‰¶¬év}6\Õš¡¨ª%WW[„˜99Yã'DÁ8Ö›‚²²ˆ˜¨*ËözGwttÝLŒpì:´ÖÔ¥b ç UĘ»Œc7`MÈEµ°ìOŸÞ°X4 ‡ž)uÜ·Âòèõ ÝmÏrÑ0!ÂbQg5¢JØRýÊwÌ3ù<¼þ9ýèSŸ]}UHY{Ÿ¸¾íÐUEòžŸhiV5•)O[¨q–ü¿ðw4ßÈÙÉ‚º1L!RYMUZvû#1æ  ! „Èõõžãѱßwh%Y­n¯Žüîßû7—{BŠ4Ë’áàùµ_~FÛ(f²Å—ͤ’qˆ„ !G‰­P*wC?aK…RšJÿZ³ÐúÇþO_~>|+©Ä‡=žoOO©÷»‘³³%»mGR†y ý-Oq ì#BiªuÁp˜BácÄ–†0ÎÛ]¶ŠRkæÙóôrÇõ“=1&.î-ùÔë÷ˆ)pÇaäýw/éûàtYSŠD]kRJ\]î)ÑÖ5¥1Ä:S°ËE…ªa·8n<¼8¥Úh¼s ϪUŒ‡–Í É)RHÜ?[ñÆo>¡mkú~`žÖšápÝýä_ú¿ú|øV?fÝaøs_»ø7^}tγ·/)”á0ŽhÓbdA·ñ£ceWœž-Ùœo¹z²ãìbM?9º.óƧÙc‹l/Ý÷žÞ¿á°;rqºàþ£.Dž>9p<ŽœÝ_Ð4–qòì·»ýÄéy‹-$§5ÝÑÓ¶) zˆÞ]”ArXÄÌ‚²ÈöZUº³,Öj†nÊ­ûENäí·4„HŠ’à2°i Ð ™ãä &$ edfâµÑG\ˆX[à|Èb'á¥Æš@ÓHL)p=L·«4~š)¬!•7;\tX“SÖ”…Ň”éº ‚ ï︡ Ûí[F6§K^-ï¿{KJ›syëÍÇ(¥YÔëRS–𾏾ÞÐ4-Ã<‘ddu~Š‘ÇmyÿÝÛL.ª-Âh~óÝkŠRSU†ÓÓ–Íé õ ´Uœ¬[nŸíó…'Q,[ºÃ‘'Ÿ¢|s¥­üè9ðmp¾ô7/ü6ùã×W‡#II±j˜ºë%0 ԂŦÀ]"‘¢U(!éöê¦`±hÇçÔûÁû·|ðî5e÷ÏZVg ~´Íõãœ÷ë…æàý0sÿÁ%;úýˆ5‰W^_ñå/\1svÂ!ÑT$Í~ïÑu^ Úh¼ÏI¸)¥ ”IOY—­i¬¡ëF”ùò™J¤ Ü(Rˆxç0Ú ŠÂD‘Zrûì@ÝVøäIT!ð"¡ª¬GXŸ–LnfÙP€ÒøÙÑ”.Àñ=±­Æ\)¶7åiÅj½àìbÃ{?w`·ß£›DÑX¢¬7Ë÷-rºÌ;o=eè&^~¸¤^x!ùè£]?PZMÓT™'OUem¾‘yE'U¤¬Û¥ÐFBxçéÇ€Ò->æBˆ„6’àÉ"œÂ ´fš1¢’< ~ È(± …‹3b”H‘wé1€,åÊää¡n¢^(R“„cS—ÙÁØô¬&ÐD…4‘•. > ¬fž"Ji¦D¥‘H%@¾Ã)RJ¤à B£“g½®gÇ<ÌL)ƒ”³Ÿ!)¤I„1'õýDUZêÚrsÛqz^ó=ŸÙðþ»7¼÷á-/¾ü€ÓÓ>z|I˜1õ,Úšf½àôÑ··{_yûÍH1r¾Y€ò´UA?N8±Z³Y¯qó ³âÅà=O®>à0k.NOJry³Ç'( MÛ”tÝ ýðç¾£Æäïôp¼”ÚüicUV“ ‰÷‘g—É'Îî-™ç¬çæi‡ÒšõYHm$Æ./¼÷öÂG^~¸äüášÃ0ssydž&šÊbÌ!0ös–ŸçpLO`sZž²Ñ,ךã~È4_IfúÅD‘áœó“Ç{‡5„À– ç\Fíc ®K¤©$B k)šU ŠÒ „$‘‹FiRˆ$pãHQhœË6æËEÃØÏtû? k02'ÇwÿÌÃDôŽè<"ºã‘$ËUK¹´D R¬±Y)'EvO™×™K 4¦Ð$‘GœÙ„y¦, taúÎTdv$7p{yËv‚—^<áÓŸ8á°Ûq~Ñðê+÷¶b;&º1°8ÙpólËÛ_}Ê͓µš"fO„qö4uCˆ‘«ÛóüÚð£EeijËG_{L"‚1¬6 "Á0Ìœ¼Ô"ƒÀèDs¢¸wïk5o½ý”'ïßÐhÁ ׋–ï¹¹é˜ú‰B Ö¥"Ÿ Œ2L£çä´BÛÌbC$‚Ϧ’ÑEªFgpÎhli˜|ÄMH¶ÔT½#êÚ ¥À˜¼=0*; ŸQum4Rª ê ¨»­Üê £P…AJ…w‘Cß3Í.Ûq×k4eiQwWˆáëè½R¹™f”"o)LÊæiF‘ щ՚ºª0ÚÐ,šœ¤\Y|Ì4ëy#P¤””uÔä‘Èó¹’œm,—ï_CÓððÑŠ‡›’·Þ|‹fmøÜg_a±¨¹Ü÷ü½Ÿþ"ïüÆ´¥æÁÚpÒš¢`œgꪤ® º~ÀÍž¶®:“›N¶‘X—”2f³’~D)…¬JV«U¡¨—ûëù'¾ök;ž€oóõÝÊ›¿6þÆjµúÅý“[ê¶àÉõ‘å²bµjÙo;†aâàŒSÀ»Èùƒ%¨È›o]qólǦ5Ël‰xïéc?S×>z¦ybè'¢ˆTmAJ 79ʪd±n Á£KÅrUæþÐ1ô=Ý0ðÌafFŠÂ`¬AZ‰’Âj|ðôýL á\&ë̳EiY¯ Z •¼ÿöN—Üá„“Vç܃ÒñÿëüÀ¾J½¬ñJ³ßwt!2‡D’¶m‰1Ò{JkX-êª"…ˆ±š³GËSV'êEɪm)R•U–L“˜úié¯ÄùŽÛ”ñ]r>øâÍñóD [¬75ÇnâxII££<,Ú^ÞÐÇŽíã[œ6¼üÚ¦¤yãÇøÑ£C`]gó’$cŒÄ$Ø,E-©+CYj«ï n-¶È£GHéÎM(d_9R*ê&Ç\UÍ/)9y8†ÜÆK€)Ç“ËrÜ< IŠk,IFÊ6ófï2K¯0D)ïÂ@h‹š²4(©)«ó”H²…ºŸg¬ÖD—ÐÊ ‚$Þ*ÆhÜ43öÙî¬ë:°0Î#JKêÚb”À(•ÙcöCJäÕ\ðLÓD žª2TÖPV%)¦¯U­¨jƒÆž÷ߺD¶ §gKjo¿õ¡ß÷™|æÔìGÇå­ãj×!Æ.jT]Ñn6ÌÎsØèº>ok®8¹Xb Éú¼`¹n1)±»Ùòôj‹9ÿ`¹i)tóä‹gÿKÿpwù¼|{Œâ ûðç}bµ=òèå ʶ7}ï sÀT†Å}Cy|uÃÙÃ’—_X²¾XsuÛñÁW¸i TÆJ†)”aï·Ç-M™­·“”w„Mwì©kKŒ¡$Û›ç<§‚È4x¦y&Ä °ùàIÜùð•[hÊÒÜÙ¤;ª°!PRS—U™¥¸ý8\ÀÊì믌DXAUT­¦l5ÒF–gi#Ò:Ê…fu¿ ]iD(ׂՅåE¤ZIêCµ”­¢9-h6õ²™ÜLQ• JK¬5hkPV`­¢, Ú &7„”]×S–ª2h«22õÃ]ñ(Ùu37Çž¢’ ­kŒˆ¨èxçkOYÞ;åì¼FM#o|ñ}ŽÝ—_=å>ó…5Ì~âéíćOoÙï:ŒµHcXß¿@/–L.0ŽÕý’<¢ðø”ƒUúa¢*K„ÈëöØ$q^Ñ3£…dž<…dÖ]!I¬58?€’4Uƒžý¾CªµU- e#°­¤°–>9Œ„²V9ÞZX¤”µfw} © l)I)±² ·ÛRJ”Œ,lþ³ÆVMU (¥„w‚&ê¨RöWu[æHp3RJœÌÓŒ$ådŸafš3 wÚ|2_ëü}x0V +Ív4ZPÐJRZÉ1Ì<}zä¥ÏùT¼ûÞ _þÊû|òõ¾åÅï}{ Bßó_yçf^}mÃç~è5Ö«k4¶PŒ^ðáå·Þxã¦((/ ›ó–²–,6)²(Øu#ݨëŠyv”u…ŸÓ_Ø?‰O¿¡£üŽé¾ À×Yaf¼ù(üÁiž‡ï Á¡›¸½9¦{//¨Nk>xçŠúDðéÏl(E¤÷‰§»‘iö\, ¯u{–è÷­Õ¾FŽåZñôÃ=qi8}ÁI£hd¢ªRÁàãX—%ÂX”„²åö<Ü0qzÒà\¤m l‘A-k-Æ –ë’#«µ¡i%J–«’²U+1FbŒb±ª0FQU%Ó811’LÔMIQd™ÃBúnÌÌ=‘yJ€ÕšåI›UÈÌëžfQ ­Â¹™à#E©Gœ=ý¡g'¼t}Ow eå`ÕXÊ"«cŠôÝÀ0ÌÈR²Y×h•Ù‰í¢¢( 0ÖbŒEmZ$P«Ó’¢›h›-ïÖ liÐÚЊ‹Z°j4““<Ý;v½ãá¦âéã-s|ßg?:¾úòÑ“¤TÜÿÜööÀªÖœ?\Q,¼õ•¸~¼¥°Pœ+¢Òè$yíÓ ¼”gÒ¢4Ds4‹ M@zÏá8!µB+H>bïZíÓóÝÐs»="î^ÕãaÂM‘“M›Ûò2]Q*)¯ã$wž3Ñ'†~ÄÍŽÕzAe5Z Â솘<²Œ”e- ðï³§€1)ݡǔ†v]²Ú´L£ÏvÞÖ ­"¦À8ÏH ‹Ó[˜;uŸ`s¶¤, ‰1žæPИ=òSdèFŠ¥F—–v±Ì™…ÁSVmS2N¶4”…fÆìË ¨ˆ<â¤Øƒ˜©ë’ˆf»?Þ‘`˜f 'EÂ…Äí8Œžá°å·?À)…iZî­J?½ÅhIðž¦55²Þ,¹xÔòògλ¡{Fß}È“wÞãöêšÃÍ5¿ù•7ÙÝÜ…ÀÍÓûë‡[¾rwùÓwâ¥ø®ë€”RêöÇžýÛ‹Jñàá’ó—NÙÝv¼÷ö%§çKúÉ¡–‘vÛ÷÷X¯ÿЧ÷k¤Olcá„€Q‚g ¶-¨›ì²cÊlZiŒÅæÀn;qÿÁ)Ͳ@ÊÄa×SvíAÚuCYÙ<¦»QÁcË"ÏøÞ£ …Æ–š˜")DV‹aSšqnFë„©5@·;Ð#¦Ì ;I@*Ë–q!E´6µÁ¶šaèGGDQX…–àçH]Vøqäá¦DE8†D?ÎŽ3o¾ù!ßûÙ×aî‘Q²Ûu¥hš†#>ùC§ˆB²{ºçìEIU'ÂpýÈÕÕ‘> dÓrÝu‹†Ÿû³ýüNmý¿[ À®¿ _xóWºÿýÞyûÞ¿b#O>8à|¨DÕz”‰haxéõS¾ÿŸ¨$ÇÞ£¬Æˆ„@Jïñ€9ó~v3?¼ÆÍŠÈáÐ#eD%X­*¤„8»X3 #ÝîÈ8™˜æ‰DB¤Ìà[´ù’F`ìèûh›qÙ‘'æTœUU ôV€¼F3F3;1ŠqY_´t‡A$ºÀqßcvõ™ú ! ]4”ÖR–¥-P23C „à€Ä~wD™¹ u–Ç訪Ši( CÛ¶ô]@‚¸‹JÛVÄ(*‹6†¦*‘> ¨º¡Ÿ"E‘ RΦMc9m…˜²ÊkÅ ©ª‚ŪÁu|tÅÙù)Ú(»Ž{/µü ¿ï{Á"*ÅÖï•Ä®VìGxó½kÆ1qì'„Ž\}8þ‰~~ã^þçÀwPé_ úôdýëOžl³L¼óö5í Ýh}º%ø™ËÜ{uEý D‚ÓEAUŒÃIJ6 .ÒCQ[¼Ë@؃—/hÃ8;¦™Ì¾3:I0™É:!†€PÖk‹eÅ08æ)PšE“­±¦Ù¡ÌÁQ­,ÖH¼H+Ñ Ænên}¶Z·¹ãh,Ó4Q4Ó<’HŒãÌ8Î,Ö-Jfˬº)±¥ùúš2xO?vÄà2‹°©!Ð{RJ ÝÀáöÀG&çX,[¼ñ!›øibšfº¡#!hâ”wõ›;Õ%1 ¥ÀÇÄp˜xúìš}HS‰›Ý6“Z0#…¥ïúì‚Dâvß±:ßp²°l·×·;Ú²as¿¦:SÈ)m"µ=²†ë«žî8r}ÝÓwýØóâK¼þú+·Ÿÿó‡?ø»ö?~§^†ïÆ>þ¥º1|ô×þ“þàê´ j4IBÝn>º¡­ ”Ö4Šö¼@&ÉmyåŸ{Àâ¢BD§™Ñy°ª,Åè&¦~¦¸3í:Ǫ.h5Û›cVû¤DpŽÊj¼÷ŒãDª»}y]ºCÆqD)A½*I2Ž)ENN´mC³(éý@Y,75)DTm™Yƒ…a&n®¶«©ê’¶m™†‰ª¨²Ga2;߆Z°ßps. ó<¢T)ù@JmÅ¢mY¬j–«ö.2[1§ £2 ÆqâìlMUf<ääl‘µZbM‰2Ša˜˜æ™aèg 𦢍 «–9%Þ¹ÜbêŠóÍ‚ÁEÞx‹W% •¨ÊŠý!ã+——[N>`î* o|á]Ž×?wŸ¢®(uËÃ×OxøúšÓõ†Bk®¯¶,V¯Ï |æû_åÓŸyŸÿ‹WÿÖÔÇ÷î @úN¾ ßàããwûtúù/ýôöÿà“§n,>ÀÛ<»êhKCPË€^[B2/øäŸ!Jxv’dàØ , Á0GêJ3Þyއì›7w#Qäè¯ÂZ¬µÌÁcÄÊ_h]w!$ËÍ£³[1Jmp>¢MVãi•¥¦²4«‚ª®p“'Å”)À2¢”dÇÜ-XIQYŠÒ2 Ue@æ„äºÎÿ])Øœ,‰궤]4…ÍÙ}2ÑÔ R)Žû-·Û[„ï=Ó4c‹‚åªBW]¤†Íf…÷ýáÈéÙšyÊVäBÂ’àì|EL‰E]¡e–:û(ÃÌ£V±‚¡›øà²ãý«vÙ¤‰ÂMÃ0ãCbF®žÝròà‚áö†¨/~ò”.¸yºg×íh7ЇîqvrÊùÅëÓ ËÕ"ÿ *Å;_ºý³¿ò·Ÿüm`þ3z^¾³‹Àñ­_ìðØÿuðœ5šÂÞ|gÏ—¿v),£Š<íoéöGZ)xxÑðûþÀk,–šíõïòËY+AÙ4ëå‚Òjúq ZTŒ»žãvàÁÃs 1ŽnòÌw`™µ!Bç„_Rdšs¸å8ŒÓL7uTUxbÊ!"):lc¸yzE"rq?¯7ÝœX¬[êeE]RŠ")xж‘Hq&ºÄ4ú;å¡BˆD<ÒT5Z –ë–ÍfÁÐ C1©3÷`šFbð‘ðóH66TUŽ0?vUQBÀ»9G‹còF`ì;ŒÒ„”èç>wC)ÑnÙÞÌ ^>)¹8]ÑG¨ÅDfÖë†E[óâ½õÝÏ‚ÕrIa4_mX=ªØ>;}€ÊA㙦‘ëë[ž=»A…›Ý]@+ßûcoþ‡1¤ËohûÅóð9|\Ýcô¼ûÆÏÌ4Îþ#ï{–µ¡T«'{Þ|D–W>¹ä¥WÄq¦¤@ø]¿ï%ÎÎLýÌó<ä˜ï˜8ô1EüY,kªZ2zG3>:V«ZúnÊ+ÃeiA&ú®û:Z9ÏÉÅšº2¶àÐ :‹#US`ZEYWÔuÁqß!|Ĺ©ðãLa êª$Æ€Pœ§*K‹–²)P"ûôk-™¦l2Œ=ûýžýö–˜’\r¹¼<ðø£kÞyûCúaÄ¿ñ§>ú·†ƒÿÒ?4û?ï¾Ã âÜ¥_ø¥¿8þÁvQÑ,²è§Ð]u„½cQ–È¥§8©A×”Õ’Ó‡ >÷ß{…ÍiC?>ÜgŸ;‡‡”è»ç<‹å‚è³×€w°ljRHÄ”¨JMq·ïšºdµ¬h«’º.™‡‘Û«ÛLüI-Ëu‰ãáÈÑut‡#Ræy¦{\tH©Iweš†œ Ç]Çûí!‘Àäç 2Í(¥X.LÃÈb½`±hsþŸ£%uSQÔ%Ûý7æW¿h¼ì¶{Ž»ÂD\T¶•yÎއ'ë%Êtaqþ·R‘M K£§=‡}ǽO¼ÀKŸ~ %5¯½rã~75W×;BŒV†>[¦‹Äqwä8÷|ú‡_fiKºý€×úžâìdÁímÇ/}þ+|ôÑ%¥±<|xÊÙÆ7­ÿ~õw˜¾.þóð‚ÇÛø×~þ'º?(…ÇŠÅqtôÇ‘§\¡Œâþ÷¯Ðµb<Çm‡])>ó{^äbSÓàÙÎQT?{¬µ95¨Ê~õÇnb±ixðhÃa?0 ŽD&Y›Ñv©5»ÃŽÙy–'KÜ;%¨Ë’ª,˜C¤ªjNΗ+Ð2«Û¶äÞÙ «Õ‚ÕºÎN=!R6Uæê7%ËUM[Ü{áœ¾ï±Æ°X.1:Çl8?Ò.[ŒVx?çtÞ}Çn·§;‡‰º.i%"ÆîÈbYRTy+¢«œ“£Ï«ËíŽy9;[C`³ZÒÜáeY@Š Î3NFë,œê{Â]nàâü‚W>û}(xõå{L!‚2$Ia`¿ÝÓTK^ûÞG<üþkKn.÷Ü^]3š«Ó’Íb£Çc¤n6kꥡßù7ÿÖ=þ“)ñ䀿ïØÝÿ7Íóóñ8à€ñ/MÿïÓ‡êŸø¡ÅÿÊY(Uæ8{ôgÏða&- ¯ÐvÉn·ç“߯Ê%øÅžÕ²àJ Æi"]?ñÑ㬱Ì>ðìjË£‡žÝt(- Ñ‘T6G--c? Œ¤*nonuE]ôÄ-K$‰àGºa zP⃣´†ýþˆVŠ”òKZUZ Æ)ç*%èÎ{´QØBS”šCw`yGÊY¬ji˜I6§Know©˜'O³¨i[AŠ¥ã8b´%„„H‰ªªP§‚ýmÏ8´…¤(,mÛ2;G?(eXÖÍ]*‘$$GŠvÑ2¶®8¾öko@ðlÎNÙî„aâ•ïû^Þûè–ã8²¨‹ÌcHКÍË+¾ç_|Èw3pùË?Õÿ‡o}eúK›SƒüqæÝ7>âó?ýŽ—;Dêðåž]Ñ–%ÝMÇk¿ç^ùû̳gi £i*Ë<{ÞýàŠãìG”m½Ë£EQ0Ž#Ôi¸}×aŒ¥©Jnoo .ƒÌóŒH9/ðpØ‘„`s²"•){ïÙ­³/ | ÌÎL}¤(L¾ðµaµlJd:oð%)K»Îz~)J‹TPZËbÙRԖͺF¦„-,Ïöö€Šq9ì,– )Eªu…µšyˆ!P–ãá˜%Ò''”…Á9ÇõÍ5Ã0@Œ-X4%›Ó1Ì@UIÝáȰ?przʫՊº²x! UÁ£*~ÛïïÁ#·×ÍyÃùË×OoøÕ_ý*Ã8ȪUc¨íÿöá¿ÙݺŸý†G ~7}🀰pÀœþú_ßÿ_¶¦¿ÿÒ'ïeO½îÈîòÀ/ýì.÷œ½PQÞSÄ8:ÇõG;^ÿçqñú*Ð’ ¨ L¡øÔ'±nKliñ .ŸÜP”¹öÞSXIUjŒ5xç]î¬Öœ_œ ”¡ª+| „yäüÞÄÄ8”­áØA$ª¦b³Zrv¶buÒbMƤÊd)%ÖëªTŒÃ@Ý–w‰·5ÑGv»Cžñ¥,,íbA7LóÄÉjIQ—@d»Ý¢¤d³i°Ö°Zç5ç=~ŽÌα޴,Ú%ûÝž¢´,O”¥æv»%ÄÀ¡;¢µ¦m[ʲ ªJp< øÙ2GÏrµdµ^S5 ‹óS®ozÆí *pDRpúBËïùŽpœð³' 0Ëž©îGÇ»_{ÆõUGYZ‚Ÿ)jÃùƒŸÿ«ÏþøŸ¿ùËwsÿü í¿x^¾{;ðó¿ü3ÿåÕ¿óîW†_°­"Š@QiŠ¢àéÓž¯~å*Ö÷Sò$ŸÏgÿ¥×xýw¼Ä}7sqÿ„“EÅîæ€'±lKJ[LSÖ˜¬—™ ×4%¶È1ÖÇCGÙL˜¦ó{§H-sˆ†ˆ áp{@n±V±ÛÝ2t#aÊIFÖæ°a˜æy¢, «U‹ÒŠ¢°Lnfv«u…Ь*´É]ÇØw\€!õ²áôdÍbÙâ’gv#ƒ›˜† BÈéƒãÉî’ª)¨ÚŠ˜"c?°Ýn)‹‚¦®X¯jŒ‘ôãÀn¤zv»JÃbQ¢E-j}ŠÞl0gç<¾ééûžÂÚE‹Pš³—Ö¼ö»^äúrGcKúƒC‰‹O4ø{A¿?æ;­e£(*É?¿ÿK?óç>ú·ßpùùniýŸ€t¾±ôûé+ó?{ü‡¶—æ7/œµD/ nöO?<ðôkš³‚ÓWjF?àzÏÐy^ü¡û¼òƒ)X×5o~ù-¢)¹ÿð>¯¾|S*¦Ñ1Ž‚Ú¹X´(¥2aÇ*ŒV4uƒ ‡ãþëûÓ03OÁt)(›‚¢,HZ‘b¢Y,ˆÜ4q<UAY•,Û:ç T2}yÙâ 1¢•BkC×3v`%‹¦•uÿÊH†a@!FvÛmþ~µa½Z°\-°UÁn@ZM½jPJRÙr<Æ@Q”HÇé5FD‚ª©RÐ6MU¢”¤:*åxïíø»?÷k|ù‹oóö;ï³ß8Ëõv¢:-øÌ¿ôR(¬±L‡‘Ñ÷¨S‡›GÞüÇL>`µb½åýwŸ±¹h¹z‹Ÿú›ÿù‡$EÞ½ëú¾ëZÿçà¿ùx Ü<Ä/þÔ~ùï¾ýÅñ—Tc¸9Œ(‘Þñîo^òƯ|ˆÙÊ (×Á¼|ö÷¾ÂïÿW;iy÷¢±œž4„yöø–ã¡'Ä22¹‰a˜ç‘ͦ%FÏ4Ì ý@Œ`•eF®¯®¨ëb¤(5©X›Ý„ÛE¶ñöt%iÖ-g§(%‘JdbJ‘®ëAk¦0sìЦ¡,²\÷ævOŠ0õž®ñ$¢LHc¸ºÜâC§HÒi-.DŽiž™¢#ÄŸ&%ÔË’qs°H 4‹šÅ¢½Ã+ Úhº*3‡¬‚<ö#ã8eá~‚Âæ®Áj…H’Ýöˆ8+yí÷¼|çS¹½<`kÉæËíaàó÷+lo÷tÃH³jP2±<-xë׿øW~ôÝ—À›w—~ün½üÏ À?úˆoÀ4 î‹÷Ç/ÿðWaûËmcX4–ÙÏ”µå¸yóW?à0Èç0 \t`ûtàÓßÿ2‹ fQc•æÁƒó;QМ­ÈEÉ8ÎLÓÈ쇮ÃCUVÔM…T’¦­Y,jšeMQÔuÉ0ôÌÉeJ/‘ýñ˜_ÙR3;¤”Y2œ)9´Q,š†Ló”8$#ee1…a³^prºFŠˆ1Y˜T%…±, UeÑZ¢¦)Y¶-˦eò#Jhf—ï’CèéG áý Ñsyù ïsPÇ8u˜ªÀGV’ý<0 G”R(­©Ë†¢*ÐZc”!FIw˜ù¾Ï½À¿ü¯þ6ªÅ’”ÝaâìÁsêyöø’/üêÛÔ‹ŠU]çЗ‹ŸüÔï}ñðþõÇ¿öN)ýæÝïxâ;Xëÿõaÿg™Mþü†„øV)é®@Z` E%?û;ÿ'§ÿ»GŸˆŸ“L.Òõue™Ü¿WsþÂôX°)Ïbbßßð䉣oæáƒs.onØí÷Ô•áñãK‡žº*RBÂIY¸!r»Ïíø¢­1QhÍÓ«k^¸·aßw„³ã)§÷„”=õ%PUÙòZ[5ù‡#…µ4‹–qž!Œ6Ìó”í¸Û–nׂi‘BRUEY²?QRa´àz{K¡ ´6hcr.@ßg‘PJÖR57‡-æƒ;[ïEŽäú‘’D¼KžÆ‰Ýad½ª89iØï¤”Ì!pZXvÄGá:ÇŸùÝ/ñý¿ëìo÷ºäéûOAxê xúôŠ›ËžA(Ú²`YUìãü^I÷Qzç/üè{ÿÛ~Ÿ~òîw|øÐïŸiðÏò>/ÿx]ÒÇE 4•øí¿ã¿¿ø7¿ïwÖÿòîöHð ªPt»#ŸøÁWxøð„—–/òø«Ð)Ééù†Ò·¼ñ÷¿ÆÓ'74Ë‚iš¸¹Ý2MeQ£§ib Œ£gÊhªÒ2M3³Ë9óä8?m(–%dzÀþjËbQÃ]º±.ò‡J Œ’e0•¡ëzšº" ‘Sx¬æ°;¢”`s²¹ÓxvÛ[–ËûÝž¦©ïÔ€žÕªÁËvDkEŠ‘ª©‰ºã‘¦®éúÌ2œ§‰fYß0fOç.ÀG¿ô7ÿÁáÚ?þÔÿzÓ$ÚE˶¿¡© ýÍ'W׌IaW5ï|Íóìý=^$ [áÆHQæÙ6…"ëN¢Ï$´¢l(+ÍÕõ5›åÒˆÐ,DŠôsG?¤!Û ($ëÕ’iЬ×+¦ydFª²$ ˜Ç‰ÑÄ$( ‹²¥4ëõm4>¦iâì⌾ëèŽ=Ëå‚õÉŠ¦m ÁÐ 8ïHÞ±ÝÞrzz1ÝuÎVÓå’]×ᇉ…)ÆpØí±EA× ¬š çU]1LnN4› !³Ù8N E¡©´Ì1bJóÆ/¿Gì4|í q9²ùtC¹—Ô2â€Ý¡GÛLRróÀ‡o˜¿ñkcþã$Þ¸›÷÷wÿNÏ?ÒÏG€ÿ6GÝ °NVíøÿJñ¯/_²V×<|tÆíûOyÿñ º©xøò ûÄ“’*UDƒ?÷û×7×_g j­)‹‚››-ÚT 5ã0du\ ´m RRYA? ´½™‡‰º©Y¶ „$‘ )UY LŽsw1ÙeY`Ê‚ëgW,ÖM–ÑÆWzJ’Ýá@SW©™C+ƒŽÂøàØoØÂ"R¶$K!’ÈŠÀirȘV2ïl#ûm¸sšÇÒ) ”’Ž#uUâý€µ’shª6–µÍ`ä8Maûb¤| Ê2‹ªºCOa-£‹ nšùÒO?þæçýÿÒÛw¯þá@¿o­ýós àÛ¦|Ü5}\–À¢Y©ßû©¾øŸÿÈÿôå.„åÍ/¼Í$ Ö'%'çKöÝ@é*>úû·ÌcÀ”¹åV*` ƒ™°3Œ’ FÃÍõ%UU` ‹ÕŠahš%=Ea˜QFJm1eÅÓoëªD[K«,¾ŽTƲ¿|J `"º$%IãLYœËXkÓXžèª°ùk¢äöñ‰&Us¡¹¼9²Y®xz8°sP,+š4ïϹÿúƒð«»WÿpwùÓóÖÿyøf ¿…¤/ýÜ_¼þû½/ÿ‹Õ¿rq²ÁMžÝ®g³©™]bóJIk ¿òW¿E@—‰E[QW ÛÝ‘$GÊÊæÅƒ´mËõõËÅ’D6 íúŪ¡^Ô(¡±EÍÔOH“6•”¤èQR€ŒX[RÚ‚! \__a‹m4BJPpzÿ¶†ë«kâ1¦¤¬,AˆŽ¾ï)ËúÔ“ØÂ²ÛíèûõjAô‘±P&«-³ðƒ£]¶xÖŠÌ=(kDJ”eM»¸KUfÆ™|ÌhU„àY¼”0bæ¤-Þqºªè»žZkÎNüõ?õô>{×ÿ2½wË£ó9à÷ß¼âz~þÛp÷² wmæ5ðÕ_û[óŸ¸zCýÔ'¾çB †aBƒQ稶ìÃÊMÃ4;ºþ€V SćÀr³i—–Ó“Æ€‘¦®©ëša˜ÝȪYeŸ}ÛȦ®ïœzea)ª’ÃvÏõå5B$êºa¹ZPXËj± ¬kºCÏpÖôw¯Lâ/üWÛýßsý=U+–•aöŽå¢brŽYxésÄE¡RULóDô)‰l ¡dÎíCºîHQYRt´uÍ(<‘!ÌèB °H­˜I ‡CεOé#ËÍ[Xú~ÆÖ–¡è»ieQ SbnbBKMSJŽûÍrÁa—•†eYÒw#ualj²ªXmrjÏ0@ çYDŒ•8%(O*Æ®'^G%M]àãÄ<ÌÁaŒf³Y0ž¢ªwæ&Z— }‡Gòâ÷½Lñ)O²žèáêé³ó´Ò´Jñøíýoþämÿ#àé]1îïÆ³ç-ÿóàŸúùzÎÀÝ«sëçø¥ÿ×~óß 1@ðç‘R°»>òÞ{OÑ%á™f´Èn¸ÚÚ¦¶ÐLó.¾-‘I0 =ýpd/¾ü .zʺB[W$Ū¢\4º#.yzïy|uMT‚)ŽÌÑ£JEH‘)8Taƒç8öLaÂ1s˜;¢J\o¯¸Ù_sœzŽSçÇÙÜ;Á‘xzsÍíaËèg§+(õ²fg¢IÔECJ¾;r8ì(Š"g‰VšÃ¡CIÁäG„È@°÷žî80u#›Ï^øžs½ô€‡/]ðÒ«çV²X[î=\ò…ÿÏôïoßÍûßvÞÏ;€oÍNàë;æÃ­ûüçÿëËÿìsÿÃåÿž?¼âñW»ù‘0Bm,Aê’ØÂ RÚ¬ú+5­]c„æéö–õzµ–‹³{4‹½*¹~|ÉÃG÷8{¦iæâdÃ0ŽÜ»wŸ¥²ØÅ <) ¦yfU7ŒûŽjѰ,ÙZlœ9ÝlˆbÁ8 œÔkäB嬾(‰ÓÌà†Lí- Â0#µfê'ˆ‘õjAð‘ëgW¬K’¶©¦‘Mñ€q˜é‡™óó{Ìó„ØY.Wtý€›=UY3‹)³Âpö¿s„G!!MY2ÊãV¾õ3?þôÏ“×}¯cŸ¿þÏ À·LøØdôÍ_øóÝŸ|ôIû#›UÁÓÛ#Ó“@ËšÛ›M[rz²a¿Y´ }7àÜ©ØÝÞâ\s­uA=B#*T'©£¥5þ0±ªJ¤2xnt™ %ëf‰w$tÝÀr¹Âj‹2 Tu ) „`yzÆöÐQ™PÙ‚Óó3º¾§ßIˆ‘Ð9–eƒw3qŒ¸aâþú¢Ä 3Ã]çQ•%·û+Öí)MÓ’xúä ‰¶)å“qÄù m ËeÅÍÍ.c«~pÔë–99¢L´+Ã_ùoÿ_ÇüÖ®ÿùå>|Kv“ŸÄ¾öùñdž4³Y¯©«š¾ï†Ì?{®®oÇ™0 šz›%‡Ã„ˆšº]p<ö!ÁŽ×‹¶áêæ*ûè"û®c:ÆqäxÌ—µ©sŠo?ŒãLÝÖÄ99žÌ9êº`ú¾?²»½E[. ‡ÝŽã1Û˜Ÿn6”EE»lPJà¦ç)%„4ØÚÒ#~ž©ë«5¶©rìx”Ø¢ ¬êzIœè‡½@$ÅØOö;¬1TMÅå·ø90tÑçh±·ßØ}õk¿¼ÿ<ÏY~Ï À·8à9Åôá?;ÿ••­ÐÒ”¨5ÇCϱŸH±¢ï»~`v­,¥ÉŠ=)³V ©k–«%‘Hwìiê†ë›knž]bŒÊ$Ÿ¦BjƒÕk,}×cd¹ZÑ,šªdµX¢•@YK]W(¥@JÎ..RRB)Ê¢ÄZ›yüu’~šýÄRiÚå’ª®³¤ø°åéGOY¯WH©À(’SÖrrrÊíÕun=•¢nj®¯.!Â4{ºÞ±Û:æ¹`±Xä¸1­8ì„ÛÝžÉõüì?ýcw¯ÿÇn¾Ïgÿçà[¶8ÀÇøë¿ñùá¿@9¦a@ÉHUWôg#¤„”‚yœ±šÙù;­€ÂËì"QF\ˆÔuEÝ”œž`Š»‹¬X.rt¸óžÍÉ nrH!³±¨”xïYm64e™ n¦©+º~àx8dSл0­5Êý‘Åb‰Dd’Tr:°›g„¤Z \pTE ÁÕ“"žcßåD‘M?}pEIÝ4()iëšã0Ñ&Gw)낪j¸¼¾eyÒrõžãÝ/¿B^û9~˽éùyŽ|KŽp1¤>ÿ7w?qñòòVÚBúÑ“pEB”–i‡@Yæ´›"ÎÏ y¡¢(?ûg¯þð>¿åèóœêû¼ø¶(q<ˆ_}ó—ßÕ6Q7¶0lNJ^zeÅê$§-ÚŠ"³›Y¯¸Ù3#ÝaOY4\ÝlY¯Ö”eÍÜO!HÚECSÖh¥8;¦Ñg·»at0ZsØÑÚp²9åÁ£GÄ‘IID"Ã4q~r†QŠà<~ΡeQQ%ƘÌ"ìŽ4UCQ”4Mƒ5E–2‡È<k(´5-©«m4VlNN°ÖÐ,[ e>€Îb “MÅÉ™a½©˜Æ ?GV«†fayöÎü•¿2üÚêïž_þçàÛe €>}øþ—Ü¢H8çJá}`½YbÊ„P›ó’‡Ö´m‰TŲÁ†ª²PÁì'B Üìo™œc»ÛÒ³w2I„k(mÁÉb Ùœª¨(”áöv›Ù„'gœ.7´eËqÛ¡¥æ¸ïr°iaÙŽø9@t}f/ip“ãöæ­ÖZŽÝ‘ýaÇ0x±Ö’Òœ=u]Ñ @kRP”’óó¬YoJ” (1I¤ÔÔmÍ0ÏÔV³n_ü[·?¼{7û¬òÏ?bÏG€o—"„Liž'RUQ03óÔ³¨Z†aD°ÚfN ÙÓ~¹DëDõ‚a>Œi°çÃT¨NNåéñ0’P”¶ )Œ¦;ŽÌcOQ[BpGl‘u÷H‘ƒ2Ž•34Í‚iœ0ÖP­æÙáœG™œƒ”èZ]¢±–ãaOè¸0ç`Þ~DYÖ4åjI×wïä“ Ïnnò7ŸD6+1ÔUͱëóVâlA?ô Ý­+”ŒÙ€ÄZtÐÌ“¿  ô~â¤Z3L;¦Éd¤Ò:Çš7-Bêœ$¤ nH>柜H­â—6ý)ïÄ[dÁð7¾þÏ ÀóàÛâøz¡6¯Oó ç@$rhGˆ()Y,øä™Æ‰²,X­[b[ CŸWmµa¹ÈFžm[33eQ|ÄMb‹U«‹‚xçÿ¿Z¬PJá§™RX£qÓŒ’û÷î‚:—ÄzV‹ÖÜýÿ”¦*ª;‘œÜO¸i@ iª­%Ó0"‚`ž=F(Vë ¤„) ŠÆÐO#§«%M»@ w9í¢Étèã‘q³Ð8‚„¢2<{ïš_ûÉ«/’Ò ÿ`ÇóËÿ¼|û€Þ%Ñ.)%PwY~ÎÍ ãÀ89ÆiÂ;Çv{ ¦ê1N#[Æ%`¿?ÜÍÑ­%‡ý‘ºihë¥ýÐã¼gš<³÷Ò×SxÏšû¢®ÐJgp¯®0Fã]B*…’ØÂ²\,qÎáÃOÙTy¦/-EY€çÆ™¦nPZ‰ì¶·4«ŠÄf³Æ»q‡uôÓHUdÃiÎ$¢g—WuSƒø˜ºœ0VeBSik5ò†x>ŸýŸ€o›-€°V¬Wký¢VŠ>š¦ÂùÈ8Œ,ê£ Zk¦É1tã8R•}×#k‰” ?;œweE? xï&[ˆYchê­Ó8Ѷ-J †q@k¥EYR·1¸œü+‚À8Nw„<óeA»Xäèòi¦´!1”V(%)KK×R’TUˆÃ;5† =FIú±'DOUUH!hÛc²Z±(rΡ–š¦mèö)Úu‹Ô*ð[Þ Ï™Ï À·]@JÖê“LÆ „Hw.ÈÙTS#­d±¨ÐJѶ5‹eË8MTU2Ю Ek)ê‚åf ¦IBÊj’JØÊ`J;ÛÓ»){ Ê„–‚Ñ Ó4°ÛmÙ¶ÔM•­·ìvYœˆTm™9 Á1…™¤%é®EŸæ4H+Q…f±^ ´ÄÖ[Yæà¹Ýospøè€ž«bÁ°‘(¬ÉÌ¿²(¹¼Ü2ÍÙ\+ƒUã<ä±"¼Ÿ¨*C»¨‘x¡åùÞÿ›~žoþ»9@+6e#^ç™ýnD%‹ÒšíÁ3Ï0O3ÎO´KIQX$ÛÛ>;â¶ †›‰õªE DÄTš„§%³ŸCÂ(Â0L­4Ëf "q8(}ƒž,…,¼¤2¤"Ì3µm¨7 “›)ê¥4ûnGZ„4Ló@]¯˜§‘¹ŸÐÊÀ$HCDM’Ò–¤FjÔ‰¢‡¤sJ1æ9Ðu3»Ã€’‡ýLQXö»!$1V\Ý ­hZƒ2‘²H1é»Bú¼õ^¾í..ZVÖH¶7=WOf$ ­sF  $(©ØfjŸ}Æi¢ë:.îÝC™¼Ú›úõºåòêŠvQ³^¶¹›˜SòØè³ÓPY“ £þKK?MH•]€–튾ë‰xÆiþÿ²÷';–íYz'ö[ÿn7§13oî½™É$‰d²IšH P(©&5Ð èÄ‘^A€^A£ˆšj¦IAiBII€$Š"!²"£»»›Ùévóï–{/÷Ûd&YéAÛÀ™m;vÌìì½¾Õ}ë[l7†#! ­J¡u ~Ó’âLž MðXëÐ mè¨iá8³ü½¡éØôR+‡Ã™®é8χÇGæT—Ñd·,,M±s¥TÅਪñÜßOt}Ã<<ò·þ´|ôÔö{J>Íü°U©ÃfÛñò³-ÆX§ sš©(ÎYº>Ð8ÁÊB«EáÅ‹g|óõ×4]ÃááH,Ëæà››ªJN ­Ê¦ë°Þò’O?±b8#§q 4#çça ¦DΉç/ž3Å ë-¥VbŽT©Ä”˜æ‘,`­PJ¦ßö‹z\:¡m¸½½aÓ÷4m`·Ûc$¦È´Ž ;ïÙÝìÀÁ4l7Jž¹¹]Ö™-­J‡kÖ 9Ò\HS[¨ þ¿ ìxbÿ=À§þê,/+3)e6{ዟ9þèo¸»»ºpúK†RÏ"”¡\Žº]Ã8̈M»ááþ‘áŸàS<¬÷ަk0fâv¿cN‘qªLS¦iÖ;B#<{qËññBÓJ*8k)l»k»m`Ó´\æg…9&Œ14ÖS¬âœ§ÛôœOgæ)ÒßlÑR(1ÚÀëW¯Ùî¶h…Ëe@)ëš®JMxqœgÚ®eGއ#ªJ<9Wj…óéH×tˆnvžaðÖñjxîߣ*|ýå׋bQTR,GbŒÜÞÞ2]^þg ã¢ç™ë…˜mÓÐ4) (#¨ˆŠˆ5OÀ|j5B»©»Ç7gÄx†i"匵˒ÍâÀ›JMJ»ó ¾…¢‰Û» ±ÏȳÊç?}Æét¡œ›nKkæ<±ë;´o^=`œ¥ï{.y‘òV¶mÏñ|àp8òÌ=[BuëØlwÌóÄ4ψ§Ó-ï<û»[ޤ˜øì³ÏÇÍJΑqNl6æ9q9=°Ûl(±Kâó»Ïx<Øßuì_l]<{qó¾yÉ8OÜm7LSæövKÊ…9&¨ËºoqÐ4vÙm ··íO¬½´¥èSð >¹ ´{ö§¶ùûF¯ßu-ÎÂ~ç8&αðâÅÓ˜Øn;†qÀË›7ô}ÇT&Ny 6™Ýg[´&¤ ć„õKtÜ·yÊ\t`k;º¾Ã—†R /Ÿ}Æñ|›€éó43œúMOßöôMÏñá„wŽ®íxóêž}¿!͉ãÃq[~¶gœ Ý®#“Á6/·D)h»° ¿_s÷wï8lî6¤Tع=õ1q:éú-3Ú¼ Ü?q.з-ô­’â,tÃ<ÌX›~f =Od 'øDQÀªV¹ ‰š—í¿Ó<³Ûµä\É©ÃÃãkͺM·òòÅžš 㜨µp÷|Ïá~‘íz¸™bd»ßж }×Sj%¥Äå2r2gš›À{Á0M'ä:óÌù4rx8bÅÑ5-MpœNGœõx¿PŒ]ãqÖbTp΃1œ‡7`„W¯^s:ž M jè›Ö{r.t}ÏîfÏ4OÄ©ûí-V —qàÕÃ=â<¡éõê"C>Nœ.¬Z6›ž‡Ó#.ÆtäæöPb¬t]ƒË8 Ì1’såáþ )ER.xoi›ç=·7[öûÎcï0+ŸŽ'øTRuVúýýl»í¹}vCÛ7 ÀÛ·\}ß¶»nÙ”ëdÕÞ_FhÃΓbBQ¾}ókvû-Æ\XT€¦a&æ ²È‹‹(Ãe ÆŠ¬›~ÇÇeU9‚7žÝ~Ç矱h•i¥¢¤ºì ì6Îy^<AŒç,Άi¤æÂÍnO¿í8ŸŽïiš–7÷Üìo¸ÛݲÙwLóÄ~³åáñ@âHš#Î;*1Êñüˆ3Aùì‹çt]X~Æ92Å‘œ2—ËD¿•¿í¬Ü<Ý·O)À§VN§IÏ—‰š+]ãñMÃeš‰S¤ çÃD~ ªs¦ë¬\¾¹}Ö1“ؽ€üX¸»¹ãõ7ômƒ3žœfæS¢Û´4~Ëé-y€O(UMÎJ× SRÞ<â82N£Žó9RKâæÎÓ4ž‡ÃÏŸïyóÍÆýÜðøêÂóÏ6|óå#î';ìmË‹ÍsÒÃLh=;¿!›9§ y«l»7Ê·J‰Š¨RBÆô-¨Vк !Ýnîx|8àŒ#iÆÛ§-ÇoxïØé-5-d£tÎÌCÄÌïÜBìÙÜb­áõãl4HtøjÐÉðúç_£³£ŽÂ›:ñê«Í~Ëãc"3§KÛ×3­'ú®¥ßu\ÎM3#/ í‚\™€×4à‰ðŸˆ Ö-,k¯¾ÈÑÐlã0S5±{¶¥hB6}À{Ch=mho<Æ)Y ÙŽãö7ϘSa³Švh0Xg «D2Õ ) `-777ÄÁ*¡i1Öp¾\軎Båùg/¨©ðêõ·Ë^¿èv}Ó1NÇ8¡sÄï<Û› ¨p¾\ˆ%Rb¡Há8œhºQÇ/¿ù9§ùHÓt˜a¬8 Pé:Ï4ô] ç3Ö+Ö(1%âýçm»ì˜¦H©¿Ã|2þ§À§Öˆô][}pò³?<é1µ0ÇŒ‘ÀpžÈ13Ï3¡ñ\Î#Mèú–Ëe"M3¹,‹<Ú.0çÃ83åDi^´÷¦8‘Ò²5«ëZž¿xIÛ5Ä mËç¥Ð×uXãñ!ò" –4³Ýmñ®YÖ‘åDÁ{O·iÑuŸÁ8EjURN”Rˆ1b¬Á˦ß.ENc˜Ó‘››ýb­"/àr¹¬;…g¬sĨ„Ðbæx<Òõ‰gÏ+]kpÎ OÀ'øT˜K†q×ú€ˆpû¢åOþ´çîsèwl¦ïßr><>œßŠcgnö;îžÝ2ŽÞ;އ#§Ókºí’£Ó´LV˜†Hš¥µª­Ê0NxçÙnw‹¬×<Ó´R*Îùe™ðâåK\ç1l¶[^¿~ÅñrÆ[Çͺø³ä´€øågnoïh|Ch:\pô݆¯^ÿÖdÆq$ÅDÎt]K×õĘ8ÄzZߣšØí¾øÉ–ÏÒðì¥"¦p>MXk1æÉöŸR€O/ÿ †Æn·{÷ÙÃà UCç-¡ó<ÑZ‡³4ÃÃë3Ï_n‰YÑZ˜æDpöíŒü¦ë¸¹Ûr|xäÍ«úþkv?½år˜¹{¾(÷mËœ eœIsB¬¥ï·Ü4–aÙﶇ”ÞyŒµl¶^¿~Íîö†R+˜æ 1Bp®m—¥6ýª¢E9œlú#P«r·Û‘æBu#5_ˆS›@è=©\ƒÁø@Ïlw¡¼‡ž†®³Xg™¦ »]KÓ ÓY¥‘Ÿ"€'ø$AÀ8clÛ5Œ£ÒxOÖÌé”™¦Jš+a£t[ëhBC-0M‘ »ç;.:â6ê\™‘Îwà=÷¯ö—<¿ûC.§‘íaw³'ÕJÍ•Ð5”ºé¦9álàr¹ ]èH%±Ýn¦Á.[‰µ‚E8ŸÚ¦¡m:(±à¬!„@-…¶é„q˜‡‘àZrùöÕωcäü8ðò‹NÙjë”â•~«Ì9q»í¹¹Û£9s<äZIc¥¨ëÚðœ ÕVTÕ¼¬Ou€'ø$"£ª&¦‚œ3\Æis…iL¨*]çqÆ3Œ3û]G³i˜/3áYeöJé&,…qœé|àåóçLç×ǯØì÷tíÃqƒq‚ï‚õ\Æ‘š ìïöÄ ÆN ê<µV¨ÂM¿lÊ)s³ß3žGºuAÏùx&M‰¾ëÉ9c´R«Asa¼$ª*ûÍž9G¾<ü[´±wŽ—Ÿ=§0qó³ ì¶-ö¾eÊ#?ýƒç\ÎÒI1-i­ ²ì óòå†n»áñx ,”ȧà >Á" i‚c4‰¢ë,ó4!xv7ý²' UÚ¾Á±(^L‡™š óñÂîÏ6XW¸y¹åþÍq©üûB  øÆü‚?yÙ²ã†Ëy 4 "‚zТ»ÐyÛ®ÃÃ\"*ä”09'´(—ó# ¯ÖJ¬ŠoxH9-òa¦01c;‹ÅPZøõ·ÿšcxM»iÙÿlÏqRµ¢Rx8Øß쨬sŽ'Ú¾Çwž",ÑJ‰¨¬3ˆd Ó7Í[ ×Ät¤m{ºn³¤ › !xÇÖz¦)’sæævG!Óö-¹(!¸…ûß0±–RÁKß{œ<>^ˆ)[yµ§à >1Y¶ lZ¿ä_Ö¼£ Kk°j%劈%å̶ëz®³¸ài‚ÅÃé0â¬CµRR¥íqZôóŒ~õúÿÇë㯹ÙÞ²ko–ö °Ùôt¡årèÚe5WU¸Ùßà}³¬k¼÷xc)¹âí"Òx*lú=V5Vº°£èÌ™¯x8}ÃùxÁÙë=Î:ÆaYGv<^h7˜‚!ÅȦ鸿?r9ž¹Œ3Î:¶Û Ö ª•)&昘çeº°Öz~*þ=Õ>©£X+bœ#猠\N#ígª,TÜ,Æ1k+¡ ˆÆóÈögNqäÙË| /»ë,ñ8óìÙ-çÇç é<áík~þÍ¿ä³ÛŸÑ¹¶›ýfÃt‰1áûÀÍn‡ˆ¡ë<óŽ i†„Kœ ó|a»õìvŽ˜ˆCäÉðŸà=¬[.o^Ÿ0Õrzæ©p¹Ì«>`ÂXC‹Âïëo'ž=ß1ì”ãHÓ9šŸ¶œcäö¶’ˈ¥²½i‰$.÷Ú6p|<‘mfûbÇÀ„‰ß¢ýHº7lÚ|þü º¾'•„dåðxæîÅstØôÊ\hÚ†7oîyñü½Û0œ&¾>þšoÍéò mÓ¡E©Œ¥ t(¤’áͲ‹0OJTÅn,ßN¤% –¯þâ߯!Qse˜'Bh`gJUN癦ñ|ñ“Ž—Ÿ·ËrS!®)ÀÓTà|RE@jU“§„TE Ì1ñí×#.x¬rÊÌç™»ç{ï°¶áøpa¿ï¹?è:ÏóÝ™)†7_h½Ç9%[Oh:´@g:D=AÓ4LÇ3ç|DEÙßxõê|öì öÛgxÛb²'Ÿ3›vOßvÌãÌ÷hÍ<¾ù†óð†a|dœFN§3R+Ñ/¶Øš-V„ñõ|`>FÆa$¦BZR̼:Ñl˜¨Œ×}€ç‰ífËépÆ[1†ñ2á¬c¸ 4.à]Cãáõ«‰8—'QÐ'øA@+*Vè6ži*üñß鸹uüòßhuX7Ý–àÇãýÍvYn 7·=sŽàà0]è}ËþvKÛÆÓ„:¡¨âÚ€ ¦BŒ‰*J@è7´Æ`¨äZ™æ_¾™Ó°–®k9xúÐ2Ή¦ Ô¢ø¨^|››Ä0ÁnÓb½­ŒùêýŸ OðI ¨uFw·[J 2Ï3ÏÚÐî=¯†Âe˜™ãBÃ0sŒ`”®\¦iô”ñ2±½ëÉ9‚b©Äa&lMÛbœr9k‰óq–»ç7Ü=»Á9Ë·¯ïiû†Ð:†iÀ‡€­ß,¤œ®qü"XÒõxcmÁÛ-b„œ2ííͲ4Ä Á9ÃþùŽxŒŒq&–²Ð{cD!—Dž„)&¬D,—ËÄå 5“bÂnÑ·Õ“ñ?À'Çüøí¯Î¿îwæg1Vnn·Ë‚ÍXÙÜö/Ó`‰ƒ2ŽããÀvבc%›Dc ›Ð ¢4›Àù2búf ¿ XgmK®…’2ÙT¬z\ëI%QP>qÃ8.àã›Àîv]ä™ Ï?Î4GÚfY@êƒ%Íß,ƒã«7\†k±&Æó‰íf‡(%-Â"Á"šÉ£òp:3e…8/܃¦ƒ”)I)*KÈŸe°bù£¿ýœq¾`Ì„ZO‰²ÔLÅXCœ}Ú òŸl`EU¤ªXvÏz†K¤k Æ*:AÛ¶]˱=sc-Z÷Ô Ó9“óŒRQ]ˆA]³ôí·ÏZ\댩ŒÇn»áîvOUaÏÔ Ë8Æ…Ô“ó4óÅ~KŒ‘9Í\¾xþìÅÐo:ÞÜ?Ò††é´Œ'UBבç„Oßö\ƉÝÎÓöjA#ÂápA¤ò|·Gá|9]FŒ³‹ÇFÄ ww=ÝγÛy^}{¤kˆãþq@Šá,™ýÖ#ÃD¾Ê#?O𩥈©ÝMK*ßþòßZš¦ÅZÇGB´ 9³Ù´ C¤¸»ëyö¬c~>3§ÀãWr±tÕq:^Øo;rªœ|Óàœe·£Ö%ô#t›–)fŒ(¥VT!¥BµÂWß¾æ§_¼XºÇ>x†Ùoz‡MËbï8?žèúU¦HÓ8Þ|û†Z*ûÝžÓùDÍpw»ãár8ɵ2Ï™v°¥m<6ž½Ü2Ï‘ããÈ`ÁZG)JèBÃnÓ¡Æ4Òµ'ÂSðŸ0T­)cËíg[RL¼þöLãzBð\†‘œ<¹Tîî¶\†)–ðÂbnáÙMO»s`éˆÇ™yŒ´}À‡eÃ.F0FÞKæt„;£ñŽ” Mãqn™ßõê MØíwÄ9"öý†à=»me¸ xgÙ†›ç¤)Qb¦i=F E2F,1Ï_Ðòüw<ŒgÚcwÓòê›#mè)½åtézG·my³Š„6m`"Z”ã岬ß9¨°Û·xÒ8•'x€O5Þ’ª‡LØ:šâIs&¦Lç=77-§ó@pŽ\2>´œåR8<Œ|öG—ãÌÝÝžîE¥ÜyâœÙìZN‡™b”Û}ÃtˆLóEhûŽÖ{.ãLª™»»ÇÓ²çñtáÅó-—ãÈ«o_³Ýt1œGú®áþñ@­à­Ðøß¶””‰:ÓÞ¶¸ÖQbi»†9ÌlnzŒ3̯3©QšÐ1]ðìfÇô™b¥ÚBNŽq˜é·‹ ˜óÂÍvCÖBJ•8Oxg«œNù!gfbÕS*ðŸV @£Ì—ûùaÿÌýZ„Ýí†×_-[xæœ)Èօ„Qr.l6 Q#7·çcbsãljûW3Î9îî:4ÁíÍŽóáÂ0LøgûÙ–šçã@÷,°Ñ†¢Ê7ç7t]K …~ï©Véî:šR MCÉg,ÝM‡Ÿj-ô» ”šhº–ÛÛ;ÎÇ ÒBßw¤âˆS|[Ÿ?¾9/kÄS¦ñŽK„nÓ0Œ™á>âµež*q@-Þ[Rñ’€LÎæŠí„œ ¥Tîó}Éuz÷=}¿úñD­ü÷ŸÿÈ<—ÓëoÒ¯+ Þ eiãYkPj›sžªœµÜí»eBO=)fîžmȱ03ÛMK¿m8ÞOÔ\pšuÈh»]<õt™1ÆrzeÛµô» m¿°î|çyýxúmÏÃᄊҵŽóùB¦Òô±bFÞ¼z`ÎXâ<3œ/œîOL— 7w[J©ìn6Ä9c1ä’ÙÜvÌ1r&nžmhÛ–»›=mÛ¬ááᄨbŒe"ÃeÂxƒU‹XCV0ÆZcäÉó?À'XÅ ¾³¶Û8œ³Ä\#ô±`¬Á:Åz³È×EÀZÃã› ¹VŒ­Ü>ïÈE99gºÛ†Ó8µ`[Ö0—Êœ3¶ótû-û—{昸\&º¶áþá@.JÉ•/nÉ%q.¤RP­œÇÈ›ûm Ê4ƨDhCËO)ÀßôÐÿ-TMã)NÓÅáÄ1ÆJ)•yÌĹ²Ûµ¤Y©El1Îñí×)fšçŽÓë‘Mã0"É¢¹rœ'š6 ºèò…ýíUåÕ·¶»-]oˆsærè6[Œ(qŒÔ,ä9/ £žmoxxs¦ ËqdÚ(ó9SæähQ‡Äñp!´ qÊädÐZhCÃå”9#]³hî÷Ž”+¯¾™¿ÌQGž¨ÀOð F¦N÷¯ê¯nžµ<¼I+›¯2M•ád9½‰ŒÃ¼pú 8Ÿ™çL¿ñ¨ZľyŒìok£ÄЍµÌRMVžö>Õ>Ñ4À9;{ðcÎ…i*¨)¼ø‰ãæ¥Çz U!¥ÌeZ+ó˜°eœfÄA•Êé<á½Eœ`ZK*…¦ó´Û–¦ï;xÇöå³1)¨g„aœ ½c,‘¶o)šæ™Ãñ VÈÆi· hȹf •,Œ ~Õ4x< 4gH‰‚åÅL5‰Í |ö-›[Kž3ˆÅTá2L¸à)±"Æ’bÆG΋âN.™RËÂ’áõ«©T¶ûv’91Z•Ðr)´›Àþ¶c»[Œ=RÌÀxKh=â,¨ðx8ã¼§då|™¹\Fv7rUNœŽÎ{ú>дžªBŒ©ŠJe¼LTàx˜æ„ÁÑt ¥ ¢Bœ °¶ÐnaûÌá‚!N• ç!"¦¡>ó;ïçSð)ødŽ h-u8?Ìë *Yð¹*©ÀþY Û;_]P]`zß1=&Šƒé¹yÖb6Û­„ß°´Ì’’Sf8/£¿U+)VT3.xb®Œ—Lw³ #t»@)¹D¶»- eøðú “pw먵²éŒs”\È©`œE«Ò4 LÆh6Žóce¥‚ÆLI•¬Â¶í¸<θÖÐ4–J¡ë=â–ž+²îKˆS%tÂåP©I¯Æ_žŠ€Oð)å )ëå|Ê®)·¡iN˜¦DJJœ­½1fö/;D (xoyõí ³uH…yÎÄ7‰°qˆ(R¥®áü9Òï¬5˜àh—…š„>c¤ÌÛz •ãa"¦‰ýÍÛx¦ó’ÿc„‡û)J»mðÁ3s¬ØÞa½!ÆŒ¢ UwÛr:NëÒRÇHi¦b‘àQîû\˜mf¶™æÎóL³ H#Ü?\(’cD¨Hcy<ÉÇ3I3fç¨ñΘ—BÝU¸ûÂpi"ƒI<Ž~/H n¦áü˜‰c Æ\ã°Þ¢EP†Kƒ–‚Xƒm )e¼\k™Gýª&Žï¼—OÇSðIÀÕcï_¥×¹$Œ7ô¾ErÊdâ´ÜßûÛ~Y +_Ÿév ó¤dw? Ìse~³H…å(øÎaÄqz3Jµà‹feŒ™Ð;²ÍŒ‡„qPÇÈ‹/v”R¸¿?¢E‘Ä)³½m9ÜŸñÁ¡Uk¤ß¶[Pó”ˆo2 ø§ßxjÊÌsAÇŠæ‚bØ¿lqA…®‡ócb· <¼ ²,$ç‚sË& iZ–†Ä¹†œ 5B)Êé1þZ•Ãjüå)x€_¹úÉé¨ñ_YT –$oâó°´Ý‚“eùæÅ,»ùnîZއLMo)ÅCœ”;¦T–Y”i*#”\éû†qÌ §™¶3ˆ1àx¯_‡õý4ï\ùŽ÷ü/{Ýô?¦:ƒ{2îïýþÇn¦woùžÊ]A`Žå0ëí² {݈c¡ ‚·–é’h‡k,—!ѵs±œ‰d— ­£¢ß,í4‹€1XkA+»]Ãé1ÒÞ:¦!/¬»`8=ÌtÛ†ý 5/Ã@¥(s,Tò¤hXÈDo¾˜/3ݦ¡¹YHJ÷3—¡`JÅYH¹.ëÃZKh-ê-N„ñœð½¥˜ÇŠ"¤©02Ïïv Ceމã )+Mp”Â"ˆ*K°ÄLKNúú”õÝÇw½ç?äZê_òžÐ'øôŒ]¾çœ|Çs彂žùƒ¼—Ø4•ÇÇCüv³sŸå»½GL¦é ÛMƒxËý·Gú­át­”ϘְÝšÝÒØÞ6œ3ÛφSf¼dj­$…°±\3ÖÁö®%‰Ð{ÆËL•†8D4Wœ]VŠÕ¹’çÌñUc)ZØì—ã©d^}9âƒÁµ‚c<L£L—ˆ›]çxó͈m„’ ”Âù¾Ðö1J. Ö’‹2L‘œ*µ*­5T5Wœ7/ˆ.‡¤9Õ3¿íÿ»Ñ Ðïñìú=у~äõä÷Üï±ÑË0ö}O~$0|ìüï„­1ê«ó}ýÍó—î³h”‡ogßdÒ†­ež#¾±ŒK+l¾$¦KBZÁvp±3Š2}±V Ã9â7†4dÚÞ£gð·Û.{KRR„rœðÁ‘‡ I˜ÆÌæÙ2ž<…9Wº— ‡¯fBc¨D ñ”*P©²Ô-²pùffÓy.o±É0+é,äX1Å1gÌÖqºO´]Gžà7‡3YÃéU$ç‚ï-Áâ ¤’Ø=·XïHI¾Rå‘ßn¾‚€|~ß¹ú@ñþçú‘4B?r½Ÿào|ȘåG~O~„ñËG¼ˆ]ßk_o.õWíÖý£ËבÁb™uYæ;‡3–ãyFDé7 Î ç!Ó‹xƒŠ‚T¼säA™#ÄcAT8"íÖ-²ZYñaÑÝÏÚàP Äe´w·ß2Ò‚ž”ñ’hpôÎs~É'è¶B>Wlq”Y±³2\èûßy4Vj)”YI)³Ýw¤¹0żX¦®ûÔUÏå×9sx'ìwîbôúÞ5ÑùÇÎ}_}@ÿ5¢'øhìïþc¿þ±QÀûÀõ1󗯾º¢Ám—å±à|Gš*¶ëë ¹T¬1ìo—”‘”Ø?kÉs!抖ŠõŽÐ/9|ÎKN?;Ñnµ*¥.j;j„à §Cfwë8ÝOì>ë8}3ÑÝ4Ę)yá´YñÇ|J¤¬Ä)œ%‹Ò> ¿±Î,€S¦Û-,AÓ8Š*ͶA‹r>D¬SšMƒD!ΉË9‚ÊÒiÐx|ã±Z¹œgº[¡Ù,Z€¯¾LÿF ¯Vƒµïxÿ›£ê{F¯øúcÀð10x×èü‡3þðÇÎ}×ãÝ盀Š~èwT¨ýõgk”#ž~#œ&vwv—ȃ€ú͆q˜ÆÈî¦a8Î )Ño-iRŒlc1,ÂxÊÌcasãpÖ0¦Œ+JhkU•”*§CÂXÈ"Ø>ðæ7#ýMà|šÙ¼hx|³GΆóW›¬b¬\†D†vOiñ¦©’§H­Š÷Žiœ)³Á:KšÓ4)ã9ѵ-sÌ”¡óµ •ê+ûg×Ã4e̤h•¿ÿ·«ÑÚï©øë÷|]?`Ôïž«8_¿>fìã£÷{bü?ÖÈÍ>7ïTš?M˜÷Œ_~@øîçW&—Sþêë_ ¿º}áÿ0CŒJœÛ|X4ìhh‚'¥Š©²È~£ —L·5¾šh¬Åm#ཡ 8oiÄPr%­íFaÚ ½£í Çofl+ØÎS¢»õœÞDD”*Êé~äæóEPÄ5B™•\Mc™Î•y\–œæœ—BCÔeéÈ¥àZ¥f‹øå÷–¢Œo&|up>'j.ˆ~·tB0äYdžþ™åü*ÓX^¿óþ[~ÛR}ÿúë0<ý@à}ƒ~×àë;×]¾ãgô½{å“!+¹ßã7ßcèï¶ì{ß7ﵘä@À{m§ÓÖ÷[X9êW)Ú_6[û‡2 9j®ŒçL·ïézGÍÊ‹?Þòæëi˜AÁ8¡*”aáÂlo=9*Ó¤´àË|HÔ±P¬,Ôb'oyU!çÊ8*Î J<v/<Ã)“ÇÄíöÄcB‚!ÅJÒÊpHˆ14ݺ¼Ã(‚býB^ÄEª`D…œ„2šÎâƒGKhÅ(M'T5¸`qÁçE-ÅŠˆP L‡Âé¡þ2g¾~Çðý ¸ïyÏ?”¯ëŒócðþÇúð~KFz÷gä½k]?…(à÷¡ø}^Þ½gøæ=`xÿ܇^ç/“ûóž×°ë €áÛ_Œ_}ö‡ë-% íÞ£R™O3•v»,ñÀÁ͈Ë)¡(Q3®5  i΋qWYä´3Spb) ó}$ô¬€@Ju× §¯f6Ïî3bƒ¡¿qœÞdâ¥Ðn qH¤ Ó±à‚b¬£dƒë„t.LJœâ ¨2 !XðÑŠxÃåœñ_é:á"Šq Éb#Žå­É ª²L)ê/Tßæÿþ#-Øï3°¥ ùëw~}ϰë{F.ïÌ'C&ú}©èwx~á¿I yÿ¼{/Ô?:„œò -ß\ XV*ßL­•h¼[æøÇ“¢µÒ˜Jž S® _Þ[ÐÌœÒ)t†aŠXc©¢tAK%Nd©!Ô*äam%Šo ó˜ÖÈq) Dˆ1ã{»äý±’¦D­p| VŒw„­g:Gì,¤q¹÷ó¤ˆ[Þ¦2)6XD–Á :×·ƒûíŽó}bwÛ¢©b" Ï?E¨U¨YO‘voq­çÊðX¿ò;×Ä¿s]ô×âc½~ù€—~7Ï×£—wžkÞù\>Ð:üPŠøÉ?ExßëšTÜH àc`ð¡¨à‡tô#ÅÂwkñŠÓ¡þÅáMúųŸø?©y Ï•Bœ¡í½@3Î Þú>0_*±F¨K¾ŠÒÝ çS¡ÝÆÇ ªkØl-y¬Ô¤äTÁ-ú€Æ.ÒD³ˆt<¶Ï)fæ³22íÎbÌgÁ¤‚!Ï0äBFI‡BcÁ)Ä“bk^¨F)ŒƒôP1³b8›Éb¨ ý¦ÅåñÛHÓYŒ_OœPbň0Ÿô¾¾|¯m÷>@?R|ýXëOß‹ÈÞßË{׺ü€Bñwµÿ¾ïûOðW<ô5€ïj×}_ªð®áÛ÷å}À1ˆä#ž‰÷ Yøæô¦þêùð'H³"fq2‡7#›\ØÜRRT¡ånßóëû´ìè—¾| ŒÊ% ‚ˆRL%j%ÕÂ8¬@)‚µ0GE'¡ÜGœ,!·ÝLU†ÇDè-é§‚m-%)±‚í„áñ‡½1$§ÄK¥–¥e9 ‚#XÁ¨’Ž-/K²µB Î.©‰VEœ!͉ñœP1ÄXénókýE)úåz]м 𼬾sýÊ{çÞ ãe½ù÷MýÀý¢¹§*?œ9ø ¸èÊÓ—÷ŒÙ¾ãuÌ÷xu>”:ü˜ ÇüåñÞÒï¥T¬µ¨J®8k‰³2Ÿ"³5lö­•Ý>03ó¨øNàõÏ_C•Ó9aÝb›ÎPæºHí,Ó©"*Ð-ìÁqX¶þÄ©2 …ö™ÇK^y¯ä,äÇB³5ÌG% …æ6 ÖXâ¹’[C3ªŠ’WÚ5Ž~¿0ýÊT˜‹â[a¾dr®TPÅ7†4)ã©þ8¿—¦Ùã¿ïíßäшëG®¡|OíçÇ,(Ñ'ø!ïÒ{; —›ûƒ¯Aë÷Qþ»(½""ú‘¿Cdùå²þMæFü] ð¡éwR–ñXÿbõë¦×/J^ ´–eöÍ·ŸýÁ×,šúLJc5‚óŽói†º¬Ì]*ò*Ë–ç!ž•,,t`UlkÉ#L'%ÏŠs²° ‹P§U’L–­Dš”qX•YZ‰Y03šÁõÖ0ÞÏ8o1a ˆâ¹RŠà¡ k÷Àз¤#Se2ÖJ\Š’qÊkÈ©’³’¸¤X¿|ÇàíGŒI?ÒzÓ<*`Œ1¨.cGªúþ=v½ßïèGº|ÇçO5€¿.@xÿ"}¨¢B°}ß3 ƒÖE>^ß9Êõµ¼÷¦ÖªÆ˜êœ3€ÖZëjðšs.Æs½I#¿ý0ª*€cÞXŸûÖØk­ò YÕJ©¡”úêò¦þªÛä/liß Æ-Ò^‡W3¾µ`ÀŠ`Œeš2©(]ˆc\ÒgHƒ"V©E)iQ 3ÄqPdÈKÐ (ÄQ©%¡æK¡F ×â©R‹.^¹VšGk% ¶±Ô Óa’ šIеТ*L‡‚q‚&¥sž9/ºibÙ~d–j©KÝ"ÎkÁwÂéÛú‹åWÖ#"ÖZÛ×ë· ±1ú{@€ZJ©ï÷‘ºÞ ¨jyç^Rauº~­9窪º¾ÎÛŽ€µVuñ *"Ú4Æ5¥Tù8}øw>ßÁ=À t½€òOþÉ?á/þâ/øùÏÀO~òUÕú“ŸüĤ”dTµNÓDÁäœk­•ív[J)䜥ÖZJ)”RÔƒsÎÌó\­µrEwèz1«7q"‚ªšw¾ÿn áw¢U5µV_ra³õ—ÃIÿ»>`jñ@œ5‘>Ä|6U‚1T£è V=5-dE0F©²†(F/]!GY§ìI¬^ñÔHkÐ !_”t.¸ÞR¢bÍ’¯×¨ÔÄ2öKe¾(5éò3³b]]œÚEÔCªÅ¦¥×ï« ¥R3Äaý;ÄæHJ±†+>5AŽæWÎøÔ´ÖXk±ÔÕ彯”RôjäÖZWkÍ"RK) ¨1Fô·7Ð[ç "ÕZ«9ç Tç\‘ꜫÖZ½\.UDª÷^EDSJÕ{_›¦©Æ˜:M“¶m[/—‹zïÙn·õîîŽõ¯þÕ;·­>EÝUÕúOÿ)wwwòçþçxïåW¿ú•þ›óotÙl6ªªUD8FDÔ9§¥]/šÎó\çy–œ3€¬^ZE¤¨ªI)­A€^ÁGK)\=¿ˆˆªšõû¦Öj®çj­Æc׫oÖ¿Ù®7„ÔZ})Å[›Ü4Ç_N§ò•îôº%%–Ü»,E²qŠÜÞõ¤©Pb¼bœY$¿ç%´§B–J+¾³˜ª¤AúîI1ˤí²g‚°B·¤`Ñy¡§‹â7K‚¶¬.u¬ë~3!=L¼¦Ë¢ÜkT(Ãò±!ôçíÂ,L•ÐZÆ1Z»ìDŒ‰4e|kH£.*ÃA^•Ùý¢ëƒ ·Þ{¿†ìú®§¾ðÕõzWk­Š,Y)y»FÌ£Î9©µ–Z«:çpÎÕc5ÆTU­Î¹ªªµišòâŋ꽯ªZ½÷õr¹ÔÝnW½÷ê½/Ó4‰s޶m¹¹¹á'?ù 777ì÷{þÞßû{ü³öÏþÆVÿß5¦O±ýÀ?ÿçÿ\v»Ó4Éårá_ÿë-€ÇQ0ÖZs>ŸMŒq§ÓÉ8çÌår1ã8^ Õ–RŒªºyž­ªšœ³©µZUuªjk­¦”bK)o?l­ÕÖZª±9çëç¦ÖjVp1×áúZªÚÎó¼;Æm¸IÿÃþYþïop^)¯‡Ši„V\kкÔò¤ˆ]Þ~Õ¥÷OÌ:¬kÈi\¶‹T!Üò‚1øÎ23ªPj!ÆL-ŠÁPëòû­­L'ûÿÔ¹ûß÷›æšp±ÖŽÆ˜º‘r Á1eãlŒQ©"’k­Ù{5ê”B²ˆcL5ÆdcL1Ædç\uΕœs !”Zk6Æ”¾ï«÷^²ßïë4MµïûºÛíjŒ±ÞÝÝi×uB¨!¾øâ‹ú«_ýJÿÑ?úGüãüèˆòSð# ÿí¹?ÿó?ç_ü‹aj­òÅ_ð³ŸýŒ‡‡ÇQÞ¼y#€ñÞËýý½8çL­UÎç3ã82Ž#¥,ԥ癣Æk)EJ)º>jÎYJ)¤”dý¥$Æhrε”"Æ]†Z«”Rdˆ+¨ˆˆØõ{FUk¿QúoK_þ>ZîR2¸^(Z1ê–Í=©âì¢ÔçºxåºxÕù’qŇ!/]§ä\—•\Å Vck­‚H—Š:–H¡…2/`§ŠÝ¹.w‡!M‹ñÛ Ø° p-È™®ëhÛVJ)æ|>Ë<Ï&„`œsr{{+"b¬µæööÖÌól¶Û­ Ã`×bŸÄ­ªJÎYRJ&¥drβFö!Äeš&)¥0Mó<ë<Ïvžg†A¦i"ÆHŒÑ¬Ï“iš$ç|}MWJ±)%ûNW@k¬—ËëôóöyùOY–`•¼ÖrR”u,·fb¶4Ëœ i(HYD?KZÃtiR¬ƒ¦‡± â¹`[Yöû ‹èGš âÁ¨ÁôË(2výݳbYº T ¡1¨Â4‹ß8T ƒñ¼mMR  œ+çüüS"`¡D–â¤]ó¾ìÃæa³iµë:íºNœsÆ9'Î9k­Uï½Zk­÷^Wƒ¦i !Ðu:ç¤m[Ú¶Õ¦ièºN¯ Ð÷=!ñÞËúšWð眄®çœªÖœ³4M#»ÝŽZ«„ª1FÖtC¬µ2M“6MSÿðÿP½÷õ#•ï§àäý?„Å&âœãæææmqs†k»ÎˆˆqΉ1Æ®¡Ÿ™¦ÉŠˆÄ½ˆccŒÉ9›ã2¾›³É9Ë4M¦Öj¦ibš&3ϳLÓ$ó<Ë8Ž ÃP§ir—ËERJ Ã`Æq4Þ{³F6¥äRJÖZëŒ1n­p§Z*é!ÿ*žãß2MÞûÆàn„é´´ÚðK¸^ôi·Ë&Z”䥨©K^_æå>×v¡P’â´®-©kqJ¦i2ªê¼÷¦”â¦i²ªÚcàUÕ¯ùX?zk­oš†’‹æ”s9Ýþb<=ü]µ®t¥ ç³¢UVip°ºlÞ¦J*yY÷ÕZºg–<ÄBMºä0‚ëç…ùT °î¨„]ÚwÆc¥é Ö.}­ëß`–â—!štÉ„­EçºH—a°NÁ2Ou‘ÿJ0­¤£:*YïrÚý¦ßõS×wÚ´zïsΊˆ·Öb­ÍƘk…_s~eï9!„P®‘X¡6M#k;Ðt]—×´¡¬¼ý²zÿ|e–R4„×k|5æÌoEAê;ŸëwÂw© ÿPx€ï‰>öÆÕwŠ0W00ïþÇ‚ ¿U›}{Îcš¦)¥Sku€[gªªÖÕ˜©µŠªšcÜš6\yÿ.ç|e½²µÖ§”üzÞ«jpËa|ðÚ´­Æ”cv_Éíég¨®·äó®[¾n¶– Ì‹2Ï|QR(Ì^­[P0,½xÛ eRò¤Ôµ(¶†4+*K ¡¦Š6‚o†^Aܲ ¤äE›díã/}ýÃ7#b–zÃînÑ.(QÑ %/œ„:|o˜'ȧîͦëÏM»ôç­µÆ9çWFßÛ\| ѵ”¢kÊöîl?k¤púªëcú€Zk͛ͦäœëjèÅZ[¬µå†þ!¯ÿ1ÿ!ã¯ßò?¥ …ym¿k$ø]±†I…½¯8û;k­²ªÚkÿþ +PW£7Ó4™RŠäœkŒ±¬Ïa='WH)]iÅ^U½ª:q€[zÛ¡¦JIíe|̯٠/‚W\/Ø y\ ¬*ËàYëv© hReáÚw‚Í‹õJÍJØ ÖXæs&Šï³ †u  ¦³be™õW]*á¾³Ô Ó)‘ ¨¨ y„vcÈã6“,]„O]»L9š¹¿oüö±ëÚzí×;çü…×ø•.}5j³ÎPȵsej®ïµ6MSK)ˆ"’€TJÉmÛæRJY‰DWãÏïy÷wCøüãÿ«Œ?‰‚þ{j‡õßàÃ3û…ïÿüàc¥ò¾Kéu)%ctÃ0ÔËå¢+àúpÓ4é<Ïå:p”sfeÊU\ Av-Zqët¡„ÐhéKå¢çqªM”qgh\+¤qáá/={°[ié°ŽkY(¾I ”‚¸E ¸ŠEJ^&7f™"dQïi6B>8›ejP©ÌcA³2_âÒη ¥¸f¡(t{¡Ûây)¢™*ˆ_Â1Ð6Ë¢Ò:v§ÎoÎmª÷®8çt­¹Àªª_ ®õÚY?JJIWÒ–ª*kQ/«ê콟œssa¶ÖfïýlŒÉié¹à-|‡§/0ö÷øŽ0ÿ“Úð©Àw‰oò‘ZÁÇ4Üàã»~®ÃB¥;ϳK)åRJ¾\.aš¦:Žcž¦I§iâ|>3 ƒÇÑÄí4M¹”ârκ2¯3f%Ù5 xÛAXˆ&¦´m[J.¥L›ãt šÛù&— fi¿U2éÛÆ5‚sJ­ ùmO“uyStüI§¥“eŒ '0ÍúzY™/P×F—,#€ë0Ñ%1 ‹îŸT°Bšn)V¡5”´Ô'b)HÒ¤ÈÜŸº°9µmH!„²RuÍÚN»l¹zû5b"ç¬kj€1¦Ù§iJÖÚhŒ‰ã8FcLtÎÍ@²ÖƮ릅ґëúsÅ“>ÏÈטˆÁÿ÷ü¿L@ýŽÈàû¶Â~h«Ð»Â“ïÖlÎÙ®C?ÈÎ9³zùº’¸\.qGs¹\Ì4M>Ƙçy.)¥c,)¥ëœÀµn ×úªÊÚ0KóÁk­­µJÓ6EU«¢Óô âïæ-Z4àD¨qõêE Ý2ºx⺨)€+ˆ]j Æ šëÛNº0ôTÏÍ"Š„•åùµèʺZDGleÓиL&Z'K!&À|*KþïLÕK‚é/Áû²ôêÚ‡¿êýëZ71+Ê:~1æ ¥”’1%¥”E$c¢1&Ã0;çæÓé­µã8Že†”sÎ}ßgcL !¤õ-x¿°WÞK¿kOà1ì'E ÿ–;ßwA>Æ-ÈˆŠˆ¸RŠ™¦©ù|>ûišô|>›aä|>3M“†Á®Þ>眣ª†Z«[óZ]UfV6ÊU[àZL{}\é¦Î9B‚5Hœì9¹qÓÞ›SE̲·f°MÞ.#¹ñR—"œ[ÄBµ®^ß(µ¬Î’ï‹»~-P׿}«p²„ýl€2/µ†Ð-=~aÉùE—MÄb„fb]ÑC7ø¦‰mßÔBY«ó¬“}fm§ÊZg)ª*¥±Ö²¶fUUsιˆH±Ö–”R‘h­ÍÖÚdŒ™‡a˜¬µsŒ1{ïçaŠˆ¤yžKιüä'?IëXðéÙÿXcþ$W„ÿ¾mÖ¿díàýHá Àv]Wj­åññQs6ç\Îç³òÊæ“RJ\­5«jü*)U×óU´B×k-µVY=þ[Õ3Ê"ª×ˆ¡YŒˆr™ÞLÁísƒ©âC—±Z‘u0¨:gUÞ¢”¼„ë¹*F—Þ¿3‚–wÞ »DâÖþ¢.ud}S4.E¾fo`]®©âúeuxu‰0m6±»4}(>øB¨Þû¼¶M¯ðö=¸~}å_¬ÿ{]ß;½ÿäµ8›T5­"©”RrÎó4M ¨›Í&NÓT繬´ßï õ/ý?ø1L¾'’xê8Žv»ÝjŒQû¾¯yÑ3)¥Ü¶­1R}1]¥Çj)¥^éeïˆXHJIßiÊJ6«ÁK­ÕXk¯ C²rÔY_£"ól$ß§ZüÜh_ŒiU4_vc/Uñ[Á&(iiÉ‘õ‚Õ¥X¨iù—5CUÅú¥°ˆ.\Ó€s‹@¨ñB³[Б鲏ErÌ8,L[$7ÑIHÍÖ—uþ¾¬J:²ŽìÊ5ʹä¬=þ·ž ]ÇrëJÊ*ë4`±Ö–µÏ_Œ1ÉSœs%ÆX×É¿’R¢mÛ«òϵÊÿ{•Ç?À_o ცÃMÓè<Ϥ”ðÞëf³‘#§ÓÉXk¥ï{Í9W©ªªë ºNÓ¤!„«x$+—À8çH)É: ôVgðz\'¯ÇÊ]ÿ­Ð…3&F«irZŽÑ–)Û2Õ`1–°7‹ÆÞÝíÂÜËãâÉóšëYòuVÏ®y&Õº‰ó`¼¬EAÁµ‹ÿÔ¢„\ññ,±µ\Btâ‹k\i‚/¡ u5T½†þWc·ÖÊ:|à º‚ƒ¾óüëÇ꽿¾V !Ô¶mëf³ÉMÓ”uŒ—¦iª÷žÝn'›ÍFû¾×Z«ZkiÛöCK>å/‘ã?Àï!|gD°ÛíЫEß÷z¹\¸¹¹Éã8ú+½t’Ô”’ÃPו:çôJ$J)ek­7Æ\«Ûê½×U`D¬µuUÕ£Xk‰1^¿®^²,Þ±£'MiLCt¦ÍÖîÕ”¹š² |*‚k…tÁ@™Ž~µà7BžXž–E"b¡~›*˜E[°DÅ š'¡ ¶htEÅ—¶uÕ9[W™¬·Ê;«W¿€®Ã9ºÎô_?WçMÓè:þ[CÅZ[V1Î콯"RÚ¶­]×Õ¶mµëºâ½×¶mÕ{_×™‚º¼v]§+h¿»&쇶ðžà –:—÷^îîîôx‡²÷>6M“¼÷É{Ÿ½÷1„V0ÈÖÚÜu] !ä¦irÛ¶¹išÚu]iš¦´mË~¿¿vZhškíÿǘë?À_> àÝVQá­î_)Eoooõx<^Ãø:MSõÞ_{ÿyžç<ÏsN)Í«w1ÆyUr1F›R²ï†¤UAHRJ”R® BZqÕœ³æœ´”Zc,Fs!×ä‘"¥F£F•šM¥H©…’ª**%•º²5çUÎ<EŒÔZ0XªVZgT#Æ ÆXu`¬¨8#Öºj`‚ñj«VlL6ÒT1Vƒój½-ÎY]ÀÑTç|¶Ö¨÷þ­1;ç’÷>] ß97{ïãz.:çb!® ×ïÅÂüTï}¹ªó®` µÖëþ]S÷;=OÇü0ÏÿnޏªÄê8ŽjŒ©¥Ýn·u5þÒ¶m !¸”RÊ9ÏÃ0˜« ÐJ(bŒ¬ÚƒfÕ””ë#¬`@ÎYçyÖ«piÎEK)R²Ú3ªÙU;clvجK_®h.Ôh©5ÇMš3)g‰±HšcUTb*RK^ÄÿµªÈÂRY Œœ÷ê`½ÑàÚÆ« ¶ hRQ1ÖX ”lªQ_ MV\qÖ¨uV³y­ ¤Õã'çÜÕ¨çõ‘VJotÎM!„)„0­Àp}ÄB !Ä®ëÒ $¹ïû,"ºÙlj­U¯²àÛíVsõm^ž€à >¼³\ G–eûLíº®NÓ$+”Ýn—WmAãœK)%3ϳñÞÛ”’_g$ÆhcŒqÕäZøË9ëêéë®õ‚k­ ÅjRN¦ê°³›¬ZF)9jÑ*&Æ$9âë`½iB!å"E+Ô"9UJ͈±¢ª””‘•$"‹N_-jemǃQgºàñÎZ_5´Þ+ÖhV¬uZ«ª·Á”"NjSMm²3›ä¬‹Ö‹®^¿xv!Dkí콟C³sn¶ÖÖÚ¡išÑ979çïýt¶m¯@€Ô4Mjš¦xïóºÄ£ˆHÝl6u5þwúþ?À9Þ'~« ³‚€LÓTDÄäœËª0cJ)QDlÓ4¬:‚Ìó\ÖÔAVfZ»~I)•RJZ =¬…Ôs9—RRÍ9›õÔ&½tX1¥z©kŠíõ×HŽIbSìçäC6a“k)*R×úWIÕe_¡¡–ß´*ÖÙ…DEPãÞïÚ†Auê£[D9«sV-¢j„Ð8]–© ⬗`¶Õ±|Ó‘½w%„0ŠÈBHÞûÑZ;[kgçÜàœ›s—FçÜ轟ךÁä½ÖÚØ¶m !$UÍMÓäU·¯n6›+oà}EŸ'ïÿ?* x÷fyWwàmïyqÎc¤iD¤6MCÎùÊqÛXQ´9gUÕ’snSJ¥ÖÚ¦”r­µ-¥„SS«&-2ÅrÜù~£êL©]UºïDo#‚ë8ëétr"bsnžg'"ÎZëDÄOÓäk­¡”Ò\#…U¤ n'‡á—Ï~óú_~!R6Fœ‰±úZÅ¡ÕyïÝ*5æ±1W[çlcœs¦ªZ-jr-"£f•®¯* Ñj­*Ö ŠeYÏ ˜\J5Èu¡¨ ‚ j–žºŠ±uÏ­ Õ£Fl-µTkL©PTK5Ö¤`´dÍÅɹ”dɵ–¬ÊœâœCã0†ñÙöï~õÙÝŸ½®u®*õªæ­µ×vàUÝ'ÕZ¯y~òv»Më|ć4û¾K›ï馀¿|èóJŒ]çü‡ƒ7ÆXçœ]÷¸•îïj­Íª7hs®ÞÙÎ|ûøÿ}ñ›7ÿŸÏ„Ò:Ó’3Áˆ8[ë2/cŒ³Îù&&l]v…Zƒ¸¢Å¢Ö£Ë6b5†Z Öˆj1GÕº¨Y#9¬±RÐßþáF4æ²ÊµF´”ºr…LUj‘–õÄË´c±ѤZ´mŠ7¦Ä8åT‡,†,BŽsNbÈ 9—¹¨–üòöï~ýwþàðJLM¥¦j­©"2¯ƒ€Å{Ed™.¥ÜÝÝ•uðÇ4ú¾K”ó醀¿2| Þ1×!Ÿœ³=nåñ[çœY¹>ø`ûvSþõÿãÙ¿ýÍÿùóR44®5)‰oBouѰÆ:Û4­m}ïrª2ÕâE±FŒ©¹cÅZ㤀AÕqÞ UM®ÙhURŽ"VP­ƒjýíS5‚–‚u®U,„*˜ŠRó,BÉZ¬HÅPµ–ZTK­9;çç9o»>I-ÕZSRžÊOå|R×ú<ǹ Zk«±¥üÁçÿoÿìþóoRŠˆÑ✭ëh¯æœëíímqÎåõýü—ÿ>-¾§ý þ½Á‡ÀàÝ´A3ϳ;&„Fœu²é{ýù—ÿbÿÿú¯ÿ«/R®¡ñO0±Öù“XïMãvÆoÚ®óã0 Æ8­Õú¤äbÌ"ác@-Éq6…b*Z– >ƈ÷NTU±yÙÔ»l#5¬Ê;cDµjƒ–¢¢µ¨£Æš’SE«3N}h“Öe¿‚ˆÔZr­˜ã¤ÖKjÅWc¨ÆÚ2Ç”Ç|:?h©¹gËp9Vc ¦‰éÏþðüê?ý;ÿ“ûóp‘qêÍ;6Mó~!O~„Ñ?þü„wÏÙëMý_ÿæÿÒþÿoÿÅOµ¿ÛÜÕ&ìÜñq¤o[S’]wgƒ½5> ÎJ¢HÑb‚ F+Úö›§IbšÄz19'I1ªub­ñ‚ˆQPkì²Ë+E+‹í+ÖXrÎ`‘g-iiU.Z Zµ¤¤Y$B–ïiU´¦)i×oÕÛPç)Uß4užG5"j‹¨uR/ùZêyxÔËôJKI5ÆIsNØPÀ]âößû_¼úOþä??ó[I¶Iu=ýüƒÂ[ŽÁW¯ÿ•üïþOÿ«—Ço6·û—ÅGšŒ¨ R"¥·Ïo¿X'Á'Å`ÀHŒ#Î!©DÉ5I)Qœ÷X±¢¨n7;«Ê"'"N¬±ßH)…%Xþ-ã,ÎYRÌXc˜Ó¤F ¾ñšbbžgu΢Ëú\bœÕ£Ó<©°N5£U“Ò5½Š6*F´• Á9ާ#sLj­)Îî¿V•A/ãEçyFÌ`}£Ãÿìô¿~õ÷ÿÖVøaJNOÿŸ$ è0ôûø_îùõÿýf·ý\sIJi$ŽZ5fÛ¿Ô6]Ä=Û®—s91×YÄ!)䜌uË«†ÐIN ï;)%b—дbXT>E–Õa1FjÎ4MGŒ>æ9¼Ç9O©E©yÙB ¥HʉªK® µ¨R‰1j-I½ ¤\¨¥Š’Ë\&5j)ÕêËÝs½•[J…Ë0RR¡i[)5×ã𵹜4ƬUf Ýì6íóãÿüú¿9üôåòC5ŸŽ¿äñÄü÷{èG¼?€þ_ÿßÿ¥ÿ—ÿî¿òŸ¿øÛqžÎj­×W¯_KI™Ï_þŒ¶÷\ίQ…Ýv/SzäUþ S>*ZMÓ·UÉR“1Î9棊5¶È¨©Îª³J ]¶àªÓišÅ5ôzŽ#[ßKq…óeÄ8§mÛˆ*ªT4'¹T!åL‰™\ m×aÆ)a¬ª ¬£žò‰ÆyMs&æ‰)ŽòÿgïÜu$»ª0üíû>§ª»º=3Öˆ;91±€„W <$–í”  $^€ç @" A–XÈÌÅÓÝUu.ûºN‘‰l«þðÄkýgÿ{¯ýÖº>?|¦«{.‡ñ&*JYú´žµw¡3èäŽLëC£‰ÊJú²þ3|ò¯¿Æ¿ýã/ëÞûõŽw9|ýð‹öä2ßzþƒu± ÓýÂýÃÄ»O¾«ž^?§©M“ï†ótbê÷|:Ì;‡§JDȵr}µçx<âc M ZƒžÃáÀº®’sBJ#îFðvÔÖxºtR^±Æp{¸ÅzÇéx¦õޱ[’O“FÎS÷Þ‘s¡µ‚óžeYˆ!*ÑÐj£ÔJoc->jÉ´ oޝdŒ#Gnìïº'(}Å8Ü 4ïï$Ä-«7Ÿ2/+>*·ƒþø“¿çŸüø÷§÷~ø³K±\àë…_}t †k»ŸŒÆX¡4wojVÜÞ*­µ¤e!÷Ê.Ž„TÊU–ùŒÖš8•SA%½=‡¶MÇOó„RjÛ]X;emjÜïdˆ¦§ÎÓöœÓ2ÑET)]¤6Œs*¸Þ™Ï3K™xöœY&Â^„¦jËh QJÐX^ª—ÒlQ×·žZ ÊlGvï Ö:©¥«ÍôÞXZkñƒwîQ¨í)ÐÙˆ¨+§4¥WØíw´ºÉ¨­bÁ:K“†Uš”K^‰1âœ#çŒ –´¦-ÈÓ*É9+é¼—Z»:½Áùxæ;íûœç…Ö*9%|P@°žFN瓬KÂGÔþ: ‘.ÿ3ò+o#ÓèR)eå<¿¾Àÿÿ k@÷«ÖkIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/kwallet.png000066400000000000000000000165761217176075400233770ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞEIDATxœí›k¬dÙu×ûqΩwÕ­û¾Ý=î™ñLÆž±ÇŽe<‰c;ʃ!¶‚Dvìˆòñ ó !‚”@$$@!ˆ@E‰ lâÄÁ NÆž·g<îžîÛ¯ûª{o½Ï9ûŇ}ªúöÌæ>­Òíª{ëÔ^ÿ½Ö­õ_»DÿŸ/ùv/àí¾¾ÀÛ½€·ûúo÷Þîë;¼Ý x»¯ïðv/àí¾ôÙ'?÷³?ÿ¡élüÏ/_¾Œ5îÙz½þÄÎöö“yn¾õÿé?œ|»›üÔgþ< ðÞžø’Î9¼u¦D ¨¥5fù”ñxBoe%R)$ñ§øBTÏãg BBðë¿ù¯ß´¦Ï~úÏ­ï±Î<æ¼ûÞÒ˜w™²Ü믬þ™_ûõµÿ–Ü{ß=òùž{WQÌGï\|æÞûïã¾óúßùÛ¿øôl2{b<™~­4æ…_ù'ÿ`ø‚üÕ%DDäÓ?þ“Û!øG½wßg­ý^cËGœwëgÿn:ߟ¦µ_X¼®ßp³vžç,ÚƒùlƳÏâœëB@iM=«Ñl5iµ[4[-jY h„€@À–ž@1ÏÑ%5Óé¤÷mÈgyÇZƒ÷ç<ž@’%˜¢À‡€¬öâ¬>ʲ ( )å¦ÒêñD%ëD¡¤ÚÈg­uÿ5¸ð5!Ä7•C©”•R)!DÍ:·¼{$˜ðïý‡}p;çÚH´¦Q¯W·i6›dY†Ò „¼õø@÷žE«ï}À‡Ô‚$¤ßÞ¬÷-k,Æ&£)³IŽ– ¹Ÿ“H…wÎ:¡Ô]@ˆ3Îî½Ç—Êê—bSÀã³Ùìñùdޱöù<Ï­÷©¢£SÕ­Õkµ¸£Mš­­ftçF£Ašf(-Áƒž<ÖÄÛ;g)ËSZ´Œ™=­¥„*ïqΑ$ B‰·à¯ý•ŸÕÛç¶ZóYνçG>ûQþð+ß`eµËtrÂêÎ}$kag§Ì_c><ÀÚç$.$hí«´´ˆ&à.Oñ8ëÈ‹œédÚ›Og½Y>G)E¿¿ÊÊÊçΟc}sƒf³Iš&¡*@]|”® ‰wg B€,ËØØ^gçü6;çv8=>å÷¾òûËÏ!àœ#%!†Ñ[ðK¿ü éßú›¿Ð,KÃæ…u>ý?Î'æùo¿ñ/?ÿ"µ`ó?…),+f„ßâäòÓ„Ñ‹¨b—£c‡-fBF!œÁ Ä…p&I4ë ÞóÞ÷²µ³C§Û¡Ñ¬“¤ieplE‚)Z*¤(¥h6š¬môÙÚÞ`um4Íp-ÙÚÞâ›/¾Äëã×BF.p<ëÌ[ T’Zk[ÖZ´– &c^zí×oB@¥)R8¬-ªŽ^}Ó£÷^hð÷>õ«ü³¯~Ž'^x7x†ÉÑUŠñ1Îx$Bj’à‹Ti½ç÷ÝÏöÎJ)œ³8k‘RÆ,d„€VšZ­F«Ý¤ßï³±¹ÆúÆÍVc‡ƒ)ϾpÌí½ÃQÁG¾çzpƒZš!(!!€s±RwÞ€þÊj3I²ZQ”dY‚‚¢°”E‰`Jƒ3.ºxðx_⊠e9§Ö)Ù¸gžø šúqDyJq|½k/‘¼Jqzb2ÀS¼µËR!ÍR¬µH!˜MçyÓlV£·Òem½ÏÚúëët{+$i“ÉÔsy÷„«×^gÿpÄtšã|@KEðÒ+‡ìl×*f©$Þ{„u$‰jýÈ}RüÇßùwá.Z­V[I‘™²D%’@@œ3Ì&3¬©)âëÎpœCº9B9ÒFŸöIêï!yÐÐθÑ.ÝëßàÚ“¿Åt:#ÉÌ{FÃÛ¶9n›µõ>N—,k‚¬SXÅ回ãö9<sr:¥(J„¨R°h)PJ0ÏK^|ùßÿ}Û¤Y† ¥Â.fh™²L€ò. 4óðÁ÷s< ÜÃôÀSš E1¢, ¥qlo#=dRCè¿H‡,Š(¡B‰h¬¨°©6@Ç#C pëö)§£œ$ÉÂâ"/‘*®+[kqÞ#„ÈŒsÍ7e)eÏX‹1ë:¨Ì8·ž’Öklq›ókÇüÀw+r—rýå:OþË„×7û¼6opãæˆÙ+h¥h6[dí>Iû¢svý!l>%°h£e±×_ðˆŒ–Wõƒ{¹¬'öö‡EÁÅó ­†#U ™ñ…ÿÛäó‚Ï}¿a°÷-nµxéÚ*ϾÚâë/hnßÍ!ˆ_y×Å÷w¾uõ™¿» –Õ{Ö–8'B`ƒÇ– /^êÐïÓï4›¥A'X™¤&RúSÔqóëÔ”ã¡óCyÇO}Gu>÷÷â ¿;]ºt8S. ):Ö ^H¤÷$Þ”ˆ?žšµ‚‹Û‘,77wÞóÚk—PJqw[¶ˆ¤2¾.ÅR`øAàZÉž÷çc¥æƒÇ–¢,~ûïå.Áùõ1÷nqqûˆ ;SZ¥EKª:I±¾†/±ùQŒaEÕµí¬Îù໎ø­ÿ,QbA†‘ü”Zx@‰.ˆ"¦Å<7Ör~#‚Öl¶ùø'>Á—¾øEŒ1(•°hÉ#·ÜA,_X¾Ø¾›‚ï(-qÎEðSzŒ)±ÆpýÖëܸ­yþµ&õÚ9zí‹l®y.´'¬ê]Þ G‡GÈD±µ±Íêʺ|h,p嬵Hë x¬÷”sCY–”¶ ¿Ö_.NJ…s†ñxÂééÑpHž±1Ñ;„II°ÓÂ1˜|óU‹-ghå°U5uåÒµË@ ÝÀ‡ºÔë RÆØÊg%Î:0ŽÐIZMyR(Ò$eg{›Í ò"g>›3O˜Íg˜¢Œ ÌRÑ h™c)Ïp@AI’jê"AHRœ@V†{ó¹’@§ Ý~?f+¢ñÎã\ )Jê>Û;;¬¯­st8 žÕQ²ò,$JjñÇ?þßúìOþ¤ÕI’¶€TJu±qqÖQÎ ¢( H³´"Ä8¾Š.çRJ´Rt»:6¥)c9Zää³|ÙÜTUwÚ €’T+Òª¦Bà*ƒ­”xé‘ÎáœDº@«ÝAÊØ!zë¢‚í¢’–V§ÃÎΛ[›\zõµz-9NˆæûÞ÷þu`¨£K‹Žs.u.D”’Xë˜Ïæ³ù”áè”N»›¤ Y-$6Oñy¬äd¼/i’ ÚŠ4K(Š‚ò*õU!@ A¢55‘`}@Jt±ÐÖc¥@*t‘¤¢A’¥w ·ï"YiitÚ¬ml²³½R µ´†\té¹óç’e „lC*QXk !`Ê*ªøj4ëÑØ2àƒ«Ôœ€wžZ£ÎæÖ:“ñ„㣤Šì|¨ÊYZ¢¤¬Bˆ;i€ h2"ŒÃJ‰UzüŒB ‚tHûï<Ö…¥HeB¢uJ·×Å{®B ‰kJ“¶Zí&‹š@ë¤c½Ö:¤VØ €EÝh4É)ΗØÒb ‹5†Ù|Æ{}˜_úå_äÓŸý“é„ù¼`>ŸG]¡ÌÉ‹9óéccx…Ec zŠJ¨¥(Ò4AWÿW‰"II¢Ñ©&M*ÑñyS§Ö2ªXŒt;u²TÓl41ÆV=ÇéÖÞÞùýßý/ƒ¥Ôkõžsq”dE¦0ó|AU)è´;Ì&S&n‚µkú(Rš­&B€qw,Î9f“©øÌO|¶u!»‹]s>Æ©) ÎØ*çÇ4‡¸Šñ¥”´ÛjYápÈÉéq$F<‡–\U8É3s}¿lØ‘$•’8k¨• ©(u-H„¤Ý¨ñê+¯ðòå+8ï9 xî™ï~øaVWW¹ú§@.^¼ÈÑÑJ)„´š-|ðLÆ“jôÉlÂ<þñî’¥+Èç>Š“EnqÆ‚¥ÑJEf÷çÖDWkµ;t»+15.þ ¹<” „D QµÙ‹`w´>¥bHœÑŸñ·¯Ó²³“#®^¾Ä¥K—ùæK/³º¾ÎÇ>ö1{ì1‚̦3ï¸x‘÷=ú(µZïùžÇȲ ­W®\a08a4³peg£Wíþ° WVVd¿µÞ56²¥±Ñ•Mn°ÕP2ZJ¤ÒÀ7÷®ªÂõZ¬Vc6Ââ<!üƒ‘(!QJ#Áîîuz½.¯TÇ»~˜çžy†••>ï~÷»YéõÐIÂt6ç±}V«E·Û%I¬µœŸðõW¿Á«¯\â7þÍo.7á pp°HÓ4±Þw‚Q•¹RRÌ ÎylÕ¬ «0 jÑbýí¼‡H’˜.ûoQ ‹Ÿ~™ÄBEX è÷WA–eSòÁ?öAnÞ¼E£Ùdck“V§ÍJ¯G½^ç`ÿˆ§Ÿ|–K—/sõõ«ÜºµÇðt„) в@+ux«Wo=Ãá°  ½óIP¡…¨Dcm4ÈäïmdO%ñÖ£Dœ´8ç+¬<À/ÇNQu¤@úJÞ^œèZÖwô¥T¬ }àÞ‹ÀùóçH“$$IJ·ÛåädÈS_ŠÝk×Ù½z«W¯qt8`6ŸEOR ¥5J+”ª/I{á¹Ü„ƒý£Þ€A´¼÷˜êÄ‚|fñÆ/+)룮^¯× âLoi¼‹¦­´ƒ»/±”¦í/K¨ÞišB ËR¤””eÉÞà˜½Û\ß½Îîµëìípz:ÄelŽ´BIMšd‘åEœK­Åé4¡Ýëç9“Á<ãÑ(`k„ ·ÎB˜JVöΓhwžélÂêÚ*Z)æÆTSâè Ö9Jc–çùÄÂÍÏžówöñSž{êy¶¶·9³wó6ׯßäÖ­Û ™Íf8çQ*ò„¢{EBUÍ€±–Y>c:™1™NÈg3¬³¸Š}uš¢”ÄX‹±e @hJ)ƒƒcŽvOùäÿ ŽOÇ1B$’Ø`pÌÆÆ›ëìî^ǺjææE‘Ç1ôÝ›çyågOÑI–ðåßù=¾ñõ§q>ž"*7ÖèD£–ª‘VÑŃÞ3›Í˜L¦L§òù c"yÇŽ³š>9Êû€sñx)ËèÁ‡–R²Qÿèg•rfÐ[)å÷—>—蔦P:SÜÜÝã/ÿÔÏ‘d ßuÿ£èDâl‚3†gžy–x<Ϲ}óÖ9”V”¦¼oßöZìþÝçqÁZ%‘Äd¬ ¼óÌó9y^0ŸÏÈóy<ôè웕hh$bïãq\ã,Öœ‹iJ*:­>ëëdµL^½vMh­ÄÍÑhôÅZVûQ¥õ& _AÍF›ÑpÈ“_’,«‘¦ Y–’&YÔñ«á†Š <^„*ÿ/öÆÉLåg…êEƒR–†¼È1¥¥(KÊ¢ˆ‹÷>æðpÇcý‰×{‡³6ì"@>¤h­©×$iŠVï¶4Ìæss:<ùµû¼Çèw\¼8¼råÊ/NóÉ%)äûU»P¯Õ7Æ£“vZKE#i eµµ5ŠöØc§?ýÓ?=!yãÆ uåÊ•ìøø¸>™LZ£Ñ¨3W†ÃáÊÉéÉÚÉÉÉúÉñÉÆðt´=ζœqR¨Õ,ÍÚY-«I©*f5äyI>Ÿ“—9¦ŠYÀyGiŠåäIHA»Õ¥–5ªBÊc‰Û8ذU!¦”¢V«Ól¶è´Û4MÒ4%¬sskÊS`dÉ~»ÓÚ_]íï­­¯®­­ú««Ç«ýþI·Û¶Ûíq·ÛlnnN···KÀŠÂ"aK@Ú{ŸÎçól4ÕNNNƒÁ yttÔ:<$RÊe©iµšÓ••þxsss´¹µ9ÞÙÞ™¬¯¯Í×ÖÖçý~?ït:E­V;뾋ÇYCÏË[ü&ƒþ¾=þ†¢ÿ.`DY–êääDîïïëëׯ'7nÜH÷öö²étª­µJkšÍfX[[3çÎ3çÎ3ÛÛÛ¶ßï»F£±0êÆ½ÕŽþO}ËÅÿ_þúüÙê8b<s||ŒµVL§SÒ4­ŽÃ§¬­­…Åüñpý‘.ø¿5–ãúdzÛIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/lists.png000066400000000000000000000100361217176075400230530ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚÕIDATxœí›kpTÕ–Ççô#îNw:!é(IŒ¢hpðJ¬B°®)­¹uE™)¿\-ËòƒN ×k•/tʲ …>/Î@ù Æq­@3‚b‚$ M’m§C§ß}ó¡sš&tòµÆÕ®îÞ眽ÏúïµÖÞ{íÕð;~Çïøÿ ághOlmm}PUU}0l]²dÉ!@ÔÁò«Âd 掎Ž&‹År,Ë$“ÉH"‘8$IR³,ËÍ¡PèWEÊd`¼ãŽ;¦}ðÁí&“ A¸Ð¼,ËH’¤•ó±X¬E’¤ñxü‡P(t`ùòåü¤è'ø¼&¡8ø=ùòåóEQDUUTõ‚¢(b41v›Í¶DQ”%Éd’’’Ž;v>¶¨ªz ÿ Ü}÷ÝÇI“'E{^É®œˆ€±±±ñ1‡Ãq›ªªB2™4Ȳ|MqqñõÙ£\DÆH$‰T*…ªª(Š’$éГëÞ\m*Š’óš(ŠŠÇãùûC=´´ú‰h€Xõzýò3f¬eyM pÛd4d4innîöa5a"è{8¶(Š‚$I£>ðKÂ`0ðÓO?9 ÑêÅq¶' >k’$É0 ïwEL&M€‰,ÓŸ¨eY¾l?mk#¯¼Ý>ÁnLJÚÚÚlhh˜f4÷F£Ñÿª««k(hNoãÆ8΋®…wîd^{;î'ŸÄ2kÖdu9f”––Úª««ÿ ËòZZZÀ± 0ÔÛÊÉ$÷¯Z…h2pæÝwñ|þ95ß|ƒyúô‰v7ahµgÏžÓ@Þ¤i@¦½žž7ßDÐë±Î›Çñ'ŸäаðW ¼†X,ƦM›z½èêëëëïà‚fBp?ý4‰înÕÕ1åÏF™7o¢MN ´Ñ?sæL·×ë ²¸víÚååå_Üxã_555½pçwš¹@Dvª^{ò¿ü…«þú×IarÐÓÓã¢@J/ŠâÃ===:»ÝÎÌ™3Ÿ}饗n[»v­×çóm«¨¨xÖápœoiiù—Õ«WŸr®vAȰ{ÕUWñÉ'Ÿ¤/Ür Í3teøK`pu‰Çãib€¬_·nÝ»~¿¿2 -«®®& -v»Ý‹§OŸþðþýû}@ ûì{EQ ŒF£Ób±`4ÙÿÝw¬¸þz¦ßz+•••$^x©½[wïÆP\ü ‰ž†Çã‘×­[·!w‘Ž ¨º¬ëÙ$D€x¨¹¹¹Ýl6—:ÎY– ‡ÃX­VœN§qÉ’%óL&“µ¢¢Bß×ׇªª>z”ëd™ãO=EäðaÎmÙÂ?ý‰ÛV¬¸âj?Ô¾ûî»Þ>úè?IG˜âöää !IZbÉd2ÞÜÜì‰D"Ê”)Sjt:000€Á` °°—Ë¥ïíí¥»»³ÙL8fÞÿˆh±pâ™g¨üÛßèt8¨­­ýÇvxdoÖ×××oÎ Êx 4ÇcÐ$<Ï™ŽŽŽž’’’é6›Í‹Å$ ›Í†ËåÂjµ‹ÅØ·oV«•ˆÓI¤´áÎ;i;z”… þ¼’fa¸øãöíÛ¿ÿöÛo¿~b0.8Ã$@¨©©©ÃjµV9S©Ñh³ÙŒÍfÃh4’L&‰F£D£Qp»‰ÆãTWWSQQ1¹Ræzá‚g×544ü¸wïÞ¯IOý2ŒÒH/¢¡P(²~ýúþS§N­ZµjÕ’$‰‰D‚ŠŠ Ë–-Ãï÷ãt:ÑéFâwò0šàÚ-‚4(Sæâå¾á%&qìØ±Þ¾¾¾DYYÙ,ƒÁ@,C–e, v»`0ˆ¢(Ú9ÀÏŠìV.2´ë»wïnÙ³gO#bQa™´ðgH;©¤¤dvUUÁ`x<Ž$IÄãqÊÊÊp8Äãq‚Á EEEã•mD =|´°CG_«Ï…±®ã5“=µµµ¶ÂÂBî¹ç, >ŸÞÞ^Ž?N Àh4RPPÀ¹sç˜ìsƒ\ÂkuÙe4Œ'$¦2¸j¼æškj4ûZ¸p!‡ü1sÇ)..ÆårÑ×ׇÅbÁ4+/4¡†~¸gAÈœec¼1A0”––^§*ŠBUUN§“††âñ8©TŠX,Æ”)S(,,DQZZZ¸îºëÈÏÏs§ÃzöçÐú\ײ1ž­¬èëêêJív{±vè©ÓéPU•‚‚V®\‰(Šœ:uгgÏÒÕÕE$¡««‹mÛ¶ñÊ+¯Æ´ŠËeËÙ‚eß—Ë/L&º+Vܨ¢ Fòòò2/½hÑ"ªªª8yò$~¿ŸÏ?ÿœGy„“'OðòË/³gÏžQ;ɉå"#›4­~$  €ÑívÏÔÖ ÓéÈÏÏ'‘HH$¨©©Áét²qãF6oÞ̹sç8:¸*œ:u*[·nÅëõòÀ——wIG¹ÔxhÝåšÄp¯ ä•––΃áâxˆ ˜L&, ‚ PXXÈ£>J~~>ªª …¨¯¯§¹¹™³gϲsçN6lØ€ßïÏ)ÈpB6 ×ÖPŒ‡Ès¹\3²G¨Ý l6&“ —ËECC÷Ýwªª"I‡æ›o¾Áï÷³wï^ž{î9z{{sÚÿÐßÙuÙÈuŸV?Ü4<tuuuS \£Ý(f³«ÕŠÅbaýúõ<ÿüó I~¿Ÿ~øöövºººxê©§Ø¿æù‘F|¬J¥r¾ãX }¶¼˜L&z½ž5kÖ°e˦M›†¢(ô÷÷ãóùhkk£½½7Þxƒ¯¾újÜÂkP-oA’$b±@ ÊT›ñ`t»Ý3‡&ANGQQv»n¸††V®\‰ D£ÑL±¥¥…W_}•£G^–ð¢("Š":.S´:íº¢(ìß¿ÿüæÍ›2d342p<ÈÏÏÇåra³ÙX¿~=›6mÂáp ( gÏžåôéÓRUUuɳ—œDËrfúÕŠÁ`@ÅÌÊ/‘H°oß¾Èc=ö߉Dâ$é ݸ È8Àì—kxJ¯×STTDII Ë–-cÇŽ<üðèªJ2™dÕªUD£QdYδ\ò)IÒE3„$I$“I’Édf*>xð`bÍš5Û{zz¾º‡0Ö »±®®®æÁ|Âl6F‰D"L™2eŒÍ¤¡×ë±Z­ØívæÏŸÏüùó)++Ãçó!Ë2v»=³wÐTZ ‘H`6›Q…T*uQ‘$‰#Gޤüñ/½^ïà éX`„¬3α,„.q€ã5ƒ¡0›ÍäççSWWÇÒ¥Kñz½|ýõל;wŽ%K–àv»1™Lèõú‹Ì@’¤Lf*•B–edY&•JÑÙÙɇ~ØÞÖÖVN‘…_4Ž•cYYÙÌü!…&”ÍfCUU ¹úê«9xð »víbîܹ¸ÝnÊËË3š ªjFج T’É$DQ<º€~ÒqŒ‹¶„cñWVV6n84/Š"ÅÅÅÜ~ûíÜÿý„B!>ùävïÞ¹WQs‘3%‹ÑÞÞŽßïgÖ¬YøýþI«}Náal yyyy3úûûǵÙQœì]N§£´´”»îº‹Å‹“L&3Þ=‹¡ÓéH&“™y¾½½UUYºt)¡P(µsçÎäÕ>Á0Çúc5ž}öÙ«¬¬\XSSs­Ýn/¿öÚkKýD´"[øìy^û-‹³Ùœù}þüy¬V+Éd’p8ÌÑ£G±ÙlÜtÓMØív:::NG£Ñó¤#XÃæ4Œ…ˆÕ××Îû€Ò÷Þ{ïŸ-ZT9NÙGîp˜­¬lI¥R:DUUsçÎÅb±àõzÛLƒa„Dë±EÃÀIÒ'«EÀtƒÁ˜ÌÑÏõ.$A§R)ººº(((ÀëõÒÝÝMmm-Ó¦MËl©‰'û|XŒ……´:%Ik@°èõúäÚȉË^@&ØÚÚÚŠ(Š,^¼˜ÒÒÒ‹Î 8r䈖2bJÏX"ò`Ñ2£Ã‰DB>uê0ò¾{´EöŠNÛÈä*½½½ô÷÷SYYÉŒ3(((¸d*îïïoß¾½Qì&–+¬‘Õ«Wo:HgaOÊüXTT”_RRRP^^ns»Ý·Û]d³ÙôTWW³`ÁJKK‡=tééééŠD"!ÒÚ:"ó!@!}>ð=p(`rúúúô}}}úcÇŽ#`¼å–[ÊfÏž]Ößß?%‰”WVV;ÕjÅf³]™:qâDYi0#u6$Ò¾àà. êâ`Ѷ™˜ššš,MMMù€È7æ›o¾¹|Μ9åÓ¦M›ZSSS^YYYl³Ùt¤g€QÿÄ0ѿ̈€ô¦j2³Å4t¤‰Ð4A#ÀLÚä,Y¿óF£qÑ¢EfŸÏ·Ïãñ4“˜I˜•¤v†k.Ö 1q1)&ÒŽ¯—ôx€QLà7—ðÈ…wÖsAK4Bô¤Ž’ö£NÑ¿ErA“#;éKûâï ÿÄ.ï镚,/IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/lists_attr.png000066400000000000000000000050571217176075400241140ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 6Íþ:ß ¯IDATxÚí[[lgþf<Ûñ@HMœE1!@JCYB²m"PªxUjÕíjÑV•xChÛ‡"Ñ·¾ ¾V⩨ ûÒj[ VÙ°«"Ñn›°¤6 qâ$pÌb;&¾Íu2c&_Æñ˜¸ GÉãËŒÏ÷çúŸ^È y®…¨ð·¤Ïçûƒ(ŠT,óíß¿ß@ JÇÿ5$€º‰‰‰!«Õºƒçy0 “Ìf³~Žã†yžN$5J%Ð}}}-_ýuÀl6ƒ ž^Šçyp' étúÇq#™Læ§D"1Òßß?Y+ P«‹”^[úûûC’$DQ„(>Õƒ$IÐ4 š¦Àép8ö ‚°Ÿa466b|||!•JÝEq$“Éü‹ÅF:4%@‘/èÅ}ýúõãõõõ¯‹¢H0 cäy~kCCÃ+ÊÕ° ŒbÂqX–…(Š!ÁqœÀ\^ò\S„¼Ÿ‘$)ƒÁ?9rä8=@°QÕßÞÞ~çùj°Ñàu=.DÓ4†‡‡'ܰXŒ Z0p...ZAÇq5íÙF#?~\À YÊ“k wÌÇ)ña3s)3/Ç ’<ÏkŽ©±1˜ÜnœÎ5 »»û÷×®]k¡iúûT*õW¯×ëËg Zd—QBrzgϞņ –}yqpšOž„uçÎ5c€Ëår´¶¶¾Éóü›·nÝÊ©„+¼-Ï0øÝáà ÍfÀï¾Bð›oÐöÝw¨Û¾}í“i¡nܸñ€©bVÜ€¢0÷å— ( ¶ÎNL< ÿ{ïáP^–t:óçχ éJVzƒæO>A6‚ßëÅK|¡³³6R\iõ>|š™™YÀWê Ê–/¾Apü1pùrMEƒ¹¹¹ €V‚È¡»yóf\ºti郮. _¿Ž††¨3õ)»D0 HW…‡®Ý2— ÉdàóùÆ$çÇWÅÔ¢ÈõE*•â¯^½:.…ñçA@Âáp(‰Ä%ÄçÙ…B¡ dÿl!ÊñEQ¢òwïÞE2™\QˆüJ±ðÃhxûmPëÖ­ <ÏcjjjJ²N·Z@¦—(Џ|ù2:q_ä8„>û i«;Ο_3娠 +ÄDèÚ°¶]»ã~6Å+ƒƒ0ØlkòÁb°¢Z€ f32ÓÓ˜ùôSX_}Ño¿ÅØGá·vûšçápøa<_(æ+f€ÛíÆÆwÞÜyÿ}lùüsŒkª¸,óóó³ û+iˆ”ÙÙYܾ}ÿmkƒpú4b¬pŠÏBiuS"‘H¨ý+f@GG=z´^{ c1ôöö>óÕÎ÷Çq=ÈËë¾¾¾\È1 5¡¸(Šr½ÂIÊmQk5¢@=+å•9ˆ’þù>'B„†}Í]á3gÎü‰¦é}Êt³‘A’WHýZ«­«•U¯¾¤J ¤V ëtNldJýá|ÊËçZ7aV €(…ÓÖ­[ÛÔy@µSáBJæDí´2T‹ L.—kI’Ë^9©p¾•.¶zå¬z>3ÐÓ(¯×»Éét6¤ÓiÐ4 yk¬ÜT¸…›ÒÆÕì+Ä‚r»QZ¢€áàÁƒ¿¶X,j/›K…ýo½…éS§–Ráwße·çZgÊšVÊçû¾$u{®”iTº¹¹ùe“É”»I’A×T8ÕïUÃ’í¿ƒ UÊé• +)Gùb èÅ€iãÆíJªÉ¯õJ… åj“PûBUj9Û÷¥0x½ÞM‡cc¾‹ê™ [ñb Èwr¶ïÉR@é«• +c¶EÕï ‚ynã8¤ÓiD£Ñ4ŒÚPZ Ú¶ )­çôH¾Ù£BP$ –eqóæÍ…‹/þ¬¥¢´:ÀÕäýåRÊ™ñ<å4š¼óÃq\î5˲J?~üoÙlö®Ô^59X,›+U±)(ÇT”u‚l×êsåÁ²,ü~öرcWÂáð¿„* ç˪®(jÅ9Çq0™L«š-’™Àq\Îë•çy£££ì‰'þ‡ÿ `Àc©!"¬Æ ®p€zlxÊàha‚ºÔ•eY ÀeÙÜÊ\¸p!0666`À}OJuƒŠ1€@755½l±XÊNiõŽ¢(æ”W®<Ã0˜œœD4I’?K+@£¥!RŒ¦¦¦¦=W~ÙIíýXA Í"çŽt:@ €H$‚;w"‰üKC–š•/Æ€Éd2µÇãq”ÊVÓQÖž+Òé4 †ÉÅù@ QqàÀ$ vppð¶Dû¬VåK™N:uÚãñ¼ÑÖÖ¶Íétº·mÛæ@UŠ|¥n¾seÔYXX€ÍfÃ0X\\Ä;wàp8°gÏ8NLLL$‰ÞÞ^¸\®e‘äÉ“'/×öµ$B¼tÈÙËb6›åïß¿¯©Ÿ§µþ— ™|G8F<‡ÇãA{{;ìR§I)ñx°A)}¢(ÊÆíÛ·÷ Pà(æùºSâêêê¯=ÏgŒ1¢iš‹16ïõzÒíSact¢ëú6€× -bÌÖ1côt:ýÛ;wîümõ Bø9ŽûéøøøÏšÝ¸Çð™ây¯_¿~àoò­<Á.<€‘J¥â3ã{˜Çq(‹a>…vLn+Ýpëºîú±äwMÓÜÜíÂ\èXƘmÒT“Ið8·{ D£Ñ_\¿~ýžçÿ®ªê×ÖÖ¶…‚€r£/Ö××áñxN« r|Œà§ŸÂ5110ðûýÁp8ü%cìË£££2€gJ½xÀÖÕ5 K‹‹ †È?}Šôî.FWWá¼È!Œ1þ@ê€37à8ÈOž€pÄH™GXZÂÅ!0¾ŠªŠÍÍÍ£f¶r½Þ ¸¼ *ˈ¯­Á÷ÑG`‘ÈP‘a>Ÿe2™<­Wl:Â++ ËËÀÎÎP Ëò€"Õ!5©;22‚Óàhxù^¯·¡Ä`Œ!NïPúâ‹‹‹C­(¥ˆÇã;ùi}á€a¦RUUUÛÛÛ{f¤ñ·3]˲+ YöÖPG€ŠA€¬WÐ9Ž;u‘l6 UUϼˆŒ(Â{éÒÀ¤°A€ûFüSÇÞc5…µ³³ƒˆ%ï3]‡üø1¨(bü«¯f|ÔàìÉ„ âñ@œš¤î݃®(˜üúkQ´Ôö÷÷÷Z`Oï„AÍdýö[¸¦§¡ìî"ùÉ'˜—¤“`>ŸS*•r­°gð]¾\]ýo¾Aø‹/ð†çÎþ (ÊKKü³^ "MG.—C"‘@al ìóÏ¡Ì΢R©œ»Ñæ´ŽB¡kçþ={Àää$ £âôþû(* fffÎ}µ›ˆ¡’“4,…ÍÍÍÕ”W}i|P†›YŠB ã[ž`÷©[u^Æ›äkó{û¶«Â+++¿áy~ÙîJtúàN­~§÷j1JI"¸(lšßëE;˜‘F¤ÑÑÑ…ú/ÏK w²+Ô)0vB€ü~ÿ%BÈ)Âë·îfÕMt2„ùùù÷$I§”‚çùÚ8%…­\¯6Ûìx7\cÇø………].(¥µ›÷C ÛuÛvžá´ˆÁ`p‰·H\'¥°8ïr6ãÿCBø:㜒ÂÝßH;8’Ïç»ÜO)lºl«øo÷γÖ€7p¢ÑE”ÂíV¼“TØ \» °°°ðq}ÓR¸›œn=f†‚Ù—¤ª*E)ÂF«`‡A8#xš1­ÓÝ#õaÐÌýÍ̤ë:ŽŽŽrÛÛÛ›v^†;ØË ‹S€0Æ Â)íÝ*æêÇb±ÂƒîQJ¿Gµ"Ü5gÐNž­Wbæ9Ýò„I~Ö¸®këÍx<^¾ÿþŸdYþ+€X¯Ô°aQo$ÇqÐu‚ tÕ[dкÒÖÉC"‘P>|øH–åÇþ eDônHÐ6v$: pìZŸöLCÍÖ:+©T [[[»ÉdòÏ6ÛUƒZy %—ËU{ 'Þ黽F#Ã5MC:F±X!dÓXùW²*v "­<@ :¹òÝaž¥Ó”R£P(˜‚ì_¨6YÚ6¾I„Ë¥R©ÖÍétIËnyKUUBjÆ«ªŠD"J)fggÁó¼zppðoÃíËvª ÍB#Íf_¾yó&›ÉdJ¹\¢(zGFFέhr@±X¬‘h¥RA2™„(ŠˆF£p»ÝH¥R¯Ö×× ŽPÝp ìïïoÈøÀôÕ«WuñâÅÙó,{QJk+¯( âñ8Âá0¦§§!5‡L&³‹ÿµÁ0'ÐPí±ý@À(€Ežç˽¡UG4+tÔ§¾\.I’Ífqrr‚h4ŠP(3;QJ‘N§­ÛàŽ¼ ê†+U Èðqçø¶O=ægEQP,Áó<âñ8!˜™™ßï?EªFH<ë4öí!͘æÞzžRªår9G+;­f>ŸG©TB(ÂÄÄDQaË IDATxœì½w˜\G•÷ÿ©ª{o§É3Í(çhe˲l9gáŒÁ‹É°,™vß]ðîË.™]’×ÀšhlNkq¶lɶ²¬GÒŒ4š<ÓÝ÷ÞªúýQ·{f$Y~ý<ï³?\Ï#MOO÷ u¾uÎ÷„:WXkycüåùÿúÞÿoÇø oà/|¼€¿ðñþÂÇø oà/|¼€¿ðñþ‡÷zHüË¿ ùm¸’³XÊ5 önãž{ÞÃÎw+9ý-£8¨?ÐN{® ?¬@WH´m¦>ã“oßJ^„4ê™ô¥¶2àGÔV†y¼½{‰'¥©lèŽ;ÉŽ­CŒ)ŽðH÷Ç„‘„É ?®Aú]]ÁÖî­ŒMÏÆ°™—dë&à:è‹}ªk+é7TR ¢ŽU›¡:HÓãõ†P-+ …À¦s¤´&] ck¨¯¬ÀZKòQLcC£ÿŒ(«"m€¥Ê»ÐZ&k« v‚µv54jmÞ –q*€œ­kÀh'l­ V žÓK´1ÉPýzß×8ΰÖb%6†XŒ°H!ñ}©„ô3™”ò«ks³|ì,PŸ R5æZÁDß“ A ÓQÑTPÂ…«@Ilº1Îlm1Æ X RJ¬KYø#^ï{ý €›Mkݤ›ÒÏØ€Rø'½š [U[Q[]‘]2RVMNg‚¹Lj ‚‰§*_U%”1Nˆù0šò¡ñ”@y‚²ÄÁ'ºŽ-Z[°cœvÑÚ cMl ¾'QJàI9ôªXGÜÍë51Ð6ÆXƒŒ£ñ3jÒi?›IeGWUŸ’öå¢\UŨêŠìiBØižPÕQ,Úh‚‚Öä 1X[6 ëV¬å ”’(Ox¡qäoq¦Ä‚) ][Š‘Fk‹±Cï+rË$œ™x½æåÿ0N½Zk†¬8ÁÈL#¹”ŸÊ¦&g«ÆeOMjn:“žP‘Î,’ÉçU{> ,ÅP£µaKK:ù!„[ÑÖ:un¬€) Ö"„D²În{M?j8 LjÐÉáhOæÑE­cÐÄHü„Ië²zVáT cžcñXÇðp€B:²än ¥ÜŒëÈ &`_6™Hç–&ÏñÓKÁ[¶³¬NÝ[V˜2DÂÆ¥p\"Ò‘ÓV¢Þð܉„µÖtu@µÖDŨ»JàyÖ÷ÐÆ¡Ñ÷}<„’$})Í´Ö:oÐs¶UkB9SQÁ 0æ•A¬ò† «ä‚‘¬r VfÕÚÃX`(å¹ Õ¶Ì1JãxÇvŒ~à‰¤z®L…p¶_ z:ÖåQiØD{0üíäoîd%¢iËÚ÷¸B:RÀù¼^ÂXkíAcm,­p p(e"fccŽc<ßÃÚ« ÚWøÆÃó§Ei:4X]âaD™ Üñ¥rúTˆW Ë <‰èéÒj׃¦¡d¤kb„Hi±¡EJ0ò8’”U~9ã.9aíNõ+UÆAy¥—ìviÈ„=âXø^ùµ;„=&Huô°¬ XÍ<áOrxî?¥¢k"k…'„@yªlaJ6\<ÛhíV’§PZabKìÜAŽ?Ja89P\2ÊS™ù|cEÉI,_cL¬Ñ¾tê]+´¯ˆµ&”TÎU©zaK¦À¹†e8xB”FTˆ°Æ•HÙDàq¢•Ày”Ž©c]H8à<gc=oPø.†Q²ãîFËÂO¤”UŽ ØòJ•2qk¥p‰FQú¬I< 8޲yÅQºtcKçs s I*{4¾§ð|G µve^)_:É$9~uA%ÇR®&>Zè¥ð3B¤…‹ñvñg!ëxСõcU°^РQ”©¿ ð’°P–¤p×cZ°hc­BjƒÑš8Žñ<Ø÷iðf¸9( ãâq¾˜?£§¿{Õo¿ºü5Ài€XhR"úÕ¼+YÂ&.•,¾ï!¤@‡Ž}—øF"bõ´‹Ê’amÂÖ-ZKD&1Pò”Ä( ©…cÛR$ncH\èY[÷Ó—XÖâ¢Á÷óçbá¼ÑjïcýæÃtuïC$6XIAØW ¶.Ç›/LWODß@HGg‘t&Jàû búó}ìÙÛMàKÆŽ©fÊ„*æM¯g{K»öt‘<òÍOìç‚ùMŒ©Sœ6©‚úÌ4ÛØÍy³«y÷òi|ãÖu¤ÓqìJÅÊ‚>:nTÖ÷ƒ+}˜Ð)’ éçDZ]õš¤_€±Ei_K­[…PØÒÊ-_‹4þ¸,—L+tc"í´Æ%‚,.¡RÞá0„ýÚR&MP4E¢(B)¯^ö<å)¤ˆ‘R%«ÚÅ„pÜ &aêåktZ ˆ;¦–+Þ4‹-[Û¸ó®uôô©¨ÈÎ¥ʹPQhðEÆ—(%é/DlØÔFÓÈ*šFd0ÖÒÞY _Ô()‰µfü¸jz{BöìëbϾ.fÏÁegçàŒ<òÌ"m˜>¡švthÆÖ)&7„…ÇðY4³žy3¸ãáôöÇþq„ÜZ9…] C)Zè̬ê,!å×y¥âÂZKé_NÕäĸ È^ä©ï)ýc‚W"ùoÈ…[J±jllm‘˜)©wyTaEY£ˆÁ“(ማƒB*…W²çI¤ÐZÈf|b$S„% 56ÖœÞ *YõÂn6o=ˆR’L6M*H¤ÓÔT§="ÇœÙ#Iб#³ìØÓ…õ=Ýü@¡°ä‹– ˜=¡†LZñâ¦vž|ñ™@Ñ_9cA3FÕÐÔœåÖ;^&HIþþ½óQ>´¶ÇÔVyTe`ïÃäzÉÞÃζ~fŒ®à»¿ZG߀+U;žÀYpÚ·¤aKBLl•IBgOoÏäß|íâÎ× ßÛ¥ësõ!Òö[k  ßr”ßzœh† ”’U£cçÇ`= ÒåòLRlQV¶´¦)4‘ÁD±3 ?PJºÔ®R|è†Óé+n»cé”"Š ÙlŠ3ΞJo_‡{™b¡Hà»:…Þî&Vpîéã˜>¥ž¶¶ò…ˆ§W¶J º{4½Ý½„Å<•UáQY0cZ×_6ŽêÀ]㼉9F5ç¸õΗY8g-‡úx~õ!¦O­ãÚåSyüùnúñK|æs˜2ÒUíéÐÜõð>sÝ4ÆÕIÖn iš)¸öÒ)Ü|ÛF$®aˆ0^&…vÈêAÉKBÔú~ê^c}€ËÁÆ£L(µí±Ò6FTJ)±GÕÆÏÝ€#Bú˜$ÚF¹z5T”TºÁbâ]€TJц46Õó¥O]DcmŽOù>â8¤/veTçœ=—#]<ðЪª2ø¾"Œ"*²9N?}"ÆT²yÇ!žZÕB>v½…tZa´¡kÎ[:•Mu<üèZº:óTÕä|GXû#²Ì[ÍØÑ•ÔU¥8Ü]dbcŽö®<6Òô…†Ð@_oHm¥Os}†_=²ŸÑ#2œ;¯€\9‘Æêxx;©”O:¥8ÐÚÇí÷oåÂeã¹óþ^ÖoéfÉÌj6·Å4Tx4ä ½»ŸéõÔÕd’-c.ƒ8l¡½Âª+½} ¶ S^j°òUÄtÌöðç£È@Ñb÷SÞ^5tužì(%C¤t{äœ.†k‚!Ç´ û)†1S'æÍçãñ§wóžë3±ÎÃO¬keÙ²i‹1K—LgÂøéè ÅbDX9sÉL‚Š þøÀººH¥=¬…BQWŸãÒs'òÖ+¦3jdŽ]{ºØ¹»‹'žÚÍïØÁ³/då†C¼¼³‹@XæL­eú¤ZM¯B阖¶ža÷ø–sFqÓ‡»X@Q“­myÖn=Âi Gsë½›‰€#=„‚U{ól|ù0q"½ÉkÉerÙSÚvôJ«<ùg.|[â¢FGFa¹àÏQy”ó”EÓ¯M¬#môvkmHL’p1ÃHȱÒÇ}]-mˆŒKµxz±)£Z;µ÷®kç“F6Õqãe®ÒõžogîÔFúz¨QËì9øþæÐ¡^–9†U,Z2…êÚ>¼šb1D)EC*•âÒ‹§qÆéã9ØÞË/î\ÏýngÓ¦ClÝÕÉ@D[{?öÑÒ:@KK<¹—[ÿ2<¹‡ß=y€ë.O:P¼ç¦g¸û郔â8SÆdøû÷-B%y…LF±aÓa*2ŠIck¸éæ Ô§aþ¸ ½yÍú]½4W _QY•&|tl]Hü·Æbbëö0“ÔwB÷”ºèŠÞ;Ü­øsÐßÕª"oí²˜k­cóV‚à•Žrt2"Éã‡Å˜°Cç&F¼"¢HSUå’3ÆÒÒ¡Y4$?ºo“GW1¾1ÍsÏmãÊ+æóôÓ›èìècÏžVž~+—\4—«Þ4GYO±¹\ƒ¶L_Ï[®\@û¡þp×^|©…ÞÞ<Í@¡ˆ¯Àó _)c¢bŒŽ](Z ذùZ±›ÇV¦"“¦©1ËïÙÁǾö­>ÀØŹKÇÒŸw[ɤ¬y¹ËΙȎ|û¶­hÀ>yí²C¶„aĈÚsg¤&éí£¦ÖÄNè‘[én¡h·QÀÅ_¬ ȳX)Ùôç œkýÚb ÖèÃÖz;¦¡Ýó“}yG1y€á"‘°GÚñû28\a—‹:ïÀZg¢ÐpÆé³Ñh² úÓŠÆÚ,®ïfÉìÌðÁ/>B}]%¾lÛ²tà¡Á|2iŸ[±‚%K¦°ek+--]L›ÞÌu×.ä®û6Ѳ¿‹l.…'}Š…åCCUš©“ë9²‚)£*)ZÁ¾ƒ½´襵­†TWÌžÞÀwo]Ãé‹Çrã›çðüš<¾j?ÿÃfV®­¦²"Íì©u4Ô¦è+h”/ÙßÚÏÚ͇X0¯‘'ŸßOuuš÷^6LWYžºº9NÕˆ‰ ?½—À ýêakß퓃^ÖšRù˜µ R‰‹Ÿ½&„Ñ ¶.=ßv[kZ]Ù®Aå\ºWpç†  cŠÅÈí8Ê´I•PBcêê8ÿ¢™ìÚåVÕÖíGøÉ/ñíÏ_D}~óÈ.yêeþæÃóàÃë“}r†HkÎX:•µë÷²ú¥´ªcòäf.Z6…ºº¿¸}5=]d2VCQkÎkæ¼Åc@)Žô‰eOk5ÕiÆ7ç8m^í‡ûøÓ3{˜8©–5ë“˦~}÷>óÞù´´uáIŸ•k#%DňóÎËïïÝƲvS;SÆ×†iY½{€ºŠ€ñ ƒõ }=!§Î¬bÛÞ< ã²çT2¡¥¡8Jè0Ä;¬Oùç]ðÁßþ÷£7¿ý¤)[ÙØÎgmœ56¯­Ý^«E3H _Ý=,ïÆ±¶¼wÞ ß ƒ3'Ä bGà·ú<±¡“ýây&Œ©'ŒBZZÚñæœ2šQMµ¾Äâ4Œ§<Þû¶ù\yþD~v/ßúïøõ]ر½ÛÁíwmä¿o_Ïn}‘öîˆï}a)SÇVs°­—¦‘ôõÙ¶§›6vpíÅÓhï+’ÍHR¾`õú6|áQS&Ž4 ص§‡tF2yR-±´LlÊò¿ÙÀæ–<»-sf5˜86K6¥SkʳëctR÷¡uœ˜’ .”kÀ"¥ºØªêd…? 1a„5ÆšÝ@Þ Œ²ÀNž¯H¥S® .ÖGÀb0Ö‰X#X0,³Fúôõ¹¿×ø0³)àžg°~óFÔU2kÖh6nÚOj°‚(‚Ë/œÃªU»ð|E6“Æ Á›.›ÇêÍGøÆŸ`Þ¬Q\~þ²Á;®EwïÿøígX½á 2ŽÉÏ—( #*Ȧ<ÒÙ+-¿{ú ûøÔOgdC†}-Ý äCþý敬Zׯ[/˜BuU £ QdÙ¼ógžÖLXŒ“FO«áœ…ÍlÛÝGM>zíl¾ýËõìk+0P°Ì›âdµúå.:zú¸ºÆ8.ÅaH6ªh°FzRÝd“p¼ÑºÑóRË^3òy«±vÀZ{ÈZ»»ôþÐU; Çq¥”ø)ŸT&E —íBº¤àªB]ÒåQŸs1ŒºÚ,›÷»Ôö}+²r}+ïºr …bž1ãØ»ïéŒBÒØTMÃèöìë&—Í€…†Ú –Ÿ3…^Ø…0‚GÛÆÚ—[ùî/!ö¹å7/ñ=Èç#ºzhn¬d쨮¿n.™\Šk.™Â;.šÀYóš©NKΟ[ÃçÞ9“w]3‡ë¯žÅû®æ. IDAT›ËŽ}½,œV±1q"•fÿn:»‹„:¦X(†¯ÜËÚ­í¼°î kvö3±Ùç“×Ïæk¿XÃö],šâø€Õ–X·âµÁ™¼'”V)-^ÊÁW‘¤µF-”gÿ9¶²ØÝf¢¦ú¼oL{línOˆYƒÎ ‡ÚoåBª¶”ò ‘Ôß»J®rŒµIjë6h‹/õuiÎ[4’ÖÎÕÙ€ò|ùà ÙÒ’§¨ Õiòý1™œkÀ8Îx<)èî-P‘óé/NŸÕÄŽ]Gh=ÔM./ÄTW¦yð…V6ojå’ó&óÔª½ôBn¸âbm8﬉|âmÓˆ†²`’ ×VúðŽ Ç—ïéÂùµ@-{:-Ûöòü–nÂBÌ@!Û¶aô¨*fOA±3rT–q£*éèŠÐ/¶pçƒÛ˜ÿ‘ùÌ—cbcŽŸÝ¾–Kœ@kg?ý½!©\r63A !…ÇT —æ´´kÉý”¾\~þ{oûâŸ~zÝImsø—fÌ¢¯Ș^ŒÞh„¼lh-ã0 1*Ù`ŠócË…I…—†+ÇO2‹Z´õ(¸¢ÎcÒüüž—y®&ÍgÞ᪞tû‹L;’lÆGII&UA_~€™3›Y³þ@¹>Ob˜;£‰ç×¶ 0ÄÖ ­àÊKg’ <·ujøÜÏ$ß_ಥʹvÃ÷»šóã¼õeáŸhlÛÞÆŠg÷ÐX•fùSظ½ƒ¦‘•H©8cîHD X¹öQ³cw1PY™âå-íìïÒŒ®Q¼çšS8\ØP>æ¦=L›ÞHW{o"tSx¹L"s‹-¯6ÜÄ2Hš¦”š¬ÿ³Ð_<©T]Ÿf·¦ËHY;4|<Žr“‚›”h m~(Kô’EÂÐ…V$Ðv¨—¯šŽ/ ;+_ØÇeϤõp·ÛJf5R*j«žÚÝî|~kÉåRt‡°~S+ éë‹øð»—²l¦ë­¸hòìa÷y¸~vÇZž\±‡gVíá™3'ñ7Î}Õ ³Ùo}ó¦¯füÈ,-‡8ÜžgÿNví>‚E°fÍ>„P„±æÝ×Ïg׎N®9"zBF×d¨¯œ³x,;Ûb 1Ó'ÕðÈîCdÒ>ƒ¢¬q;i ’ý–å9•"‰®ZÀRÉåœ$ŽÙ±Ð[ÌÇÆûŒ5­1Û\þy¸­Æ ´~b( !(¥ ë:vKÎ\:\.;Ã]ÏÞrålfŒÎðË{7q`'5·÷ƒˆ(êßsUCQ¤‘‚¡idu•ùþ<Å0âíWÌáŽyÅtu+/ln£2T¦þôÌNÖîîÕ [µº;n_ÃþëYþðÐNîº{3O?»ƒí;ÛÈGn« Ù„`ŽoÈRS›aܘ*RþýW›X¾ €oÿ|5×]2‘ù«É‡£ëÿMl #bÇ1Q¹¢[£MŒ6ºì-'<á»ì†_œTûŸc Ûè(Ь6ÆÚ­6ébxBœÀ;p SNsB„8fì¸L˜4’?>´®üùËÖ°µ¥Àá˨¦j:zŠ´ì.oQÒ«ÌÐÓ7àj¥@kÃCýôbæÏËß¼mÆ+Þt ôç=ª–| q’’’ß>°Wë‘sÝ“™;§™Mõ_«€”/QB0nT5“'Ö#´Õè(æ©5im릮&ÃܱžX¹Ÿ?>× ÀK;{9ØÑÍüÉ•ìê¼¶'WlCÊÒüéDèqRKi0Vk·&ÖÆ•˜ÛÄm,¡´UÎÚJ¥äů&|8zzz#am±æ Å¹ƒ¯Ã>›€ÀW?p`ל9š7/ŸÃ÷~½º|Ì»ßCJÁ¨I¦2MËÞvÚ»òŠyúz8x¨ŸÃd†ú*æÍ™ÄÙËfðÁ7Ïàc¿ˆågg\S-ÃÈG2|àܹ5X)¹êìfΞ[‹@;…Ó*ùNi¼¸£Ÿ}åYþõ›Oχtv‡  D¡¡iD–ŽŽ<2)äóqÕÌ­­½ìÙß À´)#9ØÚÇþc³¦60{Œó€zû5R9ͨËB—hãö „aHX )CÂb‘0 ‰“Ûkk’¹/o;댷ßüª;FŽk' ù™±6ú„ȵZëmRL'9‰Ãðc\Ä!q~†º‰¥ª-QRÒz €ÿó…üýVÓÚihª•Üó§|û”RðüÆVFÁ’Å3™:¹ŽÊê,o½hKŽ¥­s€îÎÚ;ºèï·lÛÒÊ=ÊrÇÝkY´p §Ïn`ëÞnæÍ¨&' >¬îàìù#Y¹º{žÜʶ]‡¹jù\Þ·|â+NÔš}|ô¦¨ð,a §ÎÉÞýS$ŒØ"Yƒ‡:ƒ#rÙ€ªê€Þ"©ÀefN«¦²"ÅÞÖN¾¶x1«wöqð`'Õ•~¹ÄµŒ‰1:NT~²x´q­éŒï6Ä*‰’*)©ôÄ$êR!½* ûÏØ8œŸ÷ÒºÛ˜xƒþr!„:i Ç+O>ëŠ@,ݬÞÚÇ‚i¼÷ª™ÜýÄNfNn ±6EuRßÒÞÞK±PäC7œÉº­­ôö °~ý|å±zÝ~ž_±k¡wÀPßPCyþÅ=ø™€þ¿¾o3{õóßØË¹K'ÓØTÉãoâ+w›÷vsÖé“;²š –M`KkÈô¦à˜é°@EM†e§ŽaÕ {QŸaö¬FîøúROGŒh¬¢iL=öw#• Ì7¦YZwòà3{9g^Õʹ…ûþ3ÊÇè©n£PÄq\îÍ`Œ!Ž\@k´Û¯`I¶©…ns®”h¥]!­UxÒe„…’ž—Z ½›·\2“SÆäÈçÜz°Àê}ƒ¤$¦Ô+ª+²téãÌS'Ðѧ½£` 7fþ¬f:÷ÐÓ[D èÍÇ,^8šÕZ¹òÂS1r°Õ*å±`¢« Z»»—ÛîÝD&# ‹yâ8"Žb¢(&,Ä ÙÔÆhŒqïGaDFDE÷ù8Š\ÙtK ¯~Å~&í½q¬u·µñkí6kb†‚ äâ P•lH*\¿Hò%O?·™•›»¸æ‚Ѥ„¡¹ÉÅÈ×­måoYL_Ìüy£˜2u)*²iúúú¹èì TT¤1HþæÝKÊ×QÀ‡¯?uëwÓÕÙÏ#Onç󟸈Ñ#s\{å\žZ¹=»Ñz¨‡'ŸÜÆw~åøÇüD({Zxè‰<¿ÙiÏR Ù’ñLž>šñcê¹í®uHá/¤déé“yüÙK7&Ž®ã‰g¶óé3"k¸ó‘Ý\{¹óPòþþëOrÃÛPUUIXÐÄ‘&Š4a;OÂLcâ˜r_y‹ãTÆEmbâ0r;¥µAÇ‘ël®ÄòÅo¾å„µ‚¯€°ãg:*Æý:6ÝÖšõ€WÐ÷Šv»ŠJE%ƒ^ÀÐ")%ý}y¾ësd|à‹¨ªuq€Íûûøø_ÍgÉÂñ¬_»ŸéÓG“χXkؽë¯ØÍ™gLáHk'©£=L•ặÌ'Å<òÄF~ö«g¹ãæ·3nT5?¹•bX$, ©T,›ÝÀ†½!ûú*¾ðÕ|ÿÖ5ÌžÖÈ’Õìj Yµ#O?pÞ)Õü×?_Âêõûxôñíxž¢·/böìFB­yjÅ.**òùÙsšé d3)ÆÖ+ººòlØå8Ïugà†¿{€úŸ¿Z>öÃÄ:"Ž¢²°Mâ–Ûð”ç6YhÖ5¹2Æùÿn†kaãH»˜åyò„ OØÑ¨ÐßU4–NcíNk9`³Qåa,Úm HÜ‘$‘´oII?]m, µ9òZñµ[×pé²q478;üø³{©òá¯o8•»ï[ÍYgLÁÆ©¨dúìñŒl¬ä¢ófò¶ëϤ²âØë_²p,hATŒð¤áéÕm¼¸á7ë-üÍû/`Þü Te+5ºŽSÆ|÷oóÁ«çðßß<ŸËOsç˜82`ñä ¥ qgÌ„ñµÜôùK¸üÂYìoíæÍ—ÍáO¾ŒÐ®AWOÄUçOå®?näÜÓGÐk$ë6 º¥7ýd kÖà–¹˜õÛÛi=Ô=ø0‰¤ë‰5šdƒ^Yàn3åÈ_éé&N#´Ñî{ncJ{щd|ÂhÑ@o”¡{”-¹YH9¢”‚Ä–vïº×îQ ”,”¶—•y"b’fH!L²‘Tr¤Kóù«OáÙöñ…ï=Ë×>îÈÑKÛ{iëp…˜³ÆWæc|O0qÚ(ÞsýÞš¬"€ ç,=îõŸ;»–³GÑ}¨—Þq_ù×ûÙ×ÚÉs«v1aB“'6ðùžÅ„ú¤ÿ0©ùÄÕÕw<º…GÝÆþój*Òc‰¥Çáž<>¶…êš,ýŒUM‘4[·tðõÏžÀ˜Æ¿ßëðƒÛ¶ð“Ÿ¯à¶ï¿@ÂnDáz'ljð†n³å˜0åŠ ;¤N\&E$Néj´qrqtýeó.ÿÁ®½ï¯ÛŽä„@‹Fcút¬;Œ5›íÖg¤9s`Ëœ@›RjÒûçÔ•Ó ÆhL¤1¡f € kwòo?M[ÛùÌ7ž`ûöCtô`ÆM¨çOÚÌÛ¯ZDêU‹Ôǵ—Îæ7œÁ·øtÐØXÁþýG¸ûþY½æ`Yø';þÏ;gsý539ë?¥µÛð¹ëgðØSÛ8ÒÙO¡#Gúxû5s¸ë®•¤÷ñóøò?^Á§?r3æL`ôÈøŸ¹ë ×sùHŽÄ<¼ªõÕ¦„Æqõüû¿\Ã-¿y–?ÜýúDÚXØAÛTf1–Á½I;),»wµR3º‰…Óê™2¦‚åËçsÛ}˜5µ‰9Sjii˜:c,ûö·ÓÒÖÅâSDZóåV&OÍî~žŸÝ±š|°hN µSS“uø>Ü ¿»o?üñcd2çŸ7‹7_¾… §p¨»È¡þ˜_Þ³Hî}l÷?³᧘:æ8̘<±›¾ó(k_ØN]CŽB‘×ìào=oýøq–/Æû®žÆšÝLjrœâ¦ÿZÿºœE“CÍ_½u ÷Þû•9ß ÚàššÒªfPÛbÊtph¦Å"PR¹v{0¬ó¨SÅ …È}ççOÿ²åÑ/“ë*?/àD£~Úgsé\0ÝSÁ¥Rú_”J”Ípy‹÷Ðx@ÂLu\Re¶Ü¯´´Ô^áŽF¤øñwßÏåg¸DÖïVìçîû^æç_¹oüzº·—OèL\~3o¾jýyÃ\M˜ïG(A×@Ìô)£ùè‡Îgâ¸Z|l [6à™Ûð}÷L‹b1Â`©Èf¨Èd*ÒÒÙYdÑésXýÂ&ZtÑ8®™~ÿWl9sÑ_ý„p @]]†b1FËg>uë7·#uÌ7?}«¶°nã>ÞwÕtbàñµ]\8¯¦|œß>ÖÂÇ?ýKêª<””'Ð2øì@†Oë+å)”ï'=ŒÕ°¹NŠp Ũ°hí½ÝtôwOŠõ÷ŽÐªÛZ³ßb÷;””vüØ2Y‰Â˜b¡@†ƒ$¦ÜÌÑÙ1=äwkO…ý¼ïc·ð߬CoY:š /œEK Õ?½c¸û–øÝ]/ÑØPÍ›–/ÀK§©¯o`Ê„f:Úû(F†îî§ž:¥|F5×KW‘«® ¾±†šêC_ï‡Ú:9Ü>@¾·@*ÔTg©ªö9´ï ïý‡‡JŸÝÜÍ5¹|••]}ôôöóùO^Åî]<ùÔf¾ùiçŬZ½—(©Öñ ,ü#øñ}ÛÙq ‹Æ‘• †R.?y¬æUŸÄ‚ÜkSÚ$’óÄ/wDz HK!/±ðSÃtöI »ºâ°~t_JɃBší5ÍÕõ1¬eºµ®€!Ý´Ó¾ìèm/¢´‡Ðí”Ïf+9ÿâ¥üú—+xðÁõüûWÞÊ çB³g%Ÿ/°~g‹'UðÓo¾÷~êÞÿþs¹îÚ³¸íw+(øäG—³w×¾ðngñ‰¼iù<®»n ë×dÝú]ìké¤Ï ºzÈwõº®äÆ…¥[ö´cb×ùôìeS™4~$·=²ŸÛhkëç—¿}–ŒÐ¤*2<ÐÁ”ñ |èoâ¡û×qßÏsï=Ÿ*ßÚÊÍ-Lm¬Ðn9óÕ›ŸæÉ;ù¯\Mjnîí'“ze ‚’:Ô¹/Å‹J®9·ÅßZ„óf^ô-i3éaG8¹‡FØ8ŠòAà÷X«7 ¡.µ%íal²Ì]„ÖƒA"÷äAž0ÔÜ”À!’FBxò!¾§ùáÞÍ'?ó+.½â|æ3WðéwÎáŒÉ•44×±g_‹'U°dF-—]6—ï|÷!n¼áþá3ËyqÓ~ÂØò›_?Åè‘9öîiåÛßÜOÓØ:.8{&o¹ê4ò&$ãyØ×MËCtö‡¤}IWwžSfcÌèÖon¥2°<ùôF~ö“]ôtÈd|ªªSDKowž /šË—/åñ'Öp×íOpÁK9ë”A¿qýA–üÕdöw>û¥ûxâ©mLŸÝÌ?¼ŽQ#³,»æf®u©ÓùñV½8êµ$y’µ¨²Ý?–ˆ•‚uB*צq®Ô´?ó¯C?wR°öi›žòž0c›z¬µ{¬5]BȺ£}fK‘¿¡ïa_ýÎá‘Nþø?+¹øÂ9ȵç¸dÑ?|:'7±~ÕNž]µ•o}õjzx+c‰òUé4Õµ=]=üêö§@?C]}Í͵ø{†G*XmxôO«™8±‰ßÿ~Dš #ÉdÒTfúîîf͘ĕWŸŽŽB¾ö¯¿¥õàT.Ç5—Î/ßÍ#ëÚÙ²r#?Cþøp#ËfŽàKŸ½€Iƒˆw~ö8ØÒF]m±æ„ÃZ‹ƒ•¹%…[jI;ØWñøÖ¼ ­„š ÀI‘@¿úz¯vì˜fßO&¥ü‚”âT!†? ÉèÐmd(q„áû†U³–؇T®}œR.Ÿ]Ô–¦±MÜë{iÈ@ÞÂ/îy™ßÞ½ŽÍ[Zhl¬çþ_ÝHsâI}ûö|üm³¹ãá½Üú‡Õœ»l2³&6ðøŠí<þøËt%eã¾ç<Â"q¨)t÷!=÷¨c¡º¾’EKñÜc«Òñ™þþ¬fÊŒq\uÅéTÖ¤xâ‘<õìf„„Hx¬yøÓÔ§¡+¾ç׌kªä³s‹§T•“I>òóÇ^¤¦2b>+“8jÒûò›.çŸÌ™H_¹gð=TÒcHÛ¥aS‚8?µîþ}§jÙDÏÓ_³„:MÔNº .È1Ç“þÇ¥×H$÷`ÐIóÆ¡Á"‡ŒÄ8ÉápM©ƒDø ýO*úÈsΞÏÏ¿:¼ªéöGöpóoW0uÊX~øyÛ¸ã±2iË—6aO~k«_ÚÃUošCýÈzZvä©g¶³ÿ!º:º0×êNà2w&#‘VÓÛ²ìÂ3YûÒ&òù¦Ñ5Ìš9‰ó&Ï¿ø2«V¬Gç#Ò•”Ø×Íï?Ÿÿü»ó°À?ýz K¦×sÙ¢†a×~ Çð¡/üžOm¦®&p¥^$%oJ ÿÝ&Fžç¹þ‰¾kÊ-¤ .FaPÊ4«CŽY&Ь‰þº½ç‡_ø·?¹‰ŸËUW1SHÿ)ÔBJé!„*‡(M‰–Žkp5 6rG¥§¼¡@x>žòð¥}…˜¯[Æ?|`á°k0À-÷íäôSF2wBŽÿ¯½s–ä*ûï;Ý==3wîS»+¤ÕJ !!@ƒ1Âà[˜Pel 1Ä„ Ç)ŒËUŽSÆÄy‘ä¸(‡¼ B%ƒÁÁNRE‰r‚y$v@Œz­zî®v÷Þ½óì×9ç˧{¦ïc…v7‰1Ú¯vöνÓÝÓ}¾Çùޟ¯½ï+|à×^:7iÞÿ©ûøGïùW_{ˆ[^v W_w%Þ§¨qüØ£÷=ÁÖÖÊZ£øºèuõÒu~ö/g4̘+]¾Ê½w=Â=÷>ÌÝwbú½ˆ$MÁ{Æ“‚Þønÿí·œÕòdýÄ|ô÷î`óÉMV½Ò¥v£L«zb1aüM»ò³9Z„NÒ#î%ÄÆ„žÇeQºi:¯Í‘¿ˆ„÷þëEž½êþϽ{ÞQìœ&‡–“më«cƒ÷¢1¬¨·MŸ‘åIÍå jœaW´1Bd0ŠDq@~Í[¼÷ÒˆßúÝ/ñ䙌_ÿ¥—sx%\À¿ø“‹g_`)¶ü‹ß½‹_½-äõÿò›®§´™ßøÿÌñ'N£Ñ¬o,qäòUú«ºtçÝp%K½”å•>UU‘MKf“}„{î;Åý<ÆæÖ_ätbC¯á¼Rã¼@l˜zÓÍÏáÎû‡ÌJϵW øÎc#ÄD|íÁ|ösð§_{€Ù$ãÐ%K,õcàüÚÁéó÷JE£Øí§:Õ-÷5AêIF Ý4%/>žEؽvÍ› rµÂ*0'€s’2x[´~ÕúåIßKü÷Annš9Î[øV[ÓFìuâ8 M!“(´b$ ÊL£Ð¨zÆã’«¯¹‚Û~ö®=²ÂuW¯°Ñh·Â¸ëXÎO½ùÃ|æcoã…ÏÊ^ÿŽßçÿç7X]îâ\‰Í*¬6­Y=ê"LÍDPëÝ4¡—FT…’ç9¥7$Ý>Ëz¬Ä)K—ÔM¢Šœþ`À±'¶Y;¸†ºœ¥Á€<·ëù‘[®àæëŸÅãcøìgîàá‡!ŽŸ‚ç„àë§žT‚ÔuæDÄDÄÒ¥>8ÂÜDgyž3÷¶=°¢©héË7ÞÿGïútzð¯Kqê£zn³ƒ³ox[¼*‹ŒßT£'DäfTUAM¢È>Öü4¦F~Ííqœ™ ʰ Æ£uËxÃ`pzó §ÇË[3>üéoðíûNņ^?á†^J·Ó%Mxõë?À¿|ÿmü•W^Ž>ôþ7ðÆÛ†|ã+÷°±6 í/Ñ•0Ì{-Δ%Љ…^$8ïÙù…Gøü¯lŸÞ&éÆ ¶no“ÐôϘè­ÃD&Ž¡_ ’T½RÍ ¢AD…uOÓUG6Ë‚ômÍ«¯A¹ø´öRôœ$@÷Ê¿µí„®FøæwNpòtÉ‹n~6oþ©«8(0Þ÷ï¾ÊÇ>òß™fT¾$W¤½«ë«¬®/säÈ:—Zc{ßÍG4´IDATkÂ4³t“ˆ·üÌKxÍ+¯fí<š¯e>þÙûøÿé+Üuçƒô;1IïéóZƒL“tºˆÂj5ß&N躘8Aꆓћ—uwÕÝîdƒúêßæeþÎQ9ÒÍ;~ÓŸóôð’Q…ndªþÛhTjª\Œœö#¬0u#˜0IÜ!J¬Õ¦õëBT4×0"$‰çþ{åõ·}ˆ_øk¯à?÷ƒ\¿oâFHëMÈÅ;8¸ÞÇ:ƒF1/~Éu¼æÕ/àÆ®â¹WopÍ ,ôèb2·é8Ï:8`+w|äöoóðƒ[|ó›ß¡×‹¸æÙXVVz¬út—»,ÅGçëœäèýÇÙ>µÅ±'NÓéD¬,¥aÅYÜ!ÐBxÓ¹iojëÊZºý.c¨ŠP!„‰ðÖ1›æôf>¦g°<`X qβ×AäA¢#kQ%[pŽ:€Yys²vøÈ‘82¯ŽMò^AÖÚ"~1½Cçû˜¿cH: q’$’ng§½rÖÅñà<Þ*¥·Ì¦‡䵯¾‰×ý¥çóâçæ¢ØÖ¯GÇð§_{ŒÛ?w/ŸÿûI{ÞzÛ_àu?y×0ô[×pèøÿo*×çÚëð‰|–¯üɃHœpÙø‘W¾€7¼ö&"Uþà¿|•OÿÁWoOI:¦“ÇFðeE܉IŒ!Ž…8Š%Ïi… c¢A`ÈÐïw‰;lQ†‰nD»‰#zƒ>I’EB>ËÇ ½¬¾nÈÓ­ªÌ^<*ÊÇNßùý9€,Ý­^¾þ¬¤“¾4Š:ï1È@+4ÜÒl›R1B§ÄiD§“†Ž™OùÞ¡V[méƒnSEQÑIS®8r€ˬ_Òç±'†”…e’yýˆo8Ì[þêK¹ñª>}žݴ`ûâ·FüÖ‡ÿˆ/~é^Þú¶ãºk.ç½ÿäœxü$+ë)‘t±Î’Ï ¢´ËkâżçW‚ÕAÌo~èñï?öp^‚Ú +ÊÓ ¯í÷¬õúBPøbCwˆ£¤Žñ‡i¿G·›RYK‘åØzðT”$ –—I:uŸäјé4£™ÓÔPXWýÅ¢œÞqüø©s×$¾QGn½$í&7ÄqçïYÔ µ=|!°žÄ IÚ%NÒ^7´‚ÿ® ²ò svE/Š-3¢¤ÇáÃÏâà¡Unºf×­ñ‚¯äÆç­±;šÿÐþÛí÷sûg¿Á—?ÿU\%ü«¾ÞJwÿÍßf43Xé$ˆ ’!Óv4Ë,/óÿÞëyûO?o=žó–_ü6O'Ž÷“œ/ÌgKðã'QR3ŒÖJ«%í÷èõ{à<ÓÙ¬ŽºGÑòê N‚÷Ž3›g(‹rçV ‚÷ö~ño0Yý%9g@íÝÚ=üŽ¢ÓIf(›m­_ I aTÚ·i¢:Iìü§ ¹p /}Qÿ]›.Mî›C$"M:\wýa^ùòë¸õeW°1 #ÄÃSå›÷o2ÝšrÏýñ©ßÿ*Ç9F‘ÏXZ[㓟~kë}Þô†÷1é/uñÖ× ­"Ì*11«ƒ.E1æÝ¿þQ>ó?^ÄÕU&g†Á—±/ìJ’xŠ'®Y'8ÄäK„áT)‹‚¤Ó¡Ûïâ¼£ÈòÐJw°ÄÒò€2/˜MsвÄom±º¾J·ßciy‰ªÚ3§¨úú6s–rÕßèmtW¯¢ôMq”ü]ä,‚O‚¯¿ÓMéöz$Ý”ýíÄù­¡¶æüvB„Ö=ò}ÈŠQÄžºàv.²GL%aiy@/Métàä±-¦3éΜڤ GtÒ.ÿüŸý<¯þÑ+¹õµÿš‡î{ˆååþž[k[6‹VˆJ–— †^jæÚ÷^Ù¿ÛÏ»ï#&³˜kW¹4I˜z¶r=²O1i/%NbŠ¢Ä[KÚëÑI;x瘎gdÙŒ(Џäà:4exfÈx4^ìÌ!]ÿUYþÊhRœ»G—BUO¢Z¢Òݽÿ7ÞÀÈÄÄqBÜéœÍ½5¿1u~òCS̺3fƒüÆÁAX°4íàU©fgF§9¥§ÂÊÆ:ê=«ƒÐ©;Ë*^ñã7sË‹Žð®÷|†£÷>ÈêòÒÂ\eñmËfÎ'"ôš®ß î÷¥ÿ}B´óÿÂRä‡aÔ"Ìe‰˜Ú=®º¬ ØŠrX’v:t—zH§ƒ­*&e‰1†ÞR—8™glžÚbccƒåÕŠYFQæ‹t1‘‰d­cØ>? ÐýùxõÈêåIœÞ™è7 rp1L n b¿›Ò[ê¥z÷ûÁbp;9¿yð0½».;÷!¦Ð›æ4æ§„y®N¬ìt{,­®°}r o+ ×3†ÞÒ[[gèHNѾ°/CŸmÌì¹Îí3&BêïêëÖ!]1Q‹¸MóÕ;&KÝ*LDéõz8õ³‚<ÏH"&"ÏfDÆpè²Ëpê9yìx"ªú«Å­ãIùèùé¬Ñ)ïœ+q?îк(´nnPs¬CÜI0µZÉÔ¦]ÃÑêÑÊ…YÅ{ïh|ÙÍ÷&QrN;rB­^¨X^_!ŸÎBfò¼u=¸Ê1ÜÚ¦cv"ŸÅ]-2[ôÚö±·«ršþ½¡”ËïüÝ5U>¾–ˆa=š¹ÃÕŠ³Èáó{iGÖ©öÍ+ø ,Óñ˜3[›ØÊ2X°¶±F(ò) 8o9yì8F Ë+«A†_ÕÒ§»ÏTã§åŠ$•ªÖ=C¬]]Ø«ƒME$q­$YÐ*p24\ïѪŽ0™ÖÕ9îÍquRƒº…oz]ò«AŠC–WCƒˆ|: „ÒäÔûPI“DQ¨bj¶ê6²Bhù2ž6ì'$Dˆ¢%H¬"d¡í‡cÌâä²u•~žrï]5g"[UŒÎœa¸¹‰ªgí’ Ö¤Û킪¢äô‰'YZ^"ív›2²"BPúÜA«£Zey¥"™Â$,X{ÂÃ%iÄ,üÑó:Á:Båšv2 ä‡xßzè…ÂGýE¡ ¦åVŸ/RHˆì¤ƒÓñ[Y|é‚Hñø¨¿¬É[põïºçAæ×Ÿ÷no^ú]^ âãˆ8 AœfmãÙ™0³@tƒäP_±¨·Ðâ®YiP%›fl<Åd8"é¤lº”KÑ_^¢Ìr¶ž'fV± I—mh;ÕÚîo -sB–NݦŜ×ÚÚÒÎÚzÊ|kÝõQMôÓÑŒrõ¾K ŒâDpÎŽhé6 ^oêØj_Q\û<æ©ÛY5ßëª÷JœtX¾d­ÖŽCô¬²æl¬¶×Ý î֫Ǩ,¤-ÄÃÜO`DZäÏ/±çÍÓ„ýtæýS¤ï<'XU‘³ùdVs>sÎS¥«^.@$«êujÕ/M¼ñCU] "¯n]ß­:pb„ ÚD¥hŠØl+v;‘¸Þîxtï®áúÚ[¦¤¶ß$À>…Gølâ}Oºýþ§C(µ€× B½ª 6`ø§!$sI©¡ñ@¢0ÑHž*?é»@ñ'x÷2§¢#/zõW‰„®Ub¤îP»8B0A'˜+xí'mÞ6Êù¼Y²oiÈ kBUIû=k«¡²¨¥èU¶ oÛŠœÖžÈÖrú– ¸Ë`Œ ¤£×gþû< »‘»êIágGáY>ñ„"ð’Þpx’`CeÀä ÊIE·Ã³;W¯ZTœZ´†a3ªûÁîQ­¤Ñ¡wTÝÔäP·ØÕ࢜—­uŸW»8kû¿eÄûÚ÷È]£¾×–’×*>“˜Þ`@š¤h¥Á1á¸ÈÄÌÆSª"ê4ôDvHÝ Ò‚²ñÍg;”>³àúðy@þ^û|·º+Ôk” ò8"§€3ªú°À¶¢9ÊHÑ|T(NU+U-E()Q¬÷Ö:ÔFBe$®TÔ:ï½µU]ѨÏ~±œõJ*ðàÄ9W®²ÙùKÀÇ•z[#f*µWm®ÄÍÓ¼˜BC‹mQîëûœ'>Òxó‰^&Šè.…dƒó6!ëð³DB‘ğã&4SJ£U´Óäöz“ÉÚâð94kEÛ0o×^êp)KàÚÇA6Ó`?Q©2!ˆêJÑõHš«×Ñ\Õ^«Êx,B)Qd­\éKxgº>*Kg’ÊkiÐÙŒBr-£D÷·}ú“7‘ú|¦œ0çï Ê½–œIK}o¶ÚvJX ‚…²ç]sŸŠ÷ÕŽãÃâ¢0‘¡ÓïÒI»ÄQLã%¬Ï¬oÄPäÓá(Ë~Á³«6¡Í¤ìõõw¤¸5ç9ZKf`"r8²©ð(è8ˆs?A)W(:Cɦ¢ÌTÈð>shx[YWN+k\iË\µìŒ¼ËR5S¼ø5*Ûó€?Û‡€ëž…ê?=7ÜÕpa0š¨öúNÑ“´ƒâû™1-³m¾Ï» ÙÏ[ž5z`¢ˆ¤Û%N;ñìTjUÛ“ÍfdÓÙÎ=¾}»½¸@ý¶­àí:Ÿ­£˜(<lƒ<*¢[^u"èÈU5W˜¡:ïuŠèÌ#™z ï]é SUšÛLsÏ–÷ÆyoÍו|åhHrý7€Ãó:à0¾ÜUÿ~Ã>7þôá‚@tÅ£R¡rR§‚Y(pÍA­‚nºÇ®Gë‚ÇN„‰#¢8®C¦%ssG 0WºÊ²$ŸNC‚$‹u ™¼Ss*Ø!­âÜ”´ÓÀi„Ó +:Ùö0ÅûÈ?t¢ªcE' Sõ2SÕÌ"¥U•©³®<íÌöeÎê·azÂ+|xžWM×ô›üdç7n¬Éw‚EÓó‡ "Õ‹¬•"š+8¯>¦‰A=üp—ílâ6&"BÔB»ÇÕ[Fc>÷ÒL ©ÈÇ¡‰ô<¥œ½ý'‚0Ô g!„Á:U'@‡¨<lN<:DÉT5C«êDa(èÏÔ£Sõ:³b Í¢2×¢òÕ–s£|Ù3¾° ŸÇó˄ꬣÀËXä3 ÔÞÓÿ_pa[@´¡ÖTÖUÒ°Ðn÷¤ cOwkÔsP晹ÛGkË¡v,IQ´EI•å”y·‰Í‚c÷¹¶×@„]„~Çz„’P/¿zÆÃ TÇÀtÒˆqEGÀHÑ‘ªŽP&`gÖÆ3gµÈ£q凙õSuÈeú¤BGá·¸úFØÑ®o·¢vþbüBà€HŸ¨š¾‘¤²xkÓíäÚ„;=o-a‘B6¾ ݰ]YRå!ÓG“SæCu£³,àÜ¥ë*`jÄœF'ˆñ›>p'ÐT57÷ñg…ä§‚ #IQ·ík‰ŒCCp'rMlÈ,|ÐmB`Áõ»Í¯Æì³¶¢,ÊPÿîšžC!B'íí¥Ùïm"h(§¼÷³)Â&èÌ©+L2õ:Au¤¢#T‡^t(ÊDñgÍÌ也”ZͬÏúŽé¿ wÏna‘(Є“¿÷½\ øÆT"_‚Ÿ¨Êï|í{vˆ4%”; A¡“2×´­µ8[RU®°uj—ÖÚ~cŠ…±±jBŒ=ˆ&ŠnŠ’›Dz®ž1èãsUf„ýz¢0©2B˜(vjË8/lVX†¥Õi5sä÷*¼´VÒ^ÌNQ^°·<ôÏÒÛpa ]þq§êKu¾AíÂõ~8ÀMö¸z«ìbúUYÍû BƒïÎGÐ’¦ [¢äµ"všàpÉT™¨‘I„ têÕEy«c12ò^&Þ¹™—ig…¥/§Ög]ÇôËŠ?¨»ï®g'w7ÄÜ ýTnd|ªá؉x˜zq3ïÌÌå&¯Ä—>;euR8ŒuäG~¨ÅÝw³àîrŸ¥ùóÇÝO.T DªX%µS…SÏw¶ –sŸ~ 1‡ˆ1¹32"00ü™à)ó•Úw¦J¡hP š)š¡:Ed vjÄLÔK¦ÂTÅfÞ›\­)rkKß™X†•£8é(N*\ ü¡†G¾¸ø!öçîïOdïH§)eæí•5ZœÏTdfŒL0¦D¨™Š1#`¬ªNƒë3Sõ¹zW)Z ” 5¢Éhˆ?E˜*d2˼“ÂhR¸jRVê-UéÈpèÌSÜ£ð …ß# ÷ð8дc­ø^1Á¾àAO¨\òsðªú%„ÓˆDÆH˜ U«ê­B‰£T´ª¹:ÈP“yñ9hn`ª+äê|îÄåêM…ueål©¦´Lq¸Ò#§å)Ŷ¾ ¼èß^N@´o=â÷¦ög (€qeIÓmïìb˜ª£ÎäˆäàKp¥‡Ì˜8SÕ\Õ•ž¨P•Ü›¼ÄkE™ØÊå%‰XŠÊ1ÉëÌÌoyJQ¸RþüE‚‹´"ˆðÆs{›¶< ÿïEø¿@Õ±j–_*‰Ë»Å›‡0^ñ”jâÜk¥²Œ­œ¯ˆ¬E+ϸðØÌñÈ1¥8 P¸Aá“¿†à*…à\iÚ°¶½áá\á‚ @õ NäGGerhFʱRuã<ñå. ÷A Rø™Z\.œ\þ ÁŠ;J@ì‹ÈßíÛ}Š„ú‹pApá€/yª#%Õ•À׃¦íƒ{!¡×Ç5­Ú‰Û Äï Á^„ÿGp^ÕÁáû¾?ÜYá¼á"<Ãá"<Ãá"<Ãá"<Ãá"<Ãá"<Ãá"<Ãá"<Ãáÿ㯧MïæaIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/lphoto.png000066400000000000000000000172231217176075400232270ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞZIDATxœí›y”dW}ß?÷¾W{uuõ¾oÕÛLÏŽ˜ ÉH€Æ³ 'v18Æv0ÇÁ6›!`B ÁÇ€ X€£´‚$І4ÒH#Íh¦gé}ïªê®õm÷æW[k¤8öá8'÷œžª÷Þ}ïÝï÷÷û}¿{뎸á†8x𠃃LLLrôèQ˜˜˜`tt”C‡±k×..¹ä&&&¦§§‡ÑÑQöíÛÃáÃGÙ½{Љ‰q&''immeÏžÝüæo¾d²™¶¶6zzz¤§§‡Kahd„½{÷299Y{ÏáÇ™˜˜`ß¾}ŒÓÝÝ]{ߥGŽ061Á®]»Ø³gÃÃÃLLLÐßßÏe—]Æ‹mBký¢oþ¡ÉŸ÷~ÞíÿðóÀÏ»™?ïüSµ+®¸¢¹­­­3•J twwOLNNîþ¾pÓW¾ò•¿z¡ûþEpðàÁP{{{G*•êèêêëèèH}÷;ßîO$â‘P(" Jâðá#ÛÀ¿ÆÆÆDWWWëàà`wOOÏp*•íëë½õ–[†ZZš{b±h ¢:tã8lÊÌoZ¬om³´iã(xë öK)CJ)ëùÞ÷s#`ÿþý±®®®®¡¡¡þT*•ÿþm·tuuö5'š:f ñËvHç,ήdYÊ”YÎX¬m¹¬ç=¶Šš‚¶–(%i‰›¼îˆÇà@4M«Ï7ŽV®»îº€išmÍÍÍ}]]]Ã}}}cƒ#wßuç`[[k—aãϽ/[°™^.°œ.³”.³œ±Y˹¤ó¹2X®ÆÕBHLCb¤˜AAXB tÞ¥¯·»³½½½ëŸ•€W¿úÕÍ݃ƒƒC©Tj´¥¥e¬§§{쓟üÓ‘¶Ö–îdKKÈÇrËÙ+émÓ%–Ò6+Y›œÇVQQtÀñ$! ¨40¤$T„R€”ËÑlæ=FRÉh__ßðÔÏDÀ¡C‡BýýýíCCCýƒƒƒ#===cýýýÝÝ]©nøÛþd"ÑiÑÆ{´†t®Ì©¹-–Òe6|·]ÝrÉ9Kc¹ )1dÅšRA •œ]*D•Aå4RdõœÐläB~!\pùå—· õtww¥R©Ññ¾¾¾±[nþ_C­­-ÝÑX¼µÂ­Ê. ™Ëém–Ó é2+Y‡m—lIQv®„¬XÓÄ”‚`P RÙ`Õ àê±D E•‡ð Qé(@"R"†b#ï—ùããã£/H@2™L|æ3Ÿùýû÷ïkiIßzËÍ}͉x‡4CÁÆŽŽ§ØÜ*sn-Ãâf™¥ŒÅJÖfmË![ÔäËË¥H‰)$† "¥ )¨¹«®¶j\ÿ\õdݲ¢F„®|—U×bÇu@Jÿ†)Ø,øŒŽŽ¦„B?ÏÄÇTJE¯¹æš÷ŒŒ´*­ÙÊ—9·Rb9“a9c±”±Y˺l¸J€‚€€­²?’±ÑÔòÏç3§OŸ>522rùßÞ»ÈÍ¥QÚÀò4šj\V]W3}U2uÍ}«ªÇ²6(ö­†ö{ÉzÿªÿËÔ-¯…¬×Y^íS¤”­5p¤óŠÞ®®Öîîî`ö"¦§§ÏôµüTU€ L£+ tˆZ×È`Ç÷F•®Û½jej‚WS½F „¬‡Ae,^R?ÿœ?Àra=¯l ††††€‡Ÿ—€óçÏŸèL˜D‚Zk„¬¸`e°õÔ`ñšÉ«Â¦wzIͪ¡P·x• -|Âu-½5 a%½!QFE$YM{²F•gBÖÞ!µ&÷=ytt4õ\ð5fggg¬rQµÆMÙ1)”B¢h‡‘ª$TtƒmŸkÐ*iUe÷C£QÝë–¬²Zµ®ºfQÙðP¹ÃÚu/¬ž¯+€&]òûB©ÐXYYY\_ßÌôôö¶µ7™,‡€Q±˜¡«¨ÅŽ„Æp¨‹V£rS£ª[ã§Äšˆ5|B5—׉;Ȫ[º^ðÔ‰”BbTúëJÿír•€±!„©µv/" “Él,.-¯ô ´µ'Lf7½J:©Z·ÑÒ;­®çlž3XQõç¨x-¾= JT)>YÕçk¾ÔHiˆw!„¶5# ¤E×÷Èðp¿a }¶moÏÌ\˜;zôÈž®„?É0Lq=­US_Å- ߪÚ7vƒâ?UÊj×jžTqóªkìÐ ágZýP |ÿXî aGlÔ)¶’äèïëíjooïx^´ÖúSŸúÔy€®fÔ~EU¤®ˆ›ÖZWŠ )ë@dÝÚì ¢êçv‚lðì‹DS ÝÐ_ÖHYBYë[}¶”Uûûžd‹0ØÒ’èíííN_DÀÙ³gÏ´7IAèÇo- t!ý !«¯ñ”þg5Z*ê,+Ï«–ÆþjÏØaYð7¸;4²!œê!P¹ð†²%l6ÄÈÈÈÏi5.\¸pNy­1I<$ñj¨bžš·Ö’ ²á¸*zÕ ôN*8¨¦ÁF‘¬Æw-DDƒ7ÔB§2ŽŠn¡Á¾P¬äßçË5æ³Ùírs4nŽdJº>ƒ¯á¯ ‚_ÑÕÁÔãºQ}b„ôÝѵ1M¡õó(xy¢z®APk^FCÌ7¦Rÿ½¦ XeÈeV8v×wXë péßû&`mmmeeuuc÷®ñþdL’µ4¦QG/´®Ž²fQÿ’®Y®¸ÁÒ˜AJ«çˆ.=@Ù }Ùu 4Êsk:S-ºD€Š6€ÞBd€@H¯§¹ðÓǸÿ¦¯“]𦰽ÂòÞI>öÁ÷2>66,„k­ËËå2 SS»û;›$³YŸ€J–¯0ìí¨Á«®Ü(F¾d"ƒJKOÑtâFº›LîýéyŽ=µÈ•ÿö· ‡Bhå5x‚¨¥8_T&A !&DµNðý1„P.œšæÁÛ¿Å™GY%€¾¶$[f’íâ6ÛÛÛŒŒŒôÅb±V`é"”Rå/ùË3 .m C`ue÷-*b·îª;S^EÁMUÞ¢ùÜ=MAÑ ²oÏ '¾}77f ¼û“Ç.W­Úhñ ¡ª¢>œ@‚!XYX྿ÆñÝDÔ°éL6jî¢l—pP õw²YØ`~iñÑñöʤèb >'hAД~4¬²^u;j•ú}’ G¥¨*p½P©)vCz4L(Í>J2a‰™>·Î¯\=I$jÒÝÓL,å®OðÍÛÃÎAúÚÌ‹8ù Â#<épŽç²•/ñÖ_:Ê•Ã{éêJ2·º‚S¶éèIÐÚÔÂééó˜!A,‚({ÌmdÙnZ'2šå@úÊt˜-œzjšìZšþî–––öç%@kí~ö³~a YMiTAËJ]î¯üh­jº }ÃËÌÈÌŽDq“­l[íyK._üæ üð±'±K.{ôÐÙí°šÙ`£èP’y´kQvÊÊ&( ô6càðÐSÏpË=÷óΫßLkIP¶,–ÓVv¬µÉ÷§Ÿá­“—c–%k…4Ñ.ƒ+¹Œ»ŽG¶i 8uòË‹‹L½d²¯¯¯8{O?þ$hâA…@áYE„öP 4.(…ŠÄPÊóÁ v]²Çî¢U”Dñ<‹¬å²š-pêüYúÚ)Ö7×ikn"žha¼5NTÉÒ(QÂ66(flBÏóØ*¸„´Ek¨‰&t<Àí>ÀŸ¼î|ãþg¹îš]ä7Ö8 29nzê>v'Rü‘=Ø3ÊèØkV„ ‹Ïrz}šÄH7Â)¤¾HçææBßøÆ7޾ò•¯¸´\²h*µñ²³” Û”m »l£œf¬…¦Ø8Zy(é¯ÀºNžæîÑH+ha V29æJçéKíâ_í=@2¥·=I$B˜®ÛnËÖä 6HAÀ(Oá:#±vÎ/ÍñÈ#?æéGΰeÍòy×cwO‚ÝÌÌìüÅÐò—Íž|˜ w–™tr9Àû¿t¿öë¿ÆMßû*nYóš×½…B. ÀèèèèE$‰?þð‡?üáJ(ŽDèhQÀþúo(ÁTH”çù랇ÒO·Â¾\¥@iJe‡IÇâùõØV‘b¹TY®6H¶$(äK”]›dSÏSMS(S€«Ð´!0 ƒßá÷™Ÿ[äª7]ÉÓK§øà§ÿó¡Ïn‹1üØß±’?Czm ]ܽ4Kâxžžð M½¼çMÿ³ÙAV9¿ò(G¸jG*¬ `Wí{¥òs¥J)”«(ºeZÍLŸ>ËffI±PÀql ×ñ†”óeú†ºˆEšƒ½ÿ÷˜[š#ˆ‘lOò‰Oš¿»þ¬|«ùu §†Y›]$ŸÏS¶KHa€a€k¡=ƒ–‘nöŒM2wâ…õu±(ÿ~Ñâ»_œÌ­ E~‘ïýÏ}<{æY2¥­’Xó Ï.|”tbl©@~­Œ¸Àu×~ÑÑÑa!DDk]ªàzª{‡h§<¼R¸žC@K\Oñžw¿‹?þÜe`pˆó=Ìþ© ÖVV(gsì?r”ëÿæz¾öµ¿äs_ø"AÃ%ùƒ?ü¿ì¥|ð½¿ÄÀΕÄä×V)ol‘sK ÚÿÚâA2$5+3‹<ñøÃ<ûГø…£Dã-¬>õ8í±yþàz1BO²d¯p÷™/²ðá±µ™Åu\v àzʳqm-à¯} f,ÌffB)̯\ûÖ–A(š_ÕŠ«ŠœxðŒx„×üÒk9;3ÍWÿâ¿1:¾‹Þ>””xZsæì ÙÌ:GŽflj7:æø?á²W¼š·\ýYž-J(»°µh1³pÁÁ}‘þþþAà¸8uêÔÈÆÆÆŽp=×qkàUÄÎ*9¶ ˜¡p3$ E0£ad €§5…­ž>v’ååÞðæ·ñý;oæ¯ÿËçxû»Þ…üðч°\|±@¬¹‰#—]ÎñÇOpówþŽXs©½{9ñÄ#Líº„#/C8š~3Œ»,Io)‚ 9 G£” O{Ø%E@ÃÙ™¤R©‘šnnnº¶eï @)…Ò Ö×¥TƒDhT¥ Ò¡ÔJC¥/h U*SÊ»x "!“‡¸w¼ç}Ü{Ï=Ìœ8ÃÛ÷?pìɧˆ÷tÒ[ö8sú$ýý$[›±<›Dg†¶yèîð’«_Åòâ,›™-.Ýó&ž9ùcÒªŒÛƒ•5pƒ%´-ñ£=}ìÚÕO_ïw`Ïž=»kd2YÊV¹Ð0 <ÏÃqœ Z³ƒŒ*!žçá¹.®§ð*a㹞òp=­^¥ŸiJΞ=ËøÈ$‘h3ÓÏ<˯z-Ýÿ(áæóþiæ§/`»IGo’_×oÑ7’"‘ˆÑÖÖÂÆ…Æ&w3þ}CSăa¶l‡°ÙÎÔžNFš&HŽÒÒ7ÅPÛ8]}t´ö! _ï]W±±±QBB³]vk‹R©Œã¸˜•âßó<,Ë*`µFWªW ÏukŸn¸ª…BÕ2‰F “õ•5®ýÕ_cñÂYöœâô™³DZÂüOý³ó‹D•I[,A('—/ðù¿ø3~û¢`î±[™4»öïee~­áCø“ûiOöŠÔ7œ•J¶³²²²yú™™¥[ÏÝ37=}æü¹sçÎÎÌÌÌ,--Ímll,Ô< PÈã8>ØF¯ëJZ´®/xŠzçzÏZøÇUc{ºÚ[9ê4Ñx’¡?ð³ó³ØÅû~÷Ž/°ù÷OÓ•oCÚ÷ÿä‡|ä#J@HM1B¦¤³£ÅåÉTnsÝ^|àÇ?X8{öì…ééés³³3çççççÖÖÖ···ÓZë"/ÐLŸ­2®ëí¸ k@D/õEOÿ:h‚ú±ïn%t|nl»LW¦iÐÒG‚tD»¸ãÖÛPŽÆjÖ$~ëÑû޳Ñltfè›ë"»¶F0 \.–&†$[ZHg·øèGþÓþÁíw|(=ß ¨IÛ²ð\×·VƒÕ½à¢V½Ö¨ WWJ£¨z ü§*¡¦¿÷* !”âäÓOÓÚÚŽ4 *"ÜôûÄü-sŒüÉ눶¶¡”"KàZ%2ÙM"±8A3€iØŽCwwϺֺøbÀ×p\×s}À©ZïyH¨ä[¾.оêòüg 4#@:F+4B¤ÓYΟ¥»·dGq7Nü‘â”ÁÖ×ÏÐöl!5ûöíc3“ñ],§ B°½½M±Xdïž½å‹÷%@U«Ä*°z û­:O¨­terTñ]ý§J”ÿi˜&E§ÄÆÆ*Mm­¬Î.2·²€’w\{-M=Mìo?Ä+cW±÷díÉN\ö^r„{PÆv\²¹<+Ë+”JeÎNOŸù™ ¨U|JUÇ]³¨V>1~&¨ŸWZ¡<¥<<·R/(öüÚ@i¿œF+ ò\¡hŠ·rÇí·0Â&ñ¼ÿ'Œ_r˜üÇ?d`°‹pT‘íàßr oxóµÜó£aMìr‘P$ƹÓg(‹,.-.ÌÎÌœüY0Á ÊS³faÓ0 †B†UÙÈ(O•‘®:€EÿÇ1×ß¡eº¶ö×ö„O‚ðPŽ¢pˆ;¿ÿ}Ú»Ê%G/ãÜégiëé`ya–÷ýæ{yík_Ï©O3¿¶ÊÙóç¸ó‡÷ÑÓÝIkSŒxSœíRÙÓghmoçÔÓOßxÛ·_´õíÓ$€ëºþS]=CÍõµ2ÑR"ü½m¸^Ëv°Ë–c£]PÚÅö\<Û¦ì¸8–åzØÚE£jiRk°u‰£¯8ÊmדmËæº÷þämî¼õ¾sãM<üÓyä‰'xæÄ“,ÏMÓÚÇ+éììĈÅyæØã4'“œ;Þš›™ýâÏ*àºÕRÓ;  ‰T„ÍCÃ4ÑZ`é"Ö¦MÞ-á”m"Á$*(±òš€´È9tÎÅUy¡ÐÛ6™RE1¯hkïæ%—_ÎÍó5Þýßãcö1Îãcÿ8?ôS‚ñ -‘}ý¼dj?{_öR¡gN>MW[+f0Äm7ßüù;tÏô? T…¬A탑O<õmmm$›ÖræÎÍ0žÚËêÖ¹åó¼üê×ðð‰,ÌÍ£4LLM±‘]`~.ÍØàñæV7×8°wM%O;ض‹U(2656M¾õÕ/óæ7\ÇÐÄ$õõoR²,6W·˜Y94âØ²Ìò³ÓÌÍ=Á®Ñq:ûøÖõß<þïÞóûYÁ×ÐZá:.ŽãøÿI£\²PŽ…U(p÷£’Ë G‚ÌÎÞÁ`ïë™" ‹+DÃrù"±Xœ§ËÎÓÙÖÎüÜ<¹Ü3x–ÃÉc³žÞ¤§»‡üö¦`jß^z{:ÉÅ#ÜtëM$¢ZÚºqÍ™õE¶r¸e,[Ó‹péÑË‘Aƒëÿö›Ë¯¼êª·½ñMo,RÙÊ +ÿ—ttt„lÛ&ެü/•p ȃ‡CŒNNâZ6ÑX­”çR,”(Ø%"ƒ}ôô¡¥‡åjp<\×A)e• ד¸†H´«ð”]òÐÊ%Öcl×®cQ.± EF”ζ&â‰ÍMI‘3ÎñıÇÞöÖk¯»òª«.(¥¢Jyžiš.¾Ì¾(ÌõõuñªW½âΛo¹åMMñÁTj! r…V©Œ”SšhOQöJ¸¶¡°]ÏQ(×ÅU.®«q•F lÐ6^¥VPJƒhé¡]¿(£UE\ý=E¦!†¿û\KIÙ.±0¿ÄúúšŽF£¾ûÝïùljtdkcccBk½¥”* !,Ó4íÖÖV÷Dû>>þŒ”2gYÖ–Öz XBl*¥¶„ù÷¿ÿý¥E@2™±X<:5µ;199pl»c{{»9“Í&Š…BÒ²í×qš]×M¸®w•VžTJµÖ†RÊ„ÖZ¢µÐ •ØÿÉðâwjjûÍ„B … P”ÒB8†4lÃ4JÁ`pÄV±XØ* +¶ã¬ƒÁ¬išÛBˆœÖºì8޵¼¼ì¼ÌL&£ÛÛ;Í׿þW{÷íemu5½º¶Z˜¹0³977-‹Ñ|.+•J1„ˆ OD””aÏó‚BÓó<Óu]0B µ0„¨’Q/‰+£ª“išZá»’®aJJé®ÖÚB”…E4¥P(XL&›‹@ °¹¹™=yòäºã8!„§µö¨”Z/¦ýoë_WI{öÞûIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/magic8ball.png000077500000000000000000000461721217176075400237350ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœÜ½wœ%Gyïý­ªî>iâîÎîjƒV»J«„(À$a@D'œ^ƒÁábßk|ß‹eƒqÀìkû:lll_’1Â#„@(®Vqs˜™“OǪ÷î:SÓ{fwµZüÖçÓÓ}zútW×ó{~O¨p„1†ÓQþü/ÿ椯MÓ”,˰Ïö<…Öm4Á ”B B „ÀS „@J‰)Æä׈â<Æä{@*…”’,MkRÊI¥ÔÖ,ËÎ4Ƭ6ÆÌJÊu@``cúBˆžâ¨Rê°/˲ýRÊ®"˲ )%ZëáÞ>σDqlÏicÐY†­5Ȳ ¤Yŵ™Öùÿ‹kžHùéŸzëüF^¼SúÖÓ´XA!ή̲ì²4M/NÓôâ,M7¤YV×Y¦´Öhcr9 H©B ¤D*…çy‘§T[yÞ£žRw !îBÜ!„Ø)„§”úp›0&û¯…ÿr(´ý²$MßEÑëÃÁ`m†DqDÅDqL’&$qBZ ) Ó,ßSØYƒ«´rÃa¥Êsàø~àøA% R©žQ­VßV¯×ßZ«Õn|ÿÏ…Ÿ6Æ´ž²†:Éò_B \ž$É/…aøêþ _ Â0"Š"â($Šbâ8&Mbâ$!I²Â¤Y†ÎR²ÌÒ¿FkÄÈI‰ÈH%ñ”tàãûÅT‚J€ B¥Z¡Z©Šj­öœz½þœF½þîJµúÇRˆ¿Ä˜ÎSÙvÇ+O{N’¦ÿk0üP¿ß¯ rᇄQHˆs$qLR MÓ|ŸÄ$i6üœe)Y¦]ž§–hßÏ?¤Ï'üœ‚*•  R­P©T©V‹­V£V«Ûh4>4ÖhüX¥Rù}!Äß>•í¸RyZ@ák­ßGñÿìõºkúý>ýÁ€pÐg0 ÃQ¬öGÄqÎQÑôéõzc‚€Àh4ê¬Y½ŽU«VQ«ÕܧÑj5iµZ,4év»Å½b”RÔujÕ•J• âø…öWráWª•5j9è÷{ôºõKÇÆÇ?6Öhüˆ¿ |ã©jÏQåé €«Ã8úÝAoðü^¿K¯Û£?èöùÞ2€³õû=Ú­Y¦i4êlÛ¶K.yçŸgŸ}[¶œÉÌÌL!´ ~à#XŠáã(b† ™e×có裲sçNvìØÁÞ½{9<{ß󟘠^¯Q©V©V*ù¾Z£V­R«Õ©ÖkÔû5õƒp@¿ßxÉøøÄsëµÚïJ¥ÞDOmóæåi!:Ó¿ÐëõÞ×ívÇzÝ.ý~/ßz9 ú}úýÍf“p²fÍj^úÒ—ñ¢½ˆk®¹š37ŸÉØøØ²ûkS~DÈbƒ(Ï£^¯³fõ.¾ðB@Ðïõh¶Z<öØcÜñõ;øÚí_ãž{îaßÞ9*Õ““Ôëõ%¨× áׇLBÂAXŸ˜xÏøøø‹=ÏûŒ¹÷»Ù¶£ÊÓ ›’$ùÃ^·ûÚn·K§Û¥ßëÒëåÂïõ» úƒÝn—……y0pÙe—ñú׿ž—½ì¥lݺ)%ÆÒ4%Š"ŒÑ!YŠøRhB‡ƒ"Ïć‹ºÓ4EkM\pÁ\tÑE¼éÍob÷îÝÜzë­|ñ‹_dçÎ!™šž¢QoP«×è×êÔ¨ƒƒ±0Žˆâˆ( Ÿ71>ñåZ½þN*CƧ „ર?ø›n··½ÛmÓíäèõºô{½ý>½nùù££yÁ ^ÀOüÄOpíµ×2>>Nš¦ÄqÌò„Œ“–Ïó‡ŸËÅ2‘dñ Ì£cÐZ“eÙЩ̲Œ 6ð–·¼…W½êU|ãß೟ý,wÞy'‹ ‹LOO/ ¿Ñ C¢(,¢•ˆ$މãdõD’ü]£^ß.¥ü•§*‰ô”@A–eoêözÿ§ÝnMwÚºÝv.ün—^§K·×£ßë±Ø\¤ÕlqÅ—óÎw¾“—¿ìeÔêu¢(¢×ë-»§-A%ÀS ƒ!I2æææØ±ã~öíÙG‡ìÚµ‹z0ΪõÓ4clß~ÛÎ9‡j­N­Z%É:Í6Ya:, l”!„àꫯæÒK/åÎ;ïäŸø÷Þwc1&§§rúóH%Šb’(Pò05&I&o˜˜˜8K)õ6ໞZ~J „ ÓÙÏv:µ[-¯ÓéÐé´é´Ût{=zÝ^—N§Ã‘#G˜žšâW~å~ìÇ~ŒÕ«W†!ív)%RJ 'y%%ÕJ¥$ƒpÀM_º‰Ï}òfv?þ0‚óÎ;53˜^=Éú ëÑ:cq¡ÅŽûâ3ÿüivíßËd­ÁW_Éu¯~—<ó2êãc4ˆã87E?Â0ÌLSžùÌgröÙgsóÍ7ó©O}Šûö±jõjÂ(Nâ$"‰#’4&-ÒÔY¾ýðÄääZ¥Ô›æwSO„$iò?ZíÖÚÍ&ív.üv»C·Ó¦ÛéÐíviµZÌÍÍñœç\ÃûÞ÷>.¿ürâ8^&xcLÑ»&¨7ê(¥ØýøãüÉÿù#¸{'—>û\ÿÆWsÑ¥Sñ ’>ýn›Ö|›D¤ÄýYUŒUƘ˜h …âС}Üøo7ñßÞñ3héñã?ú#¼ñ€5«ê9:GÇyÏc"â8àå/9çŸ>ûØÇ¸ûî» Ã° ýbKSÒ$%Ír¤™&Óú¥ÿìyÞù.‚@<ÝÁ:Ó„qô?æ?Ðl5i·Ú´;mºÅÞ2ÁâÂ"N›·¼å-¼ûÝïfzzš8Žó4mÑÕ›Ó½À|Æë Žåý¿þ;ìÙ¿‡úÁâòg_ÎüÂ<{öïAB’¤†Ld¤B‘f‚$ Éút’Ä B ÎÚ´Ëžu«¦&ùÊWnã}¿ö«Ì]äçÿÛ;yã¾™N§ËâÂQÒ4|’$¹/„lŒ¡ßïó¹Ï}Ž/|á ø¾ÏÔÔcãŒ3>1ÎÄÄããLLN191Áää$““·xž÷FcÌÁ©v«÷¾÷½§ôÅr¹ëÛwŸÔuBâ8ú™……ù/..Ònµhµš´[-šÍ<Ój59:7G…¼ë]ïâññ<(ŠÜ._ ·É6÷÷ÿ{Þó«¿Ê뮿žzË[¸ç[ßæÆ›?Ïc»ö`jãTן‰™^C×,jÁîf‡Cá€ÙnBäydãSˆ©5«W#ý*Q·‹šk®¾šÿç­oeëÖM¼÷=¿Æg>ù)ží÷0³z Ý^‡4IȲlè fYF†dYÆ9çœÃää$;wî¤Óé‚1˜¡s¹4f /Û|ß?OJù ;Ùö¿âògŸ´¬Üò]5B’$yÝÑùù-.,ÂnÑ.¶V»M§Õb~a¥ï}ï{yó›ß<¼RjÙ@c µj•þ`À¯ÝpQ’ñ'òÇ|é 7óó?ýӌͬeóöK›ÎàÑHóÕ›oaßãpxÏ.ægÄ1™0y@ ‚Zɵg°aËV¶?㙼øùÏcÛªt≠Æõ¯3/åkøÙ·¾•7¼æzÞóÞ_ã×~íÖKÛANzÙe—!¥ä“Ÿü$‹ óy'Ujj³t=Ưÿˆâßéèà»ÊFëg™;ò©…ù£õV«E³Ù*Ò¯Mš­&­f“……Œ1Üpà ¼á o CL1ʧ¬ýAPeaá(¿õë¿ÁÖmÛxñµßËÿþÈrÇwÒØ¸oÃY<¾Øâö/}™ÿøÜ§¹û?ncÿ÷Ó\X$óʯP©Öðê ¨Ö‰’Œ…ØÿÀ½Ü}Çòµ¯ÞÆÑV“ ÎßΚÕS  AàóÊW¿†É‰1~õ†¨×\yùå4;-’8Y.Ú- C¦§§™ššâ±Ç£ßïç€!A4üS˜3H¥.÷}¿)„¸ãdÚÿê+¯8%¹}×@J±æÈüÂÇæçN¶Ûí!Õ·šÍa¾Õl’¦)?÷s?Ç÷}ß÷ÑétŠØÝ;&vü€ù¹#üï?ø.¿ü 6nÚÈ_üùŸÒ û4¶lã@gÀþ[naîð^Òn‚ 3gmáÊg^Æös·qæÆ ŒÓhŒKŸv’2;;ËÁÝ»xüÑGyð‘G8tàþáßçóŸþ$¿ðŽ·óßÞþVé0üðýë×­ãoÿÒ8æº×¼Š½ƒdY:t Ý- C¶nÝÊ ^ðn½õVz½îpPŠÑC(äiªb<‚”òwkµÚ}À—¿Srù®@A«Õúã¹¹#uá·‡‚Ï?§iÊk_ûZÞô¦7Ñëõ†Â· 9í×ëuÚ¿ûۿÕW_ÉæÍ›øò­_& j¤^Gvïaßcv{ =žý¼çñæ×¾†«.»”ɉ 2“ÑíôéÅ1Ic’zµÁ†µX¿v† ·mãêËŸÅã{÷ñõ»îf÷#ò®_y7åßùè~õë7rdî(]| ùã?ägÞñvjõW^ó:0zQqÎ9ç0??Ï]wÝÅ ßcó“)R¢„@*H)ÿ,‚kŒ1sß Ù|ÇM€”’8ŽúÀïj-³pú úoµ[¤iÊE]Ä»Þõ®¡Ð-í>@)I¥Vç·~ó7Ø´q/¾öZ¾}×=,Æ)‡¢”{î½›=F<ˆ˜Ùt&¿ü‹?Ï»ßùs\tþ¹dZÓéöhµ;t!}#éO‘®Ù@X­Ñ“æÌÑ?LE4êu6o܈W«q¸ÓåÑñÙ›næâ‹ŸÁ¦-gòøcS¯\zé3ø­÷ÿϾâR&Æ'éözdN~ÀÝ'IÂøø8Íf“v»MšæfC€H!2+•ZÁ&)å'9Ž?pÍÕW’Üä)}ë$K‘å;öÈìo6[M:ív›v§E«½ä¦IB½^çmo{•JeèA—7eLŒOòwû(ó‡Žò£?þ#ìÝ·Ÿ¸RaÁ«ñí;ïdvïÒ8áÙÏyÿøÂ[Þøz¢$áÈÑÚÝ>ýAÈ NèÖÆ`Ýt¥J»ÕCŽ­"œœ¡'}zqD³Û§ÅlÛ²…g^ò äÌ 8Ì›üÇùÂÞNcf#ûfç8sÃ~èÍoàƒïÿ J=‹NDàn6{xÞyçQ¯× ÃH¨Ýj “aív¾ïõz? µþ~›|µjùŽ@J)ÚíÖæêv:´;-Ú6­v'Ùv›$I¸þúëÙ¶mÛÐAr·<¼JñŸ]=ÊGÿê¯ùå÷ü a˜00ЮsûWÿƒÙ}{ÐZðÊ×¼š¿ùðï±eÃfçŽÒí÷Dƒ(¤Ç ²Œ~Ð ]³U«0wô(ÝNŸ~¡×®£'ë 2Ä ý(¦Õ°jjš3ÎØcSíÇÜðÞßàž}VÏðàÃ;¹ö¥/abjœÏ~ö3ŒaFß:…I’066ÆÆ‡ì–ƒ E§Ý¢ÕÊÛ*o³&Lb¢8!LRBåÓ[E㌳˜2‚(j²7Ô|ëÐ<÷w"¢¹6r6†©u¤±‚….Ä}–÷<Ð-%²Öàÿ~+[·n¥:1Å7ïø6/}Õ+ø½ßz?W?÷ùd™Éh.žç Ma–et;?°CЩø>AP!*?ðßS¤ŠO‹¬¾3 Äú¹£GþG«Õ¢×ï²d:ôºÝe”õÌg>¥Ô°ò¯‹e,à)ÅC‡¸çÞ»øàG>€Pjš¯öF»ïnð*\uõU¼èš«8º¸È s¡Ç a%)¡„cã46o¥VõùÇæ¦}]úqŠ1|u²~›mÛ¶ðøåWbÁ‘ƒ ‹ºih(: ‚ÅN‡oë›\~þ¹ÌµîB[¶náá;Ù¼eó1‚w·$Ið< –½Çtº|äq% ¨TŠalÕZõúzcì*'• :Q9í>€”’Á ÿcs³GÖõùŽn¿G·›Áö˜Ù²gÏž¡×_ΠÙFR¾Ç×ÿã+Ì̬gËÖm# ¥àÆOŠÔ€¬×ùþW½‚4Ëè ¢ÜyDQîÈe†´6ëÎâ~ð“ÿöM>µã(½4CT**ÕëvUšÄ¿PöNY^§üÍŠbrþèüÛZíƒ^?ÑÓíÑíu –wRòðÃóo|ÆŒË(Î’dšÿ¼ý^ú²—£¤4=º‡÷Ü•›¶žÅÅçÇB»CÆ âˆAÑs§OWªìo¬âÿÆcüÉwc˜¬øŠeÞ†*>‡çö1½z5l=Óà…ðÕ2åa‚*íNŸC‡f &§Ø³gç_x>Íæ<Ý^4=–þËyÏ;–ˆµÖ¹À{½|@l¯_|î†á«u–mÚ@IG¯=rdvk8‹q|}ºÅ°®rE­Í¿í¶Ûعs'RÊcK M¯Óe÷£ñªï{YQkÉ׿öUzƒ¤ä¢sÏA)EÒúaÌ N$)ÚóÙ©Æù'³†{!m- &ª(£Gvµ)¡ÈZº2vîÅ0³*µ%ÁY ƒñbGŽAWªôº]À0=9Åbó(Y¶\Ø.¸£Šì€·DQD·Û¥×·CↃckišþ„±3‰Ÿ.RˆÅÅÅmµZ zýƒnŽÜ(:v´}é(Š¸é¦›Ø·oŸí1ÌÇ÷¥)&ÓÌÍ"Ò†í>ȵãþ;0BP¬YµŠ4ÓôÃ<ä ã˜~’’J¦Ê'Í4¡tîƒesV(¾âÈ¡ý¬Ù´ÎØccà…)p˜À+XÀ«Ðmw‰Lî.$Q̦[˜Ÿ=Jš™‘&ÀN\µ9‚Q€ýAŸÁ OoÐc0è/ËVÙÁÑ€Â(…ñ<´R¤xŽ6ñªu’8fDù(`g¾¢=^æëG‹Ó4eÐj>a˜ÇqôBc̪§´Ö...^F!ƒ0Ÿ¯7è÷—Å·¶Œ!¥äYÏzÖ0`"ÁA>ý™Ï°¸¸H­æÓì´©þðûYBù¹*ܳŸÃ ‹Ä™F(‡ä÷Oo£®3ïÚªÂ?¾òbÞó¼m˜nÌæñ€kÖMP‘+óô:-ö™ÞvLÍ@¥ ž:62ßc0 ŒÕªB¡M¶ŒìxÁ²öÛ®ãã•0 ‡CÌ­‚Ea´6Kõ íвS)§ Q½hqqÑ£˜(\ªlùÅ„T«Uƒ333lß¾(Š–…€Böïßǧ>ýö8À¦µ *u2S¥#òD žG«ÕáËwß^…Aƒ/U7И˜`Ï£"ëUˆSiǼ÷Ò¼pÛj¾öŠ‹ùÍË6¦edIŠ1yž'Ó†Ìä3ˆDPáÈ‘ý¬^»6l…ªã a¡P*_G@ `☉U3„Y„âhpŒà]°8‘'IRL3 ‡³¢Ã0$ÕéKžŒÜN:Îó{½.q¼TÉrÒr_¡R©Ç1ƒÁ€óÎ;µk×2 –åÍ=Ïcnö0ÿ»søÈ,ʃ°Ÿç¤Œ„„ Âmìæ£àÌZ*6³ÿÑÒ“PSüÆ7vóp;䦟O/Myë×ãg·¯ãž{×mYNRH3Æ 1Y;DøúÍ6Âhg“ÓàÌ#rJ!Ôë5ž!{L®š¦Ûê Èý+pnŠøD>ävÞ~F„aDÅפi¢NUn§õ7[kµš—‡ƒQEyåÒ4=æZ»ª—mc —^z)•J…(Š–ÙE¡ssGyðÁôº}ó‘ÒµÀgㆠ 3„”P«£g6°sr ë.ºÎþ½ÄªRÁdåû„I§÷-RQ’×|ùa®Û¼Š?¸ò,"-ø—kÏç™&ØqýeÌýÀÌýè5lÛ8…É2°8w˜ugnÉÁÚØ’ i õFE–%lذž¹…94’(^*n‡—CB`Å(À-I’³k‹bÄ!I’lLj§*»Ó­õ¹ívkcœ$ù Gù$ÈQÅ÷ýaÚ7§µFƒK.¹dd:Ø#e›‹M<@£QçÜmÛ M¾«×Âö+8û…Ï'm-2wðªQ>ÓNTdš‡{¼xÝ$‹IÂÎVH;ʈã Oz 3Ú©áà‘¦Ÿ@½ÁÜ¡Y&ë5ümçæ™ÁÀ¦‡…%ÓÓx:!¨Ö™^»†½{vxÞ2á»ôoµXÇ“päÒ4Íû6¢˜¤X» ‰ãZ–¥—ŸªìN Ò4½¨ÝnûIœëôD¤#œ?È“>VÓ-úý>k×®å¼óÎé! ÝíðÈ£ +ýŒ‹/&¨Õal¶^Èô³¯BF†G¿½‚ Y1Ò.òuþ~ïïúÖ~È2þôÑ#Ä™àGÎ^ÍC½.{æú|óè"?yç#lmøüø%ë!N©Š¼ Ý\`ýÖm03A-¾’( æù¬_·Ž¬9ÏÌšUT…bïî}tû½bÑŠx¤÷*Þ{E$QD'$qÞÖY–m?UÙ–ÞÀ( Ïô$i±6O¯h×Ò4eqq‘ –eÁÒ4eóæÍÄqÌþýû—Ev–Í}÷Ü3 ™.ºp;k×­åàø4rËù¬]»šsŒOTéõSL€AJ Â!ùÄ=û@HD½ÂeÛgO5ØÕjØ>=ÆGϘf!Éø›‡ga²Ab$"PìÞ³—g^~ÖmAφ$F¤¥V¯YÃÆ‰ :|׿þµÜ{ÿý´Ú‚FŠD` Cú/{ý¢XðòdK’¦ùR8IBçLµÖO-úýÁÙa”O«Š‹Êï¥<ÈÔÔÔpnŸâ%„`óæÍ,..Òn·‡vQk Úpß½÷±g×n6oÙºé)®ºâ >ýàãH¡éú\¸} ßûì³ó qq[3×Ðlu˜ »Ìµ̵»$iˆÉýÅ÷͵ j ñ¸ì/¾ H𠌨±*KQõñÑ&I7fjËY,ì{ú]T–Ø~Þ9QÆ<÷y/âýïÿ-2&ÓÄ¥ Vøö}Ÿ( è4’ÙÁ§ IDAT-”,"Iâ8%M“-?÷Î_ø‘=á”à“À_ôïÄ`Ð?#¶\’¬Hÿ¶´Z-fggY»ví0 hgþ,,,°°°0ì0Æä½eưk÷nn¿ýklÚ¼™ KyîUWqë};éÛ·L3Ô=Ã=³síU—sÅ–ì»ýßyþ5Ï¡Ôø‡¿ý8RyÅ8Â%áC¦s…îv¹Úïž+—ÔN/_r”=­³ÕÀá'*¿' €Z­êeYXá§é‰³Z¶,,,P­V™šš"Ë2޹ÆN²Ô:_³çÐáÃ|î_þ…³Ï9‡ªl W?÷yÜòÅ›éFR)ÑÆ3€4(Ê{ïzí¼óHyàdÕ:¨ :ü b¿F«ê!}Ÿ=µ:ʯ¢<Y©Q­V¨V*xR-.î{„nÝÀ›ž9ÝÝ1Y­ðš×]ϯÜðËž›£1ÞÈW?/zê¬y³ï3J¸.#¸ 1Êh­‡«žfùÞ˲lÕ©ÈïI Z­GQ%ÓZç“7žˆc3;;‹ÊWå¦Û펤BÛmlŒ¡ÓërçwrËoáE/¾–zØåœUã¼øbîßñ à£ÃÉ–ùü+YjoZƒŠ ñ@ÅPäóµòAIRÏ'E‚” Œ‡o8zˆ¯©ðK¯xisž^¿ÍK¾÷%|ñæ›ùħ?CP –Q~¹Ÿß¥}»ä¼ ;SØ=ç~×^“êl¸øu–e*ËôøI7ºSž4Œ1*Ó™)VÕÒ'=¥ÈGÁ>|˜F£qÂÛ°æ_?÷96nÜÀôêÕLô[œ;=Nwý:öÎ¥Ÿy$ž‡#Št±”ùÞK™÷% ¹Ø iIœw˜ •¦¨$Ä4çùþ‹Ïâ×àÕ„ý>ûzm.½è"çøÀ?D'Tÿ­/ÚéA+¥FÎîYé.3dÚ®|ža29ÅaA§#d´Î_ÖFŸ”ý/—$Ih6›'ÅBÂ(âðÿéŸéw{Lx’ñ~“Mdóä8SdTÓOgÈ|Ѱ@pÁ0Ü/ïÝCù =¤?Kñz-¦»ó¼û{žÍŸ½ý-¬o Ã>gnØ@šf|à¿Ëã»§Z8´v“òæyÞÈón(\‹í9wj¼ÖùÚFk2­såËNmPÈéÈH0Âd:_†ýIŒNFR_¹!èöû|íöÛi4¼úúײº^ãðÞý¬GP¯r41,¦£Ih%1xKsò…±7[ÚKY,mð² õ© :<{í8ÿýe¯àϺ$v·Ëº™5ìÞ½‹üÞïqû׿ï9ºÞ£l}ù}í(_ûy¥‘>ÃÅ1Sa'•œJ9a`C¢´yrŸHBÐì´ùâ—nÁ`xåu×1èõ¸ÇNVWk4ÌŒ­¢™ šý½ABìŘJ –F &Ÿó/LŠ"×úz±e¼Ê+®¹’7_ñ ÎZ=E”ÄTƒ õZ{î¾›ðCÜöÕÿÀó½ÇôÁòŸ)›‚QΟ›%,aèKÌ ×0§Ææ§# lz¾—w¡?A¬äð Øï7Ûm¾ðo7Ñn·yík_ËšÕ«ùÖ]ßF¶Ž²¦^ãìg’5&è$š…^ŸùV›A<@g!$ á)„ôPÅJà«'*l›ÙÀ•[7ñŒuÓŒ+ˆãˆ±Fƒ^¯ÇÿúyþìOÿ”û¸Ï÷+|ûN°´L­ËöØú £Ø¢&æÈÛ0˜ŒS\’þI@)™)¥ÚÀÄÉ~çxÂ-‡@'s¯Þ Ï­ÿþ<Äõ¯{×]÷ |fgQ‹‡™ª*Æ6n¢ºú´çÓêäÓÔ’$)4,Ãóò)XU%¨™”UÃêA9ð©Í¬¢R xàø§O|‚Ï~ö³™›£R­ž°Ž® ]—§w[m_É\Œˆ3©!5˜ccè“(O«V­ŽªµÚ!cô&N,¯“*,5Þ‰#„ Õ÷ï|üG\}åU¼ìå/ç’K.a†4ÛmDØ¡Þõ1Öyšl²Bš*Ò4!I #tÔǤ1¾¬©ÍpÖºÎX¿ž#‡ñå/}‰ù—ϱãÁÉtFµV[V/÷x¥øÞý_VÀ.Ý—CB7‹˜û¢ðoEb`þÄ­lyÒø‰{Kú?ÿ×ÎÃJ©¼:'Vù¸Üp£LÈJlàÞÃÒp³Ýææ/Ý·ïþ6ϺìY<ïyÏ㢋/bÕêÕTj5„PÅD‹>Q¤I¥"“†`¬N½–¯üÝhÔ©‡âß>ÿyn»í6~äaÂ(Âó<|g|b¹eá—ß«,ø2Œzw÷§éìsKàŽ&q|J?OsZzÆnÏóóÅNRÃG œ#/SæJ*Ï"FÀ|³É—ný2_¿ã6l8ƒóÏ?Ÿ .ØÎ–-g±nýz¦&'™™žByùÒsqÑn·yäá‡Øýø.xp=öóóódZãyÕ‚òGÕ½\FyûîùQ 0êžåß'\JKÉä×ï5ÆœÒïœ~ðˆïûH!WtˆVØJ™²ãÙÕîåÞSJ B§ »öîe÷Þ½Üzë¿S¯×£ÑhP­ÖŠ„‹&Šââ‡úÄEo¦R Ï÷ Jqø‰P¦{·þe»îîG1HYø›~¥Š¥”DJ¹÷ÿáïO)<-˜˜œ|°V¯!„8‘Gì iùr¯y±‚//¼¸Ré(á+¥Žƒ­WÇD‹‹,4›Ç\£”B*E¥RY–€q7ûLw£;mNd÷ÝwrÀQ¾Á².äâG-•R(!1ÆÜwr’:¶œxž·czzº¿[ÐPjå[Ú³m3c.lºWJ9ìEby¯™{/{\¶+@îØƒ²G Ü­›ÑÉ8²ÇsÝpз ‚ò*iËŠ¡è9ŒÖœ°B+”Ó€,˯š^u¿TêªQSm± o…o‚Í+hµßŽ´ÃÅ`y£Žl˜B†ã¥lšÜsö9vïú%£j%çÏõuìq9Ù£”:†úm‘JáùÊS(¥úBÊSþé™Ó2(ô?õ“zfíº¯U*U<ÿØU=qÔ Aþ«[µZz½N£Ñ ^¯u«R© °q”v®¤ù£„éæçÝëË9y÷Ø>w™‰(íWúnùÿå~€2OHÛŽ98<<å¡”‡Tê¾,MœªìNÛ1SSS_û……ù|¡çQs`9ýû¾?ü/»V€]EË]޵§#í÷ˆÆ<PNÔ ã2Áñ|Q¥\_ÛÃçæûçìÏïXú=C_ËÒô”;`N+fÖ®]Ø¿ß*Ï÷GÀm`Õj¿H©c†Ô+ÛϲPG q”íwY¨LõÇc9åR¦~×d¬”ü){ý+?ð‡ù!øÒ©vÁi€âÈ–3·|ùþûî}Càû„¥å`FÙê2Ø>pwôŒ» JÙs>‘]·B.³Ã(F8ý®èŒ­ ¤•¼ÿ²—ï^ã^W~–ÛJ)ßÇ÷<ÏŸõ<ïö“Mxl9mȲ”›6ýËøøÄÚ­öH§È·­­õ}¸VŽewQEKŸÀ2çhÊŸËÎàñ®=QT`ënëXÁñb—öG™„Q‚/ë;ù¾§ÔÍïŸRÀð~OæËË‹`Íš™7nÜxdvöðZ»öݨZ)åk܃ïûÔìæ6°Lx+ÑûJB>žðDX`T)k¸ \WØö:×Ü•£ò–/YÁ÷}jµê§ƒÀçi1=Ü÷}ªÕÚüùçoÿT%_Ôpøv_Np¸³cË+^­d‡çÜ­tÝñLÄ(o~¥ÿ­4’çd¢QŽj¹în)·•M •Jþ;ÈA°«^«ßìûAœ²ÜN4›‹A…­ÛÎþËuë×ÿd§Óñúýcã]ç»±~ÇË´¶lóËB‡Ñqÿñ´ýDš^N9›x2 P¦×Ãw…8JóË÷•ô>>>Ö³¬pªå´àÝÿï/!¥ä /þæ¶sξeÿ¾}/÷}¸F€ëñZÍ·¿´å:}Ö´±ìà†v<»}¢ÿ2+ÆýŽ}ö([½’çoÍ–}{›Ý´{Wø®"còÕBƒ€j­Öß´iã_ûžG§Óáž{î9e¹6‹?‹o~óF*ù¡uë׿¬Ûíw‘—Òl¨g7·¡€e 1j •ÌÀJB]É?8Yß Ìn=Ü÷ƒcGþXÁ»?*‹8Šö­Â(¥¨!s­Vû§}{÷>¾cÇ<8rž“-§¢¤ îxà‹—_qå—êõúKìúÿ®6ßYæ$Z—B.ÜðÏÞãDvÿDš^öNÄ+yë®ö»ïê^cAàöqØï¸~‘;§0oMÔò_&¯ÕBŒþà7¿ùMæææìÍOÙ |Ò( NÇ,,Ìÿöš™µ×v»]Ù+V·‚B,›>îR~y Á²£è<÷¸Â?Üã…ˆÇA¹Œ2Vèö;V¬¯c¯wµÝýmüz™ÿ4}­FP©|¢×íÝ×l.û]ÉböË/§ €‚w+îÇÿÒUW_óOGf¿] –„í{ÎzÏe{è.¢4ÊÚž ŽgŽ‚r)Ó¸{¾œÁ•oATªõõz½Óëv>°oß>’$YV+³Ròe…rJ8ð ÚíNöÐÎï›Y»ö½~²ßë™B+„ 725> ø¿±副$ø“ÄÉ8‚å½}v©žÀ±ñþ‰(Ôo ¸+ˆV«5õ`þðèÜÜ 6|?FØEûž4žp`á‹c7ãïÛ·÷Aåy¿==5e³|¢¸Æc[¬¤aJ 0yq™À¾€qcìù•q"aFÅñ£zGʾï(°Øw·wײ[4ê *•êÃsGŽüþì‘#Bk-Kí}22YžNBøö³¤1Æ?2;ûSÓ«¾Z¯×)À©É…&SØ:e™)^Z€0išÇ:<.À‹Æ5Ný\¦0£@° Ž޲°G%…ʆ­Ÿ[ìû”—µ ´”’Z­ÎØø8Në—gggâ8öKmý¤@pÒ&àÂ/WÆ‚À›=|x0è÷ÿûøÄäMQOGùOÁZ`Œ±¿b®¥”–%,›'T´×™R Øï;÷²`RJSÜßÃpHÛJ@qRªÿÐá³öÝ-£l½+øòê¡v©Z­Îøø8Ƙ¿™=|øSaVœw¶í`JŸ—ÉìDæà¤à _›rŽÇÛíö]Q8øµÉ‰ ­”²²•ÓŽ·öÓct!pã4`ù}lXa }û?…y°×h+øB°Â2†#pûٔΙ2PlÊM5ŠîËKÇÚÍõ|ßgl|ŒJµòСCµÛíú€_´­mëQ28Ù Ë©ö¬$ü29ËLÏÏÏLùOccc¶‘´m ä.œŒ˜vÔ‚£T/ËVãua"´#`»·q¥)êdÔ[Çå3S.e­/´ÛØeòÜmÙê¡ÅR¹õFƒ±±ñÞÑ£G~qaaÎSwÚÖmë‚àxå„ '"| €Š1¦²¸¸øÕZíîZ­6’–¬ep@`2+ö¹Q0Aé͆”Xªþ €´‚´×ZívÄÒ¾K±Ú¹‡­¯­¿qâw“¦é2g6Š"DZ±În± Ž4MÑÆP«ÕÌää”éu»ï›;rä?µÖ“¥6µ[¹íËòYI†Ãr\‡úÝÙ XÚ·{¯Ø,uÅqÔm5›ÿ«Ñ›-z°lƒÚãáf…]ü_ºl`ÍÖÚÃF C9÷qÆM––éš [ÜcÍrÇS¸ U€Ñ8ö][a0që0 ‹%tCQ›+‡›J¥ÊÔÔ´ˆÂð/ØÿwY–MígÛÓ Þ¶¹ý¢á Xﺌ°×YÛ-„°`…êÜ‘—Zk=´ÕZk!¥:“´íP÷ðlWh­Ý“›S…¥páоI’D„ah)_86_'I"ák¥”˜šžFÀ­üÍ,Ël»%¥övKV´•tö.£ºŸGFO$x2vß¾?b«, ÿmcô‡ÇÆÆ¡ÛíÔK½}nhc¥‹úËëë—µ{Xg¯È#XçÎÃ8Ž ,Ž%¹?PvD­Ã‘›¤!Hœ°Î8ÝÜÖÞ[ÇOÄq¬ã8–öÚ,ËDš¦xž'¦¦¦QJÝydvöÃEïÞ³\³+ìrHèš¾cÊHŒÐþ2õ»‚wµß2‚kûƒb³ð*„axðg±±·õºÝZ‹æü-^hr–e™,ªi²,…—ïjB<Àp©z{BcDq,®“Z묫'¤”¦¹æ»cº]–³ï°\ð¾óÙ¶¹= =ñ0p…boîú£òþåÍ‚Á56“å !jBˆ1rpÅ7ƈ$I¤”¥Ôj!ÄDá[áÃR#êBà©BÚ©¥”JçÝ´VØF¡•Rª”j3F–E\†[f LY µN PºQît¥R‘žçõ’$9EÑcL*„¨!%ŒÑ¢]¬†ûÅqÅ9gÏ[mO‹öKKmŸq,kËâüŠe€ãxÿ+eGÅÿå^@Ÿåaâ2°!ªBˆ cŒâXºæІž“Rö¤T“`ª¶¡‹kSë¨[ ;oÞ \Σf)¤DþÛ´ÖÜ §7÷±æÇö?HÚA€ò¼Î²f¯×[ÐZGBUä+0FgRʆÖ"1ÆôXŠš¬-wͤeƒÌ9oi?e¹2®4Rh¤(„+1À(Û1 £Cev(û¢hl_Ñ(Ò”žKôGqOk^BøRʹãHX›=d~@¡"ä‚ΊOmi!øÄ©·ÕSÜÃ6tZÔUc’I)ïûR*Õ7ZwÂÁ ¥µN ÇÒ3ÆÄ,w,…”rLgYjr? ¬Í£”ƆÛiéœ(íËlà:‡ö½€SKÛcmep·‘…ð•1Æ}Y·r‚%ï_°¤‘Ê“dYÖB„|cŒWh",%ŽRçûö‚ †áÐ4û\Û°Òy¶‡áV°¼2ž—()5j­I’¤Æ˜Aanl{¥Bë¯ B(Õ0Y–8϶ù—I]M/ {¥ñe'p¤/p²X±¯Ù9?ªråJI¥Tà Œ%çÅudlƒ'ä!£E´ë cLZÜ#BÍ rx4¹–*Jw¥®pž‘±¼&!yG“Rj‘§†3cLœ¦iV9&•Û‰3|¦ÍWï 1F ¡”RÕ,ËbçzË£ºÚí½W¢}ws}š“ËžDq%KŸmq+gX‘'XÀÓyƒ­äÛ- ω+ç^¶ÃÆž‡‚¦‹ÐÊÚZÏ ç†”X܆ÀV³¬º å¥BØM*òÞI]ä'ìù2S™Yav¬•Kú[S’I)=)¥¯µ¶ -ûX°œ%GEb£úkNXN€•òÈ£CׯÀ’3eÿ_xÀ¢ªµÎȵÒ2š'„ÚA“¯~iGÁ¦@&„ðÏä]ÅYqìfÌ” Û‹ž ¡ ‹À6”P'›SðYE¯è‹v‡ž ‘³ŽÕT ج_Z:¶õË °‚N §RH)+ƘÈq‡\Ƴ²pÛçüJ4omÅr* à&)ÊeTGÎÐ~*¥|Û9ÃRˆ¹p,MKrÍò„žc7mªä *ââ=¤B«X¢`WûS–Â.ŠgF0ìL²=pEíõ¬çm7;=vÏçÜ„ E'Q•×ir;¦¤”A–evmËeߨÜþ'¥é+•'37°œ–´•qS·ÃœµÊWTE¯Ško…"a)Éa8¼ÆR:KvM !â°ó 9õÚpÊÆû]·žV;3–B.ûlã\8õ26špÞ5s¾£Wøœƒ$+èÄe†Dkm¤RBy†â¼{-n’È•Çù¼by¢XéACA³<„ÒäÔH)ý"¥kµ†‘ØP8öål²ÃõÒ­Cc…!„IaËE¡Ínq$·ÞöÞ K>ˆf)%r¬}ŠÊ¦,×l«í6ª°@¶ÀHk¬goÏ[ÖH “aŒQJZë.KŒÛ®e:/³ÁJ‚?¥L`Ù¦—ê¾è2mgyÆJzžgsêîŠÖ¶Ñ,uzÖÐ:ù A‘ÕeÉ‹OXÊ”y…Pl.Üú 6š,1GæÜÓ55£lkùL0{Î:¡6”t'è[AÅÎ÷íýbrßA~‹ýž&g¬è£yÎc —MÊ›­“[gXþ^+–'š vË p¡aºRJé™·aCÕ÷ §,.ÎI±4º')l¶W4˜dÉDXa[ÑÒ¡Í;Ø>uU»á•q¾S»ÜðK—Ø©ü~B, !³Úê ÊÚúÄIÄÅ;Ùè@‘‚.¢˜Ì`åyŽãËYăkìgW.£d6²œ,\ÛÃ@™¦l……çyõâåäˆ{ÚkóáÁy‘äž¼¥ú øŸ_4ž¥m·óÃMø¸Ôoßϲ†ư3©¸ më༓듸fÊe ×w±šmQkRç3N½ÓbKŒ6™T¤R)£s¥±›k:\0–Ù×=¶íìî—•“À¨”…n_Üm)¥TR*’$ŽÍÒX}Sh†íÒ…ÛÜ\| )IDATdõKçÈ=岆±©fÁr ¶6Ù‚¡ïœwA9šì¾§®}ŸahëË’9±× Q˜Ã’ëjîPð… )"Š"ÅœyJ‰x)C˜ÛJŒàÞ{S[å8+`%ûáÞ°lïËÙ?|߯€IÍR§mdëiþYSAî Ø0Ð/Â&nŒQŽýû[fXî4¹ì`§}Yö°rË&ˆ¬±CÔmè:¼nxèÚü´ ÿrı  ,Á¤Hébx{T˜Ò&KÜ„Š"¶u†\O] ›²BÝÞ¯¨ˆ÷Ýþr Ÿå)h餄Ýbµ>ñ¿¡‰ÎDÖ¢XX ºæÊ ß ,ÌF Œ™1Fᬠ2£Mb¤N•’ZRc†&Àn©³w}W&VV®ÌŽ)§š°pC+‹F‚ ‚1&.B¸²çjÇ^¡™VxV‹¹-œsÖŒÄ,¥‘Ýþ‚ȹ.sî羃MX@Zí·u} &×î[pç¼ë¹JâvJÙz‚5) ¡2)½$ËÒˆ%g°¼#ö#Ëí °”èš‚rà „0¾ïé0 Ó¢ÓÄ>Gc‚‚FÝ‘-Ã~î"ZP…ÆÛåP,0Ü^0X aÉ–´^’§€Kƒ=,H\€ }”Âiç9¶‡íPb…ÿ¯µk[nÛH¢çtÏ©K¤\µcç![•}ÝÝÇÔþÿW8.Û•d+¢DÀLïfÀ&DÙ^ÅSʼn9§O_ ŽÅÕ…ù>•e¹,óÀU#²d@bAsJƒ÷ùÞ TÒË  Úˆæn îÜGÒpS+cÿWù÷LÄIþ`fû;qì'ùµ®?¿4 ^rõĨĔ²hÍ&Ì‘Â_o¨ûšdÔ>ã¬&?_ 䳞ù28R7Ð;b$3 0`Ö‡Ón·«1B¿º€yð¾là Õ¢Ûc A^ |…­ž”,NN‚ÙXÁÞºI*ѼË÷2_?“`´fA¹ðƒÃ¬Ã§x¾\Ý„'G.û­Yˆ'iÝÆû÷9ø>ÕÌn=+çTûcêŸBüÉjKÔ_÷5ÿT€séE$cò*pl»¹õ°Ý#Àðn`LùŽ©ëZ³œ{Œ–PsèŒbõU"Ë UkŸçõRÀžn#s© q¼õû(¾ÞÀQÁ÷þ}ªñ;‚Vн¿Ÿú˜d¿®ïc€j¹“aT2Ô(¿¬èÃj45 ¬Áá—{’¨!„¡dÇ¢ÿ¹ÕÏã€{ ;ÖG_®Í»0UÅb±ÈëõM=™jaSJ…ýõþƒ€$‹[ ö’Ä[=ÝÇÿ–EÝo9s±Ã<3Щ \ïð=S÷»NÓ ô©ã‚ö€û л‚9À‰")Ęº®óÁ¢_ϧ™sßÿA8JÏÒƒïÛÇ<’DŒ1Ù½Où7öÀO`®ªæoÀ¬ V9®Ç:-Ãø:¿*T(S©2O’¢Ê©f€À ¹Jœ[ð–2ß±@Û¶9ÄÉ)ºŸ‹¼¤jEâ}ªçÝÂ<@q'À¡ÀVÈ ªˆ!2Ä0=VS<«Çl`z& úñaÏ\ wç9φ¼úÕ•'ù/ÃÚypæ±Ò1 ýïD ȱ‰‰û’ñû¢}_¯8 üܸ?ÚÌHp¬e<==#ÉDДޓûî8-1Ó]³~=oõ•(}Ùf’xŽ÷å³m[ !d¡d@9ô\.JYÄ@TU‹1b¥*il»ÝæínWŸðÖîUíÀ긯ù£¬×XÇJÇß®‚Êý%â=ˆLH!xñðs¿<ŒÕÔ{GÐ< ¬¿¹8Y)‰~µZ¯ÕdzVþÊ<àPÖ}}ßϯþ´Çš¦ ËÕª¾Œ‰)³UCGQæòÔ°„£wë1f Ò.i¹ZI·ël}»¶ÍfƒR¨àÔ¸ º‰yåm* 9àšÎe|úMÒ(LMlæ5ÿ9ðÇ@¿þÜúÿ“³ áhv4ä š)œHC7à­Þ§vž(> „[æóûj*"X­V<99éRJÜî:2¨IhÔDØ,÷=SÊ431C6Ž·Aš€ˆ*ˆ!ˆ„T…§MÃåjiëõïÞ½Ë}ß“ûA#æCžM«u{ùŸ\ÁÌ=T¢X±rC©ˆª…&æBîºÎ+@ÝߣÁ¡ï!˜¨Š„UjŒw^]ß_üòƒªÜ‘u0›2¨òüü‹E‹ín'CJDLÐg“4ô–úˆ@}iLåh0Ò =’Q1"ˆ`.¯²åo¿þŠÍvë;ÝÇà¦yöÝÏ;f½ÕT2d&BSŠ51æ¶ms×uJ÷Þ碶G¹€#$@ùs´mƒ&F£h¦TØæšÿÌ á÷ù½'……äêòR–«î¶;$Šä 6tȆ ÂDi€BÐÒ–ðž07B¨Øä„îngÛ!ÉWgù´mi0;??gÛ4ööí[¬oo½ß¯ÇïûbÐ ªµ×ù37Q¸J#%kP‹1…^1Žýܾ§VRëIñ軂(AEsŒ1×´q>pèÍ;J„ Ÿ_]ñêóϹízX4ìSÆ@ &B£ÂtH)ßGP&gÀ –3®û„Íï×öôò_^œq×u¶8YÊÓ§Oó«W¯°¾½µ#}{Ì*kwXni~=O+ò‚…L¨s럫ÏQ™øÀ_»-ÜWÉ&"èøP ªPÑyœÜyš·X,XÆÜñë%·ž0áÅÅ9¿ýÛSf[öCf—IÔŒ"&2–xÊŽD JPç—u&Õʯ™ý|»EÒ€¯.θÛlÐHkϾû?¿|‰íngÜcè;ú໳ðýŒŠþŒu[ -¨ZMlLõ€ÀG€ÿ1í/Àÿy•šþëßb´ÐŒ¯KiØ?”9ŸNßË+äyww‡aŽ)Hf!¹\.ñüùs\\^âÍŽ»nÍ»ÍI”YB1x!*®R," ¾"V§$9F†:ò"g{Õm`·;~yº²îvåÉÒž>{Æ—/_šå ìIP»c*ûùÓ‡ƒ¶É•Gë±AÓ¶¦*ǶÛÿá#Û'!€?ˆØD[´­ÅÐ „!‘ïËä*Œ#f‘$V«·ã;~´9†À'OžàÅ‹ï±îz ¼þó5–C¬#C‘ 6 š BªEIp#ˆ*j¢ª”Ö§Œífco®ÿ‹Ø 8_®¸Yߨ_|›?oð˯¿LãLµLOM 9£‡›Ì”¡~ a$@Ó´PU»Y¯ç*3ßæQí“•ö§ŸþcmÛZl"BŒ÷Òg×&¨*¯®®B03cÛ¶¶Ýn±^¯kƒ2ŒHòtuŠü>»ºâææ¿¿ù…ìüˆ ¡Äª’¢#ȪÔd¹QEPVòMb],eK93YF?$4ËSë7·xóîš‹¯¿6m[Ûu_¼xn×××è‡Ç.$€:ØCòì}ÿ½™ý?Bˆ›‹E‹Ø46ôý'øÄUÅéé™ÅÑÄAC°{YŸ~_^^Újµò»àÕÕJñ!ŒùŠ‚*ž={Æþþ6}âÝ7ø}ÓOžƒg— í¢¼ÂE „ŽB62‚TÇåïSƆœÐ ) †lÅ:I¬–+¤n‡LÅ6¿Ý¬ñígçØþñ›]^\à›o¾ÆëׯN/ˆªqæÜmæ"ªQ 6 bÓX»X išƒaï?ðµýeÛå>“kmIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/movie.png000066400000000000000000001053041217176075400230370ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì¼y”dGuçÿ‰ˆ·äžUYU]½T[­]BBb‹X cÀ`ÏŒ/x˜ÁöàíØÆöŒí±<¶‡Ÿ1f1‹Ä. ¡í+ê½[½wuu­¹ç‹÷"îï—ÝþÀÖáœ9¿qNž|™ù^¾ˆ¸7îýÞï½ñ”ˆð£öÃÛôÿíü¨ýßm?R€òö#ø!o?R€òö#ø!o?R€òö#ø!oÁÿíüÿ®‰°×ã¤Îã3‹Ë2ì %Ë22—9‡¸Œ4sx—á\†d‚Çã3NÞ9DñxïA+<å3…(…2 DÀK3ÞñKïùGý ˆ ŸK ‹„QD` É`@©\b0„!åR™fk‘À„Ä…˜~§G…з= …ƒf&Äq„Æ`“„( ÑAÀ ß'Ž#JÅ2íÖ¢ •r™d0À9G…qL¯Û%0šb©LDF$ŸD¯Q ¥QxP­AIþ. A”B¼Ñ M‘ŸíM~ú»a'Q(5üíé«òþ ÿ+)1%¥Ô*”ºdŠUâå|`#Pu"0ˆ˜§×“ð̵%8Î~ñÌ%'™@*d ŒD³ý† Q¢½rqµØz’Jù~ïeI £¸·Ýëôþñƒ™zå ÂP¼åÿñ_%¶˜(97¯2ÚY‰*ÿÐÃßó)QgÏċΉVtŠsÓ&ÃÕ (¥ÐJ‘ßÀçÒ’§Ï—só÷œZ¸¸Z„‚\ "¡ÈÙùŽ`(IÀpü‚Ê-˹Q ÏÆç=x'D¡¦X!p™Ç9‡OçñžÀŠ‘^®Up­Wñ”ÎÊq1ùÊ>u§îñâ?×ëõ÷c볌·ýÜ÷V„˜œòÓm8ž¡Rø\°<ó;@ ZÔp}®ù ”äÇJ†S) ´B)N­Çÿ_PhEnê‘\E?=ÿÿŠ6<õàí^äu(ª¸g*3|··Ì]ˆÏ‡ @† (±^˜Öð À 9{±:÷*ø/²2.ÁMî>pâ]ÝÄ2ZŽQºÀؘa´<‚%£Ùéc3rÃyö€vCKA h^.ž—£å÷£baéæøúþû½ÏfßþïéYÇýO¯jxÚhQˆÏW¥ÖgͲBëáäO Jû|Ò•Æ(r tî pœ3Öè¡ÙQJðtè‡wThå1ˆ|·)~Ƣ̛”Ñ£À½—Ÿð¹cùnóýݶü¬:xà= ö{á!eTS)íµ§3商¾ÍnExÙ9‹q®ú–büuT0h£¹ïþÃÁwÿy…he ò![7.gçyh¥]Rç½Bÿ °Q2·ô噸emÈ0CÕGÁˆ~9Š ÿñþ»_›_êü·ÿô«ÿõÿ(µ¼ú2šÍ%¢0BiO¢b›¤„qDDt{Â0$ì`Ÿ‹"É,Q¢Ò,% cPàKXˆrp8° AÑét0&¤P±6ûìXL{T`(–JdYJ1QhœÏ]ˆÒ¹2* ë³? Cý«g•×ËY³C 8È6õ´eDHj™Di *WÏÅÅ.Z)L¨krÜé‡îN(üó#»¾i`Sœ£$4&¶>|à1Z‘zÁv2æz-6L,çªË72»4ð¡!6FeC3 NŒ”‰4¬óÎÍÚ³§µæè±£W £ùÛ~|ñû)@ný†æù¬ùözÎzÇø=½¼—ƒ3ö?†Pm(,Dᔀ¯õ9 Ö¥¨§m„WÂð2¼óÄQÀEço"ІÌù!ðËﯨ#Ó³]{ŽÇAê…Y­ÍÍÆ¨/h¥îò^6{ä1 ÿ‹VJ™¹Å~~3Éûá½ »£(*5ã•_“/2 ^„AœíÛ°y%£qe÷?º×5SK¤*Ë=$j•˜N¢é,ïp΃bré’dÖy-çmË ÅÂîÇyè”d¬=ÛÓ@Á\+¹ø·)€µÖ¯\¹ê¯¦Ö®½ò'_ýò‡ÛÎC­……ÃišÞÁ¡;ßÝþn œ8B•‹­ð rÐ7”ÓY%‘§¸B!CäÍÙyR ?¼ÜÇ3‡9¢ÏÕ " ¥—c}Ö¥ˆgvq‘ã§f¸hû&Ð&ŸY¯B7”çoYºÌ±Øìþ}¹þ§ÔK?µyŒ¿´Ô®© ÂÉPÔY—¢”ˆw ´R(¥ul7Úáxàë²µOOPˆÈÉç¸Q›çzíçÆ¿uóê{î~àIa¤®bïF§èPÑu–ÿðšK9q¦E&«´k-öïé6Û¤Y¯ýþïó•›?G\,’¦~ü¬< B愞ͺÏ&çgU€‡ö–^²SÏÎÌÔ«õÚ ãã7¶ŸO–ZÛïõZo{Ý«¾Óí´\\X8œeé}qJ“´Gâ´Ä ÞedÖ¢œè€<ÄS ”AT.гP ~òÕ$ÌY(/¹°´Î †X ¦üýÓÞV6ÎÊš§¢Fˆ 1ÆÄ 1Fk|#Æ0ÒXÎ¥W®DÆqâøÖ#(ÍhTàU×^Â57\Ãù›¶Ðîϳg÷A>ÿLÈòÕ“,̶( 6Ó´ÎÁ㣠ˆÇ£Eß„â&DºJ©ÎÕ;·~اлÐ|KCK)•üK%5äò•ÔMp6 ¢ñ™ ‚ÿ”÷ò)…¢\¯”G¤Ò$PÆ{…Ë,Ó§ŽsøØ!Ü ÅD!F& ™[¦G–ëÆØ²`ùš©‹6”·^T­Ö)F!Í¥–ïØ®,õ³Ngq~±¹ôØ ov¥‹®ÕËRxÂwòäì’íöû‚÷ "¢ãR,v;èј4%2š Έ0”+%vl]LJÿùkQ€ ´Ð+:Ý„åõQ¾ôÉ?ä‰ÇÒì-ÑîY¢RHk©ƒ„„qJµÚ`æô1™¡Za´R«0fŠ”WDŒ…EÚÝwÞö Yö8“µ:üÞŸcí¶U˜p‚¹ùÓØsˆ›?÷:K§ÐQ‰r¥B¥Zà_þ&§N-ñ‹oy%²ôÙéÞïI_¾uÓ­ ^†Ê)Ec†pÉË3Sª=¥8­”Jlž‘f=w| βhÆäi`Í0ç* cTd½ïJëü:ΡûÉ$0;Ä«×ã²µBvcšùåÖ¦A–$FœB4F˜0d¬1ÆÈh•F£A¹:B—)‹”*E¢  ×íÓév}’tüÜ™Å^¹h")ØN /)Ó'¦92³H¸Ü¥e€ó8£‘,%#ÆGJ|þÞ=C?ùÝK¥4¿ú¶—qâÄqŠõåÀ£ã"Q¨ÑÎåX%8´w‘f0ÇX8A}¼D(œ1ôŽæR=Y¥X3µ‚-ÛÆhõ{ìtgfOƒÏ‰YJ##ÔJeP)ÝAŸíëV³eÝ*¾pç#ÔËîºãŽ·ß{xö#ÿf CzS xï893C­\¦\*†Æ€JˆÞþ\âæ™–`xÜ@Q5PàDŸ Fç,^N«³DN†"ô9u›‚R©; (ÃâR¡b¨Û^h4A–Éoxí«¥& ó³ì·{åA С"ÖåzƒZ½ªKåš®–k1:ÒT+(Ä!Û.¹Žb±€KSÒ¤3Ðo·0*bÐë0È,µR‰+®¾žR q‘!¶U ðh¦Ï´Y¾jfù4ÝV‹r¡FÁ:Xjc t¯Ï‹/›  Š¤¾Ä\û0ÒéÒÊ, «˜ðM²n“AšÝûžâÉýÓ³:$1ÚÖRT–«¯¸ˆVkÀôÉ3ŒNT™owÙ¼~Š~–2·´DµRAyŽ —`žãλ𒤵¸´wæÔÉM™í–C Ÿ˜‡8Å"Qæl­?›Q“³aö¼ZÔF;à”ÀÍÀi¥Ô? 2§P^DÜ9F]©s ù™×* œ6-à¼Ê”ò™‡G”âB)y¹õBŠ!E"ÐÀä!¡gŸÇã}½c—tçØ‚F dÀ “†B1*Çà¼BÅBLÇ”ŠuÊC½ZG…1Ú€re¢j…@ghÑd*_Ý“Ë'èvû”ƒ€^»M¥ q2àÌÒ6Ð=1½ØO³lÕ'Û+7n¹ýEמ÷¹^÷fDqº0³»~d÷î«ÚÝÁúüýß>ïÄþãW¦©‹Î(R‰Ík–S¯VªUb_À…yAiÖOH½E‰Ð^?¬4¢ÐÞ(À](Â3æVà„ˆ?¤”ÚÁÓ®cÈ ™s‚dšã\¶s#k×,'Rš£3sk’Dh'ñ 熠΃3:Í6S•\}ÕfNÌ,ùâFAhªFá”áOþþ3”ƒñ\D¡0ÐP—2w<ø¶®YI¡2>6J©32Y¦Ĉ©W¶¥Ü¨cðd¹?¤8ˆ¥ÊºU˨jtÓzÝûNá®û¾J·Õb´1ɲU4*1_¹å³¬Þv¥8Ä& qéÙk£¾RŽC08¤úÌlgäÌB;›™YÊÊ…ÐVªaavÆÚUËFªÖö–?zÔ"½Á}ÝÞß/þç¥ÂO„·ÅŸüéŸhñ^æææøÛ¿üï—Û¨|þÿô—>pàØk½§„ËŒRèÐÖMVY>¹‚Z}„BãƒèDõ;‰±Þ—•R7j¸qØQœ—LkŒö>/ÕyIÚ3ØýEF”÷ÇOÎÊþC'è9K¨C~ç—~bna±Md4.¼rç-qyI¿ÙäÈÑ3œ8¹ˆ‰ xƒÒIž…ô ŠÑb¬Ÿ‡¾JA¨ Aa¼§P(ÇuFÂbŒ"¯´œî“ú­$AÙŒÄ ÅÈ YžÝìÅ}FÇ ì;zŒÓ'ÙýÔQÚ‹)•RÈšm[¹lÓf\{Ž;¾ö1?ì™ËBÞ¹¹ áx‡±Ù³Êø_‘ È•læYXêZ¥Û6O9k}Ae[Ö­°k׌¥£µØ>±g¿Ù\ܸnmÉevdf¡½jÐïg{ì?ÿªKºË–/_üÍ?ø“»~÷w~‹Ó=ÿ³÷L‹Úõ‘¿(Nϵ®Ë¼¾ôcÿû[Îx…÷YE{MDÌ. ¸üüD…2"mBŒ‚B¡€V™W6u8(Ÿ×_+ýy‡X#fÚ®•K»K®Ðm%ý¯ì;tr|l¬J@LçV6¬_È2„¸V¡1>ŽMrš8õ‚RÄ%t­¢A„F¥ñâIÔ0s©„t©ïÑêY¢¢z‰8„‘b™ÊDƒÑFÀx\§ÚÁh‡ }Oæºý9¾ðÇY62Âe—\ÌêeËP¾Åw}™ÿþéi–œ0²b=ïúë{¸ýáÇ0'ÞK¬Æ8E'P…çh8Wå#J¨WŠfÓ†å#ÓÓ )J²ÍV«Õ(-ÅÆF¡±€½äÂmöîoï² m»zÅ {z¦m­ ìÒ‚ÛK­bmY©Š6k«Pö–‡LÏ9™ÿåßxÏŒ/ÿÕ̓/þÖõÿ…ò¨Ò»¾u›þÎíÕÜófу­oýé·}ðþ¯irÍÊ .3¤vÀ]íCᨗFGÔjuJå"AhãŠ+C’­VÄ&¬QSÿ'ÿô¹Û1Q@¬ a!ƦŒäõb‰¤Èü|‹'÷ì§Ûñ”ªŠXpNˆÊ!µ0D…Š4PªD¤^0:/ƒ•a&ÉÒg²Q¥ˆK è÷3´O1xjš¹…dƒQ9f¬Z$ •rÀxcS“SŒIz–éé|ü?ÎÁŽÃy(ÄW½öw¸áMï¢B@¿o9µç›¬çPÕ)ÂXh- îzn€§CÁÌ Qdز¶^ß°ªâ*3¶À¹W«Û¶íNb7¯ßh¦m/ñ¶ÝîÙ£OMÛn𨓫¬R$NH­Ãt¯#Fg­â­wËò “sù&Ûÿú½³­SÓýÖÄú«º¯¸ðŃ—œù]–]¿üÖÕ?Ù–ÏO¦I‚Ö!Ö¶xËÏý¼ßyÑuÿÀ½÷¬?px½}bÿÔ™ãs#n7BD¥’iå5¥ /¶,Wc&£Ô+Uâr‘Éj?RÇh‚z¼õ¤€O3| ‚€N·Ïmß|É*LšaQ˜@¡É +Ô5#ò]BxDç.DHš–ó6¯âlJBŠô3 ¡a¢Q`ÇÚ˨M°¦VâŒI1í‹ÅÝߺ¿~ü³X/x¯0ZQç}öAÖ^u#¥r@{ÚóÔc²÷ô1Ö¬ZƒFa(âœà]@·'½çfDÔÓÔ.ôúícA`ÎfÏ ß¦™ £À:?°•ZÁNØŠ=vr>9´6«¤cz…M­³guÙ(À‰B¥õBh7Nƒù–Ô*¥ðâMµÚÍ—šíýÙÜi—´[Ò_^ÍfæÎ0i}6tMšöB‘‘š¼ã­¯<ñÚ׿¼¹ïX’ÎL7µMmbmbì‘ÂU,›<°ïÉÆ—¾zKù’ó¶TíÛÛØsp½sd®–ùLç"Ï+ ã‘‹FK • Rñµ“Ä‘&KCŠE÷!‘v´ì€¬Õ¥ïÊCy´Ž 1’A` 8Q( €&EBÍÀ)æá‹ß¾Ÿ=§›X¯†ÜIΡág_q1c×¼“ÆUïà?\QÀh!Íþñ§8´ïqJ8L Q±H1¬ Óã!D­Ÿ£ 8[“{”ÒZk@$×]l-¥N;û]ûíDcY¢‰mâ±=v¿5º–./ÚÝ»ŽØ?cØ+öçé:».PÖyìÀccåm96ö@¯›^¹½˜¬[1nïyø¤Mœ³A q©VöM‹§Î´ãR ñb0>CEŠÀ(µØóoýêCµJ­d’AÏîj^mY×pëÖ¬²›vlêÅG—m_Ûë«^•F:•’¾s¢qN- :½¥“‡~üè“{Ï?Ýœç‰ïìæ¡}3¤í’¥yÍ,Ò~ê4Öz\Ží1âÐZa¼#ÕW^¸É‘eˆOQ|ôÓ·¢%C+E(ïHÁâèù˜¦^åô2Š(Rhexí /eÓ%—ñ?õ:6¬?8,æ¥h zöyǧo=DLB–d\¼º@27J³“R*’¥y$Q‰Ç–RÂ,Åä¬Ù³ŠøûaQg˰< ^@òüya¨)Ú:ÝŽ­Ëv®Ù³eÙñÑQ[ˆJö¼Í“v‘ó IDATçyçÙ#‡fìÞCl••öö»NÚw\?e8E{FÆ.uvãÔˆ­V±‘Å&6±&TÖÖigc£M·«4™ òåÔ‰9p°3ºfjYa¡ÕR•¸P¸ôÒ-nÇÆå¬^^1{÷ïO}¯b.^w¡j÷Ⱦ½jÛ¦-é—¾õ-Ù°¾‘=ïüKޝ¨T·lÞ†21óm¸åÞVU…­«":‰ãèéG,B ƒÅ“Ì/uñƒ6‰írÇ·ï&í=LPTÐÍ6+7oç7ëý<ùÈã<ðÐ~”Ö¬_¿)¤” ôz'xßþYt1æ}ÿí·øû÷ÿ·áv4ž¹£l˜œ :Ûþà ³Ôçe/åÄIÃHp͵+¸û;óôlR ±A—ÄxL  PÊ‘iõ\ÓÁgK®óBÚ…fçÉ2Ÿê]ö°aõš`¤2;}<ž=³˜)U°…¨‘|鎯Úk¯¹ÌþØk®±*Y"ìK®¿Ø<Ùëìo{Êv¯›JNuIjY ¬]jIº¬$Ö(e“ÔÛÙŽ³«&´u6µxíLà+‹ý®Ž#òŸExQ)¤PÖ&é]tÞ:FU­G‘¸” 4þ‚Û í:æw>âWmœòãcá#»fs3Wl_­çÓ^xüø)FF‹ÜÿÄÇö-Ьz\³ XŽžîrr¶‰CQÄø]ª±vj;§ç-K?F¿ÕÇÓëNó¢^ÍU×]ÃÎ ®æE¯µ>p’¸Rg~î:†îëqàØS4ÆÆøÙ7ü, øê­wRŒªüÝÆ?ý¯ŸÃŒŽa°ïÈ€ŠFŠ””£VÒÌ÷ÚlÛ8FÁ(’΀¾Ï—¤ ,™Ægd¡C{‹×šóÜŠBf •‚Ì Z¼(­Ôô骥:ßÙµW.»ø·~ÅÆ`ûš‚ ï«n›´•b=AÑìÜRš®^3b7oxu{ôt’|þ«Çm´~*-ÚFh땵™ˆìÉy¬øÔ†:¶ ÆŠ¤©ÒºÞiZã%ß@ŠF•­ë*¾3¸åEeTW¢ë€^ÀB»™mX·šT0€!S JçEæ+ËY³f9w=tš[¾±‡'öŸ¤T*ó«ïy7Ýx Að‚k_ÈÊU˸úòëƒ[.¿t¯~é+Hû}¶]ú.>úD¥`zÁÑZj2V‹™ ˜OC·ë˜ï QW”Å›„T„Ô$Y^Q]Òú9º€!ˆÏ7^ˆššWý¤Œ‡"/»îôº|äæ±nÕ&^ñÂë]æ…¹ÙE–MŒ…*­œ,(ïH>óµ'íçn»sðé¯uÏÔxjBåñ8ŸßeR”1x¥p^Å©éy¾vßS$K‹¼ìÚ­˜°Àʉ6n',„ì{âIö;Âó/¹‘‘òòI>û¹'˜ü÷+ù»~’fgŠw¼þù<ü•ÛxëÎ×±§m¨©ç>q”R3|x„# -S£')BHDˆNSURGÇêg•ó¿* Py\BæD’DÉ ï”Ôàáݳiý:þ÷Çþ‘»ï{„rù•µ,_¹œ»ï¹Þp©››D~ï¯>6òÍúEߤ.0ºÛ^¤·r™>DfÒÈ“ˆ!=|z•")µ;ift–€ó±aY»—EñpCˆÊÊǘ¼h÷»`n³½D«×c´Úàøì«£êE¡=HÙ±c5î\E§=`×áGu±ÊDTP'NsÆÐ¶)Z Êk’ć!Æ„ôz±B+2@9…A¥›S>4KP6¬\ÎwNžd×þ¼õu×2>9†2ï…›&X1ºœ“­YZ‰âK·ÞÌ…Û\wÅEìzé)zè¼ùµ¯çŽß~à8þ¼Õl[Yd¼Ú¥Ù÷lX_¥Hz)Újz½Œ Áhð&ņž4sIJ( þ¹)€œÛ׈'é%j÷ÁSHš²rÙ(mßÊû?ø»?ÜäÒÏã¼m›x÷ïþ;^÷ò7òÀwnã ¯½/ð¿û˧VÉ;^uE¢‘ ÙšÕïû‡oÔÞ÷L$»Û*©”é+õ‚]\jÙ«.Z]èÛ¾=°Æ:Q©VY£ï¬rHlpiŠWÑFf¾9§Æ*£` ó:}€XOÐiÅ|ìÞñ‚+.çÕ/½•‘S§Ù±c½\~ù*S îþãÝþÛ÷ ¾ã"j¥ù¾%•ÎV0AˆµŽùv"Oê ™Hþè§ãÐ6…´„—½ÌpÅ[ر¹ÆÎÍW Meh14í^ã'ð©Ï~–ç]ùbV-cûÔ*¾×yÃ_‡Mç¸é%W°qÛM€fóùó|óŸŸàë÷ã×]LCšuœ“OS?ÂoÿÚ{¥xòὫ á£_~”æL+¶ñKÛ6rx¿&Í‚LS+ñûN¶¹ü’).ݶ†¯ß³—ù9Å™EËh¥H²”b|Jjløìuÿª\*ߥ“e–éÙ£LŒ5ø§þÍÖqªÕµUžwÅåZØË{ÞõnÂȰ{ߣ¨5›xêôI®ºæZŽ?Ñ“ßâÆ‹_Ê?|ñÛüÄë_LEÙlY9N”¨UBª~$±ÖÉÜ\gpì`k0²Ì¤Þ˪•õBìRG .G»×–ÖÀʽàÅÖ§<‘¥§ñü¿QDt^´™G³ sêÑÝË/¼õ§Ô{‡¨ÁU—nã%7\ÏH¡ÆN¿™rœïí¿bçóñ^(U l^¿ƒ¤ë¸îú«©›ˆ‹·Npùùçqß)سuÙj…Ä*S@©¦‚Të¸V*Æå’®\uõšÔ+—mX³:KZÚvàhxƒ°8½h:­–¯–ô¶ó6ä© „#³G9|xŽ®¸ €Ó³KLŽ×E½ZàCŸºM¶_x^L?Æ…—¬`ÍÊŸ™G í… íK ]Tš`m†1Z'`2O$³8$…eåÊpëZÀüü c‰\»±Ò¼ú•7T#/Ä;Ø?}œ‰Qǵ×ïD\‡7ÿÇ?çà}£PÖ|ø3ÿÄ5/z3×®©ó…/OSˆ4a ™>Óg ¢¢¢9ÛfÓúe„nŒ·½ñ…<úØ·øÚߤL>…Ô?»|Ÿ0P¼Æ‹ê• kWN©žgÃêå\yñÕüç>ʗユ0ÐT EúÙ€ÝÇv“åùT»@ª4‡÷)ÆÓF—)þö Ÿä‰YÏÑÓp¨é(Æ1£•¼+'¦É6MVÓÑjœn__”w¼þ’à%לWúÉWLNØN'Nàó]¶©Àøª1Y?µÜ)­åñÝûqâ¹ÿ±Çxý›Œ·üÔOräD“õÜrÛÃ<²ûÉs#ûê½OÊ-_x"|Ï·-ýú/¾)<Ý<Ê¡Ãs\´fï Å0 PÑœ˜ïS-Ù¶aœ‰ZÄzBq8¯=ÞiÄÁ Óè0`©ÕÚ­Ÿ¿õüí‡ÿ'gδ¸ò‚+yý+ßDPQy™û÷ígÝX‰eëAïþíòÊëžO±ÐYZâw>ðA’Å%Ðb*¡&Ãx=¤¨G06¬YÎÛ_}/¹f+S+B¾~ß2oÐâÀûïÚùôoS“¯'¡×·¬žšâ•/¹A±–JP©—yâ©Ç¸å¶Ï㎞îò¡š;wßBóWù$›¶Mñ†—_ÉÿÍmÌœjó¿ú œ\ÒÌ´•J@PŽQ‘áØt‹bÁ²v¢Îørƒ6Š[¦PJ±÷¡‚ØA–‡ï^ùg徟ˆäÕwäP&µJèZ ŒÕª4Eæ’ÌžêòÍG¾‰su=Îë^õ&ÞýΛˆ‚€Å¹¾ýà×ùüŸææ“#Å«.áH'SYÂDêåüž­$å=ghÙüI…2{úL¦L¨ò§h™¼Ä»Õî©Gw÷°™“õË7ñåÛo¡º¬ÁÀÎqãó/ãáïÜÃ×îþ,¿÷KàUÏ'ïéó7üë,¯üø¸ñó}±ÅhEðêW^ÆÑ™ãˆèD— „¥Ò€Vg€(°™pòÄÍžei6¡RزfŒ^³K8DA¨S  ’”Ô-2Ѩðš_Ni¤H·Õäí?ÿSüÍ?ÁŸ~ðŸè,uxèÑ›yÉÕ¯d©™ð_ßó«TŠŽOßu ¯¹ñ">vËÝüäk߀.Œð‰;O¤žùS?JcUJ&¢R …¢¡4â½V £åq~È™èg•ó÷~T¬àAÄÍ¡§žÒO;*/¹özŽœ8ûRJ|áÖÏðñOÞ J“9áÞûò¿øóüºÄûßówÜxÅõì=ÖÃû<²lv ŠAlÄɦœÛ©½ÿpʲFľƒóÌ.žs]º—nØ8!*=»±@p‘B2Ë“û÷ð¹/>,_øò7Ì#Y‹/ØJ“y½ýq¾ü‘æñ™{P(¾qß]ÅåsúÙe­uÿØg$™ò#—ß~žýÌ™9gÎYg­w½m½ï÷‹v”ÕÍ>µI:ÖXDÍP¬–Ž·^dÞö+bzá$ÿë#¿ËʾV.Ú¸–ÝûŽS®NÒ™[Çï¼éw’/¬ZñZ¶0·àÙ½ÿ½N{Jê|ðfQ?ƒ@òäË'Ùº>+š[¥bD(%í™ íÍzúó´wå‰Â.Vtæ8vø481Ë ØFKüfŸ¶lŠb¾ ?ãÑ×›æþö7©•šðÓÝ]m|ð·—›®¾‰é¹ãX+hêêປÞÈcÜvíͬèMóù‡ŸE·¬ ¥¥pTâxЙóMYŒhÍfŸ-ã»ã \@h„´¶¤9)41‹æçtíYÈC«h¶G}TLÏͰf}'¤­iMù~üÒç©ÕbææöRå‘]@ É…Ãëùçù(s…iZW*þÏ÷c- ÷A9€œ+¸xUâhkY\*àd {e+͉c!RJ!;{Z¨Ç„2ÔâéÓó¦)­â«7Ÿ¯Þó ïàÑGÿ‹7l ë¶sݦËîZÇþÙ],;)›/v1¥=|ÿëÏŠÃGW¨<ðïî~íÉÊ8d³"tiJCSÚ!VtäÓä2–Ööi#XÑÙÊÅ95µÀcã´äó(£‘&É™D&`n¾Ê‘‘y¢ØÐÓ1„[èÈws÷½·³óÀ“¼ï-¿È–‹.åM7¾k4’*¾ŸÃU] e^Ùw˜_}Çý¬]³'ª‘÷$Žôwå°Æòü® ÂŽ(ÖƒŸI`n{V4'Å­RA¨ñ~.hÖ&mÒ'ÆŽÇõ8rl9?Çyë×Õç¹ïÎn÷øà|”^*süÔ³,Î.¢áÔÄ(7Þt 'ŽqÇ5oà™g_á›ßÝÉ U}y‡—O%ùÜîŒxñÀ+Ú»¸ï¦!Zrg†§=)¢Õý]Öè=LáA,éîêõ(Rõ¨È5WÝÆá± oýà;Ï¥[ËŽc;¹ñM¿Ç±±©é¿ö{o‹;ÓM~l¬üû¿ø¿tÏoS­PÂ#”šæ¦6¤¤óNÌ.01Q'¬j‚PÓÖ¡Hù–Ñ x®‹Ò‚À´LZÆãºåäØÏmŽ'žØÉŸþõ_15]£½·…®ö¿xç;ÈäZ˜[8MjÊå*‚°6K.›æèè—^¼ŠtÓ0§¦–ˆ¢¬Ã+#‹H×ÁZ(UËhÓ¿"Ãúu ,/õX’IQªŽdI#>8cš VÖ ¯oºñ vtê =ö7]w#SÅYÆ'Opó ·S*Oòðì©ìÅ ¹¥‹¦ìA±ÂŽÝÛ¸çæMì>¸@Gä‘<º½BCsF!lÄu—õÒÝ*Îm¹tª8¹&#"’jÝ:1Ž´äS”Sýð¯ü>×lîa°§‹ÿá`-õb„à¶µ÷ó¯}„ÕŒŽ .Ê'ŸÜþÆî6]õÝñì®CèzHÞJ"#èî–¸Ê!¬V*ϱœœ]D¸’´r™[ª!…`ÓÅýTdÚ`b0Ò§Z­"Á¾•|õÛßãÄØ@OkšÍw¿!|æË¼íÝ_4ï»ûœÔ wb>•S"ÄÍXüÖ ¯^ ¦Ž«xîÅÓ¥9½Peï¡lÐ*ˆ,®+ÈçÓˆºÁ$##•’”£mÏn纫·08ÐŦK.䓟ÿò¯ÿá&iŒjµÊ†Upׯ$Ûžalô÷Þüf®¹äÎßp9cçÉ+Ȥ}bmH¥%V)´¼62DZñV¯ÎÓÕÓÎb¡ ™¦\­âg…ŠÁbР“}óÿ.Ë€™@¦O/ÎËÃ#¯ÉË7obÓy›©”«t´·16þ2kÎâ½oÿ-gOðî_ú]NzŽùâÉû ÕyŽžÂå+ã·‹/üÇ×Äoü¯óÄS2z`LMÁW¿Ubr×$¿òëï$ݼ‚‰bݽù®;ão~sŸcÀ´ä‚FKk‹be«‡UŠªxnÒZÓäºdü1‚”+Éf}z»šˆ¬MBSƒ£¨Ï/2»4 ,j¶\vѵ\¿ùîºþJÅ3 Ót¶trÚyð»Ô*ä[[iï¤Eø~‘m/¼Äl1fMožrÐÞ¤82Rdtb ×HºR)»òèzD=N4üäé"k†²,‚F€J`zâç?/Øå_¬‘A`ÂzÍxÊcçž}ì;|íĬ]}'ްuÓ8:¾X†lܸ™ç^Ú‹±–5ƒè_q;w=Å@Ï¥jH~¨âÈqk†Î^‡­ë³¤|©5 = v@l¡^/€F½|tÜ*,ÊÕÄ2&—q_˜2 µº©DYû¥o?Bkû:öïßÃâÉk í­uözš{Þó!ŒµÜwíÝ|á·óÕ/ËÞzÓV¾÷Üsrj¡,®Ûº‘º4ÄaDow'›#5/½6A­Zgxe3k6vN%-g®#Ég\Ú›Ò° bAX«1¼n«.»†¥Å€k7_Ϧ V°ïÔN^xþ>ú‰?!ãgXªÄ<ÿò1ÒJ‘Ïw±võ:¾óÙἋ.¡^¿ùëÏÓ”dó)\G²D-£µAå$¥J„ œFÇ,Š+³}×AÚs.QaŒ!0?½;øgù²á =E…rffZ¡ÆQ½íÝœõÀçÈ4»lê\pAšZ©DWG3"ÝÉ©Cü`ÛsuÃÑñƒ}­|ãáƒ|ã‰)´§^:Äøô¢øÁ¶QªÂºJY´4D±ÅFU::V˜/?òiTbû÷ý‡'¿Éúus×Ûoåw~ÿ]|ã[uWmæ·~ï”*EžrŒÖþ,Õ&yð Ÿ4­]&ºù¦{ÅÁÏrñE-äòec™ÔÔk!Ý+Òä2.­ÍŠ¥R„ŸQÔ5œ8UÀõQ=)Ó¾déH*aÀÔéSÜõÆ»YªÔyäûOÐÝ=ÄÞC{=:MªIÆð®‡85;N­pt|–\SžŒ—cza‚Ra‘Ã+xqÇQ^záeœæmyŸMšñ‰—vð}Åäé%°‚W÷ŸfäÄ,ÓKUZZÓ(×E›: ìîÿ€¤®Ì‘–ZP?¾'zæ©×˜^,³÷ÀL¤8>y„Ù±«V¬#ÛÞÊ©ñqN=Ì›n½…W_}–k®háž{®à?|'ë;ºQ~å¢àÕ‘ãÜzÇFmš—_,“J{´µ8´ufxlûÛv.P+†h“N+Úó* DÖ%ˆÖn“‹§øý?ýíø½o¹Ç<9Íçÿý³üÖoý!åÙiÖ_XâØ×øþ¦Ùyà9î{ËZ.¸òFÎ?o‹¼÷í¿lŸ}öÅì–«øÒ¶±×==4y‚š 9p´H r^šºµT£ÇzLÍ–(—+´6eY*ÕÊAj1 ŒÎñ£G™.Î1>7C©R㉗žFGílºø:¶‹?ù³¿þ~žˆ IDATãµW§Éåzèm:#GpëM7ÑÖÑCgëW_€ò\«ôõõP£¾TÂknÁ(MsÊ¡%Ÿetb‘þâ«ì;2C¡^Oj³Â*l`Àº W‘úé"ð³àl‰¥rq”drì°³P˜aaq‘\s'ëÖ^É՛綠½™­W]Ïê5™Y˜a©0¶…ÓKÓØªåÞÛÏÇ—?ýô:Û=.^ÝÂ_ønز-n ë. ]iY'Å…«[8qz¹r•æTÎq]k‰WÚ¤mZ³X ‘™X|ü7ÿŠ›nx“ÿøóO²0±È=7^Â5—^F¾·¿ûäïòŽûþ„Ã'¿Ì¯|àH)êq»87­êÖõt±>¼i¯<ñ8†L6Ïšö #“¢(¦Z ‰#I{Î¥T©SXªã¥\ŠÅ#c§“˜51RD  ñüK/²g÷^®Ü¼‘öl Ù´dõàåÜvë-œš8@:—bïÞì=4ÅÔâ o¹}+åJ…‘ñÓìܽ¦|'‘u©„Z›Û™Ø³ÂÒi”›ãð©)ß!“ó°ÂòôóÇ9y|ž´çâ9•’X«Qq„±iø©Fà?¥–ÎÍϣ〥Ò"ß%–ˆkuFGI¥Ò\8¸™;n{)§ÌàêaZS}¼ë®ûù§/?ÆòŸÜNß ‡\Îãñ—òŸ~‰O}å›/_KÏê!tP#F¢…@z‚&Ï#'¤k#‰ÒH4!a|e5¾r¸÷–;C"_l¹ê:êÞJÁ_üÏOsbò›/½…–öÓ'‹¼ûž[¹è²«Ìwú¼“oiQ¾ð¨íÍíÌÙŸÉÐÔì0<˜'司iÈøÐÝÝÌÄéÇGçŸZàÉ23UlÀ×'“йÅY Ks¢ÌR±È%ço¡XœáÔôV_ıéW˜™ßÉÐÀŽØÉ?|âãHiðü kÎß:¢²´H©4‡ïø„J!dš§¿û5^Ú=NKK žO+:Úrôô6 H;)ˆAÆ hO"lLœZý\ÐØþ€‘Xb«udz×°jåy;v€éÂI2Mt´·rhô8™¦&Ö óÀçÿ=óCZVòÝoý/bcÙ½kõê•ÒƒÝ]´w¦˜8…qÚ9é\bOsAµª™-Ä8-)0BHáj6²cbQÇwó•]´µd™Ÿ¯ðÅ_æÏ>űñSL”SH!EBqg<•`*+Á8'½œÒ&sÕÒÙÄ;n¹Š—^|QìxñEqåÕWqÝu×ÿ¿hÛ€mÿë~˜¾î<¿ÿûïâ­wþ6~õl%¦§³ŸC## õ¶±éò>»rUHûÊ“8J¢¤Ä÷%žHRÃÊsH Ïhm…²mc¬É!X,xösÿ±]Zç_ÿÝM«y~ÇãT+ço¸˜«{Ù¹û^¬¨-VY½q§föñw]*Þz×µöK_Ÿ~&£0Š·ß±…›n¸”Žîa†òI~•à KAKSŠ$"uï$;Ðhƒn´d+ ³åYŽ¿†t'F§ÑAÄÄØ‡vî'ÝÜÍs?|’—ž{bmž¹Â$×lÝÊØØ1šr–ó‡Wr`o©éRßèØ鈵×#ÆQ²Á¬’A`ŒÀ•×ñH¥ü„oÁÛ88 J¬WÂÆV†Û_Ï>»MügàŒ(¤eaf\…3Gú³^œ]\š³³…¹z5¡pòÑR¥ªÇ&GeKK³Òq]µ´^à\»õ&\n¸þ|οþ:~ñCWÑÓÖBK*Å=72;[g׫'Iû€8ÊÁuVH\)Ñ2A u=+¥’® Ò‘M:•´¸Ê¡ÌÈ»ö „ •ëfxx ÷½õäÓ7\{5wÜýAJA?fçÃÜ{Û/òÀ§¿Ãä¢áÈÈ’~íä µ¦=†qÈÙÅ—¿ù<““ct¬Mš+¤hÐßÊÕ递 ) B‘ZZ0&™Né–ËÈÀ%“N#bC×ÀjFÇÐÜ×Í<ŠHwÐÖ›EÉDSÚc¡RáØÑ“¼óî÷óð£Ÿâ³Ÿÿ[>ò_þ–—·?ÉWz7ÓÊew˸|h"­a€Ó>@X“¸Ž8Cc£H´€# ’a 2Äb!Pb4F†=:†¬â¡'>M­ûâšËïá‚ó/$I§’âgv?ÈcO}ŽØtqËMwòÊ+;xø±ÃttõP®•RR.Ãe[ ¡ A% D£AàŠÍ=º‹×V‘L”P奄À÷TîÁ‡¾#ÎÑgòÿŸàJ)"cPBLI%3ÆØl*•Rx£-ÅZÓ³óÀqþã{OÏqX3Ô•Ù²å¢ÌM7ÜÒýg¿{#­-ýÊsa{GOÁ¸ÿ-ìZ9ÔTºä‚6WeÕî: P¥_©dk(†Z›8ăÕÕ©ô}·®ä£Ÿ<.•ÖR&v@¬k"–Û^øŽê‹µ+ÖÖçxéà"y?Çîƒû¹jë5¼ùž;Ù·w‰ë¸í–ûÅO|›·¿çÃ,ÍÏûŽ@Ô­!2†¦æ4FäˆMˆ‘ ön!ªA_#$B*”ë$c¢e,B<å#\˶綳X¬bµfÓ¦­,Ì-°÷Àq®Ør¯ž +,·\õßþEùúWøßø¼áÚwð/ÿþ!>ûðÚ#?9ÎÝ·¬§X Ù¿o‰Ëot(KII>§hS.§§BZ[=®Þ<Œç Žbf¦F;1FÄÔŒC–„躩±©ë íÿ˜!D£ )¥FãHõÇóåÊ—Rž»&çûoÔÒ®°Š»rŽ?Ð’irc´Ȩ±ÿè8{ŽŽñ™/¤Àu õ{7ÝtCç·ÜÈ…ëW¬ÈniC*¡ˆ¶fYb5:XIéð”W*UÐ*m])ÛÃ…ª§'åI¹¢¿;xæ‘u¤FÄ HQ,¨,Lª¾Ö~Ùší´W^yå…29§\²á|ö:ÀU×lâ²+GÙ±ói.Þp9ñ¿Æ­·¾Í4· ê™é1­° ôµ¢¬&ÁUiJ\¡>Ëi,EâHÇIj%4Ø8 ½$‚(ªR¨Írhß³Ü|Û{Ù¾ãûHásíuï@„1",óàOð/û87Þx6ú?<ýì·¸ýæwòð·>Åg¿ò7¼õÎßäôÄI¶lZËöWŽ‘koFdr.ùü朠¯­…ɱùVA-¨J5ñþûÖ1qp»¿ß† ÆXê:î²€×ØôФÌó¬8‹õúKJE5 Å|©T^mÜ8R}¸)“v ¤}ÿÖ|6õÖªׯÈw&™< ÚX*¥^9v’]Ç>ÇÇ?ñÙ3,á®”¬èqo¸áæÎK·\Ê ×níY7¼§+°®ÞøÎÖXCEk+Iý=·dxä?štÍJW£±Ö!¶uò¹..¹ä›v|Ó”_#K3³ÒIû&ˆb&OÑÑÖÅ®=ÏñÄcÿ.®ºúN¾ûÄ×ÅÐÐy\¼õzþí«(þð7¿à;Æqׯk|ŽY¤½'å`$8Ž »oוèP$ä$h9R›„/%²8®¤V˜'v]ÞpÃÛX5¼–¯‡üìgR5ø ŸI©‹V®P+Vùm½ô±uÓÅlhcoÞdžÉ!µQõ¥Š¹ì²›ìSÛ¾SÙ´TÚ8]~³(”Æý™ù ™iÉ1Ô½Jª¥œ¬Ý¸j#ó3'yó-¿fÿáó îëjëºË¢ŒgñÓy‚x'ç¢ËAÆ‘®@Ö’®Ž …¥b-VC„ÆX…1Úq0F“÷R|ïùÿàøè|7ËWÝŠg-Ίó™˜'í;<úÌ·‰Ê³üá‡ÞǶç¿ÉÞ‘—¹ëÆ{yôªÇrŽÁ«¨–Oró-W0¶à`ƒ"µZãUzšc.Ú¸‚?zï BA½0ÍoüÎoó­ïMߊú‡×ÚóW ÚÖì)[7¢pþ/¼1(UŠ¡“é_;ørµ³Ë‰£0Œ¦ÌRT(Hù–ŽÎ<óC «Jó³ejéöŒ¢FUA‡twdÙ¸ºƒGNNT R'ã2$Ë®ïqŦ[jZA”éïìcòä^{/¡4²¸Te:ìbtÿK÷xô‘àž·ý=ßzè1nÚú2§ÏñÙ/~Šý؇xóíy”ܵ¹‹& *|ÿ»_å ÿô/<þò~bchI¹\ºv~*M­^'•réÌç96>MÝ „ÑùÆî·ç¬³$aÔ{(oÑ3Ö ­F”RW´eòWX -“ P²ÁÞjï×ZO”ëõ‡-6.CÊœsi Òjt[Il±hk*¥Ð£ÏI)²¹ôûCcTEƒÔ@£­Äq±Zzõ¦´r£X*ߤ…Ni¢ÈÛÏKc­fª!f+‡m¯ëJÑ’ÎÐÕßÓ6ØßËÀ@?+WsÕ`'kòûÀ¿ŸT¾Õ*×R8xž—Œ_Ht Q‚Æ0507[£³Ý"T†7\}K9FFvP¯€ ÂÚ]¡C(›¹à²÷ñÇ?AwWÀÆá-Iôb†»î~Ýl\s%ô?Ó£÷sÙ%—ñ©¿›ÄQ’÷¼o‚°Æž¾É7¾ümüÆÃL.&ÀÖZ\ÅEVã;> ˆ´¤Õ©ý=,ÕXC&QŸßÐಱÎð#ê@þ¨T£èÅ´ç5+è2Ö¤¥ÂHé[c|×óohóý,‚ö|î£Öëï@rÔâ h|VÄë½Q‡Ä¤\b Æ%0q‚ô+PÖ’’¾Ù?~j Зväåétv’r ¥Ôú¦LzuÆó¼!]ÏJ›ö€&¤ÑDƇ!DZgÿŒn´9%,äB*B‰¦´O[ký´¶ä\µ?åÑÓÛIX‡È6å‰ê!óµf&NZÂJ7¬¤ùžÕŒïÌG1ÖJBG Mýê§³unîlcExæâ£e»»éêèaft/n¾ÂÎ/?J¡4Ï>þ_سc”ƒ…E‚0&©æ6g¶f_Ö岫Éå|Œ–Ôkåª&ך@Õ„aG9X RGÄ 2R"„ \O5æ¼ÚÐ\@N,' \ ÓX¤¼+r¤ìÒˆW©aÏuW+);ÓŽ;¨\Õ*®@ ¡@Gó#…'¶ñ†±¥PªÔ¾]‰ƒR¤ãÃXQià×HPÀB ³¡·÷ï«q|–0BÐêûfÏ©S÷[ËP–€uHÄEˆæ•™Nù]æR+¥’t²§T‚ŒEJA[ÇD†R­F\ )E˜„”eþ£$Ý+EƒM.ƒf%4õyWÑšk!K*‡?G\)R¨Ô™+,`DF'ÔõVb¤E˜¾°gBG$ä\É`g -í½¸é,9eÐi?–,TªT‹¢@ãæÚs²-iú»Û8xä4‹ %2J-de;…r £- …òÔÎÃÇþ70 L7îY ÂO‰–WQiK&Ö&k¡j½»†‡€Œ€¬2ïIÕ“ö½%DÞsÜ•©´ß$¬‚„ÝÔ˜Ä& G6w67ßߪ#„ãhk"S©³‘µ£‘Ž+õ਱ÌÇ&JØámÒ“"(k°BZ¬è;ÄÙ\vƒ<ÆÆBkíq#°B$=qÒ& $:¶8nš“S;åÒ©ÕŠtÊQ­?ÝšÍzn[>'cÊQ×q0\ébǼ´±IR‹ jˆ21VªdÇbˆƒ2Öwiõº:Zpp±9E™6ˆØÅM „1¨PPQP/…”+KXÏÁ.FK5*Úbmrî_-׸hÃJšòiêA ž¤V (, uÐj<«q\ËÄôÊdSi½ç؉ÇZvß9nì~?âþÈ7nÝø}ŽÍZ¨[ctݘR=Žž€á;B´¥}¯ÛQN‹çÈÞŒ›ju¥u´¶Òq<Œ5ʺ®Êâô9JõY¡1Z ­±±1BÚetâÄ_1 +l KÈÙH%ÕP0òÌ߬Mc“äGÂF'»¬bâ0¬—£àx¹Z_j|'ˆ¥Òb[¥ ûÆË.ºna²˜3qÂM"h£´ƒMI¢ZAhƒ‰ Æ8h¡L^ß'#À÷Òh,‘ Q„°$˜]ª±dKÔ«6h%hMçijéæhoN±a “¯N{u,ÄÄYNBÍÀ +u‚z‰—R¸éK(§ž˜¸X’ÍxH%̳¯x"Òz©1Gá9°œø10'B ‚º°Ttòp¶QØoü\Î*…"¬õ"kç¢Z}ú¬Ð!e.£d¿çù-Rˆ¶¬ãt§3)/Ö±Rá K „ÐV&dÍ6ñ¥0Io@=’Ùܯ[ᔌ ëÅjuV[æjL7ÆP £8YaOØ‚A¢PXG´±$!ÂòN0IÖÓ×–¹ÝOŽõõl¨×ª+“ÉW– fhïiæÒ )-aQ®ÂRŽbüÈàx¤Ë¶gváe³ØHŸIº[k©Çu>ð®·S™]$Õ–ÂØ&ÐDÜzšÅ°Dog7åÈz9"<LÔ¤'ƒ¤«ÉyiRŽƒÖåZÈôÜ)JKU¤§pI®)ÃB±ì:8òdE£¹©7îe!8ca’ÄÖ¤Eañµ±õÆDg;Ïç¬Ï°|ÀpÆtpöÄIÒ3_1f¢Å ðçÁ!ÁöåR©.W9ÍŽÝ™”ŸÏx®²0X#16!FhËçW(%dénoAiÁØjëzX_¬‡zÂQ*Õ5ˆ„k79%5Ä6&ˆM ˜ã¬“{îS@³ç¨´§-UŒ +@X‘ o…¥"K• a8´ H¸BkQ±G6çPˆR±D˜+!ò¤¤X×D,q`ì0Œ¥Ñ&Àš4¡pˆˆµÀª$ÔÌ9Ó ¼icœ”OT5ÌJÌ.,P j Œ´çrä\ZéÝŽ™\XÚßXp( (ÛÄßZ³¼^‰„ÚF.hY <©*BÏÆ±­5X"›ì:yÎâ{ËZ qËs&wy¢ ‰Óæ“ D%ð3”Kµú3‹P*» ‡®+㥺S®j•БN¥Ú¤ë(¡#a¤ƒ ZÄ‘r…Ìyù.]Ž µF&Üœ)CCWs~U±^u‚ZÆVÁV€ÀZ‰cY­ÆQ,cb Aj´…-UÂ‹Š Æ"BÓPA?ªa#+ ±IÀµ, t@­“Jå2k•&“Qx²H)” imÍÓÖ’CÊ8q4¸,WŸ:uƒ—òiÉçÉfÒcY\(ÖwŒŽž˜[(‚­5æ=*2™ïª}½ˆ^'?A D€õ=·¬¤”JI_k­Œ1"ÖÖhk#AÃ×^ÞùUu{N2©q{÷«6KΆ€î9k`Ûl"cå v¤œä•(—]@ ès…ÓͧZ…M)Guä|7{JˆX ×ññÜtš¸Q5d,„:¤)émÉg{±`¥À³ÒÆE5ź^+K)/“¯…1Ž´ ÎãÄq]¥¥¥ÊÌtF7µdš„ô¦Žµ.r“©Òx¾ &:3)NB|K_[-->‹µ,RG,.„kšJiŽ ªRYc#ª%“sµü„@Ó•¹¦4½nY¬‹^Z OŒMOOÎ/žŒ­)6>n9ÉS Ý_DPÁRmh…åXýl?v$¨Þöæ.%U6Žc¡µqÀªX[¥v´ÑŽ1VZ‹ÐÆ`A k=“ ¦*¾NeÁµ‰V)64€ú‘Å?Wwñú\Dcžqb–ÚÆ{y዇Ou§\?'•jö„ìHû~6å¹Nƒ÷DJ™°‚`ël¬A …N’Zµš@ÇII•l„2"9¨F‘1Z£„®tBReбÅÅAx’¬T,Äy×èp„Æb(Ô ¦Q«×°ÒA¢ñýTÎ]“Îy4ûò¹ MnŠ:š1(Ÿ80 RÍ0 IDATv¼0[«TëSS…¥ùZ-š²gç!ÅÙ3þjCÖ‹?ëK5âddì(‰ö®4æ0ÞöܳöÇÈ£‚ ¤bUOW»P"mŒq¤åìÂ’L§<é(%Iê$¤1VFÚ(cŒ´Ö c´ÖJmQÖX‰5®N¢±RcAtÏ„îÆY6#ËÚA4$:Ýx¼lvgý‘eçfY‹y€#„XÑ$$×íò}/§„ôtdRnÞs=ßw”RB%)¢8¶‘*)G3Ú“óSK6qÒ6i4¡Ï&ú6%@(‰ÀAHƒP–œò±<ÇÃñ]WV`|•œ°ˆ„¨®|Jµ%ækq±\\ µ]š_*.D:ž²– Á§ºü½üÆãsMoÜXüšHÑÂBÖ“ÅÈŠA¤§²l ¬µöÇàŒ H!6 ôµ:JùÖZŒ6"ÛÙ#NO˜r© ÀHeµ’Ž‹ç¸%åržÍ#´1ÖãXc¥±V£¥6VıµZXm ÒZkì9Ñ„„îF ú£>„lh¯±Èçúp6ÏÝÚØæÁYºeû·æ.g#eBU,!m›#T“ãʬ'Ýœã:ž£…5iaÉ+)ÈäÓí6HŒL{_úH+\7Â!¬p…Z`¥P¶P)„‘FøºT˜©+#+Ò3åZP³Dá)clµ±3—x9W¿ìt{çŒ{94ל ÕC¬“ØýPt ¹L¶ÄÑér-œ:çµzY~jE5Ö^¼zHK)c¬±‘Ö⦛oÆÈæòÔô #ÇŽ«Å…I§V\t*¥YTkRX+Fxž/RžB"¥`EÅJ[+´Öke¬L´†qc-±¤3$lÒ„IˆË]“¤Øy}AÃòÏåǦ±–sËþÆòï¯Ïg,çÅ]kI5Ö0¢ÇC­M•h™mQ7$ }Ý3‚)’(ޱ6L¶±`Z$ã^>0[žxJËcÎ5Æ%©ÖáœñÅñ$;Ws6L_Žç—…a™¿©T ”IÉsÝ’ç9•Øšê9¯7€9qâ':¯»å’ÜbÁQÊnܲÅ­ìäÔ’›£8°óÓ“b~vBéú’Œ‚Šœž<éÌÍÏ+âH „p!Ò©”Èz>ŽR"FHƒÐV #­1"6¶b¬UÆZa`•±Æ#œZ×tÃ]9g¢–Çï±Hv‘ߘ8¯¡Û–l9^Ö"Ë-HÒÑξþ\3´|YΚHJB’â´ÆÂZam#SiÏxÇË…˜úœÏ6p&©uF%ŸsŸ‰Ó9«ÎÝýËÉœX@Ôð5)¨ûJV×)gR~½5Ÿ©#¨ʵåðÏœšœ°ý½}üL°ÖZP`ú¾o·^v9J qj|†¾î.&¦éï¶år9v”°—mZk^Ý»Sس›´/űCœS²ZX’ó³ *6FyJÈl&…ë¹"ã§H;B-„LŸm¤µÔ¡6ZÇŽ6VøžQÚXi±FG± ‰¤Qc“IWâa±ÆàhPÙ[6ÓgMÊ™hEJQWØtlΘ8ëQŸ{LÞÀ3=ã³¼.CzÎb+4ËŽ¬ý‘ç~ÖµüžË1ûr.P΂¶ÇO‰ÀU2ÐÆÔ=Ï r¿Þ”ÍD•0>£ö§gflWgç™ùYÜÁ6©-¶F¨×B¦f ,.V˜+Øt*C_¯ËüBE¬°±‰D[G³ÜxÞZ"]åž[o3®+CG*‡¯¼ºÇ~û[©¥…Yµ}ÇK­‡j2*J 2ë rÙ´ôÝŽçJ?åZGI” ÔÉ)“²m£­ƈ-µ¶2Ö´0%%ÀÄVjŒL²ÂÚ3YM`ìGñuÀwU.ç©T±ŠÀX)Î|ÿ3™X!A:JºÆ›äÿ„Àµg1.­H"Ÿ3yös®ŸXn·ü1Ëe W~y±Ï}KÂÛe•KAäH¡éÄHëHÕPGŽß·äSa[S.Îçs¦P­/«~Î]üŸ)I†(‰­M¸ƒ—–jVJ!Ö¬ê% ‚5+»èéi¥­ÙçÐñ±jx­]·f=ƒýõ0fjþ4×Þt½¸dóE¶³µ3µ'Ožä±Lj´²'_yB½ôâ3ÂRS õsrçÓŠL:%¤tL¹\±ý}a kEr4#$ÖaŒÁZa#Kc¬Ðq,µÖň´Ž‰µ@km#kŒD`4"61)׉s¹Œ¤©…V"äœtk…ÑVø¾£R¾¯¬dY%¬Qb"áÔÚŠÐØeóñ“®åç4‰Ó‹‘DÏÚ9=9”´Rb„Ú“B#¤ØÈhmjQ¤¥Rº©}(^ѽV‡õªnõ¦tS>kÚ›óvfnQ/­ú PA? )Ôk¥mœŠ6çÒvͪNO-X)kWõ’Ïz¤S¾—hÎ 7¬c×kÇD¹X²ímÌÍ©V#1·Pµ—^ÒÎÚÁa100 ®¾æÛu%”ªM½×Þ»ÝLÏâ¹B•SG zá¢Z©Ô+ê¦7½É=rH8®#Ò"Ært|ÇX„0ÂURd2)²ž'”R`S!­TBıBX¡:FÄ:¶ÆjŒ1"ø¿íÙÜ×uç?÷þöÚ«»ºzg7Éæ&‘’,)’¬Hã${Æ@˜A^˜Áyœ—y˜·üó  g'†ã%±­Ø–"ËZI‘l’M²—ê}ûÕ¯~˽óð«¦h'–e=&¾€ºêÞï=÷œïùžsâDýxb[Žaˆ”ëÓZKš8Ú0¤mJ™( SjCk-,­…”dÚ"?ŽÍ0D¤PR˜W¡•–ZëÄBj-´!•¡"íÅ&¤%R®Âœé††¦B •$‰RÓH©$Q±’Rdó•d¡zV•æÖt6?§2™²:>º«+öXå³Yíy6´’R¡ôÏžñÏ- Ñi·8”ÒÚ¶ .n9»šöÃ7ÍŸDÔ`þdL0ÒùI"P †HÐÚ•ëD,/,õ¼Ùp(ÁÞ~#‘2B"†NIêÉ%±-IfZˆÊÂ<åÅ*ëkç˜_¨0W£T.píÒÓŠYJå2?z€~°Û¡`‡3&Rº2rÒ "S«$$ m.¦mc%†Ö¤Š#üìàã“Ì~$ÑP*MÕü´S›¨„áp„e¹ºÓ÷"C6ã‘ñ\–çXZXc4ö©7ë£ÂÛuν´ÆíÆ,ï/aœèJÉa¾$PÊœùÅfÚŽ(‚‘=j`ºñ’F«Ïþa[— Y†þ˜BÖcîJQl®”Y©æôÃÃT÷Ò³¿ÊòR•N»M6›çáýš^Z(ð¹W^…xB8ê" [¸7æõmòVÄrÉ&ˆcêõ>õ“1±˜Ž‡:šND¯ÓýÎ1û{8á>å|†D ”Ž8wõ /½ü†ýÇ-ˆÙ|ÃÁšgž¾ˆ4%w÷ïñ¿ôeJ¥‹ë·¯³¾¾Ê™åUŠš¨„l^³ueM¯äµFÇÂs ærß{«ÆA½‰…iÚh•ÖLjõQÜù1c>ùì`­5½ÁˆDi¢8âîÞ]Î,¯QÊ9é4iuºHí ÓôôÍ»7Ä• ôç>û4†4I´ä3×ÎR?q…íÙ=êfLsdb¤í̉"-L²F±ü!AÇ h-Ð £`šö`y4ÄËÀóltsyk•r!K¹ìi¥B\ÛâŠwžÛ÷©7ê”ËE¤tؾ»G³²±” Š":ƒiÆ4»c¦aˆEL\™ºgÂS’LML·,¤U êÎëÕ«™ïöð<‰FšËÏ¿Èo~áw1Mƒî`Jí¨‰Ò’(ÖXB“$>W./`Û&/¼ð"«4›zà ®µÄÆêyÎn®Ç Æ ¶#ð:LûŽ)DC¥èÏ:hqcè¥Õ,cövL}‹¢ÔþÄ8=x!Ò2/AÚ ©Þê’q lßÛåÚ•+¬VVÙXÚıâ8—Ï/PÌ…©ä¦7ŠYYšãòù%Úƒñ´.nÞî JíX2ålejn ƒ‘1 âQ(žþ>ñ£T1d˜©bViJÅ [›ePšÊ|Ë4ÒqnXøA@o8aei `DôzúCŸDk2N:Gk¬fÍ'ÒomžöQÒ©ù‡ô²î…~¤%⑳ü©À, $fˆJÍØWZ' ÑÜܹÅü\™¯~ãëÜÜÞ!—ÙÆ9JÅyW/mrf)«þõ×>À”6ÿá‹Ïã!¶£aSÎYôÚâÔRhô`á˜?Ðèn€ÂY/ü8õL6õÓ«?20 ›F³C¹dà:©Hcë\•Ë[+˜u4YÛ¥vØa¤3L£y¯5I¢q,™k S‘È£ ’š#E’º¤ýz$’¹r ’”‡¸x~…ê\ÇuB­YÏcN‰ÅI§N¹h³yf)£q‡•"£©Ëõ[ÇÄÞ<9G਴Qu.cbÑì¢(uš.xloôl`â§&+ÿx TAȶ)©VJ¬¯/ñGöGÔöº¬,l°º¼ÄŸ~õÿðÌÕg™Džº²Æ`4å/¾ýC7ÇÓO¬RÌ› 'ÞxŸkO=CÉô:`™CÂ`¬ÅØô™•ã±Éa½GœF„ÓTâ•Ö ¥uræ#´ûmй¦aÑ 8i7‘ÚC)“›·orvs?óRA«?âÜæ çÏ-`&ßý&;N°ç×0 A,4 µ…éy?HvZkÔ,.I P­ÒÃ×J“$ŠõÕyž¹¶‰m@¾C©Te4|ê'unßÛ¦Y ãåȺ¥B‘µ²žÅå­u–—žÂ´LnïœpÔÐíDTç‹X± ŒÀs 0Mñ\•$h¥CÒÞÀŠÓ¢¢Saé§ÀO3A“ `ìl×P„¸^°³\]öÖV—ðÃËØŽä•—ƒ•Ê:ø¿þŒë÷¶ùòï|ŽïS«Y^È1§$á7_À4¦%1M¸½;¡ÑñÅò\{9«ÍAšÈך J8°¨GB»7äöýûÒä¹kOa[‹sUç—RÒêVX­.‘$é‹fÚaSÌåðC¥Ïo.°ûðP4j se2YN$Ž-qmƒ(Q(•þLcv)´RiMÒlª’Viv´Òs\Ï!S€hÉ S'IbJù R*fùõWžG`ÒnÈd¶ o¾»G·3¡P̰PÊÓŸ¤~œ1°q¢é§TÊËyî· }”Rxž…˜¤zFô£Ó/ Í‚( 9i’Ïeøú·þáø˜|6ÃÂÚO\ºÌx:äwþÝ¿Çv,üñ! ÑéPÌi÷úìÖ9·xžý£gÏ,#Œ >Ø–k‰t¾¥€$V¸ŽAÅbDzà9Vê|2òÇt=ýÔÅ«4;]&AÄr¥ú¨_­.¥&‘Æsš„âlúÖŸüõ[h@΃ ës´}p-‰ƒcIL3m'©™MŸ ýÑé„J¤N š`’œ–FÍ@"ˆé z´ÚmTbS*ÑbÂ3W/‘$`šÓ¬­.°[kòãî’ñ2œ?W!’’¢øCRGÑ”ô‡õÖÛ2Èg‚(FJȸ6—Î-rÐI{ >>ù À´ž®Ýípwç¿÷»¿Íý‡w‰•ÇÅ‹ë¼ðü³,ÎU14&7¥‰µ°B8Åuml3ƒŠÕRSºÌ•=66רiôzšj[` pÌT‹—ÍØd\k—ÅdêbÁ£wØäí8Ѧ™¾…£‘Ïdb/™œßX ÑŠ[÷¶é|^yþy¢XÑé Èç2hl2ŽI¢ßüá‡äsyB|–«ž.äm¡B&i  i¤o¼ïÇÂáüŽž´eÌ¢.…c[Ø–$QŠN§MÆs1 ‡$ÏͰ¾tŽùùbÙø Á$ ±%Õj‘z³ÅÞ¼Íç_}ŽbÁâÖ½‡,¯]fiÞãáØÇ@"¥¤7 ˆâÏ61$¬/Ñ‹y.l.rïV—{¯Gض{C}Jœ*f`/䳬,-'>gÖr·®—r%Ç…õ \Û£ï8ìQÎ,£T‚VS46þÈÂ"Gµ’å­;wÐÍyºã½±b)/ñ\‰ü©b®èP.8l®e©”2ô>çÎäøã?~‹i㹩9VJQÌç¹x~Ç4yppÈruž7ß{‡¯|í/™†´ËbeýmÖVÊ\»p‰D%|ÿí;õøý/½Š?\äí÷¯#ü€j©À ¦Ž)AzÃ×6XYÈ1ö§t:áÌ»ž‘-§—E „Ó¥5ƒá€ïÜ%¹¼u™•…U*• át‚m[Œ‡Nš'd3å\Ã4øþ›w(—òlž™c¿vÄÍû˜_\ŵóB"M…”Û4BâØ&«‹Î,—ˆâ˜õÕ2?x­GÍ,ÖÇÓŸ$”ú–a±¶¼Â«Ÿ}Y7[\ܺH>çpÒÙÃu<¤‘& rP;âÃþ>kË+L|ŸXi,sNϧRrþÜ:S‘ƒH4¶-ÉÌæZ9VÊ9d³…\jö×–ŠÜÙiü„DBkÍp4¡qâ³¾\ aÂß½ñm^ûá›TçÎb&_ûö×9³¾NÈž Ž/ðÇñ÷$üÊ“×è'ÔöŽi¶:dKÏ_YàÎÀ@J0 A%·|„€ÕjVoD³5¥‘†FÊSÍ\za”VL¦a²»_csu‹V»…e[óYÞ½þ6ÞçŸzŽÝý:wÞec}ž•Õ—ùûü锵*?üÑ6s¥,—/l2 ½hÖtËÄsLš Žm0W̰0ŸE Èf,¤arÒqú6¥AêÏ~>¶QdNœ¢<õp ?ð)r,,=šÍ¯¿ÿ&½QŒ“g¹ºÎÆzdz £)Ýn“ýú>÷î2_ΰ²´LüØ;žqÁ #j!“ !ŽÁ³Szxä+ã)åG^¸ Ç>·îÔh4‡”òeÞ»y´‰a¶Îm«1½Á Ï\½ÆgŸ~oþÃu¾òµ`8 dD½5& % E&QÄ4IK·-3þÇŠi˜z†$¢™eÔóK â8ž1n³‘¶±âðø„D%Ì—‹\ÞºHÆÉp÷ÁòWÁ·¾÷ú—ÃÞa½£m–çùÇßâÏ¿ú]Fþ€ÝãJ… õf‡k—¶À,p¯6"Š5Ž-Éz&–%‘l["¸®I>ïàû†!°ŒÙ>é´kø§²§q &mø´WÛc¿¶Ëg®>Í΃#­)Z%üèQ;®òôÖ¯0&Ôj]j'÷yöÚÓ¦ÇÓO~-ºý)½~DÞM™ÃÓÛ3 5Ž6]<éD$JqÔR-;¬-H”†þ0¢Z)p_¦ ×i$NØÝ?`4ê„-¦#‹lÆekë år–ÿôåßãâ¹-îîÞÄ”.Ç-ò¹,–°yûÖ ^|âW8:é²±œÃ-TØ9§!ÍÔ4 ñHæ:kKÅ´dœpõÊ:ßì?H‰«YæM˜£ñ”\6ÇtQo`˜‚¿ùÖßbè‹Õ*o¾û«Ë«üÛϽÂêÒ&ÿûOþ/I†L£Óp˜/gè§Œ'£ fÞ3pô—eJÚý ¥¼É¸’%ŸsHbE¬<×Ji ýQõ© ãY”×uéôZ a8TÔŽw±<{ûïSÌ,ÐîÆtzök=¬Yý…ùE¢(¢T*ø1ÍfŸòJ.Uf PÂ8•Ò¶†ÐéÇAăý.[gò€‡R`’lÆÒ:ýfÌj£€Í¾ýÝïÐéóâsϰ¶6Ç¹Í ’R>GÎuxêâ5âDcš™Lž0l]b¡TF­Íé0lbpÔžPrGâ9a”`H‰kÛÌ•:y¨æôúâº~òÜE]*–t­YÓI,t%Ú¶Ç¡îõ¦: sZ†îZt}M¨ŒGޝc§7Ͷ ÛÀ¶$ùŒM.c³R-²¹6Çq£ÏáqÓ0Rs;›Ñ< öj » ‡$ãQŒçæxú©'P"àÕ—_âÅç^àêÖ5:í6Zdž…¦SM{ÐåÂÖòÅ´Jiw!$ù¬Íd±w<`Ätûq¬p,Û6°,“|~–äš]ÜŸ=:úçà4)©`HÉÞá]LÓÒ+K+Z±þÌ“¯jÓ@ÿù_ý¥¾u§¡»Œü1ý¡¯Ã0Ò•ùªºX(p°ßÔ�K&“šKÛú°›è8AoïùºÙõõ\ÑÓÏ_[Òó%ëÔ†áØóåìc>Iú™L–á¨Ëü\žK[O pxçÃwA¦Ã…ÐôÇ^ÿñûÜØÞ¡?àOF¸®Ç$ˆŒ‡œ?{–¥Å³Äqü¨¿ëZX–À± ú£)½átÆ yÛ2è |,ÀÓ4ìl…aD½Ñæƒoñú®ó×ßø{&#XZ^àÌÚ/?ÿåb‘V§E0¡Ùî2 }&SŸ0Š9i ¨.ÈäHâ$åt†–-‰BÅp’$ŠJ9ÃêrÓ–$Œ¢Y6ô#ÿíãBÀ#¾C¡•âìÆY^yñEÝìÖõß“«Wž Š'Dñ”‹[MÚ´;m†}¡'cK'*&›ËS*Îcƒ^¯£ ù,‡µžžŽbm[¹É [IDAThÃìGìµ4ɬ)ÃÖF‘¥ Cœ&7Ðýa¢-C?Gëµ AÆ10„ÀŸDŒ'Ó0¡Õ?rý BJÉÊr‰DŸri~`8‘¨×qxë½8¨58{vW^x‰ógα¾¼Š°½s‡7~üÝa¥íVá¸ÇÎÃ=š½p& EbŠ“¬gÒîOiõLKòä…ªóY¤LËàÛñ, xš~l*àãðHT0£A«•ÖVÏðùW¾ÀÚÊ*ÝAð8vŸ™VwÉ´Åý¹y{‡£Æ>/ª÷õûè“vMû“±HÍä4Zk­”ö¼¼~÷í[$q„a¤f$ìÖÇ·Fã)4çÖË” Žš ß™†1RŠG›ÖÄqB!—ç©«W8i£IH”&—ϰ¸Gí EãdÄÝ Ç¦á”´]%d3ÂpJLÈf3D‘âÃ÷·±L!žk1b>:Ñ$²žEƱØÞi²wØáÆö‡õÌRVZ}ì ðI¢½·“>Ï\þ Þ|ç=îÜHIj‡G {µ#îÜ»ÇþÞ®ëRÈ—Èd ܽ÷­q¬¨Ì•X^Ì ”Æ2-¤4™ôšìßߥï+zÈ|ÆæƒÛ-¾ÿN“‘¯¸±}Ìþa—ï3ÂGô¡šQÁ®í°ýà}†£1ç6¶@Œ©Ì¯põ‰«|pó}Þ~÷¾¯1DŽãF“0Œ™/W°m‡Á° $8–KmÿÇ10LI&Ô[S|?Âu%žkQÈÙ„Q‚eJ‚iÂÑÉ`FÒÍ~ÄNB…´;užºrÞÀçý·p­‡‡‡ÔöL¦~û¯Óéµ™üÉ”|.GÆÍ2„á×s©í5¨íÜGš×d¹âba”Ò6†dg¯ÅþQ—NÏÇ4ÒºÒœÁŸ}¾?Wú)RS¾÷Û u‚(l¡”M«Û¦¢ó ò¹FÃ~aÄRuƒƒû¼ð|Õ¥,ëËêÍv7ÁµmÂ(àüÙÇcÆS¤‰a¦oÿÛm&AL§?ÁÒšNË)ñX†«2_!ˆ|®o¿ÍsW_æ­wßeL¹rñI^ë»DI—ãã&em¥Í¹'9nFH¡0M2fγØß­SÅÃr F@%Ô;1q¬±M­!Œ‚NoÂpR­”ùAZ Ól Brp´K·ß¾?áîý»òUÖ–/rýú[|íß ›™gJtâÑî´8¿¹ÉÞAË’X–B£’˲¶›˜^‘b1$ÆsL\Û¤Ñó½è :}Ÿi˜¤¢XxŒ˜ÒG~r¤ƒµÃE¦åP.Vð2În¬ŠË¯1ŒITL…rž šb[ή2žDÜyPǶL y‡§Ÿ<ƒa¤Œá(™i;<&ž-8iŽC,ÓøH$úˆžLÍ­ëº|ñ×¾H»Ýã¨q@Elœ©²²¼Àƒý»´º)æi4j|x+ä·>ÿEnÜnÓívBâX‰š`˜ý*g¶°-“œ-©Õ‡é”ò$5õžk1Gô‡´Vô‡{µ6QršP ÅÂ×o}Èêâ—/\âÁ¾‹ëX,V6ÙÚêqÒÜgy)K­ÖÀ÷áÜÙe>sí Ž×ñý1ƒAŸ¥¥U´†XE8–MûpÉÜù2ÍÞÓ0ˆãÔ/¸q§N»;Â0älš‰|ìýÿxQèÏ}_½^“$‰ Ú4q–ôû¹L‰Í•K[âääˆ×ô:–ŽëR,Í¡’„8‰™†“Tú6¦±só=ŽŽÛX–•î0ð\‹LÆ&Š4¦L­ç©’;]ïØ?s±?6Føåú¿~! ðËõ/oýÿÊ×/ð¯|ýÿÊ×ÿ2%qÉäIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/multimedia.png000066400000000000000000000221041217176075400240460ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ IDATxœå›y”dW}ß?÷í¯öêuz™éÙ7Íh$FB B²A0ˆÁ±V#; Æ8‰Mpbda;&vr¼0¶±  b¤‘І$4ÒìûôLOïKuíõ¶{oþxÕ­!ÇNbçäžóÎ{Õ§OÕ½ßû[¿ßû„ÖšÿŸ‡õ=W~çK@Ÿ!DTZ÷ŽÖÚDk_ƒ@ëXkhM¬µnj˜WZ/k¥«Zé…{ïXþÏ~Güc±€ü“Û7Á5Bˆ+€]Z3 lÖè,´Öh î~0„ QZ·¥TÖº®5 ZëÃJë祔OJ©|yß“ÉK÷€öæ[öZ–ñ+Z‹Öº»HýˆÃÀ‚VjF*ýKÀ:­5Bˆ_ýÝs“ó?]k´ßæ:6¥B–žR SÀ¬Öz“ÖµÖÍ!©Ôo)­>÷õGŸ]]ôª \¿k«áº^O†KO>ñ Ë4~§Ù v™–ñ gÐüœÖÚÖZ×Üþ¥o=¾jÆï¸íújX§5Ác_Ù÷äc›‡Ö¼¶DoCÀ…™E¶m¡§œÿï}û»¿ôÖºÆUJ•RÖðKZë?hu‚gƒß€”ÒÊŠßÊçË?úÆ×ŠÂð»a|OÊøD§Ý™}ìàqõ€Ëwnt¦f¿Ù ¢-Vj²Ý‰~V`+¥~áÎ_°Ykå!Ä4(­Ñè{ÞtÃU³…\f{Å(¥°-‹u#ýÌÌ/oºeïîMJë¹Göž¿õªË+¥QZaÛvþ’ Xy0LKÏÏÏ——+'|ßò3™_,—r®ãÆÂGßû#wœÃð@’ć:íÖé8Š.<øÌÁæßßu‚ÞRþ‹Ëõ·¸Ž3ÑhfÆ(¥2†!>e/ú¸Ö ”B§1á!RJ”Tä²>ï}ûÍhàØéÉšñ·k­ë7\¾c<Šc×2Mvn[ÏÈš¾K6r­µD’$¿øÀSÏ|Íîm9[…a¼Ý¶íOxž·ÇÏd~4ãg)•ÊX–Ùxÿ»Þv2‰ãÂ0<…Á‘( ÏEQ4÷ߟz¾ñ·@iT ´v ÃØl‚V»Ãb¥N'X¦‰i4ò>¥BŽr1G©˜e÷Ž1Šù,[6 ³{ûz¾tߣt:!JIOJ噦108Ð˶M£d\›FãÒ©½€Ò)ÐðÚëvm›zêð‰%`ÿMW^K)?Ñl6i6ø¦i3-óÇu¯ô}ÿÍžçÿób©DZÃ0šÿò'Þ9™DщD&' 8Çᤔò|…Õ¿zäÙKf`[FbA£$ ù¬iØ¶Åø…y¢8A£± a(­1 ëZä²ý½EúJd3I"‰ã„(Ièí-2ÐWfh ‡\Ö£ÙlÑR †a\Àj¸zÛf[CìÐJÖ,Ë:a˜æ³B)à#"o{dÿᯭ|Áë^½g­Öú¨äLÃÀ²¬ã¶cW\×Ýáº^Ùq]ÇÁ´Ì¦!ŒZOI)«qŸt,cvl¤ÿŸA°á̹iÚÛ2±L­5O<{”8‘$RrùöõlÞ0ŒìúºcÛH¥Èe<ò¹,®ë`fi´:xŽ Z!e‚L$JkLÓDÀõ¿õ'÷?õ}ìݺÉð‚aˆV&×l7· Û2±,Çq1-!Œ@ÿw8(' ÃDŽC !B|ì›OuôÈ–© ç·V«Í ÈÐôlçû8Žÿ~„x·eY“w¼fï„aˆ“Bƒ¢›¼5ØZéä¾Gž9œÿ³ßü7 ç§éJk|ßaïîÍ$+fkœ9?ÃÔìŽe"•d~±Fo9O©/ÇÈš:aD½ÙNC˜†V; ÞhSk4¨×ª,7c”péÏ‘ññò¬T`¤¤­¶]¾}0èË·„!›gÎûõõëF–«õæ©{Ï{Ÿ±ÍçNUõw¾w!WÎ>þÇGçÎíßT©œÝ¾f t§Rr{ËíAÐy½ejlÓÄ0L,Ëþaagî¼áª –e.®Ø„†i€†8–,Vê†@ °m‹8‘(¥‘:M…Žmb‚8NX¬4ˆâCH)‘IÄá£Çé„ ÊÎã”·âo¿šhîYT<®Z3xeÐ$R26Zêyõž¡Í¦) Ym4›=¥ÞÆácçjµ 9Ø[jõý¦í—êc‹ÕÁ+vOØý¯>xúÌd¥è,+kþö}ý«»6ïÞÞüæŸüÖ‘CÇ™©‰¢ŠªÙ(X,*)ÄÎÕ­VËÚä4¦ÐX¦@A«i°¸´ˆešØ¶í¸ J&D*Æ‚|Ö!‰BææÚLD1ašøÙù¾µä˛ټm•¸(qh·ZÌÍ~©µjµ‚δ¥4Z©¼iŠõ@8½8Óšš®Ô]»Ð ÂvËóœæ}>×|ý­{›õŽßIÐ(ºÍÑÙØïªzsI®é£ÕhˆXèÆÂ­'NOõ>}hW·˜šY¤Ù¨#ã€J½BNÖq,#Ûƒmgi·´a’+gèÉ»ìܹ“B©‡Í[7²ë²=̵sì?Ùd¤ 87±Às‡Î#£¥ ¼¼ (’ŠV; µšƒR¾mÚ…Þ¾^ uËú=Ív'i,-ךGÏÔ›Uܦg¨V9o4¥”M­T]ƪÙéĶ֠¥å‚[¸lKŸì-ù"NN›ºÙLôÄT[ßxÝŽ$ïn4­R…¦·ÄHÙbz®ÁÙ‰T37=Α/Ç·¿áGؼýÇumvlÀ°ƒ}}LN-²}ç6ò¥'ç›$í…Á,=;­uÚd©´|… ØÍZC½ÕÁw]혖ž™Ÿ1²™œW*”=àä{npb|¡¥"£ÙWT ÓLtЮžQ3®Ú*¤eêxZm,ÉÖ«[ÆòŽçy©c=W©Ëú8rRt:Jì{ì½uS¿hu@É×6êó8z*B% Q¢V³A$´[¶lèçŠÝp?7Ïñ“çh·#þæÁ§Ù½÷ –Û. ßµhRª4Äk…Vm¼"ÝЦÙL‰Í¡³ø³¯}C÷—Ö°iã:n¼ö*óÈéùlÁ÷{|7ôg<©BwakãÃܾnÃ0Ð{ߎ|Ç[i6öÑcǯ@ˆ¶Ô²Fºæ¸Ùúö-ñR K==µD]f1ÐxŽIÅ$R"РJ)Њb>Ç®ëXÓŸCêˆã§ÆQÚÀs †ú×`Ù‚Ùéeº@1cà:I"±-A'–H©Ð¤ üÀ („àü…I¾ùÐw™˜:À¦õ^ÃÚá~Ž›ÈJ•LWf|Ï£Xê!ŸÏa™&RJÂ0" C’$Æ4-úûzqÛBxq"{êõ:ËËÕ¨U_Zîëí]Ȭ]³øÌÓ‡Á1É{®c„™(,C£•B)RŠÑá6m\H;MµÚ ¿¯[÷`˜pr|ްÓ`p DÔ6 "‰Ò0º&ÏÙ‰ˆbÁ#^V¦zyT t‚†ˆBÉ[o¸†ÑÁ!ga¾Òo—ÛYÇ)±fp€\.K­Vãô©Óœ??ÁüüõFN' Š" ÃÀ¶mǦX(20ÐÏÚµ£ŒŒ ;¾ç .Wkƒ&NuŠ„íÔê ÄQB.kÓné®)Vé-Vh7[ô–úØ<¶…N'Â4Ë&0ÁÏh2®ÄÒ6A(IÅ®-ƒ\yÙý§1=/q.m.‚)ïHɶ-Ù¹}¦P­V³.Κ(ŠÍþ¾^úûûXXXäáo›Ã‡²°0O»Ý&Š¢´$ÕºÛ²¦¦f˜&–iaÛ6®ëR([Ë{ö°sû_JÉé³gq̘0tiubFó?Ý&›±©týw~±B³Ù&ëf9uî$Ï<‡ëºŒ­æÉý§Ø°n-ŽëRiä-AƵ(䮼lÓ2ùÓFtä_9hRš¥åy‚ BÅ2;T^3űèï£T*òÈ#²ï¡‡©×jÄI‚×uñ<%q’¤`(‰’’$IÃ%%B,--155ÉsÏí§`€k®¾Šë®»­5ÇNœÂµCFJ ÷˜8/8ýt‚-NL©ÐÃñÓøæ¾‡që®ÞÍÌ\“£ÇϳiÝZ,×c¶aÐ?hà¹&3 M:AD!ŸÁq,””(ëèî˜=qŒÝ¯:ã\så•Ch-z{JärYîýÂ9|è–mãzÅAµV£V«Ñétˆã8-c•ê:”FC C:6†iÒl6¹0qG¾ó·Ýr3¯¹áz†çŸà²]8|ä2QØ6Tª-ž?xŠÃ'±qýz®½êJ†‡xð‘ý(i!„M¾gÉjˆï{Ì/·X\î`ϳð\›D) ýƒèšïŽm[ض~ý ïº†T ¥R‰Ïþ ŒŸ'_Ècš&¹\ž™Ùæçˆ¢¨ÛKtC ´@I…R)ãU3 ˲QJÑh60„ þøO¾Ä“O}—w½óGyõ5{yþ…ôöd0LÒ0;7ËácÇ™œ]à=?v=c££¼pø(óKó$IÌÌBƒ‘->B¤•îøTMëzÌ1³ÐN !­Q/!ö^äÕJ›©[·ÎεZMúØ·ï!¦g¦ÉçòضFsêÔ)’$ÆulÛZmO•ìöàJ¡¤Lës)‘ÒDu[Ö8î€Ë²Ð†A£QÇ4-Nœ8Á§ïþ ozÓ¹óMo$“ñ9óš›ØÿøC€dûÖux~ G‘óK,/·±m—B®ÈÜL•¹©9²~–ãçjTª!Gr¡d|b‰j­ÝÝèW°Hs€®ºòêŒÇq¨×k>r„žžâ8Æ0 ÆÇÏ¥>¯œÙt»üœTRJ’D"eB’$†BJ‰b5>DQ„VDZI’˜Z-$Ž"¾üå¿äܹó|èƒïã§>øÓdszGÉf²(¥xô;ÏàÐÏôüyJ…5]+SœÊñ“çÉø.ƒýkMÐ ˜;?Ž)\×áÀñ9~ê,fˆaˆ´¨â „àÇþé{°m§ë¯‚êrÓ²Èd³´Z-<×ÅsÝnäwñ=ß÷ñ3>žçcÛ6¦ibBˆƒ«a®Ö¶maY¦•Þ-+u¡v«0 ¢(¢ÝnqòäI>}÷gè)—¸õ–[©Õè)Ø}Ù. 3d~~™™¹i²™ J%ÓÀ·g. 4( Õz€c¿hèQ¿² ¬[¿Á»rï«0 Ñ•œ@*…eš©¿*ŸñS“—ªÛ?¤F’$8N–ÁAúÉd³BÐjµ™šžbüÜ9.\˜$Š#,ËÂ0Lâ¤Ëö’ÞbbÚ­6™îo´ZM&&&øìù>ö±M«½“ÃÇN0˜íebÒ¡¿¯ÄÌlƒÛmF†Æ˜]h1ÐWD>a%%OË2ÑZa³•—@Á–;ýl6»úYwXÇq@×A+TiÁ£uZ¥)-Ù¼i»ví¢¿¿ÏóÈf3«@’$œ9s–'žx’'ž|’åå*Ží`±0"Y¢Ýn‘Éähµšœ:ušÏî^>ð÷Q¯7xáðQNgýº=X¦EÆTªm‚ fbºÆÀÚ2–b™&³K¶H¥©6[¢»>¡µÖ«DqÌð訷2i˶0 ßó±­t7ð©ÕJo¥êaË–ÍØVÊ»û¾wÉâ!øÛ¶meÛ¶­Üþïç¾û¾Îw¾ó×xÑeDWìl·[‹´Ò´Û-žÛÿ<?ümnxík©Ö\³÷F¦ggi·=^8|”‘áx®M¡˜Ã°;¡c ôei´,b©0dB£øBˆ×€z§#ò…‚w}ÄìN(ŸÏ±T±Aƒ'e×ü»=¶R¸žGO¹L£ÑÀ¶lJå–eu#¿ñ}<<ÀÈð0þйbÏ>ÿ…?¢V«áyn÷ÿ_t‹F£AooßjLxpßÃìÚu»vn§Ñ’†fjj™¥Ú®[b÷Ž­¸™ ‘!(d,¢ŽÅžƒ ôåxôk­¦Zë ´…áêì”Ö†B´Û)cdš&ZkzzzVëxÏóÒèyx®‡ëy8ŽC³Õ¢Ýê¬V‚µZF£I»Ó!Š¢—¾×_ŸøøÏ3<4„ÆjÖp×u1M›f³I6“% xàÁ‡[7ÊèP‰$†A_ﳋã´Ú =ý=”Š9Š…—ïF$UúÚïVÆÑ˜Bi5 ô ¬®Úa:–åµZMÍæªÉÆqL¹ÜCÆOij!R®>µ€´U ‚Nê R!¥C£ÞÀ2-×ÁIÛI¹=Û²ìt‡/6¬ç®~„{>ó4šMD×òVˆ«N'-šlÛ!:=zŒ ““lÞ´só,,Öé)•‰´K_žÞÕ…Ξ?ÄãûŸä{O=ÆÌô,åRC£k9`Ò ('–²°¼T©TkµœRjÕt=Ï¥§·—êrÏ7±â)Õj¥W©,uÕÙDzè4Ààû~º›«5€ƒí$8ÝZàâ±~ýzÞýîwñ¹Ï}Ë4Ii»”ÖZS¯×¢Ñl°¼\aÿþ¸óModãØsç“TO¡Ã6ßúÒ÷ø£™)f¦§¨×k˜ÂÄñ<²¹ù|†åjSlj\Y7?XZk¿_i6[?W«×)—JØvÊ© ­¢Õla‰i’È´ò¢›þÚ­VZ K•ÊPÝ¢É÷ýÕšÁuœØ!qœ.6¶õb¾þºkÙ¿?ÀumVe Ýja˜&žçÇ1gÏž%: °8;Å#ßúëT1˲(ó¬&ã;Ì-Öˆ¢˜N±P­Ÿ ÂhH `v-À2AÐÉß|ó­·Ú¶cô÷aaâû>N'ÕàmC©€éØ´š-fffSá²›!’8!Š#’®lµr%R¥eðE™Ä²ÌÕèŸÍdyáÀÁKg7ÛX–E¡P ŠB„0زu }½½DqÄÉÃÏKm;˜¦É`_DZÈv'‚٥ê܉‰©‡¥ÒÇs@ ˆ-­µBD@müä‰fãÐÌìÜ5[6mLwÍqˆã˜5k™œœêvsi”WJ3::Âñ'X®,çcâ8"Š=Â($è´[müŒO&“¹´DvRÑT)I6›%Ž6nÜÈÐÐÓÓÓií±Zk(‚ `pÍ N‡NСR©°ní:FÖm P(R©6B#,-בRÅ ÍNP›­T'æ—k'y  ´äâ: B4 ¹ÌÌÔÄÄWK¥ò5çÎO°mëflÛ&Žc<ϧ¼’îl›$I›œ¾¾^¶lÞÌÓÏ>K"ÂÐÇóB<ÏŶœN§åày>Ùlfß÷ñ}(ŠhµÚضŸñY³fù¹9LÃH9Á.ab&n˜åå*†iËçñóeL1ƒRJGRKõf³Ùî,×ZíJ+«@X0`Á‚Ò´V\ÀJ­,µ‚R>Wlßß|í²Ë÷|èÜÄ…õ£#Ãd³é„[­¥R‰8މãÇq°¬´ëÛ»÷J.\¸ÀÙsçèíéYÝiÇI-ȶ-l«E£áàû²™ ™Œã8t‚ßóCkÝ•ÒÓ}‘«=|ÚI†ÀqÝÕ¶ÚìªG^©÷üñ SSaw¢Dv”R!w}=–L»¶y.QzAIÕÔ%ÑPk­¯Ü¼>œ_~#Š¢Ï=~’«÷^a¸®K”Ëe–––R®6=Žãpçwð¥?û &&.Pî)ã{^7\œ-,«¾Úšf‚Êå2ÅR‰ ©×ëØ¶Õ­2mt——J" Û²ˆ“8¤ËàÈè¹Z«½Ÿ•³4éâC 4TlSÌ— ÙùZ+¨Ä2Šu·K{ÉAI‘$I¢ƒNüÅ\ÞÿÉÙ¹¹+Ï¿Àú±µ8ŽÓ%3bJ¥ËËË\œ.‹Å"ïùñwó•¿ü*&—ˑɤ©Ð¶‹01M«»{VW0µ¨×jLMMQ]®vãN‚iªU+óñÒFzT¦§§H ¡ÁÁIà…î"$t´… ™Ïfk×ô·ƒÉùN³®²—"ZK­¡^ïȾþÞŸëtZûŽ8i‹yÊ¥™L†F£iš”J%ªÕêª%H)Ée³¼÷=?Îw¾óî{ˆ™™²ÙlZ1Ú¶ebvw~år\—|.ǩӧ©,UÒã0¦µª(i"„A>ŸYÍBQ1<4´úÛ™ŒÐ6Ä J¥Äži@l{~œ+ Ç=CÛã,•x}¿’çç*—–| #¤TWÖ7¾æÚ'â©{:AçãåêW]A&“!—ËÑl6QJQ.—©Õj«uÒe|n»ívîÜÁ·y”çŸÙ™LÓZ-ŠLËÂêºçy„A‡|>Ÿú·7•’²û¥r‰f³‰eY‹EÖ­[K­ÞÀ0 í8öÓ…¬7éù å~íäôÚu•vÖhÇ/)Û-èÎ…GtÑçÚÝ[_þ”€Vh¥´ÔJašB?ðÀß|ãæ[oûx’$:rŒ=»wáy.ù|žF£AE”JéÄ‚ XÍçív‡¾¾^~ìGßÁM7¾–#GŽrüÄ fffÓÒ6аm›|>O±X ¿¿Û¶ˆ¢­²û=é(ò Áq\––yówbÛ6 À2ÍsŽãøõÏþ—`ç¶-Ì=> Ã%ƒù¥GÏ,é(Œ„š÷´ÒšÞ"¯ €ÖZI%NŸ9'®¨Õôé3§†®¾æZrÙ aräØqvîØ†ïyäóyZ­N‡\.‡eY´Z-’$µ0Ù%ßÊå27Ýt#×^{ µZZ­NÐéÅ1Zk¤”A@§“qFZdIÃ@Žc“/¨.WA@¹ÜÃm·ÝJ£Ù¶l*õÆ}Åžuí[nÝFoo‰çNµhÄËl[ŸÅ÷«9SAC¯Èã2¹”¼¤WUÆ û¾ë2?7×ÈærÌÎÎaš&QsìøIZ­Ùl–|>¿ê›ÅbÏóVy¥qÓétH’Ïóèé)Sî)S(¤&/«Å•i¦íðJC”*Iš¦i ¤â§?ôALË" C<×í|üã?ÿ{K•šþÖÃßÓ‡Ï,êå–Ò*‰´m¡›í@ËDj­Uz¥¯ ÀŠ@’Ÿÿ7¿`ÍÎÌœŠÂ`!›ËñÀ·`ålÁÉÓgYª,àº.===8ŽƒÖšL&C©TÂqd—ù¢ˆ8ŽW¥3˲.âm,Ë\M‹¦ib[™nÑjµH¤¤X,r×]?ÃèÚQZÍ6år™ûÿúþÏ}è§öôÆuƒlÛ8ÀÌt…z½õ}êð k¼"‘ÿ@\ÛÖ0ÖÏ=À,ôõÍ<ûÌ3 ÓÚüÚÝŸîr&™œš&‘Ã0(‹”ËåT¿ˆl6›¶ÑqL„a¸J¯¯ð «µ‚eãØÂ0ÀV«E¡Pà–›oæ®»>ÊÈÈa”ÉøT—«•ÿü›¿ñ;ã§Ž˜Bt¦›ªÃß¹T6M#U‡¥B½Dx‰ ¤iÄ´„êíí•­F˸ﯾöùF½ÞqÇ àï&') TªUÆÇÏSo¤‚ã8ôõõÑÛÛ›Öò] )—ËôööR,q]!Äj)6LÝ&I§ q¡gÇŽ¼õ­oáƒü·ßþz\×M¿ÏIk‰»îºëòùüô_Ý÷WÎþçÐ íg´Î¸Rg|[¡ÔI¢ô®-ƒúío¸\÷”²:ŠåK àÒ ˜öô’×Þðýä“©ƒËK~…G¾òå?ÿÂ{ÞûÏÞÿ/?ò3Üs÷§ùñw¿“O|âßòæ·¼€É©i …<}=e¼nèºnÚ*·Û«1Ã0 2™Ì%Ý ì ¨+¥çy”J%ŠÅK£õÊÈ_ø…OüêW¿ò…b±066Vä‰gĆíWþýÔaHOh*¥õÒò<õz]A`6›Ò—þäÿ|ãÆÍ×ÞôC7]þïé“üÁïÿ.ÿêçî⡇öñÑ»~–;v†SÓ³äò9Š…<žë®¶°…BÕíèVâ°š1LÓ\m% ¾Ü8svœ_»ûž™?øÜïÆ2Œ(ŠBÑh´ÕÂRC ÿ^ê0¤EôŠ:ÜhÖƒ$J¬D$âî_ý¿ŸËç>~íµ×Ž|ä£w±k×n~åSŸäá‡â§þÅûxï{ßÃúõˆã˜…Å ?íþÇÆbu÷3™ÌË.îéé¾ýÈ£|ñ‹_¼ðÈ·þmSˆiÓ4E>— ‹ÅRR€ÿIDAT(®ÑWuøÒ ¨”^Q‡×–† 2-3Rªjµºü‰ìÞ¾õ­ à w¼‘¯Ýw??ò¶·ñ_û³¼î¶[ùä/ÿ2ãããd³Y<Ï#Š‚0æ¥~÷?RJ*ËË8p/þñŸñ«¿úkêî»?ýüCûü\’Ä“†a¨l6Ûq\7,÷õÊÁá1=³ÐÀu|„HìbuxiùEuø/xò’Ù\Òs‚Ú¶Mî¸ã-êüø…0 ƒºRª’Äq®Q¯Oý»_üÄŸŸ8~üöñþ÷_¾nlwßó~ò§~Š/Ü{/÷~þùoÿíw¸å–Ûx×»ÞÅm¯{ë×þ­¾\­17;ÇÔÔ4&8qâdòüþý“û÷ï…¥¥ÅC f„  , !ªž— F×®—…\QÿmÕá—ŽïS‡c)©UC®¸j¯^3²6i·[  Ó² %¡”2þè ÷þõSO=5ù¡øš;îxSïu×]ÏM7Þħ~å?²ï¿áþûïçSÿá“üúgîa×®ÝÜzÛ-\}õÕ¬¥¿¿ÿûD€ Œ8}æŒóݹgŸùîá»GÿÓú[n½uýën»mpÏWäÖYëÆÆãØñ“ÌÍ/„ãããsí{ðäÒÒâ,ݾÚ…0ÚBPëšù°  "„¨{žÛÙ°qktûoSÓs,.Ö¨Tç(F™_\Jy„ Åø™3·ÝU‡m+="ÿroþ/½7ØÕÔl €>`zI—Û¶KƒÅl6ë4›ÍÎÂâÂbEó¤ll¨-RÊ*ê^R²ٽ·I™ˆ”ÂRÿ»ßsü;½8ÙÂ\R0Фz[¹{Ï)XŠtMRF¶Ò½7H“Z€îÞÕE×÷Mî—|Á‹`X¤z›C ŒÕýûÊÂ"^Ü͈Ôôÿ—ßEüG°ÕÅE—qÑ3¤ ¬ìèÊóßiü£àÿåñ?¯îäÕ7®BNIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/my_documents.png000066400000000000000000000142341217176075400244270ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚSIDATxœí›[¬dÙy×ë[kﺞ:×>§»Ow{n¾Ì˜™‰í±­8q™DN’…$xà x³xÍ"Ï<ADD¸((b{ÀQÆc“!@‚ÇcOìñÌxâé>};÷ªÚ{¯õ}<¬]uêœ>Ý=ŽóRV«Î®ª½j¯õý¿û·¾vÜ?P>ñWË6Zêý}ïaå£SºëFÞC( ‚£ð íwA>@¯ì<ˆwˆ€ˆÇ;Op‡Gœ?µ †b–PK$"IšÀQ€zb‚”Œ” FH G“#öŽ÷‰ ±ÉßÇã#xó%H5H‡[ïþ&OÇíR§F8€aéågž¼ð ¡„ÇŸ !<øà"x>€— Œ÷/ Ep8‘‚BŽ€8Á¹|‡Ãaíž E5 IQkPMDU#é Ia÷ø6‡Õ7!‚0óÐ@ŽîBªÙ\ýŸÙý_š÷€†ƒÁ‡PŽ• ÁŠÃ;Pçð …:Tf®å¤ÃX p% $õxɤº&œe‡-þ3EQ" ‰ňf$#¿ÔH6Á0¯5ðÃM8Þ— ;ä3Àï¾Wüèiž/˲htŠu44!: š…3!XF“–ÈQ‡zE pº@næ~–ZH¬}GûÝ „تEC¤&:%Y"*Œã=¼d® d ’Âpn;0©á“@¬ \½ì?œPÇ)6ˆTÑH€:ATÁ90P•L|È«¨ym‰°–*‡¸üš‰¾as(p‚Y:‹YÊÒ`‘¤S"FÔZqw >ƒ¯š9¯’¯½­D=> {-NÀ]_ø¨S’VèÒ”:9Ô‘E]€ä0Ÿ0;!ÆPu¨$p3žØÇ sCè\«6š‰ç1—Psó †IsIh¨µa¿ÞEÄ¢‚·L¬h–õпõ» ‰ÁòOñ‘ý—y¨@¯;pnâYV"HŽä@EPóŽ"â2ܘ'i/Yw!a–爼ó8'ˆó)qø–ÿ€÷4Åãl¦ fY–,¢–htÌ$!ÞŸ‰’E] Û§,L ÖáðF¨»Â§÷áË@—CO.G­è #Öh"?]$ I+ú Á[3ÍÜÍ„¹ì h w® H!œÏ»ÄPM ŽF Eˆˆµ ìh–ƒÔ‚àÅaÞ’·ä=ĔݱKàHÊvÀ¹¼Œëð) Ï;p€°þAyÁ¹lÏýRÊ,­x8qç' ¾ÞyD Ä—x×Á»…+ ¾¤”.…ô)¤K]<D\ë/,»>mð®¢Ñé ç Ô5¨+ˆ®À»/%ÞbRD/Jj]¯sà|V'Ð]‚Ð…8éò0"Ûtè VÃO™ãåJÊmQ¤]H$‹ÚÌç !oÎåkp%Þ—×¥”>Á÷)e@á{ÒÅSâ¥@ZS5a¾ÆI©E{ ’E5I ‚’ xIÉp.k¢´ûœýzöy°õRMoôÓ|üàk¼³€pzt]a?ËŽ 3,³æLÈÆÐ9D²x‹óx.ॠp‚tðRRº…ïQÊ€Ž é†%ºa™NX¡–é……Ðq}Jߣð¼+ R(3°ˆ+Zà|6¥­9—Å_²¶Í¯ô7˜ùVºËü$Ðy 0,îiµîȵ6®õZN²‹šo‡wï' ð²4HI!]JéQ†>A:8—e ºÑ"¿¤à"Q"j5Qj¼ˆx'ù7óïÑ2s'úk™•yþ“à Ü¬ðÝVÇZX…,^sƒ–‹‚WA²^䀇ìç¡rBbnŒsÓœ#¸…•]Öyç²[q® `Hé†Ù©ûY€œ×5g(Ú†SÙÓ˜s­ëleߘ`{M8ÞkÀÑ;º¹óéßúÕWpÅo}í_n}é[¿ÀÒǧø^«ûþÌÕ-èžkuÎçÏ~áž÷ s[‘¼ïYí~= :ìd®ß3À½Ï±„àñRdu“¿s!Û'­ ¶¢`çÍ1¯}ýÞy®|høðoê,>)A5/j–ÃËùµÀíNvÞ,Äò½DvC"Y [fäÀÐçgͽ6†Z㯳y )‡JJ3%±vmC\‘ãQÙ.% LAÄPU‚+ÀAÒˆZŒºªK <×XÄiÁª¶דÍÍ6n–9¨ÚН¶YK”Îjã&G§§ ¨ƒG”Aœa©3À½a ¼9¤-$5ŒH’[i+ËÞ2¬ÍI%g¨5 503gv(9ïÆåÍ’Èâ•üÜdÙÎ÷ÜLåN¬ì\´CZï‘$Û’™:à23ZœƒÔ>/µ1†sB’\o˜ýÎs¹ÈBë‚D^|¶"xþ b0 ƒ¤‹ÈŸ­}2wEÁ¿ù<¯ÿÎçS–GËlnm✛nÚþøœaíŸ[;;ž;gq¸æ¼÷á Ok‹-‘®¿À'~ùuúÃ¥Hö0h%¨½&…Û¯ïróÛ7ç÷—?¸Lò)°¸wÿÆ;!çRïõ­š·ÞzëG'ð=ç!š¦á“Ÿþ$õ¤ L‰sžb³ õdœ[3kSÌ2Û‹Ë—/sãÆ Ö××ÙØØ8µèâ™Ù>gsL&vvv~:8¶··yî¹çx饗èu{€bV£$”ˆ#Ï…NÛ€Åô½­òäÁÖÖ‡‡‡ŒF#677ÏÝÀƒ¤BUçÀ\¿~W_ý)eQ´¹æØÂçÓêdf§æðæ›ß¿oý^¯ÇÖÖ›››ô{ýyiÚ5"Î0- €ÍŠ dñw@·Û¡( ®]»FÓ4<ýôÓE‘‹fU…¼a7O¨f loo?´‡~Àd2FUyùå¯óÕ¯þ·S¿.^¼ÈÖÖ½^œSC²hÎ.yˆ P2×]ðh[[ëv{ ‡C{ì1ö÷÷Y__ϺÝ.|v³Q–%››[\¾|™Û·oóöÛoáœÃ{îü³£Óé°±qõõM._¾ÈÅ‹—è÷ûð•¯|™ .ðê«ßäèèh¾Ÿ#›››\¾|9K®³“;ÚºÚ‡AUÔ<1&DÁ º}–––xê©§xë­·X]]o|vuα¾¾ÎÖÖ%VVF\¹r•ååÑ©Gß»w_|‘étš¥G•T×YŠV×Ö¹°y‘Í­-Ö××VçX¨••e¾ð…/ðo~ý×øÔ'>Æÿƒÿ=g‚™±±±Áöö6ƒþ€ˆ’´!™¢–ÀA|˜4M¹º˜,GeÝnK—.±¾¾NY–¬®®2ÙÜÜdyy¹åÒ:’äµµ5®_¿Î+¯¼BJF¿?`mm•õõuÖÖÖáÁÒpšI õá=>õÜ“<ÿØßã+¿÷ûü«÷;L«šªªX]]åêÕ«HO8pš  å (—é¦mä”’R´‡n—«W¯²¹¹É¿øEž}öÙSbü£ŒápÈg?ûÙé7ÖŒ‰ãC,Ž™Ü%USÔ=Ÿè,÷økŸû)ÄÁoþ§—¸wïN‡«W¯²k»ìãÚ0ø$¾I9n|´!°´Æ0A¿ÛgéÊ?þ8O<ñÄŸŠð÷Nmš1š"6Ù§©&˜&,FbjÐØdn¦„Y$ÅHJ‘=ý8_úÆ·¨ëUåÊ•+TwªIªÕæÆ]ã{„fuv€^¿Çæ•+Eqvê?4BjÀ"4GXLÙ`ÅHŠ š¤|T¦1¢©A“ækSc1&.o,sùâUU¡ª\ºt‰›ã›8d.Õ9$†³.öŒlÀ ú>×.^›ûí?«q|ûmÃ!Ì¢´3gõ ñÚ›&­3â#)*ª š")Ö|è‰mv÷ˆ1²µµÅèÖ(Û”¥Y­Í7Îìã”å™EŠ9ƒÊ`-¯ØÞÞž#£:Þg²w‹u&¼©I©&65qø˜fÄ×ùà46¤¦&¦ՈƄ¦†”"Olo°±±AÓ4ôû}.\¸@´Š”²7Ó8OOûT@­MüÂ3™¿ù ‹­ábŒg§þ©GQvØxÿ'æ»ñ(ÞŒ‚ÙW-L>·Çl¦­šj>Ro9õd(ùÙÏ+>x ãïûãÂ?å_÷ï¢vOTû\T-—•ÚbÈg?xÏÿóçså¦)ù_~…k×®ýxÔkƒØê)ób´ÆgaÞì½ìø¤îéNòlŸËÕÉ*öý\¥Ká»<¹ôI.÷žåOôå¹8+ǧãȈ¶N=¦”+¼âhŽß½ñ­ €T¡M…CqZ/Ónþ„Ê“œ`QN癩$É‹ǬìRC£Si(zJ¢¡C—¨:/ŒÐÚ‚ š-¥Ãp USçÆÀãxõíÿÉ_üä/žC©aõ˜8=ÎFuŒjBÚŸˆCfÅJ8cyNš-ðÌrŸÙí¢rù᪤¦gL‹#Ф”®ÄcÂR‹½É )Éœh¤=±qm'˜k½ íIÒ‚œŸ%ÅÚf««Ï‚1T#6Ó–Šv†÷ˆOx‹ˆØìÙŸrxÔpë­:7uœv,ç'YS3†iSáCÎü|EÁh4¢i"EÙ_›:‹7Yœ÷Ìèf5¶3¡ØL$îÛ39ŸŽ)‡Ãf¹?!ã•%¦€÷‰¡ô˜¦)MœPÕ5ã}ÖO*]WYàe*¨cM(òéŠ‚ÂÆÆ:;;;\¹²M9X¡©§ÙÕ!Òv„¸wíNxhœTgÕÚbH;£í™fm`d±ió©Häs7ï#¢QE¼’Ì3°‚½TQ5S&õ„¦I¤ê$´D$˜uPhMlZ>BìïïP Vivß$„’$ÙÎîZCgœvß'(ç,EÛ²ïFŽñ5’ö€& ê!yRø¤HHH ,‡>·›#ª8aRQS&‡™ó‹ªp.Ð&>0eÙdÁ—yzYæƒí§>Ì7ÿóï³váFn†Âq¢ûs‚Z pYTµÕ…ö³jlä"v–M-˜Î â=Þ'ÌL¢ | iÂKBTqÓŠ:™6Ô%ªqkÛ€³Í}XÁbVW¾ýM>óÑïñê÷_ãöÎ]îþðû<þøc¬m?ÅáÞ=–FCÄ :+–ÊôºMhLA‰X2’¦œ¦˜¥aî²…ÇZ@%·ÙZðhÒ„„ú€¨âÍ“DQSÊÚ˜j–sJ3åä°÷áP«+­ÅnêšÝÝ)GÜÛ?bï 7XÞú>»»cuu™ri•XOs †pÆ”™ÛhD“b)ajšk‘š ÀÒ‰Ïw‚óïÞ+f'Š©à4áS„" ð¢ˆFüQd̘ñøU%ÆÑ/FÐ`ulòé«*šl~ ÷oqçÎ-VW—é¯^&½Ã‰o[ ô³A8˜&†!ed ˜¥¶˜åðצ)'.ªmð•ŸâSÄ|@}¶C" SSüb¦8ÉQOá`\3ŽÙ;º‡:EãéRߘqßÚsý&E| "ŽP8Š2w}…çèÞ-àý¬\~Œ›ÿëÛ”eÙF³Ö×Lü±vxý|ls¡ãÀ™¶›1\ Nð·SÎúû~w9¹e6jl3T¡ÖŠIcLšÈ´NÔuCŠÊí•^ë¾Êþ^Èyˆ5„òQq@»mf3c4òt˃~‡4ì""”e—úðO>û ÞøÚ¿§Ûëgn-D{Çt’¸ò¡³¾UÜÜØ¢“NSðÚý£áü»˜”IO&Õ1“iCZ`gJ‘ºófø£Ç®ÑÝíQwŒi̤®àQÉ'“sÆÊpNÙe©7 !xzƒ%Æã]RRz+[H9¤ì ï{@Gos‹g~æ3çÞ?oìììðÆë¯qØTL«È¤n¨ãlç>W­D)¼±—öyß½Á“^ƒx¡÷ KÕ2q¹“47›¶)ñCUÀK¨9:aey…~·Ïp0Ä¢2=>D,âcäèè˜åå%¶?ð¾Ù?—˜AÈüG1F|Ñáp" %.>MÛ ‡?XâŽÛåËŒƒÜQT ºKLú#šIDÇŠÍüÿ£¡yqÒøà`einÙg4XæÆî»üƒñ·1Àϯ~ü/±¼¼ÄàÂ5ôî›çã«#ÞøÆ`ýàU’*1)U©eZ7Äd¤vg)5¼»s“·ïÝdt¥Çí¸Ë¡L!X›QæŽ ˆ„¸’/sIÛxÕï,1è-SuëìU\ۯģÜà¬hfÌóõå z>£á2k£ \m ã;?äÚÕ÷±±ý;»? Û¥/àI'EÙ§‘’¦ÑìQ T„„‹Ê~<`/îs§ÙcßyWv‰£ÄÆ’!Ò¥G7Ñ$äYøœ³ëYļ3­p}†å MŠ‘m€¹“òøƒ˜0—auyAoÈRo…e¿–£´.Ð…Þ~ øëÛOpóÛ/zƒ¶òb$Œ˜ W*E )ãñ!·«î5{Ün8–ó† ÀÀSº«š $«£|À*ó>¤üßufÄΣÎyË^£†¹<^t²´ýE±=Í£SÇÜX[[¿Ûív» ”Q1êü…+ÏË¥åm!9ë4}K åq'Ž\+ V6):Mí\]a-…žÕîüáÞ»IC…žƒþ*«¬²:+9×zÓr‚xoýQÏf}‰³ÊŒÈyyqÞÊn9gaséŠ,—ëÖwcëÛZUĤ~¨öß>z‹¿³@Å-~û¯\ÿ¥ÁÅ‹oš¦÷ÆÏþù¿>ì÷ûì<«íªžL&n:R×5€Ü½{·³¶2rRtlïxª.¨… “aÏÂÿ‘«Ï•óšáƬŠ4;êŽ1¦¦iªÙ½Åy罟‚‘~X Í↮¿óÓ¯=±öÄN¸â7¾ñW^|ñÅ/Óù3~[ëÀ6° ¬]ÿ;×ÿñ¯ü£_yl0lÖu}Ü4͘AJ¹±-Õ?­“âœåÄFݬxZ…<õÔSË"òàFªs.nݺ5½sçÎñy(íËfïEÄŸaf¼÷ÇwÆwâÏÿÒÏÿ÷ø=à€Ü#ü.°Ç9­² p8"·”o¹à޼÷ZUÕ8¥T‹ˆŠˆ¶‹8q@*Š¢é˜-~jÃ)%·³³soñ;3»‰ÓDšªj¿ßOððN’Ù~fÏ53cœ•ª %ïÔPµ¯sÿÃ-*ÇÀèÞÞ¿}üâ¾XhÒ ‡‰Hp¹ yB 'FUsF¬Ÿ·8\;€àÎd–g×§mPïÇLÔt°7Þ+˜rØ%·ÈßWgЦ°|„?‡ÑŸß‘÷R¬gr¾g¢9²<|íÓk‘?¡æ¿o“ó~ò0:À…öÕ{À¼ÿ—‡’Åþ&YçÏ=߇YE ΈÙÿ'ÃÈD×<€ø?>àÿmHú¨Å‘LGIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/mycomputer.png000066400000000000000000000153361217176075400241310ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ¥IDATxœí›[ÇyßÝ3s®{¿`@4  Ä `^¬* ò­$’)ëbÙå)å¤Ja^9e«¢HoæƒKñƒ¤‡T¥,•KIdÉ2m+ŠHI‘Ñ)Ê"’€±Xâ²X»ØÝs™îþòÐ=³g— ‰*¹âªÄ]5{fÏé3Óßíÿý¿¯ç¨¯?ó Î9FGG¡V­‚R¥@)µáÐJAù¾F¡ü<­ß2·˜¯@xO«ðÿßr}žeY–‘¯yN–e¤iŠò}Ëêõ:Q¡”BD‘òs¥wÞy'zË+ü4þQà]FŸ5÷ÿÉ‹/½ôÒ7jµÚõ(ÒãÕj-«Ä@ ÄPqYœ`>‹ØÞ8o çjàÿòzëçÆLžûWc‘Šˆ,cÆ~øáßÚ,Ðæxÿ™ h6šÌÎ̾çàÁƒŒS¯Õ¥P– ¸ñà­€ÆO›?zzKTJ¡µyž‘¦ë ØëõxõÕWß*M¼Ñh¼}XkqÖbr@4´E¡QÚ/Ä/Êgÿ¿FE ­<ÊêH¡#M¤4:R t¡9Ðá•ð…+¨ãÖ£’T¨$2¡ÕÚíÖÚ A[X~dxcÌ-3Ä[ÇqSM<þç/ü7ó˜J¬ÐZ£"Æ •.«‰hñëÿåÀ… ëâþNˆ_¤ uÎA8ë‡sâ )‚BQÄE«Õg¦©øƒþk}­J‹×™'7æm ^*@ëˆ(Šˆÿb:4ÉèÃï£JމbœòžP‰5@¬€°g ÆZòÔ‘ö &·¸Ü` N‚m½bµ".(Â9/¼“RA(Q8q$ZS«Æ\¹z“o¼ú Gg.Q×k­-­?11Q*÷çS€RhqPÓý¼OfSî«kªÊë‰+œê*åТ1Þ s‹Ís"cÁXŒ³hWåQâ=ç — *뤼ð¦H+’Ц×îqâÇ—8{þ ¶Ýf|o³S¬õJššDDÞ¶ÛoP€Ò¥5±Öå…;¹%V¯ß6J5O©×+ôâ*ß?µDŒ ˆ±8c±Ö#`C2uÞœÁºëî-Î[,î¼µÄ (A‰¦ZMÈrÃÙ7®qþ¹14ê,AëÜÏ +5.gfzÛÏmõ =°Åï[©É¸tu‰é*ìÜuÕf—;úÇ®YH”·œs gg bκÒÊ^(…Ž"¼×‡xG!pο¿x¥"âHqyq™¹ùkt:=’$"I46Ë|h 8ñnïœ0»m¦ [Sã[yH¬Cu.‘1=R¥ýæyÎ]["Í {ïØIU×[}*€Ë,.3Þe‚ûzkú8ëPÎáDg„C÷ßMwr!³ÖIRÞ@¬A¬·4ΧJQ %Í0iÆáœA‹‚("ŠÖK7[Ü\í‚RT“%…iÖªõpZ—ç†øÃ¿–e™·dS«Õ¸téçÎchhˆûî»!MÓò{I’°¸¸ø€W€Òžˆè(`€(úí—³™ÙGóöwâœâ”3Ô’É*‰|´[/ 3›æ¸^iŽëg“ƒ éO)\µ‚$Écœ18ãhß챺ÜÂC(q˜ŽEYë½ëCË\ÚU/KKK„›™™¡^¯óÍo~“#GŽEý~ V«««­ðål{O²Ö±r³…T=Õ&nÖ‘$&®Vѱše­'<(´ÒH¬qT(‚$‚J„ô5¦“âz}œ±8ç'R¤íNJfÑpƒ@b\ž#&…Ô"yŠÍ ô{(WÅŠ ¡&4›MârÝ–µµ5FGGùö·¿ÍÝwß½!$ Êuh…Ö µOƒ*Öä:a­ñx£Çn™É)¾7‘çF÷ÐÐEžÂ"Ê#|n=Ú›çD+¨W×ëcR‹íçô{)¹õuCRÑà@ŒAŒcA¬'`I‡†(&Êz÷Cm@0ðÀB°AkµZÿ%é‚rÞôi0"R°Ä .ªÐ2ï;zˆ©Õkìý•‡hþí1þêø³Í*±óq‰  —[\nãÓ”Ë ’œÍÀ:œµdýœ¬Ÿá²mðY$€"AœElîÙ ÉC*5>”â'ë©sÀ²ƒJ(²‚snÃçÅx‹Š(@P´¦¯brg餎©J:N‘[°hO^òã3ƒË .5ØåyvçãßZ‹²Æ¿ç JÄ:¬Û—Øbrë­* %:Ž@U‘8Æé Œ?ü5 d}À•<`+÷.0 °þæ9[bÀzÄa(c©E|â+?ä± ËD:â[/¥a-Òíc•&ä·"Æ¡­wS±ˆµ>ŽYo¢iT‡ÚÀ+BðŠÄZ6¹A²g2œÍ›ƒ Ê,CÀm°ü 7À·9¶ jþ5#ï+4* ?<{•ÿýÒy°@£ÆmÓÃH–ã´çíþ³PÙyÎk<%öe­Å·"PÚÇwèCÁHƒÕa^P”Ž|—ÙOí½Ç–°Þ¨Œó åÞRÌÙ2”ÖD¡DðU]j¨Ëðh“™‰&wÌNrìÂUŒs$qDYùTX¼¼5ñ•‚*+$òåqÉǰ&”Ö³Á“ÄÙÐp(±…ÄëDH mòÂx…ƒV/¼¡ð8Ž7ÔqуSá"J)L?e±Óåsð>~ï•“÷ÿ³Os½ß#iÔ ïGrð@(àB‹U”B h)ê^èg$áóp”Ö }Ô@< Ý^¯T€s®ìt:úý>yž—l±É¢­ QJC\x€ò€ÓésûÔðwɺ]ŒqØ8L°ÀdÖ*ëtµR[A>>.æ®Yô0PhÁ¸®íœÇ„‚öçÅg…Õ‰QP€oá•ëýú)íNZN¼b Í JBáCˆYQþûªX³°Qøõ—÷õéÐßλ·¢PœòlAT! ”×ñŸy~ ` $Ö‘~PØÍŸo.‹c'¾=U¸› ͨ4#Þÿˉ¯Ï["ÙBýÚcVÑôÔA@ X)[å….üÂCÛ\B–pný(š'Îæ-=A«õðÁA5o•‹÷-^|V* ¼QàØJkˆØ®¢bÁçŽ]à¿|ãuúÆR©F(â¾´„  çù@a!³ Šý¯))Yà9ƒØÉ3$Ïq6ljóL17`snÀímÈ4·æƒXŒ(Š6€fì•­&¥ Q'n68ø[Ìõ¶áÚj›F³ÎÈhjµZ¦ r~ÁçOˆ¬óî ⛪¾âRÆ`(œÄáõ׈8RÊ8Dû¾Báu[¥¶­6@•b­/°¬µ4 ’‚ôqá‚E«IÇ1$†Fš\ît%aûö)¢8"Šãr×'5À9ßU:‰!öís”o~ø/9Tð8±ÁºY†ÍIS\–"v½Pt’é†,QãŠN0²¡"ÜÊÓßàùàˆK-¹¨mz-ñ.¬cœæ‚eÝ@Fåµ.ãÖYA;O€”s¬·s‹|Â#© q‚Ä1§Ø4“bò>.Í<Ãd¬­aòÙu—ûƒ!0ØôΩøi!R*À‰`Š223¥Ð‹‘X£#Ò¥#¿#v†Ð¾Á!¥´ÓžÁ%U‰×w… `m˜o=”Ø/HHq ï™Úu»Ø~ÕíÒo{¢”‡,6Å÷`eXŒ" ©q mP"t:~ËiÛöYÞÿ»3Ú»B± ß6Ã÷óðħ`®DaKL+ïúJ‡t¢Ë ­p\¿è;ë+GçÔ…¬"QðÐ8uNèåš™Õçé¶Û!< Û`… …å·²úVíóØ9ÁXG«ë5ûëÜÍã{ˆ•§µNÛPÁûE "ð€ M'¡ÕMé–%Ý—‚ì„ %ñ±ž|;IJ?ëÐSQ.åü¢}u¡•&5C¥R]ß~#x?N¼;* ·Ž´×£ŸöqÖ‘›œ<ϱ¶°€* a­#ŠCœÃàC^¡eP~_²°þ WØÀŸÿþó;vìóßî¹,Ò:Jª5DZhü^A’$$I¥ì·Z«€âÆëôº=./,°¸xÕ®®¬tšÍæ£Ýnï>} ͈•$yÊ;7³}{m||LOOM319ÒšF£ŽBãœ/d²<'Ë3²^еc-YšJžçý‡~èßo&@NçR†ø%Áû6¦É·x@’$<òÈ#ÿRœ0:2ÄÐØ8CÍ&õZj­J½^§ÙbÛôÔÛ1ô}áøiã+À—ß8ÿÆ-'œ<}š~¯G¯×£Õi±²´B·Û¥×ëÑív9wöôŸ>þØct:M$È!®ï†Àù]£¢×±™'@è ýÄZ­ÆÄä$ûöÞõÓ„Ðá¨Õp¾ôè£þÚ /¼°¡ü,†1†ééivîÜùÄóÏ?ÿe`È,¼–«»gß¾ ß}æ™obŒ¡Ûí–¨¯J^èö˜ŒÞm¿„©æhÝn¯ýivíÚÅþýûoÍÁBY¿+á „váuØEÑíwÜqÇäwÜQ}íµ×¨Õjþz›jðJ¥ÂÞuòäɾ²²b€9`èà»qHÃQæ³G}OýÕ_sÿ¡ÃT"ÅŸüɧ0äl8‡êgpxjlɹ±õŸfø#>töÜ܇¾ò_ê~âÿñ_‰ÈŸüéç>G§ÝæÊåúý>ÎYV{ـŰÈó1pάg¦Y–ÑjµËjp3ÄE^õ6diúÁ¥¥¥¶Z-ÛívµˆÔþðc(÷¼ï~èw’þñÿÐøÐï|è‹_ø³?ûXR­æ—/_î÷º]scéF¥Ûíž±Îýž F©-:>JA5W.AÝ"‘Bå·.„b œÇü©ßþí`%*z…aÔk #ÃC´Z->úÑ[’š8ŽIßï⸬-¬µŒŒŒe•J…n¯K¤#ú½õFƒN§C­V£^¯ãDØ{×]üÑ“On•IÞõ—ùÔËZéÏ¿ÚÐú.û‚I…¡ÅsÄÙ6ëòRøÁùÅÐíö*íö*««7Y¾yãS¹8þ<íN›,˘Ÿ“Å«WùþóÏcŒaáêU@£uD«Õ¢ÙâÊÂPš‹—.ÑívY^^f~~k-óóóD:bnnŽj¥ÊÂâ"I¥Bš¦Xc¨Õj\¼t‰v»Í³Ï>‹É ËËË,.^cee…µ5¿¯"õäó/¾à¾ië»´°ª‚9‰HQës¶¢Áñ~ôN„<˸çž{ž¨7ê\ºx‘¿ùêßðî_}7K‹7˜¿ø&÷Ý{/gΜAœãìÙ³ÌÎÎ’eív›Ý»w3waŽÅ«‹œ;wŽ]»vqùòe†G‡¹té×o\ç»ÞÁ¹¹sÜuç]¼öÚkìÚ½‹¥å%”(ÆÇÇyóÍ7¹÷Þ{yýìëDZqñÒe¦&&@C»ÓåïÿZc¨hßo.nÊs‰XÊκýˆÓ?³Òqú[¯×›‘Ö¬¬®2>>ŽXáÔéÓ}÷QŽ?Ρà굫LLL0>>Îõ¥ë<øàƒœyý z³çβwï^–——‰ã˜·íäÒ¥K>t˜SgNqèCœ:uŠ;ï¼q¥<ÈÙ7ÎrôÈQNœ8Á÷?@»×e||œ™íÛcee€á‘aò4}W±øÁMïÞB§Ýã±ÇgvfÆ{XH}vSÚ,0ÐFN†††¸ysÙ?ùá÷¼‡<ÿyäN¾v’·í sn²wï^Nœ8ÁáC‡ù»cÇ;ßùN.^¼Èôô4Fƒù7ç9pà'ŽŸàðáÜ9s†{ï½—ÅÅEâJÌÌÌ §OŸæáæÕŸ¼ÊC=Ä™3g˜› ßï³°°ÀÈÐng…á¡!¢8ú§… òŒB!Y–q÷Þ}ÔëÍr“¤ÈýÅ|5£uœÄDID”Dw5êþ!ãå¥FFF¨ÕëìØ±ƒn¿K§Ó!Žcn.ßdxx˜+W®0Üæúõë%€®­®‘Tn,Ý`tt”+ W¨×ë,-/•¿ôXYY¡V«±pyÑÑQ®.^¥R©”Ïû °°°ÀðÐ0óóó¤iŠF³²¶B³9„F˜˜˜`bb‚ÉÉI&&&رc·ß~;“““T«FFFؾ};»víbff¦œ?66F£Ñ(»¢qÅh.rµz4Ëév»LÏLÒï÷i6›ÜvÛm¬¬®03=ÃõåëLMOQ©VÐJ311A·Ûe玴Z-&''Y¸²@³Ñ¤Qke3³3´Ú-&&'h·ÛÌÎβ|s™$I¦Ûï2>6N§ÓaÛÌ6––—رcI%ñµH£ÎâÕEÆ'ÇÝÛj­\|ùå—üì³ß{§sÞº###4 nܸA«ÕBkÍo¼A’$¬¬¬Ðï÷ɲŒ}ûöqìØ±• Gœ£ßO§ªIB?MétÛlfÈs¯ŒûðòË/ƒÀ̶N:ŇàÅ^äÈÑ#¼ð 8x€Å«‹\[¼ÆîÝ»9ùÚI~ùÁ_æÙï=Ë‘#G8~ü8;wî¤ÑhpùòeöïÛÏ‹/¾È¯¾ûÝ<ûÜßòЃqáÂÆÆÇ˜žžfîÂ÷ß?QÑhquñ*·íØÁÄøÄøg>óé#O=õ×w---•±<11ÁÔÔ;vì`ff†n·Ëw¾ó¹qãÅãt;wîüÀˆWo.c­¥×ë™±‰ Úíyš262ŠÒšãÇŽsôŸeeu…={öpåÊFGGé÷û „(ñ}¹^§ÃP£IÇdYÆî=»Iû}>„û™O¨mÛ¶ÍŽ  UëµZ³V¯7†‡‡šCCÃõF7ªµj3I’ZEÍ(Š*‘Ö5Eu¥T¤#•(T¬”ŽÂâBã܉FDœ16ÏM–õ{Yžç™IûYÏX×3yÖÊÒ´“åy·Óé¶³,½bŒ9EQ{}³õïgÄå³AQDÇTÖ7¥^¯/h­¾öµ¯Ñn·Éó<çêu©‰HÝ9W#4JD¤†oœTñ.˜@±%\H9¼•,)¥2­É@÷¤ZëJ¥JÑÕúJ©  V«166ÆäääߟØQøµÖº†‹:¾ßïí(ÛëõÚ"Ò¼ÈVEÆÏ7V7ð®RÔëõòk-Õjõ¼×Æÿ¬ ›?Ùª±ø‹õç…6Á6–1æ-åì/:Þv@ݪ¡ðkü´ý½_düão‡ÿ¡ð=þ"؆oßü·¼IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/mymac.png000066400000000000000000000136701217176075400230320ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœå›]Ìf×u×kï}Îóõ~Ì;36ibpÚb;Á8N"#zÛ!Œ€¤ª U•"!åB„Ô$R¨¡W€()®H+… ’&棔‹Rˆǵ™wfÞÏç㜽Öâbïó¼Ï;ž;1liÏsž÷œçœ³þëë¿ÖÞ#îÎÿÏ#Ýî×ö÷ŸJ±ùI ²î %GwÁA§áâx¨‚ˆ£H¹–z#€ãñDË%¦†‹» õ‘"@·òÕËWu·PN»»„ò*‚bDÀË„PßÜ \åø¿Î9ÿþ•+÷œ ëîçæ«ß¿ú±¾ïoøÛ0üóŸûœÞÀïlyä~ç¡KN—áÒ(°ƒò‰ðݡ˰3VŸ8ó,¨+óÌ;c¥Æ~o/–t£»NÎJÆé:XF#ˆ‘µ'9,™pj‚è)Y3¢=½±Ïhp0%â˜:s5úyd¼·ÇïóßðË]w{«8ÿÕm8šŽ\Þá‘ËSºU†qâd—v'ÄX\AJ0 A Ä*¸H Æú]Ò:q4A²¬õn·¸À¹®ðº š(ìM&\CŠ¥}¼ è7rÑ~“`ÞÃ|åô.L˾˜û*+Ù‘µ³š Ë…Óç>“šÈÎ…š`lM}×1 AJí?ø¼®e )š¶h:RgiÒÆ )S Ɔä’Æj1ävg0ÖÔ2ܳ™ŠÐãÓs…Ó–Vм/çhi0m½Ze…Zh±”:@MÉ9v×÷ì^¼Àd{L¯Ê´Ì& š;vfSRŒÕ6Òž €”8š†BL€a¦X€4ÂÁÂë[€ a(ð'£–{w 4ìÆ‹nfX® Ý>ì`¥5 Ø?é7¤˜½–ÎÏP—V­êÚ Œiš€4 óŽÙxDÓ$ÔŒímRŠçÜjê“âÉâÅÿCJĦ%5‰&EÚib¢I-)ÌúÚ ½µés«àîÕD&#gkVZÔÓ(Œ)Ü<…®3aé…‚yáᇋL›"ê‡NOíÆ¸€ªb’ ÙâðpÉbeì]œ°T8^¬ØÝž£ÐåžédJŒ±6Nj´%ÇÇP€Ž5úlj͈8›¦!eDLin ‚ç¨åt9áB ‰¦{Æ¥œ½6‡ƒSÇ´!“¡VR[”À²7½¥øýº[7p~¤ÙÆúŽÕò”W®Ò4‘{¯ls¼ÌÌ—=[[3b(¡m[B H¤»€bæÃL1%Í·R;&´cÆ8Þ9ëø¿n,ÇQõÌå´×:¸z ‹r†ù¢”£!Á"— q™ó®p|¤Ÿ¡ÈW¤ÙBMèû]­8=:æÕks.ìM¸ty—Ç'ôY͈ٚ©›ÙK~/¯ ÃyÒpHmËh<‚i¢ÝNëNP¾Ån­e@Ê<0‰ÂÅV^8ÿÁ¼ôí—&ô*4 ¤þÔ0eÝì4„E]N+"î„4%{"÷+rîjG§çúþ£Qâ¾{wY,–\ßßgow‡ñxŒÈ Üè³í¯ó}$¦Pf*3•^EC$…é¸Y+>è],w¢¤ŠòÀ^ |ç^9„ÓÞèz8]AîK‰m±øæbUþÐ[étÙèÕ"¸ê‰ÎZrבsW‰NFs&/ç|ÿû7YöÆ^f4Ùfÿú Dª™Ñx̨-åì l¨.Q4ŸÊ¬Ù ‘¶‰„¸bjÐÊ´’HÇïê~F†váGfÆM…?؇㥓{ådåô}YÜ\B4+uV•©©„>—Fa #rîÈy Úc¹¬ïyîÉ«ŽùÑ!/¿r@;Šüè;ï'ÆžœÐ4-óÓf“ M `FJ&5…ó×À˜R"4…‚·!ÐFgšöÆÂt{‰Ô>¢é]×ÎÚÌÓiâ`•øÖ!¼p «NðXt‚˜[A¬tÃl2áû+¦#á`îiÀ:#ºpÜ5œ,çx¿ÂûžN3æŠPº'œØg_Þg&¼ëÝ.¾ó]|û~›yg-GûÇ\ÜÛåôô&q™MÆÄ$ô&$ XÓÐx (ˤKξ ‹¼C¦d‚[–nÓs_Gîç_¼Êþb‚Ï•©«,L¥¶¼Ì !‘•vÒð`0¤ëödŸÏä`ôIÙ¹8Z ÒáÁQïX™‘ <(BÂ$ÐÆSâõL³{?ïÞiÙzpÄë7ØÚqpýˆ)ÂC÷L8=>f2‚í鸴½YFÊHB©AÄðè—Š¿ xû˜“ùœÙîÆYçö¼ø½?ø•‹{»½ GûL›Ê±Da]¨Ÿ›™%œõ"KŸÎb¡Â"ˆ7'•ŽÖÔN"u' VÚÊœ@Äë,?ª­zìu Y!ãJŸpè b9¶–Óå Sggg{M^Ó†BVDBY—ƒÚûÞè—e.¯²ŸÕ‘Ž×Šº~“º›ˆ®X˜t…ÅÅ’Ïoìß G¶¦[ô¹+¥¬àuóQFÈ¥¹áB:@„’qζ;h¡ó!Ô7“ÒS2¯ït—jÐ6ç)¨ßñhzóÜ9#óÛÏÝŠ«¯|o"z}Áøá?TNÖÀ?ܬ}¸œÝðœU Ô¾9¥wP\Ö­ó;0~ëE?è‘R`ÿú1‡GŒGcRLš óîô5>úƒCl;÷.篨MŠ&*Ù¸Tr‡ónÐŽÒ€Û[·Å²*ídÂ… ¨e&“iXÃ{{å¿•¼ P×éî»ç…@YB»•¤üpÆÝ–Æx{,`«œ‡fíÿ³q€®ïcYаuÖ«Ew×¾á3oü§¦=¿ëßÌJ·f}5Õ®©Âú½Î-çã‡ß™ŒGÌ&²êÙjK({¯Á+!)w­;<ÜÏ1„ÍñzÂK}ÇÍØ7° ^Ÿá`¥?^ž±Ò®ÂR4)‹9\œ3Á¬ôSŠÜ<8ê7÷ Ÿ «þ«—_¹ú̽W.}t{kÓÚÀ¤Ä‡ä±¬Ì!¤/]ŸªdØÄlNˆ‚©‚ãZ_¬2EFȂĺ©-BÝ…&fËŠ”ÇpF€BYr‚"8šµ°? I«»BÊÐ ½”ø2Ïãúõ\½vã_<üîw}«¿ýÏ]Qµ/ºÛO-V6µMÙ`\Üq!ˆ{F$zJ‰QÓ0ÙÚâðèX†ÍJçŒÀ©Ûá\Ìm£%U¬ç̻ֆ½±Â‡õü[¼Ä‡},."2j’-– r6Ú¨““ÌÍý›¶sù“*QþÖGž|r~G†ñµß~ŒbH=âæîæ¨ïn_æþû.côýÃCYžžú§?õI¾ûÒ‹^¿‰¤&FÄ\2Ò©ê}ô}ïù«íoüçïýïï–ï½b½‘)›Mí;2ë·ŽÉÖ^þâ?÷ k^üÚ?ûõ_rwùô/|ü³âQˆŽxmÓØ{Þóžð>þ3ñ<ö~Ç`ww‹£ƒc²•¥W¢»GW;F8D„?ùÄí]`s|ä©?~p§sÃØÙÙà«_ýêmÏ‹ˆ¸»?üð»ûw¾ãܼvØr_Öý{íéV¹ìkc©#&B@ØÛÛ“Ó“SŸŸž‹Èß>Sýk5&R¬å“ŸüO}ø£üØý8“qÃ|±Ä•õA^ï¼Mîu†œí5*Œ°ñ)«ÐIDŸúÐS]¹r™yÇCˆ@§Ýz+B ‚„DÓFbhHð/\Œ?þØ£"òŸ€°TD2¥4³éfêÏ>û,Ï>û¬?ù¡ó±?ÿ1žüðG­“û’kKsö¼o€[„‚§:Û:»Ç?øøÃ“qË}÷\ÁÓù˪Ž#ÔEÞ²pY{ÓÙ”­ÉÖ/T0[ÊÎüŽÂú  ̪Ɗo~ãëþÜ7¾Îû{”ðËŸåûdµZ•w[}ÃRŸ×~¨3m¼è×9zü±ÇF\ºçÒkúЯ©NêØÞÙá‘䱯üÖ¿ÿzÏ9°¬sUŸÙoüä\ßÛßýo¿ËŸ{æ>õW>ÍÇægµ-‹åâ¼,o†õÉúÿóœÓú ü˜ÔOÿÈG?òÄ¿ûßø‡Ó-íú³2öu;øÎ·¿óÊOüÄŸü¥—^zé%жO+‹ú¹ª ÖpVßò„÷¿ÿQ~ò§~š?öÄü™?ý§Þ2ƒ¿Âoj}VˆO?ýôGÿñ?ùµ¿yÿý÷Ý»\®^³EínÃÝÙšÍøæsÏ=ÿ—?ù‰_}þùçbú§ÀIý\T·bÃí*_¶·w8::<“å-9À õ4›ÍîùùŸÿ…Ÿû¹¿ô¶mÚf>ŸßånwÛÛÛìïïýê?úâ¿üÒ—¾ôoÁ)npÌ™5 –°á lÊüƒ ¡h´ï}ï{ßû™¿÷÷?óø>ðøÉñ19gÊåëÇß¾ä•óëvI§mGL&~ó7¿ò?ówÿÎç_}õÕ)p;+ø¿à­fÜ}õÌ3öO}èÉÇ»®ãÂîMÓ2™LH)ž­ëÅXú~u•×Ü+íV²*š3jF·Zqóæ''Gì_»Êì£O?ýôÿò—¿ülŒQÜýlÉ›o €­­-zè!Ú¶e4¹ˆ¸ˆhÎ9=÷µ¯}­G"H‹È(„ÐÔÙÆSŒ1…ÂKܾϞsvUÕœ³æœ³ªö«Õª_,«årÙ眵mÛÿõÁ~Pš¦é v…¥®V+ú¾g>ŸóÒK/‘ó«³ß” |á _÷ÝwŸäœË¡›ÂÈÝ'}ß'U»À®»ï;À®ˆlSwŸPܦá,1…è,Ý}B˜»û1p$"‡"r¦”–1Æ•»ŸˆÈÂÌ–fÖ›YŽ1êÎÎŽ>÷ÜsþùÏÞcŒ¯yw€7n¼5nܸ!³Ù,,‹Bˆ1ÆFDwUá¦"2‘-wŸÛÃß(±bäî#I¨»+%˜­€…ˆÌÝ}N‰úÇÀiý>1Æeι:Uµ”’N&?>>ö^xÁSº½?úè£o †~ƒ{؈ ¯%BCfŽÇõ\[¯Ý ¬”@ÖU–” ·9"tޏ»ŠÈfú{C‚½YàŒoRá` Ÿíƹ!‹l’ƒÌ ‚ ÔwµqÜñZò³® ê}Þ°Po8Â&3Üc”Äwˆ¿^zdlàüù–y;ÁïH~î6þµõ€Jè(ùIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/parallels.png000077500000000000000000000513251217176075400237050ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½y´%G}çù‰ˆÌ¼ÛÛ«^­ZJ%!¤*¬Œ§)›Å€Át„¡ÇØ=3¸ûû´»í>Ãl¥š™cÓnÓn{|ºmŸÁ6no-1í ŸÆÆ6ƒA a(Ih«MUõªÞ~ï»KfÆ2DĽyï{%¡*ùØ3&NeÝwófFFü~ßßK çß*‹üÛnÀ·Êßnùþž—oàïyùþž—oàïyIþ&*½ç1ÖÑ£ˆÅEDõ÷åeÜÉ“¸ñ{œý›hËßõR¥À±cÛ…r’^/&­Ä‹ÆŽ;†\\DÎÌÜ«jµËJ)#“$U”NëÒ8×rEaLQüˆív±ËËØ±Žž€{Üÿ¿@q’ãþï(‹‹ÈV ™­¾Cf-©Òr-AîbnM¸‡M®¯Sôm>³Ç´Û÷™åeìý÷cáÚÁp͸ç!C<ˆšžþ·I£ÑÊÔ ÍT–Õ¤Jj”i*¤MVB ÎX—”%.ÑÎYmu·°Z”¦N©uOçy]GP<ú(&âÿ«" ÆÑ£ˆ#GP­ed6ýAY›9›$õéD•*•YžJÛȄʄ+kÂÉiÎ'•v†Õ.m‘ä†27I§ègEÑé|JŸ?¹ÿ~ìÕÒçªèЯ%ÓÓIV«¹zbÔ”´õi¥–^%Ü—ûëw"˜ þ9zˆ;–à-9qÝ_Z;ýˆµÙ²KäÀêvnòn^ÔÒ"ÏëºÛý;êŸýw Umxð ªÕþ ªÍt“ÌnfJ,Ôd]Õ„›ªK¹±(9ûražxnõU˜b/ކpãfÀEÒF-~Õ‰Wþ†InúеŽ.åVnŸtÒÛ‹Ó§?¦¯/÷Ü#äÑ£ˆ»îúµtnn£žé½M%ĬÊG¤ýó ~óÕ8@|’y#*gÀ–à,˜Ó`/€ý ˜ÐQI¸ãÜ»þ«•7~ÒèÚ³NmõLazÐÉ»ÉBþw Û˜Þú jé­Zbçj S"k*Ù¹^Ú'¿ûàÛ°ùaaÈïŠgï„ôvÈî‚45ë+6(Ö`ðW0øE(NÍ>d“c?mÜÌ£fPnƒÇzw¾¼ü±òäIÜ7K—oBqü8âî»'‹‹‹Y³Yk¥®9ŸØÁ‚Ÿÿˆ0_‡ÒÏCí­¡Äï\aå7;sôy(? æXp‚ñp|ÇGœùª•å–Ém¯H·úý~¿\_?¡£™øÛBˆ#GPóƒ&­ÅÀtéšR¶¦”=§°Ÿÿ0g§ÑíPû4^ µWC¶À¸›üep6?›?%¸zíY§Þò¯´Xx¸´kë½~»»üègŠûN¢OœÀ¹çað7€ØÉ;ïüùdÏžf«æÜ¬’µ}Êüñ/sï·¡€Æ3P;äop¹—xǨsÎŽB( Ž@á,”ç`ð è»AƒƒzçW\òúoÜÌÃ&·íÝ¢Û):é‰âôi®J^m™@’éòG³ ji*[2iÎ(wùeÂ|â_ /½J Ðø_aêÍи ’Ú¨"§ÁôA…6°•¿?T äÌèÞÍOÂÅ·ƒWk>hÒwÿ˜ÉK¹>¹y9»¡ûÕ¯~R?ŸpøŸ½ù׬5u¶Õ)»Ýþ??ø›B•ñs| žÉ©¦Rµ)iÕ~åþò¿Gñ=ÂRGSÿ¦Þõ[F¤°[`»A8( (O+‰]h Â§ó€Aƒh@Àpù?ÁÅà¬k¼õŸj›}¹ìõWÖ{s/>{_ñ\ xNDæ¿þõÇk³ÉâL û’ôÒûDñü$êÂüý¡c}ß!Ó .Øz‡§aïຄ!&|8;ºG¨`N2_Eþô> Å?÷U«;¾fÅ÷þï†Æã&ÝØ(¶Š^ç¢ÌŸÎ®|±€Íß±cÈ[§?˜5wåY&§šÊÕçÝÛ¥û½ÿMèKwà€úOÀÜ÷CóÕ¾[¦³6÷ýÌ–Ê÷Ó:<ª O¯!Í… GÍI ¯- ˜d’Y(-<™øª¯ø°æÖÿ\–§—6çmûóŸ(¿®€*óçts.mÖ÷+÷ø‹ò?¾ŸÆïÂÜ{ý…¦$¾³º×ðíGVD?>^ØÑ÷ˆl¥6øò—yANÑ•èp×]¤s| ž•3SIMÍ*±u§ÐÿÏO ½~3¿ óVCyÙ3éCÄþfÛÜ„þ;<(ÆÙS1‹&Q‚Ì ™Ñô4±}¨ô·<ýÏaí—qS‡ËÈ;~®ì¹¸áäÆçŸy(?ù^ÜdneG!Ľ÷"½ä3“™éƒJ>ó£¢ø`êã0÷}Þ;Åx†Ù.˜ãvkRßW4nto A-šÑ­" È—^8ç‰+ ЀlÑ?²óçÐ~³§­š{Ö¥ø—ZÛ“š|}Pt»KÅo ^¨³Xuîöeï¯7LmJ5Zs‰èúãÿNä›×‘ Óïô]./Û ýÊBWµ§•E½eèóàð ÙHŸh+¢íİžÙ‘_N{š¤s>bpÆ Nº§–>‚›ºå×Mzø “Ÿß|f«ýùÿôPþÞû°UÇpGÜs?ôCÈv›Ý3Ym÷~¥Vß!‹Ÿý?™ú,ü· ;¡“9”›!UU½Ø¼}{–«"HzüZ½?" ¾Aží¼zU ÔAOЭ?ƒÕ·x d³'­øþiœ=]³Þ핽óú7‹?ú#ÌsyÇQÝ¿ó¨ƒÉ?ÉZÍ´™)5¯„<$Ëßú9¡»GH€Ý3ï4§½T‹ÌƒÕp=ß>W„~‹`"Hp/ ‚p# ‚¡"4.˜ÃxZ22"…tTËó"=Oþ3¸ü+Ø™ð?9÷ÇE{éâJñpû×裡 Á6ÜswßMrÝÌ7UOvíMŒü6Y~ø7¨ýkØÿaÐÝ€ö •…9ôî©ð˜²•ðOT™ÑBa‚ÄHpe¨ÓúÓ€´áo±Áƒ®ÝÔaã^Xy¿dúm¿aä¿ ÅærÑßܺœÉ+zÇ£hç­ÉžÂ¶²ÆìTâš‹Ê}íÇEþÕ÷°øQ˜ÿa  ƒS¾=*óŸ&’=z9îÀyŠ{çÏY¼äWâa¥_øû¢pˆp™µ Ã'AÚpõæ$™†ÚÞ@‹ýðÕ×A÷ló ?¨Eÿ¡Á`kéÙ™G·î»û¾ ÷ß/’—7ÞÚlÍß´;©Ï–úÃ(4 ^bCg ò%Ï;PEk@¦ ˆ¶ .h!*ÒMAÔA#X@…¿ &ÀŒBDµÁ ª{bšÜ·'»ÕKà…Cû#¸„«Ïè¼ù`Ù¬NÆÊÇ#î>J²xä Y³1ÓJM}Wb¶^#ÊÿúDNÅŸ„½•ÂàÞ©š«éûc¨µC©ÓpÒ3С åÃÍ2à\E:EîËŠp棘õæ^CÖ÷A2ïÏJ\Bßfoü^Íæ3Ý••Gxªwìï¨mÀ¹/¼®±0wó\–Lߨä韽O¾›Ã§ y#”«Ÿ JƒÍv#äV4ÚHÝ»³Çì?¡ñUÓ:',hâF‰õDM‚©XY‡¤Ô@ô}˜”Ý[Âù¸úâ§x݇L±y)Oóv»ýÅþÓ9%ÀÍ5Ò^Û¨5j3*›Ý«Ì_ý´ÈW¾“¸ñ¯ õ*èÍKÔ}[Ë.¸Ü·O¨Š,„6‹ÈÍÀ¬Øçaz†á~ç%{ Qß‹Êù `FŒ¢ ©‚€þ¹é"L¿ Vî‡/}naß}ÆÜüï »zfíÒÖÆõwŸëï€ÍϽc¾>ßÜŸd­;eÿ׋ٟ€~ôôOyéV©o„›Hõ9*ßc\/‚ú®:|‘yš‘§«G´ÁÁ‰áæÃE• %M…ñçE Ò/¶ÉAPûáâ ¸üsA|Çë’‡Ëdc5ï5ûµ¦h¤:Ý•Hu‡0Ÿùu1 Æÿöÿ„WõúbpH7ƒ®j8zî’Qè*¨+y„טQúE4QÕGÓéü¹¡+Pˆ×L€HØ@5Ò(¨íéWÀCo„•Ocç^óºì<Õ|ãça‡ !ªÌg%ú:±õèkÙõcþ¹[ fh„0FŽp`ÝÈˈv¯b¯‡>— ŒW# ¼ÚPiüÛb9&:‰‘Ø‘ÀQ;èJ»6 ·ì£tzŸuÜþœúÄúg\5.¼U¨£ƒ,üi1p·3ÿÝpã/‚9í?÷6Õ9þÙ‰ -¼"‰œK9¾20 Ò ¢%üMÀPtÔrô·‰¿Çû˜´p­‹4­žïBç!X|x3âܧ^'Üu · ì ©‹¡—ÞE\÷Ó` èŸ1 *x·.2(Ú· òlpò„uÈP3€ˆ0|£‡¶ÏTœ$ãÃ% ˆ²Âôð\#F@Äç)†£ÅˆÈÅ*”ëÞ!rg@gpóÇàÂÏ ÎýÇÛeí+¿†tBhæ8üa˜/tþ‚QŽc=ØZ|ô¡+v[*0:´MW||Û‡Ò˜#T MЊ–ðû!+N2ɯ†ˆPñY“0|^4· è6l= 7ÿ,<õ DïÙwÉÚÞ3ñÊmVî¢ûµ·Ó¸ j Xû”¯PPFÄF5,ƒÊ¤b“+¶YIÐÁ'%Øà°ˆ:¨™:õ½]Õ¥' € è¶nš1¢:ÏlëÇE{,c›,äg¼4§{ óiXüa¨F<ù“ó4öCý\þh¼ÊW£;Œ*ÔG³ Ì æ 6 LvΫÝaôµTppó45|6¯îûa7C{Õˆ¯?”}™2Ì0mMÅwÀ2Ò2Ú?¯ó5Øÿ˜9½ oêÀo]zë èº7ÿ3XþDÐjJ=ºÈ"¨DIE:©b$ÙV’:ÖzÛY_9 Å)èj ~ì>ß ÛñRkÚ^‰ b‡4Ï0âˆ!d41áÓ„ÿDâÁX´ý‘.‚y·Ã‘{áÌOÁæ<±7ß/ÿc/Ùå*¸,R1 EUÅV;çÕ³´¾"¦Á#Ó aq棔d²y¯Y÷QUþ¸ImÞæ\œ²l} [þÒÌ3ƒRú±AR‰šlʸñ}ˆ‡þ픘Êù=éÚÏßö1±öä»-¬üžïtLÓŽ!%ªç¥<ìí )ƒ ³AEJÙ.o“W~sö7¡½† Ñ GÍÝS/‡ÙW@z#ÐòLÓKÂíRQ·˜‘bì¨m"´-šúaÌA6ëRD߸ò'Gæe¿fÙDÒ`­ ¼@Äë„Æ#€@35 Ù~vÛ†ÁÓ°uÖ†î3Ð߀>£w*ƒ[¾|ÐkÂÞ¹:5¶êH«²xA+ˆ„QÉHF Ѽ þðõ¸¹Ý“ß·üC;àO¦rþ¥¼é,,ýnÚh{+EHšŠ]†0 !€T’]ûè¿A®nÂäÀ¨+H¬ ?‹§»œ¿ ö¾ZßÙuoB~l¿bµA„(ŠqæK”š >jsÁ¿™‚³¿í¯úû¤„#¿®ãC`—Œf59é«-$jäÏXãë©ï÷y‰ÞS°þl=[çB]Œ‚€ ½ê)Ô ° v䫿ÞùÓ ûžÉDf?"*¢Dßd¢(‚ö‘ ì}üþm8W<.ß_Ü;M ïõrà;=}tî‰5 ã*ÅTrC€8†ù걆ÌÀÊDZ'é`¹Ï^€­6…BC¢$I­Ó ˜mÂt j¸ü8œ#?†XXDîÿNØý-èöYI1& $EÉ—A[Œ™†¨ºƒó9X†¤çíïâ[½£×þ:Ø-xê„l ÄÀK% ¤ñÌGAYúªkû}ÜÝ}N}úÏøq-ƒÌ@£I¾6`y½¤³ë=ÈK0%Z ´µdäÍ{`oæ/þ/Ô«…ëÿèǶÓT ‚fžùcÑF(¥ Ây“ÀÜMðìׇ&`;´mмŠ Þ¶E‡p«ÅêÜp!¼5 ‚ Œ¶YÖàòoÀ7þgàËk`ûrýÀÔücû›¢[ k$ „P¥1Í¢]Ì?»Zìéäz6­“Î4aÏ,ìžÙY†‹÷b³{‘ûn‚~æ_Ý30xÆw02\È ™ñÌ¡¤r^K Eªî…×ÚA žý%ØÿýÞa‹Ž¥v#ÅS;Ù¬~ûÄg²ûn‡ù#pá1.?ñ/š?+§”ÚœiÕ.í­‹FKöŒ•kQUX7õøÓýÛžj™ù»öƒúë?rØû^oß«#…’ :!,uÒ 3ð •àz0s#è¯7¯Q¢ÈzÉÒ¹'š Ò5ÎýðÑ÷ вÃߣƒ—^¿ÎÿEywëÜî/Èi±b…锘žµº°Î:!E"¤Èê Uk¤ÍÚÞ)QC»f¯0 §Ïõ=Z¸Ù…ä¾Ý°§\<§ öNÁÍïƒù·ÀÖ×½·/ê#b93š¤S¨Žà †°SX°¹·£ª ¯õ÷uƒÎyà÷àÀ»f$Þ‡P5ØüöÔg‘éòÀÐ[fé?âÙÓ°™c[Ídsqºyz¡©Öa{8‘kLn°y!L!ŒÑ„v"“ˆæMsSËÖºÝñxûußyQ{üspÓ‡`ãa†ó.lp´UÈÄ4t9)¤ÁWpÒ;ñ.‡Ú^„©Š4>ƒf#ÇÆi˜ðFc€*üu&f+YÂÿÝ._<…»}ÏÞOYç.Y;¸¤Ñ«¤nÓh;p®t‰J õT¸Rµ´SR‰V&më@Ú|F¢šEiæÏžî½äÆíÚ³nØþ|áW°»yøP? ƒ‹à¾ãÒ…Ì ÁIŒí¶a@%Ã:;ðæeþÕ>ÙzÚ§@þ ì{[Éú°öiÌ¥G±½>jn?ýþ:§?õ§\X‚©iµºqîɃi²î0=cmÏ Û-µë ¥·œ1ÝR¹¾,ìÀ*´°F€¬’Y%Ü®D%›GöÌm}þìÆ›¿ëZ·3ò±¼ ±>Eǰr”|Ì{Pß5²ˆ;¼Óa]ˆÏïYË0ÌèáQ.>³ýðèoóÄyÍM»ÿiÏ8“Ÿ6B?+”¹dLÞ6šÂI\B®dº .ÕtÖM)©¦Óh;k¤™•©šÙ·»y^–²ÕÞʯð«Å­Ó3¤‡Âô@cû(rö&ØÿFP  WB›‚YÎ9¨„´Ã¹ AMè-hÙ‚ùWz­Ð>k@Ö„æ^̹/P\^Æ&uúÚréÌ“¶ß•í©æôùÛ_Ò8'”è–Öu´Ðm ›8³éœéé:F”[¥6=¬Ga F(„s6K…›±°W ±‘Údpóx|iã·ü-xýÿ ýg½Ê¯³‹óW\²q‡x˜´Ï€/ýJ†ð.d¸ =~]"BE!ÁáB¶.€á ؤf¦Ågò§-öIGñl¯¯W IP M{ÉCºï"ì;ƒFƒEŽÑÈvœ¤G'ƒF3=ÿ½¾t—ëgl>½¶TZwçÎ8aÏŠÂ-áìÊ —›"Ï»-Ã` )Ÿx½'Ç>ñ&ìÉ÷âNŒHV™œ)¼::z7Üö*ºMk×v9QÉj}ZtqjέÄ$VHFÅ|Œ•l€$dMuÈ6Êõ<\`¦2 óÑ †˜¨ÜÈ…OáQúϘҔ!Cè4 S²›Ù‘‚M!:Ý]ò“G&˜¿A'„¼×Ãþ8ˆ£w£9KùÚëÈ/ÌÐs%[å [J—Q¤j­—ìn,ð²ý«&Y×~¨¡ÜôÂ_\x‚¤Ü@|”íàà†Q¹8ŒSÚÕÙLÖ‚ÛòÓÎûP®hÎÜràÈæÙK_qÒžq…}fS»eÝ.7{ýmÊ/Î`xsò>Ü püÊŽý'»sNÁñ#è×Èk»Š®ª76• ³«&{ˆîÜØœKa Tx0Gí5áXü9ÓÇ*ä3ž êHFÿBˆWL\—‰vµ4¢6Û`¼®‰íÕŒíÓ¤X:Šæ½ÏMŒ*Qª_ƒ”¸ãÇÑ(^½;½l©tÚhòsrñõogf6Ú™zU_lÀÚ—`îv€Ë¨ÁAÝü½ eoD´¸þÅp‚‰ ÀÀ‚îAÒ€tž„ëg<2ØØ|Hë²#ûÝ »Rl)?ºsâİùîžçëäDïB¬ß‹¾QQÔJÕ7–‡1¡]¥Wã:2+´oçÅ€Éä¶{âu.Lû6!|JôøaÂP£­ Ó“+†áp©À¦‰(QB[á[|bGcõÍÈ9gOœÀýÑ~\ÑÇ)ÒhÕx¢ãkÞ°çÂÝË‘9Ÿ‘N}"`ã1(.Þì`žü}/éi†Gvè‹&O†PV™C0þ¼îB6 I‚jÕßRŸŸ»nj÷T6µw/Å1ì3ëØ0åÜ~3ß©DÚØ- Vë´!JÎGY¹<0š! \Xh'ÏTýyq¾ £¯ãÅâGÇažÃÖNâ~dX„ñ!•ÑQAX'…u7X¿:æO–w¾q[‹,f¶`êúoÈï®/•ÒdÂ'ÆŸ¥Y8è<ãG_‹NóôŸúŒ¡¬ù”¶‰ý‰šÀx¢ m 37h¨éÝjjw2¿05•¾4]<2©ƒ¯® Öq®À¹Z0ç<óõ¦¶´Á1ó-l@1q¹ï›Î}˜Ž²çÑàÕ”Ê ÉzâÒ¢K]¼ÆÇÊZ†vAZ‡õ³I:·^;ŽGðiáæ§ZYcÏúüÍ?ðÒüܾ> ÊYßü0D®Â!”çuï"”ç!ßèbNÿ Ôf‚ã%Ýx­gÓ£i°ACØAX– „~¥lοY·XWióàkÞªŽ¿vtnÅ1 X&Ì—³¹o£)!Ж J²GI¯2jÃp Þ„¸?ò脯T8¯ÜÄa /ù2HQx PŽ2‚7ͼÆ"„w%1Åt£^ºùõtß+^Ú<õ&Ý–(a‘QòÓ Âês¥üߪý0ÌŸ¯u0§? õ†3uœa4}ÍŽ>#°5ÐëИú‘p}ªfævïÑõcÇÁWyqJ‚óŽªk/µOÖÅE¤%žÖx~U[âMšö€I³±U¿³àM†³]Œö ¯CɳAõKBcª¾£Q©k,÷Þ‹ÔgH÷$ÍéÒÚ}éžýïžß¼Ü0YêÒÈø4¨T¹6 IDAT!®(K½o+¿À6_³ý¥eì坸1|‚št3gßT@™æ"ˆ¢³_Ö÷¼KJ±Xк¹öÚôÅо„ÑXð|ˆ“oÐaÜ¢ôêß–!gc¶ÖúYD2LDÙóhG] LÔ1rãGœÅ+‚ªwaæO~Çø¼ì0HquE!ŽœD-Ü8SK™·³7ÙÇ3wi!eîGtSéˆÊ' áÂUƒbÙÏÓè=sÊÏýÏf}_£V¢7Â.®‘Ò*¨¹ï–V_§;7ݨՎ{Ë«À«{Wa<A«øb“Z:.Ws¥I%Äõeg' >6zÈfæß'^¸Q€i‚Xç‹`Žƒ˜?@2Ek*Qv—Ûuø-ÍþrÝÕäp±PÞæË0dÕ¿#³ R”^Ú›°5€ü‰‡}¦l8l™_ùŒ×@ä·¹({¾K&f!³ióСyÿŘ¹4aTÖûïìèï8Ü»íÄ)ó*{ÁQˆh Ò-'¬WÿÊ1Z²¼ÿaØQÉ^£ BˆcÇ‘­©Ùš³jƦ3Ò¥»œE>ÜN@d#•ÿ™g¸ > Ó´“°´¹ÊRwÃ`/> µÃyi3ÿŽæÀo. ¶ð‚|Qi75=ÝÏî½÷îiû‚K¤aŽbÔ.‘{-+¬× nò¨úÆKjlâÐÎH´Æ_1œo¿C)Ë0æ®|ÚÑ„YB"Ú̇ PI:W“ع|ñ諃‡w(7\¡Á•ÒðD\z“~Ôè6Úâ™4‘ll™éú…¥Vsá GŒ+®MŒ›>ð’åBæ0oÜ;$²éۤȟÍÖÖ99B\u>`X¢¶!ÅöØžYÁ(l£õpZHGõø¼a  «~a*’ðª½zÀ(yce[z3ÃU°“ã/¼?Ž(Ôbª¤k:k泩éW‹¢‡ÅHµ«àí Kéq‡6HF)Ž^†]³©[£æÖj.}¬ÝÁ™•g ­œ_«GÒµžÚ-hƒÄ Ï&¢¾øZ¡Õ|RèÆÌÌ̋הч¶ C¼èõëL² ^bÜ_ADƒ†{•a8óuX¢DÄÜy0 àCH‹7/‚BˆuðÖ‰Þè´(ÜBMu#4RŸ½­^ïF¦-V¶ ¶Päîbæx:i±F&P5Ù”ò@oiýÀôžÍà啊CQ ¸êƒä—¡yËí‚bNÚV³9°éÑ£wBqÍZ2Äþqî‚Ñ W‰î5“Äù„Y ߯J¹² paq"HòD¤¨/‚ šBã¶MɾúRŸG$kÌ 1%fö]ŸØõÐ~Ój¿ÃãD Su_’ŒîVnÈùšlò¬«sQ¥‚$£×´é×Ú›ùÞÆ¥³*9p«ß‡HÀh¬=#ŽÄÝ?Ê ÷C²G¦´’b.9|ø™8‹óJ ½ þU쇌rBÂÎÄY?ÕÃÖÊZù|óÁ[ŠÏ6>Œ“•; F…1æØV7ò’£ø"ðÿ8ˆ®S…lÔšiÑÒ³oTú™ÌÊœ°×æhFT|^@uF¸¨×Ð}C‹³„Ó.㌒œÓÒ!$…’¢©<Û_Þ¸izqdƒÑ^¡ò(1´Ó­llÞIã&ÊÁ#I2_›™‘Ýkï}ì\Ü_(ÌüÑAS!5,¶ÓÚÍ a…T¥ì ¸ZðèÒõ¥Ñ@3ë<âê\Í™¿!V‰tvA*“fÖ šIMÀäH¥GÓݨHyEñ …Yƒöå ­,«çË„³Á”!“ÊáÄ\«ž=Üí ®ouV9{xäx¹P‘´Œ­5¡ÿR!tW8ѼN”½–TyÖj%Ñxáb0tÂ߆ Òú^š]Téx- ·MÙÌLÈ‚MŒn€ dJD⊚»®:nŽg~ÜÆYo—¤Ý~ßU–t¶®êínf•kÊÚô¢èy/}lgµÐœábÛªúOj yŸsõg­âb¦X²°Œ—QÛ¥œXÌ yNouoÊæ›Œèâ¬'jœeÏLJš-Hæ÷¡]C–y-IäÑ£ˆ«öRã?ãhÞP#‰Ñt<‡¥›ð飴 Q3*WHX„ùeÖBâ‚)˜ ÜhØ7.•a1FBHSº¡é®Ú¾Š²¸ø‘”kJH‘"©É´>#ÔÀïÄ&[˜»cç,ÈV“ “5.ÕKVûm:$ÐR¤à–âR½ž>Þï–‡2g¢ÒÜ0 š¢yŒ>ÅL—Í!“s !êYºµ®ß à3W×qBÕÖá·â ‰ êÜ?#|‡K·CÆÕ‚VPŽÅ~WÐ1¶4aĠ¡h*|„Ù ‘p!%pµeqyY23#D«›&FÔ½ºTA2¢ÔÇ‹oÏØ®td#à 6;µ¦8ã”X.”]™‚ÎWWÂõ‚öVbWb¹–ªÓƒ^Ññ{͈‘š‰ R£1D˜ ë ÀÚÕHm*ûj‡ur/ ”eÈmF(ÃJ¦!¸ƒšËÃú‡ISàyhÃ-ê’q\A$@dÝgúª†4ПØ6ÚQ¨g¢¤©WSɵçds hˆ„¾M¥Ò£øÞU2·Õâ*§’kÜZšÊ “°’ÚeÁàà%7B ƒ¤Ôm™É‰ÙÀ‰u0#Twà&ˆ¢v Ï8!ŠL¸"2‹ËË•ðá*Êp½£„$ ḠZ7R)o&ûŸŠŠ#,ˆ<§ ÓŽå:~äI°mʱÂDŹé¡Q΄uh@«br®!|ĦH£pNa’„Iá NîAJ†ÁK"Hl©6•›N¥½~1(=ê™3_§l@Dl )6SÍ:’‡“E†•ƺ݄šñªÐX—IW$X£dÑS¹ún£é~Åf YÜiÄ0òC&agƒA¸È„õ£Kv6[g¡ö8<ú…¡0O.<>À1Úï0Úûê=1$,w|Ú7S|s§‚¢§dæ”5¡"§«Ï ÂQ¹kdÒ²­¦h»Dt +ú²£æÑ'ý¤SŽ|=ó¶)úNˆn}FtÈÏÂàrEå‡âjÔaz‘Ü 1Z‘ä’~"˜¾ª>‡R‚I}ŸÎ?2þ¬Øß˜«†¼ÕvVÁ~Ü¢RvÓÔÏœ¨Ot´Z"sãßÕs‘)ÕloÝ7WŽYvƒŪ@ Ð!Ú³ÁDÆL2~ìoOµtŠ\[õTNšÁ aÖ.ðÎÎNa\jò$‘¹0.÷Sã“›¨?J`ð \ÙE¸R" )¤×?ǯLÅ+—6£Û˜01¢wáb'Cc+¿Ë,¤ùGå 2ràTš}%wfb’áÐ)Œ¿Y|¢¢â°]uÑ€BX?7‚.–¨ ªá«0’*§ŒÉ0nQÚNgÔ¢Nç±M£”H‡cÊ‘Á“Z&æé‡#P`‹ $ÊP'ËŠk „+š®*éUyŠç&¹i*4à'˜Œ3açAÃŒ;3MV±Ã9Ø~ï5 ?>µ¯Ù¥åp#Š*sª}¨~F'H‰ A ¨m é@ù;TdÔýV°Œå¶‹Êy/¦¥¥ M½ü»:Yâ¸SµŸ“f¯iM0ÒTqS­Éf£Q&Fˆµ¯Xƒ`\2¯¤š^hévAy¿^–¤>jK”ŒÉ¶ÂÈL8 µtEB‚b¦§GlœžF0$(¤JPÙ‚æf¤Õª}‹}Ïp€LÐùŠµÆ¢õר¶ òêJ|vµ¶IÿC\ညc<`<µ}¥á`[Œð\‚‘š‰©¢r'IyåP™sé°~¹²Ù\-ȦǓLU'( ýÏIÀnAcvDC[SÚ$3—GýŸ¹ŒTº•ˆ\Õ±®I}jÑ¿Ë'”j¸Wxì7@š`ÚíBZ­ÆÐ®(žú/¨ÄW v†çE@ËÊw7Q•ذH€œá,­Pvöd˜aRU}ÕÏi ÆvâOª¦k+ŽGYé°Â"0¶,û~oü‰öÅL礿Dhæ¶Y±µ~‹éI¥L­>‡Œcöõ9¤*LMXÕª¸…úÜ,½³Ûi°“ŒfB¤8]ô¦4Ú Õóm¿ÖR5iÕ0FÒÄj¿#-†CæŽ.Ù9 09˜þ8òvbdhЍœ´½ñܵåð²0¤N—=©…Ûj#÷~œTÿ“‘€´FØ\¸ZíõX}¿4i£¹{¾ó€·ÖÍݤ²g fpâÛ…u¿çç uWÍÌð\Št6eª“,Õ:±fÃN|j5FB01ox]µ¶ÀïÍ6*;;&öâ›làd7«‰‰è€\Cn¸M#ÓVK\i‹îªqÓãúN¥z^½3ÐÚÿ2aÜmÒ‰¹Úr«¾gždÏ›ÛQÖö²V‘«XNðMí…°cI×´“Ñ@5œtN'TÛÃïx2Þµñbð3[tw»*‰e U•c2L©6ú2'Àu[X][/¤]%Åf­•<µuùbIsϨ'“ñyÁ&L˜-A-{¿(xiYòÒÞªz¶g·À­›’IiŸ45Èfè^Z/Ó¦|J[Ñ.]]ëÝÓØ«ÊL–RÝUí;óW¯‹K:~Ómû|N €Öá…HŒ4@•Ñ“€ÑêêêùÁþDz|«e¢û¥î i7Òš\ÒK§.8qpg‡§ú݆öU7§®X¤^þ`’šLܹØÈNgýªý…qP5 ÄÙÅZ‰KBº~©»z½|­.pšH×¼û’pÕóc÷~÷³JÙÎ"…Ÿmú£æïä]Vã{WW“^éNæã*Ëý`O_^ÓRгÚn ´\W‰=Ù]ë:j­qBL2_Uþ®JŒ5ÈÔ½,™v/kM= ƒŠz¬Ž³Çû]å·H¹l/ ë.KåI‡X+œØÙ;­Ñ÷_ Ú„¹€Œ´på=cVµO“xÕl•‚JÙ¿HWf4ïsN~¯š‰ÉZc㯲8ç܉P ÓZ»/¬Þ‚•l*}zpö™U—\¿]CM&J¢Ú®Yjý䕪dM:]ÕaáHØZƒ²[£Xê®&SêicÝJjíFzý _ ¯ÉþWÞ?–ëà‹Ñ\ܱíU cñ/½šHñ_!4ð›"ÁÎIœèÙï„À*¡ª¿_ûþîQ0yº•w ×–Ú.#X‘®|dk¥õÖ¨]UäOÚòªˆ€Pø©lª2¸“0áìºä%l¹€ÊÄ#ÖŠeŒXée;? æšì›ÑÕÉ|JÔ¬‘QK<ŸÉ-»çÏä¿™ýNve˜Ub;Qaä7؉ï×XœsîäIÜ“Ð=¥·JX)a©6<ÞæÙ%m÷lPV~ç®1ˉ¸ü$ål­×w._Î-9ÉRÚpvέ—Ìog~Õqz>©¶…ß9¢1·ýáÕ‘·Æ,ÕëÈÏœ5ª‘<è„X²B,¹\¯§=úy›2¾’öšË¤É­š·È—¨%®4daáîx·¶—²ô/-š|ð¤÷?™ QÇ´@Œ^„-bœsî~°[StkEÛ\q!­«SfyãÉA/®~©ôl§VÁZ‚ 4wÎW%/Q ’7Ñ=ùe)ž$“§´º{¹«ho£¸®}Yød‰ö?J~UËÆm"?ªYÕÄEß w(ÛÉS⇠ËþÎ!ß•ÎMjƒ·ûÃrâîé6唣ÛÏÌj)Ü„;_ŸIê>¹Ö.Ëéq‰‡í²xnC¬úµæ+þï]ocók ýMÕHyç.`ôêTîÓ/–ôoN|ª¾êÛDÚÇd\¾*ªÂh ‚ ×·ÀâÃÀ<þð¢ªfUåZ͸fxKÔ\¢HŠb³æÜ’Öâ¼HÄùL™{º6ÏÇ·CÝnï+ý˜ôâç`Š-¿;h\ =uˆõ'À^x¦­ä!£Äy!8‡vKÉ&›<õ7 ý^«Ša›£C]erLÑWùRý=ž7¿£ØM€~ÁwæWÑS­´²À°–*Ó«„-p8rG9¼ªrân¹E) =Y”«"µç1ÏŠšxª\+ž(ÛÓ“ÛGÌvðN¯7%Ø7+ÎQ<þ ê™x‚4yJ*yÎXwQ'åªÜMoùè‹$ý÷Çç#Ðd öäÜ@&þÞIS…ak¿rÄŠ+ûE>îTìäÄó%㌨,€½»(”6aú‰'OâºH©sºù†Y5¥X²%—³ŒGzO÷—»L\][%FuJU,UG0¬ õ[ß;Toš –“éô•ºË–dj—]N÷¡‹”×4ðS)Ó=„D PXšÃöOŽðU…s2cX‰ÅóU¸Ä9Â.fã¸÷^I‰ñj¼gæN>@5½:™ ˆ×$­ )‚DJTýµàxÑ[€%¬iSôÖMw°á¶úhõΑ¬|©dí”òcÕ^Vµ@ôì«‚«œWqŸ„€v)hÝÞLä‚n¥uÕII/iÖËÖ.ì-m»–RßEAŠßbszGMUMSGí +ǤëÒƒ9Ž09%ì®Å´ü"6sr7z@uÉUµT3RU¢V€ Ð5'åNÖ•ÓiëòøöìÁ7UîB½qônÔá‹$õ6õ¤Éô@2+ ‡åû¬áÛ„CJãØ:éÅd÷­Ñd\2&U©«|xæ½G¨7‘ûß5ßÜó·²òØn—Û®mÖV´Ý7Ø3ÓãƒY{°~}ß{…9ywÏ=n'ª=g9¢u© )’–y¡¨ ½üjˆ]Â"/ªð›tÎËLÎÀ`¿ô]Çä1†‹ß}Y·º¦JÊL’ÑÓã誎ºÆï1'=éLÅÉ¢H›ˆfííÂðˆœQÍ&yûØqtX2ÿ¼ ¸GÉq8òý?Š:oH_¹HfZÝœ¹Òq$±¼ßIÞ$¥laýJ Léè<æ×§î=‚›\œÃ8é$V5ƒP~Ùµ3ã™Í^Ê?@ÌÞ)9ø¶@ç¯_¦ºþL¢[µêfMµÑºÎtïnw^¤¼ÿaî¢óÍ€A!>}Ùl‘ÈMšbÀ¬hð=Ã:2TâÍîääœÉŒëäZÉÒ¯Wp%vqqQÆK†ïþÕ¯Oå¥`i_z4Yª“ª ‹ß/BÜñŽo_ù“r©©Zí›gºæøq¬b[®<2<Ó_ó£¨=  Ý„Æá:ÍsuÃ]‰âÝVÈïJ60[Z¿4ïݴ è>Ïpð• ëŒôDâ C,ÉpÕípO9F€)»°òyÈv!fŽ6iÝü½´Ÿ|sÒ»ô9µe?®²ék‡f7Z‹eo÷ ½þ­')»§0÷ß/Ìý÷(9 !„8~qó is@SÁ‚Ü 2ñZ¿[+ã`Œ6?~šxR«‰¤Áe†¢O¹/;[‡£ÅÇ[ÏžjôsÑŸ.J« '‡v¾:ÖN¥Âøó„Ñ~ÑžFuIƒK‹Ó?+6ó÷e‰ìÎ]?í>¸¾$Þù å}÷ù·Jœ<‰8pqô8â®CÈf—¤&IשÕu×N§êõò&¥ù€ÉÄë\¢öI+¤rƒ³Î¯Lá=!l)ˆÂ¿Éõl×ßjŠ‘ÃTí×prI vÕÙš.{’^~äetw{ÿýÂr?,õ5>øAäþ¤Ó ­,aQô¹^Ìò³87ßWðhªfaÌe` 8ƒ( ëZ”Sç/5y íáË£zèWÒ]_üòÑö—>ö;/yMýÖº”’K›ãv=–:£Ø?2<AVÎÁh÷ñwÿîÓÿºïlöÃ&­?¦S½VJÝ³í¶±9®£‘ª…Ì6I3[¯5 [ï9×ÐμT•ö}ÎðFѨMiQ YÛA°in(¬ÃM¼£Œ§8 ] Ù¸ñõÎ1R£ö“ Çýªó&C­É¸Ö„]/‡é[ w6Ãm^Ü¢tæ”úSO¿á Ý·¹˜Þ 79¥K±f +Ï#ä.Têh& ÊpTÔø¨HUƒI{lSutr2E?©ªçf›§Ýã—ïþéoÿlïæ3 xõsê×~Mm\ºÔ”j˶µvsÍLD{iÓ«ÇóÕÉÕ5Ñ1Ið§?‰xûGâK?ó»âü³—s³¿š¤Ù%jóy'n·È×13V›)ò·„û!“ÒæŒDÖpR@·*z¸¼mØB;QMxu($~ "ƒV [çáôgáÆo‡lwhgu¯kÇTÄR µªj8þ½ÕƒÍ }¦aê0búÖ)Ê$:ÿ‘Ø\¶ôôYŸsR~ÒÖåçDÛÕJ-ö!PÔ¤a¯Lø§¢.ßCš@§1z2OQÂâoTÎU£1# åcúÆ®÷EO-]l¾sa´kàæÊ×Uk=‚ ½Yj·‹T¤JÐ [±ô9‚U×±Ú ŒñÇ9mSÀRŸøqxÃ!-½Gùô{䥥5ëósb®wIΈúTšL7qµ˜[ peºë>‰QøÍFŒò[i´`ž •]C#`¨¦öExú3pÃë­C²’Gb6O_Éó®zàQ“Àò2\^†LBsê ˆ]·Iõ!Êî!ÑÝú'r0Àõ%)ml`™ÍdDúMŒ»ùHÀ¢$ÇŸÉP› ªŽ{¼>nf!-fÃX¤Zéo\¬]þüÍ÷Þ}·l-)9èHeÜZ¾.{ më²– ¶Þ¨Æ×뤕F$Œ$¢*5Ñ¨Ž¶€µ>ñxÉ-pÃë7e 0X°Ë›Èf—´ìQ6 ³ ý>I©ývø0LÒ¸¤©¢òßøí‚á^2šq‹ßYÌIè¬ Î|QrPÃìMà÷Ö¯²Ê`1ñ}òw*×U×ñ÷-ô6Àl„ÑÄ¿},­A} јJ)Í.ŒÝ…¶Þ¤u †jß1ÚZ!1>¯ãïdªâùhæŒÀË`-•»d;›jnæ´ÀÉ#÷¹ýù÷¨´ìi´XYíØÁÔúÀ&3™«ý‘º©z÷qP"vZTÎO gáóëOÁÓOÁ\ظw£$S×clÿc‡W݉eø&šè¸É a„eøÎj¡F÷Æ6È@WM §‚™D°µ Oü\ÿrþW3žôÚÉŒ}«Ú^gŠcäO®Ôéh?7_mU"+á;`í¸CWµë•þl;W•üDà;Ÿ(Ì@Û kôB^LËu;›è48ƤÇñÀåÆut×v—´©ín%"Â+öÆ|ªª>#­üSªU-ï‰o¯_/ ì/m…Wѱ‰í¼-„ëBxßWae°ÿIÐáœÁ×+K°(ž°¡º€å3–ǽuÁ¡× dÓzs·“z¶Ø—IÀO¾`,‘.U‰&t$Jji¬?–Hãªý¯ X¤mU 3›'ÅY#6zôku·ÖÌÎ º~ó¿åG?ãT®…3E¡i÷ ·¾rÙe{àÜ|‹á&ÄÑãy~Wù;vPWXý^µ«ñœ `¨‡ø\A=ìëŸ H•‡±áíÏx‘øN†/‚¼þ7é »«9å@$ÙPÌì8 ~Ѳ²îxí¸—„óßp<ð`·2¸Anyxý°sè¶ñŽ‹L&o¨Ü[IU“D[_0.åñUzâ·*c[ªZ ÎÏHSJkÜÒ9‘çZ¬Ftò¢oëÙª ®ËÝt»¥±Úβn»°²ézýs¹µsuhJïÉOÆ™q–jU"&C–ÉFÕ‰‰|ùÿ¶wfM–×}ÿÌÚîÚ}{z™îY0˜Á2œ‘dÉ!y¨0|°%ù~÷Gð'Ð_ÀÏ~Лü`A¶Â2fÈAB&£‚N„IDATe1I=Xf¦gé™ÞûîKm™é‡º…®nH‘6-Ìy麷³êVžó?[æÉL¯°JŽyRhpyü[™ïËüž.vP]ÜSnòɼާi¶„…E¸ûüÕ· Žã_ÿ!<¼Ç‡²ù{/AXþò?¤~3‚a¼N+ïI¥¯¥¶•‚©ÛTúU '9ߘ UyP½>;SÍ>κˆœð•–)|Á-Ù#ÇÓ±‹=åjG/Oâüxoâ>‰çkyhÅÙ¤—9ö“Äõž>ʯ]Iµ^oÀýQ –/QM¹J÷p6ú×gÚTýâÙà©^® "©y!ö¤_¥ÕU˜|;ß<“ù¼ ¶\¨¨ŠfÃÑ?„¿ûŸ°løß‚/={÷ñ¿fdØzÌàË«üÎRùþ_NÙØŒøÊ¿mÕ)<Êÿ~6VÞ¿š¥ò’šÓ»±”‚*YEÈg}÷Y«YìÓJD廳ÁkÃÃdÎ=xälÏ2Ztì‰ØžÍmº8žìÿy‰És/±ÈЉÛwŽí“îûSc5îRT ¶já´0óÊß³ZQÍW«¯>¯Dqùì9 ÔÜä{ jó*^]‚cn-D ·Q pyocYˆBËG?„ïü!7†ùÏa#bðý¿æ›[A^ÀƒLØÚ:曫)Ã[7`tó­?æà{m¸Ú%}ÂäêxûY .Z ¿ª™Ì¯uå9US}V›Ï¥yå¾³à©ò·tAM–<>rìö]R>²Â®1ÒÕØ85µb2hó­·ÜÅwÑ%Ã<ñT:ð,û©°ÝËܵ‡÷LóÜÅD‡ÏûÅ™À’¢f½ªµŽÂÄ•‹CàtVq’T]ÚèÒü—ITÚU¶ +ÏwŒ˜Íœ*¬€DâÑj€Â°{_øèÀA/ãê圗Ÿƒ­»üp:ãnTcϯ³G@ßóÀ÷X´ŽóOS¦õ”ÿée~ý^×òƒÿÚeé‡5^ÿ£UÔËx09­UkP5ÕÕ˜©Ô~5çUÕæ•ûlåsU Uåqg~ç¬É€–Âu4®ð`sfÃ%Ç#ÄŒ Ëâ|<Ÿ ¼ ËÝÈNb›˜Ü²'l‡Š¶3–£¿žú¯-µE¯D…½}šy}uåÊ'eG¡UKÇóJ›’JóY2©¼.©:ÇP2±¬ùœV²@p¡Æk(TžÓ}lyø8bØóÐ2å7¯YD˜¼÷#¾+°çG<•ÇÀN Dd‚ÇÎ1šX¦ØßðøÝ¥+4ôf|ïcÖo.ò¿؀•쎠oNQЫéY)ÐÒMœîËë* Î ¸´Õˆ U7‹(]SSÁ’‚zƒüyß=âEŸw•æ±…}“Ñïfa’5F\Q"ß¾uK³z'Ї‡Ëd\²×]Æ«½”ÖÈåK×V=×E| G);ÀQÔcÌ )+ÐdMkYÎ žÏ%›pÉZÖ]ÎrÍòeOqaê`¤Ákúœ¿¾ÄÚ+mhŒa·Ç ÌÜi!U]aµJ§´¥µ¨jwu¾!;Ó®ú}ùìòº¦à|——Ùü“>Û[cîÕè¿ÉÑžÛt‡™åAîq×.NàIúÉl ˆÈ|o-$2> ¢Ù…ç3'7sã^ùxÆ×K­_n¨+¯Aí<Å€Én\˜Âp„RKçC·Ÿ0¡`uHu«×ªõ¨ºŠ²MMè®Í+Q†9½=Hü6¬]à üè y×áy fgàÐ×à±£4ÛXžŠÇÁ,¡ßÉ™Þ;&©Í Ö_¨¡y‘0 ©{–EVÇ…ÄrIœlä9«*w+ã7MÎB‚  Öòh^Ydñæ2Ñ’Á1< ?ÉÛ«n *äªæúœòªñRyÏÙ@¯´:ÐRðbë/óþ>ààÞ˜wBÒWÛü¹rÜÑ›&ç~ž±?3 6!æí3A«ØÞY`˜ø–Cß'Ôâ"¢ëu¼¿™ñõòtê+W—ÖeØxɵ:ç0ˆaìNV•þ»T‘{vd±ŒÌH>hˆTáÓœƒÄogÌÆ »´ÿòU¼ã'}÷Lö@|Æž/ï&°¯"ŽD»='ž°ÃªÐzÝ!þöûd;ï`¾1­Û`ÿàË¿"†¤œéT1ÖBÏ9w$Š‹øÒ/¦ÓÝšñ¥i¦³œQzÄðav§Nûú õ«—@Mà  Cæ§óüjðWº‚rK¦ª¦—®¯:ðTf%_+\[ãø¾âé_ì°·ónˆûõ–üðÀŠÛJ-;YÊñ±f?&ûÆ=ŒsîdÀ9çÞq¯cŽ2ÒçÚŒãð«õ ÜFþ`·pjiƒ¨Ó0> ¾°”ǬâXSÈjž³"¢8išÌ­ö{îKIN;lÀúš°Ð†f 8-¨zçP+mjk‹Ð˜³;Ê3Ž!N É‹]Öµ.Ú,¶a¡SMïñ˜þ±úäÓŒ{–÷Æp¥Á—By?‡'(w/sl© sè‘3^ É~ÿíÂôª¨Ò["º÷:j-$2 jÚ°ìëNñœ‡\Ã%ç?ž¸ßXüòEÍÕE­@ê u®EøÂe Ëxa a3> 0“!n8Æv¨I‚ä B-òHœ0fì<Í9Þ1Œ§ŒW¹_¯«]„IúVäHG™µGNs¨=ºYÂÐ)¦ý¨8æw07Þ:mî?/•ÙÑ7Û7Ðù?‰‰ÄRod´¥Ø±‚fYr–•'ËbYÄH[Ó™[?¸kiJ3lÁÚ’pnQX¨F&Ô$Q„îÔ‘v/($ˆBh†¸á„é(#}:d|ÿú n–“x0±ühß!ŠþË-ù[­ØsÛ™¸ÎðPžÎrº~„¿%Ý÷¦;SŒúÓxò¦gr_{•°±FÃ9´bÅ:.—±rQ`ãÖļ;:Ï- —=Vkަ³¨hú ÃÓ‚›o¢m´"$ÐXºCäyNÞŒèn,ÈC?®RL3Ï µOO!]DZ±Ç Kw–1ŒSÅt%"þø1Ùæ–¹¹ÿ‡®Õ+À-ÔÍUÔK—ñˆM=Ð4}Ÿ—±ä+uNç,nÉX:ÚÐvNšb¨§©[Úï¹+½Kxx ¡ÓQtÐ ¡&ß9Ôü˜©2#(ëæçp;b¥Ø›ÂÞáaÏQ×ôžoÉ´fß)uãžhÇ£»->{“˜½Ç¤ñˆìßðék*ªîð;爰4µf9ð8oQ=܆Ö:¾ÈB/·Ïí¹è|í–¨s5E u ±c!OÓÔ’¤Ž<Ãz·º‹uöëJºÊ#v>3Æ.` ž½LÙ>è^¦Ì@F.gŒ‰wIÿf‘ì&˜ÍŸSã?/n¾QD2 }üõ‚ž5…† hù‚:S‹™£cŒë(dž¦s4¬•–h»¥þÄ­OY2>* ­š ž ¤H€âÆ©£;µ 'ÎzŽÉZƒÇ@m[_ÖÚžujÏí$Æ>±»5ÍQfNî’ü4á&ª øSP»/à--ÒX h¹åTs>B­!¬*%Kʱ(Ê5“Œµnj¯Ì ¾?Ÿ³w(’ÈcúŒÙz¾ÇÔ@¬„™UŒÅ—‘‚µ Ñv ƒºf˜fŒg0m„Ìöº$«ò­-ò·nþü¦þg¥ªkxc}õ*ÞÁ^3 ”œZM–aji[Ë‚µ  m#,XçZÎÒÄRSŽ(Ë¥§tz»6Ëhæ†Fl íüø ›ƒµd^§®FûNÉX}#®k…“Û}O³'ç '“iŸ„;äŸÅÏ@µ×o‚l¼Ž^ß\$° M më±ä+–œVç|ŽYТZ5êb] šGµVƒAÈÀe b<;SÈ4ƒ‰ÆJ16ؑҌ5Œ“„é4dº2%všôÀ}xDþê ó¯bùüßü§°¤p ·á«ßA½WC_7x«u|i Q=§ê‰GS9šFTËP\ 4Œ“º5Ô€È8üÀà§ ­5/e³Æ‘ƒ$;³02Î ô2gåØ:z ›3Æ[÷I†×È>¯ûûü¨vàÞµ ø‘‘¯hf–véVæhEÊ5­ÖMp‘¯•'Öjø`¬"Ç‘ie“Ìž)ÃÄ@œ)fÚ2M!®AìFdõv!tsD¾}ˆí\Å–f>;ªÿeS5}¼ùÒÛB]ZAé9¦z_2¢ "Šm1¦‰iÑ c\ MdM9¦aË IDATxœì½yœewYçÿ>û9w¿µW×^½¯Ù²ÜQð§² ÈÌ8Ž:þ”ŸŠðûé 3¸"‚ÀÈ(ê°‰ÊCBHÈÒ!ét§—ª®ªî®}¹ûröóýýqî­¥@4Ý©8>y×­¾usoÝçù|ŸýyŽ$„`;Ð;ßùNõäÉ“©ÞÞÞ©TªG‘‰¢¨»R©Hš¦a†dš¦¬:ŽÓTUmåúë¯[ìëë³_ùÊW:oûÛy×»ÞÅ=÷ÜC&“AA³ÙD–efgg)—Ë8p€¥¥%Â0dyyÏóà $ !›ù!IÒúcûyUÕèÛ±UÕeYVP™_ü…ÿø|°í_MêóõÁwÝu—*„8 q«ïy×úžw°#Ÿ‚ Ù¬×5MÓeUUéëéAS5TMÃ4 ,+$I‘$Ë~±Xt–—––¾þõ¯Okš6õÕ¯~uòé§Ÿ~òÊ+¯<EQQÓ´HQ”çë+¾ è²àî»ï Ãð§ìfóµzýˆÝh*®ë†¡c˜ÉD|ª ÃÀ0 LÓ$‘HN¥Éd3¤Ói9a% ]× Ã²²–iîB°V(`™¦hÚvqzzúD6›ýfµZý¦¦i…a¸¦ªêú©þwŠé²àî»ï·aø‹µjõç«åJÖu‚ $ŒBÂ0 Â(Äó}ÇA¯kÈŠ‚"+hº†a˜$©TŠŽŽr¹ds9t]§»«‹]»w“N¥$YQ:=Ï»íüùó·:uŠ…ùùB­V{àÌ™3_¾¤iÚyY–/×WßÖtYp×]w]gÛöÇË…âǶc»x¾ë¹øA€ˆ" !¡( ’H²$!+ ª¬ ( š¦¡j*ºnɤéì줯¯ÁAÆÇÇÙ³w/ìܹ“¡¡AJÅRçêêêLLLüÈììl}qié¾f³ùWQýPº<Ø®$]j'ð®»îzI£^ÿL¹XÊï8Žƒã:¸®G!‘dEQÐu UUQY’‘dY–$Y’d YŠO°$I ‘@QU,Ë"•N100Èèè(CÃÃôöõbè:hÔë”Ke.Ì^`vvvqumíyž÷qY–OȲLÔâú{óoÛ ¼¤¸ë®»†ÛþZ¹X‚×u©7Øvß÷€ÚRñ±O¢ëz$ÉRS’åyEUWY E­¨ŠbK’Ô+Ë2’$¥€Î0 »=׳ P#¡**’’ Ò÷}4M#•N±cÇ##Ãôöõaš&¶mS,™›ŸsWVW¿èºîû€G6 ¾ýøo—ÌÜu×]‰( ßÕ¬7Æ%I"Cv“f³I(ŠŠišär9 ÓhAøÐÒòÒ}’$=æºî”,Ë¥t:íf2‘N§}Ó²¢t:m¤ÓiÒé´’ÉdtMÓÒÍfsXQ”Y‘ǧ§¦ØÍæþZµ:îØŽ¡é:R+ý4ÉT’;v000û†ÎèȈÑÕÕõšåååY][û¼ïû¿ <ú‚ÃxÉ àVßóT¢HàØ6ŽmF!†®“Igéìêt ¥â'Ž=öÔ ÅÂÉÀ‚ïò¶Í‹þ]Μ·ðÔ‰ão™œœüÒsñy®ë’5ÍÐ4ÍÊu×]÷¤ªªOÞrË-^][ëxêØ±kgffî8îÜ5ꪪIaR,Y]]%•JÓÝÓC>—Å0 :ryò¬7—ÊåW8ŽóBˆK’m—¤ÙsI—. bT’$dYFAFÈ’ŒeYäòùàø‰ão9{öìs"ü6µ?/ C¢(B×u‘Íd W_sõ—GGG¿¼¼¼ü;gÏž½i~~þ5…µÂ«ªÚFƒÊäÉTŠ®®.²™ †a’Ëd»mMÿ`½ÑxEï$iæ¹ü{·]2DBÔØC'öÜ5M%JQoÔ?ÿ\ ?™L"„ Z­®§€mÛ¦^¯Ól6ñ<MÓŠû÷ïÿbWW×?ÌÍÏï^\XøñjµúzEQöxžK³Ñà\­N:“¦££ƒT2…nèdÒ©lÚöƒŽëþ,ˆx.ÿîç›.$I:&„ð%$MQ´VÎJ$8;5õÈsýyï~÷»™err’z½¾¡y¢ˆT*Egg'aqó-· IJä¹Þ™T:ùË2ÿTˆð’l¾CVµÏu¨T*Ôku²Ù ÙlŽDÂ"iYýšª~Îö¼_HŸÊ€ x­Ç$]:@ˆ‡Ò¤$KtMÇ4M<ßG‘dY~Î?÷SŸúÔ·ý]½^gyy!"ÙµK½‡÷÷RTýÈ`÷ÈX*/ú£ÐKzž'«« Y’q]‡B¡€í8d³YòÙéLZÓ4íwk•òoç;:=\` 8ÿþ?üã YVŽÉ²|TQä3w¿íç¾›C»-è’æÞüæ7ÿ¼ç8†!F×q° „Ľ_þÊWîtlû9ûðo²%†zËõ#G®:²÷åûwfo„×EQ©ÕlÉud-…¤uci– ËËk4ë5<ÏÃ÷}t]§«³“îî2™4Žã"‘ïèBˆEQÑ4EQQÅSåiE‘ÿQ–åÏ*ŠòøÏ¼ñõÛÖ{¼¤xë[ßj6¢0º6 <ßCQ’ÉO;öÊcOû»çê³Zˆ³Éìíì¼ã–]¯|Ù­ûÞJ*7WªM­ÑtpÝ€P(¤3Y4#K¨ì­†#(KT*E¢0Ä÷\æ©–ËøA€eZôôtÓÝÝM&“¥V¯ÑÓ×Ͼ}(•KÔju<Ï%ŠÄzºZQ”@Q”?B|îÍoz½ó\}ßçŠ.y*ø-oyË-zý«Š$›‘ˆbgPÑpúèì¿ö3$I’‰…våÍÎ7ÿä­?uÇÍ#ïÂßs~¶ÈJ¡ŽªttöÓÓ?ÆðÈ^ÌT W¦Öð¨”K4 tC£»«›žÞ Ýàé'øÜç>K©X ‘HÐß×GOO +í:¼ø¶—008ˆïû4 kŠÅ"MÛFA»)„8!„øM!Äg~öÍoÜ6á’àMozÓÏ7?ÒT I‚v%NÕõ{Óéôkþàþ ü/y_)>ö 4MQ^÷ê›_ñÆ×Þü.¢Ú“ç(”lPRd:ÆIdv ¨’báàû>²,¡é]] “ïÈ#„ V«Q«Õi4LOMqß×î¥V­ Ë2ÙlŽÁtuu!I2µzƒƒ‡`ZéTŠD2¢(4›MJ¥ÕjlJ„HÁ? !~éçÞò¦§ŸCÿ‹é²à'~â'ÞzþÑu=.æÈA"$éžL&óãþð‡¿'´N½ ˆ¡þìŽÿ÷·Þþë¯ú+æÜô)errÇ·P’;J'ÍF‰ZeYïBR3¸ŽƒmÛ(ªJ&“!“É iz«ÿÀ\?µA`Û6çffxð๺®ÓÓÓËÀÀò¹ÕZ 3™b``ˆ(ŠPÓ0H¦R˜†N†Tk5 …"Žã´MU5Š¢_}ÛϽùƒ—‚×ß ]6¼öµ¯ý½Àó~Q× äVE/„,=dšæOâŸø®‰–M§^¤›®ßÃÇ>øë¿?2Ôqåêâž]FKŽ“È R^evêÊ5}7P)רÕêhš HÔëulÛ&Š" ÃÄJ$H¥’tuuÑ‘ïDo ñä‰|å+_" CR©ƒƒƒôööb:k…"»÷@×µ¸r)Å•KUU1Mƒt*ÀâÒ++«›+Ž.„xç]o}Kã±ü»ÒeÀk_ûÚw»¶ý.]7Pd9ÎÜE!~ÎfrÙ»>þçþm-›N½ è¯~ùu?ô‘þÞï›FÐUZ=‹}’ûPõ,µÂiÖ–&P“Ãôí~B¨¬­­R,ñ=¥åe.ÌÎR«ÕQœ/‚MÓH&“¤Ó)Òé ÉdMÓBðõû¿Æä䆮ÓÝÝÍàÀù|…b¾!º»{E^ÿn’$¡¨ ™tšl&ÍêZ©élÛnkƒ{„¯»ûm?[¼L"ØÊÓç#¿ý†7¼áMÅBá4Uͨª†,IÀ÷ýHÕ´¤3éßøØÇ>¶¥Q£%| HÖ[^ÿƒ¯û£÷¿÷="p¬raD€•#ðêT ¬­­`f÷²çêÿ YÖ¨Õª$,‹sçγ¸¼L¹T¢X,R.—)WÊtäs†ÁääYææçcÇPWH&MrÙ$Yga~ H§Ó ÑÝÕEÓ¶I¤2ŒïD"ËHŠ„"ÇMR«‡Á²Lzº»±m›OŸ¢X,!ËÀãBˆ—¿ý®Ÿ[¾¼’xžð†7¼áêR©ôIpµª¶?$‰ @’¦‰Äÿ„á_~úÓŸŽZj_R@úå/»úŸþËþŽ,‘¨®! ] «»±H£ºH±PB2‡¸âæ7£é Êå"Q$H§’LŸ»@µZE’$Â0îQ(•Jä²išÍ&_øÂßqâĉ`a~¾^(¬y_ÍgM«·'ku÷ì@7:Qµ¸Oqp`€îînü @V5:‚ˆ¢Xø’‚ÜÖŠƒBŠ;úz{@’8úø¬¬¬¢(2À? !^óŽ»ßZ¹œrxÞã>ùÉO~+“ÉÜZ,—Þ†¡çy^«=[!Æ«•ê_ضýµƒ‡}ŸišJëoÍ\{åî—|ìÏ>ð›ºf%jåó„AMÏÒ¨NS¯,°ºZ¦j¼î'°¬$õZ! •J295½.|!b;,Iããc\wíµœ:ušGyäüÑÇýæ… çO5ÅFÓ[™[¬.Ÿ<³°63=Ôë%@jµ“Ç—ïùH´šGZ¾Müw9I­Ï‘$X][C’$^tÃuôöv†!Bˆ;€?¼ÜrxÞ4ÀfÚ¿ÿ‹vìøoºª½(¶™*²,!"¤ÈQ³Ù|ðÌäÙ¿r›…•¿ûßúžë®»qoaå,ní²–Âm.c7ëŠ5æŠ\ÿ’·1¶ûjlÛ¦T®Ëf˜š>G£ÙD–$"E‚0 ñ<Ý;Ç9~âï}ï{øæCþoâdR/0 ô9 £(RîÆnèéîî“UeÇŽ~zº»)—+ô±k÷ndYAUbû/+ rëÔÇínò“Ð×Óƒ@ðÀ7¾I±XBQd‚ øÏÿñoÿ—‹÷Û¢5öÔ©S<ðà7n[)¬ý\(¢)×qp—0 ƒP¶tãÅ{wîú£;îø¾îÝwxO­º‚[¿€¤h¸Íe<§A­ÖäÂ…º¯gdçÕ!(J$ .ÌÍÑ´mdY&‚(!bhšJµVåóŸÿÂÓ>òðo_¾|ø"ð0,f³y/“ëÃ0ã8˜–Å®]»pl'Îq´.‰VÎCŠÃ^™ÖÏ-ÓP(1 “뮹 Ë2ˆ"üæïü·ß»úrñ~[Àu\ïèÑ£6¿°p•ø¿Šèœçûx®ƒøØŽ#¿âåwf,C•šåiDäã»U|·A£á°°¸Š$ØwäûX+P5•R¹LµRÛÔ×_íJ¡„ÄÜì<ðõ? Ãð!àBë: <üð`.—󮹿š~C× Âp½iuye+®8ÂÎ㸮 ˆ¸‹¹Õ›°Eø²„,Ñú]¬ ÖÖÖèîîbß¾½-³$2a¾ûrñ}Û MǯÝß}ïêøñ-./ý×Z£yfiiE\Ýa~ôU/£Q[ÀsÖˆBß­â8.«…2³ «Œî¹L®“Z½J£Ñ$Š"Ö h•†7®¨A,¯,-LMý{ AÜvÖª²,/ttt,>|øàm·Þz{g¾Có㾉õz“âê ©¤Œ¦é´µ‚ÔR+Ü,|9ÎZ·ÂH …"»ÆÇèîîŠg$àå¿þ®ßø±ËÁïçm4ì;‘$I:Ð\^^þ+àÌ+^~Ç/ÿçÿð¦EؤY9 IàT*uæVˆ¤#»®! |Ê• š¦Q(ãS/€u᳞!KrdFM‘eC×{"!®Íes· ½&JŽE­fUU±IlÇ#p—QÂ%@Æq¢uá·O>­v÷Xø±CkI–Ö+˜µzM×Ù³{7+Ë+móôŸ~é—~å3ï{ßïFßUÿjÚvØïwcÀÎ7þÔ+w ÷³6w‚À-….AàÑhÚ¬¬•Y\*²çÈ+H¤²Øv“ Õæ8. ˆZˆÕ~Ûmný/}éK?ì:ް,kDÕÔ=Ь¤tUCQøª¢É2Åb1é—•„"Ù$¹Ž~ kk h©vâ9ä-ÂoÏ>´#ˆfP(èê줫«‹J¥p³ïû? |áRò{[™€MiÞ1z®<4~çKn{qW£¼ŠÛX$ ÂÀÅ÷}*•:+«e\_apì ¢0 Ñ´Qd™z=ή !ˆ¶Lý¶}€84ó}Ã4”ÁÁ ƒàÕŠ,_-#¥¤V¨ç¹®ëâ86¥r©ùØÑÇ'ÊåÂâáý£’ï”Ø½ïTÍdemÓ2‘•xE’âaÖ…ß~^Z ¢(¤Ý­Üh4^ïf £è'.5Ï·ˆKº:&Àè«^ñ²kòù4Nc…À-…aèÓlÚKuVV‹dòCdsÝøOa܅ܶÉâÛ\±“&³ºV`xhIV¨T*-aÔ)‹biyyõôÄÄC?úè'þéÞ{ÿdmmí©Ÿzí†êJçØä6–hÔ$‰õ0OnM,É-áÓRùq€!ÖFqÃl”*r¹,éLš(¶UßÿÖ·ÞÕw)¾ÝL€BœçÏù¤©yñÍ×uûn Ï^%ôD¡ï{Tk ÖŠU*5›Ñ{Q5Ïõbo¼¥Z£ÏpþÚÁ0t‚ DÓt9ÂO<1÷èc}%Š¢•0Š– …Â\EE@ÍwtÝð[¿òº×]{¸/ñõ‡Oqûþ ¦™åÜù™V'±±¡Þ/¾Ü¾D¬6ÌQDF Ï%•Œ Qs³s!:¢H¼ø_—ŠáÛ-õ¯çúó@÷èpï¡}{ÇiÖWð"Qè…!ŽíP,ÕY+ÖðC…Ž®!D„!²¬à¹ÞºÍ‡ˆvØ·ÕŒ/MÓéìêDQdxÑ7vÝóÕ{Ü/|ñ ŸYŸŸ0M£ç%·^óº7þØUoÛ=ÞÛ{nUã†Û~’|G7Çžx]×Éd³¨­Äϳ _j _–‘$Âh"¾ªµÝ]](­ž‰( ¯áÿ›£v±'ô]qxÏP*!á4Š„^Æ*¾aÛTª6µº‹¢˜äò½Da@$€0"ŒB6bý‹Ã¿­ eYxžG ®:|À|ùýÐÝo{ÛÛ~úÉcǼpav±«3qãîakŸ¬èÔ´QöÂulNœ8Ntvu¡ëúºjo‡~Ò&áËíËÒºàÃh §T×utÃ@ÔªH’tÃÝw½]þП|ð’DÛi |tGV•|§DØD"ÄóêuŸjÍ¥i»dò½¨ª;z‘ h©ù¶Ï·!ìØãÞD„h¥„%I"•JS«Õxä±ÇXY]åÀþýéññ±XX\byeIVÑT0ô8;yšµµ5 à»»Ã4Ö‹YRËû—[6Cøòz'T[íoA_Aày>VÂ"’Éä¡w½ë×zÅKÁôm€–ú—ƒ¸â—Òú²rÔœ8ô Cç…Ô›¦‡ë˜VEÕ-Á†at‘ÍgËi¿ØlŽ’É$®£01y–Óg&0tEUp]„ˆ5KËldsy ]Ó‘•Mo°sÑÉŸÚäø]¬Zf Š"Â0ZïJr'ûä“Çö¿ìewþÛ@‹b$DÂÔ:RIÏ.x5 fšç…ض‡ãa€¦›ëa“´½ç–÷¿Yø`,ôhýw›BM×ÉåòçÅ€¢($’ Ã@×ô8¬Ê­Î¦¶ÀãX¹Úìýo:ý­/Â[´@«[HUcÑÀ¶›;{/Ó·dâÐ ËH™z„ïñ<! ®Ðt|\? ‰“:­7¢0\÷þ£(z† Ø|ú£ˆ ¢u@´I‘ SÁj OiÕôe%þYneõ¤M)ßg¾¼IøÏ8ñQ„ˆÚ ×§Šåø{Dµj½ÿR2};Ôºb?@7MM7´שáza$ÂÇ qœß™„-{/·vm:ñê^¬×ÿ/va£:¸Y3DB ÃzC‡Ür+Í»Qékig_^ßn²‘ôiŸö ao€@Ä@ˆkqIÄÝË£c#ú¥büvl€ uET+|ÏÃqCÂ0fR„øA´në=ÏGDY’‰ÄÖÿì?oUÿÏü7ëš`=s·éB–Ù*|‰–½où«lÚÏI9~b‹ã·‚0$ŠÄºÆ õ9]]]½—ŠéÛ ° ²,Ṏàx~®Ÿð¨mË%‰J¥wŽußAÈ⻀c£V ZE Çá[[ø›S½qq'^K#µ^+Éíh@Z/C·^ÿ¯k‚X+´³ˆç‚d2Éý÷ß_¸T ßnØD•šãú8Žë…DˆPŽ˜éÕr 𑥸ÉbCª½î=›ølWÛik×ñc¶+{mÕ¾Iøòfá·¾8åµ4ÔfÇo#k4ÑÚŽ&ãz¹\Ž'žx¾T\Þnh{aa »Ruh4\7 iû±à#Öóû2ÕZ™Z­Šª*¨ªºÉ™›Ûo½ÙÞoœø‹“FR«‰cK5¯ç_,|ÚÏÇé¿ÖkÚÏ·;6 ;Üìømõþ%IBU¶ÝDÈf3˜¦¹r©¾Ý-DõRŦÖðp½jÍ! ñ/ <›óçΡ(*–alÙùû2€ç¢ÓßrÀ.*å¶ëø\$ü”¯¼žï‡öL±Úß’ñ{&ÂVEPQTUöm\×#ŠBt]çïxǹKÅì퀨u Ûñk¶R©6ðýˆbÙÆku ËJwÇ+%=¦ÎžFaèèšöŒðïÛ9|æ€MØäÙÇ®þáË[„«úuᅵ¶ùˆ¶ù™ ±éùv‡ªªT+UÂ0@×u‰DãCüÐ%›#Ü.hÇm!ñưT±KŽ8¥r=Nÿ6=*U]—ѵ¸óÀJ˜LMž \©¢j™Lz]åntÛØê²É¯ÚÉiCøòfáKR w›C?yÃD´œÅÖ°G,äVÂ'ºX ´¿póéWBP.Çc’–e‘ËfN|ôc]¸TŒß.€Xø.àNFõbÅ-x®m{„‘ X‰Ûº MEkeá,C£Z^äÔÉ“¨ªJ>—E×õõŒÚ³‡|G±ÐöÀ7„¿ÇË›bÿÐO¾¨ÛGZ÷.öôÃ(|FÞ¿ýš¸•<Þ)Ðhí4BÐÓÓéS§(—Ë—lÛÈv€GܘYšs‹Õ% …0ôe‰Z=v ËÔPÕ¸ß>iF<øÀýDa„išôöt¯o ÛlüfØpü¶tðl.å¶{ùäV±GÞôÚvèƒcK­=Ù#6LAË „aüÙŠ¢ ¨qv±X*†!²¢ÏeÅO—µ°L E–14Cið¹Ï|Ë2Ù9>ú,'«9¸8égàž]øl©ômnøhù lîó‹ž%ïßvüÚ ˆO¿ªÄmd«««qg1±™;uòä'Êå²)™¾ Ø0åÖÕ|àÑsÓ¶'ƒ½ $)"°Vj’NdRº&#èKñØ7ïå±G}½½ ì üu§ž™„¶]…¿^Ý»HøÅ¶þÜnõÚœôi×ö/ÖQ{$-Šk -ÇOÕ5ŠÅFUQð<—jµzök÷ß÷íWŸ=G´mÐ2!ñPFXª‹+µ•¯=4sat¨‡n! Ñôi4=º:’$,E‘Ñ •ŽlÈGþôÃÔjñŽÊ=»w’Ëåðƒ¸C¨ílü,6yí[…/·ì<í9ÿgkRhKÊWlœôà"3§|Ãõ°OS5Ûfmm EQð=•¥EŽ{ò}gÏž½ä÷2Ø6hQD¬*ÀjëªþÍß?=¿Ül^wÅ8Ù”†$ Šå&²,Ñ™O k Ñßc±pþÿó“€a>t€„eáû±#½Õ`#î—¶ _jÙyYj§x7R»›3‚íÚ›=ÿMê^´A°Þì¶€'£i*a²´´¼nŠNŸ|šÙ îûú×ø³ËÁð퀶¨+À°ZªØ+ïÿèƒ's;¸é¦›Ð4YË6ɤN.c¢ªñÞþ‘A“/|öÓÜóÕB’$Ò©4W9„e™ñ= 6¥|ÛªËßÔ»·înù–6…†›„/Ëòú–‘­Ž_xQÍ£Mk%¬–––â5¶ºÆé“O3qúTéô™ÓÿÅvìK:Ô¦m€MfÀŠÄÌJ´ IDATXJ_¹ÿìÙ?ù‹G§\y /¾ýÕ(J<ã_ªØdÒÉ„’J2¡Ñ øÈ‡?ÌSÇžBUrÙ,W9B*•Â÷ýª[»©CÞÔ²}Ñ\ÿzúwK¥-ÞlRÂgvú>ÈO¿¦ªDQÄÊÊ*Žë¢ë:‹ó œ|úi––Þ5sîÜã—‹çÛ -jk±˜#Aù=ÿý3Ç?ÿ¥£«×Ýþ³ÜôÒŸÄÐã¤M½á’I%°¬¹¬Š&—ùÐ>ÈÓ'žŽ3„Ù W]ud}s½Æ¿Eø­†ÍÂo'‡Úí][º}bÓÑÎ$Fâ"ïÿY@EQðƒ€ÕÕ5\7^œY*™™:K¡XøÀÔôÔ.'³·.Ò%b-0 ,¹^XxËÝ¿qôÜWºé%oà¦Û~œ„¥"+õ¦M"ab:²¢Ñ‘¸Í%>þ±sìÉ'ã ¥‰$ìgxh0nËî¶+wò3>žm´» yKÊ·öÝêøµkülv‡R©Dëõ‚ÂÚ*¥rùoΞü¥ËÍïmXA@œZ!ž×?,Šå•Ÿ~ý›{è¡‹¹ŽTYËXX¦‚ãØ¤’®ëá‚lÊǵ—øüg?Ë£?LÅݶýý}ô÷õ¢ëzì· LÏèöÙ4Ü!oŒv¯O÷Â3ì¾7?I‰5Êüü<÷ß?kkkA°ž}Ð4 Çu¿tß}÷¾©Z­ÚÒe¾OÍvj ÝBBˆP’¤¶C¸ÈFè~þüyå½ïùí‰w¾ùÆ©šß…$mͨzЉ³çX\©£ë&]UY⡤ÑhpàÐA$LÓ ™JP«Ö ÃUS[Íí¸Ÿp¯Ýñ³IøíÍfíü¾Ýи¾,Ë\8žGy„¥¥e\Ï£³³“}û÷aÛ[û;ºººç*•J³õ½/ëΞm €…€Ml tâ–ñ ؽs0e×WPY–1 •¡¡AlG²4ˆBfÎ-ðø“Ó\wuË™8­ƒC뉠0 âIâ² •N“ËfÑu ZkŸâhp£ÁS–%”Vú6‚¸“‡x%ý“ONO?†a°²²Â¡CÙ|{º(ŠH¥Ówvvv& …Âe_¹-M@›6™‡X²ªÞG:šõx±’$ihŒ ’´d²ƒ„e ( Hùl’zeŽ™3÷03ù8k««(²D´ßó)‹œ¸§]£9²i ÓÐX-4¹÷þ¯ó‰¼‡¿ûÛ?¦¸:Çõ×^ÃßðÓ¼îÇŒÝpÉd’ (—Ëœ93ÁôÌ Š¢v³I½^£ÑhpêÔÉØ© B’‰‡Ž\ÁÚÊ*gN¯WùFÇF ‚,äòÒ2–em>aÞþýéeuá6„¿>6¶ïÈ ]_E–•xxCQÈç2”K«TjMl'Àu$Iâ–ëGØ5’ed0K6c²V²ÉgL:²:Gù2ÿãwÞÉzçÏð_ü;vôñã?ö£\}õÕxž×ò- Š­]CéL¼;8™L‘Ëç™:;EµZ]¯8tY‘9õôI‚0$ÆÆÆQE­­b+h-Çõ"ï:`är3÷…€ö‚èT*í8¼o` Z-µÂ5ÐutÒ`um•zÓ£iÇÅ¢„¥síáä³&cC¤:ͦÇÈ`;z³¤S)\×ãï¿ø9~á?¼™W¿âV~í—ïFÉdjý„ÖëuªÕ*©T Ã4Ñ ƒD"A¥\f~~.ât]ÆÇw208ÄÔÙ³ÔªñjºÞ¾>:òy|?@–ezl6{1ÀK/7s_(hGÉ];Çú²)Ñå{Îú…t*LÀòJÛh:•šÃÎá< dY¦#gQ©: I\}x;G;èÏ¢© éTŠd2ÁÚê_úû¿dþÜ1r¹ü:|ßguu ˲0M Ã00M‹HDœ9u:^{ï¤3iö8@¡Xdyi USI§ÓŒá:öú{-¯¬Ïç6õ%Æ=®Bˆ[.7s·56-j'¯»æðH³:+·»}ËX4UÊå&¶÷6›ûw÷¢i A(ðCÁìb…|Öâº+̳w¼›„¥“HX¦†nèô÷÷²8?E6“ÚÒ.¶²ºLËlÀÄ4M¦§¦°‡¨¥â÷8ˆ‚ çÏÇ£ã²ÌÎñë6_QI&­ à¶BÜò‡ü!ëròxÛGÄ£E €ìí·Ý2´ÿp¦•¢R\ÀóÒ)b©BµáÒ°}êME‘9´¯Û £ˆZÝåü\™Ñ¡<û÷ô´4–†„td-lÇCö$rÙ,Οcü@„ªiûqÃFËJ ë†¡“J¥™››¥X*’N¥ñ<ÑÑQ::;YXXˆLªÂÈØ(–e†!†a¬ï/L&“T*ñ­hÂ0¤T,ô7õNâúÇe¡m­ˆÿ>•ؘ¦i¦÷îÛŸßuäûxÙ¾“zÕ›8|p'†±²VO¿Poxä³ýYl×'‚…å*MÛçÐÞ>òY‹DBw ‚tRDz4–N2•dyy‰Zy…t:‹qåÐqVVWI$, Ó@7 LËÂqf¦§‘eßóÉåó °VXö›±ƒšÏ366Šë¸[Þ«§§MÓÐu=j6›óŽíÜcæ%›~6Úî ÊŽã8ß÷?ò•#‡÷ ]yä@Ïzó7’{Üf ¯›4mÛñ©Ö®½bÓTqÜÓPYZ©£ë*öt“0U4Uaq¥Ž‚DBÇBR)I’q—¹ó í¾‘J9¾‘G$«+«ôtwc&†›I’™žšâð‘+Z'Üd÷ž=<úè£,--Óß×iŒ355Óú:°¼´ÌUW])¾vï?}bvöÂß<ùÄ·¬×ë—õ^°ý5@»[Ø%îZ.‹3÷ÝÿÐé÷ÿÑŸ=ñÞßýÈi»Y¥Úð©Ô\lǧiûAÄîñîxÖN‰sø«…=)vwÅ;zј_®£i –¡‘´4z»;c»/ÉLO&“J¬;iŠ,³V(!¦e¡:†¡“L&™žš¢^¯#È2ŒŽŽb™KKK­<…`מ=hº¶.,,Ïç¤å¥Å¯?ø¾Òh4ªÏƒ_ð‰{–ˆ×¶Ï‡ª/ºvg:‘ÌÊ«k5ªõ Û£Ñt1t•C{ã‘zÓPq½€Õb“á,½ÝYd5ãk,-WIXº¡N›ôööÒlÚ€ÌÊÊõZ‘djìÕj”ÊåxUŒ®£ëV"A©Xdu%®K  ¿¿Ÿ|>ÇâÂAà#Iýý}ìèïó ’L­V£^opÇw^+„h«†ËL/$,³Q^ê·ß¼·C6:µ˜©A¢H£ÞpÈÑß›FUd–ÆJ¡íxìë!™Ê£›Y×\ÏG×tU¦«³ƒŽŽ¢ÀF’%jÕ‹ 3$ ¾idG>cÛhšŽn˜hF|Oä ð™ž:‹nÈŠB:fphˆR¹L©TFUURÉ;wîÄ÷<$ |?àüùóÜzëm7&I]´W˜\fÚÖ>À¦:€Kl Nu¯?trÞRë9ÝHf†û ŵ»ùÖ±îé!Ÿ1ñý]SY\®¡* 㣨Z EK0¿p&ž¾Õ,9ddt YVI%$)‰® gOñòWþ$ºa¡©*Åb‘ååe`š&ºn`š¦1{áDŠ"c:£##Lœ™`~~ž=»w#I{öìæ‘GAªÊœ;wž+¯¼òÀwÞ¹x^n$¹­B­œ¹MÜ$RŠŸü›GùŸûØ…lZï|ñ c£#Ù½WìGUãòmi,­6èêH244J?ÒYX.bñŒ¡¦JŒïâÞû-ýÓ7¦ ùL&›6¬Âê‚ehR$IRí«_ùòü=÷Üs~dttð•¯zõU–ƒBV¬D‚¹ÙYšÍ&ù| ‘J%ãp0 QQß9N>ŸÇCtÃ`muf³aüÔO¿þvþß•6O­ÇÊšB)WÝ Pjö¤,®Ž÷ö‚¤¡&«%—B©ÎÎñArùn=I­b³²²Šij(ŠD:b``”GŽ~lzúBujúB5%I’Jêõ£¯zuue¥Pk4êà^yåU{ï|Ù÷]i%R:“ahx„ 8yü ôöõ]ôöõ±¼´ŒmÛ$¬Él‚ññ1ŽŸxš¤eÑtl–—ØÑßw'pY{Û´Ý}€‹© €-mb€½s¤£se­Îþ=qî]R’èV–¥Õï1>6Œ•Ìc˜Y‹ø¾‹¡©( ôôàùA83sþà8p\ñD­î>83sþh£QoßÏ/yêÔÉ•¥¥¥²ç{H²‚iYÑŽA!+233Shš÷$ŒÒh4Y\XŒwè{öìÙ2—0?¿@¾£ã–?þà‡».73á¤6ùí[°«ÄÙÁî„¥‰LÚì˜8»Æ‘#˜‰Ž'#ÉI–VÊX–ÁèØNP’(Z’Ù¹E!ª¦ 24²—…ùÙ…™ •¯¶Þ_o=Öˆ}Ž1âZ„ìºnó¾øwßLg2ýKK‹ sW\yÕU}}ý×NŸ=‹ç»˜º,ËŒŽŒðøÑÇ™Ÿ_àºë®!Š"öØõæzÚìÜ7Þtc—e™·Ÿ»Ü|}Á¶€À#v  ìÏæD(’’,qÅ‘ÝD’…jèx¡ÌÂâ ==]ìØ1†¢$p}™ ³°Ìø¤ºFoÿ(_üÂ_?D|«õQqô/®NÁäÏþs÷ƒDD6ŸO^uŕמ:ñ4åb‰¡¡!vìØA¾£ƒù…<Ï'™Ôèìì`hpó³s˜¦I­V£\)ÓÛÛ{;Ï^h&âÐP"^(iú`¶¿Zw¤±á>††AN ›Y ¥õz•±±$3ݨz†R¥Nam ÃÐeH¥³ä;º¸ÿ'$6-Eâ‘´2±(·¥Ÿ!vÔNç$¼Öß`ž›žYÔ4½†g''1-I–Èd2Œ S,Y]-Ä{Œ,‹»v­O)AÀòÒ2ý}½/}ÿ~À¸ÜÌ|!`s€¥ijnÿžþñ¥Õ*‡î$›ëBR“èF–åå5$"FÇö¢43Ź™iÂÀ‰û‰ÚÍêÊRszfú›­÷÷‰5KÀưê0œ$Àyb€€T«Uë¥ri:•Jqvrˆ? ]gçÎqÂ(dn~.î* #8€¡ë„­¬à¹sçéììÜcÆžËÉHxa }W-ŸK÷ÿ×w~ÿgSúc\qd?’šDÕÒD,//’N§݇@!ÎM!K"^1#E ícê왓'§œ™ÖûoîÒh7¥6€BëZcCCx­×E ó³}ý;˜:{§ÙDS5‚‘‘R©sssAÜD:88@gggëV¹…¾ï]]]ÿÞòH’$•Xík{vö^óá÷½þWweŸ^&—Ëqàà„°ÐŒ ޱº2OÿùŽ>$IÁ¶=æç¦1M#Þ/d%éêæáo>ðˆˆ…ûlÔžT ˆµƒOœ‹¨³‘ R§ÎNÍX–eWÊefggÑ I’éêêd`G?K‹KÔj5dY&•J±kç8®ã"„Àq\VVVèïï½ý’3ñ"zA@ŠI£Õðý·ïù±O~àmËhc'ÏÌÒh:ìÛ·‹®î$%næX]]ÂnV݇™È ¨&K‹ ”K+º†, rù4ÝäáÇŽ?D{»ôw§ö¬B•Ø<„€Ôl6š¦e9HpêÔIL#Y²£Ùh2??ª©ÈŠÌþûQÔù€ féÈçoùïïÿÃËn{lº`H¾ú¼þC¿÷˜º’›˜˜"#\?äð‘#$SÈjIÑY˜ŸAQ$Gö!I*ŠarþÜY¢ÐAUÃc‡8nzíÄɹ£üóyÑÞaP#Ö>à¹âб¼®œ>yÏóQU $‰‘á!TMe~~>^„ìÚ9N*™juÉ\¸0‹¦ª]©dê²¶…mk\t#©Î|.yä®·¾þ'“ɬtáÜ~á8>†nrÕU×F ²ªãû>+‹3är]ôíØ…@"ôç¦O£µö(ªLOÿ.NŸ|òñÕ K­üçh€vª}‹Yছ_|ÈÐuò¹çff¨”ËhZ¼º6®æ™›[Àõ\$ òù<£##x^ljµk…·?÷œüö´­ÀF?`è}Ùmðú+®lºàßh4múw 2<2N($Õ¤V)Q.γcp©L’¬Q¯×™»0eÈ2$“:º‡¸çžz”X/Ô.Ý ìïïï¹ù¦›vû¾O&“Á¶mΜ>…išˆ’É££#”J%VWãU0Š¢°ÿÞx ~á{>óó tuu¾ô·ÞýÞËn[lºIœŒ~øè„˜=7éëzš0’p]ŸJ¥ÉÁCGÈä:U³X^:ï6Þj¤5‹¹Ùó4ê%´–ýïì V+‡§ÏL=D,ÐîPf»M-Iœ ⦛_|°¿¿_“™d:,+?~|}ª© „!óóóë÷Ø»w†aà>’ çfΑL$öèšvÙÂÁm €M¤;ù…¥ŠzâÔTIR4‚P¦a{¹ IV‘三suyÓ4Ù1|€öh¦Ï>$‰çù(²‚††Ñ4…Åxù·ïû ´–Wë㪪vš–ùâç–•ÏN/´÷4j.›”©NV–Ñô$‡¯¸E1ˆÂÂò$ÉT†Þûigr§Îµ’ëè`tlŒL&ÉãÇ)‹ë~@O/ù|ŽùùlÛ! C’ɸoÀiMÕëuÊ¥2]—É lw´Ýã]}ûлîL˜šqaö=½CŒïED «:®S§´2Eg÷(ÉT–ȯb×–™öq¥ï{¡vq¨]h´žÓ‹…Bá“ÿó¿þÒ—¿R§§·—ZµÊéS§ÐTI@"™`xxˆb±ÈÒÒBÄcg##ííáñ °—–èèì¸ýî·ÿü%·-6eM@¾éÚ‘›>ó—üs#ÙôÙ3OR«9ì;x5Vª$P)¬LÑléêÝ…L„š,/̰¼xUÓÈD*<~lê!bá}/;y"bS4LW kÄZJ/‹kŸøóþí±§ž*ïÝ¿<~ôhü¶6Š à!óó áº.ÃÃC˜º¹¾Ítaa‘T2µGU”ÿZ>~7Ú–Ø$üyù_÷×ù±_êÏ&&NÜ‹ãF„‘Ì#×·^¯°2w!ùî!B¿Ž„Ë™SÇðÜx27 Cz{z™žž)Ìœ_{Œïýû·ÓÀâù„Iâ^*±¯¢/.,œ{â[?ÔÓÓC*•âøSOáû±Ðß×GÂ4™_XÀq\? —ËÑ×׋ï»DQD¥RÁó<-“Nßñ¯ååw£m€‹Ò¿]Ù´yà—å×_30²KŸ›ü ŽÒhzV–C-D‘oY™ÓÊ‘Ï÷à»e<§ÂÙ‰S´ïE‚ŽŽSg'këwãþ^·rµÓq_â qƒˆM¬Q´+¯ºzÀ4 òùSgÏ2?7©T’žžnVVV¨T+qǰª24<ˆçÅ[L]×eum®žîÛþµüün´íÀFö/ô¼êå׿âÆkÇ®ª—–±›M7¢R­3²óÝDA4©ÏQ*Ì‘ë@SB¯Nµ¼ÂÔô$†¡EM×HY*|óģĪû_Jm”‰ÍÀ±?$S©ôK_rû.DZÉd²¸žÇ·¾wš…A¼$¢·¯ÛvX\\⃃ƒ¨ªº¾Nfqq‘l&{ÓÞð¦Kn+\´  =zt"º0ù`$É2^(cÛµºËÞ}W ËW…Ðaeá ŽÝ$ßÙôÿ7w®1rgÿ3çÌåÌu¯^¯½ë8vìuLÛIIHbŠ ­T"@m„@¡Ò!øEâKE‚ !ÚJ´´G¤MRhÓ¨©cÇvêuìõz}YïÎzo3;÷Û¹½çåÃ;³»IeÚ&ï>Òhw´³šgÎùÏó¾Ïó¼Ïÿ/\Ï^S»ðÚ…§qšÍª¸:³|¬ý–„“¯“¡´PYŠx÷ºç¶±±½qß÷H&„M“ñQÿø¾ÏàÀºbii Ï÷ð\-ƒƒ¤Ó©Õ£b+…"†aôF£ÝM7ÚÖ©¶EÌåéåàä©·ó°q|ƒZ½…Ô"Œí»é–^ש°²xMÑÛÓïVÑp¸85…ë¹m¨€­[2\¾’Í^›k^àg+ÿÞÈtÚjçmŸC¿ü+ÝeY!Ý OÐÛ×Ëø™3ÔkjxÔó<2™4Éd‚\.G«ÙB´E†‡‡q]—@Z­&åJ…ÞÞîv7#Ö}@ ^ùÞÙåjq×3)–$R}ŒŒ ã´J~»¾Bni†˜•!‘°ðÝ*­f‰k×f•œl[j6•séòô ÇGÅÞf ¦PÑÊ4 馓)Ré–e‘NgÈåsLN^ ¤«ŠŸa˜ P­Ö(YR2<< ´ÙGE@¡P §·ç—>ùÉGº–n*¬+ÿz¬IÈy§Î.å®\—ޝQ(ÖØµ{/VTÇsjH¿Iqe–j­DOo?!ÝGø *¥®^»N$b"I4bIŽž?ÁÚY¾b½Jºý¡Ùìœ119ÉÁC‡H$“ŠrÎó9qüš®·™E%ý}}!Èåó«¿mÛ†‰F£kUÁåq+ÞÕtpS mT«‰Ê¹í+3…âÜR­V¯Ö°]ؽ{Z`#Üh’ÏÍ´Ó©4R4Ñ‚&Ó×f©×›mú•€L*J>_n­Ë'¸yá?ŒJUc¨Ì%ôâ‹/üàK_~|fîú<÷ÝÑX+g||œz­F¨ÞOo†H$L>ŸÇq]|ßÇŠÅèÇõÔ!‘z½Žãzf"‘èZ:¸YЙn-+fJ¥"KËËèF”;vï Õ("DÇ.³²¼@È“NÅðì*ˆ&—.ga$àû½q®eófüin:ì%†UhÅB¡üܳÏyòÉ'¯”kuöïßO*™äâä$ ‹hø¾O4%“ÎP*•¨×êJB.bhhá „¸žG¥R¦¯¯¯kéàf¬ÀÜCwíÌ$-#²°chh˜žt Ï­ø šµ… ‰Dœ¨ ¾W£^/qõÚ¦iJÓ7sñòâI~öòïÿçc UʳV4õzëkÏ=û{ꩉdFõjÕ*çνӞ hšNoo¶ãP(Râ¹.ÃÃæðš”äry’éôÿØÇ»’nVtš.: öïl6J5víÚAØôñÝR4)®,ÒlµH§âèÒ&ð E² %ÂáP›ŒÙÀIÎ_Z9ÆOú÷'Y§/°ˆ*uÊ û¾/^øæ‘£ß{í»çöŒoŸ:/„’‘ª¨k:…bßxžG:"•LâùŠÜªR©`„ŒÞH8Ò•e`3 SÖóçî8ð‰Ý¿çÚÌÅÕ¯¼ ½IDAT4ؽsÏ®"¼­“Ï/#„$“4ñ½:—§W°m]!ú2ËùJ!»Pz?åßYg³ZF•ƒ§Q=‚: !)¥ÿæ±7O›‘°ÚÂø™qÊÅ2Pé`t“ü~—m*hª¨"£ÛÒ?÷WýæŸýç¿üùïºcÍÍ/‹ÇÙ>œÆi©üßn•Y)”‡ 1×qð<Á¥éD ‘høB’IÇXÊOÊï»ü{#{oYxµØí÷0¦.Næ[¶SÞºu˜Å…yffgÐt _B†A&“¡ÑhP®”‘R‰L ¡iúªÀdny™ƒ÷|xëMòù]¶)ÐüX÷»klèÀ7¾òØò¹ßz°\˜åò¥K”+;¶‹xNéשUKTª ñ0º®P©9Ì\/ m‘&TÜäìÄÂIùÁÊ¿7²•…  !š“¦wî¼Û¶?s†®˜ÇeJ&¤T*®ëÑ××K$i R„ ‡Ã‰.ø¾9€J¡,TAeûgÿSŸ=pààÀÒÜYægi4-Ûcçhºl­¦ÅbÛñIZ„xB°¼Rga¹†i†A@,j"bn±r3Ê¿7²:ÓÄuÔ†@†£±uÛ0f8Ì;Ùj©MŸç“H$1 ƒr¹Œë¸á GèííÁó¼véx ¦ié‚߀ua? lÝ{ÇŽ‡ùõüF¥8O¥”§Þ¨54MgçH§UAxM\Ç&_l"ш[alW %\š^Áó4 „IÅ(«Ù«ÙêÍ*ÿÞÈ:|†uÚ!ÀÛ}ÇžÑG>õÈ¡ÜÒ"===LMNRXYY ‡M’‰µZf«©$å5ÁÁA„ð1M“¡­CW‚ x©No8PÍ uÊvÛá_¸ëp¯÷öõaY–¢J&™ËfY\TiGÆÖŠ[ØŽÊù;u‚±}wrêäɧ»ä3°ñ€µö¯Ä_ÿÑs_yúh6´äåJ“Áþ8a3„íøx¾:V©Ù„M%ôèz‚ZÓev¾ÄGÚ‹žýË/¾öù‰©å·X*é&kGÕ¤ J¥Rmbbb1n%ˆ'«óŽëpáüº®ã AH¬XŒ@¨)a)B\|ð¡Ã¯vÑï @§šÖ@SŠ@õ _zýÌë?8–ïI™T›aF¶&‘h¸žï”*6¶­hàƒ@âx‚z£Å}‡åòJëÛ_øÇ×ÿ6_¨£Š2›Ý@ç$SÕ4À9~üø¬D2´eˆaŽDé!.M]\U2÷=h4JÈЩ׸®‹aÄñÿúã?ú\³‹~o täa—QìŸ9Ûö _üç7Îä–¦ë=½·Ð²\7Àõ•š‘p× žç×ÿû/=ñÕçô¤/‚+´eçQ»ò®ny÷Ûz°éSSgO:M8ãö]»±b1b–ÅåË—©T**‚P(D4¥Ùjâ*`”žþ¯>Óe¿7ëR§ŽHôŠ+·¼R_|êÙ·ÎlÛ¢ûDFh¹¾çÑr|*5M×0 ]ó™É–æþæñþÝ÷ßœ>‚*Ç^GE“*ï¶ïz2©: 0&'.dÿéñ/¿ôòË/ÏIÞ{/##£ä––¸zõ zû¸º”’X,Šçzض¦éG¿ý­—fºì÷ÆE¶E¢;‚ ´Å!s:[}çµs‰þƒ²K›£Ñt¨7\â1ÕáûŸ7fŽ?ýÍñ·moŠ5ž¿ÎMèö7½uÈ£ €"+€ˆ„~êÔÉS§OŸ:»}ddÛ¡{îýÐþ»ïÞgFÂñ¹l–;öìEÂWzB­–-ûû®ûa mëE¢MÖ)…¿uf~j°ÿ­äßHì±jµ+@Ótï٣玾üý©ç¥dµÞQ-ZŸî®ùïµN$«¡:‚*¤Q5Žˆ”RÌe³3sÙìLOoï±îàîìÜÜ€â Ró†i iÚ=Ï»%2²Ú-V+¿¡½gh+p;0Ü éƒþö¡‡î¹÷þ-åÒ2 ósÅW_¿úÕ©«ùï¢ö9Ô>âV…ü³¶ÆàjM•ô¢ˆ$2¨ÌÀB[Â4ÍØØ¾;w<ðÀƒûÇöíÛ6ÃÆââ"V<ñ‡ýÅŸ>q+üÞ,)e iZ'#ÈÓV L!‚àë/mh ý«‹ùæÊÑWÎ=±Rl¼Ý~]g§ï²Ö€Ù“Rúš¦5PigÎ4 ýíG‡{8ìyž{î³'&ΟûÚž±1ýðáüÚÈè臅ð_¸U>ošбv$ˆ¢¾=ÛQ‘`Ù6”²*5ûJ½á^BÝøkTm·r½ÿ1[ß#xÝá7L¡¢Á@ûgµÌUPô³ç¥”•x<k4­[å÷¦¬2‚FQjl?¯²F×Z¦½Þ·£Çy«ìF×qÙ•‰úæ'QQ ·ý{“5¤†¼Å7dSX¿ž¦PûZ;êæËöë7ÈSe?é:®B‡îÖj?* 4X÷yn•mf¬ïtÎvŽ‹û€X±6;`õ3ÁBíçpóþPlP™E·9IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/password_fail.png000066400000000000000000000442321217176075400245570ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 3/ Ôº IDATxÚì½w˜gyþÿ™vzݾھ«ÞewÙr7:‚ÁMn!$’LIH¾8„ŽùQ“ \-ËÉ–Õ{]i¥í»gO/Óç÷ÇÌ®Ž… †ã ½×õ^g÷ìÙ93óÜïýôwÞ ãî»ï–÷îÝillœ‰Dljٶ]ŸËåEQðûýB ÐqUU˲¬Œ­X±|¸©©©òÖ·¾UåÌø†ð‡úâÕ«WËŽã̵g¥¡ëË ]Ÿ§ëz·$ŠaY–Eñ‰²,ã÷ûPdYQüƒ!A°Q4P ]ÉåóG Ãè]ºté¡={öl_¼xñ^Û¶Ó×_½}FÄo0Ü~ûím–e½¿R._W*VJeIÓtÀï÷á ‡BCA þ€Ÿ@ @("‰‹ÇˆF£„‚!|>0H0ÀqRòy§\©¤9²;¿˜Ïç_TeÃ'?ùÉÔqÿpûí·'-Ëúh!Ÿ¿;ŸÍÅ5UÅ4-,Û²,@QdYFQ|ø| ¢$!‰ŠOÁï ‰D"ÔÔÔH$¨©©!î½Ö×Õ‘¬©!‰ Jº®sìØ1öíÛÇÐààıãÇ_…BúÓŸ>vFô¯#V¯^½¼R©ü[v"=W­T°, Ó2ÑuM×0LÇvÙÚ$IBA@DIB%$Ir¢Èø|~b±(µµµ455ÑÒÚJww73gÍ¢¶¶I’ÐuL:Ãøø8¤¿¿¿8<2òl¹\~жí_Üwß}™3øý U©Xüi6I˜¦a˜¨ªŠª©hšŽi™8Žƒˆ€ ŠH’„Ïç2$Iˆ‚ˆ Šˆ¢€ ˆˆ‚€ ˆ‚è^€ ¸Wa;H²L0$ÐÒÒJgg'míí465â÷ùp€R±H6“åxÿqúûû‡ÇS©èºþoßûÞ÷vŸÀÿ¾ðÛÕJå™l:Ýmšš¦Q,•¨TʆÈÅ»z>ŒÏç³Q( ¢8(Éò¸$ ¦$É9Y’*‚ 4Š¢ˆ  Ö²¬z]Óƒ–iʶc#K2‚‚ bÛ6†a ( ‘h„iÓZèèh§±©‰@ @¥R!=‘f`p@TÓ´þîw¿»ñ þw„²-ëËÙtæÃЩ¨ùBžR±„i™H¢D  ‘HàøË¦imyV„Mš¦õŠ¢˜‰F£Z,s¢Ñ¨Fíh4êF£D£Q)‹ùE‰–ËåvI’:DIì>Ò{da¥\žSÈç»ÕŠê% Áq0m ]×Áp$Ì´iÓhii!žH Ë2¶eQ,•µÆS©Ÿ†ñùï~÷»/ŸÀÿ`ܶzõ›õŠúŸåb±FÕ4r¹ùBÝ0ð) ±hœÚºZu"“~`ß¾}ߘHOìµLËüŸ|çþ¤P09~üx×èèè9ûöí;{hpðü\.×c™¦è8¦éÚ¢(L&inn¦¦¶ŸâÔŠJj"¥åòùÿ´mûï¾óï;€ßaÜzë­ŸÕUõSšªQ(˜H§)‹H’D2‘$žL íÙ³çæÃ‡?þû:‡ÑÑQa<•ªÙ¹cDz£G^z¬¯ïªR±4×4MÁ²,tMò-"‘(õ $qü~?’(QÑT2Ù츪ªŸ¾õíoÛ>€ß·Üò€¡ëÐ5l.K*5ªª„Â!šššÍ]»w]ÛÛÛûøëy±=ôPÍáÇÏ|çDjâC×ëLÓ5JMÓ ‰PWWG<Ãï?a'K¥5¦eÞõï|çè¤ß×—,Yr¹cÛË-ÛBU5*jHÄãè†ñЖ-[þñõ¾ØýèG•'Ÿ|òàêÕ«Qü¾Ÿ[–5jÙv«$Jµ¢(P©TÈd²”+elÛF@@ñ)øe†ã8×-\´hßÖ­[a€×0n¹å–Û Mûši˜J¾X “NcZ îíýøÞ½{ÿùpn½õ–†r¹t£eÚw¦Õ¡k*ªª"‰ñxŒxô¡Ý­«êW-Ë¢T*£©*ÁPGàé'Ö®½LSUç÷}á_¾`EÇÂ% g]=§'¾ÒÁZnÛf¬P¨š¦"Š )¥žŠedÂdt4E¹X@×u ÃÀçóQW[K}}±XUU±HÖÔá86’$£(2’$#I’.IÒI׈¢ø$I[núàœÓ·Þzk \*½`[ö2Ë4Ñ I’‡#lß±ã-;wí|ä÷p=ÀôÎÚÚK/˜þ–ËWÎþ@$,ŸË—•RYEÓL,G"‹£øãXÒ4Pš(©é ¹\Û²0tá¡AòÙ,†i ih¨§¾¾žX,N¡X ¡©™Ù³ç’Éf(Šèº†m;SájI’LI’Ö÷9Žó³›?ôõ´ÀM7ÝtA©X|RÄ€íØ¢€")¨º~èhßÑK7mÚÔÿ¿AíÞµXuÉ@íM²òý—žßq—ã3õ§›(bX25µÍ44wÑÞ1‹@¤‰’&R(éä²Ê¥>¿B}]= ø}~öìÞÍÏ~ö™ô¡Pˆæ¦&CT4• /ZEKk+†aP*•˜HMN§)W*8Žƒ,Ë‚€ã8»ÇùŒã8?½õæ:§ n¼ñƻ˥ÒWYA@Ý8¾ìó=Fßù•¯|%û?8 pE’Þóöó¯½ñºóïÁ.,:x¨‰L¤±šnB±iHrA b˜`n0Hñ)ÔÕÖÑÞÞN²&‰ã8  …"¥R‰#½½<ûÌÓò9DQ$OÐÚ2ºº:A¤P,1oÁBÁ ÑH„P8„$I”Ëe2™ ù¼«JÇAÀqXã8ÎÇn»åC{þ¨ÝÀê±cÇŽ—,X1uýZ¦5 …È “l°Xqõ5×>öØ£Tþè`rÜpà LOL|Y‘å˜,+ˆ‚€†aËŠòõh,úéûï¿?ó*ÂÁ›o¸ò=_ýÒ?|Î1Õ`vâ8&ÁX¦^$?qTjŒ@|3Ïz¢¨P(ä]C.¤¯ïã£d3Òé4Ùl–l.KM2ßïçСà º†¡O"ˆ× ˆ>†û€h4J[[õuu”+B‘]Ý=8Žƒ$Š’€$ºM‚Wà h¨¯§R©°{Ï>Òé ¢(lqçê»î¸mô´€‚³2™Ì·‡³dÙ+üLËA8 …>eZÖüãÛÞyú€½úò³®ýÑ¿ûO¢@(Ÿ:€eiøƒTJÔòä'26Š/D6›Æ¶¢‘0GúŽ“ÏçËrk2™ ‰x”r¹ÌÃ?Âîݻ͡ÁÁâÄDJÇ1äd<llˆë¦áó×"+nbkK õõõ¦‰(+Ì›¿Ƕ]á ¢$"‰¢WÚæ^Ÿ$I456€ °yË6ÆÆÆ‘$à)ÇqÞy÷«s´* zìܹsxÙ²eÿ92:¢üþå–iI‚(‚ã$+õ¦e­’e¨P(3MSj—-ž±êÇ?üÎ?FÂÑX.Ý‹¥çQüIÊÅã” ã¤R9ŠªŸ¥+o&IÏç±l›H$ÌáÞ#‹EÏ-³q°m›ææ&æÏ›Ëã?Áš5kŽíܱ}O&“I†¡†¥å‹š–Í•LÇ*ùÁ°FH8B0ÄÐ ÅG}Cã”—#Š'„/ ‚ûžä‚ R©‰Dhok%›ËR(¡˜ö‹ÇýÙi€]»výýýO ¢ø\0œƒã´º¢‚»*l§£¶¶öýÓš›/1-[ ø¬øþÛ?5s朶ìDFiQ £–©”òL¤ gXxîõ4N›N¥R¡P,‹Fè=ÒG¹\AEœ)ᛦIë´ilÚ¼…oûÛ/lÙ¼é{¶mïÆ 0Ë4+›WíiÍ-¡P(, „#aBÁ ù|žx2I²&‰ x‚¯¾$I^Y›è©‘ŠZ!ÓÒ2±ñårQ]ñ¦+ó¯ùÅK§&G*•:>84øï‘hôx0œgFmyE¢‚O’;â±ø•óÌ»òÆÞ3MײB9{A’Ñ+èj‰|¾ÌѾAêÛÏcñŠ«‡ÑÑq"‘0ƒÃC‹%×(sl&‹CdYB¾ÿýßóè#Âqœ­@/ÐçÀôì'™¬‰÷LŸ‘pd‰h$â|Š ¢ªþ@A§¼IáK’ˆ$Tý,ЍªJ2‘¤¶&ÉÐð†aaÛι¯Zµö©uO¿.É‘7JDJ×t}Ë–-ßZ¢šÆŸ[ŽÝ§º¦¢›U¯½ú²XÐ/ åìÛÀÐòZ‰RIehxœŠböÂ+\PML +2™l–|®0ó"ÅŽãL¥|ú‡xá…çÿ?˲6ǽ¹xø°>‘HèK—.möû|˜–5U´::–bÑ¢…ôôt£iดïÑ>‚ຼˆ ˆÞß\ã0•JQ__ÇìÙ³ppb–iýÝë–{£Å¦wïÞ]xþ¹ç¾´s×®s†GGþºP*sV,_À;Þz9¥ÂºšÂ¶t -ªjŒOdé§sæEĵŠyJ%7§Ÿš˜QÄqœªi{p°,“ѱ‘¡ÞÞÃ% ìÍ<0TSS3²`Á‚y­\yqm²F1tEQ…B‹eÒãG‰„EÅç‚Ëq< ¸´/T _t£Ö“¡í8LL¤™ÞÝE}}Û#Wÿí'?õ®ÿÓéàÿáðŽŽ–GGG\{õ¥ÿ‹ð\Ç*SÎñL,³Œi˜ärE†Æ°…Ó—b™Ù\EQ˜H§ÝU︺Ä>¯‚®Ûˆ‚hüþ‚¡ëôôôH~Ÿ¯Ávœe‰xbe[[Û;£‘p—í8äóydY& SQuLmÉ\:·§„?¹òñÊÝ]á ¢ˆ€Ë ‚è‚ P,¢ø|Ìœ1ƒ±Ñ1ÇÁ²¬üå_~ü§÷ÞûûtÀ¤¿_ t=7¾ÿ-3ZÚ›I ìÆÔ²Ø–†iê”ÊÆRY†GÒÌ\x-¡HœJ¥ŒiYضªj®éØ\ÚŸ´Ç þüþæK.¹ä[šª:Á`°CVä™’(E|²‚$Kà€i˜È’Œ-ФÓi«££Y”B’P)…IÔ43‘JƒGí¸} ˆ¯þdïƒûž+|Ûvp€‰‰ êjk©««#—ËœoÆ5Àç“ ˜ ó†<4,žß}Ùª‹.¬+eÇÑJÃØ–Šej†A.Wdl<‹fH´v-¶LJž¥_,–<#ÒÁö„íŽIÀm*1 À/µ´¶¾Í2Í·K¢x–ˆp㺦£iªZ!“Í”7mÞr0›^0§S0Ô 3fŸ¬K\WOÝ&ÑmZq…?ù¾€Ûð4 7¿ i¥R™ŽŽv7:ê8X¶ýÞÓ͘ øD=t¾õÚË—&“QÔÒ¦–Á¶t,Ë \®ÎOK¶OÔc˜¦ebZš¡OédçU¦k¤‰Œ§&hokG%r¹œ'Œ"é´32::¾ÿàÁ /½üòO=ýô}©Tjçû¯»´Æ/«D¢ æ,¼ˆ‘á!JÅ¡Ph*ò'zK¢'|<ÊE÷=A<6r°-Èär$q¢±(¶««Þtë­«›N'  $Ãyá…ç/¯7´zeË(a[†¡“/”H¥óä :çÎBV|蚎€àZãµÚ.~Åø›d¿ß‡iZ(ž+·mÛ¶—7mZkÛö˜eÛ£¶m§9YSwögÿê=ïY¶ )ôüKû¸øÊÄé;vÔ«$öŸ ÷“„/zÂpÙá„:²±-lU׈„ÝDÔ@ÿŽãÔØ¶s ðƒÓ‚w>a Ôw¶7Ο=«›rq CMc[¶e¡VTÒ™"©t«âPS׆c[˜–…(Jèš>¥óÁžrû^iºSQ|ÔÖÕ"I"­­-œsî¹uëž\§=üèÃ?< øV­\úžßµdõŒîÆÆ¾q…³/ú’5õìØ¶ EÓˆÅãnèU„/L _0-ûwä êë꼚 Û¶–ž.¨Nö$€¦E f¶EBj)¥çq,—âK• ¹|…BQcÅÀ¾#Ø3æc;€ecÙV•¯²û÷J€C0D×uLËaÉ‚¹«¯ºêŽÕ«W_¿}ÇŽõÇ÷×Õ†ÎÑœ-J> J'3¶¡©vïÞ…tøõ;÷¢Ì;Eí“®ŸP%|qòwQ˜¼eWÀ:a”ú|>|~?N! gß¾úñ¾o}Ó>š»;§ÅeAÅP3Xf۱Р“bÑ _Ðh|x'ïø÷uä÷ï¢oçNóæcz4?ió9UîŸmWÂÆq\,‘H”B¡ÀÆM›gîœ9Ñîî®7 0:6Ž Ê(²‚eé>´ŸT*E0“aeM# Ÿx/?úÐ»èøæ}®{Çd7sµðÅ©J¨IÚ,wN¶ÍCALÓ$Ͽ瞿m¼ï[ßþc€àÀïeü"ŠDKKS\´Í¦êº~–å ëŲŽôŸ/³¨Á·hÑdÊâùðÃ"Ïž{’Îç«ýduPí„Ãa4Uâà¡Ãì?p¿Ï$KhšŽã2‹§6j4ÐÇ>Jè'?Ç¿p6ƒ£ùðÝÌøÆ}žxåÊwߪ2üNfO ضeÙSµ„šªÆ·oß1þ}­º7’è÷  (5‘°„^É`ê,Ó½iºnqàkÏ0£¥ñÂK’a[ ‰P~ßûPwïž´úNþ к=õ·j£PñùH$’Äb1QD× ÷ä$‰h4J]}=õ–Iâ®;3›ÿÞüpçí®Þ÷„Âú¯ZýÞŠw,¯`¯ZH–å)§µR)÷œn è¹€~  ú#Ÿ¡¦Ñu7ÊfYOüÆ÷ 31:Dó{¯ ¸d.±•—0 Üð~Œ}{±½lßÉ* zõÛ6 ì)@L¡Q”ðD£Q‰‰d’H8‚?¦|ëÍô-—¬¢ñÝïÓ¢ùÚ«é5JôîØÁ£w¬>Éúwoó¯¬xÛÆ±'A`MýÍ- ]/ƶ)ä‹Í쪂@ à Ÿ_±ÐÔšnbÙ?þÔ#Ùrœ! qþÙÄß{ hnßç—¾H°€ÜoÄÞ·§Šî/Ñò« œÈV3ƒí8ˆP•Ó‘ÆFqn¹‰ жdóï{¶nƒ /±à¯ÿš9«V1Ù¶ÜvËÔî&'‚>“«ý„°O€ÀqàæÜ ’ãV/wvuøN^9mò¹ ]GÕ,î¿çavn<Ê1àâK¸æ_¾ OýkýFŒ5ë Wáò§Ÿ¥ÎËèäoúö¾½¯âþÙ¿æw¦˜`*r'H£#ˆ·ÜÄ(0kñR.¿ï{°uÆÁCè‡záÅ—y×çþ•w^xG}Û¶ñ›>èˆ '~Î+ ¿)X¶íL1† ‘ºººÆÓ)(¸÷^@×tTÝ便ŒM/åpÕâ¥|ä _›Ð6oGݺc×Ì'ž‚¼ÁeO`ãÖ­ü嘸ãT~'¢–åž“»;šˆ¦ë$ ¶mÛV9]0i…Y–íTîûÍ¬ÙØÇà}óóOöWðò&Ô‘ìB«\Â.¹Ó)Ñó´çž…±,Wü×Ï©•\&Ðn¿ ì?IߟXñ'„É"Ž‘1äÛoaè\°˜‹>zly™Êðz.‡](`—Üi•òØ…<•ñqØøŸ¸õÃÜyÎùÖmÙÂÍ7ÝtÂú·Omý ‚€,K8ØT*eâñ@`ì÷I¹o ´ €ù~Ÿ|§¦›I€÷Ì^Àƒw|öUÜøþ« GÀÁï@`ábœ¦ž¾ù=LhA@ùÚ7°º§ã8–—s·=¡[S«ÜU(ŽŽ£Üyc@÷‚…¬ºó/`÷^Êå†_^M‡ "QE‚‹¹ýßå[/­`ÑâÅ|åË_ÃôöI4L Ë41McÊ÷‹6oÚÌDjœ æsõÕW]5cÆŒ5¿/ßû–lðÃÝ«¬xk›·-:›û?plÚL®TÀÖ-lÓÂ1ÌWL¯á[71u§ÿ8>)@÷Ÿ\ÏðÚ‡)šüâ1„åËqjjªb¯ ‰¢ˆ86Žtçj†®y ¸ôÆ;`û6 ù<†ªc&¿z'¦¡êø¹få¥ •Tö ôÑ:Ràù-/²òÍov >Ëvk, Að6ÅfltŒ±±QlÛ¦½½­ôøš5Ÿyñ¥sÌ x iQøÑ[âÝ‹ëÛXõΫyË9‹à±5d1- ¼:»WW ;°l"3gbv4±îž¿D×,D¬/~zz¼UoaY^} âø8ö]·3Ìš3+®»ví&¯•Ñmp¼})_õ\Ýâ†6m‡„( ,\ÄgŸ~Ž¿ü†q÷¤€Y³çñækÞÛ·‘ÑutÇÆq„ßê†98ø‡¤e•W²!PÏ‚KV²þG?å‘B/—_u5†a"Š">E! P,Ù½{7Ùl††úz4µ|ï§?ó™ý>ïo÷/º˜+®ÜôÂúºíϬ§ARWŸDyá—”1 ¶eà˜Úk˜:–¡£[&öØѲFë%o¢oïflÃF[û,]Š“H¸7blýOïb˜3sW®z3öË/‘.Pu ÛÔà5}¯ûYÛÐLƒX¥Œ4mkÇø×5r`çŽ2oÕùøƒá©=EFQ†G†Éf³˜–IKs“ó ¿¼gÿý}ìj Ùi( ôO~×s‰5ÿý0ÃÙ Í_HpÛË”K%7n8º«kíÔ l]ǰ ÌtŠX¹BÛ¥Wrtß6"†Mèɵ”¯xŽ$RsëMd–žÙ\{ÞJì/’ª”Qu[×áµ|Ÿa`뎮£˜:ñJ™@k+ßÑt®{â!³#4úÜså•è¢QDQôt¿JEehhÝÐÝžQØòÀ÷ø´¦iöéŠPNÓ’ORtÕ0:·SŽ>³o'G “wœ{þÝ;(iªk8™®@ì×0-Ã@³L̉qâ™<-^B.×¢UhΛ„ñã㣴ôÌàÍ —¡¿¼žñJ™²gTÚ“Â} ßc:’¡WË„›Ûù¦·?çn‡x^Ç,ÞôÎwb'ÃÔ´¶xnŸŒOq‹O‡‡‡)W*˜º" >tèÿ½øÒ‹¿×.¡7JØ¥1£ä°Ztïè?ÊD ĵç]„o÷VŠ•¢›<1uSÇ1 ïõÕ¦†mèh¦‰61N<›£öâ«)úfÝ÷]Â+ÎÆ|é%.ìšAåå_’ÒuJ†{L^ÓñulOíÈ–N¢\$ÖÜÊ·|AîØ°€y\óö·hm¦©³s*è£(2>¿ŸL:C&“A …<åвNW IDATRéðšÇ×|8“ɨ§\ãtBÈ24ÁÇ"F¢\vÎJÄ[(© ÛĶLKÇþµÓÀ1 ,Ë@³,ŒÌ8±b‰úVc]~1¾P„®Í;(>ó8ã¦NÑ6p,wÚ–ñŽ­c™:¶i ±Rš¦îÕpëËÏ0³£ƒkÞöº:éèîÆòÜ>Y–ñû|hšÆÈÈ¢(¢V*ô;ÊûÿfóæÍë_ümˆ€ä€iAСNêB5ÇŽ G¸dÙyÈûvRÐ4 Sw…eþæi›†©£›6 ÄÊr²ß“ë¨üè?-å(Z&¶m‚ùÚŽiz¯’©Ótx vÚº°¸³“7½ë:Ú»»éêîÁ´Ì©Äü~Ží0<<‚eYˆ¢ÈÎíÛèö¹çŸÿˆi™Îé§êÜB¶ƒÝò5„ Kyª¿9gÕÂeøî%ïàúç6n˜×{}µ‰ãv{– ƒ}žõÙµŒç3ä&¿ü7Ë:égÙ†˜ Ó’µü{C·ìz™f`AG+ßù.:¦÷ÐÑå®|ËrC¾>ŸÛJ6::Цi(>…}»w³{çŽÌ‘¾£7¤&&†^›ýF@õ½KH5,sNC¼A*iòšcèþWÌœ…ÿxã@W°º7ªŸOõ^ (Û6N!OZ×òÞ7Íÿë¸ý⓯“ûÆîX‚4µògû¶Óêéü ßýZzzhïêÆ²l,oõûH¥R¨š†Ïçcxpˆ-›7q¼¿ÿcGûú~þzÝà7*&«5@±Ý×`AÕÍEí- J® >?6„IrIköÈ Ã¸‰ÃŒú*sRpïói`Âû½Z°¿îÿUïóà¶0uGã<ÔÐÂ'í¡ ˜ÝÙÉÙ×]GSO­==S+ß²l$I²,Òé ºn I"ÙL†CöÓw¬ïëûöíýìëy£ßè˜ ØrÙ0­%]ur:-¾0>‚UÛÈ­02À„·‚×0'-NËeü©-FÓ´½ÿñãv¯ÌŽÆy¼¡™¿ïÝG0³³“åï}M=Ó™ÖÕe»GŸLûjšF>ŸÇ¶­©B‘áÁþkëÖÍwêºnžÀ‰a{@6AÔ SÒÀZÐÒR«¤ÓâÆñaĆf.kë 240¥ ~5cø¿HÛ‹Y'€YÑ8Ï44óÅÞýÔ=],yÏ{©ïé¡¡§Á+ë`óæÍnë˜$Mîæ^”,344øøÏ~öÓ?) •×;<ÿFÀÉ‹@6@,W*BÍ´&¥3ªÔŠ™;F‡5NcÕ´6²Ã”ªôó©(å·vSø¼•?#g}C3_ëÝï¶1wu±ô†hœ5›Ú®.A ÿøqžzjÛ¶mctt”ºº:š§5S)Ÿ¨ïEÛ²Ÿ}üñ_üôår½‘‡å©Û n]ü0Z„ᎅ³é—Ï£±%A ðÃm/óa°`ÁRê¼ 3¼iUQÉï2-oNnSÖ‰ñbC3ßîÝOƒ'üÙoƒ…)MÚldx˜­›·`Z–›æ›Ú?pŠâl›H4zYMMMøqƒßè* Ú-œl‰ÉŠ¿ööÛ¯["1UâœL™š¼Jjl˜HÏ,$jƆ±=ƒÍüY`RøŽgì%Ö`”ƒÓX{äÓ€ÚînæàF¬xœÏãë¤'&8ï‚ ±LŸÏÇÎ;ÝT¯ÏmÛÌœ1˲1LcjÛI’âçžwþ“kŸxüØ85¬ê9­¹98­1T'„ Ö^C몙ÔvÖáv¼ø,—\Áâ›ïd)Ðì)UÓ›Öo9mN”*Í Çèomåù£hâ--,¾ñƒ$º»™qιtttrèÐ!R©¶mGhjlBSUÑíZNgÒDcÑW”¥ ‚ „ÃáUgTÀ«‡‡«÷ö{ÎYÍXY‚H¨>J¤³†Ù«¯ un'Ënùsb7}á;_§îcŸa¦§³­*ëêTÁ«¨¢®š:¸çsø.¿šËÞq=NŸñvø¡d°ýcà>Ç€/|Žão½”Í_`0«„{ª^õªyÀ0½ÿöšC_úþuO0úüŠ¥Kwl§÷Å n§¦ÑÝÝCKk½‡SÈ»[Ó565Q“LNUþ”J%JÅ"ñxüd„€KÎàÔðy«?<½§«)qê ݵ¶ÍT‘ßü9e`ÖÜÌ7qè¥çyØí <äÍ G#ʤ.9i¼¿¼öô¿ã±Á~ ·þi.Xy%M‰ ÿoþšâþ˜†I4eöܹL¤ÓŒŽŒ +2Ñh”®î.4µ2µ'ÑèØÉdâmìîÃ$œ ÎàÕé?„—/]ÐQÎ÷‹–eaŒçéÿÜ‚À…s² ãÐæèó»&'ºM'ïÿ Ów „¼“©GqÈ=³–ó–Ok,† l¼ùƒöïC’$æÌ‡ã8?v ŸâCEzº{ª-~†‡† ‡B^pUA»ã\ðå¯~#x¿š zˆ_|Ñms\Hs¸¡xœpîü…Ì E8¸i=#}û=Á,Ü×2'YÀçAñ~½$ÒaË ÷Ì\µâf'HÀž?½‹ìîÝtvvRS[ËÐÐ×èéÐÑÕI0œJùNî_‡§ÚÁ-Ë"“žh8^{¯NCC=Š¢àóùìr¹<¨VÔu~À÷z¯®ÿ .  ªªúË®yñÆ|þ­a`é¼…Ì E9´i=iOøŠ§3¤ª¬n;®>èɉ!ç¤W«ê3²«Â“G,ç©Ç9çâË·m 7gè¯?ÎìoâÅl–‘‘Qš›š øýtwwÓÛ{tê,FGFY²d±óÌÓO=Ðßü¿¶oÛº¾T*åþ+ì²=Ã<7 ì›òù·F€es2×~ʳÞå*W^eõûªV¼àùùõÞÏJÕ1ä“ÔÂÉì x'uÌ2yz-ËŸKwM¨yà{4xe^‚èêþé3g¢ø”)wphhˆd2!ŒŽ ?¿þ—/¬-•Jù3¡àWgáRh}|7,œ3˜#[_d¾t ZŸÔÒ)&ža1˜Æ‰Bêψ'Í“1*Öpcö¹a&¨”Ušú3\SÃÜsÎÆçó‹E9|ðÅR‰`ÀµæÌ™ƒeYƒO?ýÔ£ÞW8gp ø´Ÿ ëkùsæÒ¦9ºcé*¡ùN¡Ó¥ª+W¹Ž÷ù6 -Á?c&ÑÔ¥*5"V€_ðn”+¯¥Ùx…¡ç;…¡ç?‰¦@éìÆ^±ˆÃ?ù) ´5³w~¹¦8ùÆ-m3)?™y¬ [¸WØRŽ<ùÅ@~Ó•SL œ"èT°¨Ž@CmÑåK8öăô~ó_ØúÁ÷‘Ž…pjj±¼¨`_ß1jkkgúýþ™§5¤h"HÖ­‹wõü}Ø}ð ÛžZCËÊ‹i …_Ó—NZqÕ>ûäÊuÍÀ9{)Ç~ò*@tî W.&]¦Ü’@lZÚfÓ{øÀÞ½½êÑ àˆ"²Ñ¸WØd}O>KΨÀåWÒèÙÂIB÷¤–&Ï­­~óæ°÷Ùg8V²‘€žO}šæ‹/$ÔÒ‚iš‚ÀÄD Ã0üuuu§wAȹkÒʽ{·TŽõ>,Áç ¨›ì{~MçOS(ò ·ïd£Oò ¾&@™9 ûì%ôÿ俨X™=Ðm¤ÏgRi©A‚Á0uí¼ôâ ·„€Å6}"l¾èÙ"}O?ËD¥—½‰:/P ªÁdùR{S+ÓÎçðú禚Ujo¹…вeÔ,_Nׂùhªæ=$BcllŒææ×ßxÃy«Ž¶ÍVàa?ü](j&×?Mó¹çRMNùô'Gë‚“‰Y³ÐfϦ÷ÁS1!8w&ÉÜA¡¥‘c~¿OAÉ_€—6íÚÀä³e€6‡E‘¶À½²È&?0ðË_’*áMWQ‹[-T ‚j¯£µ©•äüyìyz-9Ë}?½t9Å…‹Hœw.š$sæÎA’Å©z€ãÇû©I&/ø—ýrÝi €+ÀÖ`›!ð¨ÿàJ“Cž¡nÅY4Æk^AÃ’G͵3fQjíàðÃ?Ǥém$>|¡³Îâx@À¶TdYǤ½k>ÇúޤvïØ|ò½˜gqT„͸ ؆7¬'£àÍWSó* hil%<{Ö=ê¸Â¼ÿý¤gÌ`,‘@ŽD±L‹é=ÝDÂlÛF’DŽïG‘åºH8rÁi€kÀ|Ñak+Ád X19úüS$—.¡6^;¥b-³`1•Î.Ž?µ 0šbDîº ÿ’E(‹Ówd?Š,¹o–Eš§³ïö-ã9F&OÕç0Çâ°/_<&}îŠv®¸Š„‚I Ö5¶]8ýëžDõÔBÓ]wÑòö·£Ì™Ã`&‡¦k$“I:;:ÐuW  RÔÖÖ\|'rÂ=°ol8ÿ& P0 ÷—O=g9ÉPœ˜'.¸mzãO>N0š"d®=Ÿè9çXrÅb‘ã ýˆ"„Ã1jêÛX·î©—q;ÅO9fZô‰"›¹W’Ø"ÃkŸ¡èTà²7÷¾?YSOlÑ<­{Ðp÷ÝÄ.½œúsΣ}öl2™ ãã)$IrëçÌrÛÆMC7¢®®ö’Ï|ösþ3ðŒí# |†…ÃëƒÊKסÿ…µ®»ŽÐÇïÏþ3Æùç‘{î'("0½•ƒË[ˆ­8‡ðÙç#*AúQ*fP<ý_[×B¡µöèÝÀoh&î19"ÀfAà^Yb ÀГÏPŠø`å*â-­„.^EßKÏs\UpììsH\y%á¥K ÔÕÒÞÞŽiY NõΚ5¿ßïÆDè;ÚG8šéS”™gPåæÁ÷dUcÙËç”À.ÛäÇúáóŸúKÊûv€Fš5“‘7¯@m­¥ñ²«¦ìô#‡÷ 8:²$b[&ÓÚgspïŽã{eöðºÉ'A ÂmØé“ õÈ#c1øÈ'?´§¤6vt°I–±gÍÆW“t÷ümk%388„eºÍÎÔ××£i¶íÎdÐ4ÝOÄ/9€Ã·bg½Mj½`Gn;²ê Ï£?¿íù[7A[Ê]·25Ï£®±Ƕé;²¿_Áq@”dÉ&¶m]ÿ’jðš·bï6é=;v‰Ü_8,ZPñùк» —Av wÅÙ vv²MÓÊeQ›d2Iss£££KîseYfæŒé,*j…ÑÑQjkk/>€õ˜–— Ð ÐÖ¥ ùyÍ¿â,ŒBk÷^¬={°ÂBwÜM¹£‘ñ„ô¶¹ø‚ @&›`xàŠ¢`Û6`„`ÀÇÓÏm~‰_ÝJà×Þ¯·YŒüÜ¡ÿ§6O ÃoÖL¤æFìLšÒuï%3oÅöJŽÃî;ñûý8@ à§££ƒr¹ÂÐЉ'Àuww!I’Û?è@ÿÀ‰DüÂ}ì¯Ï0€ë›^H½h;öísJZjQëf$)?öS´[ ~üÏðµœT‚ã˜4µÏg2ƒøàvÊ¥,"¶eQ_ßÂàÀ±Jÿñ—xíµx“Èà8רŒü—Ì‹ƒëžH¾ñuv.YZÑW^Dýå—#D"ƒA¶oßîî$J8@[{+Š¢04ìnf---D" Üj•e¹6 \x.L/±Vò‰xXÅê8"žÖ@qÅ«.À?!ò¢ELŒ"‰Ñ8mŽ'W“ÞÛ°-·ŒÄ´LêšÙ¿ßÞÞóè©Ü¿_ÃHS•æ/AzƒÅðcãã[Ÿ9tàåÇ÷î{æ»wÇ[[éìê"‹±{×.2é4’,aÛ6Í $“ ‡¨TT,Ë"ÑÕÕ‰ªªØ¶M±X$›ÉR÷:©ÿ ­a“@(Íè®kúÞ7ï¹,PüdžP»:©¹ä"¤éø–¦ÉŒõR[ßI8Ç6òT £:°ŸÏç>,Zö‘ˆÇÙ¼yÓFÜMÂ~›ay@œ&68làø‘Gvmî}8•Þóø£ÇŸX›mïꦡ±‘B>Ïþ}ûPdÁP8D{{étš‘‘‘©'–vt´c;î¶õ¦e1<2BMmÍÅ·ßq—ÿt@uŽxÞ²Žó~úïÝÚÑ>°BAeúÂåDλå¬å¢‰±^Ê¥4uÓ±qÌ2£CG>ެ(X–M(L¶ìèÝÀ‰Þ߆‘&†CϙΑ/«‡€‘N§SÜÿÝÿÞ±sgvÖœ98À–Í›½«q±ÜÒÒ‚aZ á8î®aíím| ¯0xhh˜H82S–¤¹§+&…bW_6ï=?þá÷>ÙÖÜý4ªfcÙ"s®@$Á-mØã8$ëÛ°Œ"öí@×ÜÎ\˲hlhäÈ‘£G¥6ý×o{ép8ô[ólßðÐPß¶­[6444‰Dصs'†áÚÍMM„‡†PU Ó0I$455b¶m“ËåÐu]‰E£—žŽ˜L¨…ºx40÷ãõÉw¶tL÷ Z‹ªZ”Ê:þ`œù W¸R± ŒJš±Á=‚ ’É -‹®æ8|p“ˆvkñô>´9]˜z³ó;€ÀÀ-ö9îaÄ3T-@Y¼ä¬–€ßO2™ ÷ðaÜöo  ÓÐPÏØØ¹|˶e™¶öVtݘÚKp<•¢®¡þ¢Ó¢GûI á­W¯¸öÜe]KŠ™Q*å2ªf“Ëéè™KMm=¶YÆ1ËäÒ}d&HÔ¶ È–^$Ÿ£÷È!ü~¶í ø"A™^Üý2î& ÿSï$ y(f8‰^²êâéªZ!‹£é:[·nu ÓÝ$¢±©‘JEexxp÷ hmmE–å©íd†‡‡‰ÇâçÝðÿ·w­1r•çù9÷9çÌ}v×»c¼¾`lcbCi€&*ð£Bj#PÕ?©"RÔVŠÒª„Ô?¨Q«ªj I¥ª4)ICÁæ¢B!¨Ò´ÆŽ1x½Þõ®½÷ݹϹ̹~—þ˜3Þ ŠÒ¼ÎÖî'vW«Õ~çœç¼ïó>ß÷½Ïï|eÛ€Á~;NžaK³Ç™ Šˆ¨ßà¸!öø D‘D6@Ô*ø ¥1<X+Kó=.õXx6mÂólzy¡zü¾ý?­Bñ±ÑŒ,¾óŽ;w8°ß$$F&“†ª(˜øðL©!†(JX__GLbÄQŒm##È岈ãœs4š-Ȳ\L¥6·ܪ) Oþò³sUvêýꌉ ÇõÁ n=u@ã.¢ÐBcm‚(¡X‰l1}ñ"¢8„0ŒmËcöÒÒÒü²wW§™hŸª‘ÌYúµû¸Ù0 H¢ ÓL£X*bâÌ¸Ž Ž8Ž‘ÏçɤQ«Õà{>(¥P5 årQQ ß÷б,‹›»:¸ð§¶)ãìÍ·ÏVíÖ"¢XA«ÓE:[ÂŽe„~ŒxÜjë Ð<Òi$²á{mÌÏ/BEpÆÁdÓ*ffçN†U|ú–¬} f“heð(—É"›ËÂ0 äryÔê5LM]€$ö?YV022 ÛvÐlöšE€s”Ëå^ªHÜD›Í& Å¿ô¥‡µý‡?Øô;~ÿìzíÒô‰€fËÁÍ{÷ÃH‰ˆCœxh5a;mŠCDJº°Ú \ž_¦) Œ#¥)0uŽã§WO&Lþjq•\òQH‹KËòäÔŽÜqÒ™ LÓ‰ Nž8 A{Áà*•@)E­^¿Bü¶o/#•Jm¨‚ÕLÃÜÔrp+F€~©å%5wpi¡ÙZ^w×vDÀÞ½7C`hä€QõÚBRNåÀ©y˜›_„ëz“›žÏ¦P¯wüF«sò*†ÿ~÷X=©\¤W_}ùGßüÖß.,¯¬âîÏÝ”ž‚aš˜˜˜€ë8`¬·ö_(æ¡i*êõ:Â(!†®cxxQÜÛ$âº.Â(VÒéôý7(6Úúû†.#›ÍjëÕ*D9…[öî„ßmRaÐA£Z$«ÈeuÄ P3³K ¤·ßŽ†á¢‰ù¥ú…… ™»Jl4r¥ë|«Ùì<ÿýï{æ™g.u‡B6“ÁôÔ*•5@AJK!ŸË£ÝnÃu\0Æ JFGGA ¥Qò:(•J_¸‘0‚@tÇí»óCÖ*•FGË(ätÄ‘ Fºðœ&šÍÒi) ±×mãòü:Ec€( Ș*¦g×N}ù÷gÍÑOD¡AÓ¥ëºþ??ÿýŸýö·'3ù"víÞ Ç¶qîÜGW #AD±X@†h6›àœ#Ž"”ËeÈŠ J(ÎQ«Õ‘Éå>ÿàn»‘0x—Ú_ñº]4Ûn¾y'T…€D8õÐjô¼örY"ÀHÍf K•6TµWþiš Yâ8?Ó8ŽÝ¿Ÿrô×Ö1¨’€  BèË/{åíw~xnß`Œáƒ÷OƒP Ê((í)€¢ÐëFEÇÈå²Èf2ˆI Æ9,Ë‚,ÉEMÕî¿QЗEÊ]Gvþõ?·o~aŒËØ»»Œ8°Aã.hä¢^¯‚RŽ|F‰]€Å˜k HÏ(š2”òªu«¹Ti¿¯™ˆAËÉÚÀjÂ[(‰sNÞ;þÞiESùÈè6Lœ™@§Õg½rÐ4 †ŽV«… @(ƒ"+AG`Œ" ¸Ý.†F†o»Ð?ï¡oÏýÒŸ>ñ[çïþøË²Ë«U覉›Ê9„~¯þüÍ6TUFZ…!â˜bf®Ê88Ê‘ÏéX¯µN7;ŸXþýßÊ I:’ÿ!_œžªûAØ+c­²Š…Å¢B)$YF>ŸG·ÛEÇê€sÊ(FGG!=òÊ8G­ZÅ‘;?;v=`°°~ûÑÃ/>÷Äßý÷ûžNs³33èX!vÞ4]cˆCœ¸pì6,»‹´r6sþIDAT©B(f°œ +hªœøó Èš ÎNVNñO'ÿþ¼²0 PJ½©É s»wïA˜8s’(β™ (ãh·;`Œ!Šb”JEhšBHÏpŠ3¨ªš¾ž cÀ“á±G~ìðá#ÃëËgQY]D×£ðƒ»ÇK¹¥ükµ:B‚Œ¡RŽ˜RT.*UŠ"2=¥€ƒÒå5ëøU~ûœ„dºð©PSÛ^†¢ªøè£sð|¿Gúb‚t:E–Ñét…(%ÐT Åbq'Òñ6(Šrìz@?ìçŒí¿eç½üÆ~Ój­Âj×ávœnA±{G¡oÆ¢0@½åC€i¨" Ι¹b % ù¬ŽVË^º¼d_-ù÷g L~·¿6°÷–}ã<üȵõ5 \œšB³Ñ¸r4\UdÒi8Ž Ï÷@)### ”@QŒŽ^bŒ½v=À@ï4÷öû~åöûLªïTa;\/„e(ä ²"¢ ‹˜t½ͶM‘ ªˆ )æ{Uç@L 9+•úëv5l®#W_èÛ Æä¯~õw5ŸËÊËB&“mÛ˜žž†˜”ƒG:“Nj~;‰ 1†J½#‚CCCÈårGï±G»×#ú¹?`üðíû‚Åpíœn·Á²ìÚ‘‡*AD†¶åÃõ"˜¦Æ9bBaY>W{ù?)Jy7Îþ³ò=l8mæµ÷”íÛ·䡇Ú³¾¾Y’¡8ç˜<Œõ¡iÓ„¶mƒÇ0 Ùl;ÆÇCI’ž¿^… a ÿç C/ß÷ùÃã¶Ÿ‚ípº!œnÊÆË9!AQÄ1E«ã#ŽtM!”rTj6Ú–Ê8ÆËîùåqûØŸ¼x¹y›ß‰³¿6Ð?ª¨¶ZMÄ‘e ZJƒ–JÁ4M\˜œ„ëºàŒƒÄ$ùÛv…!¥€ìÛ·¹\öÍG¿òås×;Tºçùâ G_]–Xn‚ã†pÜŠ"ct$/ˆÇADвˆ¢€”&# )å¸4ß‚9TÂgŽ­þÕ?œxâÕ·.¼< ÕòM¼%á1ÛÐó•T(¥R­^‹¥ À¦iHg2X^ZÂÚZ¯"í[ɦ ìÕü}àÀ­ñþ©SßÝlÑå=€Ð?û›cçžûî+KY“Âç£èXF†L¨Š„ $ˆIoK˜åP ‚ Š)/ÂâjÜ»†ž:û'ùΓ“«?Ɔ Ûd «I3ÜívÛ™œœ\34ÌtšªB×u„Qˆ ç'!Š"¥`ŒÃÐu0Ú;%Lã”Òé{î½ï×3újZ7SZìo|óÝ3ïþèx½U`{*vŒeÀ! Š ah[‚€ ¥õjý0¦p»>î>RæÕ†ÿ¯ßxúÝ¿¨7݉D”é{Jo6ú;™RØèSž8qb‘ƒctÛ($Y†ªiD 3§ǽ=€$Ž‘J¥ É"\·‹(Š Ë2Ì´ùO_ÿÚx›ÍÀ·ŠüÛo²¡”³“ëÞmû2Ûü8¥Þvët!ŒzÜÕ† Û Q*è$…ïGî±7¦ž{õ­ /0Η¾“°òkAû) d\’$q×®Ý·ë† AP«®£cYèt:øì]w_ñâœÃ±t½.Ìt’$µ_:vôk³³3}—Ö+Š`׋0¿Ô ï½kÇö᱃¢,¸ q„0f¨TÊP*èPŽù¥ÎòSÏþø[gÎWÞPã:Ièÿy÷þš{©'i ›¤©ÙhÚ++ËÛvŒ¡¡¡Ì¶ÑQ¡Óî`îÒ%ܲ†‡ú§ƒ‚ @§cA×uèºñüÓOýõw®Å¤· ø “h©¶ ðùÞÝù1A)Câ6º^ˆµš #%#ŸUñö{ 'žþÇ“OÕ›îÉ[ßûÑ5xó#’(` ·¥] rÎQ©¬.OLœ9?==5Ç8§Êi)MçØµgOù B :m ’,óB¡ðøë¯ýË `0(ôÕuÇ—?µs|¬ÈÅ<«Û ÒÄøõ›yé…×>z–6›¼õD‰Ûìœÿ?™cé¶hØ–Õ¾8=535uaªX,¹¥¡¡Œ¬¨¦$É Œ‚sÛ¶¡iÚéºþä›o¼Îo ¦‚ƒ˜*€ÔåÅŽ;Vâ¥á‘±´íh6›­£¯_xæÄ‡K/£ç(¾žHoàïQ Rë$_Ã9É”À÷ƒ…ùù…³g'έ¬¬,˲Ìò…¢¨bE0ÌôŸ?þGxúZɰØBQàã©@ pÎ…K‹­õƒ{ôñ¥•æê‹¯{z¹ÒùäÁWÈÙ"öXÉÇù(Œ1Z«VgÏ|øÁ+ ‹ G5-Õ-–J2çü‰ç‡Þµ˜°€­7úŠZÀMöØ@Û>š5,'¸äv£™$×7B>ÝB×0ØÐTIÈa¿“Ýpò5—”z¦¤çX†aèžçù×r¢[qô÷”Ðkü9’ül'½‘¼õýϰuG} O3‰RXL¾÷,&¶{­Ó—°…o\ ‹ŽíaNÝåÖÿ c°·eÿ4‘‘D. KÈÿ€¹ v‡±±]œ\Ãú~3î÷`“S`ìüš_ÏÂó]·³IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/reminders.png000066400000000000000000000061121217176075400237050ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚ IDATxœÕ›Yl\×yÇwŸÃ™áNI”*q EY-¹®Èu^”¨q‹:Hœ6/UD}ð«ó¼Ô@b( EZ‰›‚aFeq[bmË¢JZ²(R¤Ä¢È¡¨Y83wîÒ‡Ë;S\æG‘ús÷s¾ÿù¶ûsî?€º§^‹ÆºÿòѰöuS‘› м´b —eÉø­~ý?ßY|íÄ*`Ý“Æï3@­ÿÞÀ?}ÿ«­?hŠûÐe™[¦Ì SæJJ`6o.ØÅÌKSÿ7ÀìZ5.ÖêA;€ÍÝË–Dk[€@Â÷AX¦­Q¢³Ymëb¯wü*óûföûA @4;}õêÇ)…Ky…º°„­‚1 Äš`ð'~ö/€Fú.Õâ!;„‹“ýEíÏŸÿz¬½Î7c€¤Ao=¨¤HûAŠ€-h彟ýï_ÌPŸð h€ ÌôÂrjvøÂè’)à¿Là öÔÁ“p¬ö6ƒŠ<¨µh\®ÅCvÐåæ.=xð‘#‰V¹tC´¨o UÀ¡`Àè2ܾ4qyþÇß:(8Ú³#‡ø @ôoþù+ »ÃaÅ­VðÒ4hëeN(,CêÃs#™3orëW/ÿHf-Ú½Ÿ¸!Xü¾ý=ßÔ(cØ&–J¦q7ZTÌëéÌôÉcÿŠ‘Ÿ®‹€N Âáý @hþî{ ³µû;r]à)1ê;k µÅ}°’Ó±D°TÔŒxö,F~Gø kÑ™?5 %^øìïL5ô²/¬‹í‹Ó—4°¿i# :z,ЬC~É2WN½ü.ŽðSÀ*Žú×$úS RäÙŸY,¯õ6 Ò#}AĘˆíI…É”NÖI×É$s040z17øÇ+À¥F¶ï¢aPXû‰eÛ›A±ÒKmO|),?Á´`9—à×ó°’1 ‹4…ÜÊ6ZZÛµ‡ŽY8#_ówj€(/^ü©ßïÿš®ëŸ†ñq.—;ÿÜsÏ-¯]窫’ùõ?N ~rìéÇcû͜ȕ, Áç3ÈI"IÑ "ˆôø¡IÈÁHbõ‡o~{ôvØ×MØ $ |åÊ•ßÅãñG,ËÂ0 ŠÅ"º®_+ Ÿ†ñq>Ÿÿì7Þ~ýõ×ëäö‡¿ÒóÿþÒ‰'w7Ì ñ‡”@R°‰IErõbLA Á.´Z04n®þÏóÇ{ò¿ŸÃyªª%À½OZ®_¿>‡ý›]lF‰”T*5>===wnxÂø4ñÔÑPÛ®à—Û$r2\±`B!J|Ø-ÀÒ4\øÅ/¿9ûÒß¾ä6kǶmAOfâ•ð?þ‡º®Kº®Ë¹\®eïÞ½-Iw^+l{c-Bé\±XÄ0 Î¥BœºÝ¡ › £–$H*VÁ6 •…‡>í?ýjfDUÕRø[XXH²æEQ´5MË:uêço½õV𠣄ŸÑ¶´´t={¸ukLNN24¹ íçÓŒ€í—hŠ8­h-ùÉi­·¶mcYº®cÛ6¢("Š"óóó7;;;óT˜'xu‚ G­k7n …èLÏóW]:‹‹‹¬aÞT1 ‰]j‘xÀ&µ¢ ª*†a`Y‚ ”~¢("Ë2†a(@'dÞd vCc ù|žÖÖVDQ$,©“ %A¤X,bšæ/ÇšVÈ»víJLOOã„e›mLÁk òf6î«««hšF*•"‰à÷oêK¦…ßyçß }Òßßÿ#œÛÒÌ«N„ÊG¢Úßââ"’$ÇKDz|·bn%xyØ·o_·(Šm€;ï[AĶm$IbnnŽ––LÓ$—˱²²‚eYض]Šë·ËŸŽð’$!Šb)Ò Îâ°%s÷íuxpp={öpùòeš››1M'ÅW¿ß ¬®®Ž å!Ôu|ªª"Ëò( |ôÑGSTPò«Š€ZøY–¹téñxŸÏ‡ªª¨ªZ‡˜Íf7tx¢(¢(ʆÏÎf³Å·ß~{'l™U­ÛÙäv8tèжׄB!E!NßÕ¶¦i›öáæÍ›3Ùl6…CÀ–£õÀ”Ä6ƒ¦i(ŠB.—Ã0 lÛÆï÷Sžy–C¦¦¦FpRæÿÿ€c Á`°¢k-ËâêÕ«cÜ!`ëgWÑŸš´\.ÇÐÐР@õƒjð×*ª5lÛ&›Íß}÷Ý OxM‘µÐ²S'Xk¸ý™›››Êf³nÑtÛ‘ªF,É×áÚµk£8å³ŠÊæ^5 $|5p¯MDz,FFFÆpÔ¿¢×ÕjšP­ ÷ÊlÜþ˜¦ÉçŸ~ íp¾6˲Š|ðÁF¨‚ŸÏw_g”7Ó>Û¶1 #‡3ú9@ðæ€£G6z¸§f(#\̲¬Ò>ŽíW\õ\9|øð¾û‘”ûõd¬ó-T‚\x1Pöïß¿ƒFï6ª”¿ït0<ÐÒÒÒ½£=`3µ/ÿ_Ü+¼ uvvÖ%‰ŽªZòˆ­l~ý±ò¯¨”Pž}öÙî@ pÏ£ÀzAï…à.¼h€ÜÛÛ{XÓ´R‰ªÖ(/ymµ_~l§¨”P›››¿T^²ª%¶ñJÍ¡T*h½;nqxÞݯ!•j€ÔÓÓ‰F£{oݺÔ> Vªþn,….Ü„È *ÑPžyæ™Þ@ •w¦¨tÄ×ï¯?fšf©´î•j€ÜÓÓsØçóynÀ ¼ï¦Àå×LLL,ãqE%ˆ€ÚÖÖVr€›Õã½b#7;ç¶)BIÕÝQ7 ƒ©©)ãÕW_ýκŠU¡À×ÐÐPr€ÍÎzÅz›.·ëõç Ã(Mšº#ï®:1 ƒééió…^øãÙ³gÏ·ñ • =z´>‹í¯…àp·ð›m—:6Üþĉö÷÷ÿ0B åé§Ÿîsëòµôþ›M€®‡»(B×õ/¿°°À+¯¼2Úßßÿp˜ÅYKXq8¨D”ŽŽŽ>ŸÏWÓÑßî÷:w6¨P(”Ö†Áüü<£££¤ÓéO€ÿ&€e<®!Þ. Š€ÚÞÞ~¨ÖàV£_¾](8+Et]G×u …LNNÒ××ÇÒÒÒy`Hâ¡æb;©@ ]Éd’\.·ã´\‹6Úv¡ëÜ)òB¡@>ŸgllŒÙÙY}ôQ$IZ=sæÌ0°‚‡Bh9*ñÂñãÇO9räØÁƒ{UUí8yòdWµæàÕær9E!ŸÏ3<<ŒeY<ñÄÔ××3<<<†óí@UÂÃöØÀj2™œ=}úô‡§OŸºNž<ÙUMc^qãÆ 4MãöíÛ\¼x‘D"ÁÃ?\ZO4>>îid#lG€…ãU'qÂË"„MŒ¬q7±)?~óæMòù<™L†™™:DGGš¦ŽI\¾|y“ ¡ò8 gp¦œÿ¬ÚÆÖÛ¼eY¥tÖÍê,Ë"™L’Éd˜¥P(ðØcÑØØø…5étšsçÎ}¾Ö¿ªR%aÐÆI--–_|ñÅ3…B!ašæ¦kp¶r”kçY–¥úúú@4 Æb±°»LÆï÷ã÷ûéèè »»›H$r—Æ%“ÉLÿ4Žç¯ú¯#E`æÍ7ßüІócµp¿-9øzzz:;;»ººšûúú£Ñh<ŸÏ#Ëò] $fgg¯â˜gÅ“ Á+:Î7;€qœ¥³®0^QN€ºººêÐ|@Ðêëë#?þø®îîî¶ìêììlhoo¯D"ŒW¼ d»Nx„óÁ¢†#üN³#‘;kdÀ·öüàÚvhm;ˆCН©©)|ìØ±h2™¼ðþûïÿ £7B5#ç~Síý›õ£œ •;„ø¹CF`m¿€£‰S8Ñ©jðfÐ9·'¼³IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/search.png000066400000000000000000000167731217176075400232000ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚäš{|U–Ç¿UÕÕ]éN:M7‰! Ä@  ¢òA ø`FE]g”Öñµº®»ú™gfG‘ñhDaEÃS2á‘ð MBBHHHÒéN¿ªîþQˆY`ÜÐaîçs>7ùT¥sÏ÷üî¹÷žÛ’‚äfû[ÿpüø»¥!ÆH I……E½s{\ÙSU䌤¤äI‰‰ž¸¡‹“u'OºQYS[ë/Þ»w×M#‡U­ ïÞ½Gdvé,8DRr õÀ8õùŠ¢|«q¬ûô“ï@$éÝÐÐ0±^ÞÈ{ᆱkb¢ÓG”P(¤Ä"qY–AÓìF‚æÔmª¯<~<²·xoÉ¡ƒ‡WÄb±’‚¤ÿï¸cüÝF¹ùÉ7êÒŽ­¶–-kذ~}E©ß_4q+œv ¹oŸ>i£FJ;vlR÷œ\}oɾ¦%,Y±mûö½>oñ÷©€o `Ì­ã; ÷ÜÝ÷Üõc9WóÚk¡W~ýëÀ^àp¨‚­wÜ9Nݲe{`Þ‚¿®ª¬~ý ÜrëxIÓ´ÿ4éîÿ>tpîkÿý›Ðœ_=õð9Pª-ÇmŠ«½Ðš„õXð$³> “eWzÝžùï¿ÿ£œ^½l¯ýî÷¶nÙö®ëñƒ0æ–;ìiiiã§?üÀëžDWâ-cÇï?p XNfdvKyêé_õ|`ʤL €f œj€š-{ÊÏûc~x’À¸è\ÿè#Œ}î¹ç³Þ^¸Ø¿ü£ï×u} ¾wC‡ßl»¼sÆøÇ›ñv¨©Q0pàz`.PÔÜ7yJ÷·Ì¿¸ÎŒ<'-%ÔZS¡h²,4å¥u¯¾´Žß͹¹=Ä®úÈË»û£å˯]œÿaíK–ކ±ñbÏöÀÛÎÓÿŸL}3 0`àÀåÀ³ÀJPÂ……޵`þ{À=–óÇ* BÀr:hY“¥ÿ®:êËÊî2œÑ£'¿¼øó¦Í›ÿ0ø†!&Ý=!eĈ¡óÎßë>à¦Qc.Ÿvÿ”¹ií}Î+rº-^vgvͽâð¡=ÿÜh%¾Ã­_¨•…¨5ʃp¤Ê@×U$—ba¤ºxæ?gÅ\î½K~?=¼§dol℉Î%K?¼Þï/Ÿ·ßþ[Ei¾Ðþ|©œ½z^õÔÈûMœxçàe`Wv¾¹‡íYŒZQmnéç›-ç@q-”Ö.ÉÈÞ$ðyÁ—ÞöhD~â釤 Î+¶¬ýlÝ‚¹sçyüg3‡+ªò˜®ëBœÓÎ+›Ã%yÜî=ðÀO¦-\´¨ú뢢ßÅ÷N›Ýmÿîí¯½¿åp³e-Ñn1Ãz¾¯ªÂ ª i Jæ²xÊœ.Ô`Ž™ÿ:Õ>åÉ¥eÀ–ÇŸxâ}#6îöÛ‹Å2/ªôhÈyÓˆsRڻŬŸÿb)ðÕmS^v¼ûæ ¬yÞd9iã|ÜZÂ"ÀþZS!N8íàPAs€Ã‡ŠCÓphN´'ަz&?|»cê/——_̘1ã«ñãîHs{¼ëzü¢N~3gκð…GBÑв¬~SÅÄf5æz_c9Øõˆe­èÀ‘ œPÁ¥K‡ÍàP¬^‡ÝnAp™8‰sô„±âªÁ^³víºŠòÃÑ‘#†ÅâdIâlvÞH’$÷ï?è¾´ÔÞ]ôþçvoŸŠGfÎñ êG¿µûxxÞ’6­kµí¨ŽÂ1vsO É A‚ *$ج^…ÕN‚ÃN‚ÃA‚݉&I¸îŸþb“æéºûOo¿U4dÈ Ÿª(w)6…³ÙùT@»›ou‹¿ìp¨´üDÁˆ1Sô ·wœ¡òz÷.\»­–…À|+úR’•+# ÙÍío‚N œ²Õcý¬€SµLQqÚm85NEÁ•ÖÙ«M¸ovõ¦ÍÛvº“œöΙGÆbq CœÑÎ'€~C‡KݶíëÊԌܣ×ãÊp1ÈÊ´óK¯›ÌX|lI^±"/,;…¨ nkGè”[9ߺWZ›ŠSUqª6œN ±oÿÛ£nO†¿Ü$Ò³WϞ͡/‹q&;Ÿ®ÍÌì,JKË^‘“îÑ£k:kE¼G–Ê t(‡5À—Väë3š@Ü”|’lJÞ)·ŠzkÊÙ ¨8W²ÏçèqÕ ãþreVf§!Œk$YæLvÞ6BvÍy…ªÚŒpT?ÖåŠ>v_;:Y˜ÖšÞ'~\ K«a{ª™ð2­ÏFA—ÍèËm gè[@QZ )èÙ=¯‹èñâIî¤4»Ý‘å°Û?½ ;Áœœ+S#‘ˆphîFO‡Î —yI·ÆÛ’훌À¦:8ä5!ø€¨aFý[XD[ùÉ Ë É +€ÀHë©è'ÊU›jsØí»Ã~a·Â^¯×#t·§½áJô:5‰–Ó-‰.jM‡.I EaoNj& H¶ú3γ–èëÖK範‘˜ÜÞnÄÝ1I¦ؔDE±]XÂÐeI–ñzÛ9§–Ž`k³Ì küqà2;Øìp4õV"Hø¶ÿô¯ånŒ„»Móùä` ^èq µ!:àXUUƒ")²ÛíJŽÙI‘vËaã ª50ç{g ìžKþF›^j“0À0@`˜˜ —†-ÙáI¬9^D£{Ìqaì/)© y’œ©‡”X[D:ñoÓ`³À¨¸›aNã³:ßy£Í3ÐõVEÆHNBM‰íêãñX¬1_èã°Qs¢î„tYª']ŽÊîúÆS•–¥N±ÞoQ„Øb¦ô€dœCâ›?mÆiçã1ˆFAU0¼Éh¥öååG›Â0.x=ààî¢=Ü0dpz¸6Ò¾>à”êtB^…$ €Úf*(Qú_Ihçtˆ ˆÅL‹Ç …4†ÏE»ª:Ý{èÐá2»Ã¾ãÛVˆ¾ €}k×}vb̘QíCáŽZÄyr¿ŸH^ž¨òi?eKò¶¸¥‚¶R?[ÂÓ[˾åôd9‹B8jþž‘†P cyE…Rv¤|·¦iõã4x$??¿°¾±Iñ:õ.Spû+u" Zì!³O›æŒCb Ü$ë,Ú˜n.É-ÏãVk1äX˜äh˜äp˜äPÉN;¸Ë·lÛÖj®•%™³ÙùTÀñP¨qÓÚuŸÝ8éž E†r}×~D¯¢Š,£K`ȧsW‚d%DÛT ¬uÔh•[ÖÕHÌŒx8jÎû`„›¡W†´êªªö_~¹ù¨¦iù†0.”¾ Øüꫯîºmìè^—½SvgµîëbÔd76¯[ tUÅT„ÁZ†¤3hí¼nˆé¦ÓÑ„CÐÔàN€¾Ù eÅÊÕFUUÕGNgBÕE)Š !b’$í/Ù»kå¢üzÍ|xº/SE©IÃØU‚Ò£;Šª!ä(Øì6‚d3;*gH†F1 ®C8l:l†`êOš/]›‹PA­¨(Oþø“ÕÇl²òŠ×O}^,#hB–”sdïV>|ñÔ¿Ì00¯ÿ ¾}{{útè@ñ¤Nf¥CQA±#l*èªy‘Û@hIxÂ0GÍè‡Ãf䃨«7ïÓ ²RÌ[±×_ÿ£().þm×.]ý•ÇŽ¡( ÑH„^={òÔ¯æP²UU‘”ïž¾q1"I’d·sÛì¹o¾‘–ž–JmÖo‡@3¤¦šNŪÝ4» 6$ÈRè`Xë|,bJ?†¦Ô7@8=»Â€óoæÎû£1göS×TWN‚eGQYY€ÇíÁëu‹éhšÙ&ãq{Î_MP˜4Ž_­ZùÑÛ/½øÍuõuøìpSøŸ1}aëØ[ 8À•h)Â6›9Níï…)ÿ˜n®õá %oôÍ®>óõü%K8TêgÚ´ij¿ëúMÿ˶íu;g~‡êº~RÆ8žõnP’$p=0vê´‡î{ò—³\ÙÙYfå3 )òã¦s6 ¦ó6åôù×°6:‘(D#&äÈêý²Nÿ¯¹óPR¼gž}š$—Fá_ö’zYûHzZjL×Ùy¤¼ìAUµ•hvh´ÇΤȤø| €´®†õ0dò¬Y?ïxëØQȲ @‡üPyƒ& ¡Ÿ>ûcVwpªÐΗ§A·´ÓÏÊÊÊ™ÿ§·yãõ× ++Ê–/XðÎ=“'OÊ®¨¨bÕš5ôê‘KÞõýPZê/ÿi’˵ê¢h¡Ð¸FUwN{ðÁAwMg2xÀ7RH ¨B0dÊ]–Íév‚§Í6¾®¶–%Ë>bÙÒ#«V.Ë^± .7nÜ´ùÙº“'=ë¿XO0"¯S&Ý P[QQõ è¿3 ÄEÐ „¸È®óxSF»cÜUÆ Q¯í{Ü=;û,‡áÓ- ±cg¡ØøÕV±aýÑO?[»9þ XaÕÀ OV¯žŸÝ½ÓªOVóõÎBš›Côì‘ËìÙO"C¸¦¦vnssèIMÓB @›)Ñ èhÝöËÉíuU½:uïÖMμì÷?Zê/KXµêÊÊŽbS’=nûé 2ÒÓ C˦ÇU)KñùÄEÐ „bB½Öôè`AébýÜrùÙ²ùk*€ýÖ­r©uÍv¦¢¾¸&'7w⦂‚û·mÛ®®^µšh,†f×ÐEŒI÷ÞC¿¾}¶WW×<")ò×)>Ÿ~Ñ´‘€YrZN·ìŠU+²¡Vå–+ô¿ÖR¾£FžºèÝE·¯ýì3Ûúõ_àv'£9ì4Ü4âFFŽ௮©yØ®:>õxÜñ‹ ڔξMíó\­ÐoÆÌ™ÿüoÏ¿0<I¾üuá.2:vÄnW©©®¡w﫹kÂx€šÆÆÀLŦ~èrj‘€óÕ:çÍ›ÿ‹±·ÝzõÂÅ‹);RN×ÌLœN*«*éÔ±Sî› C¿0ó’\®ð¥@²a+?ùdÖÕWõîºpÑBêdgu%!ÑEÅÑ ’“×—çÔ”ˆüœs±—Ykw:甈° ,+¥V”R'•RKÀ `iÃ: ¬«@÷ÌV€ü«ˆðôUÅæJ©“§O}ôîo~ëÕÎZvlßÎŽ]»˜˜˜À‹"Ï"ò4ch ZEhü™·$Òj¼CJiÂf«U­õ*¼SZ©(u’Ö `K¬ƒ¶ áæu]ƒRDQ4@þ•4@}óî{ÎøúêJóå,ËètÚ(­q^ðÎágfj’‰é)ʺ&nÞ#"ˆsˆRxZ_Ød£ç pZ#Þƒ÷h¥Ð@"2(¥–#­WQêtéE…:ÕÕîn:Ä:ŽÎùêH£Ðˆ­%¨§Ò ~üE7É?X$°ûSaóñ.âs ¤¤ÙQ(ˆG5ÂnÚÑfçxrV›Ãè *îÎn9º‡èñå Nk% འÄá½~ÚŽ$Vú,h¾„ uPv%a'ŸæL…n”ø»úÿ1ÍcxA>0»Rx‘ïM HçP ŒJ9Àã½¾Aíi+ñ“m[`å°=ªQ?õÞ{#g‘ŸRˆ÷ãw+ ÀÖ7ÞÄ{Tã*çÑÞ"^)¼ÖXçÐ"¨F‹žÎŸkÓ6¹.½ôκVË‚žüÐ5ò JI ZÀ‹;Á7K#ˆÒÔ8¼ ¼¡¼CœÇzû} {®#–srÀ†'£Ô(°Ùx½ϰ‰ùÃÿ‘Vcû¶.…XðʮV ¯»íG>Bã8Ê×x±àÎ{\mùn!ô÷À¹Þ¾®EU#5x ÊQJ‘eˆ7 ª I‘F1*ZW~²Q$1b¾¤8…± ãÀZµ†²¶!16¸AgqNðÖcÅ?)ï|ïœãý¢Âý%| á#º½‚ßûÐ׸ó]&çw2;Ó¡GdYBžhÒH‘eŠ<Ú‰'Ž ‰¶´SO»%´3O{òX˜žb×ù;é­TV°^ð¢ðÎc•àµ~úp.ÚdóclÖÝÙÊ#K5ƒÞ€oÿóôöcæ·ÐÚ5Aš{²¶g²åi·­XH´ p”µ¥×¯è®ÕtûkkCz½ýî2E‰þÂ<ïÒ”ÿþ›o¢3‘cÖ Ê‘"R ÌÓâséuÐvn´@Æ@£@ô®H+â(%üúïþϺâ™Ýɑӂ­•v¤Z(5ÄZH•"‰Q¤é$­VÆÜVèõ=«}ÅÚ@±²æYíkÚ»ú|æ«á;×þ7ô·hç_œ„õ41ˆÏªêQ£ç  ÁªqÁž‘+â$âðCGùÔí}þö[«ÌN™žž¦ªbååmâe% ¥òü£ŠH#´ˆo22i*Gg‡xW£”á‰c«¼ÿ¦ ¡*…Kž‘ó¬ƒEoJSTÂÞ-Š·]›³Vxf; _º«Ë}ìQ¶Lƒõ5¶ìa«ZEMЯÇ!ZPD‰&ÍòVÆþãkù‡;n#Ïs²,#ISÒ4%Í2òV‹v»ÃÄÄè Þ~Dü8‹iE(i51º0ŠÀÖ˜ªÀ™ ñ“-Çþâ}¢G–ç|í[]nøÈ1&;´á^te‹]Û4ÎÁñCÞúžûѺF1ÄU}œécÍéqTêTÈ$5ŠDÇ´Òœ_yÃøÔÍ7“ç9I’EQ­—Òµ&Š"â8¯8sASs#dkâB9Ê6Ú¸&·ñz­‡« LÕÇ”%"%G»_¨¨ëškßq/‹'WI# ¢Cþ¯<Ö‚Ïâ©’‡Ž¬ ürÐÅÖ=L]bËá8ó^!Ρâ(–,͸îíÿ•<ÏIÓt“ÐßË¡ý†Ôs´œ÷xï‚°Á;Ö5°®Qq…wÎT ú=¾Èñ'–yásfyþnã]ü0 § fÚ!GAy~´À˜_öŒ)~õš½ø²Ä%˧{ô‹’Õã±²Ò§ªÆÔ8qX/ †¥ûÀï¿ïûzâg-‘M¥pñÒœsÝËæT€z°Ä©…û™i{>ü?„¯|ò¥üí? Rò¹/-27#bñ„Ïé´#>}Û þÏm'˜žÊèöj~ñšÝ¼âê|úÏ^Æ=g;ýÕ£<û⌟}ùE´;ÞyÑÉ2k«»­µW×u=WUƼw›Lø©ŽX¼œuRqùYÄ¡µGé8db~Ý56’Óø¼3˜…‡ØyÅ^ýÊC@ ÞòÄBÅÉnEšhÀ"Þ7ù>乿Ý7>ÂϼtÞ9fg3.9ÔáðƒGx÷/_Lü†‹Ø³{’ç¬Y¨àÊ"s`ß¾=?þ?vç`mÀƒ>øÀ_~ê“7‡å1•k6ò©5@xßD‹Í‡84…$¦¬F•štŽ÷_õñÎ2ª,JSý™˜Ð}h÷ø0"–ÇŽã%WOñœý擈ÉÓœEÀ7]¢m„Ç®¿†[É ÞYÄ q²Ã{Zà?x;¯ûÕO‚Jù©»€îòï y Q’¥½îË_4ÇÇ?t5*ª)«Q‚Î$nÂWÐâÑ6°¿Ö6¸5Ýt¯¬œ yñÅOÞzë­_‡×}7´wž³–÷8¼øà¼Ã;‡3•(DšÈLTÐg±.M¤af*gvß<>rš»¾þ0×ýçç³sÛ4¶(9º0à–Ï=ÀÏ¿õsôªnü“«(¨X- "M¡5öy$Ѧòe ÊZkMǤi‚ŽF¡®BëÍí¸o¼ñ]eYÞ`­='z\³ß°‚Í{œ[Wm/¾1WÁ5ºñ9Á7(+¥ÑMÿ ?¨xæe»8p`+³3)ÿ×°wÏ×]ÿ÷ü»Wþ5÷~‚Ÿ»vÝá•ÂR‹ÂÑTƒ•@ê!]ï˜h爌 ¨f÷£ AŽnÂåsïz×»ÞR–åõ#6[çÎFE©ÐõÍ£ ínßÜX¼ŒYœq€R‡l­©':/àáÝÿíÇ™™LX:Ùãªçíä[ÿ÷>tÓC|óž£üÒ[0ô%eÌi¨@ºP‘*ò¨T¡¬F*‡¸ ‰#t'1œ€Öh³%ç½'>ú§ú߯ºêªoc>$Ʉ؟€gëfŠ£É,½Ç¹@|Þ;œ5M ;„¥ÞÕxoƒ=¢V†ç>s7?ù’ ±¶"Kàúßù*‡Îñæk÷râÔVŽ­  HBnañ v)G¤66d´Hi¥9q»EÔîçq‘DqèZŸÓÂ7ƒðñßü±óÎÛ=Ÿ¦i™$I@QØók”VÐTÅ­s!Ðh4!Ôÿ5‚ÂÔCÄ QÚF鄉NÊÝžàúß¾_|õeüâÛÿŽ/ܹD¼çí—òâ+/ XU¨¼0Ä¥a#j, Mä!ÇüÜÛì#om!”¤6çúOÖ‚ß$Sóú®]ç·ßùÎwÞð7Üð¦V»¨íÙ ´BéfÇ7ˆ :7.—˜×‹Â˜!"Bwˆ³JåÌÌÆüÁŸßˇ?u˜Õ¾pþÞ­Tõ=;æè\Œjð*¤Øi…hOAéˆ ÷\ÈÜÄ^ áÔò,<~;¬É&'™žennŽV«õ]gÖ5A@Ã[í×ÞøÛï}ïõi–-èÀôg¬†üB?Þ5ªßtc¬ÅãÇZà½ÃZ‡)ׂÌ;(§-òÎSÓ“èt‚;·bɸúòm\rÑ<ò‹`­Æs¤7‰.[ˆ ‘èEžÁÜÄAúkKüþÞÄ>p >N‰§§±Jqjy™ï>Ü{øá‡YcÎ9¬a£œµXg(ú&:Þðæ7½uye…@Ch›–àl¨ÎŽ1ÖbœÃû@rÎ ÎyªÊ±wG ­ ²‰è(!J2’8'íL’·&Ð:à üÄ ¶£µ%ŠƒV)áË éOâz-.:ÿÎÏ÷ñÀc÷óž?ù-µ¸ò‡.env†8nR]¥Ø¶}ûòÞ½{oúÎáÃ÷EqÎi5c-Æ:Œ ›Û\sÍÏþ¼1fÀ÷Ö,gýX8çƆ]vÎŽãßðóŽÁ°àŠçäÒC[±ä¤í­(£’6J¥(àtÎÜLÆsŸ9ƒõí¶åB‡ê0¢¨‹˜¹tÎìg©XåÏ?òm¬àÙ‡æ8xðüÐj‹"’8F”fii)‘ÕC‡}ùÈ‘#ŒOmÞZ‹‡«k¼÷¬­­qá…mݽ{÷eÚYËYËÙ±pÖÚ±íP,ÞÛ!ŠGœ§® “Ós¼þ§w³tÿ-¬õN“Ïl#íÌ’¶fÈÛ3èt–Ø;ÅütŠOžÁÄ„c¢YQ¬ˆÝÛv¡O~ôóôNgÿüÏ¿|yÞ QŸ­c²›Ã‡P—5­‰Œ‰vŽÖŠO¿0!ÍÖšH)T¤ˆ3Eš*Ú­Œv}t‰C‡öÓnw‚æYÏâÒIŽ-.EÞYVWW˜™œRyžeYNNLL,išR™š²RU5U]RUkC*^”C¶mߺ/KSb{f|¬ UšÕµ‚|ÞppOÎÊjÁÁíϾx¦‰?Œ»F!) ¨£Õjsùå)‚Ùx˰¬Y]í"´Sha4FÅ1*†©©¦N§žˆ²¬H’g=ËݵõÊÄ”®bemM:I[×u¦éêj·ÇÔT‡þ Çp8¤,kLmð Ÿy<åpH+oÏë("N¢ 3BM$ÖŠã'Üó`Å¡SLO*¾ôõc\vQ;Bxü¨A9~_“FO]‡qݤÕ^„ª®©*‘Fû¨Ie5M¬Õ¸p  "X Ná#AÅ¡æê­%¸Ðmð÷"DZÓ¯*+ }êZ(ŠÖÕ3š)pãšEUU8ç”sޏ,Ë òßžÍv°Ö2/°g~ŽãÇWY\ê:$=Î!vÜiºg!‰'UÎáDp"!sôáÞq¤q¶I^ÐèDE1IœÅ1^ K3úý­vc q³un ýµ‚º2 Ž,Ë™›€n·›ïß·gùø±#Ó'O:êºÄùŠ(ªqxoƒk0Ö°Úí®Äÿã·®6 xï0µáC7~åJ¿È½nåü­ší“aH!Å£ª°_o¤ú¦Ê#M,á›(rTD­ëÕ¨|¬#t¤É’”$KÈZ9­4c0ÐîtX8±Èd2E¿Û%Ž"¦§§¸à°¼ºL¤#¦§¦i·Ú¾®ëÔ£QÑê‘£§_fÜ §OUXo‰cK’À‚²X8c Ç©ëšØûΉÖzªÚh”¦®-ÝÕU\]ð»OÒ[[A|ð«Î»± H“ŽwŸQ:=ª3žæª†Î;²,%Òiš¤)y–‘$ Y–"Ã2LѤe9$ÉrÖºkLNN2ÑnÓ™h k «ÝÕ¤·Ö¾ð¢ --عdO?¯“f V ¦ª,J[â¸&Ž-J‡àÇY˃>x@üÀý÷Mà‡.Æ(×µ¡ÓI8¶ÜâØéˆ[2bkÞ:¼ Å'‚ò¡c$M\ £þA£ZÖy”ÖX ®jfgçÐJ% Y’ÇÅ( ÕÊé®­155ÅÂâ[·lE·[¬¬®’Äq0ï †$IÄó®¼ò¸-mzûƒw¾NoITµ¶H­*ܶ÷Á ¢È’&–$Öúî»ïž;€ñÀwC> 4ÑpX±cû4¯yÕ=-LL´¸ôÀnL]é4LnÆÙTCtl£Ç]e!T€´ò,åäÉ%ìßµ6tpâÝ4-!Dps3³ «Šé©˜›ŸgnnŽº~\©($C3sÅÉKÓ_{ðÎ7ÚNµñ”º nÅØ"Çc|SÎ7D‘£3‘²úðãåãý‡³¸ÿÛßfï¾ý™µŽºv¼ø»qÔÕ$Î+zƒŠ(ÊMxûÆö®éøÒ©['¼y«Ãñã‹TUMœÄDZGamœ Íò”í[¶@SaZí®Ð[[#ËSÒ4¥¨‹‚G—ßeeá7[­¨]›ˆUWQº yl+ sLá,!zO–Mòå;îøÄHæ49©óãÃ5Ó4>^µqaœÝ…`hrûñÀ³RPÅáC}Ì1qaœå±Gÿ™‹/½‘Ñúz;zÞé´Ùµs;K§–iµZÙ×Ö¨§Z]ÅÅæUž´S¼uäÞ•[Õ”Ö`µÃä=\‘áªW+œhý.·Ýö™ßÙ¹sÀ¦é€¨A!";o1k±Æ5ieÈÀãIJsÁöñXç°ÞãÆ…Ó¦›DmvnŽoÝ{_³ûñ9'9F®4Ï[ì9ÿ<¶mÝÊäÔq»ƒCá…ʡڥh]W¤U…ª,¦2”fH©Ö¨òÓTñ2Cß'OSþ鮿»5I’{u3ø9Ò d„¡©$J"òV›J j²¿Ð `ˆ“QK0 Bô£n±VãY^ÑQ¸½ ƒ3y›^¯Ç·¿}Ï}Îs7 |&#N˜žž ÝÉéf‰3Ô(ÌpH酪練º®Pµ%6*ƒ15ÆX,“ô‰ÚSeÍg?û±_N³ùM4 ´N,8ú—ûØvìÚuù®;ç¦ffÉ"5†:̬£³„Ô'y‡ °ŠÂøI³¼۔ϜsTeIm*Ö†+˜ÊpóÍçàþƒLÍL=é+œóSSÖú¦Ba”P›Šº° BÙñåq¦&ªk’Ú"Ƴ@¯ ÙŸùÐÇß–$飣ßP@Òh@Û˜ÚÜ~ûo(ŠÁ|+oܹsç³ö8xÉþlÙ²•l~œ£ß0,KÊ¢`­×£ èõztWVÜÚZ¿Z[[-V»Ýa¯×ëõ{kýA¿_ôûE¯ýªªŠ²žþÚW¿råwÞyõh§ÏÜyï…ÊT˜Ú2V Š‚Â „,¯RK½ëÌR‹Á•5‘1ÄÆâkƒµ†ÉÙ)îúì—?•¦ÙzÝòGC»9ÐZišÎlÙºu×p0HªªŠËªŠ¼÷-…Ú27?w`÷î=)¥ÔòÊr·ßë÷†Ã¢oŒéc@”ͪ›Ç 04ñJi›Ä‘ÑZWeU _õªWýÖ-·ÜòÓgÚ¿÷‚µ†ÚXªª¢?°¼²J¿×ÃvW±'OQõ{Ôµ¡RB™[ê¤Àºù jC×yÔD›ûn¿÷ËŸ¿åÖ«7j–"¤ôª±ÿ¤YQ–e­ówïž ‘56rÞ)ï¼6Æèªz:¢@´ÖE:Š$ÒÚ‰R^)%QIÇ.‰b'±(­}ǾÝn»V«%Y–û$K\+o•~¸ºèÂxÿ_~â“ÿ©Õé0†Æ¦xu–ºªYívYYY¥¨†˜~=u ³²‚)+Jg)c¡nÕÔªÀÔ5 ‡Ê;|þoïú›Ûo½ã•#¡Ç œw4©UÐ*@%I2<ï¼ó‹Á ‡3NœˆªëZêºÄ:¯b¥ejjã AЄ(Ž%KI’T:Ò$–ɉIfçæ%Ïsâ0²¢&¦¦$Ë2æçf$K[t:ÑQÌüüÜ[~øùÏÿÊï½ï}ñ#/z‘Ž¢˜nwgC˜]×5E1lòûŠÊØài\˜¨ë+>vKèt2V– >ñá¿yÇ~ïHèsMGŒÙgßþîe/ÿ)W ô{=žx⨴Z:“´[-iå-¶n™£Ýépúô)5,x/¤Y¦.¸è"Ù¹c'¦v !Mœ4ÍL¿^qÉRÃü¡¥#­V룯ý…_øÂ ¯ºú¿þ¿~ÍÞ½ûé®ué÷ûEÁpXPÕS×Ô¦¦FðJBÉÎZ"2úF¸ã‹wÿý§ÿæ¶×_zÙEß+ü“LÄgžðÞc­uÆšàF¬ÅÚæƒã½ÕUEÇͨCÍ])ª²¤,Kl€ø0Ëéð 0¯‚;eŸ"á(EœÄ´[­““““?ûŒC‡~ã'_þò·]óêW¿æ™—\ÚÎóÎ^iPMÐ…¤kÐpôä ¾úÜò÷ßøúoÅà+ív‡øìßD>5ã|Þ¯‡ºëçšFè¦*òˆ´6W–˜-7ÜgcÖ5‚4Íššš~Óµ¯yÍ›[­üªg>ó’¼àà³·nݶ§Ýž˜qÞéÕÕÕî©ÅÅÅ'{ìîGŽ>~çÊÊʯøÑ/²4¡(`£«ûn‡ú^ÆHžêø»/Þ†cÔN ¡óæOšÁC6Íe†æj8™$=ôÞò«¿Œµv"/ßïéÈð¯ÀÿÏÇÿÑ5ì,þÌÀÃIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/stats.png000066400000000000000000000140441217176075400230560ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞëIDATxœí›yœÕuç¿w©zïu¿×«Z­–Ô­ I´V$!@6@ Œ1Ʊ˜Œm2Î`ìl2‰;Žíù“I“ÓŸó©ªWu«îùsïYîmšÎQÉYpŽüäIÔø©4^{[ÞÇG>û7lÝø;^xœùË/à`×n¦/\G¹ØGÿà5¹û÷ï'(–‘ZÒÖÚÄÆg7A@ Ø’ 8 ~-xЄ—ÅÏÖ2þñôÂZX·f)[¶íÁZÇÔÉ覣½7?ŽVЇn¿]?©³—Éæñ²µDAH÷¾×HÂ2Bˆ#DØýàè¹<ºôÿÿпð~wàý¦àýîÀûMïéõØÞ{ÒïåË-‰À:À8°&eg!1` à N@hgÆYœs¿<ÞuàªXkIˆ£ÂPP &bÂvˆÇC˜‡r¤#vb3€6{ÉÊ=‰Ðýq“˜PXgÁ½Þ`Þ zWpçÆZbc©„åR¸ÔâV{ž>}Ù™+æÌ9®cê”öÚZÇÓÖ’§>Ÿ w Ìþ"=½ýlßÕ]Ù¾sßö]{{Ÿ,–‚_)©ï‹"³ßX‹s`q`ß^§ôް¬s˜ÄņJ%:;‰“O-?iÁúsV.Í­[¹€©mù·òÊ0˜÷ÂÎ+î{d#¿þÍ–—J¥à&©Õ÷czŒ3ïÚ|ñ¶pÎaŘ„(Šs• øbcCÝç/½xMÓÅçœD[“÷Ž;7gZs¦­äêKWÎÞ¶§ø­Ûïú·o=ðø–»Â0ù³8±OYkqêÍão ç‰1DaH¹R¹ö”Õçõ¢õ§qáÚyÔãoU_bÌõ¬ö<×\¹–+.Y}îï|ìÜGžÚñË(Šÿ3ˆÁàÜÛo£f—$1A¥rþy—]ûý3WŸÜ|ɺEŒ¯OŸIªÛ*¿$Ȫ¢[$Ÿ»t9ç®Y¼æGÿ:yëm·ýäˆ?g’8á-Ò›·g±I@¥\þá‡/ûÂ'>´j.ËN˜ˆ$ØÑGß2Bí­9®þä*ÏŸ}Õ- O¹ðÇ×}î¼$Ž6YgÞ’¹½)œ3$±¸<þ3_ûÙc“Z§Ÿ·f>S&6F`Ãá0&íä{I΂R „@ Á²…iiþP{[[Ûs·üÃ_^î×nö²Ž7‹ÂoÀ9G[¢8žý¥ë±©6ëüó×.d|sž$NżGÿm¤¤@)Mû„¿·~15Ù?ûÁ?ßx}‡Ÿ3ßx³FðÆ8‡I ¡f~ñÚ¶•Ô¹+–Ò¯!‰ ¡³©_þÝG°)Y‰AIIS]ŽsVtGÿéë?½íû¾úfæ„càÒ)- ƒækÿò»›zzºÕ…çœF!ïÇ!&qïf<òŽH òõ9Vžr<ƒÃç~å¾_ü¬Ç{΂PÇl«c‡âuB®ýú7Ù¹coöœµ'ÓPÈ[Gš·5ã¾—$"ï)ZêkY¶¨“þ¾Á¿ùùm?Ü$Œ}P ‰GŸœ4Iÿ˜Ÿ`hž±˜e§žöÝ®ƒåãgÏj§µµë ÃÅðýHÚÞ¡À÷5“Æ1wÖúWžuÏÃîhPZ‡R„|½²õ‘!Ljd†$Žž¾ríç7n~‰ÎÕ'#±Uá?(†t Â%³¦³mÇžì¬y‹nÞôÌ—0°4û?„£ÌH¸êªÏÿÓÃ>ËšÕËñ¤£TŽHÌTõcÈךlV1¯ó8z{{?ºé©G¯;‡O©ùç'/^㟘Ïçhn¬ÃZKìÕöÇP'hO3¡uõõõ,ZvÆ_?{ïM'¥²¾€dLó„ßÿøÇþø‰g6³rÅiH X¬ü?"üyQ‚À1¥½ƒ={^]Šl> ëžët: ‡ÌCudëÆiÌ u…¡_|e'JH¤Ö€×?0\ÛÒÖJEDI–ÄZ¬±À;/S†Pn¤Èá‘ÍùᡤD)2}Î9¬5„aL„aÀðÐ0år‘A(éï¢T¤<™QÁ¬¨…\#º6—-àšÉes™ÚBsn\>ŸÏçjr…|]®6Ÿ¯oxð¡‡7N˜ÒÔsRk„(å ¥3  RW_O4€r@;Ê•€~çR’Ëøòò…Z´’<©ñ´F{ ­JI”Ò©KL"V¯º€ÿõôM¯1ƒ‡Q$Ô`©U‹È7âÕæñòMdêsµ55¹ÆÚƚڬ<®­Ég³¾—­õ³ž¯¤V‰@ $ØØzçžò9°)½=}pÉaŒœ¤‰Ž¤µu{{hm›LEG`ˆê„èû> £Q,‘Ä ™ —Éàg|r¾—Ñ(­ÑÒ¡¤D{Šár‰éS'“™ÆÄ‹ÿüÀ‚‰-ùL¶P[›ÏÕfu®Fg”/A$Ö¹8 )%‚¨B¹\!ŠB’ÈGØC^Ê:îêQj겄=LØŒä0‡¤Ýh)×¢³s÷þâ×Ñ\ìo ‚œík|ßÇ÷}²ŸLÆÇ÷=´ö«~]Û2S"’”eDC¢sŠšZ½mə˗rà@‰ ˆmBR )Ça˜˜0 ‰MDÅ$QBG„Qôúøa !9šÈ’†FîÉl6K®&KM. ãÙ³g9Šƒ”††ˆ¢8Ær¦Ö!Sí{J§ì¥9…çi2ž"“óÉúŠŒï“Éx)ûÙŒG6ë‘ó}„tÌš¾€û~°‹Ø– *ÖXlœ`‰DIÕ R)K™pGÄQLœc¨”CŒÅ£€88:W›G U „â µ¥aH67Ôïï~ñm“IÆ ƒ‹Èd2h­ÑJ¡tÊR¦×é¸÷PJ¡´Æó<”xJ£´L-@¤J½Ç‚Óyì§3ézu€Úl#å0L=ŸqÒàãá”Å:ƒÑížTÄB£µN°ÂÝ S6èµ"æˆEKY(4PWWOCC£Š=Ýû÷¯8}Å/bƒ³›˜QvÕÕ!O{h ©¥Dk…ç)´§QJ¢=‰_ÞÓrÔB´’xžDkjV*šš=f6.â÷o¦¾.‹ÆCªÔ“øÊGJ…–%têUDºoQk…’­=œqDaº€3–M’0T¦¶–Zì ä’…³Y¼ðxNZ4Ç‚~ðÁv^úû—€9ÀPÿAâøÐ0Àؤux¡Òø\ëTËJ)ô(oäž:ŽÒbTp­Ó‰ÐóÖÆÌï\Âæ{CTÆ =ODJ”JTM_¤Ãa”¥DI‰Ô‚ÄDÄ&'çÄÄ )ä´vc-`ÆôfNogöÌ©@GéÙï}~é¢èÖNú_Ù‚3Ž$‰«œ¤.S{iUì¤h)‘*e¥eúŒxJT‡‰DI¯ HÚV b3sú|{¯ìè&ŸóJ¢«9‚® ª¥B’1%eúM¡ªÙ`u> IlG9Ž,qd(…46ÔÌ‘51¹æ”NÖœ:—³N›ÍÇзé±Ç‹¿|Í…xƒC«ë~1—†¶rDp™j@)¤V©èÔL•¢ Fú¼’i ¤¤¨¶éu•s †¹sç†Mä Y´Ðh饿.UÕ RË4rªj…2.…Di…Ãb’d” •Jòº¡Ÿ1‹èrîŒfOÉ3±I²rÝÚ °ý¿ëÛOÿѕ瓙¼˜`ׯt%È$$B¦›”ébƒ¬¦ªJŠthÈÔÍI!ÑÕó‘xDx12 J•2i”9ç¸ù¼ú€OB€ÐD¡ªV~O …¤R£ª^B¥ï¯Öû¢$"61±‰1‰cÿAZ›ƒx51«Q »ôâ³#˜Óµ}ãÏõÔÓ;ùîuߊ{v­#9 Ä!Ĉv•NÏÕÈ}UÍß9¬½µ¤ÂØ„¶Iyêk—²åÅ=Ôf³Õ… ‘þ‰ô(IµÏÈoRq”RbG’ÈG!½]0oÆR¼uæi¾÷?ï¾/0ܳì#Ùg/_{å ŸêøFŸ"ÿ[74½-FÚnx²+ÿw7ß3áž»îéw<Òûf‚Z@~öÜ–ö9Sru-2v޾A*Cý0ÔA‘CëC¤…éBʺêÇ‘ml¢±¾_4ÑöÉ[˜1ËðÑùW³µçzKÝÔåëhnh¡{O/·þèö-/=“ÜÛ°˜§Î]?ûÅÿxê—w¬.\1Ì›Ü;þN!uÿÓû 7ýøÁæ_þú‘Öý›ž˜@¼u”¦S¡q*ºi"ÙºF?Wæ/μvê¢3º/šÿéîeÙ ‘. ¾½Î¾Ç»?F’u½§/Q¯¾ÚëíîêÓ¯îíWôÉPî‘4í¦eаÇMgfŸf&Ñ–´0#†Öd3·ëÿrëtl~fpj}zîü޾e³V÷¬™þÑþÅÞ9üÁG;øÁÙþrtz¶rOvÃÎ[š:[OŠW4Ÿ_ndJ¼k»¶þ/O^µ¶ }?IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/system.png000066400000000000000000000162241217176075400232460ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ[IDATxœåšy°eG}ß?Ý}–»¼û–™yšU£ 4£A3ˆM¶$c"¹À‰MW\®8vʱœü«’à»Ê6¤Š …–„pb–¥‘‘œ8IhI³iÞ¼yÛ]Þ½çôòË}î}÷¾7’†$.ÿ‘®¹sÏëÛçœþ}û·|¿n%"üÿÜôßõþ®[2þÇï½÷ÛJë=ZkQ(´V ÔÄ jøÿd÷¦ßÇþºÄ8µyä¥//ã—ø]A¶^+`áÄO¿õ­7 ‡OP:ÿýÝ»¯¸ V«Q¯×I’¤z‡B)µåZARJ Ua¦Æú•RqŽjøûplìWU?cõØsª1£g2q/£ßÀ{µïÎYœs8ç!púôéëÆež@)†>aÏî]”Ö“f)J&'?œŒÒz­Æ…¥ô˜ÀjìwF÷M€¨ô¸Õµ×àq€^¢yï°¥ÅZKQ–xoY[ë eœ›l¾9IbWž§<þØch­Æ&¥Ð:º ¥ãõpòÃß•ÖÕ=ñzÔ?lLH#Uor‰«J¶¶MÞyœw8ëðÁƒÒ9rd㉛Þ5€VŠ<ϰÖò‘ÏÿhS!7ù¶ác&ß/Õ?™èÚÒw ùdìY2þãË)õ"CB@ù’û>yƘKÞŸl¾k¸Âs{vrý›ßJ¢Yž£ãp°œ ç‘>`Ë’bPP ,Á³ž¢°ˆ÷ˆ”‘h´­µ¦’XU$ÆDó©™FE§" ÆŒÒH€ %Bb ÖZN=ÿÇŸ>þì áEÂý& G6¢PxçXY^"„ÀÞéWM×°hÒÄjÅ .J„àâ<Þ:Ê~AQ}‹”ØÒ"! AÐJâ»´AMDP¤(D+‚ÒŠ4IHR×8Hå,%ú]™›€€aéâ'Ožay¥PQ¡‘Ê ¾¤ @åІÚòzG槸¥®YäYÂìL“Ož\á|§D‹ŒQʤd …É2²zÔ [¬@W ¤ÀˆF´ utœZ«¡c@Dá¬$@ˆš£Ph£+"ZA{­ÃóÏŸgy¹ƒˆ'Íðaä9.S¢ãªäÇ:OwPÂTžR›iÌÍ DQËšY«-b=â+”ļ ñB ©¢–·@Þ¹(d`-´DPCà«"HAP„ˆMQ8Ο_âüù%¬s$YŽGð9 —è Aè ðŽíÍW캂  Óî²m¶E+[¡×Y!Q*.heŸÞ ®ô¸²$ø"„È’hïâQ‚Ñ&ÎOB:†Z¨Q TÔ†Êí ”B,^\ãü EaÑIBªâ£Ô 5RûJŸ.S”Ê€õÐLSB·Íñï-ÐY/ÁqÃ5ûõhMéÞ|é …'8-K\á+‚_^J "¸²À—©œŸÖS9Xm”V¥aNeCp¥ë½>Ûôz}`> øJ’:•i†ío†aãP…¦ÄÃýÇþ†ãý‰IY\^æŽ7¼ŠîŽ=H²ÁzA°žà­ ª–’d äWºj2‚`ŒFS†`xÐ8Ê^Ÿà}Ts ‘ChI´Ö$IBé…v{^¿mF‰ŒTÚ§*‘¡ü#‘GÎ樂`tdaÐûÀ`}@H4Ç;‘»þ…ZAxt0 éª$=•¡Aé±óè2Å J‚õØ^+, ‰+­:«£r0&A$`­Å„Å[‹”%Z{¼ó¬wÖYïôñˆŠ¡R$š‹(µ‘Õ‰ Þƒ±~´äaÌ^€ah‰`DVÕ]鑤 £ ¢@´£‘D3‚Tª?(…I Ib0IŠ6ê9¤>Æv£ÀZlY\€6r‘Hu³ “fBéèwút{}|P˜Vq q,ÁYÄ:|°HpQx”6xo¶jÀK0J.*0(¬Å‹‚L£kZNé<}çPðÖGûÔ “e4:Æv‘5¤‘“çÁ{TQâzü`€ˆ£dHƒÖïƒÂS èfm<$ „éRðžà-Á„²DÊ‚àÊÊÙZ†ÿeú5Á•1ЬQ*¸q¶ÆU ϰfN;N,/ò¿æo`½^™"Ú¬N*\„P$¼ŒÔU%UËQA €¬ã‹2zpï±¼(t’Æ\#Q SÄéÈ(­@5‘8&Í0I‚¤9Á•ˆs8e;©/G„Ô˜D)DJç¹æŠmüÒ]oáégŸãMï.þçÿ8Î?û«3„Z©b>>àBð!ºn¥¡/Tð¸Òá‹®Œ+E‘=ú¸Ò‚‹U¢£_I”I*îi·ø€¸¨âcß0]‰á“È4µû!L@o8A 5¦Ñ@{_ÍISØø0•$xÖdPâúÑÙEÎï·1I*/=dxxO(K‚÷hQxïpƒ_ xbH³%!‚ ™aÔžø0 „8Î;DbôÍ{$P:ê¹L"¤6|Šà…~¯¤´¢gÑF“e5´ÖÑ)VNV' :”Å;*xÎ!EI°6Raï£ÊƒG¤·I‚IÒøÐ¼†Ik˜buc¥%xÞSúÐø²ˆö´ 1`¨üO•вA…/Ÿ(ðEI÷ù¬ÅlBV˘™™E‹²=`]YR­£c  Ðh“¢RƒÑž‚³„,‹ÞÚZ”µQJ”±ï-¢ J”Ò˜$c›>Ï7>ý ƒj~qnFƒßùØgùô×~@Ro¬E\£TU$x„, .U|Y0Åyʵ6Öy\o–ms-Šê9yš º=lÃR•T”-¦5"%õÑOè TeÛiäöZ#ÞDûöq%Á•Ôë!IÓ¨uF£µ¦Ñh°c¶F°ºÑŒ\:‚rˆµHðøÂ!’Tr_ÞC€Ò¢Ê‚ïŸZäÛß;ÍÎm-Nœ^â¡'ÎÐ]íª¤E)]©gÅëM\I !>8“›ád´AU3¥£*'• …@áú Ê¢ Ïš"Î9ºJk\·C°"%Ññ<ÃWð’&À¦0ˆÞ;Lp<}ö"ïþ¯ÐªçxL¢Ñ‘ãF" T@ëÈÎ$&-Ji*ç0ª)Û!Uàòmè,߈>RiNÑæ¶CW’ƒ÷a¢4BàUG‘~ù¯ 4"÷ðÔãP"ü§ÿ Ï=†Ï}õñBÓ UÌ âÑÁ!(ÚeðB,Œ$I|¸6U"%hÄ1!|TǼތãT™Oþ‹Ÿâ†k¯âî÷”A} gÙ¡×ø©Û¯ãï¿ñnöîÚÎz¿1 Ê3@QÜuÇëyô+ù¯_û6Ÿÿ“¿àø³LÞ"Ht”õZ÷üÂÏógß~(° ˆÉ‘Q•¥ZÍT‰bœÓLeuvÎNóÚû¹rÇ^ÅX­«\UœÇ—RH°\ U!®®ê/óñ_37ÝpBàË¿ý^ö%Ëló |è]‡øÖþïûùŸdÛl“N·;|£˜#UY–ÌÎÎòKïy'~åc<ð©pxwÁNñÙû6î¸ã”R|úcæÑG¿C!ÈÖ¤x+¬Þä#5G|`à·ØË‡Þ÷fvooÑšª1תñáO|‹ß¾ÿ¦kiô‚ª¬4J'è BÕ_äã¿þnyåA.,.055Åýý'1÷Î/PZKš²,»¤Ú[Y–”e‰Öš£Gnâ«÷þ{z½õFƒN·‹ˆP«×¹óλ¸ïË_æÆnyÆ0ô!ÄÕÖâ¬ãŠé:¯=|eü­í|ˆU—*•ª´«Hª²·‰… º¿Èøµ7„¾§×ëœw®âP£tv¨µjH„ÆèŽR1Þ¯¯¯£µ&Ͳ‰°9 ¨Õë¼ýmoãK÷ÝÇî]»'$ž0ñÁ–ÎúѸB`¸ ‘J©X° ‘¾*t¬ hN’4çM‡çøÑ×ß6!üp’!„XÂÖz‹Š:ç(Ë’~ÀúzŸ²,qÞB@ªJ“ŒáœÝ+ÕÜúý>Ó33ÜüÊWÒn¯MÅ-Np¼x(A몊íFQ +^±´îÐßG"@Ú¤‘èánOô%þ½|èGßH»ÝÞ²C3Þ¬ýµ5œµ€"1±:œ$ Z›Hgf¦ÅÌÌ ¦Ê G‹ÇXØ!Ë2–.^äá‡æ×_?ñ"1¿ŸE#Öò“wÞ¸I„“gô‹˜Èˆ ’¨ºHžøÑæ¤iìäW~ÿ«üÞ¯8ßø ¬µ[Ú.k««Ñ¡¢Q‰fûô4S­)õ:i– hú½‹‹9þ;wÎÓjµHÓt”ÑÐÚÐi·ùìç>Ç«^ýjÖ{½‰wNÀdÒ "7FŠÍt£0(xâé3œ=¿ŒÑ ±.’? õ£2LUžsèÖ6$¿‚û¾þ(¯>zx Þ{.R úÌïØÎ `­%Ïk4§šÔk5’$Áè”bzzšÖô4î:íÕÒ,ÃzO=Ïc~RiCšNŸ>Ånd,5¸4ÑáTYUU P:!mNñßü.]gxðñgxò¹ ¼°jiwÛd©ÆÛbƒk÷ü”U1=Ñ‘#”m~ámwœÔøÊ_¼xIJgß^\Y0==Ö†454šMNŸ:7¼q´Í%"´šuZY=§×íR”%išU{'š¢(¹æÚë8öèw8|øð¶˜ÀpõF¥*­¨·føâ#?à @›„¬–CVKQÊ`L ™ÊÄ"ÊÄîoµ‹“'¼rw¡×±ÖnOhY»ÓAkÍž}ûY·Qx¥ÎùÑ&j-¯‚ßÐÌê;ISœµ¬w:4›MÖÖÖ°”¤I‚R1GÈóûöîaPLi š€‰ŽÌä Œ†æTEW«Ò¹ÒQÐ}ü1l‡ÛWRF‚€÷¼ûõ ŠbâÎ9Ê¢`×®]¸²dfª÷ƒí#z¸úš«IÓdäý‡è „¡·÷Îc‹årcªPØç¶Ûnãþ¯ü ×]wíK QÀT6†ùeDlTÜÕBÌÓ¡r†Œ²A¥Mµ¡÷ùÒæÈÁëécN»Ëtk kYšF"fL ‹JQ¯×1Æð½§~€(ÅÍ®fvv–õõÞû*Ë(´–eÉúú€tG2Ò”„æÔÔÆ¶ßei‚g°> Õ{y˜d"¼UzÕßUe×hÞþæ×QÚ(Î{®N—#˜caÖ;‡µJ5‘àÑzƒQc˜ššâK_{˜cO/¡šs€Â=ð]®nY~í=?M^«á½ñPÕ"Û­é©‘–„X_ïóš×ÜÆw¾ó}óÍ7žNΞ={ak…AÃT£ÎÍóב&zèF!F›¸3kŒ‰'>*[ÕD\X=ÁÞùãEŸ4I˜j4X][›€{}}k=à£X-RŠ™™þàs_c1ìdçÞÙ Ós”úؽ|øï¡,Ë‘²¶ÄÚ’õõuÚí6³³3@À¹»÷ìåïxGzÏ=?q¼^¯™GyäÛ›œ Lˆé™)®¾å&´–‘3}ôðè ±º;¢Òp ÿ8ÍzN¢£c]ët&AˆÐï°Îâ¦Õj‰& Ï?÷wÝz5f“áù€ñoç_Ëc=Æ+o>BQˆeYR”%JGÐl6+MŽ‹ÚívqyN½ÑhåyŽ1æ¦->Àùèië:ç¾é ÚœŸîÒm’Ÿt¤Fo}}4¹CPŠ¢,#uU‚wŽ¥v‡æT“V«Å©Ó§9rô(£\ ^†§PD8}ú4"B·Ûcmm•,ËI“„ZžQç쨆0$HÖ9œwÃ(·˜ÀK+¥¹ëÇî`ÂoŒ…É S[ý±¾?ýÓ¯NPÓKµ<Ζ kí6§ž{žýW_Åüüüì‰'®ªâöíÛyø‘c”e9".Ö9NŸ=ËÞ]»Ù»o/ iÙðÈk­VÃhÕ[XXø~!ìÝ»ï:`vmm m ÆT)x„••Î_`~Dz,-d«ÕâÓŸú£/ýæ?ø3ãóü¿:-®&›VJ¥T¢”Êžx≃EQ4ûý~Ck}…sŽ'?A«Õ"Ï3jµœF½ÎÎWp~á|ÜS€‘jm0ÆÐív¹°x±™Õê·4§Z¯ZZZš]Z^Þˆ Ycôꚥ¥UšS­ŠÂæ‰-K¾ùoÜ¿Y†ÿ#†W÷ r LÓÀ°Ø6??ÓÜÜŸùÌgh6#[ϲŒ¹¹ææ¶Q”åˆd)¥«³CjäÙpò$'žy_åÃBtiš²¸x‘ žZ–Žê~?þÄ™Ç{ìÏ6˲e{üå§Š*•à¦zFV0£L%I2Ójµj{÷îýQk-O=õO?ÎõŒLA)Åìì4íµ5šFõ¢øßøAé$‰1?¶Œu@Q Zgœ;ž¥¥%¦g¦GY`5gðÇŸùÌ K[dº\0¶âzLè¬:˲lÏUW]uÃõ×8tè¦C¸áʹٹùæTcîäÉ“õ¯ÜpàÀ~ï÷Ÿ^¯7Jm­µt»]ÊÒ²mÛY– œƒAÉ`Ч,-IR,Õ‘Š›ê˜í…Å‹ômÉÜôt¬ƒ©ø@–e<ÿܳ~âž{Zk—7Ëõ²0¶ê#uWJå"’Ùn|Û~üM?ýêÛ^ýúë^ñн»wíR/¼pŽ?ÿæŸó—=„µ%"Ðn·ñÞó†Ûo¥±ZG’•$)FçÚ<ÿü󔥧Ѭњjá½ÐïÇÔ7nÆóÃ>úý‚õAŸ<ÏØ6;;ç‡àœc×®]3·ßþ†îû¡5@)¥Œ1ºV«™4M³B­ßï7€mïú¹wÿË·½ýí?³oï>55Õ¤–ç\X¸ÀûÞ÷IÓ”ýû÷3;;ˉ'YX8Ïûßÿ~Þû‹¿H·×ñæaë¼£´;mºÝ.Å $@ÅCØ"TUáh÷Zijõœ¼^ÇlzÜGˆÍf“àlÿ½ï}ïÏ>øàƒrÙ(¥ÔŽ;Ôþýû1&Y__¯­­­5———ÓC7Ýôîþæ¿ú7ûöí!øÀÒÒEVVWX]Yáô©Ó\¸°ÀÚZœzËÑmõzc4s³sÌNÏpàú$i‚B±´t‘'ŸzŠ£GŽpòäI®Ü¿Ÿõõõ!ÄQP­QÏ&IBž§ ±t¦M,¶‘ª*<¸^Fð!Èišâ¼ã‹_üâçûý~gb‘_J>ô¡©Ý»w«F£a¼÷9Pë÷û­N§3[ÅÔêêêíNç]y­öÚmssÍíÛwpÍÕ×p͵ײ}ÇSÍ)²4Ř„¢ðÍo~“C‡@‰gþ³4#H (JÚí6ý~%€ÑÎÏÐþÇæ yžÓl4ÐZ³Þï@N’„éV‹ßùí÷‡ùÈG~YD&êñ/ À'>ñ õš×¼F¥ij´ÖI!×Z7EdÚ{?Bh9çf®;uêÔ+.\ï¼ß£•šmN5ë{öìU»vîbjªÉ³Ïþ€'NòÎw¾ƒýW]…s.nZ|ö³(¥¸õÖ[9räƒ ˆ²,ÇÊo!m¸²&I¨×c~ð¹sƒ{ïý/÷?óÌ3óþ_þåzÝ+®ŸïözÌNO…¿ˆ¸Í2¾¬ìt:*Im­Õ"’i­s­uCk=-"3J©9cÌŒ1¦B˜ît:ÛVVV¶-..n 3Ý^¯e˲që­·^íãÑMõÐC%o|ãóóóüç?þãòÎ;ï´AgÏž‘§Ÿ~Úìܹ3;xðPÚœš¢Ó錎ð£$RdÍñ'ŸùïßúÖ7žxâ‰Ï~á _ø+¥Tùº×½îGþèSŸº÷Ö[_µã7>ðÏÿð£ýè%…¿,ÆÆé‚R­u."5 ©µn‰H«cF)ÕšDV˜WŸ¸J xà«ÓE10o}ë[•R±0OÚí¶;vìX½´ö–C‡nš/¥+¢Z///uÿàãÿ×7ß|óWõWõ\¡¬Ö:(¥Âµ×^û#‡:òÀ|RD¶nü ß½™þfDÖW¯„n©p³xÂ)&cÏÞ{ !8[é½/”RýV«Õù­ßú­;~öçÞýリ¬6œD½^ç›ßø³§œsw{ï?þx8wîœ;wîœo·ÛþÌ™3nÜÖ•RJ^DЊ ojÃò‰#žG-+`tÕÿP@mPEQè¸íݧ×ëI·ÛeuuUVWWemmÍ)¥ÖÏž9³>^O÷ù>„ú?øÁ›¬µï}éœ+ʲP(¥Êj^pJ)/²iç÷‡@Æ>¾zxÁ†F ó‚aN0Tý¡ÐÃ~c­UKKKÉÂÂBrñâEsöìÙtqq1¿páBrñâÅlee%ïõzzïÞ½’çIb&Š)õz1ÀÍõz½m­íc:išv¼÷=ï}Ï9·."}âQ†áü·ðÿ¢ 6]oþèMßjeeE÷»ßMOœ8aΜ9“­®®ÖŠ¢h(¥¦D¤ ´Ò4I’dßž={ŽfYVOÓ´–¦iæœSÖÚòìÙ³§VWWàœëôûý•~¿¿Üï÷ÛÝn·½²²Ò]\\ì-//¯;熚`EdK]ío­ r¹í†nÐoyË[jlÎÏÏ·ÆLš¦³Y–mOÓt&„ÐL’d6MÓ–1¦á½—²,{"Ò !ôʲ\+ËrÅ9·Òï÷W×ÖÖÚ/¼ðB÷É'Ÿ\ðÁ‹3gÎxª½½Kùÿ Z_NþãqyIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/systemsettings.png000066400000000000000000000203711217176075400250250ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ IDATxœ¥›yœfUyç¿Ï9÷¾{íU]UMoÐÐ4;šA£¢F\FM\MòÉ|b2‰ŽÎ˜‰:*3!£IŒå3£Æd~L‚» (²6ˆô¾Q½Uwíïvï9ç™?Î}«ºº ’ä|>·îûÞ÷.çù=Ïó{–sKn¹õVžm(¼glt”F£ÁðÈ(yž!@*–’MøÏþ ›`Y¾Æˆ1€""@DP$~ŒÇ)ö!(AÀ*À¨®\‹ ty’¥¤Ä_]ÿ±g•áùŒäÔ{öìYÀâÂFƒ¹ùò<‹‰¥‘V™>x„nRBlŠ•€¨Á ` @0¨ ¨ `ÅAÅ `E €1Õˆ„¨*@ ªŠù¿Xx9ÕvíÚ½kbb‚Z­¦õzƒ$I1¢*XHÔˆXƒj@ĈQAÅÄXŒ >€5bE@Å"V$¯†Ô’¨¢bk‚ jEL"XDŒA#jPƒˆU‚1 ˆXµbAÁ¹ Á;ò,¹Ëp™#wyÈó\víÚÕ|ï{ß{ñsZÀæÍ›7OLLP­ÕhÔë$I D@T0©Eƒ!5JPÁZ‹Ú+H$¢†E­`1¨ Š‹ˆÄï"Ñr☔x!Al@0ˆ1 ŠAÔ Ö`UQ#QI\îÈrGæ»ä.>Ïéæ9.Ï fN•÷4ÄD i’P­ÖHÓ‘(ˆ5ÅC­EÄ’¨µ#$bð$CaÚ€C¢€QÄZp@¢X1`¢E+Ñä¡Ç#Ñ}(x<çP|Z!ŽSJ,i9¥â|¹N»Û$_hBž¯pÇs`DHËW¿ú†‡†Ðâ" Fc@$€F%•hÆDÔ"j0%Áh‚Ø µVFTsB0‚Põ¨Ä bEQ%Zˆ|¡`ñh°q€5Œâ}F·èzAK' ¼ìÚkÁX4xó³0†r¹ÌÙ›ÏæÎc9¶\Ãûœ¨.AB"#x‚‚A‘0^<¡­xU‚WB–Óu Á£ÚÁyƒQÁ#L@]Ê x ¨„rÅÁOJîÁK hÀH²@Ë ÐÕ€í*õceæ–;îú*ß»âE Ž’…pšÝ<« ˜b[³ù|Jµ6±`S2kPc ±Tƒ¡Zãsò®šRÄ9|dN >à³€‡M,š+^Ã϶€#–™ÙEL7ÐÌ=åÉ~p„ñµg0}p†$I¨—„é<‹€…®‹~\ˆæïø@ ÑœUxŠÌ&r:=A…H„(¾—+ ‚ÒUHUI¡V¯23=ÏØËñ£KÔÇú=£B¦ò…%09êAL‚ 9>÷ÏÏŒ±XcÈ¼ÇæŽnæ¸ðÌuŒ U!ÀØ•Èõ>~ðèNFª¨—ÊTÐ9!äaÙŸ{VAEf °WR⢖%@èÝË4?)S4B’Z:]ÇŽŸìäð‘’¤ÂèƒÍéfmÔ;0àÄ â‚'HøÙô,@¬! ˆÖŒ1ó“'¸oÛ×à‰'âý¿÷kÔšžêð >ë„çÑ< !Dmk¯µÐiÐø›WÔBð(Cœ‰ù2ÆA ‹Ù'”S¬WöšáÐÔÞê}õø¬\Á)BŠ× rÅãUzå‰ú<¢€ÆÄ˜í}D=–›Ÿ>Â÷íÅTkøñ4;¾üéÆõ˜ÎY·‰Ê&HÉ¢jAÁ«‚÷Qèž‹€ Ô4÷„<ÃwóHzÁ£N‘TpA([0¶ÂÒ¡iŽÌ,àœbËeJ=÷ E€ëZ*c(J$ý3] HMŹhîðóó4ë£\ö«ï¥Ôèã’ÌsàèqÊíÊi@úû1…?&ïñŸ;4s„Ü¡™¼'øÂB ¿6B9Ť–à>¨æh×c-,´s¦%oµ±I « ¹—"•TœzlaáÁgHðH©ýËZZÞáƒ;͞Šbk,Y³CæM„qn‰ÙÃGÑ$!­W«¡õ„à„àCôq=©Ä5«=Ib}X4q´›ã³@põ>ºƒóõH‘¦Õ”–81»H{¡ µ µF‚|Žx¯q9êÆyB–£®I7JÚ%uƒˆ:PÅâ Æ}^`0bè8IB;Ih.Ì21±‘à óì=:ÇäúI*.CÒcd™?–‡Fb+B7Á4±¨!nÞ9BðÍA ibñ60¿Ô¢¹Ô‰ ì+‘8.'Òz¬1ÄFâUcÀ–PÓ!䆲6 ÎÒÎÛ1ÇâÄàõYòcV‡F#±ê+¦„rJ[…ÕxUõ0Öìá¢+Îäþ¼‡?iÐ.'¤¹c¥:)rú à"!Fâ ±žWƒ†<úcj­¡yÍ ´3Ú­6­V/%JÕ J¾ TY ‰Þ¼/â¦"k i’ÆåÔJUæB‚†Öæöt ˜Y]!ŽŽŒF+0–` `È\ ¯¿ÎËÞð6þî«ßáUW_Í+7nä÷¾ô8ÃcƒH‘½¡ jbê 3 ñsž£ÎrJÀˆâ2%Ϻd΃-“8G˜Ï—ËÃL4Þ§N ×SŠZ#È=äÚÚF0TФ—ü4LBXÍ ½r؈Lil Ó-´è-"-4ÉCC w1”©Ä¦¾´ççÁ ï%ú¼wˆz4ó´;m²v{˜x/—A ñì•ÍÚ›‹Q£°¼Gs dIjˆ$(hÀHzº´Z­S\ ¨Œ¡3ß$t`1 ´k)b,ƒ}ñ¼ZÓ<ó”P4½?‰]Œ‚vmaŸçhæÐÜá|‚`%‰5¯‰Á”’˜üø€ 14†Ì¡YFpu®Ðº¢ê ,òfÌŽ£¡ƒ’uîÙ8à†nXuà®ï1€ÖÑ94íÒÉ¡Û;8}ýñB1tæ—(•,®(L¤èÛI¯èÉBX6[u>Ö & ‰¢$M‹XžÅôO‰æ‚µˆIÀ€h‚ØÊåè>>‚\Ž‘€à +ô”,D"‘0ƒ?ÝN=Ð+…­1„¥¡ Ú ¤Ý*¥?ÿ¢­”× Ó—µÈŦ=öï56ƒDíä=÷ðx&øX0áÁ¹hæ($)E#,Þ¤ RÍýImc]É&@Œ<[€0 OȾ»„Õ<ÇåÏÒÙ½}糺€[LÒS²ÂƒûŽñ¿¿ù0çMŽPêçö<ÂlÓ1Ð×ÅwbʬAcüªÅ¤ ¦.L />÷L§WêözæÖD¹À÷*ÅPXùäš;‚ë|]OnsLÈ ©ý,ð’§ÉOÒɺ«Háÿb@s¢” L/f¼ï/¿‡6A-Ò_er¬/öÚ´×””åD(æãv > X­ÅÅðu[݉µP¡ú^?,6¿1 ¤hÄ‹QK(+Ö•PÆDž$6a8ÍH.¸èÂUî½ï¾ØC…ÖJÖ0T¯Ó©f´:]B§Ãü¼a¸¿ZôÚ¡E3_}`™œ´˜„ê ke1ÆÖ@´ÓûÍ,“]´¨"ëì•×–-,>F‡ˆG«%Å8‡¦Ž'³€ÖÒâjèÕ"QkÞ£AȺm,–ñZ™3Æ×ðº«Îá{ïçþ‡é«UNêÒÊrõW¨¹xÅ%P]ŽëQ)vÅüY±¦"+×Ñ äÉ`ªºbï—›1ÒL"éÎYBÓÃàÑ#ÇV fÙ ¢ 8š­œ«/\Ïmÿó—I¬YÖuw=¶—F5‰m.1…™‰K¯8è ±¬õ¢£ƒ¡w3-Jïfq/+à?D!õ¤ûür3>*Ò›vìH™€Ð¡ §Õ$Ö®:ÐÞΡX:y†æJ’Ä æ@ 4—–Ðn†dÑM¢ÿSUVzثᔉ¬¶ì=Z8•®°=Ë‚IÐ2Pˬػy‡ÒöÑ’%W4ÔûÓ-`Ç®ÕQ``hh¹  Á·˜ÜÓm®e—æÈ|ŒùÞ»‚”VX6ZñÊóôYjñ•s{§ô˜zÕùËþÝã–…`¬Ö¬W«JI ­)AÞ@0rzðÒ—¿|ÕG~˜^z¬®xP·ËäHuùœ”NØ1!í.®[æ`Œ.ƒ *+xˆÆPáÉU©žüáTþ`™ØVÒÝ!WŸ$'q @Àæ \Þ…Ü#ò,åðSO<±úy'ùœ!¶­|g‰_~íåËçTðð÷ð‘7Žðá7½…ÚЮyß-’eáÄšeR[>& ±fy.R˜uˆ•“*-ü<²<+•eÑJÓàc-Ћ*©”€'ÁyÁ˜~²¼ƒ NƒI½^[u ÙnT‹feœ¼¶Ú˜] „Àì\›mS)ŸûÊ#LŸã±/Þ@µ”劋†È'ëy½LmEg=a%¦º˜B{=`ˆMÞ—^ÈSÃb/ îC½}ˆÉ‘øl¥B³Õ$8EJéimáäOÿâæU®Û[–™:®ô¦Ô׮㣟ýG.¹w_¿ç)fç:˜zI%k˜Ÿ+V{½µôå½®„ÁåxÝÓ0½ÈÑ;ݜ›'³}Üâò&6nQAéu—C×òœRµÁÂbJf5á$}}«-`ű *B­ÑàñÃØ·Z½Bc¤ë…¤Dî•d\»’È,k®À³ÂÔ½æ±ÿ¸b-½ó~DQ¢¹犢'š}Ř˜ð¨‰= Íoi”‡Èº 6)n"«ë! P¼šb“” %D ¾”¾þÆò;1 UŒÀƒ=Hiý‚K©•*ï,`Ô#á¤uCSX•D 1¨‰®%ÙrDïeŽ!ÖAâ=Þ÷Êá^cµèK¨Ç;w9>x|È©Zá[»ˆMJ„F^ºêßü;å¤T*'åñíS»¿˜ÌÎΟn!N"®óK¡A‰9ºM@lœ˜ú+eº8ùä'™Õíœ8¸áú•t˜v‚ ³U¤â¨Q¼ûƒ£dm¡b-e“ÓÉËt­£\r¤¤ää´:BÝ–(‡.™Ih{KRéP!YŽö2B§LÕxÊx >¥TíP¢D¬A•&Ž´S¯ý~eàãý…=þú-zgò™Oýé*î¹çTÈ:¸¸ ±Q£ˆ$q¡A ÃýÞó"%©¤ô}r.G¿û#6^{¾™;f.Ç–ÜÃeã¯%èé„\é¶RéÝüdï 3ùFJS\|Öz&ÃÏÓJæÀ5˜)=Ä?ìÜÍB>I%Yà̉6çU_O7ÍiÔK´ÚެmyªõEö©“»%–X»®Åeõ7cÓ*õ”¼“a³*‹µ;ù?˜âÏoû,œ¿îœû=¥%¦ªËoR\ù‹°¥jQÆìP¬-2ÅØú>P‰ÝË׿ð?ü* ;N°£y‚Ë“*ÿå…Ûùö§úyó{?Ãe[Æ™™™#åœñ]¾tèÞ¸áa.ܸ¸~+K­Ç¸„Gç^ÎØñ)n9p —ö?Èõ[÷ñá·ßÂ_}é l=w;·åu¯}-Ÿúf—Ͻ„ÝMlé{˜_¹à7¾ã¯ùË[ÿ/[Ï›`ïîYÞòê7ò·=Í+¾xù~ϺW½kl79pàÀ)™”¬ß0‰$T‹7±Œ)ÞljYß@=å#o¾˜Û¾<É…EFúû–ïs é({¡CXËQï™a 7:N'À±ó@? i›£®ËbÒôq˜9|=§åg­¤Ÿc®Ãœ¤À8‡Ü<óG>fX:’1Õm“Ìó¾Ã"e`œùs•Ù¨Ð<ê8.9Ø3X;²™ýUS"äždã¦M«Ø·ÿÎ9êõ:o»"§”–€ÒIľ’NYk9¼ïXKÖiÓ.÷Q-Çß³%Z®CÛU€a¦› ( ´Z K]fgg€ ëѬCË” 3­M”9 ¥[ªb|›¶w@cÓ»Yì,ÑnuXZèrìÄqàBÄ&4Ò„¡Ñ  ÁâÂ!;-ÚÍ.Kí&SǧQÖà“Äã|NždnfvAÞyFÇFÄ&6®Ý/—´Ð{o'„À§þè¸äÊ+YZj²ØÚÏ–M–™Ö"‹exv?ö$Ðæ¡Ç>)›¥ Ín›†õÀ§‹ß~Ù4eh6sdÀóèC ,ðð¶‡ñÀöÇ^Íæ5yúX›/Ýùe^±µËã÷D™ç‰m?¦…ãé¶!¼†J9iÒu±Yš,5—NãE !Ðét°Ö.[~Y‘•ýú HkUÚÇPcź5¦ÆEC“ÀöÄ¢kU.Ú9Æxu £Ö0^µ°pxÕ\˜9Äxe€‘Ô²¦¬À,YkŠ8Æ‚öq÷#OrÇ#m®>Û³&=‹¡¹]¤ÄNp#[„ñ2ìr†¼­dÈwo¿}Õ3¥TÒ‰‰IêµµZ S@€å&Dç¡d©Ûfӆͬœdㆵ|ì ¯çó‡ûyË–køÖÌ3\=y×l>‹r½L3ë ³ðµ£û9>³ŸÐfÑô‘öð’±5¼ñœ«øöÎùøÖ"}a‰eº•!þÝ™ç°eãúë}<±;ß½û¾ò£oAÞ‚j\ÝÀ;¯{;c#5:’qtîLðéoý5T«ô§Ž #“àÝ×’+®¼rŸüä'™˜˜àرcT+•˜e-WYºÜßè%sïy÷»ùÞÄú-—Ñ×0|ú3?à·ëßrîú-Œžðlèçúò´žòôì* %Ú¡K¿©ÂìjÝ%ŒTÑEŽÏæ`µCÛ_ÎQw”°t€ ª)3V®!åI»|kÛLMcû¡=ŒT†(ÕRÎè; «BN`ÿÜ3̶ŽÐ s¦fHÇRè÷ 'éB·Ý"ˆ,œÂozÃ¥¿¿€ gnâŸ;~úS€ÒŸ}üÏÞ¹å?÷¹uC±ö}û[[Àa~¸÷»;ì;qˆ©Å#<9·ƒ‹ÏæÌþõ,f‹$•!B³K³Ý!$9•´F©åpGš´ç9±wŠl~ž¥šR­•˜›ŸáÞO0rw•®ËX?8Æ€¤ô™@* >ÇKð2H[JXì@''YlRª¶I;[Éɱ´½ÃCR¯­®Nýþ3FV­U?Æøðç8ðhc¸U…ýÆ„IÙ:üRFÎa|Ë™4·×9+à¬þQæÚ‹ô—9Ø^â¬u#lßÈÞ=?¥ÛépÁØ8;æ$e:Ï©ppáÛ§w³°ïI’uW°ip }µy{Í”f˱w~ÊK8¶ÀìÙ –käÁòØòAqX’R±R¥ä¿ýáMÿ¤tŸùó?NéÏ=ÿ|xbû>dóßSî?ƒîÌÛ¾{=ÉàÍÜý£opÃKsßc¼õ³|av{fÎb®;ÃtVá­/8ÆUÍ>îù?%~ù#wqéMÏpÝÅ—såÄ4[ÃüÜø-|zÓUÜxS?ïÛ|ÿþÓ÷qѧ`¡(ƒ÷J­ãÜðŽ_b¤ùr¤ï0wìù ç$³ûÄ“„pV 6®iZâÖkú$ÅR×?gÈÊKFÙ`Ý.Îè·ìŸ™âØÒ i6Τº¾Ÿ³óÚ¯þ)7é[~ódÏT±I#¥ML¬µøö£|âóðžÏ]ËKÏ¿”_X»ž¿¹ÿëœëã¦_»„G¼?úÆmŒ³‰·¾ÿB©FgI â!Ðô942>öâ5¼tüó|ø·®à‚_ä5ÿõ³üÜ .¥¿\ ®¬Ž@½Ï‰µ§×Ƚñ¡Þˆª’;Ç‹.¿‚7ÿÒW¯PÄ-™:°ìÙ·€¥í?áÊëÆÙTæãOÏóÒ_»ž‡6Z:»š¼jüB²lc2g ­å‰ƒßá£å¯ä±íO3wà}æq˜ZbÛÒÌ£sÀGyŒ=Së©U,ï y d5’~~t÷Où>ÿ‘¿|œ-¯Ù ÍÃôU¯âô7VÓÖÿ©QoŠ-JÅfw?ýäªsíº ÿÌ&¦le®:Áïßð>n¾û6¾óà7Ù;º—àÞÖùÆ3³B¸| ÷~Ýy”ÙJª ˜áæ[ó‚þµ¼ãýïaÛÁÝ\øWÛ9sð|†kEkÝ ÄÀ¬áÅ·=ïÚÊ—3à–c02D K œÒ2ýgð‡ÿýÆžÆ Q㩈”Uµ ”.¹äÒoÞ¸U¥ÍŸ¿÷Ãt:Ewè%LTïbçþg¸ëGÃ<ôä¼xýE¤jézÇÔ‰#<óÌ"R+3üŠAd/؈-zzAáÀì µ3&8û¢ó¸gÛA²»P¹ôÀ,k¶™+øc|ó¿CsÿkØrv—~ÿ}Üþõ™•ý¯ÀZ+•JŤišŠHÅ{_«ÕjÃïÿßýÈoýÊÛß°Çã þ\·qO]õ)Æ®‚G‹žrüãc·Ršè£Ö7BMëtòE$÷¬ïᜑµɉJ|VoœÑaîÄ1¾~çwÍyÈ0ê°¤€à.ÒוŽ3òK¿ÈÇ_ùR®½Árû­säx’‚¢{e¹«üœÜtãGettT6lØ`l$‹¨t:{É¥—¾öꫯyÃ;÷àŽL±5‡J¿·Ru¡Ê>®?ŒÒ¶*×_°ž¿j':D£)EûL#5÷^•íµL ŠÒö]ÞpÙK°Uþnl{¦Ÿa¬1A󞬓ñÎWÿ.·?±‹y¦øì½·ó“ÿ‘òe#Ì5çªZ¸‚'Ãá\ŽbHÄ<7ëׯ畯|%¥RIŒ1VUIFáàC>0ûîwÿöÐŽ;§XÛwì‡ú ìšZ⺋\¼nž×=ü?ÿÁï°óó¿ÈGž‚©”´Äòú5ñ’¬5Øe]Åå·$I8qtsí6껜;yÆÌ{ºÎQ®¦9²Àëv>õŸ}óóm~ácßàò5›™iÎRÃB§Éb³‰.,Ñr)õZ‰¾J,øçà]ïz“““Ôj5õÞc­U{z °ÇsÓÒömŸ¨Û„]àðQ`úìšæöæV^õº‹¹qêkü§§pý ßJ~VFÅ(Ý>ÎW\Aš¦c|Ác2cLGDªåRéÐ}wü-—\º•C'€9`)ÝÚEðsʺ‹^Ͼ G-bf µêeà F±$Åê®ÅáÈ»‰)óÍ÷pÞºó¸ú‚+é¸.ëúǧ¯Ta°ÚÏd뉔ï&­V¸hò\”@µZç¬Á3hf#µ¨¡’ôQ/7HÓj”4I@Cã9Ø?uHßvÖY$Iòp|i–šŸäÌéûæK´ò™¯Ñ0C´Ú2_£Õ­1ßÉIRKÈ«^,3œ ]oØ?Þy²N`¾.˜…õ)—l¹œÍ#ãôW+ 6úÙsäà…òÁ|ô¹0@U¹éÆŠªš‚RcLYU+@½½pâÒαÇþ~ô½/€î!Æ*9ë–vðèÞ‹ùÐ'ž¸ãšóF/´³Zl'“—4T4.iÑ×ÄZ_/Õ:;é•c¯ÿáOb²QaÇ¡&Õ4e¸¯Æö#ól-3\.³®M+ƒUãîÝÇ*78o]…ûwÏ1^¯RIŽ.äŒx^½õÅ\øÁ›¿µs÷“ïèï‘¡,ïþøy…Á>ø!ýã›þ Xk{¡Õ‹H¾87ß7õè½·®;{-ôðÿpœ;ö4¸e-¯ÙùÛ®ã LLšRb.ÑK¨z£·Äëü²MçëHòÃ×o_d´zœ¹¦¡R³ ¬9N_Ç29¸ÄšAÏRb©´<놅ÑãPM3ÖÀø ÃP‹Ñ!a~_ÎÚ¾b~qé©î—žÚìè=øyg‚·}åkjšGôßù›½%^ß78°ëKß0´ïÁ¯6ßÿ'ÜubÿÈ·>íé{â CGY/éÓñ%žå¬qÙ XI©{ âºÛ½wä׬gL+ ´Ÿ'ŸÏ3<<ܸqÙ Ç1kkkXk1ÆÄõF£kV"B_ß'õzCŒÑFa„aH«‰µ–J¥Bµú¤."ßÉúÆ~8Šöì.U„4›M•¦ I’¨$‰I’„4MUæÉ2cŒþ¤ÞhüQDÚ"öÔIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/virus.png000066400000000000000000000113641217176075400230720ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚ«IDATxœíšyl×}Ç?óffî’Ëû(‰²hÙ–d]”\ÙV#Û¹lÇN“"AÑ:AÒ¢ñqšEI€IáMQ’Œ NnŠNÛq“ÔGb;±eY¢nÊ´D‹¤xîrw¹Çìïõ7Ë¥UI&˜4ú;»3óû}çû½Wè ý^“±Ô/|aÖÉ;…b›TôA(Hƒ!KñÆH’—¿ùþRñ³¤ìÝÂíJðHÛÊ•k–_·ŽúÖVìXŒÀóÈMNrîä ¦Ï yŠvä¹¥àiÉx|;¾iŸ¹ã¡‡bË×­£R(0óf?qßAÖ%iز3aòí·yúá‡Âlåê/aäýæËz¿_P%W²ceï²Øòk×0üÆ1~ðM1p•Áµv‚ξ ´¯^E×ÊŽØÐ©³›áÿ 6´¤,ú%´¯¥÷ëèÙñ÷¸³%¢õIL»Å!˜ ¹^pÖ`=ðôûÍ×’`@oª!Î,dCÅŠ[X< 9 >8>ÉdÝKÁ×’€TàJ¨HHÀ¥¯¹<‰ô µ4™`ÉŠñr¾•„J€O‚@ŧRt¦—‚¯EðÈ.’fmŽÏ¡/÷“]̽Œf( _‚-t’„V€ÉN.æùmå. wGK>O,”?±Ðìëã/#Ec¸«%õBÒ2†÷öñÄcÛÙ¼Ðû%üv|2§µ\ò¡èÃl8 žEYö›ÈâAÿBžûØVvìÝÊ¡ÆTâ§7m\}_ïªöIÚÆ‘=}ܲûTìÝÆCM‰úÈ® 4ZQœ&‹·ÇÓúõ) Ùò÷ý2µû8… Ýûøv:]ÉWϵ×'Zï¾m#fÔÃÐð†¶)AB)_â¥×O1šu|¥þË|ûÞýº_ñhäá›oZk­imOAŹÙÏýì ¸Á'ï}óÒ™ä=ØÓÇ-‰DìŸú‹VÜ7 ëBK:ë"&¿ùI?Ç_< |ò¾5³}dI»À7lËúâµÍ±õÝ4\³:WÁÀÿè8Pµ?+Ûþ†Žâ¼ÎÀÐ;;7E¾\ù±|í œãk_mn­øc¶ƒ„/`Æ7 íØqÊvÀ³ÿúJÁ)ú7>x˜£—À㻈¹ŽÞþ…k¤Í±çÏróÍ+5©ÄMˆZýÕ)^yª\xl¿÷#ûúØ©à‰ëºZWmï]A|ã-píNhh3™3púu(å´Ô5ÃÆ@ó ð}p8ùkäþg9rò$†ÆWʯ=p€Göõñ‰dKò©O>t+q_@Æ*>ûO‘šf×î­ ¥s¼ôøk‡ÆêÙ~±õ…y)noåþžMÝ÷l¾¹—ß?D®°æÚ6ˆRHÚ—7a™"9rfê¦waÇlë‡ÝxUóõÛw`àè¾"1-¬¡ Ù +6ÚÐ{#\}#¬Ú Ñ$HO?»© ãštÆmzÍ‚5‘+ÜùÁf¯×0Å_ßùàÖ5¦PöuL)ûàKê›ã¼ul 9œåº?ZÇÄééNc¬tæ§cv£Kp÷2ûÀoéÌMsºŠ 7¯¢!aë/:r:·wv6rîénKr×][׊¶¾[aÃmó…7Bàæ†Ôþ¯>>¨p|ý}Çj¢í+éõ&ÉKÛ׶խߺ J.žJ¾®¾$jB¢«žýû'X±ª‘ÖŽzŽŒô<=ƾEðØ tÇë¢ÿxó­ë>ž!ÞçšÞfp-´T~  7 ©.Æõ­-$·~º×Íü<áQú³”!>È€¹áÕ@Ä“˜ËzYíNˆaj­C<]DQöH%#lܹ’xĤ!áØÑ³;ëä£?OS:_΋ÖA@oc*™ 6´CɃ‚ ¦µ¦4¢šËíÉtõBË 4:"ÆÐ¹Þ, „7L¢`žUÚª Ô%}w}A½ äÁ“º®ð¥¾–.CуT )v”Ø…ä¼(†¤P.8 «·² †Ð ¡… ŒP›z"VíW…B‹ðûù¾!A˜!x‚w¥ƒùn!ç¹EàëàØÐ Ó0sVÿV ÔF a¦“E^Ÿ Xv_¼ØÒú¢.ðô8ç>ÔìíœÏ]uU2A˜¯ç´„F{ŽY M«5ÂÐBóŸwŸQTÎ~-(?Ô¼WÓ|uÈð³Uƒ5­{ó¬ ê ~À«#™Ìõ>øìî¢è[Ë“þŒ³v8“ÛК¨#±k9[ÎA*ˆÔCëj°DXëSóýêÿsVh75s—ABP „Uƒyñ!ðõ³™‰šÖ½ù¢Ã/ÎŒ08“Ñ|ìÁÃ/‹T îÙÄç…É·zÚR×-o§»¹ìjÙÓ‚Õ×C4v¬Xˆêléߘ–6}CÔÌß0Þ͆”(9ϲæ»Aàƒïï‰×`f…Sq9—›eh:ÇÛ3ùl øÆø›<úM.½ª\pKìñ]Äœ<Ÿ‚ÏØ¦ØÙ™JRµÙÔ»œÆ®nh_ ~žð–`êY˜5 µ¡ðÕ è9˜§}™Qœ·ûyâ¥CReüÉ—^¬4¿læÓ¾µ´ >±Ä“Ÿ¿};fÛ H4ž€­…ŸÓ¼5/ðIç@da¶ÅЭ½úw„YFó,@Öâ‚ïi <Þzgöçìtþîߣî¿-x58Ÿî;Å´i2ÝÞ”Ä4…t.»µ<.Ýys8*SPþ $G Ù„Á4Œöß@~\›wPÀ=oTƒaøL%!cYSÂ`×åÈrù ÉæÖTBkÔ¯hS<2´i‰†¸Zü”s0ÑQ3 ìéB¦àé V)›/ÀÖÛ Ϋ ªnPÌ€ïÒÜP‡RlXR¤¢§>fi'*Lm :ÿKjÑ.m(>ÒE-ð\z¤ö[§ÇöæBÿ?€ª¥ÍNAz4D(z–!HÚÒ È€â4È $›jɵZá ŠyȤÃAèt9?ÉðO܆‰sP)„® _-ŠÜ dF ˜£Z„ `®ôÞ7”ïa¡# ðŠ0[úF°Rúºª73­Ý$LŸR)2“EÊeËtt5 „ BAC&Ç¡«D¾³ÓŸÒ.P-´$(·rÙ2ünMQ%Qžƒk†LL nT T=˜ è 0ðÉÁ_Ÿ!Ÿ)ÍU³VÔfûÎU4¤b³ (®Ž/…ȧÁó¢ PºÈR€rËá²²è.oÑ•H§À\.7 ½X²„ØÏAiÊ`Vôõ¨ÉèP¯àŒZ$c&ɈÀôúÇj÷›äÏ@öm(§ÃÔv‘ª³a *E/@]fù²-À„“Ù²‡* ©Mç~S„ÃËЂX„ †Q¢&Œ„ ÀWÏ 1pÝ"‘x´¶úTFmU9_…þÑ-X h‹BSTûfÖƒ´SŽ.~Ÿ@f‘ fK ¢k™fª DD€e†³hÙ±åL‰dc‚ú†xM`·Úå©6\C³ŸÉœ;‡a%±ÛtPŒ @øL@¯$} ïdINóÔÛï8•²j»Ðù¢ApÏГPÖWîìèÀ:7 mñð…áˬ°›khA T… —A© æòUº-^ ÛÕV™ÐVÑØÝHcGCMËUuÔz€R>2=ŽœÎ ˜V\ Xí.ù2 ºètH8> SEZ0hŠØ±ié^ ¼±`LÎdÜ"fšu`ÿÄ–×vtK~Ø"¯2"Q(¥tÇ»TB¾s ³½ÑÑØï^ôT[jP›9ÿ³BÎÎLŒAÉë—* œªº¯š}•¦Šdg]D*NC"Bql¿rá¦èEpަŠãŬXÉ• œÊ°Å6±o肨Ыà…zà­‘<Ž™gÝÕ) SALä§0š›--ˆÆÝW2ì)V›UPªâ 3d: ¥Šî™J@IòEŸ™L†µÝ!êÝû$_t9<œåªuíx)›² í>Îø¢Ø}œÂ¾­ê铹ܧV·¶Í•xíð8;S1èJ„'=B+ð¤ptx‚L¡<îIÕ¹i]cX®‚a¨ô4A.M11uñ:½Ú ÐË^ÇC•+¨Ù"8øåê…‚òõÎñXÚåù#iß&+šSV<Õ­÷ù­¦`p$Ogʦóúv^{ó4À÷/&ç%»Âw.çÄT®tïõ×-­ ›ÉñY¬:›Û®©°ýò‰!†Óù{&wOLUvÎd½î޶(¶ýîbÓ$¸.”+PñÀ©@±ŒÊåP¥²~¦¯P~¸íæK”¯84˜ã7Ùq_q§çËÑ©\ñ–«Ú1 Â=Êð1ŽìeõÝÈ®:~õ³ÃY·¤þüÙ© ÷/ À3瘼£SªtÁ¹mã½ø€µI%£Zû¾áՓÞ:ê;|lw?™¾µü[öäàéÂN!Í){®+Ž20›–c-_èêD´¶!͘ÑfTÑE–Ëa¿ð%gÇʼx(ÍÙ çÇžÃÝ_<̉gÆyqW£Û8œÎîX–J¦!bBsŒ;–‘\߯/~ø:ùtñ«æ…˲€¾µ¼ª2κ¬ë¬Ûv×zRmuÚüg]*%—çœæÔ¹ôˆàŽjÿý¥wOñÒ‡SêÉñ´³r`°Ð[q‚ú¶v¬æHXº¦ˆšaêSU‡Ìç)dN Íòjÿ '†Š‡\W~þ¾ƒüÃ|->3ÎßÚäžšH߆”‘–x 3fCs#eóüS>1ñôýùò¥ä[P%øõ]X]³<Ù¹ªéS;n[O£o2ðê ÏŽû®|wô{©þûžMô`ò7¶eÞÿÙ{o%Ò^  ‚@ïòæ\ȹŒLò“g|ïÝw˜×.ÅÛžMô‚¯G,ñ™žöF«ëšNÞcbtæ9ÏáÓïÕ_T[|ïîWð%àƒÿð}¾³»Ÿc ¼÷3+W´üàŽ÷Aƒ­KØhX W½™Yð!ïòľB®ànÙÝá=ý Ѿ>ZeÀ=†Áf%ùåýüûBî[Ôjðþƒìö.æž*ZSI½¥]=X] x.­K¾>kÐÚ@¡<½À}˜þy±|-ÝAIƒÎT"¢•胑բÊWsGäðâQ è] ¶–ö¤¨¯´¶¥7ìU«B?Üó%¦±(ÏühéK+|}"4eB¼ºH2uJ-P W|Ååw:AKyZüd&[‚«-h‰1“w|mŒJÑEÄ#\××ESK<¬ãË(±¸“¢—K—ß\$™pr<;‹r}(zi‡x¡BS rî´¯ärn&ér`‰øZÚº–ÓäÝFÆ3½¦+©ODYÑÛF{O3ËêñЧÇx騳eïÛ÷÷óÔRðµtÑ&¤G7ñ ÓäO€mô``)íïƒ(Þ0%ßûB?¯,5_Wè ]¡+t…®Ðï!ý/dX¯ IP²%IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/app/vm.png000066400000000000000000000071371217176075400223470ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMAÙܲÚIDATxœíšIlW~Æo©¥76É&ÙM-–¥P¤‚lj#À2Ac|›ã ’kîƒÈ=rÍ)@ŽÁ&À9ƒ Ã`r,™¶m–)Q\D²Iv³ª»ºê½ŠU½°[–kAFX`mÝ]ß÷_ß«oðoðoð» 1î䕸RéŠî_aü—õ ™ïÌö½Æšõ뿼þ/0þKõ˜s"0Áß-7–ùó?ü9RÈ1·¼þ(ª€N/âŸ?ý7â¿w¿úû¯þˆGï'€~²¼°ÌùÂ*m3̓Ý~ýO¿fwk÷¹FŒw´ç†ÅN¼vé½KüÙ/þ„óåØ’Ë…¹ |{ïÛŸWCþð8”vÎÓZSÄ8|öñg|sý>üðC|ÿ¥EÅD!†ö³mŸ_ýë¯øƒŸý˜úR™Äº…:Ï"€@Ô=í±ÛuøæëoXYYaiiéűú$-e¢RJ.^¼ÈG}ÄÝ›÷)-¼  Nሳ€OêÝC¹`lH%Zj:q€ö~›¹™9:΋eöÈ,/¥+€µ–ùùyö¶÷ˆ’,¸ÊEäà'Ú Þþ«·ÏxÚ£—ôòsáQˆ[w_©“¬>(FÇT«UZ{-â$FAÁ- =¸<ƒÂ¯ú Oy©‚Çè´;xž÷ÊÈH 0¸?xÜn·9êa­ÅZ‹@P.—kº ý8ŒÕèwŸ@ûºîj—(‰òÚ츮K·Û}|‡0Žlv~pÃlÑblêBÊn™êUOíþ÷îíÑï?ÊQó¾ö‰ãDa„@`­}錳ð éÑs·nÝBJIû ÅæÏ]ôŠL™:³Ëîw{€òÔYW»D& 0ÑR#„x©ŒZwÔâƒ"cBpçÎ\×¥×éG1Žë€€¢SÄŸö¤‰P0P O ¥l(¡ˆâîâº.QE/£VŸDztccƒv»ÍÜÜIÐ ˜ªM!¬ ä–p§ÜE@}·BÖ…ôL 8ð}ÿ¥ð,ä³ÍZ‹1)%ƾúê+¤”ÄqŒçyÍ€ê\!¾ëãún¾ä@*­€´ è]ŠÅ"GGG$IòBˆËÜùiäG…X__§Ýn#¥$I|ß'8ò¼ä”Ð œÈ „ B¢$M~ÑQ„çy„aøÂÉZÞÚñý~VÞ²­×ëqûöm”RùuÏó÷Cé8¤ä•Ðþ9Nz€£Î$6IhEøÒªûOOOsùòevww¹víÚs“´j¶)¥ò}cLN4í[·òûŒ1iÏÒê¤ß‡DI…ë¹sŒi††Xù‹•y-4ƒD"˜ngOÀq¢(¢Ùlæ÷¹®ËÊÊ ÛÛÛlmmM$¿¼¼Lloo#¥ õ¸É#(‹Ôj5>øà„A0ÔÔ$IB©T ÓéP©TXZZ¢P(pxxÈÌÌLž…)  …:ÙÂÄqL¹\¦×ëÑjµ˜ššÊcºÕjå.°¾¾N§ÓaŸ‡Òl6ÙÙÙ!Žc‚  Ùl2??OEܸqƒ$IÆ>›Ö¦ÖÏf‘µ¯kÇW‚!´Öó¯’—@Û±yöž„ö÷÷Çöç™uÇammm(l²¡µ”’ƒƒ¶··óÖvkk‹›7oæ×¿üòËü÷®_¿>ôû“žMRÄñìjñ§‹õÏ6îàÝ?w¦  ž«Ý4f„ÄFvbw–!Š¢Ü ãFqæ‘lò"kš”R¹¸™0{{{ìïïµ¶Ï ­5²›>6Äb™¿8f㳜w¶#JgJ‹žë¥îÜdMÐÓæYGm“¶8Ži6›µ»ÿWH)!ö€B­5C°¹…r¡Qp ¸ÚMã_JLÇL qÓSƒÝFÇúaÒjµòQfæ!?¤”èDc‹Ôi°ÂRª–†š¡Üœ¢óVÑ)âI!ÓºÑX¾¯•3bÝn—0 Ã0o™(‹ÂƒïøÐ᤿/¬À­¸§ý\¥U­ì•q´ÓO‚½Ôm²ß“Hcèõzôz=¢(¢×ë¿gȼåEÂZ›Îv{ÈJßÜ‚;X M_ ¥ë¯’—@k-$ä34Ù Ùùl”–³Ö¦3Ê#xQ–ž„l^ ×éåCbƒA{ùK ´h”½2®J3vÔ‰PB‘Ø“uvÒÈ0˶î³Âó<Ân˜÷‰[pè{@_)å©) G¥!Ðévp—0sÂ0dkk !Õj•éééWÃì!„@vÒ’n„AXã93Ço‰$ôPJ«S¶Áúµ8 Ýn355E’$„aÈììì+!ö¬PJå½€´i9”HÎ]9wúÞÕ{·¡/€”RÎÿæëßPÔEÊ^³eN¼l4t:4ÃúþÄñÁë)%²×ƒd¬A XXZ8}ïê½~\úÓK©eQ"éš.Qa›–Íÿˆ……îß¿Ÿ7)Žã¼ZVßR¦ã™Á`±”çʧ8žÐõËõŬùtÁRbÖÖÖ¸téËËËܽ{wâTõë !®uÓŠ¥ú•À›òònP¢:_=7XׂÐKÇìwïÞeii‰••îÝ»÷àuƒ§=‚^€Ò*÷‚B¡¿%ҀОnyàW}vj;8û÷ïßçÂ… \¼x‘½½½WÇæ{"nw£.²(1¤9À-ºÙÔ˜Ô€p]wAJÉ¥¸½Ÿ ÕXØv¶©7ë ƒ£Þ¨ciqD ŒQ´¥@¨È1Ç,\ׯ 'TT¾­Å&Ïóàº.<σRJìÝ»œóø À²Ù,Ê·oã­·þ†a€s€°ù€)“Þ!e8NJ5^úýRB†c¢mRŸj9çp]_|ñŽ;† .`rr2c`Aݽ{7|ðA„‰/×ÏGt_Úñ£Ž€sŽJ¥‚O>ùÄh Æü±|C `©²à&˲@D›p¯Çº¦ä-—Ë(—Ëð<ÏÇà %„èÝ7’Æ÷ûçyC ežÛ!`гãýŒ14 ܼyëëëÊœtßPTcÁüæºnÈî½>iœîF£Æ)Q.—á8N8… ÆH)Ãê` e:â~;ã°v»r¹Œµµ5诊TVlÆ8ƒDÔyäLNNâÃ?D½^ïj+®±YRÓéêê*Êår£ÿZo–M@`œõb€bÏž=xá…ðÜsÏáÝwßÅ|€f³ùû¿®u˲ðùçŸcuuU8¸¨ëþsÒ̬—ÌÄ ¸rå pæÌ¼øâ‹8{ö,.]º„Ë—/£Ñh|cþ¯Àß½{ èt:#ëHBŠ´À@¬ušÍ&®]»†ÙÙY8pgΜÁóÏ?gŸ}ï¼óÞ{ï=Ôjµ-ƒLr Æ\×ÅÒÒVVVB7ØLQþŸY_#0bàäû½çyaZ©RLÏó0??7ß|çÎÃåË—ñòË/ãÂ… Èf³‘qBˆð8~®‹WETµZÅÜÜîܹ³%ðDH@B¦³FÌ„­&Ëä¯Dš 8Ètuê/ÒÛ/¿üÙl6QûD„f³‰µµµˆÖãÀ‡åqôV'£— KQ0ŠåJ`E@ Þ'Þ~ûí¾~Î9<ÏÃÆÆªÕ* Ÿ–€8x!Dx¬¬×‹tA w…âZÛ, qb;666`YLÓ86­è¡*C$X§‹ÙRDŒ"`xLkµêõ:¤”}ZE@Òy|™®k^í(B HX¼t q2ôsÛ¶Q­VaY2™Lª¹}”$OrÏóÀ9‡€„I["c@\ûŠ aÿ0"¤”h·Ûá*Qi}»ÄÁ'i_UÃ0üe½ÒàT ãœ÷Mª:yDÏóÐh4`YVðÓÚhWF@܆ù¾N€çy`œûkÈt Ï­*Ög†QñÀ²,´Z-!ú¦Á8z–6Š€8ðAàUëy2™Ld?3UÔÆ]A'A ^Òn·aY8ç¡¿§! NBš¹”öca+e°–õ çÆ 8¶Ž%¤Ýn·—I¡Ì0P!ˆH_¢‡‚Èâ_s]WûJÌ㸉Ñ(Bôrgå{Q@Q'^Ó5!#,@=¯¤º'bòCÀ¥)§A!E  µ‹ 1ÿ4Æxd ­‚©mÛC|·_«RÊ0ÁÒçu×uáz ed·z;…¶Ë`šòÄO`´ycù|~Â4ÍÜáÇÿˆ€ÜÎ;‘Éd†¾ƒ1†b±øÐäääÉZ­Öìt:5-øDxAkC#„ˆ‚º9"R»@^™µm Í|>¿÷Ðw¾óÝ#GŽ=~ìØáC‡Ý?11q_&“™X^^.üøÇÿdt: s°m?þ¸<þ|CµF½þõüÂÂÒìììg7ææ>½}ûöÍv»½  ß l @l†„‘hZWfž!¢¬”2 À¿cÇ2 YÓÄW_}…Wþê/‘Éd°ÿ~”J%ÌÏÏ£R©„û ƒŠ¾ðÀ@J‰……´Ûmüô_þû÷ï÷#Úí6ÞÿýŸýýÞz­^¯ß圷¥”]Çqìn·ëyž—ʆÆ"¢Ý»wÓôô4ãþy@®Ûíò=ôǧO?ó78:í6ªµj• 666ðä÷¾‡¯×ÖÐl6Q¯×ßÅL3Æx¢è+9ÏóÐl6Q*•pâÄ ìß?þwi ­V ãããçgΞ=sûö­¹_ýò—ÿœÏçsâçyrqqQ¦ ŽC-`zzšžzê)2MÓ`Œ™RÊ<Bú¨Úÿó„.cÌfŒu‰(Ï9_ðëëë?_^^>öõÝ»T6Ö÷~úé'ù|>_/ÒŽÒ‹EŒ¡˜o6› ·ÐâÙj¡Óé Õj¢Ýê Õn¡^¯£ÕlÉv§Ýž¨_ž˜˜¸}àØƒ¿›˜˜˜gŒÕ_ï !ì@>OÇqpõêÕaðF[4 2 ƒ9ŽÃ¤”&c,Ë+Ñ)e‰1¶“s^2 £(¥,µÛíõzm×úúÆ®F£QªV«EÛ¶ ¶ãälÛ6!eFJÉr¹¹®kpn¸¶mI"D䘦ig³Ù®išíR©Ô/ÖvîœØØ±cÇF¡P¨0Æj®ë6<Ï« !*DT“RÖ…m!„EDv&“®ëŠb±¸ýY@Ç„ @†1–•RæŒ1ÆŠBˆ"€•ˆ¨` ~2” ªÊ 3RJ€I)IAŒ1$1‚ˆzYŸÀ j¾7¤”55ÆXCÑÐ"¢®Âà0ÆÔsRK3ˆæùjF0á§«ùtÀ¸v\ÐHгE•P©¢r}=ËSàÛAmhjÇøÉØüŸüf ïAþ¯È05À9DÁ›è­˜ö%°@/ßWÙ"¡««k ô–€‡`¶±’JZýqDI1]3¨cý^}…§¹±c¬aË IDATxœì½y´\Wu'ü;çÜ[ëª7Ožô$ÙlÙXŽ-$ƒLÜØŒv ¤a%!é$_€„’^Y½i’|Yd}i tt'tÜôJ:b f0°gÉšek°Ÿ†÷ôÞ“ÞüªêÞsÎþþØûܪ7H–mC:g­Ò+UݺÃÙûìá·‡£ˆþþÛø¿kèWûþm¼º#º') ˆ(‚M-Œ1PJA)ï=Œ1ðÞÃ{PJ!Ž#X›BëD”I"­5œs "h­¡µ†µJ©×&"DÿÖZË¿Gr¹DÞûbOOOiÆ ½º¢(*0Zë^ €"¢sD4眳J©ÑcÇŽ™ÒZ׌1õùùy¤i ¥¢(Êž'ÜgxNcÌ‚ûŒ¢ÖÚ%sFDÙñι%ß{†÷>;÷âg¢õzµZíeÓî’0À«1³¤i çŠÅ"r¹\骫®ZÛÒÒòšõëÖmÞ¶mÛ†r©4X*•º{z:ºº»sƘ\±XTƘeÕÞÜ܈(OÆÆÆfgffNÍÏÏ?¿gÏžã‡>\­V÷íÝ»÷sn2IÔëõŒ‹ ôã0~¬ ™èq£T*®ºúê­¯»ù¦›v¬^¹rûå—]¶²£££P*•`tœ<‚w"ï PŠE€R0Q„R¥‚ȘÜÀÀ@N)UT?@?á½ÇÜÜÆÇÇí³Ï>;6::ºû©§žzêСC÷;vìé±±±‰z½Ž(â)ýqau)ŒÀ¶ PJÁZ ­5J¥RËUW]õú믻îí7îÜyÓ7nêíêŠóQ"ÀÚõ4E-±päa•´‚ ”†ÒŠÿòF-4„”‚Vï LÄ¿‰ «”|>¥5ÈyÔjUŒãàÁƒCûöí»ÿûßÿþ7<ø½áááÑ4MaŒA.—û­þE3@’$pΡ\.ãŠ+¯¼æµÛ·ÿÌMo|ãíÛ®¸bSo{X+ m4â\Œb>h g-ÎŽcÿþýg{ì±oÜ{ï½ÿ°gÏžûªÕjâœ[¢"þp~àÕnP,ò;wî|Ç{n¿í_·}ûÍ«ûûs‘Ò¨ÎU133…¤ž$b\À BE­‘L¥4HV?/q͇dsª2 ¿ Œ¡ð÷F7ˆAž@LdÐR,"2õzCCCxôÑGŸ¸ÿþû¿tÿý÷ÿí©S§Æ‚Áª”ú7–2€sÎ9¬\¹²üÖ·¾õÿîæ·üê ×ÿĵ­mHçk˜œ˜Ä|­’I‰Ð<)0a ËÿµŠyåëÈÀóòæU­uãPK¥ šô–4ç4FCk¥5ŒÒ|}ÅsÎAi8ŽÑR(Μ9ƒ]»v }ýë_¿ó[ßúÖ?qâÄeÄ¿1@!MëHSBKKKîöÛoûà>ðÓ¿¾mÛÕW·•K˜›šÅÄø$’Z’kFLVi0ÆÐˆ ´Š€XÃ+Í+_ó±™>VAþ€‡b~ÊŽÑPF!Ò,m´6…ÑrŒRpÎûÎy˜8F©¥­5&ÏMà‰'ŸùêW¿ú?¾ýíoÿÅÉ“'G ŸÏÿßÍ!—ËaÇŽnù¹Ÿû÷¿û–·Ü¸£³³ S“S˜:7‰4õP¤¡PÐDB2%+¢Ç… ¿× ÌÆZÃG´Vbè…“© Âÿ”QÙŠ—S0P&ˆ~&8?—†2šR¤–grÞòë­ Å<ŒÖ8{ö,zè¡ãwÝu×g¾óïüõ™3gjA4õ ¸þòË7nøÈG>ô{ïzçÍ?Û¿¢³³Ó8{v‚Áh(Ò §òP.Üx ?ëRE²¤"@Ä=KˆaHЉ©”ÛAg‡òfô?#ÚE³(*€ßËqZ‰iÈ "&$9~þ|¾¥€'Nàž{îyäÎ;ïüÄSO=upmÃøWËÎ9¤iŠB¡€÷¿ÿýú…_øÀïnÛvE¿s FÇÆ‘Ô(m 4^±åm5´@Êðñë AP0|#FV`Æò>Šmä¯fó@›ŒñuøM1BteŒˆøHV=ß#ÛL| è•ÆZÖâr0Ó{–ù\Œ$I°oß>ûWõWþõ¯ýNŸ>=EQFøu  ”B’$ؼy˺}ì£ÿõÖ[ßüîîžVŒŽaffFˆ¡Ãº< I1±=¯¡¼çk9‚V d«ÏyæÏ‰Q”‰ ¨ó1@Ð÷¢Q”10`Y µé<-¸«€ì.ˆß`ï¼ó ùMÅÐZabbwß}÷3Ÿÿüçc÷îÝhù_`ä=ïyïm¿òËü“í¯½zm-­âÌ™Qxg¡iÜTÐá&<)xÒ€U0žX @&Ûó?ªi¶u&ÞRJìD†ÝÅHg:š“‘™‡µ‡†iR'Ú˜ÌT`,@g_ë Ÿÿ0k;gE}i1S œKñôÓ»ëŸûÜç~÷Ë_þò%I‚8Žÿu0€µ¹\NÿÂ/þÂ'ïøØ‡~gÍ@¿ÃÔô$Œf‘*7 w›§Ó{,`< ˆX¸¦)&&¸lBD(q/v3B$ÄÄ6 İÇTÆ|Œ‚+Åç1bv(Yý<ÎOü P‚ØÙœ+™ƒcÇŽáoÿöoÿÏ_ÿõ_ÿÆ /¼0pƒ[HÓë×mèüè¿ö¹Ÿzß»ß_iÍcøÔ)$I#z43¸DGB‰èL ðp<§< ¼Ü³Á-GˆqGB!Å ­¡"a†à&*^Õau¿ž%Š‚Q¬ã3ie¢ r4üÅ?ŒòÌŸOOOãÿñw}êSŸúù£Gî‹ãXp‹¨œs°ÖbãÆë~ÿÿýýÿuÓ­o|¥gNŸ†"b݉¼ˆk—ùb€&°þ&¶ô‰¼30^ŽW¼"6•gâ­(••Yh䨀ÖâÓ7­®þh#H!ƒ?¨aë?0­RPJüQ­/šøÍƒK¾O’ßøÆ7N|úÓŸþ»víú.Àª¢y\ øá$„( MSlÙ¼eë}öÿûú[ÞuÓëfj³:y RJÔ;e£ðÃàß³‡jvö@y°8‰ÓMçðr¼jœ‘À-‚„qÓ4\¾æÀ„TJAP>h"fãwD½Lâgϰhär9Ü~ûíŸþô§¿ò¶·½í}>¾ÔãÒ‡ƒ Hê ¶lÙrý§ÿìÓ_Ùñ¦×ŒŒÁä¹ID:bï Äq–@8Åb=àãÙ‰ž Zy-D!„ÉöAÖûá"ß E’ð‡‰ôp€cƒb Ø#*C D 4™ûüƒ%4¼Hâ_h(¥ðú׿¾5—Ë})—Ë•¾öµ¯}1|~©Æ¥•ÔçêØ´iÓöÏüég¾ºýÛNŒàܹ Àh¬ð{€cò.3÷&™@Ä꟩G€¦ÌM'£A Å¿ÑAZhDâ.’”ÁH>‡\?¬*…Öb€2ñ²÷™ 4è/Ä_¬÷/ñ›ÇöíÛãßüÍßüüm·Ýö‹2$õRŒKÂD,mÝbÓå›®úÌýÌW¶¿iûêSç195É>7 HHó &"QJ,€W!æ'ÝÀ‡”ÉT6ò3e«wC”ç¿Z¼ E`×M†¤j0TÜ¿à"Xžø¸äÄcûöíñÇ?þñÏ¿ãïøÙ…Ä+—„·iã¦Á?ü/øwÛozíêá±QÌÌÎB›†–áuH ¯á¼’5ÏaZ ¸ýA6ˆ‘({Áãj¥ø%K^ëL§±¯¤=«å„‘<ä`@È̪`z4éo€ÕcFÁÿÇ/G|ýC!~Û·o?ö±ý·›nºéÖå’L^θd`íàÚöOüÞ'îÜñ–W ŸÁää$t²¨@l‚× |ÇiÀ‹^·™~nœ×ƒØÔS*³Ú”&Y$êÁ7Ä@ÐÝJ”‚ï‰Øó€çÃÈ‹Æi\,3G5Ü; e>óRLFüLÿ‰ÆÎ;+wÜqÇÿܰaÃuóóó¯ø|—„¢(Š~ý£¿þozÛ›nœž›ÁäÄDÝ"’Õ§ÃÕÇÖ€wyç›,Õðܤ|H€!ÎÞ‰~”‚ (¼|p䇉5¨ç¨-¶€j€<'¬~Å×`|rІøK¢·¼å-½¿ó;¿ó7kÖ¬Y¹\(ù¥ŒKÂüà?ñí–<ÎŒŽ±ß4±Bæ'³Ñdzî¡A2‰NˆMZ¤|¶8µjZìPÓ‚$åùÿ‘ü±_ûD¾Ü‚“§G8JÅ«O“|J¿@Ê{V;–ÆF Dq Ä®ФÄïæ0”g{@D±²'ÁžàþƒŠ<ÿ^œŽfÓ3˜‚*xY_HB‘+éWøa”Ëe¼÷½ï½õ¶Ûnûä+9Ï+b€-›· ~ôcwü·ÞU+âS§F@¶±Òì’x`JܺìsÑÁ+Þ?o151ELeï£@>èþàÔñð¤Pðñ xH ¾èÃ@Tƒü_ÃBΜÁ±:4¿@¾*€9ÄßqP€sðZÃPSJ˜Z…3qì¿äù—C|/1•[o½uððáÃX©T>833ó’P¢—%®¸bËeøÙ_ød¹Üƒ‘‘QhDPdxùQ8ÅR7“`¦7 0(`cø=K RœÈI€D‡„¡’§å·" Hd9é&‰AOÔ°îGö"­‘cäs9DÊðçªa†”³LíË›@üW›þžä=Ò4Ekk+~ú§úg¯»îºÛ_êy^²¨T*ê?ÿçOþÁ•WþDߨè8lâ # 8@ä8Ê&‚¬xò õ0¼b#ÑËTj>´™}5ØKК„½HŽò…ÔPhvç¼øë¤Ø–ˆµBlbäâQ>8Î!Žc.‘¼%¹Ô”©ˆà$Êèd AªŠ^}âqÒ)tÎaóæÍøå_þåO ¬D{ï ä+¨\ÌT$8ˢΉ¾q À %0ð«=¤‘€Z­Ž®®N¼ÿýïÿµ7n¹ØS½$¸å–[>ð†oÞ153ZkåÙËR ¯©[ÞS°\7^Vp}0Dë='  ²µÍD÷b'xhf,pÐ œ r(æóèëY‰¾ÞA”J]œ®•Eÿ¨/7~Œ»¢4VQ Ží믿¾ýçþçÿS¹\¾(~½hX³fMç{ßûßnmëÁÙñsÈrw ™¡§¦S^–A¦¶D*xo¯Å›ãлÙÔx ÅI#l¼œ0ƒ÷J+tuö£¿wŠ…N0•jBËò±9Ï“*Õ€ŒÌF0P=y8ËÏ\O”ËeÜrË­ÿ~Ë–-Û/æ<Í×\sÍû®½vç¦é™y8—6ââªAH9yùðžU\E1ß).øhFŒÂêÏÌp&N¢¬)9´”Z°ºw-ZËý`êZdÏF“9i4‹–PjZZ€8fc0Ô ü Glóm„y½xàÕZ [¶lνóïü–––•e¶··•?óé?ûŠÅVŒ b‚+!`ÐÉÐ \^ˆ©¼a­%mÛ×éÁ´—_P®afq’ÔŒ=]XÙ¾BÀÙæhp%@€F’ÌàÌé3þø±cÕᑱùÙ陚\E*Šc](t±µ5ßÕÑ‘ïíë+ôôöÆ¥Réb¦æG>8w¦RJÓÏ\ãz’ µ\ÁM7ÝtûwÞy€=:ßE1Àu×mûÎÞ¼mv~֥Њ‰ÝâB‹‘FBï¤p”:NWü$d”˜C¿!¥‹Ý0®ú¡ðІ°¢kV–ú°@Ä/@i:={vÕvïÚwndäÌpç†W­^=Q®TfW¬Y[íhowJ)EQ¤ÉÏLMµÕëõÖãÇWv?óL[±XìêîînÛ°aC¹½½ý_„ý·˜øA²ndt ··×‚EÂùž.ð’‡8`X¾‹×¬Y3÷ö·¿ý€sîñoûÛ§fgg/]zî2Ãàš‰O>›ìæ&9Îïxõ‘ÒÔ‚@ؾ}ûk×­[·í|׸à Ù¸qÓö+·^½±^¯ƒˆË•´!(d(€…Hkˆe‚·Þ®¸âŠ×¬_¿þ O,¾Þy`ýú WlÚ´isš¦ðÞ1€Ã‘X¦ap?E´{δê,€¦$¢'YR¨&̆¹Å+Žù–+-èéì-j‚€Š(⾇î=uüôƒ¿ñÑß8ñÅÃÃÃjµZK{{û™+VŒi­-FTóócœ1¦Z(æz{{GêõzéÔ©Sý{÷îݺråÊÓ===gÀLpÌÝÑÑQ¿îºë<ú裹ŸüÉŸ\ŸÏç_¶e¸€øh?Xû™Øw$¢žްÕ^Þ‡¢›$I°fp0^³fͰ œ×\±bÅ«W­Žæ«ó.å|;­Z3¸Ã¹s£C;>-ž‚—ÊZÎÇÏ,v"x§2µÀQ?fï8ÊÓ×ÕH…Ú €AŒ"޳O~ÿ‰'~é—~i6z¹0››ë8~üøƘÚúõë÷vvvŽHà$Ë^æwhú܈òù|mýúõG7mÚtxxx¸ûСC›‰(0`¤é7¦¿¿¿ºeË–ƒ>úèØË­ØYBü`é#XûaåKB-tÊÓÈy€¸Ëj­VCKK vîܹ³R©,‘PË2@¥R‰vìØ¹=_(¢V«eÉ ”—“2ñ Õ3€Ql,ªPG—•^+vi²¤]ø@ .µ'´´”ÑZ)ÂSLlƒ.uøæ]ßxîöÛn¢R©ØeîÝNNNö¯[±bű¾¾¾!ùüåŠe * Õ«¯¾ú@¡P˜{úé§·:ç `ÃðŒdÖ¯_?ÇñÇ/ѳ/6–Yï€àêÃŽ<‡ÎYð÷ž<{ R\KÞKç h(¬_¿áú8Ž»_{YÐZ·¯[7øhç­dß¡µ¦2*˾6†8KZfMˆ¤ ‹1 :Òò¹dlëò°·¥‚¡4º;+\m#‰Áþ)¸ÿþû&Wöö?±eË–i,U]vbb¢||¼ݺuûŠÅâ¬s)u @¾Ðßßz×®][œsy£jMs¨¯¿þúá^xá…¹¹¹‹ØYL|ÉŠ Ÿˆà½Ëˆï­Ï\lGĘŒ'.´2+c¤ÖbÃúõ«7nܸi¹‡[2Ö­[·&MSIõæÁ+œu¼Ò*«öitcóÈÅQ¤`"cF³”БüUJ²k5´òlü ¨´y3YÀpvzÏîÛàï|çq,]Ñnnn®klllÕºuëcÒó=×+ñªU«Îô÷÷ìÚµë ϳ=Þô½ŠãØmذáøþýû'.愌ðyøEÄo|ÏDeذø§Ì{À[g=7ÆöN$‚tD Ñz’¢§¯W·¶¶^³ø–¨þþþ«ûúúsi=md¿ª…]µCŸ]£”tÍtÐ:HBd4ŒQ"!§ß!ŠH¤BhæDÚZKˆÍ"¯Ç²ñÈß?{Å–-ûK¥ÒbÑOιüðððààààacLr¾gjþ  O° .vÅF«W¯®T*ÓÏ=÷ܰ*˜oº¦Þ°aÃäìììÐôôôA"/ćw™Ϻµ€à,Ib—Ÿ¬—›ç–sÞ[î:g¹Ín÷'$$µ ù6lذuñ},;Y¥RËemmm¨Õ«ݲuf#ž² Ù, ?›ŸõgäAˇâ£×ÛCÁhÖ¶7ã ø|Su?úì‘o|ý0–Yý###ƒ#¹\nv™ï›ÉTêõzÛ¹sç*ÓÓ3éä䤚íðÞ—äW?ï07n|ajjª811Ѷ2_L)E«W¯>}üùçgÎwß$ö‚¾—òYbâ{r¼<`YÖ‰aŸk¹Ù¦óLt0”÷$n¢g5®4®¾úê ííí-Í÷²Ä ,—Ëæ·~ë·.3F#uYæÇ¢Ef3|§àHAþRy°¡(ùtšÒµò ‚rq¥–˜Á%Õ8l€]{÷Î ¬^u¤T*'XˆôùZ­ÖQ¯×s«V­^îYšÐ:99‰‰‰‰ý###ÏLMM¹úê«Óz½®smÖÚ+[[[¯íêêZ“ÏçÏA e½¥”¿üòˇŽ9²æúë¯?vsrÛzpppú¡‡>“¦i[s÷Ïfâûl凕NËÀ¼œ¡L’¿HjÁ‹]ÀDfÞÁfNx IDATábOÌ<޼$ÔHÜÆÖÖÖ Î¹ Xj-ÏÆ˜òÊ+¡®åûf¸—Â, »[IIE­IUŽëð€drV0÷`]Ày”Ëär’'(§TÌ?8vìÙ±;¶ c©´¢ÑÑÑþžžžSXÌ‹ŽKÓ´ëàÁƒÇÓ4ýj¡P hŒ íkçÒÔž>{öì½3337twwßÞÕÕeÌ-s]€ýÿ)­u266ÖÚÓÓ3 ,år9[.•FGFFrÙˆŽ± b‚85–œp’Üታ|àYxIAä}VaåÈ £`áï=FÞyôôôövwww8“=È’Ù"*–+•¾`Y2!ÏgL¨Bd”Ò,Ú5¤ÅãÆðŠŽcÎΊ"…8Rˆ"…–’É2³Œi¼¦§«¨V§O®_¿avѽR’$ek­)—Ë“8¿è÷I’t =qüøñ?ñÞ57¯lÒ™ÓÑC'Ožüã“'O¦Zp~æR£CCCÝf ±¬X±bâìÙ³³MóÊî1U D\»†ëç±a—²ˆ·^t|ê`­ƒ·ÎYùÜÃZ o-ˆ–§‘Ïs†ÐÈŠ™ctôÔlWW×är“?;;[jmm^îd˜ññq{öìÙ/Ykéb+)¥ÐÞÞŽÖÖÖ¡sçÎÝ›¦iÎcj­m±X¬Ž—À˜@f,åóy牦ªóµL{Gb™K³,ïà‰ ÆÄNaψkÉ#uÞ¦¼¢½‡ [ãIóiëYô;a’Þì xØ€¤iØY­gÁ3,~¨B¡Ð–Ë磬›"Ü4‚· m¨ÊQ~ñƒáÇbU AŸ1‰Î¶]i[¸ú¥§fffç;;;—ˆç\>MSËåÎ×!‘”&&&žÔZŸóÞcåʕв›ÇâÞü‹ˆ +â4I’{gff¦qþ0³nooŸ›œœ,€ SJ)W*•æff¦ «^âù¬\FTk¼ nëkgyõ{ga­‡u$V>3‘#b‹ßÙlµ{â< n‰ÈùSÄnlšÂèÆ˜ŽæXbÆqÜ‘Ïçµ÷&HÿlV)3äÄÄd¶óé}v¡ÄÏ—/x¤%?€ó„ ¹¨Ñ\‡D!1^Ò4©öööV±ˆQÓ4â8&‰Ò-+¢§§gâ½{÷>¹ÜÊÏår(5”RÒÙ4E½ÞHœñÞWµÖ{:;;·ƒ3„ëÕÞÞ>?66ÖÆ‚ ø(ŠêóóUKã%wß á¼l(R¸¼¬\ç([ÅÎ3ʇ`0g^㊘^Ä|à¿Ls@l\À:‹(Ž µ^ˆqœç÷ Ò’ÝgÆž`>˜ ÁÉÊU E‘Ñ­™ø!L ‘B™¥ÖM%{HÓš-—ËKšà8çb¥T œ×@ÓÕêü9çÜiæ¨ÆHúð‡¶«Þ³ÈÍçyK¸Åsá½?íœóƘe ­µ“Ž]]5À¥(ŠjóóµÔ:ʳ¨¶À!Ùɳ…î½–÷ N‡#粕6§ À‘—9‡'y/YÁòy,‰ýÆö>^ìëë«¡ÉÚÏår6MS國1!¯oÁ(—ËîúíÛwÖkõãAÏç‹Ü¿˜™Y«Éçó‘#G²  1-·ß~ûf0Ò·³ùñññb>Ÿîh¬;==+W:âZÍŠXö€bÑíÈKmÉóKI aâ ("2cœW{³Ñ' RP›aÅ‹çÀÅ4ÆD«ÖjµŒØÌÏϤiZccÐd[è+°Ñ[BÔÐ#_*ûšV¾Ê€À$zÁÆ *Û¾M±«# €ׯ¶¶¶òôôtÀÙ&PZë$Š"J’¤X,g–#ŽRj¶½­íºo=ú{ØwfË–-ؾ}û’U†µƒëÖ!±m• òù<ŠÅâ[ºººÊ&ÎÃ499YîïïoÆŒÎ9:{vºÒÙU2õÄqd,¶µëxYš$b[)‚WÒ_)DB(#8Ó¸YRñÊÏŠr «h@SØXbX‚ˆ¤iz.Ikš6@Æ” ?W*8„€VšW>!‚Ž´d 5V½ÖFkD*‚6¦)‰Á ŽÍ÷Ø×Û[šššêXfò©X,ηáüá[_*•ÜààšŸÝ¼ysÜÙÙ¹ìÍ#Ž"ÄQ„J¥‚öööMëׯ¿9Žã©e®Ïð>:{ölI‚Aaª;??£­U=Fǰ©ƒM=’Ô¡ž:Ô‹$µH,!I Ö‡Ô/@« 뛽6âÈù Mt>„„ƒ!)…Câvz ƒ4M`mڜIJ”FGG'ÎML8–ÆÁšk¼…´V×Ù?XØRU²~´ÖˆLÓÝJñf‹oÉ®MÉv,`ÅG>àâ©sèéí'''W$Ia!çê®®®sSSSmDt>¬^˜Ù¶mÛÚ7¼á éîîŽ_¬Ã6!µÖÚ ===¿ÜÑÑ1‹ó3˜;uêT[¹\Nòù|5œB^öùçO´j]èÐ:Fš¬å,'çk›’„&ü>µ€ ß9‚õo%µÛ1VRœoGpHŽ!ï2Æqž`½‡Ò@­VCšÚ© 2Àäää䨨Øt¶£¦â¨^†ÕB¾fèlZ…M£†} 4”Š`L„HkD&B…}øŒè$Àû¾ÎZ´´´ Ri[522RZD•Ïççã8¶ããã]X‰k~>¥ÔxGGǺJ¥òÛ6ZkíØÕDü4Íuwwß<88øk}}} |ÙqèСþ 6Œ7€N:ÝÛÚÖßa…%‡Ô{¤pŽ`!±—Öz¤)!‰:~YË´^CžQB/¸AfDFhò$‚Á‰"ìN*£1??OI’Œ4?Ã/@k]›™žЫ6›=·QmžYŒ=£…Û6(qbU ƒý`B?_>§'ï6ƒÑ„U«Wõ>|xõš5kö/ºUµjÕª‘£Gtww«l禥LÇñ¹ÁÁÁÖÙÙÙÏÎÎ>Çñ­õ!ç\Uì¾(Š6W*•m›6mêÉårg|©å‡;qâD'éþþþs‹Ž£z½ŒN®¿ìò-ùÔ¥ðŽû8&C¾ŽSçA"]ÙÐ@Úâg}èzÎp`ÆÀ>CûD÷[Øü#¥3•:==•ŽŸÎåò*Iê´„ZZZ”1fnttô$‘ߪa0‚—h&öu€òÎûW J@v×Ä׈ âV&ºióåPXªDuhjÈØ R ¤’$ÁàÚÁ–çž=|YµZ}®X,6[üº\.O”J¥Þ^xaÕààà‰ÅÏÓÌæËåòü5×\³.MÓõ«V­ºÍ9§´Öª¿¿?)‹ÊSgû^ÐÅtÎéÝ»wÜpà Ï/ÇìråµQ>‚Kƒ4B(oÃÞÉ'ÂKkH¶}c[¥l£¸­½G(Qâf1xqUö ȱ›MÀèèèôÈÈȘn’Þ &ŒˆP¯×g:t¼Z­!6‰w 1®Åá ݸ‰BÉÖjœ ÀsgLˆ†ÀÛ°ªàæ± €æÙö"¡f«{ö,ŠÅzûúÖïß¿¿ÿºë®{ #sfíÚµÇwïÞ½µµµu¦³³sòLžz6ŽcÕÞÞN‹¾ äÅ’JÝÃ?|ùÀÀÀ´„ª›¯GÎ9sàБ-}›:‰êìæÉ*$Ï+Ö¥!å+xÞÇó|Á0‚°û _ÙM® <É9¼RÌ ÁhW çÎòžf›áñ%›$‰9:==…\!Ï0"¾ÑJÃȃ&ÐÆ 2šõ¹Ö,êÃ+’Ý65ï··ñ̹<ÿædC¦žÔ±yóæŽ¡¡¡«kµZ‹l8ŽÓ-[¶;tèÐú¹¹¹œßh&vø«ýÿņ}æ™gV§iZ¸æšk^À2IªûöîíwQ´¥ÒVÒ)œæFö.¾Ðnœ²¥Ïå‰ä‘& :;:ÌÀÀÀ¶|ðZßlþ6†)—˳7ÜpÃþ|>‡zhë¡C‡VÕëõ@MæL-ÂHˆî”RþÌ™3¥ûî»oãîÝ»¯½öÚÓ;vì8rž9³§NžjüàãoX±eõjO)ótš¦q/àú%ÕÝÝM«V­ÒgÏžÝ}ðàñk¯ý‰nvÌf Q¬ðp¶[Ó ‰¯+ÿbvÛÈåb$©…Ö¹\žKÔ<3Tâ6nÚØqøàÁ›xà}ã7î1Æ,m¸´»¶uëÖ£išæÇÆÆÚFGG+gΜéªÕj$RÉ‘rŽ‘ïB¡€J¥Rݾ}û‰&ø|íåÒ‘Ó#í÷þà»oêØÐvuKKÑØÄf>:ïbªY¼ƒ¸¢V mᵑDû³¾K!cÈ;‡Áû)S#ÅKJzò”°&̺%(#…$JKgÏâøñã‘_\¹¼„nºé&<ýô.?µwïÞÇæ«soã˜#v@#²·`…kû’;¼˜ø¸xâ‡ÑÒRÀÔTŠ(2ÈSž“5CÆŒOqÙÆM]GyË÷¾÷½–;vá €=òì‘þ]CÿeWæË-&Ix’ƶt“ã½ÈsYœâ -ÁÕHü€W¦‘)ä$¾¡¬D2¡Åe÷)-f©ÒÜe=¸é‘‰qäÈÑSÇŽ{r¹¼Æ% EZ[+”ÏçgŸ}öÙûž?~üíW^y%¦gf€¦ýUƒøKÄþ2Ä¿HúC+…r©ˆ™™Yäâ À|­Æà†V òX¿î²ö‘‘Óo~ðÁ;®¾êªGÖ¬Çò½Áƒ¿Ï))ƤÅb1ÅÒñbÍ$l½–˜§w=yÅð¹çoXyY×Z“Ï©$e§$´m!ß„üyÏ}”g”–íîX%:¯ꢙ¼H}Œ˜Ye惄B@pyR¥Fâ\ïû÷ï{$I’áeò+—2ÀÔÔåó9ßÚÚŠ‘‘‘‡vïÞ=¹uëÖö@Ùì p&q¡€Ä/$~È xiÄ#Žc”J-˜š…‰ ZŠ-¨ÕªHm*åj}}}…R©týþƒû†Nœ|ꪫ¶nmm­âüMâeš.zd9Ç?ßsèð3Û¢Bíªõ—w·;$–Q=ÕX®>ï¤Hx%ù{ZöUúzÒÜ$ËkÙdƒ¸ö/˜ª^R¹”à]Ó½ã'±Á@vN9´´T011ŽÝ»w}ÛZ[]¬ÿ±Ü]ýõhoï 8Ž]­V;öÔ“O=<5=ØÄ ;¤if8ãt‘hÄW/ŸøaäóyTZJ°–ƒÅ–òE€ØÇ­×ëÈŠfãÆMëLÝúƒüàO=õÔ)Ö›Ž4¨sq#଩sCC'ºî¿ïÞ‡Ÿ}üöÞ•æu+Ww·Ã7¿vÆy(/›QJÅ.»y’©ã”»}^¥pÊÂ* R)H3N•60x ûºF? ùë)øùâú‘D­¸€Ž`­Bl"<÷ÜÁ¡£G>hŒQ!é§y,‘Åb‘8€îîn÷ /Ì>³ç™»8ðö;oÀäÔ4$ð¢šG‹‚}ÀÊâRlµR,¦§g¥Ç1"c¤ ’¤ŽÔ¦Pzº{Kí¯[ÿøãOœ¨”ËGzúzO­X¹òl±PHµR@j*_É^*M™œžl9}ºtôÔ ós—µwäzûZ;bçÁX~SŠw¶‰¹{ ËZ–å,žÐî ÅA62ðÞx8×P¡žV …\»‹ycŠEÀ(8ã‘&PNv4'iÐ%î—äã(ÞºŽÚ6Š9rÿ\pùÀ 5“Œû$*1ÙXœRŒx*«ókv Ég2…%9DÆ Š{ö<ùÐðððÆèeÅ?p¸ÿþûiŊΓ8°ÿ«÷Ýwï¸|óe*t±¯ªDn. ¦þ°v×Ìåbtuu`zzsó\i € #ƒ82 äÀÙ±(z¨rEQGGišGšÂÕë°µ:lš€â˜cö™$Rð©TòF§:â•ï‰ý{¯I!_Ò“ãgÏ2{¯`ï¥9„ä@Š2´ðŠˆIu!$îB¤èF1RÊð/çSà쟖R+f§Ïà‘GþRš¦SQ78vÁØ÷ðð0ÍÏÏû‰‰‰}ÿüÏÿ|÷©¡“(µ´È•@ ÷„šáùñÃÐZ£½½í0‘FjC„²”+ç8w.ÇPƒŸ:ºsH¬G*à ì.Mùå|âàSJy›9Ÿœ´®ó΂,Ay ‘+ƒvŠ,x?VÊQÆ!m«ÑïÏ‚`%Â* «RX‚L*Æb¯‚a(=à$´JÆ=Èroƒb!ÂÁýOì?räèwŒ1T­VÏ[ÿbÉH’Ä¥iZß½{÷—¾ûÝïVs¹!ç;Ã÷Qû‡Hû£X( ¯§m­­PJ# %Ö>„“ “–˜Ø¡Á‚#é´‘Åé}Ö»ÇÙ”ëð­ãMÊáÙ`a+(D†“[ƒ†ãà•"å‚w¶©w™­À}|œ¼(‹X©òH9€dxeAÚ‚T"‚…»–™‡ ©eäùÙ‹ÅÔjgqÿ÷ÿU½žœ¹@ ÁµZŒ14>>þä?üÃ?üŸcÇŽ¡Ü´¡Rˆ¾ä¸ë%J)´¶VÐßߋζ6D&’à‰åøºãzž˜øND¦õ)\£³†CÓjò\ŸŸ²$ðž a31b.³f×Ì2ï¡C–ïJîv@ÖÙÓ6²{Ã~.ó‚­áà•…Ó Èp8™”e†P)‡”•…ó^æ2­ ŠÅûöý`ÿ³Ï>÷µ(2¾Z­^07âEˆÈ*¥jO?ýôî¾ûî‰(60¦É|±~?2)†Ñ­­e¬XÑ‹¾þ´¶–abÞÙÌ9Ô¦H­ƒoj¶à½dÐ4wØyù–E¿†F.Ê!‹rPÐ’“"Jf®øiP.$úËK»ñ…gF|ÔƒçðY8¤ðÊÁ)Î*²:׉H–`é0â¹ULK©„ù¹ÓøÞ}÷þY’Ô‡ÁýØ/8.Šjµi­ýôôô¾¿ÿû¿ÿï{öìA©Tä(€ý}i÷bº?Œ‹fðÞ;I“ºû‹_üâÝCCCÈçb‰ÿóé~XþÿEÝ5¶Z!ΑêØ+pÄ€­•b,YNO¬c­•»ZÞ9PJð)e÷ñ‘âMIÜ஢Hjö”çX½ `QÖ/Ћ‡Â†à‚n ä9ÊÿGðÊÂk •*•‡OÀ¡§´·1}îdzÏ=ßüÔÌÌÌQ­uZ«ßï_<^@µZõZk;55µ÷ïþîï>õµ»ïv¡%Ü«¿ò]“’Î+?Ó±ÒMÓ»¬”×#xAZ@ÄÄàØ{pV*s-'iŠ Æé[¾È‘¸Š:¼â;yß™V KA!½´ˆ“H+p” TÉÁØ:¾÷oýÍóÏ?wE®V«]ôê^ìcÜÉ“'¿úçþç_ܽ{÷+ ù¾’ÑL|âK‹5Bc#ï(È8ÃLL2A µÀ´!ÞÆç‘îœÚÃ~|ê”ÝÀ þ ¾Ä-Ì:|¸¬¤KñÍBy/äxˆŠ^QÈí§¬¨„K¿,¬O5Jù3 „)Ä8 n™k¸ƒYM~âXH9WPÎbK Šœˆt/n‹wPÞA{'F!d;¾&¤As#hOhm«À§øö׿õÙçž{î"%8O³‹¯ˆ€ˆRcLýÌ™3÷üå_þå'¿ô¥/½,N¼¨k¡iGM‰ƒg-Õ€¦([c5:]-+8¸V\ )Ý»åülë›-G\Ê:yñæM–W¹u@ʆ ³$m^‚!<@^Ý>0Bë6Ÿ… Œœ/=€á¹Y„#´µ–¡§€ï~íÛw>ýôÓŸÓZWÔ›K½^êxÅ O´ÖõãÇ}鳟ýìÞu×]¯ô´KFØ9+˜Í¡í:šˆïeó$j€¼àì!DLÞIá,ÌÁ)Nàq:$lPæ—óF ²2@$ÄgÝ/8,² QÖÿ7[Åâ–†€OpEri°}¡271ìÒ`Ô–rÑœÆ#ß|èë?òðïÿÿí][ŒVÕþÖ>ÿeþa†¡Ìb,2 i«…@#4 ÕĤõ¡¢>XR0MLÛXšš4iJh41½<4M|ìC›´}°1ñD©±ñ‚à0 #•û Ãü—söÞkõa­}þжFh+È~˜ Ì™3ç?ëÛk¯Ë·Ö0MDþ¨mÐÿźXCÙ9×afÚ·oßc<òÈsî·ß~ûßX’‹dªSýwSϽ;?¦ÿK¬síL…§>;Ñêçzk“†tL€X1%nì=÷9¢ë>#€ JÙN3ÿxŽðͰý0S’(}X1£±ûlþjÍ vm~ÇÎgw>$,'sñßu>ÿ(ë¢M½M‡uÐÞ½{}øá‡ À÷?D%Ð¥>ÁT)R#D.ßY)ü¤6aB°ÄJêÇÇ’ÎÓPºm SÕH‚?OÈ)Ú'2çy¹S9ÿ¦ö³.ð˜ŒñG]o# qˆ&`a)kø‰*âÀ)_À\‚gðªdÍ /l{þ©§ŸÙñü(&3—uðÁ éµ.êØs‰DÔ@{öìytëÖ­yžçÞyç-íl_RDÚíé‡lÒJ‚‡ LRkÞ´Eᤌøõz\2€Ja&mV )<Ìå®,U:Ð ‘(•Ë"‰Lš8b@{¤toO°I,´Xé"B4‰õI@çÆ·ýýÉ}æÇyQ¼—¹¬-"¸8I·‹€óªl#µE¯½öÚ/·lÙrvffæ¡{ï½·ÿÃúñ–÷Jö, ¥¿^JI½‰bU†{\í®ð»|üÕ%c‹®éŽL™¿ˆTv%]R·ªný£HçœçI+À~NP-à¸Ôå=EƒRÁ„ϱË–4 'QPu„ùW ¢s:bûÛ?¾kügÂr"sY O óßùÇ^”nt!7ìëé¸Ý³*Щ¯ýK–,ùÖæÍ›·Üÿý‹†††>pa~j  |Aʺ9HJ´ô¨$ÿYýöÔŽ%ļWzWðlì¥zA¸4 •ü‹âàPhà'xuéŒf†ÒGO)‹?ÙEp&ˆ™Xê6ùQ?Ê…ŸMQ3²Zý}81y.nòé_ï~e÷oL9çZÌìÓ™¯E£ª¬èÇZÿMÚ§¯cl ß¼qãÆŸ?øàƒ+¯»îºò‚òLM.\zÙÐ$K`.›H%U¡`0¿>ª{Å’:f¾°æ ^.$À±$dp"Ur¼ pQ!‚ƒ7?^ !Ø®žÃZÛY¡€ÄGpôÚœÇOœ8„fˆ²©@H¿—LŽÁc60bJ•ÏÊ "ô  Órxi×[¯oß¶ý§§Nú[VÉÚ´‰”ÚuIÀÔQMDι…cccßÙ´iÓ÷6mÚ4´hÑ"eóz¯É›£¢Æï!)Øcü†d@ÐKFKAæÄæ !À{£|‡$¼ØÃd㦠O€x A5€÷@Ðgƒ´ëQHi“°(ŸWˆÀ$`§Ç(ª& nWp–`Ç‚°¯¯†ZmïÅŽíÏýá¥_üE^äY–µtD„{f9\²"¢Šˆô3sßðððÍ·Þzë6oÞ¼zýúõš­fÊÜ<€w (Qþ•rûl”i«A¹þÞk±fdMë&†pÙT9jc&pBì=àm(£]ã\¹@ŸË?Í2:5…œ±¹…šÈÕÙ¿•ŠÃ¼Æ†•"g¢ñLÝÂh!Ke@£†Œ˜<2Í;wŽÿyÏžW~{îܹ}•J–h3K "q6èâ²€Mî t$0scþüù_Z³fÍwï¾ûîoÜrË-nÁ‚aÌ6›(ŠÜ’d–+ VP–TiY–z )êBDŒEÐÙzÑ’AÑ\Ä9ÂgÑðqÉÿSÀ+%,zD¥†1‡ž&Í«`mù*"ò(Š Èõþ*jÕ:NŸjc÷î}»ÇÇŸìèÑ÷¶2ã4¸“§Ð®²½l>‘>}D4822òµõë×ßwÇ׬Y»ƒhµZÈó޹b=þòI…X0Æòô‘#‚O»ßòüaÂO¤ãüEVëßjõ”¶­GH¢qÊØäh1H–V&†«jýUTk5œmvðÆ›‡¿ð»C‡>î½?–e®02GÐW$å;û4"’lƒ3תÕêÈâÅ‹¿¾nݺoßvÛm«¾¼j -@^ähµs„:»ÈœÀQ™ù3·*D5Õð³éœ=j?¦trò,&"Ã¥aÌÁop€„hnœÌ~êìÁæÂºŠC½QÕ+˜j·ñÖC‡^xñ¥?>uH—:"ªŠHŸattttÝM7Ý´qÆ 7¯^½º6zõÀòvKû0—Õ³Ht/hLu¬#ÙÔxë ?õãSO :ÖâŽxʽ>Q§vKP2Gd-ÚT0éQT«VáêUDçðþÌY¼ùöÛ{w¿òÊã“““ÛÚíÖ‘Ë-‘SˆIÀŸz”µv"Éeìcæj–eCCCC7\ýõ·­]»vêի—­ÃÀÀˆ:¹v f'$  Áµ|H ›»;¿œNR„ f À€B5AW#(]|øåüíèÑ£ÏÎÎΑYçœ'¢‹xJy&\À@Zê:¦ã¡âœ¨×ë׌ŒŒÜ°téÒUccŸÿâòåË—/]º´ÑÈæÍ›ç*–Ix5è}é%¤t0[à©{ˆEê4M"È|€,Œ"8×lâÄÔ™â艓ï¿3ñîž#““»;ör³Ù<C˜&ç‚#—ƒPÀZÔ&‘ÞÃ|D¤ß7cÑA“LUU;"êÎe ûûŸùÂÐÐЊeË–]7::ºlddtñg.¬Ï»jÐÍëo ÞW!«Ô¡ðÞ 9.K;í„#::­ZÍ&f¦Ï槦ÎLŸ™šzwâÈÄáS§O8súô333Gb'CŒ-ç\pDt¨uÅ> á .éEdÚe3u¦È`€‘Šè±J¥R$¢ÁZ­6<´`Á’F_ßâz½>\©T Ïh F£±ˆHÈóÎÙcŠ"?qbÊ{?ã½?“çù‰©ééÉV³yš€s>„ifÎsìˆ´ó˜‡ ‚æv&OŸå“ €‹Jù_-"‰fLP{ÁQ cæs޵Ûí¬Ùl:ÑÆ»©Æpœ#ªÃêYD$‘("cÔæC0Ö8‘8¢¢èœ ιÄ%""Y–ÉRóþoë’Àù‹´é3Qêj^"§[Mç“h/2 ‚ À ê¶Pb=õJ ¨é¹þ‚4ç'a]8o¥£WLÝÆ®zÐSÁ–€""r¹2 úÃr—Õº(6À•ué® ® ¸².íõOÄ쩳¡AB IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_desktop.png000077500000000000000000000515161217176075400251010ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½y°%×]çù9çdæ]Þ}¯êÕ&©J¥ÒfY–-<ÆlaŒl ¼`0OwÏL@ÌDÏL@0COLÓAO ÓÑ@ÑAxÁ;ŒipÀl`dY¶e ,Y’U*k«R•Jµ/o½Kfžó›?~çäÍ÷ê¾ZŒ¡{Ÿ¨[ï.yOæ=¿ýûûýNaóøÌÿ Ý^—¢È)òyžÓét)Š‘€Á€1胉ß3Æ4s¤çF_L_o:FÍ‘ÓùâqÖ蹚y6üÕÿŒ#†Ö…`Ò¹LëH¯[ã<¦ýù¦kØðYs^‹Ajï ÞãCÀ×5Þ{BÔñyzB ,KB—¬ùÕ annç\3o{-³,ã«?A–eÖùrÃ~CWò­ñ_ìQ¦¼Ú‘ý^Ë·Æßó‘FÓW¥¾Åÿ@F"þ^ÿízöYœs ¼Üø– ø4BÔÞóªW¾ gÜeßb€`#„€÷ž;n¿ ëÀ9K–¹-ßb€€#„€[ÜŒ c°ÖÎ~Ìš`êEʦ×ßÿÉ<°ÿ&Bƒ1ö’ÇL'PD¾$¬‹°Ú&¾>å c}‚D4l=pêŠ 1V×£›·¹’“zMlמü¿°C3"Âïÿþ§¾ÿý?ú?~s\“0†nºq/'NÂZsId0“vìÚõÊA¯‡EQeEÑ!ËÒ"®aêe&0§  èS3ó³ôžˆàŒ% Xku~ ÈìÑóµ^O'oÀœæ‡5Ÿ›ÖwÛàÎÕ÷Ä€,Æ„½çx#xd°Æ ¢Ä±Æ`BhÔ-€Í2$‚@Þ{¬µœ?ž¢(Ž^ !ᩪ꪿—¾ëCàú={8{þB”üéç[hÏéÓg„~¿Ožôz=ò¼@Œ(êÁ,ƒµ l¥kž›M„j!{­Ÿ†/S¤pʹñõÂ'boBùŒÅ˜¨¥,X±ˆ¬±HP,ÏÆ@$üôüSÆ1F¢ÆR†I×d~ùˆVUÑ@ÁûªA쪪j~ƒs®sµH] ß°)Q]}ýžÝœ9wk§çžÉ‹Ë2Œ…<ÏÉóLaá"×ÉŒÁBTíJì¤%í:6C½³ˆéb³êRÞ|µ˶µÊôé¯Å"ˆµ ¡7ÀÀÍ9õ8œÝÀŒÍ§†8GKµ®QD°ÖPUTTÆeBUE¦iÖ"J³÷"W´XçôûÍ&"8k°Æ6jt6d$Ú G–e,..²{×.úý®JQò£tãÀ)oH„éIþ!c y^çÅÌÏWVW9wæ °Ñ™6W dRûƒÁàšmÿåæ\\ÜÎÊêj#3Àˆr«Ë EQð§ò'>tñcœµgJŽ5XãÔ¶U¹S&ƒ3•²`ŒSU¾—ƒJ­u'8=k‰v+JŸ…ÄYÑU@BŒVôWªs*†€o|V¢ "‚žSŸÇÏ AˆÓ!¢N”=£æÖ³‰ß‹Ò•’>^‘@ÖéòÊ;¿w¾ëÝ”UuÍDLÄÿfé\–¤Éf3€S¢ä.'wO=öÏvoÂìÚ‹­'H²·‰àvJ €§Æõ¯¼,Øô\< ˆBâzõA$‚/‚ /A¥&<0µáâõ•TÍÅèÖ‹` ±xÔ,è$HHö=( z ¦Yw?c!Hô’3 QÅ#,ÎÀ`Ð¥¬,/<ñeþÑÒ2ï}ïcŒ!È4¬[6IûÂüüߒܳ‡ˆ0?è3žL€-@ÓH¦µ–…~Ÿïxë»Øq×ë £œ±ÑVf+­´k$¸3X§s™FÀˆÅ˜xO9%.„¯Þ*/„*P‡@¨AB@ê€ X”¨Êe*“ÊÊÓš 6ú(QJ½¨3(•Z¯„׌2‡JìèæV+/¢‹è|zž@B¿›Ñë=z†¿úü3ع›¸a×v¬5´P"Ä,âˆÛ·mû¦©ýYCDp1R™íCTºU‰Z[¾ÀÊ™Ør k¬N`5 1g¢£‚C—Úc‚ÅWž:¤§B¼J¤D©C¨TÍÖ^ ©£âõ/blk"ÉÕ;w˜LÃH xÄ%²AÇ &cñQû$¦4ˆÕcCŒuXј±O©0ÞÐéäôû'¯ð7_9ıãg™˜‚늀q6š½nQ7·ê¥øýïrdYFa `j¤Ì`”µgRÖ¸Êc¬ÇºŒà ®ªÌ⌳ô£kjœ:¡ö™¥>J]êZãYïUðA¾&xª¦’HÜ`ðxU¹ñ=%ºoÀ/56j‰Rn“}¡Iy)Í/ÊùAT³¨ê‰úÔ+|ÔŠø†0!ÃÑøÊóð#OsèÙ— ƒmsdÞa&ÓH6Jýæç";vþJþæaíH`ŠÌ .zú—«#‚P×å`xk¯æ¾g&ž´zÇæŽ‹þàø O–}&`¬ÁÁ¢Ž¡šƒÜl µT8¬·êT 6ø(bA¥ª±ªV}¢_tÒG‘`ê­M9QB5{\lb€¤ç&™ÓÌDÈŒ%ëäXžyæ8‡ž}‰ádBw®‡sjÒ(½"¢ÑëØLT/­k Âî]¿ÄOc6¤ÿMÂk YVÐô±…ŠYé…רFßáü’J'†¼ßaçõ×ñŠ*çÁçÏ#YLm°úY‚"TFÔ· joƒ±*áÖ"…SòÑy2œQµÔ„Ð’2ñ‚±^I‰~I:ÆCËËï«D›æ qˆ„hÒ¢¿ ÐÉsºljSç9ôô1–WÇtzó 9R×H Q‹šDå&iFðú^ìÙ½[}¡¿gâÖ! à18kÉ3Ç…‹«¬>‡+‡X—1¶Sõ0 zssE†`èädÝzBq@îÞW„Z9}â=R{$µŒWOJJ(aaÓŠó Ìu»LꊧŸ=Îñãýù Œ“iLj¦ôÒôœ sèð!pÝž= ;ÿsŒ­ ëH cbÛU„šº öíÞÎÒZÅÂ|N‘sq²Â`®G0ÇþAj8äÌÚDË“DÑ//çbÞƒ%“5à1ˆUS`2µÃuиÜ™ƒ¬j$¥T#„ &Õ5AcP ˆ˜F#‚ÑFÏœ)cCM#t;Ö±“ç8zô,£ª¦ÛÏq&j©47’ƉSLmN ÛÞ?„üî]»oÿZòךC¸ÒØÂ T€ÄÆh 3F#¤Òà½gâ…;ç±ý;ú½æ{ûöíjž[±lïÍsvy •?‰`¨k¢J ˆ|P“ 6TA#.+ 8 ú<&wBL@©–ÊÐ,”2… BOl”<¼Gb#ú¢ÉOÚCÑÀÜeä™ciy£/žey}D§céç]LÄ/LžˆŒH¤ÒùD¯Ób"à•…†!f·ÂÒß™¥öñïVÇÍ[™˜-œÀ)¬k¬ªÎà ®—᪽<纾öŸàèÊ =Ç«_ýžzêÖÕ¼ýÞ·ÀÊYn˜»‘åªå“iî •§UȤRÛ)¢D‰æFœUéµ^*ÚfTêCÔªœ ¡†4Ô·b£ùªf‘i¶ÒDO?å)”g”̒e“ñ„ÃÇÏrñü ËÜ|#>ú)ñË&JyÛÁl¨¬ï9l„®Ó!ÊóóƒÿºÓéü“²,gÎZÛ€p‰p!Æã1Î9Æã±†pYÖ0D›¡fõäyðWÀ}ísÎf«‡±ú9“)PãèvsNk>÷Ð#˜P«|+ühB½²Ž÷5ˆÁ:‹Í!E 1{(ÆÆ¼DÌ)8KQ„ZxùÔΞ['`(úŒÑH¯ÄTgÒ‚ñ46(i‘¸A«”bTãM¥Ð˜›o¾™ÕÕÕYËsŽ<ÏF#Ž=ʳÏ>˾}û8qâwÞy'{÷î¥Óé`ŒišPRjz3cõû}Ž9r[b®Ë3@“؉fÀ)®_Ž=ÆTŒW×9ÓŸãäw|?|w—÷ÿøÿÆÚdÌ[úg©ªš¿èÔàVÆŒ.œ ¬½j’¬ ØÙÇNÅ{¤Ò$Н¼šï531 1 óktÕéóŠÒ‹És²nAðSׄqŒ'øI„qÖ"FC>[«ÚwÎb­áüê.œY¦ôž¬Ó!Ï TšÑ4¤A“+äBr&U[J­€UH~€u1D–©#("ƺÝî–ªYD˜L&Míž1j~ó2C4 ~\#>h\Ô´BcS PÁ"xc”¨±EÌö ¤§šË”52ª¨&Á ÆZ\'ÃZÇhuÈù³K ×J\9 “ÕºL¡E½xQË_›˜yPH2j…¥¨Óð6~Þ2iñOŸ>M]×3QÂÖZõ®u–ñxL–eªO%ø8}¾ù˜™ `#ЄÆâ} ¬<ÆW@†ñ3YU›^ëÆYŠ~ÞÎ9LQ 69A©‡.¨yÁ$çØÌ©ƒ–e8¦P”Í÷=âuU#e “šPÕøZ] µš¥ ˜øWD0N¢3f0Nst;Ðí(”å¤bii•áxŒíäô»@sš=ôªÆƒ"{¡®f™èûF5• E|1à' Ý蛣LѬ½°¾¾N]×[ÎÃòò2·ß~;"B¯×ãüùó¼ï}ïãcûwß}÷LB_ OØP•µ `QâÛÌ2™”ŒWFPOb"E06ƒ<Ãö ²~ë2¨¼Úd°HfÀxŒ¸Æg‚DÛ¬žuÀ‹'>áƒ.z’´¢Àf¶*ñ•'ÔZ›€ zž:€÷TexÁŠñ„˜Ýt…ÃXÇêpÂêhLBÖͱbë4Ýì´>À8ÅÄLm0™%Ô‰!œš_cý$š­$í`’&5 %L2 †[o½•¥¥¥F ª;Ïs>Ìx¤¬5úȳÎ4\3bÄCHUEL¢Ò4ˆÄŒbvêØ›#5ØÂqˆ/ÁyĘÄÚ{b’1ÍOf"iŠäüµqv¸¸Õ\³Æa` c Ѱø ª²¦Í·¿4˜»¡¬ AãþÍÖ¾¦k’ÉZš|¿8ý2®õ‰ÄYLnÀd`âëX½ƒ9„È©nP¢úN0pôQBÐob&ÉqÖ‘ èCƒ \:¶‚ƒÛ’Ô~ûuû±9š¸ÚœÁ壀hܵԵ¡´ŽÜdˆB'§Ì9l–‘çœÓèÞY§x|Yëz-ÀÔÞ¼èB{­­ µ •Æü>€øCÀÑ,^4G ~ u‚XõŒË¨«šj2Á—ˆ(‚$jAVk‚¯1άÅ:µGÆšWd<ãb¶1ª]ŸJº|ÔT"iŠéâ›,Ë• ¡À“ƒ Ò6[j€6´Ûf†öëälEèÍLu¹´Î.vY牧.kjS‡ÉjM½Va!/ м Ï6mq.Cpà4q¢ñÀƒ5‚ä¶P©kè9¤ ØÚ#•†\Á¨wd™¹èÈh0ãcuv»2Gcc^b›XT«MµN$¾4eWq“¥8ÜD&tqƒ¼Ä8L¦µ‰TrÅBåI9f‘hbPL¢¹ŽTþ…V-á"Z× ¡V-e I"ES“AÐb´Qgù"ÒDTé½Í mÚ¯¿i Ð`÷Æh•l#.t2^–¼ÿ÷³½÷%¶õ:LÊc2NGḻm(C“/3õüS“g¢w#¤ !}mDÔ›ÄÆFébnN§šF«DæÒgêõdžSc-¸&åFDã1±mÚx‡ É,%¢j+,b3‚T‰a¦V‰ÐB Ÿ&ÊÅ("Ì4ÿ[8—ÃúÓ÷Ú ÑN m5®É€.¼q;…µœ6øh—ãBÎç–¹]FuÍj5ÁäÆnìȬBÀRÇÐ)Õa¬Ê‰Ü5‹‰™À–$€Q3¢·m¢ô*õóôÛL@ÄMÕ¢1M áÔÔD'-;3N?–ZÚ?¿a"%hR!.1e"~h€…¥5„±&4sÃÛ0Ír©ô·ÕyªØöÍz=‹A6ËÕ l k$ }ÿÖ©mTUh5C&`¼h7lž!ºQujG–Ä%pJ¸¶­5‘±]tZ ÑÑKª=/S"¶´Eh¨?}HÕDÀÄ!©œˆxî€:ŸR‹¹JsŠ4¦ÅÑV5àO,îŒó¥$OëZâg&E ™dÆzoÖb›ß›UÌq9 1«h´ý~{ÌÖÍŽR©2بmK ï-ج‚§ò²ªñ"TU ®<ÖvíX ×)0Ô¤Þñ$1AÕl$ZLÎÉÔÆEGZ ×ø!¡‰Ã§ ý&ÒÞ4*wÚÜÔúñIU«—™–æ|’šIR£JòObH˜ü½.­X ±}]Dahƒ&ÅNm]Ãæïf‚µÑ¾­€ ­¤zCmå,n¹?’פE ñÛŠ…Õµ!ëK:½û¶÷É;·Ý¸‹o?°‡{æùðþ5§Ö×Xè²è£E÷,6w7NHH‹.uC(‰’ׄ‹ÍJÎ`Bh¢& уvQGmÖH¥´žëÊ´Hcú©¦ Óc’€›6³„Ƨi¢˜Æñ*SIXÔFñú˲d8’eY³­kz´_·‰˜rÉwØþ%†Ùœ3H{%Óreˆ?Zb \êû_ƒw˜ÌröÜ ¯;°‹ßø÷ï§·­ÇÍ{.™ç·>ýÖ†žA6jÆ“OkØZ”ž’LwЄojJ2Ú;7LÜcÇ7sGGÔF”¬I°}œ/µôH£ÂIÙ=£ô•4¯&1†âŒ×”ø¤ùaeekí†mßSAgb‚ápØo4mˆÖÖÖ(Ë’N§CUUÍ6ô³LÀÚÚÃápº‡ðe à\, w¼nà"ˆ2\±oÛ¯zÅu³¦`}8ÂÄÌž.`»”Z"Ý íÿ›PÉ$/°M¼&†ô ™~™@ ñÞéG¦‚-mÌG¦¥W…;úíÉù4›Î¦×2µù­µ#y2=ª!Ši>oWû´G» £,K¼÷ŒÇcÚ=!VVV¢·[B“ɤa´¶Ø‚âÅÆ:‰aêÀÔ÷ñ¬­•—|w tÓ!u©ý~~Zxaˆh]3d*M© +D*§Ò֞ɵØl>ÈL?#¦ÑÜ SF4cØÎéK»°¢aŽMךLOÃ|²ÑMç5±ªšÈ Aih¿¡‘c Ó&ä¬Ï’¦˜m›ÃÄö1[0@Ë&5ˆU „ ¼S)©}ì¼Ý8ƨ€ö̤DMÌã›Ø³H­(›6z¶íù©JJž!åëLúNô´Ó4"ÕàÒðiæó%£-ÕA?klxtÄ1µž›ˆWH«Òˆæ$Y+Ù0û–DÙl§g«9fó¸ú( ÝÈÉš„«O¥„ºf7jIã\`R{2iÕÂY¦Ë“Ê®L˜J,4Zvº8i7I¥´ß²Ó§ ¾@2×iêÖÒ¨Çߨ¢ôvK@Œ@Ú¡\š0Em {ý­–†1fƀ͵mÄ6;w[}'™Œ+u_Ð NÐr˜DUyí´{bRR¯/ùîÊZ ëZ^0®ƒš“T•÷åÑGh'u2U‚%ÈF'®q°‚:e&êѶ֥¥ù›AËcŸ~AÚ_ˆ•±ý&©#(Á“®²)í9#“DçÄ`b‚Ã5Giï¢Mþ„\ª–ÛëÞnߺñÛÚ£]^~-cK BÀľýi¨?x8ª°Îñ«?ÿO.ùÞÀ¾ztDÇZºE†Õ›¯\IÞøh& ’Ñ6*SO¥Ê-Ä0D™QÓâI:–ˆ*Úh¸s"4Þ’jqÑãOÂ1öOÏC’je\Ií]ÉL4a]RJ&j5Ñ(@WQKI“c{•ãróÆß&!4[ \å[¶·9Eí©†Cò0äÎÛ÷\òÝ‚šã§—yí­{èdN·”K3DÜøF·aÑ+‰UÁ-¿£ñ±§Õþa@bytZ+S§3¥§‰qqQó xF“@¢q%Ö!˜ò¢éŠÄ¿zmk¬øÄ¦Jb_Zf{³Ä^®´kV³gÍ>Å1E<Ë7hg¯®/ ý° ÝÀΦàW‘`©GT+ Õ¥vgçBN'3<ýü)†z_Ýx IDATuˆE"iqL䃔 gÊ!1Zræô•öwǶª$HÄT²¨–ãw\Ò$­žl vüÅœ†S­æRÎ?B¿±‹‡ Ù¾ÃP©íš† «ö‰!|,D!nh)5 †Û(PÁ5ZťѷPõíÄÏVE›‘¾Ëikc€Ö $…c1Wî\A§·±;͹³ç™Û6àñƒÇø«/â‰/òØ ÏóÏ=Ëüœe®×iœúöÔbr7KQªÄõLSMœRÂÂ$‹MÒôïÇàIýQ"`ÚZ¤9}“õœ‰­ß™j#›ãC<6æ",>Õ'øæš%Äú¿Q_¯I-]q'£…½~Ÿ¥åå û·)ワý÷ÞÓívÉóüê€ ‰h¼~ã,dc-ýùyÊoåÍ?öïyëwÝÍC_?É ÇÎÀxÂâ-{Ù6?`00ôzÝX(é4–´9Ã4¾OÄjœÃ–ÃßüKÚ˜±O¨>I…¸h³ jÚØª ;tëÙd¬uJÈ š×H¹$îíLSt°âñ•XÇü> àCt‰Dâ½jw‚!é@{ÿ.Ã_)÷ù¸+9EQ\4Ù/ÝÑbM€LyûŽ,­ùí/>M·ÛcçM»)ò#²Óï÷H›¢¯L;…Œ¡{ˆ©â„óc Î`ü4Ä´YÉÓ&‘Ze$³má%ë.2­jÇú[»U:¸}ÜVck€²b€Ìå˜Üâ2GlîjG)‡Ð^çkßNô\ ÈÓ.¹Ö±… Hv[¢-„ºLªŠQå±XÒ&’säZð%Y[š¸3í.ÆZ-©&45‚{€ºÒš¿:íœ.É@a°y¦Î••iÙuêÃsÄh ).ÑB#4ÕÜmÄ$ÕÔ®(Ÿ&åcQHì¤òøªÂ”mF”±Tµ†‹¸±±²BߨAnã­a 5Ñn!™³úgRi¼yÏ€öq[­qýfBd2Ĭ:ŒÞ Æ¥FdSëóØö…©£G«ñ¾±.®½ElPp)íVOô$±MÜb p˜ÌaòL(™Ÿ‹,ùÄ]Ä… û÷Åšíæ©cØûéˆÄŽjAˆàœ>P߃ÜB×a{Åø½'”5¾œh/aUB‰¯R{¤Rße\B™5yzDï–ÒèI³±ìë’õ7ÓR°Yf …}[m 7+¤¼jPØ_ôî>0Nxï½3¿—ž«b‘H¬´Ú<’:ˆ¬ÑûüØØ hã­å¢"ˆ¶Ýr%öô>7q£Ù›¨µh©iuê_DsåÑpM82Þj3±içp¬ÅD€)¤Œ‚èFÖÚ¾›MË´Yµ†w!îP.N±1Fq¥èO¨¹Hû“:crâqÖVŸÒ¬$ÞedF°•)¸'ðj$ýr~Ä@¤=(ëŠ Ï( WѪ]±ZÕ›¶¾1Û•ä)·zµ³FA¹!X«j܄ֹÕ]°( -6ªf½ý¦OÆhÒiØÄÚ’%ÄGCÓÖíëøW‰•»Q+ˆY¦;X§ZHƒ@H{ú˜f Z½çÑëÔ$9‹ëÌS¯—ìñº©V›„zžÙµüWjóúf-@½­JUÕŒJáµûdós¸®Óf¶ ÁL¼QµZ#Á`|Ð=œÌaQ3¥Á M¥qZ‰<ÑLTçSäÆylθÓ8lÓ"ô»êd¦¸!<ÙÀ s ŠëAl¤Œú>M[É}ÑÊ"kµg+¸¬ÏêÜ \|îëøM9t:殬›Gb€ªª®*Ï% h+|.“ Ò›8ÆeÉß|/¯zÕíhReóµÕËæ Øèõ^þxÓ¢x˜~ûõ³”ŸÚþ)H$‘s6Ÿ²uŽfþ¨I *¾Ÿ2ƒi ÒDâ7L*Í\Ñ\F¤1ˆn}OP„qR¿šÇö£X8£ŠO5ä¡C‡8}úô–Ò^×5»wïf~~žsçÎ]6[x%¸æîà4ÞèîÝ»¹¸´†³vŸ¢È˜†öSÑ”0A¢~Ö¤RüV*‘Je“Ígé>|ªÎ›–ŠnpjZâݼçlŒAêÆm÷"4Ï…étqᄱ›˜³ØøärL+‚Lô“ʪÄ×¾ªXY{eŠº‰9‘¸°"¤'D³!1çœÕmåÅ17˜Ûpoû¿«1ŽXY_7§P"¤è©w?5E)¥»!—Õb¼*¦”}Ȫï+¼œÓ0ÎGÂXçbYY‹3ÛÞ%ÌÓÔ#¤#cz©9vó˜Uh2[ l¡>ùÉO\èv:µ5fâ² —et Ml4Eœ›T¦5Ózþt×Q]«¹m“p…£StèÏÍQ–£ñˆ^¯ËÉ—OÊóÏ?GUל>u*8p`meeåÕëëCãÜ¥ÞrÛB¦x~³m¼Qéè÷ûg¬µ»Ý^¯ö5ûöï7ö`R–trý}ãñˆÑp¤.¤1ããFª¦}jQo$8™Š¸o¿÷zO…xË[=Íd2V :‰DuiëwîY4OÒÎeÑÄÎw¾á \8¾‰ÍgIîf`Gq ®&ÜCôv„d6;c®™ÚÁlél>PÃ’,ÏÉóL+L³\=ÖRt»ì»áªÞŽ’ì¦GLÁ!@V–åêÞ½{ï½þúëyì±Çƻڑ2iÛ·oçÆoüŽƒâ½w@Ánl?hý½$šû¶WßuÉ9žxê)Æã1“É„ÉxÌp4d&„*´L¥&Ôªºæïø~ªªbiiiC;÷¬koÿuv޵üvj3D·ÐKßWw:=Ö˜¦³ø²‰$®Ð˜½È úý>ý¹ƒAŸ}{÷^îki4È{ë¹çL„Îãëty|X`uqqñ­à±Ç£ßï_SC¤ˆP–%yžs÷Ýw/<ùä“ ¦¤Ï‚ð ±ÙŒ‘Vð=úÚ×¼fÃë/>ü«Kk¬×'„˜ª­}ÍÛîý^&ã±BÅ-_u_ÚÚþú[1<­YK™jkms‡‘¢(¸ùæ››Pòr¡à–û¤[—õz=¶mcÏî=ìÛwÕ„O¶L j˜Üø^_÷[ÇçÀ…·¿ýíß·¶¶Fžç ƒkvr&“ !î¹çzè¡ï;räÈ1`P¡Åç5P¢J¼dÊÑmm¡•¨¸t¼ù÷pÿ°²²Êr]ã}àÍß}φûÍŠêgåï§•>¼¦Ì¿íȵ¶Ê,Ëxá…xðÁÙµkËËËL&^õªW57¦Újíf2@QJøùy¹ë®KÕߌ‘oPužÓ”Ý4Dî0%p¿õY‡)C$ q`×®]w?ž……ƒÁÕ\ÆÑív››-cî>ìcªJ`ÿNZô:Ä¿±„iCÀÌð¶{ïàwïS¼åÍ÷4Œ8Ë>oU ­p0ízn,¼úFÝÑÜO}…¯¿þæçXkõ~̗ɤ1“vìØÁââ"ßñú×_î»m}œ¤=Iy’ì<þí¢ª· ni¿Î<³'ϳ닢3Ø·ïÆï_ؾ°íÈ‘#ÌÏÏÓív¹Ö‘ÌÀÑ£G¹ûÕ¯~×Ë'N¬NÆcœ.ÄóñZâëXCµCÿ&&IŒ“¡Äð0ƒî¸ãŽFýn›Ï²Ó"Ò4p4ª;=ë«sX ô-˜[\\äÞ{ïåMoz#_ýêWyùäIlLÞmålš­œÀï»ï¾+­í†ëE¥WÐ…L„ODï1%úXvcn½ãÎ;ßpÛ-·Üñ¦ï¾çŽýûöïzýw|‡{Åí·5Î̇?òaΜ9ömÛfæÍ¯xa"ÌÏÏóè£òñÿð^wãÞ½¯«½ç©§žâñ'Ÿ,¿ðÂé|ð飇?ýâѣǀ‹ñzw¡Òßq|="Ê#Æ[1rWÆç/—æÝð:f¯yð×4Yy‘ÀdR³gÏnNŸ>ËS²²¼ÊM7ÞÈêêJ3×VšæÚWu£ä'IÏZÏ{­Ç*1çýßv÷Ýï{ëÛßþÎïùž·¼òöÛ_Á {o`Ï®ÍdO:Äæ3œ8y’µµ5ž{î9èv»ßpV,m¶ô¿þvホ[n½™ïúÎ7ò_½öµ°Ø¿¼¶öŽ—^<Ê×>Yýå_~öñ?ÿàŸ¿ðüóbÛPŇC!ùu|\Â"3ç.°ma¶ùÚ,™›ÿ^Ríkâ™…¹OUüòò2óós,]¼HoÐeuu5â—‰¾Hv>=ï Äwñy’–ŸgwíÚyßÿô?ÿÄÏÜ÷¶ûn»ùÖ[èt:”“ µ¯qÖòÂó‡ùÍßúM¾ð…¹xñ"yž³k×.¶oßÎxÅñãÿ‰sçÎBà–[náýï?ÿýÿðOɬåºë¯çÆ›nÊø½ï{Ãúpø†¯}í©Ÿû½ÿø;üãÿïë§L}ÇÔyLë‘Ë&„¬ãícfuîÎòþÛ­^)ämv³FûžD›\ã¦É·X[[#Ë2F룅-ÃÍ-੃Oo¼PcxÍ]¯Â-ÞÛ¹s'çÏŸ÷¨J7¨¤'†èÄŘÿÙùþÎ?þoþÛÛŠ¢`´¾Æ…‹(ò‚N§`÷î=¼ôÒ1ÞõÎwpòäIî¼óNöïßÏÎ;YXXàܹs<óÌ3ô·*m£ºYRÚ‹Ø~<ž07×ç5¯y +++?~œ¯}ík<ðÀ|ìcã¡/?L–ç,¯¬àã=xo¿ý6~ùW~åÿüg~æÿýù_ø×þ»¿ó–icâo¡¦ýûobii‰ÕÕœsÔuÍŸgΞc÷®´9]ßå Ü ’ïŒ:~Ïà6´a¤ã6¯ËÕŒ™ pþüùæ¹rp׫6|ÞëõÒ&‡kLD"²X×uo¸¾>÷Á_ûè½õ­oëŸ<ñ2Ý~nÑ!/™Ë£ ”G~˜Ó§Oñ½÷~/{vï!sZa\–%.\àä©SôûýfÁ¬Ó=z7{3>°¹®~4177ÇwÞÉÜÜ·Þz+û÷ïçàÁƒ:tˆgŸ{–ýû÷cDpyFU–¬¯¯³¼´„qŽ~ô7Þµÿ¦û~å—~éŸÎÍÍíÌòܰÆッ¼÷þäɓԵzïYZ^a<k›Û41²á:·òÒ7—y‰ˆ†€Aà©á¦k"¯~®Y#„0›Úw´ôÞS×õÞºö/­­­YÐðÊ9CícLñpiâÝùm \8öìnÊúʺäôÉS WG¬--óú×¿Ž‡¿ü0ƒÁ€nQpai‰ýÁ€Nžsþüy$ússtº]–/^DÐ[Òcšjšª,A„*ªûí TuÍÚú:Îæ¨«Š²ª Ûv,R–%ãш,ϱÀKGŽ(z( {÷2è+îàEo ûï~ñ¿ígÿñ7.ÏȬ‹wwZÂ5T]ÕT^ÏqæÜù#UUÝêbŽd–€Ë§yãqß$£Í¬À÷{ˆNñÕHüå˜c&¬¯¯7ÔuÍ7ýu–9›esŽKÓDÐhóؽkWœGµˆµ–m óœ;w>ÞW5ÂúpH-¶íÛÙ¶°À…å‹€åÀXkY[_ ×Ýp=;vìäÌ©Sܰoý~P&=üâ‹\·{7ËËËTUEì¹î:¼÷ºCf–±çúëY®5‹¶çºëȲŒáÚ²Ö]7wîØÁ¶mlŒðtlß¾í² çYsã¬÷vnùÚOü¢³ö_&¤n3±ÒÖ.›5ØÆ<@Ð §±à @c´¡•iÆòZ5À–  ·'*Öø¶mß¾O‚0›ï'œõÕ5êà¹é¦ýÜq竨« #Âé3§Ù¾}‡zÁgϲïÆ5`5†Üf\ÃõTeÅp4¢®jò¢f<3˜›£®kýîŒiµï¯ßïS–5ss=|\ÄÏþóÚ  ¬ÆÜñŠW À\¿Ïp8Ä:×ìÃ[UU³Ès½9–—W(ŠB›;Dؾ¸N·C¯ßª,qÎqþÂEªªdÛÂËËËtº] !PUó7_a2SU·ßq;wÜ~eY’e9"gÝ¿8räÅi­ãðá#¼þõ¯›¹/ÐV œ ï[‡a›?ŒãA÷ùĺ€-|€^xPݵs×'»y{èõ.àý~×¿á ¬,/QäÝ~Ÿj2Q°Æ–VV9øÔA²NÎ7죓낲ÜQ×ç2æóXkÙãvSÕ5UYQUe$–0™”ZY›e ʾªXܹƒ·\÷ŽŸ|™ºªXܾÈÂÂ<ÆZêªfn0 *kE¦²Œþ\_÷:4†n§ÃöíÛ±Y†k%˜‚HÄ:úý?ñ,««+ æÜu×]Íþ¾½^7¿ùͬ¬¬sýž.8‚÷Ú#0˜XcÌ-ÎÙ#2“Sb].Ô~híd¼_1ÏbØFÂK|…sµ«Š6k›™Ù•<ËÚ»X¿­èv¨c+u‘g|ä#áØ‹/b]F]׬¯¬àEøð‡?Ì¡ƒOsû­·òÖ·½Åm‹üÍc_amm•µµ5¤|ä#ákŸbmm•q9æ™gŸá7>þqÖWÖMÔYû³?û3ž:xN§C®ÏÊò2ŸøíO6®n¯Ç|æ9uâ$7ß|3ý¹>–—ùØÇ>7X,l›ç+=ÆÃ=D¿7G§ÓÁ9ÃGã78wîœæþCà/þâ/øÄ'>Áp}ÕÕ&“1üÀ9|ø0u¨¹çMob~~'^¦Ûíqþü&“1ŸøÄ'xî…gÕ@8òâ‹üÑý!¢÷²Ì æ¡þå”'ÖÅ¿vGŽÁ帤Èrª²äÅ+ÇíU†£!k«kŒGcœ±tú=VW/Ðø¸×íqúô)–V–˜L&‚Nž3šŒÈ2‡„ÐÜTyyu•ÉdŒˆg‡Ÿ¾Ù];Ïs–V–¸xá|Œ·Õ±üú³_ £µF„r2áØ±—(ÇDN—õÑ:Ãõ!KKY]Yaqûv¾ø¥/²¶¾·ƒºÝ.Axÿá£/qäè±ËæýgIòô¹ÁàôVº¼„Äû+´û¶šãJcvPëÞòeYþt·ßÃZ­Ks&c4ñò‰—øÒ—¾Äp<Äb9räûöíceu…G¿ú(>ú(/^Ä9ÇÒÒ<ðÏ<ó Û¶mc}¸Îc_ý*ÈW9{î,Ýn—ååexðEþ¶-pì¥c¬®®ròÔI޾x”뮿ŽS'Ïð¥/|‘cÇ^¢Ûípúôi|ðŒÆ#žæyvîÜÉË/½Ì¾ôN¾|R‘õ5œÕÛÀ>÷ÌsìÝ»—ñxÌ—þ2ËËËŒGcÖ××Ç|îsŸã™gžaÇŽ”“’G¾ük+k¬ŽV™Œ'œ=s–û¸Ÿ¯ýëì¾n7Ç^ŠnÁË/½Ì§>õ)~ú§ï=»wíæù矧×ïñsÿêç¨CÍúÚ:úЇøgÿ쟑eÛ·³´´Äüü<ïzç»È³œádÈáó¶{߯÷ß÷³k×.~÷÷~—áúþ¿ÿsʲ¤×ëqèéC|׿‹wÿÀ» <òÈ#}ñ(?úþÅ`˜››ãóŸû<ïù¡÷ðö·¿ùùy{ì1¾ð…/ð“?ù“”eÉÎ;yòkO²ÿ~Þýîw“e'Nœà÷ÿ÷ù‰Ÿø D„¹Á“É„n¸·¼ù-ªUòœN§Ãž={øÒC_â…ǹóÎ;)Ë2V4t²ìÇB°¿ ‘€YDNÏ“­NíåUUÑív¹çž{ètºT°j£‡[%–.W6Ó,_¼ÈÒ… ô»ÅME·£·dïâIæçé÷û âUÖúcƒ¹ËކHt¦ú½>U]QÖ%y–Óíu)Š"vkèÕëõ´ ½š`3Ëü`ž<Ï©Kåø¢£éiï=UYiÅr· Ûé2¨}M·Û¥?§aád2!Ë2æææ(ò‚ÉdBUWtòsý9Œ1zFšš‡ªªOÆt::ygÔ•uI¿Û§ßïS•ºèEQ0?˜ÝRº¯UUìÞµ›“/ŸÐû,zOžçEÿNLhð€«›+Ë’Á`À¿ý·ÿ–……ʲ¼j5¹á~þçþ’7ï¿ÿ~‚ƒÁàço¿õìܵ“ª®ÌÍñ¹ûï篿ò׈Àןý:O|šÑúˆÑxÄGý£œ:yŠºª#œ=s–|ðt»]VWVÙ¶}Ÿú½OñØãè]ÆW–WøÀ?@–e,/-“9ŸùãÏðð—&Ë2V‡« ׇüê¯þ*"Âúp~¿Ïg?ûYþüÏÿœN§ÃêŠÖ ~àƒ ,KÖWÖ1ÖðÄWŸàOþôO”Q«k-úð‡XZZb8RäÏ=û¿ù›¿I§Óa¸>¤ÓëðÉO~’cG)Cä^zù%>úÑÒë÷8sö Î:~çw‡g¾þ Î9Ž?ΩӧøÒ¿ÄŽ;xÝë^Çd2ABàÔÉœ>sfµîÿ¹ë®»%\ZþWÈNœ81?š‚PÕ?YZZ¢( .^¼È`0P‹Ç$0kxïÙ»w/ËËËgŒ1¿MͲýIDATÖþl‹{9¹5Ë2²"®ú™áý_~š»ï¾»¹eÉÂü¨ÊŠûî»[o½µ¹Ðc/ãð !h;tžÑëôøø­“O=ÉþÐbÄÐévøô§?Mo®Ç»ßùn‚¬±¬­¬ñÞ÷¾—<Ëét;|åo¾ÂSŸâG~äG¨ªŠ<Ïyî…çxÇ;ÞÁömÛéõz¼ðü üúAÞóî÷ðž÷¼‡,Ë8øôAÞ÷#ïc~Ak Ž;Æx<æ‡~臨ë:¢rÛÍ·q[LM¯¬¬pü¥ãüðû~˜Éú„þ\Ÿ¥å%^óê׈º°°@¯ÛãOÿôO#ÑÖ:ŠN—e»–—–øøÇ?ÎÿøÇÒõpI=À¬x~³ ¿\]Aš«­=.ç#lÉÎYDìYÜ]R·R׋øâC_dÛâ600Oï0 øÊc_Q‰xé88}æ4?ñ8>ø “É„Á`À—ú2sý9æús”UIY–pÿ¿ý8Ç_>Ž1†óçÏóÄמàþ¿¼ŸÊWÌÏÍóÈð¼²ÌÒ…%ʺ¤ÛírðÐAÎ;§ Ѻ¢ÓÁY笵dY6½¿ò b$â¦û%©¾œd§-b¿9Ö¿RD0Ó°,¡ÛÉ ò,ãÿkïLƒäª®;þ»÷¾¥—™éY%@H „6°,YØ’0ZF"(Û¡0®JU ¶ó-ö‡$ŸüÇåò'•¢Â§ÊqlaÊo!“€@›mH€„4B²–žîžéí-÷æÃ}¯§glÇvéLu½×o^¿õÜ{Ï=çþ'ÖX«×ééî¡·§—F½agIñhƒáKû%öîÛË©S§ˆã˜y×Ìã®;ïâ‰'žÀó=ªõ*÷}ö>FFF8vüC¡Pàs÷}Ž­lE)ÅØØ÷Þ{/q³ÿ~«Üó™{xzûÓmhM6oÞŒT’]»wá9J)î¿ÿ~¶mÛF£a½s+W®¤¿¯ŸŸ?ûóÄ»iøò—¾ÌO>A¥R!Š"–-[ÆŠ¬àgÛ~F6“%î¾ûnv¾°“ÑÑQ´ÖÌ;—[×ÞÊc=FÖÏR­Wùâ¿Èë‡^çè[Gm#Á°äÆ%ÄqL¹\N^d<G94‚fÙøBxž½f'ñ¹¤~—Ôvéééa``€žžòù| !”BöSœdww7ýýýôõõµSÓ7¡ŠU®ëÒþ¹Dz¸@ ™s·åÐFS.WèëïchhȺ[¥ÍúIOÉdøÈаfÝ\·)%3gÍd´<ÊÆ [ÉŽ»^Üņ ˜;.Žt8{æ,### …ŽëpñâEúúúX¹r%BªÕ*çΟcãÆ8ÒÁqÞ:úlØ´44Ã&§FN±yóf<×C9 ×q)^,²qãFb£¤bç®lذîînkÄ]Ý]ܶþ¶Ö>»wífhhˆÎNkv:ñ\õë×E¶7Y¹j%«W¯fáu A@>ŸçÙÿ|–bq”®Î‚53Žçà9ÎB£Ô±F£Áˆ(Šèïï_z¸”’B¡@?Ôj5Ο?ßÂ5ôõõ¡µfæÌ™ ÒÓÓC&“¡V«Q©T(•J4IÓ(ŠRøzÇÔaZp• †ùŽç ¤@Ç©$ÅâEØÏög¶Ó¬7‰tdÇqaH<Ïãð¡Ãø¾Ïã?Îàà •± ï¼ý>ú(ï¾û. .äðk‡éÈwP¯¶¬ûƒ¯äÿ€cocыصkóæÎã¥=/ÙL#ßçåƒ/ã9ÇŽcùòåìÙ¿‡Á™ƒ9z„0 éííeçó;ÉúYŽ8Æ¢ëqèð!”Rœ|û$µzÁÁA޼q„mOoãÝ“ï2ïÚy?qœjµÊwù.§OæÚ×rôØQžzê)†O sÕUWqzä4§GNóè÷eøía-ZÄÞ={©V«¼ñæèX“ÏæÙùÂN††¶°zõj;4y.žë¢õgÊQÇΜ9C>—»ûá‡~pß¾}«Ûãi—žvÿÍfsÒøŽ÷SySƒ1ý¤2=æŒ3Â7þǬY³¶¥õS%˜>äJ òjÏË$Ó_yŒ1´qˆÕ·¬¦2ZA9¶«qǵidwÜq…Bo|ý\3çݸˆ|.ÏùóçyóÍ7Yó‰5ÜrË-Ìž=›‡zˆ pø÷Þ{©Õj¼úÊ«¬úØ*V}tƒ³yìñÇ@Ö-[¸óÎ;q”ÃÈé–ß´œU[ÅìY³ùÞÖïÇ1·ÝΦM›èÌwòõo|eË–ññÕ§«»«÷_·n·®»•îîn¾öµ¯±xñbÖݺŽÞÞ^^yõN½sŠÛÖ߯Ú5k) <òÈ#ܼôfÖr=…B“'OR¯²bÅ –-[f{e‡ÁY³fqþ¯9ÿës6‘Öh|×Åó< ]…ù¹\ޝ~õÂøàøÔéç%A)~6cãäÚ ¼¸ç%Š£E^ýu¢8BJA.›cû3Û Ã€þàÀ™Ógؽ{7…®NÍ&ù\Žýô'̹zÃ'‡m—Y«ñì³ÏrÍœ9„aD6Ÿå…/ÍdY¸`Í 1Â2Ž $¬á&av¶" #Hp‘)Q%–ÑD¿?®X·’ŽŽžþyÊ•2…îãããH!øé¶ŸQ)—Éf³¸žÇ¡C¯qú½÷(–©Öktäó<ùä“ ¿Ãk‡^ÃMDì;p€ Ñ°Ì£BÒÑÙÁÙ3g¯ÖñdŸüþZ—ÅD†T'UÝ,;° Û\²b2K„¦6°9ãLdY l,:MÊfŠS@Lç$øñ‚Öú[3füM__Q’ÏåÙÿËœ<~¢iÚ~§¤"Ò5t¤’(DZÛä¡ûž‡’ hZ«#ñ¼ ÍFƒeu=Œ Æ1·HßRp¬„É¥\Û¥Å+×¢t1$·/t‹U–„_£Ñ:‰y1aIÛб-`éx.QÙ„NRÈä¾u hp¤­YE6q(Ž5ý½}l¾ývšaW¹‹øö··Öþí[µ0uÉó“L$¬v%/»¬çÚ^| ·oG%§w$JÐÄ¢´@5Q„r²Ç&¼”™€¯—貟XÇõ8ÖÔju °¬Ü|Ó >þ±O$•TŽ£H«gÙÍ)­ñ˜–€›HSJ~ey%ZÜ€¤w%HöùpcÚŸɹҵ)Ê"ÚVR¶PaÉ%¥´‹v·«”2á¶0¸”ùÄr'µ¤J0Ú8i‰¬GÐàûÖ;§oºÒØV;†MUK .´hÓÖž~7mËö;jÏ[lOjMÓÙâ¶Ï¤ë˜V/»‰(ŠÞœAÆó©ŒUIóÝÛ©yßÊ´_[€è„• ÙÆwƒhçmÕ6'ÿ~ºã¾ï‚>P¦ÛÙL^míb ,ÿ¹žòóvÆÒé”LÐ×Ûƒ6ÐÙiaí/î:0 QÛ†Noÿ7sÂþdZøËû>K†ÿõ/ÿú0J)ê:ÒXÛ U¡SÐjÝÂȤU8M«(S²„Pë‰t&ÓFuÔÞ53å‘êôµH>ä͵ø¦Ò^bò¢µ–ÒÜØý%È-9qŒdE¤É»7"laý¤Á{Z?A&í|aÇóò²ÿ¨2­ 0ÅRÜÌÄN_®ˆëò* KIÙ‰1R ŒB e (%•1©”TB ©”q¨0ÓJÀ)à8ðð°gâÂÒÓÿþñüßW>P:;º¬óf|&Ò¨»±ÆJž ã$µP\ÇQx®'}/£üŒ§2Ù¬Êd2ä²Y'“Í Ï÷”ïùÊ÷£ß§ÿÇ–ßYà¦ÍíÕ—Ø~©ع´™²œz®ËFþgò‹®ÈÿY¹¢—¹\Q€Ë\®(Àe.Wà2—+ p™Ë¸ÌåŠ\ærE.sùoœyüÔ¼ÒqIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_flash.png000077500000000000000000000321271217176075400245220ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF)rIDATxÚì}y”õ½ïçW[ï³ï;ÌÃŽ8$Ä-\ccÜž>óâ;žhž×kNïDoL¼7n9'' ‰#Þhà%£(7âÊ D‘À°Ã0kÏô2½VWÕïýÑõ«®®©î™†kÿ#ËòaŠz®@àp: ‚p› (++C}}= â6­žž|øá‡ ”"•J…eY^­(ÊvòT`ªÀp¨÷ù|ûAÀ‚ pã7Âår$n³Nœ85kÖ ‹A–å¿Æb±DM ˜S¸û¢(vrB®¼òJH’UU Ò¶Y555X½z5Ö¯_ŽãÊxu᧦òs…)ÔŽãÜ„BP\\\þ8«¸¸úùªàÑ5@€z.€9J©‹çyÔÖÖBQ”‚„ÇYUUU „€çùjÝ„ Sí8O%A:!p¹\Ð4­ áq–$Ià8Ç€¤Ë‡œk`q¿Àóð<_¢ªj﹨éà „8Ž‚ýŸàr: „@’¤9ñx|¿‰S¡ç’ 8Žã¼Ç¡ªªª€ ®ÊÊJtwwƒKÛî\1fÊW A˜Éq(¥'p‚Ëáp0? D?’ª˜ŠX8]»€ð裶¶´´Ü’L&]ÑhÔ÷óŸÿ¼jdd”Ò‚ï$ê¾’Ïç!+V¬øò 7ÜPër¹¢’$%Ãáð·ÜrËëHSÄêépš„/}÷»ß³råÊ]̉Auu5JKK Gø ^¯„Ì;w~{{û|EQP[[ —Ëõµk×~õÖ[oý:9¤œœˆ<+W®ü•Óé„Ãá€ÃáÏóH&“Ì¡)Dyv=¦f !EÇAH’žçáp8 ÿ À£º9P§Œòu=üðÃÿT\\Üɾ(ûâü18Žƒ¦iäÙùLø”R”••‚>úÈ Îyž‡(Šðz½õëÖ­ûÆW¾ò•Ÿ˜|:Õ ¦[bŠKy΋/¾¸±³³óQI’ ÁK’AÀò<ÏO» Hï6s4EaäèÙÕ¦§×ËʳóÍ·V0°¯ª*‰<Z[[ÿåk_ûÚ–§žzêCý©¦/N'ë( ¾áà͘1ã*AJxž'„N–eQ’¤Ë¼^o­(ŠÆŽD"†ð !())™v @ÉH™NÌB6ÿÛlÊËË‘H$‡¡iA04+ÇqÞ/}éKO­ZµêÇ#SJ5UU©¦it``à…Ûo¿ýýÉ8ŠÂ8ÂçH¿ýío¯ijjz†çy‚v«( ðehh{÷î5?:¥yìþôÿ ››uZrœR}KÑSFƒÙÖ›>³Ðü¼î3uwwcdd©T û÷ïG[[***Àó!‚ €Y–!Š"xžKªþù8q⺻» 3ÌýÜw?úè£{uÿmÜ<‚_iB ]yå•ßÿÞ÷¾wMUUUƒªª"!„Ó#’H$¸ÊÊÊ^¯W2{«@Àø1g%Ì!ɨbhÂÊt LFðv¶ž9Çv¾¥Ô¨ b‘•¢(âñ8"‘ÈÁÑÑѰ¦išªª%„¤†††N<ûì³ U<TIÑþð‡¯(àÖßÇWTTøÖ®]û?Š‹‹%æ0•ÏPÌ<Õ³ÅdÅ‚¡5 Á ɰy4€à­¶Þã3“h÷zóëFFF n…Eªª¢¥¥¥éꫯþµßï5…|1H—‘¥0bR!Ïéb׬Ys}MMÍE¥¥¥-æ00€ñ%Ãá0Þÿ}D£Qôôôœ]&Àâ(¸ô^'i>œÉÐÁ‘ÏN›cú\‚´{ŒeIí´Û<;wî„ÇãÛíÎ"٢Ѩã™gžùçÊÊÊ,'pttt¨··÷­'Ÿ|òá;wž2Ààž}öÙoÔ××ÿokȸ~PJñöÛocÖ¬Y$ o½õ–ñƒÏ8KˆúîO Àô"ÍÞdŒçÝ·ë­KÓ4ÛÇ)¥FFÐëõÊ .”dYÆ»ï¾‹ŽŽ#]¬ªª‘7`N`III¥Ïç»æhºòÊ+¯@¦ž€ær®ÇÎÚÚÚ¯²¶9õù|p8Ø·oDQù⿸nñâÅk·nÝÚOÛíã8NÛAÇÞ§ÈñZUµy0Ôh¶‹Íl^¾Çì" ëó d6l8¸xñâ§–-[öT*•:¶cÇÃ08ÃñfGiié²;ï¼s–Åå-*Æá<š¦ùÌ€5 t¹\xÿý÷¡Wÿ–=ÿüó_áy?ýéOqàÀCÕM·ýOŸà±4¡…¦ÿdj«1 ;ϼD‹“g÷Ú\aa.BÈî5óŸ{î¹ùf'pÛ¶mX²d‰f3Ù03 ª*Âá0DQœ  K÷áÔ“€ÀÇ™z1 ³ Ûµk*++QUU…Y³faïÞ½@˜Ã3>1­ýÓÄnã e>ÿ˜Í’K[…o'ø‰DvëÈ‘#Æ9f®¯¯‡$IèïïÇÎ;ÑÚÚŠX,f˜Xv;::ŠX,†x<®è›˜?Y'Àøá‡¿úÜç>÷õp8ŒÑÑQCªª ÇƒŽŽ„B!8hšfØ(30í‰ «6ÈÐý ÐÕ/Ø.¤ò%H-`·›' Bâñ8º»»³ÀX>AP^^ŽÖÖV¹§§Gêíí5|fn½^/À¶_ýêWG0šBaœ0uß}÷½rÁôµ¶¶ÎPÅ©+J)€_¹råÜeË–Ív8H&“E‚ p:Ó®X*˜± QÝЬ´àXäÞù¹˜½‰jJ)<UUAAWW×H’„={ö ¿ð Û¨„U¯Æq\rtttð¥—^ÚLáI%ƒ4=ŽŒnß¾ýÀöíÛ‡nWâY–ðŠ+®˜³|ùòÙ,þg9l†HsÌ;‹3v%ƒ´ì²è˜þ™Ï,ØÙóñü J)FFF0<<œÅ-0"È €9sæÔ¶´´øyä‘m&A«:õ0‚Lc©z*ˆ/\¸P»ùæ›?×ÒÒòYŽãÒô!DUUÎãñ4˜ÄP(„cÇŽeźӯþ 4pœ ³o@Çd)¡Y³‡`·Ûsi;ÒǺTUÅÁƒ –½çàÁƒ „ ‰ µµÕЫV­ºxñâÅMǨ õõõíÚ²eËú—^ziBÅB.­ «V­òÝu×]Oy<ž9fˆçyD£QƒA£úg``‡FEE Bãl(! åÆŒ(ÉbüL!šñ<%̆ ™(`^®?×{:dË twwcæÌ™8zô(B¡ššš ª*R©*++Û*** ï_OÍ›;wîê%K–\ÿÐC½s²D@¼é¦›n...žcR©”ÁU'“I:tÃÃí_¿¾;‘H”swÁY€1 &ó}j uB¹çÚäÛíùœ<;­144„`08FøÇáÏþóv§Óé_¼xqùüùó;+++áõz9 L#0?A7¾ŽŽŽÛìÔe™Óò@ªËrq©TʈEwïÞêêjD£ÑÒÕ«W—ööö:6mÚd0^g@2»ß,”Œ`LibjÎÚSÂù€0ž©ˆÅb†×o÷ÞóÎ;¯¡­­­AÓ4Ë;vì:;;!ŠbV~€iÆjšÖ¬çm’ùR¹L€Àå÷ûl´ Sõ Ì.mÞ¼íííX´hA¨c)av²Ïx@²U;!„KÇ~¸ô'™T±x†pÒ¡Î!_?—ªÏMÓpôèÑœ´0×Í™3ªª¢½½MMMضmš››Q__ŸUÂèù`0ˆÑÑQA@DßÔêdÀ:ôz}}ýŠãÇcxxØø v444 ££”Ò¬€%‰xž?ó, Í®ò#GõÄ‹áÝe6¹¹ “?—0Ÿ+ÙÞëééA"‘È)|Bˆ¡iUU5¨Þ¹sçbppýë_³ŠFyžGII ¼^/4MÛg¢‚O*¤=øàƒÛ®ºêª]rÉ%+5M“!<Âó<ôôôpõõõç¹\.ƒf8Â@¢gø¨¦ïdP“ÍÏÞúYé`«°ô7ä¼Ùƒ/þ÷ûýFÍD¾ïÏB?]­Ú5 EѨ H¥RT–eM–eyóæÍ»ž~úéW1Æ!G¨è9åð¦M›voÚ´éŸ QÇóÏ?3K ™iKÆL hÞÉÌ“·KÛ"ÅI$T6é01+h·¢Ñ(úúú&ô9@ÀàX…$I¨«««¾ùæ›7 …u¯ê·ë2Ì[,ä`T·µµ•¯X±¢RUU§ªª^Ó4é3Ÿù̧[[[Øb!ëÇŸQL.?ëäÒüEÌ´@>/Ä6´ËG '‰œNŸÝÌÚXÌ󯬬,zâ‰'®î¹çþ(BŠ¢BA\ÇŽ ¿ñÆ!djé„hrS ð®Y³æÖ9sæüذ~€ºº:ø|>‚€Ý»w#ƒçylݺ0jÖÎ(íËq g°„ô}S£JV†™jëH^ÒÆIp„ËY×gý73‡‡ž”cÜÔÔ„+®¸Âðî—/_nxý]]](--…ÇãÉŠTUEÿ37ÝtÓwî#“4ÌVP¸ãŽ;ZçÍ›÷ckþß®&àÀE1â÷ûw ìö!Sã§znT3:bÊÚ²BŸ\9÷4cIL™NÎ"8nŒ r‰e©–ÓY4{üÇ7<þ‰©TJöûý»ûûûw755E¶oßnœwQÇÔ°úúúÿõ›ßüæ"3hŠLÔðœ_1‡~¬c•ÝgÜÛÛ‹h4Šp8ìïïïW9Ž3Š'›"=¹T/I£8K8¬¬“ä6†ð³w>#Š &Pš§§3cϺó{zzŒnéɬ‘‘i``@¥”âÍ7ß<ºxñâ{öìÁÒ¥K³„n®0õ´!=m,gbHÈÅ„Ãag2™óð­T°ÛíÆ‰'Ð×ׇ•+WÂï÷·´···ð<ááa[fkªœ=»“Ͼ>—1 <ºú È`"ŸÉþ®ùß}}}'%|öþÕ«Ww¨ª A°páB¼úê«Ø±c***àt:m‹B¢Ñ(†††œ:³?@ÈÅ=zô£¦¦&øý~°¾ó:|ø0jjjÐÜÜ QQp<ÏŸJ0aÁV=##À1B'ºÀeÀ`‰€LC)±5Vágï~„ýýýˆF£§t.XÈ„]^^Žp8Œ½{÷¢¹¹’$e%•b±Àãñ$1NYXNàñÇÿ ®®nýâÅ‹?[^^^cîöå8ååå‘P(žç½f[t&kGgr5$«!”3©iì0l|¶¶`§O¥dÜÏ·'r*¿õøñãhiiA*•2RÄEEEòܹsGª««k˜oÃ*ƒB¡Ppÿþýÿuçwn—¹Ÿíô™¿§É¦sf`Ð1t°ý‘.1'‡P(tZÌ kaZ€ñÿ”RéOúÓáŸüä'ë‘é Ðt?ˆt@ ™þ€ %ƒÌ$Ð(€ÀùçŸ_ÛÜÜ\¢išCÓ4žã8Þçóù¾úÕ¯f%ŠDQ4(á©@n¡pÄœÈ8q„3ífÞ¼©Ììdgé„wR–100pZ~¿¹CÈ MÓpýõׯH$#½½½~BˆB)Õxž—#‘HjË–-#º ó’AÄæßÏòåË[¾óï}KL£á,nŒð9&|4P>£ %¥ ··rJž²°wtttLP[[‹½{÷¢¬¬ Éd2ëõlP—$I±‡zè£|u9C~÷»ß=vÛm·}£¬¬¬ÎÊèM#‡£Ìáp ‘Hðûý“ÀDvùD™7;dE&²‡9‹±C-ÂÀ¢i„u±ÒpªAIÊèé=aPßSµX­¼%Š"JKKQYYñx<^ÿ›¹€X,xá…~‡q.×—‹ׯ_¿oýúõ?P¡×0g‚///÷¬]»öK Fg0+›ryô™¢‘ÏiÌþ$«”›p9M26À2Ié›t÷û/‘H¢»çøIµ…Mv%‰¬AŒˆD"ÒÍ7ßüìFL<›0 àÆ™ ä"„oºé¦º¹sçžO)•!!„Ó4›9s机ººr³ÂfF"‘,Ážî]Ÿïù ¯Ÿ ñˆõ3Í!aV"ˆ‡LÁ(e¥TË´ŒiéJáh,Š==9KÃN÷êëëC(¥”5~B’$¸Ýnéþûïÿ§£Gî'„h4J©FIƒÁîÇ{ì2h\°±0©ßÿþ÷÷ÔÔÔ\auEÁÐÐ8Ž3ú·lÙ·Û ·ÛmØ©\'çd?>ýkVãVf/£þ8¬9NçõÔ_zS šFÁs\Ú飀FÓŽÕH pfëA €¢(Ø¿¿‘ TEEE•Ÿýìg+Í5Œ X±bÅùW_}õµÈSNlB@Ͻ÷Þ»âòË/Ñn(@]]¼^/vîÜ ‡Ã1²qãÆ÷C¡,Âòx<^fgr©{3Xò™„¼þ€9ô³)ñ2l<ŸÝáœ~­.Lš®/P5- $p`¥¤±X }}}ÓÒç¨o´ÍpÝu×ͧ”6_pÁFÿ µ(Ä ‚}ûöý߯ýëOédP*SâhÝ@€äóùZY‚g Á¢‡z’$a÷îÝp8øøã‡æÏŸßF{zzDVé:Ñ}2!_> «ðMÄ ã'è…+”¦ K@Ò»žPŽE(‚ßïOw“3ùcJ)êêêfΜ)>|8tþùçc÷îÝX¾|ùDjfXÂÀœ<€q¹7A*ƒÁ jjj`©i<>üðCȲŒ /¼õõõsX9ØÆ 'µ“OFГ…åK³ÙŽžFÓÕ:*UÓ¦€Rhé"(r ƒƒH$zfS;E: ¸è¢‹ÕÔÔ@UUtvvâõ×_Ç–-[0oÞ¸ ™Þ6Û1¤×D‘gNU°7GŒ\yå•mn·»LÓ4‰‚H’TtÛm·]b­Ug!¡9c6Ù];_ÀZŸ—ùLΠjIÖÐÇ´à©FŽ@#<8JÁiÑd Ã~?EµoùÕ OÍÝ„gÖ0w±ó­( .¿üò âñøð‘#Gº9ŽK!=5$åp8ëÖ­û‡¥&@/ ¸o¹å–…_þò—íõzg[A}}}¬ì<Ï#‰`çÎp:[¶l1¨á“öDÞc}^„ìÆ3©Ci:i£Q€jǃ€ ‹c$8Y–õ™Ä¶dº§œq‡… ¢µµÃÃÃX¸p!J¥Œš€ÆÆÆ,P¯ ìÛºuëí?þø!31$+ $Pà}ñÅ_òù|Ø¥‚{{{QRR‚ŠŠ D£Q)Ê<>63"–°á1úl L#*++#³gÏ>XSSãu»Ý³ªªªPUU…444d ðb@ˆÇã'V­ZÕKƒˆÀàñù|°N_ëls+Ø®]»Ç?¸ãŽ;Þ µ¶¶6}êSŸšež\uªê?_)v–F 4Cý€6ž†í᪪À?ì7v¼©O<£-cå Ø9΀Åt a`` üË_þrÜsÏ=Ç/^|1 ÿ˜¶efE:+[ÿý÷_ò£ýh³]M€¼‘H>ŸÏv0„Óé„¢(xë­·ÐÖÖ†®®®ò§Ÿ~úK<ÏÓP(äzï½÷Œ FÌŸlßoè³ô}jP©4`cîÒ^šÞå`Êë›rDKŸM/%4°’>“kÆŒåÏ>ûìUŠ¢@Ó4nÞ¼yعs'æÎ Qát: ÿˬb±»~À˜šÁ®@ÅØÁƒÝvµ‘HhkkCcc#|>_C$ÏóÄöíÛÇLÀ<]»~¢CÓ4¨Š%•B`d©”œUB ÀB×çÿèæŸ£Ð'JQ}Ï›¨ev!Š3®¢Ñ¨£­­­‰õ,X°±X ]]]ðxÁÖ­[wmee%ìBXwÐdLÀ© œíú@ €p8l\¨:«Ë—dÏúMGzI95Í ´Ì6FÊrú¬iòÌó€XŵÃá@0¯¹æš§ý~ÄêizJ? ™Ö0- à×ÕE™ D¤;î¸ãÓsæÌ©³Ö2F…d¹ 9O7EÁÈȢѨí…òœRóп1¾`6tÀ¼×›r6Ðÿ3@TUUù¾ûÝï.ùÖ·¾õgdB©º½ê² ëÏ V ºï¾û.¬®®^€×GÃð±XLììì¼”e Yrˆ°ÛÉAã™ »÷ŽŽbttñxsCˆßï/u Ç `vÌ‹ŠŠJ?ó™Ï¬ÓÃx³£CzhdŸÞ¹~€`á¢:{$é ª« €x×]w-_²dÉLöÁŒ2ÓÀLm$`¾„ “CSSSÅ“O>yám·Ý¶^²b’gé.¡ˆÀ¤Å#]:ì»óÎ;W|þóŸÿ±Ïç›e5MÃÀÀ€Ñàt:ÑÓÓƒžžƒ :tèB¡PARS´šššÐÒÒŽãPVV†%K–  C#+**àr¹¬ÓÂúwíÚõðý÷ß¿é2±„N±„x†ºóÎ;ç]uÕU¯J’ä³rñx@õõõðz½èëëC €×ëæy^ŽÅbòk¯½ÖÌ&…Öé_UUU¸ôÒKû‰œNgÍèè(æÍ›EQÐÕÕežž (Š‚;wÞpÏ=÷¼¢›…@0iiéÒ¥W¹\.Ÿ]%ËFy<Äãqôôô`ãÆܰaÃÇ0sæÌº«¯¾º¹`¦n%“I\xá…ëh_|qõ­·ÞúåÞÞ^Gcc£‘”³+ áy---7x–¡‘‚‰t‡B¡J»Ž A ( ‡1`hhhÛ† Þ×U )***?²Ÿt@·çòk¯½6ˆ•+W^ …vÙµµµ#kÖ¬y ™ºÛ0PÙ¿¿ÿŠ+®øáå—_Þáóù*(¥¢~™@*Š¢ràÀþíÛ·Öß§k @‘(ŠI€ªª*̘1n·»°mOqÕÕÕ¡¤¤`…Ÿq=¶O"]é«|ÿûß©±±q÷…^تªª ª*G)¥Ç)¡Phøå—_þ@7lŠBd_ "`hóæÍ;é|1ñ'D¦Ð@àllllf>@uu5b±ÌZ¤°N6Qìšîw…‘iù–?Y·n]/2]¡;|Q0ØT1°ËÄëO†‘nM` Õ2ª€Að12¨¿¿ÿœRóg³Í—eÙ6M)…Ûíö"36¥Ë ¡ Ø£oZ«Ì²fXMË̤ô³v0F«ú‡%M´"+ãtSÁžÔ˜¸³á„Ÿ­…&ì|ÕÕÕmúC¬ì+e2Lfœ…áMèG–Lh&Õ #shs$ã—Í‹"I·ç¸ã¹¥nÏò0˜Ì.ÅJù¬SA©E^¬`tŒ ¦C1ÑÄæ³A‘Q¢–בsQàç¢K`²jÚÀæ¿|2ؽ`2Òä***æË²\à¦p9N Æ,B6ËjÒ;P8]æóĉ;fΜ9¿ šš¥—}Å_yå•ÿ´Så§¢NNe‰z¸X`æ½÷ÞûÇÓ6Ýá»ÀÕ¹¸Ìõ—²,Ë###~š ‘7ß|sý®]»ÞÔcú!Ý«?©±evíá'õ}‘.©Ð yÁ‚KÝnw…ªª™F{À²]ì‡Ã Lks÷俾ÅñfMýŽë·ýqm:À!Í/¨Ò5-+˜n‡@38‡@@M¼b"~FôÐyùdÓé€q}Ý”èÂ7“HdšwÛEôÔŒ€ca^TWûæò®iÓ¢¾ãú!Á&ñp†OL'H;G`¢ •|’x:@L±©`C" 'ç ¬üŒfò)ý–Ó »ˆbº…oX*;Ø»Oö* € (¬ «€Â* ° (¬ «€Â* ° (¬ÿöëÿ¦|räWI°IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_floppy.png000077500000000000000000000257341217176075400247440ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí}KÌdIvÖw"næÿªªî®êêGõ4x<ŒfcÃHF„fƒpƒ„` #a#d ‹‰‡@ÂÞ³äáY€¥ae–X!k<30ã6ÌTwWWMUw=ÿ?3ï8,Nœˆ‘÷ÞÌ®¿„:O÷_™yŸqÏûq‰™q€O.tS;ˆhùÖ[oý‹ÿ#?ñ¾ýïF±#3 LÃpÎ!&ZvþØOþDXtˆ]çá@é‚ÿ/çÿc`€!¸ !"„€>D|÷{ßGçC r 3bŒ "Áú®‚ÜuÝbõôþ·ïß¿÷׿öµ¯ÿÖ®ÛN2Àýá/ýÅ¿üÓõ¯üà»X,Optt”oDD " fàh¹ÄîáþäŸÂï{óÆÑ²Cç=á@ü}€f DF†!àá£'øµÿø7ðc?þ%¬?Fß÷„ÌŠØB¾LŒþÏýÔ—îݹýŸÿù_øÜ/ÿò/=™»í$lúxã×¾ñëøðá#Äàœxï3è—Ë%nÿà6î?x€7^»££b&`/`82bß#ÆúâÜÿ!Þyç]<{ö¬’ô¼÷ˆ1æ?ýý+_ûUÄ0œ~ç;ÿÃíºç$üî÷þçÓÏ~ö ïáœÃz½®T¿#ßuX, ", xïÀ`x",‹Þ¨¿70cˆ #ǫ̀Ïê^€™Ñu…t>ÑH¿33îÜyo¿ý;;o9ÉÌ‘ÉÀBðwß¹‡>ÈåA¼úêkøÌø¬h„DhŽŒè1Æt’¹8À.P@Añ#gÛo!ƘSšÈùJ‹0r—&U9/Iú‘W®\ÅéÙb 1€È‰ÈŽ19*‡ØâùA IDðä„Mï…&*\ιìÚs‰`ü´y˜Öé& ‡œ÷xýõ7ðûäÓèû¿ûöïÀ‘CßoÀ]"Œþ õÏ‚»„?Õ¬FâõëüÙý!¨_°[Ì„€#‡!03®\9Ã~æ³8>>F _øÂÂ;·¿_Žšè‡üÂåÁ‘­ªÂdÉWbÛíåS¾ù÷˜fç¹pÜÉÉ nݺ•33îß¿$u¥ê(Ù9 .™€Ì€úKú]ð\~×Çsåäýés¼Ï8µGf Ã÷Å(ÉŠ<ç@NEiì ñ?¢eÍêå;%MÐJ¿ns®8ç’SˆqØyÏ™8Q†’ÕOº™U5Öû, aLQE8¸„{€jM$!2Ƶ‘ðç%âRÚDì “@²|œ9/„€'OžTI ë„(çÆÈ€¼sˆ‘9ÎqÙ(͇0äß”’hÏö;PB@ JÉ\Â<ÉtQßý_ßHÔ:pÆ&¹”!dHšrÓxôÁ¹Ø1:˜‚]Àbˆ8;=ÆÑr‘óþ…Àšñ³š@?·A`/`š r`޼~ýåœmÒiÖ)*iýÀbÿ_»ù:ߥqX`XLg߬ÖDŽb8Sp*îW ­ßmòíRyÊycÚ‹†rš2«Ÿô0Œa`0ã`¬”3€‘Ð_ü,ëüÍiL¢=Bñ“/Œ`ËŽÁm8’Bà(ꀹ¨°Ì3‚ªíäÅ‹€mÉa2Ãf€8˜ÿ}!ùP*/DšBâµÕÂ@kÎ_* `©ð…rQµåÖögFPnc˜™Aä2³x`7DŠÙ÷Ê‚å¨"2PWÿò¹ ÿsÚa æZ¤´›lUAúÝ–'É9p"¼þݽÿäöóFÄpr|„Ţ˦TSí­½·R¯Í!Ö#Ø#!4í@}€âmjÂzõ!t©°D òw㥫è::˜= 2cµîbDLæ3r]´a·J¹7ª^SÁ#ânà´*¢æ‹ëþ¦0¡ªGG1«°"X Ôûâá Ö¶Ù÷’DÝoWÏ¿b”Î푃Ïp±)ÚvÔrãØƒ€K…*’iÇã&“Û“ô+ÊÆ Amø  Êf“}©DP©íVõØ›ÖE"e maÀ>Ð:n­´·ÛlWPë#dFÚ# œÔÌqTh­ºÛÓ‘’Ùß’+f¨™BÎJ~[DäÜ¥4@ÊFY©o?Û›rò\C,ÿüÀÅTæ Æ5ƒUÿöøü®z¦`ÆpU£€-;T j3B:–#<9‰c?">¹@è‡ ¸DJùiÍ­ÝnSÄIKÃî˜í l úÙª!,¥ðå½ûÂíY•úÄ3Bdœ/°Xt‚缫–n Daš”ÓãbŒˆ¹Së2yæÜ]jS¿v^Zm’ð§øLxù¥kðÞU­NÅßÖ›Mj¦‘ÖáŠØ Vk*.åHú–á¯lI[RcÒ ƒpŸT¥R¯ÛfAý' `… u¹ØþÖï–!4¤Â%Ú‘ʑ!õ–[›?¦vÊsM#ýŽ`v‡4ÀN(*^Ré%×ßÚßm1HU¿ß£c&@…Š&a‡ÞƬ$Nad†cÑú» òòY:ªÆ<ýléQk¡×å4€1ܹҧ6(€( äN¹ƒZmÂÀýA¤Y Hi¸Tù¬ÖmóÿV#™î…ŸÏó;œ@æLï€Tù+…ˆc¶Wš÷cæ\ ŒäÛ1"åc Ì’Ú“ c•·éœË! 6ƒÆÄ}RÿÑ$0‚ª ™á|pwÁ³ó5€ÕùrY(´ý³0 #ˆ‰ˆpDðÝef‰dÛòo"¾Úè'8õŸÎ-É èƒ`¯¶®Â1JN Iy›ƒÉk24ZAÛòvÁlÀÚ@œ9Š-Ê#·¡`ie’A‘²ÆóàäÌöÏDTijͤ)îÙdk¦ð9Ÿ° f3ꉪÊ,ùenª‚¢štbH]¼ &QiúhRæÜ×É‚“šÅ¯sA¨vfFÃÞó§óÔØœÄz#Û~ì»Î$|ÊôpçdÝ C°1c= Y'ëZµåeÇŽ ‰µ8Wu¥lì.˜Ñ¥¥L` ïRTàœËuÀt³DÆýKLêè v€Ôÿ#Ž tÞ•öúXÂêBI´5k5X?Y[ÌÁŽŽ ºôhÿJy˜ mdœÔØ WÏŠ8è€ ià6ýˆÊ%·’c45˜1§å/S p²è£Ü«nM¶É R™Ò2f¿Æˆj~ÁÆAí¾™ˆº§z8ŒôÛþ@¹VZ™é2N K6flm©ÀRÌ(¼P’˜%|ÊäCK»c•ëßêÅh»9Õa.c8–2°­?ë 휿⌖‚‘ÎhÉ+‡`lô$ ™ *ª²5±Ž @Ìˆì¿ ¶"T°Jõi{–jÃArØ ªö ±±¥ê­µE!ݶ½ÖØ4ÌO KvD–Û¾XU¢ÜJdD<‡jà¾gck? ÉŸX"«ömŽÈŸ$QB»—‰Û¹N`d§Ùœ€mEÎÔóXJïÞ(sÔ+†ï!Fœa¹è’äs<©Ïe“>@Müœ@’3vÞsg98§"X¯³ÜœS*$õ$jèµ›/Áa¿xôIýŸ¯JGpª¯eÁ²aø”FN—º|&\¦÷¨ÝÑ( ½©VûaãÒ!}¯ IœÀ] ÄóÎ!„ÁDÓœÔy)-ع5O“p9'HÙ©fzŠ-+h60s®Ô†ór12e|d|!KºüÀÉÆK–µ­½˜Œôu2ûä^fœ@M$ÇÆ"ù8" Ã2¼í ’v¸î‹O$pª Æ”K‰QZÄ´æoÃ?£R_W#.53)»'1~i ·u¹‘:‹eQbmM’e âAü÷U÷`©èÄ ÇÛ²/P§ê-ƒì;=|>‚¼t ^¦mE’ãKK²jù%ÿX`DÙŠ÷4€:¹669t[òadòîÌhä›*LMÉ7SÄMí'»s(Ÿl¨Ì*$Ÿ”îû¾RùjÆÞÂYú.9;X.Ó4ï.‡ƒÖî”ÌT@Œe¥*Žª‚àþsÿ†ˆò=Â¥ž »¨žSÒª9ôûe|€Sé‹MoÖ£‹n‰~x7^~aè'ËLJ’QuºÅw¼‡““«X­V[5™ñ|Œ iØÚ?³M¡H-Ê*Å”’C¢$ÔPçðüâÿáßÿ*þÒO¿€7oÂQ™­ò{Mÿ¹Ž3»O¿ïÛ¡öqw²µc½>—v°axøá}|ý_ýKõ¦$ÒAvBƒn³•-Ë­c\«âH*‹l¶;réÝzqë·#WÍo¤ä%ks«¤ÌÊÄ ßh9ŤÆm?„L‹+õBÊéƒ*Ý:iÅqNy{ãK)Þ¿óÞ¹ýÜ|õµjûWò2rr²þR7o¸t¤0böîQ®Ï"f)=¾ðâK¸sç]ܽ{§ž8Ê:ÑúàòÎÁ„b*ͦ¹¦¨á\rhHfyçr¿¼¬‡[ê½ÏÄ-*SK#ÊLç6Z×s4™¥× !f¼j˜åræ®ôåËÊ â¹ìÔé8$oRQ¢§g×9—` _|é::ßU!]¶ÂS˜Ã,Ôô< {Ñ¡A…£ô!Z8::Æ+¯¼†¾ï³dë+N]’ 1-*ÍéeˆTr×Î¹ŠˆÎ9PÊ?h¬«Ì彇w 6«•j“¤LŠÐ¹ DT&«‚*é±Îlˆ©/?eã8jÇ-Ò+ô4ÉÂãhVŒQÙNéq½VŒÑ\ˆAgPÕkû*a—Ë%‹%†aÈÛ2mšæO¤¤[ä˜çê¶çfb]º<ÀyMþøjòàI'¡ìº–Ë£LÌÌ0¤/–óºN8Û¥(­‰¦ ü|@!žÓ„3ùÜ65 õBÉbTî ÕYND¥åÊx×ºÓØ`ÍŒ,¹D©Ý:!3ÖEt>‰ QšçW&Í„ŠJQç¶ëzHµÕ^£žZ63sîë»L3€® ʈéa8;ž's~E™w>—,mñÈÚ1"Âf³)¶½yZ›m´Û-²ZuØ–HÛýöšöØvô©ëè8mVÔ^Û®Ÿd ÛþžòÞÕÁ¶`ó(Ò¦]¿1›ÛŒ9æU]öySËüú­³Á19K¦M”¼N=ÆÁ%‡+duîH˜É"È‚"WMF[ôп±%ê,¡Ûž sem"Ê÷n™ÕÚVËÔ1ÆÊ×±ãcÀIgP÷ƒÒû˜ÕGÉ£Ë~ƒ¯æYWç¼Ý&ƒ.õÂ}[•Öò‹­,! ‚OvêÀðï:È›ÆS¾šJ…ª•´<¡ÑYÇq[ª-X$[&m‘Ý^O¡]qÃ§í·“XÝnË´ÊÄm†Î2®½~»Mêoœ_ÁEˆƒÐZi->€ËãG6'•Ö"®Ùåâ.WFÔQ>ªä±S4@¤É"ñ#œ¾›¶ço—93q'ìß“X¢[­`§1âgÄj¸¨-G²ŸU'”ªß†©ªg¨LW­eoÒFç’$‡4õÞW/×H3µaãä·©y¸¤ ÐWÁµëÕ›—ERY%$;Cé"‡Ó5‹ƒÊo‹ämi•fRU‡Œša‚iS«ÓrmKXkïÛc[©Öãu|–ií9íj` "–esÌýZéW›¯ž»\Tÿ‘’0Aq1†ä§<s¢CJýæÓKØcÄ>®àl&°´ÂêzA™¡ÌR¥O©Š9ä‡T¼F¾v—E'µJ¹Ý‚ÔÊBI5¶3–Àm?}Þöû˜t×f‹ËsC’P~YsPð£UBÎ1 %¸”ùô]ä¼ñ­OFâSšÞjGÕÌ$ˆŸ"o†ÙrpŒ9ƒ#ÐØÛ)&ž†¬w+ž²// ? éc0RbÉeF$/;¨"£~õsúœ’TjÈ & ×\F|Nh5žUÕö€„£cqxÍ(¡®CߪI4ÐgO̘ð%ޱ&ÙJhjñ»UÐÑœ‰1­ïÑVmŸ‹„ b^JãbSç㌤´žsYeÔJRJĈMßWRIDé"Éê„zW^MKDÕ;rœs9±$¯°•qØ¥Ôä;ÉÒµ(×Q-¦’œý…ïk;Ç´rwäf‰š²Ý8*˜1jslÉøžFÔ„PNà”,b©¦d\’âM¿IÏ«ÌÊ@š‰j©†2®±´ÁÞ È§’IL.Z¡”F¥*Æ—Õ¡u‚D»l6|á~ÿ«_ÁññQ|æ\ý®T”^µ[Ç5ÆùªÉ”øö¢Ïêsó@X¯×ø'ÿôŸã¿ü×ßÀÂûœ´b” ¶Ä[&ÙŒ³³«¸öâKµ?Cå9Ûê¬:û„³Q@Ö[ Y}o‡a¢’Pœ@Ó>fÈRÏŽ¸õúëø[ógðôé#<|(ß÷ýö`²ß¸M0%<3~áQ¸,lݽu6¶vNOOðÿáßÃ/~嫸Æ7þŽŽŽ’‰\“²³Ì‹_ Üó‹gøðƒûxe³Â+¯½fÎÞÿvˆ^œ@Ù¿›Áwt§\µ:{(’Ú6ç½pnöþÍ22 ¬~±ºÀßùÛ?‡…'<|ø¨rÂ,sè:¿oSNF•ãeusRdBÊfÓO:|6Dƒ±1M]gê­‹üÜÏþ þûo~ '''7o`³vÐÉãââîÜþ>>ü஽pÝb‘ÃÁ,XÍ3>†žÀŒÙDX¦d’V‰×ÉëסF¬Õêš2Øô}¶ÕÙ&§¿®ë°^¯ñ¯åßâÁýà½Û ûÚ¸[÷À—^z oýÔŸÁññqŠÙÂR¡WKÔ±l¤þViÔûÛg¶pçΜ]yA36UDT‡Ø5¨úñÆË¸ï}ôCŸWc!s¼Ö7H¯œoƒå`%´å:J¿Õ$¨Ê×st›3„µÄÑ^¯eh‘í½Ç½{÷ðëÿù70 eºV¼l¸U=01D, üÉ?ñÇñ曟ª¼ù¾ï·²}cI"K;.{ÌcÀ0”yy9žoÞ†›•e&‰¦(;ºédaãñ«¦þ(0›²Ë•ÀN׊… ´žÝÚûäUHM’0Ʀ±ùmÙw±Xàůc½ÙdMQÇüÆò'Û©Œ¶èÄéêû¾"ȜڷÇÓR4¦þ§Î-1žO°ç圎1¥%g2=38ÿNŸ1ìVý ³Àªï¶bHûræâ4x›ä!@LGÃá6<†g±ªúkS±’mdHuÖš•ºM]®QÂ0ïk?fç|ýnÕý.ÆÛ¢¾Î½0]ÖZŸÚB—q˜ÃË:SÉÌe±èdšõšÖ]*àથb§RU£Ä´Š´Œlõ#”qt¦ ]'YCËhÖdè¹zŒÞ³MàTcC­J•csm¶s†¹æÚj„QFI§Ûëää˜&Œ¸¬¬ZT’Jc5Þh2ÖÉøÛ;fMWÙô{û>a5Ú쑹wKíò6‘’§·©S…õjëÛ-wÛ1U a’)!Hœ)iÏÓßö{kçõ¾[>G‚vI==f¬/BÇbÉc4KÁi²(÷ú™k´¦¬]2öRk[¯¶-lèŸ}q”•8¤ˆ ªznâTdd›Í&­l½íqç†ÙZÇÆ§¨2x&3'Ç„ªl£š!ëŷĶ„²÷k‰¦B`ï1Æ0yýŸd«K¼­ÜŠuºsšËt1 n^Ñqµ‚×j{1€Ü³ØûàÖû¶Ý4Ú l½Q;0åd!g‹%œ+ ¦Þ?áøø=N^t€Ì4¥l÷ln"¬òKä~uãgÝd¥³2=(BBMPµ„¶ã¨%k\âçñ›´;˜"7‰ÆœâÖ²±ƒ 97µ×¹K,®¾%1–ø–ãZ[I®.»f¤d®—‡µ@¯£²Ùlðìü™dMǬ.‹n-‡“2€,uàâüY[9f'­9³’Ü2ÉX×Q0f¦½ŽŒ¯qÞÒ8+'®1Mº$¿$½Äˆ“»íLêxô^!FÄË,S©¤†ÃôÁ[Ž×©±d¹R­(Õ3«Ê´ßŽ(!.rig®MFiÓŠ:›D’õWP1gÒ2Õóm1ƒeûì6òÐc¬9´Ñ†s.­ðiIeÞÄÀ–ðzLÆköì‘{/¬`Y|Ù{s —cdâbëa5×n™@`Ì)çë~k¯½w£™@-%ëÔtÍ4ªO¡4ÚA¯bJS‡0`jû<æüµQ‚urçœÀ–IôZYxô^Ê„ÉT)AÛqŒ›¶së4K+]M|Õ®t™—F%÷ÌÛñeQAÚÈQ Z`Ìc¯¼Wã•·*Óvß¶*.Ú(A©1­kº[y;\Cv+É›Íf‹ØVûéïöíõE›Hi<„ÛÞ-N–9m.„̸êûéK<=¢Î pU£ÈìŒÚFŒº²Wbwû0cÙªÊ;MgHó£Mð´H©r'ˆ sFÉLžbÅLz}›l ¦¿Õß©Ç=núÚg¶8Ô¿ÔºR…¤-#YvìBP“á‚SYs¡ÌG(¥ÒmN ì½BûìR±œï½Äž9Í‚µéF@{úKÒFe‘X®m†«ÕjÔ¡ !`½Y§ö­íŽ^«n-ȵe?ôèûMUt#ö´Uéíµ­†súZ"ZÍ'ĪrjM†ý͆à’f/> >Åb±ÄÑò(7À„±Þ¬Ó 'b€]0û¾€4¢üªØbo¸šnÝ>Pº{™K˸r)³ÔÄcB©Å·Ò­+Œ*1¹É ŽoK !Òç½/%2E{N -cŒ…@­ÁZmVpƒ–jR§hÖz²HNXU‚BÄÙé†0éÝç›Mò“¢!â4Ì®¤]rúp”„\jÜ´³„’VO asŠ(Û±³‡ÞzçŠ@ç|RejvŠ$´Ò7Vß·)Ø6ÚN£.3Mí܇qÌ$hÞÂk7êQ¯¡ ibFÑ¢9-Úþ†„ïì{YG•B޶ò½ÒåB ðTfHÏÁü+c`2xòXÒNÉœ‚*¢ÄÍ””Ò3_´l׿U—z/;Ã9—W1À:˜ÖQ²V΄ô}Ÿ²5qT½Z†cÄ6z°û[í1ö èú…xB¸˜q"×ê1*DêÃÔã+f¸ÊÍ@ß-À`I@cÈÈ ož;jKV ¦R%i1…º¸Qq3(v ijlC„œa—­Sh'bhC ¹íɨVë½ZBf5“U[Ækϵó€&s—M™®ôž&šá²4_™éËò³ê"›óÅLp¼L50=$‡ÛÎÕ¦2oϯ·ê^Ôc—훣º˜$eàD8r`7žH—n4‘®R&JyN)Zí .5«ràuªE$¢‡ BAlÂcN…²M@ÉÜ)ÁZµ-!h¥ÒšˆÖalýÅWËå¥B…Ì9œN'gó«û²®#àâüNÏ®àüüYʽ-sq~ï:L²±\×±m\ÛU;ôUÇ-‚‰¨ÊŽ!\Uon‰rvŽÊ¤Uëx[DðÎç:€uÚäÔΧËå^6„ÒkÛdOöéxÃ0À§u3N­ÉIÏ”í<•žmYŸ…ˆ°^¯p|rŠ®[äçÚ¬×eDïá“ùœƒé‰!ÎyiÇbM¼A<#"@×ó±HÄÊõ4ÄÊûÑÑcž¶¼,)æHAûþ¬æí*©Š°tÜjµÂÅÅE=WŠO`·Yt ñ@íD¶ #c×'›2gû^%@ßµ¤ N@vh 8ö§§WbÀùųÔ9 FMÂ]Âl6ë/Οb¹\`Bv²d\ }[xajÉ`éj¢"Áõº€ceÖ¾2q,ã¨Äžžž`è?yR;TÉIÕµ!w¯ˆxóæË¸~ý:˜Ko,¤`}·M[ËL3'›Tr¾|ä9ØnKW É­ôÌNr'gW@Dè7›$`œý´0l¦È›a’BþÝb±ø¥W_ûÔ/…+ó$fÐA©º*fB’EC(q ‚¤¼0HëI÷}›7oâ«_ý»xôè‘,k-iÊSsµGãÆK<|ø0‡²cÞ1Õi³`TýÝj‡±ò²÷º´­IXmå%Ú”w)£“®uç62púèà!bÑ¢yînÀ(&Ù_¼ûþ;ËW_ógT‹@¥žMÎÁ'î+U6¹„zîÙÀb±ÀñÑqe[§zôîÝ»‡7nà¥ß0Zf,ÉAEÊÒ¢T}?àƒf)Ö1X"µ¦Àj£–àV Tæ§Ù§8²M®@)g׉¯˜¤[ª}_3åÎ*Pêþaa9FªŠ¢ôúAïµ³'lJ€Ý0 ÿàîÛg¯¼úÆ_cî’&PiU[-Þ>ƒI³wÅ`–¥`Ž–†ÎIí\/ùÖ:W÷îÝ«§ßñv]¾Ö³·¿Ç˜Lïe¥¹¶ßە–Úmc>C šÂfv´O¸ªk%}¿ÉWš‡IùÂü»˜­3xÂo„™: p à€†aøú½»ï~êæ«·þ4³7ž´FÂíGËeiz¬$ƒ§/à=áÝÛoÿ·a¾ àÏzç_Q(4 ÛÖç­$·kôŽuïdo7ZZícU¯Föºm%Q¯×FzNË|%,/tVB‹tÛtu)@]»v ¶*øøñc·q¢c €K3‡4ù^ž÷x‚¾¡ÇÀ¸ à5? àG†ax÷‡wß»}ó•×ßÜúpbß»®ÃÙÙIEDu5¯íHÖó¿óÞí§Ã0<pâÓ+Ë;‰ ÁlH·µHêÅSRhÕu/GT¼=·%² ¬cÛÚû6¤-Þ>Ì !¢Öe²' åq+W®œáââ"O%»qãž>y‚MöÅbvø†¡ÌŒÒ’sŒÁA´øs1€b[ÕÈ n Ãpç‡÷Þ?zåÕ×_¹zå,Kûr¹ÄíüïóÕêü¾9Ï^ÃÂ3ŸÀÃ0\‘ÅmCIG+[9[*Ýö8{½1ç¯eUö­5 ¶6Ð2b{ýr "tÞãêÕ+¨¸"©’&ÙdÁÌG'3)xX­×¸v횆ˆÆ²É9CÚ=îÝ}÷[ÖDDàÇÞû7½ïNÒÝÁÌnú˜ù}Žj/ôAõ7Š1Æ[·n]ýô§?ýz!g—-ÒÇliº¶"˜G¼ù| äì´<6¨h“B@ö7ª‹·¿cŒù~z=Åm×yºÿ!Þ~û{ð]ÊÏç*eSš.›ß8RîC°X,äÚ9R-Ësh¢§aèÿÏ0 ÿÀwŽï_\\LΙÒ"© °ðÀM§!„ߌ1RÚÏImy"ò * Õ÷¤‚QôìÙ³øÍo~³÷Þ"ŠÎ9NÇê§ÓssÎ^O ¤—Ós Ç¦ç\¦Œî³û Œ…• JÌÆí>·333û#ÅÑoÜ¢dîX¯˜fíoHÿ#ÆÈjå{>Ñš(Ž1rdÌñ!ïzïÞïºã‡«ÕªÿÊW¾2)ýs lуùþÄ9\0³WDw]GÞ{òÞÃ~wÎ}§”š%ç/—˰\.‡ãããa±XÄÅbÁÍqp”Î!ç¼^KŸj2œî· ¨ûŒ©ÈÇÀµe†–à '¤DH\f[*Ž1ò0 ´Ùlüf³é6›!¸a(„×cC1™N™Ñ˜RœL`LŸºŸC< Çy³Ùp/S¨žxHD‰èÑç?ÿùó·ÞzKûÐFa”˜™‰hH' .<°$¢îæÍ›¾ë:¿\.Ýr¹¤““w||œ?‹…ýsGGGèºÎu]çt{×u´X,èôô”¯]»®^½ޱ\.•9\×u.I½V¿ëv—l³nTâ;cœÉ°éw+þD6P3Ó ÆJÌ #(Ñx½^Ójµr«ÕÊm6êû^™‡1c"zLÄæabÚ— !ðf³ÉÛ‡aˆ}ßsú‹«Õ*®×ëÞ9·°:>>^_¿~}õå/¹ÿ⿘ótcL0êì OžL`8ö7Eà8ñF~‡‘}í¶©}¢©‡‘kÏ2Àîöj¾ýlŒØSßǘeŠéæ4Cû׎¿%´ýn ?E|•î–p5uj¯uÛܸô¾Îœ7íLÂeÀÚ6¿q ¡æ¨‰ÐóQÇ¢s­bú®3Ht\úÛ"Êaû^ö77ß-ŒŒöÑíö–i¦4Ì3¶c{– —e 0%à˜šj)çZ©“î9 oÍŠÕ.­Ö™Rÿû2€¿~o¡e†1óÈï1ÕÞšùÝš†v<;áã0cΑ•8Eü€B¨15=f»Çìü˜9™"6šsžÇþÛçlmé”9˜Ò ab_h®Ñ2H{Ìœ39fó'™á² `o@Í÷1µ0N);Ý:nSv|ŠÈ–ö!üœô=ó\d0÷7¦5,¡m†˜ó=ZŸ£Õ¼“ðq:Ö %JÛ6åˆÍ©éö8L7µß~¶ßç¶í²¥sZÍ÷9F™Úޚϩã¬äëqcã­àRy€±ëa\ªæÐn›"Ú¾Ÿíõç¾?/ìËcßçÔó3}Ôãö&êÇ©æn>‡ô©}ûê²çÜ0‡ü}ó<ç?·Ü 0—EÊ~àÿw¤Ò|ÎЭIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_game.png000077500000000000000000000535261217176075400243440ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½i¬e×uç÷ÛÃ9ço¬WóÄ8TQ,")Y”eÙìx”l˳;t€F:H€HÐÒé¤$úCÛ‘8hÄî¤[i£Ƕ”Ø–lÙ–e˜¦LI,UEÖ<¼y¸Ã9gù°÷½¯(R2'¡|Å7Ü÷î>g­½†ÿú¯uDŒ‘÷Ö»wÉÓxoý›]ï)À»|½§ïòõž¼Ë×{ ð._ï)À»|½§ïòõž¼Ë×{ ð._ï)À»|½§ïòõž¼Ë×{ ð._úø#?ÿó¿Hˆ©$ PRRR Š¢@ %Ä“ª(>Õïö>Z”å)­d¯¬*B´Æà¬{–cô/ øjŒ< üIb „éT?ö£?Ò)5!xʲÄ{)5eQà‚‰@¥5UYˆ‹‹+ô» ­©X]ÛG €!$J„XãqÞ)J)”’xëñÁ£¤Fk…±©Þ9ªª¢m~÷w~ë=ZÄ‚G…’ï—ˆ !V…>¨¥^¨ª]h‚÷Xç¬1æÆx<ú²µî€Ï¸Î¼Çysž<1DB|ö³¿ú–e÷Ž(ÀwZ1FBOuŠò?]Ú³ô‘½{—{ý¾|˜ÆÐ4 JIZ)Ú¶=l­{ŒÈÏFÁ@ ®ÿ;ðßXk¿Û[~GÖn™=üŒü}!äö QªÐt;ª²D(I§ªètz(% 1î3¦}l{kûß__[ÿÚ¨ÿ“â¿þníó»¦Þ¼ÛëýÇŽyôÈÑ£BÁæÆ×®_£qÎ!%ZIʲ¤,KBŒxge qÞøˆwîßñعÇÎ5E¡áÿ¿<!³öÿŒOÇ)Î{šºÞ}=h­èt»,Ì/pôÈáÞ=Ç}ïÚÚú÷^¹võÆ`gðß„íÞëwEbŒ3~ëè±c?xâž“¢5 ÏŸ‘Á6UUqäÈîà ‹ó ôzʲB J¼ÃZ1-MSSkF£šÑhpFiý÷Î=üÈÿ(פúnìþí­EQòÄ“8võÊ•Ouª’N·‹* :eEYhU µ¡(KEˆÓÆãuÓ²¾¶Æ³Ï~ªêpøÈa9wîè­;w>{åò•¿_7ÍÏßx§öûŽ+@ðþÇ{3³¿yß}§ç;Ï¿ð<ÆŽ»‡ïûèG9sæ>öíÛO¯Û"Þ¼wXëðÁ|ÀÇHpçvf­Á:ÿ\ð?}øð¯c _ 1n½Ó×ðfWŒ‘âàÃÀÏ !ÎÝwúÞ{ÅG?ú½,ÌÏï¾6Æ”AQ¤·/ˈXç!PÇXpÁ}"1F¼!‘ZS(´*½¯N„àNh­±DŒT”M„¡¢UR®…kD„@ƒØ Aˆ^scŒ%„³½ˆ%RÌ()*)D¡ÊRJ%„”)TÊH„@J•®”y€<Ù_)•þï¼G PJæ@9½¹”™:Uʇäø±c|ýëßàËò'¼ôÒK8pˆ¥¥½Ÿ^_[ÿË@üÀÛ‘Ý;¢~¥Ûëÿ]¥4«ë¼ïÁ÷ñÿ=÷ÐT»cL/¼[Û§¿/Ò_)‹H05 ‡;´mK1)ZØUR’—ÿ†@!€(@(QÝ]bÌÚO¥-¢ {Òž” ÓÏÒ"¥ƒ”JP‰A̧V¢¤˜l"D"Þ{„ $!"D$Æô9"€O–Í´-mÝ⣧ÛíQu*„xñÓ{•ÒÎùùY¾÷{ŸbqÏ"_üÒyùÒ%˜yr{{ëiàÉ·,»·Ë þ¥_þ[OIõ+JKbˆ<ñäùáþ!NŸ: $Ÿ¦õÛÛFã1´M›¿ñ!¤T+Ÿ!ò]cr÷&‚LÂD‚œ~-)ú@L•‘§žÜ£ $,!Åî‘]S.©R&³¯”š¾§‚#+ËËl¬o‰ÀzÇÌÌ,÷œ¸‡Ù™œ IñÒe „¤Ð\zùeþèË_æý,EYàœÃ÷¯~í³¿ú³oåÞ¾-ø¥_úå¸ ì-«’'žøŸüÁOrÿ½§q.àœ¥Ó©Þòß¿{E"+Ë«loï$ó* „ä= H7‰Ò2¹ !‘ê.+T²9‹˜n¢BS­ NÿhŒ TJ —,O¨&ÿ쾿 ­DÞ—$Epž›7¯aŒcßþýÌÎÎ!€ºiX¾s›ñhÄé{O³¸¸')H»’B¡”@J‰Òš›7nò…/|¿zæ”VH!pöWåW.¼Ùûú¶\@Y–œ³{‚'žx‚O~âÜïiZc0ÖÒïõ^ó;7oßfmu¦nðÁ(¡@J:eA§S±wï^–––^õ{Áû)«Š•å;Xëì3'žÖÈŒ)$S,ÐJåˆ;Ÿ|‘̹"›pq·ÐãÔ:Àät3Õƒ¬Ÿòz#1@ ž>#1z¬K®Bˆýz`csï{öî¥×뢲’”eÁÒÞ%|ð\½|™ªª(Ë!dü@¼O‚CGó}ý(ãqÍù矣,J)¤üià¿}³2|[ àœ3 ÂC“ùÈG¸ï¾Ó œsT½ÖZª²àë_ÿ:O?ý ƒÁ6GÀ´ £ñç=J ʲËÜü,JJnÞü#öïÛËûßÿ§OŸ~Õ{.,Ìã¼gme!@%*›]¥*iBI”)’;P2?äÔb$Óœÿ¸”ÓœAN½–Hg}jÿî%ˆb øB„3L+pÎe¤’xçÇ)ñÖåx!e Ö¬õ©hŒescƒ½û÷ã¬K.$¼(©Á#½çÔ©“|ô¾Ÿ¶mxåòe$bøVdø¶à7ó7–ÿ«ô_ßüÐ÷|ϱÏže<®ÙÞÒíu°¡ì÷¹}û_üÒ¹ðÒÅ ’œþ9bˆ”EÁüÜ,ÎV××¹s[ TÒ’+×®qóömî¿÷4ùÈG˜Å¹@ŒžÙ~Ÿâb0 „@)dN·RÚ¨Tº´Cr2u99ábô%-'¦ N½W¯‰‘—Bï\ŽÞ#1œ÷øRBVºŒß{—žüµÉѶ2RÑÖ5ãшz<ÆXGÓ´˜Ö0É~R-Be¶&ÙõÝ{ê4;úuÝÖ›kÿì­Èðí)À?ÿß>ùøã~øá‡ !²µµ‹(†r¦â⥋|þ÷~—õõÍ|B5²ðKú½ÃÑ¢(˜ë÷©›–‰VRœã¹ó/°ººÎýÐ'9pà £Q'Rt*öMÓ •ʦ>¹¦®YY]aa~žÅÅ=éF› ä5ëÛ¼fòÝá`ˆóŽ…… E÷“è_Æ@ï“{Bâ¤Cˆ„s´¡ik¼÷k FÆ:Æ£uÓ`­%±Æ"¤‘¬ŒÖ’v‹R!@ÕípöÌ†Ã¡ÞØÜ8 ¼øfeø–àsÿÇo骪þùƒžUsssܺu‹Ö¤ÌÌÎqýÚU~çÿþ¶¶·ÐJ'‰fû=:û O]×€ ®kdLÎWÈtRîܹÃç?ÿ>ùƒŸdiï^Úqk U§¢?3ƒw X‘R¡´æ…çÏÓ´†å;Ë<ùä9½|»k0ðÒKBpäè8€”!51¤„íK©XàïÂ<ƒŽ£i Èwï±Æb¬!F¨ª*¹Ÿp‚tàÕÔÊÅBE¨úý>÷Þ{ºxñEÿ{Àéï´ÿ×[o9?+Ëâ³ÇÛôøq¶¶7 ¹R'ìlñÅ?øC666ÐJ§QtÈl vXÝÜäöí;¬¬®²±¹Éx<Hâ}F }DjÅòÊ _þã?f°3€©MË`0"UU&+ 5R$³ÿâ‹/°±¹ñŽ À9Ç+—_áÂ¥‹Xc¦ß°(•\’ÒEAQ”hU TÁâžEœ³DÀyGðoÁ§R·1–™~ŸN§‡1ïÎ:Bð8kñÁ'èΓO<ÉÎÎ<ý^—C¾j1F^yå9ò*øùX—/_Æ{Ͻ÷Þûº?| Ä>àrqË;‹’‚§Ÿù›››Ìôû Ži¿ãzŒwžÇœ"Æ”Jœ(%P²Èé` j•N0s§S2Ö<ÿ‹uîè'?ñ‰7z=oÉÁoœ8~\ÏÏϳ±±ÉpP‚§*K–—oóü‹/b½G‰€s€ˆx/ÈÌì,ÎÚ„¯“N— tG}„íÁï{÷ìåĉãoê:¾[k<ñì׿ÎÚê*Þ@03×çÔ©S8pˆEÉÆÆ:kë넘íÏ2¿0ÏÎÎ6këlom±±¾ž2† Fôgz;vŒ…Å„)(´FJMQ(ʲÀZÏÅ—/:ïýùðSWßÈ~ß¼â׎>$ªªd.h[ÃÕ«×RZd-Ö„lJ£º±„¯¼ò2ÇŽGª9-æ)¤–¥¸qã:÷Þw/Þ:ê¶esg‹{â±7å×ÊÊ ú'Jnž{ï€ÙÙYŒ1ܺy‹¯=ó5Nž<ÉgÏ2éözœœ›Ç;OÛ6lnna¬asmµõ5<Ⱦ) MÝ4ܾu“—^ºÀ='NpàÀD”9EŒ„à1ºöí×+«ë¿üøÙó›R€?ÿ‹§Ÿ›™}xÿþýÄiššá`€÷XlíìP×5ÛÛË\¿v5U¾"8SÀ‹ ×MWm-R©TˆÉŠRÇB§Ë`k›g–ÿ !!zÊ¢Ä:1 „ ×ë±±±AYV w¬¯mpâØ1ß´ÐÞ©Bà«_ý*³ssì;°Ÿn·—Ð K‹øà¹|å ó :r”ÖÔŒF#œõï)Ë‚õõU677Ùð {öî¥SVè"aFÅí[·èõúÌÎõq.Yç‹‹{ØÞü[õÌ3÷<ñøã£xSY€TâŸ:xPE‰1–ºn°Î㜅´M‹T’n§ËžÅ=tªZKt¡éu;()©[“…/B£¤Np°ˆŒš1n‡²J€VŠ™^ù¹ÆMÛ7¹rå +ëë,/¯°¶¾Æí;ËoEnïØzúé§¹yó;ƒ!;Û[´m8Ö0hÚ!W®^!’XCeQ$î@‘Šë $Ö§¨Bª…€u B±½½…s X²9‹˜€RE¡Y\˜×Rèÿîìû [€o|ó›÷ôªê©¥¥E¼wøiÚo->$æNÓ´„Ѻ [Ulmn tâøn—ñx1&øV*¢`ŠÕÖ: ¡„ÃшJ8î‚ÁgëëëôúsÔmƒw–ÍÍ· ¶wn]¿v­Á6Æ[F£1õ¸a~ažÛ;F£u]£´MKfb* MÓ0®ÇÔã1RJJ•ŠÛEYÒ´-;;ÛŒFCŒ5c°Æ¢‹d@…ˆá=*ƒTuÓ|ú¹ç_ì=ôà™ñwÚ÷wQü{––”Öš¦iÒ‰oš ^Ĭ‰žÌõûlmmÒ´-sUáÁG:eE]3J¶[2–d#Øp>ióêÚ:ÞZ´Ö¬¬ÜfϪb"ÖêzD[iÚ–Íõ7œù|WVk ƒm‚s8k†”¥Æú€³#>:*}ˆ(¥ðJ£é“54Æ1±ÎbŒaggUx—bkZŒµìe1¬M@SoS:BÊ:fúýÎh<úÏðöý†ॠ—dQŸY\˜Ë¾ˆRÓ´X›*aÆ´øP­ÑhÌ‘CGØÚÚ)›T¨ ʲLH™J8€©0BÊ™GƒvÞ0  Ç…¦[h>B§êqge9_ mÚtc¬£x‡ÊÎouÍÎÌ0pÎSkÅBÈÄßà¥iæç©ª ¥D¢…Qzºý>Z©„o8KÛ´Œª*‘K„ÈRÄ[—‘BTÌ„œ€g¥³³34Mû·y'€Èßê÷zsUUaœ#Fs¢Ð)ð&5v(•ˆ ÆXvF#žüÀ“¼tákëë()±­eïÞ}¬­o ¤ÊÂXkiêšQ=‚‹‹{¸³|­ÎZxàýÄxú™gp™?(¥ÀX—.B+LÓ¼îÖŸùÚ_³²²Âž½{©ÊŠñhÈÖÖüàXÚ³çuçέ;<ýµ¯±oß^z½>Ö´¬®®sêÔ î¿ÿ¾×ýx€?üÒ—’iVcB.<%Ü…@ÛZŽ9B¯×Ã; aü>z³}:ÄùçÏcK…T‘>>b½¡*JfgçiLCQø QQ@TÄèˆÈÜ,SÑéTG/_¾ò'Ožø£·¥B‰ÿ`n~DïsÀáé÷zJãUŽd« ¥ „ólmnñì7¾Ið²,‰Ö6ÖxôžÇ828ÌòÊ R*Ú¶ÁZ‡sïçÎ=DÉŠ©ÐB°¼²Ìíåå g–MUUSè¹ÐI™^oýùW¾Ê7žû&gΞanf–Õµ5.^¸ÀÁƒ¿­¼xé"ÿòsÿ’sçα´g‰ñxÌ /¾À÷ß÷}[¸ïûyêCâ‹_ü#º U¨)ÉÇÀp}î€'žx"Ç<éô’ïŽ!ræÁ3\|åe®\¹ÊÒRwJGR0[=÷0EY2€ ªª6 tœÆI§ßg4þ'À[W€W®\[(Ëâá~¯·[÷θuQ(­PN%ZS¿G·S±¾¶†w–­ÍMbH@·¡$.\à±Ç£w¹Ç¥‹/grhÁìì,Ü?Z+þôOÿ”íÍÍ ÝšÕ••\KõóÃG233Ëæö-%RJfçæ0Ö¦rm¡Z&Ó¹½µÁ­7Y- Æ£Û[[ÔMým¯Yãñ˜Û·n1ØÞÁXÃÖÆ£|Óï^w—‰üÇŒáÏþì+D½^g-ÖZΜ}¿ðs?ÃÂB¢(6ư¾¼BcæXXXd~~‘ùáæ÷ÿ÷yåÊeª¢ êt0­AJÅã?ÎÉS§XYYÍÕÁĨÎá¥$x… Á;ºUI[Ëï»~ãfyìèóšÍ¿Rü‡½n¯Ba­IumëTgIxÐR±wï^^¹ô Û)(sÁ%˜ k«klmmóðÃó±cÚÌâQܸqƒ¿ø‹¯séšÑY¨ÌûL·ÙÇÌì<@iMŒ)>xÓmÛ6OB`¤äìÙ3,..fj¹ÇZËÙ³g˜Ÿû¶×|`ÿ~~êÓŸ¢(Êd¾­ãô©S=ztŠõOR¯˜)CAYU|æg~š÷¿ÿ1Ο?ÏÆÆý~ûï€GytÊüüç¿ÀÓOÿ%1ÄìB=÷œ¼‡âÜsÏq~ê3?͵+W¸|ù uݰ°0lj'˜™™aem¥$%EV€ j­ð> ÇÉT-ŠŠ²(ûÆÙOÿêõ®õo„‚¯]¿ñžÅÅ3UUÑ4 ÆšÆ`mCŒpgy™µõ ¬sTEI$ðÕ¯|…qÝNzÝ>`ZCc;ªN…’’ÅÅE:U*Ölíì0 ÁF£óó øLúôÞ|ê%TRð± ï=ƒá¤da~ž~ï‡9xè Ö䔸‘RR¥4B‚’©R÷Vð¸ióJ$FŸO3REJiE¢x•™ u÷{µÆòÏþ—_ç굜}è!<ˆ”ŠÁpÈÅ /2ÜÜæg~ág¹÷þûñÞ£dbYëކ4M÷)2փňˆ‘ªêPu:”¥¦Su¨:UYaŒaÜ4_ѱcôXPRæˆ6U¬êºaÿ¾%Ž;Ê… /#¥"8GÛ4 È‘¹ù¹¬ù°µµCŒ›„Z)J­ˆJ1_ì!Ĭþ„Œ)À;ÃéûïcnnŽë7o ”D ˜é÷™››e8 ©DR™P8‹”’B§S£”~ÃLåd½Þ[¼O,Îy"Bâó‡\Tæ6µ€LMSÙ•UÅoÿ_¿Í+—¯rß°07›8~ZÑíVœ8q’‹ö_øüøw¤ÓíÒÖu.‡¼ï¢%(E XE¶Di/ïe¦¦¹Ô½\ȶýàòòjyàÀ¾×¸ï¨BðïeYÞ§t/—L s´ÖR•UYP7‰À¸½3à샱²¼Âúú­iS3câÓ%‘DŠÎ«Ocj ñ‰<â“©õ1$€Èfggxä±ÇØÜÞÎmÜ !G¢mmJä]åe™n¾P­ÁûÌÒx¯Pªø¶Šb¢}…Z²­µÉäºLÍ­Ù©G!ì^‡ ÈÔg¤RtªŠÛË˼pþ… !&N Œ¤NT»Ä¶ÄY‡U­-Þ œSH­PV>õzrþö@ȧ -f¥”8“"yÞZœMævb„TU‡¦1)2—’×orìø1>ý“Ÿæ‹ø‡Ü¸q›¢ÔÓˆ!XسÄOýÔghZÕ«W1ÁÁÁ§tÓÃýûøØÇ?. ^¹|%42óâæçf˜™›a{gbLy7ÉôK%PR$_(™ÌqQt;ž?ÿ<ÿâ_|Ž…¥E8ˆ”"uìllñ‹¿øó<òÈ#ŒÇ5!§TÖ'pÎã£': â¤]-Ü%|…È<%ÖXªNEYV¬¬®‰Ôã1ëk¡$1$jyÓ¶DïYܳ‡¢Ð ê• J!bDšAz¢ KnŸLGG‰ÖÉJj¥pBî[Y]?½ßÒËoHD ¿¬T9}bŽæCHšøÄ”ŽÁÂü,õ¸Æ:KQ¤v¨›·n±ß^~ê3Ÿáùç¾É³ßø7¯ßäö­›ÌÍ/Òëõi[CÛÔlmo±³= ©Çì?x€ù…žzê)~øVV׸rù Zj„LuðN¥Y\˜gggHp6SÈ’ï—y”‹”¤P*s ´lpÆBd}s@`¦ßC*ÍæÖkë« †´mƒó.áî.â¼M<>ï‰!Y²è#àSÌ#÷IŠ€Pª¥,*N<ÁÅ—/23Ó'H™á\Ÿ„§$ãñ˜Ã‡rêÔé̎νÂD­Þ¤'*…ï Ý™>Mݰ²ºÆíÛwÈÜì3NŠ¥ÅEÚÖ0nëìwCn‹ÈL,™B­tAQ蜒éD;ÓŠn§Ãí;Ë´¦ÞÙÔu#%Üw_æ9xB˜Ýá¬Oµzï‰Yuâþï%ÝíÔ“¨R+šô{=zÝ._úÒqáÂK $Z*b ,ÌÏó£?òc<õáÓíõRÇqÆ&`w–ç(cñ΢OA³O¬k!È ¹Õ®Ó餸ǘÕ}ûöíÿ`yeåI)õ_ö{}¬miÛ6 ¿©×u*oЉŸtâd%ètX_ßàÆÍÔu›A¸œ.y¬sÓ:wYj”ÐD"ÎZꦥi›é „ ú4'@fá:ùÆÔ@‘9¦7@"•¤P¥….S  ô”`R–%ƒmÖnߦD rA(‰baaq—Ší’ }FsDgs¦à3P9±©eLH©X¦¦1‰faažÃ‡²µ¹É­Û·pÞs`ÿ~î=}/ó UYQTjÚ˜{œ™¦žÆdZyˆéÿS1¢ßÝOY–ôûŠ¢Â˜Æ#åá}KK+“W¿¾ ˆñ'S~³ H|~ç’ù›4lH)S¤­RÄ­Uj^8|ä0s³3\ºt‰õÍmBÜ QEwæ,¦5yBîŸÏ7)eвc*þ$ÄÈöΦ5 ˜qçÌtö€Òšª(RúTh©pE p6S¨SãHpóÖm^üÿ#Ž,º¸<øOÿ)½^—¦5‰¼ütD[ðc,­5c±Ö$bk¶:r2G w'§ !"”ÓDãºfaq³¾/Ê";ƒ\8K-aEY!ò‰ù¾S½Ô0"2"£¼«gQàEL1L+·Jz¤Ò*øõï¨1òäOs äýt^Ϥ¡Qü~¡tê‡W)ÝJƒgqÏ"?ñ×o\çê•«lï ð!·<¿j"†ÚU‚<ñ1 ¥¢ì$Aîìì°µ½CÝÔçQ…fÏâ"ûöž ×ëàC`gg›Í-ÚÖ$—SUxRþ_ø¤6Q©:Šu`›4÷%¨G‹’á¸Æ¶6™á3˦ÙB±gqÙÙy”T´¦auu•Õµ5Æ;ãÜ¡$‘È< FRšªSå«„°±A=ÓéTt{=:Ý.²ƒ ‘SsKĮ̀IïúdЄÈ}R ‚KÊ&DÊB¢ ¥‹ÄÜE”ÚôK­Sføþ¿Q„H%§€È¤2ùÈDI–buîvÄLºr¥PÄ(‹’³gÎrâÄInݼÅòê 7®_' I‰`]².JiÊNIU–Ó0Óïfö°ck¸ÅööM;F Å©S'8sæ GennŽªÓÁ[Çp4duuËW®píòUv†Š"ÓͽB ÑZ"­¢Suè=ü0+ßø;¤A.˜?~œªª G L9¶u²ÐÜ€#ÇŽrèÀfæf锉°º³³Ãí[·¹xñ/_z™Ê¢Ìmë竌\¦ÈMšŽÉχŽ#ÒŸžÂI©QiÍ4ÈOçrªBª Be„0x¢Jé4¤2•óZˆÈC¯’õ·Æ·—Wz„¸ÑŸíWÖ:Úº¦m[š¦¡mÛÜ §²_KQuUh´,Pe ¶¤Öh¥wûõ”¢Ðk=ƒÑ›7®³¹¹I‘­-¼st;]ê¶N¥eÅÖæMÓ0 i›†zœªbgÎ>ÈáÇðÞ±µµÍ(g!x ]2;7C§Ûeks‹ë×®±¾±™*óTO•sãn&«:爜ÙD„”TN"qæÊ!Pv;ì߻ť%Ú¦f0`Geįө˜_˜§*+V××yî›ßäÆ[(%©Ê = ÈÊU§¤ÛéRUUUÒétètºùû=ºÝNþ^‡N·C§¬r{]Ê>bN­ó9MM_‡/Ü=ØbÒ[T%ݪÂ{¿ rïÞ½{ÜëZ€â9¥DœO sÓ ‡oâë´š´rIÒŒ‡]~ŸÈ©XjÙ&Íþ³B`ß¾ýÌÏ/P×-‹ {×5ãñ8ñ š–Õµ5L¦{5uCÛÔ,,ÌsêÔi”’üõמåæÍë D"  Ji .Xz½Nž8ÎìÜãñ˜íí˜\Ð’¶5 i“Š<;$pŽºI“çR%3¢ EO)£!çÏ?ÇÖÖ6e§BË©eB}„èÙ»w/÷œ8ÁÉ“'1Æråò\ÏÒñù´ÅÔ&@$v;—'Ù̫ΥtŠ"Sç2Ëh’säÀÉ‹´çÉð)Rw§# g…d‰4Iíu †ô4—LÕ/·ë{îêŸpú†")Æ·4iLàPcZ†ã:Á¢õ˜q]SÇŒÇ5u=f4c[Kc mÓÒÔ5EQ°¸´‡¦iyöÙgÙØØ`vv&AÔnâ¦|ž P²¶r•Ë/_â샢ufHb²Ó!$JYð!¥TÈï!×^£4²ÍeƉsþ®þú‰˜ 8Èžj¬ÜÕèi঩[ÓZL“„;á4ÆÜ•j¶Ó`Û:áæ!0ÛëaãÒ…¯sõÚ5öíÛÇÖÖvn¨Ì…™˜p‚²¨¨:ÃሯüÙŸqî‘Gišk,R+´”¡È³!r ¸;,*Ý„R¦Ü;xbð¼ðü ¸àYÚ³ÄúúuÝ2'£ Ó­˜›™E%×®ß`\¹ÿìƒÌ-̳5H”nï»+›°†bƸkR •ZÊ@!e²¬­J)å¤ð”ê©iÔ»tí"Ë~ך$%‹"ÙïJ¬ßAœ;´B‰Ø“¸KÝ–yà’Hu(ɤè!§§áUó5âDøë<­iSS§I9¿1é”·­I?³fªõ¸NéŽsܾs›óÏgii‰f\ça mö{d¬!Ð4 e›˜Ç·o/£õs½ç8£Ñ¢(.ß8&£cò”ˆ Ó)XŽjʲ`ùö27nÜàÈÑ#ŒFCêq‹÷6ßEŒ\Šez=ʲäÂKèöúÌÍÍÓítØ©s\×¹Š˜…–f ¦ÁVSH”mÉÉÎ`’.Šê‰¹¹t @ÝåþSJ˜ä6¡*Ä\Q>8Ïëe‡ä3²ï!î ýn0†0…aóf'o®’móI7m±†ÖZkr Í?o’ÉoLÛR×ÉBh­©Û†›×¯Ñ4c¬›Ã‡˜`ZŸRœÒ$h6x‡u~Ÿ¼ôÒKôgç0¦¥Ð-eYcÌhaRÞÉ2gÏBдmêáëvxååKx¦°s¹úâB¦Ó§‚  )ΧQ0/_¼È™³âœ’E![Änˆ)`©!&†H"AÈ­‘H5F¨PIiJÓ•:CÂI]v ¦)öDèqW™Cê8JË{VW×Ê}ûöšW)ÀÕ«×´q!f¿ïòø“ -OM4+³m&“¸&… kOëá1çü:ŒM­dmc0Á´ mÓж5¶iiM"I˜ÖR›ôuÓ´Ú!¤àö­ÛI)ZƒTž¶±ÄèrÞ§ÔÊ'Š %­iY]]ek{+Glj¿/¤@ĈÌ€8–S0%Pì v¦%Ü;wî¤n›ºEHHSê mÌnfâŸc.çªÝ{)SzYhE£5Ú$pIk“yŠ ¨´›ô¥àrº‘]õžBŒsJpâ5 ‡ ¨IßZG ÙO)‘Ð&^mî'–'«2ǃ!Äd ­¥1-u“=Ó&µm[¬5´Æ¦“ošüº†º©isñ)úÔQd­e{g‡ªS2ÓŸ?17)œÊ‘ØF†Ã+ŒÇCZk¦Åù@Õ­ÒIƒÌR9Oד½+ãá­T¦¤®G@ ,%ýù9 ©’EñŸï…”"Å;mËÎö[[;J2jj¢³„UY’‚ôHÓ$‰ÄlM}®Dȃ!…Ô4*XÖÈÆd<£¸ËyGvmÊ„NŠ‘ûïIŸ»|X‹iÒœü¦nÒéoMN`ÉÂOD S¹:h|ßC\¿r•åÕï<äèÑ¥Æz—x JࣇÁâü‹ZÂQ¯º>! ÅúÔ~~ôè nܸòß·ª*Μy0Ãä-%ÈÔÂCDÊHpéš&i1çéQ$”R¹”œ@©:Qï Ý µ¤n Š2±µ(R0DĤ.1íȹ ŸÄcj‰!ì„öJ$чÄT)A©Ij’nXŒ“€#ìŽ\ÏÓ=CHæßØ€ÍÑ~2ù†¶MDж©6`²É· tÆ$×'$”Tù" tÞàÔ}÷qèÈ®]»ÆÖÆBi¼OéÑÁǘíÏcBb/kYd‚I F“OGNœ')K>=!R² N’¨ Ò> Åœe4ª¹}û6Þ·y6p`¦7ÃÑãÇèõg1Þ"c¤P%H‰3&©ˆ" ÇöD˜ ‰Õ&Ÿßê —1¥})T覤֓”–¦m)ŠÄÅ>fp"U:ƒO3‹'P"NÎ(3ê£|8çcêJˆšP ¹&žš'&>*„^Äà‰Bå®8í]³6MÀ¶6Yç\zJFÆý›¦NA¡µ%4¸àóø™@°i¢fRCQvйµkœçŸ:}/ýsfgçÖ#¶6¶·5m-+¡sÉ7B~Þ`¼+q OV† ~Nª }šÐRÁš¶¥ÛïpöÁ3ÌÏ/033ø3ÎS×MÛV%عmÛ)JÇ„z©ˆÙw éP^a„DªÙfxšduµÒ”ez¥Vš¢Ðk¨lAkÊDýÎU¿T½ÌÏ_Š  Dfßø°Їl¿% ôx'qΤÂRÓ?6écOùnœNÝž '2§a.Mú0.öÔ†#[k0ãcƸTø±›¡akÒ¼¡àw©h!7e8g)Ê.UÙAĘ;“ZvFCnÜZÆÇÄÔ8eá@Äz‹÷f ŒLžä3½æü¯ˆ“A€w³ Q‚Š‘²ì eE©o8ªÇDX¢wã Áâ#ª@]9S]j›úOdÿ¯÷|Uh= Ñì$÷&¥PjF)=???÷ÔÆÚÚ‡{óspÆ<à›!ë¶IVFg‚©*!kÑ#°˜NބϨ ”ÊG¤ÕJ€ QdN$ˆ˜›G$Ö¦B’j-­l¦TZêDgÏ]MM]Rej3)ÅV¢'§èDÒ¾˜ç#>ˆlþÓcŸeùj0¡p窔OU´T)Ÿ™¢<‰(Qø\$ ΧB„õI .?ì14kÚ3Iõ²ÐÛÖÒf(ŸëÝ‚â¥àãÿìcø "fqañxS×ÿ¶óîS;;Û§œõ2“»”Ã.Ö.Ú%´`¦šo¥竪ó9ïìÿc\6­!ĉ|ÕG Æ;ñ¹Ãçú@êþÌC¦mÁ÷Gîo›zÁy'Cp !ÍvQHR'²HQ¸(¸cü­àï !6móRÈ¿£þ¿ö¾5V’ã:ï;§ªº{fîcß»Ü]Q|ˆ¤,R¢,‰2e:Ù#"’ ;l†dH2(ŽóÃH„ÀHâ$@ž°õ#FHJ"Àq[õE‹¤ ‰²¸KŠË]rwïÝÝ{g¦»çäGUÏíûØ¥$Ä ’ÝÝÓÓÓ]Ý竪S§ÎùшødО 0›Ö"Ä>‡³…¬ä¸*tÞÃù€*t¡F×y8W£îXF&ßÖÜ’/aÎ%@BÒ<ÍMI šöÒà,"ÿ^Š7n™Y\2Öþ†©êß8`Ý—¯\zO;›½C“SŲBtie%zïÏ5uõý·Ù|öÇ ¹’|@ÙçZg¶„¿XJé­™åxf-Kâ,žÕ§&£1D"| 7ÕuýÈ|sz?q¼‹‰öS1-GÅ+ú?é÷‘è‚öš8)H±©ÐߊJ¿Å”þ¦%ûq5R§ÐiŽŠððlÁ6ÁÄ#¬÷hMk¡7¡wM]öƒÏC5…\‹±žÑÏ6²AMbVìs0+Ú]±PŽ2!É-ž)¸ø§¡pY~Uä ‚hBˆr·E|^ðé CÞ'ø¢f#‘/©VÌ\UÞ$ª§t1Ôh™±h Qø._¤rÓÌM¸¼´Œõõõ2¢èiqí¯·°Vl[„Ta'8°øM´v=ËÀ§ýÔÂqWŠu”·”Ê^+gä…!],•ðOñ+†ù°)E€ 1|vQú<XãR•§ÒΣíZŒüuÊÑB*QJ*™B»G¢R6ß×1ÎÔrù}^ÉCÄ ¤˜R,ëÖ eºŠ"&Å-å•·XrþªH!ŽÊŠ[ ©hùYKï|(ž?!EøÐ"ÄnKQ,&M¨~ª§xÐwtÓ{~ú»ÕÂ÷8gв·>Ø-ôØ ‚Ý=Èâl¿z[¼ö¦Ù-e:f—°ÇUä·Éh~ßÐB^âö)d_‚ÒòSŒGô]‹5–>A^@+yŠR¶§HÏê¦Z^¤qÜmH¢g²-pHd@…±)'ZL”g* Iª1[½˜ïÁGt‹`Òì“R’ˆ>æp«” ¤¨Oá‹¡h›€±kçyÃv·Mh„mBþo«'Øööÿï‚…0ûk @€âs`°ðÈíï¥õÃÌ¢®ø»LôóÄt[)g*å„”`|@´1UGk[XWmõ¨¡÷Ö†¬û0Á“}6ÜiZ4g,5Ù}-3ºÒÆ.H ³$yQ4F†Q…º*OùT š@š§–’­VÈ’;¼ˆ2Ñè|‡X¦‚¾ëàc(þìy« À/f³hY cYD @å…îê^Ý8€2‹ÙT»ŽañßݘØë;ÁTR¶’殿?okú,šM´„!üôƺ?ô1’HDJœ9B€5Ñ{tœSϤ2¤†º_:oÑÔuz%ªBÕ¬Ù×!eY‚‚M~¡F¹xyñÚnˆ~?Åb'ç›É†`P\”TÀ Äò(\¼l”ÊÜ»wò>e€læ-®aÅ$x#Tä÷AômrÁ8U ú¶'È6/^Ý€ìj±È¾ ÙÆç㽇h‰÷/0s|€HB”¸ˆü ! C›z«E™  ‹ir1Â+€$Z–w$2Ø–yz)…Ðáú‚3æ"R¡|õ1ÂÆ€ÎõS鄸5¥îB@í}V–IÁ&B¤R^dl‰PaI0$»ãb”ï‰dcrBBÉ'’ÉŠ·jkÉD†0Š–/Ø{²‰·Wû¥á”‚R ³ù`?vo“,eŠª,\NŠÖû_G¥ïf‘ǸÖ{@ |È®æUe0™L0ïæ0Ö"TuUá ox=ªº.:Lž³ÉÎgΜÁ¨¡®j$MXYZA×äs»«  ¼ÄL=/Aq ãÞI6Í®¬.e"+âì²ñf+¡vÿÌòAcìÓƒíQ5I¦ã­27‘÷œ¯ªlJwÎ!„qÑ2AF¦·ñ™<Âæ„“’Æeƒ”!=±1ÏïѤ§“HcX H™Z µ`˜ˆÅ”—WS|ÛåoÞ.¦.½å/z™Ð$Õ IÛÖUû¸¹#GãÎÛoÇÊÊÊBzñÅ—ŠNÑAR™ÏàÅ—^ˆ1pû›„³õh„¶m±ouï{ï{ðå¯|¾Øä`eeýø¼3ËÈææf:˜1›Nñþ÷¿LŒßùçÿ¬„³eV”С2}ÝŠÂésµ¸ë®;‹Áˆ±¶¶†?{êxáùçQ7ÍÎÀ™oƒø3Læ±$ ©ôB6DoM@0Þ{T¾F¬3HBסó ‚÷[N&ZhŒ%b9F4“WõàSHôí=z€ø¢¨DœB&hqÍVkÀIÀ}FÎD… Ðò0mçs+ ý‚OþîK(x×ûäí¦!|¬ïÆ 9Ö­®*ÜÿæûqâøqÅ<]ʯ»m!0fÆ=wß _Ò·c0Š·l^ ÛÜØÀòò2Ž9‚³gÏæçPE»ÈB¾½ôáë}–ïàÜ€7;†×ßuW9sØÿ_­äá£݉Çqøð!<óÌ3xú™gà»vp/‚üGcIDATªsögÚ.Õ)F$ÃHÖ!IÌÊtt)»é‡”Ãì:0 A4䌤N @™ˆÚX“W3©FûÙœl ô{»ð¾÷þµKŸüŸZ#èQC(l `Trh•æ`D6fáT‘Ç=*S˜€DÊ4yÌH>‚z§g(ˆQ!ªkÆšgw$¥3¢r4ÏyŒ‘²f­ÖLoN";3/B–ÚÎǶy´hÛ9ºy[|:¤’J­wçü£žF¶jj<ôÀ}xíkN@Ň~»ð¯&¨B½Öù×*{Ýk§pwÎ ^­~;A’{ŸÇÇñãÇqêôi|ññÇÑÎṲ̂úa¶æç%È$¥€d Ns‰£)½A*Î6ÙÄn[ªy‰Ÿ@1ÁÚ¬Ô<\¬ g†6ßzïÏ=ö °RŠ_OIèãלµ0V‘Rîvc*¾ÿÅÇŒ9¯¡G- æ9È3Gùd}ÀÇâê6g3$IGEEUpòä <ôàƒh𦤋Ùû…ÿE—½îõj÷þ¾¶Ma`è½­o½å;v _|üK8uúySk‰þ±ÿ¦Æ1Ñ$Ø>s¨uy±­ëëª0”„ÎH`Ï0®ÊàÐÇræ\ù!—t?_íë¸ >¤ÏJŠ¿*)mv[âKR§ìDC0ûíò;ßÔ$Z“—³¥õsq´)¾Í(Ö/Q$MH!G·m¦D·|—I&Ö×.auuù‹?þÐ[>wóÍ'Ѷí‚t¢/½#Ê«)V{)ƒWû-<†;_üµ„5ú=cÌ"¢ñxÌD„cÇŽ!ÆÈ\rôS¶¾äñÏËW@J‰G£QN_Hú)cyÁ2ޤ”pâÄ r®N&ŒF#Î zú›õõõì£ÃŒÑh„étÊ"‚‡~˜ûôöå¾ ä)œ-n[1ÆÞ×AœsÌÌÒ³¬õ$¢…=âСCǨë<2ŸÏ%¥¤·ÜrËã³éôsßúöw~fyy 12˜ã‚Ú&I€÷ÝÜ#¹&‚wÀ–5’ Ÿ€!Â, æíü’1ÿy wt_\^ž¼ç}¿ð·Þzë»sâ…Bú°@µ¢_üsŒšdÞß+W°¹¹‰Ùæ.¬×~í×>øØh4jTuT^°%"ÃÌL [*¨|gdG#ÀªJ6’ª"âÁôЍ„Ç”î^DD‰)¥ÄÌ""j­•üh fî÷eðìÀ”/Ð÷õF2)‹™œÅ‰Š&ß¿+ìØŠˆ¨1FhJ G I2Ê€¤ŒD‘DD’RJD4{å•WÌï~âÐÎçãñxgªÊ¡P7 Æ£ &ãÑÂ&U9€KÀiŽß2ƾBÆÿüüçÿÕÓO?õ¡!=m…üœ¡^¾rå¯8örÕ–÷lï#Ø»ˆ%$2-lô$&´m‹KWÖõç~ögÿ“÷ÝÛf³Ù>"²ªj™Ù‘!"[„m™¹ßg†r,ÓÎ浪=h@½÷êÖsh[•ˆ´œ¦åøp¸ÿmQŠ IÏÆ”ïG"BDÔï/nW>YÐsõA6•¥´@T5öÂfæ˜RŠåœ ˆH¯ª±ªª ?ùÈ#ÿå3Ÿýì{cȦ]#9\ž@ÙïЖ0¶4«ÈΦÙ;ˆk!I÷ì³ßùMì(Wã ¬TõÔ/üâ_ÿ Ûê±qSÃðV™­z²¢²ê¦ ÙA4ÆÌJuöìK¸ãö۞ݿ_ûâ‹gÞÀc*Uµ"b™Ù•:˜ÁÖˆˆafSZ"0šC[¹lÂ)õÝ&Ç^a(p=z i>eq›w+䪺A[×WR@'¥µ 3'"êA‰(pÄÁ' Á«êÍ|duc:’™VÇMb^°zö|6Z–‡µDžDQ¤àqêÔ)ï7yä'þ+MD¤VUÀ‰ˆQU[îg‹€Ÿ^ðý¶´:.÷PøCu¾ ãÔ8zìËð˶k ‡Æ³Žòw\[ û^H™YˆH „ˆ``æ„=@ cæNDæ_øÓ?}÷t:-¯¬ÂW5jØB½›€¶È®¨ñÄo›Ng´º²  §ïíÐ3¤ ×)€ ³vÖ}ãëOüUdùVÈCS,Ûm¨°sùòe7›ÍVªªzÜó.olü½étÊK“ ¸ŸR‰Â˜ÂJa,TçÎÃææ†>öØ»/™›Ïž=³â½ß ,\'"€íÒúSöXàrœz } ô¾«^ìÿï(? hs®z""fî×(eFE‰m•$‹ïƒûåñI•|ˆG'KK+o}ÛÛ.éË_Ú7NQ×ûsDQ%K°ÇÓy‹àCdÂGTõI"Ú‡,øme;ØÚù|nCUa¥ªªÏVÎñæÆôo­¯_MÆ#4ãÑ‚*ž‰ÐnNñÒ™³°Îèc½ûâñãÇýl>oˆé¦ž?½|ùÒ• Ð$šÞ´lí…]¬c„Ò÷B/Çu‡æÝ_hqlqÂvÐ`çþÁ]U É`kÒ²%XdŒY¥ÿKù½¿„+²> Ì<"ú^B9“0ªˆT¢¸i<O*çä𡃛ï|äéñÇ?ðòËçéСƒ%C Jn£ˆÙ¼Ã|6ˆÖWV–?’BøERúÂe&%Cô[`×××1¤A¬*÷'÷Üó†c›=÷Üsûϯ­±j¦6Í)Tî¸ãŽö?ñðË“ñX/­]2‰T›ºâ#‡Œ¦Óù¡óÖ/¤æ½Xºy#"T¾“–¨ÕA·¯e_%—~¿¼¦”z0!¥$ƒóQ0 @r­Þ#Ïúq/ÜÒºÉÓoûYìð Žqfq YX µ:õÂ1Fˆ(–ý@GlÇ“Ð0Ÿ·IDdÿþ}ë>úS›_òëÇ^:w®¶Ü;‚ä{Kãåtï½÷žmF£ñío>óÅK—.pU2ƒXìŸ?^Æã±„B]׸÷¾ûÞ~øðá'Oœøêí·ß¶|þÂù£—/]Þ×ú®ªLNœ¸éòÑcG7bRwéÒeU1p×uä;o–W–y}}}åÜK/ó>L‰àz¥/¥Ôkø½–ÏEf;…/)%|×c¯e/æÚ{l{Áÿ°CG_—þ½Ðέµ–M.dŒá~Ë̽MƒŒ1<ì°¥¤^ ")¶Š`Œ©šÑèàd<³‚Ôu#1V)‰¦ñ¨™¾õ-o¹pqmmùÂù‹ûc ¶ªëöÐçOœ<ñâd<Ùð>Ü?ÝØüþs§NýÉϵK ܥ殭­Åµµµ@n»í¶Ã¯}í-¯!´1$¡pèàÁõÇaMR%IÕúúºSQNª¬¢&xÏm;§ù¼%=F­GãñÙ³ßû~Û¶™]ÑôFŸAÓ©¶æÖC§=¶Àn\Møý³ï6ôæùØ *^LMpŒ‘‹QÈ–smé5˜ˆúñ‚ϸuñ,xUÕ~vœsÕ¾ýoN¢]qV9'UUi=j’ïñ>$ïqÖÅ¥¥¥õƒ|ǰéØp2Æ(’!U•£7¾éÞŸzæ©§766^ºÊ³o³ÈàÆÁƒò¯ÿ±×:g“÷~ "#’,4ÏßK’’«ˆfË™÷žgó9Ígsê|K¾ó´¼4±+«ûëÙìÌÉsJ;¸ÂÖ§n|Oƒº^íwÙq­ 'hp¼oõf+¿-lªJ1ÆÅc¶ƒjø¼@åêú6ﻹJÚ윕ÊUZÕ•„RŠICŒSJuUE‚t‹ÆÚXYœ³ÑUµW :ë¾Õ}ö'~ÇÝŸ<}úÅÁ;ØÖ؇=@ÿ‰ØjÒ4Í‘Ûo¿ý@Šrª¶(qœT-D,¤Pƒ‚Hý P€RJ¤"¤,€bab=r䈙ϦÕåË—¾Wî¹3d(ø~^œvlwóƒï2Øn›ö îq­²SøÃ^ ¶=lÙºÁ±¡‘k¸ßaXc»Ã0ÏCˆ›yÙ…4qI*™7JJNSLIœŠŠ$QIˆš ˆ<"‰É“ÞsïüÜÁÉÅ‹/ãNúîà¾ûïß·¼´2÷Ý|.† A*lJÉÀD8û#QÎO—„BJäRfMª¨lR"NI«ÊÒñ'iÞ¶â»ö4€hØš‡ ð;öûß[ èÞ ;ü‡({ÙJ[Bí°sëvì÷ÖNÂö¯Ô‹î˜L&ß7L ÃJÆhÎuÄBÌpÖ¨5VsR¹J]e“sN¬©’s&Uu«Ê¥ªªBS7¾©ê4Z:€·=üðÁÏ~úÓçÏ´k9xØJƒ!à¾û º©Î;˪š[7söAVÀdÊR°Bˆ2möˆóvL³ù õlg Œ³ì¬Ã¬ ±á×Ýy§<û­oÍb gK]dG%uP·ÂÛ¿£¾{µô½º»áÁî±ím(4Ø𷇽ÇPðC¼fßþýÀ)ç\ªœ#W9­ªšš¦Öºjd4a2£uei £ÉDšºJÆZ6É9§ÖXiš:Vu-uݤñ¨IM3¦‡ßþðø³Ÿþt/Ó={€¾"2¨8ØÜqûë3Ÿ“¬4.äEÙ;ÈraÙÌkDd2{%”}ë1ŸÏ±1òlº)ÓٳٳéÕ¼F;›¡ªks÷½÷ºo>ýô4¿†Ý]c€aýöú¾çø¶Ç÷¥ ¯wl{·Ø>\ìü»•Ürm:xäèQ$‘ç­1©jjÔ¶BUÒÊ4£Æ£1&“%L&#™L&X]Ý'KKTU c:Ã6¨¬sUjšFŒupÖJ]׸ãÎ;ùæ[n±/œ>½·!HË¢ÈvjVUyË[ßʇµ³ùÌX†aWUÙC¨ØN¬±ÌÖŠaæœ:ŽA é|ÀææÓÍMÞÜÜ”é›W.óææ›››25˜M[®]…ûxpò?{òœïÚÙ/éZù‹øzo`·emgݯõ,b[¹éÄÉI þ•Š+©F#ÔUÎíÓ4#4£ãñËK˲¼4Áòò /­®`uuE–—–Ø™JÀyµª+±Öª$%W;å’Ö§®*ŒÆc¹ÿ¾ûøùS§v½Ÿ«¤Ë€8tð/M& ˆsNrLbg,Œ3¨œ³åLXhÅ01³c>dGFfÓ'D`M™m¸Äˆˆr’(ð<¸úå/}q†ÜÅ¿€«»ªkøn+ðƒ­]°wþ(…­ƒÄpµŸ_ pWû]T¯½õöeßvsÃfZÕ•ÔU…QÓ ©ŒÆ Fã%^žLd²4ÁÒò –VV°ou«ËËXZ^-I¹röV2™˜ÊG‚# Wg—¶_ÿõ¿±ç;½Vî`üÒ/ýr$èFÝ4â¬c ›)ÌûtlƸ»g3…¹µ–‰Hr¼Z^:† >䧘$gãN’Éžcb©j<òΟ\9söìÚ+¯¼,—.]óÍŽÇø°4YÂh2ˆbiy Œu/--(j$f_Åsç^Bð{Gí,ŽÅþ¼G;oÑ45:ŸySÈ)\™&kíÂÅœG g’¸fqUýû÷óV:ïÀº«2ïOS9®ë‘4£ZšzÄãf„ÑxŒ¥ÉãÉË++¼²²"ËË«¼´¼œYH ’  rv.cH˜h!¦ì«q`ÿ¾=ësM,/-I”8µD’ó¬åžü¨¤„ëÓÄå<½†‰óø:`ÔÔð> r7£Z¼Á{ÏUUIðÎejµ.„6ñ‰›NŒŸ<ÙN¯\–˜§žû.¦ÓMœ|Í-8zôb ¨*‹µKWX ¡qÙù3„€*'T ³–@UU¸õÖÛÐv-ξtu 8rû÷ïŠófŒ ÖæÔ³L!/„‰‚!LÈïääÉ“34E‰"pÆb:ÝÀÚÅ‹€#ÇnÂòÊ2 @=±ªŒ»¶ÙèÓá:çØºJòûp¨ê^h¸©kF˜ŒÕزpÉâÂeyIJÈêj,lq¬Ñ=ÁyMˆŠ·ÆŠ@$§‹-Ý9• ÝÆdË’˜¹O“J XTU vUãPušª‚o*´]…ª®à}…ºj2©”7Ì»93³5®ŠD"0ÀîycR(gâM<ŸÍ9•¸Àœ™CþbuTD2ñs¡Ž‹9·à­·Þï=NŸúÞâY÷í?€ƒGæçŽÅ˜X¨póÿ) ƒo3"hNŒÉ ¨œqb,aÿÁƒX]]…©ê옃59Ï1$¯š¼)‰ Œ±pU[]WU…¦nÐÔ5ªªF=Ê‹oM3*Ç›E¾æLCd‡€Þs›aMö 4Öf"i–=ÇÁ=“Gß(×OùA”­åÿãr×y¹€ë¼ÜÀu^nà:/7p—¸ÎË \çå®ór×y¹€ë¼ÜÀu^nà:/7p—ÿXGFȾ}IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_hd.png000077500000000000000000000454151217176075400240240ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½w|\Õ™øý=·ÍÌÑhÔmK–ä^p¯`Š1%1›¾ ï† %$„,YBH6Ȧ‘I€@(S K Ø€ÁØ`Ü0–p‘å"ɲ¥™‘¦Ýöþqï\lÉ–m³Ÿß>0kî=sϹçyÎó<çiG8ŽÃÿÁÿ» ïü_ø?ø”ÁxÈ•ÿúUEùø´éÓï®^S&„d ႼˆBøí ¯9Žƒ,Ë躎$IÞ=‡c•LùîÛ!NcÙ6’ÔCï"ßÈ'%?@\²,ôl'߯û÷ {Þ_ù[þX ¾;¶ƒ@’ÄAíÜ¿ý/¢µ¥U[õÖ[÷tuu]Uøyøõï~ÛÿD…lÛ¢º¦îÒQcFך¦Ȳâݳ9PÏÈ¿œã8hš†¢¨ìÞÓ‚iYhªŠª©(Šê"LˆÔäÿö¯ oÒDÁä¹Då8¶m£( C†Vcš9‰™L!BHh²,a¹\$‰p8L8&›Ë‘N§{¯EQü¬(È’„ãØÈ’ì~—e$Iøãtûs¿KBøD¾sG3‰dò "SUÕ¿ã8Ô¨§£cÿ¿½óÎÛÉ’´l0p–‡A!„$"‘H½$ I–س§…½ûö3¢¾žâ¢¦eö4÷Ð'ÉŽ?ûÙÏxeù22é4’·êdIî™xÑ«³‚èë;þª¶-›`(Ä´iÓX¸ðcÌ;éD†””L$hooçþßþ!g-ú8cF&‰ +*[¶nåµ×^cõêÕtuuõâ’$PUUQUÓ@2™D’%YF–Ÿ0%ÉC~±ærY&MšÄ×ÿíß(ŽÅؽ{BH>Glü` ]Ý)ÆC  aÛ6EEQ¡Èêd„X&zOÈ1Á @( é!½N8IHÈ’Ì<ÀsŽ¡C‡òݿ˴iÓÈf³½~§‡Ã¼ðâ‹<ñÔ“Ø–5Cévíl晿-e̘±\ü™KøÔùç¡i/½ô"Œ3šÓæÏçµ×WðÐÃóÚ«ËIuwhãxñÅyþùç¹ãöÛ™:u;šw`ärär9~ôÃÒøA#ÆOà–ú:t]GQ”Çvzq¤c…A!˲b!]¯@€¬ÈÌš=‹5ﮡ²¢‚ŠŠrlÛ*…º®ÓÚÖÊ}÷Ýû¡"¿øá­·ðĒǹúškx쯹Ò_þóæïóØ_%—Ëò}MýѪ+ï½÷~úÓ\sõÕ|å+_¡»;EgGóçÏ'žˆ3dèJJK±l‡p$‚¢(u¦i*ˆÁ°\óoœ´àôÓ_---•-™ªª’N§]9)ËX>’B!t&í·ÞÊK/½tÌý hšÆì9s())åÝw×°³¹ù 6Š,sò‚…L›w*¨ –i)Š ±l Û²±Ãq•MDZ±m Ûr°ÛýØŽmcš’$h¬Yño½ø¦aø}vêi|ÿ–ïSW[ÇþýûˆÇã„B!À]0¦iò÷gŸ{£««ëTI’z­˜ŸýòG=ƒÂE©Óu]†ϲ,‚Á ¯å¯E‰Çü×ÿë¸! —Ëñúk¯õy/r湟äì‹/aÌÔ™-Hδ°l›œib˜¶ã`Z–ecÛ&¶mcY¶icÙ.!¸÷,LÓ$Ð(×d6lØÀ'¾ø5FM›É³ü-ûZ÷°üÕå\ôéOóÍë¯ç‚O} - ™H®bª( áH¸.Ù• !è¬y$ T«ª*Bˆ^ S!wÑ4¢¢"6mÚÄm·ý„·ßy{0ºT¨®©áü‹/åã|šêÑcÉét#Ç´,ÛÆ´mLÛñžG²O¶í_Ëÿk˜&š€n[°?™@Íd=}6Ÿ¿¹ž¿ßw7ßt ±}ß>n¸áV¼þ:ßüæ7©ªª¢³³ÓßÍ„Ãá•’þ¹ Wd¥P÷墪ª„ÃaÒé>ú(wß}-­-ƒÑí Á “§pÙÿÂç]@¨¬‚t6Kww Ó²pì¼àèE¥$$Ý)vw%É™6’*aæ ÂÅ%|êëߤnÂ$þñȟɤ\Åóé¥KY»nß¼ö:Î8ó º»»BÖÃ:0B±uP^œÁâº^/+ –eáŠ"£ëa¼ôÒ‹<ôÐì~ûmlû£Qø§œz*Ÿþ—9ÿ“‹YýöÛ¬{{c'OC-*Q×pí c'`†a`¶3Î<›!#FóüŸïfgãfššš¸ö›×qÙ¥—òÕ¯~]×Ýmª,× éŸhpõUWN˜4¹NQdlÛ"‰ ¨*ïoÚÄË/¿ÌòW_eÓ¦MJà?D"xàAÒÅ•ìioÃRÄÓYÚ÷ïgHQ Ër°òÖ¾A!À¶Á¶Œ‚‘À±-²©µõ\xÍwyãé¿òö ÏaY&†aðçàÔSOeÞ¼y„#aUî>opˆà˜ @’e]ëÕB4M£µµ•»îú5/¼ø™Lf0Æø¡€¢(D£Ehš‚‹ad2Ô­bx}=BV°l›d*ÅÞxÉLÓ±Ù<Ýä ÁÈf‘…Ó.ºœêÑãyù‘ûèÜÛ†mÛìܹUUÝÅ¥(µ–eýó€¢(Õº®‡=ô0Kÿ¶ô¿ …Bèº~¬]d2º Œ;Žã°ß>rF éL–ì¾ýtY kVÑÑ!˜1}c'N„`­ñ.vïë$™Íy¢îÿÁ1‚˲ÈårÔœ0•O]ý]^{ì׬¢yçNÀ!Š¢Œ°lK×ÙrÌpì +õº!a&;šw²}yy9555}:Y>L°m›––ZZZp‡D"ÁôéÓ1 Ûq\ÐK\Q&œp_tgœu6&OÁ ê´%SìÞ×A2•Á²]Î0Øp‡H0HIHcŸcpîW¿Á_ñš¶m#›Ë¡jº®7²¹$I©AèrP8@®‡$A"‘`÷îÝý¶•$‰¢¢"dYƶícíúˆ ïä‘eÓ4q‡d2yÈߘ¦ÉúµkY¿v-ÿ}ÇíŒ7Žù§Œ-ZÄ 3f¡ «¤½+Íîöý$º»±QF˜–Eý°!e‡ÍM襕THóƷɤÓhšF$)ïìè(Büs@0®©*²,‘J¥hkkë·mÞ½z<¢4H«ž|òÉ„ÃaB¡ïK$$“IÖ­[G<\Ò°i ›6q÷¯EýÈQÌ›¿€Ó>v&SfÏE©,gËîÚ=ãÍÑ€"Ë|°s7Á€ŠáZö졤²Š­¯uï줺¦†p$¬;0!öó¤0 ëz¢ªÈ²BGGÇ!WUÞ¢u¼à@ÅiĈ,Y²„%Kž`Æ œuÖ"N>ùd$IÂ0 vìØÁ?þñž{î9–/_Ngg§ÿÛí[·°}ëþò§?P^UÅE—]ÎÙŸûWÚ…8H”Éø²¹ñ2¡XÅ™4Ýé4{÷îeÄÈ‘„ÃaYê$I¬8¦Éðà˜"‚nøÖ·d=®UI’ؽ{7¦iöÛ¾¿‹ |¿¼’$ǹöÚk¸í¶³xñb6oÞŒ,˃AÆŽË×¾ö5–,YªU«¸ë®»8÷Üs)..îõÜöÖVþç©'èî€#…`0@H×ql›P¤[HìØ±EUÑÃ:ª¢ÔIB"ÿ98¦å( ¤‡ô:YV’Äž–C[øò„r¼à@ˆD"TVVríµ×òÌ3ϰxñbÆŽKcc#[>ØÂÎ];Éår”””0|øp.¸à>÷¹ÏÑØØÈK/½Ä‹/¾Èo¼A<G‡² Žqˆ lŒ~²¢ŒDÙ¶m›)BQÔêÅÙÑÂ1€,)åzX/‘$%‰–ÿPÅÅÅÈ²Ì 7ÜÀ 7ÜÀ;ï¼Ã÷o¹…––VJKË@:::0r9FŒ¨gÅŠ7ˆF‹8÷Üsùò—¿Ìg>ó¶oßÎç?ÿùî6˜úƒ¢ièÅ%ìhj¶¬¼-`Ô`¹…T¥N×õ¸ÞµÃ€ªª¾LŸö@ ß_a¿…ÖÉ?ÿùÏlnhä„IS˜p‚ãjô¶Ã®];1bg-ú8Š,qÿ}÷ñÓ;ïä«W~P0DMM åeet§Óƒ>fÇqPThyÛ·o#N£ë:ª¦Ö›–’8fKÛ1€"Kõa]²,“H$iooï·mÞS˜Ë压à8ZÐò»‘ 6оo_ûÚWéêNÇYºôo,{åe:;;¹à‚ ˜;{&ïmÜH0 cÿ~–>½”K/½Ô88¸áaÕÇ!V^Aó–Mìß¿Ÿ!C†‰D†¤Ói]ˆãL²ª ê:A&›9,är9âñøqŽã`F¯-è'>ñ Àu¼,þäbÂáZ @&æ/Ü϶mÛhlØÌˆºZ¶nÙB¼³“TwŠæ¦d³YOV÷'{úBB–…oÿpÛž lÛ"Z^AG4÷pl›¢’22Ù»vïb^à‘ˆæØÎHX{¬srL ‡õzE–Qe™¶Ö¶ƒ‚>„œôx¼áw¿ûÿú¯ÿê?aâD±Zö „Ä’%K‚üËç>O[['N`å[oqÚüù$:;)//gþ‚~€ä‰µB#„ ›ÉÐÖÖÊ–†F$Y&—Ë¡ÇãØ¶Mee%‡ó'8ŽC(EVUv45í Ge¹~08éQ?á–›¿ÒÃá:EQ’Dkkëq±ð „B!î¼óNÆŽË«¯¾êû‚Á £GÂ0 LËbÜ„‰¨ªÊ¾övâ¼÷Þ{L›1“ÅŸ\Ìô38ûÜs¨ªªòW?¸+µ²´„h$âÇ ¦i‘Ig¨©«£®¾žº#Ðõ0FÎÝ.æ/I’,»Iv÷ø²„$Ih¡¡X)¡`Msm²¢ u w6ÉQÀQsDZ‹t]ª( ’,³§eP,“hšÆÝwßÍg?ûY¶nÝÊš5kÈårTWW3räH&ŒOEE¥%1&N˜@:¦³³D"aÚÚ÷+)Á¶m׉ä­þ@0È›o¾Éîü1gúÆÔÕÒ²o?q‚¡š 3î>Dz,„$Q‹‚p¤Y–èŠwâX¶,’ËaZ&¹lŽ\.K&•¦;™¤¥µ!„s¡Œ´-ëXñô Ëòp]×CyÖ×úOæU@€?þñ\vÙe455ÑØØÈI'ÄÈ‘#I¥Rlܸ‘eË–1b'Lœ€,ˤR)L³'à3—ÍbÛ6¶—f¦i‰D‚}ûöaÛ6÷þêçûlfÏžÍÌ™3ijj¢¡¡7RZZJ]]±XÌ·Ì…B!rtÆ;‰wt²lùr¶lÙâ÷×Õ•ä‰îgéÃa΂…œyÑ¥Œž2“òŠr—Ri¢ÅÅ8–É“¿ÿñm |î¢O3þ‚‘_Û·oç·¿ý-Ë—/ç7¿ù Ñh”@ ÀÔ©S™4iÏ=û,=ü0+ß|“>ø€ööö^‘EÆ ëhܰŽXE%SçÆÛËÿÁšŸýü´··ÓÕÕ‡µPŸndžx9!!-Iâƒ#ÌpÔ ê4Mò,JKËøÉO~ÂÕW_MSSÓ±ŒgP ´´”¿þõ¯,\¸wÞy‡n¸^x¡Ï¶@€/|á \wÝu >Ü5¿* 7näÁäÉ'Ÿ¤««ëq…νm,{ê1ÊËË©¨¬b×®]nì<Žiš=)ë‡YQˆD"à†ˆÓ˜ŽŠn¿í6µ²ªª^ö¶€¦i2oÞ<~èa®¾æjV®\yLƒ:¨­­å©§žbÚ´i¼óÎ;|ë[ßê7é”SNá‡?ü!§và²í-[¶ðÐ_âÁàƒÙ>˜PTTĺuë¸é?nâœsÏåÌ3ÏD×uººº Zé „ùøÀaÇj 8J BzH®È ¶m#¹'Žç/þ…o}û[<þøãÇ4°£ÚÚZ–.]Ê”)SxóÍ7ùÎw¾Ã+¯¼rP»êêj¾ûÝïòÅ/~‘@ €mYlojâ‰'žà¾ûîcýúõê8MÃÀ2-:;;¹ÿ¾{Yñúë\|ñÅL›1\.wAMQTUÅ2- ¯þB$AQÔáÇj{9*pgH(*Rðv47ÓÒÚÆÔ)“ùõ]w1zÔ(î¸óÎ, ù[¶láÆo<ùš¦ñ…/|›nº‰êêj7Ì«¡¼ô>ú(¯­XñX*MÓ"“É y²††nûñ9mÁ|.¼ðBªªªHu§°lE‘Ù»w/[·7QS]MMõ07»:¬#Ëò˲dà¨'Y¾ùæ›øGo¬xcFm]í+++‘$‰lÖàŠ+®à¿ø9¯½ö§Ì;™ /ú4uuu¼öÚkºý̘1<ýôÓLž<pÀ¹sçR]]M2™¤¥¥…“N:‰{ï½—¯ýëD£Q¶lÙÂË/¿ŒeY”WT°æÝwyï½÷ügžtÒIœsÎ9 :”P(„iš½Œ?Ǻ®SR\ìæÚ†Í ¬ZùŠª2jôhBz!ß»ùfnøö·X²d £Gfò”)X¶Í–-[„iš¿;iÞIGMµGÅTU©×u¼)R’%‚¡ àÆß‡‹"twwsñÅSWWÇç?÷ùAµêºÎøñã™:u*'NdáÂ…Lš4É¿/I&L`„ \wÝuìܹ“ªª*Âá0ÍÍͬ\¹’P(ÄÉ'ŸÌ{ï½Ç~ð–-s+¯Ì;—믿žóÏ?ßw[†A:fëÖ­466²yófÖ¯_ÏÚµkÙ¾}ûa} ‚mYd²™s¯Œâ™[[[ùÍ]¿fÅë¯sée—1}Æ Š£Q? ¯¨†Ãz,›IGáè³…ª>À]¿üå-§ž6ÿ¦ŠÊ WðŒAÛ·o§¶¶–¢¢" Ã@Qb±W\~=þØÑŽ‘`0È´iÓ8ýôÓ™={6³fÍ¢ººI’H§Ó¬Y³†îîn***>|8%%%¹œ;::xùå—±m›O<‘ÖÖVn¾ùfþö·¿0{öln¸áÎ;ï¼Ç+d³Y¶oßÎêÕ«Y±bË–-£¡¡Ã8´m¦$cxM ’äVS‘d÷_7ªHBH2¦i ëaÎ:ë,>uÁtuw¡ª*UUU†‚W—/·w45Í¿úÚkûÎs%¹6»{SÜJ[a=ÌÔ)S±,Ó4 h²¢ð‡{îáíիޏ’’N=õTÎ9çÎ8ã FŒqRwíÚEss3‘H„’’²Ù,›7»É•C‡¥¾¾žt:ͳÏ>Ë[o½Å%—\B$á{ßûúÓŸ˜5kßùÎwŽñyŒ7ŽqãÆñÙÏ~Ã0Ø´iÿó?ÿÃsÏ=ÇŠ+úä–e‘ÍdRâ%Yòk#åë$¥S)}äV®\ÉåW\Îé Û²e…°–p51øåÏ!Âáð?>¾èã E9Àè9ƒA2é4?¹í'<õä“ä ƒ]Š¢pòÉ'sÉ%—pÎ9çP[[Ûg;Û¶Ù¶m---èºN0$ …ƒ¨ªJss3ï½÷/¿ü2?ô0‰d‚ &ÐÔÔD<gÖ¬YþŠÏ‡ª‹F}àÖÍq6oÞÌã?Îc=Æ»ï¾ëß‹„ÃTx1‡’$€‚,…Ë,ËB ˜9s&—~ö³Lšt²,³öݵ¬^½ú{W_{ÍŽvÜGÌ„¡p$\'+2B’Š×õ0»wíâß¿…W—/'‰6dª¤¤„‹/¾˜/~ñ‹Ìš5Ë_éùdŽ<äãõ?øàöíÛ‡®ë4MCÓ4Ÿ6oÞÌ=÷ÜÃË/¿ÌöíÛ}Ëݺuë˜1cßùÎw8ÿüó}Ćb×W)¼ñãÇóÝï~—믿ž—_~™»ï¾›¥K—’Ëå°lË‹¶0MI’‘eÓ+1'!+rXA‚7ÞxƒuëÖqó-ßçÔùó EP¥êXÆ}"À‰é!½BQÔƒ^ZélÙ²…›ÿó?Ù¸a‘HÄCfß+«ªªŠ¯~õ«|å+_¡¦¦Æ}º»w ȲL&“áý÷ß'™L‡}ä‡B!Âá0<þøãüþ÷¿§¡¡¡×ïçÌ™Ãõ×_Ïyçç×áû0·¨…s£ª*‹-bÑ¢E¬]»–_ßu/>ÿ¼_CI’$¯Êˆ…aé¦PH’$±oß>¶lÙÂé zÆ y̱Œóht€úpX)Šâ+#à[|ÐØÈ¾ Û¶n%¬ë^ÂåÁ(**âë_ÿ:W]uC‡ú.(™Y–I&“lÚ´ÉÝe„ÃhšF ðÎgžy†{W_}µ—_bΜ9\wÝu|êSŸòÿQû-ò„&IS§NåG?úå¥e¬^½ŠÍ›7cªªz­,ËIJ¼@Ú^D ‘ÍeinnÆ4MŠŠŠPeôï¹Gÿâ—¿|T¹‚G.u!=,»Q+î‹išFËžî¸ývïÞE($“î{ïÉ%—póÍ73nÜ8€^Q5õ%ÜÕ°ÿ~6mÚ„išþÊÏ'z®]»–û￟¥K—’ðòò„œxâ‰\}õÕœþùhšæqOÈ‚iYT©âŒ3ÏdÂĉ¼µr%MMM¾>Çq°L Ó *Ud2é »vîÂ2-BÁEEÑò•+WêÀGC²¢ ë:8®C–erFŽ»ÿ;v67{ `òÇÁ4LFŒÁm·ÝÆE]pP„nŸ}yûâ÷ß!º® ……B´´´ðÔSOñÐC±c‡›’.„`áÂ…\wÝuœqÆ®ùÔ˹ÿg¼^#yœsxÍp*+«Ø¸q«Þz‹îîînPø;Ó°Éå²4íhÂ2ME¦¤¤$¸éý÷«þC²GL†aÔ|øaÖ¾»–P0ØËêç89#ǘ±cøå¯ÍäÉ“lM“e™ææfó²‡Ã¤R)þþ÷¿óÀøšµ‚ÓO?k¯½–E‹‘OýhŽgì¢ð’Góµ†-ÛFUfLŸAuu5Ë^y…ææfòU×Y–ioÛK²»‹Ò²R"‘ˆ&€£Š>bP¹.äåC!yþùçÑ4­—ݶmp`ÒäÉL›>ŠòrLÓtÙà! $·fîÖ-[غm¡Pˆ<Á­X±‚‡~˜W^yÅ—ã .äÚk®áã‹¡ª*¹\ŽL_Y:…Ÿû黯ê߃^[oØF¶mw^L“ÊŠJ>ùÉO²bÅ Ö­[çŠ`û$‰Žx'­­­®™ZQTTTw´Ã9"ƒ_ýò—u`ÀObüû³Ï’êêF–$òÖ²,dYfƼYŒ9EV0û,]]®ÕsáÂ…\sÍ5,òŸÍfI÷ø¼!y„%„À±mlÇMÿÊGá!P<ù[î=Ø`;ª¦ðô˳¤J’À4M´@Ó.$-æõ×_óãý9’$:::hkm\cÔÌY3+ŽvåE˲ذa/¼ð«V­¢³³EQÐuH$â‡}å!ø¥Úu]§¨¨ˆòòrFÅøñã ƒîyƒ@yΙ/–aÛ6· ½$$SòEåô™3Á²e¯øï—Ÿëí^äU8FUÔñ2±ž IDAT¡P(N§Ì+Å€iZu!=¤im­­464¢©*9o•؎Ô©S¨¯¯Ç¶$MFx"ÀÀÆ- Ü'ØPQQA*•â׿þ5>ø ,àšk®áãÿ¸‹øTŠäZ}>5KUU^yå~ûÛß²fÍêêê˜4iªª2tèP.ºè"¦Nês!{öìáÑG¥¹¹™I“&‹ÅH$tttø£óN:‰™3gzµÝx¤* 5Ãkغe BÈI`yçHŸ#ضͬٳ0Œ¯¾ú*š¦ùÐì·G"E†U«Ö—dIÔ麎ªª444H$¼\9˲1bcÇŽÅq@–²ì9‹„ —Í!lÀî{9ŽMeE·þà<øàƒœµhW^y%gžy&`t*EWÛ9Çq‡ÃtÆãÜrË-,Y²„yóæq×]wqòÉ'sÿý÷cÛ6±XŒ×_‘n™ÿH˜'Ÿ|’;v0|øp2™ §žz*¹\Î7¶¤Ói–þío¼³f W\~9ªª“!)¿’§L™Bq´˜÷7¿OwW·k=ó%$eººÈܹ'ÒÖÖFCCƒ¿EljÚeY¨ŠBeeep„ñe@Ç‘Žçˆ`öœ95.;‡ÍÍ>û²,‹ââbN˜4 UÕpp…„$,ˤ´¤Œ’’,«ÿb‹ŽãË\vÙg¹ä’K™;w.š¦‘J¥èJöíîÎGÆ´´¶rå•WòÁpë­·rÁøl{Ú´iþ¤éºN2™tãëMUU9å”S¨ð²†aPVVFQQmmmX–Å”)S¸ûî»ùá~Ä ß¾|0ìÑ€ƒ» „ÄÈQ£(«(çýMï³³y'8 ¨$×I$ ׳Šœ~úBZ[[I&“ ¹yÙL=&RTBŒŽ8Bøˆ`èСõ¡`l6K[[›w€‰0~â¢ÅQw ¹GÁ!:l(S§MCë‡4Ó2™5{–e”%›;4GST…T*Å·¾õ-Z[[ùéOÊ‚ Èd2~u¯ñãÇSVVƆ hnnæ‰'žðw ²,‹ÅˆÅbŒ5Š!C† …üâÌåååìß¿ÇqøÞ÷¾Ç7¾ñ îüéÜxã8Ö¡w4‡˱°¼Òº3gͤ²ª’Íï¿O¼3îê’khCLˤ¢²’“O>™gŸ}Öß ´¶¶æ Gbð쑎cÀ ‡Bʯ~ù«Úp$âåù'Ü‚Y‹ÊÊ*†¯õ·\¶m1~Âxj†wµé<Û<̤Iø˜®ëüùϦ±±‘¯ýëœrÊ)n¬·å³,‹îînV¯^ͺuë˜2e Ó§OgèСhšF{{;›7ofÅŠìܹÓW0ó‡Y[F¦­­òòr®¾új.»ì2N9å,XÐç¶óH!_ꥶ¶–²²26¿¿™;š0 ¡¨€@H`[6“&OaíÚu´´µ‘H$|h¦L™Ry4ý8¦X’åP0¬ ƒØ¶í›W…Œ9’P0ˆªºž­ÚÚZN>õêêëÏìkÛþž{0>y.±råJ¦OŸÎ¼yóÈd2¬^½š‡zˆõë×ã8o¾ù&¯¿þ:—\r —^z)•••lÚ´‰•+Wbš&gœq×]wÙl–¥K—’J¥H$<óÌ3<ùä“´´´ …عs'cÇŽeôèÑ<òÈ#¾0ï’÷SƒA¦MŸÆìÙ³)))Ü, UqKë„ÃafÍž…,Ët§R~QÎ`(HMuõ£!€s€y'TVSSë9òÍ= !Z\ÌÐaücÒdFŸñã’øP#leI¢»»˲;v,ÅÅÅ,_¾œ§žzŠššZ[[Q…ÆÆFFŒÁÔ©S¸÷Þ{¹é¦›H¥R\xá…Üu×]TUU1wî\žzê)öîÝË /¼@[[ÅÅŤÓiÎ8ã ߬\[[˳Ï>K¢³“p8Üg¬ÃÑ †¼Qhذa”––ÒØÐÀÖ-[É9UÛfü8W¤µ´¶ú>p$‚Ð&꺮¥R©#šô‹€pxDQ4ªçý×nu ‹¡C‡‰„Éår 2„±ãÆá8`›ƒèk?`FÇAàžßWQQ®ë¤Óiªªª˜?¾ŸÑkÑh”¦¦&‰Ñh”3f0mÚ4öíÛlj'žèi€––ß7?uêTÚÛÛ±mÛ·2æW|&ã–ÂÉ&:¢¿MÍÑ¿ª§ +ŠÊ “&¹Ž¢÷6ÑÞ¾!ÉÇŠ5j”Kù­`8L0‰DtàÃ!§^…¸¡[@Y’)¯¬@QTB!ÑcÆ`}؇BHt%‰F£L˜0ýû÷ÓÙÙɰaÃ…Btvv¢ª*¶nÝÊ/~ñ >÷¹Ï±`Á^ýu;ÖÕÕÅ3Ï<믾ʂ ˆF£„Ãab±Ùl–p8ŒíY7 Ã`ÕªUny9EÆvlïDÞ`Ù– eåœ4ïD¶nÙ–¶€€ººz^_±‚í^ #MÓ(//M›6- túɽaÀ0dÈÐá€ú(--eÇö&***™šÚá¨cÛ#EaÛ¶m!˜1c«V­b÷îÝÔÖÖ 6l˜_*‹qÑE±råJ~þóŸSQQÁ!Cü*¡»ví"°xñbjkkÉd28ŽÓ«hgg'3gÎäé§ŸæÍ7ßdÔ¨Q¾Y{°ÌÄý=Å6M$IbÜøñTTV²õƒ-TWð3“E¡8ZÒCz-pèríÀ€ `ÆôCóûiI’2tª¦zæÕ"wŸoZ™«Õ¶myä¾ùÍo2nÜ8:;]YII Ðcp1M“ÎÎNÆŽËäɓٿ?ضMII ãÆ#›u“M$~ÔPþ©TŠ1cư{÷n®»î:Æçºr?D§Q!X¸¶–X,ÆŒY3ÉwÜy'­--ì߷ʪ*‘°,ËÒ$Ž0Bx@ ëºøÝo~3Ê« À¨Q£xsŨŠJII Y’ް^Þ0pÂ1Mƒá554mßÎc=Æ9çœãÛö“ɤ_½C–e^yå6nÜHII #FŒ`Μ9Œ9Ò'eË–±qãFb±ÇgæÌ™^.'7n»wïæòË/§©©‰²ÒRf̘AX×]Åð#Œ-0½Ð±‰' …|VYUE0dèС5GúÌr€°¬(õùƒ FCEEŠânO,ë£[ý–m‡Y¼x1·ß~;’$1wî\dY¦¶¶–T*ÅþýûÝóú‚AfÍšE>„½³³Ó/ Ÿ/•D¶m›x<î;ƒ‚Á >ø ?þñéèè ª²’ÚÚZÎøØÇüR15äËÕH’DWW{öìa:Þá&”éóD£FŠ”””TåÍÀà®8iÊdÙ=@Ùluø0Éd9묳ysåJ~õ«_ÑÔÔÄI'ä‹X,†‚Ù³gÓÒÒâ›zÁM±Ês€Ñ£GÓÝÝíËý²²2’É$ÿûßyôÑGyë­·Ô¹¹ø3ŸaÒ¤Éd2Gìw9*8PÉt€„gÎhnv“ ¹žÎ‘º®K©TjÀ”9 =jôЊòŠàÑ)3gΠ}ß>oˆ-X¶…¢(\ýõd2{ì1Ö¯_Ïܹs©¬¬DÓ4‚Á Ñh”ââbŠ‹‹ý0,I’|n•N§}=¡¡¡Õ«W³fÍvîÜéïÉóE¥/¾øb®¸â ²F¶¯æ‡ ²,Ó¼³Ù·˜6{Gô„u€˜$„(æœB"Y–Çèá°v`ŒÚ¡CA ÃPù×£"‘Cˆ•\.G$áæ›oæ÷ÜÃ’'ž`ûöíTWWSWWGII‰n±$¹6¦iºac™ ™L†®®.âñ¸¿•ÌŸÒY]]í}kÛÇb\~ùå\pÁÞi¡Çï}:sfÏÁ4M²¹,¦Ñ;IH®O! úɧ¦i’ú€8e™D2Á<Ðëz2™d×®]Œ?UQ?n|ìHž{XºÔhA”y°,‹‡þò~öÓÿ¦»»›Å矃ƒsœ4äBpp°M7ò'CƨTÔ¾_ùˆXüq=â¾ûïgõêÕ½®¦éVTMeذaÃC¡”N§„„ÃÀäÉ“‹KKKôÓ•6¬_Ïmÿõc–/[†$I”——»E„Àú'a™…à8ƒí¶9B9 ¶oÛÆÏþó>ïçDC¡zXŸ(IÒ€B‡%€ò²²áÅÅž “Éð«_þŠ{ÿðº’It]GAû¾}Üÿý\}õÕƒKß'ÅóÿùÈòðWZo¹õVÑÂö&×  ‡ÃÕ¥¥¥‹´@à=–ò6€žŸÞ~;áp=ð³jþûg?cäÈQœwÞb’‰ƒËŸþoDÀñ!¹éw?½ó§,]ÚÿÜycP  ‹)ãÇ/a€[ÁÃ@q4:,X ÿwìhB–e?v¼ô+E!—Ëñí¾MÕ*æÌžC²¯¸ÿ‚|’Ë_þòþûgÿ}ȶ۷7‘Éd\ËgQ4+ŽTíò°æ»N˜T*ì÷¶µQRRBQ4JÔûE£D"dY¦³³“+¯¼’U«W‰D-ðÍ'ûx [G衇â;ßùÎa-ìÝ»=F h“‚üÃ@( TT”×jªk0L“=--”•—Q‹+)¡¤¤ÄýÛs¾ìÙ³‡/}éK¼ðüóE"~ÒçGñ Óç (Ï]ï¹çn¼ñƵèèèp£…- Q=lX€@%éCŠI’bápxb à€Àõg3öïÛïjý²D0òƒ*òÐÞÞÎÿ÷oÿÆwo¼‘Ï~ö³¾ þÿ z9·ßq¿ÿýïÛ¾´¤„šêFM$âêc²$1zôè MÓdw$‡!€òòòp8.ÍÛEášk¯¥»»›æ;xûí·yï½÷hkiíóXØT*Åwÿã?X¿aߺþzJKKI¥Ríò1ün¸·|<\ Ç·&B$æý÷7sËnáµ×úê‘„ÄØ±cøÄ¹çr`ÆÌ™D‹£þý@ @YYÙEQ¢†av'pH;vlyqq±ZhÈf³nðÁĉL˜8‘x"Áê·ÞbÉ’%XýÄ>üðüóÎ;ÜxãÌ?m>†i¸¹‚B`;6©înÊJ˼(—N?‰D’ò©’ÝÎdpö3A>Ïâá‡á'·ÿä‡o–—•qég.á«W~&MÂvrٜ۠¹õ“Æ(Šuç°^ÁC@I¬ddQ¤(_Ù?þ8o¬\EXñ¹+® ¶®–âh”qÆUÓÒÒÊ’'–ôù¬††¾ò•¯pá…rå•W2lØ0âqLˤ¶¶Ž!CªBPQYA"‘ »‡6Y=ÄàΚøHð>,Ð4 UUY·n?ûÙÏüZÅýÁÈúüÇü—ÿ˨ªÊßžy†W–¿Š¦¨|ásÿBm]­_6¯¨(9rdôô OBÇqœP(xBþX˜l6Ë­?øï®uKÑ,}êIž^ºÔ¯ï7aâ~ô£ÑÒÚŠ+úìÌ0 ~øaž}öYnºé&r1µun$oTU¥¬¬ŒÒÒR²Ù,Éd’d2éžÑkšX^n½›6÷¿KVä•ñÉOúPW_ϰaÃzµ7~ÿþïÿÎ;ï¼ÓïKɲÌY‹Îâì³Ïf츱ýö-„˃Á †Aww7Ý]]¤R)²Ù,–åf'¹ºCO ˜Á€B¶ÚOƒ^‚àp–Ï<òÛÛÛyâÉ'yôÑGÙ³gkD+H¶ÉÇ:Ž[ϰ¸¸˜o¼‘‹/¹Ä–¢(œùñ3}¨>œ!CÜÌ0I’(*ŠÈÑht"ð?ùÅÜ߸ú¬,„EÑ~}×]:ïüó/ÉgÏ8ŽÃÛo¿M*•bîܹ½ªläaïÞ½<ýôÓÄ;㾬ÏgúfRiN›?Ÿ‹.¾è“u8Èl¤Ri2™4ÙlÖ;d1çU!ë)ƒÓ»ßg¿¶c#˲‹t»ä=ƒ¶G\… ¯š‡ðrù½ji’’û=þOž„„$FI§RìôܹŽã–ÐËd3¨ŠB  ëéF–i’Éf‘„`ÞÉó¼ƒ&{ûï¾ë×={VYp³œî¼ãŽ_Þ~Çÿ.„œCxçú㎪ª‘ŠŠŠ‘é/™‚Y³fõ÷,À­òñ¥/}émŽò«&-"-:è~~Ëi¦W~ÕÝKÎå!ß²,B!Ý-Ò¤©Ir-¶M(ê•+ï¿ðß#…áýÁ>R˜6mÚA×lÛ¦+™dòä)Ã4M q˜ª!ýŠ€ªªªòXIéØ}ûö‘Íf‰DŠú^A@aìj'_寸«²¯Zê<¬çûß ÅAaàhÌ_pk°L·ìm>¡5›Nƒ$‰Aul4üæêÀCårÈ|áâñ8étšòò²Qº®GãñøÞCýö ð¬GbÖ¬YCÊJKt·¨AÛ^·Z†cÛ=¬­Åù/"òÿ¯~å_ó#zÞ½¯ç\;d}Üеî=rÝ) Æ£ýÛñ¯ô" Ãþí ^¨kôów/ŸŒ«â8Îè¹sçÖ½ýöÛí‡Òú亮kmmm‰D"±»¶¶¶ð˪ØP¨xõ÷Á‹ð¯I¾õŸÓdzÉ{1!ÖÏ‘¼z:øíþiÀqSçó`úòH³m×Dç8níxcãS`"väÛxÏã¨kÉÏ]*•ÒF]ÖÒÒ¢tttôk‚í‹„$IŠeYN"™lïìŒ×oݶÕ/N˜L&}­[ö'ɲVþ#<#N~ ÜZ8ਠ½î*Xy$ØÆ,€Od…+¼áx/Op=xëù»`‚9àZÁ‰Þ‚èõ;Ûñ9žíx+Ôq±”g Ž' =´zÊjA_yÄâ^Ï·ÉÕ¶,r†‘3¼:BP)"Vâúhô`(++²‹Å‚¡PÈBØ}q>9€ã8’ã8R"ÏdË+Ø»·];ݺ½­­­˜¦é!\î©oç€$„G‡[•¢ÇüòË/“ìê¢8EUUq=çéÙ}¦”ïGʶ”ï+Oˆí Ôã’W1TUUÉ$ëÖ­Ã0 ÆŽÃøñãY·v-M;v˜={áp„·Þz‹ÎxœââbN:ñDöíÛÇ»k×bãÆŽeâ„ ¼·i (ŠÂ´iÓ¨(¯à7ß$‹3gölo—Q@e}OIÁ—þõ(˲ÝU6ƒ‘sskjj¨¯¯§P+Ô¤¢(!Y–Õ`0(ú;î¶Oˆ\.g·µ¶%'N˜H¬8JWÒͮɤ3˜†‰„;ÙÒó^Èú|±‚ÌMÔÃa’]]îVHÓ„‹øüaJŠw¤Š$ɽï–€•ý=´ìq#9ßF– ž%#KY’ ƒ˜¦E2éÆ+hC† áÝw×’Îdȱâ¢EE$’IR©@€òòrÒé´_€JHådÞ}—îT !±XŒÒ²RRé]Ý]ÈŠL¬¤ÄÏM(ôµ€ ¯˜–E&“%˜Íøåe*«ª¨2„²ÒR²ÙL²««Ëîìì”åQ싯s;Ét9Žƒªjî镚†¦©îª=‡²þÂUyHjù—~A&I–QdÅ[á.Â$YñK„÷¯w‚†ð^ˆ—ýswò× ÿ–$‰` @À+ºè8a]'Òý#d$I"êÕ)ÎO^I,F4RD@í©*Ð4ô`ÈßY(²Lq´UQýß…u=¤÷JG¸"+ïšÓ=|Ò•ý6’ÜxÀPˆ gÞÛÞÇãÙd2I"‘èýÚLÓ´»»ºã¦e!ËnYSMUÑ_ ó'ß_"í0" PŽKþ¿=çèI’èAô«ºðÿ»$#+òÁm¼ñôüFö«Šæ!‰xPôÔãÕúkØñÆ–?¤Âvz² ‹‹‹ ƒ=É&B …ÐTÓ4zžíõçÀ”V÷Ô(²éé 6BH´€ÿ^²,“H$ÝÝݹT*uHªë“LÓtr¹œOĹlY–Q•€@SU×…ém9òb@ʯ²YÛó6}¼ ¸\‚Eη¢ |±"$·’¶+ûóGîYéÇù`âP︕ÞD¡ª ŠÒå‡ÉW@%]×{U;Ñ4 =¬÷”»Ã=¥\Vd?ÎAUUÊ+ʽrõî³TMC h}Ê>”ž$HÞGÐcpÀÊI˜–‰b)8Žç\Ò\N-„ “É$ Ã0PÒ'†awwwÛñx¼3“É8’, UUPÔBŸ¿§Õæ· ŽãjIJÜ¡Óó:ýt_°…éçvá}÷ý 5qoFÄAŽ{/¯Eç›¶)è&ô"X! ÿì<È}Ä;ä‹=g½v’$ ikksY4ó²’3™ÌA?¤HÈ#_BGØ’@ØRÖÛmÇvÇ«¨Š¿ú Ó »»{¿é²!ë3Ü7X–åVgggG:15MUó©ÕxU¿wÿ*Ûn¥,Ç¥Z˶¼ýOÁ»”.Öû»?±=»¥ XÁVÉv¤<±yìϱÇýä÷ÛBÂî=G¸÷má ÈOZ~ïí¾‡®‡±ÌžêV ôŠlvw'½å¸mÛØ–í‹0w[) ‚ü³dp„7ä>Lòý FÈÈ I¤cRõŠ"Ýñ"¬–J$œ.w²YöRße™L:c'‰ö\.g¤R©Cö©â*‚ŽmÛ¹l&“4µg/ 6Ž#Žop,ÇFv$Ÿ:ý—ë£x„M sáäy >êó«„p<„Glǽç`c;©ðº#p¼²n…r ´¬Ôó*ºßƒ!·ÐTËžžÃ.«*+QÅ ùu†aø ¼¼œ`(H:òÓã"‘0’p‹=å•Þƒ±ÝÇ%ÇFÒ$âÁ$ú oò•¹‹ƧØaþ?¾ö™ø${¦Xö¶ÀÈd2¹®®®Ît:m†a}Ú ÿ PDzmÛ4ŒL*êî•í€ãUývÇÅdÞøQ`±m·4¼íØØ¶ãŸÐáŸÔá8¾\ôu Œ#HÏIòÆ·ï0²ž9ظÈw útü1ô¼S@Ó@rÉ < ¬“ìJúΣ`(„aäü3 ò•; Óð¨‘e™\.K:›ñÓÈCºŽ%w,ø__Á¡6H2ï%ßáÄqŒæ tN`¼²ˆúš­lM4"$DZÂí[c;¤Sé®\.—²,Ë8œ=¦ß]@.›53Ùlº+ÙÕ]VZæ"ʳæå'XäW»íàHÞ¿°ú=ÎñØ=ú‚iš¤Gè%¯{ô§àŽß·+7\î„íŠGôˆ¿ÉJ€$˘†IªÛõ|º‡9¨½Iùy° ,¾˜(àxMÄs »ïà‡mü⡪k”eyÝ4Míîq Ñ-ˆˆ‘TU嬵¼Ýnß—Á:Ʋkµj/J½˜…:< š6b§ÐÁáxþ tËÄmðæâë÷ïq¸Xâp¹ôÿŽõtSÒ¨ÝS8rÝ‘Ÿºð[(„öÞÀèv»Ó!Î9‡¦öHEqîPížAŠ1ÛͶµA¼y[Û¶¿íÍ`|{0~‡^DG‡0¿wp·¾Ÿ´³ŸÉ/ƒûͦÝnç6Ûíª,K[–åu]»r·k®®®V×××¢¡ªÚÁ1·"˜ZÄ.:å­ß«¤ 1Þ £˜8X,0+ŠÛ{þ(ìëÍ ÊªòÖÂE޼(g~SGAB.ˆj¹n ƒ@p"{'šïÊì¸Å|>;‡m¹mÓÕUÆÚ6ç<ƒÚÚöLRþz—x“ˆ8oµìF$áØÌ@ w*ŒQ‘RN`›»²lªªZ×u]³ŸÃŽ*€ÀÄ4€Ûn6õ?ÎÏÏß¾}[i­gWWרªÚ›…y>(î|÷—îŒ"À|6Çñ“'íµh“FIã=Ĺ„¬!SŒ6È2Óî ­ƒÍµ¶‹Åg Ë€Î1^¼xç½:…c‹Åâggg¨Ây„ÌOŸâÕé)=z g³YOÎΰ-K¼|ù"‚ÇOáÕ«WX.—~§SFˆ=òYR A{û»I8ÞÖ+Ÿo/ß‚ù1Öëõº,Ë뺮wa˜”cfáÀÁÑÑÑéÉÉÉ—Ÿöùo~õÑG¿¾Z­°~¿öóuA·YC‰aH´©PÂDžÈc¤«Õ «««._ì{XzuŽ÷VÑâ†ÑþWŒ+&È"d&!1TQaѤ( äÆÀÁ‹x¿Qä/mnš¶±È‹JkÀ9ìv;h£‘爀¦®Q7óù Ji8f”e “y¡®«ýœM>wTã»(#Iˆ’Ý™œs¨›ÌþÄÔ—/‰gÇǸ¸|ûû¿~÷Ýo_¿~ýÍ÷ßÿ7f.Edô ÿ1 àØÝn·Y­Vo¾ùã7¿ûöõ·›åbù™³öIU×FÄ)¢@ "ò6~$Á‹¢B8À€jQØíóÃË>cHPK|¦0Hx¢K/ÝúQ:ÝJVކ4o¢®í’†ó)U @˜IwJ¢ëzÖíYÄihR³€¤«¼{HºÉKû}Øk7ZTøo!✀™Ei훲Ü]ýý‡þ´«vx÷îÝùÍÍÍ6 “{ƒˆ(p˜eÙË̘OæOØÚ xÎÎ-,ð ò4÷ù ”"""¢`{'D.­§hûG]QJ ¹"W+Bj8ËÝ+ „v?rUÀ"©ð)Ô-cƽ©¸tãð˜m xG!NÄ%`圣ð.¼wâÚq{ÏKrò¸Äq]įÅÄ2ý²9B9λZ)µ-Šb³\.Ï‹Åw"ò—›››?_^^þP×õ@=¥L@ÃoF8ð Ï<p|NDÆ "(¯”"c i­A©i­I%áè½FmÄÃÆNöôÉÓæ ÆJ)EÁ\Œb|„ k⤈€ø®I!U³ˆP«7|Iˆ=>c儉Gº+k­bfbf „–pÉDff‘6ž™…Çã\(¯MÏÌb­ekmÅΕlˆheŒyãœ;ošær³Ù¬E¤ÂÄFÐ]ˆƒnÏéóàó§¨@h­Užç4›Íh>Ÿ«Åb¡ò<§<ÏU–e”繊>Ë2ʲLc(„¼2Æ(cL’Ž 1Æ(­µ2ƨ@|ÕG#2Æ´Â)¾‹]TJQÒרï=Äpdðâ‹sÎň±Ö¦Dv-qCدÓ8afnšF¬µ‘°.WB¼ :b­å¦id·ÛÉf³±Ûí¶Ùn·\UUm­Ý1sY×õVk]–eY¿{÷ާˆ? €|ü ò&P4ŸÏñüùsurrBÇÇÇtrr¢ŽŽôb± ƒƒ5ŸÏUQj6›©,ËT–e:Ïs2Æè,Ët ¦ „×J)¸_ZƧÒÞþ*†‰¼Ö§‚Ò±½ÛUB\€:Ì6ÇögH·¡¹JÐM³"\òÞ‰Œ¸Àùm\ðÌÌl­u1]ü€à"Ç7Mãêºæªªx³Ù¸ÍfÃöææ†Ë²´«ÕŠšívk¿øâ þú믧‰‹{œ:ÂDäX$‹¹Æ|õÕWôé§ŸÒéé)½xñB=~üX/—KU…\®+í)¦ˆˆµwÀ)µz@¬Zâ¦K™{„ ÃT4šJÃшJÃszüW¥ÄoÑ!B;ö4µ¤-qÁS¢Ç¸è9)׉'qªÇ™±î¶¬ôó2³ã Bün}Ó”eiëºæ¦iøòò’Ÿ={æŒ1îììì.ÒxÀ¥Q âÛ¨¤ñýÙr/®Ÿ/~Qãïtj#ðœËM‰ ßM¼‹õ C€è÷§‚!"MºO°4#åö‰;Äiø^@ø†‰9#r î=ÓøTt÷EzÿwOØý}[ÚþïèRÕ¿/¹úýIûÜ&à†$÷Þq/}?÷žý²c{úîN |¤b4mHÊi8Ã)ÑÓ¸”h}¢ÞEÜ©x „ÓçTÇž)ñÓ~ CÒâ!CCºÅËéÒöÝé>”ˆ HÑØû©ˆ>ÿCŠÚPxŒØ¸G&žH~}Àûè}nt#i¦tƒ!ýb(m?O¿]ý6º;§÷tSbU%ïÓpŸˆC\úP?TÿÁ‡8L@/~ê£OÅM6”I‚€ÔM«c¢xèÝTÜ}ëê¿ë‡¬Rûá!"¤Jîî’6iš>`†Ú7ê>´د¼¯µbâwŒ‹ÃÅ}Òÿ˜øû¸{kÑ#î.é1—£SuOïÁî_!ëù7•;ó!êû©î¾mù©ø¯ÀÏî?ÔÝ}ÝçÏîÚý €ÿs÷OÌÉf\v…œýIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_laptop.png000077500000000000000000000535571217176075400247360ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½yåYVß÷9÷þ~oËÌZ»zïééža–Ò˜Õ¡ÍHV8ì`“mÙ‚ /Bv`Ë–ÿ#YRX`IHx‘#†`1²#FÁÀh€f4ÌL¯Ó[U×’•U™ùÞûÝ{Žÿ8çþÞËìꙪ&B ü"ª2ó½ßzï¹ç|Ï÷,?13Ú&ù=l6S°%»oûf–Ç+â ßõWâ­Oîpµ^‡5PK`@Ö I9'ÈBŸ) Y0A ΜŽ–ƺ@J~-!ƒ&3,¦ÂíCÚ9l¼3²†€¨ïŠY¢ï…ÅÔ¸yKIô½Ÿóæ­‚‰°3Ë,fB­Æµ›…Ôe?¶&Îí ûG• »™œàµýJJ š8³'ÜZ‚–Ê£f^|Õè:ØÃþÒõ‰ùn+Î%†Á¸uhH‚œ„½9ܸeˆ@ê`1MܪH’ Š‘{˜÷`*Ü^{ !'ãµë•jeÍj€ª:#kf¦gùÁøÿç]2) "œØÌÓž½' «=X"ñûÛïé­ûW}¿¿ý+Ø,´»þ¾üÞÚ @A(†™ü¾üÞÚ ¨L¾ä°•`E~ü^ÚD@0®þãWQ}­ŸúÝhÙœ?q\aûÛñwÛì¿Ø©=ÄÆSH%[—i‹lóÄ›_¶Î·u'"ˆ6Þ³_ls=9yißˉkˆçõkl8·l®åã²u:ÙŒƒïÖöÛ<äø|q¼ÈÖ}ÆýH<›I£Sÿ¶¸e) XÛ] €Z›€LÎY:w½D1ÃÈÖ¹˜’…®s7°Ûv¾OôÅK©ÝWu—2'èúDß+$?6'@ÇÛ9é¦pÅw2¿F¯ô½ïÕ÷qÝ^P‰ï' ©FßCê:?VÛ±‰¾w7°ï’AÚw *‰É$Ó÷J—‰ó}/[¿'0¿IÐ¥Íw¹ƒ¾Ï~þb 5¥ëý|j‰¾*}ŸHÉèzñ}0ªZ¡SrÍ$˘¥­ “;ˆEÈãõ÷ç¿fñY „»VÐA,KJ³¿;›ïî즺–(•vݤS²$Ë9™t©ö9ÕœÅ:‘ŠH¬28{&1™ª­ rZXLÝI0T äð”èȘb$›ôÂbf’:EHÖ÷°˜‰¤®`"¶;˲3KVª‰É€lx;·'Ȭra/“*Õ$!bÉÎì }ðçÏgWFv@$)ý$1Ÿb]¯rá\²õ`䩉tYØ›ct&!¶˜%I¹"YLTP”®G=¦–˜’ÉP ÅJ®¶î–ƒuµÖd%R’ãÎtò!¿ŠÂI={rZ¨w§VÇ·…ŸøÀ—Ÿýø¯]úÏßóýX®Ÿ 3Å0¿´B±J-Êjµ$¥„HÂ0P¡b¤P£¢Y0ƒ¤ê³‰ËB׉«C*®¾šdW?”Õjdf}O» ±Dm2a‚QA}%c‚ª¡’”, ¤q¹¨º2©%”J’*ëº&KON úCj ñU '¿×œ\ïZÅI¦ÐšÜ&3aµH)#]òc„¾KHÎô)‘sF²Z×\¼´Ëw÷wüùÏê±ÏÿkïÛyÏd¢ädw4 †`U°úr‚ Lï9µg–ü÷ßaÿfù¿öÇ»ßüÒ?üL'»ìž;‰`–C¦BAL”R«ré¸þÚUÀH)£ÉH ĨøÃ)âV´ÙÕ$$Å¥¼“! e`ow”„›7èû.¾1*‘°›AoÇßb 7〰Q/ ª`ÆÅ —xíꫤ:æ‰Ïû2&“Ž_ü…f»$Ômd(6aA\lÏÇDN!KŸ´*‹Å_òÕ_Å?ý™Ÿ¦š!’}ŸfvE6Bànt±4æÎ÷Ý¥¾ŸÏ­QŽù¢¯üj>ýò«|ò_|œÉb‚ØÄ?Þi`Y]MÕGç;¼üòs\~µTž¸A?3úéÉ™ 2=%ÏÍN @þä‰ÁGX³^)ëA%Qé˜íÎYd¸yí2)'_q"$ÒÕJ¢Zåƒ?ùCL“ðÈ¢'Q eÄ„6:">2ÙuhÜk|i*;‘BÑ4ô² &˜-X_ùkàKÞq?©ËÎÛǰ¦ì³ØÀ†°­ÚœU< aTÔ¯Zhv”u)<ûáŸçÉû¦t9£f˜«¤†Q“Ÿ ‹ÅäŠÀ´ó0†Æ~Jݧ‚v•ßþà{ÁŒw2In‡ÖðÌ k¡†©2é2‹óxõÊšœç¬ŽV…Å%dÑqðÿS`âwR{ú¿Õ)ø²ÿû¤ˆƒÃŠ®?C–bp¼¬I|%'‹ÁïÜåŒCµ6þªA¨[èê6®hõUU U(¥"*õÕ ª¾*U0«hSURJT3°êUqM¨é諹 %@C5·á“6)J¶V©5ôˆQc"E¥ oœ7,P<³G.I~߃©OHXÓ¾ú-ìÙ™)³é”ßþøsüÊ/ÿ6 ÖŠ’)ôÆdÎá?üKÀ¤þ$ùÐnFͧ`yckƒªp<`©ƒDÖ˜$CXßÚçè•уë˜(Y¡J5,ÉHb$!ˆ—žBSëãs’j{hwèsØFIþy2·÷ŽÞ+¦FQW‡¥TGôª¨JLzœ<Žó…çõ—F'[ÊQbUú䡮⫩{(›™CMÉš<$‹ïƒZ3×DÉBÓÛÏè6ßçSÆ•-&Tª/†86'C« ³ifo1á™OðKüϽp…ÅîœîIEU©í°¤¸®i¦ô´?h4õ{Ê <­*¨X—°ªëÊQ5•: ZÜ®&óÕ!wiÄH¸}dÄ íí+À¬R«Q­`%&;Œc5EcB]1ØfåcÔ2_ñæÂa•X5êjÑpa6ݘÂmÔž6«³ÙÜ„¢ÕHÉŸu„ræ PD)M`¬¶pŠÛõø[¥¹£ 6 $TÚ±áÛÄþ¥VË ˆóõ¹‡³;=‡‡+~î}ãŸz ɰ{aI’Ñ%vw×i‡5QêöhWOƒê¶˜Ÿµu %|eœ¾3`]ÜFJLf2°”8”LQ¡˜R1H‰”yÊô vú޳à+©‚ô™ZK¨oEMÐêê[Ô}øRÜÖkqðäj´ÿL '?ªºÊK£m7eüÞb2ÍŒ‚ *JÒD u+¸–¨#HÁ™7ƒžNMJ"Àh§f¤Æ;X¸af.8j ÎÆ©hhð$3£˜ïLIùèó|ô#ϰ,•ù™IŒj ’ŽYxíæ!u­tÙÁ\žO8gÊ—|ÙSüâo¾Â’ž$1m)øÈ…º¯Œ_é?U°äx:÷=)ƒjEK¥Ë>¶É*µª%×TÒà@ÉM ¡Ò販8M"Š/ sUÕS¶DI–|qOÒ€œ/8A¥ *B'BU ä IÒˆÁÊ%¡ÕpÚg泎›û‡|ð£/ðê•ëôÓžÝs;~ŠºvL&#…‹»‰0‰q»³ÿ“ ¤ÓDÐ0@“KÔT Š3bàèV•Õ ¤>‘»Dî&t]Çd=ðÐãóÑç.³šL±ÉŒ!·ÉtB¾ï<,z.v™§×ô)#¬횃G·^ %T1G×êÆ5€’9(´Š©Gâj ?^"̱j í)–Xy.\{d—,«æ¨¹ò˜0ŽEÂÍ=›Ñž¥–`;³k(*9°–ªGõÌ|‘ì,¦,W•ßøÍçxþù˘»gvä‚iX#*ÑXØX­Šsã³£ xC¸“ xÝf›Ÿ¶9Q×e–ÇK^½|´:@ r— Ÿp.+7÷8ný[GîK#¤.“%³˜Ïöor¦7÷¥[­)µR‡êj»(KU´„+¥NGÈH­:ÈŸÀÌ'¥š  îBŠ„m®$C©ãåQ¶† Üí Pj¾zsÐ ×T}EJ¯#ƒØ„E}¿ªq.·Øb¨škààÿ³ dåSϼ³O_ápuÌl>%KŽ%Ö#êJºÑœãDniîàFNnwÀm.?³ÜyK8à¨Võ•£‡Ç·yìü‚½Ý®ß}“«×oAÊL&="®Â·sF—ă~Ò.VzñÙÜ5%¹ðZ„ßM‡1cîÞçÿNDÐgØ5nyä|,Ä©ÒuŪa7®q{±ƒ>t‘ÄCoy'ëa ¥žyŸ™*Ü<^sµ.™¬ õ£/°Z® gÒ¬#ïìEKê^X%8xƒªÔê`É*”ê iÌ+„ˆÜÅmªÿ-âÙ´‹âÊâàQñбYx ºÙíèw„Tt5`Ë‚®Š«ú$¤>»Ý ¤VCµÐ‰3…W®ìsýê¥TúI‡äJ]¯7œ¼„¦ÈÐL+Ô ´š¯ÒÂ‰Æøxäò^§¿AìÓáà»ÚŒœUÜ ÔœÔZ0›`ë#r^¢(G×_Ãj. ëåæSdgÁìâ.yÚcâ+ ‹1Å:0YäXžèiÚ»«J]­Ðjè0€¶Ð,¾/Ä`)fÎd ÏÀŒDÎ (_œ_o¦GSd1Åj¥R–+ê2Ü´>»àÌI„£Ã×/ß`µ\#¹c2é°¿>êæ*ØœPñm ·ðs[`¹MÀŠ£b6¬ Xõì§´MáßÓv—YÁ§·” ס8Aƒß„tîeW_¬È ”a ÔB’D·˜1¿p™MH]ç»BQÃl@²P*x¢ˆx<ŸÂ“"-ù©Y:0˜tó† €©Q×]ÔõàB1xºµZ#WªƒK5q©Ž«kLó‚k¥6¹KtgPŒº,ˆ’ ºV®Þ<äèxMêýdN’°á¡æÍêÈ9ø=(VŒbP«3’¡ÕÔÕÓèyIõè§iYE+JíšýßÖÓ'Mõë¶1¼=Ü«lb¨¹¤[¥“Ä …Õr µ¢C„<’=“Ù.yÖ#"ž´0T¤DhµkÉ~šbà#yoj¾r$e(PÍMB2ççÍœò²ª™L{dÚ‘†BZW†a X±>»_ŠkUªÎjË÷Ëx`7jb¬¥OLS” ·Ž9¸v‹Rú®ƒÎ3¢$ RÔ]H3¤ô˜°9žMBî,´š:òׂU šÛU¿§Á…ÝZJK|acZîy{“@´*ÇË%º:&•‚%Ïý“iOÞ]§S,'$'ÖªÈÑÊG“W µ4%C='O½ „Öê©dÒ[B»x‚ ¦©«T3&Ú!ÅÂfú„ª6TrEìZSÁÖ‚®Ön¶DÈ)ÓíLÇUU†”ê‘G‹U[4Ñ¥„håàÚ>·n-Ìèg&2Aju‚ëO©‘0D=iaÖ%¢ˆ›¬L”­I%‰ ¯˜®#{¨qÏ?ÀlÂ÷D ½I@D¨±2ó,£)“'=’;Tà0M˜î£…ªÑ/ætó “é”ZÖä›ûôÉ]H¤5) ©rò‰ÑH'kecÎêvw¨Õѵ8 ·.ÒÒDèÔ£–I]Ô Ò ©›cC¡®Ö GÇØɤ§™¹ŸžÍF—­3XÊþÍcÖë™tôêI&Ž1é& MJ¨ó ´2ÁKŒŽ} |sõÒ™'à Љ¨‘Ù3D^F¤Ð[h+MÇÞ$xn`üTèfSòlô˜ÎŒ‚"ª”ÉŒK7¯pýŸþ(o»pž³³Ì·ûÈOüÄÏðâ+¯ñÉW^Exî+ÿ7nÓg‰v&Љx6ÐZ( w×tƒœ1Ý/'_­ °y !¾Œ¸@m1­NG­¢©c"è´#õ O#+åpE¹qËY֜ɳž~6AkåÆÑ’å‘— u“ –°.JLšé5@ÉwùÊŠT ÓŠVÏ ½©¦]‚¼jÀòVkAdB΂ LV²@²ì‰¥[Àì ¿í æQï^¦ØxãI£T¥”â“”…‚råö1çÝŸËk{ûüês—yôч¸òÉOðÅo}·žñ¥¡¼r™÷‹ò²{fÔ¡ºÙ“@²GºT!§<>™E9WÌ`ˆ”ŒêxÀsųÔð´E éѱ|OùN»SºÝe5 «5z{ÉÍË7Y®dÚ“f=I ³ìEÅ k‰¤Í´Õà…3Ðe(BVÅ´ød631Jqcòª«|iµ 9a“´s­Ÿ“ ²úŒó}ròG)åû¿ÿ›ß¤ ˆ‡ùDŽÌÙ?¸M¾x‰?ñž¿È£ù$O}Γ|ÇöWø_þÁÿ0ÿ#ß÷<ù5êd÷cKdÕ$q"]Èî®) 5*"ô§î¶™yjvmÉ %sCÚMÕ:ü÷Z‡ˆT+ˆºmQu³€k˜:éXš1?8Ðãµg#M:RŸhU;îAÔàBøj<Ò¼ ŸP²Ä¤GEtLŒiØx‰è‹é’ÜtùÂ-´Jk7[Ë?˜ã»e…¾è ¿ø³@;Q‹ÿbx Å’“º¾EÏà OåöÂ^Ÿ`«c*Y õ¯îRƒqºŒÔ÷Q¢Ö!oƈ7&ø^ÝÀ&”)yfŠŠ¡9ØÖƒ¡G…õz«ìÌg¬×»‹“ÐM:DÝdB?Á'HòÖJé°õ@5#õaŸcà¬7uP¤I4dLª³jê ¥º"°HÅ º@¨U=*¨Õsº”ˆF(6¥ Ñe$/&Øz‚–êié«‚J€Êd3’“kžµ¢‡‡hñJ)¯9sñ^7ÇcUºŠ„i!õÈíxÐâ¹ .Øaî6< Áݶˆ9€”ÐUeuxH?FÒ†°ì°2¬  ÌæSÖëÊî)Ðwlm,ëšã¥ŽLfþF†K ÷PBƒ‹¯Þˆ¢I€©d>ÀUÝ%s¾=cC‰•ö]=bhƒ\\˜²›žÔmA/Ù²t ³ž>M}zJ[«$ÊB™V{´T¿—a k7'ÍžQ1<ñSHh 'O:Àœú×Ëê€ . &¡H—H²Uv·„@h{È ´*žQ3³|é:“4x›Õœ€zT)C…ùtÂítÌ|±8q¶Ù´£,„uöÌØœ“lXò<ƒ1/D!سC·æ.©0¦+®¾µåØ?e×\Ù°N©C!‰`9CÉÔað²ë2DÔ-†3''oR2¶®P µ¹–¹Cú"DRøò‘ãˆiIÎØPHL±:¸ (h1RmDOõÏ Žê€YPÔê/˜ jMN.°»Þän5€ï?ÕížÂ°¨Ý´ÇD<>{`X€2ÏHé&;»³gÊ“[ºbéÅ«Á€ -KqŽß”ÚJµ#ÃÇZH¸0ª2¢zXZÊ‘~zQëàéäV&t/D„ÜMœ ~L­,ª°Ž¨›«\ËV>]rQ…!Â×ÁÚIìcoäÔõ=ª3_ÕÕ#• 2x°'Ì•T¯Rro“g M=ÓA¼¸×  ¼É´p‘äAšõà9oRÑ,XÍèP|È%“rb¾X°7?‰úé ]Ý@µ šê>¾¤4–e“ÚdÔ6È"2vÒ5ò•ã™·Jµ š)‘¼Œ1ö䮿¸u²Þj.n­ÀèbX¦e({£ IDATpmÙhd~?¤àE´1 ‘è :÷H×c6A(îéhsAJ!YEuðà0ÀzÉz¥ä pß]ûþ§·7G§`Ö–ÅóósBŠ«a]­˜v ú޽YOY/Ø=sRE-SÒÚÐå[;€#rÝÇ’"ÜʶÆ{0ÀiÖ 1‰ÂL°R=7´”ªŽåêu¨žÅñyRx^Zâ¡~ðæWÚò“.L¿©¾ÕÍÝÁä™{#iâ VÍé`ó ã`Ðü9Rعðõ­Z¸¯ƒc+¨QåZP χìϯ¼ðc|é|‚?úçú›,®/©]ÏÏ}ðcü?¿ü ~û–²˜ô>AQêä5À‘O^ÆíªƒªVîláÊ{ØCk„TÇ;\@ÛäËÆ,Œ« bmó\-%=Š=ZY[[VV׈8ã)£Ð<žl¹†€ødBŠ4µ pºo+× ¥Õ&¼Dç’C[k&šGlû±£Ú›ÜÞ0Øl"Z€D2;SáÆjÍßûÅObïš3}Çjí*>¥Ì1ÆÎîœs;=yDÂ0&?Н(i§• W­]™ˆøŠmuøZ4²pZ¼À]¦”²¦5¾U Å¿qþÛ,7»D4q“s}‡RkcÄsÓ$4,!Þ”|„µõP²ä±B*Ðì•Å'®éª{/*ŽÇ—­la"±dܶ¬ÑÝn÷.&®înõÁg› É}êΘ_XPÍóóÒ;I‚pŸ)9ÉÑŠ:}ÕÝ?õþB 5ØlṽµEj"]а£áÛ;³$P[ám)µÑ6®A³ðlÖ˜!ÒѲ“Û&ÙcÖáP¢-È峓 MÄÇ#žOr«Šž xÜ?Ñaæ¡`“'ÎÙœ³m©õl6àÞ$à.@hÍBÄ|õçX¢o¤»ÕòD„,B–èæåH,Ê™Ãt4{Ø¡]ɼ C#]*oƒiÁž ÚV€áç Ðh±$ÄÙëÖäÅmb¶Â¤Dᆡ²¨I“1"}<ò˜"Ó8idì8ݼéW+ÕðæM™™CMZÉ8¿­Ýeï¶¶HÙ•Ã0œô^ÞÄö&»…·BÇâ]?ÞÒ-o´ª«‰­^O°ÈŒñDQA Û¨Û’´Vj•Ô“¢¾¾åŽv°ñf‘áxl,'½eÓØÖ 6Bh¹‡àHöãkKãnç׸?wû<ü\=TÜÍѲóýÍÖEnŸ‡ˈi¨Õ]jk+ö‰ð°ide4,Î$IëuqÏÛ½UÙ©+l‚/­h!ªYÅsÛkUÔ µ*«õÀrY¨ƒ2f.ÝwŽ>X:AØê¤„WÞvRfËil Ð$ˆ"".[Ç4¯. E6‡˜|SZí!­ÓÇ(ˆ1¢Í\7®ºm‰Ð„-G?®ÛŽǧ©£ŠgøÝÌRó µ"D>Ao¸ A ù³Çøll×Ö$ž£Ï¾Ý£÷1åŲÔЯ¡–Ø¿qÈ­«·€Dî:údÐu<ñØ}|ñçÝÇ¥ó;LÎîðþß_C÷:z2Þl© •—ÆæPîþµêÝmÀ“+@Ú]Æ=oUê²ä £Örìá„UÅݺœ6û§ž[¸’þ¼OO$!ŒÚ,ÌA+SüÒ– =äÚ=4S¡Ú6™54G˜U,…{܆å%à®MÀ è‘â_¤,·N”µû·ùCo½Ÿû[¿ŽéùïúœGyò³X—Ø™žÔQÿó¾ŸÉâ,½ItÖð•¢ZKhþùÖ](èí„4Ó³Y 1qÛcüM²Dë8Ü&£ÕÜm`ßÖ¤7-0ž7»ÙHæZ€²Ù?äÀVljFmdÐÒ¼,@b“¬è6옮A}MÚï܈›I$¬µ(f9ª]*Þº¼Ï{¾óßâÏý±/úŒ§ZVËB¿UCßœ—¾ÅµÖúêic¡âGëÐVz31™“@[ü¡f##×úñº6Ú‹-·Të¨Þãúí!¢Œ¿€Éx’h³=ªôhøìiÍ´rôÍ ÚˆõÆM3ÒÜÅÏÏú¦KÃ}{s 0ènª§L«)’³ã¨õšë«;6}ü^TÑaå^„ŽPÏ5€öÌ›•hQA,AМ°³°Ék“ › 1ÛZI D­AÃ6Ϥ}¿…¶-‚sÙü)ª7mbíºgÜuz ÒãßZ4¼Š•›ðgV\ˆ¬ê¸õ|5-Ò’CÇí´ùÓ…!w­=¶ŸÎ1€Dÿ<·Ñ‘ ª UVõŽg€ãv&!ºD FÕAPË›¯MÅ×ÍïÚÀŒÞ‘´}ÊÖàëF Ú­´à?y‘ÿ ”3®¾íÉߗㆥ[n’’d×P[@Ù,ê÷Æ"Ï-;dlðI»Î®’– úö¼9;¦-fÁ¿L*¸mµï‘>o+€Ô; À·”sð7dÄ ÕÈz‘1IR#¯j¾:⸣‘DÍmk^@;ÆÛÈŒ'h rþÚq"¿ÿ‘·`sÎ-=ëÖ©†#,X{ÊöÛüC•“ë§6.¤Ø³Á'³¹¶à)eZ7¥™Å(|=qC¿‹íM‡â7^Ü®Yó¡­!ß;³QCc!{¿<ÁßâÑâô]ØãŠCˆU¡è¦¶¥X[ÚØHBÝoº<ÅÖ|k™4³ÐM[@sÔ,wݘÓ±Olíê”CøìM·g`Íß#•ÎHLmkØZCõ·4'®¢Û@„MsëQïA(îJq¸W®[‚Ü’'ÆvfÚ[·Žîxž¡ÀÍ?äÙƒÁÛÈ“¥jÝ|„m ›“) Ðj™â}€šÆÙÈÛwOóûïüp£3nÛªy|V¶ÌNCøq^Ý–o ©[ŸÙæšþÞ¾Ø6PŸH³í‰èxÈ(4)™H÷8÷À›6¡Ö¬Æ\y†P©Wœ‹FP§·ý[…Z;®¬à¥ë…i×Vlì`‘÷—[{Wõ|·cOmµ7‚F7íQb`¥¥‡ƒ R;ùVä­=ÂX;@ÝŠf2¶}õvÉíƒÛ¾›_}•F ùFR¶Îg´F”#¢'Î= Ûs9¶ÂÁãÖýºç„•wY>µÜáÓ7ÚÞtu°QÔ‹§_]»¼ÏŸúÓ˜÷ü…¯½ãqìf~ýÓÇ<Í 4rÎcÓ¥Íêi¶í¥œÆ ‡ZôæKy³š¼O\„gm³ -Eô.þÖsöoëïŠ{Õ"?aØ<¬$¯ëKÛšbkÕž*Ö¹´•]qzYãšVúñ6 KÄ&J;u`©q§µDûcû™îu³7C·Õ8ò0*‡·yìÒì O³°ÂÇŸ¿ÊÅs æ5Š/DNiçp÷rG{?äMCgo÷¶µZ|ïñ¸4…iM¢ŒˆHn¤¶4µŠçÄi[7O(t×M­„K·‰%´ð00rí;oko=‰þÀí­×œØFÛá/x½‡×Þˆ ·™œ“Ãw—Û=$…¶¹Fu:Ru ®—pxÀë7îp´oÓiÏîlÂCvé†BŸ“'V¨nüV¦N‹ç·[+’Ý·öÕßš%oßè ;¡ ·¼FÌÿË"*&­Õó]r?î›,‡u‰}Ìb…ǤDý¾3€52{÷Ö…ÅL=yõ}„ŒæD÷°èëN‚[Ù¦•_?o¼Åb¾Ç¬à@©´!ÄÇÝÔóìꊩ¼±¦ ×®ßæÃ¿õŸzæyd1#‹øªlÞÖhª-ŠekPõ wõ$ÿ“æXíQ±¤%,€ûþ›¦X^«àTs{¦¦¶fCNBšÏ:濼éN¡þ2Üx[höHÞ¥'ÞÁÏüÖK<õîÿ‚?òe_ÈÏþÚ3¼ðòuX0Ë<ö¶‡x(¯93Y3ß9m_ð¼úm £èZŠU²`í|UJ:å¶©ÿ—Ʋ®¢m¶­A©¨dï#dÑ}¤e'£w7›ßè…·Ý÷Ù 9£ÍÚR«Y(|ô1ÎLRæ·>Éó·ùøÏþ*ó3»œü"“IòļøÒ‹,vîêIôèO­Ýiؾ<†7ÞAwŠíÛ&ßGÔ/Hê|ðk#ƒÚ $d£N‹§®n›[›Ú#¶LÞF·î^Û~}³è šZëvGìíõv­þZGBË/!0!Üæžyôî¶ÊË%ÌK.ÚÝÄû›dXá­·UÁ鉆7ÒëéWÆœ¢pÅ U8V8¶ XŠÁfP¨q×bH2²$.\8Ï /“ÜÂ)&x4/\¾m£Aíºíw†+5Î>oé·Ù4GÞ¬Öm‡ ¥\á¯÷6¯½w¬Ô&ÈÆ¶ªwH‡Xóin…%ÚÃÄßzü¼µFŠ\«þÝ`ÝðýxݽÖ„”(%ô~ "Yò ™fRŽ e‹û®«cñß6…òºWÆœ2"f¸ÿRB6#/"®ÂsäsJГÂ$Ž™5ž–,ÓÒÊe{Óº‡µ:¾‘œpW¥ÛqÚﵜäÚ.abGŠ×ü¥Ðs ’ºxÄôúã#kã©C§^‚nÕ<¬oU±¡RkØî¡P¢ý[Óœ è˜YœhNBœg«÷¯7œÁÖMË&mÖŒ{ë0û;lþ,§Þ¼¿ý½¯º´öFËY6§Cºé§H«jìt™F©WùÄz‘E„~ÙtåØÄޣܪõÚu[•‰ Ì'F«“.i|O°ƒ]…L²‚JÔnLÈVÊ÷¸bqÛ E7~yìÙ Xr¶’ì¾”TïTnKñö.«]­^¼^úÏaðò´¶â[pÈ$"Õ-iÔ6 ÈÔM£eDz¬sÂ+wiküB"DñEäÔëÈ„Æ8%'÷‘ÎWŠh+኎حµIkBØÝmQ}°¥­îPÿYº†ÝI|I¡!RØß F=Ëæ%ÒN÷äéRÁâWÙú‘óüÄ( ¯xÿÁ’"½›Í &Ƈ–âüP2žléµ’<Û7ÅË0I›Þ…>’®Ž­šWÿÔŠÕŠb³¹î¹‰ÐŠ®×Ôõ1µÞ_°ã ªšÛ«çpÍbâÞMšZ©Ë5C¸@ËÐB0æ[ê?½ÌsA=õíé0®OŒ )¡ÞÙðí«R(µ‹<ÿ¦z}²±!?8Á!-×Îé‹“@¬B"Qõâ•ÞBF&ÐßÜ¡epÀ¥ÃØâÚ]ŽnïÖáçÊ´§MPÓINI€ÔRW¬°XHqM0)Äÿh‰£©ïüܬfp*°®P+R”¼ò^Øjð -+ï/X V Æu€`ê‹È ˜ žO’Ëþb* iVeœ» U¼m2CãÈé!³ó[;iG5$/W×4®VÖ‡GØ•ë÷%©¡RCÄ[½§¨zñ,Ù’“PÖ¨eW•·bÙF/ˆo+ËW)b]tí&¤^Ð,È ±\j˜·§© ܉4¡-)b ŽŸ±Æ3o¡ñâŠ&5‘ÙÔÒ¶ L“\ГwM•>»ë9IÎŒ™A6gk¤ þ§bËì &Зס`Ã*òŒ²<¦ö¦EѨ±É°jB°YP'çVî`.ü¥R fŠÈû̱{£¢wÍ¿Îä’3%%o¥"Ùýú”eü;'!wÝè ä,$É$QD<š•³#à>pŸ×ü¥‘ÑÏæ-àiØ(%è½ò'u‚t2†E“´Ö³m•º›˜Sä´mtËô­k¡rÝÄ+­5fp»©A)4N¦õFbݵ†Ïµ§”bѶÆKÄ=å»óÂÞ»œj{p\Ë_µz‘i\s˜†¡r¼R:”½ë?‰•5bbEX/Yüùÿ‘£ÿý¿ âì´'0Þø)ø•o8)%ªÀ@7û«ô5Ù´K;>ò±Oq8ý'\åI‡-&, 9·Né/4Ä\™Ê¥k6&vúçA²'â&Gí­–no-6Ï'¹iÙÂ[w¶A´¾šÃæ'ÛÜ7àU¾]v!sð¯Ÿo uM·0:£·“’¿ +µ.fíZÒˆº{é0i‹èŠ-IÕÂ[’ÐŒ"1>ù©"ZÈÉ躤t9r(ˆ0çæžhÞU‡qš¨ïàä¦ÀÊ©LÑŠ)»ÓŽ}üi~ã·~Ç݉¥ÐŠ0EÆWۜƞÛo[ß7j¦ý¯.'¼œÏìÕœÞ^—´}¢íÏ7&iûû7:âä5NÞðéûߺÂN&[?6¸±å›ýZnÁõ‹#¡â»ÉŒig$SÔT8¾ZÙûæÿ.b²u½i ïû>LOk€=Ç,t\Çêðˆõ!Ó×®¾ÂjuÌù,Ìg;Ÿßz˜“7ý™·;MÅ}w·Û‰ÁþÿùöÆhñ¿GM/[/׬–Ç®÷{^üÊtí^õ Ð1‰Éœ¬‡˜œÖÛ4qåçäöm}uç;>ͬO¼òéçØÙÛÝ4EŠÛ +zê¶_/ m““¾ñ·7þcÛRìѺ"ÜÖ#~ÝU·‚G~IíÄZkáÈ1µÙD«}·}±íE½}žíÃÍoF#1¸0Ÿakà£Çh«01nݺÉSïxœ\ÏÁ¯~˜áuÉMýÏéL˜%dÃoƒÈ—: ×ø®ïúæöùæW¼ïçþÈkä.zÿXÂHä´h^^š–yêcŸn¥ÔÛ4¶t¹W&2T'DsçMêÐ!¢-,„ô½¯Uoß’LüÍIÉ}ey4¥Ëþþ_Ç{BŸ¼‡tÄÌ\­™”$FÎËõ„éléM±J ”¡½©Ó¹ü$ÃHÞ•Ò‘ú.Ô¡g:ºNIÉÕD­™ùb'bS£ybP6r哨°Ê°ºåï)ªBî+ðâüùÇø7¾þ«øÉŸüñoþ…ü¹ÿÃçìNáÁLyê©ÿ ³éiø‚;`8rxÿ/üþö÷|ï·½üâÕKbkü‹`Kò™˜í,ÞÿWºÄƒð¸­.·ãþd:ÊA¬]SJM¯¨|Åw?øÀít¼JòøãûòÒ‹gxõ¥3<þøu'¼úêYºnà©§^áêÕrç1…” —/Ÿaµšóà}×ÈóŠ˜Ï—¬V=/½ò_ò‡~ƒë7α:šc’ØÛ¹Ê³/|³n`oï€Bf>Y’û5{{·8¼}–b‰W^|Œw>õQžþÄS¤dÜÿÀ+¬×s.Ýÿ*}g”Ò¡û×/b$j.\¸ÆÕ×.ñÚµ‡xàþ—yì±—¹þÚ%nî0Û=KÏï­úO|âÚßH9I}Ía¹#^q“2¬Óû/\|ê‡ÏìwçÎ¥ç^ºDŸ/É‹ÏÿÀ䉷}ÁÿÇáÛþÅ…ûÏ R¸³JDzžþ<¾-¿öáþº©÷Xµ2™-xöéçþb­ú7Ÿ{æéå%盈¨‰t–s.óùñóé<“3R«»š93ézR2Ö˺¬GÛT¸šÕRçÏN'ë®”$óÅZVËŽõzÂb> Ö« š ‹ù’õ:®Iˆ­Y/;ŠeúÉæ1ú$J)°^ÍØ;wƒõ2Sjз¬Y­f$Qº.^$! Ò§J©=†±ZÎØÝ½ÍÑÑ’ŒùlE:úÙ ‘ŒVoì COê4#i ”)V{R¿¤ïÌzjõz®.WIº^õOö]ö÷AÐâ8FßõÌæ3ÌÄû ¹ïésGÖ ¼–dÕõ½ÉÑ2!¶àæõ—»Ý½³÷¿ýmoûÀÙûÎ}Õëâ:ã"rîxîéçɹ;)?ó³?ýúõoίÏ‹÷Â…‹?¸··Ë‡ýÃLgNç6©J)“ò”—_y…ýût©#ga¨Ëåšù|Êão};“®c¹<ŽzÉ–X Äûtoõ1j«îŒ¯¡¢ê¥ÖÞØuN5;¥*†¿jqÐ4ÔêZã-¬n„ä$lÜ·^¡dHÎÛ‹y>¡YàŒèFd4qcR‘ Z;$9똲3î*Þy,YÂf³)µÏ>ó «Õ’œYàhXa–xôчyì±·p¸Ûí»“¨´Òöã£#Þöö·qpóæ?><:þ³¯{œà/ïê{>ý©O1NO‚ÀõpŠ ½T«.¦3ýÁó.Òõ=»;g™ï̜܉Ývwöø™Ÿýin¼úßòmßÂçÁÆœ¼ôü üÈü0ß÷½ßÃwÿõ¿Îr¹öì·n*¶ 4=L`*Ÿ@{ͪÇÞÓˆ-l ¦àqö=…Z§ŽˆjŽ/Æâ}‚›<’’49oÒÀ’¨L¹PA0©…:œh9‡ñ»Š ªwfç?eŽ\¥ë2¹›ð=ëoòÇ¿þëø†où&öÎo˜Ù_þÀ?çïüOßË£o{;ßô­ßÊ7NuUXí,yè‘GQÓ?sx´üzyï6súDÈ9óS?õSœ9{ö¤øÑý±× €™2™Nþë /~÷»¾â]|èW?ÄÏÿüû9wþ\¬*ߺÎ+z®\yéŒùΜÃãcT+e=pëÖ?ö0{;» Õ»‰ú;€q)•.÷d3–Ñ <%õÕ!FžL©e@‡êÄ–JbŠP“±*ñ"Küe¯¹ïY×5µTW0îR´{†âü|$ÿt)Ñu†¡ êïý­ÅQûÈF^—ˆ¿Ì‚Hf™tµV´2éâÄFÊ=)á}‰­’¥‹J±D— jÝʈOLæ VË#^~õeÎììÒO;´xµòÁÁMæ; {ô †a=ËÖX´¥nÝ<àk¿îë¸pñ"¿þëþ-õÝȉÒD„ÉtÊùóçùŠ/ûÒ“à´Êh™­&ò—~ô>ñô'ùʯ|9e‹ÅÆKj0¦Ó)×®_3{gxäá· ZÙÝ™qûè˜åñ!Ï?ÿižxòIrJˆd–LJôÓ¯]~5ãÑÇ¡%§ÌáÑ)u¼ð³¼õ‰'ÉIèûž££¹®^¹‚©òÐC1›Í©(û·_|‰·<ö»{;Lû¯Ý¸B’Ž×®A2î¿ð{{»¬‡57ÈðÒKWxä‘È“ÌÞ|ëû7ÈÀÁÁmŽWÇ<üàÃô³ž¾ë¸~í’W.¿Â}÷ÝÇd¾àìÞnîßDµrëÖ!ËÕ!=ø0"ÆÞÞYn\{¢ÊññŠsçÏ ’ÉIX-Ñ ×®ò–ÇgX¦‹9“”¸¾“Ro°Ž7˜®V^=ŸÍ#{Z8^®˜Íf|è×>ÌÞÞ™?zs?x¦“—ª¿êNAC^§TõËç“Ý‹>ò(ù;¿ Þò–·óë3M¼Þ2³^¯yð¡É)‘3ä.síêuRÊtÝ„û|€ÙtŠQÉ]GJ; ÃÀ¹sç1¾›bæ³ÖäœÇcRøÁçÏáÖámΞ;OJÂ|¾Ëáòˆõòˆù|ˆpÿý—˜ïìƛטN&t¹CÏED˜íÌ8<>d(³¹¿ÕäÒ¥ Ìç R—¹yp“iß#)³{VXÔvövXs{¹d1_`bÜwñgv÷è'SnÞ8€ Ó~Jvv,væ”uaŸ<™Ò9÷L¦ ´TÖe`:õ—JzSc6é9<8ä¨3泞ÕJI{g™]šÒåžõ°â•—_å‰'ßÊP fF-•gŸ}–÷¾÷½üéoüF~õCúöißÿýÓóTkåøø˜_ÿÍœ€Ål~JŒbå¿9{æ,û·ù‘þ!î»ï"9ç×i —W«óÙŒœ2Ë£5·¯ò¶w¾ ç/0¨÷Á}¤ë8ØßçÚþ5>÷ŸÇáámj)äIGî:ž{æY.ž;Ë…ûN˜HÇÃ>ÄíÃÛ¼|ù>÷©§ (“iOßw¤”ùôó/pöüYî?‘ó÷G$qýúuŽ—\»~•Gy„ݳ{0üí]Œ%ÇußUÕÝ÷s¾ggfg?¸»$EY‰"eÓ”[Eò Àö«óä!~rÞ A$yD²#@KŒˆØP(Ù±eË-F É%¹ÜOîÎ~Ì̹_Ý]]'UuoßË;+RöK@0S÷vU÷íª:uêÔ©ÿ9§¢w|Dª2nÝy—•µU6;K¬­.³¿¿Ï©Ma0qpxÈųgÑ™÷ëwÐëÑm·¹uë+«klvÚ4Ûm÷ÙÜØ`<s°¿Ï…K—iƒÞñÎÂÝûwYZYåüö6Î:²V“{û÷±ÃœÄh¶·vI³ “¦õzŒ†CŽŽ8sn—åÎv‹ë·na²”½[w(\A–5H)£á˜¬Aô–IDAT‘z/«‰¡™eüÏoþ~ù—eÌ?A©÷€ˆç ‡½Þ,艹´D¨\âœú¥ œç¿ÿþïqÿþ}Ο¿à|€Öšbb¹µLUX2“xÇ•b˜1iŠR†õSkìííá¬òQ¼‹í IRŽú4²U@Þ(£)ò’¥®cp< Mò<ÇhƒÅ (P…bmu…Ýî=¸G–eØ"G/µ9ê²³½KïÀCáu’0 É‹œ$I1.àʵ«<ÿÜÏá*¸yý•«è´Û¼óÎ {=>ûü îÓÏû(¥I2Å»ïÞâì™Ó´Û+¼ûîmY“¼*Ø»»Çáþ>ÍFƒãÁ±ß98‹T+ŽN³É­Û·èvÛôíFš‘K­ …ðúþ/O}ò§ ‡#D[;;¼ñÆ Ë««ìß¿Ïh<¤ÕnSŠåÕW_E|òSOSÚ‚kׯ±¼¼„—ߺ NóøÇžàö[h•²±¾ÁQÀÛ—_'M3žyæŽú=Æ£ãñ˜,M¹þî-v·wØØÜD©&i–’¥)­Vƒ;÷~è… Ì'YFžyéÛßâ~áó¼þúkÿèpÿàïÏsl…×ÑÌì~û·ÿó T"Å“O>™Zkyá³Ï³¹¹I{.øÃ PŠ£ã>Ýn‡££C†Ã‚¢ó̳ϰÔ^bes•î{{÷¸yó:7oÜäÙgŸa<Óî´(JK§Ùä;ô¿Ù9½ÃÙ³çp®¢ÝnS–%ýã>?øËWxþùç9´AUYÍ&/ÿÅˬo­sé£,·Ûܸ}›v£Åp<ä­+WøôÓŸ¤ß°º¾L4Æå–×^û.\b}sápÈêê*‡Göö¹sû]žû¹çqNÈÒ”½»{“ðÊ+ßç±Ç.±¹µÍR«Íh<äøxÈþáׯ]ã _øE”@Ölróæu”JøÑ~ÈÖö—.^bue•ƒ£})†%¯üàû¼øâß"MÊÒrjçׯ]g8’¦W޾̙3çXߨ MSÆ£1Çý#Æ£1wïÝc4Ól6èt:¤ê„7nð¥¿ó%¾úþ#/}ë[Ø¢Pzˆ`†¾ò•¯N+9÷ÙîÚÊýÍÏý<ÿú_ýKþýoý&»»»‹×þ Ñ@>Òl·é,u9öo¿ý&IÖ K2î?¸OYt;mšÍ.¥ÍÙ9µÅƒýCPÂQÿˆfÖÄ(C£Õ¢ÝnÑ;<¤´ƒá±×Ÿ[Û§9>>Ä–%"Ðï÷'ll®ã\E™—˜¬‰1>¼|‘ç,u»Xç(Ê­5©I$IFš5¨\‰- ’$ÃU޼ÈYZZ¡×Ûg0²¶¶F£Ñ Ón“$)û䥥ß;äÔé]Ê"çÂÅG¸óîmŠ¢bÿà>N›NgWlomsïä°wÈ™3”UA³Õôy%õpÎÑétÙÞ:JqóæMŒIÈ‹1Íf‹sgÏrppÀxf8ò篼Â[o½E‘çŸÓJÿqPœL_ûo¿ëØ»w÷›Û§w¿ø±ÇçSã§Oô“ÒéíÓ8|`†Êùˆ`÷î?˜–ïîRYKÊ+[q||Àæ© ŠQ‰‡­ìDh8µyŠQ1ò†¢ÊP–å´lk[äùDIЖ-¼†½x{€«üÖ*"…upC«µæðÐ#¥5pjg‹Ñ° r%ˆP•–qQ°¶¾Ž³>hQUd&¥Û²±I97G¶ªÈ‹‚õõ ¬-QJùŽÖôûÖV×±UA0õA Ûí ÑäEîÑOZ3.vÆðÏþù¿às?ÿ7®Þø¯{{·u*ãMÓŒ `’$ný’f³õE¥ÖZ~íïý÷ïïÓl6)Ë’Á`€I¦Û@ ¿JßÈè¶W¥Y’bÒgKŠ<÷j_J />J£Ñ¤ªJÊ"ZˆµJkiƒÒ–”Eáãë(¨¦‘5ç(ò‚þhHUæM­&( RñÄ®‚»ùhKA€¦ýîäDZYša²Œr<¦°ËK]T€¯ë$¡‘$ŒC[`­™Ép8Æe€=þÈ×hCÚhPŒFñm¼L‘¥^ñSV%Ñ;³íÐ&¥ÈÇTλÖQAWš¤©Ùäk-Ýn—V«ÅñÑ1OúYʼ¤wÔû­õ¯j5Ÿ'ÀKß~ ç/^üíî (Š‚û•¯Òl40@¯?àúÕë$4`ö¢ž4øEÕ©LU¨Â@U;×à>{ÅDš†Ø*êÆ$ ˜:a’@4 ”×¢y'U>Fà8s°ÈÅó0. ïC—[ :€ð¤N„E/ÔÞ>Q¨ùÿÑ€=µ„£¢`ÿ`Ÿí­-ªz"]kˆad&~ Õ#¡Äcÿx"êbI8 g!Ä{BâIj…Õº¨F¹Œòœ3§O³¾²Œo¼ù—ß|“v»ÍÑÁþL’üáü>« Ô޼ ÿ4k&$I‚u–w®¼@–eô¸}ëÆb70‹“Ìdï¹î&VñšL‰¦Ž“Z™DI‘ˆc0<æŠf§…$zÚQÑÈTy–5ñS†èJ@Ž* )ÞA•1†V«Å_}•»wï†-s­3Ã@ÌkÞf·_Šú·ÙÉX+Sï)„ 1œÆãqÐKlcmAQdiB#ËQÿ°þP«Ùw˜!€g?õ4/¿üýOcV1c0:Á9ÿV)í:hq†šN@³(˜ÌÙ$Ó¶©ÚlòçDk™:ÞÇ~ÆÏ•ÈÂl)¬,¯²²²ÄýûˆáV'£Ø‘š£EØtSp„9f9˜­v›Ý]öööHšV@«~ˆP9ÐJ<ÁEYKé‰ c„•øº5¢œB¾ÿ¤”ÂÞ7qUUã5¯Æº+Ë¿ÔÑZÏå زä⣗þ] ¤:A›„4IN]¼çïÊùÓ7]–1Y3¾'ÒÆ4ÉBzÇ»UõÂ>h«wï½qy®$qpxØ£¬Êš—·ŠhÚAt²¥ò¢¤ÙnzM4T<Æßx'ˆgÅ•sôû}߉"ü ðéøAõVõ Ž—#ЉZ[âê”cw0Å“MûßN.î/ÁË_ÖZ*©¨DHŒ&ILšÒÈ2n\½úeWÉצ>æA¡‰yª´öób<†^…—,Ë“”ò1µ2T¶ôÇ«2ÙZŒÑ”åôLA´ÆCY3”¦i¨çpNÉÝM¬'Ë\À‡W(tðËãÄ2‰6¨à=äÊëosóöÍñ&x­ßϹ´ï.-PVBïÁvÏìR”%N”v>ð*œø1±ÞNMÊþþÎ?Êã÷½¥[d¾cEE)#¸œ™ÆD2ð/£x_˜ž¬f—€‰íóø´š^È‹‚e:~gUúX:¨íušÒîv¿<<îM×Tù3ðñÇ?¾þª×XêvÙØXgu}ÕµUÒ¤ÁÞÝ=’vÊé­Óôzl®¯3}ˆW«Ú²b4±¹µ…µ-‡pÔ;`sû6÷0%“$ìì³±±‰Ø/­ILXJçââ(­#IRo¢x‰µhmpU…Å×5×þèU¢×Ò‰°„wòåLт҆ógw§f– )´80:1Wh­YY[gs}m‚-ð¢ü⤜‰òFúÀ§N Uïí T4†öÃ-¡,/ÞNÖ[0Ið%0±[ˆÿ [ƒÍS›››Tâh43L’ÐnuPA™…¸/÷{ŸL’ä/À׿þ»§>ý3?ËO}â§èvÚl®oÒ^îjÃÕ«o³¾¶ÌÊêÅhÈg>ýæÓ`8äòë—ùÔÓSOáyYðƒW^á3ÏþÌLÝ?ù“?å¹ç>ã¥ïZzí×èvºœ;{Žï~ï{.ìnlYø%Ÿ¨JišÄ¸°ûñK„VÁƒŠö¾Qà´&Ñ‘õëÉDÿà+þâT9°â-‰|:XnwèNñÆë¯óû¿÷õ'Ò4ÀŒ"¨™f_ì´Ûß\]Y!/ýž»(,•³_=‚@åü6ÈOá«kËdY“4Í0F“bH)V‹V£1Œñ˜·FF³Ó"Á &¡™&¤iJÖj¡•5štm¬Ëi·;4šmlU²º²Jå,Í´K«Ýĺ‚N»Ú!§‰AiM#1¨ÄCÒ´I0Ú¤þ€GƒNÀQm &Ñ$Ê ½¢µ'¤ ñfÝÖzE•‹µ‚µ%Îúɶ*©¬¥´–¼´^ÇQyA9.cʼd”)Š‚|œS”ež3. ò<§(JÆå˜rÊó1¹-(G%…ÍɇE™“Þ´¼wt„ˆ„%¸&C¨€0ŽÜGÒ$ñÌ4¡tÄh8ø¼1汈Îîì✜O”ú­¤a¾$•ŸI~Ϫ'ŠŽI ’œóJ5]Žˆ;aÿÁC¤$°TGŸV' Êx«ó2„›wÞ¡“Æœ¨Áù¨œóØ<‰k­ïmN•ÇóÉTú'<;øšŠ‚àåâ}„È“50” p¸AÓ:È+¢G÷µ:ÔQSèDðÁ U£FÃÐéÒ_Ud°`Q-Ê;Rx/cQƉþ†cÃÄyL¤›lŽÑZ“e ¶’ÿ¤µþu±¶_G ÍÀc.òöµ«l®Ÿº°ººô›ÝvçoGK‰1ˆ›„=¢<"4éYN]ÊŽ˜7Bæ¢r#ØÅ „¯\îzmLÐMƒ³h{vnâ 1hÜÔV)TñÏ-$´!aQ× '¯IŒ¦ÁSì¬HÏÚÇö/¢|ÐoþDÅýKè£Ä  Þù·Œ>0D‡:¢ƒ ©‚*ï:gbFÔÙÑFPÇI5iil—#ú0…Gý*þÍ»{ÿøî½ûÃ'}Œ2Ï™1˜µ ˜]‰677ϯ­¯ÿݪ,Ÿ*lq^‰:; šÖI¦!ŒŸI¢”ÑÊ[lˆŠ¶þF‰ˆÚ;ÑšE.vN)1ˆ… |}ñSN‰ÒbD‰Rh¥â"‹ ”2‘Û¥p"ʇÓA‹&%s”Ò¢¢z2òLB´qzPMz3¸Þò3ßÓ‰S5>â9¨xcOJ‘f û!Ì~©ü;zwt•qÞ}$Jň¦âç”Gšz.á!¨þ‘"Î9' \UUZëbuy%?ñÂýsçÏßl5ïØªúƒ7ߺüöÝ?ŸŒé\ èà À›Àj³ÙÜqÎ-Šâ °tBÞÂQD\ã{5^îÕZi­”R ¬i¥•Ò£µÒÞ»T•˜¤2Iâ´RN_Wk£´6J)0ÚˆÖÚx\‚­µöÏÕ·6g¨”6æ­´R>|»7'ÖÆ ƒ®Ö+Ÿ&š§â4ôo®¦¦šá”ÀʼnND|à’ÞU"JœTT•UNHœµÆ9‡uÎà\Yt%¢œs✄Pç*q‚8çpÖâœßd;çJpÖIUU¾Ü9±Î‰³ÖáC1'IÒߨØ8ÜÚÞºÝiw®ôûýw/_¾ü (ŠOŒ@}ÚÚÀRÈ[áZ h¥T¨¥”ɲLÒl6M’$*IÑZcŒj¤ ¥³D'ZK£Ñ0I’ª,K•ÖZ%I"Y–I–e’¦)iš*cŒÊ²Ly.1aÀ•1&‰åI’(h­ÑJãŒÖIš¦""&ÀÖ&Ï÷t¨µ ¾lBSU’$µæÏ´? ¶„H‚ÆPIUUAôqS°á'NB]±Öê²(UQRZë—%뤬J±Ö᜵EQà@ª²[UTÖVÖZ±Ö:k­«ªJEáœs®ª*Š¢¨¬µXk«¢(Ôh4²yž—eYæãñ¸‘¾ÖúØ–¶¢_EÎ4¢Õ{tr'@½¢fêoL3UEÄÉ¡´ÖjuuU¯¬¬¨­­-½±±¡»Ý®nµZªÝnëF£¡;Žn6›ºÑh¨F£‘4 $‰Î²LgY¦’$1išš$ItdÒ45~–k£”RY–éÀT’$Zk-J©Ä³Ö!Ëe`9žPýß>>H,Ÿt`Öíü =ø€…qÜÃ5ÜGÄyÖÅŠ—0çØ•X[I 眳[…¥²Ö†G¸¢(\Y–ÎZëò<—WÖZ;Ýh4âðð° Õ;wäèèÈEa¬ˆØªªÊ§žzÊ}ãßñx<ß`±¯àùV;¦¢3éâ¥K<ñ±©³gÏêÇ\ollèÝívM»ÝÖ­VK×Úh­c Zk•eþ0)°sã-´h­ED*¥” ƒ¦ED))~×@FçœÖZ§áº Ī”ª™.M¯ëÚµ ‹›|XŠÑ'*GkšH±¿œˆ¸ØžxŸˆØÐ>'"Þ^Lüj&"Ö9—ˆˆUJ)ñË„‹¬&fÖZr/ÌUUUU£ÑÈ>xð F®( {åÊÙÞÞ¶""/¾ø"+++'6ê¡BàKf“ñ(†Â0• ž¸"÷¨w~ÌëòCÃ$sßv_¬_ÿ=jŸãŸšËãûÆÆëZ>QÌ1;„Ù„Pg¯¶V>C Lö¸¹2;wÍ[âN#^°œ»nkõ{£ÑÝ{ØX=ý‚F1?ø0UÔ…BjŸëßc}™«S¿>ßé±a‘¨êå±Á ³3fVæòÉŽ±–¿ˆï¯je‘8âµZ°™…m›Oñ}ëèÛ…k8³}'Z(£2|áoýÄPãñe㌪wÎ|cëubŠƒŸQÕò8ƒç¹À¢¿È5Jf×u5w/¼—0ãç:ÔbrŠ›ò¸œÔÖúìf¹Ìr‚ú_µ ·s÷T ê×›Zæß{aú‰ ¾l„tR‡¨¹kõ—³L©µd–}ϳl³ <\øúwj×mQÌ47äóKÃ|§ÏžÏë}0_Yy›Äk,¸w¾ÜÍ•¿ïô `ÁàdžY¶;·Î*ãl×lí{\·Ë¹kõ×çv~çYbýçó“®ÕÛWßùÄk‹þêý1Ïöç×äù%bž0꿳h‰Y´ä¸¹û~lúÀBà€é¬™—ªã÷“gÑ_ýžùçÍöIÏ—¹zñþú,æ!ŸëšîzY½ƒ=s^&©—ŸD4óœ¤ZP6ODõ‰U¿w~ÙeA>“þJB`-ÅFÖ·IõÙ_`‘°X¬E3µN <äu☧yé¾Îæëõçþ¤ï‹"VÕ9…šËç f~†×Ë î™/Ÿ—É/ïIˆœ0û'·3ˆúƒêì_æêÏß_Ï矵èåêDWçB,øþ°÷þ éaÏ«?뤘çB«û°Aœ/«Oº÷ž“ô×Åê?xÒKÏ{¢>)4 ‹®/ÚýöO’æ×ýšNjÇIï¼è}ßoæ¹Þûnû_'ø(ý˜Nš=¥Iúˆ>äé#ø'õѺþáNq€yúˆ>äé#ø§ÿk ަW!ÆIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_pda.png000077500000000000000000000353421217176075400241730ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½yœÇ}øýUu¿~çÜ3 @€à-‚’¢;YIî¹ûn|äÃxäoÁ{îº ¿ÿàƒ¸á¦›pôÈ!t»~|•‚Rœ<‹u;õŸI1÷þ Ã÷{ð¼2\׃[( \.£àyèõºèv{ÛÆÆÇÞàO£_WÏ+æÏ%€AÔ²F°3 CÏó<8® !%„1!P(âQ h6œOBT«UüÍßü-ž}ö”Je0+üò/ÿ2FGGÑévcM(•KŸÇÿéQ_ZÂu×íÆ_ÿõ_Ã÷ì¾î:üÁïý_ØuõÕÇÌÌL<Â%¤T â…è?‡æ úù¬Ì³šó}€HÀqJi@ !´î:„ðQ]¶Öår9÷x.‘UÀÖ*à )%GB €…€ëJ .Ú톆j0JƒD3!Ðh4033‹r¹„(Rˆ”™ëXàJ©„éã'ðô“OB)…/>òE\¶óJ¼ràPavvO=ñ5ÜþŽwbqqa 0$¤4 ’Õ´êg¤Q÷ÒÊ!Bt:-xE®ã‚¤®#„€ã8 !Pp]œ˜9±.–Y³ÙÈ=žKëìPRJ”pRæRB)…áá!\|ñÅpç¤ÊŸ>øð¼Br|qqÝnŠÀ ÂÔÔY˜>vGgN€\{íµh7Z8ï¼sðòþ—á«Q¨pñEbdx½^ D‚›Ñ×êÉê+6ÿÍkÂXÙDZw˜™9#GŽA:’$@! ÇEGÊëgmàé§žÊ=žKR®¯{@J WJHIÒI”7Ï+A)…b±ˆ‚9ÂÉÍ?ݹDBÈD Œ¢0&Íþ™ ÇǦ³ÎÂöÍ[ñʱÃ81;‹æRÃ!4—ô¹dÇ%Ø»o?:ßÉ3,§E¥ŒbÈP qÙˆ L"­@‹E ÆÇÇ¡ÑR8®sÅõ#n²0€Öç!ìûK×”$D,…ºÝ.&&&EfÄ.;J³j€àH‰ÑÑQ|ü>‰Ÿý¹w¢1¿·è¡Ýî Ýéà¶Ÿú)Ütó-8tðªÕ2”â ¨ø¾}ížH+‰ý¶8ylޝS P\n·[RËdb‚ ÝŽ”p\2\ß¾ÏÂà €”p¥ )e¬s8®>æy(½Š4‚²¦áÈ¡£xÇ;>úßñð'ÿ¡bDQ„÷ß{/þŇ>„éã' ”6CÄ£š­²JÊ}³PeÚ$@×Õe}b±ŒÀà8. fb1&c±x&aÃ8€ãhà©™4kê$Êåj,†–{ÒV 1HhyE¬‰Œ Âô‰Ü|ó-¸ùæ[ªŽÐÝÐh¶àû]T*5¢B¨œ²ng¹X°u1 @B+‚½^Í툡ŀù¬óàËÂÆ‰© @A8œ‚ T«C8眭VmGQÂNs!9e;dÐgÍ„”?€ˆ‚.¤ë%È÷{m¸’091VªKfcEöË@ŠC©eT `DA"s @„ A­û8BhS8&±ÎúWˆ€õ}mó H×›ãã£øÚ׿Šï·qá¶qlÛ: (íP -P‘á –&®à =â9]-ÑáQMöåi%€Š”u¨Ï‘XQ†(u-2Ç™@‚ ¤@£ÕÆ‹¯Çvÿî¼ë.ô¤§ ¤ÐJ·ëºpŽü±\#¤vˆ)P*–Ðl·ñŸþêsøâ—[×gØ8°ïGøÉŸØóοD`B‚–Xç¾Ï†€#¥¶…m1 ­[  ÛÆ/¼ý-ø£Oý\vÙe¸îºëàûÚ-kldáÌofNbìºv½¬’¥”J½¯©oîeŸ·ïc_cüöqsã8èv»øÌg>ƒ{ïþuÈø\ÁqÅpb.aÚ\/0ÈŸ²! „vûJ¡ežÁG bÆU;¯¼éMoÂŽ;Ðjµ¬À RȱGQ´¢#%O´e¯±;*{¯¼v£(JÀ>oÊRJÔj5ìÞ½×íÞV Š ÈADî ñë{gÇq`>RH$ R DÜFÎÌÌ Ñh$£À²2F%uòΛcq@š8Ì1)eŠ ìÑm®Ô†9çyºÝ.Nœ8¨×‘€ $) €#(±Š^"à?~ö³ëÖà•W_½óÍo¹®ëÂsHGBÀ°XÇ‘Iš’ïûð}?‰ÓÛ#kH)†aŠ„¹,ÐÔ4'ÒÄEi_DÇÑÏF¼9ç8z½¦§§áû>TÁ-êø‡ "I‚®fÿë(ljÙ_ëw»ïcmÝ«‚ ûÝ™9…|ûÛ@vä"±®”JXµ}Ý ‘œG,6’M+q#Ðl6Q(!À(¥ DÚOÀ‚–µ±ÖpJÑ@Z?[ôF"á8&Üœ«˜¨$SÑtfE‰REQJ±ËŽRû˜á€î\ûÚ ô !ËÆ³ŠžÍ€>÷ ¢eú‰©W¯×Ñh4aTÚ„äüѹ–pÝOþdîñ3Í à +׊û9;úM§g³})k6’Mýìµy¬q%¥Òí:è”æ,J)¸®‹N§ƒÅÅÅôuŽözB”õ?¬svn±AX‰Ñ1DúaóR» QdGgro¢Ôè4HÊS ³¢Âϲqs”2ETv>¡´B¹N ÃPÇúc¢¥Ø“Èfü[~*Â`Sm-ÀXÙ°!°(V …äB°Á°ó,ØrÜfëÙ¤Í,ëÒfžb±ÅMV!5J_†¨×ëèt: ‘šë"iŸGªÖaœÏëE§äØHˆ¢4¢Œü7¿³ÊVèÌolÊSø²úÄò\¾åŠ¥Ñ)$£?Š"ÔëuÔëõ¾Ü 1Š" pÄ`²½×¬B^_0È´M€ýhœbÅ60HdŽÄòÍ=“¶,$eý¶‰˜½Î›øºÝ.†f÷1‘ÙŠ¬)°ÊAÕÏ7Z?|À _š¡úÀŒ B"˜A$„0È.6‚—µo)“yvü ë̵YÃKKKð}?å02†!„ ((€ÒϽ¾ê_ÜÆkRôã¬úwl3Ð <ÏÔ–³z[#Ï“ñöu¶U•åÆÜ4£Ø6?³`ˆÈä fÅ‹¹R R ræ\ĉ«ëì€Í=zÆ @[<ÜÏ£Ï> ´ü4ŸìÈ[ɤmzfN¼m'ã$Y™oêgëWq½^G«ÕÐ'Jc˜6}ߟG$¹Á{Ò/ëH§(Ö3-|¥—¤t¢…¥ü­¤äåÞ)£ùgerê‰2¦!OHæ¼MXívKKKÉ=ìûØîe!RQœ¸ªß7~ÓÔ³¬¼6E@.pJ°eÖN·aP„pÙÝ3¿lPiPD1ë’R&Î3™ÕNcϺ‹•RÚÌ'-HÄÙC?VV€VãnW¬R:@60±«UmDfËYbúœÃ Þfñ‹‹‹èt: ›Ï³Vtè;Kã6D?{:Ei]à5eèÎa0ÇéS™oO¦ Ã0å ´›§}ö› Ò˜ãyœ$K`Y=À)ÆÞ7rߘ}¦¾…´Û$@‘Ê—° þׇ>ù‰åßx`8! “7£¾Yh¢{ƒl£„™Ñ_(EÑ@¥ma[ƒÄp¥Z­êõzŠsdG¿}_ãW`"¥ß׺¶âëȃk÷°§YÄ`…G³®]YYgIë·‘¯Ìš‘™Íâ±ÏgÁÔíõz‰Ÿß€M Ùô4ÔRz)ëéCšõpѯ)Ü󾻞Û0H^\õ}âÚ è³éfT !’ΔèaBǃFÔ Qn «˜v‚ ÀÂÂÚív<ÃW,ó#ØÊŸ¹.å\2 ËÖ[ÛiÊgš œyàåyôʶ†æO¢]Û;[Ù[ÉåkØó å1ÏýkDzf¡R KKKh4–ϲ5ÈΊÛ©”p+ÅfŠRd°NVÀ½÷¼oÅóæþD BŸgx¢-Ó•µûlÚ„“MúÈ:„NÆME …Â2q”§Dš¶ï¤ÐaY"NÍ5Vè/.qFüÂlˆ'Pƒñ†pê\Ê"²¼<ËuÝ”«Õ {uô½’‚hêh6›‰Ü7\È&"#nY·ag!éßZP@¢ø¦×Ÿ »vðþ{ï9i ҌÏáÒ±Q¤3æ;ÏtËóëç%zØ×ØUÜlD†aˆ……t»Ýd$ÛÏeÇ VâJ©4u'›Nø±±ØÒâoK<ëĈ¾I–Eº ¶`´íl®^žì·Fy#ÏMR§ÉëË#°“qC }+·Äèg bÍÓW3ú 5­4%Kè¯ ÎßËÙsYŽ‘MÉK$äHbf4›ÍD}3š ÙÄ’Ç ì`– ‚Š]¿PÊ"üõUW‚ Sµ"›}YG€¥ƒ:YÀÀJyû漩Ÿ5͹^¯‡ùùù$¾ß÷R¦3Œívó¸AÖ)ÅiÕGD'Áp ^;ä_{íµ«ª·ž@ý²zTXG-9iÛÿY"ÈSäì<¾<ÏœÛÌËZæ³³³èt:©ö²""¯ýeJæy÷lËÁ´“§$¹ñâ¤(=ê”!^S°ZØ Õ³/jçáQò;O ´Gž©c ÃÜsÙ‘jF±=’M|ÿĉÉr®v{Ù‘}*Ü É‚@©T¯Sœ°¨_ Øsz•Œ|ó½\©²Ùð O]^ð&Ë5²f›­ÐI)Ñëõ0;;»ÌÞÏÆ÷mX-7HêH³Gšû ³ ’eÿÿ^èB8–„iW½ ›-ËM§–žM±ë™óöˆˆû~€Ž"ÎÏÏ')ÝæžÙví{ÙúÅJÜÀÜ ÐKÁD0\ECSJ­¸ó®_\ñü†8‚°•k-Ùªm)yËî”9–M±Ù2Ý Ë¬‰Ühè%Û¾‰70¤›áf¤âv H@©åïbu0vý8p¿ÿT1åÛy#À@n̼Ì)c‹ £ôe‰ÌXƒžáT¸¹·V$­WµVÂ[/¿pç]Ïå¯<@C^ø{Vêþ0 ‹ÆdÏ“B‹e̯ÚÈÈæóg3ö¨·‘`F§±÷{½^Š;Ø ϯŸ #ŸŒ$V‰”Z`¦DÕ5wZ£.>58Óà[^±ø'@?' Ml‚–wvv†AN–+i÷«½ˆàÉ̘E½^O•4{g¹1QWà ŒÂ,+Ëq„¥®3ëÄr9ÀÏ­À2Ö~ Í5Ò, ™ ¤“ElgNÖ403íóö¨ÍoŒ"¸°°°ÌÞ–ûN—˜¶R Iôs¡û5øµ¢˜•+×é“Ú§H)îS¡ŠÃeVZ¸qðdC€¾fìÿ|ø¤u6.+X¡O $Ëg%6£Ê& ÿ7 ÃÐÚõ»y³u¤m#s-¹ý¬À±£S+} f±L^c Ï•aÃtc(k“e ýõw$2ÔVÖì$›ÌÌÌ,[%¤ßæò¥ÝóFîZsÛ1¤ÀÈŒu¥³V’¾Ãªúp5066vÒ:¤èÝú $¯Î}?€1³®à¬mm:ÜìÌ‘…¬Ì?ÓÜ ­¼ŠDÑS&bŸ^c°ÝjŸ´ÎéèûÂS)a*v‹”6m{çìN6¿í¤ÎA`ûÎ$7Èr-¥ØJ‡„ÉâX%\þo,-´ÎƉŀ0ok\«ý$yƒã¿Ï HìýÕÀFpƒ4(h6™¦DfbÜÚQ‰üE2lؘÙÁ&DÈèftdE@rÞ’©J)?~ü”Û?“ÜÀ(‚:g@ í,¤>Á'׬ƭ¼A±½u ˆÓkç’i‚¶»×\“T‹GW^Z×jáLrƒ>H½6œÑuXA+B¼æ¢÷´ `½u€äþ ¶ågÖ@ ÈÎç3©]FíöÉ•œ“Ázsƒ4Rï”^5 XÙCní:?Ïy–… K K¿h_ˆTi?¿m½^/µ#׫…µäJéGÙø&*³*(%v~o]ymyovŸäÜ:kØÞ)ƒ ‹ØóL® qd˜BàĉëòQz§0ˆÝnAàóŸÿ<ˆø=õñ¾Qj¶èk"#hbX+BÐ{iäA! ›·lÁKûãg~úv( ×> · “]DÌ(I"èqf °×²¦iȵˆÌIƒ¸Œc&U5•Ä·Ò[¡?ç`?kr3¾õ¯cËÙÛ ]‰( !D¿ûy9À}÷}çŸþIë–Ø'„v:—gÀ˜! …"¶ž½ nÁÃÁƒP­¸p¨? dˆ–Æ…dœêýE,=\[±½¥•Ë8— BéË"ôJ%ñqkK 0ÇÄÁQ"»mÉÙk°!#Öçzp„ j£Ó;†…f““›pîöí˜[XÄØè(TÔÏ\ äßw߇N©þ«²>þ±‡ÿô·N-Yõ_šYoÂxÃM7â‹_ü"žùÖ³˜Ú4 2lÕfÊ*sºœøÚc„'¦&±ev*€(Ôš“hìÆ¶úMq?faQ€Bâ>ËWlkó¶BÇ ’h·;XœŸÇÏÜþv,-5ù!ˆâ­²žá4©à¾ûþÕi]·&fà'>þÐéA&'°Ûíbqq·Þz+æ*3ÕZòþl"ûFžsgR”µ-,ÎÁ 6sD&5-¡©˜s˜{'mZ•RϬg!"Ž022ŒãÇOàØ±ilݺ‰¨‰W‰8?Ðý+ þOþäONzýšùN‡ç/÷sÚíöíÛ‹R©@0 !ÆIDÉŒ"29v²"m®R¬âß¶(1ϰn޹€"(²Ê€IdÔ„‘”“gÊºŽæ4„Ã‡Ž ( &ͤ+ÃܾÕÂý÷¯<êo¹å<úè£+ÖYSGÐ'>nDÂW¬×±ýð~l]Æ._ÊéÔ|ÖŸW¶‘š[ÖxÕz‚)ÇÑH¦ bkD./Ç#Ý”óžÕ:&¤@È,¦L¼¿TÊj­€î¿oUõNFë25ìÿ˜fg>šÝqj—ŒXÌBý!ЉHËJ"ÝÙDšµ@l•‰âQÅI™rÊl—AdË¢_,ÀB@ˆAe‘.ŸäC¬ÛïOˆÑ%2}£»fÅÏ÷ß·jä¸å–[ž[·¹ƒ¶*MQ*ð¤˜Àl¦ze1=;Ø6—˜¬2C#Ÿ))cY™ ƒX€A˜µ»A'± CL™2§ÊH—ãéÏLsE*¾ŸÕlVüvìЮ]W€¥ ™ @J=‹¶V«abb­f ‘Š044„ùùEÔë‹9„`éJŒM ä±P_@u¢ ÅÀ̉„a€ƒ©É);v ç ½IDATÿë/ý.¾dn¸é¦þÊ#D(:! õJŽ+±ïŽxÏwâ¿õ›¸ûž{ðò¾„Ïó0>6?ðÑmwQ«M¢Ýncaq !û ¤p144„r¥„úb…bžWÂÜì,:68ÔÈ'"h3±A$£pP÷­)"8`;ÖõX'‚”j#CØ´å,ÔjC`Vèv» ’Ÿ†$‰ßýíßÁW¿ö5„A€+.¿ÿòCÿSSS8qbB[ÎÞ‚§¿ñ |êSŸB¯ÛC„¸ë—îÂïøYÌÌÎÁutlþžßø ì¼ú*\|ñ%xæÙçÒqA`œÞv;~­V‘RÛ6mÆoÜ{/>öàC¸ìÒËñÆÝ×aia ÅJŸù‹O'Aª©‰ ¼ïÿ^wñŘ>> `rb‡^yüÇŒééi¨ À7¿¿øž÷À•æ‚HI ’ª¡R©`qan¡!º.à÷ÿw×1·Ür˺@^ØÅNœ'¿ÛÁ±¥E;rß|ò)\~ùå¸íg~…BµZ ½Nw½ûÝðãñǃëðž_|n¾ùV<òßÁÄÄŠ…"¾ø7_ÄûîyþÕ}÷ã¸OûiÜù®;ñÝï|ù߆ëð™OõVS[ÐjµqÑEé¨c» Çh´z¨ ¡R©Â+zR Ón£Õnãªë®Åßúnxë[xÿ½øòã_Åú/ÿo¸æjÜÿýxÇÛoÇgÿý¿ÇU×\…(RøÁ÷¾‡÷¾÷½xç»Þ…ÿçsÿõz·Þ|3ž}öy<øñ‡Pî´*`||Ï~ûY<þåÿsó ý^±ßï-ï·>¬`'œÈøÃË~ä#9•{Pæ“=n–ĦíÛ·³âš7^û†Û¶mÛŠ7\} ¼¼/¼°``Ç¥; „ħÿâ/°wÿËØyÕN0€Å…E0/üðE9|o¿ýv9zŸüÄ'ñ¿\=Fdž±ç…=˜_XÀŽK/Å#ûvíÚ‰mÛ¶áÿþÓ?C/ŒðÖ›nĦM“h4š¨xE\ºcÎ;ï\l?g+&'&±uëf´uø½çž{¦¦¦0;?‹çŸyïúùwáÛßz_ýú“x÷»·Ür —^v9öxO|åËø©Ÿ¾ àá?~—ök¿ŠçŸ{{öü»®y¾üøã({.¹ôrH—0?;‡¿üüçÑítñæ7¿c££ Z­æó=ôгûÍê×l¿jx5V@ÞÄ‹LY¢¯oHÇqQ.UpÖæÍxåå—ñöwÜ?ÒÉž­V½n›ÏÞ‚íÛÏà ×߀ÉÉIlš˜ÂÔÔõ:­Ž>‚Ë®¼Ï~ûÛxî™g±ÿ~?z=ö.Ýy%öíÝh´šh5›xøá‡ñï~‡öï÷߆·ýô­è´ÚøÂ_~ú"ÞvëÛðsw¼‡Äž={ð§ö§p„ é¸8|ðêõ:vÿÜçðÕx ‹ øÝ| óØvîù8vì(¦§§±ã²ËÐëöð…Ï_ûÊ—ñÍo}_yü°óª«qbfaè£äU°wï^üæoý&9‚ɉ Á󌎣»¸ˆ¥ÅE(¼‚‡/¿?qÎöí…ï‡( IÆ?þÉ7âàýزe FGDZëê7àø‰¼åMoF§ÓE¨"\sõëñèßýì¾v7Þüæ7c÷îÝXXXÂÙ›7ãüsÏÅ¡ÃGàu ¸æ ×âßþùŸ£\)ã…ï¿€v»‰ÅÅ%´[-É@1ÆA¼‚Næ â•õÛFüª òR˜­”ì•XMvÄË Öo‹öW^ùO®Ë -¸FGFpáEáú®Çøø8Ž?ŽécÇá غm¾úÕ¯¢R© X,¡Ýlà²Ë/G½ÑD³YGF8ÿ¼óÐí´ñ½¼€©©)t»] U«8kË&>t¥r¾Œ}è~|êá‡qî¹ç`aqGC«ÞIr¹ŒN×GàwQ.W°e딼"FFFð+¿ò^\xî9øõ»ïF«ÙÄù^ˆï<ÿ,:&7Ma~v¿îuh5Z813VŒÉMS˜ÓO>…­[·"Œ"8ؾý<¼ô£—Ðiuà¸.®¼r'¦¦&ðØ?ü=ö|ÿ‡É†•‡ùÂ_ýÕ_Þ†¡#Ýþ¨œA á Y„®H+q€•F}òóïd>ÒqËÕ**¥^wéìÜu%*•Z­T¨Ðõ},5ëèù]\sÍU )€P'T?~vWÇÑ Ø³g&§&qÍ5W'û 4 ¼øâ~bÛÖsðöÛ~öoþø‰‡ Ç$ÊÅ*¤# ˆðÔOàu;v`xx~èC’ÄØØ(þâÓŸ±Âmo¿ ívõFÏ=ûmlÞ²Õr Âèð(Ž=†F£®óû˜qäð+X\XÄëwîDÁu¡c©¹„ï}ç»P aaaaµ¡2®Þõ”¼ žÿÎ÷P¯/bzfFF‘²9@#ß|n`ÖÕ7œÁNVÌŠ…D0ˆVƒ|C!uʬ£”rˆÈà‘Ÿw™ÙUJ3{Q Û%Ô—1wbC•<ÏC¨BDQ€( Ñj¶ñâˆ0ÎëBè½wí•ãèñã8rèpb”˜† aàãçßý.<þøãø??ü¼ÿýïDž矛¼Ø-o»ÕJ%ùíû>þí§?‹ï÷»¸ûî_G¥VE£±ˆ0ŒÀ`Ø·A&^Kí®&pÆî`‰z} ós³ˆ"! ®ã¤B©cÝn³³ó˜ŸŸC»Õ@àð}¿ •˜…C:&`æz@…D13)¥(>NR¬³ûœœV£¢x™+)¥Ú.„‚™eŒp Àaf× ž™ \¥” @*ýÔN2ߟH)˜Ç×–A¤;Ž@ŽTPJ@)†î“<Ñ´èÜèd¥pcGˆ $êÁ›Þô¼ñºëðÃïÇÂÎ]»àºeÏCÏ÷¡"ÆðòËûqî¶Í¸fç?A«ÝÆâÒ8ÐË:2€+œ$CˆYÃþÐàxÒGìæ†ÐKÀ(ŠD "Œ—ÊgÒ×3C)=ÍÌ+x®ëº^E)ed!>`mA…¤A0sDDE‘ùFEÌI†êɉ`PzJ) Ïó¨\. ""fÖ­ !”RR)%…’™S£=þ.Ø„ ¥ÝNçH†Êu\¡¢zá<³5L€0Œ „æl©’äñ³!W«œ!°N*ûÑK?B¥VÁÔYSètºxꉯ#Â>ç R¹ˆáZ½ Àñ™ØQI.qüßè]qSl7ÈI /É0TÊz6½á”Žˆ†I&±R*Y;hiiqAAŽãx®ë†Ì, N,Ô°™{(¥4½™ ‚@ø¾¯Ìl$ ñˈ EYäW«U Q©T¢xŠI)…RÊ6í¤R*áqÙ±")GQä.,ÌÿpqqñHyKe˜¡Å£…b.ÀP*BFÚ%§z›$Òåéc"Mö;«xU‘:ÁöJ]Jg1Z&éÝÍd<თUÆ´Û°ÂÏýH/#"S_ÿÖ\Ììx¯ t([@@©(8tèàã¥R©Z*•<ƒ"RBˆ$ŽbÀ"Ž9K)!H'Ù.òJ‹i cccؾ};ef¿$z ‚™“Oü[ÆeŠ¿%Ç{Â3³ÓívÛ?zñÅOŽŽþvEž”BHH)áy‹Å˜ ½‚œÎÐŒSÈ,R÷(ÎãNçéA â)ç``À›Ã-²YxœBn*yt×É-gm1MD„R©ŒbуpœxÉ.>xðài·›{¶lÙR‘R*"’DÅxRB¥q,ÍhÐú—ÐÌ9á΋YÚºu+ÿèG?¢éééÕë›7oÆE]„R©„J¥ÂaRÜ™ K1‚ 1À”pX©T6L•JK‹‹8xèz½ž5 +Ëþ ÞòX™}W3dV§p‘.³šâ:Vrnš‹,¿7T, –…kÌüË3£X‹€(ŠP.—á:KK ?z ûöî_:pàÀ8|øÐÎ>{[©P(Èø¥(Ö³(.[Ò€™4éøœÁOóŽg]'»Œ\tÑE¸à‚ Ðn·áy^2/^)ű802‡•RJaÌšÍ+"R±¹"з uF¬¢r·ç_P(x^­V™­VkÇ¥”2 Cn·ÛEФŒ{Ï^FŽU²Æ¸éc3EJÄ)Þ þü,2Ôžpãx$Ú£€’ÙB Èþ‹‰¡¡Ç»àøÚä|,"–µ“‘lh€9b!¤ªT*\p]ît}1442Þn·‡GÌKé,)Í.#CÂXã7æ^¬±Šñ š¤j6©¨T*‚ÓÓÓØ¹s'žx≾S°iÓ&Üu×]˜žžæ‰‰ (¥¨V«±ëº$ô.,„`×u•‘ë1DñÛQ:í6Š¥*ÕJ¼;  (B§Ó†”®ëÀqƒ€¤#Q©V¸X,BJ‰B¡€r©„( …„ ¸X*Âu]öý33׆†˜s\«Õ”‚5ë—*³Š™£x‘©N¡PèÆØTF—Š Âh *öøqEÆ"c"‚çy\(Rš`  077Ç“““ÃЬ‡ËŽãd½O)¥„”’LüÀÀAÂïõˆQ*— €(ëoBP­V#ß÷E†3t»]H)ixt˜×!!ü^`¦b©„R±Hzo‚Ô÷€µjõFåJ‚´²ÖíöàûöÊUÊPŠÑl¶4Ñt"NÁqÐíöP)—4’=ý ÐÊ¡[€Wô¸×óá\”ËeŽ•Jö¼"‚ PÅXñ ÃAÀCCÃLz:”ªT*Üj¶T¥\ån§Ã=ßü à2ÃBô„éiR‰n#™c—33»®«õ)Ùè)«Eþj Øqššš‚1¥”S,Å7Þ?Ž-³WAÆ-D0Œ×)¨V«Q¹XBJ2Ær¥B^±HÝn—Â0"¥Õj•&&&ÈqŠïK#cc¨ôz‚€@:££#(‹ˆ‰#£#=߇p]ˆØeªX8^×f×rNÜdaÂu$FÇÆ˜„€#%ÆÇÇÑëöà>‚0`"`rb‚x0àZ­Š¢çqÏïq¯×3s¥RaÏó8F*ƒÀRJå ¨V«Éa¤XÉЦ^`¾mœKÆÂ2¦ªQúE\×µó“©ä²eßs‚ÐtCF €™MýÄ] "~!I!HPhH|ÌLŽãP­Vëûú÷5f(€W,Â+–È(ܹnŒ´Ñ±1ø¾Of'RÓyý§Ø5†œV0e¥Ïó'³^Ü©:qµdo ŽãI?‘z/(MôIllJýC ©RŠ9Fº`CûRJ%¤„t–R0`­Sµ¼ÏSÏiŸw~5ðjgeˆrÎ¥œ¢ÕjEms·R¡à’”Žt ¤ ƒ ‹ËØ÷ZéX¶ "PNª£yF»¾]+E ‘$Áœ{×¼Î7ˆO·–³‘Ï®ë¢T*"‚D—ÀÊÈaË IDATxœì½i´dÅuçû‹ˆsNÎy§šg ª€b @ $$Yš,É–ÜV[“Ûíž¼ÚÏOnÛýÚÏÏí±ŸÕä–[¶Œ’%!a ³”EUTQã­áÖ2oÎgˆˆ÷!Î97ï¥Àîî·V€X+oæ=y2ϰwìá¿ÿ;RXkym¼z‡üß}¯ÿ½ã5x•×àU>^S€WùxM^åã5x•×àU>^S€WùxM^åã5x•×àU>^S€WùxM^åã5x•×àU>^S€WùxM^åã5x•×àU>^S€Wùðþÿø’_„Àã®ÏZ0c-Æ‚1k-ÖÞxÕ•ÿÓ²{E8=5µ!>h±·H乪c±©pŒAç{()ØzÞyQ 'XƒÑc4‰ÖXcÑFc´ÆX›_6mìD½^{1ðýÐ÷Ë_ñ1ü=°èû¬5èDçAY’$ôz½\2¥0Æàû>R*þð÷þ€ïÜy'•j)‰WÒ"¬%èu:|þ‹_ä}üQ†!÷Ý»N«‹ï+¬Ôv×yë[ߊçyDqŒÑ!%Öº Q””i ‘ZœÅ18k•+…Nܽ˜˜h`±ƒÏ“ƒ•J•b±È|«õÎA·{ø(ðwÿÃÒçL `íúÌœÿSÇðLÎÌô°?=“ 3å(‹x^ÀÁ÷3;=ÇÖhŒ(áL¤ÑÚ Üd³œ<˜´Æ¤Á%@ê¬edlŒsÎ9‡0 é÷û ±n†ö<û W\q9«V¯$Ž ‰‰QRâû¾§8zl’cGŽhô}~ôàÜ:q 0tÛ]j#uz6OíxŠ«¯¹š(ŠÂEêB)”Tx…Œ¡1;K¿Ó!ŠB:íƒN×ŧÆP*—)Õë(åQ(©O,G‰Ô*$.xN¢„n¬ñƒ€bP`td„ŽR¥v«õm´ùuàKÿË èdmf"I…1üÿÒq&³>ðI1²ížç!¥äËòÿòÌ3?¡2:J¡TD…À %êHâ/PøA%]Jh’„A¡ã„ P"ð%•f–þ`ÀOžx‚›nº‘Ÿþä'ð<Á`€µ¥|qµ^§R­b i©—G¾bÐíaÔêU ¥A¿ßçØ‘CxJ"U@qy9¿¶£GÒëõ—FúÅ":I˜>y’£ûöÑiµð‚&Š_µ’e+WR^³¤Äó<â^ŸÖüs§N¡a~îGªUVnØÀеk Š%¢hF†¢(¤\*Q¯×‘RÒl4þO­õ à³ÿK `´Y%Åâø•” ÛgXø™R <ó½.bÕ(¥¨V«l¿g;O>ö8k7mà]ù£££A¡½^‡fcž~·K¥Zcdt„b¡H‚¥ßí27;‹CjããÔkuŠ…€8‰èö"æ›sT=gò,ÛWmç–[o!Š¢\YudçÛï÷Y¿aþ¹O‹Üñ—_åЋû1ÆÅòIƒµh Áúµk1Æ <ÉcÇ\jª$A¡H»Ùâ¹§áÄÁC”ë56l9­_ÂÄŠ•kU„Õ.P ¥JIÏÇ“ V3CN=Ê3;vpøù}ÔÇG9û‹¨”ËDƒÆ@·Û#1šR¥Š‚™Ó§Akà‹ÿÓ „X!Ra/Êi_fd€Î°2dÎnn¹W¦Ï?ÿ̉“§¸ù]?ÅHµÊ×~ÿ˜›™ãæ}œ«ßyÅR‰ö\ƒ^»É`¡Mâî«Èî­pPP 6Ù4MÔ:IïËd•çsÝÍ7óÓŸÿ„{oÿ&3S§(V*H) Ã>ý~r½J}t!äþS`‘Hâøžçù™ð‡M÷+Y,z‡Å3<3±YZ$ü8ŽyÓ›ß̃÷ÿÉãÇ™o6±Z#•†v›A¯‹’C¡ß ýÞ€N¿GÅx—Î)¥ò¼¼Õjqòøqjõ:W^uÕ"eÌWJI}t”ÙÓ§ð ûöîåW?÷Y”òè´ÛÊ%0–BP$I IÇ^ôzÎÝyhm˜àÙÇáïï½›kn~ÎÝB¯Õa¾ÑÈ3iAú |ŸBà”ª…RžïãKq&ÐcŒƒÐ6.³¸å£eß®çØ~çl<ÿ|.¼ü z½a8+§ßï{͹Æ÷äPÓ?A´ÑŸªÕgÃh×Ë,Ì|üpÚ5¬$ÃÏ™ßÝrÎ9ü›_ùw|ëοãÔáÃ4|g’‘'nöë˜yoÏóSøÕ¢µ!LѲöÌ ¾çc¥Ë0†(¹ôŠ+¹öº·°yóYt:„xž—_“”’r©ÄéH“Ø„Àóé´:Xk)Š„ýBÁÇ/À’ÄÍÌ^¯G¡T¢6Rå»ùbmxïÏÿR šÓsJ³<¥| Å"åJ‰Î\“ÖÌ §Ÿ ÕœAùE”’+6fãæsXöfÆ&&ò{%¤@[Ö†$Lèv{¬Ù¸‘|î‹Üý7_ãÁï~—«ÞyI½~¥$Ë–¯ ßë­k·Ûh´ùü+É.‡‚¿þõ¿]¶mÛù“›7o.T*•\øÃ3ùL‚  ´ÄÜgÃÁá°kQJQ.—Ñ:¡ÙœG'IŽþÙ´ „yœ¡­Æj‹© ÍSÄ4±Î¬Z >:‚Nç^â˜ÄìöP(xäáGxaï^©XƒH9«5A¡ÀÅ—^ÊÖs·ºkM£v?¸ýþˆ5çláÆÛn£ßéE.Ë€R¥J™$Ž™<|ˆC{v3;Û Óé°lÝzjõ”ç GIbˆã˜^»E»Ù`ùø›6®ç oº’µ7Мo1Ct꾤'ñ‚"÷ßqíN›ëÞýÂÁ Ôê5s &‹“8>8ö¾¼ÿ•àß¼ã϶nÙòsÖZÎ;ï\‚ È…¥”BHù3•$I®ÃQÿÒè?{?{vI}¢ ˆ@’¡§Æè<çÏÔ%¶µô1 Jæj`l‚¶‘¢ZëSÏ÷“ ­DyŠ$I˜k4]4.&ƒb­ÅXWЩ1$Ö ”O½Zå[ñk#üÔ§>I{®A¢µS"A¹D v=µƒç~üc¬R¬Z¿­çocÓÙ)J” Š¥…b€50ßjÒëõh4›ìá G^|‘æé)VMŒsÍÛ¯çüK/e~¾E¯Ý&JŒq¸G©Rá‘»¾ËÌÔ47Þö!zÝÅB?8zèÙÙ\ÿá~ôŒ »€C‡¯ÍêÕ«^‚°ÁK [ÃÝRô/þ°Ï]ªÙ>™ß>“õÈ…nÌ¢è]A¬5 ŸÖbµ,ÖjÒ ](ì,-¥ÀXÆb“ÏS¬Y½šr ¨ Ælª„qcRD¯>Rãó7• ïùÙŸ¡1;‹MÒ"’”FF˜™œdûß}‹ɶKÞÀåW^Á¦õkiµÚÌ5癚ãĉc Eúƒ>N‡·^w…BÀ…Û¶qá¶mÌÍ·ØàE~²ó¾ùÍ;YÿðÃÜòþP!œžA'i "N¸úæ[¹ûë_çÉûïåo¿~§CŒÑlÌ]‹f+ð™@}éK_àþ>ð‰Z­¶©\*±qÃzWÜIýä™A‘B­Qå~ÕÍÜ—*CæodXºªjk²ŠÖ°À‡•%S”aÀ‰%Šu÷!$ZY ç¤Pé„DIéBqŸ$1IâèD’8 ¾tBZè¥:2ÂOûö=÷þìçiÏ·Ñqì”Uê#£ìÞñ$wýíí¬Ür.·¾ÿý\÷–kèµÛÜsßý|ï»wqôÈ${žÛÅó{÷P(˜››ejê$O<ù#Ž:ÌÑ#‡)•+Ö­cÛù[©-_Á³ãÁcÙšµô:bí° «5ç]|)ß»b©ÄèÊ„aH¹Z¦×íŠn»³ú‹.úæ+*ÀöíÛ¦^ÙT)—ظqc>33a/ljb£(ÈÍ-[!ÚÇ2ÁîÙb2{‹Lgîâ˜!ûÌR·2K œÖ,.BcÖ¦¥iƒµÎim¤Çwç'¤@k“+ F`­I©?èvÚ|û/ÿûÂ/!¤$ ŽÀ¡<ê#c<õÈC<úÃxÃÛoà¶}J¡È=Ûïåù}/09y%sŽ=ÄE_ÄŠ«ÁFFGˆ¢ˆb©Ì®]ÏñÔ“OR¡ÛíÑhÎqþ¹ç±õü­œn÷ø‡{ï¥è{¬Ú¼‰A? I¢AÂúÍ›¹ÿÎ;Ùráë ¾6–f£qÖÎ;çâK.Ö,¹ è÷¼EQ§fi›Öú%H`fâ³×Ù¾™²œ)- õ™–`e^^N?sA.± à  µ&ðýEÛ†-…Á™o„µXi‘B"¥ÅZ‰•.áVÊ)"v8~‘H%(Õª|ë+Εo»ÚxV£‹C%¥j™?ÈS?ÎÕ·ÜÊOÝz ÏíÞÅ£=A¹T 6lØÈáC‡8÷Üó¸á7111AµZ¦>:Š'$ð•àäÉìxòI–¯\É 7`~¾É‘Ã?äümçñáÛÞÏöñq}à>Â(dÛeo¤×žÇ¦ò]µš ®¼’Çï¾—ë?ð>¢8¢^¯ã‚Ò`0øðå—U€0†q;¶Oz#•R/%‚¤‚F^¢]b¾Á „"I´+à,)ï›ÅKÑÂü»Ò€P§fo8KÑZ#¬E;–‰Ãö­Á¤`‹ (uJÝr<ŒE[‰µI>ÓA ­AéöÁâÊxvív—+o¸V³áèi@¹ZáÀ®]üèÁxû?ÌÍ7ÞÀ#>Ê3»ž¥Z©¢6ÆÊ ›ôz f“K®¾š¿úÝßåÄÑ#¬X¹šBàS«×iÌÍý# FDaDÅ‹nznúÏÀ¹Ní–‚< ï ŒÑÒ»– )7 3ÁƺRê°r`­s)¹Ò¥‚´Žçï ,¬Aë—¯DZa±¬0îÙšn! ±(!ñ=û¿ó®ºáF¢0ti˜xA@¿ÛåÞïÝÅ›n|'·Üøv}ìq~üãgÉ´ (226Âé©“|çŽÛyæ';95yœ8Uxß÷Á ÎÛvo¹þ:Þõž÷²zÍ:úƒ>Æt°ÆOìØ‰ŠÞv=Q¯Ë?l¿—[?þI”Pn¶ ÚX.¹ö:v>ø·~ü“h«©×ë(©.ø“?þ/Å_øüçÃ2Ì Ž"¢8"IaÈL:eÞ(¥áÆÃf:³J)¬Ö$K"ÿW’†™D¹BdŠ" –¤”ÂXëRµ<дˆÔW[ J W6δkRjgæ­q´-kV RÐHYŒeA[d_êÄÕì½ À±Ã‡ˆ’„׿ñ :óó®V!%•jï~õ/9ë¼ó¸å]7³ï…ý<±c#õz®ðµJ üÍ_ý7àAº½.µzRµB5 ®­‹¡^Ø»—§w>Å_|ùÏùèÇš}ô§)Wª´:ÀR-—yüÉŒó–ëÞÊÌÉSì|ø!®~ç;é¶Û€ ì÷¸à —ñì£1súË–S.Wñ‚ Ôíuo¾7|ÿs™FQœcä{7Š"·-ޱCü2 ùûƒÁ€Á`@† =QDÇÄqL4ô:Žum/#NÃÃø¼ÖÚEuâpþ”ç–D :}ßùxÐ)éÔ)ŽNI¨6}&%à€¥Ì…X›Ç8®no±¸Ø@•§Ž%,€B©Ìއæ²k¯¥xžGÔêUfN§ÕjqÓOýÉ}÷>@­ZM aŠZ}”ùV“ßý¿Áýßÿ¥r‰µë×S­P)–)K‚¥B‘jµÆòåËÙ´~#¥b‘?ÿòŸð+ÿê—é”JE—å(E¹XâÁ‡¦^+óæë߯©“ÇéÌ7)•Kx¾B I±TàÜ /àù§ŸO¢|r¥L’$7/€¹ úÎ ¤B÷<$IPRâ)—Æe^À…nŒ%Ñ Ê:MÖ:Aˆ…¸`©µ°ÖEünf/DðbÑÌ^ȬŽÿ— й€T°Æ¤i_röQ 4I™>wk©¥°Æ::ÒY ãb„ìÔ=OÑn6hLOóÞ‚$ŠÒ”·^á‡ßþÛÞpçoÝÂ÷ÄJžår•A8à~ç·iÌM³jÝgê…ÀÏ‚SëŽ!¤£Š å˜ÉA¹Lµ^eÏžgùOÿá×ø…/ü¥R‰~¯‡‚v¯Ç#ýˆk¯½†][ÏgמàÆ÷¿Ÿvs-,:йàòËùÆŸþ)I¡” Z­a´¹b©,X€8&ŠÝ Í8lRÇCG"–²œUš.YrW „ÌaÖÌ5ä(0D~vß—ºßw ¤TV&udß÷Ó™™b yýÜÃ÷R „°y š}^I…òî¯Òó~OX™»5%”«Ö`‘J9å–•=Ÿ“ÇŽQ­TYÖ&”…€R¥L»Ù ÙlòÆk®fvv†öS­–ð-„Êg8+’Š%´±ááêÎ"ØT',M!—^¨”Eâ”Û±‰‡pŽÔ/ À |Ž>Äë.¹éyxžï̭Ⴧ[¶Œg­gÿƒTªUªÕ •J…Uk×òãOòÜ3ϰbåºÝ.³Íf‹ù¹ÍMfg4çæhÌ5™o¶h4:t¦{´gÛ4ç›4ótÛ=V¯ZÍÎ'ždßÞ=¬\µŠZ­BµV¥P,pðÈ6o:‹RµÊé“')U*|O* A•kW33u#$ ¥ù¿þëõ3*€N‘¯dÈ\’ !ƒ{3Ù“ò¬Á˜«uê3Do«n hcH†™ù#ý¾áª¡û_çß‘ 1IL’ ŒKéœ92yê3ÄÅÏͽµ®™„…F;”çëôýìºÈ®S<åsôÅ\xùem)øŠ…#£cÚû<¯»ô ØÄ03=ÃøØÕj‘‘Š…×÷©Ž'1Ñ &c<IkÀ‘Ú &/>É‘ OpøÜcÚ|„CgæXíDO ¢8$J"bm)•+ÜwÏÝÔªUjÕ:•r‰ÑÑQ¦§¦1&áu—]Α}û\°ç;K¨“„×]|)‡ö>R ?B:NFΨ‰vm\æîÊ®2Oe”òr Ÿ¹ ÷¾Ÿ6Žxž‡ô||ÏwÛ|‰'½E³ß}§GÖY“AÅ™ûB"”û R"/ýœ‘ §¾”®"­ÀZí„jlÚl‘˜aÇZ£ã…L'½M™¹©ö€µÄÆácãcxž Pð(–KXâ+V­d¾Ñ@(ÅH½N¥RfÙòe?:Éä±#T*QHG(+}8±q†µ??÷…_eù•—ê"Nû³z8o¤U$qÌ`0 V¯±ïù½L8Îøøår™Z¥œÒÂúŒŽŒÐïv <7Ó}ß¹¾ñåˈƒÒ—J‰8I^wF0‰kÓZ³²ÐQó²C89œ_“ZŒ¡k1°d–ƒY8ø”QJ™7{¨Œ·—ï#‘*=†]PH—çûX‡ùƒ È„L‹SCAæì‡{4òóRÒmµ(ËŒ/#ð| AJ±Ìülƒ$ŽX»a½þ€J¹D¥Z¡R­²råJöì~6–]_dLͯr¼8ïXËŸý³?à×ÞûoY»é¨ V- ^ÓgÊkRj„a„ÖqZ»0ìÛ»—eË–Q.W©Öê”Ëez.«Ö¬¡T«Ñk·(‹éd§V«ÑtóÉe’dá#ÏcÒ SòŠ—IÓ2¥«SöÞ⪡Í]J®Œi·Ö:,?µ:=,Ëi«—Á‚Ö•òÿ´vB1›¶­ a°&Åc@µ )$Ö<¥R‰‘Ñ:Q”`ƒ€  (P,—ˆ¢ˆ‰ñ ‚BàèÝ¥2'C*Ï!QŒ'\J®Ž(ŽTyìø.î|ñ>~²óoá„E™Ô $s!øÐ®6YÓ]æŠeiZl…äôÔiFÆÆh4H¥|DÇÔÇV!…%‰cj#£ˆ0Â÷ªRÁ/Dƒ%HŒ>çŒ Ç)Ã.ž©™Àœ‰^ô–³B€J B¥7Ù¤Ð8?KƒÈá gwó¤cHÏsT2kÁ¸Ù”uÝW³v]Äy@ê@gÁV ´vOŠõbS¸_I0B¦_䞥Lí’q&‰ã¨ ¡¾R”k5Æ'–AœP(™›kÐëuÙ´yÕjåùøOf•òœ©Hs3üÖÃ_A?ŒØbñ¶BüÍ5Vº8&öcŒtªŽäí+E«Ù R*£”äî' Ü|óM|Ç&1I‚®ãIÊWt[’(AåR‘B!àÿè÷9zøµr‘À °vþfqM"ô tB8Ý$øØÇ ~¸Êë«°~ÆÜ9¨ÔÚ á^k ¥J‘Àw³›6266†’Î"U*U‡3°Øeûï.Ô’ƒkgTmœÙÕCѾ»ÁÉé3ßž>¤Z¤F)öoÜlD ûü0Atéà = yvi§ÍÓX¬IžK?#Skc žt %±¶Xvñfç6Ô§™Y,Õµifa„£¡¹XÆ¢RVÔÒ¡“˜h0 Pð1:¡\®R«0uz €úh£]Û¼ïyè$¦MàtžÄÆ‚RTG‚e…e¬ýåœ{é°v*òñ 6† P@IEl «V¯àøä$Ï=ûÕjÕõgsÅrù%çZ,—ž“ºÁ 9ÍF®ÞZ7ãÌB95ƒMub*AÊ €N1lƒT޽7ds.+©¾95#—dðìj¸¸óÈfùZŠf3©#¶" IDAT^¤@;N)™u7.ØÔ gäå½%h‘çÿžeòÛÀW'¹PžÍô`åÔê#”Ë%ºÝ.o¹þ:jÕ*Ý~—£G3;3 i4;=C}dÔc†NöïÝG}bc QÑï÷¹à¢ ÷ Ë`±0ÙŠn—Ð-Ó Hqm±)ÙdÎÐ.¤s Ä`xd… ldÅ„È ;Y:˜$)ÛWèÔo§”qkH ®Ðƒ« ¸ïMÖZ’4›F§9'™Õw´0-Ü3‘Bmj)â0ä¬sÏã‘{ïeËùç3è°X„R¼î’KyôÁ‡¸ú¦›˜<:I¥Z!Žcöï{µ«×󞼟öîÁZK¹\dÅŠÕèDCAr®<Ó¥÷Êhˆ@,“ˆ¢G%¡®¥b€0±lœ·ßøNNœžâñGàš·¾•Æô4¥J¾÷]nú©÷0ˆbáÀÑÁ Ïìx‚M[ÎFGV‹(ŒŒïùϽŒd‹- a"ÍžHƒ³R dºP’P‹"O§LÃn »ón8 ±Ðèên¿a« ­ÅSJVF¢Óý…Õ$Úá Gw°Õâ)]c12‹ òã°$Ò ­Kÿ$ ‰‘#@&h-Y±z{Ÿ|œÈ˜”/¡‰µaùºµÌœ>™*›œL×.òhÌ7Y¹bùØOóÕ¯|ÅIcŒv$éä¹2æ÷M¸«p™®"Nb¤€w¾ë=ŠEöîyž=»w#¤dåªÕ,¥ÕœC Áªuhµ[˜D#=Å Š9uü$—»$Š™oµhµæçþî[ßšîXpésVr‚Ó#°Úð’4P€52« A¼bQ±'+êdëÙ,VæDžo1ù²/I’`“Ä¥€é µÖë˜$2 ÀX V¡ìK}1†´Êºx{úW&%Péõ¨¬ÌlØpÖ&æ öïym,á`@·ÝÆ+Y¿aÏ>ýcc”Š%.¸àbfg§ùû|ŸÉãǸäoä#Ÿü8‰ÑtÚ=¼À£X,R( JA% (/<Šå"ÅbÉ5£Æ!…BÀÛnº‰e+VsêÔ{w?‡‚gm¦ßí2±|%ÏîØÁƳ6cA·G†H©8°÷yf¦§Ys–ëŠjÌÍÑiwüÕßüõ¢›4„8ÿ˜§=ÖQ¬Ig»YjÇ-` ‰hëb$ùYñGàE!=„Xº”æ%dÏTb@Ú,’V­Q)?À-—u÷gXÓp¦—U3g/¤ÌSJwÞ 7ƒ£aR%2›¤ÍÆ`ƒô`õÆ\*fÒ®§˜Y|bS:Wæ«ì+j‹€££géaŠöËž¬`È`apîü$Îõ„ý^y%ßýêW¹þ=ïÍÐ4á€e«Vrá¥oàá»ïæ²·\ÃôŽ'Y»níN‹#‡ñˆ\{íõ¼þ¢K8Ûù<úÐCÜwï½Lž" £¼…^¤ _¯Õظi—\úª#4æ›ô:s?rĹ:©î¬^·m¿—m_JÒmÏcx~À©S§8°{üì?§×íÐhÌ17;k‚ øÚË*€[“(£Lå8Ö8p'0ÂM7œ–©t¥—v/ Ò}2mI#yÈ3†Üg\ƒôxy‰Xdåf»`â³^0TXr 5éù§‡7¡p\?£SAÇ7.h”V8lAºÆ,Ò`‰®D¾|õFFÇyà®ïò–›o¥Ón#Ìž>ÍÕ7ÞÈžßù¿9´ÿk×näÔ©S\õ¦k8|p?>òR ®ºòMœ}öf>ðÑsã­·²oïó;r”ùÆåR™ARª”)Ukø~ÙF“éÙ½'Ožàر£lܸ‰«Þ|5í¹ë·laÿžÝt›M.¸ürfNO; GÆ*UøÎwX¾n+VqôÅ™:uŠn»{è¯oÿú‹/«Ž£—ä40Gàxžï1ð—Tì”"Ab¸wЗ֖(X”T …¡T¸AöX—¤.$ã!d‰È•"u9Ö`.éVï°Ú`¥Å ‹@#¥‡´#-&q–Ÿ( ÖC¹û\*é ,ž³^Â]ó Ûå­ïy7·ù˼þMor¸„6XÑÇïtøàÏ~Š/ÿ?¿Ã믽Žb1 Õ˜æê«¯ÅÃwîdÃú œuöff§fèôzŒM02¶Œvkž^·Ï|»E«ÝfòÄqÓïuÃóó º­6›ÎÚÌèè8ósÓ¬^»Žn§ËžOðOšF³IØñ¤k›žáéGåÓÿúß2èt™™žaòèQ¬1±Tø0¬]³šjµÂ ÝR"„B @–BÁNãDF³inž’)Eäå+c!QÊ[¨Mg£9•LJ•ƒBYX·J§'%–ì3.ûð„ÄóBeØ(åÖBà¥40”@˜t»T9åË…Û6t©ÿB{;rˆ£ˆe«W±yÛ¹|ç¿U(ë˜8Ši5›”j~æsŸg×ÃkË|«Ã³?~š·¾íí¼óæ[زe+Ö¢$r  “Gqâø ŽMåÄñãLOM#¬åøäfggèu»ô:=¶n»€±±q”°ŒO,ÃhË“÷mçº[ßÒ£3ß& „!ÒW|ïoþš7¼å-,_¹‚¹¹YNŸdzfºo¬ý½WT€Ù¹9ŒµT«•T)(”bªÃUÂÌŸK B¥Lof®jÿ—¹P\6![ˆ ¿±Ž ”-Çj2ç3u!ÀfÀY^1”lf™GÆNÅiÒˆc:å;çŸÏ«C¹Ñrn±;?Ï;Þ÷ŽîÛÏîOâŠÄQLÅÌÍÎ1±f5ÿì¿Àžx”f«C£Óã‡÷ÜÍY6°aÃêUW†×Ælj[ÑÓ$$Æ­r¢”³ºÕJ£ [Ï;Ÿ×]xÅ ô™X±’v«Ëcßÿ×Ýz µ‰ æ¦gè÷û„Q„ôv>öÝV‹kn¾‰N·ÍôÔ‡$‰“¿ýÛ;¾±¨  !ƒˆ( ‡h×zaõK¹¸Â$Ò;žh·‚…˳”ˈÓû–/ˆ4ïZØyQ5ŒIòVoŒ!I»r³Æ®øÇúqïnͬEAÚûë:|,)³8qý ©ß†”càÀŽ— Â…–6­'ÄÖàk͇>óóüÕý!«6l¤V«£­&Žš33L¬\Å¿û­ßäÏ~÷wyá`‹µgŸÃwõ;wrÅ•—3±låR‰(ŒéG²FJ‰ô<„P¬\½–b©Dcf†0ìS(–Y¶j»Ÿ~ÓërëÇ>Bml”¹éY¬1H%)V*ÌœžâÑ»¾Ãg~åß#Œ`vf–cÇŽqêäÉÐWÞ¿<“ð)@&¬EÕ¯ì~Xá`Ö%Ã5Qº’¯HWÅ0it-ò/µ 1[¾-…lÄB6É•" ³u†‡£v·6ñ…+S"g± ”ýŸ?„ÉyCCgdrÂ’k²©K¾bk-ýnek×pý­ïæò_øÜ—~aµ[R@·Õb|Ù2¾ô¿Ïßýõ×øÎ·¿K0±‚#S3¼ýN ¾ÇØØ˜[ÚÍ÷ˆ­NÛ‘h! C’$BII©^gdùJæ§Nóô÷²uÛ6.»ö`-Ýv# JJ‚R‰$޹ë+Á{?ùIV®]G·ÕbêÔI¼ðQýu©Xjþã 0á¦ü1|!Ž51ö%J x¾JýêbÍY ‚/Ŭ•íH.Ø´ë»…ŒAš,P³yºgp«{hcrÉë¢|×?•uÓŒÀ€Í i+°J£ÈK€ÕîkpÝBN¿¤³$žëДÔX)qôK»ÕæÒk®¡ÓœãË¿ñ%~é?þ'dê!ÜÊ¢JÂÇþ3¼ëä{ßü&÷ß÷ ‘[«3Ûê2ßë;ŠxaµÅ ÜâÕ‘<ß' è6›œÚ»å«Vrëm·1±z5½v;ï—ð¥‡_,bå_û×Ý|3\þFâ0bjjŠû÷3yôؼï©ÏEQøròÆò6­].ž$/H€3¬l@*j ,ByžGÖ­»P ²¹RA@†)ŽV©´´k]m”fÆz˜¥<ÏKkõé¢þ(Fg+‰˜´”Œ%1%ÝâÓnÙUrlCXãV167ó®ĵÀ-$îüÒ¶3DVD` ­Fƒkn½•n¿ÏŸþæoò¹/}‰‘‘ý¾[+8 cNOÏ06>ÎÇ?ó>ü©Oóà=w³ãñ'™­¹ÇŽaßó{é÷{¿è×jgôýgP€ ˆ±iPæV¥’FUÓ^¢iqÄÃjÍÇ)J”ËEÆÆÆòvoO)Â(âðÑ£lÚ°·@TH1%\kô#< „ƒCí–ŠBàI©©)úý>+V,g0é‡V¯XÁ ‰“?(`…ëIÆÐhÎa´atlÌñkOH· ˆNÏßÙ0! ØmÌÜ".)H”A…ÑšNsžo»Gð÷ü§ùKüâ—¾Ä9¯»€^³é„½:p=ú×Þt3oºáFN=J«9ÏñÉcÌ7牓˜^·JÕA±ÈØÄVkúaH«ÙÄX÷#B |åQ®ñâó»yâžpó‡nãâ7^I¿Û!ŽŽ=Ês»žã…}{©|àŽï¼ü2ÂgZ-ôaJå2ûöîåѹúê«ñ¼€‘‘GŽ%ŽbªÕ*kÖ­áÁÄZÍ7½“¹¹9ßwpô ?žò‘6Áx,ÄdPrÖC˜nvè>¸5‡æg¼éí70¾j¿÷k¿ÊMïÿ úÙŸÅb {”'‰£˜^o@ ãˆÄ‚ª”Y·ù–G!½~ŸÁ`@¿ßÏ{2Úó󋪪R‚çûËL¢¹ï[ߤyò8ûìçXµi#½^%%‡dïóÏsèÀÆ¿øÅ÷|ìŸx¥ÉŸ‰1)ÔfS"_ÐÐÂgASR®€@*I·ße¤Velt”uë6pìØ1¶oßN’ÄÜß}J%„‹Eî¼óNúý>ßþö·ñ}ŸÛ¿q;ý~Èý÷ßÏîÝ»ˆãc4aEJÅ"«×¬á¡‡`|l„$(hÍÏóÐCFÿðÈcж߳='b ®UkvfŽo|ãv&OœÀó|v=÷,w~ójÕ ÅR.tþø‡§/ Üó}¤¾‡R"G+ÛóMÎ>ï\>üÙ/ðøÃñ+?÷iöþäFGj”Je¤ç;we4q3è÷èµÛÌÏ7i6´ççi7ôº]âìG3²@\¼À£22BP*ñÜOðõ?þCÆFjüóÿã×_µŠA«‹ïûÜÿ"GaçÓOëó+ÿî½ûÄ'Z‹å{æ± ¸kˆãˆ0 1ÚàÉ´‡Nz¨`áƒI’0H;‚{½ý^È÷ôûtº]ºÝ.QÞlÓm·BP(h·ÛLMM1}ú4žïsíµ×Å1Íæ<¼îõlÝz'N§Óéàû>Éè(ïßûøò—ÿ”{îÙŽT *”Ë´Ûó´;-ü‚‹°;ý^Ÿ( SÜÀ-~Q.—Y·v-qìV=眳9zä'§NÓšŸgbbœÁ`€1†‘ÑQ:­Úh*• SS§©T*T«5ÇÅïu¹àu¯'ŒBÀöºøÇ>óó|n¿ÿ[ÿMÏâÝúÛ.½„+–33;‡6–8NR`Í`Ò "ÉÀ1!\ š”¨À'(iLO³ï©ì{æÇ¬\µ’\¿‰n»EàI¼ àùÝ»855Íã>Ê›¯~ó¿¿æ-oy(•íp4gàåå P¯×ÓßöÁaå8Ÿƒ”Hµ˜àl‡s ÐqÂÖsÏ噟ü„Ý{ÜâGëÖ­c÷îÝìß¿ßù]Ïc¤^g×®gY»~=+V¬àìÍ›™<~œ+V „`l| ¥ƒ~r¥B¹\ÆCkŽ?ÀêÕ«)—‹Xåri-##£”Še¤Tìzfë6l +V¬drò8ý^ŸüøÇ\vÙ<ýôÓÌ7[LNåýü÷àÄñã4›Mßãø‰ã [|c-Åb‰#GŽÒjµ(•JŒE4sŒŽ¥ëý“§­qœ4æÙ°y3›¾ð‹¼¸w/ÿõþe,ë6näâ«®bbõjüb‘jm„B©‚×ïáxa+$IÑ›Ÿg¶Ñ`vê4“û÷õú¬Û¸‘}æ3¬Ù¸A@{~Žb±ˆ¯ÏïÙÍìÌ,?ú(çžwî_üû_ýÕßÊdU¼Á+C®ù:ÿù?ÿþƒßûþ÷¯Ý¼i#¿üË¿LµZÅZM©T¦R)§æ4eဣÆ|“N«éLg¡@Øï'š ( „㤀t•P‹1‰ë\I\í!ksµǰˆrá»ÔQJ'$)Å ŒIt )§©£1ž‡N4…R€Â-i´!Žb,¥ü<û‘6eH§¬g•]ÝR/ÖB’R«¥ƒ½É4íYé23q’Ä1•r™m—^ÂEW]…µ†VcŽö| “¸N+é +|E}b9#ãXm}Œ6´ggJP*Uð•â䩼¸ÿañ“O³q㦇~ã·~ó£ÀY)¹6J.$I#¥ô„F‘5mÉE. Žc'1X7Ë‚ €”Šb¡@Pt¿ž1<‚À§Xrx¸TŽ*‡ÀŸb±Èøø8J)â8¡ßàûc|¬xžûµ1«5JW³©|¬Ir¾¾1I »¨\ SÖ¥›…AÊ<’Ö ¥çšALÚ2–þ•¶ r^ SÞÄ“È$]p"ÝiwN &E!ësÄ­) ò{H^•–a,Kuœ u T©P«.`òrˆƒÌµ´›ó®—OüÀÃ÷°Ð˜™ãà¡ét:„aÈs»žåÒK/ýÁ¿ú7ÿúß‚8+ ÃDJ+¥<­u$„ð¬µq’$‰ÖÚ‹ÅÈó¼@‘»‡\ÚíÖàð¡CxÀ£<Ê¥o¸„+Vºµëý3ÿ¼ ïyxþBßf:rHÉÚøq¿¯#ó°µnO«TŽóëÀÖ83í&²Jùÿcõâß F ÓãùÖb¬7t÷ÊZž‹qRÈ3ë;Á[ÂèXBN$9`œJ8·‚éÿ ûÚ—DW‹C¦…¢—H»s|<Å\¤p W(ép%‰Ö´š-fçæ˜9}š~¿’©ÓSŸ<ž|ôc½ýæ[nùË0ŒÎŠ¢(úÖÚð…¡µ6–R%„ˆûý¾‰¢ÈÔëu|ßÇcÄä䤧µfçÎÛ~÷÷~ÿ§Nœ\;::ÂûÞ÷^V®Z‰ÇSS^¾ú„ÑéâÆýžóŸ"S1|­¹,-þäÔLpÂLg~Vø1vɲ)i%oEä ¢¤0¯‰ dÍad!2¸W8žÈæCSxϰ¨þ°ð ›ó=†”b(ÎZtÜS¢ò_(ti´ÊßuTá‚o%ݲ1ƒ0Ì€b! ÝjsâøqÖ¬Y3÷á~äö­[·>×ëõcLècúéëµ¶o­íK)Ã$IB`ày^Çqây^"„H’$1âñÇ&&&Ïó§OŸö¾û½»~ïž{îù”Žãà]·ÞÊÙgo&N¤’i€"1‰ûa‡Á`@oÐOy™ü—ð†`^W•[¢¸E™­E¤½ýÖZ„N "ý¼uAÙâ˜ÿO G"U®Üò.’´Å-ŒtZ¼‚ô§e]Ð)3y.üônÏL¸6n/ªášP‡”Já§ÌùV„HW'>BX„çbªÀ (AØ9uê8ýAH¹\ oxÇ;ö_õ¦7=DƒÁÀ¤‚ïYk;©Ð»@×ÓN¡ôµÖ}ß÷CcLÔëõÂB¡”J¥¸ýöÛ«õzÝóœz(!D{rrò²;ÿ¿ö¾,ÈŽó:ï;çÿÿî¾Ë̃ÁŽ! H€ I ²D”LKŽÓåÈqª²ºRyÒcW*zHòœÅ•ä1o©T¥Û/q9N*ek+U$“”(R*Šâ&lIË,wíþ—sòÐÝ÷Þ‚q’Ç`NÕîÛ·»ï>ßþóŸõ?þáŸþy~øôi°1µ¦ÚuÆêê¢UÕü3sÿ^/Ú,ÑhÊÀë.V2 ùo#}ççªb¼Ùîój=Áûjþ³á;ÿÐÖ¸µhùkOÂüûZÎ-|>“‹÷l¨í#ÜØSiñ¹Ì“Z@ØU„¨3}ª²Äp0„±¢Ð^¿WýÂOÜ}ìâÅ[yžWeYŠˆxÔ" `¢ªS‹ÈÀu/Á±ªŒ‰hHDeJiB¨:NiŒ©è«_ýjß9—1³5ÆäªÚÉó\‰È߸~ý×¶6·¾–gùÙî¼ÝrþcΙì–hהذ¿iR `!"Šæ £PWU‰G/\¨{üñ÷ò"Ìœ‚Iêû3WªZÑÀ5ÆÆ†D4j^cCU5à˜6¯2ÆXÑ3Ï<Óef«"LÌ™¤”‹j'Æx°¿Ôï.÷—ŠÈ1„žB;)¦BTrÉS’BD UÉT5Q§PÑLU¬(¬ªUX@YUYT ÒZH’Š´FfBk—hÖ]íˆmò}¾.€o-6>Žþ÷Œþ¿¥=]̈Z•rî×Fh#9•@ÊmAk-„™<ˆJ ¼UÌ\Ñ´yMPòv;"¢qóQIDCU¦”Bsm‘’ÖÖÖìêêªM)eY–¯Ñ!":xüø±î‰':ý~ß©*IJEˆ±ðÞwb¹!¯ªªBÈE¤H)’R.¢…HÊ“H¦¢™Hr¢êTÔŠŠ«¢ Àˆ*««*©j»% U”¥5·µÊ6-È“­XŸ}ïaÎÁ³È!½·÷ŒÖ]^Pë“æx\\÷ì ~Іñu‰‚vŸH©f¸‘2³H@$D&ŽÄ”ÐoTÕ«ª1NEdœRÆD4!¢ 3O¦OUuÚk%ÃxAZ”ªšûF"òÀ2³tºÝ“/þÂé¥^Ï?ÿk|ìø1W–‹$Bȼ®¬Ê¼*KW–e>™LŠÉdš•å4óÞ)¥,ÆXij”R–R*DÄ¥”2Uu)%'".‰±ªÊRoÍŒj-š¹} ÏæþZR´CŽ˜ß‚â#]ÑçÓÅýrÒ¾S fÞâQ]<·aìœñó÷rŸý"a"!âDD‰™î%Ä~ªIDAT%bLQ3)ð‚ˆT1Fï½ÇãíédrG3O›sÇh¤D³¬TÕ3³1km¬ªJBq4‰ )%9xp‡ÖÖâR·«¿üp8Ìb1% 1çJWZcr6¦TÕiŒ)‹!dɤ @&"åD”Q–RʪªÊbŒ.Ë2£ª™ŠX¦a¾V…Q0RQ’:|§ex;M4ÛvpÕϾ®ûG h.!€YuP,Hƒ9&vóºaÎnªo«DÔœ½"a¶¯D$Úh®u,ŠÎRª­O ˆ(‘4LOÆØd {cm´Æãœ7ÖÃ\qÔ‹HX^^Ž“Ñ¸¸·¹9ÞÞيȈ™½ˆTD˜9†JUMƘcô¶µÊÌÂCD‘™ªºf>ØY‹^·›RJ.ÆTy_9–€ ª.†`*_å•7Ωˆá›L&Y·ÛÍT‘…²ápèœsÙd2±ÖZ·³³ãò<·“É$ët:v<³µÖ‘#"žL&ìœccŒi$·^D¨ª*2õ$!c,…à©4²ÖRŒ±ö„™E!µ‘ÆP¥¬Ëf~mRÔÚ•JSCA›ïEc^Ýõ²ÖÍ4Çku㨪¤:l‘T-_‰“Ö–hªcZëÅ$ª‘€D¢II}Ÿ( qÅ„hŒ .s¾È‹Pt;>Ë oõLðéСpäØQÞ¼woéÝwßÞÛÚ«hÕ0¹÷BXôÌ~ï<;cl².“¥¥e¶Ö°µ®®ApŒ1L§S33眱ÖZ6\c\ðÁlooçÎ9wàÀW–e¦*Ö9çúý~ctÖ9—RrÎ9GDÖÖÅw¬µÖM§Sîv»ŽˆLJ‰kCD¬ªLD\U‰(e™aï=Å™jE‘še&5 %U¥:m°N‰™á½Gžçu 1‚÷pYgílÙ×–ŠmµqU]l—3ë5£S#Þ "I%%5ƨË\Ê\k׿(U´¹ò©Ùª’P—»¨Àì™82Sdâ@̾ާ Š1„ñ ÆWÕÒòr\>x0t{½ÀÌaýÔº<üð™Þ•+Wäí·ßzo2Ž1w í}Í MÀ§ÛMDäsÒív¹Ó-e9Ê BÁv»½Ðï÷Ãòò2“g.sUUYfžŒFCËlœ±Öt»]wðàABp½^ÏzŽh朳Ýn×¥”l–eYJÉEÁªš­¬¬X±ÍÈ7"bZ½À9G ((Ë2¶ÖfCÖZÀN‡T•ºÝ.@ç²™¢mŒA§Ó™‰þ,Ë ·KÊF¬ƒ½e ÌÞ+â›kTD4† €j–9Éò^²Ö*³QbÃ,Ì\Ë„”¢ª¦”D’HÒ:I2 $x0E&œsÑf™·ÆkM°Ö%[Oˆ‚„˜FÛ;‰Eã‰õõ°|ð@Ô$zvcCΞ=sè•ýH®Ý¸qsód\Ø—–ï3 Ðëö…‰SžeÒéZä Ûd S¹ƒXU{ï1L8Ï Î󜋢 _UvuõO§3™N­¯*òÞgUU9ï=…œ÷Þ®¬,;i1º‚M)™£‹)™”R&"¦yÙ”’]€µÖ¨ª6Æ2 ,"Fºö+”j]B¡e™£fªÍ<4­Y/›¿D{õ€…¹@%Ñhïª _yUI’…¸7`°Þ{ò>X‘D1%N1š”¢MILJ‰SJ$ªFEXê—ªKjtÓ ZFZ»f@X`ôýžK{°f|³VŸN&˜ôàÚ!qÎ) £Î:‰Ñ§é´ÔèCT‚ö––R–eUY^^IÝn71³H]5KT5‰ª¤$1IR(¢16•åTTEŠ¢“D’t»=42fÎB’H9êêú:Vc†llœÃpg7ÞzKX=&ý^ÆØâØo°y¿t€Ñh,UåÅ#"i•ã¬Efräy.ÜÔÜ­ª ÎeÁóR¿"Š¢`2™LYë>»\–%bŒ\yÏM‡ò5Óc䪪²MWö!˜P7¬˜£ÞœR4)%Ž1±¨@R$唄E…ZPhíM$­-h¤Cc@k»çE³tK Öw®!u&³Xcpë½›rèÐŒµR–¥†e0ØA·Ó•sàÈ‘#")É`gG¶·¶0BЦW¡4Ž ±ÖŠsEÑÁÊÊŠ¬8€î±£È²\†Ã¦“ îÞ½#kk‡¹ßïááG•0âÃë×qéò冇$l˜¿ø›¿‰o}ý¿ Ûïãðñãxò©OÈ`gÐûÛó·Ë÷û¿wµY22Ï׺ÌÐú=ï2u7¤2s"&dY6³€E‘Z…Ê{ß0AQ–ÓÔÊrÚ2±nîÌí~±ŽJ®*n‹GNË’SóYJ‘ ZsU•cUáf:€JݨbÞƒ £Uj©ël0ÝÕÂNT•1ÂÌPmyAOðéÏ^:M*©uWß|SÎlœc—år÷Þ]€KÎÉ©S§pâÄ ‰!àꕟãÖ·¤,K@k­X60Æ ™˜`ØÔ9ÌAxG˜ŽÇrûÖ-ôú=œ<µŽGÏcùÀ½yãnݺ•F£‚¼÷zêôiL‡üüµ×ðéçžC $ë2ú _ù þô뤇Žűã'ðÈ… ôÊ~ÐE] î£hF·6`ö`ˆöøº&ÖwëÞe&¯—UEQ´E‘Ïö;b¤Æ”Z#Œ¨ÂWʲ¢™Û¸aäd:åà}Ë,ˆ(‡à›–„×¶ê‚6Œn»ƒ(€à=‡v9ŒÚ•@–gBMiã,n¼ó>óÙÏâ‰O} Á{(€^·+¼{„µã'°µµ‰å•¼ýÖ›8»qçÎáúÕ«òÃ^ÐÁ΀ªªÂ´,aØ 3NÇa‚G¨•Ôæ¥k`É&FW²%‰HPRôÆŒ‡#ÜþðC|þ‹_ÂågŸÅ×1 Pt:¨Ê§yW_÷>xgÏ_@  `íðyܸøn¼ó6.^ÄC=Äïß¼™}ëßà_ýÂf áÆH-Ö¬pS iVÉócýjôÑ%5Ñ.˜›X[KZû ;N°U•ÅNåmtÐt:ýHóé˜&ã · ‘­“ùEëÒõ“ÉtWÁV´±-(Òž·Ë‘£ƽ7ðå_­Õ¹L(ò;·?Ägžû GC;~/½ø6Îï|îóxÿ½›òÝo}³îªæ+ìloAEár‡›ô.F+“:Ý’äöøaœzhCª)_ùáûräN—½÷˜Œ'H««ˆ)á¿þçÿ„¿ó;Ï^þ ~ò“W1ìàðÚÀã—.á½+?Ç—.A¤hÌŒO>ó þð÷ÿp`uU–——ðoûþ°ÆÀZ#ÖZi“Àm‘‡]îÌ&"¦)öЄ1ÍœÎ†Õ Nû90f?bW;X"@½^o– ¼0—£S2‹!¬-³kUá}ÔR›9æÇÛJaèYP‚?³ëˆ£áëëë8ñba¬`Ã('c¬­Æ…Ç/âÞ;ŒF˜NÆø¥ËÏâé§?õ»ßÂ`8€µãÑ¡òX^ZÆõü=”gÐ_[ .'\Ñ=š`— ´Ó—Áù?º-ó Æ; p™ÃäÞ&~òêðÜçžÃ»ï^Gð)ô{=¬>Œ[×®a¸³¥¦b(,¯¬ ×ïa:žÔÁ½yŽׯc‘æpÆØh ÏââëíÌ¿@4ûKMôÇÌéÒH„™¹e¯ªýHÚÄÌ"~Ú‰œë: ª58¥™"ÚßÕþ£³ÈáÝ`™ß‹?moP]‚&Tå¬Ôk[?‘™1 ЖÓ1DüòsŸÃúC븷¹‰­Íͺí¼÷ˆ>€™ác@y°gNàø#ç‘F÷p{ø Øëw0¹:A TÎ – L¼ÐƸsû¶·¶qôØ1ÄgMº[[[Æè-¯4Õ׸)u—f&íÌeÈòÝ™Þ3äY&™sâêX4iIuVãØš³¿Á0_+óâT@µ¹±­*‹xæ…*ªH6K#T;MDÒpZçË"èfŒTÌê7Ǹ=GU¥±Ô××—uY©™ÒFG/º]‡¸õÁ-.º]¨ˆaž–¶·61™–CBUy>|ø° #T•ÇÊÁUDïëÄkØ$ÅÒR9ù­ ¿ÊGÖãß|ãßâÚÏ^–Èq{"H $Âêh¥5iÃ4¾Œc'NàÞ½{ì+#GŽBE…ˆ±µ½…¼(`\Æ“ñ¢uYßIL"y'lŒA'/v„fÈò YžIže³ÊÍT/‡u…Æj–IBM5IUóz½h¯­#žêÝ-`ö,½T>r ÕÉM­P­²sãamW*Bµ(˜]¯Úü&šZ·BT×"4Æ€DcÝo¸ÎvQ T»h›ëš Kzý%LË7®]““Ÿiš9C²¢#øÊ[oáÜ£àÊÕkrçîݺ –1xâ©Oà¥þ ¼ÿ>ºŽHL¨¢Çê ‡áŸìà?¼ó¯eùÔ*6Ç›p;˜z1É•Kƒ>ú©¯µóªÓí ªJœ>» ?Ž[Þ4:P·ÛA©wÞz«~èÎÉh<¸,Ã{7o"¤„<Ëá«J¼÷òÏÿ忸?ò¼"/$Ës¡&Y±Ñ¹vaî&mG^32kiL RF]~¡vØ7Vw·j+¼‹zA-×gË14Au^¸YSÐCç@œëÔ¸ØIöNIítA©³ÿg±¿ç–Z­mXYJ§66ðâw¿‹_?~ÓI½”5fŠõ yõ/ÉácGù¡‡Öñý^œUDsÎá7þÒ_Æÿ£¯ãÝkWÑéh§ÍŽt WâÕm³9˜OÔ1à `%E§õH¦„‡7Îáùßø‹˜–F£ñ¬ZËùGÁÖÖ¶\yãgü‹—ŸÅp8ldm-®_{ùe¬Ÿ;E­TÇ>>9t©ßC§×©} KAf–Æ—²+¥ˆ¨n%׸S¥5² Íí«¥…r­3ƶ÷™E ϯÙuV l”EY<ÖÎó¢ó{´µgUF›(ažUÝý˜ÌíõöÔ™³xéÚu¼úÒK8{á1Te]»XZ–c'×ù;ÿãOä—¿ø|òÒ'ð£—_E™<¬èõ—ä·þê_ç¿ò2~úããÞÝ;uÜeØ,G‡:óUG ÊŠÚk(ì\†SëëøÔ3ÏȹGÏCŠK—/ãϾùM¸¢ƒCGŽ"øÓªÄÑÓ§eZ–øÓ?þo¸ôÌÓ¸|ùi¼ýö;øðöøàᬕ_zö³xòŸÄû7ßÅïÝć·>À`g“ɤîª* k œsX^YÁ‘£Çpf㬜=»ã§N¨îG0D8yâ>swoßÁÛ?}MN¬ŸÆÚ± ǵÎP8ܼv WÞxŸøÌg` £*KlÞ½‡ðµ¯}DÌbçþîßûÞØ8Ç'O—/ùKÈóœk5³m&/’h]9»5ñÎD÷ ­ß™ïóùÇBDZ ñ^ÌPs𗇳‘ H£¡3 ³ú@­í ‘íèo‚OéÔø ÚÙ©Í`2ÖÉÎæ&~òâ‹üøÓOãÀ¡C"Mu—e¼yû6~þÆr`m g}”U·n}€Á 6½33Œ5!ÀYÓX[ÛH¤n¯‡åå%¬\E–9×îvŒÆcL&øÊƒ ãðÚ!±¼ó曘 vøì…ǰrð`hÛ$ê6ïÉ[?~ç/]â¥å`®]»Š¯|å+ý»ðÿÑ?æöOÿÉ}]†mmm͘¸w4ßO,.ÃæÇïÏì½÷Y¬¶¸´[”‹ÝÅÛ%iÛ-|ömºh,ZbûÃÚïmÞÛ,综//~û;øÒ_ùk3Û€¦zá•ïw6·ðÔÓOã± âîí;xóíwRÂÎÎ;Û "¾’GÎ_Àêê!¨Ô!i“É.Ëp÷îìloã™Ë—ÑëöáƒÇòò2º^íu¼ó³Ÿâá3gqþÉ'áC€JÂ¥§žüa€ìÓƒIn ™}úÿ›öð€Ó>pÚÀNûxÀi8íà§}<à´€œöð€Ó>pÚÀNûxÀi8íà§}<à´€œöð€Ó>pÚÀNÿ ¶ÊpÛ×ÚIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_ram.png000066400000000000000000000214071217176075400242000ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ 0ü IDATxÚíœy”\W}ç?¿{ß{U]U½¨ÕZ-É’-ïÆ0‹Ù—°c28 @„œ!YÈ0 ! ë$ìì°ØlÇÛÛ,Þ-Ù–-Y­–z©êZßrïýÍUjŒqÎ1Cì9žó>:u$Õéºuß}¿û½¿í5”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””ü¿G̽íñbE.ùè™68ôÞ;¿õ7zèߩϊȢ>ˆA|@  Æ ‚ñF‚ƒø ™ i<ˆÑ A Öjįê T‘ÈhP/¢‚X‡bE¼ D^ð¢X‹ƒU0F4T & J0AL0|#*‚ "A1AC @DET‚“ÂXˆšPˆ‚‚A@‚@ƒ|À[HxT5ˆÇ F‚ …QÄyT­ñF1*¨b‚jaE¬¢ª5NŒŠQ#ˆEUADbTÔ @EÄ rÇÜ=ñ­{v}g÷ß^ù¢so£óCÿãpÑÆÊªü,'²ùÙO9#1’PçVG‹ F«ÔĪ H°¨q¨Z€Å x=t-U 1¨ÇÅetý(‹( Q œD!K€Q%¨bl„‘w`bœˆZÄŒDxVÄD°‘¼DŒ x1D($(>X ‚!6 ªÃy‰”`°ªÁŠ(Aq¢h0(T h¢¢pª(ž Ãÿ+‚ú J0ÊÐxaÕØ!Þùù¿|æn®ä?ÍþêÒ/÷OE5’˜¯ýø|jÁà½@,£kˆŒ (ƒpVex‘ÃM4\‚0‰€zÄÁ>cD!€€ˆ ª5¨ñ¨c-¨Ž LQ6õŠPo0Öb‚'ŒÞ¼xb§ŠÃp›Œ5¨õ„ ¨±˜àðj°â)BD¬žÂC UÅ«/`„ м„áf Š 2¸¢Cƒó(&¢Èà«DXÐ@¡ˆ ׂ  `$x$ˆ`mÌôħl;SëäÁÊ>ú‚·êýß3„@(7 0~8X£€€±à.‚—±axóPra‚ y 211:$PT0Öü¡%£Æ“»Ô (¡€`Àˆ!‰ ;š´EQý7 FAFŠ1(<ÂðZÔ `#ðÞáqˆ(!DØ8¦j-2‚àP$ u¸[@Œbux=…ò,E]@ ¤¹C"/àÎB‹ŒÔ²ÅXSA‹ª©¨Õªø ì™ßÇw®¿”{îc¡½Èª<j¬q6bY;ŒSÀ†§`,,2¶­]Çøª ‚Ó዆:ŽÕ€±‚z"X`ϾY–}FU†Ó²èÈMDüP;)¼cu}’53«ð~(Ñj †0úl6H¹gqkŒVC×â ¼Ç2ß'¶µu#£UÀ$ ?¥Äxò TŒa¹Õ᮳LÕ ÊhgŽv¥¢8BDÃ¥ÙlqÄá[¨O¢*xãˆÔàüPÄ Þ@Œ®{öÏ’æ9‘µXb&*ýÂqóÞ;¹ñž›™=xGàé'<~¤µ†nLp´ÕÑòµbŒÂD£Æ«Ž~ wÏ’4ÆP¯ˆÔB¡ê 1àqTCƒþÉÇóáïƒFµÎX”R02Àª \D"²‚áå~= `…`b‚:¬‰ðÅ€™-›¸4¾«wÞȪFL –>vdV%õcT€K»7àÏxÉAOšçHÅb1± ýˆ`À(ò^ʪcÖðî…¯3·Q«8°]ª6ÅK(XÂǤy ,µœ|ä ¼î˜gÐÞ7O4ÑÀàðA(8Oášâ!Ërêã“Üžìã3;¾ÅºéõØàùé=·±sÏí4;‹,IRÁ†AÝC¯˜`‚w+GÀSâgqLø[NøWh×a&æÒKŽã÷Þö*Ž>r;.ŒÎCo1&€îXKWô 2Ãyßx3:õ\Äô×óÙî«iÄ}Œ‡B"&d™—óU †JÆÜÜ^õº°~u2”~¬1TìžßËßðÞôÆgò%ˆÇøÉ¾çðN`Æôñ:ôÒPå ‡ªuÜ öÙ<õ FÒ™CubWà$€#%„ò€ ì¼c7_øä7ùàó>S0m¾½ó/èÇu>™™ç.»ÿ:ù-&Nø6ÌØò$¾sÁ&^÷Ú§³ýè£q¹ÃF±–Ä$¨5DVè=¦gNâÜ¿„ÓN»Voá–k—yÊX5U¡V©‚zÔ+…ó^z0ˆ:¡K-XÎï]ÍÆúdüPazj‚úêU¬Û´–,W TP×â„Ô[úi@´5ª¡Ê„: ±1¸:Ø:0À&5jãuA"Ä0ÑèM`Mœ‚N€«`©R×±DÞà‰Hœ\ S‡AïǨGã4P­­ÆxÅY%òC§nÿ)•ZÙÅ&SkVCؾ he9.èHîuëéæ º±gBÖ€N°quƒé‰qN8áXÒ¬?ô‚ãÁŽœ^è6—˜œjJBœ%T:1­Lˆªu’‘SF1*<žà¼üG!ˆ¬(@èÏòžù ´Î=ûÛªðžàðÝY/%+ܘˆôSjôøÞü&þòæ³÷uV›Sµ[hø C§®—ñ•ë΢㠵)Ç﬛ÄfË Òb СÇe’ˆtÐAóŸÌô>oØÂÐäLFKÌîçÇ{ŸÎXÖàncùQø.ÓÝÎ%˜ª’e“,_q:½¢Jc¦ a¦Ð~‹"k ªÃÄB*¹K±E‹½‹GsÙ÷OcãøZ¾ía`¾M•0uÌçô/¶§)S¼äI«™ôË´|ÁªÔ¼¿Ÿï@ár\ðŒ®Ÿ}·_^°vMÊG›W°*i™>¹’Ä1ï×qþlWÞ|?YXæÏ>‘J¶„÷޾ËȲüÕÑ–"°¡âøúŽy¾ý“غºÉ-$Cæ(t®ªâÃ?jý§+a% ß[\ß<šÙvÄ£·¼¬ã(œ§×Éè÷³¡ç?ºù2:¹¢Ø²¼œRÍ*ü¸;Áß/m§Ö¬So,“WZHÜAƒ ƒ„ùð¹þ6îíÆLE–×G²6Y‘{CPGP!àû}ºŒóÛ3|þà1lʧèFóLÚYHñ"Ç|.|®³‰Ùþ:yıéG4è“EžÂg¿T8Éظ 8G{)çc{æÇwy¶ :tí£YâL(|Âxš²à°gy†«í‘Ìݻ̧γ:-Ô{:ƒ‚n?%¶²²9}±ý,'düp‡óoK©­NAQœ¿a~DƒP †̇ܬ1D¯o?âí(ýn‡4Œ²p÷U;ÅVr|Qà¼' D4ÐÙ˜ÞBÂ?Ýó-¶L-! ]1Õ3üõ†)èÁO» >tÉ}L–ŽjÎ9²A_Œ!»kh<οÍÝËùá›lIé”JÅpO¾Š¯Ý=ŽHµ:®j¡ —:$é“ùbåÆÚWê”zï´n~`u•÷ΞÏâ=mÆ’ccãw8+DELar—£ƒ˘xB€tqó/ù>l»6tøäME}ê4~°óbþ}ǵLÐ¥¶áL>òŠgŸ9FXh!3GñÇoYF%ÐÍŸãU3* †‘XÁåŽ[÷/ñécª|ñ5Çéß½µÉ[®hQŒE#µP ¼÷xy|µÁ¨°’¸¥ïxý±˜ú¶O8v\whàŽ{wÿB è°ô*t€Çjû1Vਔ¤ñÔÞésÉ6®ºê t÷E˜Æ2?Ñ?eËX,¢ÊÁþfžzÓó™]^ņ“sN¿g;U‰YW­Ó+Òa©Yõ0Æ^B0µtÕò¨ÕyâÚ«EØ»›÷7ç}÷ü5µUk9ez .˸ªw¯;î,þdÇ'yÓ¶Ò4캜?\s&ÿ_Kó`é#4¢Iþ‹­aõÈáxENްbVO;štˆŸZὟýË_ÿ•‡¿„íøž³éT.(öÐØà‰¤Êsl•ª¬¢"1=ͳ–þ¤gÑ+ëÖ Ø)ƒ ðÑ?æù'>‘¶qÜÔÜK+[æ·zçÞ~13õq¢JÂKŽ{oþÂ{¹cóïÿߟB×Ö­ÙÀÖãžÁtaÄ !yèu»,½:;—:\}â]|éeÿÆ97_@Óuyç£_ÍÇ®ÿ2i–ñöS^Îy·_JžL†˜3OxúÙ9È,]ï‰PµŒút$Hø*ŽBôA+€ù¿6š^ZÎjÅ2­4e!ïÐì·Y,RvÌ^˾±6;»»øâž‹ØzêÉüýerãZ¾ÑÿűÌ7 Αk˜~úÑ\ºïG©žõ:xÀñºÅ€ é°Æv9¬§\ÒÞÁ›¹jj'É1‰¶¯åŠø^ÖmÝÀ…kïá»Émhg– R°:Y&÷mš.c®èÐq9³þÐ’‚IísTª\Û¼Ž¯­¾…ö‘Óì›pœvðå|ë·Æþ”›”?ßû9|5æÜk?Ë»®û[j«yô¦ ¬±¼ÙåÞt™VkŽNg‰æ`‰þò2Qð̰=±L |éªO²éømœsðr.Ü«¶®áß\Á•û®`õëø^÷.h]Ãä6òuUnš¿‘õõã±G#É_¹ùÃZ€àɼǃhĪˆR¯†~0+6eFS`p¨0,ƒ–p?k㟕nàÖ5)ÜîÆE©)ƒmÂÆõtÕÞ'èúÇ_úi¿ÅþÁ]d.cþÖݱ7/0³9â€#O ÈJ ë¾Az…Cdž‰V{wF1¹N÷ šch®„ƒÊ7?þUìÛGqïáÉ&9±r<¹èfÅÈ75‰~CÞ¦"8úªLDöS#´ûLtkt ‡kç$Å8.X­Œ‰4" ¦z16÷X?6ôiþJú*8—ó+œ¿†¸ ÞÈŠøC¯(BÀÝïUÐFV Ô,¦!0]Æ %HLRù•Æs& Ñ€¨.4&j4j1bx['<ÝDÑ(àƒÇ‡°òr!àüÏǾ§ÎÑ5¡á©ÏÔÙ¼y3Ùø?¼üÂà*¨ Bp)ÛawïýÚY©„ØbŠ€¢ø~ À à øÀ¯4²4“ã½ f€sˆUrÍ)¼ÃÜ¿Ðbaå”ôàTq…'¶†MÓ«ØØŸ¡¢ã\xݹœwá'Ðù1U*õTÃÆ/RÞbµX)ÄšîÏ{õJ¼‚â€à=F„<Ë1¹"¦‚+ܰL•"x¬¡ðHÅp žàVNü‘˜éJ,¨â¼+^ú(ƒ ãuØ$§ Õχß_C‡Ý®€UK:PÐ Áy¬‰‡“¶– EŒõù¯4žsžPQÕcS%!O…¯$dï>¯~T|¨‹AŠ*}rœ8¢à‡m×!cph–o¢Â o£Añ!£kSÒ¼tS 2²ýJãE‘2ЌΠ£R¸±xCt‹¡¬(‰^±÷9ÞÓÕãµµ ÂÍ»nçÚ»ŠJBðÕã3Ìõ¡(c)òŒX†h­eÅú0’øa+¸ºáß·‰dØö~H!$OH ‡H‚5¹Ë ²ˆ3xê‡-æÎºQ?å¡#eØÏ(Ð]SeÔ†úƒD¬ˆg¾Ó%’@ÏŒ¡P Ö`+碓{"[°ÐdŒ í{©Ø˜¥f›Åþ"&šb®;‡sů4^°\Ï%)í´ÍæÆ¢ž²¡¤Ü¡îýÑcÂDu‚zcEÖæš]7°sö6zí6ããëX?=Åòd„)ARH ê©óhµBÒWR‰pšBá4Œ:ž‡å‘•DNöó$Í}aT+ÐDÉ]5Ãó¨HFj-Îh¬XŒ·ç ¸û8w¤ñ xçîa¨õAÔP«lᣯÝÈã ôg9þÍ7qËÇemíd¾·û2Îx÷¿ø4b{¿æÜò)wüÌð̼åë¼è´˜…þ-°‹½>Á—>=Åcf^Okð6½êgìûÚ1LV_ÀŽ=_âÙõÕ'™M|äŠËxß;ìûÔI$fºì Þõåvÿ˨Æ?àíO2Ÿ¾¬ÉÍu Ðà _¸–w;®üÓ€*/øÇ»ùèk7qÄø1èŸÌño¾‰›þö¸Ñ¼åŒw_ÌÁ/>™xý¿ðñkÎáIÿë}4?û bæ-_ç×ýÙ—¾ÌÑ8ó߸òÓî7ïî7ï'ý¼;Ÿ?“ÄfãSø›s8ëùóüÖKþ_rºì{ìüà+Væ}Îí?¡ó¹·Užô?¯çŒÇWù£çÄÁÁAÎøà|øì-<~ëF~²ßóª]„þ<äy(û†µ‘D+ôšã;é‚ ,ý¢ ÜÆâEU`?Ðbï¬'ô«À.À"¹áà p Ú5öÝñ˜™‹A– û<àræçtÐ&ÒlÆ„í»èµ ÞÕ0f?0Ár;g0°ÀÐ!¤†LÚ@ë;ïB„¢`£Ùðñ5›³Da=c6¡Àx¬@R‰‡·ô¬F4>ƒÉhA°D“¨+ÀZÆüf¢:Ìã£ØúcIÌ( ÇÖ&a`>LcõhìZĘÚ*T³ÑãSŸBBÖ‚!ªL Þƒíb%&®Z09ÖTˆcô%©L<"ç]‰«˜`€.ä+UŒ@ëA"CЇáP#x…J5Á„h:;ã{ÙÐzUìª*Rô Ò0F2.‚Zⱑ Ckw‚]³ MûÀ$«b7TÑn¾WǬ@²6Dm’¼JԈѬqAưõô!q7F4Aч$`ÌQÕ€ë²:óˆœwR©b5  o‰« ÚÏ€â,ÆD<ø ð×I1bM Á dË„nFܨc:9ø6š)ñT•°˜oa%k@Ñ¿D¥Z%D1¸6ä]¢É„P(ø6áà™œ‚æ´é+f²‚.eà†ñ€©7¥>ø’C\¯–R(:Xl¥‚¶{u‡OÏØ ô{Ðë>bçmlãmhgD•*Q¿€N£(Bx ¨!!Âz…-Lꩌ7ð=ÝÖ[’Æ8t è,£QLe|:}hö©ŒO0C·.åÄë×`‹òÚ÷Ø™µè @ÚD4"Ÿ†^ ý&ÆDT¦& ›B»KÅTëcH¿€nQKR‡Å æ{$&&IÆ Õƒfúˆw¥RÁ``¡½Œ(NÐÌÃB,6Žäo}øu}UñTÇB^À½ ôš-”>ƒù&ܳŸååÕxmP웥’ͳØiœÂ{@ 2÷(»}¸ãNLà:GsïÒ~¸óvº÷*ZÌÒÚ³—»“ùÅÕŒá÷ì%dqqÙÀâöì'ÎX\^O·Hpûf©d ´;HI`þôRºùVzÞÁþEPyÄλy–ÂÁ&®)8ë .,´1ãÃ'¬…ûÿkdq"!âøMGpĶÜû¶­~,oÞþB¶Øi`Šg>éùtÃI$Rvó›¿ñJŽ’­2Ë»_ý£ Ö":É»ÞøfÎ07@¨²éqOä¿=æ¥lŠ6¿†?çU,é‰ÄLA¸ƒ³_ðj6°„)л8ë9g±Ùo¥Â8ØÝ¼øigp¸n>¶í–yÅÓ^Ìõav&(ÇGÌy¿úé/âQ~Œc²º‰³Ö=“Í\ T˜œÜß0“‹{IDAT̶µûØuçÃa>Iþ岯ò•‹¿¯[ŸÿyA¸ž{1ÜmfN¯¥®×pk´‘2F×þUz;õhvÇ)E¸T¸3z&}]à™r ^Ö²Ë<;äzÖÑÇÑI´Ü•¬ÓËØi·qUR®¢nävs ;£o®¦æoå.Žb§ôÝêævîÔ#ØE^ø!IXb§Ç|h0×@0Ü”<•Ë\É#mÞ;ÍIÝËcõÌúyng#÷È ¬‹nå‹?èrîe72±ºþ E@øui$·ù¤ ï8~³ ó$Zp÷ bóôF$ßCYnlz*‘pÒtÌBØÝvllÄ^7ÜÒô¢ˆúqë>¹£FIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIÉÿ/È×Î9W3—ÿ¬6V{ÂËÏ8#-—¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤äÌÿ«‰|ß9"IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_smart.png000077500000000000000000000423571217176075400245610ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½y”eG}çù‰ˆ{ï{/3+«Jµ—J»@ ’±ofõB{ƒiãqÛŒ—î>ãiÛgz¦gŽÏ0ž1=îqû í>înÛíc›EB¦Œ„@HB+hA¥’JµWåúò½{c™?"~qïËÊÊL¹ícu^½—w¿¿ø-ßß*„ÀfÚûÞ÷¾ ‹¢xp½1fʃR çZi”Rxï)Lu–¢,(‹’BÞBÀ:KY”chšc Æ´Ñ(ÔÄ1!œw(EQPU¶±øàóþ²*iê¥â1…)!и&ÿ6…ÁhŸ³,pÎ|@k é>‡R@k¯Û4 JÇw!Ä÷«úMÝP”Fœw¦ÀYš| Zë/{ï?ë¬{À9—ï]×5ιø\†Ã!Î:¬µôú=>ô¡mxüÔfà½ï}ï…ÞûÿP–åë‹¢P¨ørÚh‚ƒkLìØª¬! ÆƒVxçÑZ·ÇUU$Š4ˆJ)´n¯'„ ”š˜¢(@Å+‹çÞ{ʲ$÷4ÚäŽÕZçoSЦi¨ª*ßßY—‰Ä;D"€4pœw‘À­ÍÏT>x꺦*+Œ1ÔMŸ!\]׌VFTU@Ð÷ÖÚozçÿÛØz|~ç\$d­XYYÁ5ë-Zk†Ë秣ǎžs_±ÑÁÿ±û±)¥ÔŸh­¯›››ãÔÉSy€½÷mÐZã¼CkMUVXk#QqŸV:rŠÎ@HÇ)¥0º%ï#¡hÏQJå—ó½÷h¯+\Åhƒ .Ïðî¬$ƒéCœ½€w>lQ`TgðŒAf§sqàÛäëʳi­óû†°Öæw•u–Ñh„B‚Ë.½L_qÅ×îØ±ãOlcÿr£ãÓm‹‹‹çÜ·a¨ëúÇ«ªºn~~žÇ},¾¬Ž/[Eçb'ŠXÖTé(éDkm;Ð(”V“ƒœ~ ×"§tÔ.w+Š‚º®3ÇðÞç}ÝÙ­PQ¬¤çIì™àCfç2J%NäCäf>r ­5κÌíÆãñÄûɳ7MŠ2ö×Ñ#G¹ÿþûyík_Ë…]øaßxxˆà9—?‡»ï¹{Í}&cÌ+‡Ã!O<ñ8óóLVš ÂÄ,òß2ó¤CdËùÒ±eYfÁƒÒЦn2q”e™¯+ƒâ]"†DŒ(¢œUš~¿?q=!‚½²‡u‘K¢Ža‹6ñ^µBôûý(›Çu|·@¼Ojòü¢+ôûýLÁ!÷‰ôWÕ«hš†S§NqÃçnàÍo}3^pá‡Ó%7MËËËkn×½`Ó4çÏÏÏSëv&$ʶÎdnàœË,×Z)?µî¬ÉJUYäceÀš¦É³_t k-ÖÚV‰´QEM)•¹B Lp |g]Þä÷Y|ËÑDW‘÷ÉJ_|áPÂM¼÷øŸ­(#DE‚‘'ÛœDV–%uSó…¿üø0ðÏ6:NÒ®{Åu ‡Ã³>&ë¬rÖMlÓ*^Nf·hâÖÚ|LQe‘÷m2Qˆ²ã—µkç\&z\O 6Ðdk@K~Ëód””BQþäšE‘´sÈ{ LÈu¹§ˆ6á ùY’$÷‘#Ä!ÜJîÙ=¯«—ÔuÍ¿øE=v…zFˆ ®ë³>çu3¡ ÉˈüîêeY¶ò\)4º=G ËÔ4M;@f©R¸D2ÕD´g= h äk8çÚëùž‡L”ÁÇc£yµuï=m2W"=‡v£Í¦‰àmßÿ¶³ˆmÃ:€s.ÚäI‹,tdo…)²)%/žgŠZ¶RŠ…Åzý>eYQˆ‚æ,‡.4ÖSõâ=œu£°Í EÙG©hú©¬ñ+‚£L¢¨"…kOP£5ÖÖÉÖ€Š9€£ñ!PõgÒ3‚J\À7gÑE?b©P)Lð8;ÂÚ”‘Ø“X2ÆP‡eE&+—QÞ×,- é÷+BŸ8)bXk#®a-_ùòWð¯ò8pàÃItmX'Xmöo˜|ˆ²TX¡Ì[B$¯ü„ ¤”ÂZ›ì_Kc{vÍð~òÍ\vá,[§mÊÁN>ò¾ÂK_¸•—½øâ8ËTÀzLmçþôNvm«yû_ÀxÜ uÀ:(û;øÝ?ük^üü-|ßµS7ŽB;¬Ó€§a+¿þ›çgß÷r.º`;‡s²¬¸ÿ ã‹_¼…ŸyïË1Fc´£q­ÞÃoüÖŸðK?{=[·LE"*T|žéíüÁGogÇ6øþ7¼ˆº± Þ¶l™åÿü.Ž~Œ_ø™·ÒX‡Šr†š}ËC|òS7,Ç”U9aBC™ËÃe¾ü¥/óªë_ž}û6¥¾ãíïàs7|nóÐÔ ¶±Y¶ «·ÎNÈÛ® wÎ1Y®~Ѽéõ/æ 7ÝÈ?yãíUÍác3Å [§—ñ;ÞÎGwïã¹ÛnáµÝÁÂ\Éâ¨ÇùÛÎÀŽ×rãþ ¹Ø|’ë/yˆ¥Ó% Êý[OÅóvìá9³·òºw19µ Ï›gÆ,²¸õÝ”ý­õçŸa0èµSêSAoùÊ-\wÝuìÙ³ç÷a"˜0Ç7J£Ñ(ƒ<¢É·1&Ê´ŽÆígÔÞþ¦+ù7ÿ|+ozåNŒ)Y8ý$nñ4_¼ÝqÛÜÑhELÓ€]æöo9>uKÉh8b¼2¤±MÜW/rÇ·Ÿ¼¥`eiÈhy<¶®ae‘…3KÜø5ÇÑã5ÍxÈÊò>ìxÄÒÒˆ?¿}Šk¨—©ëQì·Ì£ÇKnº£`¸´‚«—©ÇCPЦ^·Äý‡Ÿ¹}Àp8¢ 7Ž^8Å®Þ78òø!¾~÷I¦Ý#èæ(M¹Ýh8øø_¿ã‹‹‹,-œfyi‘Ñð ;Í-üƯ½›_þÕ_‡֤•Á…ÙZË×¾ö5ŽŸ8NÕ¯> üw»w½ó]ÙJÚ0èšMÂêʲlM£$Œ1Ì/[Þò’‚ýÃ'ÙâŽñøÒóˆè‰&8ø¡—ž"hM]+à=Á{+¾ïÒ!/¾d­<Îyžà1\{Á"/Ü·„òçÞ9\ðx½žçý¯üáG¿_fË£®ëÜ·ËËËÜöÕÛxÅu¯`vvö_†îþr½ã'fð†9@=®3ûÏŽ¥'lwˆJVÀp`WÉ¿xï-æãÚðÉÔrøà)+Oe,xÞ¡„€¼§*~” çñÖ‚³TÚâ­Å»šà’Èr°ô«£,!ÄÖF‚Ã(K¿ç@yˆø>‰(ËÂ2è5€ƒ`!x’&GY8ú=‡ó ‚ÃhÐÊs^ñ;ûGÙ=sŠ}Õ#l/Ÿ¥ÐaÌžÑ_±eáëØû~‹Ÿ}»å oz-++ãÌ]«²ÊØA¯×cyy™;¾qÃå!õ¸þu \ïøe“u£ÐÔMä‰Õk!S1{ÄTJ³<òüô›Ç”eà[MS(‹Â£•"xÞámìäà!X‚ „83µxç¾A"À’Ì1›öygQŠÈ=¬'X‡mâùÁÆkG°ß¥A×Wxñ8‚#±Ó=8N‘ T47#ŒŒŽèã¹Á°"Acˆ¸’Å„13åÛô·éù' ÎVæ¨mÅC—èïü.¿øþk™™ÝFd/©Èmï=½^ùùyzè!P¼\ýjm4ëù$ëvà¦÷(•DY 0ppŠø¬‘0Tú¯:D‚¸*~‚Ç%¤Ò‡ÔK‹„zDÙ÷x¥ç‚;5ÿóû§è}æ+¼ò¥ïä¯nŽ/ñ¢ÆWŠ®ë3ógØÓßóÂõŽ §W} ,#ðQë G)ll5/ؽD¿hð!uw(šèɳ©EùBp8×`­Ã5gSú@9 {cÇ[K°*qu‡·Ñy‚ìÜ'V‡Jl?¢‘AEvÕ@P‘èâ9`Ò3)’‚—<…‘J;½àã5$?rÚïÓß 5[Ô"aañÒr²·e£–“Ñ4‘­:Opm(Uðqö+Y±Èð¨‹%™Ö¹ØqŽ,&>±k%DðÁQR³·\HZzê?êôz­Ž L;'bFµbÐljåmi°6q{Ù.Ú†¸ß×Ó6-€ñÒ‚€¨ú±Ï³›äé $Ž€§RAXk––§,3Fsǰd4žbq£|‚wìÙoxâÉ9 8q*`µ¢_Á¶Êâúi ‘ƒÄËçÎW!²ù¨±kðéØdúl&ƧO@*OªI  Ã!n9Å:hZE.—Ž÷i€§„¸ÈºP²Jq&r+]ç°9q{§p9éï¬D¬£mZ ì†hå ŠDUUÅ@Ç ¸€Oš{šŒx0­a¸äøÖ£·>¨¹ÿñ‚GÎì¢v è²æu>7ÜëØ»g+eY²¸4fá«C¦z <0¾¿U£²m0æE{—½p™Ó§4ÍyŠÂx¶ôu£h‚N\Â¥Y$ìŸ ö(åã`…ÎlNì_%$0wð*ášJÍ£ãÇ#¨Ç L2:D©õ-§si}#¾ÿvÖÛ&Þ^™xºÑššb—øñÄjdG£¿ 2HH8øÌ»&Kœ`>â:>ÊjÓk8xÄò“Ù¯¶sþþ­\yÍ€7í×\¼í»f+fg*‚]¡*5 GÓ(Byè’商ÇçzYØÎá“c¾sh…Û¾<Ï©§ø‡§¹õ~ÅK.÷¼ä2Ëó÷ÖL•–±+¥µVòŒ÷]ýA¾T2ùPnšÆip›†¢9B¡.4hE ðIWI¨£Ò¸L"¸@Hp·óÑʱ*]Ú)”·ôÌÖ`Й모n´m&&pÂË×…„»ŠRàCÔÚm ʰÁQVðæ×]ÂÕÎpݰUbÚž¦i,n´„k°§¢F-D €¥;+Þr@±šÞ¥%ãWíb¥¼€ùñnôÜñ`ÃÇî=Å¿ýÒqž·í8¯»^ñš†ÂÀtå1 ¥‰`Žè©S³³,$0HؾqÎE´'ÝF@$9+Êy\E!D½'ƒO>t$ºèI)$¡|C¯˜Ã&°y¾Õµõ¸^ÿ&:ßT@ˆw¯} ’ˆ~‰–8þ¢0(¥ Îãlòp5š-Ëð?½±A O3:±„õ%g“N¡T‰èjªˆ"-ÔÍF?n¨ÇgŠ£(îbW¿ä‡ÏßÊ=w?+?z1ž~7Ý¡ùÔ-Gø÷_=ÉéSóÜx߀Ú:â¼˸!‰Ží ;¢‚¨45¾N¢u™::e–ó؈^zך‰ ùÆB´†”Šº¬ ñ;qŠP´ÜHð•®ö/ƒ¯µžˆ±|ºmÓf`’t64 `´Éùumq€Ž#w°;vF)BÐ@/jÚ Š"F -Õ†±çÞÁ¸Ž¶·(Uƒ©@Qj 3½ÀTƒuŠ¥¹83‡ân®˜žæÚëwó‹o¾‚‡N¿›n‡Þüýê!Þ}í?üŠ!^è(ŒÄè%¹¢U ¥ÆhBSãmä*›ˆ-ʨ݋¨Ã‹™'„³ŠänˆÆK²‚K"A7-Þ' ¤(sÌE7š¸*«6úyMÎÙ”ãùR¾V1$ÚÇmøsôÀ‚ úWJ•ñ kÍüPñð±’{Žö9qî9Q1ö3,¨˜iÓïU8çXÕhcPaL¿l¸hvÄ¥»öî¼àüšËw7lŸÑ8Õ£®-ã'ž@«GyþÌW¿ñ ~îmÏå ÷_ÎÇn8ΧþŸoñ®ϱãyC4–²ðèd(<*Xð ÎYÉ6o³¢ë˜ãEαó“ØK3Û·þ¥äœŠçx¹Fv#¤øÀB·9"ûEçòÁƒe"èöé¶M+JÇkg]F¨„(¼÷™]Gë@åÓ…§®á=Üç΃‡†;EÅöí%—_0˯é³{ú {f‡ôbzP°mkïs cs㽜\9'OÖ||‰›ï3wó¶s¼êò¯}Á˜k/©Ù>­¹>+CÇèàÝÅ7ù¡ý»yç/¿„Ûžx=½ñ4øïä¼Á §Ï(.ÚŸÏÚè‹ßŸŠ–]² ’œ÷ F>KÎû4›]Ô1Ó }À'd2hÀi²ø.ÐXK™â˲Ìì>„9¯Ä ¬§‰¹q%0¥m™Â ¼š–È[Hæ¢÷Ê3UN,>ý­-|ñ-|{~ö÷yÙ+gø©§¹l—fGuˆb\S a„wãÌ=üɨƒí5Š¢Ð¨A³«OñÜ×ë±\\ÆÑ…=ÜþøUÜz×ÿåÆãôì1ÞzÕÿà#.Ú»‚Æ*OœBø,×mßÁ«~îû¸ó¯ãßþéa~â_ÝË;^tšõ˜ ÷Ê^`XʘÇ7±tÉml¡ÝèÜŠƒ-Ž+‚ÊæŸ8uˆÜÏ{'аr‚kknGøÄg=KMëš^_Û´`E¡rÒg-ëº,Å#€#§4pË6n>¸“Þ–ÞørÍ/?w‰‹f¥¨kÜh™ñ ËÃX'GµŽáâF“ÄM2ÃXa\c”ŽrØpKú%Ï»t;ï{Ñ~N©‹¸ù[ÏåÏ>’O~äÞzÅIÞÿÆ.Úã9õ}†K‹èožk¶nç#ÿôüõ£oæ?þÅ þ«ß}ˆË·åû¯†—¾ÉQ•†éž§*À¹ÈÑThbŒB?w*+zø@a"dð ´"˜¯s‹†/=6fqùì;H8]LLuÁá‚ËÁ69;ª*YŸñtš˜Ž›‚‚c´O+›lcóßÒú…ås÷mã ïኋ5¿úŽ—ì=DoeÑòˆáRÔ¤V˜²ÂÒ´B`dc¯ð¾½¦Ñ  žé)CGQû‡úôœ<Ítq?rÁn~ðW®ä›'¯åßrÄOÿÞüõÊ'yïkG\¸Û1vëúŒ––ÐÝÀk¶íàÕÿø…|ëÌÕ|ê¯_À|åI~ë??ÆÂü2ÿ×§f¸ê’ÀÕûÆl™ö”Fá£(T ÄÓS2zÆuŒhœá±#†¯<>Åc'zÜñdŸ“+[˜=o†}Ý"ýÂ'e™üÉ Frºáõbfź0~m8=üüóÏ¿qj0õÖÁ`g|N6èhª£ZqýÕŠöƒ+\Tž Y\a8RÉ9¢¨L _Vœbi¬9xºà¡“ÃQŸ……À£§ /¬Œ^Q *OUv÷fGlß¡¹`§çš FlŸ l8‚‚Qå« ƒÙ)ÊýÏçŽSÏã_ýáÜó o{Ái~ìÕ+\²ßS˜x|ðjzƒ)ôöÝ,—sÏãÓÜõ}û)yl‰0‚2U­°c{ŸÃs[Ø¥s͆•qdÕÖk¾=ßãøpã1lŸ-qÆsÅ¥[¹ò¢‚k÷æ9Ûæ,fyÑFC2Y£Û·8Ür-ÿè7P‚¯'‚C% ßë㜣nj<ë'€#GŽ›4…… .ÐÍ Ðºd4‚Ú”‰Ñ8…rÌU{ù6Í¡ÓÎßßãêk{üøE'yÁþ†ÁyøMÃ\}÷¼x™:%v<ÕÞí|òJö¹{øÀÛÆ4¶bIíÇ3<1·ƒO| >qÓQ¶=1ÅïÜxœë/ã­/«¹î¹cÊ¢ÇʲE/ÜΫ¶>Àõ?÷<øññÇ79þ×›§üìQ^÷üe^wÕ W]P³µ¯i\E=ª-Ÿ"¸ã”ÁqIe¸ì¼>z÷Tô5EÓxšÆAP”…ÂŽ<:€·cìxÄø¤Ã9Í’8³@k¨tt6^6Üôí>7|{;j°}{§ÑœD™­Töºôz1“YbFÃõûdÞorQ•0p)Õ"Ê_Î~ՄѤÈiг3Y˜â·®æªÝO¢Ç5¸Æ‹ Eu S\ÆpaÈòü"+6ùÒ}`vУn+£!öä"Ëc…á(kvôYyÙK9xPó[¿ÔãÎǯá/¾¼ÂÿgG¸tæ?ý†^÷š¢ A=r'WLÝÇðrNÿÀ…|ñ¾|úæ9>ý§§˜Õgxåe‹¼ò9+\u fv*0ÕÓÔf4RxWãý8*|6è£i(ŽÎ(¥ ºˆ²½2Ñ3¹8ÖÜs¸Ç'îæîcÛØµgš}Ë ?øÂ'9.æÞa0* L›b/^<éÓ®›x$°9–¤•¦×ëáj‡)M'XÃ&M84`4³ý%f{»Vd|"àH¥_(Pº€ôM©Ñ!áá: R¾~ D­‘ÐÆzìš•eŠÃwñ¦3¼éýxìÇžËg¾þ>|Ãcü¿_y‚÷¿v‘W_5Æ%+ã€?t?}uÿà‚müÀÏŸÏÑÑþêó¹é–¾ðùEìh‘çn_äÊóÇ\¸Çñ¢=#¦ªðL6íÀç8ÐäÕW¬pÍE#fû¯5£Æ°¼Ð°p¦F¹3à=»+Ã÷oyœê¼S44EÉJØB£gi!o]Ó×K”nÕLJT©WFŒÃ1pDi“Ùqî[Hq€ÀÚV¯êz,ÖÛröñºÏì4)&‘*ãñ8ƒRÝÃùZ¤Á’ñ”Ò-Ú(´ðC§Zp©ôt¦ŠÔ›¯'¾rqÙK”R #'oŠ<ŽÜi\– Çøñ˶ñžÿñb>úWûøß‰[ŸT„•^qÑ«.ñÒ#Λvl)aCYÁ¯Œñ~ß$ŒQjÂ)Î;ø@4cÕ>7€VªL™€ °8ÖT&ä ’Ðy])baŠV¯FqH˜ 耛†‚5:GKy—ìHoQ–%ª– r¬¥Ò )VFƒRme/©ÖSE Ò\%ç5‘Å“X" þx•|´1T*½hŒàÞ;Lqå 4Ö*ΙgêÌ7¸x×Õ¼ìy†ßøÀˆ[=À—îò‘Û`ü— \±cÈ5ޏjψ‹·5”=Ïtéé÷$Pá‚ÂyÝ&ª¤IiÐ1ö„…±biYsç‘>_ytŠE[ñko<Ê  Ê£àþž«,¬¸)ÆbÄw\?X»Io`·”1fBÈEŒ:UÆ«ÁÑŽ“‚§Ü¤£ˆî׉3)çF”Wm@g/ˆ•bR ¥÷ ]t¿]&§L|¼×4¶ÀYÏpqˆ{äÞºýïxwŸSïÚǽGÏ㞃Ûùôÿ·ÂÜ6bÛt‰VC.ÙZsÙŽšÙiË–Çþeg•j•Ð41›øøØðÄRřͩ¥Š;ŽôYvS”Sš};§˜;~&öÛY=ß+æO¶…¯¬µ` 4IéÞHD(dëlã8m0ƒu6×½«Ê*DbªĒхhù*Jh•ùÎ{Ç #C›«4è†so…3¤ t^LðP8 Çá%åÐ66'b¸&ùÞË8£¬wXg˜;1Â=¹‚Ö'yñ â-×o£vÏáÌc§ùáwÌpç£û9sâ4÷žâÈ!8vt™žqÌö+¶¥pÖ²¥ï˜[rØbÀ}%ÏÛïù«–¸|GÍÕûO£§¦ùùÿ»Ä“-Ö,ôÝVR•âJ«˜Ú(ìõ´={÷pìè±@¡S…,&€çÝÄß‘T4Ùs‰ –ÊbA‚0ECt)D[u­‘’Þ"bAw÷xð.U³Š S²‰˜Q>и¨¤IpF ÄŒ×ÕJÇØE­Za½faÁQ¢LA±2âEõažw`šê2ÏHõ)vìä·> Þÿú!w?>‹ £¨ø¢˜púˆ9é_S˜«r7½ËY¸«\bbá¦"AŒî½ëLÿ$ç)À¶[ëvhõí³H0FL¶ˆGŸÒÁ<)" œéê>e†Éà{KÊŽE&LPY·〠—‹£QÊ0±ß.Я.¤9¶@uì /Ô'£ç<½33 f/cåáƒØÇçX¨MF ãA©$>WµÄͪ²ÂÕãŠé¶LnÜ›b–‚ÏÑ=ëm{÷íÝ(ÕA¡c–BÀr]=añZMŒumN²®+çÛcD Ý?&:̹v€ýp3r˜U:ÎhÝÅ8< È”èÞàÕV•è$. 9c1v?¢’1ÞXÍJ“úÃkVEñc >!\³Ý‡‰z=éVùýb160…¢wÃícÑ 6IÛ ±iÚµSe¿u2kSëüº¾Ê¨(ça¥b9 0(õŒÖ*‡V¹D)r^É3¸8øÎÆ]Ê“KÓ… rˆ–w ÂÍ¡ßk¼«£ÑIÙØG 0'6nwŸŠŠ§ê ZÛT$RÖR#Š(ahJ)ªªŠ‰·¨*q«‰h=mã1½¤™/•¶›¦™ 3F#ƒË)ZiN+p«U+š|’ó>¥]I¤ñOi­O¬›Ž’kYg±6žë%¬ßÇúÞ»”ÔÛb÷bVÅx»ÎpÙ¯hê:¦½­1\Þ·…2;§¦}>É\«y– ('æF£‚AÃïr±(Ý"92hƒ"6S&Î6L›i€ ù¯h˼[kTßx¢`a¬˜ªR¦ 1˜ôô©3•Á0gqqÛØ¬#ø@Π]^\ÄÙQ‹ðd[šñˆ¥ÅåÈòµxê8CÁΜ^ »¶(ñêºfq!•UO)J<0++,/-g¼BšB³¼4ÄŽF ÔP*Öö.Ÿ} |ãY^^Î~ž‚±¾“ uT•¸ëêÁïú\6Ú6®¤J›¢˜Èƒz烘,žo?æX\ÔÜ}´¦±ðú—”(_ Œj” hÑ:Яt™ÈyçZ°)Él‘ñÎ’Pldï!äNÊE9¯´Tú<ûLaR8{«f®$ïvlÛBâMÅ狯ôš÷“ó´‚••À—q\w‘aËŽ’[ï+ôUÆ6 *Þ’ ’Kò¯ Á[oÛp ®ì‰šzRR”¦nÚ b DZ9ÅÇ¿Z0=£ Òøغ½Ïïüê[>æO¨6¯N©X:ÅIñ„d·Ç4jK†¸Oâí(tI“í>A—4~Ýq¦L6!ª5÷Äÿ;Ä[TLžjJ¸ÜÚ-aú*Z@+ ªÀ}G+¾òÍ!eÑ^[¾¥ä=´QW›i&€:$+ ©cœw1c%A—Ea˜ê>rSÁ¶­Þòò’±3”ËǸ~ÿ“ôªÈøÅ ä Ÿ'³œOõ|¬mð>`2ÒkLÅc´Rx›²q%@#Nâ‰ÂÖ¤Ë ô?ÇDRD"Z-dzœw~M<.z'ýDÿ¬Þ_˜8“û%üÈÕ†ém¿sSÉp…(ÛÉ· !úºåx"Ñÿ<Å?e3:º‚ó ª-É. 6Ä*á£=OœôüÊïÌŸòL÷!h†#'U¡¡TäY/ >`ôTTò°‘Ëñ  ‚œ^1šV`à‚x]i…)ò êé¸_fx—3”ÊÊ” ÖhÕièí¾.Û(4ô‹4Þ"¦Bk õÌ$¡GÐ Bã ø/láÆÛýÒåÊ+2Éd)ñtÁÚègã"ÀÇë¢Ü4u“·g0¡W!¶MÜxgàgþuŸ§5ÓÓ´€•ÛløýW¨ëhÊ ;6:ðГ–ßÿˆ•¢lüBÁÝ[>zÛ˜ºN©g>¥Ÿù8€·tÜö°£PÑwà¢r€uOÝÛpÏG/ÙýËÐðµï8n?äD9íC ð¤ãßlh|ì@!üR+:åøø] MÊ ÖŠTÍFMàÓ÷X—"Aùd^V –FŠÞ0àwo° ÊD0‚•tPV`Â/P7u´z6øÙTDÈyc Ž63H8‚„>³¸ñ›ïüßJ~á ?ð²†[<°eZ1½E1Ut3fJíÐÆ³³ÓSŠ~ ŒÉFCϦŠ@UÀ ˆUF*‹>NU0]ª"Œb¦ÐeˆÌTq¦Êö8|q¯â³÷¸ÿpÅ–~ˆ‰$¦µ¤º%÷»“L¬® úƒ€M…Bk£Šÿ"å @$ÁŒR½_Z~RóO×ðo>§yë ,»wvo/™™†O}ãú%++žÛ¿c(t…õš©øìÝžÙÇ 'äZ½10¢*‹vñÉœœO \ª¸CZtÊ;ŠÂí2qeZ§Ï Mkª4ðEahšv š¢(âruM“pùÈ©\ZÂVjïÆu(Ð ¹kš¦­.­«è<¦,’¢*dw‘«ÜϳÕÚxOY©RÌÀ’C¥mœth”\õÕYBÝÕB3ÐZSVe¶¤¨” lM3me&HØ™OÕ¶¤üL7DZ°|­Zû¸±ÍJ&²Už-Fá¨|‰l®ëYÜJ_mc'–±ò29MÓäõíÖ÷2b­#‡ÚÙî|‹¦ÊZÇò~²6¡cWÌ„MþÛx$&w¾s.[ҺѫRB¶[ùZE)5Ð $³g5Äl”¡ MÎA” %Þûœ¢b‡æuúH¡iªµH„IV“˜YÝÁR:Éÿ$ÚòÚH¡CTª]M,Çé§•Ù,ñ’½^/_Kà\ˆ+ƒõz=$`E,*YSYÂçŽ gvc-´N`ÎEÀßðÆM@ˆØuN{’–kuÊÆeÈXk\h×Þó.Ö]é"_R CE@>W×ê"ab e£iÀEÀÇÒ&ª@[Á¼[YS²(Š<€²=¾fËi„SHç+¥r„®8k ê;õ¸Î“¢ªªÌµº~‘ù²Þ‚2-;—/eT®ÀRkz½Þ¼,k%o´mªVp”w’ei¹nƒè//&:¸[FVÄ@w„Oê•:Ù'.ƒÜO:±‘Á¶±±ÐBÒAò2®!ä8Æ.èr°î=áép„¸T]›ëŸk'ëX?A–‚“wÊú’N TwPKá,Rp«KøÖÚ¶ÿ6ö–7¿ØL^€N‹0¦Nì0˜(e–Š+ɲ왥§7] tŒVFÙšP*Z ²ÞžÌ”àÂÄàtÅÜ[䥬,•Ís@jÇA“W+ï”¶Éûä¸û†¶N¢p„´חI!kk¥³Õ$Ä-±2kkÿñ¡ZBïºÜ±±oàÆBB "–€< 4hé ‰ÁV1±D>_£³â¶ˆ Br? §S‘5‹"¤T»dl·£$RYêŠ"ÖíP!Dyþ®|È%ï2òÖQÀ$9V8ÕêE3j¢˜&´ò_i…¡%8È^¯Çh4ʃÜíÏnøÝ„^¤×—ô†7¼!ÿÞÔ‘bþ ågöÔD“'¯ ®tÖȃY[ïVé¦9‡GšÐ„å'»Yä¾è¢Üe6IË |h˽wïiLļó¹Ú©ˆ0­5^¥ólT*»&¨pËœO†i‰)§&Å‚,²!û­³9¦B§ä±œ„[t--!¹¿ ±ºø[ÐòŠv½éY3¯ –”2Åî*w µëƶe󬱆 mع³.›E!´ù ™5Û@¿×Nœr2{YL5¥U–Õ]&QU6…š‹ÙÔM¶VD TÄ•HDGV$uE“ÌzÆ¡ íSRd|Wæw-ÑcL‘çnÖW'ðøñãm?otà'Øä(•¬¸$PG:B2†»&K†‰¡^ö­\_«¶Z¶)²ÆBÈÐÅV»¦ë¦Uʤ%ˆUX·³®µÏQ ^×ʱ!zÌBQNsñF•pz稪*O¸ln$¼~¿ßEÒ¥Dì‚AÝtpyŽ®B­•^74?7ŸoÊ ”Yœ_>áø2㻊•Òq0¤c³"ÖAÀºÚ·Rw0³½ßaß*¨,z½^»bxçþ¢Sˆ©&æ˜:‹™ñòn@O"f¹¶°l| "”bA§ª_«k&y¥„»ÝŠ®˜É‘×Ek¢Êso$(t¸2Ì¿7Î$¹Ó˜‰jÕ"ï3[ÔmRCWÁ{\J2Šº«f‹ÙÕÕ¶±ÑU,ó †V³ÏúøÖÓ?ÑUŠ²í‚º©£ÉZN–gí¢Â͹üC pyFm4¥)FÙäìÑAÈ,úBY”-~’8^oèºÚEì­kì:þãMqQMaò ±¾E¹D® ( –è]û¹+lcil‹®Éy@›z–^b0äE´ÖÑ®÷žÆ6YžÊ}DÞJ§7M“+œáÛÄ–.¾!Nt‡®å"ÏBH«E]g<O(}tž„PŠ(*‹2ë1b͈BÙÍŒÅ4’™:¦nPë‚:–î¦â2ŧY! a×–îÖ·“YÚf u’C\¤~ÁýEîŠi]»·×™˜äz¦Ÿ fMÓDÜ¿*&ÜÕ]ÂëáWáf]N#„”Ù¸žÌ‘ÙßÔ &•“ò8y- å"à­§¶qæwß9sSæIÓU e1©îŒ~ºc'mSÅ¢C) ² aêΙ}Dõºé›pzвZ™9‚ƒgœ²p¤2¹I.Ý@{ï@HuûAjò½ºþ!PyYÿXkÙzUEŽ"¬;ûÈ#øj I€/©–³}Ý„n#ÏX-‹ïbMWBÂìö“dawÑçӞ ŸªŽKS0ü®i(¿ózªEµd@»(˜tDîlßbã¢ôtåa÷<™åb*I‡KÖ’RÑ[X•UìÈ58Œ j!ßÓYÀ)´•Jˆ GèBÔÒ¤ÈcQžI¹ÀV~ßÚü"¤u'—B$œtñƒ¶ƒcí"cLdï¶ÕUºÚ»ÒŠBµþç\¶d[—3d%EÕ«b(\"ˆ@ÈÜH}Ö’/Ù±ÊêèrÖ®UB€õ‰êrà/¡LŽxéÊâîÒ±"÷BLMMq͵×pÍÕW3 Òà¶IÒbgÈF阘6Öö“„r’tÉÂiÏmÿîê] "äë¶÷ŽÛÛãÚûË5'Ÿqòú­¢¯ÿlàìèíözÂò->ø ·ÞúÕ¼˜Beœ¡ËñºÄ¹Þ%cž ±Íš%ÍÄ6¥²|¾î•×ñïz³³³½å÷D»æê«Ù·o?Ÿ»ásY, ¦!¡aÔJ¬|½u»:怠.Êæ¼£Ðh2š',|ïÞ½¼áu¯gïž}Ôu½n»õ{©Ínéóêë¯çÛ~›ûï»?Š,£1¡…†ÅD5ÚÄZ ët=#@ÈVhmS¥¾ñJŸsŽÝ»wsÁ…PVe¬ül;wSŠ;w°oï>¾õÀ·€ÖßÒ+ðÞãé@ÊëhψÐ4  èTtYÿDŒ€V ƒÁ¦3Yþ¾·hA¿ßË,¾‹tñ 1 »æêzÛÆq€ªŒ1v¾µI³›Ì¦n|`¿ßg05µ©z6ß M%mW©ÄZ"± r|Ú}:­+€7U-}&¬€l+MãÚU­Dþk£~——— >0 ˜ °ÏÀS¶–ôDpÀÆ]ÐI&×zE@÷øÍ­‚2º^À.Ô}ð~¿ÏÔôt®Qûl[»E ?rA3ºªÚh¥ÝdÝú ÷LAp/‰¼•LZ!áUYÑï÷éõû…nŒEnßHÛx¹x—…·ÎQ•eŽŸ !zß k¿ÖuŠ©{và×ÕDì¿ҿâÔ*Lt-¯× óa“©aEYPš"†^uâôsjVðôzU ¢|ZO›p0%Ç›8Îr€Hòwts×Û6)º$€õml w1XQ'b˜ÈÈñþlг hu'ñ­ˆµ:è3Ö<(òZ ëu9ÙvSµ‚‘R”E*.”Ph—&K©KZÇ5î>¼±þhÞ9víÞͶmÛr™½‰¢¡.ç|»†à:SäY¿‰*aÖ[¢Ë³SqõHU×g-Ø@Y–ìØ±c½!lß3-„@¿ßÈ1‹ZÅüÈÕá_>xzEo¢~ðz›6zs©aFjyëò®rz‡rî›ÆöíÛ7sËï™–£“:P{Äþc91§ÅE¼Ñ¶ÉbÑm­:¢3Ti&´UQTžmëkF›\9$G0¡âÑ1Óª‰:À:½Ý¶©¼ï=eUQÇ).°M 7ª]ÛîÙ¶îæ“¥e$ì:‹OØÆæ`Ó͉ÚDˆŠK ¦=Ykq)·, ê¦É¡ØÏ¶õµe×>j BAU”Ä•Xõ¤‚¸Á¶)3Ð%ö_•½ÿ§B[³ÆtB¦ŸÕüÖ×$c*:ÖRµ4À¦¬'­£ %¼‘¶)gRqðàc¼²êÅå_|H«`D?€G>ÛÖ׬µiñí6k¸,«ðê½ÇÛ¿¥5ƒ"@‘Ö Š*-!™³Ú'_¶1hm²:Ì®­>+*ÚÇÖq1 ßÖ"ˆñ!ã4²Ñ¶)3PIXµRiY³”YǪªb¸²B\å+¯ý¾™[~Ï´ˆFŒÅ6e4EÕF[’‹Xên°mœRî[à:‹ E¿ÁŒ˜«& Íz<Þð-ÿNµ¿n< ʲ¤…­óqÍE- S·Kb„ðÙ•ÍÖÓ6A!¯@¼Ã…¸¢w `$ef¤ Ö”¹±°°ð,üÍ{ÏyçÇùûÏ.ô²ÈÙKÝl+!¾H››Ê ( ƒ,â¨"׳…–•Š ƒGMa˜ýž'€s½¿÷žAKÆù( <1#%Úxç&ÓØD”ÕÆ#‚t‹óÉ äl^×öÎ3è÷Ù³{÷S"—Ÿˆc£ï"+‚ß]I´J^WMmqî¶MåXçãbŽ*Öò9l¡&Tø‚mRÂ9žù﬊ø_ˆ0•Rh¤&@LúpÖâ\ð >Ebå,É µMAZµ>þ¢08'+}Ư¦(bpcÎ?Õz3휳¾Íl”4×{–VŠ@ ¬I–S¿ß§Î‹r9´1X멪˜aÔß‚YOŒ÷3©°‘K+feÄÆ£:ÕÃ1xbüú„ëò\Ï}ŽÙ¶:?'œãÞÏ4:ç3Ÿó±t\*ÏʲJI6ÑP×Ltqa kUQæ•Å7Ò6ƒ„ºçDE­FGvo´Æ9)44ð'-ì¸ánèœgnH×êæïzõs‰ŽsžWRU zU•+ë\½­ bŒ¡ŽëlØ„ž<}ú4çï?+biS¼G¡1¦Í•WŠ!µ"@åÿÖºö†Ÿj}mçܳù™¢±6Y)ÙV«\yT I,--¢^ZçmrÛ„ o×ãŸ>ôÄc\véåôzýXÊ¥Š…—Ÿ. ƒÒš'O¦âŽÝŽünÝó7«xý]48Ä•îOfv¬TÒïõSœ…ÏE¥ŸVÞyjjŠÑhÄÝ÷ÜO•XE”¢ ®-è !Ü¥Pï×Z^ÇL´Í(xÀY÷ À÷+¥^Õ4Ín PJM,Hùµ¯ÞF33Ž~€–BÚ=éà‰Î ©êLGlLÆDi´vÐÙl=kçâÏ;ûÌ åÏ&®{´M^¶½F]Õ<ξc»×UEQ„'Æ{¯ÛX©^äjA)u:øpð'üõ>¶Æ{=í¶°À8 üyáà0B(u„®‚RŠ»îºKÝu×]о|î„ÔLÌ;žIDATx\Dº´Ö*%Cx­µKß!•E J)•/•¶©t q‰ÊùrŒZ]PîßM­jI\š*%à¶ù Òd£dçÊoïCÁ+ïƒ Ákï½í<¤Ö)ƒßý-çNì3Æ„-33â÷é3 !…sœ›¸ŸVÛ x"t`˜*ï½Ò±©ªªTŠ_SƘüI•ÀUw{Q¡,K7 š^¯g«ªòEQäcRqeŒÑ©&2ƨô-D$÷¨T%bQBHé7©A¶‡îì ‚kiPIGç\ðÞ«¦iÇÅx<.š¦)š¦Qi_He^‚snÍO* ®wÎyk­OƒïëºÖÚ`­õMÓ„º®]]×a8zkíH)5,Ërå¼óνç=ïiÒào˜ lxñ艋túîÝï~7¿÷{¿G¿ßÏã!R)ehÂt÷Š0iÐLÚ–·wþÖ¿Ug¿êì_ëw÷&–¡zÊÖøøU¿åo·j[÷ã"Æ+Ç:À‡œ—öût¬ïBRÊ®( §bŒx÷³îöŒ¦ì¾óïäcûUUE‡À¤Ìל=€†ÉÁ4«>Å9¶Ÿë¼î¶ÕŸÕ±Ö3®Õ¤c»Þ%€µyõo×ý­”²«·§mnÕ9ò¼ô'÷Ô«žaÃí#€7¿ùÍ|üã§J@P§u;¹û·|VÄZƒ¼!œ›„œ‹3¬¾¿aË IDATxœíyœWuç¿÷VÕ«·öëE›-ɶäcl³¼@lâ|Â&1²±Ì0Ì’|Èì“a2LòaI2I& C¶qÆ2I> °‰± ±Íb0¶åM»ÔjI½¾÷j¹Ëüq«Þ«×‹¤nI­r>9v©_WÝzU}Ïïœ{¶{¯°ÖòB§ßüÍßj¶ÛíOîܹ£m-Z)…”âŒ}¿1k-ÖÚF·Ûû‹‰‰‰cú×o¾ù¦3ö¬õ&QV|üãÿc5ÍÛ/~ñ•{o¼ñÆk qœœô†üïB µ¦ÈÐ" !PJ•Jȃ>ðÇÀÏ®æåÖƒfgg×tŸ†ßãŒQ­V]UûjµŠ!ô÷k%Ïóh·›X#©†ÃêZJI½Ñ \d`6MÂ0$ Ã!ÛÃZK½Z§Ùh¬Ë»ŸýîïþÞšî+1V§roVJI½Þ Ib‚ÀÇ4¶‚ZXÃ*C÷Öu*• Aày‚¾9e,AP͆€¿T^¬v È`­%MÇÏG ¢ Ñ*Mévº,Ž sssH!‘Þ`ȰÖ07=‡)|wé}ïû§k¾·´°«ÕY{c ozÓ©5šÞ°+i­envn‰%õ5/á‚ / ZÍm†õ¢ˆ 2¬1þ>Qi`Ìj‡×¾Z­ò¦7¿iU÷ÞtÓÉC¹ÖÚ5Zg“NGú¡ÔX]`cµíWKù÷—mxÕ«^uZ÷—«7—¶WJqèÐa¤”ŒŽ¶iœ‚5?}|Ú1[ÀÄÄÄ’ï/›0æôÞ§´X­¤åÍ1}W®Óé09y˜z½ŽÖê¤PJ133Ck¤Å±£Çh·Ûø¾ë"ß÷QJ•NLŒOœ¼Ñ ¨´X½ ©hcAZ@P¯×¹öÚkñ¢l˜›Ÿ;­ûK €œ¡§Þ>ó¬íBA!ÃS©x'ý)¡’Yüá2¹ˆ2‚§kû”«¥ÖX¬°(­H„a‡šì»òãŠ+–×HëIQ/“ޚŽ$ÞøÆ7 /Üçkc2ÆŒÖXkQJ9FkR9ÓJiÒÔµõ¿È‡“AhÛgþ¥—\zÎþîåha~aM÷½ ðÎwþ$ÆX’$Áؼº×b¬3ØŒÑXk³3pä*ßhÒ cœû'Dfå¶/<üð#\vÙe¦×ëÑí.¦.7dz3³NZn‚ˆÍó"c¨Lõ;¬Úû ¿ŸMtç€Ñ‘¥˜óöÒTS«…4š Œ1$QDE:‘©#ëÔ#+SªÕSÌ”cÀv{GÝ.„$Šfgg¨WkLÏÌ155™pD–FÎ}xƒ1„Ép!…T³ÁºÒñ¾Y ²³ÃžCQSh­i·ÛAH÷HÒ¥U-Š£+ׯ Ø”:hPÚéáïÿ?øÅãÇ}äïx{Òjµê×izžHÏÃó|¤”X«'íbh|7ýóô4Ä»ì5»øŒu &Š1Sˆ4ÎÌÎ&xôÑGý»ï¾gþú믿Ø}Z±FºxçÎSjWZ 02Ò¸ààÁý|þóŸ¯4ujµ:zƒF£A½Q£Ñheã®Y–ɹ‡S™?`‡ÛÚlhÈÍLJ,8äÀ`H±§) óóôz]:.Q·WéÅ=fgg ÃÊÈ3Ï<½ƒÀÚhzz¥ôöF£™%n,BH<ÏïT¨…5jµZés÷¸|}¦ÂÎ~ßý:ß¿Øw€’üÀýÙµŒ‰Âö'~`DöÃ8&ç:“SõÅ8ÀÀdéf#+嘯“¥c’¤N½E½qOž¼ùlÑÑSˆ–Qmñ|¯âž'ñýÏó³( sÁɧ@’Gm%Ò•†K5YŋȴA¿½@X ‰‹!é JéY0)¬”ãÚ÷³†ÙpâùïáûYñÒÇó$RzApžÑ&V—¡9CôÑ~ä¤mJ €8Ž'¤”<„pR$å @ÃZ‹Q}çÍÉknäõÇz'Ù¹HÁ06ÅL ù5›_ék„âbÍÊÏÜ)ÂZ‹teèÈl†±A±éú﻾Â9Àoýöo´Mi ¥¼@‘I“èÇÞ…pŸó¼}ÑOïG}q†l¾Âxo„!p#JS`¾ü[‹Í<…¾}P…›wàÞÍ“HOæééV’$›€ù³ÓK§O¥@µZÛE½>ósÉ—Âáf9ÉÌn*p{%F",a¬Xkª$N:Ð2Æá@ꇟáN¹¤”"{W§¥²LeøØc<{»jE?i›s^À°}à¨ÍÍÍnð}Hê¥ÌgúäÑ¿å™orß~ˆù,Ò Îùí{ñþ?z–-£nY+¬Ë¤Ûؼ¸øŒ¬æúÏö3cн«ì@ )…ŠSÖë¸óÎ;O©¯K©¤”m`Ëâ?*—~)-Öæ9–úê‹¥žk7R÷8ÞQüê'Ÿ‡ƒ]¾þ¦í\½½Æäñ]¸gHêûÏÈ¿þ3„À¥¥Cï)¬!H’dì,uÓ éŽ;î8¥v¥Ô@h3}0ÏO“h6—z³ŒÔg×2ãÐ÷ãí€ÿò—»á`¤à_Üù,5_V¤ór©/ÆlAêûÆd€Ê\żx¤XO ]‰ùèÀ~X¿ãT©”@)Õ”Rnô¥²ŽÅsR†F÷e~e©ÏG‰e¼ðèsóüö'wÃh|É#_>Â]?x„å{Ž)· Ô"ëq±Ôç&€ÈÝÄÌÈë„p…gžç/J¸Ž¤õÉ'Ž–BéIO Šùäé-áq–©”ÐZ !„´Ö#ïP)AÈÂdEþørRŸ_³X¬‚š'øµ;΃PòÑ¿|š^GñÁ7Œƒì;1)„€ øR ­»_iC”º±u¹gÙ%ýa€ÁÜ;¥Ô©Èg‰@à ´vQÆÀhkHµÅ÷IºÔ>ÈÍ™½£¶ðšYMZ‰©´„ÍŸI½Ì|løõá_we(u[?e J¹Ü#7\KPX|£µ€;~û¾ø¹Ió¡g¨œ_å;¹’P zº(Æ2È ™å#‚K«Ù*Å:³Ý^wÙóå@þ_ ƒ)[ý4l±ˆc©Ïi(”Kæ£g¢ÆA7Å:ð] £¬AkKEJ”4ì Ê3O" )§ÌD"0HÏ?·«Gœ„Ê €lüÌS,¢ U¹p˜¼²Ô›‹»îà™þw ´¹d=h,Æ1tbè"óR„p«ŽÍÏ—# pûío]ö|)Y<]xY‡Š!† cNEê ׄÎÀùæó,ÆZRcˆR˜O`Ô‡nB4+ˆ´uv‡ ÌÌ ¢(×SùÔ4™O^)/•ýº¹j•…+Vö¥o%©·™¨/Î,¯ØÔµd+‹ÁüBÊ/þÄ¼èª øÄ'¾ÉkÞx)ï½e+˜‰Ò…gdÙFC¤r‘ê¾øÌôÉéÐ[nËŠ×J €%sóm>®æ4ˆ.ô=h…”tSC§—¢,õ½XS™mG'†7\ísd&å³–Û_ÖàŽWJÚ¢õòQÆAqØà´VŒŽ¶Ï|ÿœA*'2ZâúB'ËÖ,‘zk µŠ`´ðÀS ì>qýÎ:;7…™UXe ÏÝb«Ç" °š…NÌ7žmñÐLš#5:ü/ò<ì"©üj”¦Þ®ŸÓ™A¯¾á†^/5ŒŒý±Uˆ~ õ'­¼ïžçO?¹Ïqj4à®÷"n{q‹£ói9è?cØžpU>Ú öŠÁ‡›jDzàrÏ+Ì‹N²7\¤î¥ïÅQ©€’ óû ¿ö]? Ò“˜ì¿ãû‘ÐB£³¡Ši[_j¦”kJ¨¸Ÿs©%ɘl5KæZ@gÓÇêçÅÌ<>ÇK® j"5xÆ’Ô°tn8ÆçqŒ•RØÅº4§Æ.›¶,7^5NýÒ1ºOƒ‰*to{íVÚCEÅg–l¨1®²gCKò+s Ž)Þpý8>¥è‹ù¢Gº@YÙù`~‰{]qö7²X‰Þò–ÛO©])0DÖÍÂúFÛ0ó]k [6V|è¥üØo<ÁsàMï|ÿí'·3ul¥ âÙþw‘Ý.…Å—† ­€gŽÅ|üÏ•üÌMLMïG‡RÃv ñR¸ç¢Ñî¼1†‘‘sVpJTÊ!Rùù˜êʲé3 7ÂrÆhGç®Þ¢øõŸºÁ÷]$©Ñ‹MÖ^÷‹9»i Á–Ñ Ò¼éן‡§;üÇŸ»œ aD¤lV{Px§LåùMáóSÚ5Ú°žÇm·ýà)ws©5@>þS°Àim˜eI.@GfcB£@[¾µk–ô–ñ,6$ À\0à{†{¾×áçþÇ^|þ07¾ç¥üÂm#80I’·_$õE¿_Qdß=A"Xè,,Ÿ…) •E滬F#—a~®% J ç…P÷yüPD/ÑH/[*Þ°_X””üÒ_æ‹ß™åÑ{&aÎpóû^ÆgþÅEL>@WËT›L­÷W<_dSËlÿ5m°ØuÕ²§:öçTVX!„”c|}+u~Y!&Ï XC)¯[¸°ÁcOÌ3kO'ù=ß“¨žâÿº Ÿ‘ë¶ñ?w%oEÀ 7õ—“ú¡\DPʪO­´eÝm:£RÀ÷ƒY!Ĥ4‹L¶€Ðd¿$x0ïŸþ)ÒÔ°±-¹íšqîþ_Osÿ“ üÐU#t£Û3$©vÈG?øjn¾¬ÉUç âÎ O>}Ä©}à ¥¾ ™å ij ŽcvìØ¹¶Uœ×H§:-<§R Žcíû¾Êçv—ví/‘C"g~¡b7µ¤)?~ãî¾ëy~ï‹SüØ+Fñ=h0ã ù§ßgéÅGÙõ\$Í2O‹¤–>£ˆiÉR…û,€¤ÛéL¯GŸå´ÚÝCJ €F½žkz:gx_µf¹}i±ºèÀ@#8:>—òCW5i¿j3}æ0ñº Üþ²‡f• ÒH Ö<79'©Î‹¤Š‘¾ágÝ"`r TŸ©£SëXí.â¥t£8ZPJOC’ï\.M’fön> 8û]C¬ÀW¿õîK ¨ðÓy–ûvuÙ¹±B»*ð¥ß!±HÐ`nU€Ê·+=#ÿ`E–õµ}; ×RÙ$“Ëw9[G­~r95@£™(¥zÆ8éwÁ·)„ÕnÞ±Æï¿ý<¶ÿ·9ôät¦Ü‹t|QÓ“—ÿ,7D,VXtÆ|› [Æj$;wìœ:«U NwõAÇÒ@)5)¥—©VÓŸµ«ò-â²~—“ú¢jD %Gç ÝhŠj0ÉÔL<éBÃØ¡²®“Jý"ñwø|ÆÀhƒôdVÃu@’®~³’Ò@ 9‰µÙ ^ô-Ý<Ú–¯â•ñè¤êÛšÁzAÊJ—Àñc³ååí2R¿°d9ƒpUnÐÖy¸TðÁï~÷»½³ß[Žvžâò°E*¥°abËM´Ê¬ÿì@gª6["v˜ùËÌã7¶Ï|§®³•À„$C@–#,|Oo`®ÌÒg Öh7ÃÈèAòÊ€@d]ˆ«>J«^öŠ—¾÷Þ{#­uÅ(gXkÐV÷]¬Åš%*Úôýÿ\õ†›Í+e¿½È Lòy,çú-7 X¬6ý-ëœbH“„f³yèlöQ‘Ú££k*>)-¾úÕŒ±‡vÄ¢±FÖìÑx^l‰¯‹5–$p¬ÉjK%H—@’Ð+,kœÐ0e yÔ2×TJ+&6Lì;»½4 ­ÖV|\ZØg-ör“©U£³=€ HᘿœÔ¯œÀqíu>ÓHÐ/=î‡qó§¯$õP ùXÑn"ŠÍ´TLNNî9«=T µ¸€Pb¸ íç8í¬3XŒVÏ+F‚O,õ‹i²i&…™ÆýRŽEˆ*„ R_²/õÖjgfA !äsgµ“ $×8­´Èhdóõ n¬Í€ …ÄéO!m;ÌHnòo6×w éO&õÃׄÊ«vV[cÑZ!…ˆ/»ôÒ½g±o†HÂz@ËQi0== ð¼'=§^­+wåàk˜~èu`ºqâPn¦)D6é0l·g䉥~±f¬Õn¥p“ïUlÑJãûþ|·Û]7#°Õj­é¾Ò`ÓÆMÏïÛ·Wk£¼¾…­³°°QX[Üìe©W°˜‘n-H‹/ÝJ ‘c"+]Nê‹3‰†Åß•„÷‡'c°ZcExb÷ÁC×­ðÚÍ×®é¾ÒÆ.¾øb.¾øâÝ•0ìº¿ÝØªA¥:Ìú>aÚÖØþ¢ÎíªÀ÷,¾ôÀóPÚ2Zµn8ôí‰|X)j–%ϰ€tÆxí"•©Ži?‹Û9¬ÔTZ ðo> 0kŒ}ÎZ®±Y|Ýh1n'p!Da-ÿER_LÛâý±*<7mùgŸŠ™ž³ %?ðû¿ö† ×owóŽÝÿ+§†3³ÃM-ÈÜRYÿFk”24gÕíä}:ôÞ÷¾wM÷•%ívû©©©#×X¥Ñ:³Œ³¤Ä–Œõ‹YñÀXÁ?þ«ˆçwkü1gLO[~öϾô® #!ÌÇ‹ ½Åö„͇ª‡’Å(”%ðæçw­c?­™J €Í›¶äwM>Lj”‹hw(e¨+Ä–IàÔcÖÿ `Ô}°@jGŽÎñ‡wŒóÊ/‚žÀö,Û¯<ŸO½ïb’…c$Jæ7b,.øÔŸM”Ïþɇg€šBŽ"MÝ®a£íö7Zˆ¦¼TZ P îh»ýwû÷ïß©sCK´V(cð„ ý0$õý-€`>ÖTöïâ ï¹”'ŽŸ’k6i?ÿ$»õž‡[~f©/>0JeïâÖL“”l™Øo§k(Î8TZ/ly&„xDHñ*ëp£5Z)tšâU*ƒ@͉ҶÖ- 9ÕÑÌ~÷ 67ñ¤ÏãÍщ5Òóݶ1ËŒõ˹—BX´qFº÷IIâ.A$ívûëg¿‡–ÒÞ½{¹à‚ VuOi06¼ßÍÃ2iœJSËÜÁÜývh~@ÿß%†! õZƒÀxüÙ½ÌLO³mû6ÆÆ'XXè ã$S÷î VJ çñ¢4Íã†4MéÅ1­VëY¥ô „ÀUwòhVFq´Mé&Z»mÛ•6Túcý‰8HAµV§Å|ì7?J§3Ï•/z1ÿßåÖ×ÝÆ¾ùMXcH㸟RZ)5Œ(e±Úi¤$Iˆã˜4U4›­¯r޶‰[ •‹¨Ól6¿|hþÐ;ã$¦V¯¢³¤‹1OX·LôãNêÑÁÀ÷Bò¿÷qž~ê)n¸ùF‚J…—^Ê_üùŸÑj·¸åÖ[™MSWâÕÿ.X^³8·4I’$!J„Ôkõºs·$Àw¿ó8W½äŧܾ´XX^c·Ñ¨ÕóÎ8ŽI’”j¨0*E«ƒ`Àri[a²Ï~øï¨T*üéŸÜE”$LŒ12:Êヌn¾ é{¨DŸ 5ì"ˆZkÒ4%I’ž' IDAT4¥×íR­T;•JpßzôÏ™¢Ò`™8ú=av:^£^«U#*aˆÖ¢?v/Ÿ¶O º 8p€0 i´Z´<•$ìÝ»—j5¤×íâ•!æ/É( çûGqL/Šˆ3õŸ$ cc£ëVt&¨´X†v´Fî=¶œ>>ú(Vš#-~ø ¯ç¢‹vpðàAúMÛ|í?áj´F¥)Zkâ^DG$qL”$DqÌ–±±»§Ö³Î‰Õl2¸žt×]w-{þÈ‘©?Ü¿ÿÏŽÑj5©7›Œ´š4j ¤ôRàù+¼lñž~c A%`ëÖí¸@4Õz•™éš¤¿šO!”*ƒÖ© øƒNSææYXX ³Ðaf~–$JعcÇÀÚRrg‰®{åu'mSZ ŠëùhóÆMwMMù™N¯#ü Àóºž'=/ÀJT)µ[Ç?/)Çàû>ZköíÛK% ñ¥$šŒHSçI’8&Uifçg{„d‘¾<à'q6þ;×/îFLl˜ØåyÞgÖ·‡Î •ïxç;–=ןÜu¯ïû_Š¢èuIû¾³|U±ý-[°)%µZ-çm¦Ýn¤”h­I’ŒÛ—¨V«÷£yÝn—ÉÉ#L›¢×ëeû[òø3Ó3$Ú*AøÌ§?ý©öìÙs7œ'è•®c—Ai B TÜ7FfGõÁüÒþ—ïù,,ÌÑl5Ù0>ÎWݻw3:6Æ–M›¥ÕlÒjÐj6y䑇ٻû9ZÍ&Âóh„5úÚר»w/ccc4 Ú##LŒ³eË<Ïãk_ÿ:OïzŠ«¯¾ eÝnD­ZãñÇ¿û±={öLõ»‰Â{—Šn¹å–%çJk.¢âþa>$IÜ}÷Ý¿~û[n¿ÍX³yÃÆ <óì³a³‰’!dŸ µZãÓÓ<ùÄ“`->ú(išR¯×‘¾Ïc}‡k^z žç¡”+çw‹Ç¸å_&OÑj´Ø´q½îì?ðù¯|å+Ÿ6Åå¹r-P: 033Ãèèhÿ÷² (E}æ ºgϞɯüíW~ùÖ×½î¿GÝž¨×ëT*ÀùüJ%H<nêÔ‘ÉIŽ=J­V# CªÕ*Zkægg™«5VÒh4H’¤ðƒÀ Gm·õ¬°–$IŽÜ÷•û>ª”ªá½x)¸|Qâ<ˆX*š™qQÖÑÑÑÒÒŸMçtÌÇ©ÝÚÃ?|ÿÈHûOv\xáOmߺ•™¹yL¶Älš:AÅgãy›‘R’$ žç6¥t ,F4GšlØ8NÇ %RHªÕO:U«!a¥Â·{LÝsÏ=9räÈ 0ä¹_»è€’ÕþÕ_ýÕÐï333/¸}äô@Ô€&PýÒ—¾ø—Aàoûùù ·^x៞Fk …ÒŠ$N1VsÑ…;¸å¶Û¸çÿ}QÍ«~-Õj•¸í6šÍ`VÓ£R©ö·¯­VªŒOŒóÐC_³Ÿþ¿Ÿþã}û÷=l:Ù;šÂ1Xµ¢P=°ý´&*³ ²ð­µ!D(„¨ãß´Ö¶€‘üçm·ÝöÓÿáßÿ‡—mÙ²™©©)â8ÆóÜÀÆ(|飅äÿÉ]|û[ß@aµÊÿÈðš×ÜLÔ‹Rö}@£Õb¬=Æïû²ý¯úÐßìÝ»÷ @,„˜æ€y`XBt€ÈZ›!RãTQQ#œ3Z,ý9•ùûµZMÔj5Okxž !ªBˆ†1¦IÆxcÌHš¦qk­Û×\sÍk>ôËzÙ-·~¿˜eòÐ$‰JÜ^ÄžG­Z#¨V8xh’n§ËøÄ8££tHÒm4A½Ñ`ë¶­ÄqÄïÿþªøÃwÏ/Ì?A¯R© ‚`F1O)å¼bÁÓb¥TÚív•R*/R?g´ó¡Äð}_\vÙe¢V«ùÖZ…5œä71-kmËZ;’$Éh§Ó_XXët:þØØØEïz×»^óî÷¼gä‚íÛB0yäùyTšº1%ܪaÆfu’J¥ÂÄÄ8ÍÖZkî»ï>~çw~g÷¾ð…¯j­§Û£í´V­ÍÕëõãAÌJ)çq’?/¥œ·Ö.]cL”¦iÚétÔìì¬ît:笓O6e¬´¸ä’KÄå—_.ƒ õz=Bäã~CÑ´ÖæÃ@3MÓV·Ûmu:V§Ó©ÏÎΊN§S½ð‹^tË-ßÝ­·Þ:öÒ—¾´¿ƒ×rQF·¼›aß¾}<ôÐCæsŸûÜžGyäáN§³·Ýn›F£¡F¯^¯/Ôjµß÷;Bˆ ÿ9/ c3!’$I´1Æ|æ3Ÿ9gÃÀ Û·oo}ë[E«ÕƯ^¯ûBˆPJY£ ÔŒ1õ4Mkq×z½^Øívƒ(Šü………t~~>ô}ÿÂV»}ùx{lûÖmçoÞ¸qcE!›Í&ó 6Ž"sèà¡ùž››{¶Óé<ÁÑ‘‘Õh4¼Z­¦kµZ†a†ax^„”РÆÚŽ¢k­í !"­uš¦©žœœ4ŸýìgÏ >ö±´M)½k-6l°;wî¤R©Ø , … PRÊTJI)‹‘7¥µŽ•R~’$^š¦^š¦"IEÑ¡8ŽJ“´’ª4Ø¿EQÛZ+=Ï‹Â0ìÔê5uÅ‹®ˆ*AE×jµ R©ˆjµj²çkß÷µçyJJ™â?±1¦g­€H1ÊóBH!¾ï[ÏóRâyžqX+„Èß!Åy‘1&²ÖFÖÚÄZ› !”RÊø¾oÃ0´Ù°³nÒªŒÏ©”C@·ÛSSS´Z-!„ð|ß÷_k]BT2 BT€PJ!|²˜AîFæÌú!„°ÖZ!…ëVJÙ_…4»–·16ß”1&µÖ&¸ ±1&Î>'@š$‰ ÃP÷z=»ÿþuSÿ{÷®~Q²Rj€Œ¬1FŒ[­µBwgµÖZ#„PBˆœîïñ²ØAžè:„W+ê3_ãÖýQÖÚüÙ‰µ6µÖ&RJeŒQÖZãyž5Ƭ ó×ÂøœÊ DZ‚ÀJ)‹(2Ã/^á(®Š Ãy…âç•ÔëfÃL1ʧ„iö|•Ù&ÚZ«¥”:Ógù§ÃøœÊp È?#k9ŠLÏ—Ï3‡‹AÀ¢ÏKžµèóâ#€.ýßs¦ŸmæŸ ÆçôB Ð_È­ðY1ÈÅ/fúé†cúùss ϙ½gùg’ñ9½PÓâäJ¶ßËPÁœXýS8w"F-ÇP³èÜâ÷9+Œß½{·«m8 %&/4ÀR5 kN]ÚOå9‹A²˜ÁgyŒßÇÙöÒJëþ­ý g“ÀŸ3ÜIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/dev_video.png000077500000000000000000000443111217176075400245310ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½y”%Gyàû‹ˆÌ¼kí½ïRk—’°A,›mX\8„Àÿ†Á/®ÞeÐÚb¬‘B"„x©üïŽQÙcÀ?w^Ô'>|Ÿ. ¶ Á_H©^†!RJ„ù7HÀbŒ&NcÒ8Ń@!Åe`EñàÏ€÷ËßÓ·áûp!pƒ”òSBpEH ¥$aR(%Q*Èåº1†$‰YYiÒétPJ"„±¼Gn~8õ½|©ïÀùÁ›¤”WJ eH‰R)ÝÇ!×q!,R”J%†††Ø¼Y°¼¼ÂüÜ,XJ ¬ý¤üWà5ÀÔ÷êžOÏ ÿI)õûJ)UDøZ çŽ(„¥[·nfdxˆÉ³“h ãõõqÜùðòÒò¶ÚíïÉËÉïÉ]ÿÇ€ ðçJ©ÿE¡ À Xý‘R7ëJ”J!aE!Ù9aèæÙÐðû/ßO¹RÁ¦):MI’ô­À/}¯^òû`mØ)„øïJÉW*f9=²ß‰‘Ë)J)ÿ; ÙùQaŒA ÁðÈ'Nœ@kMªR­ß|xúb¿è÷ `5ÜêSA\š!Ú!^厥º„ÐEx÷ÛFà9ƒÂZKÇÄqŒÖ!•Z™©)´Õ¤Iº5‰“w·Z­_>^hfz}ãûUàzà&àÅ ‹‹o™›TJ122ÌØØ(ÃÃ#¹gP)…”¢áJ9¤gœ ñI’¦)išÇ1ÖÊQ@ÜIÐqJ’&ÿðû\dÓPcÿ ¸‚° Ä ›„à)å-ÀN¥”B ”Àh8;5É‘#OòÔñãÄIÊeû/eçÎíÞŒ×ú”=º€»5qœ$qŽüì“$€ÅÅyfffÜö$!MõÏmôxÿÄ¿mÝ}ÿ³sìÃÍî[…7 !nB J)…¡”7Ý@ÏÒËŠ«®¼‚«®¼€#Oáþ¾É©ñq®»öZ¶n݆1 <Ëw\À!=CxB’dHI“oOÓcèT“ĉç—ñ<€NÓu÷ýÏFàjààf!äMRr¢$¥¤áàf«”k-B¸€1YB¸Ù}Å•WpÅ•WpôèS|ñ®»839Å­·Ü„RÆh´¶t:œÕÇqÒƒìÞÙï¾µÖhm0Ö'Îk˜èôEÍ•æ†Jú?1Œ/nn’BÞ&$;„Ò)k²×C¸›õÜwv\&6¢4apÙe—ò‹—ý_¼óKÜu×W¸ýö¤\.Ól®$½²¾á1ijýww»‹0Zâ¸ã9D|PV6râ8YwßÿH:€vX¸MÀ‹â)ÄBˆQ!¤dqv¯ðn(¸H™ÝS¬")Ÿ_K„k"\¤Ï PB’ê”÷à7eç®í´[|–; ?A'’$¡Ç4hµZNéLS†GGÙºy3oxã ‚€Fcñ‹Ífë-l`É%—\²jÛ÷ŠÖ¾MHù+ÖÚ7Ë,,ÌÒlµ ”¢E„QDµR¡T©8¤XK©T¢V© ‚€îs»ï ÑÆöû.zöÁKš¦X›¢ ¢ õøÀoþ6[·nall„v;ÎÕf‹…ùy:íV(¶mÝʮݻٽk»vî¤R« ´ÛmÚí6+++¿»ØX|ßFû+^þòUÛ¾ÆIòçûÎ¥Æ2OŸ8I«Ó" B‚@ÃCƒlÚ²™J¥L„”J!+Í6ËKËa@¹\¢Z©ºkNÀ3!<ÛþÌ÷fšqOÓRCŠ!5)BCj VkŒŒ qü©üÞïÿ;vlǘ„f³Íòò2ÃlÞº•­›7sÉþKÙ¼i3•J‰ h6Û´Z-:8Åêc-­v›æÊÊb'î܈K-{ΰô˜™ró|Bœ$ïKÓôI’0P¯ðê×ô&,.//377ÇäÙ3ìØ±ƒ±ÑQJ¥2Õj…ÆBƒV«±0P«¡T€µ™Ç¯WÃ/þ¾ „{äš4Åà}Fš“:?¶n kh5›lݾ•·¼é |ý¾û¸dß>¶oÝÆÞ½{¨×¨T*¤FÓ\iÒjµh4ÄI‚M5©Ñ¤Ú‚IQYK'4›­¡$M^ÆÀZ à=`aaq#îs.¸±ÙjÝ_¯Ö*ƒCXk8|ø1Μ9Ãââ"Ɔ‡‡c×®]4 N=ý47Üx#£ž’8¦±¼ŒÖHêÕaæ¼Yj–”§Ø­ý ÆgãƒÑ“R¼É¦A¤Æ!Æ„1ù ƒ0ÚköAJjÀ‹°–BŒ1DQD’¤nv{ï`’$è4uâD‡ðÔ8b3)Fƒ¶.,MVš+èÔüŸÀG7bðÿÃß°j[ÈÜ“Ïkedx¸R*E|å+_áá‡âèÑc<ùä“LNNz‡KÈöíÛ¹üò˹ýöÛ¹õÖ[9xð Û¶láúoDHI¥R¡Õjcµ¥Õl#ëÒAÑïß‹ùáÚ 8iÚeç©pîY ©¡½#&õœïLISáÅO(m5V[XqÄjçîMÓ”Ôâî罌&5n¿m\^€I Ú§œKéIR(bÜóƒ>`îù¼×õRÊo¥IRú¿ȷ¾õ->÷¹ÏqüøñuO¸úê«yÙË^ÆÏ¾ëgI’„R¹Ä-·ÜB«Ý&I¬1`,6P  ôœkŒ!ÕÚÍîT“¢1:%Õ‘Í~˜Ï|æ3«vÞvÛm;v¬ù¯ú­W1£gXzp‰7_óf&vMpðßò»ÿõwùàïï>vˆm;·3=5Íwÿí»¼ò•¯ R©!å‹”T›…vWÞðÈפ˜.›Mñ ¡îÎnÉzçôÉ”H“Z§¤)ÆZ„08kÃ!\A7cHJTúÜ‹Dxâ0¡@Ï\¨Úø„¥6µ„Aˆ¼˜ Iâ ¿A©\~Ëüì<=ôGŽéÙwÝu×Ñl6ïÙþâw¼5¦˜ÿÒ<ïyó{رuí´Í«ð¯ÿô¯|ò“ŸàM?úfúîÃDQÄÁƒ¹æÚkغe CCCŒŸ>’.°“¦º«Øãg·Àà;íÄØ£Úº ÑZR Vï4=¾¥R¸ô/‘åÈ.+‚ˆ™ÙYª¥ ÛFˆÛ1BZ±BD\ Ì’–0 Öõ[<¸ü²Õ®àç[TŒÖ¯>;u–{¿~oÏ)%{öìáî»ïîÙ^®”¹òÕWrà«Ø;°—“'8ræåR™-ƒ[¸ý5·sçwñ#¯}-J*fgf™ššâ¾ûîãGßúVê(©h,5”Âê¢òæmz/·N ½oy†ÆjMª³í ÞD)7c3¤É© T!a©„R’$M±F£TÈÌôÓgOsæÌi.»òj®½æâ82= ÜB€ áó¬Ö^\D`6¾WÀeqï>qâ‡îÙqÉ%—0??O»¯ âÒÛ/…ž>ò4#{F8tìÃÃÔËuš•&›G7£_¬ù‡Oÿ?ýΟæoÿîïˆã˜¯íëüè[ß ÀèØ(ããã”Êe¬‹Wì´·Œv¶»v®\SÜV!\)¯•K?ã»Õ?.»HF% x«¯¾šîãôéÓ|õ«_åÚk¯¡\)SŠÊÌÌθ‚ ­1Ö¢=³p³R †…½ÂýÄþ¢„À*I9Š˜I½>@D¾¢(¤\.S¨!BHff¦‰ã$ÏLÎ\Ï'ôq€¿™±¥V÷Á V«­Ú¾¼°ŒU$#œ-o Úh´Õcˆ;1a%dxl˜ñ§Ÿæ%/y O>y„’$! C¶mÙJ­V' ]>s¹:ùÝE°Ÿa;ߌ*(h²`®yç‘J"„bûö|ó{¹ýö—S®T˜žš"ŒJ Ôy龜¿ý0Xc,lÛ¶•z½N©Ta˜Ÿãð#òÄc122ÂýÈ3yv ³Vï¡õÀêç$*ú¢x²aäjäÀ±ºìA044´ê„¹“sTöV@ÑM°LâÔe×t:–[Ë´ã6Q9âé“ã\yå¤iÂÀÀ­VËUç–"†ˆMŠ Bï ûä¹ìÊ`27¬Ë/ë‹ )$lÛ¶…K÷_Î_ü¯}ýë8qòÃÃ(©¸êª«¸ñÆH“” XZZâ±ÇãäÓ'yø;19þ4±6$q)®¸æ†‡Fh6W΋¬9¹úá[ßúÖºûz s¯n LJ$ÃÃÃDQ”gÆÎÍͱoß¾Õ'<2Éîkv»¶KZíN›V§E³Ýd©¹ÄÂÒ§§O“Š”ÅÅE^vÉËi6›T«µžw`qi™(oçRd÷Âs“kãÁ^?À—‰ Ncï*lîZ.QpóÍ·²²´ÈÙéYvïÞC†h­YXXàäÉãœ?Åé3g™c~n–V«C»Ý¤\©0\© „¤Ýét:@1¯a}0zý\ÿ~øØÇ>ÆK_úÒ5÷=ßàdT*±iÓ&¢(Êkê———yôÑG¹õÖ[W0ýÝi¶½uÁ¦€ôLÊrs™•ö ËÍe%'óà dbz‚F«ÁäÙIFGG¹ì²Ë¨Vk”¢R~­R¹DØê Wž Œ{þGHg PÔÐ3±ÎT”NC¯V*”Ëe¤RŒ 3==Íc=Êé3g9}ú4Ë+MÒÄÍîjµJ¹TbӦʹãK (,Q¢¥d^‘9"2°–fnÌú•>ëÁÖ$‚>Øpà‘R­ŒŽÕ†††ˆã8'€'žx‚7¼au†ŠÅ2{p–¡}CÌž¥Õn1·8G9rùRJ,9)YX\ ®Ç Q©”½-`0Hœ+¸T £)¤Óæ 3¾ßþ&3³R¹f^*9-¿•J'¦&g8;u–ñ‰q¦¦gh­´H’˜0Œ(•#jÕ*J ’U)%I¢&C”1¨@!ŒKÆR`½¸~êÚ…#ÿ\ÐCý^¹ €™0 '¶oÛvÅö;8qü8Q144ıcÇX\\ä/xAn¾•¢ñÁõ6Ã@æ–æˆÂ(×!’4!b&&'xÝͯ£T±hÒTÆ':‘D!å0Âæ½_Š}}”ó½+ðZ­F©äZ¶Ûm&§¦8{ÖÍî³gÏæyý¥RD©T¦V«¹ÿ@ é9D ‰1)¤LQ…R!Bh` UK¹P°ÌìsÌØZ‹ ô@P`Ÿ& ÃdÛÖmìØ¾‰ñqÂ0¤R©°°°ÀÁƒ¹é¦›8tèA8NX¢W1Ø <º­™œŸtÉ’IL;iÓ0 ¦'§ðuúaÖÊ d„aÞ¡“Íxég¶ËÄ ¨TÂà @HX\\b|bœÓ§O3>>ÎÜâq«ƒ1†R¹D9,Q(¡Tàõ@¸Z¬DaÂâöK|3 áB"o2%˜@£¤ õIû9ÀsE~ýDÐCk™eÏÂ@±{×NöîÝË‘#GÐZS­VIÓ”x€7¾ñ Ñét(—ËŽ „SØšåÔ¶SpÒVÊi}šåö2CÍ!Ä‚ ³Ôáú\¸ÁÕ>E,ƒN§Å@4D93)“çÎÝ+ˆ¢ˆá¡!„4 Ž{’‰‰ÓŒOL0·0O'¥R‰ ©×ë= ¡„XaQ¾XEàn/4X BI$mƸD’4uÎ åDšNò)EG©¢>f7 ù‰ ‡J•ò†ÞˆKQ4ŠK/½”;wròäI‚ `ppÙÙYN:Å _øB|ðA¢(r³«TFEŠ+ç¯d`ë‡7vÔV ÑlИo¸‚Œx€[~à€\¦Ñ%'»#Â0Ê]ºÅpîØÈ_»÷ë<ñä“´[mZíXËÐÐ#CÃ>c§€pÙ­ô[°B 3wqO-B¶”/)s•HUWЦSB)‰Â+°ÍÒÒ"år4ŽÑ©Æjƒ5f;®ÇA½olÐÂ¥Œ_°bÁó¶Iœ´†‡†¸áúëùö·bffc årc ?ü0·Ýv“““´Z-ÇÊ%¢(B„‚«ã«¹rðJŽEÇ8»|–Ä&Œ qæ»g¸é7”2ƒ Ž;D¾õ @­^£R©ªÇž¶Æ004Ä‘£G¸÷þû¡TŽ뮼œ=»w£Ó‹u Å/‰mÞ!Cî=µN-ü» df~Z ÒÕZ\}ZÖQääÉ£t«¢J©ß–Rý:¬ Ö \ÅôÇŸ.8™ãÀ}ÑÀçÁëh±2*W¸ü²Ë¸á×röìi¦§§ ‚€Z­–[·Þz+‡ÂZK¹\&Š"Â(Ä–,õ¨ÎíC·SÝ_etl”ÉÉI>øÏäï{G~ŸV«ÅÜÜ»víD+|oÙcâf99=C½>@½ZÃXÃ5×_Íå—]B§“äþ„.»/›¸ =­jDV5l…×7V§r‰P‘;z²NäE0éÒZeçwk"óóÞ ­õ;Ÿ'·/|ÁçŸX`ph„zõñØ‘#®^ne…0 djj ¥×\s ÓÓÓ9‡ˆ¢Èq„R‰p d`t€§O?Í_þÕ_RŠJ¼ëÝïÊïqÿ7îgçŽ](UD¶]Ó›– x $¥ BHÁp}k4GŽõ½ýœ²êîE%Â0ÌŸ«R©P*•žs°&K5ËdÅ%Ùw’$«ŽËJËýûü pø­ ½óŸáWõ×Ö}†þÙ®«§Š²kÕÍf³Çm™ÅÆ'dÝB²>@q罊÷è'¸¢V_†RŠ4M‘RR¯×iµZ>|˜‘‘*• J):q³¸¸ÈÙ³g™ŸŸçE/z¿üË¿ À“GŽð÷ÿ´Z-*Õ‚ë8óºþtc HC ”¯/´Hº¥éY¾@‘=k­s+ I’¼#2û !³ëû÷e×ÎÎ-EqеÄCñ~BžEúÐEáàãZsÏ=÷ð†7¼f³É'>ñ‰¼®/\­5óó®}ZqÓl6™ŸŸgdd„|€/|þsÜs÷W9öÔq.½l?òÏߣz_{¥\Cù ^+k9ÂW7¦èÓgÿg¿‹÷*~gA›~(GñZE®Ño½ldÔöùN ÜËH)Ù²e+ßüæÜñ±ó ¿ðólߺ?ù³?aaaJ¥B†y¼ MSÚ¾,Žc¦§§¹ä’K8øíƒH)ùПþ“SS9zŒáá!ïÃXMyêWßók©T+±†žø&.ó7Š¢üÛõîz'‹ç\Èwqf9M?'(ÎöL¹Ï³Í¸("ÀønXcc# Ô9zì8÷Ýÿ·¿ü\{ÝÕÜñ±ó¥/}‰ÅÅÅ|h­i4,//E¿ø‹¿Èÿñðþ_{ããì¾tcc£”ËeÂ0D¬2cºvym-R@¹žÞlÈÉŠT}NA)GúÅ—†ÞQ4›M¦¦¦6ÄuQ8@fçQ®Ö¨Uk,¯¬ðõ_çª+/çïÿïþÙwñµ¯ßË·¾ýmçç1ÆP«Õ¸å–[xûÛßÎØØ‡¾{ˆ~äCìÞ·Ÿ‘±1VZ+TªeBåÓÿüv‹J¥¼*f.|#©0Œ(—+HáÌÅL„ZkÙ½{7û·Ëg?ûYFF2wsoŠV?… ké E±Pd÷™ç2Žcn¼ñFÞûÞ÷ròäê\Ë …‹Ö'PkM­Vcpp© R)‘$)‡9̉§ÇÙ»{7oÿÉŸä?ó3¾¢&SiŽ=Æ?ýãg˜š›ã%¯x[7mæÐ¿}ÇJ9OѺ®/¯í¤„AH¥Z¢\)³|ºÉòbƒ™¥EvïÛÛ#ËK¥÷Üsa²eËWl{ÍÊç*‹×ò1ôƒ‹(êõ:Aðá˜Ã‡ó¾÷½/W¢ŸËs\40FÊwüp9qYGív«ÅãO<Á‘#Gرc %¥0dn~žV»M}x˜-Ûw‚uÅÂÕFaD)*­îoЧA@Ÿçý¡ IDATµ\æá‡¦ÕlA)Ì·Û˜>:\ ÿºë®cÿþý9\,ȸMEŒŽŽrêÔ)>ô¡aŒattÔG)Ÿ;\<°Î½¹yÓfçh ”sx ‘ÛÞIâúãœ={!%££›‰J%Êå²OÛ² $¡ d€ \C©ÌY¤u¯/…*hßP«V?É'ÿîo¹ù–›yýk_G³ÝæñÇwÏØ—c­e~~žÅÅE_Ñóü@‘Íg ”bppk-ý×Íç?ÿù|_¦|n<ßiá9ßý¢Z¯Q«V…dªµ •¢TЍV«!©VË­sÕÌ{È ƒÀaª€(²  x‡L/‹fU÷ÿ€r¥ÂÜÜ<_¸óÎ<î¿–r'„ ÓéÐjµro\qß3ÁùrŒì³&—QQ«Õxê©§øÔ§>Åôôôªçz¶÷ꇋ×+ØGˤ” "”Bª®}kq5öQ:¹'x0=ž6ÄP9ŽT¨’d`x£W[ñÒ;sܹn¿ôíÝ‹šýZš9|:NÞºxÜzésE³ð|gif&As»þçæÀçuþsç½. RJ0†ÁÁ*å iš¸'0žr›;óôx¿¬AYX³GE%ëÌÎϯâR¸–²Ö4wºŠWÆ!Öš=ÖZ‚ ÈݾE×ë¹ ˜”ÚŸd»ÑŸ£V«1>>Îg>ó§õ—Ý?Ó6"‡ó¢v —Rº<»@1::ÊìÌ´‹ªÂs×N&ð,>"Œ)h¹6Ó²¼|ÁÐð0•j3³ºúH‹ª/ÏþüXw¶L±øù@6›³ëœ 2ÄW«U¬µÜyç=)ÜŹ@îÚHsý¢€µø4,Aª-ƒuÚí­VËùÜq³Aå©R®çk€$PA26:êjõÖl!t¥Öù6¿Sÿó­>?sH%IÒÃúY|¿nðLéõRƒ  ^¯3>>ÎwÞ™Ïú̧±*-Ì;…2ÂØ¸ˆÀº¾¿R!ë–122‚Ö)ø5^,Ò/¿Òà‘ãñ“ œc™uªÕª«É_‹„«ÿ³ÞuÜX¸µ 㙸–KyÕ[žÇ¬BP«Õ0ÆpÏ=÷ä5’åry•³©x½ÌEô´ÊíÆ6ž³+øù—+]Æ®§äáÁ!–VVÜ H[ÐÂu @©€0Š|ÝŸõ&fï ¸Ù.¥ÀJáÖô†uWJ̽8»3GKÑ ôL°Þ1Ùõ³<ƒññqxধ§]*\!·à™®±‘]/® \äMHáÒ „¥u!hw:¹â¥”$P’(ó¡¤R9K.E.ç¾Ù\ñåÖ…Ô¬¸o•Û·ŽLäšÇöCÁËt€bô.Û¿Þyk=G–ß`Œáßø<òRʼ<î™Xº"¹ÄsU/®àM+‹péZ>c'ô¦_ÜnwE@„Bº«Ôj´[-jµšw$…€Íd\_Ör^k¥•À, §ŸÎunñþàXwELNNòðÃ377—¿ÇZ²~½ëe&íZ–ˆDŸ_°ÝXzŸœÖºr«("ˆœU˜³ËR©ÄüÁá«_ý2?ôš×ð¿ñ[”+eK’(ŒÖ\ÉØ.ði{Àúø_O ì.ðÔ »ž ΛÕC>öØc<õÔSÎr:'âŸId¢q#à"r€,R«U±Þœ¸ð¬Å¥]Ò/¾¢0dpd„}èO¹ãŽ¿dllŒ¿øèÿǾ½—pë-·0;3K…¨X­1hîúOåî*²Gœkæôëù•ûâÿýç@ן155ÅO<Áòò2•J%Ÿõýcs!PL(}®pQu€ !ïˆ!„ȳkNO³Ö7k²‚ T¢Õjñå»îbß¾} 188È>ÿ9®¿î:Wüé ?ײï]€b(Ø•oxcîœÏšé#Åt¬U×_ƒ¤iê;…';vŒ‰‰ ”R ôÌúóEÞzD¶ŠàM7Ýt± ›òä«(\Ù”G~6´Ž ü•’(˜œœde¥ÉÐÐÕª[$bee™¹¹¿˜DÉìê.g6/ü\÷‘p·ZmfŠV&Vî“42ÈÄ›R*/xiµZynã…˜içclTdò¢@ŽàB›¡œN Œ À!]»6 î`ëZôÙg>|)aXL.Ã0ô•;îd'R\¦-r‡Œ ¨èb-BQœ ²Ò4M™˜˜`vv¥”j[É+Þÿ| »W¿+øÙÄÉ'.ð»ïóƒÛmÏ’=º(pr%:Mcÿþý;vŒz½N§Óáºë®edt˜™éiŸÍ㉩8Æ{•è‘ù¢°ÝÇõúIf$I²&Ë-&ˆ6 fffH’„Š_çè|µûsAÿqEÙs…|ð|Œ¢·¼[ ¤°y’§„ÅÏ/#…[tAŠ·ýØ‘¦)§OŸ&MS~ìÇ~•SÛnñôZƒ-ž+ô¢Döà=dd¬¶?5»Ø¾%I¦¦¦ò,æ,?1S‹ŸÌ î.;¿úSÇ=“âXT<7z`Ïî]tòÓ§ÆŸù ²¨‰ •»…?@Aa˵CѯÖzŸžuÚ¿1‡Q´¶­Ÿ EæðÌzoQÁ‹ã8gõÅýçõÚ|œÖ:¯•܈l kísã{vï:"(€ÝYi­[AóÏЕû „È<¹çЇBIþÿªûç^vØÏîáÊÅÖ#ƒÌ¾Î»µJ¿Ö >y&8׬?§(©úÅÀ…ë⹋€Œk\!dQ:%…ïë“9gd׬+|‚ŒS ‘õõ+Gá\÷íEy6‘ÅúÇœ—)v™mÝ™3gøùŸÿyÞþö·÷$jô›jëE!¡—`úŸ1Û߸þmÛϼŽqS­V™=¯èä¹á9r€"\!¸kÆhEŽÉ#wY;×åÃï÷VBÖËO*…~‘Åõê} ˜”’8މ;1Qb­kûb}_¦à !ɉ 97(•Jy@+k±–ö_DÞ3} B­µyä1Ûô$¥j­™eyy9U<["8szbã•À=»wqòésAî%óŠ`æ ”¦¹ËfzQß2™½ï;~z1aaí¢þ€k#Fe~é—…(ìØµÃ¹ Ó”þìgét:…à’[Ç8k>}2·töY+ôÙ@¿³©¿:8#€ìÿ,Þ¿ÿ|¡^w=§ž+`ïž]œ/.ÑÛðPàܾ]-ßÏ")ûñïEÖã×¥ù8‚+$É®aÏ#:æÈ ”t‹GXŸ`*+++¹mŒ! ¼[GÇ”J¥<;X)•{üúI[î×ÖÚÖôõ<Ž@±̪n!À¿/€s›3×)KH7XÙChL7”¡Ö_'ã‹)\‚i![ëFÞU,ºÿ¶[_/¡Z«ÑnºžµÖ¹†iÞ!$Sº²òðl{1FPDn¿‚WÔúÛÅdDÖïr.šžÅ”ôLȶ­×Cà\°gÏžü÷óF»vî@kÍ™³«×ª+ÝÒ/a}ö™W’f~"›B×<Ì>v•¡¾ppþg5y¨  Óîðð·¿ÃSÇÓ\Yñ‹R·HÓÄõòõ\ óÁAàûG` ʧ²X·:•[Knhº;Ûsc×­y,ð2Ý-båX@ºobQl•I¿8ð¿ç+•Êyõ |×»Þ•ÿÞh(N{ ¬©!$ë¾în©D~xfïgûƒ,JÜÅXí ÄqkÝÔï^!•r™'᳟ù4£ccÔ«¤¶ÛyË ³b µj•-[·2:6ÊÌô,+Í¢¨äD†p}þLÿÍó ½إΠÎ8F¦ý¬uÕÔq¨ð‰0 Ÿ2ÆÖZ[ðÿ;ãÖÇ1»wïþ³W½êU+œüøÿx>nE¢ïw6×$™Åý„ÍY¼ñ)\Ý£»‹5@ד(Èzðf}û½kà§å¯ÖZ‡†ÝD¥Z£T.Q•c} ¡ã’K/a`h¥¥e¦¦¦™[p÷’-ÿ,²¥f¤ cIÑí*…ÄJ7Ò‚Ü’7w¼{g7Lδ |*¥ÕXæ…/¼æo¸þú?M’¤h›QKáó‰O|¾êU¯ÊÆþ¼Œk>èGl†øbžb þ+”K •V …oÈh¼ã§p5[4 2Î \†ts Äj:sìÒ˜\…íÖZÊ%SÐ:¥Ù\AJÁèÈ({ö]ɾKö±ióâ8ezf†3gÎ0==K…a Çù½#*oô@á|ÊýAªÂ{dÏ«$ÊZ¬ô+—ø‹dþ!A€ Ã0 jø–è]D¿ãï(â#ÍuðÖ3>Ï–ÖB¾,|{ãMbÕ1.ø±ð¢âh»3Ñ{7á¸A)t PX¯(YD±ÿ¹Fƒ¨ â8fÇöm Œ$1W_}5W^u £cc$Z³´Øàøñ§}Ð'äúëo¤Ñh0qjœ…Æ"I*°.R…õo,'êrkFx®%"„?Öv‘/„u]ˬ %RЍàÖPÑ…¡KÙwñeÏ‹<[èŸTEä8«µIãÔÏî®–ßm³5Vî®ØÑkB ,®…‹’ÒeKéó ŠÇI´p‹M­5®ä[óüÜ»i4–Ke–––8yj“çú)jµ ív›8ަZ­²¸¸Èä™34[-‚Ð-ç†+ÜK[áþw™O8÷·G´Ò/[ãßH:'{ߌ(¡B†¸€kõÌ^LÒÇÎ.”Ö’õ²ïd+ ´ÖIÀžýÀd“ÖÎã×M¥òˆ/°ðû­uád¸ÁµY¬¾p€®kˆW5l¦rx—îÄé ÊåŠW¸RGÅÞ×^òÉÇŽå›ßüÿòÙáCù££c P¯×™››cnnÎ…‹…”Ò‡›eÖ3X:“e»9ÙìÏ ¾À ¬‹qdæ§2"è³E‘ÐMˆìÂ3r !€"eá;cùÊ_/#„Bˆ Ÿ »Â‡ +ÂӮ̂µÎTT«ÜŠÂ’6ÂÍ*¸1p%Ù½Í&²‡³Ö¸ëâbV¬³ÂP¾„R’ªÏÞŸŸ#Ib–®‹è7\Ïë^û#\yÅ•|ík_ãÇ~ìÇóuÇÆÆda~ååZ„|ÜÀú™,°ž­;‘&AZïÖ–ží{"—]îg­ñ«“‹‡ü¨ý,?ûmúþ?'œ/ô#¿HËÏúVî·ý˜n™õLfJ]9{ra]â¨Â™~rÿðÑB)„'¥‚\šä—ޏªdG]R(d(°iŠó€zµÊѧŽñè#‡Ø·o/7¾ðöí½¤ç™·oßÎÂ|£Ç;—õ Þ¼y3CCÌ/ÎÓn7Ý I·HEæ«pn °ž0VôŠoÞZ(r€Œ²á)Bê·er«_ <'x6" (÷ƒÂw„C~Æ®B\ Ïq€bN]6Õ.QÀGƒœòäbýÙw–/«¸ù ¹µ}²æë‡˜\GnUîÌ5ë£Qqvr’ÿ÷;ø“ÿößÎÏít:œ9s†S§Nñå/™W¾â‡z|ðÚhLl#„v»ÍÒÒ’o}+Bå*Y`õ23­ë`"=¸@˜Dz¢–Bd*ÌL@!„Í0Zk[X<2Ó2Ä?gðLr¿¨¤D@ÙG@$„Pýna)7ý֜Ý!Ë ¶ødN%©DõTqx6)$RHkÝRìÊÙ×]­ß ý,í¬¨[ Ò/ô2Pà“Ÿúï}Ïÿ•#ÿìÙ³;vŒ'N077ÇââÛ·ïdïþKi7Wz- 묒,xEccctÚmÚ­Ö-Ô“Å# âª(º„·”ÊV3¼ÆHhÝšÖ;ƒ `¬µV)¥ƒÀùˆ2Ws¦?ôáoMBè!€Ÿø‰ŸèÙùÉO~²ûžÖŠ4Me†ÂZ+1R¡Œ1tü.B”€’µ¶ DÖ:.Ð{7Ö+ƒ½ žõ4&„òì±W…ÂÉJ— :—«é®28EñGv]Ö‹H)QaH£Ñ *—8qâ>ú('OžDÁ–-[¸îºk©380DÇ™YˆÚv¥›S8ÐZ#„ T.F%’¤C’t=´!dÉò3„eV€1† Xc¥µñ ŸqkÇI!„ÔZË$IL2DZ°Ö ßÓ8õg-@’$"Žc©µÂ=±­µÒZ+ RF8ä—Œ1e)e¦Hר©xYWw¨¬aÆv‹E¥ô:‚ˆ43ïºQµL‡P~)˜¬‚¨')D¸XB÷¶ûwG[úÅXËæÑQþþï?Åž={IӔ뮻–ý—_ްj¢“„ؤd9‰Yf±É&šÀ[æ>†o5JJ¥2A ISƒ1iŽôþ¼¾âoè’hmIÓ´œ¦‰J’Ti­•p µÖR!”RÒ#’$NGøry¡µ¶ív;ëI 8ðÌ ùÆJ)Ñjµ„µV´Z-%„PA(!D „=uf" ’R†ÖÚÀZYkJN‘íÞ?îtX^^fóæÍdÙ.y¥ Íë¡ F gcg}„¬µXcz«nmfaH´6Há¾n¿ñ¾{'W–—xÝëßÀ?ýÓgؾ}W^uQTbe¹éšQ”",P*—i@ÜnÎ Í Tc-£Êt eŒ‚;Ý, Ö:²‘d÷ƒ1ã#Ƥ´;奥e•$‰´Öæ¢×Z+•R“ÈÞ}ii‰8vë,ÏÏϳÿ~yän¿ýö5ï×Cårïªa=zTìܹS$I"Œ12Š")„BiŒ „¹ Æz"Œ1¥R¹…¡"ÕÝF=»vïæ¡ïdÿ¥—±iËjµT )² ‹"{Po!äq§\qÈe¼ ` B dN` ¬Aa½ß?¡^¯óîwÿZkÚ6ËeTèˆöÌé ¾úÕ¯ðà·â÷þŸß£T.¯JÊ ŠEþ¾&s÷Z ¸$iss6óSÀ´¶XÛMýËÊòòìÔÔd˜¦Z*¥„1FdÇûA‘‰@t:Q.—íìì,ƒƒƒ,--1<<Ì‘#Gž™>þñç¿ßûÞ÷2îzŒã˜ùùù,cFj­¥µVI)•µ6”Bz¤gÛC°ê’K/sZp*0Ú"•`ß%—P«×?õ4ã§)—K »ˆÛècc£ Ô!·‰EžÖ-¤ñ6¶@ØBP#p‰ÖG¡¼Qô+xsõ‹>^'± ¤):i¶œ&¿g÷NÞÿþpÇã¾ûîåu¯ƒoBÝubŸÁb]Bôý |o§ýÛžX¿SÞ´{O!HuˆåùùùÉåå¥ÐZk×ȱÖZÑét„1Fd&‡‡‡ ‚€x@4 û¦7½‰+®¸â™  xá£Gòµ¯}«¯¾ZŒÓétD§Ó‘ÖZ†¡Î¶¤Œ1J8~Xk•µ6ص{¯‚€8IXZ^bhh€Í›7³yófæç˜žšæØÑ'yJHêƒÄIJ’&aä”­¯ão§¤?ó¬Íz eŠ^¦m;ÓP ¤ð&£ðåþX)ˆÊ3Ó³<~øFFFØ·w7W]}}Oþÿ 7\ÏáÇ÷&¨C±3Â2Êìæ%ô$„d"Üš Ý.ënÜzÁÖ¸KYo[è´[,ÌÍǤc…K¶ÝÜG{€IÓÔcŒ7±€=räà¯þê¯8|øð_þò—³%^­RJf›-m­™R(¥”Ƙ®ª ù¾W¼âU”<iw:t¦¦©Õª=«”Œ2<2 ¯25u–ñ“'¨ÖjÔ¡ì{H)qëîÉ>qæ´šF)gêÚC JÓÔ*¥2Ÿ€©V«vff†‡~ØüðÃ9>×ç&€'žx‚ññq{Ú™eò(óH !ŒwLåT©µfeyE?òÈ#§n¾ù¦«U 0 Ôk oCÇ1ó ÌÎÍy_|Õ/(1Àððp^m;2:ÊȨãív›…ÅEfgf¨U«¾KœKˆ<…ØnÖjãý ŒÌL%Q©ÌÌÌ ƒƒƒ4‹;zŒÓ§OÓ‰cêõ—ìÛOPŠØ46†µÚ»×R/"\Kã¼P.¿ ÑRŸÙã2vEVüìŸ+Š\ y³Ù´gΞY<õô©''§&Ÿlw:“a¤¥rYEiONžMŽ?™”J¥T‘â\¿©µVK)µµ6û8Žíüü¼m6›¶ãÛîyb{v~€4MY\\¤ÑhØééi[.—mV)e¥”²µwNe¿µSLµN’$øÎC=ößö£¯ ‚(huR¢¨Ì¶-[°Æ- Ç1‰ëËÓOŸäøñã¼øÅ/,õꌌŒä™¸ÛÊeغ5F7Û½¯Ÿ¬É£›íJHŒõUÂY÷ ëÍ08…ÑhFFG¸ÿþû&M¶mßÎÎÝ»(Ge§jM܉}h¹ë¬q¬Ýymª‰Ó´‘1cÜý£å0¤T*Ój59sætóÈ‘'žzêØSǧ…­rT²¥JEÖ¤iÇ”Ëfaa¡355—Ë•T‘H)ckm ¤Æ­µ6I’˜N§cã8¶ÆEÌz‚DëÍþs@Q‘µÖZÚí¶m·ÛV)e‚ 0€‘RjœKRgÔiŒÑRÊÄjbüÔô—¿ô•_÷ú׿Dw:\ChE”…c—F¤%`zzŠ¡áVšM—–™›_`||‚( ©Õj çÜ({Tk ƒƒ£ w}ýNœ"…E€t¶?„1.vtÚm^úƒ/åë_ÿ{÷îcÏÞ½”¢q’²¼¼â®Ó'”w&k°Ú¦·L¸[«À1CfJFe*•2ív‡S§N%‡}÷ÔáÇ?ufâôY¬i•*UÊ•R†%­SǬm&B©´Ùlµ–—WâN'ÖBˆXJ™¤išJ)µÖZ§iªM¦D¬ãû?8'è·fÀ)B»¥94NûO½¿?ñ׋3±Bj«Íç?ÿù¯í¾éæ›w-,.Æ1R¹žÿ2”"ŒvìÜÉGŽP©”©×ë´;mtâ²b“4¡±¼Âââ"•J…ÁÁAVV\dšÆ=ËÆ !òžD®+DVXê”Gƒ‹ÄYcäMozsή›í–Ë&ÒG& h§™§6¯ô!4ÖXtÖÑ\ ” )…Šr¹Š1)gÏLš»îºküßzèÔ‘cG'’N§U.—M¥R±QYq§‰°¢#¬ýøu"´Öq·´Ök­6ÆÄ@‚ºð]ÌZ"~6`-BÈ’²›dDZk3/U–¨pÞ*Ljâ8ŽÛýèGÿøén¼q犯¸ItŠÒ)J*’Ô-Œ´eëV&ÏLrå•W†K™Ö–TkŒÕ` :µÄ:aii )hP*¤ŸÐ…PyòRäNšâ[Y!1:ÓνI)…ãÞͬµKZÅ+yNÜ ° 0„J”Bj• XËÙéisß½¦ï¿ï¾ã<öÈäÂüâr)Šl­^·ÕjÕª@%ÖZ­µî!:BˆXkÝ‘Jv¤Q±1¦c²mF így‘ŠÈ·…ïäóçE(fœdˆÇ ! ½Q‚;NØ4MW„ XXXhýá~ð#o|ãxýk~ø‡o­V “¦$&ÅÍÒÒ2{víá‰#³uûV¢(ÂZAy ¶c\ÖÉsHÒ”P®^2F ÂøNa²çE\±3å¬qN%ãƒQÖZ~kþh½'OXÂPjµZÖÒ~õž¯ÎÝÜ…‹xIDAT}÷='üÖÄÂüÜŠJWj¢>P·¡ S,qªÓè è!b!DGH÷-µêÊt´Ö±Q*q>]öˆÏfüZÈ_/9Äaá9p€] 0~ÚoOû¾3.ë·Fk½”¦ZJ)¢v»ÞqÇ_ýý—¿t×w^ûú7¼ò~à%—oÙ²5ˆ‚€vÜ!Õ)Q¹ÄŽ;yúäIöìÝçržÒ4þÖ5“ŽÂÀ#ÕP¶Y9Vo‘hœjª>$ó×ô&(ºÒt#…Ó ¬“烱a¼üŽ#AHÔk5J¥Ó33öÀýïþòWN~ýÞ{'NOL, lR«ÕU¥R³aX!dlR›&BɶõlH);F›¶–:–Zǩֱ2&ÖZ'Z§I³Õlà&™.|g“°È×D>i5³;s»·û>ó™7oÞìÚÒðò䵂¤š "­«÷ â¤;ÇeŒ©Ê_ý]_ú8(IÃWëªå«eªp¥˜l·A' ì°¾¾Þ»~ýúÝ/¿üâÞ;Ï™Ù9r„Úy‰Ö‰Ø{±ÌÖQ„ìÅ%ªP¨Jå`k0Qä ï=ƒˆAD×ïõwlnÖˆõ÷#i?”Wµb'¯AàaáV#Ô;g»ÖYa6©s>ñ­<Ï3¥”öìÙÃßÿîúÃßþæÓ›I–NÎÍÍ»xñâûçÏŸÿÊÊʯfgf'òv†Y–ƒs .@¬ñ,Hùá 2vnoHÜ:twº0;1Ìû_¬Ÿ €ÔÑÈR®K¬£•´ÖО˜­,3|ÿý†¹ví³VWWÿýÝwÂl8Ë2œh·±39 ˆ4kØY¥Ä zFƒH…Rdˆ”/F”/¼øBDŒ€˜º ¥Ø‹2¾œà,ËüúßÖŸïììì†ÏþKÚRÜ!ØÍ 5£L´ný=[ûÂÆ1Û”-§Þ¹]ç\ËZ›¥išN›NÙ²/…ßÜÜìolllÀÍV–Mžùàü¸°¸¸xúòååù³g϶': _ãÊÎ8G¼(P²ÿé£Gáþý077‚àJ¿{cXzâ„ÊÙÂúc‘J•.æÍ›¼zãÆ½«W¯Þùæ¯ß<6lJ)ÊÛmÊ[¹&Ïl™-"Yç± jÌND…2„Έhã=JI  §œ/l’$nkkkpëÖ­ç°ßÀB÷ï(ÝDeàÐÄŘŠu•H>Œ CÃ5èÅÅÅÎÔÔTÞï÷ܲ1)3'e¬€¤Î¹ 2ï}ê½OE$efmŒÑEQ(föJ©$MÓ‰………é+W®|°¼¼¼pùòòüéÓ§Zá—6œÛ‰BD¸}{¦¦ÁÜÌ{0`S¹ãÊ1{'˜@žg@X!···íµw¯}úÙ¿þøÅŸî»»"BDDyž‹RÚ!¡CD‹€@*ÅSiÐDbD(ˆ”QŠŠ Š•&£•6Ji›¦©I’ÄfYÊiš¹N§có<·/º]þËWî?}ú´% ÊK•0ž~*öª6òá z~~>=uêT«×ëifN sREâK¼÷Yë–ˆH""ÍýÔ{ŸTaOÊ9‡ÖZ¯µN²,kŸ;wnfiiiaeeeaeå×gNœ8ÞŠ}òîÝ{püø{09ÙÞ{ {”å=ôz}÷ùç¸ÿÉ'Wÿ±¶¶öC·û¢[F+ED¨µvDä*|à’-_ú@‘‘Ð €A$ƒ„Lˆ¥â2¢b­k¥XimÓ4µišY­µñng§ÇOžüh·¶¶lĹÓdÛC‘Ÿ €ƒ h T–eêäÉ“ ³ÕeT‹O¬uÚ9—ˆøDD’jåëžâqXFÅêj_AŠF"¢*§GÄ$kµò }triiéÌ¥K—æ.\¸03;;;ÝétRï=<~¼ ˆGNA·Û3=|úõͯÝþöÛÍÕµÕnoÿøDÊh MåPBj¥×Š‡Ê° }òÀˆ¸7>GDCDL„ €–ˆj7.+¥9@´Ziç¼s;;;¶ßï{ñ>´ìR??N^8O6Ánª±ÕA£áº‚pqI¸ßÜêß„ (•¢•R‰Ö:#¢„ˆ°š¾"ï½µÖ²snPýïpÙÕ¾ ³o|  ظ‘67ë{(ë šCazoÚR‡Üâ›rXÍ10T±YÑMGR©£á °B0„ÿ%æÖË›Š­îZ‰10„ no.äl:n†#ð•þ&àÀy#iè%Œv0lH†ûÍ2©K‘óÖ2D-{w0¬”P9®‘¯):ÆaݦÂ}p­PéuúFZ{L^×+bb7Z°õ`=Æ£òATǃĸ£‡Òb>Œ¦£%ô¼…å.R¯ ¦Øu qìµÊ/Á#¯×ȲF1ŨýXYìšM‰QoØZëc£Œ³¦7îeÆÛ+t‡-oô{°Óuk8Ø2c-8–]~ÃJ÷c~\ËlöÓ£ÊcçþŨ}èO¼E ð2iÒvìø8åÆn yNäG!V¶ìqÝÉ;%oš^&áƒl>d€ƒÊgÝØ2QÞTê( 4=roµ¼K ðªòsnàkµ‡)o¼ªüO+s”Ælàÿå–qÌþ$›æ6'‡§IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/harddrive.png000066400000000000000000000135401217176075400245320ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ'IDATxœå{I$Éuæ÷ló%¶ÌŒŒÌÊ¥ª²–fõÆEl²‡Ó¤t’Zºˆ 0é +9Âü(Bw$Q€æ8Ž.Ã뀂¨ CvOKê®nu×Ò[-¬ÜcßÌLs÷ððŒÌ*‰Ì8Ò2<ÌÝÍí}öv{AÖZüÿ|°ï ü{âYnú¯ßý/½×~ùëLƒ*ÇX‹O?ù„~ó[ߢþ``î|ø!„pCÑ™q¨ò¿~zöÞ³u–áæsÏaem•ýÕ_þ%„¦ÓéÀ b q’°Ÿüø/~þƒÿögýg¡ èi"ð;¿õ[Þó/¼ø‡_ûúk_°D Y‹ò k1Nisó²,µÓéÄØ¹´[Àpñî^ªwÀZ‹  ¥¤££#!¬Öœ3hcÔßýÍßüí;ÿð¿÷ßÿüÏõS©Ç3p€Ö拯¼úêwöö®a<•«k¬…§¸ÐY†nwÝF•D÷Œ±È² Zgå;8çR.l+ÿ܇ˆ`­…ÝnQÁXƒV«ÑpÏóð_ù•¯üñ'?ðÿ&ƶç)LgSÀZ ‡#ø¾b Œ1H©¦)fQäˆ,Ÿ¤âoá`ŒA !²LCJÆ8Ò$1f€µ€ìNIÓïCJ‰Ù,Âd<Æ,Š0ðÞí÷h:îü›Ðl6®û¾$Ž‘ež§F~­3L§˜Š(-åî‚2$I!‡çyÐZc2ÂZ;®&TGk,Máû>qœ`<ãþÝ{èúPJ^⟠€F£¹Ë‡ÖDŽ+ ¥²,] ¾˜h *.”¹»Ò4E’¦9M5È–è¥â D¶¼e:›Aƒ$ŽqtpˆÙt†FØ€RÞ•g¢Ï@«Õ¼^PÖh4 µ†ÖIšBgY.ï•IÒI-Ó³Õçr‚m­qwfÝ €ˆÆàî;F¸qýúƒ>â8†çy7žFWq<€°ÙØÒ:ÃJgaâèèI—„.X… ¨é„êsUЪ¢P;Š~ÆÎøô“Oq||Œ°ÂÂÂ÷|èLÃü§ÑU:B¿ûï6›Ö–ÑJ)$IŒ4Ma­…5ÖX×l¥c¬kyŸû4ùµ¢¹~c-Œ1ùxféó¶21†Éx‚{wïb0èC)Áƒ0 ÀCà‡;¿ûï¶ž€ 9@H±Á*`!ÇdÃí&`n¢òh. ”÷Û²§¸¥"0•çrÎ^¼Û¶à4¸•?==Å£‡ u)e.6€Ö¾€Áý5ÆYÀèÀWÞ–ç{Mä/ÏÒÔ­VÁ¾uv¯)º³¼L°XÂâ¹` Øš¨1€€ƒý} 1÷„,7ŒB?%Û>ù…JmI©@ÄÀˆeYÅVS)Ç˼ººÞ£²×93guEþDnjŠçcÐ:Ãáá!ƒKÞGÈÒ a;„à žï qù)´;/º¨¤¸&ç Ö:6›»ÎÝlëNOÁÂóþªûLyψ*âåˆãˆ¢Rˆ 6£¶2÷J=¥žÙ¸Xü`ŒA c4²LÃ[ã𜼯­¸R1o•þ‚tª÷[;÷5ˆa<žàäøZkH!Ë»¥’XYYA»ÝF¦3dYßó„8 Ê»ö‹× €R2—{  VaèEfŸ>_ñ¢ßºV°þ¢\ƒ GC 7I)r€!8®í]Ãõ›70 Ðï;ÛoŒÁÑá!,,;'ž:Õ8==EÍ g œq0Î\Ä(Œ±¸{ç2!3s÷p!À¹€ïû[Œ±•‹ˆ¿!ÄŠRÞjÁþ·o¿‹£ÃClnnâÒ¥K𤜛Ã9ù°da)aAËYÐG4Üê€$IÐ  µ†Œó¼10ÆËè“1BE899A†èõz¥3äy` ˆ€ :Œñ­§p®pÁw¥’ÍF³‰ÁpˆG Š"\™N±Þ]H’Ò†W¹t­€‰Ê®"`ǘN§î½œÏ¯(•ÃQÙoŒÁÉÉ)aˆÕ•UÌ¢Â0Ä_¿ñ×,®\¹Ê¥[ÞýW …Øô” ?@4DPJ!Mœžž Ž‹øIÐ_¶vÍÎ#rŠq6!Žcp¢³ænaµ Õ¾Q!I4 $I‚v§h6CB<Õž €òü›RJ+kkèml¢ÝjÁX‹££ãÜdÑÜ®®”-LÙYSWbÁ,š!Ë48wö}®@+÷.±ówXþúÉtŠ•Î ~ùßÀ“'ûHÒR=Ýœ€”Û\pXkÁ9G«ÙD’$˜L'‹é®Ü´³»§ùÿw1h­‘ÄqiÖ€yž¡J5O0'œ¡ŽSÁ…w‘f)„ð<õ¯ç©Ôç1c°¾¶£µ#>Ï÷ÍgÁP›w9»jNˆÀÄ++Œ iš"M¤E¬1GdIv™*œUãksEÉ 8‡çy»Oà\+ ¥ÚÐÆ ÙlÂ÷LgQ.“TY•g•>*&鈖Ra­ÛÅÎî.666ÐnuÛùÅR)4š-´ÚmøAç ¹3ÄÀÈsž7ÆÁ*æ‘sÆ„ ´PR‚1ß¶ÿôO~и€¥ðƒ?úãv··~™ˆ°¾¾ŽÉdct%ã{‹×!|ÏCocY–aÿ ¦“ 2­+#2'†1ÇQָ쯱s«[‚E–#w-OÔºðØëú¾·`rK9€q¾Êïaß&©SèÌE…DùˈJö.D£dw. ”‡­ŒÆ#|üÑGÇRHH)!¥‚œóûìÁ…–`©Ý ‚Zk(σ*’"¹81`®UØžæF*wy›Í†S`ÌåXåœ3‘+7V°7‘„ñhì||bNOTØ3NäZ!Ärð$¹0~ccãêE,å€^¯wY Éd‚À÷áûf³é†ƒ!,€V«étŠ8Š+îjMW359wFca÷òeì?ÙÇd2vYä*9ñ…‚’÷îÞÃÁÁ¾øÅ/ÂSZcΦú»Ï‚_pœ5×ö®m_»vüñÇK7KψÀ­[·x·ÛÝRž‡$‰±ÿä Ö{ëh·;PJUØÐùîThd"0F%k;™·8::ÄÁþ>ÂFˆV» å{ÎÆ&n—¨ßïãþG÷ñÎ?¾ƒ4Mðê«_ÅÚÚªÛùe.4žÛ}–G‰l~^4#·çÈÀ¥­-¬u×0‹\àrFs×c=k9Ex^;i8ŠDZ f’Fkxž‡—^zíN°.â«F‡K>P·,”+mÎŒÖØØØ\ÙÝÙÝpòLìíím5ÂÆ gF³Ù oþìgØÙÞ5¼°ug”j½U½@.[“¥#xJÁS Æ4Q$4 kcÙ*–§æmÖÆ®ŠD¡œ…ÐÆ B¹¾¾¾àŸž %å¥ $ÈÙòÝÝ]̦SœöûJ.˜ÃºíŸtv¥êŠ€‹èÒåŽV!½€ã ‹$„€N"—/ïî-#~)7oÞ¼!„çív»L8:tIÈZe¿s¸bá*-Þ{6à©9K9˜uE·4Læt‘TqCÍÍÍs-Á|ß¿Ìrj·Û ‡ùžÀ|Sd>áù䪹ZºúÕUª7õ/Õçë°à<ÝŒA 0 !¸Àx<ÃÕ+WÏõ–逛Fk”hµÛhµ]†e8b2ž ˲›oV®¬¬@ (ŠÇq¹RfÃê2òor)áKD¨:çaè, 899AÇ`ŒÐÛè=;anûAˆãã#¼õÖ[è®­agw½M~ŒÑh‹„'%Â0Äp4D·ÛÅæ¥K0Æ`6›!Š"¤i iÇ9E¸BE)2…Ô€™EÔ/úóNÆ8š­&=|ˆ»wî"Nblmmsíív»Ý‡g¢ÂÖÖÖšÿó‡?¼,•D·ÛE¿ßÇÝ»÷ðÁ૯¾Šõõu4Md:ƒÑÃÁï¾û1žŒÑëõpãÆ ìîî¢Ûí–ãkÝÆªÖ0Z/ìWSÚs1Ê娬ØKÌ­… Ö‚áö»ïâÃ?Äöö6®ß¸Žf³ ÆÖÖ»½­K—ºX/Ðl6WÖV׺RJüýÛo£×ëá¹çnâððÿ÷Í·ðü‹/@J‰,Mqrr‚ýý}¬¯÷°··‡ÑxŒ‡â§ÿç§xcöü ÀÚÚ*ºÝu¬®®¢Ùj!|H!Àƒ1®f Ë4’$Æd2ÍsÎÁ±ÖBJ!9k¡u–fNc¦)ŽñèÑc|áó_@ocwî|ˆƒƒ|ùË_Æjg¥Ùn··|v!ív{»Ùjvö÷÷ñ÷o¿(Žñ›ßú®^¹"†÷ß{Œ2¡ÑlâæÍ›ùæ°Þí¢·Þƒ6ãñ'ÇÇ8<<Äý{w10EH’Z¤I‚$I\5• M… Á…ËqÎ!¥€çye4)‡R "¯dŒÀ8‡ïyxùå—°Þëáôôï¿ÿ>~öÓŸ"IS¼þk¿†kׯ/ ‹¸¼»»Ûl61 pikD@o} `gg[Û[%ë1ÎÏ*+$X[]Åz·‹[·žwû‰Æ Ë‹¢\‘Fa2‘ÒqFžò*ŽZµÁâ»j‡‹)Ï: ö¹[Ïãê•«Pž‡¥¦p€—^zùÃîî..]º%²,CÅg§’iÅ^à5æÃåsYÏ{©$Ò"3Ð@²dšõB¬¼·U•;TàŒákÿákxíµ×ÀÇñѾòÊ+Ï=€V»EBp|öàNŽO@äòzE2’q›ã`ÜE]óG=EE”LÈs¬È8›Í…(·ÄqõEEÚœ1†Lk§†±'~E­‘Íë‹ÊªcËcœ¨Yk±ººŠço=õõ×_§ÿøÇö\&“ÉäñãÇøÑÿúÞx㯠µ†§¼<'Ë…bÑ•T¸{ÿîÞ¿OzàŒ•÷*år~óï RI¨<È9Ç»ïÝÆõk×pÚïÃhÕµ5|úÉ'xù¥—ñλïàÖçnáñÏÃ÷}ø¾àÕ¯¼šË¿Y(ºpëïxŠˆ& ŽŽ¡”¯ÿúoà—~éKq¯×óDçPØÉµµU¬t:HÓ žçåÄ䔌ë‚"Âl:à 3Æà)ÊSð”ÏË`<ÏåëópÙ0’n”GbïÊU€sŽF£Ÿ?y‚Ï¿üy<|ô/¿øž<ÙÇÎÎ6àøè­fœ‹y¥JÅu(8KÒQ£Ýnc{gÃáðôÎ;õ¢”EN£(Ò­V‹·[mDqßóá)éy‚ÏßÀSÚ-W&‡ç{ð<¾§ày>¼<›ä{žÆ÷ày‚ g Bo£‡?ùaØ@³Ñ„R ÍfÖZtVV`¬Áúú:†ƒš­Ö{ë¥7Z?˜ˆüÀ˜N§X뮡ÕlâôôtÿäääLRd€Á`0˜Mg³0›Œ³RcgZƒë º \Zkè<>°(öûM¥öO—2ªÑy`i€0aŒA§ÓAš¦¥.)ôJ’$Bb:›Á÷}:«ì+¸—ƒ8G´{‚¯¼¾ nšøÛ} óüD„ã““ƒû÷ïŸAn!¢Ùd<Ïl®Mµ6ŽÈ,C–é²é,s-MËü@¡„lQäh ´vDkm vMkdÚ Ó€ç{ÐÚäÙ‹F£Q戹Ê4¥$f³”rV)Ó®Ü^kwî¾[|jÞ¯¾`ðoÅø +È6Æ`4í/ãš8=íONN†J©žT¦àÆÀ²,×è˜ïÛåYÞ€jµ¨¯¶1Ú­~Ù4`,€$NXÄqŒ,ËÀózD¥w›³Jyˆã•÷[ƒ: d0oïâ?ýÁŸbkc­O_H# C¤i:;<<>$IrÆXú³9ʽçyö›ßü&}éK_âׯ_½^O6 ð}_*¥”t‡âœKιbŒI"’Œ1™Ÿ ÇED$ˆˆ{UE>/¢3ÖZ]|Zk³¼¥ÖÚÔ“YkcLªµNŒ1i–ei–eiš¦IEéx<ŽãÃÃäÑhdßþö·—î -ݳv¡Ê¯Ð8¶ÒP¹¶ì³ ˆà| ª4^é+>«ÏTDzµgÙ’g—QŸ_}ìòx–_ŽV#ÑE“ŸgyãùX€¬|çKÎëDÔßQŒo+奄O×Þ]´tIÿ™rÍ3Ä=ã§«¾¨ñsúë«WŒY%¾8ê`jçÅw]ù^=7µ~åÜû/ :ѺÜ.뫳dýþú˜õ£>©óD­NØÓ®Ÿ9žéÇÓç þÿÄñÏ-–Îø·IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/interpreter.png000066400000000000000000000134711217176075400251300ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ 4uð¹IDATxÚí›i]ÇußÝw{ë¼Ù€™ ±$€¢)¢¢)‘4mA!iI”ä8R$ƖŤ²UUâ’-«J–ý‘ª¢²>H.G.«,14E*0R’I‘ 9Aì˜3ÌúfÞþÞݺóá-xïáa0¨|H|Q]Ýs_ß{Ïÿßçô9}ºÿŸ_¢ýÆ“ÿó©ÑX,F,ÓñxÓ4!TÛÕ²úšú½j©¾^V;7î !€Õw]~oû½+û6ÞÛü&y@„¾ïø>~k‘¾ï÷ìÙsk3^ó F„Ø,D³— <À_îG)ÍŠvrèПfð5Y–!àr?q¥LB,¶ã½’)Bb™&Ñh Ë2«/kÞLHSi!´ å=YéËÀd‹†]~—hûfg•v°£®ë*¾Òšk …À4 rù“h4BH¤­µ¨ ÕÒµ¶l^ïß¼©_Õ/ Õ*Ÿ¾.›à Ã¥ZkÖ¬Yƒaí¸ Râ8£çÏóoü ¦ibhýn…Ò\ë‘ê;«ý´®÷×ÕûZ£}ZëN÷êµaAÀ… ؽ{7ßüæ7\™)‘µÒßßÏ-·Ü‚¥TÇ7ÿ}­>W{n¥ý¯Õ0 ƒ¥¥%N:Uhš)«}kò]Ó„ÈÚC®ë"„x×Þë~×ú­.ïèè(£££„aØÐh´F)ÝQƒ; ¥D²aSËp-õ¼®öîöûRJòù>ΡC‡xôÑGùØÇ>Æ“O>ÉSO=E>ŸÏìÿ‹¿ûyú{B^8òwœ>;ÅÁ»fjºÄñ磿÷ ÒJÉ!2S£LžúaDÅ(-”ðû¼i/ibGL|•ÄÈ\›}‡Eׯ-)â–…Aæ*k‰—'Áf …Gedd„7rèÐ!>þñóÑ~”üà<ýôÓd³Ùë²ëzû_þÞ?E‰Y ‰uÄ"ýTNMpâì9 ^£çÏñ£¿ú+üÂo’[”ˆÈ8úO3wÑfÃæ_%µi£ã³ôõ S˜}oj” 4±ÊYr‹ÝŒ¼î±zÀexÛ:†7î/£CTí¾N@»ðccc|ýë_ç[ßú<òŸùÌg¸ï¾ûøìg?K±X¼.ûÿâ?{ˆãÇß`óÝwƒ=Ì™cÏQHrøÕóø%Èû3L^ŒRº˜×gÛÞžhœ\q ¯OeÓÖ·ñU/gò>½Vw±ÂâÄ"ÑnfB‡¾Í ­2¾‘®Þé«xYV è4ª†a°cÇvìØÀØØ®ë¶xŽ•Úÿï|îcèøÈ¯>@9_a©0Çê^N¾œ'Þ-˜MØqX;l³i[šÉ´‰Gž@¡Âãgòô­ÞC13ÅÒÌ[¨hÀÌ¥9Õ¾ §ßƉøx¥ vTâîAà•«L‚uÐ-&P:‹qÏ=÷ððÃ344ĉ'xüñÇ9vìØuÙÿoÿ‹ßb˯ÝÍÚ5»)+wa :OÉUÈx íÍ2´U0?¯X¿aˆ™¬ÍÑc3Üõ‘Ua‚äÂ>~{I ‹…ñi\3B©gkV9xù øî¡›$ô ÄâQVÞôÇË.‡¥h]uƒ†a°víZ<ÈC=D2™äøñã|ík_cddäº&=­5ŸûÒ'ØyßGI%×qôµ·8sìeöíÚD_WAÿj>´î^^ú›W).xß6íTdÞ¹ˆ‘Í“½`ô@ŸuÛjN¾ð<cë7ã¬ÕD.œ£-cãb£P¾BûŠááÝO/‰ÖI°¾:pàŸúÔ§8yò$ßþö·9~üøu-Xêõg?÷[ø]6ÆÆ°Ït<~ûá÷3ØÝ˹‰yÂò:fó6í]ÅþÛnçØ[Ç)š]lX¯H&^8|Žýÿh;Ò‰bxŠÅtž­ÜÎôÔúEúT¡DÇ‘5Üü¾‡\& /PŸëqõ/~ñ Ž=ÊÉ“';ÚyóF1M“\.×’,ÑZ#„àßÿÁ—ÐѼùþä ^êP¿Î;wUÀí¿úÕ¯²oß>Z-qñÂYf'N òi*… ™¹]±$ùÉÇߤ°˜#šð1¤Ç‘ÿ5BÄø‹>oŽü=³é4wÜÆ¯Ü>ÈÜè '¨d= KyrÙÊd³inÞ÷i¬U¿¾‚œ`“°Í&Ьƴ$Fi¹_¿žxâ‰+î†Áº-6%ú*ó”ã)”ç0Ü Ÿ™ùˆL%ðs"½ ‚ü,:\ ³P!7ñ†áÄK?úDJ³w79ciéd lY+˜÷Il·‰˜ Ç¡P*pÛ‡þ‰žÝ”Ë¥.‡k&ЬÒ×CB;±=öir½Ý'ÎùŸ½ÆÅþ£„Éêa‡.gˆ ¸Èø©Š!‘”D.Én‹Þ®"ùé4.=)Ÿ—ÞšåС;X·¡›o^àèÏ lß´D_—KbC]±1c!‚"‹¹ýë&´VÍV^u-P_KÙ)½|E¹Z?Ã0R’ËåØº3f,Fα~K';ÃÔÈifç1œNo[~e#–SÂô ’†È,!ËðÚÈ£ÌÞí¢ÝZ,o›ÁòÊd.e¨¤ãäçãLC ¥ÇcÛyãød#רՊ2B²|§œ»\M„xžG&“Áu]&Bè‹Ï f§˜/Ù¬Úïß°‘s¿8Ïbħ …Q®òξv »Ç šêâõñ»~cï»ÃfêœÇüL‰ÉS—f0+%6ö&¨Ìk’Ý!ZÏsi©—ÓG7ñ¿_8Ì]wÝ…B£´B±’ŒPøæQ­“Q÷×"BkM©Tj¬ÿó׿B £¤ß%æp³CÄÓ¨ÜynêOòÖËG9Rôé[—ÀNÜ´k‘ÁA„?ÀñÑéí38óz†‘Ÿ]Be‹,ž/Õš¨ˆsʤz+Ä-¬¾‡¿øÎQj²šÑ–”®Ž¾ZaZ¼¦®¾WlztЈæßÃ0$ŸÏãº.¦ibÛ6‘¾^*³£'Óä¢9ÈLrâR+‡ŒÙÅL¤ÌÎýwÒ1cñ¥cèB7îì%NžÁQÏ`ꀈRÄ  X¢Ÿ[Ïó/>‡eY Ï% ]û·" е4X€vÏp­ Ñu]ŠÅ"J)ÇAÁ¾÷ïeý­·1~ö§ä² ^ȠΑ¯˜¤>Öt›ìز6gîå7™· á³ÖÖÄÖ̳6ª(-–±T7QIÓ0Ñ!TȰ~ë~þä¿$Ÿ?ÚÞ²¬–|抲ÂÍÛM¡™„fðõ”J%\×Å0 ,ËjôÝÿà=ŒN¼J,–²|Êc \ˆ*W—‘³%æLV;ôõäYÌç©T¼bˆç‡,z%„Ò˜ÂF mÄ›rXÄSlÝõù¯ü&Zëøz´^W÷Þªi¹Ûiô›'G)%¾ïS.—QJaÛvË3–m±ïö[Ð:ÂëÇžA=øñD.ô¬^¢‹ô„&P`;K•%ŸP•±•Ä’ì‡@*BU&.§Ùº÷ƒü§?:ß^×Þº(¥0 ã]j@Ó&]§‰P´mœT*<ÏCJYÛJo%iÖ\œ'O’Xµ“üâ<¥À$îqÌ s&.DÔFz>ÚÑ”áàkÂí #1TE–'XsóVþèϦ±,«xg àúL “ÔÛJ©FòöíŽs„”’ÕëÖ±º{ ÙÌ úb’<v|¹Ù¶›Ç¶#8NU.Ë”øXR£1°Ú±‘:_1)d.2Øgó­ÿa „¾bôëù‹f".k+ @©† ´Û}Të[ÏõQï4GÔËàMkкˆ–Gßx–^­‘•q³ n)àVŠ8¾‹04Ê‘ˆ@ŠDÄÄ4ãʤ˜-£Ãv˜aó•Ã0‰¡§ m*Ð CÄ1 #‚–A%ÀÄG¨FÂæÜÙ,¦i6Àwýú ›¶õÞ… T=f3¨£5B®æ!ÚIðCˆ&bPˆ0“;B¡"Ña )À«(¤.“ŒGÐZ‚ò1µ…%#˜F„P”‹ðJ„¡‹}†Ö¼côò€\môëªÿîM ¶“ÚìÞ|ßoшNåj$lÞ¾‹wNü˜bîmB•Â3òˆb™hÑÅHÚDu‰RÑGh0-§ª¶Já{>ªPAàaÇ€ØZÞ|{ÃÈ4Àֿ׬ö¢m-ÓÔ•™Õ¨)TTxõ„±,À[¦InéÅB™Ù©·¸„Pø&ެ ¥FçC*¤°1L†…¨ Bàz`[8±uX‘UlÚy7§þö5lÛnýú¼ÕîëGm” ¯zàäŠõëÈÈQH&(ä ømÙ5Ÿßˆw[jÿ»¥sçèξ·­©;´—¯ë‡ ”VU-ÖÉf¨¸.¶íàyîâ?9t¨oY PZ!ý«úéNuc˜FÕ+Ô'‘š†Ô}kõãÍG[j‚P¦-[ÌåwÐèKÛq˜Öç:ýÖ¸×ü­ ‚ÏójžÊ'žH ßó:j@çIª:U*•Ë‘W‚YTD˽•Ð pYð-²èFÿò)1ß–=ÛtÕI°;«†ûhÔ:âk¡r¹†\>$¥¯Bt‹Êëë;MvM7¨´ª†j;½uYxÐÕ³~²zMJ£e ]ŸL=Ï[Æv¯U­u#ÀjöëA„!Ôr•¿”£²¿Œkÿþýû…ÿă-ç;7t†ÿ|ç®]g¾÷Ýï¾ôÿÌ¡d˲~RC¸l‘Rj)å½ÿ·ä2ßC ME6F›6mÚ>::Ú’Z»Â)E*•"™LÞ666vˆª©4“ucGJoÑ”U®6jŬ«V‡k׮ݶyóæÁ™™lÛ^–€d2É­·ÞºglllÀ¯ÕÖJu#D˜×¼^šÛ5ÀF­Žñh4ÚmÛvdÛ¶méééÁ²¬e? ¥$™Lî<Íf år9 rˆ°V{m„tÒŽ÷tlVí:h»ÚŽF£k6oÙ²}çÎ]»nݽ{ÛæÍ›×uww¯²,«{jj*öïü¹Y.——5ÏóØ¿¿~øá‡ó²ù\n~l||rddäìÉ'NŸ?þL©Tš*µÑ÷šÈh6•÷ŒÑ¦æ–ÂÑZ;€½gÏÞ÷?ðÀoÞqÇÖ¯_¿¶··OL\¼ÀóÏ?ÇäduSÂó<æææ:’æŠ]¥úŒx<Ž‚7ÝÄý÷?ÀŽ;XZZÒÓG޼úÊ“?zòÉ×^;ò÷ZkWáj­Ý& Q+Õ†`†ŒD"†eY¶"†a,‹õ~þ ý‡{?üᇻºº„iš8¶Íìì,é÷±,‹ááaR©ccc,--5ò ËŸ¯Î[·nEkÍøø8¥R‰ï~ï/nä#J¥Ï<óÌþìO¿ñ‡¹\nÁ0Œ’Öºâû¾W©TÂ0 W¤ ƵÀ÷÷÷‹íÛ·f__ŸÓÛÛK$æ|à¡Gýôï[¶%üÚ¿=>Î… èëï#‹áû>®ë2==M6›E© /5MÅó<<Ï£R©P.—éêê"‹1<<Ìw ‹Q,•ð}¿±åvó-·ìœŸŸŸËf³o Ⱦ¾¾pÕªUjõêÕÚ÷}]*•nÌÖ­['î½÷^aÛ¶)¥´µÖQ!DH(¥nÛ´ióŸnÛ¾£×vìê€Ð tˆeÙ˜†4 ––9wö,“““är9Êå2®ë66]ëµã8D£QR©«W°k×N‡ðŸ QauŸ!‰`Z¾ïqò­K##oü¥Ô ¨µ.!ÊJ)Ïó¼àðáÃzrrR_7_ùÊWÄÐЈÅbF†Ža)eRÑ $2™ÌŽ¥¥¥ )ߟLvÅ{{{bÍÐzzºq",ËÄ4-„¨æëç ê¦Pß„1M³þ„JU6žO6—eff–tz\>O.›+ …×£ÑÈ÷“ÉäI!DQkQJåÃ0¬†á–J¥pzzZùË_Ö×í¸ýöÛëù¿P)H)=)eE5 cøïétú¹©©©Ýó [—ÓkNŸ>ÕF£ÉDRt¥ºH&“Äãq’‰ñxÇq)t¨&, Å"år™b±@©X¦X*’Ëå(ŠºT.UT¨2¦iLuwwŸß¸û–·º»»Ç¤”Ù0 •Öº¢”òjò…J)|ßçÈ‘#7îr¹œ0MSú¾/µÖ¶”Ò‘RÆ„]Zë””²Ç0Œ”išI­uªT*õärÙÞtz±7ŸÏ§2™LÒó¼˜çûÏól´¶´Ö2‰ˆ LÃ0ÏsµB !|Û¶=Çq*¶m—R©T>‘Hf{zº»ººc±Ø’”2A> ìRjI‘ÕZç”R%¥”+„ð,ËRA¨®®®÷Ä  µZk©”’€%¥t´Ö .¥L*¥’@J‘B$x-rj¥ZZk H­µPJ )¥Bh@ !TSÔçn­”k6ž×Zg¬”2¯”ÊE!DE)å¾”RÕÈÔïi ¤µ¾"¨B‘zäW‹ÝMíX ÍÑ¢l;œQ`š£¼:øR­BS»\ †¼vÿ¿Rð×µî@D3vàHx»i ›,ÝÓ×ã}¯„JSÛk}]Ào8ÐDDsˆl´‘b¶­êmÑÝ(hk7ƒ ÛW‡×ü=KˆÔˆè´Xj&G´ºhûv{^@µÕºÓbçF€ÿÃõWõú?2ã9°"˜IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/kterm.png000066400000000000000000000053741217176075400237120ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ ÃIDATxœí[MÜD~Þ²{¦'H!“HÉ$$.$È!pã7ääœK~?`w/(.»‘€œ@ö€ˆH&‘˜™d&™$ž™ôt÷Ø.×»»ª_—Ëîž$l¯6)Ér¹\.×ó¼ŸUî&fÆó\Ô¼'0ïò‚€yO`ÞåóžÀ¼ËsO@l+ÿü×ÕÑÒÒ±¥cÇ–püå—±Ô_@DÈÕ Øzu⺼¨®Qõï¸ãtÞóú…îË’ç9ò<‡ÖÚÕG£Ò4E–eã·ÞzëP×€¥¿šíÿ¡â°J’9Ld^Åau&@Dˆ"‚aÆöÖz=€J)("R "(E R“³UAEP¤D½¼Oª¼ïú‰>Vi].Ê“«I•ÙaƬÕ­5´Ö`fäyŽ4MqòäÉF_G€R q܃ÎsüãïÃêê*úý>˜¹a_ÒPN®¥Lkï6¯™ ¶ÝcL÷sÕ¹V„Ç÷1ñÎ;ïàÒ¥Kx饗 ÓÿJ)7ÀéÓ§qêÔ)äyîÚä üúÓ^‡ê³¶ùu¥˜ëëëX__¯‘f˜k×*UªT{"šù…¡"Ÿ·Ô¥M¡"ûÛºÓ¯â8ÆÁÁnÞ¼‰ú|À`SŸóĨÒ^aJM(ŠZkE”Ú4bf%î(õ®ñm(ÜØØÀÚÚÒ4­‘¤” ÀlZ Ò‰±*™´öf Ȳ EQMBO èY¡”Âáá!ÖÖÖ°½½íðÈBD0`á[j¨Ês3•ZðY–áÔ©S8wî~øá¬®®"Ë2DQTSÏg-ñYúZ©ß¿kkkÇ›Ê(â™­ÐUšAåD,ZkcðÞ{ïáܹsøý÷ßñõ×_ã—_~ÁÞÞ”RN+ž…*ÏJŠR Y–áÏ?ÿÄ;w‚R¯àðƒM« ¸bÕ ”Âææ&.\¸€wß}|ð.\¸€û÷ïãÛo¿Åwß}‡»wïº(ò,lº‹  ÔÐ$IpëÖ- ‡Ã©à­€nŒÕˆD¥C´X°¹¹‰+W®àêÕ«8sæ Ξ=‹O>ùü1~üñG\¹rI’8Úú¯¼ò ²,CQ5òB‡¼?kƒ~ýõWlll | P’Ùâ”"€ë&`£A–eˆão¼ñÞÿ}œ={ËË˸qã¾ùæüñÇ.|ZÉ=©Äe› e[[[ØÜÜtÂ8jQ¨4“Â4£€Íÿ-p­5z½VVVðá‡âí·ßFžçøþûïqíÚ5üöÛoFèõzn²ÏJõ•RFØØØÀîîn%¨£ƒ/´ã—¹@“€j¡b×úVÒ4Åk¯½†‹/âáÇøüóÏqýúu¬¯¯£( ÄqŒ8ŽšZÒ¨"ò¨à­Ô`gg›››ÈóüÉ[üD7j<éQ­ÜP7H’Ÿ~ú)~þùgtöï?÷´ÅúÓ– Nr:m€} J)ܾ}—/_FEèõzÁÉËÕ›R ƒÁÛÛÛΙúÀ§½w–âFlZ2AewvT'm/¶ªª”B¿ßwmmKXid ³æ!µo3;à jû0"_NÂ$ø¤iŠÃÃCu©wiM ]9À“8?™LÍ\#3‘Û÷o#‚™Ýr×—ú4“™Vf5_ò¾)È\ F@(¶ ¡n!´ÖHÓ´Sê~´x˜EòÒþ%2  Ë f°áòÛ~ pHÓEQ Š¢N¢þ& s}¸¼¶s0Ì ¶0ȆaØ€¸bJ•·ŸÊ{½^ÃQJÚBh ]àe½mõ'Ïv àkb§€øjb b·­$)]̪må(áÏ×é[Wƒ¡ 7hå-s6‘°R©}›É5¶…@™èHð2Ì… üº­Hm&v‚“—Ú¸^îþ*DQì2Öº˜+loÖh$ Ê4µ7Æ€q¿‘ß5Š¢€.té½w64@ço¾ù&^ýuÝ™`›„C’žEõƒDTÒa°[Äø¶ì×­C—?†Øßß/eâ÷ 5 —êÒ_ìcee/Ÿ8QI“ôÑÕË©1O&ç&*îM&ÍNê+À]OÂ’k¯Æ Ý›Œ]ÑÃÞs`˜Â ×Zç(té¿x¼¿]íj7°1’ˆ uÁã=`uðv–ag4 ’gñÄX6w‡èWïS'±<—¿kÈ‘çåOåò,‡.tP ëy—¡Ð°iHz¢–“kgQÜ.á&hxg¡Yðî  Š$2>1¦aF[hpóæÍõ'N,÷z=î÷ûÊ}Ô`3ƒ©2bfBÙf¯Q^[p‚,+iOƒj¶ìjø‚†×”ƒì‡?ÃÌE¡Yë‚‹¢`Shh]°Ö Æh8ÚmðïŸ~ZQJÅz,2ó"€>€>3÷«ºmï(s„ò£bÄ  v¹ÉèIç) ‹3‘a  @ÈdD”8l”–÷‘3sn$©>{{{@1s¬”Љh@ˆ«º=/ÑbuÏ’ÙƒÊäPE ‰³½º=Œ=˜¹P ^ʘ92sÆÌ)€¬jÏ™MÎ ­”*Ž?î@“o?BCŽ(ÐF^=D„ï7>xÑfI°÷ ïŸÌ`i~™h9Ðÿ]yîÿ2ó‚€yO`ÞåóžÀ¼Ë æ=y—ÿDfÞ#þ‘IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/memory_stick_unmount.png000066400000000000000000000074751217176075400270660ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœíZM¬eÇQþªºÏ¹÷¾¿ùy3cÿâñÈŽ"‚ï ‘ذ1Ë,@‘ˆ@‚‘b±²‚²ÄšlX¢°Ì"Rd‰aÅ ¶g&Ï~ó÷æ½{ïé®bÑUÝ}ïÌ€½z Ï‘ÎÜóÎéÓ]]?_}UgHUñy>ø¼8ïã™Î[€ó>ž)à¼8ïã™Î[€ó>ž)à¼8ïãs¯€ø/ÿúã¸wáâ×÷/üÕ»?þïáKo|AÆùADB€Sf¿U(D "‚ªÖqþn}§¼XßW¨*@R3ƒ™mn@UÊüˆ9gÀÞQd[§Î[e˜C''ÀÌ.X>¼wï»gO~sÎß>þøèï>úðÖ…ïCu…q·&,‹ˆ(ˆú¿°ÉË6Ûø¢¨ ".Š ÚÞuAEºZ„P1AE»ù\Ée½~Uµõl.[ˆ˜¡¢Ýs2¥+3æãð›Ìôxz¶þêr=])e¬×² à‹˜6Ñ î‚iÎE(*’§'«ú®j‚90@P›ŠºabÚð"*cÝÌU ½"ý&†¨€@ÕZþBÍ»€,‹ÙŃýÅc>=Â>Àlšå6(<º'w?1#„€œˆ.?÷"â0 ¥2×½ýá1rN±üݼAMh­×DdaD,`¦ª^E¼á!æ ž¦j¡ÂÜÙF=ðÌCÉæÑÂ÷ïÞýÇû»ãwcÄ„µh 9DÄ8à“Ûàg?úw>‡4M¸wt /¾ö:îÝ­÷~Š×¿ö»æ HJÈ9CxáåÃ"¨»£)t;VTk/aJèÔ§®SšFÍÝ™€á¡zRÿŽë‚P”žÒ§§ÖišÖQµXÁ]NÖg'øÕÿ¼‡£ÞÃ8ßÅ—ßú}Ü~ÿ¿pr÷¼üÆoàêË7ñ“ÿø7üìG?ÄÕ—nàêK7À#Æ€¾e5b÷¨Í-PQRÍ% ÄLA¦å:!€0Ì!œ<Ü qœa÷âCíb%é^ï{ïŽâ’¥¦:ªCÍSPÛ1 ¬2×µÌ0,…ÛÚ¨DÌÙ*AT~®ŠelDÁ&T”5Ò )cgxþÆieR5_wE¹…Õ®+ c*ÞÑŶZZ*)‹Ûµá@Îô”3d#•)´©Eæ–€‰Ú:KÔðHR‚*Žã0þówþòStiœ?8 •lP@O²@RF¡ÑßJ-üÌ}µm&h ·tÖTåéÐß%K¡’rã Õ‚Pñ8f¶ì#`V?PÅ´â–~?Q€Û0ÀãÌ\F'¨®©%EºˆYÙé™ ³«£š]6ȵô”’ÔPïé-иqÿZˆUJÍ(¬Ý<«S¤óŽÍ¢l3\ .ua­¸ñ8R90ºUj|Ws‚$Ä šëâ’ÅâX;Ejõ’žµ•pÀTé³Xxi.cEŠÆœ,y(T°4§sRUÇXä!ãëú>ãY `jUˆ‚¹‹½\´Ÿkq‚ЬNFØÒVI;®–†DTk… t¦ŒªLj‚7äj”’¡Ì­ Ÿ ,ÅÀŒçiÔðÁÍTñÀî‰0|I¹{:}„6έ*€(Ä=ƒØÊÞ Œ"ª;o€Âb–$P‡?gU çFSrYÜ<"ç\jŠZ¡:½— ÆNö Z‰€dd‡útߤǗ¶ Éf5ËÓe.É ôÔ¼©nN;væR-…*lóÌV¨Y±¾F-L̺L¡â™šGT«U—,UƘs+ Ê;ÀxZÜ'&uI™¶9ívTܼ 2¦ØìžÔc…?'*i±¸yUZÍ߬éïˆäÚirnâM›R£4°5狡ܽ€êJ £¸Ÿ¸U@QieMšlÃå^ÎRœ }¨Á›òĈRÉ¥ƒDMÃÀ…ê–*°nÀ<˳’§chÉ>Lʼn˯ãE¡ÐJe潸¾}À¸9™6QyAOVHó-é«‚’Qdß‘ƒ¶¨Ôzz* tÕZ¥¸xP ½ÚQ7©ñ^¬Vz†d׎gÞ2ëð…SJUðRÒ*RaKÈ9×5ŽáÐÜÉ@ID 9Ãzuc‘báìµ8oZR ŸÖÈ,ÊΕ]Bµx‘ƒ……G-ƒ„û_§çv/KYÃóUtp#/”tVd-ÖKÉ‘•D(`µ;€ZiçšÎæ< zö¹”°TII±`ŽÓiW|G¦œ4vب6t:’S›µC*¨ÆñN[œ¦„aˆ ÚÒn–#+J¼p@!²HÅŽì¨/Eãnu¸z`<ƒº{}¹­54:Tµª®¼ë@&õ±f©¡ÖX#¡uÅÀƒ?Ä0.pÿè¨ ߯£ûG¸öÊxx÷T3BbÄÕ/|Ãli½DN yZãôÁ'¸òÒ—pôËÿÄÞÅkؽpµö7=œbN¹Ì÷~‰ùîEœŽc±R^ƒ8‚ÀƒÃÁ!BrFšÖær­»Sx„’·P껺–ÊáéY¡YÀqŽ ÏAÒ„ÅÞ%,Oî‚ÂÅlq€iµÄ0ßÁb÷¼3âX* ˜ïîÖȧïaïòuÄaŽiy†8΋¢³˜r>>}ô!FãÛ„w~Ž;¿x7~ý÷ëŽóîa¾{¢Àñ­÷b¬NïAE0ß»„KÏß„ˆ`š’µŸB´±qÿ²¿ß´`H Œ‹ƒb ³Ø¿fïxûÛ[*Mv.^ïÂVÁ—®·ŠÒBoš’ñ fÒ(¢ÿ´\®_‹ÃÙÙ Ì÷±Ø¿‚f89þ’æ{‡Å’ªqăO>Df‘¥xRˆ‡W/W—÷ê¶GeѾ˜é»O c\°ÒÏÇ{¹)¨+ÚŸhƒÖ»i½FΫ›³y¼IªŠ?û‹w®­×«Ä0~íò•K!"§µ Šr'P 9!óR`¤0­Î0Îw‡Ö«®¿ü<ö/îWkôî߯š½YOÏû^ŸxõÆìã¼ÝÖ´ºÑu–öÅÉpºêÃMÓ„Õj‰”¦ï“kç[ß~çàáýãX,v¾µwp‰c,ÂW ¦ÐöŸ&úÿ˜à@él®,NL´Ëñè>W5¡½$gÞœ»ùLÙ­5ͪÖ̱V_Zo~‰îf#BJ¦)Ý ÿ–z÷€Ã+7¾þêk¿óç—_yk6[쉨2sW†ê†P®i(´öܼúrË5fÝÂþw-||Fi•^ ƒ¾:52¥–$KDß"; íäT€VŸíîíß#ÿ^²þà1Ø¢‡Dô[^UÕ±ì˜8 qÀ0 4 Å)ÆH³Ù˜wvv×óù\âC¤aˆÄ!P ‘C` !€™™9€™‰™©ô K°-p1¦[U´p”¬Ó”h¹Z«å*Ni"ÉYRÊH)IÎ )%M)é4•ß”’®§µ®–«µª¾OÌ?ýÞ÷¾ÿ‹?ý“oNð40€ðæ›oŽo¿ýv$BX,a1_„aÂ8ŽaÇã‡!†Å|Aûû:ŸÏ9†8pd‘™3fDä¿\æ'&BÑ‚SÀž$À+ZUU ¢ª9¥¤«Õ Ëå)%‘,9KN9KÎ9åœrJ9åTŽœ¦”WëUZ­Ö+@]9¼rúßøFòEâc»/« J7mª~UÆvö×~ŽvnßïÇ»Ýé±µU¦éÎ Ûo2Ù&»¦n¼vã|ÌÀÊ®ÉÖ”§*`ëðü|¢Îl¼5ÖÏí j÷N?/m=ïçí•à÷§>åìç}|sO '3!·Þ¶U·-¼=öIŠyšôJèÏÜýnŸé)÷¶•§ŸE®„þä§\ÿ϶7¼ó¶Òîwûܶ¼ü÷ûgõø4!Ð Ò ÷4·zÒý§ºàÆ}j‹gNW=ïíyŸjyûÛâvãçÿÚÏókû×çètJšºæ«Ïþ7ªºÂ9‡ˆäcú#@TåñÇÿ*ÇÖŽÑ„†‚ ˜¡¦†šáDœ8p’Þ;‡ËçXºOºžŽ&/‚Hþ 0Òçé’C$ChØÚÚb4Xßã?€»íê‚Æ[Üé Üéñwzwz¼ÀžÀ?ñoòÙàþÿWù¿8¸ üÅí>|#Ξ=söG£áÛvnîÚp0À9ÇÜ/Î9DZÆ•_çÒy ‘Ÿºç–—— MÀ0Ìò¯ša€™M_’YÓßÌç™ÉI¢‚ùzæ›ùØ2Áƒçäï§ßŠ12™LvG£Ñ¯x Ýn÷vüÌ#>rï#>ÊŸÿùyª*Ñ_U0S@15ÔÒ±]_ápÀ»Þýnz½>CA´DÍ0SÔ 4QbUÃ9Á2<¤÷ÎãÅ!¢`ñ×R_I‘›¨±›þo2ÈÁQ–%‹‹‹+[[[¿|[nÀÆËß™›;7QÕ4a‹ˆ°äSfÎ’…ðù»M]U‰A1UÌb¶x¶~4¢DÅp Å‹ "éž"¨€80ˆ€Š9¼7Ä3Ã;‡?µ8-3‹qÎá}q*„æ–…<ðÀí8c¤ªkʲ@ÄèX¤lL-»ª¦Åhvg ÆH5ÞCš XÔä%–zšýï&/0 Up…¥› â< - où~jˆRBAu–"‡XOÜ~~ïõzˆp‚l»lllܲúÂéóç¿É·¿õmþÁ?ú‡íwÙ ðoz‚+ðSw–iŒ›UŒ\8¾Ô]äLÇÑtŠü¹¡ª­G¤ˆ1b¦ÄhûnŒ!ªˆyÌ„à¥&Ñäòæ,{¢a"Öœ<€tœŸŸçÊ•«üìOðÏ?ö1¸ÿþEQÎÃÜÆú898qêݲ £Yà½%ÖŠäæ¦‚¹B²²PÅÈ¥p„±€Òv³ h4PÍ·ÐéD5f÷pi1âÓ‚œhZ°êæŽH£9tÌròK (mR6T•ùyX]]e®?Ï+/¿ÂÃïxèh]W«·00/"ëuèt ÐP3TcQ" !Å£‰5€*t1戌ªTQ5"ŠFâb.¢ÑM¨jú gIc˜*Êl DZiL“å½àÌMYŒf°÷ÿ+ýf§S277Ç•kWú››[ëÀ¥,Y< ÀÚp4\92?On‹‘=<¥Þ Šâs Šù\¬"8Œ¤x$×­Åİœ¸Ú—š¡Ùå$Ÿ%ÁÄ0U4G«s‚HI|ú9D,—ÕTÍ’G9„hÞ{>ðþ÷³rt3(ËâÔáÅ;;Û‡¯­eÙûÀÞO¿7Ïx¸KtÊ^áqÄÀ+hδN| UDçR:BSž L$[Tcæ)µ%D@b'çÈyÁ!9Ë›A$‚:T<"–ëž¹J@Uišï=ÿâ_~ €ï=ÿQâ܇ˆ“\Z2Dbƒ@4M)ì‡Øo|ôŸqæÌþÊ£Ì'ãuàÊ€SJãÑïìl­ííX]^ƒŽ¬ÛÃù‚íñ€ƒWÇ5úMÞy+ Ð(Ãh S#FrÓKà´'ÐÔMB"VNRO¡’6LH¬¨¹Ïü,»oó)Ãôò… yùåW8wî1×ëõNç§\~íµYÖCÐþ‘…——‰M`çÆ5þlÒå¹êuÞUœw”¥Çç L{p3šB˜hKY_5’kÑKjr²•TE“õ Ô§ìâu¹?ˆ†ºœ¼!Î!^Ú"1í!Úó•hJ ßqÜwïOñâ…13¶··OÏ.øpÀõ×gߟ}õÕWY[[ä )AQ–ƒ½Á>›[[<çxÛÛîfoo@hjj3Æý|Çá‚ËÈß~xʂݘÜ;ZÌÜ>AˆÉ2fŠh:×\EÃT ÔV-—ÉP«ìKgûN/x%&½0¥44W‚­]>ÿùÏsÏÝgÙØØ8 t€ 8{zß#žáÅSý^ŸN·G½¹…5‘P– ެ1™?Š]ä×O4 S3êô¡!6 1èTÿS5¢)#1‡BIc, Ÿ¶³‰øˆ MRv '˜É4ºV@%¹D˜nÓË” …¦QsâÔqî¹çvw÷pέuºÝ%à$BÝá`pba~Žá`HhÌ”Æàýÿ˜­ÅUЦ>à:SR 6.ïìq÷Ü;˜{ÏûXÛÝ#Äimšþ'¹µ`1‹žÉúS¸Õ÷LÉbÉ!U8ñ!e??äJ¨©TšM˜Ÿ[ ÆÈµë×xˆ·/ŽG£õ)_ûÚo×°â|qùæÎy Ø®#s_ÿ §B Ø¡8˜£)þÆ öÂ/²ù3±½3@c"™ æú“››¥LR«íÅçÞ?7EÎç÷ÞáfC ’5ŠbhîHCŒTUE·ßåw>ói6·6ÙÙÞq_º¸NÞ'(^¹4HŽ=s÷B]׌»Ý^7U Œ]ß_’ojÊëUÙ¡èô( O”$|â ±".’ÇiË‹ù gÓ'EDŸÁpÓ'E+tS@DöŸ\ñâ0qÔM©yðÁ¹xñ"ãÑ„?ùÆ7¦]a±´¸ÔžŸœTWM*zóó‰ÀJ›äÀOÆÏ J¼wzÍr}GÜx}“¦n1CHû cÞhÕ"(‹{ë|Te¸·Ë}>Èú‰unîìæZohˆSáC¼¤D­‘²ìÒ45e§ ®Ýn‡ªªè•]ª¦¢Ûé2©*z½nJhÝöØ£ª&3ïûTÕ˜n¯ËxTQ>³Q£n*v6o²µ³ÅÎÍ–Ž,ž:ýðC+ÀõÖ K?|åôööõdÄp8`40ŒŒ‡c&ã!£ÑˆÉhÄd<¡šTÔ“ 6ÑlÓ½ù:s»›ô;ÌidéÈ–——XZ^bee™ù#óàÓâû½>ßûîwøÒø[[7øÂ¾Àë¯óùÏ}Žá`À¿ûÔ§ÙÜäSŸú4ƒáÿö㧪&<óÌ3ŒÇc~û·Ÿ!Ɔ§Ÿþ$u]ó›ŸxÁøÄ'ž¦šT|ü7?Nˆ1 ´`º_­Æ£1×®]?¶²š â}ï;ÐÿìgçÈöÖ6“ªf2©ˆ ÞœóÓøÊø%+bQ ¦üþÝpcé8>Æ>§^ü3žûտŰœcÒT,YâÃþ0Ë+Ë ‡CL•NÙaíØªÆ]wÝ…™rìø]4MÃÉõuBˆ¬¯¯S× '™LÖOœ¤®kNœ8ɤª8qâ$UUqêÄIÆ“ñôýÆÉ“ŒÇ#¼óiw¸š0í1hR¨t{ý^ ?øÁŽþÝ¿÷÷ÿÇööö;Nž8ÉòÊ2eY"â(ŠçZ{ˆ‹aÄ­=È×ïêa ‡Åÿø¿ðÎ/†á MT®]»Æ/ü¿É¿þ7ÿŠÍ7ˆftÊE§DC ,KBŒ”eA‘²,‰!Pä벤jÊ¢ Ô5¾(©š ¢C]Uͤ¢èxêªÁãñ˜+PÝT öìÜÜáÂ…‹ˆØî¯ÿúSï½kmíù¢,K€¡÷~o<3©*ÆãIJ2â)Ššö™ÃM½@0ªf¸V¸¼ ãÔŠÍM°›CÊ^—¢(Àeŧô¬¬®cD5•<Ü>¿Ç¥ÚÝö‰ñ Ž´4©›œ›3æ¬ýþjJ·×Ã,Òéõ0³$èFCEiª†nÙI›:PÕ f©È­VWW_»páU5a2écÀû‚¦q)–ré›z€ÛÞuãyvVÎpuy™#µw¬Îõ8~òsÅuÜß}<õwžâû/½ÌÞÞÞŒ œ¡´¼ËåñÚ'\m“{hdVÙÊbí&ËtÇiº³”ÚðÉdÂöÎ6Û¯o2éu»›"²P|ò·~ €3gN?ÿì³Ï2)Ê‚²))|‘j¨s)`3ª ˆ)EòÄ7ÿ2·ˆ™±;ðöw<ÌSý 7GÉ“z½.Ãá˜Ë—_KrÕÌZi« n¿ÖƒëÞ×À[ {Lªë>Imjw®Ç£;;›lmßdks›¸ïÒòòò6@qfŸý¯ªªØÚÜÄb¤ÛïSxó>ï¹ý&¤Ý€@ƒ­QD6w0ŒáhHwnŽ?=ÿMv÷öPÕäöq¦tÒ61ɦ«ºeÌÀ#d¹|ÿ1rCÕ*̚ŗö˜¶ßÉdÂÎÎÛÛ;¼òÊ˼ó½X…?÷s?ÛÞíë'ÖOÕÎÖu]†½sâœw’I‘Ö†ÉÔ\šÝ¹U~š:ðÊå×øê³_¥ÉT°à´9œYð¬°y‹ÕÓŒX zR‚§­õsWh–·ËhÕg ¡±jRY]×5Æà=ï~÷ïOoý /LovåÊ•ù?øÊœ|îž;yýÚµSãñä”jø{«­Î8çêɵÆó<‚ |úý>žç377ÏæÖׯ_CiE«ÕáÐÒ·oߘ ­šH)'6î˜LG§Ó–}ø±_üá~øø¯¿ñ ¥äw÷»p¹ß €§}ôѯ­>´:ëœÛ@i…Ö ß÷i6[ôû}fçæHâ˜ñhH³ÙB+Í ¿ƒŠV»Í`0@)!Å=²ÖR%«««GŸ8þ_Œ1§¤ØŸûàÈÉÇ¿òàƒ•1oŸ\´öð}pdYF³Ù$Ësfgçhµ[´;]‚0$I:.£Ñ¨ö$B"Ľ8 (r²<ãܹsGÚ­Öo9g÷%€¼`ú›=õçVÏÍó‚F#|û?R ¥ÛÛ[ Ö:z½.G-Óh4±Æ°¹pg}íyäEAY„A€ø‘霵TÆR$)sss[Yùø«¯¾ú1àëÓʰ 8{leåoøA€söm»U/¤’ø¾Çp8Äó|Š¢$ CÚí.ZkÂFÈÌì,B¬± ŽãÚþdNc,ÖÒ4%Š"–––ð}ïïìC¤T‚i.Ï׿xøðáF–f(õξÔ9Ç®‡C´çQ9Bœs˜ÊbÛ¯,+¤RŒÇRÊ{4À:GUU”UE–ç G#ÂFH§ÝyâkðŸM À”÷µ[­Ö_iµ[dyŽÖŠÚBïçÀáö¾ã%E^PU° ‡© UUQR*¢8ºG£œ«`e*ʉ‰ŒÇ#œƒnof®ªª??¥HSY¦¸Îv:ÝU„ ,K¤”¸{å¯Ewvïû8Žв$ƘÊç[Û[dYNYàI#ä½NÐZKY–EAžçÄQLY–t:mœ3ïÿêW¿:UH×SzÑsÍV«]•gÝ;Ú?8pë ¨ª &Ÿ·ïÜ!Šb:Ý6UeØÜÜD*IÃ5‘ ò¼@¼%¼¹‰úyA–çõ•eEA£ÑÁùª2‡ëïä;-þÿ:އa€©J„`ϦßiXc@+*c°ÎQ–%yž3XÈ0Ʋ½½Íââ"EYàã‘çR  ž×9GU–ä“ÝϳŒ$N(Ë Ï÷È£U™š k§Ò€CRJ*cȲŒ»ÙšûµuX[›A4S–y‘ÓíõpÎríꤔ;~¼vˆÖ’å9 Bìùk-EQ—eišRÎY¤ÒH)—Œ1ËÀÿ|׸éh!¨Œ!IS¬­wß¹·D.W«®±c Î9Š¢`4qüÄ)Nž:…”’Qÿ4II“„V«.™³,£,ËJH‘L#ˆÜͬÞå5ˆ£xžfÐìMè\ ¤”4½¿ß¾}›õ;diJ³ÙäàÒ;;;Dã1ËËGèv;lnn0¸xñb]KT 3‰6Yš’¦)yQÐëõBÇ1UYåFÓ Ëé4àöx4Fïû 5A’¦ ·nÝâÚµk\ºt™õõuœsðº½´Ö ú}~ãŸÿ3NŸ=KÅ„pK®ß¸Î…žzꩽ‡llnñÊ÷¿ÏÅ‹ÙÞÚ"/ ²,c~~žÞLœc8‚`ÓÁí©°îíDÆ1ÞÜÙé÷…³UYòì³ßàøñã<ñäÌÍͳ°°€Ö c-Ãáˆ$IHÓ”°òäOòì7¾Î¯üƒÈ'ã€^ü.ø‡_ãK_ü°K© º.'O" ¬­­±¶vƒ$I ‡üÉsÏñÔÓO3Bܱ1 ÓVƒki’\»vå ¿ó•ßfeå=öaVWWi6›äy>I_+¬1“¼Á’&)|ìÃx^Àoýë/ñÒË/ñío›õ…Ïóøãaeeåž”:ÍRF£ƒá€ñxLšedYÎO}”¢,ø½ßý]â(BHyÉá6§DÿÚ¯ÿãiî|î_ü楋ß|ß_zúg8{î—/]âĉã@]¸ì:C„À9‹5u²Ç1O>ý3¼ô½ùÍù‚ÀçÃá ú©‡ïy€sŽü-^?IÆ£1f“……N=ð¯¿ö—/½‰øW>ó™¿›NÀ47Eq±×ëñÈûßÏÆuœƒµµ›=z”4M1æ.KäXg1ÖP•i’òÐù‡ùé‡ÿA–ç$ÉÝ0.„ÀLÒì8Mˆ“´Výш‡ÎŸ!(ŠÝÜp\™VŽ©J]½}ûiš’fžïséÒe–—Ô±ßTxÚCYWt“t¹¬êš¾,Ë=€ªªNuw…‡š7H“¤Þý8fqÀÊñÆã1žV¬¯ß©™cíÝ™ZŽio4Ö]ëo÷ GeAQ–lnïpýÚu´V5ë#&ÅÑ$CtÖaŒAJ9!K%Z+<­1Æ`Ì݈”ç9q’ǵúúCŽ=J„ÄqLœ$ ‡Cb\–ÕTö¡yUn”EÎÆÆÊÓ ‡C¤”¼záujÛ· …ªÙ`g'¤¦£Ûé UÍù‰ S¬µ¦ªJ” pΑ¦éDø˜ñxŒpæÌ™š/T’ÑpD–¦8!£2MÇÿÏ(²bC+¢õ;í…éïôñ}ŸT.^|“ÕÕU¬µHU×Î9¬3)˜™A Q“ž•—ReA`¬%‰c’$&Žbƒ«§Õî°±±N†Ø²ÄYGåª~Q–S9ÀýP‘:ÙÚÚj·:=Ã!N›f«ÅíõMææîpâĉZP!k¿PUøAÀ\à#v£]m#XãHÒ„^¯CY”Dq-üÎÎËGrúÌiƒ!i–#•"É2޼(F¿þ«Ÿ*ÝeUæBEQt Žc’$Á÷}²,#ìõ¸~ã&Ý^™^oR·[„PÌÏOx‹:×ÙûtΑåµi–1:tˆNŸ&Ž“=°ÙÉÒE¹¯cóé0¦Ä‘–EIšÄk눦„A@\»¾F±TâœÃ÷Cff›„a]¶ïÊw=¿1†áhŒ1†f³Éé³ç‚€ñxL’Ö˜ªÂNš2ŒuäE퀩£ÀW¾üo+ëH*c(òßóˆã¸®ÚòúJÓ”­-Ò<£Ñlàù>RJ´öОçùø¾ÖJÖGhã(&ISz3³t:ÝI’ç9Iš‚Te®ÌXûÞh€µÖJ)ɳŒ0 Øé÷i§)a!Aáû>¹Öì1¼A€Vu’´K}ïÒieYQVyVeé i–’&)IÓl6'(ëƘü= *«D*EY–4;µóJ’„ ðƒß÷ð´7¡¸kµ·<]ï¶bB{Yª 1RY6!?²”,ÍH“Œd’pu;LQÔ~A5e=_(Ë ©&6$ŠbÂ0$ð}|íÕç†'·Ë[ÏÛ`7M®ªªæþó‚,¯™ß$IHÒ„4MˆãxÒ1¢q“Z ¯œ @QJ*‰§5çÑjµØÚÞ¦ÑhàyJë:áÙ噜‡öÔ„û¯A)'äj>ñ!I’Äu' ã(" |ßc¨Œ©ûò|ª“û@^äMøaݲ6;;Ë­[·ˆ¢ÏÓ(¥&m.b—¾Ö9´Õ(!pÔôzU–äeAšÖ;Ÿ&)Q%1QG‹ó+øž©*œ¨`YVí÷€¿öé¿écÛ•1„a5@{>q¡µÞSs!Å$ÿ—Yïº5U](á°¦>øÌò|/”Fñ˜8ª“¡ñ8¢,«zþ‰ÿ@Jʲ¤ªJï=àı£­\x}>Žã=ûïv:ôfzl®ß!ŠÆõ(¥ñ´F+… œÃTºN¨ ¤{޾&EÐ8Š#Æãn—™^áܤJ‘å•©fÞÆq¼X–e¯(r‚ @IA£Ù`a~ÑpXwyLÚc´çáùR*kMí#¤稬!Ï˽Ü!™˜AEŒFCÊ¢äàƒ´š-ò<Ãó<ò²bX¢S펩¡(NçœFTÆ •Â÷¼š°ìÍ ¥b<ÕŽlâÐjõNHÓ¬Þé<¯¯4#Ëj»ãx¯Ü¢ˆ4Ii¶[,-Ä÷=ô$a2ÖNúm÷>ýKSË1µœÀš2Îò¼Å Gi”’ÌÌôèõzuÎnMÝ 2!¥˜äübïÍ÷=¬uuâ3ÑŽ$‰ÇÄqDàÌÌβ°°@¯ÓF8‹’­qœç9875°/Š,øAps</fYŠÖh5Bfz3Te ÎáyÞÄ–Ç{m3ÆT“ÒØÇ;`×ñI“„0lÐévi·Û,..ÒCò,CN|J–¥”e’òê{À?ÿ9÷×éo½ºÓï¿/IS”’H! <™™išÖàÚ«OŒ&±}·/(Í2ù¤C´*Kв ªª½~k-G³ÙÀ÷ƒº˜ „A@»Óa¦Û™O©$J+²4ÅX‹Úg÷ø¾h†?ÖZei’†J뺤•’N»E«ÕBH‰ÒÏ÷ Ã’FQ n­Ùkê$i÷u2}ÏGyš™^f#Ę0)ê&ê(N°Î]«Lµ¯†é}ð¥/~þâÏ~âSœféÇk ¼&7BOÓív©ªjÂüz˜ª" +Le0ê!„’h¥QJOš¬5RHfgfÐZá¬AI…UÏsE޵öÖÚ÷Æ îŽf~9I“WUA£ÑDH’‚^¯ÃhÀK‹,Ti™c³Y–H@(Öá°©QÍÁüí…9QšróÖ-ÖÖÖxù¥—vžyæ™_~ãâû{ÑñG†øÓz|ßÕ$wUQ^³Ùü‹yüñú¡|ðñ3++œ?ºÌ²bøÊ÷·oÓ²¿Ñ@ÍÌâÊ’r{“,/w:4Ï­Ò|h•µªâÆÆW®]sßùÎw¾ó­o}ësqÿw ª·>?2ü$h½œ=|ø£ïèüÏŸ>zôáU!ü­ï¾ÈQàÌÂ<ÍÇPËÇ K1W/Ý^ç…>[½?ò¾o]ôò…×þÇŸ¼ðÂ×Ö·¶žúÔ`pO_ÏÿOx³Z·–‚ ·¨TwYë#ǺÝGŽ´Û‚s³ÍæÂüÜlØ>°è­–pUEÖ˜ÁúFqg8ßÉò믥éÿzysó¿½6¾º£¢ÞõÈ€·Ñàû‘áþDɧ„¨~áàÁXi߆֨9)¼Y!^ìdÙšç8,<½˜gY—Á0L¢XÛª2å8JâñhTŽÆ›&ޝÎdé“ÎmùÍæðjž'¯“ÛZí÷÷ŠØ;ŒûÀî$%ð î¯.ÌÛTQ–y¤ÊRR– ¥âVl6°Ñh„¾ïJzž°"·¥Veàû©qØaOÈÁ!¿ž.ËäNY7Œ1û:ü1Ö¾¯ñÖÃùÛÖre{‡•™žÍ¬-•#„0-­ã¦çùö<ß ´ïk!•ÀVÊyJ©d)•Ê•TY uÖ…¼)¨®;ç~RÂÃOàíñ1°µ³c—µ&Óº­0‘a­²B(åyR))„–H)°XXc•+¦”Ö˜ÔšNZÙ׫jÿNêÏÿ…C¦0ÖÒ/œIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/mp3player_alt_unmount.png000066400000000000000000000066061217176075400271300ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ MIDATxœÍ›Ï$ÉUÇ?/"2+«ªÍÎÎÌ.ËÎ.3xaYXûÚâÀ$Žœ–ø8qƒ;'$KÂ’‘Ì Ös ¬ÁZc«u{gg¦§«º*3"Þã™ÝÕ?¦»§«íé§ ENefd¼ïû/¢Å̸*ÕuýÅü©sîcRUÞÿ}îÝ»GJéÊãžGÎ97ŸÏÓ‡~øÕO>ùäOÖá!\õE™¼ûî»ùøñã÷vww÷Þó¥/~»âÄä‚ûÎ9BUñúë¯ÿñW¾ò•Og³ÙŸ¿ðGVèÊ4Móîþþþ{»»»Ü¹{—‡?ûT€ð?Œ›f†@Æñ÷OCcåŸÃ['ç˜íï³³µÉÝ»wyóÍ7ù£>z9ˆH˜Ïç<ü¹_àû-ÚeK̯™Z9ð ”B2Èfd…d†šÞ³þZûë‚Á ãÉ„oýÍ_ówõ5îÞ½ƒ÷~´ó°€ *žÅ1óÐùÊÎØ±9†FŠ,U YÁ´g0—>©õ÷ ÃH*d3Ì=Tà ´ÑÖc,+)eTõêÆßÓ:Úø³Eâÿ3Û‹¨¼÷úwßðŒ´  f8è`Þ*³¨ÌÚÄ"fºd´ÙHYIªÌ[#¥Ո挪"½Ô͘ï~÷3@É9¯åüÖ`õãKå¿þwA×.HYxøŠà°Ì0댶ö—ðdn<]džÎºB§,’’Râ 3öf‘Ô ©%çˆfË8 4c~øƒ'Ü3{ùÀ"BŽ…É(pgSûòLîmyPVÃ9^ð‚æ 5"BF¤<#f‚`TAð^PUrJ×€[{„z§½Ñx¦µÐóO—¡B2Pµb󦽴Á8ºdäœÈ)‘sB{)ko¿ªJêÍc]ZKŽ“!"lOkšª8¿Î`)Œi#j¹V éÃdP…ÒꪦnÆ4MC]…’¿lpÌ ; âË¿û0žLˆ1¾üzÀuH@Íø|oÆ[oÝ&ç|©w®ËµD®N=âÖ­[L&“KKu…ëÒK×€aœÝÝ]îß¿ÿBÜp´··ÇÞÞ—á¥pU\¨p΃8L3šËÀ£G.·Ùs#x‘ 8Ø~õ.ÓíÛlïì°½½M#óùœ§OŸ°œï³ÿùg<ÛÛccsó±o—¥éÖ-îÞ@ÝŒY,<ø™·ùµ~•Ï?æ{ÿ7þý?0ÞÚ¡oûÄ”.Ü%¾\f[¯ÜáÞÛ_À º¶Å üËwþþ×ï”d¨/|¦®+»Éõ˜yŽ4Ïá¥g‚feà<olsçþCrÎhN‡ —T62aý2ÙTËr¹ß;óü¼`¨¯K?6ç¸ýÆ}Ì´¯ö– °i©þ MÍŽÀèPU’)¢J-«ä+ã‹Ül˜n¿B5—U[Ϙõ+¾Ålåì¦_ÕTÓM×k‰bjdSª89[Ê7€óh¼¹Óïï•Êöª>û|—ƒ§WžœÓÎöݺ Î÷fÑkfF%§O”¼tÎû¸s*9šl{°‚ùBší³§„­þL@FÛ¶”Ìœà8m×ÀõíÕQjÞ{÷nmoc‡j¦íÔœE;rבrÂ{Ï/¾ÿ>;·nS"õ “íÆ ªŒ›¿ù¿Î?õmÛöÛÙç¬ö rN3ÍhÄïüöoñæ›o¢mKŠñó×U«âœûàÛg½ï¼gëõû,Û–Î jFœïÓî=y΀¦åÚ –K E¤[âýikUÕ¿PÕßÿ‰”>ð[!y^ 9“º–zT—}¼T*@T5*,ÅÓ/FeÁ¬ôãqéÛ%fœ[+X׋ð—`…Ó¡7.Оî`Ní}o«G5<™n`s@W˜¯êÓ‡ U!—§ÏI¼ŽÍk¸ÿ"@\À 懦\à?âb†4 ÀñD`<)Ì•Iþø‡¡kOÿ~⩾æ2$ ëðÆ¥ÿX‚Ãc@g’åLœ=燜øÀÊÃg0¯¹°:抔W,÷¾òÁä‹4`×÷^Dü%ÞE— º>}³ë(GÅN #R´cqp¦ôO¦UЄñES¸ÎTãÞÍ­´Ð·ªoÓòÚ呪¨òK_úo?xpÜ®E gXÌKY„”Ò—šÃ9tž©Í÷mxçr@ '¨GàˆðêWçŽì¿¬—/c÷‡dfkç1§è¥–ÝÌWýõz}¥Tšó<ßúæ7ËÐÁ{ÏùÒŒôc`…V™? €ñ"°JšËÁºµþ°âz¸Àó¯ú¸*×H?. ×'µ`?¡Šòð'gÒÚ¼è žrâz7Πjüü)šÙÚ5±K "ˆH9®æ=!„ªªªsÿ´î.$6ÆÎ¹o‡þpÝáÏTã;;;ŒF#êº&„0¬~T¤Ô¨œsKUý£½½½ß[.—?/"Î̆$iˆž£ÄiՔษ–)©|#‰—l;Ö™Y‘lfÚ4Íw···¿æœ[^;ï¼óŽ}ðÁ2N-Æhu]›ˆ˜÷~`>«j‘JDž‰ÈŸ™Ù–ˆLÍl˜ŠÈTD¦À %lÖý7ýnû…Kî[: –ÀDÿ4û8§œÁ˜3yfv˜_ff_ÿú×åáÇ朓®ëŽI^D²ˆ$3‹=ND*`ø½~§¥äéE+jŠV¬j yíˆ=­™-k7:hór ´"{ípfÖšY·.§–´1F¤m[\ŒÑ5MãsÎ>„Tµ2³¨Í¬‘ÐˆÈØÌÆÀXDŠÔ`´Â|àÈ4¤_Ü êŸ{°Ž "KU Y˜ÙXšY+"Ëétúýu8eUU”³z€N&“á8¶"[ø0ù®ŸØ¨gxè+ŽÖçiÀ`CÌaÑ·v¥u}[‹ž˽?t¿ÃV™_ô ¹ND–1}ó«Å[ë¤& @,9bzõÞZtQ23Lì¤ÇÖ•>qdç«+ÅÀqƇ60€A›VA]Ո׀W~ÀZ‹.*Š®Nô¬´xȇyè=§™>ÉüóÂàÀI †ö£+òz#~ã2p’V¥ï8ÒÄqFO^¯UàlNj×*ÃõUi¹2Îáø—Éçÿú#« À8¬üx†ç<£'šhëÐIø4×£IVéwIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/mp3player_mount.png000066400000000000000000000100751217176075400257200ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœÍšË%×]Ç?¿sNÕ}ôtOOÏ{ÆšxìÈ Ar$ÂÒl`Á‚?!bÛ Ù"‚€ RH6°ö ‹ EF „Y!1Ilb'NâytOwßWUóû±8U·ëÞ¾=¾Hã#Õ­ºU§Nï÷üÞUbf\¶N&o:qå°ß¾ô —l³ªúÔìoEàæë—G.KÀd2 òoEQ|)xGl"Þ;Br'Džy:,oäÉ7ÕuÍñÉéïßÙ†€pé;á5çÜøæ_‹:&Š¢ÀïÞehcëí­bõðÜ?áäø1¿÷•¯pïÞ=œ¸ßJI¿³†Ë`fâ™M§|ztÂïíë81šdŒƒçú@(xIÌpÔ $µ¼7CÕÐöšÙêq–ÎL„£á˜þ§äã>âÞ½{Œ‡åŸNg_1fY¼ÕŽ- f4fçq…P¸ÜÑ T &¨  NJ‘€d0 £QAU129†!f0TáÄïÜ6˜WÚ6*ä>šDþõ‡SF•_¿»ÇË#Ás…£4¦5L*eR+“ªaÞ$ªhTɈ)Ñ$cR)ÚÔ$mДPU (‡|ðƒüæí«ËçÛSlÅÓÚÖ8'LʇŸ,pàøÒmÁ 8`‘ŒY ‹J8YÀñÌ8šEOk¦Ub^'æQ‰11­àxZ‘êkRl0M` Aðƒ~vŠ˜n5ÿ­ p"^À`gTpãŠ0l'ÉsÔV]:vNp>o^Áœ‘ ÄÄ‚â|炼—'Îço—'ÀÎÿ`oèyõ,ú‹(YÏÕHÚ·ÖÈik#u41¢©!¦ˆ¥ˆiÂÌgø¥OYŸÇvl!Ü”®î” BžêBaÖMMF:)fãg€‰a@2V·Ö_Iš°”r ¡†Š;{f‡'kÍÌJvUëöΣ94*¤uTš˜XÔ‰ªQªh4‘Zr45˜)jš‰Èƒ°ºþŸ XkIa4ÜÜs ‹ìÎN+8šBLFÔlíë¤Dm·¤¨*Uêº"¶†OcDcB5e[`>C•õ°òÅ©Àùv°ã áÆP8­aRCi•Wt^g«ß´ZK@#4MMJK©µì9Êq€Cؼڟ 0Œà/í  ‹Çsq4±aÞ(uTR5FÕ(M2jó­Ïo2èÒ@Šœ€sç!xœû J€ì·öÿy®\¯ª€žÅ½G_º]>êÕ6Ù3ãððˆ‡é¬v.‚攸Ë#ÌÎþ›å7F'''|ðá‡TU—ÕÚlÒ m ¥ÛF€]Û"Zc¿G"Ìæ <|Ôo‰jÁÇ—[Ó4¨jo3Dùù/~Ùº[Îm/Ü öfrn-ÌŒÇÇ©ëç„\çÌ$¤¤ìïïqmç§“ ÷ï? ¦Ô¾´eß_|úKnÞ¼Áh4Ì–ÐÛŠ~×¶„–aúêIê¦áôô´ï>øÄÝW^áîÝW€Fߺyƒƒý}~ð??"Æf9 ÓÉŒããcFÃáò3“î×Z/ñŠ¢¶dàlź©4UMUÕ¤”Hí;þ»»Wxå•Û¤”hšf©ûW÷¸sû%bLKÑ©Èéé$¿*ëIFV©­poOÀx<^½lfÔMª²··KB®jbÿêUD„”Òif41rõêÞ;RÊqÁµý«E`>Ÿ£I—zß/Æ\¹²{YÀüû{ïQ”…t ûR ™ppíå Ì€Û Îz¿¿åaòê‹·nÝb0P× ©ûd[zƒîá_üùŸ½¾ñ?ïCW®>xš¦áG?þ€ÇÉFË8>>Yz„¾å&“ um@]×üçý7GG)Ê¢U#뾞ÂÌ |÷»ï~óÛßþÖðŸ“i@ŒM¯rÑ_M(‹ï}w©5XÂÃGøôþ¼÷ˈ÷žªªøèãŸ- 1Ëo’D„ñhtFXߥšSsn^ÏÛžÉ ô_fêfˆÚªñëZYÆãÓé ï]KBñþû?äôtÂõƒ}D“é”?þ§“Iv™=u(Ë’ÝÝÝe Ô‘Ú]Wµ•yuÓ´çp O%` üòÛG0¿Þ·[ÇÁÁ- ˜Ý71)þïOøèc‡]&Ð&Ggc©*׆€-íJ$ªÚÍÍ“5QŸ—ˆ U 'VÒöë6/"b†ßdÈhg²·»ËÁÁ5bŒçB_ç))MŒËWßý¦ªŒF#n¿üι¬úÐóÝw„ÚÝè{ó[–ŸE56JÀ‘ïHöaÁÌÂ:ÁýÙ9Ç;·™Ïçá½_JYÙ>ëøP¼úêçÇË~Ýø©5š¦FJ©?§~7í?±]¤ýY­¬~÷03+hS’M’¦f %¯½vç<̃9‡™±õ*IÓéŒv¼åÊ¿úê]®_¿¶2Þ21Öl ÛÈÒE‹C€Ô¿$!Kìfu8GÀšÈlg¦¥®eDýYw8yýõרÝÝåþ§÷™Íg¤”Zƒ—¡,K®ñòK¿ÂxggI"ëc¶Èò»ÆäP’¿À]oO•„MЉ»q¦O̸™Yifr‘tO5UЏsûen\¿ÎÉé)Óé”ÅbóÆ;·Fìî^a<gñ>—j®"0ÕN0lç´éñË:ÚER°BÀÚê¯À>˜QžÏ‰ÏK-A”eÁܸ~°´ˆëw\©ùŸK´úTÍ“W?ÐŽÞqÿ}̳©K@·@ [Þ» ôÊ;ß~nçWû‰ ûwÚÒ ”äÅIí¾#¡áB)xRÐ÷ûëvÀ‘=ÁÅžMÀžõšf@K›Ô›×¦oj/úÊî‰^`Ó KB,»#Ó.|àµë—¼~>8ÇÉñqÍêBmšëêÉ5)xÖP`°¨ªÿñ|òþûïø_þò³ù|3ˆË’Ò/oè| ®k¾÷/ß{ð!»(({*¶~çÖº‚ßßß·Á`à˲ô!?¡‘RD†"2ªªÊá ¿úk_ý£¯~íöí;wTÕÌÌ™Y«.æÌZiÁëV$Çï«ÀÎ~E0lÄ•öXEPçóÅ¢ú‡wÞù»wÞùûwʲŒf6fV™Y ĪªbŒ1Íf3N§cÔÌá*;çxã7Ü[o½åvvvhšÆ•eéE$x”À@U‡Î¹QUUØwn6Æì °Œó&c°!g¾º Z|&C¤]V%±¨ªÝæÀ¬Ý¦SA¦MÓ/‹ÃÑh¤ÀÜÌι…™ÕªÚ˜YcLªªÞ{uÎé÷¿ÿ}{÷Ýwϰ¢ffo¿ý¶½þúë8笮k33m·$"ÑÌrN0¢™·“o€JDÀBDfd?Ý' 3¤½Ä*G¹ý1€ÊÌ-ÀŽ„LÌÛˆ²nçÒ8çRÊå$53K)Ùp84UµD„7ß|óœnœû@¢i\UU®i7}Jɇ‚ªfV¥™ Ed Eddf#`ÔÓmƒx篗äÌQ¬G@\',Ú}Bf6oÏU"R™Y]ERŠ@TÕT×µŽF#M)éh423#„ðtº•iks""ÎeëçofADЍ²9=Rºó}ÑïèÜ*¬0})Xªƒ™U"²$„35©Ú̉-ÉÌTse"¢½ló™ 7¹î¸÷s‚¢·udö›À÷#´¾X—„ŽˆzÃqìíSo ík½çœk¹Á~ç.¤ì_뇛óõ)Uàý j=Dí«A¢Õ‘ÐM½}×§»¯ ?ü³ПäúÀÝ„};‘."[Ü^¿Nêº*¬±iS.þTððl_‰­—ÄXâÖ¶uÀn­ß¹úâ."ã"ÀϵêÏKÀ²oo¿©N¸¾ºî‚ómÝPúÇë$\¬O½}8<#x€ÿËï{°6Y`–IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/network_local.png000066400000000000000000000142741217176075400254320ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞƒIDATxœ½›yt\õ‘ï?¿»öÞÚ,©-k±$¯xÅ ‹1K΀ÉÁ'sà=HæAâ8Ã/gB2yr²0ƒñ$É ˜„}Ø<'2˜l°'޼`c !#É–d­–Ô’Z}·ßûã¶ ÛRËx^ù”o÷O÷þnÕ÷Ö¯ª~u«…”’\é¶ Ôâ’’.Y²ti °­´…ëº $†@!Š¢d®!@2óQ(¤†‡QUÏóP…@ €—‘E¡(¨™y„"ü¹„?ëÀÀ–eaš&º®«‡ì9røðý¿züñ¶œ•É6•“¥¤zfuõ½ùùùækÛ¶±jÕÅ””” yëí·yú™gƒhº6FàOÒóPU• .¼µ×\ûïþ™ÚÚZ Ýà_^~‰Æ†M×1 Ó4±éIEàz……|ýß ¦¦†íÛßd 9ÀÊå+8ÚxôàéÿRt]/ ‡Â¦P|¥\×%ÒÔÔÄ#›7ÓÑq"§yvîÜÁK/þ «W_Ê®]»xã7p]—9 3­liÛaØuñGð<×s‘R0¼ÿæ[¼þúë<ð£)).a Ù0 ƒÕSU~ʆQ 1 ƒõë×#„`Ïž=<ðÀ9+?JÇç…žG×u®þÒµ¬»e=Õ‹ÏÇ–‚aË&mYXV+m“¶Òxž‹;8@ËñV¶¿ø,ßúÖ·¹~Ý:¾ûÝï"„  Íœ’š¦iVEÂ~ø!¿ûýïyõÕWI¥Rgso¾rË­ÜpËzŠg”K”ÑÖÑÉàpŠ´ã`Yv†ÓضeY § çrÝíwS9o[·<Æ®÷ßç×?NAAAåÙÈ0%‚¡`E4eÓ¦M<÷üó!ˆF£¨ªšó<©TŠt:ÍÅ]D$hòá_Þ'ŠP1{.ÑÂBz†Sôö àI+{” i–e‘N ³`Õå”TVó꣛ؿo•••‰»¿õ-sÓæÍé©è4%"‘h¥mÛìØ¹3;VXXHUU¹F!ÃÃÃ9r„»ïº“iÅÓI¥èéé%pÑê˸âš/1ûü•„â1:º{™èáßÃçôHŠÚš®úÊ­töö±à¼%ª¢æSZ‹Êä§øtß½÷*ñx,188Hwwwv<ày^ά( žçqÙå—³fÍyøáGø¤©‰xdoÿ¿ïàÆK–ñÚ/! ž^ )iíêB †éM& qUS§OEy˜‚(B‰æå啞ìëchh(;nà?Ù\hlžH$¸é¦ÿÎÑ£GùkÝ>JÓùéCa§ÓüÇ›Ûyg×r…çn$‚P4F[ߊÌ@P—«N0TU)ŠÇóâG>ª7.¥Ä²¬)-Ëò×v$aÑ¢EÄây<ýÌ3|ÜÐÀ77|ƒC²îúëù°±ÉO´ð“'UUp͆m‡‘ô¡³ˆ9 iz"‹ÚÛÚÇ·µµÉür£T*ÅÂ… ùþ÷¿¦é„B!N´·ÓÝÝűæ¤ç‘Hbèf1œ¢§»‹æ¦&âyùä ¨*BQÐU W5è ‹N9ä €a3Âámm­ãÆÓé)9].¼ðB^xáâñ8©Ô0®ëpݺëI pÙ¥—‡éé¥™îO(ªª¥íÄ ÏÃìêºÎŠ+¸ú꫹âŠ+¨¨¨ •JÑÑÑAMM O>ù$öàµmÛxéÅ—¨¨¬àСCÌŸ??;G:¦¥¥…={öðÆo°}ûvZ[}ç›H4¤R)ž{î9v½¿‹e+–sÍÚµƒA èÈUy ·%°yÓ#5;Þ}7ÕÕÙ)‡††ä‘Çåõ_¾VÆÆ¬ÕD"!ï»ï>yðàA9J©TJ‘O>±åþsîýù/.Ù·wŸ”:$¿tÍZY]Q)ób1Çåƒ>(»»»Ç ÝÑÑ!÷ìÙ#›››åöíÛåêÕ«% o¸á¹oß¾ìyŽãHÛ¶'ä± üæÉ'åÊeËd¢¸DÎH$äÌŠJYSU%çÍž#ëêêä«/¿üÄ9÷ºäÅc¤GÒ<ú‹¦¥¹€U«VñÈ?ý³fÍÂó<,ËBUUÚÛÛéîîfppM›6ñÚk¯qÕUW±wï^–,YÍð¤”HÏË–ÃNG£çš¦É¬Y³X·îzêë°cdž††Ð4äà ===ÄãySÊs 0+óóóù÷?þ‘Ç£ë:³çÌáë__ϬY³ÆÕN´·s¤¾žmÛ¶±mÛ6–-[Æ;o¿Íò+²Êô÷÷Ó××RŽD…BL!¶ãœQÇqð<@0ÈùË–SRRÊë¯ÿ]]]Xé4ímmÌŸ?ú¯õ+ã›·Ývª=[BápùÈHŠ;v …yóç3oþ<¾Ãò<EU8Ù{’'ó^~ùeæÎË‹/¾ÈE]ÀÉ“'yûí·9pà®ë2þ|„455QTTD"‘`æÌ™TWWgwŸ%EQ‡Ã~Õó˜Q^ÎuëÖ±õÕWihh ¥¥…‹.º¨DQÕ< 3ÝrJâãñxUëñV:Ot0£|+V®$ Çñ\7þÀ®ëòØ£ñÊ+¯°|ÙrFR#Ô××óãÿEQX¾|9ÅÅŬZµŠE‹¡iµµµTTTpôèQ¶gêƒRÊS¶Ñ–eQSS˲åˉF#(ŠBII)×\s f ÀÑ£G‰D"yšª&rÑ r´€h4–èîê!X¼d1yùyÌœYÍœ¹s°l)%®ç …øÁ~€çyô÷÷#„@JɳÏ>ËÚµkY´h'Nœ •JÑÜÜŒ‚ÊÊJ ‡Ã,^¼˜ýû÷³}ûv¾øÅ/222rŠ,BæÎ›Kqq18ÀñãÇ©®©å .äã?F7 aæt`.ºMjÏ>ýL,‹&,Û¢¸¤˜ÊÊJV®XÁâÅ‹PÇqp]7c ƒÉ$CCC¸Ž‹ô$'Ož¤¢¢˲xþùçÙ±c+W®dÇŽY§ø—¿ü…?üáìÛ·òòrvíÚ…c;x®w »ŽKz$M<ã¢U³|ù2ÂáË–/§§§Çq†r¯OjŠª…#‘¼`0ÄôéÓ™=w.ÓJJHŒd·å§P¦6"Ij8Eyy9yyy¬X±‚ááavïÞͲeËBPWWGMM º®Fill¤¥¥‰ÄõÜ3ÊåZ.Bªkk)*.&Žð»ßÿ޾¾>"áHÎÛâI-@×´D( VVVPQQAQQ–å¿r½3pÆ"TMåÀèï' Féïï§³³ÏóH&“´¶¶âº.………´··sÏ=÷PYY‰"Äÿrzv‡ôÈ¡`Ë.¿Œ¢¢"ÚÛÚˆÅrßOjºa”éšFeUÉä žë)NNLV:ÍÒ¥KÙ´i54°bÅ LÓ¤¼¼œp8ŒišX–ÅÑ£Gyå•Wx饗˜={6_»õV†‡‡qO[;•\ÏCU5’IŽ?Îù矟ó¶xRLì2LÃ0˜5{§ Qg,//»îº‹'·laÓ¦M„B!Bá0Žm“L&ééé¡­­ UU¹ñƹãöÛ)(( m)´L‚µªªôžì¥¡¡Ö¶6.¿âвݺ5rݺuƒ“É89³b´ð‰Dèìè@UÕœ‹ #©yñ8÷Þ{/ÔÕí¥ñh#Éd’h$ÊìÙ³©­©aÉÒ¥ÔÖÔâyîi_´ÈÏ~sû`(Ä[o½E?---MÓŠ€Ï@0ªRU•¡¡!þág?chpˆ÷}‡ÁÁIçÎ’kY¤-‹òŠ jjj²1@( BÛ&•æŒñ¨ÂŸ9AUUR©>öÍMMè†Ò4m:Ð4™l“‹EK“É$7߸ߨ½{7¥‰_ºîZjªk"GC íº¤³±=«Ñ˜ÿÇ=Ø I’y+ ñ³‡b×®]´;†cÛ˜¦YžË<F7þýh<ž—ø¸¡úúzªªfÒÛÛˆ h9ÖB8Âõ¼³äѨáÍör½^A8æ×?ÎÃ?œ•ùø±c $“C¡œr PU¥PÓԼʪ*îÙø¸xÕÅ””–R__ÏM7ÝÄû»vDø&l[Žmã:Τ!lBv&`×Å4L¤çñ£äþûïÏÊ{ɪUÜÿýäÅãº^• .MÕÁ`0ôþîÝ”WV²~Ãyäêöí¥©©‰›nº‰[n¹…¯~õ«Ì(›AÑ´"I&“Ù—%B¿ODdûEN¥L÷ˆOã—ĸ/Â7û?¿ûgzè!:øÎù?ÿ9• ¥†ÉËÏÇ0Ìœ¶ÅZ€¦ke‘h”÷ß{§žz MÓØ¸q#·ß~;L+*â­ÿx  ¦¶†x®ã€ضBà8p\Çqà4e­Q@¥'ñj xÚ4t]Ç4MLÃ`46³GÓ0 ƒìß¿E><|˜ysçrðà!–,YÌþXºx <ˆ®ë8p€h$BiI)ž'3²õ \ž' ‚DÂᓚ¦õ~.\ÇíVUÕÇãê@¿¯Œn`†ß“qê¦a GÐ4•P0è01LÓ0 ˜&FFq3`bš>º¦‘——®i£¨ÇÑ4‚ÂPPP€‚‚¢Ñ¶=þ¡*ªŠwñ ³+ˆe¥‰çÅ †BÝš¦õOÀ„QÀ0^MÓRš¦ùN+³ÍuÇõ™Øì:þ¸ÈX…DâyézÈlÒãÛ*ûk^ iŽã`Ó0ql]Ó@TE)1 Dzý{9.ŽãâÚ}z‹¯ákÿs ©Äq¤TF—h;0<Z€ªªŽãô«Šñ<‰ë¸(Šƒ£(£ËáUÁ¶ý¦F$HéáÉL†çzÙº¡ëf²9×E"³sHÀõ\‚¡ ªª¢iz6ïB ë–mÛ‰ªB%5æýw’4>¢³CS*Ñ4 C7ŽO¦ü¤(Š’T¥×4²Qo«¸ ªâŽKiÅ÷ê–mÓÞÑAIq±ß-*ñA£i®‹ç¹ÈLiËWNÁ“’t:ë8 ôàzéa„¢`Ùž”¡à:.žüOxä‰(ͯÎáÄŠÝ"l-nè˜æ9@Ó´)e_:mR¥»ö\7þÒVšä¥óˆÇb„ g{‚=)‘žÌáVlËò×ûió”€lh­ ®ô¯ùtå[HU¤ !ÃÎ0†a „À4Ç>7®ã?²zppC×q]Çvü¶˜Œ$j&¶/8,gþ´ÉÙo©õ°ÿš4þÛ ×q™]; Ì›;)=æÍ›‡"à¼ùóÒ?ªŠ`ñâ… ŒÏ³Í×¾BÀÈÈ©ÔùùýEE…s`ÂLÀ²,ý“O>YúÐO~;|ø° …PU%SòíÝËt á?e9šÏûþ`ôi{ž;ìyrÝÌêê_¾öËÔ××Óq¢ƒüü|?þ¸¹·§gCßÉ“¶nŠã8¾‡wTEÍî-d6þúßéÚ¶Cqq1ÿ¨ÖΚ՚H$ê3WUs Zó7WúÆ ø)£÷PM×o).)þm4`xx˲ ‡ƒ‡EYÒøq£“L&QT5[{ 4cö§—ìþëž³–}jí]Ÿƒ4MÍ• .¸•\@ý‘#üuÏNžìÅu]¡ëº¨©­!à:ãíý@×õl/±Ì8²H4‚d÷à/•ÑWeÑhÇÔ‚?7F#ÀgY‘Ý4?ÛWötÀ,³j‰ÇbÈŒ£ˈñ} Ÿ‡¦Ô,}&r'Û>›u€RbÄb±œËè£äy†a0£|ûö”ÒOtLcÔ~.:'¨šFWWWvÓ4Jb`)¥ÿy ¨ªÊÈȇbpppœ¹®KAa! ,<£M…Î cÌ~,I)éîò·ãñx<»ç?=ùKCUý··n/'Ož<ÔLatòyéœpÆR~æõø(±XlÂYEÁ²,êþZwZå?=õܬ8WQ`AF3µî®®ÑžÓž¬(Š´,KNªü9¦ssÿI—I)+8Cö%¥¤³£cÈ4Œjÿw€c/8Ž:tpÿÊžžK×uå OWH)-Ïó>R:çÂN`Ã×× ÀÌ1G=óYϰFÆzTU%Žèºþ !Ä¥“Ýp8•:Åt¥”ôööÎìïïßišæ„×K))(,\/¥Üãy^ #3€Ø€X™Ï= !ì_oybÜÍOàᄅ !J™@%Pžá2 ”E`ÐuÆÆF.ZH8žt]Ú¶M8FÓ´lkMaa! .ä’Õ—Lx­‚¡¡!,X°efuõøê$…_=´­À1 A ð ÐŒë»9€•\àá›±‹æéxœ™kºÎÁ>˜PøQÒuö¶vŽ;N$eöìYTVUe~5ùõžç1kÎ,XðÙ?ÊûY¹ÇŽŸ6NàÑGõDZñMh”­1<:&¡ë:ÍMM¼¶õ_§ä¸„þï„àÈá#9‡4ÇqHŒPYU•µé×ÖÇšýX9³:!Ü»îºkbî¸ãoëÖ­¶ÂUPñ×¾ € ™—]º®ãØ……gï¹ÃáœOu‡éee”——] âS¿¥gÆþSw…Ž¢(“[@}ýGCRÒôã¯X†£@8ÃA@S…þ¾>»lúôõŠªžÕÏW§BžçÑÖÚþôp*]ï¹®‘¶ñ  CNîúE¾ï¾{OYdç¤ð¿î¸kdøEQ®æ3Næ“"¥‘ˆ†£±£9ƦMÿxÖþ?©—éÄÄë.IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/pda_black.png000066400000000000000000000112601217176075400244570ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞwIDATxœÅ›kŒ$WuÇçÖ«»ç=»3»^{wmpX—d!ÈoÀB†õÆ&BHB Q;²#å (r^RD¬ˆùB o@‰þ†ƒ v@`Ö1$/¯wg_óèyOOwWÝ{ò¡êÖT÷ÎÌÚ;^í‘zúQU·î9÷ÎùŸskDU¹ùãO<Ànxïÿíû˜Ø½› .eáÕŽ†!ƬͰÖ(ùåcô~ÏÇ7ưgÏ$§NŸæÄ‹'xàOlzÏþ =ßzèÁÞ9¼ª™n!O=õÝ?½gdxØ,,,¨µî5 Dç,Î9¶2@¿¨‚ˆ0>>LMMÍMNîy8}9:ìÄ7½çžÇîz÷]C““ÌÏÏ“À¯Ø†cç\yLDètÚt;]AàœÒ¯øÅÆðvíÚÍ™3gøÁ~x=ðîËQâ² "¤i:”eÎ)'Nœ ›f„AP"@D‚€Ÿýìg¬­­qäÈ’¤Æà௜<É¿|îsìÚµ‹,Mùä§?MÚí²¾¾8œ+M€*å˜ÆÒ4%Žcn½ùf–––˜_˜×Vó\o·¯ŒŒ1q3::Ìððqœ°{×nêµ~î"BÅœ=;`°1À o|#_ü×åG?~¶æö;îàü¹3X[]ñŠDˆŒaay‘õV›áÑQDQ´åE!Žc¦§§iµZ<ûl?Â($¹ÃP“$! Ž9ÂwÜÁÑ£G¶å^a/ªš¯pñ{5‹xñÆXZZâé§Ÿfdx€( ‰“­cÀ3@snî7"yÈ ‚€™™Z­Y–‘eÆœsc0Æ”¿U•rÎEQA„6~JWò(H’„Ó§O333S"ÏÁ¶YÀ_»åñËS¬ÍÞ("„aŽçišÒívi·Û¥BU#T%‚òœ4MKe=ô½ˆišR¯×™žž¦Ùlæ±ÂnI½\>ÏΈA½pÎa­-aì•ìŸcuÅ«ÇDkm â8fyy™óçÏ—qZPæœ#ôúÔkÕUñþÚívQU¬µ=+ßïÏ~µ­µ¥«cù߃  ÓépîܹêrÆØBÊL²…ìÐÕŠMɲ¼ªKÓ´œ¨OÕHŸ¦ii˜¼>è…¾ÿîÇl6›¬¯¯—¾žeŠ‚‚襊¯+dUí¹±_U7‹äþ»W°:Võ¸O“ÖZY^^.QáQ *gØÎ—ˆ¯› ¨*Î9ºÝne’»fÿ*C¾¢þsõšõõu–——ɲ¬Œæyñåòʳ¨ ·SòRñqè d°g¯fÕU·•è]öžüxôXk™››+ÝÅ_ç  =Z_vxý”þï¡ ½ °_ªq¡ ½ß·Z­Ò0Õc­Ee} lÜ•Bª=ƒ{ðô«_]ñªÒ@O ô|`yy™¥¥¥’@Ui‰u¨«f„­ç¹\¾ 7°6>øTè¥ ~Õ«smm¥¥¥Réê9UÃHxõ글^Df<¬¦6Ÿ-úý¿Êûýç4Mi6›t»Ýúþ?f·Û%MÓžeß.йmá±ÃÐÛ*û«2@oˆ~JìSžçsss¬®®EQô=º|PÏ‹Y\•4XíÓUòL°?CxCôï&KKK¬¬¬ôP­7ž¯¼f—_ä²#è¿»÷SèM‘ÖZÂ0$Ë2àâ¨ßjµh6›dYFE¥Kl†¢*ÉòÇ®Š ¨^œbòVw§'°yév»=«î}zvv–õõuÂ0¼Hi 't»Ý‹âÉUrgµA§Ó!I’V×?©~4øl¦)³³³¬¬¬”Ô Š¢²uVe•¾§Ð;í™à¥ä² 0<2òkíûúQàY`?L7cƒ ,--”!ŸM<Šú+Go€lc+F„†††WóIÁéñíÍ‚ ll–,//Ól6‹Ž¯”ñ£ßXýhð]¥ >q©,p… àœ+yþ]Ð2 x¸öÁK»Ýfff¦ŒÕ®‘sŽ ÊÈ£!×e=cï ì( TY˜WºJbúÅû°ïìV9G€WÞÓ^Ÿ=ªÅPµ‡x©p³€ïGŠª”­V«mʲ,c~~¾¬ï¡×—=Ì«òÆð«^åûÿU$B@±¨f#Åõ׿KKKÌÎΖ>ía_-œªŠV¡^%WýÈÙÎ.U'ìÜTP´,Œ²,˹z!>Н®®2;;[ºHU¹j ¨;ýhج–Ø„õOs[yú’odBÙ†Iv:¦§§‹­ï ¤ôDýïýhØœin_ ^ÁŽPQå©\Þ ,üÜwq¼‚~ÃÄKueûKb/›¡Á»V•glV“ôÌóÊ5Eó? )Ó _¥8ŽYXX(‹/U¸Wl´Ä7CCµ1Ò›·›èözì,R˜@d#Íy狜ͤªÀ«ECõûÆ9WÍò?¶HƒÂUõ´öܹs—çµ ¡Jƒ{xÀUË€ñÄ=©íÔ©S¯z¤W‹ÿ¹÷÷K0¡+Ýq²/ÓÓÓ[ÒàíÄ_ãƒ_•ûfHÿ¹—DÀë û\è™f333ÀFí¿©£_fffzû‘ÛÅ€K@Àl{tÙààP:íuî¼óÎËî5ÉwÞYf–W³3T}õËŽ™ µùžN‡'žx‚µµ5â(¾hÏ Ïw3„‹¡¹qÎæ |>°Ùlrú´0ô*Ö¨¢Å$:ÄË/¿Ìøøx¹;\m‚æ×\¼ýŸ·úÍc­euu•n¸õõuŠíÑmôÏýÍ_? À£þÕëc?´¿u–9†G‡qÎY7ŒTDê²rSu84ßÞ.žÄ)Nm9içá]Q’¤Æü\“ö—Ç·¯øV²c*ìïe]lÇEÕáT§¨h±‚‚1€Äq€¨)œµtm›æ¨R\éßÞpÞ Yš!e!¶“Öx¸ÕÆåVò—Ÿú4ÀÆSÅå9 ‰“,sØÌà8ĈÁ¹Ü-êõ,,,ä+XµÔ’„‰á ffçHÓ"!*uSœ#Jå<éÃ)ˆºDÓc[¼Ö ûÇÏð±ÿ!‡¦Q¯P«Õ¨×LŸ¿Àä¾=¤1‚QXXXbrr’T3ÒNÊgÿé³ÌÏ7"Š"–W–YZ\â¶Ûnå÷~ÿ£´;mæçYk­099ÉêÊ*ƒƒÌ4gH‚„Ñ‘Q–W–I’:qEÛ? ÷z@íO`¯­¬ò‹/qämGˆã˜Ç>ó“Ì7çù‹O}’ÅÅEþí _drr7Añð#ó÷ûw¼xâ%öíßOÇ9â0!u0º{‚¯|å«zó[æñÇg×®]ÄqÌG￟ÿüÚ×XYYf½ÝáMoyoÛÛYZZä•WNÒív.Û¯†Hñ2Å+øú×ÿƒFÃŒ ñßOÊ`-aqq‰ÑÑ~õòIÎ9Í]w½“åån|ïáœerï5œò‘0>>îOQcŒŠˆ d"Ò‘@rq­ÖúHšv50ÐøgcŒ9pà:)h‚zŽÜ-s%s7²Š¨¶ÅË5ʧ¿JÛWÞP|3v` ¡ae·Ür³iç\ dªj烟sŽ$Iôºë®òâ­Š½é¦›dbb‚Z­¦µZÍYk³ Ä·· £X àsêÔÔ€ˆ¤$‰ƒV«%E-ƒ1RÖ1Š’¥)ˆÐh4ˆŠ"D N›••â8.hö†Û8uÞX*ˆ:µêœÚ¡¡A»ººf§¦¦Ü7Þ¸l­MsmUí¨j—":ç\§ÓÑ0 åðáà ðâ‹/*@øå/¹4ö­·Þª‹‹‹Z¯×KˆAàQŠH$"mcLl­3Î¹Õ 0ÁèèhÐh Í…y2vGê€ÈÂÂA £#£4ççi 4¨×j„aX¶¿:„0ŒPuÔëuÒ4%J]_k1<<¤kkk¨ªºÜotppÐ:ç¬Í¬½vßµÙþýû—s©ª¦@ªªYkµÖu»]766Æ3Ï[©–{ñùË9§ªªAh£!º{÷„+_ŽUù‹w‘^ƒ63Fùyrb¢oTSU¨Ÿs^êûf÷ÙòÞÕÏQÑhÔ·ºö’òÿ;gÃñ˜n°pIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/printer1.png000066400000000000000000000065711217176075400243340ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ @IDATxœåZ]l\ÇuþÎÌÜŸ]îr—K.%Š4%ª–\IÞ ”ÔÚ)¬ } PP ýÉS ô¥N H>8oMB~L[(Š&A‹8E_jíƒÊ°ÛIJLG–ØJ²´ZþíÝ{ïܙӇ¹w¸¤D®,‰°x¹»wæÌ=ç;?sfæ3ã³LâI ð¤IMÊX.•Ê¥ryŠ™é“h""ÖZG›››ÝƒòN Àïüîïýá7¾ñÒonní%Vñ·G3íÝÖgߣG\÷¿\.á{ßûþ_ø“K>J0U™šk43aX¾¿¢îƒåž§àû~sbÑİuÉÓ˜l§Xî±»Ö°<ÝOã=Èó´Öeó‰(´8`/ï@ÁGIPØq7žŽ=urr‹E… `"¾‡x¦|ÞOœ²ÌLḋàp˜>'f;‘<ŸšJv¾O“­i>5!|Æ=xÌ µÖ“ò> Ê23‘<àÍ7ß”—.]zù…^øJ–í,ƒŸ i¡ÕjýÊ¥K—þô ¼ R©ˆV«õÛ‹‹‹ÏX{86S˜Fc¥Õj}í ¼.z½îuîm“‡¦ $"ÄqNçÀûöjôz=h@gzqïÀ| ÍR@ªqXfB"B¦5â8>0ïÁ=@ ŸÔªo¢¾\¥pñ…‹:Š"' ¤R>Ä% „€7ŽR©Öˆ¢ÈTŸ=“àßýý?­V*_R†ª "’JyM%nÜXƒÖ»M…ž€ °<(äF¸óPgO)03¤T‹?|í_ÿ`°[“wg››[ÿø›¿ñÕwµ'¾ï_8wîÌ·ƒÀï×ÙD½^„L§8þ<Ò4EøCrñHVà±/ƒ~N>·{ÄŒüßhûΊ]¶í ÆÙ3gÑëõ–ÏœyæÛÕJu°6ÈÑüÿüqà¯ö @ø D„,3} „`Äq k ‚0€çy{§²Ì c tª!¡'¸~ý:Î=ÛBµZqgã±QÌqÜËóʰEøGþù_^£_ÿÊÅôvàµý5›sG˜8ßê&¤iŠN§ƒë×o 3aXB¥RÉ-Ä`›æ1,„@7а¾±ŸþäœÂÀ9 ûüÈg†4Õˆ¢RJX3Ü¿HÈ„ó2ÎCâ8Aauzn\ÏóšÊS%ÑPJ–<Ï럴pî­D­3°5¸zõ=èT£\.cv® !$Â0„ç)(σ’ À2cf¦/}é×Ðét°½½ÕW¸ÛíâÖ­›hÎÍcjj*W†P­N£^¯#ISXk!•tJY ËlI’ Õ)¢n„íí-l¬oà¿ß}¿üü¯ö“¢3žûâyªáy^mx^M)5æçs®ä üRJ°ÇèÅ=|¸úŒ1¹ÛÑ ÀQ žò <)$Hxž!|ßG»ÝÆÚÚŒ±XZz Ö!Ñé¬ãÆHÓZkè4E’$ˆã½^½(rߣIš MPÝî6¾øÜ/ŽT¨ À2 …šò<Õps æ”’Sn¤Ñ„“jT§ˆ{12“¹eËÛ<$‰É“W–e°ÖôÃÃd®ÁBÌøÙêxÿ½÷ÀlApafÙöy¬50Ææ3¬„˜Kž®Í‹n·›{À w1BJá)oìüpW<¥šRÊþ¾¨ M“þ|k­é+msA­å~b´–Á¹Ëºvë'w¶¨u:Ôûcôk‚œÇæ9Åõ±c³ûLÓÝn7þÑ9V‚ïû û ƒc‚Ü_ÄS‘’8F¦5’$`Tiçùo€ÃÖeûkŠvÛ÷¤1sMÎ_€`­uåæÍÛ^–é‘•ÛÛÛøÉ»ïÂZs¨¶Ä *T­ÏµP‹ê0ft‹Ð÷}$iRx€‡=€@yŠŽ™ÇN”RøøãñÑG×&ɾ7C'±µž‡jµŠ……£È†/À÷ýBðòBèÂ… é‰ËY–eþˆ¡97‹oýù·ú™ûpA7å=Ûzå©©±†!ʃäMH Ú‰ˆHݾ};mß½«¦¦¦0zøÉ ˜i4°¾¾fñx2ü>I ¹ÙYH)õEy» ·`Kò°w€fffHJI̬’$¹÷Ý¿ùîß®¬¬ü–µVJ)Ý(%„x饗0==¯ÿþב$Éâ<^B Žc¼üòËxæçŸÁ‹/¾ˆ¸×ë×EáÖn·ÿéæÍ›×fff|)%§iJêìÙ³(—Ë€óiŒ¡|ÿtñË_¾V.O}¾Ûíú™ÉJlm·²²räô©ÓÇÎ;7ÑIÌ£""¾øxžýõ×ßh[kS!D,¥ê…aÑê^ûá_Ôëõ¸Ùl*fÖÖZ¨óçÏÃó<(¥¬µ‚™ý+'¯LOO§:Õ*3™o …”EÝ_8qâÄB†‡f`f„aˆÇOØÆìÜåÓ§O_µÌVIK©â ð³(Šþ·}÷󒙕 $I .\¸¥”RœÇ ÀKO=µY®T62­=km`­ÕR/ênÿliqñB©Tª*5ù›¶Ÿ$´Z­kÓÓµWN®ô8÷!eì)O§:ÝÎs€;†a·­¦žþy¤i ff!„%"ËÌvjjªãû~ÅZë1sÈÌ!©õõõÊòò²_*•½œùHH)…V«%1÷–7­µ)Åb"J1íj¥b°µ–™Ù*¥ –——ÁÌœ#cX"2Qµ766¥”/¥ •RµVfY¶2;;”J¥‰_M{¤”B­V›^[[‹=ÏûXk­1q–eqf²¤^¯ßi6›À23‚ `U«Õ8_ß3œò‰jµÚQJ™n·;¥” ”RáÖÖ–0ÆÍfóP)¸sùùùÊêêj†áÿA`Œ5±ÉL\.—»õz½KDÖº“ +ávj™™YJi­µ†ˆ4aaaa@@†ÿÁêªT*ÕªÕêX™ù¤‰ˆpäÈ™ÃZ­v§\.3€@’jfÖ Yc &"Ê3ãη8² ¤·nÝ*U*•yÀ!~Ø( CÄqÜl·ÛÛùÔžÐù•Qg}–R²µÖíÑð …‹‚=ÑûWß•Je×SÖÃBDtìÚµk ÜHNþ„¾û€‚w®hx¨ƒC0Xk»«««åùùùùǢɄ4Ó˜Y¼rå Ã)Ÿæ—Æ@¯‘EÌ0…»ã èÛ·o'k7ÖfçççëV…‡£¹¹¹ÅËo_1°¼ÁÀò£GÝØý!Æpì»+[XXàõõ§ªÕêá þ!:¾||þí·ßn` xñ†ÇðÕ§û-ê‡A`XYY9ûdþDiiii:ŽããùÏBö1Å :P-{ùòå7¾ùgßTY–¶Í€>)©øÎ;í·?¶‚æqÓáÛ×zÌô™àÿfcĘkØüIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/tv.png000066400000000000000000000103101217176075400232030ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœí[MÏeÇQ~ªúÜw<“D±lYAÈbëÞ dذavH(’ þìïȱ 1[+ìH !Ad“ÁžyÇsïé®*UÕÝç¾wÆ“i€¤gÎÜó}º¾žzºº‡Ì ?Ï_v^vû…^v^v[àÛß~÷_ŽÇãƒãñ¨Ç›#Ç#ö»€ˆ.611@×î‰s €… ¸r-ï5Ì`¹ÁU ÀLǵ‹ f3@ fŠÖjk¨ëŠÖÖZÑjõóµ¢¶Æ­¶úÖ·þè×xøðá¯ÜÜÜàp<âææˆ››ì÷ìv ˜ –eA)ŒÂÌ . pA)@)…Ìe‰ýÂ`fì–ß[)þfƲø»Kq'Qˆ4ˆˆo*&PU¨*j¨4ˆ TMÚZÎÔâºb=¯8ÏX×sìŸP׊u=£Ö†ózF«í׺¬ëŠR ¸0–â%"ÜÞÞ‚@(K‚,…7¹LCLìïe¾PÄö€.¨ª[p>Q¨¹à"®1ƒN÷‰*¤5¨)êZq^W´Z¡j¹Œîù[µ+àƒþ÷îÝàp8âx¼Á+¯¼xソÂétêœ[ºîóÚ‹Üó"íESõå}µV¼ùæ›øê×¾†ÛÇ·8ŸÏX×§Ó ­5¡³Ð²*T%âMñäÉœN'ÀÜ7»óõËÃ+¶«»›FÏ<€cÊs‡Ën5Ãù|Ì•ãÞä^Skõû®v‚†Å×uÅ+_~î0Ûß øâ˜ÀÇñwû+9ÈôâØ€èÇ øÅu$@n_üñGÿŽõÓÇ]páÉ#äº̆ûøøœžâ«¿ÿ‡xû7~ Š%°¢®8.”BXØ·ÛRûL3aaàâª`š´b‘ G~š)T ¢5@ÔÐÄE UÔ÷EÑÔ qílŠ¿ø³?Á?üÍ_BudááÖÃsã"ÃÍÍ,ÐØ_pÿ¸àÈ®E^JäÂva—B(äû)taÃ÷‰]hÊã;‚¨¡,[’¡‘+¢aaëŠXØïo…ý·}ºBÌ<+DßSØyŸyR€ˆk¥”Æpäô˜Hk®]S¨Ø ¥,060Ì€bî¾ÂæÖ'B1@UbŸAEÅ7&ðX…{‚ áÚà \ps-΋žž?­X«€—Ò3FUƒ#dÉYR›mÓš*¨¤Û´xÜÐҊɇæ©ÿ3)aŠÿᙆ§µa­:B!=SÂí»2­6,´t@ß¡òªS\`Í4ÒÓ‰B1ñu ›¶x03›__"w5§×.»[žx+½éÈ)|ÁÓÉê˜%Fƒ³\xM:›½Û³€Ák[¦° "ÞID‹€Œø Æ [ä–²ÀtR@a0´LF ÀÃàMÔ°6Źj¢àª|`€\ †2j]ð¼Þ=È•O“²Ò“ xGS 1;ðYñ<_­)f)¡”õÊQá1âÑ \|+s´¨áéÚÂê^Â$¸©v«k/‚ØÁ‘ °¥÷Ykp ™ ¢h­b·[ ¶Í›Ð"Å0)ÈÐO X ÃŒ"çxahŽ•Á¢#ýÌJ¸2<¬MqªîÖ0í´8CÒ&ޝf½b4²•+<Àn®d1f]×»ƒ¡æšZOæÝ"ÕTˆ ŬfCæâ¡Áá…ã} %©{˜‡ÀP€(šÎM±Šxa"C)´)L³N(NŠ:UϰHâ£äîd8$ž "Γi£­Ôô¬ ÃJ©¡°…"Ä e/˜’ŒB(gÌÁ4Ç€i1óXÒÕ<&ÙæîHo“à³ÕçcÐÁLñ.—u yŒ¬­Ç4Em DÚÇ™}i5«A9âž TGÕ—³úK[ׯâcúds‡=ÿ[e³mì{šÎAö°Ð¦0´þ\k­í»ÒE¶0ç̼aæÍÉ©+¤Š¢ÜãZƒ¡šQ¸X 1EAí<0ÔZMêP(ÑEI,kËÎùö"8ȌƼžã+Â+Jb^­Í°Ù€ªCèkTx6†š9˜0X/‹iWNÏS8)«mÚ¹É\Eu7š Q*`­ µOzj°?âÁöZ”³’øhXÜ•ÑÅîx`[SxmQº£B;ÔN‹gl°ÜUA(“ TJg™¹m¦Æ.i0hL# ˜ (¬O\PØ•ÕàU[^2+‘÷•@¬}ä—lÓTÚ¨©#JÆ¡‡ûÛ&’Ï! á⪠†lä1ïOëæš ˆøÇ$.ÀIÕÐjY wWpQQTi­ƒŸYõhÌq œù_&eLÍF8vðKWމ™ô€î±†I…M Š•­=c$˜FóÁPáxᨠÍãhÑ „f  ÄO‡¬$HªºY=tf%\€ÐBocyL‡ëwî’‚O`ð%öÑä…ºæÍ•qY©›VŸÓþf0dä'Û'ÿOtÿ嵘ñVÓ¾ð‹†(m+lã"ÿ×Ûv¨ïi~ön|9™ˆ Ö©c±âÿ‡¶®k/èä¼@k çó Bà7ÞÀn·Ç~¿Ã~¿Çþp€Šà­·ÞºÖN‹·ÅŒíþü›Þ“#Ät·•¤kÏ\Ûµýk%Ãê_ùÊ/áÁƒX–F®X×ë:)à·¿ñ Ñfç²,øÍ¯=–Ê–X)«I—¥/õÕ¥¹„Ö—ÊÖZÑšàÞ½ìv»žonî]]6›JË¢"1_óX!Ú Ís"TEbJLúqmyݫŵUÔµúj‘\‚+£lÎ&.ÏCœð´íÐørpr™²~Ú6{Ò³Û³¿±ñë÷•RBÙe>Í@xÀùtªŸ<=-ë 05:ŸO~gºr x¨çÿäuÀ¤¿Yñ…Ð^YÎj0÷J\üxž(™‹ž’Õ˜ °)wkÖç “ f™|ü:Ží÷Ì„ûîã|>£®õQWÀßþà÷¾ûÝ?çóù¼ðê²ì~ùÁƒ/¼ýÍ?øæŸÞ»woQÕM±òšô×ìVq¡·™†bÁÕµv9žŸã=»Ý‚>øá?~ï{ßÿãÃáøoOn?ùáÛoÿêíïüîïQkm,–~÷Ýï´wßýNºâ¹µzûèÑÇÿõÚk¯}tÿþýû"R°æB +‚] c‰FŸ³MáqURÚ.·3FLÂDr8ìÇ?~ø£ÛÇ?¼}Œÿðäý÷ßo›çç&/”Üð¯ø"€q|`·, ív;GÛï÷8ºßïq8ìx¤Óñ¬ñôŠÙº—ÇiíüÍíy M!gÁÓ²2íÏ¿íâøRYwýDfîìÜùË}¾rþÚñüÞË6[ìÒÃ.÷çßËsןÿàs lÑÛ m¼ÿþûjµ:ªi===@ƒ€t:Mgg'‚p÷Ö …˜žž&:¿õõõqõêÕ'xàÈ… 2@¥ãn‚ÇãyNEO<GÓ4,Ë¢R© IápxÛF£QVVVƒtttpåÊï‰'ž;qâÄ{üÒ(—Ë¿3M“X,4Þ~&“Áï÷“Ïç·Ý¡aÌÏÏ ©×ë(ŠB<gyyù)àß¶¬ÚBÀ›o¾©[–õ¤ªªÄãqg*+•JD"‘m©3 àP( i‰D‚T*uèÈ‘#cccËüB¼^ï`<kkkèºN.—k¹c¯×K>ŸwL* Š¢zäÈ‘gÇÆÆR´Á ÚB€eYϨªêغeY”Ëeü~?’$¹ê¼\.;ëA…B¤Óé§ ¸Ô‚v„Âb½^BUUü~¿3wK’äDtnŠ®ëT«UA°IÝ?44§ /Ðu¯¿þú° ýš¦a'<êõ:ªª’ÍfÝv¦i|Èz]}êÊ•+“@ÙMÿn <Ï1EQ0MÓQS»´2ým†eY¬­­5n¶Þ¯®ë†ñð.ÍÀ-¢eY¿•eÙYêÚo˲,o)d?®ëÔëuòù<’$9Þ¾Š¢àõz©×Ï(Š"Çó·¦i²Ù¬«ÙÀ5‚ ܯ( ‡æUŸ$I-S`©TbaaÓ4Éçó”J%,Ë¢X,288ˆ¢ü5bû{Zµ ^oãÝ·oßßœ9sf³[Y–UUQI’ؼôµo#ŸÏ3==$I,..nxÈžžEÙ²p²åmdYF×õ@¶i­ÃµP%©ªªãõír;D"dYæÆȲì„̃ƒƒÎ‚i³¼MHsöh=ÉbÒH› ´¸8rm²,£( ²,Ûƒº£Ð£>ÊÚÚcccx<>ìP·‚eYN±µlý¾!Sùî022h& Ù n† äóynܸÁââ"KKK¬¬¬P¯×ùøã ƒ†A,# FQUÕ‘mF *à*ÒrC€ C¶:þÜÃÏÎÎòÃ?°ººŠ¦iD"H§Ód2†††( ¬®®2>>ŽeYøý~rü‚] AЦia\s®4 ^¯ öƒÛÎi³;sæ —.]"‹ñðÃÓÝÝíxú‰‰ êõ:ÃÃÃN{˲˜ššâ›o¾áÛo¿%•JqìØ1t]wª]DQÔø« ´W„ÃáNQØüvN:E*•âþûïçСCŽhnW«Õ¶Ö××G0äܹsø|>®]»†®ëtvvnè_–å»i–e©Í¹}–eqýúu._¾ÌÀÀ‡Þ2=T*'Ài–¸|ù2}}}”ËeŠÅ"kkk‹EÇ/¬·•hh€H‹yB·³€ÖþÚ¨Õj,,,H$H$”Ëå[zùR©tK ˜ššâÊ•+¤ÓiGõGGG7´Q%FCvÇ4M‹mÖ€|>O*•"‡©V«œ>}šÑÑÑ-¡®Þ ÇŽãÇÄï÷£ª*ýýý 055µ¹©­-Á• ‚ 4'vüáŠŢ³P…£GnyØr¹ìC› yä‘G6üV¯×ivº’$Ù>`w4@–åÀf èìì$‹qõêU ÃÀ0 <ˆ×ëuôìÙ³,--Q­VÉçó|ðÁ lQñ»ÿ®i¢(ú›5`ý7FGG¡^¯ãñx¶ÄÃÃÃ|öÙgˆ¢H&“!—Ëñ /Üõ}íþÖCaWq€á &°ÙË«ªº%™a#³gÏ …¹\Ž}ûö9Ùä;Üpãàq€+pÇž(vÝŽ€;áàÁƒÈ²Œ¦iŒŒŒlK¶yÖ »èåÍ&p·PU•£G’Ë帛³C66Ç‘H$¼ººº;>€õ8  سgµÚöã—¦P˲v-%IŠË²L&“arrrC6g'`ï6•Ëe|>𦠅â×®]kyIìʉ½½½ nKÝ¢P(055…®ë|ùå—2»åºººÂƒƒƒH’D¹ì*;½-ȲL?¢(Ò××g|÷Ýw»b‚®ëá¹¹9R©Ô¶A´EQèëëŽ4‰p‘rE€išQ¯×ËÄĪª’L&·ub»°3O¹\ÎÙ1ŽD">\,‰[&àÕW_†A¹\&“ÉÐÙÙ‰išVVVx÷ÝwÉd2N{ŸÏÇ+¯¼âœÙŒZ­Æ[o½Åêêªó›¦i<öØcNˆ¬ë:²,S*•¸yó&ÃÃÃÄb1.|@«‚‚Ïç3C¡«««ÔëuÊåò†ÒÝÝÍôô´S:;;EqK;»är9†††6ÈèºN0tÚ@ãHm¥R!Ncº®‡p ¶¬>Ÿ/"Š"…BjµJµZ¥R©P.—QU•ŽŽŽ Ë_ÛEQ¨ÕjÎqWûM©ªJww7t:::0 ÃÙÛ2Y&™LnI&“„Ãaç„I¥ÒتV«)¢(Ú+–вT*E–eŠÅâ ¨T*T«U’É$Ï?ÿü™ŸÛ-®T*-2+++Îÿ…BhäìG–å(.£-`F§ÿïß¿Ÿþþ~TUE–wîd«$IX–Åðð0ãã〳6h9'в X–%twwsàÀæçç™™™¹³à],š~®M0$ ñÐCQ,ï½”Ëe¡X,ÇùôÓOyã7˜™™ÙÑ`È>"óÞ{ïqøða–––*pï#ÁÙÙYáâÅ‹$ >ùäz{{fyy™½{gY^Ò™Oì{pš‰«Qr9Ÿ¯ÄàÞEþôC#ÇèHfùߟRôö® `1õ—¿N³¼âenÎçÌ'Ož$™LR(¸víÚîä———I§Ó b±‘HĹöìÓg¿0ÄÔ_HR•çŸ;ÃØØ—üĢˌŒü‰ÿúø(}}3üú××8yòÜŸ™çü º@6¯1>>äô¯i7oÞDEfff\k™€¹¹¹EQ¬‹EÉX$©J8ìÁôßGwwMËã3|„#÷áÕuB!>ÃGww7ñx ¿¹èÔM³HGÇ”S÷hKCY»{¯­­‘ÉdH&“”J¥)\œn•ëÌ™3/]ºôûãÇÿkµZíM&“xåUôl’€Ñ¦é˜ž4z6I4ÜM¥¦bz$ôl»}Ä["Tžuê>¹L¸ºâÔ=õ=FãóW³€Ûo†À Ïfú¼ÜÎpqN°ƒU€0Р؇–vÓ¡ÓÀ, _Ô2ÚA€@ÔtÀÓ¦> _  ßµs°Â¦¿; ‹6}4õ[`¬¸6eIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/devices/zip_unmount.png000066400000000000000000000126761217176075400251620ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ…IDATxœÕ›¬eWuß?kïsÌ{óÃ3ã±ÝŒÝ†Øž€ &fR·A…þˆ¤PF²Mˆ€ZQ’ºR " ¹þèR¥ŠRDPA¤S‡Ø‘,› *œª@þp‘ÛÌŒeÆ!@gFÀ»€×:pŽ7ÿ°WyÿW;"ð ð¿?þh^Í ®•»€µ²mÛ¿™×õ[bˆˆ³ùœ3gÎ2¯›¼¯¼r–_ü‡?€©’š„¹‘TÁ 3Ç<ï®›u’aª4šÐ¤X‘†Ô(ÏiR*×RÅ€™ïZ[»tëÅs§ßÿÓ?sëàsÀgþ.p ðÛw¼ñ¶{An:qâeRRâ8¢j¸9k—Öq²Z˜/Ÿ:ÍúÆ M uÓtÌ03’Ú4™ÀRʪà^˜R˜ãª¨'ÌAÜ:µh稪€@᯿„&{ó[îü¹ÿ²g÷ÿþÌÙs‡ 3^¸á ÇïþëþŸºñØÏ½ñÀýuÓÜtä…ïñÊÙs¸ƒët¼»P‘ü[ÍóâµØ|…[{jJ*Ì03Rj0sHMCJÅ6¤„j>75 ³DUŒ§S.\¼ÈóÏá왳{÷\·ëßíØ±úð8ðKdu¹&|IÕþr:ÿÖl6_ýöÓÏðüw_ÀT !šWpGÕPm?óâ›&›3E<³Çú;‹ãæhR’&T¦Šj!\uI"D KMQ™,Aù™â™“Ñ‘À‰S§øÑÿy™ùø57ÿSwÿ‹ßü×ÿö–ÍÄVóÙló±9o ç/®±>›SUÓéWGE‰U„ªèw2RÓÐ4‰¤ì\µØF÷…”d+o˜[ÖçBŒªfƸ#’ o½Ùò1ëînùž¸Œ„ ÄؘÏIâªéçn~´Ä÷ÍôE„[½vw›eg4C@5ªh’QÏÔ•ºnhš†&)ª‰zVÓ$¥nRÊúßn„š!Å @àüÅuÆ£QfŠBApR]b õÄæŽxå*ßhy8Ž‹`n´¢Ú ’¥¢Oáà]oaTEÜ„dÐ\º|™ÇžøˆäCÆC!nމƒwf¸ xÞýÔ¤,qwl/ÀÏׄ E­„ªªØµc¨µ ªjs¥I ‘À´WŽl•€b ,.¼dKpq¡®kb¬¸´¶^Ä®%4syuu[Öm/ÆËòÂï1Ũb&Ô½qÆU…¶ö@„Pžï­q ¤”¨bÈ"Ž@ËÐò OŠ›à-ãd«ÍÄ-Aª‰«…øOzÜÔ"A^ êÂÑYo ‚ooŽ”‹ƒHï|GÀ ")»l†A¹_( È#Û(E½ $»×” ´vPuDÈ^j@Ú+Õ­ÍŒ YÄZη 5s4¯†öÚþî»C”Å®#’-5í1ëî¥ö-ÖOmìÐI¨t®té| yS˜euiÅ=CÍîÔ‡P;T}Ó5#FÇݺÝ4kÏsD¼ÃË¢ŸÛƆ¸tD›i¹—•ݤ#zA”Ñ;Ô»¿föìmºÿÄ‘ ÅN¸)å`Éi‘£wÏ\b@û€epL­ˆ-« ÷,fUQ 3/ll-noÇ=¡ì~KT&H͈EÜÊÎ-˜½IºÄ!€§B®j„îþNj2JO hïܦÙ'Uý‡u-D™:ż,ÄWÓ‚Óê¤#¸;*eWʽ­Ýa#ŸU,€/½XSyÍ>¾ý_5KOáâ)! "¡ TeÈåWÞfhz'Jš#”Ng7K’jÞùì6­[p(¨®/ÚÙ¤Är ÊtLH¦jÓ^/Òz'Qo ¦©.XC£2_섃–Ñëâ78êJð°ÉH¶Ä…,IæJí§EͲ•n–$&HD<»·–)íó²˜&¶®°Øj #>¤î•ûVΨ&œHJÖ:Ó¬ƒŽ“JÐBèy‰LHk­[ãÚbü¾éþóÖ8Éb‡¤H_§*ŽYÚ¤V FX‰8»kÊ3³¥Þó‡$`ˆ+掔Ý7Ó¼¨¢[Y¯„”£Ñ¨#~i÷z‹\,x«}h#¾NäC pŠ!ÜLh=µ £KuCÈëmíTÎäu‹HN¦ ¼€é€h‰*v@X<¸iŠ7ˆ±è¶ä…•ÈÌŠ~‡H)‡µy‡ét¿!dA «1ÉÌ6ïˆlsÙ-/¤¦ñúÃÑa–ZÏиÀú4ä†l`W5§±zÒ£ñd… 9HruÜ[Uhcwc4ζ#c÷|NÆzRJ&–3 IJ#Ü=3R ƒâ‘i™!ˆÄNí¬xß„2ût,KÀBJfŒ«XðgŽ[އP±vá"Ç_<Êx4)î0aÒîxOÙÜ Ï®wEÝ©b̺«t ’N,‡Î-¢3 ¬¨S‘PÈ€ÍT ?} A*Rçó5K®·êL ž0dÄKFb‘‡‹Çcþúø üÉã_fuû.¯¯“š´@onÅÄIè~•`t(»¯R3ZÛ#Œ'c¶­®RÇHŠ¡“¬ÖE‹C´kkÈ?ÿeF“iN¶–45ñ”fÀ‚"’ÝCµ&“äÆxeÊ®Ý{™Œ§Ü~àÄhêÔ&:b2ªF‘ªSÏg¨fLÑ²É žp,Ÿ?™L˜×5ßù7W;5QKÄdÁÒqrfa‰єj:†õ…mA T(9jtÖ‚A êDɦ¯-ft®Ê”!g3¿Ì=r˜;·2ñµŒ'Oqó/þ3~ãÒYî;{šÓô$Ø<¹c'Ãí¤b4s f(9Ç`–%Ù|17зÊíT7Ürv¦eÛ"ß".£njæóŸHÌý¿÷{ìßÿ÷xüñǯ™ëó hj óM³TJÁ-Ù«$â{ë—œ–ÛÌZ\Ò›RÜIŸèÖ7«9–”‡d7ó“Æ£üÇœô¡±wï^F£“É„ .ðñœ3gÎpôèQž{î9¾þõ¯ó­o}‹w¼ã9r„º®ùä'?ÉwÞ9È~Jdèÿ6S•“/¡W=ª ¡Â4å» æ–œvŸ³¦¨@¬)1sËE ·|Y£)%Ο?Ït:eÏž=üà?ॗ^âÌ™3;vŒ§žzŠ{ï½—'Npüøq^|ñEÖ××13:Äw¾ó®¿þúi€y[C%~Ö6¦)«@¸GÌJ²ÕÛ,ò€ì[Èv¦”r$V0¿õ"1GДýp.Nä½ýíoçäÉ“<óÌ3|ñ‹_d6›qàÀ>üáãîìܹ“mÛ¶±cǪªâ®»îâ›ßü&ï{ßû8yò$Ÿýì¦2}ß.]adÜÑ+¶Š`î—ä JKΆ냵A))k§U…gÿª=¼Í€a¹çž{8}ú4?ü0kkkù¾–^ºt‰~ô£¼õ­oåSŸú»wïæ™gž Ÿ ‚ÓnRÑñ6†±ÔE°Kñ¦Q q¥€Ó’ym=aÉ ‘LAÞ[V÷Þ÷¾—§Ÿ~šÏ|æ3ýéO³ÿ~.\¸À'>ñ ~øÃrß}÷1N™ÏçÝ._wÝu<ñÄ|ãßà•W^a2™ðÁ~py E¿¯N~.ƒ™g\"n9såÔÀµ^ n)5Ë% lR¢êD€™µ`íزïüùó]àôÕ¯~•õõuΞ=ËÛÞö6¦Ó)±T€êº&¥Ä8zô(<øàƒÜ}÷ÝW%uh´@U5ÂhDJú¼¸h¼$vt ò̈H±º\›7í`°¸t%j€w¾ó?~œÉdÒÅ MÓpýõ×#"<ôÐCTUÅ#<™3g9|ø0wÝuçÎcß¾}[×:h¸Ȇ9©’Ã0*3‚[Î4{A®WЦÁò¸›gñözê ¥yŽ»Ë!. Ë 7ÜpŵV¥ˆ°±±ÁúúeÖ×שªjx ¹R2eKîJº™Ý±©gL_´ªJˆŽamÏQ‰0ÌaU%Æj . YοÇ(ŒÇ£+=4öíÛËM7ÞÀêê¶«ž7åzßJJì%cÿÖ'`/°Ú$°¢ã%ÿßÚ¬¼Î˜íC)™ QZù€‹Êls~ËEÏe9Q"1ŽøOÿù3ì»akÖ¶$ŒÖS@Ѩbמ›ø¿òn¾ò'_ç~ãÛÌçó°âB`ÇÎU޼ð=X;ÍÀ…2Û!Ààû³šª™ç<`Œ%‰[2Åæ8=ï`v…`h@rN0”Dd›—Ëið .È5*pþ}ìܱ‹(å{ùÒ8!DÞõóÄ*°¾1£™×¬L§,åd$3úß}wÿêW™§\ª*Àx4œ:5ìÞµ“¿üÖ·ù_÷Û{# ñªèz/€kÓmî4Í€ †’AeE b—cǽ §Ñ„ùÝßù-ª8Ø€õºÛªŠ‡ÖÖrñE"ŽfôJi¾€\ìIðæ1˜É\3Ì ©v…õÜä¤)åD£Mýª3_ÓøÈG>ƒ>Øýžm¬Š—5R g²TÿùÏó¥/}‰Ï}î÷9tèPÙ¡ Î2‚5ˆ‚zÎ_H ù〪AË…E7#A©¶!æÐ3•´ÓPUéuGå _øàºëv‹œ¶s¤«KÎÿ‰–œT*ÄCÒ^¥fsu3&¨2Ñ”»9Ãʹª©øÚ€™ñä“OrìØ±¿3˜ÍfÜzë­¼ÿýïïŽÏçsf³UUu­9‹f«„jÈæ/DRSg E®:k×j;à‡¦º&V m‡Uix6CBUà$«‘ :t(ëäë8n¾ùfž}öYNž<Ù¡ÇŽI±h8 Nî !a’½@J¹7é€j U.[©[PºÄchÉåðøµíøµŽx€“'OÒ4 o~ó›Ë¢òâ’)¢‰HEŒÙ}'M¥9£É`H­ô /j¨b*!PE#ú¸txµ¢æ¹«Ó¬0ǯ|åIŽ9Êhôê`ñ•Æ ¼ôÒK¼üò˸;Û·oçöÛo_´Ê´] (‘EŸqVœËR÷*¥­ ˆãQN*x®¥Ò&4åu—E§Ø{Þsˆ÷¼çõU{î¹g˱® gmsµ!!ƒRÏç9ª5Ïv HÄæ1Ø'˜êš"bVй¾˜ä¼ îH%l[¹zPózŽ•Õ)P  !æÞ¥”°bŒUsLP7s¼×íÖW´¡4Cum/ž]á$æ$¤'ºð‡üû÷ïgíÒÚ³WÒŠj^îÖÿa ûçK_¥²öìÞÍ7ÿìÏÉUkˆ;ލëšGµ„x®l§¡ŒÐPe¨ž×„j<¡ øLõÿ£1]ÙI›Äm¬É¯lI(]$í{©¼i2À€¶¢£ñhBUU„ªBÊ[‹} l¿n·ÄRÀRîé-ÝY¦¥e¦ì¡ç^C× YEÚwÛäœGëÒ¹ë<ÎâŠ;9ÏïcÀ‚8iž_îaD cé7.ùB`íü¥-´Êf½ø™Ûïxhºmå‰Èv`Ÿˆ¬äÕâfÖ¸;;vî¾AB›jÉÚ¢)AÚÊÒ²À·½=¡/º¶•¶…¥= g%ôRÝ¥“Lzç¶Ì-íû~ùâ¹³"¢!FBˆ¹Ã0·dfç6Ö/?þ•—?ân{UˆÈˆüÞßÏ’“/#€£Ç#ßuÝž›¦Ó鮣Gc™L&¾²º’&ã‰WU%±ŠRU•ÄCŒ•Ä%„ 1‘ÜJƒ”@±5¥ÐÕJBi¨r3w3sÕÄ|>óù<Öu#ªÉTÍSjPµùlãò©ù|®ªJÓ4V×µÏgsmRsÖLÝvÛm/<ûìs[t`¸]Þ½‘ï'öïß_ñÕñWb@ÿ9Vî5ÄˆÍ izÿ·å`ß4—éºRVx`„ÞŒŸ›U›~÷ î§÷ÙŽþ‚­ Q–™}¥ïºéøkb@»PÙôýZq…cWÞûì/Ô6÷s¯ºóíxµo_õfÿ?Žÿ EMµ< fˆ"IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filefind.png000066400000000000000000000457051217176075400227300ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½yÔfÇ]ßù©ª»=ûòÕ-k³%/²f9&!`0†Ã˜Ìb{ „I2È øÄ˜“™ƒád–˜a‰ˆì¯²$K²¶ÖÖ{¿ýî۳߽ªæû¼­V«7u·¤W6¿>ÏÛ÷¹õܺu«¾õ«ßZWA0ñÓ?ýÓÿ¬T*•a­e›Î=~9IqE¿»Úö !®øWRÇê2Ÿþô§?ó©O}êãÖZsM7ºÎäT«Õ™÷¿ÿý¿è8ÎËÝ–¯Ú¢µc Žãàû~㓟üäÿR cÌΘY€#„ð·¶¶F“““•<ÏŸ÷ƒ‹ÍŒË͘«¹îjËÎ¥ó¹ÀÅ8Ú¹ƒt±sÖÚ+>>ÿZcÌY´Ûmâ8ÖBG¡¯èA^"’€Bˆ‹±ÏzþZ®»Ú²sé| œûýBÇbÝ+»Ø±”)åÙóçžÛ>ϸ¯¯è!^BzNƒv ®ö~ÛôBApîñÕ€àR×]ùâŤç!r'€àZ®Û¦‚K þ…~s1œËÎ-ßѸPã¾Ú@pî÷ëÁ .£ì(ºèšt5 ¸š5ü+;ž\ªð¥ä^n\©,pþï/Åîϯw§ØTÎ' ×Ð^i 8ÿûµ€àü:wò쇋È_©ôbƒàB,ÿü{ì4Npv øjàpùYz- 8÷ÜÅ®ÙitEv€K•½ x1Às.]h0^Lìdzž °@ðb´ã|ú{ô‚ì—*»Z ÞWv2½`;ÀÕ–íd\©­àj@p5mz)éªìW[öRƒàZ…ÃK_Šå¿â8ÀKɾwмp!ºVl_hà_`§€àår%õàrÜ`'Ò5{¯¶ìÅr%_MÙ‹E¯˜%à|z©fîNÁÕr‹ÛÉtݼW{ÝW^‘jà¥øJÁ‹íE¼ÔñNømºlŒÚ+×rÝ6½\Šìx-`'r¯tœûýŶ;b§€`'´ã|ºZìt \±x©²"È½Ü ¸(v*Ixavë—ræ¾Ò@pþ÷Wp`ç (;•„Ïé³Ë}¿ýÀ¾×ui·ÛÔju*• A©„ï{x®‡ã:Hé ”$Ïsº-|?xNýï}Ï»®úY^2oà¥Ê^i\®<²h§s€—Ôx©²£¾<çÒ ‰'Ø©ô’{/UöRÞëjÛq>];^oàåîµSÚq¥t)\ bû¿—4/›7ðjËvʽΧËE]´. BH,/ þ²z¯¶l§p¤ ÑÅfüÅê(ôp Rðr0—Ýxµe;…#]ˆ^ˆ h$¡B‚”.rÉ‹Á%v„7ðjËv Gº]© (¬ÄU…Ñ*Æ_Šg§ç¶üŸï¢÷{±é²o‹|©Apø‰§øÂ½÷ÓÝê2?šù“'XY^fQR¡¬EË(Œ°À?øA¦¦¦ø_ó5×­{®ùÓóüüÏýƒá,Iñ]„`8è3|ºÇ©cG(—+LÏÎ295ËÔô4I4¢\©}ÝvBJ*ÂÑ(ÐÙì0ê$=ò(»çvsÓM7s×Ýo¢T®rêèÓ¤iÊòÒ2wÝuO<ñßò–o½îËÒös=ð¥˜Ùµ‹§ŸzŠ(Œ©7ª¼öõodn×.Žy†ÇO û8O¥T•þœK¥V%송õïŽ|B|°(ÿüû¿sÑö¾ØtÅaá×£üü²G}Œ?øƒ?Äu=|Ï Ye9ýN‡4I0„,Âá·:Ž;ÂôÌ »÷îÁæ)§Ož`s}õujõê5µñrmßÜÜ$#–¨ÕkÜrû«)WjœóÙϲ±¹R éºH)ñ<?èv:diF®3¤£p„*¢ ÓçÔ›M&¢FÃþ“dÎmGžçüÆoü>øB k-ûèÇøç?ûÏÙ·oß%Ÿ­ÕnÑíõ˜Ùµ› H“ ÏPRb‘X©²¨37†>%€ã:”+±°¤YŠ5šÜÒ,%ŒFÔ[SW ´$ð<¢ÄAXS&KRZ ¢o±G2ÝÈÒÇ¥”÷ýØþp|]átÕ† Ë•¯olðä“Oóä“OÑétˆ£ˆ8Nˆ¢Iš!¥Âq|? ä{ ´õõ–Î,gB ÑJëºxžGP-£¤CǤqLlCü D£ÙâøÉŒF#*•ÊÛù¥/Ýã9t:[l®¯c-H!)—Ê<øàC¬¬®0;3{Ágûäß~’øÃÔj t®IÒ¤à^Žƒïz”ËeâD ³ç`-QœÇ aá*—Z»ë*$>ÕR‰HLèD£ÔéØÍ©$N :•¯ëT;ÿr¢ÞêþÎïüþªÖª¿*¤ÚÁ(†xžGÁ,É{ÞóÎ+ì Ñ5‚.TF_úÒƒ<òðÃdY>ð\Ò4ÁCÅ8¾çº(×Á÷=”ã%vïÙÅ¡CØ5;ýŸÿ"ó§N‘a™š˜Ä÷\<ǧâ•IÓ!%ÆXÒLG]êõ§OæñyßûÞÇäääsÚ©µ& CLni4§˜lOâ(ÉFw‹Á ‹19Q]ðÙ>ññOðë¿þx¾GÅäZ#¥Â:k ®çË€µ¤NBÇ ‡C*• ¯¹ýÕ|í›îfjb–µuVVW¾Â˲<%ŠÂ4Æ÷2JÁ•F×Qôº[ÍîÖ꿪õŸÚ½wï/4[­ÿÎï{Ç¥õôKŽ£yž Î1]γu% X\Zæ¯ÿú¯‰£”©©)¬€(JØÚÚ$ŒcÂAˆÁ ¤Äu=<×Åw=ÜÀ£T©`¬ÁõK|í×ÿ#Þð5_Ç‘'sß}÷qüØqÂ8¡ÖRG`cÛÕF#Œ ×íP*W8qä(¿ð ¿À/ÿò/3== @’$Üwß}lll25=K§»ÉñÎ&p]I»=°‚¥ÅE8ðœgûÓ?ùS~çw—À÷é÷z¤i†ã8¸ž@)‰m-ŽçâC'Ë™žœà¿áͼî®70;;KJN­ƒòJTkuÂá/ð@TÒÅ÷\âhH”$Lº®çÒš˜¤\*Ñïu‚ãÇŽü»fsòþÃÿúçß±µ¹¶ø¥ñxY„¼çÇ/Ï.4øbÏž=g Ayž_µ±çñÃOðé¿û »÷îÁu]Ò$¡Óí†aÒëöØØ\Ã÷<ϧ\.#ÝB¸KÓ˜aw@šk×A¹û÷ÌrèÖ;ðJ‹GOsïý_ 7P¯–è‡äILÇÄqŒÉ2â4%Kæöì¥TªÒh–¹õÖÛØÚØbii‰$Ëp•G 8pèñ(ÆZMµZçäÉãx^€ã)^wçÜxãÌÎÎòÈ#ò‘|×uY_Y%IâñÒåâ%*•r¡²¾ç“ç9í‰6·Ýþªµ[[›œ8q‚Áf­,Bk¼ L½\Ƹ@^¨ŠqœBJéÙêÕ:žçâú%Õ:Õz…õÕUÖÖV7Æ7üÌOÿ³§.;â c-ò¼1|.7Ð*{æÈQ>÷ÙÏ1»{7RJ¢0$MSúý>Y–E![›[l®oP.WžDK§³ÁÊâ*Qá9NÉCá¢urVÀÛ½w·ÞùjJn…ù“¬¬,‘M%$IL–¦Å'ËH³Üöš;©TkdiZ‘R¢M±üÔª%Þð†»xð¡‡BpÃÁYÉV·DãzÖ€µ)Úh”U”+U¦¦Û¸åyjÈuŠÍ-Í© f&&h4© g“ç0;³‡$òä“O¯´'Ú_£”:mµE*Á{®E ¸ÖœùÍÍ-~’ýÐïõ‘B ó)•r‰~_ƒ(ñ|£ QgÈÊÒ¢(¥Þl0»{ŽR­+]<ÏE(ŽúÃ!ë«üÍÇÿ–ý{ösð¦ ØîÚ*Ö¬-´c‹@Ç}ùaîºë(ß'×1Ò²,ÃZҬȰµ€Ñ­3¢8&‰BÇÁs=pÁ÷}N?Æ™ùSH©€BkÙžEÖé84›$IÄ}÷?A8Ši4š:4r$Æ@šæàô%¼@áH¢+$~©f[–²`R Ò4e8‘¤)Æêµ*+‹ ?z3î´íàcÁZÈóbv7M†Ã!'ÃóK:tÉé ‚4ÍI’„8 ‰Ãib­Æ÷\ßgв±|†4‰QŽG”„H£A)]×-ÀgÃÁåºì¿ñÀ×Õëõ÷þÅÿ(ùѽ œ?±¯),|iy…áhD’¥H!Jåb§+ ‹W<!¥"MV[ÖWWA)„ã ­&M3’$%I"ò$-|ýƒš† ƒÑé8ÌíÛÉ-'ާT®Qm7ÈÒ˜,ϱƞЬՏ¾Çp0âþÏÏ)fm¿ßecyÏ °Â °S$I“„,˨”+,-.ðÄã‚H!R†&!B¢E9.µFƒ( ÙX_£ÑlÓnµ‰“”AHΪ„Âhlž‘¥1q…#Œ6 IšÑël¢œFâ$!×LN–¦x~ár–ŽÀhƒ5W©_°Æîú'o{‘C.­5Ë++X,ŽR”Ë\×A)I1£¢8!J#Â0Â"X^Z!Í4‰±cžýhR*„”`,ÖÛߘ\3†dQÊÄtéH–æS êTª ´.̮ۚLnÁKx¬¯wøÂ>‹çx”*%zý-º½-VH„‘#ˆñ½zƒÍõ5zàŒaÌòB(,[´µZ«‘ĽN‡Z½ŽïºŒ†FÃYš`L±¼è<k””îàñò¥ °ú#’þAÇäYN® I’`G9x®Sì$Å.¥œü‹ÿþÂ8Àp%jàùT„jeH!Ç‚O®maÇÏr@ Æ€h4Ú„Ã!›Ý.¹a4¹±XcÐZcŒA"°tš31MÈ35å Ã8ŠiLLàù«+xå€j­JnR2«±Ö¢Æ»éY¥rÀæÊ_º÷óÌLÏpË-·!‹ám±Œ,fs­Þ¤5Ùf«³ÉÃ>ˆBŽ1!‹<­-â„Tªu²4c4Òh4PJ1‰¢­s¬Ñ˜¼Xó³4"ÏSŒÎÇ@(TH(äk,q’²ÙÙÀw]‚r ÇõÈrMžפ:+–!W!‘!q=÷RHïyƒóBp©¾XÙV§‹ÇQ(©H’”,7¬ô®‡ãùx^ÇuÙÜÜ$Snqbò…Bk{Ö9T®Öö†,--°wß^W—°I‚ð¹Ï}šf¥ÊúÊ*gN*¬zŽó¬ci›;æ8¸žVã*I³ÕáhD–egå ­õYζ­©Ç ­Z2K·Û£R­žýíêê*á(D9¥r•Z£A«ÕbjjŠV»…TÈœ¥Bˆw¹n¸ôC², o)ëëœ>uš…3gØêlC’4%×ya©³8JÑé¬Óín"…DHÆzº@k˸Ÿ¢Pµ„RX!ÆvwYÈi–á`©TÊ̘VW±¾çøt6×p=¯ Z™%'%µ!¹lö:¼á _Ëw½í»Ð:åoþîSœ<~„å¥EŒ18Ê-äÀZ-p]—R¹„T’J¹D³ÕD` G!yž#ÆKÉ5Úh´6£ÇËk1¸X°<«º"ý^^·;H¡ÛíÐévB¡×õJµj•©éiöÝp€=ûörŒ…f³ù-ø•_ù†÷ýÜÏ}þºàR ØØØ Í5£pDgk‹§ž<̉ã'ˆãÇui6š´š-ò<#… z½-Ãb¢ðþ•+eü ($jm ˆ¢#¶¥n£±R"lÁ2ÏÍ(|!ŠJ«Î¬ï°8’(ÓøÃ‘ÇÇÃ!pd¡¯—K%¾õÛÞÂw|ï÷ððƒðþhÉ®]s¼ùÍßL½Qç¿~ø06ÃóK(á`MŽAR)ùT› ”4êMš­6ÆZ¢("Ï2ØüñÌׯ`uŽ6öY{v¯_@ZÈrMœÄ$ñ¶A⺞ Ö"¬F*†j¥Êþ½7rôÌQ¾ý»ßNn5ó§QŽâÔÒ<‡ÞÊí·ßL©Òæ‰G¥Ýšäó[Cšå<õäa^×׃•|ù¾/ÒéôÈóŒj½†ç—8pã!:å“hq4"ËÒ³ûük­Ñy^°~­ÑÖ`t!Äší6ÕÈ$Iè÷z„cÃS£Ñ`vbnÌæÛÔkuJå2®ç!„ Ï5q3èu{¬¯­Òën±¾¶Âw¾ŽV»õ=ÿô'ꃿõ¡ß|æŠF}[ÅÄþýûßðÙÏ~ö9¦àói½^'Ÿ>ÂC<ÀÉÇiµÛìÝ·Ù™\×=k”1céÞCžç¤YF†lu:,/-qúÔ)NÏϳ¾¾F’$~@»Ý¦Ñl"¥w–D(rÌþÎØýêœý¸¸®ƒïù”Ê%:ëllnòýÿË397Gš Y]íQ ¶Ö¶%Ï‚r}¢(ăïxx¾K§Û§Ýž Ë:ý>ÃN—7@HÁ£_þ2‹‹g˜˜šÁZK…$q|–µë¼˜ùyžƒ?^¶!D!ǤIÌæÖ&aQ©T˜Û5ÇÞ={Ùµkí‰ êµA©„ç{8ÊÅq¤RH)6š4I9~ü8>ø®ë°oï>îþÚ¯#ŒÂûÞwÿ迼"œCªÕjíú‘ù‘+•J!O9Êý_ü"ë8xZ­F­RAJI–e$IBÇ$iJš¦Äq\œ ‚®ëR¯×iµZÔj5¤’¤IÊ(Ñë÷ ÃÏópg,)o#ö쟢-Û1þ&Š- È5÷~ñ3TkUVÖX_^%ŽBúý>­V‹öD«õK¸®G¥VEg«+…Vèð \ÅS=ÆâÒS³³8R‘çY¡™ØgõøíÁ×y>ò õ-ÍÒBs:-––—AöíÝÇ­·ÞÊÍ7ßÌž½{i6›~‘BfŒAçE}Y–’gYQ·Ö`-žëR¯×ØêtØØØ`8Ðït8tÓͯÿ³?ÿóÏÿÃozóé€+Ž:vì8|ùzݯºùU Crcˆ“Âàc¬ESfLa]³Ö†Žqm«vÖh&''ñ}ŸJ¹ÂÉ“'Y__gÐEs3³4Íg…'ÅsÖO=VÏŠBjN2b/bbn({ôqÞüMßÄ|²8cD§h#°Jà+(=Ca»°†,ÍŒ†ìÙ»‡Îú:KË‹ÌíÙƒ‚$NÏ~¡¿´Î aWkŒ)Ø®5Y–Ž<šõÍÂшÉÉ)öïßϞݻiµÛø¾_L’8.?ž‡ãz…"XJPÔ84Ìw]õ:ÊQ¤i†–Ç~°tÛ¯ý¿ßùîóïýÎê]é¸^‘ ßïsôØ –Ï0;7Çp0¤Ûë¡%ÍòÂú†D)×çz>®çž³R‰R¥BµÖ R«ƒt£„,Ï™šœäÀ˜™™Æó<²,ãÌâ[[›€¬A=’³×1‹5…êhÆæã<.ôîöÄ$¾ëðàý_¤Y¯ˉgæO¡mRž¶è`G@‰Â!!Õ)S³Ót;Ž=s„½{ö¡‡,+4=^Þžý˜³­·¹ÁXçϲŒ…¥%F£³³³Üxàfggq=Á`ÀÚÚýÁm®àøŽçñnÑÞø»kDÚX¢4£Þhâ%â$&MRÊåó'¿öŽ;^ûÓW:øÏÀÅ@pìø Ž<ý$¾ïÅ []\¿D¥VÇóýbm–ÅŒ´ÛuŒ?g¡@¯ï319Éž}û˜ÛMPªP JLMM11ÑÆq\Œ6,.-ÑívÀÚ³ëêv'k°öÙÙV`Y‘P’&(éQm·É­àø‘§iÖê4ëmâ<çÈSÏ'ž‡«$¹±DaŒrFÃÔä 蜓ÇF åx IDATžanïn‚j™p¢”¬Æú½ÖgÙ¿5ú,ÈóÂ.’eKËKdiÊôÔ43Ó3”Ë¢0dee™µµ5´±ÔMªµ®ë²Ö¸¯ ðŸ#ôŽc) ™hjzš»Þx7µz“…¥å™5衤xÏ;ßõîÝW €óA†'ŽŸ ßïSªÔP®‡ëyTÊåB`ƒç4nûS< xö­XÛê@¥Zeÿ7rðæ[iµ'hÔÔjU¤’h“³¸¼HG…þl z$jÎvx¡b;ÃN2„…p4$OSZí ‚'{ ßq˜šäôÉ,œ>ÍÒâ—VXßX%K#<' ÞlÐïlqäɧ™ÛK” £Œ’Å}Æ ,’S îdÁ蜻Í´Ö¬­¯'Íf“æØTÜétY^Z¦×éÛ^DIvçN¼m9gÜÁÏžchÔëLNN’¤)Ï;R.+‹ »n¾ù–w\).k8uêK‹‹LÏî¢Z«Ñétp]— p\—,KÑYN’&¤Iò¼Pñ\×9kùJ’5–Þ­Ï QÆP«Õ˜™ÝE¿Û-¢|¢˜‘.| +++ܸ÷`Ç/OX-±b{ðÇ뱄,OQ®{Ö“¦ íÉIÖWWyæé§Øìlކ8páhˆµà8’Îf‡õu^uÓ­<óÌSìÞ³Ïóˆ“)$R@'Øñ[;À>늶c ®PȆ^¯Ç ? ^¯Q Œ1ôºÝ"œÌu)+5ÖŽRÒ$ÁV*Å;ƒ¬%Ë2²,+ d± ˆ±Z"¤+)•Ë”Ježë1qüa ûö·½ím¿þÑ~4½jlƒ`uuz³…äcÈu]úÝ.ÝÎáhH8’g9åJ™V»ÍÜÌ,s»wÓžœ V¯“ç)i–ÑÙìròÔIºÝ–¢„ ÏŠµ[ˆ"dºÝj‘e)Q’2ôéô»´[m¬ÕX[_Za b’có"$pƒ"‰DÊŸ¤ŒDÈÄÔ §OcL]<…lçAJ)I³”Å3‹dYÎÔô ž_b GÌØ $•ÄĆ4ÎÈLV°ei±ˆBÏü,Ëèlu¨”KTË””ÄQŒÖy!ÐYUŽÛ¾‚$!Ž"úÝ.y–"°TÊefff™œž Tª011A«ÝO²˜(Š9qò4ËK ôz=, ¡ÓépË-·&É«÷ìÙw'ðÀ5à™gް¸¼‚E¨W²²´Hgs“­uº.Ž’  o™ªXU,e6Çufçf8xð·Ý~o{ë[…!§Ï,ðØ£’¦EòGš$dyF–縎ËD{‚Õµ5²ý+ËË ”ãP.—A:¤qV¨3QJžgEçk@ <ßeyi•Ç}œý¿¦V)sëm·ñ¦7}-ßöíoá‹_¸‡gŽ-Ì¡YÑ1¹Î)y­f“µMFÈ0Q)W±’$£ÑnrðÐA‚J…R9ÀÕÇgey‰öíÈ“b–9žRZÅXƒg×T¥ªÕ:XA–§ u+M"V–9pÓAZÍBJ’4# CÖ×Ö˜?së¸Å2„TJeÊã4õs3®·ïY©T(—Kô{]ƒ>J9Å’*½!Ñò:I\¹Z#°F£ÅÑ#§øÂgï%(—hÖK4Z-î¾ëÜ~óÍœ8r„ÕeVÖVÙ»o/íö?yõkîx?ð¾+æçš~{ü0B*zÝ?ú0'Ž¥³ÕÁõ<šm’0eáÔ2Ý­I– É±f8qö±±<ᔫÌLOÒí¸ç Ÿ§51ɞݻX[]% ëØš[K½Z!Šcúƒ>ƒnV³EØО›eb×,GŸy†4Ë(—ÀÁñà–;^ÃúÊ:ëÌÍí.Øržá A©\FÚgµs*åÁ(:/b·7~ØØØä–×ÜÉúÒ§ŽCHI–©]‰6{÷ïåÄÑyš,NÈÈ©—ªX! {È9ƒ_.—™šžÆZËÊò®ëQ«5 CΜZfks“8‰ÑVŸ÷ŽÀ¢O-…D E%¨15;Áòâ BZÂQDxsEØÁñ'ÙØì°º²ÄC÷ÝÇéÓ§H³ŒV» Ž?}‚­M`lª «.㺠I¶øk-D£'Nöñ„ËÜ®]”ʇŸx‚( i·ÚT«UÂш| Dc¡Ùh2  ûáT”~èËìÙ{¯º}?Õj…fµAw8àéÃsèЭ,ŽN£±8žW§„Å÷ËdÉð¬ëuðÆ”rÇž:Pß÷Øêt˜›ÛÍÊâ2Âjî~Ó׊á¨ÏhÐçØ‘c v£J¯×§&xŽ;Vé oâv,A½^§ÕnÓëõÐZÓjµéu‡~øIúÃvœå#88h, Æ”O)[èmÖ0ŒzôOvðûîfbvŠÞú'£³µEgk“;_ÿFÇó¼_úÅÿó—¿éý¿ô¯/@zA;vœ•¥E>ÿ™¿ciaÇu™žžfkc‹3§Îf%Ta‰C9¶Hå¶p‘Ú qñðÎþ¯ÆÉ ¹µD‹1óK ì}Õê³-V×(û&&'ÙX_'KS”ïѪÖúô‡CâL3=5ÉÆf‡·ÿÐã*É}÷ÝÃT{†$N𼀃7ßÂæê&f›4Ž©”+äNŽT.¾§I¢±î~Î’gÆ–ËmµÖQ‰É Ö×›óßò­<ùØ…“+‘å»öîcáÌ..¾Pr‚Â;)PÄO¤:&Ô ±é³q¬OÖ×4÷7)ee66Öxð/†!wýƒ7}£ãºßü·+À©S§yú©§ùìß}’……3T+5š­‹ ¬-m`µÀsB÷¥äʪLEÕñm‰² hÕÚˆ „(Qœ¡,˜³¯Ë6ähÂgBԆǾÛnbaóYžÓn·élmá:.•Z…‰Éiz£ÖB¹Q§),O<üV(Õ~à!¥Gšd”ke¬²x¾O†Ôëu\·p¬èÌ!ËÇ&[ó¬çQkÛ.¶ -ÖZÊÕ qš211ÃÑ'åÇuü‹!ÏrÚí&Æ J¥y–Q*U¨5ªg­˜• ‚çø¬¯­195Í rì™'ÉMŽC‘é¬pðð©P“u*²JݯQ­Ô™´P«z#ˆ’”Ü´‰Æ!µÝÜŽGw¹Ïf¶€Ü'Ùµ{K K<öÈÃ(©xÍk_÷¿^1?ñ÷~ás,ÌÏSªThON°xæ ë+ëj,HY4ÂBÕ«Ó-*ºJÓmR-7p…W„EI ¾Â㤚ÔdäQV„zYC KT©oæ˜7¼ö&NtŸa8È©Vkh­)•+ÌÌH–— ÕH'`ªåá”=$‚À+!"JGHй)"}ÇY¥BбÝe0á: ¥ž -(üÛ¦ÇqqÆzº€"üÊ‘ÄiŒR@Œàe–\Å”A:h«h4êÔª5ò4Æd9B(6·6™™ec¥ÃñÇÆs^áãR¡FÃm3éMQsTü2Žã’ä1ÆäÈÀÙq”3c”p¨Tʄшr¥Â¡}·óåS È™êî£?±ÂÈÙ½o/gNäÑG¾L©RþG¿üþ|ó¿þÅ÷}òy8×ß¿¼¼ÂÇ?öQNž8ëzLÏ̲¼¸@w³‡ÉŠÎÐÖ`ÐÔ¼63bŠ©`ŽV¥M¥äY‚Å’“cȱŽÀ1†,ÎH×GT}°æ9q”«"SFÇšü—}¯=ȉõgBâù>XK½Ycb²NJ†"Ç/UQJá9^࣭ÅhÈÇ*eP®‘&1µJaU,¹îØ€¤©TªLLLÀ8`È(.Øu‘÷WÄŽŒÅª0;ÞYÎá¸ÊÕݬ,¯P <çÏP¯”˜˜hS:£ôº]&¦¦Y_Ùâĉã(žð¨‰ÓÞ3å9jNÄ:¢›°˜q„Ä·ŸiªiU<×'Nb<[ææ»îäø£“«a3sÓhÞÀGŸú3ößRbn×>Ϝ摇¢R©½ x>àY5ðž/ÜÃSOFkÍž½ûélmÒïc”ä&Ãw<Ö_Í­·ã»V–Æýbm³5lfP©D:.ÂaÚ1X’Œ~ÉG§Ï¹Ú¤#I£ˆàH™]7íåôòIjÀh8¢^›¦ÕšF›œÍ¥-^ýÆ}$a‚8h[ÌöÜfìÞ7Ç0Œˆ¢¡®ç¢(f|’ĤYÆ®Ùi:Äää$J)ƒËËËtº=â(BkM Œ4¸®W¸F#Ñ[c±B”«LδY__'é©TK”k5ò,g' jµ£~tvðË”™`š9GC6‘8lÖÉ¥¦\*SuJ2À>Öj„«°Vàïò!t·Ö©zÞðæodþÄ t}ÍÝÎòÒ‡n¾™ÞÒípŽ…åÓÜzÓí4ZM¶66xòðcßõ?ñ“·üöoèéç`{Ë–þÕ_2ôiµ'‘®¢ÛÙ" s2“#„d²4ÇëgÞÈ.o7›v“0ÞdbªE4Ì o ¼2nÅE–Š—J!HtŽ‹ƒÀÅ/•(W3ÐÏ/au†Î ½ßäÊàYŸ`à³Uß$ QJg“”*%Âш^¸Áêâ"»öì&Éuý‹À•Šõµ ¬Ïu„{Ѱ †Ctž1=5ÍÁƒÙ³gŽãÐï÷q]—3 ÌŸY"‡x )ð|­s”r0FŸéÐÙZ+8ç©?(x>«[ãh%qŸgž8Œ‹Ë„;É>ÿ“Þ Â‘¤6×Ò(µ)«ò1¢°*O@U¡mŠÌq<"îÅ4÷LsèUY_Þ`qiž©=mD&i”šìÕ>~ÿ£ì77q8Þ`yyÝ{öÑïwYXX(Uªµþõ¹8ûD÷ÝwÇGJYlǶ²‚ÕE’‚Àp{ëÕ¼õÖïÀ3%VÃ5\íÓÒ“4œ æ¦ç˜š›Á«JLž#,¹WGÖ:2Ö UÄpX[¨IJTJ´ç&©×[„iÈðèˆI5…†0Œét»Ô«ÕbYpKœ8~Œ…ùy)p2R¹Hé` ÄaBn nàJ%ˆã„~¿O¥\¦Þ¨Ól6‹àv{¼Acf£ÖÅ1y^ ¶£®ç’gÏšÔ…ûå‡8Œ8öô3ÄQ„øTªe´6 ú=ò$¡R­ræôÆ€1)¹™©x£$%¯LU” Êe’4d”Å”UPÄ×—}ò̀΋øÇâyÊQHœ"?..6a0ÂA¥J0ìtûEc •z•°;b0èQ«VŠq©p\Ãââ›[]ZÍ6~É+B¤)T8Çõ‘Já: £5½AŸ^g‹ö‚€J¥‚;Þ—h;ÚXJ‰ï¹ Æ@)¼’Åò!eN†E†/EÐKö¤I‚xØ4%(WtûŒF!Žç†1ÃÍ!³Þ–o¦¬* uanæ¡ÓœÈI0f„_-|ÿR:¸BãUÊx¤ì´Ø½¯Bm¶$[ý£AÈt»SõØ<½Æ«_'‡^÷*þÛ‡>Œ°°ç–i¶ÎÜÀFz†õµ¦§fØÜÜ`ØïØ»gïëO?Y–qòÄ ,P«Õèv:…%*“ävÚL°5±¯ïpËÁ9}ü$a6$¨¨ÌG۔ˋ‹xž{vÊq<ý³³zìTJŽÃÇ|ßÃQj åhÒ8&Iâ" &K —.Û>|:£ÚäT‚2Ý•m1Í>ïJ*bQu딃 ®r®Yy¼RRÅÑ¢ˆ‰ð]颜Š˜d`âb×´É]Ó¡¬ ¸áöºóU}üIî_yœïü†·qð®ÌÿåºVÁhM*2\Q¢Ü PžG–fdiFýÆ&“{¦ÈòŒþÕ_òîïý!n{ÃÍ|îS÷‚µ8& KbÂ(Âó]¢0§»µyÓó°±±!¢(G½¤ãG_ö¹ë–×sæéy’aÌÈ„Üó·ñ½?òÍ”Ê%Nž'"Oâ8ÒÕX%¶èXÏ °Æà¸.ynH¢ñ(,<~G °¢pqŽRªs7ìbmi… 0Óœc¥s†”ÂÙÔš¨ŒmöEª¶rR¨"=Í)%â$f8 ôz„°¸NÈàœM¶AàŒZÛË‚±“å,/-0è÷i4¸®ƒ@ Ô˜³hl1€žë¢­Eëœláx"QTâA3Àó\ü¼„+\Œ3Ÿ G‘ˆ†Ê òœRP¯HŒÐ¸eÇ-ÒÃ=¿‚”P4)åJ@µ]Çû'üÄo¾—î©>ù{#ðJ´šMÖ“5ÂQtàJ¨=ÏÀúºHÒÏu‹”-#r…Ìêõ¿ö ýÕ+‡çYLWøø}Šoyç[¹õë_éÇN“ô"² ¢¸R‚#V"Õ¸“¥Â(ã9Ayœû—’§YªñŸé¹ij V–q=ÉþðÔÉ'ñŸ$IˆÂˆz³ˆG¹qR…8ªpælh –.eÁîK¥ív›f³‰7Ž·ß@µZ¥ÕjQ­Vé÷ûã0¯œÎÖ:[›㬠 ®£Æéácƒ‘äV“ëœ4IIã¸p‹+E)-ÛŒaoÄÜDƒz£>6R׺¾‡ë98~±¨ãú”}¡Üÿ¿½3û‘äºÒûïÆ¹UVeeUVWõZ]½‘m.M™›Ä1@É’=ÀÀÖ‹ÿÿ~ò› Û`Â3ž±EʔȑÄfSbïÕ[m]]Y¹gFdìqýYÕÕ­¦HÎHÂðÈ ™÷|÷ÞsÏýÎwQtÝÈAk芑B¤ÈƒÐ‚eSi”ÃŒOþú#Œj—_:ÉÃÿ¹Iâû”f"LÅF 5’Ðç€_$„|æ°aM‘¯›ÉóG)¥!Ýö­$)W-Žÿ‹w¸ùÉmn´>åÏÿßógÿ懜ÿgçéoôiï¶Iƒ” LÐR ]‡4Ë-•0º¥¡ `«JYÃ*X*Ò8f{úÃ×™Œ|Ö¯¯C”χ³‚%eÉ´B7߇ÈäAEÑÓ4nîxȇ÷R©ÄÒÒ+++ÌÎÎbÆá ªêáç­V‹(Šèõz„ax˜‰¢ßŸüNÌpÀh: ½¥ÓÚF™Aɬ03o „*Á0DW&TæfÐdºã˜¥¦š*P„$‘šHóJé$!&)j¦cèÝ)P®Ù”«eöŸ<áóÿó9Š©pr©—Füçÿ_X9±ÌÒé>ÿì*™È+Š£$=¼îùðÿí/þ;¯œy…7þù+géµ\F}—h4&Jd*“E×òúú4W›©•±J¦¡’$½ý.Ýv‡r©È;?x“›ßæîgwòÝ:%ߤQ5-—ù2ý"!¦©[åp®·m›r¹ÌÂÂgÏžåôéÓ‡¥ÜL¯( Åb‘••â8Æ4M¶··év»L&“Cz–”SÊû‘ꥣ€èuÂ)S(fgg)ZEd"™Œ'¾O©R¤\« N™Mi–’†)Bh dU@#‹ŠB3qÊʵ"ÅŠƒï†\ûÅç<¹¿A±V¡Xµ™„!{›» ‡Ô:‹ KŒ"éä…¶i2U\Í÷=žŸÌ`ÛRQ5˜:Hòy*+fdQŠ-*¸ñ˜ÝÇOpûcN]\æýõ=ÝxÄÃû÷¸û×¹üÒˬ½r–Ó—ŽãG¼÷/¿‹ÛðÑßþÛqДͶ©$öC†ãíV‡q¯Gœ%8eEW¸ö“/B¡*Ä"ưMÔq¾1ªiÚ!Múy¨jΫ7M3¯7pªÕ*õzÅÅE–––¨×ëØ¶ýLBršØÜÜÜa™Öââ"{{{ôz=\×%:Rèr@âY1Én𨅳³³4 ªÕ*šöì>–ªªØ¶M©Tž. +• Õjõð=Ó4Çù2M“ÙÙYÇa~~žÁ`À`0Àó¼\íÄ÷q]÷pj8°|Šˆè÷û¹Æ~]3–Ì•KR‰Lˆ”Ã2üq€ï=FWMlÇÀ.—(8fÁÎ7¦T,‹)}Qäáo°½³KìGhªBm©†®©$Bâ]Ú;û$™Ä.˜$‘ÏxÌÎÆ&žía¦SíE`Ù6a€d_Ó4=IòaAKÓT ‚€úBƒÉÃG9A"MI³„¢bÒVžðèñ&ó&E» Re‚@B”EégY&µ$IÌýý}¡ëºaL‰ “‰‡çO¨ÏÌñÈÙàa÷&‹î œ‚‰áØ”›z}E×Hº›Ý=ŠóCll¬‚NTÌc 7LÈÂÐëv‰],JIdŒ¢hy嫚ÓÉ1Ûwwè¤ûÈ¥ I‚®ëè¦A±X¤\.S.—{ù‹ª˜Ž:þËì먠<ÿ;ëèʲrµC×±ld–ó÷f½.b¤ä·Ó’ 2$!ŠÈE „»ì „ƒšPPUBäþHÃ)cœRÝ2ðG"™¢¤ž;¦—<¢WÝg©ºŒ…LbÃÒ™©Í0É÷Cö€Y H¾”jY–£ÑH$IJ¡è k³sþö˜qÜ¥Ui6–Ù îv}šò¥b! 44´šÅÜbÓ”ÄdØž°ùùc¢4¤Ów‰—`䓸)aêáOB ÝD3òÌWÞ&9“˜L0̆ ëm«Œaø#Ë´{dž/W¾–ÿ¡ xÞ^ùL–eØo4FÑR‡ æ3z2Âòl¤òT%€ dê“dºÐˆÃ”Ø‹0l§lãcŠ% ´œ¡,²$Ës!™vξîwºì†[¸¥…ELÕdoø˜0öbmÓ: tIDATY>v‚BÁ¡ÝîŒûƒÁ¨…CÜD–å‡eiJ¥:CÍ›coo¢Ù¥^®³¼|‚Gñ6½u¬°Z»D¥TËwcÓ”Dê˜%ƒùzÌ÷QHe0ÃÄÏ ”Ýöeá$WÕHLR„ªæÕ.±NªÇøË]R¬Ú˜¶AÜQó\òá\þuø¼Óþ xÑ竃C/|-ÏRªŽ@hàÍ÷a7Cót¤:å_ˆtº… ‚ÌPlUS1m›JµˆY)aL,ÇÂÐM„ª 3I†¨š†¥ÚŒä€íöÉFÅ}êK TìY“m¿M±\fùØ1<ÏcwïÉF–e™BùPš¢(‰mÛR×utC' óuìÉS§»cöÆ;˜†FѬ°zæíÎ>›î:ÁcŒÂÉÚóõ*± I£€ØÒqã ©¤ˆ\PÍHƒ0 s @Dyb(5<ä©ÏR©Î0¬N·ß'ÉRlÓ8ìýÏoä|S9û?ÒÉ…B!:§ÕÄÕjäÓÝí#–ænÕ5P è@^óŸÉüÈ™ü”-U Ë´1mÛ( ëJî·XÁtyÔÝàúÆì 6ÕˆÕÅóئA2¦=ÞEÊŒ‹/]²lÖïÝoµö÷÷ ˜!Ó±WSU5¨Õj²T*ÑëõŠ ôªÕ^zé2Ÿþê—tÜ6ºeS6Êœ?w‘^¿K¯Ûç~ÎÃÁçN¬qîÔ%*35b£Ší…Ø¥“LƒT€'ñõG„ÄJ!g P„øˆÙí¸À H3X½|UÓ¦âIâPXâ€àù¼SþØ €ß?’hšFyZ¨é8žçFyFuñÔ£ž‹LÐN«$í€lOAË LL]QP4]XhŠŽn; –ãàØ„¦ J/ñØÚÛàν߲ÕÚ$6C–Îש/,"A‡~Ðaèxãõ7¨/,ðèÞ}ÿÎúÝû@*„˜`<šªªq½^—FƒN§C’$„IÌh0àØò2o¼õ6Ÿ}úkzn³n E'Žçø‰Ótú-ºû]~vó®=¼Êl©ÎßÿíÞ€(òÑ#±?ÁK&dAÄ(vé„-\HRÌŠIñ¤ƒjKúí7äOþô»Ì4ªÜ¹s— 1 ƒÙÙYšÍ&sssX–õBgü1AðUŸ«ªJµZ¥ÙlÒh4FxžÇh<âØ±eο~Žë÷ÃшÊb µþî˜A·M’)X™MÝW±‹6qfFn¨ô=žì‡œ:w†opõú¯ˆâµ(X~y‘Fc]Xt:mÅc è:¼öÊë¬?ÏæövüëÏ>½éûþD-`g 9¯­®®ZRJ\×ess“Éd‚ëOhwÚœ>uŠ‚eóË_ý’ýÞ.Ç›'û.³åçΜƒ30ôFìíµé;ô’}>ºñÝN‹’áàG‚QD,”TçfŽÍ¢Ù*¡—ðdk‡(ùÁßgayž›7ócf'/Œ¼pá—/_æäÉ“ÔjµgÔ¾*ØûÇ0)ó,åÙ³g%ò·¶¶|Ÿn·Ã±cÇxí½×¹öóÏî™[lP¹\BÆ·ï1|2â±ûÇ­M̾…Þ²Ñ Iª*d2â½ê» ’6Õ•Çšç©×kd‰`8ìÑtˆ”€ÝîZÞ|ëmÖΟcsc3ùÅÇ¿¸Ùëõ{Bˆx¬/›òâE³Ù<óãÿøßŽF£æÖÖÖÜþþ~ÅuÝBǪ®ëú•+oT/ž¿ ‡>þùGÄQÌòÒIjÕ9«HÑ)Sž©b:IE)ãñ˜‰;&ö#¤H‰£ C·@¦Äj^(z1ýN‡‡›T~ø¯Dy¶Âµ«×’öÓ~šf‘eYa­V7›Í^³ÙU«Õ@Ó´ìáô¯êíßÔ²,žçé­V«¸³³3Ón·«®ëÚ€ñê+¯U/]ºhFa̵Ÿ_eo«E£¹ÈìL «l£ ÕÊÅ1D*QLËr(:6s9²4EWò:Íá Ïpâ$^“í<EòÖ[ߥٜçÎí»Á_ýÍ__o·;©ó·€Ï{@?˲@ÌÍÍ9£ÑÈJÓ´!¥<.¥\N‹RÊ¢mÛåwÞ~gõíwßY(X6ëwîpçöm*Í…&33³mÛ, „ÊÙSgèuûøQH…¤B’x®ë“f1®çåÙÂÂÌãÍï½Å›ï½MG|ø¿~ÚûË¿úË“Éd „èÀ]à‘”²Ë‘àå[jPB,gÓRÊ]×Ëï¾óîùwÞ}g¥è8¬ßZç7¿úÁÂâ"ÕÙ§‚&4ìb˶0 U×IÒ˜…ÅEZû{øA.gïcÚÝ6{»;¤$¬ž=Ç¥—.')òñþ‡þì¦ç¹#!„G>äß%À# ć#€išªªªŠ®ëz†¥$IêRÊe)åq`9˲y |þܹ“ïÿû.\¸äþ„{ëw¹¿~Ÿp`ZõZƒ—_¾„aZ<ÚØA@’MOÃõ†<Ùߣ?ì *¯^y•wÿä»ÌÌT¹~ãzü“Ÿü›W?ýôn–e=!D‹Üù„ÛBˆ¢(‘â+HøûôÞ?¤I)µ,ËJ@CJy8%¥l•skçV¿ÿþ^;»¶ZL²„Û¿½ÅßÜÀ{8‡úÜ<³3³ØÎòº Eæ<†™*·oßäÑÖ}FcË68»¶ÆêÚ…¢Íú­uÿo~ú·7oݼõPJé !ä=ÿðØ%ŸûG”H¤”RÉÅ0€yƨ ,K)çjÁ¶ë¯_¹rñ{ß{ïâêêjYÓ4žìîòx{›4Ž™_ÈkôÜ@§Ý%Kr•Ae¶ÂÊÉ“œY=Ùճh¦ÆúÝ;Ñÿûƒ»|øÁÕÁ`° „{À6ùœÕ\ò•â×òìÑeâÑŒÞ3Ò57ÿÜrRN…UÀŽ”ÍY*øË.°€*КÓ6œulgéÊw®¼úÖ›o½tæôjUÑöžìòxû1{wéôúÄA€ªjÈLR(ZœZ]åÂ…óì·ö»#›,4I³”õõ{ÃO>þxýêÕ«w&“I è !:ÀÞ´ [ä½Þ?öšx¾Ç(¹*¡˜€TȳG5)e(l{þâÅKÞøÎw.]ºtéôR³Y4L3§T¥9k'“9ƒÖÔ œ’ƒ¢j¤IJ«ÕŠnݺ±óÉÇ÷ÅgŸýúZ·ÛßFBˆ!¹ÃûÀð€˜éråk·ü·w,Pf¤”³ÀL¡Ph\¼pá¥W^}íåµµsg–š eMÏÏO–2# "‚å”0MãP},“Rîµöׯßxð›k×Öoß¹}/Š¢.0žN›i;§mIö%ÿ;8°#@ÐÈG °‚”²XBˆR±X¬®­­­Ì×çÏ,¯,[^^™+ †Bæ%Þû{­îÝõõA¿¿yûÎ퇭V«%¥ìÁty2ái‚"&ïñßø<øVàÀrjRÞŽ&y¥”6`)ŠR6MkfmmíX£1¿R­V—šÍæ¬eÙV©T*t»]7Nâtsc³;vÇ[­½½Íì†aèI)Cò6ôÈíñ´ =:ܿȾÏÜÁS0äŬSPH)Õ£_Šªª¦SI^YÇy¯N§ßC‘;;>2žóï‰ü[€£v´ U@—RêÓ÷²éÃB”„¦¦iZEÁç©cùŧÓ×G;M:½Þ¯Õ†_ ÏÜA†£7tô¹"sU„ç-›pG|ôÿ`‘Û·‡ýÜógÚTJ©yOrz­‡>¸lŽ´Ý×uúQûƇG?÷') +¤ó…öm^¾ýcÛïú{ñ…møæ7þ¿ý¿eÿ›Uäoƒ ÉIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/000077500000000000000000000000001217176075400226135ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/blockdevice.png000066400000000000000000000151311217176075400255740ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ IDATxœå›k¬%Ùu×kíª:çÜG÷íÛyö<<“ØØ™˜ÄÄ Á1N"‚HÈ)Ž0(F‚€"à !R">$唄 ËÄ&J…<>xlgðdÆž—ÇžWO{¦Ÿ·û¾Î=çTÕÞëχ:÷NÏÃq{f’±¥RÕÙªSµ×½×ÚeßñŸ¯ðvŒÓ§N°1N¬5ÆJ_Þ5VjX¯a½‚¦°’`¥‚>@ÀjƒL{h Œ´]»Öa¯ƒ½r@p×ô0ͰØÝ}ÓëýÄÀßêÿ ÿï¨þ”ÞkÀiàà,° < \’ ù“àè»6Ç|ÃJâ«5ï8Þpª-Ìö{¾2íyf§åKÀóÀ ýã^Ô'Ç€;ûw=°É}«·*NTF €P“Œuâìæ˜ܹFîƒÙ,syÚóð ðeàpÈoç"ß. ¸ ø†åqßûNëì¤âdíLL ‰A´ÐaX`Vº€ Ùð°f­æîc5÷Þ¶Â÷Ñ·…YæÒ~oÏ3òƒÚLßÊ« ½EÚø¦ï<Ùý«õQZY„û¤2 ¢„¬ôt=˜$—™Ù`x É"Y—ó6€‘œhœ2J¶²îÜwÜã·s÷}ýþ‚‹×¦¿üë7·äÁ Vc{[Xß>èÆ_Þ²nnͨòc#ó“£dM°jÙŒl9ÌaÖ‡™À"Ìz99Y“&µ´Zã•Y´Ô~iîñÂNæüîB[»‹®]ta¥«(yã­.¼Zôåí@÷ ¸[msØå’ìÂÜÌÒÈGÕ(¯Ã7S±uï}Bka9lT%Ú.8^‹㤞ZÛ1ò§÷šxîÀì¥ÅÞ´M,ÚR«WŠLM˜# E¼e"ÞP„%37GÉÂëd†÷d K¾/Oû­cV{ã+>1Ù1kíoÞgdøÍ—j>{Íu¥C×{ÔÌ êœ9Ue|"JjAHኰ·ºî ½e‡a¸¹Â„á2s‹â)‘\ÉRÂ+ÓcMm驱>þöžMø—V'ÊF‚œ°ˆ ”À" VФ¢ (¦RÞ:Š·Å S˜aîf΂EfîrK¶šð­9éÜÜ·‚ÿï}T;šTH­n9ðÈD)Âᮥò6IÀ¿ý™o}Ýä?úŸûº$ÉA¡1ÌÌ"dfʼnäžÌFÕµžÜÆš„*lëRT‹ÀE>"8ò¦\ÂxÔ÷ s}êŸóŸ~úÏCÄͦP*ŠÁÌG¸7z[1ùNm‘o 7'%#Éð"…pEv•b*áRIRØð»ØÑõò½oæ8d ô_ñ»ùÈ?ûÝ›BR Sºúb2³°d¾Ô‹OvÐGzìš™UnãD•3ÂB ~?‹ˆÀÉyõ(¦¼<Ç!Ñ…x“6àöþðòêrÄ û¹” Ê!årè nfù¼÷§þ ýÌ]¹À'ñCüÀO¿±JH! ½aV©¤ºJ£R4ùÂV?‘¥ñ±QªÝ#%e 5,ÅŸž wE y4˜Ïh¥˜K‘£ä%w¹tÅãX«|m6òx`åý|µÚÑ× ýæ¯þí'þÇÐ&÷³‰'ÖVGi’£/\É.aÇ›„1€ÉL%LrÁ@P0•’)’YÔu­µ+”rg>w¥ƒœs+ɉ?Ú‡ßñ“aþ5èySÙàoÿ—ðWü¿ß8µÒT~vÈ?ûÐbQ2)ÞÔås—¶;“­O’·%H)¦ U n†Õ5c¯˜tPÀ ’•åžÒ·t]&+èÚBôJVôY*YŠB”W«À™¿õ£¼ûØûnŠó‡ã­Ekà®øù?0îæœ<¸–^þâùj~uÇW¬5•¢§¯kå•uX; k0šP¢[0u”Ùï(£5´¶I T#º® Å[ÌPÛBW7©€(GÇÙ{½‹»™ñõH€3Ôôîf¨ú¼³ÿÞ¿ro½2>ýí+û·>±ØçÊÎÌÓö4½k}‚º b´¡R7Ñ5½]d•¶GÅl(eJ_¡¾g6ƒ*µƒtX¢WTã3L66é3ºmºÝSEßá)ˆeqì›?úOÙ}“9ÝÀq†šÞ}À»ê}è¾±q“ÉF4M IAîú]¯ãóí:ãÕã¶¹áØ¨Q•€Væûi4Ý!KôVÓ§*zK̨Y¬9èD×e’‹CǦ…–*H+Ô'×Uº+&}kÝþ5ë·.0ßÞŠ¿ü÷~ž7rðo€?´öáßjãñIÕõ¤”â%gQJAÎ`†ì¸fÁÁN<±;çŽS›ä*±Ö¼ËxßK6´Â@FOíf.8fk;#­oÏ™úšúÑ*¦á.BËJÌMÞC‘±èÃæûû´Ómêþ"§Onéo›—{ÞYòÙ»Ose±?êça%wsYJµ5õ ?}ûÉtËTúKÙs×Ù|–ö¯LÙ=ÇPE~xšš/U{ð:§a#d>™˜ÆcËëëÖIÉsNã­-?ý•¯¤3ÎhìºuÝ;nm^Z?Y½ü ï·éw|К'>£œ½Èß~ù?†žzœíK­>yËwÙ'ïû¾pö=~pfSk;³ëT+ ï¿}gŸºF.`Ûy^ÈýMs‘{N_‰³ìéγ]¬l–(–¬ïj»~µ²Ý¹S§âãQ)AªM²…‰\Y#Ÿ”[¯éø]“výn›W<¿ÿ¼mí^ùUà7(öºŒÒ æn– Èͪ Þ¦ä4MÒêjj$¯‹Üöi£ýbÞX³ô®í§°þVKÏ>¿òo`whlvè£O|">ú»ŸäüÉÛãwßýÿí»¿“gÿâ·ÙG>ð^Þ]{ð÷8µ9crËyNÜþe½÷ÔXïH£2ÑX³®±ƒiËÞ´õ¶n ëluÜQÚ Õò4_©VíXZoŽi\ÕÞW™-»¨gO¦¾X.L/iÚ¶2j #+¯R7H'¬€ùpvgHT,Û²ÔîNJv¬âÔmÆþÅ*ÿÎHÿíß+?ø[ž÷ˆ˜ÃÛ†äÎôxm][m§|øÁOèÇ?õ‰ø¹••ôø7ÿ {úå¿ÀwÓ#ŒØ"Þ¥ò{©ô:WjÍ7lóà´ÖöNÚÚþ ÆÓu©Ç6ŽC{™3õI6Öê«£«Õcõ§âÙòXœ›]´ëm¡Ì)uÁš@µð±ʯn„|-ÌÁ X5ÜëK0RNžlí¸ùÖÕŠG¿TqÆ(—¯çveõȼ­°©kOÎ~2“ ‹´FL›W….°}ý×9µÿk|ãFË•æ[´}í~‹vŒ¼ÃëÌ´™²»y•¸££ ¨rc÷/Þ«¿³ö öûí¯óqÿeaòdµ=¤^÷”¦'62T‰aB€¤Œ«àd^%òÕ5Úb^+`iyîHî^åõuK{ûÉÿð &#y=U¦øÂäYìvP‡Z:D‹‘ÝÙµótùI‚ÂþbÎ|“ Ÿq^ÁÛÆlJcG+ÿ«þvêØ1{|÷Q>³û„mfÕ›)µ„‹7‹Óʈ©G2¦×ðׯ ;D>qæÌÑdYm7HC@¡¸S­¯³Yê~¨Jà&RÕ‹˜;ÚŸû•82ÙÄBR§ð,£Ãè2Š’ˆe.¬p³Rˆ>Â+a³‚€Æk[ëVùüâA’ô|<­Gw´3_I¸÷$¦<,~I’É þÕÄ߀1p_K CYvrûd–ª¦Q1³ý´Fjš0«¼“Ô”d9Œð¬s¢sȆ2X¢—”Uh±h£¥XÉŠL9‚®"»*¨SâXµ®öŸ´/µ_fmâx*ŠPAåP¬QÆ8¡ny=€£¥d„zœx=‡:aå)JDIRJ+'Vדég?;NRªRòlfÉLY’åLªšh#1‹ÖŒÎ¼Å¬—èÊarr)…JED.RÁÕ…Ùîü©mYuWI)‰"Y/a`­›·²˜Å­L]„:7ez™z…E˜:¨ÈrJ2•â £”¢œUFB«ÍŠ¿¼ó¼žš>ê+“Šº¯À <ª,£X)à=„3RKOF‘‘z CU­X&ƒ84d‹ÙWÀ¥”NYU/9—¨G£Ql?ü°•½=VêÚŠäýàH ´\GÊl*P\Ê2@RKVoUtXŒˆ(%*ËBEAVò,U…2®&ve÷%ßýCMjêHnEF¿ì â2x@UÒ*áP,¢Ï¢•bEŠž^YAïƒ'@‹6ÿåP-m^’÷‹EnÜ{C\ÿô§-¦S_]zŒÞ]…e|¡¡¨;F:½Z°K±`[#ö«‹0KIYRßåˆP8QJkŠ"Ë—cÕVýúÞytë!kêR›ºˆ¢b¦bÃî¢l £¦q%ÏŽ«ª“y ¶¦Ê²ˆ¾ç%kmÌJ„=ŸªÊZõ`ÌQDxÔ5W}”<2ffêr¶8ÁFJ¬c3 håÔW¯ÚÝ { fêt¹ou.,^¬»ê-ÜH–X#G[* zä¸9+¾nWw^Öc?C3ªJS³¾7s™¥"“äÑ™‘ ï F&,#•B.U!YIáá$UÖøhE•MвÚhͬ[_€8ä|³qWas3ö‚MËc錌¡§iˆ"æ ¡äO áƒØaˆxÇ"î*âVk¨v.ÙsÏ=…Ý‚Ò:aæ+fŒ_CLŠQÖg`á0…}Ù JI˜†ný2îÇûÁ 3ôV‚L*œÉ’v½¶&è§R:÷pJï|®ëÖNFÔ·ÇA•Y)ËΡÛÄ /ƒ)4†m_óå=iÙóÂPð!©Jס¾ãêüW¶õÌcO¹­͆GuÂ’­@¬7‹"‹:Èr+3+{ É?ìà ܢfxY0ø~õƒª˜§ÂßhbÉMéþÑ虳ÇkºX?×¶wž[,îZ”rlUªOH¬™Q› [˜JÑ¡xßSr¯Ù€ê!Áa Øô¤sFÌÅâÑØŸ¿¯|ÓñIWŒŒx‰m(3Áaúî!¬˜‘«¢¼ )qÆ-‰ˆ£°nñŒÌƘµ˜öA…šš‘€¾$›n‰ˆZè‹ÙÁmu½O]_`2ylÚ÷'_êºÛ_îû³—KÙ@Jµd£eÆLÑýÐôeêK ËÌO9—¾žûÆŠg¯VíûžžÛûklìA(©„© ã°d±¤E6H4¡¥>Ãó,--ïò¾¥jÞ솓©˜‚æHë&Thˆ} 9” {½ÙÎR+5 h=¥ ß´ºzñˆ'úˆõ«{{·],åŽ8=ƒ:O&Õíþ1Í/^(ç_xÁ @i`÷NøÊ·/ÞἜ*¦{‰râ=6zäútu÷â僳×ÔßUF3¡©&2*+2Dv µ ‘ƒH•yžXa´$‘ÁÚHÃæ*ÀÜzPO‘³¯UÎqçñÍ ‚r HÙ}¯«ªí‘BªÃ¬ ³¦‚º®ª>íìÌo/åÊðDµØœŸ9sÇøÔÉÛüü#M†ýàÜýpî$\IƬ‡¼gØ–»NÙ-‹³›ãG6O×\«ÊúÅèoÙ;XÜ×ôïˆÐºAíf,£ä£6úÌ"ZŸSŠÀ\@A•û’‰¬;Ú༎ñ<«¼Dž¡3ŽjEƒ ÈÜ`Õ;³Ý.¥qªk'¢¢”†”ª€¦ßÞ®¼mëê R ûÇáå_ü|üÒ/¾oe¥vØO0Ï-peaä䔹Ž*íVŒæà¥f{rl´¥»ë's”µnšïÈ{ýýå ¿Wó²a…:Z˜í¢»ÎlÆ)»§.¼Èd‚Û³`•lcvÊ ç4á¼Æ\˜!Š †l|ÐÒnÉø\ñJ $kÝg‹”v]2™%¥TTýÖVí³Yj–±ƒ ŠÁy ò”ÔL&¹Í´T©ôÐÏ!·gFÌ 3C³d£¶²&c©w¯#DdKŽ—Ñúxjé™y×Nè8ã îÕ”w|óè§ò;ªùÔã¿ï~ú³jneÁ[e̹hx)*®­APlˆÑzÄ eØÀ3eø!åÐ ªûlQU•/wx¤îÊ•äûû©y%f¨—ÂæžZÛ9¥X=äJ e¹ bá¨êõf£°T‡á˜U˜¼B&|Ôª¯§³½Z¦ÎjöcÌóå8Ÿz‘ó'ùùŸ»§Œòæè[Øê*^–±gƒîË{ô6p¸:=:º.ˆ)CަC 8" 7[,Ròİ£»t)±³ããWN@Ò+äQVe))/¹¼ˆ,ÊÌÐ bÄLÃWa}X[<%Iެrd)¹ujë½n· E“ŒJAƒH•QòþùîÒ¹•z F²Be±ô‚¢7;óÎXr¤Gä!Hf¶œC 8À–t»5)Ywá±µå“Áû¸–!¸`h8³¬Ë»Žõ!;ŒzÈt1Ú¸]…a½,I)¹dNXr·6zß]\O¢¤äT•P *‡jdnÕUÖâ0 †êUY›—–åu^r>{A&æKñËHðø` 0—ªbÿº˗i–A^=ôX_~³lšiLCI΀ h±ÚÚÊèR‚=amF}6¹KÉœd”ÌÎô*Y9y…#vCª.* 7#ùPŽ¶Ù ávÁ(víD‡-¹n"(„ Áy;,{ ùµ¡°ŠY·}éR©.\à$ØI†kK¢ ,~Ý1 3Ì%G*%Ðt¸¥À=‚ /ì wÌÝú®µ«í%ºQ‡W˜ Ž0IŽÉñ% ðP±£ØuˆáPd×òz x8Z6©+ƒGõ€WÙ€¸~½Ü–sÜ6pqÈÌæb)îvßìˆ|äfGs’C‡{xvÁÝ·u°[ÜÚ¾åúìí¸²!´1 $›%L6"ad<—‚Êö2[>^KXŽ !Ó2 ¸&9Z6týgu¤Gcžs¹ l,‰íΓ÷Æòž“‡’3WsÖžÙ Lze/à¡òõŨúÄËÛ—Ù£e± r#»!Áè–™çè-–é‡uÝÈ–Á-Ë`:ޤãð>^Y×vøñF;D¾ÞÞ–^û¼¾DôUmœ%8EÅ–\? à†ÿéU÷Rù×^ÛŸÖ—£73¾êâí†èfÿóÕÆŸo‡ofcü›ø~äÿe x£ñv«ÿ¯ïíž$õIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/chardevice.png000066400000000000000000000105051217176075400254170ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ IDATxœí›]ŒeYUÇkí}νÕÕÝ4ƒÎˆò ‡ $J üL F!$L _ÑõQŸÔh AŸø|ÅŒ $Á'¢Ä ŽÀÍôÀ=ô0=Õ=Ý=ýY]U÷ž½Öòaï{ëÖ­[ý5˜Žavrrö9§î9ûÿ_{íµWIDðãÜônàn·ç ¸Û¸Ûíyîöîv˳Îÿã?Ÿ€63,öÛ쎶ÇB€€BÈÂßI!ºçž 8 íˆD¤þRÚ»m×A}·,ôjOf´=‹voöM7B÷à·~ã×fOŸ>ýÂ{ïû©µC‡ÖxÁ±c¬ÖIâ¨fB k`"t‘1 I‰œ‚ #HBE qR(š3–Œ‘+N€÷¤ÎaÉAÒS$)*¸*)@DAñH¥W ´ÁmØ÷4w£˜1)†£ìL¹vý:Ãt‹oçñí}°&$$ê…8V „iÔ1€T©NT‚ð ¥À¥ÖÅÀ UØnœb *1A%*PB„<“º$DQi0U¼éŒ ŽˆTé²—3§ …(…é0`6`>m¿gmD\”ì÷ •ý”#“4£æD"I !ÔQW’&1RN¨ƒH`¤„ਢDV$¼‰j*A*ª¢*„t(AÊ’"‘„(êJ36Ý'}€”óŒŠÓ¹"ž‰ˆ‹û hÌkR.œ;ËÖ‘ÃdI¨’ÐÑ)HV’(šÚ+©(‚„ E;GU‘$¨T_«$@Ñ4“ZQÕÜâ@ƒ :DÓ¬ ~'R æQ5%,P‚ 0ƒâ…R "˜ììpéÊ%îyá=Hò=DÍ ú®'0Þ÷¾÷òØ·e<:„™ƒâF4æ^ÝPH€CàHAH Ñœ£€G4 N Þ~'îH(U–jxŠR<Ðhߎúúb‘]çÒH¨(IdU¶w¶¦S^õÊWðOûgÆý3ÛO@U?èóˆÑhÄ/ýâ«ùùûïgkk‹$Z¥4óÔŽƒBƬ̽®{4W_ê³0ƒpCUÛµBXµ÷ˆê_TƒÁ !¼àÑæâ†zmÃ-á †¸R ýhDVøÎ÷¾Ë‰DG£ï3.»¯ @„¤Šv©ªW †ÉÀ0†f‹¦*…:…ÁP"ª£Ú$2T•m²1 ê‚Å0Ÿ>#¢ Â!¢º)Ÿ}3|öÍö~p/D í;ÂÚÚˆÍÍM¾öÈ׸tqnêD—ª¸­&@4U[sí(¾E± nQ0¯êWµ°Å sbl¡ßžûîETe_uÿÀþÂ{ö¼¿½õ;Íôãž“§žàÛ>F)e“äÐú.ñùï÷@›Ñ;É(»a˜;Û…­ë:ÖÖFd‘F„߈ý;ýÝÞëªýhD }ù+œ?w¡ t654¬’„"º° Ñ’" èëL`ƒƒ°3™ðÓ/y ïzûÛùÌ¿|–¯?zœÁú±ÃôÚèÜ©Ü) ;%H;åP7æôÆY¾õ­oV©¯š©&.QýÓJ'(=„’T11¦ÃÓ)6Lyõ«™×¼æW8sfƒ~üã|ùK_âüÕó>z„ñè)ß:wª @ó;Áh<Æ}àë_ÿ§7žÞ+õ-¨Î{æ»ö IÈ*2î{Ð÷O|ÿòÇÄ<À›ßüþæ¯þšëúg|þó_àsÿú96žzŠÃG²>^«óöm«ò­Ýw`¤ÐÆœ¿ð,Ç“an  K5z bÏòfdu$eT/Fx¡¸3uœ}æÿáóOû¯}íëx×;ßÁï¿í­<øà[xä«ðþ~ˆÍ뛌FÝœá•9Ìú]ß¡’yìÄcüpã4øÍÏ[PÁ—f]ì…&$‚¤`^(æ¸UgØG{Ñ‹˜N&|úÓŸäíïxýÈGƼî×~•—ýÜK™L¶ñâ¸;fvà±øüfýbýZÇõk×ùÒCÿÅOß&xêÌmî„9"«LAEè4á(68S«`&“Âöæ¦ÃÀý/¿Ÿ¿üó¿àõo|=ãјÓ|âŸâ«|•‘ö+ÏYú‹÷²$RêøÁÉSó >õÉOsò䌺žcÇ^@—s]È †Æö0Ð¥€Ü“n|˜‘ûž®ÏU<(«!GA”lšfÁ†&áü³øÀ?À¾ðo<{îYÖáÅ÷¾¸˜`:@™LkžáÞ{ïåêÕ+l]ÝâðáSóU|Ö7¯Ëßn4ÆŠqüÄ7¹zmxR_$@£„«BᤠÚ×)#Ì3ÐÄ3ÏðÙÏ~†ÑxÄOÞ÷„ ¥ {al_»Ê~ï-|èýïåÄc'xÓノ¼va«A{8‚P"H@—Æœ»p–œ<Õ<µ¬\ëßI‹œÚÊ4@w}ÿ‚I "”âF)a†æŽu]Z°s@|¹ç‰“óðÿ<Ìÿý‹hîðâ•e~®Ž ‚ÈÐg%Bxü{ßåÒÅ‹užÖºþG˜O[ÏEÔ7¬ÔÙ` Œ¤¢®V)S§˜!2[ìØJžêG=çq|냬׸çGê2?µ§vJRCÙQb<qùò5ž<ù}6‡ }—™ÍÎ+ÍŽ-pd¾¸•)aE±¶ž^"@“]"%­‹7œ‚ûêðv±‰Tétyý(Gm™àD°›H©Irî!Ož~š³O¡ÏÊáÃGªÙÍ}“(r!6‰ÎÞ½ª%iZØ7û ±T³»)cn ¥"®”gj¸¬Ž»÷ÛëD€jãóæAΉœ2Û;Û-ï%@„˜íàäDÒºc èªcñ·¢BFÙ.S®\ºD™:£n IÏ‹×ËfpèÙ½eÐÀÜÌü€ˆ0¨&$ÑÀÛj pwD D&E&¥\wÞÚ‹–/žU„È™Ík׸¾¹…jfíø÷7k·kËÎovßÌèºÌh”IäºK½Döœ3ƒA(¤ËhH ˆ9U3AÊf›—/3ÝžÒ÷]Í0ßdú¼øEà«HX¥ö™@êûºkÖ¶ÔwÛžÍÑNÆH¤ÙJlü¢¨(’:v¶7ÙÚ¾†’¯oh.7#áF1Àí:¿™6˜]î!5Å·’€ˆ ©R?%u™@PÝ DU­Ö­ë—¦AŸ×Ь­‚ãÆà”&°,ùeSpw²*Ã`-ãÓœàÂö˜€ãˆ´Kh´ù’äsJL‡­Pe4N+A/ÏÏÅnEò‹ö¿Hîä^I®D8Ž.† ¸ÅQíÉ(I3È.øN3ž‚íí-J rŸçfQw–÷;ËÿkXŒõ—Ï r'O;D¡X Q#Ã}„×X #0rŽZ I07v¶&¨ ýøe1ë¯Ò€ƒH¸øÅþþÕßþ(p–V¯cÉôÝ€&7fWû V‘ÌÑÜ&2ZÓÈS£ø”.÷si߈€[Õ‚ƒÚíLËš`VöøÜI]"¤«"fF„1ÑZ÷“r­(AFÝ)%TÛÊQ29KMò¨BWk„rRÂ:%¹ÔòI ^·ÞàÞi½ª &µn@§H]|¨©4kÛn³" ÌW'Â[±VÍe°°ÉÒ¥ž¬™(-“´Ê ÒŠóÌŒé6Ï^¼Àµ«W%…¾GBÉ¢­4&iF%£©¥¬%‘B‘@Q49Du¨¢µ.·b Mµ"­$1‚Œ™!$Ð &¢fs-œYWKî*æ m[ùNý[ Š£ÄÀ°SØžlá^êwW™€YàØdàU/%ûž¿#IF5êÂ()©HÍáHRBñ•Z7@&á©Õ )$Oˆ‚ˆãžme6auùÝÒzªN„©uA-sˆ¦^+IDðÁIZwµÐªæ-½‘‡{­Xóàü…ó ÓB×f­}8†—n4â·ßøŽ9BD ¡í)ˆG]"ϲµáuz¥n­UÛ¬‰ÇðVë)»U´*“Š[êû’×ךŒõ¨dѹÔ÷xâBÁðV;T Ûkå‡(⎔鄩M°©c\½r‰Ë/1¸íI•í.†¢–—u“í —KìV…Í<ô, ëQµä¯ùöê[œÁƒ,@%œ‰ÃDsBÁ\­õµ`Ñ@ù¼©E—á­0K-uÏ£ú&ñ^jY])¦ƒa¥0L VB¤æL`GZp<¬:¥Zl·Æ)@$°™w6!«6¡)¸â®‚Æ, ««G5jÑp‘€T3·¤Tkÿ«e´*UZ’›9¨Vg< T8ššO’ê‹´ž ZIÞ °¾¾ÞÇ™~ws‹³ gñz–\Ž—£Ci• ­ïˆ˜@`*"`Ø‘ˆØ©×2©Ï"b˜gñ#gΜw׈È)¥¬ª=ЉÈ(¥Ô#é^DF@·@ZšZWBózöÙÁŠó"13`U¢ë.ØvxÝ®2pw€iDLIDLÍlLÛý!¢ f”œ³Ýwß}sÐ{8 ÉŠCWiÅ=Yê¯"bÎÁ"pfqÏîyñˆF€-<·¥ßÄÒ;W¶|Ѓ¥Ý”¥ÿ¯íÇþ†ž'ànàn·ç ¸Û¸Ûíyîöîvû_6Ь×ÜIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/exec.png000066400000000000000000000125661217176075400242570ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ=IDATxœÍ[yÕ}þÞ{}ÌôÎÌ®vµ«c%-ÂB(F¶.$%U–ì UXG  I° ©¸b„!›PB‚ är„9]T‚ ‰M\ÈH+!„VÒÒ®öš™é™î~Gþèî¹´ÒŽV²*¿ªW=ÓÓýú}ßû½ßõzˆR ç[ Ã0G:ﺮs¾ÇBÎ'ëׯŸ6qâÄCétšBÊ~SJ¡¶¶V;øÙg-¬]{ì¼ J)u^šišÖÎ¿Ï )U6k«\.§òyG9Ž£×U®ç)¥”zÿý÷‡t]gçk\Úyc ŸúMMR€RÆ(¥ „€R ]×qäèÑ Ýøê<>Ë"€bŒÀSJAIp¤„PB±ÎנΉDbZ"Q«€?Å!@h(%¨±,C×õIçk\c&`éÒ¥÷lܸq÷’%Kþât×Mš4é²+V<¸víÚ™={¶.!!pÀ'Â!–-[f=ôÐCo,[¶ì»uuu_8]ßË—/ÿþóÏ?¿kþüù6Vc2 .¼¯­­+¥Ô¾}ûÜùóçßUfX4Í\ºté=6lؽwï^7“É(ÇqTWw·:r´Cuuw«cÇ{TOo¯:Ñ×§úúûUÿÀ€êPéáa%„P©TJmݺÕ~øá‡;oÞ¼›x¬°­X±â‘ööv©”RÛ·o·/½ôÒÕcÁ2ðßkkkãýƒƒjϾýjp(©>ùägåÊk -\¸ðÛ›7o>Úß߯\×UýêÈÑõù¡vu¨ýˆêèìT]ÝÇÔñžÕÓ{" À?08¨‡†ÔP2©²¶­„”J)¥ºººÔ3Ï<³?ÙÚÚú£öövézžJ¥ç\mݺ57wîÜ3&áŒâ€E‹Ý·iÓ¦ŸLœ4™;ÞƒÐ\Olj‚mgå¾}û’sæÌ©kjj¢ýH¥ÒàœCÓ4èºÆ4hZÑBA) –-³¡0Æ1M†C‡‰}ûö ^:wný¤I“˜mÛ…ëâ±>Ú±#wç]wݾ{÷îÍÕbªš€J𔪔BC}=âñRé4R©4”” R1 MÓÁ« €ÖŸ”5 œ¥(¥ˆF£0tŽãÀÎç ÖC)BˆOÂGåïºë®[wíÚõò9#àòË/ÿÞÆ›8y2;v¬|(RÊÂgJiapRÊ‚gŒ‚RJOM@è!J%Kχ’ˆÇ±k×®üwÞyëÎ;G%aT‰Ä¯¿þúž‹źººAé:¥@ Ð ë Œi%K ¸ ü±W.‡S?B•k üò—¿<¾fÍšYœóáÓÝ;j$˜Íf‡÷ïßßsÙ—¾-—Ëz¥¶ƒç¹HÄãˆF£PR‚ PÍ•˜F¡:³PG)¤”°³6A)ECC=c§%=ÔÏóðOÏ=»çÁ¸’sÞQ ¶3rƒ_<ë[¯¾úúÏÌh´03'uÌz:FMM à¸.r9œKhƒiš0 †alJx =c étÙ¬qãÆhxKÇ®i>,W¶¶~½³³óÝj1‘E›=û’¹–eÒB ¥D2™Â„¦&456"“ÍÂqòH‰Ï÷[*™D>Ÿ/øžÃó<Äb1Lž< V4J|í(‹âP 䄨M$hKKËÏSÕ$‰æÛï¸ã›F$rJ¤RH¥Òh™6–E&“9)Þ÷=C__8ˆŸ8¥z !຾Ѭ©± i¬Œ¿ù±çõ X³fÍ=†aTMVM@kkë÷/¹dN½mÛ#ZfFS˜Ú<†a —ËR ¥Êý¹?`‰hÔB,Gݸq£>;ï8pÑh4裔 @AJÏó°dÉ’– |»Z\U`Füºë®[ÅqíSJ‘Éd0®®–E>—£ @ˆ‚RåA ç555¸øâ‹ÐÒ2í$?^)„€”RHéƒ/%”ò—MÓ„ XÙÚú­sJÀܹso¸tîÜI¹|~ÄÙçœCJ‰†úzd²6…0",æü¡ð—c¥@p>$aĬ @>ïÀó<8N¾0û~>B!±déÒ‹§L™rÅ9#`éÒ¥×Çjbœû:\Ò(!°³YŒ««ƒ¬W)%Tˆ2V M)Ó4‘H$ËåícǺ÷ïé'JñÚD-t]Ñ¿‡MJ )$2®ç•€—R@J ÇupÁôélÑÂ…×WƒmÔ8À4ÍÆŸÿüç ù)Ü^ȺaàžçŸ$ Q ”1_CpàÀ§G~úÌ3›~ó›ß¼—Édº !Ñ–––‹®¿îúÕ×|ãšëf_rIÔu‹\hèüÙöA¢ÍdÇ ž¡t9D"¬¼æšk ÃøG×u;O‡¯,ˆÅbM÷ßÿ‹Í®ërιhnnž¼déÒi™Löä› A>Ÿ‡ õõ%}‘âE€ºº:lÞüÒÝß}ßÌår=# ¦qüøkñ‹_<¿ôÿxB.—+àƒ“BB\.‡\.ñãëPB„WW‹íÛ¶õïÿôÓvMÓˆišzWW×§ëÖ­»-ŸÏòè2®ºêª¿Ù²eË“†a€ B¸ç¡»ûFZÿ”R$“)˜ñX¬ ¾¤8àgh¿ûàwÛn¼á†«„™ÓÍȬY³®Ù²åWjëj£œó¢êK<ç¾kΠ¾aeeñ¾–†æÉ“‰D ”c ýýýX¼xñªƒþ*|^制µíCÔ² Ö>¤‡j]>à ÷`Ñh™±!A=€„Zâ<üÐCß—RfªÈðþí¥Íÿúê½÷~wM.—+ñõžç•ŒKÁÉ;0M3X%Už ,>r´£0M×ÐØÐ)eYŒPa•ô‹µ¤ÐÊsô’+ˆÀÑ †gÂqüDJ‰ˆib÷î]{wïÞýëчò«7õ³átš{‡çqØÙ,ì¬ !|ugÌ/§»® Î98/Ž7,µ‡é6%¨eVö¬7FT‰ñ!„ §§v6‹D"Ʀ&hºŽ;wî;“>=º¿``Ȳ¬FÛ¶ÑÝÝ ÁZ.h ÒeÊ(„Te ýÏÀH%÷SiÞÙUæºB£ÄEqV?¨¾O¥2JI'Ô@!4M+l PB ”,ØšJ ¥Ç‘j¡œ5a¹Ë0 (¥0uêTpÎA „„뺘9sæÔ3é3‘ˆO°¢V”B$Á¬Y³‚g ¨a Š b’Ó1âøË¾P&¯ |J [[†aM÷‹—ÁwÏóð•ùó¿4~üøÚj ¸òÊ«VŽ?>¨BÙŒ1TŽ} PRTž“%K±²ÀZLÓh4EÄ4 ítÅBó  ®û¥oMÓ‚2¸ÃÐAAsssÓòåËÿ®ð‰D¼ûî»ÿ*—Ï—ï!RZ(ŸB •cì¤û¥Rð‚Ð\×u˜¦Q¨Dù$’2Ìe_:::ÚÓ©´Ô£Œú¥æÐ—VŠR zP¦.V|K›OJ>ïà;÷~çÞË/¿|ÕéÀB°~ý“›/ž={¦ãäáo¤–XrêW“CosªÉ CîX¬V4 ÃС”D__O§ÓGÊžYÚ!Ähnn¾6‘HÌ’RJÏóœ/]vÙÂ<ðÀ f$JGÊÃÈì §—Åüa'¥ç†a@p/ÿÔ† Ol|ñÅ Ú¥ýÌ›7ïžzê©ç.Z´äøñã(¨Ð²ûÆÌÏ<ÓÃÈ•_¥¢i2é”ûÊ+¯üþÀÛ»»»Û3™ †††öööþ§RŠHÀ)f…<òÈ#¿_³æ[ó2Ùb8\ :€ÁÁ$¦NmF"‘€~¦WšÀ!Á¹B(šqâDoï|°mïÞ=Gëêꢋ_þŹóæÍ•BFúúû ›'ã(XóÞÞ¡0McDb±¬{üñw7lذâ´àª!¾úÕ¯>¶ñÅÿVˆb¢4þ¶í„˜9ó Bþ&Lœ{È;.tMC]m-¢V4¸ßÆpzBJh±cš¯îEÛå2×uÑÓÛ‹x<>"xÊ„çâæÕ«ÿòã?~a4lU¥Ã;vìx£½½=gYQèº^Ö4MC"çÒét £2JtMƒã88ÞÓƒööÃèèèÄÀÀ „” …p»˜Ý•Ú]Ó04”„iŽøŽ bhÛ»·¯­­mK5ت"`hhhû;[¶l7 p¸ÇZ~ÆÀ¹Ó´2—StIEC¦ir¹L& î¬r>U^SJ1#H¦Rp=·sŒ$ŒQ¼ýöÛÿÃ9ï>gÀk¯½ölgg‡ŠDÌ‚•÷Ý”ß Cx®C×Ëî-]¿¡ëÌÙ6††’H ½ô›àÓ±³DMÍȆLÓđÇóï¼óγÕ⪚€Ã‡¿úÒK›?|+'¥.R‚d*.DYÍ¿R¤”¨oh@Ë-˜2u*”‚\áäc$ÁÐPÝ]Ç‹Åp²žø†Ç›6mú'N¼_-®ª PJ©7^ýÉžãÇ }sqPD6ðzÅ’±B`š&ô m EÓ˜ÆÐÓ{}ˆÅc§c 'NôŠ÷Þ{o}µ˜€3ÌæÍ›wE]_Æ.±%”¢Áæ¤Ïãþ;JP +êOJO®÷Š'Á Ò ¸Ig‘NŒìhÞJJ‰x<Îf̘ñ'þ·ZLUo-[¶ìï7mÚôÍÍÍÄ jvþ­Å’UèóýÊ×õÏçá¸.tMGh?ª -ÉîBwé8.<Ïe Ñh$Ø[}ŒJ)$q$½Ûo¿ý¯·mÛöÜ9# µµõáõë×ÿ`ú…’Pµ‹µ|(–¦¥ôËVœsxž/(”úß9DP½‚¢ ?»Ó˜æçU¯”É'¢»»Ó»ýö;îùðÃÿù¬ ¨­­ñæ›o~|Å•WZ©Tªì·Êý¹R ðßðµ ´ZS¸·äþÒ4¶Ðo•/GTŠR Sš›ñΖ·{n¹å–Ùžç%Owý¨F0N÷mß¾ýp>Ÿ?)û:9Å,¾ÿçÿv20¥TY1¬5Vn‚ŒE”RÁ¶œ>úè çÜížQ R*eÆ*]×ÿýî»ïž `Äí1B4ÂódÙ¹s%¥QáHÏÁ'â1<ýÔS;žxâ‰?WJý"àºîg†a|À–‘H`ŒÁÐuƒDבÏ;ÈÚv7œ„U^˲Pcù›£R* %“…âGøí>úèµRÊ÷*¥j7èºîç†a¬PÐÏóüí,)ñ /´¿û]¼xñWnºé¦9'ND&›E:=\Ü/8…FTž ¯gŒÁŠFFÑÝÕ)žûéË;víÚµûæ›oþÆ×[WN‚çyˆD"…™?ðÀþ0aÆŒG}tËÝ÷Ü3SÓ4¸Žƒ'ׯßóàx­â0€ºÙ³g¯Y½zõ­­­O™:•)d†‡‹›+DT`Y,Ëç>?xÐyë­·v¼öÚ«Ïuvv½ WSS³`ݺu¯ÝpãŸNó8%ÁãLÀۻš¦]ôÄOðÁ4MÕP?®°yZ*€aš „ÈÚÚÚ©µµµ–R*/„°…)e6h¶ ZVJja("ø^•Œ•€0ÂQ„a"‹D"¡âñ8,Ë"¦ijº®ë†a˜†aĸÿýÞ{[Ûj!„¥”H) ç\))ÕþO?í\´h£”Æ\×…ëºÂuݼëºÄ?È‘¶m+Û¶e6›ÙlÖãœ{(.ƒ3’1ÁŠõ¯Mž}ztúôé5&Lˆ%‰¸eY Ã0jƒ–0M³ÎóŸO;Ž“òòÎnIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/favorites.png000066400000000000000000000112631217176075400253260ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞzIDATxœ½šYWyÇçôr÷MÒh´X’-¤‘ÉÆØˆÅ€ †@€Ø\¡¨¤BX&T¥*¯yËCžLd“‚×T%©¤*Ûo!Á818ì¶í‘%YÛH³Ü½ûörNN÷½=wîŒflNUWo§»Ïÿÿý¿ï|çœZkÞMyæ)±™ê€EhЀeaI‰æ’Úè O~wí—ïêéÍËÜ("š™©ÿÁã¿}èåGÝÿÃ|Þ¾M)¬äþ--ö-úNjy;ޱªû¾‡ùëÒí÷––O üžþñsWžp] €DlBï¶a·ªX@>Ž‘Çf«V:ð;%Ê õ¿`öĉO7jâ£qŒ8²nIÛnÅGR뻱®–¹÷Î{ïûÕ/9°f(íÿJá®;Çsñֹ­R€±~³G«ßªúr¶At¢%(=Ì÷}èÑF“‰ \n ·‚¸JaUJÜ}÷ûø,•OÂàMðÿüŸƒ¶)ørþ®ÙÆ“q n‰lõÒÈŸ"Ôì‘ê7ꇾTAå ˜­!îÂàu(”cÇO>\¯pF›êcßi·òÝCëó»óÄýŸ¡ò0øo€òM€ð*(Eåà…ÙÃõo$*ÈcÈÛR#mµRësôPù·þR% ¼Z€VF*ÿM¨|˜»Nœ|´Zæ¾XÝša«^Oåð_m!èÈ("\€°G}æñâÑ;jÇ(F±`KÊV)`èû‡”Ç‘/ÔˆzÜH,Ð*ÎSTŽsçñ“Ÿªä¹;#l™ ¶‚ p”Æ*¸ÌÜ}âýQ9Þk€Î¡DM;l›ùBåÈíµ?‰¶Xï5ÆR¹(BÞ_þÚôìon#lA¸œ±~˜šmè ú 2ËÝÇO~¦’çxFï9 ï%黥q .3÷œxàq*‡Á›3òJ?ùE UCÔ ÍöCŸ®Ù_ûz´…yÁ;?ó”˜Ô‰ü¹(">v°üµ‡ÙÆ`¢VrK&@™½ “¸©IÎx— |;ïºÿ7Μÿѱ@qF \ N¾¥“¶pê´~GÃçu XhZ$$]ºF)Š×âÐ]wŸxL”÷Aÿ\Ò×Gɣ閂»¦“ת>m¦>RÙûâþâÍî“®C, gR®DBÏ<%R÷X1Et3b†dÀ¦³à…Ö&gûö3:Î\Ÿþ¦ps6 Çá¶rÞšÉ嬙};ËŸšžyhŠ`¢.ˆÄúYàCÀ"ù¢ÌÜKÚì_ƒò~NÜsÿc*úY·ÕÎxA|¦?Ð"Å|ÓùÎ÷F¿û¤B „ÀJ@ègžYƒ ÉI‰§O ‹ÔfŽn$OSX®Í6×bW)oÝ^ÌÛ‡*¥üL½Z¼£\.ï«ÖjÛ åz½PnœB]ˆÂäv‚>Ãeø˜ †\Ë‘[ Œ´ì†‰ Ý9"¯É ·zÝå^·Ó\îu{×–; =?˜kõoøa|®p9Œ¹þÔ³º›ÅðÝ'…”A¢ž„e-NŸ"ê´öž=%ŽÅîRN(¸ÖÁZ¹0S-U*åÛªµÚT¡\k+‚S¬K™¯[»2Ò‰Q½7ï ;4fùq"Æ]aHPØN- –!Ĉú&XZà7 ûK zËa¿×ìt;­ån¯w¥Ùí^ìùáë-opÎÔ[^ÈÅPqãÛÏjÿô)á âéoáì­ç¿xìÀÔwªµm{Š•Z£X©Ýbݲ UÒ)•3`R€Z¢w¶/'˜Æ 9Tú|æ\¯EL² ìŠq%á&{„5Öžbß´aÐB{†¯ß ¼^«Ýé´–®7›¿øÕ|óσX/ØŽdï‡O~f÷‰íÀYL'/Õ&‡ï'iëø›m8‡™‚M—€'cRËt$K@jùỤéREè’- ¬pƒÌ;R·Èí§Šßlá·{ØÞU.-Ÿ_øñ¥Å¿ñ"=gK|  ôS˵±æ½áÌEõ‘£ês{¬ÞBD±^Å)m3 –3q!õË8 œéŠÒAV+­œ=¾ÏZ5­Ÿ—v‡6à˜œCæ’è/GA/Vk eoy™°ÓÅö湸táÚO./}ß7à›Àµsßúìƒh4´%qzѹV·¯öU8ê8®Œ…@cª€m” BÓc„m[æZìeÀgÔ‘ jY2ÆåKV¹AJŒŠ“$ȃ k¶ØOæ48´³ ¿Õ"îu°¼k¼µpáês——Ÿ ”ž³$Ë ø  øÖgD0ZŒT–Ä]ô¢‹Í®§ö•ÅÇudj„а\žÉÓc?±¼Î̤±Z¬PÙãì½T +ꌟ§[&O‰ô ÐN¯ÝCy=lÿ:s o_ùÉååï…Z_°KË·SdU R%,{ÑÅ…NÏÛ[³y+²"¯…ˆ}¬\Ét1ñ€Q&6 `¨X h¸×cÏëÕÇãî¡2ÏkÐîvü®j]Cy}qþâóW–OGZ_´‹ã–B@ ­u:´0£Ã2P¦é0¦¼§â>úÈáé'*Õ¢£d·RÇÎçÁ»bÜz 8ýãJ+IîXEªFÜk"Â>g—ZŸ¿Ú|6ÖúRÆò @cùh8LÿÉàE`;°ØÆTv—݇?~xúËZ!§¬¹J)C,aT"™,¬7à«€g¯›k¡hûô Ã« ís?o~?ÖúŠ%Xæð-ŒåãS§G£]‘ýEf‚À°'ˆ)î,ºýäáé¯nßVÈ)+[*!¢v2ˆ¯ÍÈ!cÄ.0® ­‰µK¹èA‡W®7ç~6ßüž†kr¥åSÙ¯¿Š€1R%4€ÀîPQžÊ;}bfú+SÛ‹yÜ<¶­M¶8É n&ÿlõ\`ð¤j¬‰•K<xy~鯷~€O-ƒ ²_—€ PÙ–³üÄ¡¿»{ª\Ž…ñªw¬M@ædRXϲÇÚ/ 4/]Y:óÒBûB°(7Ø€å×%`Œ„¬;¤$T®ýGg¦¿ºgW©¸z8zm"&Ä $¬qb^¼Ô<ûÒbûnl<¬3ÅœÈ%Æä}` ¸Ì;’Þò úe³?h™dP¯ÜÒŒBéÑ`exžÖYkŸÖet?{žqµïÿJé¡ÏÏ3êço ~]ÆH0)s XÔšyKÈFÁ­®h\v[q Ädƒ^ñL†”ì¹Ò8RÐp©Ä8‹À2ÐÝ(ø›0FB„ &]Í¢%Ëe×*Œ@e¶U`ÆIÙ@¬jÆ€ï ÇÞ)ŒBÛ‰‘Ò€wSð" C‚ÂdO†^ɱ÷KN‘µà¸ü'Z5¬8;j޽Ý8Ú´-b4 ±¡òŽV†´FU{¿c 3[qsâcyA¦ÞÄ@8v}x-{nŽ+ŽUÍK9íi5·N>ºfÙì:›lNݵ÷!ÄÖ¿‰üW]g‚Öp¬ª´¦d[nAÊIg–™±ÙXÙ¬ %Tk®½ÍÐL¬Ê¨ÿN‹?Ö«¯­•eïk󉼢bYoD‘´ÞÁâé†Hr X„+Åt͵kÙ`´ºd¥ž´vÝœ`‚k¬;V0ß¶$Ô,뎋Í*@–ÒÈ¢%”« F7-:‹lÂØ #Ö"aU\0ïªÛÖmÂd¬£)è •ÍÆKeË:˜·¥\¹³]àZ¹ÁªÀbÄxÆb‡¦f[;Ø®þr/×XÙ^U6£ H ¢j[‡)F Ì–†žàßi·Q j¼Þ¤^ {,e˪¸BìñÐsbô—ʆAm¤’붽ϬXÝ$êÇ”JÎ3 1Dý˜Kó½ÁÒÒ@ÅžB+™Ìþ&íWÉ$gº01;4Ç%KºE!oO¸ÙÔo47U@& –õšcíÖðÿ¼`¹`›_{â0&ì„ý‹}op¶ßõ\0øYIÊ©c¹Â÷åK{‹…N1“wÍc*„Ѓh|+3ýž‰9)¨ ëÐuoº'ØŒ X˜¥Ç]Û®}_d‚šVt®N¥ ôÂ^Ÿ°ß§éyá¹÷Ú\è?×ÓúmK`/«øüÿøÝWvÞ}G½Â‡÷t‹Ó¹|«PÄ-•q $1 Úà·Í\¤+\ÃP“òb\é*ê†Ü`£˜(y{É‘¹•‹1HŠ;À-£bEÐõˆú}bÏ£ãõã¹Aÿõ7ÃÁ¶•:k BG! äæUü£ƒî/v‡þfƒþ‡vùÅíº_ ÈpŠ%rÅ)d~;ô—Ì–þb›P“Ö^ Ìx@‚Q¹IIs*Ò:˜—Rë‘ÕsU(N¡„Ý>Q¿ò<:^O½åõÎ ?j*õª%ð±bàüTiCEƒwYE?¼6辸7ô?rlP8¹+(ÔäÀÃë°‹%Üâ„SöUãÉMÍ’Ûm˜R°$66BÀp}Zk¬š´9–·âäëľOäõQ¾G¯Ûå\¿{álàÿ×’V/ A×ø˜át3MÕà `$渲€š u ÁýëÕ óÓ}¡ÿ±Yß{ÿ®|¡,WÀ.–±«·AgüIYÊrN‹ÛúB¿.FqণÍ(ÀP¬YÖm€‰ðÅà”ˆ»-b¯O¿Óå­nçê™À{nA«Ÿ#hÛÆâÍdkaÆë©õÓ_ÞÜ„”6ÐPw ® œÓá?^„/ÜøŸu¼{§ …‚|t¾ˆo ”†A›’”v q°‡þÞ«I&,mVâv4,k'(pk sÄ­ezíoµÛ7Î ¼ŸÌ¿¨-[0ÀLP,%àSàÆò1£^}€Ó÷’z„ˆ†Xž%¼|1Ÿ¿#ð9Ö÷îÙY컲XDæ }jÈÃ×Pb3=ÁF0ú{AãH¥d°éÏ_ç|³¹ôÚ ÿÂâ”`Ñ6`ÚŒ¬Þf4E0Z†Ëö¡©¤N?CX'!¢Â×ß¾†33MÿáÙžwlª\´Bibú;í†Óá wƒ¬H²ü²çý›¼æ<æ«VôZ¿ûâÛ"~>ܰ ´åR‹w’-d€OŠÌ’Ñ„F”Ô0RE[BMBüúŠß<FG,ùÜáä÷/ÆÑÂ%ÿ»eâIwÂûß1é”Xh¸(¢¿»Ò]zAIÚ(Û|0µx‡Ñ¼Ü€•r_¯KJïIFñ!JÞá'ïmM u µ¾Ô?ÿ%áÿý* ˱àš\‘+ç•Þ`41Ú–‹%çÇ6I»µ4ˆe-žõóþ˫Ǝc ‰>&~¤ÊjI¨`Ús ð¤QKŸ‘ÚnZÖ%àÔi­’@3j*a`% ó0žüýÀœ”ìúoú³qªCvȉ‘jÒî5mÃMËfà3šme®§“‘ã‘ý݀ϖ,q² Hf¨%=Š‘"@oäòÿêï>¯-¾êÜIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/file.png000066400000000000000000000015211217176075400242370ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞIDATxœå[A®Ú0D)p VH]VbSNêêº.\†nXô€ |Ç]T®\׎gÆ3vÒÿ$ôíxpìçñÌû&鬵ðžÑ·@k £ãñøõt:}y<œm×u¬6‡Ð#cu÷ñë®okm·Z­>\.—ïçóù[î~(v»ÝÇÃáð c[>ã8‚µŒ1°^¯áz½þÀô"ÀÏçóÏ55Õå¶ü½â©Õö'–7¸1ç@Šáàbå’6€ß¤8b\9Vïû>Zöí1 Á$›÷ V¨E‚peÃIÀ‚km‡ð/öƒ;LM  ®º¾ºPH  O‚?ñj1 trZ$P&P¸Rm\; ±²oƒ…XœjÓˆ ðOþ§º?€pœj«)–(OƒSm5ÄRÕ0|¨ =M0eÃ"Ò ';`ÑT jŠ%,f­KR$ÅiÛ¦%–¨˜Íˆfv˜Šßµ–Bv;Ìî@¤¶'Ìò@¤& ³=áöA…šl)–bõÈAÐu^krÔ{¹k¢AÐuÚzr»Üõ,H#t$úPOƒÜ½·„ÀˆÎX×X ¨Mæ‡LL›6 T< v£¥“Püïpx­5 j[ w£¹¥A,HišZ‰%Ì9³…„Ø@9všq@Ta -–\]Í\™+Žb}Qírm¨þ0Ò*;P v*Œi× A- –¬DM¨9 ëK"A,„õVbI] –Dü°¾%»©TŒõͱK µÄ—/]‰T_T±Ôì×á°ÞJ,Í:ÔKT Ï¥VW;ERcA•g„r¶”¾¤=AU · u)ÜB,Q€>( vÜ:W ª<Ð* ÆúNÙQ!ž)ß-!"IIÅ ¯PS‚”•Ç<÷J¥{n‰zopØl6ðz½&•«§fÌ]§Ôݵa@M :ÌžÙï÷Ÿ·ÛíÞó@Ûã8¢’ú>#nt}ßÛûýþóv»eßEð?ãÝ¿=þ 仯šOxGIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/file_alert.png000066400000000000000000000061711217176075400254340ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ @IDATxœå›KŒÇyÇ_U÷<öÉ]’+r%ziÉ$Q‘P¬<Ü,_|ò).,†XºØ–í €sÀ8Ç1l–€ B`À ¶€HŠ’-Š–h=LYâc¹ ¹Ë×>g¦»«¾ª‡œéÙÝ¡ø[=U]]ßÿ{ÖW½¢ªü.“ùm/à·MQ‘AO>ùägŸ~úé§VWWW{‘-õ5©]#;Ý7¯ÖûæÜª*¥R)~á…¾ÿüóÏÿC¯÷àСC÷?þøã{'© ï=ªŠsŽr¹Ì‰'^)2G!œs$Irë·Vi¶Kv«}°^â›I»•áövSškîE}ù€öÅujo§(M`šíN÷ƘŽmA ™Z“úv‚w`Ë ;`º1°Ó ´R+­÷1Sœ­-‡Á;eí‹^EiË> w„fû–ê·™CQÚ–èÆ@«÷î6®Wô¡•q#æÎø€í27(Äg¶i›õmu\? tj·Ž)J;»õ Â'ëã‹è‡v4 vëk¶­Bd ˆbD‚Í"ÐÞóC¯d©?^ ¥Â¨m²ùÍúA°0ûkn~ð-Jfƒ¥¦G™zðÓLìÞ^ñ=æo’ˆtèë¾(Êhç>‹û¯þ=ÜûSüI03€–µ3Ïpîâ_0óðˆó¨¡•úU(hÛµgQ‰àüéŸpô¾÷½_†:°ø \ÿ¬U:òwÙ癿ô– ÐfóÃÆèÐml'Ú’ Üb¬ƒt:i‚‘˜z=Eç¾ |®ÿ¤—A=h˯Âê½T|Œsÿó “{rú–9ºiBgS(Fω…÷^9Æ}GÀÚ$óÀ0øQÐ ˜a¨l‰ƒS³ïüá¶t›¿I›iB/p&è±Ræúµ«ìYú2ùÔ.€Æ` ĬäšPåßP½çpgž£‘Ôñl®Ö½BdQÚvìÚ§Œgîg_dú#‡ Ò0wí,nþ4Éü»à¯!¹¾Ì©!νþ]¬ïݦóµón4¸‚ˆ*¶l™;ÿ6wó#dò!X™ñ¬Îžç­—wóî›òΩüÿj­ÏƒSX;CyÏï3töïX\¼†˜hÛ[énTÈ  }íNÈ«àÓŒåS_àÀ‡†%Y½AeߟðÐc_º=g¶‚¼ý °û ¶„ŒO±ï® Þ9þ×<ô±oàUS8·¯¹ ¤ "ª”â˜3oþ+˧1ã†Õ«à€Z‚5¾m±@V‡,ïáæyJ»~»æÿ…¹ §1Qm°nëè‡R³ÜXcø½¯SÝ{± «+à3p¸õ )4à’З,#•*“{§X|õ9²4ÅÙð®në(J;Uc=N|“{Æ®`'îÆH©ƒ$ @´Rf@ׂÈRpV°‡˜^<ÁÜÛ?F%hV¯uôK;› zµ1W//°{á›”ÆfŸ@½$k2põÀ`+‰@âræs IVˆJ£ãûð¯?G=]Ã!ß[ä~3*@§4³£ôEçÊ+_eïˆb‡F¡$Y`®æ!óÉvª' 9Y ™ƒ•›ØÝSì«Ïqîø·1v}XìÄt{–º#hÕSïÈ2{æç¬ývt" é2 à ¸Ò|û¡……4 NÒNiã#*ÓŒ¿qŒ›×æ1Ö¢]@èõ{;mI6…Oø_~ᡘ¨4 «Iê7amjW`õÔ¯¯Ô×ai–/Bm7BDPša''Øc\üï¿BDQ1;–îˆÊ>xãÌdoìWƒÚåüºIÀh¤à“õ/êAêÉrhmV.ÁÚM˜hl’»õÏÌž}‡Èl ‹õ@h½wkËKL¼õuÊ#£ˆ8X^†¬Þ†Üß[‚+È*ë'÷ú] >ë|ˆõë°´€*3>dX}éó¨o@^úî¶®`³ƒLUO\*1wâÓñ f¨‰†ò–³!´9œZf µàÛШu jŸ¹ðŒ×`>¡3Y#ßÅ̹_ðëS?ÄŠl@Gt½bJeæçÞçžÙïbdž!%gZ!k¹œ‚OAªpõ84.Az5\~‘ …ïo?ïò6©Bl¨NF”^z–å´v’-ëÛ õ]Y—w›œ,¿üefF¢°ûËrÝÉ eDÁÙ}û Ëž¸j1ûFö‡pé=ø¼àsMòͶCÆGùÐ…ëœ~éoyäã_Áã6šCQÚúÁˆó˜J•³ïþ÷ÍÿªC-’Ó<Þ·\™áMY½Æ©ô0ïÿÙ·xëÐ3\¼A²|DÆmÉo¸<¢B´«ÌþŸ~ƒù¥ëX±ë 'ýR_»ÁõÒjõó³/QÝ;ìž\]7‹@¢°ºÀ2G8ú—¯Q²1—gÿœôÅGˆï Ò÷þ¶äUÉËĹ&xdx”ýå+¼þƒÏ°÷É,^Ý–HúŽͽ>q…Ùãßã~>‰sÉi‹Ô;IP`~•‰?úÂ-æöx€h|+ÁLšóøNsh¥»Ç9òò¿óÁìI4ðýG€ÂlH…ÅP«/²÷Íc˜±‘Üɵ0ézõo^ê ˜?µþY‚,Õò¨mt‚-†÷ÃÚ‹O‘fÙ­°è‘ Ãzc%æÚÙר—Ý1¾Ñ um l¸JPÙÇÿ.þgˆ Ù2üÛÇCšLéö–¸•YßÞö°æatœé3¿aqå6?VúÓ‚þF”úâE´‘›ƒj0Ðüo ¸¥ÀäÐ|ÿ ˆ+@#05²'Osϯ´Ø=}JJTóÜX¾Ìî±ÉÜðd¨ ‚& ¢‘=$u(ÕŸä’ ýjòLÐAi¦F!©cÁ‡øFH|žñHó<À†4¹5$…5Ï¢Ê#£¤©#2öÅTá±M0@’Õ›ºŸóÕ]Mê`Ë@î¹ 9Ão.i`ÌÖÀW—g…@‰P Kª>Ô 6œ &, ömMžHЯps…¹#ðpe7ø1åÁš€7‚8C%ªréñgYüÉW?(`¢[ŠÊ(‡…›jPwU ”<ø2Hq6GÎ?B2?j°Ú€l-\k+aœÖ`%ã⢡ò©¿Á;GdK(&€?(‚Œ‰cØøO9]–é“ßáCþ&Q5ÂkuŠºïD¸,Ã'ç{~QDœÃÄqбg-Æ€FF,Äà C 1ª ü|_–ÇhCÊC¨º uĽXÙ·@C).ãý(Ó>ÁâÝóò¥7ñKÿ ‰Ã‰ ’¡)PJa2"%2Ž ðÞ Þ#&«'2ç1‘TQÉÈrs·j@¾\Åþá!¦ï}Œé¡}Äj)—†Ãá’ÖöÅOß>@Q°%*åŒXbkØ5qu"ãPSBTPï°VH$Âz‡³eâ,C­A#Põ2ŒP+x<%‰IsocÁf†4rAÁ=ØL( Q7¸…k‚ÝJOýÔè;mXT}K»Ûi°ïø{ë½J¶é{:Ñ@>èwl?sõç ›-¦Ð‚ Žíg®®ó êKÑ­,®ÈحεÙ<ýV ×¶#ÝíÜwó7žsƒªôZh§Å ”ÍÆõ—î°è÷ÙíÐf 8í/Ü‘¤vÊì„VXPèGòEÞí»žNÿúÒ­+ŸÈAÁL0Š"*• išöü©×¢»ÙÎÜÍûæoQT,É•"vùè£~tffæQç— ý˜@Hw‹Óv|LNbŒÑ+W®¼qòäÉžÿ=Z€ÿÏô;ÿßãÿ{S^-¬›¡éIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/file_knownbad.png000066400000000000000000000226261217176075400261330ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÜ!kA£ÈIDATxÚíyp×™Ø}L÷ôœ˜Þ·x袲’lE—W´ly½»NþHlgs¸6¹¼•dk×&»[‘7‰”Ud{eoéˆkm)–%Å’e™¢I-I+¢HK¢Í›"A€HܘÌ9zúʨ„pīꚙ~Ó=¯úû½ï}W÷Àr[nËm¹•¢I£Ûr[Øk\¶S–å³h­d×Z.•‚ ì|ä‘Gþ¯¦i*€ã8W¿PüþZ6Afô½¹ŽW„ÿÆLÎ1Á¹œC‡Çqfü~ü±¶m_ “ÏçÀäJ™XB@aRõ9Ûýó9n®}SRüy¢÷©îÉú&{/Š"¢(^Ý_¼ol? ”ÒRu]kæú{s…`2áÏ‚©Ž+…}±h” ó9n.L%üÙ@P¬ÆCP1\L'üÙj‚i<‚ò`®Ìe _êT¤XlCîZC0S[`&LE©c*âbúz`6át”:ÀtM5ÀRk ÁD*üo”J”€ëA Ìd–΂©ŒÀRk‚E,6 ÏtQÅ…„ ì—€™&€3º· AÆæ:s¯w–T ´Äl!˜Kþ`¦”½X.‚Yl[b®£é„?U, ¬m€r°ô»¯ÔLµö—u ¨œÜ½Å¶%J ÁtÚ "l€JöùKA)Oe¿L4ÀÅš¹K©¨dª}e ÀµÚR¯,ªH °T (‡Ê¢²× a” ¥ˆÌ·²hì}ÙÇÊÁ[Š•E¡Ê ‚¥TYTq¡àJvéʱ²¨"4Àl¢V‹9s—BeQÅ„‚—ÛÜ'ÌtŸ+Ò ¬ä$Q9U•½¨„bŽ¥PYTöK@¹çñ+µ¨¤¢AåžÇ¯D–Œ¸T—ŠRB0•1X¶‘Àk™ ¬æ« Ê€JÍÞUJeQEßTé”SeQÙ°5ÁbkÅlËO©*&PnT²Fªh ° Aél‰Š7+5_)E%KÖ X† ‚–€±èÕRÌà•keQŹףKW ,? â:‡ bj— K*Ð \nåß–Ÿ²„*‹**P ËD%VUT R ¨´¢’kÀòì¼¶}X¨‹¿T‹J–d`)}Ê‚²ŠÌuæ^¯•EKÒ œëE^ê•Ea.UÊ%‹xݹåA9£"X† |!XÔÛÂ¥\TR‘q€Å† \ ¹ë.8_–+‹*Ì œhó \‚1夑ÊÚ œì× å¬8– å4ŽŠ, _n¥kKê¾€…ÖKµ¨dÉ‚Ò}\†`‘A áç/®›là|!X®,ª07p!¨^®,ª 7PÅY=$ªÒ Xì¸Ãb6y¡g¼ã8S>ñj:·f®Çg20g³ª~Û41cq0 ”ÆIš÷øgr]ÆÚñ߹˗­ŽlÔSÉË÷¾ó1ÀYt P®ËÁ\fÚlÎg™&±CoÓÿÒ«¤¾Cbÿ~¬\nÑ4Á?TÔÍ[þ"rË­ÿGtÉÿåïá†k²L \ªèé4—ü"Wþ÷!¯ãYÑ@ü'/}î9Œh´$¶ÄTãøl“rÙÿî`>¼iÇfÙ£ýk—'øgOIÊÚ,ä*—€™Xð×b9˜‹ºê|ɾ>Žÿà ïÙOSóªnº µ¾—-ÐûÔß’ŠFiú£?B[³¦ôã°,ž‚»øŠú5v¹C!ÜÕ¯©iÿ4–M×|žÖaï¡°(`ü 2ðq­5AïÅ‹ì}ì1ö=û,‰8Á;n#´c+j}=U»Àòúèø»¿£ýñÇIŸ8³È”NC°2ÂgÎ(ø¦®yþ‹®Æ»îÁ'»h¸mÊ [Ô„"ïÎÂ_Xð/¾Þé®§T 4MSt]¿ýßøÆ=š¦aÛö¤ØX›n¶Ï§®ÇN§AZŽãõÇãèë¯ãwkÜñàØtë.TG€D—ÛR]M®³Ø¡ƒèÝ=hõõ¨ÍÍ¢8¯qè}þyâ/¼ ºµyí|IÜôÙ‡s:v<†ÏçG«©#¡ëBW_OCÒ²¶àj†Ó¿&,ô|žßüêWüø±Çøõþý47¬à÷?û7oØ„–Ícôôb÷ô!ÆðÂx×®%3tôÙ–”PmݺOx3G¾½®ïŸÖgŸÅ-Jâ¦/þ6ü£;£Xé öp;‘¤Úë¥~E3º$ÓÚÓ]•0Œ[3ூ3QH/(…BaB®%sýíâý©TŠƒ{÷òÌãsæý÷Ùºz_¹o775¬@Éæ°’ œáá‘-=Œ“Já­Žà߸=;LâøqRÇ#) žÍ›eVãÈœ;Gç“OÒñãã†Ùü¹/²rÝzÌž>Ì|;—=£ëX©U’ĪÆ>gz»Ý1]ÿaˆ ï&. • Á@?/¿ôß}òI.·¶rdž-üñ§îfg  !•ÄÊfp ]Ùò:v>Dóú ®Y‡#@êÂybGâäóx6oFöù¦‡m¤Þ{¶Ç£ëõ× ¯ÝÀæ»î¥6¤ÐÛ‡‘×qòy=?òšÀL¥ñ&êð×Ôr&:À•löÆ,Îz¡+$+Ý9Û²K €×ët ¨T:.]âõgÿž7žýV2Í}[¶ðð»Ø"ÊCCXyýãÂ/Úl½€50€ŠDpÕ$Ÿ‡áËDFïïÇ»e J8<é8¬l–è[oñá·¾ÅÀ;‡Y±óf6l¿™z4†¡Oü»Ž>2&3›Eΰ©*Dsà ¡#™$ŸÉ­:lóÚV2…Óæ€ P’ê‚H$âK$ÿ¾¥¥å¿†Ãa,ËZÔu»”8ŽÃ¹ã'yû¥×èxï8Õ*vnXË®€‡šþA²±èŒ¯‹`Y¸ƒAøìï¦óØQÒDv?ÀªGþ¡]»>qŒ™HÐó³Ÿqá;ßAïécýŽ›XÙÐŒbZt aÁ>Åçç¬Qà• ¸c B+ÏtE£ÏŸ,$ûJ ^*Í0 .¾!r߃Ÿgý¶Í¬ ùpû ‰–‹˜Ãi°-pf0w0Ó)TE¥ÆïõãVÚÏŸf`ï^²ƒQVÿéŸR¿{7¢Ë5bìõôÐþ£ÑúÌ3H¦ÍÖ·ÐèñCt¬ab9w& à8؉!n vìàC-À°$¯èÿýì‘ÿwŽhrÏ‚0Ÿøý\‚9¥èë+ Ô­l¤¯µƒoý’ÓÇÞçÎ;ØŽ'ŸCOÆq˜ie–3ªk•D ŸGcÆ­th}ÇÞ§í›ßÄîí¥þË_Æèí¥í»ß¥íå—PÝ>¶­ß@Ä´0ûÑM gLâ³ÐÙàv)œÏdx£§›SÃi<¾àËý¾­ë}€\2&ú×ÐR'qMÓX¹i#V¾@|(Î[o¿Ík¼Ã=›7óµP5µ†A6›Åaf“Àt ©$nÅÅúH#ª$“¾|‘Á§¿‡~±•Lgƒo$³º¦‘pz˜L.GÁq>þŒˆ“"ÈŠÂq—Âw®´óëîËh6ç×WÕí}¡·2ù|`.è°P³}!!E‘ºUM.‘¼`‘TáCyö½Ã nÝΟ44ÒÔq ;Âpl„MJ‡‘¸¬á8h‰8+›W‘Ø~ z¨O¤gX§¡~%u’Œ{(J2›¥ Œ7CMTÀvkÕ4žèêtÞíë²dÇ9Q'ÈoöÄúß¾í>Û5X²\@¹B0WM"I ÍÍHªŠä÷â® ²ß>Þ<õ[Œ [xxEk.w`ÇÑ-gLÌ€ÓCoË9Â[wÂmw Üy'_ûìY¬K-ÄsYLAÀf'xÉMÐ=>Ë ßïëæx´?/Á¯%Ø3à˜G;1?†Jš *Wæ{|]]Š¢ y½ý~ŽìÝ˱³gù^>ÇWëW° p÷]aXÏcÏP’„sáC|UUÈÑ(Ö¥6òíIEÑavi}dÇA•]$a¸T^ìuÚR‰¡x' {‡á=à"ùØq¥òRƒÀqB¡Û¶oÇãñPí÷sdÏΟ8Á3™a¾TßÄõÍz®×óWSoâ –Ç6чÉÚvøWè…©|™ÙzÅ p»\ Âì%ÞŒö;±|¶»%`¿põô¥`ìqñ •¾–x½^6nÚ„OÓƒÔœN¶wP0 >[ÛÀ*—BG/yF®z)oäD4ªü.¸5¤S 까ÛqŽ °/oÇ=˜ÎK]°8Àµší ÔÔÕ¡¸\hÁ@€Ó{÷råÜ9~i™ÜSßÈ A¤g —Œm_Õ»B‰„¯^QÂëósÚ¥ònbˆŒQHª8‡s°·‡Mhk…á m.EÇ!#ÝpnM# rnÏú>ø€£]—¹³¡‰Ybh ŸdA§ÀG:x® ˆ€ð»DŸó’ÈñÔ-…AdaŸ ï óäfì=,¤¸Ö,ô¸¼7¢ºÝøƒA.ƒ$Þ}—ËÙaB7ÞÌú\Žô¹Óôô÷Œ9 A ä`BtX½CQ#lº†aß ì3àxzŽŒü ‹@¹º }nÕã!²f n‡€ßOj4…ò™ÝøšVà{åeì½oM'?оÌPå{*P­y lÞFzõ:ÜýDZ/¤û{®¼i:öË´œèÅI,ýEÓåêÎ÷ÜÓ¥.UÅÓŸN“okCU<Ðzýü‡äZ>$VÐI³øÅ „íŒ{o~ß³™ ²®ã†áö Â:ÑÁ~úæ*·’j€âœz¹¹ ÙŸ‰F9ÿÒKœ{æ´Xœ`¤žôë?%$‘˲E†œ0.3‚âW{4t×cäΟ&Ô߃ªFslOܶî±Aøü‡þl woÙ \ þdG'Ÿ}–Ö_$h9¬­Ž Çct'b¤- cTˆò謊„.Lbék€1,`ȶ1bƒÔè:+špܪzéJçý&Ôä໯ýÕ$ÅŸS— š˜Í°Øçmÿ‰üúÑGiÿái@bs0„¤/>Hʲ0‹ÖpwѦŽ{Û´Ñ}Ê覎û®ÈˆyN‘élcêfëêuR•ìºE?WàßüÍHhy°”Ûåƒùà/ÿ’ø›{Y­ùXë `Å£ $‡Ðg¤£Hxc‚u°2Á¦Ž;¦ø³<Ó*è$.]¤Ùm«ÖP¯y6jðlø“ÇauÙ¸å˜O¿©ëtþâœ}ê)ŒóXª¦Zv‘ì%:œ¾:ëÇÔ½X´Q´/Ҩʷ&ˆ÷;EËS´Ø@Ò¶q:Û54±±±‰ËѦÁdâß™PûøÞópêØbEËÍ\ˆÊ"=ãÒOJëÓO#ww³ªºŸãîïah4¡#OÀD‚F5DhT¨I>~ O±ðí¢ÏVÑç4àôvŠÔ±¶:‚Û¥„âѯè¶]÷eø_G¾9El@.µ +ɜͱéŽZŸž®^ÀŸÉR_S‡˜Ï1‘1«Ù9©€ñÂÇQÝT7¬À±-¢}½ ô«É$Æ ~Lør‘&°F= û©2 VúƒxjDw<öù´iD€ÿù=Øûð$·‡É 1Û—¶m3tö,­?øý¯¼BK¥6ÁHÄH$“ä[Ý5‰ð‹5A±ЀˆÏË6„OÝ…0œ&rø”Ž6sÕØh{ÜR0–JN$âø :Õ j$"öÄc·éúÿ0!ò4üä!µ(K@¥Å&ë³-‹þ#Gh{î9RûöÑ Qåöè%“ÍPl±à¥QO¥<@Mu J}==‹ÝÕ‰“É" 6ÁU«põôK%ÉsÇ _.ÒÖh¨9Íà±,Á®HR|pc"›ûVÿžùsèYŽÌ Ï.èß³‡+Ï=‡}ò$«këñÚé®Nò¦qÕØ/üb ÆÏ|ð ¡HB$B*1H6›Å¥¹q†Óä.w`‡«ñ66âD†’CdG…ëŒ3¥Ñ÷c¿gi„œžÇŠW³®¶‘þ¡h$Ë=Rm?rœ'¾ (2@çÝÆn ûú׿¾hw/äyL†_døçoR½¬X»e`€ä•vr¶uU®ÑM.rï\ã–ytsU.¡ºìp5ýý½ä²”[w¡}îAäæfôA†;;±e _}^ËFÐó#pŽÓ(ÒKŒX8²-Œ\M”©ŠÔe—ãÜ"YVóZVçË#UBK³*x>çµM“øÏÝÞMóW¾JUC=¹W^¡çŸ^UÉò8ƒOš`)(^TÀïÖÐ"uä}^b½ÝäÏÝ÷âÙ½eËf]Çãóc¾ñÉ“'‡ðŠFÂ.®X”Œa`‚Ö³¿x™±Ý¶IĨ±m‚[·áݹ C’~/ûÞrÇ4 54t»QúúÈäsè£ç 9£¯c¿gip!Ä6 ¬|±*”wù¼yISåqË©0dNÇ:¾Ûêé¦ÿµW1ÛZq‚¨µµ„eÙ¡8‚mM€\»váZ¿Áëz\¢ˆT[‹xË-H>¢ÏG~ß>òçÎÓuBMÍx<^¤Ö²|ô,8—êF©©ÅPT¢ƒ} §“–ãpF„=6ÊÂéõ0ø…¶$¬Ò<€Oh— uÅ D·% í÷“Ý·¡Ë—‘êê¬hĉÆpâ14@« Âêu¤tô¥VÄH ®»þ1êÝwãºùf¤U«Üî™(¡®íÛ½^¤`¾}¤¿ã çgÃ&<7ì@<–¬eáÒ<È‘:ò$zÈe29~+ÁÏ-8œ‡sÿ’¸äÐr6p:Aˆ"JM âÍ7#iŠßOfφZ[‡Ðê5h· +*v0H¶¿‹üù“(+W#Ü}òÝ÷ ïÜ‰ØØˆ ˳·àõ"nØ€KUQ««¹ÔÝe6\hÉ =Ueo݆oÛz»1CU¤MƒT_ùL&!Á{¼a‘´<™¶P¹Q-À ƒALÓ,‰6“ýÓ-=3}èò´ß«ªÂ¬®Foh ]WGòÕWÑO"ï–qík°i+ú+?Aoù ®›v ß½åî»GŒ½ÚÚ Ÿ8 +'À ‡é>tȬ½Ð²GÒó÷·œ®w¶Ü(xx½«ì™“™LŸ‡=MBÇ—&¸'°dø|>IUUjjjÚ¿ýíoÇ5MS'zHÔLž:Õ#çg*Èÿ‡ Ã@K&ÅÚpX\ÛP'+½½¢ûÔ)Áv{n»èô«^»Ý²zûûí¡ì‘#%ú£'IìÓíí§êàµu1±Pø\Á(¬–››¥BçE[гíŠÈ!Ãfo~£B÷—¦©ž7™L˲ðûý‡Ÿxâ‰O[–Õ8j ÏJ@•ò >oƒªÏÁ–Û¼êíÊ™³ÛUÓ‘û[/^8qþÃÞ>uîÃCÐÓÎÇ2»óm6T ZüG›~Ѳ×ÿ{N¡°Î1Í Æ/›ý2œŠÁàŠŒ½Àq+—ËålÛŽJ’” ‡Ã}³Í18ŽC¡P˜òéb¥iMÓüÄr3[Õ?M¢-Ž#ÝeÛÇLI:èû”aUV^?b#ë–Ä+]¢¨»J X–e,+÷30þ3ô‚“#6˜Ö{ìf+ÿÐv„_Ipæ¯E/Û3¯”÷.Ž Ýâ:iC áPµ®^'*.C—j{cW„9Ü 1‹k|õúæTQKTU­¶üÁ•N*Ý7µo±ôl´ŽÀr›Ÿ¦ðú„VE‘úóývsq'€ãBŠÉŠZm˜Á´Íe‰,·Yµÿç,Ì?·^IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/file_knowngood.png000066400000000000000000000203571217176075400263340ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÜ3ß|ii!IDATxÚíipÇu€¿î™ÙXÜÁKOñ&tQ"%Z²K–dË”ä+ñ•ÈùåòTÊþ“r¥üÛW¥*?SIlÙ’)Ê’E—)R”DŠ¢IÚ<’àâì.öž™Î„hçîbw‰f ±˜ÆìtÍûÞë÷^¿í……¶ÐÚBËF£ÇBËí3.ØÉùä­eíYëÙ¢RQù“ŸüäÇ^¯×¥ÔøL|=¯”Šé)ÐlÇ+„˜ö=¦ó7y/gÿþýöíÛ÷v!€MÓêþóŸÿ‹®ë ú™¥6¢R ÇqÐu·ÛÜ·oß[B¡² YÙ–4À=44¯©©ñ[–5mí›JcfsÝlû&³·²h…t«sJ©i¿¾ñZÇqƨªª"•JÙ£r³ i.€¥rFfu*ˆgsÝlû&eâï7{}3Ó}«¾[½–R"¥??ñÜØùQ™e͹4]ó Álï7[n%üéB0ÙuÙð/ò@¡@0—ëfÁdŸ ­À ·#S ¦–`Šˆ ð˜-³™ÃK‚¢´ùväæ‚éúÓàVPd;§"ó!èÛ‚™8„SAíÓ¼Z€Rk¹†àf&ÿÆ{dËd€ÛÁ LGKçÁdN`¶-A^óù† ðL•UÌ%?Lw(ŸÙ½ 00[ͽÝ!(©<@1X‰™B0›õƒéBPða`¡&ß¾ÄlFS ²\@Aû…àéç»/ÛL6÷t"¨Â½|ûÙ„`*kP>@1ÇüÙ‚ ›‰§‚Ÿn6À|in)•Lv® ˜o¡•zeQQZ€R *‹ ÞäÂ'(²‘+˜keÑØë‚Ï‚#WŠ•EEa ‚Rª,*ºTp1‡t…XYT`&Y«|jn)TM*x¡Í^a¦ú½(ÃÀb^$*¤Ê¢‚·ÅPÌQ •E?ú:~±•U"¨Ð×ñ‹‚’ KuªÈ&“9ƒ› œÏÕÀb`®Ö  (ÖÕ»b©,*êO;…TYTð”¢%È·Ég[Ø!¤ (š<@¡APÌ©¨-ÀÙó%ŠÞ ,Öuüb)*)Ù(`‚"šƲW¥¸‚W¨•EEÞŽ!]1@°°AÄmAÑÔ.–a¸Ð ¿-ìRB•EE•(†i¢+‹Š*P,[Qɼ° óÛW´y€\=üR-*)É<@)'} ‚‚ÊÌVso×Ê¢’ gûK½²¨(œÀR… PVo»0°P (¤q% .yýxx¾!(墒¢Ìä‚Bqän»ÕÀ¹B°PYTdaàÍ9 %SH© ÃÀ[}cx©@P(™Á¢ T (¤qeYøBË^+©ÏäÚ ”jQIÉ%‚r>.@çDP.âüRà¶Y œ+ •EEæ‚ê…Ê¢" ¥”3Ú$ªØ ÈwÞ¡èÈÅÊÆ.Õ¢’É¢ÄçpòL¶íÙT±í\®¿UÿLÏÏåºÙôM繌·çѸ 7 4R˜ü;& òf&Ëη%˜¦Ke?Cç>*Ýî5Ü|ÝßÀ*~†ºÖ «äʃ/²>Žß¡QE¥ÏË}~*,ù‹u5~\멸“Â7²¶8ÝíL ÈÒRòsH(÷»X¯Iþ¡Ú[ùÈúÚ å-ùÂó_YûôwkeM|wÞ|€8—9˜Õ<œ+Ÿ`²ñäÓ—øœâ6ãõj¬Ôà{~Qþ¥ç–}ø«l¸œàÕáöo®«]:;ó?áçS=ìÁÌ{ WÚ:– àBËoâÕ+Yj¾­ãúÊŽÊ]žZ«ž¾úú0Óéz·æýnÀãy†JªiÆÈ9ÙþÆl@PŠE%&¦æÚLƒW°[¼°½bgÅÏF"‰0ádˆáX”tÂétrE*“þGð+¨´¼[€ù† W™Áù‚À´L"FÈë ò„R|kSù¶†ÍÞ­Ä“qll,,bf ÍÑðËra›j³P¼èòq/¼™¼³– \€`ŽÜ Æ‘±3 ¤hó´.Bðw«|kVÞ¸O8¦ƒ¥,,ea+ ›¶kçé ÷Rí«Ri;„Ãõ2Ös/#ƒ¬m—ë0ðv®,²l‹P:Äñ£œwŸYÓä^¼éÞ²íÂçø0s ‹D?§ûNqîZ+¶°¨ÖkÂ#O-wÐŒ7ïSÀB›}s”CÄŒp6|†_ŸýOS¿=¸CÖÊz’V {ôˆ˜N÷¦/Þƒ4 ?Õ>Å¢ê&7ñ¬æðmTMôŠæãáóiæËB8ŽC,ãÒð~{þ¿9Üõ1÷W<(›Œ¥Ä­×5?aÇi¹všŽx; x@xîl|€Fcq¹Š²hÈ ÙøÖйN#¹ ó RФ¤#ÖÁk—^æýöwØR~7«¼kHdbØØØÂ–¦Hs.ÒÊåÄE„O!ü ý€t¯NhpˆD,žJ´b“(ú<@¡Aà8NÖIf’tǺxóò^^¿¸—5ew±¾l +Ž­ÙXZ[Ï`é.ÄÛhKœCym„¤ð·ÌÖ`3k·XëW¯=ä/÷¼E’`e=˜Ï¬Ýt¯Mo&}J)LÇ$m§¼†Cs¾—i›\Kõó~ÇÛ¼zþeê] l®ÜJÚNaëÖˆö3òóêðeÎ'ZɸM„Ui .Ý`©yˬŽi›Ç#‰á½ö)NÞ˜O²%è[Á•°ô§{9Òw˜€QFsͽT»«qëî9ñ^cáÞÇ=xùì¯P6l®ß†’ KXã‚w°èItq6ÑBÒˆ#Ý#‚R i•‘ü}åêŠs¥õZ¨oo¬ÿP´Ýì¦ôÄ{ëù0÷¥RŠ”¢7ÕÅë{xéäo¨pUòâÖÙUÿµ²î¦–`ª÷´›âÄàQ^¾ð+Ív4>L™×OÊI{üްLp.ÙJTF×5„Ù±]JI $uÚRW¢WÛ]ºñz,ßß{q°ÜP'5ƶ‹ŸjÎ+FnÔ\Ó1éOõñnï[ü±ïm6Õn¦7ÙÍ«¿Á¯¸¿zÕžt©Oû~ãá^ä4¿¹ô_œ‹¶ò@ÓNÊêI8 lÍÆÁF)‡¸ãBâaÏ•—J…ÙÝô |ÊË*ïjvÕ<ΛݿÇ'ýøVúX+×Sî*G 9¥/Ñ™¸Êï;Çþ¾÷ØZ{7ë*×’p#»RÀVW—éÍtãr¹Æµ^H?‰?YôH Ô~¯™IZ8ÂÐD¯?gd³N.WÎÛ\®·›H:Bkè¿¿ò —øÖßaky3‘vLÛbWõ£„Ò!öuý‘2=È÷WþåâNFà–÷KZIúÓ½¼Ýýo÷¼Áꊵ¬¯ÞHÚIs›‘éµ;ÑIWºÝÐÇç{!é!uÒ¡ïÄ@ÆqìÃJòj&ÊIz¸d&{9wKG9DÍ(íÑK|Ò{îáNž[úÔ=JÊJa96–²BãÑúlj˜ÞêúUî ^Xþ‹¥ø ß_Ý'm§Ê ðAﻼÙý ¾F¶ÔlÅö¨æ¬Ü /ÕK§ÙŽ4@®q i`žUôpL;}Lì1ã#C/>ïñçÝÌ7Ù—RЏ§'ÞŹP ñLœ§—-ÕÛ0mKÙ#á™IÉú\>¾¸øqbüÑùAwÏ,ÞM½hÄ­¹¯‡{N†!sÃñFϤ&Ù\ÓŒ¦ëdÔu¥†Ì:3í8šƒ!\㚯k:Öèý¸_%âñÜìM'8D]´šŽÜrþ¹€bÏ ¦­4×}\Ž\@× îoØÎÖš»qPd°°dKXXr™¡Ú[Í£MãÒ=¼Öù  |À9HÆÉ ”Âr,"™0§†Oðz÷†ì!¶Ô4Sæ.Ñ6BcôDÕ0™«˜"}Ýá3 Ün7²× {ÿ  ‡Ãí"Èë`vZˆ“ϲð™„Å㌘þÚþÈKG~E<#jFÇ‹/F>òsä°±…%2,)[Ê®Eµ"¼Úñ2ÇÃG¥‡HÙ)†3.ÆÏóFß«\J¶±­æš°„5"mäH‘¤+s•8±qÁ†1BÔKχCjppp@oàÿlƒ÷¬(—øŒØt…Ÿu 01EZ 8Ê!šæØÅc\h¿‚r{/ïá`߇˜Â¾#má „ƒ %ÖT®ã¡ÆGhO^boçËœŽþ…þt/©v…r1qžÍÕÛX^¾S˜ãZ/¤Àº­N"*<.ü±pÏëøéùxQm ï¨ ¯[çHß:Ü˹P aàLû…èÒ`eãô¥{ˆg¢Äìaö\}‰°äÁú‡Ð¤6"|#ÂWjä7 ‹ Õ›H’àÓkŸàï ðX퓤E%ÛkwôI+!@‰1ðlzÍn†Ô†ËøœÇïV:ŽôÓÞÚ‘Ò—©¢š½ÉnZh%ı[‡{·jZ6„í÷ûe*•jøÑ~ô}¯×k8Ž3-çp*O}¶×Îå}'ö Žrðº¼4i ,Á§ùèÊ´srø2Ôyëqiî‘,ݨö;£–¡°…C½¯[ØüiðçûÛÐ=‚õÕ›°5›”HT(9 pèµ{賺ÚH^_×u¤&ñj>ú‡9wè’Eõ±¶„_ÛiŽÚgèç£[—~Ï‹(…&„ à°´bÛ¤s¨WÔÃFm+']Ç9:H‚÷×ì¤ÖS‡µcSðÄÿ·Ô4KÅ9tþ3êjkYj/#%£š/û7d rÍéCèCŸ ÷†Z£´¾¢ì yµRìI'ÕQs˜>Þ™:Ü›·0°ó3é74ƒj_ –!e¦èêB„t–T.G– Zã§IÊ$÷TÞÏRßòq‹1Á_÷+\ÒàÞÆûYçÞLY—˜ˆ&FíÌHÀ?l‡éW½(ÝÁ%¯ÇúšÔˆw¤i;ÜŽáÑÂr¥þZJf>1{èâߦîÍ«(Ä<ÀLîëÖÝÔøëÈTgˆ%cô„º0;-ª—×!+$=™NE>$AŒ•5ˆ±ÂÛ (5eÕì¬ÛÈ%óˆ‰ƆSqúU/––¾Mj˜C6ç\¡"¤¦®òÊiqüÃDˆ«ü‚äL<þœFÅèýO÷Z!>—º@ëïâ®%P–`èB˜`ª ¿ÇOLD9ž8ÊéÄŸI‹h ¤ë„ ‘à”y‚§¡‰ñói™æšê#¥%ÇC½±C3 .ž¸ Å×~–;ÕªŽôEû2LjÍÔãÏ9¥ Á˜5¸4”-bË’mÜ}Ç=$‡St·öRž©Äm¸q4›³é3œJþ™¨¾.ü •:cpŒ…|–´ Ÿ¸Œâ2\„¯ãÁËÅ–«„žÚþO¬ú2ÕÉúHâc"¼:wáç€R„`ìo¤””{ËYZy;V=Äε¦·í•¢zDc N§óƒj`BbG ´ëÖM 4‡!ˆÊÈç´^×u¼šŸ+—ºèìíáñMñÔʧYá_…/Hó)v¶dµ˜á’&5*¼¬¨^Åcë¾DT óÞ…÷pù],ÝÔHRO ¥$$i³,–iwP«ÕÇùB„"ä ÑBèB¿¾´+.éâÊånÚ:.±kÕCì^¹›;}«©v×``8Ù”SNÀb‹¦ ®éTy«X]½Ž'Ö>Ű5Ì¡¶C¸\no©ÇÔRH)I‹íê2•¡^o@Š‘%>!`X… ËA¤¸^Í#¥@]]}œºØÊ¶¦mì¾ó9V{ï¢Ú¨Á%]Y—QIVç—î¢Î_Çz6ñÌúq;Î_NœÂívÑ´­–ŒÈŒh»tèÝØXÔ‰\ÒEœ(!5t¡__Ý“:ý}Cüål+«*WñŠXçÙ@µ^ƒK¸s"Ÿ…0p¸u7 þF6×5ß'‘JÐz´ o™‡ºõ•ØÂåÃbG:”Ér† ã{<Ñ#„@á8'Ï´PgÔñõ_g‹¯™Z­·ôäL6yÛ*¶Øœ¿énÕæÕ½,ò5Ñ\{/Oo{†ºŠZN>G¬3…Ûp;uº®“Ò„´,#3âðé.Ý…Góà$'ÏœE· ž_óÛƒR§5à•¾ëy…B WÑA¡Cà7ü,ñ/ã†<½íËx„›SÏaØ7x÷š®áÒ\¸¥¯ðâ~\¦‡“§[ŽFynÝs|¡êQêe#>é¿e=aAPJaàtöéÊr–ùW°kÙy²ùI¡$'œED%.Ý…[óà•^¼Â‡Oøñ‹>Àg8y¶•+}ì^ó5ž¨û2² >4¡å\)KêáóYO …$hYî[Á£+ãñæÇè¼ÔÃɃçð$G„>~0rT-ÏqêJ _]ùUž]´›F±˜€(CF^¶ÍiQh©ESõkB£Â¨b¥ O¯šx&ÎûgöQQäÁí÷! ‰†ŽŽ†® Nw´røüQž\þßZþ·,¢‰25"ü™8¤@©¬ÎCTÕ¬ô­áÙÍ_%¡:þ)å¾rØzR“ÊÅ¥k—9Øò Ô>ÀwV|&ãsüŸþL}‘y@J©U^^î ƒX–5-8¦êŸÎù›M=“õÏt ³µ†~ÛÛçBÝ£ˆ'ã|ðîGµ Þ¼“öÈUö:Àê²Õüpã?²Æ·¿À%ÝSzü^¯×8@ n·›šššð/ùËÿðz½AÇqäl(žÍFùÔ–™Z¾´‘4bÁá@y°l‘fjËßÞ÷~y^Ïg×>#¦VºîhÿôG®~ØõѰW¡Ä¤ƒ×4-sàÀ¤”Òqœ¬¬ˆ,<áñxdYY™;‰¶mû˜¤Ô,›y‚ùø‚…5²r—?°ìÙ¦•f¹õäÀpø+¯ÝY!Ù­©ª|gYbùÞÖ7ÚÎûíÉpª75•@`)!„©”J„PJ©d2i;Ž“Ö4-SUU•œ)XJ)LÓͧµã8X–õWÓM¶LzVà²ax(5 ÊSáÅkވǶ+Ì‹jêÎ,®^ôJ¬;õçÄPç€=h[†aLiilÛV¶mÛJ©¬MÙt/ÅRÚĶý±%›ª Y~‡@[¬öén÷Åäå3×ölh1gøŒ³ú|Å‚tòÁ—6û½þ Çñ˜æåΡxËÌ„ŸfA2yl?C²ÁÿŠSCúû›ë­1IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/file_temporary.png000066400000000000000000000074431217176075400263520ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞêIDATxœå›ÛwTE¾Ç?U{÷îÝî$bH!@B”‹:’Q'0(ØÞ €y“ýÎóšî S‘Û²¹-žKB¾˜÷4x¯†Cîw¾O¾˜· ˜M{AB6œÛõ—¼BÂbs“0Uñ{fªÜR‘Pˆò°À!0SÚ|óBÂtá©yòÅ¢Mƒ³¥-…Mîšÿ íþ§'˜‹ßûŽJ§KSJqóæM"‘###¸®Âô™x /BÒŽM:™Â±-µµuÔÖ®Ä4ͻʟJÂlu/)3)𛦔ââÅ œ;wž¦¦fÚÚ¶‘Í–L&‰ÇÇ3d^ÅÁÉ÷#‘k9r„úúU477SZZ2­bÙ: Uz* " ŸÖÎâÒ¥ÿ%³eËvïÞÍèh”Ï>ûŒ3gÎ044JM  ‰é5hl\Ç~ô0/½ô##£|üñÇÔÔÜÇã?>§¢ó!"/rÇå\$=z”`°˜Ý»_¦¯¯Ÿ÷ßÿOΟ;‡×0YY·’µëÖQ\Ä4LÇA¹Š¡á!Æ¢ctu÷ðÝ™3,+/§ý©§xñÅ]\¸p‘?üáž{îYB¡Ð]JOíqÓɼ`f"$Wq˲8|ø0ííOQQQÁ±c|õÕWóË_=ËêÕõ””“J¥‘BÒÕÓÞnZ6´BÐÜÜÌXlœžž.Ž|t„•ËùÅ/ÅË/ïæà{رc+kjf$¡P,ÚH&“:t˜žÅûüºzn°}û6}ô1t]#J“´mP ÓkP¹|9..Å%Å!I&^/Á`€šš•t^¹Ì»ï¾ËÓÿò4¯ïßÏ;ï¼ËOü”ÚÚÚE!aÑ<ÁC‡ñì³Ï!…àȇ2åõýûikk#•L0:2ÊX,Fʲ¤€@0@õŠ(7#¸ëº˜¦IIi ñDœë×"lzà6lháØÇǸxá"{÷¾JGGGÆŽä`>=`Á«A€ŽŽÚÚ¶QTTÄÑŽc$SIöí}+ªp•b$%™L"¥ÄðxÐuMÓAëºèZ&®ë plÓë¥i}3~«V­bãÆœø ïq¾hLgd"‘ XÛØÈçŸN_o»v½HIqÛvˆŽ ñù3¾º¦¡iŸ]ˆ59ñ›†¦i `Ù²eTVVâóùðz½¬ZµšÚšZ>9q×uhkÛFDZŽ“¹ã> Çqøâ‹/عói®üý*çΟcÇÓ?cYyŽãŒÇ‘zvu–]¬Lxm“œœø]Cj™t¯éÅ4M¥PÊA—®ë²ný:|~?'O~Jss7nÞbxxxNqÁä"[áÕ«W©«­ÃÌlB²zõjšÖ­ J#¥Ž¦eÝTm"üÃòUNô)LÈ«{<(åÒÝÝæÑ@H\\LŸnP¿ªžž7èëë§ý©vN:uWÂyoˆ¸®Ë™3gøI[W®^ehxGüc,Ûa<Ï(© @"¤@ÈLušèº!`bCÓU ”B“¿ßϡÇèìì¤ÈçÏð"%¶ëðÝÙ¿ÑÛ}ƒúºz¾þúkêjW200Hv·~>$ÌÛ$ lÛÁç3¹pþ<«W7PYYrP"£´@(&2ë*¬´ƒíØ8Ž RRVVÆŸÿô'’É$ííí$SI„èB \—å•Ë)«¬Ä0 nÞ&cݺõtvv¬xALgüº»»Y³f ñx‚¾›½¬oj@HGטB )%é´EʲpT¦‘ åe!>9ñ W._fßÞ×2Ӣ㠥D GêÔÖÕR³r%ÅÁ¼¦É¥KÙ¼yW®\™uU¹`r ŠRŠH$Bss ]]Ýx}^ª**pŒ¯ $š¦c§ÒÄ1,e!¥@úLô¢¢L¹B*-áìÙ0'ÿç${öíÃãñ`YÖ¤ÁÌäSضr]4M#T¢··—`0Èh4zÇÙÀt2/ˆ€©YD£QJK‹¹=tÓ4ñú Çɬö™™âÒ‰$É„P:šð {`{poi ¡Òº»{xÿý?²k×.ª—W‘L&ÈXE H2DegMJt]'Ë E˾ãÐ&WÖ0›ét:#Äè(@ÃãEh¥ˆÅHÛitË`…fš8ýýôüîwŒù%‘›·xï½÷øùÏÁý÷·0:¨„PH H‰D IqI1Á`T*I"Ç0¼$“É9ež7ÓÙÛv°mÛv0 ƒÑ‘(£Ã£Ht4]NưM×îØµqÆãø7o¦öÍ_súÃùÍ›oòpk+=ö(Ñh,§åÄŸtC'qá”ã¢ë,;a¤R©e^0Ó‘`Y®ë‚&°•²SØ–‹Ž ‘HbY ëú¤“*)•NS²u+—êWQì1hmh aÙ¨¬;0aa&fÀQÉD"cg”ÂqÀuI¹ ó& ·Ky ¶mcz lË¢¤$DEeñtËJ£i3wA'X ñäÓ;Ñ,‹h8 ®ƒðz'••üÐú°-›â@1´¶H§ÓñxÃ0 R<‹‚zÀTv ‡±XŒ`q1étš¡ÛC¤RŽm#5}Ö1hY†ÇCû“Obø|xV#ƒAÆÂçpÇÆ¦9á(M@ „Âu\ÒÉ$±Ø8†×Àð¤R ¼^ïÒ0)Ç %%% ô÷SVZŠ«ÜL7TNfMÎÜH)E,CÙ6®«ðÕ×cÖ×3vîÖàÒëEeIT™å‚î‘ùýÄãq‚ Ð=:^¯wi‡@®ð „ÃaªªªPzúH¦’ø|þÌŠ.O)Já$åå7ndMÓú¦»Z~ÑWƒ¹Îß溺,ĵk×ill$™H2|{„“Ÿž`dddb˜]yÓ4©\¾<ãáeË·Ò(MRòÐC8R’ìÎ,¥dtx˜¡¡!®_‹P*C÷xèïë£~Uý²‚y;B[·>ÂñãÇ)-)¥¦¶–ÁÁA6mÞBMÍJ”ëÎZ¦eY„B!Z[[I¥Rwî9Xn*E`ýzÌûªqÓi¼¦Éúæ ¸¶K×õëlÞ²…Óß|ÍÚµø|¾Þ] WxjÁÙ°RŠººz”røþò÷¬ihÀ_ä'•L‘J%I¥RsS !Ð4íŽÞ5ù¸.¶ºŽîÑ0tXlŒÎ+¬nXa|óÍ7lß¾}A»B >ݹs'GŽ qíZ®wuqýúõI¥”†1-ŽãL^fr'zŒMjhšåf\Óë'N‡ñxtî¿ÿŽutðhëVŠŠŠf”-,xW¸ººš–– >|˜òPˆ5kÖÐ?ØÏÍ[·ˆŽŽd,vo/ãããw̹ådö3‚Db¡)ŠƒA‰gÃa×ááæüù ŒŒ ³mÛ¶Yï$,*³º´··3:2Ì_þrœšêêkëéîîâÚµ.FG‡9{ö À]=A×3ówî)¯G×Ñdfá34<Ìwá0(ÅÃ=D¤«‹ãÿ}œ½¯¾:£<…`Qî¼òÊ+\¹r™cǨ®®¦i}®réì¼L]]=†aN,s3І—ØØÝ]]躎”ÃÐ1}^üE~JCetuu‡©\VΦ͛éìü;‡þëþõ_f•'_,ÚÉaìßÿàÀÁ÷xþ…çÙ°aƒƒƒôõõqî|˜@QÁ`Ƕ …B$I‰º®cY.Žã2>çÖ­^nݺE `ãÆHMãÓSŸñ·o¿á­·~CEEÅŒò,)s‘ i{÷í£££ƒûýïyæ™ghnn¦¦ºšh,ÆÀ@?CCChšdhxM×ñè:áðY”Û¶‰Åb”••±¡¥Ÿi‰Døè£?S^^ÊoûEEE³žJ/ÓÙ€™„رck×®å£>âøñOxâ‰í477Óܼaò~@<'òҸ®‹×kâñxðx lÛæÚµk|râƒìÜù3yä‘»äÉõPsOˆ•€¹KBCCo¿ý6—.]âäÉ“=ú1Ë*–ÑÒÒŠª*ÊÊÊðš&ºn²Ò Þ¾Í@ÿßw~ÏÕHÓðð“¶66oÚt‡£3[Pøùà¢Ù€Üx¶%šššhjjb``€«W¯rùòNõWÆã™±/¥\<¡PkÖ4°­í'TUUáñx¦-w®:—Œ€¹˜-^QQAEE[·n½«Ì™nyͤøbÜ Ê"ï=ÁÙ޹öä纹‘oYùä›n{6,ÉUÙBóRV!uæƒ%»*[hÞBÊš«œB°(®ðBH˜oY ]d‘÷~ÀBZw!ñÙìÍtï-Ù~À\‚N'ÜR’2S¾B±¨6 Ðw‚Å"dQ.I-– XŒ^±d×ä iù|ŸÍîîÿléóu„òòu]Ç4M,ËšÓ÷žKèÙò,¤ìl<ûÛ\»Ò“ïä3f|ðÁ­uuu:ŽcCaCÀcw8‹àÜ)¥êëë;ûí·ßÎùïѼøÿŒúÿc$üù_„ÎIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/file_temporary_128.png000066400000000000000000000204471217176075400267430ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíYp\×™ßwé}C7v€ØwÉ’(R¢Ly,)¶llj3/ž±c»’—8•Šóà{æÉ®ÌËLÊUNö²@ÈÿÝu‘òI‘b‚ †Åk•òŸOFKì /‚e’[Ø)¡„B÷„Ðw¿ûÝÿär¹Ü+¯[)=4_Ô ±Ýò ‚°é{læ«\Kå•W^½pá ÃÐwt£<,$IªÿÁ~ðW²lÉ%ïƒ%"†®ëȲŒÃá¼ôÒKÿ,Š¢ ëúŽ{ÖŽ[Ë0 CE pÄãñdMMGUÕ{Î[«glÔc¶“o»i¥X)Ö’h¥´Ö1Ã06ý{e^]׋…Bd2MYmS²¬Ôļ’²ê [=¾“|ÛM+ÅJ¢”þ_í÷j¢{­´µ~‹¢ˆ(ŠÅã¥Ç Ç1ÛÌ2 ,f`¥`»÷+`«$(ý½¬—Ï ýb5”ÍP $ØI¾¶B‚õµsÖ"A©(MßW€O Jÿ[! 6°,AÙ=Û!ÁvÆð; ö¥(`·¹½&Áfu•ç¯'îW^×jŸŠ¥°ºÑö Vþß V^sßG”›«‰ü•÷°JXN€O‚€{éNHPzl­²¨\d°l%çF¼A¬L[/O2™d~~žøì,©d’ÂÚJQðx½„‚Açžç²²+!Â=õWzlµt«`éRÞœ&»M‚X,ÆÀÀ-&&&PŸÏ‡×ë% áõù°Û쨪J&›¥¿€ùD‚ÅÅvÍšé=tˆêêjËɸ‘ \(ËZîíTˆUi©TŠ«W¯rçÎ*ÚÛÛ9ÿä“Tü8NDqãQ/—Ë1;;Çøø8¯½~‘DbžÎŽ~øa\.×–Êh *~X‰Ý&A"‘àµ×^#ÎÐÕÕÅ3Ïü ‚Á*l6ªª‘N§ˆÇã$“¤3irÙš®! ɇ·ÛÏçÅëõR[[C}}ÇŽ%›aphˆ_üòW«<ùä“x½^Kžy%Vóø•Ãj‰`¶òà5æV®§ë:üã‹Ì'æ9ÜÛGkk >¿5§0==M$!‰‹Å˜›cqq‘l&‹¦©¨ªŠa€$IH²„ÝfÃëõ ihh ù@3MÔÔTS[[ឆ†Gøõ¯ÿ‰ºº:žyæéUMßõfFw" J¯cÊ®n·Wl&_ÿW®\¡çàA|àÉd’›7n219ÉÔÄ$‘H„ÅÅAÀívãõyihhÀåra³ÛEQÈ)9RɉÄ<#£# `·;¨¯¯§³³“îž.š››yà“47710p‹¿ÿûŸòøãg9tèЦŸm»C¾JQüþ@É©œ9s†úú:r9…þ[LNN0~÷.Óáit]§¶®Ž¾#}466R âv{ÐU»ÓA&•&›Í¬±X@×5Q"¹¸H,crr’‰ñ»¼ñÆE®_¿ÎÁCéííåÀ<ôЃÔÖÖpùÊU‡†øüç>·égÛ©^`%,'@¹%A.—ã—¿ü­mmtwuáõz ‡#LLNrwì£c£ˆ¢Hoïa:D]m-~¿ÃÐI.& UW Oc“$ÆcQÂá0gêc6G–eì;ÑH˜¾£GijnâĉD¢aú¸zå £##;~œÞÞCtwuáñx¸y³ŸçŸž¯~õ«”î‘d Ê‰Š°6K‚……~ýëâØñã´¶´ Š"wîÜarrŠ›7n°°¸@oïaNœŸdr›Ífîaç†Åd§Ë ŠÌÎÎ2;;‹¢*446 ( míšÎݱ;ù! ‹šš:æçæøàý÷¸xñu"‘'OšÃÃá`àÖ-ž{îyþìϾŠÓéÜÔ³m–ûÆP «I`6þ¯9uêAš››PU•ép˜‘á®_¿F¨:ÄΑîî.|>/™LQðz¼d³Y²¹š¦¡ i457£k:‚†6› ›Í†fèô9@,%‹røÈQjëj¹50Àµk’H$xø‘Ghom¥¯·Y’yá…Ÿñçn= Ê…²êV‘@Q~ñ‹_òàƒŸ¢¹©EQˆÇgé¿y“Ž=Ê™3ghll ›Îàr¹Èd2d2Y4ÍÜPK%D  ‚Á  ¨ ¢(a`äÓ%DôüïêššàÒÅ‹è†Î™Ç£¡±‰Ko\äõW_Å8w޶¶6ìÁ0 ^xáøÖ·¾¹Ìç°Uëf%öÅdÐjت¿|5oâ/õ+Ž=FSS#š®“XX࣮3xû6g{Œ§ŸzšÆ†z$QD¶ËD£Q“d2YÀ4óDIB”D$qé&$I2÷å‘Äe»rI‚ˆ$H’D,åÚµ9Üw„±Ñ1TEáóÏ>‹Ínãµ×^c||—ÓIOO7-­­üüç?·¤>VÂj"Tü!/¾ø"µµu´¶¶ ÉTŠë×®322¹'>ÍÙ³gȲlVŽ!FQ¥Ø°¢hn·&‰"‚("ˆ¢( [‘DQ‹ÇIDÌB–$óó<üÈ#„ª« „B!4EåÌÙÇñxܦ^âóz9x°ÙæàÂ… –ÕG¹`  3XVÏ¸ŽŽ‰Ä8ØÓƒÝn'•J30p‹¡ÁÛœ9{–Ó§Áír¡ë殩™L†l6Kgg6» AÈ7´ ™›ÿoîÂ%"æË-É ,F0ÏD]×ioïàä©Èå²x½^ªªª¿ †Á¹'Î#Šo¾ù&s‰5ÕÕéëãöíA&''-«r b7ˆÐu_|‰“§Nâ÷ûIg2LNMòÑG×9~â$?ô.—³¸¥Z:AQTDQ,Ž©æ§Ð°¾x\X±c^”J SR躆$ˆ€ªi=v ¿ßO*™ä‘Ó§™››ãý÷Þ#“ÉÒÜÜHß‘#üö·¿³¤>Ê…ŠÝ âÒ¥K´´´R_W‡¢¨$ ®}ø! œ9{Ǧi†A&“AÓ4sœ/4Ú²žoxLie'O†% &¤ ”A\Ê/䉑¿¶ž'ÚÔä$~¿ŸO=ô0ƒƒƒŒŒŒ"I2ímmø|~Þzë­×G¹P‘1©TŠ7û9tè 6›t:ÍÐà ¹\Ž3gάªBD$IBQt]7Çûb0E¾‹WºÎÈ74yI %R¡ØÐKdóRA(JŠ|QäÄÉ“hªJ(¤µ­?ü€xʉŠÜ$ê­·Þ¢³£ƒêPˆL&K|6ÎØØGŽ¥«³0UUM¾t]–D?‚€(€HIמ'–œŸïùH‚é›Ý†±âUKRÃülj„Ü8q’\.ÇíÛ·Q5ÍÍTW׬+ö·Cˆ¢( ÓÝÝ$ˤÓiÆÆÆðxÜ=zQeÃ0Ì^Uè±fÛ•4àR¦H óxA"ˆ¦°£`~꺎®ºI2—ËÍ?¼ðï¿ÿ>v»½è+Ð Ý0ÏU5•®®nšššˆÏÌÐÝÝÍðð0‘p˜P0HG{ï¿ÿ¾åJ²¨¸BnÞ¼I0¢¦¦šL&Ã|bžH8ÌÁC½Ô×Õ‘N§™ŸŸ'›Í.륢ŸBï.ipн½poMÓÑ4 ÍÐ)¥äz>ŸßüæÿòÞ»ïÑw¸MÓ–ë%ÖÏ…—/ðÜsÏ ‡éêî`ppM×ijjD’í V öÔ°ZÚõë×éîêÂét’N§‰D"ȲLOw7²,áñz]׋f'‚H'ÿ›¥c¦ XUµ¢¹D Ò€L¯×Ã[o½Éoû[þâ{ßïÃÈß³0dˆ‚€(‰¨ªJ.›å_}å+ôöõŸ™á@K wïÞ!PSSCË\¹ruËõ±™:Ü ö|§ÐÒ4³Ç'¨oh@× “Ä¢Q›š¨­­ASU MÇåra·;Šù Ÿÿ·¤ìå놢¨E…ÑÌS¢0²ôÀåv144ÄO~òw|ç;ÿ…¦¦&EY&mŠz†v»§ž~†ººZ‰Æ¢8p%§0::†Ë夾¾Žp8\¼ÿNëÊ*T„ vçÎ|>?Uétš¹ù9Ò™ ­-­8$IFË¿AXÖhK=½pEspWU UQŠ&[ióˇ‡ÝÎüÜý×ÿ•¯}íkœ8y‚t:³L\ú½D†\.‹ªjøÚÛ;Ðuƒ@Uããd2Yª««‘dããã;®++Q1~€ááaêp»],..’˜O`³Ù¨o¨GÉåÐBã—6tÅÆ0›WUUrùÀ|òÒ©ËÄýÒ1I’Ðuþð‡œ;÷O?ý ©d2Íâ8AAn‰P"E$Ibjj’X,F}}=³³³Äãq‚Á UUU YRWV¡¢ü‘H„ÚÚZdYfaad*‰Ïë¥*Àf·çãø{Ÿ¥^­Ù\.ïWèÙEáž{.õ~§ÓÉßþ·¿¥¾®Ž¯ýë¤RÉå½=¯Sy–,‹RBiªJ{[;ÝÝÝx¼^U%‰àñ¸ ƒLLLXRWV¡bÌ@Ã0Ç|¿ß˜J.G ª ÃÐQÓþ_c6L0¼\6wr—OF$aśͼ^?ýéÿ"òŸ¿ór¹\Ñ@±·S$SѬ,2 ÿ%šÊæ;W¯b·Ù±ÙlÄb1dYÆëõ277¿­ºÚJàjØ, Òé4¦ÝíDQ2é º®ãózq»=BÁÇ_zóK@Í+ykBщþÿŽ>;‹äv{­×ëå÷¿ÿg^ý"ù—…$Iy“ò]½Tk Ðî¥Ã°$8zì(~¿»ÝÎÜìºn*¯¹Et+uU.TŒ¨ª*z^£VEÉ àr¹I¥’ùJ+i}#/ÈåTåÞWÕ•B0yï¾ËÈ7¿A¦¿]–‘$‰÷Þ{矎ïÿûƒ¡¢ÆÅν¬§SlvówqtÉ'˲L$aaa§ËE*•BU5;¹\ŽL&³çsìÚ[7 ‹J¥R朾(˜š»ª! v»Ý\Ñ#ˆù¹Òä=}•‘¡p ¿ BÓ¼^Úÿî2ù7Ãä·ÿÑ÷ïy±¿Ÿéñ»|ûÛÿ‘ƒ’L&)XKSÜùÿ+.m‚`˜ß`È6“T ˜^Ët2iJÑœ¿H¥R¸\®m‡ÇY Ë×n”¾Öƒ-,,ä+ÑÈ;\@”$tCg&#™Jãõz…ª‹CA.§ ªz‰)·–ŽªŠ(I´~ï{DO? ÿûÿðÎØ(ßøÆ7yâ‰'H$f³KW(¸‹—]Ó(~z¿Í&3pëý7o †8vü8²,ç_þ¨ƒa§«7ª“Ý"Á®ú6JWUMÓ‹=½ÐEIF–Í 0DQTTUÛ ñ—C M‡\÷Ã0‘ÍQS¤§ª EסtÝ`Q{V+q8å¿)9*Ë2N— ǃ(‰º©Àéº^ül¶Nvc8ØÕ°ðõÒ½^/ªª ª ‚à*‰Ê1ͳ@ÀŸ·ÓÍÊTUuK_€ €Ýfãö3²™§N=@wu5‘—^Äö1$ M[Ö¹—5Ãò‘eÙ ªªÒÞÞNgg'©Åì'¹\I’ÀU5­I’6]gå––H€Õ˜ºUIàv»‘t:ƒ,KH’Œ( fHw6‹¢¨æ,aµýíVŒ¢(<öØc|ýëÿQ žy[]=³/þ=•B°ÙîÍ$,yÖ»«ª*ärY2™ 9%G.—Ãáp ˆ™LQp8«æÝJ ¬U°„k½1|+$eUUH¥Ó‚ˆÝnC–m$“Iü~_¾×yÏÎz…¦i>|˜ªª*tMEÏ)xúúðœ<Åìk¯¡LM":,÷Âê’àžgIijjÆÐÍh%¯×‹a@*•F¶ÙÖ\b¾²Nve%lž‡›MfqaÃ0pº\ȲL&“!Ž0?7gzÚÖ‰¬Ù CB~Ü׳Y T}úÓ$>üäõëˆNÇr`ÕXú2ò–ƒ¹biŒT:E6“! ‘ËfI&“¸ò F¶ëýÛ—aá›$ITUU13'›Íâ÷™½>•Lât:©©©Ù±è_ ÅÀPd·›ÐŸ|–ìLŒù‹$i¹r¸ Ì®o€,Ix<ZZ[™›CUUjjkYX\dn~ކ†ú•w_`³R ¥¥…ép˜äâ"ÀTú ƒøì,““(8{¶A\^¡†¦a|âÓàõ2óÇ?B.‡ ÛŠúž%fa¾ïäVñ™æçÄgãØív‚Á ³³sÄãqÚÚÚîyîÕ°¯gWÃfHÐÙÙI<>ÃÜü'•LÒÞÞ~Ïs¯…}7¸‘¶ºÑ…B!0tb33hºN Àåt17;K*•¢¿¿ß\Âm·ãwXâ|DÑêÐ3Y<ííœøÛo“îï7õ Ž"óyEQÂá°ãp:H§R(ŠÂÂâ‹ ´µµ“J™ÛÓxøà†‡‡±­f®mº®çƒ?×9'—ÃPýÔÓ,Œ‘xë-ÌhR³ñ%Q$›ÍpýÚud›L&ÃøÝ»8.ZZ[ˆD"LLLÐÛÛ»æ}>v³Û%ÁÉ“'¹s÷3ñYœN'¯ŸÏÏüÜ<@€ÿøÇ\¸ð’¡»Ãò¹ÝnªªªÖ)O~”WTDI¤æO>KN×Y¼qd¹è¨’e›Mæêå·™›“ÍåˆD"´··a·ÙˆD£ÌÆgyðÁ×}þ½˜ ´dP-,ÏZ‰&€VKkiiÁírqw|œººZªC!TUcüî]nrúôiN:…®ëär¹mkÅÙl–Çûèé9H&“Y*×*å4004CÕ>ô0Z6‹¨ièhùÅO=ü0ñØ ñÙ8CÃCØd™C½½„#Q¦¦¦hnn¢¦¦fÃçß͉ ØÃWƬ•f·Û9sæQnÞ¸A$Åépà÷y©­­%pìøqÞzóMb±èª.Õ­@’¤{½rù2ݰ‚iç£kÈ6s‘eSñ»36†l“I$˜™‰ÑÕÝËåbrr’‘‘Qü±M=ÿzÇË=7WK;|ø0²Mbtt”¹¹9ü~?Õ5ÕȲ̕˗é;rŸÏoI¹Ö Î(¤>¦Ï@@È/1—£9ìvt]ÇëñŽDÆïósèÐ!Æ'&¸;~—úúZººº6ýüë·e÷°¸\.>óä“\»ö!SS躆Çí¦µµééiææÌ@Ë÷Þ{oGºÀjai…oÃÈÿ„¥!Î0WiºŽ(I8NTUczj M7DŽ9B6›eb|œ±ÑQžýüçï™ÞLÝì3°@€˜+Ó:DKË®]»ÆÔÔ4‡¯×K{Gï¼ûº®sôèQÒéôº½xíû­~ÿ¥óü’EýÆ— ÝÜQÄép (й‘Ïϵë×Èf³´wtª®fxx„þ[?~œ––– ë`¯H`Ùl`©âb l6O=õÓSS  ‹Åp»\„‚AháwßEU5nܸÁôôtq‚EÈGm4]ªî•ÞWÌGí·ÉÇ ö °Ùm¸Ý.DAd&e~>Á›7H§’455ÑÑÑÁÈè(£c£(¹,O=õÙM×Á¾ „µÅéfÎ]™VH¯¯¯çK_ú"ï¼s•‘ÑQ‰n·›úúzxùå 457ÓØØÈåË—‹ù÷»ß‘N§×Ô²W¢°QÄÊF³ßK’ÈèÈÙl·ÛE2™"“Íà ¸Ñ“T2ISc]LNN26:Æ@ÿú§ÿŸÏ·¥:øXÅnÇ \™ÞÛÛË™GOséÒ%l²®®N<^/MMȲÌÛoÿ?ú÷Q[[‹Ëåâ7Þ`rrŸÏ‡ªÞ;w°Ú=W.Y 85§€EQ¢®®Žù¹yB¡jDQ$63í$I¢µµúúZ"Ñ(CÃÃ|ðÁ<ûìçéììÜVýì˘Àí4ôfH Ë2çÎcqq‘K—.ííx}>êp9]ô÷÷ÓØdÚÙ“ãã|ùË_^×7Qø.œcèz1Ä{) Ü`i{‘ÚºZ4Ueaa‰ÉInߺEuu5 øý>¦§Ã  ñÎÕw8{öQ}ôô¦Ÿñc¸vâë6 §ÓÉç>÷9zzº¸xñ"·‰Çã8vB¡ Ç'¹¸È…—/pøÈª««¹ñÑ ÆïÞEÌoòTº(ÓÐudIbdd„>xÙf35| ÊŸXôî ‚@.›C7 4àòåË  ÑÓÓCgW^¯‡»wïrëö-®\¹ÌÉ“Ç9þü¦u¢õÒ÷MLàf^°SIP üW_y…Ó§¥­­•úúz<‡÷‘HÌ366Æøø8µµuÔÕ×399I,娉ãÄ"Q|>‚$!©d’Ä|ÂÜ$*¿%œ¡ÅM£²Ù,¢(Gavv–ÆÆFZ[[±Ùl¤R)ÆîÜáÎ;\ûðgΜæ3Ÿù̪!_KÖÅÖê Ü’À”nº°Qoß) žyæ¼^/¯½~‘øìzº»illÀçóQ]]Mmm-ñxœ‰‰ Þyç*.·›êP5s³sD£Q¼>?Ó466ÒÐÐ@ @E© ÉdÓ¤ÒiÒé4SSS„Ãar¹555<øàƒ¸=”\Ž©éi&Æ'æÎ1¾ð…gy衇$iÛϹ Ê…][b\.çÏŸ§©©‰ßüæ7LLŒsòÄIê©®©ÁëñPWWÇæfÒsƒ‰™™¦ÃSæ¢Ó?@%’©4’,!×?úˆl&CîÖmÒ™4™¼oÁívÓÔÔLMM5޼Ý?‹1=fjzŠ7nâr:øÖ·¾IGGÇ®úð­Â®‡…[aȲ̑üXÿò˯ðÊ«/ÓÖÚNOOÕ5Õ„‚A|>‡žžúúúP•d*É‹‹‹¤Ri”\ÃÐQ5 Y”p¹œƒU¸Ýn3E’Ñ L&Ãt8ÌL,F4chxˆH$£§áüùóÅ­»QV£lVÀN*`µë­–·¡¡¯|å_sâÄq^}õU.\x‰æ-tt´ …ðûüøü>|^/·ÛM0,æ× {éZq¿ EQŠë÷f“³Ì'ÌÍ™á\£££ÌÄbtwwñ/¿ôEZ[[×Ú$¨x?ÀFiv»#GŽÐÑÑÁÐÐo¿}™7/]ÂårÑÔ|€úº:|>.—§Ó‰ÃéÄn³å×!Š`,-4Éård²YÒé4©TšD"A$fjr UUèééæK_ümmmË‚QÊÑлE‚²ë»A0–;vŒC‡‡¹qãýý ÞFD¼>~¿¿ÏÓeÆŠ¢¹Ç¦ëù%éi  ’É¢(P[WË㟥¯¯¯¸y…U±;­+°§ï Ú(m;yív;---8p€sçÎ1;;K8f||œp8ÂøøÝüò³Òu€æ$Óiêm­Ghkk£©© ŸÏ·ìåë•i»CÛ^’`W^[Hß-€YÑ.—Ë ššxàòûÜ»AC!¿(Š8Že^D«íö§°T ,·`'½Ä0Œâë`Vƒ•=·ÒÝ¿¥(Ël U1Væ-×½·ëÆ­”ÙÀŠ‹ ÞŒÙNšù?Ž$°Œ[ua–«·ß'ÁÖPqQÁVä½O‚Í£¬ €½"A9uŠí`;÷[y¼bWïEeï4o¹®mµäÚ ™· K%@9¸½$=׊´rÀR P°ÞyÛI+gÞrÝ{?àeÞ'Á½¨˜Í¢­Êûq'ÕĨ˜=‚îcoPv3ð¾X:n…„¨X3p=T¢`¯ÌÇí’ âÍ@ØÚÿ~"A¹PQ/*Çu­È[ŽgªTÔ&Q•J‚ä¯tÜ÷l2ïNòW2 îû¶w§åÚjcï *æ¥QVæ­T¬—¾W$¸on£L;Í¿ì3Ðjwè^å­4” »ê ¾O‚Í¥ï{+ Çîr %å*×¾³V[ºö£øq%AYCÂ*Qlï% *Ñp6мåºw9­«ö2Ãï÷»À=Û³m4…¹VúfŽo´/ÁfU–é¶âIDAT§O÷Ëî.—Ël}kÔ5°cø|>! QSS3÷£ýè'.—+ ëú=’e3 ^oqÉfh·Í¨í†Ão’$)¯¾úêË¢(Šº®[òú4a§…EQp:¢ÏçsÌÏÏÛ4Mskn›a¥Ÿ`·{a9 #BN×õ¬Ý1Àì‡C’$I K;+o†aäß¾yRvõXm7ÐB™v‚J#— hšfhf%é†E´lyx6›ÕÙAÁ4MÛò®ß… +­±ÊA«¾xÍOJåÝÇê¸ü Çÿ§s”˜IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/filehash.png000066400000000000000000000026621217176075400251120ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ ]öe2IDATxÚí[=K3K>Y6S ±?h£·0EüŒDµÄÆîyAZÿ€å­/ ÜJñ(jŒAãWˆØXŠ•ˆ]ó±ÉÞâ²a³;›™Ùìå:°¸ËÌœÌ<çÌ9Ïœ~Êÿ»xpmnnþÞÚÚúU( –=ª:µ(Šbù­>ÚoU¶¢(žŽŽo<ÿ+ÿiõ{"Á`p4ÿá6íiÁ¨×ë ( Ôj5èìì„óóó XÔj5¨T*Hmê5K[§×¸™¶µÖ¿«Ö ŽÙª¤ˆ[½Û©SAQQßQß‚ ßµí™àZë AýË 'A0³ =(¸àär0³«‡ ¸põ]oúÜ-€ဠ¸c>Àîäx@2yÛK€Æ©±õŽË6¹„A§}â?©ù3ƒn!KÜp­Â£c>€tÅbºººÀëõ6Qáðð)#‹5yvÇØd‰¬´˜N§A–å¦6^¯Âá0²Ïññ±a, -£ »t< žœœd…B!ðûý’$Áíí­¡}$ÁŠ®d‚(ÎÍÍ!ûžž¶´ýýý ±x‚ë˜àÇÇR£óóóHÉd²¥ù[…HÇ n]:†z½Þrýke –K$!ÞEº&!‚2ÿÉÉIðûý†>ŸŸŸÍfM-€%XhM‹”I›™*•2XËÀÀ Q1ƶ'Dòù<ÜÝÝ™:@°XY‚Hk:ÚTt2™„ååeb$}‰$ dj-Ú19ÛY쌃)tL™ ŠfºeâfãbêµnÔ¾eAeú2;; ’$$IðõõÕx …¬¯¯Ú¯®®Â÷÷wã)•JP*•àññ)ÿáá*• T«Õ¦G–ee™$ñÚïz½GGGyKKKH™ê¶X[FFFñŸv'Ê$ àf|µß¹\ÞÞÞ d¢ˆF£D„‹tYb€s©¯;88@jtppé_PÖF¹F"ÆÃâ‚€Ò¨ÞüÕ~ÙlÞßß›'Mû ,¼+j`’$A&“1´]\\Ä+ A  ¢Þ¤@PQaõGzzzˆû®­­a·Íd2àóùuûûû°²²BE©Ã ›â¾•óc¾4#CÿEúËœ¹nàÆ½€±ˆ¤?¤E6ŸÏ#&wvv`{{»©ïðð0är9¤eÁËËKSÝîîn#_`vø©»çLR‡Ž¦R)ä~Õ÷ùùÙ0yA`zzš*õÆ â¢R©ÀÅÅVú àßü¿¾LLL@ww·#9 µó¹¹¹b±hh?33ƒìkf-¼6?\SbŠ¢ ' ¡¯¯h¹àl¼X0A¦>À̤͎¿žžžëjjŠúŽëfÈJ+år.//[jÔJûãã㈖€þ:­#>ÐÕÕ”Ëå–ë_[ÎÎÎ,£é1\[Óâ(ŽŽŽBoo/¶¿@9@žaP¤Ñ´‰Åb‹ÅLµ ï{OEtZ‹@­yÚÀŽví|Ó2A.÷X œ(Ž/އe… L.I±ò,¬‚$Ñ<îÀ­þ¥Ž¤ž–a1AQÁçóAµZm9(œIµjcG¶QÙ°··÷÷õõõC­V“I—€þ¶O£â ‚òúúšƒŸòS,Ë?cœC©êÖIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder.png000066400000000000000000000067071217176075400246060ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ ŽIDATxœå›ko×yÇçÌìÎ^)‘¬,Q7ËIÅš­Ý H¤qÝWE …ßò5$~ãwnZ @?@,M¶A/€›ÔÔ°ê(’Ân9”])ºØ¤$Sä’ÜÝ™9ç<}qff‡«%¹K.¤}€åìÎåÌyþçžÛ9T"ÂÿgѺZÂi4òÆo077G§Ó¡ÛíR¯×9zô(«««¤iJ«Õ¢Õj±ººŠ1†#GŽE+++(¥˜EkÍÊÊ ZkŽ;Fš¦Ü»w­5'Nœ ÓéðÉ'Ÿ†!gΜammN§óX»Ýž_XXø¸ß=e­ûTùÔ3¿áïæáÆœs¤iŠ1†4MIÓ”~¿1†J¥B¥R¡ßïc­%Žc”Rôû}šÍ&J)ºÝ.Zkâ8&Žc¶¶¶ÐZÏt»ÝcÌ|GQô¸ÖúÜÂÂÂɳgÏžž=2³Ðj·Nvbê7× ÇZuVSÂ9xxXk åã8Fk1†$IH’„jµJš¦ôz=Œ1Ôj5z½ÀL·Û=EÑlEg£(z<Š¢'Úíö©………­VëD­V[h43Íf“z½€R €~ùñIœrú±:­sµ#óãö}j È•ÏG5ÿÞï÷g¢(:Z¯×g£(:Ýh4žhµZçÚíöÙ¹¹¹ã333Ç›Íæñjµz´ÑhlØOn­õ¸|{“J ùÍ-fgfèCb„HS·ïS I’(Žã§*•Ê©v»}®ÕjnµZO<õÔS5›ÍãFãXEsõz}lw“[k=Þ¿ÝAšß:9ÃÜl +ÐOç$·êc»¶CðòË/Ÿxî¹ç~pþüùçšÍ&µZíP î&×ïu¹úq|úô ³í:©@ßxW¦4ˆQÈ„¯>4A|éé§Ÿ~®Õj¶©‘rk­Ç« àÜ©£Ì¶k Û)„ ‚ÿ¢xøT«ÕzˆÈTGÿ'®±¾™²tnŽz³Bj¡Ÿ‚V*P9ÑK¯ÉSYk]ù·ˆ0]Ž:·Ÿtz ï][ã3OG [}Èß$x%d“]@878?®š»)6ê|ù\ΔQç@Xëô¨VŒ†X ‚W,1§@)?øŽLq²ßkížsÎUÖ°µµ1–Äú‘µåÎŒ¥aÀŠü8®çÜþ7ÙN’$ÄqŒ5)qcRÁ ñÊ« „|ÔÕŽç'€ÓÈ&­µEÔ˜¦)·ˆÅX0íiïP??"`³¹¯LÂÉG6rÉsˆ8ޱÖŒ2¥È¦€† Sñ€ˆ XàœxpÄß?®L…‡aˆ`³dj”X7]“CÄŸW lÆûÜ Ž+SaÀap€8˜ÝFÀàG?°Ö_Ö%ú‹6·€jà.Ç‘©äÓ ~RHý²'PåÂ%:)hÿHÜ sn*Æp2puÖzj[:xÿ·#³æºÁ„©0Be>Ýs§ƒ"òseD°yHæ)u tP vÂL [„·âÙ`ü("@ë°N ƒ¨e2×<°›L „RjGç WXŠñs€Ÿ Ö¹"D~M0,‡™"`E°bÑNh…ÊÂ@q®`Mð0I°[‚´ëó"ˆË¨ï| ìð4wHf|ý­*›3õp0ÆLÅìlÃ!âpb°ÖbÅ»9‡/x8íG_œ+F>¯‰Xc"ÓJ†ò¶¤Hñ¼VÀñs[©Ìâƒs­Å?En„ítü>ýZ$C£¤0dNpbqVã´CÐkñ!ààþ¬"Fê„ÞÃ`T¨è؆¯ðJ¡•gBêe.'`RƒBP¥Z–w‰B `+q$ägSc@Nßa…÷ò9xù=p™Ï Æúr·ÓkA_ Í<å§K§ï üàTg”Ë@ìW.ó¢}|ï,ÎFÎP 4åPŠa3q¬ L€\y­õXq/›1`„É-¢¼TÄ]_ÊòÿÅFßbŒ0I¸qh´ÖS7„ÅL@H`Ò” ç4ÎzWç­¥²Ä:Ö{ÖOŸ Þ5…‘¡Î~ý¤Q Î̺‰SLj© ±Ïûs¥qþ÷û–Ø8þ!O6f£d7c¸£ RzÞ90I‚5kdQ¡–¢<žFk]ëõv™"Rðþ½o°±–~¿‡s''å½õFWeAVÂÝmCšJMÁ¡ˆ¢è÷jµÚÔì@êIÒÇ:‡R^iA²„(õìšÖ°Þ³lö]Q<™´ॗ^:1;;ûÅ^xáO£(Ú3+ÜÏUæW’4%Iœ@ @‰Ã8øuÉ–À•B”° ÷¶wÖ$¥ø3ž€_|ñËÏ?ÿü__¸páT³Ù$MÓ2#–¼Ê¿G‘/Šä[mŒ±Ì·ªüöIÅõ­-‚j£E"šn"ÜÛN1–b:øM6´8Úïõ¾øì³ÏžŠ¢ˆ$IPt_Ÿ/¯ äLÉ?çç«üÁ©˜ÞÖ}@pøé°[V;)‰‘AÊ줨L=|òüy•u\/ø¡ ‚ _ É#»IÜœˆ`L–êZK 5AGb,›=Eϸ"ý=èÈç2€¥ÅÅr„©¥”Ò@pæäÉÞW¿öµ@ØIçqª>.¡òZ‚Öšjá2PÊm9JiDÁz7e+‚@£‡÷ÁHù0™ÒåÆÇZ)ˆˆVJi¥”ÕZïÊœa D¤PzT¨¬”"¢(*V‡óiâ >3ì&¾4¦Ëá°ñ;€„™ò•’Òù'ÈÈ@Ð"¢›±aWÉ©œ÷s‘Þ¥ùiñÖ^ž%ºà» †‹ÿ‡ˆxPña@TÆ#"#RÙqÞMʶDk¹G…FeÓÇ»Á¦™Œü:–äÔRvèwùœo„<ŒŒ*÷ªäñ¡Ó£3>Ùùg,Ép@¿øZV¶ D€àÁ¦Æ“½ØQ(¾ã(ƒ’PxÏSj3ÿ{âåtñ´/ƒ05&;k ‚(…à“&+#‚—`Ì ÄÙQᨲÎíj2ÿËÙdÙMjåwB©| À9$s‹C-”Úš,ÖW–—°‰ßeâÈY‘ªND—;=N:¼—Ò0ˆòkƒ£dŸ¤X"Ë#?¿/ȧǒeBZ ¡V•qûQøó„¥ÅÅûÙ©yàHvOÙ&9P= ÐðÊrÙ“@ÙP,;ûƒ4yj¬è¥®»Ù³›w·Ì•qûô@@sey9^Z\\Ï®µ€:C¸CØ€‘U`t£å@*¿†XøRÐ7Òßì¹õ»[é•ôöýž½ÛéYãœüËXZ\ 2ÅâÝcXRÞÛÙGînJº6ü\ù\†„A€R°íH6·ÌÆ'[æÆJ'½µÞ³wÖ»vÃ:1V„@©†Vü‡ÖêÇcê¿k2Tf€ƒ HáÙîgG)¸—Òe ‚ÀÿC…û·?Zùð—×?Ž;Qcýý¶¯m§²n„TÑJ«Dˆ¼võÏÿðÇUFàðÆðNv½lf!ñX£: €a*• aÚN§óÁÝ;w~vëÖ­K—ß{÷½¾úڕΙ?þ³OöÜï®®ÇwjQPÑ®ä;¤œE‹¤¸ö—ôú$Ê 3†ÛK‹‹7p8Æ Z PjÇs{òžáý(Š~zëÖ­ûæ×¿þ_¯¬Ü¼~ýú¦µViD› ¦[g%ÒJU EPn°ú¸ âüí¯þâó—&Uö¨dÆpHñ.ò$ÐVZ·•R´ÚmLöÏQ£]ØH¹ª”zODÞÞ–«Õêæw/^äÍ7ߤÑl†ÕJ¥å*•Š'J…ƉÒ¼VRi˜êµýþÿüð[?=ˆò{`–ïeô³Qµß¹téGßüÆ76>û¹Ï]˜ŸŸŸ{riéw¢(Rà drxøwà-¥Ô`£îöû}Þ~ûmÚí6a:ç\¬ŠLüò˜s8ëpÖ¢tP‘°Ö>xõbíçß¹ß:¨þûW„®,/»¥ÅÅÛJ©"Rùþ÷¾÷󋯼²Ýn·ç_þö·ÿþË_ùÊÙõõuŒ1+J©Ÿÿ ¼¼¯”º—·7œÉ5 ^í5nÞ¸‘לR*ÉìL5Fœx¤R…ð~íƒþnýÊß\=vÌs02è--.~¬)¥‚F£‘Ôëu×ïõn^¼xñ««++Ÿÿ“/|á'³³³—1w´8вÒÃES­5N‡~¿O»ÝΖ|°xÖ ¨@Î:¬èªuênãÚ?}§±üƒ›TaïÒÄt(a€­áógOŸ~ëK—ÞúÌ3ÏpìØ±¢V˜Ëð¨ÿð|úˆxDuEmfFâ•ÿž¹üW¯D÷¯Ü†ò0¥mrµ(¢E„a¸3Ÿß„}E)å*’оñÎcm5û‹·_­v–7¥Ò ¼Ÿø02Õ½Âù(îÂØm)…Ÿ)Þ¾üîÚí_¼[56PSR@M{iûÿšü/¹2œü KIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_128.png000066400000000000000000000136041217176075400251720ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËKIDATxœí]]ŒÕ}ÿ{ï²fwí½ÆkƒàÅÀÆN1(…‡£‰ŠDÓTj¢¾UAJ„D[µjÔ—¾4JÓ ÓÐD_*µ/¡‚¶ˆRªz Ni &ǰÛ°xü±{íýº3ç߇3gæœ3gæÎ×Ý;{½¿Õì93sæÌýÿÎÿ뜙ˈ¸|Qéw6Ð_là2G­ˆJcET³‡ÚGDuûÔ|yËÕ»ê·Ýò¹ÿþ‹"Ìw!Ø@6:thÀ$ïØ±£Þétö×`ëÖ­€z½ŽŸžjàÜR•Jeß|‹^ð^Þ6°"X´¡ìP,—]õz}²Z­NnÙ²e‚•Ÿœs1Î9\×ÅOO5ðóOqçî­øÊä8V\Âk C=r ^ÍÛÆ ÓÓÓ“°¸R©LŽŒŒLÖj5ŒA~V*Ñ.ç<´ÿ­S ¼ùÑ<îܽß=0‰',9NÀ0Ü@5÷=l i\­V§Qã âèé‹xët¿¶kß=0‰¶"x‰aF[²Þ—ŠËšE ˜1–Ù®¶]›[‚Ÿ¬ã;÷íB‡KmG<`†íÈt!M€2 ؈Ðìp9±€csK¸wêª@ðàÀ!„®[H Ö5²@!j:+äµWÛ.ŽÌÌã—ÛøÊãxèÖíhs`ÑÖãE'£ó˜ì(5¦§§ex$? ˜1ú”½·_Q )‚oáž©mxèK#hsà’# jžDcýr¦ ”ŠžÀŸØ¼yó£Û¶m«° ØD”€û-p ›àüÒ_ð¶ÞìËœbèuÓ¶Ò`zzúѱ±±öìÙƒÑÑQ_UªÂ‹d¿!ø ˜k‚oº@£môt¶Û µ¯4ðÔž={022Îydo_/˜_nãÕ÷ÎaaÅÁƒ_܎߸U¼„¶n‘*ƒÎ Š96 JA€éééû&&&&GGG×½ðç—ÚxõØy0ÜûùmØYß„U˜o=>³‚"‚¥·Ój€±±1pÎ5§m=Aôøó`ºu;¶Œ aÕ.‚7Çl…JQ”†( ¡ Þæ”ojàÈÌ<~÷®kqõø&,;Bð@`×Uy©wÔMŽR˜( —§%ÂZçÃÏ–ð¯?ÿþì‘[€JÕïñA{Gi Æ"ԽФˆƒJ’(áªÇ¬ˆGfæñà­ÛqE­Š³Í°9W…¥|bD„{¶rž¹Õ:J1#H¦E³w~ÒºÓ´AË9Ç\£‰kë›°ØQÔµºx4;±z 7µ\=Ϭ·”‚Y‘Eh¶ãmdêF(9V¿°ÜÁM;Fá(Y<› åŠI›—ï ˜‚¶™=~ L@Z PÄõøG·ã”pOøœs8ŽãK¯å‡1ÄŒíPå]ö—ô3…Qùƒ<( Êz]y y]×U„Ï]RB¾0½ªM2Ht‹d=qÄ(¥ @¡ ^öx©öå:I]Ž@ Ä,É£·EÚN3dV¯—¥ ÀZ›€nP…ï ÜuárâÜâ'Ìö’øaz¨˜‘á#ˆ_ce¾­×»®ß¼I"=ñÃ<é‡HaBΠBRŽ“ûŠÀ ¨¾UåÃl/ùÿÁø¶ŸÔ±}í”1*‚8ifÅ–SȃÒ ß$PÃ;Çqüž/½~yLlާ骅ZOö¤jª~ ÎI„ŠYñ 0H ,0U¿ÜN-(¶ÐÔá^Y·Ð$•$Â@M +Cï—ŸRå§>`„Ò Xrû̈é}[Ì' õ|@'F^”†ý&Wœ<Óæ'…ÚChAÝBmЈyÚÈ“ôÀ‡e8Ïôíjcõ†Ó&ÇüãÔ½š0òÓÅRÏ[N(démEÃñM½’mƒ…±)›ÓÈ9›–ð@™€²€ü®—Æ$IÿÖ©]±0&‹¨§KûUÏ@is4®Ÿ³€²j®iãÐU»¬Ÿ©êq~q`ÿc¯WJC€~›€ìP4àgþ¼Uõ,¼òòIÑõQiÂP ´L ·„Zœ'Ïþ[ì¾Z@y¥!€\Ô1úõ0!T‚' ÿI"Õ h›døÇóI==\g”‚QXODò'-$‡w º Ù{møXôl™zÖ5? n*¸›°>ˆ`$mÀˆ)CESÄI² ÿDº—‚1ÒÉËÒH23¸_PÃ@™øQí´Èî)'0‹oGw¹ç;(=ÞÈÇ%”Ò¢4Hv-VPúx„·o›#ƒ²"/­1«u¨u]Ž îÜ~Á–Ò~b&Já ï_O¨Ñ ¼Žõ’ŒX÷0ëèÛËL#mÎ’Οj&¼rÑ¡çO©T­.(¦ËÌ L[°öD=S7š­fÂ!dÖÛ$¸Üõœ>“!²žP&¨v—‚½@?ˆ ioCM3RÈ];¨½ß4Ùg ìœÀ^e£ˆPÜõtÁÅÞµíþ¡,£¡úNf†}²Î‚3A¥!€ºÞ‹^Û-Ï—„>ѼÿÒñÓC÷j"×bû…¹ íq¼g šV¨©à2´%ÉqâSž£íž l‹û]c.„î)ZCú"kh$œr¢4h·Ûýn††8Â:-\è$…l#€rê™Z¦†{¡ròž &Æ€Ò V+ESB0‰ýÔ°÷é÷~fènE­3!ÄíWaó½åvq>S)¾õõ0œô™€ üÓ½:Y&Õ¹èýJ®º¬ÕpQôþ ,Xî§6Pˆ‚1? ¯hV€‡ËÝz ß: D| PL»7P ȶâ;€LËøi~ 5oF>ค¦SÔ„° úöÕDj³Tß püÂ^¿¿¡l3R·ÄêR½(²S&"hJÞ’õ‘Âw]e²GÄx¬OîSïn±Í ²þ¥ € ëM#pòÓ?¡I€ŒÄä!ü sh>&æ“ÂHË38‹­âÔ?P˜™À¬>A"¨I¨\¾ˆšº5ê!xª_ÉìÙT¿z®­%‹m²Ï;ÈR 4 šIfEÇóÙˆ@í…jöO¼a$¸G´aa© 8´Ùƒþ~i .®z­ Z&°—HšÈév^’ã}µ.u9!w\Ë AºWõ4­ 4µÍ Ëb; P¬EØ3³â P0 DØ»®HØ,EèåR¤3`aÕ¾‘q̋ˆyÑM“è3‚”é݆M·åw"®èÿgM7)Í/fXˆ 0?ÏïÙA­k³àuÖOŒ]¿Ô"p_ÛYJC€õ ìÐ{8„Ú'½ëIáàT«í7V/¬¸Áx’jd( Ö;|+á^°S7V(LPI±Øâè¸*mŒäANò²h3–κä¹^ÿ¤‚]—kïôC6ò¼"í%“ò¹/8>(¿°â*ûôýE`]h€´©â~d'ÂæKãN°vÍðgˆÅGÛ ‡~éª=9oΓÖ¦§‰JâG0³G„ÿú P1ÍM9X´ êšún YÆIöþÔ· ¥!@/ëMB„HSâKÅ>5Œ{Ñ‹ßÉÕ´¶º"ã|fñä-› «.:.é¥f%JC€^Úñnóû]Û çND\Û @Kü0ï L@¤'(sm—0¿bϲ ¾F×)¢¸ÞëdµA,[eL ¤ì™Üå—iu8»äD {Póûú݆$ ®ëŠ_ Q 1O_÷æÂBôÔ¿ô mŠ ±ê¢eÎøé¡P|ùºë®PŽÉ6:޹T@€ªöf!lËT?bÒgg5Ž…ÕèŒ(EndGß ðÔSOí~ôúë¯G»Ý.%8çè*ðLŠ7–ËAþAô[°$nüÙ¡2Ó¼>[r,BîmÐWùä£;vìxáÀÎ;ýLsªØ„˜Ö“Ï2±ÃqÍË»æýS[ñ““ŸáÁ;nÆôÌ"®‚þ> ê×Eó+–Û 'zA„°¦?IDOìß¿Á¯r$˜VDÎ?ÉùÜuÑétü‹HrÎp­‚nÞ‚óç>Ã7lBÓ!´ R÷$²zbˆXD Ä .'|¶ØÁR‹C;8b!ùúBP^ÖŒ{§¦açÎ…ÏL›P‰ÄéÇe|sùÖa†js×ljaÛèÿÎ9ULöAÛå8»ØA³#ŽºÈŸ›ƒ_…É¿w&`ïÔTh±v»J¥ú’×þ•.âËt]W×DŒuýEÑ( UÖ^ÆÉs«øüõÛqn±£9} Àr›ãbÓMø“/1”‘†Ð¥vñçCëæ´½'ƒ*x~Âää\ êíJ‚áÃÙÆnÛuµv®ËÉKò¤¨Ïsû{æ&€"tuâ ³-IU^>®^)x›ªT*‚Õª¯º9’“@žÀr]Âb‹c5ÍŒÞnÎ^?¢£wÑ–ee»€Q*Ÿ£("¨¿ÿg¦š¨V«þõ8ç€ò‡$ÚKbµãâÜRÇÑKŠÛ,^t%€ÑÃa¬«‚Ž"€¿Î9Ï$ɬDÙ÷.Zjµšo"¢¢8ÍÐì:¦ºj¾Ÿè"àØ‚lΛ‡(AÛH`n3 «+'!B·ÞµÎJ¥"|庪ˆ¯W÷ù½Úƒ]ÖS"4Kl‹ Ê(µÅ9qQK¨§ÃN’H0-L"˜?ö˜Ò䜣R­¢"SÓisÒ ð7¢뺧‡^` Bh„NbzwÄ¢Õ•ÕØ þ¤{/&“Hrù‚d¨#öœ.mîv½¢î¸æ-.tÁ)T;,¶íËcÔ_ó\«DRžì#!}©_Û¬ÍrP° @ ñBŽUí]öùÛI5€´ÀZg ™¢¦™Y”Â|tÛ]Ö«¸BäRï1eþ>sd-jé ½®Ìßg¨³ëTlb¨ ê-Ø KY&- 3Q£ý@/§Æáia†Lqý®f!Ô0°‚ô$ˆUùfYÞ0°(ô^ËxP.ãßxׯ»½/Z´8Ð…_E6-`;Î/££€´X3ÓBê+Ö„ÕY´H¨hÂK[C@ ߦ ±žÌ \cû¾Öþ„ 9+ å­Ó@ @І‚N‚´¡_ìöZ˜€~8‘ökf´'ÿ_¨´pÔü1Ðî ¤ñ ºn÷Âô+jˆ¿¶7i#[¥Ñ»B+ùQ;>3ýü¿QµÍ$ñ„°®aÊ ð$mHJph~"Œ Ÿ™ñ‡¯!´@ Â4t¼2B@€ª±˜å¶cªªYL@r²êg÷’/ïÿÌC¡™@ öNMÉæÂ<Èž,©ú@ -G€~ 7 yˆ—lÞ^Ö@q°Íš `ûI#½ß½8 ò·3º›&¯º÷ßUˆž&ÀÞ©)aT `æ R‘ ,‰ (MN{u)¯ÑÛ4@ô´ðã33&X°ä-+еƒÍöÛÖ+ÔÇéàQèAÊ§Ì êSº/J­-‡_:»Ø9vlnõ•WŽ]|»ˆ–&™(@yGB¨CÞùQ>Ì2^" ÐkS”™TÊ)-‡.5VÙsKÎì§ íÙ Ëî%E%´Šhg,ŽÏÌ2EÌõÇû”ÝÙô `YúlÊ“ ІËѺ¸êΞ_vfOžk}8¿ì\ŠÈ­‚á½"Ú˜fZ¸:¾Á(bEù¢{?€â¦„%E_NEÕw3Þ.§ÖŦ;{~É™kt>=Óèœöá?sâ/}?ȱðz¿´óÃÆŒp%„°%ˆÌO‘ ÐT°ýºöqûK«îì¯.u>œk´=GÖ¨Ÿ¯ÿÃÞ=—³¹>’hiã% ®ô© lêßü”(¤Ñ*úVF^ß ¼¸êÎÎ/;ŸþòRgöä¹ÖlâzÕ5±1Æžùè¯î^ÍÕ`I *3ù©†…qÐÊòŽô[Ø*¢ÚÒl;~:¿rñš«œö?þïù72×ïÿÌᙓ]¬ðäN Ì ´ BBé De­Ÿi±*#lž½ëºï5›Í7þûß_~ù¿}·5¾çŽ{Û{]›yJ˜~Ú€gN=yoáÂ’k!üEóa 6!:!uÝœXvømTÚj ü…矿¨tóoŽK¥iþ2h÷ †¿£§ŸÚÿã¬íO‚®ð´Güq !Ž8„S(#ƒH€Ç<\b|ì¸îOÞx÷wþçßÿþ,âDªpF>,Êܲå£ÿÍ}=>0 ôH—h*eRD™„õÒëO8LD¯µZ­×ìß? ñ= !ÈnQ$¥2„> y]}ëÈ'?ºÿ_Ò·>=çŒÑBù[ïòÍN#‡WxŸ²î² AD‡¼àÅz½~ZîPÂ`õÁ5熜Ý_Hzç ôÜ'Ox+å=dFê÷xHdd ³‚.„sè@ä FD ðÖÑj6?ð…üÍÎ…¼àp½^'ê@Eóqˆ{“¨!ªc3?LMxFü¹‘ÿøÎÑT'åD¦Dx_Œ#Þ©ü‚¤“(¿Ÿ?þü›o¾ù…»îºkWÖgÄ‹=üðøøx¤Àc µ›Ôrˆ Š«Œ;ÿ6úŸ}ÿĉ5U“™ßâ™×ÓÒItøˆÌ¡Ÿ0ZYYYzâñÇÿô÷¿ýí{~ëë_¿obb⋹ïÀŽÃ~8OEF( èûÊSA‰@hVœågǦÿøLžvfE!^¹÷ˆyBØ›l0î-Ò9”d“¤t&Ùý\³û¦›øío|ã[W]uU–&FA‚‘¯Bw }w榯Ý0uÇÝýÎ]·_û£WN}àW`óÍJûÒ³›_ÿÞ§¶÷!»B^¥øò!™4jBh1ˆ/ Þþ6°éC‡§OŸûÜ 7|ëá‡NrÉwà }||üÅ"î!!¤¶b4ó Äl#; ¬½ø›|ï ^øE¡°·„YL‚ô2DI^Ë ‡ô!€¡S'O¾¼¸¸ø'®7ë&"_àŽ[£¨v'…1SJ–\¯~ÆË˜(š«5fþnóÏž^ú'| ï 4¢™A\†ø‚ÁœyŒ?®ðÒK/}õöÛol÷îÝ·5w¶nÝz}x”È@†Àªð*ĘŸÍx`d®ºtæÙÍ?{zè¯ð½(RÉÊiårn!à½y Æ€}ð‹_ÌüÞ7¿ùGòÙëÊ#<´¨ÇËûÙœ@¢cµå3ÿ4~ô‡+²}}E~ÏÞªr퉗>y÷£_ŸØ\¹f|˜Ãiÿ³'|zÿÄ ’o!S—~b=ŽÎ•Š™S;•6Æi¸"~!%+64@P¨j¹ ªçŒè÷M” {n¹ÅïTïŸ8ÑÓ'aŠÝÿgÌ1\¬í3ÖIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_documents.png000066400000000000000000001203561217176075400266640ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½É¯$Ç}?ø‰ˆ\j{{÷ë…Ýì&)Q¢¨…$É¢~$Øacûb_¾z`ø>Wÿs@7þx`ؾÍqF $k£¹5›K³›½¼­¶Ü"¾søFdFfeÖ«×ýE‹õm¼®ª¬ÈˆÈ¬üî› "¬a kø|‚ümo` kXÃo‚ó˜DqÓ<5¬¥˜5üW†ŸÿÇ/_£ÐëD´Âk¶÷÷/áê•ýÿ3ú߇ ÿ÷E¬-ÎyÖ` k膟ÿÇ/_·oùUàûåg„~¿¥ú½>%ÑôñÖƒ®íqe»ÿaü€wÏ{oç"¬a Ÿgøù/<g^Ä.J„GFˆ¢Q" C~Gè÷zPJÕæ{t’á7Æ8˜×ö$¤WN |k3X€5¬áS‡Á ,ªSÁÑ@pÿÕ"{Œ1åkQ0Æàñ8ǯ?ãá8Ã¥Q„×_ÙE/T@R¼´yغ&køÜÃüâW¯[%òuB|ÌÊG·Hýljjëãq†7îÏðð$Ã(Vøo_ØÁ­Ë>Ÿã×Þ›aç¥áù_ûš¬áwþã—¿~Ý"ÜëÌÀñ}kµzü¹ËψàD­5Œ15¤–’lB! ”‚D„<ÏADŒø÷fx4ΰ¿/ ~a€€& íçok[€g„ß¶t Œà`kÚë@D•‘ÍBHô{}H¥J½»ßïAI~mÂ*î~{!‚ XùY8˜äøåãñÿûW/ãò&™ñ‰ ˆ$IsPKç}X€5|æá¿üõk¶©Bèï½Î¯Bôú±Eè>¢(D¯×àN ïBpǹÝßY¼ døõ‡'øä8ÁÞ(lEüÜnÀüÞJ,PÀÖ3-Þk°†ß:üâWŒàÜë7jŸ PD?îA(…^#PqC‰8f$òVk]{ï#¼?ÎwÞwÍðÞ£§¸²ã¯^ÆÞˆQÏGü¦3Ûÿ ܸˆ½­ À.~õëß¼FNÛD`‘<îA ý^ %%z½>¤’è÷z%wv¯ZkE<Ï‘$ Û“$A’$¸zõjM÷öEöO î>šáW`šhõ_­8~^‹ˆïؾ; ªcJÐþEìqMÖðÌðëß¼á8µCô‚€R½¸Hôâžý܃ ˜£7ÁqkߊîDuÇÝøže’$Át:…Ö<Àõë×!¥üL þÿðÒn‰ø 7@bD¥røò¾ýá™üذx“ÎÖ` §Â¯ßøÏ×À…¨¢Á¥åØJ ôz=þ¼‚;$vÇæä>Ò¶‰îEQ`6›áñãÇ8>>F¯×Ãõë×qéÒ%ܽ{³Ù q#Š¢s#§Eœ¾ÿx†_}8Æ4]D|Fü‚ò |õêï!Xx~°&kÀo‚Wn±+: ‡C„Á€]UÃ[ÕÏ‚à‘Ô^}$•RÂSr{w~QH’GGG8<<„Ö×®]׿üeÄqŒ$IÐëõÐëõðàÁܼysaͧ&â7?¿ÿxŽ_4Æ4Ñxa€ö‡5ÄÏ4  ©añzĦÚ˹Ú|à7o¼ùº}ë^¿o9ËëÕ6´ˆ=Ú×¾}ôæ\ÆÁ4¼ ýsÜ|EQ”â¿Óõçó91™LÇ1^xáìîîB)…ñxŒƒƒcpåÊlnnâàà7n\ˆÝ¬„&â¿úê&†1»ê ™a>ІÀ Ö~†_X€ßxã?߬"ÙøÁª%›`Q_ ‚woÔsk8`nŸ¦)qÿþ}äyŽ«W¯âK_úF£²,Ãd2)÷EQI0öööðî»6ï{εkuª ò‚pÿ0Á¯ïM0M-âeÃ^…ø¹çÎk›÷s¦í¬%€Ï3¼á8¸¨ûÁ¼îtIgTc]<.\*Ù)¢»W‡D]ð4ÞMK¾/â;½>Ë2Ìçsa:¢ßïã«_ý*.]ºȲ ÓéEQ”î;?̶( ìïïã—¿ü%ò<_H´9Ë>ËÏŠÂàÍS¼ý`Ь0xqˆWoÔ?3@nÏ­Œ}!öx«Td_='À…Ášü–á7ÿùÖ6@¯ÂÕ¶Då.{Í=ҹɤ@Üã×^ÜûL!xø{q7nOŽäyŽ££#¥cøwRB%e»gÀm_œ¬ À9ïßxó6€¿lpc•-îõ ¤D†ˆÂA Ã…yšbr4CVÛЦÛ;„÷¹ýÉÉ ŽŽŽ¦)vwwqûömlll@J‰ÉdR"²ÿç‹ú>!h»î L&“…Ì»¶ýúßg…Á[÷'xëã1$€/]á¥kC„R€È`žH PhS!¶ çº,‚²’Š”²ÆåÝri–B¹¾ÁrßZøŒÃ¯ßxs[ÿÿ«0°µ¹‰Á ¿Á}±¸ º\eŸ%h³äçy^^—#bÓé>Ä£GÇ1nܸëׯ#ŽãR÷wHÁR££/ú7Ç.]º„Éd€‰¨”‹å/Kä'Â$-p÷“)ÞüxA„—®öñâUF|“gH„DJEajûØm)ðž dÿ–YûŠ¢€ @*HÐâØOáç^€s‹üÿ€×ú½Wö/—¾òeþ,VôÏ´…çú‰5ZkÌçsL§S"Ïsìîîâ•W^A¯×+ÏI’¤ þq÷`ÙýjC~ó<ǵk×ð³Ÿý Y–-Ø jD)-ð«Žðþ£b%ñòs›xáÊ¡d5B07€€RaB ±ˆÜB@Šú±.nNö` u*=kàÚ ðüd‘ÿù›7 ”jÍ.kãBÿ¡)æ;¿½Cz¥wxxˆ'Ož@)…ýý}\¹rƒÁZkÌf³gv¯]\¿í¸#þ~¤”˜Ïç¸zõ*Æã1Æãqmn÷7Ï ~óÑ î>š"V¾zs/\é£PJ„@J…!RØÐ\á‰ù@“ESùŸ÷My]xŸ%b¾Z³0Ì›s¥ ¡§€5xF°A6Ea‰ü¾Îþ»‚øM¤÷zîs–e8::ÂãÇ‘eöööð{¿÷{ØØØ€ÚøfŒ~‚»ï|Ž/¥\ ®¾= ÏóÒ 8N1ËÄ Yªñ›Opï(Á¨âÛ_ØÇ­ýBe{F`NDB €h‘ÅWŽÛ9e ì0þ]`ôo ÖàYAà¯@Àå½½ßIä_…Û'I‚ããcAJ‰çž{—.]*Õ ,ËZ xm†¼&W÷¿ë‚æ÷îž÷z=<~üEQ`ûêóøðÑï?™aØSøö/áöþ¨ü #’€‘µ¼€³ÀÖÝÇg‹æqî=p†SÏ ÖàYèOT °µµù;#ò·éöƘ’³ú~ûû÷ïc2™`gg·nÝÂ¥K—Aé–0ÛDü¦Õß'Í}6ùómmmaëÒ5<ÖC¼ýî Fƒÿã+×ʲ[k`ªM]N8ÁrþØa³[ùÛýû­ó·N²V>“ðÆ›oÞ†ÀöÆpµö¿"4=¾Aωøóù“É‚·nÝÂÍ›7ksäy`ÑGß&¶/Sš¢~š„/ELæ‚k_Ã[‡s\Úñ­/lãùË•a63@j8‚ï©ÁÙÃr$mñ©ñçù×*À ¸ ˆV7_×ú¬A·÷ €óÇã1?~Œ““ŒF#<ÿüóØÝÝEÇ(Š¢6G—›nQ¾Í0Ö%%´]ü?ï'H³.oÆøý/nã¹K›¼©&$zÁ*çÝ"êQã»…«xJlí úYuìyÀš<ð£0:9ÕYàÓ„¶€¢(j©·³Ù ¥%ÿúõëxíµ×jñõ.`§‹Ø-sÝ5Ç´Á2ß}vsÿïOñdZàÊf„/¾0ÂþVŸ½ DÈ@jºeì3GáE õOCÆe¿²®[ÁW>üvwž°&ç~¸i2,‹\û4 K·w¿(ŠÒrþäÉÌçs ‡C|ík_ÃÖÖ‚ (ÏsМÓí›ãšï}p¢ÿ‚MÅºÞ Ù ûýÑÜàÿ½3F?øý/îàê–1 `¦$çᬷ7HŠÛ¥ýß—Îlæóf:ûj¼Ö䑵 à3–\ÚW:Oû A[”^3`ÇYò?~Œ€ˆpýúuܾ}ÛÛÛPèpÐ…¼§}ç¾wûi# ¤Œ¸‚Ñ2/€yNˆ À>Hpï ÁÞFˆßy¡5¼&H ÈH"2é„êäk¿Åb0ϲ_÷©~Eª¿mãümÆÄó†5x ¿ÄËÓœA„ Ù…Æó-ùé§Ó)ŽŽŽ0ŸÏ1ðÍo~³Dúæš¡°§]Ç2CŸÏÉ‚}ðB…&$!) ’œ@ì(ößyœâッXá÷_ÞCÈ"Æ9—Þ‚ ¤‚6!ÑâÆ[ä°]¿D‡q¾v¬yùMq¿ †€šŸ¨ëY(£ÏÖàà¼ÐöYA¡š -š¯yž—.¼ÃÃCE½½=ܺu ›››ð¦*,ãкbòÛöØÆýM)j“kFø$3È´½P T€ ï=œDøÆ­]›¬L Fþ²Š”È‹(Ón¼{×v?[¯p5X¸=Þr­^ï<²na â§Áý5øLÁ2BÐD0ÿ³Ÿmç8½3èc†!²,Ãx<ÆÃ‡1N1ðâ‹/âêÕ«óžf€kƒÓÄÿ&H‚€E}­$'Ìs$3ÜK=‰A¨ŒS¹&¼y+Û=ìŽ8ç¢#?¨TÍ„0Ú€Èâc=‹aoÑ`Ø´ø¶xˆ¹:¿·`ɽ[g~VáŒü*Ðf$ó9»ŸÞÔÍýqÎ'ÿÉ'ŸàøøD„ýý}|õ«_Åh4긜§CòÓ|þÍ9¥©daž¤¹Aª $¢@¢IÄ€Â6Р2jîþa "àæÞB¤(ìm`}ÚëX ¾{í2³ŸmH¿ê¯^;‡¼sÉ;pÚúkÀgD3ÓãüÀO\i†à:_yÓWï\w³Ù ÇÇÇeÞ¥K—pûöm\½zµÌÂ{VXª×£›H(Éš·! Í ³L#͹•†‘Ä0ªjnãy„§Ðawƒ¹ÿÜø?…ð8®¨ˆ´SgüMy˜}šÎîo¾¯]'êt¦Kü'ïoÙœi*^€gz¦0²ÓÁ!¸‹¬ó›`Ìf3ŒÇcÌçó2Öµ°ÖZ#Žc|ãßÀóÏ?ÿT!É«H+Íë‚“ Á•t2Y¦‘i*uûíA€^(ÁEtˆ+æx÷wѽHˆ”DHôÙ•/S‚½½•иLæ» ùÚÆº=ËT‡ewù ‚™aM>ƒà‹÷.üö¿øE‰Œý~£Ñ;;;¸}û6â8.³ðˆ{{{ØÛÛÃ`0xæ|„Ó8½?¦-”0Ú Ï æ™Æ<3І ¤À V臑bç¼!‚Ñ‹¶•ÈbÞæ€#0õä »­õBÐ¥º¼Õ—XöËë_²v‘èÚî2íä¢XÍš<<¥:¹|Nùó<Ç|>Çññ1„øÞ÷¾‡0 Ë”×ÃÃC|øá‡˜ÍfØÛÛÃË/¿l›wTs'¬âß÷í†Úæ©Á<ÕÈr $6ÃPB( €`4‹ùK×"aíèÒ¨Vie51ÜëÛ¨‡÷4D·q‰Z°ÏFÙi:wÞv**—ž1¨J è’(žÑÛ¼ÖàZ§œ•‘ωûóù¼,jÇqYKïèèJ)ܸq;;;e”ž?—{žq:øKh"äsû4ÓÐÌíû ýH!Tl0ÆÀhg°lwúH/ìMÀ<#Î”Žºí~Žù-Áðmåν7Mú³ˆóõ{(½A§qt_ÒpÆ?7›!@’GxVÆ‹U2×àžYX“ï:ߎÇcdY†Ÿÿüç8::Âöö6ž{î¹²3N3lö´õ΃ ð• ¤ !É FüœÝnQ 1ìIôC… ¨ܘ:ÂùÛ)u}TDEÖñ“Bc’ÌR cõ¶kå!„ Y‚#:3á½9-Ø×ó;9wãø2ã_9¦c¢µ àw |¤õ«ë(k霜àààÓé´Dú×^{mažUÖº Ö…W Í5[ò¥À00ˆ¢À¯„kHß­N(Q•ûÊ´Á41˜¤…&Ä¡À(’ZLm*™cü$ Í%Ȥ%Š>âû“-Ó÷ýïNóÑ/3ú-3^4÷ÖàS…eÉ8ÍOžkàWC®Ð†Fju{ Ué·wb~3þ~Õ½faš˜Ì ¤…AHlôFq€°°øDŸ–w eå³×È ›0$üŸpèãÒÜWJ*ZÛ-Ü_T?®sºûçsÿ6µaÿ̳üÚk àSáWûѾ*2 C•繟ŒÕp0Ä“'Opxxˆ““ìììà¹çžÃþþ>Â0,U6¨…½®ˆdg1ð9C6„´0˜§i^@*AÃsc%à*UtYê- +4& 'ûlôCÜO¥:¸ë+ƒxl8pQL3ãim „ HáØÚÊÿ+[Þ¥§9D`%"»¿v ¨¨ˆD55q«ß”<Ü÷äþ¨zï÷×IÙÅÁšxÐÁí%ñUE2Ë2|÷»ß¾úê«×§“ñ;8(7nàù矯Í×…ø>œ§¥ß÷©@¦ Iʺ}^0²ôB6èõ#¯HÞB‰}0†óùOæÒÌ %†=ÕóÛá´tcNãç1¹&MsÌS XI…ÿš÷®Â#;?<ß%å°¾åÜæÁ¦qç_Ôý‘ì^šv€rÞ¦÷¡ú‰.ÖÝÜ^J)Œ1üÌY–û·ûÅ—_~ù¿ïííýÁÍ›7¿uóæÍZƒŒ§1Ø­ÂeO;—¹½@A„,#$¹Á<+@¥'‡,æ ÏÚî2íºV­'.Ü‘ä3ëƒÅ {{â¶øÜS YNÜ.ƒ¬0˜¤&s\ôC…ݽÓ$³by5~á¾t®ç°’ëÈ~Ë\Ô$KƶNç{:öÖ<ß?°V.ßq{ FþÀC/¼ðBüãÿø¹ÝÝÝ×¶¶¶þàöíÛß}ùå—oߺu+v.Ü2[ 3 %—Õ <¤Y•s°ÄÆ©Âæ¹Á$)P@\Ù‰1ˆužû ÒÜ`šjÌS )€~€»}®áÊÔø¿›Ûº äß@ yžWÆ–yW! ]Fº¦¾ßœËtì·9Ö}._×À¹ƒ/öǃÁ`ø×ý×?üþ÷¿ÿ??÷Üs¯|á _¸¶³³»Á.Ч<ùi‘ú z¾• 2I®1M8JZ6ú†½×ùÆX+óJžw¬Þ=ž³noˆÐvF¡•&ºÓwÏš‹0Ë œÌ4Ò\Û A-²h8ì4z¦yŸ+—HÓÄPrÇ%—$#*+ u‰úåsƒ‘ýutfa®êÜjßuѾIÚ$Žó†Ï3¬?€TJ]ýú׿þ¿üà?øýÑh$„Âõ·}ÔO‘wpˆ™iá¹9—Ï€8”è÷Ä¡àFÄÉ2ËÖ-;Ø=˜qêmV„¡Äæ0ÄfOÙLDZÁÏ ÆpÙïqR`–òFG=…+Û=ôÂÕ ‡¾‘pš¸úߎ8x×Ôx­ÍQ¢¶uôü9[éOËyµX%¹9ü4à’WjÛÆ‚}âœáóL|_˜¦©RbkkKæyncÆ»ŸŒóÎÀã’Ù¼+2@šs囤`Ë{h‹hb‰^ )¨.˜«ór@KÆ!ƒXa;F¤¬ÁÎ'h)±n¼à ×wzˆÃå.Âeû/#ñ¬1°Ð|ˆçì³…Ù€¨\o–Ý:Ú ¼ß˜¥‡j§>,phï èî½Yò{ù€o[ ¬ƒ\$a–eùÏ~ö³þò/ÿr!lv8³TÀ'Yk¾¬¸}jØooKÝÆÄÖ @/äZzdXG/Ú%ëÖDW"ä†0ŸŒSv²{0ÄF_!*Kvµx pº=£ô¤ZÃáI’c’pé®A¤°5d1ÿY<šØè9Ë4rí¢¹æ tƒK.qÓ95€?Óâ)‚ãÈÆ øS Tz|&û™„MÊ@@­”<5þÐ@ú…_¬ !„"¢üÎ;÷Óííí8MÓ§öÉ/•Àb‡ö ²Ü`–k$eƒ AÄÁ:±bâ@`n×¶^“”ˆ/X¼Ì ƒ©­¥G†‘•íBÕ]²ë, &giIʪDH\ÝŠ1ˆÏçK2ƒq’#Í ´&HÉ1(m$í~÷6}^*…¼Ðœ(E X?u©HÞe¬³qïyôèÑ|{{;~š0Ýe P‰ù (Óœ0÷dÄ!sû~(¹5Æt¸ZŽIXN, ³Ôà$-fº¬Ãï\k•Fͳ^›?ÜÂñ¬À$áºcUt IDATã~¤°5ˆÑ 9¯à´˜ÿ. ’ܺ 3 2„8R؆(².z¹vNs,Šè«Ápð”µ1¾Xï^;U ï@-b¯ÅEÀfª^{'àÁçCD€yÈ0û⿸ Ô‘ìi"ûû° W#o–Ìm×Û²AFÄ}ð¢@AWHdµ (Ÿ5"hYÎeµ&©†1„A¬py+Â0R¥/›ÌÓ7›&"ä¯1ž³%? $6‡6ûa%â/ /^v/{p’jdWÚ…èGB›¡x O7ÜÝb´«RÔÀäÄlbºýÜvYµx€Æ÷•!¯Mg¨Ï½ ¹¸5Ï<ø<ÿÖktxxøäþýûG®·žð~}’‚³Ü`–ÒB„Jbc¨ÐB›ŸnLUç´5,£‡€€«ãT#+€@öF!=…ÀFë"ÐKRR–†Cp=¾IjËraÔ“¸¶Ÿšå·Êz¹6˜$Ìñµ1ˆC‰~Èv% ›ˆØpmœ´yŠ@Åõ%uŸ îïk"(­`ï‰1õJg„}ß* 47Îðy&@ukµBÌçó'ï¼óÎC_q…>ž „€ÊRÌâ0Þ@GE.õ–uWcPüj[†– %eêmUVk³§Ê(=A/kšç­Õ\Ó¹!µ¦³'óóÌ ý£¾B¬$U%$ßUw*‘Ü'0É8(Í ”â,Â~,OÍ+( q¨¨&ò ï;÷ÑYç@Öþ­Ü·©ï ;‘hŠüÞzSjZyÌnŠü?w¼ÖÀÅ@IÀªÀÑ;ï¼so:ý~?pM9NZE pr„裱õÒÑÛ!0šuôÄð²ªçÓ0·½´0PJbw#ÄfOBØ ÂuIbõ›áÖIL““”eåA/À•­žÇí­ˆOÍsÛ¡GÂ$)l¤!! %ö6BŸzBQ›ÿ¿y ¦Ë{v)$Œ6B-póÎõüyKu¢ñ¹ƒ”÷ªEâ輆¿{ø¼Àâ•ýËßÿý§Ói6ƒÓý´ïL!ĈE£$´iú«ºzüçší“Ä”"òî(ädÁ±þÔQaè´ E嬇˜[ÃÛ,#( 6JF7ù ÕªÕïÏíJ~“If %0ŒCln°ýÃï÷÷T.ÕÆkÓøç¾(¹°(t€TMZh›·y`‰ºß:à*C RAËÞ—ê0Ÿgà?'Úý}ôÑGŸeûûûƒ¥'·¹j­“Ó£$ŠÙ€ðjÓ·fßyÂ¿B¡Ž?¹sçÎãï}ï{7» D¥îß¿ñxŒ›7o¢ßï#˲úk †@³P€Rpûº°?-¨,«%…À –Ø(Ëí¹#Ú‹/°QYnp˜jL®Ü‹6û†±‚69¥Å(é_ûb3@6|Ù`–( VS.بHV#Vµ­6¥—Z sbή !×(ûVç6'«¿u…PŒ³³ÈEîÞi <ƒ ’àʽ/Ku•¥]XKç ÙÙ´1æà­·Þú8Ïóׂ m†@)%Þzë-üä'?ÁÑÑ~øÃâÿø¡”* ƒ¸Üoââä2MAÃ!`ûp”Þ<ç(:c€^(q}' –€Ü§ÑM׿`¹Å]ÐD˜&Üd3É %°3Põ#(kt£Ž€£Ö9ܾÐ'³¼¬þÛúÃqÈÞˆ¡Œ±Èwú­„ƒÜ‚<׆¸¼WÈÊŠî)wM½»šŸ DRr3’&úÞ¿æ¹µÝù|)a‰úuPmGh§ çŸ[ào,ÌßyçY–é~¿4‘ÌIÿüÏÿŒÿ÷Gˆãð€­­­Z‘G¨ß‡$²b4H5ûÔ“Ô„ £žÉ' Ï HœÖ¤Õ:¥]»ëB° 1Iв³n/”¸¼Éé½J°¬(Ζð#íž\êðd^Ø®½® 7•Nü¦ÅD–U]…Í Ì“yŽiÂ.O)Y•mŒ€h"{aÚðGHÒÄÖÖòÄÅsºˆH+,ˆømv„昺ÍA¢r9.½€s€5`p†Àݽ{÷Þx<΃AÍàDÿ$IpïÞ=$I‚ù|ŽÑh„Ñh´ØäCÖ@ƒdóã™Æä$CA@OIl †VD6TåògÓÝ> M˜ä¥7Ï8Üu£¯piÃ%ü0âk³øDu!&',qrLZhÌYÆžø>Ç5Ä+;F¥»r•=Wkˆ…÷†ã¹Æñ,çJAJ`s".Ë—70¤D>ϬßqY±^™.7@Ç᳑Y$FŽByÑ?‚ zX²pôáóNüG„ˆH÷îÝ{ðøñãéÕ«W˾]¾Õ? C|ç;ß)‰ÀŸýÙŸA)¿~@ ÆÀĤ’˜Ï‘ 5v†F=e“q…nò×îâ–NµÖÜY7åî;ý À¥ÍˆóíGjßêt ð¼UgâqÂE<²Â $†6|9T6èȳ˜?mü;NM5f)—þÆ ×v"„Š«ž|òÄ’ŸÛ–¦~w¤z[ë•T’%6·~sC/šãš’¿ÿÙA€ƒ¤W/Ïñ÷ –$*±¿ÍpQdàóN€úï !èàààã»wï|õ«_½ä…ÈóQáG?únܸxõÕW‘eYÇì¡È8F/Ë00ÒÑe9¯Îu ¾ΈÅ9'‰Æ45F¶×^*€Èf½Í®Ìv I4¦iÁjеäïŒ"Ä¡„—w¢nmŽÖ¬Û¸„ùñ¼À,70êeÃw?ÊõêwŠÿHÔ¬ý¢9TË!`ã¥aê!DcÎ6“¿ûh÷±ÄjO ZÎ…£OMBÁòŠ“êóÕÆ>kTj¬ ƒ»÷@‘eÙ“7ß|óÁýѽ¬×óÕ€$I°¹¹‰ï~÷»*7`ûÌ,Òë(ÆF1A #Ï9}ÊÆaºD@f ¦)UÜ>”¸¶`lh'¶Ž7wÔ^,D D„yjpŠƒC˜$mD+ÿ¨RT¾í¬ ŒmËj Œzl?ˆÉ=âþâƒÚþ •º=ÙÔa›z bn¿=Pˆ#isî­^¾b `[áéíYnp2Ï8ÀI»F=¿5pšàë#ʪ† ¢üÏÝö´MÓn«W²€Üþ\T­ïdˆÒ·o“Üy¥$éæt‚ ¡žÐfÚ¸ àsM<(ÕkÈß{ï½ûóùœúý~+®:u`%Qנ׃ ‘çÕÛaª‡$Ó„ÉTc’ä…AlF¶ì·ûÀýó–^(”µÒÌRm³™Û_†èÅ¡õßÕkžµô™,; dáxšád^ÀB?VØì«Z¥ ŠÀœ²^S™n^õ4)… ¡¶o®R·HÜT=Ü{?{AÀº”¬îÆ|>±¢Æ_9®Ù×%Á.J  À¼ÿþû÷æ7nÜè n+ÚŠ(Zƒz=;MSTa_Ô8¿êð“å„iVõÚÛîKlöB(E|‡ø«¤K)xn"äÚàpÎvÎ+PÜK PÊkªÕ"æŸ%N_IîT”¤ ”d¸¼aÔW¥dãˆL´ÝS.¢évÊ„ƒˆØ &PË-Xzo„Baò"8dç÷•ÑœÓIΘOþxcjYƒ`kÃjnÝæW<ïi`M*(¥ù£G>úàƒoܸ1xšB @ó9¶@€l)¹&3ƒIÊU€£€«ç# ¥„-ﵸF›;­&® ›L4טÚÎ>¡õô£‘ªÜODXàH]×Ú¼/ÒFÔÌUg9Næl§ˆ‰[P–Üþt¹¶Y”EJYF:äsÄPÀ"¿ìÎm¼–®É6€¼`C î¾ñ›¶jÊõýÕ9véû÷DwW~´m¢U$û¦´xž°& þóQȧÓéãwß}÷ñw¾ó礔g΂«!HJ C¦ Hëšu8µqÿ³œ Á†°ý îîh½z”À@2`”.r`2טdF¢HZ_:×ÔV¾=ËÕµ…è Áˆ8M¸Äx’j[t4ÀFO" ¹ëɨWaU’4×i¹o ÀŽò«F=‘¿üIªÃÖLC¶ º=æÛY}È×@Ü{ª¶¦¡¯ãQ“Z®÷‚ô~>÷ÀCÔš eÙøÎ;~Àý2ág•\Y0ê &˜:1Ï80+¡öF [KO!ÍéLùüNôÕœL Œ[hCÃØõ%¢°è\íñ,â½¶¯HsÃ$1( ¡*\Ú G•×€ñÔ4æ8}-§iÎéÄiÁ±õR DDPdKæžC¬š[¼ö{çôÇÖæjAÄ6ܬ£±¯Þ—-œ¿ü³ªÖ‚ñÖ{¿¶\<ø*€1Æ$ï½÷Þ'eQŽ%«±n$G(&&‚Ðè÷aŠO+@†±ÄÞP¡Ú AT7ê¹óÔ kðC£$#~ZpNÁ4c‰C!GÎI2ÕµMò^5^Ýy%Œ!LvÎR )F±ÄÞˆ×sײLÆíªSÀô’¹q®Ù[0žК‰K`‰l°s_Ìnàù¢^í眪[†ŒÍãþX÷û/Ä*8Î/ZNj[Ãû Dëðs5¨ƒÿÈæwîܹ7‹Îê@0 À…< AÐÚ)˜ˆ@½ @¤)®]ßÀHr! mX|^1…»æ$¿ØoÏ5¤ú!¬4á»NÃóÎà#B²Wb>/˜ÛaHÜØá.ÁÎÚ¯­øÈ.Igžg¦I´àTåíAˆQO!Pe #Õ.9} —÷5é’” FkkY¬l(ðÎYz Þuœ¦*ÖbjbÀòsÖÝ/MöÕ€äÞ½{Ý»wïä•W^Ùõ-ü>ç ÃZküæ7¿A–exå•WEÑ †a€=™Â„ynNÇÈ8$›çÆèä>q$±;bIµÒ6´hh[­$7£¯RVò@–O5f)»Ì±Ân,Ë(½*· z]UÄ/£‰[ƒgšS•CK£°,1ÀVó­™ÕëVâ<Èó¹{£š X*‰¼( ©îÒ[vÎÂbÑ¿)A4×ïš{ùü§Pˆg€5¨Àÿ-4}ttôðý÷ß?zå•Wv["$ þáþ?ùÉOpóæMüÍßü ¾ùÍoBk]݉`¤„ŠCˆ$…ѦïÑtdz–éÍsŽËO2n:êIôC‰0`·˜Ïퟄ]7Í Æ6Ì8ׄ^$±3Pœß¯Xl~ZÎ$¬µÞ• ;±­Á•à§Ý!ç1øÞÒ)«Þ:@T£ªÂ¡¥ßË›êBETê!Áµß¨å:jzº©(&±8OÔ‰ÇEU¨ÃšÔ¡D~z2™}ôÑG‡]ƒÃ0ÄÝ»wñoÿöoHÓ¿üå/ñî»ïâ[ßúV»N-%L¯5™DK©¾‹Òlêmj0MMéRÄýP ª¶á‹1ò-ØÐ#s|P•ê;Ë 6{£^€0´õôÖl®µÜz‚žXÄŸ$ã”Ó‰{Äî0F?än=.–£éwÉ"úbŒBuï4Uºs]»onÒÍÉ(k<²ä¬úÆ–]÷ê®—iGMâÕ [Õ»j`ÛØ‹‚5À÷uD€ò!É W2[›=…^(9­×Z±ˆ8ËïiÚ˜IÁÁAÖØ6+plÛ÷BX¡«R¥hë@|¸ëqMI9ä8Ç45àL¿Ía€8à½8¤÷‘váÊšXéŒ~ä,¸|o%Ú;øV§• !9ŒZµ/QêˆT'΂¯›])O4dˆš1‚¼HËÚå,lâ‚ÂÖ Ž ¢ÙÛo¿}?Iô €CÜçŸ?þññ/ÿò/øáˆo|ãí™Ä(E11HÐæ&`¸üW`mr .´‘šÃsG½J·—÷£Ú²p²›‡]‘ÚÖî#lô®õØ’ïˆK)‚/ ]n¶æ ¤š0›˜&Úº %ö7C #U;Ozn¹uM©…]¶S}ËR„»`{p™eŸ³> ˆœ=¢)94³m\‚}d„h¿€¦ ߆܋ç4Æ^ ¬ À"#„ "J>øàƒ=z4»qãÆ¨é Ȳ {{{ø‹¿ø üð‡?ÄíÛ·!„(“ƒjn.€‰@qPP’€¶¶!ÁA>Çsc£ô)¸ÉÇÎ0°o¨âpËœ·`=B@(öL“¹Fª a °3Ћ˜È-¯Oà¯Õ\C1Ë å'ó3›ªÜ‹9ª1 DilÓÄjÆj ŽÊ¼yA7LÕùY䯺QýÔ…€ÚÞ¥D–ç„,çhrðænÊšùÛT¬ @þïUÚ’J¡ Ú±¿–±ØeÍ8ÇÚrýZ.ØáÜ©Ý7ÖJ§†èRË»êHû·M…ˆÕ¿µ p¡Ðâ (,‡?xçwîgYFRJáû÷Ÿ†;“0Q„¾$„"‡ú ¼( @Û¾:öX{˜¥ œZbV¢@âÒÈùí™0˜£ôÚBc]¥ßiÊö ×ôcI\ވˆ§¹F‹î»œØ#€B ŒçÜP¤ÐB ô#V!âPq<„´âwY“Ì!I mP—¢Û†NL<9ç£í•çX¢f8¹NTÚt޶9P·´Iû¢1î"`MÁÿ] €ù{ï½wo2™d[[[qakú«sæjf~¬t³lžÀô‡gÊúrD@ ©Ç)Â'6Ø¡Ilõ]`>§Ðþ~W[K ”‚Õb[ÅÉœk†J`g¨Ð÷én¯X晨Œv…!$–Û'9ßú0ØDªô!h ä…©­QޛƫûÐT |W^}Cœõ)åò„¹ÿb'5ÞÔˆÑÝ¿æÑYf5¼X€:8bì¿ ?üðÃÇÇÇÙîînÜyâªn8c Â$%DšÂH±Ð2l¸Q¹&'Ü,4É ¢@`ö$j)Ä«&ûb€Iªq’d˜§ AOqSÒ@XŸÓ% 7=~€S® I¦1ËY·‘@/ ʦ" ‹øKî/Ûø¶éÝÞÀ¶·|Í–(pOåi[ õ˜'},û›úü¢šÒ½Ç‹t® @;¸úèè[ßúÖÕÓNB Š"h­á« %S‘¦^ç¼W†0‡m€IÂM2æ¶µ×0–Z¿=옧%E™h“æ,âO2¶sô#ÅÞ‰@x5ûmËïJ ƒdn0ËÈöñz‘àŠD¶ÑY¿þ*Ðêy£’r[ÂÁæ<Ñ,øëŸÓØ,‹~l¬\ªLRJÃ_3Áªƒ,[³©ßûljü‘À4oK~:X€v(mRJ¤iúèí·ßþ¤(Š/+¥–¦|ºìÀ0 ËXúÌÄ-·ãb>‡Ès˜(âb¡ñaÅYÎïטe¬[÷b‰ëÃqÈã Õ“qVQCüM€còÇIIBÈ !VÛ}…aO"°2~›û®kM dû€"É ·7/8k1T²TU¢P–ü*1©Ë«ðtzk³ª€E}2BÏ•; ÈÞ G@/z½^«@†!~õ«_áïÿþïqïÞ=|ç;ßÁ•+WpãÆ Ì]!PÆ0 @f)Ì)ÇsƒYb ÉÖåïK.™-ª8•/ÀC,iÅpm€“Dã$1Èrƒ@VEG]ÀŽ)ýöËÓ!TVJ Â,ウšåö=›µÈzt»˜šô¢„ Ž˜4–º"*elP þ½r"zÕ“¯º†r ª¦\ÍX ²ÿÊRßå9þ¼Ýü•¬$ÄjGs°& )..5xMÁ—35qŸXO@º»»³«HV&%Â0ÄOúSܹsãño½õ–Wª¡3Ä1 3Kq8ÕÈçœß¿; 0°\ÒX½S{«Šù@ ¡¸ÿ,јZÃá ¸UY‹ýP °ÜÞÁ,VGëwJ°…"- Òœ˜¸hFÀ^ JÃ¥‹H´¢ï±íb¬ô¢ öm(ö}À…y7ƒŽj¿BMk´„+ty¦j¾ú Œ/PÿÖ  |ÓŒBÐt:}ðÎ;ï<üîw¿{C)U« àŒ~?øÁprr‚àÏÿüÏ¡”B–e HKÆÀH E¸DĆ)“å8-J¯ò«£|ø¡JHlCÇ9zJàòH•~ûJ·_Mï–@Ù,¤0„YÊ™܃,V¬¦Ä®™°©¹fÚ¸D¸$ƽ´ Ì3y®¡5AI®q8ˆ8q鎨ԕ…ûÓxÚ¬ôÝÂ9ÿèÂv÷屚̘Î>»^"8“D ¹£i~Ø58 6 Hk}üöÛobŒA  I¼øâ‹ø»¿û;|òÉ'¸rå ’$Y gz=¨éEšƒ?¨«Xª§”‚ ƒæádnZn¿Ñ“\<„[ ”–r÷ø/[¦$(–ÛÏ26èÍs>7p¥Èl²ÛS³š±¿ßÖB£¢".ö–‘mÒD'q´!GqÓÓz þi(âPKŠ/ IDAT¹äÞ§&D\fÔoæYŸÓßµ‡%[ëv !X÷w}Ö6€O ¼‡Õ!¿PQþÞ{ïÝÏóœ”R O³ÖÆ„aˆ«W¯"MÓîè;!ØØëq¹ð<ÐÙláT÷'™Á,'ŒSöM÷͸²´»‹hÛ†”NÔçÁU“$3˜e¦¬ ½Ð¦+Ëʸ Ý¢šÁßu:šgT)z±° E¶œ¹!>vz¶/¾wÜj§Ã•¡ÛPâ=™…k6JÉ!¿uk/*ÛISýhn©æ¤Šû·)ˆP–w¿HX€å`ÕKÒÌ{ï½÷àøø8»téRkH°K vœYv pý‰lq­V$òE|eŸ¾yN˜%IÁ‚Û}‰AdK…C,­®ÓܯVŸVì%È â>~¹†!>>Œ%ú‘D\fø¹(=Ûþz7žUaÓB³‚+ gš¹ylôCôc«J7)—ø÷Ž7¿p¿|ÄtíË Q¹vÛ½m!LaÐV¦¤)yŸ>46Ô-T¨üWÆ8Ø=à8¥úikÐþ¯Qæ|ðÁ}òÉ'ãýýýΜ€Óšˆ”à<A1Ÿ³DàRúì…%.‘rFB^,J¾Ñ‡Å”Úý±ÏŸ½¶®-"hëíK6¹ÖPðÒ‚}}¾a8,‡t±üæ5œ¾ d˜·ô× Â‰Õ„IN˜çyÁ„& ¸­W?„m?Î2ÏÆ€¨\‡ˆ X¬Ûsù.)†±bK~ÈöM\‰hUi…mn5öJäšK¥9£¢%¡äìÕî¿V?ÎÈ \š`ä_\ïpó*š–……siñ˜£5³Œ°”Ɡ @ ´ vÀE1¿sçÎC}]^ý§k^Bc@ý>ÔÁ˜¼À˜L&óÂv Ž$¶‚ÃsE¥ŸöXT#YB Ó„$ã¼{m8z¯ýP! *ÄÍ Àiº+#f©‚æ{ 2ÍH*a¯r ±¨Jø)ÃþºÍÕsÃaÒÚp’³a„ŠmeÄŸC|BE1¼{Óþ6à‡o°“hHzƒ©ÅâßÄoBMmhÄ-@)xÏFn%€µ à·Np¯Ù;wîÏçsŠ¢ÈÚ¢º¥1Ø=;±!Ðæ˜"ô¤ÀþH"8 Æe’ ?ÏË‘ÒÙ ¬øó\#׌`QÀF½ž+< WV»k‹íÕ¥¶¢1,qáb¹f¢Ó%¯ã“ºúºuš×áBcsͱ“T—½ )(¯eÕ¹½h™·U³c]¤_E„lÃP×tÐWp:RóÚõÏM4®Â°ê#Æ™¹0„oštƒû}5 ½{÷î½GMŸþùQ9°I”Rè÷ûÈó¼³Y(ˆ ¢F*i‚Ë;ˆl2Z­ùËÔ —÷>Ïó‚åUêm?âH VªDÈB/˜keÁì5J«|kM˜ŒøYÁÜ>6û ý²¼¸õc›ªbЩAAv\n€$ט$óŒCŒG}…½a€Ú~>º{U—Ô®gñ~¢D|í )¡‹Â®Óâvô7ÜXÏ]ÃJ1¨“ºõÿ¢)ÁšœŽÙÁÁÁ½>øàðÖ­[£Ú bFQ)e)´U¿L"ˆBìÊ y,@9ôÂÖM•º=»5qBÑ,ãl<‹Æ›‘(ëýÃúÔµWÍj„V¿¸qÉ<×H-·ˆ`ˆ‚ªÚo8\¶‚£°nÚpàÑ,cÃd/ØÛÑØGÚ»7¥îîߘÆ}òÖé»5ë÷ݵ'«“È…yZðë4¯uá\û È lY´OÖ`9x?MÙ/ðàý÷ß?üÞ÷¾w³ ©]nÀ‡~ˆý×Åt:Å~ô#¼ôÒK0ÆÔ=–#™(‚œ'UðSŒ?¥±Kp¢O’Ìs&Jz¡@?ˆ\ Yiâ ECx ë·'BbU‰Lsñ(Ø(ô"‰Ð–îÒ K¾OšàìjÒÆ-ÌsiÂöÄÛ}…ØNžå•±ÐÿQêk,šç}kÂ:["ÅÅ=±@<`û®ÃûbYéµ&­¨á¿ÝØIÚˆ4X< ¬ ÀéàK”$ÉøîÝ»v®.¥DQø§ú'üã?þ#Â0Äh4ÂK/½ÔZ@ÓëAL&@^p­À– THÉ5ØÒžÙ ¿0†±²€Áïi¹8~‘²‘}ೂ‰’œSx…b%ÐëÙ ½‚Õ˜|ÅžÖhbzau{r-Ã.o„öd™bìÜ{ ûFƒxÿ;/@9Žªb¥JzçØÝGM>_Û°¿@c=ï½op§4&ô¿ízà(1K‰ÈyÚt@#$ØI0ÆLß}÷ÝûEQ”R4:Š"|òÉ'øéOŠÃÃCDQ„$IÊÄ Æ"üÃ÷zœ"œe ~Ÿ‹„Âùí«Ö¼àâsk —‚ãå‘àî>ÂR*:Uˆ¨çô³TaŒ°yý„¬àÚ¡­0ˆ8ðäªYßû Þa¹=‘NRNí†=…QÌ¥ÇØ6A ½é×eCðÕÿhe@åè¾f1gõy 0’RTÇE}½¥*FãË•¨¡L¼°ëO Ö`5 Týgï¾ûîGÙÞÞ^œçy-¦^))%nݺ…_üâØÜÜÄþáÂïX>Äöé¤^‚†ü € d…@’d¥kmÐcÝ;°ÚPÉíÙN·RºQIA¬×@fØ Òªܹ×h´FéuÎ ²‚0Ë LSƒ\‘ØìK #ÅmÉ…¨=üK “M‹¿÷™<âäî›?*qš $wõZh‡=&¥@Q¸˜€*[Ñßß‚j@Õu—%J—HþÁIúé"?°&§/Ô•A<¸ÿàÁƒñþþ~Üì”evwwñWõW¸ví^xá|ùË_^èX[$ @$ @BB¦æ¹AZÚ@° ¯в»Pçöþì]Þ'U°*Á…@ç¹Ašóg¥€a(0ˆ'üX5G/AÎZ¢7€È"~ÎU‚ 6!6b+I( Ø‚'§ÿåzÞ>G6ÎÅh‰Zà•(ó÷èÞk¯-R›hNå½ãXƒêÂÈWÍÄ}Q›Ç)&¾%Â?^ýÓD8öõj¾½â°&§C)¨— ×ïß¿?þú׿~©98ÏsA€¯|å+¸}û6Â0DW AÛ@J˜0„˜'˜f„dFìZ*`zJ†Àœ© °CgÌ5ëõIN( ‹þq Y•«PacÚsî;×\ÖŠÃ ã”»û„JÚ(@Î"4DHóŠºÝ« . Ê!Z¡YeЄ2aJ@€W÷åÉÝ‹µ8£j_/pý«c>q×Ü8ÇŸ·a!lUìÁùñË*"ÃùÀš¬Î è“““Ã?üðÀ mƒó<‡ÖqÕ“ªMæû›Ћ1?œâh’Cè…lp òä(=F™³pK~Œ4Ò‚3 Ó‚“q8ö_ g;÷LXJÁØÊ¼Ëj¸›cˆ0O` ypí(VØØˆÑ x°ŸÝçŸßvoºtý´¨"sÍÜÓÕEÈ5mÁ!V;úøcÚöµP¸Ôó8”Á>5¯CcÂŽuœa’8N:‚èBñM–AG•`™çùñ;w>qßSgwÇ–)'5ÖÏÔëA™#lн~ˆP²àè2Ü|±ÒÞZb(ûf k8,4’œ3̤`Ý~Ð\%ÈÕì3XŒÒ+ýÙu¤t…œÃ”äS›[*K#Éý·ýJ‹§ër\©+YNœ‘qû3)™8ºòfpL½£6`™à³ÂºNä+m)ÔüÖ­þöÞ<زû®ûüÎ~—·v?u«µt«%µÔ²l <ÛCŒS„ àPa*ù‡rM¥’L¨d˨ “šL`Sd©„³Ž™‰q†2–ä16¶$›ÖÚêå©Õëë÷ôöw—³ý¾ùã·œßÙî=÷-Ý-¹¿Ý÷sÏò;¿sîùè¦"•”NCÀfÈ!4¤üTEÉöî€f Þ eܼpáµ\™p!'IÇ%"pχo‹ÁÝÒ8ùÓWúÖ¥ªª8ä0!D‰à`¶t}&ºï9Y„çNP³OÝ‘á ½0Rµ| s†–kiûBT÷;î:Òù§„þ€°3ä²û°hf[¬”UÔÉs9\ôò+JT}ÂeÙ®Xøþ]¸gÆAÇ·`[ªTwµ}ÂLø­R0D G/â„28°p¬åÀs-]œ³X£¿„÷Z¼&]B\UBTv„܉…¹JeKTfÛÚÀXyNÅ-çT° bùÇTé6óÈ[@î€ñ`Úª4¸~ýúÍÕÕÕèøñãíâK=1v²m`8{¸2èÉS1ˆEu (QzŽt|QlÕuD2Nþ¶FVF&ºÆ²nÀ âHIdÎwT… †8áˆL¤ªRytdµDpŠí!!LRx¶…™–(b[âÁë2ä2s…!  ¿øpéd†‹®^ç‡1ÁàÆ#è&£z|uƒ`´š¨ìîÚn?h@z°¶¶öÖÒÍ›³•«¦D€É†¡Žò<°(eÃÇDþÅ‘Q·ˆS!ÞÁÏ_¸ m&‚jFEéUéöêFé)èË*AžÍ0ӲБDEe ›DæQ÷–’˜¿HøÈÝõæf\ŽP%Ì Bó`~ÊÏ‚|U´Ÿ ïU놄”ŸC6Ž)Ö縵کŠ!–™H­ yæ$s¾ÿÌ{˜»8%ô"Û± l;·î€æ`Ú¬Á`°òæ¥KDto­¿ˆ`U A€`ã®+ÀÎŽpŽKã“âö#p’yý±´†“p{utì¿2@*÷]s;S9ý)a oÉd #gr`˜ÔÇŒñ-À†l–pì„BÏw-àÈ´£¹½j÷U9†±ô]K#Ÿ wM23’k1F=v^Çܧ¥KËêÀ¼p_&×gùAMCb•GP®?[Ë*W÷î€1Pá Hcœs¾þÆo¼†!ÇX<­Ã”‚HOÛØR@§ÅÂ’/#ðÂTÆÝ3I×uD¶œ%qŠôÞ,´µ©’p`¦èE@˜pÙP4u,@=ÕfÃêc•!=Œ€^(ûhy 3²™ˆâö£âLµDˆc’Xèd¼Â{"-þš°‚šK5~e!VSÛ™« U4·8¾‚„‹8 Û±åovðÈ^w @s0UÇ@tíÚõ·úý>¦¦¦ª€Áu]¸®‹¥¥%pα°°PŸ°¸q„Äê"JEÀLg.#¹½Q™<­AÎR"9y¥/'©È+Êzÿ¾Ëp¸c#ðD¸²ðÛ7MCh–,lƒP&]‡aaÚAÇËš„&F¿"ˆqcÂåHº~ "6cº½x]#,˜wäæoÚô ÏRo3¾+#+Æâ„yüj?….@B¨}È9£àÀ]0D¿À_][]ÛÚÚÆììlåÁŒ1ÄqŒÏ}îsøâ¿ˆw½ë]øÄ'>ûï¿Ãá0 i ò<cö†ØjéPJް䲬VVòºùÄ5'& Œ9¶C’MDD2QÛ=öQ,4/I4ãùB]l8NÞPt(â$$•ù®­Õá-È߀–¶¤Ÿ_!YÌ!•¤:ÎDð#ãŠ}rú¶a¼3 zâšÆõÍsÌïŒåûš8[âøey¿8n˜*×_ùÚ·”ýã.h ŠW•Sô `ƒÁ`õæÍ%?þ`åI­V gΜÁg?ûYœ={—.]Âûßÿ~?~\«ÚÐÇ9ÈsÇÅp'D2ËÑrYå\.|ëª^ÆXòõäI4×$À $¬°ÐµÑ’-ÃTY°âË: (‰bG¶sm†)_øî‹AµÜmì"‰ÐÂø8L„‘¤×bèz–àøLqfèJ¾9$-0âÒ™Oµ‰•6é«B—g2êçP‡®ôRPá_UcžÕÞá.hê§àvËqœõË—¯à;¿ó;Kú!c Žã`qq7oÞD«Õ‚ïû˜ŸŸ×Ü*§ p.b<(B;àpHyu”ž+Bguî ÃER‘ŀ铖|a,L!l#o¼êF= "‹¯/ÛzZ®…Ž¥‹yp˜T+â++9ÉX†„ËeæÛò¦:¢8ˆiȬþäG†8¬ð={rbÍ<‹Hk‹ÇÕc5× Æ}¦\Èä«Ò8·–ñk¸K&Å RÆXÜíNm^¹zD”3ªªÁœs?~'NœÀ¹sçðÑ~>ú(ƒA™sÁ|áa’ ¶|0ŽjZ~[L4’1ÿ½ˆ#å"m¸+[†)X””‘ºé#`ÒÅ8vƒ˜Ã±€®ok⪮þk‚¶‘‹¢EÁµfÛ²¾ c &< Eãâû«}©)öæs3[¥—íLWlÊ=±±¨R#2Â@¸¹“d^Ê>»ˆÛ¸K@…'€QA¸úÖ*8ç°majI€sŽ0 ñÄOà—ù—ñÒK/áÃþ°ÞWºc ž õ}؉ì(Yª  ö¤$j7oÙ ³…ŽÏàXÊxQ®þ;QБæöÂt| ‡».WÌ&åTo8dYmåº&"Àg˜À€–ÃD©1Uƒ€Œ(>eÈ”XS*Ç&ÿ–|ðÈò)4­`yI)‹Â3Ç3‰JæâÌ© d"x•ô!7†»-øq×x§€–¤¶íÐN¯‡^¯‡V«•?QÁu]<þøãxüñÇADØÞÞ®G8ÎÁe!‹¢Z¶ ÝaLˆÌƒX´ÝJ8Á³ S(jdÙî7V!æ[,«4<ŒEÁŠaÌaY@ÇÆCײt—¡ºU%AŠìQ"â„wƒÁ±æ»::]X‡"²d^Ž”ó\ãÎJ݇Õu Ä7ÍÊ}XeØËì¢FxÑãM2 *GJÀZÜQÖSZ3¸KšƒiäD”2J’ëëëèv»¥T}ÀÐꀥ)È÷EÀÁdo¾t Bé eyÇc8䙡¿õ®µÒ™1õ”ÃT$üô#iÉï¨~Y>ó"æW“æœdñ±$Ž…iÏÒY‰ãâ$IšŸ³z~éõ º9)ò›3.nŒenS7£TóE0v—í¬öÓrmC(5-ÂQ‚»`rÐR€ã8©ëz¸víŽ?^2ª—TÇ¢ë&DÈê@VŠ:ƒ%ýÓÄ Ã„éš€¾M˜ê2­Û'\|Šs0K–Õ ËàÒa" zD‰ˆœëØÂM¨Ž8òmÃrñ¢ÎƒaÌ&B·w,Ñ; ã‰T^@ĈֈÍT‘¢/¦-ãT_“Í{ƒZ¨g‚ %«ÙLÍ¿j–: Ñ0hªc akXæþ„Šë4Ë/À]0˜Œ"q]/m·Û¸qãÑ $I’ÚˆÀ±/8‘¨°Â!¥H™ƒA” ‰€ÆÚ.ÃT ðlÁÒ²"“ƒñãTÔã߉'Î ‡"‹¸hYUJ-!µ$J… JĽû®Hîñ•.LÚ¨—YêËjHíõX&i•º8c”“@JÜY] ,·?‡e£€ÈFd¬´Û42‡XÞIÊÕÒüܸKB¡J0p×uR×󰺺 #Œ•¡h‚||k½~о倇žË°Ðeh{¢Öjêµ ®Wºd”^"Äü(%Ø6ÃLKtvlIJ²ÜóUHÏ ŒÒ¨—¿½ÃD€Q[ö„Œ0 ‘“¿µËʈ(¤‘45ô{Kܘ”ÌØÿêP]£Iá6OaÒ‚:N« ’°È1×|WmÕÕÜî€É €Œ1²mý~¯1âÆ9Ðnǽí©6ƒë¨’Úâµ°Æ$ޔƅôÛ3Áá{‘è@›pQ3`®cÁ·YV7°hÔ£Ì o^2%Èe¡2€16Ðn[h9¶ˆñ§¬ w(ö*PÆÈ”D"”ò p-1* 2æ¯E…3­W3äb¸oñXˆ)+Û`œkÒI‚°Ñ¬FËf‚ù˜Ü%»@Gï=öǶ‘¤)¶¶¶033ƒ0 › PˆÓ7v€û>\8êE`m [[mÕAÂ(½¡ êø s²ì7•5g&ã÷c©ß«† –´]QµXÅD)W¼B,o6WA¬H£D‡sÙXcËp`ÛÊÔì¹æÅô’*PÔ *Üwz—ÜhÁBʹN ®âÐF\–{ Fµ(Ï!þ]àm¦ÈÇî:¶ƒVàúõ똟ŸË‘=σçy HeOQ÷%×sØÃ!ÂTê©EŸ·v‰UëÍŠ+¦2}· áç0i‰c!º3“_!â+w™FD`ЍÂP6îð]†™ÀÕ„-Y±˜LÄ3Þæ€H%*aÊÁSѼXºˆˆëµÇC?ý'›EÅ¥)Û]¦(«ç*È«dO¨¸ÃÕA’¥4×S€+ä­ƒ»`rÐ?[«ÕúPš¤¸÷Þ{±¼¼ •í¿ø¾Á`€••ÌÌÌècõ‹E”• ÷‘ðÛ÷”á@˦Z–ÐÅÉ ÿ­®f¤²ðT§ž0ÂX$æXŒÐõ„=µYNõ×…çºIcd »ÀàÙZ-ÈêÅVõE#ªœQÛs‘x¬0\vƒD°–Ú\ã¶#ˆêI;ái”Õ3¾%p—ìèŸüâ/?à: …™™¬¬¬¨·`Û¶K—.áþèÐï÷ñ£?ú£xßûÞÎy¾–É­Õ‚µ¹ ‹sP“„’”!ŒýX mà0,t-´\`œòÜYŸ[Ð¥Éx SÑ4L‡um`:mÈdi¢$…”‘›WR׳­LõÊråÃXèúÕ‡Z®¨}@L… s#T×¼ñ§†™«G«~æñU¡ÃEê6q”Y+D)a½ß¬ÒjQÂ(ÝÌ-€»`0n÷ÝwßAD¸ÿ¾cèt:X\\`ˆñƱªLøç>÷9|îsŸƒã8˜žžÆ“O> ÏóJ× i°“Dô ôýÒˬ c€ ê ƒD¼N-—a®eúÙëïÉtß)1?ŠEñÏ„‹€Ÿn ¢þ<€ŒÈv2ljÜ#P–rº,¸½°ˆ"¦¶V) ¯U¥›ç¿gÖ†2CÖ'иo3,£dŸ,—Òx©òÂpˆ0 Ñï÷uP<ÏÃÚÚΟ?¯û´Ûmt:ê–aDàžF†2' Q*~ú!æ€ï0t} åŠpZ3j­ÔeSÞ…0ÍCR)È":êOÔ Ø…˜oXéU;²a¢Š{p8–P'Ú® ßvƒ‘nÎ  ãÇ™ËO5JU‡*µ&§úù ü—7L û-âÒÊòã¬ì$2ÉjŒîÁ]0!üÎïþþq"úmÎ9Þóîw£Óiƒˆë®À>˜ÕPÈ`Y\×ÅOÚuèy Û¹YÆJ@Ä¡«ø0&òíÛƒ+JËÊr-cº²ŽòÛ‹Ô[!9¨nÃ-¡í‰ #uœ‰„MßÅ)•× Œ‘,bê: -²×¡Gœ– ¡¡í‹Z€«ÛC}›dàœò˜¨’&Šøh|­RƒäŸb2OQgLÔÈ k½ÃQ‘R@µJp0p—4„OÿÞÌøÇq~½ÛéÌÞwÿ}xâñǰµµÛ¶Ñét°¼¼Œ‡z¨dT ÃÝn?þã?Ž'N`vv§N*· ÏNU‚Ö`Î~(|÷ªˆfÇ.7Ý6l„»Yi³‘ÒšdaQ1?×a˜ D+2eÉ Qz@Ã=Èþ|¶ø‰RÑÙX49ûÚ>CË •w¹9Ç«3-_%<ùP!LD¶d¯BÓÅgºRë„ *lÈÔ–yd(3:ö"Žh2ä§Âg<’ ¸KFÀ§ïNøÛ¶xvfæ#‡Â= ¸çÈ=˜êvE,Ëc Nkkk¥1cH’išâ³´)Õ IDATèÑ£øÄ'> ¥–búé ßǰby‹ÃJ–G8Ôfðe… %&×5—p¡F@,$Y®àø¾Å´xn)ÑFTüUxFÒk ]xq*PÍu„´¢‹˜*’&§ò‡g|´Ü®¯õ1ˆS¸¶…„K„—.BMö*°«¨@°ò!•¯F ˆ@/âX¤#mµnR€œ!’ÊÇÜ%ðéßûƒøe™Åý÷ÃC'N Ûí a¤3JzY–…N§ƒ›7oVާÜ|;;;º:ðÈÌ@ÎA¶ `c3NŒV[ÄägÕuÊÆFq-ÉÝXVB,J [„®L{Zr¥Àj<—•@†¨lAŒÃIõº}*‰Œï’ ²`ɾ}*Éàuo™á൦ðÐBg® ñÆÍœ828%´¼LÃ'SÁ—«ú1TtBõvó~S=’F?âXíóê“ê¶ó3ÿÕ|Àv„» Ÿþ½?ø4€Ÿð<Oœ>Ó?†À0Â)äO’$W*zff‹‹‹‡•eÂÕº¹½–HH}m›à!Bj·‘˜Cê89'³ùEÌ…ž=LTH/Dxn ºè.J‚1™›ApZ[ÖñJ9ÓñQ*Ær,&‹˜ŽÑ|4åͯ%ZžŒeªD(]…1<:·¶WðÒâ:9:…‡xífSž Ë2íß&cYšÇxÛƒ™3°¦¢®? Q¸øœªÖ›©ÒÁ]`Àïüîïÿ:€Ÿ˜ŸŸÇG¿÷#èv»áM®oZºh·Ûàœc}}‡FÇ•×(ÚŠÛràycàƒ¼3F‰Á†Œl7e¥O¡‡ðTt š „¡Í‘íµ²ú‚d¼ìÍ)€%ÙéPúìCY³ÐbB¼o™EL)#@%1|”:!?©¼Ÿ0Ä…sQx:`h9>¾ï©{ñµ×nâ«gWðÓ÷`µ—àêFˆ¶o£íZU]¦$eg¡ÖT8©8L?"¬ö°ŠŽC!§Mä-­Ìôsp—HøßýýY?íy~ð¾®ëj#]9Ì6Kı, ¶möm¸®‹ÍÍM=zt¢DJ ¹.`Û°†Ã\º¯Bz‚Ê“½$‡m¹ ­¶Hò2â0úrÕóUñ ²I,2#™çÚ"ã/p„'¬¦Õ¸qü:ˬôòžâİWpA臡0xŽ%T00ËÆw<~–V6°xu.Lƒ\ÛŒÐ9¦[<ªçÈ9à «â¼,S ˜Ðù× TÜ6'ÖYGBYô¯?å®ð á)xô‘‡á8†ÃáØ"j¿"ív«««#~)1ˆ1Q&ÜqÀ]WÄYû.ÉYUL~*‚¶ ±hÞÔ£Î}gA¼aJ¦@#sÊk "#bÌózû8Œ@¤”HÜ“Ì*ä\KÔ5ÔÞ0¤)ÉF(â:¶mãèÂ,677AƒMœœm£ãXÚŠ±>HÐv-Lù…ŠÍP†|Ê**%6*•a{b+” 8‚šù¨s1@µ–Âòyû ßòàô©S þñÏÿ“Y@í(ä¦oYˆSSScC‚ÇV d£îy°°4AÊE îa*,í ¢ˆfÛ••e=MǨ#®mY ŒD]þAÊ0L‘,¤)º ¿½#qJ™2"4ñT|€ˆýO¸Øè»Y÷#žœæÇ7¯á8fff°¹¹ 7ÙÁ=®´ãa¾#Á0!ø2œ˜ä½©ÑÔ÷7Ð^l‡¨€¼9HÐ3\}DŒêl?ŸÇ㮤T×ààà[š(ä—ð>|¨±ø.’f"":tgÏžÕîÁ:7/VʼnKyÞó@›ÛèíÄØx”À±¶'Äb… QELQ“ûP¢·NüÑ%¼€„„±/°¥»ÐÎ¥ T¼nÕu”Êœ¤ñ‡ !Š·w,†é@F2J &¡J¯å8¦gf°µ¹ ¥°ú›Xº8qÏ –w"pžu fȈPqŽÅ©'œcµ—– ”ªêÀ{Rñã,ïxP@rÌ팈c ‰´ZkéÁŒòSŸN§ƒápˆ~¿ thpt:­j(B1K.å|QP³7„{(@×Rùí› ÈÈB¤™‡‰Vº½c]ð]À‘DbTNÁ¨k+?{\Ê*Á@"òPÝÉ&&“<×qÐí´ÑïðÀ!ßx~)î?:ƒ~,*Y<°Á¡Y „d²>H+]¤‚XPf¬1Œ{>·Þñ JoU’$Ï:Ž#­ÁYמ&/¡²(_¯×C§ÓÑçë‹Êqâ_ºt ¾ïãÈ‘#pG×äË$»96p 4œ±ê&jÀô«[–HðQÁA=Ùj\óë@„ç*ñ’ÐðæjC–h“rôª8'À²!úz‚ó+ až”*[8^€´7ÐRÊÍ•m}½^/#ŒÁâ©ãÂql°0F˜,‰ù“ ‰¸a’zBÈ…1N mÀ”Ç8‚ó „/TþmrÌC‰(•A±lªÜ„ƒï&œÏ*̃Yð¤6ÅšeAHªÜx˜¸; +ÚG” i˜)טeØäÊ0áØˆŒ¾l.ÐÇ[s¾ÈÌÙÈüÜŠ €exÇ€òW!}qÝ$YÍöI^ziPvÎ9¦§§±¼¼ŒÓ§OWžΜ9ƒ?ù“?Á¥K—ðÖ[oá{¾ç{ðä“O–EBÎÁ]Ü‘ž€4…Ž£m4¿ÌØ–på5É ¬ì'“q ˆÁ¨œ “&̪¤`.uªxÊE¹®ÀR…m€¨[0 ˜ª„¥Ê‘0„öC¡¾¤©Š<„&±ƒL‚ªËqûݦÞY¦_œ ©‚sÈ ½Ðy  ´« (’å½R "ÙN,UÜ^ô&tmQœä¼hDГº]"B/L±ÖO”½MÁ,YÜ0ÆÆü3’ÅÊ»UˆzÎð_W2¸åpÛ @¨{›ÆŠõ…õb7“pÎDÉçæ?„™ ÔƺÝ.–——qìØ±Ê<‚4MÑëõTsÞÜ6ÎEN€ãÀŠ"ØDà–(æ2ùGèÖ6#N†$Œ „ŸÄ’¯c˜¨®—r&tûTèÝ Ñº°íAÊQzÍ©²j=ª|y‹¾&·÷WÿTaÓI@ ä9>3"?¾Ôi˜zÈF9âLZh2Ú(ò0z×~Á-#5œhÆÑëö;~$×7¿sª/*= Š>˲0;;‹k׮ᩧž‚mÛ¥ÜÿºõJ†@îy`aˆþ0Á€[à²{¸kSŽ@HËÈ'd„nZº‰ˆ¹”x¦\Zò:ž .ž,+®ŒzõÓ&cüò<Þ‰ëw¡àö"l×wϱtc2WL—,3·g…SRi ‘y¤Í1ý*Q½<[*ÙqWŽêÚ ?u`æ8Ž"B¿ß‡çy»4ŠÉi`œ#õ}´à F å¬ÖF.˜Äü” K~$ ‡‚g‹dßœZ• Ë éñšÜe!\4”‘z¢¨GÛB®6¾ÕGš×UD,Û®TA\b\â"æAN&¶UýÔTZ Þ‹ŽÇ»û‰©ði|ù}ƒ‰ @Ó䚊}ujÀ¤bûÄܽbYZ'eÉ™ð(Qj€ïûX^^ÆñãÇG&5"¤žnYHúC$Ó”ÓsGÏOr>ÉÅ#‰ü1Õ}|W"¢ŽÝš(,U„@qZP)ú‰* *öyR·<‘4KhÒ×Dö£§\ ~_µ6—Qm—ÁµÖ‡”Çé1ùÒ…FlËíVa‰M_œ¢h0Âp+hA#0a¤]Ýö¦RÀ¾‰õ“\—øÞTÓày¦§§qýúuœ´Ì´D_Gå#$—*F›cÄÒPÈõ<ª¦uzÿ(ÀØñ˜:Œ$çoŠ£¤ÝˆùuשZÖ­7:¾˜º»P*c ív7nÜhtÞë¯¿Ž .àÔ©S8~ü¸®:¬‰€dM<`É`r]m$ú6CBªžž»9‰àŽ+8°j¬›¯ÙWýj€!k4:Ô‘‡)gp-QšÛ—yÊ0J·¯ŸA¶KA¬† ƒaWö°Rä*‰k9$8ÏÁ åÖajg³ŸÁÇ&J%1àÖÉM$€½Šá“ ün‰À¤Ç”öÓˆæÒMÀt2ÆtA8޵P×uñꫯâ7~ã7póæM|ìcÃ'?ùILOO—Û†‘ìȹH ò]X²æ_"9½ÈôˆÞ–ÜÞ5 ƒŽK½U÷Qº7á¹)0y*üÖµÚÁ·²z„„f;¹«qB ¦zq*b¦ZÂéÊã£ÒˆëÆ6p; ’RX¦fì†ëjÏÈ4ÇÉgR–Ûo¨%’û›Ñs£#ö[oúc¶Mz|n¤p/YÙEÀÃêê*fggË3é”~æ™gpæÌA€³gÏ"MÓê’âŒ|` v8DÔí"J²Ä‰] h;€ï £ññé½EÈ"3'a< cÁñ¹T)WpeOe’Ù⫚˜än ÙpAX†‰>rl!æÓ9 ሄQÒ›R=Rë¡î¯Šñ’<)Çù ¶*œ¨¤±ÆPÄý1¯ÝAU '¨{ª"˜`}Ô¶Q˺õ&ç5WH{ 2#Ñcp]­V 7nÜÀ=÷܃Á`;Çq„aˆ0 ÁÃÎÎNŸ>¹¹9ôûýrbÉ~®ƒ°b£c¢ ¢V_à‘Ï…ªÿ?™h_¸˜T)"ÙCP%͹à{B²p ¸h:â6½ÅÙ(ÉeˆîEÌêJ§%ó,†¤ÐµhÜ1ÈLD9!^ Jê±*ÑÛÔ„ÄmL€hú|Vm#ØÎæéËÁ‰M @‰­ŠmãÖQ±½îû¨ë×Óô¸êm{ù±¤ý MS]ß/IA€•••\‚4Máº.>þñcuu;;;ø±û10¥š„D2ÓÇGÚ Át}‘ø£„–köÕëÇ&˜Üž ¤†žLóå”%ãøÒ]h3AdJ!´Ï0²ÄáÂF=NÏa˜‘1"~¡ M$ U($IíGœˆ*ÃLÝ#Ýš,{4æ¸E_¼™1ß'„ÆÌÿ‘hî(ª¦zP”0b¹Û}M~××¢‘€ùÒOTú¨íÊz¯ÜÝn«««•c¦i ˲ðþ÷¿ÇŽCE¸ÿþûÑï÷s×ÕÀ9à8H}ÁMrÎ`# ÉùMP¥4YÇ/î›tÛ¸kÀn㊌XGÍúAˆõãÆ¨=–*~ÃIÝ‚¦'¥¿Ã0ÄÚÚÚí¶&&fä`š¦ØÚÚÊm¯9îyàÄ€Á4ã‹ò` @·ß‚xŸ†»ÈÞ–ˆï(w!5òÕ¶·aó!M(¯D’2¡9HÃÜ fèG}ѹ Ë0ÛfdiñâÏ–õߥ¼Ao$Û. 2ú;â5!Á“˜ª¬’“€QÈ>ù÷S¬ßT0òX’ @w u!ÁŽã`cc333¹ŽCUõðš¤s×Y–ˆœ›k87d¡À)!L™lß-2 }É하<.&ßœ«Bú”€ N?”-ĘòE÷"[u Övƒ†9,«ƒ:LDKî8e°m†C¦ûðÜØu“oð°ötºR šŽc´?`]¿Æ%ɩߙ#󞨻­Bì;B¬Ÿð‰™Ø˜6Û¶Ñjµ°¾¾ŽGy¤öœF 6 ‹eH°†Z]©Ò하¯š‡¥ßž86¡e ÝÛ±Åù* fÜígWº6g@œ2]x”1Qt´­bHÌ!©qGVBe($ Boôc©ç;L´'“ê Hx+Æ?ÃL°/HÜ9QŸrw˜_–·mÕb|í35­€,¿¹|àÁ@-xíÜ9:}ꔚšêC¡$H³/…9ýQêF¬ïá÷2Ž^çÄw  2Ò‚Íê@£†NrMÕ0”<VæÄÑs€é†žQ*8fV1Hˆ÷¾#,ùŠŠg D´CöÄÒn0HD0Ç:žàöÊÕÖ¨ÄxÅE8ýèÅ„8!¸ÃŒÏÐò™æö™êÜàù)$J˜9ÙŽ=îð:³NnjcTŽ‚&€¹To\)†ÕÈ?‰ø¿_œ½éõòû÷é+ @¥ÏÌÌàæÍ›H’¤¶ ‘këpæÇ=ÖÎXƒ, ‰T_"Á…Ô‰_Œà2ìÙ™UTŒ›'=‡œJ‚ á™Ú›dFCmØi‰zü„чU`1£_z¡ *D²ÚQ›é¶aã<æüymdäÏ< ™ØÔæñJ2×®þ49kÿ¡)àÆw“ž2”=M¥€Ý ô¸cw3#xÀ´LOOcqq½^¶m7ò*ŒŒj„@7Àýâ0FYˆ’,ñǵI#¾ÙâkÃ,î°, o Wm Ý>PeȤ_ŸÍӔ埔€ÞPYòe›sŸÉ´^q̸xƒâüÍgU\gCö#$¨Ü5o“¾_MŒ€æ³3·™ÒA÷' ŒÛvçT®Š˜LO€eYð<I’`gg‡Òƒ«€ˆàº.è¬Àʈ@ß!Ú‰°eOƒ“Èã¾Íeê-klÉϽº$ôí!g"µWÚ˜k©Ð߬…˜:‡!{·ëÔ e›H¸DN¢ñ\K¨) 2eX¾e“T)Y­XÖéõõú~aË6ˆLB}ãÕçPqk5Tq€ôb$xíÜ9€Ó§N©i˜úñ!¨v¸ÌXGű¨Yß/Î>™z0a(w˜¢»2ªôà^¯‡£GŽâÐx6#ÌL§«›“Hʨ—BèöýP´·X–¢ì¨ª¿»ª:6û¢þˆI“‰ˆ£Äú„e`:î_)…‚ð×…W=®œ8]û<VZØKMÀ*ÂZ„ÝJUû'Aø‰Ïב}ûðÀMO´Ûm¬¬¬àᇮ=Ƕm\¿~Ï>û,,ËÂ>ðÜÿý ¥ˆ@렕†ðÜD[Û•˜ßär✴ c¦EùÀíÁ=GTJ‰M\Ž[A¬¸},Ðsw„AÒ$*O_x D@Ûf|Ò<•úÀå‹ÚÈKÀ ÛtE a'×` h¹Ls{ô¼÷“H¥s96º$cæËÎ9R+˜èHd–G­&Æ®æ7Päa" @ºÕWÓX4eƒ`pßôø]ž#Ö÷ñ cæææpîÜ9Äq ×u†¡–Àó<¼ùæ›øò—¿ ØØØÐ½K%ň@ôz"]/dÑûzäȪæ?C˜0É‘)àʶݜ„ß¾j´Z5BbV”ƒ¡õS.¸|ÇSIȸ…ÝÓÛ¦„€ÌRÌ–JûÔtô6)–pΕ*e10&»ŠãÃLöÚÝËDµ_öZ¼¨5?Eh¢`̶Iö7>v¿Œ€rF@U#Pñ<¡ âQǪôá ENœ8}èCˆ¢¨ô²’ý‰sXqŒ´ÕªD'fœ£Ë§L[òÛŽàö®j¬‰¬ˆGò«¥ŽË—¿`œÈ ÂDàÏ´Ÿµ'@4Ð1ï.yicÖ÷¯–9 ÀÐÍ™9xšê¼ €Á’ˆ¯NÒ?Ëm\´´V:F™ (û€êIâAÒ‚‰ @…:Â*!˜ˆ¹M©RS…¼±hN&çì£×õr·Uë@Çq`Û6T™pUÿO! CÜwß}ø©Ÿú)üå_þ%Þóž÷à‰'žÀææfÕÀ`Š¢ahÅåk†‰ØØ„V ,ùÀÁxù*.¯[ƒÇ)Ћ~,Z„{Ðò²ÒâÀø*D{*™ÞPèc-¢þËÔi;ሓ<å ³`ÙYÖ;±ìsþ9bR—ÐÓàEHö«1ˆ"®æwµœT*@Åò ÖsÛHvöfÞ¿Ù# lnnbaa¡tNÇ‚üàñÞ÷¾³³³:3°ò'Q –E`…"¢*üwŠŽÁ6>T>?QVàCÿ$ I!ËP"}˜±¾íµD—"Ó®Õö¢×«óõüj¨ÚžíHˆ Ê"ܘ„4I‘H1ŸY²¢“U|ëé‹¡ö.n®Cn2þÕAˆìšTH™$iÚTÔ ì*§i:mª¿ï› Pq]ƒY&\I333¸víyä-˜ Z„Û¶õõuB\9>¸ã® ;Ч)³Æ\èöAJß™ IDATÒlà;„™vÖÈS7û¨³ª c‚x¨" ñ. y3 /ç§üà¹ù¸1Ì¥øôÖeÃb–xA9!Šb!æƒÀ˜×q´n_|¨´R¸žÞ½,½E:ö³5˜y Š(¢`eŸÙÊkÉnS‰`’ckÖ÷/Ð|•`ffËËË ¢R™p…xf-À&ÉAÜ÷Áú}DqŠ\¤¡å-—àØ"(æemÔ¼U^A |?È/,ùÂS ;ܾXÅhR¿ý~ {v ,¦Žqœ ŠcpV–mÁb–!ýäÛžQÞb`lo€ê£E€l»úŒ¸íƒô‚vî1ÆT_Àâm+[€y{Jÿ/fVIÀxä­ã೺Ohr¬ò8ŽƒN§ƒ7Þx€p V½ø£TÉú6¶¶9Ø”…)Wpd›ÄÒ”ôËÝ­”~/J~†±…„‹°âyé·WÉFuÁ@{ÕíMId’qÌßO•`cà)Ç0 ‘ð!Âp(Ò´–%:–o!ÛVŽ'* ~ñä] ªi¼°oÀÙóçÉ Ц)dêÚ®Œæ/,ûÂæz!Ø7»€ îÒ´}?2PR@ÇH’D«“¼Ü9ñœ1Ù/0€‹Gü¬í‘x°©RÄ1ñó©·’Û'bƒo¦|a7`  †mÃÔœÕs˜vóì=ÏÓ•˜`mm ƒþ)O‘&]8ž×ìÓ(íœ/_`yÕŒ̹‚`䯭>§úéÜ:jpíÁMºf ;Fgu F±­Â÷}CøòºPî=ztß"Ï”þ¯â`uu »s †ú6ƒ†9`áÈ%¢#uû0fHÝÞ³ Ó>Á·IHÈ¿Üû!¢Ou„ÄÌöó<¾ïcee/^Ä¥K—ð¾÷½Ä×õàyà8°¥MEG}Ë·oÔ¯­Õä5iÅrcÅwósëa_ ÀÙóçswñø£šH®Ü„&²+¡#÷¹ÈÛ Lí¨‰Z0jßÈs'UFA±°R¦¦¦t™ðQ©Á£ÀôÁ“ã€l, EmÀºXtyžH½çÇ)И®µïÛ„Ÿ`Û‚˜1{*ãânÇQKeSQã]»v /½ôVVVà8Ž9×uá¹h©©dÜ“x—SÁ5R›Ý&yûñÐöu´‘p€õ|M @!>y F‘C†f`×ëDØ·@ S”>ê8fffpýúu|û·{9ѧF!³,ï‹â #€:=!`'TÜžÉìA.Zy™ýûÜßn|b>“ιîµ`Û6vvvpöìY\¸pqcaa=öÚí6|ß×Ï ­§‰òìÙ&2w0æ¼Ân"€8ªªkÜ"8P $‚‚$ä%@ª®ÈŒ¬°4‰tÑX¸ëûÆýMP/¸i\ZZÒvU  ,Ë‚ïûHÓT71çʤ\žú>œ I@¶7¨0¡Ø¤$ Cù„[—5€@4Y$ô^ŸU“ó‰²2ëJ¿Ã—.]Â… póæMÍíï½÷^LMMi¤w'W1ÓóG[íJb¾R{ªö§× +¶—ï,´ý(]Ôäp+$ê1˜†@‚(«ö)ŠÕ€¤jÙt½É÷=ƒiP½½½]òñ—*ñÈy}}]s½8ŽK‘fĹp¦)X®[ œÒ÷c â¢wàHÝÞ¶î¬Ôwó{ÊÍaâ}}^h­æû¾ÞvæÌ¼þú뇘››Ãc=†N§ß÷uñUÇqtv†y±Þ´4•&2Æ0ñí²+õ#¾¼ÞO¯.oÇWÞ\®ô#þóÿlÿ¯xK@…‡€ @UmÁTÎKƒI†ŠßÛ öÓ»ˆ¡ø¾¯{x¦EbY–Î9ž~úi|ýë_ÇSO=…}ìc‚ ÇÕ¤žÐsí(BÜné"ÔA´ ›÷8<³ºNÅàW—·ã+—Ö¢+ƒˆ‡Æ¹ë¶÷{ºÀ­•˜€Bd•+d€Ì-¨ˆ)ì‡AÐXßߢl&g4 €ïûXZZÂC=TyŽëºxá…ð›¿ù›X__ÇåË—qúôi<öØc•×!×ÙÒ^[­9Ä1à0”'¸½Yιîß·i@!¾çyèv»DDä¹sçðú믣×ë¡Óéà±ÇáC‡´noÛ6\×Õ’•’¦Š×¯B¾üj(÷IÞĤ:@B‚"EP53/!Î!™¦-ÊÎsð”ƒóQJÛ›ƒôêÚ ¾r};¼¼6àfâÇ €8Oº,€N£‡:!Üä }EOCÙE¨ (ìá ëûP¨ ÌxÇqÐív±¼¼ŒÇ{¬ä-„±ëâÅ‹ØÜÜa}}­V Q•‹̱AŽ‹^h!MRt.Cå 8á|÷Ã?ŽˆHC¡©ä¨7nà•W^Áµk׎9‚‡z¾ïÃó<´Z-X¥¿xZ—©> ÿBðÂwùWDDês.l&²“q¯Ä¹ü.rÔ±rB“t{kȯ®l†×®­¯­ÒMf¹ÄÜ`À[³“c¼ü|n0 ‚Å7Ãô(tj,UÔ`рؔ4’B(æX–…N§ƒÕÕÕʆ¡DÇq°°°€Gy‹‹‹øèG?Šûï¿Ãá°<¾1ÃûŽ¡ízè"-øí÷P@cŸÜvêBX–…V«Ïó°¹¹‰sçÎáüùóèõzèv»xôÑG±°° Õ•PeŠù“MDÿÑB¿Bô ƒ«ƒ)çºø‡ªü#=“Ô½q.S†)_™S¢p³Ÿ\[ë%×—û‹½X´²ì"¾Îlχí¦`Œ ˆïåWñìd7Þ n—`‚é(~ª8~U3Rìb=÷½©0¸0#»Ý.®\¹R‹`išjqq?øƒ?¨‘§$bK6ÄW¼¼×Þ+GßÀÇq4€õõuüíßþ-®^½ ˲pôèQ<üðÂ@øï=O‹ù&ñ7WsÎ 1ñþdŒÁ9G’&HSŽ4M‘rÊ]eˆï¤ôy…ìͼN7ûñµÕ~zõÆúðúp¶CÖÁÓXV`œY,Ëö`Ùœ©ì#ÆÌ 1fþöž;÷?è »þFÀí$ •®ï *‹hæl¼ï €ŠºÝ.¶··±³³S*÷@ ùþïÿ~¤iŠ(а³³³ç`šý2ò59ßtáù¾ Ðï÷±¸¸ˆ .`gg³³³8yò$fffÐjµ4²{ž§­ùuùæRƒ ȉ­­-q¡? !†mpâ²Â+EFY5V!ïZm•Ï@üYÛ‰W{ñÕ¥­ôÚÍx™(eH“eXvËñsÀc°ÜÌJ‰1€Y‚„0)U0#~³úõ{îÜ¿8än10ÄÅÉPÈïÉïžÜïÊ"E· ¹DÅ÷ª·µfÿÁufP/³Ò{mÛÆ[o½…{î¹§¤Û3ÆEÞzë-´Ûí’忸ò~ƒ" Œ1´ÛmA@Ää¿ð Zê9tè~øaLMMiDWÜ^qzu*ÜW=;e (Âòò2Î;‡¥¥%,//cccßû½ß ÄÛXßJ°½ãƒ9.†Q¤ÇÍTÛ³\Ŝņí!¿ºÖ¯-m„×ÞX^eÌJܳÀ,Ûa°-8À˜ A´”P‘€Ü®@zyJ€/œûÿ›»ûEšÁ-#äWKÅå¢W€¢G`Pü>îØ}SÇW/·"kkk¸ï¾ûFž·½½=ÒØµ×D›ýR 8çZÌ÷<œs¼öÚkxõÕW±µµ…ùùy<ôÐCÚo¯b÷ÍD)3ˆGþ˜Ç1nܸ¥¥%ܼy+++ØØØ@¯×Ó]—”úàû>†Ã!â$E”$¢Õ;„Î.î;óèä*ñ-K Åf?ººÞO®-m%W/­ÆWÐ#`1Ë·ì@ ä\œ—ž«¡d3KÿV¯JH|þÜÿò÷Ï5ý]v ·K0u~%x|ù=@¦ Ø(€*B€ßG©û ¬/`•»Ýncmm ®ëŽ †1 ‡VÁ^Sow ¦5ܶmLMMˆ°¼¼ŒÅÅE\¾|D„Çãĉ˜Õâ¹eY‚žçé°]z½®]»†¥¥%,--auu›››è÷ûúz&¢ÏÎÎjÂcñ\!?–´ØòyÌ’ ”1 BZÙùÕ•íÁÕKo ¯ bZhÌjòˆD© @[£Y¡–7A‹øe`Ìú$8ÿçÏßän("d‘¨Ï8Àn@ýyès)²¦§§±ººªEÜý°¸ßJi ´Ûm}ÎùóçñÚk¯auuív<ðfffZ­¦§§vã1ư±±ÅÅEܼyKKKX[[Ãææ¦{VÅT=ÏÃÔÔŽ9¢„¦4¥Ü«¦‹Pm³l¶ÃD°eò‡PÅ=³ÐøÊÆ ½zs;¹ry-ºÒÓk`l°°Æk«G”{¬"÷²æV¿ZTµcÀŸžÿÕïºÚøÇØ#Ü FÀboAñMÝ¿Jÿ/®ú>Ò@8 @_ÈàèÓÓÓ¸~ý:úý>lÛÎûŒqë9:0šˆT¹ð–––pþüy\ºt ¶mãèÑ£8uêT Ù777ñæ›obee+++ØÜÜÄÖ֖΃PÈêû>:¤Õ3¬Wc"¸ù1 ‚©2¹N Çf°m̶‘ÀÝÚè%WWv¢+çWâsý0}SÞ¢Ëc²`ÎÈ@u;öÿ]Ùð‡~õ»6ö{àQp;€ò£PáÔóá"çß³Õ¿ôý€%€¢ E¶··Ñív÷ÅЗ‹€Û‰@‰øŽã`vvŽã Š"\¾|.\Àææ&:ž|òI:t½^KKKxå•W°±±íím ‡Ã’Øî¿ÿ~mù·,Q¥Ô’’Óo"¸Š0C~MÉJ'þ÷’µµ²^Ù‰(í¥üâ¿ùÆê—³|HfÃËôÁÑä-( ZÍùÿðâ¯ÝZäno$ œB$%rŸJRz1Ëâz“ïzÛ­LŽÆÃÎÎæçç1 * }{qÙíE­Pî»v» ˲°µµ…×^{ /^D¯× ŒrW¯^Å7¿ùMÝÄÔu]íö›››C«ÕB§Óçy%­b,Ë‚¥Â¥ ÏÇ ñ…èê;mƒ¿ÜÚÚúÊ+/¿üüÿöå©'`û÷<úðÑy8–f·¤Õx³Gh<ോ¿öýþ~_½)ÜÒHÀB ")²öb‘œSŒL0Õß›€ªm•ß÷M?³BHõr·Z-lnnjD8hj$Ìš`dúý`0ÀË/¿Œo|ã8{ö¬žëÔÔZ­–6ä;v SSSѵþ]¡Ÿ €®ê£¾œ§éÏ/ºH °EÑWz;;_¹téÒsŸú…_x]Gÿà?} #fkÉ€·"ȶp•êK^[ü—·ù[,ˆ€¹`Ÿ"ó¨í¦`BQ@ƒïuÛv ã$S\Uv€©©)¼õÖ[Õ-ÀqMWâ^Ãz‹RÒëRÀ`0À¾ð|ík_Ãòò2|ßÇÜÜŽ;†ÙÙYíãW;¶mk]‰ôE1ÞŒƒ0磂 ¸l…nX×+m"D¤þÍ7ßü»OýÂ/¼”ÌúÞ J¾j•v·[ z×ÿå‡o+ò·Ï –™Ø¯Â°LoÉýž\·ŒcL¬)bÐÄD`”p?Tõr*077‡ëׯ#Žc<îÚû ¨¢ôhW\ÇxþùçñÍo~Sõæççqâĉ\ν‰ü*ÏäîJ?Wo®¥!^KXYiîⳎãø+Ãáð‹‹/>÷ ?÷sgÔã,,ëî:¿P„Tí>[kþ’uðÜÿë‡,ºo¸^3x´(©È’ªjaRU °-ºß`•(½³³£†ƒ±ñîæü&!&Ò)ß9 ¢ô¾ò•¯àÌ™3ØØØ@xä‘Gpøðam¤S)Ì*€ÇDxÁ«ôssiÎA}¸±ßf œI’üÍ ßÿ«¥¥¥óÿè'ò+êñ– ï[ýAuÜÍíîän(” ²,Àù4`ÂàÉOKnkAp|5¨$`oö€÷½™j€ã8HÓÃá333 ÕTP–|å“€ .à«_ý*._¾ Û¶±°°€cÇŽ¡Óé Ûí¢Ûíj„w]·¦k~Ô}™ËâºI´Lb`Ù6Ò4}1Œ¢Ïß\Zzù~ò“ÿ"ús_-rV÷‘ƒW=ß b =I|óÒ¯÷ƒüÀ‘ ä¥Õ\ÈM:§ÊuSg ¬ú®·T2qÀ¢5Ûu]*»¨Ñ“ÁeJ«òÛA€••œ?¯¼ò 677133ƒS§Niß»BôV«¥E~SŒW×0¿xíª{.î'¢3iš~&Ž¢7Ÿ~úé¯ÿO¿ò+ëÈ">Ç‹@“<Ÿ½³ïCàó—~ý»oItß$pÛ€! ¨MJßW€Y2|XÇå+â`êõf&^§/ÞSÕ< âô7>Ç9¿ºµ¹ùìþÀ¬ ûÍ|ä ¾’ •AÈâF&Ù„¤½¡|Ì~¾5¤`Ÿó7î<äî< À”YÁPETââjŸr*¤/ªc ÁAåè H¤ôè¹¹9ܼyS[ãKYj @q{`Ö××ñꫯâ•W^ÁÖÖæææpâÄ ÌÌÌ ÝnkÄW:¾ñ‹ßœwq½Ƴû2€?°àù¹¹¹—cxì‘GL7nQýS›-ãʿüÕŠüÀ@Ìf"?ú¨)Ò+I@Å ($7kq0ãꆫ¾ß2P¤,æSSS8w–3k4 Í uö(ŠpãÆ |ãßÀ›o¾ Î9æççqòäIÌÎÎj¯t{3y¦ŠÛ›ó­9‡à¯¬À@ø¢gãüâ"ôäIE´ÍÊOÊ\ÜWe×™,"QYÖ”¾7¹`ƒ¡¶üáåõ‘[Ý7 Üv`ÂÙó繌0_32Ь!À!DHù¢¢U®Â±RÀÍ¥¥×î9rtßî¥òB,_&\Yÿ‰®ë–êÿWé`uþW¿úU¼øâ‹ØÜÜÄôô4xàíÛïv»:~_¢AOÍÍ\ޏþŸCpù%/ÌÍͽ¤ÆªseV #—ÅŠ%áÕ6†F¾˜`ÄH{– Û,éýá›ÿÇÝÑÈÜaÐÁB@&(® Ô‚ÄX*U ¨CÖý†µ„à•ϼú®w¿§¿²òV{aáð>ÜIÍ yŒ1looëÆ&˜=p]ÝnD¢dö«¯¾ª;>|>ø fggs¥µ”~o"½iÔ3—øc"zÀ€Wæææ¾dôìÌÑfÇ(s¹g¨´7˜zÕS-[áÖÿÛ~úØ~¨Ùo#ÜqÐjZŽ›ƒ-û€*$2DB¬\…®ñ©2–`åæÍ¿¸zõêzÀ´Š›R€²ÐOOOW&µZ-ÌÌÌèíÏ=÷^|ñE¬­­¡ÓéàÁÄÜÜœÖí•Ï^Yõ‹b¾š‹¹4à*€ÿÀU"ZðêÜÜܳ*¿~¯ÿú… œˆðø£š¡LD¥°ËÕ¡ÇzU‚/4ÅÊ_G{ª6еî¿ÿ¯ÿhÜ©wÜ‘ ¦Ø””ÞXtª¥RÌCS´,½DOá¯þ퉇ú{Oòä»ßýÝn÷žééé{¹b8p·Ûç_ûÚ×ðúë¯cyy­V ÇŽáC‡055UâöE£^…nÿw0þÁ܈¢I’À“½ï8wñ"çœ+›@ñ7S¿/e†VI â¡ Ë}–†/L}ñ§ŸF¾qÍÛ Þ6@á%2?2är€LŒ Tå-PùêE2ÃOMSý˜úóKŸúÔ_ø ãíjüñðzè‘Gÿ“}èƒßwÏÂhAÁ ò1Ka=z/¾ø"Úí¶ÖíU°NCnÿwDô cìYÏœ:ujcggaæj÷Ý©`ÄùÐïbƧÚfªtÍÔ2¼{)K_œzú¿?ùßN¢¿‚·*]…E©À¬# ¸†RcŸ" L#cÕºÉKü?ŸùÌâ}<ð¯¯\½ö}ÿå?üd©ÊmL# ê|òäI<øàƒHÓT…1Üþ€?%¢/Y–õôéÓ§7†Ã¡n*255µË'{Ç€zæÅHASJ«»þWÚ±H­Á[>õ7¿¤¢ûÞ–œ_ÁÛ’™«(å(Û€âð!²jCÊEè¡ÚEÈOj,‹@©ëÚ•+[Ãá/¿ò*Þ÷íß6vîŠ8Ž£+é¨(Àb»k‰ø— Äùg£(zæèÑ£—fgg) C­F¼ƒ@=cÅí!(¾«fñØ1’€4RaÔn¢ÔŠ6òçZ:½¹?ð6&P¿lÑuT” ™A)4%fÚ2`Ñöp8ËzÍ ¦;0MS³bЛDô €g{½Þ³Ç‚  V«…{ï½wâôá; j€Ó5hzŠC£(ÀdÓcvínÚq—Ï|¦óÒom÷¼]‘x‡€×Î#túÔ)%Ú«$Af'P/L„ú !ù” €‚œÀ ‡Ã¿¾råê4™¯™ í—|‰ˆží÷ûÏ?~ü’y½#GŽñßÉðú… ÜHR¿›) ÀX*›€ò”\„,gÉ4hÇ[9ó™ÎK¿µ‚ÁïíŒüÀ;„ È¥Õ‹dr~…àf-Bõª˜œß A®"Z}éÌ7qzfæ‘0 Ÿ¬²¢è62Cñ~úÔ)EL/äeª{ \„»x–Dëîúë"9ÙßîȼC€a宲 ˜`ú•UÅ!3Ô´¨€ LÀ°Ë—.õ|ÿoô+ï~òü¶o{ê?ŸÉmѳŒ±g<377÷w»¸·o%àF¸°IT|‡éý©u €ÓRâ×çŸùGŸ‘㫹ÁLf–·+ìKüú’Öt#¶ S¯4-ÿ¦¨gùŒÃâͧèŸÿê¯}èCü¾ô¾|éþçÞò©Ïw¡„Àüí”äå¢ü{ºêøí÷ÿÒL¶7óS?úÞb6~ãß]\Ñ#¦ÿ_Ë 9ƒßÙóçsœÿíLÞ@eÈ‹<¶™U|Ôñ¬°^eVæèçæ?k{ù÷æï§ŒEu¯ÚE(%2¿¼Rréг?ýoPNW~ÇÁ;š•EHŠ€PÍzªÒ‹sƪ»ˆ¿75"Làú­j °Ïæëu<À¨8 µ‘ÇÏúÒ÷ Säøï$¸cÁo1Œ mŠüæ1UÒÂ]äß'¨AÀ*×-·Û~@PõHà äÿ–€w¼  ‹õF[wüA…$ÐÄE˜ƒRÆÃ¯úòÏü- )ãÌù|«Jªý.×¾s¡€¦±VÅ|$Æw"ͦ<ÏÔŒ ‹6þüЗæ+øâü ¾e$€:¸‹ðo/(HU.B-XÉà÷¦f†QÊ=ÇbEc=#žZqïßúÚ/CAšûVàþÀ·¸pÞžpöüyn ¨õi‰‰½•ç¿ÎˆÒKK[!@øÎGf[J`”®»›çûÐ×>uç/Œýއoy à.¼# è"dxpõ¯·“é‡ÿê¹WíïxÏÉCíï}raêÕ«[›;;½—¾úsÏb|Ùw<‡$ASyIDAT¼£îÂ; u@A1ØË…ðÿ{÷®0ðÿ:¤³ZN’Õ™V›Óõv_ö½CòC [¢M\^¶Üª-$°…A)Yù[g|k¢s«u €-uAS}ÊŸœ–þˆ ü›-Ì»ãàQÈ›7IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_documents_128.png000066400000000000000000000346751217176075400272660ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½Y°]×yç÷[kg¼àD²eÒ¢†"›;Õjv\–º•µc—«¢vªÛò”rÊí*§ü’V§S–9.å1/‘c©ìT\ê(V”hÑE‰j‰E‘ˆñ‚/†;Ÿsö°ÖÊÃöÞçœ{—IëCœs÷¼÷7ÿ¿o­-Œ1ü”þá’¼ÝðSº½ôSøNâv_ÀNÐ;Õ=zôcÌ<ð0üüìÞýóï9|ßÿ—¦éÿ¸çø©ÜF:zôèà5ßyçóEQ<2777°°°Àüü<ß=µÂ•œÿâ¡]+ë:~r!åÅ›½†Ÿ À›H5ûÏþùùùQ˜=–±þ[k ØûB µF)ÅwO­ðƒ³ë¼ÿà˜c  ßZNþÉ/îãÿ½ÙkŒoöoâöÈñ7¾ñÒ4Ýσ¥”ºÝîx€~¿OÇôû}¤Ü:äÒZO¬ÿÞ©ž{õ*ï?¸À¿ùØ mØ( Ú@ u'D7}ïx³h+ ö –R²±±Áh4baaC‡mk¶€:=z•ï^á}ûçø7;@^c¼§–0³oô¾êôZ®Å`¯¹qÓëõˆãc kkkœ:uŠÑhĽ÷ÞË]wÝÅ7¿ùM>ü†­Ñ0Wüøµ Ëøóüëì§Ð°‘— Ƭßn sçMݼ£w´Üƒûý>QMhpÝ/..rêÔ)öìÙÃ<@§Ó!Ë2„E¶½2Æ`ŒaThž9¾Ì_ÛàCïÚU1¾e@c™ÞØ÷æKƒÞÖðF ÛRÊ#7779yò$Ü}÷ݼÿýïGJI–e ”Rôz=Úí6ƒÁ€^¯·í5ûssÅ3Ç®ra5çöÏðºŸL® r”6H)Ýõ ÆYn «p3ô–€£GúôÈ_7ƒ…ßž©[i©gŽ1†óçϳ´´„Öšx€ùùy”RdYFY–áxQQ–%óóó\¾|yK0Æ µf•ÍÆÆóóó<üðôZ-Š¢`8¢µFb/0eYrçw²¼¼ÌþýûÑZ‡õZk´ÖlŽ ¾sü*W3ž|ð>þð CA,iÅÀØuªÁ!¦Ž;•ù¾eàèÑ£Ÿì÷ûyäÈz½^x¸uæmÅÈ›I1\¸pS§NÑív¹ÿþûYXXf~8óQ|]à|®¾k×.~ô£qøða¤”(¥ì1 Íß½ºÌ¥’Çßµ‡öÞ™ ´ÀÈÊÀûà®~]Ú fªº¿-À9B·ÛEk½¥¶ï ‡C^}õU®^½Êý÷ßÏûÞ÷>Ò4Å:cLˆ €Ôxª»)%ssscˆ¢ˆÍÂðÌ++¬9²‡ý{:d ÖËŠáÐdd]«qqÚLÙöfè-!GýÈž={ôz½7•ùZk–––8{ö,RJ8ÀÏþìφuyž4‚Àq&{7P'!­V‹~ðƒldš£/-ðøáÝÜ9Ûb¨`9ƒ©…tµcŒ0S}¦òy«åo€ÞÖ×û‡{#éÔõÐp8äÌ™3¬­­Ñï÷yä‘GHÓ øhhÆ ÆXfQ€HJ eâ8&IÖFЧ_º„”’<´‡~'a¤ W³¦ywG õ?jT“jß1 ±ô–˜Ô<¸9ÿ~áÂÎ;‡1†ûî»#GŽ„u>PÛîF„±êGÚ²B3* ÝTÐnµˆ¢ˆέñýÓ«üÓŸÝÍžÙ6™‰XÎip¯®õ _¿Åµ×&þ޲Ûåå7*ëëëœ9s†K—.qï½÷òîw¿»‘šÕ£÷iÂVÿ-1 %eiØÌya:‰¤•ÆDQę˛<ý“Ëü·Ý‚«#M”x&œª¬@ó;¬ÍuÆý0S6~GZ€íÈ3®žî ‡Cƒkkk¼þúë,--±wï^<|ûø1 )LãVGJaý´1Œ Ã0W(mHcÁ\'"Ž@kƒÀ Ë÷O¯òÄá]$qÄå‘u QÍG×™^çY}ù4b€-­§/¾azK@]+¯µÝ«¯¾Êùóçéõz(¥ÐZÓívÙ·o=öq¼õ-k¼[Æ „]¯”a˜k²R‚vÑNR€Ò>5„½æ¥õœÇ˜g³´Ç2€öãøõS1[-o\§[V‡ÇñÀpÀˆ/¾ø"¿ôK¿Äòò2EQÐn·™™™¹¡Ì!XÏ(£\1Ê5¥2$±d¦“FƒÁPîüV T …bmXrÿî.ËyeÂgµ©3ÚÔþ‘ÿx\`‚pµˆñmÞIp= ÏsŽ;fµni‰$I¸óÎ;à ÜXÐXjå%£R!´É\7BJkæu8&ÄR’+Í(×d¥¦›J$ á.;W„ŒA•W÷cÊØu™êkí¯5w2î!v‚Þ2°]¹r…cÇŽpàÀ~øa’$ ûM«ÞÁö‚0*4ÃL¡Œ!Ž3í„Vâ˜d FÛdMJ6åŠA®ÑÆÐJ$ ýU–y‰g…×Ð*…Ëók ÷‹Â5oõ\˜D«ûÜòönˆÞ0NEQpöìYÙ·o>ú(N'¬Gä`’áã‚ ´ èF…Fí4¢H"9Ú}JeŒY©‘:-»½pçÏ• |¤n@HŒÑM¦NQá©™@Í3xæk¦·n¿“@xM^^^æüùóŒF#î»ï>>ò‘„|Þ~­Jž"8ÆÀ(׌ E©¬¶ÏvbÒxzEÁ0W 3…6Æ’ù^B"…3ÇÎ-ábÇ&G°@Ò†h\uÍ8 4íA4ó~㬑‘“÷üŽqBˆø™gžy@)ÅwÞÉ¡C‡˜µÝN¾šV§í„Àj¯óíYɨÐ` Ú .šò ÁZ‡A¦È ÐmE´“ȹtƒ½ûÈ¥´ÁR­-K~àc?c)áþ­¡ßiqÀVþjÊxtÛࡇºãÈ‘#ïÿä'?ù©ÇüS)œRj[_^ižÕDéR®¼Ô 2å"yè·#Ú± ©^Þ5ÆmŸÛí½¶Ç‘˜83JÃ0+æ”v¦ÙG÷X)ÐJ#]CG8b¬)r¯ Z^Dz£tK ×ëE<òÈ‘÷½ï}ÿä3Ÿù̧|ðÁ÷ÎÍÍ¥`M|Y–ûl¥ñ^Ûµ† çÛÚ‰`¦Ë:šæ|;¥5ÑbXT¾}®+‘SÏa—¥f—ä¥!Ž$3„2/ÉsÕ¼Ö:Ô;Æ1ãT<vcþ`" 0 œÀz×P·o €hïÞ½½'žxâñ_üÅ_üýèGÿñ}÷Ý·ß§oeY^“¯Ã³Â>†¼4 ó’B¢HÒoIZÎl[_í£r»ï(÷¨Ä‘`®“ÆSÒ3N`˜)†ŽÉI,Ù5¹óÙ$¼f )ÑF‡ä/äõþ‰Ô·­ïÛ¸çÊÔ™ï¿Z Z­ÖÞ/|á ú©O}êŸu»ÝX¦+¥&vØVÛ±Û¦Óvc Dô;.’w&Þ!0 GŠQ©‘¢z4²~Ü<ših»¦PŠXJzí˜vrívî&P#ÐÚESLv-¤©ópü¶»ß©À‹ñFéÍ€¨,Ëþ}÷Ý÷H·ÛmùF‹ÆFÛ¤oÒª°`2M® ±ôÒˆV*]GŽÆ@ ËÔQiáÜBiZqÄ\7!,µ©Ãý§óí…Æhè¤ývºeÐX(C¡´;VíÚý·CC N¶•½!X,{ï5ŒcìÕsÚâ@7Ho¦@*¥†?øÁN|èC:8 ð7ÿ>¨Ó¹bTX-h%’…VD$Ït¶W6]ÊgtÓÈÅnûÚ¹ý¹ÊÒ0(lôE‚~+&‰ÅÔxœK(œq–ÆËHC„À ÐõâSÀŸ±ÇajÇÒÆ€AÛÇ·}ØË½òÊ+gÂ-̼1!%¥áÈ\RÐmIRÇoÁ=xYiª<ßaøI,ƒKð¾²r#0YdÏ8doWßk» ùwmfЬTH!- Glnæ”å8ÒïïÅýÍåx~µÙ“µ6 8x|§·ƒ {ù±cÇ^õ­Ôõ²nƒ„@Œ†äW×{î`¡ Qd}»v±”‚Èåù›¹bTÚ(¹•HfÚÞ·[Í ‡uߥ²¾=/ ‘6×Oe(ý]kô4†¼PlfVÛ[‰d¾›6RÄæ-€ úýhmˆäôÔm"ç§)ÞÿO€ßçm` VèÕéÓ§Ï,//ç»wïNëÀNÇœß èLKºV­š¶y¡šBC+̶#’X€±L«€çFŒ±n$·È^;qÈ^T!{ŸR Jâd˜+"iƒÆn*]€6=VñTÊB2¨µvqLŰiV`2ÇweçZ&0No—~ è×^{íââââÕ;î¸cŸ_!¥dmmN§c­1˜4µPjY"¤ ‘ÿ ·ÍËÄ™¶p± ”ΚyCé°¼ÔH§íibs}£y#*·2*4ü¤T†V,XèÆ$q5ÈÄg ^BÏ¿1”ºb”½§µÂ’´©™Aã»nö'¢|o¶ˆvÊÜŠ)bôp8¼xâĉ×ÀÞX’$¼ð üê¯þ*Ï>ûlhÇ6Rb¤D…6¬Ë›ŠBf:’…~L7µOO5¢Ëü,×,o–¬J„0Ì÷bz1­ÄÚaíBm)ÊÀÚ°äÊzÁ樤KvÏ$Ìõbâ¨b²'ÏüRiÖ]ŒbŒE ëÞÌ ƒ0¢b^ n0µm&>n½ÖMí¯¯³7^`èV Øxå•W_«ýËËË\¸pv»]=h&IX_PÎ$´#ÁLÛæùZ»Âˆ;¨êJ­Ù, Yiˆ„ “JZ‰ (¡k1…ªàâ8‡,w´ñ¼Æ 2Í(·%äVlS­ÒqÖÔƒQ}ÆÕ§ˆõÌÀ3§ùÚUƒK¨ buy;B·"ÔÀð¥—^:öfYÆO<ÁW¿úUöíÛGQak“¦t‹‚¨#”­Á+ÇDáAm sñ€6F‚ùNdƒFjZè´½Ô†ÿ :©­ Êz¾^Sc_Q,´a•ä¥&’‚N+¢“H °±>v£ÞMPgºÁ "jlWgz]¼n‡ŽenQ;vã|7O·Êä'Nœ8eY6E÷ß? pÈHSâáå¼p¥W«í°Y«ÑwQa;)ª§È•&•‚ÙNDI_j婮 \´9ÌmÈÆjû|×¥–T~âù;Î6̾âZ°é÷° î]³r:f2ËØ! ¸UÅ }æÌ™s/^ܸÿþûû¾™3˲°€*,U`>²Â¶;W2׉I¤@û¼½ic¤¼Ð׿Õo'IJB­u¨€'µÃaIÒDëJ¤ð®¡xKcPÎB™ñ<Σ,à\Rg¢ý{ •JXgj2Y:¾ºU@_¹råü™3g–öïßߟ¶‘ÁšxâØ>˜¢`SGä…Bè$ÒåíÒº…Y¸µP0ÈKŠÒÇŽq–ªåMaÆ+\ƒÜ¦œ­X2ß‹ˆeUèmIÂ6{ [°nÞ †ž@ì¨4߇uM®3W7ªØ ¶®˜aš yƒtË,€RjåäÉ“=$ìA—V«e‘eVê#‰–kk#¢™³(”vm€f|YAæ†a¡À@+•ô{ ÷@›Z+ÖÆ0Y˜9U{˜ ®¡ÚÏy©æŠBiâbç.d°L©ëWc ê©B6®Å6úoú˜q,Àêíd¼o¼øâ‹'Çë+¿ò•¯Ðï÷yê©§(ò܆:i¼,¡a ´Ð§{…‚¡²Ú.¡çàb63†’X^Y72*4ʵ~Ïu"’Èê¥6ƉV¥íFÃÆH3*ÆX+4ÓNÖÕ­¡ Ñ ÆT×PïÑÆZ)¯ýÕ!Õkv?…ôÏTBÖvÊܲ©b0:~üøi¯ýq³´´Äç?ÿy¾õ­oÙön¯M­&˜ٶpª0* Ë›Šµ¡BsÛÆÆb,oöîÁ=›™âÊfÁf¦HcÁB?±–%ª5Xsî[ÊV%W6rŠR1“JöôczmïË›ÎÜc¯5ø_ÉóæÜ„tÈWmŠZåõJ« ô¯îQÌØ¿²·Ê@:uêôÚÚšêv»‘ŸTá÷ÿ÷yï{ßKY–vð6”kkH …†,Ó¶ñCÚó*ný¿DiM4ΰZX×þ`Qjê? x;¥àžáââââ… Ö|ðÁ…ÑhDÇüò/ÿ2ZkF£QÕSŸ$h¥YYÏ1Z±`¶--BǤ ô°AXÀƉک`ÆAÀ˜fî1z¥ ™"+«^/`Úi¶Œ®°D+?vV7Zÿþ®~4øïòþ±m§X ß±tK`eeeéôéÓ¯9rdì‡C Öb DAGjZaüð¬JÛ ìP} eUÚÖ­~[’F5tÏTûIi…ÌâÿnÖÍØI‰ æÍtè50°1ÔvL°]ÆJ ç›kî¶jÎÔÀÎð@ìõiTÐþj¥·TfLÚk.4zgàVÅî~ÌòñãÇ¡vsSH L#ZºÄ6VTGŽIƒÌpuS±‘iÒH2ߘm‹ó׃GéR¸µaÉÕ’Qa褂]½ˆ¾óí¥¶È¢”¶PT”†åAÁÕœRkf:’]ý˜n*ÃõãÍu=b‹¬X1áÉA)];VÝäWžÞ‡áukq“t+»‚50xùå—ÏÖúâP’$•50“¤ˆÑÓë©:k e£ùBA, Úî]ƒª©‘t(bVØTQWFîHbçÜý~mTÆ0Ìì@_}œuõë«›¾Â,ÃBO‚?.UÐç¡g¿A}v’Úb÷\j®Î3ÜTäNIÀ­€â•W^9^Q…™´®\¹Âòò2¬4¡Õ‚ k²nȶu‚­XÐkYæbp~Úž¤ªíÛ^€¼4®¶/Ü&²¹` P¾ÔŽ ê·%-7¦À{àÞÊì+'!?÷°op`a„pRañ݈:ÿßðöÇf~}Ã鯇n¥ 8sæÌ¹•••bnn.B¦)_üâùÞ÷¾Ç_üÅ_0;;kǤ)¦(Y(ÊBG‚nZåûõc¡Wh*-iC‰&ä®Â ‰6†ÍL“–íTÒoÛÖo›šY6É V¦(´(°B$d- Ä{}~À¨Ž ýÍÀ ÁÒÆ±¨Ì °Yìœ ¸ÕÀœ?þµÅÅÅ+»wïÞç‚ÜqÇ<þøãôûýjœ@£KM„¢×‰„Ë¥k]?þ£”ÅÂ@ÎDXx¬è#]¶+Á¨°}±°@RW3T¸ˆ4ZÁRÒ¨š,*Ôj®¡jî¬Bm4ÂD.Ñ(­š< ~Ý;•*.G­ØžÜò¡az8¾~òäÉ >úè>_ú­ßú­‰›ÕB’$’X*ŒŒ¾WJûІ¥¦Tη·$®‘§áƒ¥K/‡…®)ô»‘‹šÍ  ÜäÇ Ú© “DHk¥Æãý_ž_ÞÜ‹f€èÓ>¿©¨ûyª’r#P*èƒ:o‚nµ(`ãå—_^õ3mú?Þcâ=È0s-ÇH\ô¯ÉJËÜv"˜I}zW×v—:ÆÿE‘Ïó©ÆøóùsB˜ LiC f»26Ö:”Nº|Üa[êëï‚z¾_Åžù!V¨¹‚Êÿ7-ÀÆj?ÜúÀƒ_|14‡Œk~c§´…̆9G^hF…Õº$öBÍñMÒuð }ë÷\+ ­^Ú?]‚¥ŒJîæH$³nD±m8Å]ŸËR°‘½ `5¤ ‚ïVZaü+ÜɵÇLÃͪ‚cq=×Ën†nµ0@þꫯž­#žüLœvK­”bc“µM…Ô¶a³Õ’ T¨^©4›¥u ‘„nKD+'¦Q–ÏÍ•„J7ØlÛˆœfÄÏ VæªF$ö<¾A'ÊNËEýy®¢þ[Ô‚ISa¬à®g;gþá6Ä€>{öì©‹/nÜsÏ=}ßÒjµÂÍÆ%Î:IJÑO ©”A»ü,\ÒEÞ£Â0*­¶§1Ìv¢0¬Ë(PáøÊ63æý ã „MÆ“”ʰᆦùzD®ú_Av¯ŠÁx¿ïae¶‹Ð›~ãv d¼{ð@PeÖó¦àìÝêGÀ\¾|ùâÙ³g/ùùÒ4åG?úŸûÜç8vìívÛ>ÄȦp‰Ñh¬úáXJk6Fš•M‹ãw˜ïFôZ7É“ã¼ß§P†•¡beÓ¶€÷Ú¶¤“ZfúáXžYaX(ÖFžïDÌw%­¸iDMkýyëá¡ÖS[hŒ †Â4p~߀,Ö‚¿Ú÷êP‡;…ÜŽ7‡j¥Ôò‰'^ó.À ÀßüÍß4kâRb¢²,Ôô³Ò°:Ô¬ìs›iKæ:’4–q3xßvØrÍò@³™ii{üæ:’Xš /XÆ6^Ý,ŠN"YèEô[~ö°ª&®ÓØe…òËÆúzÊh÷Dßáì©=Cȩ̈)¹2lcE£ Ûh`ýÇ?þñ)à !ÃáO|â<ôÐC<øàƒ ‡C a¡,g#éšHXT¯å+vc%a_.”aX˜07P¯%k#„«x@¸™òÂn¯ 2m³èÐß_=vQ‹A”ª‚Jã¶7Æ •Fãg&±5)üØÅZ0þ ü1Ü¿å¡nl8¾1ºSÄ(`tâĉ3J)›o+Åìì,=öX¨„ÂHš0\ÁŒ`®%tÛ@…5eÊ…!s´bèµ"\†k 7åŠÒØñ‚eÕÖŠe@ }C ê …r=„N‚l9¸æìÅÛ`GëšOcüHá*fØŠ¡‰ÄØxae¤ª”rMÀíè“'O¾ºººª:N¤”B)Å`0hn©5:mÑèT€!"×'ì¬#×üK覂4–¡i¤ŽÚFP»½6¸9€e­;¨*ñzl@ŠQ›(7š¸Ú¸–ï5æûxÑ ‰»°FÙ˜i¯§Ç«#â™Ò|O·KÔâââ…¥¥¥µƒ.ø‘ä5&Ž­ ¸î`™[¦h2eÙŠ$½TEµbH,ãKm J¹²Ö¢ŠÆ°ó*E¬Ü‰,ßd{íùØ ™ª5Ü?°£bªGû´ÑHÓ "ýïzFPgó• iæøº›¥Û%fuuõõÓ§O_|ðÁ|ê'„ Óé ” oïÀÍ,UIRJe;~Jeóïn‚›÷O¸`Ìî&œjfÊÎ! 4$1Ì´E˜÷Ï; &NÛ}]AhÇ‚ùnJ¹uFÔ pHexaTu³!¸ÃY¤-Xè·­Ck™¦h” LãëfévdÚ³|ìØ±óãoùÆ7¾Á /¼Þè$äÜՑÍÇ¥€ÙŽd¶-H"Q4•Iæš•¡–D0ßÌ´$‘ëðiâ,´>Ò¬ l·q'ìêÊ0¬¥am¨ì¨`,Ó#g╲Ý=Nžº{0Žù.´¯?Æ·¯‚¿+U[×\¿t;ÀàÁŸüä'g€0>àܹsüîïþ.ßüæ7­øNRÔ0§Ó’̵%ÝD„ ΰ–‘…†õ‘fuh[ÉgZ’ùޤxë`Âø|߯—•†•v¹¾a®#™íHRg%l¦aØÌWŠÍÜvÅRTÁP*e[»êÚN• ˜01€ù¿·Bõ€6@ÖFš\éF6P®v†·k¢HdÇ?Q…Be_¾øk¿ök<õÔSäyÌ­Núå&e,0…c:&`øyy‰ëà^äyP¡zàÅu—ÆBÆ‘«¹|<ÈR”0*¡PšDÚúCâê EÅèô@˜À«]:Øt‚özÉ —ÊÇ!VDiÃÕ‚8ÚѨœn§”§NZ\]]-ºÝn’ç9sssüÁüY–….aŒF'1º(1J‡–lÏÄRCâq)‚÷ÙBUådn¹þa®-«ŵ óÝGA+‘ôÝäT~¤r=B×.• Ú\ëÒîZë=úSŒ? Óü¹ìÜL\ßh,SØ º`.\¸pîܹs—îç~,)Ë’õu;îºÑ%'­1¥b ¶íz©šUµMi\aD áòíj;E¤µÞ‚:úç[¿Š¢pͰdKÖ&\ºO* „¢DUþ®Ú?¨ýΕÕþ­Bv’nWh5/:ujÉ¿ŠhÞ°#I’µœR º)ÌupsüW~´:´!W†µ¡ ì„€Ù¶ eµ­10,´œibi#þÙŽt(`5¢jp±6äEQ+ûrðäÜ>ºn-êþÛõøÎo»´Q{»dýCw,¼­Xw]Â?_rÝétRVÀÈ4f^äÐé`JÕ¬Ï;c¡´-àäÊFæ­DXdŠéÍóî#ö1@ÍÔu}€iŒÅú–œixIDATFyÕê3‰3ý!U¬òüqåõÚ®0õÐ l°<´ó4ƒ¾7/¸ÓÅk`ðÒK/½ZïŠã˜üà >ð ÊÒ>Ä4Eªfâ…0#È•aTZƵb˜iÙ±Ðd@VØíÀöõ͵]'õQCö‡‡~•±ý€Ya±þvlÆ•ÜkmMA—MhO¾¼\UÝ5™€'9£R³C' ÑpØV,¯í…2iã4DÿÕó)µ&+lÐKë>꣆”®ž°Øî^\[XiÐÚ2|¶cë>Bç„ © ¨b`¬ë&ÀÅ Âàà`kQ^ß(›3Ý%î$ÝÖFüÞïýÞ?*ŠâW_ýuöíÛGY–ÄqÌSO=Ž÷ÞÛxq³IS(E¡É ºsûNÛíC¶Úd°n +ìN#˜MÝÔr†Fjv¤‘.Î2dJçBÒØM%*¿nOeMx"%JÛª 8wä$ÂÔ¸Y?¥g®· ÊÀÒzÑtbêb\íW-z›Æ_øÂÄqüGøäæ×ÖÖ¸té÷ÝwY–!„à7~ã7ã1Ç”Ú0–¤-ÉL* Ún¬æÚQC‚vKʪv CŠf÷­FF™5ÛI$˜i ;+¨[έæ*ÒdSä9÷-´8~q•ùNÌêHr}&™Ø>÷ÎAï®n*2UÏšÁ¡G'¶tKàÿø?yÇwüåÇ?þqöíÛÇh4âìÙ³?~œ8ŽCê·±±ö Á¡”$iÌœÌÑq㆒k„l¬J¥fÛÂÍëßÔZ{<ð&wPòÒž#}÷‚HcÄ”@ÐöŒ ;A…LzÄÆðÁ3ü`ñ O<|?wj“vLUõ£ÒZƒ[^ë×ÀÕAɦoô¬[˜±„õ;ën©c~ûÃþ0{öìi¼õsuuõúöOb ûu…ÓvÉG:±°íÞx3ï”éø±…6†ˆcß8j÷›l€h'¤¶BÓŠ CÕU{¹¸O²|õ2?÷<! Í¢ÁÔSz^2”6\”NpÇR˜0Í0`ç„à– À‘Ç…1†»îº+LE­V˾†-Ï]Â~‘0‡ Ö˜´E9±‘Q†$‚™n4°ÍƵ]`Mû¨°‹’VlèE5i,¥¸ƒÒÎK ;Ú(‰…ë0®ÁþÌ ëëÌP ²Uö¤uYÏTÃÔ5·Ð†«e0û~›†¨ó_ï´ÞWô¦ À‘Çëh§5¼Æˆ<ÏÁ]Ç´ÛmÖ××Ô±PÍ&Úï÷­`hŽcL^Њí˜~zôüij#{°Á\¦,³b ÝÄ–„}Â^Ø…z–•Öï§‘pîÄÝTÆà;‘„µbkkHc qv}ÄÏܵ›+E5*ÈgkVGÊu'ù«ÞŠˆ$¦®ÚÚQ$ðÈáÃÂܱ%ù1F4GÿØñx³³³\¾|v:¾öµ¯ñÙÏ~–¥¥¥PÔIBKjZBMl|ÇÏ 7¬m_"a¶#l¶ù7Œ8†xdÏØ7«C µ˜ïØÉ$"軌KeXÏ4¹ JÛaG*]]Ø÷{;ÀåÍ‚åADmt)œø¸‰¦®{«d5MTu/1í3>Þçþ»wïæâÅ‹:tˆÑh„”’¥¥%Z­³³³áýB&²•1“˜$ …p)\‰kŽÓöÔ.Ì¿²+/€d¬¶Ï8m·ÂU¹"¨„¥Ô6È`lªØK%e³–ÕêØXÏ É°¸.Vðlž0·# 3é°5³ý2Yû[Â3aq¢(bnn޳gφ7€onnòÙÏ~–_ù•_¡×ëáKÆBL!ŠZ)Fi²R¸7C+‚nL0â§’¯w +WEÌK;È´ ’XÚ}t#7$\KYaP®XÔMlÊè‹:¾Ä ̨P\Þ°³Š×#€q,ÁSˆjØÿ»YçØYº¦Œi8c¿ëŒÞJÂo­uCˆyè¶BЊ¡ŸŠPó¯3‡?ÆÎ+ˆ©˜NMÓÃþækßu>š‰?'6 ãQL¥¡Õµ_S·Z>m¸,À3õ5ñqÇ1ëëë!#˜››ãÓŸþ4›››UF &IéŒÖÈ#0å¸?´¾Ýu¶D hÇ&Cõvqq¥†‘²}±´Í¦I 26ñVH2e݈1V¨Ú±°ÝFÁ¤7{øƒ0ø*¥ÿÔ€£Æ)i@SéwÎxªÇ7Íìi˦ÅP‚ý~Ÿ«W¯rçw¢”¢( ÖÖÖ&¶WIBT*Œª^ÑîGçæ¥-úhlh¿EË·Ú^uåŽäÊîŸFø×;ý¸°Ûo0ÌM%T‰ Ã#å5½ŠàëÖ;©Uöj@3ú¯ “A;mJwÌ:ó#Þ˜˜¶]Xf¶ˆ¼ø@ðî»ïïªW݈c{Áe‰c—Ø÷þa{þSéZµŒhŒ2ÆÃÆv¶¯Äµ‰ÙIDE6–nFЬ„\Ù~þDZ—9)Ñn6ñ 嬛ýàÊ«|¿á¦¸‡FÜðf @޼€íÑóîÀÇÛåõpƒB¡Íö7²k×.NŸ>Íc=Ö€U[­@è2R""I‘)†:q¥ac)ª‡kóp :£Rà\5i ݨš¿7X* ƒ×0blÏ¡›^n"­¯Gú~Ù6ŸúzßFîŸT#¨(L®ß бŒ¯S]®r#oç¢( Í!u(ŽcÎ;GQ8pÀŧ¨QAÚéÆÕˆ¡ðÚ·¿Ò)k" Ø‚CÐÌÑmPgë ™ë0öq}Â)c@L¹‹É¨¼&%5Î *¸Ø Œª°›»¸fðæXÐßà>…û”Ô,!ÓÓ¾ñå×ü{+öÍ!þý‚>(üÍßüM¾üå/W#†•Ƥ }²Æ[? Ê™Ká…Ml¦ýÔ‰Ú¼@TnaPÀêÈ0Ê id˜m[LÁ½Àü 2“þßûÑFÛA¤JY³î  N6n+šže§ÀÁøåãÇ͑Ç¡ŠÆišK€í­ÁÔßÛ¹!I’Ðjµ DQ„/ =üðÃ<þøãÕ5Á6‡¸’tg(èg ±­â–Óul@:»Zèª@;ȸ>ùäVXËD\ÒXébm ‹RªZ&¿–ΈZ`ذ¦ÉìêrvÎÄ5!¨»ÏÀ:Và?õõõßÛþ½• €f&pùòeî¹çF£­V‹ÏþóÍ.a7‡ J‘);8l$ßILõZXígûv3‹¸²‡ŒÓH„,¢˜yó¼mUÛ´Òya]ŒH!«`Ñ I]ü1«£7þ­Ü1 iàËÇÀ ‚?• }fP·×bþÄïíìÃÛ½{7¯½öd4YséÀ¢3¢m`c ID;²³{Y[+ÞXÑ£Ð+ÛÃGÐKLÐvØÚ¤ÖƒÑ­È÷7”ej 2 Œ÷¾<¸c‚@ý÷Xä¸S&œ¦õxÅÉiÆ ãYÁõfá÷µF¹H)™å•W^ Ð/P½Q«Î !0qÄ ´º «jX—M­¶[wÐIÍÄT³lgÒijº/WûàÊ•+¬®®Úém´&Šb’8&rs6ï¹.Íïæ5y×p‹G9KÀ‘Ç56 ¬[€qœà†„àZ.À7‡¬­­Mh¼wõ‘¦DENA;Ë«}P…6äÚi»€nì´]4ö8m§íž Q…nå3gΰ´´Äh4âž{î±½ IBåÔÓÅ:£·9ûô¿ßDí‡m:‚^>~\9|ØPYƒu ž^ü7l/a­ÈgBˆÐ ä™EQ¨(e_.­ã9ŸÕóüÈv 5'w"¦kü4mBÐn·ÑZ³¾¾ÎéÓ§Y]]%MSî¹çæææ0Æ0üú£ÕŽ[úÆ"zšëü®¨®1+õÚêP»´^ž;·œÿøä¶óºèzz]û£¿,4Vó}up«˜€ñeú:b)%N‡+W®Ðï÷)Š‚4MùêW¿Êw¿û]þðÿоYD)Tš"WVÙÌ JKbaèFNÛýź‡8íÄ×òï¾[É`Z\\ÄÃÂÂ>ø ½^8Ž‘RZæû“REöMª‰Dm½G ƒÙ×U–ä¥^_Ί³—6Õ¹ÅåüÜ•MµVESÛn˜¶—LÅ}Jª¹Ža26`Êo¸Î PJÉ—.]b×®]¡;èïÿþï9yòd5¦ÀHbòþ ‘ÑtâªB7a1·Bo˜Ôx? EÁÊÊ .\àÊ•+ôz=öîÝËÂÂÝn·!8u‹"¤´o8“n^lèR6Õ¦šØ–}urµ&[ç¯läçO_ÉO¬É QÒ4›öTC/n÷,¯—n¤-<R÷©§†þ¶Ö~`zKX<æçç¹xñ"ï~÷»YÿÎïü£Ñ¨Ñ2f 0?CËø>{Þ¶û”$I(Ë’ÅÅE––– ,,,pèÐ!fggƒ¶'Iª—~‚«¢(ì§,cssÀúÆ&«káõ0ºöFkc hC¶:Tç¯l‹WòóÖôÂŽ7Qª‘QsLXÅü?;öïmÛ‡y´­8í÷~¾ôÐ:X70 ÿ¶žñEŽ?VóóóDQT™ZOãæ®SÛý¹<#7668qâW¯^EÁ=÷ÜÃÞ½{ét:á]EQ0xýõ×¹xñ"KKK\ºt‰ååe8ÀC=Äêêk›ŒF#FY¸‘JÒ>¢‘^|}C½za%?ÿÚj¹$¢ØIF‚H\ë^‰j¶`þñÿé‰a>\Ÿð>Þ AÇ}¼%˜fþÇ¿½l"çÚí6Y–…ôÏ…~ü`ýXÛr[­‹¢ˆv»MQ\ºt‰¥¥%”R,,,ðØcÇ1yžsõêU.\¸À¥K—¸té›››h­i·Û´Ûmfff¸ûî»9xð N‡²,‰¢EÄQB’¶X¨Å•¡^¼¸^œ;y9;gBˆ¸Õ¼¶ê"›¨Ÿýã5„ø³ÿá‰á¶ñéz ѵïzZ¸Œg×´>Íòuÿb)ïn„êç«Ýn³±±Á™3g¸páBx{gQ,..òï|'Ô"¼ö÷û}:D’$¤i,BE <@ÙЯ¾¾©Wï+¢ìÿx~õY»ÂyH5âvùÝXÆø‚?{õÞYæÃõÈ€!U,°28õûz(Šèõz¬®®²{÷n;iä>|<ˆ›¸Á8¦Ûí¢”âĉ<ÿüóœ={6hòìì,ý~Ÿ~¿ÏwÜÁ<@«Õ¢Õj‘$ @£áÑ”R/‡ÃgWWW¿ó¿þõgÿײ¹#¿ð䯿û€¼; ÿ¼D~ Tððg'ÿøÉg>\¿ÐXæ¯c3ÿ¤;@›­!ê¿Ç{·"Ÿ \¼x‘½{÷†‰£·-ÂP!gum¿zõ*û·Ë /¼€Öš½{÷ò¾÷½]»v…mZ­V°þñ3;;î#xÏpî:9Í?£´þÛ•••g_øáÿîßÿ»wŽíXZ{|Aé: À”Mž?ýÅ¿©Ì‡ëLkÕBÏp/£Ú2o ¶r ×…i×!áñæ:ym÷Û¶Ûm–——yúé§9~ü8½^ÇsÇwÐéth·ÛéãóØqOOc¾•eÙ·>ö៣j÷±Æ}5o ¨Qƽ–h>óÌ™ÿå#ÿ×5vÙºn`¬Zè_—àaa;/²«¹¸oì Déõ™C¦mÓëõ8uêßÿþ÷Y[[cÿþý<ùä“ÌÍÍ?î+u[ÓŠ1æià[À_-,,œö+ji°o—óÂݸ¯9j¼™óz£ùó3_úè÷®s󛦞 V#ðîÀ#„C÷wÏ}|¦€ûM6¾Ö9|~ž¦)ƒÁ)%eYhÖŒž}öY^~ùefffxàسg333¨Ù"sXÁi8ðô·¹W/ðšªwìs›®Ø¾ö`®_àîFÿy÷ÿúy¾tì†ö»zCD¸ãk>:­7—Ö〠¯üä'_{î¹çþÀ>°»ã{ÆÍÍÍñú믳ÿ~Úí6I’púôižþyVWW¹÷Þ{yüñÇ™ŸŸ&~ mÿ+¬†?=??¿%÷!oݼ%³ÿ³…À ÀPèòÿîýÍçžÿɱcobío’Þð !Î%(g |XRÅ9 €Ñ`0ØøíÏ}î÷ÿ›õ¯žüÔ?ÿçÙ³gÏ»§ÛWÿvïÞÍòò2=ôßþö·yùå—i·Û:tˆ}ûöMt5¦?MÅð§ßè=úû¬¥ÂÐdød<à]ÀõÖñ #Yn~¹ô÷ÎßÌu¾Qº1de :rø°„Rl 8̹½°ùÒ“â£ûؾƒ?ó3ÿŸþô¿ÜµkÆØ©Ø—––xî¹çÈóœ»îº‹ƒ233C«Õ"MÓº¶?Í1|›{¬ÃâÍ 0X¼ó?óÔýïú…ôëÿÕ½ûKÿÏ©W¦(É|íË3ßþ·‹·Zûa‡f «ÅÖ xÐh„µ}ìíϩ„@ýOÿiåôéÓýûî¿ÿ_~âŸ`vv–'žx"Dúiš’$ Bˆz¦ÏÏÏÿÕNÜÃu’·v°%p`u͈)Q Yùúÿ>óÌ¿=·‡ù°ƒÓÄMq žÑ›XÉŸ«Ä ‡!œ:yòëëëëÿ=p/X0¨×ëÑét0ƼEÑQcÌ·…GVv꺯—Æ:¥êÌò¿#ˆW³Át²ÛçµxåØÿ6óŸÿtnóáM˜'p,Kðâ&öªž¿M¨+üõ_ÿõ?}ôÑGýàÁƒïYYYùáììì·â8¾- ߊ¦tP×™'ëK³™À4¾š×¢ó_žùÏ:€ÛË|x“&Ь¡‡bèMfý¥Yž$ ^yé¥cÿõg>óßùm¼Ö]‹Þ̦ɭNùлÞMwàîÏá~Ó‚@c~ožÿ?çžÿo æÃ›8S¨Ž]  `:c•ï<º^¦ßnúɱcæ¡w½kÒÈH ̤0úû{¾ý;_ñûÞҋ݆nÉ\Á5a¸Ö6o+rBUÌc„Qö=7u `ô÷ïxæwÿÜïs[.v º]/zÇch¨Ü}ü¯Ï¾ðê™o»ûæZš2ÿ Ç|óVc>ìp»é6ÄôлÞåÝ\]©BÚøVd>ÜæWƼ©Žø¿ß²Ì‡ŸZ€'g €·6ã=ýÿÔ”™õCÜÒ—IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_empty_128.png000066400000000000000000000104351217176075400264070ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF8IDATxÚìMnÃ6…gh·ŽR8 Ÿ¢—ë2‡È&«.z‘®ÒäDA³(:ÙE­ÂHmýP$õf8Ø$+âÇ!çñ‰âY©·°`Ì? 3Ÿ¿'ªˆ™™Câ6|À/qcj‹bÌìBîš?óþñññ—¦i¥‚Ηš (fýcÎqå\þõõõíååå÷TPaÖß™^¯×?}}+éŠ÷>xïCÛ¶¡»·OOO¿…ºî`vý­œs+"Ú¼¿¿ÿu8~:N£[ßP‹‰9.v__¸ѺÏ}Û.ËàçïÇzï)„@Þ{Úï÷ôùùÙ2óš™ÛÀ¥Š®Dä:*§„Õ¡ps\ì¾>P.¿_û|-tßÚwë³sŽœsÿm¿ÜÖm?×YªzKw¢9•– ‚Øß‹…àVå… ï¸ã‹b @0ç¸ú* —Qà;b¨‚¡ÊŸ 2|b!ˆéõC 2”È- ÁرÀnA‘ZSq%*º¦ ‡ H-0-J±Y!¸ò¿ÿFªH€¢À˜V:‚¾A`êHPT( Ax†TÅœÀwc'€Jª{ Ûrk‡@• !JL… fþ`,ði JÅ”KÄ FC•ß§@Fú¥÷¥† ¯ï‡‚Ò½Òc‰” EcÉ9*R Oð]Àµ ,Õr5™Jú¶A°t¥iw‰ŒZ @pÁG€cRhsEÝgxa §ÑY$" A ÉY$N –œÒ!:‹DD€)ªUÉ–«ÁY$F ¶ß`†¾‹L%O!9‹à#€3‡g|€>/ÕT"JBŸÇ—š4PkW‘‚¾Á ¬¸äl æFh¤ÎÞIq‰~2H:HÎ"x4F‚Ò¤d±B@ F@ƒ@rD ‚tc ñƒ@©óøRL%j³ƒ@PЩWgðPEâÒÀS: Ø•C ÆhÆi üb+„(r‰Ò$tE¢t)H3•,€µÎe÷‰ÕrÝ|­¦•:€fÑ( ¶åÖê,R™ÆÞdíÎ"ƒ@­ Ì"V—¢@€t"0p!(úxxi4›JDê¥!@ÈU78s K¯]äPĤˆ®×ë䕌Š2(- ]‡H[¸•tEÕs¹£€VS‰:!(gúh‚räùZ ¨f6p.æ,–æ ÚœE‚Ò@çܤE¢¤APZw@Ž”âk5•¨JsBs“kƒ »hä‹HpäÁk Çu@B½œ©A~*r˜cð¶¶BÈB‚ H©%,©ß’[BAhÎ"8ç ‚…Æ\¾Ö4WP»³Hì£aV°‹˜Ç׌×ÈžäÒj6•˜`È, fg‘édÎ"(– éµ8‹àÓÀn¹ø%2€œE¢"€6b*­úÙÀ%Ò@ƒHXªµ`ƒ@ƒ ’BúžZ] Î"اƒQÓ@-Î"K+w‰\ú4ACR?„˜@ͤCÿÂ+²ŠX[x­Î"u‹D-¥H3•TûÒ(‚ê÷h„@Ë;‹uÚ Èõ?©^!DšP+¦„@í !ÁüßVûòh‰i "bÒ@$cHÎ(RÑÀ ¨, Д¢9‹`@x8´&gS§.%fhÎ"è`¤…r°NB‘sˆÂÃÃÃýn·£Óé4 Ž¡ýc¶_ëzúöO½´Ò4ÍDäaØn·¼ßïép8üùüüükÓ4;k e}—Œ­ ÒiT¬>¦¬V«¯···?œsÎ{ß&¹þ¹éœã»»;·Ýn7?´m{OD«”}Òôé‚%Ñ‘ˆ>™ùè½ÿ€®l6›Õjµr»ÝމhR< !Ðñx¤¶µ÷žN§Óÿº›T! .f¦¶mCûïMò!Ñ& «ô¦i¢Nض-y?­kóÞ“÷¾šHÀÌÿ³\YµbX¹,ÿ IЫ"6IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_favorites.png000066400000000000000000000123221217176075400266560ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ™IDATxœå›{°$Õ}ß?¿ÓÏyܹݽû¼»ˆ…]­…°^È`cl#aY’•8I•U‘ó‡­Š,çQJÉÿØ.W%²RÉ_ªJ¥åX¥8Šƒ…0b…Ë J V,»°,ûöÁÞ÷Ìôt÷9¿üÑÝ3sŸ;Ë’T¥ò«êÛÓÝg¦Ïïû{ÿι¢ªüÿLþ(ƒ¾÷½ï]Ѫ*[¶l¡ÝnÓív‰¢ˆ©©)fggéõzÄqÌäääšëK—.‘¦éšë}èC›¾ïñǶlÙR›Ý¶Ùlîoµö¨³»Û3=ï9¸ï—&"sï[à¶Ûn»"VÓ÷¿ÿý‘Æ©êŠÃZKžç<ñÄñÄÄDmaaaÚ9··V«Í´Z­kí®0 g®½öÚݵZm÷ÌÌL³ÇQú,w-§g»`•ë¦b^Kôö‰ˆ·ÀÛ¡›1˜çyl­­c¶A°/ Ãß÷g¦§§wA°'Žã=qïÞ»wo3Š¢(<Ï[óî¥Ärò|—$wli„´ê‹¦ãš°vüÿ xì±Ç"km£dpo3¾ïïžžÞåûþžZ­¶;Š¢=333cQ…›1¸-v3ÎÌ&ôrǎɘ™fDf•4Ïñ ë}ïm×€Ò©¾gzzú#¾ïïôú¾ë¯¿þð®]»šoƒÑ\;åÌlÓã1ÍzHî ›ÏP@up^ÞV PUjµÚmÛ·oÿ?ÆüR’sòbc„m5µBâI^0]q>̼£Ð„õèm×€§Ÿ~Z«Ü¢:‹ÈšqªºîýÍh®ñÌ«óܰo‚8ÈìãÌŠB_ß÷® €ï~÷»#MÐ9G³Ù\óªa †¯Úœ—Ï/³c²Ft³ãÃCúÜ«–‡\%—KD†éÉ'ŸÜðÙFYçz÷‡APUG·—²u²A/0& Ù·¬Àiß ^<òÈ(ÃpÎ1666ÒØQh8W0j±Y†+Õ¹Rw-m¾b\h„+«àÃþðÈ“5ë»9ç°Ö’¦)yžã›*ë ©‹ %¬Ô§…˜¡{«i$zè¡‘'=66¶¡ªJÎ9²,ë3¯ªxC†î”BÚ:ðü ô ~§{ÕQàÎ;ïyòO<ñÄÈc×£J퇙_ñœRy{hC1/¿ë{5<øàƒ#MÞ9G«Õiìfd­ÅY»¾& …4©Î $_…ATqåÀ«öwÝuרs_'iZíª7'UEÛÀŒ7øØW{Xi è TšrUÜÿý#M~­ƒC¼m¥º^ˆrÞë?SP·2ùÒóëà¾SŹÁ,ëÓHÜ}÷Ý£ àðáÃýrìÜ+,ÿÓÔÞõO ÷ý3Ù»<)ƒØ+ÏSP¬Ó>à†´õh$¾ùÍoŽ49çããã+¦Ö;óÉÉ¿¡÷ú³lùµ¿?õ¾Q­a}ÒA_ADúq_‡@QU¬sHåå*¸çž{FžßÃ? å¤\žžº |‚íïÅktAoI dD m¨ÜK?"Î:œÓ¾_0ºq:?ü0 —çœcbb¢]|;ÿƒ ̘IÀ³'Gô"*5 ,ßfeU- •(ª#PIžÜå5ýÝ~CônŒœC­-˜®¼¾s >È"Ú}¨Ú; þV$º\Z8CòâмÐÍPµXk±Î`TI{†¶™\áõËÀi®Ìvl¿|ÞˆV ª*ë'ç²Â,–ëzT?¦š}·tù2êšì'Ü5nM^. u…NšJš®¼?‹vÿ´ 8$¾¨£º0`šŒêpªu–,ƒEfPõuƒŒ°Ì .u,Iæú¥òH¬¦Šé¼w¿ÿonšú‡·ÏÜñÞ¿ý×±ÝÛÕu[¨ÙþuˆÍ ;½ »5ýL}˜AÊn½Ð ÅóðZðv[.¥Ÿ–¶Ÿ®]çN=lÖcÉî “¸°û¡ö¸XJóÛOš6£5 KúÓ¿±×üÊ{ÞóûnùÄÖ©ø#‘g¯sÉHa7jôMH_]* Ï„@@?WÌö»•Rz)ׯWÅ%o©%ÉZ  G襈ZÓIRo ÑKYïKör¸°œSdÅ—Ï`×pÛ»þ?þä5»o8Ôü¥?øWû?µk{x3.ñQ—M‚Þš7b‹6— æœcJ{§EJñWºT ”)KúZѽ‰2ð·9¸ÞJ\Îþ±—y)¹™Û0Ö?Máa »‚ù4.ˆ ÑHüêÏùüç÷Ä÷5÷ ¶ÛBhAÞƒä dçQÒ‚a J{®zN%SºB÷‡ŽjFM_/ ›(ob¥íkn/ÙJà ˜ŠáRW ì)$Ÿ*̶s:¹+êÿê-}Æ×G`Í"þ~uéñßûÂO~39uú¸1¼ö2\zf½Ó¥ µÆÌVçþÂ]y­åátpíªg«ïe¾V8ÏìBqí Ç'Ú&]Š˜óï¡ÇL1‡ä)žŠÒI-ç3Ú©+Jd­~~hOÒ¨=Á ó.¾óÑ[Â'?óÑó¿sç-Ík­–Óp Âΰ«YéàVH»R{Ye¥4úK»•û–Âñ¥¯U]°£ð'ÚÁ¶fù6ØŠhе–¤—š€¹NF7ÓA_°/úU±ÿJZb"ž¨ÚeàÿÉ/Í|ësŸÿƒŸy÷ØÝä.×Boc"…÷¹Rª5 WN!?P>ë¯uu!{U‹øS¨UæòÛI⃈KP#ˆ@/Wæ—rz™£ÚŒ¢ºã›0¿.7:$»wn—=»vy¾È«§Ï<÷®ë¯ùµOÞ¶ø›¿ýñè‹S»»éùý¾[A}(>WÌöjÛ ‹j„á>Ží€žG]Šóv’Ä7”QaøåÚÃ*õ^Õ[Ú”yXå8 ÖZ¿Q¯GµZ- ?>pÝuã=4¾òàø½÷|Áýâ_|kîkêÚÎDåÛúÛ0t¥¨–pVø‚áó:~¡yòKxù)"=±VVZ-¯<†Ûi…[*Ÿm®v‚†¢Ö‹HMDbØ3Z«‡ÙŽ—ßð/ýΊ?ÿ[ÔùôÉã³ÇLœb*Ÿ0ÌhŸùi- Ã`¬þ¬ò’] ²Ï—ÓJRU‹îðÇÀR®Ž^ xˆ„Pì/tªžËsÏ©ú¡§NÍ_>?öÔQ{ä³ûÌo|¤õ¢f½¡i™êö“³ŽýW¡Oû9ÀÀ *Ɔ˜AmJÄŒ×F,«9¾®¿½fèïªÓZ­èQ¬%øªÙ<¯¹¢j‰€!ªEv뛋¢_øjüåï|ãÜí³%£«ÍÀ® ‡Ã²Æ †¤_ÞSAö ;S4A` ÙuL``…äU7j GWcLO dÎ9O!D5RˆP $ |­GÛêw“ñKOeéå‹#«”²kLÀ­aµTÏAÜQþ<Š7ÄÈJ{_q¸Áûð½õh œ>{V›FG‘‘¨kѱôJÀ ªF Œ [5t€íå-¨t®¿io(Ì­ˆÏ«| ¼\aꈲ#HðÑAú\Ixx©˜+ ë°ÜnÓn·µV«õšÍæR†¡1&–¢åU@8EÇbm6BWW?ò†¤?uð¹šy?*©ò*æÝà0?ާ—P¶ XRíõ4\PŒHõSëæ<Uƒ*"yše½f£±X¯Õ<ß÷·ŠH øZàš¡›¨ZSx;–üš˜æ 1àHŸ‹„ù1zÞ®Ëà•½W_5¦ü,'Ÿïå—æÚùü…¥ü™‘ÂÕëõ^·Û wêæ»nv®c/ž_Ì^½°”[JÜb7uN„‡¯€N§c·OO«™4ÆL‘¦`¬C'ên²Ñ¤“áyÒ÷º8)©Ã©n)¡KgÁãdç©›7iz' ç‰k9!xaȪ] ªB”Áh› ñ$…Å$ŸëØ7/,e'Ï/æç–{v¾Ýs5ßCOøöKÿþ–u·¯]¶->9>ž%IbTµ)P++£N5Ž˜ ê©ãÉ`#‚j B¿+$˜l‘åd†cæ³t¶ÝÄù´ƒëÍuO.gʼȘŠV´@½žAA>΄ùIL÷ø™çO´Ž¿4ÖŸ9+¯ž›O.¶S׆âFÄxB¨à•uÁÿxù?Üú·ñwYD¤†á™n’ÔöˆHSU}·c’ɰÐMñË>ôÕ_û5CÚKô¿@öÓÈn³•,™'Ëêdù$Iz iz ç’„3íKø½S4’“LÉ1¢ü¹dª1ıG3ä裿ï¿ü¯»þãÍŸúÜ¿¹%ËI–úž û.Rà@‹|ækƘoÆße8zü¸û©ƒg=Ï;ÖMøþŒ™ñ5Ó4a€‰Ca“%j š# ôÉôçÉ®ù,ÆøÔµ‡Äƒ$EÞîpΑÛ}çs÷î=÷ü O}ñ?¿üã?Z^œi-ì|ÿÁ…Ÿ¾ýFùÀµ“¯LMD­)/b/dîV¬ûIà<ÉÀ×^ý“Ÿ}árü´2ô±c¼îºùåvûDžçDahiîÞæ©§x¡_ÚzU*` [@u½wüÙλÛ—ô—¬Kº1Æ<%"ú¾¼ÇñÙÇ‹‡øs®Ù÷^]Úœxšþç3y}ßD¯Ö­û cT*Ðiµ ÕóÑ _¿78ÿ£“~v ûßåÄŸ|ðê8tàžç©ªÎ¶;/Ïs+^<51Çâûx¡+ZÓZIHç±µŸ#9øetì’/U?7<<<<œ]Ó•(ŠØ:9I-«û¾SOÏ.ÈRR—JklÙœ)æÚ‘û¾zâ;_y}¾Fàè`‡ˆŠÈ¥<ÏÃ8²ÝíSußÁ•Ç. {?Og÷çp&^–|ñyg‡Kæ_Ýè]ÆøÁSOÑh6 «$=O½2,vƒYø¸SµïûÓèä·Ï:p˜~µ)GOløºÑø©ƒNž:`­µÔõÂñ–i©Ñ"”1\:sç|ég¾²xíûÃ['’gÇ›òc«œQzÔ%åyÎüܾ_LïèñãzèÀª#â#EuëœÃŠãÜK£zß+Ýwù­lo€Ž[}+žô’ñºÛæð1ž‚Íñ²å'ŸxÞÿw}ñ©ç†ÏÏÏ_ѤDÏ>‡€Â±d€ELj‚(¶¾/fáÈߎ¿xïóO%‡\ϊ ¤£›ìq €Z“ôz+îý—Ïpa"}íËž?ùïð\¥ùû0î·ç»Íå{ÞI+Êøú7¾Á;ßùÎÙÞ˜†M°ï8xÃùÙç?RëÔyîÏî?þ“f›|}S’«þïñ?—»¬3¿ŒºÏzŸÒ|½!óóó#íTU<Ïcyy™ìcœ{ã ªÿ"]5i±Y¢Fñ#T6ÿÓÍ4àêøœþ7Hd°—› KIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_grey.png000066400000000000000000000304731217176075400256310ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœí]Œǵßÿݳ³Ÿ\HZ¢H궘\èÊ’bØ&î…ýà‰‚ ¿ø%~2òæû`ø-¸0ò*RŽè§À@àÜΗÄ1"_Û’mŠeriѱÅEK‘¦)JüØÏ™™îÎÃΙ9SSÕ]Õß=S?`0=ýYÓÝçÔ©sNU9¾ïÃb±TÇqbë¦X‹ÅR1&Ò8‰ëZ=b_’ZÑo½õÖñîâñ °xàÀ'<ø?···ÿýÜÜÜ™„Å”’аX,j¸€w¿¿ÈA€ÙÙYÔj5ÌÍÍõ¾ß{ï=Ôjµ¯íß¿ÿŸø[ï¥]6«,–„D 8LMMarr²÷===©©)ÌÎÎbbbP oß¾+W®`uu€ëºû××ןŸŸ· ÀbÉ›3gÎï.Ò·¶€Ó²ˆçyvšívžçáÎ;¸|ù2îß¿……¼ð ˜™™€àÎ;ÏÏϧþ߬°Œ=o¾ùæñ €Œœ‚Ýë>þøc¼÷Þ{¸ÿ>¦§§qôèQ:t¨wüúúú'oÞ¼ùÀ‘#GÒûÓ]¬°Œ<\ÀÇA_ì†ÎŽ;WÀƒ @§ÓïûÎÀZ­`'Dç8&&&н6¶··Á€à/.. ~§Óé»V«íËâÞX`©<²6¸P£cbb¢çh›™™A½^p¼‰è8ÅßÇA½^׎Çß»wï¾ûnOðŸþy<øàƒŸ®?99‰Z­ö îý0Á*Ké9{öì1‹Aï®2Ñ]×í ôìì,êõ:fff”|ßW ¸ëº½ÚÛTÀUܾ}—.]ÂÝ»w±{÷îHÁ§kA€Z­¶èâ ¬° 8ºñoG…ߘ˜˜ÀÌÌ Çé øìì,\×Õpjwû¾? Ü€y nÊÊÊ ®_¿Ž»wïbÏž=xá…°gσ‚Ïýôˆ‰‰‰ƒY”Í*Kæœ;wî˜ïûJ‚ g¢‹5¹©€¢€s“=/VVVpùòe4žàïÛ·Ó”oµZJÁ—a}–Òrþüù^ Ah NmppZ/RW! þ±cÇz‚Oÿ§Ùl*ŸÖ ÿg*‹²Z`‰äüùóÇ»‹JÝu]LOO÷šjr]§uô]Fª©¯]»¦|2õÛívï\QçÓ± ’b€ËËËÇ»‹Ç ‚!'ìÚµkè›jt•€“pø¦vyQÌýÿàƒpåÊ4 <üðÃ8tèЀà·ÛíÞ= ȹ· iaÀ 8$^t`XÀ©íM¿9a58Q‹(øŸúÔ§z÷J%øeÃ*€àÂ… ‘™lÔæÐëpB .VÀ‡áÿ•–I¨oݺ*øÜÔWaz¯¬0Æ\¸páxw‘¾{Nf5÷ž““mzz:ÔDú/l£(àaÈÂqžçáòåËøàƒÐn·µk|ÑqIëÂî%wF훫 fyy™;ÓŽXp‡ÿ€^8Ìqœž“{ÕE¬€Çƒ;"Éú!Áït:x衇ðéOzHð©Æç÷0,®¯Z–OÖXX1çÏŸ?Þ}¨GºŸÃÝï§l Ä8Žóý ŽÍÌÌàñÇÇÄÄÄÐS6›¥8øóà‚_¯×ñÔSOE ¾ì<ªõºÊ@§¬Yb@BºI6/NNNö„Ÿ·Ù­à— .ø333xúé§qøðážà·ÛíÄm|ÀL€óvV$ç_À¬ð—” ðá‡âúõë¸qãfffpôèQ<ú製}ÚíöP?ФM6þ|ß,° 9/º®‹={öX“¿„ܺu«7 þc=ÖÛN‚/kãG¡ÊŒŒr Yã‹X€ååå#vk¡—È:óŠ‡ þüüüà·Z-e¯ì(tD”¥a}Õà€^û‘ãºnæiœ–>$0+++¸téÒÀ èíÓjµÐh4Œ„<®BÐ-sÔº°õI± víÚe춤ËíÛ·±¼¼<П ~³ÙìÆ+C1Gè¾*t•‰ã8C–€ªÒ°  äPϹ°Ø®ÉKfÑçÂ… xÿý÷111gŸ}î ŸG¡¼V«ÕÛW·#çYékXí'O .V¤€‰7—ö¬"Hƒ·ß~7nÜÀüü<>ÿùÏ÷šcFFCzŒ‰U¦ó\ÓˆĽvR¬H@Ò”•"ȪÍZèÿ]¸p¡Ö#á‚kkkÒž°sIj|ñØ(EcÀ'mgPç 3-GIlll`eeA`ii)–ðËHRã›D¢ºçps¹ŠE Ó¦„ìø,Ï_4Tþ ðÇ?þ°ÿ~ìß¿°¶¶¦ì9™æÿŽsù1¼#˜L1¨ºgµR m¡2­±ã¼Œ&ç/UüüÃ?>|°½½-º,‚^g«$Þ{²éœ·l Ø*€%¨eòAäáw áߨØè ;M­µµµ¥¼bí©s?Ó,˜“O|I»›b@òÒæY·“*‚,ü¢¹Ì…e}}zƒªÐ˜ ¦çÖ—/-ÂÎå?°N@ €l•NœPÇï`r¾¨kpaàÃs© ¹ã–-©SPËW t™£V$`”S}Óޏç#³]\çû>VWWŽ£Ù}ô†ÕâÃk‰MQ!$5»M¼ÿ¼<4ÖŸ*" {$X²9uÒF&¸iD*Âbæâoª1iŽ@±¿>÷¦“5àyžRˆ¹²ˆ*§ Ý”a.àâ2/‹ê¼6ÐR ²ˆtˆæ¹Ì4¦ZŸöçeÑm~rÕQQçö}µZM«æýa¾ÝõI± À’;ªÚ[܇ >W²™Œ¢S&1vRü˜(¤LÁpe ³®òèX`))¼¶kËz½®l2˜öæ3õáÄIÈ‘õø“%©Ê÷º:X`É…°7H¨¦çµ=·Ä :ñxÙdQ¨jY±VæÓtÉr²Ê!È«PÄ8,ÆÏ…š+Õñ&íg"‰gߤ¶–)¾ÿ߬²=u± ªTdÌü¥oj;Ëj}‚ïcªpÅZ9L0³Ä4L˜'VX2GÕžå5¾(࢙/žÏ4,):×¢BÖ9E >a@ÊòËä0s_ôîÓ±b{_]' X®ÄsDµëã* ®ôT©ÝyåX«ú¨_tÞ¥!øQ~€$mk™àGÅçu¯§›Ë×{e@dÎÛþDæ¹…WæýOëºIkn]Ç¢ŽÀ¦Õ"M¬°¤rrâÉj}îà£}’\Ð7eë³”+ ™Œ:&K¬H€5ÿ‡‘µùé[&èI„?ª ö|Lºäf1ègÔµT÷1m¬°$FÖ®Ûû|™ï÷z\¡„ ˜ª;p”ƒO¶o–‚èlË«,©"š¸bS€ÖÅE¥4øzÞXvŒNw`@ÝœHªdýÂ,Ù"ia€%3DÁ§u¦/³Îü}üwÔDŸ¢²P¡ò¨¬™sQtvª„¹(«À*€Œ»@ÕÉÅó®dT5s™B|:Xã>.ø¨&Qš÷*Ê#‚¥‡*žk•Bþ÷@gçmù0gaÖÍ•²¾Ö°dFJ€¾u½ø&c &™é˜ûDtš ya@ʪÕÇݹ)y‡ö;.n’P2«0ŽƒÏ:KˆUÅÖæÔkIѱÂÌY÷eþV¤€U;äuTm}YY⌮uŒÉŒCdþGu†’}‡•!-¬H@TÆ[žš|ÜѵÄõªsñcâ*‘8òÆ*€D%Ÿ$™~Ún­/Û7μqzš?Y5¶ P!ÂÌPBwšQ  Í!g]˜²;GçX•P¥sßA}¬H“—~Ô­‚¬BZ²œ}¾-ª À˧Ún:8¨x,ÿ͇ÿ⵺ÌjQG§rIŠU HÒ¶UEÖ‹V3Êö KÖ-ŸJ„Då“ÄËE Aö?x¢WdyäXP0£¨â¼´üÅkÀ(_‹êº¢0™–G\ŽðS¼& þ¡$$êÚy4¬H@šÚyA¢I–3UêlS SÔ¨¾aבeôÉ®õž$Ýž«ŃeE “¢Ö›N\×ÒÐÝÕˆ?+n¾SÜ?Næ Š¬B‰£÷–åH–š9*y¤ìP ÿÍ¿Åå°u2\×M¥§]˜"áíò0¥$›ÜT¦ì’”3«f€µ·2¡Ê!ĤC}‡a’ ³Ÿ¬¶Ö±DÄsE) ]ge^X2º«8T­y@VŒîT\º¨j×°zUÇ©ÎoZž4'l@…È3¦JŠ ++ ¬–å5xXXM’K£li ‹2¤U ÈSèeTAˆ/n±mß‚ªICoQƒÂÄ=¯õX”TAYÔŽbM¯Ú—7¢j~S>OøÑ-·î¹eÇ¥Eùߘ’S´À©zä MÂ<û±¹ :F'|(›AÇ)uþ,ÍÖH€n¢GÞTÉ"HUûÞ$¹Gvž°}9aaO+"j Ã4± e|‘*‡ÃÝwñ¿ª‹L†ý‡51¢Â|I£I° `L«€"b†'Ivž¬6€¢öU““g^€U ÈËLK“QT*œø;,!Î`:¦zœ÷#i$« ãÀ)+qAÕŒaÿ9NØŽ+Õ½I¢h­ äTQðEtAÔ¨6y“fÇš( «©Ý¯3àgY-.«2 JP¿¨ºý×ó´TNÀ8BÕLP]“~{žúâHªl°„褣V$‚œGsHLâßTö°>ÿQè ªÌóU^~~‚®e•XPR¢&€G²JH’ ¿ê7`61gذ_ª²ÄùQ ¯“)‡´± UwŠåAVcdYw&×TÅéuvÒzöaeÍãý² À’ q›F:•ök2Z°N•H»Ù—GsÒ*€°–€>qRce˜8ÓtB|ªrÉbþQQ‘´Ö6JŠüøD ‹iÓ!NF]”÷^æg0qü…Y&ek4¡û&Á*K¡ˆ¡+ø²Ž7Qç6)l½i”C'CP§Ï@³ÙÔ¾¦)V$DçE´D“å½K¢Ä8~Úð먮±½½mÀeÄ6Š#NBMœÜ^ëËF7âçMÒöó+´Z-«,‚„_ÕÓδï½²¶œþQÇŠ4›ÍL­#«`Mþò êÿ/#jÂñ¼ºmU¢’ŽÃOµÏÖÖVäu“`€¥r„ ¼© 0É‚ 7Ç_Ø9£Î!;^¦0Äónoo+¯“VX*‰‰ÿ%*é'j¤Ÿ¨sÆiûëD.Z­:Žñ¹M° Ö XMtC²> Ibû¦eÌ2üGXPRâ$¶Œ ®ëJ»-›F¢,&†É ¡¦ÏossSûÜq± !i>˜$f–䃠òûOýüM2öâÎK(£Ýn£ÕjEî—«´ WyXE0ˆN—Z]D¯ZSë Ëô_ŽU9“…Å`S«@ôú'±¢}ü1Œ™µ÷Ÿ° còÈ°Š <–ND ÿåyžrxoB'ü'Öü¦!ÃN§3dX@IMErF‘$T„" •åihŽ7¨Í¯“u~U€ìY%F#·÷Ç*€覆æMÒµîùÅDÓÞrYb¢ IøeŠÌ¤×a2²Ì*áÞÿ¬± e©ùÂHÓ*Ð}©óVqºÝŠûèÎê›fž¿Œv»v»ûxS¬’*‚8/5u Éc„¬>Bœ8¬Â°ë˜ Êý·>K*˜*‚4^<´4Ø;/N¸Ž„_5œxRLˆÄÆÆF®”U)P…¦€ˆI‡˜<®™Æyî!Ö̲Y}tþwÒÑ„ÃöÝÚÚ’v<Ê«Æ1þœ÷5³:gXí«3¥WÜëÐ6ü€¼{þɰ ÊâùNBU–Q‘ @ìä“Fo¾0Eª[&•÷?Ëgc@Êöª2ºŽ3“{-³T¡Ê¼"%âuøõ666"Ï«àûþXgße*›.Îqâö(³_W$uhÊþÏÖÖ–VêpÚXkdCÜÚ>ì8Ý6¿ŽƒÔ$#0*4¹µµ%ø#wË*ËX@í~šÛdŽ‚8Ö‰ø[û·©ÀK&Ž6núÇ©¹ÓJ­–•¹Õj ôû·>€Ša›Å¡ê“ î–9˜MO–vsss³ÐwÈ*€Xá/–x ·,«µƒ`xD_Yï;Uš°¸NvŒNÞ Y·ß¼± ÀRY&''‡Öq«@–U5RPX­Ï‰òèX úSa€%'Ïà°—ÐÒ‡žIÔ³‘mO2å¸I'$`§ö'çŸmX†H#ö=Nð$Ÿ¸ùQ#E]ÐOdZ__×|›PrÒ²â>èqW$ô<Ë/{g`ѰgHeiµZ¹wûUa@’>¬´ö¸*Y–_3÷ñ”ÃÚÚZiÈVäHÞ½í€b•A}%T=ûtzí©0¹g¦Í†V«UH¯?æ³'XzD½T¼]Z”Æ/âÚa™öu¸ù¶IY’Ü3Ùtbü¼÷îÝ‹uÞ¬°@BÄ$”$N¨,É£yÕÙ&Íë˜öê‹Ó0NlŸÍ)¸±±‘û€QX0fd¡ò¶2tj}ެ~AÜf•7*îŸôšq° !U HGÕ´èt:Ú=UÛãøL.áD…ýŠj"Z€ª ?'Ž"(âe ‚sh ÿ°2Å™™'1ýT„…ýŠÆ*€ (KˆÇ„8mâ¼ )»d}æe„9ýL:þ¤±/¬®®*·U PÕDesš$|–žçõ>iU¯ò1$qüÙ¾¤ÊÂÏ)Zð©3ØÞWíçü2L†I— [Æg«Õ*E‡Ÿ0¬HÆq Y¸È2 ÅÒu„Ÿ#ŸCœ‰PtÆT­ ‚«««… xV$cÿ Æ$=Ô2Hš&?¯•Ópvš»¶¶Vº˜¿ «’q|ðA¶æOJÚí}ÂÔiuR(ªs4 4›MãóË®•5VÄäÔ©SG|ß?6??ééi4›M¸® Çq¬"0Ĥ½v@ßlªÝu¢!²²v:¬¯¯GXq|ÞXŸ¯À#<2°Òšÿf˜Ôúªä> qÜŽP:Ѩóû¾µµµJå‡XƒS§Nð÷pìØ1;/L­V³µ¿N'U/¿Jˆ“(¾>JI¬®®¢Ýnk_« X`È©S§Žø>,--a÷îÝð<µZ @ñyUˆHø¾ß«õã¤ÇNOOîܹct\ZÙŽ2%±¶¶60¼wU° @“S§N-x±V«½¡µXV—$ñ¥(E@±ý¸µ>gaaSSSøøã±½½ééiø¾ßó¿Dõü£eÙ$¦4X½üÂÈÓ9h€„S§NÇNÿøââ"<ˆ'Ÿ|óóó˜íígê¼*CÏ»"yøu&æÔåÈ‘#¸té®^½Š'žx­V SSSÔ€j½n³MÜ'‰ð—!X0Ä©S§¾àëõzO?ý4Ž=: ôdƆõGW‘Ußó8ä¡‚ @»ÝÖ²’L9tèîÝ»‡ .à‰'žÀ¡C‡põêUÌÎÎöü1&M“ÎPŽã ÏÊæÀ+¯¼òr_àð•¯|»wïîŨIðÓ ªFÊ“¬çy=á»nŽ=ŠË—/ã׿þ5¾ð…/àþýû¸uëfff0==zG:O£ÑÐŽõÇÁ6 à•W^Yðw“““xñÅ155ÕsìdÛ/‹¤§¨ÖW Úÿù©§žÂææ&þô§?áñÇG¸}û6šÍ&æææP¯×c]SÕ)¨Ùl¦Þ毑'Vô9O>ù$êõ:¶¶¶à8ÎØ%ö$I¤ét:hµZ=Áw]whVÞ,˜››ÃÜÜZ­>ŒÙÙY|ôÑGX__ÇÔÔæææ”eV­“=÷ÍÍÍÂR|m #–––‚`êõ:F)ÂfE£k¹ßn·‡^TY‡œ¬ ¶ÿž={Ðét°¸¸ˆ>ú­V õzÝè\|Rß÷±¹¹™ËpÞy[ãU½ ðw9û÷ï/•i^xÇ÷ýÞüöÜܧýe#ãæA½^‡çy¸sç<8 ü¦Ï¶Óé`uu53á§{¥ºÇY3ò€ ä¾Þ ‚Àq§—ÊÉCCiÍ SuèåÉ<²{C÷.¯&€ŒC‡áÒ¥Kvúk¬®®öÌwÝÄ v»ÌÊ^†Šf|ÞÞA†ž¶çy¯‹šXG+‡M1jø¾?àà«Âÿþøãóóó¡Ï“oó}ëëëFxêPtm/c¤,Em/®sغÞ6Ïó\jCÆ!ÎD’Uj|Yîƒè4£NQaùøy½üÂåå£õ²rè ãUÍš‘Q‚ðË„^\æŠ µ>JŠ@%øQf=A5)G–gZ²N§ƒF£Q¹Þ|I©œ0¨åÅe™àXi¾”ü%¬š2ˆ|Þ~®Õjð<¯×þ§ÿ.: ³Pqš$¾ï£Ùl–jÂÎ<)µÐv¾N¥dB?ðí8ÎbVµRU¬™à‡ •˜FKBO@ò ‚&#݄N§ƒíííJtáÍÒZ*µÐ@%ÔaۤʠV«ͤ„Œ²*z]Á‚û¨9@Ö@˜çE7QPžçõ„¾lmü¢ÊS¸H`ÒóeSE0´AnRYE †ò’zõe™“bTÅqœ^s Éä#:eåÊlkk kkkÆ×IJÙHá @ƒ°8¾‰p%ûpàùÎ÷W„"ûå§ýUãæñÚ?̈"Îqy†ÝÊ.ð"¹)݄ŷj[Ôþ¡µ>ÿíû~a¹¿y(^Ûg!ôÀ`Ú¯ø_¨yAÊÇuÝÞ\²vd”=ï ŠÝ‚sQá75éö… :_e-žüŸ¶"Ⱥ¶7Áu]xž7ÔµÒî†]6Š,Wª À°–ç¿u„[µ¿Žð«ÎÝûö}ß)Ë ’4„˜em·ÄY’|ßG­Vë}“B SUü²¼KQÄRÏ<óÌ€P.--ñŸºa:/=„mqj÷°k—]« (¡—!脇£Æâ+ºü:TEÀ£0V¢ð3tkyqS³Ý¸v—|-“°¬ÈA™„> qn>U@ÖÍ”¸c„§êh)‰ÐëÔ¦&B&ø±Íz“ëAPš&@4¸fÙ…^„·ùÅ4ak¢Gœ&@˜ê4©åùzS ó­Z–6ÊjP­HμQ"ÏÐ\>2‡*Vóë dTÛ]¶¿i{=ŽÀGî_¦—„×ðUªåe¨ÆäÏã^—åyª(Cùt,€¤f¸i»^\§snÓ}†¶eð¶ï(¼Š"ÂyëVaŽƒRtkž=&ÀÙµ¬ûëL÷XÎËÀbŠŽÍçA£ŒeΪLQ ˆLÀ`9l]Ø·jYç8ÝóªŽM 9}F­ Æ8 QäUV] ±+Yµ ÉzÕï°ë«öÑÝ/j1ÜŒÏ#œUVª$`ES–{¥›¼y ZùŽ»MWàc_+¬ 'pœ]¤,/³ˆN¹Â†Kzî*`âä5¿Ê?ƒoñüâ6ãv|ĵ"}À Þuݱ"Ê„* ¬¬a \ˆ› ~² Årf}Ô9”ûÊ¢¶v¦ŠÂÁ-¶*Qx€„0aþ4Íú8VAè¾U|AòÂÞ—l(Ã}RA÷Cæ¾ß]¦õ*Ó¿f½á1Ñ ¿1£ /hšèüÓùó Ëë(»˜;wŽ„Ø|}˜X¤öIDATÁç˼tbÓÀeß®°NÜ®:Fv¬+£òQh—¡LÝ‹¤ªærZˆNÞ°O^×Í €S£ØÅ àr߀‰ùŸVÍ®{=Õö±c…½ìÿ©,åÓU>ûÍk}U­¦ ¬GÈ>aËi9…p”)Ë ˜6bŸƒ2R¦ré8¹°óuÜ:PÕþQ–@Ôº,Ž‘.W¥;pFùÿ…ý·²üï²”ƒªº~<óÌ3À`ûßÁ°à;M°ç°eHö…b9­šÝ´y0r@_¸´Ñýãì×#ɘ€¢@vwãZ²í¦íx£ãGÅùUõòë2.ÿ3k´€` ƒÍ‚úmÞ4pÑ·Äiwì]V-Çö ‚Œ› Äý¿U¿OY•ßhÈY¤¦€ÀÃŽ}¼î‡Â†À°5  ÏEm ù…í'[® £b­˜0ÿ·ˆP`ÒaÁaYüˆè4 ±Îd»ö¾ev–µ\yæ‚ ’ƒ„”JHšv„ˆ¬WXGMv”B ƒÎB@_$1ëCÏ[–0à8 ;'Íû°µµ•ÉyÓ¤¨r¥51Eøoú6µ ùÎby`]Q&fY_È¢Èâ~ÌÌÌ (¬©Ò3­$–µóÉ7@FYƒè+ Þ¿Ðoˆ¿SkH®‘:Uz1ò&˱F&ç…ç™æÔ`ün ¥Ànú AÄ$2(ì§q¾ØŒÂ‹‘yY]4)¿V•&)•@äܹsëº4/ è$_¿ÛÔþ{Ê,@¿æV)­eÓ—Ñ y|Šhn‰×+Ëó+º©…¿–——y»Ÿj~ v´´„ï6úaB² €A¡Ö ûÉB‡q–•CåÙCk!ó~TY1éEX¦÷(ËéÁÅþ<L)æiÅ`ß®ð;3§ Eyä‘R<˜Q¡ê÷²êå"UÀ¬ÀÒÒr^Ëóš×ï–ÃPÇ`ÍÌ£ ¦BÕr*MK8e¼—ae’Íh<diÜóOŠ€lD.Ô$Z—‡žU¾U.{2Ud–0h}_ðon ˆÎÂ4–-1WÁÉ›V«u;‹óæaô¦2 o³m! œ° HdߺË:¿-!XÁO~OÛíöíf³yckkëúÖÖÖuß÷·³¸f. `yy9`aBú÷Ÿjy¯[.R& Câom_}¡£©ê=*ªÜ&×ø{ÖS/ òµn S_ oÔºjP_î$ „è'‰N@Q!zá@ímã4êÿÈ+ïssój£Ñ¸Þh4¸ÀˆÈÖ†ÛïqRï3~ gÀÌççÂ?Ùý=ÙÝ^ï~H!ˆaAþ Éo™†+À¸=0ü_°ººªÜnJ·†¿±µµu½Ñh\ÇNõCì¼;ôŽN ¡\uËÙð'NœXNTèrS‚ðÓ7Õò$è2 FL€ø{äcÿã$ð„ê?'µê$¿àúmv;5}ì2*èøÉ‰'.›‡¢š¼ÍOÀ$vnf ;7˜´i à @7@üꨢðT±Ìiaúߣöït:·Åß°Š6;9ìfCO’œÜ„(Fˆ)*úDùâ(€°ã*Á8 <‘Ö=$ßܰ~ ÏÛïy¼/ë~|âĉ9\ @9œ€b¿|.ø¼í/kÿ‹Ëa¿Cýe´ÊVž¢1½Žã ôòóY|ÈðúÍ _ëS_ |Æa[Ûgˆ ø§üÏónÜ¿ÿõ¯}ík¡ÿ̦0¨ðé@rƒÂ!*u™‚O3$¨¨@:~òòË/—NøòYÜà†’B ŽCT[Ð61£PlD*‚2fV &ô¿ðS·ünß¾}€¥¥%Æ›ôø”q¹ñ3_ðjY…(à“‰,--q“ž,Ê !çc}åÀóTiòߖ˜t…þÿøv†µê ¼Èòò²ßU<âCÏÕC_¡Ó6™_'6(÷u?xùå—sÏî3¡pÀé¾$¼†à¹|@Pª)¦°ã 䃊ÊB…‘VÀ;wþ´gÏžÔþ˨âûþO±SËßpnß¾}cœ†[zqHxZGTEy¯w:|÷»ß-µð%S@/Yì/Àgê°oj ˆmH>\½zõO<ñÄÖ­[·f8Â? Zþ³ïû—Üð÷íÛ÷ëÏÏgˆæ3FñïTÈ1Íûv§ÓùïgΜY‹Þ»xJ§€^³ ¦ç#»ØñÐ@"MôSˆ)TXg™ƒpˆ{÷îýìÚµk;Æ à€ÿà†ïûwüqß¾}¯§uòååeðP~ý¦¡°ÅÑ¡£½´P)4Ýsÿù7¿ùÍ‚º*¥TÜ Ì-j7ŠaCú¦fÏ0ä¦åÐSë­·þÛC=ôWG=<=­3Pkåù=vÌù¬8·wïÞÔ^1Ì­Úž©c0%ëàfWø+E©s,\ØF¿vè "¤—f¢»’ˆht!`¸Kñ£ðç?ÿù¿«×ëÿæ«_ýê_-..fð¯JÁk^ðöÞ½{š÷Å%–€8e<·ØôŸ)wüÒ¶H‚ È´`ûÛßþŒÊuîܹü†#NH©€¯È* @ ;/Í6ú‰Cd^}_x±?`cccãG?úÑK/^<ü¥/}é ý×ýÙ¹¹¹³ùK¹ñvþµ½{÷¾VlQ”ˆþþ»ƒþòü9ŽïûçNŸ>ý«¢Ë'±Ó]7¿®®_€wvÐOEß@J!žÃ` ±l˜1n ö2 ¿ùÍoÿÌg>óÙÝ»wï[\\<’åÿK‰ úR{£»–=1Iˆ9Á$! D|ö³ŸýŠëº KKK:Žƒ‹/~”f¹=Ï;÷Æoü ƒ×än$±n*§€%ô_ýÑ„§Ñe˜À®î÷úC7sE &!©> 5~ùË_~ôÈ‘#ÿâsŸûÜß<ôÐCYü]*%ð2„D!𠎆«³}!Y0¬Þyç´€çyÞ/Ïœ9ó{0á/ÊôO¢ªÔè! ŠSŽóq¨ýHÍ… Zü¡q'£l™7CxõÕWÿßþýûÿá/ùËß|ãß@NÎÃ?F…>ºçb¦ ƒÁæAxívû§o½õe÷UÆã/£’ è‡ ¡þä šcýц¨y0 yˆÐg}‹ €›¤î‡~¸¶½½ .àùçŸÏâï® [Ãû¾ÿÚ¾}ûV²¸HI {L¾Râ»Êåábiu˜’§Ÿ ¿Ç7TÉñÇ©¬ ÁCG¢U@ý øK­]À»-;Ü Ö›Íæ|JÿgÅ÷ý×ЭáG\à ¤ sxhGÄÄ¡²gcuuõ‡/^Jð©ªð#¢„Ä!Þ,è ŸoN/L ê$!.ü +bÀà¶Z­_ܸqãEÓ²w}0+`møqx‚ çÆ-°oê"NÑX!BMHøïCpøQH³ªŒ„kiz‘xÍOÎÇ"äý¸À}Dçp®\¹òowíÚõD³Ùü§2?€àl½¾Àÿx\^† xç  ¯ (É‹7÷2 Apoccã¿tkþ‡XuáFL(Æàð¸28ÄSMÅ&€è$¸p87oÞܬ×ëÿêõ×_ÿγÏ>û5!‰è>ºµ;vjø Iÿë(¢(¿ƒ”:Ðù 1í»wïž ‚À»wïÞ6,,,̰šÿÞæææ8{öì»`5¿pî‘Ç*Ë( våeee½Ñh¼zûöík«««­G}t¾V«µ|ß?wæÌ™ï¿óÎ;kÂñcÇH'YFI"1Ù‹C/{ª™}UN²’k©4!B_Ø6¶µ>ÇZ–‘@a ¨H5§ßZKÁ²­ùÖ°Œ$‹ GÚ^þ*[vF\‹eŒ±U·Å2ÆX`±Œ1ÿ­Y˜?àÇIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_home.png000066400000000000000000000150421217176075400256060ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞéIDATxœÍ›y”]Uï?{Ÿéž{oݪ[C’JQ)2BAÀЀ"ÐÒâ€"ÏnmÑ·Aå=ZÐ'¸ôm£2ˆ !Š" -¶Ã“–AlŒ$$$¤HU*•Ô<Þy8ÃÞïsëR•Thx2¼ßZgS»ÎÙç÷ûîß|ö§n8Ó4ÐH4€úõì3õñC‘EeÖ³ÏÏ£çÌsè9™õ”˜óäì³®Í=b/1<þØ#È—¼ãµ§‹€ö7’7€3*{‰™‰…÷†0ñFpŽëÿ|jzºÉ( ø—7ˆ7€óìòàƒcÙjìÂ+¿‰»p þDïÀͼ´xMèõà£8ð“¡©ªñ¿®û.ÿð¸ý?Äh]Ey¬ç‹ÊFÀ|=z=¸Ä(ôo͇ò›ßû!ïþ»3¦­¥‘Ÿ=ôK‡Mit÷6åöëÅÔëÀå"¿÷æñ²-nÞx/{ú)ôíÝËøØ(;wî$JòàÏÿôŠ“( ½ðGÿ H¼Œ½|Adû®Ÿ ’ܾé~Nyë[ؽ»‡B>Occ#¶m³cǮÃþœÅGŸNvø…wÆtá@úµfîµàëa¦ïk9ÙÆîy€ã×Mww7žW!™Lâº.®ë‹9ìØ±ÛÜwÿOYq»™Üý¶˜Îþ XôZ2øZðíp²÷ó~¼“M÷>È1kd×®]¾O<žÀu]ÇÁqb±èzûöíè0äG›îâ˜S?ÈøÀžÝ0ó óµbòµ@·xã»?Mó*î¹÷g¹¢‹;w •"žH‹Å°mÛ¶‰ÅbõÃu]vîÜI¹Raã·râÙ0:ÐwL,œþ°ü5àõUÀ´)o,õ|"Öñ&î¹ïgtu¶óÜsÏ!„$QSûÙÏhB<'“L&ÙÓÓC¡Pä»7~‹·w #}+Ýpê1`Í«Ìï«smG—~Tëý@zùIÜu÷&Z›ynûv,ÛÆqZZZH$vîÉd²~Éd@)öîí££³“ë¿ñ5¾èºüâî=lñbõhÙj=xúÕbúÕ áèâOó#{În_wp‰8Û¶mömܸ‹c;ôõõ‘Ídpb1¤”¬_¿ž|>ÇîÝ=AÀøø8«W¯&ÙЀ4M†ƒ€¯]}N,Æý·]» c±úmÙZðà¯ã¯é˜.ü43ÜûŽÃ;›ïÀ°}û6ljTÞ‰ÑÜÜ̦M›øÝï~G†ärY6oþO=µ…«®º ß÷Ù²e <ðçž{.£££„aÈèÈïóåÏ_A,æ°éƯ6w, Uq½xø¯eþ¯õm1•ý÷©¡Ýï8òäs¹û®»@twïªy÷Xýlš&‰D»f¶íH$p‡ááa-Š¢Þlß011Áàà Ÿ½ü2.¾òZÇr ±êðCÀ»ÿJþÿ* hwÃ̯ÆFö¾éø³>ÂÍ7Ü@1Ÿ§¿¿oŽð3×ÓÓÓôõíEk £G!_åñÇ~OÌu° ÛŽ²à™!e´FÙl–0T\zñÇIÄ]þõê+b‡µ ü¬êvüpïë @W<œþõÈPÿê¿yï…\ÿÍëÈe¦Ø¿×uë«­´]ê½ï}/kV¯Æ0â:zõQëVsç?¡maŠB1DzåQ´sß÷ç¼´PÈÓßßÏÇ>ò!b®ËµW}ÆX¤öÿØOtÆ;_/Žˆ…S¿\öŽó?É7¾þUÆÇÇ® `œŸ¡ÞÞ½<µy+ÍmM,:zœ¯ýðk´·-¡,;è~Ü¥âçYìzšÓi„u "ª’…”J%z{÷𡼗˜csõ•Ÿ uÿF?¹$ÜôZ°Îõ'~322¼øÝ½‚k¾ü9†‡FŸ«Ç÷Ù‚Û¶]Wa€Ûvñè#díÛ+lþõ ”²•³¼ùíK0×Rî]ˆï‡õû-ËBÖs»‘år™žžÞwÎÙØ1—/_ñIZò}7† ‡'€ë^‰@¯Ä çú£ Œ.þà'®âš/ŽýLNŒÇëê>có¶mcÆœ âÍEºÞº—@Ñýçiò㤶ñŠ0ÁfWw‹Ïmdš¦YŸofn×u ƒ€îîø»3ÞÆ7oºƒiÕ„Èö] \ýJx¹prÌþÅðx¶é‚Ë¿Êg.½˜þ}ýä²9ÜxǶq`rFmgÈóB´urfÃ¥,Zxïß )|œ„‰™‰,5IÿÞÝ,=|ɼ Ì&)¥r™]»vñ¶¿9‰n½‹Ë/½˜D¦÷Ë¢iYøçW €3ÊÈý£S…†‹?û¿¹ä èëë£T*Í«öŽã$<@¡åéÍÝÄãIzw# ‰”  4M&“Á/ìâ´ÓN?˜Ñ³MJ•'½e=7Ýö>sé…XS½W˜ÍËâÀ¥p@7ÿpŽ]úéx®»ìªácÿø!z{{©T*ua_ŽðŽípêiH$s„˜-M¥Z%‘ˆšYÓœã!ª¼*Õ*;wîäØcÖrË÷Àe—\Œ?¾ã§uY¼JüB øà<«<øã±¼2þùêosþyï£g÷n<¯Z/__®ð¶c³nݺyÍ@kM†9¼É0 Ç™sßÌU÷ó;9bå*n»ýN.½äŸ¨ l¹Àm]–¬ˆÄ‡ê+૸ïŽÉŠ%¿tÝMœóγè}á‚À'së‚ÏŽõ/%<€”’ÆÆÆ9am>^†1Ç'ÌÖŠž^`é²eÜúýÛ¹ô“Ÿ$³û‰$.OTDò< xà\bžOc—ùþ›2*%®¾î;œ~Ú©ô÷õ„ªnó¯7)¥¨V«T*<ÏÃó<*• ¾ç³déád2y>õ©O1òÜä.{¬,RçÓ3ÏÏ÷iìr™Û{sÑh×~ëVÞqúÛØ··$Q'×CÑ)/Ò+¹áÆÛH77òØc#¥ŒŠÓÆ4M,ËĶk6/%hüqæU$qÀ»ê߯…$ Cª^ßóð… <ªeŸþýÖ¹„o¸+?—à©_ßyLëõE£õl Gœºá„/éܾkbíGñí›o#fHîºû )qb6†ib©ÆflÛÁ”&Zó8¬úÈËtf¯Tzñ_ÎfRæ (ó”ŠyÂ@á¹| Næ¬w¾‹+¯ü"¿ð6Z-¯-gšm­­¿I­\uÙ'.ûmÕBŽmÏï ©!‰³°l§¾òm­í¸ñ(Fk¥PZ#„@h B€­4J«CÊûbÞÑé9ó̬¾”²n· êïR ¥RÉŒ“Í&<\7F_Û·>þðYÜXŒ-ÿüa¡½axêÝï;ïLÂàCÝÝ=;…”ù¶…­÷Hi8‘§7‘RÒÜÒBSSSmÏó(‹4¤RX¦‰axžÇøø¶m¡”ª3/¥$‹E ¡ZÃAZS.—#€k!N+BJ¥ê Qø Åz-bRJz{«˜¦ÆóB‚ ‘ðÐZlÛß¿ï0Þôáü·Ñ=ÝÏ~òž{ïW3>`kí`é²e­ccƒ¡ÖšXÌÆ¶]’É8##cÜ~ûÄb“““sÌ1œuÖYÜú½ïSSSÄb1®¼òJ´Öø¾‚r¹Œ”’žÝ»‘R¢ji¯Ö”ŠVP:ÓZcY---477cZklÛfxx˜M›6!¥$—ËÑÕÕÅßÿý?°qã”J%òù<¾ïsùåŸ!‘°)•¢ðX­z!v…>רgs¡ãOx @¼TÊ"„¨Õ÷©TŠÁÁ1¶m{×uÙ³gétš––¶lÙ‚ïûlÞ¼™ææf®¿þzJ¥•J)%–e19>AÕóX³f žç¡h¢”ŠÔZÈš„!Ù¾u+‹-¢¡¡)%Zk‰ìر€|ßcÁÂlÛ¶ÉÉIvìØA±Xäšk¾BØX–CµZ¥Z­bæ¼a«@GÇâú`*Õ€aH'†iJ’ÉÉdA†‘Z¹®K:ÝŒ!Sù<ííí444ÔÕ~æˆÅctvvrØ’%LMN"”Âq¦!¨”Š„¡Â4MRŒ Ôª†a†!‰D‚††ˆ!¾ïcÛM˜†A¥R¡X,ÒÚÚF*Õ@¹¬"Ê«Õ BÌGæíwýð ÁÆÆ& Cbõe>ŸG)EX–…ëÆTÈøØRJÚÛÛ"JšfìÑ0 ù<¾ ´&ð=´Ø*À4ã S©¥–eaÚf=©1 ¥T=Ñ) u›ÉE402ÖÙÙ‰eÛ ]À@JM,æÂ!¼­9χ Ñ*FN(jPvu-á²Ë.#N“Ëå8úè£x×»ÎÁ:×& CZš›(WŸ™×4M²®Kà‡$“I‚ „¨E ¡5étÒ´ÐaH¼ÖV›`vÝÐÚÚÊE]D*•¢X,røá‡pÆgrÊ)§`®›$æ8˜Fˆah ±˜F9§"¼é–¨{fÎSšú¦iª™ÂDJmÇ}'Ÿ|’t:ÍþýH)9餓øÎw¾SWÓ 6ðñ|ÎdÒ4‘B ¬76J+¤h©±,Ëq=!%FÍûX4åóyžzê)\×edd„ãŽ;Ž3Î8ƒ;±1,ËbÅŠU\xáGÑÚDJ…Ö!@kòój@6;qàXYkåGJI Dk(ŠX–E¥\Æó¢Žm[[¶mãû~Ýþg“š٨0D) B£ÃPDà«Z›<„ÈÇ(E†ÍËå‚€r¹Œ_ã¡¥¥ˆ45NGïR ­#T´up^2Ãð ^˜•d"¤F+ï{ †{öô1<g¦1ãð^ *J)¤”„J՘Ѡ5¡ :Ú8êZý©Z‡ˆÚ}ZkÃú3äy£££$IöïßOÇâ. icV¤I–Yk§+Âpv25?¦VóýcöþMA¥Taa{;ýè?’jhfhÿë?M‰Ï|ú¢C)“L&ðuáµÖÑN­Q(L!£’¢Ö ©™œ%^ªö,µg ࡱ‘óÏ?Ÿ¦Tš‘Á +ŽèB.¾ðò¤`Ù6žçcˆ0Jžt^•ž_¥ÌC©Z]|%P(T22<ÁãÿñgŽ9%EwõXÕk æQ„@JI>[àGwÝÇâñÉÓ»ŠdÇ}z—²juÁØÊÅQv7Ëw)¥:rhÅR‰L&ƒV ËŽ‘LÆñ}\6›yøÿü–çwì`íQG¡j‚ÏpX©xܳégÄš|Ö–ÙþPžâ´â¹–}¬{óᨩ£)瓨P#„:@æ—Ó ñ¡Â}Vmð8æ¤&žzŠÌ¸Æ0všl¦@¥éq’žÀt"§¥¾ -4Jk Â@×àª_Å&-­-!hL¥˜š˜ 3=],uŸP k}…ÕÇ7°wWž©½!–cÑà4S˜®Rpç°Î&”’©õl 8j^ð"I9Ÿj¥ÂYþ;é¦6N|_#^E£ü3nÏ(8YªÙ #c,éê¬Ûo†Qņ$ÐQ©ª˜ë¢‰òŒr¹\¿ÿ=çžË–?ÿ™|>O|¦úÔ‘3Ÿåí'|ˆtSo=+MP…Àqù|‰¼“!(VÝOÇâV”šÝd=„œÇ„B¿n2b``€Á=Sd|Cuï¬TT’a@¡'—Ë¢õau" ˆÕJ#L¡%hZJ$-^µÊ‚ i]°€j¥‚ ÃÈwè(Ž ±¿w’|“bŸxF›ð•Räòrë²,^Ôü¢9¨•2 ­v‚¡¥´ÂDƒjÕcÍQk9rõj¤D*õ:Ô¬é<ßÏИÒB©?¬Ö¼¬žåt¨Çr4õ•V*J„êÉQí}…¶£k)DÔv›•L BÄí$ƒÓÏò˧¯¡§·©ãHaÓóL/ËèÛ÷mFèãø%¦ê›Tƒ"Ji CÏû‹Œ¿ ùòÔ-;wö:“#¤aÑ»}œŽåMt­2¹ïŸçý'{¬_ö.rÅ2“…>R±vv3e/O–êÙÞ a¢‰TQHp”Ƭe‹CÑ~j#¬i@}€Ø2†ek~ùèµ<ñÄÓ¨Jå瘭ø!¥‚âÈcÛytë(”3œ²òÓ„JSU…C~u2tÆÉ2>’ÄEJ¨‹žýã>ׯ6lZZSä³Eº–/fj"ÏŽÞÍtttòès7óØö[è›|œBu” OEiAzsð}¿ ¦eQ-Wð}ªï!dë½j¹nç Èe³–I"GJSØ$b-4¥bÜñÀ5üçÖ_0´+@‹—´pØ’BBPnm 8­Ø²í÷¬Yõ&Z»P>HC?)„ü­’™£¹eÁ ż÷áý}}L •°m‹–)F3¾f×ÖA›­&?ùíÕ í›br¸Šb€•Ç>ÏDn€žü ìØ‹¡Öš‘áa i¨ljÖV]JÓ4•Æ’(‡Ëqˆ¹1lÓ¢±±)êîžîù1ÅȆÏ3Üã1½?@û†˜Ât%Ùñ* M6»ž$Þ`²ìðUôdbëÀ½4'—²¸a³sähý¢Èÿ´ònÌ©±ÒÌßñX—½¨eQ{ÊÊâÙÇH49´´5€PŒí/ÓÚÞÄ–G{hhŠÓœnapß~®G7?@vLŒA¨ aÔ>;餓pãqüjµ¾ TAÝ/¼ˆV­ï/¡/w]~õË_³oï É•;Ùüìo˜ Y³n眿‡n×áM+†wçhY˜"f9Lhjh`áâ6ž|ò9öŒÒÔòŽ\÷ÌÇZÓéÍÀœ˜™ÏTf®Ëùt¥7æZ+ G¢Êš0¯‘ /d0BI×›[š¦0®0 )NçH$’Œö1\“ÿþOüÛÏ‘f@¹\¢««‹åË—ï×Vÿ`šÝ’€´,ܘ˾½CÜ}ÿ7Y¼¶DPLДn¢oç$B˜¬XÛF÷3Ô2vRL™l}xέt¬lâá·’h´iH¤ÉŒiÊÆ‹ÓÁmK–¶?ì¯0ëÝj²¯²±âåÎ:òøT3 #£I-0iN'éÝ=L÷ö>šÛc4µ9”§ªUÆfƒB¡Š±°„7mùéæTQJe$qZ[[­¿üå/v¥Rù (1{lvHJ‰ ÝÜҨʀãMhƧó$“.[&waÛ6Ëjeb4G.S¢Z­räúVö좿_àåºàUÒ­qöwghh®º-©ÖæÙˆO憎Ô!†‚K«…êÕ ÌæR©ÌÈÞŽcàU„^ºlùéÖTidl×{ÌX(&GJ¸ŽÅøHÀª£:'»{ó圱ºJ)eÛvÜuÝÆp¦ØŸ£ðsš”}ò„a±XÌç*=—ªûÌL”¤¤êèZÞ+{<3=²ÖÓù„QS£¾v]»ÔÚ²¨[ÆKK”•YlVP&Ä —²_%µÈœÏAmŸÀ#õÎ _¼ò[]yæo)Us‹ãñ„—tKË^û–nÒ5¶nýÓßìéßq¬W­&¥°Â®Î•ão^¿áùT*"´ H!„¬':Qo&!‡ Iµ{”®%ðZk%¥¤Zõõðhÿ¢J¥dZF¬Ø¾¨sŸi™Å|.ãŒN %5”Ç. d¦­¥½¿»{{Ç=÷Ýô¥áñ='TK¡¥Cáe'ŠOÅß²ló‰™÷=òPï!wˆô׎9´lÅR0Ûÿö=÷Á{î'2! p€xílÎ:ŒÚ!kgQ»>ÔAUIÕŽ°vmm-O/î÷ Z[[ªK—-¯ÔÆÂÚ3¢»{û8ðþ/}ö–Æ»ï½ÉÜ××çe'Šó7EÁÈ¡(`î†#(ÏHÌs-1>Ín_êCÌs>eÿ‹ÿ¿j¿x¹ ýGoô¯Çßpú¿‚bàøôšîøIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_inbox.png000066400000000000000000000105731217176075400260010ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞBIDATxœå›[seGuÇݽ/gŸ»Žn#it™Ñ@á@Â%Æ ØP…ÃÅI€˜2¤òòÄ U$ù!߀—¤R©J¥l.± I€@T031…Çž<Òh4ºÌÑýÜϾtçao9’ÎÑH» a©öh¤Ó»{­¯õ_Ý«[ÂÃo³È·[·[¬Ã¿xöÙg§^zé»mc´g@¼J=”öja¤­§Ÿ~Ú~î¹çîtr€×¯];_.—캮õÿ%<„´ÛíàÑGýÀáÏŽ ¤ÊkclËRhmøMA”‚J¥íLáðçGØÞÞfwg‡lÛ&Š¢·^Ó·@¤”h­ÙÙÙ¡Z«ù=Ûþ…B»®K½^çúõkìîîbYBüfÑeY4 æææ¨V«d2¤úp»žYÀu]ÆÇÆ(ŠÌÏϳ´´„!åzùuCâòJ±ººÊÜÜ™L†ññq¼T GèR×åܹsxžÇòò]ööö˜Åó<Â0|Ë9‹(¥‚€ÅÅšÍ&‹E\×%‚ž)­'#iY8ŽÃÚÚ*W¯^eff†¡¡!¢HcŒá×%2”Rìììrûö"žçqñâ,ét)_êô`_¤”d³Y¦§gØØØàöÒm*•*““ç;$óvʾw–—Ù(—addÇqNÄ[=0Œ9˜ÇattÏK³²r—ׯ]ãÂ… d3™·-K(¥hµÛÜ^\$¦§§) X–•Øa|ï%½À`ÀB!ë^ŒIæÆ ÆÇ'ÁÝÕþ­Œ “ävÅÖö6w––Èd3\œ¼ØqùÃzcú’wè ÄÜày)&''I§Ó¬­­R­V™œšÄ¶¬$$޾gýp\6Ù÷ÜÃ0@ ‰6†»w–ØÚÚbtt”áááŽË÷ÒÙÄ.Ýs¬>`’¯¾*bÛ6ÃÃÃxžÇêÊ 7çæ˜œœ$—Ëéƒ!a hm5ô†ç¾ÁR€%Rp„`•”´Ú-–n/ééé Å–R€z[Ó_z`ݵŽBJ‘Ë嘾pr™…ņ‡G….Òša·¥ ÄÛqf’a, Žä]IÚêŠ]!PR²µµÍÊÊ]r¹ccSxé4Rt±|?}OÍÇ„ÀaBr]ÆÆÆð<µµ5êõçÏOâØ6Q¤ÑZfµÑD€Œm6Ú€Ö1B@ʆ”%±%x–ÀhÇ´6ܹ»ÌÞÞ££çìbyó y:Ö–¾Y@Ÿ€NG–E©T"•J±¾¾ÎóóLLLP( ý†±ZÕT¤!âÓB QržÂ³4. ¸ •E«Ùdyy!Ó3Èçr¨}—?¡~Ƙ؞Ð' ¾ïcLNNQ«VY[[£Ùl2P*áØö© 4ûY —ôÜ+vo†ú?÷Û…QÄ^¥ÂæÖ…Bééi„´Z-¤H)ûï)&¸_Ôh6šx^šK—.á8å{÷¨Öjíx·Ç>§Ê ý?ÿñÈA°»»‡R‚©ÉIlÛ¦ÝjÅè*•“\O願"yâ˜Â)$ããÔë5Ö×ïÑjµ( ØVœŽÛâ,pâu@òƱ$¨µ¡ÙjR«Õ(ò”J„a„ïûŠB€”qŠ¢)¦ÓMün»ÝÂó<.\˜¡\.³¹¹I!Ÿ'•òò˜Ž ¾ ½$:ŸAEÔªU@01>Žëºø~\tÝwÝûƀɬöÖíˆt<à׈dl!ãããÔj5Êå2ív;&ÈÄãöõì¼·Ïg']˜}ÿïz!þÑà·}¹\–Ò:ÒAØ·ô$D\cìOZ=B:{€ž~Îd˜™™¦\Þ`g{›\.‡ãº ]ãNǽҠ6šF£1†Ñs£x©abŒAªþu·nè©BŸšƒ”}LØzßÆÆ©T+llnb·}2ÙÌ]bœN±0]_aÐlµÈ¤Ó –0Ft\ñAéHNÔ®{t)ãío¿¸;îüC…äóy2™4÷Êìíí‘Íd°lû¾=§*ˆ$h´¦Ýn£µfdx˜L&“̺~`µµ[¤0ôK½ÛK¤”ÈS¬C¢(BJÅù‰ öööØÚÞÆR)ä6CaÑl6H¥<††QRöœucöãü@mã`@¨M¯Œwà!ÀR#…”º"ÝÕF™xU™Î{û:EQD¡P NS.oP«UÉd³§ÉqnG@©T"—Ë¡µ&êQþ6üP³Xn±S Q‚È`öÝ3Á©á‡¡”¬PGzŠE)PUøÙ/|~§ ,ƒÆƒA ( ©”$‹dÈØ–Á±–Ï¢(B)ÅÄÄ8»»»T*Úí6¦ÇjáZa;6ÃCCÈdÖ{ɾk;>/\Þáû¯W˜Ž­@Æe/¡$FÄ5O¿§ˆWt1 8z@/‡7ëçžÍwî5ù‘ߎÉUÆV‹ä;FИ˜Å×ÿÚ⣗ZIÔ!Óö÷%Åb‘\.Ç­…t=˶ÔÔäù.4ãxïÇa£ƒ†=Fß9ÆÊô"< ³hþ«€qU€é©°²!soHÑÒ‰[ 0‰Ä Ò)›÷~Ôf´ØÆq2é‡)iÿh_%êÒ쬣”uÄùŽö¼æßíþµÑ¨çÒ^ú‰ÑÑÑB¥R¡V­ö$>% keÃÍÝ‹Ì|ö3¬Óhÿ Ælq|EèT‚ƒÈ dìòtU‡•€”çàN•¼ýC~xk“Kƒ’ò/EQÄÐðR*Ö××çÂ(º©”ªÖjÕµ#À÷K®ë>þ‰?õƒÇÿPú;/¾H£ÑèËüŽø™Ú—¾ÀÐ3Ÿc9ïµé0¿ "Œ¢ýÓîÿ߉ö˜H#, R"Tü B©Øj%QJ’J¹„•-†®ü#îâÏ ë{è08Bpa2qþxýÆôj×sJŸ}æóÓ#ÃÑËåxåÊ”„aHpÜ2þ]ì7žgõ›ßfªÒÄr{nöNg¼€´ëî–)]ùgR˯ ë»íV_]¢(" C®\¾ÌÄù ñè{~÷oûÑ€0 ¿<4<”]]]ã^¹ aô}‚ Ä"¼ÆòÆ¿±òÍoq~„3oIȧ\Ú;eŠ/ÿöÒ¢ê6a«y¬.a"•b~~žvÛ'ŸÏ?õì3Ÿ¬×8GBàÏ?óÙ!­õ_•Jƒüâå—;kø|>bÕ TÙ[ÿ¶_J1ù'Ÿf9åá·û\ªè"Ú€-Ï¥¹·ÉùëÏ“©ÝB¦Òîïöûýi­©×êø¾ÏkW¯2{iVÞûÅúW/n~€0¾TÚÙÞf}m ¥Žmã¥Ó'® cH±½ú=¶¾+˜ùä'YtÚ~øÀª€6à(H»4v7™¸ù- »7Q2B:ˆã¯4ˆäÈ­Õl¡¤äæÜ³—fÉ䲟ý³§Ÿ~äÅ—^ºÞÝþ@üé§> £èË…b¹¹¹»º®K†DÁÉž0Œü—â—Xýþ2Þlâ8ªG8\VÛ J‰ñc7¾AvãuhV0~óD:„A€Ž"Ü”‹6†F³ÁüÍyÆÆÆß¾rxô„aøEÏKMÕkuÖ×Ö€eÛH¥£(YŸì1h‘÷—)Þy‰òþ›ñV ÛV‰q?U°• ”IQÛÙdtßøV¶‰ttò±£Û¶ã •TÌß¼‰eY¸®ûÅO=õÇSÝ6wüéÊÑZ%ÎpûöíÎzÚu]té¤!¾˜Uh.b–^`CÀÄ~„UGÑì “Ä|1ãRÛÙäÜÍoÙº~ tpj5Ä;J×uñÛmjµw–î084˜½³tçËÀßí·íx@†Ÿ³”z¤ÙlR.—øøÛêÌ~têG'³¦£|c‘â⿳õóŸ2!4®-ãÒ8"fû´K}g“‘Ï‘Þx ÑÚÄ­8¥eÜ(ıíd%)X¸u Û²QR~éãýØÐøØOJ0_MYkk«¾T7åi}ŠÙç¼—²õôßæž‘ßÿ÷lI[B:åÒØÛbäæó¤·®_CëàÔc)ŽãR÷kT*Ö××ÈåóC_¾ÉRøÉ?úð'A|ϲõz=¹þ&p]÷„†ƒHjÿÇÝŒPT³Ù}ççɽûƒTê­ÍuFßø™­×Q~¡úí”RèNŠ­5~¼Æq²Ù,õF㎀wÿäg?­Y‘Ö_ˆÚ!¶ã ’áµî]K?,ÆR–…¿Ù8¦ü%ÆÇ«¼¹ù<[Q@˜fxá¼3ß{Tc )/E»ÕŽ·é'(³ ÀI&RC¥ZA 9¥á‹À×ÅcïÿÀã~Æ)¯vuπњ|¡€’’jµz‚úŸÁH›vz”ƒÕÚA† dÔßøý1‹Ôëõ#›³¸>q*® x¯å8ÎßxnJœx‘“\Q‹SŒH¾KÂ(¢Ùlv*µè¢vå.F*„Ö£y¿Å^‘ÏåDGZëø #Òh¡õƒÏ´y¤Ñl>kÍÎÎ^ðR©xûÙ½(ÙïäP_B&ˆäÌ/`aajµJx:¢~d×C„ ‡˜šš" ÃѦF\¨Üwéþº´Ú­ß³ÖÖ×. Äûd’ò¤R(¥:3+“*Åp* A³ÙL*0ý*~/BJt¤i4êܽ»œèqÿR¡èªCž„„—­z½ñ¿t.ÅîÇS÷,« ©drp`ìg[–Å»yׯÖ<@]!£»ËËø~@£Ñ<š Žœ‘ C(¯Y­VëÕ^w~ÓMv]]vêu PQ1P*%·5ßü ÔÆ\Ž´[­§Bè"È$4CVAܶZÍæ¼1f:¶—~Š%Ú`dd„0ŒWbo…H‡çööö‰Bí@¦êÛø0ãú/_ýUúzýÚö;.\œçŒtKÛ÷©ìí¤õ"¥$ *•Ê›ñ'<¯ÀýÍЯ€Ç¶Ç;KKÛÅ$öÝÓË#Wà>¯¼=vÎàzrú @|,üð×àþnðÕ7£Wà­3þÍíûpî{Àð?@‘³ÞFüÍüt~q¡ÇŒü¶Èoý_ÿ ÎY…b%JIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/folder_tar.png000066400000000000000000000626551217176075400254600ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœì½YŒ$Ùzß÷;'"r­ªÞ—Ùgî™»ó’!òФHšÖ‹íÊ6,øÍ¼ÂHàLÞ@¶)JÀW?~0`ûÅz DÚE“)ÞuîÌôÜ;Ó==3½W×–[DœóùáDdFÆ’™U™QUÝÿFufDœ8q2"¾ï|ûQ"Bƒ >ŸÐg=€ œü³@ƒŸw|ç»ßÿu¿*";oíëׯunÞ¸~gŒ÷?ô=þ—:®­ Aƒzñï~ÿד¯¿ €â›ÉöE¡ÛíâyÝNßÓt{]nÝòÂå>7.vGïÿëÀÿ³é±5@ƒkâ;ß˸›O+.&Ÿ´‚­V‹V+ î{»E·ÓÁó¼¹þ„üðþ!»xáŠF+Õ>ˆù;;~Ã48uL \øU 9'GàÙÏ„Øó°ÖN?ã8ÆZËãÈw>9äáaÈÕ­¿ô•ËtÇMøÊN ÔÚ0€Ÿ{|÷{?øõDþUD@©oâ¦ò‹ÉŒžõzžBDȪÞCÞ½7äáAÈVÛã[o^âµk=w¾‡1ú£!¿Øßüoo@ƒçßýþ;¿žܯº œo:›››Áfbù1 \D0Æ`­#j­ƒM)…R ÏóPJ!"DQ„ˆ8ÂÿtÈ£ÃëÚÂ-Ä€ð‘Ë$–ÂM¢a žy|ï?üuœ5íW“]ßLˆq*¢û¾¦Ûé¢=oªww»<í>óX…À•r©”Â÷ýéö2ìE|ÿãÃ)áÿ+_¿ÆµÇd¦„/Ž1 ÐÒÐÒv¼…ýž hpîñýüðï/3O>´Ö‚îâyšN§šÀS1¼ŠÀÓ™;ý;WáÑAÈ;wx°?æÊVPJø‘¤¿ÈÍ÷‰Ä‚íµ.^†48s|ÿGàÀ/—€·.pDîõ|M·ÝA%3¸Ÿ¸^‘À³ÛY†ãÏàÇÅíGC>z4äáþ„Úüò×®qeË‘^–ðóùìvKÑ«cl hP;Þùá»W* \{Ýví{t;m<­étºhOÓí¬Nà)òžÙO · ùÁ' ÆÆ‰ú_›ÍøQ ?öÓj¶ÏS²yùŸ†4Ø~øî{n~Q* \Óiwñ|M§ÝI¶;x¾G§]”nŸ¯Bžðæ‹—§„/@dalÕì÷dåýd•1ù¥Æ€Ð0€KñÃ÷ÞOýà•3¸NflÏS‰h~<O÷¥Ÿç‘À—EÍÞy<äwLŠ„oq„ ˆTдÌOA]Ä h¼›xbd“‚‘Í¡ßïB¯çÔÑ~ÏYÕCà)qsŸY‚?oÈ~~ûÎãï|rÈ`lxãz7®÷ç?4``FÔ$t½ aËÜÇÆÑ0€ÏÞ}ïÖ|,:|3™Y.¢d:ËôÂîõ“ÏnòÙëú\4ƒ§xVü¤Èþ×¾¶C¿íTu+ZçÇ2ÎMíË(¼QTá½÷oÍ"ÙÜ‹5—l8Q¼åfê^ß%ž´Óí†À ˜û­Éw+B ÷žŽyçÓ#“„ð¿ºC¿3#ü(ãΫÂqoU#|Žñ^:ƒ«¢<}1R£šÓÅÛSמ®ÑÓÏ”À«ð<ø"D~ Ž-ïßðÁýalùÂõ>_{yžðÃDÇÏŸ›BÍí«¾—%N€ÚÐ0€3Æ»ïðÈßuøÈŽÂåƒÝÔ:¬S7™V´;î³Óî4¾aÌ,óâ,öF¸uï[÷†DÆòÆõ>_/!ütÆÏÞÁE~ýªïeç ΖPP3~øÞ­_Oê×Q¼ ¼\Õé¦þŸVàÓ TbTÓZÑítPº!ðÓBöžF±ðÁý#Þ¿? Š‹„oV˜ñ«/ U ü*oŸª±<øá{·~ø=_º @Í líNOk‚  øø¾O…~Ò—ÑZ»Àó!« އ¼¸Æ–[÷ޏuï |ùÅmÞzq‹–ç’{ŒÀ$cÜ;Ñ5sŸ 7Ã/òø5À9Çß»õš‚ÿø)ôû=.ììÐëu¸ˆâгÈÚlYqn?òþg á¿T$ü±“¡Äôq”=¹ã<©l<Љ;9!°$Äÿ.ÐívÚܸ~mê+_DàϳýYÁ`óÎÝ>z8¤íéJ³„Ÿ|æ 7ûø ’ûd›­ösކl þTâõ•—ñ<¯4»,Íop6È>)á?ÒÒšo¼za)áOû©ìö]e¾ÌµOÃû–DÍ© ²bÐÐ Ð0€5‘Ù¼ÐjSâÏêì áŸ/ &†w>>à£Gú¿öúE^¿ÑŸ~h`"κ¿¤ðe…¶KöÕ†¬ ÅŠÀµ+Wâ?§L¸ý`À‡†ô;?óÖeÞ¸>«±7ã/$|µps…7W%ôF8¯ù¢ç{\¸°ÓˆüçöÇüà“îMá¿y™/Ü(¾)ßóÈpC(Šü‹ãæ”vÒ¨çï¾ÿþÏ£PÛý-`VFª1æ=ì9°7áÒV«@ø“3~~×R†zV°ç¶+4*À³ŸUêæK @6ÌàtJ_·ùÞÝ}cà m~å׸qÁáÌ1ˆœÚžZËF¥ñd—XІ¬÷*ôû½J?~^-hPLøÓv9n^hó³o]ž#ü±qËl•'´ŒWe&J%ªØÿ†œsdsÝ«fþ”4Œ`³øö‡»¼ûÙ€–¿øÕ«¼|Ùe7q³}h™‰ÖjÍÙ~¬B¬‹,ÿùd •;=°v-CJžÖ0‚áÏ?x‡†\Ú ø•o\ŸºóF±k3—U'É7b•§z¢§˜q¬$ö7 àüAòoÓqϯ‰Tåí?/Hß·?zʇ†ô;þ”øE`?šOÒÉϬ)ÊfØufüüm.e4ØüëSõ.©lôàfÑ0€5°)²Ú$#(“DžG‰c0‰yïÓ#@øÙ·.Í>zo…Ù½ÂûVŠª»X¸õ Bƒ³ÛÓóRÕQäTfhÀ¹Âº„ºL yÖA6yçïðò•×cß~äªñ”YéçŒk%?ÿ8†½• †%RˆJ£€ÅÍêîû¬aÕ3l²Ï+”:–þ¿ ŽK¨Ç½þ³ÄJ rŠðñ£1"ðÅë.clñCnv4¹ý¼Šqp¥€žæÎÉêý9â_„&èÿ%)¶•jÂ[@áp‰(Z¥¯DXäMP4¡Àçþ¿yÂO÷W쯊˜Û®8Vf“­œ¥s Êl…Y>³Q&mÌKb.ù=eãXáØºhÀø¼“™Ÿ}š»ŸõýgÛ·ïùƒYóß#`æÀª>û…La‰‘./yäûJ)fÅJËÚ¦ÛÓÏF8¯ø¼³‡eD½èxê>=–!0gI_*R§L£BwÏ5­>žL]‰YB…’päL©ýcÚG²Sg ŒyI¦î¤ †¬dnûÜkùh¿¬‘//îfÛf‰þ8Äÿè J:+Ë‚óTEƒ¬Ao™”P#°TýÔh™ÓÿSF7F–]£‘Î#>生A6²m6ÓÍ‹ýËÊ€äz³í’Øÿü9”Y¶@È"b/Ë,µ $;³„ž~·P&yL夛faóˆ‚ù¸AYÄ_öXösó×Îl¬ óçõø|?›i—ÕÛó¢ú\ÿYŽ0×(‘3æü‚+qJS×+Ö0€5Púœ?‡(óÿ/k»‘ëf> ³{…Î_æ[ÒoU O~&.ÌæɬøŸ&\u½c Xî]þ¼“¿ÃÙdFÊ‚­r}^È‹ñeâ}Ù/+0›¬8Qâ"p¶?Éï®Äœå¿Æ[Û0€µ­éÒ 4á§ÆPF”e³vA7/ë§Än0gx«20l®ÿܵfýU ¢„Iîx#œKl~aÐ盺W’q¥¹ssHiÔæöMiNŠçÍ1’ _*üì%ãH·µ%'¤ßÍö‹Œk¢ak@¬Ì\_ bÓŒ2 ¨!ùÉnηžŸÈçDþªÙ7{B¾]>I§DÅÈìžsÿ©d…¶ nQ#œCT%³4uNÇ2²0(CÌSÚÎzòçæHÙõ²ç¥L!ß_E ÐTj)!üªß°ê±uÐ0€µá´ä¢‚îNu8o)£¨˜½óX)”¸¢KÑÿ_ª6TŠKwB4 ` 4úÿÙA³Ø¥—%®©©VJBu3Ô§Òÿ–Ìæ%‡*1«0;»j¬•ú?PÌÜ °ÜäÑ0³A®HNO‰yN:È̦ªÄZ7'âg¾O¯³$Ò0‹9×b‰®2ÇLÔ̆Q)½Ô„†¬Åü"•Ÿwœ–D$¸%ÁmnßüXÜg^G/Œ°„TºÓ>W Ð,ãqEQ´Í­\h$€s» JCc ˆY„!ÌW J÷Ûé"(óýe§ŒJãbɦ$Ø9Ä4­îü¬3‚EåÀÍö«¨ ðdfÒ›#4Uþ8ªîbʱhæŸZë+"mf‡¤Ö}k]ªqF÷XµzDA=Yñ¼“ ak ÌÇ[Ç5RkRAÕ€!«‹Ka_¶ç2Ã_:”*2gOX¦S”èð"ó¢yVUQ¦Èh¦ã¯{v¡aë£æJ·å—|vAmqT±Êµ™s«e•¤”ûøK†_ftœ©9vÖ(ßqIÿ”0…|›Æp!ÖÖ&š­týg€ä‰S ¡ÐCÆ[¶ÐGÐóöÛŠ`ŸÒkåöϹù’µ ?1%ò©  º¿ü†R àœBªcMOsÏ#H±±@¡Ü÷¬Må(S2UuýËÎa~×±Ìêþ-ž«ó•~W 'nV>—Ô™Jy'x®¤‚ ¾;õKAÙ©ªì@…›0éi’èèf^÷—)Ã)‹ë ¶ì:y÷ez:Ð0€5ð,® ðÜ0‚üìO ±ç¨}‘›­Œè\rzÎ,â±üļ œëœÆjÀ:H"Ï»*P†“0‚óò;§*}Ehné/ÊN¾Ë\pKúÊ3œBÍ¿7ä:×Y|æzhÀ—g«0‚U*&¦%Áó¾À ñ½°“9¶„ÿ-šÓ•¡ ÷¡D:™ž_q½²[©rÚChÀxU€*T1‚Uˆ¼®E@+¯³D¬d ¨² –qnØK¢~g±ßZ³’½ ÚÍXmȆ ×uw°J’žu{B> F0M´Q3‹}ª‚‹ÊXú Ki„`¡ÿ%ÇÓF©åY†Ÿ”|+Ž,¯Â”ÿM2ÐùDj‚õˆçyB]KƒÏúså¶ ¢vÙlžåê^¬&,Yî%aü6 _UÌ/âÂ6ùœ†:Ð0€5`¬=‘Àç]<ý>ý+g2Rµ‘¡¨‚]`.`gñ˜Ýì_ÌYdª¬N¼Ô`±p(k£ak¢™ôWÃIU£cÙ ’¾ z7ÅºË ÌšÎ_‹Ì쿤íügmdQÛEÄÐ0€ ༅Ÿg‡,"þÒÓSU¬‚ÌÚ1w<Û¦Œà] šº|èŸÌâ>J.½´m¶{S£Ð0€5Ðèü'Ç2F°ôÞV{Þ2bYªÄïÝ»™:+ÈÌð—KÍ«Ê$\äÛ¯bNSCæÈ :ÞÚÇAÜ)V© \z^þ{錜%àY(àJVûý>•ªÏ™ïº¿,ð¨D ™sƒPs«5Ð0€µ0?4Áɱ‰2aù)!&ž€4+0ÇŽ%mcáÙ¨´=,i[5Ë£út€†¬E«7¨ÇJ¯MŒK0_Èéøå^{Iþå ó ¦Ú€¿ÒX+D#0Žë³25  Á3•û¬Ô²‡™Â›îË« 9d ®Ài±™¦1o|\œYX2˜Ü†¡”Æ8l XS®ÝgŽù 4÷@ ƹLqyÓÌñDôO¤½Ò‰:'ëOWû«Ðó cÏ´É¿J‡5êÿÐ0€Ï Rz(«¾WF+E+}¢”fÞ› fI¿ÊøþÀ4¾N=)2‹ATïìÒ0€uÑþÎY’\ö Vú‚ØŸÝÓæ‰Û¯,rg•§¾¨®ÏȪ&ãXˆ’B# àbYØ5AŠ ?ËŠÌ^Í%óÿ¬‘•Œá¯JœÏD.‹âóóýå~ B[ûüÒ0€sŠªUr8ZQ"èœÕ>«ŠÏñƒòzøÒ<r†Å•]%Þ†¼-BÁþ¤Ü+±I4 `Mˆl.Jk™ùYO5®U~€lÀUΛ±ú—uXuÍ*Ž2‡”í.Eh`ׯ^6 ` ¬«œ4ø¥aóH™°*õåŒ 9×^Bøi…_É[òr·¼,Ÿ`zlÎÓ·øYçŸäa˜{·7àóMF 6Œ ™'²ihq¦Iuäßì‹ÀœÕ_å)?÷ø)XJ¼ÆeÁD‚óÿŸ†¹a5ã4ƒFP4Ô—Ý“%úÌè—é,¯…îpYpQæó¥ËÊÇ xº/²E  ±œCdkæ«E^ÀY0‚Ó®¸¥3k6®?_ï0ÓÖNEÿùiº*ªo5¢Î«Ä°[rîahk#ø<°ò/þ¹!„/ý&ûŸ«ÒSS°êA0OO’z™TPè*÷¢€Ÿ¼oºYr{UÒç*·¾L*ÉZÿëæ XÏB(ð&¥‚•SuOY*2Fn.KN\†UÄ¿Lm(ã43¹äÜüAиæè¿,ð9ÁºŒà$2‚MK!’ûL¯5Ü›sê—ë’ ÃÆš¥L\*$‹|Êïœ!²bÜeqÿ©„q0ÉÅ8Ö<Ç4 às†ã2‚MÌäu0K™!±µ•e’ÉòË4-Çbg@é╇«ÎM÷íí©JO XÏr9ðEŒ ®ßS—‘R¦ÿÍ‚LÆ*HVl’æ+ 3e³ú¢ƒUU€ÒG¡%2§û.5 àsŽ,Qž#[›äÇ)ÅÚüY¦0e Òê>Ö²ÍVŠäÍqYøï”ï¤IFD•Ûy49ý‰¤aÀóPøYq[ŠTÜíiE`·™Oõ• 3°âwmÓ#ó8–«/È“=X(R’|dö³úAe©çù4 ` ÇÍ£ak`.Y¤ÁFPÁ·“ÍͶ%44­ëW|Áœ¹>ݡ敹+†]Ø-°?¶å’¤ÔJÿ XÍü_Ž£’Ìéûª\`Ngþ<-WöWu|–80ߪÔ]—2³ò‹¤Ìê ´D%feÞQ °žEëÿóмN>Ÿá'S«!{¯ÔˆWL$ª6á/w! ‡Óë¸oãù¢#îëé¼[ hðl"g)xÒ9µøç˜u>€g®ë)Q«¹m(ÉùOÏYÀªŒŒŒ"aåG©8Q °&$­×àT!Ìn»ÈüþÙFêî³Åã ÒxgmKÄòªs¸©{c[.i,èz“hÀhT€³Åµ äÛ,÷ +L—ñÎ /!Ìí$7[ç¥þD] ÿ‚á°xNd…£LÚïY¼NÏøø~cn»˜­7û®”B)¸÷ð }ø û_ýv?@>ÖX|ß_!ÛïçW›ÇDÃD£]l4`rø1ÖÄxÁ­þu‚ÞuZ[7ñZ;+÷ûyF§åö9ÂÍÌü R€§ûrD•;0KåÂÏ4w ¯ÞîpæŽ\ì—¨l°6ja¿q1¨<ý7Ùj¿ÂÇzÃ&¼ÊÍ›—hŽ÷,¾isxôÑ“ ;×{˜ ÃѼ÷÷xõˆOýmt+àGßßãg¾uÄÁ¸ÇÃG7¹Ü›ðÛ¿öKuüœJ”If²OÏ@ª`­³ ¤3¿ÊúéJfð,òÿJ@iÛŠ´Ã*¯ClešøSP5NQx®$€u!+õk7»Ÿ½¥•at÷ÿ"¼;&>ÂÆ#ŒŠ­à{™r 1£û„Ã{nÇŠö:xí¼ö%Z½ët/‰ÎÅ/‚vŒöóÈÊ|õ3ƒŸ-·¸—™ýKÒxWº~ФT4T<š•®WîÔÜÀóìL|ÛAh)Å—@½|ä——€þ«ýˆ÷ ÎôULYù¦¯OVsµvŒ‡˜Écƒ8ºÿϱ€¯{´¶_ 輈j_§wù üδ×BéÒQ<—)Vô)èèUfÿ’çRdå×ÌœSÝÚfbdæú+4;]C@Ã(„k7_þOƒƒ7ÆãÑß4aø¶ˆ\ÓZƒöÐZP+UzYŒ² ù×ÓÚ½1J£’Øuk-‚‰! C&ñƒGOP¼O«½ÅC#ñlѽü[/|Þ¥×Ñ~¿³ÒÏçãžÎü™`šÙê?Év5—ÈèË |YLCs×-gòùh`Vöó×m|>߈U‘ø’•ÂÛÝÿÛ·¾ñ•ÿz9þÅ- IDAT{|ˆïyŒŽŒG¢pBN°ñ­=D+¥õ,ít¡Æ8of–¹ê3 4x ±k¢6ޱqŒX… GD±€k<¼ ¾Ÿ<@…Áó<ð{Œ>a¸÷cÌhŒ`io]§³ó½ëoÓê]!è]"è^Dû­ÞÒ,j¯ ”)C–_ª½*ø&×An3 #V¥GË%%;òç÷/V:+‡Òç‘øÀ×/+oø¾÷7úÛ[_ûÞw¿óÕ÷>¸Å•KW¸tù/_bçÂ.\}Ï×D“1“£C&“!“ñp<" C”ÖN^÷ZéK”{ý’}NªÐè´¡§°QŒ #"c±qL4‰cbƒø^àt~ ÚWˆDÇsê,Z’ÅJD¡PX1Úû”Ñ“»<üàŸa⢈ÖöUúWßâê›?Eïòkx+x­íµopáÏ/²±¾Í"˜[ºÛu¾Ø/NL/B"…M×rÂBëf;õ+>8ŠÏUþØóÎ|à'/ßËP¼|­5—.nÓëv F Ž<¹—;¼‡ <´ßåÒÅËlíô¹zã&—.]fëÂW^Þk‰FC&£CÆ£!áðˆÉhˆ]Ô™R*Q (Aá¡´vR„µDq„ cÂI8åãÐ"Ö ”ßCc#¬š€€Š5$m1(À¸úVØ(F$F¬[à"Ž#—oŠ"ØêÒîöi]ÜÆ1²÷áÇ~â£ü­Þ èÖZ[/ÐÞ~¿{ee·äÊ3~!•îx¨*@š*Q÷ïÜãÎoaEÓíöèïlsáÒnܼÆööW^z¥qއ†“!Ñè Ê“á!“ñfcÃA¬FОò|Ç(<íÒY“^„~eP"fJHb"Œe Öºv‚¼N‡ —/ÒêõчçøA€ø(ßC Xk\¢L8f:Ãæèá·ÐAß1¿O°ýí×im¿Œö»Ó»xbQÿ$Œ@S3ÖÌùT^]¦q8s˜¥ Ïo»’N(aå—+ô'€Øš²SJΦÀ¨êÂ3Éþûÿø—ðeào? üuà p*ƒ,ÜM…1`)gÇ×ZÓnµèvÚ\»z™øå›cBF£1‡‡GìîîrçÉnßR(íÑjw¸tý*W¯^áÊ•+\¾zƒ¾çq¸Àhâá÷^¤½ý"fxÀèðãÝ»Œž~Bxô«"¬aÑ BñÐ>Ú P0%üi~»r³¼XÁÆlŒhå ">AÛ§½³E«×¥Õé }í{xÚOf4AŒM>W¯lŒ„F»ïº{ä÷ÐA¿{•`ë%üÞK´.¼N…ÿc9VdiF_Ï»ÐdúŸû yZÎdïΟCш·‹ì E·à<ž M!áXq>5q‚sÏþ»ÿðo]^µÆü2ðu¥Ô¯ äÐÇ™å (oª£½§ÿ''c0&9K´rLak»Ï…‹;Üxñ:‚džp4æéþ!{OöÙýäc÷>ã~·EÐ ¸¸½…§gÆÀDò)YC0Eeæ_YÛÔÖP2É?<Š‹;Ï Î„üû¿öª:WÞV­Ÿ0ƒ'oˆ‰ÞT*ø1áWÑž:c@«¸³ ÊD€|—–§i·{ØÖ6¯|åë¼òÅ—xù'Òq’ÑÉ`Àh<`2Ü'œLˆÃÁ < xÎÅåF¹ j¥ 7zNÒR‰oÞš$)<¥ð[m:ŸV'¢Õ٥ݡÛ÷0zibépäÿ‚vÄoÌÒeØçl‹ÚP4þ͵É ©²èÏŽÏÌJ™Í®7Ž„§£Å¢•$VxM¨‡tŠ»þËÿã¿ù+ñß÷¤…ß¹† Ú¤>[&ÆÆcZb°ñâÑä $tTjh•Ìè ñ–è‹™‡“{¢*‰ä¥0qL<™Ç`â[Œ‰Š$•¸ó” úQ.àF%Yf’\Jl©Þʧ’Ÿ1À‹ˆÅZ!èlooÑîuñ[mð4—&c‡cŽöy¸û„ÛÿïïÓù³½Þ×®]ãòµ+\½qƒK×^„àU˜L0qÄhxD8>"šŒˆÆCŒPÚýVބ䎔ÚJö•™Î3;æ‰Ò‚Á`E¡­c|­v‡N¯GÐéÑîôi·{ÐҠƇîïsûãOytÿÖ WnÜäêµ—™}—Öëÿ6VåŒL2ÉŽòÙR¾•Yé³ Ž§ ”L>é« ðp¯>‹Ÿ‘ZPø{Ån­åïkìxD8ú1¢Á ºà·œ¡«½…çµÀÓH{ ¸ŒgļDc$<ÀDÌäÐù¸•M­X¨©"àÂg•÷æ;=Þùà! qN"â0„¤L”X·0¤BPJ£I’ÐznV—]–!zÇ ñÈ#F°X§"XƒB!bѾGÿBŸv¯G«ÛC OûNåð4Xa{g‡KW,q|“7â˜É8äðà€Gö¸{çÞýÁð[-ÚíÛ;Û\{ñ&W®\áæ‹/±uùb"01q„“6Œ•„kÏÝ7íî×TVóy–øÓß™¹ûîÎQÊÙ´V(ßckëí^ŸN§ôÀsŒkÙ}ô˜O>½ÏÃOïótoÇtÚ=Úݰ Ÿpð>zúé¿úË+½niq ÓáôDÿ\˲PaÉ}ªb“ <ÆÄitâ9Òùó¨…ÈaI4™JƒVÄé«1ÄfÐÄéÃñ»ø^ º=TÐåãÑ;èö’ÌÜ$<$"Ñn„ CA>6ò0&Æ„†(Œ«1ݺ—åx†Vx‰H+VÜË’!òÙ"  1Xë¤kÁ‹˜„ˆ”“N|OÑÚéÑéõh÷;ø­6ÓcµÆ8B²fZ£Þºx!|­étÛlõ»\¹²Ã«¯½ì¤cÙß;àéî>{G|ðÝïñƒØà)èmïpùê®_¿Á /¿Boë2·¯¢´ÆÚO˜ ˜ ǘÉ(!hƒ gŒ-a "‰„cfJ)'Qx ­<|Oèv/Ðélt»xí>x qŒ…ÁÑ!ÞåÉ“'ì=yÂáþJyt·¶ÙÞÚæÆ ¯h f‚£Ü(ˆc‹5Øpï˜/]Q¿Ÿ?˜~›êÉÏüU³=äT2ßbÒÏQh9š,V[–á´xF- þÎë…}òï&_”Ê{’™;q=ÙpÈ„ Ÿ¢<Öm”ßB·ZØ ‹ò=”çáéºÛ'è¿¢1f“ÄL0 ÷î>d2ÜÇFãäå ÐÊ/±+èD„Еr¢¿“–›!þ¤š¬‚©%ÚÆ1Jžï¡µcTA¯E»Ó¥Õëtç²ç1˜¥«‚$ÂéÔ•½OÖY¦F ­5Ú÷è>Ý®qó…ëζ`-G‡#žîíñäñOÞãÞÇwø‹?ýçx­—/_åòÕË\¿ù;—/Ñn_âÒ…¾ïcMÈäèh<" GÄqŒ5V /Ðî^+V¯G»³M»×…  ž‡LB†£!“£1O>¼ÃîÓ'ì²ûø)Ñ$¦·Ý§ÝéÓÛºÄõoÐn˜p‚ØìÖVR¹ wWJ9cªÒÕ^Ÿ2âHíŠEŒ`vvÎfWÿ_<{30/d[†FØæ¬þ¨$òUŒB- À;úËÂ>‘cÁ3#ŸJDMkkÆ à7Ym”×F·Úx¾‹dÃk9&ÑÙ"è}•î‹¿„¢ýÛ„{w=½Ãèð3ÂýûÄ“ÇD£§h •F´ïÒfE!Ês!º"¸·Ñbd¶ˆ„µIL¾ï;?|«C«Ðê´ :Î-'¢PÖºØôØNT„„ÖËjEðK¶¥±‰ø=uU*´rŒaëÂÛ·yý‹š@kƒ!O÷öÙÝ=`ïéwoÄ#èõz\¹~•«×opéÊU¶vvè]¸ÆN§ ñð8ŽðZA§í.¨Æ#ƒCŸì38ø˜ƒý§<¼ÿˆƒƒ=†£?è]¶vvxåµ7éoïÐj˜Éˆ8a¢§Œ'‰¦žY“Ã,Ž›CI•ìbðÏô»û§Pó´³Ä|_˜Ð³ûJD4º2o^J[Zq™~+ýO‘È¡ Þz¹°kõPQ5{Ñ |G:6Ž ‰‡û(_¡P~¤»ŒöóÙûÁö/Ó»ö6;¯~‹×~€hpŸp´Çdïc&û·<ù˜ñÞ¢á3äi­$ Ûå^¸ ðñ‚~à·‚ Àï´:]´§“dƒ gE@$9eþ-]¯pGÖè¥Òå­,Ê$Æ= ¡(´ö¹qý/Þ¼ÒŠáhÄáÁ‡ž>Ýå`w—½G»DÆîÎÎ6¯^ãÒåËt{}®]»JóðÞ#Ø}ü˜ý§O 8 1±ÐëmÓ¿°Ãµë¯ÒíoÑítñý‰Â!áÁ=FÆ$‰QóŽZfPRᩘþÞ ±œëEÉÉÝ¢tFVs]TÝõl•éÃI’!Ø‚'!Ù~xÆsÖÉsZ€þÆ¿Vا)W‹å¶Z;ìéÄðCbÂCì¤Íh´Ï£¾Ãþí?B‚έ­ëô¯¾I÷Ú—è_ùý7¿ vìÄÞÑÑà1ãƒ; ¾Ïáý÷hH§¿…ßnÓnµÐmŸv»:øI½@k &ŠHÔUH ‰¢dîÙÏÑû´ ½’YÒBúÚ‹MŒ™‘MÆX,…ïû\»q•7Þøz{Z]hoñÑwþŠ?þý?dÿñÞúhK·Ûãò•«(Ïã`ï€ñ$Ä÷Û\¼t+/só¥V€ßnÑò=âpL40Þ{Jh¢i6¤Rh?óû‹î²eXT©ßш‚{£´ñÜ}ŸJZ9†»èäƒ箜ç?i™ýO1ã’4ß“ ð«kä'µ0€O~0ÌïRæW …<.¼d–QÏóéíÜLîÑè)áÑcŽîßÙüíîeÚW^¥wåmzWߢwåº7ßæòßâèÓ?&>¸‹Ò‚§,JÅX‚±Äñݵ¦*KZ@9­±4W™/\$N¡K ÒÊ çy½‹ìì\B÷wÀ÷A½ó1ÆDtzm¶‚G´~€±­v‡W¿ø[[[´'VûÊbML419xÊaºò(ÚGi…ï·7ûƒ›I™Ôt©ç^ÛI”XÔÌŽBO¸…RÁê+¤'›ƒÐÎU÷]Ç'òz¸@- àÓ{ïö‰¼^Ç¥¦º±x xè$>ÞÅ ;}^0H#qÄäèã£{ì}ôghÏC=ú×Þäòk_¥Ûõ‘Î+Î_o Æ„¨(D¢š–”AL Ê‚‰& œÛqí©¾Ž\"LbACy>žïáé­VímôÎEh÷ 2‡ŒöÝå³ÏîòÙ'Ÿ°¿{€ÖÚïpùÚËlooÓÝÚ¦×ß¡´‚£,#¢£1Q4Nr Ä<ßóg¿µ}¶zÝÅK}~[óñ£“ÈÐ 4V@O |eĞș!—¹õ(gôgñ²4ËcÝžÓ,Z°¤]uBΚHºµ€R>Ê\‘Ž”=kPxÐjC ÒtRlŒ51q8d²ûcì˜Q·‡ºxA/h¡‚Ýê¡Ú=RW£µ1Žˆí±¹ì<ƒ‰Aû€v‘rJ3åP ŸÝçcpÜÌ+Æ¢º(?“Ä„ËĉóQˆ5#”X° ÝïÓõº.~·ƒnw ¿á„£û÷¹÷þ»Üûô3žîî2¡ƒ>ί~…¶ûh1(m ´FKLM0ƒC¢($g°¨$ŒP ¥t6˵±êоñJ—ÁÄòÞGøÚÍKpgwÂÑÄr©ëÑöU‘—­ÐùTÈL\¢œØ_èSúzÿ¯æ»Ï°L¨{=ÁÕ‚•ÄØÕ´aФ4g’¨S5Æd¿Vhñ¯“È`¢´ä„fâ9–£ü6A»ŸüB$Àªmi»Phk'twú´‚Õî‚ÖŒöžòÙðÙ'÷ypÿá$¢·½C»{‰ë/|•ÎÖãɉ#l´ØcB"v\ã„«o2³’Ÿ— ”E8ŽXÝokúÌp—/_Ùb»Ý哽ǃ˜­¶æB'Ÿf\øR<”W׌Ìê…=*°˜ ªÖE>õ0€’}µK” ñk Þñljúͤ+Y’rZÆÑTò’Î^.k’uèãáh„B¥ñý– juñ;¾¯Oã{­nx<æOþðŸðøÑCƃ ;—¯ÓߺÄËoþu¶·. qˆ5$|ŒXK˜ÖÄsæï9›GAoοž œ`¼/:àÅ–Ùjs}»Ë'OCF‘¥ãë Mgƒ5æû˜‘ý,¨È ì cÇtõ­Ž™>rÚ©žd Ü¶®ÍP%Χ=—ü^n|œïü$ÃS%„ < ¢f&,OˆÆŒÍ¢~»K«¿M»ÕÂ?šp8}Þxë[l]¼ˆ„&ã§D£=Ž|êÔ"Θ.P’ü€äkÖòý¬QûfÑV1z0àÞ°Å[/^âþaH‹]4hÎ; ò›ÄÖòx`NXÍw9Îz…éZÀ“\Ð-äT~¨¢’e±T ]W«b……©`kŒiê=öJ b ñ8& ¼w ÕÙâÅ—n°»w ð<Ç>’8¦|òÛ,Ä®·ùÓ?Ùuß_¾Ì“AÈ(™ÁËìÑùG/À8¶<šÒ¼„Mଉê2æâ0¼¹ªNˆËÐ>ØÐÓZX%cP FcTMâÝJƒQÚíyX;`üècÏGkÏÝ÷§†s£>û÷åÔ ¹91>»¿Ï^¾Ä¥žÏ0œ¸^§Ó|öÉ0½¢x:ŠGǽá%íKâŽÛ]¥ÁN¥& V™Ušk„ˆÅÓÉòZ™É^²CR$’´ÒNww¹+˃vÖƒJk˜$†C…ö|ü Ò³¨d–:3ÄYa3³£LÓ·5EbÏÞßôè(²<Õ7ëç†7·qOû´@ií¾MB”HRJÐËOJøv~—vÅ7ÂIDdbÚÊ+ÖÍÜø8#-É B’ AŽ›ú\# L:þÍ(_1ˆò)8é>4®t÷$®ï=="§Æêæo¢œ5\{Z—OžRbðŸÈO&´‚íÒºø'Óå9HÓ†¬×®œè^T~Å6€1ÂÑÄ2ÜP&_Ö&þgÉ X€VªnùF,à+—è¢H‘å¼ÉÜI=ÝòF(LóÙ“hD‚Q™ù~Ë1ÏÓL&ÆhzíbLýôŸ½¨L™°TÜmPÀ.°è½Êæ2€sé¥Ës›…J~Î'X~åE}Ê‚ ã_ç¨GÈ=/M½ Í÷gImñ²7®$ØÃ¥Î{(m¦}œ†ágZ0ý£!ý2,{_VyŸÒ¹ÝZáhbx”_¡§º÷Û-ïbµžÎî 8Àã8%ÁŽAið;m´Ò?]Ä#ùy¹KO€çÅcÃ;½^íú:ÖtÆW$Ò@à pö‘âì’÷H(¯1X6šÅw c>8€ÄµUSE qú¢×èõºcÑùŸUø¡”KÃÁ·ú_mc̺b¡¢R3`£”¢L>á$rZq'2t/9¥î·â4lj8мÊõ•Ö„ˆ Qt»m”R ó©ˆøË¦v*EàûŒ&!‡‡®ïl»8þZF™Ë6žÕ iè~)6!=V­´¬ís¶¯ÀFÀWÞ~»@y½~O=_×S4ÁYЕV\¸tƒ U>À,”[XSENÜŒ¬dé©kY%N@•y%&PÀÌXz W@³Ôô×p£+ºÜÌ•ê1NÄÊ=ƒ¹cƽ¨ýZ±l]¼ˆ|$vUtJó‘óƒÔÎe8‡LÆ!Ú÷\Y­ºozêïO"­MÅÿ† Ìcsv–îs‹Wà7›™(NÙçW‚c3€į˾‹µÚXñ6nLf¿ÛæÚK/`bãb¼=ÀT”Ô³7Âó<Æ“ˆÑpD¿×ÇÆ&c «bÅ-c–Îpª±”¡ŽÇír!ŸH/_qÀÇø]§ñF¬ÄJˆ¾ŒØKÛcý(¶¾lÚ‰µRLcúÛ}ŒŒ 1:Y~F' SØ4EXá“ñˆáÑ婌_¾ÞhТ’x Yµš&puß‹W \é¬ÙþIT€•Åÿ̶g6]4¡˜áÁw‡áw{¼öêËt·û„Qˆ‰âdfͼJ^º®-­€ƒýCïîóÚÍ«bŒ³"lvœyXÊ •ÁUPI—ûìSúý.§±I)sÇÚ& IDATÍZ‘úý³ñbTâ¹hÀõe.páFLøq›×3¦e@JÐeŒŠD_Ø/àðMå¶”(zí6XÅápˆ×ëÇ1÷?{H8óå¯~…›o¼F¬ÇÄqœ¬àsðè ‡Oܸy ?ð‰ŒÁÖ2ÆÜˆ%]rÜ{l£b4^Cÿµù¨ÌÇå×øºÌu]£gjU'ìÌÂp• !]ý“XZRG¡…¤Î€(M· Òåh4Á÷|z[=÷ø«?û6_ c^ÿò›¨Éwk }øÚ÷ñ·P‡5Ñ©à\à’Mì JÍV¿9Íک盽+è§\¬cå«Õ<®U½y@eÎÍKéw”RA‹Å«¥àf 1ˆ(zýJÃá`Hài¼N‡ÉdÂ;õP–׿òeˆa<ØçÓ;wéowhy#1ÎXßgcPnqOÄ$îÀS¸î3—)¹Þ™ÓËKÝåWXå5¨í‘¥+×ÕÇ1ººóR@þ8ÌK ðxu¾ä‚KÒ"´Û-' Ðî¶™Œ#Þù—ßgkk‡«o~O~øâزÕiÑò|¬=T``®€dó‚ÏÜ#|ΰ‰Û1÷Ò­î¨åIƒJøTm8i@™Q°Ì @´€õÐ\V´[ž×c0¡Ýj…!ùÿý9?Møð½èô:hOãû>fáª@›…« èþAMsÅtnÞ€T–-Öì8·˜ ëèqÀ"ã_Õ1/³];°|OÓí´Ž'€¡Õj™ˆïþ‹oƒµøZãyŠVK/©³y(Ä­ (šŠ åSÉh“}n¶»“BJ¾ÕØ–1›ü¥íLnÿ¢ç×R*‚Ó¬ˆšZÚƒÀ§#ÂÑxŒB”ïª{šØº|¥”[yç4Ç6÷g@ êº]ͦp†¼æ(+ݾÎT2€woݲ_yûí”Ècæ ;݆# ×&µ¸ï§¼­“,À'Š<"1. X´´¦ãˉÓMO60…UŠiU`Ó$•![:mídz(8‹“,`³Æc“[§õ:¬"d?ã’c)òÄŸº5à©xù«@)ŒÖt[ÆX¬ž¸á)ð|ƒ2§' ’5 ëxN$qž">/k¬ÊâÌvV%H½’´ñ™÷(Ðæ¬£·O)Úí£ñØÍ¾Já+…ç)ŒrŠcHÔŽdJjÒK!ÙÕš!d k±àtqZ=ÇÅ*FÀôIèÜ>¡h ÈÇ h¥”Rêtmy<­ð´vß´ï£s1§3ˆ8w¥#ÉŠI (BŽ ±èý’Üç™@VAi‹³r¾{ë–øÊÛoÃŒØSý?Oø$ÇZÉ÷ÔpnÐòFQJÑò<¢ªÂ!µBeŒ©¥»Q*±Æº™Vîï '¡¥W®lp>"Ë·XŠïáêðè³”ó|O¡cíâ“{ E@óc±.ؤ†®föÏcÊ +?÷lù0Ïöw¬Är’Ì«“¤Ÿ13)ñÇ$!î§g³V å{®4·œÑ˜ÄbDá‹e1(Ò’ f¨RÌÖ. ~JH'öWŽ%$®Át3ë Ì Ó¾}­@)%õdâV*Fc°g"y OYÀ ”3];½Q2˜ÆÄ'Ÿ'\dúe™°ÎÍßPìî)ë—·¹ïéŸd)Pµdž&}ЧP¸ iHªõ“ouD¼=˜ÙIN\<—X³ÐÚ²±GPî…XçZu¾Çf%ê@È,XÈÇ©é>«”êh­zr.$€N}ÊMt~¥§†@Dµx.!vsš£Qšõ" –`ãA§óRljal4 $€R W¯Î;ÿ,!Y¶\Ôtf›F6(`S‚Q¿ís0©ÉÝ[2Æ:û6~Ê*81(‘bfnÂÔ>ày ë£F§ |~!³D¦iME°J¬S`0Ž@y'¢2î3š6¹4X–ÅÆ¸  Xk*m#9‹Pàsßb’?\:°•F ÈÁ¦9“ˆ üŒD¡Öµù­ð°6ÉÎ*hd$48(…UJEžVÚÓ„¶‘€$ÉE)|ã±6ÍhnÑVmRdÏE[ 'ÌÁØ<%žµýwc@â"L™€´Ö: ´ö|-a£ç:.8-"žÙеRÇfûÞìPOVjY<õ”²žRVk‘g%r«n¤Æ?+6ÕÎ~8ØÀ-ÙÄ]}V {Ul”¤êÀÏþÜϹãqÜöÄøá9üígƒTîOiè¿5Ü—Eý奯3•X¥ôk-¨EHn¦ ÐÊJ#ÝN¡ñ¬‹þ›ª ÈÊ‹';µZ ¶jºÈ¹xêuªluº¶¥Æb=mÎÇÏ=P‚X0^S tÒE”¦Áâ{]ÅkæÆrF†õä­×ʲ ]46€‚F3 QÒÄä Šµu€ið©dþJîñ²ËœÞ›;»Ò0´öéÐŒFwž„‡¡ ÿÇgóW¬•€eÑ(15¯ºûÌ@Àú_tbPnãæöÌÁšMgÒɪ596ˆ/&ó{7|8 m˜9{8¨c„51€dnö’yÍÓJ5@)”ñmÝ+i“¬¤†äà<%kÕ¬Ú“=°Éû¾:½Æ"{#>:Š?y=~2ˆ2MîX …L«kmmp¤SÔ/à¹T€¸yô;­(Tâ P ˜ƒJ£7ˆRQÿ”$‚IledÂG‡ñá'OÃÇO†ñQríxˆ«Ÿ‘ÖÓlŸÖÐjeJ'_›×{§Œª¤Hª4wh#™Ù:•ÝOüIî³~+ìLôd`Ž~ühò`w6Þ=fU´º…ŠCývã¬Ù8+.Ò¨3xI.@vÀ³Óù‚£û™¡ŽÏ EJDþšüã9úl/|úé^´›Jõ÷-À x@?9æU 0·çnýOóÔ1îšâ@©$âÚ€nŒ€3(‚5}ɱ4"@"v¾4ø±Î-ñê×àqÝÄÑãA|ôÙ^”¼<À‰õm˜×ßeY‘ÜòñýÁ­ß©‡ø¡~ ãòÝ”jÜ€ …—DžnIòg ’”L?Õæ ÿÆ…€ûQ¶Ëµp02fwïíG{>ž<ÀioHVÁÆxüø¢ÉoŽü¯·~ççþ·5‡½5EÅ.[7Ñn)¦Â-–ôo,yÌ/¾BÛ²ýÌêÓ©¼sÿhòNÒÄË|_6ÊêDÀïÝú?÷ûÇò±Q§ €¬[þB7À<²ï·H*ÿ7L …Èò’í+—MJÚgnùpbíî0?<Œn?ž<Fö1N‡ï33Øõ‹d®³&ÄÍü¿÷Á)?ÔÌpv[¢šHÀ‰05þ^¼û³„Ù½¡PhcµCkŸãñƒƒøàΓÉÃah?ÅÕ´L­òYÿû‰¹©”OŠößýàwþ/Nz­ã¢fh¦¶f‘åi´kCÿEX)1æóF)æ×~G"{Ã8|tÞz0þtÚ;É¡€ÙJV½5†½ößøÑïþü¥-7ˆ:³³Igº2Ðù‚àÜ€’1r5<² Ó’©‰”tܺ€alåÁÞ$|yËÐÊîÿþ/Ÿü9Î:¯8–þ¾ o~ùÌÿ?þ‡§KüP˜&»7Û4o÷ ó€ÐØò±Øc–ÇwÿÅ÷¿÷½ßÿ½?Þþ9¼Ö o}ñæe|­E$ÑßOã>¯<îÛ?þ‡¿ðÕ9’E¨‰<ÌtïrÝ ÅLÈÚäó”I""a>ß½sçÎþÖoþæekû­ßþT|-ÙdÀÓ¹ßR¹1ÅíÿÑÙ?ÔÄ4Ÿ x‹A”R¶yÉH$I,M@€L£xTžàÿä·~ó7³–òì*ÕÅÎpöoát·?üGëL‰j“<’Ð6¥…(%M.À JHn &ùîâÜ›{”Â&tEáÑx<þîíÛ·ÿè¿ú­ßú¿“Ã:÷YùPàT Þå:n÷jÑÇðÑÿü·j‹î;ja‘ AÚ AµPcš\€¢Í,QCÞõ2©u*»„ŸDÀ?»ýñÜ?Ô%„ Ä£ÕÒ©‚«šPà. »& ³x«µ–¿z~ æ"2Ý{ìh•¶ÙœÝ*~ïö?þÅS‰î;jaÆŠüÿí}{Œ\çußïœï>ffß\R©‡%J²dWRÙMd·IÝ4HÄmZ´@"Fóhb§¶›A´@ÿ(Š¢±Û¦…•"@ÖEâ$@Q¤udGŠ‘íè‰eJ$E‘_ûœÝ™¹wî÷súÇwïìì’âCâR|ý¤åîÞKÎÜ™¹çwÎ÷;oju «'`ß$€ˆ(H5SmäF5þ³+ü4þ´±?}»{ym„úU…g=ÿ¥?ì…ŸoóQÐ^ÿ­«Ïøm"€»ôVð"c0J6(EÉf“{ã’Â(Ãe:Ú(„n$b½HTú0‚ŒöJPø @”KëròËñÞœ}¿móØð;W«ñÛDÉB HöÌ3SóVÕÅ98 lîϺ*ò3WÝ€q& ]×Ú²é¡ô@5’ŸIBÍ ¦ñ{q`"™’¢KºKØl”Nx«^ s^óEü‹x¨.€ÏûüG®xuߥ`[àH+¾=³6c RUbˆˆ Žšu/%¸Øæ?®#lž2ƒ­Û¦®ˆvO£<~ÓÔcfõοÁLd4ÔŒ b f0’ÕÓÓ.í ÚZ‰3Îçy¤w|ǺúŸ}ý·?zU?°]@ç!°™*k ³¡x˜ÃÃ9†¹HF&É &…MŸÏ¹&¼\³ˆ•€Ó ¸¶¿öòã¯@ 0‰ûF'˜I óë_±Xe¨(D4¶‹fNÁêRRo;‘dc_›^ÌË:Çc]àÙNòpí_užøço½¸ |±-&ÀíP 3ýA)O:õA[ؘÓhìŽ@$`¢š\üÙÿ^# Ÿ•Ëm\kÆcgi°kt&5-£m‹âÈØÌC˜ñˆš½a^ f"ˆÌ(¥õ¬Yè›Qˆ”±ihÚE¥Gó–F ðVæKçüõü‚s°£“_ù…_ê«Û£L  §LæV|óùõ_û‘Nÿ…𞤠`8gpäç@@®#sõR£ ÃmΙŒžûZH7’¥Ñà5†À# àjµÿºˆ¾ÎWl:nZÏï…÷ÑðUÇ 0  º¢ÕøÝªTá2ÎR¨kã‰owÿÀÀE=/U6ÖŠïìe\Ô™·s ™›ú“_üå·ñ/ßUlÏ<€ºârúõ`ÕÝ¥/«ÖàÔéòÍ/¥øÛ~ßôO휟ü›í,|ÞÚ*! ÌÌr v Žˆà:ªœ÷ƒ#B¤’˜e Ó¶¼²ËHaˆ„f„«sg jÜìXöÆ6Šib¨ Za0/1V7ª  Qô j……ÖŸ@ƒ!IS¤¹+*qÏ­y÷ +Åkû­|×Ô©Á Ø€«l>Ý Fä:úe; áÛS_ý§ÿ¦¹®—_yåš){ÝÎ 6Û/íp5Äv!°|ë¹å/“ë~¥•¥ó{wå÷ì»c⇧'èo0t ¡šQSHwËq.#MÁI$€PGD0rpQlŠõ†c+Qõ¸­« ¸Æšja vU€áٯ ’©H=ÅÐ$z}={ª‘©Œ YÏ‹ t¨0h$t"$Y´èÓä…Å>}çÕ£kϯöÃ)Š .\af©™%D$D”a$ \Ü`|Ý?zŸ/3Hª'§¾öÉÏ_ö¾BØÖ‰@Ê„7׺{碯üŒN·²0¬’a:¤^?„ÕÃÇý‰#ÇÖŸá‹33é®îž~t׬ûQç’]9…ÛÌ„E~¨ ÇHÒ$F— «5Ë2Ĉ¡HqîB+qƒHmt™WT¬Ãú­Ìc0p­È‹êÈ‹ûóóÖô-Œ  õ©ŽÁ{€ç8Kj-{Á©BøéÅÿÌÁ×Ö_Ð'Ó¾°ózÇÃÀl,x£ŽÁ2"JGuåõeŽG&Ûòý2døäÔŸ~êó®â˜ó|Øö‘` ³ ¹°µ^Ërô5×)ÊKréÀkHS¥ÔHó•îðôS¹|„?b²‰ß;÷ÈÎ9z´Ð­ì2éø*ÀD@ уË@VG¦#G0R3\³tdÞÌc8«Kl[Aõ± NÈ bWÌøGÏÃ×û4éÖ ®Ñã+ÁÔÇ(@uH1‚™¯ žj?@EÁ¤ ç·Û½^ Ã뽂žyùHï›Å@—-îŒ3`³"@†@ꕬbG–ªH!bR¶$14ûÊmx~`cüvý*.r90¶|¹ t Pü¯©'>ý3þk)ôop%f‚À`&+—²c"ÑA' îôZåv˜KÓiçÓÄah©§2¥Àn½pp垀arßSûn™s?Ði»;g:É#Ib{Í”½p œ“Úó˜L u f‚ÔY…ñ#uê1¦à¸¶ y›Q\šÔWoHÁh À¶sñÆs¨!Œ2Ó [b¨ÜTä5»‰‰"ž)DâªvŒ´•€¹Õ š|oeµÜ¿Ú×—^=¶ô"ˆÖaV4`Pé† TLΧÄB2”° º23E‰‘R²xWfõ•lnÿ ¨7¼ÐË+·Úzâ p±øÅ©o}îñæ|Gö.ãŠ@r ¥º/h­/<_êñe šÝ2›TUpœåÎU!MZ®JT‘±i~äøê©ÃÇø9uÚ9Ï컽ýðÜtëžÙéägr~°–Q7`n„DÇÑØ™AäALufÁyßHJ¸˜mÐm'Àõ@7P¿Ü8« Ï´6`ÀÌCu ®ž¹åz@ bˆa=IïT ¡®ÚSAš8ä­ ê’“ý /96xje½8¸Ø­Nt`jb+LB¥ÇeH]©§SëPKn¬¬ê“éùD6Þ (ïOE4ú­óûÄaž&pžH –m´î9Ï›vžsf«ncüÕø©kÑûW˜6ÊbÝbh`ÃÄÕÅõ[h®\¥=­„Š)'E›šÂܺ2ÀÒr(­‡×ƒú6|i~6Ý»{Wûž;÷L|d¦û*$ÞW`ˆ9zwŽuÌÄ"×KÔÆ…8 Œ[£ä˽ˆ¬ fÔ |yH ¾¤øHѹë¨Ö )»53“ éÆq­«nÌ7¥¹ˆ!ÔY]çi'…Ñı…®~õð¡Þ·—ºá8ÁêÃ0`£RÙ*2 A\9Eð$ŠÞ@V…m ¥Þ~[°~Ù6£6I0&-£[ïÇ€x 6"qR_ œvŽŸ.ð·žXKÏ<ÿû;±õ̵jüÀ»Iª 4òs`¾¨9Ázl‘Ú·™¸Ù2rÞÁ'H È ÈVª“ +ÕËû_é>ADS³SÉž<´ã'çrûa&™¯ª  Â\r "P8¶8¨£Y87VªŒM Ý;#ƒ od—=«LíÒÞÃåCƒi{oÂûq±Î@FU‰:ja#ï5ªùì ¦ÑÓwr_ ?}ôLø“W^[Û/F]˜õÔ‡Q Bá˜+åàMƒ§ˆK}í/ÀÞDÐÝEßjÙ±(.Õ6¿’}|&Ñ[š{²B4ìñHcßãÏÛmÓ-ç™ÆKíð·­e ÏÿÆÄþÇŽa‹àw-?ð®Àf4Þ«i‘µ¡76À¤uz9`wÊ¥ÎTÊDÄ¥©¤¢YÀ9s•¨µºîO<þÍ“è1¦èûælÏŽôGr§ï‘a™™BjÇ1Õè"‹‚¢8ÇY&Ü0ŠFÕˆ—tc@tÎo)Nžõþœ%LâÞKM'ÝF^$— ðcàà%ÀTcݽz@ .u€(ÏU½Ñ÷îÏ~ýÔ™•×=<ÐgB©ÌCS:•ª!œTI¢óY_[ …h±ÍMÃÖ{晩Z­¿œÿ•Zïõ@“ïiîËÆÓ7Ö¿gˆQc#;àqÁáÛ`³¥tåàoNììÍ-×rÍ?p•ÀYóº$Qo†™œ9|†f&&B1ÕòÈÚT¸6;'𚪢 X‡˜Zßyvù c|ÙÌæî¿{ú¡»w»¿51‘ïKTfLCÄC…3ñ˜êYƵNÀq]ªL1 iõ²Â›š¶Þ×ãóÆOmº @]wþ2·xF)æÙÉPÿ« kšZû±ãXg],Æ!˜Æ"œà+¨x€‰K¦”ÜrUÑ‘¾ð û_XûjQê2 =õ TB¥$P gž”¼©†ªÐP™·¼êéb?±É»v*Àœ –;/5ÃÑ9v( î¼÷\$ÐDMtDÏÎáVð’#Óc;žü•O#F!͵¸>Œ¸Ú à-`uŠÔéÒômðTÎò¤gÒ6»ÄåO¶¦&³¦P´Á4ñ½×Ö}ï¾²©Ý;:wî»=ÿÐÜlëNncèl0AU–à$«;ÙHy£I©öþ)kM ¡(0ZíáÆ3 ¨…þøc¡êÚx%4[„ްÉXbºPëRAS™@FÂÁT@°:m7füV“Cý³ˆ@C‘C’%HòŽ–éöëý^ÜpíÏÍÐ'¢>`6Æ(Ì´8¤L¤¢¥ézPUßYRœn³ýëŸĺ ËøŸß-q¹P¬-5Ðì½ãkþf9ÐÇæ]|Ι"lªGm¤Æø?Yؤ _/Æ\£°õÈÇþîøò¿¨e1ë[*ípQI’0'½ XW  ¢Š©“‹ÅÉ“KÅKL6‘enþ;Ûß¿c:½of&¹?cÜÄCÊ®5ƒ&«@Dpì¢pE.ö-ŒÈÁÅÎUf(Ó¨Åw³¨h‘0 Qp«=z“™+]«Uû:š¨½·Úf#73°D|}¾nÆ‘:" FÖJ€¬Õ-¼Û¿Ôõß;½äŸ=±´ö }Rî\0Qa†¡™Tpì‘ ˜²ÞM,×¹™¾ —ƒýÜ?~Ð~ë¿=Gÿäã÷[kòŠí¤Õa# Žk–çNÖâ¿ÿ~>XxeþÏ>õkØò_¸`~ö£k§ÓÁý×oX7É©[NøÉ™@ÁÒ!1Öɲ$˜®$l©1µL­ª¿xx}¿uLÞ¹;¿gïîöC³Ùû§3û«„°ª—$ ωs Žúãèù…\ëM]B\pìm ¸&'çb(ÚèiPÄâ%3ˆ zz“Z$óÆ¿êÝs46ᨅ*b1N+ƒpòFwÝž9xdðÝåny¨_Ê2}ƒ 8XÉÐJz!«´©ÈŽvÚÁZàS?{¯%Y†ÕÅEÀg~ñQ[_ZÙöÏóàáWÃý÷Ü7. 6h"ƒo‘"ÔÚêGõç šƒêÿtþëÿì?â/ð¹X\wÐàÇÿáXÞj9¿ýÒ·áv¯Pšö•G^••ÏS—ZßÔeH–‘ZJlùñ3ÃÇN—ÏÙD'Kfïº}â}·îì<2ÕÒ%lÓ•¯\ðMý>Á9À1C™Ác©ÄFМ88Ù™Â%±„9H,›5eË(M·ÑM7FÒDÁÇ››¨ \–Z겪÷ÚéU{üõƒý×ûr@ÏÌú *(ØP$P¯”x˜z•’úJË^–ŒÐæž&]‡_ú¥{-mçX?³ü®~–GO¾îÚsßÛJnvö†³mœ"­žœÿÆgã¿!pÝÀ8>ùw>`­vGÔ<Ê~‰‰¹üû/<ëóvž„ÊT[dd‰°9†¤à$au©Yh—•¶^>Ü=üÒaý3‚ûâι|ï{ïšük;:öá„í3™ª` ¸$.\Ýø"õÒ€œB$–,« †!T"@6<|ˆ9ù(öÉh /5@­ž¡@€KK¸d½Ú£oøÇŸê„¢§f=ŽëùR‹ÄѼ,¸OV&+C]¯rís?÷Óû¬3=vŒõåî»ý±mÂÁC¯†ûï½ïRS„›`o%µtøÇóßüìïb,ʸž=ƒ‚Î…_ýùï·A¿ç?ÿ‡ËœúЦ[*ê@æ´0Ï.M„,5ÑÔ9¥Ü¢ ­ÅÕòÍÅç†/øRêxæÁfëÐ;m÷¦°[ÕœˆGeu# D.q£¨ –­4 âf@¦LbªU…Xá’Ì unE‹k%?ýêñâÉîZÿ4z£O†’ÕæÂÐTƒÂ¼xO¢yÖ“Òg®·tÏÜ?õwX{ªƒ¬ÕB÷Ìö‡ôï/¿òJxß{ß{¡á¨lØÆÌ|×T–¾E9çªûØü·?÷·çª¯nܰÐàW?¶S[9kü—ß{>ý‰¿nÿé?<Êْ٦ª ¨Ó<ï'’¦4%ÕÔ`9ƒK![PIDAT[>„γ/-ƒÒÿcêžÛ'Þ¿{.ydfºó@ÆáN¨t¼ &Œ´ž~ÄœÄØU~8D0©ûlj5ßBˆÅ2Yš Ɇê^Tt|¥§Ï8Ò{ †u½ØXCÈ 3BQ1à…ÄKð2,¡”ô4[‡.Í&Öª†øÄÝkiž¢=9å3 ïöGpI8 Œ§8G5›š++Ñ,aÚš$ÓÀ¾ÿØüw>÷8®c¥ÿ|¸á `¿ð±‡ >þñ}ö…/=­ÿò?hÿã±g¥˜Pµ<:¡¬Ò„sƒ ©&”,7hn†Ö‘ãý7Ž·o™ajç\kï®Y~ÿ­·vžÌq_æÂñZ ÈÅÔ”S_ DC‚¤IÓ¥®ß¯Ü‹Kkrhu]=Õ?Ã:õ Ö7¢’ŠJ؆,QàT¼ knͦ‚Ù„õŠ¿ò÷s({ÅÆÆ{×(㬉`kŠpX…láéßîýÈCGO­UûöLµ~èÞÙöw­@¦Ki÷ÐoÎîÿí×ÏõØ7 nÀ[à3ÿèÃ?ó÷﷼ݲ_ÿwOÛïÈÑË j÷¦Éu†UÓ’ΈƒZ¦–²£ÜÌÚ «å‰…zùÀÑÁÿkenîö[²öÜÒþÀÜ”{8eÙËqËÅ©8 kq}ÈOŸXò/.®†WÏ,÷èèPP@u¨pCq¨’>E!} ×[ªù@§WJë;[ã¿þî·Îô†ƒ axùrôW!¶¦@h½ñµSaúžÿþÜGÞ7ÿW~ôÁ]“ÞX[íõúOízê_üglD×tGß;ÁuE¿ÿ‡ÇA­.Êbóå"Ö¦r, ;ð­8ž‡`wÁàÉ¿ÄÒÒ4vç†bªÄñÆr¢Ü2»ù±¬ÍW ?‡½© ¼µ‡®‡µ¬²×Öéý÷fr¬ 2èÍì`žN0TÍÃxN)±ŒÉ23´ËÊÚ‡ŽG½QnÝí ¥ÇÚУð¿÷ ggqfiïk%8½÷4B¹èÈ.ì¾­p´D?›Ã€×1½p²ÓÂl^­9TwìD§ÕÃZ·ÄÍbn¦Á±€áô$zÝä…Ãé6ãî\°ÐK0µo×ý¼·,ñ®!@2yà‹Û<þ;OÆsmí븲ïRq]ÀvÂQ3“°î+{þÌ}QÖ b}cii:Ë;‡¡ÂLÎɰíª\¢–>%$™ÅrÕ °Ì€252@A&jð¤2QH+&©ÈØçHB‘xáÕJ*VÎú6#¹–dð•£´2$£^w¼›æ5„-$Р!sõ ïõÇq“ޘݡƎ@ +‡µ zbxnGX>³ÆwÍx^Ÿ›¬’Ò8aŸ8£~ÂŽ+³ˆH‰‰U$Iˆ,ÉJ)…¶†bÝ^K–Ó®íõ¹ =!!\," U,6fJ/|á×)Î! ^þ\¸á=ƒ›ð6±µ•uÔ‡¢Ö¼h&A‰ GO È!øNÎnf¦CäS.ÒN j î28rÏ*o6XhËvì0ãå‚<çVQ½Gf3yìyoâ-#sá¦çÃM¸ÜÐä¡+QkAÍÉš½¹P­1õsgàkXŸ;ƒMØãÌTr Íd"5£z¾é¶µ¾N0îÍÏG7º×ÇÍm»oâ&n`ÜHzÑMÜÄMlÁM¸‰›¸ñÿ~[q†ì.áIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/link.png000066400000000000000000000052061217176075400242610ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ uýkÓ IDATxÚíšË×u‡¿{o=ú=or<Ç)Š’èØM mÁPÞ œÞÚûìòä/È2û,ƒ0²H-'l$QdÓ¶$Kaô HÓCΛóèî鮪{ï9YT5àu . Ð@¡ºªÏwÏýWUåó|X>çÇ À À À À À À À À À À À À À À À À À À À À À À À À À À À À ÀçáHþúï~ò·—×–._^]ì:kÝxTÞ‡`­ÁYc²Ì‘&¢(XÆ€bƒªÖç䡯€50:.•4ò$ï¶Òl\TåoŸ<=Ú~züaååÇó—ß}cªV:ß^ê6¯-´óVêœ+SW„ Á°g` ¢ Z›=1UøÄüú²­ 鸪ä©Ëš$Ëœõsf¿¨Â¢ò›©{Às—–¯­.v毬ÌÑHB–ˆˆRÈÓ„îS•‰s8Woc,Iš’fEY±±¹Ëö¦á¥Õ{/­³¾Ô©·ËYÝü´pL€gÐg{¾ JÅ¥–ܾz}•—–¹ye‰×ç›Ü{ð„ý#FýcZÍœ¼ÝÀY‡5J#Ëivhôïm±3ð».²{ôæ:äœ1&KœÍSçTS3uLV ªµû‡v]H)˜é»@LÂ’’8K·iŽ*Þzç7üÛü'?üÆZT4z(ª~m@s…æÕ—ø“ï}¿ú៲u8Dþá'¿ñ.;£MŠ*PV9ÀETQSŸç€¢*ˆƒªàÙØxÂûÿ÷{»O'Åa ñ´Pl‘Îwxþ+·øú7¿Å½z‡õõ‹ôV/òê+·ñ8ÞHSÆãcã¢b<öH¢Lò€óOÕXµþQ(Bäøèˆƒ½}dX€¦µø•Ø ò ô®\ãûþ]~ðýï°~yà üñ+_cey‘4MyÿþcòFÎ`8¦?‘§É³÷ˆÔQá¤ÂõŠDÂi¸ŠuµbÑIÛ0™äq–¤;ÇÂs×¹}çwîÜæÅ/®ðà8`ca>ãÅç.ñµ/ß oä¬,/àCd4*0Í!D$Öï<7"(¢„ x/xÀ˜”¹¹9VV–Ùlã‡wÍX¹|™?û‹ïðêÞáêõKìЕ<Þ; ½v“#/>‰‹0Æ`¡¨<ÎYÊÊcĨbÎÃà@Š2pr /^àù×þ6[ÇûÅïqáÊ:ßúÆ-¾ýÍÑ{CŽCŽ'¨*''FÊÒBåå9ƒ1ƒÁˆÊ’ÄQùð, r.” ÂhT°·ß§¬<7^¸†¯JN¶³ùÑ@Jkí ¬_]ci¹G#…§ÃÈÞá1ã¢"N *}­ú¢Šµ–ª “j³N¸|ˆÄgÙày¨MŠ*£¢¤¨*œs\¾²F#O¹ÿëwxû¿—ð.eum•¥•E\b)JèŸYù4M0ÖEˆUEYz 6\ 8­û‹á4L´gêbÔ(ªUxOðB–¥ôæ,+K ܼõe6·öÙ9>!ïu'‚V2< ¥'ˆ€*.ê'm1Ut"r§´†`,AT£ˆˆhŒç€@RWfuU"¢uæ&àÇ%Yžpóå?€V›?ÞàÑãªÊÓïé÷GøIú¬2éªL&Æ€<ë*Š¢âêÏz\€ª §ïYštYÖh5ò‰0ÕC ‘ˆÅ±ú…òN›…åE.\xL³‘Ójf°Æpú=«L½«•:Î×]bA!Fãc4'£‚²ò„}ˆ2õ\0ÙØ}º™eƒ+Yše &Hô"A°Æ˜4MIÓk Fë©u2SD ÆœéíèÙ6‡Q”$qišº¤(+Ý?è'ã­u0uÛ‡¿J]¶ï\ÒUpQu¬ZGAÍi¾â¬%qDT副'Á`̳!éÄ>àlž$.!VÓñḨî‰êîÔT>ü½ˆ™s‘\ÁŠŠWT&ó #"ˆÔ²ÄaŒ!2 gÔ[A?5#4*RÏš‚³I*âb”bG‘§¢|4mÿ'ö ¥ÙiãµIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/filesystem/vlink.png000066400000000000000000000130761217176075400244530ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ  ,5z_±-¾IDATxÚí›Û%×uÞkï]U眾L{f8ÃáU¤Ä;E‘”“E‰mÀ¯vÄ€½%/ùäÈKä!cÀ¹B Eq,’ºD²I‡B oâð2"‡=—ž¾žKUíµò°wÕ9=šéž¼%«QÀôô9U{¯Zë[ßúÖ*ùýòïþî  xöÔÚC§n[Y‰uÇ&˜˜péŸ( ‡ä“ôGãðC×»¥ïüÚ/y] ‡!HU#ñ—6··~µ±ùö´nþä»ÿô¿{³k‡Ó']O?x×ÉÓ_ºëÁyš0ëng¿¶Ï›¬î¿ÁfäºÏÚ­nþ° H¼kÕx÷B¹n°´?­ÿâ°K„ãÇ–VWGÕéî<Á³ÜÝý¿ãÿó#ªquozº׫‡}ÎnЏÝÂ{þ&ep»f6=Ôu£{m«—¢Zû7ÉMÛYÝ^šÌš½CCÀL13K!ŸÝç±z}<Ö­Ñ*„ ”ÿ̤…ýY´½ÉÌvLJ:S‡iÀæq{´¾9x5 ãÚˆSà ŒJaX ’³ÄMAó Ôü·ëï×*¨BáÒyÓØökcoÝxZ‡Étæ÷æ?ý":ø—ùB,_¼Cвvjøù/>àµÿýU§ÖF %E0…5]C1é-ibHþéM!Ý}染üª°;žaO~é4O}é 9hÌi«LjEͳ7miZE¼È F:9`€îÂNæùß<£pNx÷ã ¾÷ÒkÌf5'Ž-±º~.ÎøŸoœçí?cÖÌðÎ J†™¡ªHy§Ño”vŽ“9çp.}\UiŨ ¡,£ÒSÉ|ó»uËΤaZ+m„¢pˆOG$‡@®c" ´1=L2<æë´y¦°àÙGïäÙGïäß®ø÷?3›6 ƒ±:r¬¬T`BlË^&’ž}úÕÒä°lIÿ%)ŸG5–†žª,X=65Àî¤áêÎA¨Š@ðÙÀîXYÊé˜1âÉ›ïAMº†ÆÀ"”¾õäý8_y‡×ßù˜ÑfÁ'1(ŠÃPS‚ˆÏ®ŸC¬s7“ùb,…O5RVšqËþÞŒí ÛSV—L[£‚Cp.mZH Nû²#‰v¸ÞHªÙ–6¬ª\Ʋkš¦P1ƒ*Àݧ×ùƒÓëlïNø«7?`ggŒÖ-ÇÖ–YY]F0bqÙ-UÁ‰%`5Ÿ‘!¢˜)â„UWR‰qíÚW·¶øø®u.nMˆ®Ì0ê(ƒG\‹–΃Ùýfèb%{€Aª:s.…Bç¢QúXE£5a)£Ò _}ÚŒŸ¾ò6o¿wYÓ¢fïæ( 96ó}û› "FpÂ`4¢ ض\Üø”÷ßø9Û—>äò“ú)pŽÒQ³Ïh 'sÝõ“'ÙÁÒíÐùu^™Z‡ÚÇ¡ ¨ç ‰é“]zifš’ר¹ç4_¸ç4•w|üÉev÷ÆÈU£* ªªÌ÷HOÝe/PÉ PŒ ‚†@9®\ÙäÂù_òþë?¡¾ü.;_Š *'Ô-DËO›”aè{—áõµyÞËEDÀ‹Ë–Tĺò0!¸Éü)"Æ~™5p|Ï?óû5üð'¯sîÍ÷JN\É dÅ¥k‚÷Ž"ü`@ë<Ÿn\e{s“­‹çÙþô=êËà}IQV8ŸÂU5…£åÒ:æS³LŽA=+jJ[œ8‚ë ÌRÌ.’ïÁaÌ¢2i• ˕çîÓ'øæ3óæÛqùÊ5†Ã’•åŠ ms`.¡¬˜P%”^‰uË…>âãwß&^yö?ɘ¿F5%^Ý€º¿q ¬"”€%ÇÉýM¤­ËfjÙ°GFaèÔ xU|‡’¬Stdáó‚±ZV1ðî… ÿé¿üŒ?ú£ÿ ¡æä=k”¥c:§˜DÇU"XõŒéþ.[¼Ï·ïûéÎÃcP­ÁÖ6¸µ€Æ]ÑR¢Ö”=ÓæPAô("Dbi’“akF­‡Q´‚9韶X—¨ŒV“Õ—KÇê `iØ5xéÅ·ø³?û?|ùUØ¿ kX$6F3kÒ]Dð¾@1ÛmˆÍŒv¼E³s•Éå«™o`iÕ*„!H E9𥨷ˆª¢1=þè’/èbj? „˜ij¢ ­3Sb+¨sà¤/^œ£Š ÊÀÊ0°¼õÑ„ï}ï%þø_ü 0Ûoc¸ìië%ðëR`QFÔ{&ûûìoo¢[ŸÁÞfÊÌ~–—ay.€ ”ªóUË^1³‚fˆS¢)ùáçÔ}T¨ôbfZUš6b8—ÐËn`ÉÇVž¥AÉòRÅxùGoò§úßyñ/W€¼ÒƆɞ‚ ª–Œ)P÷¦¦ï¢ã]h¦*(FP­ ƒ.THVªÚª„²ÀÄ¥Ø\ŸÀó˵‡™v¹à(= ¡»šdM1M4Ä"hÊÙ.HDX¯*ÖW+Zà—‘ïÿðÇÿü_»àÖ`y(ÍtJŸéîtã}¨Ç  TC­A5‚r€wà<.Ì í L!= ÆDØâ‚m–@ÜTé²ÛÑDÈq èרÄ6"Ôb"š!Ѐ²p;6¤~öWïó¾ûñ_ÿø4¹p8†h‹íï/¬Œ9‡¶±M§/ ¬ÒÓw>Tøj€÷/‚óD˜TRÉ#,¥>©¾P4eñ Š]H$Šx¤0º4¨QQIœÀ™K‘%zYa)Êùá~Ä¿þgÿ 8Ÿ6_Œ 8¬maVÏ„®¡Û”¿¼ƒ¢€b6/Äã\ ðP8ïq]YW–øªB‚O”'¦SU‰½\ÆÃLú¬u4´9bÉ­\¶¢JªÙc4œ«KkK%lŒ9÷Ö‡¼òÆëÀ[I–¨N ~8W×dAaQÍVtP$Ìy˜5°7_Á`D"Rµ”ƒŠÁ`€8!šRT¡¬pÞ¡D¢Å¼Ñ9ŠZBËÜÅÄÝêAy)‹¡j8ǼBX]ªX]*xù¯?ä?~ÿgüâ½·Rܳ Õ¦>§¤Óo>§?Šʪg8ƒà`eV×¥nZ†jE ŽÖ”²l(Šç\¿ÉhŠæÊ/(`–¼BÍú¨;2²4õÉPQs©Ò²¹à‚ÃU-ðñ/ßçµ_æ“÷>†FY1ì*;—–„Š€ˆÇÔ`çÐröÁÇxâ«OóÀC÷1XðâÿšW_z•íƒáˆQ9bX ˜ï<Á¹Œšê–ޏ¹j2û¿¢Âôqn¹„4K”ÕrÝ[Ž¢ð4›3øäÃó\8÷—Àeà8¸a†änyfieeƒ kê&+y_~úq~ï;çŸ{”Õ ‚w¼ú¿Þ…éŒI]SéQQ1¨Zœ¼÷5‹5¹•ùæ³ "Gë ’&1A5YÔré*E(TÛ{Æg—6Ù¸¼‘7_ƒ?RÌͯ1‹{ªB‰8‡Í"lïÆÝ}…o¼ð5þöo?Ïs_þ÷Té~ßzî«\ݬùñ_žãÝóÃΘa5"„À`XÊ‚ÖM¤Çzšn9 hörF8Â:oëÚ‚"$ÖËX˜QžAYréÚ˜wÞÿŒ+[›ù)JJeâòæó#\*P°I “&Ýu¸Æ7~ë7ùÎ?ú»ï$·U©ÖÛ™ÁS'ÏPކ\¼ºE;k¨ëœP *|ˆf´؉‚XòàÌ ¢e P®cJ7Dº²^sqc1 ‰U%ºé½£({{;|ò«KloídîX,ÈÆ9Þ%$—¯ $ ¤vÆ ÊO>Å ¿õ-~çw¿É#_±Ý‚"$ ;ƒi4Ìç”’‘PœÃ{Ïd2eóê5ö÷Çû<™"ãBòˆÁ%ÖÄ”êXYã…ßù6ÿðÿî?S​Wv¸ðÙ6m­T¡ *;6âÉÇîãôéã, lníríÚÚF4ƒjÏW4FhÚª;˜ŽlŒ,F§¢*IŠî¬ÛUƒÖ•ËmD5æªÍçû¤J†Š àÑÍMϸó¡ùÚ Ïòí¿óÜ{¦DK;\Û™¤ H3vÇ¢EŽ[æäñUþÖS£Ñxõõw¸te‹ýÉŒé´fP…¢‰¾‹¥ÛÙs³(¢G¡…†\ÎQ gsà$KeŠ8GYIï¾ìBH©®BY!!à0´V ðµ¯?ÅßÿÎïñøÃwb6®ìpáÓk@jxÃOgŒ'SÚ6²²2â¡ûïb}m~òÊ›(0™Í6Î Ñ,c–ôzcW ¨%L8²5ÖÆtÁ’¢0kZ¦uCQ¬_e8ä/ùÄå‹!„@ ñ¡¤™LкféöSÜ{ï=<óÜ—yòá³ *ÏÅm¶wǨÎe%"ß+±9c2CMXU¬­.ñøC÷""œ¸mhÆ´Ž…O!¡1‹«.c°õ|&)#G4G;#Xî hL8iaÓižjPqûí묮¬¦’—2ñùj€+ B5 púÚ6q×£ð¿ýO<ý'V—7Ç\¸¸…™R–—kûôäDça2k˜L#uÓ0î9{еc+¹Tfu‹™`q®Š*†:A{"еäÁëzƒfDU\L•a“é X­pï§8¶ºžè/$B/+‚€K<4â‹?À·Ÿ†;ÎÜÎÕkc¶¶ÇhL=,K1=aÊ•‚šbÖ2ž­Fœ8V—–˜Õ ³¦3š¦Iù>g]—¯“€ñÖ¨`8(Ìæ\Z¤¿ˆÓIª±¶vœ³§×9±~Âih§ /Žª¬’2 †C«Ë|ñÁûxæ±3>þtƒºn2~$¦©™{&¡Õ0•\y&™kÖ6Lë–2¤*Ñ‹PzO#mÛfª.}ÛÞr/1y•äªð™.c&*Ü)„ =µ¬·m¤žÕ ‘á°äÌý÷qÿÓOQ¬„ý=|Û21qÔmduý8>ôgï8MUMÙŸÖ̚ث]CÃ4¥·˜΄ *½ðÙÆHÓ¶415¥¿¾ä·œ Ì’JÜU‰·¤ ÷  ãÆuýÒŒ Š´J=Q%g¿p/O}ëYt6åƒ×ÏamK( ⤦UåÔ©<öМ¸mñ$²?ž¦øí‹«nšÓ/ª·þé™CPbŒÄ³—vB‡ô©;fö)–ä0nUénÔ1Íé/¢´Q{”6Rn{g¦UΞ9É ÏÍO>áƒ÷Î3i•j2¡‘¢°¾¾ÆgÖ- ˜Ö ³ºÉ˜’€ê€Ž¥‹¥«õ‘šôƒŠ)¿Ógv³ùp`o u©$6³[êÜB1ÕäŽYÿó¦:akgÉdƙӧ8þă¼ùæ#üôÜÛLwvO&´Q-/±ººÌñµ%BpLg5uÝd¡Ò2‰:X5Ó“6ë ëÚô}zëR·u˜Ën¥ãZc] ¤.Ф,`1i:b¨IîÚ’ÛQ‘¨Æd:eiiÄÓO>ÂîxÊ+¯¾Á;ïžÇ&3êA‹sŽá`@ðž[¢Æ9E5›Oe°úµI•.1äPéjÛ‹c÷{jçgTöêúÖ*™Ai’µºTeI–lùV•­=bŒ<øÀÝœ:¹N ._Ýáj{$-"FÉ"¥öOß5ÒÅ~9‹Ì||ª3‚-†I¯ù÷)?ëš;Dé‘ ØY´/ '.Q˼6'ó4årM0›Õ`ÆzQpò¶Užûú„"ðêëoqáÓ ÆÓš‹›œ:yœõµ¼óé»ÖM„ܬV›{ƒ“¹Yr7qÒOtžD?f“1#§sn¡)»ö²ˆàÅã²^îœÍg‘|ž^j[%¶3ʰÇêʈG¼—;ÏžæØ±U~üó× !påÚ6»»ûààÅa’ŒxØüswÇÅé4gä&n^kLNß֔ΠÝnÓ”e3@o§ž? Î9œ8ÒÏ<“XoqâR¨ÆtÖ n²8–F%_~ô>–FÛÛã~Jk<™‚iê ÷]ÈëœàÀT¥Í«ØlƒS,ImR™±»~tGˆ½¨Ë‘Œ0\ŸÅ%xç â“gDÒß³—`‰ ììM˜5‰ Ýuf»Î¬sqã—.o3”Œ§S|þ®,8¥ÜðË —õ*Mßœ•…”'€wªôëjs/(öÒä‘ÝaT„Ö‰¨÷ÎÞS„@¹¥ËÕsù¹Cjß&?ÆHÛù˜­ä.3g]Ÿ d!¿ÛœÍ.Rpýý­ÀnòJÊŒ óš¾ëV4@WAjg€BpÒ4q£^Qã >?>?>?>?>?>?>?>?npüƒˆYª— UIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/gnome-run.png000066400000000000000000000047011217176075400230460ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ 9®ðP± NIDATXÃÅV{pTÕÿ{îÝ»›ÍfóÎn^dÃ+·0  ¦>!Šã£­¢Î”):Z”ªX™–)âTТ鍵 Êc#F4BHP0M²›l²¯d³I6»{w÷ÞÝÓ?ÜÄ4ÄŽN¿™oîs¾{~¿óïûÝüŸLX³¦!# æ4å™0#ÏÔÖÔtôîúú¥oõõZ*-½p Y;wî¶ÿdŒn_ÅΜé`Vk/Û»ï}ùÄÉeï¾÷e«µ—9ÓÁn_Å~L<~ú@¾)Ÿ%''“ôtnøù¼,+**¡(0öÍüI€›>0#oFG{{›L)Å[o¿)Ýÿà}Á·Þ~S¢”¢½½Mž‘7£ã'%ÐÔÔ´6#Ã((Š‚C‡iB’|ݡÇ4Š¢ #Ã(455­›[Z:£¤²ú¯U ÷WÔ,fÅåå·ýÇ164Ð’ò«Ëÿ'õõõo¸\™çy¬\±R5BãÊ+%žçár9äk¯­}U¥R÷ÞûË{Øñêöì-›Ÿ†J¥~lê]}Ö‚ÈŸ®Z´ØUTY¹ô¥äñ¢}}½, 2E‘™$ILQd Y__/{|ã†hM]]Ä3âa6ûs:¬¦nIdb3ó**ê–üld­m§Ø’å+XIeÕ W\„f‹™x<´w´+ƒ‘8V^VÎ{<˜-fÀcî1§(Ñ0´q:,­¯ãEV(¥¡H$¢ú݆G1<<Œœìl<ü›_ã™-[ˈ̈‚õNèÀ?wïþˆ§ü¯Ru™ÇÁç“Ö»†G·=öÈCê¹sfC¯×C𔇔àt9 º](ÌŸ…õüN÷`ÞÙÖÖ¾+"0Õæ—UU%èã[o½éFìÝ¿Ÿ)J¤ 3_üó6nÞܹp»Ñ?`…,‡!+2´Z-ÒS3 ×ëa³ÛÐÓcÁÖç^èl?Ù2ûŠ30Õ*kõ?õäÆì%µµÂÁ?ÄÒºZ F´žjÏïÇq1'“ï¢(¢ ¿ëÖ?ÂFGG®ùâôéV(..Öž;wÎÿ½JJjŠUZîlãá0ì‚ÝaG¢. y&>=v¡ph ø“ày9Y¹ðùüx`ÝCá(˜“çøÌp8Ä+ÑHÝù¶¶c@/EÀdÊò2‚EMÇ>Ë«ª¬OyÌ™=Í-Ç %Pž‚§µJʪl›ÿ°õÈþÝ»`sôƒã8*íg΢ñãOX0$]ËÑ>=ùi䲊˪j8ЧÔjͲ´Ô ‡ ªTå08ŽƒZTcÈí‰0iò#õz‚ ‚ À@åx|rìs8¬šîîîÐe•pr-¼aõ­¨]¼”ã … EРŽã DÜuÇí8Þrêõù¥!Üsç$?8B@8/@Vd„CáÈtðËÖÏSgeyâµqp :1::‚ä¤Pž‚ò£c\…ç·m+JKÓÒ“?{þÙ-úë—]ç í›8J!¨T‚‘¹’ŠŠ›¦ã\ª Hjšaž^Ÿ°`AI ‚Á¬ýý˜=s6¼>ïdÏïÃÌÂY¸mÕjÜs×HMIÅ€ÓŠ`(BDQ kŸ%óç‘.³eMbRêB­Fý®Çã‰^JˆRXZ:K¯Ñ^xŒ0I+Â+yžÏÈH‡Óe&Eg¢0 ! äÛ%5ê8¸‡Ü8yâ$²²siÌÂÆ§7cthdõù³m{02å'”aQO¾)&“éóÜT}õÕ/Yz-tÿ>J„g^{ùE¢KÐÁívÅz}¿Ý(Šðû8|è#Ì3:þ@›·üɺ¥%@@„N¿ÿµ(-_€ $e]ýò_ˆ*>¥fq WTT„ί¿®w¸Üϰ'© Àƒ!<Ï„LV;ÇQ¨DQ g›žÞ‚–Ö6s[{G¢¨V“÷öìà˽~xÐuÀx`Såçæ3½>ÌBñܼ/àCue5¤„®î¯F™JT™j¯]„/σÃî@ZzÒRS!Æ« Ë Bá ÜCÃøW—/½²#:è´?Ño±4ë’’tãcÞ'!ã_ž= @ ÊÀ®wÞs½òÚöŽžnsñü¢ÂŽ7^ ¶¶ž"ÕÕUìþµª»»z»kxdAqIZvvÀ¢ÃxøÑÇÁ¢,"ˆjšm4àæVÂá²#QŸ Ž@ê·XÎÐŒŒHçGÚ7bàrÌ9.VtÜ‘#G22ÀææãjkïÀÝÍÍÇÕþ€™Æ,^‘÷Å‹ÑÙÙ£1 ÿصv»ýÕÖæÏš6®ê1÷FC†Æ @¸¸+½”Râ²e˶;œvY§Å¢E ƒ¹yÙo/\XÒÆiawØ”5 ·Ð³ù‰_zyüÑOÂbé5[»»÷Çv%ùþ/;»º!Šjœÿê+ Éii)ó1Çv%43go¹åæî[WßL ¯š ¨/àC|\üd ìyo{vësµB9y…Ucׯ×ëŸhåÌÜÜò´tÃvA¤@ ø…Ï;ú޵§§€2%åበ" @÷Ž«Í3󢫧=]=Q£1 ‡ …ÜØ˜wâ2àëïí:«âI5µ[­n§s^8Åæ¢­sešOf @RnnNQõ5U ¬¬¬ï×ÿvྵ÷Þ86:–k¶˜qèƒÃËýþ€ €7F$2!ZÓŽu|â9Ý#Sc -=€Dñ±1 ð0 Kgt 8™>ñü>öoÙ¹3ùe2IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/goselection_small.png000066400000000000000000000025631217176075400246460ustar00rootroot00000000000000‰PNG  IHDRàw=ø:IDATH‰•ËWÆçÞ[]]ÕÝÓÝ3“™qbma’‰¬ A@Ä[ˆÀ‘²0X‰¢Hü,A ‘ ;d!¡@b (±DEJì Läx¿f<ÓϪîzÝâÆïrJG:·êÞ:çûDz‚¢`jϧ€‚÷žÃ'¼°qúâÓÝfÍ ŸæèD0sð…¢s ƒO”r ,Ë"ÓksðÜ6_ƒ|ùøã:—ìý¥•%Œ74lýEŠ÷ ùf{À‹:üüñÏÍμú%Õl¨†å.þG ŒööèÇKàn%¸ žÃþ#_ÿëMO Ú°ðLˆŽ@«=pUTAµ^×±î%Ö[ùÝ­¨æ°úÈÃ?½ñ›Î›[f°5Á6ÌØÊa‰Aäö+WU}N˽ĥ¢%T…§2Þ+NѺò VŽ.M^xéí×þñ ÉNJèÚ=÷ÉÕ­Õ—ÔøÙ»nšÞá¾vm€.#ÖöWÛ›BH`ùÈbúÝ_~+ºri‹ÑvJxÂ5ÇúþCØf@¯½LF„Í&ÆX,ƒx¡*+Š"'K Léhùˆ.]¾ýSGÁ—Véýå俾ùÏ¿1ØÊ¨:UßÓ[ãk„YL3iF1A£‰³†J ” ¥R¤³tN2Hᢥ™4YYZdl†3×}´sú _ùt˜å»¤ƒ)EgÎ|5ÇvQ‹¼“!1”qÎ$œb‡Šâ=T3¨æ9iš1&Lv&è Å~±>Y£jùÒÍ6³õ3¯þûí÷Z_½^\£zZmK?îÓ…ÃWXj/³È"]–ˆh’3gÈÎ ½!Y3eªC®ïl“´æà Å¥ Ú¬pÃàÒä òrûXçkÉþ ­~Lo_ýöqîû›êÚ›E`ƉEDÀ£TZR™’ìFæøÑÆùÇ6xëíó¤+%£­!XêI1ã¯÷Îv_Û%^ŠýBwöB¬ÑB¨¦+h›ÄÜ4£ÇFOžûÞ…Óvø'836ï-ô¸˜_ªSÌ­Ð c‰Ãˆ¸íFqËG­f6ÂÔÄÖëæ.NÁ(NL¿ù‡S¯¼ø»·^ö‚ˆ- Aå8?üOÝÿj@Áv„¸…Q]$±Û Â`Çfb›rÕÝÇŠÆX:Ï6žzþÇÏÿ¾ÓjçÒ©+¶Îg9b?ý‚Їõ𗮏-kí®µ"ÆH&b¯J¹ÎZ:õÀ‰á•ñ®QA¤D åJ޵ Œsg1Ã6ÜÅo¨×÷6<ú®695·ý ÂÑŸ~ºªüm~ôàµBõŽ{µmÌɪ¨&UQa*]PdÓ‘Õlx—è|„)ð‰})ʯw‘4ŸÍçólšg’™.ø÷]ðëŒìîR²ÿe³4Á«¿o«ˆ¼Tã%£´œ¥sÜ$rÚÐÜ‘9èÿQ)aÁ6Ig³Ýf­É«I‘OG Ù(ga7¢ZVœ¦Ðþ¹%ýIõÑŸIêãQÂ]{Çsg­«Æ¥™ ¦”×A·-ÄxG Ì@sjU»·v‘ÿ/쀈–®IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/logo.png000066400000000000000000000270741217176075400221070ustar00rootroot00000000000000‰PNG  IHDRÈ_­;ˆesRGB®ÎébKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEÛ  .-öä9 IDATxÚí½yœ”Õ•ÿÿ>OUõ¾É£^D”¸ j•¨£¨Q«Ýb2N›L2ê73“ä—™ÉbÌ$šñk¾f™ùækÌ2ưE£q‚Ú¥àQQ«”Å•%pÙ÷¦èµ–óûã¹OótQ 4ŠRçõj¨å©ç¹Ï}Îçžó9÷Üs¡,e)Ëá-©L¼ãu]&Qî²”ÅF¢$HRéx¹ƒÊò‹|­Ë$@¡&‘€âÇ©ÒÚX“ÈÂÀIÆ3å'U–# u™5qu鸈È`”Fø¶ªnDä;O)ìŽK¥ tïËR–@êÒ‰‹Q—NˆˆV|¸SUGŠìnŠªÎnaQ2žiÙ}Ž85‰²5)ËG ©L¢ÓÈŸÊÄcªœ#"wTAUTA@Z~%ª?SauM<“-e…ÊR–%@ŠÝ¢T&U%ð ”/«sWdgCMëó|ì¸Õ½< µ­Õ"ò°)OÂ×H&Ê@)ˇ u™85ŽX§2qOU† \ðm…a0‚ëÇ*à•9­<=£…‰ÿØ—ãFG)äw£(‹Pù>ÂËÉxz[˜Ä£,»^e9ÜRDÀú‹ÈÅÀ÷€3Ù TU<ÏoB.§´6+UÕB$ºG³ÂåÏ w ,IÆÓ;?,mŒÁZû¾\8d×z¿î£ÔµŠÝõCÊ™.÷@öä‰^Àªú ®óy†h)PnÛœ'V!ôà‰@>#$&îÖD)÷¿WU[“È´¿ßx€¼ èÛƒ“ ´YkÛÞ…6Æôªá Ý4XkµD°§J„~.šÓÃWÜ7}ô`¡ªJY—IÄD9QáFQý'> Áu÷P /ž²‹ãNˆ?¿èÛÏ#“.­ˆ¨‚'Êw(pG]&1 Õ5¡v®$þ<à+@¯À’¤ä€À`1f)°Ú}Vo­m ÀÑÃ@ù;àÓ@¬‡î#,1à-à‡@k -ø¤ªþ³?àJO_[Ú¾èúöÀ­ë2q9ø,¿œà#B`H©ÁO>uy5}û{üef ËßÊrå ½}j¬Ãõêâ&@P£~+0‘§2‰L2žÞ\OwâA‡‘|¨8„×h^ž1Ƽ¬´Önía Äëá=Œþ£«>¸²“/¢=d“Uñ™xÀI¥ã$™ÝàH' úIàkÀEÎR Ը˶¹œrZ¼‚íÛ ,;ËÛ Ú{væÄ•Õû›ÄÝ‚œœLIeâ¿y'à'‡ÙÜIÞŠîõ΃ð܈[é^ô.u­À#Ƙ‡€×¬µõÖÚžà)Y Í]7ëþzJ*€Æ®úEü~ [Ьï”-è¾6‹Bz^Û·èÕ[Ђ”ˆÆ`Ú<®¨ÆœÝ)Iâ¯cT¸_TfÕe¿æ'ãé-‡‘Ûåcz[k›z*¬k­]¬3Æ ®®u éç8ÐÿÆc~j­Ý¸\’ cLe©ÚÁJ7ÚCèô8@‚ÙèÞг{²/1˜LBåJðy†³Èù+Àyb”ø'«èÝWð<ز±À¼Y-d³ê³ÿ†ÓYAü.ôUù]]&>]L2žn ßç‡YŠ•(Pvkm=pŸ1æaàßýäDçz}lŒù¾µvM€ä#+ÞžîÔnôÔ¥ãÑT&1øE§WúN”Ð8 p¨*ª0n|%}7ËšY6®Í³ô­,óžnAñ]®XL:xÈ€Ä'ñª€DE¸EGþ-•IŒ ßgñZ”`Bc›µö·sñçMp€ù‘1æcÅÖ¨,%RLbëÒ‰ÓEä;ÀýÀ? ŽÝTÈ@D(ä•ÇF4$B$"4l+°ú¯9²íÊI§Å¨¬7t°—r$^AÑw¿«K'nNeÇ@I¥Ô}Ä€R±šë@2#D¨kïc–­Gƒ?<ýIn¸ìÅpRá1 W7 úI:k¥Ü,ÿOé?(B4egƒOÚƒ+JÏ\1ð·Ül¯ìl,0!Ù‹åïd0È£ªÚë°b5¢1Èe!ób™ym¼·¸†ú«#z„´Ö¾`Œy8ɹÜ_žñ“²)EcÅhÚcùâlÛXÍÑ#wqܘFÕJ.ëQ(ì¯5Qbï.j'6­Ï³dq;žçϘGc«ðذ:G4 ËÞÎrÊTõÚ¿£ÃŠúÖjÙÛY^™ÓÊ»‹ÚÙ°&O$Êþäy ®Ö㎃|8ˆcÞ*µ`éˆ$é{‹÷xŸÔÖoªâÝד™;‚÷^L¶Í#VáOXt—È{aÛ&?QrÃÚ›7äˆDü0¯‘ ‰ óç´2â˜vY–ö6ߨîë:AÄËó„ŠJؾ¥ÀcS›xè7»øË¬6­Ï«€HDÊCcˆ´[kŸÞ}õiü5GŒ»áf¸°p>ÇŽŠ²£¡À›¯·ÑÞB—Ö#`ï,h'âçWRY-àˆUø„ý…™­¼4»…u«ò4ï*‰Ð¥V–nÉR ÉîhüEû’Ü¡X,UÜ®´$Òz(®ýˆ†UòÀÖ?í « ­-QÖ¯èÃöÍUŒ0»8éŒz i#—¢QaÌiŒ8&B>·y-øüaÐQžç/¨ª¨òx3ÝÎì'šYµ ŒíÁ6Ä€W€4{)áÊÑž¡È( /=QÖ‘V™øÅëz EüDü°pãÖJÞÙ1˜ ¶7£OßÎÇOØx ù½§­<#Vm-Ê6óêó­lݘ'›UÆ2×èa©ZBïûwã7½Ý_Oʰ}zÎÁ¯¨ö·èxø; äÃJÙ£QUòù<¹\®SÉž\>Ê–õÕ4n«dͲ~Œ‰oeðð´…Bç°°:“ ‘(¼ú|³ŸhfÚ<-Í….¡ªär9ÚÚÚèÝ»w8&;ƒ‘ÓI_cŒìcF½hîÁ6T8 vgú¹ hVÕB‹/¦¹ Ö­èÃÖ Õ{âÆœ¹^ý²Ñ.ð&+«=–½ÝÎS4³â½,»v(þD`×CD8ÿüó©­­åk_ûííímÊC¡P ŸÏ‹ÅÊ*-Y:f‹9NßËoÅ_Æ| õ½ºTü½Æ¢Ï©Ê"²NµgtYý2¹í= l6ËðaÃI&“€ðì3ϰeË|8gžy&sçÎ¥­­­ ’.(ߞ̾­Ž-E¨iËoY“ k’ñÌÆž¾vPA4ÚùŠûŸ›–Ëå1b—\üiÖ¬]ËóÏÏeĈœ{îy,Yú=ôÎ?ÿS\tÑÅÌ;‡uëÖQvn¯dá¼a¬YÚŸ“ÎÚÂÒw¶ó¬f¶nÌw ïK‘óù<ù|ž¡C‡FI$ 2„¶¶6Ö¬Yƒµ–ªª*î¸ãÎ=÷\¦L™Â]wÝEïÞ½Ëè,Q:§庡‚¿:ºÇÒY|AÄ;ì7sPDU©¨¬ä¤“Æ (óæ½ÀŸ½‚Ï~6I$éPÞgŸ}šºTW|6Éi§ŽeóæÍ @Èç<¶mìͬ?¶²tÉfv4æºF>ï[úÀ"¨*ííí|âŸàꫯfäÈ‘¨*ƒ&NÓ»woÎ>ûl®¼òJªªª:ιtéÒŽö•e ½o²ÖŽô〥P(ðñáÃ1|óæ½ÀYgžÅµ×^·‡b'“WR__Ï«¯¾ÂÙgŸÍqÇ–/_F4õv*´· ím~fp©jŠù|žQ£Fѯ_?-ZD{{;ýúõãÛßþ6[·nå ó±}ŒE‹±hÑ""‘H‡›‹Å¸ì²Ë8çœsX°`»vYФ?~x7Æ#½C ýúö£ºW5;vì`Ügv€#Åò<ÓNËÂE A<† ÂÒ¥Kv[hWæ-ˆP•ºNuu5S§Nåè£æ»ßý.ƒfРAL›6 6Íf÷ˆh…ÿ¯¨¨`üøñÌœ9“«®ºŠŸýìgeì)Gá&kÕ|¤wHTÄ´ TÄ*8``‡‚ŠH‡Я_?***Ýo÷FDhmmeûöí455‘Íf™1c÷Üs«W¯¦½Ý:ÌŸ?€L&Óa9*++;v,‹/¦¡¡M›61vìXr¹\åhv§—¬ r$¯ 9x€¸­›ÛÚÛØ¹³ë»ššhooCœEØ_€´µµñöÛo³`ÁfÍšÅÆiooïThíÚµ¨*ëׯïdMª««¹ð yüñÇijjbþüù\uÕU´µµ•!Ñ£€îõJܬú‘œò~PvîÚIKs ½{õfñ›‹:>÷ëïî^GþÞ»ï‹U  õõõH÷«¶“Ïç=z4UUU¨*§œrJÇyKvëÂm¨¬¬$wX€íÛ·³jÕ*Î:묲é €“€>îõ;‚ªé^€¨v;Q1Pþ^½z‰DÉæ²|ê‚ xñ¥—xò©'÷PÜgŸ{†Ùsf3~üxZÛZYiWtßÿÏf³|ñ‹_dÖ¬YL™2…k®¹fŸü!KUU\pO>ùdÇa}}=¯¿þ:ŸùÌg:ܳ²1#ðYl?ÜÚÙyŸ›š8d$=L¼G>‘¯|ùf*++˜?ÿeªªªø›sÿ†‡þøÒ¯½Ê©§žï¼óK—-áSç_ÀÀ™=û9ÚÛÚ»Móù<§vkÖ¬¡©© ÏóX¸p!ãÆ#“ÉP(ºœ'‰ÅbœwÞyÌ™3‡X,ÖŽD"466²råJÎ9ç^ýu¢Ñè‘>q88&DÐß>“Ù(VŽŠŠ ‰³©½éKTVú{QŽ;–y/Îc̘1Œ5ŠYÏÌ"õd"°¡Cùò¤/SU]ÍuO°zõ*b±X·¯™Ífù¾À/ùKŽ?þxú÷ïÏ£>ÊwÞÉÂ… ;xH)å0`_ÿú×9öX`ôšï~ç{{€cãÆL›>•‡~p¿­Cw$‹‘N§¹ùæ›yòÉ'ilÜõP(xûí·ùêW¿Ê¼yó( :”qãÆ!"L˜0Ïó:¢m{3T¢Í>DÖãËø«ƒþxÔZ»¡ì^[¡b¨W ,žçiŸ>}%Èòù<Ë—/gúô),[¾œêªêCÖ¸ŠŠ ¬µüà? —ËQYYI4¥¹¹¹D½zõ¢OŸ>üèG?êp—®ºê*fΜɋ/¾H[[[ÇÄd(ô\ õqÿ08Œ1ŸÇ_¤0È”­G 7MšÈ”ÉÓ¸¿vÒÄ-ÀÑ"Ò»P(ÈÊ•+töœçdÂ…ÑÚÚÊÂ… ˜:m ;wîìÈ=”$nŸª2lØ0***ˆÅbœyæ™ÜrË-œ~úéÙ¾"¯ýk&OžÌŒ3Ø´iù|ž¦¦&ÚÛÛU:3òàeàNkí«eÅ(ÇÑÀ7ðkñ‚_(ajÙzD€›&MdêäiL™<íñÚIë€þ—ˆ oii©üÓŸ¡¥¹Ed欙xž·_Ѩž!—ËñÙÏ~–O<‘ãŽ;Žêêj¶mÛÆ3Ï<³Ç±'žx"·Ýv›6mbÕªU:sæLy÷ÝwÅñ‘fàmàçÖÚ? t„X޾À¿ÉÐ!ÿéвõdÊäiÔÖNdÊ”iL™<­üŸÚI§wxžwUssó?<8ÝsiãÅ#ðû*±XŒiÓ¦u,ŸíN@LD$‰H,#fÀƒÀ=ÖÚÖºR£ÇWB‡<P&OŸ\ä:y™YÄÓz#l5š×€Û­µ—[kŸ 㣎00B|ãJ`201tèzà[ÖÚÇ˼£.V)ép»jodê”éL™VÊÝ8̤HcZÒE®Ä¯F2Ë‚sÝ_ñºæµÀcÀϬë28z a ÔN ¸É´6à¾ÚIŸ¾ŠŸø6æ»]a`dñ ?üÊZÛþ!yøpîàÁ<¿þÀн³Öñ°©a¾q~€t¶&72eòt¦Lž¶¸í¦ICúKHÇÂõƒJ±ûö&0 ¸×Z»ú0v§Â)èóJü%®‡B6;Wó-à) ÕÃó=‘Ð}xïszŠFE$r¨½”ƒNq2yz'"?uò´WoštcFk€‰( ⪄P–h50¸ßZûÒ‡ìrmïCÏDþÓŒ_ê®g10ßZûVWÑ­ƒ”m€½Ýë÷3йXH°%wX$Läk'MDQ¦Nžž­4q.ÂÀçQHÔÁD¥û;õ„Ý©À\àAkíÃ]‘ÕÃXÒÀ÷é\½ð`ÀQpàhpVcu`)Š£\=Ü?¹ûX¼KsU_‘õuWWè!N0=$æ)ÄOü÷µ7ŽQ˜("×:~ DDH·íãûh³à¯zœ‹_”aé®CP9ô5T]Q†F‡ ªuidûHï£B¢‹q£|Ìó7Ƙc tÛœŸ*`‰µ¶ÑZ»ëpå ïÇÓ mY•Ldš“ñLK*Sæ NòÚ$Ëî&+ª{ˆççYkÞ9@ô®õßÚçñÓ¼/žÇÏlíq­ ”!p¸ÎŸ¸¾9Õß]ÖÚü!è‰ m§£?’‡(gé£*Þ~Ž`^±__j$,ú¬à\´^!7¨¯Êþœ§GFêî~\¿;#ý¾ŽÙË{u.¬tçüûÝGRz¦â¨M8ÚUá©+á)ŽX¾O„ °IDATŽ¥2‰=~W*h°g;Jÿ&ܾÔ^¢n¥ÎYª%£T{±ÚÕÅñÜÿ•Ƙÿ0Æ\îÞÇŒ1½ºxXÒ…‚Š1¦ÚSáÞGŒ1wc>ÕÅñѽ(û|·îzo€ø…1f|ßõ:PcªJüVöäA¿†ÞGŒ1}ö€Þ{9w—ƒ[ ©LbH*ÿZ]&qù¾£:ñbå“‘Ÿâc¢{SÚT&±‡rÖ¥±ºL¼roÀ(¾N*“ .ïÌ"I]:+¾ŸT&!]ƒ ñ`]:ñ©ºL<âÞ÷IegÖe^1© :ùà;·«Ý}÷[`,°ÈZ;Óó à‹ÖÚï‡R ð¿ð—¾F1\©—ððÜ„_fæàøåg¶¹ã~Œ¿–áv ¿¾a#Ù»ðóýŸsUÿæŸ §»)ÉOœË²É]ï®Ö7€Ïðù¼ü»µ¶Éývð-à¯À…Àüu}ï£][ú3ßXkw¹ßþ3p*0ÄEØz¿Á¯’,ÿ½øgüõø• ÓŽ(þ ~mªœ;v(~i¥AîšCñWþÔ —ÿŠ¿@j~†¥%u¸ˆ|åzE›æ ò_ ½P½a´ cñ«¿ü<O¿“Ê$Œ*ßÁ äªQîA¸@U®IdÞL¥I=$!þõû¡z«Šü½ § â!ÚüC2ži )ä§½M”f§u½€û’ñÌ©tüzD"ÉxúAJ{*“8Õ3y:O·†îëï†'™ÿLe§â—ɪªY·ÆèÞd<ótèøï‰È Ð Çw$ã险tüAE~]“H¿P—Ž÷a†ªü˜]“Hw,ƒŽ:Å ü ¸¿,'ø:~Ë)I(îœXüÊàŸwJ¿Åä§ï:@pœó»wc†áWטä_;¥ý7ü óÕøËv¯~‰_ ±;òK×îYøëG6cîÄŸ¹hqçžL6ÆÔºbçá—›æÜÂO8`¿å×_¾iŒù…ê'ñ÷ÿë»~À]øEÙþ Oÿk厃T¹¾×§C€?¹ë½ëú¦/p¦;Ï@üªˆ·8wwˆ˜JÅó6+ú'‰ ²JчQ6 L@¤xÕŸ ÒeU*8YU¿ƒð ÈÿEÈ¢:Xák¢RƒÈsî¼ÃD¹á6U]-"'©ð?£ò-Í r£`ns£øE¿+ð=…mn¹Ü±µuéø èÝÀBë=F*Ü&ª»‚çŸÊÄQ8•…uéÄÙ ÿ¤Ê ˆÌ‘è1ŠüS*“è—Œ§ÿä¼Ì Uu“ˆü Õ(`T@”l]&>PGUu*è|N5¢îAýÌÝÐ\km@È—;eòØ‚¨øUÁ¯Æ/Êövh$ÿ+0¿²††xH «˜VZk7c~àÀñ€µvKè<·9ÅèVB¥»‹¿ìt…³qà|àjkmcèÜœ‚Ýæ,WÓ˜©ÖZuà¿Øl­½¯ÈR}ÛYÚKñ3Ž=àÖÚÙ¡cæ§cூ ,µÖ®V¹Zá¾¹¿ÀÛ“á 41ËÜËplØbc"¥Üœšx¦Ê$Ö;Kjkâ™ n$¯@Y:+™È¬ð_•4Êï’‰t°üŠT&ñ=”O¡þ ŠF€'Q^«Idš©tü‡ÿ“L¤ßsçºOѧüþը¢|)™È,5sy]&±AD~ ¼²$•I\’Œ§Ÿ«KÇ{)z’ÃP¹"ˆ*ç ôW4#B-È‚šDúþÐ9W¦2q¸¦._ZÏ,þ”Œ§_sA G¡Ü¥èïEäÑd<ݸoP=gÒ{[kç8åNñ+Í`÷þaz3 h Àú]Þ¹N¯ý.Lô½âà§É¹Y;è~ÖqpîˆSœ Ny‹Î]ï,ظÐ=í gqÆ7cRƘ§Ýß,7ÂÙYð·J^_ÄþŠ¿î¼Ês2ð¨1æ‡Æ˜¡ÖÚ®*™\Œ¿œ8æ/+ˆ¿´ö!cÌkƘ[1½­µùbR“È„úC= E±Ô/zPHcÇ£Ú¬Àp’d<½áv:ÅòD¤¾£¦¦¯n;¶wðe»¨8¾'•sTäÞT&>+•Ž?]—I<Ê$f¿FõT”〔¢·ú£¾/ÈXUî­LeâÇÕ¥Õ"r‚ KD¨*”gRp’d<ó<ÐO;PíÄ/=ëïúFÑfE§ˆÈ+»Á‘ŽwZµè9—`[ð€ƒZ®¡Ñm]ó%•N9Jýn‡;§·¯Ð1ÐæxG©ó¬ëÒ…èXá(uîV甊iôw¿û¦sõnq·â—6:ùLÅ #Æ^êß8ÞµxÒóùbÂXkmÛ^Ö‘7?um·]î±^=‚H®ÏÒÙz¸;Œ/!ò°ÀäT:q{2‘þK2‘¦.“ &p±q­3ÆÜ<„Pg_å&ùJâØbŒù‡ðïÜþ78ÅlëÆ3{ ¸Þ3ºè<Ç»Q»?P\͹13ëŒ1'…ïË3ÂE•¦tñÛ5.vI±oŒ¹Ès§1æän4£ÝóIcÌ8Î6kí*N¯‹ Ã}ÅÏÁSaŒ‰cÎ6ÆŒwßµ8+çì|Q2ž®a W¤2‰!røÑ¤x È%¨VÒÅhR$LÅH#ðZ]&~c‰ù†+SéÄýîZÍÀÀ¹*\àÜk}è«pµªÎpǾ¨ª~>•‰Ç’‰t8Réø¿ÛTykß#…V¨òE„»S™ø5ñt‡‹ı¿üÚ3Û‘òði`0=4ÒzÁo¬µ+Œ1¿îrY¶9Ëq‰Sê¿„8H¤H!:Þ[kÿhŒ üÞó¬‹é¢aiç®y!’Úì€pyÿ¯6ÆÔáï¿w‚ M?b­}¨ø¾Bò° ±>eŒ™áBÄçqà>kí;]Ü[p¾àóÕîa?kŒyË6žp.žÝÓ`¤1æ%üª‹Û=ÛZ{¹1&L5Æü·sa'¯íÅz‘ÎíØ]p--¹[à.EJ¥ãO)¬‘Ï(ÚO”•"Ò܇ žËî÷*‚¨{öšEùð»T&qèLT"P¥è¤Ý “µªü^„êd"Óê>[¢ª/ 2®&žžºæ/ù!ðT*xT…×¹:Y?ªI¤×„ÚVb0’˜‚‡ªÔ$2kêÒ‰/<’J'nG˜›Œ§Às£Ñ.¾üw§äG»pç¥Àýø òù‹ÐH»ÀùÖ9Ò*Àwñ÷9,âHêã.ìøþÓñë*rP‹_&óç>\|Ϲi%º#à+]Hø .VäyüÆw]äm›»Ö/B¿{ ø¿%‚?q¡çJà,wÜ—ðËò@( È‚&Wñ1˜ƒë"_w8·k+pOÀ…\äê7¯4À¿ÌYd€…øa<À¸~¼½« _?¤Jvnß"à1T7£¥û?‹ê·ù"9N}\T¾¤è?ªj9› <öîFuKDD³â÷ÉxÙ,"×ûƒŽŒQÑQª<ŽHR„µÚ ÷ªêôuSàAQýq‘ÕÛ†ð/À÷í-0RU£¢7×$Òo…ܽÿBYRÂÂÝ ,l¨I¤×ªÈçúªî{4¤ì­Æ˜—ÝÜ@ÁEµ„|å-ø™²›r–µ6eŒIá—¸ÄEUÆ:ò xqèA-] ñuáá•ì®_p×ëd•Ùw‚Ùüð1ÖÚ‚1f“|ǹ¾ãFß øUTîîeq¸.~;¿D›V»{>ßä úÕ}¾ x¶¨/²¥®º—!p·¥Ø|4!ò–„H‡ª®Ed*Ú),œÈLd4•I,TÕÅ ˆ ÉDºP—I¼ n³$…%¨ŠÈîßûÑ$éÈý(¨òXGTÍaS]&þŒ(Ï9vRHÆ3¾~?A¸ dsQ¸u­Š¬ íd"C2žn¯KÇ_ÒîÊ… Á9™«RBgD_؃Œ©®CdhaŸùEÝÈ7:ÖóŸÆ˜¯}~‚1æ>cÌÍÝÍYÚßëL.ÕÞ®]üú@~ÛÝ,ÝýÍæÝÛyJ}·gŠG¼d G8do+ëJåE•N%‰ï‘³U×ÅyS¡6¥2SIê:~/™#U—‰w¹:2hgqÚKW9\u™D—}sPUMܶ^÷¸™ò.¬zðßÖÚJDŽÊR–•üÿV.9…÷­IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/000077500000000000000000000000001217176075400220625ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/appointment.png000066400000000000000000000155111217176075400251310ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËIDATxœíYŒ$Gzß™Ywõ==Ã99ä\$‡K.Ï•R»´,¶%h%¬Ù>  caÀüà?6 ÁlxmK^€Ö†,Á^iWÉ¥DRÓCΰ{È™é¹zz¦¯ê®;?dfUVVVwMW 9;U *3"#¿ˆŒï_)´ÖŒ1º_vÆør1&ÀˆcL€ǘ#Ž1FcŒ8ÆqŒ 0â`Ä1&ÀˆcL€‡uüËßûýÿyæÉ£oxžG|†@<ô¤ˆ]H*ž9ÑË2÷ &‚§Ð{ÄØO8ÀS ¥õ¦mp鳿õÏþþßþˆàÔñÿðWÞxÅj'–¤Ó.è>ê„ë:á,IFÒö5¥£t èEÑöïƒU½ÂŠè¿€KWoâº.BˆÖO!´Öþ/8—""L„­Ú)WZû2·aÁ“ <ÏÀõ<ŽÌÏqx~†Õõ-nÞ]{è&€†šÖLÖ Ñ:ÈxMë<ªÄp&QGí4Ê‚@IEÛÊTÁ5í ñÃñ¢;ÝqÑèÖyB˜VfvÊI£"Ï%Å hgfpô¯‰ÎkŸï\‹† 0ç&›¥˜Ï3Y,P©ÖQZñWÎóƒ÷/b…\¥Õz#¢Û6önŒˆç½öcÄev)¹DäÄÏ“Ž!*õ&+k%»±J1Wäö½Mʵ¥r»%”Ò\¿½Â/ýìKÔm‡çOåÞ¹ÈÓGP*×ÉeÊÔ›õf´ Ro€ÜßÜ¡\m²]©ày ‘1?xܶ ¦‹y×eZæh4³\¼r“#óȤSA®ÈîXLrxJñÄÜ4?úà2ëyÌM˜*fɦMй “ÿ¼Ñ¬ñÑåëR0;Q e™hí±¹ÝLLKOèVµÏ¾š€°ï« PìÚìe(Tÿ6€/´w ÷gH@mBXƒ£µBQ®Õ¹|íz«ÉB`’wW!°š¶C©\eéúM<­0¥ôE­± ƒZ£Áå«×Ù.W¸¬¥,Ÿ®‡!%J+nÝ[ •zƒÉÀFØ“:HP!—ê°’[dˆùEíó6QBë[G•»[XÝ}¯ïqEÂvúÅ Ù~ª(™#±¶ŒÀVó©'[Õºh[ð­k-2´À¶³Ó¯C‚Ÿûé—q7bpÒº&ÛA ”¥sø(`œ¦ñªà‘ǘ#Ž1FcŒ8ÆqŒ 0â`Ä1&ÀˆcL€ǘ#Ž1FcŒ8ÆqôM€ç˃©MsHSœÃÀ£š&Í—¦= 0è* ˆ Îã ¢– ^š††‡”&­5ާö¿?À………¡$dXr†²T0¼41DYÃLÀêÆ6¯¬2?êàV_‹B^|á…ÁR 5 /òÂW¾20»/,,ð éаpqaðgƒöó=bùÂS×í^ØÛ· 0ðú»È†E \¯!Ãz¾Añ°ò)á=`Ü yŒ 02‰ý˜#! é•…1Fþrónu6¡îÿÆÀ]<þÈ£M€Q‚èÜ—(Ę#)dò#_BZ!ŒN ÀئIWï­=üñ…BˆÈ¼Nd ½ƒ†lWš,¯l´vÛã1èc@Aµn³Qª>R/LŽ1ìih@JiŒ¸iðB ÷xŠi:²qòü`?½‘Ì”AIÞÿ(‘«ccè!=ß xhùÔC¯ÝëD0m3ÇÈ.p]=9q™ÝïµÓ1¬çƶ5ÃÎ'ðKºL°º7‹:7RôÏ?]\ìkçÉ^jqii(½ï…!¬˜ 7¿°°@ךö!Ëq.õ±/O?r†•O-ˆðûHÜ.>(dáP6‰ZZÚæG/ i“¨¥¥%Î{v‹^xn›D 1ŸBøsÝ-~âvñhÕÕ e“¨!ȉb2X¦Ä0†SÞ†²IÃͧP®”¢K¯]Ý@CHüªÄ>½0Þ$ê¡Bk…òüvß©oЬo~ƒoÒI8¸ëdiÌ!•†1úƒÖ ­<„4XYú>Oåþ ÕÅß`óîÇþþ*û]$Àÿ@ÑÀQŽÑ7´ÆólìFJÿ…™çÿ1žÿ›l\ùWh­ð<{ðZ ìÝÅÐM!ã‘À/ aÕ/„äÖ'ßåè™7@|Ò¿ÂO˜Ü_~¯UC ßßG×H 4$–i0JS¥_*‚Ò߬ma5þ9÷ иÍe Ç¿Åöò‡Rî@µ@_CÁZûÕ6c=RoK=®ÐZ¡´‡’•¥ßçèé×ÀUи °ŽqøP–Í•´òªD¸"(†î&À¤,sL€/Zã9 ìF«úCŒ êWÊÆ Š'¿IéêØèË”ˆÄOÃŒ1\DKÿÝ¥ïsäô×À©ƒ»Ùþ~`ó˜ó<1ŸgýÖ´>çºF?ÓÁ¢‡µ8Æ”~§YÅ(ÿ Öü× ~ÕW°ò@)P.Ôo1yòmJ×þó@=‚ðS·q$ÌîçiÆxDKÿOÿGO½vÜí@ù(Û‘m®‚9ÃáY“;û·ü‚-»¦„ÇÆxÈhµý;Èò;XsÏCíZ |; €Ó&Bí&“O~ƒÒÕÿŠRÞ¾jh/ ÚˆôhìãÁc ÑÒ¿úÙqìä)°Kàît*=<רk`NphÒ¥´zyßµ@_½€12´F¹6N³ ÿ‡ÔìY¨/ûŠŽ*ß³Û?åBí6Ó'~šÅÿˆòkðK$q$@Àcü-¶/Z«Ö@HÓʲzõÿrôÄ1hÞ·ÖV¾(?^8[`¤˜/Øl­^FJ«õ®_<Ž$ô2î{Ì]&¬oÕ…® ”} ³¥$åQ)Ý¢ºµL}g}÷{¤_ú:ÔWðó[¬ÛñÝ:r–Óú}æŽ}…Ëþõío‘üà=œê nùº±ŠT;äÌÙ&“9ÈeRÌä‹Xç_‡ú=ð ÚÊ(]G ÀÛsšgŸ9O³ô¿hl”Ù¾ls³f°cghêÊœBäbŸÂÊÏû–¿ "ß~Ö^KÉH/Ê>:†³ϰä "K+ÒýE¶–ˆ[Zg שpx¦@>g‘™Nadò9©"ˆT{€GKß°k®ƒ4.åw@úõ·– 6 sœô±Ó¤µÇ¤RҮߌÔ7е ÜúÇÔ›°¹^aùº'ÒÌl–¹ù¡˜}•hûžH!ŒV{1´ÅZ¶…~tFšHÓÚ÷I}þOyêÈi˜)€5 FÚ—£”oÔiœ4·ü’Žç÷íÑøU¾áwýD´ôGIü:š•« ,&`ùç2™Ãˆì ,$–L¸uhnsöÉTßaùÇÿ £þv1|ŽNºNÊ ×u[ÙühP{bX$M•ÍÏ9,_ ^ì PMÐA× ùdj˜±áܬ‘ |™ì×E Rèð¨`4Që`x7œÝÍ’s¶‘Í•£oL~™O¯ý§Êÿôã¤rè`ô.TvkÓG|¥t@.-†ÊÑê?Bݪ’^i¿AÃÆÊWºçøÝFÏ ¦w hR8Ûe¶×®òÙô[xÛÅf˜Št+¾1ö€VL=ó7XZø·<½²Œ3{‚ÌdCÚàU‚’1Eü$’É!7´êœðiùGJw”ZûÄêðÎ1 ;k šë”î_áΡ7È}±òQ+aÉ6À˜{"•™ •Î1ñÌ_çÊ¥ïrfíÊ>Ffz +=ö¦ß 8ÀWºnúh¯ýk¹u{UvËhA5n†ÿ¦ßö#ÛÕ¾jLÈÀ®y8ë”w–ùaå0¯>ýóÔ½ Úšn„Ï1nö‰tvŠüԵι_ã³¥ïqºt•¦g£§fHåæ ¹¿yðAEì„V)#%Jz@ ‘ ŒÀ,¾:%dgiVš¸¥uv¶osóÀ›4œ4¹â¨"ÚºÛ« £_©,Ùü\KAâÜ·øó?û¯q‰Þ©ì4®MBhýGkÜÖ Á%=Ât áøÄRÁ ’–?N³\C•·(•îpsþ-œþË LLŸÀkH´QpÂçH$€Æ:ôÇRš˜é<ÙˆŸ>ø‹ œ-}‚°×qòXÙ<Ø;t*:NR»OŒIÆ!¤O#M³RC—WØjØ\H½Æ©§Þ"_œG¦fÈæ0¼:³sŒ~=O c)úc !d Ò¹«LŸøe–álùrÚÁ3Æ$Ø[mý'åm”IJ#ìQ„í~Ð$¸^QÛf£ÞàÖ‘¿FJž _œ§0} a^Á´²aƒ0z «ôpÞFyÌ'A:ˆ|1>ûK,~fq¶òb+"t0è‡nýu—þÖyÔ–|"ÊW(F¸ îW¬ÿfOüÍ{;ä§’ÉÏ"¤…F×ður70ß»#J+3MaÚŸ˜gþ*KWg·ßeZ¦ô¿¤î_ëôê&MŒÑ! +K¶p å¯O¿ÍÒç’Ó›ï07eì>Ï-å-wpÒE:H ]¸QÑÜ;ñMf¿F¾xÂô1Ì­ 3½g;; ôW¥”ÌpýO üY7£Ã&PÚƒÓosó/®1§ï%W«†`Ì/ÑŒ£ÑJ³:ñ³Ç_'W<@aú™ü,ÒXoUû½*ôÄÀ0ÌÄêbŒ=i2h”ç <T®%Ýqĉð$@Ê­Ÿ8H~âéÜ´oðɈ{0 Ñ0¤1®ö‰–M`eIe'1 “œàõ*‡t*9îŽÚ-‚DŽÒΩÌVº€aeúžÝLìF“išFð`ƒ1âQÞ$êa¤I †…çÔ™0]_ù]BÄ Á„Þ@Ü€ö8@è/49¯ŠVR’·†OBb´`(›(iýhm5Ä4…ÓɾL…ò\\×¥¶¹ìO{²[ÁQô"B?† € g‡­Ûd ‘®ƒÔûªÒ”ŽÅ¥¥¾î !†#‡!. bš Ø—G+<¯‰çÔ¨.½Ã³&~ Ћd»vcÆaKñ¶BΫóÿ)ëµ"†•EJ‹Ä÷ÁcØu.@kÁäóçÏ¥Ô !†&’kªýÈvš´òpì*vc‡û[½àõXÛs,€½ A -`Öªsêì¬T. Öz×/õlR¦ÿŠø07*h%P®@+›´³†ö—ýu†ÚÕÙ©à=ƒH)²¾ŽÁv¿fgO®É `š&?~ÿ}nܼçù1uÝÞGmÖêU˜hpÝx.èŽz•ÃÞqÇbëicõa}ïÚd&¯HØ}=ëQhUC5Öx£rR:0ÜbëÈÝá*" ÚQ¾3Ü«I…¤¦5±f@P^þ„ïý÷ÿ†4 # ÂÏÒ_“ïh@”Ò‹üò¯~ Û¶ýªMûÐãÚÍÒd³ ƒô†nÕ2€u ‹–Q—ÛéŽÊjÅ>wo C+ "9=azÛ†t GGöG´÷I މ×ð)!d@ NîëûµÂs«4Ww˜«6AÉ"¶€aù«‚µr=ìjƒ;uÍ•ô RªÉ™æ sÙ©|i „vü%_®íË7 žñˆ¬a<}”ÜôIÌTi˜Aú4³3³4v\ݽm€ùùù¶c`h¿ Ü-(@è`ª\½›v<*ToG\ª“<µGzB‚ìI)t04'@𺵌@4 <×­²ywœP~@iŸ°òÊ£´[oÒÜ®p¿áp³ø$îé×IggËwÈÝ|cwï1Ëb ˜Ù fÚ†Æ4ËAFøë N™‚Uçà‡ýñÓj´] v!€€¬”‚´eF*ý`±‚bB/Ñ ŒEt”0^É*·u1ª¨@I!Ù¢5mµ\º-?1L”ajt´°´Ÿ.$‘1_à“Þ}ßü»¿.„Vî¬mþèßùðgµÒRÂ×·ÒZ¹Jè½ •RZyžŸZ£´ÖZ'r<‚(Oêu„ènq{¹Ãóè$|û¼—ˆÜÝvëÀOMû?ŠH´B{u”[Ów¯Z"+$®™iÈLãÙMÜí5ÖË.‹)}wúUOŽkYÎa4jZ¤ „!|žº ¡ì2ž3+Ôô7¸b|.ŸÜúDž­ßÅ\UœÄÌA°Y)X^üÈ[Vç&Zl®QöÀ^qtV»Ëz~ëÔa /?ÍÙøÜä¿?rx¶€È³½±¥/nnÞ¸P©¿»ÚÔ+ªmS*7ØXßfóþÕ{[4vê¸åÊ2Å,bª€5?Enn’üÌ3Å,3†É”e2u<-_y9›~íL¡8_(Á«óѽÒí½vâïÕ9\ör'íìÄŒ!Ȭ¯ß·j•r}{scëúÕÅ­û++U´.w;;›ž”rùÎÍ››sGd&òE<ÛVëëÞÖFI5œŠW¯T\§ZUJ+Åî 땉qÿ8)’29O/òÄÃÆÝñø{¥Ãß099ÌnÐO=Aê•38s“Üù¼Öü8³QñFymýBµòƒu¥´ÁÆD†²ë±Vl¹ŠÓ îilOáÞßòã­ƒžð?÷g†A:—&—I1™Ï2kH¬kuëÍú»Ÿ:ÍW¿Z­¾y •ÊÝòìw§ŒÏo56ïnܺµY—Çe i]»qÝØZ»cW¶w×i:ø#NW „_}é%ùô©ÓbyyYomosî¹óâØÁC¼ÿgïèË—>ÕÍF£ëÆ×^{+W®P*•võÛ û¹g?÷Oˆ©©)N:ÅåË—ùG¿¡­ŒQ/šGœ´4§lAU Jìh͆ÖlxŠÇ¥V©c—ë¨Jý?ì-ø;o# YÄI¬tJ¤,Sä…V“B0«³LÍ´©1mÁeÏãöÆwß_L×>¼QTRXbkkÃ@ÙPBÖ*“ɨ^#š„±«½ðío›õõõŽ }óÍ7»üöÂ~îÙÏýƒÆbkk«uþ;¿%<  l·=Ø6ý¤”ìUÓÀN[¸…,êPpïoÿfÏ(B](ü÷Ïš@(ëLkAÎÇ„²))ž¥ñÍŸi:?ø¨¡Ì͉2¶c£TÛ`O¬ÆØ?~ç·Â·>É? ¿9±>9û(`„/@H?ùu ù›¿­äÛÛ`Ä1^÷5â`Ä1&ÀˆcL€ǘ#Ž1FcŒ8ÆqŒ 0â`Äñÿ5ˆVªî˜·‡IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/attach.png000066400000000000000000000362741217176075400240500ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½wt[é•'ø{ÈÈ™$‚)‘”D*–TÊ¥T*… .—§·{§§ƒ;Øî0³3³Û»Ì93g§wwúìv··{fÛÞuè¶+¹\vÙU’(1$0'$rÎûÇÃ{€ÊUåR"%uÝsp¨>¼‡ûûîwÃïÞ¨T*xBÄC¹Î €»¾4‰D6›ý+o,—˨T*ˆÇã(•Jô¦îW¬‡|O£u?Ë*J¥2™Lg2™Ze2™^ X¸\®‘ Qõ=À(—Ë‘b±¸ÓéôÊÆÆÆl$‰nmm}øúgÞ‡|€–+‰„a4÷µ´´Öét' Ån‰Dbár¹l.— 6› ‡&“ (‹ÈòÈesÈf³Èf³©T*5¿µµå\[[{{iiéN ð…ÃáJÝgm;ˆÏ¶€&He”•J¥úرcçôzý+Ge2™T(B(‚ÇãA*•B*•‚ÏçƒÏçƒÃá€Ëá¢\.#“Í ŸÏ#‰ ‰`kk ‘HÑhÑht. ¾í÷ûÿÁív;–––è†ïWŸ &DõÅP”J¥ÚC‡½ºgÏž¯h4šÝ …"‘R©jµZ­r¹üž?$™Lbii sssðù|ˆÅb‰P(ôý™™™ÿÜ××7‹Å¨{¹'Å|€äª/à=zô•gžyæFc—B¡€X,†J¥‚Éd‚F£yhàt:±°°€x<¾577÷¿;Žÿìv»ã¨mCŸJAŸàþ„Zñ %£Ñ¸÷âÅ‹ÿ¦­­íªJ¥‚B¡€R©„½­ "±ø/”M§‘ÊdîRƒÁ€@ ÇûÄßÝ qëöm,.."ßüæàà`2™üÔ ø ÷.Ôªg`9rä7ž{î¹k05 J%ÚZ[?ÒÌçr9lll  ‹!‘H —#½r¹L¿Éd‚ÇãÇãA$A.—“Û‡F6‡ó+×u¹Ý¸sç"áplttôÏðƒüUݽ~¢¢>À½ ªâ ‚P¾øâ‹~èСßÖét„F£ÅbÙl¾ë …ÖÖÖ°¶¶†ÍÍMÄb1D£Qlnnf}>_<fãñx6NçT‚`ˆD"~CCG£Ñu:H&“±d2$ ´Z-t:ŒFã]Ÿ“H$ðöÛoÃëõb||ü?üà?øw¹\.‡_‚Ïðé…ÀÀâóù¦×^{í/÷îÝû\cc#ôz=z{{Á`0è7' ,//Ãçó! Âï÷cee%>33ãóx<¾`0Éåri9>D©î3 &hhhFåîÝ»uííí*½^ÏV*•P*•hllDKKË]7ù“Ÿü333ÿöw¿ûÝß) Ÿ‚Ïðé„Zù,•Jµëµ×^û/mmmŒF#l6ÚÚÚè7 x<ƒA¬®®ÂétÇÇÇæææÖ*•Ê€€ €BÝ«Rñ ààR/‘H¤yõ% ’H$ê³gÏv>|¸Ñh4B­VC$a÷®]àp¹€÷ßãããp8ÿåþáþ$À~Å|€Ojåó8Žé‹_üâÿµoß¾g, zzzhG¯ÏÃ=1x<Ž LOO—?øàƒéÛ·oT*•UQA Ø©üÈŒa 5Å0Q€€€€@#H Ⱥ»»mW®\é°Ùl£Ñ.‡ƒf³Z­ðî»ïbrrýýýúÃþð?à!àŸC*˜V>õK/½ô?uuu=ÓÜÜŒgžy ±°°€l6‹¹¹9 %ßyçÛ.ë6QS|¤ò‹¨Öð«û3f2AZ‹­ê5‚Õ?7hOúýþèk¯½v X, , –——‘ËåÐÔÔ„sçÎ!O \.ÿûåå剑‘‘·«×-ãåi·”„DgΜùÖåË—ßb±àøñã‰D€••¬¯¯#NÃåráÆþwß}÷ç¹\ÎRñë¼ M¤©/ ¦øz©ÿ{ý—Bòä4š4J¥Ró—¾ô¥£]]]B‹Å6› £ÑƒÁ€|.‡ï|÷»XZZšùë¿þëçÀ<ê,Áýê‘ñëßòD äÎ3›ÍÏ”ËeLMMa`` Õ××÷€ ó Wÿ&Hs_ÀÝÞýÔ2È•Ÿéh.U?ß7444:22²±¾¾Žr¹Œ@ Ðjµ0 0G{{{/×=ï}ÉÓ* ÇS«Õ‡.]ºô{:Gäóy,­,I0±ººŠ‘‘‘Ê;wÞÉårC Wájf¿ˆGOÒ(ƒY¤%X°À÷Þ{ï---Ãá0Êå2f³2™ û÷ïÿ2Ƀ|øÓJù|Æ«W¯þISS“¬§·âj5ozz°¹¹‰ááa õmllü¤âW@†gYJÙ.†N¥úy)!â 0œZ (•J…B«Õ …B“ÉôŒÙl>²öp_VàiïóH.]ºô»]]]=v»¶jž}nn¹\™L‡N§sÑíväÊ_©ü È•¿ÝRª~n ¤ï± 8222éõz‹±X ¥R áP U^"³§§ç"j…­{ÁÓ.Õj}þرcÿ¢©© GŽšŽEíûN§3588øÿt¼¼¸[ùÔœ«¿¥”A:†Q[[[ËÇFQ°áó”J%`µZOÐÝï½=- R®<>Ÿßqýúõo›šØ‡@&I–——AVWW144Ty3“É8@šÜj±=eö?ßTœÿ°… Ó k AÁ‰‰‰ùp8ŒI.PL%©TÚj6›[qŸ}òÔ¾/ »zõꟵµµ™ötuA¡P&&&P©TF188‡ÃÑïõzßijƒ °<“Éd‹D"SKK‹M§Óí`"‚¢U‚(XO§ÓSãããÓ©Tj9•J¥>t/ ª¨¨×××W@Þf³qx<Òé4d2Xz½~ÿÒÒÒMü3•íã>|øµC‡niiAGG`iq™L…B‡ããã.—ëÇ •ïÐh4æ½{÷ž²ÙlgµZí!@  @.— ‹…J¥‚b±ˆ\.‡t:çž{.‹ÅçÆÜÜÜÇÇÇÝxx‚ ‘H$ …â™LF)‹‘L$@Ý[•l©Ë{® <é ”/ÔëõÏž?þ_F:ä‹F£ØÜÚAðx© B>!é¹sç¾ÞÕÕÕµ{÷nšØ155…J¹ŒT*…8Ž©ÕÕÕ›»víÚûüóÏ_×h4͉F“ &ƒF“‰. ÿ:a0P(´ …°´´„ååe9Çû7F£ñ¹·ß~ûwÜn÷î‘Þ]'T‚( “Ïçs¥R •J…î3d2™`0`2™rƒ!¸ŸþÃ'T¡‡ÛÞÞ~åøñ㟷Z­Ø³gÀëõ"™L¢\.cttÃÃÃ!—ËuûܹsçOœ8q\ °ššš`·Ûï¢ÕK¹\F4E2™µòÐû®T*¥Kà, \.¸\îW_}õM½^ÿG7oÞüÓéôý†TѨÈ`0P©Tè†SJX,‚`ÁA­·áSË“*Ôáà644t]¹rå›f³™IÅûét>ŸA`aa·oßÎy<×Ë/¿|´§§§]  »»½½½à|ˆšM§±îó!##—Ë!ŸÏßõ‡‡Cóý• ô˜L&är9Nœ8­V‹ááaí™3gþ‡Ã‘¼ñÆÿ'jU»{µ•J¥R"AüJí¿X,•J… RŸ…ºÈÇÉ“ VåS^¹rå›mmmºÞÞ^Ú|ÏÎÎÂá0>øàƒ²×ëõ]ºt©½­­M«P(pôèÑ_aàF£Q¬¬¬ ‹a3D @$A8.§R©L¡PȳX,…BŽT*åªÕj–D"B¡@*•†Ï™LŠÄa·Û¡R©ð‹_ü‚õÌ3Ïüo¹\Žñî»ïþ tË`0˜6lrÅ ­T©TB©TbÔYâ^Á' LU>ÁÑ£G¿røðáÓmmm4‡nn…Bù|·nÝB,+;vL¥T*…J¥'Nœ@SS}±R©„©©)D£Qøý~,,,`mm­´¶¶œŸŸ÷nmmE£Ñh¦@î›ÍæH$¾N§“ïÛ·Ïh·ÛF£‘hllŒA©TÂl6C¡PàÚµkøñÌ>qâÄ_–J¥ä{ï½÷ßpT.B¡Pˆ¹\.ÔvPU>ª´ôû@ð¤€2ý\“ÉtêÂ… ¿c±X@eû¨UKFGG±¸¸Xiooçðx<®^¯Gww÷]Ê÷z½ðz½ˆÅb˜˜˜ÀÒÒRy~~~u||Üã÷û×P+SiaF¡PÀÖÖwkk‹çv»çÌf³éÌ™3öîîniss3 ¶¶¶H$`·ÛÁápðòË/ã{ßûëèÑ£ÿk ð¸Ýî!Ü;b±XÜ  ðù| ì™L&\*•RÕkVžÆ0®ò±X,óåË—ÿÔjµ :¨”+X[[ƒÁÀÒÒ†‡‡a0.—‹ÆÆF´µµ¡³³“¾µêWWWáv»1??¿Ùßß?²¶¶¶’ñ׆¨Èƒf÷.--ÅÿöoÿÖÿÜsÏuž:uÊj³Ù ÓéP(àv»an6C®ãsŸû¾ýíoËÏŸ?ÿ—ëëëÂáð§mþd ¸\nƒR©K$då—Ëå"ŸÏ£X,"›Í"+•J ÷Á[xP¿ú/^üý½{÷¶wwwC&“Ün7*• ’É$nÞ¼ ¡P±X …BÖÖÖ»öü1çR™&''1== —Ë5qóæÍþb±èYòƒLGQãûS÷ÁÐ •J%óî»ï¦¶¶¶RW¯^ÝU(˜&“ ‹K‹ÈçóÐê´¸~í:þþ¿þý¡cÇŽ}ýõ×_ÿñëýêó:N§P(Ä.ÅJ|>©T årét’-’ý5×ûHyÀéôñvïÞýÊñãÇ?ßj³Án· ›8rùŠÅ"nß¾h4Š––444 ££†ÊÈÈ2é NæææŠ}}}7\.×iaÈÜ{¤ò3øÕEE @ñh`r8ét:~íµ×°Ùl†^¯‡ÃwÝ $“çèÑ£‡Ã¿ëp8¾ïõz§ñÉ  ý­VkV©TL.ŸR&.—‹H$Bs …ÂjõwžºT0eúÙr¹|ÏÕ«W¿ÙÒÒÂ<öì³HO? LOOczzÍÍÍàr¹hkkƒT*…Åb8d2 cff&û‹_üâ½………Aä‹5ʯgý~œ9- FæLƒJ@ezzo¾ù¦€Ïçwñx<¨T*°Ùlx½^ð¸<ìß¿Êîîî¯y½Þ?ÂÇo¨ÕÏ immíP*•àp¹È‹`±XH¥RH§ÓˆD"ùµµµyÜgÂéqÝX @{ùòå?kooWräȉ®®.zBÇÄÄ9‡'“ÁÍ›7Ô2rƒƒl6SSSÈårp¹\ðx<ùªòï FÀ\¹òÓ¨@P¬Þ j že4òà;ï¼ã\XXÈz^Á$àv»¡Óé°k×.ƒ¥¥åH0}XÔ³sðÚÛÛêùJ…¹\b±‘HÅbÁ`ËËË“ 9Œ÷E\}P¯|Éd:ÿüóÏÿ¶ÍfÃîÝ»k««Èd2HÓîõz¡×ëÁårÑÜÜ ™LN¯×‹x<Ž……¸\®ò7ÞZ^^þ$ h¤é æìÝËH‘7rÕkxAj-—Ë-ß¹sg~kk ét•J, ¹\@»:: V(.¬e|˜ÈA‘[,«©{Ïž£Z­\Êû#‹!Nc}}^¯w$ó¸àqdCGËõë×ÿ¤­­MðlußO$ð KKKp8´òÍf3$R)ºººÏå°¶¶†`0‡Ã¡¡¡¾™™™ µ rϧ2¤ÇŽªÝS/€ÍÑÑÑYŸÏWH$´`±XX__‡H,†F£éêºg¦„^ý]]]Ç,‹Áh4¢X( ¡¡‰D¥R @kkkë^¯w¿ÊfúÔò¸€r~d—.]úzOOOkoo/]â››@¦ooܸ±X ‘H•J•J…V+Ùøáv»‘N§144·Û=áp8~ÒDSÌ_Êä?(‰£‚—/rKñ¥R©õ………@:UÅ£òø…B ¥R£V«­uÏMýdà³Ùìægžy抾±*• ÅR‰öþ‹Å"ÖÖÖ0777\©T6PkR½gyÜ@5Oòº»»_>}úôK0 HJw¹\¦C¾T*µZ††˜Ífh4(ÕjÌÌÌ —Ïcll SSS_þò—ÿ²Ûgä*Mâárþ)Ÿ 2Œ Ø\__ßÌf³(‹4˜L& …¸\nC©T2ânÂ)UçR©*• &&&0;; ƒÁ.— «Õ ±XŒööv¤Ói„ÃaÌÎÎbrr2çÎ×+•Ê4Håû@Ò¬翞Û‹D"!ª,]/Õ©¢D¹\–¡6G€&¶Êåò}'Nœøœ^¯‡N£A¹êØGãq‹EÌÎÎbbbb(™L΢Üs<>a µï ‚0¼øâ‹º{÷nEíÊårX__lllàÎ;P«Õàñx0™LP(èêê@Z‰ÍÍMŒc||ü@`ä¾Lõù=ʆ êX<•J%Cq Êå2Í0", l6›_}îù¨:|?î¹ ‘HÄ*•Š¢mÑLž|>\.ƒQiù\.×vñâÅ?×ëõ"«Õ ±D‚T5ãW©Tàóùàp8088øf±Xœɤð€ÎìNZ*äáP¿úê«ßêíím¦J¼Ô`FƒÍÍMܺu 2™ hll¤+}ò…B!8LOOÏÍÍÝéí×IÛ%Œê³ñL&“Z"‘€ÏçÓÊ'ù|±X,ŸÏç “AŠk×®ýq[[[«ÅbV£A¹TB*™D©TB2™Äàà ÆÇÇG¼^oî^ýtÅN >äøàƒ4ýë¸{ßߎÕO=[ ¨õz}“L&£siþS©¢Ñh2›Í¦ˆ8ð…ÞÞÞËMMM0™Làr8ˆ'È (•Jp: ½Ž‡Íì$Ø8*•êÈK/½ô/;::`­&q¨.^ŠÕ»´´ƒÁ‡––…BØívzÿøø8ÖÖÖ Õñ.3 +Cx+䟉ÞÒìv»]«Õre2 …Íã+•J‡ÃˆD"‘t:Q«ÕÏ\¼xñ_jµZ2œ O&‘ÉfQ©T0??‡ÃQz£R©xP›U”ÇCõN€Îv1™ÌæÏ}îsÒÝÝ-¦§wlm!‚ ¬¬¬`xx|>‹"‘»ví*䌟••ŠØñßïï©ü ÂþxB…r²®®®Z­B¡þO* $‰§KL&SùÒK/ý^cc£¤­µ ¹Ù|ɪé…B‚Ãáxkk«äʨ-ìÛ Jù²‹/þáñãÇ÷Ö—x©.ÞX,†[·nËåB&“A«ÕB­VÃ`0@ À=áF$Áàà VVVfÇ; =þ yùíðÔ9üÆÆÆN«Õj7è t s‰D^¯·¼¶¶¶tæÌ™ÏÙíöV‹Å}c#bñ8 …²Ù,ÕÈ:ãñxÞéÐÖ›þ‡²­m7¨o·Û/_¾|ùsÝÝÝôô—Ë€tûûû‡¡Óé ‘HÈBD“É„••Äqô÷÷# %oÞ¼ù#9þHå?Êxÿ£¤~8…üðáÃç™F£étšÎV*ƒAÌÎÎn655Nœ8qV¯×Ãb¶€Ãå!#[5ýn·N§3:44D…³¨µ±?´gÛNÐ$¡P¸÷µ×^ûÆîÝ»™6› Ií¢BžééiLMMA¯×C(¢¥¥|>ÝÝ݈Çãƒp»ÜX[[« ½L&Ç@®Ml_¼_/T,/T©T=]]]ÏšL&…Bd2šÆËåàñx*Éd2qúôé#:ŽÑÚÚ ±XŒT*…d5Õ]aP~;ŸÏ¡6¥4…‡Înî×úùÏþÐS”îH$BS»(vuFOss3$ ( ÌÍÍÁëõÂåraqqqØãñüäêð£–ÝîÕOU0'Ož|I§×smV+rY²³ˆ º„»°°PèîîV™ÍfI[[tjò…ÒìSäŽíLõw'³§NúïÚÚÚì6› …‘h”îÝK&“p:H$P«Õèèè€T*E:•F"™ AVMÿωÄ0Hå? îÂ]ò¨@­~‘Õjí=|øp·N§@VöUjW$A__„B!d2L&d2ŒF#B!æææ°¹¹‰¡¡!ø|¾¹¡¡¡·P3ýºÄûIÏÆÀ5™L'?þš^¯‡ÕbA©P@<‘@†~N§Éd°ÛíÐj4(‹ˆÆ¢(‹H§ÓÀØØØÄâââOP+_ׇ|Du1ˆ*óÊöíÛ×m0X[[[tƒÁ ãÝX,‹Å¥R ƒÁ€††FÌÍÌ JQM‰¾¾¾×AR¹)6/eú·{õ³ðØlvó /¼ð-½^Ï··¶B"cÃïG¡ÊZ]]ÅÔÔ ,V+t:Øl6B¡íÇèèè–Ãáø'À¦ÒعGý\Ûaø$GÆáp@âÕdG©T‚ÇãÇã^¯‡T*EKK x<ìv;|>¢‰££ØØØ¨ŒŽŽþ,‹£fú?ª{çQË]uŒ^xáìv»½¥¥Ʀ&¤2$’IT*$ Ú²QÉ™TŠd2‰du¸Øââ"Kƒƒƒ?.‹n+?„m g%(z7€(”Э¥R ~¿}}}%©TZ–J¥hjj¢S¾år>Ÿk««p»\XYYžžþÈÕái·;Õ Ôõ+tvv^ïíí}Å`0Àf³Ídbks¥º"N<‡Íf£™K ‚@4¥kp:}[[[7Q‰mLc?jPºqãÆ†Çã I$°X,‹E|ÿûßßZXXX×ét­V Š"—Ë1;;‹x<޾¾>D£Ñ`Õô{QSþvïûõ€æ …ÂŽ .ü¡N§cØív(år„Âad²Y”+,--abbÍÍͰX,I¥J$ØŠD¯.‚‘‘8Î¥éééw@*>ˆGìô}X%êOÊ( …øŸýÙŸÝ NOOGþâ/þbêí·ßž;xð R*•2;;;ÑÞÞƒÁ@W°¹¹Y¼sçÎù|~UÎ=vÖô (®\¹ò§&“IßÚÚ £Á€T:P8ŒR©„X,†þþ~H¥R´µµA¡P@¥T"™JÑÄÖ©©)8Ž´Ãáø!€Y™Lª‚¹m>Í£t)PM‘ÅÅŹ/ùË1û'ã‹_üâ1£Ñ(°Ùlèééøý~$ x<ÌÎÎbvvöæúúz?jmÛ=ú)…jQç8pàsÝÝÝg›››ÑÚÚ &“‰@ @mA:ÆÁƒiò Ád"²¹‰J¹Œ `ppðT*å¬>[Û7¢ž–GP\ù ¦“jžœ8qâÔ®]»TJ¥ÇŽ@R¥¼^/"‘†††æ«!ß*ȽŸêäÙî•O)Ÿ¯R©<÷Üs ÓéÐn·C*cÝçCªšÌYXX€ÇãÝn'ÓØb1$"‚[[tNàÎ;ux½ÞŸƒ´jÔTÛÎ>j”A†iaÛM@´¹¹ùôéÓ§»Äb1Ž;FxšššB±XÄ;w SwîÜyw·q=Ò˜ø„Je+_xá…oèõzY[[ôz=b‰=…<‰```íííH$P©ÕˆÅãä¸ÚR £££Ž½Ú¬â8vÆ¡}ä¨yJ¨íK/½ô¼D"aïÙ³‡><Ùãñ X,RE¸\®ŸD£Ña«c§@]·ÎñãÇ«££ã³Ù ›Í† Hâj±XD¡PÀÀÀ …:;;¡R© V«Q,é°pq~###…¡¡¡—J¥‰ê³Q!ßNlkÛ^æ>ÿüó¿ÙØØh0›Íô>¡Pˆlúôû166†ååe§Çãù9jœþôú¹xF£ñø©S§¾ªÕja·Û!‹ ‘ÉdP.—áñx°´´„ŽŽFzšw(B±XD(B?FGG?‡Ã·±!ßGÉ£À]_âÁƒ_Þ¿ÿy•J…3gÎÐo¢¸ýýýØØØ ¿rß÷agÔ½sØlvÓåË—ÿD£Ñ4ttt ±±Ñh‘êY>Ôñ3ƒv» dX Ñðjªwfzzú-ʧžm§¶5ÛjÎÓïˆD"âÈ‘#àñxHAÔÊ/ ¾‘Éd&QóŒë5m—PÀåh8{öìï´´´ì¶Z­°Z­(•Jƒ(”JÈd2èïï“ÉDWWÄb14j5Ò™ ’UÓ?11±±±˜Ãáøjìž*_ß%:D‘@ôW¯^ý–J¥’wvvÒs{‘Ëåàõz166†ÉÉÉ›~¿ÿ&HÓ¿ ”ÐÙ>»ÝþÂáÇ?¯×ëÑÞÞ¡Pˆ d2TÊeLNNÂï÷£³³:J¥, ‘h• 9¾npp°222òV&“ÅÝÍ*;fú)yT¨Ÿò!är9ºÐ‹ÅÐÝÝ ¹\µZR©j$ŒÇãÃáÈõ÷÷ÿ#j‡O?û~½Êj‰;ö•ÎÎÎSÍÍͰÛí`±XØðmЬݑ‘‹EìÝ»"‘jµÙl©T ¥R .— ccc‘ááá‚4ýk¨…³•ò‡€ê‘¥T¾\vîܹß3™LšžžÈårdž¿\.#‹axxÃ@à+„"vn7µ ¨ãöiµÚc§OŸþªºšË—Ëäøô¾>;; ¯×‹Ý»wC­VC!S€Éd"Z ùVVVàp8Jo …)Ô9w‚¶ö©äPU>jÈg³ÙžÛ·oßsMMMô`Gê Ÿb±ˆññqLOOoNLLüäêØ)‚P×ÒÅb±š¯]»öÆÆFI»ÝŽ&c‰6C›(—˃p¹\0™Lôp ‰T‚H$‚B¡@‚ÇÍ`0x5¯ÿ±ˆ÷?N† LÓ©S§¾¦V«™Tª7ŸÏÃçóÁ`P=åÑÑÑ7J¥µBêS½;áø HÏž=ûßwttì±X,ÕÁeÚô§Ói8ðù|tvvB(B­T#žˆÓs{\.ײÛíþpCÇcò}”<ª«Ÿ>¼±½½ýœÙlîÚ³g} ÓÄÄ 2™ ÆÆÆ0666 ?@-äÛ©lÝ«¨Õjœ:uê7•J%t:x|}òØôô4¢Ñ(:;;!•J¡T(Q*ÇÃ,FGGÓÕ¯¾¡ã±5ý”<ŒD=Ñ»§§ç²Z­¦Ù=333¨T*4Qbjj*V-†P©Þöú9ä‘H„=666Ëápì³³³Èd2 ˜äL¯×‹™™Øl6èõzˆD"„Pƒ ×××1<<ŒáááŸTÙ=TÿýÌÞvyPО¿Z­Þc±Xº¨y}ét‰D ‰D“““˜ŸŸ¿U(&AzüzlÛ§¹w&~.—+}ç;ßykqq1söìÙÎX,Æ2›Í(—˃\.Gkk+„”J%¢Õ¹}©T ÃÃÃs,--ý µ&U*Þl>'÷ €:ÏŸ@´{÷î£:ŽE­þ¹¹9šý»¸¸ˆåååÈìììû WGµo'…šöêïïw¬¬¬Ä®]»ÖS,E±X …B===ô<âLµÊG¯™˜˜Øt8õûþÃ@½mò N eþ ---¨?Tãd2,,,`ii©?ŸÏÏ‚eú3‘Ô€ç0ÈLÝ"€™¿ù›¿yÿÍ7ß\‹F£ô€‰¬ê¨vjvÏØØXáöíÛ?ªŽm£æíTû¾ä¾Pçü±@Öú-jµZ¿ÿ~äI,‹nîX__Ï.,,ÜFí4®òúë…šêé“Ì¡:`*ŸÏû|>_´±±f³™<*V"A¨:©; axx###ïomm áî&Õ~®{’ñ蓼t:Ý.­VË‘J¥ôñê¥R‰bùÎD£Ñ _Ò¶6>|‚ÔŸúªþ¹ ÐÜÜl»~ýz»ÅbŸÏ‡B©D"™D¶:¶µZØ™œœ| µi¤1¤„E"÷å—_>ÓÚÚʉDPÈå@5ƒIÍîq¹\‰þþ~j8E}•ïqz®O%÷kêã©J¥ÒQ,ŸxŸ/ær¹,ŠA uNN2™üð¼ƒÔ3–Ï?ÿü7ìv»Õb± ¹© ™L››µ*àðð0œNçÏ#‘Èj¦ÿ±®ò}ZyÐ(€•Éd …B¡L"¨¡ÈÔÏb±H­þŸ-€6ý‡þ£G^4077ƒÍá Ð ÃÃÃp»ÝÔ¸Ö§ÂôSò ™@ …BeccƒV:}q,‹ƒÇ‹ CÓ¾õzý‰óçÏÿžN§C‹Õ ¹\Ž@ @Oìt¹\p»Ý‘ÁÁÁãI÷HäAPPN¥RéX,v×°X,0 H¥R!$½ï³ÙlÛË/¿ü¯›ššÄ¶–²Ó7E(¢Ù=£££Å·2™ Å]Øîô\åê+ …¢ñxœ.ý$„B!- ëwRövÉ]/]ºôG­­­»Íf3ÌÍÍ( ðƒ(—ˈF£ÆèèèíjCGý¬Þ'~߯—û@ý¹¹iŸÏ¦H“èC’d2D"‘ËåJPKí„ÔÓÖx===Ÿ?vìØKF£6› <>þ@Ô!‡+###oãî#瞘*ß§•{VHõx²2HÇ. å÷ûýÑh…B᮳qª'yël6[7È•³SV€îTªžÐñZ­–°·µA©P ´µj «žÌ•ºsçÎ@ˆžÈ*ß§•Y‘T!%·²²²¶¹¹™£NºH°¡¡†µoß¾k =½Bu(s™L¦õå—_þwMMMж¶6õz¤R)«Ã+ý~?œN'œNçϪÃ)¨~ª—ï©“û½ÿHg2™Ðüü¼/‹Ñ'dT#èt:´´´\2{±ýV€vú¨¯_¿þ¯wíÚÕeµZaµXPàóûQ(J¥044—Ë56==ýjœOE¼ÿqò €ò’¢ÓÓÓ‹¡PÔiÙ¹ ˜L&´··‹NŸ>ýMfx»¬•¬â\ºté[G½ÔÔԛ͡P_ €T*EkžžÞ¦R½Ô(Ú§Êëÿ°õ+Ÿ’m ¡ˆ•q_ €ø­·Þ2 g¯©© <étÞµ5˜L&œ9}wúûE<ï?Z,–“ï½÷Þ¿õx<κëøxPúY@hµÚ}çÎûãÝ»w¿¢Õja0 Õja2™Àf±ðû±¹µ…ruÂ×ÀÀ†‡‡o-..~P½÷§2ÕûëäP©T*A”@Z-&T‹Å–~øÃ:Äbñ‡Cèõz°X,lmn‚ÇåÂh2ᇋññq‚Kz½þÙéééÿ:88øw333ãødó[©û)²X,]===¿ÑÙÙùªF£‘P'Œêt:è´ZT@ V•‡Ñ×ׇ۷o;Ngýú§¦Ä{/BÔsøîë5Š˜€@€NM8üÊ+¯t·´´@§ÓÑBƒÁ¥R‰D"™™¬®®bkk ‘H$ëóù~9;;ûîòòòÀÜÜœu)ØJ¥Âa0Âööö¹\~°££ã´Éd:*—ËÙJ¥r¹2™Œ>}¤Ëa#@$F¥RA @__nܸáîïïÿ@²{æ° ‡3=j¹_=>0l"F hÐ|ôèÑÞ+W®tZ­VhµZp80™Lh4èt:ú\¯×‹P(„x\.< ‚HdÈd2ðxaË IDATxœí½i°eÙUßù[{ŸsîôÆ|95R©4"„ƒ‘…A–ºÁ›ŠnGØ4nG7Ñm:¢ý ¦èvÛf “ì¦R#»- (¹J’ªTªRUÖ”Y9½ùNgØ{õ‡½Ï¹ç½Ì¬ÊÊ¡ò¥]+êÔò¾sÏ=ë¿×¼ÖUåuúÏ—’ëq’¥»§¹Vº]Ußú”Û€cÀ"°Œˆ (°ò,ðuà!à)`ó¦]õu óÿûUÿíuÀM¤ÛÕûªê@¾Ù&vÉ&)6I°6Tï=øðè½ ¯Õ£êKààÓÀovsÎkO·*îöÎTÕÿí¬Û9Ò_X`°¸H§×%I3¼ƒ2ÏɧòÉ„2Ï)]z€ˆ ˆOQ½_½¿ß{÷1„O‘†ÈgnîÏ{íèV€¨×¿ïûÇý…¹£ûfqÿ Y¿‡ˆ¡,JÆÃùdLYF¦Œ(¥/ñÎ#O&BwaN¯‹÷ÞãÉ÷N¶‡ðÎý kíÿœ½©¿ö5 [ G}å~Á$É÷ßvß¾ã8Y¯‹K™— ·ÇL&¼:’^ÛII«Šª(©Òœ2Ic(¦SÔ+¨b’„$MI²”¬ß#=z˜ª(ìæ™ó?±u~õ›Äȉȣ7û‡ßHºUpGUV¿¿°¼øö{Þþîǃˆa{{Ìh4k,/‚z‡+Kʼ œæH\òÞ9\€˜ðYõàÇ;Ï`q¥CÙ8{þ-§ŸxêO\Yý¨±æ“7ñ·ßPºpGUVÿöÀ±C¾á]o¡7ßÇZ‹GX[âö>HÖIQUŠ¢¢˜Ó<èzU¼sø²Â$ ÆX  ¢WŠI&µdUYaSÇÁ»n§¿´pàä#õå$ÿ ùÜ;7‚ö:–«²úøÁ‡|󷾃´Û!IT ëk#Þǃ÷de¹Çָ⥠cέÙÚƒÞ;lYbl‚Xƒi¤€±–¤“a¬e¼± óû÷á§œNY9~—ËO|þ ¿™u:ïAxú&Þ‹B{®rÿtqeéoz÷[Éú]Ò4Á¤)ëS¾énã¿ø®»¸÷Ä©5<ýÒ˜O?|žiᙌ+мÄX‹C‹çÀ,ð¥ÜCÛMètúä“ \XcßÑC ×6X}á4ï¼íÄú鳿(è‡@Š×ö.ÜX27û.Gªú¡$K?ú†w½™ÞÜ›$¤½.ã‰ã]o;ÊOýðƒ¼ížEK–Çöwé÷ÓÀp5ÏPõŠWbê4ÚõžÁÒ"¾ªØ<¿J•ç¼ð¥ÇX>v„ß÷m¬œ8òª¬þë›u?níUÌùÊý“Ûåƒû!ëvÈ eÿÊùî»YYHwüÁKë%ç7 &SGUyœóA÷WÞUø*0ÚU®ù§..ü{QÒ[Z¤Oyî¯cþà~ö?B1™râÁ7’u»?£ÞyïÅ ¥= ïü –æßrôžÛñªØ4 y^q÷û8q°·ãóg7*>ÿØ&/ž1O)ó2¸EIUÎ]Q⣑<ïÎUxç(§9Þ9Œ±tz=Šé”|<¡;7Ç;OöÞÿ7¯ù ¹´ÐWõ=|ç ÒNlbO LbQI8y.g\x6Æž¿|nÂüÅy}r• «C¦Ã)å4§šæTyN•á(Âë¤à)á)‹œÉÖ6ݹ>‹G²úâépŽ¢ Fá‰c¤YöwUõð͹5ןöœè½ÿŽÞÜàmûÀ;EÄàœ2åôœY›ð©GVÙ7Ÿ1Î=§/Œ9{aÄæúñö˜|<&ŸL(¦SŠÉ”r2¥˜†GçÜ®oSÔ+®r˜¢D:½.ˆ`“c ÛçVY8t€|2!íö¬,Þxé܇lbù¦Ü ëL{êõËö™$IƒW˜N ŠiAÚípîü6Ûãc Uå™Nr&ã)ùxJ1™'£„b2%ŸL)Æʼ¶Ÿ\üUYb¬Á$ ®rTy"t}†ëô°I‚ˆanß›gÎýð+´]Š[”ö”Ecä›ç–—¨ª ±W:&Ó eé(&S¶Æã) xçƒŽÏ ÊiA1™PŒ'A ŒêÇqì¹óÃ÷*U@…b´ÛÁ;ÕÂP:ý>6ɾAá^yòµ»97†öTý}Y¯{ošv(óƒØ‚ÑÖ!7†ª¬cÃç£*+\QPæy#êóñ$`4¢OBðrÌä£*K01„ ‘a²="édx¯ˆX’noÉUþÄØ×p=IUß”õú) Å´1TÞ3Ùb³ ¼bÒ$DóTñÞáÊÛwyN>Í)¢ÈÏÇÊé´I_ Ue HÀŠÖ‚XÊ¢¢,«A°>žâ¯‰ÈoÝ [ñšÑžðެӡ,C`F˜Ât8$É:¸¬ÀX BHàĤ+Jª"ÄÿËI°Êü*vÑ+Òƒ©Ô†¢§A=‹I»oºâÖ¦½‘ÃIšC¬(ðÎã|Åt8&É*lš4âY}ä)©Ê*}D·Ï_dí¿â÷‚ÄXÄ$85øÜã´@Ä`ÓŒ"÷˜ªÂ{Åk‚$ö À0¼·âµ¢½€ÄˆCUTTe8Šé˜édLÚÉ›^A(ïªBz×Å@Ï«f< bÁ$áÜÆ‚±áQ ÞÄ´‚áÆ„&©`;c !ÔÞ²´w :c–½÷TeˆÊ©W¦£ Óñˆ2/°ÖÄ‚Æú>uŽPØ|ïr$‚˜±‘lXý ÄDpH´;¤6 b’E–oÀxMiÏ@AU®¬b§Ç¹ u§Šk}xf©ÕL¿r拱ˆM[HÀ&3HÈ"ÎCñI㊄sìÊ3ÞŠ´gH£ÌWõÑ…ÛuŸå¢'WHD½M›E†‡×A 0„•1 ”ÚWÿõ{ö DÁxÜ6màºÜg‘Àì$ClŠ1i\õ1ØX-t)) &ª…Z DŒÔã­L{ˆLPÝpe…Xuü•ûð¯pnĤ˜Zì› lŠ©W¾I£¤¦–3 b£h‚D9"Óës7ö P¯ÏW®ÂJ]¬©¨¾L÷Ѝf~IXéùix”( ìL Ì$€µ3mÄl‚¬]¯³h/Ðg}U‚˜ ûÕ_sºEl`¾$)$Aô×6Q"`m”3c0ˆ~UD° ˆ*@0 ²®èêõùÝ7ö„/{W!&Á{Ô«ÿêD€˜“¤Áâ Ï f¢¿ýïM< ‚¨ÿc0₨_Ç_ShožóêœñÞ¢Qü_¥c‘$‹Ö}÷b³xD{ÀfÑØ›×°ÿµ:0-Cgx=|½IN£þŒ÷î8¯î<3½n3¨ ÀGÖdÓôÇÞu;eQ°qú UYb“„¬×¥ÓëS–%ùhL9™4պĄÍ,tkâcÒ<Š´bý’ì %‘ù©DÑ_ƒÀZ v¨ê—ٺٷèzÑž€Â_š4™zﺧ¿ú$ùxJ´c=˜± i·CÚÉH²”ª¨-3æK]ã'6¤yën4MË+è-c°62ßÖR@£*¨;åÑ[>Ü¢= Ç´rÏ W×ï/ó°òC}@ ;_âÊ’|h°iBÒë“fT-*6$kL-úw3?Öμ“b%|á#A Œ=Ï“zëG€Ú“@däªêÏ‹I~¿M,Þ9z ó$YÕÐ RåE( /K¼ŸtC½¾±󃚜~«º§Nò4*#>+ÑÚ—:„mRˆ€ÇÊc×£(: ®Ê®ý~]íMêýŸÓéÙÄ’d '|ªJÀ§¡ü»œL˜Ž'T…Ç©ÁU#`¬‰Œ7³NŸú¹ÌŠ;¤IùJ#B"pføÕú?zO‰ðÄuù}®CÚß`ßmŸElU˜WIßÕ¹g "Ÿ.FãÓn÷¸zO’¦”EhÐÕI½&MqN¨T%x­Ãu±r‡XÂEÉ C"C™W…•ºÞ£nˆ àÖùÃÇkK«…r}Š»¾ñ“,Î{*-¯é”ÿI‘UWU¿j½ûY¼R–qæOå⊮™+Æ ‰Å{ƒW‹6å[5W¥Iç6!~F$DúD$bbø± (Ûbø«ÿAŠqóh²¿ý—áøïbÓ;qÅ NoözoÓ/•Óü™b2!C‹vôõMàZ˜hâ 7&´yÛV§‘ÙÊ—K€!VúJ‰øÑˆ(0Äðk"<Ñüù«8 )©;Àpþß‘¿á¿‡»~L‰ú›«ÿaï`U½ÿYï<[ç.D†Kk bM8jP4Œ•êR®]̧ÅüÙ!-@4zyM„Ÿµ/ŒïSÙ œ:ô¿ðÜí?JµøR.ƒî[¿wUÀŒ~S¬ù‘í kï-ÆQ H…ÛI Ô×ïÍÔC`aÛÀÚ}ã¥m2ìCè@±üsÕ+m ékÑ Ô°¾ð ^8òÓ”éK¤²ˆ¸9Hö޹7`øòTŠÈ?ªŠbsíÅÓ1¨Ó”fñe,¸ò^Wþ`ÜLãË ÿLc‰Ú+øS-PÊ:OûQž9þc8»Žõ ˆÚ«º7’n|ÑóO7NŸeûÂZpóvÓ3þ2«Ow>ׄ,UùÇëm)q©C0XíSÙóœÚÿOxüŽw³>ÿ‡Ÿi°GéVPD~É{ÿãgŸ9yß‘ûï ("×4®Ö¦´æ¦FÁ°‹»ÍQÿ±´ÎÞà Mp¢¿âU?‰{9t)Rõ”µ…?ä¹Ã?E•žÃ’a|ŸÆ‡Ü£të¶Å˜GËi~ß¹§ŸåÀ·C°ª»ƒÃ ‡:L«‘ÉR"‚CšEÔS׫,Î'èdë¥qÅÏ&iòòõ(EâÀ¿çÌÁŸg{ðï<Ö÷›¼Å^§[ !Æ|d:qá¹YŽ3}Ã0 jë­`P<â·E¨M<¨‹Ÿ ²^C:e©,2Ççÿ·_8}Þ$饯D?JéóizßòGlû ˜*’[‚ñ5Ýjx@¬a²µzÇüý@‚wŠâQTj$ˆ~õ ³¥G|þMæÏ ,wíñgŸø=Öž}âÉ$IÉÎ+E+ÎÐûÆ™ûñ/àŒÇÝ×üf\ºÕp˜ ôÄùpŒsç˜[Ù&¡Ã—m©™­dQê(KC·cxççùÒç>dz–$ë<·»êo W²øÑ?gþ›Î@epå­vg´·-”‹i•ÖL±BU”l¯®Qæyh&u"žãñõj¯_»Y¬xå=ï\æÔñÈ‚$1ˆÈ%÷ ÒIBö/“~Û“PZÔÝj·p'ÝjW¿A+£ ÆÔÃds›j:]žÅèpÔL§a¾§**|Uñß¹í3Ïò©ßü ,qáúEß^ÌÁmÒïø:ê^cooЭØeb9Wa­Ðíu(â¤0õA´ã]DõªõëŠñ¸ ÏG¿ÿ(ÓÕù_þ?1nª‚ÁÛ»¿Xó„ô=_Ã؆[|å×të*¯šT)ó Ksì[Ydu}J^T¨3˜Ä¨ÁÆâõ†2/Ê[Þ¸ÈßûÈÝ<üð×ù•ŸûuL±Í:õY+vï&ê æÐVXýùe<ƒ[n5´#8@HÞ¨÷¬ž=ÏÑ)oyð(’¤ä…0Ê•áDMâs )÷ݽŸïú¶ƒ=c(‡«ˆíü€íÌHù¶W]Öe š¶±X+pI¦Äœ@½›°°6~¸oü[õî!±i)½’âOÀ¼ñEúo»p߇|ä‘GùböüðYPƒ/-¹ËcÁJT[Q=Õ¥NbXïl³Æ&wÌÝÍ{Þ÷~ZûüO”Zür“ŒŠ= Õ7ªêwˆI¿Ëf½ï²Ý~7LéªK¾‰7;‚¶æüDZ޳ÓÕ5íóÇ-cš×u¼ ¼uö)ûßý“|üä¯snòtç‹ó@,'‹ÒIjEàpïKÉýtŽÞûøÜCŸå«K…Ça^@Mzå{óaÛ|kÒ_^Nç÷cÒ.h9ëõkJºf<7 lF¹\B0·uïlåøfW•Øþ¾.¶ónŸßí‹áO«É¿ä½íw‹ß}ç׿òO^´?òàG©´dZ#\œqì}<—Œ3P }3`Ð_den?_¼ðÿæ¥C¿Ð›µúaï@€oþ6&ù€M{Ç’þ<¶·€ØŠà¼'IûØ$|3ÑêúiføÑ„ vQ0ú³óÃÆ’¢A*”Ó ª>´e}°Öj9};¾x»~íøÔ½ã«éW7¿Äwú¿A–u˜VSrr‡¼:œw¨Ó°ï@apâÈJSñ…µÏ1¬¶Y6ó7Õ¼Ù˜þ&ð÷€¿nl*¦ÓŤ]T…j:ÁX¤]ƒ·J’vâ>‚@#fgÕ¾;V£ Z P@ZEuý€zŒpä뫸²˜ý€`Ãä4“vGn̰Êpêf•AFC BEDðÆã£”ZQiEáK¶ª-ÆnŒq×6 õ’ «WA7 ÇxЈtï´B;“âµqæå´Àfݵ z߈A…™gP3]äâ1ƒÍä9ÿE) €WÆkç(&£¦˜T[Õ¢*±Q ͨ|Å¶ÛÆ‰«k¿#˜ðhÄãÃ;x<[ÕSÒã꣊"BY^[SÉk €þK೩›Ô…[u/Çlõ¶J¸TQW‘oÈSºós1­ïºÑꓵ›ÓE†kH[kqUÅðÌiŠíÝÙÌÖ}…Á q€¨4¦GÍ|¢Q>{îшÂUVˆUU1O^ùÃ/C¯¾ø»À÷ËÒøíaÚ¬Úºi3E‘G!Hã=j*D-ÞUä[[c¬ìä)¾raN€™y;Á)a¸„5t2K9ž2:Žb¸Em5(†ªATPcC È˜0a¤þLÍø­¥€ŒGq¸(<^âÈ›(šÌUÖ VUÅdrṁ€ïþ>ðˆ¤¡³.¼ŸÍÞ5µñFlجûøê÷5NQCbP_‘oo#Æ0wp…Þò\0s‡s¡DlæÔ—£àCóhÒM0†ÖØ|áEÊÑvüh4ÉD@ ˆÆ‘sõBœ1;Ìl€+½®JÔFì\ø·k0úš•˜7ß«ªÿä½"2kÉŽ-\ƒFË]Dêv 𩵕_Ÿ±±Úgµ}®,˜¬oPå9ƒ•}ÌZanP UQQæ¾ 0F°‰!í†ùhÂú /1 dš9ý4"| ïb7¡©¦9£µ ûY:²ÂÜJŸl?¸ty(IÒ„|Z±~ú<ëÏ¿D>ÜŠs†#*cs b‚;hãûM¡³B´Ù«( ´ÓÖj¯Yïšgá•k Ãæ–ÖûÜ‚¼¼T|:%/ò—ýÜ«¥ë€¾ªþŒ±æ¿ëöÎÜY€M@pÎS%Å´ œ–q¦‰+?öâa¢úÍ|Ÿf:wߦÖ?–|‰ªžrvÕßÍýw-9ÂüÁƒ –—X\™'ËRÊÒ3™äãœig 6EÅâ¼¥*Ê–ÛV¿i‰{i EÃlïÛÄû/Žíx¢ Ëø9ï<[«¡ºË+ÑU«Í½KoP ¢¦ ‰Ö«¼–6¼E£ P7¢Ôõ‡"€Dæ·ô}cˆÃˬô^1þ÷Äêû€ç/uŸµ²t8ƒÌç\ï:Ä«ÀÒUÿ‹þà]ËÇŽ±xôGï8Ì÷|û¼õžeÎnüùWÖyúù ¶í8ØÀªJIsÅûZ¿×Æ^íÔ!˜Ý}ýaÖ_ ˜Ú`a7"ÂSšýƒ7ƒ6ÕŽh¸©FcBf¦Ûë“IÓr–€ÆM¦¨õ½ÓÈ|m3§1hÅ$„ªb»s˜$½­þ7D~„ )RiÈÞ|”èðúö^5Tõ{m’þàò‰,:È¡Gø;~€¿ùîЭS)lN„3ë“©#É+l“–ˆ {ïØˆ¡eôÑD“460Pv&ƒÔìüüÎó´Hj?2×(¦ "³×õѸ‡$`³ÖŸÔÌ÷8ïpêbg’ΤBƒo+ŠX`³Ùâ!ŠÉÉ€üðÅ×\XÌþ1Ýoy\ÿZÄ«ÀÒ ª?xÁÊ~z‹ Üß!ÞûŽýÍgÊJ™: cÛj}^[÷’€q´·c›EMÿBìómfúÌÀ0c¸‰¡à‹¥È ;ÉÔù€ø‘TGÙŒº]“6F ÷ñÞ;ª¸úk7Ï©k1<¬v/n&¢Tñ É`¯ç’r:ú"f/H¯bác_À¬LÐüú·—_P½Í&É»ç#étèÍõI:kCÏ|×2Ê•Ï?9â©S¦yÓ£ ^bë–¡Ùˆ¡T©‹)ê˜~kD­*v¯òúoØ-ê¸BxíÇ?fæZÔŒ¿‘:ü¼ã5an\m…;õTZá}˜ï[!>Ö«_ÔÌT€5ˆ‰0)ÙÜådø@ûÝV‡…{”Þ_?‰Û¸1­gWUýÆ´×_J;]Œ6I8¿Qð{¾Æ‰ƒ]V·*ž<5âì¹ù´¤(U驪0É«ªIÑVE›Òª%^u°¨)ö¨Å}ìiì„™'¨ ZïµHó¿æ¹ìx?êþúÏT #fÓ( ´a¸S‡sAh|]ëùÚ>0bwÙ¾ù­¦7À@˜ê0£÷íÏÒÿàø­7Š®Nˆ<à½#ŽèzT•gccÌ£_ƒ¯œL©*O>)™N ¦ã‚bR‘O+òIEU)¶“‘ˆ £ÞbAg0újÿ?¨Uð#…*-•ÜšÞ’u…P¼ÆFç·c@Ëý‹ÿ¸; Øò±¥©ªÝÀ cS“ï«Fÿ{ßQükK-¸øž%ÁÄaÕùöàn`As;í|Ës,þÔç‘DÑòÆŒ\­x¯*!ÀS:ŠIÁ8™RT>øþ Ué(óŠ|R2æxó+ó,N1IÜ#‰»r›Z„CøAêv> ií Ý]ª8® ªÅUŠs»À4|šDN<ñìêëE/ºãu3H"®zm«ÚŒÛÍt¥Ã ªç•¯¨|…W׈÷`ÔσÍãc `!™gÃtA:ÒÁت²$¹=fŠsóû HZÜØtÍ«>ûÒÐ;½ Uéɧ%v˜£jHr‡+±CòIDATØâu•§ÈC<>ëuèÍ÷ñN©*jpßÊ<hˆu÷Þk€ ÎÓïQÏ[‹±ae›T°Öê'Dc; SªªdZMÂlžŽöê­ÃÓÑ/ßáþ±Ëˆ °“…kK$L®|…ó•«šR0gkd¾÷'6ˆ~ïÓC:=Æ]M3̦$ôò7ÏÿäC›…®ù·ýÁ"; +]ò*ç¶Á2°sî÷Þ÷ǯX,p5ðºIÈsÅŽ ÄäT’i¬} “6Ê¢"ÍRœƒs/lPæçÁÕÍ»˜™ 1š×lÒ³MCPÈX6@g”•Áu‘¨´ê±òÀÿKžü ^®â¼£tÃj¿ïeÜEWuÇ3+–Tæ;n[¸ÒlS¸‚Ä%TQ xçQ=„(¶¼@^¥Vê㎥xêÎÏ3\þ"ŽrºâòîôgóG,Èeø§!µŒšYTÁ¦L¨˜· ì_9fß8÷ÿ}%f^ ެ˜¤‹«4ˆw,Y¡Ø¤Š;+HÑ¥²]唥Ç{¡Ù°AêfŽ:Ä>]F›„ÙÑ…4Ö`Œ ÒÅÔ.#;ÜÁº@5rçRΟÿ,?ýß¾Ÿ/ŸyšêÓˆ1œ›n2ª&Dí Kgåjé¢X1 ’© ¹{ß·â¼#ÁR¹°ú+_Ὃ^£o‡†A‰v‚áM‹ocùÀ2çÏ<8ÏÔç˜2G°‹âæÃõÔYÒim˜Fæ«z –ÃÙA †¹ç'yßÑïá‡õ¿™o~ef^ nCÌŠÉz U~XPæƺ› "Ý„GâdîX9¡Dmõž¥$YŠM-6KȲ“Z’$qŽiãÚ ô>ØÎwÂfÕ‰ís¾Øäžü}Þ²ò¾í¾ï!I,iŒã‡½LØÊ„XB ŠIêö]âœ-TE0ômŸN6à¥ü ¥+ƒ paÞ@p{C°ÇGoA­esé îcâ&|ð®`Œ æšH(ñzš0¹ðªi" F„ĤômŸñxÊÏ>ò?òüÖÉ+ª{õö‹IĤ]š]µ±TNpªˆQšø½±dÝŒ¬—‘u;tûAF§×¡ÓKI: 6 Æ`ýÖf.ºp•†ó;ÅUA½Pâú!‰nJËÍ6€øÊ¹G¨\ÅcË”®``æ˜Kç觃Ô1&^sìjÅj¨ Fk0Þ{¶üZlâ½§òeUfóµ«t~bSR±lLÎ#F°Æb¬ ”F † Â &–Œ™&iVÊÔÏ õµh Ò9¾pêÏyôܰW8“ðU@ÄÞ.&E’nÕ˜™ÞÞ±árˆýß÷ ·qð¶åðC츉΃óŠzÁ;¯Áû°V|m€Kˆ b B OLÀ€´Ü½È2¬¼:Æ%Œ‹ÕvÅH‡¤IJ’¤t“sÙ<ýt@Çv°Q5êǺ,MvÚu<¨öPTC€Ç;*_†F­~©ÆPñéõç8ÍóØ(uŒ±$Ɔçb›÷¬Ôcqãóúߢ¤2ÈŽ×,d‹äå”"/åC®„®B˜û$íb’°·^“©«w銆›â)óU”{C{Wá¨õµj­Wgþ½Wƒ¯£~u†©o¾4­\¢!U+,Úè~t¦ÃÁH‚+ëSÏV¾…Ù6ý&Y’‘$ 6±XkÉ’Œ~Òg.§k{Á²—ZØÎ"ŠQÁD4‘Y ×å¼Ã»Ø_è4hñßJŸ³“` Gd¸1kÂ,ãÃlëm€„Ï`uÕñ=¡¤Çút¯¯Â\aÝÈÕØ'LÒEl§¹^o·>+ýJP_àü˜É¨¤,‚o^Wû†ˆ_û y‰á±¹ßAAblÂõiþÝÔÎÐØuáë,c:û»¢*p%$WØnðª°ïÈ?\9(I'lÀ¬ qƒF#ê-×% .eáð>ÜH|ˆ÷×òÚk ø(¡àRk±’Lš3ëõ 0ñˆÐlæØDü¢¤H:ÃÀ ¢ÊÉ¥ p¡ÙÃ{skƒ°ÆRšŠ¼ÈÙ–-R“Ò³ýà['=¬ØFiÔˆš@ Â4aV~Xµ1¸$5˜ƒÝѼ6Ú0²®-lê Mü²h«ÌþvV^ÖDBU‚÷x…£ ^0æ°¨5Y¿©Œ5õ–l¦- Rб†ÊÍôz¼Ò°’ b¸Þ˜)‘(PâÊBñ.ÎùØ $ö.òÝ9®ôPEØg¾À'¾a¾‰{ÔbTDÈ%g[·1ÆÐOÌ%ó ’‰¤5)JÓj1uñQëîYƒH8<>.šX3PŸ¸B­Ó@Hsަª‘x3) ^Ñô†@Ì~`ÉfýÃB•Ž$ÍŽ\a¦!¼W–P•A쥙%í:„$ [²Ñ_áÜ*Ÿ…uw†wgï·=´Ý¾ûc02Áª%+:ø\×áR‡MâÖ°ÖFCJÔdŒ¡( 6eƒÌdÌ%óÌ%stl#6ˆûø­ÒV Ö„ªâY½`ÍìÀd/>›†FxKÛP£;¤í£– 5(LP;Ü( pDŒ±&ë…  Âlóźd+Áf=´Š1ž¥}lâCeŽH`xå)‹Èü–Ÿ¼‚ º}ô§ÝlÚÛÎhí%$@S½]ó߃x!ÉSüŒRp©Ã%Ž*©â®#W$$¨=¡¢d”8/†ží3Ÿ.0°ƒòAbÕ¶AøÛÛ㢠£i@Mì%xᵚ¨Å=µÚÐÙîå;Ô@ MêÛƒ–7LȽ$LÒ úÞH8E³'oBùÕ˜jtrû Õh ›Z|å© ×ʸՆtm4E·¯f|4Þ4J‚zJ‹DiÛ^äÍš•öykt¬è8ÜIA“péš(j]Ø­¾©VÂ6rMÿNÉ“³1Y'5)sÉ< É"]Û .¤‘8•l¶âfÑÒù-&6+:ª€+}—m°C4j ^›Fé’®œÞ•õWB @’X¥¯¾Â. åõJ‘¯¢UÁp}‹áFNÒ1³¾9ZŒjŽ„šùµU«‚ÀüÙà÷Ý Ø! jIÜ2Æt"èv\iÀ/õQ)£XÕT‘DñÖG+=ZÞq•ͯ”Z2ÒçåƒtÀrw……ΉIB>´Ëʼn]C±Ì\/A¼‡JÁv‚ŠâECyÚ.ï-UÔìZÚ¸`\éæöW €$û>3·ïŽã&í I‡àŠ…Ú¸rë ~º‰ª;qv@CKU1ž2Ùž2HúÁ¬¹¤Š×Y`È+!„ª!pRB…Ù ‰úµu¦ˆökB ¨—ö'Ó°Šªp/ÕĬì:%aãßú Ŵݵú˜ÆÇÔN9“Ÿfí±ÐYb¹³ÌÀÌ…JäȉþþŽCÚ†hx-¦íï·þ]êM±ÍΠPTS"Bf:˜*J‚ë p‡lÚ¿Ó$½(ê-¾“¯?‹–b3ÂhõTQĪJÙZÒï㪠ë$_j¬éÏ•f¤¯"¿.»j<ÑTbs¥§Y‘»øŽSOG:í X,0¾}‚î#¶o·ÙZù˜Èô¶TˆïÕåŠÐú·ø¸Ð[b®\býüy*­X/Wú-ÕËe;KX1d6e±··ªµ³¨_ó:>—rQÐ6¡âv˜Xè$}é€Ã Kl¯{$P߀˜ã¦3‡I:T“5òsO…lTÚkU÷¶ôe,öØ8·ÅÂá}á&ÆùÌðhÛZ{A-Q.-1_3Qj;‚h3Õ`Q 4'Ðî2úy‡ôÒ)¿†Z9«Y¢² Ñ(B)ؼYâ.ûv.<{*Æ%Lc‰DÕ°ÃÕ$`V,¤ƒWO'érdî+Çîá©sOáyiÅLüíÆ„Ñ0ÕåtJZ ÷ØŒäLŸGçf–®Œß5«nž¥¤fLž½SGTCBÏvtìOqßáxäì£WÂÚ+•:0¶·`A•j´Š/'HÖkÒ”³œ|-'•Z©V•²zj´ßd&Z«wÇ͆ &Dfb^‚zh —vãæCPÁyO7MùÀ¾ïúüéŸýGFÅ6ëù”ÜÕÖó®/~Ù[ a.™Ã`ù¦£ßÉ+÷ã- âân£aÓšñ;Üɾ’s.?ÍôYÏÆÖ:O¬ý%…Ÿ0)s¶óè¥Ô·T2Ø-ÍldTXéÍ“™Œï}ë‡ùá¿ö£lN6®h‹Û+€XWMÖ±¶ÌWŸMMÖ [j×XŒ±ò€Ë:f®JÃp}ÂÚ™-.Kµ>ó%˜Ð¬fÕÆ¯×ØT«_K m§í"PpüÐÅ'ÿäã¬Ï²¿C¯*èÊËó[/z¨c;T’´ä¹ÑiÎçx‹{OcœÕâ¹–í£ÉžÄ„ÃKÃS”§¡|ö8ÃUAŒ')'ØþZ¸É6^‡/èÂÚ“’©‹å³ëš… @aCÆ™ð/þ:Ÿšÿ´˜ýî^™¯W STùÆ—GkÏ|nnÿÞ£¾lJµ´Öù¦uÔîZ nÔ:~ý¥M²~—¬—†$Ió jd×+€Öë:ОµÞŸb$Ç¿‘Ľ“Ã=˱¾ÿÖ*ÚÅàãuç{ñe˜"Öaš|…“kßGÞ&ï‹©Ù:I3cz ·²•:÷oR. ÏqvõÙ¹"ù«w€2p%éüªÑ:ÅÖÙ­Õ¯ý#¹ëùßî}ä1ÀÕ´kõ£0ü¹+Е—¡+5G`Ÿ™¬?ó««Væ¼õ-&íµÞ6©cu”olW)«§¶8xÇ26 =4Fž´W> ƒÛW#æãòFŸÌnFcÖ—íI¬@lÒ¦>w›.ò%[×Ð6:›ÏNs&刮öíí3cl¶ µ¹è±q×â5æeŽè›jœ$åè%Êéææhû©_ô æ™#fú;â»ëq°ÕÅ×tE窟)€ç!yhºõÜïl<ÿù‡ŠÑùÜØ IRf•»ìÌÜ™P0R÷ük)¦ŽµÓc¼ AŽ:Äl§¢|Wev,&m½çk¯¢®•Û}øËõîba³©Yo]%\ŸÛמK¼õžq9f;B”dKV§jwÆÔÿ¬ûI1!¯^± &ÉPõL†§žÚ:÷•Ÿ/‹Í?sJ_=}”ò‘£È hz5‘ÀMà H}9Y­ŸüÿNõ–ï|ÇààÇ; GI:1’DYï ›'ÿYIé-ߪ£Þù{2r¬¾4eùPkiŒÂ Ç/Uy±Î¾Ô{—£¶§p¹k¯¬ËÙµ×R÷ô5¸Új73ip);ÀÄþ1AJ†ü†G§U>9yf²ùâ#U¾õi¿û Í®%ÕÉ}¤ïzÄ_t]×BW ÕϨÈ{×€Ç ÙVïÏŒW¿öÔdý¹·dóGîí-ßv8›?<—Î é-1=ÿ£Sÿ‘j¸Êü‰w’ô½/FÈǰv¶bqÅ’fÒ¬h©"^vØm}Ob‡å/€¿—ë·.“Ö¹wú‘4Fgû½F@i}QôïZí1¾ù·Vi‰Àðüc§ŠçÖ¾¨Œ¾æQ°/£Ù{ü ‹èÄ ½k,¹›^U.@õ3 l‰¼÷I0 {N}õµ|óÙ{óÍ“w#Ùí6í¯ˆM²j²UA7Ë7_\9ýgÿ¼·x÷{˜;úV’þJ!T%l­:ú †nÏì ú´CÀ2cTíúÕ_sm;ßßqÝ/÷›`§;y †K­Š$¨ÓÌ$@£ævÕìPµ„h2Bàuôy¥ú HO¿NHçì¤Ä_¹È{t•Í¡Ÿ)€3"ï]ó˜/GP=àŠíyÐ$Dá͘û¦ë'ß4}øäíësGççoûFïþ6ºûîÄ&)"žé8ÔÒuº‚Md‡a~ÌÜÆÚ¨WPÛ¼Tàhwàï²Á¥v¶ Amþ¦¶?t‡H‰fð%u¾ì”µÇ$fàDóÉèÇ\a çúÑ55ž©~&N‹¼÷,ðHì<0O˜<< Ù~Ðû‹áKo[}ü÷îÛøúŸî›;öÖÎü±·&Ý}'èï;ÝE*'`kb8®Í¬Úêo[êи  ÙºÔŠÞqñ—xZÚG5® §©chê£h«`Çó„Ötи©[ƒ¤œùx¯-]¯ÎCGØcuBØÛ¯ô€Ð‡<ég!½Ó“Û6Oþ‡C›'ÿÃq‘Îáîò±ùÁá{û‹'ÞÜ™?|WÖ_:`: kQ|ºoÕû †ëomÄò%nÝUÜËF´O±ŠÙà¼Å]J—1«üi1Ú\lì´¢' ÒDùÒwœg(=†Nz¼Ö@¸­§Ž°¹ã˜ Ï ºÀsÀã`ç 7TÕ㓵gOÖžÞwáñ?ÞgÒ…}ýåC‹ýý·Í-»waþÐñNßáAw~¥cû}ûÒævõ¹\ïv÷„v”ñúK¹€»+y›X¯éTtÞ{’ô/R~ñx µ•¯ïRÖíu =*ÖE<¶ wÚ)…CzÐ À²/óÃÃsϬ Ï}}þÜãÚÛËúûæ:óóýîÂÊÜàÀñåÞâ…t°ØÉæVúÙ`±oÒ~W’,µiÏ‚ˆ˜$º• Ή ÎQgÔ;œº2wꊢš GÅd{4Ý87œnoަ6†çž9_ 7¶óáÆº/‡çäøÚJz?ƒŠ­‹DšdÍ%T@û A=vÀN€~Iöž“$o{‘êñ£¸g—ð/-Q'’•{Ǽª ŠÛr×ÀHÀÀ.ì‡h§ovŠñz¶}öÙìüSw@;@G¤×O{½ž±i“¤Æ$ÖvzÞâþAUz±i–¤ƒ…^[ ˜Äø|{sä«¢HR£“ ÛU>ÎÕ»B½›º"Uùt¤:S$“ƒÂ`Óî[»[ ÿChz¬ R¹(Þn¿W÷Ôñf‹<ÖòI¯${÷sè;žC§);ÜS]Ú—½ºÙFÔÔÆ”°It$1Ô%u¹F ¤ª>-Æ# Pƒ»}æÉXÛÓÜæ6¹M‘4žÐÄà"³ËðºïãõÔ âà‡YGú¦sóf®`+ z¹X@cÔ1€¦jõâ«ÓQø%ÒmyƒÚú›ë8+j¯àå¨V#— 7:årß×ýà_’Ü»fŠØ lê_Nm­çrù}™¢ÎÆšM«½Æ_ô:]!¥$÷œ%yã´.Þ„"e.‚ÈüÆl\È« Z6]º$À ”ä®3tÿÖcáÆÇ¤•¶Œôöê¯ér`°êèÒU^R=røÕÁëxE Ìï|ø+¨øF47!kf±v=îD=_Œ!! ºV£îÕÀëxYJIîxóÙ<¶×R7^À%É YAöþÇ‚—¸ËàRU:¶Ã›¿}nB¶­ìÛZÁŽ´™kT»}¶ÞÍÌH¨(îÒ~ŸCsG9Éó-ÓñæÐ븈±Jçý#=wQb6Fä­'Þnßwïwó[Ÿø5Îlž¦tç¶ÏÓVÊíÈ´W$=:ó_¹ƒü¦b|zÊ—7¾hB–ðµú};éuì A¥óþ/“Üݽ]¤ $­î¾ûž ÿê“ÿrîä…§1¶ò-&e¦Ú\*%¡àd„f†ÍsñÛÛ¿Å{Þõ¾rë±õ©sÕcñµ$¹^{ϼN·&ýÿÄ.D‚ù…IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/date.png000066400000000000000000000365631217176075400235220ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½y˜eUyèý[kgªSU]=ÒÍØL""È` õjÌ ¢ÆGåÞðE“¨‰IÔ$~$1jÌ£!PñAѽ óØŒMwÓ#ôçp1é|‚à ZëÛ”Vÿ¡µ¾èhã48j )ÍÀ™Á3ÿ„ø»=»w?³`Aç‡N9eå‹-zøã£…ç(!2Æ{ÌëíܱãùŽö¶W®<ñYºôI­õ?Âo6óB`Y6Žã`Y"þNyþàààg.¼øB/ZD_ßQ¤¨Vªÿ\˜üVJ9¶mcÛ6ÝÝݽ`Ñ"^|áöîÝK±X¡çÐ!”RTJ¥o7ãí¼'ƒ£'lÏóp'©RqI÷ž½|ÿ?¾ÃSO<†´mÒ©Ç,ù¶üÉJ©³,ËÂó<þÇÕWãzÞ‘e!°- ×ó°cé%¥D+u]Ow7w}ïû<ñÈ#ØÒ"•Jqì±ÇÒÙÙ¹8RÑ%–%ñ<—÷^}®çUMªì¨˜¡B¤ØŽR ÑD*º:å§X÷ü‹tvvòÒšõ\úÖ·å2™|¾-G&¦ûÀÁüõþrm[[éLÛ¶žÁÃ[JœxæK)QJ½1•Nóòºu,èìdíºõ¬ºêªtÖïhËæhËdØ»ÿÀ _øËÏ=Ú–k#É`ÛÎÅ»êíEHy@)39RŠjµzJ†™l–¶öüý…á¡õ<iYd2„ÐWzž‡çû8Ž{TQH‰ëº\uÅ ‹ \"Ô+urmy\ß{éÙgŸýR&Á¶mRÙ Ò’ïÁûè¿!„8¢ š_RJaÛ¶H§Ó|ò£ÅO¥^£”bÁ¤2ÒÙÌs?ûɽwÒ?0Ààà •råuaPgãúµ‰ÚcÛï—”RØŽ#|ß'—ÍâûþéJE,X¸7å‘ïèX³níš{úzûèí`h`ˆr¥¼H+ålzùå™â=/ µfñÂETË•¹«€+W½c,¢ÓF\J©…”¸–ˆ“;ÚÛ9åÔSÙµ{7O=ñäÞ¶¶Üš—׿Œ–Çv°›7œwîI¿üÏÿÜëУ¢H¥”Ú²,>ú¡ñÕoþëImm9N9e%›·¾‚çû{žyê©«Ÿ~Š\[Ûv°›sÞpîyÝû»Ÿš!ޓݧ'x?-0j7˜=4>áVÍÂÉ=æó(Bh!D¤… ŠÂÎŽÎN¤¼ºmííí½Ï¬~šåË—£€\6G{G'A=ÏÎ;¨×j¤R^¹¿¿Û²ìÚ± )õzeË–/ÏfsT«UKJéL³ÅèI12æ:¾ÞÌ 0^êNÈZëY `"zEÓûäŘï`4#ŒÃp´Àr)"¥9nűìÙ½Û•R`ÛŽÜ¿?™l?íÒ‰í1"mŽ4h ÐZפmëZX'CŽ;îöîÙ•zqÍÎ9çìþ}û÷’Ëç UÄgž¹@)åî ûJþÛŒ&~ÔtM11SLÓb€«ÞñNaY’FФ֭´R£J™bao1žQ … @k_iTÁÀРÓÞž'•ɰo÷n»Z«²uëÖžB¡@µV¥Z®râÊ“x©J)GJy´´ I¥TÁñ=NÍiìݳk¹”’öö»04D­Z"¨§( ”R ®Özº !b3Qb¤RJ­PH¤Bh@)¥„AQë‰i3RBÂ0AI¥B)…Hɯ| šÜóö·¼ÕBh¤#¶@Â1Íâ¨ÁD†R ¡ …âþ¾éLšPEK*•*‡zzJžç‘N¥±l‹°èZ­†mY²Žý5„¡e[–, èíëëZà§Ò¤R©R®R‘PJIÛ¶…eY‘”’(ŠšÛS2À•W¬ƒ…!Q«ÕD„V‰µqã¦âŠåËO ‚ðOÏ;ÿ祳¹ Š"©µZ)ÖÐZh ~S‰±2‚å8¡Ö:Ø·wÏŠc–-%“É"¤Àvœ›´æ­ ÞЖËÑ–Ï“I¥8ÐÓsM-^ï¥üŒàèÅSm×QaVvnßyÒòeÇΦQZJgn,UkçnÙ²åum9ã¹dÒÞQ £çlÛN ËšñÆ!dbÝ F Р¥¶¤P–cÛ«Ÿyº·R*ÿˉ'žx·DøZàÚ¶ùާ\ßU¾ï£µ­DÁ´l€¾AÑ××+‚0°ªÕš§µö-!jéTêÝ•jõ§o{Ë¥ØTµŒ­#ÂPÒh4Z+Czf¾yT R)”R<ûÈCä}›Kßú–,^Â)'»°2ëýl:ö Þ³âÛøGÐ$ühÉVî½û‡8ŽË ø‡|îóŸ¹Ry"åûU!DhI«fI)bã0qGÁ¤£Ø?0€ %Ð8Z©œRjp\WWQ¢£³N? \ß´ŸTø$„ê…ÂA*í ¡#ω¹2'øƒäËý”ëŠÊÐ[_ÙÆ+Ul× >öçë•xºÍxçóŸ¯qJvÿÐnéR-±yë^­Øà¸sè³i\—ó^÷Z,!èïïçµgœÐQ‚%Q¤ÒQ¤l¤°Â(õz!Ç´¿&•¥rYTk5,¤ÉÈF È^DA@½V§¿¿ ÂȆ¥- "AÜ û¶rIÿ œŸ^ÉšWÖb¯<žCýƒ¼²q=O­ÝD]\N¨C9¨Â*8>ù¡½¼åà\˜>u6R=é8Jö<ý4Ï¿¸žCÑໆsÇ[ оÞ"ÕJ•ZP‹Õ,­2 =)„#´ÕjU8¶#&²&”W¼ííµ-íØR)…D&>½ ¸Zˆ¢€j¹:û‡ŠÝŸL­Ÿã»½×Ó º Þõ»×Q©V8°Ÿµ%i/“ÈçQ­@X¸a‰ÓŸº/=Ç€²Ø;0Ì5×^K½VgàÀ^.¡«¥žeßšR±DÖ‰‚Z­ %ÂBHa @J­´Bh­”ÐJ1ö5!¨Ø˜S ƒ·a‚”ŠPQw>KƒLQŽÇŠýëéÙ¹‹×]ò6þç-Ÿæ_o¿ƒ¥K—R®VìïgÓöÝ "°æIÿO;~ã;Å17°Ë&N;ïb>ñÿÜ·¿ó]N>ùŠåÅ ›wíƒ ˆw†ý´ìÛ´S­V #EEDa”2.SBHi,È(Š =[¼&ÉPk"¥„DhJXAëøzEÔƒšy¢Ù:æ"îcÉ1KÃˆŽ®.N;õV¬XAi¸È‹/<ÇöWƒë~÷Oµ*ÁÈ«NN¤Ä¬’ëÐ^ŽY± Ëvȵe9åä•wܱÔ*5Ö¯{™Wž|ÀÈÍ@A)€RJ5ÓO¤&édˆ¿V­ ¢(¦CfdF i-#­u¤5c_Ú: ÑZÅ!CišS¦0ZÃE@½^=K¢hÌŒv\ñI l\¿–¿ü³?çªw¿ KZ<|ÿýüï{BtÆ*°sôOaÄ›Nê䘌K9Pd]I_5äþWû&ïOk°]zýäŠ^ݺ‰¿øìgyï{ßK6—çñGæç?üÃÇž –ÇyÇçYlgÉÚ’6Ïbë@…½j`Ïpò¨ÖêDÑÈl& »+%¤e&ªV:’´²&d¥"”2\¢•ÒI(mxߨ J™2b¶6@,9TDï©o&óâ/Þ´–Ÿ:Èýš ^gÿ¦—QÙÕs¯„Z<v}µì„có;Çä8oI†ÁZÄ›úX–q Ô“ŒPØŠê žö&úÖü¹a ¿>tˆçŸx!`纗P®Oíü÷@-à¬)þí’cøÞ¦^k!Ÿ:k)þpýìÔ†0¬£t„V 5VW ;ã¦èCi)"Ð*4 h”ÖÂÄquÂa †1j î{O‚a‚°Ž^°œ}ïý,‹ý-œ}ì?@µ¢—¯äП€ÎeÆðÒ³›„üüÕ~žØ7ŒR0Pyb_aêÙ¯$Aºƒ½ïùÅJÄA'à˜œ›àã餕aÓ Œá.Dâ¾ÇFúøZŒ&WZÐZpÀˆV˜ ¾ëÖ÷ÜÀ·Öàžû·Ã¢ ÁÎîa¾±¯)7¶™LD•Í}5*½*¾3b$Aû"F¸}¡aà‘çºYv ÄÀMçó©³–pÓ}ÛŒjq§II(þâÉÝ”ƒ‚ãJîx¹‡ráX‚Íý,)x®§ˆ–k!ÝÅZ,eÒ&º×LôdˆÀOƒcóÏÏw†F‚ ÿ²ö…ZˆmY„ÊÄU6ô–Ù6P£·klÜXF×ÃñÏ!0EWÆ@ic[5joâ1Š”&RQ⽃I³IAO£ž£ñ¦ùÿ$ú_@-G§/LÝ\!ëÖÑé,×–5U¿R}j˸ß\<êµFóž#M;® yì)6c?Ù£†0âãg-gÕñí|k]Òœ·$Ç·^êæ¶+V²z½Å€¼oñÜþa.?>Ïç/XÁï\Ï`©n êe£ÿeR è,œD'/Èð§ç/¥¯ñ³í¬:>Ï};¹ò„N^ÛåóÉwrí© xu¨JÖµøðkñÓmýüÃ#;'`äDÔëÆ¤IE–1…žØ(žÔ:Ã`h1>ƒ¡ud\Η4<‹lîå»W¬äÍËÚ¸ÿ“çó‡÷m£{ß¹?ãÆ2šŸÇq,3›¤4)mȶLjŒÈ¤z¤®wBª³ôÄ&»`º±¢8žÿu=|k}õ©[û+ìî)ñ?Úö×hw$ûú*qè«(k¡‰»I é<‡â •0霉q±©¯ÌÿzdZ+† !Ëuvª¼ØSââe9¶,qGÑ=XÅw-žï.3P­O,ÅâZa#tÓ5(„±"ЭۘÜÆÂ:éeLÓªµsÐÇ"¬qò¿¯aÍœÅeÇåÙÿ±sØ9\ãæGvrï‹L $®v¯!iÏfðOWaÄ‚"YtÛÆ^>zçzSƒwêHi¢hRpéyKyàýÆÖøÌã» Bnšå÷RpÚâ Ë2.Ï(²2ï“s-j!ǵwmyÎãÄv×±èJ»H‘p˜Ž3”.dó&f‘DÜ\ß\K:|Þ¸8þRˆnW,ÏxÔ#Íò¬ËËýUòm§w¥É:´äÔ«÷‡ mt¼f†&cÒXI¢GbJ1!¡&e€IAkT¬ëô¸,#KÆáÕ=r_y’œ½˜Ïž¿œ3»ÒüôêSyáË9÷ö— €eaÅ:ô[ëq°’¶¶”,L;üxs¯ñó£ˆ0û'¯=í]|æ‰=|å¡6{L j¯éLsõ‰y|K²ê„< <Û‚ –¶aiÁÊËËó ½¼í¸~nË&O¾} ¯¾ÒGÚ1:1ëZs#|¡ââ¥m\q|ž]w÷žÔɱm½zןÞův q×óûŠA·Ïaf}Gš3ºÒ|ýmÇóƒ½ï9¥“/=³¿Ø i+¶¥šR¿ZŽäZ@cìµFͲFbŽëë'á:ø×þb+לÔÉ»Nêà˜œƒ¶ T¹}Ã!žÛÚgfQ\xñéÇw³4ã*%E£×2B¿»€ïpÛËé)¼Ü[gñþ©À±x`wŸo`÷p½&µÛW Ù6°—ÞZhˆ?v©ëLÀ–ì)Ô¸éÁí¬é)ÓæZürǯ UFÚ—óŸ¼É&=¶ôgÖ¬~†ëâ"Á‰[„Õˆ{^ØÏ=Ïì úD€#L|R £4ÿßÛîoT’².d~ü|7?~z¯1§ õN±ùÜ®AL U°~¸Ž±JãH¤-æ^‰lK¶,±e¿©jîvhmôûw kNÏ­ÿ"¡Wâ;‡Qüj.ØC¸T‹åðÉljÎég˜l鼆y|Û¼Æþ~.0ŽÀÍî¦Rh® „‘XÍ0ʇkún²6â`¿Š]<­M×l`ö Î@) µPƒªC¥nâß¿…ùaƒkSG%Éà‘’°Â, ÑÍÆ÷¬E )?¼öLÂ02iÑßÂ<‚ÛEZ°÷S‹"Sv¤½¿‚H¡Ð|àøt|%7Û& 3„¯hM=Ò¨höq€Ù[J52sáá¬Òý-L‚F0.š¼,o˜} ÉÖkö@ë~ óÉ^ÃɤWÔ,Ô9ÄâZAÄÛ¯3ÙäxBŒæàŽDÿãûŒ3þG/4Ú훯HŽi™ ’ë‡S 5 3Ý{a„æ“!DÓ~L³€Ù«Ñ:ú4Ü<°O=õÉ  (¥¨T*œyæ™tuu<ÆöÑ ìß¿Ÿááar¹Ë–-£££cÎɲºyaÝTüÛa3 RÎ^(M«„ùxЄ¿øÅÚî;.IDAT/¸úê«'¼ïöÛoç†n˜É¡Í{ú¯_¿žŸüä'<ôÐClܸ‘B¡@#¥sB`Û6ù|ž3Ï<“·½ím¼ÿýïç”SNi0R²Fÿp‚„0«~#ݺ d*8 õzTÍùáf€æÙÿå/€öööQª×ë‹E|dÕðlðHˆ•ôwï½÷òÅ/~‘^x¡qO&“Á÷}2™Ì¨ßFQD¥Ráá‡æá‡æsŸûo~ó›ùÛ¿ý[.ºè¢GÑìÕß$¨F*‚f(æä´*B˜¨†}6 †O?ý4xcÎ ’RR,'ÙÓ)eã Ǿ¾>®»î:~ýë_†á\×e‡Œµ ’gÎår(¥¨×ë<öØc\|ñÅÜtÓM|ík_k0W/éš ´´E4èhv±9¤ƒµ) 5Ë#ÌwZVOR,ùøÇ?Žëº¸îø—š / yÄiA³”Y³f —^z)…BÎÎÎæC­¦l#ù/¥$9ܪ\.óõ¯5kÖðÈ#u`Ûö(|æ¢æäÀi¡G¶ƒ>ŒèÔ„®¼òJzzzƉþÖeaY›6mâ‚ . P(°hÑ"<Ï¥f‰:Éf³tuuñÄOp饗ÞsƒÄètðL1=š8%8ÂÉÍ®Ïl_0Z_{íµ<öØctuuM)âÇ­iœÆ+a6€«¯¾šz½Î¢E‹ÆÍ²æ>”R„¡Ù™«V«M*Ò5–0Á'?ùI€†j›õ85õ7ª"èHÙÄU§B‹q?[HŸä²Ë.ã`Á‚8Ž3í™8·+™‰ŸýìgÙ¶m .lÉh á+• …Bmï$^@«Ù0A.—ã›ßü&7Üpçž{."Þgi¦ ›Ç$%aª‘ŸÌÁ¿jp¶ èÍĊߺu+ïz׻زe ]]]Ó&¾j¬Š a†††øÚ×¾F*•j9óµÖ„aÈ¡C‡Èçó|üãç /ä„N T*±aÃî¹çž~úi2™ Ùlv !H§Ó óùÏž_ýêW8Ž3êäôéÂÈØÇ5‘J5l€Qì4bœÔ_Œ9y³ÍA'Ð8½²iÖýë_çæ›o&Š".\8¡(>ÌÔ;3b±È¢E‹ZöE‡⢋.âÞ{ïeáÂ…£®¯ZµŠ[n¹…;3n¸b±H.—' ¤”´µµqß}÷±}ûvN<ñÄÙ{MR6Šcµ @Æ<Ð(ÑñʾFØv4Ì=Ðx;³Ð§Œ`L¿~ýznºé&}ôÑÆ,šŽõ=™©¢Dÿä'?ià4”R pÚi§ñä“OÄ;¤Žè}!¾ïóÁ~J¥ÂG?úQ|ßÇó¼Qm !p]­5>ø`ƒfªŒÎo²½PèQAÓg¨#UKÉž¦³(Š&Ý‘²ù¥µ&6G¿¾úê«|ìcãu¯{>ú(är¹YYßcÝÀ©p°,‹ááažyæ²ÙlËþÂ0$¾ô¥/P©T¨V«Ôëu‚ 0û%Ç(€|ä#œwÞy µdÂD5¼øâ‹ï¦ƒo«Wc…„0ÛùÅÄ¡˜FŽxN^€éS#&RŒ!¹\Ž;vpÙe—qòÉ'óoÿöoäóy/^Œçyãfâ|$U\_|ñEŠÅbCŒí·\.³téR®¹æÀ0D+\”R”Ëe®¹æÂ0l9³“~wíÚ0ëàUrv€Ò”fñš@´q=¤f¦6nÜÈ<@*•špÆ'¥ááaÒéô´ýçéà‘\_½z5@#¾ŸàaÛvƒ.¿ür,Ë¢^¯O*®“k+W®l|nEà±Aœ™2·‚ááa‚(4ËtS6p†•!³/ ‹Ýd™Ötm€äá“Xºïû ;`Tû±Ë544Äu×]G¹\æÁ$—ËMšoÆeRücb-X°€ÓO?€îînêõ:ašíocX¼x1µZmÒv“6§3«çâ: !(–JDaï ÝT*èXL^¹?£ž›‘0¦Gã}3r31'šõAÀ-·Ü­·ÞÊïÿþïS.—É妮9œ®íP,ùЇ>ÄG>òÀw½½½8p€îînzzzX·n—_~y·éô›¤‰'‚ÄšN›­ú°,‹á¡!”Òæû¸($n½éïÔ0§¢P­GŠC•R Cp2hæü±ß+¥¨Õj ÒÑÑÁ7¿ùM®½öZ÷M%¦kOŒ©$Î`YK–,aéÒ¥œ}öÙ£Úœ²ÍD’½ôÒK@kIàxì±ÇLh+Lɳ—J% ÞUâê¬86G³…žì­Û¼YÎÓîyÜ“J'û;Bn:Ðh&žñAÐßßÀûÞ÷>¾ño°xñâÁç’A›ðâOŒiÆm¦zZAÊhÉÏþsÒéô„1€³Î:kÔ癀”2ŽFj¤q4¶ÁD¦N­ãlÁÖRaö*@E ±#’ͤf`|%³¯R©000ÀyçÇßüÍßpÅWÆ0³m»!.§‚¹†¤çÂ`IBé®»îbçÎtuuµdöz½Žëº\rÉ% ©7“~GÔLÁìO!lÐáè œLÒÍ9ƒÖ,0G0’€˜®˜ˆ;#ÂÌ©«V­âŸøD£Ú§T*Q«Õ̉3Èš®œÄLÁ²,òù<•J…Ï}îs8ŽÓÒ°ÕZS(xË[Þ 'œ@±Xœq(>Å•¡Á!<×AJѼ. ¦{¢T¤Í^Ù0ÙFÁÜÊÂ#Õ23 ÙA@>ŸçŸø7Þx#çœsår¹AøV6Âo"H)ÍG>òvìØÁ¢E‹Z2nÜxã£>Ï„„QÈÀà nÊ7qÑÄð±îÐ8ñ6k ¥ì¤Lqjب4YžÓ—Zk†‡‡9ûì³¹ä’Kc5Apؤ$@’Àr]—?ù“?ᮻ³³¥ñ—„”Ï8ã ®»î:*•Ê¬íš è`áÂE˜x I:8‘ùZDZkÛ(&6æbª¸I³ƒÒjFÖwEôööN©#i:¥Ùcí‹ù„$®ŸN§ùêW¿Ê­·ÞJ>ŸoY±”è~¥_øÂRR*•fe&A R±Äòåqiœeš€$RD­ã#ŸZÜJ¢X­4wz`ºš¯Là\@JI*•"›ÍòÏÿüÏÜ|óÍär9R©TKÑEýýý¼ûÝïæ}ï{ÃÃóbÐ$BÙ{¨­#S§hYFÈ'öБÖZGZ K›cµ·_´à0l“×]w]ƒøcW&%… …QÄŸMį’âÕz-`ó¦M1C¦±][˜_²<\ ­µVZH©U¤Dœ1Ô­¤âœ¼sº4Ò3,™v7³P-‡dæ§R)®¿þz~ô£MIüR©Äðð0ŸùÌgø»¿û;ç4ó›W¥R)víÜÉ¡C‡XºtžgãØNc‹¹xm fÏ1ÖZÄ[G÷öõÒj8´žäìà©@«ÑE)`:÷Ήˆß*ÈFM‹EJ¥·Þz+·Ür ³&~ôj®Nr]—õk×#…$“Nãx®c›r›ÏrH|¥´¶,‚zÐ2˜$‹æ– bôr$ƒ8-¹m6p4‚@RJ²Ù,žçqýõ×O)ö£(bppZ­Æm·ÝÆ7ÞH__•JeƶKBødyz2û}ßg``€­¯l!ŸÏã¥Ò8–‹ÝX°ª“²­Ai­R •"˜„sb“NÞC¤¢¸ d~ŒÀéÆFWÍÎ ’òî|>χ?üái``­5wÞy'×_====T«ãƒ.SáÌöäR-•ˆÿgŸy†J¥Lç²åx¾‹ãzر B$¥y:ÌIqºÔÜ1¦S³ êŒG© š‡¸õ¹”s‡#%„xžGWWŸÿüç¹ãŽ;ËÂ'"~__žçñÓŸþ”Ë.»ŒLY78’‚—dÆ'DOÞ{žGµZååõëH§3¤Ò×Åó\<ÇŽÏ”ÍFxÐ*Ù3`|æfš–M©yŽÎôþ™Y$å`ÿþïÿοøEr¹¾ïOÞm&þþýû©×ë3ê·YÌ·ÿI1ÌÚ—ÖÐÛÛKGGžëã:®©9H\Q{þc TJOYÆ6mlÇ@’_±=æÇœIÅÌl@)%]]]<ûì³ÜtÓM¤R©I#|…BÇqÄß»wïŒkûÆêùfÃ/™ý®ë¢”â¹ç_Ķ]R© ®ïáØ>–ã`Y6ZHS÷ÛÄéŽÁ%À7ððo†4S‚ÎôþdÑf©Tâ£ý(•Je‚Ž$­wß}7—]v½½½Ø¶=i)xÂĉ*iÞ.¦™ÆÎ~ß÷yå•WèÞ·‡¶lé¬ç¹ø¾‹ïº¸¶oÏ Æª`ÔÏXÀDšÄ„+Pg Ó©h†Ù”WÙ¶MWWþçκuë&\ž@¥RáÓŸþ4ïyÏ{(•J ÍDƒ¦0RŸÜ›”µ’u“Ï=ó –eãûi|×0€ë¹8ŽGçk€¸Roú“pNA#AÐMk'4—šO§ $¹:ƒ ¥$—˱víZ¾öµ¯‘Éd¦\œÉd¸ÿþûyðÁ)—Ë-ûIˆ®µÆ¶m²Ù,™L†¶¶¶ÆÂ–sÏ=—}èC²°fHVKïÙ»‡];v’ÎäðRi|ßÇw=ܸæÐ²Í &¦hܸO‹s\Ì…FG©1-ñY·Þz+åryÂåáÍm»®Ë¶mÛZ|Éç(Šeâù|)%Žã4“Ú¶Rªáa$÷[–Õú<»úY„eáy.é´ãßß±\ÛÅ’–ý bÐ0Í´ž|EPc ¦sÓä ãå¨ó“‡Ÿ©>Ÿ® hûöíüâ¿h¹©C«ß¤ÓiR©Ô8<éçº.¹\Ž|>ߘõÉÿdäÒ¥KGÙÍQ?€ƒ²í•WÉÄ}¹ž‡ëz8ž‹íØXVb<2n‰ïRMW¥ÎgEP³5$bw: ˆÿÛn»¡¡¡)gÿX»p$)aÏd2´··“Ïçof€l6‹ã8tvv6Œ½$”xO=ùãzø©Tc¿Çv°mËv–D ÐzL÷9æÌóíÎÔhf‚ÉÀ¶mªÕ*ÿõ_ÿ5jà'‚‰˜£YÜçr9:::F>!~6›m|ö<ŽŽŽQ¿æÝI{dÛ«ÛÈä2¤R)R©ž—Âõø7`Ä]„Ùkâ¹- ±0ë-OZÀL½€ä7Ó¹Ç÷}öíÛǺu뻑̤Í$Üœyííí´µµõÉ+!~r-NÓÑÑÑ úXé¶úÉ'm{¤R)|ßÃõ\ÛÉýa[H!*IÈ5~?£ÁŸÛÁ‘Í¢U#p8¡Ù HføX‚$º·yêdL˜„XŸ}öYŠÅ"z/cº‡t:M[[ù|~”ÈoÅc_£úHà@÷¶mÛN&›ÂgÊóñ\DZ°]Û¶°-‰”ZÔ¨HðÌà°‚`þòJ)z{{‰¢ˆžžž ï+—Ë âLÅŽã4öN¥N\×ml çy^ã*•jˆÙlv”dH˜$1 'ZïøÔSObYÇöH§Í¾ÄŽçá¸>®íà3ó¥ˆc $Å€³ƒ9FÓYóe„aH¥RaÕªUœp -÷òQJ1<<ÌI'Ô¨¾™ ¥ƒƒƒüñ\uÕUÓÚ4Óžç‘N§Éf³ ‚'›G'úÚ÷ýQÌÐü>“ÉL¨¦öíÝËî]»Éd²¤RiÒ©žïëß±®°¬Øà‹s$ù÷Ùûa‘æ-”ìÉó©O}jÂäLJ*r¦ Fim–§]{íµ|øÃž6ñ›Ýµ±[Ê'Y³Ý2ûeß¾½üúþ_ãyžç›ÙŸJáyfé™ãxØÒFZÒ¶ã ëÜÇzŽû0oµ€nbâ Q(&Ýb& ˜Hb±8i› ±“xsò¦Ùu›Èi¾6ƒU«U}ä¶lÞŒã¸dÒi²¹éL?–žïbÛV£M-ezÛñœ LÊZ˜YM¸ îYÈy« „Ã_ì9Y›É÷I7!^b[$öEÃýŠïëÎ%Q½Éà¥5kxæé§©ÔªdÒY<ß'›5^C*&ïŽîX®ñý†ãÍetZb¸që}Æ©§)mB‹M(qÐYÓôGJ«aÏ÷¢Ìù†æ Ló+!jóûæïš?O•OØ·?<ôÀO¥É¤s¸žG6“kèÿ”ŸÆñ<,ÛFÚKŠqÄ7&àè »g ²h¬b´ÖÄõe:^fØ,ôMMzò¬¿‰ 9gZ놸oEðÉÞ'Ÿ'›õ¥R‘‡|ˆ­[¶â86™laÙ¤ŒHZÝ( Sì81LÁ¦Þ\éØÚ3þ¦tF„Q„åZ¸®=oA #J™Y™¤g§Ã“U)¥xáùçyfõ3†Éd³äÛ;L×óÈd²f¦§}<ÇÃõ\Êå ÕZ™ „uÂx÷/Å{#&uYšaœw;—ȲhúkÄšY夕6Õ5J™Õ¶Ú̺H+St!Àv³0ÃõhkkÇu}\×639ÎÚ¹ŽY¹ã¹6–ç=ïzBN;ÎéÛ‰¨—–H[ …ñù“€“)ûÈd+$Âä„­óv|¼ 5DZEZ#ÐñJ¥ãÎ=Ï£sÁfË´Z­jTB DE1(=Ö0í7>6“e˜à¢ûwÌ}cù­ùr³/=êzâscô®´RXØ–…%%–cÇáÙ˜¨ŽÄ¶c"».žåšò-;f׎ 9 ÑË2‰)‘ÂFHsüO#¦2Íý1Çœ@2/¡`€(Œ´R -´ÐJ)lB¤5™Tš °æ¥µhR)WÃ0Îɇ ›–˜.“a:E ãÆ´!¦‘¦ÀùØÌTRh„e!X–Y‹#¤©Î•–4ÌaYiaYÇJ,y‰°,ìÄ “V\Î-foð€±ì¤÷¨ª°- Ï÷,J¥™­85¨ˆØŒ´&Š'¿8ï¼sÙ½oó—Ÿ –#A™:õH7 Ùfh.#Ϲ-Ь'º0RŽ6îÄû$3Iÿ]ÄdæU¼ú®±Z¼ÂF…èXG‹$OÐ ±ý#DC<52y ÑäHv½þ$óÄ ¦V¯sê©§rÕUW±ú™Õÿ`˜’‚ 0» (&Þt T.S,—¹êÊ+Y´h!÷ÝwÿH4Lh”mÒ…*&t2È•SOüÞL1nLtszoþŒúìÄß5ÖÒ›BJsÄÖˆ¥=žDãt. f(9R„K)GBâMŒ5î1_OÒù‰´i¥ÃÆ=¶¦Z­röÙ¯çƒü=*å"Û·oA`05D‘²¤Ô&ó “zóà'÷ÞË1ÇÛ.~µjÛ·c{^C¡6VÀÈ ×¶l„'6, [dôHĤ%R˜$ˆm™}pÆ®¥K¬e+¾ÏXÎ6–-±+º‘»Obç#îU3m6ZTM•ÍZ)´2gò&Ï*.5‹´jÜ—”Ÿ¼W#÷+Ei´6I²(®mPJ¡ÂˆPE„‘BE‘y)E…„QH©–l ‰¢‘’kÞýn„ÒÜwٰ߯e3@¦yvX@+%é¯9BˆýZkzûûøê×¾Æ;W­BŠx•J¡…h¹ŠHf#-ÁKŒsš˜·‹tL¹“‰´½*-»Á–”ÈØ²ãÂH˲±,°¤)–´„…e[ˆFM6Ü;ÃÐ<Ëaì˜XQ¼ÎÑä6"¢H†âºG™ÿZ)T55Ò*ÒD*" C„T¨H‚m›=µ9mÅ0™iOEQãì‚ G2 P‘ÂIù¬_»ŽÕÏ­æégŸK.­‹lÚ’@Lc…BxBˆ­õ1ÀÉÀr­õ¥À;§ÛÑoaÞáUàïýÀîøÿ0±´ž¦• Òf'â¨E *„xBk=\ ,cNu)ÿÇÂ|‡T€§€_åøs˜Öv¤SJ!„d€<°X*„h‹@Š‘œd+ñsTcÂ3ÍOŒ©k˜ìÇ£¢/Mýˆ¦ëóÉ31‹˜Ýpè†0Œ07 ÌhD˜ÙŸ„‚‡µÖ~̱ÏenŸ¬©©úš/˜E¡Êt‰6꾦2±Ñ»ç¨c$À03Ó’B‰™ñNü2{iÌü [Ç¿ÿoÓ!àd®,Ó›‡’‰`&kÄñ'%ðL y˜f7c\j¢Ù&…ÐrŠÕ·¿ ¡RSî7,í¨_1æó”0m˜²¡ÿæõ€ÿ·Â±ü[˜øÿÍ+cdCôIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/folder_inbox.png000066400000000000000000000262511217176075400252500ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½Yp\Ù™ßù;ç.™‰ ®àVdY*©K]jµJê*m-M¯ê¶Õînìéžp‡í²äûÅÛÃL;ÂŽyGØí?Œ#ÆGx·_<ãki©Šµ¨6VY$@ €Äš{æ½÷œÏçÞD$L,$Õ⟑D&póÞ³|çÛÏw”ˆð?»Ð»ñpñ˜~Æáwz¡RJˆˆdïãÑ…t(ÛU7:€RJ*}=ƃC§ã-éËBgD°-PJé òžçõAP!âó˜$÷ÍÞËæ¿¸ W`@EZëšµfM)Õ³Õ·$¥”ûçþüw¿ûwþîßû?‹IŒ'ˆy<ùû7Ón ÒúÕÝ (¥Äó| 4þÁ?øûåµW_y[)åmEÛqH†‡?û™ÏœéëëA¬¸§=Æ# ¥ Z­£` €d«ë;ßý¿ ë:AàcÌ–å12‚  Z«šF³‘ÇÀ–¶˜ÊyQIœ "hýØr|T¡µ&Iêõ:ÖZM:¿[Ym™‚JLÂÚê*(ÅÀÀZk¬µ{ÓòÇØ”R(¥(•JÔj5cȬvØÚèl9+%Zkc¸}û6SSSÔëu|¿c7Âcì<ÏÃZË7¸yó& A JéŽìûí ³+ñ<\ÒÛÛKµZå£.277‡çy<ö =x(¥ð}ŸR©ÄÇÌòò2=== =ø¾Vª5w[¡ Zkñù„$IðŸÇ÷}”R–¶|?tÌõö‚€B¡€Öß÷‚¥¥%ŠÅçΟcdxc #Œûß÷©×ë\¹ò)kkEFFF¢§§‡\.‡ïûøq²AØò~>W”Rxž#­Zk …A´t1¥TWãݵŸ)|©œAkr0 Y^^æÝwßåìÙ³Œa­},vß÷)—Ë\¾|™z½Î£ ÐÛÛK¡ÇóütQª)ã;²ã”Rˆžç¸ÁºHp"buu…>úˆ£GrêÔ©–©ò#[\7oÝbjr’ îbù¾ï¡õòî¡ ­¥ §†aH.²²²Ê­[·(—Ëœ9s–þþ¾”츭?3ðùä#&&Npèð!<­±’9¬~†dBºX´ç±¼²ÂÔä$q366~·c§sÙûñéŠèìÚlòãÈé!¬®®rýú4åJ™ÇOÏç[ÜàÏ: dd®´F¬eææ 7ggÉçó>|˜¾¾¾Öä{ž—Іu}i»ñï–1tAB®å È8‚çyär uOËTÌår¬®¬P­T8yòÃÃC(µw¬íQ†ÒšF£ÎôôuVV–bhhˆ¾¾>òù|Ë«w·¢×ÉØt7~ÀîÖefB©»G—/_fbb‚C‡áùžK;û3iMèòò צ¯aal|œÁÖª¿—¼ßO쩸2‘)ˆëzAÀÚÚ*³³3”ËeŽŸ˜ Pè‘.i™ñËÆ­;iy6 Jµ-ƒÌVc s·n17w‹\.ÏøØ½½½ôöö¶­úÚýæˆÀ^Òbfö\Ⱦçù¡3/_ª21qœ‘#8¯vç é$ÛTRmZÝ)Òªí³RY|%%„.ób•ÖÔë5¦§§)‹ n`ùAâi­ÕwŽtÆÒÈâ^šm™‚¨”ÂÓš ðÉ…!kk«\»6Iµv˜#‡ãû~ÇÏ´â^ÆJú^¶°X7.YB£P<žVéß;c'Y`fey™™™’$a||œþþ~zzzÜä§cК÷´¯;ånçç¡äteòm£•ù ÖÖŠ,ÌÏS­T8~ü===l+ReEˆ 4 ĉ€D)¤ÅMT›¦,¾ßžsï|従ó…l È6 U+…1–¹¹[ÌÏÏS(¥¯¯¯Í—F?D—hç:Ùé^a£‚˜º’=Ÿ XYYáòåKL?ÎèÑ´!÷nÅ­|#%–JQ"ˆç!JZ_[ÿv›œÄm¦j“ùBèC Æ (MÁoÿêÝíR¡5µZ™™ŠÅbKËïíím­úLÞw'äös€Ì °J‰R´E5ž§ñ=0Y[[cúÚ5*å2Ç&&œH¸Gd1kš±Bd  õÄb=¨l_ÍúpK{_dýs¦wh¥(X=El„Ð7Ðæ~dZþ2×§§Q <Øbùíî\wmÚ¦=Ónîöˆ¤õ®‹¥”Ë~i³òù<ËËËT*Nœ<ÉÀÀ€Û Ò¸tƒœÖ®s€j$˜PÒµžjq©^°ÎҜ⠙‰ ”à)0xäê±ÐFAoðZJÚvòžáöíÛôöö222’Æí „¡sì(­‘í×_ïGgx`f`§È”Bø(Uh9ŽÂ0t"áÒ¥–Ï@”—û(©ÒçD€P‰„RÃ’dã‘rG²Î2È"”©†ïi…(Áˆ¡Ü„Áœ ØÖÖ[•ƒ‚À÷©V«LOOS«Õ=@ÿ½½=ärë,?»¦DîÇHŠÈöúR° -½À™Š:Íu Ÿµb‰ÙÙK%N°¶ºÊää$Öš–¢W(6¸s³>lÃýž‰€‡0ý­ç‚3­<a¸îFö}Ÿ0—cqq‰;K+=ñ…þk¨ÆB©)$ùuÖ-V!bÝ*ƒ#€x=KI)}a ÑxZQl õØí¼õ´brjŠ…¹yúúzKãöΣçvådj¢ÚЇ6^]°é.Í@ûàe@ •þç!Óôç4°¤•âö%~ò“w8pˆfÏQê&G%¢Dµâ ­I§/`œ#ØØõËK÷C笢–€¯¡ MñX[+q}ê &‰9Àà ËÎÝÄQ’çoFÆá:|ÞJ)—<²!˜º-k==¨µ*?þ„j~ÚáÏÓ°> «1ƶlýŒý‹Q-@(%€´ R,аPÀ£f„É™[øW>¢¿§À‘Cãz+7L'?3av¢ãþY—ÐràXAÄbŒÁ˜„8Žˆ£ˆz½NæøÌ3Ÿeªœc¶\g¹2Т°Öb ©Üg+H,Hää}ÆŒÒ$¢©'–;¥:G5k¨ÆÎÑ411Áɉ£Ì\¿ÎÒâ"QÑß?@ÁZraêêõtêPJ©àC·Îº®DÀu-Yf­cùQÊê+å2µzѱ1Nž<é2‹VJ”Ê5 : MÓ*" ´Aã¼})ûw ãD€M ¾8oò¢=¬ò¨F‰Æ¡\®2<ÐÃÓO?ÍòÒ“S“,.Þfpp˜ÞL/ÃV¾¬[dØD°ì¹#HÚþß_´[lÊòã8&Š"ªÕ*Åb‰À÷8wî<£££ÔëuV–WhDÆ…Vµ­1¢H …vA€t?BKL}b¤-ÑCaD#(,ihY¾ï!"”Êâ(bdd„çŸãúõëÌÏÏÓh4L·n‹õkz ì‡#HRûþ2€,l+X+“EŽå—Ë%&ÇÇ9~|íy¬‹DͨMÔÚ¢v²W®å¼ÿ÷Êr´‹õGQÌêê==Ξ=Ëèè(““S,-.184HO¡‡|Þ¶ÌCI½™ÙÝö ÒêKgèˆDTÛ íHj¯[cZŠ^½^£T.úçÏŸchhˆz½N­TN«–¹èšjs½ìuB¥åª–£H+… T«Õ–ðùÏ?Ëìì,óóó4 Éåó„™gÐóZþŒý"‘îv\uœ¸oJ`¦è¥Ê‹±–8ŽˆšMÊ• zƒññ1&&&(–JÄqì»V­öej·êvp3ÝfÛoeÎ'YÏ D!J‘$†b©H!ŸçÔ©SŒŒŒ0uíKKË ÐSHspÉ¡.ïsŸD!ÝhÓºÊ Ü­z±–$1ÄqD­V£\.†O=õ$ƒƒƒÔë pïZ…ÙÄìh@;éR6ëà’Ûç/]!õzƒ(ŽéëíåsŸý,7oÞlqƒ¬~O.©E¥yÂÞšŒÙ\uˆ®•À=›þ6-ßgÞÅQD¥Z¥Q¯366ƱcÇ(•˘$«{sÉÒZ•ÝhçDÝ®Ìe¯ö?f>G¼9Nœ8Áðð0ׯ_gye…4ÿ?L7ÒzZ»¶ÊÞÊ„=Äÿ®)À±[Çò-ÆX¢(¦Ñ¨Q.WÀ'Ÿ|’êõͨéVÉ6J37l×Û¦3ÐÉW2ÚºköÛ/qhFIÓÓÓÃ3Ï<ÃÍ›·XX˜'j6éëëÛ5Tº-~·”ºl;D‡•BÕžð€õHUêÑ3NÑ«Vª4 FFF8vìJ)Êå &­x¹Ý|flX«öÚ[´id5X·|Šrâ­Z­†ÇO0<<Äõë×Y]]¥¯¯—žžÞ–Hh‰µ]2‘®¬À•À´E»šþŒå Σ—$©yWFkÍéÓ§¢ÑhEÚë|2••uJè¶iuJµ¬€ígýˆÇ1Ib(œinnŽÛ·odž޾^Â0GøxÚcØ©>³ž@v@ë¶½ˆ´ä}­V£^¯344ÄÑ£Gñ¨×kø¾ÏÄÄCCCܸqƒµÕÕÖ^,ªè¸ÚÀuºêN{+»sÑ]¨Ñ}1ÕòEHÒU_­VPJsâä †††ˆšÍf`G›$¬+{ˆI Dµ›š;dÕI’P­V)ôôpîü9ænÍqgq‘8‰ééémmÙ¼-|¿Ð¹˜½ébþ3Û>óå×ëuêõýý=âV}½VOkíÜUÚâüÙ&¾.î$§È‚Iè.9Àæû(—¡Ô¨7ð}‰‰ ‡™½q“âÚ½½}6¸ª+­^nÛF›îŽêÝeuHíáۤ勵=z”‘#­À€êrÒîee„öqÕ(Xß)º›{àÄa­V£¯·—óçŸbnnž;wîǽ½½-"pÉ&©+°Àžû:ö¶…o[qû¦sìôöõrôÈa‚ ¤Qo´’(önè61кàh™E²Ðv·Ö &¾ïsìØ1úûû™½y“µbÉEsyüÀåvâGβÝ;Ew)a÷¥Ù䨱Vý¡C9p`c’Ô›··þúL ó®uzo­ŒÑmMMÕŠìF¸’Ä`mƒþþÎ=õ·nͱººJ'-Ñ÷=×ÔV{ïÕ‚î(`×Aë¶}º3§-nŸÏå8zô¹\žf3jÉúýB»î¼×PŠ´"êþ<#ãÞÍfß÷9yò8CCܼy‹R©H__Bn=ñ4SL7ßHÜþ¥NI`wAm«^¬%N ÍFƒ8‰ellkmkÕëö È¢Õ€Þ'H  U,bãûÆ Ëà +77?Oq­H>1äóy<ßÛè3hkˆ•ì¿Î°c?ÀzÚ‘´X¾KÌ 8yÂíé¢hOeý–PYXx£ãjÏnOZ,¢5Úû_7c›M§œ8~œÕþUæ©Tz Ȭ„´)ëcÜ¡ÞÝÖ°6?€°nâeÞ»‘á!<˜²2g×?ˆÉwñú(€Ð…¼Ìÿú=º6Æ`­u…#ûzÓúËòù¹|ßó6ÄI$Û¿Ñ!t L½”½dZ~½^Çó<&Žc``€8Ž»^õëÛô75ºÃ¹qQj…Õ½£j«û"ä|…VY±ó5:‚Ûø¬ûõVÚÿ~æÑÉPEQŒçyœ:yŠååR÷rß÷Ó i•”ÎûØq™87ÈN½°Æ¸T­¨ÉÀÀÇÇ[åN»Eº9·Õðu¥R‘¥¡m+K31D‰ÅÚl#øÀÍ6V  ;”C­Ïeç¸ëzƒnW[¼;ýÑAs3npàÀ})7¨T+­DT?uuS# Ã”0QÙ%IB³Ñ@€#‡344äbùqÜÙÛ`­³b+$fÝ‘cÓÝ-YÁ§uÿ÷\j"éŽà†¡%¬Öbî ¤“·V±”‚$ŠB‹âbÉ Rµs²¶¸AZl"Ðà+WwHˆJó¹ê,"DQ„ïûœ>}š;‹‹,..’$ …|¡Å¤CiØE!‰ zƒB¡À¡ƒãa°£Uïîç/6ÐŒ-•¦áòÍF\⥈ۺ—ØÍÖÇ&AŸšO±1T›†BNóäá>*y͵ÅFwmb£K@áJÄø«ðú{ÿίò¹ó9B‚”çV¾—iî>‹¬û |­tv|<(ÅØè(A´’5v Á±×0Є¾ÛõûÇÿvŠ¿øå1>Ówž™Ñ!BÕ¡•&lØç¡™ ‚ü ÅÆ;?í¼TV‰ ÎLà6›x­Ý2 5¤Ö‰3{ï)tŸÂT¯ ù¢fì´æéÃMjM¡Oo.¿3"šÍ&ýýýÎïÐØŽßóÈçrh¥Ãp½™Ê­¯l’vbóåATÀ¯þ<üñ¿½Î?ü÷7øÜo}–Y¤Ùá¢ç‰ÄX$±ø©?|·E§÷vª~#–t¢»ë£XðCxò—5‡z5ãc!?Wˆx®ß’Ë{ôôøôBßÇ÷uGc˜qß ×¦yJA!Ÿ×žçµœJ)u¿¤·""ñý^s~ávÒl6TÇÊ#I‹ˆøVœö®´ºgý¾-ïM‹†ˆW~÷YË¿|­ÌÜ…i¾ôíó\0>ÖvzÂõþb'ëRp…&‡4¡b:†ç¦®p»”Pö…|èŠ_ùžvYM[<(S²ƒ¼;ZWˆJkO{†¡DQù¾ßÜÞw%lË”RÁ‰“'ÿë_þKß»R,4£h0Ž#}ôÈ‘ïrù/aÈs_øW>ý”ÉÉ«ø~Ðõ0µ2isãù .Îý<ïóü7ÏòFõÑ!‚nà4|Å çŠLÍÃWþnͼÂÿS[E5JHÜÀ&Iº›g{n%bÑ(¾ü Ôë5._ºŒÒªtcvöŸ[kkžçÅa– =…¥«W®^d‹øm†- @DD)eg®_¿1sýúÐø…Bá‰3§NýŸÆ$<óÔ3œ8>Á«ÿã‡DÖK:¥6(Õ¸%ïµ|ø¶ žÿÆ“¼Qõ~ªˆ@p¦ßï*•5Åclú¦þQeU/"qIât³jg[ºˆ¢&ÅÕ^xñEî,,P)—‡“fTŸš¾ö¯Ðj@HDdK%¨`”«iÚb‰¾öÕ¯þÑÑÑ!­_ÿú×ùø£Ó±ƒ»p¾(–U¤nïp<~‡‹ï8Eêù¯ŸqœÀìXQ~`h±}ŠM7ù#7^cxúe<ÛÀÓ :Tà¼IÐ’ßÛC‘$yfgg9pà/¼ðúê«<ûsŸûîì­›EQ‚“°ÛM>t¸¨DÄŠH""ѱ£G‡OLÿèñÄ™³ôööñÎ;ï¤'Xê]¼(…PˆnShÎ3½ÃÅwÞeá•)¾> ý®""‚¯H'_hXÍðõ?ehêt£ŒŽª¨¸&ã’©¥ÖÅù¾ÏÚêï½ûŸy懆éëëÿÂSgŸü‰€HDâN&vÀU_øÊ/ýA’$G|Ïç™Ï>ÃÅ‹rkvßó ­—³»`rõ9rõy&šïpñŸpóå)¾5hY"ıý ›|ÅÈôk N½ŒªQõÔ«5±I‚5k¬{u86b]A­5o½ù&ÆXÎ>ù$µZóçνô¹g>{_mÿ~è*ü¿}ï/õ(¥¾ßl48yú4}½}¼ùúXc´0¢X»ëœWÌ9!¬ßÂÇäMÞ{Û¹†¿úµÓ¼V 0É£#¬8ŸÆH¨XmJ‹íL½Œj–¡Q‚¨ I„µ wíÝéØSåÖ«§5wnßæƒ÷ÞãüÓç¹øá‡DQôÍŸÿü翼ÜMÛ»âQÔü=k“3J+Î?ÇÔÔÓÓÓè¶(T«nÿ®^#€ k7ñë ­½Éûï¼Ë¥ÿ>É‹=1^ðhp‹›üñ¼f­)4D34óýS/»‰¯¡Qq¿‰]ßv8.Ò¦0ŠÞ¼pÁ…ž8M5U½^ûA·íï˜~÷»¿ã‹È÷ãØ066Æè¼yáQ§>t‹•¶îÁË `"rÕ›øµŽUÞàêïsé‡S¼Ø“qÞŽnÜ=éXB 8Þçq«b¨ÍØÜë ÜøÊÖÑDx*Aù ¥=,Ô·s(­[YXí'¶OOO3==͹sç¸>=1æw¿ûÛîÿÇÿòŸ';¹o‡ÛÃ囂|-INœð·;¹og~ä%cŒêé)pèÐ!>ºx‘JÅÅí]í='× ù<àJ¦îËKžmÐÛ\ ­p&~ë—>æÒ+Ó|k &hÌ>pŸ ÆBO 8=à3[2›Š#‹o36÷^³„UЩ¶/6=ì»1ÖÕEgu¥f¡çyLMN²0?Ïgϸ˜ŒØ?üíßüÍÃôi[ð[¿ñ›_TŠï$‰áð‘#Ôëu>½ü)Z©Ö&D+Ò*Ýnmg~íÝ@S§§9ˆå ~Âä'.õê/žà‡‰G½ïLl#Bo¨9=ä3SJX‹G—Þb|á TTA5+¨¤Ž2ˆÉÒ²ØËôq¥5¹|¾µÏ"CµP“í dIDATZåƒ÷?àů¾ÈÈȇ|ßû«À?ÜîžÛrkå¥$1~:xˆ+W®R,Ýé×mj.ŸC)w†Ï^Z÷³¼¤J¡y›°¹ÂÍw˜ºt‰ /Ïð徘Bè‘ì!+ôŠ'†|nÖšptñmÆæ^G5Jë^¾¤ &AL¦íï±UdŒ;bÖ÷6X\žçqõêUVVW9qòTºÛþÑoþÚ¯m×·-9Àoüʯ>…R¿—$ ÄXÃÕ+W\^FßâvÌäsù–ºo{&Ú (ü¤J, "œâ&'}Œç¿r”×G½oMáíÙ›÷[ùg†®Mkåο‰ŠÊxQg+?Iýúû7Zkòùår©ÕnWR§Ä¥?áçž}–ÁÁAŠÅâ1­õÿlËûmý8yI¬-øžÇÁƒ™¹>ÃÊÊ Jé6ùd ÃÚÓŽ*à? x¦B¡¹@®¹ÈéÚæ¦'yïÇ7y¾'&zÛë[N>ôŠ'†}¦WV›pxñMÌ]@E%t³ŒŠkhÓ@l„ˆÁ²¿c`­!— Ócê2Ý”Ò\¹r…Z­ÊÑcG±îX½—~ýù•ÂVÝ¿/øÕoû˜RêŒ1ŒŒŒ ´bjr2Û…±aüòù<ÖnzÞX^R!Ïm,pš7˜žq›7¾ô…Ã\0µz÷:µÐ“Óœ ¸¾ædþ‘¥·½}Õ,£ã *ªƒ‰tå»›û +Ž „aH­ZM-.wÐåÚê*“W'yâÌôôöP«ÕžÒZÿðÿÞï~÷å"ü‘µ2Šá˜ŸŸgey9­p±Q&ù¾Ÿ,öIûßâ%™u—È7ÈÕosªô#nLóÁOøb_B!ð0]ø¦¬…@qjÐg&•ù‡ßâÀÜQõ"ªQB5«4!©‡ïôWœ[8ŸÏ»y²õŒ«W®EJSÇå¥_ùÖ·ï»Ðïù‡oó—G•RÍZë*Uø—¯}‚1Ï÷Ý©éjÏçó'4ì+ü¨D.­~Š×˜žQН|~Œ7ES¬Ú»:¬6••Ë<|'ÂWŒ‡—ÞbtþuTTFEUt\CÙew˜äý÷ëï¬ÅÓš\.G­VsE¥Rΰ¼¼ÌÌõ>ÌìYšÍæµRßþÓ½nuo ò—ÅÚC"ÂÀÀËKKNö§Þ(+.<™ÜÕn—>´—"ÄErE‚ú"'×^ãöÌ5Þ{‰/ ƒyM²EðÀXÈûЉÁ€›¥„b¤8¸ø#s¯C³Œj”ÑQ •4§+_ZÁ™ÛW!—K-¯tNœŽ`¹vm ±†##Î5/òÒ·¿þ{Rç]à›_ûZVúoŠaà>ÓS׈“xý,<œ/äW”èш̺ý„~´B˜F&O¬¾ÊŒV¼ <÷ôïb5¹K'°¹@q´ßg>õð/^àÀÂU *£ãM2ÿ!è<D~àã>ÍfÓq2åi–––˜››cddÄÕ#Lâo*¥¾Æ=BÅw€ˆü¾{JÄ’/ P*YYYqgáIë¢ÖÁÎ& ü<‘YÚ[4—ÝCã˯0«à-sŠÏŸä}£)VL«ó‚ó‡ú<æ+†J¢_ºÀÈÜWP÷™ü‡Ûg—L›Ïçi46nÏK’„™™ >;Dÿà‹wî(O{?à°A|ýůz"üMiÓº°p›(ŠR6·~JV>ŸÇÄtÇÅŽ_m ÏÎEŠ ¹JÐX"¨ßfbéeÊó×y÷r‰Ï À@*,øšÑ;UK%VŒÝy‹¡[¯£š%çèi±ýÄí=è¢mvú²Õ½}? Ø$†•R,Þ¹ÃÒ%†‡‡ñ<cíw¾öÂW¿¸™6p±ö·QêY!ð}*å õZ-ìL> Cgk:bÜs(¥v½± l,¹P¬ŽÊ¹¥¾Éê4Ÿ=ÝË'âQkÀ@Þc¹f©‹btñÃó¯;?*£“:Ê:M_e tÜçlÜö¢/wÃu›Yísda~~žÃ‡IœøJÉKÀ[Ú—iï/~ù+J)õ ð¢³iUK³ %^RH›x©×j(µ‹ø^¶Ùˆò£DùÄ=cÌþ½‡NqöpH©a™YlдŠÑÅ·Z“¯£2^ì&_‰kY?¸óñÐZæs4jµ…žwƒ{Ì_]D>ÿÚë?þ4û…ßvñ/ òK­oÛõ/ßËÄÛ/ (Ö€ø±» ï¶-W¿¾èŽ˜áÈÜç¶úï4Nâ)Á 9pç †æ_‡¨â=IL‘,™£}ÑwÑw|>G½V[7÷’ÑÕÝÄ%8—´ˆd. ¼ü­ìšvøÈ=ÆûÛ÷Öºt§¬ÒÞù,~ýN«0ŒÏþ7VÍ D=^¹Èà·QQ •¸¨& éîBÛ\âj ÆöÅW ­ÿ¶¹üÁW¾ôüÿýã oÜ„”žÿâ—~Q)~mï[¶3hí‘FœØÓ5#¿v'ÝH1:ùŸ/Ä350Äu”qÞ=+NæÃÎUA©ð<Ïuôíe!à€?†Œˆý¾ÈÃ?HÚ­µ~x‚샠‹__¡¼àÒÍ”Ñ&BÙ¤%óe·éí"iõsÁótš2ÿHxLþêó¿ðÅúÆÛo­ù¿øÜ>#"¿ó ½ûADð‚ õÞåì|ÿý Äà5×(ÄºÕžÙø™¿Kês}p§—{º­€ÓÆpX?þ©â¯ò¹ü¾4Niå| Z¥'{ºmNÚÓxªíwZã{šR©L¹RiÇnÙö¼ n!à´z[GTº¡¥uÎN:ñ{°ÜvyÁ$ ÚÓœ9s†Þž^ŒIRßÀúŽ#âN$—{íÚÛyQJQ,—¾ÿ‹_ø…×ýóçŸ>ÝßÛK˜Ëíˆån7NJ)”§Ýyy){Ï~º3ô\m­4žçqåʧ¬¬­áû¾#¤%‹÷"©†¿Þ‹ÖìاÉ&I:áäСC­;6u®9¥M#›¶W°i„qC[öˆQW«Õ3qÿ‚¯´~¯T­üšW¯Ó~âVfBlĽÌÁÍmRwÿUµ}Ü ŠÅˆ`“—V½¯‘ÙôsŸ¥œ»Ö$¥Ë++”+î?÷yö–¿îtpï¼ÖÞûþÂÜÜ€cÉž×úéáyë»R³âÈ÷²…;–[Œ­«÷¤[­Ö3¬`Õ>q€ä>ïwúPŒ5xhWI½ÙÜú ÝÑ@WWlºúë~Çou‰¥Ð¾TZòLiíˆB{èôô Ok÷>«„••ˆ ΗֻÍ=VíoUëj7`i <±(Ô†äO²dM“îèõÂcŒÙf¢Ô=ßnÃi»‡R|¨P ¾1fΊÜPðTûÃ6<ºM¨tÂQ*­Ÿïˆ#SæÖ_ª­æÚä­ZO˜ngcí±mYúûû9}úô#iìJ)šÍ&·nÞtò]’8¹u'¬G­jÿðÁ¿ÿOÿÑø/ÿékÑW¾ôü‡´Àý!w}” ¿W&\©ubXWú´;u£E$*½Þ5.Ó|cðÃíyìõ^ÃA ´&Žb:¯¯¸“¼«o( 𠤎 “$ŠÈ_èú©ÛÀ‰„»;¼~üšû™™:Õ5Lb\Îç§&ÓO!àú—µ¬5D{P`sëçA‡¤pG)u Rˆãøã}kUîÛõ¶A\Ï÷ ‚cö§Ñ~AkÕJš±ÆGуh]*xÛsOD¤ )$Iò¾@Ø2‡üAÁC_.‡Ö cvVuìQ€ˆ%ð}w|¬1f‡ü‘¾ûx¥åÉt_Ër%3¸²¿Á‡¯¿yA #“Ü+7èHØd )àN ûi…J9€µ–ÕÕÕ=Ï«è”3n¾N)õAöÞøøòåèÉÓOt¨î?D„ -IûÓÊþ°´Lç(ŠÖƒ\–T„ù{®în/ü v¿ÜÀZéÖŽéG„˜oq/ˆ"Ø)n/,<ì&ì)‘ÕðáÕékÕìC{«ÞÇ)‚ñgŸ´h'€[ÀÛ–Çxx¯ýC‹®N_‹€xsãA"a“¨ß,˜ÀŸm̪‡m&€GJ|Œ=LJW§¯ÕÚ±™Þ€yŒO7ÿbs&ðMà_ǹ«¢ñcü”Cÿß]¿|DœñðÈx'ãáà1üŒã1üŒãÎ4ZòL¢àIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/folder_outbox.png000066400000000000000000000220061217176075400254430ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí}ytg•ﯖÞÔ‹Ô²lÙò.Û²¼Êkb;òÛ YŒC&ÄØ¯ `Â{@âCÃ@x„ 煜ɼ2&''ðfðƒç,2±! ÁK²µX«µY²ö¥×Úë{TUwu«[‹Õrb«:ß©VuÕWUý»÷~÷Þo)Š‚4&/èûÒøx‘€IŽ´Lr¤`’#-“i˜äH À$GZ&9Ò0É‘€IŽ´Lr°©¨„¢¨TT“Æõáº~|¢w¥DҸ᠒|Íñ*Š¢(Š¢¦àæ…(™æÏHÜg š²+”f¦- 4!•Šîàt0¡0~\q°Z­ (ŠfYÖBÓ´ (Šb(вèÇ2ÐÈV‹ŠŠ2×­[—É0 ýöÛo_¹té’O¯‡ ¦-À'f-WÖ¯_Ÿ³cÇŽC·­__˜3u*¦M›æÊÌÌôPišv±,›EQišvÒ4n·›¥iÚ‡ÿRZZúV²^' BȸK š–"##?þxÉ_>ø ¬¶¦†øý~â÷ùˆ$Id”à?ûÙÏî `:€LY¬iøäÁ ž€-[¶,¸páÂ+ õ ärUáxžøý~ÒÓÓC¡QUuDö_zé¥çäX iøÄ"¢õÇòÜsϸZS]M*ÊË Çq„Ò××Gzº{H˜ãF€†††KÙÙÙ›¬°šðè%-ŸDˆ€ýû÷¯¯ªªúƒ"+¤¢¼œT”Wç‰ „ã8ÒÓÓCz{zÏñÃ’¯ªªpï½÷P`9€¹¦ÈÐ ›€4SOÀÒ¥K³^{íµãŠ¢ø¹P˜üí¯%Õ—/I’ˆ$Š„çy …HWW'éëë#{` ¿¿ID …H  ^¸@ª«« !*QU•H’DDQŒX€þ~r­½  )‰üú׿þ-EQë¡™ÿD?«~ý´Ü`枀;v¬®(//•%‰„‚A‡‰opœ?wN'_ƒ,ËC §»‡\ko'¾$y€¾¾¾¶üüü{¡‘¿ÀDM?ù„tgЃ2eÉ’%YÇžzêk»wï~‚e-NÀ²,žGeE¦ää °°€¦˜¢É}¢ïST (Pz‰9~üøÿjlll×Oáô"AKÿ¯±i 0aˆ í{ôÑ»Zš›?Rd…ƒA  Ïódppüùý÷I}}}Œ&«ªªYQ$‚ D"€¶¶6ÒÙÙIþ‘e9æœwÞyçm†anCÔôÏ€fúmH ýé&`b“ÉÛ´iÓœßüæ7/B”p8L …B„çyâóù4òëꆘrEQ†@0$­--¤»«‹ƒÁðûý½EEE@sü Óïà€æõ!?ݤ1æÞår±O?ýô<øOfæ‚`0Š¢@Ó4X–E(BUU%¦OŸ…‹ÆT”ÈJ€,ËÚgŠÒB *: ëG?úÑË—.]j€fúyh¦_„Öñ£1ýæÊÓ`Ü0B;ÃÉ[U^^þ†,Ë$ ‘ îè…Ãa"Š"éëí#gÞ9Mâ̾ÙüÀööö’ææfÒÓÝMB¦~€?üðœÍf»šé_Œh¾ßŠ$¦?mRƒ­/,,t;vì«»wïþ†ÕbõòŠÖ´X–E À¥²2Ì™7 .L^³I¹ gP–µ^\Ц#N (Š¡¯~õ«ÿ*Bš³ÇA³"¾cr-M ÀõÈée8räȧ¾ýíoŸ;gîFŽç J"hF#ž¢(°, ¿ßK/bîüyÈ_°`Ô2"Y–#ÄÀÏþó×Ξ=[®†F¾aúBˆ:|åé&`¬0Ì=6l˜uòäÉ!ÇqsÏq\¤È²Lº»»É™wN“榦„fHç†ÃaÒÒÜL®¶¶’¾¾>B!uuu^¯w+4ǯQÓŸÔëO7×ÃÔÓd—ËÅ~ç;ßùâ¡C‡žÎÊÊZ AÓ4†1AÁj± »»å/¡pI!æÌ;ª‹Å«•¢(6†Ã0PdE|â‰'^ðAÓv€Íô« ªHr¡´ (½g¶oß¾²¼¼üÿ)²BÂáðP­×6UUIgGù}éïHKKˈšïš-ÀÀÀi¨¯'ímíDQTrâĉ_BsúVAëçÏà‚žî5wi1æ~ñâÅî'N|3 öI¢D‚ÄÄ ‚@ˆª’®ŽÎ1‘ŸPôúzzzH}}=éëí%ͳfÍú44X`&†I÷¦`ìˆ!öïßgSSÓûªª’P(DB¡P„xÞD¼¨“ßÞÞ>fòcÀÔ éîî&WH0P÷îÝû-hšoîés"®§/-×#“ÇÀí·ß>óäÉ“ÿSUU‘çø!æÞL¼¨÷ε´´·Þx“\mmù0uõwttŽŽòOžü˲Fºw´ž>7ôô¥`lˆÑz‡ÃÁ<óÌ3_èëë«%*‘x£g®µ¥…¼ùƤãÚµ1“ŸL´^ÀnR}ùrÏ’%KîG4Ý;Zº×ä1&òÓ íd`ëÖ­K/\¸pRUTÂ…¹!æ^àyødäwt\ù†Ä;€Æ@Ç{ìh¦´Q¾S¡9~ŒÁñK @†Ö³™™é|á…žƒF×Ðzƒøx­—uò››šÆM>!C;8}äoiié‹¥À:hŽß˜cþDe²æÌ1½@Þ·oßÖ§žzêû‹-Ú,DQm¤\H LY8Š¢À0 êêêP}ù2nß°Ó§O¿î›ŠW&㊢ðÛßþö”$I<´˜_€–í3úù“wöŒ€É&æyvyõêÕ3ž|òÉÿþ¹Ï}î+Š¢Xyž ±èûi†A]m-._®Æ†ã#߸–Á£Á&Ã0ðûý?þñõˆ¦ž%}›xÇ0™ &“g·Û™Ã‡?ø­o}ëx^^^!æ ‘LÞpÄSЦQW[‹ÚÚZlºc¦M›–š»ŒkVY–EGGGSkk«zŸ^Œl߸ÚàÉ"‘Á˜äâââÂgŸ}öé 6<$Âá°¦õ4™@€hO\MM êëêpÇw {Ê””Üd"E¦( úÓŸjDQ é»T½(KÊ7 nu0Á–<ó?øÁ?|éK_úvFFF®A<Ã01¯m·ýEáÒÅ‹hjj–­[‘ú»Ž³•••õЈ6È·æ¸À¼€ 퇒öîÝ»åØ±cß[¼xñVA h†MÑÑU ’ÏúVÛhß575O(ùfVišF0Þ{ï½h\¥Ìô¸U bîW­Z5ýÉ'ŸüÆž={þA‘;Ïóï=žxíc,ñÆ`èííESc#6oÙ’ròãCjBX–EOOO[mmm¢ãB K@öb`0Ål6sðàÁÏ>õÔSÿ”——·’ã8x“‡ŸŒx3éFHØÒÒ‚šêjlݶ SRÔæ'ƒÁ(MÓ¸páB$IñíÊ’/·‚˜½{ €T\\\øìŸ=¶aㆽ¢ ‚ s YcïÙÓt„tUU … Àólvº»ºÑÞÞ†eË–MlâËd Á<þ|ƒªªŠ~„j*)ÁÍ,fâ@ÎÌÌtï{ß;úÈ#|Û™áÌ sŠÃ2 C9ZùdYF @Àï‡a)Ün7òf桽½½==(Þ¼n·W®€¨*rÇóøpÚx?¥ºººOÆ@”™àæs"Çpðd¯×›µÿþ’£G*(((E‚(€5̽A¸nÞU¢¯ Âï÷ƒ ‡A3ŒNúL8N@C}=êëêqÇæb¸Ýn@ÞÌ™hnj˲˜’“31OIh†AWW—ïìÙ³ú³Æ?©œÀDÄK………¹‡~àþûïß?þüõ’$ÁÈä14­¯&ª ^ ¢¤Ó <™Ìž=.·;fªU]m®44àŽÍÅðx<‘ýv»3fÌ@ëÕ«`XYYY){HhÍ´öpp°CÞôu¢2.|Ò€Š+€´zõê9G}¸¤¤äáÜi¹Ë$IÇqÚ¤ =¦§„ˆ‚€>¿~¿aŽCÓp¹Ý˜=g<OŒÃgàâÅ‹¸ÖÖ†Í[¶Àm"ß@fVr8­-­`Y.—k\™¨S¢(444´ ‚Àé»Ìíÿ-íÆÇñ´ø—lܸ±ðÀ_())Ù;eÊ”ù¢(‚ã90 –a42) Š"Ã?àÇàà Á hŠ‚ÓéÂìÙ³áñxÀ²É»¬¬ íWÛ°uÛÖ„ä˜>}:Âá0š±pÑ"8ŽþΞ=ÛJ‘¡ñ”rí>Y`&Þ˜J-À–Í[ŠŽ=²ïž{îù‚ÇãÉåy<σaX-P4 UUæ8øá÷ ¨ fΜ Û«Í:â œ?ýý¸sÇöˆôf) ³gÏF]m-¯\Á¢‚X­#_cXèæß@ÿ5D›¼[Ö$Òx…a¦¤¤äö=<ðå{î½÷ïN§Ç že0 @E‚A|>‚«ÕŠ)9SàñxƤ•~ÿ}ø|>lß±cÔçY­VÌ7µ55¸ÒЀE‹ƒ5  LäÓ4p8,VUU]…¦ FPÁ-æm{Dã­V«m×®]}ôÑ£7nÜmµX켞Œ±Z­`h²¢ÀÄxð.— 3fÌ€###a»ž „|ðþŸáø±cçNØíö1=€[÷'¯4jÍÁÂ…ã^:—¢(øý~©¢¢Â‡Ø `JÍ?ðñ ÀäÝn·íÙ³çïŽ9òXQQÑÝ,ÃX$Y†$˰Ûí „@ày‚A„‚!ŽŒŒHØÆ\‡æÉ²ŒÓ§OC‘dlß¹cÌäÈÍÍE(Bçµk°°,æÍŸ?æ:"€^œN'[PPàúè£z›¾iûÌëÞFˆw¹\®‡zè3û÷ïÿÒš5kv©ŠJ©ªÂ0°ÙlPd>Ÿ¡`’$Áj³aêÔ8].X,–äWŠ¢àô;ï@–eìܹ¶ë$ßÀܹs …ÐÖÖ–e1köì뮋›ÍFçææ:%<¥Ä˜h0·ïæ¬äv»³zè¡G~lÉÒ¥ÛUE,ɰXX0,žç µ¡Y —Û —Ë›Í6î›â8§OŸMQ)!Ð’äç磲¢ÍÍÍ`Y ¦Ï9[˜¨ÈØÊ²l¤€u¥%‰;@ë“÷î۷テ>ºhÑ¢ÛE"Ë`*QàóûÁó<(ŽŒ dO™»Ýž²%é9ŽÃïJKát¹°}ûöqY3YEÁétbÁ‚|TW×àÊ•°9cÈÆuӇÆèÀ”¦€ ¤ZÌ,E–I -\° w×g>s÷þ}ûŽ..,¼M–e(ŠŠAÏóPv›999p8cræFƒp8Œß•–Âíñ`ûŽ×å±›IßOAÎÔ©˜ ¡©±uµµ`G“-4wAë²ÛíLvv¶7I¯ñâ,X0ã‘GÙóù<4sæÌe’$A’$(ŠQ IX‹×åÌ>Ÿo¾þ¦åNÃc ?áÉŽUUsæÌA0@WWjjjPTT4êÐ’ ý7™ùÿø@*Ö.O`ÿåGöìypÏ¡™yyËDIB˜ã Ë2YESp8Èž2e\fx4ðù|xãÔ)äNŸŽí;vŒ(dc%]ÿùŸf,*(@(‚ßïGkk+/^<òM!à„YëýæÌOH+V¬˜¿wïÞÏÝÿýûgæÍ\&ŠÁ`¤´Ùlpd:RâÌ]]øÃïy3’’?Âc¾Ó·²,Ãf³¡`q!.–•¡óZfÍš•4»hî2Ãétfbhò'¥“˜4>ñs<¸÷¾ûJLÉž2/Ìqðü ôE)uæFƒÎŽN¼~êòäãÎíÛcÈO5é$z0@dI‚×›…Y³f¢¡¡ÍMMX¶|ùz]ߨGÓ4ƒ¡)àÇÄi¼qcÒŠ+æ8pàá’’’G¼YÞù†?€ÅbËå‚Ýnò‘7 xãõS(\º›7oŽLº˜Â«êþÀÜyóÐÑÑöövÌš=™™™Ã^7îþâÛóh ã$ ÄåË—Ï=xàÀÞ{wí:••5Oð<»Ã»Ý ˂ҽx¢ª€N@ª=ûDèìèÄ믟’%K°yËšg=ˆ®¹ ¿3o‡ó± Il6òóóQVV†æ¦&­Z•èâÑw¼™v[­V¢M€¹hâ-@‚6л}_Ü·ç=|%''g¡,I „ÀãñÀb±D&„€¨êQ¶ªªN¨456âí?¼¥Ë–¢xóæÍìx´<昸z­$I˜9s®^½Šö6Í Ä *kûÍ÷Ë0Œ98!~@BÐÉ74ž"„ùóççîÛ·ïïï¿ÿþC3fä-#DË0pfdDÆÖa õhQÆÃQ ªQ‹ ;„©Æ•+WðÖ›obõêÕ(Þ¼9r-©ÔòˆÆŽàKȲ –e±¨ g?ø ®\¹’tTq| Š¢˜M¾ÙLbÀ¤õFH'¹Ün÷‘#GúÕ¯~õ•ùóç¯3V¾b-–ˆÉRuM×ëІmH! º ºÄ|M ò׬Yƒ;Š‹˜Ìþi¹:Ê‚ ''³fÏBsK3zºçaª>—0$¨kúôéV˜Ä …£ DÀ¤õ4ÂZ,äÁ={îyôÑGŸX¶t骪‚6FÝ@ëL¡õ¹t$ZGÄÄǬªPiZ«X×þTZ+ (--źuë°qÓ&Àd‰Ì˜(-9/Á±ªªBQ,*(@{[jjj3uê°u¨Š‚¥K–x(Šb!‘U?ãeÜ`!í½²jÕª¹Çÿî›6}‘fJ5i®jj×UB@ZލF›…@@ëB@ôfÚESâTTTàgÎ`Ó¦MX·~=TUÕî7NËGŠ.(Š‚ p¹\X°p*+*ÐÙÑyyæJ†Ô¡_{ÂB@ ¶  (›6nÌõÕW““3u…( Pd9:?θºáØé¤¦Þíy¢šiôfFó`:îzP~éÞù¯ÿÂÖmÛ°vÝ:(Š¢]£×òÈçqjùhŽE -Dss._¾ŒiÓ¦iÃÙ†ždþ]Ìá_êA&í§\.ûÜ¿üËsS§N] ‡AQšÙMD‰B*tí'Ñ!ÍзÆb £Èñ«d¿ß/ɲÌɲìãyÞ‡}Á`ÐWYY9ØÜÜEqP„AEQ¸uk×~õ¶Ûn/X½fMD GãÝGþc^`LÇFwD¶‚ Àívcé²eøàÏFkk+æççCQ”!ç«ªŠœœ¯ÍfcyžŸˆZ €RRR²cùòå%¿–Á#”F4 *B¢ÑîSú´j†¦ašÖ%Š¢ÈÁ`Pæy^’e¹_E¿(Šþ` 0ØÓÛ<îÜ€(I>Y–‚ ƒA_¿ÿý÷ßï•$ITUURUURE’eY’eÙXÅè^¦~õË_~Ê›í-¨ª¬Ä”œd{½°X­ ªšÐVN¸–kÿ;Žã0gÎ4俢ºº³fÍŠXȵ( *!`Y–Õ­€9”RDšByíµ×´Ûíš›Ú@UQeI•þþ~IUÕ€"Ë>A}¡PÈ …üeee}}}~EQ|¢ ø8ž÷ƒÁÁªª*_KKK"鄊²,‹¢(ëÜÄÛ~ƒ\ã×3ؼOÑ _¼x±uÍš5ðûýhokCoO²³³áÍΆÕfÓš%U½¡Z>äØ¸Ï¢(Âf·aeQÞþýÐØØˆ‚Å‹c¬€QÑæÆ“?!€¸œNë©S§êOœ8ñbMM §(ŠO‘å0/¾@ 0Ðß×øð£E‘tBE];EEQŒyk澽݈À,½†‚ª¦ïHÜwñ&ϼ ôôô42 £ó'Út¯®®.ô÷÷#++ ÞììH§ÓpÉ ”j¹éF©øóôÿ¹0‡©S§bÞ¼y¨¬¨Àœ9sÀX,šOeº†ÍfsÑZ{šì77" SŸ))ù)ÇqZÀ†èÉfbiÀœ¸PãŽIDd2¢mÍ0æÊ5S4Mhš¦€ÖÅŽ€ ¿¿>¿YYY‘Ÿc¶Ñ±[ó±IÎUœG% ªªbùÊhnnB}}=–-_ÅtœJ¬V«‹¢¨øy)EÄP8Žcô}¬~¯ ¢C’Œãâ 0<¡ãý¿Ï°.ÔÕ«mÍ¢ Š ËÚˆJ¢ß ZÒA›ÀírÓ©Í0òC.0F-OxÞçýxA™™‰%K—¢ª²sçÎ…ÝáˆI^‘ص€RÞþÚê’æ¶UæhñÐÞ>aã%D¼^Dת3¶†“f^Æ,Q1®cþl~ÈD¹ïxá ¨sçÏuôYX4Mņ¦À04,, 𢠸Ñqíº:;‡#SÄ܆a!€ªjä™rCÆyæèCU‡œ›è<#$TK—.Í0¨©©Ñ&´š"Š¢Œ(Íä ¤,´›"qJ˜d~RnžF‚ªªa•Všaòè‘Ì:Ä #Ìqp8p»ÝºET%VÁ’™õ!Z>LÆÑ|nüyŠ1çÁáÀÊ¢"|táC,Z´ŽŒ ¨² €Åbɦ(ŠAre7"N‰…š $Eªoj  ¨JX„«,ÃFrÃÝad/ ··=Ý=àÂÚ}*.•ƒ¢((ª ¯×kÙ¸q£ÑÞÀ”ãfÍ0­EFŸ1<ÖBë[–eÁê‹Jp‡ÖÖÖΗ^zéåþþþ†¬¬,dddD¢‡!c-NXÑê1b5V¯]ƒk×ÚÑÙÙ †¦a±Xh¯×kÁn^0~ ú£?löûý¼áí«ÐZÔàq»åþð‡?>|øðÿX±bÅC?þøceee¥V«•óz½‘ÄÓ˜›¢ê…DbIQ¥( ¼^/ò.DEy¹¡5š"L[€ Ë+*ú@/òÚx…qЦ‘™•…_¼òÊK¿øÅ/~€ì}á…þ³¸¸øËwÝu×]'NœøI(¬ËÎÎÖ&{èyû-OD¸Aºñ¯þŠª@’$Úè¡•+V àóáZ{;¬ ãp82µ@ŠáfX– SÕbtT§deeá½÷Þ;ýÍo~óëõ‡„¨², ï½÷Þß8ðÝ+WÞõµ¯ý‘ŠÊÊ7­V+—™™©-Xa4 ÀP‰ÙJh*¢9Chì —.EYÙEÐ Ã8].¢áyº ˆ‡¢(aßààUVžBS2tvv^ùú׿þQ—0†›üRP}}}½Ï?ÿüïßµk×§_}õÕgƒÁ`mV¦–rÖúÌ­(áéD— sjD›OPPPBZ[ZÀ0ŒYûSŽ›^8Ž“Þ*-mvº\× P4 ‹Õ PTðk_ûÚ÷êëëÛ e2Íïá5²œæÌ'$I’Þ}÷ݲ_½fÍÝßøoßx¤²ªê †e9O¦4C !<¦èΤªªE€æ?Ð ƒ•+W ¶¦ªª²˜À¾€›^€çù«ÆÚ€cŠôã333ñ“Ÿüä§¥¥¥g¡ýÈùFJÛœ¦6R݆0hV¡··÷g?ûÙÿÙ¶mÛþÝ»wÿÝk¯½ö¬ÀñW²<جÖÈ X˜"s£.IR„aI’7s&¼^/DQœŠ J7·˜5¢•¡iÂ0̘½~oV~õË_þç3Ï<óÐRàæ×¯Ç/Ïn£“FF¬U DQ”ß}÷ݲƒ~÷ÎíÛïzêØ±Ãµµµ°Z­‚ËíŽdãóº²,G^hI¨5ëÖÁétЦçM9¨ÑtŽXÉ œòÙ´iÓ’·ÞzëC‹ÅâˆX1œN'ªªªþ¶mÛ¶G¡‘B”PsOh2$š/i¼x’‚özçÎ;—•””ìÞ¹sçgrrròUÈÞ?Bìv;lv;TEÅbAWW×¥ûî»ï¾ÊÊÊÄ®ƒñpx³ €7QÁIDAT²Ûí9µµµçsssçÊ’<âIV«áp¸çî»ï>|îܹ hÚ‚&£%?ñk ¯¤3úô‘ŸŸ?ãÓŸþô{öìy`ù²e;, ‡#Ãì.—ñ“ÀÃ?üùS§NýQ¯KD’¡ãâ0Ò£|Œ °n·ÛÝÒÒò'I”H8¶/$„H=öØ?B{óv>€i0½}‰{DÇr_f°@{»g´wüÚ­Vkö½÷Üó©ùå¿ÚÚÚ×ßßOÚÛÛIoOQ…üøÇ?~Ú{³  ÎIzOãâîV»ÝÎüõ¯}EUUÂñ\ò¢¿’B^|ñÅPM¦#î%Œ)¼?ól+‹~ 4aËàZ»víêçž{îø¥K—ª$I"gΜ9e±Xf@{)´ù½À 1éŽ?þ}BEqØB!gΜ9c±XŠ ½|ÙxõºÑ‘Pu¯‰¬‚S/v¯×;÷èÑ£û–/_¾L¿'ã•ðF3’“Y]ž|òÉÄ"ËrÒB!]]]wBÓüÙ¦@#ß‚%³ úó8¡i¾ù¾’ æx¸û¸—ŠMȲÜ@¥“Ì5Ó{òBün]]]+4'ÏùŒáio'ºgÓ5ã×`0O°$v'7¿ Ð6l(äy>H†Á3Ï<ó}D¾\híð°Ö „9Œ4Š!Ãb²74ÆápLëëëkLFþÉ“'MÓôh0€©wúƋ뺴ŒÛívwuuý)ùuuue^¯w=€fa”ÎÕÍ‚ñpwÓ?<´¶‘’$)ÜÕÕÕÿe(êÛ¿ÿ? ôCKïÆ'znT»ÿ‰Ä­ žç•×_ýjÜn娱cÿ|öìÙ hDݼ‘W¯ßàÛüÄáVáp¸Ù¼ó•W^yéùçŸC;y&lŒÝ͆[J$Ij„>zæüùó§:ôSBˆ9Ü3ÈŸÅnJÜN >QëׯÏWEñù|MkÖ¬Y O/7"Ó÷±a²G€7»\®i„:t´0/€Z†íFfún(Ò [§Óé>xð`‘ÅbÉ€¦õætê')ÞO)ÆÃÝÍ> r ¦¢@‹ñµ â_·vËa<Þ }@,±4´0ϼÿ–%¼¸Uˆ%XI²?8¤¤ HãæÅ-é§1z¤`’#-“i˜äH À$GZ&9Ò0É‘€IŽ´Lr¤`’#-“i˜äøÿª˜V»©IÈÆIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/folder_sent_mail.png000066400000000000000000000232271217176075400261040ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí}k°$Åuæw2«ºowß×Ì;3ÌžÖ±z!´k‡íÕnìn yeÉ+Y‹òÊ+IöFø‡~Øëu„Bâ%Ùµ²²#,‡Â–„„#´ f†¹ó¸ïÛªîжœ°˜¹3ä2 œpë}Ï|`óØÈßÜpÙLÕÊ)TúÌëÆÈfp/šküù?Í⥙Œñ MÆ«‹ ;ãsˆ¯:<†îp~½`ˆàOn¸l6UK0†»öö3…öÏ5qçNàø‚Á‡ß¾ ¿õÎ<ãå¾whâ"w\úu€a@€[ï{æús§Ç÷LÕÊg<ó÷Ï6qçfA øà['ñ Û*˜k2ö/Û;õ·â9Éã]7"ˆ #6Œ˜Å2ÁŸ¡§Í¤[èíiú"Q~èðõ‡¶úM:€$ŠÏ°Ï|×ãcc™Ïl5‘‚îà"5¦) åv''¢‚ÆÏ0·Çg™`ЇSEz}Ä c¬ pñ9f ÀFr†EvLH‰0thòŽA¯÷§#ï~ýÒÃBâ1>fAÛOÃÒ‘ñŽm"v…? pÚ¼"² t\î`î†Ì€ ÈÍœAý·ÙÐ#€ÈÆ ›Ú9í>2VÉ‹Íߦé]†{_’+éGæú¥lˆèbìq‚ç2+¯Ü³Ê8,Ä’A+¶oºŒÁmy½ïÊWúÚ„ÁQ:•É’ƒ~§*f½”Àa@€šïÏ‚dÌŒù./!axrN¡½§ºæÎ¬{Î&Ñ^¦‘̃\ŒDiz‘¦5§‚ÓYàùƒ•!HtW&Ú×^ª.eÉÒ:ýÁÁ7é—††…¬]Ö´f>',ätxá£C‘|´0‰NV£Ãá¬Ò\ïÛH²ŽœÄù²Æü)9Üv=Ú–Ž3ÀŽ‚‘«G±l¬ãð:dÄûhåÉYî8Ï]†çðÎç\³.¯´%CÌß;‚Î&ð« ,€Þ¸( ÆÚœ.q2¿WäàÜ–B-߈’Þ”÷“aÍν*²n C†XdÍž®§¼¢ækèŠÕ‘\Pù‹‘@,‰iyè @€¯ÃzQŠúâÍÛ !9ªÀ\v0ù01¯ñƒМL%Bu&„:bÎ̵D€øú€ß½)? øÃ…µZøïhIDçác5zèFg’ X@@…é› …úû^?Îù$µFÈ™~]Yën 6‰ÏÓ™!âþ["€$Q Ö¾‚ÉÀ{v 2"Xs/¹é¤XaÉݯOzè·ýDo‰ãšûHì ŽòŒFê,"=³¤CråJvèå_èLg ^þ°¡{ŒJ!݈6“@[Cpš%IÍÃ$V¯H‡˜³I8™: ‹ øÆ¸k:šJãÿ¸0¶Sö[’?.î`~X‡26ZìXo¿»p°\(w2ØHÎ;d›qÇ7ùA¤‚õS‡Y”ÑOYÀéfR^ÔŽä­{©@‡‰„"¶±‡„¢„¸=ŠísÙNm„ øÖ;¥¨cˆKá»%çúͦÄ^Æt&q6!ÀjÓÀ“¡n‚°nÞǤK‹ë% @Þý³äM¿(PΘdo2˜ÐÑÐ#€_´¿D|=©Å备¡|dåã}a(w2ÛøÃ|…,ä§ÖBG®ÜA|CÌ’ ÀÆo ac¬Þ&®Ý„ã.¤ T»} W¶‘[`’%š?)OHDlਠ4egVšñ)+-ä»s»]³ òí’óê±çÿ/„~[K_‚:þ\ß©^AiÀˆ$ÑB>ËÐ#€(Ãù^‹¢ tk/ßfdSAüCiº6¿ïôqO„m®Þ#_:#`Øiµ:ŠÇèbd°O®'3[»¿¿R(gòG J[¨¶2ô°žÁEV±ßÓ§aÊ9p”—6¶K~:l cí½ªC ¨£…ú`³¦×à4Q^´_TªÚ© ›óûió¡âÒî8rD@+¬´Ó†µ¸µúÔï²ÛÓ@EMÞQ b…Áä–{}‚=”7ƒpççê«E µÓÐ#@?Ì/n“æŸAȹª‹v Ê´þ(vÛÇe»“(oìðeÀÀêþãÍ­ .=Õkéë€#KŒƒ 1^ž‹relý£«Q$,¹£Ÿ´I†3'¿”[!lŒ qšÆGv–ÀDÏ3Éw¤ií¹V̘[q à:)ƒ À¶Q…Nò4sË}W¦[ÙŽXÚƒ&û.g ˆY ²h/¨»æo’qßxÖAåÍùS72²“ŒQ³õü®$ýÒÐëë= ðÑ ›0tCŒœUo{"›º±7v§ã¾É ŒS)S7“HëïÊpl!Sþ^_Ô'Q¡ß¡bàJ½@NKvàŒÝO°½b™©Øõö¾Yv—1°Ø\Û ÚáG€ÓP‡µê« ‚ó $?Ó $´‹™ó«¼ÄÅpñ6°ò,‰GL.ï Ki††AW£¢ …Vàá~ò;Uæà…‰õhînKä'–Œç'¬½†DÐîRê†Vö´¤»ÎÑãïfó{=ß9Ôãñ-Kº#ÈZøuF À»:°Š„ù®½L’$ õü^TP¡< Ó ŽÌÇ9_À -u ÀÆ×ád) Ôv¥O)B2‚·ï&^˜ …bv™ÑŠ|±\ ÎÈ›RW£N0¼a$é¼Ýntá·SºÛ; Õ²º²Çxç ˆ#ó¦­íEËáG€Uh=}†(66ÄsïæËûÎ…a &æ }³ËÍÈ Hg/À…ƒq¢H¬]èd"‚-e+•WMÛóI¼xÞÎ vÝ¿t°f[¥1늆9éý?B ?œ¢* "‚ÁÖÜÛò‘nsï,´ä•ጠÊß+¨÷}ŒŽ.rê8ò*y¶Fâ4(õ„µš~cf4¢lÌ/Äzfkú’ß`y$7•±V¿™ù1’kl£¡@€ñúýÊ›qÅš ?ÍÄDÆ åCsjÖõ ;”ßö¦zN òvÃŒŽ-4Š?')·ŠÒåªÕ¦ª¡šd Ühò5çÜüðr#â{æïzç‡þ×ß¿ùò›lü*ßnÄ,¨Ç¦«çÒ5câròz¶=ã¦x䥵FÁl=àr“ql±{x¼týÑ›6Tˆ°¬i|S58oÓh¸kf!ú7·üÊŽ)|ú/üÒ/~ñ{ÿsûdð+vmÆJ+êûå §“bÃh È»}(1óæ7…Êì@þE`$¨`õƒ'¢53¹­[DР4ñ±‡ DA¨Õh¹¤wmš(]–õßù—Y\vN7^:öŽWïýµÞ #œ„I­éV\¬ýIvÊ«Gõ(oŒñïÙïÚʰÝû˜½à4Zȯ'ܰ8åÒwb¾ +çŒØ%L…t¬hÄh5Eåòå³ùÞŸŸÀ‰ç`Ïõ—ãO¨ÞöýãxËîITJ:m$ ¿yx7f÷ã}ëY.·÷úN÷ºh÷þîÙyLiÌ,ÄÈz›Øní{ƒ/a˜™‹ÑpoëGù†¤È¾ š.“ çIöÆ¡Ú>¶e³{§ñX8‚ê;ö¢\ ññ¯>•§S! soö{y?=}PD`4b“c~¯2nºz÷?3‡kÏÁRÝ-0õÚÎmôι2_›‹°Ø0Ùµ.ÿdH‚Ád`ãÞJ L ‘(^EKl΂J+”(GÀOç ¥k/ÂèXÿê³Xnæ…Xhï'3êQŒ(±é÷“§VRøðÕxùØ"~ñMUÔ›‚f$¹:æ4,Ì ClGX\á<ìw9Ämã}ÒÆ!@`W¹š€«:i4IÛ­R´5†þq®½cc|üÎçЈ¸mŸýõ¢Î¨"Xnƨǜ¬T¼Ü£7pîfÁö‰Ð>cÚ«‘öd†  ŸˆQofQÂ=nǃ¡G€±Kn"Þ÷"Ó"bC,„¬$‚Àíª   àÁy tÝ…˜Ü\ÆÇ¾ú<Qbb=E³T»1C=f¬D&ÝœDk¾J@ ‰ðôl›Ò^+l°¸Â8|"F3êçÁ†wªÏírÚ`쒛ȟxUI}^‹ÄJ+!A(¯—j¥¸ï8A_sôH ñ`½…€Å¾j%2é‹ R¡_‹Y-fN4P UnˆŒàµYƒc‹¦ÇXŸûW˜AäŽêtJg ³ø¯H°ß¥¹¨¤>Ozl"aE$P¤¬œr.r„‰füÀ à×]ˆÖƒÏã£w<‡»þëÅ ×gé8‹ âì>)´"ŠÀÚ®ÚᤆýêþK\8 1‚ùel=ßj °C¬‹%Ðc´£"ã‹   k1M 01)0€@’Y%›" 3ŽÄÀÃó ×^z¿~çóøú'.:)!H_éVàÈ-ÓRDµJ:Eœ¼(©ÒÐ}ÊÙ~a©Éxm6Bw~o*•+šä|B}éÝȃtÿPÞ§îz˜X£± `L¨ Ê ®& H²‡Zñ‘HZ€GæÎyÏ^ŒTJøÈמÇrÓ¶ä ÃAÄŒåÈ`¥#ŠÛ{}‘|(B­¨îíÓk_¡¥&#ŠÑÓ°“R õ¦äÅÙAŸ4zºÿÝ1½ ê;\SHZ+JØŒ€#D“Êm~ÓVû¡€ï'Üxý^Ì<ð">ú§/àë¿y¡ÝIDº+j«õön”ù P¶|E¶ï°»™Üônµr%ùëæïÅÈÏÎéÛÎöº õ?|÷€UîÎõ:T—ïöˆ¤„5J);õ#Ímž°ôYÅ@@‘‚÷¿û|ù‡ð‘?݇?û½¨–˜mo{³÷É.3sÊ`œ¼¡1P„ˆîáß·K9×K»çéZœßÍ:¥Y¯Y:Cyà}°pø×rC‰hű.“è²¥” €D[£ˆaˆ]þj¿Çö†1" Õ`üÝ aë{.„.•ñ›w½„zÄ`XïÜR+ÆJ+F3êî©[ )²Âî ´†2ú™ãwÍËÞÑ!ß šC€éß}‚$ñ?ú«BRXš%ŒT5Ø!I«Ä‘˜ L!ii®T  BPZ¡U*ØÀ›B01H)5R›¨U‚ÊØˆ*—ÀbMX!i1Ä(øÛaIò'1—ƒaõ ¾HᆷíÁþûŸÇ‡¿önÿðnŒ„ "8…F£µÁœÁn­”ÏÛ¡ Aàßݾ~v¨A¡&å”pE ©ŒUQR©)Ò-&UÆ”°!˜€há)TÆ*Tˆ[‚"µYIÜH‚$ T ”ªÔ*•Mc屩‰R%”ºþ²Qü,<^Œ¨Ì÷힇ȭ’‘T &6¸ï°Æ»®»ûü">ù—qÛ‡÷`$ u‚µ†‰å¨ƒ¢Öw4Ï*ɤ4>Ÿ¾ûµm²¤~>ÓT%EeEjB)šPD“|é•Û•V›E©M ØL*˜T& “¦ ÙÛÐPv|!;'%Â"’8€D”&$ G”ƒJ8ÞÒå-ES¹ñš ~õÂ~ýg1¢˜ ¼'ñÌ>öæ&bõ­ƒøÊÜJ¨úÒ ÖJ½¦Š\¬ç:P±CôKjæ÷.akyã˜IbÇ n1$2„Ø@bÄ"ˆ™’é ‰e®ø»x8Ë]š.¶!±išB9~:Éý6…ßíùŠ×aZqk?=bpñÞÍ8´Døí¿9‚F$ëÊ|7¤ô*&ƒÒÇ‘XOsq‚}P0ýÅçIUBHòVÂ|¯`$Ã¬Ø  ¯¤·*´¦C„XÚ{YÛ˜ƒ b$—0Á~Ï·£GÑR¦´"ƒŸ¼&xÛùcøçŸÏá÷¾{p㌕×ÃNÿ\•Púff/ß@ D¢¤b$K”,¿$V™ŽÔ“@n´O•§¸)@3Äó{§Û™/+½© .mfñ_­é>Uñ»²¶„BXª¼2 VÑøþ³Ëø·oÅ».¨Öbés¬Ý*èzlO@.W-«"Œ@"Ó!šÈ²1ñÔ 1EìbF« ŠcJò;ÙâB”´uIJ$V}«jº·%¹r,€¦Ô`˜7¬Øú(k[ !ˆ0H¹ëd§@q LŽh,œháøb„÷\\Ã¥[Ëkj´“žA8[J™¹Z°H7?í€,c82ÉÄÜ1ÕW,f*Ø5î¾õÆB’[×Dnë7+¼×ŒàÞzE«ÌQ dã ¢“J$!BJidð@tVO¢;ãîÅÆ†^MV5FËÀ¡ù&®Ü]żo “#.ýê´Î–vîµ¾›·¯BÖ<™H)PŠ`í5੤ãå…ýâ7|¡ mn•\φ;¿(Äbì:¶5êˆo ¯$¥¦ùsö¸:f÷QÀæjˆñ«³—o«â÷ß;…J¨`¤÷[ÈÖ›é¶b™Ž“VÝM£Oâ~­XÍùYs`n&z¬ß|AIå€Ðˆ…춤IO·T©MƵ)uR*¶<:k~E†ùé“q¥•liCž óJ÷Õi²:øˆeóF±`ºª±iDãå-ì.ás×Obªª  (éÎÌ?%Œ÷Ëç‚3¨ß^ïeiEX˜_Œ,Ì™s3ñæ/x S³ßº%­1^V4§‹ ‰©•Àî•¥î@²pÑ”NÆ}¶pMbÁ×(B @ Ûà ¬uÎ!S²#v"ùd-ÅÐ!AÅvçlíÕ¥kì{»|Xæ+B#fl 0U#ì;ÖÄÞé¾ðîIœ;`´¤PòŒA§šáhPèŽ š‹KæÀü¼9pâÕh_sÑ,´%²íY‡ÂSý–„†Ö ['5X¦$â%[R­ t‚½Îù#‰2# †Õ °ÝõÚú ’QDrªCú†LW†. ÏÆxö°éìÕ 9þKþ¤¤å$j)ÍXpÎX Û*ž>ÚÀ¥Óeüþ»'±c\c´l™?hüüºÓ•û°Å,–ásæÀüÑøÕ•£f&7l3dÌ¿íèwßr¨ß*tŒ€ÂÄ6 t@ ‘V Š¡"Q$TàPièLç#aˆV ck¡È¢+R bÀ$®"‹#‚!ë/fÍ©¦`_°ÜýIÛ†§»Øa#f`×d [Bàéãu\²µ„/¼s;Æ5*¡B è¤§A©Í÷OQgiÙ8q<Þ7çÞVË_Èì3ÿ{WöÍ|¶Æ /EˆççMnQqCM&e ¨ÞJ8h@„¡D fÛÕíò ‚À®¬1h  V ZBv¿[óc`Ër ¥âšÉŠêNíà«î#6Œí£%Lמ>ÒÀe[ËøìuãØ= *!õ=Ü®u úH*¾¸d,Ì›WçÇÆú/8ùÌœ-‡Ü6ó½·Ôh¹^P©P#^‰8ZŽe¹̈@„hA“†`Ÿhµ½Ð¦je©À6ˆ;YæÈ@€9°ÑûJScƒ½%™ö+- 1¢HÁP¨X—€ 7¨¶ÆPëÒ:ÎßUÂsÇb”¼¹²x±]V1õ|°¯YÝ1VÂôˆÂSG[¸tºŒÏ^;†=“FK„Rpú˜ßñËÍxßkGóG6›ÖO¾»ðÈšËwó ·½÷-õÕî߉‚ïþ÷@®»ý•x!’å&K,‚* J UaŒa\ “š(+‘JÂF#n–¹^/IÔ,IÔª2G#dXs² ‰ØØQb"(u**Våš¢êæ°<¾{t¼tÉî_*‡‹#ŒÃ‹ÊAuʵ¢­9ûmD°}LcK-À3¯5qÑTˆÏ¿}»Ç5*áéa>K{ÃGÆ<µØˆ9|béá{¾ûØ#?ýû•‰±K/ýÄÅçóŽ5ï¿”ÏvÀmGpe½sâÕ) nÄ+K3Ä–B",ˆ ¡¢2)‹¶+"HDLl”&4#ÍõF…ë‹e,/Œ£U¯q«U&J"œˆaýÍ&fRa€òè(U7¯”)¨P‹öÒD)T¨Çí›uŽCL×4¶h"@ºÁUŒ è?®³7#°= ÙÂД„SWpz`,ÀT•01BØw"Æ%!>ÿ¶¶Õ4FCËüubÿ‹<àAß>wsm¿»0vÉÇœåÞ™4ù%s]I Fü¾µÂ=Çî¿êŸúMÞ­y€¢sÍÎ2Ÿ½›Ç.¹É!I Û8@=ù]KëÍa#DP¤ˆªi5$›GÙ{xÖ`±{ìµL•ãxyÖà‚M·\]ÃÎ1‘€P>¹1À,ò €ÎÝ\{¼[ÂÅgï–±Kn¬û;8èÏÐÉ=ÍÃü(°.ÈŸÒºïš4L÷ §ºroI!Zˆ$ˆ¡Ž°¡Mé L8çC’3éùeB- 쟋qñ柿ºŠsÇ*!¡¬ k@þoÃöðvmªvexòQN!¯ÞuƒØ‚ë§yäO]|öîu7a’B’Šš ¶ãÆ¢äP¥J )Š…¸E*(K¢ úÓÀH€ñ²F… .E¸h*À®©bGM¡¤í?€Œáô—¥3%ÂNÈ›ý*´ëI÷_mñ§G HóŽÖÑ/<™zö¢SºWp2$à9d`(%Ða™”n‘R,¤@PÖýà >‰:± 樈Á‘:ã¢Éÿãš viT T=™ÿÖ‰á]žÑ Нÿ鬺Y@oj€w´ŽßzÐÝg=ê[¤S¾S¨§4aQ Щ&•Ê òÈ”¥•M×2ÆK„*‡ëLøÜ[G°sT£”¬Ñ/lØô8¦ïÚTýv_°>äÐèn~ @'W'ɬpãëщÛN)óÓ´[x‡!!&­#Ú4­hrzš*µ¨R¤b!”(¬ƒ‚ª&TCàµ%ÆÞÉ_¸ª‚=ã µPÒ€ˆ<Î’õòs7×æÖ¥Òƒ?Æ.¹ÉÅJ9rßsa3â‹JQ$’hæÎhþ/–ý²OÖ½‚ýYÔDï8^mÚz‚*cKJ…-»ÿ Ê€iR¨BplÙ?ÿî-æ‰mÕêÎ# +ÿ|Étõ‡"Ãðnä n(ðFÙàɼ+G$‡8ž»#žÿ‹WÞ)¬.€ x_@ÒH¬¶Ÿé­»#Ô&êT*·È(VeÅq¨¿Èÿ…-!°>FHøYµ~ë®'/ÝõäÊ¿öòâÑ?¾qÐ=¶N t é'îo‡¶}ZÌÜ·â…»Nó Ú-|ñÙ»åœ;2 -‰MŒHÇ!&"i½&˜»—±w—B°Róg$,½ *µy#¿séP2ß‘r´ š³yÿ?Ïén—÷tÖuÃö NU" CL-ÕÂ2¤ñsBy—Âå—‡˜mà©’à3Pê9”JsPT?ü‰­Ý_›1D”02ÕyÄ ³ ³‰@„‹ç¿t—ç´ÒÆíîÑPS -)CDZHGZs„]W+,óØBS>Eš^€¢E"ªþøôP÷ü"% e¸)bã¾W–÷ÿÇ-›t5œ X8þ«xáK÷`>`½ºq_œóµãFMZØI+xSؤ7WÊØQq^mío@¾ÑyÀ€¥C¿15À~ªÃEÞfš~‡KçÅ|`#ßd—vE°ö÷W  ´ot3fcÁ&ÌÑ’+‡>ºùŒe¾G¹É_ò{C™l À9_;¡¥…²ZÁDQ­ ¤«hÅ,DJ–b q–0@~ãÍf¼£U¦ý´FU€‰ÐpÀœ€”,$>›˜ Ó}ú·4å¾™’IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/inbox.png000066400000000000000000000262511217176075400237150ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½Yp\Ù™ßù;ç.™‰ ®àVdY*©K]jµJê*m-M¯ê¶Õînìéžp‡í²äûÅÛÃL;ÂŽyGØí?Œ#ÆGx·_<ãki©Šµ¨6VY$@ €Äš{æ½÷œÏçÞD$L,$Õ⟑D&póÞ³|çÛÏw”ˆð?»Ð»ñpñ˜~Æáwz¡RJˆˆdïãÑ…t(ÛU7:€RJ*}=ƃC§ã-éËBgD°-PJé òžçõAP!âó˜$÷ÍÞËæ¿¸ W`@EZëšµfM)Õ³Õ·$¥”ûçþüw¿ûwþîßû?‹IŒ'ˆy<ùû7Ón ÒúÕÝ (¥Äó| 4þÁ?øûåµW_y[)åmEÛqH†‡?û™ÏœéëëA¬¸§=Æ# ¥ Z­£` €d«ë;ßý¿ ë:AàcÌ–å12‚  Z«šF³‘ÇÀ–¶˜ÊyQIœ "hýØr|T¡µ&Iêõ:ÖZM:¿[Ym™‚JLÂÚê*(ÅÀÀZk¬µ{ÓòÇØ”R(¥(•JÔj5cȬvØÚèl9+%Zkc¸}û6SSSÔëu|¿c7Âcì<ÏÃZË7¸yó& A JéŽìûí ³+ñ<\ÒÛÛKµZå£.277‡çy<ö =x(¥ð}ŸR©ÄÇÌòò2=== =ø¾Vª5w[¡ Zkñù„$IðŸÇ÷}”R–¶|?tÌõö‚€B¡€Öß÷‚¥¥%ŠÅçΟcdxc #Œûß÷©×ë\¹ò)kkEFFF¢§§‡\.‡ïûøq²AØò~>W”Rxž#­Zk …A´t1¥TWãݵŸ)|©œAkr0 Y^^æÝwßåìÙ³Œa­},vß÷)—Ë\¾|™z½Î£ ÐÛÛK¡ÇóütQª)ã;²ã”Rˆžç¸ÁºHp"buu…>úˆ£GrêÔ©–©ò#[\7oÝbjr’ îbù¾ï¡õòî¡ ­¥ §†aH.²²²Ê­[·(—Ëœ9s–þþ¾”츭?3ðùä#&&Npèð!<­±’9¬~†dBºX´ç±¼²ÂÔä$q366~·c§sÙûñéŠèìÚlòãÈé!¬®®rýú4åJ™ÇOÏç[ÜàÏ: dd®´F¬eææ 7ggÉçó>|˜¾¾¾Öä{ž—Іu}i»ñï–1tAB®å È8‚çyär uOËTÌår¬®¬P­T8yòÃÃC(µw¬íQ†ÒšF£ÎôôuVV–bhhˆ¾¾>òù|Ë«w·¢×ÉØt7~ÀîÖefB©»G—/_fbb‚C‡áùžK;û3iMèòò צ¯aal|œÁÖª¿—¼ßO쩸2‘)ˆëzAÀÚÚ*³³3”ËeŽŸ˜ Pè‘.i™ñËÆ­;iy6 Jµ-ƒÌVc s·n17w‹\.ÏøØ½½½ôöö¶­úÚýæˆÀ^Òbfö\Ⱦçù¡3/_ª21qœ‘#8¯vç é$ÛTRmZÝ)Òªí³RY|%%„.ób•ÖÔë5¦§§)‹ n`ùAâi­ÕwŽtÆÒÈâ^šm™‚¨”ÂÓš ðÉ…!kk«\»6Iµv˜#‡ãû~ÇÏ´â^ÆJú^¶°X7.YB£P<žVéß;c'Y`fey™™™’$a||œþþ~zzzÜä§cК÷´¯;ånçç¡äteòm£•ù ÖÖŠ,ÌÏS­T8~ü===l+ReEˆ 4 ĉ€D)¤ÅMT›¦,¾ßžsï|従ó…l È6 U+…1–¹¹[ÌÏÏS(¥¯¯¯Í—F?D—hç:Ùé^a£‚˜º’=Ÿ XYYáòåKL?ÎèÑ´!÷nÅ­|#%–JQ"ˆç!JZ_[ÿv›œÄm¦j“ùBèC Æ (MÁoÿêÝíR¡5µZ™™ŠÅbKËïíím­úLÞw'äös€Ì °J‰R´E5ž§ñ=0Y[[cúÚ5*å2Ç&&œH¸Gd1kš±Bd  õÄb=¨l_ÍúpK{_dýs¦wh¥(X=El„Ð7Ðæ~dZþ2×§§Q <Øbùíî\wmÚ¦=Ónîöˆ¤õ®‹¥”Ë~i³òù<ËËËT*Nœ<ÉÀÀ€Û Ò¸tƒœÖ®s€j$˜PÒµžjq©^°ÎҜ⠙‰ ”à)0xäê±ÐFAoðZJÚvòžáöíÛôöö222’Æí „¡sì(­‘í×_ïGgx`f`§È”Bø(Uh9ŽÂ0t"áÒ¥–Ï@”—û(©ÒçD€P‰„RÃ’dã‘rG²Î2È"”©†ïi…(Áˆ¡Ü„Áœ ØÖÖ[•ƒ‚À÷©V«LOOS«Õ=@ÿ½½=ärë,?»¦DîÇHŠÈöúR° -½À™Š:Íu Ÿµb‰ÙÙK%N°¶ºÊää$Öš–¢W(6¸s³>lÃýž‰€‡0ý­ç‚3­<a¸îFö}Ÿ0—cqq‰;K+=ñ…þk¨ÆB©)$ùuÖ-V!bÝ*ƒ#€x=KI)}a ÑxZQl õØí¼õ´brjŠ…¹yúúzKãöΣçvådj¢ÚЇ6^]°é.Í@ûàe@ •þç!Óôç4°¤•âö%~ò“w8pˆfÏQê&G%¢Dµâ ­I§/`œ#ØØõËK÷C笢–€¯¡ MñX[+q}ê &‰9Àà ËÎÝÄQ’çoFÆá:|ÞJ)—<²!˜º-k==¨µ*?þ„j~ÚáÏÓ°> «1ƶlýŒý‹Q-@(%€´ R,аPÀ£f„É™[øW>¢¿§À‘Cãz+7L'?3av¢ãþY—ÐràXAÄbŒÁ˜„8Žˆ£ˆz½NæøÌ3Ÿeªœc¶\g¹2Т°Öb ©Üg+H,Hää}ÆŒÒ$¢©'–;¥:G5k¨ÆÎÑ411Áɉ£Ì\¿ÎÒâ"QÑß?@ÁZraêêõtêPJ©àC·Îº®DÀu-Yf­cùQÊê+å2µzѱ1Nž<é2‹VJ”Ê5 : MÓ*" ´Aã¼})ûw ãD€M ¾8oò¢=¬ò¨F‰Æ¡\®2<ÐÃÓO?ÍòÒ“S“,.Þfpp˜ÞL/ÃV¾¬[dØD°ì¹#HÚþß_´[lÊòã8&Š"ªÕ*Åb‰À÷8wî<£££ÔëuV–WhDÆ…Vµ­1¢H …vA€t?BKL}b¤-ÑCaD#(,ihY¾ï!"”Êâ(bdd„çŸãúõëÌÏÏÓh4L·n‹õkz ì‡#HRûþ2€,l+X+“EŽå—Ë%&ÇÇ9~|íy¬‹DͨMÔÚ¢v²W®å¼ÿ÷Êr´‹õGQÌêê==Ξ=Ëèè(““S,-.184HO¡‡|Þ¶ÌCI½™ÙÝö ÒêKgèˆDTÛ íHj¯[cZŠ^½^£T.úçÏŸchhˆz½N­TN«–¹èšjs½ìuB¥åª–£H+… T«Õ–ðùÏ?Ëìì,óóó4 Éåó„™gÐóZþŒý"‘îv\uœ¸oJ`¦è¥Ê‹±–8ŽˆšMÊ• zƒññ1&&&(–JÄqì»V­öej·êvp3ÝfÛoeÎ'YÏ D!J‘$†b©H!ŸçÔ©SŒŒŒ0uíKKË ÐSHspÉ¡.ïsŸD!ÝhÓºÊ Ü­z±–$1ÄqD­V£\.†O=õ$ƒƒƒÔë pïZ…ÙÄìh@;éR6ëà’Ûç/]!õzƒ(ŽéëíåsŸý,7oÞlqƒ¬~O.©E¥yÂÞšŒÙ\uˆ®•À=›þ6-ßgÞÅQD¥Z¥Q¯366ƱcÇ(•˘$«{sÉÒZ•ÝhçDÝ®Ìe¯ö?f>G¼9Nœ8Áðð0ׯ_gye…4ÿ?L7ÒzZ»¶ÊÞÊ„=Äÿ®)À±[Çò-ÆX¢(¦Ñ¨Q.WÀ'Ÿ|’êõͨéVÉ6J37l×Û¦3ÐÉW2ÚºköÛ/qhFIÓÓÓÃ3Ï<ÃÍ›·XX˜'j6éëëÛ5Tº-~·”ºl;D‡•BÕžð€õHUêÑ3NÑ«Vª4 FFF8vìJ)Êå &­x¹Ý|flX«öÚ[´id5X·|Šrâ­Z­†ÇO0<<Äõë×Y]]¥¯¯—žžÞ–Hh‰µ]2‘®¬À•À´E»šþŒå Σ—$©yWFkÍéÓ§¢ÑhEÚë|2••uJè¶iuJµ¬€ígýˆÇ1Ib(œinnŽÛ·odž޾^Â0GøxÚcØ©>³ž@v@ë¶½ˆ´ä}­V£^¯344ÄÑ£Gñ¨×kø¾ÏÄÄCCCܸqƒµÕÕÖ^,ªè¸ÚÀuºêN{+»sÑ]¨Ñ}1ÕòEHÒU_­VPJsâä †††ˆšÍf`G›$¬+{ˆI Dµ›š;dÕI’P­V)ôôpîü9ænÍqgq‘8‰ééémmÙ¼-|¿Ð¹˜½ébþ3Û>óå×ëuêõýý=âV}½VOkíÜUÚâüÙ&¾.î$§È‚Iè.9Àæû(—¡Ô¨7ð}‰‰ ‡™½q“âÚ½½}6¸ª+­^nÛF›îŽêÝeuHíáۤ勵=z”‘#­À€êrÒîee„öqÕ(Xß)º›{àÄa­V£¯·—óçŸbnnž;wîǽ½½-"pÉ&©+°Àžû:ö¶…o[qû¦sìôöõrôÈa‚ ¤Qo´’(önè61кàh™E²Ðv·Ö &¾ïsìØ1úûû™½y“µbÉEsyüÀåvâGβÝ;Ew)a÷¥Ù䨱Vý¡C9p`c’Ô›··þúL ó®uzo­ŒÑmMMÕŠìF¸’Ä`mƒþþÎ=õ·nͱººJ'-Ñ÷=×ÔV{ïÕ‚î(`×Aë¶}º3§-nŸÏå8zô¹\žf3jÉúýB»î¼×PŠ´"êþ<#ãÞÍfß÷9yò8CCܼy‹R©H__Bn=ñ4SL7ßHÜþ¥NI`wAm«^¬%N ÍFƒ8‰ellkmkÕëö È¢Õ€Þ'H  U,bãûÆ Ëà +77?Oq­H>1äóy<ßÛè3hkˆ•ì¿Î°c?ÀzÚ‘´X¾KÌ 8yÂíé¢hOeý–PYXx£ãjÏnOZ,¢5Úû_7c›M§œ8~œÕþUæ©Tz Ȭ„´)ëcÜ¡ÞÝÖ°6?€°nâeÞ»‘á!<˜²2g×?ˆÉwñú(€Ð…¼Ìÿú=º6Æ`­u…#ûzÓúËòù¹|ßó6ÄI$Û¿Ñ!t L½”½dZ~½^Çó<&Žc``€8Ž»^õëÛô75ºÃ¹qQj…Õ½£j«û"ä|…VY±ó5:‚Ûø¬ûõVÚÿ~æÑÉPEQŒçyœ:yŠååR÷rß÷Ó i•”ÎûØq™87ÈN½°Æ¸T­¨ÉÀÀÇÇ[åN»Eº9·Õðu¥R‘¥¡m+K31D‰ÅÚl#øÀÍ6V  ;”C­Ïeç¸ëzƒnW[¼;ýÑAs3npàÀ})7¨T+­DT?uuS# Ã”0QÙ%IB³Ñ@€#‡344äbùqÜÙÛ`­³b+$fÝ‘cÓÝ-YÁ§uÿ÷\j"éŽà†¡%¬Öbî ¤“·V±”‚$ŠB‹âbÉ Rµs²¶¸AZl"Ðà+WwHˆJó¹ê,"DQ„ïûœ>}š;‹‹,..’$ …|¡Å¤CiØE!‰ zƒB¡À¡ƒãa°£Uïîç/6ÐŒ-•¦áòÍF\⥈ۺ—ØÍÖÇ&AŸšO±1T›†BNóäá>*y͵ÅFwmb£K@áJÄø«ðú{ÿίò¹ó9B‚”çV¾—iî>‹¬û |­tv|<(ÅØè(A´’5v Á±×0Є¾ÛõûÇÿvŠ¿øå1>Ówž™Ñ!BÕ¡•&lØç¡™ ‚ü ÅÆ;?í¼TV‰ ÎLà6›x­Ý2 5¤Ö‰3{ï)tŸÂT¯ ù¢fì´æéÃMjM¡Oo.¿3"šÍ&ýýýÎïÐØŽßóÈçrh¥Ãp½™Ê­¯l’vbóåATÀ¯þ<üñ¿½Î?ü÷7øÜo}–Y¤Ùá¢ç‰ÄX$±ø©?|·E§÷vª~#–t¢»ë£XðCxò—5‡z5ãc!?Wˆx®ß’Ë{ôôøôBßÇ÷uGc˜qß ×¦yJA!Ÿ×žçµœJ)u¿¤·""ñý^s~ávÒl6TÇÊ#I‹ˆøVœö®´ºgý¾-ïM‹†ˆW~÷YË¿|­ÌÜ…i¾ôíó\0>ÖvzÂõþb'ëRp…&‡4¡b:†ç¦®p»”Pö…|èŠ_ùžvYM[<(S²ƒ¼;ZWˆJkO{†¡DQù¾ßÜÞw%lË”RÁ‰“'ÿë_þKß»R,4£h0Ž#}ôÈ‘ïrù/aÈs_øW>ý”ÉÉ«ø~Ðõ0µ2isãù .Îý<ïóü7ÏòFõÑ!‚nà4|Å çŠLÍÃWþnͼÂÿS[E5JHÜÀ&Iº›g{n%bÑ(¾ü Ôë5._ºŒÒªtcvöŸ[kkžçÅa– =…¥«W®^d‹øm†- @DD)eg®_¿1sýúÐø…Bá‰3§NýŸÆ$<óÔ3œ8>Á«ÿã‡DÖK:¥6(Õ¸%ïµ|ø¶ žÿÆ“¼Qõ~ªˆ@p¦ßï*•5Åclú¦þQeU/"qIât³jg[ºˆ¢&ÅÕ^xñEî,,P)—‡“fTŸš¾ö¯Ðj@HDdK%¨`”«iÚb‰¾öÕ¯þÑÑÑ!­_ÿú×ùø£Ó±ƒ»p¾(–U¤nïp<~‡‹ï8Eêù¯ŸqœÀìXQ~`h±}ŠM7ù#7^cxúe<ÛÀÓ :Tà¼IÐ’ßÛC‘$yfgg9pà/¼ðúê«<ûsŸûîì­›EQ‚“°ÛM>t¸¨DÄŠH""ѱ£G‡OLÿèñÄ™³ôööñÎ;ï¤'Xê]¼(…PˆnShÎ3½ÃÅwÞeá•)¾> ý®""‚¯H'_hXÍðõ?ehêt£ŒŽª¨¸&ã’©¥ÖÅù¾ÏÚêï½ûŸy懆éëëÿÂSgŸü‰€HDâN&vÀU_øÊ/ýA’$G|Ïç™Ï>ÃÅ‹rkvßó ­—³»`rõ9rõy&šïpñŸpóå)¾5hY"ıý ›|ÅÈôk N½ŒªQõÔ«5±I‚5k¬{u86b]A­5o½ù&ÆXÎ>ù$µZóçνô¹g>{_mÿ~è*ü¿}ï/õ(¥¾ßl48yú4}½}¼ùúXc´0¢X»ëœWÌ9!¬ßÂÇäMÞ{Û¹†¿úµÓ¼V 0É£#¬8ŸÆH¨XmJ‹íL½Œj–¡Q‚¨ I„µ wíÝéØSåÖ«§5wnßæƒ÷ÞãüÓç¹øá‡DQôÍŸÿü翼ÜMÛ»âQÔü=k“3J+Î?ÇÔÔÓÓÓè¶(T«nÿ®^#€ k7ñë ­½Éûï¼Ë¥ÿ>É‹=1^ðhp‹›üñ¼f­)4D34óýS/»‰¯¡Qq¿‰]ßv8.Ò¦0ŠÞ¼pÁ…ž8M5U½^ûA·íï˜~÷»¿ã‹È÷ãØ066Æè¼yáQ§>t‹•¶îÁË `"rÕ›øµŽUÞàêïsé‡S¼Ø“qÞŽnÜ=éXB 8Þçq«b¨ÍØÜë ÜøÊÖÑDx*Aù ¥=,Ô·s(­[YXí'¶OOO3==͹sç¸>=1æw¿ûÛîÿÇÿòŸ';¹o‡ÛÃ囂|-INœð·;¹og~ä%cŒêé)pèÐ!>ºx‘JÅÅí]í='× ù<àJ¦îËKžmÐÛ\ ­p&~ë—>æÒ+Ó|k &hÌ>pŸ ÆBO 8=à3[2›Š#‹o36÷^³„UЩ¶/6=ì»1ÖÕEgu¥f¡çyLMN²0?Ïgϸ˜ŒØ?üíßüÍÃôi[ð[¿ñ›_TŠï$‰áð‘#Ôëu>½ü)Z©Ö&D+Ò*Ýnmg~íÝ@S§§9ˆå ~Âä'.õê/žà‡‰G½ïLl#Bo¨9=ä3SJX‹G—Þb|á TTA5+¨¤Ž2ˆÉÒ²ØËôq¥5¹|¾µÏ"CµP“í dIDATZåƒ÷?àů¾ÈÈȇ|ßû«À?ÜîžÛrkå¥$1~:xˆ+W®R,Ýé×mj.ŸC)w†Ï^Z÷³¼¤J¡y›°¹ÂÍw˜ºt‰ /Ïð徘Bè‘ì!+ôŠ'†|nÖšptñmÆæ^G5Jë^¾¤ &AL¦íï±UdŒ;bÖ÷6X\žçqõêUVVW9qòTºÛþÑoþÚ¯m×·-9Àoüʯ>…R¿—$ ÄXÃÕ+W\^FßâvÌäsù–ºo{&Ú (ü¤J, "œâ&'}Œç¿r”×G½oMáíÙ›÷[ùg†®Mkåο‰ŠÊxQg+?Iýúû7Zkòùår©ÕnWR§Ä¥?áçž}–ÁÁAŠÅâ1­õÿlËûmý8yI¬-øžÇÁƒ™¹>ÃÊÊ Jé6ùd ÃÚÓŽ*à? x¦B¡¹@®¹ÈéÚæ¦'yïÇ7y¾'&zÛë[N>ôŠ'†}¦WV›pxñMÌ]@E%t³ŒŠkhÓ@l„ˆÁ²¿c`­!— Ócê2Ý”Ò\¹r…Z­ÊÑcG±îX½—~ýù•ÂVÝ¿/øÕoû˜RêŒ1ŒŒŒ ´bjr2Û…±aüòù<ÖnzÞX^R!Ïm,pš7˜žq›7¾ô…Ã\0µz÷:µÐ“Óœ ¸¾ædþ‘¥·½}Õ,£ã *ªƒ‰tå»›û +Ž „aH­ZM-.wÐåÚê*“W'yâÌôôöP«ÕžÒZÿðÿÞï~÷å"ü‘µ2Šá˜ŸŸgey9­p±Q&ù¾Ÿ,öIûßâ%™u—È7ÈÕosªô#nLóÁOøb_B!ð0]ø¦¬…@qjÐg&•ù‡ßâÀÜQõ"ªQB5«4!©‡ïôWœ[8ŸÏ»y²õŒ«W®EJSÇå¥_ùÖ·ï»Ðïù‡oó—G•RÍZë*Uø—¯}‚1Ï÷Ý©éjÏçó'4ì+ü¨D.­~Š×˜žQН|~Œ7ES¬Ú»:¬6••Ë<|'ÂWŒ‡—ÞbtþuTTFEUt\CÙew˜äý÷ëï¬ÅÓš\.G­VsE¥Rΰ¼¼ÌÌõ>ÌìYšÍæµRßþÓ½nuo ò—ÅÚC"ÂÀÀËKKNö§Þ(+.<™ÜÕn—>´—"ÄErE‚ú"'×^ãöÌ5Þ{‰/ ƒyM²EðÀXÈûЉÁ€›¥„b¤8¸ø#s¯C³Œj”ÑQ •4§+_ZÁ™ÛW!—K-¯tNœŽ`¹vm ±†##Î5/òÒ·¿þ{Rç]à›_ûZVúoŠaà>ÓS׈“xý,<œ/äW”èш̺ý„~´B˜F&O¬¾ÊŒV¼ <÷ôïb5¹K'°¹@q´ßg>õð/^àÀÂU *£ãM2ÿ!è<D~àã>ÍfÓq2åi–––˜››cddÄÕ#Lâo*¥¾Æ=BÅw€ˆü¾{JÄ’/ P*YYYqgáIë¢ÖÁÎ& ü<‘YÚ[4—ÝCã˯0«à-sŠÏŸä}£)VL«ó‚ó‡ú<æ+†J¢_ºÀÈÜWP÷™ü‡Ûg—L›Ïçi46nÏK’„™™ >;Dÿà‹wî(O{?à°A|ýůz"üMiÓº°p›(ŠR6·~JV>ŸÇÄtÇÅŽ_m ÏÎEŠ ¹JÐX"¨ßfbéeÊó×y÷r‰Ï À@*,øšÑ;UK%VŒÝy‹¡[¯£š%çèi±ýÄí=è¢mvú²Õ½}? Ø$†•R,Þ¹ÃÒ%†‡‡ñ<cíw¾öÂW¿¸™6p±ö·QêY!ð}*å õZ-ìL> Cgk:bÜs(¥v½± l,¹P¬ŽÊ¹¥¾Éê4Ÿ=ÝË'âQkÀ@Þc¹f©‹btñÃó¯;?*£“:Ê:M_e tÜçlÜö¢/wÃu›Yísda~~žÃ‡IœøJÉKÀ[Ú—iï/~ù+J)õ ð¢³iUK³ %^RH›x©×j(µ‹ø^¶Ùˆò£DùÄ=cÌþ½‡NqöpH©a™YlдŠÑÅ·Z“¯£2^ì&_‰kY?¸óñÐZæs4jµ…žwƒ{Ì_]D>ÿÚë?þ4û…ßvñ/ òK­oÛõ/ßËÄÛ/ (Ö€ø±» ï¶-W¿¾èŽ˜áÈÜç¶úï4Nâ)Á 9pç †æ_‡¨â=IL‘,™£}ÑwÑw|>G½V[7÷’ÑÕÝÄ%8—´ˆd. ¼ü­ìšvøÈ=ÆûÛ÷Öºt§¬ÒÞù,~ýN«0ŒÏþ7VÍ D=^¹Èà·QQ •¸¨& éîBÛ\âj ÆöÅW ­ÿ¶¹üÁW¾ôüÿýã oÜ„”žÿâ—~Q)~mï[¶3hí‘FœØÓ5#¿v'ÝH1:ùŸ/Ä350Äu”qÞ=+NæÃÎUA©ð<Ïuôíe!à€?†Œˆý¾ÈÃ?HÚ­µ~x‚샠‹__¡¼àÒÍ”Ñ&BÙ¤%óe·éí"iõsÁótš2ÿHxLþêó¿ðÅúÆÛo­ù¿øÜ>#"¿ó ½ûADð‚ õÞåì|ÿý Äà5×(ÄºÕžÙø™¿Kês}p§—{º­€ÓÆpX?þ©â¯ò¹ü¾4Niå| Z¥'{ºmNÚÓxªíwZã{šR©L¹RiÇnÙö¼ n!à´z[GTº¡¥uÎN:ñ{°ÜvyÁ$ ÚÓœ9s†Þž^ŒIRßÀúŽ#âN$—{íÚÛyQJQ,—¾ÿ‹_ø…×ýóçŸ>ÝßÛK˜Ëíˆån7NJ)”§Ýyy){Ï~º3ô\m­4žçqåʧ¬¬­áû¾#¤%‹÷"©†¿Þ‹ÖìاÉ&I:áäСC­;6u®9¥M#›¶W°i„qC[öˆQW«Õ3qÿ‚¯´~¯T­üšW¯Ó~âVfBlĽÌÁÍmRwÿUµ}Ü ŠÅˆ`“—V½¯‘ÙôsŸ¥œ»Ö$¥Ë++”+î?÷yö–¿îtpï¼ÖÞûþÂÜÜ€cÉž×úéáyë»R³âÈ÷²…;–[Œ­«÷¤[­Ö3¬`Õ>q€ä>ïwúPŒ5xhWI½ÙÜú ÝÑ@WWlºúë~Çou‰¥Ð¾TZòLiíˆB{èôô Ok÷>«„••ˆ ΗֻÍ=VíoUëj7`i <±(Ô†äO²dM“îèõÂcŒÙf¢Ô=ßnÃi»‡R|¨P ¾1fΊÜPðTûÃ6<ºM¨tÂQ*­Ÿïˆ#SæÖ_ª­æÚä­ZO˜ngcí±mYúûû9}úô#iìJ)šÍ&·nÞtò]’8¹u'¬G­jÿðÁ¿ÿOÿÑø/ÿékÑW¾ôü‡´Àý!w}” ¿W&\©ubXWú´;u£E$*½Þ5.Ó|cðÃíyìõ^ÃA ´&Žb:¯¯¸“¼«o( 𠤎 “$ŠÈ_èú©ÛÀ‰„»;¼~üšû™™:Õ5Lb\Îç§&ÓO!àú—µ¬5D{P`sëçA‡¤pG)u Rˆãøã}kUîÛõ¶A\Ï÷ ‚cö§Ñ~AkÕJš±ÆGуh]*xÛsOD¤ )$Iò¾@Ø2‡üAÁC_.‡Ö cvVuìQ€ˆ%ð}w|¬1f‡ü‘¾ûx¥åÉt_Ër%3¸²¿Á‡¯¿yA #“Ü+7èHØd )àN ûi…J9€µ–ÕÕÕ=Ï«è”3n¾N)õAöÞøøòåèÉÓOt¨î?D„ -IûÓÊþ°´Lç(ŠÖƒ\–T„ù{®în/ü v¿ÜÀZéÖŽéG„˜oq/ˆ"Ø)n/,<ì&ì)‘ÕðáÕékÕìC{«ÞÇ)‚ñgŸ´h'€[ÀÛ–Çxx¯ýC‹®N_‹€xsãA"a“¨ß,˜ÀŸm̪‡m&€GJ|Œ=LJW§¯ÕÚ±™Þ€yŒO7ÿbs&ðMà_ǹ«¢ñcü”Cÿß]¿|DœñðÈx'ãáà1üŒã1üŒãÎ4ZòL¢àIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_delete.png000066400000000000000000000431171217176075400250420ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½g˜Åöý«>yÎ%FÒŒržQ’„0Ñ,‹Á Ûc‹ ŽìÚïîc0»^?&zYlØ]llÀ666Œ"PÅFY“ÉÝUχîêSÝsFH ÞëݺTê>Õaºë¾ëŸ*´PJñ¿éÿ¿)z8nrÑE‹Åüß‘HÄÏñxÀJ`€ï¶nay­­(µü²(IS˜­ß%¨ 8J«— >!%%HIdÄ"&"jª{÷2®§‡øŽ“ž««û^¶²RI!sÞ'’à=!€RŠ|>ïŠ )ë Žsý„¶¶+íÛ‡=† !Ù0+GM†ìîñÀñ@¥$ÖÝ_‚’|·Jû~ÙÅùƒZ6)/‡vTI}TWcUU¡"²J‘ݰ‘š|že;vL|®¾þv;¾:"Ä£)éw‡Óp=”ôžK€¸”ãmǹnB{û¥‹öï÷uibäH#j]جÄ*¼º¥–ì‹wm!J˜˜•ªËõl€*T™òp™ í‡ã’ ™„tÚý›Ã†“­L“‚šBe­­Ÿ¯«»£/ŽE,ë ï©aøÞ@ þõãÛÛ/YÔÖ†"é4•sæRQ7ÑÞ™ t÷B¡\·r³,(Jå១ï•+¯8ªÙÒ… óêr\X–K€TŠX2AMCv?½MMÔ ,ݱcüsuu·ÉtZ8B<,ßCupÔ  õj\Ê:¯å_²hÿ~üÊJj–/gè± ±::aÏ>èìvÁ·,\Ð-PØBàø„ð‡È`ªúí>™›…±_.+åI 3KýrÞ3yÛtFŒ 9nÃ=c±·©ÉU;wNx~ôèÛœtº¨„x´¨”}xkúàÒQ%€®÷¸m×ÛR^?±½ýÒÅmm(ÀJ§²|9C,Àêî†mÛ¡£Ó\D ­Ò>&ØáLˆƃ >àšåå—…_VAGôöÂØ±$ÇŽe„r Çž¦­Ôäó,Ù±cüs£GßÞŸNâO…÷À;8ºPŠ„”õEǹn|GÇ~˯ªbè '0lÁ"]]°­:ºÀò€W(ËGIOH\B„€÷Å¿eØ 1 A·jÿ)K僵z½¯$ƒ‚¯S>-- %É1c8F)¤’toÙÂO<7zô÷2é´Š¼ÞÁ%€RŠB¡€UÆÚ÷[~e%Ö/g¸þ6·åXWœ;ÊÜ“BP_ež-àBÃS^€T¥} ¨ÅX߃ßò…·/”Ž`÷ÁßP"㬯§váB¤”toÝÊBãwì˜øL]]À;pl{@øûH¤#.tU$g|Ѷ]k¿½ D++v ŒX°€HG47Cg§«ï¥ã^hížØoßPBzúŸRYÀ5 ‘À8£õ«AÄ¿\—¨å‡ à…†Éf]r;©úzF.\ˆRŠ®Í›©{B<â‘@¤#ŽŠ H8Îø¢aí+\±?ü„¨]°€H{;45¹àG" ¥W‘Þ–n‹ÓžvJe×Pï©¡Á÷Bîž)|µ&BÈè §0øfÊç]Ø6uuŒò$AצM )]ï`ôèÛde¥ˆñðÑ!Ö~Ѷ¯ßÞ~É¢övÊJFœp#, ÒÖæ‚ßÑá‚ï8^‹6|z¡Ë%¢$´:´vË8ПŒË§Ëµþab0àµX},Ÿw%]±HÅèÑŒ^¸%%›7S“ϳÔð¤e=jKiIÃðˆ@뮄m×{:ÿR ~¤ªŠÚOtÁß·¶lîîRË×É$ðZ¿òÀ×’A…¼_7{)ʨ‚Oëý=í£”Ñ÷¾jP%óbàK—ž[‹ýÁŽ‹¾a˜=šº… q¤¤sÓ&—žw ½¾çzGŒ Ç©ÏÛöuãÛÚ®X¬[¾þ¨ùó‰îÝ ›6AOO°åC øÀ¾×8 [û¦7à·þÐÖØHaË_ï J­_‰åô{ù—/o˜[pI੃ô¨QŒY´å8´oÚ¤ƒEž­«ûž<ÂÞÁa!€¶ö#‘–gíçlûúñû÷_±°­ )±êjFžtuóçݽ6o.¯Œ †oµ}àƒn¨€°'À»ŒXz¯7zô™êê#â>ARÊñ…Báú1û÷»ŸD«k¨?åü°q“³¬’Î/~¸#'L‚ñþ!蟫ç†5„éøúÞ¸&\áå$À¡€.Ó6G‚ ‹!¥dÿ† Tçó,imÿ|]ÝmªºZD,ë°z‡M$•ªË ×Ý·ï’Å®Ÿ_]MýÉ'3n΢­­®Á§[¾”A‘ª·ûí¶fÔo@Ø$HÈ-Ê ˆÀ½ÃjJ—™ÛsðÄ(Q^°¨zÔ(&-^Œ”’}o½EM¡À’ÖÖ Ï}›=dHÑâÑâaò ŽSŸ-®»w屢<ðã55Œ;åTÆÏ™M¤µé/, !eðŒ}Ëør×…¹M°x{„ï÷vi0€Íãå~—‘þÀ’íÛAJªGfòâÅ8ŽÃÞõë]ìØ1þ9)o—55D<ïàíòÀé]àÒóΫÏ ×ÕïÝ{Å¢¶6¤e­®fÜ©§¹àoߎÝÔÝÝXÚàsOR—†kÔTîø ­ŸÐ¹ôÂçøÿ¯+×ÊËÝãíTÀA‰.øᆘlÕÒ‚“ÏS=f S[Œtö¼ù&Õù<ǵ´Lx¾¾þ{²¦FE#‘Ç J½+uð®°âÜsër¹Üõõ»w_±¨½iYĪª˜øÁ2iÎlDs3…­[ýýˆHÄ2îË*…0G”Óí¦q¨S H¤l7˜é@ÇÞ®<œÖ8Ðo=ŒÌûé÷/z’@îØtªÇŒaú’%H)Ùµn+ ZZ&>W_;Æ]mYÖ£¸>ò;Jâê‘Ï|ò“ã³™Ìuõ»w_º¤½˲HÖÔ0õïÿž)óçAËvìÍ›¡¿ßÑ+ ¸UÊkˆÞ NËtã(í—#Á¶»_.¬è»ëµ…¯ËRøØ+¹‡0À¤çîJ!°F&Q_OoGëV­bçÚµˆb‘vËbU}}‹=|øWlËzä׿ýí;YôŽpÁÇ?>>—É\?r×®K–yà'j†0ãCbÚÜ9¨–ò[¶ 2Wìƒ;šJà áÚê ü1þ$B4 ŽCÑqˆE"îïpÄÐÜêýÙ ekâ [8™†¬ea\‰Å|uçžVùzkö7H¥ž*0GF"UWGOGkV­bÇš5XÅ"m. ¶9#F|ÍŽDþíC²:8dœû‘Ôe3™¹cÇ¥Ë::¼–?„ƳÏbÚܹ8--6o ¾Xž¨¶¼}s’‡9‘C臖Ñ(ëví⩦&:3j’IÎnldòÈ‘~ÅA[Þürååt}ØK 'ÃVql›?®[ÇÚ]»J1cÔ(Noh *•BÙv T`¥Ê»wxˆ‰&‡Ô’`Ô(*ëêèéìä瞣uõj„mÓ&/ŒÓâsÌ—e$òèC?|H#‹‰çžuV}Oÿõ£Z[¯XêŸ2”Y>›óæQln&¿e d³¥é]âÞkõæc«%‚eYˆH„§¶nå×ë×c;!°•¢&™äÊÅ‹™6jض€w#ãÍäwÚò½gŲp¤äÞW^aåÖ­Ä<¥dÚ1ÇpŲe «¬Ä¶mßÐóçhÃC%(ø-Áwà‘ ª®ŽÞ®.þöì³´¼ñF@ˆ‘#¯–ÑèŸ~ÿÈ#í4>yæ™õ½}}× oi¹R·üŠaØóáÓ8o.…æmd¶lAd³®Î×€$ \æeËh™ òäÖ­üæ­·p °mâ²Yd$ÂÊJ®8öØ ³o{`Š!hY8Jq﫯òls3V¡@4G)…]( âq&ÁK—2¼²’‚m»-Þ´„p'˜xå¦=à:ðΑ@däHjêêèíîæ•gž¡ùµ×|¼0vl³5jÔÕ2yìþóA©ƒƒ"ÀGÏ8£®·§ç›Ã[Z®8¾£!Ʋàc§qÎrÛJà ={üè¼PÊõÿCÀûÙ²J±,b‘O47óà† 3êgÌ`ÙŠŒ™5‹]o½Å_øCö473¬¦†+,`ÚÈ‘. Ö8\R@)ùÅë¯óLS)9öccѧ>…S,²úäµßþ–œm3eäH.;î8FTTó:½´ø—òðb– U[KõÈ‘dúúxé™ghzõUW«ÆkŽÕÕ]íD£þù/y[ïàm ðáÓOßÓÕuÝÐææKÍ–¿øœsh˜5›\Ë6ú¶nÅÊå‚bƒ” ¿ð†t°€D$“--ünÓ& }}L]º”Ë~þs†ï?ÏŽuëø¯sÏeçæÍ 2„ËçÍcZmíÁI‚w*Â=|–…­¿|ã žin&R,rƵ×ò±o}+pÙ‹÷ÞË}ÿðôõ÷3eäH.^´ˆé49O˜ êÖ÷Žû‚wž5|8CêêÈd2¼øôÓlyåD±È~!xqܸ–Ę1_‘±Ø#=ñĽƒÈ 7Ü0èÁ³O;m|W{ûõ±­[/=®£K)R55,:çfΤoÓFú›šP™ x­8SÆj¯\è}J–±PЏeñdK ¿ß¼™b_S—,áŠûïgØØ±gª®­eÚI'±é©§Ø·kouu1.fDEJw,y1tÖ.™¹Õ¹Üye®Óóÿ„ØRò‹Õ«ynÛ6"Å"ÿõ¯`Ìœ9ÔNžÌ[þ3{»ºhéîfêðᤠl}_¥RÀÏ^9S¥t  N?9Û¦jÈFÖ×ӗϳwçN’ŽC²»{H³”Ç%Òém÷Ü{ïÖÏ®X1¨$”gž|r]G[Û ²©éÒy==Ä€ÊÊJ–|ò“Ìœ5‹ÞéÛ¶ •ËùúÝÞZƒí¹nÊxY”ÂRŠ˜eñ×íÛùãÖ­ûû™ºt)WÞ?CëëË>[um-ÓO:‰Íý+ûvíbCOc++9¦¢Âý;ª4gÏ$ŸVxûÊ;L }¾~f¥ˆxÆÝ}k×ò|K ÛæÌ¯þÛ¿ V¿Ô56R;e {Œ}]]´ôô0uØ0Ò±E½f€W?þVÃߟul<‹l•C‡2ª¾ž¾\޽;wb)E´·wH«”Ç¥ÒéÍ?ýÙ϶®¸øârÃXÊàÌ| ¾½½ý›ùææË§÷õ†TTðO~’ÆY³èöÀ'ŸËòÁ4;x”¹t5§X{@Ä,‹•­­<ÚÜ\jù÷ÝÇAÀשª¶–é'žÈfOlìéaL:MmEŽù· 2øî—ùeÎ XàʪfiðׯgUk«Ûò¯½–ü &OfÃc±¿«‹í½½LöH`{$ðA6²nñf½Iï\ýnv?¹b‘Š!C¨3†¾L†={öSŠX_ß޳4UQ±õ§?ûYÓE—\2€l€¿[¾¼¾£½ýºÌöíWÎÈd¨F¥*øÐ'>ÁìÙøÛ·cy@L]î÷Ä{:]»z¢€Ja Aܲxn÷nþÜÒB¡¯)K–pùA€o¦]ë×l‚ 4NÑÓ³~ŒÁ}0W:„í‚°äץ˖’û7l`ÕŽX…g$øfzíÁùù•WÒŸÉ0¡¶–ófÍbhEyÓ&0³nõÆó¤€ö”"2lÃêë)äó¬|üqþöÆä€]BÐ\[Û<|̘«xü±gV­ xœvüñuûö}³wûö+¦ Tu©ýø9Ìž5“ÎÉ´´ ŠE×ÕÃ0òp­yà¶öõ½st H“#nY¬Ú³‡Ç¶oÇàë¤I°kóf†Âg§OgæÐ¡äeð> Ì-% K¥Î™¨þ›6ñÂÎX…÷À×I“ “É0þ˜cøÔÌ™ I¥È{*Àt¥A xc+õ9šC‡2lÌйO=ù$/¯^MØcYl>¼¹v̘°ãñÇžñEß0ô ðeˆ;;ÿ±cÇŽÿ3'¦J*2>væ™Ì™5‹ý6imÅ*Ý@ Þh<è°¥_.dYÄ,‹÷íã‰;(ôô0eÉ.{‡àë´kýzþû¼ó\ÔÔpáÔ©4BÎ A€f*S¦„ "ŽRüjóf^Ú½Ûÿškøð;_§×|_\y%ýÙ,ãGŒàã I&]ÂzÖ?0Í0ñ€8àh;eèP†Õ×cçó<±ò¶vu:Œ mûÙ`Û›FŽý…L,öä‹/¾è†”R,YºT$‹Å“v´lÿÉq£G_´p é03]ÉÔ#Ø·e3}Û·#l›h$BÄ3òLàÃDÀØ7>qËâåýûyj÷nн½L^²„KùËw¾N»Ö¯ç4 † á‚I“h:Ôõ½ ©}‘vCj â¹z65ñ²ÿÚk9û_ÿõ]?'Àë>È/®ºŠþl–qÇó‘éÓ©I&)hc}ð¦Í¥I‚º:”°XÛÓCO:MÛžÝ<¼j=±Ø]‰áÃÿåù—^ê­¶•Šd3™¹U–5¾qæ,¦.ZÈÂ%K˜6y»6¼EgK ÅB(8¥°½ì(…-¥›½U«lÇA:ÊÛJÇq>)yiï^ž>àÔÍœÉe÷ßOýÔ©tuuq_Së;:ˆáZÓŽr—pq ËZyÞ€ô .GJ„÷žnÝÊ+G|€ùçœÃ§ïº‹t*Ek{;¿ß¸‘ÎL!%ŽmãØ¶_wX)¥»þQ¯þ bÞ¾TŠ|[ûš›‘Ò¡qÂx†©¡rØ0ÆTV’éï_¤l{„~W=ý…ÂШ”ØÙ [›¨.Ø¿q#û·m£X( GJì¢×Cge:;RúÑd°”bKOÏìÝK¡·—)‡|êfÎäÒûï§Î#ÁMM¼ÕÙé’À¨TåUœã8ʶ”¢`Ûü®©‰W÷ì9"àë&ÁãMMn¸XRƒêeݸ0À÷ɬù®.ö77#ÚÚÈmÞÂö×ß ßÞN¡PRtœ”~ ¼@ˆlO^xO>A®¹™=›6a‹•¢h‚ë8>ÀE)ÝcF™–º¬¨Y)YÛÝM¦§‡ÉK–pÉ_'M‚ÑS§ÒÕÓï¶mcCg'1ÝŠÌVcT ’¢móжm¼ºo¢Pàô#¾NóÏ9‡ Šd’mmm´ööºsOLà=‰`Õ1¶Žñ>þ{)E¶³“ÌîÝ[¶±í•—éÞ»˲”4, Ü…,%éÜ·ŽmÛèïê&›ÉP„Ø^v´è墑M28J‘³mÚ»º˜r„Á×É”Ý==üfûv6ôôÕjÀPÒ‹‡ß·¶òZ[Ûmùá4ÿœsøôÝwcÅãtõõ•$€,-©A•^Ý+oëÇ ¼Æéxõ­g;;‘Å"Ø61\CÜôü\ à!ˆÑH„¢],µjÇñ[zQJdÝÂ½Š´Íã¦Jð®wòy¦.XÀEG|$èíåw;v°É‹jꀊm€ÿ‡;x½­ +Ÿçôk¯å¬£¾NóÏ9‡üû¿“ŠÇ)«€Ê¨¦­âÛ多§ìB¤$†;þOàªrÜ.x¯„Dñæâz û$0vœ@K/hõàÙúÜ‚w}Q)œb‘ÅÓ¦1b̘£V©£¹äþû©›2…îžÚµ‹M½½¾ahyà?²s'«ÛÛ]𯹆³ÐGr¤Ò±óæQŸNS(lì*Á—fY¤YfÛnh˜HÇ/ æJpAô.j+Ú^—ôo ZD™j¡ %v"AûÓO³å_þeÝåpF76rñý÷3zÊzzzxx÷n6õô ¶ÍŸvïfMg'V>ϯ¹†Å–¯S﫯Òüoàd³®›R|Û°œ0IL»À¶}£@ Fgnë·(!¶t‡$I\ßÓÂUJ1~}ãO,pcÞu~P(cÇàHÉ´o} a,0}¤“–?9ï<ölÙ£ÀéŽÃÖL†µ]]X¹§]s g¾à¿ò [¯¹†bW"™,õPà÷KCÊücJ ˆ@©Ïð%{Ø(€°–Ѫ•ÒÁG)ÿ\A‰–÷€:HñH\QÁŽ@*ÅŒo=zËò$ÁOÎ?Ÿ}[¶ðˆgŸˆ|þ½ÿå—ÙüÕ¯bww# ·Eƒ¬°•ý€nd|Œ¸J¹x …àxƒ…a((È{â\«ˈ:PjíàïHéƒîxÇQB€Š Zx4¼$¸è¾û¸çüóÙ»y3–e¹à¿:¿çå—ÙüÿH±³‘Lº“BŒ"º#(Ð@ x?dL°ÉìqÕvŽ–î(*8 ®Á§pAÓ':(òZ—S!ZܾqáK\°ÝI¶*@Ýè÷¦Rl¿ï>¤”ÌüÎwŽ* F76²â—¿ä§çǬ³Ï~oÀé%6^}µ+ö ƒ@˜ °ÒÜB`D±Ë Âñ•xи Úµ°Œ“lÏÝs¼?hã‚oÁ´ 4Ë,­FŒ{i»Á” `¥Rl»ï>¤R̾ñÆ£K‚™3ùÂãSY[{Ôþ¦NÝ/½ÄÆ/}ÉoùzüBøãñ&ècRú Ì>‰‹aÒ+;  ðÝ@èõ\H8”ˆ`fhË`›IÇ X ÷0•¢é—¿ÄQй7Þˆu ÃêQ£ŽÚßÒ©ûÅyë‹_¤ØÑá‚jùá <êw™­ÒxAÓ8´¥DY–ß8…w/¢þÅGêJ#ª§uy<›Àåˆ HsßïÔdI¥Øò‹_ •bþM7Hp4ÖÊ;Éïh<{תU¼ù…/PðÀWøPÂ@ïzM„$…cœkz n7é‘”ÈNØ ÔËŽøÆš×ò †háÎE.Gm<šDÐÒÂtË‘ÁÆó>**Øú‹_€RÌ¿ùfŸºìm{ß%…;ÁE§®U«Xÿ¹ÏQðľßþä-νó¥‘MСT·<ï˜I€"%wÝ'À/ÀqÜ’”Z¨-%y/øcZ&ðQó|J_üׯ(Ù š4¾ú©¨`ë½÷º$¸å¬XÌ÷[¥*;¦ñ}›ô×LÀÝUWù:? Ó¥ vÚ•Ó@ÖºÃRÀß/÷ðÓ6€¨«Â@Z4ƒëæÿA´¢‚æŸÿÀ'A,#ŸÏã8ò]Íé<ÜI×g<#ê¹²«V±æòË)tvb¥R¾Ÿn¥ÑnÃÁ•¦A‘žá–¦t(Hé7^¿º”hš³Uur”"ïõèÅ ß^ƒór„RòÝï´ ¼s…qžÅ Mîöý]‘N³åg?C)űßý.V,F"‘ —ÍáHç}ajÏ;‘H¸kÏ?ï‚ßÞN$™t;i0Z¼ž &ŒÙÁFë÷Aô¤¯Y¯¦d0›*A§èuÇ›XKD^´8vp?fSðö£”@Ô­^ëqt«×÷)z×@ äHè|Sh¶G)u&Yé4[ö3€ ’ ²Ù¬;å½^E&“IÿË©Ï?ÏšK/uÅ~*UjÕ¦nÄ¥ g-ÍÖoªÖ[ Vw¿è«#†º¦Êöš/„*õÿÛR O7Ó7Öj@·v-æÍ‡Ôú±3 IDATçéûhÑ/ ƒú¿ç1¦éž{R²à{ßÊÅH¥Rô÷÷ãØ¶û©8óítò^D©TÊÿ nÇsÏñ†¾ûåôtغ×ÝàHçz_ÿyŒc¦‘ðŒŸŸ”H€pÒŒuÊ…õ}‚u¸Ö´îÍS9†CPÿ›dq;¥<7&fË=÷ €c=¤Óiúûú°mû¨z®Gª¨¨¨ ‘HÐþÜsüí’K(zÖ¾öµËî—À÷<àmã\Óõ#t?S"ØÆ9þ=CD§@¦ýsÛ`ò.0ûLi`ªØ¡¤:̈Tĸ§'Ð׉P–€¨¬dóOŠTŠÅ·ßŽ‹QU]M¦P Û×çI°#M…‰PU3„¨W‘mÏ>Ëß.¹Ä5ø<ðM—N-{@®çóûÀ13ðãw6BM3Fãàªn=@'0!7” ~)qŽáJ˜ç›†ˆ~}½Ùò5Ȧ 5އ Dm½êôÝÌÊJ¶ÝsHɰsÏE¯Æ1dÆ â••¨#0BÛ¿Ÿ\k+ʲè[·Ž–n ÛÑ•J•êÃÿÒøÚ4¤…ã~¦¤pŒ,C÷0ë_ŸScàˆðïãçrF`X'9…¹\Îí%ô¢ZJŸ}1\$lŒ™³qÍûëV®ÿŽ?‰¹Ìý0É¢€H§yúhðAd.ÇqW]ÅI ø:ïH&+§»­?|ùË´77SŠ©–Å0oο?‘³LçM8Ú§ú·(õ×ÔT.ÇâË/çÄk¯Å)Kàañï'¥Èõô0jÎ>|ÇüáK_¢sûvšR)†g³$¼y”f‹WÞu¬r£Q™‹ÐohëdÚ º“MG\ûãql\ŽÎ´ã<õš‡(¯õ%p[sœRôOƒRî·Ù9d&Ý)¤c¦ÑbºŠæ¹ ã^ý55ä d6Ë¢Ë.ã„k®Á.± ’ÇQËÞßËõô0rölκýv†ŽK!—£½²’L,Vjezæ´7ÃòÒ ¬¡XdÓ²‡àÃv…yNúxÞ²pÁ8‚ÑMí@áÖŒ‹zà› šÙ>î&‹iÔ™¢I¿˜ný¦ô0_ÎÁµfûkjÈ&عÇ^z)Çík‹EwƲ'Jzöþn¶§‡ÚÙ³9óöÛ©;–|.GgUùx½´‹–Pêð1e•‹©ëÖ 7}}H³Î÷Ö†„ÇSèå{ÀüåÀ.zÒÛ3PļróÅL–Z”ߌ~eª«É%8¹Ç^|1Çõ«8Å"N¡€R%÷.+w4u¾§‡‘³fqæw¿K͘1r9º*+ÉÅbè¨ÂºW×;9Ì:À¨Ó;3ÁG•qÌĂޅÙñg»‚åuj˜7ÑÙÝ”åT‚)ôùš f¸œo«÷ 55<ð\tÇå+8žØWR¡œ÷A–nÎõôP;kgÞæ’ ŸÏÓS]M!wÁ2âñ‚’1¦ëÀ4âÂa_³•ë¶kž«¥j9i¬—® ô„½ß¿4‚Ïj7G›ÆŸãfWn¤LÙ`ÙHª“iLÚ558žØ_pÑE,ûÊW°‹6Ò £ß?)×ÛË1³fqÆ­·ñ§¯}•î;è®®¦¦·—x> ˜ á¬3(G1ís„VXB˜÷‹{çùDÏ­×ÉüŸ´õ®{äLV ¦Ø«‚Ù a)÷®5¥Š¬©ÁöÀŸ¿bKÿá\ƒ¯XN|xæ|oÇÌšÉßÝr‹/ º<›@Ç4t ¬¦z€ûFpü¥ÆÀĨœ¡nŽòöûUÂ@D"Ë Ú3ã÷ƒ ì ·ìr¿ËÝ#,òøN6˼+XrõÕ8ÞlY]Aï÷”ïé¡¶±‘Óoº‰Ç®½–î;é©®¦ª»›X¡€¿Vp(F¯¥¡Ù‘6 Çpý¨ñÛìKˆx\ÝYdV‚k˜*ÀÁe‰¾i¹žå/wÌ$ËÕdª«}?ï3Ÿå¸/}Éuóìð8˜ÃLßë¤lO/#ùà7òø?ýÝ;w¢jj\äó¾6Õ§nåa/L†Áˆ¡¯×j#Р‚£•] çõ)åG—"”ÄŠéÚi±2˜x××h‘v%Ë©‚ˆd=?ßÎå˜sá…,þò—°m»X<ü¢½‚†ƒ#GFäúzÑØÈ©ßùÕõõ®aXSC1‘p…e±,7 êårq³^˹ÛåÄ~Ø 0{H×W,‰ áëh­ʉsÓ´ÊœGè\óë >û„ §ºšl<Ž“Ë1÷ÓŸæ¸/~1áS‡±© @:îǪFŽEoo/}½½ßø°%¥È÷örLC§~ûÛ<ñ/ÿBÏ®]ôÔÔ0¤§‡d¡€ãYé~ ·ïÇ 5QÎ`4=©rÒA½,z¹¼ àÅßõDsÜ¿iÝ—‹L f˜$0¿ ¢‰€r‡|uWU‘ñÀŸsÁ,ú°=ðÅaÓÂ9fìXjkk>lMMMôõö‰ ¸ÞÁˆ†Nù÷çÉo|ƒž]»èª®fXo/‰BÁ#¨»o•òÇøû9,Œ$J@›Cô̱: Þøïú¡`½ò§9Õ´6þ}81Ïõz -/ì1³×[Áµ;º«ªèÇ‘¹³Ï?ŸEŸÿ¼Þuž”‡7Û¶»ÚƘ1c¨õ&…Æâq&NšDE:M¡`ö¿)½÷Èõö1¢¡“¿õ-ªëêÈçótTUQH$\_×›®'sßëz,‘5=#(u&I¥†‚#ÞgÝ)]÷b¡›šnž928ftëѪcßæ Ë¢ËÖyçqìç>çÇö•:üñ{Û¶‘ÒaìØqÔŽ @ǺuØýýÄãq&O™B:]á®Ïs˜ÿ¶~Ÿ\o/#fÌà¤ýWŸíUUä XƒÔ™_ŸšF£Š†Üi  U@$ ¶¼OµÚ†¨Ðqíß0ú4ÐFgÇ€‡5Ú_:ªªèÅpr9fžw󯺲áS)Ø5ø’±ãÆ1r” þ®§Ÿæ'ŸÌsW]…,‰ÇãL6te¥G‚Ãù J9> †Í˜Án¸Á%A.ÇþÊJrñx \îw™H!˜ÒÁ$CÀÀƵ+ ¶JÊ^€Hhh…úâ> |Ð-êó:;ÚÒiz£QœlŽÆsÏcÞåWàmìB)Žsø²ûŽ”Œ?žÑ£G°çé§yæÜs‘4ß{//$˜6m••• ÅÃú,úy¤Tä{û6}:˯ÿ&éÑuär9ö¦+ÉÄãþ _„P¿!ð#!¢D½†j~Ñ €kj ¤*?˜XƒnvuŠÒ("M–\:MO4Š“ÍÒxùåî’gGÂÕSÊ_akâĉŒ®«`ïÓOóìyçáttJ§IUVÒôãó’G‚D"Áô3¨¬ª¢x„žK)E¡¯áÓ§ó믣zÔ(²¹,‹¹"=l;QÀt(Cð‡œù@çW–Œ@!(*EwB¡Ìç°¤`|˜ —ëßÖ蟫s4JE"AE±ÈôO|‚y—]†c›á]yX³ã¸b⤉Ôyàï[¹’UçŸìè QQámKUV²íÇ?æUƒ TUUR,û³é\èëeøôé,ûÆ72jÕRbÅã[w$â¶joX…¥ "Æ9²XÄVÊŸä#C6@T«áÙ¶XÉV$â f&س¥·þ1=¤Kˆ è‘⬯}Q\ÀŽíÛ=wä0ûzy´)S§Rï­JºåJ^:ïñ :×­CACc#uõu é •ÄQÎ!g©\WÏq¦N›ÆØqãèX¹’Õ\€êè ™J•F'{Ùâ.‚ÃÝ“ÕÕìúÉOXÿùÏ»6A2Éœ9s¨®®v «ä»zÖb±H$aöœ9>øo|㬿ñF@Ï‚ßü­Qïš QË"'%¹xœ¹óæÑ]]MW"A"]I[O•‰ø¶X,Ö­ à3è¤Å‹§ïli¹½Ïvþnæ´©Ä•bªT|´öšÖ¬aß®]TÇãD¬’æ.êÁÁŽZ—é­ÓßOÍäÉœòë_3dæL”R¬[»–ÖÖV¢Ñ¨&>ùé¿;¬¥˜ÑØÈxï+£+W²æÓŸÆno'¢u¾gëw> âQ »·—ºK.¡á?@Äbär9^í5:;;ýÙÀ‡ú¬Ž'öç/XÀ°aÃXûo°þ¦›°’IT4Z ÷Šàh^s>ß'à‰}ý>=Å"}–żcÒ‘LððŽTŒËŽöÖnÜPœ^_]]}÷K/¿œƒË–.§òù“7nÝúm}} 5–…°mΚ<™³f±õ7Ø·s§OíN zÀP4ŽG§¿ŸªÉ“9ñ¨™5 ¥k׬¡u»A‚ƒLzÆ™ŒŸ0€Î•+Y÷éOcwtI&Íú/‡É Ii\|1Sð,¯ýíotv$8Èä8±xœ æ3løpÞ¼î:ÞÒàG")aî^Z*N•™êÔS(Љ0ïØcéN¥øÁÊ•ìËå°S)Ú‹EgZ}ýéÚÚÛžyùåíþû+ãË—.§‹ÅSÞܲå»{º»†áFÿ~Ê>3{6ͯ¿î’ ‘ðûÀºÞú E ìë£zÊ–=ðÕ3g¢¤dÍê5loÝ~ÐÆ–’îâQ3gÍbâĉt­\É[^HÑkù&À¾Ä2¬æò7.õÌ!%v_£.¾˜)wÞéK‚W_y…ÎŽN¢±ƒ{VÇqˆÇã{ì± á~²gÃu×±ùæ›±R)T$â·üðœ¿0‚IQŠÛ¦Gæ,\Ho2É]O?Íî\Ž~ [Ù0aÂ÷+9æÖ¿¾ôÒNó¹|8ò¤åËã…©ë¶n½¥½£cæpÜPðßMʧçÌ¡uÍö¶¶Rû.¢®Üp¯"¸Fp¸»Xö÷S9y2‹=H)Y½z5-Û¶¹’€òÖÅŵ|gͤ͞I“è~æ6^x¡/öË‚ÿöX’Ÿ#/¾˜‰ÿùŸˆXŒl6Ë+/¿LGG±XÔ`Ï*|ð.ZÄüÍ×_ÏÖ›oF$“à¹ÜZì›CÇMñ/õq£L‹ýn!˜³h½‰$ÿó×§Øåß:ÓÆ¿£jĈ[za·þ\œÿ|aœr≉T¡pêúM›nëìè˜1×r>}êT>=;×®a϶mTÆã¾O9 Ëˆzý`K”¾'(ûú¨œ<™<@•G‚7^–m-e%A |Éì9s˜4y2=Ï<ÖÏ|Æßû;…ÒèÙÀýÊ^&)¥pz{qñÅŒ7Hðò‹/ÑÑÑN,p­ºå'X´x#Ž9€­×_϶›oF¤Rà‰ýð( pÿ¿ º£]@!è*è‰D˜µp!}‰?~ò)öä²ôѨ3mÒ¤;Ó#FÜܫԮV­ðzƒ~>þ”“OŽ¥ …3ÖoÜxcw{{ã1¸$øà´iœ·`»Ö¸$¨J$ü8A×b¿Ü01Œ}Ç“s￟JM‚×^§¹¹™h,Š9ŒDëü9sç0yÊzŸy†­Ÿù N{;V*5`¤1‡ð[W~Ù2Ã/¾˜±wÜá“àÅ^¤£½}€Mà8ñDœÅÇÇ1øÛ®¿žOì—¿Ü ÐðV“¤³X¤7§qÑ"º#îyòIöd]ð;¢Q{ÊäÉwWÖÖ~çÏÏ<û÷Œ<õÔdºP8}ý† 7õ´µÍÐ$8mútÎõH°oÛ6Ò‰‘kRnäIaØPýý¤'Ofæý÷“nlDJÉkûMMM¾a¨—6™;w.S¦N ï™ghþìgq¼ùùf€Ç”—ôË'³†”RÈÞ^†]|1õßÿ¾O‚V­¢­­Í'mÛ$“I–,]êƒßúÍo²ãæ›±**PÆ8Lmä™6À $ð$mg¡@w -“S¦LùaUmí-<ýtËÞí€8ãôÓ…©ëÞzëÖ¾}ûŽÁµ N™>O-\ÈÞ5kØ»m•‰QË* |p ƒP6¼cª¿ŸŠÉ“™~ß}T46"•býÚµ455¹¾s4ʬY³˜ªÁöYZÊ€ÿ¶º?|ž6ËÔ… ï{†¡Ó×ÇÐ+¨ó$A&“á¥_¢½½ !555Ì›?ß×ù;¿ùMvßr‹/ökõ|mnËïŠÅ˜qÜqtG£Üó—¿°Ïkùû gÊÔ©wVÕÖÞüð“OÚòýW;|èŒ3â©Bᔵo¾ùÝÌÞ½ ZœÜÐÀ¹‹±ï7Ø&X…–ˆ†¾'¡ÜŽ'ÙßOjòd¦üâTÌœ @?½==¤++©ªªrËž}–í+V¸à'“A C=^c†Ñj¾¹I5¢½ó¸G‚!+V0Ú“Ò‘>†æ‡Ðwßp{=ðU$çgès‘(ƒái_mù<=‰Ó/¦Ç¿×ò÷%rÒôé߯9òÖßÿå/o >$>|æ™ñT¡pêš7ß¼%»{÷LM‚“8wñbÚ^¶A$UF5è­»ÖDPýý$'Ofò/I²±qÀ³ô?û,­+V ;:Ü R`SØ´t¥Y@|ïïI)‘½½Ô¬XÁÈÛo/û ¤½7ÜÀ¾[o ¶|ÓŸ÷ž+ÜÀ áÒ;§-—£+gÚ’%tE"üü±Ç؛͒ö$“ΤéÓï2rä­>öØA‡@€}v"Y,žºvíÚÛúwíš1·7餯FÎ[¼˜ö×^§c[3•Éä êÀÿ€/!YT?‰É“w×]T,^ì?CÿÓO³ë²Ëp<ð…'VÚ?$[À¨_ì{'\[Ò³ ª?ûYFüßÿ‹USã–g2´ßtmÿñà¹zú~J·tsß›`«WBОÏÓ‹1yéRº,‹ŸýùÏ>ø»“IgJcãÕµµ7ÿæO:hðá ðñ~4ViÛg¼þÆ7fvîl‰ëßŸÜØÈù‹£ë×éhvI±,_´ùRÀüm¸‘*Ÿ'RYIõi§‘hl¤¸u+}<‚êïÇò–g3ïå½»Õ ºŒjÂ0…{Gf2$æÏ'uÚi %ýO>InõjT"žÁG¨å›zß$I€ü‰K—ÒrÏ£²/›%ìN&íi³fÝ]=jÔwxøáCÞÎýä'“ébñô×^ý¦¾íÛghœ2³‘ –,¥ëµ×ènj¢"•rœ†\Á²d0lƒ¨RB.‡*±¢Q·Õ{sàÖ,ƒÐŒPš/ï:ÀôþN¹r™Ï#s9÷G2‰ˆÇK-Ý8/¬dè·ynG.Gw,ÆøeËèˆDø©¾×òåô¹sX3jÔ-¿xè¡Zûƒ¥wD€ /¸ QiÛ§¾ôÊ+·önÛÖ0Ô“gÎäÂ%Kèyí5zš›I¥R¾$´rÝkh–ƒ«Ã ðý F€ å ñ6û”)7A{þ `Æ9*t]äA~ûåJ•Ö 6y¯3›¥+gܲe´E"üä‘GØ—Í’v¥RÎÌùó﬩«»ùž_ÿú[¾ÿÞï”—\tQ¼¢P8å…_ünOssÃ(ÜŠ»lýkÖнy3‰xœˆÚµB-ÝÜ't -9täP?´elŸ2ûå~—K¾ÑGIÜë}6>7T6ü妱¾¦3›¥;cì²ãÙg ~ôÈ#ìõÀß“JÉÙ ~X}ý­ÅâÎßüæ7ñ&å“õö§ ž~üÓŸìTê©–/ÿjõäÉë÷x/ðäúõüü…¨š;—Ó§£ ,)ݱ¢4°aÀr(}¼ÒÛ÷=ã<ózsé:=Ï.ºÄ8>`TóÛd³?>jìë±á‰/ÑÐß ?«ù>æò{æy}¹Ùd’ Ë—³?áGžØ÷Àwæ/YòýQ&ÜÚï¸åëô®$€N_¸êªD²P8õÙgŸ½­}Ë–£pá¢BÑ’ +Yûžm`zjù¦‹hä親I skV¥Ie” ð÷îŸRnÏžŽCS(!J-ß Lo_ùd’QË—³Ùq¸íá?øb¿#™”§ŸvÚõÓ§ßÚV,îŒS,±íÃÑþ£Ð_Í(:N!–N?õ‘³ÏþêCBÜÒºaÃÌc€ß¯]‹¾úP d6oFTT”$AØ d ÐeãF èùA$fÙ`)¤Óý}£¥ëm€Â±ˆú„PÞôöö’O¥yür6J‡›þðög2dîdÒ9óŒ3î7}ú­ûm{'Jù#­õ„×Ñޕh&Ó›°"òRìtú©s>úÑkÇ74lØ;–í·k×rë³Ï™;—ÊiÓÙ,–mæÀ‡Ç»›nœïzéáézÚThF²9Ú²,wЊÎrBgË4 ãÚr.hÀÅôІæKÎÃ5r³}}ä+*¨]¾œRòíßÿž]™ ½@g2éœ}æ™wN˜5ëÖN¥vê¿®çÑÜXŠJå‹éôãŸüøÇ¯ÔÐðæn\+ø7kÖðçž%:w•Ó§#2¬b‘¨Wæüxßßö*46F¼üë4`X–Û c‚‰ ,3É s¹ëÊÜÏœ°Ž1˜“g,ïù£–E®¯\*Eí²elp$ÿúû‡Ø‘ÉÐt%öÇÎ:ë® sæÜÜ¥ÔNs´Õ‘H‡ÂøºWAÁqŠÑÊÊÇÏÿÔ§Ä}¿úÕMo½õÖŒÀ«× |ó B ›7»•™H T¦(7]@ÓÐÀ•KáòÁÎ;:4. þIDATÀûöÃ×Çu拉TÀ^°„@ A_O þñdzƶùçß?ÄÞL†ПHÈó>ò‘»'Í{˾|ÞûΡ>ï!¤#C#  à8¹HeåcŸ¹àûç÷ÝwëÚ7ßlürõj$ðï'žH*£°aƒÛš4 0t¾é–»\%½[àu ‹Ýƒ „¿’_¤èëé!_QÁ1Ë–ñºmóµ‡\ðó@.‘p>óñß9yÞ¼›÷çó;9 >þÁ¤#¦À/êÍs+ÚvÞN§Ÿ¸è ¿2{æÌ·öâ®CpÏêÕüóÊ•ÐÐ@jÆ D¾€U(`E"þg­7µ>.«¯Ãú<,Â$òõ¸yïrê$|®ô÷õQ¨®fIJe¼n;\ý»ßÑêéüL"!W|âwÌX¸ðæ.ÇÙiïUétD øFš§ ªªê©Ë?ûٯΛ5ký^\ÃðÇ«Wóµ•+qI4Ì€|+Ÿw»’ú[Wx¹Š.§§+‹D u³yo].;¡;îß××G¶ºšáK—òŠíð¹ßý–Oççâqç’sÏýþÌE‹ní4¬ýX,†¥ÝË#˜Ž¸ 0S$!ç8…HUÕSŸ»øâk#?ùÉm«Ö­›Q ü÷êÕØÀ÷O>™˜È Ü‹’ÉàJ¹ûP½aup(¶ÀÁ¦r x:Þ.ó<ï˜cÛdz{ÉUW3|ñb^Èç¹ìw¿eO&Cñ¸ó… .¸³qáÂ[Ûr9ßÚw爯ÓQ%¸¢¼ eÞª®~üó—]v-?úѫ֮mLw­^üç)§¸$Ø´ º»ñx <íó¬`¤p8w°có< ¤±î 2}~÷d‰ã8‹Eœ¡C¾hÏçó¬øÝïØ“É¸‹qÇãö—/¼ðîÆãŽ»¹=›u­ý£º™Ž:´w/‹ÑêêÇ¿|ùåÂúïÿ¾é¹µkg$ÿZ½šðÓO&™J![[Q™Lø&¥hnhõe«Õè”ïéSú_°ßèÀ#ÊgÜG á:”a3fðt6Ë…¿ý-ûúû±€D"!¯þÌgîž½té-û3™€ßòv:êÐI(Eζs‘êêǾô¹ÏÙâ¿þëÖgßx£!Ü·n#ÇŽãkKŽcĤIÐÙé {»VïïkÕàÿ:ôdFý1{^¹(w+Ÿ$PR! ìÃy±¿Ÿ~äºûûÝU» ç/¾øÎ9K–ÜÜ–ËíÃþÝ»Há.\™*Œ¬´ÔÇÂP0WÏ6¶H† .‡?ά—[Ë{¹ä¼ýœ—…°¿p!',gdE›ºº v¾tÙewÌ;î¸[Ûs9_ìîØþ¡¦÷ŒfŠD"d=ïàk_þòµwÿÏÿ|û…_œ·Û6†ÄcDº:‚ nÜÈæ§iÀm¥z½c:fQúh’nѦDwáš0¿ÄþNEé[‡zuU©$t´Óôü*šÚÛÙžÏe.»êªÿž½hÑ­¹ÜN¼P±4TÇ{•Þ7žŸwœ|¢ªê‰/_}u÷ß^}õo®_¿lïÞ½5ÉI“"U±˜¿Æ¾Ž»cYä…À¶,²ˆË‡³ZW2ÓÉìÿ/‰ýÒ‡Ãûþd]®¼ï(EŸÔÔÔdÇÏll9kÞ¼‡GŒýÇ®\n—°,ÄQŠòLz_À\n¦è8¾¸ø¤“Þ:îćçòù„Tª¤¶½8€9 ,à„ï­ËßÎE,ÓÍ2AÐØ#ÔzÍczÝžx4êÄc±Þl±¸¿/ŸÏ öŒïe:,ƒBÿ7ý7ñPðÿ¦÷wúgi!(–\@IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_find.png000066400000000000000000000300221217176075400245070ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½}|Tå™ÿÿ>çÌ93™É$“™Ìd’!!‚…" « ‰E(Bu]­][tû}m·[«öûÝvÛn«n»ý¹ÝÝÚn[k¿¶hëÚm¿Öj¥TäÁº ø€!&3™d’!“y:çüþ¸Ï$“@@Á ù¼^×ë>sfæÌ™s}®ë¾î§ë–LÓd^Èï÷ LàýÅ>ä˜ À‡øc‚rØF{C’¤³y#bÙòU`.€¢(sUUõÈ’„ašd³Yt]oš6¬_·õ}»Ñs£µö¤Qß8ËX¶|•G–¤:§t©ß˜ëózæ‚AϤP§»]C’LL²™4=‰ÑŽNÚŽ¶ÓþN‘ÎÎæXg¬>ï6Lsë)1. °lù*ÃáX] ­š<¹zõ%—\¬Y3ñz=ŸÑud_©TŠL6 †€ªªh.— UU>Ÿèëã`Ãvì|…7÷5ÄÃáð3©Tj݆õëž9ãhc\`ÙòUs«‚Á;§]0mͲe×0wÎl2© ííF¢tuuÓÛÛCâX‚TŠl6‡iH² €ÃáÀérQâ.Åë-ÃWî' PU5 —Û@ccÏ?¿‘×vÕ7G::~i˜æ£Ö¯k>cnœb\`ùŠÕuÕÕ¡{ìcu«V® ¤ÄM²¯ÆÆFÞ>|˜#--´µ¾C}}}¸á@CWk[[ H½ViÃoØØ}^_Umíä’‹æÎ«œ~ÁtwÍäjÏ«eÚ´ix¼^2™,úÓFž[¿ÖÖÖG Ó¼ïÃD„÷•Ë–¯ª ƒ\qÅe«oºñ/Ñ4Ö–ö½ù&Ø·o_æÅ_l9ØÔtxèÒ@H:ƒÊÏ €h€¨€Ã:ö“>~å•S.¿êªóf̘ÁÌÌbÚôi<÷Üž^·.ÞÖvô‡À6¬_Ïþì8ÅûF€ëo¸ùÞE‹Þ¹fÍ­Ÿ×KóáÃìzã öîÞͦM›Ã/mß¶hŽI A€”õ:g½ÎÀ°.­ Z12`·Ä¸€"«t.OIɬ[ÿúÖ¹ ]ZrѼy̘9“L&Ë#¿|Œ75÷õõÝöAÏ:–-_U[]zúÖ[?=wÉâEÄ¢Qvìx…×^ÝÉÿûíMû6ìŽÝ–$€N«ì³$ÅPPè@X½ŠP¶f•. (Ü–”šŒ|áßáó—.½¬®ä’KP]SÃþ†<øàC45½ýྪ78«X¹êúÕÍ›÷È]w~Éãñ”ðêÎlß¶gžù}xëK/¾4 ”ŽZÇ=¥g Dç8÷ï0ÁiýRHåoTfДe”ZÇy)r¨Úœ¯ýk—_VWgÿØâÅ +üèÇ?eó–-õÙlî“ÄØà¬àún¾ëš«¯zàoÿöoèÇÙ¼y3/lÜ”ùÉCîv ~h:´ôŒ%Y@7M³¨ηÎÕ¼ŸAÄÝ@$v?ù*½‡[øÑý_’Z÷®Ë“¡(ú¿% tá‚—Ýñ÷w̯»¢ŽªPˆgžy–Çþë×ñdÿåÖ¯«?­0NqVp÷<ò©›ÿjÍ ×¯¢ùða6mÜÈSO?ݵþOz8¼ƒò"óÍ{ kšæ"`&0áºû $5LÒeáñQ,büv™ßÿö1~ýƒÏ¨"ø´Ê`Ö÷î¿ÿË–-·Ïž3›mÛvð£?HOoïmÖ¯{ô”Â8Å'À7}ú‘5kn]³|ÙÇÙ·w/6làg?ûÙÁƦ¦u@+"Ðkc0ØëÒ¦i€À ˆÀ.ÿ^¡âÇB€á’!O„¤søëË$ƒ¨*¤ÞuÇ7Þtó_U,\´ˆ]õ»ù·{€x<þ!Á%Àõ7ÜüÈí·}vÍŠ˨ߵ‹?<÷÷Þ{ï6Ý06€&„2ú°lšfð÷Àr„‚‡+þt¬?¯ø|zžÝM6›ƒl2iøLä&ÀdÊo¹éæO~þï>Á’¥Ky}W=ÿú½'‘8ö Á#ÀªÕ7ÜõW7ÞøÀ-·ÜÄîúz~ÿÌ:¾uß½›€çýëO0hù)Ó4ï>ƒˆàóŠ£)4ëÏ Êö[Èé9Ðu¡ülrYHg îåî¿, "ˆB¡tõÊU×ùß=gÉÒ¥lÝú?üÑOâ©Têœ FÓó¨£cÁò«W_¶dÉ·Ür ûøãÖó­ûî}ØÔQD€v Hš¦9øO`*ƒ / þ2Ã${Éðº8²+NŸ®ƒÃ¹œE’S@R ²²„G·˜á5—KǬï倚gž]÷;EUp8sêê–î{{ì×[–-_uÞ±‰xÚX¶|UíŒÓ¹ë®;hokcãóâÛßþöV`°èb° ·ß4ÍOßA´×“¯ì±(~$¥çå(о?…®ªBÙº²Š ô,ȲÉ*‘áW[ÍcŸ©“Y×HSŸ|ê©'ª‚•¥n·»öæ›näðÛÍž—^Úö4pùé>¯ñŠÓžâ-ó<}Ç¿àÉerlzá~þó_ìKfR¿ö"”߃ @Ò4ÍBôÐEñ§B„pà0´6Bùšª vMkØòÇv°;À¡ ápÀ¯¶šiļ‚àÿу?yìwO>ŽF£Üù¥¿' Õ-[¾êÞÓ}^ã§E€+¯¿wõªëæÖÖÖðâ‹[xö÷ÏFöìÛû †*?PþÈ`ox€v2" ·ö‘Hм٠Ý6@‘AUÀ¦‚ªY¥%v;¨öR84ûA4U›è7¿õ­ßmz~cÊåtò¹Û× ª¶{–-_5÷tžÙxÅ)`îE ¦M›6íîo¼ž lݲ%ýÄSOþQçw3´Îÿ9p+§çî ½A!!òe؆¾ü €Êà¨*@ÕfyË ¨vñ:OÍ¿Ú2à šÁëáÿï_ïß´sÇ.¼˜Å—^ ðÀ©>³ñŒS&@(z`Ígn-Éf³¼¼m;?_ûÈ&`'Q¾œª»áž¬išwŸåx—^¨Èᢠù Âq€cÀ¾¨¨â5›%Ê0QAS4UA³©hª*J› M³^k*šª¡Ùí¢|d“iB0‚ @lÏÞ½/ý~ݺ·cÑ(·n §nÙòUkNïq?œ,\üñ‹/ž¿bΜY¼þÊ«lÞ¼¹#ü7Âò“àOüÓßÍnùݽ+G(u¤ú}¤@Nçx#Hx³Kó6l Ø$«´Ye^T°)26›ŠMQ°©ª8¶Ù°©vlª†ÍnǦ©Ø4»_<4 UD•øîý÷?¹}Ûö”ßçãê«/¸çôùøÂ©@.÷ùï¹åæ›èK$xýµ×yü׿yœnÝêÔ’ÕŸÏlø¯¯V?CXꉚvcñCƒz ØÝ ¦,ª|EE²Jy°µ§ØF:§¢(*ŠªŠcÕVp¬ •‡þØÖ¾ÐD~ùد^nmiåÆþoYYíÅ Œ™µS¦}lîܹ—N›6•úúz¶¿¼ý¾ H"W§æ^±:síw€1wª®$ë/ôà@·vÙÛ0O ”Ê0±)ÂØTlŠ ›¢bSmÂ3¨ªå TlvÛß~ó¿càŒ=O>õÔ¶×_{5åv»Xò±Eðñc%€ ÿaåÊOÍdØ»g/7oþ-D©ÊL™{Yöã+?«WUûäçöòð%FòND‚á 7‡IC¤äÅKRx~¸Ò‡Ÿ³©‚yÅ+ê Tu°j˜¿èj.\ò©.PÛ€Þß=ùÔŽH$Âu«Wâ,*ª]¶|Õê÷D ï#ÆJ€)3f̸bÁ‚ùìßÿ»wï9FêQ骩ó3—,¾VŸ5o¾¤ª¨ŠŠºµ™§€µœ\ñ£¹üáß;}"êW¥ÁI ª\ ’%ÃÏY-Ã2/²‚ªØPÕ¦X¥j³‰cUEýÔß|§/4mq7Ðóø¯ù­7÷S rÁôé ‚Üsc"@¨ºöÓ /Yà8t ú={_Bñd“?’½`ö"ý/_cÞº” U+ÈRl;£|ØÌñÊ)Ò/ ò†+?‘„·ó–Î0ËÏŸî _Ë ­2d+0”¬ê _جûWmÂK¨¶²Š ¼ôš[{=Q o럷î6 ƒ+ê.X½lùªÚ÷FïÆBw0\YWw]]]466õïØùÚ‹ª)ÙªšY¹™sÁ*¿ <¼b6_Vál jþ1àDßð(øÄÏF†Yv^°D*ð rÁ¹áž Ð Ø÷([ÖŸ¿ï`SÔ+WÞžš>óâ„¢–$ŸßøÂîæ·ßfᔺ‹Îéj`,˜:{öœùÓ§O£¥¹™Co~Üœ«MÕ«§Ì6§^p¡ôé%,CŒ¨ým]-W*–{$IwÁ}ˆI Õ>å·¥ ]¨ìBN†Âj€H ;V@Ud¡hYFU$¡x›U(–duÔK–¬JL¹`v×k»öi:t(ív»¨© °ô½PÄû…±àš©ç@kK+ÍGÞ©¯VëàT£ºv–éó{àz]ý?^ìgº$¡I6´nƒ\¾èX9‘Û®|]M0m,"K¯óÇyþZV„(V)YÇy±)h²Œ6wáÊtÍ”™ý^¯ßØû澃³gÍ‚¸p‚¡ÅýèLÚÛÛˆÄzüÕFypŠª™*©vT ŽÁ€Ï.ÃwünJ U’Q{!× ÿ1#h$«ÏOõ.$@8+îï8k^~†aÖÏç ½€„¸GY²¼Œ*)¨’TP5(¨²ªÙæ\´´×¥ö¾¹ïP¼«‹‹.š‹,I,[¾ªî]êá}ÃÉPq^í”é³fÍ$‰DÛ\nOÒ¨1=þÉ[^¡Ü²˜+9>·WÁ?–©”äö1Ðûà¿AGr÷…‹=ô¬˜)<ª²G{o¤×ÇWCÈ$¡J6¡xYAµÉV5¯Ôlµú¼æj§\pìèÑp´#¡¶¶W±¬Ìç"NF€PeUUuUU%±XŒ®xü×4K¼A<¾I’£HQyŒÜÌ« Àn(É»Û$}b¾@'ÇÏñ/DDCö§ìþæþ‡vø9áâei°”ò"‹sŠ‚f€Vsþœ\Uõù©d*‡;z].'`Îi<ûq“ à-+sº\Nâ]]ô§2Ýe¾ ©´,(—xü6EF¦0z3¯Â·»ÀWJH ˆv=‹§àØÈB÷X•ÏIH?.Œ ãB‘ ”.ËVL`#£!¡N½`vÚWÔãñ¬  ö´žþ8À‰fÙùn·€D"A.g´—zü’Ëí“ÅÅŠ,!AŒñ6ã÷ÀM½ðTVô ’R°Ý!¾°~O²$nŠQ]åTÿŒÌ`0‘‡ÄP#[7wÜw­BùR’A’Äp£$ƒ,A& Õ“/Èz½åzg4Ö„|ååpW'#€Rl-³NöõcSí·Ç§¹¼6ÍáÐfLÁÇÉq ÀW+ð'Ý"µì§Á%æãU!t#éb’‡v&þly¦åÉ º4芤üòŸ“¬Ïèà+«Ê|AÓÀJJJ@,49'q"”ÎbW1™L ÍQÜár•Èv»KQY z rråçëú27\™í)¡t’pÔ)^OBò» ÀH^àdŸ× ^HÒà3Yf2äL(r•ÈÁÊl*ÙÛ ÷ç*N8ÁPª Ždu’ÒRÅå*µi§*KhºŽÑ‡nGŠðK5¨s‰Ã:: I]tÅNµî?‘ŒŒå³ÃÏç¿ghî2dWq±M±)Y»&¸jå3:çp" HyŽPìrÛÎ"Í¡Ê çŒ!8QçN¢nõA8ÿ†Õ‰ Ë¢ê_(4JK‘yv¿'Úxp2ÐßÜüöç”û¼®t*^æ, ÅÝNrÑ8x›ÞÚ9ǹü‘¬]B´÷ó¥ Ⱥèqõƒ–y*1Àðz=îDÖŸ¯ëuSÜ„®ƒž·üüëät(ö@©Qr¹l%²Ì»ô¾õnu\áDè‰Þ®†£Gƨ­­eCc7ø‘”»HÎÙU̶9 åx˜J)T¾HVs[¶žÿ@ýŸ'Œë€Ñ”?ÒC¡hÓÊ"¢ëBÙ…Š×s¢yâqC‰ €³¸¸¸Ô0àPc@ó¹œVîd­€Ðëêêܶm{ùêÕ+ih8èwhf‹»˜œÛ‰ÙÙ‡¢ôNñ8"–'E¡ò spÌÆÈ‰ ÐQ8ˆ#|ŽWòHÞ¶Iù£YNŸ‘S‘ô,du«Ì‰àÏãHJ^æ)))Û»w±œÃÖ'¯ºìÑpûÿùA‡C dúb·;pÌçÁèJ@C3Éj?Þ%HRÂ<®Ó^  ½ÁÀG¸Á“µñ‡+ÿ¸qkËÂu](<«çI`èPV^+Ìííí­*))aÓ¦ÐuÄ §s'ëêú6ìÛvhÆÌÅ-­m̘1“'M›8â+AA$á89o *²°zy°:ÈëÓFðÄ&(ÃIC­~8 1ZÝ?’òÍ‚s…®~ Ìx€äÒ¢ãÇç[.›­He2ìªß?×÷!8Yœu ‘èé@<ï|ö÷ÏâóûÐsé —†Ã[ŠÃïÁc_ý™J&‹-«cKØÒ`Ë Q‡‰¦[’Õù_8rViˆqísfA™³JÝ:ÖuzG.‹CÏYÇ9ÙìPÉé8|e8œ"ñt¹×çsnÜø1áþÏiåÃÉ=@>{wö­†ýÛ·¿\uÝg>s+µçMÑZ7U†ÎŸ ”cvÆ¡= à)Å&+Ș’„‰‚!ËÂødË%«Ê0Áfõ¿ q…íÿ±ÃÝÿpW3°üX*9+`.+¼@6™Œ°~‡‚>xRÉd•ÃédßÏÿüOú„Ç9Næ Äúÿx$ܶ±#M>ñä郞©&i¸Š*Êpý8làØÿ6¹L[*ƒšN£f²Ø2ÔLV¬®ÉC¼€]-'ÊkÕ-Éç½Âhb ûn¡õ×°|}˜•g²82iÙŒ°þŠ2Áòë/q8îÍ›_¤¹ùÀÖsu°cI׋¨|{÷î~aÓFÿu«W¯bÚôéjSÓáòÚ©Sz«üO@8‡Û0CØd‘Ï”LtQJ2È ¦,a"cZiZÕwÞêóÓ´òßX<ÀhõÿÀd…‚à./¹¬•@2 é4dÓ"‰d:-¢þªDÝO²/Yát9yâɧ1DÒÅûÆðìÆ=ÆB€|0)nÛØ^õèÚÇœ_þò´9âQ¦NÉUùŸ@_?4·Ë‰ê,ɲd)ß&”/å@¶aÊ H‚`õäû‹‡„c™È1R³.œ+pùYKù+sh:m¹üŒ(3Và7)¡ŠÞ,Íér:žxòZŽ XÿÖ1<»q±&ŠìBLß*Þ»w÷ n·ûº+®¬cÞEI{wïöÌž3'Y€dšZ¡±éüZ‘ SR@Ö-`Y·ÎÙI`“À=@átîõœ°ãgx§Ž>Xß畟Ë@&iK0…åWW€WL÷“ ]/ŽuÅyæég0L“Þžø?œÊCÏ+z«yÊ#á¶uÝ]]‹~øåÿùÃïãõzÕd2ã 853U©,´…æV˜T‰$[Ézd+Ql¨P¬aY¢¤ %B¾¿NÜPèòúºQ@}0ÀÓ \~ƲútRq~’jª f°[K‘EþɃ?¥«;NoO|íöm/¾vªz¼b¬0Õ@ à~qëÆµENçW~üàCÜyÇhØ¿_1s&5H[mè¶(´EÀïT¾¢ O (ÕÃ@*WCf~j¶ådydå瑆èåoä :xòm|ËÕ(?%êÿ /ÔVÁy¡¿ñÔSëxíÕ×ɤÓÛ·½xï)?åqŒSÉC,€èìßÿæFUµ]=ý‚i,ûøÕ48À´éÓ™â?o‹ŠöžÇc@ôVL€ªX–j!'‰¡W)¿Rk¡ÆH‘ a ¯ü¼õëCI {zV4Sàú³Y±|é¼Ô††.JØ»w?¿þÍÿC7Mvï©ÿ2b™û§š,ú(b§»¥¹é7“BÕ3Ö>òËêPUˆÙ³gÒÔØÈÔiÓ˜bY, /AI±ð6k^d%õÓUAEõ´Md =u­áÈw$Z~>è3 wr9Qïçrƒ‘~.-ܾ‘… W(þüøsyD"Q~ðƒÿ¤¯¯¦C‡‰EÃOžêï8ýªû÷L*¯¼zù=“B•ξïj&…ˆÆbøý~t 9 ÍíÐur‘TÕª ql³ É'ó“­ä~’E‚á`ÈÊcpÒæ ò]»ÖlžÂžœUϧ-ë—J?ÔV ×ï,ø“Éd’¯ý[h<„§¤˜ßüæñ+9ÎI¼—FÈÀy–L&_yõò¯ÔÖÖ8ï»ç›„BUtuuáõŠî³Ö^hi‡ÖèéI›Iœm^a€ù€ÐŠ$=A!òA_át.='ˆË~ùÞ¾4¤-/à´C(“ƒPã·VÁXH¥2üÓ·îcß¾}Ô]QÇœ /ä·?þë/o„ÏÉΟ÷zÇ;ÂT#¶]™¿lùª/VUVòÍúµµ54>Lí”)ÄR ´u@G—ÊT;Øm¨…°bEh&(€µôàT.kB‡nâå²V2‚?e%¢_€ªaKûz î»ï»ìë->÷7·Qæ-§7уÃáà7?߸~ÃåíÑsgb˘«‚2YÑ_óñko÷û}Üõ¥/qÑEshkm#TÄä‚öŠî„°`U)»ò¹]mÊ`Œ0°ÁÃH$0Ç“1 gX fÁovÐú1Àí‚`¹èßDÒ‚B´¶¶qÿýÿÆáæf¾ùͯ±há‘û÷7ЛHàphüæ±Çâ_ºëÎg‚UU«u=·ÕY中Üç÷«‚ÎÔžAùÝ·&#VO¿òêå_ôxJœ·~ú¯Yµj½½½ù%Ôte"1ˆÆ¡7!”gS^(¶ÁU8-áýÇÖŸŸÅ«Z¾,ƒ»HDùå^¨ôA °²·°}ûN|èÿ‹Å¸å–OQW·„êPÀ¬^¹lÈ÷š[Zã®"çå@ù¸ö gr×°B”“—Ö]ýÅb·»|ÉâEÜqÇßátŠ #+.ˆe Ú±8tõ@ü˜èD2ŒÁ@°09ƒ ÇÍÏO/˜ÓoõøÉ€¦ ‹÷–Šñ|¿®‘[“ÿâQÖ¯_O*•¡?yìÀ½÷Ü㬠…ªNÇxË<$ûûH%Sƒƒ‡›[âN§ãîÊŠŠGÇúÐÎ6Îô¾yTXR<ÿâE_ôûýÓ«*+YóÙ¿fÉ’Å$z{qx€^}=Ç ·ú’¢‰¦ëÂ;œ ²,2?ivpÛ ¥n1 SæèÒ=ûö5ððÃ?§ñP†iR¿k×3ápëS@é–-þŠ “êP€‡±–¶ö0’³gÏæúU+®Õcü`R¨òîSypg gcçÐ bwÎIˆÍÕ@0´ê¢‹þâ:EQø‹ùóXóÙÏP[[C²/‰Ó5Ô@,ŽÍIDAToý‚Éô[möL¶€ Öíæ;‘TE(Þ¡Ó!”_ì·64²/D¬«‹_þêq^zi©TŠþd²óÅ­†È]$#’^ ÈagóÖ­´·µÓ—ì#›ÍÓ§OãoÖ|vàº}}Ib]±­.—ë“ã-.8[{—!6a XR TÏ¿xѧü~ÿtgQ /]ÀMu#5Õ!2™ š6²yX[‹æoôAwƒ›¨*8lb^ùh Ï£«+ÎO>ÅÖ­[‰ÇÅr†ýûßÜØÒÜô_ˆ ­ßFì1\…E‚W^{ã_ô\¶$Ú¥áÀAâñ’É~2™4’,ã-+ã«ÿðe\ÎAB76®÷z<·•—ûÆM\p6ww" QxEV´ÅK–,½®Èé,w:Ìš=‹×.gÁ‚ùd3ÔQÈðn±Ï>·ž7^ßEOâÑhôÀë¯nÿðbi×aÄr¸ëþ«.¾xÁ•O>ýÔ×ãñ8½=½¼ÓÖFÃÄã½ôõ#›Í!Ëšfç}î6.š;˜-îpsK¼ØUt[E 0.¦Õíãn4ˆP~¹%Å€\HY’VTpáÜ Yºd13gÎDÓ„†räÛ •Å»ãÄãql¤éðaâñ8ÙlÅ6¸þeåʬZ±|àu8ƒ»+++~pZä=ÄÙ&@Å"” HPb“y³/œ¿84iÒ<Y’ðx<„&U1õ¼)LŸ1ƒÚÉÕø|>\nר³‚ú’Iººã´µ¶Òpà‡ÑòN+]]ÝJÏf³ÉÖÖ#olØ—ßζ1®ÑŠ˜÷8¦K–.]:ó‰'Ÿ¼³·'a‹Ç ^{£žÖÖVú“ITUEQÄT–l6ÇÔóÏç«ÿû®‹D¢QrYýÑP¨ò¶w÷(ßÞ/€Õù†¨[=XCÊ"¨€SV´y³fÍž—'CŠ¢àp8,ÑPUYR0L=›%•I‘L¦ÈdÒù5zèO&;†ÛlØ÷ÂÚ!Ö9t"6ˆëÁáx @2Bùeå;-)fyÉóW#ç †îMÔ°ðB齜ÜâGºÏjDk p¾ð ÷‘Y³þ"뢫«›ææf^Þ±I’q:‹Ð4»ˆ ƒL6K*ÕÏêU×qEÝÒ‹¶µµÇÝn÷'KKK¶žâý¼+Œ'BE(¾±¯°Ã ¡£„âó[Ñæ÷(L"2v³d,Ö> Ipà~íõ×ïT/ˆuÆèêîâ­†ި߃³¨—«»Ý†¢Ø0 ÈfÒô§R\Q·”Ë»›[ZñxJo++-}ô]ÜÛ)a¼`8œ ®çWÜVæøì¡)„ò ë8‡P~ú=¾'•Á¡ïPúæ¾}_q»«c1:»»xõÕWi9ÒJI©›â"šÝŽ¢(˜˜¤ÓYúû“TƒÜyÇ.‰ÆÐìê}e¥¥÷¾Ç÷;"ÎŒWØcyTí踧ïXÒÙ‹ëêâÏ~‰D"AII)®bEš†¤ØÀ4Ȥ3ëOâv¹øê?|yࢱ®.$Y~ÔWVvÆ[£éùÝäaú0!¿³x;"¦ˆÌŸ7ï{¾r/^¯Oi /Y€¦ÙI¥’äÒi L›„Ý¡ár»(ó”Ig¸ïÛ߸¨ÏëÅép®éˆt>¢›æû’jv‚cGA€6 £½½½õÛÿüÏk½eexË<øÊËøØ¢KÉd²$S)Ò™, (6Å.7ž2vÍÎ×¾ñ-Úà —³hM,Öµ%“ËuLàÔЋèChº¿ÿÿ±íwO<ñ{¯·o™Ÿ¿œK.¾8?ÀD&“Á0 Yôg¸‹]x¼Êý>|èg„#Q\.'~Ÿwn,ÛÒŸNŸULħ‡üð÷ dÃóÏß>gΜÅQb±Nš´P_¿¯×‹ÇSŠÛUŒÃ!CÝ4H§2$ â=q®¾êJ-\0pá¶öözÇsy±Ëõžv¦çS>0¢u µË®¹fí‘––šrŸ¯Ú4 t]'Ñ› åH 6UESmb7j›†CÑÐTk_ZUeëÖ?ÓŸìçÊ+êUUÍmimÛ’ÉänÓ4Ûï0š¨NmˆÞÆ ;¹¦æ{©þd«¯Ü‹·ÌËô ¦Ss^ ½==$úúɤ2˜9E²áp8q—¸ñú¼øý~^{c›·¾8pášêÐÜp$¼¥?>ã[ÑLx€Ó‡ íˆ+Î?ê{zzï1 Ãi˜ç›S‘‘ wt`·©¨šŠj×Кæ@Sm¨ªØ¦´¾~²$S·t Õ¡§¹¥uK__ÿå.WÑóxwÈ"š‡ ªeÞ¼¹ß{õõ׿’ÓM§nèºIO¢‡xo7Š¥pMµc×욆]³[U‚Âî={Ql K/ ¶¦Ús¸¹y˱c}—»Î &ª€w!ÍÃǹñ†~ ðû|ø|eÌžõQ4­ˆxðíûî[¨¨Àï/§ÜçcæŒ Ðìvâñ8½‰ýÉ$ºžCQœÎ"<~Ÿ` ‚½ûö±}Ç΋O2Åuné舼ç$˜¨Þ;ô"¶ÅÕÛý÷ß¿Í4M¾þoÜn9Sgš o7¦«+ŽM­»fG³khšUU±©*Šª²oß[È’ÌÂ0sÆô¹ûö7l9z´ãòÊÊŠ÷¬‰8ÑðÞcÈb™?üá7/^¼äêpø(áh„X¬‹Ö#ï¨(Çç+ÇãñPì,B±)d39}Çèîê¦#eÖ¬™,¸xþÀÅ÷íÛ__æó^ª¬<%Lôœ=„U« °âŸøÍŸÿügç¬Y³˜º~§­XW7ŠªŠ–€jÃ¥Ùqºì¨š60Õ¬¡á²,qñü‹˜5kæÜ½ûöoi;zô”I0&pfï(²5—]vÙÚ­[·òÑÎ^l¦•A£½=L¬3&¶(·ª»]C³ ¨6ŦÐpà À f¿‡$˜ À™ÁÐL"5uuuk7mÙÂìY³¦‰aPáÑX EQQm"p»\¸‹]hvÅ&rÙ,‘Ž¢Ñ(ñ®.ú’IdI¢¤ÄM0dRUÕ“ªyný’© `‘ÀW~Z$˜ ÀÙÃq$¸vÙ²µ{öìÞV¨ XáG³køÊÊIg3„Ã:¢tÅbôõ‰ýùœNÁÊ ¡I!ªC!þ¸~ý ª«C(ŠmÍõ{N‰8»($A;¼öÚekwï©ßVP¬@³Ûðz½˜mŽtÆH&…Ë×T•PeÕÕÕLª®B‚9³g‘ÎdÖìxåµ5c½¡ œ}’ H®¸öÚµ»ë÷l úT*D§«EUho‡‰tFÉdÄÖʲ ¡ªàä±àâùȲôÈk¯¿±f,73ÑüþÁŽXtÀZyôÜsÏÝ>{ÎÜÅ‘Ž0áH„\V'—Íb˜¡PˆI¡I„ª*Q”A» ‡#im¥3ÚÉŠå8ÿú®z$Yºmþ¼¹Âĺ€ñŠãHð‡çž»ýÂ!$Ëä3Ù4¡Ê*B“B„BUC\w{8Bkk+ÑèH›6oÅårÍ»tá%õëÆ'Òˆ&bVuð‰+ÖîÙ]¿-P$`Se Ã@Óì„ÃÚÞiãh[û‹TTW‡ðù|<ûÜ`upåuôõ%·ìxåµÚÑn`‚ï?F$Áw¿óíµCH 8::£´¾ÓF[ûpˆ˜Àçó±mÛà„’ çÌö¼}¸yõh?>A€ñ|·ñ zè¡mßýο¬ V ‚ØT…t&…C“JZ[Ûhæ BUAªC“00xõõ]ø}^öîÛ;êD’‰±€ñƒác=ôà6dø§o|ãv€ŽHý©E‰c Ž´¶b` …,¹*T‰®ëi¸T¼«+þèh?:áÆ =A+ÐýЃnûî¿üËÚ@E€`°MµÑŸJa&©TŠÖÖwx§¥•¬•G‘e‚UAªª*xìñ_ÿãC?ùaóh?8Ñ ŸÈç%ðaÍ,úü¾°ø®»¾|s__ÂGɤ38œŠTÕF0XIUU‡•i-‘èãÑ_=úø—¾øÅÛ€ìD3ðÜC>ÓZ‹~¿¿zÛË/%‘8æŒtDH¥R9”øÊ}ƒ¸].¶mß¾õc‹‘m¢àF~ŽaðÉÛ_Þù•D"á ‡#¤RI4‡§EÇCSSÓÖO¬¸öÿ r ŠU&pN#ï *Š@ 0ùå;¿’Hô9Ãá0}É$»†¬Øxâ·¿ýÕÚ_<ü°“‚ô88÷‘ÏŜߤ£xÇ+¯|ÅétV‡ÃllL>ðýïÿ´©ñà“À.†¥Ê™ Àeˆª A†Ò;î¼sq2™rþâáŸmv a—'i‚äwj H "¥Þb”¬hø`!ŸÐ:Ÿv7?¿`Ô”xøà!Ÿc1‹X›xBœ2&ðáÀDWð‡øc‚rLàCŽÿWìžMŒ€ýIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_forward.png000066400000000000000000000224301217176075400252370ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíy°%×]ß?¿sz¹Ë[ç½7«f$4’,Ù2Þ7QÆS àI!E¥RP,a©¤H˜„”-HŠ¢*„T !)bÙ$˜`Rì‹1`0’mei4’gF3oæíË]»ûœ_þèî{ï[fæ½yo3÷;Õs»ûõíîÛ¿ïùmçwN‹ª2ÄÝ s»o`ˆÛ‹!îr p—cH€»CÜåà.Çw9†¸Ë\í""åê-º—!vüÜK2ïª(`àN„\±nDDõY ƒß‹ã8ø{ÿþYEãYæÐ@•¡&¸…Q@ÈÿPT…Bk±ßA¥iºþÑßú¿L’dUUÝUOz­ë  V«UÿøO>¶úšW¿:L’¤¸ü·ùWUPP>‹ýªµzM§§§m4g§ª~·W  oïã86Y–&µZ5 »o?iˆ¡lŒ¹ðŸok|5'„âœËT­“Ëñ†4Àf@TUsņ¸UÈe¯… ¾äž ²‡hnîJM`¬“ï mnílñ÷Àör«o…\ÀFØ*üÂø}4ÌCì ‚!õJ’)Î̵ÉT¹¼ÖåÜR‡À§/5q^¹²ÖåòZ^œkpq¹ËJ;Å«òò|c„Nêiv3 çCOø¾ôtãMì× ‡¸ ÁX!-W»¬´µÈâ$àù+œB³ëyan…z5âãg×°’{÷OŸoP‰BÎεQ„À€ªÇyù¥ MG`àë_=„ßw ÷+&à!ÀðÉKÂ\+æ±ÃX¡ÙõÔO;õ,t<Ó#!+k]FA%'ÆD5`¥1[Ú‰cµí88óÊJ‡Z%#˺QÜ€ð¡o†¸ÍPc”Ç=Ÿ›Kùð ðÀ„ðF<~Ð2¿œñÙ³ËÄÕ€Oüm‹¿~z‘,U‚0$¬DQDT Âü3®Ç˜šåqh¼ÍŸ?×d±‘1Qµ…{ïñ=7À³_Ö{èÜ Tï<£¡ãî÷üè- Þ÷çm~ñ3ÂZȯ?È©c#„¢LV覞V×ÑÌ<ÍTi%Žfdzš8NLÃkÃBÇ3V5ÄVŠè /ü2$Ü/ 5À ª¤N¹´’pxÌð÷9>Z ùëKŽçÛ|Ç«+¼þpÌ›_sˆ#Su._ira>aÙYªÑL…õ¦¢VñòðA!4ÂrËáU ­àU7 K¸' °ˆ@'õœ]èrÿÌŸvŽ·™¡‡¼¼œñóOwøÎÇ+¼ùXÌ=31Ͻ2ÂÑ•&ó ‡­†¤ÖÚŠÃ020Á§/§‹øÄEO#qŒÅ¶/ü^Bhÿ0$ÀàƪŒyö•Žã°vylªŠzeµ“ñóÏt8T¯rl>uÞqp¬ÆÃG3þò kÌ®ÃØTÌW>:ÊìšãO7q™rr²Ë©iËxÅ’¹Ò÷WòDï–0pOú{€ˆÐJ<Äóº{G9zb’VXg¥aˆ4äG+|Í}!¬¾û+ªtSåÅÕ€¯zd„‰HYogtœgq-åéçÖH—[œ÷ C'p0",·Rž»ÜæÁƒU>v…ËW `½óM8Pƒ0@½N õEoP àÄTÌñé œeò@…Ö83Ÿ±ÚÉòŒo)|ÊZýÓC °xU&ªGÇC^œkÑMÝvŠ8¨xˆü¶M(ø4ØÃõFìx”·žA€È /-´9:^¥™8:‰çÐh…æ:Ü?=ÊÅa½ÑâèTg^Zä¡CUæ[–èø!FB¸ÒŽ952»¸Æá™iPÏÒJƒù¥UŽ™Â;WTõB7É ;®åŠt. ©SI½2=Þsê`ç•{¦k\qº.¯>6ÂòZ‹Q@ˆ5=kÍ.ÇLG!nÊå+KŒÖ«T+ÎûM5ºÿ&`¿+N¾T±ã±zEµNY·Ÿ8zjZ5ÿ[V>UFGë\º¼Hµ36Vgnn™$Iyô‘{±Ö ÅP±F³Ãs/œÇ;åÞã‡ú… û,œ¡° v#üÁAªwʸzÅÞQ­FÌLOpéò"5LŒ×#dΑeç=ó +\œ]$ ^õðq¢( s®O¬}dÁVÜåÍÿ¦ ¿Øáœ2R¯rïñƒ\™[a~qUX\Z#Ëf›ÀZœäžcÓczÂ/N7ì ºY¸ÙÂ×â"N=apüØ4§ÇIÒ”F³1†û*‡À8 É\–Óïù|ÚÀ›†›!üÞ9ûè‡p^ñª¡% -õZ¥¨öÉOžfÙ›¯½ëöMÀ~(ƒ!¸yÂWõE®¿ßjËJ Õ’yÕoOG 8›…ïË;0ÃDÐq³„Ÿçþ5¯Ì<Þ+‘Ú‰c´š—|§.ãv+|dÀqW঵üâ˜$SšÝ|0hæ”ßûì:W<“5á½oáC4ÿÞn„¿ŸA[z÷·âìÎÅÍSûù>ï•NêYkg¬´O±ÍïŸnó]﹟ånÈ·ü—sœ¹Ü¥ЛüiçÂß?Ý•ÝÁ7ËÛ×âËJ^쑤žfWiv•å6œ~¥ÉG>y…o{Û4õ à»~ù"/\Nˆn‹ða3î‚© on¨×÷øUóÔp'õ´2HEÈ~á÷/òK§;¼þkfæàxŸVúþ5„¿ßõ[5Àßa p«âü2V÷ Z´Ôéô8¨Kñ@Š? >'Áá¯ycSã|ϯ^æÅ¹B”-~@øùoÙßLàˆQb­Å3°X¬µXk¶Yì¦%?¾ün~Œ`ÌNɳ›åú?ðV ß÷ì?=5]º„!¡ä@Ùr 9 >¾n¹ï=26=Î÷ü9ÎÌ%„VzŽa)ðÞ}î#6ƒ°h½‘’|I‘\°ùßûZÂ!‚ $²Övàs;2™‚@ýóZ»ý’_3¿‡«áV ¿ÜÑoÞšäd)†o€xøD3àä×å$øÞÿ9Ï‹s)Q›òN(#…Ákì[L€÷åÁÛŸ\DX^^Æ{µ–4MQU¬µ=axïYXX@U0Æâ½ÒívI’ç2²,ëh»e8ù-–®¿\OÜ.á—¶PKk1ý{ïö7Áä—æ/š¿çULœàû~mž3s)qg7˜€«ÿì]cC&PUIÒ çò‡$¢ ÌUäÂýÜçžett”±±Q®\¹B†c˜ššâäÉ“4 žyæ3Ôj5ºÝ.GŽ¡R©°¾¾Æää$³³³LNNrêÔ©ëNJ]–Âï·Sø½ïnÚäW!­!6öñFÀ»Þó§ç üó.òsßz€§m‘1ìÿÀý¢Á¦<€„Á&§¯ÿgk-çÏŸ'¬5,--333C–et»^ ‚€©©)æçç{ª¼V«2==M»Ýabb¢§€sÒoùåvq[Tý`,Ü7Oý¿Ý>áû¾šî h@T×ñY à3øƒÕ€ÇÞóS3ã|ÿS˼8Ÿåuö× Ü ¬j• Ƽß:Ý{ϱcǘœœ$¼÷Ôj5Nž<ÙP»ÝÆZË#<Âk_ûxiš2>>N¥R +º<qÓh4ˆ¢€8Ži6[Œö~°HîmŽ.Œ‘|Ð…*åtªý޶»Â/çóÕ²O`Pø’Ï/k®yïr¼ëëáÙß{žïÿð*ÿùŽqrÊRÌ!½o¾àÆÎ 1[•ÞŸEhµZ|ò“Ÿäž{ŽÓj5yüñÇ©Õj¼øâYâ8faa'NpéÒ%&&ÆY__'ŽcÒ4emmC‡sâÄ ¼wÉ„³g_âøñãœ>}šz½FWPõ\¹r…w¿ûݤé௖޽”O¡ß týæv,W­¥@ÊZfÝt¿…Oéý—ÉéO®n6 G‚µ€w~íÃüÍGŸã~}•ŸýæqNN™ öƒ[;ƒ¶Q/ýV,…­ŸæàÁjµõz€4MètÚLOOÓé´™™™& C—èvÖÖÖ˜žžÆ¹Œ……y–—WŠpQȲŒÅÅE¢(âÞ{ï% jµ'Nœ@U{‘HVöÍDßD”‘†µA`{‹µAµÈmdŒ`Ä`Ä †^'N)ÆÝ ¿—ðÒµÏ.z/ØaJÄHnþh-àµ_ÿñØ?øÖxiÑÚþ}ì[œÀ«{\y‹áo|ÖZ:Dùn¡‡:…µåÛFJ_`ffclïnÓ4í©òryì±G±Öpüø=Xk¡V«$Iï\%\Q@E!ª†òU9Ýn~/ùënòûU… òÔ¬s=:ÍÒA¼w$IZ8¿¥VØð µ2@‚çZ>>)Wv†’o…|Å×?ÌÓ¿óxUº™²Øtœ[õ\èœ^>ú±+D÷ÎPÝIÔm²®ç•JdyçXÊ_ýÑK,Í/¦KüO4Ï}zN²®ºæÂ®mÂFz‰™Í®@©¬µdY†µAï[eè6x¦A› ekó¹±úÉŸ¼"nddï=ÎåQ÷ž {ß5&X7=©*ÆZTç²Þ=ÖGêÅ53â8¦R‰É agY>Þ^½2è‡l¾h»ÚwŒu€¥–èå"ç!óJæó¨ÅÄaj4b)S|æòÖ½Kv;åœåk¾ú~þöÏLxù ÿâcñäÿû–öÇ~úé]Ÿ¨ Üðn»þÞ펼êw7³1ç [ȷݵ7¤DµŒýó²êÞùT6z÷}óV(ðÂáÛ(ìã­[|/Æ On-úû]ñ)ç(&{^w¤ÊÃ_yˆÿuQYòõ76®ÏvÊ:ËW¿ã8™ç¡/Dßük£ßñï]ÿÕðünÏ÷%SzµîPõ}A–¶×;”\Î纙Ï[§SŹþvæ=™Ï‹72§¤^IdΓ:Šm%-ŽÉ—¼•§çI=ù”o^IÐužV Ý VSÏ;©ó­_~¹g»|ð²ÛQOæÕ`N'åOœåmo9†÷îUg.™ß˜øÁ¿ù¦•Ÿ}ã™ÝœkƒW*õßýß›}Ç;Þ>’¦éõ¾{˰Aë¾VËí‘\È™ë«äÌ)™*IÖß—¸bº7—ÛîÄA×åŸI¦t$¾¿xH2èz ä}þ›§R梘¨ &ÉøÛNH÷ð²é\§J5´¼uÔñ¹O]àìlót\±ï]þ™×í˜4À@Wõƒm…h™Ûg ½[†àÒWÛ^ó!ÜNóêœ!õ ¤ ‰Uº^è8è8¡íòÙ¿;½}]§´³œ—ÿ­ërt 2$^rR뙧縶’iDmf;8Öo°@»“ò gyû›Á§^yìÅ+­LþËgÞ»ü3_¶#ÜÑ&`£¿QTÞ؆l[ù·©áB¥Aî‡ãeõ’WŒHþ*8†ÿG¶ùâÓI¾îñy_¾ñ‚ñ‚U!PA}ñöo•^gTHÑÀ¼¢™c¿ª¤ 9 þJ-_þæcè_]|쥹ÎG&ø3ï]þé×^—wlMàfá÷sô}‡o0ÆÎèØÑ͹þ\käf£ç—)`õ¾¿hþYFêïuÅL_NQçñ™¢™Ÿ—:4ËR‡&…}(M\þB§äÎÈþ,Ö+k­”/ÃÞx”“‡*%‰ûÍÉõÙS×{Îw$¶´|¿©u _·>ÂÏO”¨'ð~ –¯OšÂ£÷Å¢¾ü† {¡£jA"—OëÝ-[¬zÖš)±¤¼îõ‡¹ÿ`õÑ$u¿9ù¯?û൞õ`Œ±á@ +Ë9ûBhù= üçAmi,vð¸â\â/…êõ&µãð¢X @qš¿Òz°¢XŒhÑ#½º$£ ªˆ¤\×ÜŒ Ò#Mé¬ÜJŸÊ«ÍŒ¿t†·¾æ É3W½¸’üæó¹÷.ý‡×lk6ÀãÓ4m_¸x)L’®¨êUŠ˜n6ØîzÝ:Ô~ß ÐÛ.ji¼â|þrçÌçN`æ)¶ gP!+œ·®ÚNèªÐÍ„Žæûº^èøü³X$ñ†®© ™œï‹Ú~5SÇÜ:kMÏ'œáË!;=ÿØÜZú‘?òì7-ýÔ«_Ü|¼ [H†ö­o}ÛW&i2ÓítÇ3çêª>àv×uÃÀ-ˆ”½jZl^Al‰ª– b4Œ-AÅT,ahP±q Al ãÀGµHÃZD…TBµQ¤Aª#µAˆ #oÂ„Ø ô&ˆ¨ Bc"ƪ1b¬Š)»%o92cÃãcÂg¿°Èüzz: í7-ýäcH°äZÄ5 Ä\µ”ñ¶AúŸ;¸µÑC‡Cê“©Ž¦:Ju,J=2Q-”¨U" +‘‰ëU‰ª5 ¢ŠQMlXÁU±aUŒ­`mUŒ­"¶"ÆTEL11b*‰‰‰ AB ¹~V¦0[‡ÏYa±™ž¶Æ|ãÒO>v¶–3CÉq yV@‹¬@ž“òeN²ç´Ð ý¯ÿkT{ùˆÆuŠL¬ÀÜzƱJ@5²$ÿÞü6ì ¤;(A½U O=Aõ‰ïC‚Ò½2QPZn¾Í"¯Y†¥§˜£WÁUîË}È~h™ï,äÚßî_¤\-ò =”}7Áû“íŠ e“6ʱev>¡‘zŒaååòïwt&pᩯbô[ÿ+˜ èÊÃ/ŸEÅÞòÜËžÁ ïZÛX º!Üè²; â&a{b]ý‚ÎÃDÅ;e¾•².¢ß |~ê}Ÿ—Å<ª_O=‘ ߆vó·0Püt'×~æ^áúJŒþ Ùeý^)øž)Ùø¹·ÊšæyuK5€Ë "-Cùm$©_ <õ£ßö ù‹÷\R *þ¸é™o ³‡ f'¼Ù©ù+rr“I ä™æ™º¥¯¬e(´~Õ”‡,¾ÿQ…;œÑC…ðmY·×*EЧ¥2¸úCÝi-þ tËÊ5°§r¾—ªº9Ð\áªÔ#áüJŠ mP¯ÿhÝÅ÷?ÚsòïXD=Áø?þE°!šu{#j ùjYä†Ô_½Š¹Ž‰¸vÁœ\ØÜ.ï{¿{q>µŒ†ÂËË)*Ò6^߯^?¬M üêI€øá'˜øö_ Y‚±%>€Se¬jò~þ«ÔØõ SË×êmÒ&«sÕãzÇ\å:«-Ÿ“`?³š«ýã–±H8»”¢BÇxýIUý°J.ü´Tý%î8Ä?Áä?ùo=áo1 3-XQb  h¦~[áŒÆ†ÀøfƒçÛ¤¾½ï&ÝмÍ}JÎ3xW°”Q”Ï_θ¼ìöÉ(mþ‘ñ€ñH8³˜¢Ð6ʼò°ÌU„w⇞`òÛ$@‹²ó-Тw.‚TX}IK=ÇïXOý†V,±5X³%<Þ€Œô#ëä–dàsóI6éE™‘…Ñ4ä ³¦s æ. yWù±ñ€ñÈðüB7oùð$}µß²í„wÂûÞÌÄ·ý ªívA̶-¯Èãa2Èæ›AZæž/®d„¬ÀJÛ“:_¦ zŸýÙ'X#XcÄ’wªYl‘´½,¡*hˆ¡B¤¡)Dªùö`fÁ/‚œˆ^oÐírW»„S8:0 Ï/&¨HÛª>©Êµhù‹ÿþ‘kwÞ fä?„H ß^çZ†Z {W ŒªŒ10Ûr¨lmåa ^Ä”‚j^"˜‘ÇÁ]”PóçCE„ª@E$Ïï 9Šœ¹.U„ šïW4F¥Ä9¨¨'%t]ªkg8ÒžË8øÁ‡BÇéž2ÀÎñ±€ñØðü|m‹~À«~e¡‰rÝÊÞ;‚ؘèЗ¡­rýV¡™WI¥rX4‰•—–S ’'ðQ $Ó`£ç{5yë hÙús ƒýåz¾(aÑñ“¯+‘¦TI—D¦P&õ°¾ÞÂ}š×úÏä·ŒÇÂóó)^¤mѨç)új?]ü‰‡¯û4ï  ¨ë"QmGjQ š$N‡f&ʱùþK)ŒÓIDAT7vàœ÷š‡I†¼£ÇÓß6äD(—ÍÛù¢xBͨ’È´$c$ ÉùZ(oZrjŒ¨7p“ÎÃÑRø Þжʓ8>¬¹·ß@H~üú‡;†7„Þ܇:ÉÀåõåeåyY,Û,fÓç†uõ(U ©„TŒÕ1 DMTz#`糌GðÂbŠ"m«ú~¼~HZþŸÚq;øR&À¾@(v”>;°5ì—M_ÄÖ¶l0Št€˜†:yû63Å]J!üËx(¼°” Ð±äq~¯åCºð¾ †Øz•õ«A¶n‰‹#]!Ãâ²§zÛñ ‡ëy†ïÌrÞò º%Î_ø±wm‡Ø;66 s2Ø!aØ• p>ïØ áìr‘áSž,2|½8þG¸!÷gH€}„fkïc)û^ºpç½SNaªf©ðÅÕ iqþS:Ðòçä¾ç!ö ÚÒ´^yЀÊ×ÞæNL€W˜ªõ.¬ç]º}Ò«>¬4”ëÇù×Ãû‰òwÿn­J“¢Ò¨Ð ¥ð¯CŒÇBÅÀÅF†"-#úõäj_hɬ=cH€=Bâ°/üÍñ€²uj¸ëø^a4"—[YÞ¥‹~@O)¬ë义}éP`0•°Wž¶­]0û6®¢¼*#‘‹²Øò Ò²^Ÿ,úóËPoß„CÜ S‰‘°|½ÇuP:~ª[ŠxKx…ÑÈ¡,u…Héí§ÜÔAf} MÀvPE¢;RÉ‹ù÷0§Ÿf ]0¡Ð]‚t¢ãðÀý Î5ñúoA]‘h!»¹£G6b¨6£þh-÷ܶ¯ ¹ÖRœÊ£d82q&•Vz“µáÈ#†É1iÍ7üû, M@Ž¢·Nâ(þþÌw @"š X#zà~vò!â¶úç’¶^„–*-n‘÷îz¨~¬N¸ëJkŸ‹ÃÑ&`I‘€ q"¬zaÙCÓs{…w;Tqq v‡iÝÝ@ðbé°,t4BÉg£SOÊÀT<· w7Œ!‹¢ý~Åà°tP,¦ˆ ûó ݸ» póQÔâÞÜÃNo?ds@ ñwÃ0ð.Çw9†¸Ë1$À]Ž!îr p—cH€»CÜåøÿä‡{LUÅxBIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_generic.png000066400000000000000000000270531217176075400252150ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí}yœÕuîwkíî™îY4ƒ4Zц¤Amh´ÌHšÑÌôhG6áÅ~Á6b'Ç&ØÏƉ—lNâ8y/yÎË/Îbcƒ‰±p€%cË6` Ä›Mfë÷ýq—ºU]=»@s~?ÁZnUÝsîw¾sî©jÂô¼uÅx³o`ZÞ\™6€·¸XSÑ !d*º9o$“Ę́ªªª_¾|EæØ±c}…ÂðËžç Ÿ©ëMÊ3Æ&ýoZ€L&S·ÿþôÇüé'ž|ò±—^zi````øùçŸ|èßÿýëW^yåÛ¤Îĵ'¥»i˜¸¸®›ÝÞÑÑþ™ÏüÁO<ùä}ß÷ÙòÙÏþé_›–Ù4Õ÷1mo ¤R©š;vl½í¶Ûnì±Ç- ÞHJËmGŽ|@v*ïiÚΰ¤R©šîžžöÛŽ¹ãÇŽ}·X,–⊠‚€yžÏŠÅ+ЬP(²R©Ä|ßg”RuÜÀà ·eKÛ¡©¼¿ÉèŽL…ÏG˜J¥r[·n[ÝÑÙ±kß¾}Ë–-[ïØ¶-÷3Æ@)¥”Òû"„À4 ˜¦ ¸ÿþo·wgïÀ÷_šŠ{”§ Û¶³]]]ÛŽ¹ýöýèÇÿQ*y‘™´l–çŸïª¯«¯¾æ#˜¢(l&!Žãäš››Wuuww_~ùå;×®]»Þ¶,5Ó)¥‚Ñgùدgƒ‚Ÿÿüù·¶·ï?þÂñïM¶ÏÉèð-iŽãæ.¾¸yU>Ÿï>|øp׊Í­™LÚ•ûƒ€"‚3‚n†aÀ¶ùÄÿ‹Ïÿåß]ûë×\ 2}NÀÄqœÚU«Zšóù|×áÇ»—-_¶1“•îû(¥oˆK³, ¦i X,ú½½½ïzðÁÿ~2ýM@q'×ÒÒÒÜÝÝÓsùå‡{–/_±!N©dŒçùSíãDZ@Áw¾óð÷vìèÜïyÞ‹ímÚ41 #½zÍš–|>ß{øðážææ—¤Sé0xžwVWÝ\wÝoÜü¹Ïýùm&doy0L3Û¼bÅE½½½=ûöíË_²aæªL& ðÁñ<ÿ¬Pz\¤+øùÏŸ?¹uëÖ=Ç?ÿ݉ôó–4Û¶åËW\¼sgoï¾}ûzÖ­[×ZUUU pæîûg†ÄMµ8ŽB€ÿó×ýïy÷» À¸Þ2`Û¶ÕÒÒrQ>ŸÏûìѱž{΀išöE]´x׮݇êYµjUG.—UJ£3g‹HWð7óï¾êª_» ÀɱœwN€išÖòåË÷öîì8xð`oK˪Ž\.W¼5fúhâº|ßgûöïß7î½÷/ŒJrÎ ÍÍÍKzzzº<Ô»zÍêíµ55uÀ›™;;Eº‚G}ôÉ­ííûK¥ÒÓ£sVÀš5kÖýþïòúM›6íÎå²3J¥’šé„€1ôõVé >ò‘~æŽ;nÿFÉ œµ°dÉ’–ûî»ÿK Ì_Z(hÉ~<•ð‘¾ÞÊÆàºNœ8qjÓ¦M‡Ÿyæ™û1BT0žÉ÷ì÷¾÷êk,˜¿tx¸ƒX¶Ó2a†(H  ²8¢ÊFü‹.œÁ›<[Å÷}444Ô~ü曯Ps¦®sÆ N/Ý¿ÿÞáB”QH#5 ¦e¶yœ@–W c ì_‚øû­æÿqå•;÷ïßÿvgϘ´··w/^¼x¾WòP*yÜïû(cÌiš°, –mÁÆ@uÐ/ÿéèp¾‹çù0 üå–[nÌårËÏÄ5Δä.¿üí=¶Í×¼i@áù>ŠÅ …"<¯*+n@ƒ-\¤ÂЀ&Æù(Œ1A€5kÖ,¼þúëß Àõ¤qÊ!ÌœyɱcǾÕ4kVïû8}ºŸOz~°ú¿aðJYË4@ˆ!úl‡!ê´sÕõÄÿãÛÎ7êèºN:Õ¿eË–Ëžxâ‰û#„g 4víÚÕÛ4kV˜¦‰TÊ-‡sÊëî¼R Ã…"Š¥üÀ¥ÜE˜¦Û29y¬Äâ„ñ<ä ¥’‡ÚÚÚì‘#·ß`ÆTö}& `îÁöÈ?(¥pÝlÛF Qžïû(K( (y%øAȈÎ,΀˜‹8ùw—^ziï¦ô¥’©väâ‹/ÞwôèÑÊår®T !A ït¿ú[žC4¸Ò ƒê… à ò¥PJÁÄË‘{ÑÜŒìû|È/¸®ƒ§Ÿ~ú™ÖÖÖƒ§Nú±Ü~6¹÷ÒK/íÉår.¥ÆLÓDU&]>K) aòa„‹ Jž‡B±ˆb±ÄK»(U0Rš  ‰b¥òÎ/xž¥K—.þð‡oüuÎTô9¥`Ûö¢ï<üð]­6¬P¶°CAÿ† <1T6Su4з1!€¦iÂ0MÁ H$BJƒþyL"Œç *8ŽÁÁþ-›7_öøãÿ+p!@[[û†Õ-«›Ê7UU•išåá] ôm¼Cu¼§øB%-¤$ãå ×;ÛùB©ä![]=rûí7B&ÛßT@f÷ž=û]×1$®ð1Æ`ª««8ÜÇŒ–i|›ü[ô™F¦žç£P,¡X,¡äyüº"æ4 n ¶mÇRÐìœNAû~€ýûöu>|ø˜d†pÊ\@:^ÿØ÷¿ÿµË—7ÉY6Òñýý„a‰-ÉÈ¿%ÑSûµcÔ›¸†Éy!^B"‰|«·ÌEÈ~\ÃÙæ"\×Á³Ï>ûìÆ­{_}õÄígª€ôäó-]ÚŒî“c¨®®‚#BCú#ùAæ’¢l¦Šk2Q^*‰21mœó)èRÉâE‹}ä#ÿë„ÌDû™*¨Ý¿ÿ.ùþûX‰‚\. ƒP‡÷$Èñ…Uâ ñ4e"MÆ‚¦gg ZÞãÕW_}åºõë·M´Ÿ)y?}öìÙ+vöîÜ$ol,ƒmÛ¨®ªBßéÓ ”çTÊÛTËmDˆ×â>ÑyôÀ·10JàQ ÏD ZäD Ú0 0™KA30„Q„Î "NáMHA{žªªLæöÛo¿Ñ¶íï{ž÷Êxû˜Èç{{æÌ™]Œ/$aŒ¡ª*ƒT*aæÊ?†@"”mƒö•‚öP8RОç£7Ÿï¸âŠ+Þ9‘ó'm„™—½ím;åßãBjrÙHh(û ò#уÆØÛ¤Ñ@SÚxSк1DBÊ7‰/ðëŸøÄ-¿9gîÜã=R@!Í+š7¶mÙr 0±„wr¹l¹’“Ð`„HšùCJ~!_(q¾P,ˆRe€ðÔ´irT°â!eRN#Á`Ï”pB¸pÞM¿ó; „¸£ŸÊd µwßþÝuuµûE(e¨ÊdP•É„Q6hI³ª"$ÍÂ$4ˆ-Lñ~Ù˜RÐÆY—‚æ‹EW]uÕ;7lذsôãC™ ´,kÁÁC»&Ó‡.µ59‹ExžbŠÔ•‘Bù7 LdLÅó‘ã)T$Rr2Æ8á£>c A?!Í] #ŒBhTÉ„±²E¬è妆:ú¾L&ã~êSŸºÉ²¬ú¾ÿßc9oR°yó–Ö––UK€‰Ï~)Œ1X–…ººZ(‡Ó ³Jž9å„q$„˜h zÂKÖIy)p¥’‡íÛ·o¼òÊ+¯ „Œ©zhÂ@©Ù饻3é4€É-HH¡”"“N#›Íªü~Di@Ô(FsÚ@'m›T Zò…SÐñ*èòtâ³Lpüäù·ÞzÛµ³gÏnË9vuuu+÷îݳ€"fS‘6eŒ¡¶¶…B…B'g´þ"yæô³x.Ãú5Ķ$7´Mw+Ðó ”!`¼nø~B šÀ4˜˜Ìˆ¤ ™p $é¾5·1Þ±,•<ÌŸ?oÞG?úÑ!×2ÆNtü„€buttl_²xI#†"Töl¨Àƒi˜Q_BŒ0öÖg&¥Éh°-‘Ž€Ið¬#DÙL•nh )h#!qQSRú~€w¿û=okoߺk´c'Š3<ØmY¦H`àĉgÌÂÌ€qeÊ(¥H¹.êêjpâÄIn¥b&$‘²Y[aV© ¡&‰hÉ"ŽBDåõD?òxêûðýÄ °DÖ‘ˆ…/Y Â¥„œƒ‰¾T¸ï‘!¸®ã9r䃶m?ìy^ÅNLÈæÎ·²³³sèÉ"FG>¥,|õK@öh7/…2†šš††‡188ÄSµb_Dñ±R ’…$úñZ*wDÈGh4â†Ï¹t©äaÛ¶­®¹æšwBî`Œ•’ÆyB. 'ß“Ÿ7wn5€ÈǘB¨¢TÄÕš8”¡,ί$ õ3`É,¡ø'!\‡â$ȯè’vγ´Üö;7ÝtÍܹsWVãq#€aMÿòõ¯ç¹’)( ø aZü-f>cüåO*÷€ €$£Džƒë:h˜Q_zTÖhFÅ{MžÉrEçêœJ³* !ÊòzIh°M"ƒÜÆà3†Àá£eŠÂ×0¿`˜&øâ$ã¯Öi¼JÞgÙxéÏNJ%sçÌiúØÇ>. aÙ'iÇUB1Vµ¬zû<øwõuuF±TBàûÑ»¸@4åk;eõo’òc°f/¾ô Nõõ©O®G 6ŠCˆÞ‡æz"ÇÄ®•ägGÛ¯/Tî§Â¶‘« 97¨TÍQj|UÐ|¼˜¿{÷î«î»ï¾¿c1…פöîÝ×[_WÇ˾ü@±Æq:C†€,  òXðcuB'TÂ'Ü4̨‡ë8ê#Î:GàP0™ÈüãÇÇX?Õ®›ÄÂ+A>’úw šÂ›â´ïû°mÛ:räÈõŽãÌŽ+t\àºîüC‡mxê1 ðûÜÿS„!dL(_eå|A 2ÕÊ÷[–…ƆµmT_Ÿ0øñmêxM± %¦ÄD¾Û¦+y$Ž’Ä|ñÖT¡PD©T‚ïû±¬£{Œ!åðp­­­ëÞ÷þ÷¿‡Èwð„ŒËt÷ô¼ûž{îùß)×Åðð0s´š;Ñ¥ÁD‹0& ñ4¦.‘‹Ä{u=¹d/¿r'Nž “-@¢;G 9a[žUî^‡SyL’»Hp+Iî,±îq´ûŽÝ'Ñ£À¦ ɨ†òZŽãà•W^9ÙÞÞ¶ë¹çž{Tv?f „TïÙ½gOÊu´ðëê¯#Ÿù P(ÁÝ@%Û§Ü4È„ïch¨¯G&æ® §£A~df&¡H0„S™‚Öï{ô4›T ºX,bΜÙ3>ö±EjÇŒkÿó»|sñ¢…¥R ÃÃà ÄÐf´Žá̑ʒ1,2h$M㎆a`hxÇ_øO:ò­bƒfUl[ $þ_?.†ÑÛ'eçŒ ’ˆe¥ûŽÝS˜‚oY‰ŸSÄ‘DZü={öýÏo}ë›ÏccBBˆÕ“ÏïYxá…O2È@Lú¥ ™"ß§8bd‘O1 å_Ăьúzþ²éXvP¾Âü³tr)×U4ÏèQ† ÛFB ©HA+RIAóü‚JA C‘)hà °,ÛºöÚ_»a9`ìy€ûöíÛmü%Oß÷"ã{Fø[9 ¨ÜFÀ¡ÒWqd` â<€PJ xcŒÇÑj™_(E}}-Ñ?0Àù*ää61s¥R-ÓD:•âåéŽ0 äyÂpa˜Çã¢J±~e»ìšìKACAR :¨‚6ˆ ß°àÂKlÛžOy|L°pÑ¢5kþ‰7J)S¥ò)@%ü1ðx_S>UD ?Œo“Ê—ÇBÂ? •/Ü@ 3/hD¡P„ør§> ~…ñTS®‹l6‹l¶)·¼zª¾®§ûûñꉓ A  SÊS¬Ü§¯>ªãLIÆ¿o}ÛdSЖi€p¯¾z"ð=ÏÆ€„ãúܰsÖÌ™)iê ã$p¥È›cL܃†L®84‚$C‘ÝKcà] ”¡Žã ±q^|ée5àР“Q C*=—E.›E:•*›±çEM.˲ð‹_ü’»æoYô`> 5eD¯+HÜÓúQÛÆŠb["~¢Œˆ‰%k ÕUU¸û®» (}aL`šæü½{÷îøÏ­ÈÐk“èCP±ƒ? Žú%”+ŸEP‚B éX%(¥¨Éå044ŒS}}©eà p]¹l¹lUU™2¥ó•¹xØ–¥²ŒP•É ®®¯ž8 bš‘A•ŠNT²Ü¦ÍâˆQp…´¢¡ÄÚˆm«˜‚–}3¦]‡ðÅ&Ã@&“Á«¯¾Z¼ûî»ÐÏc£Àºõë·^rÉúeP,AƒA ”ÏdŒÏ$s§QcP(ˆ‚ølŽòK$òŽ(`|M2Ý’çÁ $ïr«™Sˆü1„Hrá !B¨ãµë%¡nÐ%–móÅ%ËŸ£'¸ï¾ûŸ8~üø€Q€R}ó'né­Éåc ÅR £ü"Tù{ë Êg %t7 P‚‘(_`DsI(!È¢Œ u\‹.\ jò"J÷y…¯çy*nfŒFUÌ–Á¡!ŠEÔ×ÕÂu]˜¦‰††xá¿Táf¥Á“±2?ͤ–n4ÒÏËcù‚†¡­„ó$™Ì Ú°- ò mú?àK_ú燼À F5€T*µøÒ—vPá1ˆ Ëxå¬0PÍG &Ït”Ðø‚40µƒABT¡È¢<Ÿ‰E^Ÿ¯g¥ø¾ß÷áy>õhÀÍŠˆõwf€Šèâ¶ gžÆ(^?ՇƆ0M¹\Õ}}耋6”Ò´m‰h I^ tDÑû§Éí¤Ë¶T¸mÛ°mŽcGÞ´VnF3¼Ÿ=ýôÀý÷ßÿ0€>yk €BöîÛß¶²¹y†‡ù0©ÙvN™¨¢òb Ò3Pºn 1”PdQsŠ/Èà†!+ne*4_ÓS¾ÆPP0N¬_n•£ËÀË× fªûäF+—°yíÁéþ~ÔÕÖ‚¸ ¡ƒƒá÷䉙ª'œ’Ð ÑPbJV³%fHTì— A®ãÂu¸Ò-Ë„Líë OÐ%à®»ïþA__ߨâ‘ wàà]¶m#(‡EΘ¸kS¾„fH¯¹&R'‹j¦åC¦±ƒÀ29œñDFTérQ†òs´r°xQ6Uý19ãa‚C¤¨%²HWÀ ”‰¢¨íK¥RH§Ó¨««Ã«'NÀ4Í(AÓàyL¾>†r†ë>Rᦠ×qà¸\ÇU_×ÝÊh™\©üR©„»îºë>Ç™ôÁšššš»ºv´@¡0Œ  *·,}ºdûRùTí“(!Ý€ä ¨@…Æ©ÈgKh³l˜fTéòõ,1 f($£` Ä!Ü0(3¹Ë¡œ·H7£8€*ba0¡‡à8 Ã@cà ôõõ¡äyÊ"JNB¦UëÇK!Ÿ1Àešp]Žë"åºpl¦¡-ûj™À±Šœ4?8vì—ÿqôèw êû €âüê;ß¹wÁüµ0\(È'„O— DLùе ” Ð]„´ÈÐâ)øù–eÁuþ9-‹¦cÃ× 3ä>¹ìLˆ)H%b‚R“HäüBS Õ¦PˆôË 4ÀàÐ ²ÕY¾Ý؈ã/¼œt’ÇÑ@ Í”(×dÁul¤S)¤R)¸Ž˲4Ò'ÓÄãQy²|éK_ú^?•äOJ%˜uèСnû—Š%®x@Í|JdvŽ(T V.‚0„.áÃË2á8ÇQ¡—ôçJñ±–‚Š„G„c3ÙH•Â0_Sänxë‚|òÛæéhC¸‚RÉGÉóàØ6êëjñú©SéçJiÛQÕ¾„˜†ÛqI§‘J¹H§RצÏò©Ùï©S}ÁW¿ò•¼?&Ñ–,]º¦­­m- ! ¦a8§ÜkÉhʺ>,L,0Û2á8.×có·—¨¨„‘qy¢¢~€hdQ¨-F…!fð› Œq>@8!5O1›2þŠùGÆøvJ)†‡†aå,„ iæLül0$„:Ì+ʼnÿbi6“N#J#“IGN- MòµºJ"ò¡‡zòg?ûÙQÄàH0Bˆuû§±¡ÁfŒW“9ûÅìPËµŠ¼ ŠbdžÀ4M¤œ\×…ãØ ðƒÅb Aà«>ˆ –?ÃPP^C ‹L k‹ $!ª/“HCL±²hHÃ4ò˜ ¦Ö&5ˆi‚Ò…B™tUUÔ×ÕáÄÉ×`šü™åÊ›aðU·t*…L&t: ×ua‰PUç/gZôÐøËw~ù(€gce?@Uf–eÍ9pð@7þ]ß7OU‚FrŠp »n$ÚádÆáµ Ÿg솔 ¾^ˆµ@²:Ø‘¶8Vµ¥-0y¦J¬„g/MéC¾A¹±qÅ넎‰Ž|σoÛ°, ³f^€ÓýýðbJšj‘}?ÿüñÁoÜ{Ž+3€Ö·­_·n9Àá_æÖ¹K— ùy‘ª•–m™&œ”‹T*¥–XýÀÇÐÐ0(•¿@„!…>šw+™™xh³ªÖÚ$Öåæ‘vù ”ñÆbò²k ŒŠŒ$¡Âµ™ Œ‡Âò»ƒsgÏF¡X@U&õã/ð!°ÆZµH#Êc '¦H¤Üû{å•WTê7.Vì¤ìíwüÞþL:Í}ß°ø±*Æ¢iX±0-¾Úæ¦\8¶ùöì ð“r*†J ý9eáC’…«5‚°-@¹¦YH¸i–u F¨ŠDD†XqDùñrg©äÁuÔÔä.¥U•r žU"¢\« bc¸œ­q%9îLƒ)@Ù‡ïû¸óËw> à%=ö×%b©Tjñž={¶ÀÐÐ0<߇ate…ø,Ž›ðn+æ>88©\UÆ/ÕΤDt ¶kL_ù}kǵ/W˜ôía‘)%/ Œ„G%!_ƒ¦x(QŠ1DN‡’ D=ÏÌùž™Ü’!r¤°Ef¨q‘/ÃÈè@N(¾oòoYËóü'§|ðÿ0PéXK;‰8p «yÅŠF€*UWºëpŸnYœ½ûÁAõ@r_âœZ÷×Â=y2(‹3ü$‰:qоâ|Aš™29ö’Ä ƒŠÅUÔJyhìº.ÿZ¹i“)Bù‘–ÈröÈoM©¬ª2†ÊoM$òØ;ï¼ó‘b±x @±Ò±:Ô^vøðNË2áy†‡ êW,ÇåF"„ןyC¡Ò¥O‡œhrP å̌뷬Íbm>˜þÃe„&aå>^ŠÎ’ØCe¾PR*©²ŽÉ|ßçˬ®ÈçûE½B|Éšó§¸`á>á2¸°IñÉEúpÏ=÷||å¯bØa‰‡% .¼píöíÛ7ÀðpA$hlK…‚/ï&œíä_SEüo9¨üË6V/{S ª_1s•‹ˆPHE¾À—ÕŠR¢á-¤T. ‚ñålYÀIí8(‹0$þȪ&-RÑKÜdt¡ö™/Uy%4.rÛ#<úß?üá±G1ÂìWÀíêêÚ3oΜêþ ƒþr!$Ë–±µôË¢øD®ôÄá[›MÊ$*͹¤ÿ†àºˆ°gÙHæ ú ÜAç â0u‘6 ‘„¼Æo,˨ÀŸ•#d䪦 Æľ_в2ÿ’ÄâÈpç_~„RúÌH³_€ã8s.¿üòîS}}èë;-Ö•¹ê¸Ñ³²“ÂÙ²$~"œ£$Ò ?šÁ0m¶%€ƒhÇØ¡0áìOÊ%äå|Bº0QkikWŽû1$ ¸Žƒ¡¡a5&²üm´*è0²J@ E‰rr òYÿ/¾ô’÷Ýw? àõ‘”¯ `îܹKjjë‹%¤S)x¾¯04Š¢æ/:±(|©¬ðQóž!ÒV*Pÿ!±v’„»£àç ¶!Â)Åtö£ÞTCÊE%á½ÄSÐÜ50¨:Ë2áû¾H‘Ç‘€£QX÷@C¾0JĸìëŸL æIDAT GQ$µ÷ýë}?}áøñ!!õó–[n1N÷÷_ÿ—{^xê©§|ôRuuu5ÙlV-ÿªGHb]e“.üh{üB´ó£mDÚÀ)ÖŽÝWø""n#’®ð(*† “ë÷²jÑ;&¡é(KÂ}ºÃ óGA )_‡"í>ˆÈ¾Å­·Þúå'žx⫌±>Œ"DX‘ À„e+V¬ØÒÝÓ³©wç®eË—-›‘ÍfùÛÀò§YBz*P<à¨mynB[ R8=Uz˜ŒÜ–°m‡ƒ<ÆÙ–CÍêEÉ¿¦Ìò¯›a ++?ºO*X3å*Bå+c D-k¶ÍKžúéO6¶¶^Õ××÷5ÆXbö¯Ì±"€ €Y溮»lóæ-ë;wìØÐÕÕµtÁ‚UŽãˆrêË[–íP‰D=HR[Bhâ!„ÉÈÅÿÂv8½Fm+%ðÑR÷[ÁHBÝêʈ·¥"D[Äô¶XÝìP„0®|5)”½_”!A8†QåBàŠ—\>ý™?øÎ‡~ûƒ×ø úrâË¡„’  @€ ·oݶ=ŸÏ_Òºqã¼9³g„îó$_‰@-árò“ÜŽ?ðh¶•EThÇ1a–ëÛ¥ßU³3l‹•7Íð¼‰R©„ÁÁ!•'‘E²¡„c@ DyŒiòºŠááatwwß~ôèÑ?dŒMù  ì B,pc˜ `é‚ /\ÓÕÕµiçÎ]+Wµ´Ì®¯«¥øˆÁˆ®@>¦¾=Üž”hjøGió"Ok‡Œ:ÞV†‘Ø]"†¡]Wô(KÈúà{ž f:âèF—¤`ýúÉÆ "þûA¦iâ;Gžèضí=A|‹16<ªb1FPbH¨0Ë4Íe«W¯^Û¹£ksOOOó²eËjªªªàyä÷ï¢.B6IecHh‡® BBéb`“Ö!Be%ñ½­+`ävÔ]pWÀßJrNŸ>-W3¾ð”JM À é ÿ\ï‡>ôáû>ýéOý€'G‹ÿU/)?.Â'‹]×]·uÛ¶µÝÝ=k·ut,š?wnʲmŽ ¾0ö_Æ*µ#Æ ¹‚ñòÕÖø‚jkJO‘È`Ù¼¨uppH|îVs1#SBÛ³ŠdåŒÁ¶¸®ƒ“'_C[{ÛÿzêÉ'??Vø&heð)¨Ð`Accc˶íÛ·ïܵ{Õ† fÏš9 ¿)˜Èôv%ÃÐapjøB¨ÃòÙŸè.Fä R£€›JÁ §úú! ¯!ûÒ(Kt__ÐlEC  ÎÀ4 |å+_ýù¡Cß àhRåOEÝM‘¨&8y¬°ÀE‹/^µ£«ëÁjr9þ£cá c )upI9/À¨!¥Î&âäi†AN§Q,Ñß?bTR¾>µ“Q"ÉE0¦a¢ªŠíå]ïz×?þíßþí Œ±_ŽKwSlºXª ø‚eYË6lh]¿£»kóŽ;–-^¼¤:JRªÞËù‚>Ë5x.oO2¤×dŒ·tèl$Œ1Uñ,ß'0´tñËëÆíKßÞC¨|0ÆKÉ]Ï?^Ú´qã^|ñÅ/0ÆFÍþEtw @í7† €Fe³Ù•í[·®ííí]³¥­}ÉÜ9s,Ã0"!eHîq•ÃKM=Z;Ù-èí‘Ãȱp‡0¤,wñ38§NŠÕ(ÊWc+nV!AxŸÙêj†¿ü«¿úñ5W_}€ÿˆ×ýª»7À"‡"$ŽXØÔÔ´r{Gdž½{÷­Y³fí¼†Æ€QíÄa¢%4m` o=ŒK{äY޲YZ© Æ+¢3™ ú0<4,\A8^ò=ŠˆaŒHùz…mÙ¨®®‚ïû8tè²Ï~íkwßÁ{q¬ŠP׃ @€ n 3‰a\¼ì¢e›º{zÖåóùåÍ_\Ÿ«®æn¢ARN&-Õ#ÂÈ7"ÍT[–…×^=–!Ô”_æv*E±'“©‚ë:xü'?9ÕÖÖöžÓ}}÷0ÆF\ûO’7Ó"] tsÇY¶ió–ÖÎÎÎÍ;ºº–,\¸0í8NBHMA+X­4Ë’¼‘)h©àêª*‹Eô>-ªvtcŒ*_­)?b AmM !¸ã÷~ïÜtÓuà±ÿ¸•y¶€.¸›¸ÀòšššUÛ;:ÖïÞ½gUkkëÂYMM/M;wRÐ`|±(“Éàõ×O¡ä•ø{šòu7Pî"”WÀ3ÕÕÕDçŽÎ[¿÷è£Ì;9‘Á> @Š\˜ª0À‚…‹­îìܱ©'ß³jÍê5³ëgÌ ñ]<:²+(ã ããñ²R;) ` ™LÁk¯¿¦úŽ(?  öI”Éå²pÿöo¼ØÕÝu5£ôþ±¦~ãr6€.20Ç0͵---뻺º×wuw/[¾lY¶ªª¾ï©Ï¿Ž˜‚#w˜Ê4ÿ²Iu6‹ i_9…†¡¿/CÆ`Z&êëêï{ÿû¿ñgú§7xj¬©ß¸œ+ ‹ n3Ìq]wù–¶¶ù|ïúíËçÏ›çX¶ÀóÔ6Ï–´Ì ¤R)œbíhHÉÛ¸2S.Ï œ|í$B(G‘°"˜!—Í¢ªª Ï>÷\qÆ ïíäÉÿ 0m•E’ÇY.ÊfsË7oÙ|Éλֶµ·/;w®e¾))h Èf«144„ÁA†î—†#PðˆÆÆ˜¦‰?ùìg¿ÿ[¿ù›¿àtÚÆ&²Äm€Å³fÍjÛÞÑÙº{Ïîë×­ŸßÐØÆhÈ*¥ ÛãOAóÜOŸ|í5ž!4ˆÊPFˆQ¤RiÔ×סX*a×®]þoßþö¿€iŸpT¸À,BÈ’ÍÍ«»»»7öä{W,_¾¼±&—.â̦ cHgÒ`”áTß)ÿv¡n@ÆPWW‡L&Çûþk[¶l~_©Tº¢îÚ&&á*e-€&ÇqV´¶nÜÒ“Ï·vvv.¹páÂŒë¸ð}oJRÐúvm¢£ºº§OŸF©ä‰ ¡êƒiò¯’Bðñ›oþæ­¿û»×xJ\|Ú¦HLY³,¨©©iîèèÜÔïY»eó–…MMM†i‘·¦tW0–tXKª)™1ØŽ Dzñš\2Fˆ”1d««PWW‡¾¾Óèèìøø±üàÏ }ñkÚ¦V8_È‚çΛ7¿¥«»k{>ß»nÍÚµ³êëëùg`ÆS T&˜"M\,#¿“,_Y» ±©T ÷~ó›ÏïÙµëÆØ·¡}îuÚΜðdS5€†a¬lY½º¥«««5Ÿï]¹ô¢‹êªªªà{> &‘‚æc˜Î¤Ñ'ja€2ØŽƒ¦Y³@píu×}ù/>÷¹›ü jihÚÞ(ÑKÜšR©Tó–¶¶öžžü%Û¶o_¼`Á‚”eY®‚cüs; èïï‡A PFQW[ƒÚÚZüâ—/zíímïÿïçžû"€ÓúMÀ/øzÄ\ š·wt®ß¹kçÚ ZΜ9“`”%ë(w‘B:•ÆàÐ<¯B ÌnšÇqð÷_üâ]ù+¿ò.?IýNÀ›'aUS€Å.\¸¶»»{û®]»W®\¹²¡¶¶vÌ)hÆøO»X–…ÓýýH¥\Ìnj‚8|øðç¿ú•¯Ü àåøMLÀÙ#²$~±eY+Ö®]·®»§û’®îžK–,É¥ š1À±m”<Ùê*ÔÔÔ࿞xbxÓÆïéïï¿ ßû›6€³Oä*e€9¹\ne[{û†|¾wã–¶-KçÍ熡¢=¤”â:êgÔÃ4 |ò“ŸüÞ7Þø^?‚ø<]¦ àìRJò¸¼©©i]GGgëÎÝ»W­_¿~~ÃŒ`±*hþ¦qÓ¬™ð|ù|þOzðÁÛ‘ÿÀ´œ+BÀQ!™‚^±â’Î;¶æ{w67¯XQSSS£RÐA@ÑÐЀc?<öjǶm×xžw/*|îuR:dŒMúß´Œ[ ðõˆy¶Ù¶}õ–¶¶¿úøÍŸxìÁ‡þ}èùã/°—_y•  ³}øÃ_°p¤Î&¥»ixÓÅ"–訩©¹nï¾}_øÜ_|þéÿ|äѪU«~¼0¶¢LFwÓ.àìRfÀW*W6444½vòäQÊØ¡¥~ã2ÍÎ?1À‰£`Xü«¨¨7ݦåÜcôC¦å|–ix‹Ëÿ (&þ—ˆgIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_get.png000066400000000000000000000245171217176075400243620ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœí½ÙsdY~ß÷9çÜ%d"P¨µuW5{†´¤±ƒ ™Ë°É M),izì‹R8ô EHÞh’CF8üà?A~b8¶iš½8Â!ŽFŠ‘43dkzzR³tuwíUè*€Â’H$r¹÷žóóù73ªªB­øFd‰LÜåœßù-ßßïü®ŽðúB?ï 8ÂóEðY_PJ©gq!G8Èg¨x5úy>Ù;_Gx¹QL°ÃËÃ6h€b¥‹ˆËßGùçš#Ax1:ñ©ˆ8å¶%"ƒÉ¿té­3ÿñ/þâ?‚ ŒH$ÛàÈY|yà×rþ›C©4 ƒä½÷ÞûÓúÓ÷W,trAÐ"Âßø›ó‹­Ö¦áÕÄ?þ'ÿõÿ D@H¾øGM€ùå_ù¢I’Ä%Iª­µÏXjpXPJQ*Åô{= ”>)¥T0âøigmàD ­0øy„—J)œœsÞ¬'ø9—ma  ˆ8zÝ.a¡µÆ9÷<®ùOJ)”R¤iеy(²%‚â?lom±°°Àúú:Zkލ€—Zk@X__guu•ÌfàçqO奯Cš¦ÌÏÏsãÆ Ò4Åóì®þOc Ýn—›7o±²²‚֣ͮ±ü¨ ……"Š"*• Î9VWWY[[ãÍ7ß䨱c…*yV÷r„@)…Öš¥¥%îÞ½KELLLÇ1Aš¼˜<þ¼¥•(¥ÀR©DµZerrá'?ù 7oÞ8Ò/ Œ1Xk¹zõ 7oÞ$Žc•J…0 1Æ ´räŒ`ñçr†áÀök­i67¸yó&«««¼ýöÛŒ‘eÙ³º¿#ìÂd¯­­qíÚ5²,crr’Z­F¹\&Š"‚ Èí6#ðp ¢hmR£µ"‚ $ŽcVVVøáÀ¥Ko1;{‡sîÈQ|ÆŒ1ˆ7nÜàîÝ»”ËeffŽ36V¥T*EƘúÿ,`€Â–ø”ÒƒAÀúú:~ø!ëëë¼ù曄aÈqôlaŒ¡ÓépõêUZ­ &&&§R©P*•sU„‚{­ÏÝ/"‚ÖaèÂkMÄqĽ…{´Z-.]ºD£ÑÀ9wä 2”Rhc¸ÿ>7n\GkÃÌÌñÊã˜0 áûgiæGÖ’£”PkM„AHŬ¯¯ó£ÿˆóç/0wú4Zë682 OÅ¢òŽ^Æ•+WXZZ¢^¯Óh4£\.†!Aˆ»ùÌ‚Nd¡R´V£ C4›\¿vÖF“7Þ¸H¹\: Ÿ2‚ `ccƒ+W>a«½ÅôÌ µZjÕÛû¡Ïv0ân_C!0ÆäšAçf! "â8buuvûG¼ñ†ç DŽL“B)?¡óóóܼy“0 ™=q‚z½N¥RÄøÃy9˜ÖÝ·ø‹Q½†Î¡ÉM—/ÈÜÜNÏ&0'"ìé‰a;ò±2F“ôS®_¿ÆÒÒFƒF£AµZ¥R©ä!žAk“S¿Ç®°Ÿ5;êãÄ(Šˆâˆf³Éü§whm¶¸pþ>Žþ GæU:ŸÌ••nß¾sŽ™ééáª/•£³Kx÷8ct` ð4PdŸTÎNùW® L@Ŭ­­qõÊNŸžcff† 0¼ê2 •"Ë2îÝ»Çýû÷)•JLOO竾Dç^þ>¹ü'ÅÃp ð¤D¹:Ó˜À›„f³É;·ÙÜÜdnnŽR¹ôô/à€¯ÆS´·Úܹs‡V«ÅøxñqÏå?Û?#Òì©:{BB P* \V9y4$66šlmµ9{ö,ÆÄ«Eææmmu•[·n055E½^£\® ¸üa þàŽÞãâPœÀÝ¡@1îÒ€3ðYÅR¹ÌÚÚ*ׯ_gvö'Nœx%L‚RŠ,͸·på¥%Ê• Õê˜Wùyl¯¤áŸ%öp9ÔW€ÊÓÊ£¼VšVkƒ{÷î²¹¹É¹sg)W*~¼L„A~­Zi¶¶¶¸}ûí­6ñÆ ƒçÓ·—¯ÿsãþ¨cîá ‡¹´(O/LÂA4y±‰O*}üñÇÌ9ÃôÔ¢žïN%ÅFD)Šå˜Ÿ¿Öšééïå—ËÄ…Ê/ˆmåZ‡q‚“Ýü<›!.nW£´`”&Ž}„`Œg£(b½ÙäÖÍ›´77™›;CùN¥g/û]Ú²,ãÓùyV¬P«ÒhLP©”·ijmž­Ÿ³ÇŰ_ø•%ÖpXp⣄v©Äêê ›››\¸ðõz k­O1óì¬‚ìø¹JA`Z››Üºu‹~¯ËıIêµÂÑ‹±½R~׎àW¾Ë³¤‡u/â~7øÃWh<ÀAP8>J+ }­4h³Ùäòå9uú§OÍa4Ø,ãY‰ÁîÀÿEƒVŠOïÝãî§ŸÇ1SÓÓT«5*•ò¶¢ÜÓÛq„áÏøao?`Ï(àyX[…%øŠ#c0yuk—ØÜl±poÖF‹7ß|“J¹B?M'Å ƒAqF•R„QH?Ïàm´6hŒ7¨S.ç*?ŒåõÃØ#ã[\ºbûߟòµ#»;{òÏ7þ¿ƒŽcŒ6„& ¢0bum•ÿøßsöìNž<‰µIšóP¯ p††0ŒX^Yææ ¿cªÈÛ—J%â(Wù%qvL„lÿõP®]„½ðÛ7†ì¼¢ç…IИ¼&N6Þ$a@«µÁÍ›7X[_åâ›)—Ëô{=_š~0Ÿ}_¨h¥ˆK%œÍ¸zõ ‹KKŒS«Õ©V+¹£»ÂËß÷ñŸêU±WήTðsW9 Tî ¢P±÷  H¤••>Xù€ ÞàÔ©Sd6#MÒûø´dAâ8fuu•kŸ\!ÉR&c-ú]ž—LŠ pn÷´ûsá ïúý ¾yhí·ØÁüƒ|ŸÛ·§ùüç?O£1µ–$IŠ#<æ™ýÌy’Ê7Zøè£Ë,Ü»G½VçØÔõñqªyuî`æCIœÏËCöa_'ðQ\S!˜ÀGA@ú$Óí;>µú…/|ãdzÕéÐítqâ†Ú`Ÿ'+‚´r¥LmlŒ…û |ë›ßâÁÊNÏÍQ©V‰¢È§¸£È;®#©ÛoüöáŒ|ûºÉ¥Wç°YFš¦¤IBÒïÓëvɲ”sçÎ333M§ÓáÃ?dþÎæÁê gÏŸgbòÎi’àœÃYë_Z£B´ïª§ݪ²û¤¾ð&  ¥¬µd¹Zïu»lu¶hm´Ã/|á¯Ñh4ØÜÜ$Ë2*• VWXy•K/röìYJ¥˜­­išêðvž¼oQ©TˆK1K‹‹|òÉ'tº]¦¦§91;Kýso³ÙÚd~Þ§t ÎÂ:K,E¼ÃXñÅ=x ÔˆˆDN›YÒ,¥ßïÓëöØØØ ÍRNÏÍqöÌÜ A¯ŸEqÞÃóü1KKK¼õÖ[LLLÐíõèõzíf6ÆG1Õj…N§Ãþý¸ÿ>•J™³³”Ê2k±Örêô)Nž<Éù;,,Ü'MSjµ¶ìö4Ï}CŒˆà8ˆøœÃ¿êý¶²,ËH’„~¿ÏÖÖ›››TªUÞ¾ð6“ :Ý.[¤I6 ]ŠÒ³8Ž(W*´6š|ï{ßcnnŽóçÏ3±c's±Š“$áúõëܺu 'ÂÔÔ1_•›‡v&IK³Ùb¬6Æ›—.qlj:ïųÊX-allŒRœ¿ä•=ì½E{‡&+qŸlž·Öl}§Ûa³Õ&ËRNÏæì™³ˆÍ ú½A0É·³ç™Å0 Š"â8¦R.Ón·YZZbuu•™™ÆãÛekk‹Å¥%zÝ.ccc~Çm^•†!&°ŠÄ ÍM¢nBe¬ÎÏþ…ù;óܽw—­nŸz­F)ߪŒ4ÚðB02ÃE”˜×Ã* 2‡EÀx À÷(ÄIÂõé÷“|Õ·¨×ë\¸ð9jµN‡N§›w&É)dò8Z ÏÍmò(ÁTÇÆèt:,/?àþââ`—’ßèª(•ʌώSŠc¢8&Šb ÀÒšÌz?Rû“ÒéõéöSÊ• sgÏј<ÆÍ[·y°Ö¤ZMóR/—kƒV¥”o¼cP  úJŽ Ø+¹·K:XröÙI@áè9çr•ŸÒíuhonb­ãܹóœ:uçÍæiê]*½›Gï‰"1*ïl¢ L@†ÄYD¹T&­%dY†sþ>•Ö…鈢ÁïAàC;B*Á:òÕ ¢ sBÚÞ¢ÛëS­Vyûíϳ°¸À½»÷èå¾AÉZ¢0ôÚ@Pn DE.介ÞcJŸ«8hIëë¼ÊOú [oëëõ:çÏ£Z­Òétèözù^8½ç ©ó­åGSçÅ&ÖEØ8ÛF»™ä;sLž|ÒJ£´ÊWlž°V¾¦Á‰ó¬Sy¨^’ÑO[ÄqÌñÙ“ÔÆ'¹sç+kÍánÞØ‡—AnŠÂAaDЇÄƒôùNl€‘|ÅáJ€äfƯzk}lßíöh·7±ÖröÌ™<ÑcÙØØ Ëì Ìj¿ðÔªò[ìZ Î ¹…áwG·½çç(èä|`¬©€ÿ}›WÚ_'¤.Ý$¥Z©ðÆÅK,//soaN/¡VÒÅa€Q ¥M^ò&8 "æ){Oèsá¶ÅöYF’&t;]67ÛÔjcœ={–J¥B·Û¥×ïƒÈ€ú=†ƒ©PˆDP#Ýóê´mš· qvzäN s`Å'B6’e)ZñÚÔ’´ÚÄqıéªõqæ?gm£E¥œQ©VmD¾,.'iô!$±üuÉžrŸ áÅ8q8ëHÒ„~¯O{«³–¹¹Óœ8qk-­V k­WÁOäí d|~iÛGþבÁߣFÏÊð¥²üU|mÉä’“õº‰¥\.qîÂEVVWX¸ŸNj«V‰âˆ04šXvàœ zªã/’A»àÙPÁ¹ôñ}šz•ßétØÚj366Æ™3g«>Iï=aóƒÝñ(jn·†s"$"QÀ:å ðeÀ{†…úP€u¤íA1>1E¹Zãî½{¬m´(—Ë”ÊeB€VÆ ¢F Ož¦1Ø]ÕÈÈo£*¿ u¬µÌÍÍq|f†Ì96ÛíÁªŸg—‰"s~Õ¢È&ÀÇr†7­G ¤IB/µ”J1sçγ¶¶ÆÒÒ2Ý4£\*#!¬ÃG 9žŽŒú*Ûqx&@ŠØÞÇæ…Êïõz´ÛmªÕ*gææ(—Ët»½<´+bì=V µàDáÈM€+VþðgaX^j#BÒ鵯1âjû÷Yoµ‘8$+Ť‰wZ‹º‡Qö¸ê§ýA²çwpFØCÛ§diJ»½Eš¥œ˜evvçívçä™ïˆyXI>é.·ÿi¡Yw#ÏÔð¥$¥ÈRKßvˆ¢˜“gΰº¼ÊæÒ"ý$¥SÎPÄAˆ1Aîü*ï·<îUÞûåWFU¾ÁYKšeôz=ºqsîÂ9ª•*½^4o6½;¡ób`tU§ÎÓÀ™ƒÌ)R ‰Nü6 0/F±ÐÏ<˜:Eß @‘ÜÎæ×ÀJ+²zz(~õ J.7'J£>$ÂüÛ4'OÎ2>^cþÓ»lll Zƽ‚‹¼ân¶H6='PÈ=K¿ß§ßïS¯×™=Nôûý<ÏþòN>ä,îÀ{ö‰ŸÂæ'NHEH¬Ð³ž¿ç³…E‚©Hð¨Âsϵ€*Ìwþ2€µÞ”h£pųóŒ·_hŽn·G©Tæ­KY\\âÁƒ²4ËMäòÚµâÙ;¡ût÷ÊFÉ6•Ÿ¥)½^Nž<ÁÄÄĀ⅗{âBQ"~â{™¯Hsaèg¾HDrrˆȰêÇïíWü0ð+ÝYïWè¼Nu´Üat,“$ÁÃÉ“'©ÕjÜ»wv»M¥RÙ‘4t2¶‰Ã¾M@ÏÓwƒDN¡ò{½ÕJ…'f‰ã˜~?y%lýNäÜ’S¿ýÜ ,òþ}aë†c¦$ÞRaÿs! •’¡hm‹Ö¹{:çè÷}õÑ¥KY\\äÁÊ*išR*—‚üq1ƒÅ¬Ó=Òö~¨ò{Xë8>3ÃÔÔ1¬uôz¯àª/šËIžÔ‰ L<+Ø·` 0ê:AiAå“ïzÕÎH8­Àeþ8Úxg“Gä9…\œ:uб± ´7۔˾©tÑ_¡øþÁŠB‘Á?9ëH³”^·G¹\bnn–r¹Lš¦¯ÅãâŠa³BnóŇ™·Û½lTòç!ˆ€V(“ŸH>¡’ûÅ>NµZaaa‘VkdZw¯°Ø&’W„ûmX=êõ:ÓÓSh­_«U_ °›E-`b=ë|F0wÜúÙPŠ0°Øéá½zïùT¿¨<”Æ™úÖd¾ÊxPTtÐëÑgΜ¡Ù\çÁÊ i’RR )ŠG½BüE”o×Oœ81x>pš¦O>š/däes¿`þ[„7 ™õ¹‚¬à? Èül*øs@>öN`–‡‰-Âí'C¡ ŠL-,ܧŸôq£Éi`‡°Îa´áôÉ“¨|¯Ük ñ‰šÂ<€/õ¾@b…,Õó'èB !uîHN‰ •`sN!°#~ÄúÖ…6Œáܹ³¬®®aí6ó­`ÇãsƒŒS·×{²+xE x/=³äžj½FHß¼ ¡ pC  ?ù:Ÿxòá…Àä«¿ˆ,\á‡=VéÇÃȬE€Éc“Ûj ""JùB鼩‘VZQ*•^ùïQÀXG¦…ÐYLfÉ𱿰ä¢yšXœ7 …ÝPø2o\Nì âûœP¢°¢IÊ3ŒøÆÙ¥F«'«†ÏïBdØNÇ-ùÙ¤À¨pZ«Þ÷~ðÃõñÚXœ¤©vÎ)grÅ@¥šWE'²=¶n Š¢k ­L«Í,PÖjz«oT·Ÿª~âèôR¶z–4×™-=ß’F•90~«Jùß”Z¡“¤—ÒIÒ,åƒïÿ »]EŒ1»ßÀ#ßj¥PZ‹öû#]—\·Ûm}Š™•S¸ Â0¬› 8c³lJà"ã"”@Œø ¬Åÿ¾€ªadGÆ_ØþVùU N÷öÏM T\ LãT9˜¹0Vž9ß0õK¿Ñ-Íœúâ¹ÐÎM¾7ßc±iI3Od¹§ò<]-¡B3­PÆxn h!Iš.$[ôûÎ'ÿÛoÿ¯níêª$‡M²Ú¶}W)å‹R=-­Õgí½4³Ë@WD2È5@n\š¦í4M¯÷ Pο3H¾€“BbE*LÀ0 ÷FJ » ¿óϘHëúl¨_ª«ãoMš™¹YJ㿈2Z5a€2¥-ÊX|ѯóG*X7 LO¸É@­QF+L(Ú„ÚDeŸxû/RÒ»IkÙº´ç¶±7Û¦XvùÛÈG —Wƒ¦8ÛÃʶە€ Ú£ L€ˆØÜp@ lâƒ?À/âÄkƒiÌ*3qZëÉs®T¥¨¸¤T`rÝWVFˆB”Ê·c);%>hǺ4åÂÒdXªVÆ’ ŒX Œh=\Õ¸<ñ£ ý˜{ÛZ穽üC­†ïsÀÐZ”RÚ„Qpá¯ÿíVÒüùõõµ¬Óí¹$uÃ:ƒ˜ŽLþH©×  PhA¬àœ•¬—ˆM\’ºþf–^ùc°ƒ— AÆö á&_Å ?¯¢KïÁ©¿©ÚÉPEc±Š¢² U ¥•–¼¿°‘Ež—0‹ä¤ 7Bý)%‰ŠH¨VF—½Ÿ.AVðþû»Ú=þš_—R8¥ŽO½ñ3õ$½84ûVo%®Ó³>Ì”ÝîA†ÍŸF 5‚1à´’DœÛ²Ö‰RqÂøõïÔÆÿÒCN`~üÁ Ù·ýyÑBé ÿ%ÕßüŸ4á˜R**IFC “ uDJ Œ2¢”÷^ìu#Ú¾èž90ù@{7-*K9tÔŒ¨ºRvT#>}(eJµÊII%Ô.vÆd¢c‹)¶³ò ø÷2hŸtŽ‘²JZÒ@¤g­¬%©[ë§Î¥V2›§|azí&¢þ÷þˆøgÿ€’, Ȥª3Ž)'§&ÅP!#‡R‘‚P†S–0€WÇRX=Øæ zílLH)MÅnQ“èðn-³bÖ­:G)ªd©Ñ¢­˜²õ•©Fv] B!À¡8*XêZ\]KŠÝì÷¬éô2ÛîJ·ŸÑ1¶¸Ñ—Nê¿õ¿áï"ݦÊ.£Q`¨˜PZpŠi‡DÎúøçk¯d੹¢ìjð‹¯¬ó\½R¡"ÐhíПʥּ›vç!zKaväV#ö"Yø…¹r4] ÿ³ÚÁ÷“Ì$x6q›ºyhõû?ªH%»TTî8Å®!®—™_ xo¾K»ò/¯utÚDj„€ãaÁ-ì¿“ÁÇ…?`» ý.ZÈ?ý¹ºÐyçùÚü›ò·sÿè½ÁU½ ¢ ø‡¨JŒ$á9…Ó¢ØrŠÕ”g IDAT5Êêô/ÁÚuÈîAöWÔÞQ¨oêÝÐ[–ÜnúÞoþÑmâd¤€C嬼fâ¸"h(¬¥|·ÝÅmúïE¾¡Ð6Ÿ@pñ$xLÃ_­R ʨ!‰´[Áî.2œ Y’þå þé¯OðsÆY\OÐJ%þÀ|9À&bSFïXi$ïÙÐIQ|ýRcí·ÆþÎôÜ•[‹W5º¡Fz¹ôÜ€ƒå¶çdtM,÷%w™“Ç‚x: ‹B90¡É9‚œ9øV'£Ÿê±ˆ±ÏâÇóø¿z“{k½+øÿVÿøÁU¿ˆ8¶A…1ô‡èÆ$Je¨€Á‹¢4ÎoÖÙJ…kwj“ÿ}º¸|ÿ¯ÿ\È/ÿfÀ›ŸÓh·¿Åø(h•³bîb@Ô‹n‹é‡jÿ/ç PðN(þôË\_ì|(ÂÑþê¯=xè¾ã^ž&TT"þ¹_ÏWÿ®|F¶ç„N/s?üq8ñßþù÷îßÞrÇB0úõx<½P!¼SJ˜ÿÎu~z·s¹éw;ÿì×®Wÿî7’Ý^A’îg~ _§¹%°|¯;3õß­ßz°x³eiõ“¡"ÐO·ûÖ‹+Gð7ª ·¾ñïýtírê/m}ÕOþÖ?ûµ‡nÿÅ€ýCð”Iè*ø;~ì·ËË+÷;™°Ù˘Œ^]!°¥þ“RŸË_ûï\^»ÇæÝÎÿóÎõêoí>ùðj Y^ˆ|?=~ìwãåÕ¥N&´º“!ê Á3bÈ‹ÉÿrŸ¿üÚe¾ûIó£(Ôïnýɯ^«þÖ·ÔÖWwŸ|xõ†BÐF©MD¾—ÎL… g™Œ !8D1PŒ¤Û'ÿ#~x}ãr)6_jÿß¿z­ú÷¿­¶¾úÎ#¯àUÈ}¼?о›?öñòêò¨„z÷Í/ j¿˜ük—K‘y·ýÇ_¼°õ'¿ú™w÷ª ìá»éñc_‰ 5ÁT¤ˆ´Úó¡Š/2²ÑÉÿç+_¹ýýʵƒçU1kï§3Ç~/~°¶ÜÉ„f×r¼¬(ÅË´á)sP/ÁoVúüÅ×?á‡×7>*ÇæÝöýÊÕƒëUq „ÒéɯB°ÚÉ8YQ”C5ÜÞý#/ÃoD=¾÷µùË—K±ywóÿüå­ü¯ƒÀд ÷Ó™É߬-o¦Âò–åtUS UÞäÅD&Ð(ïG=¾õÏ?æ/o¶.Ç‘ywóÿø¥«cÿà½ÇŠ9^€ÑèÀk‚ï¦3“_)=X[Úì;Z§«š±T2F ÞÑ]¾ýÏ?æãO·>*—‚/×ÚôËuÕ¯“@ÞïÔ&°ŽÈ¿Ëf&·´º¶ÜN…{›gj†Zôb AæüÊÿUÝáϾö1ŸÜÛº\Šõ—9°Í߉×MÈÓBž,ò<Áôä”VÖ–Ú‰ðéFʹ\² FLóÉÿ¢îðg_¿Â'÷»—K‘ù2ÈcÙüx hÚ‚j"¼ŸNOü~yem¹•8n7S.Ôê‘ÞöH˜ƒâI‹eS“Åu‡?ÿú®Üï~TŠÌ»ÀUR”ü¼®Û„€õ\~¯¼²¾¼ÑwÜ\Oy³aŸ9HÌŽüšÙâÏþåU®,ö.—"ý%D®ElOã<¯³ÀHt †ïgÓ¿[Yk.mô7VS.6ê±Â>Cž qp¢føÙäëz•k‹ÝË¥H¿‹<µ?Š×]`[ˆ¨Z"|NM|¥²¶¾Ôì;®¯¥\šõ3ñ R'œ øÚ|ã_]çÓõþåR¤¿<˜ü§œ`:Áv8&NÞO§¿ã…Àrm5åÒdH#Öƒ. ‡ÔÂl-àçõßøÆ šÉGq ßÁ{û‡]<€!Fiã–ßM§&~¿²Ú\^ï;®¬ôB°Ÿ@´„ßRWL~‡ýon²ÐL.G~WAíâH¶c›9@x?jüneu}¹Ùs\]éséXÈxišà“ŸX˜3ü|Ðåß~ó6÷›Éå(Ƚ}žR«=p$cEØáƒljâ+•õæÒzÏqu%áâDÄxÉ<•è qÂÙñ€_ˆz|óÛw¸¿áWþHœ¨ŽÇ‘ìŽQŸ`݉¼—N6~§²¾±Ôì9®­ö¹8Pµï ô˜è;8ßøYÝå_}{žÅVšO>‡ªöGq${bÀvðùƒï§ÇÆ¿²Þ\jöWWRÞÁ.ÿþ$Pb…óão«߸󻬶ÓË¡ÑÃ÷̶[ À£1J5q¼Ÿk|Åó–«)ç!µè`š qp®ð¶Iø7ï/°Ñµ…F¿‹ÈUÙÖÐàðq$Ÿ a("òd²ñ{ÕæÆòFßqk-áÜx!Ÿ}°Ä çÆ~&Hù·Üg£c/F} ¸ö<Úp À~ #Œ!´ÞO&¿Sm6[}ÇífÂézH5Rƒ§¥Œ<7v€ÄÂÙñ€Ÿ S¾õýEZÝìrh8†o¿8€ýc´Æ°È÷“‰ÆTšÍåÍ<‹xr, æš`Çü§Þ˜y+Lùö_,ÑêÚ£¾,ÏÐáÛ Gp0>AË'ä;ÉDã(¯7—Ú‰ã^+ãøX@%Ö Þá{s2ä|òí­ÐêÙËáK†ï9âH¿¢½&P¹OßM&Æ¿R^ßXê$ŽÅÍ”©Š¡”k‚Ô 'CNë”oþh…vß^´z¸ö"tÞ:€ÇÃÎ}ï'“õß)o´»©ãA;c¢¤™(k>?qB[ÞûpÔÊåÀ¨<Î1úð Àãc羃÷“‰úSÚh-ô¬°¶™0C†´º¼ÿÉ:}+ŻτáÛ/ŽàÉ0ª–ï%úß/5[wú©ðÓ»~ò陓Rçy;|»áHžcØÆkƒï&ã«´ºöШ0PÿBÁß¹þ¢¨ýQ¼-b^|¸‘—Fä§½c_Dd'«Œ´yznW¸Žà颅ïU°ò|/糡^‡¶)GØG>ÀkŽÿÑr?R+1jIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_new.png000066400000000000000000000076361217176075400243770ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËeIDATxœí]ÍnÜFþª9£Žþ²Š±–dkí‹ y…8ñ)N"ζó{Ê ä´OaEI€Å^’r‰åK ,ûsÊZJlÅ’fؽ9$§Ù$›Ý=MK`X35Õl²‹Íúªª›$„ÀÎ/Ø¢;pÅ¢g¢"š~t>¥œ—YŒˆH>YS3Mÿ‘X’Á'"c37µ5(šÞþÃápã“O>¹†á¨Ø®/wè´«•Ðí/Õ>F6$mño¿ýöá7ß|ów!ou )Œ=VVV.úé§éõŒ4yÌ QÎ9z½ƒÁú×_ý7ÆqÎ[ßY­GK!c ž={v|éÒ¥åÉd2÷»²;£êŽÑÑÓ•eQœÊf´ì •}'„¨ýwQ—sžÀÆÆNNN""êQTëD*`Ò`S'Eúƒ¦ß·ÑÓ•eQ4”ìgÙß²©»LVö7c Œ±ôûìwÉ÷ˆÇ̘`…úbºÇKÐÔ²ëJÏ„!ƒµ8€FÐF/A#P ¾ì7eF²r¯ @Ö¹ófÙÏ&f‚ F`Ö#:F ó ÕÀû@WŽÜ¢ ®/Pü½jº/¶k:¦bÔLZ׌ ø¹Ûôþ`«ƒ>¶Ȧüâ1LÍÆçaªïÒ6Fý®LǬÄm…¥-“ !À㟗ÿ êõ@s¡n½×»^M”ªŒ­Z'û!=ÂåµÀê³?Q(†C³'ptt„~øpãÆ ,--Íé³ãøc‚`-„„¹Uƒ©º3H5 %zM G:6Ùküuɉ“Ϙ…€ ñù¨n$S0fewuòýƒ°··´×ûï¾+ÑXå§½U”e<•mXÖäâËîкùƒ²Ü #p¸v탃677s²™Aw™0åÔèø:}ª'¹[!>üðC¼ýöÛ€œµçNRñ©úÞ†,égÝ»0¹keŸeËþ¯Ûg0î”YhE¸zõjú»¢œ#ê/å¦%Œ JVD[#HdÙcËþ6§, êsÆðôl€àp œ@ý› ½“W§=9Tù︆}†Ëk=éµê ôŒ€ KÁÁÊ`Îh{ì¥Nž;¨s¼s7k-f 0u É$¬úÍ@`•Ÿ@ôV³€ª‹¤£§+ËBö¸Sý-£Ò¶b€wÙÀÙ=éC*YW–…3P±Óp’ p5h¶ŒÀU*YEmÁY ïáá!=z Žöû}Åǘs›š>Fª¼u×z š0ƒl»Åö½geÜÝÝÅ_|t ÌêÄ'IxÎ`c1çA•:l.ÃÇKPå Œ.1'>€•\€ì®¸~ý:ƒ¤‘À¢.á—h ì85(yïE,?7ΆK áÒÀI(Ø üàƒðÖ[oÈG³ áOýS°×ÖJÛuåÍÛ`Y¨ØAös§fU3Š"\¹r@¼ØAö{C0>«Z![Ó!àEùÅÏI™±T»^¯OP±ÙgXX@*«óvÅémÐÊ"dƒî’:ËÖ™‚ Àolˆ` $‹_•Ïï†Ì B¤w,E£MÆlf3bÊ'~€³l`#àÄðK´„à÷ij%aͭ߆'¯×f³ä@Øg7ë àY6D„kýÐú€ 'wéå»fYÜ6tFŽŽ¤‘Àˆ!˜œB¶óK/ß5£È" Ì~'K™€³làîî.¾üòËø …H`Nåßu#ô+‹Ší˜‚3ðÆoäjKO¤ÂÒ]zú®eE”%ŠLÂjUp!nݺ•F¯^½šî|‘Ó<çiù2òó³1ƒÑ©H Pná“ÉÛÛÛf‘Àä÷³‹AxN° 2ëD©÷íš¶i%4(iB]À 0£„_ø‚ãTÛêõ¦F_HB —\Ù˜@gâYèãJià<\%nl$‚te¶aÕ lìx!Ÿ™kOSÏF¸*HV[FâYM`œ)÷!no+Ð6`ÚüÛ!¤FÀã¼IÛ)´ÊQ9<<ÄÁÁàwޑ׊xePbã>äñ«8®úa ÆãeF°··—‹Þ¸q#•ÍX@€MB¿ñÜÂûI˜ŒÖ‚ÙA’ ºòz¨Û‘FpF¯_ŸÕnmmIu^gg`£åù•A.S¼†Õ¬Ð4N»š œÑÀ[·n¥«ƒ···KŸÿ«ü¼· ÙåKÏFFpQgë&“IZ Ì9—ŸØùðyÅBâJÙ4G`¬=M™öl0›¶ð¬&cÒ(õºl6úÑ^Õr ðï({.2%avcïµµ 3‘²ö°½1Ì}o˰¶K˜LVe t .b69u¹ø³é±0·?@Nnx6p–Ndʼ»‚øž¸1Ý^§i ¬óGGGÒH`NÊï?—7E%¶ Gtá,°··‡¯¾ú*>h!XÔÓ­'¨Û—:z6Œ0[YdÎh`¶&pkk«$Ä¥ºemÖù¾ž ©Df‹ Xg‰¿ÿþûiMàöö¶¼&„çÁ4Á4+X¾—üa!*Üu½ò²¸gÍQÝò2€Òý\À ,F³² døŸ"x)2%a*Ëï2E”Oˆ¸$,\è6ÚÎBÁµh °Ã~VWÑ–Ø`.ûá N—‡W>SY¼2¨‰®ëЫ¾‰Iß%¬L[j¬ë»#ç³8}qd¥\p+5¾oyÀ ë¤ì™Ÿ¼S¸×ë•ø„çl/÷Ø›³ƒXVÞ ;vP!‚ŒxŸ J´ˆì ÷ÝwxðààþýûéFQ٠̉ðlÊ’Š •”C÷â«Ð\QçXB Ý%ÌŒ@’A~ôè~üñGÀO?ý„œp58Vò,À‡Ø¼ë~˜ÔQÁ üøãÓGÀÍ›7å?b‚ñŒ¼ýE' @ååeÜ¿ÀÌÈÊÓ3+·{÷%Idn∣“Édnð¤>„^~Že ÆA­NˆGˆú󯓫£ïËÀèÐÀE7/Ž’’°Ø (ö VÑÃ*øŸ;ô¶^[Ê|ç9 ”AÇâ’°ÐpyºYˆÃ’¯Ê˜½Ác)$R—„™†`Œs€V¢DÁhºKœÚòañÆ"úaNË‹N`UQHéojÊ|ˆÙûþÍ ÜßßÇîî.àÞ½{Ò@P¼:x>Ö†.5¥g¦ÛÓ•¹¢Ö# ¤‘@`v²œü‡/ƒSa«X ý6åWÃ/Ç0yoàæz߉5Õ´{ûöme$PQpuž·ê~–>s:†ÕÇË¿7жXÉÊ:=pïÞ=ó‘À¬^Þ ”þªU|ÝÿÊ¢y·Ì¦O`Í ”Åx<Æx<.?!" "˜$k»®L%wÇ÷Á|\l@ÞoÞ#ðkupüe-Ý:mûöݺKØœ,³<¼Žn[ù…Œ2¦¶¥:\XP€ÿŠ) Ì|Õ…PQÄX®çH»¯,=Âæºìͪæa|›8•ÕŽÇc‘4n „ Ž?à4•Œy»{üWÌ«ûI ÷R'“AEìïïãóÏ?ܽ{7Êb%z‰(o‘VÍó«äÝ--³géàl$ð矖©7TÓ ÓÖ‘«B²q×[Yd ÎÒÁ·oßFÅÕ~ï½÷žRÏF쿎Üt̾ FàìAËË˸{÷.€Ø$w•({‘Dy»¦åçÍœ-çœçVge3^ôB ¢i<@uª=@õLÕYx2•5^š®f!Ùc ,Nu&T…º–Ήpˆì”}wœj jzt®ªm;YD!}†aŸ¥Ÿ½§uPÇçØÂ `´2÷›¶žs—+‹:“ Ò ¿¦2ÆÐk¸<¼JÖV_uN]Œüá|u°ò$…zº^”¨ä]7gé``Vh#‰S%3¡ÿ*3¸¿¿½½=À;w°³³#yæ ©®ªÝ&2úM© éöLà |üøq |úô©tyxLG@Ħ1 :¦M«õÕ×ÞîîeŒþ›—F8£ÅH`2Íåh ‡‚ˆç £ ‹¡ˆUíëg¹ˆ³Ãþ¬Î2k¦ ÂÉ»ƒ Ã4xv–7`JE„m<‡‹4ÐN`¹šÀ¦²W‚rÎqzz:7øY]+}q¤ ç­nÛ>•Ø‚QH¬Wûä+Ú_”è» Fà”VÊ„ÐÞ%¬Jf[ÞU#pFëÊŽƒàLs—°*Y,¯.«ï±×Óm²{™P²Ó†á,P‚ivJ ÊóÔ÷´ë1Å‘µØA½þÎX@éÊ£pòûe@"Â~˱Ý;Ý&3¨’›L u†ª „À÷ߟÖ&‘ÀD–žÔ”L ººA þ…5)·QTb Î6‹~üø1žFUrFÐÉM¢ºj>†‡/h A][ǶÉLí$ˆH¬­­Ö××çB½¦ +UéÑbð¤n Åeü½ Â0\Bnél;´6€ÕÕUÚØØÀÉÉÉÑgŸ}ö×0 ×9çs3K VUÄÖ ×4ªN"É‚ ?|øðŒ1Æ97òn-jÛIÆ ‡C¶ºº:øõ×_ûQ ÚèÕ`œ`éÓB8pBDgœsù*Ú†hm@| ƒ ¶¾¾Nh˜­Bàìì,M×AÕK¨ÚNé¾!Š"ʼn C4– :==åhѱ(Šæjªì:âÛ`Ù‘©OÛaËcIDATxœíËsIžß?™õÄ“à_=¤ZÒ¨=­uÄ&b"Þ{/þìý|q„#f»ó7¬¾­#&—9n¬½;¾ú6=Óî–ú¡&%µH‰Iñ*Ô#}È*¤ô•H¨ÊBVæ7ù{e–PJqU!®|¸zãWéCÑ]Xa¸®›s'o†Ñ}ñIeµW!¥bäò½ç%e…†Ñï:Êó<¿T**¥ÚL€Wé3y!„J©ð׿þõýÕ¯~õŸÃ0ù"ã4ö¸4j¹ÞFIÞ'å»+¥B lÈÞs‡ëwno™F£Qûå/ùo_Žt3SD7BÈßüæ7 sss¹(ŠÎ<¬ñïÊ4ÐÝiƒ^t·O÷k¥Tç}R®û'ngËuݼ”RDQt£¢Õì}E‘‚àÜÉã`б‹H3n¹nôÕƒFto'÷û{ÑkЄè'ºÈ¢Û^çGÚ5Böùl`ë›kÆ9ÖÛp—)7*ú‘¥û³~¯‡ý½è5€”)å™ë&?ñçâ¢{¿.ô#0^§Mš ÕcTÜ º:ûÌñË(˜×€ÉwÌM“ ŸÆ>ìõ´H0K8G€Þ Þ%@³mØëAWH0T$¸ $¸Ê”pY$¯Ç%Á°{¹nŒD˜}\t¬W!A?i0èX÷uºI0³¸N}Ý å´0ŒƒÁ™%ÀE§Ó.ºÙ›"Á¸R ßg½ºÁ°k !Îù n —6/:þ!à"+¡ßyýΙŒm;~×IÐýz\qVp%3pØñë&ÁUÍÄË`R~‚YÀ•ÍÀaǯ“W)—`Tt¿¿í$Ù øH‚É y? \Ò ˜ ¦áý›6 FÕzÏŸ¥‘Ÿ` pvÛHÐû~Üé`0ñ`аcI0[c8‚>4ôëôqLÃ~eg*º€þs÷UIp«”ÀÛ@‚i‡’'I‚YÂT£ÃŽÍJ¤ðC'ÁÄÌÀIÜY&Áe]Çý:ÿVMݸÎN›UÀø‘ÄYS¯-8î±ë&ÁU¦„QI0K¸Öhà¸ÇfE_è‡qIpk¦€ÛB‚ë$O/Æ!Á­!Ü\g=î&b;>é‘;«$¸Lq–p£ÑÀqË}$Áä0Ñ¥a•†Y!ÁUÍÄÛF‚™‰ŽSnV$R/.E¼i\É øH‚Á¸¨ÓgEÁœ¹`Ð8åfeZêÅ,ü3 ·Ü¬Ô£³ØéݘÙ`ÐEå&]a¸Ë$ø˜tM˜UÜÉBfQ Àl’àÎî2+SÒ¬c*fàm&Á4êÑ‹; š…Ž¹ ÓÒ¬âƒØ!dV¾kÑ!@RñaŠÊ4”¼ëÖ%f Ô!³"‘f Ü!³"‘fä!³RYÀµçN«ñg¥ã»I|Ð;„|$Á æÞuÌbg÷ÃÇB¦p½QÊÍJ\`¢f`rü2Ÿ{ì¶“`V0q3pرÛ@‚ë¬Ç, ÷‘1gp‘¨êw<¹Ùäo¿ãƒ®9αqêx“õHAJ)$?WÂEÓ‰ÂÀ¡ˆ tcQ†á™]¹ÞúC}Í~õ¾zvø±GƼÞå]Ô¶msrrB³Ù´0†Iã*!D¨” ãú‰nB\H€QEFƒãr™f³‰×ò‚@3}ÀcñbH¿ˆa‡Ú¡—<0ä›ÐU<3jÏvpŸ¢C¯†¤Þhÿþ¯þê?~ð3Ó²¦ùÐ(%¤ˆLÃôÿãúk¯V«½4 ãËîF"ÀE"1Ž‚••U¢0ÔÝ®˜€€»“pþþïÿÇßö>Db¤”Ê0Mñÿëÿç?ÿÓÿþën)0²F‚( i4šäósÜ+ Â0Çôþ +GSE÷&SnH)…RŠjµjA`~rü.Ò‚û)uQaƺÀG̤”ZRû@ë\Ù çy@)ü¶O»ÝFJãÜ3r>âfôC«å%O4=cyœ“£z¨z¥ŠÊå2žç1??O6›% Ù¶ƒï*„Я>>>¦V«‘Îd Ù9¶#¨÷!´†+¥¤^¯óý÷ß³··wî)š1}H)BðêÕ+vvvÃÓ0òüà¾R>@7„ÐHr‡\.‹mÛìììðõ×_ãû>¦9‹ó#.€aAÀÓ§Oyýú5Ùl–t:iY)úYÅŽíÀqà|§J9–e‘J¥) ,..R*•øÃþÀÁÁ!¦iÎLä.Â4Mjõ:üãŸ8>.Q,.’Ïçq]Ó01äyŸÓ•ý§ÐÀ2MÇÁ0 ÃÀ4MJ¥_}õÿØÚÚdkë>†a|´&ˆd¾ÿþ=Ïž=òLVW×Èçó¤R)lÛÖƒOOÿ‰wfr~] ýKÆR ™û8ŽÍ«W?R.WxüøñGqBHô«/xñb‡\6Ëââ¹\N‹~ÓŒ%oÿRóE$±wWÑ÷ ;-˶øâ‹/xôè«««‰yòqzI?H) Ãï¾ûŽýý}Y\\$“Éh±oš†1twÒ¾%$:J ¤ûË“)Á²,ŽŽŽxöìÇÇe>zˆmY¥Á%aõz§OŸR«Õ¸·¼Ìü™LDZ1Mk$ëk 7ÌÚ„¥É”p* lR©羽TyüÓŸR(fæiš³ !†”ðí·ß"„`}}¹¹92™ –ea&R޶'ñ•óF©0pfJHÈà86‡‡G|õÕWlÝ¿ÏÆú:BH¢(Q?N §Pñˆü¸»ËÎö6étš¥¥Óù^wþp‘ß‹š$ ’ÊJ˲9>>fg{›J¹Âƒ‡H¥R:¢¨Ôÿ‡¤y CF;Û;¼}³§Íì¥%²Ù ®›:£x_1GöÄ/„@ÈD/0;VÂáá_ýËW<øôK‹‹ÀíÉ®& iÐh¶xþü{*å2KÅbÇÕîºN,]±ËäÌ@¥P Ô¦ç1a¸H)1MÛv8::äÛož±¾ñ ˜†Ñ±>4hÓMr\)óüù÷ømŸÕÕUæææH§Ó§ö½¡ÍûËæ-ž!ÀD̰¬–&¶-1ŒSeY—ØÛ}Mí¤ÆÖÖ™luFA¼ËóBbeiQþþý;;Û˜¦ÁÚÚYçŽa\=êÚ!€ã8A0¼jä@ìdºì¢MËgœG¶íP*•xöÍ3¶67Y\\‚dg ¥î&b‚HEìí¾a÷õk2™4‹‹‹¿~2ß_f§}Þùs§â¸,’›IL—dJ0-‹ãR‰ï¾ûŽÕµ>ÙØÀ²,"Ý9$þY)$¾ïóâå Þ0?_`~~!žï]lÛî´×$0Q?@Žw¼v™HÃÀ¶,Êåcöß¾¥^«±¹¹E6›ÑÎì;¦ )©Õë¼ØÙ¡V«Q,.Q(ÌŸñì‰+‰üKº‚ÇÑþGQA‡D—¹(0cÝ@+ˆG|óÍ3~òÉO(.BÆYÇ·˜qš¼’ããc¶wvPQÈòò2…BL:í8§ÖSRì’m<è쉬 é›F…:“ÕXB ºô+–;;ÛœÔkl¬oà8ö­Î-Õk*oÞòã«—8ŽËbq™|>K*•î({±I0ñïŸ\8X¡•³K*ƒHÓ0]áeí<²8xÿž“j•­­-òù¹®çíß÷ÙÝÝåíþ[ò¹|GÙK¥bçN, ݶã~™:“ÒÁÄüW¨Ú@t{ A‡7-\7E©tÄ·ß~ËÆÆ++«HCÞ½@ A«ÕâÅ‹ª•*Å¥¢öçg3¤ÜT‡ðÓŽžq_”¶5Š$èϳ«¡7ž ‰iê R¹\æõë×Ôj5677q¥¢™\“’ÔIHÉÉIíí‚€•Õòù<éTÇuN;^ˆ‰µå q1Y3°k˜4’…&†aàCj’V펂¸¹yŸùùyM5K4ÐuRrtxÈ‹;X–Åêê ™L¶ãÙ; æ0ÙvÅxöü«‡ƒ' Ñ!Á1Ž'X–E©Tâ»ï¿cmmMG¥$ é(O—‚¢ããØÝ}Íîî.ù|ž……²¹®ë`[6Rvuþ5a¢f 6§¿âëTA4ŽèH˲¨T*ì¿yC­Zåþ§Ÿ’Τ üàFGI3˜¦IìììP*•XXX`aat:Û÷FlæÅå¦Ð~:Ns“7¯Ë.mbÃ4;f¢Ç\×¥T*ñôÙS67·¸·¼L„ap­Ò@ —ƒ7 ž?Ž×öXYYéÄï×ÕVΙPütÚnl?ŒN‚dô_§"®¥Ä0M\´4H‚JåJ…ímÊÇÇåÞò2Ÿ>x€ãØxž×yWáA·àO_~Éææ&Å¥"ž×¢Ùl’ø’±Ú«2&OÓ0Éf3xžÇ—ß|‰çµxòä •JÏóô÷†aa˜JÉ>W»\ÊxZh\ðæÔ)ÙµÄk·i6T+jµkk+|òÉ'„aÄ»wïØßßç_|ÁÚÚŸý«Ï( ÔjuÚ~Õ3-è;S •J‘N§ÙÛÛåÙ³oB°±¾ÁêÚ* xñâår!“DÀ¦³@ó¦}S &äˆG7Ôý*ù£·«‰ÂßoãyõzƒrùÓ²xòäsŠÅ"Fƒ£Ò1¶í°¼¼L&“áýÁ{Žyøð!ëë¡K£Ñ Ã3f£ešä²Y‚0âÏÿògÞ¼Ù#ŸÏS(p\¯Ý¦¸´Ä/~ñ ^¾|Åîî.ÏÏ‘JëŸ^«//Ø)m*Mtòt}Ëu3 ‘*uF½ïû4›MªÕ ­–v¾lmma˜•J•f³…a¤3,KëŽëR©Txúô)ûûoyôðó ZIT‘¶…VôÞíïóÍ·ßÒö}–ïÝ#—Ë‘r]l[› år…l.ÃÃG™ŸŸçùÏ98xÇüü™l^Ã0º$Ì͈„ ù’ý¯*þ•ÌÇQâû>žçÑh4¨T*¸®Ã“'OXX\ Q¯S®TˆÂiH$CªØ…¬×Ò9ŽM6“¥\>æ‹?ý‰âÒÅbÓ4QJëïö÷9<:"ÉP,;î\­èé%Yz¿0W(ðóŸÿœçÏŸsxtÈ\P ›ÑùüÂ0´&>ua0¤ÐQ@×ÒýÉŠˆ0ñý6­V‹J¥J«å±¶¶ÆÖÖOP J¥cü¶¯3n¥'(”)õÆ I²‰c;¤Ó)Í&õZãò1a"„DJ¡Í»ÕUmÚÙŽ^ˆiYq®^ÆEA”J%²Ù O>ÿœÝÝ=^¾|EÛk3?_ R ˲@š:¯¿Ï.k²Ÿ_Ú æP×d$©çEÏóh4êT*U\×åÉ“ŸQ(¨×ë4šÍN4îÌ„®§)b;Þ4°l[›Œ©4ù|>Þþ.BÆ‹4’Œ$˲±,3Þí4]«#Ò…n#…¢vRÃoû¬¯¯“Ífùá‡çèŒßT:ƒc«˜@“ËöíÓh—s½ 3Ó•IçëQ¯E~µZ¡Ùl²²ºÂæO~Àq¹LCëÝó¯ŒÝɆ”z5’FQg×Sÿ6¤{ãuxB †¤J¼v›R©D.—ã/þâ_³½½ÍÁá…BH.“ÁrœSñ5š45Û§&T¢å+ÂPúf³EµZÁ¶m>ÿÙçÌæ¨7x-E²švtÍ¿Béu …)"¥ºìÊ•pĈ“·€Î"Žjõ„TÊåñãÇìïïóã?ø¾v9.¦ei³qÂJAg?ÇLÆ œâ×Ê^<꣈À×›QžœœÐjµ¸wï( R­&£þò{`r¶3ÂÙ{o ?Fïè4šÍ¦N[Y!›Í²³³ÃQ©D¡0GJ¥ºVþÈIr /&c&¿§ "¥}õIç·Z-ªÕ*¶móÙgŸ‘Ïçi4xív<×OfOÂŽPô~>+ ATªU2é4Ÿþ9¯^ýH©T"ÌGzù—ma(º¦°+~ó8žÀ3å/0;vÙ´€Î¨çÔ£×ö<êõ:žç±¼\duu €jµJEºy¦°å´F ”¢^¯ã8Ÿ~zŸ\.Ëîî.~»M6—w[KLË«¥à ÊÚî»YôšêÔ†!AÐl6©Õj8¶Í£GÈår4›M|ßçå[º©P¸ÁÒÒ™L†—/_r\.ë•Àn £+Š8iñÒËÃ/6¹4uà¦ÝnÓh4ñ<âR‘ÕÕ”RœÔj¨HuÒÂn7ô”†'µ©TŠÇÊîîårE¤R.†aaz‹˜qpa0¨·cÇ3Çc@Ç“¬ªË¶¯Õj˜¦©Åc>‡×òh·Û€ÖÆï@ïŸBÏ´šMlÛfss“t&ÍÛ7oñŸl& XHã´.wû#NgŠ\:+xŒîOܹ‘žzÚ~›F½×n1_˜guu!õZ½«>w©çO‘({¾ïë)aq‰t*Íëׯ)W*z‰¸£wT‰ckĦÔ/“5/̀ĥ†í¶O­^G[››Ìåçð¼6íÀŸÊü7»Ð>ƒz£AÊuyôè!¯_ïrR­¢²*ÞÐqšZv!®bŒfv¿» ›¨ëºQf“f³ÉÜÜëkkz#ÄFCçó0BA«Õ²,î߿ϻwïx÷þ~à’I§;)ñ£Í†cLã`h÷'qûxꣿíS¯×Q(>ÙØ`aaA+ͦ^øaö½†…öDQĽ{÷H§Ó¼ÞÝ¥Z=!›ÍbÙñŽ J 5ƒ¯ *:³À`OPwø¥º‚8M2™4ëëX¶§d©ž´éI’«RŠF£A&“ááƒOyýz—jµJ6›ÑÛÆ"b°et™µƒ¶e%1¤¯g8QôP¨PáF(ŠX]½ÇÒÒAÐjµôM "’6ñ<ËÒ–Ñþþ;ŽpS)R®'˜@?åp¬œÀ~i“(uöR§ó½¶í¤R)ÖÖÖp]›v»MF;~Dø~@)V㼄7oÞÒ#Òé†avõÿÅí9™ppW%É êUô¢(Âkµhû>Åâ"Åâ2J)Z­Ø®—ò†³‰o’me<¯§Ÿ;ìîîQ«×H¥Ò]aåø| £õtédýª{ÐsAEø~@«ÕÀ²l¶¶6ɤӴÛ>Q!“*³“){[ ”¢ÝncY6÷?½ÏÛ7ûTªRnÛ±"ÞKP\a ÍÐuõÎÆ Š0Œð<ß÷) ,//#„Àóô¨¿ "?êº=!¦šµui$íRJÖ××H¥\‰¢Çqµû8’}âÚ½±%¥ÉâÊ~_Ö¯a¼‡OHR(|?ÀóZH)ÙØÐ©P‰9sÓHš¢;Ñc*EêÖ1  KÔö^ûº %­ÏÂÂnÊåÍ›74[ \7…i ;éƒlÛ&Š¢¨ÙlÖ«Õj³Z­vßПZ±óD³Ñ0,Û±ôÜäá·}r¹,ÅbÃ0:>üY@Ç$g;í\¯)-¢d±‰ÒâôÌy‰ãCté†ÂÉ”rSlmn±¿¿O£Ñ$•J#í3:VçU‡­V‹L&cÿö·¿ýï¿ûÝïþ!Š"—!÷qº'€Fƒû—ùïþæoþö¿x^‹( ¹·rÂܾïãûþ Ë\;’ô½S¿DŒ>wª;[€*R*DSõvnr±ž–|ÏMÀ÷} C²±±ÁÁÁåJ%N€í<:¶ƒªÕªJ¥Rít:ý²^¯¿±,Ëè»hèû¾¬T*´ý`# #Ré4 Xñ¨ŸåE¤ŒàGÚÍ2¸üŒÝfFD‘O±X$“Épt\"BâÇNÏèÍf3”RF®ëúâôóCÑn·% C6ç ÖWWñÚmÚ34êâCôÂÛÎ(³dJH–§k=í,ÏYQ]*ž'ô“ P •Ëe Âðî=²kmàm„&A Ó´ÎÙƒ“ )×qt&ƒi˜fjB—½y@!8–œBôì‘ͤ]¤Ô¹õ1&q? oöv_ýÝßý·C?¡…¡F‘TJ ¥”®nM‰%ÿJ ¡³ŠtJÖ@‰ CDÂPRÒPá]@¡”QìQ‘Jr«’®ã¾;÷)„PR% #4MÓs§ñÃ?ü_)„ê–Ïb"; aŠÀ‰?K‚”¢çïu¢÷&GOa1r&©¬¤yâž ²gEל¿Ïk$@çox@x”€6ÐN¼II´xË-[£_ûüãªoBh߳Ы>½Ï¥ë²”–ó«†Ì,!¢ÚQG>Q@c0ñ T¼§€š ](DwzM†°[»ÿÿ=yxÄæ^·IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_replay.png000066400000000000000000000226601217176075400250740ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíidÙu×ç¾-—ʬ­«kéšéž™žéÑLË#ÉR+ldIai$c A„‰0Ø ÍŒ$ ؈°A²,;lü…€|€#–Èá ,Ù’g4£YÔûZ½Õž••Û{÷>¼÷2³ª«»kí.«ëßñºr}ùòžÿ=û½)ªÊ^˜}x°8 ÀCŽ<ä8 ÀCŽ<ä8 ÀCŽ<ä8 ÀCý""âB°mèN’y>¤B_wŸµÚá€ûý2r@ "FUÝvN(ªŠˆÈ;ÞñÎÉçÞùŽï¯ÕV¢¸Óެu¾ª ÂßOPQÏó’b±·Z­›ø•?øÓ$I:¤Ú`KêÀÏgÿÏýÝ¿÷Þ_ùÕ_ùÏå2I’ÈA`ÿB¡E¼üÊË/õ¿òARm`·z®®P«-‡êT†ªUâ$9˜öûùÔ ÃƒøªZVÙ&DDä£í§ý8ŽI¬%I’ݼÞì‚  wD!$õÙ„µ~Â=‘;z¢ê¤ÓéÐét0ÆÃ˜ƒq¿"—M³Ù̵õ¶vפvEYZ\¤Õn3<<ÌÀÀÖZüýÁó<KKK í;'€g<ŒgX]]evv–ññq¦¦¦PUœÛV”q€]‚1áæÍ›ÌÏÏS*•‚#;ÓÔù»U5žGFT*„aÈùóçyýõ׉ãß¿-gt€ûß÷‰ã˜S§NqéÒ%Â0¤\.ãû>Æx°E»¿æÜù Ïxa@±XB5eÝìì,ßüæ79qâiÆÆ˜„ûÁ÷}fgg9wî###T«U¢(J5€g %À¶„’@Ô3߈¢Ïóð<ß÷YXXàÕW¿Í±cG9vì1<ÏÃÚ-GØÒ1N8uêׯ_§Z­0<žç!";š=½.€ž1)³ŒÁÓ%A…\ºt™¥¥eNœ8qà îrGoyy™Ó§OÓjµ8th”juR©D¡PÈTêì´rs»aéªÉn{žG„aÄÜì,ßúÖ·xòÉ'™œœè:ˆu¤í!ŸD¹P/_¾Ì… ˆ¢ˆ‰‰ *• …B0 × ç㽡g—Ÿ8S1]äD˜ŸŸçÍ7ßdqq‰ãO' ‚m°CxžG«ÕâÌ™Ó,,,0<<Ìðð0¥ÒÅb¡_åïêD»«k/"˜>“ÐÓ!Åb‘ÙÙ›ÔVjœxê)†††pÎ`‹È'×üÂ<§OÆ9Çää•J…R©DEÝYŸ¿~7qÏØ.ÿÀ~““!ŠBæææyõÕW9öØcL9‚ˆÁ¹ÜA<0 #Wù \¸pK—/Q.•=D¥2Чò=DÌž™×M÷ëMBOøAÈââ"çÏcyi™'Ž?A±XÄe&áÀ-X UÏóiµ[œ9}šÅÅFFF¦\.w½½Pùë±¥ìN.|ALîøÝ(annžW_{•'‚C££€˜„uÈUþÜÜgΤ*bb’êà ¥bq­Ê—½oǸª÷šˆà cð}Ÿ0Œ˜ŸŸã»o½É‘éG˜žžÆ÷¼ƒ4r/‹sç.põêŠÅã Tº©]Ïóº“,•‚²—shÛùÝTø„¡Áózù‚ X\\`æêê+uŽ;Fy Œ®q&»ê|ÏóX]mpöìYjµeFGG¢\^ëå÷WaïÇ(­!€f*{+j;%‚GÈšäQF,,,ðæ[orìèQFGHznÕï}dC(F0b˜½5˹sgèÆö%vî·ÉÜ• O~ñÆô¢ß÷ñƒ€Å…N:ÅäÔ LONÝ÷4”ô»c°ÖráÒ®]›¡\.3::ÊÀÀÅb‘0 ‚`Ͻ»¡;¿ÉŸ::>Æóƒ€¥¥En\¿Îj½ÎÑ£Ç(§­+ß«¢b +õ:Î_`e¥ÆÈÈCCC ¤!^ž[Ù‰àÓáۙܶåÞ ]{—k?ó Rqž·Þz“Gy”±Ãcˆtû…¬ý…\å‹…[·nqñâ§Z­R.—»éÜ|ŒºoßÖ˜ï|Üv¿È/‚ O²™ÐŸE\ZZäüùs¬¬Ö™>2M…{êåÞOcètbff®róÖ-JÅ"Ã##kT¾ßuôö‡\Kݺx'äÚÀ÷<¤¯¼œ&foÝb¥VãØ±cT«ƒÛhgÜ_0FXYYáâÅ‹4 †‡†¨V(wk÷kgýÞ†w›Åž¶ùôgóÁ÷}|? P(²°0Ïw¿û]¦§§™˜˜Äxæ/œ_ ÙL¾yó—/_Â÷ý4¶¯T) Yo…ßu÷[ÅtM?@nw[ëë ÆKOÂ0dii‰+W®P¯×9zô(QT@Õu=éýˆüÚÄâ8æÊå+ÌÎÞ¢Zdd¤—Π°çèeÇ~£÷m& {ì2R¤b$žIH©ƒvÄ£Gcxx8%îG¤×d<•ú Î_ Ýj166FµZ½CÓFöö`\wª1ûÚÂ÷Ò%Á1«'AÀ§NŸbjj*­,ƒ³6gσ‡’©rÃõë׸rõ*a2>1Þuô¢¨VðŒéúA{v9ª;V×ë4Àž)€5è9ˆ>IWAÀòò27®]£^«ñØãS*—Hâä&ŽòáðŸ¸ÓáÂ… ,,Ì344ÌÐðåR9+ß“ÚûnÙoç2ºóu©faôö±xŸârIÝ'/S•žçáeµ„B¡ÀÂÂo¼ùGcüðalbIlò@´Ó­q\¸pkmZÁ«V({M鬗î÷K±wc¹ÛºZÀýÑýHµÁó} ¤Ú /*--/sþÜ9–yâ‰'ˆ¢íN»ï÷Š YNÉRµ†K—.qíÚ5ÊŒu»sƒ0õg$Ëäï»Ø}°gqÀÝ!A|cús…(Í ¾òÊ+?~œCcc´[-’Ħ׹Ûè+â‹UΞ9ËêjÑÑ‘nwîbûû‰]ÿ€•IDãy·9ˆyQéõ7Þ`üðaâ ¢(¤ÝnwgÛNyÐÿà À÷®Í\ã⥋AÀøxÞ[$Œ"|Ïd-].´K=€õZlºûkÖ¡?ƒh¢“ÕuН|å+ÌÌÌP©R©V)K™½1ž×];±ì…fÝyºÖhîYîüÄÛGî€e Î)ÖZœsXki·;T+U¦§àåW^áèÑ£Œ£ÝnÑl6ÉóG]§,;s_¾ûQAà300@ÜépéòEæÃ(´j÷ š½^³ÇtÍ7ó­vßqU·'a <ȪLÖ8çH’„v§C³Ñ ¶¼L½^gjj‚Gyk7oÞäÆüù·¾ÅÔÔO¿íi†††¨×WéÄtYHgaz~Ïó(—Jø¾Ï¥K—8{ö,…B'gàÌÎÞâÖ­[Ôjµ^í%ÀƒA@Ì=Å© .ŸX€oÀ3‚Û…YæòÄÍp{?@üÝ ™îCà¬#Ž;´ÛmVW,--â'O>ËØØFƒù…EÂ0âðáÔËenÍÞbqq‘ãÇ3}ä‰-Ðh4H¬]6zž¡(‹,--ñÝS§XZZb°:Hu° aðì³ÏrìØ1Ξ=Çìì,Õj•jµŠµ‚ ë×7ôÖçoÀç vJ'V«„°ÔNÛ匄ÄV»Új»ã¶«Q@~ÒûÊ€lf¨ºî¬ã˜f³I­¶L«Õfbb‚cÇŽáùËË5šÍžçQ*— ‚ÔGˆ –——yã7¸qã:O’á‘‘ÌIì­]Ì—`½ùÖ[Ì\½B†LNLR.•(”Šé¾;„å媃UÞõîwqåò._ºL»Ýfp°J©X&ŒBÂ0@<Ÿž±éoð€ÄZm¥Þ´8U^¿Òâ˾Ä@1àû+ðwÞ7Jls­·uìz ×³÷ èÚÔ¬ÕYKÇ´ÛmËËË 'Ožddt„Æê*KËË8k1žÁ`ðŒf)ä0[Ö2P`ii‘o½ü2c‡166–nn!‚³–ååenÞºEÇŒŒŒf-Zih—¦rMÖË—°´¸H±Xä裩qæìfçæ¨V: T*8W µ¯•»grœBÇB£íXn9b«ü‡ÿ;Ëói’xjÿëW˜­uøÇ™¢+®ëole ]n߯x0& s4S;lb‰ã­V‹åå­V›©©)Ž{UXXX$îÄ Ùr*ÉÎaÀÏôšM¢0¢T*Òh6Y­×Y\Z$IRµ›·§•Š%ÆÊŠE¢¬13­ÙÄd"4Ti6›t:1•¾ïíßǵk×¹té"­V›¡¡!J¥"aØ[Ì‘¾_q’Ditõ–%vÂjËñ¿6Ã<]åo¿wŒßüÒuŒ~ñC“´b·es°û}+¯ýíî;”$I6ëWY^®Q(8yò†††X]]¥Ñlv«pkFGÒM­|Ñ´žà{a˜†ŒÅÕj•$I°Ù¶wÆ3iåѺËÚRÁI¯fßï6f±¾SG­V#Š"¦¦&æìÙ³ÌÍÍR©V¨ Tˆ aâ‘Ô)$Vé$ŽF¬$jð"·Î,ò™ÿv•ѧóS­ðï¿vAùL? 6=Žn·SÁ{¯rá§³>UùµÚ2Íf“‰É Ž>ú(‹KK$Ir×Mz¢L–NöŒIW#…ë\w"dkÄ`|“m…'Ý…—r—Ù'Y¶¯Ýn“Ä1år™“'OrãÆ .]ºL«9ËàÐPVNSÙNÓ¼Dâ”f QðНOLâŒ2]€T‹üÎyÏ3¼ðã´:®×qr¯±Üq¸A`Ï4€æ^¾bm:ë›ÍµÚ2aòì3Ï284Èj£A»ÕFÑÍïUØ·Qžhº.AQ|·Ö¶¦ãšfójd÷¿{ xºJºp£^¯géáq†‡‡¹xñ"óósÄ©6¢ÄÇ9°NéXG]|:¼åÃŒÂõ06Ƈ~ú~û÷ßBDøäÇhÅ››Ù©ØY=dÏ·þJ½lÖ;GÇt:VVVhµZŒ3==˵6ŸõÛú)ƒ~A*âY?ýVd;#'i(Ž“®É:qâss#\ºt™ù…y*• ^X ±>N•ŽBS„DLš{uéE…®¯@qò0ÏÿüÖÿ."ðÉŽÑìl¦-n/ò»¬œ¦¹ú\ø­V‹Z­F†<ýôÓT«UíN'³õ»³Ci7 (ëߥ³K:ûšÍqÜadd”J¥ÊåË—YXX$,t°~‰8ö°Nˆ33’^Wï*BóËÀÄažÿ(|ñK§øÄûÑŠï®â]þääµAèvvFúf=½Œ^§Ýfuu•v»ÍáÃcLNNP«Õ°Îež÷Ž>vCìee#/\Yk©­¬P(8~ü8óssœ¿x™Z­MÓ•H’ë‡é{ävs œ¯“‡yþ#Âo~ù»¨Â'>pˆvrÇP7ï/Ü k€íŸ¯›/WÒ~’$4›Mêõ:Qòä“OR©TÒ}nã…ïvùÀ‘U[­I342ÊÛJ¼uö 3W—h&%’bíF·#×29ÆG? ¿ý¥SX…O~`”Nž1\‡þÔöv±aOàNΙzùiá¦ÓéÐh4i·ÛŒcrrUe¥^Gö±ï ¤ßÅZÇj½ŽxÇŽcE瘹0G«ÝJ…åÝù‡g—AñáÀþë)åÅ¢“hOåçÐ^íd»Ø•Ž ®)REûbûz½Žïû<þøcTªÚ­6N³*üž@ÖÚ‰cí˜JµÂÔTHm©Swϯ œ[ãùç-ŸÿòYRX‡s}UÍÌìdwÞ”§s]êéwâÕíN‹á¡a&''Vë«ÙžAë:߃È5½:K«£CÃÃa ¥}Ï÷GÎ-Añèÿ¨ðùß?ƒ"¼øþQ:êÐ,û»9›ÛLÀÖΚ§tÖ&t:1õÕU8vô(ƒÕAÚí$îÆÑºû(‰k-–1ô|€{ŒqÁÀëó Œó3Q¾ð?Ò½‚_|ÿ0ÜÏr¹Ó¾}l«-¼_å;ç°IB£Ù¤Ùl288È‘©©tK”F#k8Ÿ£û+yj¹oç1›‹‚׿£|üyR¼øW†é$½‚ÚN°5×í³/c%îĬ®®¢(LO322’:Íf–zÝÙþEEºÉ—€IÛÅELÏ6lÁs<:ÁÇ> _øƒs>ù£C´í®wݹÔ_¾Eµ¯ˆÓ¤\.1}äAf-YÚí yÑ Í³µbÜCÀ{¡(ðyÐG'øë? ŸÿÊŒø¾¡þÜn7:[î表Uâ$¡ÑXͶ5çСC$IB«Õ>•¿ýå…þ`G õœ¦ŽÜmqÝ)¼> LOðã?æøõ¯^"ð=Þ‚lÅ®¬Ã&:‚rG/µ÷ilß X,255E¡Òét°Ö=ô‚Ï‘ú=Ú×Ý F@³"”¦U¢- ¾3ïxlŠ¡|înòÁÃc®ÓX¸¹eMpÇ<ÀzGÏ9G»Õ¢ÇŒ26vU¥ÕÊâzcöÅŽ;ÈZë×ëþ½7tÝmUÅjÖ–jƒz’ÊÜ*jí– ) ^›w¼ë±I> —ÿØ×wÿÂÏç¿öÙln餷·…wÿ¦wœsÄqB«Õ BŽ;J¹T¢Ó‰qΑÖn²Ž¸¿ @Öݹí’5- eÙÝô¡¾zrJ’^^ûÞ˜“' ‚ï „øÐÛ‡ø}»ÌRbñ·-øªüù-Ç»¦Çøðû$øjø“ÿ"}|µñŸ>þ[>Wïfö…\¾âT±ÖÑn·‰ã˜¡¡!>ŒˆÐn§³þ/‚ÊwÚ#t~Û)¸¬-ÍõÝ·¬¦í\V•Ämpß)ÖõßN;¬‚µJ¢ip;QêY?à†C<Ã?zï(O=Rá Wˆ,hjMÀÙÔ$¸œÍԻʹ‰k!I qéá,8—š ç§Ò­¬æ×Z”¬fóž‹Ý1¡9 Þqx„{òGߺõo«/½¢µ/¾óó÷zo·ïœÇ1ÅR‰Ge°R¡Óéì •OlzïXTGú:¢5sr(ÿ)œTÀÙaÓÊg¾’)=²ü¼u`-’ôÙ}íĨµ¨uÙßXGà,ß¾ÙÁMŒðþwãœ~nðÓßþÅ{H7m휕¡ÁAŽLNbDèÄñŽkÍ{Ž-eU×f¹º}]¡Ó«¯ëÚÅ JºÌ«»zÞõœHµ=¢hF u.°C“u‡Õ=9°Šï߸Ú&äGß5†³ú¹Áϼú™»JŸ€Ê‰µß{? ™ {׸æFüÛwè’t»å\OCtŸ³);Ôõ’&{îß!ÎáãøÆL›dd÷=wgÝç‡~éÎ$èþrh¡P0éïÑzø~qGÿÁ"¡g§cÜ ÌÀÀ*§x±‚çÐXQ£¸¤·ð*QGb”Ĥ^½'icA1¤æC2bˆUÄÚþ’íýƒ†ˆv­Å{Æ+üðIåÿ½±ðù¡_úŽ[úÜÛo s%*?ôC?ü#õC~ÑÚ¸œ$¶à¬ ­sFUEUåîîÖžC»- ˆªHêP¥åÖ;޲OœxFÅÉ'Ù}qÆ7V|qâ‰5žX|cM`˜DÒÊobñL"¾$ây ¾IðM"Æ$øb1ÆŠg1ƪ'V$bŒŠˆU‡÷`Æ '|ÿxˆ›_á§—5äÓ‹ÿæí_ìd]:)qŠÀ0”³Çú-íƒjçY¯ÄݺÇû_×AJ>…²G4à•|¢ŸBÙ'*ûDÅ€°}•¯X)HT.HX MX(HP%($ â…‘øa$^‰¤=b‚HŒˆç…"&ÄxÆø‚ñ1âgñÆ}‡’Uxn, 3_çµK+Î÷̧~ýäou_—@IÓÍ9!öW»®x‚1ˆÅ D%õßaƒ4´*ø¡øO¦:î™á@ ƒ¾)V‰Ê¾DÅ€ JXÅ‹B ÂH‚B ?*‰ñ#ü (ž_D¼¢¯„xEŒ¯ bŠ)€S@$‰IÇOÁ¤&vÏßÜ ¹ËòÚì oά:cäÅ…_;ù;ÈIÐÀR_w‚)TE!A„)|‚hcõï,R¬Jtâ}¡©ŒùR¬øñ xAˆç?Âx!"!b "^#ebJ% (˜2"%Hï#”PŠHF´@"Ò Ô?‰( Xá=‡}^=½D£ãZ"üå…_{ö›Ý‹SÕõêèãÁC„ð¹àO=‹øHiñMw—k­*x¦4$/_‘aHÓ@Á,ˆ%Ó–Ù‘¤5õ5÷ÿ5´/hÌ#„üÃ7ZT‘¿z»_»¯Ø¶ö nW{}÷eÝóŠ0·§¶ÓHáðÍ{²S7‘ ØsŽx•ÿá3?.ªÄ°ŠøïküRR¨M—†w+o ]b}:1–ÐíŒê{ ôò"HAB×=±“”oÞ]r/lø!]d+.û\Ÿµ´œbo^û3bêG~ùMyàêéžð*û“?‰6kàºAI'd­_zÛX»,x_#óÍJDÖü¹ýþúOÜèù§@¦RM–}VÚ–zÇán^=˜<ò³ªº$²ìÓ]‘ ÿíϣͥô±¼†‹¤³ã^[¥m‡ïªÆÚHèNÁóàÑAŸ¥¦c¹£¸Ù§ý‰©ŸGõšÞügŸ‰÷/¼€ÊÇ~—ðû2áßîæ“oÏ|DZîºëžØŒ¢ØÂé]×Lì-[œS|Ox|8`¾iYh9ôÖ3þáñO z†ž¯³O5€Pý™ßíÎ|éSÁÝU7šù<¹³F¶ß–®›³[Y×* ÖJ¹î œÏ3<90¿j™[µ0{ý¬?>ñν¬­ùÏ>£° à þÍG”Í|Y³7PêЧ‚1zBÛÝi‡­lä¼Q»Øa$+'loí’ ßN ˜¯'Ü\µpëÆÿðä§TÝ«¤ÂoÎö™n±gÀ ú[¿Gá¹çq· @ð=Á“ÜÆ U•ŽÃéÁÝÐäßµ{²ë¸o†Ÿ£Ï0"ÔÛŽÅUØ¥}0ºpš ÿ™C·ê ×꙽~ÆŸxIU¿ ¬~áÃ~"@WøÁ5—¹SÖÙhú{CÎSH„‚3<:ÐN\þ -)|O*šl•Î:*­¡éuj÷G{ýÑ]ÿk×ø~Ò Ë7¼ŸE_¸´óõ³1yƒénÀ)ø<{(ìþÍsþøä§Ôu…ß\/|Ø'°Ìàßø- oÿ(®¾”?ºñk­`| ²,Ì\µTž3‡ Ë­µ³±c¡“õdIÿ9ï0ýó½…×ävÒP:g¯X,äAºöN›v¤<\wýÊ !\.Š¥-îù‹­!þɱ›õ„«u‹ÌÞ8ŒR¾Ôæü¿z[²Ñû÷J?øsDÏ} [Ÿå^j×ZÕe‘xF§< eÃùù„ZËu ’îÓ»ØpâT%÷£šî(‡â>ŠÆ‘!”´.J/µ…þCÓ¿E…JAÑ‚B¤š¦‚]îð h ߆ÑFDá‡|ÁîŒý¿UO¸Z³ÈÍëç‚ñÉÕ¹\øù_}úŽ œ¦4Bù? µ%Ì&úPlÖW„hŠSÂlÛÒ²Ž è½NŒ†Ë$Y6ÖÒïìi.ü¾Ã¢4¿O@#IóûEzˆòçRHA L¯)Q”È),‰DêWfuºyKÇÝS Õ1Ÿ¦5[Š Ö#õž ¸¹’puÅÂìõsÁÄäKê´çðýʉ»Žê'@éí'8†k-± §K‰ BÃXêX’8³n¥¼¤1€g$nëjµ¶g”4cfRÝmH+£^VÊí?ú#ùí^ÕO³²º#PGUšŒg™1}Ô=çž×#Œ´C‡inæën çÀ÷ ÏŒÌÖfVܼ~6œ˜ü”KÕ~ Xû—w>ìˆ_`‹#¡@:­“ÔàZIº•öÕõŸ˜ÄJì4~>7•¯½¢Q|ÔúkIDATÌ¢`º÷ÅׄZXñ<çM(KÑSRs¾Ž,7·Y?‘\øÂÛÌ®&\]IЛ×φ/¨ò*PChÌýó§6Õ×÷À Ù¶ƒõ]*Û™PBºh¤t=¿\Ðý§4}/ßè0ý÷3óª¡)>‘FÏ øÒ«ÒmCýç¡ïÓ£>s« 3+n^?ŽO½”Åù5 9÷ËOnº©óÁ`Àõ¶ÛË[?sä°ëî³ÁkÖ&,< <õYAh:$§Èvz„œ‚o„£s«i¨§7gΓS/‘Úüé–Ä[êã? ÀíXßbvלÑmϧ3<Ý ÈHG ±‚Š1[Ë“6txžðÔÏܪåzÝ¢7® '¼¨N¿£°L&ü¹v|Kêô€÷ƽtÍó‚€'y«Z–3èË?tÍ,§Šg LJ<æ– ‹Þ¼v6œ:ò uî5Í2|³ÿô‰mõò`7a$ýU(`}™8Íö%)6!ÿ4:1¬ Åa$‚FËQnæê™àÈÔKªÝª^ Áîf3ɶ U$ð0…(Å›†Ôdyõ>Ajó³™ß¶ÔÅ^›9™þ4i†¯N¦ö%Ï"jê_h²ë{àŽPESÊgþæÂ¹µj­ ¤|‰2á[Å^›9LM½ˆê«ŠÔ€UP»æ3%5-[«€ÜŽlªHècJÑN’ÎÞ|µ#~ 4;–zöêÕ3Á‘#/`ÝkôÒ»{¶aÃ6ƒLøÞ@!»¿É·õÝM·Žwùí@0FBhv\ªö¯^9NO¿¤Î½†È JÔ"’¶·ÛÝß®g­þÝX/|¸sMpÝÑ5óè¤hGXýSh]‡ñ’à)¬ÄJråê™pú‘Tµæ¯mãòÌm‡)lÒ½p78E¯Rì‹ß·p é.á±AZ© `¡ù–ÒzÓ1Z ÉÌÌLøè#ŸDõ5¼°“ìBËà=q@€»À”#¼JÞ°²ÍÉj•J:—SNL>m0,]¼|-<2õ󨾢²÷6=|€;À«”Ò ŸË‹z[Ž Õ´È+q¼íKà†·ð™9}ùšLù¢úu  ÒêÚ|ØÂ"Öíã@kö$~˜ ¶.|@Eqâ°‹“–Aê¾Ê ÂÐÓ†U__»:0ñ÷ |hѵùºíÜz  "h1Jc8‹ó% zyûmž6ûkEiˆa ¡PŽäK…ðmʺp~>ùZâô‚Š´Pm’5‰ïýœ_‹‡›ªØ(B‹EL¿ºÍWžî V=ÚxÔ$àšijˆ–ùºõ˜‹5Z(-î£Í_‡›Æ„a¶‰Ä.CP1Äê±"N 5 +tbXuÐTG ÜW›¿/²Ù1{5ð $âÑÄàQQ/ýIÒ?[ƒ*{´døÞxx p? (‹+és¹Ý¦ÚMïdßo}€=ÅAøã€9ðã€9ðã€9þ?´à” :f'IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_replayall.png000066400000000000000000000240401217176075400255570ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíidÙUßçÞ·äZkWuwuwõ:=Zf$[¶l$#A€†€`•À€–Ã`Ä`„$‚p`6¡°#@þä ",³ $äÑbkfïéê®î®^fºª²ª²*3ßv¯?Ü÷2³–îÚ»{fê?ó:·ª¬Ìw–{ÎÿœsŸXk9Àë^ÿ‘âî=þÅß;ÐF‡µçcíí*ìÆˆ=p‚·9r%ð½æÃì'îµÂ½Z`€Hqò°ùs{±Ö""òÈ#~Ë;ÞùÎ0ÆÖPÜ+áç ÜÓã×»#èžv#"‰RÒþÜç>÷é‹/½4…;9«NÐn—q±Öò~ècqœÚºKÀûÞ÷Ãf©¹D½V#˲]iÔöžçÑ\j¦ËÍå§{ºxäþÆ‚ÎÒžàíAvpß!"Xk‰¢ŽdY¶¡õ﫲€8IXZZBkM¹\Ü{h­étÚ¬¬´èt"òmÏc²U  Úí6 Ôj5>ŒR cöÔëà.D„Û·o377ËÀÀ Úóì~…ã]”Öxž‡ïûܺu‹¹¹9NŸ>C­^#KÓýùèBkMÇ\¹2M³¹Ìààårc "j]ô¿èWëiÏÓÔëuæççxê©orúôi&&&0Æ, ûA)Åüü<—.]BFGQ­V)•JÄqŒˆöQ,`E ¾ïS.—QJ¡µf~~ž .Ðh48þ<¾ïd {­5Æ.]ºÄ7¨×댌ŒP«Õ‚ß÷I³lß™51€ºïûˆ:_Â0äöíÛ|íkÿóçfdd„,˼Á.Pœßf³ÉÅ‹/Ñjµ;Äàà•Jß÷Ýù×%ÒG—í-¼µOîÈ÷}”R(¥ð< ˜å©§žâÔ©SLNNæbá ØÜ­ÀZ‹R áúõëLOOãû>ǨÕj”Ëåî¹ý=¯ëz‘hqËïûÌÏÏsåÊ9wî!*•ò7Ø´Ö$IÌÔÔsss 344D­V# C<Ïë ÿ`C(P¸)§=E(–„o|ãëœ;÷ããcâày ¼øâ‹$IÌØØ8ƒƒƒ”Ëåû"|ØD ·$ˆø”˪ø¾ÏÜÜÏ?ÿ‹‹Ç8yrÏó8ƒ J!À•+W¸|yšr¹ÄÑ£ ¬Zï {/±©Àú%¡_ ܸq¥æ"çÎ>D½^ëyƒ{üeDh­‰:U.dd¤›âõ ÿ~`K Ð"@,<ƒ CææfyöÙg˜œœäðáÃŽÇ~zKoùœŸ›cjjŠ,Ë8|ø0ƒƒƒT«UÂ0DkÖzÓ÷ÛO¬R€þ2áPhªçy}Þ@> \¾|™¥f““““aˆ5æuWÝ×9}~ùòe®_¿N¥Ra||¼åÖÞ*«¿_ñÓ¶=ô” øJi<Ï' CJ¥ssó´Z+œI7¸ëÿPÅ}c J)‚  V«ÐhÌséÒ œ8qœ°T*~iO¿Äý†(E–¦\¿qƒ—oÝ¢\.322L­V£T*¡”ÆZK–edY¶-Ë·Ö' I’h\_`ÐPˆlÑ×¹ÝϾ¥ÀC§Ó¡ÙlEI’tÓ½µÊ`¬!K3¢(¦ÝîE/¾ø—.Mqtb‚ZµöK„8‰¹>3Ó­ài­Y\\¤Óéì:·÷|V«%NtT{ÞY×$ H*B†á²ˆ4E$Ý®lꌵ´;®]»F­Vs%c6qMª5‹µÃN¡Œ!NR<­ñ|ïXûöApæìÙ}^¬ï{ð=¡Z­©O}êS¿d­m‹ˆ÷¿Ø°2==ýä?ðþŸ‰¢¨ l«R·ÆôŽ&Ëè´Û$IÊä‰Ap÷,aõ?}ÏÉk4´€Üa]·Åÿ»‚ˆˆÖz|áX‹(ÁÓzÎZ[Ú"b¶ã6ð«û¬µ¤iJš&¤iŠRê5*ÈI’lø|¹\feeÅXkCvP‘[ßb¼öȃ?c q»_R{Þ›x€m¢H#£("Žca‡sk<Àk…[Úí6ËËË”Ëe†††šFïŠÖ±F£A©T*üõŽŽÕ¦¼,‹§DÏóHÓ”™™._¾L–e÷Ê|=¡`^SSS,//;:Yì0ÔX²A˜ßWâj•J…4M™››£ÑhpöìY†‡‡zöJiŒÉ¸rå ·oߦ^¯w{´§w<3¸õj v °x¥„¹¹9ž~ú<Éää$"rPÞxžG³ÙdjjŠ8Ž¡^¯wKÉj^x“4Ðvï Îý(å–×â±°ÐàòåË,,,pþüy*å ivÐB¾(‚í™™®^½J–8|øH·šX”’• ;j_®>u ®[Dãû u¯9$BfggùÆ7¾ÁÙsg?èÚ%´ÖDQÄÔÔFƒááa†‡‡»uWsq=›Ýá¾`M °Fü¶H{^ÁyGm†a¯MÌó<æççyö™ghLçÌ™ÓxžwÐB¾MÞìì,/½tka|¼×:æû~·¿Œêj°¸ß©i4J¥7o^gqi‘‡ÏŸg``à@ ¶kmwF`jjŠ™™jµ‡R«Õ»ÝCE§ö^a}9˜õÎäNÎeuÓ¨ëêo!ÿÆ7¿É™3g˜8zà @¼Šó¸ÒjqáÅY^^æÐ¡C R«U ÃÒ¾5Œ® ×A뉡µ¾×àÐß40??ÇÅ‹YZ\äôé3„ap kPœ¿[·^fjê"J)&&\èë òà{º…7M·Z®^úçdõoïÁçÈovŠu=ÆÅú}ÏÝÙ#ì-é ÝÄq±÷À/^¸ÀÄÄÇPâ6§ºjàÜÖšNÔæÊô–––îîò†!žï£û‡A÷ã“tÝñGÏV¿ÛEýF¿k@庎‚ ×uäû‹‹‹¼òÊË4›MN:M¹R&MÓ{O#[Šiæç癞¾ŒR‘#G¨wsû¢n¿ŠÕÛ‡ófíîx“uA ½‡6¿1\Z¤”F”P–J^bö)•ÊÌÏÏóü ÏsüøqîNÜÞ+xž‡µ–ËÓÓ¼òò+Ôê  wé\Ï÷P¢%Ü ÍtÒÙ£% ÷†ë;°7iàV XG‰„«N¸|é gθ>ƒ(ŠØ3Üýk}„4—›\¼x‘(Šq^¹B†ø~^Áë»äϾŸ*cveŸ[ïKÜ*Ö¢”&ÜfÖ«v/-QÏžellœ8‰ÉÒ¬/†Ù­*¸÷ñý­×f®qíÚ år‰‰‰ *gõAôºsïñä³vSU_?²QXÔƒö7¸#Ü9UxZP%É;b"¸Ù„§ãìÙsh푦I/[܉<ò¢—(¡T*ÑZYáÂ… ´Z-FFFò-_Šº½Ö}cy÷:Å+„³C½ÛÔXÓïö÷' Ü Ãr»x€» E’&¤YÆK/]ä…^äío;gΜ¡EtÚm°²-£´Ö""”Ë%Ò4å¹çžãÒÔÕj•#GŽt÷û)•B·<)åª}½wØÛ/¾µ½ã_½ãx¸Íߨbò”k¿X€-¢à"¬Å‹Éo­…,MÛV.3;;‹µ6§’XYYîÛ–åNšÐû¾žçS«UɲŒééi¦/_&Š: ¢=¥t_§Ž ùà¬Ýª’u'möf©°Öìõ»y,ÖXÒ4£Ýé¸ Fܯ50Ö;išÇq¾eÍ"K‹ ŒŒ óÖ·¾¥47oÞäêÕ«\›™áá‡Ï3qt‚N§C»ÝÁXƒl ·ÙU¥Z%ð}®\¹Â•+ÓÔxÇ;ÞA§Óq›a..øZ+DÀ÷}@ãÈÌÞyÍß±t_DÀSŹÞ9ÜÛí•°@×å’4¥Ýj£•Â÷]uîžz€\±`Œ%M¢8¦ÝjÑXXÀÃùóç9rô(v‡F£A†9z”ÅÅEž}æYnÝz™ócxx••QçgÍív&JQK”Ëeß¼p¥¥%‡†¨VÜfWÇ»­p¯]›áæ­[$IÊàà ¥r™0rϸ6ªîYȬ%I-qjQJȲŒVl˜òލ8kvg«ÀXÇf&#I’$fpp€¡¡!f®_wqÀ=ôÉaLFÇDqÄrs™f³ÉÐÐgΞ! C––štÚm”ÖîB ¾OT*óó|å+_err’S§NQ­V{ilÞ›Ðjµxî¹ç˜¹~R®@Õj•r©ŒÖÍæ2ÕZsãð‘ÃL]¼Äìl1¡[_5§G¡}È tÃrÛÐI,7b>óÕåÐg¸ ~ì0¾ÞY[\Ñ£±StÀæ¾(K3Z+-<Ïcâè¥R‰—_~ùž¶kõÖz·ãXÇ´Z-–––scllŒ¨1?7O–™Üó¹íj aR.•i.7™™™á•Û·# Ãî¶v+++ÌÍÏ“ecccÔk5gÙý¹8%Iâ„z½Æ[ßúfff¸víív‡Á¡!*9ï_Ôù»  …ÔV"ÃüJJ”Zþôë dâóÓß}’ïÿ§¸6ñ[œD‹ÙíU]Ý]A¸P4K±‰¡^¯366†RB§ÓéjØþ;Ûµzk qœEn{º••FGqêä$Ú÷YZZ"ŽbgÅÚU ÖYµÖ®ü¥rH½^£µÒbvvÖ)–1è<ìoÔ»ýy^ÎæõÒÐÌd,..–Jœ8q‚‘‘¦¦¦˜½}›ú@z­N–rBHç"$™¥g,¶3Ú‰%Îà3_~™w½q€ùîÃ|ê³3|T_ã7ô8Zž`‹j°Kyt=€1.Ž=|ä0Õ|ˆ$éóÞÿ4°kõÆäV¿¸´„VŠsçÎqèÐ!ü5°9A´ùú+ Öö•\«Öº{ÚœÓ×Zã{žïái—ÓK¾Õ›]ãÌU[¢N‡$N¨V«<úè£Ü¼y“k×®GƒƒC½ÆÏsKXæÖþVlXNm#,·S~å¯f9ñöS|Ç óÕ¿x‰þkü‡÷Ÿ@o£KÚ§Ù1åÕ‹S­Vˆ¢¨ï ÷ý1öAü}^7öˆcšËË´[-FFG9yb•wÕ&iŠä-Ww‚c‘¬ =q&ÖÃ!™ÉV¥bJ\R)AP¹µ;î`ã¿ Ýaååe‚Àgbb‚ááa.]ºÄíÙYêõºKKÃR¾³‡f–(µ43Hµ&<ÚçŽsytˆWÞýÞGyò3Oó‹¿7ïÿócxÅàÌ&’uåàyÀ)€ò«…–°Ö®êM‘îöð{½t¹ë¶Qã˜v»M³ÙDåV?<ÅiµÚ$IÒe §§§i4(WðÊ$©çRAÑ«6uÐþ6,óOðQ¾ð‡Ï/þþu~ãG'r%¸óGØ@DôùóÿÙOüÄ¿X\n6‡¢80YVÊL¦1:MÒðÃ?û³ßó–G0»¬>õ*dn½O'ü¥æœ;{–¡¡!Úq«…e¯ö%”5·½¶ó÷4ÍXj6)•J¼á o`vv–«×®Ó^‰éØ i⓪b7§Õ §Ú|9¬ò­ï{ _ø£§ùØÿ¼ÉoüÈÑÍ•`T g­µ"b/\xñ¹ ^| ¨ È?¡ ZËÛD˜ØMP¸|“{E ·Òj148ÈñÂê—{ôíƒÔþ·ŠÕ£Ýn“&‰›ô­ðüKÓܸµD+®†¾ó74†jV®ïzï£|á3Ïðñ?¸É'øHW ÖsL»óÉÅ`ò5?€Ez*ªƒ Ã0*rÎmÿ¹üz»‰§DQÌÊÊ Ë©“'Êc€@±÷Ý«☾ååñ™—IS—Ò¦¿’~›Úœ *²‹Åd™«(¶[˜Ì0ql‚á¡!Ò4¥Ýqkýkíâë ô5ŒH7Újtë ,´áïÊU¾ý{ßÀgÿø9äO^á×~p _õÊä;Å– çÒïÎ}ÅefÚíÕj™#GŽ!QÔÁ³“¬ûU ‹k(E)”d½BÑ&K@? OðÕJÇ~ðüùŸ¼r›_ûþ1|]d;Þy€þ/MSÚí6Yš2>~ˆÑÑQ²,£ÓiäS±¯#HÎÕ+…º^a;&à 4ZðµJ÷|ÿøó?}á6¿ú}c»2¤­)@yn(þ¾¯àòÛí6a0yâ8aDZK}^ëî~8Y«nVÐ}N‰s¥Ûhëõ€ùeøZ¹Îw~ïÃüÙÿº€þß ¾÷V‡UÁ]8b[ØžX§½Ò­³pwE±ÑÑQÅC¹«Œ¼…«A%‚VÒËŒÁ¦›m=Œó€Æ2|½Rç±ïyˆ¿þË+<û’P£çBåÍZ¢…øî;b˾ØÉ}õ&·ú8IX^^F)áäÉŒ‘eY—íŽùïÝJ7’é;dõc×±ãîkí â»Qø45Ølû‡6sÍ„§¤Æcï9ÉŒ=ö†ømþhððcA¶2¿­¤`Ç ¨ÝÇqLE 1>>†ˆtËɯ¦k ÝÍ?ä›íÞwVÃ…¹õÏГfw¾|­ ²|ÏÃ5êñ_ 5$Cí€Éñ1Ü\ÌøJ­Ìw¿ç”üÕßúº1x¤SÿÐ}¸ùßßoõ}¶¥EÿYAçv:”V;vŒz½F𦳽+cÞkëzôœ÷rÍš™±dù󙱤Rã:wÒÌK’¹ÎžÄ@’’ bcÝs™%6ôîgÅÏ¢ÔÒI,˱a%±´ËO¾cŒŸ~ì8W¿™ð\;Ãßáéò±ÜX4|µ^â[ßy”¿ü›ô_5šÙпùú ÿùm_fl ¶¡.½ËòÍ$Ž©ÕjŒw/bt?±Î†î`TÆBš ÝY§Z!ä¸bj餮‰Ã ѸǙ%JÜk5¯õ~âÌ¥e¦«8XÐ ~çï^¡Ã…Ú^­¼«jžÜXˆ1µßúÎc|á‹×_h§ ÿü7ŸhüÖ?ØT ¶Îä.¿Óv=‚‡fpp0oÛ’²íú]ð:_¾æqA¡fVÈÄ]f3ˆ,1B$–H ¥…¥ƒ¡r÷­¥mÝómké@þ3ù!ÐK¤,e‰ Ä bzœý K]-Q)î~²ÙÇrk1†Z‰öŽã|áÉ™ÇÛÃ?ÿÔÏ5~ë­wµÌ­(€`cŒDqD©Tblì¾ïßw«ß…6ÜÉ­ŠûGˆ-Ò4A)PTÚ€Ö ”Eû RP¾Eg 2‹JZtæžó2ðRðŒ;ü,Ú5 ´¼µ„-¢ÿ´vûð°Ü\Œ±õwþ“cüŸ/ßx|¡“1ü O=Ñøo½£…n9J3™adx˜cÇ&º[ž>°Øòù´½-.'/ªlÅ€LV0›“åGÞ-e2K–Y²Ìe“LâZÙm’a’ §ØŽ$˃Žnð±ËÃâ[ÃÍ…˜ç’€wü㣠Vôãif{ø£ïßé lIŒÉ¤Z«144Dš&÷tF`_Ð-©²Aù’þ‚FÿÍ·ôÈœâçŒ;¬±Î d³ƒTogG®‹1/&>ïþGG(ëÇÓÌüöÈÇžÞP ¶ØRúJ Aîje?°*€»z€Ì€2m¬£e YÄXgÆY}øÖ’X‹Æâ‹§m,PXWú· ¬Í·ÖqJÐ}ß|x•ÌuîÞ«³æ3 1zÐç]ÿpœÏý•Ç›±aäãÏ<1ÿë¬rÝ[Q«µŽ¯ÍÌ\ú«¿þ›‰v»­Ó4ÑY–)c2é‡î—RHο(D°®òvg È2+bR+d(IR«$³Š‘ Eb•t¬'1Jb«%¶Z"«H¬–Ø*‰p·‰U[El•¤VºS”¤IQd&ÿ`÷°üåc™ž°ƒßòÖ1>ÿÔíÇ;©±#Ÿxæçæ?ÙSÙÌšED‰Há¡ÌdG¬1£ù¥Êk­¦÷­îGòo»ì›¨âÚv¦÷ÚzHPÖª< %¨j +Zª'¥ª/~YKXõ%({â—| +¾”JTBñKå~)?Ð¥’ø~€BÑ^€öK¢½å¢=¥Dû(å‰(Q>Jy÷þ9.ãĠǤNøÊs ¢ÌþW­å‰ùO>’Â@Dœ×ƒ(á¼L±-ÆÀúä!{q޵AÉÒ"#Ç´7vÆWµQO*ƒ¾*ùRªV| *åP¼ÐÇË*(WÄ +h¯Œö+¢½2JWDé J—AWDIQù!!"%)„@ˆH€ˆâs_Εã N xL茯]X 1ö¿ˆð‘ùO>o)°Öf"b®Oð~Zý*HPAÕÇ¿ŒT‰øâoï¸ÀÍ;ù6Ï›xc ÊuO‚Ї_ D‡žˆòBg½*DT$JeˆÊÉå¾"ot‰¤Aˆh Ã’¹кh à‡÷wy{¸:ŽúLŽ•¸p³ý¯=-OŸÞT¸Öu)Àý¤~ý‡¿]·ý0"V$¬¡jèj;)XÑ¡ bqÃ)ˆFHqñ¢aIɹ"°nz¾:Zãr7žÓË)×ÄD{4ox®×…«‹´…æJ ±A´€’S°í† þCï¢öÿ© âddœ÷÷rÝY–o­Ú×ÚTDð@^ºÃæ·k^ë“mŸP×ÊwÝë{§ob.iâ%h´R<­n`íïëXü‡ÞEýÇ~´‡í4A‰“© ÝL`} ÏÏ7|±ÿ9[Ä«±ÑÉî®Kìõ›àýóÆÀ¡ªB!Ü^I%/cù‰¹_{ÓÓ°ãa»û ÿ¡wSÿñßχ,§£û×ÙUÎú£[Íߨ£¿wOœ‚©MÚéÝ¿k_Añ3jÿD0²‘ÞÛIDATã>¾VÜngˆ’ÛÀOƒýüè/?çÁ«ÐçßMýÇ”ç„/½V«Âøîfp¢¶7nf×ݹ dû¾ç6š€v ­k´7–RDdcŸÀÚ¿Ì$ƒW™çßÍàû´M£®¤uÞo—YwîÜ+/Ûj˜êäzq× º½Ï±dÖrlÀÃáÚR‚(™Å˜XkÿHxîWßdáU¤áÃïfèŸíC¹ÂzOåÞÙBè §h§wØk'Wš­,Ë«b·­(À½ÓßI3×(²§‰´uFpbÐÇSp¥ƒ0‹±±Æ~7æÍý꛺öñªP€ðáocäCŸîYþšV3-à)AánOŽzt2×Ù³v#‘’/hÕ‹ÓîV5.v`ÛŽ¡öÇýcUœ(°’^¸™bÌÞL@[G>prÐYþ¥F‚R2Kf?b ŸÅq8«„¯ÏÃøoXñ ŽÙHdb-‚ÖÀ¢°°b9÷°Gª]›V¿V}ÁÓý[ÀÈz+Í%‹9¼-0¦}%]Îhõß¡P±²×f[,EfO’c…SCžÀT#A³bøˆ±Ö _ˆæþý×­Œ°áùogøÇ> ÆÃ&w²× AY±Ù2Â+B: H¸ÒŠé$9%˯âÌ‚íõƒä·½Ù^‹Æ5ðjåhp-î\嬎`+ŽðmþØZ‹ €ÀÝ'èïV’›BårHvÎGŽÆ»îËÝþ©a_àâ|‚¹-™yÂZû-,Ñܯ¬><À a•ïûOXlÔÏ>¯‡É€LáÇ`«0~FÓ´í¼æeM߯‹X„¢ËÒeúòqxKÁCÊe ”ß–)Cþœ»íâž+YkË ¡…K mFh!Œç9´øu[]&âxÍge››Y¯Eœ*„#Âm1ö ë,?ˆfåá;ªØ«ÅÊi³t³´ÖˆÄ‰¥ZëW…WbC›+Û‡r i Yÿ¦ë{ N± ‡½ Ž~/àáŠe>H€Å€2B›Rµ©”HeZޤG³ïòF9f$Úy Y8 ÿ¥ù5+Æü[kì_€Ä`£Ùwgáí°¹wkÈ Yfm–XÒœ´ßi¦•7ödôz~ .…*– }‡Ã- ÖÃØ„c’XÏó”W}D®Æ¾=¶Û»nwwçoë„rÈÃËKó.ÕSÆ~ÄZûYÄEû³¿|~Óø`+Àöaa÷5êÌ@œ›ç’ÑS€âí‹4¤Pé;ú+kñ°ÔÑbE4š! $s{\ âö¾aLj|©FŠR2+Æ|ÄûY›Gû³¿üЖ¬çµ¦»F‘þ­©XV+[¾/xxdVSÇJ;S¤¢\Š Šmijñ!&¼\øqíwóüB4ûK[>(Àf¸k¹hS¸Њ’X\‰*CõFÕ«-lé“XŒ…ã–Ë )"rE¬ýkø…åâÜ>Î`[-ä$ùý }E¤M`-ÂѺF L/¦ ˜–Œcì‘èöÇÏl;¡TÑh,×—3è ÿK,ñíÞ1•t { ø‚²†ùÈ "Óûakí—‘\ø»¹`p`×°¨rˆxzóæÏ~†*ß6f£Rä` PÆÐˆl.|ó3ÖÚ'Ž@d÷Àò (À.¡Ê!âçÂß,£ëwùÂ:À¹ýU¿Š1OXË—pÍ1{(|8P€]AUú…¿…þÚ^ƒ@þ«V„OœðcƒW1æ ¬ýyªÇ `ÇPÕè<žÛ*ŸkûxwÑJ”`2KÝw–¿rÕZû–^´¿‡Wi[øý†®•P¡×5è-VQ _´é:„*ÊÒˆ ÓX>Œµ_ì|û$|8P€­#ðt½Œ„ùìá–¥Ÿ|.Œ3‚‰„•¯Y–¿l8â )`E.»<ßqûì£ðá@¶k‘ÀCVv&|qW·©@$V¥BrKH—`ð¨0>¨h&ö²Âü–'ZöYøplk‘ÐGTò€í#cw},CJ¦SRé`¢) "<ü¨Æˆ½”¤ö'ÅòU낽} ø6ÂØÅ^?¤äã VºëøN.lf¢,OÉJ ¹,HR=+H].<;û)±ö«È½>x€Q Ñ&çõCo·<!¡- jƒ¾zrè;¸˜¤³Ëæóíľ Blí½>(ÀjX‹ñ}lµL—²ßýh·!E±¬Cny¡JüP‚ ÿ7SÌ7RÛl¥´qëºçÛ¯(@?DHK»¿‹í[×Àµ¡kV”Æzš¦¢T IŠíHFG©d÷^øp «!‚Õ[àô·ƒ"aY|ZÊÐXeÈòrî>ïsg(À=‚€AÄZAPÉw¼ïŸëAÛôñ÷ÿˆEÓ¿„r®<IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_reply.png000066400000000000000000000230731217176075400247320ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíyŒeÙ]ß?¿sî½o­µ·é}ïžìñ8 ØD$ã066‰’(äˆØÀ{L`p”DŠ"°Á$Š c!¢lgì±Û0Ó]=KïU]{½Wo½Ëùå{ï{¯–ž®êªêîq×·uúÝw_½»ý¾ç·ß9OT•]<º0úvñ`±K€G»xıK€G»xıK€G»xÄámõ""Ûq!»¸?ÐU‰¹×DˆUuÙ¶ØÁïù w±n¢ªqþFDDUuÓÈz¼cìû¾ïýuddäH»Õòã$ñU5ü.¨ˆ¨gmä aµZm~ùÅ¿rùòÄ‚ªê½š£àÿøýØ/ïßúÞ÷uÚ]Te7­üpBÏ÷u~n¾ùs?û³ÏLL\ú‚dª{SPU«Îüj¥BàÙivñ°BßóäöÔm»Ü¨ùþM 7@!ŠBˆãø­¿´‹‡"BEš$ÎË÷{ Dâ8‘V«ƒªbÌnDù°Âƒ1†N§KG új[ EDètÚÔëuFF†)—+8çØb~8 "Xk©×k,-Õ(•Jd†ºg­·ÐmUžçE×®]gjj*=¨±wùî.vÖZD„k×®ñÚk¯Óétð<k „‡[ÑjŒàû>•J…$I¸uë‹‹‹œ:uŠR©´ë< xžG«Õbbb‚f³Éž={¨V«A€1†, ÷ @ÅXõ}ŸB¡@µZEUYXXàÂ…opòäIx çιm»¹]Ü"‚1–É©)^»|k {÷îchh˜R©„ï{“j†[J‹1jŒé1˃çy,--211Á§OŸÁ÷}’$Ùò îâΰÖÇ1LNN2<<Ìøø8CCC‹E|ßÇóüÌYß.³.|©Tƒµß˜››§V«qöìyÆÇÇH’d×AÜfˆÆZ––jLL\¢Ýj±oß>FFF¨T*”J%<ÏëuPÙ »€•$z۾ﳰ0Ï7¿yãÇqìØqŒ1=m°;ŽtoÈ;‘µUåúõë¼ñúëAÀc2<œªüB¡€µkS§Ø˜‰ÝväHOnð<é±6Õ…Â7oÞ¤^_æÜ¹s™IˆQUvÝ‚•PMý,k f“×_{Z­Æèè(ããã½^ïû>ÖÚ»ªüÕØ1¤V¨#c 6Ósss|ã_çÌ™³ìß¿×/Xyožº=Å›o¾ ª8p€ááážðó^¿•+õì¶ànBŒòü´5ß÷˜çâÅ‹ÔjuŽ?†çy»9ƒ ÆÂ0äÚõëLMMR­TO³z¥R‰ 𼕽þ­d±Þg;¬úlËŸ³´Z­b­‡çùÔj5&'oQ¯×8{ö,Õju@ÂHªò¯_¿ÁíéÛ U«ŒõÒ¹©Ê÷0&ÕÛB€’ 'çiÊ~”P`zú6˧Odhxý®3,7»T«qõêZ­V¦òG)W*”2GÏZ‹lsáÍ}7«1èÀ¼ÌÏÏñêÅ‹œ8~‚½ûöbDpêzêòíÔJÇôômnÞ¼‰µ–ûS/?Uù…*?¿í{yæÄ Üú~Æ ¹6ð}–yóÍ7X^^æèÑ#ø~€âø–(@h·Ûܸqƒù¹9†‡‡ëyù~àõ=ÙÒo™ÊÖ4À $ÓAÏYô¬G!˜ŸŸ£ÑlpòÄ †††ûšàíˆÔwcqqë×®†!{öìIU~¹Ü‹íûQétk·¬ª¬ö ¢7–`-Fú>AøŠæç¸xñ"ÇŽgßþ}ò¶›‹ "$qÂää-¦¦&)‹‹‹‹\¼t‘£GŽpðàA”,qô0p ëÖZ’$áÆܾ}›jµÚ·/–Šg=Ä„UÂß‘kZ‰-@W`ç®\T“Ž,Sìù¾ï³´´ÄµkW©×ëœ@¿÷o1<Ù $•†µ…âJ“°´´ÄÄÄ%<ıcǰֆрZÝ)6äãB¡P$ C._¾ÌÒRÑÑFFF©TÊA€ïýAœ¯ßç—Ž¬ÄÖ¢€^XyC±4G #éWy~šA¼}{²7²X®Tèt:¨Kà¶s »õ4{033Ão¼‘âØßËãç¥Zë:z0”½wHjOÖcÕýC:Â÷AŒÍ”ü´ôlao|ãÇçðáÃÄqDEýκÅ3ç÷,…B@œ$¼òÊ«ÌÌÎ2:<ÄXV­SÈqUþÎÌ;_ó:u‹y€l(òÒ¤Ùcƒ/¹6ò9‹ \¾<ÁôômΟ?O¡X¤Û ûuV÷ER $Æ055ÉÄÄ‚aÿ}ŒŒô3zÓ±HwmæŠ _›=½gäÙÉí¾“~ÏÚĵd9c-~®}  CÃ1q’099Éo¼Á“O>É·½ã4›Í{"‚jÚ  ‘$ _ýÚW¹pá›ìݳ‡C‡Q,–  …â}ÍèmÛV¦€º$lì˜÷B~HÚï\š‘T1Ö ‹ \»z…ãÇO0:2B£ÑHCFÉϸ2ûÖ÷ÍÓƒŠåÌ‹ŸåÚµkxÖã©§ž¢V[¢Û ÓJ&çH\‚ucWçItųeà²èr«Ô)±Ó,FîÞAS%äpª¨sDQD·Ó¡ÓéP¯×‰ã˜ÇÏŸcÿþ4 ®_¿Îµk×9sæ Ç'Žcš­V*¸Lµ;'dàT«ºÝ..\`jjŠjµÊÁƒ9pà"pýú jµZOÆZR -âÈíÿƒUk;×–£€-™³Lûž0µáœR)Zº±â!ðßëÖ@d'uêPçˆã„( {‚¯×ëT«Užz×ST+–––a|Ïêµ:—/3=3ÃãçÏ36:J»Ý¦Óíà’B‹à[r¹ŒçYnܸÉ믿A’Ä8p€J¥‚ït»!ããc¼ûÝO33;Ë›o^aff†ÑÑ1Ê•… -Û66›Ÿ×W9÷ŽmÖ½¡à{b@ÚÛ ¾ð{_œçÅ×ZÔ›1ßÿô0ï>YƈP-ZªEÁÇ® ›rÖ%1avCZí&µZ$N8uêG%Žjµ:aS,±ž¥à”Ëe—øêW¿Âá#G9}êãcã+JÓŬ1©3ùÚefdd?•r×ƦœQ±ÿÀ~ÆÇƹrå ÓÓÓt:%†‡Gfèæ9ƒ¤)íˆ`³| ¶¬Ë«»_‡¥¢á×ÿø6Ïn’?øÅ§¹2Ýæ?ÿïÝ{˜‚o0Fð=‹5ŠÍÕj&|çI’…!íN‡Ærƒúr:aâìÙ³TÊ–Ë´[mTÏ÷0Ödãì~P,h4LMM177ÇýûÁX ªÄqÌÌÌ sóóøžÇ¡ƒ‡(WJ ÙÄKÏbELzqÝN—…hjµÂã?ÎÞ½{yóÊ›ÌÎͦɠœ4¾±Yõoö0î t ¥ØšpëFw¿ R4üÆŸLó+¿“¿÷û9Pµ|ôwow–»J”8 žP ÎSŒ¤:Câœ#Žc°K«Ýfii uÊ™Óg9tè Q3¿°@ÇéC6T‘¬ÎÀ ¾g³:ƒ"•J…F£ÉÌÌ “““ÄI’åò-°oß¾žó7˜Í3¦Ÿ¢Fœ*õzƒN§Ëèè(ï~úi®^½ÎíÛ·évºŒŒ ãœKáY„¬¬û>8ëÉiL€Ût R°|êO§ù4͇>x†úP™ù‡·xùòOŸ¦“ªŽ0’DS;Ÿe“$!ŒBº.Fƒz½ÎØØ(§OŸ¥T*²ÜhÐívUkåã V1F°ÖdI£€BP.Wˆâˆ$‰qIº¢IZƒàá{>žïõ§_‰I ™sÀ¦§©j%Š"—–(—Jœ9sšññ1®\y“ÙÙÙl@¨v0 Y\\$qnUÒ¥éý/¨1б’¦]‚‹]F¶ÌÈ_°¦?æÏ±ë›ÆýªÐlµÃááažzê)®^½Îôô4ÝnÈððAPÀR³”×Aì¶]¤±7Öå‚á3ÿgŽ_}a’g~à<¯yŒku({àöUi ‰œÒPÁW%qŠS%‰c‰º!æ2ËË ÆÇÆ8‘ ÿ.7DQôçÒ½%d@ãªM£ µ8«Y(˜Ýi¥²Yå¹oLH" *ÄIêˆKEΜ9Ížñq®\½ÊüüÃÃ#”\‰ Ðl>v®à®ÍÙl½(ô.ÂÏ“…Õ¢á3_˜çW^˜âû?xŽ›'q} Y$NÎm„ª¦Â“˜N7&‰º,/×8{ö {÷î£Û YZªe³ŠsCºä:G­am7Y•$Ú4r³€Òi·‰£ˆá‘aÞùÎwpãÆ æææ£¡êPZìyØ?Ï/¿p›gž9Ë­‡˜X‚`ÅÝ¥LB‰BÅt; qÒ¦Ûi16:Êñãi`£Ù$Š¢TMoQm®HþÈê϶ ý9õåeŠ…'Ožd||œëׯ3?¿ÀÈÈ…bZhŒAŒ`¶i¬¯¨·^è”4Űþ£*Òžÿü Ó™ðriðÓ¯çsÝ爓ˆN§ËbØb¸ œ:y‚}ûöÑ CêËËiŠ×lÿØé—Ý"Ýn—8Žâ‰'žàÖ­[ÌÏÏSì¦QIî :“[íÐk³¶Û’ vwS)†ßùüÏÿá4øÀn__ø½K2i¨—$ ín‡å¸É¡CÃÇNcxi˜[7oQ CªCC~º„ Ì¥ÜüãØf JVjÕÏ/”Ão~‰ç^˜æï~ÿiæÏæâ7pµ x¾ÏØØ8ìhÉGÄîh|üÀÑÓìšiƒ˜á¡a*ç*Üšœ¤V«Q.•(•Êx¾ß M7›CÞþ<@~HU0BɇÏ|q‰O|nš¿óþ“,ž;Ì×7(|ÈLœâ$&&NÙn¤71ò[˜¤ç$¶Ûm‚ àä‰ã,,,rkr’(Ž©”+Å‚ôKÌ6„m7šÇ"P„ϼ¸Ä'>7˾ÿKçðµ9(nÆW3y©yîáç’7ˇÞw,þü&…=y÷jè²ú¾tEŒGA @ú)ÍV‹BpêäIfçæ˜žž&Žb*•Ô$Ø|Ìã.Lè)€Ï·œ ,ûð»/ÕùØçæøà÷§þx&ü{:šÉX²:º^6ìQ1+‘«w%\J’„}ûöQ­V¹uëõZr¥¿ˆDZañFa;'‡Šeùì×[|ässüÍ÷¦~î/Ï*…ü 6¬³%MÓO”0èã<‚ÂÄàp©oàsúô)fff˜›'ŠãÔA´±‚èúâöäl6Ð ô^û¿jK|Ïw‚'òõÙ„BVá°¹”y dYÁ~ƒžƒ´ Â0J—’9®|ëÖ$zr%u3 ÿ‡¶ŽP6NóN7Ú]îè_ûÉzaòÔ»ßûô^ü'ðµùß%hâÐ$Ùdsh’þV°’×WI6Ö ÈŠÆ›¬~/ÿîÃÚÒõ••N§K¡PàÔ©“ŒÑj7i·ÛÄILâ’´P¶ç©õ_WÈs³ˆ&þD«ÿìÿ©œû÷oß_’3ñå™OÝbõ„8Š92VàCï¬R´B1°xƤ¹/‘¹Fèÿ ½1ø|§ Ájþ~µ8øLÞ^‘FêXk9tè CCCLÝž¢ÙlR*–ñüté¹ÜŽ®³BÌæ 0ü_þ-ìûõ÷ûþ§ðåÙK^‰o/Ž…ÑÀðÓÏæ}G}>ý¥E®…1W+†á‚a¸h(x‚g/›h<›áZ#xÙko[Òjb+kß[›Žóé—ž›’ÉtG¶ýð"½FçÝnH¥RáÔ‰“Üžžay¹N¤%lÖšŒèºšÿ›#ÀÈOýGµŸú¾oß_r'öóÒL‚Å!›µù«`ꈗ¯7ѸÈåšc®éøæ‚â‡o¡`ߦ)áÀ k<¡`…Àƒ¢+¼ì5ûnà¥ß/x&}oÏ‚ŸÉ7Š5à“¾ŠâY¸cî}ÀÇZ[mÿ`EÆ>D­Vezfš¤“ôV Q]»Ö↠0ò³_ÿÑn”|êo<½¯ÝÇW¦#¼,ðØêôPPßò_¯D|ök‹” ér0 ø&zN‚\˜%/®o(x†’'}(z&m>=¡ä§d(f-ö”ÄbOœà¬¤¶Ò ^ºˆ€ÁiV°Z²«MÆ}­ì}k8çÃ0û!ÏÓÓÓ4[-Š…"¦`rYõ.uCù¹—´ºO÷»ö¼ûxév„'ù,ší°šé±†ãõÃ@²AÀ‰âŒâ²ª¡Ø’©ð<ˆm¿%6¬…ÄgA­ ^úŠbI]`IfLö*ÒÛ¤ç_#Øì¶uí®‡‚ab­åèÑ£ÌÏϳ°°@:­è°w%ÀÈ¿øÆ†¡ûôw?µ·P=µ/NExÙ;l»Ã”•cç2‡/HV9†Ót6B>#Á%’‘$mjÒµ‚ÔšÕªh^3¨r‰mPŒÛÅýD’$8çÒ–¨VYXX Š£ÞÜ…£?áGÂÈ}껞ÚS¨ÛÃn†˜lÕæ»÷•GV“:š\f’¾fóT2î²ýœË¿—êðÜÒLð½BÖÁ÷+N½ ¬½ä‡ ªJ†øžÇ‘ÇXZ\¹Dò_¿#Æ~áÂ? £äÓßõäx±rxœ/ÞJ…oî7ó„”Úc…Dúj8¯FRoÒ¦/ÜÞ{Å+ùO0  Þ=û^Ç1žg©UÕÝMŒþâ_üã(ÒOÇù±bùÐ(ÿ÷féý»@ š¥sb + Mëc š†vž€oߤ¯i„…Ü´©SXö ?&‚,"ðM &u<½¼ÝçûÝi”Ë•J²æ·ƒÇŸ}Eþõ·éøGþâ…±ûô_95\ª<6Ì‹7;iîí IPũծªzꜧV’t[gqÎ#VOóˆÓ¦Iâi¬¾&Îjì<Òæ"g]ä,±³.Q£‰ZոإÛé>Ñ£‰³šÜñ¶USÕâT‘4ë–Û›üO„O¨ù©EDED­1‰µ6²ž×Y\\˜Ÿ‘ôTãÂñþå? c÷›O.WÆŽðõÙÉÆæÜ*0šà4V\Œs1.‰T]¨IªK"\ÔÕÄ…šD]£núv5 »…::¡ ; Û¡v›¤½ÜqÝVDÔŽ [ÝvD·ÓiÆt1ÝVL·‘Ði&h+f-÷eÕvþ>O­ëªý÷ƒùÞ|;À<0t³}É€øËŽþæÙÇÊ•ƒ‡Fxi:„$ëùîÅÜš;01Æ„¢b´‹juÐ6N;ª®&œ¶Ñ¤­.i¡I[“¸MµÕÅ]ânK£NK£°«I7Ô°µCí¶#í6c×®GÚ©Å®±¹útO]ŽHÂ5¿g×ï*¢I¤ªNRôÎZãÁ©Ðsá;UU`üÙWÎ(òï žTî¯ðµ©.Iâ°Jï¯E¼åÑ_#!¢áŠÒ:@Õ¸&Ð¥…ºh§MÕ¤‰ºª!. qq—$‰4‰B;‘†íHÛ˱[ž‰»—þ<Ôβ28ÑtQWˆ\cV5î¢Ë³¸nãáxj}¬Öª™êÏ~íYˆ²óˆ$ÊmZþµU³VÛƒ;.¡©—~^"`pgoŸöþHr-!šmgD1ŠdÛb Æ’$ôˆ¤é¶’HºîSqIäŸúΈ$Z{¤±h2w×m£Íy4‰5ºñ ºÿï³kŸÑ‚Þe}ìJ"òŸTõ}ÃhÙc®ÇîÎÙ¾ Ý߈±A¤£X1©úŠº@¤‹ÐN·i÷šÐÚ"ÒZ -„¬I¤#B3ݦ›OB„³íì\‘X/¼Sl¨(D ;°‚&ª">á«ÿS—?ûÏ!‰¶póÇVëö$ •;ÀÏ‹‘Ñv¬ÏØvÌÁ²ÇT¢Dן{·!÷f} Y³ÑC?±³&ÃóÖ|œ~eÒc«‰×?-\6+"KSj¼ã†ô×XþýŸ¼o$¸W˜ùçŸT hø¨1òg˱²Øuñ <ƒ#'}˜ÚFœìÞŸmô˜Fҥί:·¢¹¦N{YÆÔùË /Ú5‚w~ˆ¡ú5°þŽ o;G©íSý˜5ößÖB÷×M89æsµÓvÇÇÓèiS§ÙˆöÛêeßá=² þAN¤Nà©3„°üû?ñÐj0ÿü“JjO›(o ú¬oä‹KmÇL3á̸OÑ7$ƒÑíN4LZ챉fÌÝ›5›;æ`sçf­ $b%/.‘¾Bé,Qxׇþû¿þÐj‚^MàüóO:z$Ð×q|ܳòÅ…Žãv#áÜÞßèj¼}M2mƈ½{c“Çl)yXÓŒMë q±ˆÂ„¨{.°ö“Óíä=b„'÷\œËH°MSôóë?Øãôx@¯ôÚ{i]ÿ=«·sÈJW1¯ñ³fíßê*‘å~ÝRÛ'Ú;ˆdŸ<Ãí™;¬ÆÉ!€âÚuŠïú0£°#$¸W¬Ñ9öüÒ%‹HQ„!1rcþMèøÎǪ–c£>¯ÌFt’íÑ xßT(8•$MÓ¤Èò*tºŠ„@›4|í ÚF{=¾ ´ZMÑ\3HS„Ž¢MAVh Íh®4RˆP¢X WCa´(4æ•Ë!C‚Ž)’(í¦~Ç.iÊ£t.ü!µÿö3hØÜúÃckàŽØó¯&¬EDªbÌùd¤úžÇ*GG}^™Ûsà¬RZòˆ¾h˜õ:”ž3š}¨½ÊÜH$%€ „Ždi_é«ÿÕ& ©Ù~MܶSm:GèôK©ð»"= DF$+›®?0æF‹†U7/Æ,L9¼ý`JªÍX íj°¦ºÆÿxŽæŸÿÇ­=¸üíöþò„E¤ŒÈ°9/Ö<ºŒ#>¯Î‡™9¸w8`¿g™ûZÌÜ+ÊÈ»dvø¬ÜCˆ§],¡‘¾ÀD$Ó„ $|m+Úø,Dµ“¤cñ`ÉBáô½HDH žIŒ¬L… °¯d‰[°8éÀ@Û9m;Åm€XmÌ1÷[ïõîù¹åØQìXùj•öIDATý•Ë‘2F†‘Çó|¤úžË‘Ÿ‹ ÝH×_Õ{#P. KÓŽð:µ=Ì÷=¹¢âæ(1O‘ºXÚ˜^J8¢/¼ÁíÁ–¬×$ûiÁÄ­¬‘·ë«1É.o…H `\Z€bb!l@«íˆÜ„Ÿ£8JíO?Nã¥Ooð!ÝÛꮇ¹Oœs{õµvz2. îYßšON·’÷"Âã{.ÍGt㌛½µ60ÅóRÛ,†]%Fk„:,‰G!¦ßSF×}Ÿ iÿ,)|#n5YãxÝ‹^w§,éȯÄʽ þ âÝÛêíĆ+žæ>~6ÙûÉ×SÀeq|Ü·æWgZÉ{8·Çgb!&ŒïM¤ƒz‚ñD"ŸØAS•5L , t$µë'àú^¯Aß•ܧ‰S ¾àIçf ØšüÕ=AÙÒPé6a³%oŽÔÉRÐË(ÏyVžŸi¹÷"1g$è&nóŽ¡Mf@@¬–¶*ˈÔ0Ô@»«"½µ#=k?[ó^²ˆÏ¹ôœ:6ÕWç>v&ïum…:ÊeQ>î[yq¦å˜\Ž9;æQðó$³©&Æ€ Xœx’_"ñ$Äa$·ýy»£‡•ÓX«v‘aÓÊzöÙÓ:ûÑÓŽ4´ª©ê%”øV¾4ÝvL6Nz¾Á ôf`Þ­åú4ï XQ±¢bŠX°¹» tWàwÁ=çòf?r*× uzåc‘ç;ŽéF‰ßËH°¡–åöô¦jõFXò曇}ºîÛ[JæÎþâÉ„´§êêžó,/Îu3͘£U‹oÒudƒ-Íךþ>“°e³Lö \»ØlùIÎþBJ…º*—p<çùòBG™k%¬|#éâOw5«Z~‰"ôÆ] H‘`WÁoÛÕ•òè ®ÊET?æ[y©9; {Ëk³¥]Þjø5_®GÓÛŸ³fM¢x»$Ø*¶S—&@[„eU^Źzb^ZŽ ÞqŒ Ö“þ|ûõ|€ARµßëõwøÎ. ¶Ží5¦i–® 4.¡îY+|©;]Çž‚àÙ´W‹˜U­ÏLóßÝg0¥ #Á. îÛB€kúÒ'0òœ1ò•V¬4ºÊž ý1Æ;úb6wU¦T@|»K‚{Àöh³¢ûB:s§¥H ôÎ=kŒ¼ÔL”z˜0VL×çÑÕ& WûyrhCùƒô;¦\@|o—›ÄNÆS¹&¨‘:†µ"/µhvãÁfÑAîåµøä/›¬ß3•ì’`3ØdvžT´©£z ÕáK­Di„Žñ -ºÄËÔ€¦‹C÷—:Í’CmF°Õâ. 6í!@¾ZSÞV"!-ÆXÎÒÆÏ‘/7b•„î 4¿ ®• =”Þ8Þ¦ óËÙ%Á†±ó)µT01Щ¡:|TŒ¼ÒR8P0DŽÖ+J¼˜É² D†^ù^ʹ‡JHàg¿j¶‹;á~æTÓŒ¡PGõUQ÷3íÄ]*?np„×èpi7¯û‰ƒ»6;TÄT ÷ñß~¸?è§v“¬·Dy9Žõ§–Cwñ‰sÁa¡{CHDL"‰& ü4ñf Þž©”°Cåûr›oGÜ'ä =s@ǃ—/ÎÆ?µ¤ú•±óÊ‚§rÕŠ,‹“.‰D8q¨ÜƒÏNê ü 4_1y×?À"X™X £"DN/¼9ÿxù¨¼ïظ°!×»­‹ÈiIw‚àØÚrÄH!ÀŠ Q ’­)‡<ä*h P…«ÆòY¯ÂÞXqâtQ-5µt%%À¡HÁG éü<!iƒítróôHâÁ ÿÀutÅÅ©L" XPqt04Änµ÷÷°jŠOØðÑÖ€J/´K‘k‰Zº¢X%!‘´0/ñÞ~C´xð a ù ©°óU»(FÙ¶Þ¿‹u±¡™A»øÖÅnqÝ#Ž]<âØ%À#Ž]<âØ%À#Ž]<âØ%À#Žÿ-¨0hÄ4òIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_replyall.png000066400000000000000000000240401217176075400254160ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíidÙUßçÞ·äZkWuwuwõ:=Zf$[¶l$#A€†€`•À€–Ã`Ä`„$‚p`6¡°#@þä ",³ $äÑbkfïéê®î®^fºª²ª²*3ßv¯?Ü÷2³–îÚ»{fê?ó:·ª¬Ìw–{ÎÿœsŸXk9Àë^ÿ‘âî=þÅß;ÐF‡µçcíí*ìÆˆ=p‚·9r%ð½æÃì'îµÂ½Z`€Hqò°ùs{±Ö""òÈ#~Ë;ÞùÎ0ÆÖPÜ+áç ÜÓã×»#èžv#"‰RÒþÜç>÷é‹/½4…;9«NÐn—q±Öò~ècqœÚºKÀûÞ÷Ãf©¹D½V#˲]iÔöžçÑ\j¦ËÍå§{ºxäþÆ‚ÎÒžàíAvpß!"Xk‰¢ŽdY¶¡õ﫲€8IXZZBkM¹\Ü{h­étÚ¬¬´èt"òmÏc²U  Úí6 Ôj5>ŒR cöÔëà.D„Û·o377ËÀÀ Úóì~…ã]”Öxž‡ïûܺu‹¹¹9NŸ>C­^#KÓýùèBkMÇ\¹2M³¹Ìààårc "j]ô¿èWëiÏÓÔëuæççxê©orúôi&&&0Æ, ûA)Åüü<—.]BFGQ­V)•JÄqŒˆöQ,`E ¾ïS.—QJ¡µf~~ž .Ðh48þ<¾ïd {­5Æ.]ºÄ7¨×댌ŒP«Õ‚ß÷I³lß™51€ºïûˆ:_Â0äöíÛ|íkÿóçfdd„,˼Á.Pœßf³ÉÅ‹/Ñjµ;Äàà•Jß÷Ýù×%ÒG—í-¼µOîÈ÷}”R(¥ð< ˜å©§žâÔ©SLNNæbá ØÜ­ÀZ‹R áúõëLOOãû>ǨÕj”Ëåî¹ý=¯ëz‘hqËïûÌÏÏsåÊ9wî!*•ò7Ø´Ö$IÌÔÔsss 344D­V# C<Ïë ÿ`C(P¸)§=E(–„o|ãëœ;÷ããcâày ¼øâ‹$IÌØØ8ƒƒƒ”Ëåû"|ØD ·$ˆø”˪ø¾ÏÜÜÏ?ÿ‹‹Ç8yrÏó8ƒ J!À•+W¸|yšr¹ÄÑ£ ¬Zï {/±©Àú%¡_ ܸq¥æ"çÎ>D½^ëyƒ{üeDh­‰:U.dd¤›âõ ÿ~`K Ð"@,<ƒ CææfyöÙg˜œœäðáÃŽÇ~zKoùœŸ›cjjŠ,Ë8|ø0ƒƒƒT«UÂ0DkÖzÓ÷ÛO¬R€þ2áPhªçy}Þ@> \¾|™¥f““““aˆ5æuWÝ×9}~ùòe®_¿N¥Ra||¼åÖÞ*«¿_ñÓ¶=ô” øJi<Ï' CJ¥ssó´Z+œI7¸ëÿPÅ}c J)‚  V«ÐhÌséÒ œ8qœ°T*~iO¿Äý†(E–¦\¿qƒ—oÝ¢\.322L­V£T*¡”ÆZK–edY¶-Ë·Ö' I’h\_`ÐPˆlÑ×¹ÝϾ¥ÀC§Ó¡ÙlEI’tÓ½µÊ`¬!K3¢(¦ÝîE/¾ø—.Mqtb‚ZµöK„8‰¹>3Ó­ài­Y\\¤Óéì:·÷|V«%NtT{ÞY×$ H*B†á²ˆ4E$Ý®lꌵ´;®]»F­Vs%c6qMª5‹µÃN¡Œ!NR<­ñ|ïXûöApæìÙ}^¬ï{ð=¡Z­©O}êS¿d­m‹ˆ÷¿Ø°2==ýä?ðþŸ‰¢¨ l«R·ÆôŽ&Ëè´Û$IÊä‰Ap÷,aõ?}ÏÉk4´€Üa]·Åÿ»‚ˆˆÖz|áX‹(ÁÓzÎZ[Ú"b¶ã6ð«û¬µ¤iJš&¤iŠRê5*ÈI’lø|¹\feeÅXkCvP‘[ßb¼öȃ?c q»_R{Þ›x€m¢H#£("Žca‡sk<Àk…[Úí6ËËË”Ëe†††šFïŠÖ±F£A©T*üõŽŽÕ¦¼,‹§DÏóHÓ”™™._¾L–e÷Ê|=¡`^SSS,//;:Yì0ÔX²A˜ßWâj•J…4M™››£ÑhpöìY†‡‡zöJiŒÉ¸rå ·oߦ^¯w{´§w<3¸õj v °x¥„¹¹9ž~ú<Éää$"rPÞxžG³ÙdjjŠ8Ž¡^¯wKÉj^x“4Ðvï Îý(å–×â±°ÐàòåË,,,pþüy*å ivÐB¾(‚í™™®^½J–8|øH·šX”’• ;j_®>u ®[Dãû u¯9$BfggùÆ7¾ÁÙsg?èÚ%´ÖDQÄÔÔFƒááa†‡‡»uWsq=›Ýá¾`M °Fü¶H{^ÁyGm†a¯MÌó<æççyö™ghLçÌ™ÓxžwÐB¾MÞìì,/½tka|¼×:æû~·¿Œêj°¸ß©i4J¥7o^gqi‘‡ÏŸg``à@ ¶kmwF`jjŠ™™jµ‡R«Õ»ÝCE§ö^a}9˜õÎäNÎeuÓ¨ëêo!ÿÆ7¿É™3g˜8zà @¼Šó¸ÒjqáÅY^^æÐ¡C R«U ÃÒ¾5Œ® ×A뉡µ¾×àÐß40??ÇÅ‹YZ\äôé3„ap kPœ¿[·^fjê"J)&&\èë òà{º…7M·Z®^úçdõoïÁçÈovŠu=ÆÅú}ÏÝÙ#ì-é ÝÄq±÷À/^¸ÀÄÄÇPâ6§ºjàÜÖšNÔæÊô–––îîò†!žï£û‡A÷ã“tÝñGÏV¿ÛEýF¿k@庎‚ ×uäû‹‹‹¼òÊË4›MN:M¹R&MÓ{O#[Šiæç癞¾ŒR‘#G¨wsû¢n¿ŠÕÛ‡ófíîx“uA ½‡6¿1\Z¤”F”P–J^bö)•ÊÌÏÏóü ÏsüøqîNÜÞ+xž‡µ–ËÓÓ¼òò+Ôê  wé\Ï÷P¢%Ü ÍtÒÙ£% ÷†ë;°7iàV XG‰„«N¸|é gθ>ƒ(ŠØ3Üýk}„4—›\¼x‘(Šq^¹B†ø~^Áë»äϾŸ*cveŸ[ïKÜ*Ö¢”&ÜfÖ«v/-QÏžellœ8‰ÉÒ¬/†Ù­*¸÷ñý­×f®qíÚ år‰‰‰ *gõAôºsïñä³vSU_?²QXÔƒö7¸#Ü9UxZP%É;b"¸Ù„§ãìÙsh푦I/[܉<ò¢—(¡T*ÑZYáÂ… ´Z-FFFò-_Šº½Ö}cy÷:Å+„³C½ÛÔXÓïö÷' Ü Ãr»x€» E’&¤YÆK/]ä…^äío;gΜ¡EtÚm°²-£´Ö""”Ë%Ò4å¹çžãÒÔÕj•#GŽt÷û)•B·<)åª}½wØÛ/¾µ½ã_½ãx¸Íߨbò”k¿X€-¢à"¬Å‹Éo­…,MÛV.3;;‹µ6§’XYYîÛ–åNšÐû¾žçS«UɲŒééi¦/_&Š: ¢=¥t_§Ž ùà¬Ýª’u'möf©°Öìõ»y,ÖXÒ4£Ýé¸ Fܯ50Ö;išÇq¾eÍ"K‹ ŒŒ óÖ·¾¥47oÞäêÕ«\›™áá‡Ï3qt‚N§C»ÝÁXƒl ·ÙU¥Z%ð}®\¹Â•+ÓÔxÇ;ÞA§Óq›a..øZ+DÀ÷}@ãÈÌÞyÍß±t_DÀSŹÞ9ÜÛí•°@×å’4¥Ýj£•Â÷]uîžz€\±`Œ%M¢8¦ÝjÑXXÀÃùóç9rô(v‡F£A†9z”ÅÅEž}æYnÝz™ócxx••QçgÍív&JQK”Ëeß¼p¥¥%‡†¨VÜfWÇ»­p¯]›áæ­[$IÊàà ¥r™0rϸ6ªîYȬ%I-qjQJȲŒVl˜òލ8kvg«ÀXÇf&#I’$fpp€¡¡!f®_wqÀ=ôÉaLFÇDqÄrs™f³ÉÐÐgΞ! C––štÚm”ÖîB ¾OT*óó|å+_err’S§NQ­V{ilÞ›Ðjµxî¹ç˜¹~R®@Õj•r©ŒÖÍæ2ÕZsãð‘ÃL]¼Äìl1¡[_5§G¡}È tÃrÛÐI,7b>óÕåÐg¸ ~ì0¾ÞY[\Ñ£±StÀæ¾(K3Z+-<Ïcâè¥R‰—_~ùž¶kõÖz·ãXÇ´Z-–––scllŒ¨1?7O–™Üó¹íj aR.•i.7™™™á•Û·# Ãî¶v+++ÌÍÏ“ecccÔk5gÙý¹8%Iâ„z½Æ[ßúfff¸víív‡Á¡!*9ï_Ôù»  …ÔV"ÃüJJ”Zþôë dâóÓß}’ïÿ§¸6ñ[œD‹ÙíU]Ý]A¸P4K±‰¡^¯366†RB§ÓéjØþ;Ûµzk qœEn{º••FGqêä$Ú÷YZZ"ŽbgÅÚU ÖYµÖ®ü¥rH½^£µÒbvvÖ)–1è<ìoÔ»ýy^ÎæõÒÐÌd,..–Jœ8q‚‘‘¦¦¦˜½}›ú@z­N–rBHç"$™¥g,¶3Ú‰%Îà3_~™w½q€ùîÃ|ê³3|T_ã7ô8Zž`‹j°Kyt=€1.Ž=|ä0Õ|ˆ$éóÞÿ4°kõÆäV¿¸´„VŠsçÎqèÐ!ü5°9A´ùú+ Öö•\«Öº{ÚœÓ×Zã{žïái—ÓK¾Õ›]ãÌU[¢N‡$N¨V«<úè£Ü¼y“k×®GƒƒC½ÆÏsKXæÖþVlXNm#,·S~å¯f9ñöS|Ç óÕ¿x‰þkü‡÷Ÿ@o£KÚ§Ù1åÕ‹S­Vˆ¢¨ï ÷ý1öAü}^7öˆcšËË´[-FFG9yb•wÕ&iŠä-Ww‚c‘¬ =q&ÖÃ!™ÉV¥bJ\R)AP¹µ;î`ã¿ Ýaååe‚Àgbb‚ááa.]ºÄíÙYêõºKKÃR¾³‡f–(µ43Hµ&<ÚçŽsytˆWÞýÞGyò3Oó‹¿7ïÿócxÅàÌ&’uåàyÀ)€ò«…–°Ö®êM‘îöð{½t¹ë¶Qã˜v»M³ÙDåV?<ÅiµÚ$IÒe §§§i4(WðÊ$©çRAÑ«6uÐþ6,óOðQ¾ð‡Ï/þþu~ãG'r%¸óGØ@DôùóÿÙOüÄ¿X\n6‡¢80YVÊL¦1:MÒðÃ?û³ßó–G0»¬>õ*dn½O'ü¥æœ;{–¡¡!Úq«…e¯ö%”5·½¶ó÷4ÍXj6)•J¼á o`vv–«×®Ó^‰éØ i⓪b7§Õ §Ú|9¬ò­ï{ _ø£§ùØÿ¼ÉoüÈÑÍ•`T g­µ"b/\xñ¹ ^| ¨ È?¡ ZËÛD˜ØMP¸|“{E ·Òj148ÈñÂê—{ôíƒÔþ·ŠÕ£Ýn“&‰›ô­ðüKÓܸµD+®†¾ó74†jV®ïzï£|á3Ïðñ?¸É'øHW ÖsL»óÉÅ`ò5?€Ez*ªƒ Ã0*rÎmÿ¹üz»‰§DQÌÊÊ Ë©“'Êc€@±÷Ý«☾ååñ™—IS—Ò¦¿’~›Úœ *²‹Åd™«(¶[˜Ì0ql‚á¡!Ò4¥Ýqkýkíâë ô5ŒH7Újtë ,´áïÊU¾ý{ßÀgÿø9äO^á×~p _õÊä;Å– çÒïÎ}ÅefÚíÕj™#GŽ!QÔÁ³“¬ûU ‹k(E)”d½BÑ&K@? OðÕJÇ~ðüùŸ¼r›_ûþ1|]d;Þy€þ/MSÚí6Yš2>~ˆÑÑQ²,£ÓiäS±¯#HÎÕ+…º^a;&à 4ZðµJ÷|ÿøó?}á6¿ú}c»2¤­)@yn(þ¾¯àòÛí6a0yâ8aDZK}^ëî~8Y«nVÐ}N‰s¥Ûhëõ€ùeøZ¹Îw~ïÃüÙÿº€þß ¾÷V‡UÁ]8b[ØžX§½Ò­³pwE±ÑÑQÅC¹«Œ¼…«A%‚VÒËŒÁ¦›m=Œó€Æ2|½Rç±ïyˆ¿þË+<û’P£çBåÍZ¢…øî;b˾ØÉ}õ&·ú8IX^^F)áäÉŒ‘eY—íŽùïÝJ7’é;dõc×±ãîkí â»Qø45Ølû‡6sÍ„§¤Æcï9ÉŒ=ö†ømþhððcA¶2¿­¤`Ç ¨ÝÇqLE 1>>†ˆtËɯ¦k ÝÍ?ä›íÞwVÃ…¹õÏГfw¾|­ ²|ÏÃ5êñ_ 5$Cí€Éñ1Ü\ÌøJ­Ìw¿ç”üÕßúº1x¤SÿÐ}¸ùßßoõ}¶¥EÿYAçv:”V;vŒz½F𦳽+cÞkëzôœ÷rÍš™±dù󙱤Rã:wÒÌK’¹ÎžÄ@’’ bcÝs™%6ôîgÅÏ¢ÔÒI,˱a%±´ËO¾cŒŸ~ì8W¿™ð\;Ãßáéò±ÜX4|µ^â[ßy”¿ü›ô_5šÙпùú ÿùm_fl ¶¡.½ËòÍ$Ž©ÕjŒw/bt?±Î†î`TÆBš ÝY§Z!ä¸bj餮‰Ã ѸǙ%JÜk5¯õ~âÌ¥e¦«8XÐ ~çï^¡Ã…Ú^­¼«jžÜXˆ1µßúÎc|á‹×_h§ ÿü7ŸhüÖ?ØT ¶Îä.¿Óv=‚‡fpp0oÛ’²íú]ð:_¾æqA¡fVÈÄ]f3ˆ,1B$–H ¥…¥ƒ¡r÷­¥mÝómké@þ3ù!ÐK¤,e‰ Ä bzœý K]-Q)î~²ÙÇrk1†Z‰öŽã|áÉ™ÇÛÃ?ÿÔÏ5~ë­wµÌ­(€`cŒDqD©Tblì¾ïßw«ß…6ÜÉ­ŠûGˆ-Ò4A)PTÚ€Ö ”Eû RP¾Eg 2‹JZtæžó2ðRðŒ;ü,Ú5 ´¼µ„-¢ÿ´vûð°Ü\Œ±õwþ“cüŸ/ßx|¡“1ü O=Ñøo½£…n9J3™adx˜cÇ&º[ž>°Øòù´½-.'/ªlÅ€LV0›“åGÞ-e2K–Y²Ìe“LâZÙm’a’ §ØŽ$˃Žnð±ËÃâ[ÃÍ…˜ç’€wü㣠Vôãif{ø£ïßé lIŒÉ¤Z«144Dš&÷tF`_Ð-©²Aù’þ‚FÿÍ·ôÈœâçŒ;¬±Î d³ƒTogG®‹1/&>ïþGG(ëÇÓÌüöÈÇžÞP ¶ØRúJ Aîje?°*€»z€Ì€2m¬£e YÄXgÆY}øÖ’X‹Æâ‹§m,PXWú· ¬Í·ÖqJÐ}ß|x•ÌuîÞ«³æ3 1zÐç]ÿpœÏý•Ç›±aäãÏ<1ÿë¬rÝ[Q«µŽ¯ÍÌ\ú«¿þ›‰v»­Ó4ÑY–)c2é‡î—RHο(D°®òvg È2+bR+d(IR«$³Š‘ Eb•t¬'1Jb«%¶Z"«H¬–Ø*‰p·‰U[El•¤VºS”¤IQd&ÿ`÷°üåc™ž°ƒßòÖ1>ÿÔíÇ;©±#Ÿxæçæ?ÙSÙÌšED‰Há¡ÌdG¬1£ù¥Êk­¦÷­îGòo»ì›¨âÚv¦÷ÚzHPÖª< %¨j +Zª'¥ª/~YKXõ%({â—| +¾”JTBñKå~)?Ð¥’ø~€BÑ^€öK¢½å¢=¥Dû(å‰(Q>Jy÷þ9.ãĠǤNøÊs ¢ÌþW­å‰ùO>’Â@Dœ×ƒ(á¼L±-ÆÀúä!{q޵AÉÒ"#Ç´7vÆWµQO*ƒ¾*ùRªV| *åP¼ÐÇË*(WÄ +h¯Œö+¢½2JWDé J—AWDIQù!!"%)„@ˆH€ˆâs_Εã N xL茯]X 1ö¿ˆð‘ùO>o)°Öf"b®Oð~Zý*HPAÕÇ¿ŒT‰øâoï¸ÀÍ;ù6Ï›xc ÊuO‚Ї_ D‡žˆòBg½*DT$JeˆÊÉå¾"ot‰¤Aˆh Ã’¹кh à‡÷wy{¸:ŽúLŽ•¸p³ý¯=-OŸÞT¸Öu)Àý¤~ý‡¿]·ý0"V$¬¡jèj;)XÑ¡ bqÃ)ˆFHqñ¢aIɹ"°nz¾:Zãr7žÓË)×ÄD{4ox®×…«‹´…æJ ±A´€’S°í† þCï¢öÿ© âddœ÷÷rÝY–o­Ú×ÚTDð@^ºÃæ·k^ë“mŸP×ÊwÝë{§ob.iâ%h´R<­n`íïëXü‡ÞEýÇ~´‡í4A‰“© ÝL`} ÏÏ7|±ÿ9[Ä«±ÑÉî®Kìõ›àýóÆÀ¡ªB!Ü^I%/cù‰¹_{ÓÓ°ãa»û ÿ¡wSÿñßχ,§£û×ÙUÎú£[Íߨ£¿wOœ‚©MÚéÝ¿k_Añ3jÿD0²‘ÞÛIDATã>¾VÜngˆ’ÛÀOƒýüè/?çÁ«ÐçßMýÇ”ç„/½V«Âøîfp¢¶7nf×ݹ dû¾ç6š€v ­k´7–RDdcŸÀÚ¿Ì$ƒW™çßÍàû´M£®¤uÞo—YwîÜ+/Ûj˜êäzq× º½Ï±dÖrlÀÃáÚR‚(™Å˜XkÿHxîWßdáU¤áÃïfèŸíC¹ÂzOåÞÙBè §h§wØk'Wš­,Ë«b·­(À½ÓßI3×(²§‰´uFpbÐÇSp¥ƒ0‹±±Æ~7æÍý꛺öñªP€ðáocäCŸîYþšV3-à)AánOŽzt2×Ù³v#‘’/hÕ‹ÓîV5.v`ÛŽ¡öÇýcUœ(°’^¸™bÌÞL@[G>prÐYþ¥F‚R2Kf?b ŸÅq8«„¯ÏÃøoXñ ŽÙHdb-‚ÖÀ¢°°b9÷°Gª]›V¿V}ÁÓý[ÀÈz+Í%‹9¼-0¦}%]Îhõß¡P±²×f[,EfO’c…SCžÀT#A³bøˆ±Ö _ˆæþý×­Œ°áùogøÇ> ÆÃ&w²× AY±Ù2Â+B: H¸ÒŠé$9%˯âÌ‚íõƒä·½Ù^‹Æ5ðjåhp-î\嬎`+ŽðmþØZ‹ €ÀÝ'èïV’›BårHvÎGŽÆ»îËÝþ©a_àâ|‚¹-™yÂZû-,Ñܯ¬><À a•ïûOXlÔÏ>¯‡É€LáÇ`«0~FÓ´í¼æeM߯‹X„¢ËÒeúòqxKÁCÊe ”ß–)Cþœ»íâž+YkË ¡…K mFh!Œç9´øu[]&âxÍge››Y¯Eœ*„#Âm1ö ë,?ˆfåá;ªØ«ÅÊi³t³´ÖˆÄ‰¥ZëW…WbC›+Û‡r i Yÿ¦ë{ N± ‡½ Ž~/àáŠe>H€Å€2B›Rµ©”HeZޤG³ïòF9f$Úy Y8 ÿ¥ù5+Æü[kì_€Ä`£Ùwgáí°¹wkÈ Yfm–XÒœ´ßi¦•7ödôz~ .…*– }‡Ã- ÖÃØ„c’XÏó”W}D®Æ¾=¶Û»nwwçoë„rÈÃËKó.ÕSÆ~ÄZûYÄEû³¿|~Óø`+Àöaa÷5êÌ@œ›ç’ÑS€âí‹4¤Pé;ú+kñ°ÔÑbE4š! $s{\ âö¾aLj|©FŠR2+Æ|ÄûY›Gû³¿üЖ¬çµ¦»F‘þ­©XV+[¾/xxdVSÇJ;S¤¢\Š Šmijñ!&¼\øqíwóüB4ûK[>(Àf¸k¹hS¸Њ’X\‰*CõFÕ«-lé“XŒ…ã–Ë )"rE¬ýkø…åâÜ>Î`[-ä$ùý }E¤M`-ÂѺF L/¦ ˜–Œcì‘èöÇÏl;¡TÑh,×—3è ÿK,ñíÞ1•t { ø‚²†ùÈ "Óûakí—‘\ø»¹`p`×°¨rˆxzóæÏ~†*ß6f£Rä` PÆÐˆl.|ó3ÖÚ'Ž@d÷Àò (À.¡Ê!âçÂß,£ëwùÂ:À¹ýU¿Š1OXË—pÍ1{(|8P€]AUú…¿…þÚ^ƒ@þ«V„OœðcƒW1æ ¬ýyªÇ `ÇPÕè<žÛ*ŸkûxwÑJ”`2KÝw–¿rÕZû–^´¿‡Wi[øý†®•P¡×5è-VQ _´é:„*ÊÒˆ ÓX>Œµ_ì|û$|8P€­#ðt½Œ„ùìá–¥Ÿ|.Œ3‚‰„•¯Y–¿l8â )`E.»<ßqûì£ðá@¶k‘ÀCVv&|qW·©@$V¥BrKH—`ð¨0>¨h&ö²Âü–'ZöYøplk‘ÐGTò€í#cw},CJ¦SRé`¢) "<ü¨Æˆ½”¤ö'ÅòU낽} ø6ÂØÅ^?¤äã VºëøN.lf¢,OÉJ ¹,HR=+H].<;û)±ö«È½>x€Q Ñ&çõCo·<!¡- jƒ¾zrè;¸˜¤³Ëæóíľ Blí½>(ÀjX‹ñ}lµL—²ßýh·!E±¬Cny¡JüP‚ ÿ7SÌ7RÛl¥´qëºçÛ¯(@?DHK»¿‹í[×Àµ¡kV”Æzš¦¢T IŠíHFG©d÷^øp «!‚Õ[àô·ƒ"aY|ZÊÐXeÈòrî>ïsg(À=‚€AÄZAPÉw¼ïŸëAÛôñ÷ÿˆEÓ¿„r®<IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/mail_send.png000066400000000000000000000241541217176075400245310ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœíY×yßçôv·¹³0H H*–dY‹e[¶µZ2%+Ž·Š‹,IvUT•¤’Ê‹ìT¥*/IU;²'^d)¶lÉ%Š’§,k¥lqì;AÌz·¾½/§ûÎ̬³äüQÙúv÷9ß¾œÓJDØÆkz«`[‹mxc›^ãp¯u‚RJmƃlcc ×pòTÿßsb_ylãÎFA`ƒå‡ ÑÓ…¤‹ˆÉöó¿k¶áND?á1ʲ‚”ˆôˆðࡽ?úö·ÔuÝ2"¾¬`€ípñΕåü;ƒR‰ç¹ñ7¾ñ/>ûÌ3ßL!è䌠E„ŸyÿûßqâäiÙÆ«ýØÇð\øûM€óã?ñgqi1‰ãi/˲MæÚml”R”JQ·«2©RJ¹}ŽŸ6YæfYVh…Þ×mÜÙPJaŒ`Œq±f=ÆÒ\V„‚¥)Ý0Äó}´Öc¶â™·±PJ¡”"IrÁ^Ùõ'‚‚E«ÝæÂ… ,,, µf;pçAk  ÌÍÍ‘f)X:®É @;ÇqH’„3gÎpüøq’$ÁqœÍ{úmÜÇ! CNœ8Éìì,Zkí ŒåûM€(´8ÊÁ÷}*• Ææææ˜ŸŸçÀŒÓï#lãö‚R ­5—.]âܹsø¾Ïèè(Aàºn¡É âÙð¯ïQZ‰v4žçR*•¨V«Œ""<ýôÓœ8q`[܆p‡,Ëxé¥9qâA022B¥RÁó<ÇAieÈ3‚ÅçVÕ”¶&Àó¼ží×Z³¸¸Ä‰'˜››ãðáÃÔj5Ò4Ý´nc0”R8ŽÃüü®ëæB»Â¬Ž”B´­×h­p]×õ‚€ÙÙY¾ÿý'8xð;wN#b0Æl;Š› ÁqD„ãÇsîÜ9Êå2SS;¨Õª”J%|ßÇqœžú¿–Cõl‰@)Ý»ëº,,,ðì³Ï²°°Àð<íÄÑæÂq:/½ôÆ££c S©T(•J=Z¡àZò9°¬°ªEDÐÚÅó,CX`}„ ð9áõ$û÷ßÍÌž=h­{Ú`Û,¬ ¡²Ž^Ê‹/¾È¥K—¨×댌ŒP«Õ(—Ëxž‡ëº7”»¹fC,²P)Z+G㺞粸¸Ä±£Gi,-rÏ=÷R.—¶ÃÅu†ëº,--ñâ‹/Ðnµ™œšbhhˆjÕÚûeŸíÆw×ŰÌŽãäšAçfÁÅu}‚ÀgnnžVëIî¹Çæ D¶M­B)KÐ3gÎpâÄ <Ïcçô4õzJ¥Ò‹ñ—ércZ÷ºÀ>ŒZu,;‡Nnæyî¹g™™ÙËž™=¸ŽƒÖôD¶±ù\9Ž&ŽŽ;Ê¥K—add„jµJ¥RÉC<­<õ{ãÈ×#³ý>“§}ßÇ|9sö4fƒ»÷ï§V«aD‘íÖ¢k@°râhÍÂüG%Š#¦vì`¸^§Z­ö½ÂÞß 3@N¬ëÕ.¾¿RC8Z³°¸È3Ï>Ëþ}û™œš´‘ÅvuñªÐZ#"œ:}†Ó§NS““ ÕW„x…ÊÛÑuUz]Í,Ü táâæEèÑ3 ŽK,,,òâ‹/Ðl6Ø33Càû–Án寝6ä*_kM·qüø1ææfª366F¥RéSùn/¿QÖ pó,ü‚)l¸èây‹‹‹¼üòË´Z-öíÛÇP½n?”3ÂkÙ,X•¯ÐJ17;˱ãÇÉÒ”‰‰Iê¹ÊïÏê­wh=@X‡íf¼÷‚ðE¡`Çq ‚‹‹‹<ÿ ìÙËääŽã‚˜;^Løâ|­hµ[œ>}šF£Áðpáa›Ë_ÛoRÒl°X°ª`…R.å²Ê“GË ¤¥¥EÚíwÝu##£·]Ò°¿ÊH tS¡ K]C#Ú±Pñà;gS>ÿ|—ª Ÿx[ßï&†æâgNŸ`bb‚z}ˆr¹ÒËå/—àoÜÑ»Ylˆ8Ê6æÜ]êå lU±T.3??DZcÇØ¹sšéééÛÊ$ôÚ‰¡B˜ë;­á[çRþô©®!M…#—þÓû†x <Ç© —ª”¡V­Y•ŸÇöÚqzeøÍÄ™@6tâ¶õÌu½y­4ÆçÏŸ£Ùl²oß]”++[œ0X–|¡›B#2,v…ÙŽa¶cÈž¾ñùçCÂØ°»î2Vq9úJ—ßø«þõë–xçÝC8å!*Õ*•JÏ+rùº7¾˜÷«]s 'PØÈÅ E{za–3ˆNÞlb‹JÏ?ÿ<3{÷291¨Í_©Tð›aYíwR¡ ó]a®c˜ë¢LxúrÆ_ˆca×ÇÔÎ*®çñÁýu¾þ³üǧF˜œòyïî F8žëå‰íZ1F¥ ºò€0p3&¹®FiÁQš °‚ãØì¡ïû,,.ròÄ ZÍ&33{q]7_©´9ŒPˆE’ a*´XŒ¬ÔÏu qO½’ñ¥—b:‰aÿˆÇïpd.%•” ¡Ï‡Þ6ţ߾ĿùZÂÐÃû—覊LÀÝ,•¿Æ”­.%Ér`£›B±7-²†¥R@¥R¡^¯391Áøø8ss³9ò­V ×Í‹ ki]æª82cûn&4a!4¼Ò1Ìu¤GüÇŽÅ´býãce—.‡”´0äkæÚMyß[§©úÿ‹yþúh—ªo™*ËçÂlä\ƒ] ¾zÆn‹=‚zUļ9Êå2µZá‘&&&1ÆðÜsÏræì™^“*½A²î‡KüÔÝDhDÂ|ÇðJÛ0Û¢‚øÇ‘áð¤ÏDEóô+!žk§U€²«htS¾v!塟ØEÍS<ò™—yü¥_g†T6ÖèæIÊȲE‡¢HÛDQ¹R¡V«12:ÊŽ;åÂù 9òqøíe/a½þ‰ØO&„‰ÐŒ ]Ã厵ý©ž¾œòå nÆá)Ÿ©ªËç»øŽF‰`×aZ“ZrÍnÊc2>øS3ÔËúe¾úb‡Š§‰S!“{ú²”×d€ ©ë9ú¢m­®ãP ª•*õ¡!ÆÆÆ˜šœ" Cžzê\¸x‘Àð<·G8¹…ûŸÏòì^754cKôËma>4Ä©ðÔ+†ÇN¤4;†ÚYb²ìñí3!§æ/(¹ŠV˜ò勆Ÿ{×]LTùôE¾MÕƒ$5dÙÆÍíZ¾Ý è/¶…gœ÷ú¾G©R¦Z­2<:ÂŽ;¨Vkœ8qœgŸ{†4M)—Ë6ÇÞ3 7f'M~¤FHò8¿Y¢_î溆ÄÀÓ³†/Hi„¦KLT¾}.$ðõ²'¯X¥s¬&S¾p6ãýïÞÇdÍåá?¹Èã/v¨xŠ8² ê—Y벫4ÀV ÿ*E 6{¨òä‘›—”+¹o0::ÆØØósó|ç;ßá왳xž“G ¦`„ëS~Ž1fXo?—üÙP˜ëØäÏÓ— _>™²ÔÎxãt‰ÉºËßž ÜÁ«nVÍ-– :‘áóg ï}÷~vÖ=þ£ <þ|‡Š¯rŸ`ýc7H´×på6:Š>•7žú”ËeªÕ C¹Yxâ‰ïñÍoþ­fÓ–R=YÂ×¼²…È’^z×° ³]a®+d¢xú²á±S ÛgÊL )þï‰%O£”{­S³š-,@¥üŸ‹Âûæv¹|äÏ[sà+’ÔFë5‡Ö<¦ômå^;YCǵ®‹çÙ"Ó©Ó§xæ™gh·[ שT+("L¨«þÜáë¦6Ô›ïÂ+¡•~´ËóKž4,¶ oÝUbÇË×Ov){ú¦’“E·›ñ¹ ÂÏ>t/wù<ü‡çyü…eOåŽáz²Á ¬áÞN‡X&6žÍÒ”$IHâ˜8Šè†!iš°oß~ÞùÓïd÷îÝ<ûì³<ñ½'ÈÒ”‘‘a?°ä.–®vßX‡Ï¦w…fdXè ³¡a)V¸^À3óŠÏXꤼe¦Äô°Ç׎·)yk¯·³s¸†ÈõMqà@e|î¼ç÷²2à#ÿó<iSó!N ¦Há­Ã<2€ 0À–S|ÅaÕ¸!MSâ$¡Et:Í xžÇßøÞô¦72::ÒÛÜâòÜ,ßüÖ·8}ú4Õj…áz×õ#ù†IEœa ÍXXˆ„ùHÑ–íúüàRÊŽvYêd¼uo™u—ÇŽ·)ùƒ½ý•Óxu(fÚw Ž2>s~úg±o²ÄÃxޝ¾Ð¡¨õÈÞ{¸F;2”Ük8 ƒ®½A×(æ–B/grg/N»ZÍ&YfØ·o?»wïÂÃââIb7ºTz=¶’*ŽÊ‹F6›¨\åùdn™8ÈC‘BRMY^hzüÝRÀB'ãM;}¦ê}<´Þ>7!79}xT–ñ™ .¿üó÷ÃçŽðð§Îðûﵚ 66ùt£*fÀ3­Ù¶äïmIk„ÌX•G1펵õõzýûöQ­Vét:„Ý®U­J¯ÙTLŠB!Êe\í`”C¢|”dËÌ&Pòà™EÍÿ›ÕÌ73Þ±·ÄDYó¥“á­Ùü[˜@\*Íø³‹¿òË÷ß>Ë#Ÿ:Íï=¼—÷=`5Á0YƒƒWm¹In>bruŸf$ILÔíÒnµYX˜'ìt¸kï^¸ÿ~‚ `ii‰0ìÚÎ×Ë_×?¥4šXBqi‹Ï’ñX2Êõ9Òôùêy‡¹FÆ»÷ûì¯k=Ú¡ä߸š]o¸œÌðéó?öO_ÇÛÖyä“gxü¹UÏFr]y‚µEzKRÁ…—Ÿe)IÓº´Z-)—Ë<ðÀìÚµ‹0 i4›dY†Övý\^'ºêQhE†"Ê )cÅ\¤Xˆ5™Ò<½ yìŒ0×NyÏ2ûjüT‡jÍAo]Ôƒ`™ÀÏàÏ»ÜÿàÇÕyä“§yìH‹Šo3†k'»ûç{p.póRÁ¹ci³o†4ÍòØ>dqq‰0 ™™ÙÃáÇ ‚€F£A·ÛÍHÕêÙ\í€<ηÄo¥Š¥æ#˜©(žšƒ/Ÿ1,t2Þ¶+`Òóø£§B†Ç]Ôm¶‚ÝÑà¥ð™ .÷ý¼íà0|ò4_9Ò¦â+ºÉrÏßšs¿Æ˜&‚ÖúfÙÉ3&#‰ºÝ.­f‹ÅÅJAÀ}÷ÝÇôô4aÒjµ0yHwÝ꾄eÉo&°Ál׆{‰§æàÑ3†FWxýŸñrÀ玷¨*´aº ßa}숣¡œÁgλþ'ðöCuùS|å¹\$Eš›ÕGñ<°¡©à•]6VåÇqL·Òh,E]fff¸ïÐ!ü  Ùjű-ø ØŽæZ(ŒX Óeâ_î —»ø‡Yá‹g2Ú±áà¸ËpÙåëgÚÔªˆZÃRÞ6À„h eŸ½èrø^Ç»ÿÑ(ýï§yìÙ–Í^Ř5žgãL€ÐWpYVùíN‡Å¥%ü àСCìØ±ƒ°Ñi·cz„¿.cßwH.ù)ŠnLÙ$OdUlà©Y×ÎÂX¸{È¥^vøÞ+1•²Þ‚m´²šà³ç]öýÂëx×ëÇøØïœäñçÚT·ÊM˜R“ft£%àjmcÆðռ™§¿úê•oMUÇ#­H)¥V1@o« ijˆãˆ4Mcrr gë·Z§UOŠ²Ë«ŒâãoÕÅJÕÞ‘5]œBšŒ@šB'2,µ…¹–¡ ïÅüÕß„$÷jfK ÕÄ#5Ë .Mo‡ÐFþL£’ñ/ÿêe>|ÇCñá^v#õóÉÊo”Ò8ZÓé´™›½ "Ô*µ’OɪÃoÿö©ç>Ý ñšJÂ9`•ž”&6ãº3{f¨Õj=©ß*ZÀÓPñŽ*®mòX®w«Õ:YŠO¯\ $µM2ÃRQ,¾ßåï3Í鶡ӵ筟ÞËÛÜDqôR—©}Æ+NnêúÆtU3#¹F+u¦Çª\~åÚ­6x`”Cæ(2\Zbbm0öÍn+@%"$iBuíFM“h­·Têû¡Ôò&Ì®R'߯m…D\AžkØè\†±?)¥ˆSEÐU8±¤P*+L£8 b«¡Mßg¨ê0\u¨—<çz– 9û“µÆ‚£=¦îÝKci‰¹ù9L¡T •…ÖŠ–z. —_MS›¹›žžî½8I’õð-¢WR AÚñædS G ±§ñ\Áu—ïÑoâ××ëк.™Øý„+¾ÆÕË»Šßø¥2¦&GââÅ‹t£czowíÕÔVh€Ì|ßgÏ®](­‰ãø–†¶‘è…ÆëE •o‘oóîhÛxÑs¯‹Ó”Âu®£uLåñû 4¦ï{ÿ[X˜ßϤ ®ã²ï®»˜ŸŸÇ x½ï 0Æ0<<Œëº„ÝîÍÞýŽ…m>V+U|ÏüöÿÏ5ÍÊÍpf¯`·Ž*&ËR@ÃÑ« "®ˆˆRÖkÊ7kt•V”J¥M ñn'躤iŠï+\W¡³lÝ Y×B”Ke\çV4@ëêüBŽ£‹rJ/Ù߯ŒÖª{âäÉŹÙËAœ$Ú£Lf”‘¾–ãWKE%'h¯í<·'±Q´R­æ‡—#O½ùª‹£’ØÓ7$7H¼âEßyâ‰äl]‰«‹DÏuÞàŠµR(­EÛõ‘ÆJ& öd))Òóp¾ûï<÷Á‡>ðÎ,M'Æ¡âè>¸ UC/¶æ +TV Ò«Š ªcž3±¯âî88âMß7Y™Ú·³6:ZoÔö?à¨RõºçgÈuÚÍvøÈ'þÝV‹ÇæL·™‘%7"m+ÎUJ C©®‚†Öê²É²óØŠA&yš×Ë J)“$I+I’cÀE ”ós˽·!ñQh\_ãx ÇÍsÓýÚ –ú?ezŒŸ¢Gg|=ýà°ì<4¥¦î¾KL¥ºV™TÚMÖ5ü»‚ ´kÊÓ÷ÿ Õr.Z¼˜¤kV„9ƒUÔû…Éׄ%H’™6Y·ƒÒ1²ôL€ˆd¹/`€h²ü¾£¾zÔºã¦gU¹º>¥œ‘]ŽÛëèúWUêŽ JZ¹nϽCPë'IDAT}[yYæQ"J¡Ð6‹"‚®MzhGª*#¾ÔÆœRÐv·F¬Íš­µƒžíF}#8®kîzËÏÎE·Ìµç/ÅndâD–ß½\ÔhúÇÕgš‹ÚMnÔÉc2I»±dQL–$’´Òø…¿èÍȉ 19¤¬$øFJ}Át7ÏGWFÐ#Ó詸#{µaTPRÚsò‡–^ÑþØÇ yJ]åuT]Cí+!ÒUJ”£TÕq¥ê•T¨R³¡a‘R‚K³ÎîïÇ£ûZåà,~ã2i’ǧ²LôÞfý ‘ÞkyÚÖ$1"Iˆ$m¿ýÍU¶º#hy+‰ë–Ì-‹Š É K,•ÆàhÕ÷²¶«0`W$Õ&Ñ#3 ’å*R¬‰ Ës~nbJ2ƒ,uI=ߘV° Ç !œ#¯÷ö†Ó_¶F ó¥_¿ñ›å¸-¶‹ßR˜]Ã?×RÍ•æîæÌŸº¹©Õ ¥òd@6rU³:³^xM3€˜UÇ™<”œ¼uQˆ6¨Ñ÷¢«c`Òõ¸è*¼vÀ¤èê8îä}…ä¯ïõ×*ãÞÄvx8SÑÕqÈÖŸ ^› PHþÄ_X¿ÌaÁ;¡kãë® ^{ `RTyg|ƒˆ¿ècµÎšàµÅ-ù”BõšRÖW¸;¡‡Ö ^; P³$#"ãÜ·nLðÚ`€‚øc‡6‡ø6,w¶‚ &n™ ^ý `²Í%þfÔÊ &Ø•3Á-àÕ͹äëÍ">@ÿÒœ ½Mb»»ï»¥Ë¼z  þèÁÍ÷ö7+5.·¾§Ý«“òPOmñM­˜ßâØ^} ¥èÊ8ÎøAlCßÄù·´Vlsñêb€,AMáì8Ì–PúΙÖ;çI¯…,FîÂÝóCÜ"ñoQçÛØÜ!JàU±e’$!ÎÄÝx÷¼=ÿźI~^ ^öê¤èZ¬r ê¿Ë-.Ë»›†;ž$nãμžàõ²tZŸÚyÑ¥”©‚D+2G©L„8ë[º ½ð þ’7ß1ˆI€BÌ6\?¤ÛÂ{Ç)ÿäoØe<ëW$): +ˆÄJ ÄY±÷~?©ŠeJÅ*ä‡Ä ‚H†‘LA,¶];d›®þƒï¡ú¡ß² ø²u[¿Ø/ý1Ð<­UG+Š‘8ÍŠÆÌþv³œÂ= ÐäÈA´2t’"Q¤Á6\üû~Šú¯~´ Ùº¯a–5@ „Jèhh‹]9Þ³ÖW*z¥4Wwòƒ‚(E†H‚•|–Ö{ ×ÂÉþ}?EýŸý8.¤Bü‚R¬pÒÑŠN¿ AtîúµeÙjûvÌžêÛŠ¿­®† &~~ Æ®´j+EK„¸o›¡eô3õõ©÷0W&Û&àjØDâ÷üe@¡hiEÓ‰éß‹¿G/»®¸4ª5\z ŽˆdÊÐÅÐÁ ´6jPkáŽa€M"~~ aµ}KY=X¿QªŸ'ÃÆ&w»@Èinv éŽ`€M&>,k€Â ”j*-¥4“Ôä‹3V® Écÿ¢@ú¼ÿþH ø€Êœˆ„ éˆæ>À¦â¶g€-$~¿`4iow¹+qý}%d]DÚR„Ö5Ö„¯;nkØâ(¢€Œœ@ZZá“3¢ÐJ­´ùW'¥ÉïuQ´Q$ˆ´²Ìà8›W¢¹m` ‰ùÆcØ’$€(¥´ˆd½ÝÔ×Tk|¿l DÙ S„H ¡b¦¾õmAn·%l1ñ ÿ¾ˆÀ(¥šJÙm: 'pý¥ÿ׈Á JHó<@‘ë ¾¶MÀ¿€™BR…J*SHKi»‘jºVÍîJáU+m7ªUE™"  ‹e€MÝã¶b€Û„ø`dg2­‰•-55ûª1k¼ˆy…š_uEzY`›0’*%‰‰Œ „l²xÛ0ÀíDü\c­TêˆJAkhiHDcDIaÙ¯¡T+¾æ?IQÈ» l*8U6׈HW‰ˆ£7/p[0€·ÿÍÔÿùÿ²r¶µÄ¥0ù.´©Ú¥µÐÒ!H’ÙMºÉwî–>]/êÊH°ÏY´Žƒ(´1¢EŒvT¦ã$ã¤J×JèÍÓ·T~ú(¯‚„Í5€kÀÒQ‰6ʨL¥ºâ¨öhÕu­¤›äÛ)é%|V”„W|ku¿=ß  (1h1â+ÄIÓÔktRFê)BZ/;”}gݶ*¸¶œüƒïÀ¿÷'‘Nž» zéŒ ŽÍ(£ RèZYµ’TÔB+EûBšIž Tv£jû–¬ñD0 Aç;ÍXñWFpLFY 5-¦dR36¤£ÎÒ$1Áp€³‰¡à–3€»çõàV!ºM¶¦Í@A$5˜R£PI*:5¢R‘@À±µFÄ*Qˆ»ÙX®ìNuÒ3ý6»`PaËgAMAÙܲÚÒIDATxœí][Œ[Çyþærnä.¹Ü]]VK•ãTv›+8-R@ lÀ &iZŠ"EaMÛèKQ´(z ô­I>èKÐ ’"¨Ñ6I +BP‰¬(u¬X±×–,{uYí./KžÃsæŸ>pçhxöË]‘+SärÏmæ›ÿ6ÿ )¦˜bŠ)&ìA?À¸áK%|^0ü]¯ã¤ðÑßmàüA>Óý€?è70BKkÔóŽi6âƒ~¦ûÁ”Ž)&SL8¦˜pL 0á˜`Â1%À„cJ€ Ç”Ž)&SL8¦˜pL 0á˜`Â1%À„cJ€ Ç”{„fx@ø ŸcX˜`ø|/x^k$úY†)ö„ð7XÐÏ1 L °ü~?æ„絆zÐÏr¿˜`Ÿ¨sü•îfË@âyö 9ì ž;wÎ/‹sD4ö½£¾F´ñÉËß½Pimý ؽŽT÷Üù_úȧ!?qx_p‡×jµèüùó›C»è6†N€R©ô,cì´ÖwµÖþü‡R ~€>æ)öì/è éØƒÄ˜óÊ™³_NØbz8UËc,(•J/øìP.jaèRÎ8"¥<âû>cxXˆÀC’$h·ÛÐZC zå0ü;ï‚`œ±Ùrù¤ž«€áþß™sŽv»(Š@DoßÿìÄÐ À9§8ŽñØcá™gžA +µØŒ1„aˆF£"slÞ|íµU@k!ðËŸø ?ý3ÀHïº..]º„ . ÕjÄí µÆ‘#GðôÓOƒó‡ËÎ$"lnn‚ˆÀ]¾òe܃†g O=õæ?tvh÷k·ÛxñÅÑn·‡vMC'€B¢(BþÅE†F$ƒk½Cº »¡’$IëtcˆãžçA©‡Ã!0ïÇ1´Öû&£ë“$A¢ô>Ôc Rvš„ˆÀ9O÷cCÎ9\×…QÁq$ÉC5Mm€(Š: ‚"J) ´£6Â0Ü8ç`ŒA¥c "H)G¦JG" â8F»Ý~¨$€Rêž I–H’¤s|ÐZCJ™zLD”ª)e*†‘€1–öü‡‰À=‚‡am¿š’¤CúýÀl@‡q§ja¬$€ã8pJ)$IòP€1ß÷Ñjµ@I²Ã0ï¼Ü#çŽãŒÌ;Ž“¾ÄÃî5”ëºhFÑT¬ ÷8$ µ†R J)èmïÂtœ±Rº`¶<06ž+Ô(¥ÚDДCM€ÞLƒÛu¦”ç||hW#P8ŽqçÎTZ;;ŒÑÿceH)S˵Ÿh7¬¾}û6ŠÅ"fgg`|ŒÆmƒÍ†éÁýÀ9G­VÃææfå3½^gÂËBˆñS†»Þ\J,.."Žc4 DQ„ÅÅÅt,὎^äfŒ9ÇŒ¤¨V«h6›˜™™ïûØØØèû¶;7Єƒh̃©clmmáæÍ›XXX€çycB‚ì÷Þïš$I:’877‡™™´Z­T ˜Ð/™D”ccØÀ Œ ”‚ïûpõzëëë(•J(‹ïiuÐiìlƒ³Àx<Õjžç¡P(ÀuÝ4Þo`†ÒM½JJ92/i$6€ñ!€aº±x+• <ÏK]*•Ê{ÖEdŠÅâ{Ê.ày†ï4j†ØÚÚ‚ïûð<¯§=d7´í dËÇÆ´ÅÕna`cíÚ£`¦²|ßOGßÂ0D¥RI?Ph €‰î*”A€­V ­FÅb®ë¦ïš…‘¶ág$€]n¤Ä(0/ØÎŒI’ž°G¿ò`~ )4›M¬®®bnn¾ï÷ƒV„×¾ñox߯—pâñ€â¸3bØç‰(­+»ÑMÞA’$]*rØY>@’$iî\LD?Ø¿eŒ!0ÆpëÖ-ÌÎ΢\.§Ç N¡€­wßÁ þǸõÒwß¼q/X)¼ý•o|§?ñ)|è onI«ÙSj­Óº2vŽ]fçŒ##€ïG]C »Á¨„……lll ÑhàèÑ£8rffpçå‹xážCñ­K8;Oø±î “ĘÆ…*x«Š}å-ܾø=|øÏþ‹ZF¶rßÇÔSßû›34lr)Œ§0 ]®8Ž“J€Ý63òeÛý6#]×Åüü<¤”xóÍ7Q«Õº|èQlÜuqûû/á;Ÿÿ,¹yËÇ ÀVû^B˜ÖÀÍPð³•Áþ¾ø9Dµ  Çó™w²ë蛣’C'€­Œë·Ùã߃nJ)!P.—Q©TpãÆ ¬®®v¹’ÃÜ 5˜ãâûù§(\û!®­ß»4­,p àFxéÐL€Se@®\ÆÅ¿øÈm&o³ëÃ&†)K é!Ú^߯þ6Fäìì,„X]]ÅÆÆNž<9ôáeY(`åkÿŒú+/c¹ ¼[®®íŒ’1ðÃÛÀ“óÀ#.áµoýî\ú>*ï?wϰŽq÷ŒTK`|{C€ƒØ<ÏÃñãÇáº.®\¹‚ÍÍÍÔï–ø¿þ_Ïãp²É•u Óø @+ÞØøuÜøöBoçIöÚluhKF*úõpÃüA¼€A ¥ÄÑ£GáyVVVP©TðÈ#¤÷º_¬ÿèÿp4T¨ŠŽx×èÿ—k@#Ú $-¬¿ú ·ëÁ ´I1J 0R/`7äíïŒ1T*8Žƒk×®¡V«áÔ©S(‹ûšœbB³W®þF% ¼Û’>½?}t~·²­°ñÚ«`Û† l. €ÀŒ—Œ#  jd­ßa¡X,âôéÓxûí·qùòe¼ï}ïñcÇR#k¸®‹µµ5¬¬¬`fé8\G`=Ö©³È ÍAÖcà°üÃG·ã®yÓQluiº¶›8€ëº© °›‘×/|?ÐZÃq<ú裸}û6VVVP¯×qòäI!úJ#jßxã ¬®®âСC8uú§p½2êOź?ÔèZ.,`€-¬Û¨q‰ò±ã µ“€Y gŒ• °%ÀnšÕÃc 'Nœ@¹\Æk¯½†—_~=ö*•ÊŽù ¦—5›M\½zQáôéÓ˜ŸŸ'Báƒgñîå—0Ú“é¬4PŸ™ÅÒ—¡2‘Q;Äôx {ŽÀØÆõç÷dVZ©T“O> Ïópùòe¬¬¬t^~›¬f{çwpéÒ%Μ9ƒÅÅÅΨfñ£sóÈrÚgÀŒµeû) ƒü¹ƒÂp×zè%Æ*`«€~¦`CJÙ5/<ÏÃO<ëׯ㭷ÞÂúú:–––àû>¢(ÂÍ›7±±±ãÇãÔ©S]¹ :‰Q<õJO?‹Í¯ÿ¨Ù¬ë *s˜ýø'·%í:½`ÛÆµF¦iÔ¬<Œ{{ž×•X‘ÅÉ“'1;;‹«W¯âÊ•+)I¥”xüñÇqôèÑôÙìçLê5,þÆoCÝ]Cí;߆n†îÇqÝÙx¹„ÙOý* }¶ºÄ<€ mÐOš #“ƒôè¼Ý+LDÑqø¾Ÿ–ù šJ),..¢P(`ccI’@J‰J¥Òµž‘}®IñÒaˆc_ø#¸‹‡±ù­ç‘ln€ÂNdÁ Ì÷ *ó(ú×0óñOCÕk€ Ϋû¹M¹ù>VÀ„a™œµöÆ<ÏKEþ ÄK’žçaii)-3½1ö5Ubñ7ŸCécÏ¢úÍGýÅ P­&´R`Ž/Uœý0Šû8ÄüB§ñ· š'éò:m+¥Æ/%Ì í#îökH)Á¾†ƒ÷zOÛX¤Öœ#Gqäw~‡?÷El­¼Žvµ ¾°QY€Žcèv…€u^öž½\`»ÌΛFF€ÝËÛׂJZë4ëØdÂ…ÌbGþ¢ÖPÍ-0Æ0sì8âCG…-P£3Sifðngê+ñ³ërll;Ûµ_³_v/½Q ºæDڸ뺈¢¨«,}þ$+8„ï# Ã\é—1ïmê"ÛÓíò±RÆuك ýš^of$ì\ƒ<$IÎ9ŠÅ"Â0DÇi‡1¶ëdÙ<1oî9v{¶^Ì«XS&¥„ïûp]7çäd;¦1HhÛ÷}H)†aWšwV˜ï¶}Á,µ1¶ÀÀ* Ÿ!dÆÁM¯·m†aŽIïÞ ZkÄq !D* Ì»ôzÏ^*Àœ3Vn yèA%@ˆ(`êyâ8>C¯²Ã´ƒÁ¤ryž—f4Û:ßF¶·g%ÂXM 3™8ƒÚÙì£/ͨb«µ3›v¯Ø«½‘w¾i€½H# ‚ Àìì,Z­VJæ¬J±g[ Ø„FF€^lʳâÎôz!DÚë5ô²ñõQ¨‡^6Àn÷2Ïc–Í5¬1 ò¦ÑÙRa¬Ü@;/0ûRyhßLƒÎëõ½‚(ÙköÊ0„;¿ÖÞx7F´çÓ«LJ™®šj¦|›dlÀÇŽ7Œ­`$@¶—g{ªÙÌT謮Ï6rÞ÷ìçl"J/Bä!ÛèYQ¬µF»ÝεԳ¿·%™ô©µîZý;]q4Óøæyíò±"€‰äÅÖ³•åy^ê2ýsúóŽgËìïæ³½ï‡^ i»b¶!˜÷»<‰`D¿ù­qÿÌ4ú¼Æ5÷4s ÆÊ 0›m díS™wïÞEµZíʆÉöè¼ò~ŸwÜv9³R)Ûðög»aµÖØØØH žýÙÛÇLnBöú滉k˜‘Lû\sOsQ`$9y* ¯ÎÌÌ Š¢ti^r¤™=Ô+ar·ïÙ½=în¬{ÛÕ²U’½t‹‰Ç×ëõ®^iÿΖæ:…BF#½GÖ§×Z§1[ÕØ*d¬T@v,ÀîYc­X,"‚®)dfZ´™-“•Ùã»Í=´——|bÞlöŠöBæ³Ålz¥iPûÆØ+•J‚ =?»Þ©"Ú13Ȯ˱Qƒ-lBØ•Ò˲)³·Õþž'ìaç¬4²-o»Ç÷Ëþìû>šÍÎto{ý{3ç;Žƒb±˜’*o<Áö̳dƒ^cI€¼1~†˜é!FìçõÜlCç5v^¢i6ÐdW°­kóܰ<28Ž­u߯7¹ år¹¯hþ¿­JÆn8،כѰ<ô#ƒ‰Yž7—.¯ÁÍpl¶ñóz¿ýÜY.«×M ´Ûíå¶ŽBt-u×ë¾Yu`¤¡Ém´d£Àȉ2ãõû aö²æ{¥Oê>öB?·Î6ÐLgss³«Üœgöœó®%~Øo=`!YyѾ¬±y¿èé“R¦ÿ š‡B¡íå^F꘱£jÆJúa=¦ŸØžŸŸÇúúzßã{5Ü ±´ÖiðÈŒÆFA€0 »E|aÖ2n6›;BÜ¥R …BaÏïo< "ê"€‰–ŽC¿ê›o¾I'Ož™Îz/Áó¼ô? Ìä”ý¼¿?±{ü¶a9’ÿŽ:îܹshÐyãŽaÛý µþÈ(®;t¬¬¬Ì\½zud"kï`ÐŒÐР˸gáç 4A0‰W“— ªµžÅ=‡ÞJŒ±Æ¿\¿~½þ I ÁcI­c^´þŒ<(xæŠE® R„fØFFˆÚ ZQa£Åh6š`•…KÞ¡#—9ç ƒ­q_ º÷kkkÃ05"•Rî¡C‡~2Šû½…ªÕêÿrÎ/ߺu‹†}ù=ƒ%³¥K?/½™àØ|§ K8:WFƸ“Tq·]Çúz ku$ëuÔ6kX_¯áîÍÆ7~æ3[>q"Úý.áV«¡V«u•‡aÈF’?t<÷Üs1€ê°¯»_|ù·Î6À„æZA2 ¾``ðà2 ‚Ð œb ‰8†F^üêW«ƒ€pÀÍÃ{š ®- ®s¶{Øþ£ÆÀ%c‡& ~úœ¢?¦˜pL 0á˜`Â1%À„cJ€ Ç”Ž)&SL8¦˜pL 0á˜`Â1%À„cJ€ Ç”Ž)&SL8:k“õÚ///³V«Å Ýn³8ŽÙÒÒ‹ã˜ÅqÌ’$a ”bJ)V.—Y’$ŒˆÒòb±Èˆˆ)¥1"b·š˜?\Ø;ѕŵ'9ü³¢qεBç\ommi!„æœk)¥®V«z~~ÕjU !´”R;Ž£oݺ¥Oœ8ÕÕUí8Žv]WA /^¼h'#e÷ÙÏ#Å~ ÀìíÌ™3¼Ýn³ÅÅEÞl6y’$¬Ýnób±Èã8æAð(Š„çyã˜'IÂËå2oµZÜqÁã…B+¥x±XäI’)% c¦¡8Î9çBa”ˆ A1ƘÀµÖ€!c÷ç™™ïŸ÷g œs‡ýWjÎ⢦9g¦Ž²‹:X³Ž5cL3Æ´î’Â@i­µã8ŠˆHkMŒ±t@¹®KDD¾ïS’$T,cLK)U’$€<Ï#!1Æh~~^¢,//S«Õ¢ ”B‡a¨Ö××É÷}zýõ× B˜}.9²àçÎãwîÜá[[[¼\.‹(Šx\Á·¶¶xïØ0Î×k¸µ²Iÿ+½6è…"ÇûV4S¾q?÷Å.â8û^Û‹ZäžcV‹ãxàv0¸uë–€åååÜãY @èÕW_eصk×RP«ÕR033ÃÛí6ã˜û¾Ï•R\JÉÇJ)[ŒsÇqx’$‚ˆ8cŒwÔfG‡ooÂèo£Ë…\)%¬ß¤aû\Óëv±Ñ‹ïà{ŒQaË IDATxœì½w¼Wyïý]efv=ý¨UÛ’ldãŽÁئ¦òÒ.¾!@xo!väMI.$¤“BÕ 8l.²«dÉêÒégŸ]gÏÌZëþ±fïs$dIÁ$öú|æsÎn3kÖó¬§üž2Â9Ç“ã‰;4@IˆSvB`­”¬©TØP¯³xýêÕì8r|hâïÁÖ.=e×í_ß@ ”ÀYR œŸ€å~µ!pÖ‚Ò`3>)OÑ ¸ö ÆeàLÀÁà…!‹Kà4(¥!íÅfz¦K€°'1›SuWOŽÿ¢ãIx‚'à >žd€'øx’žàãIx‚'à >žd€'øx’žàãIx‚'<÷8vèÇ{ÿ©ÃåAëFpîyÀeN¸mBÊõBóq?ðmàëÀNœ{ÔXÁ·ñßr¢;á 3ÿáÞN±taX,! ÎI\–bÓ \¶kÏsƼÚY Y¶çþç>ˆsö‰ 1þû1€µ`¹ 'ÿ6\µzEebA¹Hš’z‡¬Ù"3G i‚3y,MJÔàÈ0dšÍÿ4}RýÍw‰ðCg  ðã“ f}bg-¤Ù_Ëão?{3•±!ºí˜útÓMΡJR+²ŽÄ:É`-2Œå A¥ˆ^Òùù·÷¼ìO ~4ÀáWÏqâ²ê‡ÊýIŠÈÄÇÞ]Æ©`g ÄÉç+gnyùªó· Á¡} 4ê]*ÆÆËÒÄ’´:^S‹Hc\ãŒÁ6ëX¢2¼e•‰/Ÿ½ýžïÚ¸ût”:é9‚ÈSc{[ ·z?ò Л Î9ðjîXý—8—qÒº6Ë ›ýÍÀ9[_¾þâ3±Î±ÿ"—\0Æ›_¼ž#-Çç¾3Í¡}‹ˆÅ&ÑH­@JùîVþuÖh!•$‰׎“Ô7\RÛ~÷?;­^uòI!„œäyü¸h ÿ–&¹$ B]p'ÁÃÖ1/-lX÷së.ÜŠÒŽÙ¹˜ß|ýüÚË'ú_Û5Ûáð¡B,#¢³þ÷Æx; P$kÅt›-ævvpÆ2zñ¹¯œ»ãîÏ;©>…|ôŒ¢Gùî·ÿãôø ðëx&0œØ >.6ÀD Úp¢RÀ9oôEÅO®¹p+Q$Xl¥<û‚‘£ˆß0ðàá6Yb1Y†3—YlfÀd Î\šbU@8P¡sdœcÍÅO¡4\¦~hêÓÙÙOyÛåD† ”ßû žæ˜1"%/ND‘>®@ÐÄ¡«AD¡ˆ¾†|,Yö–36T Õ"8K7N¹è¬áþ5êÞõ©ÃìØY'í$$]CÖI°Ý.tcïí é%A–᲌´ÑB…* h/6‰›1£›7„Xñ.p}’BxÃWD`~ú”àÖ2¢5U¥(+Eé1«hD 'RpñÍçwÿ¯U'V‚1$±CZ÷ïm04Ò‰ ×Þ:Ï®]5’F‡´“´bÒNLÖé`»m–¨ä°iZƒ„pp›e´Ï!M8PEVÞa[?À‰ã$¢Xö7QzLës¼c\kBçˆÃ<Æß>î pÁ¡«Ù¾æï 纷 s¬yJaåÊõBIŒÉè4R\æØ±kž{÷ÔI»&NÉ:)I»KÚŒIm’VÓn"p~÷ À\7¥ÈÚmd!$mÅĵ +¢Á±N«q¸[ ½­#+0ÿ?}öï)¯k·ùdµJÝ9çÓ6zÜ ^pø|}â#`êàŽW›9À>GW*˜8%‘Žf­ƒÒ’æœð¶VfIÓŒ¬“‘´b’f‡´ÙÄ6ë“:BØ,Ã& ¦“4è8ÌõºÃš —¤8“"¬õÀÏÃùðÎy| JTÈü»NHL’a $*ŠV9! ,Õô<Âü4¨"":‰•yìcáÈ­åxk®~$–àÌKþ ß[ûQ¼QÖ…Gd’À¦)6˰YÝ&íx詇/ëz$(×9„V"´¥R!”DÈÞáÁ!{%b"âÑ@h„* ‚a7\zâ‹rC ?Çã55~d §õ 0tðõÔÖ~Ô#u®ò8fäwè2çcsBå»ü¢uˆ Dê´BJP´B(…ÒK‚3@‹G‘¯t±øõKzæm!ò5;¾ñ#ðÄààëaâo=@ã®Rà¬MM’àlÖ'áó+9 CÐBkOp¥AÎJ!•B‘KïûKxËë}0÷åKü[ ïêüˆŽ)8v8Uñôt°)QÆîs&qÖâËÜÇÌö;_†!"AiD =±µBjÿ?Z"•—=^¼¶Á5rZ!<¢©ËÈâè²÷OüþãG’zltÿk˜ĺðk¾\p6»Õ¥éùþGÇéøÐ!è´Fê©ýΗZ#´D*…Ô ¥eßK‘Ãý‘é}â—…a~lËÉ/Âiü—H uÞ²è-k$ý¨šs·a d†ãÊÜq¡¤ÒK»½GüüP¡FGþP‘FÂB@PБ"(ê=Ö:–΂!"äà'_âK–VèxƤxØ!ŠyèxYàSˆï»,¥ŽOH‰PÚï|åw|ðBkd¨PßýZ+”VH-¼D)wk—X„ Q…!îÿ‹->Ø÷8êüOÔ8žî/ÿeÀxbí߃°ËÂ{œ³ù¿¹x¤›©Cïæõô½RÞ 4J{âë@£•¿–(­ÐZ¢”Ä pÖ}céœ!$2(”Gü{§"qè$Æó¹fÕ*2kIûÈp² X„uy­ãÜ$έêç<¬p©@y¯gð ­‘Z¢´\"~¨Ñ'~h”–~÷kÖâ$w,W Uˆ*T¹ýÏÇü[?J50—£?H0>.Ó]žtlb£;æóåã)û_ '‹Ë¢x|çpI‚Ë20©g„å? ¤©=ýŸz2P¨@ç‡B‡Š0RD…€0TèH¢C‰R ¹[²¦‰AËÊC>×#¿ÖÃÞìò×ÇÞ(óú$Æ•33”¥$‚@ô£?4p97–Tdtñúªw$ùU¥}n–%œð!?w“3)Ñø8¥õëÑ#ãÈBÁ« cr0IxxWåV½Rµø/‚@¢ƒ¥¤—R¢•g­ÄmÎõ@F2ä®Ï <²è_¾³e å7¼ü{y’ô©hÜ :Lä?•\®ƒ2 MSº@žÙ„WáþÓÁ îL!ÜéRºMRºÍB¸‹Àm„»ðÇÀ¹½óõÖòeû_6ð´5æÛÁÐ•ë°ÆƒAz`ˆ`h²<àa]é>EÏ•“¡D.þ½»§´BÒ« *H%PJø÷½šø·BIS(«EÊCÃÜü‡ã¨P,1ÀÑ2÷\,L‰»Y…c-Ž ëplÊ_—pÀýÄ|˜ϤY’-¥ûžàЀpÎo¼G9þólç°Ö’à“ë ¯ÅyçýŽšŸ_÷”ýûI€õCC¤d¶Ýf2M±€‚HŠÎmkÁ¶]ÎýÒ¿Y{çAøµ.|z‘Ã"^~˜ïI¥i;:úD„sî”÷ Ì€5À¨Œ:·â]o}ë·ž÷ó?Vû†8pýõÌ<èóïÒ”©éiv-.r0Ž ¥D;G (÷rܬÅ·ewðògCýôaøûèïÀ6PÅàÛBr©iµÐC`Átc\·ëq¿r… *€СFF‘÷ñ£]BEiï뇹 ¨„Wùÿ9¤_Eˆ¦T!Ai„ëß9ƒ0¼¥ÊÂîÌ3|gð¶â Ÿ- ‰ç×\ÇÉõP:K1¼.D«!«Ö–xÁÙÏæÇW½’|ü3÷ýÍ/üÓ³)1MXxì´¸nlŒkéÎÈêÕTV®¤82‚®T°IBçÐ!ÊwÝÅoÍÏ«Kç½w¿î︠ ·c+€ýk—tþÊ•ç6Åâ<¦_(z‘k­Ï<ËC»b ãƒ>ä²Ï‚@€’(ÄÿÉ H] (ó¥7ç{'…V­sþ{nùÅíïùÔŸQY[7Ž11¼‚PE´â Í3c fÚÔïÊpÁ5ðZC ºqJ7Žyá–W1¡·õ×ëÕëq¿ØñêÓ~v0u"4yÉì,_ž t~§d,Ü^ÿÚ×~§²Œø½agfÈffƒY(ÐIS P‚UÕ*CccT'&ؼ™Ê¦M„¨áah4½õVöúÓÈNÌWn¸qûàåW¬–G^3iW\÷—’ZíOl–yd¯ë5ŸÈ+„Ö>Xˆè§j{^XöÑ-E/ø#P°ø—( ˃\ó¿–ev¶X}ýÞÏoÿÊägß ¯¼øùÌT­ÆT³éu~P.— «U¢ÑQ k×mÝJéœsÐcd©\qÅÙù'ÂÓ¯¸‚íô¾[·¾ó7Öbᇈ[ïèÎÕÖLJI;)BIŸ:ž!Nˆe®zÎ ùn÷ßYúH‹œ©-?/•Dê u?¿ûõ_¿µ=0Ë'¾ú1~㹿Àë7¼‹!±€#Éܬ¿FjRæÛ5J-ƒ]Úå Jï6Ì´cªk5w%»¸~â.Úð’£Vô¶ô+\õúgžö…?ûæ/ó}>H‰Çæ»åâýªî,Ÿ GÉpGA~PnÓñ_Çâ-þ7žyæïÏÿë¿’íßÏŠ!°pÝÛÞÆç?ÿy42 CTVJhCt¹L08H°reŸø”ËŒ\}5æç¹ÿOÿ”3?ýÏ¿ðñ|àæï¿îWn^óqyIóБ;‘A¤V˜îR>†€‡¢„cüö¿›ß0î«hq t™Ï½IùìÞξꬼýù¿°æ_»ˆ7]ðZÞºñúçZnf"ÚÅ®è~Êa™0¨@ pP‚¤f™Ý›0ûå„ßøÃ¿å†·ÜÍ_¼é/8=<“ |eÏç¹ËÜÂÄkË¿èÎÖI91¸ÙAÙ V,© °õÎ÷0çïI€×R«…wñ‹\ðpèÃæà—¿Ì‘ÛncïÂ/¾è"VW«ˆv›v­Æ=Gް¿^ÇY‹±ëƒ3¦ß¡ÛAž·çI3þS?Eëþû©ÿÅ_ò[?ûÿþòsßúöß¹âðÕ‹7®ù讽øÑÆž¯/­]‹ñ1A¢c"†=Ä¥îø¯¡’”«“föRJTP",,™Íï~÷‹~ùöþ&ãÅ!®ÞôvO|çñok€÷Åm†qÓ[yájÁð…ÕbP ÞŸñµ›ÿƒ-‹pñ¦ ¼èœ±n|3ð…@2Ák)òÉ7\)f¹æðFZºÂ« K(æÉŽÜ¼zû‘#”„àÁ_ùº{öðô«¯æ‚7¿™ [-Ú33Ô ÖhÐhµÈŒAKIf-I·KÇdí6Y»Y\ìïHÇÒÂê‰ *çžËÜ÷¾Ggn– ðK¼á (|<™™z=BS"Í X‹ÍKÏ$Æo¿œP8—Óßõ„dh¸ÄžsïØ¸mU[«Œð…7ç»ßüíÚ}Ÿbx¤Àe+žÃÅ‹ü"ôd«ë ÙÍ´A3i“t3Ll}#›::³iR¢ñrñóÎ`€!ö™äÝú+Ƈ*´ W£øä Ãw®Z?Ëgö’I‡9œ¢ `TˆËÚÎ1é«©œvë.¿œÅ{ï¥~ð ¹9ZµN‡V»Mb-”X)iÅ1ÝFƒdalzštjŠìÐ!‚‰‰þîï ]­’XËšmg³í_¿öÆ[:é{Q%æ6AL2}g2‚*6·œ“ ó„Qgó ®×wtS˶§¬b×wvpïg¿ûí{U² Íÿå‰/ô…¼á¬Í§sèÐa¡|ež­ì纯{7‡Z2Óžb±Ý ÕNèÖŒ~A6q$‹*„ºî $ƒQ\zö…Üzë.†Ì3»›0 qMNÜm˧Xr‚Ø Œpž—Ì):,¬.KYqÀ–•+yÑßH4x€ÆÁƒ´çæèÔjÄv›Å8¦¦(áýñÅN‡ÅÅEš33´&޷SG{@ÙÁƒØ4¥qä6xö¬«Âú¤_DˆLhE:7C2·@ßì³Îæ;='¼³g!3Žz+cËYã$ó5îü—oƒ2“HãEÐ0¾¬+ŸråúuÐLÏ×è¸&»;Ûý5òKèÞË‹7ñ@s2[«Óšë’Ôr»SmA¶àHŽ¤Ñ¨w™¯790?ÅÎÙ  ¯ü™g1pŽW-¢LÃê“"R/Z7KÁ ”Ë%@ù!6…Ïæ/D ;w’v»´¦93C§^§ÛnÓnµhÄ1µÜÔB œ#‚ùÅEJ¥Ñþý¨(!Èâ˜pÕ*tµŠMÒýûI¤15ÅÜÔÛÎ;±oï2¬ûdN€I„X+M·‡,Rá”ßýÖæ‡q$IF»rùå˜RüÕ{®¡\šàЏñ¥$à™Û.YÇìT™¹E4öqó¿2—LªÍ´ÆþÎvÖïá¾™û88?Km¾CkÒ@šg­ ˜yH qèk-œ³„E’¥ì:²‡ $üµ @‰ (Žœ0‘  d±ž ?à7Ç3r#°*ñsUÎÑžœ$IZÓÓt‰ÛmÚí6õV‹…8&s-eÞ7È4$ajf!ÖZL§CZ«Ž!‹E0†îä$ûïgazšpÿ>.zé‹Y ÏÀ‰Oæ QÚpÖׂ&îzXˆP´X‹í ƒæU?y&ç9Àÿ~ÃÇ ÃP¹!žÏ¬õÉH¦ ®Ä¥›7­ç«ßø. Ó)÷ÏìB ÅÁö~””tÒÓ)œßÃþ™if§,H±­%Ô9O—@6 ±6‘aœ:èH‘v,“‹ÓX+iDTO*„—gÓ½è‚Y>sǨg€cõëIœ;yœ¹ÓlÒšž&‰cê³³´ëuâ8f±Õb>ŽiZëa×|N½€…‚F#¦§I³Œn³IunŽphU,âÒ”îܵƒ™ŸŸ§05E´bk l!­jç¾¾.‰1IDuãz%pIBœ¤tR‹Òާ>eœ·üôÙtæ¼íê€ÅŒ”‚®¿+ÏéøÝßèr¹yÕÐ8s35ÚG`×Þôâ˜Ë{ ”¦ÄÔÚ-fj,ÎÅ4¤d ørnw ½°-Hgg°™ÃªE·c™]¨×3o©ûÅ –š#œàÈ™º”å :E à -ñ•8íN‡ÆÜ™µ,ÌÎÒ‰cqÌB·Kì\?¡wåÌ9´sXá'ÕL’éiÚÍ&ùy ¥Rkœ1´[-jµ±1´j08ÈȪÁU´»HÑÅŠÂÖù\A¥p6½9c-+¶®fãÆA6¯®pƪ":‚o~övþé¯ÿ«FÂs¡Ÿ¦åîÈÈDiõ@4Äb­ m˜ÞÝ¢ÙH8X™G+A–ZâVFg1#©YlìHgò”ÆlÙkl’ÌbS‡Ii×â2ÇÂB‹¤e– Hû¤SÍ{RàŠYϧ*ÍÁ‚ÃOtŒ¡V«áœc²V#1†z®ó¥abç©s(çr5ë™b¡Õ¢Þéæ•:ÎZ2kÉŒÁJIÜé€RŒU‚U{?Ïäæ_•f²*DÁ~ò¼=g,³÷`ö¾ƒìˆ¾Q‰PÖÒžl@b`õ:RÞØ²‡Fʪ™iˆ‚‚Æ?âª? †ŠÃZjÚ­d A½“Ñ Nâ[Ð$— pßÕ×ÌW/¡Éå\ÒÔa;Y„4g2L _ÏêÕÆÂ)©5ÈÏáàH€Ü3Ùã‘UqŽý $ÖROÓ{ôp÷£\fŸãY^Äér÷P扞,ë§~»ü=ãIƒ””«#™Ã@¨ÿN‰ªïåÔkè”|B|b§I ÆRÁÄ(Zé<Ù”ðêÃ&Ýÿ9û«¢—£4ûiy%¥‘0Ò(Ò®ƒ \æÀJL—~œÁ9NxfHÁ¥Î?ΰåö ™òÅÚ/„]ô ¡µ;õ¿ óß*öœ²b“P8u PWB,8–@'ËPBPP %åQ’¦_ ˜', ËÖ…<ÀåFbObøz,Û:G׌sX¦ ×OüØÊb­E¤è¡q>D. -­ü¸Ô’À»ˆB L¬Þi+Co³içßÁþ´>A<„šõ@cd@ ¶ Ê+ËoÎY‡ËÄ–0÷¼¼A,Oâ_f؉^ç ¦•·2pà$ "¢~ÒÄÂ{!ÈS 9 â®@ˆ+„”ý„D‘ûù½°«Ë3xm¾Ó­sdy¨²ë  ­Å u®ÿÛþuœëg½fY”BÆW¯ K¡ÄCÇ2¯ëÇy‘^çÜÐ;YŸ©|1±Ã ‰°Ž,ŽQƒƒ!Iô\'Ï5Yú7ùÅ%Í…‹Iè'2Zé–òT8륔³ùw2¼¨A ´ðb}yÅzΓ¾‰¥ÿ_$n©‰Z—»œ]šúÉŒÞÃ45@ñ”tÁôÃÁ·ŠZ_!ežP)„·ö!¢Àëxg-Æ9t PÖ’äÄ5Î,‹ô!áü>ÇÐ’´3‰AttU”B#!—½ØÿÃÎÚI¬5Hí‹LšSó˜$çŸ$J eYr «¾[[A„CäY­.õ3rË ›^Óê<Öî|""È@€råŸp*d/Xå—åÒÃøß¹Ì3„5î["à”0€íI€SYËàœû’’ò·ËAЯ¯rëwÚÌwv΀râkÑÖ¢¡›z™s¸<ÃUNJÈ Á Z*tÌ.Ä "\–ÑíD ¨—ýŽÎKÇ=€8f~Áƒ0$MóæH;IÌä $2˜r‰ZÝ"±”P4f ¦Rû‰qyîŸÐ€¨d(|£P BI¤f‰r€Î°k68¦é@ò¥S–Æ+¼a©Ám§j8¸5±6/ Ö9Ÿ|¹LüÓSx1ozRÀ²ü¯”i ‰$YFl-ÝÜð³¹ÞOŒ¡ U+Ðiq¸n ¨qÈÝzÆÖ ’¤›yŸéÛ›­s µ$*´cföεc¤–Xçp.·äUÞÉ0*°0Ñ¢Ey¨H£Þ„y¿SÉEº³^ÌSŒ@„àÃÁZ CúYH=#XúÆ&y¨B óøRÑšKc!¹õ”1@Þ·ò”¦„õÎeŒ¹ÆIùÊJ©DÒí¢”o¹"¤\ЏåŒT.”R¨|×Ë,óE޹ñ'¡m-]çHsÛ 7FÆÇan] „('íZ‡™ Æ&†¯ ´$í¦tâ g!%…rˆs0¹©=3˜®A(…ËŒ—VæÐ­E ‰)–èN3ŸM3¶ºÊ$Í%QŸ[ñíŽB/òU$¡@å‡T~çK%úI*Jx`LàÀXÏìa! ³aS®‘ËõßÉ ÏÓØ(g€èÚÖÚ¬-.¾rllŒb¹ŒÈ“=úmZœ#évI;²<öosâe0fY_Z”sƒÐæÐq¯hd|Ý<ÈžttÞÅÃ:oIc‰ë-´ºÌ.°rí ã«*Œ®(y Û8f½O1² IDAT¦›ìß1KsÞ‡Ù”RXk–ì­p)‘«¢²™qÎÌ0±jw»#}|½·«dÙ_FUþoèu¿¯7 ï=à뢒& ´w[ÃáH“^~„eþð¢p*¬??WW€‰?Ëëô)f§Ôuq’P_\díi§ÑnµX˜™!ͳ!Â(¢P©PÅdq½N–eý6,ý$MŽ6úŠJ‘d™Oq¬X9Ξ{9¬érBy+×çø9¤ptš]öÞ3ÉþÃE†G+ÔæÛÌO-"Œ'„µxï Zã¬E rÜAyÑ\pÐYÏŽw1>QñDÏqlA¾ó ^ßË('~$P@iÿWj%•J¥%q+c±“v3¬ƒ T G •8°£FÚq¡¸îT!€.Qa)!äTªœs…(ºáÐää³V¬_3†ÚÂAùpz·K³V)¥:ªx„.ð;_¹ø¤'¾Î‰¯}•ÑÀP›Áä¾:ÆtYúËô)”#öÞ´€‰!ä3O’ü=Ñ_‚ñ÷Ú~ðM÷>;ÕCÂ?T«¶wr’¡R‰j¹LÜíö‰/ó¿a⬥>;K¹Z¥œ3Ko *å½cÐÎåÄ X].’-Ìqsº*”«åíü½ðu2‡[E_0ä©ÞK ƒxˆtKÈÐ’áêÀiAÑT¨ØÊBç«VB|„^¨Ö<:×÷¹¡'µ¯/*·3šõAAʼ±E®÷ó’/,(ÝWcqgBi«É?Ÿ´˜VÞS±EÃ|ªm3‘Ö»ËQtúÎ8kÍJ•J¿(±îßC…!q«EÚíR¤]¯÷ÞZK¦&DRbaÕȇÏrwñRÐå<›Ë<§[ Ò!…ì'i‚·ÀÂö}dØ-Cˆ— bë¼]a¨²£Û¸©C_¤²V°^9Ö }æ¯Ì ?JªC ]’,#*KŒ•3 s½ÔtGÜȘ¿#AU!»mÊÌI1@nœºŠ`ø]éQ§úÁ¥a=˜ô†Vjûp±xút³ÉÁ¹9ÖKIX*ùàS¯ï^ïk ŠE’v›…™GF0Æ`A)E¨½n`QWX[‰¸wAÑ8ý|FBMÑó‡€x‚Éüî½÷ïEº·–æ(æÿ¥¸ÀÒî—¹x–ÎáH(v¶qxO•ÊÚ9fE®ûsGE ´7dU (•Cæ¦ÚሊA¯‘)=­ÞOHÅ’´ = d WHD ¶Ó= ê÷î)€œøa€Rùá{˜÷ô^ïïQïÇuq- $IB³^§P.“¥)½ØBšçVh ßÊ6sx÷<©Y@)çË»µè·yÓy©·Ô‰„PºÞ.·³ÄÖY¼9¹Ä½‘Íw¿u8 %éÌ3È6}ª,ÙÚ3‚P,kZ5?÷ ’ý‚Ô|m06#NR6­[EbRØ1C²èÐ@Âø¦2õùîƒ}¢'å…€¸™bRG’æms:>©ùØñ°P°cÉïm SS”ªÕ¼c–ÉC/;ˆYê]ÇB)È×Ô¯®ÁÒê¶ ƒ—^z‡§¹áú{IkŽp@ZÇØš+V 3;upº‡>ÚœudÆÑjfTÊjé><’ù°ÈrßUë½>6’'i÷óí{ÓËÖÉQ½$ËÆ’v›•kÖt»8k©Di–qËç>GszšgüÞï1tæ™´''±I‚ÌsDq§C†~²¹o¬aÐÁá‘Ó{æEl;k€M§°zÝ£++ )WCŠEM¡¨(5aQFš Ô„¡" 4a EÊüP„¡òýó~a¤ CÔõ~«‰*$„l‚Æfôþò`EI·•¢#å½PßbŽÄ¤LÖÛœµz ¿÷S¿ÎÜ\“¯ùL숥‡;°rC•¸bS;æRëKŽ9„ð 'I’=zš`þA¯r{y–ø‰÷XfÅ›NÈex‚‚¸ÝÞ( F7mbÕƒDZw™óßöO|‚ÚáÃ<ãýïçÈ·¿Í½øªRÁq³éwŸ1dIB’e¤iж–²€û6= U*£ |õúGÉÜtG­ŽCôm%ÎŒ•ëy!Ò9p¢ß²ßÒ9ïm(p”Éâ§#Š;± Ò®ÅJ°ÒMf2Ò¶¡\ °iŒÞýü·sÙ–§óŽùMnÛ¾‹P“w%õÁ¢á§oXÍÔT¸ã6VªË6 p¤&#M¡¢£%ú>‚a›ßpÿé,Çv]>u "zÙ7¹jpÖ¢‚à…+Ï=†¬=ã æA…!&Miw:t üÖ·˜{Ù˸ìƒäǾô%îyßû8|ÓMèJ…Õ[¶0¸v-ÝZpÿ~õ:…l³‰*Áî—áº16õ±W)s7 |ÇoßÐ{ù¢È\;ë±ÛÌ,•†‹ÁZ‡1k,B:LH`3/N…i¥Îs‘ÅA‚ TÇBÊCEÖ¬b°\ejf}SGh¤–go¾ßþ±ßä¾ÉxÉ¿ŠÖ”Å¢&,h-HŒaŪ*«W°¢¸‚[¶ï}¡µîÝ*w]…p¹Z{,¶˜ï¥ý&|ñnÊ’!/œs|tynïk}|# ÑaH\¯S¬T¼Ï®I¾ë•Rt›MT"ƒÀ×ôY‹I’W¯=ï¼:ãùÏgþž{XØ·#ûöAR,QZÇ1íÙYâZ3®ºŠ§þê¯Ò=|„ƒŸý4í=’uÚØ4E:´ X,PJ›ìŒVóç¯úÿ‰BI˜vò@ŠW™qãúõݹºÇÚ^»ßÞMzѽôÚ»¾K½gcijév YfISKšÒÄá²™qØ ^Èðú#$FÓêd¤]¿àJC)(±iôt^³íuLT6òþëÿ€ëoÙN±CâB€I-ÝŽ!‰-&ÍX½©ÊÄê1¶­Ý·nÞÎÝ;¦^h>¥4”"í„9*Å“2c(DÎ8Rãh·2Ê%oƒ¤©ï’–…`«ð‡¿%ýƒ&óâ”SÛ"ÆZl–‘%ÉU+·ný§-/{í}û|jUžÔÑévIÒ”v»M±P 24DõŒ3è¶ZºñF&ÿý&6_õRÎyåKÀZêÓ³tê-â¹yŒ•¤ªÈTe7FçR.Sˆë¤V`ŒÅdŽ8µd™õ‚¨»45ïÕ=ñë ‡c½&{©EŠB¨rCÊ‘YŸ¶¥’N½D6ù'œyÚ7P£)kIY¬*LP)”©8„Ó|~ûµ\³ý&¬õ§•(B’®¡YKHZy·óÌ! ¤"I3fëó¼øÒËiwþíŸÜ»ÐFr[Rïp ØÖS`Q:º¡ï{uj$@£Ôž—âZí½›¯¼ò·Ï|ÍkhíÞÍü]wQß¿ŸÖ“33t“¤ß‡_Q004ÄðŠ¥ˆg¦(,â3ò™üû–WðÒ7<CHG…t\ÈT=¥i}ë·0^Äæþ½±“zâô`üOd<œ“Ók{硆¼×˜d€nbh5ç™ß¹uÛ^]ÂÚ6‡§§Ù¥þ»ò&†Â€‘áA¬ù™6ÍÙ.Y'OBuž‰UQ0¼.bp¸ÈÄøçLœÅæñÍ|ú†ëøÖ-÷üN¹Â»óý±«¥ã“ œ€4Wrüã{J,JGœ‚6q=#ÍfÙ„VêËÏx×»Î]ÿ¼ç1wûíÔwï&m4| (ÏΣlÖ9Rch..b’„±1&&F¹kÕY|ðàOÖRmŒÐ’v$1Ò9B—€Ë°Æëj“ëì,³KFß1„\fž<ìx¤Ï—ÐawÔç6ó¦”pàÄ•¡³“ ûn:À¾{G(¬§::ÌÐðÙ¬‘—¢N»’âÊÝÔg2g:Ä-_¤ ²ïª©L!C wéšq‡Ý³{©F~åÊ7sÞ†oÿöŸ_÷Ï/³)/pè±`2ÒÎ á§·ÍwŒVÁžôüã4%k·ß:¶uë‡.yÏ{(­YÃÜ-·ÐÚ»“¦ÞÆÛ Öº÷Ô &óÍjÓSD-Åþ±Ó@uÁX&gSªëB”ÉÖàœñÙ29äkzF[~Ÿàúþ¿_Îã‚-üߣÞ[Ê>ú˽û÷ií °.¡µX‡!*ºsMâë,-°î¢qTwÓ‡¿O{Þ—ø8AéèŒþ\îyëH²„ݳ{Á ^°íÙŽ}“§N‡¤Ý¦›_÷ãðËvÿQ–úR”±Wöe­%»ŒmÜ@ihˆ~C'@˜Œ( ^3ÎøºUÌη¸nGÌ窗±sÃ3¨ C!k÷ë—dͱl.½w%"+“$júz*§}†K.¬³bTóàô fé¦)BHŸ„’Gäêm\ Š<Ê× ²õ‚4ñV–Îú¢™ RK!¥(¢†£ˆ( ”Îq I 5•r‰ûØÇMÿ¾ RäíÎøÇ'·ÄV@8(Ãg~oô‘cPÞ}l×ë7lzÚÓνà‘( 9òÍoÒ:|ØcÿBx‚ƒKŸê$$6˼ϯËÓÀ–g‘GÚXr'}Ð"Ëèv»”*JÕªŽ_…tYFÇÄóóˆ@±é9—³ùÂmLݲOMŽòñ3߀(V(˜˜ã·‘i0%:I‹ÎÄ{9çâïó´Mçpë}ù·ïßF*2†ª¢0ò½†ÉãZ.íf— ô ¤È[Ð?4FáSÜQ¶†1`EiI¡šBh‰V)$K’%LŒ®à¹›Ÿ…k‡üÙW>ÂŽ;§ïƒ<8€$8¾@¤é-ÏúЇ䦷¾ææ˜¹öZf¾õ-vîô  .DIŽbRŸy¢tþ(¶^hY©¥, åž@ϥ̃>äUBiûÔlÀã‹LŒAä×raHPˆJ%žòÊW²þЧÃ_æ}wD|üü_fØ6ÐGa½mx©`ãaæV½“«^v'ÏXõS|cÇwùôM_#Ž R :ðzUZ#ˆ”Æ’>1TI‚¼%}/i„‹.³7ú¬œ#Ë&3à|ˆY‡þ÷Røs ©I8cb-Ï=ýÙü?›^Ï:q!¿Ë;ø}Àb¹X)¶kµä Y‰vPz#Ѓ‰ãóƒ,»íå7ÞÈÐå—e6ޱí6q½ŽÂïLáûùô”§Ðš üîÏ­~™KqŒðÜïõ¾‘Ú6›ØN‡¬gC„!Áà c\ÀèSŸJeãF ÃÄÅ"Y­FíÎ;™Ü~«¶=Üÿ¾°x˜îÀÊ>ô^ÇV?”ð˾g#Zdbómœ1|)7¸›Åt‘_ý‰71Žw3öÍîçŽÃÛ¹kïê Ë U€’L(kM9,úd%Nö»•÷æÑÛùËó¤tí»Ž$]CÒÍ|Žcž’aœÅIC'mÓÎZ¸$‚~ýâÿÃ˾ÿÕ·™” ¤àv•ÿ¥ƒÀÒøaÜ@çœß]iúÝ—}ýë}âˆ0$™œ¤¶gó³³ÅbØ‘A€V ~ç÷ž½«–žÃ+z«›‹rk .g*Óíú¡@±Ze`b‚Âúõ \tgœAuóf‚õë—&ÚlÒݹ“äÐ!\§ƒtŽ{?ñ º/úq6oeãäýÜ3ô< ¦ë÷Ø2B?*‚ÖÓÑ€s á*$ÅëÙ¼±À»÷qíí7qÙùO¥íŒéQ¶neÛi³‚³òXvuîà¾Ù{Ù9³“ÿ˜ºž=õ½,vk4º lâcT%èˆPh©suH^„’ÛÂ!¥EXòl"ÈRýf±Ë‘PC·›²§t˜3W$’Ky??¾æU\óÎWýÎÏ|7SDýž 9(“÷²½þ¥.?a³ù——½å-áðóŸÔÚH))­]ËäÔj5Æ¢¨ÿ¨UÕ#tþT®Þ#ÙúïçH ß¹[JT©D84DaåJŠ7R:óLJ§ŸN°bÅ#(M±óó´n»…Ûo§þàƒÌ?ø s{öphß>­xáÿü ÎÛ·“#¯ ZßÔº¥‡Iåu‰ËïË ‡ÌÓÈ%'.ÓÄóÜðÍL¬ãŸÞÎÛb®›ÙÎ=ë°iåÿmïÜb,9Ê;þ«ªî>—™ÙÙ‹g/^¯í]|bƒmLp@"Ül)O!‚ Q"òD yŠåE "($቙‚‰‰Ù·&d2AWWyìSŸ¢"VÏûˆÐ-RDê®(âÿÙ¤8 šŸ§Z\¤Úµ‹ÞÒýƒ)wï¦Ú¿·°€1ÖÆc&>J³ºJX_§>s†Ññã¬?ù$õò2Zט8ýØc¬œ=‹q×ë¡Î1¿s'§œF,/^ýÁæƒÿÌ·w/í<¸kÞÍ—ý²(úsC Öõ«þЂúq=ühc$µo&ãñh¼²vêâÓ'곿äϾö¡½åÀ£Ø “uÏ÷¿¿Ìƒß]¾Í`ÿ?sÃá=êÚy,\Íõ{®çðιfp= ½Evõ÷°£ÚÉ/ìy 7ノÍp5›Op~|š“›'8½y–•ÍUÖF«Œê ­ñNc¬b-¢”®Ö›‡zŸþÆçxݾ·2²Ì»] ÜÇYX7SHüÅTÄû÷ï»þz.Ü?›ÇS^u~cƒúøqÎ<ü0ëO?͋ロc<@Ó4hÛÆRnQt¿³ÐmUE¥ó‡ºfrö,õ¹s¬=òa2AÚ¶Ûò-ŒÇñ±º¦ѶËÁE˜$|àü¾}ì8p;ÐÛ¹[–±Ÿ B[×lœ?ÏÉã˼êjzK_úÄ{Îr`m…zoü®E?B9œcZˆl!ÄîÍìtfvµ\ÿ }Á]áýÇŽ¯á'0·ÇRUë õŠoôÉô©s+œ9w†¢z‚þü7â'Ú J¨\E¿ì3¬æ(MIUô¨L^ÑO`–XèÁ 3¬B„Úøx¥ l ‘A,.wW†; ~ñ¶k9zì)~÷ó¿ÃÍ×_ÇáŰÓ-r¦^æäè$ìäèÊêû‹Òþñ줿$(ûý÷\8s†â¾û˜[Z¢ñ“ gŽåÂê*w¾ãl=ÊpaY_GˆÓ–åÔüg ¡(ÀZüdWþ:ƒEëè’2 ÓëEj˜(½LžÞCÛ2ôžÑê*óû÷3àëçÏ3c² ŽØÏp&!„ Eóó®ÞuE(鱯ÜÂ0.K9zŒØã½q®ƒƒ0 £ØV!†H&îUD1!’y«Gqš¨æWZæwT(Â_þ*>óÙû8¶¼Ìõ×ýaÙg³³²¶ÉùSªÊ¾¸Tf¢â}Ÿ\^fee……ýˆ²ªï9·²‚ctáÆ†ÃaÇñãfüÆ^bfâ„-ý×tõiÄ{LÛF«àA#©q9`£q½^¼îP:ç({}.<õ4k/»ƒW^U¿võW¾ùðÎ/¼’ˆ„sà$€YÈmD_¤[R%wÜ÷êµâÕÕ䥜:sŒ²$ncãRõÈì¡”•cØâÜe¯¤0±åÝ/Kœ+ãžeAa¥+¨\‰ÁNë"Ä[áÕ$Z<+1Cð!Æ]f€Pà¨ë€3†Á| ×ÖF“'¹xγvFçÏ`K%Œ…ú"øóP-Úƒô¸xü-€1æŸP¹cïi××é¥è¾ê÷±ÆpîèÑ$3¡¨*4„ŽfÎea—%®×‹„9+èõ:Êã\¢ÃˆÂ×¶Å…@ȼ~¹ËÚ¶±­Ü4„É„Ð4ô÷î¥7?ùüeLX£•Tà, ¿´:nþêw?ÀbØ÷ùWÅÍ$Ý3`êBZ?E—}ý#„Šzy6Tw©*«G1×OP*Òž”Þæçúì›ßÍQÿ#Æ~‚sJéJŒ@¥‚)ËXJ6EÃ8ë(ãJ,1sêR°e# YA‘Ôá 1´eÜÑ,e}uÌúê˜j¬Xü2<8gÖpºM2¼Û:w¡°6îé”U;u! Æ°±ºJn®+ò(ĕ۹‚áý>fÆM˜D±¥04“-@¬Gªƒ~<¦^Y¡˜›cÏk_Ëxm§zˆz2Á•%e¿ŸötL66cj~î¶ñjKh-u°<õÆorð‹¯J{÷%³‰ÂÑüßñåàW„Ú!-, çnkšÀh4I¬^±B×ÔžÚ n·¼™{®} VGlìÙd÷Ü.UŸÂ8,Î: M€Î %ÞOÅ‹'"žQ^ Æ:&™WNg…¢ˆJQÏ®PŠÂ¢hÛ@=òT=¨¸6}µhý ×IDATŠ´Œk‚´ ÷ ú×ÏhTõM…Ѭç:¾H庨¿óÁ³. »(ËH´03«M^T–Ñ*¤…¡&Ÿ;Ýz¹¶í*ƒ´Úùûïg¸w/·¾ím\8~œóO<ÁÅÓ§»ŠZhšÍMʹùÏwuÁEÄpâ ÷qèk¯Kn^ $ Çí_ø í…>2qH0ˆˆöz/ÚœŒh¨ú0·X {®šçÐ5{¹nß~–wòï'¾É]K8·GAi œ¿ãZäÌ fmð4ÒÄÕA¾f&É T£†Ò–ÉMˆ´Î ÎÇŠ  ±¶bmdhW"-žö\T2ë@…`ùl ° "×(™#Ál9Hd¹´›53¯²iöÛ*a±E¶æk¦òI±²BdPG¶(mÞZ “IŒ"ú™L0!à†C–nº‰«Ža¼²ÂÙ£G9}ô(››ŒÎŸ§¿°€sƒ1æ1o,#± '^ÿu}õµÑx ÜþÅâ/º@%®ÞTÌ Ã!+k ›à†píá½¾v?‹;æ¨l‰Šáä…S ÃjÈÐ ¨\EpBÏYT<ÖÎÄUËB4ñšTBT±œqùPBOôsZ×uÔ4„„78pë­\uäO>ðã³gÌÏc¬=lœ{ b |Œã‚8N¾á>®ùÒë‚Û¾ôÂÅ>Ú SŒžQ=l œ][åꛆ¼ôÖÃô¾ ¬n¬SÙŠ^QQº’ž+)L‰K¥)p&öñK[P˜’Âx„– Å"P¬ZŒ±Ö"š6´Ú™½ |ˆ¼…Ea©ªŠRï>Ä—I³7¯>Σ“§Æî s¾×)@zíaI‚ÞN¦ØÕùc0П›‹&<¹ÕHÞ4Ûà™]WØ }64&¦m¹XÔïwÝEÊI, $î`cmT’ä:«’>××5²¾ªºå_øBšµ5ð~oçVˆîOßuwýÉ·¨×z˜Ú7Ý݈HcÙ»P,ðÊ›òý=0ö&ª"•½I­_“èð…±Xc±Öa¥´%}7 g{Ùumã°Ik[ -ñ⣅0³”zñüÖÄ*e'‹„ƒÔ„pÎ174ø*0Ú0ŒÚ†6ÌM’ÆhŒ»£Å8œÀfPcn÷!Lg~* k”eÉÂŽìØ½›¢ß|~ ë§Ðùï-ž|ÌŽl f>#.‡ÃaHRÓ´1+æösÎ(­±ñžÑ™3`-½¥%D¤Ìô29•ò¢Œ½as☌ Ú‰EÚi#&¾NPÕrin «–s+k/—0žNgXîóÇkuÆÅÙ_”ôÝ는$õI爫—·âfܰµÝÿÌ` ¼4mÊVËÂîÃ]%e•€,3."V””Ûsú-@Lýnk42o‰ÁZ†Cv,.‚µHÛÆuyÉï3³¤{;ìsBpŸå9Íﺲåù1‡­*êS§2ḽDq"nXÔ"q¿æ˜}…ÁZ޽ð$•sqƒçgƒ™=ëÈd,i;¼ôögãzÜNűå«o»fF â¼ÄÇxa°£¤·P0Zi_ð¨p3 ÷·åfH—x¡!îI0²sq‘¢(¢i‰‘úöÙ÷ŒßB»8áá¥h3â&‚š˜@ÔZÌhD&r á azÞçøÜlQlU±qò$¡mOƒÁW¶[#“:aÖ—ôŠ‚^YPX³¥4{óî+'Ï:U•n¿(gß&(2˜TŠy;‚hLí\ðŒe„¨§ A}‚Á¥{Aˆ36R¥JµÌX¥ç5Ò,ŸLÖ»Jª9ÇèlËø¬BÌ^˜_ÞÅ­÷7©*K{ö0?DTOÓLY>gúÖ`g.Î05¡Ý㳂‰i`îý§€‘ìI]c½G{½ØHî§+‰Ä-çóß9s˜¹†Ùk qùú›·(Èá¦ëŸ‚o¿ÅÆZïߌêUU‰ Û„–~r f¯‚¥5"ÖÚX x*SÑhCZ]»VZD… ‘rúI!ò÷ÊŸ'YÑÒqé×ëÀ&â_G6õÁÞ[6Žy¤Ñ›l/v—²5z±ªr`q‘Fx‘-ÙÀ¬àg/j‹€gžOW²(’Ù.ÜTñ“¶%ln"Mƒ&dP.g¬`V,MçÝ®ÝßÎ݃1ß¹$fø1‡1æ;Ƙ{¶|7MHV@S­@D¢Û6æÿ©;…ùyñ~êò÷ ðÒ±¢ð"àË?‘ä·Ž//ŠçÖnfJšµ`Rªðh¤E4ÐJM¼xZm»Ã‹ÇKK-5"VCw® ¡;÷V¡gåÈÊÀtsé„|¦‘<`ˆ˜zW9T¹Sg,À›|W﬿íLL¾Ñ‰ Dgf¶Î 9?—ghöïy¶'ó.MƒÔul^A4s„ÔjΊ!“I|ÿŒФ3.á^`ðèOQøy< ìQÕ{E¢°¼AAÔJ³_¤ku‚O)ºmÒIêb+âgöYHd“HR 3"0–´p¯ªÞ®ÆüÞ¡§ ®ËŒ!x• ª¢OO{ˆjìäÍÛ89k±‰å[rHš¦KÙÔÚȸ}LSÜA!s¿¶í§> ,oÁül†ÌÇ«ê á׌ãíµoî W ¬Ì’SšdÆ£´¡ífx›¬EÐ >?‚Ц¸k:»%B5n7W8Œ ¤Û’§…’ö,Ô(~ý°µøûþNUÿBTï±$ JÂ7ª„T š:ÉʈµI3},,å¾@:O·FÀZ¤®c‰45œâk®¬¢zªŸÂ˜Ïkÿ„þlcø0ðacÌb+áÍ^ýÛ æÕÖØ3‘y&¥q¬@ZBˆçmt|R‚ )¥–ȇ Ù÷gê:•$/½ÉŠF.bÈdè_ÂðÀCù¢·CÂÞ¨ª‡Uõ1ïFu}»ošˆÑ7fêç¡«ËK "MŽÚÓIóÞb"ûVhšX;Ï\‚6æ,ððEà«óÐOšÆýŒÆšOÌ'UÁk¸ÕÃë7/3°$’#{Á'óï5fAg,€B)[Y¶²7¾VU0 "Þ’`b©ê§1Êß«ðçÀ±íúl«ƒïKÇ[Œ1ïTÕ×Lêz¿÷>.s¶qO“.c°! YLìh ÄçÒìÎÖÁÀ D3Eñm¬ý–-ŠŒ1'~ú²øÙƒyˆ8¹þ@T…^&F^ÑJ{§—p³*‡¢PSQH$òIô1ög²ðóoHèŸFh³Ãž2†EùðÙ纶ç³<ü³ÖÚÏbÌÖÚ_.Ëò%ý^ï¥Î¹AˆDÎ=‘쿳vZïÑ•´¦³ < <…µß5ÎU‘ã?—óû''0œ>I­ÍuAõ‘p[P=("W‘ŠÎy‘RD%u'“iïh«ªµu†jàÆ­ú-ü›Ø)ìë¹ÆÃð8ðø–:ÿs™ççcº>ÍûOu¤˜ý8pÌW·¤Í¥¯½tèÿ<,z¶ÆÔ•q™Œ+ p™+ p™+ p™+ p™+ p™ó¼¡FWÆÿËqÅ\æãŠ\æãŠ\æãŠ\æãŠ\æã¿é–u ¨qÅæIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/notes.png000066400000000000000000000356341217176075400237330ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœì½y°eIzØõû¾Ìsîö¶Zºº–®Þ{ö陑f,cIÈÆÉ‚fL`‡¥p`!„m0` l¶° # ¡„,Y²-´,+4–4ûtÏôt÷LwWU×úê­w=çd~ü‘yî»ïÕ­^ܯgº{ꋨºïž{–<ùíK~)fÆ=øÎývà|{Á/~±xˆ@ƒY@b Ò`Ö Vaª˜•(5f€!&‰‚i@0IÿDówM$g$`Ñj:_‹ŠˆaÎA$GÀáQ1 Ñž"˜(‚ATÌfˆ)`˜8Ä ý׎ ˆ–†åÓt ‚‰ÄôC´ôiyÅ¥wÅ0“|'‹ 3óøF„¤ÆÌ3°&Í-‚„Ó&Í}û›Öyfk0Ic•4çÑ"†HžŸ¨ç iÒù” h%&(0)õˆõ@ûÈ¢ höæO? L¹S:DCt½@NtÒ,ˆ1Txs’&Õ9L' QÀ ¦G ‚ƒÄ  81qD”¢€€".aõ˜O%^ÄTQQÁE3¼ˆ“47xQœ¨˜™yDƒD<’ç6:C‚¢Dœ¨PkÌÌ!„4x33S¢™ Ö4¢â0‹HP‹McD¸šP9|]Äãc XÄD`ì0–0 ˜…„‘f µàD¨­ÁW5Q ,̰F€†H m¢YˆD«Áj‰#-€¹vj‹» ¦ ç”›8[ âì÷ëþÿò‡Ql?ˆñË…ÅG[{œDL ñ`¦&#“dþœ³Zú>ÔîÑþi1q£D˜ Äâgh’XèS%=W„n<ñHÌ÷µt,àk–$Upi ÑÀ;®N÷X$ÿЀÓ<ÞA@D—hƒPbÚ¤wð!s°øt}PðšæÇ…,óÃD¡!¿¿åI)ò§¥wN"´¬ôŒaÞž' o…i¾£Ê‹Àa°¦wÁüa0{{KNn‘¯ùïxð™hß#3wp¬½mh'§ã!ß/jš¼¨/míd…õ‚ÄÀt>ïI·Dq_EÈÔª`!!ŸÆ3#QžM:KÏ tókI"ÉÌ"yÜóyi Pü|9ò{;ïóIÉŸÍÂ<êÁTÞ„z GlbW½òØ‘¿eÉ'G¼øÛQ¢i'sñÜbáûÑ{+“ßNÔP’&)#n~Îâ{.ž{ôíó<ÈjÏÍ6GN¹0Îö7òµaáÚvìí¹,üÐå0ƒµsÒ>gqÎÜ’cq9/kGvpY¨MĽê•oOHë+xx…ߎÂ⽎ζ9¯áõÁëÇë9÷Îë€Ä0×ï\8θÇÝîuôø[0Ö—@´€Ø;i²õ|Þé 1ÙGAÁî¿C $»ä0˜ 1.=ÿ¼ÃÀjà¨r`â¼ó!&oÏ9jØ?¯[ñ³åÒ!Ïòˆ›¹,$òÏýüc¸Ç£î´$…[›£bvð½ýCìplc>HÉ!VÍI’|Ž’Ã¨äЮ¦0l®mã@í ·‰Yó²óÉ9öd%!ÈrPdÏ9"'ШóMPÇÊIÍHšÂ´± àh:¿ô0éW§w)Z É7‚ø€Åì)b 쉥û¹jMc!Çrä·ƒw4Ÿ€mâ)'ÒBjiÌÑËœh³6ZæÉɬåËÇ»Ue"¶Nmqzø$ZÊq´‘'10SDsV+‡Ccƈ`1&ñãÓïS„+ŽRÞD£5ÝßÅê°Qg,ßÇù4Cê4蔣’ƒ @TÄ54Á§Ü’9Äfˆúœ~˜"Mш ¨yš8Eƒ—ò¡›Â½.‚4EÊô†xØP‡’ÂB#¨‹ JÄp±ƒÉ1‡ái¨QçÐZ«:8ƒ TQŒhžèjJsÉMñÄp8‚Jšóh50/)ãˆ`"˜ÚJ/ÉÅeF [;Å› |-w·ä|w—ß_ ÌfwŽ£Ø8-ímDec’óÎ)¶mHâ  ‚‰È|È& –䄈*f)w®Y-DŸ3~óý“èµh8”“à@«$NÕ÷ˆ&ÑçBD5b(O ¦EŸÔˆu‰T`q %¸.sCˆ–_R  "ª9Ó1ï“$#A4 (aVA)¨©2!6)CRÖ5:C¢¦)Ö€…ˆ8—¥ÐH¹GÐ1;yžÈÉ¢6yæPf‡D¾‰f‰jYM c–ÐÙ@kUnÌùXFZ]4E³øÅê<@ƒd €™è—œœ°6+eéÂÐRIuµ&Š1Z]f4m·µEä€{Ì*æ¶GF²­•ô‚ºÅ66ɺ1Mu›RnZTV¦ÔmÔ6;gàÒdÅ:¿“ QjpVÕDçÒ¬Ž $­M„Žg)ëO‹C\¶•Dò³€Ú°ÂBH¯èPA¬‰’\&uJY{!$§À3c’§?U-D¨s:^æŠzaÛ“[X ´×žŸp$帘ø;°BŽ[ø. /ПÚcz·ë"wü™®+ç¢4ýÞfõÄp++û’8¬½‰[Ȫ)ÐmJÉ)ô”9%‹åëÅRþ_ídc«C20á öAòoíeÎ<À•óï"äy·pšš–ô>GSÀ‹ó»Ì{I“|8l ð¶…eã¿Ë;…Wù}^-µ²m¾ÛÂMæ·°åß—ýfËž½ð}±`÷¸Ñ²@ç —•܃w"Ä,M£&o{p^¨-qßþâÿ¼vX&îáÿ;lI:ø°ÕqÞÑ—xÑÚ€ï=xÇC¶÷y÷ÿ¶Ô Xê—Þƒo ä8Q´ˆ¶£7³:k¹p¾eS²BJŽ¥¦¨`×!&4£I‹£7d¹pûßT0Rò Eá`Åcâ+±XA]³ÿÜ&£ÆÜÿCç`oNîâ¼9ûކ<§ܚ⺃”ݬ' ŸÚe÷ù]¶Ÿ½Áæç'L.Ù½²ƒÿÆg?™üï|˜3?ëzªýêMþ=ðz`¾Î4õ@ÐÒáKGì8dÖPš\Æ•(¢sºÀ¬Ït{›~î\ÿ¥›Ô±FWz˜‡r_Xùî“<ô#¹ðÎáOö³ñ×Ðl–Õ‘#,[pO$h³Çf4>×'øÂãÖ}âfsÄX1?_Ñ=Ñ¥{n…jkˆö¾×gï·yéï=Å•_¹EÑSüÙX0~qÕ'7øà_ûk﹟ÔaaJµ7"äšCm×¼¾i°¤&ð;ÿ9n1ޏRôJ(5Ý„Èøcny—Ý¯ÞæÖ—‡0¬iÆ3”Oüݱöø!¾ü—>Ç7ÿÑUz'ƒw¯ >²}iÊJ>ö׿‡Óß{ÑŠj{Ÿzqšìrõr0–oÜ™ |»Cki«‘ˆdŸÚ –J³Š»ø×|ß¡Ý.ĈEaxm§wØþÂ6ÛŸß§ž44éJŠRÐûJ|­ŒžòÔý%>þ³Gµ`|cJç\ÁÉ }fÓÈðÙ.þ‹xò?ç=õþa¯ø’\E½0–`ó1½9¢`¹xûÊ€¼ú[zàOô<¡ÑHurNQñ5Í0`UÃ|b ¤¿¢LoDö¾z…[_Úfïé!ã« ¦Â Å©’î Oµ×0ÝšQy¡#Æà|Ÿ‡~ì+¬Âx† JN~x[ÏíRG¾8ãì¸À‡þÂ÷a6ez}ˆˆ N8½"—¬®ëÐUG¬*êý¶gÁqÂÝêÞ†`EO• °ó¥6¿¸Ãþ3êq Ñ(zJïñ'?tŠSßµŠ[íÑìͲΔk=¾ù^晿ý<ƒÓ]š:ÏÊñ(ñ¹d}v{ÈÚ#\üSÓÝè1xx€t;©‘ˆAµ;¦èEu‘IU@|Å?ý>ˆ»Ô·f ñ¹æ>Æ€ˆR¬8tкX=fvcÄÕ_»Ìéï=ÃÊÅ5ša}¬Á¶7Ô[Ò p^P'ÔU<Ü(ã(4€‡Î ŬËÕ_½ÊË¿x“éÕYªØ(êR†£šÀÞ¯¸öË7éó<ü©8ûgqEÃl/ b¬œ*±™Ñ£pÂl§f6¥.cÃaì<ØçÌ¿ðoSïØ-Dí0eå5b©›ˆ© ® Mˆ32 jh§ »ÞGl@hFìü³+¼ø+W¸òë·Øyy‡ápÈÿ·¿Ÿµoöã±ò§,Ußnˆà76Ù°¦\+hFa9¸ø‚êê”§þÆsì\šP¬t.vrU®%¢fXÇáÖ„¦꽆§~æyny—÷ýjÔÚ•ÇWyä“çp%ŠB(6JV_¡ºÇ×þçgÙ~fŸ/mš}ÂVL*f±SMt4ÃÀàá.%!Fšýšñ×n²ò‘(3L=BI¨GŒžÞâù_|ŠK¿ú£Ëc¦Ã'îïð®óQý䣜zò Õþ„ãnÜaËm€o£È ¤>÷瞥ºù¾Ÿ}?TÍѰìëF—íßÝæ©ÿáE¬úJ$¦µ adI‚T‘f0ÑÂÓnÅ3èö¸ö«7Ñïù3ïÁv&t×=ïýô{ÓÚ‡ÜÅM\fˆ®pß÷Üfó³›L6« é€Lìp‘§¥<‹¸S¦ ~Ýñô/¼Àw?všñµ=vž¾ÅÖïíqí³/3Ý©‰;M„“ïÝà]?ñ(~üAü`€õæ°ÍÓ« ËT€ôÍ:¦§ðÚmàWÕæ„áå)#Õn…[š½8g#1Cyº`û+»|᯽@gCè®;ªQ¤Þ©€×)éŸ-(N÷œ)é>X²ÿÕ Ws“}èž+¸ü+78ñä:g?q†Éæ¥öz1¢Ó´@ÅŒÎéHo½„Ž#NgT7§tO µØÑœ:T†¬96î³õµmz§ºì|ö¿þ‡™ñÈp•áú ͤfý½¼ï?ü ¾ÿ"R*TCf·vR/I'ÇÎý@îfv§plͬY÷¡:ÿ»œo ^™Þ¥›ÈÎSCÎüÀÍNt‚Þ»z¸~‘Êñ‹Ò…ß_ãV•Kÿ÷eºÚCJGyÂóÒ߉û¾ï4êB» @æn™‰`u¤{®KÙQfµ±}yŸó6a¼Ã8 b¢¬<Ôåúo5tÎ8г}ÌŒ“"Ô;3ö®Y9_òáO7þµÇïh¶G4›Ñ´Kò"™ãÎ F=Þ¡ËËÃå¸|ÎbUÐÕ2-5 ³,Êïò2â ––;IÀ¼±÷õ=îûþ˜M‘|¡x!Ê×ÿÎ%êÑWôÐÆñȧîç¿tíyˆ‘0 „Ý *Á\…ÊcôK¿ô2“=\O]™RßS¬—4³åËã¥jè] }%^1½¼‡}ü~"õkò"(5+®/bÓ€H¤ÞŸ±weJÿáû¯>ÆÅ~):Ød›ÙM£¦¡0%pÞ%#¶tÄq TÇ´l_Bd²{›5–fß8øO= lÿúm¦/MYyÿ ÷}ï:õVCœ†å¦gL«XK 4uCq¢dë+C‹5®Ð´Œè¬l~nŸÝ/߆n‡Þá½öQú¬ROjêÛ3"’x¦7NhI &ÆcÿîãX„KÿèuA˜\ŸPÞ×…% @]ƒïyÊ£›ãkc,œ³;¬sbS±zn€`RQí¢‡ü§æÁ}qâí!ãé>…n ½•>nà‹‘XUì|á&å™ÝS%azŒD‡¼$ô, ) UãKîFW¼ „_Üâ}úgÿàYê½aÏ–AhŒâD ¢Àäæ˜f§Æ÷õ0¤f —~é2A‘š÷ýÙÇè_0ÛC0ÄIZ|—ר¦ Âcÿöƒ\ÿ„*2 Ó)±`K›¤X‘~dð`ÉÞ×+ö®&%…¬±ÃKsšIdå‘5‘X õíŠïù«ãþO<Âìæmâlí—¬žë!Ò'a2äæ?~™kŸ½ÎÖo³õµ-öoíó#?ÿ#ôÏßO7o˜?°&°wó ÷s§ oè4`ªŒÞ£Bo½ÇäfÍÓÿýevžðîŸ<‡ï ³Í)‡fZ 6 ~£¾¦)¡2v¾ºÏ}ßv ¿¦L®ŒØyfLÐÈÙœ w~•ÙíIB¸ƒW#`ÁUï9Š~—Ùd‚‘¦Ö\·üzC|dåLŸ`riLlr˜Ù-¹¦Š¸µ.²^«šY¬Ù¹´ÏýÒ¥¼o ‚Ec“Ë¿õ ×~ó›_¸E¬#®çðÇl¿æüœç¾Ÿ#îÏy¾–õ‚7ìj˜ÎØx¬ÃÖSû4e‡²¯¸‹]®þÃ-öžðä_z˜òþ>Õöôp_òY„•ÈÚ¹U&ÛS /l}eÄ™ï;…ø¢Ãæn%N7ãä+¨Êís_q€‚ë{ª­Šñõ¾Ã¸‚ú‚zg?qŽOüõO U<óL!ÖSbXzãq€$B…þù7~g‡.!‚©1x¢`tuÄïüäS<ù?‰ž ÞÒìG¤€h†:aý½]v~y‹ÎF­ç¶ˆõ¨‡¦©Ù~n„i YBÈ}ö_ëìHG¹òÿ]#LÚI5x B³ÐræèeléžíáP";WÆœ¾Ð'Ju‡mk!-_pƒ+¿½Éƃ}®ÿîm^üÇ¿J3ª)úº§:tïï¡.y³Ñ”Ýg·èõßõç?ÊcŸz7ĆjszlýÅ”XUÄeE¡vL µ†â|‘:«ç&˜aÁèÝסV|æ/~ƒwýÑûyôSp]˜mŽRÊ5FVÞÛ#ü}ÐŽQ_«˜íVøÕd½Î®ŽñN©fRH“[å¼¶¡wÖ †W†¼ð‹W)V•P®ãYy¨‡ë»ÇÂĈ¡fpa€¢TuÍèå}Îèib R¾.4P<Ò'V êÁ¯ÁÚJº©Q„†@=6¦Û{ìݘÒÝ(xÿ{/ø©á×zÔÛcšY•HûXPc˜u]-oÃ2Y W3X»Ð'’,·Œ0#j (ë ^ø_¯±óôOþ'Ò=7`rcBµSsúÉuŠUO¬…jר}z›³?t†zlØ,">¥Ú¯’:V¼Ò{ƒ€_UÂ,ðôÏÅþÔcœúøIà Vï1úæévžqöÁI¤Jh"ÎÁÎó#Bòþvx¢"©& ¤"‹òd—j«â‹ã«ÜþÚ½3%X`ÖDÎýà…týÑ{…& e‡•‡zl~>0¼¼ƒ…´g„Å#sfè?¼ MÃðÖ„fkFcª%ë¯òîO=ÎCèAúo *ØîŒÉåmħŽ)oÆb}1¡š —´ˆ9R¡ÁwKŠ £Šbµ 4Æäú˜8 Ô8 ƒs%«{ªíÀçþòSœùØiÿäý”gW_ž¢D|¯`û¹}šÚ’®ìl/R¬+[_Ùev{B¹Òa6œ¥ž>’ªyÄ ªL:ÜúÝë|õï<ÏäFEïL“—'œûø)îû}§™íV¯òúBŽƒ ÌG†WFÄ:¤ ±£A.bø^‰”J§WòȧÎsæ{ÎrßGÎR®ö‘B‰Í”æÖz–¼ ñ±‡þ½F`´?d6Y¦¬‘ãèÏÕîèrâ±·žúÊôú>ë¯óÄOžgº_qëŸnqé×6)úJ羫½[_Øâ3_¸ï÷P¿¢¨ö¯îÓŒʵ’õó=®}cDq¶CskÂSóy>øéGéèC! ijšÙúâ./üƒkÜüÌ-¤WÐ=íP…é)ÅzÁûòÝ yÍ«p?FjøV±rf…á­ÓÑŒúö>ÅJI°xÇÚÔÐNäGå_§XÏÆ‘¸;eº¹ UL[øøñ¼¹)yB¨&Ón^Vx,r' RÒ=סúíMzJ¨áÉÿâAüz‡ÕØã¾ï¹Ÿt›Ïÿ—ϲ÷ü˜ÕGºôÏõib»Yæ ‚ÌŒÉ•)ÝõY}WË¿QAð艒[_Üâ·þô>§>¼ÆÚ=fû3Æ·f/×ìÞÂ~y¡sÒƒ"ÆøöoÂÇþ³Ñ=ßMVök~¢4caðDÉÿÄ{Xh5•sÕa¹*0Û"¥Roîë˜ws©ŸÏyyá[R‹!„H=›`wY#å(1uÑê_ðHS0Û‹¬=ÖCW»L_E¢Ÿ±òHïÿ»Oòù¿ò<·~ã:ƒG: t ¦5ˆ*“iÃþ¥=6>¸Îý8Á×}A33´P:§ šiàÚ?¹É¥±`E¤о⼢÷•y“¦@¬éµ!ÅzŸþ•÷³ö¡ST×ǯ=áb`Ê•û7ø®¿p Žz{J¨_iõ†`UšTQM­äŽF*¿UIxƒº©¨¦3œ[š 49 `bØ(°öp: ÓaÙï]EH^€ªC͘\Rn”|÷_|ÏÝWðÌÏ]¦{>ÒY+pÎÑÐàDhf$ ݌ޣ=6ÞÝgë+»ô.tSoA¯øSS­ Ž` †Æ ÕÖŒzÖpþ{ÏðáŸ~7Ó]ªë£4+¯ÕÇ–´©FÕ4£¼ ÕkØ éÈ켾ɾݕt¯Q‚9Sªñ¨-éníØ,ÐÜš08_2ùÒi"1¸;›PPkêÙ6§?q?ô‘ ^úß®rók{º'×xð_=ÇÆ7˜Ýš@„þ¹?ô·¿›g~î›\úoÑܬ“$(\ƒïx{¬~ü!N|p…sßuå¹fÆäöˆXeIüv‚°Š•°õ¥} EšúîOÞ+Ò²¸kk®Y(“k&jÒ &içWáÑùï·Â(fä£s=†*”P”º¢C`uC½Yqý©]ÆW†ì¾0bøò˜Éõ aiêš8‹„hÄYÃÆ+<ñã3S½e M=¦ªªud© €È±ù£Ât·æ¾­òè_à™ÿå%ö/íÑÛècU³4~~0×÷¤–@Ü[Ã3",¢*Îç ÁJ¤/`©ä?fçò˜ýv]®˜ˆ˜¦RDŒMQIÙT[ñl<±Ê©w­sò'9ñž5:ƒ’ºŠ¯Š|€ÐDF{{I(ª¦ŽêÜ¡ŽÏl'¨6ˆú¡STãH¨ŽÆ¾¥Ð.̉–Š> çð=Å÷<©rØev»bÿéö^³ÿâ„á c&7'Ô³ÂäEÄyIËÂ;&ªIÚ ‚b­ÃÆãN<¼ÆàVYeí|W:\¯ ÌÂ,0ÛɈ•ùQš¦bk 犜•\V"Ç\€ÞÆecºæ:ù-ñ`ýÁ¼x²Ü@¡ç@=R¥þ=õå7®ì2z~ÌîK#†—&L·*¬®iP¼3\aH‘¶Â©š›TÔâpÁõ'>²ÊêCgÙxô$k–ôÏ® ¥Ë†°&51Â,ÒL'Ì[’¼¦ðµà‹‚Ý›·©ë)Î{DtîÙ4*.¯ˆ<.x«Xß-Ì÷ˆH®‚:p¬Š®Çu1ÐL"û/ÌØyiñåŠÝçöÙ½îî×WIDAT6#îWP“ö@òUOÑà!NfÃç sн¯Ãùoп¸Âúc+l<²BïDí8pŠ4j‰U Ì–6JZÒ‚æÕkwE4ybeok“(‚WÍFô²\€ä›¿C!íý±¨¨‚t$-ûî—H'åôC-Ø~Íî³Cö/Ù{aÊðÒ”ý«Sâ¤&Ô†sIßk Ö3¢Ø8ROjDg¸¢ {¶äôC«¬<ÒcõÜ*kïZ¡{²DœC Áª@34UƒMB®DZR–¯öº…¦ˆ¦‚[qŽªž°¿wç\J•£˜.SoÏÕáËa±P4ÅNpÞQô=ÒñXm„ÐÐŒ"7?¿ÃèòŒá¥1û/M™nVØ,0«Ôijá) Ó†0 Ô¡E’¤½VX¨Ëê£+¬_°òP—r½›\ÚRaj„IM3¬±På­Ü²zço´æ[Ìõ)¿áp¾ÃÖõ«Ôã ×MÛ”ˆHZüÊ+ƒÞø ¾Å™ú0²=hGñ‡ø´ÎÏ*¥Ú™±óÌ„½gŒ/×ì½´Ïìv$Æ@lZ@ðŽÂt#NÁF3¦ãó¾o¬=0`ð`—•‡úl<¶ÊÊ….E¿D;ÙA]ÕÔÃT_h19þ²¯?´¥Íñ̃hâúѯi¬ؾuñiëœ6ýì–¹)IüU™S,Wý‚à ¥à:uŠ…š0sL®ÏØ~yŸýË»—ÇŒ^n¨ö+âÔ D|)X Ò‰icŒÌ† ªÆÌ~­`ýÑk`í|Á#zøNI¡ÚÆ¨Ç õ~MÜmw@ ,ÕÌ :_kÙúëÐTÜÑ"½ÝXJWxö·wïí¥= EÒ9ê–nûÃ~ëzYâjQ(z>—{V ¡j]ªÞ¨™\™1ºR±ÿò”j¿Á*Ã,& ¼0¼B(a™ ðç?p¬?Ò§ÿpŸwœëÑ`…P”©‚7Œqiö+š½l„·â[o%„|« I”'„gÎÏÿZ)€:¶o\&„€wÅÜðs…£ÛMÁ˜#àÛ«æâÜSE:àûJAêH=1†/Œ^­™\«Ù{iÆèFEœ44Ó„lí ŠáJ¨‰ÄQ âR¶°Ôaí¡×󩎯‰X “FP[óú9Zþ¶Då@Ç«ËO¡äv)¹ˆ"®`6³½y+»~¹E_ø9QèkÅý†ó#¬TŠÂ5„i`z%2¼#<@@µTûz/Pm7Ln6ŒnÕL®×„a ®"ªEH¼ê:bU$zÃuƒ žû/ è+Y¹Ø§ÆãV=ÞkÚ½µbÕ§‘zÒ@”ÌÉ~ðý¿ò›ÙÈKŸÝ"_u®ïeD_l¾|Éþ~b€9a@Qz°œ^çØ›D¥]«c0ªÝÀôV`v;2Ûi¨÷"ã†8n°FˆM ÌRÖLĈhŒq £”=Gï¼gp¾›Ö\(éí"Ý$âò(Á`©‰óÝÞ[¯áÀ8£=ð6¹9¨£ b>SðÁoBò²ë­«—Àe±Ÿ%÷Ÿôæòª`³×uZ-àÖïM¹ö›¬J­X"1Eº°T·›ÁÒ2%¯Bq±ö`Ÿ•º îÐ?[â EºŠŠ°i¤™TKg‡Ü­·2w¿È²[Ä·mcZ._ õÎu?‚ú‚ý[7ØßÙÂyŸ]¿D0EQ ÊAg3–mû(À"ôÏ;œLöREn¬cÞň"¨7LrÕÑ=íéŸ0x `åB‡îI+ G¬"Ö¤ë­ÊY¯£Ûpók±d­«Þ!ê—çH’vO_ûdODÙ|ù%¢¾Ý7YuÉúwH_xC\cÁX9çx×ß`t¹f¶hF!lv?p¥sÂQ®;´«xÕÔ•«N«‡›™Á´YÎÝop|oYÈÉQw€P=Âå‹F`&AsW" - ÆÛÛìnÞÄ9Ÿ'ðE‘W&%BÒ¸Ôxã‹CC¾+l¼§‹K]Õsí[Z•6§¤UFïÒòÅݯÒFò²!' FmH·5òŒ¿B™ç|âþ¦nðNn”-¨¤"•¶ŽN$íSKCÁo¬ 1¹û-MÉbÁâ‡óÈÕ¯ Öû!ÎnEùÜÊ×öÀÒçj¸’ÉÎ.[×^ÆE’Ùqð…ÇiûùöºlÏ ;®j‹%ß)œüáÀ§ÏFÞQq¿H.s~å‹VK ó$Wn_y‰fVá;Nç"ç)Ú¸µ`q™ ðiý΄ì‚êa±½LÇÓzrDdäë¢p)ì[ö¹}õ2Zø9â!¹~ÎûFÉF䛸ËÁÝ¥~ ÓTA›Ís‹Až–HBÀ‡&Á­K/QOÛ°¯¤è'JQ9@8~ôpçâÐ{p¬ ‹ÆÛBÖ® Ú,êù;¢z‹Þ‚½0?GRB¨í³yé%Ôˆ&£2÷­ñ—ÝÈ6Ï²Š ïLsìÍ#|Ài‘ët¹Ü¡dA¶ÚÈ_U6_|z<Æw;I=äÄOÑ)sÒˆÑ/¹$lyàž8XŠäN¬øøY0èÚ¥M‹â¾5ôÔ‘’U™O]âþ[—^BŠ"«–dü9ïð~ùm> •@KsßÎýÞö“LG÷Ë,üC:}Ñl áÀïO×å`J[¯>eóÅoRO'ø²“„|V ¾ô©Bªû ÈGÚ¸Ìq·‰û1K†›º4¿ œŸŽiªUTEăZ&´/Øâô@:Èbrcœ£ï±y9ëþy(XP¯…ÏÈç@´RIcàžøÆÀH"[Ý!>lÀ-r¹$BÈb%ˆ,HÌñ^r¯¤»€Ü|áêÉ×éåû –þóE¾mâhQ 8A–- ³{6Àk„Ô‚fn¬Í“7yrYÔç¢üï¿óoUƒ;¨è9F]( ªÍ[ܺô"Z–ÙœH\­š×&’ÜÀ¹0Ï( b2žsö üVŸÌ}ö¹Q7·ò„q…tÎQ;àk§\{7(Kh"›_†kÏ=‡CsÊ·Íïe²üªÛÄÑ‚˜Ûwz¯2‚ïdXàú¦5ÉÈWALS724u0WwHü·ßÂYîòÝÿ\"¸éí[\úÊ—Ù½y ßéárÔ¯½—º¤û,ZüòZWîI€× mm]«³E5•­Í2[HÜè!.Oâ]8äËg£q1Bwø¡ ¾$VS®í®½ð1FÊþ`.IZÃÏrÒgn{´ˆÛÒž¿4tÿw@6Ú»w‰k]¡)É‚¦ò«¹®_ˆØÝÆÕ¼Jǃ¶nÝâ¼ç%DE 8v_~‘¿ôfÃ}|·CYt¹™­ÍPxGQäí®Z\D È]ÜÀ{¡à1»fóØ}æ\œTIcêa®ž7ƒIÙ<Ë÷™'nÚ)?âÓ·0®ß¥Ú¹Í _ü<·¯]¦ô]Š~ÞçHt9*”Ý‚¢h×ýYæx2òYªÿÛn*÷âËÀ)â¢!"PÄ`$ÃÙ}«ó[nÍöÁ¡šÅR½6¸±žpõs¿ÇÕ瞥iÝÁêSØ<ÅÛöù- ÊnÍØ\ ôèú; %•ùîä÷âGÁ"R”a€ø÷¬ÍáÏÝ8<:?o¾Ù£´Rda¹Øb[y#ݳ×ÇcëÙgxñ+_a2Ú£;X¥ßë$·ÒZ½©ÎQö \YÌëlîôÌý­¨‡ÎaY«Ø{6 %®÷.M£iZÞÍbêÖÍãøsŽ_ŒÙ/HRËX>¯ëõÀ£k/ñÍÏ‘ë×ñƒ>½u”´‰•šfjùË~I§›ìÚ•ÇG=m½ ߪ̂Ö\.ÞÌÉ}@°´½OÓ"-‹Ï9»Et ÷ŽßûÙË6sÙ«>\ ÝÀSí^ç…öyn^~ ítèoœ@}.Ý"I–„ø€+»tzœOÍÄÚ>Å ž“l”¶ÄÀ<> Èom¸ç@0¤,ѢȓßêðV·~ý‚ ·¨ãsX͈ˆ„ü“Ž/ êÝ«|ósŸãÚ7/㜣·qâ`£ˆ\·£à"xe@Ñ-S!mÛÏ»Eì¢u¨ì‹C?w ³”h½{õL"¾_âÄÕ…jDý•ßúß‹j ‰Zƒ&¦d‹8(;àû ÆìöUžÿÂçØüæ%Ô úëk¨Ï ¤1"4¼W:ݒΠL’ÄRO„¹ÇÄ ôáø„|L\Ú%ìõ¸ójß#ÇŽ~Ï];^ñ>ËžÚ¿Ûï¯v¯¶#Ç+]ß6h®ßIâWb¬ùdý‹ÕåcY·gNsÏ€À—à:`] Â”o|‰K_þ›×o!¾duåêó, ?-é'ô»%e¯‹óisIÁ˜/ ¹Á‰Ð–"Ñ8¢.ܲ.aÒHLJ[I'Ó°;é„ÔVt.’LRòÑ$uÜAÍ¶š£ ©Ãqb±T­‰.:Q©Ñî©™°é6Jê’m’¨Ù°DbTBêßgJHOz9‹$s‚„,žÌ’g—%RI„+ ùIÄF´qé´Aq„Òx"˜ÆÄÌ^ÐÆN”º-jbTd1Òýç D=NIw])¼ ÁØÆfé]cÞ:a~?Qr£EÉnÓ¢i‘G¯’4Z;–‘$m:~ðö2?×%#HLûz!Æ›Y²³7šŒ D‹ªS« ‰"T–zëÌ4EHj„ÚLk!6&R*u¨ÀšñxgÕ¬ u¢Ñ8çç|!”EͰ²SÆn·kUUÙÏÿüÏV¿ïcåܹ³˜a»»»Äíĉ6eeÐÁb„¢©Š‰jÄf4"æQ-¼ÓhÁ‚‰6"΋“@Uż¤šh/*Þ0‡ŠªiF¯8Ö˜8‰Vk[?'KŽ?“»i±¤‡³ûh–Œ¼¨A³±1ï2j)’fA“Ÿì“¨9‚–Ú²kV9!Å_P#š˜ç4&4™áUDLÅ…4&G´ iLÌK´´TÔ%¢‰b¦DD,b©]R‡‰‰E³b ˜E¬6¡ÒhA+‹T¥‰Ñ#V1ЈXÍŒš¼wM´œ÷VUUİ£Ç#[YYÁ9Çúú:w¨€ËW®èh8d<ËÎö6'OžQUUÑ~¿/³éÌE¡1F'¾ðÞÅh.Ztª¾(DpŠx|ļ׃9Só‚jZš Š9Q±Xª8—êY,zT“À ÉŠ‚hb"bÑ’FgND‚™¸¤õ£ú¼Ï³%C.y.F QºdˆZR*é,Ñ¢ÕÄ›JÝ4Q½'‰n1G=ˆJ#!ª&‰~0Q MˆQ‚0÷yÌRð±R(E£Œ¼ó±™S'!ˆEkBÄåÑÌLÐYŒD³Ð&M°&†uE ©«hV#0 M¨¢!„K_†CœV3 MˆUUÙþph>xѪiÅcOüžzú)¹ÿÌéu:¶º¶¢ÿ{W›Ç Cß#µN §@“¢ñýÏá¤gh7õ§+òõ‡FYZ^oÃESØ+Q#êƒJ"µÒÝ—n$سóêòÊîïÌ 3£Ì¬Y&š)[fnÍÌ‘ ƒ›ɤ³í  é D3ÀrÌÝMž]Ó‘N˜œÃŽIIÓ!š±a\˰M¸“´&O!™6.ô–†à˜Oo‘$E…Dš§1 ¤KÅXKÒ€HnÚP+£Ë”H8i‚€d§§KIf‰HLÌ4(º`ÈusI™êaÃð—‰q˜gRa‰ž@=Ýiq8ôØíZ?d$ÉP(2»v­Å¡GöÞeô¤3ÍLû?öy{{Ë7o.ôˇøùýû͆ÏÓ0áææ†ýˆ·—oáîì½£¹óóþO^^]rwј9öÆn›äHÒ3ÓÁ±0ÜLw¦„G†{sƒècü—clOs Ü’Oe3š‰"EK%Íh[*ef”äøêj"mÅôb°|.ùÇ‚TcEH€2 ·I#‡HÓ©>¬KGŒÐ'Ía©Bçœ@l«L‘Rn“V)•f–ZX$;€Ø,Ÿ}X¥™B†‰Œ3\Çp‘îÞöQªRDr¨Åà´½RR¤Ü=÷¿ïõî§+&kÃ'pè]¿}ú„ëëëÌ>+¤¡ï0Z *i”+¦Š¯&DÇñ퉟q_pkå· oÇ%]%Oà~f]êmÕL‰-Júô»ÌëÂUž<ñ'Þ™ø,ÁéD<¶úLÉíÖ@A™¡m‰Gm“fœo€]ɱ£ûº2iB}þve¬•ô™g ×Js†+£'¾2½ÖavpmpÿìÑúnœÊt,8œÀOÜdfZ5<˨ǸÏúTœæ‘0ß ÏyDLí <‘¾ B ÏFÖ/teè¤ÛpZ¦üÌ8¶qÕ+퉫g™¯mª¸>'5½2m-g ëPËXË}<§x:x¨†×´õ«Î^Õøc´N©û5­Ò­iå?¥=ÎuʳuüØ ü¯àþŸpn·Þ+¼x€¯ðÂáoÜË Ãp‘¯¯IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/queue.png000066400000000000000000000145371217176075400237260ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË&IDATxœíÙrWšççä‚L,¸ï%Z¶\ªòôEOÌD=CwÍrÛ3Ñ3Ñ—s9o2ýó]QÕ]c[ÖÆEâ*QH¬¹3™ €"H‘HÊfþ°-HæùÎ÷ý¿5…Öš ÷ò®án‘ À=G&÷™ÜsdpÏ‘ À=G&÷™ÜsdpÏ‘ À=G&÷™ÜsdpÏ‘ À=‡yÑ…â¶’áÒ8“¿%¥?T„ÉësÀ粎»FºÓjàÿG*è©ô!¤eY9) ¥"WƒÆL®×ð9 ã]AÇ/"ð¥í ޵־ÖZ]÷¢&Ī^k­þîï÷»üÇÿñ¿”ŠÂ(Œ„Fßéïk6=ðçûZÁ$„ʶmùîÝ»Úý/ÿùïÚíöN¼}׳© €¶m{ñ¯¾ùæa¡à¢•†Œ|–666gAL‡œ6 W‚™=!„0þþwÿItº]LÓ Š¢q®9ÑËåð<Ð`0‚–t Ã0@k”’Ì øü ¥$ C<ßÄ›?ÎxQQ¯×(—ËH)QêÚ#Ø ¥DkM½^GkŠTz@G:¥§AB€”¥GGGlnnÒív1 ãÞSð»„aø¾Ïöö6ïß¿G4äXèðG‘@”–eá8ív‹ï¿ÿŽÃÃC¤ad&á–!„À0 >|8âÙ³g4›M …¹\CJü¥øHm¶m“Ïç)—+ض͋Ïyþü9Qa#› —€a(¥xýú5/^¼Ä4M¦¦¦Èçóضa˜zÇ1å=)RbY®ë"¥DJ‰a˜R¯×yúô)•J…(ŠF AfŽôÔóêÕ+<ÏczzšR©D>ŸÇ²,,ËŒ9A/8t}|Lµ”)%¦ÿ(€X+ñ¯ÿúgÖÖ±²²‚"#ˆc„”мyó†7oÞà8 ‹EÇÁ²¬˜ …Æðçå‰&Hµ€iš˜¦I½^çõë×Ôëuž|ù×q³˜Á`Ýn—W¯^Q¯×™œœ¤\.÷l¾išÉ拱r±s³é¥¯T˜¦‰mÛ|øð?ÿéÏ|ñÅffgÐJ¡2“pe!0¤Áû÷G¼~ý €ùùyJ¥®ë’ËÙ†ycq™ ÓÁ½&’7hR!øþûïX^^amía¸d¸â‹æõækööv)•JLNNQùã=õƒø¤@ß$a!D_˜¦Éñq½½Ö׿ T*¢”ÊâHU³ÙäåËW´Z ¦§§)—+CUþMâRgM‚aÄ‚`Y¶£Z­òÝwamí1óós!2!!RöØxýÃ0XXXì±ü\ÎÆ4Í„èÝ|ÜåÒ0ˆT2GœâµZW¯^r|\çáÚ9ÛN´Á¸—ýÓ„aHÂ0bsk“ÃJ¥SSS‹E\×=Åòo g@kÝ{]!¦iÄ bAÈålŽŽÞÓl6yôø1•røôõ~ÎHMh£Ñàå«WtÚmffN«üØ·7W0ƹ÷LkÆU¦q- ƒ&À>%–•£Z=âÙ?°²²ÂâÒFBxî„ aooíííDå/ ¨ü\rÄ­žüCà2 ” ÄéÀ‘eÔj5¶··h4<|ø×uãkß‹ªžøÔžÏÖöGGGLL”¨Tú,?é¦DïòœiœwïÚ`"®Ubb‚X«ÕøñÇyðà!“““?‚˜½“ãc666ñ}ÙÙY&&Jäó©ÊƒlBÊ;Í´á×0FÝÅ\ΦZ­ñòå —X\\À´¬X~f‚úö»{ììì`Û6 óŠ%ò®‹mÛ˜¦qŠåß墒M¹æÆô…@$õ}mÆ šÍ««(ò?£BÏ8PÖívÙ~ó†Zõe*•˜è}¬ò{.Þ€‘M@ºJéÄå‹SÔJ÷Y¬iš8ŽƒÖe´†jµÆññ1+««LV&{I›ÀmÜ^×ÔrrÒ`ssƒ0 ™ššbb¢Œã8½ÄZE‘ÒTñ_}…B|ßZc‰‹ä™~‚´Šx¸ ¸ Œ¢ß÷©×j´ÚmºÝ.aö¾Wkˆ”&Š? ëué´;Ôj5ž={Æìì,333‰I€¤@yà¿ ü¹_±—2 ¾O',Z£µ@ç&´Nª›BÔ)ä"ÃxÉàß]T§µâCµÆÁþ>–eQ©TðïôÞb­&LÓ\¸Êdžô£i ŠB|?$Š4afµ·ˆ ®ôþ!ýáõÝ@­ã¥‰"Eú½~‚«’2܆ôƒ“,MEÔju„Èú >'\ÐO Ç|âÈ—VQÖOðá2ýg`0ø©Wò‰¸§LX¶õ|¸J?ÁÈ@ÂèWgýw‹«öœºHߣ´F$qÿ¬ŸànpÝ~‚á$ðÒé Dý#0d¿:²~‚ÛÄ(ýÃë¸ìö§ñÇø’Y?ÁícÔ~‚¡&à*6@è¾@ÖOp[W?ÁX BÎ]`ÖOp#g?ÁYÐúJ$ð¢÷fýãÅMôœ5½_Žh}1«Ïú ƃ›ê'‰ö§\nò~‚ëá&û †š´ºœ P:©†!1Y?Á8qýCMÀ•Ü@­“hÀ婬ŸàÓ¸­~‚á^Àe'Ï HJì=fý£ãvû FŒ&’rÍ}Éú >Âô ψ«(€8¶8Î~) £O_ ôØ–õ³Œ)ÑJ±{pÀÛr¶ÍÂü<…b7Ÿ'—œúÁÀÎ8ŽÂp  ®ˆµ€c?”Ó4°¬Xêõ8fÐj6Y}°J!_ ­8þÉC€¯ëñæÍ6Õê&Êe&+ … ;cú凒À«R­¯oN#&‡ý¢Dº‹Õ/žÿÈêꦦ¦—ÔTŸ+RªV¯±µµEÌÎÎR*•Éçó8NBôz…5·1"&®ðº’DRI6žH^ºù¦iâ 1Y¬ÕjllnÐl6YZZ²lF—gR¢"Åþþ>{{»¼ŽãÆÅ©Êï}j4­7loF""yß³^Yœ #ŸœœðîÝ;&>¤X*Æãí"èµmoS¯Õ¨T*§ZÈUþù½ãÁˆ&@$ä/VZ_ÒdRÌ~ûšÁ²,ªÕüøã3VW0;7ûÙ{ qí¤¤V«±µµ‰Rй¹¹žoï8†aœŽåëq;¿§¯6‚ ЉʿdÔp¤•­BX¸îéôr½^g{{›f³Áƒ«X–M¤«îé‘B¢µâíîûûûäóù$ƒ«üa]Ãc_KÊÓþn¨ P|:袵FiM¤J)”º¼ûx]¤Ù0Û¶§ÂÈqR©Ñl²¶¶F¥\A©Á$Õ]‰Büý†iÒiwØÜÜ Ùj2Y‰‹6ò…NÎé…s£{wÞz>ŽÛÕŸ¢iÄ/ #|ÏÃ÷j$7ð²¬30>*6©Õj¼xþœÅÅE–WVR… S½]è8œkŽŽØÚÚBJÉü\¿h#Uù©™ëöfîa:á“à< ÐÉâ´Ö„Q„ç{´Z-¢(DHy‹>™ˆ5€ä\E˲8>>áàà€“FƒGQ,ñ}ÿÖI¢e™(¥ØØØàý»÷”JE&''Éç 8îG³nI:Ób¯‹«‚²ýi¼?Ýü0¤ÛíÒî´©T*øA@ ´cßâ(xÌ’mËÂHBÉ–eâ89ªÕüðýw¬®>`qq‘(Š’¶õ›¸á: ‰K)±m›““66^áû>333I87.Ͷ, C븥 –>kÜ/aÒÅ¥=€!N!VWxwt”Do‚˜4%½ó®ëb˜&†iaÙ6ÇÇu¶¶¶¨Õj¬ñŽãàu½RËŽãôoÞl³··‹ëæYXX¤P(à&ãaRßþ¦Ý»aHg?|Bôÿ‰?Ÿj¥¾ïÓét˜˜(±0?”’÷ï? Â¨ïÞ•–D†HKÒÀ2-ŽŽ>ðÇùk±´¼D„a”Б¸À†”ä‡V³Á‹/i·ÛLMMÅD/ŸÇqÜÑë»w·Å±½P|¬òA³¼´ÈäädÜiêù@¿.ýúé Ñ‘ÎR ,§Wÿ7®¾ÿž?üá_(WÊüæ×¿azzšN·K„± \Ñ,¤;r–ø<{öo¶ßà¸ósó§6ß4cß1ø-·Ÿ†¥ëÏ­ TZ¡•"B<¯ƒëXX˜Ç¶m|?èÝ€¾Ãíï± U²¶DÕ¦EÓ4i·Ûlnn`&333t»:.J«KiƒÔÖ[–ÅÄD‰n×ãÙÿû ß÷¥R‰r¹ŒiZIÔÒêl¤äk,Ïy¹&zA» «´"Š"<ÏC)ÅÌÌ,ÓSSD‰8ìÔÚ€T²µŠ×^·K«Ù¤V«!„äÛo¿¥P(pppÈŸþô'¦¦&ùú믩TÊ4[­Þïvž6HÕ}¡XÀ0 666ØÙÙ¡\.óÛßþ–wïÞQ­V18“ٯ؉–¼=Æ?gƒv§@k-´Ö„AD·ÓÁ¶mæææq]‡ Î!OwztM•R„aìžv:ªÕ´š-–——X[[C)EµZÃqfgg¨Õküþ÷¿g}}=®å‰ ù|L¥aôg‰Û­Å™Ý|v°DH•J…ééi€!§~霟ÛVñÅþ½NN}H·Ûáää„jµŠã8üú7¿fjjŠV³E«ÕFÉÄÄvÎÆq\N'¼|ùŠÃÃCž|ù%ÓSS„axjüŠ4 r¶çyüðÃìîî’Ë9,.-’wãJß÷ézË+ËÌ/ÌóúÕ+vvvi5[LOO÷<´¢ÞºÛ­õ™xÈ)  ”Â4 æçÉårœú¡—ç6Y€N"Z©¹ò=f«EõÃßçÑ£G<|ø¥"jÕ:~àƒär6Q¤0LÛ²Èål ù<ÇÇÇüåßþÙÙY–––(‹½ïò}Ÿ½Ý]vvv£ˆé™Š…"®ë`Ûqe®a~@­Z£X,ò‹o¾annŽ/_rxxÈD¹L%!†Vêj@Þ¦Y¸8,¤baaœmâÔŸùßþ„Ȥó‰üÀ§ÓŽO}½~Ìäd™'ý׋EšÍÝn­5†4zרIýa.—Ãu]Úí6Íf‹g?þI®CºŠ‚b±Gòœ\RŸ'p¤ ûš°ÑhÒízLNNñ7ÿîoØØÜäí›7IY÷,Åb±ŸïG ER^Ãr0¬°ö”Fÿqqq—ÉÅ+’R’ËÙXöÀÜß´z`óS’Úl6©Vkh­xòdååeÂ0¤V«ÅÝÇI¡%$÷W ´‘øä2!léÓRK¥ üÀ' Þ¤LéËþ(E/&Ù3¤€z½Žëº|ùä s³³<þœ½½]¦§§™˜˜è›„žÝ¬.êj­µB¡eZa«Ù"‚0èuîž ô/)E³Ñ Óé`˜æj€Þh¥ ‚€V»E£Ñ Õj19Yaýñ:¹\ŽV»ïy±‰=34úM÷*k )1’„RED*vÓ{%e<[G iÄÚC9`ÂÅÇ_ íN?(‹|ûíoØÜÜbsk›N·ËÔänÞ%gç0ÌæŽ0yQ ÈüãÿðÿÛÿ‡F³Ñ,û_ŠÂ(§´2µ:=Lª§F4¢Ùlˆÿþã¯þéþÓߦ¥ac\r²pÐZEŠ ði&®”_¬¯³°°€ïûŸ ”ºd‚Eô„A ¡cA0M³2|oRŸ»Ä&%ï‹Âˆã“Ça}}Ù¹9^½|Éáá¥Ò¥R±7ÅÃ0Œ8“xñÜ@ÖZ !äË/ž½|ñâ50¸ÄƒˆÓ™rÃV#¾zúõ?˜¦ñ·ãfñbu2‹0Vùf‹Z­ÊôÔ="—ËÑl6Ö.z³x¯‚ØémýØ”¥¨¦ú²¿ijJ½n—0ÈçóüêW¿bww‡·owèz]Ê …^²HJIÇÏ8Åà\ µ“‰Ó>PŽùô)À0ŒZzøÇ²ý=[ûöAÐétøptD)Ö?faa 89i µŠíè8{àÄÙ7Ný‚WÞ˜d4N³ÙĶmVVâié¯76¨„!nRjçl,ÓJz<qXµÿÇ E\ˆËeI$ ’ÉÓñDî1ÀÁD‰Ê¯21Qf}}=E×&Ãx_†ÙúQqÞo?âF¤£åý <9ÁÍçùå/Éîî.{{{1ùT ¥"”aYvÌ9Æ!úì=wBˆ¾D !½Kú0ûô+£(ê%›NNŽév»¬®>`ee… h4›h¥zìþ§ѳ(íV ˲XYY¡R™dk{‹Fã„H£ˆœRI½ 9²«˜jÕAŒoDŒ¾B?Á§DO)E´ßÞ¶mþê›op :Nü,‚4ÑóGšÁ ÃF³‰ë8üâë¯Ùßßgÿ€À÷ ƒÈ ±í´vP^Ÿ Ù›1κz$°¯>ú*ß÷<]Ïca~žåå%¢HÑiµÐZlë?Kˆ¸–¢Óé`š&KËKT*e¶·ßÐn·P:JÜÓ\¬ £·ÿWƒÁ:c€+›€45©!Rqö®Óîp|rLζyúô)…|Ï÷oÒÖ&HCUaÑjµqrO¿~ÊþÞ>A„F¨HcÛq —›_Z ÔÙÒ³;2zÀ·ð¼Ø‡÷¼KKK,//EN›8\þSµõWGʽ»ž‡i,//Q.Oðöíív‹Ø-¶rhôRΗ‘-ô™6º±š€Ëô%fív‹F£‰ë:|³þ Å"žç†QйŸ@)Úí®›ç«¯¾âà`ŸÃwï Â×Õ†?r'©Eü”ã&†T£ŒU|Ф,?ºÝ.Nß÷Y\˜gii дÛ@_ª:ççŽôxžsƒ¥eJ¥2owÞÒj¶âÉ)fšÅ5{6λwš›4H@Z´©¸ª¸ÝnÓítÈår¬­}A±X"‚ØÖ'•¾!ˆ¢ˆn·K¡çéW_²¿¿Ïч*–’w]"ªKë8¯0DΆ¸ÇLÏlš2к÷x¹V»CxÌḬ̂¸82)8±B÷gŽôÞø¾a¬¬¬P.—yûv‡f³‰ëæ1 “ˆdþr¯»¸aÊùM@¿Ÿ ®ÔñètZ˜¦ÅãG(—ËA@ÙÆ_J)º]B¡È—_ÆÚ Z«‘³s½ŒfZ†nq-"Ð+Ä5ÀÙ~‚´F¯ÓiÓn·™žžbyi Ã0ñõúq>¶@‡¨HaYÖÍ‚ .)WQD·ëÑn7)•Ê,//é'È0ô¹A€a£ €„ÖZxž‡V“““ÌÍÍ#ħú 2Ü$Rm055E¡Pˆ‡j5›„axÊþŽE(¥0 ÉÒÊ2ŽsQQ†ÛDª LÓduu•jµÆÁÁZ÷k<Ç!ÂR,//_»Ÿ ÃÍ"Õss3ÌÌÌ šñh€«öd¸}¤Ùu\èWr‰QàZýn¢7C&T®ãÒît´Â"@C\½Ÿ ÃáãºBI!#Ã4½œm7„ïƒ 8 %F%k"~âƒl.ßOávÆgq¹ho¾Ç8 é'0’—d ¥Î0v¨W¤µŽ öáG¾òG¤/;ñŸ)†•úE2üt‘©ê{ŽLî92¸çÈàž#€{ŽLî92¸çÈàž#€{ŽLî92¸çÈàž#€{ŽLî92¸çøÿѱC6””<IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mailbox/tasks.png000066400000000000000000000472301217176075400237230ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË IDATxœä½y¼eWYçý]kï}¦;×­)U•TæTe’0 ‚D0(D”fhl'PÚVTZ^PxAp@°Ûn´Å‘f I y¨¤Rcªêu‡3Ÿ½×zúµÖÞûÜ¡êFðmð]÷sî9wß}ö°žg=Ïï·¾Õ¡”ú–ño0¾õ­OÒ¿áøVh¯ã»al”)¾£ þíÿ@•Þ¥ôY­ø¿¬ø¼Ö1X±¯”þ^)¾«™å»ÖZÁa›f˜Ø¡=£J÷.¤( KºŠ š‚¡Ê ôï‚!¾@âsX¥ȨRE12ra2µå²Ñ³+’œ9R©žÑ¨%“›Ÿ=¶¥Ö¨ÆcIm\!‚²‘RÊŠ,4³^§Õôg>¿8×ï§ ­~ÿDO¥ïéiïKçZôIKçŽü{`²µÿÏ ê;–Z^…aõêŒM\TÛµûÊé«w\4ué…WŸ±g[eòâÉéÑ­[7OÖÇãѨ¢"¡ûšDÇ t~PP(¥0b˜>ý¤ÏÀ¦ôLŸùÁR67·Ô;9ß::Ó]¾ÿᯞ¸oöÑå{Ž~cékí‡úÇèÑò׳Z:¬”ÿfÌð­Ðð;‘ʺ{¥Ø5D\ïØsͶkö)©ôI%E´`ÈÈ쀎îТËcÇç—ÎÍÝuÿWÞöðmÇo:ðÙù¯š%™ñ×Y¡ ¶åÿFø÷Â+A›öïêT´åÊëÏ~Ö?zÁuOÚ³û¹goÛyæ jv”Ä&ÄR!Q ‰ª¡ç(B£”òuD¡°ˆøíB&†L2R22‰A°XÿÉÙŒL¥ èÑQÒeyø·>zÃ=_>òé‡>5sk¶dçq*"Æ1Á¿)#|·3Àz„ÏthÏù„g?oÏxê3/þásvì¸pTFˆ² ©SQb•¸5®4‘ŠÝJWzÅÁ•%ŽðÅÚD,ˆÛZ0Aб™'|¾gÎNe8ÖèÛ.-iÑÔK,§KúX ¡À*ßvFønf€2ÑÃç¬6×®}ååÏüÁŸ¸ú§/ÞsönŠ'Ñ Jl+T©«Øét¿ÂµÒh4ZE¥•x¢‹'´ƒÁ"âÈ `ÄäDµX¬˜œQü‘üžÊK†  †LRº¦KÇvhÛ&ݨÃìâÒÒ#gþîËÚ÷gßüØá¯˜– pŒÃŒðÿ+Xi«—Á]ZŸLê×ýÄÏ{ù«ŸõóžwÖ÷UÒºŠÓ* 5âVºŠñ„V¨@x/4òU*N\§6Ë?gâì;‹C0õE Ö3…còK”´ k",ŽAŒR0°¬Œd¤6¥iš´m“Žî™ýÍüã—>¸ï/¾þуŸ,›6NXO*<®ñÝÆá]û× 2U_øSWýÀË^ý¬×]tþîïKú jY=J¤b"åøÄGå?Á 3bÈlJ&RÉ0’9Ý-™WÀãµ¹ˆx1îg\ˆr˜`­Ùp\ë~…zq ‘Ú C†ñ¸4EfSÓe–í]Ýã±GnüÔîúÝ;?vô t08‰°#ÊRaÃã»té]éî«§Ïxõž÷+Ï¿þÉ?_ïUkÙ£zœD'ÄÀMÀ9%³i‰øY.v-BFêÈ,6˜zƒrb‘!M†x¥ °âæ?0¨ gB5Q( üZ *ÈR64"¥ImÆlwžE³H+í.ýóßû™?zà}ƒój!0†™à;™V®z‹ÆþȹúúŸþåç½c÷Ö{*í&¢)ªºV v8##)}; µ·ºÅPþÉüßâ]oá¾ gþ©ïÓ+÷Y†çÞú•/^ ” ‚µv(Øcõù3ºi‡Ç:s4£6Çg¿ö©÷Ü÷¦ýŸ¹§œÀ)¡ìm\ûÚ¿C  ò408óÉS[^ó_ŸÿÖ¼øšŸ‹›u&d£Ñ±NüäX¬`Õ§oûôm,Øà‡ê•Íõ­ƒ›‹ÝµáÛ釃R+Y¾-o½9kMéo÷[¡)iÉ–f›#úðd¯ÝÁo'k€±ðUf´RT+ '›-¾xç½Ì.t¯P««Iøž'ì%S-ŒXz]Ec­ f§•‚±Î³¨”æXk†G›GéW²þ×?qèÿò›þ3ìg &øN`€•Ä—Ñ‹k#¿ô–¼óE×?õ5Q«Æ&½™FÔ "r±[ÉèÛ]é2 ï‚0’:-Ö³üƯ­lÎ9 8î)‹§ò=[±DZiͧoÿ:ýÙ/pÉOæEOºžkν†í“;$N˜çP÷vî_þ´c ð–A˜‚ ëSìšÒ¡|ÅÆo­8‹#Òš¹îž<€©îú§£ïúâo<üV›€ÉšLð5%¬Dü€ôÙ[Ÿ|ã_½ø=Ͻø²—ëfMÑ4UEP $e )}Ûg€_õ2 •³†Ø<Õpx óŸKÿGybrû\œÓÇé{'+"¥ùÓþ,ºáþð•ÿ×~ßÏ­{γêW²¯y#©í â\>ytQ,i‰O)£Drâ»y„̶l¦U¹sæAö^·íWjô ¿ñð/K&†ÂrúSlp|»B´?–T/¬NýòŸÿÐï?ûüK^®ÛUÆ¢q"•¸dÛ%µ)=z¤ ÈÀ{ðL²”Ò«V³BÖÝîCЦ…^Íÿ/n5Ú!€èԉ呕G'—ùðná?_ûºS` çiƒàBËÚû6EÝ>™-,‚H;§”Ö c-Sµ ®Ü¶—;N<ÀÏÛüZ#–›ß²ÿß„ ¾%PÁ-æu~tf2õú¿¸îÝß{áž—K?b4'!&“ ApAÔ>}麨›Í\˜5w¶àÁS™dÞ¶^ç6ŧ` ÷*ÀDz86¥ƒ%qÌݦżæÙ?Ú{^Jѳ]wÿþXf‹3bBP”`¬%R:²åa¥Æc—±ê(Wq1·?v/‹”-ƒÇ=ôéwY÷{10¸à…Ûžyý_õ;iËÆ‘ŠQJÓ3}º¦KÛt蘮K–0=z¦ïµރf±ÎÓç߃¿ÏWñ!䄉 ïÁ™"b±6unaëƒF¥ó„Ìï¦9¼²Ìpæ¶Í\÷ô+ø»;>qÚßV»Ý'“ÙA¾-³æß(F)MÅŸ?Ì‚Yuaÿ~Ö#µ)gŒlãI[/¢‘ÆÕk~bç{ǯ¨? GüÈÓC©Efο†rÐ7yI}׿í©ïÑdLD%ªx—nÊÀôé™=Óc`ú¤¶ŸGó2›â¸4rÀ·Îï#1Žàþ%^¥dXÏDeíš Њ$ŽxÙsŸÉŸ}ù½üÞ?ýÎ)÷of³¤f€ˆòvüÆÂÉáþ 1C8Ë®IüèbÅÒ3}¬çMìæÒMç11Z;ãÒ7ìø=­&ýî9là–‡Æ†U€ç®p"­*Èõ¿øÄߘž»Üt-#UŠl¾ÒÌV H+–H,¨Ïã½ó%‡JØêÄÿ0Ø\¯7‚Z±Š B šÄ,·»Ü{ìQ–[;y’¯>ò•SõXï>iÝJU7r'XŠ•á»-›©F2CN )o”½’ªôX95)±ŠOÆØ;}˃éNûŒ…×lû•ûßqü-x‡ÔãÁb€’îL0¸âçvÿØÕÏ?÷'{ÍŒ±j­”Ÿ“§lj8ËÀ%dêÒ¾ZÊa·gˆ®Áim„âwp![Ai…µ–_%‘R|îöoð±¾ÂU»ŸÉ‹¯| ÿûÕÿ…ËϺì”×½08JÈ0pçòö¿OÑJƒ)–X¹b¥€_ XFa‰Pˆ¢ðiø`09Þ±ÚY‹jTa,åò-±|´ÍùÏIáÄMË7Ÿ¼µs!Üîèe7ʧe€ñƒ›—ÉKêç¼ð§žð¦AÛê$ŠÐ:öáTV#Ê •*˜@QbˆÕŒQ&j°„UƒŸæµFðÀAáÕÃyg½uàcðÖ†{¡VM8:;ÏŸ~òŸ™=®xç‹ßÇÏOœRxºsJ*]ŽtîvacL§×btÄë¸J£•æÓÿòu>øé›yöEÏçã¿þ‡ìž>û´7ÿµ…¿áþæMTuži¡}%‘ñ^Æòl§•;VŽ ù¬Ç>eâΑ‰%ñ.—¾íÓ1&õ$çŽí¦9hÑ9³wÕÑWM¿jÿïÏý6…*@)åyëÔ’à” àWXù`wðŸã¡‡xçKÞÍë¾ÿNuëC£cÅÐÌæIT“Kžab—fnÅß²æö€—¬FæÛ%¤ªÛ¡ohÑɺŒE£L$ã캀֠ÍÒóû¯=þéåOvîÜO¡ 6$N'Êr;¢Jò¬×í}]ÅF ­Õ()íäVdä1¯ö̰r59‚H¨Õs«8 2¿FÊéZ@Iÿz/Ap eõ:ðW¯ÖøÆýòGý;'.àsoüלûÔÓÍËи|âùœ3r%_™ÿÛß Öå꯵ÆÚ/¤³f…°Ø«˜ƒH$PhŒz¦ÇD2ÅÎêNúÓ]:º·åèË—^sÇoù%ç‚ÜlÄ 6¿ÙuÝæg\rñö˜¥…ôµÕCÂ*!õÕ6&w¯S³|Õ«?˽ÎHò…Z¥mn¿r¼ßŠÅˆ›°b=ºÀJ%ŽùìWîâw>ðI¾ÿârË›oyÜÄc,ÞÂî‘'"Ë¿–1ºžÁ©‹TlN|N_—iœÊ+†5Æ9#çqñèy\öì3^2º·r¹ß9dk¥”>•`]ð¾þ þ5UOÙ9¯NŒ®D:FG‘‹€÷b…ª)œ7>Èá U~eÖ'~ˆ%³Ögó: Ä-3CÒ–Ì¿¿›,˰HV "­ùÄç¿ÊŸþÍMüò ^ÏÇþó'˜ݼÞính$ªJ¤¢!iô­ÄÚ5Ôu0uCè%DKú¶GDÄ&½™ ÇÎcïÖ3Ç/|ÅÖŸÂ%–ÆYY§4ÇN'r§ÏöçL^}Ñ·];*QŒŸÊå‰f¬c„µ0G¡§W¿2¿zÃçÔŸL,鯰oÈý_k•Uㄯ|ãaþæS_ç׿w½ìÝëÞàãqŸ×£ ´ e~¥óUbõ ¢œd;½„Xëº×v]­¦žc¿ 0 ®êlN¶qAãl.~æ?_”\ìw R@q /áš PA$W~ßΗF¢+ EE9â¶a5‹ËÝËL†1fÍ$Èá_ÿ~N½ßÚCkE³Óçß»…«.¼œ·\ÿ¶5÷[ê,óñÛ>‚Ù œPhŒÉrÆ©V*Üyï!>øñ/£:SLV¶å5 ëïk¥ØÇb0âœdÆfô¤ƒÅ0®'9«¾‹‹·ïš8ûºÉëqDRà”c= DG 0riõÜ žµíƒvJ¬£Â“`„I®‹÷©1“aízÌðí"‚XK«Óf±ÕçÕÏù9ªñʰ-Ì÷òÊ?¾žÏß{#q´ñxØH¼‰³Wblе†Jq÷½‡ùÝ÷ü;婼ôÜ·qýŽ·rÅÔõ¾þð_u”™!˜ÂøêãÔ£Méš-Û„15ÁÎúÎ?{ÛySßÛx>”±k©õ¸£àžˆñ ¾oËHÏ•7i¥}ÎUÄcȲrˆ×]rÁ Æo:à–‰uÌc‡¥‚“(AûõŒãΕå¯pîA–10†Ô:†Ãèh•>ç*þúÖ?_¥ãñK%È*ìÙ±çq£M© I5¢Õís×ûyÚ%Oa¢11´ß¥ãß’È'«¬î‡êÉÄE33 ¥mB*; m[ô¥OEW˜Ž7sÎèv?gꈨSøoÖ  1Àn_5uYã¼3wO^™eÖ‹ÿyCÎ8bk]™Ô:@Ðzñ•Š!5ýl@f2'¬c S–Ö©GØ,'rxeåÚ‚ƒHè§žqÅ^fänÞ÷™÷ ]ÇŽêÅÈÒ²Ìrán˜aT£:Æ_ýú#¼ëÿ1»“7½ôÍ«ö[L9†öŒšÏƒsdW$‘¬Å‚²bQøÜ ܼ§2 cÛ´m %Š1=ÎÎÚ6οpó÷¨†:“a5°&¬T€eˆ9óÉ“×UFõ¨m¹d ‹0ʹYóÊ|Ä8(Ÿèˆ ÈË ì”ø`¥Áµ1Õa­f/ù§ñ—/O½à©\}þÕùÿÏ®ŸÿÒg¹`çy¾a…÷,~ž™ÿ­ô$Ji]E¡É|@H)0Aí dˆk-RÅG.GÈ6֒ꔎmÓ·}êºÎh<Æ™£Ól¿bôùßÐù[„.Eé*ï o$‹ íÐíÚ5ö„Ôˆÿ8±eÄÐ7Yþ26be­Öc„ «Ë/k…¬Œ†ÄàúÄ–‡ñªÂŠøãç(t®Ðë÷Ù{ÎYLŸÕâ-}S~œÍã[xùÓ_¹á /±ú({v]˜9=Á§û>?ó~z¦I%ª“è`y¸{1~A'VpegD—1ÏéGPtN lFßôèI…¦¦l‰6±í‰cO!á,†iº!˜;&®ùž±éZ%è°Ì‡<Ëfˆ00†A–%=Zð•}kØù¹§Ïe™’™c %r" Y²:¬-hÙ-gÂTvûžuõ¥Ü>÷|ð–ÿ½ Þø¸éf>~øm<Ôü2‘ª Õ°@ Ø$|2% ,¥mÀ*\°$—‡ >ï„ËÄЗF2ªªÊdeŒ›Ç&ÔÑÕÖÀšN¡ò—>"`dó%§%¢Ý„Š›i Ðbò(¸ŸšÌ:DÁîȉ±~¾RøpÙ¾…ëûÓËÓfD°VñÂk¯àýŸþ-®<÷Jöì¼hçX,Žó¥Ù±oùË(¥‰uí”×½¶ë¸Ø–Y›gB+qw)…µ’× ®<^æ P3•‘ù «”˜˜ZTc||”ÊE•§öïí~è³A PP4bë–sÇ/$ʳ\ŒÉH³4O´4Þ, Ê%µ†~–2ðè>ØýN"¬ý k·¨v¯Ü&ëdžyÍSµÜŸ©µLŒ±ù Åkÿøgœø8Æ‘Î},ŽÓθ}îïùУoæ¾…/¢$FI”gû¬TO‚[Ùe5·õ¹ΙVò¯äjtµjÈ“fÄb¬ñ‰°®(µÕ™®Ž0}~õ‰À4%«ŽL¯¡û](ñ<µwt[¼É;ÄÝ"Bš¥h­Ñ~¥k‘¢9£ßÏ"qi_‘|N2¨õDÿÞ걡xZi‚ÃÆÚó·_]­fÊÍ÷ÝÂìòÌ*»}½1.7ÿ˃YêÑ(‹ýcDJSÑ5œ:c ZëqehÕ†ü†<Ø#⬤ü^VÞµ›;Ÿ%Ô®‹ëLjë[æ0 V "3רo«žE…spœR>gù„+­€¢´{[|Y½‘8“E"ŒØ<ÍKøAkíV â<ÇÅÕß”o|rGH|pÉ"a Ì%+` ëÁý¦­¼²‚o¢ ‚X÷ÿJ%ááǹñ–øÙk_ÅùÛ/`£ãPûnf»,}ÓFëµÂà²b•*ŸÄêæÀÚàärצµÆX[²„Š{ ­hE@xLEEëy¢±Pe„Š®RU ñæ8a—±Ÿ[YCòèZ@cÑ®øÒѨJ–”Ö¤Ö)E¤BëU—kg¬Eií­Žòä‹ ¥…9ûÕªr)G1¢’ɘOŒ.±+»\E ÕIr±D‘¦Óíó×û{¶_ÄÛ_öNϸgá&2; Õ‡ÎT–^G¿çé.C 5\^±î•=†¢(‚!“°¸W%®|\Y‹Ö!gïÊH%ó-t 1I”09Z}!Ø×M½Ü²ÇB!†MÍX²;>Ïõ²QùÊrv¿äDŠ|gÎt™ZKE(Ú¾¸ *gý:³B)Šà‰Ÿ§r§°á•½ÖD—7Ò!V 1–~ôÒå*~çGÙ<¾eã¬=·ïcßÒíÄ*¡Ü ºV{"…¡ ÄÁàÄ»µ¶p®­¸1g‚ Z;7r±„p´""b$NЛô;,2Œù k©fs­í Z*€³ –´u¢%„aŒA•Pm¤uÎ(åÛ)3%Q—×ÔáƒF¹(]viÃ*GêÖ‰æSŸù&û8É?üÆßsÙYþd2àÆcAjzDºŠµ†È%ê’.XÓ‰SfŒ•¬«)U+—T–õ ÈzsZ7ÄVˆò¸Jí¤†ï‰M**A °]ïF1†°DÉÇÆJàRnwpVu,®Åžx1 +!e[åÒ=­µX%h%. Gé#„3"Xe ÀXRk`fQ9)4Ä"Ö2®rUÇš}žàæ/îç ?úËüà/\ç|k]pËñòÈò7©E#yé—-õ xH)ò9ŽåzMÀ›gùP¨7ùÁþwÄEë!&~×ËÐ1Š>«Ê7ÓŠTäò+µBªj° 8Ê0ÈU@Y÷;êL뺦´VšŠŽ©é˜ÌZº¾÷ "xú ®é‹¸Uë(Çnל€ÂDÅz}¸¥l}¬nÆ4Ä@!?!€B¦Ÿùç;9yó¾eÝó¬5D,]ÓD£0v€RѰÄR¡êWù}|­£vŽ(]ºã `”R¹T[éÿtŒ:Ÿ…Y”Ô‡W½yçºjƒ IDATxØÇ_Œv^A¥ ucÅá3 uvÒák ÓzH ¹€IôÑšM=ªP‰È(É\e±ërK‰-D‘ÖÃC®\ç…:5¤‚Vñû ÷ú ÷1¬´­µVt;ŽmñžŸ|cµ±UÇ=ÕÐ*âº]¯eGý|>uôý´³eªº8s×Ë} ˜œ…º +Ô`Im‘î0L5ŠQâ¤høJ Q $gi•Õ‹RÊá+U¤Ð[ðÞÀÐWÉ)ó¹–*cœÆ9(¥TY„&ÄlGùÆE*¢%dÆE°2ïÉ.V¤Ðù™ÇZ)Äön—+} ®º¦`Š0!ÑMøGñ½S¸I’$âÀÜ"Û&&yÙÓÿã)÷=Õxâôµl­ŸÃß~Z÷R‹€+B!¸½K¢)u‚4‚Ђ`|Ñ7YÞ)$Õ†°N îˆ%æVù|)¥ÐÚ-Ay€^dJfÖåGx Uò](7x LPE1.þH9Iè(çæà‹.®H³¹—0ËÀgé¤6#5YÞ%c½Òº†é¶…שFµšpì±%>þáoð‚'¾ˆm“[O¹ÿéÆŽÆùüäù¿Å5›_@j‹òvWÒ¼*ÙxBäv0Kñ “çRÚ¼ËiæórìD!üÌà"d@9‹OÅË3¤À'Øg˜ðåˆqÖÉ.«€`°×Ø©¦Òž!óŽžHi_èÁÍêntäV{T—ò¼g•³] ``&å÷Ó@nt䋪4¢HsèÀ<ûðר»ýRÞñÊßÚðñN5jÑ/ÞýzvìᓇÿÓ¡Õóê¦@&ƒ-msÛË/”ë'¬xåˆN0Ý»sö¬mbæó(cÑ:TC…ŸŒÔ¤Îds•:¸Î£ÝÒ´iV˜ˆˆû™ók»<ÀˆDÇÄ*RŒwQ)pu€Õ®ßž*Ýrnò‹Ï@çN Û (\Ýß°éSöy Ë2¨Ê}1Üu÷AFôf>ýÖþW%|œj\½ù:¶ÖÎâoüÇzP‹F\‰·-*J‡§˜xœPº— b ‚Ãâ™"õÑÀrR «‰•½N SÝII‹¡o32/%¤ma_¬þ ŒŸ²¡‘;°z}ƒ1®bµWjDˆu¢¼[—`:wh»Kr¸Y éG)ÓVd@tvn¡KW_X`ƒ Š¤X:@Ö7<åÙçsd:㾃°mrûšeißÊ8{ôR^³çÝüýÁÿÆ×fÿ™8ªxGѰUBDŽ•ÊuÂÕ„(¿•a{ÀEúbcðÖD8‡Ö¥S>ƒ€§\‡õ”~j# j¤t( XÃ3„&¡¦'Lféf)±Š¨FIzTÉ]¶ÖÆø$OŠy&³˜ÌE³}o‚ú(«‘PÈi ÑEñÈV†ôdQ4â°…ñíámÞªÍ*H’˜oî¿‹×àÈLƿʼn'yÅyoæ罉M•3ègáD0Y†É²„äXSÊc ¹!ºZX4nÎRër'Sc\”Õ'àd>)Vùyt~í²ŽÄ¸V<&c©›=ReEN€­!ܱbk K}—ÖœD1 1Õ¸B¢<ÉÄbÅ9lD)çtðAr S†x݆²âÍ[¸jxMä;yKT¡ñ*U‘DŠÏýã½¾§Ãûßñ{Tâʪ£|;ÇU[žÏÞ©§ðÉCÿƒ;ænp=W “e(]à'÷Ù‰ÿ`:‡™1A>%ÑîÂRüÃ9¦¬æ‘ÆOˆ7CSú¦ÇÀ¦ô[¤6˜^Cà/ŒÕù†m9I&,·S”rÏÉIt…jTqOÞÄÏH‘¹“—î$‚ËY¬™k Y”yž:t¥¤È_‚—_î[•jÌ·äî[gøÍŸ|;Ï{ÒóOqŽb4³yº¦¹¡}×#ñ$×ù³Ô£±¼!æª; ŒÖŸVgýÃ.œì´8 W4¶*¬ <Â/ßw°2)çrUD&­´C;ë# ô„>+õŒk¹âœ 00ÛìÐ3®Õ[5ª0Viäx ¨Á÷šN”ó^‰Â*òdQ­4‘ÇÊK¥@kñ«`…ñ8F`‰J%æáûNpÓ?îçg_ô*Þø’7æ›n<´|;òà‰¸pâ‰ìl\ȶÆY4â n›ù4cÉ4Û»Ù;q SÕ­¬WFQ‹F°¢Èlæ ëH<7¬µ.Ò©=LÔŽ‘­XÄH;d‰|AÕFè¼A…sÁG®“HÏö™ë¶Yl¦D.㢫.j-° Ü3´çÚ–]×´PiF“:µ¨BEÇtI ·«ø^|¨<ÀâJ´-‚Ñ*Ç®Ÿ5â%¡=r §eâP/ÀG{“IkšÍ.Ÿýä}\séU¼çg‡ëÖû[wñþå^‹XÇÜ6ó¬|ŽJT%Vz¦‡C¬cÆ+“ì¨]À¡/'<ëÒgqý3~xèX™¸'‡YG‚X»Ê¡è4T|X•¼™Æ:×—ÒÚÇY4F9‚g^a8ÕQ4âÖ“Å’™”ö ÃÜr‡ÁÉtØdXc¬f!åˆ]`,-§,tÛtÓRªqъ목ˆub>R ¥‹Ð­öä³68A—+¥\~ 7 #«¼2ð¢qn\·Å 7*îÂzT¼"‰ß¼ýÝEËü¿ï¡^)âöëûoãÞÿÿÐLITk…$ªš2 x¯Ÿ›žír×±Ûøó?ýÙe« ™.0¾“‡"yîDp¦ÎY³Æ3‡U¾©eî)tr@£I¢Ø/˜âi©]Óe±ßd~© KÁ‹Ê2äO>w[ü(3@¸Š¡……A'åÑÅEöNwȬ¡W¯ŒÐHª´=z&uHÝ ±(´vHÔŠÉWp¤œïܘ¢Q“Uá½ lPÆ®Á¨&÷›Å>R&ÐïxtßI¾öùÇx嵯à©{ž~ʉ¸mösüéýoe`{ĺšû²Ì3¡v V«°Ú•$æØ£óP‡k¯ºvÕ1›éI2;p¸È›w.?Ñ ^æþUø66äöòÌQäCøyŒÂóÁyUœs¨“uYt˜oöܺR 2Ybg ¬¥ Â<0¹eÏl¹ÂêŒWÇ«4Xè·ˆ2M†³=S ‘X"¿‚EùȘï¦D õþQʇ—=‹.‚å‰I*YšÑiöèvzœ8Ô!¢B£RåÄÁõl+o|ÙKøÕ—¼á´syÑñû~Ûa]ñ¢qLšWêXŸðê.ËeAGšÇ‰£„'œû„UÇm¦ df€Ö®G“)èæÕ#ÞIæÕ™µ>›X9_ ey:Ñh/#"“JF3ms¢»ÌòlÏf¬‚Ž,ø¯„)Ι`¥pR«ggÂ_³ ·8o²Ç&£q‰Ê(õx‰n4``L.ú¸ Ô(´rº_‡¨Wî„ö}HþNïS´"I4‡<Éí_ÜÏ9“{yáSþ{®¼Œ]Óg±ur;›Æ'kŒ’ħ¯ðùðÃïãoý—ß “@ëp–ƒVïØ 3bŒÅ‹ŽcõQ¦ÇWwi§Ëd’Q%ÎW¤ÍoÔ¿…P±×÷ËÀA2ØñN"ï-UªÀA…‡ÔIíÝó*¤é¡è™íA›ãííE/ñ3`‰Ù5`È ¥wÅ1{œŽXêJ·–RŽ,,²¼¥Í¶š¡Õ˜®Op¢=O;êÑ2$+úÚX|BespÙ+ wÅLâˆXà í{ñ¨]”+ŠÈ2Ã×>w{¿4ϯ¾ô üú+ÞÌXãñ…u:Y“ÿuÿ۹鱠¢k(庛X³¢í¼ÖDÚ•li¥ˆKˆß‹ÒÂöé3Öd¶¾é%‹äS™›õ®Ñ¥sË ãó&½ÝÔšS¡’ÏY Ž â¼srÒV>WzY¹ÞÇ—ZÐò×£ &8 WH•À)˜Eu”¾ô©ª:áѹ%Žï<ÉŽÑ­Ôãc•Q&j£,Úômб®šÇeáºSe~4•"žáÅŠ‡—xô®Y®¸èR,ÂøÔGf³Øœ§»(ô›äÝ?ÿF^ý/?nÂì_¾›?yàÜ{òëÔãQ ´ºPCF«Ìq“j†ØûóE N"Ú½öšE:Yký‹üW!Þ‘•WÓâô·R•«õÜ-VHQX%Tµòõ†.5?Ö1V,Ëi‹ÙîÇ:Ðô×9`ËÑmùÊâÿðÜ! ôí1Ðçbàø|—G—æ8²ÉTeŠF\gKm’“ÝeºÙ€žJÑÊ­vñÎtI¤âŒD¸ˆ˜ÖØå«Ÿ>À®Æ…¼÷úOШÔÑ‘âÄÂ ŽŸ<Á¶MÛÙµõŒ ¡ú•#³}n|ìcüù¿G×ô¨Ç£ÓØ (®`vaY—àµòn[¸­²Ðœ¡ÛïÒ¨5†Î×ÌÜç7:Êò¶¤õ]FŽ#üÿ¥ôÉí W/|(‘ŠØËý&G[K,Îõ¡'.ü3'‡±´ Õzë€@K™2š²ûÙÆ¹dÐmg^\dfë"Û[™¨L0Y›`¢:ÊrÚ¥“è›lØÐ,q~x£õ@P+¡½Ð£9—ñ#¯¼ž361û±‘QÎßuÞæ0£-ñhó^ö-ÞÃáöCĺB-å…;xdùA ¢ÕsøÌZåÝס!Ádó&¨µîZ=†é§“;¤Ògÿcû™žî<ÒN—0Ö¥f"?ö†‡„_kX ‘BœþOtŒVŠNÖa®»Ä‘åezó©Óý0àТXäk2@YX MSBñ\è ç›<Öšçì±&ãÉc•1¦ë,ö›´=ú&£—eCÑ©üžBtO9=˜Z0™"©i®8ÿÊÓÎKß¶ég]Ž÷ö³ØŸcßÒ]ìoÝ͉öcÌuOÒÊš¨"‡†X%®™cð®I4 º7è[¡èNlQùÊrÅ/.Œ+Mc´ •”o>t'OÞûä‚fXZébqêA…'ƒ(¬ÊŠj(‚3^­²t62Å"í¤""­Iâ+–Å~“ãíEŽÌ·ádV¬÷Ù‡c‡áE6†„ë)3AÌa{/=ògZŸ˜ëñàü ΛØÁ¦Ú#ñÓµIæª ,ºôLJš¹§‚ä9ëåäÐ`-ˆ(¢zDšZ–Zk×é-§3Ü>{#÷œü:-ÝáTMÖ¦gúdÖÕ8D:F£©Gcˆ„[ž1GtÉ—KÑr¾%0à¸_!³ADÈ2K}$aÛ¹ >ûMüÌ‹^UœF,¬ExRÉpÌ¢x˜„Ëç+1@)P”ææ¢?†‹Ò>â‡òá}W—QQ1}›²Ð]fÿò<³'z* Ű̃… e«ýoó²®] ¢§²–eßì"‡·Ì°kl+#ñ“Õ ¦ë“,öÛô²ƒÌ¥~ .Å)8†ò‚±)î¼ù;ÇwpÅ…„ƒ­{¸áèÇøê‰›9Ú<„ ¨DUo.9Ÿwâ£nÊϤ«¢e(¥ PHœ,íƒÅûŸ‰ºÈ¶Uâ˜Js¤)ç\p_øç™_šÏÕ@&†VÖt)p>#h-±ï:¨œ©´‹˜â™!€äðž'ŠZ'¾"Bº»®XkªQ‚RŠV¿ÉÑö<ûæ—Ig.¤€–ÁrÐ_B¹7ð™” Xw¸,s2÷"~K*Ÿï±oa†ÙÎIº¦K5ª²¥¾‰©êõ¸Bù"4 uüRT˪ú )Gîjòò羌ËÏ)Š5n~ìŸøÅ/½”<ô—i'Ò ªÑʇ²C†S0“2¯¯!³¥ÞâVrj‹ƒ‚ÃgM3âu¾uú!|ß5®,ú¥™°ýÜqæ–g¸éŽ/–kègÝüºŒø‚Mq¼É|¾ÂÊŒg)yjn×Zy¥ßN¢J1W{o;6£(Øòñ +¹„оåƒ ¿v\ˆ—È;uT¾œ­Ï|*/;×¾ÀIk=1µìŒD“Ä‘óXú¢j\%Ö1Ký&‡[³/™Šë1^·ÅJéˆZœ0’ÔÉÄ0ÛY`ßâ,g:0“ºû«(è³Ä2ßô4.ƒ@7U>¥e¸¿J ¾Ë¥jÊ~šû©¨P4Fg1ã¾ãóì[8ÂÂ`+†‰ê8[F¦˜¬6IªÔ’˜Øû¾ AĹS¸† ;7íbzÌéÑN¶Ì_<ø¨52jV±gZÀ%FÉUéäÃü~ŠC¦“â ©•<¿^)èÍ[èÂäXÑ[ R/>÷5ìÝt%í¬åA®sŠSTEâ+¹{ÙúÏ™ÿ»œ\öG ö–H¢bê±ËËHtÌr¿Åáæ,\¢s¬M/I"à1ù:Âcž¦§jµrzKŒ°Ì£æf H(ê GNt¸ûÄQ,?F+k’¨„éú4[F¦«Ô=$>F-¾ ºo1°l¿`œdÜ ™s}øÙ¿ü0±v&ÍpÐÚÔ+îÇ5 V Ÿ‡õsVlN¼ÌXŒŽœ…žrÉ5«Žûý»^FUéÛ>F,;È\nº‡ u)EüÂÊûi\oæH¹ÌìZ\¡‘ÔImʱæ,Ìqè˜_ý™¿žÀ ù®5ÌJâÍÚZ®à R aŸ¹‰–ýIÆÔh8Ä ixàÄ"gOa{}šêh•‘¨Î–úËý6}“’ZÃÀlæcûá*Œ0¶u„ú3üå¾ßæÂÍ—ñwü5]Ïãâ%'(PØÌÉÂñ²rœ!d— àûÝ •üXa_A†ŸsTŒ¸¾ƒã#“èøÄÊ àê­ÏámWý_<ð,3þæ}Ìvù¼‚ä9†Pù)ò#©SŠÃ!ÁŠÒ$*¢W¯6ˆ£˜™Ö<û—OðÀÜ"ƒã%ݯEæXâvøl &X“ÂæBŠËz„G²Û¸ªò޼Ȅ™ù÷ÌcÇè&Fª£lªL1U`K£E'í¹ŒVk°¶ï x€ÂA&üÕ¾?&zع2#ÈXIJ©Üͺ’ä«GØ®aä?´§·Ás³…Õn_­VrÖZ¦Æ7¡IhTFÖ87캒½WÒµM™¿~ø}m 7œ¤Ç;Æ3cÈœ*[®Á— ¢ˆ#ò¨_-ª0Z©ÑHêt].Ÿàþ“³ÌœèÁ|J^¤€ÃòEàÅB °j¸[.Wz’/ÖÀ9î2ÿÄ@ŠÙUu,ûN4¹k懖ŽÒÉZÔâ:Û›Ùܘd$©1’T¨Æ‰¯a kMáĬÖ,U2ׄüiË^Ÿ}o-Á•à°x…$‡ J;@‡°DB©ïQlÅuâ,•oYk@mêsÍs.`ÇŽÕM¨Ë3ZÇxúöð®k>Ê›ŸI;mçç4Vr“ÕµÇ-@c‹@nMDø$5Æ*#¤&åÐò ÷/œàá™6Y@þ¼m,Gä†ñSV¨€½ "âŸ4Uf€PᘽýæöÄ{s)`aq1ã¾sl9Èxu„3G+Œ$£lml¢›õHMæúý"Ø´¨ tic*7‰„âA,®­Œ£–K®  .XVÂp…IAÜÂÑSp³¿¹x!ß‚È$Ö{ÅÇ @ygL/i³å™1¿uïëØsôr¶×wÓN[,æxæÎë¸dúJF’qb#",ögé: ™öLÌð5j¤$‰B[¸à쉈¢ˆz\aÔ?›q¶½Àƒ G¹î$ õœÛ7L^ “!ånOð°úËÀÐR"b}×°€-ðµôã\ýz:é[ŽÌö¸³ñ•êq•éÚ4SÕ ú>½4ÍW’¦G7M}wL..Ç ¡%z¡„ô7”'2²º5LÙ׿RE‡ÔÄ|G p™‹^|¹Ëç‹u z&åÈà0šûóV-‘ޏùøg˜¨L±©6ÍTm©É8°¼fÚ$‰*®L«˜éübòê&ZùV^J‘xÐWÕ1£I ¥ÇÛ'yhá(÷ÎÏrôx׿®§«ò”zÔþ=.ø3ÀÀÀã­Ï¥«[ k²7ñ˜ùqvÅgåT2Ðkži1Y;ÌhµÆ…Sš©Ê›j“ôMZˆPoËvÓ¡Ôõ“ð,ÁØ0̤á‘tùz•€u 峪‡ï ô±Ì~1ç ¸½ü K(h”ñI¬þJ Ò±kð)õsÏ9\NYèÏcÝIëec«¦Ú1a¬4Ô‘'|“D¸J=ª²Ôk±ñÌŸààL‡ôh–³â0 pP¾I“ñ/¿h£¸âbÖ3¼ B˜ãKÙ‡yiôï@ˆ†…¥”ûNœd´rˆXÅœ7 £É›ê“ |˜Xüjά`2ATÐíŽF\úš_ …Š(MÔ!ó •€*ü>+Y¨ø^é‹íÃð²üÍÂ\tØÔí)AÛ°¯»`ëß•)è Òeí¦yd@¢>ã5ò•Ø‘D£I±JƒVÚáàò,œœá¡™KG{°l q)H’àj ëÿõ8p] PÆ)Ž›ö›O±ß¼‹â=¤fG&œ˜poe†jìœ@»F·QKjLÕÇȬëi<\î‰ØûÌÎu½¿‚ æólè™üôåÛ¡¬Öè–g½íÁ; ÖøþïF&íáòb;Ïȹú‘€úKù³Ð xHœ”ÑZSÕ1µ8¡×™¨ŒÚŒƒË³<¼0ÃÁ“-NëÃ|æîsT€ýòeå¿¥c‚°úW¿0V1€ƒ!Á-˜ƒ£¸%ýKÎߙϦÝ´OU§d‘/]ŽÄwÆ(DO¾ªU™p*¿2#çV϶LÙÒ§5Ã(÷Ìa¨”ÀaÖçïž×½ø6¬” ‚ÂqKŒIavQ⨫µ/l‰¨è˜Jäˆ?šÔ˜¨ŒIÆQOüÃËMŽïbæ2èÙâÑ(ˆ¾aþ‰6ß Xýeà·îê‡u d0À?>€/¦ÿ‹óã+×ã9yn\n¦Ñ1‹¡oR¶Ö'HTL5ªP+ÄQib‰ÜW•"µl( ×á ¤ ‚ºdÃZ|e‚5ï©ô{õýºÿûôbœR-ƒàu¼øäÇ$‰BþÃð%]ðÆ:¢ÅT¢˜$r>þñJ±J¾I9¼<ÇÁ¥“<¶ÜâÈñ>éLê\¼!´#ž"3r‚‡åƒ~k‚VÆÿ×§“+™Àae¹‡ûÉÔ_W^}xѽ¸œ¡¥ƒe–IéNô™®«ˆF\a$®ÒÍ2L$$JùL[…Q¬3ÃÊ©«C¶}y忉˜9 ‚†ò(@_sM6Ä8Ã~ƒ0xrèy¬ðáj<”ä¹&ù”øZw _¡5‘v ¢*:¦‘T™¨4¨ÅÚi#Í“^>ɱf›ƒ3=z3èʰÍ„Ó7ìŸb8L!¥7¤ûÃX—ÖÇa0ÊÝæ#œŸ^É+OÅ0ôˆBk…“­ TcÅåŒõÙÜ'Ñc•©û=d~B=èÐ.£ËΛœÉ$§r`Œ2QË·iÖ¿g7òük†RÚ´js°Z”o—û ?†H‘}V»Ëˆvù†öb­©Æ1¤ÂXR#Ž4‹ý&Çš‹k-q¬ÙæðLŸÞlêÄ~~ þÂ*Àæfå3žF]‡îc#OM\)b Ahò¹þçœh/SÑäJƒµÂrÇ€ô°ÖÒ7†^–²¹1JE'LTëDJ±ØïÒó3n½›ÌyhÝõ«¨¶?žgí¬º«ðQV\dc…â ǡϟHq~¯E #Î: ûD¸TóHGT"·êÇ*uªq#–íEfZKÌvÚ]êpt¦Gº`¼£'¿Ywô8 G¸ÛþOO“ ú×ê‡Ó0€÷ æ …– MîáoûïáÇêo¡¢Ô Œ°Ø1X00ËôÒ­AŸÍ#£Œ$U•*JišƒÝ,ee.Ò‚Õ:–Á@0µ'ÌÊû }úVn[9ʾµâ{¹9:<¤$8BÑFèÛ[<üIáp‚V.?F¡#·âG“*¤Êh¥J¬"R“q²×b¶Ód®ÝáØRã³=Ì¢qä ž+p6¨º’rGö> ‡ÖýÁZÛÐê‡ H€’{Xùƒk²0Ê~ó)nì_Ä‹ê/§·âœ2ÍžÓí™±ô3K/°ydŒ±jZ”×"YŸæ`@7KQž3«@VÙÜÎvX±HåÊ 'EûÔp±ù¯ZÝáïü˜…j'þa™A­„^>¸óÄGIDAT‚òÍ ”Ý?µOᎣ˜zì¤ÞX¥F5N@„Ö Ç\·ÉÉN›™N‡‹}fæÐ2Å›¸TjÏMÙ8É—p ³Í°ø_3è³ÞØøƒs {(0Ax´¬æËésF´›k*O£»bõY!Ž4ýL8¹œa².=“ÑM3¦}&k#Ôׄ*V1•¨O7˼Ñõ0V§ °è`{Ë*¡C™z"…Í\=¬ÚŸ¢€U©5±C I=)t½[å÷8TQت¼7¯'ŒTªLVê4’*±ÒdÖ°Üï2ÛYf¾Óf¶ÕãøÂ€f3…ŽYí±ŽÜ ðuóŽÊGü–Žø=†£~v#ÄPÙ¯$…9XêÀ(Ð b¯¨¿‹Ë“ ‡$V$±"ñ¾‚8RÔ«š±FÄÔH•ÉjMõcÕ:•(qO!ë™”NšÒËR—rm]ç1Çåð/þ9Û»8»ïºéšJ«:<À*°C˜ë Öš º]r—‡#~ø¿‚Ä£ú8ŠItÄH’0Z©1Z©R+T¢+ÐMû,ö;œì¶˜ït˜m8±Ø§×6ÎÌ qý çí³qKí¾ì«ÜbÞŽ0[ùË8èRèÿ 6ÈùÎ*/MpüXÅ1Á8P¡ÆE¼¶ñnΈwäÞ*å@+…o!Hij1ŒÔ#µ˜ñZ•©z‰j‘J•Šï”™÷ÈØ^–ÒÍ2z&sD$3C‘>ƒ7)˜!8Ë’‚r0Ipâˆ7ãŠÂŒ!“P‘3Ê›yJ‘DuêÇ+uF«UjqB¢bK?Kiz,ôÚœìvYhw9ÑLYne¤=ã…·øLZ<–·Ž ”Àæn6oG8„[ñ˸¨_aâ¯N1>M') qR H‚NÄìPOæ?5ÞÉd´™ÔAáJ¤HJn=­µ_5PMzÄh-a¢Za²æ˜ ‘TH¢Ø5˜)úäe}›ÑÏŠ‡Qç9uA2@ÉföFZi{ŽÔ)yìB¬žÂÃùcæü•û\u®ŽBàÆ~¢Ze4©Ñˆ]?EƒÚŒf¿Ëb¯ÃR¿Ã\§ÇB+e±Ñê·â-0ðéïFœ˜ê[Çp_z/_4ïF¸§ë[8 ÐfEÐçñ¬~xœ ào¾¬ bœ$¨ã˜`ˆØ©¯áÇê¿ÉT´‘ve׈äv@IC¢ Ž I4ªf´’0Z­0RuH¹‘T¨F ‰v!÷|BCߤô|ÅÌ8õà’)K`É»NS*ÁßÕBXËf¢?Rš$*‚6#•*ÕÈ%kþŸîÎå×’¢ŽãŸªêîsî½3€ÃËœŒBâ#JŒ!lHŒƵ[ÿÿ7®‰qgâÙ7*h@ƒ‚8‚QÐAÃÌÜ×éîz¸øÕ¯»Nß3ã¼Ä{©¤Ó'}ÏísN¿¿wÕ¯ë†ûwѳÕ-¸Ð.üÅ‚ »=ç·Û‹ÀNÇ”g@§ÞÓ&­:ÁËýËü3ˆªßBlÿ"ýC¹÷JÁ‡k#€ CLú‡ËG2 ޏ[¥rh˜[1‰œÒug„ °Ìj˼v¬Ï*6š†ÃuÃz#ÇÌUâU[Ý«/oƒ¬KÌóìc^-Ô§qgQI1¤Q­ÐfiÏ ›DÊ í¾a¨¬aæ*¬±4NS¸5sTÆ YÇ#‹Ô³Õ.ðv—Ͷcs·ckÙn¾O´!|¡©• ~Ÿ²äû—ù…WÉï€MDꌎŸ:}W¤ú<¯‚4«HP#š A´ÀaÀpÔ~–¯Ì¿Ç=õ ³€5gÆòn&@erã|7cÀV†ÚZæeÞT¬ÕŽºáPÓ0w5óº¦qUÞ¯H¥WÖóK/ã0ô*èC\j“r,/¯å3u!(ù{8+íñu?¤ÚÙaUŽËÍRÎû‡$[Ýïú–í®ã|·ËæbÁù¶c»íiÛÈ¢‹´¢5¿ë)xµIT~›Æ¸ÿ´ÿ#¿òß'r‹Ñæ—ùþ¬¯H®’ò †ìŠ:†jÊèÀ±Á½|}í»æÓÍýk}1½KÍ€ö¸‚ªok *KSYf•c­®Y«*æuͼªi¬,“nò~zUÞz Ä‘ >æ²£&’÷jG|•ÆZŒ‘íÞÛ°Eí] ïY„Ž­¶åÂbÁfß±Ó÷ì´¶ x/“I»DnÚœð Z%@B¤}' ôá¼äŸáiÿÿ`”ü]ÆrïÒDÏ«®Ã ŒÑ9ºçðŒ1:8 ÔXŽòÕùwª‡gÌ£Awˆ[2 #5ñaÕG0ÔVææ™ìKTÎ2¯Må˜Wb‹kë˜U¹¾žsvÜÑl˜l‰)@Ó¤!c¾.|·‚5ˆIi}‰Í®e·ïØî{vzOçÞGzŸxm—“…[v`…Ý[æ…$aß"«~›$áðÛþI~ŸÎ2ÚümDê—Ô>#®¿ë@€iŽ@5Aƒæ„ º8zøšlØŒ-Ï÷Oñ|ø1ð²Æ÷šâÝcó§_y?F´t¼ìl Ä8ÂÇí)=nNÔ'לmôçIÙTÒÆÎdI7Ú'Oˆ £ŠA¢Q”'™ݾv|j{wÈ( B”9€4L[zOfB²}ž)glÓ~ í£D m”˜¾Ë 7qÆŸáÙþGü;=Çhß,wÊò®rpO¸·ß#Ê¢‘Aµ¼®¸“‡«G̩ٗ9âîÀK?gMîƒo„Ùî[½–Ϫ Ô-A¥>éw×çâ¡MF2(èKR€²Ô“²)17ˆ’%_]Ht}–øN}Þçø]÷$Š?ÞF¤{Á˜ØÙeÌî•jV€û“°7YTåCµ¦ÅY¼Õ|’‡êÇx yˆ sÁæéÒp ÎIR¦ÊQAÍf›>¥É™~1X–|ŠkÃû2Yb®Îjwô”rKšO´!â³÷Ÿ4ïÓXyrvbÇ‹þ—<Ûÿ„Ž3¸jïKu_J})ùj?öj­!”ÙCqáFŽ™ûy°~”ûšÏ³a/=#æaæd{k Ήs¨Å¦dF"Ѩ?±ºÚW¸ä6AC²(…\#È×CLôQšIö¼à£yþt×è+ðÛ±ã´ÿ5/ôOq–ÓŒI]Õýt2§†y:Ê1¬Ÿ`Ù$¨“¨¦a–¯ßÀ1ó)>W‰“õƒ±·,ÍqU‡1GƉsh­\¯s4‘` †6æÖ_;ܦøùÚŽÈçp.Dð9aÓ§„ïsh×'©Ô…4Vït¶D•óçÓ&/ùgx¥ÿgù3pd/èS[¿²­û¥ÆA @© ô¬$мAI„!Ê7r'ëS|¦:Å-î.Y;ØÕUâl¥ò¨>sFCå·(†ÁgsYÙEÁ§±b§g}ßð™ð‹”øWx•Óþi΄gèxq‚f xéÝOmýƒ°üøËP±Liy¹$„¼Çq3¶pOuŠûªû9b²žÅÚ§‹Ï#/ÊУÑWãž/–;1Juš­ôâ]Nìy7¼É«ñE^÷¿áÍtÉâi¤_N×V5¯à—þ”Ò8”£Ôe-A}„¦8Ô,Ô|3*næv{’¹8n?Áñê9ÄÜ,KêªGš À˲ðªÇ ÷¨sRfç$Z¶xÝÿwÓ+¼^àlú+³¨‰Ñ™+_œW%u®HêËq °JLµ‚j„2„¬‹kä÷ÝÀÜÜÂæ^ŽUw²ÁG9nqƒ» “fÌŒC÷H/%¹œý¡CÿÞç¸}'¦›ñþ™Þ M¯ñFx³éot¼‹iôNº„N%½»”ö©Ä_Š‚—5"–þ}r”DP­ šAÉPAwÄ$Ÿ×q¬S™ Ö¸£æ6Ù›¨ÍÀ! ‡HDÖ9ÄaÞã<1¯rL\ ±Ã"¾Ç…xŽ·x›˜Þ¡g‡8Ôáõ•½”¦j½¼ìбÊÁ»f:†Ûäs6NµB™O(MFI˲†)C)õ5Êû”Õ5µÑú}ô{(` ¢gYº•¥”ïiÎȲQºö¯7ú€`¸]>—¡c™G˜bÕa/òÿeéZUãP–XÕÇŸ‚W@Uy z˜Ügà× xׂᕬ x¿Fi©§¾‚.ÍWK0§ÇT‚ËíÓÝäÞúyeÁ¥Ì½—j{ òôV…rz¾®’r=Æ~$€Žò–§ðÃH†Òdèß§—faJý¬Ôòó§@–@¯zÿªï^þ¦}5ö3¦cJ}]jŠò<%@ù÷©Ÿ ÷¿ˆÓmzýRê}ß^ŽƒB€‹%H¦R6=—cJœé{.ò¥>·ô!ä8(¸Üñ߭˵Á—èÿÌ©{?Džׄ ꕌÿê*…a™_IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/000077500000000000000000000000001217176075400213565ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/add_dico.png000066400000000000000000001131131217176075400236120ustar00rootroot00000000000000‰PNG  IHDR\r¨f OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGD ;¡òS pHYs  šœtIMEÜ %æñ©5 IDATxÚì½Ytçu.úUÕó ô€©131P$%R¢Ê#+¶¥\;±½N|ì$΃ŸNòpÏ};¹~ÊËÍÉCVÎYË+qîò=YñMâøzŠÉ&©‰eA$±Cè¹ ÝuºÿÕÝU=¸öZ »«çªïÿÛßžEQDEQDEQDEQDEQäD £|/Ey*"Å/¥9¢ŠÏ”ÝVD‘ã¬ôÂQ5Ìü.*‰?Å(òTE«ÕVcY¶¾…Ì0$‰<€ò¿#eŽšPPЊþ4Z­–"‚\.'ùâ|>¯¬Ú&*UÁö«Õêgþj)?QpaoooO¥Rñ™L†ÀÈÀ‘1š#¤üÄhÕjµaoooKQEN‚ètºfŽã¨a8J(à(qİ ØŠ'¬þ3ƒ™ƒ¼æ ¯}šŸuØÏ«pdáÀË=V~\êyµžCîW{^£¯‘{¼ÚsäþÏårðù|P©T&½^ŸËd2{G ¨Ž’¥´Z­*–eµ ‚  ÚŸÔÅ©µPÇkúÚ§ùYŠÔkÛZë°žuªR© ù|^kµZUGí¼)ÏçU‚ ¨U*û$v²ß¶ÿ¸Îy9EFùsä^[~\êyµž#õÛA(yÞã\?åŸ_ïÿ ðFÏçU8bd¶ê®]"PEåúTS~†a$'ÇÉcÉ€¨qD£XG*@B2Ýɲóf·<è÷;Èç=íßÖ(hdǯµË׳óW»_~û0ß«äQÃ1‚ 0Åõ}¤ä("@‰ù+ò„PÁÓ|íqXÏšãrŸÆNû4‘Àa>ïiÿ¶gºó×»k×:^í\Õ{.¥‚"Š(ò[+šãö…ŸÆN{\ÀÓþmO –¨÷w7Šá ˆ"'Œ78Œ‘V€‚N4¨¶ØE‡åÄïqN€¼æ0œ€‚ú¥T 0QäÉïæû5 p‘ÀAÆIÎK8/ð4‘ÀãöýE PD‘‚N*"М”ò´vÚÃÆî*xR¼ÀA‘@=(á0õ"ƒpâûù|þHº¶ PD‘'„Žj8²à¨ï´Ç%‹ï¸"Fø‚ÃÔÔ‹6Ê‘Àã>O  _H‰(òŒwúZU„' (Ú¦ˆ"Š_ ò×*%–BTù|v¹ú­vŽ Ô>.É;¿®@#î‚Ü禔XAŠ(rB@#î‚Üqžçð´‘ÀÓÚi•¦" dÇ=ªME ˆ"'œDù­(>©Hàqp$'¹½ØAw~r_4¹HAŠ(¢ W$ð¤ÑóDOë·=M$pX ¨ç|‡YJ""ŠüËoe9ðÓÜi•¦"Ï vç—ûmõ"…PDEŽôäêS ¤ ãÅ‘ÔÚå«¡ãÖ^LAŠ(rBDi ª g¶[*MECõ „§Õ^LAOØÊ*¢ˆ"'œäVi*òd‘@#|Áãl/vœ62…PD‘'€` ŠUFƒc$p9’£Šê}Îqñý ˆ"O (@E@qN‚+𤡶â <^W È_¯+Ј» $)¢ˆ" x»|-+zwZ¥½ØãAìøµvù“¶ó{@‘úåÚµk )ÔØØìv»râ pÇ |÷»ßÅw¿û݆^;11÷Þ{ïÈq$Ï „8¢¤Ÿ`™ššjXù bøë¿þkå>æÍéHêÚúj“ɤÏçó6†a¼[[[ŸÆäu‡1?ÿó?GKKKÕÅ-·ˆ#‘ðé§Ÿâþá(7ðöÛocbbÊÉoÀ UT{äÀ³Ø2˜šš¢ÊNzzzpúôiœ>}N§‡133ƒt:ÝðNèóù0<*>f0044„îîn A¯×Òé4=z„ÅÅElllàÑ£G€ÎÎNLLL`ttãããƒÃáP €bf¤ ÓI5SSS˜žžF Àõë×1==Mw÷r…ïééÁ`€ ª/,,”ìöDéï÷~o¿ý¶äg&&'qûÕWÁG£Š+R°à— ƒEÆ€ bºººJþââ"Ö××±¸¸ˆ`0ˆH$B‚ßïÇÄÄ:;;ÑÙÙYw˜ñiòOʰ,«Å$R%ôv9Yg0ÐÓÓƒÖÖVôôô ¥¥ERá‡éëÆÇÇ111o}ë[;ýÚÚ±¶¶Ю¬ÀþßþLRŇÈ¿Gþƒap£Ì@WWýóù|ÐëõFaccÑh”±Q‡Íf£|ÂåË—)×`·Û yòä¨ÓÉÿï¿ÿ~ÉýriiiÓé¤Êîp8àt:!Òé4Ö××±°°€õõu¬¯¯—(<Ü—/_ÆÛo¿]±«F£Q,..bqq<ÏÃd2Ád2ü‹ÿšéiì¥RÈsY‚P¢øåÆ€ð?ĺº°´´$Éx½^x½^ø|>tvvJ*ÆÆÆ2™ }òÿË DWWü~?l65lãããJV:¨!hÄHˆ]Åœ @”˜ìà±X ÓÓÓUœìè­­­T¹‰Ò‹úp8Œp8,«ìv»îðä)X[[ÃÚÚ677‘L&¡ÕjÑÖÖ†¾¾>úü½hw¿þuìÅã…¿D{ñö’ ä²Yù|…ò_`Çýõ¯a´ÛFqíÚ5LNNÒÿÅ»»ø{ÛívtvvÒÛ^¯:Nö|C ‘ÉdFF‘Éd …*Þ_ll6[‰¡ ndz6‚ óù¼bJ>)˜N”¦§§‹ÅJvnñãµ(°ñpêÔ)èõzzœ,Š……¤Ói¬­­a}}ét  šÀàË—/Wõ™£Ñ(677±¹¹‰ÕÕU€Éd‚ÛíF[[ý|ÈårˆD"Ø}ÿ}ä®^-*~\ô—À^¢x;•B.“A>—ïdý~|íïÿ½ÃÃp»Ý²ßejjŠƒk×®!brrRòùD1Éÿ~¿¿ä9¥¡P™L¦Ä(ƒAd³YzÝÊEŒÆÆÆ`³Ù$ÛíöÇf´Z­bž¦+±Xywww©¯-Þ¹ë‘S§NZ[[a0èNN_|á×ÖÖ(t'Š^®ädÑùý~Œ7DŽe'ŠÏqÀáp µµmmmï‘H$°»G$F>ŸGö“[pm¬ƒaä2iCc/ǃÜð¿ýÝßa§¨\àv»áv»áp8`·Û÷] !Æaii‰þz[Jˆ!ðx<Ðëõ°Ûí°ÙlÐétðx¬øŒË—/S8Ú(F‘L&)q‰DL&KÐápPEÔjµ%¯O¥RH$’ˆÇãØÛÛC>ŸG>ŸC>ŸGjs æ¿ÿ;¨m6¨­V¨F@¥B>›-3 ü¯?À—ÿûÇ¥?ú£Dþˆ°, »Ý‡Ã“ÉDB-ÃPn Ĉ1ɹbã 6 n·›’5Ñ„XÊÁòò2½½»»‹X,†l6‹ÍÍM¼ûî»’ Qâ÷Ôh4GÚûr`²Ã·µµQ%Cr¹Ûâ E”7NÓÛDÙå”›ìâmmmT© ”l$KŽìâb%'!4ñ"omm…Éd¢J_.ù|Ç!•J!™Lbo/WTúʱT‚ɈøíÛÐ45AmµBcµÒÿ5´.ò‡¥ÅEäÌf ¿ý6R©ŒF#58bÅD"ÔP­¬¬”*‚N´Zm‰‚jµÚ’ñy“ [#W¯^¥|Y䘔ˆ „Õj¥ðßf³Ájµ–okk£¯#·ÅJ½²²‚þð‡8 rbR¿üå/ÓÝûáÇô‚­­­Q^]]¥J-Vp9!a©/|á % Þh¹l$ÏóTÙ‰¢‹…ì Äww»Ý5wPžßÏsˆÇTÙ µ7—Ľ{PÛlÐ8å'h€«Ë++è}í5lmm‘ ƒ,ËÒÞn·£««KÖ°% $“IHž;Õ”œ,j–eáñx¨‚¨ª°‰Ôj5r¹<ööøâ®/xðdÞdB>¿» †e¡2K €ÚjÅÚü<Æ¿ò•’×qG M"‘€V«…Z­†ÅbA:¦‹(x7%BÎ 1ŒÕ „A˜L&˜ÍæªF¢œù¯u-ÅÆBÌG”ÿøã.\(áŸÈ¼@)^ê8Šc^~ùe¼ÿþû…8vñ„…öûýt!”'™4*âEKœçyz_¼£‘ÛÕÕ³Ù\·’ï+º‚G6›…Z]ØyU*5ÈzR©ÔÈçs‡:o¹ÎN¨ïÞ… ß?›¢Q0Z-5©H:‹EÖ(Ó\¡R©Éd R©°³³³ÙŒÝÝ]èt:0 ƒ½½=˜L&úû‰á“‹&sMÎ31¬Éd›››H$¯!ÆAl¤ŽÔX|îsŸÃÕ«WKÖÙI(ˆ:ò€Û_.étšrõWÕðÅ)Wh²ÉîTî“‹™pñýz%•[L& Fl–ƒÑhD.—Ã0`Y]Ý\Hcçµ4áG|¾ó‡=Žb1Ú,B|jíjF£ù|‘áÐjµ«««p:H¥RÐétày,Ë‚çù>@ìúH!‚D´'׌ÛÜܬ0Ì嚸Ä(‰£ r×ÑjµBd2™ºvüãÐ×âÄp«««”¨¶XHˆ@v©…ò8œ|†^¯G"‘€N§/„à²Y ÊÚçó]„Ä€= ¥—576™x¼ª(¿-V†òïßÜÜ °X,`†&ét:D£Qð<•JE5•JÁd2!•JUœ{–eé±Z×…\k1¢H&“%äÎ;’¯}óÍ7©Á `kkKឨ¦åøÎ;ñ~‡ÃA ,³ÙŒÖÖV8Î Vº^ …B%JžÍf‘Ëå ÑhŠ»¡£ÑD¿w¹P¯¢?NƒÀ0ÀÞÐTwï–(~¹1ÐØœ›ÃÀ•+Uϵœâ×2å¾|ç4 `ƒ»»»Ô $“IŠÈ9å8Ž^Ûr‘"ój!Áp8Œßüæ7¿ù mÇðŒ„„ÍΞ=[‘8ÒˆkÀq%{Ré4´mÑå0Â`0 —ËÃ`0Q|®¦4‡_X Hê‡Plò Àÿƒ„jç†=SòW×ç™L²ŠOþ´u~ßÃÜ~œïû8w]©‚ÜûËwe4ØS”µµµŠl41Ä—Rké›*´¸â‰R9åhXÑ¢û÷së,c°,r¢\‡5¾×aÅétPî§\ZZZ ­9È9P ÀâäN´ø˜Ùb–PV‚z¿#Š•|S“|PẗB…åîîîcQȧÞù‹‘9Ã[+ pÜfZœ¨(@ùÅ©–yWâ·‹6T©_`j½ÁÁ¹€gE曛늊Ÿ}ëÖ-ZŠëp80<<Œ‡¢¿¿ÿPÀã$KŒÀc8G$‹ð¸ìæ' nƶ"„#ÈÞ)A‚ ÉО à8똙¹ƒ²÷qnk+¾ø‰ «« Z­Éd< FáæÍ›ˆ“…ž5Pþ#«ªå¡B1¨fÐŽ8r€2ïu iØ ^â&›ÕO¼õ˯¥IOK`Yþã?~‰––¸\MâªÂ]‡Z‘¯+Ș›Á€®®.¨Õjp‡`0ˆD"žž„ÃaÄãqètºšµO2(z;ÈI*׸£1åMWð„P@-¿«VÇ:ù¿ê›ªP©yõ¢€ƒ AðÙgŸã²ðùZÐÛÛwh8Jú Š£%¼ÓY¸ÊÞÇh4¢¯¯ð}Ο?¯×‹ëׯã7¿ù âñ8âñ8ý^âÛÇ‘ B:‰ßËf³ÕÜé•Z€§(‹‹‹%aA±„B!š $TÕyAÒ% a@FÔ@ÕÙ¹‰‰8æç"ÞÓé˲ØÙ ãÊ•+ ålnnÂ`0À`0`aa‚ÇÊÊ xž‡×ë-yŸZ<d$@"Z­Ùl,Ëbcc@,ËâôéÓ˜ŸŸ§•v¤ê“ää8€ƒ8R‡.— ‚ `ggGáŽ*b(÷ûÅ‚eµu ¹ÝC¨T‡ÙlÁ`Á`Žà~÷ÝwŒÀ /\€ËåD<ž€Ïçkhç[[[E °„ë× Í8wwcH¥Òèìì‚ÅbÅððihµû6?WœôS lÎÍUìªäþðð0¾ùÍoÂçóÁl6ÃçóQc@žsÿþ}¼óÎ;¸ÿ>îܹSu·ž››£ˆüÍßü fggñþûïc{{»$"Q8]ÒÜÜD @ù{“ªF¹ã('º¨\X+Iò5U—|®DH ‡ÃH$àyŸ|r^¯Á`pêToqAeï€eY°, ³Ù‚¯}ík g¼‘²åS§z¡Õjár5¡µµµ¬[P@¡¹gÆçƒéîÝŠß'~wm׆+ŸÏ†aÀqâñ8U–õõuZ´³³³‹ÅB¹ƒþþ~èt:loocnn®X Íâüùó´˜+›Íb{{ï¿ÿ>¬V+ÖÖÖÐÝÝl6‹ÁÁA477ƒeÙê®@† NÓvaõžûãXtâ\ñÎ$î2K ¯¤ÎJÜ„ÒÇJ`¦ ‚ç8„B!„B! ÒÔÑ,Ç!™HÀé,xÎ>D$Rè÷O”›ã8œ:Õ ¿ßp¸%¿úÕ¯‰¿æçç¡Ó±ðûý ‡¿úúúEÍ?…b¡R®.£&‡,ØÏ²¬ÆÇHåå»\®ø¿³³ƒD"x<ŽõõupN‡?ü;;;8wîΟ?ÅÅEèt:¬¯¯£©© MMMCkk+Ö×סÓé°»»‹ÕÕUX­Vlmma{{ccc®€p`W œw©ÅG)à!ŽŽ,//ÓÇÄ@„‚•û¸ŒØÜÜD:Ïïa``ô!</X–E(„Ãé@(D8€Õv®••…^õ0™,?SÜáÍ`¦ÄDÂ7ÀqÂáôö&$`¹p‡l6K{ö5Jx× @$Â7hÿ>§Ó ¿ß_‘Pˇw¹\p¹\`###´‰1MMMhiiAKK ­î‡›šš`±X ×ë100@IÇÙÙÙ’f¯—»‚ Ð0 ¸ˆ\q»ðãŒNðûý% ! éün,†x|<¿‡ÝÝ]ìíñˆF£hkkÃêêŠ\ “Ù„‰‰ËX]]A"‘D2™€ÇãE"YPÜÁÁ!ÀÐÐYÔK‡Ãà8÷î݃ÏçÅÎN:‹D"×^{½‚ØßO$Ðh4˜Ÿ€l6K}U£ÑˆááÓ ÒTWeù«e†pªh`xžÇÒÒ\.VVVÐ××'û]k‚ФŒ™¬«ÓéÐÔ´Õétôõ‹‹¥bøJ¹ŸWº ‡IPlÄÓ†pD€Ü€‰`0¸ï È„þ<¸øn,«E,£‹³··{{{8{ö,àõׯ€-v²að<‡Óé€ÉlÅ  át:1;{ƒ‡ça6›Á²,åÈ}²ã‹•%‘H€ã8ܽ;§Ó…ùùˆÇãðz½Ò>Ë›ÍVÓîíñH&SûŠXРРçìÙ³Ðh4ÂG"8N$ ¨T*ÚìYdÊ¡$9à û3˲%ãÚäD)~Æh@ÎP«Õ²¿¯·áðæç`dd *U¡e•ÓéÃʄŰ;‰àþÜ,&&.LÁyà8++ËC0›Mp:]xçÇo|Á`f³™’b—.½Œ{÷îQ(I>§\nÜø˜¾ÆëõA«eñ替 AÈÃf+Œ°|ÉdCÝO¥RÈf³¢ˆ@ >Ÿo¿—AYØLÊXÊ”Ëf³ÁårA£Ñ àƒ>€Ë墋¥` Hn7¢Ð-&¿• |©æ÷ 52wvv*ø#‡ÃA¶Â1$PÅ5 { Jôw55Áívú¨TÈíí!‰`oo^¯?ÿùÏ100“É„ÍÍVVVðèÑõÿçfgÑÓs ‰dáHáp„*}OÏ)°¬ƒƒÃp¹ t||¼ªÜ»w·h\8{ö,X–…×ë…Éd‚ ä‘Ëå+R‡oݺ…–Ôj R©Bß;‹ÅŠÝÝ]8ðüˆþ§}¾ºP@L¦úÍápÀl6#`xxóóóà8>Ÿ|Ùl}}}´ÿßãî@x€µµ5d³Yd2d³Y¼þúë¸{ïúÊà?$Ý"ÄxH…ú%•D gh–––ÐÙÙIÃS%^ À”¸ÿ$d·³½•ŠÁÎÎÒéÖ××ÑÕÕ…­­-¼ùæï"™LRr¯§§Ý==øè£àñxàñz‹= ]ˆNœ'^zéRq1Ðe!»¸çç c~~ßøÆÆÎNf³‹¹¤•Tƒ‰ÕÕÕ¢Î!™LÑ]¾­­‹===¢~þb-W6¡WÎÄÖÖ$ ­ÃáÀK/½„\.GÃ{"ïììÐ(ÀÌÌ Âá0ü~?X–Egg§¤Búé§p¹\hmm-A@! xÿþ}´´´ÀjµRƒ²¶¶†©©)Œ#“É@„Âtå ,ØX߀Éd,¦ø|^Y~ ‘HÔ( Nšºœ @â¶â ÐÙÙY÷EÛÙÙÆÒÒ"ööö00™Œ°Ûíà8n·ÇáÍ7—r`2›ÁsèéîÙgîFÔ}©™ ±±„NÇ¢··ÐÛ{ >_‹Ìb,üŸL&±³³ƒîãòåW166†¦¦&:4$—“&άU¬©¡ Z­–r~¿ ÃPû±±p8L“{\.fffàr¹`±XÀqúûûñÑGã8,..bii MMMp¹\à8‹ëëëXZZÂöö65ÍÍÍX[[ƒN§ƒÅbA?r¹ž{î9lnmÁl6Ããñ  VIÞ‘wÄ®„BaÁOúÓš­Äã˜Ê(Àî.ÚÛ;hÇ`â¿ò]Éápà•‰ËûoQž ©£ý£„xøð!t:gΜ¡!Bâó×Ú’É ÍÍî:ZPíワÝ- sÕàxž‡Z­® …CØÛÛ‹¾¾><÷ÜsˆÇãÔWßÙÙ¡ AŸ~úi±àÉ…š4tÿþ} HBÎÍÍa``ÛÛÛ°X,Èf³X[[Ãk¯½FÛŒïg|²ðy½p7»‘ÏçÐÕÕ…t&SšÂ[žÙ(Cú)Q€#àÛ×+ÒÝPƒ¹-|ŽÓՄϽö:Ô*U‘ôSÕôGÉV^âNÛ‚Žç¡cY‰$"‘p‘@ Ó\óBÜ?Œ^xA¶àGÊ—L$Èd2Å:7šš†«ž¿Bá ±Qûñ4ÑhMàú»ïÂâr¡¥¥‹>Ÿ¯î¦ Ä ßGÐA<G"‘ á<†aÐÒÒ‚‘‘z›äü€þþ~:Ìs}}½$ú ÷Û¬V w³9ÑD¥zƒÄÅ@R£ËðE­VØ×Êd2’C"²¢¹öòˆ@ –|Ÿd2 †a‰„ÑÖÖ^‰Ë³³³èééÁ§Ÿ~ ³ÙLCyh¼¿½Ý—ËY¢Õ”‰ã8KÅ ; .ôèêê.I÷•"¢õ¯\ IDATÄ»#ÏïU%µdOC8 ­×‹X,†L&#Y§ÐhØN¬øR¯'°^ŽP#†Ò„péu¤¿˜,;åçÆáp@É"!Å<Po XWFl•D*ZyËöd2Içί­­aoG[[{q€e­–¥ÐŸç8$“ 8œN,,,`pp¡P,Û§Ó–ÕÁãñÂb1—Àðz{4áýá˜N´µµÉÎ!K*•B,C*•D*•*©Ì«ýÉŸ€¿³íCCà8z½+++ˆÇãðù|àyž=®9¹]¹ûËô~Të´±±QqŒ)$à1‰LNNbbbN§“^ЂÿJ½²kO0DKK vwcƒH¥ ‘·Û žçŠ ;Z˜L,.>Âõë×ÐÝÝ]€äÉ$ííèéé|á _,I*%…ªAŠjv͆‡‡a2ˆ-AËå*vª@` ù|á˜Á`ÀÜÜ,4-z½¾HrŠ8„ÎNèÅyÆÀ,R½^Fƒååe¤Ói,,, Ó²f’ùHO=y‡MÊd2ÐëõØÞÞF:¥X‹¯oYïG Cát9k~¾R ðŒ[j¡HEHþvy…Xi¿R†~jê6ìv;R¨¯¯&“N§³H zŠïVËÂápz 0€Éd``p°àwV„”¤”¾ðÙÄMXYYÆÎN yäw8.8 õ ´'j}>æçça4‹ìú´Z-Z[Û`±‡:Ž6êêH"÷³e=ºººÉd°µµ…D",//cccgΜÁÍ›7qáÂÌÏÏã¹çž£çâqÎX\\ZøÉ'ŸÀåraqqCCCØÚÚ†ÛÝ 5©‘*¿ÒÛUZ¸‰Ï—ÝnfÃ\ h”<,WÅt:…¡¡ÓH¥Rèï„NÇB§Ó•DÄòÜsgK€ø¶DÌO*ï€|‹D"ÉÉÛÅjA‰D¡ŒÖétÂb±Àl¶ÐèYxb?™Lbff>Ÿ~¿~Ê ŒŸZ­U ækúüRÇ6çæ0øÆô¾Éd‚Õj…ÏçƒZ­F"Q¨ óúà8Ž‘,A’1Hdii‰µ,ËbddDÖ¬­­ÑÜÿ¹¹9"<þ……‡ð3÷««ž”2kµlI%`#Ór£±fÐ`ç‘J¥h®Ö9!‘3gΔ(y¡ýY‚îÊ@½½½¸páÍ&$ Fwvvh]G<G?5Çáüùó²ÄÐÐp! JÈ£«³³bï-}Î F+¢ 8BBfÐË Ë²ØYñoP¨Fþìës$)™"[ŽHÂé©)8œNl†‚†Bèhï ÍA8ŽC{{:::àõúê* ,!›å`·Û1::Jw½F ªzB€äX €iz6› }}}† ÞétÒôàááaZ7@ 6é@nŸ>}š6!™„­ú[ÊË‚…¢ßžËÜ Êk]Z",6&Õ– xÄ]q@¼ÑéŠ@bˆ Úò9ŽƒZ­‚N§ÃÖÖ&FE‰¬™™;xå• ln† ÄpÕÕŒŒŽáÚµ«¸råwÀqæfgÁq¼^<ÚÛۋш:¨Þ”L¬DÁà‰-Ä‘ {•/Tžç‘L&,¡££c¿ã²ÁPú@n}¡Pˆ")¤Ñ©Gø¹ßL ¿˜çïä –­¡’”K«Ö 鸺'²%q€B²‰|ãÈÒŒàðÎìv;T*3334" Õjáv{ Ó±EæßAËtM&3¢Ñ"…BEwwL&zzz`*Öú3"¢©¨TúBþ`p‚¼úêçJÊ€Ëßcy9½Þ—Ë…ÉÉIh4ìî·^¯/µ}5¦1èõèììDKK nß¾M»û455Ñž‡1õäμµ^#Õ÷Q-ˆŽ“0 d‚Ô ÜýO„—.]ª? P‘²¿xÁçó!N#•JÂd2¡¹¹­­mÐét0›M0™ÌØÜܤù÷,Ë¢««^¯§Pàì¹sGy°jD” E(¤™h €ßïG"‘ØO>*;<Ï#ŸÏãîÝ»H&“ØØXÇ—¾ôvwcðx<ðû;‘N§ÐÔÔD³) ¨Ašñ!F£Édétfsá|0 ÇCa~8®(¦9Œq¨‡Œ½ÿ>G‰{V’é'ÜGšudmÉ?ŽHàD!€ÝÝ]Y .O•Ý^¯Z­>_!ïÜápC€¥µv»n·»äB3raÀ:"ËËË…‚X^^†×ëE8¼ƒŽ1ôW02~œ9óâñÝ C—L&ñèÑ#455Ád2¢©ÉE•ŽÃb±ˆ"yð|¼& >ª–XäãããØÙÙ¡H+‘H Ãl6ãÕW_ů~õ+üþïÿ>Þ{ï=¼öÚk%†Jªä¶ƒ°´´„l6 †)4m™žžÆç?ÿyÚAøÔ©^8h4j †ý^‰%Áþ2c ©ÔþÐBô•ñü‘‚޼A¶@Œ[ÛÚ V© K¯“ek%µÔ !ÇÆÆáõú Óí——û¸f³¥Øù'|^(CCƒÅRàý Õj-q¤æ –—«æÄD½úIÃL«Õ F•J®Ø)™ŒÕ&y‰Dï½÷íl6›éÿäœýüç?§“~âªÈòóL"Ùl–ö $Ñ’­Iâÿ‰DYŽƒÝfÃÙ³çdg9ef¯Ü•$ÇÄ÷å§ð”\qIy¥g*Ü‚ß\fbpÝ`RŠ ƒÕ²ˆD"àxÀq‡h ½Zz°xq-/¯ ‘ˆ#ŽÀd2–„¦êñUKü`Q=Aµ¦ ÕÞ‡eY´··ÓQm_ùÊW:6“þ‡wïÞ…ÙlÆðð0Þÿýân}ŠLcxãÆ üéŸþ)®]»¿ß—ËUuˆÇãp¹\èììÄÒÒÎ]®7Þx£ÉãÁƒûp»ÝÅ®ÁsÐÔ!T++„{P8€§Ìòäu:W¯^¥ÇÄYgf‹‰D²k_ÙУtD"0™LX]]˲xôh†þX–…ÇãÅ£°Ú‚Òôôœª{¨(‘ÕÕ‚€ .Àh4V„6¨]T­á¦TÇ_ñÍ¡¡¡bmC˜º ‰D>Ä›o¾Ik vvvJ\„ ÌÌÌÐ’` ¡GʃËëòÉ÷êé9…\.‡¦æføý~ìîÆE€Py‰EBšŽv=‡tá#isÒ¤.”T=M±q%è$SIè‹ð2gðèêê¢vssn·››¡"ÜM¢½½ÓÓÓðx<ày‘••ŒŽŽÁá`©oÞ^Ü+#R„*Q@{{;2™l±? P§!+ƒþ„,«(”Š˜Ü¼y}}}’¡»z|x­V ¯×K‹uxž/)¯%¥Ñ$Cpxx‰D¢HÀšñàÁpGÑE=¿•À7“Ɉ\NÆ*K “r•(À3FµŒÂÈÈîܹӸgˆÔ/J!™(Ì䛹3ææflooƒç÷àp8FÐÕÕ…_ýê=¸Ý$“I¬®® ‰‚ç9¸Ý˜Í&x<§'QÊ0`]^…Å:‹‡ !É@`/¾ø"ŒFcEª¯üí*'¡£ÂgŸÕÌÌÆãXYY©0zP–_«ÕÒHÔnI‰6cbWê}å~« T7äõ³¥î(€R tÄ„T’ÆRQ€„Äûl‰:†‚AD"aFð­©AûÍ^äà¿P£ö¿\ôz=’ª €#ŒÄi§¦¦011QR!¨Ó±rZ"±W ‹Ež­¯'/ ZŒ“¯¬®ÝŽΟ?¡Áý‚"º âóꃹB ’µÌ(»Z€Àä‹/B£Ñ`ooñx*• z½¾2ƒAØívƒA,.."“ÉÐ&"‡£„LÍd2xï½÷ðÅ/~ñPh¡–Ï_¹Ôé«¥àˆ‹8†Ë²º¥7(‹‹Yùêm¼ˆp\'ày‘H<ÏA«eÚ Û†µcnvƒƒp:’\@ÇAv·’ºÍ0ûë|_YäÉÐj<ÀæÜº.\(ñ“F#Ôj5E.z½ƒƒƒÐëõˆF£˜…ÏçÃìì,u >þøc|ûÛßF&“ÁÆÆmâñƒü‡>ŸCCC0 Ū>JÄ`0ДßzÏ…”ë#•¼¾¾.Yò«pG ŒŽŽâƒ>¨ÿ" €TR>!yžC")ŽÓâ±±±ŽT*‰ááº+“Ñ<σçypWÌ! a``sss0›Mp8p:hkï@2‘À•+¿‡ÓYWD@ üÛ¿ýKKK¸råwJ&ô’s"î\í–÷įV¼%J’Ëðx<%3õ‘ÉdpæÌÌÎÎÂápÐÝtii ØØØÀÐÐu%ˆÒ§Ói¼ûî»ÆÝ»wñÕ¯~wïÞE$AOOΞ=[wE PY —MJŽËuRjž¡L±l6+y¥ÉÁÊ~0ó÷çæÀ€Á;Ó0™L`Y1<|Ÿ|rn·››!D£Q´¶¶ammn·»XèDw·&“¯Àáp–ào§h窽ßަÓD£èt:Øl6,--allœFÄNE ìÈÒ¨^¬CaöáøêjCC1<U2Œ¼>NSס«« /¾ø""‘‚Á Ed—ïîîÆøCªøµPX Èr£ôIâ(@µsg·ÛpT¥²ýWYÒ}H9ðââ"º»{°‹A«eáóµ@§+4ÿï´$ù‡9¸ÝîŠéA…Ô¨t;€ý×AWWnßþ ^¯ét —/¿J›”æú×'Uƒþ@˜“ÕÕU8¨ÕêÒ)¼ °ô$‘èâÅ‹” †€Tó1 C¹‚h4Š D"ÊTçjs#BÙî/¥@j*éb¤¸Gк/næˆ*= .½ü àÅ—.í7eöÀ0<|ºdF z×d¸e°}0¤;_0D&“†ÝîÀ‹/¾ˆh4‚ÙÙ‚ŸìóùŠÍ>ÇëŠÔ®Ž®o6Œ `kk ü1 FGGÑÒÒ‚h4ŠL&¯×{ ²^¢ür¯±Ûíp8:|P¢úR¢‰?âzñT z+•b g,ÄœœÄÛo¿]ò˜Z­.­÷…­V+ .ï’P Swþ~­¼ÀÒÒ"66‚Èd3`ŠJQ¿Uhâp8`·;2>«ŒÆªcâc2AH&«ƒÍû÷ñÜ—¿Œ¹¹9tttàg?ûÞzë-,//-Ó½|ùrMÆþI䔢š*ΞPy{/·'{ýH(Y! "(¿P---´G!¾_Æ 5"Œ†`êZ°å’I§‘Éfá°Û17; ½Á€ÙÙ9\¼xv‡^¯â¤á®®®†wúZí«ÊÏ•¶»™;wªçÑÛÛ[EÎãúõë¸pá®]»†h4Šññq|ÿû߇^¯Ç׿þuÌÎÎ"‹áÂ… OÅ Èžƒ*!@±q#§m!e¨õ*öãb1¼Ÿ4\½—¤²g2Èd2…‚tÊ­Íî(–³.Ò÷ôz}e“ôhq"7oÞËêJæ"ÔGÊCa9` D¡P˜0¤V«qîÜ9\¸p*• ßüæ7qóæMúýoܸh4Ztg2øÛ¿ý[œ9s†"¯×+©Ä¿úÕ¯ðâ‹/JfyôèÐ LÕ81ã_ù›… +·½½- D¦‚ްƒjŽ O3Æ>bw7†ŽŽÎŠÁ™LÙlÑh ~¿?ùÉÿ»ÝŽL&»Ý½^wÞy^¯· ü6;²™>00XP†)Q~ùˆ€Ø¸dKÒ‘«¹Uýÿx€jÊö /€a à…^@ @gg'¼^/¾ÿýïS†ÿöíÛðù|ƒø“?ùܾ}Ñh‘Hƒÿò/ÿB €Ø=Bwww!@9W@œ\_ÈT1G\HKîrÙ-m%Ö2¢lÙl<Ïc}m 6»·?û z½ ÃÀf·ƒN›ÍŽååb±üþNÆÀÀ .¿ú*dgd™A"BÃ%­rþ¿ Ô¨ÅL~ò ü½½tw®{ó˜PÍ” þ¡Æw–ê,Mk&¡d ©‚ž[ µ¢äâJ ·¤»ÃT°Ã%aÀ:F}“bùå/ß)î$¥F£Èf Ð>âþܾõGŒ .b`` âõåŸw¸/W.KŽkŠ®K­’à?ÿ9Ô_ù ®_¿ŽŽŽ €ã8 çŸUi$  ¨¸/Ô ‹Eï+e”rà#$„µ­f è_©îÀÊÊ ü~?b±îÎÌÀï÷Ãf³ÁF”(} ܇ßïÇôô4ôz= ¾õÖÛÈd2ðx¼øä“›ðû;ÑÙé‡^o¨)M\¾\GaP¶û.–xBP5wÀjµâÞ½{t±g³Yܺu ¯¼ò ®_¿ǃL&C»=½& 2(Gî\•×?Ô0¬UgK(àè ŽãèsjF*GàæÍ°Ymˆ'âØÞÚ½{w±¹¹‰‘ÑQ–°ÛlˆÝ™†ÇãÅôô¾øÅ·(áøàÁ}ètzºƒÛlvLMMá•W&`·Ûñ /`y9¿¿³úŽQ£ƒ¸Ê-‹– šê:K_e £À¥K—Ðtú4‰ÖÖÖ`³Ù ×멟\RüøÇ?PHœ!è BxhANÑåÒ€ÅÇÅbÊÌ’cµ €R|„D«Õ–€ê{Ä>ôßÞÚ†Íjý»w1|ú4ì6;l6;FFF‘Ífñ¿þŸÀf³#“Ébyyï¾ûKœ?ÿ<úûû¡×òÄk@¼ ˆòW,úª C¥¿ùòò®^½†?üÃ?¬ÓxÊ“€*³¹æ”`B‡Z,8…LFµZ—_~:z½±XŒ–ò…ÐÙµkרQ$†`||œÆ÷' iØ*VñXybPI!Z­V¢Ç ‚»ÝŽ­­-zL ÐétH$’’)Á/¿ò †ÁŸœþÓŠj@½^K/¿\0 v;^¿rÙLz½¡X÷ÔÓÁç }3Ù,‚Á dÒiôõ ]‚OzX^@°¢z¡ ‚Äïk³ÙÀ0 žþyzMúûûi 4!aív;½Fñoÿöo!.B‚ Ð Â>úL1YJ¯×ÓäŸï}ï{øÆ7¾A«å0NeN€PÓ©ç1 ίP @b·Û=xÑf³!‹I^€’¾€â2Þ2.Àj±T­-éñ_X„ ö52CEcÑ(~ñï¿€Ïëƒ øÑ~„þþ\¹ríííÈç«G*áqõYÕx€­b†^- ù¤§4E(Th ‹Å`³ÙF±´´D{’žsÅŒC’gΜÁ½{÷Šó¢%ÍD*Ρ ‰a äõ±XL² Xùy:H3zº3)à1 ‘‘‘ªmÁäÞ[èþÄ :|óƒ–K±þ7>þ^Ÿ™L™téLG__±€EyHPÎßoÈì™SSS¸"Ã7T3râ¤Òä[ßúMÖºzõ*‚Á .^¼ˆ .@§ÓáâÅ‹´N`ccƒ¦ ûÛß–ääÉ>ñìƒêÃRĨQê<ŽŽ*.ÀQ2¡¶n Rt²FjT˶î: yð™LÈd³ˆE£˜œ¼ =:;»ðÇüǃ#èïë‡ Èå ã¾¥}|©Hš ¨ú Œr nܸsçÎÁh4(%˜Têõ”aŒãûµ ÃàÍ7ßÚt„t®Å”+º  ÊN”ÜX°½½½¯G•J…\.§€§%bWbrrããã’ƒ0ä•»²<¸C/÷°”¢ÇbQƒ!„BÁâ8p/þçÿüG,ÅÍ›7 …4ƒøüçß,„ ù„¥ZÈ’aÉ_-•/Ávw#[,µ•3hnnÆÇ •J…×_ßûÞ÷ðð%îÜAH½Šü‡²®@$=¸‚PêD "‹ Ty¸£TRÔ1HAGØ(_ÜòóÜÉ0 ¤A(¾5éÖ£ÓªŽ÷ŠFcÈf3…BEf<Šû÷ïد'Ïd2…‚t  M>ýþbG#†OÔ]·üóȯ]^@§cÑÔÔ\¢ôÄÆR\‹ P™L5y€•[·ðÊù/xôèâñ8–——Ñ×ׇëׯӶ`~¿v»6› Á`°d–à“î T­Ï\bPáÜp1'º6V”ÁÉ IDAT«jµçÏŸœ?»»»…Bô@éP(„wÞycccˆÅb´\º€~ a?±B§ÓiÙƒ“““8sæL5#ÓD& qĈøðJ1Ð1—^z‰F¤.X (ƒû[[[±³³«Õ ›ÕŠö?¶¶¶0:2¦8ÈsæÎèt$éEü~Dc1ŒŽŽÒéÀƸtÔW½Wü5§&'‘Édðïÿþ tvvÐá÷CDz8þyØl¶ŠPàÝ»wát: Óé±»C*•**éóØÝÝ¥mÍ«Åʶhª‰Õj…ÍfCGG†Á—¾ô%„B!Ü¿Ÿ’|Á`×®]ƒ^¯Ço¼ÿøÇ˜˜(dK x½^ƒA ÁÉ´!2cpccƒ€ªîƒÌ)n ‘HÈÎ?bbBAÏ4beÉb/)>@€FTî×ÝÝžS§ R]¤ @…nÁÜn^ºdƒ^§Õ—^~¹ð=m¶CEÄ„¡^¯˜ý£ññ3(©nìðû!Ûƒ‹}üÅÅGH¥þøctuuapp°fJ±4C* ZW Âò¯¬¬ ­­­!Dª13¶W¯^­Ïj‹Ë~«„ Ýal5{ÔŽH¡€©©ID£10  ÓèÚµ«øßÿëÿÀxq×ËçóòyäÎØÞÞB>Ÿ‡F£A2™„ÇãÅàà Ôj5b±Uš\.W3þ_Øœ›ÃææfÉÔžzŒ8kÏï÷Ãï÷#›Í9¯"‹! annsss¸|ù2:;;100€X,FLj‘æ(µH`ñ5ž$ ƒú‰DBáŽxÒVVL¼Õ¬(ìæi„B›èìôÙÿb±(</%|ík_G4+’hKPˆd2ôúª1¿­­-$“Ih4´µµahh¸˜Z›§Í4åÎi#ÍA‰ß¹sÁ`­­­àyZ­¶aÆžøÚ^¯^¯ýýý˜˜˜(‰õ“¢ÎÎND£QÚIÊÐÔÓ­j” Î(ÀIB'6 PNV¶uèªé œÍf¡bT0 ;Î;wÐÑÑl6 ·ÇS‚ˆ{a³Û)ùµ¼¼ŒÑÑQ„B!üä'?¡õÑhýýõk×áõzpíÚUtvvbll¬Ø+À'(7FÅE¬ÕjÑÑѵZ«ÕR&ß4Dj,P;XÀétbll @ét*• v»²çÉd&“éÀe½âá¢âï+•†K^Ïq\Å5F£°X¬ày*•Zšü«bc±-RŠŽ('tš››1?? ²eØ>PPúOo}‚ñ3Ïa}} ³÷îáÔ©^0*+Ë+˜™¹·ÛƒÞlÙL6»?ýéOÑ×ׇååúúúqçÎ4Í^£dX!ÞŽ±±QØlv|ó›ßl<" žè[<F£MMME¥—¶ººŠL&]R6],\%в¤R)¤R)°,‹µµ5ܺu W®\Á­[·pùòå ¶þq7áy,ËB:y¸©¹µ†îàÉdMMM¥}…Jw ½½¾¯[Ô!Y®X½Ü•bž¢\ºt ù—)û8‰¨ÕjQ^xéÛÞÚFWwÞý_R¦Ÿøªn6ká~ï½÷`³Û°‹áÒ¥—Ñ××Gw~›Ý†Þ¾>x= l6ìv›¨ÀÁ# ©Î‰D‚ `uu‚ ®vïú‚¹˜¦‰@å$ Öã©«)Hlm ÎŽ\¾|jµ»»»tDz2™¤L4ÅÌÌ X–…Éd‚V«•lÙ~ƒ@ÂŒ,Ë¢½½÷îÝ£îÒÊÊ mßµ¶¶Þ0ü‡ÅdéI‹kP ¤R©Š’QÉ^…¡Ów¦ðü `ÐëáñxÁ¨¨‹]QTÂ/|á X^Y†^WÈô;WŒ…“JÁŽIóPÈœF˃ô£¡»» Ç!‰€ã8øZZhëjñNÏqY˜Í¨ÕêbÑ€¾¾~ÄãqÉÔV­hç“ã ¶¾gGGE…\ss3†Áùóç©F)GÀó<½mmm’ש^#H$L&át:ÑÓÓǻݎ••…îÐ.\(!ðÊ£öÛ}?α`Š8€”ûp•t:M/Úµkת3¼ea@N‡çŸ¿PPz†TO@ò¼ÞÞ¾ ¯„ìÒ㽉pG•¦»§îf7VWWðÒ¥KP«5t:E• ÛEKK ‰8ÚÚÚKT¹ÞñàÇjm„ x饗('J¥¨òonnR´°¶¶†þþ~hµZ8˜ÍfÚÖ(Œ‹D"hoo§ ‚Žã0889 Ç¡xúúúaµYéù0 Èåò²´o¶h677eÉR¹Ð²bNJt ˆäFƒÉE P£–¿zÕ`©¢øÌó<=ZÏóxýõ+øÍo~ŽãÀ²,.¾ø"òù<š››K”^,ƒ.— ‡ƒ’XƒƒÃ0›MÅ0`}»› pûöm8‡†L&+2ø¤n›L&˜L&ê[÷õõ!‰Ðßl·Û±¸¸ˆH$‚ÍÍM¼þúëX]]…V«¥Hezz+++Ô_ûíâëïv»‘ÏçËåD R¥­ÀÔ.#Å@å¹'¡àÄG¤Zƒ×m d]„}Eçx{<c±€†©b’ÉD1 H¥’H&SˆF#àyGañkµ,67CEXìÏóÔÏw8`Y¶—åg}>ùäœ;w½½}Å|ÿ<” ÉöרoHȽ{÷`2™ÐÚÚJ#,õúðZ­n· ÃàsŸûu#¶¶¶àp8H$ Õjqÿþ}œ={f³sssò¾ßï‡É4mqq‹G}777?öˆPÈHL&“Ðh5ˆÅ¢Ðjµ°Ùl0 °Y­ÈB8¼»ÝA(ä‚Pèuߥƭޒ`r¼\…{zzh:0 ³’hN @  h ··:®¾Æ w‹÷¾¾>ÌÌÌ@ÐärA£Ñ€ã 5Œ#`7µ‹ÅÐ"ló¿ÕbÅÙ±ç‘ÈÆÁóòù<ÒÙ4xž+|ްßRP†´1¤X4jF ³ÑƒÞN«Þ‡Á[ÓŸ`ræ3„67Žî($`-!#¢Ÿ–ÊéÑ1‹Å FÅT(#¡­6»½¾Â #å·9ŽC*•B$Ïsôööatt¬$ H*Ãáÿ¿½7 ŽãJÏD¿³dVU–±¸“’L‰­…jdõ´[ê¾áG{Þ1íyœ˜ˆ‰™?ømæa"ü6óêð»_|·™;÷aîö´|mkéM”(’EH P –\Î9÷á,y2QU(®©:TªµdUeåÿýß¿?À­[ËØÚúÞÿ\¿~œs4z¦Á ^÷9ûÎØÌJ? MSœ>}NÇ…ünܸ0 ÑljÐ:{ö,Â0ÜWÝ7*Þ»wëëë¦[û$ìñ£(Â…  „ÄÒÒ -Ô è$mÜZ¿‰íÎ&Þ}óx÷òÔd"A¯Û…0쑲ÏÙg;-Ùö>ÎÔ''195…@…¸uõ&þÿýÅ—×®"Š"´öZÀ$vÇðÈBü°¡—Q»ÿô•ÅÇ6T´ÙÜvfË͛ߠ^¯ãܹsXYYq´aá(êõ:Þ|ó­a@(…[ßÜBp,--éšs¼ôÒDÑfffpýúµ¡çiX"Ðí?î{ž}á ‚/½ô’{ÌæX–Ðét°ººŠëׯcii a¨¨Öñçkkk išº‚-C^__/D¤RxÿƒP«V½s“FÆ@$šíhö¶ÐU]F‘B «zH³J B‹ï~?b<þÄxÿ)„¨²¨ÄÝvàÎÝ[Øëìbª1­ßS¥‡RÆ^ØÉ@¶ó¬Íòò¸1†È¹‚qÄ@ ZŠÛh4Ðétö÷”W i–! lll`ÞLßm5›X__G½>4Õ >ׯ_C½^G»ÝÆÂ‚Km·ÛH’GE’$˜™™ÁÑ£G =׊Œµjç·”—/¿íB‚ƒB¥9í~–eØÙÙ”ºÒRz e¢È… -ø‚»±±õõuÀD’$1“¸ví&&&Üã–-ÎÌÌòöíy¨×륲g»/!‘¨½´‹vÚF"c„´‚L ¤H‘¨R P¥…œêÑÿ‘œPB¡(© ©HÐîíakg »½]$"…ò y1cU£Ä¾÷½ïá³Ï>ë 6 SS“Øk·Øà Yš!¬„ØÜÜD¥‚‚Í›ƒAbºÑÀÕ«_`~~ ÖëuDõºkàññGáÍ7ßÄ×qëÖ-¬®®8:Úét ­ociéêõº 76a!$¶¯&Àj~ãò#Ÿþ9Þxã Ì™E¥Z-\xåˆ@Ù 8  ÆÇòàÁ¬­­¡^¯ãôéÓņ·ž|;Dtii ®È¨i€ÒÆü···qéÒ%\¹rÅ1Œ¾†! NA!•):²‡X¦ˆeŠ $‘PTBR Åtî„00‚¯ó%ˆ;!:ÏB'‰L ÍR´Óv{]ìõöŠôÐJÚ Çl$ MÓB$ÀÚ§÷ïß÷¨©¥ãÅη–o! CLOOã7¿ý5N<…›7¿ÆÜܼ»@_ãuœ>}A ,//£Ói#Šêhµšxï½÷°±±Žv§ƒ(ª›‹üææ1Ó˜A„Ãa8jYŒô ö€7ojQ„¥¥%í TrdSi”D @Í4É´ùý_}õ¦§§ )¼£Øðe“Á² zÍfÓe@ž5£Ë~ò“ŸÐÉ@~TA ú©T)-ˆ’©RdD@q©½ü\B Ý,U "‰Þ”Ù¨¹õ~ iX•’D¥HE†nC @”‡“ŽàÙ0¿ä·¿ý-~ô£(8ö¦×í"îõ07;‡é©)ÌÎÍé6×DêQ¢‡€z6®…§Ù"jQ?ýéOÕ't‘ŒÿóZ‚ä;ñ#†‡Ië¨à0Œl:oƒÁúú}¬¬¬ ^¯#IÌÏ/ Ñh`qqÑ9…”…¾º¶ŠÅãÚ9·±¹%Nœ8ÕÕUr슱Öçu¶ ¸mL²¹¹‰4M±¶¶ærìàMËΜ9㜧:M› MS=Ñõ븱±‰#³Gòï@”þRÒ£„FÐï|ØÏ@¬øûk_¬t  ÁCcxfL OóÕ=êýY~T ¬„Pøé3:Ä'¶Ój!ªk§_=ªccsi£å<¡ïtÚˆêîXÍímaˆÌ4Èh·ÛNà··›º¸( ‘$ ŽºœøFC‡£(2qý—ö}ú{÷îarb÷îÝÃÎN _^½Š·ßþ>šÛÛ`ŒavöŽ;†V«YH™¶’Q¦±!NDû;ÌÍÍâ¢N·oßF’$Î)û‹_üÂ…·?gffFn0zíÚ5¼ûî»ØÏž=‹8ŽñÞ{ï¡Z­buuUGü3b®zGÿ)5±}Ã(3¿=Ña­¶WÊ8…vêÙ$,¥œ#К‡Ýþ!€_#n×­[·\;'Û¶Ë–çí>úëñn§^¯§ãöYŠÆÙuþÂ|úé'X\\D»Ó1žìÛËËx÷Þ1v0Ðj¶X;9ISœ9sô^{í‚@kÅ·Þº ëF°Ž®‰‰‰B¯zËntø)÷òw;|só9rœ3Tk5œ>}œëŸ9oÒ_óÛç⸻¼ŒÈPzÆØ”=Š"×ÀÃ.ÍÏÏ£Ýncmm ívŸþ9\*±mÒh4$ >úè#yh·Û¸|ù²K²ï(cBàøñãBbbb‰õOMý- TSë§”B*êz šþ+hêilASêH€’p®@¢ h Æ àÙ0Üù³ãî»uëÖw‘ÂÛCìîî莾o¼O>ùXÇý§§ÍS ¾þú+œ¿pÁ ä¬GâÆ]ýBç|õÕ ,..¹Pdš&X\ZruAâý>ÀÂüB) X,FƒÛí6šÍ&ÖÖVp¼ôòË.F*).¼ô²I–¯FJéH½àÊÿüŸ¨œ>K—.!Ë2,..Žœã£þ€®hµZh6›¨×ëØØØ@³ÙtÙ‚6ñÇf ®®®âÇ?þñyåá.‘@ö§&á‡JA…"RÏZ$Þ4a €éù‹DÈ LXÀ–X{ÑbKHÆðí¨±¥òÔS(`jjÚŸ“®zþüÀ÷^=gxDÅÅÅãØØÜDEøþ÷uŸÀ¨^ß÷¼‚„?dÐÿnËËËHÓ­V 'OžÄÌ‘Ùþ!Õ<øA©Àƒî›œœ„29[[[ØÙÙqåØâÔÓSóZ‚,ËÐn·uXÕT¾üò˘˜˜À¥K—ø½ËÝò}À¡§„€r * ¨Ñô’nÈL>…$¹ðK©KHr@鈛Ï^€~]ßÇ A4õ_X8Š3&ñä7Þ4š‚™´MØÇ­¯ 'þN7f<=Ž|ÿý݇> loo¹ÇWVî`~~×®]Gp´Û|ðÁÝÔÙ§ñeh”R ê@aPÞE³¸¸ˆ3ヒ$IÐh4pïÞ=lnn:í oÀ¨!@[¸dAa¡R·ù"F+ûQJ)1UŸ,÷ò©Y™¢Jƒ€4‹¤ú> H©“¬ð;G Uy`œ0Ú ÃðÀÑUvíABi§Òz†N%çé5\èÝõùçW°¾~—/_ÆÊŠöÜë&#ZÛ´ZMœ?µZÔw&^ßL\»ö%„}†¥LýËàU«Õ\Úr’$øúë¯qþüyܾ}çÏŸG†ˆ¢h`Àã†û5KÉoÕ~´ €@;‰Þ”BižñÀ'ÆìWLPTj¢ Lâ¬@åïCû“±1<‚Z è·Ç. òôôô¾Ú€±øÓƒÌ®ÝG z{Íæ6¶··ÑhÌ8MzöìY7àszzssó˜ÍkJ«Ûí¢ZÉçèõz=$iŠ^¯çìõò¹µ'`k­Øo߆ÿì°Ï(Šð¥IŠ¢ÈElo€²gY6Ôûßo­®®biiÉ…G†ûŒ_~ù%c¨ÕjhÌÌäÞÏΣÖ0¶¿ëý`¨>´9 Œï@)L›Šê¶`Ê8þ'4 ï5€g³|;Ôz§ý¦ 6 0559< xl+(ì´v˜\þVA ‹‡Ž/GcºáX@–¦€q~YÐlµtH°ÙD}¢Ž[ßÜBÝÙªÀwÞyA‚ì^k»ÏÏÏ_7åh‚1Æ8>ùøcÌÏ/`º1½Ý]t»]0Æ0Ýh Ûé`gg§Ðvk×4Ò&øvguµ¯†ö'EQ„V«å’ƒÂ0ħŸ~Š‹/¢Õj™f*z`Èúú:¾úê+¼úê«Îæ·éÄVVV\¥^¯ã—¿ü%~ö³ŸáW¿úP¯×177‡8Žõ|‡ßýœs\~ûíü3R•;@©þ3!>¸ÄE¢rs@ ”Bß`´‡GÿÕØxö«Ûí:jêg§õKz!û(³B·Û5šWaåÎ ¢za8 wîüyܾ½ìoss§OŸF„øÝï~‡Ó§t…ÜÕ«WÍíX\\* Ç8sæ >þø#ÌÏë>ëh4xíµKHÓ|ÖݨÎÁîÝ»N§ÅÅ%pΑf)z]Ízê¨GuLLLâÖ­oö9]— ³u [™CLµÙÙYoZ‘þ=6sÔvúä“O =ÓÓÓ‚kkk.Ü·±±3gθólÛ¦Û6ã~»q@‡^¥”xå÷~ç΃”º§­ªÙ 2a@¢tº.eTûlF ÓK, 4ZDû”2>ª#”ÀQ / 0Nz:æÀ¨¦@9Éå@ÿÄÝ?þø#¼ÿþøâ‹Ï±³£[¹a€0p÷î]ÌÎÍ9‡Wš¦8áÓ LOO#Š"ܽ»ffçµÝÅ«|óóó¨›F¢ï¿ÿ‚ @cf¯€½èt:n¶=cõ|v€èv;+H©\Ã}‚\Jj8ùóŸÿ÷hó{7 Í2ìîî¢R©8 FÙkµN:嵿ççnnnâþàÜï†!666 `¹ººêÀâÍ7ßÄÆÆΞ= ¥Þyç÷þW®\qÍAOž<!¤y‚ ¢”¦§Ïœæ§Ð´ßit-ü  ’¢ð«<•ø°;-<»Á eÐî½½ÝLNNáÁƒ-Ôj‚ Äñã‹èv;¨E.]zAèl7ûz’éøâ"æL`§ÓÁt£Ÿüäæ èßGPíóèß¹sgÏžÓá9¥ ¥(|Ójµê É(šNK{B¨=Šw~þsô~ö3\ùÿÍ7 Ÿì³Ï>É' „ÀÉ“'EÑÈ6üôô´ó×\¸p¡ð™¢(ÂéÓ§è›ë`˅˃ýõꫯê´è} A°ÀL¿ _ø)Ís¤vH8_Q}«ýŠÈ\øsMƲමEžžÞÏ úxí&'§ðÖ[oÒ"€R IDATй¹9£%˜¾`KaÀAkï—gö=”£°t—mn¹½½…$IÇ 8çX^¾e†ŒÙÿ½b¶½Oów¼ý¯þ•¶ÅÇ?ÿ/ÿ¿üwÿÎÀ­+WðÆþ!¢(Âõë×ÑjµðÊ+¯`gg'Ož|ìÉ¿þóêõ:Þ{qÂjØ÷7瓘ÂN¿ˆ€m÷EµàÛÖ€:¬< A@’<  œ1ƒ=Û555åö)¥û€Ö^­V=w)ÌP°_è‡Iõ#•XÀ‡~ˆwÞy¿þõ¯´b&i@k¸f¡'Ožr¡®Í!sýv?ÿ\›êçÏãÜOêžLNâ÷ÿãÄ/þí¿E²»‹Jšâ­·Þç„7¬ã׿þ5Nž<‰N§ãš…>nÛïQÃÙî·& (¹à«2•/€€nõ%!M݈7—è9 ÿÏ5 b~À ¹°¡ª3gÎ Š"ôºÝ¾R;( ØOZGÍ xX°±±îªö‚ D£1ƒ0 \ã‘õõû8wî|ߺ€a‹qމ‰ 9rQrù%€ïÿë½ï|7^~?üÏÿÿ÷¿ù7…û;Vðü?xð×®]Ã¥K—E‘ó“äN͇„‡a }ÁÍß÷@38ÍoSw­Í¯|VAŠ cZó+PkXͯàÆž‡õÂ1ûÃ÷z½¾ÃAü ƒ1Ö/ `ß~ÿB…n§‹NWkºi @„ØÜÜÀ©ÓgÐj6±¸¸ˆN»§+…NW7ÅL"\[[ÅÂünܸ®' ™.6üÇ?!0áµ¼*M)…©©©B?ŒùGQ„£G9Ç›-Š××Ñpþ_ü ,¼þz_ͺðöÛøáúOøÝý¯}…ðìÙ³˜ššBš¦øúë¯]|?Š"g÷[fð°Þß_^^F»ÝÆk¯½†o¾ùƵ ó¿øÍ›_£Z­a~~Ι8.ÐÅèÆ÷=öDkzâ‡ó,ÀÓôDê”å“ÿ’p ÏFàËë¡2 ÷Q…n·gŠ|”K4!ØÜ|€(Š05=n§ƒ;wn;sé8ôæÆ&îÞ]ÃÜܼ©ü|úé'8á%´ZMlnlèJ¸Ni’º×w̼À—^~YÔnw* 8â×DÜëáÁƒÍ‚F–Rbwcta¯þË9ô\_øÙÏ hÿA7¶2ïÒ¥K& Òq!À©©)üÓ?ýSÁùg!û·‹?ú£?Âòò2]Ž@šÍ&®_¿Žf³‰……|þùçX]]Å™3gÇ1¦¦¦$ >ÿüsœ9{óósEÚEË´¾ÿ¦l,ÐØüðH~þOî~U6ÆyO_ø !}§Ý>j@àÊ•Ïpñâ«ØÞÚÂîî.VVVðàÁ&Î;;wnc¶;‡¨azZû¦¦§‘¥)Ž×€×õïë¯nmXGÕ!êõH·# ;d„ÌÏÖAÙKÿ‡â8ÆÚÚ*(¥ŽúÛh@À{ÿþß#0 :úG»ÿêŸüÉÀ^€Î˜u¿ SFQ„(а¹¹‰«W¯"MSLOO»A"¶éêÚÚšk*rúôi„aˆÓ§O»#ï¿ÿ>Úí6fffÐh4\¶äææ&VM’Rˆ Ù ÊEt¬žÓu 19ü^2Ê}Ê´÷È @tRýVb OCøNºí¹ó¯¿»ÈZóµZ »;;¨Õj®O?ðŠÑXv0 a@}C„Õþð¯¿þº‹AaÀr>ûÀqbÊM¼ÝÊ#….Àûœ|»;X¿Œ1×æÚ™I7o¢ñÚk˜}íµÇúQö(ŠðÊ+¯8@hµZèt:hµZ®«ÏåË—AÁ… Ðl6Ýd¡µµ5—dÙAΩûƒüÀ½Ïêê*æææÜH°3gÎ@éÌ6F8§”–ÿ(|¨‚¸«}š_¹V ~-@E¥ ©ÄCÊ)¤<œrô˜£€ï°¦7/½vÉ䆛RQÊ<™%_À°ˆ€¥»SÓý?RÁâêÇ|ú­uìîî"öõRJ I0gjû}f0Œ<¬Ýîï[ÀñãÇC(?f?_EÎ3===p¼ýöÛ.`qiÉJ#DkaF„¬‚=pJÝð÷kú÷kýñWPÄì+Ók`Œ¢U ÓÕjF™’©<”@zØû ¡÷…ßþðï¾û®»ßvþù»¿û;÷zÛ „3V´ÿÕ(t_§Aßת½sê€p]Ùù0þ€^¯‹åå[ØÛÛsÃ4ìmµZ5³ ô}³.€1†8Žóš#‚À¨ aÐþ0ÇàéÓ§ñÆoàâÅ‹xï½÷0???øX¥ë¸¡˜®70¥$*Œ!džìCŠm=•WâëQ|ó·íä€AæÅ@ŒQð…< €LíQJÛcð”€B)åœ~BävVš¦ûÚUùKT·šÅÓµÊz{ó!‘º},Àí÷éúùäº ,hB¬¯ßG«ÕçÜ ;çÜL<α_J‰£/‚›<ý4M]CŽJ¥R8‡Ã„xPØn¯»‡N¯ƒ8‰!¥Ôù÷ö¹Þ—£„xëeXzÇ*Ÿ{BHáI©³ mXTwVȉÝn ™ÌPêPHAŒþsÕ|e{Þ¶ú2Šë b«­R„}¾isÓshÌÏ»¿³y®r$Øâ“*‘±R¦wH¹é‚òn‰ÍD´£ÉUÿqö5”P,§ ííd‚‰é MÖ{ jëþ‡÷“çú•—µ¾Õüö¢÷k’$iøéã è P üXåÁ|ÃB}Bllèù6¯žsî´¾®dnžŸ=|vBBÀC–eȲ që²âjµZmŸ¦>„X¾»Œ›k7ñ`÷’¤EF)2¥/UJ¾Ñt¹pÏsïƒC¹ëŽ#é^Z.’ =ÑÃNmsõy$. ¼Ž¾²(ä–æÛ!¬RI][à=‡HⵓÈÌÀÆÄ f£yœ8r_»ýîŽlM3Îv”Rdnœ€ð2s1÷»ÇÍVèè¦J—¬ÒæSµ¨‚êL ‹Ç–évÓîJ"’ÿÀ½ç’¨!m­Êˆÿ(ñ15*DôöûX,à!À!ü¢Y°»»‹ÍÍ ´Z;PJ"pÎðû÷ŸøÃ>­ƒ.Žc7ˆ1æarrõz=o(Zön®ÝÄêƒ=zwîoãÆò—èÄ]$YŒD%ØK»¦I§Ûhé–„“üï~Ï¡pz@MœŒ(P*0Ë0La†Î¡¢jHEª…šJH%œ [aµºx!¥âB&RD•:~ïÄk˜ª4@@ÁgðVE°ó”Ðt¯ÓVqy{qÝXD!·û™·•ïžÐKïäD¦gPà÷ο‚þÞñÇô'äê×_¦ÿýÿýúÊæÊ×Àûöz®ªË—ïø“R:­UöŒä[ð3Õ¨œá ±€G-ÞëõÐln£ÙlbggY–zÚ;/3 ~À²'!(¥HÓ”RpÎSЂ«Z0z½ž‹ï+¥@)u P©T\¸¯Ýmcmsë­{¸pî&&#dÿ2.¾ô*Î,žÁêÚ*d*«iœ,@Wx'/ŒÀ^¼Â”}ö€ßüæ7øÑ~”gŒõó¨¿î ?°1Ðc°€‡5öööÐëõÐÞÛC«¥†øZ›RêRzm|߀Õþv³Ï)3+ÜVè³,Ûªö—ÁÀ#MSç<´÷ß}p·W–±ÙÙÀíµÛ ŠSgNƒt”&¨UjHd‚T¦P œ€qªýŒé[®vFÁ¨àaŸC)8e`T#„PÝåט ŒšfhˆVÀÀq´q ÓµidJ 1„Ȥ€BeúV i÷Í` R‚J%%D¦oT§A °“n¡ÓkCJ—Ï]„È2Pô’²,uíÅõà!ÛK4§ùÄÑ~bö`˜iãÊ8P¬†Z¥ªçJUœ>vQ4ÿç—ÿÿß'Ÿ^ûú‹½fÒ”8Ž•çÊÚ¿|_¾|Ÿ|ò Z­–s þùŸÿ9N:…[·náý÷ß/Øø¼¡{ÞHÉ9PÔëvÑ‹ct:mdi†ÝÝ!°···š[÷Àjvëä+€}Oÿ}`ÏŸÎùP°—M/ß'èù I’âÁÖ&~ýŧhm€ÎQ'XTA5¨`‚ÕÁi€€s<È¿ ãàŒqÆ98ã:Žoï#zã$@€ ÁÀÁÀÀHîäTDA@ 3ÿ$Q`”¢Ô@Éi–z/)Qø[Jáî“BjŸ :ú/ª8cê Ó¨f5L‰Žã¨™;`Ïé7ä| ŒgÔ{¤ð·n8dš•B8á+!‚ Do3ÆkËøì£Ïpã›ë2I{BB +Ïi`P¼ß¿ÿôOÿ_|ñ>üðÃÂóþâ/þó7ƒ»wïâÞ½{˜ššÄêªÑÛ>¼Fÿ Ðî´!E†v»!â^Œ8î!ŽcÄq\°¹ýÍ:îüû¨k^Aí÷m{J©£û>0”íÿ~çÏ:î,˜Zàð¶,øý„ßÞV*„a€vwŸ]ÿ-æ»ó˜«ÍAÊ€Iê• TÃ*ja Õ Š ¯€ó @XÎp¦÷j„ Gí 3ýú<áOÍ¿ )R™¡—t‘d „H¦Ïd¦¿§ì^„A "$QBBÆ)z´ `5Ž ‚J™î7fB]15ÃÄÎ… 94òýÄxÿz13‹At$¬„àŒáêÆUÜX¾†+W‡Ö^ a-D¨RÕîäÜ÷…ª°ûõzù—‰¿ú«¿ÂÝ»wqñâE\¼xÑ%—ôz=üõ_ÿ5~þóŸïnã‘ìqÜC’$èÅ=ĽB´ÛmB°³Ó*ï !÷…Û×öe··v³m…»ßßevà{Þ(¥úÙü¾ ºoèi;@&⤇v{Y+ )UhÛ¨ˆ‚Q¡D¨5T‚œiv 5œ1pÂÀ(§ŒpǨ—„/!œ/d !3d™€È´ó.¸Ì]&Œæ·~óZ%”P ’èu:ØÌÖÑ$›yy1¬)âM"žƒùýV¸‰™$¢µ<uQÜïGܱ©é<¢”{ò[[f XH¦ˆ™Ê´ày€~L \2úgögˆãY¦Ð$IœÚëõ°½Ý£”"×äY&f 2‘i¡7 Éܿ䘀PÆq'3‰TdP½=ÄèºäÚ‡I ôœš |AÃçL€:@Š{Ïñï¼×˜ë/¬„ƒ v÷vÐM»hÇ´ã.2–!¡)0ý%ùBâk<û£ù7 „ž:uÊ¥–ök’Ä â¸§oí=ôâÒÄÈËZ¹V« ÞaÂ>ì>Ÿ¦÷€²@—…¼ììó+ƒ¥ïKñÀ°ô ¹öÓøeS Ú‹@9CœfØiwQíÕPORô:]ôhËÀ—1Ò,D/ë¢ØMCTÓjY„‰p‘ŒP“B"ó0ÆÀ$Ì9µøS#zæ»IèáÒ6s›IÈL ½Ç2iþ6 ¨L™î ¬„DÒ‹‘f±é8dZŒ{ê 45 `ó¼ŽDÈ'ÎD(26ꃈÏü!¦æ‚î¥=ìv÷°¾½½½Ì<çPÖ`e!‘RÇÁ…'´v_™™LMMáþýû˜˜œD&t¯ün¯‡$î!MÓÂ{pÆ@Lç›a´¼ÌÊPޝ—sò¯|ì²ð[åõýØ’ËçÕ†^û%`õxÿo@·猛d®’™BÚK³)IµóL1daŠ@qd*@&$*E,côDUQC5«¡è­TÊL`Òœ¡)wN»sÇ™å-Mbù– B ËD¬)`˜€ *S ɤ ¦y¨ÍU’Òf[V¬›H"MÂõÊ…Kƒ˜B% [shÿI˜ÇõüMÅ)$z‚Šq#:逨\‰4Fþ¼k{úšÏ"|99EºÂýüšÍíÂq¸6Wƒ„»¬UË6û P€‡a¾p–=ùe@ôyü÷îw.-Jiߢ«2Kðï³€͵žž¬« ‰Œ dT‚0@RaRpóÂI´/U‰ÙEOÖË5YC…W²Šv2®C„Ä:LáÌ8&Ó9û ð@@ ·fB ¢à ÐÔ_Ae$“ )ÑLÀÄâ‰M¯.WºáÊF¢òLG/ 2Ç,²,½*šÀÅJT“K¢ò2fë÷P&o‚r]ž¬bõü›eá÷5a™ÒZZK)-ü¨eª[fý4í a-{êûù@YÀGñ ŒAßöcý|-ƒJ¯Ë‰ŠÀP¿( HÔtèIõ•(™Ž§k;^‚ i6A’@*‰D$hgmTx5^EG¨°*B€Qn}âûÓk¥Ò,Dy K ÉÝÏ÷%Tªt"NJ R’Œ@I;KP; TAR¨i3F (5` ©î8d~ºí˜45z¹ô4¿Ž:™Á¥Ê)¥ ÊD›ìÐR¯†Áj}ÂólJUˆ0Éô˜1p P=f\ƒ@¾S† ;˜Ôõ—pcˆ ‰hæ|H;¶ nd9”a!D§ Kâ8Y0)Ò„xux΃øÏ³4¿ì ³Ôß^ŒåØvÙÙÕ/ßOób  úA>Šæå|>êï3èok‚You¡ìU*3é­¶M—qˆYPd?«J‚É<åYr *(Èh†ébŒr$@HB„$D@Í”® ´ßå3þßZó#Õ,…$HD%T =8bD,ù `_2â&Hbœ«„‚ú‡Ý©”(TJmOrÍ/9 um¨‚b ’j åâ)õœ™ƒlÕ~÷[A÷ýü–ræà è¶öAô}° ÛEƒìGúƒüƒXÃ(ïëêÚ¥wµ›‚Å´s*ïïòþyjÕ§5ï\ú2¡®§Þ¦€ N4$‡N¢Šºüz)µi`í|-ü&Ù'SÆî×O© Õ ¦tWPœ@§Æ`L<Ó‚\yˆAsÇŸ ûY" ú0-Uœz©#€Ô3 •Ц”¤Š™a¦¾Ïx'`Yûù‹o_û  œ¾:(Ì8,Ä7HkþQà m~°?‹±jO9¤è¶è¼v/L'•Á§Þ¥ ”I@’Å„#ßÇÓ/'®ÔõêW  `0Œ!BR3´CI¿ÎÁÒþÜáGR$$1K©ÇN€€@q©ýÚöçaÒh^3FœRþS°TÌ (ÄöýZåw'µß‰0UŒ¤„’ƙȤ޸˜Êµ¿eÏ# ÓNÃWåL·A±ìa¶µß=çal£jÈ'e=ìÕ'}Œ~çÒgµ.>nTRɼ <ÊVºåŽ;YAûûŠƒ2sß¡tǂꙆ¿Ô¤ v€ \ÛóR9ͯŒ­OR‰Ô,À&øp©ËÖW\›0@@XÎLtoIû9m¾‚É$&mÉKÚWd§“ä CŒ@Û²db€íÏ× Ë™¦øÉeVà›£4 é—Ðó0t¼%®3’íÙÈ(ÇDPÇÔü<¢™$=‚mú@‡axL GŸR(׉袋ÑDEU")²8AÜNf $ì2äó ]|T)áÇE<»ß:ÿ|­ï&iúO×-ÔXÖc8uä ⥷åm¬ol¨T¤EóìÅñ4?N¶çE<Î1¦&¦ñÒÉ—05;…½½Ðo¨6‘@šfH…€2¶¼£ù¾–÷œí|E‹µôö–0¢)pU{ðU¨U#4¢&æÑ˜:Ê'°Æîa›JÇÍ 7Ù|AÄ ¨ëPL(¤ RtUmì Ì*èµ»ènöÐI:èÊ2$nÜX"RdR¸æŸØ7¬ÔÃ@í÷]hÛPÂ$.™F+DÔ¨.‚ª° NNŸÁlm—ο’Q¶ÝlrBbòBÀx^`®,ÌÅ÷^}»{;Xùâ6Ö?»­æ€b§×A/KLì¼dç3 <{¿}6ETk’‰,äP˜<ÚÀÜüæ0FÝSö MIDATÞ®a¯›"S™©ÏÏŽ0ZŸ„zC`5?+¶_ç*Lízþ~ÛíKõyñìJtÆ M¬I²Ûb ›»ëØØ¹‹¥¥ó8¥&œ'Þ6Ï Î €58qÉ=ÎÃï6n†˜pp¢Cb<ˆ×Ñ Ì°yˆÛôZ¼ªn³*º„rÅ©RD‰üóª!NOU]ßJæ‚…°r]­Ü\'¿ùÍJ•R¨µ¤›lã$î<'ð]ò¶?oþ„QŽÑ˜jàû—¾Wξ’wåqUtFšõ½Éà(ÃÀÇAÀˆL`}{ÿç¯þ7|¶ò+t’æ““º‡ }½¥ÿj°ðŸío£  @°›ì`;Ù*@ç~÷cq…üB“¤JREÁhlÿVyÙM2ÓÑîtt[6Bb‘Êû˜F|hÀ¯¼¯çE•K K®eö A~SdX‘HÓÓõiT> Ñîì¡›öeY.D¦ aF«Ú:œ€±þÔßõþæT³ëDÆè¦]ÄAi'»G×é qW¬* ÚORm¯[­š '¡ª/UDïJü|™Ï›ü]{í cpÎÁâ2{, òZÎ9x ?G– yÈD¡S´3.áÚ”é†Ì%ñ”‡¯èÍìS®ëþ `{+ª@*}€«g.D)€›@ïæ8`¼¾ƒK7ÉÌD'= ÈÕÚÚÈ3¢išyØŽ>å¡+þè5f†–êâ E€T¦ˆE†D¦RöÉR8ë…*û/ø¶Ïµm(’ ‰,D=äÚ$Vø-˜.ºeá/l,/ü±E?”ê,<¡$2¥ ‹™ ‡Ëäë…ñúN-Ûk@æ!8BJµÆ(÷Øß‚Œ˜mÅŸ7óãP¯¶xìOx¾™ÀSc*o:¿,)2Báfö c~ÓæUüùi½c¯ñ:4š…ÄâEœ@åÂ?hZs™ 0¯Öß±ýR˜n c&ðó'–Ï> Úß‚€:\ûÛ}å•~ûrüñûÆë;çP~^½`Œ4£Ñ7t³â&!váÀx}7MÛ ´p ðƒZ)-š †(ß¼›cSà»lF†s­lb½™HdA£@ÞÄ“¸I¿û$þ31¯ïœ °Ï_n‰Û?(ŸÀx~NÇ¡€Ac»žÖë¾k¯ý¶>ï·~¾¤ÇD‘¢lÐ&@PìJ¬úøÆ0^ãõíúTÉ(Øéä`»½PÔ4¨ásâ—ý ßÊyúÖ¾³çP¶$ç!œu#½WŸ.?c0^ãuH|Ê÷ôk´ñ¸æG¹ƒÏ˜|{LàIhÇq9ðÓcÏìsšgž ŸöWÙÇP˜2ä#‰kày¸åjÌÆë;Ç\CÍ>vº?Çp˜¶÷‡r¸qcJ¹×+åÕŒS_ &0fOß/ðÔÏu©—ž*h}8iÍZ™qâjÿ&ó‰ÃþýªjûÆk¼“ ”¥&›ep‘R7%ó>‡>HxÝz•8Ü~€q9ðØŸp(™ÀÓblf¸N.ì> xλ²V¸I©ì&A (ôK63€ñ¯Ã¢ýÕP0 à ¹ÕøƒM€ü1i§ôúC<Æ>€1û¾Ý\©~Aûçã¶­à@Za/› D*(a7Ýyh †Óã5^OþÂ’EA/\m%ð…»Ÿ€H)%„´ Éô~¨ÌEÔFX„䃒žD¾ùa\¾õûí³cGxÝ mYÖ¦ÃH½vÍ\þÌßJ5 }½1~¥€"šþ—€;uWØ€x*tý¿¤Zð…Ì ¤S UVA¢R¨ÌÀ¡Ì <4À9×'TJ¥”nVúÃ΢J}å_Ä×~ïM¾åR9F(Æ€€!d<3¨“'$á2’B ‚ dÈ@AÔ0ɧ0N‚³ ÓG=|.ÁCÕjwïÞ•A¤RÊî+¯¼ò&!d @ z¨ÑH‹~ôøišv²ÌcÙ¥Oñó Ëdd <Íïò$Þç‘ÊŸ©¢¢*æ*ÿSNéûÕJ-¨° áC5 e5L`‚ôP¡7-XÏ åˆžpÄU€@q0ÉÁ$C T²xZ‰HÊ@$SÜ߸·Æ8K)aPðÐÀ§Ÿ~ªNœ8!³,K¤”mJ)¤”1!$TJ1BÈHmÖŸµßÀ Г‚oã»=ëóõ$ßïaŽ¥ˆ¢’I)¤ìTxˆ#Só˜`“`€Jar§Ž´;‡jƈ.Hb.5 °Œ‚¥z¨?”R ưW ö(ˆâ’!­€¡‹Ld’0ÄY–%c0ä÷€••yôèÑ4dY–)¥:”R€(õì­k+äé¯g‡ýü<«s Åd]²¹#³ÝÇNâËïBD «¿XÁƒ½ ´»»HÒ»zi$ z:P='ÐŽ 3·„kz@CµRA¥"ªE8Þ8ùh?zåǸ¾ò%®¯\S»¼£Ø@`Àõpÿþ}œ8qB%I’eY‡aH÷©@’$Oý ¦iŠñÊ׳š-„`Šª‰£óDzS'N“sçΓåÛËXýx›[눳vâ]t³.(ÏL zÀ—!Î$(#¨VC„aˆ(Š ç)gൗ_Fš¤Øjn‘½Z,¶±{(ó(ë[YYYq‰š $˲gò¢(4›Í§öA¸ý§ù>ãÕçZ§Hf³ŠÆnܸonßÄýÍ{PTA2 ·ÑMb¤J€Q3.Ì\‰ÖU0ÃD¤‚D¤`’BÈ k[wP­†81UVé¹³¤5Ñ‘«¸WÎ:À SÀßÿꫯƗîx=²*Äz{ýÎnºû»Ûn‡ÖI3iJ0teÉ ˆÑ>VøË‰BÞ$!0§Pqßô–I5û˜Bø^¯ýõNsw‡4€Œ¯‹ñúN¬·@`ž)ö#)ä*Q(@"%PJ)•iÚGBÊ· …ÞŸ„”R¥k@!@@…AåžÈ²ÿ!ºâ:®¢=6Æk¼¾…ÅêLˆ]±#2ñ+HÜ$UvH8Í…\ â¦ô¸ ˆT¦ç E‚ 2Iâ(Vh&ò–ŽÀx}gy‹0« „Nrm¢.)h÷~·Àþ@ž*ܯ´ $&Wæ+Yüa<®q¯ñ¯ñ¯ñ¯C°þ ÷×\6мIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/binary.png000066400000000000000000000116521217176075400233550ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÅIDATxÚì[mH[~öCM‹¾ÈŒD"T(º‘î®k~ ThIJBfÝ*ï VÊì!©eBTh‘•n˜J…®ëf›åÈk#«Õú•Y:÷× »3gfçcw»Ü{g|ß93ïsÞïsVEQþˇêD°wïÞ⢢¢?¿~ýúÕë€*•,}°¿‡tOŸî÷ôØE©‚ƒƒƒL&Ó_ÃÃÃ6oïÓŠA)666.11ñÚ칃177Š¢0;;‹„‡‡¯3†(fgg333ÄÙdϬ\{ÆùfÛ]`ö5­ bM[-qo×Jh4(40ô5é^­V¯Ýù}¦lÜìx-FPÙNËM@FÃÑJúô‹°UÓ› G…^¯Gff&3Sî§Á`€Ãá€F£V«åœ†á§OKKƒ^¯‡ÙlöКG­Vcnnΰ&033ƒÁÁA8,_¾­­­ÄY 4ößööv|ÿþ‡ÝÝÝÕ—j²}€7ÿðë×/æþãǼc¸Ï”XØt¶P«Õþ@ŠS ÅîÝ»¡×ë±páBäææzð}þüPRR"Ê1Òsrr ½^ýû÷sL€C¬Ð*Q}ú£øœaii)JKK‰´¥K—¢³³S”Ce¿§½½ákë>€ôaÞ¢ƒß²eË8‘C,î<ì ›uúÄ a4eå :z½žH3ˆ'šCee%8¹€{¤Xœœœ”•,ét:œ={ééé8|ø°-;;{öìÁÐЗËEÌ ¤Ì¼ÏÂ`SS“hÇÈæ3 (((ÀË—/=h_¾|AJJ ïs.\à$>ìè÷T˜>víÚ°X,’@ˆˆˆÀÎ;‘ŸŸ¬¬,ZEE<ˆŒŒ lÞ¼™3ƶmÛ—/_&f>w‚lÜ_ÒÜÜ §Ó‰øøxb:Ìçå- rrr••…’’gÒÓÓqàÀŒŒŒ ªªŠ3žÙl†ÓéDbb¢‡sô{ ‡¸¸8Áš€„Û·oóòòÒt:t:¨èäwèììDRR’¬ °»»ß¾}#Òžž>}*9:P…ׯ_Ãn·óò=þœ×/4 sòäIóvŒŒF#î߿ϡMNN"77¥¥¥¸qãgü„„øÄÔR—2‹¼´àà`àxzŠ¢——‡¦¦&©›ÀÖ­[;vìdwîÜaV}ÚÚÚî±0j2™ R©àt:qüøqgéV½(ûÛ »'(%O¨©©A__Î;ǬóÑôÊÊJÔ××Ãjµ·ÉØl6Å3/¹À®øTX,(ãããœÅ‘°°0Íì±é½[òt)ÜØØ(:…¥Ëä´´4œ9s]]]ô¶¶6ÔÕÕ!%%…)˜Üéô2÷…ÓßV»ïø–òlLL úúúxy­V+ï¸===Í HZ ˆ‰rŸ*Ñ¥¡V¢þJ &o?©“B—› ‰2­V‹yóæáçÏŸ‚%F(!%c³A ˆ¨ŸÎnܸѰjÕª³³³¿¤öí¤þ¢Ã[âTjµšzüøñ½OŸ>û€óñŸàïŠønÛHgâmIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/doc.png000066400000000000000000000172651217176075400226440ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÐIDATxÚä›Û]×}ß?k¯µïç~›3wŠCŠ’(‰”(Y—ÈŠãªN(qëéK?0úÐ?£B‡©6E>Š´pãÂŽcÑ–I‘¢(‘)R$gȹžëÞûìëê=£á„”HšCõ³ÖY{¯Ëwý~¿õ»m¡µæ·¹ü–õ }÷»ßýwßûÞ÷þ"‚૞B|ø™7Þxãøÿk§·Œ¢(ÐZ“ç9¶móÞ{ï|lç9I’Üó4÷žì£öí=ñûöî ï­oSÃöš« Ø»¸!Û‡éÛe˜íú½Ú†aܳ¾ûù}‚O„ÝÔñ° lÿ¬Bð^ ì:!X¾yƒ?¾H©äÅ9KK‰F#>»y“ÅÙYÚ6gÏžãè G¹qísú£-Ž>÷"ïï«è6`»Ù9MÃ@kaû À½@ð<™î4n¥DDÔÛmÇf&MhNu¨V«´[º­6qâ•+Lµ;÷o÷¦·¿HúÛc`ï"v·óBG1Á$È£ˆ4IÇâ`Bâ—}ÆaL8ɲ࣋ŸÇ JZ$iÈíõ ¦ÚL·æ9óñYÒ,aaéÍÚÁ ä“‹g}áEÎý€é™–—oá•m¾õ/¾EQ;”°op?ϡ֬à•*ÄqˆWöRÒiS¯Wð=›ÙÙ*¾M£VF&–cކtB&Ìõ”+MÊ%WA.$­FóÎ<¨4+hfº³¸n™f«ÁüÌÒú‚ÿ„‹ ØË—iœ0‡RMR’(f2™0öp=×òõ‡¤s‡Úd‰MœÄ £IžÐ„˜ÒÁvlVÃVªP¶ÄuJyÊÖÖRt¦R6·nãø6k›·h5ËÑÙ?MðËøô ]A'Q$÷C’©˜d BâjÈÄ ŽúDã€ÍpŒ¥¶ Ésƒñ0$."†ãž#)ÙáZÈP <×C AšL‚1IQô#² e´Õc2™pkM37ÿðüÿÈ,pkå6Õj! ú››”jì’O»ÝÁó|<¿„_®¢L¤ÐÔJ œR‰™©üŠÏt³ƒe( SFÍN¢ÛtèT›XUî|ƒF§†%Kä$Lgó åªO»Óaz¾‹cÛäèëða»GbÛ+·1ÓP¬®ÝfRäÌu¢ ÂÐM"ФB4Œl©»>Y3 #Š¢IL¬#¤_! 쑞 G!¶cÒH\Æ[ ;£x΄\æ›CbÛ`ªÕ!HFŒÃ*ƒá-¿ü¦xìŒÂ1Ñ8d‚ÁÆZÂø®ËíÕU¤ô%üj•þê*×>ÿ©bºÌsóó+Ìtg¸rå*¦ÊŽÃp0›Ž˜L 6—Wˆã.¯ŸCçFaùM´aðÉgŸ’ç -ßçÒ¥Ë Gn/¯Pªxqœ™ùy ÛeQu$ƒþ€Zg’ˆÍ¹Ã4.¾[ÅVošÓÕ*ÊĆ3Uƈ ºÝ.ŽåRï4­/QâÉ A­5Q8lBf(FAå(ŠrÌ``‹‚(¨Å ‚dÂx8ÂqlÓ"$dyN0£#ɨ`ªi°º¹””ë³:^Å”–Ò”¤O‘¤Œol‘Ø’z³IsˆçøÜÚXÅ( ffºûOÛ%Æ„qä„A‚k‡„•ŒQŸjÑ 2¦Æc’qÀz¿‡W«’NBÖz+„ãyÂÞˆDæLL‹~6‹l¤ õ Ç/ô„ qí2R)â,ck<  Fõ×®_!JCƒ!ï¼óÍýõ îeNw–Jµ†)Ù n­N­Zåéƒ(Y½0fªÝ%ö¤íÐlÔñ—gMPJ…Ð9…i¢ +,<ÓÃQ6Žç¢ÓÃRã‹&!E*@j ¢ÑH­A‚O0”"§ÀB’’eÚH)´¢˜$èØ 6IN*|e0 l]0Lr¬² ¸û£ î%«F¹Š_*a*ÉT«I©QFú.Ý©–çáû¶ëÒžòwM2 ¡Ú€B s0AD¿vaå ”‰‘çĹ*GkEª H ´PähÚ ã “ KÚ¸ËQóX…àn][Á8ŽÈ³œ4ËÒ;JÉ’œ ‰0„f´MNvÆH AVh´Î0 ²eTj,GÓߊ˜ÄXCHŒ\K0@‡‚\Ø9Œr0,Œ"£ ûÒÚc¥€ÁúƒÎ’ŒÕÛ7ȓϷ¹}ë#·Ì8ìQ-×éõ78Àá;Q¥4Gš¼è¼@+oºØe“Ÿÿì=ú½„?ý³w@Ã8(èzd±&•Y(Š@“X J䤉Â4=„N¤R£÷„8ö…¶ë¯¾ö–e!„à¯ÕQJ!¥äµWÞÜ™\)Ewª½óÞ$/  0ùà‡?ægÿxŠ­aÂh¸ÁÁÃKص:_{y‰ÍÞd#”À,KjåZddÊa¼6 N L!HsÈL½°w@ÏóîÚèÞú½†©( J2N Þè#×>¦V²øîŸÿ1§..sáôy._\!L2V?…·¿ý6GZÕ;þÀ4ãú•乤×ðú×1b†ƒ‚B¤(ÛøgÎÚÇ ÀîAÿçÿø{ž}þY”¡8yæ—L·:zêiN}p˶‰z}å n~rŽoüÑ»ÜXÒh×Ù¸±Š ñå„§:U*YÂ4#ûÄ sÊ„aÁÁ©ñõËü͸Î×ÿäÎüâ4·?» :¡é› ‚+ç>âùG8ðüq›ˆ÷ÙØy?ôÝî&/>Fg¦†_ióÜsGðªM¢A™0Š/¢É··¬Ý¼…{,´êè\pm3¤ž)rR\+¥Ýn÷{HÃÂl4 êó_ÿö‡4ÜÕ©6®é!í†Á`òÑÉ‹\ÏŸ=eò«Ó¤ë3`hþøW‰2÷O7A§8Êd±Ûàƒó7ùÏ?ü)Êw˜m·ï·Ü= ÓªS­ø8¦Ë¡Å%¼ªÍh2aåÒulW’1n—(ÑêLð«Ÿü¬ó8z˜¹#ÏóöÑ:¿wÄá¯ÿË„åѬzlõB6>‹ùOÿp™oŸáÌ¥«¬rÞÿä6³ÓU"Õ¥öô~Éã¿ÿ¯“¼ÿÑ%·¶ËÓ3b¯Á»lpH”vÈEDcœ&e3bk¸‰[Á„z·E÷;à—@+®¹ÈµóŸqìØ,¥dLƒN]òñ•?;³Œœm±±žðß~t¯VBš&¥$au­ÌVyÿÖ5.ÞVL’åW0ŠœYy Ÿéý`„ “Ç ±°ˆã1å¸B†@LÂwÉIˆÓœ(ùB;#,ÀàyÁÙŸ_ãì{ŸáÏÔ fëÃ=‘oÀ«@‘öÇØ —ÍÜ¡ªk\ûô&ÙÆ?a´Ú8ÕiŠbš—æMdsòì*ÿ~?¯Á»Ta§„¥,À@™„R˜Bc{¶!°- Ç2)vQå3Ï•¹¶‚©ÐYŠ]óŽ‚AÄ•Q@»©xzÉA9õ’¦ á“Ïýõ€õÕëús(;PëRÄPŒÖ¨åcܹE~ôó-^<ä> °]i)¤’TU*nLE¹ìá5\ ibÚ6§²óÎ’»ÅÒ >7{·<ª0µH⌺-p<© .]]¥Ê÷ùΛ°6ÌÈE…Ë7b[²¼\ܱ¨ I®ñþÉ ^γ/žxr2àæõk”
  • <õÝÙ.ò§8}îµr‰ÑxÈ Å1n,ßbjúNæÆßþýO¾Ôú¨}{ýƒODüÞ7ßÙ ^.þë?ÙYÄ»ø‡w-j~qá+˜÷óì>ªõ‰È€{$(ß?{,Ïïx€ ƒ,ËPJÝÒ¾RÊTW)åN–e;ýY–ý:¬^€©Ô“ÉQJñ£øß,-Æ‘&œû€îÔ3ÝYNxßuÂ^|‰á`“+¯qpéSÝ.ïþ¯½üW._@é:„Ã-¦§æH‹ŒÞÆ:f‡V«ÁÕ+WÐ:§;3Kůë„åk7Ñ©`ñð7®_§^­2ØãVŽ{iÿs„îÄû¡ÓjR¯Ô1MX˜£Ùj2Ý®sðÐaÊ–Íp2 ÞlRqLò¢`j®KÍs943G­Zgvv­M,G{U*í*Y’ã)Eµ^§\.3èNC¡©Õš¸®M9ËH¦Z… V«'1e×GÙÒPONºÀµ¤ HpK%ya ¤BØ Ÿ2¶i™6žåâå6†,ãx.Žmb9ed† …—cÛ UHbÇAš )M|ËÂD`™CB¡-lËC Rb›RY˜ÊÂqý•»SÖóÜd}«G©VÅЂ•[·hU'¸–Is•IäÑÛá¹eÆÃË7W(”Á‚#Y¹uƒv£Êí[+˜–ÄÚ„q\kò8¡?Þq› ƒÕu ZS*ûdYÎæÖZH Còù•Ï(Õ|6¶z¼ùµ×ïJ©Ý· ­5¦J){.ŽåcKè¶:”j%\Ë£Q«cº.žéR.{H%èd)õrÛ4i´;8uŸvØ@IP†ÄžTÊ>™kSïùØ–C­UGå’rTžQ.׈㔩v›…ÅÐÆ_°Ðdyþd$’DãH›4 É¥"Ž#ŒHá˜cÂ(ÆÔñ$ ¢ &šô  ;VÄM0*ÃCI”°È’ŒÔ‰™¤ I“I“e †6ÉÒ’ˆ¢è,¥Ð “$AY“?brÔ#_ƒE‘sàÈ¡IkµÚŽô­T«wIâZ ¦g§vÚÇÝé¯U©¹-„¸kÜíÒ¬×ï« ìk–ؽî×GàînŸÿô<ýÕ-ʵ*¯¾z‚d’ýÆÊÒ¾æ<èÆ¾jáÛíI?¥·1@ ˆSx€Ÿ˜&ø  <Ì»'^=¯ç×j<ÄF¾ ‡)ôáä£~t?•úQ޽߼K ÆãØôÃ>{¿ÅÿQÙàX@)…ã8¤iú•ÉHbÆÞï™ßdì½ ìŽS~©€ž9qâÄë‹‹‹'ò<Ï–¶“™öƒÒî·'Ã0ôêêêÙS§N|,üÿ\~ë¿ÿ¿]Konˆo[MIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/empty.png000066400000000000000000000066301217176075400232270ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF³IDATxÚä[AnÂ0ÜD)ð NH=VâR^éêƒz.|.ú Àê¸'KQšÀ:ÞYoÀªÓDÁ;ïŒ7¤ðÞÓ3·’ž¼Uœ‹Öëõçf³ù8ŸÏç{×E1è\hmFv‡Oó8ÜÛ{_L&“—Ýn÷½Ýn¿DX,¯«ÕêÍÚì5Á¨ëš¼÷䜣étJûýþ Æç].—ÎÙlÏìÐsíï›ífÀí~`C³hhŽCÛ˜s”Lèw—eÙÙo^I‚ 4Ù Bø U-ú˜Ñ¢ ¸ j-‡>6Üû@à Bè·©g@ q@h®–RƒC|ò’Ô¤@èêsÝ&DµsýÓÿXú‹Ë ³¤²Ì Â-yTË@¸e–Äéb Q‡Q8A¤Yz'˜"‘j2hÍ,A@®g¤:$ФÖX@à.sm&˜,ˆh‚`¶ 2ôri| ¢N°Ëfjû]á¢I°ù`šì›i($Â,Á»öÆÙ*À¥nnb çA¦`> ݱƒ¼¶l Üû"k2Ù Æ*@.³Ù rÌ%³«¤6´Y‚Xá`½*}0ò‘ØAhƒ“Á”™}AdlLÈ’8tÔ,ˆdÉÌt3„Ai³¤²H)A¡ÍR¶§ÃVÌ’é a– 9 k uB„DÆæ•ßåð &¬pÔdP „Y‚ÔR“–Y‚ÕrÊ ‰% ‘x4Ì’ZU‘$Xs‚13Ïø½Wêbέ[²Þ¬ªŠf³]¯×›ƒâuëš”{·A©*VhTpÖÌr¹|ŸÏçKçÜoì¨ëZ-Ç„˜Ê²ô§Óéçx<Dxäöôoÿ 仯¸WÃÇIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/encrypted.png000066400000000000000000000115221217176075400240620ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFmIDATxÚä›OhTÛÇ?çœ{'“LbLÔ—h_­6X ¢”´E%JVº°‹ð ;-´ ] ]¨íF\‰ K‘®²Jáá.Ðâ“ÔV4 †Bl4Ѫ!Ædf’ÉÜ?çœ.’‰“8™ÿ3æ=/\rþLî=ç{¾¿¿ç\a­åK¾$_øåäjÌÇŠ3gÎüþìÙ³¿[XXX(ôp!DY}ë#W=sg×3϶֊H$âž?þ###ÃEïÚ³gÏÞC‡ý|£­d6Ƭµh­ihh`Û¶m;Jb@¾Kk €ïû9WsíÊ–Û·vÅ×[íì ¯-gØÑ²Ä •+éË€’&SÎU—Ræ,gÿ¾&J° d³£T2k€zƒ°3Ö‘ cLmÍ`½Äa=6ºk"ÅN  dÊk©Ÿ)×E¡BöÄë¦*\­@(ÆÙªš”£ÔªB®r. êfë­€Oì¦^hjf7гT—hðsƒÏ<֌՘@=¥ªPí ÔÒO¨KB¤Þf°ëð½ðké,ý <ÁJLdÍE`£:K5 –ò\KëP1ÙÔú!€°¡"õaÃ'Dj ‚S΄}ßçÅ‹ÌÏÏã8®ë†!®ëÒÑÑAKKË*7t­Ø”ÚWî3ªÀõë×7µ··f×®]ttt¬ôyžÇÜÜ£££ø¾ÏغuëªÕ¨drµ¡h®]»ö›îîî¿Æ^¾|Ƀ8vìýýý«^ǹ{÷.£££ pæÌãÎ;?~ü³(ƲÍ`ggç`__Ÿ;66ÆÌÌ ܺuëý•+W8räÈ'~~kk+§N¢··—7nÐÒÒÂéÓ§I¥RÜ¿Ÿt:]WYŒ)\€‹/~ÕÓÓs`bb‚™™ž>}ú¡££ãÛ\¹öì—íܹ“Ç344Ä®]»8räSSS<|ø°®~BE p]÷×ûöís_¿~Í»wž¦³³ó’¬‡nv[ww7¾ïóúõkŽ=ŠÖšñññº;Ke‹Å~ÕÖÖÆ›7oxÿþ=Zë´Öz°Ð‹²ÛvïÞÍË—/Ù±c±XŒ™™™ºzŒ‰€ëº[¬µÄãqæçç±Ö¾?wî\ºPF({0mmmxž·’¦ö}¿®9ƒJ• ÐZãû>žçáyž¿ÖNJŽd¶¥´Ö„a¸²K[˘ Ø•/@öi‹ÅÅE¬µbí  µ^uWƒæÕÖyÍ`†„aHöy¨Rœ ­5A¬0 Üè­£²‚€0 ™››[uÈ ØU ‚ #>xž‡µæû“ Bc@a ¤Óø±¥&DCm CH‚Ph[¹¯„œ®ð¿ÿñ—È;:g§_a‚QÇÐÞBãþ9x`÷ŽÆ¯S‰·øËbñ‰H„Š L/5ËÜÌ+¢Ž!1¤S³D›Új ‚ÈõÃ[ûS¢©¹±åí«ÿa±„A@Û–-ììúéòо”’¤æ¼Ž”’0ÔÄš›øªs;÷¾»Ço/ý='€ë+çø×uéëë¸}ûö·E3à_ßÝ‹íøÉ×´mi§©±AHErnkÂå·¬zef V ÂBš7m! ü€Ù™9ž=}‘7Ü !©ùŒÑH©Øÿ‹_Òk&b5Zc‚kB´6` H…G9HÇÅuB‚ЉÿŽãº©…ÖX„¬_B¤åZ7R"€À[$ðæilR¸N„hëf܆6ÜÆMH$Z‡X«±Fctˆ5&L „Á"~zžT2Ak[BI„$¯Ìnœ„ˆµ Êq@H¬c4:ð*… ¬p0&Àh5FhLè-µiƒå:yíx5E ÈŠýH©ÖëYþ›}g·eè' U+'å^Œ³Tùæ¨)Ê< …@e0Å ¾Ú ‘²I –_>%kR(|ýì ‘ Ó+¡ïòü³žQx°Õ¡b ©(›vÉšH%K’Ýz2¡0TåÛ‡…rˆµ¡ d)°2)°” REiøj¥Æª¶;,VVOT¤d-\ª¨KNÐZƒÉŠÝW¾ÇYn3Æ®Äö&ëû›ýíNfËÕRÝ`s|¼P Õœ.Zsûvš6µmŽÑÐ#¤mðMŒ²a°Æb X#ÐZ‚µ£ÐÚÁØpZhˆµƒÕ¬c1ñ¾,·µo²Ô8'‹ñi"*¤Ñµ¨fEšˆt‰¨ ŽÆ*"Q!–&KqÀF´#, ‰¨Ÿ´7¿˜ L– ”ZÏ”Ë?*+t,9j½L{ó±}™ÖKÉSóQt²êÖjÀbŒÆhö½œt.ï—Ò_ùæhæ‹ ¥p#J)¤rŽB:ÎDzpA[„`yõ3ú2R*å¢\)%J}<ÂF &3òùõÅÔ‹90™€Dû™éÌÍ&H&“$âq:¶ÿˆþþþ³¥Be*9!¥´=zXRJìKº¾ø¯Çÿ?…Œ_7KÿosIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/exec_wine.png000066400000000000000000000160611217176075400240360ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFLIDATxÚä›{Œ\W}Ç?çÜǼöí]¿lÇvš(ÁP䤡%% /5¥”¨TH• -PU@ ýU*•@B‚ªâŸVjA*´UÒBˆª$*¨ äéò²“;±ã·½ö¾gvîãœóëçÞy¬×d×Ù‰ª2öhîݹsçü~çûûþž£D„_䇿ü®å¢~ðƒòÑ~ô[­Vë•®UJ]Ó{åc%"W;/Ÿ½çå½EDÅq}æ3ŸùÔÁƒßÜxã78pà—ÿ¯í^¯2œsˆÖZ*• SSSÛ7 ÖZ²,[u7Wîìµ¾·rǯ¶Û½¯<.ѰVnÓëÕø+¿š÷J¥”Š)W;×Z¯zÜ{ý@HðµPB/:Ö«„òu x­•p5d¬TÄjJpÎ Ö ¾Væp54¼Òs &°V^ %”Ç+¡_¿&ðJJØ­E ½‚¯—ÂWÿžàEéªúÝ[ï¹8PAÐýLßuÒ¿UÜg¯‹ûy×nx$¸Ú"‘’dˆ = q«-ªØ1¹‡¨Ò}ŸY¯V»~5´l¼ 8[/tP¶bå΃Tþ©ý{"àœ¿ß5˜p…ÿ/Ï×êYÖoâ@Baƒ+ãp@Ä¡P0­PêÊÝî5!kPÅukEÂ+™Ñ@L¤»H·Ú"ÅÿW ­4(…Í3²sÇ0'‘Ï^B5/ã$‚Ê0õÉmÔÞøkèÍ¯ó ¹Š¹]M°•&ñóÈzc8ÀY”Òý‹ìì|¹3 ¥¦5OúÔߵπ«`m@ÖZ­œv3E’ÓćÈð~‰;YÚ{7[~ó>”ÖëRÂz³Íkâ¯Í’å]£ N\—]—íÓ_al“ Sä. oµ1‹ ¸æ<®µ„Ζ‰p¸¨BóèO˜ºÿœÿü§Hfg_•‹œp¦ ^!压Xo÷(P —µ©ód‹Ž|q»œcÛ&ɰ™Ã ¨…Ú§_ÄÍœ%L ²{'ž ¾0Oe|üUy‡q€Bœëqƒâé]XáÞ’ãÏP­(ÌÜ6M°i†I Vik‰…Ÿ&,.ž*I/§6œÑ>w˜äÔaÄù|Á0…‚X¼ð¡5:ÄÉSmöüî}œ›9Iu,âåä$q)ƒõzwâÑ CШ‚nz»/ŠEpƒ@@¹óE# ÐXI|G~F0¡£Q‚z -§èÅ%ê­%âe!rPU`ë[˜9–1ºcÿöÌ—'"¦ç¦© hWì¾ë¢A‡Ö·LþÆå~Mm’³³t]@A ¥ÿ¡±ø4í¦îãòianÖÐÊn(¤`‡w0<^aëD›ñì$ÃÍ LÛª¿t=?Zú>óºIš:êÅýµóæ£,( aØ¿óa»…ÍC»°.ïT7Jží-ØÜçñÒË @’ž?ÎìçNЬ„ngëûnc÷ž½DS„õ6i“Ÿy™™§žä…G¿ËO¦§Ø¿÷:š3vè^D„e=Ãéö´-n]Êbýq/üu¡„°“vqX£™Îrë †ÖŒ€2õíMÙ|䥓£*u&~mã›{”æëPZ!•{zó=ìúóϲtæ4ßúÄ'Q'/ò«ï~'?~ YÎ.^ ¢+4õ(éB_‡]e1ì îl´ tÜ Òý”á¿VD[Iæ¦9ôÈ£3O6?C¾8ƒYœÃ¶„g²í|íG›ávï™åoÞþ÷þÑ]Ô¦¦æ/3kÞ¸e'æÏ“fb|à:oûª AÍ?õ¡ˆ8GžßÍ–wÝ@š/{ö—n…jC½€i[òÅ̇½Êg}Jk¢z³?zž/Í¿•,0Ö>Kš-ä-R³D*Ëä*#b„Y,ÇNñW›ßÆ?}îÿ¼¿ÿ§·™o6ÿŽvý~nÈo¢­rÚ*%7 Ú9ªÔmHm6Ä^ 8?o˜ŸÏxÛ[Þ@TiÙ¤ãP€ŽB‚¡*Š|e·¬ÇiÍcÙ 4Òœ<[ÀØÔ;~ ˆAœA|È¡ý«ª;ƹ@Ô¬#2ÆÉã2´í6>²ï³ÜwãÇøÖóßàéçaîä9òK—‚ ÍHcG\ýnÞy÷;¸óõï`¢1E3C(á? ’˜®ÕÐy~ʹ­„‹sdÆ€±>Prç,ˆEQETº¹€Ñј¥Ås|òvúŒî¿¾ÊîûnáÉóðºÍʇ÷œïÿ8NËy ‡VšZT' "¬3œ™û1I~'›°Î‚ÖªÈJV¼2¿ÜÖ,\Ìp6ë…gQÎ"Î'I”«\…m›ós³Üõæ×Óž?KÖØJìçNssúxÁì嬾ZýfœÚN5lãìE²ä%¶Ôްkê8{·^æ‰c_áú‰7)2RÊÔ|@ pñY'h%D¡æ‘ŸfU”µX›#Ö"b±&GœÁIà¿FEu׫ÎRO*qÀé'`|ë($Gq &eŸ}Ž}î9XÀá(0 Là³§äÙ;7½»ŸüJþ“B‹Ë–é¹¼ƒ‚@ÁèPÈS/§Öuw_ŒGb|’¤Š¸• QÁ.¿È=·oàÒ¡ïrë]SÐN½r-H^<Û^ ƒ®Q7¸0w=c)Úù¶pZïQ  9j­ó-gqhÕŠæÒ|F{t‚,Iãw^œÁ‘ãœE‰®D€‹™qÌLãýïÛ@ÚLzI}ٱ̹œ#`lèW[êòÔܯèÐûþõ²"yÝÈz@é÷]ÿW"ÍŽ´0:À¤ç bÖ:Ä#¡°P5Ækó$‰æ¦=›ižý1›¶× Õ1oÇt#?WdD QWp&‚ÖoÃØ¼ÈþŠJŠMÖZY;¬,I+%Z¨‘ŽÜV”ÐAŒ BŒd¦Šqœ‹ýWEb9Á­; öÿÙ¿0µ3†lÚ+Öv#¿Nöt…W¡7‡Ü4¸nì¹ËŠÝWh4Ê)Ä*L®Ö¯“½G"ÍÜ’¡52Îh³M­ºH²|žT×1•Eì¤"ŸÜÊÌòç.×IšCÄíæ%Þó›|ÛlöiÆnª@*8×ûc Á{DT`~a#ñf’´…8q…ù‰ßý8Ž×L„áz„wÎ'C•HóƒçæåG¹püE–Î_€tÙ÷²6¦=ƒÉ^ kìÞ‹Ùt6ª0}Ærï»v`’‚0¥VƵ‹äÇv…!]ÆQ!~én»% MPŠ0 tHÅTâµj¢˜6(ζ`îøK¼e"bßþ;¸nsz5$ }—67Âü’åÙË|ïñÿáÁ‡¿ÏŽ]»Ùºi›Æë,ý£“!Ê]è#?ŠüŸ"û£0‰º«Ý±í½ÄQ…ÍÛQJ_95¢ô â¯„¹¥œß~cñáQœ@n„4u¤™#I(AkÍp#äÞ;7ñÞ»ÞÁ_|ì×ùË/?ÇÖ­Û—þƒÊhyÛg{%ü $øê©W‚*òb€×M½µÛy¾"@`­×Æ‚ëlû0ˉà¬0=›túýRÒQGûŽ4U8§È󔩉 ÿø…Û;mõ˜ã¨À¯Q~ÌJ· Däs}CÐ5TÆÜ Œ˱(å€HŠà!utˆÖe®¨L*Õí …îíù/W â+IIjPºÒS\qœ¯|ˆ‘³’4o¦2”S¯/MÉ‘Š@]A-Àé:‹óC\:=Æ©3cìÝsÎQn$+’ ¢` è$\Î €¤3S F }§hE.x?àÄ€sT¢®]æÉãoøCBýôñ¯pþÇÿÍÌ¡*íæŒQˆ Ñ5È´"×7"&·LrËÍw0¾ów »€HRô"AÐLÐsU0ˆÎPÏ«¬Ò8-;Ee•Ey–S«>S+k IËUUÑžO³cÏŸ±#;YR\9'PìD -yn©Uã®×@pY  Yq[×qiݱ:׃,ÕWŽïSt]ñ¹h]$x´ØÄb¡=¤¨•!Ë-µZÜ]bž¢€0THÙÅ]M Y!œZe>H­öwWTL0!Rî¸ðʳ¾JSÔ5ÕjØ£€&hÖæ D]u(Júa¨V"Au  ¨@¥« ´*ˆWáœtÊêKÇ D¡µÃK‡D¡î¶ÓMBÆÞ­j>WžËŠŽÔ•Ó¨½7ÒƒQ€¿0#Rmª‘¡;ªƒbGDuš% ”#Í µjÔCŒ1mtx×Ö‰$¯„ßyim½‚#½ýÙž¿Æë²ÿu¹Áv;eqq‰ ‰¢ È( ‘›ëІ çTÇýùÝoû.z =“k¾Ô*sSë¢Ïç5ÖûCÐ5+`rbÄ‘KnišÓnçˆä„aF\‰‰‚ȧõÎjM%ÖÝ,ͶQ:D‘_¹ËôŽÝ_9¨XÝß÷½/€ªnX:І‡ª}ög­£ÙÎi.e,·rІJlHra¨uÂ_ù"ZÇ>ks¦@J¿«^\÷ F1¦¼â'wª—§œÔÓ ÃjµJ¾JghxXá&…¥Vî³>¥ CM5¨TÂn›\&PQ ­Ò+p] ^F}ýL_šž0¸7RuΪµ@eÿþýwìܹs¿µÖÀú~ò²Ö_o]íó×ðãn¥µ–gžyæÑË—/ßü~üÂÿzübP¬õûÄáIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/file_broken.png000066400000000000000000000216251217176075400243510ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF°IDATxÚì]}\TUúÿÞ¹÷2/0ƒ ø–Únf[Šˆlbi¬i‰ècuUtÓ°ú”b”åºmV~ZµÒ55ù˜é¾¢?ñ=_BDMÛÀVKM!•h-% †afîËùýáÜ~Ó83 3w†;#çó¹ñ¾ž9ç{žçù>ç9Ï¡!è(·o¡äEQ@¸-ÑÈADÙ›ÈôQ¹ ¢(*<222N¥Ré(ŠúÅ{•"e<©‡­}½.*•ª­çÏRŠ¢@Óô-÷Š¢(444Ô¶´´\ÀËF&Dª:uêô«òòòBƒÁЉçyÁ›ð¶áä~Îx¥g¯QåX®‚³¿Ý#„ **J·xñâÕ‹/ž/—ÄedK,˲±‘7‹ZEß×§D5`ÿûíÿ&„ü|ØÿßÝ5éEjµ¦+€NEý$G½™~¿ €šçyJEð"„¸- ¥'P.׫F£ÁñãÇÿóì³Ï. „ü WTTTræÌ™s,ËÞ6‘EAç öÅÂ&„@£ÑàòåË—³²²æÆÿàˆ,‹åz^^^¡¿F§’"‹B’´ÖjµµµµuS§N}ùâÅ‹gm¯ŠŒŒŒ}â‰'ÆÐîÚµë`CCCÃ0~‚J‚fi˜\~{–eÁq7cÆŒ¿|þùçGp¶ú†/]ºtÁ† 6öéÓ§÷¥K—.8pà˜=åÈ¢ ”m®”J†aðÊ+¯,Þ¿ÿ6ÛÈ€°Ù³g?ýÜsÏÍfFŸžžž À¼}ûö}›.AC[³T=9OQÔj5V¯^½aÅŠëXl:Ÿ=zôãï¼óÎB)¯Nffæ•JÕeïÞ½§Îž={>,,Ì­ènm²JÉA%!O¥óùùùrrr–h `‡çåå-ÑétjŽãÀq8ð‘GIày¾fÓ¦MÝùÌf3wõêÕzIUt¨Ò@­V‹O?ýôÔœ9sB®ÛD?Û»wïþùùùË»víÚÅb±¸™]‹ajòäÉ©Ø]»vºqãF³d :ª”ÚÚZcqqñOl…`Š, ¨ÓépùòåËO=õÔ¼†††ïl#Ÿ ë¾nݺ¿Ý}÷Ý¿6›Í·¤XKKKKéÖ­[ŸÊÊÊo33sAEEÅ—vôºuë–Œ=:Ùl6ßò>žçÑ¥K—茌Œ‘š·mÛvÀÕ(Ñh4ìáÇ¿úñÇ›Ar;ƒ@H ½Ñu Àã8~æÌ™¯ž8qâÄõD¼óÎ;óf̘‘.‰}Ç÷IÆàôéÓU©T÷ìÙóù¹sç*íA©Ð4M]»víÇêêêo¹Žƒ1²H‘ -¥R© V«ñÚk¯-Ý·o_=Ý{æ™gf¾üòËs¬V+œ¥ž• Çqˆ4bĈxŽã®mÙ²¥ÈÙ}4MSµµµ?~(ï^0€ ]2„HzX«ÕbõêÕÿX¶lÙ:fÝcRRRÒ—-[öÏó?§NuõNAÀ²¬*333 »sçÎÂÆÆF“½DEÑÑÑá)))w•——Ÿ‘ À¡‚vÉ"}ùùù…999K4Jt/!!á¡-[¶,‰ˆˆÐpçÑ;A@jjêÃÑÑѽΟ?ÿMQQѧRĤ*hšFbb‽{÷–×ÔÔ4Ñ4Ý‘¸ª½h`DDJJJʲ³³ÿd›Ýã°wÞyç=›6mZcoôµöNžç×eÒ¤I#wìØqÀ™c*--í~–e…ÊÊÊ _üJŒ, ¨ÕjQUUU••5¯¾¾¾Z¢{,ËvËÍÍ]Þ¿ÿ~&“©M%ýúôé0ìÚµ«ôÂ… —ìAžçq÷ÝwßÃq½wïÞ¯Ú˹£4”ªÕjÔ××ßÈÌÌœáÂ…r;ºgX»ví_ÇŽû Édòª±¬V+ 4ø¡‡Š·X,× ÚÓAA£7n\|YYÙiQH⯜Er…¬ù ~ ¶³ÂÁó¼0sæÌ¿”––Ùѽð%K–¼•••ÑÒÒâuc‰¢FCO™2%½}ûö"£Ñhvõ ÷>|øÂµk×ê=õøÒ1&“É ';{(eþ 4P¥RA£Ñ`Ñ¢Eo9Ð=öÉ'Ÿœ1þüçÍf³Kºçiƒ‚€ñãÇ4 ½Îœ9s¡¸¸øSÇðñÔÔÔAjµš”——Ÿi‹? ­ `MMMÆ'Ÿ|òoW¯^½.gðjÐÑÀððp¬Y³æ_o¿ýöZÜ ç°#FŒøŸ+V¼.Šâ-;exÓX<Ï£{÷î]'Nœ˜ iûöíÛƒ‚  OŸ>}Õjµ¦¸¸økëéÝ»wÚºuëÆ÷ßÿ]y(}¥XØW^¯×#??¿(''ç¯nHŸ¼yóæ¥Z«Õ*ë7§Nú€¨;v|VQQQ%IA`0´iii‰%%%§¬V«à* ÔKŸa˜L¦æÕ«Wÿ@ÃÊ•+ÿuîܹ¯eú–Ôñ‚¢ üÒÒÒÓ999EñGÉâïÙ³g¿7.‹‹‹u¤{¾]V«III‰ÉÉÉÍfóÕ;wIN!;; ÿ©S§ª¯^½ZçMD±'"zË–-»ËËËÿÀÔÜÜ\µpáÂÕ®¤@[¾EQ V®}ý­V‹êêêïfÍš5¯¶¶ö²Ý‹[³fÍòôonn–ué7!‚ @£Ñ0S§N@UPPpÐh4Zíuð˜1c3 ƒ’’’2w!o Ã0hll¼±råÊmÞM3n×®]û·oß~ÀÛ„OÒ~‘F£q!Ĭh#ÐF÷§M›¶à믿þÂfôÑ ¹¹¹oŽ?þ!£Ñè5«h­ÃAÀ¸qãFêõúž§OŸ>ÿÉ'Ÿü;,, „ð<=zt7 úÏ>û¬Â“:´¥E!//oçÙ³g¿@ët: EQ*ÍK—.]ÓÔÔÔèjÊÚÕûT*®\¹R=f̘™Ë—/ß­h#eY‚ <ýôÓ KJJ>¶£{º7ß|sîSO=5±¹¹Ù¯ô‹ã8ôêÕ+nÒ¤Ih,((øÙ‘‘‘šqãÆ=pèСϛ››9O¤€'õ`Yuuuuï½÷Þ&|çÎcŠ‹‹ÿÞ»wï>PVVöEnnîFOýÒF’’’&î¾ù3(ZÖëË€R©Tá=zô˜påÊ+!„¼òÊ+Kt @ÔôéÓ_²X,¢Éd"MMMN£Ñèòhnnvz˜L&§!„9räSýµZíß|óMµ ¤¥¥…BÈÚµkw3 3òâÅ‹W¤ó---Äl6»=,‹ÓÃjµBY¾|ùûât~þùçBÈ{ï½—kkÎQQQ •„Âqáyþ–CB!7nÜhÊÎÎ~¦éž¶¶ ƒmk>¹9ðxCCY¿~ýFÝmÖ¸cøðᬫ«k6›Í¤±±Ñ%äÅb!F£‘2dÈ$½Þ~ûí „ÒÒÒBA /^ü/Ã0#×®]»[:ï DQ$5555}úô Æ`0$^ºté!„˜L&cRRR€èiÓ¦åBÏó·€@EB!§N*2dÈxQ¶ADÃnoF¹¹T¥ÓéÂŽ=šŸ““óݰ x`óæÍoéõzD÷‘'P„‡‡3S§N €Ù²eËᦦ&ަi‚€ØØØ˜¾}ûÆ|ñÅŽÖ¹7ꀢ(|ðÁ[«ªª¾€¬¬¬Œ¾}ûöåyZ­6|áÂ…9"`Ó¦M{ûì丸¸8Çh&©Ìž=û‰mÛ¶}\VVvâûï¿ÿ.!!a¬M¸9=.Úú%Œ¦iÃK/½4ëÕW_}1""Bg«‡¬³D²¨žçUÔ¦L™2mÁ‚óœuZHm04Ã9ŽìDµZM'''Ù¿ÿÉÚÚÚ–ÖüŽ×Ôj5*++/ðÁÛà®»îê7kÖ¬?¸z†çyèõúÈ?ÿùÏs„Bøæææë„“mä[;jzõêuÿÖ­[׿õÖ[¯FDDèÜÆ*ÁÄ`|ðÁ±«V­Z€r5»HH׬V+222»víªw¬×#ûìSHOO™’’2ÌÙbÖ@€À_…ñçËýèÏw ‚½^Ï>öØcÉ[·nÍ;vìð4MÇÌ›7o¦;Ù–˜E_Ÿ»mh ¯’ÀÛo>üÞªªªºÒÒÒËT'N|tذaIÎRØ»$P< ôüÕjÅ!Cõz} 5˲1/¼ð _@òy]yƒ¶éáèaÆ݇›QÎiIIIƒìGGž@‡"muæO(ز©ú÷ïÿ[=æÎûGw»Èm‡ ö’pÏôéÓ'%$$Üç*ki(¿°o-t2ƒ¶|»¥¥)))C|ÇqE±ÍÖº¿Ú hh / ©•öÍ-.-òð†²Ú%Y´?¬w¹ßí,w¡Rr wø ÌÈ¢`APû”Yè-hƒŠt€À?àQÚË ¤È" ¨$@¨À›N»ífi‹«LZÞ\“ëY_êåîz[Î{ò=w PüÒ0%Žþö˜U – ¥o «”ÛAÔ‚ ¢í1ÚCŠß3¨£W IW°R¥€"äDøÁ¸Tݛߢ›õL P¼ hÍÌ •mb;ü>P®PA‡à6A‡ € ÉÕÁ çÛA½. Ôh AÐA&E ‚ ‘ .tÐ@(3_Aг€P£¡ ‚@„ìê`©®p²—]äq 9\“ ²…Úv¹###Ñ©S'8æÏu7…ÙÚô¦´ôÜ—ç½}V¡EThš†Z­Ìfóõwß}w¿N§ë,Š"Õ–QÐÚbζvž'‹OíßÓZ4p{Ð3gE£ÑãÇŸÂÍýe©åë£(ŠÒjµŒ^¯jhhè,Šb´7Àr·;V{n¨  B4SuÀO„£›HRr4$EQ”Z­f†a###ioŒE«Õڦ͒¤4ïþÜ`II £(ŠAÀBDEH;qIQFãbs²Û“gü½¯ž"EŒÈ¤nCQÚQìÊÿ ßG-Vý·\¬IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/image.png000066400000000000000000000517061217176075400231570ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFHáIDATxÚì½y°gÇuß÷9Ýwùío›y3óf;¤H‰-Ri-–eË‘C+.EŽËŽ;‰“T⸻’*G/q¥WÅv\JoeYŽ,S”HJ"„ˆ}_gÁ¬o_~ë]»óÇÝú÷X$;%½[ÌÌ{¿¥o÷és¾ç{¾§¯Xk9º~ï^rdGp4 GptÀÑudGב]GptÀÑudGב]GptÀÑudGב]Gptý®5û>,Á÷ý£™|§.òÛþ™I’¼Û1Ôë-€x衇î{ðÁÏäynEk-®Mþ÷Ñõî^DPJýŽÔaÃz«Ÿ{ž'<òÈõ/ùË/ÆZk=Ïó¼,ËÌýØý•ŸüÉŸüãY–Õo|«ÿí´àß®ÏúØUow½“Mð^^sx³½Ýë¿Õû¾ÕçXkiµZ|îsŸûù/ùË?îyž‘ÔÓZ«,ËZJ©0‚ok¡ïd²ßé‚|»×ý›\Øß ãx'‹óv?{;ïûvcææì­^žç…@WkgY–zåw¨*&T •¼Õ]~û…y'¯y'¯«&A¤ŒVßjwýÛ0ë¬3nqF\ÞGõûw½ùn¬û§ëE°¶üœzçÿ­¤Ø¸¦øE=g¹1c]ð.ø÷Ž¢óïî«°yÛ°îv·ÖZ´F³Œû+Ÿ+¬ëPX°¥­Z@Y°RüL!õ®µÕ—bÁ”ÛAlmâ¹€®þyhsÛCûYªï´Í62sÛÆ¯²åÈ”Dª±J½+A,R~ºuv¯»ÅùÓÝÍîW¾ÉyÙy'T|†úDæ<†µåÏ¥BäÒÜ[yßRŽÖñ5Îèç¿P¤ü…àØü_ÿéÞ2¤V÷Þ°ˆÐ¿í“Å‹”*`Ë •j`åÊP€AS­œl+Í"» Ú˜HýÎÆ^ÊXLi8Ö̽¹ø‘Ú0šñU S}·3qR³x_5}RŽA•ÆhªÏ°ÅÏTip‡ SQŒµYŠbòP~oa„Rþ¶Ø¶4¶j¡Š±ˆãQ¥%Z)Ge¥1@q¾¿´t+Å&4RüÝ«æS`™o‹©¼oƒ½jÂÄ8)§ÎZt5ªr&¬¼r±­Ū2ÖדTܺ±¶<¶X¸r¥* Vbʵ0'­š…ªÍ§~Oñs‹QŽU•ï±õØË…næ]¾·6iŒCYÁªbœb+ïÒ,¼W¾Ë`[¥±å½‹©h¼S½{¥0OaÅ ¢ê0.ÒxÂH aD•c² ªþ¥JÓ²Åë]ïí®õ;ÂÕ[uii¶z£-­â hƒBT1QR2 Ö6ŸS|¦*&K@Iåÿç]™®MÝa¢4 AŠ5—Æ…!Y4`¬;öbÜM ,lFjÚ„Uío)oo™ó—ÖSïk‹á¸CƒÅ+¿´Z¸âõÅ„èr2  ¤Øíªô¦œ°flySåæ.wŽrb 8n°Z\q&TÕ~¦ò¥+/Qqë«ÝiÀÁÕΕz—WË:ÑWÊ +¶0d'R)Þ_…€j«ê¾Tñû&„ï5µÁ7aÈÖyùyŠâƒTe>bëûÓ¥Ÿ+>ÿí½û› `>çœOL”8°©ÚbÊx]M¬Ji,ÚJí*+ãÒ=Øb#a„ÂH*ßXÆóÂê‹q&Ø›¥Û­6±BÈm³¦Ü‘R¦šÕ®¨<’XÈ«×T Ñݽª˜ÄÊ3U8@W!®Ü­ÚÝåÖVDsÖàŒ0#&*gµ4b¯ÚÑå˜j+wRaq`ù=ª =R…­<÷Oǽ·Ím-H™[*) ÃÐø´j—«òª²4;9änK T»5©&¯r¿Å’KiúR{yK@7~ÔñªÆ-ÊJá¦ë[î\±UX)ÍIQ‡®ÊØ­’"ÆV‹-碊×QªšRRi`®WOVéõÄÎ/"gª¡µ”î¼N\Jüe-¶¼qR©çÙ uõæxOP Fש%`Ã,ªþb[ZZª ÅîÎË×T;JÅ|©áY¹.â-Á§uîZj bëØk¤ OÕä—^KÑ,*eªœ.½Y^®&“ò½”Ÿ£+Ÿ#ªÉfEÞ–jô!H¶ª Íb)ÛÄ&+…‘)[x-Uf@"ë¯B…8™ 5hmòå,–Å¢$?ÐxŸÂu*´hYY[ƒ@Sº×&ã–¹¼¾A¾¥WqÐÎgÇJ€'Ì‘Y«¬rdEclõâJ=YÁ·B^îjUîÇTF»Š4!ÖÉá­È\Ö¤Jƒ üÌj~TmVs6VYx:loK½­ªÊ7ë2žÔ³rGbë…­S-Û,‚uv†*zå-Š™2×.±‚TáæÇ©A—”è·Ü"è’ü1•·ª_kÑ%j7ŽáUß%PÄkꬆê?k‹û¶ÅÎöJ_ed>™TªÌ>¤HÑ”‘2&»³üNQä¶r E¼×"ä $¶æ1tå-œÍc¯ˆ8‰µ4ÆXLõí©ño +~Ù+%/w²©™+©Ýz›tJ[‡±s™¿À)t¹ƒUµçÄÙ]%{§Êت”.u Ò%‘Rr ƒ#B^‡1Û„¬r‡›pŸQ¥²MØ*¶r²Sx¼ÊÍ7©ˆã}¢ó@Ù` å:)pµQª¹ÑJJ *uªjÏ.MȬ²•Úû•ó"óiü{Ö;£æê¤˜jãæØNŽÞ8bE^.ˆ8ñQ—Ä­Œ¦D»Ôÿo¢¨v]íŒmvR“;× ^(|¿_íQ«Yz¯&TÉcØÊïc(³q2U¤WVJ/ ˆ RÄÊ;éÙЏnÊñê2¨r˜¦Ä3ZQΛÔ^ßxéž”ˆÅa[â7ŽWD–w¨ ss\°MZdUÊéVVa¬Æ2W”Pu¨}/ M(%:35ãT¸ÆšO/­Ø*[[z• i[Ú³*nV¤™œ‚Ò,ïÇ6¡ ©348¤…ªÌñ«¢lañ[lY’ÚCÙzÁæyu;ÇÄUãÖ¥Kµ¡SíàÚkˆƒÆ5ª*ÿ:9{U©b«Jäo]^w^Ê‘©¦t¥K/d¤*º5i ª+VRçè¶ÊxÞ)xKŠj@ -Y*±N¥¤Ü(™KŠhí7pާʺ٠bj«®¤úGRñðÊ 'nŠêz"ÕxNið‰‚’Š-Ækm5ÞµZ{¸8ä¤UR€OTáêa¾èTçÛ`,wž®Þ9ÆWQâ5Àsê ¦©çÃÑèª^(®±5YVA•ì©2ï/(§[Å%S1Ou¼§ ¡'ÔIJŠ$1eŒÓ–&†–( J®LUá¬Ãe[wB¥aÂP¥7²Í‚T%Ôf1JF³æª|»ùÞÊjlÍWLžÃç•®¹u ô]ŽæHä&6‹‘¡‹cpFœÚsEž"sxJÊtX£êV4ºª2"‹“m½Ë,ÀX'%ÊÔk¥vãù©Ô=MÙÝÍd•³ Ä3Vœ‚‡-†¯d>†QbŽ*mtœu½° “& {XQÀn®.óã°5¨ReU­tû¨2=µsƒk„Jåêº&¢šO–šBW`Mά¢ë°ñ eHm#5½-µ–±Iøæ•;‡c¸‹oÅ)çé9n¿IKåPEÖCÍi1T ßgÊU«µ¤³¾j “:Ü¥µª$Cœ:}euUÞï$w]]J¦J`eJ'ª©¿ÃÖ˜£•:©«T5‡÷¥6]ÞQ®šâIÓŠ»¨R“2UªW‘>ðJ!¨r$uA£h ±£êI§EݽmvKÕ!N%µfáhèT«*=}#p±Î®ªST©t@.õÔ€GU(y±V7ºÆÒ%Ö²ÄJHêÔ>,JZ9†­­ËvºÆáIÒêl%Asê.ê}¥e‹XÇ•­é`'‘«wµ®%\M5 ·„Zɬ˂ŒXqD”4òqÛhì¥GÌKÔ¤BêådTÆ¡+æ°Òö•»]9Šã9EÅš•{ÜTu qKÌjçTÅ)¤,[¼ÉZYV¡6RbK\s,k"¶•Þ_5s„­êÊɸl‘úÖ’=æÄ¨¢dNWñÞôÊõÍÎ×ÛW\º‘{䋨pI;q´M'Ž’& R¥{0N¯Û› A\~©°ÕZñ'Žá;G–Ds½Œô³sgHÍFº © —ZhaÞÔÊèœø!¶®É×liÍÝ+©JNÂÍ5p:&enç+‡ïçÀ©KËUÊß/ ™ãçòbk5ËHÁíøs£Ì«…œk}®€‹uZQ]!}%óÛìm\`éÒçùà‰ãi›VàcSak/âùëCÖ/_cë«ÿœ…ø3ô}²,­É•&h²ëÄk9´ckqjÝâeçBAÓŽE#]SJ›àWknKé¼(Æ6s س̋R¬#Qw«(KïΪóèì!M~%~¨ŠëºA"Q[ï%UVÌŠ .åQrè¨å6ì\ù’C"L9o*{/ Ú¿Nû¥Ï³ ëÛ ‹=NKØÚÓë( §OãÿÓ_fõÙmþôOý>>ÖT¢±¼nÎ"΋¶æDds;¬ ‡VÍ ŽVϯZe›øï&!M1knc8€Ï-…;e@×¾EôüŸï+à´†©ºš¦ê hhFik‰KPØyùVÓukkÒÂ<în·Û¨W’¬ã?óó¬¶SF3Ãt4¡ßé ÒfsgƉŸ•A‹ó§¹zcÄ3‰‡ÿÅGùþÿ÷ˆ&iY|qNª]ÙHšçÆR‹£œ“K 6ßÚÆ›¦Ì¥šÅWnô› …ö¾˜šwuâ†!+s,mU ²Ö¼èX“3@Ûœ¤ð&-©¸]±¶‘n+P5RJ[u¨¥Ëá Üò³Ñ>zçuÚÏÿ ž“š6d ‹ mâ6¶Æxʲ´ÐbßçôÉ÷œ_â™ _ùÙƇzˆ•ÕU²4«Sʦ[ðoÊ„¬A¬!×~3Ò¨¢„94Xró‡bÍ5Ï:zF—ÚžËÿÊ«j™+C+ïa›>††Sú¶—úÖ<@ñŸ®:]”?UK¸”ªØ½ò÷˜ðTÑ£®TÓq­Ê|\ëòw¥«RJЪéiUõ¶•17ðI6/`û9˜í„>&MÀ䬮öñ4äyÊ©• œ][ ô„Àº. jÆS_ú^ èò;”(ç?A)]Ž·øSkÒ­‹³TW«n"…(U¤ËÅM ”F”F”*æM©â^”T/) 9%XUìT-…ôMK㾕.æEtñ~QÎϵó™R¾NY”'„m!èAû}é¤nWN®.sÔ.µÛ×ó$whì¡­kÆtQl¥Ô©«Œå—ií3n“>ýKô$Çx>ZQ’°Ø °YÆl’0ŽbŽ//3M‰“ZŠO÷h/àÒån¾òY’£µ.]£Ì3”=s©¦ð«&ôF—ïJÉæ™`3§x.CžpHLã N÷Cç@ÎM~©­ P^qʉ§I W_}± Óñ¾ã{Þè´Ø*[¸SW«œc]œ˜næyMÛܤÌu¹:÷z¨ZWHÆ ÕmôÜ—è'{è^“¦¤™Â*!JR¢YÆÅË;äbxàÞ5âÉŒñ”½a‚ÒÐéúL²„­ë7ÉÒŒVKcL³˜5·o¥,`¹gûŠs¾³ˆ®Æ¯æ÷‰*+qGϧ{æpQJæ?ö¸Ttùh†¼TÍ]{ù/<õ0»78yòâõùÆç +I6å§þ£WÞ]0—:(Å•â+µ¢Gì|÷«WÆC3wÆKÓ R÷»NA¹½{¶iŠ…ÂÁ³ÓÞ~• Óå`Ñ|&Ó?PÄLf1|ð Yž‹‹]¦QÆ,ŽY[îrËÚ2—»ÊåW_á žÎw=¹ ÛMÖ6¥n‘[‡¶µN—3ŽøS,sM&îù¨Ú1¾zát*\—0i´=äò+O1žÆÜxíEF{W¹üÌ“lm^¤ú<1M1GµM6Ë8ØûðVªQë”*«IjÚ¸¥. ˆUn·VÝÌ@U ;ÄìÔ}ýîAÒ(Y)É&©Ž¤ “7žÃ»ô^—$³øÚ£ã+bë¡>`rúƒ§OÈ“ß×h_Љ““ÄçOãòñ]~îoÿÏœÿéÿN·‡Éí¼ìª*@9BMlYVuìÙ­#Ø9nÞÑô7íõQrÊ9b×-‘×B”2üT;=KàÒ‹/pååg¸yåe.=ó[W­Ð¾ÅÄQ”Ójµñ{šn¿ƒ¯P9I8Ýþ¶Ï.ð|ß'Š¢oÙ¨ì|`]ÌuÎ*¨] 4Ô†8t¯q³ÚŠC¼¸­c¶öžž§™m_A¿øÅâfEaLBšf¤¾ŠNKC–c²h0ç´ú-ki>IbeY„K‹ŠLŽ/´YQºai:á¥õë˜PÞVéýA.ÍiæøëðÎE%ucÇ|ü|7«z‹£·ç0"åyd³}Æýk%'ÅÇW– ãO"LjÛ>»»c|„ׯlÓ´èöÛ*$M2­ˆ“Œ¥å.qœ°½3¡­+‹ÿÒ—øž?ôýxZpyJuèq™kÓÀ9±ÌÉÅçøùãaç`ÓÁPËRµ«0ìpñ¥'yâW~‘7^~šÉÁÒô8vv­¡¶ŠsÄÒ^R(« Da¼,áf¶Mtp“õõ~'¨Oz}× ÐÖàðІKçÔË‚4r)[§?¾¡ÄëR.sÍYÊ&“’<ûEÔh“´ßCÄâ{‚Vš^¿E(péê.n0h)¾ô[¯ó‡>s?Aà‘%1Aè#™!ŽS°–é$E¡éwέ-óô×åµ'Ÿã¾?@žè¹j &‡4/-çäõªQ"Í·Ÿ½ùq57ãPÞ"àërÑ-Ä“˜'~ý+¼úü#ܸð4ÓÝ+H” ¬¡×Q,.®pb°L†,öB¢É”õáqžbÓV[88ˆ&–Zmlîa$%èVNùl^½O=Àœv¾9•ÛÎɰ Ö‘K»EVûfÞèÐóª”ÄSŒŸÿ“k¯²°4(O(+tû£YŠ5†g_ßâµ761IÂÊù%üèí|ìC§!‹|PŒ¦:l‘Φ$qŠR7÷G´;>6²qõ*ßù™¸òú&»ÛL÷v‹æÊvÈÉ3ç9~â~i 6kœçöÈ!✮a§Þ¡ ‹_o­oñê3qáÅÇo¼N¾s•Žg9e–n=Çx2%"zÁÇÂ5ÖN,£rËt:%¶SVÃÂÀ'Ë ¯Žw NdŒF9¿í^¶7wˆOÍHí³–ÿî à0`¨dÅŽ/jÕ¶9¿EêcQ\âÓ:µðòÄ1æ»]«g 4õÿÂõǘ7žfq¡Ãr/d%…LÜ Yš²½=æåK7Yì…<ô©óÜ}×i°ùÆU8¾@Š0OH“„¾O;Ô¼xa—½)ŸúðYž~ù 6®½ÊÏþÝçyê+¿ÆdŒ2ilè,whõ9uÛ½Üý‘OqßÇ~««KSly“Ï»ÿ7ç{ÈÂV×_xü›\xñ›<óµ_‚ƒ}B_8½´Èù[ïĦ–Ü×|øÃ÷²{sŸ—/^déØ=/`i¡Íhk‹4‰HÒœnâw|NŸ]#Ž™F áа7¼ÆÅý›üàǾ›áúˆÝý ¶‚'¾=|»Þ1ëôÍÏŸP ¨¥N‹šŽ6;Wý§y£*®„ÛRe[¨Wr¢W‹<Ó^,Pz'ðHÓ¼,").^Úæ{?|†~øQ–óK¿þ<˽ùÈmÄÖ‡,ÂJÑ¢.(üP‘)ËþtD”yòÒ[ïñ^üW¬O¦¹%\ÐìïfhOH'#¦{û\õÏ|åWX]»s¼—¾ûxà»>A§íGºå¥J©Ä0ysd Ú?€8†g~˜Wù2Wžý:}ÏrÿÂ2 'Îh:J“ÆžVÜvû9Ž/ô¹qyƒ³«gI¢ºK!^4c¼7"šeX`f hÒÉ «„>xW_]gs¶ËµÝ«|鱇¹·–¯¾Áõá·÷º¬ù¾ÉR¬E—æîdzåM[çq'ó‡ÕA§Ôë>”Áº-LE¤„øõGñ6_¡½ÐÃbÈÊ3ù²Ü0èxL%ãösKÜqûqR„_ýÚkÜzn•Ýy ¢I„ï[_³åLFŒ'{<öÒ.^ßÃêí)NïÐo{ºG{Ñ@ä19ÈÉuFšdä™E¬¡ÝF{yúK/óü#_æ—OrïGdùÌ­Üý²²¼ŒÂE«§Og€ÍÙ¼¾ÁKO>Â+OýéÍ‹ Ò{Voae¡‡IRzÇWïàiƒøˆR„¡Ïæú&Y–’FÖX:ZØÝÚ%M-“!ûÞf¬` Æ“˜[ÏâÖµU.M®¡Û)­=ÅëWÞ@Ýqç¹Ó,,„ïO¢óæ0Õ9÷Öic ”ÐHá#ÎÓ@´4­ÐµÔÊZÐ>ñåÇ™¾ôžBN¿bâ8#Í2”{Šlµ…ñ<^¹¶Ïdsæx—È Y”2›ÍÈrOž¹xo<÷yš‘˜Œv'da¡Í€Ø²¶ºFÞ͹¸q?mqëRÈ¥íë,uzÜØÛ¥½X¨uࣵFc®½ð,Wžå{œºã6ÂV€à‘Î"Ö'ÌÆöÖoàå;|è–[¹íÜDã”Ü¢hBš ½öá³$yF;3„a‹“mžú/_¸ÌÕí}r+dQÎÒJÈñãAª9wâ)¡¦YÄùãÇïnŒ9ÖZâÆÆ>Q”Ò[äIÊtÑò|´¯Y<ÑÅki$ƒÀn’n†Ó¿åóÜ×^'}’,çÄòŸº÷;Xí-0NÈòÏ÷ik±+P­J+¶OàûìGâÙ« ÍSL3œ¤,´–X6,, ~ØE)Mÿä³ñ˜ë+[Œ®Å¤3C9@· ^z–—GüeþÎ{5 6Ÿ?ÑÂí~µîÓ¾¬sVÎ|ûÎ[>í¯âÏ•"‹FŒ_z”4ŠX=|QLâ”À÷ÈLŽg ¾»ã˜83Å9y^È™3Ǹíîó̆#v‡#~ãñ¯óÔó¯2žÅ䯀RØr““eYbé÷-‘Ú'N`ogí -Õãõ}ÆYš2³#Îß»‚îY¶3:¾à…_kl¤È“¬À±#´;>ãQDè‡[ìÒm÷øîÜGÛ(thé-¶0¹%Ï ÃaL°ÐלQsáÒUV—úô¢IBÇh¯xðxœhžÏJ×#Î-ñt†LÛÜœ’ú–0Pì÷ùðÚøø Ëææ6“YÂ6»\Ù<`¸½¿,@l6w´‹ÛÐdçH·=h^1ªW#s*´»¯=Îló(XX ¹±±KwÐØŒd2e¡×¢ÝmZг”ñ,a§x=ø—_ø*Ód³¯^bw„  ¥3H-Ú’L“Ìr¢IFÖ³ô—©Çí”ɦµ²i]À²¶²„ß6ììŽI‹×Ö¤&%§ –°åMR’IFšüP£<á»?r;v–°vò,'-¼–‡Fˆg ÓQL% ʹ¾¾O’%tÚ-”öÉsÍöÍ]¢ÙÝÒx0`<‰‰g¾6ˆÖ …iœ2S4>Ûcö§Ú >;шÝtÈ`é'Å«Olsåå½oŸ¼Uwp#æ¨-Á‚¦8‰Êíí«$_b‹ +µzÆÔÅ‘òia’—•-ñÎ:û¯<Í$‰Yi·ñ|Ñž¥ô]"àõ7n²±µÇþxÄ“/½Îh3Kã‚ñëøX<_t„,Íð­Âo Q”±ÐnqîÔÇ–4«‹-¬Z ¯\ÛåÖÓçXßÙc±r0œ¨’”d=%Ï Uo2ÎðCEšfžG>3Zv°å9Ó8!B½%zÚ/xOð_k¢YBbSD ;›C<‰ :>'O®2›D¤QÌx¸äà·‚–§åQôB·å£­e¥c|!šy´³cܸ±Ï¥ä2{ù‰nÒÒ`}ƒ×z_¢P‹ªôsU³C¥xu+*VP¤8J½8Ä"9ÍùzµDÜÔç×YeØyé $™á‹¢Õë2šeœY[dkk›á7¶xî•‹ÜXßå`<%7ÅtÆXº­vK#Ê#ÍgtÚ-ºVïu¹í–3\¼ºAh<Ú+†3§ZH>£ýz>ËK1_ýÚ5¬n£û)ÉA„A’ZO¶ˆF1if±©¶|lfiw4Ý MJF’eX›Óë„\ÚZç#§ï`k{‡m?äžÛÏ`- G¢$Å¢ÐJx)n›•µU²ƒ ÓiŒF“ÙœÕc=&3â,EÅQ–Á $ISÚ¡f66L¦1Ê׊Ýí!~‹Ô‹Y¿¹ê)BF;–®êòÀ=ï~«þ11vž´vžÃò9cëgÍIÈ«çäŠÂÓß÷QÊc¸·Áî•×ÐfÆöÞ3;åå‹1ÆpýÚ6×¶PZÈ’„$¶ô—ZøXÚ­³8!cÂ0d:žâµ4í–ÏÝ+k„-Сb­¿ÊýŸ<ÏóW/Mw9Ù=‡Í-»;C¶Fn]ë’¥†óç±p<ä…Ë×ñ´°7žÑ^laSƒÁó)Ÿ)cÉmÎp2ãÔʾ®íïá)…És’YÂc_æ`äiNxäYŽ'iiDetúÓYÆÍ­=Nwq[ÿa+ä`w¿e¸ºqßølÞ1žÌxòÂU–ΦŒ7v‡Xß2>0´TÈT圻m…ÁbÀpÓë…´aÃIDàiƳˆ SLãœv/dË\go¸ÅÂâ"wöÏq¶s–õë»Ì¦3V»$]àxÀkÏ_xw pî¹õ¨1@ƒæµ Ëá¾³‹,ucþÏŸù%¢IJ¦C†{›ô¸°~…Ç¿úU´—‚2Ù!ðücI’“Æ1JÁþÖ˜“'úX|¶Æû´ÝžÇâB´0™L #Ò4£O{©KJÊBg™~»Ë₇î¤Ì¦:е!3“ð•×8ÑY¡˜œíñ.Ÿü®U–—nìï³Úksò¶€×¯ðñûO“ =^Þ¹LWµ8>è“[¤?åæh—ɰ0úÞq +ƒ%¶·G º)‰Œé{mô¢% + ![»#®ÌvùÀÚâ&¶¼ra—ÛﻓmØ[Ÿpcý€Y Ký66Œ¹re‹$V]Žu{$jç¯]e8¸gåVŽI}6RZ',½æ`4#ò2FÑ”‹j{–Ï0Š8ÍX[]ãøB‡<ž1‰¢ÄGÐkw8½Ø'fÄqÆæh›íñw„kôó6›6¦{.äž…3ÈÄ~Π_h¾ÇãˆÈLZ›PÆ2ŽÙÝŸO³÷f"Š,‹ø;í¯pÿgùØ'îæÕg¿Îxz F)«Ë}î¼õ ¯oo“D3†Æ[cú tWÓn·¸ï®Ó<ôÐ÷òGŸaoë:w~úSl\»ÈãÏ=ÊÎÍ!'|>ñ±ï¡<`÷«ôW¸|ó&_Ù…@sæxž:ÁŽ_{êeÆ1·ÝqŠ~Øçû>ôƒüùÿæ?#šN¹íS·ñÙ?ù§Ùã ëÏ>†¹m 5XæWùW޶¹|}È(2ÌRáûn¿‹,hN|âA^zùÖÖ4kgOñÅ/ýEû„au%dµ³€QÂÆð&á´ËÉÎqN,æ¤vÌî¾Ðó;ØvÌx7"8&ì¤C¦bè¯†ÜØÝfm©Kb'¬®ç–ã+ܼ¶Áþ4¥ÕñÑ*Ç‘òÒÅuÆyŒò„Å^›½Í 6øøí÷rçÇ8v gFJSö÷2ÆÓ™5´úm<£ˆ¦íå>ýˆƒƒQô. àp¹µ¿dú}â¹WÙYOøƒýNœ¼…›76¸úú%¶/^!›ÆìÝÜ£ß]àÿÉ䨱dIF¶19ةLJïþ0'?ôQ>òÀ§{†•îû;t”âÇ>û£ìæ1k?Òçô¹.î/þM¾ï;?ÁÿÈg¸åü­xJ±¾±Î… —µa©·Hwñ"šGy„ÀËøßÿ=ü¥?÷§¹²¹Ï`qÀÏ=u…‡¾ÿ“œ»çNþÆßû)ÆvÂ,ƒÿäOýn=sžO}×è ú¼úê >ó™ïÁ$•çŸàü½§QÁ€Ýk,¿Êmí§î8Oº?åØ-w³5Îiõ4ŒGüÓð³´ƒœá4"Š áqÐ-Ëtã)M <»ÿßuî.8~š.¾ÆîÔC«‚š>vêÿþ_øcœè¶Ùý/ÿ:#?$ŠvÙn2¸·Ã¹å%ÖŽ-rÇÉ[ˆ&SÎ?p–=ø ¢4aýÚ6£Ý _ý…ϳ½wÀéã=ÂÐ/pÀ4egøÝð݃À:á³–ÿö?þ¸åöÓä|ðüý|ôî»ÈEÓÿþSüê/~ž/]¿Éï»åúßwŒÛÏžæ÷}ì;ØÛÓmwyñ¹Wšœ«»(¿ÅÀïðòSÏO§´Ú9+Þ€ÿâ/üI¾úäóÄøÑ?øû¹~ùYþÔÿ,íÖ" ½^Ø%JR6nŽÁôñ<áÞûîä›O¾Èµû|õáÇY¿8âÌœ@‡6.¿Ât<Áki:‹n¿õ4ÿá÷ÿÛQʧ>ói¸û¾ò…_çùQ>ö©²»¹Á‹Ï>ÎÚ‰[P^ÀGテÅz€ÐeõÄñÆ6½ÿ.de‰ôÚ„swÜÉÝ·æô-ç¸ùÆU¶w6QìL¶ù¯ƒ?øÐG¸çÌ ¶f#®^ºÉŸýÉŸäÑßø _záî8{+DrXÌÙÞßäôâ=üð÷|‚.ÜàéÇLÓ”^,¼úò Ùy…{>úÿÓ_ú«<öðWù[ç0Ë wßy7KÇO³rÏù~ÀÎd(ŽxõÚ˜$1|ê¡ßÏÚÒê»U&L®ï]à¯ÿÕ¿ÇÝk·ñÃ?ôƒüÌ/þ_ûêÃtÚlj¦cÆã˜?ñéOû)O¿ð,ÿê‹¿Ln„åÞ’e?±Âˆ)O=û‹­eÎßzްëñØS±}}‡+W®18ÖåCwÜÏ?ý¿‘g{žÝéý£Õî1‰3ÒÜpcãÏ<ñŸþÌwóÚÍËüíŸþ»lnÅt[mŽ­¶ÙîóË_øEþå?ÿ×¼rí ¯>ù(?þïü»\xí%&›|ï'?Êÿó³ÿõùßäêõÝŸû¡¿Ã±~‹ŸøÃŸæå§.óùo~“ȃ›3’VÌ©c+l\;à'>û£ÜÜü&_xšüÔÀûÞO³vëY.¿v^¿Ë,žrõõ<øáÓ»Ÿîò½Á1²qÆlkÄÎlĉ[Nsixƒ}™ÒoÁ¯}íüÊoý:ñ'þ_xü‹\¼v@ØZDf–«¯ïá劽Q¼Ä_þÿ ;{7xí¹›‡|ìÓ”ú¾ã¼ºqÇŸŽ ôǨiÊ(žòÙ?ûY){'ÞÑšW.ïЗxìÙëܼþó¬ž]€V—K—nplµGçÄ"ÿâ×~ƒÝõ.]qñ«‹]n^|ƒ™™²xõÊ k˧XO¹zí*ßußÜsþ..úüÒÃ/Òi __z;n=Áòé®\Ùä§æŸqjí>ñ(?ø½Ÿá™—_`©ÛåË_û¯ü“‹¼øäMt; i ‹½.¯Æxê‘ml±xj­‰âÏÿÕ@ 3ºÇ|._ŒB›¤L†S>|߇‰±IN¬:„JÑïgo;Eþ©8ÖoIN¥L¦ J Û˜æ9?ø™û™ä\½r‰TßÊ˯¬sÿÙç–x¸Ïñ3§yqp‘­=Æë|àŽ5v6¯pÏÚ)N,/qÇÖˆÍ'xé•F“=^yæ >xï½ÜvÏÜÿ¡{Yôظr/üÚ#<õÌëÄ©âþûN1fÔCù-^}m‹Ùd“AÀR¸F˜Y^ߺN»½Àþ8£e{ؼ8¬*›X^Y&ÌiKÌÇü0qqßýw²ºÒåŽówpc{Ÿ$ÞÆ*És²iÌþì½AŸä`mRövöÙ¼<âvÿNî¾ï.â»"έ­0bî=žïá £=HcFã O<’$Å òÌ0Xà‘‘²¼²Àñå6Sÿ ‹ŸýÃÄI‚xa “E¨öˆë7ß«,ÜZ´§è,$EÚ÷9×ép~µÍK—oâ!Ça}k›ëÃ+>w®•çìŠgcD[â$cg˜Ðk‡¼vs‘ryãkä&EZ9˜ßñÁ»ë8žjóÜK3F³›<ð@ŸVëÚË€”4ÓÄ3Æù;=‚Üðàw~'ûû|ó–7X$Üu»¥¾A6M8}ºÃgÿÈí|øƒ1[›œ^ÓdÆò½Ÿ¸‡áp}k›;̲"‹& Ÿ<~ÉÌ’JÆ ßãöskœ=¹ÌÁdÆ3/½Æ­k'Öhw´ÌI"py;áÙ‹OsÛ-ËÜzê—¯ïð7ÿ—Œ§=~ü³ßÃgVð’wøÍ_ycŸ|ðADA笇'ÐJCVV–ñÛƒÞA<qùÒW¯m±¾s€Bˆ“”n' Ð]žV$“nF{LÓ˜`qF ©™#ü¶ÇârÆto÷ÀõM–E|óñ¿Q÷îY•Ñîh¦qNf3< ž)ؼ\ñùoHZ,÷ýâh›“åÂb…¶ï3šî£»3Ýg©Û¯ÏbWxå•GÕ"1û„aµsi¾Ž1)³ÙƒÑ#“mövž gFdf(cý¯Þx™§^û"*ϱ­? fYÌ8³¼¶¯ ½6&͉PôþŠÁLR–,{“1Þ8«˜E‹ƒ KÞØž‘Z¡³2äxÏ@2ñZxZsaÏâù>Åžn‘ìÌTFÖ5Xíó•ǿ¿ø}FID/ÐX«È•¦¿ÚGa§)3›Ñí PFAÐæ‹O~™,IÐZ3[Œñœ¥nò“ ¾ï¡”a6“JNt ÓiÑ„k‹vSÁ䊽=Ã4z‚)Uµ/^¾@”C¯Ý…âĵ<Õø!¤iŽß‚TA>+JEûûEÍHˆÆ@û*~6…ã š [QN’CÛ@Ç/D§ƒ¾-QdÚ>(í3™ŒÉÉ ôÛÂÞØ¢‚€Å@3c–ç D)ëÐo^€ôz¡õ|PÛ'ÐX6¯Zv·oàYÈ|,.zã2UÜsmn¯‹‚•ä‚ä––§¸v¢Ä Z TÀ`²9¡|hŸNlZÃÔX¢|’IJÇxôƒÈddDQÊÞÐàuÇNúxDQÌpZÈÆ£bmò¤ íývqªk’ó³S@Ž,<Ãp¢|K b5ý–fqQЕáÌÐÖ³øžFrÏ‹Yð„•EŸ4§¶˜ä†~‘'ÂR7ÀjÃN”‘N rOZÄ&c22$9Ý–ÇéÁ2ãt†É Y ql!¶¦ÕSŒ#Ã8 4LWoÌèö(:"œ!äÊB‚Yô ӜԾƤ†ƒaÎj[3ÎsLGHÇ0Î ­\°9´}!× bƒ)E"*6´:EgrW{D³¥tQNžd¤!H½ØcsÓ0 tlY&äêVÊF–Ó÷ÀäÂÁ º>ì™”–°ä Øßˆèú]BåØ1£|ÂdÝÒWÁ'ÐmüVL+Ô¤€mgHV4¶ÍÆàk!Ï-›÷'IËrr¨5~”sêx·˜¼$fo7a3¶,‡xxQÂlf1mKØ7^NgÍgc=fï†a°¤ØŠ§øÚ-Mn,ûyD¨zJ3‹3ÄZ2ߣ—…ØI´•£Œ0ތȱè@hM4ÊÙŸ®nâ}ù3šö*DQF»­h[EÇ ‰oÙ3È…“ ë&EiXY'›ç,ôe ‚ƒ©E…xeAË@K)¢F#K¯eôå)†cC7¦’2åheèö4íT‘šœA[ØŒ-[¹¥e„Ë×34BJñÜ… òÂètVœrº»?#Ísö28Ñò¸uù§×2Ì.[»lmL‰´"BXXê°°dØ¿>b[:-¬¢7ÐÌÆÑ{OóÜ2ºQ„_ƒiY^¿9ÅhËb Œóâ…mOÓêÄíÉ-ž&Óœ¶ÎiY! ~K“äi £ ÉÑÊ’í ;ãÔ)/ ˜Œb¼VÆÒ CŒ0šŒ‰sÐ*ÇŠG°¡8µÐf¼”°e¤Õ…‰¶ä™BrÅtdPÆ¢»‚Í-펇j)" ˆ=”†ƒI† i"ŒÅ”‡/ Yné)´`YÒH±çD‹Í Gh­X¬.þ½?…̇c‹¾'„Å–7,{ž¥ÝW,[ÅðÀÐé ƒd±e–€¿ èj‹ÃîÔÒêYºÖ@+#ðg8Õ^!°†ñŒTϰv,$˶&èT#û1­ž‡mù˜8!M /5™Àþ˜w¿ÈXKöŠFÀÚ”áHˆf­@Ñ9> í¶7ØÛOè$A;`0ðIÒ”V&¤:­Vξ5Ì!¹ahùÐÎ`¹°µ›3V9ý8E·CÚK™—b“)ä‰ a×CÚ0™æ$X&Fèû‚ [tùĂ׃DY¦»¹É8Öò\0L­%É-ÝžBk‹ÍáDGX(F‰e<ƒ^KP¹eã SL~h±Ä3èv‹ƒišpéÚ ®ÛuÚmÕ÷BŸTR$Î!7̲˜x&¬öB¢8& ,6€t,Ð+òèùï¼Õ¦‹ò̰è aM }=Ej`w{HÀô@ÀRC'ÌÅÌ ýØ’j‹M q“‹xŠtdيݰeñF3˜%yœ J1PpÚ ñ•e71Œ¯MHËÞÁ„üx†Z*BAfr²,#Z²HX^v¼‰bú„íé4¡?ñXôzììhзÌòœ'—=² åò~Âl ý„9¤SÈ´%Ә굋'”…]Àz…H¦»P—èœ!HR,¾d cß’)°‰… ü ²‰eà+ˆeO“Ì׆ ÉD±% [:ÁZÅ¢QìcÙ 2*#Í0cEf2" ×Õ´{÷rÏ£;Îiµ‘²l zm]´o¾“à…RÅ€4Oi·Ê&Ñ–Â!ˆs¦ËÖŽeaâhu„Öq8ˆRâ‹—@ÚƉÅLR<]ÕîG°·két :€©5œéµØÞ‰bX%`63ÄÖgzº!ô}akh™Z6H˜£Å2 ÚQät{QB:°lg)&3túBGµèK{dä\ší2œ¥„…)S•BNùjE,–hb BßâH¡·¨ ʣӷ䓌L ³‰%Ž`à+Z=Ø™ÂPȬÅK¡«= aËï[²©"mYzËš‘½¶âŒßfgd3CYöCß÷X 4)9ù0ã–å%ÆAÂÞ4¢k…½O„ÉnÆÒ’Þ§[V –=Ú¶yﵓ7ZÀ™±ÌRCA+)„Bñ®°¼¤hŸ´ä‰À®e6-R@k,ä‚Ñ–4/¯o9uN‘FÏ ~¤Ø“ Úv`åTˆß‚I–pq+Ã0a!Íê÷½ê±q#"J„åS ZÇ|´õHÆ)ÓŒÕÕ€éÔlOÉ´‡h!ä uÌÎ8!K ¹ôA»802ñ? qnñZE„¿'ä±!éZZ¡£ñÌ0è{HžÑëxär]œRâKðÈ&…i)au©õ ×£ g,­ ¸1²=ž‘¥)‘Ÿ¢•G{ ض`f°Ò÷°bHÆ â-v76È5,®öt:t† '1ì Û½dYì “‘ewf0™eñÞ³–ÊÞÂÔ·L­åDÛ#l)®MbΞè¡|ÃÔè÷}òaÂqSßÏ ca$Üz‹ÐÒ°rñ~¯ˆÁí¾bqÍgf2Ö÷R^¼žâï&œ9g–ò¶Ç‹SΞóœ(@ãöFÌî†%I¡¿d91P±âúÅ„,Ïé­Ç­ Â.©oð&ŠÎ `g8F|ºmÅFœ1‹É Ç{ŠHvGÐÖ@¾XVïöÉšƒõ”®É&†ƒIÆB[PaŠI ßSŒ®%Œv ×…³'Cž¹3Ê`aÚ}á¸òð=i;eE` Ó,b<›‘«‚Èf–åÕ ÕbC’@{œÒi'[/ìKχÑxÊ͜Ŏe7gàµ8}Î'’»×r6w ý¾ÐÊÄm¸p%c¡ ‹!Lb8؃VÇBÂ)Lư½mgNge¼q0X„<‚xú>d^Ê8€x#áÕW€[rN.Åôµ‡3laß²7`u ]oB®-mK!_*Õ9É-+]HŒáÒuh·à䱌­€‹ãŒ‰2Ü~{›òHMÂÕ=Þ›"(ËRÂVŸùû;M¿>x^=î“òV}Ö¾ù,àæáŠo:v˜ù˜½8h³gÜï­s|ógÍŸvö¶$9§r~Ó·;yë]o~ÈÓ›'¹GG¼õäðI=ssjmþÎÏ ž“…]¿'.ïh ~·_óGÆ¿%d­5­V+l·ÛoQ~÷îí¾ç÷ÚëþÿpµÛíÐ 6žçy¦ÕjñÔSO=ú¹Ï}.HÓTëˆ÷ÛgÖÚ«“W}ÿ· {¿“ãû·o7^k­ÕZ›‡~ø"bmé¤Óé¨^¯ÆqìEQ*¥¾ÅsÞé ëÇÏ|›×«ßÏ=Ìòw`²Þ‰ü.º ±ˆdÖÚ0b­Ek-žç!"ôz=1Æü¶|c–edYö¾?'M‹CþMí–ßé]úo ˆç¹u=€¡þßãñÈŽ àhŽ àè:2€£ëÈŽ®#8ºŽ àè:2€£ëÈŽ®#8ºŽ àè:2€£ëÈŽ®#8ºŽ àèúÝxýv­=€XÛôIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/image_disable.png000066400000000000000000000423061217176075400246360ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 8ØÒÆ¢ IDATxÚì½Ù¯$I–Þ÷;fæKDܸ[®U•µõ23ì!‡œæ"J$„  ýz IŸHD”† ‡3œ^Ô]{eU®wÅ73;zðXÜ=âfeW6 q”dUæ]<ÜÍÎòï|ÇBT•·¯ÿÿ¾ÌÛ%xko_o àíë­¼}½5€·¯·ðöõÖÞ¾ÞÀÛ×[xûzko_o àíë­¼}½5€·¯·ðöõÖÞ¾þ"¾€ˆˆ¾0 I’·+ùš/ù­_³®ëßô6û-ë(ðÑGýþ£Gu ahoÅ#o¾ñ¿m¸ízû¾nŒ‘ÇûùçŸÿˆªªÎãbŒñ÷ÿ÷ÿÇŸþô§ÿmŒñ?joøÿÂëû8ÊwýÎmßÕï ¿çœãg?ûÙÿüùçŸÿwÆ+"3Ƙc."™µö·²)¿­ýÍ@¾Ï&¾Î×Tu³ßÇÖß·ÖbŒÉ€‰1¦Š16®ux¡ÛÖ_ïZ xͽ{åµÖ÷"›ÿ¬oóÖ«ý¿°í»ë¥«[Ñõ?u÷ûûnY_Ó­#( ºuŠKwÉtû{ªívl7SYïóÛ*à/økvÒ¾PaD¨|äúg?{e(nM©µXE[oÞxmÇŒ×æ)Úû’Übñúþ¬·|q mEÛ[P^ùq¢ëÀrÛ/螯¾Ö^CvCÂÞï·ÿ¤÷S›u}½pÚûY;>åþ­{{SêúïîU¹#;ù  ë_ì,pïatÿ½nPÖÕûv ÈÆv´okCÙR‡û"{ŒE^õ³Òÿºt®14Ìîµµ“ÎÖÆ­Ã4ªëM꾇¬6¹óóÝ¿¨l~çU‰OTú!½ñß FÝ«€–Ù¼A{»í½h'RÐ{"Ŭ#‚®€…ôks­Nu˜씈ö×­³p;ž¼ºHoC¥õ%QÙ1ZÙÜÅðÞ¶¿Žnk£N´“NP3M\%ÛÕskÇxd'’l—Nƨ=«é,Žlïv}MÑíMÉfdƒÃöy}78^R CP{í¾«Èêæ¤ûïî}BœHjÏK Û”! Q¶Þ"+£këê MÇS7ÞÕõ¸NNèJ{í„Ѿ!˜Î{¬ßÔlŒ ótMg‘Å!퇯P§Ò1þv¢žUdCæ´`±ãòÝ%¢ûŽ:l3•á5× $CÑN8Ôþbˆn í„>dí!Ú[8¥}Ù\m›×»kß]PQúátu“fø,ÝdÕ¹XÿîdäŽ;tÞtÖaa‹o¤çå[Ã’NÚ¾_\VÏj†)«Ì`èÝù«ÓÆšïqûsò>°Òa³öÕ22°`£ÒK Û¦º‰=ëD ³Ç‹ºI;v*@ì…ÌNúZ-¸ö"R×[º†#ƒ…—ÞÝÞ«¬qÊæ:¹½Ø•nÊ‘~ÊéE£Áö#Ū¼“NtFŸïâRÜëÑ—ÛÛµÝ7ïÚsß(ú8¨O‰JÏàÖate¯qú€° ¯¦—>´`A;›ÔnÛ±?*²Ê±H'ôa¡‘N5#ûqT'iìî{BíDíD †ø WÕÈ-‰ä»_¯…69¥SâuÑ®½L»`G; Ó6ÜïK!²ƒÅw}§ªEÙCV);pyµ]G2ý3v­‹e·‹iºÏÚÁëû"H¿ êÜÛ°ü饬͵·€‹¥º÷%ƒµÛdPšˆè›E€aÜ’aèÚÜ´ìýù½Œß*'ªÓË .ÛSSïÔ»+@¡{CµlMv“h#Ù­Ì{›³‰S¦]Tx§î¹OéFQí×Ò¯Šô‹!Ù¾ÿ”‚ìI‰ý÷~£09]{Óu©#"H lHêèŽ1i/×·eK»¯ÝšvËH¯&—u©7ô¼.XïÏ¡o /³öé5z^W7Ò­ZtEC†–è‚­ž¶¥g÷¡µ³z"²BòÛ*Ò¯‡Ö‘Õt¹³Ž£ KJíT_›½”“¯mª ¸º€Y½MìmÖid c:YpL·NÞÆ®Uîì¿ÏN½¾ÉùÚ‰þ}ün@uË\Ê&ýl¢†Ð«@6_¤W#ì„[éÃÅ}p'Iÿ›¢ì`£¶Ùù¢î¼›ôø…•s|ï »¹Í Y5¥ »ÌÖ€îÚ¢ç^Á¢{°v¿Fßz¨}}€¼»—(vÓáê%Æ6¢©n½JÁ xiéÔšBÿÞ¥ËÈzm¶e¥šaI¼5ò!ż~W#ë*¦[®HþJPà&RÆß3ìcuCKnA]°u»–(0Øù»n=mm§ÝË­÷=TV¿'=&nÏRôþÖe#{w)CnAViåå†M(ß¡€eEÀè6µtW÷¾s¥Ç²®9†Ã -et‡„Ö0ÿ »~©RÉvQp§Ä¢úue Ò·›X!ûŠ—¾WwkzéRÒ]Þ S ¨®øíT/"ôiÁ^QÚcðº4ìèpyĬ®ß-I×4ôÖ;u@f ­ª[îÉÀºŒüªoÔç}ý°·)ÔCÌÚ'K^‘÷»dÐ0§õIf{é²[Pv)ÓÿFŸ.ZS§*o—¡úa ÂT¹•{NéÖåîoeL×¶'òtñ•î¤À[¢Ä0uûì#Ç´f߀”%wHRÝZšîx¸ìm†šûßo˜(:0¡Ýú°³á›,ë>̃lru'ƒkçdÐøÝ)»$ðà>dPíÈþT¤Ã¶ÓÀó‡àvèMÒtåÖw7lžY߀ T†¹­ša£c“£tãIÃÇvëÞMJÑþ¶Ë ì÷Õº½…~YÙó¾.ô4¶µw‡t^Âݧìšc'*˜>!µ“˜a­K…£=3†£s?ûRÃ>ŽFרeõìæ"À}÷¬Uw°Æ`±‡+;(}'ÞÚ¡×Ap“afdowvÇ=‚a¬é¶qw¶R÷EÄ~oßÀ~æjO™8`Y¥ Ü†Â‘-@”¡šFä–ÄòºpKMúÝ*¶€¨“ºÛ­¨×Üå´GˈB·‘£ÏÇÈŽH:íàÛ˜É]^~·›¦ûpÌk(ŒdUßm@é zUÙ³ ] :p>Ýø6i¶D{-ù7Á·=¡ Ê6éñéBTÝ&²/ˆ»e-AÿÁµ×ýb'ô™Á.âîö)dUÊîßSÙs×·TIëú[û•CêW¶Ð^Ínª@ì%¾z%nZ´iL¤{!}C~é©{Ú¿²Ö ˜.(‚îÊN…ßï‘nR; tosx÷ûr;9°'-­…]–pÍ ܲzØouWEªà!›§=|²ÝCÙ»¦S¨lW]k‘ßj'„¯Aĺï݆0h_v½b»6ºSÉ«vG†Lá6¤í•8¬vm«ô‘kÆ+iΞÀ§£9kE±Cý&TöH´¶ÙJz-ã!ZéÙLOrK¡Ûݘ÷•œo’ö÷Ê»DÇÞÊf´½oÁ^·×É“}ôQ4zÈíËÝà¾Û1ÜY ±³4h°=ØAv );¥óí VüœìÑk×ÛMÇ֤׮êëö¦ý|Ïëk{µ¾r[P]s½:èßI?”Šì·l•—n$è·»z Ï蚉¼ Üõ³ºìÝíõzÑdGˆ!½&–érÒï?ìãïuïm£Ç&µvª‚u_dëáÚ7É!~c"ÈÈN—\nYTJµ{u²ö-: ¨³¶ÒÏo›Ú¶# Þ°fK5Óë§·FØW&íSé+kÙÝÐ,ýå–áÚhoÙðmŸGz<Ã^˜²IEr‹@w _JäAàómE\6ªô 0PünY¸5ð2ì†Ì}m{6§Ïéo4Ý|Ý—…™µ¼msï}‚^6eæ¾Û!ƒv….«òTöšôz»Ø¨½tHÂõ¸˜]@°Wâþ}@`¿ŠÙ­uO;¶ÛQë’fgÁd#§ÞOöp û¸¥®ÄlH¦°¿¬Þ,«vm§líM6uÊÒŸn>î’Ùfx·Wé„5‘Ý%ƒÌ½ÃfªlÂüN6=wï„~í´²åÍ#€‘a‰uû¦™n‹Ve÷:kê`­’\/ŒöÅëIؾúnà:rèÂ!Ù«YÞñZ‘>àê9í©u¤÷¾Ý†ÙX•è%ÝTeóuMŽ™•²hÍëÕÎÒ¯FzInµ`†7•„u#€Ê-žÕ'hº ôÐ÷z£ D”k’J¿ ®]}ý2nóÜfÀ*îu{’Õ@¤2hì+Éz±®¯ó—=Ì¢°3ɲ—ÕÛJƒ:ñAú%€ìå?v§1xs&pgðvZE{(Ôܵ†Ìmøgý÷80*ÞÁMÙ'L€ ÝMÝöRWù4äÝw8-í½›‚¤ß’eïMZ×»…Û°9´«ø¹-žtɤßfØ”:ݪXo­ÿeO¹¨{Ãñ^z½'/3 ëÒ+ûLgJI7ÿÈoº>ÛSË~¹A‡’¡Ïm£‡®›K»#IJÓg”Æ’[ðìå´+BÝÑ$| æ³é¿JÞ€ÙÓ¸Øn¶r;‰#;ÌûPo·5º®‰iW¶µ³HörŸíb…Ø«¹»Ã¯ëÔ´zï&Jw¨ä _¶rp¹…†6½úHFÙ9C«Ú#ÔeÈ~ófteá[­vÛðÙ§Õè[¯é05;ÜCh)»½ƒ.‚V•–NötåÁJ;ûu{ë’Sw_!°—‹èw†w5ʲ‡z–[:>ÛyÈý1Òá ^Åp%î²§nÃ0”sõO]0l²òèOô ƒC!:ÀOÈ]÷ fèÚØÖóÒ‰¹cP j\lHÜçÏÏ8¸ó29„{ÜÀíøh·ñºS’î“õö8» ¨þóÊ+;­ûèþ cÀÀàívu'¥ ðê.„ `Wž4¨}»ÿֽܖtˆv5‘~MޱÔMÅâÅŒªsB³$1Ê‘¦ÄpŠ˜cиÃåm™t3 z×÷«{çf^œ!fþþþíÛ×íÊÁwÂäm`¼Ão¼q ¶@g ã»¯­{NÇ0·ÐŸz ÖÞw‚RGreæ7/©ŸþœI¨§ã“#BÓP,J¾ù¿Σ?cÇGÄà‹¬{ÅK2ð}e†§›¢Íà®t×S‡ç#¼Šn•[!­Üb@º{áµwé;zìé|½²›±«M¿5‡òª†ýžÈÃMB¹¸`tù êÆá¬E,KÏ‹›ŠùÕ Ë¯~Aöß’e1† ®ØUùéNáÖãÖÙéí¿ûá±(`»ÿÙuÿãkDö2¥ûåtò}ª€M¾Ð=Ïö8’5ª*æzZqý´C¥^7šôu*¯ÃòI1_Þà^~ÂÔÁ|ÈSCâ`QÖ¤‰E€éÁ˜?ûŸ0y¾ä§ÿïcŒÝ¾çfÐm§ïØ3´½ü„îç¶=‰ÁsÝ’i¢·äìÛ|@öqá=ˆ©]ò¦e`דe']î³0ÙWê­K:ltÈÎb÷·±vó.ÎÊ9æù/˜$‘ºQšª&MÀ±XzƆQæ8>ȹ™Õ<ûê3¾þå;üà¯üe|V€ÐìúîAÝÒ/ÉÖ²k³‚Ñ[ÜötWï&¼(Zßþh+†=cèÛRô ˆ Ý¾ßyɽgìEÚÙÉž…ОÌIÅ,/H^|ŠÑš¨ Ä@ž'„‹e%Ï£Ô2=ȸ{œóì…òåÏþœ‡}Äh2!†¸áøeOÛ¸O²´c¢QLÇ!¤K¹ô¯„h{÷Te?§z[ÿ±ÇwšFÃ#ç^‡ 6¯cuFè>íaJ爒®œyå8fÕŽÜ̱wÿ¿Ñ¬1ø#ƒ?«ß±–°¸@Ÿü|µ 42™¤ípeŒLÇ ÎZ§ÎÖ i’’‰çégŸb¬l†ØyŸÁ{1­þ_dSö®9‘M«uM¸lþ¾ý¿0¼þîŸîzé°žõÀÈfÒHVzÿõ}õ×­ÕfºD°‰`Ý›¤nŸGßÉ“Ýsjd äU„/Ý0¨ë†"8á£÷Oc¹ºZ2?Ùz¿1½£_º8݉`2˜ÒÝb·ÂXéK¿eõ·»ôõNdíߤµ+Ûšx‹ÊÍù Ð@S×ð·¿…°wj¨îö·;uCoF`Ðó6]¾`84)›SKð/># &M!cKÝúñUäòª@QÜ›ꆢ„* Ib¨c`q3'†ˆs¦?Ø|zck»š¡>([[×;¢­p×ü·„yÙ3(;”h×ó{—çæì‚—Ͼ¦(gœâç/ùæ“_¡DBløøß¿9 ƒ|´O´ÛÞÚÆîQ(ÛuèÃÕ]6CDÀ Õó¯H–çØ$¥¬=‰5Ôo× >BÓx<8$ƈµ†û–jyÓV1VQñ^q.Á¦Bš%± ã€Ã仩`k-ÞûW†€a‹ô¶ª©7ÕÃö…‚vU:p{³cðËkÌËÏV9NP„ j°VHœѨkVYFœK Φ„Ð2’yfypgÊ“_~ó¯óñïý¦–ÝÉîá¤ÖšÕ3ÃeÑí™‚ÝÆÙ ެ¡wðÅ:Ä£P/Ÿ~Íó/>cvñ”b> Iæp™Å‰#4µ–<¢Q&™c$©KiBÃËù jo§÷_+˜‰—Á­÷ti²KèìLïî9UhßH•5Ħ¤~òkr” #ŠM ¾öhP\f)Š \\/I3Gš&Xq„±Fð!2¥xX Îã<áÉgŸñáïücöA¹¾\Ø×Ïð÷r [*û¦³¶FgÄ‚F¨Ê’˳§<ùôW\Ÿ=£.ç@$ÉRƇ9b ±n£¼JòöÞìúè˜Ç%¾š3ŸW˜Äþ6N c–êž“¶É‰Ý‰º1²ÿ°ô=ìÖ¦ £ðü3¤Z²im!͸¼)¸¼\9áóo.øïc­!u‰Š÷š& Yb9šŽxöø.ž¾àÞ{ÐÆHoœNB”л]°!òŠjŒiû*øÆóì‹/9ñ˜Ùå3šâñQ%M„<q°Î‘§_7Ì«¯¢Å9¡¬¼G1/9»¼d4‘Kž;êÅ’ù~@× î=ƒ³ïé-ª×ÝéÝAœÔW1“còçß}M–§h„ÄBØ*}//—|øðwácä×_¼`”:Þyçض}£¶ýxk…(P6>Ö<½ª8¾k©.żi° .Ê"b ĺ¢(Jfç<ûòS¾œžptÿ>ø!Þ}D’Øë8øÄ”ØaJMKÐxϾþŠóÇŸsýü1©Qîg#²ƒ#ÀˆCĈpçôˆIž1»Zp49"ø’$O1ÞS—¾i-¯1JŽ!4Dxðà.7çs¾à¦¸á³o¿â^vÄËë+nŠê» À³×ûÙtÿ?4ˆh·÷ßé`k2 ˜Î4ÎÎLà ú‹o0‹3’<Ýöë´ÝÌ,1499qz:&Ÿ~}ÁñÑ„‡wÆ`-¾ö ÖWšº¢® ¾=»äò¦h»r0'¤‰ÁÁå ÞP—*‘b»™ª$ ÔÅ%Ï>?ãÅãÏùu~À½w1:<æÎÃGŒG#Å{Ïäð€Û’tq³àìécΞ}Aœ]’EÇÝÉ£,EC$¨‹ c+m¡o­e1_c úˆ*$F(æKB€ª©(M…Ö ¨ÏñÑ”ãé„ËúqW ××ȉçôè,wß`4ìÕ*Éà¡~@Е¢ú²§õëEC¸zBsöx•c#©s-è#1FD!O…8q¨1œß”4çp’àUˆ>ÒxÕ¶bx~yÁãhˆ¸¤ § L'S4‰\.f˜à89®–7Œ’”YYä« kq¢¯¹yùœëÏk88=Á9 b㙞ž¢hê†r>ÃÄ%Ž99:Å×Eñ¾!*¤‰dyªñMƒ¯Œ!zò<'6 "ÊM=ç¦YRICžZˆÆÂ<.p!²ôä#‡ÊPóÑ£”;ÍáwÀ«KÝØCynêt·þѾz¸µ£6†c©gç4/#ªLÆ)"¦ý¸³×íCkL.MHÕàËË—W¼÷ðˆ°â¬sÌê%/..8»¸âzY¶Z®f21Ø`8šŒ Dœ@=Çã1u¡Ìªš±1›—xI­CC¤©=ÎXÄù$Á8¬.K¥j"ÖYž}u†•ƒQÆ÷Þa’f4UCÔˆ1–Ôê&F¬h[} ¸Äb¡ôŠoêU 4M ª#¹Ë%#0J>ŒM1dM]3-¨Oh”td1‰òÍåsfW—ÿòõRÀÞÍ_!žÝƒ"wÍcç³®tHš ¤6+þ<úŠúì‚÷äÖ`DhBÀÓ.œ*V ¨=>¶y]ŒãðpÌÉcšª¦¨*¾øâkž½8§ö¡=¢fÕ‰ÚF M/%>´d‹ÁIÊÅ¢¤.#1*Žï0)”ËHbãÚÎ ^‰!¶™/´˜$±Ô•ÇYË8OI\Ê÷îáT0Rq¨*1*U°YŠ‘Hð‹Ë&£”,ËðM ø€1B ®+Æ0J3BT|ã¡qT³†`ÁY¡¬KNïñÞ²X,išÀ’‚ëEEUú7”…{%Ûíº·¸—^O­)ZY—¥ºxB³¸l”1›¤YŠª'Ô YêpIÚ¤‰Ô¾íú™~ùéW4¡æùùEY!¬5ˆDˆ- ѼâëHL[É‚a¶ 4•àrKék›†ét„uʲ¨‰A1Î4ê(Κ¦ýwˆÚrÞçšÀôàIæ0Î`|hj÷E±™ÍkB $Î!b‰ÑPÍ ¼o×2ƒ‰µÔÇ7k´}CÛßÁP.kʦ&É …¯)BE6š2±Âù“%×gåw~¢èþÓÂeðáŸÒ­éãžXÐÎG?éæÌÀíáQ[ °ùÄ1ÔË9åÙ3ê;‡±1-Ç/1’f)¸¸ž3_”uÍÓ³ êÚÓ„@ ›`¬`6¨Ú:ÁûHž8Ž2Æ#Ã$w(ŠË-g7ÇÓ#æEIžXªª!H„ óÐÎ= „:b\‹Ö­1Dßz¦Ë,¬jãÖZ²4'5¶åLÛȲF(š@Ј‹ #›&4µ'zO]•m#lb±Î µl¦Œ’Ä`PW+xoHâ˜Ù¬ä2\QÆ üg@­¶ý€7"‚T{øÝùë"mHžØ—Oiç(!í•û›ƒг§<Á¥)u9œæ,KŠªâjYòâü’Ù¼ ¬›1©Bâ,âÚfxTOâIâ°©0IN޹¼^`ÕŒ•ÃGKŽ[êrIžZF£ÀW_ß ÆaÒ@¨["©àD¨ %•”wݦí÷ú·¡{øŸî'itΫé4’Œ¬±ˆªrNq}Žhò,ih8»¼DU™Ý,¹Y”ˆiEÁ+éÈ!€sINCÀXKS7gpÎpw4Å:0N˜¦îp‹›K|Sp¡Q)ŠŠEÕp“-/®fŠº!ÉÄÖÐÙÒÞ‘HUGŽr,ÂMY`Vº…àß^žQÕ “lÌÑÁ‘²ª!±ÕH•£†ù²½÷&4„ð>RÕžhÀðMÛè M n09æ‹‚¿¤ŒcÆÉˆqž}@¢W¢Š:P5Ñ8Åä%OçHš06™fŒîްÜØ¡Úp49ÀDýíD€ TY•pm{7M ÁGBl[¸"­Aùhª<¿þœëógÌn®¨Šuéq©„à#IjÁœ@D MC å¿]bñ1€´„ËZÓ'Æ´ÄMÉ“„ÄXb­Ìʾ L܈ySP‡î²l˜/juÁGÇwXÖ eSSÜD|hŸc2Jñ1¢1¦‚F>nÔÜÖ¬$¤b§)u8H3j©XV –4I¨š’o^œqg:%j«a¸™„°ªŽ4Ò4 ÖÁrVàlBão^òptJî©5†Ú{lšÐ®ÓRo(ª%Yžs'=â09d>+ð'Ë2&I†ÄŒq–qñâòûõ¶¹[wfŽDÀZGT¸˜“§žÿ§¿Æ×hU± Ë3.æ×<ùê+Œ uV6K>¶„ ÄàrYs0ÉP ˺Äe–45äyuÓPWž" —§DY2"s yn$âhF‚ÅkàÅõÉgÛgYÖ¼;a”[feÉ$M88±\\—¼wÿPΖW¤âgª†  ³ª ©Ú”ðîé£lÄrY‘¥‘ 5™q˜\ Ag–EQsí îMñÑÐ~†¡M+#kª¦½id~S¡¢\T7LËg-eÕÊ–’ÔbU©}Ãä`ʽñ=F‰åââ’‹ùB«éˆ1¥^4$©c±,Y,Ë7™ PLwìi%F««Šó³—,–7|MÄs¾üì1UܸmÂhliU ÒÎfbqÒÔP,=b”$·”× Yn1I¤(<65äY+ÅVµk!Í j„£ô%M-¾÷ßýœùü_y|eI+ñA"P;Œm FƒÒ¬r8±A¬0›yÔ ÙABð‘Ñ#wiËÇ –q–PÕ ‰dÔµ'u9>Ü?ÊY,+êh©«†O¾ú‚q>áú¦!Ps:É9>šbmBž¦<_^p8ð“ÿäoâÿô™]¿`±ô¦h€ó‹‚“ûwÈE)æ5³y…÷-åŒ \_/ FYÂ8I RòâæšªñÜ3–”„”rq­‘Vuƒ7íæ_Êœ»£C*_RÕžédÊ$OÐài|À%xH“„ižªˆ‘E½dYWœº)©:j $GŽ»ù!R‚·‘,MZ‡¬=^ë¶lÔ Q¥ªjвÞ4~ch%מÿóŸÿ îŸòÞûw9þ5u3ÃZ¡¬“QÆãC.–K‚o¨æ µÔ¤y‚I .q¼sgÊG}Ä7ß<£X̸óñÌo.yòüŠyÅ$³¼ÿÃIÇ–âúš4s5›1».À ‡“”\– _?=£ª'§¤.ãý÷ñè£ñOþ×ÿß4œ|pÂOþÚO)¯®™?Âý“)’øô“O©ê%W³ŠÊ+M€œÞá^f˜¼ÿˆ³³gL§S¦GS>ûìªFp©2[&IŽ Ì«®I9H&LòH ¦(…Ô$êÂcǰ  J6±ÌŠ%ÓQB a2s41»YP6—XD"JÄ9»œSk@ äiB±¨¹Ìæ¼wz;§c&.¥^E¤"e©›†¨ŠKŒ ¾ñ$£”ª¨)+÷ñûGUŬ€ßGï?äùìšbøñG?âààˆÙlÁÍÅ%ËËkbã)f%Yšñ—ÿêÛéë’–Mn ï<äàÁ»¼ó;?âÙ·Ï'9e¹$á÷ò{±UïNRþñ?ý#~ðîûüÎï~ÌÑÉ1F„ù|Îåå%V”Qš“äˆß<~Œ5‘þàCþÎßø)׋’,Ïøù³k>úÁÝ=åþøÿ ÖáoþáO9><áƒwï’dçç3>þøC4Àõ‹§œÜ›"6£XÞ0º¾áÄ9N‰eÃøø.‹:âRuÅŸÿñÏpÖQ5;ã ©úÓÑäûÉÂE„ÐnŠ+þå¿ÿ¿¸;=áÇ?þú«_òõ—_“$c|SS׿úñ#¼‰<{ùœ_}ö Qa”ŽŒ¨ixúü%¹qr|„M Ož}Ëò¦àúú†lœòðô>þg¿âÙ·/(šŠ¿ô—~q)Mh9÷Ù|Ƴ§Ïùøã8Ÿ]ñ¯þäß²XRçOeUòÉ'¿â—¿ø5ç77à³§ßðW~ï'\œ¿¤j|ôÁ»üùÏþ¿úõWÜÌÉÏ?ÅÙ%ãÔñ¿û1gO¯øõ·ßâ ó†àã‹›Š?øÉï1[|Ë“‹güèÃa>ü˜éñW3Ò,Áû†ë‹Þ}‡ß»O2‘fcbñËš¢©™rYÍ(¥!uðù×ùô›/øÛðû|òä3.oJœË…›‹£BQž<~Éÿö¿ÿ3ŠbÆù‹DÇüã¿Ä0æ|qÁ“/°ÖPWuÛ/ ?ù›qóÍ ÃùU@æF|û|Ælö &‡¸„«ËãIJ2ÉùÅç_òÞ»\^U\^Lò”ùå6ä7)¢00¯®o®yïÞîßáÒ,øõ×/IœðxtÁéñ„ÑtÌõõ‚?ùÓ?g:òÍÓoøá‡óüìy’òù×9»ºäåÓ9&±yšröü†ª(8Ê|:âżkù“?û5wïr0ÍùGÿèãŒS7†häÓ)‹Zø'ÿü±IÆ–«ËVXJ<½(Q öË/êY .ÏþŒO?{LTÏ(˹º¼Ûðãßùï?ýÏÈÒ„$µ ¦‹ f³ÿùßÿ/¸÷‹ÿÀ¿øwÿ–ºñ¼x:çƒG þÍŸü’²lh"Œdø¨hˆX;b<>ååY…³ŒòŒ:6Ôê)ëšÜÒÌžS˜¼ýßóÉgüäÑÁ÷•„)Öîݽ߂À{÷¨ê€³ÐT ï?DhåÙA¬Y²J<`œ%xbˆ5íxVê,F~øñ}š¸àúú’hŽ9;›sÿèb„P•Œ§¼Ì.Y%u5çîé”bqÍÝé”É(çôÞ” ïóòlIÝ”œ={ƒ{÷8¹û€ûï‘e)‹ë>ùü1Ïž_àƒpÿþk=Z¥ˆuœŸ/hêY–‘Û).ÂÅbF’ä”uÄ‘B³úT_1p1'Ï{¼çÞý;LÆ §Ç§Ì–%!,ÛR9*± ”ÍŒ4Ëe‰h (JW§ö”;÷ïîxަcï¹W×c0VPc xª:¶8"DŒµhT²<ì@ãh”1%4æü'¿KXQãÆ94zÄUÌfo 7FHìêï–£$ádâxy5ÇZË8‡ùrɬrŒ’Œ;ÓµæÝ`4 Fñ!RTm˜>ŸÏ©µâjþ5ªqÔóðã½;Œ8^¼l¨üœ2œ;À˜¶Ó¶tÓprj°xôî»ÌË’o®e;§Úkb˜N~ò{§<|X,L§í©f=ºKUÁÍbʼ(ib[Šù:ðÁä¡Q¢D²4åähÊÑÁˆ²ñ<yÎlé™NNH’ §/–«eàùå3NŽFO¸ºYò¯þÍŸaÄðW~ò!§‡c Z|õé'(Â@rØv=]°ŒF#l"hsHU Ö*Þ·ï™3䔾ý„0Q¨ÅYAbh0&ç–eˆdÎQG%µEÈQ–>›v®/GÐH]+e¤Î0ÍFÔÑ£Q‰|£àÁ9ƒK…Ú+µ®Æ‡ázÖf­ #8Äq47Ø D6k™ÊªŠLC#ê„PC½2ÎV–.¨X5rA¼âÚùD1øÕ‰#Æe‰¶5°4‹…ÒØ€ñ0ÂqS1’®>™¦j„ÄB©g,#“Q.<‰I°b±ÔTZÓÌ!ˆb3ƒ5 Öyœ[15I„ØJršR#ÄøzðÊn`4ëž±`C[½4 ”5ß TëÒÍT RU­‡9+$“g”墤(IhiÇ,³„pQ ¦•9H-Eáñ±Í¿Ç#ËbqÆà&ŠM…h È¢A£2«KB „|ìXV ¹µŒÆ–B#u,ÎEJZn?ÌgÛh8r–E©EÉ\DK’¢ Ò´˜$VŠM â nb;V¦ª`cÛF–5`Ò6ï7…"Vh¢FÆi«Ùó±ýÝ Jš ²RMÈ3¡JÝ´8Dæ×«ó€ÚѼ‡$i‡_c \Ý̘é¼5àÔ`!¶ÈTi¢'4Â$µøVÁB¨Ò6š¦öމ T+˜ ¤U*…bYa-4¥´•dÕ¯Æ+i€×êž@X}°d¬•E!*εãÑ•oyYøýfSã0¢A©ojB€¢¬‰‡äm˜ÞȽ«Ö«Fã6ü™¦Å(Ö9bHCnRŠ²Â©iç b$Ár02D¸*¾†4iÃ~l J‹DÛ¯³zÔts†díÐjP¥¨Úœ›¦­Ý6P[%Š BÛkgFÈFÊÈ¡nª@h„%¥ ¨ ¹ %ŠÚH&‘X)Z·éÅÓ¶Õ] 1m1WRG\"xE%òÝǹ­ @ö|€^а™h×ΡÛijX,•<‡P€K7†ÊüL€¶)BëvÞã¡( Ic¡Qå0u,Ë€0ÁÒ4ŠÇÒ¶ž’YaQµž% ˆ˜ê &o¥:i¤ ,WÃ"I‰82I1¡õ K_´ÃV¨] ‘)ØU¾Å×­÷Z«´-ÛÜ´!^ I¦h‰"ø¦õÞÌ.–M‰ÚµHŒV+íK%6BtJ:jéH8´ •D¯¯TAÉŒ!·¦íþU‘ãQNmEãI–E‹;š"’Z»®#ã‘ Î@µäûö[-`£Ð„¶,qa5Û^À(ÜA f(À7á Õ¡>¶ ÇdÊ4‚oCŸõB!ƒâÚ2˜ÑÃ:¨càrÙ–xºš¥OSA&†ùÌãƒ0š â ³£†PGŠ&2™´†–žh HƒšH%eˆ±•KW.´µs½2xÛz²q«Ã¬KP¯„´5òDÚ{OÓöT’41ÄÕ¡‘Äö™Â ?ÅBN`’·(ïÆ×æ£qƬªXÖžÞ´£ëIš€6Â8k%ö¡^wÌQ Ÿ¤dIB’UT‡–sÅŒ O¡®•дî5Z·Ÿ(@îÚ?Æ(ÁÀ81,&UNNR¦ka4±X#Œ¥­ë½ñP-`섃¬Ÿj”,mÓIž ‡GŽ£K2†—eäÙuͬªÉ,Œœa1W†ÉDH2e¹ (JôJn„Âe ÎÛÒÊL\ÊÄòFHŲ¬êÖˆÁ«Ry(kÅÆ–°(ê¶|j ð3e<²# FHš \‘&@íUhÏ˯‘ê&b¢r4¶”%”U “&©ig È`iswíýæó ¼W\‘D©U)ƒÒÔ‰ºÞZª•cÖuÃùUEðJY(j‡G)yfˆ%,®ÛÔë‚!££bòÄ®J"mA Š``ÒˆŠâ%.Wóy+@cH­´2|Ñ¡ T%ˆkßÔÇ6Ü…UˆÕV¤6¬ÆÓÓÔ0š$¨ , 2Î j h¤^*Æ+™kOU*%àëHb"&±øÉlË]1Hë™y{¾JÄ9Á¬B>Št¦XÛF ڒШB*4+¥­¯ZîAêË&bœ’ÙÖ«|Ó†`¡ŽÔ ðyXuÜʶ¼oÁÚÚkEÀ&mIŒo‰ëÀ¯ˆ™h ®Úîhˇ€MbËÏ8°©p íI(™u,¾?¼þØ’–Z:ÈHàzÙ ¡-“¢iX4P^BŒiÖZ½ÑÑ'‚4JS*㬕‹½¼VЧÇÐ$Š.cKµaâ”If9:tÌB )œ$Ž4‰Ø‘E3Á_RQpže©Ì—-ƒ÷ðN†M õ¢‚õ­%‘ËjI--"n–P5­QŽø ¦V¨B»À>Ëë6Rå¶-Ùª¢eÝH[p×Ô°\¶!þpÒ¦Êë2å- Ëöý¢‰ÔÖæó3à8rCj øˆú¶ü++˜•0™B–*õ¢šnýA—¹Á­XÃqÚV—7-è=Gœå²Ž4¢œœ$dbˆ¸)~ƒЭclOÚú‡ÿõÿ°ÿ3v‡gûèð4Ñ׈=ÝHö̙ȭÍkœÑ98ãYn?ýˆï:$I_çÜÝ׼޾ߒ[‡±_ÿÀß}'–(½öz- ð]¤ÁÛ×_¼—{»ñ_¯rl'ílÛÿÓÎä Qtþ8ÀýO¥è ºê40ã¢5ºÒZÛÄ´ÿ­ ðøIÀͬ¤”fý-÷9Ú±êŽÖߦ;Þ¬¼ž ¦ªnf2 Ã¥ëºìî§Å‡ùë à}ߟDÄXèGJIsÎ¥µfµÖ ¿«|sO˜Óv­6K£qJÀ#à"r‘+€7qD„¨*¯„sÎXkBÜÇzý¯´Ö6Y¤9ѽ9ˆûó¹pLoþÇF9€PB €PB €PB €P²G´j©.IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/man.png000066400000000000000000000751561217176075400226550ustar00rootroot00000000000000‰PNG  IHDR\r¨f pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFo‰IDATxÚì½Yé•ú%€Lì[-@¡6Ô¾°HV‘lŠì•lu÷H=’º}%[ßÑH³…C‡íðƒãúFŒ#c*s™ËTæ2—¹L`.s™ËTæ2—¹Lð̾Ã0æ¥1×QZâµ´J(Ÿ‘oPüo.s:¹Wü/DEp`€Bø-7S˜ë©.–ekã8®Ñ½,@&“©Pß”8h ÀÀ €UÜl,ËRDP.—5¯T*æ®=bËb‘t¿Õj}æß¡ÞcŠ}L-~©T*Y,¡P(eSh ?# ?gµZ¥RiÃs…e·ÛÛyžÏàe% %p€€ €Ëf³ù²Ùì\“ï±›ÏÝËw>°Ÿµ×Ï«qdëì£çõžS?®õºz¯!½®Ùcôž7zÞÿår‘HN§³Àv¡PÈ($`9HšÒçóY8Žc8EQ„ÑMëâ4{NwsÌn}šŸe®ÆÏa½s[o6²O-‹³R©°>ŸÏrÐ΋í}¦R©XDQ´Z,îIX²Ïۆ߯óGÞCOP”Ÿ¡~Þ±êǵ^Wï5Z¿MŪ×íçþQ~£ÿ3 ÃÙl6k¥R±à€‘Ù–¸w `.síÉõ1~†a4Ÿ'“çöIXq@£X @EB2»µd»±|{±–»ý~»ù¼§ýÛšEÍXüzV¾Ëoô·úþ^¾W#È£Ž2bDQdäý} ÖAD€ó7×BOóØÃ°Ÿm‡å"> Kû4‘À^>ïiÿ¶gvkùµÚõ7:WžËÃÀ_Y`.s™ës»l‡í ? K{XÀÓþmO ì•hôw7‹šáL`.s1Þ`/JÚD&8ÒHÀh³7‹öÊ(ßc7œ9f/œ€‰vû¥,&01ד·æû}ŒÉq$°›q”óvà ªH`?8’£Ü^l·–Ÿü­‡ v›\d"s™ËD&8¬HàI£‡g‰žÖo{šH`¯€hä|†Yf"¹Ìõ9^ŸËrà§iiͦ"Ï ìÕòëý¶F‘€É˜Ë\æ:Г«L1‰GRÏÊ¡ÃÖ^ÌDæ2×YfSP <3ki6i 4‚žV{1R)èïï§·H$‡ÃQ£VWW‘L&©RP*µ©©)øý~Ê'\¼x‘r @ÀT¦ÐÏ<¨Š€Àtòÿ{ï½Wõ·zuvv¢¥¥… {0DKK DQD>ŸÇÊÊ fff°²²‚•••*'ûâÅ‹xûí·k¬j2™Äìì,fgg!Ün7Ün·ôäþ_°Ý¼‰R.‡ _„(ŠU‚¯V<€ÿ Õß5sssš¼AGG:::‰DÐ××§)«««( ô=Ôÿ«D?¢Ñ(ü~?UlSSS»JVÚ­"hFI(]S!@„˜XðT*…›7o 8±è]]]T¸‰Ð+úx<Žx<®+ì@€Zxò¿–,//cyyëëëÈf³`YÝÝÝ¡¯/%“¸ó¿R:-Ý2”Ò”²”‹Eˆ•Jð¿ À75…õË_ ™LâÒ¥K¸~ý:ý_iÝ•ß; ¯¯Þïèè€Ýn×=_DÄb1 $“I$“I ¬­­Õ¼¿R)øýþ*EAÜŽg­DQŒU*Sì–|R03ܼy©TªÊr+Ÿ¯'à„€¡¡!8ú89Ï333ÈçóX^^ÆÊÊ òùöM°,k*€§©”B¬Þíímêk+-w#khhÐÕÕ§ÓI-9|å9\^^¦ÐºZÈɦ‹F£˜ššjŠ#ÂNŸçy@0DWWº»»kÞ#“É`{;D"ŽJ¥‚â•«h]]Ã0( ÚŠ F)“ƃ­-\ð¿ýñcK.…B…Bƒ;®…Î"ÊannŽÞæççé}­EA8†Ãá@ €ßï‡ÝnG8nÈ  ¬¯¯CE‹Eª,R©Ý'ä5Z J©ŒW!Š"úúúðÖ[oUk#P.—cL°ß à{ßûþäOþ¤éÏlii¡ñr"ØJa'Ïk 7lbÑàÑ£G5ŸqñâE G›eÀ“É$²Ù,%Ή²Ùl•ƒA*ˆ,ËVŸËåÉd‘N§Q*•P©TP©”Q©T[߀ç¿ÿ1¬~?¬>¬.`± R,ª”Aÿãƒ÷ñõÿøñÒoÿv•"7²8ŽC @0„Ûí¦J¡žbP+%b ELzî…R9(•B(¢„dooo]4¡\je°°°@ïooo#•J¡X,b}}?ÿùÏ5¢”ïi³Ù´8ôåÀÄÂwwwS!VBr½ûÊ E„7ŸÏÓûDØõ„›Xñîîn*ÔJÖË’S[tžç«„œ„Д›¼«« n·› ½zU*ð<\.‡l6‹R©, }íX*ÑíBúÚ5ØÚÚ`õù`óùèÿ¶`lk+*<¹ÙY”=L¼ý6r¹\.U8JÁM$TQ-..V)*‚NX–­P–e«r”çM/lI”¼ûî»”/ {€<¦µ” ÂçóQøï÷ûáóùªïîî¦Ç‘ûJy]\\ÄŸýÙŸá(¬#S øõ¯ZïGÑ ¶¼¼Lxii‰ µRÀõ K}å+_©ðfËe‰A ÂN])(Ä‚ß= Õµ ‚P‚ ðH§3TØ¥[}ã’¹{V¿¶`P~‚ˆ"ðù°°¸ˆá×^ÃÆÆ±dp:°Ùlà8ŽZú@ €þþ~]Å–ÉdÍfñøñãå@~7ÇqTQÅ VtJ%a¤d•JA‰¢H&“øàƒ ÏÝn¯ú|¢žþùCUíwh@³'YEüô§?ÅOúÓ†^O 9èJ6¹ ®Üðʯ%ädSs‡p8Lœ€¡Àf2°Z­(—+(•Ùê‹»@éúh!‚D´'׌<¶¾¾^£˜Õ š¸D))£ z×ÑçóAE …†,þaèkqd8€¥¥%Êm"]k£ì‡€“Ïp8Èd2°ÛR®X„Ó餬}¥"ÒMHØ“z]e}eàPH§ •€ú¾RÔß¿½½àõzÁ0 M²ÛíH&“‹… j.—ƒÛíF.—«9÷ÇÑÇê]r­•ˆ"›ÍV)[·niûæ›oR…AÀÆÆ†É<+4`$j |ëÖ­šx0¤–ÇãAWWZZZjXéF×ÚÚZ•‹E”ËeØl6ÙŠp¹Üô{«Ý€F}?Ã¥cÇ`¹s§JðÕÊ€°>=±7Þ0<×z‚_O!¨!¼Úr:N0 §Ó‰íímª²Ù,EäœòÔÇ· \.+nØlòýŠôÿÚÚ:¶··Q©TÀ²¬¬Ü+4ÒÐÓÓSóYdO5 =ŒHàÐ#€'NÔlÈëׯÓdåE¸wïxAÃ0Èçò`~¿‹ cÅÂÀb±ÂápH/û£Õ¦Q!áú=SÀ0õÇS••ùö:À× à7#ÜO-4²¬6|~?*²’(•ËË" …" …"UÊ÷»~ý:MûE±)’y·¡Ú§±íd r!HH¯^R ¼$¬°ÀãñÀãñ¢Þ–É¿b­€@LÊ}Ø lÞ½OÏTÝú<·[WðÉmðûîåþ~¾ï~Z]­‚Þûëws4ØS\ËËË5ÙhJˆ¯%ÖÚwEÔHqÍ µrÊÑ´ ïFvþÞçÖY:Ê`AáìF¸öªš}¯½®–– å~Ô«³³¢(Ò:ÝœSÆ$èïï˲Èf³xðàU ü1Òr²Ð³æÔ?r¯¢ª*€‘B;LHàÀ!ʼ7¸HÃåFP6Ù4<¥é×y¼ž$=!0??޳ãïþîoÑÙÙ‰ÖÖ¶]q†p7«ðuEµâw:Ñßß«Õ žç‹ÅÉd088ˆx<Žt: »Ý^·ÖáI†5Co»9Ibí¾Qv4"J@ÝtÕDOÔó»ê5|hÿ36ªb­ä5ŠvƒjDQÄgŸ}ž/"éÄððÈžá(é7¨Œ–--u@«ê}\.FF¤ïsöìYtttàòåËøôÓO‘N§‘N§é÷RÞ?Œ|Y¤sò½ü~]KoÖ<Å5;;[T®µµ5š $ʼ¨éÐ0 £ ê #D@,W&“A&“ÆÃ‡o¡¥¥Çak+Ž7Þx£©<€õõu8N8NÌÌÌ@+X\\„Óé„ èèè¨zŸz<4@²X–E±XÇqX]]Åüü<8ŽÃñãÇñðáCZiG >I>@Ø3 UqØÚÚ Q±µµer1¨ý~%‚à8¶D g=ÄQ€1¤(‹ˆÅbˆÅbt÷Ïþs¤Ó’8wî|»C4m:ü522ªhþ)Ê…J冔šðb'ËÒˆÑÊËomm­‚ÿ[[[Èd2H§ÓXYYÏó°Ûíøàƒ°µµ…çž{gÏžÅìì,ìv;VVVÐÖÖ†¶¶6LNN¢«« +++°ÛíØÞÞÆÒÒ|>666°¹¹‰ÉÉI W@ܵ+ æ]êñQ&xFH ·· ô9¥5¡`­!‚ÑÀëëëÈçs„ÆÆÆðá¯>@8ÜŽã°¶C°%ˆµµâñÀ+Y®ÅÅER¯úÞÞ^¸Ý^LM’-¼ ÃTùã‰D±Ø*xžG<¾…ááŒæT/žçQ,iϾf ïz!@H¬­á£>¢ýûZZZFkòêùð­­­hmmÃ08qâmâA”A[[:;;ÑÙÙI«û”!ƶ¶6x½^8ŒQÒñÞ½{UÍ^k.5šwDQ¤a@e!¹Êvᇠ F«@S ùíT éô6¡„íím”J’É$º»»±´´Œ±±1™Kààö¸qáÂE,--"“É"›Í î@&+ îøø1À±cÇÈö ^B<Ïó¸{÷."‘lmÅa·sÈd2xíµ×kˆ-åß™L6› >@±X¤¾ªËåÂÄÄñ¦i®¿Ÿ²üFñ™ É FÌÍÍ¡µµ‹‹‹Ñý®õAEZJ„LÖµÛíhkÛ Úívz¼×ë…×ë­¾¢öóªm€Øtx„• @9mÈD è ˜ˆÅb;®€NèÿÁƒûHo§Áq,R©ÝœÃÃ#(•J8sæ àõ×ß'w²ap˜AKKnW —>(‹¡¥¥÷îÝÀàÑ£‡ðx<à8Žräobñ•Â’ÉdÀó<îܹ––V<|øétEÒ>Ë¿ß_W–J²ÙÜŽ 6€l:áœ9s6›BøD"––d2X,ÚìYdê¡$=`·ö™ã¸ªqmzË,~Æh@ϰZ­ºdxñø>|€'&a±H-«ZZZÀ0R™°v' ÜŸ¾‡ .Œä<ð<ÅŬÅÖàñ¸ÑÒÒŠŸýìoð¥/}±X ‡’b/½ô2îÞ½K¡$ùõúè£é1°,‡7ßüuˆb~¿4ÂJIðe³Y8»ŸËåP,"‘ÈN/UØLKxUÂå÷ûÑÚÚ ›Í†ùùy¼ÿþûhmm¥¯WR‚„$÷›èÝ–“ßJ¾ùýbLÁ­­­þ( R¥mr 4¢q].g­‰þ­mm…BR‹åR ‰D¥R øÉO~‚±±q¸Ýn¬¯¯aqqÏPÿúÞ= !“Í žˆ#OP¡ÇÙ1>>ÖViƒNMM ÁÝ»wdåЊ3g΀ã8tttÀívC+(—+5©ÃW¯^EggV« ¹œÔ÷Îëõa{{Á`‚P‘ÿ|$Ò HéT¿ƒAx<ÌÏÏcbb>ÏóˆD"”à+‹¡ýÿö»gá–——Q,Q(P,ñúë¯ãÎÝ»SÁhº då¡êk–4ž¡B˜››C__ OUy"Såþ“ÝÖæ,[[[ÈçsXYYA?666ðæ›¿Žl6KɽÁÁA âW¿úÂá0Âr© Q°%ˆ–` ^|ñ%y3Ðm¡»¹>|€x<އâÛßþ-lmÅáñxáõzªÚYi5˜XZZ’}tÙlŽZùîîx½^ *úùKÄZY5¡WO¤–—5m0Ä‹/¾ˆr¹LÃ{"ommÑ(ÀíÛ·ÇFÁqúúú4ú“O>Akk+ºººª …ïß¿ÎÎNø|>ªP–——qãÆ LMM¡P(@Eiºòê*æç±º² ·Û%+¦ND"ºü@&“©S@&5q9 €Äm•h~~}}} _´­­MÌÍÍ¢T*`àv»ÀóB¡xžÇ›oþ:åÀíñ@àyŒ 080¸ÃÜ3Œ¢ûS7;0‹au5»Ãðð0`xx‘H§Îf”þÏf³ØÚÚƒ÷qñ⫘œœD[[R.kSfÖ+ ¶Õ–e)‡FÁ0 U¼«««ˆÇã4¹§µµ·oßFkk+¼^/xžÇèè(~õ«_çyÌÎÎbnnmmmhmmÏóðz½XYYÁÜÜ677©BhooÇòò2ìv;¼^/FGGQ.—qúôi¬olÀãñ #‹$ïè»JWÂ$ð:qâ~ô£Õ…hU¯ÈÔF¶·ÑÓÓK;w€ÜÔV) â• wÞB ­£G /ðèÑ#ØíN:EC„Äç¯g²Ù  íí¡ZPíX_>KÂ\uxA`µZBaDcdd§OŸF:¦¾úÖÖMúä“Oä‚§VlmmѤ¡û÷ï2 9==±±1lnnÂëõ¢X,byy¯½öm3¾“ñÉ!ÒÑP{•JýýýÈ Õ)¼êÌFÒÏŒ߾ѥÝýu˜[ésZZÛðÅ×^‡Õb‘I?K]”˜ò*w‚ÜEð‚;Ç‘Éd‘HÄe1NsÍ¥¸çÎÓ-øÑò%3™ …‚\çB[Û„áù“ WˆŽÚyNaK&ëò—þsx[[ÑÙÙ ¯×‹H$ÒpSP¢Èï#è N#“ÉÐpÃ0èììĉ'è}’#@òFGGé0Ï•••ªèƒÞop,‹P{eÅD¥Fƒ”Å@Z£ËL°ËjµîÚ×* šC"ŠŠ¹öúˆ@ V}Ÿl6 †aHÄÑÝÝS‹Ë÷îÝÃàà >ùäx<Ê@ãý==Q´¶¶T †‘0ñ<ùù9¹ÂˆÇ¥þýýUé¾ZD”Ò: BÉÔÒ= ñ8ØŽ¤R) Í:…fÃvJÁ×:žÀz=BdjÂÕ×EÔBüJNPu.Ôç& BEÍ"!S<Ðh Ø®"¶ª¢5­¼õ{6›¥sç———Q* èîî‘Xf0`YŽBç‘ÍfliÁÌÌ ÆÇDZ¶Çõ¢¥%޳#î€×ë©‚áö iÂ;Ã1[ÐÝÝ­;‡@¹r¹R©r¹,r¹\Uežô'7€h_zŽÏóp8X\\D:F$ ´h¿æìæ~­õ×éý(Š0ê´ººZó)2IÀC¸~ý:.\¸€––zA%ÿ•zmמX,†ÎÎNlo§‹ÅËI‘€P(Aàå„nw³³qùò% H<› §§ƒƒƒ€¯|å«UICÕd hEQžP³…bQJš˜˜€Û-[¢(¢\.×Xªùù9T*ÒcN§ÓÓ÷`³±D8™äTp}}p(ó&4”G!‡6› Èç󘙙A<§eÍ$ó‘ žFòöš0T(àp8°¹¹‰|>¯H±V^_UïG EÑÒÚR÷óÍZ€g,ØZE+ @ò·ÕbÕ=þªú7®!`fæ%€FF†áv{ÐÒÒ"ƒaùý`YÁ`‹Ôk€Üncãã’ßYRÒz鳉›°¸¸€­-‰ yäw´´´" R¨O =éT‰DððáC¸\.™]˲èêê†×+…ív;mÔ!6Dþ.ªzô÷÷£P(`cc™L[[[XXXÀêê*N:…?þçÏŸÇÇqúôiz.ösÀìì,ÐÊÀ+W® µµ³³³8vì666 µÃJj$Äǯú¾A 7åù Ïl˜‹‰t¢Í’‡jQÌçs8vì8r¹FGÇa·s°ÛíUQå:}úLõPÞ׈ùiåo‘Édpýú5¹ZP@&#•Ѷ´´ÀëõÂãñÒèÙxJ?›ÍâöíÛˆD"ˆF£èíRN`jê¬V«¢J°R×ç×zl}zã_úýÛívÃçó!‰Àjµ"“‘j ȼ>‚xž§…D$Kd ’577G‰ZŽãpâÄ ]%°¼¼Lsÿ§§§iˆðìÙ³èêꢓ{Óé4ff![¥E'''á°;ª¯“â‡ùj®ˆðĘïBªMpÀ@*•ÒþXÛÁ¥Ö;œ.t÷¸å(€«¥¡ïÂ÷ë…Ézÿý÷ÐÛEGG 6=X­Üâñ8HÄ I“w‡‡‡i¹†Få–jõx±Óîñxètf†aðÚk¯ÑÜRüD„œçy<|ø°ª¢.£X,¢µµÿóþO\¼xétš…„,üÕ¯~¯×‹V9"a·ÛÑß߻ݎçž{Žæ>ܺu ==½¨ˆÄb1¸\nšL¥W.¬·®_¿Žöövê–5²Mð V*•Ò$•QSU"6 zÍÃ4P@l-çe+ŸÁÌÌ#tÈ„;UƒÆŸ§%Ì,ËUU63-Gt¹ê†J‚€\.GCpõÎ ‰lœ:uªJÈ¥ögj•ççç1<<ŒóçÏÓlBÒ`tkk‹Öu¤ÓiŒŽŽRÉó<Ξ=«k Ž›’ Ä úûújŒ€~hísFHÀd2Y}0ÀZd½Þâ8%…¯òE#ògGž‰DÕY5 =oÞ¸`K Ö×bˆ­­¡·§—6áy==½èííEGG¤á¡¢±X óós(yœ\. ·ÛöövtuuÃn·ÃãqÃíö`}}æßs‡þþtt„¥¢ gž{T‡ # ¼)B!ÍDçççF‘Édv’Tç@T*ܹsÙl««+øÚ×ÞÂöv ápÑhòùÚÚÚh6 Eu@72>ÄårÁf³!›Í"ŸÏÃã‘ÎÃ0‡ÃæÇãñšbš½(‡FÈØû÷ï# V¹gU™~š!À`«Sç@ö–ÞhðÈŽØÞÞÖUÊòT=ÐÝÑÑ–e‰HyçÁ`‹¬® …BUšÑ 6XXXÀÚZ èèè@<¾…ÞÞ¨ú“”Loo§NF:½]£è²Ù,?~Œ¶¶6¸Ý.´µµÒF¥““Sðz½Šˆ@‚®Ë(µjlò©©)lmmQ¤•ÉdÇáñxðꫯâ¿øþþßÿûxçwðÚk¯U)*­’ÛfÂÜÜŠÅ"FjÚróæM|ùË_¦„‡†† a³Yát:wz%VûUÊ@r¹¡)„èS 5ü‘‰¼EQ·@‰»º»aµX¥å°ë²‚õ’Z‰(!''§ÐÑݾSr¬öq=¯Üù'ƒJE”•ÇÇŽË¥À;!@ŸÏWå&hÍ+{{!.,椽úIÃLŸÏ›Í‹Å^î”LÆj“<€L&ƒwÞy‡v öx<ôrÎ~ò“ŸÐçI¿eU¤ú<“È@±X¤}It€dk’ø&“A‘çðûqæÌsº³D•ÚS»’ä1åßÍòS¦xJ.²‰¤¾Ð35nA•o®31¸á 0-AOÄÁ±‰xÇã™ð<ññc4†n”¬Ü\ ‹ÈdÒˆÇp»]U¡©F|Õ*?XQO`ÔÄè}8ŽCOOÕöo|€Ô±™ô?¼sç<&&&ðÞ{ïÉÖzˆLeøÑGá÷ÿ÷qéÒ%D£Q´¶¶VEÒé4Z[[Ñ×ׇ¹¹9<'»\_úÒ—äˆHÜG(’»Oƒ%¨C4œ«»÷`rO™åßÍqv»ï¾û.}L™uæñz‘Éd›¸öµ =êA×D"·Û¥¥%p‡Çghèã8„Øy<Ž•„fpp¨á¡¢d---BEœ?.—«& Ø´@ý‚ £†›Z•C4;&×6Ä©«ÉdðèÑ#¼ùæ›´–`kk«ÊEX]]ÅíÛ·iI0 eè‘ò`u]>ù^ƒƒC(—ËhkoG4ÅövZÁˆµ—X±HÓ‘½îÇÃ.| À^NšÖ…Òª³§i  6N¤ˆl. ‡ /“ɤ<@@?½°ëëë…BX__“án===¸yó&Âá0G"!`qq'ON"ä¨oÞ#[ÆÚˆ€V¡ZÐÓÓƒB¡(÷Td*èOH@UE¡V$À àã?ÆÈȈf讞eYtttÐbAªÊkIi4Éœ˜˜@&“‘ XéHü´š€è»€Ó4ø€tz›6l!ÊF¬©'0‹¦¢ š<™LÒÚm艣Â0 ÝN;d^Ü®#(€È Qx-)/! \zí¿ô>Z/E˜Þïé©[ì“ÿöù|˜˜˜€Óé¤Ê¶P( ŸÏSôòË_þÏ?ÿÃììóaÑ'Cx€õéiôŸ?_å'»\.X­VŠ\ÆÇÇáp8L&qïÞ=D"Ü»wº~ø!~ï÷~…B«««´‰ÇŸüÉŸ  "‰àرcp:òÕ% ât:iÊo£çBËõÑJ^YYÑ,ù59€ŒNž<‰÷ß¿ñ‹$ZIù„™|A§%`uu¹\'¨U&-¢A€ ày^Î_ÃÚÚÆÆÆ0== Ç`0ˆ–`Ý=½Èf2xã_C°¥¥¡ˆ€ ø«¿úKÌÍÍá7~­jB/9'ÊNÀFçPÝߨ$xC‘ ¤—‡«fê£P(àÔ©S¸wï‚Á µ¦sssX]]Åêê*Ž;F] "ôù|?ÿùÏ111;wîà›ßü&îܹƒD"ÁÁAœ9s¦áŠ@±!‰º(@/›”<®×Ȭx†‹dŠ‹EÍ ¨MÖöƒyøà>FGÇpz ܺun·gÇìì,&&ŽãÊ• …±¾¾†d2‰®®n,//! É•-ðÀíöàÂ…W ¶Táï…åªoï¥Góù’Éìv;ü~?æææ099E#ÊF§Í¢îÄ äa\l‡4ûpji©©¡áp˜  FŽÏçóÔuèïïÇ /¼€D"X,F±òø³?û3*øõPX  êr£ôEÊ(€Ñ¹ &8¨«¶ý—* í>¤xvvƒØN¥À²"‘NØíRóO¥¥%É?¤0( " ÕL’RhÐpD Öíþâ/þýýý¸ví3ttDÏçpñâ«´Hu®ã‘eBôœ,--! ÂjµVOám‚¥'‰DÏ?ÿ<åˆ" Õ| ÃP® ™Lbuu‰D‚òÆ@}nDTYQ¬VZSH#Ó8€®€ÖßÊfŽ00ôdØlxéåW/¼øÒNCPf' Ç«f*¡w]†[ÛÇb1jùb± …< ^xá$“ Ü»'ùÉ‘HDnö9ÕP$ ~utc³àäØ666ðá‡ÂétâäÉ“èììD2™D¡P@GGÇ®Êz‰ðë qìØ±½‡5ª §˜ø£¬'QNj´Ð,zÆ‹ø ×¯_ÇÛo¿]õœÕj­®÷Q„}> ®ï’P Ópþ~½¼ÀÜÜ,VWc( `d¡ÆoI @‚Á  Q§Ñ§Áh¬&1n7ÄlÖP¬ß¿Ó_ÿ:¦§§ÑÛÛ‹ÿøÇxë­·°°°´L÷âÅ‹uû'‘Pj œ=±ö~©\Ò½~$”l’€‡¨/Tgg'mà!Å÷U  X'"Àèa¦¡ «^…|…bÁ@Ó÷îÁátâÞ½i<ÿüy‚AttD LîïïoÚÒ×k_¥>WìÀ ·nçˆ"ÆÇÇ1<<,"pùòeœ?—.]B2™ÄÔÔ~ðƒÀápà7~ã7pïÞ=¤R)œ?þ©(Ýs`T*Ý1rf1ÐÁ^¤ µÑ@=–‹´øã¤aã6^šÂ^( P(`~~kk1:åÖÊ嬳ô=;:"*‚I{´8Yü8Î^5¡1P ë! …¢4aÈjµâ¹çžÃùóça±Xðï|ü1ýþ}ô’ɤìÎð_þËÁ©S§(²éèèÐâ_üâxá…4³ Ézüø1Ð LF€’ñ¯ýÍb–ÛÜÜÔ"ÓDXèAµGÔ'‡ eŸJ&±½Boo_Í`B¡€b±€d2…h4ŠþðÿC @¡P@ €ÃáÀÏ~ö3tttHÂï Xð±±qIh¦Jøõ#JåR¬JG6r ýÿ&x#a;wî†ÁØØÎ;‡ùùyôõõ¡££?øÁ(ÃíÚ5D"Äb1üîïþ.®]»†d2‰D"§Ó‰?ÿó?§ @© È€ÎÇc`` ‰ ž+ Ln,dj*€¾HKnõÚV¶RJ¶b±A°²¼  €kŸ}‡Ã†aàÀ€Ýî€ßÀœ>s‹‹ –6´Ý‡Ãÿõ¿þ_œ<9‰›7oâ×~í ÌÏÏÉlqÑhnÞ¼h4ŠsçÎQAÐí¨ãKÄb1©Ž!@±PÀµk×àp8e«ŸÇµk×ðÝïþ6z{{ Ë›9WÖP¨.(¦Óº( ž bES©VWWL&ñæ›o¢¿¿Ÿ¿ººŠb±ˆ|^úÍ?Æ‹/¾X Ð ¥«_×ÖÞVõ ^¿~½ªÒô°±üŸË()Ø™ŸŸ7äÔ0Ûçõ‚³Û108„íÔ6¾üæ›øèè而”´¶Ão¼|¾ˆ“'ORádPôÑ‘¥W<=}³³sp8(Êá5â;çóyD£} '£4’ ˆ¡¿µA«Q…ª~‡úåÀcÇŽ!‘Hè÷vÔùFcÀ”x¨\*W=§lAf·ÛdàÀ+€f‚(—º’OÝ#Ðét¢P(jrßøú7À(ãÿªVÑÿûo~»Š¡otÔw#ßÿÝ_þ ÄtttàÔéSp8œp:TÉ성3妎Ð×KmE=Ÿ_¾9a<ðIÌPÞ×Êý×´ü5S€u¢Š4èl6cè΃f9ð>¯ÝœPe@}±Ô\êÿ®ÓõSC"6–‹­Âáp¢P(`n~}}ýèèèÀG}ˆ±±q\|õU‰edA"bÓ%­zþ¿(ŠÔ¨Ç\¿rÑáajžÆüæ)ªÁ¿ … ÖùÎZ¥iÍ„(V 45À3@z¤^€\\­á–Ô0L ;\l`Ô7éA \û·?“-‰$ôÉdÅ¢í“É$îOO㻿ý;8þyŒÕ¯þ¼ÝÀ}½rYò¸Mv]ê•ô“ŸÀúoàòåËèííÅØØxž§pþY5ÑFÚ‘€š¿Å:d±â}µ€Y|€am€¨ýkÅX\\D4E*•ÂÛ·Fá÷ûá§J„>…î#âæÍ›p844øÖ[o£P( îÀ•+#íC__‡³&¤táâÅ ƒ Øî=¸XÊ AFî€ÏçÃÝ»wéf/‹¸zõ*^yå\¾|áp…BvzzM@tPŽÞ¹R×?ÔQ¬†³%LppÏóô5u£µ#ðñÇÁïó#IcscwïÞÁúú:Nœ<‰ù…yü~¤nÝD8Ü›7oà«_}‹Ž܇Ýî ÜïàÆxå• 8wîæö[Œ:„”Un©T² ÕG,}ÕQŒ/½ôÚŽG&“Áòò2ü~?õ“¥!%À_ÿõ_g:0Bûô]/ Xù¸²QŒzÀ,y¬ž0ËÐbY¶JÛˆ迹± ¿Ï»wî`âøqüøýœ8qÅbÿãÿùøý E,,,àç?ÿ[œ={áp£££p8¤<åPn"ü5›Þ°a¨ö7_X˜Ã»ï^Âoþæo6¨<õI@‹ÇSwJ0¡C½^/‚A)“Ñjµâå—_†Ýn‡Ãá@*•¢¥¼€:»téUŠDLMMÑøþ~òšŠ­¦h­BPŽ•' •Y­V3 p˜€(ŠØØØ )#v»™LV3%øåW^Ã0øÝã¿_S èp8ðÒË/KJ!Àëo¼b¡‡Ã)×½tðÙMÁB±ˆXl…|##c²«#ù¤{åDQ§¨7 P™¤|_¿ß†að…/|^“ÑÑQšMHØ@ @ï'“IüÕ_ýE¤‹(Š4ƒðW¿ú9YÊápÐäŸïÿûøö·¿M«õ0NmN€XשRæåt:w_a*€W ØóàE¿ßT*¥yªú*ËxU\€Ïë5¬LMMaddT®à  êùûM¡›yãÆ ¼¡Ã7)9eÒiòÝï~—&k½ûÅbxþùçqþüyØív<ÿüó´N`uu•¦ ÿÞïýž&Ÿ Oö)gKQ¢F­ótòäIÓ8è‹L¨mX(ì‘:º­»vƒH|¡PÀØØ Å"RÉ$®_¿†óNúúúñ;¿ó;’ÂEŒŽŒBE”ËÒ¸om_Ëis@€ @ÙëÅG}„çž{.—kW)Á¤¢ÐáS†a055%‡Gwj%†Á›o¾ ´éé6\P º¨ T'Jo,X©TÚõ~´X,(—˦xZKéJ\¿~SSSšƒ0ô…»¶<؈¡×{ZKÐS©$b±5¬­Åäqàøoÿí¿brr ©Tü‘TH36Ž/ùM)TÈè',ÕC– Ãhþj­| n`E¹ÔVOŒ¡½½~ø!, ^ýu|ÿûßÇ?øÿ ÊÛ ©W“ÿ ê DÒƒ›!µN”¨Ð¢Á1ÊŽRYEÇ `W@½¹õ繋ša@M… ¿5éÖcw8 Ç{%“)‹¬­­ÉÌx÷ïß°SO^(°¶£Vp~^jòÊEw]õç‘_»°0»C[[{•пS kq-¢(Ââv×å¯^Å+ÿìŸáñãÇH§ÓXXXÀÈÈ._¾LÛ‚E£Qøý~Äb±ªY‚Oº+QŸ½Ä é<Õ~¶²`£´©ˆ2ðûýU€}>_}"FÜqÒ™42é †ÁÒÒ"'z{{ÑÊì¿·nÞÀ‰““øÑ~ˆ¯~õk¸yóR© ‡ 0 è}e¦ ß/±Ûßüæ·jªu˃U0÷êÕ+øú׿! QÔ'œ666°²²‡ÃN«õæÂÀ€/}éKÈf³°Z­ØØØ€ÃáÀƒ‹Å0??ÑÑQ|á _À•+Wh«p©T:Y!ìGp§òYíâˆÐòózzºé}eH½Gq*ÐV{eMY–­ú[™,ãóz°²J6CõF{ïòe0 ƒÇgÐÝÓ¾ÈÃï÷£X,`aq…bëëkH¥R°;X˜_À‰““HÊHcmm ÅbÑh” B2™ÄØØ(üþ@åh(H±§§§a·ÛÁÙíË5ü©TJñûôÏ[:–›P©Ä›.²àׯçóÁjµâìÙ³€³gÏb{{kkkôF ôÚÚ~ö³Ÿarr©TŠ–KKèG û):ŸÏëμ~ý:N:UgÏè´щ(—2bD|x³è¬_|‘F´.X ¨ƒû»ºº°µµŸÏ¿Ï‡žÞ(666pòÄ 0ò ÏÛ·nÁn'I/v@í"™JáäÉ“t:°ÄWújâ*¿æë×Q(ð7óSôõõÑÂÎq8{ö ðûý5¡À;wî ¥%»Ýíír¹œ,¤_Àöö6mkn;P+VVFËçóÁï÷£·· Ãàk_ûÖÖÖpÿþ}JòÅb1\ºt ‡_úÒ—ð×ý׸pAÊ–t:èèè@,£œL"3WWW©0ttþÐâ2™Œî\åë/\¸`"€gšÑ²d³«— B£(÷ÀàÐ,–çiPoo¯Ô-@(Æ‹/ùá°;5ÀK/¿,}O¿O%aèp8f§ÀhjêÆÆÆªª{£Qˆr{p¥?;û¹\¡Pù|¥R n·§*ù§ þ‹"œ'N +7ÕCÅtšÎ s´~2F‡á÷ûqîÜ98D£QÄb1¤R):Pôþýû´"É”*$?B__>üðCô÷÷c||¼nJ±6C*¨+aùÑÝÝÝ"5‹ØR2¶ï¾ûncZ[Yök”ºÃøë ö¨ÐB7n\G2™Ãv»$@—.½‹ÿã_ýŸ`LÉV¯R©@¬TPE:`ss•J6› ÙlápÆÇÇaµZ‘J¥¨Ð”Ëåºñ#`}zëëëUS{A2ʬ½h4Šh4Šb±(s ßD*•ÂÚÚ¦§§1==‹/¢¯¯cccH¥RtŒiŽRV^íé@Ú‘=¨ŸÉdLà  '­e•Ä[£a@£ˆ€dÍóX[[G__Tfÿ×J%1??p¸óósøÖ·~ÉdJ&Ñæ066@Š 8Ã˜ßÆÆ²Ù,l6º»»qìØ„œZ[¡Í4õÎi3ÍA‰ßºu ±X ]]],Ë6ÍØ_»££Å… ªbý$¨¯¯Éd’vFÒR4´F3Œ48JHàÈFÔ$`m['‘îj‘ѾÀÅbƧS²8·nÝBoo/ŠÅ"Báp î…? ä×ÂÂNž<‰µµ5üð‡?¤õÉd££c˜œœÄ¥K—ÑÑÆ¥K¯“““r¯€ˆvD@­ŒäM̲,z{{aµÚàóyå‘aúMC´Æ‚õSíZZZ099‰ùùyäóyX,Êžg³Y¸Ýî]—õ*‡‹*¿¯V.9žçùškžL&áõú <,«6ùg S©-2‹P:íííxøð!€Ú–a;\€$ôŸ\½‚©S§±²²Œ{wïbhhŒ…ÁâÂ"nß¾…P(ŒábápÅBþ@?úÑ022‚……yŒŒŒâÖ­›4{íäÉIJ†IyðLNž„ßÀw¾óæ#ʉ¾òùp¹\hkk“…^dØÒÒ …|UÙ´¨~Þ¢ˆ²är9är9p‡ååe\½zo¼ñ®^½Š‹/Ö°õûÝDpQéäá¶övج6jÁ³Ù,ÚÚÚª'úеî@OO}ߢC²^;°F¹+S<ÅõÒK/áßý»§û<‰X­VE^xõÛÜØDÿÀ ~þwK™~⫆Â!ø}ÃýÎ;ïÀðc;•ÂK/½Œ‘‘jùý?†GFÐ`à÷ûø}v` ¥:g2ˆ¢ˆ¥¥Eˆ¢²ÚQiõE r1OÔ$ 7Ô$µ¼Œ–Þ^\¼xV«ÛÛÛtDz6›¥L2™ÄíÛ·ÁqÜn7X–ÕlÙ¾…@Œǡ§§wïÞ¥îÒââ"mßµ¼¼Ò4üW†•déQ‹j`„r¹\MÉš(€f¯?i(äÍ[7ð…sçát8w€±0°Ê]! áW¾ò,,.Àa—2ýž“cá¤R°·7ZÕ<: §Ùòà¿üË¿ÄÀ@?xžG"‘ÏóˆtvÒÖÕJKÏóEx<^X­V¹èFÄÈÈ(Òé´fj+«°|z<¤VVÐÒÛ[S!×ÞÞ†apöìYê†%“IÊ‚@ÿ€îînÍëÔ¨Èd2Èf³hiiÁàà Âá0Hݡϟ?_Eà©£"vÚ}ïçX0Sìb©}¸Ý®|>O/Ú¥K—Œ^UÐn·ã _8/ =Ã@«' yÝððHˆ×Bvíñ^ÍDxž§B308€P{KK‹xñ¥—`µÚj"ù|Ž A*µÎÎNd2itw÷T‰r£ãÁk«C¶.àÅ_¤œ@.—£Â¿¾¾NÑÂòò2FGGÁ²,‚Á <mëHcÀ‰zzzès¢(‚çyŒ2'‡!Êç`dd>¿ž—ˉr¹¢Kûe°¾¾®K–ê…–MpT¢2"Ð ¦)@Z~ãªÁjA'ðY<~<AðúëoàÓO?Ïóà8Ï¿ð*• ÚÛÛ«„^¹œN'Z[[ )‰5>>Ç-‡³nZ<€Àµk×Ðrì²ÙlMŸÖ}·Û ·ÛM}ë‘‘$ ú›fgg‘H$°¾¾Ž×_KKK`Y–"•›7o"cqq‘úëJ¿]yýC¡*•2Êå²"Aªº˜ˆúÅa¤H;qjŽ|@«5xÚ@×EØt^P¸äÆ@9d³9 Èå²ÈfsH&Á ´ùY–Ãúúš ‹[ õóƒÁ 8Ž“à²þ¬oÀ•+WðÜsÏaxxDÎ÷¯Ðˆ€ZYh¶¿FcCBîÞ½ ·Û®®.aiÔ‡gY¡P Ãà‹_ü"u#666 ‘ÉdÀ²,îß¿3gÎÀãñ`zzš")Ï!l ´ôÊ‚µçêi€ëׯÓn@fà ½:d …jfT*¢.@DzssS¾¬¬J„R{(„ ¬®¬`hxÇ‚c9É…‘­šÛíÆ¯>x/¼ø>øà}ôõõÓX}wwµöÙl@ÝÝÝðxÜèïDZ´ýš 'ôäWå²Y°¬M‡Ó×>_ÍN €H‰fffpìØ±=“zn·§Êú €ã8œ8qÇa``¹\N3ï@K¸EQ¿ÿQÐÈp˜Õ€t52&»X,Ân·Ãår"“É)@áôÿì³O199…D"޵µ50 °°ðKôF£( ‚D&2€Ëí½»wàr»¥”Ltñ‚€‘áð¼ä· ‚€\N‚º¡PˆBá@ Xå54Bˆ)É+å&&,|kk[5ácæ´J‚-²…5j "`ýýýÂ7pãÆ ´··Ãår! bee…òœÜ~­Y…ªÎ§hãær¹jŽÉd2B ?X¦Ó8vX•žT: §·§ê·×¨.ª %šàà-„—J%zÑ”M)|´3EH Þ¥ÿò…<ÖÖb4?Üï÷Ó1Þ.· ËÁ% ËÍ7’?£½¯n—¹\íí혘˜üúW¾ª1N¬qæ[Û?M “Î`ii .— p:è@#`UEŽþ~îÀÀN9–Ôüs‡•ibñÜÜŒŒŒP…£â½ õš™™Áââ"Ün7Ž?Žt: ŸÏ‡‡BEd³ÙªV^5]Ec>Dù[Mð”ɽݬt:­ÛÛ½zïĉ“àX)v-ufèpP¨|üh4 ·ûXys+G}···ï{D2³Ù,l¬ ©T,ËÂï÷ÃétÂïó¡"#„x| @¢(刢(õ:HoSåÖhI0y\-ƒƒƒ4˜„YI4g~~óóó Ãn·×À÷½(ânå>22‚Û·oCÐÖÚ ›Ížç8O#’!ÿ¯ÕPÖh(ˆY¼‹Œˆ~Z DTÓÿŠÇ¼^ S#Œ†´úÆ ƒšŒ¨ïó<\.‡D"AàˆÁÉ““Ua@Roannñøg¸xñU`ʃ´áÒ"wôä\„†Q›y—/ôüü<r¹\mOyQ„P*cYlll ]ž¾›J&±¾¾·ÛA|<¸·Ûl6‹P(DSg³Ù,xžG8Ïóƒ‡ÃºBO`¬ÃဵÁép```•J§OŸ¡!A£mD’û¥R ÛÛÛ¨T¤JC‹ÅR²»\.6$ @)¸X__äÏórĤ÷ï߇Çã¡Ï´ «òöÉyp»Ý¨¨Êžõ&‹Ðî÷·,@±Ùlf&àABõ´ì‰'pëÖ-M@¢àóy‘Éfu|p%¡ÎÎassv;†a°¹µ ŽeÁ²üîÝ»‹ööv°rÐívÃåvÓW¯\ÁÔÔ>|€¹¹9,//¡««‚ Áy ÖgÑÕÕ ·Û-‡`Y®*$VS@,¿ãRFîܹƒÉÉI´¶´ÂîpT uD@M6‚,2Dzµµ…••¸ÝnD£Ñ*؈O˜|2D´«« ´È()+JóO$8~ü8nß¾M†f„ÁÁéVÈ·ÒUª7Ü,>@‘Aª"Ä?][[S@SÇ«;CÌÍÏã8øý~\¿q ½=½xüxmmítƒžœ<‰h´,Ë‚åXÌÏÏ#—ËÂår#•Jâ…^ÀÆÆ:²¹\.·¼É»ÑjG0Ërà8GÒŸUÁŸ>nl‘D8].tuuId XiØUj$ˆà”›d’üþGÁï÷W¥ð6âë]‚ˆ%“IšÙ/.{íµ×HÉ@ʨ‚¨3ôSEƒé@NJ؉ÕFKÔÓœMp€‘€²äƸpáB]Á!ÿòy ´µ¶Áïó¡µ­Mjs-+·Ë0Œ4Táã’X¸Pê„ÓåÆo¼—Û#ÉÈÑT1»ë ¤\¹\EžG2‘ÀÆÆ:Ξý‚¶•kp2p#îS*ÑnC¤ä™t`æ8©TŠB~-Ö(ãoTÿ¯V6kkkUî€ò· ¼«Õ¢Ä>Uç‡t_Ò;'Í1Ë›RQÑ{ƒCCà8Æ‚çžû‚\ hUöUKëøø±‘¦0×ÝШo†i." þ‡"›Ë‚µÙpêÔiÉÏבûR©Aà‘NgP*•h-}#Ð_ùغ<»Z[[aµZñÑGU%mll ³³“ 1±äõB£ÊAy?›Íb}}ñxœæµ½ÂúÆF5|×9?¤œ[ýö2ÈTÏ 4ÚŠ„•âg³±–O®dPŸéßSÐðüðCª”ó÷sHÈôô4u†GFð“ÿCCCr-ÀÚl59ÁÊ3”Τ씓jCMÉ,:< B-ì5Œ±ž,Š ˆ¡ 7.T¡€„ ç 10X__ÃÒÒÜn7xžG{{@”,W*U_}ye‰œÛØÜ€XÑÝÝååerÔRŠõP€Uã8Òœ4&ÙÜÜ„ XYY¡¹dð&A}}}”<ÝBÒ´‚@£'R=Kû#nll¢¥µEþkC|²o>øàƒC é?w @”$ŽÏç«JîPF8;± 2£CãĶS)¸Üéçv¹±±¹€_¶r ¡Ïå²p¹=ô½’‰XŽCIn‘Íf©À'I©¸ˆãÀó‹Áëñ"‹a{;…é{÷pæÌsH&°Z­hmmAGGR©dUÊ4‰42Èj@"’ëÐÖÖ†aht —Ëaaa<ÏSRöÝwߥcáIãÏ`0ØpƒÑû÷ïãüùóT±÷÷÷£X,â…^€ÃáÀòò²AP$˜‰ªÁ b% Ý!S“9IÐq#Ìb ¼”5âdÍÍÍÑvNÄÏ#U^;í>´íx>—E¡Pâö%[2Ù584„O?ýÈær`äͲ0?óÏ¿FöƒÁ©dŠ*â'ó‚€¾¾>\½rÇÁ²’Uùäª÷÷ûå—2˜™y„Á¡!:Óír`è8°{w¥ü€G¢³S mIÝpxtvuÑ:–ãpñÕWj¡: X]4dƒ³Ù,’É$VV–e°axd„&ÂTD•rCÃ#rÊpE×DZX, õ€Û—/Ãâøñã(•Jèììl8ÇŸeY ý©F •J!™LÂívcccÉd’f ’Ä’1¸¼¼Œ/~ñ‹uóÔÃ? úµ·SEÚ.ßW*=Ь8D ¡ÑX€(B|>?q³rºêàààÄÉ“;îÀÐÙÁÆæ&\.ž{Nêèr»k^W%á €Z¿m~~‚À#•J¡§§Á–VmŠ[§È¥^*°Þc^¯¢œDZ½½M˱wCêISTK¥²Ù¬V•+ GFFàñxpüøñ:×[¬…ùP¥+ª9Ž«–ªVårÙä¾×?N󹪆 ô…Âè“O&'§ÀXX,V9Ä0:3ÅEHý ÂŽ£î_›>T*„D"NŸ_ZZD{{;îß–µ!›ÍáÕW¿H§þT4_ª(ŠU”* *6Mgg'úΟÏóˆÅbØÜܤÖ€f@£,:)\"J¡‚Pë·ùR£ Ý’¥*•ØkDÊT .Žãꎮڋ" “hë %™J«÷ ©^€iŽéGƒáBÅCwîÜÆúúNŸ>¥%‰¹—šŒH–*•JbppN§K³Óf¦¿Ü¿?r¹¬1,¥>ôW+/§ÓIÓ–yžÇÌÌ ±°°€ÁÁAp—Ë¥›°× V³”ÿEM%¨>Wù|.—³ <~üØŒ$ШvU6mP ²ßﯩ ÐÅëLÖ™flÝ *î%“ $ AjIûûûé€O¿ß¶¶v´¶¶ê–«æóy8Yn…B¼  P(P]}®í ˜Z©î·OÂdاËå´œ0är¹h4€ôP q©T2dÿµÖòò2ºººhx4Ðï8== «Õ §Ó‰@0 cÑEÊ6òD ,//Wuj¤dÙ¬8Ké‡vZÙ„D|>¯qÐHB„ˆíÔ6X9—;•ËJÅC‘ÎþE%Adò‹ €d*%…“I¸=nÌÍÎÁ-‘ªÀsçÎe90 ªü^²IÛäa×S©$¬V+¬V>¹zíí!ø~dÒiäóyX­Vøäs9looWµÝJË4ŒŸÜß–«åÔZ9 Èår!•JÑä Žãðé§Ÿb||©TJn¦" Y__Ç£GpìØ1êó“tb"PKKK4Šâv»ñÞ{ïák_û>ûì3„B!¸Ýn´µµ¡X,JónÞ„ÍfÃé3g**øi)£)J@9L¹¯;ñ÷¹ óù<…¦Êì4­¤¦2‹Èçó²å±´¸—Û Že©…ÄÂÂ<¼ÍM)Ý”e9ܼyÑ^©BîÞ½{òÿwÑÙÙU5£¯¯W¯^A{»Ô'pcc@Ç!;³î%··SˆÅÖËeÑÙٛ͡$ —PÛãÛå†ÇãÅÜÜl H»É·¤˜?«ç@ãÖÖVÅ´"ézlÊä(éôÉ'ŸTôøý~°,‹••îÛØØ E8$ü'm3®l7H¡×J¥‚ѱ1  R‘zú{Üž.Téç¡gY¶J©ª[§á?*Gv:°:É¥®ã¯ÂîW¯^ÁÅ‹¯âîÝ;ØÞ–REYŽDzX]]Ek[%¼AÀàÐþü~?\.VWWäÙyYºy%¢½½n¹‘èÅ‹¯‚eY‚A0˜ OÓÑ‹\.GgÛ[­6x<îÙå2òù8»•ŠH;àÔ²*(  çÛß>øÙÙYúiVB©„t: »ÝN­‘P8NôööÒD­öövª777ñüóÏÓëËq666ª”åòò2USSSØØØ@?DQĹsçèçß¾}›6íééE¹RF¥\®jU”ÀãñÐç[[[«"Ê0 é¨õ{Íb =®§§YÕ@¢÷2émx½>lmÅátºÀ²"‘Näó98].?~,ÇJÙnäxfç"h“+s¹ü^{íuòãj€F\€vA±†Ñ_\\@ÿ€žE©–b9ÅŒZëy…ØÃaœûö·QøÚ×pûþɇ«¾Ù­[·ÐÝÝr¹Œžž¸\®†}x¿ßOùš¡¡¡ªïär¹hÒÍðð0Íu åÂêŽÁÊuìØ1)-º¦!ˆ†o#ßw»Ý”R'W©Q‚ÅbÑJ-‹År ÛŠÙr`-Mì÷ûkµ³kçõúpêÔ)0ŒmmmrSP«´aUa@½ˆñ÷µ:É6Lª")©‰D<Ï£Xäa³Ù0??'iÑd¹=¯J¹H8óïH¾x$‚—þïÿïýÓJ•ÀÜíÛ˜|å¸\.¸\.òyM©Õ‹jIk£yÍ¢€uZµÇ² 8Ž¥GÖ××000¨Y`´¬6<ZZZàr¹ªrù+¶\üGÿ¨æ|FFðò¿ÿ÷ø›ï}¯êñŽŽŽ*ækk ÷ïßÇñãÇár¹(O²Cj6§šA šÊÍÄqôWúj >€ª(À òLF"üZÆTH1 Íá ÊaµZµ²jîk'ŠÈçòÈå%K·M" À±677ÐíC*™Dgg'rÙìNJ°("——šb ¼"\YYF¨=„‡H“†ä©B_ùÊ×À0Ãkd£K$•ÏçÓz#äïr¹wPâ×ב0øöÛɃ4jJªÏœÁËø‡¸ù£i a?|>AÀÌÌ ï»\.ê÷dЬ…WÞŸŸŸG6›ÅÄÄfggiË0åüx‡íímU­ÁD• ÊS+ Xé&·@ úV4pdÊÕ«©ŒÂè/"Ÿ/ÈE>"M4a`ss .— >¿ù\‹‹ 46írIqèÍM¬®® ­­]®| Ÿ~ú ‡†‘J%±¹±!UÂårxŸ“çŒH#µ³9=±kÊŠ…¶¶6«,r¥RAzc–PÇþá?4<×C_ûÊ:ÖTæ?~\Ž‚ähÐçóáã?®"ÿB`ñ/ù˘ŸŸGgg'ÍP+d2‰ ™L" áÎ;X^^F__ŠÅ"|>xžÇ;wÐ×ßöö6 Ý®àr¹jHÀrYš4L€² ²Ö߇)`;*¯ôÉvuTÐþöí[?†D<Žt:¥¥%lmmb``‹‹ hÍ·ÁåtÁï—xŸß’ ‘"êQT0óè¡l Ýp¹Ü`Yn·KjÆ0!# ƒööÆ:A½h?U,±²"e¹èO`nÀ ÿ쟕thGrÿØ[oéö¤pZkk+½6$Lér¹àr¹°¹¹‰{÷îAøý~:H„4]]YY¡ME¢Ñ(8ŽC4¥F.^¼ˆl6‹`0ˆ@ @³%777iKo–eáªÊÝáÈ¿$H~‹ÛíÖlN" „Í'Y‚î1«ÕjFž”ðëNºÕ¸8;äŸ6]D¼y§Ó‰ôö6œN'íӌʋLFUPú˱TT_~ùÀÉ“'%e¡Tç³ëŽ«º[Uÿn¦ª p É—ÞÆúÚ¬Vk ‘•|ü‰ ´NLìé:èAv—Ë…ÑÑQªR©r¹R©íêsúôi0 ƒ¡¡!$“I:Yhee…&tÀ²,%u_|ñEú9ËËËhkk£#ÁúúúP.W´YAp{$ßÚÚ¢‚®¥ðˆ @™ðÊóo=CEШPVFvóøÄq0‹4‘€;rÊTÙ£ˆ»>)ì™(T--䣵66Ö‘N§Á²,UäøJ¥ð<ÚäÚ~%20BÍúíÊû„ˆD"!¨Ÿ#ßÏårQÇï÷ëÎ €3gÎPkÝÙÕEG¥ÕNÚQ¶•J…΋¨T*t“ú·W@™(d’€OÙ·W ½RøÉ…9þ<>úè#Úá¥X,âÒ¥K´+ÐÜÜúúú`³Z«Y± A·;hsL¿Î;¢†i8¼B!ÕÕUJÆY­Vyà©…ÂØJ¥–eÑ:4«ÕŠb±ˆJ¥"5mP ì•Ô3"£Ñ(M j$@ybEÅi5XRQ¬¶úJ T®SSS5‚zÇ,zÊŠ‚5êæ ‚ Ô´«R^4—›X…Êý”5uäWkûì¥<%«…³\.c}} ©T 6› ‡ÇÁf³QáW’`áñqØä<}AhC»Ý^uÂ~•õî°¶D˜8|éô6ü~Ÿf›5u€2Z ¥cRС+V[}¥å'L-y Ïó ¿`4¸M…° “ÿ$P€‘]S76¤ù$¯Þf³ÑQZR¥ •2×äüÙZ[Q.—Á0 ¬V+J¥J¥ŠÅ¢TVìpÀétÖXêF9€ýœÐH+xÝ4U”W„ ÿ)@3 BLð„ݵPjèæÞ؈C¯Ó»_3¨IЄrØÙÄÕ9 ét››H¥¶!Ф·ÙlTø•k)%*P†µAW,é «ÕJ‚×ë…ÛíÞi(ú-|S At ™kÙ3$¨•pT›‚ªj@õ…W‡iˆÕ2jç¤{!÷Âììb´x¡P@2™@2™Äöv¥’ °î6*ðj@€2  Œu[,‚‹Å›ÍVÃ|¬P(Ðø>É'JÁn·ÓpÉ5Ø…Ðr€.ᯚEÚ~Ûèo#ÅLJ«¯Ç;™ à)²yËårÕPPåź~ý:.\¸°“1¦ÅUA¢J(÷ 4ë"d2 d3¤RRÃ¥Õ¶X,4¥—Ä÷‰ ÖŸÜ”$ á&B_*•j”ª’W*ò‚ Ђ%¥¯ìõza±X¨r ‚Ôì?üo` °H¢4šb #Ë¿ÿþ s¶Ã*ôzM¹\ÆéÓ§ñÉ'Ÿ •JQRð_ü‹@ €ÞÞ^ÌÍÍáâÅ‹U>~¤¯k(9g…A…|…b¹\%¡„tzår™L¦šW*b٠ɧVä%üW"rþˆ±Ùl† €ü­v½´Òi‹Å"á§&Ø|>mÝe³Ùàr¹¨’hV!è[gÉÁ¨%òNŸ>]õ~äûŽŽŽVÕ˜à ¿ú1åFüæ7¿‰»wïâý÷߯zÝ¿ü—ÿú§ŠÕÕUÄb1ø|^,/‹ ²íÆ5úõP@6—E¥\B6›C¹RF±PD±X@±XD±X¬ò¹•7BÜ)#L„•¬Òº¸¯T jÿ_ëü1 C»\.SÅ¡T°jÁ×~5[®Çžçóyˆ¢ˆt:]“‚KP á¼^/Uõ8ò¿ d³>N“K …þøÿßþö·k…[ÀŠ¢X,€çyŠ E”Ëed³Y0 ƒííT͆Ñr¥p+­½ZàÉÿäFš·Ößjt Þ¼Ä‡' @ËçW ºÞcz @‹I×S J%_*•Àóz<ƒÖMùêï¨äi” @9ÁXMQ+ßf˜L°G¡×Û¼Äj+ ’ÓN„ÜWòÊ¢% Z @Kèô@½€žÐz­–0ëÁûz‚­÷·z#×-¶Ñ‰Æè)Žzùz9JWDƒÐrŒ€ú+­½2uZ‹L­wÎK4à@—iU­¬¬ZS &Ù ÊûF@ ñµ¼z!"#ÁÖf=¡5úßÈÚmB-ô£õ|½|}=RQë1#~ÁH™è•)-îA@6 §*y­kÚȹ2@“–¾™×˜¯&Ô훈o¨Œc«7£V ^Ï÷3òé,º‘€7b¹QOÒÕS.õPƒÖ9×R(½°¢ …^Ôµ¿¯ü[Ké›ÀS@õXk5Y¥äˆRÐbµZiïÆ×®ßõ„Åè~#ÜhîfsÖãôPC#Ÿk”!g”Ò«×üEyµZz둌êï§&5ú»ž¢>,ìÿ‘!ÕÖO½AÈES"µuÐ 3…øŒ2ÁŒRE›ñËwƒ„ž†Uª§xêAa­ùzõD3î…¯ w­”h@ ýé]3à#zÄ•:ÓMkSh)µ"Ø-ÁÖ¨…Ü/·h?üн¼G#œA=÷¡‹jô˜ž+¡…\ô®u=˜oŽ? Ñ­ ¥†Œ6ÒÔJèiŽ7â'î7Œ?,ת‘kYïÜê)“Fz¡.£œ‰£Vx¤†ƒê ¶ÞG#%ÐI×ÈÆ~’Öô0#zÇ5«øµt#}©ê«÷y¦8$h ž¥hÄOß_~T­ù³D Fp¾™÷Ú+Ùº_ÊÌTûla‰Ï*9F/´iu­ùaE ½ýâMv«°›Ùƒ¦8@–¤Ñ6O¦Õ>š<ƒB|’×ú § [Ì SøÍõ¹]G¦#P³»Wí¿$×aq#›ÓÈ9n6åy7ßï0pŸK`.s4Äi"€g„ã±Ï EÆóµ[ôð¬P–‰Ìe.s™ `·ã—÷2¶ùótì~Œ·>L¿¹ÙcžÕo3€¹Ìe.“8¬~òç‰O8ŒçúID9ÖTB‹ JÌe.Ó8ä~òçíØÃv®ŸÖ1¦0—¹ÌeºÏš0ù„§sìa;×Oë˜Ë\æ2ÀaFûaÙL$p0QÄç ˜À\æ2Àá]f¿‰öóØÏ0€¹Ìõ9^¦0—¹Làð/3}×tLWÀDæ2—¹Ž¨7ØDûƒ"L$°ÿhë0¥ ›À\æ2ÀÑóíÍô݃}žãùÚ z0€¹Ìe.&Kaò OE|€‰Ìe.s™à°#Eʵ©›Íu„ÖÝÏ 0 #Ê'K<Š-˜ÕÖ¡Ñß·›±ÓzVHm¥šA$zÇ6bñÔßù(#6ë#*n¦Ðü"6†A¥REQ,““ÝìÛ üú¼û,>û($Ïìâ7—ÅjÍŒ°Ûíb¡P¨”Ëå2Þf³íªð  â~À³~g©°žå{ì=T*Þb±”T `‚bb†9sæŒevvÖÆ²¬«R©øDQ 0 ãàÀ6ÊWhýž'ù+•ÊÞÄ'øýôÞÛÈx’¿e?>çY½GÇTDQDQÌW*•mQ“6›m»P(ä”äçES(¦»»ÛZ*•8Aœ‹Å]©Tœ Ãp¢(ZÉkž¥0ÕÑòOí³Ú{5ó¾ûyžžÕµ®ÿ2QP®T*|¥RÉ[,–,Ïóy<€²â5¦P)K8¶2 ÖJ%¶R©°V«Õ&Š"#ŠâSs%/äɯ§¡4úù9¬ç Ž› –ËeQÅ’Åb …‚@…¿rø€ƒ¦ÀÒÝÝmÉår–R©dq¹\9"ðÄÏóOüw ‚sí%G³Éd*²ß¯¼ÁTõ•…ûCCCL©Tzªß#™L©Ï1×3[¢âñ  ÿSŠÀ\æ:šà€†™£˜lc.s™ËTæ2—¹L`.s™ËTæ2—¹L`.s™kgýÿцõ—H<ŸIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/pdf.png000066400000000000000000000143131217176075400226370ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF æIDATxÚ워]UµÇ?kŸ3s;¥Zi¥¾ª€)dÀ¶À+JLC^*i§ö#R ŒÚ(áGÍS •ò ÖX„Fì€âòC°I ©¢)+§HHÚÒZA°i§¥Øig¦3÷ìå{Ÿsö9sïe¦¡/áÝäÎÝçÇœ{×w¯õ]?öÚ¢ª¼—_†÷ø+.ŸXü¥«n¼üsK®íèíE@üÀqccü þ8ý‘àZøJÏ)¨û“½2mL?¬bU³óªŠZÍ~„µ*ÍMMñÊÛ¾¶¬³³sã¨ð‘Ÿ5ûÌ©;S HÆŠ Þ‘2<'NŸ$*Å Rá¥! ¥cÍÏ«Õ ›XÔ*ÕjB¥RaÊ”)5 H’DQ@‚• c±  ¢^#T ˆ4Ó"É…“TÀ|úÕ*Šb­æÇ~Æ­µX@bmŒ(Ž…Çâz¬*’ýP Æ‚¸ÙÜ4yÁUÕ %F2õMÇ)é½Ù5ë4ÎÚüX,‰ÁbQ,ù3G€Ì½°áX=8 TU?ÕéµtæUÍJ -ˆä ¨AUÁ;32 µŽ»­µD"˜hŒ4 ³½T¸Z€hNt…kÔ¸Îv=‚ôß›k‘ÌF¬q¸ˆväÀS7¨U«¦È0yµZó DëCåk×ÿqCê\0^KŒ‘Œ?²w”ãÞÙ8:6¨€Ö & ïp_zl^î¢ù¿I2çBšÿûjÌK¹‹õnU<™°&Ld0‘Å&>ŠÌØ #ï«u 4ý²;£•êeí$ýfKgî5$×Sñï(6D±á€€àIm['°çÌ5”=‚^¢?=Gõ’ 0ؾNž„”´XŒÞƇ#$LÊ%âÞrŒ±lÜPz‘:Ö1):©0&¿Ï Aº÷ SOuZsîfß• –E”©gÈ£>.õ)OPp½£J‚UndªðšÙ4’_z{‘žƒPiñ=«ˆû¨‹!D³ˆ2.M$Ù8ŠçÉyÀ_?h¬@R"<eöZA¤H–CøgˆÖ"ƒŽñ·½‡zòç€ 9Îö)™ „™›Cf÷©@}§ÁL扔¢ã*èøñ°¿ÛEx¯¿†mnF%0ñæ ÅòjÎÏæ5 n¤þþŠrT°;Í3Áe3‚Ð2Nž„ÙýO@‘¾“'y"ÓÌ fãa„šOͨ“àPÛ–‚9Hi¶ Ô<ÖkűvÚ0¯nÅ<ÞB&OÊTñ„ûï’šZ £@Í3:çßK<Øl˜êfd˜ÍbŽÿŸ³?ŠìÚ‰éêDªUtêÔ<Å6^ðtltH:žÚ &L4˜L+5PE-ðC6ƒ&ˆÔŒ³mDÑY³‘½{ˆž| 0¦žF ëxƒ@) Žðáó˜•Ä$`ýpV „Ë’Ñ‚f°yú?)Éyç*ÑC¢úrÒÄlæMX\¡¾ Sé±@†jB¡Ð Z:çT·B:‹ôÌèL‡$³[sÁe±Æ»R Õ—Ü…eê:¦Pz-BrÈÆ'ND?vû®9sjÆï&¦–jI ¨ÈøþÐ ‡©%´ð@LúÉOºgž|òÑEïZY<´á€ð¨µ•¯áI,eóŒÙQäµ×ÜãŸxâèCï1@Š¥ð2ùeö\"¸ÔžMx€LpõëÝ—?ó üíoÇÓ8d¨Ú—@ Žt¶%w}&Õ„4xÚ¼Ùº{ÑEpèòóŸHÐ17B #EOÉžË>¾pì5ÁÕ̃/|äW~ÿÎwÐÖV¢ý8n Ô$Áâ*f@ ¹àj‰)e‡=ú(zþùèyça—,½{1?ýi¾òSGðZ Œ¦V-°ì»¥¡àE[×:~]U1k×Â[o‘\z)ªJrÅèôéD«VÁÞ½ï(ø»æ É+ðëRòñ”À‘ùkUƒxÀUw>ûYwíÄIn¹öíÃ|ûÛGU˜u¬Uì ¨-Æò”㘞åS-¨¡®æùç1/¼€mkCÏ8#_ŠkoÇ~úÓD÷݇<ýôÿ 7¨¨ ›¨O}s;Ç”ˆ1¤ÎŒî¿€j{{ñšÕÕ«aüx¢%K`çÎaƒ0&•Ÿ ÁÊh¢…à¨`÷Aê[k¦dûvG~­­Ø¹s‡ söÙ Þ{/²gñÂ…à¥ã⌊„38µ»ô´~ö¦ªÄkÖ€µT/F›šjÞg-¢zÛmÈöíÄóæÁöíÇÉ ¦g¥ÈöC2»'Ô³SyóM¢Ÿü}ÿûI-jhÏÉM7‘¬\‰¼ú*ñÅ#øÃqpƒ¥Æ|CXµ1 A§‘Æ>ˆ:DõÚk±ÃH~ª·ÞJõ®»înâyó0wÝ5¦n0®™ fuz fßUn‹é­ü}yXöì!þáÑ)S¨~ùËõWŠKãdÙ2tölâË/'Z±yöYì 7 Bw7ìßôô ==pð ¿Ø´i"WýÀàYàYTŒ¼*,yp“AMžãŽÕ`j/ƒ7wt o¿ÍÀw ï{_ÝûDÄ-šlÛ†tvbþòd×.¤¯Ï©éúõŸ@P©@µêÆ--œ200ø0Ðâßßv r)ª]G¥aˆ[î*–®êdÒ{öß{/zúéŽüÊ¥tUdÛ6¢ ˆžyÙ²9pN8>=ã ’Å‹ÑÓNs.²£Ù´ ¢{å•.Œž9“¸¥…ÏêS˞ظñq/Ïd X ü ‘£úöˆÖÊEŒpÉŠ CÚbüqÓŒüë_ô¯Z…Nœè®U«D/½Dôä“D7"ÝÝè©§bÏ?ÛÞŽžsúÁ„ Cj~vÑ"̺u˜ü³f æg?Cçχ¯|…fk ª½þÖƒÀßuˆ|8x~D&³½” Ný³Õ›2ãûsòúë4ß}7É'>Aõ‹_ÄìÜI¼nfóf¤ZÅΜÉàí·cgφ“NªYì¬1ض6l[²kæ©§0? ò‹$¹‘/¿^Þ&y06xe(¬çc¤TîªÝþèæÕ«¡¿ŸÁ¥K&ìÛ‡mm¥ºj:mZ±ª[Gƒi—ž~:É7b—/§iß>Ö]pÁý Þ|Óó}^ NEd<ðT†¹4¦¥wè Pí%204ut0xÙe ¶µa. Œ@ÐwºÀ´i|ÿ¬³6/xã‡kÔÎ?,"`°~XPa™ºœ½C·rë­P©0póÍP©`'OVR3F‘)À Ÿ2¢²xF~5Šž»ß¿ó⋨*M=DüÜsôßr Éi§X¸£-ˆ4X$ù«¿ üiø$r@ªþ>.É/^»–è•W¸újÌîÝŒ[¹’äÜs¸æššª\ä†kµLŽÆ½À#Y»Éð—ÇKn0|®oŽ¡eåJ4Šè»ãdÜ8Z®»éé¡ïÎ;¡¹¹®Íª Ú^Ô6Áø$#ì2 ¶)4¸±þÒ˜ÔÒ0»w3aî\´©‰¾ï~*š;:hZ»–#Ë—“\xa¡m UÕzokmÍq£û²Æ­QXŒë.“»¼Ôâ;˜ÐÖÆ`[½wÞ‰QW-_ÿ:ɬYô¯X‘ý@×V«…Y'"l²*Û±[’B£„‹KœI&š`Ô3q£t8kˆþ¾‹‰óçS3‡Þï}ÏÝÜÝÍ W]"¾ûnlsÅWOõÖ\ÈLÍuè o¡×2õÇ4J¸OãÊO¨Q¬ÚÑÕõ}°…ž&^w-ǺçwãÀ ',[†Ù±ƒÃ«WS9 {v5o˜7B”'ó€( Â|FH’G–)"A¨.®m>ÑQ6B÷‡3q¿þñŸÿÌ¡p~=I˜pÃõ4ýîwô-]JßåW€µ…ÆÊš»DÊ*Ÿý¥kFò¦,ãL }¦1ÇÖ(]ß H±¬ù…M$­­ô/XL¼þz*=Æ‘… 9ô?ßB=A¥½;ÒÕbgYê@®îØ\åÝ~S)m2¤½€ª¥:cR$~îy&Ü|ñÖ­ôµ‰ƒ·Ë è(Ô ÃÍÁÞ !dØ„’ʧ„šÍ¾ÚÑ S1ɉëð_¥²áišûýs?ÑÕßgpÖl7ÛI’ z/¤U›·Û©Û÷Qö™¿G ³+øDÌŸ0Ædd™n¾[ôGÑÔïüpÙZÇô]2ŸÞKæe{y¨&Å4°ûTÈZ Ô ¤Ø“èí]ÝÃò Èæ­y‚ *ceNõmâC_k±ä%¬Z·Ÿ‡ NKìŸí)j+õÕ_óþD±žüD}†nœY cD‚ßNª‰kkñíê©ÊÈN‹êŸ_–¿—#Qmlóå•ê¼5בH©ÕVY)‡ÐêÌ!õç!Žuñ2¶4ÒKMBÈL bÊœ;Ù³Lþÿ®eÐÄAÇX)@Ü˸–qTu°¨&(I.¨ÕâìÛ`öÓÙÖúùH¦úåM58 <—§9‰1Dq„‰Ìè†Â=þë5[¶t½b5©ªç3³j [Y‹+˶¦ª7I¶*ç›*Äc»ºº^ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF IDATxÚì›yp×Ç?}i$Í¡ Iqƒ,⦖,ÆØ`Db³³Æv\’˜l…u'•°e¯×Nlg7I%Ø!룜²½ÞM²ì5&»6!KB!¡[4ºçìî·ŒFÌ ºFh@UNW©JÓýºûןþý~ïû~ïµ$„àÓ¼É|Ê7u,òç½óØv/ÿJWg ´¶’, Lý^Ñ)ÌȦî y®a‚iàâB))IÕžüÙï¿åjÜutBÌ‘1oÇWs–L¶·'La „ z@ ü«Cæ¹ý©Ó&Ìt#HÛÝg ù6e%*®Â¼@Š 2%â˜4äC…¶ÐÙûL#è!¦)0ôÐqA tÓÓ Þs¬©-¦`†~Ó¡ÿ8&† ¡E–ä«@e%^–%5t\BÓ‚oD–ü‹[¼½#fŠl+‰ø¸‘"D…ÖIŽ„ ( ¨0Öî}ÜÝà ‡ð¼‚ +áž@9 Ôç€É!Š|èðpPU)ž9`ìÂAÄ‚,Kƒ9AU’h|s@$ˆá D{C¼ HÒÕœ ÇøD156z,ž0b»ë€Ê ×h!ÅÇ„99r„Üý*E hñ Éa$pCFƒ7Âpb)".:Àˆ2d2@ˆKR<’`8ÍÉ!ºw¸!c`:!Ä "ÆnPŒ`ØäKR<Ä áf‰¥ /‰ a¸› søDÔÔì¢þr;}Ý-ÍèfMј6= [ŠÂìÙÙää¤]ÍæQ×3L1èæ#Ù¦yµØ~óp£ßœ$8|¸”Ó'ðºe23³˜“—Kvv.³fؘ_ +<‡°ý}º»=œøc'55q]q’d3¸ís3Ùp÷bdEŠ „1Âê_£Axåß?¤ìL+n[Ì߬*â®Û‹°&‹™zü0Á0HMŸúú!Ý¡ñ™™+–;ÐÔYH2¸=P߯½TÍÉS¥,Y‘Êί¯Pã h¦<ûÔžÏ¦{ïäÁ- ëÐ× õÕàóƒÐƒ-$̘ ‡ŽüìœÒ-…´6_-gIdTH´Â¦»ó¸¯8–vxáés¸ºÏóì ÷òuCPÇë:!û~˜€;‡G¶oÃfŽ8Ó†>PÂŽ–å2Ø“ ¡¹Žâ/ÞÅš;—ñÊs§qµ€¤ hùóçÊ É`O…­Å‹ðñÜSeØRêùæ·ï¾.10Œ`¼†¶o|õM¶}áa¦e@ãyèé ÖéÍ8ì ÈÁ7©ëÐÕ (Áß–,hò”pÿ½ßDôäg3¨‰AxªÉIÁk CŸêªÀ’ ii°ùö…´¸òȶ×yõ­¿¯ŠP‚]Ö®¯¼Íƒ÷=ŒÞ %Á…óÐÖ$h½·.5·Ÿã8.í «„¢µ šÐ| tT\ø3…³ù¨ê·ô;ÞeÁ"h¹ÞÈ_åBÎþ˜>ëô&"s~ E« ½*Î >:þxdëÜòö5 5nI`÷c¿fó†G¹Xꥹɲ9à» Vu*M½ò¥ík#αgÂ;oTQ{áV|:œ°nÝçÛ|ÿÉÌ| Ýû_ˆW¼qM·ïì8Ç›/v %öQߤ—?•-ÅÛxtû«¼üÆC(1êØ<@ޝ pþ\,måäÉRš.ÓÜÒDkk M­ô»ûhn­`ë¶/pàÅ—™>ËN¯þéÇÉÌú•U§øá3{9þA3Ïÿë/Q­¿—ëêøñóÿÆž={8øŸeœkø)‹ ±±™ºÚK?újÊ»X¼ð>:òI|B Üþëí3hæÊË.ÓÖ꤫« —ËEGÇÚ[ÉKcKÐmÅ?âÒ¡/óÖ‹íTž¯Æð¢K½”Ÿí pÙT RwS6‡¬é`µÂ•67:Ê+˰§AÁ”ÇInþöþd?.–bm-N®¸:¨­«§ìLšHãµ_ŠðúlT×TRÛPFWO'O€€_ Lú{L™¦PY4$;eíWÀÀÀ­·ÌÅÓ“ˆ®ÖðÙÛnçÈ!?^Zho„åKál¶ Ùœ´7ÂÆ›èl¿~¿€[f-£½±!0ðyeº]>z:ýô{ìñëCÚ[Qhë­ ¢ù?ð#ãhû ‰d¡)©ôÐò©«»À±ò½ÌÙàåÏðå¾Ç_ëdåì`ˆÌ™µŒS%,N¨`Iáçh>ãfæ²&jªh*ØGgÆžúÞ/@éik(9û',–+øÍNz= ôJ¹ÌèJFÖ,¦@!Œ@(±Xíö¬R“³hw7À‰atÒ‹ ‹ÕIcSO<ñøàùíü<ΪU”üùO8–ÿ‹œË'åå,h &Ä4Ç\Ž©dÞú >>q–Oì¼Æ¿þ%ûž>N½~˜DÝN:=diY¤eeà•ëâë¦ ›‹ó©¬ÊdÎìµxËK0° $a’JbjÝN¸·xÓr3¨½\ÆÆ ¹¶°kÏ;¬/Ìgõ´õ,GÖ§aˆ6V¬žÁæ­K™‘½Ý쥽3˜C¾¿çqΜ;JJš•ûïÙÍï_Îàhåa2™‡/N2R(˜³´¬lÖÞU%¸rÅ\}x„;7m¦ß)¨k¯ÃÄ‚DÙR6nýwß±ƒÆSwbOiæÝŸup¢ò=²‘©½ÔÀÿt>ޤ}¼ú^ ½F'¯=Gº}/|»–¥Ey”t‘«íÁYz­ÇÇž‡.rÙWN)H˜°‘Äü¼"V¯ß@uÃûüîu#–î'L ?ùÄþyï)Š·oáý·þK­èÇC᜜=A÷NLHcßëÑèÁ†ÆÔ¤dü~“>¨@$¬…£Ç.`]èl_¶ï•›'ŽÔqààaRIF&S¶`š:^|X±SX°‚»¾´†óí'Ø÷ܺø ¡ðAГÿXij¿8É¿¶³)9}w+ 楟¯§¹:djHKLDÓÁe- š„¦i ®êv‡ª=xL<ž^žùîo°ÛÓyåùF²±`µÈ˜†Ž_÷c¢“cŸÊmŸ]ÅÒõ ¨rgïÓ+1ØKâ1y@Hj†CøÁc+xó`) Šo¡`y%ïŸa×Öjt tI‘5$ tÃ@U±X,hš†¦i(Š‚iš˜¦‰ßïÇáññæ Ì“0èĤ—dtŸ¤Û2XPXÈÒ¿]‚7ÕŽS<¿seDe)Ö©±1zÀðÇØ´Éþ·Î±ò‘…¬rQ_z™Ú‹ut¸œè†ŽÍfÑšŠÃá ÙfÅ’h!AK@–e„è†A àÃÝç!#£nWÝÝ^> «%™œYSÉ+¼•Y…3é·¹q'”ñ­G—¢(K"Ò>3Æ1A ½ÀµEÏm ™ol_Àoþ·Š®´V¯YE’[Eê×Áo€ ªœ€¦%b±$¡j*ª¬øußçÅç÷ û¼èÁ•ɪ# Í Ëh!en _»g°,J¨mÚ”ÄDÄâƒðpýÿºüA£Žk¢¢ÖÛ“€MM%3ÍNFr"ŽdpXÆÿŒ€DO}Þ$:ú|´t÷âÖ»°ÚºÉŸceMÑt$É>¢=ã…s/0¡°Y½8—Õ‹¯ÆP›ËMƒÓI)QÕÖO@7‘$HPer¦ØHtV-¶“ž‚"§†½b@ºöCAˆžo˜0á±5VÑ>šžLvzrDQ%<”ÂçP…VI ™*Ù˜#LŒDOÞ½Np<Óp7lfh4×€'„Xf B·¤¸-;„!½! ‚aŒ!–i¸¸y@xrKT'B´7ŒBè¼XCa–Ë7‡+¹48ÜÜa0¡ÆqrÔ0Ç×NŽŽÝ ®'1Ú¯ER±@µwbÂ{‡8Õ#_˜aF‚¸.ÜEÆš¯sÄä„×$8Ù!įauÆõ@ˆ‡XŠÃÄȵ†N„‰K"ž9 V7C,Å=Œáf‹%ãF(Á‘ Ül±48„žèÅÒb4—‡XŠ®Dü}¶)JdÛ¡êq©iªŒ#UÁãVF4j¨‡ 7,üc‡¡Î‰ÖñÑ#Ú‘¾O ]W‰ñ{18öÉ©7fç5V L=è™Qî% ¿RĬNÄHQ0¶NK’D—çôIØ1zã¿~=þ)ßþP0þ| _ÒÙIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/presentation.png000066400000000000000000000133701217176075400246030ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF IDATxÚì›]¬\×UÇkï}>fæÎܯ؎€]ÇŽcË4q]‘†€D…* (HU*ÊSKÄ# D/ RÅ—BBH$ð€DJTUÄ¥©èKPZ„¡¸BUEÚNí8öõ½¾óqÎÙ{/ÎŒ{}=ŽïÌ{k([}æÌì½×¯ÿZ³GT•ïç&ÿÀxöÙgí¹çžûD·ÛíÞu@‘©žÚæõŒ»½6ÞÆVUIÓ4yñÅÿê…^ø³»Íç¶‚ÒÑ£Gyâ‰'»×vo#1FT•Y–ñúë¯e+cl €eYŽÝÍÍ;;í³Í;~§ÝÞ(ðæþHFk¾[3“"~·þvž@3ê»7ÆŒíoüüÌØ-6jǤ Œ®;Àn‚p'ÍØ Ä8v€Ý4‡;iÃÝ^;ÀVØ Fýͪ¿ã0 ³h+ l|×|Àv…Û)&~Û&0S›ãú[e›;wÛ'·ÅÿIÕæað^!K“4Ç´-z~û÷~—å¥ûèämpã#Q´"š”ˆ‚x²¬IªP©§‘4I­RZ%O›äÖ¢„Ô&¸˜a‡¡‘®®®râèQ92V0¹%š¦¹Iw~4Ùg_þŸyþ3;žðüÃ+g8|äÈ–3­Ê—¾ºù^×VVX鮡ªEIQúúZ”}¥_EA¿(è÷KŠ¢`PxÊAI<ê•÷\½º‚×€§NfΞ}}¢è0 »œÚT•ªªèõJÔ¼ú¥/1×Èxê'žfõÆ*F#Äc*Ô'¸‚ Áa,¨ øÂÐé´øÖ›oðÚW¿Ì/|ôãÌ's´ïkS”aÄmÆiÂvLaj©¿ÚhDÚ<ó±Ýü\³¹g*u?õÇ8õQÙa˜"ª²±è13Ü4»_‡_OûÒç±VI\ŠW%„HJŒJˆ‘• âµ4‚`°¬¬58k1¢¬Ý¸ÁŸâĉD*°@dsåç=k ;T•àk,‚ç7>ýÏt:\[[Åf’0qÄ Fc°õ*ÑáE¢ŠV|ÅBOyû œ8q‚à£Eo|»`[& ±®eþÜ3õï‘f£Åó¿ÿ+£’1ijIÁÐÑ ˆ¬Ü€Õõë¼ð7ÉÓùY9vœ•õUœ/ YÄ•–`‰¦ßy¢OILGÙ-°ë†NÞä•/g-O=ùãh"tÚs”eµ-?à¶*øm>`È*_‘gB+=¯¯«Á‚*½M÷-ò©ßù-~§½Ð¼%Ö­vÃý¨¨c`-Ü/~ôçoöƒÖL1Z3v÷gÊÇÑ̨µ°42¡‘Öö# b¹þíoóÒ™Wxÿ¡T(ÅzE·ôt‹@¯‚#k=ˆqª”€ªÐ²–¹N‚KSL´Ú9y#Á—W®®ð+¿ô ¶1±ºMèI #iÀF”Íð½nYÑÌM ÀÐŒm¦ðçŸÿðƒ…‹¤®dßÂK –Ú9‹s‹íœN+e¾•’gަ¥±”.á·/qîÜ7¸~cÀÕk«\ï ?hæù‘½Ê‰cóâÄÅ›mk@ýÍú«b”FÍ ŒQÁYÐh€’:r„GùIîßcàÆeö.6YžKYžOXn9Û KMÇ|+¡™ Î@¯¬ÁÌRxóBŸå½{X¹QðîÕ+Íô;²°˜Ö&¶Ç §ö†ùA/2×t´àbT@´¶ãb°Nž,Ñ€šuš¢´LE‹„9“Б”Žq,9O+µdVèšHŠ£)}:¦Kezôu /}œL±,"Ãuì¨[ñfÒƒ ¸Tñ0´i(|@l !Ð+•F²¹6ÑB•'¬`è—ŽwׄVßÐX3dï y"8~¥˜8`©‘p测ÌÏ?@X°ó ûç÷²ÖU _ç"¡b¬˜y¼}ÐÚ ‹…¤¼Îžû&í<%M,j,D $Í‹”—Û¨¶‰B€^¬ö…WÊ2ðT¾$(£§mûçÿöÆ€Ÿùéã̵®áì¹w0åpCLÜù0¸±>šÈÚ `£åã7ɲ€Ð¥ª<ä-¾–&ør@– ÷µ m[ > RÏÝÆ »'µVŘbBšÚóyê"øP»›Xª8ÌFcÜVN0u:ì¬à5Ð oxë[ÿE‚áþ¨VÖ†I)#( „[Cý°&e†ö¯_¿JU øÐé¤òDi6"yªäibSšTeu #Äîg“ xÝÐ\½rV3ã~Á8!xq–¹¦ÐÌ„`Íòó]˲ˆúy"ˆ@ž@žB#…fªD¬«‹0¥ ‘ÙÞŸ‰ÂàF5+CIâ,;É è×Å ± h€WÏ|!M„…4e¡é>ÜÌëo›áÃï AR2gi7¤Ö€ÅYj0ƒò‘ñÎoæÙàf2ôðñüÝK/sñÂEŠÐïPeåé®]£ÙiÒš[ ß;Ïkgÿ…·ß×A+O$"nÿMÖ&7u©¯Y’ÑnZò¼¦ÙÖA#Ê¡z½C®²Sõ€Q{ìäI8 ÝnkíÍÏdY†1†?üã?BVWÞáÇ>ø{€¢Šu® ã3€q­‘g4š¦¶,)tZ_ŒÖfÆnÔŽiÀæIZ­ÖØ¢É\§S«¨k°¼gÅå6ë… ºAà8Rö 0¨|·X¯µ†ô¼Öi°²´6«QüÂî„Á;±­;•¦ƒTYj¾yþ<=ò$!I ©s¤Î‘9K–:gɜùZ“bT|U1ˆ‘bàñÁSTž^øNY1( ²Ö0dª|oÂàÝ@¨Š‚A¯àÄ¡=FÑ] ƒãò÷AèÇŠýH’·.¼ÍÞå=$YƒjµÄ„ŠRŒEµ>Šg4 ƒX©3KUC+˹té"‘ýûÄdDcvÏ&Ñ'ƒÁZe½ùïóçÉZMö53|b2© µ‹JÌ*AÅ‚õ‚Q©)u¢Dc¹råÆÂþ?€xƒœì¢ ¼—Лï–™o·8vì8"§N½‰ÅcÔÔôVTK$`cÐETD8yü8I’ €•]f‚[¡»¾ÎßöeÎç"Z)*fXÆòˆPÐàÑX‹êQÆ" ZTŒbTP§ŒT*R›sø¡÷á\²;?ŒÜ) Þ „_ýä'¹ví‡VbnòE"BM›´fr"R—ÿ bcí ¬ÔY¿úüAŒDU,ðÃ<}Ëz&ÕÇŒÚ8\ZZbiii,1™ä~«g§ù}pfçÇM¶x f+cM3ç̘¥ “‚4 ˜3`ÜB§ÝÝq‹%›¯»f÷ß3¸@Ø1fqæo+NkZ¦bKŒ‹¯³a;Ñ作êVÃáÿŠ0xO˜À,Ï,ÿ£8+@¶}Vx–>`Z±cLp’ßêÂïF'y¾£õçyžSUÕL8ý>³±7ƒâÜÖÒœ-ýuöôéÓ:xðàé0,ÆOb£ÃT»ácF2côòåËÿqöìٯ̀ÿËíû€ÿsàÌ$âIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/python.png000066400000000000000000000143171217176075400234130ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF êIDATxÚì›Ù[×yÀçÜ•¼äœM³I#v+v¤J–­Xv*ËMš M›‡<)` E¡) ôohÑŠ.Ú×ÚOi‘¢ES4[׎\ɲ­}±¤Ñ>£™á,äp¹$/ïvú`0žJΈœM/@ò\âÞ{~ç;ßù¶+”Rü"âÿ´àÍ7ßü½'Nün­V«­zA!ÖÕ·t¬|ž'/}–Ÿ/][)%LÓ4Þ~ûí¿{ë­·þfµûé­PÚ¹sçž#GŽìÿy›½å0â8F)EEX–Ň~x¦•k´ Š"|ßâl®œÙõö­œñ§Íöò¯l/IÃÒ3¯vȵ_­ý,}KP–À,µŸt.¥|b{ùÿÛ`£ ,—޵BXú퀄ð4ÉX âI: `#—ÃÓ¤aµOG´:€€°Ô^)ú—€µ@h V ,ø†é€g\§ ¬eðϼÖ£ÔÚáIíV­Í5B+r™Ùù¹>­¯Õÿ=­/ bàù5tMRZ˜¥\!×½…lv]·~­¾¾Þ%ÐIaÐôTj%Üj¯:‡U(ÕÄR`‰*¡—§P1Èdö1Ôw€Lvô]§cÚ Á÷”ç(.ÎP¨ÌSªz4£;•ÀL9”£€ úÌ$·µ›dœr];Í SùÓ\þè8¸ÿ·Ù¶û(šawÀ³Šòòv¡0C¡0G­éá*‰–´èîéeËÈžOuƒDÊ'ˆ}Üé°,‹š?ÌéKXžKC”‰¼iî-"w†Þù–i³e÷«í°R9= „¹™{Üž¸J~N"í4‹ g4MRÝLjÍpMé3ٜĬÕN}\3ËÀW¿¨›Èd†bXÀ)H4çÈÚ>“Ŧ&ÇhU¬[,׸­@pËó\»ü>K\¿9ű£ßbj¦Îåwÿï|÷×¹_(QORšºÍä§'‰l‰“LR_¨ã§0°m?¶Ô1m N£•¦ñgRlš4ë1Ža D¸±Û`+{¼Šcn];Íû'@)a’ì߆E\½9ÎäB…Û·Æù§ïŸ‘ícxºƒ²2:rTí&[s9|„]Û_¢gÛvÔì9ü©Û¸ÓhóeªÅ,?ù‰Íý ålfdëþÝW[ëA³Á?þŸ\¾Ä¶×^#aŽpãâânóÎG·êP òL>HPP€fÀ®ý¹„C¥6ÄÙ©›Œí¼Gws£Ðmh=Š÷±Yò‘EÏv†t¶ÒÕ½uÍÒüÌÛàÓú|¯Æ}ðÏÔ{zøÊïüªÇ¢;Gÿ¦n®®âd³…Óᓱ]& :>UB5HÕ¹{£JOÿ©•¦XÌ_!N„ä§+Tâ.¹^ËðëfB„ÍÎhu{kú N_}ÜáCìéÛK#öi.LÌT©7c¤“Dù³ îÌÏÇl$_6¹p1ÏÑ_í#ŒR¤cÌË×0%‘0X¸;CS·©çFê³ð«÷ š‹DÍ4Qà’t$“éÎXËöEW'NÓõ…Ã8ö>¹Â‹§9ðÜ=]]„½ýßüNýãGÔ\¾j1¶7¦ôðZ¹Jù¾N˜/yaW?×Þ{—‡7æØydְ¾?Ž[n`ÒÄ$&bT32ò<ÉTnÍ&q[-Á(Š8wþ]®Ufp\£x…´åóæ·^b ÛÍøÄÝÅ€Kçÿ›ÙB#Çvñâ¡æn癸º€Wöq«TÊ.±&)— ìÙ÷kûÍ?B¹jB¥mJðI–àÔÂy$=„Þ< g+nc­éñàÝÓÌÛ2“"¨¸ØÝ)Âê,*Z ´àQ™xÈè\=òÁ¿žAdû_ÎRQIÇ¡ì²cX0q7 µÛÄÖSX–…[w9ðÊ×8öõ?A_æü,®¶*Á剉•K éç™"ípëä'<è½@äJúG,º¬AÂZ‘»ŸæY¨E؉К¤³Ý]5ª3yMr™€SWfùæ7³y4ËÕK÷¹pÒe÷Ø"=]MR£Ê3Ñ“‚¯½r‚@Jã©6I« ×#Ë»¥ ôd’0šcË«œgêüufçѬ$VwŽ/nŰêè¾FZ3¥Ed>9Wk°ÿøsônÆ@pïbÃoPš.áªó ](éóú7þ˜Ã¯ÿ>Bè-E:ê úxLDÐãä‰g§˜¯›ôÂK£[ÿðE; wS­á‘ñCn~r3§‘ÈtqönÄÑoààa“©qŸù|ÉO§ òè^­Ý)¼yE:¡Ô<½ƒcüÊoü5½»[öDÛº ·¿¯BG½A¥J(JŒ?¸NÊI“êÛKµ8O=Ôq¬–n³0§£ÑDâ“J˜H?@ A¬Y ¤Ð@YH;IìÅD †öíäÅ/ÿ9¦™Zsð¥•â‹gr†–nÒÌVbú³;jóô$ˤð1>*5ƒr¹ŠÀƲºÐb›JÉ£ìz4Ÿ !h†@%M„‘"ðLÜÒ,Ù”Éá¯þÉdo[rŒ‹3ÄoÔ0 PÒâ¹Ñ­Ò«àèš!X¬„4½VÐDhŠØ’ˆ0& cR¶Ž®;„±N­Ü@E.fTbß+HoÏÞ5E~šè˜,”Š„^™ÂÂó“‘A/öÉ:¡“Ðq¤5ÐBÅhR£+•ư’ 5ÂfˆN€»˜)“­;¿ÖÑ‹¶¹Ã¥rÙÒ"›’àÚä+ãzÕ‘|/FªiÇF) q€® i£k6‘ÒhÔ\ðëDQ Ä0¶%_:º tgz±‡F¸ròo©UîÅ|­Š¨5HÔši“„ªS¯ºa!5 Ç~@ìz|Ì$fóöãÄA¥âÇ®íz!tÔ°"ÉõñKÔܳS!ÍÚ""!ᤇ” UðHa¢é 5ƒf‡aÓÓÀJnưûÛûËìzá l'Cø†õ8Ë»—€L*Ko¬±tÙ&ÕjŒ_/:MGbƦ!,t] …NŒŽfÂ!×—£+7ˆÔ»Ø4¸‹]û“JçÐt)µ¶ä";ªtMgûÈ"o’rj¯×£8ÿ¦7‰×h¢)A2©“HZ†E"™C) +a¦°“9tæ+ÓǦ¡1N]ÓËJ[~Úÿ3·•R¤Ò}l~ž®T‰ ˆÛGè5ðܺ&±,+á ›šÔÑt!t„4š…e;¤Ò9 ÓB‰xTÔÔŽ”{ÇuÀgmèéÝM6S#ŠBhhšþHÅ„a)$JE€!„ÔRCJ C7Vøz,Á ©ùìfÃJ£Çq¬Åá¡¡Örr(x\º&„\5f×ê ?©oƒ³Ã ¤ŽÔt„ŸM6 TŒzTÀŒ)µ§nYíª.ë¸<],5à‘(~þëñì¯f¶¶£Þ¨cyÖñø³\ÔW3[ÛYg¸ò÷gR ±Û½ÝÅ–Ë þ¼Cè€vC·¢´Ö a½ ZNŒ<Ëì>ËùZ"‹´óÁÛe×@;O;ßQlg~e¦: RÑ1Kp-3ßꃯöJÝZú;ÐuÛ¶ ‚`UÛ»•÷ŸöŸg¹öJ(ºÞš‘ÛÒ«³|yttô`EáZ—@Ǧc–Æ$¥T³³³—Î;w¦-þ/¿ðþgÇ‹ÄÀIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/sound.png000066400000000000000000000163601217176075400232220ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF IDATxÚì›Ûo\×uÆ{ïsÉáE$M],Ê‘d»AlY‘´pk7qhþƒ ¹A_û¶o-ú }iûÜ´ ô¡ u›´HÙiã2’%ËŽcY”L‰ÔÍ–HÎ}æ\öîÃ>çp$K6)“jÑt¤Ïà Ï9ûÛkë[ßÚÆ~•_âÿØ_þò—ÿßøÆ×;Nç#/(ÄË_w?Ͻ>çïáÏùµ1Âó<÷›ßüæœ:uꕺŸ³”{ì±C'NœøÔÿ¶ÙCk1†4Mñ}ŸÉÉÉÙÍ\cS¤i @E÷œÍ»göAÏÝ=ã÷›íáß}œGÃf—¶Ü*âuüqÎå äÀäÇ÷ú,¥¼çñð÷·€‡Âptl„üçŽDÀÃá~‘q7÷Ak½s<Ìåp¿hø¨÷Ž,Íàa€ßúùñCá€a;Ú Ãhðq·S l%ü?öxRÛ.îu|/ Z|Øœ| ÿçŸ7›Y6­ïÂð†ê~çî÷=˜¡”•?ø0™ÝOM~ؽ7ûz >.yŽÎgnx¶R­I“­5RJÇÁó¼{,ÿÝ’ÔÛÀfz¯sqcŒA)…Rª8/¥ÜÐñØA%IBǤiŠëº”JeÂ0øØÕæqÀÇ]ÏQÑn·IÓ¥Ô©JkM’¤“Gw¤4c qÓé´i6›Äqü¡Ùa«¯æ€û­Å»#¡Õla0„aˆ”’Á "Š#*å2ƒAD·×åÒ¥%./]brr’£GR­V  ”R¤iš‘Ðn· à 6µþÇ” 1†N§ƒT’r¹L¿ßçåW~ÊÏ^}•n·‡”*›i…”‚so¼ÉW¾òUžÿíÏòƒþQá8î<Ç1½^ÕÕUÚíö÷|ÐHp>ù}ØZOµÆu]Çáú¼øâ¿pôèQž|ò <×#Š­·à8й¹9žþyª• §NŸæ[ßú/½ôüGÈÈȃÁ€~¿Oš¦¤iŠÖšÕÕUz½år™0 HmK~ÅqLE)ñ\—N§ËÒåË\¿qƒçž{޽»ç¨”Ëm0F#„Àqßç“¿ö$õ±Q¦¦&ùç_ä¯þò/øñÄŸûÛœ8q‚Z­VEišÒ ìÏ~Ÿr¹Œïû; ÀýÖzš¦ â8Æq]0ðæ[¿dá积ñø¡CÔjUÖ V®]£ÛéDZur°×QJáºÇŽgþÀž9r„……þäOÿŒgžy†¯}õ+80”×uI’„$M1ZÇ ÍV 0 R©l©ÚòI’Ð Щ ùAÀé3g8þõú(óû÷#•âêÕë$i‚¸ƒ'(°Ù AIµZãs/|ž£Ÿ>Æ¥‹¹|e™¿þÎßò Ÿã7~ý3xžoÈ<À4Õˆ,årùá,Á`@”¥%×uèöºœ>ó:«««ìÙ=Çìì J9 Æhâ(¦ÓéÒj·étÚ ú}ËŽC†T+U*Õ ¥Œå§§g˜˜˜`ÿüã: ¢ˆf£É›7Yz÷]./-që½÷è´ÛDqdŸ¸žG­6Âôì,óóØ÷è>&&&¨T*ÌÎ>Âèè(/^ââ¥w9ùò+üÖo>‹”‰ÂHY¤åa±³Ðï÷I’2Ñ¢”ä_ü‚V»ÍÔÄSS“4š-®]½ÊÙ3gxóÜëܾucôu;@œqÈúê*/°ð³ÿdn÷Ž8Á“Ÿü$S“T+>Œ”’óçßaff†Ã‡ÚðÂ¦Ì ¶Ðìq¶šÿûý>q’Ø´¸ŽÃ­[·Y¹z‰ñqff¦ÑZsëÖmÞzë-~ò£±²²lål¹””U|ö²eÍb’$¼{é"K—.òö/ð¾À¾}{áðáãYXXà‘Gf©V*hcƒ“‰§4I·W3ÇvÍ Mo ¼}þ*å2{vÏ!¥äöíUNŸ:Í?ýã?póÆ jµåJß÷ñ|?ðq=ÇuPÊÁu]<ßÇóÇOœ`rj’N§C¯Û£ÛïÓë÷ét:t»´ÖÌ>2Ç£ó0Â.×óð<ËŽëñ¯¼œ•Ö “¸žG«Ù¤±¾NǤIj3Ôvg8Ž Í<+tºFj£¸®Kœ¤,.^@k­uÇu Ù:19rÖÖÖQRÑívñ<˽^F³Éúú:ív?‚¦xÒ/òz¥Rfey™•åeffvQ©T¨TÊDQ„TеÕ5êãu”£¶} ¤@Ie/„IÊØèkzܼqƒ°TÊfÎÅq,a:J‘Ä1•JÅžÓš~¿O£Ùduu•õõu:í6PJâÇæË¬Äî,/_áè§âº.##£Å„$IÂÚê*S»vm3 fù>Mtª-ëJAX›*Ž a)´,îº(Ǧ8­5ÝN‡F££:ˆã8c ´Z-­V“v«É`Ч\© ¥Â]hß÷i¬¯Û¥©$•j%S0D4í@fLnÁ"€ÕÛ·™ž™AIBà8Ž ÏÃËÈüÙhàº.RJ’4¥×ë`DQdj6h®7h¬7ˆ¢ˆºï[3Dk@`Œ&‚Â0•RâÞÅúR ú½Þ60”Wu¦ÿ};k{÷îÃq¾ï†!©Ö8®‹çy(¥ð|¡$k«·Y½}«TAÄqD·Û¥ÙhÐX_§±¾Fmt”°T&Ib+p„(Ô¢%YG9!!w–í_;U ijkøn·CÄqL­V¥Z­2V#J\ÇÁõý"ÿû¾O}b‚å¥%´6DÑß2%™Y]Ý.­V“Û₩gfñƒú`E·|{nzß÷p\‡4MðÌsþü;ܸy³ˆš0l‚À÷Ù?€¹¹Ý6ç·ZÄqŒr*• åJÅf”Ì[,—Ëôú}ü ÀIm:ñ™Œ×ëÏÊÊU&&Æ‹ê/N±#~€±—N²¶•‚$I¯³xñ‡d¤Vãø±OóÒÉ“DQœ564ïÛÚÁ„”AÀÈè(dE–6†4ëEqŒVqæbIJ‰À077DZcÇp]!——.3ûÈŒ5b˜|öÛ€5C²-s†,Àu=nÞ¸Á¡Cq]—ùùý´Z-Þxó$iŠ’–¥•”x¾_–ÛÚ4:µ®PÎÑ`@¯ß' â$! *å2_üâïP«ÕBpûöm‚Ðߨý³õÞÀÖJ'! Æ‚`5ÁØØg^;ÃÓO?…ëº<õôS(ÇáÂâb¡Ëó*-¨ÈÐÚ.£$!Ž¢"–¥$ŠcÂRHµ\áùçŸã‘Ù½çγĪÓÙ[Ë[ w††ˆGH0ÐéôYYYannG)ž~êSŒráÂ"ƒAT(G•u„ ÖÀ5yÚŒ“Œ¡R­059ÉñãÇò ~N¹\Akãdò܈̩0[j’l€ü¢Æ #‘÷ä@IX ¹°¸ˆçyLMMðè¾}LïÚÅ»K—Y[[#Ž´ÑQëœÒ”$MquŠö}””„aÀ£ûö1?¿ÿާxýìYZ­&“…:ÍŸ+Ÿ±S¦(d›Cý}®ãP.•8sæ,?þ8»wÏÙ,†<~øý~ŸÕµ5ÚíŽíì$)©vrmñ!õñ1¦&'?ÐàXXXàúõëÌÌÌd²Z| Y«µÙÌÌ™¡¾¾¸q!AR«i^ý,ï¿ÿO=õTŠA0;3St’’$±Å¤¸®-œîºív›W^y…v«Íì#³”J¥ŒSD‘÷­I+[Ü&·…rXb ÅC ! ‹Û[™¹Â-ZSׯ_çÚµk<ñÄ<úè£w\.·É>ª—7 8wîçÏŸ§T*1“)N/[&y#$Ÿc´]ÛÍÅ|g`[Û¦8XÃDdõ{µjÐf£ÁÙ³gyã7سg{öì¡^¯è½’$áæÍ›\¼x‘+W–QJ259Em¤FµZÃõ\[}ÞU¥ä|”/‹é MLÏ%΄ŽL~s‘™&ÒPR%|Ïgdd„V»ÍÊÊ ‹‹‹(¥(•JT«Õ"rW¨ÝnÓjµHÓ”0 ™žÞE†”J%Â0D9޽¾õå É/„$·ìldš Á¡ aÚ Ùî ¥”õç1Å’`¬R©Ìøø¸8½>½~F£QìÊõ<é]Óxž‹ëz–ŠþÊLTË9F؉ÉïgЙ‰ºCBHd›™Ò4Å÷¼ÂˆÈõ·’ m4Â`EN6 RJ„8Ž"ð}ªÕ*i–ú´ÖÙ;›ÍŒK¬.P(GmìÜè+’W ›‘L&Í•”$I‚ëz;#…ói­)—+4›¶ô¢ØvcŒ%FmQéÌËC öa%duÁÝ[nÍF&°"óóV:`66S¥©<%UÖpq¶Ä›s„†®˜ÏˆŸYÞIšàzÖùum4FkŒTSoÔÃuë0Sçê-H&36 Ã.O®õ RÙ³ƒ·€š¬=îûžµì¶³/$‰¹×ÎJÅnDPRâ(ëÎä»»Œ±¡-3ù»1«VEZíN¡(É} ±á‰ì»bh J©0Ú‚'WƒZ‚0 Šb*•êöÇqÚ îh‘çÚ½V­’$iATišÞa¢æ[),û{ïøC!ù ó²,v’)ØË"ÊuLæI„a@’$A°áo#%%ƒ8.|¼œü<Ï£Z­Òn·ñ<·è8ŽÂq,XG[ƒ+ÒçÐr Póê.§c¬g`2sT: ÉL’0 ‰ãÏu©×ÇŠ¶îTJÑï÷ï ÅÜ-ö}Z­J’$Y:s vWR¢¤*öä`Þm–Zr“ó}Ö™íî8ªèK:Ê! B’Ì‘ª×ë…jÝÖÈÝr¹œyá2Dn‹·ÛmÈ<À8I0Øt¸‘Í}—óß0ñm´¹EqރΖXXrQR2ˆ"ÆÆÆ¨T*C5ÁæµÀ¦þëì‘#GŽïÝ»÷Hš¦‰Bxž'ï·ƒDgGN”yµ'Ä]³¹·y¿Ý¨f8™eÜš»«%.¤”æäÉ“?¸uëÖ¥màÿòëW€ÿÂà[o|aÓIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/spreadsheet.png000066400000000000000000000167421217176075400244050ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  ÒÝ~ü OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFýIDATxÚä›y”UÅÇ?Uwyïõ{½Ê¢²)[#›(-ÄQÇ#nqT‚h’ j4F£ÄhçLfŒfÆDIâ6.ˆFd Œ(; ´ˆ¢‚±é†nz}û½U5¼nèn»éG ŽçLóNßÛõëÛ·~õ«ß÷ûýU=aŒáÿs³;þâšk®™}óÍ7ß‹ÅbÝý±¢G}­­£ó;»oý´½o}¶1F¸®ë,X°à©§Ÿ~ú±c‡C‡Ž(---ùªÍT[gh­1Æ ”"°víÚuÇ,”R¤ÓéNg³ãÌö´¯ãŒw5ÛmÜñº5Zß¹'Mfž]]‘¾V§´:¦õº³{)e§×mí¹¾,'´Ž£uBëÏãæ€/Ó ]EFGGtæ„ãê€/s9t Ý}Ž) ¶}I!Ë—¯üJâ÷ôéÓ23ø#ÀÎfæó‡ŸAȱè*xm)¨|wá¡ãÈ Ø=¶ÓÚ ¥ šò‰íÜB¿Ñ“ð”>®RônFJÙŽ´6_Ò¾îr`Zf^"í)Ò–üBvB$l2ÿVúy˜@fŒ èvËHcŒnqPfðZkúöíK~~Ï=÷|zÏ޽߽óŽy Žè€ÎÒÈ‘#ŽˆŽc³qã¦NB à1\—-[Á”)“yèp×óH$’444à8nÒ#Úåöb‰CƒÏ<6B€1­NË ˆ@PTTD(ÍNeeå,`ÁQ/¥4J©n+:GÊìmz÷îͧ{÷òÜóÏ£”ÂuÜ.B±Õæ°oÚý¾=‹l ¾Â 7\OŸ>' †trÀQ`@VN0ÆP\\Ì®]»Yµjáœ0Í QIíáûi^þÓ›(£‘.œ3uÅCƒØÓÈŽÕUH) …²t@g/»}ûެfõêµYÙ­]»œœÒ€V c âQãÕ“ˆ'1FcI ­AH1 •ÆEÊK¡ðH{I|Ê$FÛÂ÷|&5–uïlÁ÷oíÂOèC‰Õu‚À­Ý5­=Þ…_),¡ çätBe¡Âïyxøx~ϤѾ‡B#…Ár$Ž#„ -plÀ’’!C³•BµeÒi°,XüÇ xžGß^ƒ6ª™X,†Ì(ºì˜à±BG‚Ac¶4Äãq6•oæ`íA¼¤B`ƒÒ Œ2C‹ŒFèŒS$H BZ™!IBÛH)@ þ^\CCÓA\ÛÅÇ´DTè,„³CÙÂ`CC#~ý|~rï=TUí#Ž …ÕuƒaBb´ÁƒÑ`d† Fª•¶ f›*r"BÁ·¾}%ÍM‡4JVÐöå»C¦ Æb±CvDZ‹ñxœd2E0â›ß¼üK)¢6Õ7ÒÉø³“Ã{ö|šÕ?©¨x/+»mÛ¶£M†^Û–ÅömÛIûi,!…à :€ý•Õìýl¡œÚ(†I0 •J±ã½÷‘®sˆŽ8í4¤´Øµs'Ét ´&‘HÒï¤~ èRËxTÏäpwbȶm6mÚBié¤Ï¡@Ç¥³rå*&OžÀo.ö,¸>ë2iÂxÖ7²äÅ\|ñ7¸ôò˸ࢠx`þƒìY¿—ò­ìþä–-]ÁÜïÍ¥æ@ —\v ø÷Ç禯§¬ì\®¹öz®½þ:Ç¢|í&>«ú”?-XÐ"¿…ì¶"ÔvýVa™Ù:Ò'›ªPm@c}¾RxZPߨ@s`0x¨.×q5ٶͺu9ò4öUU¡µaîmsxuÑDòòè•_ĬïÌb9qÀn¸þFþgÙJ„%(,,桟?„ã¸<ýÔ“¼ðò«¼öÊ".þúùüó 7ÐoÀnºñ»¸Á\¢MM 4³Ï*%É£¾®…è…BݪÁV‘Ó fìB(£IûIJÆAɸ3P:£ù¥%Õ~óèÇ8¿@#¥E:é1­lgŸ{nK½À`°ÐÚ'žŽs×Ý÷àû>Êø XmÞ9ÛÐ3ì‰ê²²¤5–°0¢ÑfËÆHHkÜ@)ÁóZùh RG`»—öPžOJ' Ø.ÒrBÄ›£4¥b¨„RG‡2µÍN ­Çí€Ä‘LFà8. þüWÏšÅïŸü/½ø"3ʦóú__#•J3rØæßÿ+—½Éù_;sËf €»ï¾‡ñã&²hÑk¼üì"&O˜ÌÛ+WL¤øÆE3yò‰?²yÓyèîþñÝh/ƒÿÂz”²CÝEB»Rz 9Y³z#Ÿ}ZESsŒD"ÉÞêjV¯]Cɨjêj)êןÓKÆáY6ïUlA)Ÿ…¯,¤¡)J¤°ˆp¦º¦–wÖ­æ„~ýùx÷n¦ú)r òiJûlÙ\N<žÈ ¯Ò¦G9 »¡VL$[í(†‰žï¡´áÎyßçÍ%ËÈË/"™Šóƒ¹·qÝõב—áþù÷A:Í[«Þ¦ìì©Ü{ǶÃÂE/ò—/ðÉ®øÚcöì9Ü>û¹¹Üóããwî¦dÔéüÓ…W¡¾¾¡Ó°Î*|òIvbhÛ¶÷³²Û¾ý<¥H'“ <„[nÒ~Â×$b)æÎ¹-3!J#¬Œ,®ÜWÉS‡ó³ïEû€ÌŒ©9£®¶†ïÞr#Ú÷ÑÊ`„ÂWštZ·nqËñ€Q£Në6mÚ¤IpÝ®÷ýV­ZÍ„ ãøä“ÝK’N{ìüøC´28–%OL(Çe÷Ç»Q:ëØ44Ätò@úžÐd*ÁÛ?@Z–+ð¼4#†Ž¢ °ïoT4‰‘†tÚ§¨ €#Gdk>¿²:$Õj ûîNж;9bI‚¿zø—ÌsÛÞ­`éß–1óò+xò‰ßS_[OYÙ4üå/l¯xŸÞù#Θ8Œæº«¯åšY×SWßÀë¯.áŠ™ßæÙgþLuõ>®½j¯½ùo¿½Šgž}–¹s‰x"£;Ùo“]A^OZf.»½}ÓBJ¼T ¥,Ü@ß7HehŒ'¨k®G#hjòˆi7˜O:íã+Ms2q]ì@ˆPNi945Ljǚð±8H+„2’tÒϔԙmIì‹ì eÃŒ1ø:M*™âûwÜÉØ‰+H%=öëÏü‡dFÙt‚^°€ªûñ<+/›ÉÄŸß‹eIžþÃòÆËسãŠó‹˜ÿËŸ2ãܸ¶Ã#ÏgM5¶±)œ4Ž«¯¼œÜü\êêê1HÑ#´mÛ¶»e‚Gãái”öÉËÍå’™3Ûõ5G›¨©9À´²i)ÐÚ $xžÇžwÑç”þ̺öªÌÌšL•y_U‰øA¦••!2ëŒ!ÍÀk†eYë8Ðl³û† åYÙ•—o͈Ë¡î`=ëÖ¬!7?Ò’ý“L˜2¢âbþ¶|J)‚¹öï§ßÉ=z4ŸUU²ôõ ôéM:‘"Þœ`”Éôêuo.~iÙ8ŽKss#ÅEùLÿÚ?Þ_ϦÐÖ“'O8bVﮯ«û]»>&p¹ÿg÷³yÃff^r1±xœ_|™o\üu.ºð"fϞÅ3/bÆ´,Z¼Œ·ÞZÉÖÍ›¸ë‡wPµ¿–¹·Ï!Mðè¯ͬYßaêÔ)<øð|.yRJjkR¾q=ã'NZkÑãÎ?R¨ã}«‹{ÌÉ¡²òZ*"yyô)êEÈuéÝ÷ÐuMuÄ¢q„1‚¾'ŸDS2AUu5ñxŠÂ¢bôíGCm!7†¦z’ñ4ƒ/‰X"³½nz ‡»;èÐÓ$ª|E<–àæÙ71õì³°d†g\vÑE 8u9ŽÍïþã·Ä£I‚AsÒ·øDÒÊç·~Ÿ½Ÿî™9S:é Æ—œÁk‹ÿJN^ˆ‚üÂ}#¨ÝO$AÚx>#Žš v7ó=Ž‘)´æ†#Œ;–´ï#[¶âcñ$MÍQN2 £Uæ ­•UÕ0¶d4Jû`¾ÑhKL&q„Ka~!ÆeÍúhæ{*³-ÖÈ* Ͷ®î;æc rÙ´©œËW0xð É$ûö}JÙôó<èìwäæåp6Îpéå—òÎÛo³}û»÷ÆØ_½K.½”œP˜ÜHO+ÞÛþ>ÇÁPÚ˰Ȧ$fÛ6Á`Ïóz”Ü:^we£üÌ€?þáI>Ý[Ɉ‘#©©«cñ’å¬k଩Sxöù8ÿ¼ó TV~ÆÖòrJK'óôS 0H¾uÕDcQV¬|•6Œuª¥€ƒ¥ Ú÷ñ•BA*•ê^ ¼ôÒKÏlÚ´éC¥2Eô£ùòSgÛÏ]µ‰“&?žJ¦(›6¥+VQ]µ†úz† ƘѣéÕ«7“&MB dJ ‡)›~.ÊJ§”òÉî=|´ãc”ò>|8ƒ†œB¯¢"l [·àØuuõœ|Ê ¨¯m )Úì|õþ¯¾ñ“Ÿü4uÿ}?u•ÖT¼»ݲN'H8@iC:•"µ2„srð}í@Sc”T*sB$  †ÐZá¥|¢ÑFŒh£)È/àÌ3'óÒK/³nýú{ô7¿¾í8ž˾%RÉ.\ôʼtÊ;iu5PZãû>Éd¥4Rfö £¾öIû‰°%BiŒh Êó0ÛΔÚZ*õ–”ÔÔh¬¬üì…ûôyà+_•ö¿úÛ-ó>P\IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/txt.png000066400000000000000000000171371217176075400227140ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFzIDATxÚä›Y“\Çy¦ŸÌ<ûR[ïz@%È”)r4²Ò’%ÙçÂvøBWŽPÌšë‘~ÅLŒ'b™¢iq@B¤H€$ìh4º»ºªN-Oæ\´ºh&ÐêFLŒNDEeÖÉÊ“ù淼ߗy„µ–?æKòG~9OÓè'?ùÉüéOúY–e_ÖVq¤{û×a‰|\}ÿóp}¿ok­ð<ÏýùÏþŸö³Ÿý§càÌ™3çÞxã ÿ¯­ÞÃ`c°ÖÒ4 ¾ïóË_þòÝc“€¦i¨ªê±«yxezïðŠ?iµžðáò¾4ìùXmÀáÁ=Ø>˽}PöÙ/?®.¥|lùáö'bŸKdz‚°ÿ}¬Fðq ‘ç2?9K§ÝÆUuY$Î œ(ûŒp0°y%Žr‰£²ª †ÔuM'鰻ݧÓi“ïf”º@y¡ihôÞÿ% ¼€F²qÆÎîˆÆZFÙyÑPÖ%¾¤IDgDè4óó ²Q§Ee Yˆt]?€´uò`LC^ä F#E^ Áp8âÞ½;„QH+IÙØØ i·¸qï6M©±Zá;Šq^ñÛ[ב54ë AqãÚ5v#ή¯pëö}»Ûh£Ñe‰ã¸\»ò9Q'dþÌ 7¯Ý@JWÂåß^¥•&HG2;;û|l@’$œ9}†Óë§ØÀDo‚ÕÕÕW43;‹”’Ókk°¸I!X\X8øMJÉwßz k-J)¾ùÍ7!7oÿíÛmøW?<øïú™Óx¢À>†°<î‡YØa¶v˜8=®Ï'¹ÙÇõ  ”z$Xú2Š},*0¹}û7nÝB É™µÓÄ­~‹O>ýœV«ÅúÚ¿ºø!/žYçê͛آ`zqžµ¥UŠlÀ{¿þ5N KKœ}á ï¼÷ ¶ïìòã¿ù .ýú7lnÞ§,sέ®±¸¼Â?ý—ÿ× ùÁ›ßáŸßy—S‹‹¸žÏ}L»,ίpá«_y>*àº.½.¾ë!¥`j¶‡ÄÃñ<Î+À󘘞åÂù’éÙ9âV„­­´E«•Òtº|Óq)¡ÓíÑí´yõ• ì®ätÛ=^yér½Ž© íV›V+å?{Ôwiµ:œ?{ž©ù)¤r Âe¡Ým?3 >²´ÖRk͸ƒ€VÕÆóuQ’e9MchW%ƒ,£S ³1Ô ÊUøq„®s¶v·1ÂÁ÷<ê´Å`0f8ècK˜SdMep” H"¶v†Œ}Áäâ"e“‘å ß°³³CS7aètº'+'Hм Ë „€ºlÔäUE¿¿KœF”eÁ`7cÔ+ÈûCÊFãyM’¢µ¦?ÑK„è*cб»; Ê3ú£mê­# ~äÐé¦ô·ïP u]±¹¹…°B~óÑG¼ýöÛÄq|r9ÁÃ*à8­vÇUH¡ˆ¢Ï÷p$ØSK8®¤Ój³²¼Ät¯‹+¥„i„_YÖN­!EÚñƒ˜…å&Ë^³º´L3¥ÐäÄqJÄ|åüW°¸ø®Çüü2 3¸®ËÂÒ‘'ÿÔ¶ÊMÓ0 xð` G ”«ˆtÀ`”qûæMBßÕ¿»qSkînÞÇÔ†‰™ ”˜"+k._ùÏÂÄì‹b™ë×>e¸›Ñiu¹råwdã>¶ÖLMϲxj‹|@tˆÓˆßÞ¸ÌüüôïCð艡ô‰©@,ŸZfùÔò#kµ;,-.´›šžFÁ©Õ•GÚµùßßÛ¿^{ý[åo¼öµ/Læ‡?úñAù{ß~뉉™çfò! =*+p\Iàº$aˆ/%®àµ[øYMàø$pâÀź.~裔 ^ „‹®ësCåØŒà>?£ˆÎDØc×sh™˜¢3‰ï{„qLwjŽ8jÑ›ÑØ¦!ŠÚžOìIz³H%èv[$NHk¢‹J„ã1ÓiSéݵt»¸®Ëôò±ëã9‚©é º.ÂÌÎ΢‰x$jŽÕ>̵÷ùºÖš<#¥Dj$e£)ò‚FX]SUYQdÚj\×ǘ”ª1dã1Žø^@/ÑŒë‚qŒ†¢,)uISYF~FÜJ©²ÖMÐFƒœ®Ÿcl4Àq=‚ ¢ó¼$ÀÃx\0Hz½.¢Œó1ýþA‘µ:líì‡!›[èZ’8Ž9÷ïmb©°JÐé¦ÜÝ|@ö`‡¶kînìPä; š’qŠ8¹~õ݉ˆÑú2ÛÛÛ¾‡ëÜßÙ$ö’/°À‘€ý²ïûÌÏÍ23=…Ïóö|rÑëööôÓuyõÂW÷Äwf/NwçÀb·ßx )%J)Çáõ¯~ c AàráÂKÏÜ¿ÿý¾¹ç‚½€×^ûS”R±§ûñɉـÃîOúð>Ÿ”ò` BÂ0­°ÅòÚ:““s(W`­A)E˜D' Vc,B€Õ†FÔÐhʺFH…Õ–Æê LcжÁê )@Tš²a¢Ò14‚¼(©lM#@çÙÞ.S­Ñ2Æ4ÑŒc1ÖR׆¦)Ú¡n4AÓŽrÜçÈT¸ª*òµ™`пÏN@sÆ0è÷‡lmo±°°€r\>üèÝVé¹Inݹ5éI~wí·Äa€ ³³3' >œŸó=8NÊÒqð\—V'Åu}'";´‚€Ÿð¤}ËáRJâ(AL„€0ðq\GIf§p\—8N™™ž&hmjÚ„4Ð…ÏÊêYLSÓöéÅWoÝ`<(yñ•—¹wû&ºnÈ«ŠN§K§Óå굫$¡Çâò·oÜ ‰º(_±µ±ƒãKzÝîÉç÷Ñ6ÆPU%Ãáé(â4Å AQT /É“”~›0d»”U’’Ȩê’Í£p— låôlмô2†CêQ…eŒ+í8bûÁ™ç²°°ÄVˆRªVlmß'|B?x>IÑýSYZkŠªDÖ ]kÇ¡,rŠ| 6ÀMQ64¶"iÊ’" )lM]kE†4†ºŒ‘4”º¡¦AZƒ7”¥FÛ†¶#%F¬£iŒ ©jt£ Ý k}ú{,TxÏúX Jí"å(‚0Ä ‚(rQÖ%ô=´ãâyŽ hdMÆXnè#L‚(â$[§Âihl´—27p )$^ã{! ðý½½g9r,g„¥Hå …ÀWžç8Òõðƒ' ‹[7„~ˆô4 i¥)R(éãb™ètȉT1a˜¢<ª´$~‚ò<º6J9iˆOY„£èÄm¤H©ž_Z\kM0âÞÆ]”€ ô0AÄÖvŸ[7nâ>ÅÕÏ®¢«†wnQc¦§gX+Œï_¼ˆšS‹k„¡âÒ‡ïs÷Á“Ó³|ré×ì#×,¬Ÿb¹Yæâi·[tÚ®ÞºFQÍáz×>û„ Mq„ÃääÄó±qsæôgN¯=ârºÝ§O¯Ô–÷2Äç^<ûH“S‚•õÅGTêG?úëƒò›ñý/¸²¿ÿÛ¿?¨ÿà{ß?(Ÿ{á쑲Áí(6àáã«‹½ÿúQXî•å†ðH6 Ë2îmÜåÞÝMP°ºxŠ8éoosýúM”¿"ôñoXY]æÖõäuÉüÜ<ËKËdÙˆ÷/~€U–Õ…9Ö×_âÝw~ÁƒÝ>?~ë¼ÿñGÃ)˜ž]a}ùÿû_~AìÇ|ãoð᥋,L-€c¹vý:ž£XYZã…—Î>Ÿ´¸ã8ÄQB¯[#E”Äx®K”¦LMOàù!i’°0;ÍD·‹m ºièõ:$A„z¬®­ ¤bz¶K·Ýfum‰Þ`–ÞDµSKÅc“½)ÒVÂÒ IÆ1s³3´zm¤Ì—9R:„±ÿ|¢Á}”«ðƒ½,Ž’ ¤Äu\ü %¬Xåìe‡¤¥,4µ8®OúøA€tžâ)‰Žãáû>at‚ù€Ã:¯µ&Žèïì"• ‰c|2vvvȼ€ IØÙÜ&ð|¶6›šª,Q§®îmÞÁÔ’¦QÄiÈ­›·Œ3N-¯só.ù §²5Â6øNÀÝ{÷ˆ‚˜©É9îß¿MQN ¬áò•+œY]£µ¾úØ íDT@JI†ÄI¹—ôB”ã„>išàyë’& QÓ):DuMÚîù.…’Lv&0BÑí„Ä^ÊÜÔ,a>¢“Æ´[=¯¤1 IÜÆÝÞ$Aàã{.íÎ4/¿t€ó¯|å±AÒ±{/†Å €Æ¬ÕÝ`Œ¡¨¡¬5ÐTyIÞÔTu.KJÝ Ëš²®(Æ%¥®ÈÊ㺤*Çìä㊲.hò’Ò䕯Ö rl£Ÿ9û{¬TØóªÇ%þGø—½R÷,÷=• ìm©ëúKÓÏOóžà“Úü!}eïñK üÓèÌ«¯¾úúòòò«M³ç€ŸEöÏúœ„¤=iNRJ»±±ñáûï¿ÿî±ðÿóõGÿöøÿ {îTªIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/video.png000066400000000000000000000141431217176075400231750ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF ~IDATxÚÜ[{LÕÿÍkgwYX¥% P0T‚ÕªXsij"%T‹¤‰†_Ñh´MƒÖhÓ&MMh4Ƥ×J,4)Æ&mlS«±h­%Æ[5RK­MË£[Ø]ö5;;gî×9w™ÎÎÎîÂ}d“]Ιóó;ßã÷}g`TUE¢–@ €üü|Æn·ÃívCQ”ycÌž†aLûÓ}žã80 sÃóÇ1@@õûýjee%Âá0Μ9“p~ÞL¸¢(Xµj•À0 §(Š-‹ÙUU¥‚eYÆÕ«W!IRÂ9–.] —ËeØ'I®\¹b @QQ8Ž› Ã0‡Ã˜œœ¤‡Â²,APG¨¬¬L!„Ä!1³ùM¸ýöÛY§ÓéOÎÎÎn Bj4Eqq1vîÜI£Ã0±X 8þ<–.] žÿ—¸p8ŒòòrìÛ·,ËbnnnÞiŠ¢ˆ‰‰ ìÞ½<Ï£  €Îϲ,¼^/êëëñøãÃëõ"BUU†eY5++Kíëë{llìë`0Kª‚‰>MMMBccãòúúúo¨TŽãTATí÷³Ï>«ú|>•¢ƒA5 ©’$©±XL%„¨¿þú«Z]]MÇë?Û·oW ! ?j¼l‡Ã¡º\.UEÕív«‡2|®££ãï«W¯ÎojjbÌöȼ1>ŸÏµqãFGss35 žçáp8ÀÚµk122žç177ŸÏG?·Ür ~øálÚ´ÉPÀ¾}ûPSSƒ©©)Ãþºº:üñǸõÖ[¡( b±¨ÝnG$ÁO<­[·R3‡Ã€X,æŽF£žçM÷hÚ)Š" …ø¬¬,æ­·Þ¶mÛ¨BµÍ‘‘ÔÖÖâ믿FAAÁŸ---8q⊊Š(<ÏCE@kk+^zé%‚€œœê´¢Ñ(!xøá‡qöìYÊyúé§±sç΄ëhkkCww÷<!p»Ý˜œœÄêÕ«Ñ×׻݆anÛi 9 EQàñxPSSƒ/¿ü6l€$ItZ¨zûí·ÑÐЀññqØívú¼,ˈÅb¸í¶ÛpîÜ9<ôÐC†òÞ|óM¬[·†ýÍÍÍ8{ö,ª«« … Ë2¢Ñ(œN'àÁÄ7ß|—Ë…H$‚´Ã ¶yŽãÀó<EÃ0…B¨ªªÂæÍ›Fa·ÛÁ²,X–!ÓÓÓ8yò$Q\\ü/´Yvžz·¶¶Âãñ ;;›öB055…“'O¢¿¿¥¥¥7 –eÁ0 ÚÚÚÐÙÙ‰‚‚*[–ex<H’4O^F0 ŽãÀq\.²³³ÑÞÞNUUSuI’()úôÓOÑÔÔY–ÿnþH[TWWž{î9º)-Âh­¯¯÷ßÂuµ¶¶¢³³N§‚ еúý~ÔÕÕ¡ªª ýýýI0…ˆ2Üäää€a¼üòËtó¢(B’$ƒAH’„²²2 £©©‰Ú½ÆÜ´ÍoÛ¶n^Û¸¶ù’’üöÛo 7?;;‹ûî»TEA$ßïGss3PRR¿ßŸÚ¢yžG~~><}ôQ|ðÁ‡Ã–e!IEÁúõë144„•+WB’$zòšöø|>444àwÞ1”÷À`tt•••†ýÃÃ议ƩS§ Š"• IvïÞMd0„¢(Is KN077gΜASS!·ñxñÅñÅ_ //:³,‹ÑÑQ¬\¹†2¶oߎ'N$Ìz{{qÇw`jj ‡ƒÎ«ò¡C‡ðÚk¯BµWûž6Þ´i“­®®îŽ­[·þàt:)ÕÓá®®.JAeYVE™GK?þøã„T€zøðaS:¼gÏ:VEÕår©.—K VTT¨CCC*!DUE•$I%„¨{÷îíª¨¨({ê©§8³=òI˜ FGG!Ë2–-[F}‚,ËÈÊÊBWWêëë!Ë2E¡ÞX³Ïwß}/¼ðÍ ã‰ONNº»»±fÍCùÑhÏ?ÿ<8€üü|8Îy™`mm-<ˆÂÂBj†„ê“¥âI£€ÍfƒªªÈËËCii)é À»Ý޽{÷b×®]†ö¦( .^¼ˆòòr‚@}ŠF\œN'öìÙƒk×®Ñçµ9X–E0ÄŸþ‰²²2pwC¶8;;‹––ÌÎÎÒ>-bUVV"///)Ià Ã0ƒ¸pá wšmɲlZ ˆO}µÇƒcµ]ºtÉðï—/_NøLIIɼBFpGŸxÂ"e_Ú†4úOBâ7ÿ]UÕ„}Ú÷xyVÀã8Тܠ1çñ„EÏêâKTúqú±z6Oxž¿á»Ñs‰NVÛ¼žÃd€~’øßzô›³ ‚•qV@ˆ× +48% ˆ_è3©¶”L Ñ¢ÿ—AHÙÌ@H´Pm‘zǶ˜ XbV¢@"MÐÕæµšÍf£U£p8L+Cú9ôóÅ—ÃÓÿŽw€©4>õ7Açt:Q[[‹{cƒƒ8þ5_ð\ÀÈ.¤&hþcãÆèèèÀæÍ›QYY‰%K–ÐÚƒ•|D_kXp°-2i¹¹¹Ø²e öïßÚÚZˆ¢8ïæy!d§ÅÌ´ÀHE3m+V¬Àºuëè¤Už° N0óJF–Òmªªâرc8räl6Û¼Ü!™Z»A£0dä|Ì2ÃtÛÐÐ>Œï¾ûg^6i5+]P"”,SKy³vùòe9r¸rå ¼^/½×IRéK:lBº-àØ±c8~ü8.^¼ˆ™™ú:ŒQÌOT[XPâãªÕœ="¢µþþ~=z£££¸~ý:|>dYNX(1!•2™¥{}¼5!Õ‚ÄÈÈ>úè#|ÿý÷¸ví}çO»æÒ«|²œ Uùi1A3¬žüÄĺ»»ñÕW_áêÕ«˜E86T÷TÊf©ú>]{5³{3‰DðÉ'ŸàøñãÇÌÌ ‚Á Ýx<ï7+™­'?fê§ïÓn‹ãÛ·ß~‹žž Óú fçZe(™o±Z'°ª )k€¡ªªbnnÓÓÓ€ÑÑQtwwãôéÓ˜œœ¤…¯F3aQx€žy%ASaY–ñá‡bpp¿ÿþ;<æææ éë®ÚÅ«­Z,Òöf B‰D066†±±1ðîþ?쟦†aTŒ¾“ ëJ„LÉÒ_ÿÙ¢P™$ å“,\EQ‡Ã1¿ß¬¬¬(«žëóõø~}Ÿþwü¦ZÂdUNüoY–a³Ùb¢(Æ‚Á É$ ‡Ã—››{éî»ïþ› !£„ÃèoÚ‚%(VçIeü_¿¶%K–\ŠÅbáL“!EÅ@AAÁ7ÝtÓG‘H$‹ÂZ©[5#³2ÛlҰƲ1»Ýî»~ýú·Û-MOO«iðã?ª s~¿ÿ7EQ.(ŠÂ[} ù?բѨÊó¼,‚RQQ!OMM™.ö“…Q¹àÄ¿IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/mime/zip.png000066400000000000000000000147761217176075400227050ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚä›ÛÇuÆUÕÝ3³3;Ë]’Ë‹®Ô¥È’u³éJbÅr8ñcò¦‡À€ä-úWò$ò’äÁÈC‚ ņ$GŽu³.ŽîÉ]îrv.Ý]Uçä¡{fgf—â.=dŒh€ât³z§»¾:ç;ç|UmT•/óÇò%ÿ$¹è¹çžûëçŸþûƒÁ`p½k17Ô7þÌ[ä~çã6}>þmU5Y–¥/¼ðÂß¾òÊ+?Y÷ßÿçÏŸôwmö¦ÁT•#FƒãÇŸ^˜Ä(ËrßÙœŸÙ훟ñkÍöô€çÇÖpPn³‡EüzÇ¿Mß”10ããýέµûO_SHðV€0m‡aü}S,àVƒp-˘b?D俆Á[åײ†ëµ›âÀ­a|@dD–”„Oé_~—rô9†¤ÍUZ«÷ÒX¾‹téIs —-WƒžrTJT#hDƒ'ÖÀ¨HÅþ‰Ã%.ka“&Öf7Ïf@PA¢¯Ì×[›yI,ûHq…ÞÅÿbØû•‚f##q§•Ï盟ҿø!>WB°ø¼×dõÔý¬yŒ¥£gÈÚGqÙRu¿P¢±@¥Äر›hÝ7D|•H#­ÉcQ¨x4 ‘˜ƒxŒ±˜´]ßx@]" >«Û0‚5#B* ›ý>.MXë,cÓ5|oƒáæçÃmÔIZå.K«Mš-Âö‹l_ù‚»Fûø}´×î!mŸÆ¶Ž€qH¹S[ck7Y° ´šI*Å&êy™êÏÂ…“$oЫĢâImk‘‰´,Ñþú}úý>WCÀ¹”µ“§h]ƒõuº«)ív‡¦SL( åˆè=F”V+Å¥ãßaøù»¡€¬uе{žÅÚ¢GQ0P¡±HPãš¹ ÂåÆ{Ä$ÅemØÎm'äeƒáƆW>¢¿yÂç¤YF³Óaåäq–ÚÒ¥&ÎÆ@™— 67/£ÙnÓjwh4ai©ÉÎÈ3z†;}ÊQŽåJ4¼ÍS·?‰ëÜA7 ðEb‰ø0˜Ôb¢UˆÅS @¬Åš”Ï/|ÄÒÊiZë±zæ«4Ý6YË€¢/Þ|@8+Ýë'[Ø4cXÂf¯à×ßgë³O¹íö;PàDIœâ¬£™€$U$ŒJllRñ €H¬Ýa¡$hªf  ˆD| ˆhED˜ÚJ"Yf({ï3Ü~‹Õ£wAw2OÈ-’F‡F*4¥ÄØ@L[ìô~ÚgûÊE½´Òm$?s;Ñ(RÅ9A„*TÆHw¥‹¨réÂç¤YJš5¡$†¸X¦K`S[EŒ±` & Y»ƒ¥b†½+UL Î`“ŒN{Ó]ᵟÿé÷Oê,Ä`RƒDÏh§ÍìF[W®ÒY[¥³Ü­B"J’¦k€¨R%¬ÕÀëä•RÑoÕ«•'´;­‰81èçˆèn塊#ú*ô.^¦Üøˆf»S™¬1Dzº«ßŒ»ã7»¹"ªª$Öá¬A @Dk`‘µÀnܯã½TY™ Ä Œ(U!†ÈRw D±©ãÊ•>I=¸iw²\âçL•K¨ìqºñ?hdkFyY?ϪH È.D‹®Æ.`Li„˜âõ,ù2°vjîê*ù0kôût[Í=­#ˆëfÆV4zšZ²ÄQ”f#å×\æ“ ==wŠf#EbD¦~XÙ‚ -‡ëù™¸@E‚J…Drr¼U®lo£iFûôi¼uôGC £“kªÉÅ%Ö³7ÛTk`0*ø÷—Þeckˆ½ô>½~N·“c$LV„Æ¥3`, U{ÞLÅ%1"!¢¾jÃå‹—øçüp)½a@ z™\3nxEC$z?iâ=<©ƒ÷>ØäWï\d©ixõõOP£|ó±Û‰¡$Ô×Öö8»|v3Š!ØXÅÀ•ßU῎¿ÖVV°¢üàþ‰$mp¤³D?g–JÔ€#.Ɖ˜‘:‹±‘¥¦¡‘Xº7ú¼ù›ËÖ(/¿ù9¢‘;OvYYná¥öÿ:T^ 8¬&¨»bH(J!ˆÂló^ˆA0ÖRú°§Ü¢÷ØqtE|äÎËÜqºÃùGNcŒ’ç%çî]%q†?ÞÄ# bDc˜ÌµÙÒ8k †=ฑڰ*ĉ‘|mŽûµP›øþýÞG|HÔ{4T²Øëï^"aµ2åä…gm%ãñsÇÙÉK.m ê:¢ª't¼ª` „(ôú!Ê"¡Ú³&. DU 8ãæ’œRŠB„±ÖÒÎ,o¾‰½ü1_=»Ž¨0Ìý¼ Ï=í¥”'<Éí'–±Fku’£`”þ°¤ô±Rêu’¦cÐ**T‰ˆÔ‡kQ#!z‚^…¡¬.7ø£'n§?*¹:(XëfüÙÓ÷¢Àßÿà-@H3C¿U%*ºöBˆXcpÖ,–ç³´qÈñe‰:¹¢¯Ù<…–»wßÖåÂFŸýÑ{ <ü§ËX±n¬SìU`Õì«TÙF %Y£Éw¿ÿwüò?ã7~J¹õ'WË&Æ5XDÌlf®³‘%„ˆDÚÌŒR×V1üpÄÕþ+ÛB÷Ô£<òõïpö+_ãÄɓɑI)­è—É’ÃPÀ¤*´‚Æ‚£GWùÖw¾ÇÓÏ|—Í Þyë¿yóµéú ëG„•nƒ¬±„ÄÌÌL”X5¸X‡Zk°€5 2"χloØì;ŽÝýu¾úÌŸðð£O°~âFƒ~¿‰bÍŒpSÂàî6Ô „(U,¶¶ÄYÇ©“Ç8uêY¾ñô3lomñÞ;oó«_¼ÈÅ·ÂÑVÎÑ•„V{ µ ¢Tb©H¬ÖøŒÅÑÓë÷Ùêyzùwœ{†óümxèaŽ;Jš8œQbðô®n2ÊKºí Tyðø9Y|Ü·Ô”zm B(+!Ô%;¶ÂñõoòÔùoÐëý ï¿÷¿|å§¼õÖi» ?âX[]Áˆ‹m¶·J6®FrsŒû žýÚÓœ={Ž#«+$΂F$–ø<Ð/=yjðÇrÝ­Ó³L~(˜S̰«ÈTZ€Dã1Öâ\‘•6O>ù=þýþ_ñÁÿ|Èk¯þ'¯¾þCŠ«±“¯ð•óηÿ¹÷¾ûèv—Q©òy‰9E9.xª o0,jñdW±ž¤VS’ÚA!9 è”2¼wµX'ò™Á ±•¦¨À°)Ë<úåAý¿¤·Óc¹³Lg¹ƒs¶ZZ—‚|4œ zªØ(OcqVb¥MZc&ɪÒj&®¥ ÏåÝ2qÿ}ÓÀÅzC1—¤´—2:íuT 9±Œµö1ø¹­o»éør;Új¶{ý’¢Œ´[)Q„FæÈRK«áœœxmp¼!aæ—ç6HÌXÆøÁ'~Y­×©F¤Œ³aj¼âdm-lT&¼»±{>®þœ5$‰!/Æ@³‘Ðl8T”þÐEo† èÔÈöÛ0¡óøÌr†Ê5“êx•e¯ÏJÞQ Æê~£Yæh·RŒ1ì ÊÊ*ìÁ Ô…m—Ÿ?ßwCõ|»&Ñêi{úÜ 42G’T„'R½7d øúÛ,<˜¬ qÍb3bŸªpÚJöKYgL^÷ë"ËÐÈv·ÅW:…%I,míVºø<`’˜ë‡=®cþóÛYçÏ+þÓù”£þÿj¥²Š˜»‘*2¸J«\¨$¦ò…0ÏV³ì¿Œ}^gW„'Ú»ÙÍ0gûuÖ’¦2A­E5 N…g³àŒÎí¼Ð½zà¾'8Kh-¯>µõ±µUxÛûÎáœIšùg©,'ø0ɯ/Ï ^>ùÄãçï9sçS1ư›áÎ½5£<ÈáÞ(›“µV_úÙËÿ¶±±ñ›…ðÿùó¥{üm4‚‹d­]æIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/report/000077500000000000000000000000001217176075400217425ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/report/dff_report.jpg000066400000000000000000001351131217176075400246020ustar00rootroot00000000000000ÿØÿàJFIF,,ÿá 5ExifMM*bj(1r2އi¤Ð-ÆÀ'-ÆÀ'Adobe Photoshop CS2 Windows2010:08:25 13:34:41  Ä P&(. ÿHHÿØÿàJFIFHHÿí Adobe_CMÿîAdobed€ÿÛ„            ÿÀ "ÿÝ ÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?ô<þ¡sm~>3ÙW¤&ëìðHÜÚ©«u~¥»HÿÒl©Ÿé<~©Õ1ØÜœÀÜžžóö·Óµ“£l}AÏe”ÿ™±6uØØ™Öãç8U^e·ÇÖ=Û[[êm–l¯í ÛüÎïRʘõXô©õž¯…UnÁ§"§åÙSÍXα$m2÷î~Úi¥›¯{®ôýOKÓ£ÔF‘zÕ=P!ÀdA\±ÈúÁ’:Î^PôŸÓrmf>-•Ôìw¶ªê¸Swè™–ßW{÷\ÌÏÑý?ø%ÑàÖê°¨©Æ\ÊÚ×0FOÕF^ìÆ Ü†auMÙXm,½Îk+µ†ÆÔÜÏBÖÔßR¦e³Ðþiþš E…õÛ§db×ú­ßn÷Š(e—½”×·ÔÉÈk*g¤Ö:ÏMÛ}]öÿEûJŸ]°›n;ØÍøWÞÆ;$o†Rü/Úíɹ¶WW£ìs}»­ýY—]üå~‚«Õþ«õ,{MÿWßéÙxÈ¿Ö4ØÓánÖ½¸Ù•»–zôë§3þÒçWúEgêV xcå¹Ö¹Œ­·²a,Ã=ãh÷²»p\ïcmþ{ßꤥú‡ÖÌwãìÁ6Ñ–Û°Ü+¾—V_~^>#í¬^Ïæî®Ë+ÿOOü ª_XúŽn?T騔_•MY4d¾Á…MwØ_[ð™NöäS‘¶¦·"ï “~¦ÖlÉÏÊÊôÙMt›dµ¸÷W@Ý]5ow¯K>Ñm¾¥ù?á.[ôê­êÝ@’.Å®ÚZ4Ú[q¥öHýíØµmINu\:!mŽ}–2¶QfMwº§¶»ê nɳ îoë—î7ße¦§Õ£ôª5ýuèn̯ î¶›žöRámnfˬÕtý ]¹Ÿð,ß[,·Ô±ýGÁu.Ã~NE˜-ªêqqÜæŸ³²ñ²ÖcÙéú®Û_èivU™^†?è)ØoÕ\wõ3Ô}•ú–2üŒvíÙk+õú?´m±¬¯Ö¡™ Ç»Óý5V~“zSýwèNÄ~X7´RêØê^×ØÌ‡:œK¨e»ê¾ÖY^ÿûsü5¿Z0©}õ¾»mvŠéÇ¥}öF>u®v3«­ôúå³ÕÝìþkôŸi»ìª½¿Sð+ÂmUä]KhÄfÿcæŠMk.ªúnǽ¯mÖ7!–ÐúíÿF«ôï«"êYoHê²üW4W“KšâÈ¢ŽžúȪêm©øø8ÛÙuV~³G­ú7¤§g®àfu z~?¨ë±ØÇÜMnk[ê5—WUŽ{[²ïJêìØÿüùFG¥œÎ¶úz†{ó2.n6®¶ÒQfÚ¶·Ô®¿[Õõ,ÿHûŒ~µW\È͵÷1ƒ­°·gé}*=6í­–íºÊë¥e¶Q^E—[EUzÊݽÊ3hs³=þ«õÔ;ÙôL}Ñ5:$u[1#\=?ë'L¬´<ØÐv é<ŠÝnßJ¼‡þ‰îÞÏø¿ð¿ÎV¢>³ôŸ´}œºÀíþžã[ö9ö_SÔÛ³ÒûOèwÿèŸÒ(ç}]nM–¾¼›(nH¯í57icÝVßMþö¹õûk­–6§×걟¤B·ê÷Nk™Cïsl¸=µDº-ý¢íº~e­ÿ¶}ˆúÖ¶ÇìÿëŸo£þ Ÿ©:–»m–šë`°Išr§óŸ¿ù–¥èñWëkô[úÃÓ¬uu0ÙëZç³Ó5»sÀÍþ¸Ûú6þžŸçú›ëý_Wz¯í>™M®q²æÖÁu‘ sö·Õuq wé=Ùú?W{pº1óu—>ü£¿Ô±ÑîÞ+d¹­kZÝ¢¦×鵌c:?D§¤5ÕâØÿAàMN2Ú6ú­ýרßç¿1ÿMÃF·H°MV¿ØÿÿÐõ œl|º]FMMº—ˆ}oÍ?¹P£êÇ@Æ®Êñ°i Z!ƶ†Ÿë5ߘö­D’SÎWšß«­û7Pqe bX\ËZNюư;ÑÉdÿ1ü×ú/Ð3ÑpuQ·ÑÛúm»d}8‰üߤ¦’”’I$¥$’I)I$’JRä›ÕñècY}悔w«k²r&§5”d9Ìm~èØüK=;}_[ý^˜íüèù¤§˜¿';6»*³!õeŒŠg T ikrjôï®ÓWé¿B=_RË,¦Ï}ž“=?MM¹½t]lÜ÷7µ¥¦–_õ‹(sìý·õFÖÿÕý?ôÿÍ~tžÙí?ŠZ$§”oTêuc±¾­˜÷2ª…Þ‰x±…ŒûVK¥ŽµÖcn¿õv[Wôz™c-õ¿HL¬Œ®³7?3‹_édº¯OGãûšç1•Uc}_£o§_ú/Ì]9ۤǒCohù$§šêyýnœ›œË8‡ Õ½ÌVÖÕU•¹¶}Ÿ-߬\û·[mVÕìôEb ë=XY²ì“^MxÔ[N=tÛí¨][Í•úµz­m{ëý^Ìoç¿›]Yˆ×…^¿±}®ïOoÚ6×ëG1îô7ÓØ’žyÝ_¬zvšì{²Ë-õ± "1œ?£º§ì¿»Ûï}ßjþ‘W¥ZÓéteÕÕººû.am»ÚÖ‚C=ö5Õ²¿í­olöŸÅ$”ÿÿÙÿínPhotoshop 3.08BIM8BIM%F ò‰&¸VÚ°œ¡°§w8BIMí,,8BIM&?€8BIM x8BIM8BIMó 8BIM 8BIM' 8BIMõH/fflff/ff¡™š2Z5-8BIMøpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè8BIM8BIM8BIM08BIM-8BIM@@ Ú8BIM8BIMYPÄarxsys_logo_reportÄPnullboundsObjcRct1Top longLeftlongBtomlongPRghtlongÄslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongPRghtlongÄurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?ð8BIM8BIM  à4€ ÿÿØÿàJFIFHHÿí Adobe_CMÿîAdobed€ÿÛ„            ÿÀ "ÿÝ ÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?ô<þ¡sm~>3ÙW¤&ëìðHÜÚ©«u~¥»HÿÒl©Ÿé<~©Õ1ØÜœÀÜžžóö·Óµ“£l}AÏe”ÿ™±6uØØ™Öãç8U^e·ÇÖ=Û[[êm–l¯í ÛüÎïRʘõXô©õž¯…UnÁ§"§åÙSÍXα$m2÷î~Úi¥›¯{®ôýOKÓ£ÔF‘zÕ=P!ÀdA\±ÈúÁ’:Î^PôŸÓrmf>-•Ôìw¶ªê¸Swè™–ßW{÷\ÌÏÑý?ø%ÑàÖê°¨©Æ\ÊÚ×0FOÕF^ìÆ Ü†auMÙXm,½Îk+µ†ÆÔÜÏBÖÔßR¦e³Ðþiþš E…õÛ§db×ú­ßn÷Š(e—½”×·ÔÉÈk*g¤Ö:ÏMÛ}]öÿEûJŸ]°›n;ØÍøWÞÆ;$o†Rü/Úíɹ¶WW£ìs}»­ýY—]üå~‚«Õþ«õ,{MÿWßéÙxÈ¿Ö4ØÓánÖ½¸Ù•»–zôë§3þÒçWúEgêV xcå¹Ö¹Œ­·²a,Ã=ãh÷²»p\ïcmþ{ßꤥú‡ÖÌwãìÁ6Ñ–Û°Ü+¾—V_~^>#í¬^Ïæî®Ë+ÿOOü ª_XúŽn?T騔_•MY4d¾Á…MwØ_[ð™NöäS‘¶¦·"ï “~¦ÖlÉÏÊÊôÙMt›dµ¸÷W@Ý]5ow¯K>Ñm¾¥ù?á.[ôê­êÝ@’.Å®ÚZ4Ú[q¥öHýíØµmINu\:!mŽ}–2¶QfMwº§¶»ê nɳ îoë—î7ße¦§Õ£ôª5ýuèn̯ î¶›žöRámnfˬÕtý ]¹Ÿð,ß[,·Ô±ýGÁu.Ã~NE˜-ªêqqÜæŸ³²ñ²ÖcÙéú®Û_èivU™^†?è)ØoÕ\wõ3Ô}•ú–2üŒvíÙk+õú?´m±¬¯Ö¡™ Ç»Óý5V~“zSýwèNÄ~X7´RêØê^×ØÌ‡:œK¨e»ê¾ÖY^ÿûsü5¿Z0©}õ¾»mvŠéÇ¥}öF>u®v3«­ôúå³ÕÝìþkôŸi»ìª½¿Sð+ÂmUä]KhÄfÿcæŠMk.ªúnǽ¯mÖ7!–ÐúíÿF«ôï«"êYoHê²üW4W“KšâÈ¢ŽžúȪêm©øø8ÛÙuV~³G­ú7¤§g®àfu z~?¨ë±ØÇÜMnk[ê5—WUŽ{[²ïJêìØÿüùFG¥œÎ¶úz†{ó2.n6®¶ÒQfÚ¶·Ô®¿[Õõ,ÿHûŒ~µW\È͵÷1ƒ­°·gé}*=6í­–íºÊë¥e¶Q^E—[EUzÊݽÊ3hs³=þ«õÔ;ÙôL}Ñ5:$u[1#\=?ë'L¬´<ØÐv é<ŠÝnßJ¼‡þ‰îÞÏø¿ð¿ÎV¢>³ôŸ´}œºÀíþžã[ö9ö_SÔÛ³ÒûOèwÿèŸÒ(ç}]nM–¾¼›(nH¯í57icÝVßMþö¹õûk­–6§×걟¤B·ê÷Nk™Cïsl¸=µDº-ý¢íº~e­ÿ¶}ˆúÖ¶ÇìÿëŸo£þ Ÿ©:–»m–šë`°Išr§óŸ¿ù–¥èñWëkô[úÃÓ¬uu0ÙëZç³Ó5»sÀÍþ¸Ûú6þžŸçú›ëý_Wz¯í>™M®q²æÖÁu‘ sö·Õuq wé=Ùú?W{pº1óu—>ü£¿Ô±ÑîÞ+d¹­kZÝ¢¦×鵌c:?D§¤5ÕâØÿAàMN2Ú6ú­ýרßç¿1ÿMÃF·H°MV¿ØÿÿÐõ œl|º]FMMº—ˆ}oÍ?¹P£êÇ@Æ®Êñ°i Z!ƶ†Ÿë5ߘö­D’SÎWšß«­û7Pqe bX\ËZNюư;ÑÉdÿ1ü×ú/Ð3ÑpuQ·ÑÛúm»d}8‰üߤ¦’”’I$¥$’I)I$’JRä›ÕñècY}悔w«k²r&§5”d9Ìm~èØüK=;}_[ý^˜íüèù¤§˜¿';6»*³!õeŒŠg T ikrjôï®ÓWé¿B=_RË,¦Ï}ž“=?MM¹½t]lÜ÷7µ¥¦–_õ‹(sìý·õFÖÿÕý?ôÿÍ~tžÙí?ŠZ$§”oTêuc±¾­˜÷2ª…Þ‰x±…ŒûVK¥ŽµÖcn¿õv[Wôz™c-õ¿HL¬Œ®³7?3‹_édº¯OGãûšç1•Uc}_£o§_ú/Ì]9ۤǒCohù$§šêyýnœ›œË8‡ Õ½ÌVÖÕU•¹¶}Ÿ-߬\û·[mVÕìôEb ë=XY²ì“^MxÔ[N=tÛí¨][Í•úµz­m{ëý^Ìoç¿›]Yˆ×…^¿±}®ïOoÚ6×ëG1îô7ÓØ’žyÝ_¬zvšì{²Ë-õ± "1œ?£º§ì¿»Ûï}ßjþ‘W¥ZÓéteÕÕººû.am»ÚÖ‚C=ö5Õ²¿í­olöŸÅ$”ÿÿÙ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM ømaniIRFRì8BIMAnDsÌnullAFStlongFrInVlLsObjcnullFrIDlongH8FStsVlLsObjcnullFsIDlongAFrmlongFsFrVlLslongH8LCntlong8BIMRoll8BIM¡mfri8BIMÿá:²http://ns.adobe.com/xap/1.0/ image/jpeg Adobe Photoshop CS2 Windows 2010-08-25T13:34:41+02:00 2010-08-25T13:34:41+02:00 2010-08-25T13:34:41+02:00 uuid:37FAAC9C3CB0DF11A4A0EC74F1289A63 uuid:38FAAC9C3CB0DF11A4A0EC74F1289A63 uuid:35FAAC9C3CB0DF11A4A0EC74F1289A63 uuid:96003ECE94ABDF11901AA26220833E7A 1 3000000/10000 3000000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;6BB51832064ECBF05E21591281921241 452 80 1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;05928528487B76FF515061CD3FECBC3E 3 sRGB IEC61966-2.1 ÿâ XICC_PROFILE HLinomntrRGB XYZ Î 1acspMSFTIEC sRGBöÖÓ-HP cprtP3desc„lwtptðbkptrXYZgXYZ,bXYZ@dmndTpdmddĈvuedL†viewÔ$lumiømeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ óQÌXYZ XYZ o¢8õXYZ b™·…ÚXYZ $ „¶ÏdescIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view¤þ_.ÏíÌ \žXYZ L VPWçmeassig CRT curv #(-27;@EJOTY^chmrw|†‹•šŸ¤©®²·¼ÁÆËÐÕÛàåëðöû %+28>ELRY`gnu|ƒ‹’š¡©±¹ÁÉÑÙáéòú &/8AKT]gqz„Ž˜¢¬¶ÁËÕàëõ !-8COZfr~Š–¢®ºÇÓàìù -;HUcq~Œš¨¶ÄÓáðþ +:IXgw†–¦µÅÕåö'7HYj{Œ¯ÀÑãõ+=Oat†™¬¿Òåø 2FZn‚–ª¾Òçû  % : O d y ¤ º Ï å û  ' = T j ˜ ® Å Ü ó " 9 Q i € ˜ ° È á ù  * C \ u Ž § À Ù ó & @ Z t Ž © Ã Þ ø.Id›¶Òî %A^z–³Ïì &Ca~›¹×õ1OmŒªÉè&Ed„£Ãã#Ccƒ¤Åå'Ij‹­Îð4Vx›½à&Il²ÖúAe‰®Ò÷@eНÕú Ek‘·Ý*QwžÅì;cвÚ*R{£ÌõGp™Ãì@j”¾é>i”¿ê  A l ˜ Ä ð!!H!u!¡!Î!û"'"U"‚"¯"Ý# #8#f#”#Â#ð$$M$|$«$Ú% %8%h%—%Ç%÷&'&W&‡&·&è''I'z'«'Ü( (?(q(¢(Ô))8)k))Ð**5*h*›*Ï++6+i++Ñ,,9,n,¢,×- -A-v-«-á..L.‚.·.î/$/Z/‘/Ç/þ050l0¤0Û11J1‚1º1ò2*2c2›2Ô3 3F33¸3ñ4+4e4ž4Ø55M5‡5Â5ý676r6®6é7$7`7œ7×88P8Œ8È99B99¼9ù:6:t:²:ï;-;k;ª;è<' >`> >à?!?a?¢?â@#@d@¦@çA)AjA¬AîB0BrBµB÷C:C}CÀDDGDŠDÎEEUEšEÞF"FgF«FðG5G{GÀHHKH‘H×IIcI©IðJ7J}JÄK KSKšKâL*LrLºMMJM“MÜN%NnN·OOIO“OÝP'PqP»QQPQ›QæR1R|RÇSS_SªSöTBTTÛU(UuUÂVV\V©V÷WDW’WàX/X}XËYYiY¸ZZVZ¦Zõ[E[•[å\5\†\Ö]']x]É^^l^½__a_³``W`ª`üaOa¢aõbIbœbðcCc—cëd@d”dée=e’eçf=f’fèg=g“géh?h–hìiCišiñjHjŸj÷kOk§kÿlWl¯mm`m¹nnknÄooxoÑp+p†pàq:q•qðrKr¦ss]s¸ttptÌu(u…uáv>v›vøwVw³xxnxÌy*y‰yçzFz¥{{c{Â|!||á}A}¡~~b~Â#„å€G€¨ kÍ‚0‚’‚ôƒWƒº„„€„ã…G…«††r†×‡;‡ŸˆˆiˆÎ‰3‰™‰þŠdŠÊ‹0‹–‹üŒcŒÊ1˜ÿŽfŽÎ6žnÖ‘?‘¨’’z’ã“M“¶” ”Š”ô•_•É–4–Ÿ— —u—à˜L˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ ¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿÿîAdobed@ÿÛ„ÿÀPÄÿÝ9ÿÄ¢     u!"1A2# QBa$3Rqb‘%C¡±ð&4r ÁÑ5'áS6‚ñ’¢DTsEF7Gc(UVW²ÂÒâòdƒt“„e£³ÃÓã)8fóu*9:HIJXYZghijvwxyz…†‡ˆ‰Š”•–—˜™š¤¥¦§¨©ª´µ¶·¸¹ºÄÅÆÇÈÉÊÔÕÖרÙÚäåæçèéêôõö÷øùúm!1"AQ2aqB#‘R¡b3 ±$ÁÑCrðá‚4%’ScDñ¢²&5T6Ed' sƒ“FtÂÒâòUeuV7„…£³ÃÓãó)”¤´ÄÔäô•¥µÅÕåõ(GWf8v†–¦¶ÆÖæögw‡—§·Ç×ç÷HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ ?ßãߺ÷^÷î½Ð}í=…·%«ƒ#¸#ž§#Å’£ÂPew=n.DÑ©2”[j‡-WŒÜ¤e…í{n‡Ó¯tÁCß]Q\†ïKã(•üo”Ü[síl2I¤º¤™­Ë…ÄâcwÊ À³zEÏöT.¼qÇ¡fšªš²ª)*!©§š4– •%ŠX¤PñɈY] ‚Aë׺ÏïÝ{¯{÷^ëÞý׺è'è>¾ý׺¥½Ñÿ þM/rn ¡¹¾ql|VäÚ¹¼®ÜÜ©¶r¼ø¼Þº|f[;C×BÓQWÒÉfRÊlHçߺ÷CWÇOç9ü®¾Xo:ºèš}5¼7ö^«ì0[/%–ÈìMÕ¹kÏ€­ÖÀv3jåwMs­@+>*™YVBˆ¤Ñî½Õ›C<5D"á‚,Ö÷î½Ö_~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷]3 Ÿõ‡¿uî‰GÃ_æñÓçvØíÛÐ9}É]ŠéþñÞÿ7ªî½¹Q¶+)»'¯±»c+¹)1ôÕSLr8˜)wuв3♋…ýߺ÷G^â×üZÿì=û¯uR}ßüö?”÷ÇÖß=Ý16~Äí^µÎK¶÷ÆÎÈl®Ø®®Ûù¨!†¢Jм>ÁÈâêAPŽ å• }û¯t+üIþlÿË×ç^õÜ]uñ?äžÚî-é´ö×÷Ãpà°ûka'Æí±” Âœ¤“îݧ·è¦ˆe2E¢9^[È ‘î½ÕŠ#«¨e7Sô>ý׺åïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¢_ÝÿÌ7á¿Ç óQÖÕÝØ]‹¾iq¸ü¼û~»¼«ê•¥ÇÕýÆnd¨:˜Ñˆ )e †‹{m“Í;íšßí;CÍfX® ÈWˆ£08û:¹Ý_oùGsmŸ˜ù’+]ÉQ\£$¤él©ªFËŸ·¦Î þdŸ ;ë}ã:Ï©;× ¼·ÆfŸ#UŒÀR`7•õPbhfÈä$JœÆÜÇP ¦¢§yiT¶6íºò75ì–Rn;®ÎðÙ!±hÈÉÉ4áÕ9{Ýo9¯t‡eåþfŠçt‘X¬j’‚B)f5xÕp ž=ø¥ŽdFÁ‘€ è}„ú‘:ÉïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{ ä/ɳøÅµ¶Îñí*œÅ.vöØëL;áqReêtnæ­L,UG,F )…Ä“¦;‚x$ƒ—b¿ßî.-võS,P<­¨éš³ëž}y§›v~N²²¿ÞžE·¸»ŽÝ4.³âË]J¤Ôùt5ÐdèòH^’U•GåMÿÞ½“ô&éÃߺ÷^÷î½×ÿÐßݘ(,Ä*¨,ÌÄ  ’Ià=û¯uRß">RvŸiï§è‹«Hk^|m.äß•t•y,& 7FrX‘:†¦‚£yníÓ†Äpت¤ÆÁ‚)ŸÜ>¢‹—··üzœ áÑUÞËÓ©ëhér$·&áï­Õ 2CØù‰7ÝÈ—^6¶ÍEÕ[ ÐÆ â¶æß¤ÆSÎO…™F¦¯øzõOåÑMÏ|*ém¹›9~•Û™^¯ß0Fb¢ÞK˜¯ë½é‡ÔSî]‹Q·ëèÔê¾Þ¡Å¹>ý׺ºcäßÉ?Š;·µ;N¿ûÕ²w&b,N~VRã6Î2¯3“®#µ»S§Åí=±–ÎOQö¸íëA ^ñÿzc«Š¢}Á‡µkñuêW€¡ÿ[upí®ÚÛ”YÌCÞu’:š:¸&¡Écëif’“!ŒÊcªÒÌf[_”Õt³¢OMSÅ"«£(©ÁëÝ ý׺÷¿uî¡d£ ¬‘RSÊÃýp¤û÷^ëK?ä<»Ÿqu?É]»‰¯«¦¥Ÿù…|°ª‘ ”¢™§Ü›u]ˆä` °÷î½Õ™0_äãÓÿ2z¯=‰ì}‡‡| :¼†Íî<AÚ;t4~zÇ…ÝQeëc§ÈGÕ8úЇ¢®*jéî½ÑþXÿÍgç^#áÊΕÜ]YþÍó øØòt*ìlþ÷ÇíîjZ}×C·ð¿=¾3Åen#mSæjfÌu‚ n'5uí0÷^ëiŒ]Õ½;§º»wv¯]ÅÔ=¯¹¶ÔÎöGVE¸±û¶.½ÞùL%fæÙñnlY8üì8 ´ÒÓ%T^™–0Ö‘ïÝ{£"e‰MšHÔÿBêûÉ÷î½ÐkÝ¿yì^Ÿí=ëÖ[;S²6—]o]É×½aýá Úƒ±÷Æmä²{KaÓ“I±›hnüý->?ø…B´qæB=û¯uSÙž¿,ùJ|–ùCÜ]'Šø•ó#¬¾+|¨ìzn±MÇ·{K²wÇWì®ÇËu®|UFÙ,.^‹,»{•|uWœGçji¼€ÞëÝ ¿Ê³åîõù[ð£âŸjvÆn‹=Û‘Ñy¼{/CŒÆ`é2[¯=·©+ó”ølD˜Ìd3UÌÅa‚(ã@l ïÝ{«?ic_Õ"/üÔ½Ÿ~ëÝAÉL«¬t‘ ZiXÊ~ˆ¡÷î½Ö–Ÿð›=Õ”¡Â|ÛÄA<‹GYüÎþOWMrO6ÞéÈ]ˆRRçü=û¯uº¤LM$mù4èßìL@û÷^ëL¿„Û‚³ù§;¬V&ºz?âß.:°Ô´2˜õ6äŽ=Gó¥XÛý~ëÝlÓ×];¸ñ’ãòUYz©•£†fV©W€mÇן~ëÝj@´´ÐÃ,ˆ),ê °ÿïÝ{©jêÂêÊÃú©·ߺ÷]4±¯ê‘þ ê?ÞÏ¿uî»Ö–Õ­-ýu ·½½û¯uÅe‰–HØÿEu'ýàû÷^ë‘t^YÕGø°ïgߺ÷],±7 $l¢ºŸ÷£ïÝ{®ÙÑS*ÿÁ˜÷³ïÝ{¢­ó[·»ã£þ0ö§h|]èêO’ýñ¶1¸Y:ó¥j·–/bRoìŽéÁaòòTî|´‘PÒA¶6æB·0ð"–½qæ’)YÑ×Ý{§ŒÑ½»ƒ¨:Ãuö¿]GÔ³¹6ÔÍöOUŸ±û¶>¼ß<-fçÙñîlY8üì8 ¼³S%T^™–0Ö·¿uîŒ{K›4‘©þŒêûÉ÷î½× êEÃ)ÔGû{û÷^눖"l$ŒŸèIÿm{û÷^ë'¿ufæãÞâj¦¥¨¬øã֘ג) l`þ?}%¿¦°¹7pÿ§O°ÿÒÚ_ú¶Ý@Û?þ$W7ÿâ¹oÿW“«Yë^œÝ K‰ÌTæªä¤r²µJ°·ñþ7ú{Œºžz<xE4óL¥Ñ@,ò-É·?Ÿ~ëÝ;‡R.Hþ ‚?Ûßߺ÷\|ÐÞÞXïý5­ÿÛ_ߺ÷\µ¥¯©mýu ½û÷^ëšÛËþ–Ö·ÿm~ëÝ{ÍíåŽÿÓZßýµýû¯uÎâ׸·õ¿ý×ºáæ†öòÇé­oþÚþý׺å©Õ/ûqïÝ{®õ/õíÇ¿uî½qýGûqïÝ{®‹ . RÂßï~ý׺â²ÄÆË$l¢º“þð}û¯uȺ/,ê£üX÷³ïÝ{ªSþxµÇnh$RSå‡KÎ40>¸[rºƒÅ˜{“}«ÿ’ÖõÿJ›¯ð/P7ÞþUnVÿÅŽÃþ='GŸã>ø‚£oÅ.ãÌÐÑI["SQ u=+UÕHÀ%=0©• DîH²%ØñǸÕ"’MF8Ù€4Ðzšpêt–x!(&™± Ô@©ôâ~C£Š®®.ŒPoî;×/~ëÝÿÑÝ3æ7cÁ×ý>ô$£g#Ú& jŠŠ*Êí·Ûû‹±»B‡_I,5xüÍONìÄ('‰ÖHk¼L¤q° 4z÷ÛÑ-èz åÒ½g·û’¾‹º!ßÕ;¾·´fÇÐÜ8œ†åÌÿÍnü å0︒h†0±Sc`¦‚%X`#Uu'€kâ ù’+þ?:ô%, ´ý:Ó@cü?êô »¿°ò¹9£oOA2î‘áêao%<ÿqf7úiÐê*lCp}¤éò@ègøáÖšš¦}…MDöšy*3É#úØÉÉ%¿Û}=Ú4[C~t·VöŸ^n§¸p¸Úì~kYŒÈSË.“ÓÕS¼2) ¥u(k©ú†k­ YÜFG‘ÉtcjWªÛø—Ù;¿¦»:›`nüÅVNªª‹ìr™*Ùê%©Ïn=—˜­Ùy Ë<³É!š»vlš=¯ÊÎÄÉY¸39‡,ò±öžæ·•áo‰ ?.#ù—FâEW¯ùúØ3_OI]*!IORƒøÿ_Ú~œéÇߺ÷Mùoø¶WÔ,ßô!÷î½ÖœðŸøó>Gÿã@¾TïM·}û¯u¸ô°ÅQ1LªÑ½( ,bçƒïÝ{¯štîš=ß“ÿ…3÷ÇZT$=u¹;+lõ†ÏÜøg§¦Ênn‘¥ÞØç’ÄWÓ9Šzyë³4u°ÕA3 Ò±fP¨é«Ý{«6ù/óCäÆÃþ_ßËâgÄÍû?Uw¯Ï=¿Ó=;_ßB¢vÍõg^aú“fÖö6æÀÕG,Y=×SKš§t¯§”WAI _Ú뤦©ƒÝ{®kü…þ3fzþ«9Õß‘»Så>*€dhþpÓ÷ÏlÔwmnú¥ªáÝyzÞû.J:ŒäqÔMMECCYâR*ئÿ(÷î½Òùvçvl¿¿Í§û»uçw‡fà¾P|ÑÇoíÇšËWe+j7Ö+¤úß»%Š®±„ÑÇ6âÅÔNª««ÊÌI>ý׺zãª6GÉŸøLÎ8v»nÁ“é_ŒŸ#>Aí*úMå¹ðµ£²zëo|‹M¯ÏÕb²t³n|-->nuŸ^ÓÐU.,O¡mî½ÑAøû¹wòÉþX3ågÄœ^oòŸåžÁè^ŒÛ·pnüîäÛû{wv¨\€Üø§º+ëö¦*¯ %[P$tñÒG\ÔíJ?ü—€êÿ‰÷î½ÖïÐÿÀ(¿ê?ëP÷î½×Îú‚]'ó#ù­7šÞÖÁï,Í~ÍùO³ñ˜1µ{#}l$Š—9³²55ëWÍÎb!#ËCÌ£… 1¿º÷FÓå_Rã¿‘ïÅMýò àîÔß›kä—ÈŠÝ‹ñC`î]ëÛ]…Ù˜³–í ôyXw%&ÛìlæâÛë™Äŵåz µ¡ó iİÉî½Ô>´þDŸûf ¿}å{Ëäo˼Êo_—ù®õíüwaÐzÚÜ–À¤ƒu®Ü£Äâruÿ\Æ?+RQ‹ÌìÍe÷^èâ$¯›&º×¸>bÿ,Ï–}ƒœî-Ãð§qìxz¯¸wlòÖïÓÓý“…®Ü3¾rµ25^_9…À&>xê§iª:÷§y)bf÷^ê†?•Çòéê˜ýW½»»½÷?yîÞЬù ÚX¾£Ý›Kº»geú3lí]Ü¿z›ñÙ‰1°æ·f|TÍ]=M5LkN´â $šOuî‚ú?—ÛùŒwgvößó5Ã|Þï^‘Áoü×]|bø¥Ô{{äS¡vŽÉÚ5cæÝ™î¬Èã«7ocK=< WV2+Ÿ#O<Õo,-EOOî½ÐÏñÓäÖOà'ÍÏŽ{ƒùom/ŸŠ§¿°ÝòSâgqug|ÏÔ›kmîlÅ"›²:ï+Ù´ùI1M¯ oÜ™j*ÅbýˆŠJ梪¨Š?u”½#¶?˜/óßùkŠî]ÃØyÎÙÝ ñï?ém»Ø[ÇgíÞÅÏäöÍÂáq[œm|¾.µvÝ,m‘ª¨sRÕ½Iˆ,È.¯uî‡Ï‰”;ÇùRÿ7þ›øßÑ{¯°pÿ¾]ü|ߦoŽû»°7føÚe¾zå²Ñn¿þ÷ä39|lOC‡§¦Z¹j&޾¥j%• ¢X=׺.Í“?Ô¹ßæ·Þ;Ãùºlß«áŽo¬z§ðG{íü§mã~?õF]vŽÙ‘¨ÿDÙ˜2”}ýü— ×™j‹³™jèž’LiƒÝ{«!î*퓱á;(vßB|‹ì_‘=[‡èÍßS°ûƒ}öô}±¼žžmÓGS-ë¥ÄÅEE³d¶:‹=)ÅÁL°WF'Ý{¤Êožóñóù\ÿ/Þ›ø¹¼$ØŸ&>q?Äß‹›7¶§wjÞµ£ß}µ Ý{êƒ%P'ûmÊóÏG†¤¯ž–<”õ°IU4.=׺DŽþA ·ÞÝûÑIòvüƒŽ•å¯ù™’ù Ûc¾ª÷„ðÉ÷{Ú“^é«ëêLƒWÏ$ÑE.¤*¶‰^cªF÷^èÄÿ<¿ó üªº«º¶»ä/em™ÚÝ#·þ\ÍÖyl•wÈ^Ðø»³vŽàÇölùÊiK-‘Ü9ÊU^mÒ¼ò9žªÔ Z¯î½ÑeþHÒ,Ú’9ýùü¸ûw¶úÞ¦£dTmÍíðÇ;ÜϤž< d7þàêÕ¨ËîìîòÂNE'ñX2ù =©‘!X䕉÷^ëvLDµXÊi¦ÿ8ñ©c{ÜÛ“~ëÝjwó»¨6×r4~ÞÁîZ,¥t8Þ“ë\X¼îc0©zè(™¤¨ÂÕÑÔMŠ  Åockîj±æ-Ï–ý¯Ùî¶·f“s•¸ÒAMà8 ‘ž±kw䇞=ýæ]¿˜"™í¡Ømä_Y!:¼E\´l¤Š1Á4®xŽŽgÅï…ÛS¤wn·6^ÛÝÔŸŽÉÃIY’ìM÷Ç­>_>6¸I†Ìf«1R—¤©p¥¢&6³-ˆ÷Ž|æ-öÂ]·p–jäÕH#¹T‘랥nYö‡’¹Gwƒ|Ùm®—pX){©åZ:•j¤’2œJŒŒõQ?~:mÎöÂå·výÈö6àÞµ]Ÿ»)vN{Ø[³_׬^wü¥6ÓQä ,5ù¬˜–J™%Šeˆ¼KŠÒ<¥ÏÜ÷ºòÞïi´löÖËf,âiUâG3®5ÔVŠ´ kREÇÿg}¢åþwå½Ç™9–öúMÌîS¥»Çq,ml‘¸¯‡FÓªGÔX²°Ó§HV‰øù]ÚÉò7ä”_k{xu¯Dtï_mãÛÔ{7?_ŒÝݯžÜñA6kWî3äŽøed:ÒS,lÑÔË7–v¤0v6îQäÕç,"¹æÛ—ŠßÄPc…RºŸO U”¡ÊE×Qç7ýû‘î|žÙż\XrfÕeÅï‚åfºii¢#%uh*µ¨í‘›Sô–Ÿ“? £êN‰ß³ñ“ûûÒ ˆÚ9É÷®oöûÈíþÀÙoA9ÝT›’›?žÊÌÕkŠCÌ9'ïù¦ë~‡™,­n ´²’îÐÇúM @(W¿‹ئª‰½Ôö§göþÇ”n¹tÜvû½Ëuƒnºd¹˜›„¹Y K!,@zÇŠꮀ@é¹q_ ;ãuüu‹wu¬»“·væÂì<2ï}ÙšÂvn7 lÄ»ª—?”ÉÇ6J®š Í*SG4‹4p$±FÁ/sáÏÛW8m|̰ΰXI<"Dh]>…{A#X€T±ômΜ•³{=ÌÚs!½Õ¤—{Ä6wQ™å’;¨åøÚQ#7yü bP2ƒÐãóÛææêî‘X^€Üû›·ö·ÆÎ¼ØØmËØû¤és²î>ÔÝ»†ž†?¹2›qZ¶‡iÁIW,2þÏ’ž¡ìg’šJ{rFÍÙɧ™­"±“™.§d…®Ý8Q Veê Ær¿„0jû­Ì÷[÷¹ËÈ›•Æí#ØZ¤×I·Å,“\É( ‰!„H¨Ê;»j®ræ2„Ësî¶êjZ>ÌøAµ~N|}í]·WGÆÅˆÛ½Ç“ÙÛÎjQªðû¾›wVg¨ë)k)ÀšŽAŽX\²Ÿíw;öé9Ûùúÿe¿Øå3íVXª0јôdöµ )BßìyCa´]çÙퟚv~k·edQi¸<èçY¼AF?ÐÍ4²jd_1w·\|ºøñó!clm“Ýu¶:¿¶¦FL‚â°;ñq˜„Ãe’޵„X¹aŸAHȳ mY}>g-o¶Úo­ÍüŸm,sßì×/qk"Й` ÚÀ#âÁc@i®D¥h:Þo›,ûƒí¿¹—ÐKk³ó=Œ6{„2jÞí‘<2U¾å@ „qJZšˆ ?=¿˜—`EóÇ©û/­æ«¬ë_…ɃÃoSG;}ng¹#4}‹M0Œ¸™ëv²CЇTršZúÖÎù#”¬.9óo¾eMã|Y܈‹aª"+ä®r*Œ: û­î6ïgîöÛ¼í¼œµÊo wŒ¹P×ÇDàÒ¹héàé–64®:>m|ª–ý¿ñsã>ÓÍÕ/^íÓÈîûªÄdj ‡-·ñˆ°m=£W%'’+OS*M‚XóRÙLW!^Q·^Uå>fçè¿zÙÚ†¢Cñ¸ÍH­Eðä}H~ä^¿¸>âò'¶{MÑ;L@n{ƒ# 2WÊ@Ô Ô<-Št\ö®Wpÿ2-ý¾{cäŽgvîέ Ý¹}›Óß1{£pmÍ‘‹Åa*bFÜ[vÕv*³'™¨”¦©’X§’¦9 ¿Û¥<˜o›ÐöÒÓlåþX‚$ßÝ&¹»dWrÒD@á€P<ˆ )‹1%å>Wo}·ûœùòîâNRŠö[k¹%’(‚D@2Êbdfrh* ±pÕ: ^Kþ’¿–'tô¦ðꌦëÆ|wîÁÂu†ýé|öãÍnm­…¬Ü,˜|ÞÍ9úºÚünBŽš ©õ5CM'ÛxžGŠ]1µa¹GîNÉÌ›õ¼_Ö[G¹†åQcøÒP  *0(5TW*7}Žocy¯“·.Q¼¸þ£nÛŒv762ÈòÇÍ_ H …™HØÕ‹K2½ò+ €ùEüÆ{ÈïÊɸºï×=QZ:òƒtn,7Ÿ›k`¨±U™ày*¼GŽ¢¥&Ú¨ÆÅ´ Gíyšó•}°åÛ­¦8“tžît²#²"»–P"­Ú¹¨Ó\V„$Ü9l÷ ßÎuÛùŽyäØm6ëI ºË$k$j…Š2š'sPKé5¦ Dž›r»¢¿—ÿIíÈŽìËm]‰òbfñ)º÷&Crg&ˆTo-Âq‹–Éhé©ü­OK"Å*€) ³1íÕý×4s¾ñut°Åss¶Ì§Ã@ˆ ¦­#ÌüLkRkù+÷·g°äjyfÃo{™ìlwËiÆ”Ë+ÓË£[y…(S‰!ÏÂÜ¥OÊŽáÀü’íªÌvðÉlÌ”ôÔtÕ'#´ú©«cq¸2tN« ~ù’X"¨Ži£ÔŽ"©°d£Žžs½^F²~CØ-äˆÈŠ×W,º^çPøPùB2¸?ÄŸÆdSí†Ôþìî‘{»Î7Ü,2ºmö¾¸¬t7Ç(ó¹4W€?¤d°í¹×/”—oRM–¿ÝK làðnTõÿ_Ü7ÖNô¿÷î½×ÿÒÛÇùƒÄÓá>7SÈ#ü—È\Ž×­žWÑ5}ƒñ¯äW[mXI±òûëyb±è8»Öõà» ‘ðØkÖˆ¨#·ü1õöf¢³¥¶•pñfð9 c¥¼U49¼’M ñÚÃÍÑÉ¥‡+ <ßÙÏ2Ú›mâä|'ê|Šº‚õÔ} Ž‹öÉ–KE†µfSò!ù?ŸA$]kˆl¸jj¶$j¯µPM,3½äjXÖ'ä-‡²P¤Šž’TGЧø—“I=:”TP8âÀ {°S^™yÀ.‘¾dÃa*¦šR¿µ!å­Â©ÿbîWÚå¿¿Š4ZätÜ7$°VáÕaw^Up$:«$yˆúÆ›wî‚ÍMSØÛ‡G‡ŠdP™èzÞg ت²“ú‡²]ýã}Ûq0šÄ&*=š-GÛпn ,íµüEý¹ëb–­–»¯°SÌIsK»}O¡}’ô»¡[ߺ÷Mù^qµÀ}M,ßô!÷î½Ö†ÿË·¹¾T.l§zuÆÿþ[ß.{*¯qü²ï~ÙÂfúþ›«áÄd6¾øÜ´ràÞïO``ëDóRâü¤4J4J¼Þà{¯txþ[2æÿó?då><|LøEþ_W|R˶»åŸÈîÒÙûÿhí ¢­>Mz£¯¶F·-ŽÝÕxÏ,qå 9w§ò•„ãêD9½×º»ùbVuOò†ïï‹?ö^èì ÒuNà‡Ÿo ›Ëµû/qd1µ;ƒs×FeJXò9©âý¨|¦**!§Écî½Ó/ÉåÛò¼þü,Ü=+?ú>ù…ð‹oucõ¦#txé1ù×¶zólã7§Xn)f•(ñÓf+0Ð'’¡#TQŠj†Žš¢iâ÷^èbØ?Î'ç^ÕèÌ¿Vìÿäï߯òΫ. žéÏlŠ/ŒX-Ë5«»*{:\Õ;æðUóµIǵY"ŒBrJKΞëÝW—ò-°÷OÄæ)µ·T{纷'Éï—û§-‡š‚îþÅÍõ'[Pæ«qu0CKlyýÔÓɤq¤‚`B¨ uîoÄŒ=ù¶ïj|eÜ=Y¹ñ]÷]ðå7]Qõue=<{š}ñ¼vÿpRmm»_pi ~n§9F°~î†û„:€7÷î½ÒBùeö_Ê/äÝÓ¿7Yšïî¸êÞŸÜ{V³5Ñϱ;£«ñ4ÒÐÑçÿ…½EDµ jñµ3Ó™¥£Z£SJñ,oî½ÒËãó_ùãñ¯­k:·½?”ÈŽÖùC€Å. =ÉÕÙ‡'Dvr–*ªTÝYŽÁŠº¾ŸbRe¦§Žyéà¦É¬>W Ä¥#ëÝå±~jÒüßþaÛóo®"Ú=›òKwôNó§› UÉläl^µš¯gm †2¿' N/¬°Ûƒƒ¿šu•BÔTçuî§òøçÝÿɼ/tõ¶ã묮öùÕÞ}™µh7AQ›Ø{Ÿ Öø ÍHOP?‡e'ÄT¤zʾ¨Zê=û¯u¸Ä\QFÔR§ýjý׺Ôûá—Ç®âëoæwüÕ{°úãpm“Ý%vìêؤ‰1»çnbö¦Ëa$Ieiii+¥Hغ£zÔ€U>ëÝY‡ó›ø 7óø¸zCkçâØ…Êí^ÑêMâR¥i6ÿgl*™k¶üÙ6Ç«VËÊÒTÕc§ž’j8ë LQË$+û¯uJ_ÿš÷Ï]kWÕ½éü¤~Dv·Ê)pQîN®ÌlIz#°s´±UR¦éËöUÕôÛ“-4ÏQO6Mbò1%)÷^é×ùcüIùí‘ÿ.þXKƒ?,þeïš-óØûOgOCjõÑÛ0dh6Wâr´u¹ œ›{_öòÍõ%==,z–ê&÷^èKþBÿ»w¡þ=Võÿwõ®{¯7±î®éϦßÝqAMɼgÉàòZ"–tÙDõj@`@÷^ê¸ðý ò³ù@ü•î.½£øÇÚ/>öGlnŽÛê<×EI„ÏvÿSÏ»ëéfÌlDz35x3‘@¢Žxê £·5K*ÉSSOOî½Ñ«êÎÐùÿóåÏ[îUøÿø?ðk®1ÙA¼¶¿{c¶^o¼þDn”C‹£¦ÀÓ–_­±Ûz¦:yJjŠh‚=CIS‘i!¦£÷^èF鿌}­´?œ¿ÌnãÍu¾àÇô¿`ôÏÇ-½°7Ým,Ýýϛڻw äÇc&´ÒTbj$º‘F¥` Òmî½Ð»óããŸmîæçü¼;×kõ¶{#Óqñǽ¶¾ûßô4‘½¶·.è Ê&ÝÅdæò¤ÉU”bZQ…ÙC©oî½ÑtùòÓæÿPvŸ}u7É?åѺ¾V|oÜ/_ñ§±>+mÜvåi¶E}-E9Øß´·~äÉys(бä+JQÅçŽV‚†zZŠsº÷UÑñ¯â'Ë=‹ü¡?˜GTôþKlïo”Û³³»/«¾3íÊúåO^awpÙô;eSýBᨲO%©¢hıCæOæ†/uî¯ÈßåËÝ(¿–ÿÅ<\L½mòÇâF# »ƒ©fÜi%,8ÞÓë ‡„£Éì¼ìñ­Bc>î®b’$:c!‰O¿u…þqÿ4º£©êúÿ/üš¾Nîo”ÐSÿ§¥ÆævM7ÇjíË/ÌWw™*©1x«_9‰)*£Ÿ®äOïÝ{« þa(¿˜>Òøõñ{¸>7|cêþ謦¨ÁUüßøçC“–nÆ\fwlà¿‹czw&â‹oÊÛGtÍ“‚yd¤ÍTU!£ššž*²þëÝkÛ³ö÷uüœþl¿¾fì…]³ðǯúnoznÎÝýÏ‹Û[/±ûƒ3»öÖcob6¢íí¿_YÜxÜZå´­dòÏR½@‘¢‘i —Ý{­óz{1]šÙxÊÚô1ÎðFX0 Ü¢ÿP=û¯uG¿Õ{ú/æÙÝ›W´²‰×ÙîØ;wºd'!œÆeñó×ã`—Yv©¦„`T bH6Þîv{o³í)t§qr’Fñ(À1ùÔ;µì[Ä>øs71K·È»$Û0¤Äv4«*3 5­@Ï#Õâíœu*uÝ8ûHAŠ`i¿Œ_ñÁ¿°ST/ü¯z{õ®!¶ïdìÌ–×Üö&úÉff™#ª\~SqÍY©Ò­*øª©œ2ó{Çþäîv·1­ÞÛt“[},+©xjT£´¡ßc6ã—9öíóo’Úû÷…ÓèqC¡äÔ‚pÃ#¦ßæ!Ð}ÃÔ,1Ÿ1z;j¯aã÷ÜÃìîáê±[.³5Áø×¸p5µö¦¶žŽ–žV–&¦R‰*O0ŒÃ—wƒwåyy/™nþ“ØÍks¤²£·Ä’&¬kÀê5*UjKμµÎ<·ÏÖþèò.Ü7Ùm· kË|ÂÌtëPª)–E+¸P_å·Ìß‘"þ/gº+¦>$oþ² Îíé)»öuN \Ø8)Ò|žÓÙk*'ÊVngO²5Eõ yLë3ÀwÊ»'&ò¾õe»ïœågrÑJ QÁ©ÆªöÉ#Pi ñÓÔãM,÷ š½ÏçîWÝ9k”ý±Üìc¸·aq5߇xzjðÀš‰‘¥þÏUk¥Uj]ÑÕ=‘½¾|qÚccfr›“eïoõ{ŸCN’UâèöŽÚ›Ž¶±|Š‚,lèVB¬ÇQ°¿Ðl[æÓoÏ\í¹OØÜG~#sZ9–Bc¦?Èèß›¹S˜ï}£ö«c´Ú%“v²›g3ÄÕ·€,ųOÓaF¡9á^wÍ~›ß]ƒÑ?é¶&ÌÈî:Í«ò£¬7žçM&+hb0Ûæ¾j³Ë$_ä4sä Y4êkȶÙ'·»¦ßµÝs3îKͳÜD…«Ý#˜ô §™¡§ÙЯÞ}ƒyæ C‹fÛ丒ۙ¬®% NÈcYÃÈjGj–ZÓ9é/ó—¥»~u_ÅöØ[#'¸Ïù´·Vê8¸"c†ÛtT•ëY•®2II*†Ó©¹ú{QíÞí¶í_ÖÏÞ7iµKz«ÜíJ(ùž‘û×Ë›ß0ÿ­×î]¶KŸ¤æiæÑOÓ‰+©Ú¤`W4©è·w§@÷FÆíz’½c´*» žÛ¸Í©Ú=}t8üÕe6X›Û²UGöóKM<*Ñ\Ê­°dšCŽ_ݶ ë•[“9Šóèå†s5­ÁRȬÀêIÈ–Ï ù‘s—.ó‡+{„žèòV×ûÎÞæÑm¯ìƒªJè„h–Â…”*U~.Ò+#Zn¾ÚùÛWmõ·B|yß}7][[Œ;«¸;‹mÐaö¾&žHæÈ¦lKUš†¢·G„>‰e3§GežË[ä­ÇÜy›™­w‘[ö´gf•ˆ¢êp xZUˆYßž=Ôæß¤Ùy‘/ök‰$C-öãJ ¾ˆIJZškFm$шt:Ÿ!>Ðw¿Ãíó·0ôâ¯xÑ`ÓpmlŠÀ”.óÛ}ö6X£W’:(óSÅ%$ ñÁVáI ažLæ!Ë\Ña»(+eâ‘xþ‹š0þ–‘F¬£¡ßº”yç7~]vnž’ _ñ˜†¤`2HÀ£q¢HÀzõR?~oþÊéýû´wæ'?Ýý Ù­Çº*7-%}6z—5P²¦L¼ñ-jWcê£ΓGäYçpàý=Œ¹Ïb‹ž¶«Íãm§iðã„FA”PÊ©¦–ÅPi¥Aê1öÃÚ¹î=£æ³›"™9˜üi®LÁ„Ñ»-ÌÆ­q°ËQ#°jÒ*¿——ÆŽ×ÛÛ£>;næñ{»rKG¶êâÎÃ?ñ*·³â\>&‹\Ì]i&4£Ä£Ðô´ô줦›SÝŽjÛ·«Ý¿kØ¥FÙíÕ¥%>šr]͘®|õ³ƒšôïÝ×Ûíï•¶­çæÛyS™o Z—KkEDµ&¡[OhàbŽ"*)AÃdìþìþ\}áºh#éÝËÞß·^å¨Þ;oûŽøùw¶È­ËÔÆÙ #à²50>R£DE!ãÖ5›Ë4AËûž\÷oÛ.®÷¨vÞk¶a“Æ !Pv¸pSÇ[%h@VéžÇž=™Þ·ë »•®wÏo/®šæ¥(nm$”÷ÄbfE BšԬΡsßû׺þ~vßQe÷oLä¾>|{é<ÜϵwVC[ؽŸ¿©„KŠ­Ëâ±rŸîö/·Uõ(ŠYÔK;N+iyËœ‹°ï6»^ñãÌÛ„&xð`…¾:1ìß,Ô)¢…îvM³½ÛæîYÜ7þY›dä=žån’+†Sswr”1êOé¢y×K€Î_ôæôçLvæçkï]Á´2´û3qì¾³Çàw U8þ–¯ÅPQ.F–‘Ë3¼”N4½Ô ‚6>Èw]ÎÂooy[kŠé[p†êáž1ñ*³$ý¾] 9bÞ-}ç÷¸ÛäMšëo³H¥#±Þ4Pꦵªž8èöÿ5þ¥Þ•ñW¥ð]u´r“)‡ï޲ÜÙŠL=ýíÞçaµn»¬Û…ÒEí·©nØ.•3×½ëØwŽ`åÞ^µÙvù.n"ß,æuAR±F\»š‘…¨¯ÛÕHÐt~|Oìê_’?öËîÊ*œ´²ºx”££ÝøzšÏÞÉ`$’ÔøüåJÒ+xØ— $fh%6Ùù“iæmy[®<7…OÒ^Y¡ g'›Fh¯•¡ÊænGæ>CæY=Áö®ËÆŠæEŽÖXîA9ž{c™I,iæKCIí_Эiì=½¸ƒe6õVKCYQ‚ÍÁ.c5E:K.;'OõPE[FìcG,‘ëS¥™lLcs·¸ž2HÈÖ†ªÔ4Ô¤€Hê‚¡" QŒ0ɤMLqIü²Û'4ÛÚìÍÒ[îñ 6Ó1$Rkôò1°n虎’Y”‘©zs¦ábón;z3Û¶dU­TÆâø‡—ŸF§gn®·ÜQ}Ü9Ztw²°«Ê•%] ŸÁä{U½{m½mR˜ÞÕˆû<¿ËÐ6i¹Wb{‡óéAŸÏuþ"ŽZ™s4åQ Th¿©,mk{C·rñ{:D–R}:µÏ4ÜÈ ¤tS·ufÙÊcëûg°åÊb:?fÕG+}ž.«#¸»Kq áz÷®öý=²;£1ž­‹Ä±Ó‚\jPÐu½~ëöÛgšÊ9Ö^q¸Œª¢Ðý:°Ì²…zf‡5î#Hʾ\Û¯7»¥»JíˆjÌq¬Â£Ïæxó§TñÓ±7÷Ì_•£·w6ÛÊmŠÝ÷»Ó%ÕÉÅ"Tì½­€HvÞÐØÓjŠ%û­¥€ÅCM[¤i|§ÝIú¤oxöÜiéÔ¾?ÕéÖáÝy†þ´pØÒ,ÐÒDZÖm û׺õ¾–Þý׺Ç,bXÞ6ú:•?ë0±÷î½ÑmÝÿ6ÎéʾZH¡J—7/k­íp=û¯tÁÅ=¬ÓÇ-oŽeB’º¯oÅ~ëÝ8¾µÛ˜|1ÃQQC FÓ‹ño ߺ÷U3üÙ?–Õù»ñŸ±ð›Ë9Ô}µÕ}“·;ס;jÀõN¹íí•B<f||UTepóSäæŽzužCLN'§‹ßº÷Tœé¿ç»¸¶®[§wÈ/[‘ƾÝÊü†Ú[»cù öU \†wµÎ?Ô¸ýË$RÈb’š:AŠ’BðIgOuî­/ùKÿ-ý«ðó¯öÿVlÆÊæqxÙ«rÛ›xçiÖ Î÷ÝÙ™c›9¹òpÆÒCJõfá‚gôtðÄd•ÈþëÝ_Þ;©pO4tñ©T¢æËnI÷î½ÔœGUíìTÕRÇKù[;Ie—ÿQù¿¿uî‚}Õñohî ùkâ†y%fgÒºo¨óô·¿uî°í?Š;#ld†V*X¬|šF¯P±æ×æþý׺(:‹oPf14B¡T0AªÊAúÚß~ëÝ A@@ƒè/û-ïÝ{ Î»¬p•Ù¤ÍËMU—V+ê¹76>ý׺_O¦ª¡û ãWƒÅâÒÂâÖ·æÿ~ëÝ]Õñohçòd!†y%rï¥tÞç›ÚÞý׺XìN…Ú»%]©©ayÝ ´&ü}M¿×÷î½Òªƒ«ðt‡ÌÅKPäÁyãéÏ¿uî™;¤ö¾üýÊÚh…@•¾Ÿê€¸çߺ÷A®ßø«µ1«æXæ0¸díkcÇ¿uî…º®¤Ûµ54µš Ô„î¢à‹ ‹[ú{÷^éËpuÆpÁMdºST  Ø'ÒÜŸéïÝ{ çw|uÛž’:gŽ8üb˧ø{÷^êÐøÓ´6¼R*RÁ#È,[HcoõÏ>ý׺±S·qPÔÁ$&* áÀE·¬XðG¿uîì÷ÅM§”É=}2ENÒHdeQ¢äGôû÷^éAѸ L aUãt(M¯k‹}MÏ¿uîƒ|wÄÍ¡E˜I"†M2‰°½ˆ78>ý׺5|U&† 4T† ª¶ü ½~ëÝ#w[á·Fd1¼ÐÈ$Ve¹Ô ž¾ý׺[Scá§Ç®=–#žI?Ÿ~ëÝ ¨zÇ Cš|ÜPDµR8v`¾«ƒqsïÝ{§må°°›Óô9Jh¥VM7t n-~oôý׺,õö}\² #Lì[Ån>·µ¾žý׺6ÏÇŸ¶qmŒ¢£bmZ¬€_P±¿Ÿ~ëÝ+“ªpâ›)âûvR¥t6?áþÇߺ÷X_©6ëâ?ƒý¼?nWN›?ñO~ëÝA¨é§S…|<”P™tƒã[è~—÷î½ÐH¿ö ¬&±;·ú}=û¯tað}ƒÁà›KN‚•âñ2éF“ÇÒÄ{÷^é#‚èý£ÉVd©1ÔË5ac#ÖçW×ð-õ÷î½Öl_Ií,^à“pÁ¦ZÙYD¡µ^÷¿¿uî¸öJm}øƒïi!(²ÈQuébý׺ 6ïÅM¥‡ÈG[4qTX4a†« ¯Óþ5ïÝ{¡f«¨¶ÝEM-H¤…Zƒ \ZÂâÀO~ëÝ+3;G™ÄGˆ©ž8üaHà)µ¾žý׺F7MmY1Rbä¡§1:•¿OÖÿן~ëÝ>lž¼Æì”h±Ê©$…^¿ûo~ëݾý׺ÿÔßÎxR¢!jI«ùXû÷^ê…¾x|íLgS|²ø{¿s])òN"—sm¸)ª±Ó â¦M«Ø{f² œ.òÛUŒ–zjØ%ñ–òBb™RTØ4¯§Z"½VÅgó|í>·«¨Äü×þ[qo}ßD±RÖö·Å­÷Q±$ܳAš¼ÆOaniiiékëgFǪ•I°°²¨ãg÷œ¶Kt´²ße6kðÇ*¤è¢‰U´’Ðt½åmŽýÌ“Ø(˜þ$%ì?˜è=Ý?Ï£¬(¨dÿBË'³ó[ÙlVGänbãÚ˜ú°Þ‰k¶þبßRåàR.clÇýXö¾÷ÝŽz¾ŠH?}˜"aB Š(IéãPãòn˜¶äí‚ÕÄ‚ËÄpAذùp?˜=ê?–ŸÍ[äÈþ®ùM™Þ9¨rý¹aÜkÒ}eÛ§pû}§Hw&ǃ 5.ãL¹Þ[G^³'˜‹)P´îãÓ Ç’M$Žò;ìIbMK’Xœ’k“ùñèJ¨ªªª (`8<©ÕÍõ×ÍÜÖÏìŒs´)3­ñ“³2ùœŸSö»kîÿ{Î*ˆj·ÏSnL61“"v\õ(™M°LÔ K QQJÔßur¢EÔ¿Mdj7ÃÖÃkÛ=χÛÕfpù¬.äÆÅ“Ú{³Tµ›wtâÛÑ÷xºË)ZŠyAަ–@•³)I.Á=(¹ êÊêH ‹‚=ë¯uËߺ÷^÷î½×½û¯uï~ëÝGª¥‚²&†¢5’7YX"ÄsïÝ{ Æ¿¦¶FF¤ÕMŒHN£¦4äÿ¶÷î½Òϵp»v!2Ž( ]QAÿxý׺Qû÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî‚~ëÆoŒ×\n|?\ozž·Þyƒ¾¨öþuUmª±<2µ|{qÅ>)+AÆ#©GŒÔA*¿u±Jäc­s{µÿ˜NÍùGµ>?Ió‹wURn^¯Þ[ùóÇ º úzݱº¶žß§ Ž6ƒÓIIUá‘ݡW@'ÝsZW§%´yúž¯7âhíê¾Çcû²2}·º>â¶®£{ev¶×ÙµUt•UZ*Àìú* $ §"5‘#òKmNI>íÓf„àS£{ïÝk¯{÷^é“qWœf"²µ~°G¨¯ô÷î½Õk,õßÁñÓeå;rå7vé›söí~5PjòU”¸Žäì N‰Ø‘qØ:jXïÏŽ¹&çÞ‡¬âŒGV‰ï}W¯{÷^é«)œÃašLÆS‹Ž¶º“Fù Êz4ªÉWÌ´ôúf¨’1=mlî–ï#ª ãߺ÷N1KÊ6§ò Ç¿uî²{÷^ëÞý׺aܹŠÂWW¯Öž"ãü?ß~ëÝUòù Ø=ÉЊÎÊÝyëºdwn6|þ~­ë²sc1=Ǿ1˜9jxqXJZzXAåa‰GãÞ‡®àÇVùï}S¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{ ¿°»—­ú¯)׸]ù¹`ÀäûWzÁ×{’Z<•[îåQÎîxpѾ>Ž®*lÚ­ŸÏTÐSƒ ‘ãG÷[šÓ¡&š¦*¨„аdo¡ÿñ¯~ë]g÷î½×ÿÕßãߺ÷P«±ô™ž®š)VWPÀƒÁàƒø÷î½Ñ@ío…=IÚi2›ÓK{¹¦Šä·$ßI?_~ë݈¿”ÇGG^*ÎG“]Œµõ>ý׺7iðÛ¨úÞŒSâöî87F¡K?K}tßߺ÷Uqóâ•OTf·/jlí¥‘ÝýS¼þÁûË«v÷‚Ýbá¼§Û½]%DQâ;£®ü-;GK› iñ•OU%•ŠšŽªË¨|úÃðïwÔ픇·ó0v_]ozi7eÛ–J.búk®7qæ+;wkwFÞ쳨væÜÈnz§ì&Û»73·¨‹<+_ U”¦­áˆé =ú§Ìu²«øZ§¤4ŸÍk¾·ê¦ðøýð›+½úz¡ªæÛû¿±;“kõ&ë߸˜#œÒgö–ÁÉíÝÁ[IƒÍéŠ\tÙz¬|•pJ¢…HcêŸ!Öô¨Ã>z]ü~þh»7å¦åî^­¡ëÕ×Y~­Ú»³qRïgއrQî½×[¼è3Û;'·â¤zZIvÃmhfŠ¶š¾º›%MŽHüalÞ½U—H¼zÿ’IÕјÓý{K¼Ïû~æßG߇·'Æ/ðutŸ ;jŸ¢zSµ»Š§ÙøúÇ®w¾ÿ8­×ÎsvÎOqL‹R×-俇xDæ „Eõè{i;ê TÕXõ_ógÞ›õðƒ¹¾/ä:ëã>wlVnÉû£7ÚûB£/¶výÚ®ÜOº·?[>?˜¤Ú¡1ÒOUFFH¥‚g¡O7Ž=W厬P «tÑSüÓþE÷C|'ŸrõFB²÷i÷n×ê]ï¼ñR,2Påp[ ]·º¤Ãcò°Iæ£|½m“ÂÊï ®¯Túuí*0_=¿Šÿ;ºïäîÕÜ9 <>áØëaåFÜ쾯ßpc·†Å܆j££¯Ž–¢¯“Åd©XTcò4“KI]LÁѕđÇàkÖ™JÓÓªùÙßÎ}w¾ÓÆe~3|GËïüÌt®›Þ§xvž¯ºóhn?$äm,FòÉmz̧`ghè– «~à -©Dy¼zµà:±@§¹º6ß?˜þ3¸;%Ò]ÇÕùÏ}çþæ¡Ù;‡7‰Ý;{{mHª–«qõÎþÂ%>'uÒc*f+©Ú :úF‘KÁ¤;/ý½T­Aªôîoæu¹cìáÕ_úO™N·Édv°1½]Ô{[vÂѵ~ÇÇîzœèÊï㈉‡ñ luAyfœH1êú·  5+Ò÷ãó¶wõoJwVä¾>w…>!÷&he7&'xmŽÀÚÔÍ 9Á×;ë â\5Lè¹ )©é2K*3BÉähý^´V‚ ÔtwóLß{oä/p|péOŒ5]¿»ºzm‰U™Îä;[×»J£½ö^vRÏ.W/¶òmI¸f¬ÉÍCGŠ:±:ÑMS,Ôè«ú¹ l Òµê¾ÿ™GËîôÍoo‚ùìWƬ…$xÎËÚ]GE™í-•ʯiVõ§kâr;]KD¹zZ)°ØšóVs«Q5çöU—¶qެhýÞ_ê=_?ÄÕÝ«Ôo­ŸýÁݹ ?>ogŒýé¯# £‹6?*Y<‘"¨×¦×ݺlÒ¸8èØ{÷ZëÿÖßãߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷IíË·1Û›UŒÈÓÅQLO,ŠY”¯çý~ëÝkßòSã®ûø}½ó}¹ÔX,æèê<îywobunÛ¨†“=„ܰDÇÛÝ;STÉÂöF2Ž޶ŠV‹¹ññŠ*æ’Ž²†ÊÚO˪²†ûz=½'Þ=Uò¬ŽïÇjÒÐÕcj7†çÝpd)v¾ØÈSmØÍ>w¹qUYÃEýÁßÛ*iSxâ2o4 OQlWQ¦Ì·ýXë@ùyô6üIù?´;×n±Û›’uRQÔÔÒc÷ 5””™úz‰ ¢ÌÒÑä ¥ÉRSei‘gŽ:ˆ£ž4+¢°`êý~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷T!ò•Þ?æ“ÓòG"|Nî’–úê£Õ6÷¯1ÕÇömöŽª×ªz?Ø¿#¾WíŠÞíï­ßmòxo<¾ÕÙÛ˦Ël½çü?%°7-6Ojf*ëhjvûÇB²‰¤Š¨¼G¤)Ðz³6ÐN‡>Õøk³vöøéݧؿ,>Bç7Nåߘ¼çVìÿpùºÜöîØ÷tYL~®!EÀÁŽi*rôÔÔÊêQÍmÓçÖƒ áÐÃð¢™h¾Y|¼ëŽ×È}¾ÿÜ}§·{3r†4¬ÜU“Ø{com¬MLŽdÉâ6ÍV·è—Z)”©Òd øq=y¾#…:¼ÍÁ±ú÷‚©§ ­Ç®J£QUMF*)¾î¢š‘©a«©†œ0šX)e¯euQ¦@Ä[ï¦ú¨/å=Õ›{rüyÛuõð#;î~è'J(%¡î>Ã@íÇ,DcŸ©÷¡Ã«ÉñõytPwÝmêïç‡ÇpeÅ®%ø¶j$,«`ZG™‹É7<û×ñuo÷Ïú¼ú´/†]M·k~5õÞFhUd^§Ø²B‘ǤKýÖÅŽ4*GØ*‹=Øpé¶øÛÕ,l©%¡ø‹ðÇLDT”Ÿ;v¦§‰BE Áòo±Ö$Š4²" P,÷_!öôéøßý/ù:9›2¼ãÿ™`Ñö]sR§mtwVRtõvSÆ´õx޾ÍîóØ[G [+ú+¡Ìn*÷çÕxÆ)äsÑÀþi}_…›àÇhPl¨-›«Ãmüœ¸*:”!¹0;csà·†÷À㡈ùò¹‰·ò€R g%´–#LJZOˆt:üMÄôçkõ~}íÌþ9µ÷ “'·²8éišŠ\tÐÚáD6§zB¦) !^žHÚ'Uu*7ÕH xõUi™ê¬çóù—Veh2´{[`ôF×Üù\LñTÐä·®3!ÚÅ㊮xj¦ÂÐKEŽœ©ýªŠI">¤>ô8ž®À„JúŸòt`ÿ’/üÈŒWþ$þñÿß˾}øpëR|gòÿVQüÇ? >P€mýÐOøÖûŒÛßÖ—â_·ªBùÕ5ûƒùQæÎÚÇå²y7é>©Ìä(pBÙIöƳbç÷„ ‘Êe“û£Œ­޲ «Ò|~¬¸—óé‹£þVö~ÎÆnÝ©òïäÕnÖÌbhò8 ì'gmU ªÆTB­J`¯eTHâ²ÀSR¤§Ï­¡Ê ô.ü9è³û+äòëîòìNâÝTX>°í\–ëÜçè1Ùí¥K&Rƒ™\nÓÛ¸Œ¦sCŸ0Ôg¬j)§“Å xLJŸ^bHZ€M¿ÉKýv7Aìü]&[3[.¿rà7†T1Vâ³³n<ÎPO]LO“Ç›£­Ž® ÖT–ÀêGUòðër‚×¥?ó;[ó#â.Êê ¤u½™×ù­ÿÙûÐaªa–}ÕU›³jW&â%çpf1ô´‘1v§gÒDa×LjëË„rxu3ùCbvŽw©\nÊšZÃêÍó¾¶ïkàj§VÍRo\†îÎçj3yqSjºÈ·e=z×RV¸)U Ú6"2©áïIñWÈô ùߎÙðüÇø[²:¶²š·³v^øÞ«¹N2«UfÏêDëÝõóræÍy1ô{×?˜ÇÑR$ª«[-;(:QÈñâ:Òá\ž'¾0m¨7‡ÎOšrf5;®äøød$ O~“ÀéÕªäéQÇô¿¿'¯7ÀŸŸøzšÁÁc;à}%<6ޝåN’Jú¢~œí™ˆú«„{ñòëÉÁþή¢öî? ²qéDšJþþÂÿO{ê žý׺ÿ×ßãߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½ÒgtílVëÅÔã2”±TCQÆVDV`Aúƒý}û¯u­çÍßå;ÏÕoÔÛ‡{m£Ø¹|f{}õÎÜÝ9¼W]ïöËŒÎîm™©ƒ ›ÊÒ$p%DR4ÔìÊÍMNÑz½zƒ£Õü´þ!î[Z|Ô“yÑ!n4‹X\ño~ëÝ[ÿ¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¢{Ø¿6fôÞX‡}ù·v¦bcsC!’XáÚ›—-†Í屯‹Jш™çÉà)dYÞ§AUp¬Àû­ÔÒž]ß“ÿË»¬;ʳº2ø*úMë¶©$¤ÛÛógn Á±·æ ži òRPnÝ¡“Ãæ¾ÀÎÌÿk4²Òù¿Q¿½^¶¬W‡ß—–Îê çW¾1øŒÖg|d¨ÿ…å;°·Néì]ýYŠû—«|d{£{e³Y n:Y¤Õ,fž)™U¤WeV x³6 ÇB—ÊOå÷ÕýùOƒÈnm·$ûkš™¶ÆíÛùlÖÓÞ›jz¸L‚Ý›V¿ž¡Ž d€Ni¦eS$nUmêW¯+Àô|jø·úOtg÷Ž.=åß{‹.ÛËïþÅ߻߱w}^Üš¾‹&øËïæ_ìq-ÇÁ3CN‘ %‰õ2ƒïÔëʼn<:8ß~3í/»j™±±†Û5YêÚ tµÙ,›ÃS¹3Y=Ç—×eªëkåY¬ÅDÚ^FXÃè@¨ª«¾´I&§Aëø'Ö™ì·xÕ¶ß”Åò#È;aF_ƒo⩚Yꟊ¥†‚‚=T“TÔ44´ê¥äwwµØ’I÷î´sžŠ\_˳¨èvÎÌØ´bh6]v-/hììQÎî)dÅïJ-×”Þ´¹i2edÉdQ7&f¢£íªeš•ƒøÌf%T§VÔjMrzV|ø/Öí±ivÎüÚt;ŽnBŸ3Е孯åð™Š>irû?†ªÇç°HH¨£©‚R…’¬TïZ®Aè©õòÒÚ{}Poi±w†íÀÓVc¶ÆåìîÎì>Æ­Ú¸Úütøzê-µìÜY,n"*¬\ï´p Œ,SX_O½S­—$Sˤ®óþRÝ]&w5]€ ßÛ?ºëjë·ŽÖë¾Òì̓²·}M}H«ª“=´vžéÅ`¥5 ¼ž`±»ê6#ÔoÄn†~†þ\»§÷Wrlí©C´¥Ëí­»µjhñ&²oð}­Uš¬ÃÃ5ê¥£Š¥j÷dµ ‚¢²YšIÞI=^÷NªXž'£gñâŽÍøÕŠ]­°1RavÍ>c?š§¡›!“ʺWîŒÞGqæf5¹zÊêçY|¤ò2ˆ>„ T{¯I©ãÑ‚î^µÁv÷\îÞ·Ý4G#¶w¶ÝÎíMÅZšº&¯ÀîL]N/Dµ˜ùék©«Y" a–9cÕ©X=סqè0ëî€ÂlÝ…C°ñô¦› …ÂQàq²I5KSc1´‘PPÀÕRMQ;CK)yÈ»I>ýָ窽ß?Êgª£ÜÙšíEØ[ ¸òd7&Ïë.ÖìÎ¼Ø›Ž¦¢§îj'³¶ŽèÅ`bZ—º´°Ó+’Xúίz êþ#ttú{ã.Þ螤3gí¬FÑÚØz6‡ÂÑ­%,BòÔTJÌ^¦·!Y;4•3¼•³I+»±c¾ªI&¤çªø?ð?hwÏAôÇaš]Ѷw›íjÊ!¾zãxî¾»ÝÓÐQî<ìpÐÖç6vWQ“¥Œ *µ^c€­‡ºÓŽä3ë‹øÓü½:ÿ§W&›{jÇŒ—?UvçÏä«2›‡wnÊøLžÍÑ»·nSqçe€Ï'ˆTTº@„J€‘îÔ§M–-ÄôÑò/ùgõ—dîê~áÇn]«ØÔ4ØØ»¬·®ïë}äøê9X1õ¹­•™ÃK•¥ˆ»ZµœÄ¦Ñ”°#TëaÈòéAñùì^”—).ÙÛMŒ©ÏÔÃ[¹·['›Ü»·tÖR¬‰MS¸·fçÈå·XÓyäñ$µ(LãEÔ×Ý)Ö‹âz2»#â–ÌØ]«¾{Cnâ^‹rv\ûf³zä vJ¦<µ^ÑÁSíœ ±ÑUÕÍAŒxJXá+K+)]nÉcî½R@C¥?ünÙÝá•ëlÖéÅ>K%Õ;Æ“~ì¹Ò¿'D1[¢Ÿ›Ûi–}e$9\Fá«ÁR³Aª@å *‘î¼ ùô`v†øŸk¸ÿl SïÝk¥G¿uî¿ÿÐßãߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uzJjðÇ(‡Uo÷°}û¯uÊxi×D1¤kýBÿ½~ëÝf÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝ{ߺ÷^÷î½×½û¯uï~ëÝz×úû÷^ë«è?Û{÷^ë»_ëïÝ{®¬? ÿmïÝ{®ýû¯uï~ëÝ{ߺ÷^÷î½×½û¯uÕ‡ôí½û¯uëè?Û{÷^ë»[éïÝ{¯{÷^ëÞý׺÷¿uþƒý·¿u¸øòTÑH‰–Çø~ëݽwÔÛo®Qi6æ#…ÆBóµ&3CM ¥É<¢žŽŽ(i 4¬ì@,ÄýI÷î½Ð¹`>‚Þý׺õú‹û÷^ëÖè-ïÝ{¯{÷^ëÞý׺÷¿uî½ïÝ{¯ÿÙdff-1.3.0+dfsg.1/dff/ui/gui/resources/icons/splash.png000066400000000000000000001355361217176075400224440ustar00rootroot00000000000000‰PNG  IHDR;·mÙùÐ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGD°°°ç»þ÷ pHYs  šœtIMEÜ:*a¨~ IDATxÚì½i°]Õu.úÝN:ê;:B¢•èv,ãb¸¶ÁÆÏqrƒ¯k;yõâ?¯*/y?RI*•÷#©º÷¾—wsS‰+±ÇÇô–LB4 @ƒ„„Ú£Óê´{ï9Þ½ÖœcŒ9×>ûH"ñ»u¶ËH:gï½Öší7ÇøÆ÷33æ_ó¯ù×üëòWi¾ æ_ó¯ù×üb7ÿšÍ¿æ_ó‹Ýükþ5ÿšÍ/vó¯ù×ükþ5¿ØÍ¿æ_ó¯ù×üb7ÿšÍ¿æ_ó‹Ýükþ5ÿšêb—Ñì˜Îþ̘¹õÿ¦üw­Ÿ­ß±úÂïZäÿË¿qöi–Ÿ÷]þÄŸùÿòïÈ¿›ÃÏÂc„wp¸´º?öÿÏîÊ?Oh×àðyñwÿb¨çS÷!Úùgdgø´ÿfñcVýš/|ŽM{úv1÷ ÑÞP— ×ó(ÚJµ‹`3ÀQ[„Ïsxtÿ½aŒÉïSϯÚUw¨éyß¿a|Šß‹¾ ãñ{d{3«ûÕw®áÇ9³ž ¬_Ï9ñ»ÐÔö¾ô`ó}*úAõœ“‰ažÓ< ³è/ý¼ý3¿Ô¾Ô’ žŸÕó°DzY]Õò»Ä¸"çœÿÙëG?'ÿŠâwµÿYêçEï+~¥¾ÑÏZwÛzoOGf‘jwåüÍmn}NOUØ|ùõæÜD_R|wq˜ ¬Í9u[ö½YO̹âߤß+ªßqZÍVüµsͺÛõggsèŒ …¹~I§S–â¾:ÿü,÷Ñî×Ñï|û"ù©’Ý ößÖßÿ°ƒ~zµ•»µÂpl› ûž@qQXdvE‰^ÂßK´Øº[Fös8½ûÈgÊwr' ŒDâBl‘-sܸœ_Wìz¶]Ô#²ÚýüææÝ·¾L]B£Ú€YÜ# ®ÑhÃ)D–ýÞÙgÉÿâúe×ú¼B-þ N©c8» ‹»q,Ϫ1t%nZ hE4°B(òZÑ5X·e@ GEHËA#*§¹]Φã Êêž¾_ô¹ý¤8¦=2¶ï—hÍÐúùÅ òêâÚ~ñÊ–¯YùõˆÁùªFbò²9AP¸£õY=’ÏM4 ¼'ÿ½ÿâìï¤Gí(ŸMݺ_9ûJÒ÷Ǧ(¿g´Ú 4^«]eß°ü\xÚ0L;Û¶…x,BŒôÈŒ—lÈe²kù÷ùˇöfqÝËâR qO²_94¿œ&yÓù>Ð=¢ÆTÖÇä+¢þ NÙ½d­é» Œ¥|¬@nŽâZª-SxÎŒÏÐ/r>g×£¼ ÄÎJ¤.#žZ=ubËÕ2ŒÑ0™Tï‰ñ(6 Àü.Ü/¥æ6›~÷c8ºQÎî©õqÝÏ­ßÇë5 Ž7H¹`èǯšbrAü™ÜÅŸmÈ!ŽÚ?Ú„ HO†|ñ„˜$ÜQ8ÄœóÕýJŒ ƒ}ÄøäŽË)ˆKz€ç(ÀÅ-k7…L°Ä·MvÿDÙ-ò©ÅÐ#4_¶H+4>÷`Úå 1¢#1ñÕ}ô¹5ú±Œ¹"+Dp)Â(¢½=¢F:àlLjñ¯6m€HM¦‘«±«Ub(‰î°­@z\ HÊúÆž¶òzp@ùnÊ(:$߉y%Û¢µØIÄ%vQµÊÛSô žÞ=ã‚ٯ̪¬ïw{±B3Q ¨ÈF9RߘÞ)˜Iߦzº‹¬ Ø/Öµlr?M¶”üAþáø!Ñl´F‹®G  ²@¶Ä,v:*úB}[¦qÍ&‰¶PÅÂ? KÄxB4Ô­Æ™¦Ïæü¦c›Dˆ­nâøÞÄÞkoN4Z²ßZóè9[ÕXµè(¾IÒ-¯‰ØÌÉ+ýéh´šéŸ`ž› pcÍ¢¾ô2¿‹à`Á'ŠÆ*õzƒóU–Ž‹¥“äxUä©Õ‰lvJ2[¸E‰«:¶åñ7 ÁÓT–5;áÛì:a™‰cX~´V‹<+ÔËÙÑEÙ´a› ˆGîs\©DôDP;¼>> ”L:ÈŽs†íP/,b5áì"c/rÇl¬ƒGøhU,âIÄ«Ì5R ×·“:ŠF‘RdqDHF,ÉÄ~r;[\RÎ2“21‚ý^;ç8ž EY$«c†`Ä1pß› ¥’xNsÉ‚ðpŒîRÇ:ÑÆH…ÞÅ/üì-ÌèÅ‘Calhff†ã˜›YmùmŽ%Œ‚ @J*”üаJ³‰¥ØÛ11&ïY¶x‰»OmÞ ÝOr쨥£&?db7³Þ«lâ†.DÁíïÔ ÎFËqL|"($=ØkóñÏÉs:lIœ˜þ¤5Ø‘æc¼l¬HvÌÑ\p™8Éǹ:ÃQ‚¦JÍú¶ÿ»<³À$#ÕIÅg p~×333ÜÉÊ«wNŽS:ZQ°`§Ðh'»k›§‰Í†© ÷‰3ö:Ý+D{rêÁÛoô‰·G>KMèùÍÁ¶íŸ6ñÍ÷¥_ÒW{?¯=Û°VYúÓþö‚œ:?ŸinOܪ‡Úàf…®³ödÅ£:³Cp–½ƒÊ ô¾*WuQ™O¤ðst“³ï`Cb•Í7&qü ‰Ž²‰i‚[lÎÃõAµ;ñó5%Ê%‡çÉ‘¨à²y$gHL$²,TRÌOi{•¤1­KЉ&Íu$ÃWCˆc" iR‚UЙRI¤ìûòvg m,N&£Y¢™ˆ8YžR“ L`y4ñchº‹¤«:…M{èT3%2~¬ïŸ5y”ˆC›$ùgašÊ•%…ÆÁ›$"ÉDég’ 6VSN#Ut"G3‰%EâÌ ÑV6®ÁÖ‰¤IЩØÐ•ˆ=Z¦o R„Ž?ƒ¦§§ç=(þMöôù×ükþuê3ïôçfI·Ë"÷|Eç UdËETÙ¶,g]øžÊ–„à?ëÒUø ]à¬..J——–A•ĘBpYC_ÞÅŠ¾ ¯)Šš¡ §£´¢)zŽJ•9]W¯JxlQkñUˆÍò»eq».f×%ù±°DѶ,|—}cï…`‚<€­øá¨ÝŒž„À-؇…`õI¡À°•ïr¬#*¸O•SEbú>´7Û~Q2ÐBRƒåܱߨe¿Äý¥!Ǩ'º½Ãd¶åV¬KϤÛ1œ €(C˜ÅùU &«>”éj«b`û\ŽUV‚"4555 ²‹Ïs¨ >…‚åN ßO¥@žŠ#½g´Ê¾MyQ唡_DGÆS½ÅâJ­Dޏ¢âUà̶Ïi+$œ±7?ë *]f¸³ùÒiÑûûûjíÅ2Ú7aa©`Á‡g ˜ý.ÚÖ#;V;d,±ä‹ÿÁ`gJ³9às¢Û1J2òF`+wäÌÎbÁë)B@Y°(Î`Žd済PBr(´Œ~ú„¾•.NoÒµíÅ<*L§¬y–Sˆ(ñR´ ‹4aJï Bæ¼­­‚) Pú,…‘­ÛË)>m èM»«òè$RJÀHJÙñQ(o%ÛFб„"ŽªIÔ•XJßTN Wn0ibbœ!É£©PpÙÄãJ&u žÆE¹–îg…y3ÚRpEÍm”„6Uôudt³æ«û€} (+HÎ’¹cÏOÒ23Œ´Œ•UïI–UI¾’¬ûGR¿ Q]%ËïP(4º¬žV¡ÔI}$Ï¡B0î=gÑÜ€ÊÊç*!05*B1‘Ý(‚%ªÍ8Š‘ÜUªí û>ææJ$ ­¦!!–¤óñ¤Ä”_–ÕNkL¼5«¤äšL2rW0m®¤)ŠÕP$%g²úÂLYa$ù…iÒtøG…•ФPõT™ ÌSP;CØÅW!!%#„ô*L^6B©@®@"9!R”¥1ÅäB958âÊ¢x¤SM µ Hjé ¾@”V Á—R‰š–ϤI$@ÀbÑSrOV„Ô“0u@_ã˜]1.d—›×@’8 ûx‰-õCŽ´—ùA«àäå…, Ùu\3VY n¶ÄfÈÚiA 5ú@Ö¿#ÚŽ=Z qàät&³^p´,&%²òçL(…J’nQÁƒ&vË:WGe ´ªH 3óI.¤zŸ×ÏÄöždHAw8òªŸ¬‰ÊáíRèA¬,`[q6kK8©Òøøx ïÏR6>;½ÍRkö^‹(–j±%#,´Ø(Q/f…"£]%Ro &…p ï%Ú5û{NÅNiE" ´`ˆBÑ}¾/‰…„îP],**³”)Eâ­ ÌÉëZØ Èh„71Ki•ªVoCµMíRˆø Ø×‚Šf†³‰’,~“÷$ÅqÑ®¨­¨_åf‡Hï1Ý ÙJ僠´"\\çÆ•Ù9—Í”ªẪè,#‘Ø¥ÖUø· b%W²@yœO­¸K)ɉ›ÚµÌÍþ[–dL¾ŸL±¨Ê¶™ñ(¹Îº(Û5«Dk"‰â‘YB ¾ kÇ)QH)m•— ©…-ßi5¢"±»é>ÔáyLVY"¤eHK7JÇt/$AºäJÆgüô!{j P¦ÄzÝñÒJVf@kLxI0¿HA˜c”’£”Z_ÔÎJ­Ä±’!Ê méi%G«VËJ§•MœõIDžZìF!²›ó‰„27YI3¹ÊR2Ò§Nõ±ÞÏ” ¯™ë±T;â4r~]SŠÇbßD(ÑDâÄ‚O'OžäŽ Ül’,sB€£›YNümÐT±¹düb–‚p#¸9;4í èÍÖx‘ |Ò,Ž“`6Ó¹()ßj‡Šm/WxÛq@ª¸Š¾ätO/sl“6¡»"%µ$Ä'êhµÿ®Ô„›íê2f!K±°D›É\¬S1›šFhQ×ÍÇÄ ¬°9+‘ñ;P»›™qÜFÉ‘ “ >Ó+‘…1'3¥d èçcX¾°ß(¥æñ;A¨Vë÷¤¶Ráã ånLZ‹9†Ó¬$ÖåN þYemu6›–G’VâG¶ÈÈs1uâ3Ç %£-%‘+‘‰ q,µe2~l²*ÊWr_òú‚Gç`,÷­ùSú™}Þ>g³¼4Rcäc´$Ÿ—Ä)ˆ·ÆÒO%!%Ê¢ ¸f«¯ÌD²ðu ‡ÓbÓJÁR‰Ì£²Š·É[$öÀF`)jr€Ö“„±j Fˆ#T& d¸“Q2OÆð!Ђ<¤Z=éÍ üOùz?D ~y…þ=ïl^>âÿ¯R<2÷Ö¥<•±RÕe²(ZÐdi³füÊ¢|MVfSN"‹{Y^eÔ4ñÖ~ö¡Õ®îÚwUœØ26Ge¦Â{*vûCQü®¶{ŽÊ^l©˜",3j–‰¶d‘¶)ïb] ÎL¦ ŒU±»°>ÀªÏ.·Ô3Ù²·¸Ä0™‰m& Ë£°-ÄgD5ï‰9? g§ͤVßÏÚ³6ÌM_Ž„3,\ü¡3GdÒvÌÌUôìû=’f»bI•v™r±PŠ“˜Â¢NìDNïŠy¡±ÚA ëÎT9“3åÆFf)¿²K™ª‡O:ƒ,U©Rôe0»½-,æ¤L‘},)…6%cH„û¢ô¸ð›½b»»ä*BmI9qgú_~#[¡"ãì#BÀ0ϪQW8=8SìíbdîKsÁVhEŽ9_ˆeíY”zE'Ž¿Óq^§Å,œ.iKé/) À”ªIÄæ‚ÔG…kJ~гò¹„ÀZë¶TébxÇFB‰~°R™°e{Zæ ÑI@—$ÚåÁ^²ù™=M)8ƒè-ª”s,,!δžG422’ÆS PA&ÀßñºÝ¡Ä.ô•%%ˆêq´óQ‚Ô;k-=©ÀrU’.Ù²¾èIœ"ËÔ@h¼Ñ?8cÖ™p&x3Ò&_ílè‹3Ùd’öÑ•Doÿbg¯"¯ÐŽÇ]!äH8ç+S XlBú×£kˬrÜ Š÷+Ë;É‘"¶æ–§=dâûU4^ð©bµ"o×Y¬òî2Ý£üWIí"r/gQ¸lÎïÌz·Šv8 ¡6hå~ÌæÑ€±+µÄ&FÔ’Œ1ºBÑ®ˆxÅgd“"„š‹°ˆ«9Hɦ eØÝÉ1œ(~Ví“ýÕ9}¯V.ˆM¼0\Æé(Ç´µ[ Ç*FèäŽÈHÎy²áÙ9ÖBªá:cÌûÀ)±ÓL&IHB9+¢™ `Q¬žšpœ| ÑfÛ ãÉÙ®DTƒXLVŽc'QLör¢ å0u9¬vÐqÓH¿*Šì‰1ë²â}§>k™1ù`.¾+Ìøõ'G¤™‘ŽÚ#:èî3qWhqÎd¬Ý™œÎ 4˜|ºçÐ.4<<,MÝJÒþ¥¬‹¤3í‰ÑG’çl³£å7Ì!5ÎÐ^¤³†šÔV‚xÿJa*â"%&’¬Û²å/ª(9\׿S¢ !ì¤*H¤6 Cyé½YïÐéïµ¾ÊEA8¡vŒqaÐ!˜Gþ ‰N4¿R…öÒ¶0î›2!å‚ÓJ,UT¤ÊE§pŽU³ÅþbD—†€¶0>§ÅDEî!d)£}Ç‘—„&Ǿ´Ä±X©ùÉ ‰t,:ºmAKÚß&ÞŸ:É%g¹9ÑÐð0K×ïdYNªì… îæèŠcgJ®¬«¸\ºµ/^ò1=‹¡Íx”°_\`lÿÔ¥00•æš5h½pÓ$`Q¿[H±Ô‹-µ}œ>F"sÐ-EÑw§Iš€ëˆˆR#%AÇŽÅìw(Ûõö!f)–ò6ŒFøAU•°†×J&OŒÇ6Ä˵—6žºÃ$¯€[(ÚVþ`~-€2qæ@¤zÌó×òªY(&=™¥”ò aäÕ4H9ê²A)ì*ü'õDÎ/+8–$¡FöÞááa–å,Z±qL¹7Q:ð I”;XÛL™t*O¸‚}‹‚ ‹êfIYÂ{ŸËôbËFÊÕÛ]T \"Ó!á/Ó£(—ûP¦>”¨¤w:TY%ÞÇBKHÊñ(Ê‹4Z©÷2¸©$³8©TaéÊÆ©Ý×¢&hY¡”4RA<9ŠÔPpî C:¸­“‘ò”.vŽwÊ'˜ÕÝ·‰R42!c6r`D »PãˆåÒÄR rÈò4Q/+%ìÀ²ßMÃËI8l¿³ð’®i0m%ð‹r;#2~ Bø–B¨D‡Nc^⇆†f8àP\o$Ýác§õöŽò¼8ŨFº ¥´÷»M_ÅUGº¥©ˆ»äÝÐhŽâðÈppø^TË‹qþ²ßÂ’Þͨ”ûL[šç°[v‘•©îÈϵð_¬Ð)¹@J)þi›º‚ïƒÉ¦‘Õ½šU©¡ð¢'z4ÎdÍ5t+(­BRônFƒ3u|hãÍkª=fQˆÐWjT(Ssm–ž.¨GrðǩЕJE+`š*÷ëȰ¶³ùÉÖ³2Û\YËc‰Íˆù,‰#RðSí¤ ¤‘ζ^œêhĬ£ nQ"|fUÐUɘÐ"žªôFì’,Pˆ… )î¶$МF"”Ñ&fpbüI¼;ømLÕ(µ‹þî+±véBoíB”K]bSÒÐI 3¼IÁUÍ-Š'*´†pܶÊR¶):N’q¡—SS„Ò 0©%²äd1á 56Ľ²qWŸšnQI!”FŸœ$Á¥rÞ°ÑKO¥ÄQŸ””Hm$›Yáï,$§ÈˆX¡N=­$ÒMÉÏÛX±ôN gŒ(•A‘GžÌâŒÄÉŒ#{“ÕÇÚ¬Z¯ßFZ%eƒƒƒÜÑjjëuY×ÄÑ) ³è³–·[Ú“;[Ç»„E!íc5³Þ–JF706õ: ݃ѩ]Z¡C-,¬ê¿g/új••(Q9µ·ÝÜÚ„‚æx糿¥³’z BqÁÂòYžfNuZÅØ®ßÅEaÅS%‰ ¥&ë÷©³ÖšÓ\(zOòËÓW´aí¿N̺]?d!°·‹€ÜkCÄDå)òÏ”28Lm87¹6ØH¯’‘’ò4AöÇJ-Ë8”zª>4³Qf UÌ®¸f¬%ªœ–àVßc2xÆØ#ø³ÃTý=ýŽ> GMß7DÀذÃÑCMœµ¶ŒžÞP¹W.õáÜÅÿËú¶ V^*•¤:µÞA#ž–ÀçÎ,,v?[džŒ_B¦DƱ$!–üYD5((Ëât­Aad»%FGR‰||>´Øi$TI„X3[ˆE¦ˆÌQÏ££|¬ÊäV0ü‰Úl„™¤*T;…£y±‚H¦L¢8HTdç¥Î¦F1?…xM"ÇÄ £èŠITèX«6U!);¥%5ÃÂääI!Å2 'NœÑŠŽö›GAöñ”wïìÙ÷pf‡zs'ÿ‡FîÅŒŽÞY­Ïn›Â#÷Mâ?þ¯ ±v}®©Û¥¯v!Î]|7v_†j¹ÿ´PØûÕ£ÿÐç\¾£ Ø/[³ž =µ7Ÿéçÿ·UF/éÄÀCîpb+`“ÌåjÈÞ)^ÂR!„üŒ‡$!T{¥Ï8&”G¥"HZÔXãQ -#µ‚¾ØùÄî@ZÆFŠæ÷ÚlŽcxê%¼7ü˜˜y+~(•Zïm4SŒîB¹RÜõK{?ˆ³}=ÕsP*õ(d'ÑZh?£R -=¯dt$Â8GQ‰‚D7 ^}°Êº2Ú&¥ƒ¤ÿƒŽnkv‘8ªFP®–rü±üS™d!8ë»-N°QÈ•') ‘”$ÓÊãõ"zU ɘ&âr&’ÒHòÄÃ"š¢ƒÄþ¯d)TIY¥Ãö±}’ +Ãã³T3£M'w$‚Í?£ÂÏSqý·È IDAT¢#(!;/æïÀÀÀ)ÔÔ}ý³Í;¹¼Õ—ïà{:¾V!y`ÖWÓMabæ84r†&Ÿ ÇŽÄëı&ª5BÿâÊe ÙŒÕœí"ITÂY‹îŠ· «² %ª&ÛæTÊ¿æÖqs{MOOcbb"RÁH‡û¹ÐjW&Ĉ•Jµ®jÕÚXí_ãã㘞ž.’훽ÈN€†JµŠ…ý “Ìv3hðÄÜú³SÁƒü¤Q^<·%`ý‚Yõ+æÚMø@ÏVŽ:p|€í©L­ÚÖ¬„u†(QM¡ä°5QP:I* A½ükJ€ÚzmR Ö(DþAŠ3:…Ø5•^ªDö_­7;®cª~ÇOnÃÑÑûáxª-Ÿ¦TþÇÿ5‚µUqÝ–. ûK¨T;H'0P­,Å9‹~‹z®Cwu¹è"R… ±"£ ,KI{å,ÇJÕ{l‰nëP .`€.;žÛûô#LMOQN9‚•êm$Ãm«år}½½X²x1V­^óÎ;«×¬Aoo/õ÷£»«Ë# ÍÿNX9Ú˜›òÔîûçbûsÛÑh4ü¢+ÒшÉR¤D~~Ÿõz­»_ûú×ÐUës®uáÉ—pdô~%C~&zDU\´â÷@TJdÿ÷Ç,v#id,N$ý+Xp“•¨7à%;† äI±d|Ö'¶¬S ´dN©woM° ’[ £±fü”ÞÌàL6d'¿ ÝÁ6kb8„…¼¥×fjEYø¿B—ûL×bxrþÓÃ"XÜf`ðáOö`á¢þõ¡I¼õjŸþõ>¬¿¢ê·…˜“€zsï þ7,ìºg-úújëQËve6J'_K´2©ð‚öÛPT «^Á"Ô \·%Ňï½w[·m͉÷çÕÝÝ+¯¼7Þx#®¹újœuöÙX¼xqv§f£q`c›ú4ç¾×^ [·n}ßža`à8¾òÕ¯¢VƒVîa`ª~ÃϦ‰¦§½Öµæó:þßA()£íh®Â(6ü[ñöE¢’Í*éÝñl¸ u†mB‰u*yŸj#cTr'*tC2%>\”†w…ä>™1b–j 8æˆVK0D`ί›5f4!ŽWˆÝŽ|aµßYÀAÓÛʉ ÝhŒalf7ŽŒýcS»üħYÒÌ„Fƒ±ñº†N8¼µ»ŽÝ/Í`ÓæÎßPEWOgОÁ›Þ=ÇþËû>Ž• oCOõ<”K½‰r²”[ÃyÕNë8•™&[ÌÉ7…øŸ#„b}"”J%tuu¡Ñh T*¡··wÖv*n¿V1z£ÑÀÌÌŒ_ܧ¦¦°}ûvlß¾µZ 7ß|3>ñ‰Oà²Ë/âE‹Ap1y7&PIlUM,H¥RFµZE½^G¹\F¥R9c ]£ÑÀ‚ ¢yz­$Ï ªDqïS}µÂ• ‚jÐ=Y°=-©ˆzø{˜OÔCÈ%Óý'¿µ¾·,´/±ŽåɱîâS¾Ä ÂòV‰µ'c´ºrR}ÇêûS!@‹w&JhŸÅm Ñ0.B–H“ µ0S¾€©%Ä tZžášÓŸy ÇÇŠ“†£2uά*• ͰdY [>уs.¨àª»Ð»€fÝA%Ò3D0¾ƒOcõÂ;°´w zjçdÇ‘päÖ.S0ÎUFa9vûˆ Å•V:À+W7Švê%K–à®»îB­Vë †—^ìfê3˜89ŽÁ¡!?~£££Æàà êõ:fffðàƒâ‘GÁí·ßŽÏ~ö³¸äâKP®”#Jˆr¬“VŠ*‘Ų׺uëpýõ×£\.Ÿ‘Å®Ùlâì³Ïn- œHìH[9 ý=W¢L½Ægg…Ê(ÿ6•èB@°IP")Åáä2dÚÛ6*ÏcE¤?2îÌÖ$à ú™8ñU¼¸$µ¤SdX,7Á&9âʳ9ƒEÈK=€*ÈÑ«øXßë¬ &9œ"LFåÁJò%‹£p¬”û 3©¥\`rræ N=‹cc?A£9{Øv0QKeÂÐ@#ƒÍ&p¾‚©IÆ/^¯c͹tuÏ}·v<‰÷F¿‹Á‰'°záXÔs%º*«á7eòKd‘®ˆMq^-C0€vì"®¦Ë³ŸìDE ƒr†X¼x1¾ò•¯ :1&ŠÊä¤Y6‰:ŒãÇŽãµ×^Ë/¾ˆWwïÆwßÅÈÈšÍ&î¿ÿ~ìØ±wß}7n¾å,è[9×G›œcSHë»\}õÕøÝo~ÓSCk ’QP‹AÉ3YP!§w¸vomÎ]ôe”K½i¾=™E|€-ç"+4K‘û°&pˆìU F”"ÅóD$fkáªq‡ÀlP¡/u8vq]ðe]Ø+e[B ’ðþ„ JÍ31ö•ZöÊXžH…e‘³:“n\Ùf”RÇUaI–ñ8Öô ªÄÓÍ£܉cc`¼þ‹à®4Ç€I+ƒìxrC½}ä•p+Uàð&>z[ÎßPi»kÓ›jÀ;Cÿ‹'®ÃŠ…·bAíÒ?ãš}ÿ§(“tY@.+TgÃx–‡¶Ü“Á¦œs˜˜˜@oOö#–1*S&¡‰ gµbÅ ÜtÓM¸é¦›02:ŠÇ{o{¯½þÆÇÇqèÐ!üùŸÿ9öí߇߸õßÀŠ+"…epBŠ¥Èª~ÕuÌLO£V«™c^àæ¨° w$qЋ#ðlâ.d27Ñp“(QdFJ§I‘sIÍiØuHÅçD¡½Š{Éø&¤«QpHh±–ó$ãT’Ú®Ål…=åF¦£l«K¤ ]픵'1A.­aeƒŠ-Í05ÐY°ÑsµraAÍùŠRžVhNîRzwŽ9GþúÄJ̰áNblêeœߊáÉí!»saç€l¨àºu£o!¡TŽqxòáIÔëÜzOéÔÏ$`dúŒL¿ˆå}ŸÀò¾¢·ºåRM¦'Zñ/Kmwá•Á«"ð`Ä Õ¯R€’„ |sô›“ðÛ: T©¤óM½cà_‹úûñù;?[n¾?üá}xàpàÀÔëu|ï»ßÃÈð¾ñ¯cÕªÕ…5MlPCaj<IEBÀVrñ fS¹81·Øˆ‘*C†¸Ãä ÎD*4«ëáE_…N‰ftœ°ˆ‹ÅRž‰Þ&…ŽÂ‚ÉÉ@JëÖcië Û×±>ò1PñÚSÌ^Ÿ*F@±|‹Õ"KEBÁVs4'Aï0¢ñJ:ÝOŒH‚(%iC*F˜¯üš,ÓØÆ¿Õ9ŒÍ¼Š¡‰§10ñ˜g4'åºVppÕ ]xìþ ¬:«ŒÅËÊ89êðê 3`´ŽµÕ*Á9>å ~8æãcdr;V,¸Kºo@Oí‚pÿdn¢`ÛSSYë°IUŒ—,ÂÌFÄ-«˜Š°ÂH)q¢@w¬‚þþEøò—¿Œ7â[û-¼øÒ‹`f<øàƒ€ßþí߯Š+4)–MÉ‘ÑPŒçG"ü~ŠÞü_Ciš?ªÛ½bá0bV>«ÚvÄ *)»¥ð„`&iÞ[±?)ü!“v)Áã?«$£$5ýÊ$©HµE´2µØûŒ¬ÊÇŠ:òe™–ŒoÄ´6Ó¨‹£Hj¿id¥³{ÎÙÅÜiñµhÇÍådzã„r„Ï:ÚúȰ)¹qfLÎìÃðÔv Œÿ3Í£g”Z@DpMÆšó*Xº¼Œr™0|Âáл Ôg—_SCWµ•S¿VÞ^3n‡F¿ƒáÉíXÞ÷ ,ê¾]••"kЭÝÈÔ‘"—_§€¾ý(û¹“œ=K…"“› 4¢ã:¡¥B4•ýûÚk¯ÅŠ+ðßÿûÿ‹'žxÍf>ø úúúðŸÿóo¡¿`PHZz¸@>k<Ç2æËIºL›Ê9àRæÔu’ÒçÅG>ömÉêªØV!(os˜\kŸ´‘Ô⬔p8Å0_å ËÐX~Ü~ÍÆè*›·¡ Õ®-d§¤=*S’Ü…ô"”\06H:®FfD5ë>3C±òoàsA•I%©K,â,Ò‰Üú‘ˆ(òLãF¦žÇàäã89ýZç"{§x”mýŸ±hi‹Â06ÜJX ½ÔÚ)fÚZ_6>ó&êoaq÷XÚóôwoB¹´0 +%‡$€zZ‚( B¤ŽžÅ":.,…> Ë|ü‘Çäþ(HÀ{Ú”èdfÆy瞇ÿíw¿ ¢¶mÛøÑ~„5kÖà®ÏÕjMa+xà7OÃ!etDrá6ZFÒJ +ÉeD0d¶‘㊠ƒ:DW,Â&qâ±hg-H+…(Šú$æçȬ¢äÓHgI ±®ÈÕW•ßY©zÃUg;Yf˜_K”éU8á’É4N7sñ¦ÃÈL„S›uÁ=°4ìIíq™S ƒ\ÎM`¬þÆžÂÐä3­1ªÔUÎð‹Ó“->b¥J8~¸ýo5ÑtÀÔ$£é€òûpY¹™ M>ƒÑ©—±|ÁMX¾p zJƒQ5ñYNÆ’"ãccÃá .ºNŽŽÌ"å'bŽÍÉS¿[³z5¾þõ¯ãäÉ“xî¹çZ1¼ï}kמ‡~ðWdd#š°Ä%âŽ:9çÔñ;Zœì\â¢ôɇ“a+6sËP££~Lsõcq‰rQ\ÒôQhËâbH&¹7šåÁ $=Rµ‹q·”÷¤tì¶ +èaß!é¥[;³ú¾ÈÉLÙWjßÊ”»=sÊ¥^¸r9‡·ßyÛw~#ÓO£\vþ³ïÇBÇ̨V=¯ÔÑ¿¨„þÅ%,\\ÆšóʸìªÞÙSÇÔƒJ8%Úìi‹€’KÕ xoûxcÏåwª¼nãPªž@¬È¬«XN]ŠŽX{Ÿ²©Øþ³!Í2‹c²t¬’¾³­ßwîyøÊW¾‚u^8~ü8î½÷ŸpèÐ{*¸n«˜9IgÓ~³œH°ÓâÞØÃ<Ö„kœ^r¢]¢R%P xcW÷Ýs?¼gö¾¹ß˜ÿ‹F±1±êgÄå}ÌQl…ÉrÑãØðXN0D ˜ÞøÄüѱõÙÖøÙ´iîºë.ô÷·ä²¶oߎŸýìq_¡¾“9M,Ý©1.Ýå8²W“lG >TMvr|ÄeÇv¸Ñ4ÙvfÓ!zP13Ê¥2uã•gWà¥'VaÏ‹Ë09^AµÖL³Ø”+À/Þ¨£q «Ï)£ÖEèê!LO3öîžÁ¥WÖ°ç•LŒ³‘–:½ë@¹L—¯þq÷þͶþË$Õjé4{ž âhá€]„XO0=ÈÛP)"KSTâDXò¼áì¢ë8€üê'~[¶|Èóý÷ß_üâq2€õ‚”:Ææ¥–ìXx³EI¾ LžV{ºDÒ"EÈu i¦"¶{å‰KÏ(6‹±¹&[دëxá‹v]µÃjПqfžÇ2ġѫ„†á«+68ªÔ©„‚…<’âS‘`Jb°Øne9NŒÕu Rú„2’ÂúZX_TÍ%Ô±Åd{NÛ‘ý 0x´ÇÞëŹáìuc¨Tš òÔ•ÓAuå2ðæ«­ÅîÄ1‡ƒoOaxÐáÝ·8øN7|¤‡616êз°tÚÔ€P*µˆÌ£#ŒçŸ˜Â‹ÏLcïî:ê3­#u¹’'$´ÖHìædÊw§%–ÿIÔ”MÜ6Öªë–ubŒMí"#r3ÎÆBWW7n½õ6¼úênìß¿À3Ï<ƒóÏ?]]]‘GPÊN×[ËăYÒ»¢8Ù•Q¹&ÄVÔdÿ)ÔLqFN·QHDÚ8(õ•œ7NIê«|˜a½’9ÂÚ#³‘õƒ‚’ôØPXŒ%Åß\%GC¹KAÈKwœ¬u/ÅÂÀDãû¨›Dâ…T!¹/9IÚB.‚…Û’ˆçuÄBDe–eBAª§T3%ìcNîÁу½X{ñ(V;vŒf³tJ™Rf \ÞÛ×DOáà; <õØÆFNŽ8Œ84›Œ±‡ÞÞ‹·^«cñÒº{J±”RÇGÖ’kÔ矚ÆóONã—g0<èP«Õ™…Q' ¼(&B ¡¯²@\'ͦZ‚Óšˆùɦ´”ñYM€ƒIËñsÀ2¤œ <‘#aäT^®ºê*Üpà x÷ÝwÁÌxì±Ç°eˬ[w¡"sN®Mº`ç„Ù\„ÔéyK”Õ»ë•Ù?)­$—Ñ~Mö’ R/DÄFg¤¾ÔbGqŸâ.ÈÙ+j].‘‡œióD… Iú‹1å~Î2¢ìû]©œêÄBVK©™pM€2aŠŠ$•æƒÖê2+þœTe`• ©ô‘ÖÓ.A¬6eäCI(NùŽ“P+ÖòD’‘r0, b”­â­——àÄ‘œ}ÁI¬½dKVL¡Q/Á¹¹¢„íÛ·cÿþýØ·o^ãu\pÁ R¢]’É èil‹ÚY›¨+ÔFÁY=Ÿ$ìò,?‘I#‰¨‰ãM%ÁD›%$Û<ƒY %k$ªÙn©‚ Í’=ÉáTaKO}_‘ví ¶g éh²Ú,ÄÈVP(ÒëŠyV ¾äË0Žqà :'xuaçQEh\pÀöAi¤¢ýÎ-vf%&ê¤#ä-  rëvct° Ç÷âÜu£X{ñºûhÔKmKe‰£-s‰Ã8v¸r‘ {¹JxfÛ6m®aßÞ:úúK¨Õf§Áø k‰P­Ç;<õè$^~~ïþ¢æ–ßE;„èr .ÍOTUCz×e‰¦óqàœÉ÷ø»DnÌeSRÅÛe=ÇñdÉ!‚âzDéÏŒN-$¾ÌBuõ5×`Æ Ø¿?`Çs;pÃæÍX¶l¹ð¨mSèÅÓ²©è$§M”9:VDJ´8û¼¶ã ‰‰¨,ÏrŒ9/CP²†ôÃ0jEÕþ“R™w›N´¨Õ*å§=Ç JpHÈeÀEéšNÈ8YŒ d\&á伨'!I¦×¯Š¯O#‘–eí>Ï&#ÞyYRÔ[Kö¼.¥”‰Y_¥o$ëpƒxxRŒl–ÎgK¨ò¶¾©E‹£T"¸&áèþ^ ïÂу½8ÿ’Qœ½n %rpÍRÛň™ÑU+áµ—fÐÕÝR<9~¸‰R‚LW.·¹µ»ž›Á†Ëkèê*Ÿ”ÏF„j˜žb<ùÈžjûÞ¬cr‚Q©v.?%]À”Ý'ôb]mq7ØhqA`݈­Ê*j^hâz染¥|²x2+šÈ~lܸÏ=÷FFF°cÇ œÀ²eËõxS$¼4Ï.&é‘|•›v8eŠZk/^áùbdbp¬¼^ %™r*)‰æ‰Ý¬m¬C,VÛŠÆóX fˆ‚|‰y9Á5ñv"]þÅÆW82áñüPjÂe wæV¤b*ð¨øU.¸’«)諚RΔ|²Ž 0+ñ¨‚G§5põ×'KT5%aN3’fg§å\"LO–q`o?†Žõàð¾>\xÅ0Vœ5f³פd<¯T"Œ9LŒ3NŽ8?âÐl )Áž×&¾²cKV”pp_]V-4âafT*„R…°óéiüü§“x{Oƒ•ŠŽËu°Ò©Iæ]KR+/R]äDÏ*ý®h‰µé ëC)ôÚf[’š}‰u&R¬O„M›6bõêÕÁÈÈ<ˆ _¬æ@¹âb®4K^ ù’KB1¿:à?'$à­üBQ†šE{B¤O©Ñä€À%É|.»Î:D™XøAHÖg‹,3J)&\)цˆ«IeIùѲ‘ åÔñœM¯5ÆRgôDÌCúPB9„¬«<âì^ÂÄ…Ì´1Eb— åC Ä^Ÿ,%€Œ]„è¡QGÉÔnÑËw¡“ÃU¼=¶¸Ï[wë.Æ‚%ÓhÌÄGÛR8ðN‹–”0=é04ÐÄÌ4£ÑH_Ø5}{ëøØ§û±ûÅœ·®‚³ØåºxÝ]%¼ófÛ~2‰7_©ã衈€ZmŽ ›åVêÔ^Ô§÷ó£yg9RØ,6(Bšc'ߘi‘ yåQá»Lȉ`6ÁÐ>^xV®\‰={ööî݋͛7cÁÂ…ÂË5]ˆ¯ ¹V” ž$í£+ï‹Mi\.È!„RÓ½ÆZ Oz_PøÞ€AL)ž}G_+d ®¹@’M–’ÁU~ùdí ¡ŽÖÆ[«5iÙ_¹Zÿ”ÑÉ+¥b˜‚[7çÄñ «6n“Fb±Žq¤N/oÈ %-â¤Åù0é½ 8xÔéBm©ÜHCǺqr¤†c{qþ%#X{ɪµ4Uex°‰õ—×°teGßk¢H®®é€õ—WÁ 4éØ\W7atˆñ“ïc×öi>ÐD£Î(—qjt•œ#E¶<Äß8QÊÆËg‹³)ìõDëJý7kZNˆK•¸g"ëÈdKÈBÌQf“Ï9ç”Ëe4›M¼ýöÛÇ‚ ’„wµÔ¸´þi<¤Û¸3˺U)q¯— +¤ˆY0„›Ta»tG噋{ +âÁÑóô÷D¾¶„ìÉ ‘Øsõ†œÖ¥ÏÊ^IáPÝ‚%´òŠáŠŒü4C$(†ñ_•mâûH‰ð+‘ÖYÅ"¥ÓšŠAJ£&?·Å¦@”¤0ǹΠLšæ"Ÿa U¸ˆãÎiæ{D;Lp[¶vJŽFnR,Žƒ›Fr*v½ÒFv‡4cœæ,©¨*Ì„©É ½½CǺ±æü“¸øêA,^>FƒP©.ÙXÚsËh6fáée±j°tE ¥RKܳÖ]Â+;f°õÇØÿVÃ-‰ôJåL••¥Hª)rpš j3öLéê AS2N&¾\à(Ç|·t‘}ë³È›’¸,èµjÕ*ôõõahhÇŽÃäÔTrŒË×°mÛ¶3æAÁÌX´h6nܘùP"°¸~½9€Ñéí¨”ú£L7ͱÇɃ€2֮ˌ}¬X«èéø%§×‰èT€˜TÎÅúb Å# Çã1­æ³±¬¸jlí5…LMˆ™˜¨Ø©`BmJX]Y®’zPéL¯‰B$°Xþ8Ê ‚t†6ð·`2>ñryj/Ï­â×càP‹¼nÓ zz›èî%ôôUæ¶ôp‹wøÝ&þçq¼¾k'޹VÌ®œIÿPI0ÕÎmÐl2ÒMW’¹ø”ã«>v…ªRœ FjC0Bšd¢BlÙûB´RÆ’ƒ#W –,YŒîžnÀÌÌ ¦g¦EyuˆKÊ'yå•WB‰Ùx5›M\vÙe¸ø’KP.W‚8ªðXÎïf²ñ6¦Ç„q}6:¢.lXru°RÙm2\RòMñ*AâHNÆÊÖ£DQ”ALÚzQBx›`s¢”ë†Ôï4EUÒaò½l%f=á”ãtœE„œÂ…”, Ò;z<ŽE©,]² )Fªl“t§ýÊây¸&ad  ¯.Ãá}}XåιhTrpÍö¥g9įրéIÆ¿;íOaàHõ:g +θP€ fª Šú!²r(ŠéíÜrK¦¢Ëp’)`‘„rEà8£õŒ­×Â…ý-cêì5~r<"§[M¹©©)LMMÑ;ñÚbÚIM9cc·Õ?%Cq‰%³¸K#êZ.ü]QÔ^“¬`0Ò°HÜG‚…?ßæÄÐÄä„+\ärÕééiôõõÂ"hë,åŽ|I8²½ ±×¡ã̉|l­VCww÷Cõzýýý(›Ï©ø BD]"žyšã—%ª©À˜ïG eeLºÄd"´S éàY,ª*3±@FF×^ŽEy™8¥Å®p¤Žµ$¬V‰µàhJ”š#OXÀ´gîÈ ÈzI$Š’£ò-UÊ%$£­φF,µ¡L°ÌŸæñ£\*áÊMWჿòA,Y²`Æðð0ž}öìzùeLŒï½½‡{pÞ†Q\rÍ ôö×}Ö¶%F@èê)aïî„d™,‚(—Ë(•ƒÃQ£QGÓ5Q)• ã`7Ýtî¾ûnT«ÕÈ[µˆjeÿa£Õµj]]=Ùb6új±¢ç.TËK³Ú]3½¾Î³nxD-£ì¼¶]$­HÈãG¥~lÇFJ*Ÿíô "ú“Î|ÛAëÒV£“5û-êIŠM¢H7ïGADf6ßXó³5ÒdQ6BÞ8^˜šeÄ_Jr¿B¥…ð:—›r¸g‰y7ò˧µ¯^µ·ß~;Âc>ŠãÇ,[¶[¶|×\{|ð'8x𠜫᭗—àо>l¸j\6‚JÕ¡R)apÀ៾5ÏLcdÈÁ9ȯýîý¹Ï}ûØÇpÙe—á¹çžC¹\ÎÊÇZÊ)«W¯Æ5×\ƒŸýìg˜žžŽNê,I  (&c¢ý„ô·­‰9±æ9Eg_zDÒš1;êûÒA›é"½´hÃÊøï2ë'« (pD¦ÎÎ'Õ}L}aooV¯^…r¹’<Èè`šÈ@šf`4D º€^¤A%êBµ¼ ÕÒbØ-&]/BÞ{i;K‘á@è  2Kº^ZlH)© ¹ƒó\^mÂãÌZARu6ä]Yð<óÅ™X„à„ô; “l¯  âv k¤|\=Ã8û¨x ÙH·‡ÏÒÿQs€8äŽå¬ iÉxÉ’ÿ•ÎS÷Dl4X³f nþø-8pð ügX³f >ðö¼ù¾÷½ï`Ë–ãcû8~ö³mxï½÷T06Ô…O®Â7áâkãÍ׆ðÄÃ8ÒT´”ÙŽ(ÍfÍf+W®D¥RÁõ×_åË—czzÀ¾}ûÐÝÝ?ú£?Â>ð|ûÛ߯Ÿþ韢¯¯¯8æ&¹ ‘¥cª ÑsŒö9)*Α±ërS&¨)^ qØr¥`§ÇVþ' t7 ¿¹@9×ü2ü<ËÊo4ZB¯Cn1u-œ¡ù$ á‘*”o“}»¤ß*±­na¶a*(Ü—RH"!Ö42ÒÁ0¥[Â\ çĆ7G 9†S]Øìòd…ä’1û IQ„_¤Rkq­°ÜŒˆ}j—„¡ˆ^ñœ0´Éˆ‹~P·/[JFEBf¼dq¹„¬”NÈÄe gþKa€P¸Þò¦ÎZŒ—™QëêÂÅ_ãÉ'ŸÀm·Þ†[o½ÝSšÍ&{ìüËOþ·Ýz;6^± ÇŽƒs­k7%œ8Ò‡‡ÿq oî9†Ñ‘Fá"×l¶Dr¤ÆÌ˜™™Á¥—^ŠÏ~ö³¸à‚ ÀÌX¶lvìØ¾¾>lÞ¼Ÿþô§}\‰ˆðæ›oP%RÁR®cþÈ¢™ý²ÆïòNl$¾‰Ì‘M 58=‚•·<òn!pîXnØ&ž˜ÿnjj Fhÿ®®n”ü‚—Ǭ]‚U̪Ð>¯|È%Œ\cCN{"3âÓ‡QCŠ•*h+¿‡vY£3epNBq…,r&ƒVÖ'Èæê‘*%¤Û ˆæL9“¹$4qç“h1ç–ê ÙÚBÖ¢{qYK"( 3"qˆ2 D6Åf-í˜XŒHu' B”¹Ì QD˜ËË9‡sV¯ÆšÕkðä“OàÚk®Åw~>Z¤n¿ýÓÄöíÏbóæÍX»ö|¼õÖÞ*p3S„™éÖŽUJ”U4›M¬[·ýýýصkfffÐßßßû½ßÃÀÀ¾õ­oáºë®ÃYg…]»va×®](—Ëþ([­Vñ‰O|7Þx#^zé¥ìÚE9Q®}PÂ"ÈJÆž„dÊk8ËFñ>ãdÐ!’2E™ºÈ&Ó¹M<É«òï>9~333þÓ} úb#JE‹Y€q1.bV%Šz”`*+r2%¸jY¼™ÄÑ.¿–4•˼¤± þkù)#¢fúXêG†ÒM"—“J&ä ×Ò©0ŠùK÷0¨Z1•0åH@O)ê+)×ù‡*ùÆ‚ßÂ&jcSáäEóÝúÜÕÅ!òºL¨+f¿qæë ô®”„¨JÖXý-Dq@DjsYìúö£§·£££¸êêk‚Å ÈÆ–J%lܸ ;wí¨„åË—ãÍ7÷@­Ú>Ëš¾NOOþþïÿgŸ}6~ÿ÷Ë–-ÃÒ¥KqÏ=÷àðáè×ëQfVþY«Õpà 7ࡇÂg>óüÅ_üE´àqܦˆ[yŒðÙ, œPJ1ö°¥•åB!íA¬]œ2MÆôô”@v5ç4åÜ!‹ &iWñ}†ÅÇ!–C2eXdÚ‰ À¸Qø`QÁ"SZ6-íGµë£X"`Ë5¥}Ò$ ÂÖ–«)=CÎ7ºpâs$l2ÚÏbÿΞ YA]- —ec•!6ÙB^,,‘™¡ Ëô¾$÷ÁJÖÆ5dbdv%VHR'G”«¼T–~µR Kn§Ã³#;F­ZÃ’ÅKGNþ½¿¿µZ—ÏúÍí„©©) añâŨ×ë¸ï¾ûpâÄ Ôëugžy›7oÆóÏ?ï3£«« ›6mÂË/¿Œ5kÖàèѣشiöìÙ£’,ºÌ.>00€‰‰IÀòåËÑÕÕmÔXÒy,Þ$E*µTn0ÔMDM™Ò,­B¢é"J^Š­€mHÄ(™6“&"•Hàp¥À y~%&,â”Dš#( Ú¸:Ä !*o \FÝ}ŸèD£Dµv½‘Ï[’y³^[r2j3Q¥¦3)k¶†v‚ÏÍ48òîa¤=3¥|¸ËRiÁW‡œ8 TÂÁÚ,£8›Ó3Ó-|ÛÉñqÌÌLgHÃÍy±›žžÆîÝ»ñÒK/áá‡Æ‘#G¼Vþ:x𠘇R(¯§§ùÈGpÿý÷c||Ï<ó >ó™Ï`zz:Í´“ÎR~óu‘­!„]RäÌ1ŸŽÛpû4…H‹ Àºƒ)×»”W‚±è”ã,û‘C??ôÞ!ŒV¯^îînáÓ“´Ó‰æG„êØXAZ?mZ“߯Óîjq­T‚d«|RV.pìsjœäOàØÖž"Nô¿K¬ªž;3bN9%p Þî¤Oç3CJákk×ð r¬”Xy·Â˱³ý,ér¦;mkbYx? eݦÂJÊÕŠ³Æóq¤©ŠÙí÷m¼cqj<;"ÂØÉ1LNL¢¯·/¿²+d¤ógÎv÷7^ Õj Ì-†<•:6›M¬_¿¾5ù˜qùå—ûï%¢èè,ï¡«« ×]wžyæÿ»¡¡!ìß¿×^{­ ÈCnR’¡<>ƒ·önTÚ5.ŒNåbÍÆr¾ßƒ|5ÄÚµkÑÓÓ«í ¥wqbÉŽî?»bIåîzj”ËÔu|ø¦›ðÔÏŽ| Z„û飨ºm+n¸áLMOá}o£Rî¼>¶^¯ãK_ú~øa|ûÛ߯wÜQ˜`°‰†îînÜtÓMxà<™xpp/¼ð>õ©O©€¼EWz3à´³šíˆíö˜ ‰'jwsÖ"›•ù¶“Å|‘´¡³³³BÙÿOœÀ±cÇüÏ×­[‡… D¶ðÅF…˜ÅJÛ™&&²õÀ…ú8&¾z sBÝq†˜ôqR·£µQ• \¸¼§kï`°<½™S£@ ÀŒÎN Üß[yzŒ@o›FVVU =‘èÐ$P¢%vYR’ß:ýÝÉBW«Õpýõ›q÷oþ§,[lÚ´ O>õ$.¹ä¬[·?ú0~òÀ¿€ˆ°jåJ|õË_EwO~ü/?Æ»ïîGµZíAÖëu|á _À_þå_â /Ä¢E‹ðƒüüÇŒ;wú¸]jÁ[¼x1¾ùÍoâ¼óÎóü¼J¥‚o|〉‰ |ÿûßG\FT†•*‹ìãÆ–Ýs‘ÆSBìQËñÛr«„ñ‹T‹eQ‚FF:i×®—qäÈ-?Š¥K—¦ËSâ2äBÚ,lÕ²9!1õMY§#Ëö°Â‰8a”ʰoª=¥•veWÈÛ^œälŠÁf{Û:Œ©:Å/j#æxC€7ÉŽLšÏ–#YØÜYFzà\ÙÐJ Ä5ªÓ)w¹k“O5‡ŒGDEV‚žÐÃŒÈÔD¹ͲÈÀ‚ ñÉO~ ÿáöÿ 2­Ë–-G¹TÂÿó—ÿ7®¿îzÜùÙ;±|Å €ƒƒƒøùÓ?ÇË/ïB½^ïx¡ËQݵ×^‹½{÷b||\ÅNž}öYÜpà xê©§üÏó,oN„=~ü8î¸ã|ñ‹_įþê¯â‚ .@oo/FFFðꫯâ?øyäôööŠÊ#“#xv$â5DºœÇ‹Dx> ¡…›Š 2ÊØJò[Ü¢âÍ‘*žW%d,Ë‹(;ÒY¤CGaïÞ½þ~®¹æ,[ºL O¢Í"jj‚ÉxÕ2’°—•ôcrPþ-!I(‰Ú–ì¡Ih(h¡\=sŒù? OV‡(A€I9/Óno&2òa(B Eü1C%£Ø<\RSˆXËòS(ù#ÊÅ;#>Škæ’úðf±N-b(rë–å[d$Á’2‰R‘¨,ÅAý[Hg…`2|ÇÖ•+Wâ×ý7p妫ü"GD¨×ëxñÅðø¿>ŽJ¥‚»vâÅ—^ŒxvùŸs©ÎpÎá _øþæoþÐÓÓƒ®®.,\¸>ú(þìÏþ Û·o÷»Ûn» D„[n¹[·nE¹\ÆÔÔþöoÿý×­³Q¥Êå2jµZb£%å9šÊüi$(}áutTH%³ ‰ãZ\»0HÿQQJeÿmD'ÿïÓ?o¿ývÆ­ëÂÆÑÕÓ’4d'íå©>ò‹El¾STl¯JâP&VLôN†°,2âAR–-Ò'ƒèÅØ­(/@™£`äÖZ=³2+³ŒõqøÑõ”šËÃÂå~—H=ÉìTR¤S©} S ð’Õ.Q˜Î…»u©TÂE­Ç×¾ö5¬X¾RÇÆÆ°uëOñÃûþ9‰¬NçÕh4pýõ×cóæÍøøÇ?ŽR©„®®.fffP¯×ÑÓӃ믿O?ýt‹ñŸÕºöõõ©Å¶R©t#Ôe_¦î8Q¦*]¤”d™Û¨2·|c5‹)&Sj³Íwl‰8)öEæÊ8vì8¶oߎ‰‰ À–-[pÖYgµN1þ„4âDÉVTe‘û–›Cnê%|d9ð#äÀ.œ®vH%”<eRe|¾òɰì9ß /¬­bØHˆ„‰:)Ù/ÄÆV¾ Ož/'cv9kœDéYŠÖ¤8ÈT»Ô…)dL:('x/^„€¢Œ¥öOEGÈ¿„k¼Î<öun|íNùµ²›óÁt•…1åè6íoüáþ!ºººP©T< ©V«èííÅ‚ ð'ò'þHú™Ï|=ôžzê)LOO{³¤ÃØ×Â… ÑÛÛ#é¸u¶ûçÎì¡lË&‡È mÄ|8¸ýù0¢ó™¾ÅaÁ!hW›µîûü=/½¸O>ù„çÞ|óÍX¿~½¦IX9ò"ÓZ–(©Ev—ÒïÁR4°õƒ5iËÃ3„Ûc™¥¦$™Y;¦G.#w%ŸƒRï²Z²FV rZB½>‚±Ï(ÙÁÞ`-ëê‹5ÃŒLbÝ9ʳÎiÎßeèTe‰²?+J,0!‹M‰ÁkŠZL…«ÚTe!b¢Ë ·OEëØ‡]!=a“H-ÀÖ‹DÀ6JÕ—W^yzz{ñÔSO`hhõzÎ9¼óÎÛØºí§øèG>†©©)ìÜùþþžocllìŒ*Ô½òb~Éï[µjjµªÕ*®¹æ|ýë_Ç•W^éUQˆõW…¿û»¿Ã}÷݇£G¢Ùlb||<õìëëÃe—]†/}éK¸ä’K…òl—%²º‚Æ×UeB™"™tË¿Ò.îä')¥Ñ"I¡¥žH¨“@êÒ+!Éç¯ã¸ïG÷áÝwßô÷÷ãæ¼•˜PjÈZH6Š)$H¤´˜Ú˜e‰¥ dæ˜ôÈPGûx±¹¨q$?'˜“RX#-X}ÜõŠ,êÄÒgÜÒ”$—ôx ^ ®ÉÎ|‹1Ir€ŽÇû€ÅYæX=.%zŠŒg0eÝ)%’ä+¯HSAœ“Ö¥*FÆÉ± Œ&ý9Õê U­B`Œ»ÕqƒCÑ·2ɘØP¦~°á¢õXÑzlöY¼¸óŒcrrÿôO÷brb##Ãxèá‡P*•æ”U=S/¢–æÚ­·ÞŠ 6d,ÿœ8q>úhôÞ 6àþàpôèQìß¿=ô^ýuT*tuuaíÚópÇwâ#ùˆYû;-¶ª:ày'ÕERê ˆüBÅ—z—‰±ºŒuïL0ȧå@"ùØÓ…õ) ˜˜œÀw¿ó<÷Üsþ½wÜq.½ìR½@3+ëÐâêÂpD%Ö‘šdí¼´¹J¶x 'äí“Æ 9&Aú•RgÊo—Xª½ÝBäH&‘ûÔ²¢Aߨ0XXÚ1úø‹Ói-ʬïòÍ%R@ÕëQ¾^XÖŒæ3†J«ë²Â"¤“:ÖRzW.âÑjVäD.›!{%‚ªˆ ¤‰8Rbqnd^Ú›D6žõÙØÈ¾ßðqùÆ+ðÔ“O`ï[{qòäI|ç»ÿ॒μÉÍÜby÷Üs—Xït‘,—˨V«èêêÂêÕ«ñÑ~w}þ®–ç)säÈUð¯y¡!†® ÆA_’)Ë(›èÃÖ-='“Ú|‰¬ª¦“°å ùïãhjrßýîwððÃø÷Üpà ¸é¦›P«Ö Z"M•BÐgäD¬$ß#ª¬ˆlAªcHk6šõNÌ JˆB‡áO†êB‚¨„"3,é:I¶©%*¾J*~<^}+S¬€£¨,„¤(°Brz!A$j/xK•”CW”Þu6R`¹jÛ5d È”N%Ë9Áª<¸È_@yDØ0ÒC†XDÈÞ· o>ùÉ[±ñ½ƒøùÓOáðáØœšÂ¿ß2^]]]§ô¹å˗㪫®Â¿øÅVÆÑdVãè›X8r@•T¡á„¶y^.B{É èSYï,À…¤0¥hâÇÄ„‘Ñ|ÿûßÇý÷ßï©sÏ=wÝuV¯^-ÊeH%µu[þIB€ 'íˆÉù¿]AžLÐ|RÎZ:—hæ!#*[#H)-kÒK†8&ÌÇEãs’øæ)é£\˜»¾_àXcm…Þ48/85˜MNì'­*Z@H:v¼”šT!ÐG ]Ê%J¸”à¢XBPTXìÌ,ÒédŽŒ¬ H|NÜsd(š8ž©çkí`gu6îºëÁ«¯¼‚^|ƒƒ¹¬’Œqür¿úûûqÑEáÎ;ïÄÕW_#äè¤T†JaUå1!©¤ò£ ú’$Ÿgc9–ÿV;Y®¨IãÁù+8_YZS.Cõîwqï½÷bÛ¶mþúË–-×ïþ2.½ô2Of2Ál¡È+Fšã¤Ñr •^Â÷‚le…,[$Ç#k{OmÐ Ï^EÿÐá(’sA$|Œi›w³b¢ùu²F eJôá@§¤V%ñœd¬OŽ)(ï›@kcA*6T7’â ’ãÈJ»°/ž)†^않1ØBgŸKAw½“Zòjjóã42° ñV§0! :§üRpű~ýìØñ^ý5ŒŒŽÀ¹æÜí×ÿàÚµkqË-·àÖ[oVº„)&¯r ±È¢Få^q¡fá½ *ÌJ[Ä㉹ÐÏ LLŒãå—_Æ÷ï½oîÙã/¹téR|å+_Á¸ÒÉLý¨ÒÐ+’Cqû¦b*Ž\§1/ŒIý‰©8JËD'2äê½É{-/ž!Ãƨ\,ýʼnR¹¨$L yý&jÜ8qŒ¨è؈µ¨8gkØI2•L¬Ø!ÊI]~Y …"; Òäâ¥!·Aì8ÒÙÃи¤% ªœ)v~Y1b «VÇ~åC¸ä’KñÜŽíØ·ïœÿ¹ÏaAÿBƒ†¥TºØÝ¥}zÌZTVÁvizÄªí¡œÝÓ“„•§«&‰“" Ëçƒ9÷UÄ;'ÆOâÝñÄÿŠGyDi÷­Y³¿ù›¿‰-þp±©²ÑÀñB)”jŠM´·ƒæ-(C\t¾G‡qÈÔ#ëëJß\iMʼn¸%«ç Æ‹‡ÊdG Éâ2A°Ù¢jZ2êžê´(OŠyJ0BšŠI=ƒUžÈHõ‹ñTI Û#.#²‰í+tÐ` ˜»—Ý áõ§lXdBù:.ÕA\ï(ûgÙ²eøÔ'oÅÛoÿ/¾ô":„©é©_Š…nÅŠ¸âŠ+ðÙÏ~ëÖ­‹wH°iŸ¸ ?Uº'6máwê»!h(±Þ^¥\ñÇ$&ÄíÉR£Ø=>ÿ÷ɱ1ŒŒŽàÈá#x饗ðøãcxxXÑx.½ôRüÚ¯ý®¼òÊèºVTÀnêÚ¹,ÊÅFå±üEl©“HDÓc—#D©©ÉQoËÃÚ¥–Yª)§è-i„•³qbAV֢͂Ÿ/8±%¾‹S§ƒÄ ¢ÂB¢I¥uH"1 ¤SÒEB’íóyÂÇ5 'h$ f‰üE«µŠˆÕ^Ò&‚¥ž 7&ùL”Ö #ý<Ê5ÉÄ–.¸àBœ{îyxåÕW°ûµW1püx$†ùoõZ°`.¾øb|ò“ŸÄ>p£F)²Ð^¢.bå'*-©çEàBbN—ˆÁ¸¹«d‡xMOOcïÞ7Q­ÖBÜMmrýh©$áWêZª0SÓ“ŸI›ü IDATÂþ}ûñÆoà7ÞˆÔ —-[†o¼wÞqV®Z%Ž…d¨&H{âBsAí¼ø' ã¿êDû²•)×õ¡%'Š`¦Ñ¹vð¥s,bf¾ß„àAFã¡ÈÄGÇäý™UÌ9©/Éí–¹Cþ£$§Àµ¶hÁgdIÙ5³Z È:³¼^¶Ü ü4VNSbW‘»ŒÐµ·E½±í®Í,qÄù“WãÆšZ€­[±T*×f+7­”Ø=+• ®¾êj\´î"ìÜù"ö¾µƒƒƒÿf‹\¹\Æúõë±eË|êSŸRÎô !¨xW ñè¼MjN%é  uxŸÍÍ]öÅÀÀþËù¯§•ài6›˜˜˜P¥töµlÙ2lذÿØÇpÃ7¶‰R&HÉús VBJdr|41 µpŠÓŠT¬ ?X.\˜1ø\3ŒS ôN•Ô1i:k¢p5&ª¤ 3RÕV‚LŒ´3(u`ccÍJñÉ“tý®=m# ;õ§?g;„æ ãDŒNºµ ÕrÁ'²,P"zÒû52çØIаˆáQT㪠>¼@€3&A,ÊvX²æE´•)$ÕYÈňŽY°p!¶l¹ ëÖ­Ç˯ì2ñ¼÷'‹±víZ\síµ¸ý¶Û°båJíiMìïWR) -£Ë'“.é •'¬Êú´w¯v¦bÒ‹©rŸâj4™Yø™-Z´+W®Äyç­Åõ×_‡ë®¿Þ—ÒéÓ ´Y4IgRܳÎ9矣éØèÈé0N˜æ:Y¬ÏNI©9–'$hh$غ¡vܵ<#¤Q¢ q¨r¾LCr×$Á¤’$ÊÆ¾×¸øAX_B )vôÿµ÷nÑvUç™à÷¯³ÏE÷»„2 I!lš;–—¤â8Uc¸8‘ÔCê¥ê5©‡¼tQ£Ú•‡´“î\Fw¹*ñWÊÆ.§ŒSÆ1`[æ*$„$ BB:’Î9:gÏ¿ö^s~ÿÿÏuW»ÝÚ#Xçì³÷ZsÍËù.E”Õ”ðÅMT—tѩ†ËV’˜-ÔäÌC­ø+{|x^ýŒC)µÀ@n"¨‡ý Š1ú. íú•Σaݘ­žÂæZ‰c£!¥Á¢Ð‰æ¢‚º¸`€,÷»~Ãz¬»höï߇ÝÏ?ÇãÜì¹uÓ[³f5>þñëp÷ÝwcËæÍd¥TF-•ÏGtf¢3Ð4|_ó¥³Z Öƒ´m$ŒcõêÕ˜žžþP ; 7J/\¸K–,ÁêÕ«qÙ¦M¸úšáÒK/5ÁW7°ŠšÒY󾣃ג%K°fÍÌÌÌ`éÒ%»SC¿’ œ¢¤q.ž4cÅŠ¿JM`#XÈFd)D›Š$R€á‘ʪKÇ•¢{—m°„2 TDYá@œEI¥H,•{rµw{P9>ÎTÛõß®ïgŸ}6 ™ͤZ×gXïÅ%ŸŒ À¡Òyr>o¢!1ð°ÇhAîk<¶»gN¯ Tù¦PE¥.TB» NMOcÏžÝØ»÷Eyý5‹9åúa#xûØqìÛ»SSÝÁ‚ píµ×âŽ;îÄwÜn! A¼¾µÚ‘§z\íYÀâÆ¬N·+ÄÀ DáHÅÑ7Žâ¥ý/a®?÷!ltièâÅ‹±lÙ2¬^³ãcã„!”*Ì%•œí§ŸRþµÿ>9òúý>6l¸ýèÕ›î3µÕ­2Ξ5¥¢èë[˜I¡è£‡Õ•MiFËz €9‰å D\ ¿Øl™(RÿD(™;±\׿"ÔC¶šäîjÇs¤RÛØ”’µ´Ø:#šêÊe^gõ3Ï<«Q'¾ö`l3]¸Øí©XRÈÂR«?˜ @àLc+ÈŽº˜P8Љ–"«0TVdû9ÒA×ab “¹!&; Ž»÷ì¾}ûqâÄq‚Þ Ûùç±ÙmÞ¼7ß|3>ýéOcÉ’ÅAˆT¼Þ™—ý—x„Ö†\«÷+F[Öw*Å)ÏÔE€^xÊ_e¦Etyüšá&u-1ªµænžïÄX&×éI0%Ý0Wxì™ØÏ wñ œÀ¸¾oþ%båܹwçT‚Ä$ÀŠvÁçC°˜.nAš¡i®ZY,qœÕùö˜ÎCAÔ6=¨W5óSä™§ŸV–ñ-sãÎ’Ê8Ÿ,­Z ‘–u —X?ðQ¤T÷~ÇK”þñ!iå”8 ¨v5äüÞwøÕW°ç…=x饗05uö¼"»/·cÇlܸqÞ衆ëâûUYáÆêĪßw3«CÌ‚ŽãÅï©Gɶûk‹îïc¥VÌ\5 }ó%Œ!±¢¯¼%ŸêŒ'ô¾¸õü“¨ã§•ùj"¸ Gàd”ºîÕ?(ÿ³¬rµžœëÖ1Këû§ ŠøLR'$9¤:ÏËáïzðy˜û5éó²ó—K\*d•g¬RëlYà#㨠ýK‚MBvê´¶mî å–葸¹‰#í°ške€‚K6nĺµaãÆØ»÷E:t¨“Ì¿|ùrÜøÉqÛí·ãºë>NðOµãš¥P´íDn m¦õÓ¬(YˆëœsW—é;Ü¡#Я˜,ÀTHÂI‚;È‘J+µaKM,ƒ-+üPõµÛ„#!+/ßÏnt£6áû­E¤LeR1‡©ƒRd'±ŒÆ‘‹ÕÆ£É;ê¸Hîª3`ÚF`!’â1£@N€Ôá¥&†JÍw—a0‚"†TPöÔ3´ðO FM@ž~ú)¯€>µá<Šï]E$©ÇSjçCõTRsŠwÔŒ€ªÍÜ|ñgø¬î˜ÏÇ¿õt¿šœ<…ýû÷ã…^À›o½·Ç‹/îÃÜÜ>ñ‰p뭷ᦛn²óŒã{n}T°”ZÙÐ †ó…1ó_€­í F ï27Þõ;Îkú¹g÷>§ìùÌ£ê=Î÷FÊRº4QbV¿œÊv:ï ížÃ:ÿ3¯ÝÞùd@ïyülÙ§cóŸð²<‹Ÿ~ê)už?Ä7óZ˜(B&2+’*Dæ§ðHFâ}iGf}~5‚0 Sà(Pl+·E€½M½ ׄPî§Ms§×uõÄwŸPÿÜ£o¾…öãñÇÃääilß¾·Þr+V¬\ ¯úªôwpŸ'®6[(zœù¸â¼Z^¦à)ƒ85 ØäÐ}Žy6b@éì6å`s´š"}ç—¢Wá®y,ÆÛ¸ž”°…}Oª,ÞÈëf(Œ¦S(LsŠÚ¾¹ö /-vQ­Ç*uAÅ÷Ñ©3`Ðôü¼ORù•Ó‘ñJHð~¬…¨.âw~¼âë+÷MýµP/¶Q\‰Ì{ZpDGøNƒÿT' ‹÷6£{ê©§ôü·êwûõù¹>Ü×ûÿô÷ø—o?ߟRÂ/a||—lüÈ»tPm½ì|SýB»Ã©®3ý½D:ç{Iïú>)—ó½Õ2×,›¢;"û`Ñæžéδý9­žy¢I}ßIÂû|³½–Œ£y›³Û ²(çÏRIMÚ“ÒžöE]Å ¹‹HH•r[ìYéW¾Ä…ºtÌH¹üÌP…è;¬]ew‡[ãVêÆZDÚ½@ˆ_DP›FpÅWF.eÅ\\<TʧKÔõãð={—ª‘JÊ\™J$a¬K·U°ŠN}µê‹Üd`Ù.Ð)/BŠØ®SýIádøÅ4饢ÊÃ5.­X4ã+[på'XȳÛ,X„šgZºüE:^¼ùmž—9\öáºÐ `¦Éa:æÙÇW"žÕ×¼5BÆÀLåƒ"ß´ä¨ÍÒHóÔáî°'e¬:AWŸ¡ÒÊw ÉÇqM¬²Ÿ|òIíÆ5UÐ%5ß'ɇð=ò¡]ëÏáSçItc~Y^?Ï›ú9~v'éüºÿâ=¬êwýÚÿ“õCüŠ&X—qª5¤ŸXIj»7Kúã¨ù™ª"ðÙÝ ’œ”ˆÉ£ÓØðÁIZ«fßNæü©ù/ȯ|ÇÜ\/¿ò2ŽŸ8QhDÎÏwþ¼Yr±t´úxî]ÿMAo”1Ï>÷,æfg‹} ¬=eûý;wîÄw¿û÷xã#dÝWG¢ÛgWÆZÍcÓ0>jÞDŸF¶{Ù¾¯öüÕ^½Oc(¨{ÈóˆV… ôu Sú4ΤÇ0§Ç༠ÍXÚùë®-±%!›S«µ~ôwRU)ë‡-ƒêŒ1œnÇ-[C~f¦˜O_•4ªÍèôu¼ªÕ¬U²pÔ²øÕ¯iïï럣³f4ãퟫ÷Ü€SöÜ€ZókE‡‘xEAF‡¾± M¥x‚’µ–/Di±“×, ¡g¢–"æ(<ªvë0ôÖ°)X‡xöÌT­HO[öò,¿÷RQªŠsçfðÔ“OáµW_µ #Œm)¨«ëï{Òâ«)Öh™&™õdþ¯cæÜ¹ ”‹Ò)áÇ?þ1~ðƒ ¥>Μ9[ThҲѺœ`¨ÐdsÆ,¦4-p›Ÿß¾iE»çcçMKIâÍ’=IµÀQØ 6ìÐP$ô>‰)Ý  ¤3å·Cˆ2cÏYžò´¹ =÷œŠÁ~zÏâÖ‡W½ï)-þÍÁ¼1yQ<Ñ@EâJ8ý`ÏQ÷SãEJÔ-’â–2{š«Ýy ¹@Ö…ÌESOàN¥°Lꄺü·RQܾ‡=%çææ°ÿ~¬Zµ kÖ¬‰zz690 ݦi(åqmÐacdvv_¼ .¢Û´.oùÔô¶yÂ-PÓœó«êGjøwâ$ÊÜŠ¥’«P›¹+ÕU@1H#X ‘1J %Œ»òŒI¸Õq ¶ AÙS*å ×Äq0. Nwpð¡ùÏJÓ-¸NÝ[-‘"8þ°j‰Xc*Š@½œ¦bf¹TdÓBEÉHi3P£¢¢!` ¡N-…‡hâ·5I+7q¸Jµ.(€ämÚ”,Á†ÍÉ•x8í©*Ÿÿ‘”ëQ=0N?8kJn°ƒÂÍsM))ל¨œ1”ßÙûâ^|ë¡o…M„¾‚Ò’ÁïΜ9ƒø‡À®]»çfgñÔSOáÈ‘#¨dzæ ³GfUøßÕMm¨ýÓÖ5’«htlZ(%"¯êŒPiKA&™´5ÖvŽ9‚¯=øµ‹„7Ï͆Y1G}̵_º–òU©²)¥°¿h1XÍÕãÁw'x_ŒX›¦ºgBEv;9•gֵܯKëÑÊG%®­¶ïMÃñ*©©ÿ¢Äg e õ,[³ìBo¤ª°q[FH¶ªj^“ õ95¼­|=ÉÏ4mÇ‘Êi‰žWY“‘pµãžqýBp‹3GŽ’ÜK$b³Ï¬5÷Uq’6†VãÏiA´õ‘jÒÕ¯Më[ŒQºXyyA[ËŸÃûHšpúÌiªƒ ¢§í’ LÏÌ`fæ\~HSSSÅ¡LŠCȹ¨ÕŠ•Ã¡º§Vœ0Ö ëdíâìåE£k„X 0 £îáš6ü|Z2ûääiZ0,$ Vaƒç¼÷Dç8µÙDN͵øcYجÂɸ8êiIîçöó¥²JMÞC]hÚ«|ÖÎÔ)÷Rzlê\J|el6µ^"êÅÔzךŒÉÍ7®·áû>ëïåmUÿHã–Œ ²'òHzŠ Vª®S‹ÄÞ“ È*c{RÍÆ«¤¿ˆ¦Aá“ðc"Ñ,iÝbؘù Oó”@¶~)…𤣠¢ŸF¤x$P¡øŠ+.ǦM›¬Ž€‘…g'ÎÁÿŸ˜ÇŽO} MÓ@Œall ããÙÏ”ëhýþš‘žñÝ Š¿9j&šf`â=61Žb°^®kffc­ç¬W]&qG¸æX‚bvfcccÆÔ%ù‰¨\³­DÚGÓH޵֬^xÍHÁÙ%ÂrÎLÍ`|Á¸eô´ïK M3âüD…ž5…`Àu£#± G<öRÍ=—¸Qô!:BºXuãœÂ•Ã3i" ¢=xr}yÕº}ŽçÉn} ÀÕ€’Ø,)ø[´5è4…¾¼…\‚&5f³HA*I©µRuÙDÉXm ãKBà‡É¬-{¨D#nu<àÀ’°@O½´;…¡ZIáÄ*²J]ºYȼ›‹š£%׫õ«à(‡Ý™<ÒDžpÎg¨{ø•Ãø›/ý~½Þ`“»ëî»011‘ß䣸Çþ<ðÀ ›×Oøé“;ñ÷ßý{ŒŒŒ ¥„õë×cË–-˜ÅÕW_Õ«WãñÇÇŠ+pÕUWáÁÄ£>Š;wbóæÍøgÿôŸbÙòåøúþ:^Ú?`Qœ>}·Ýv&&&°`áB||ëµµ›P>ùÊÑû¥ÿøñÄO`Ïž=X¹r%~÷w­_oûÛøñŒå+–cfz_|1î»ï~L,8xè¾ùÍobݺuؽ{76mÚ„xSSÓøÆ7þ Ž9‚‰‰ œ={×_=î¾ûn,˜XððÃãðáÃ8uêÎ;‡™™Ü}÷ݸ馛0:Úƒª`÷îçñï|ý~sss¸ï¾ûðÑ+?ŠS§Ná[ßú>ÿùÏ£×ë¢8õÎIü‡/ýLNžÆÄÄN:…íÛoÀo|ö×Ñï'<ýÌÓx衇°páBLLLàsŸû.¾xƒ5¹QA'1%`ZwÃŒ<‹Eº*ç0£/¢/o¡×0‚õX„O£§ë1‡ã8ƒ¿G’·m 2‡EzÎÉ~L`;Fq ¦õ9œ“˜ÃËŒC1%úyLÉcèãõá·Kõ· ËsgûqßA#ch²@ïÀ8>Žiì0ó:ëË ÌâŒaó`ÃNÙ)ü*§°w¡×pFþNh p'ÆuóKLêÃP9‹„“èËÛX¤¿†qÙLÑyƒ„)¼#ÿé¯`ÄlR’3ug<—IH£‚I4gSuJÂF”A‚M«LƒìÔ7Õé3§ža$˜ýÙPEMªkIbdˆÞ£ŠD)©TÒQ­â‘¢+ÉÅÃòî’Ù{Õ†´$óò¡—ññøÜç>‡uk×2ðHøæ7¿‰ééi\qÅP¦ÎžÅ«‡êb³³xâ‰'ðøãã¾ûîÃÒ¥KÑï÷±{÷n|ýë_ÇÅ.ÆG?z%4)Þzë-Fy;ðÎÉ“¸úª«pã7¢iüùŸÿ96lØ€ßþí߯øø8ΛÁ÷¾÷=<ùäS¸÷Þ{qí–-¡þ"•Zѽ÷Þ‹cÇŽaÛ¶m¸æšk°tÙ2|õ+_Á‰Çñ{¿÷{ùs3Øõün|ñO¿ˆõ/ÿeÞ\_|ñE\wÝu¸ãŽ;Ð4 ^}õUüàÑà#?‚_ûÌg ¦¦¦ðýïßþÖ·ñ«ÿäW±hÑ"ìÙóNœ8ŽûîûŸ±nÝE8{ö,¾ò•¯`劕ؼe3Ї~÷þʯ`ÝÚ5xýµ#X¾l9 À̹sxùå—3,àÔÉ“øÂ¿ÿ÷øÌg>ƒ‹/Þ€¦Áôô48púÌi<üðÅïý‹¨brr##=ã(ß>ë‹1®×C¥]‰q½ –bV÷âœì˜^ƒE¸ Óh°³8‚3ø.FqFuŒ éiœÅÇ9}c¸Š„„S˜Õ½X¬ŸE#«ÐÇQœ”ÿ㸋õŸh0ŸàŒ|‹õ7 PÌb/ÎÈw±X? `Ñp“8éæ ôõ$Fq)NË70¡7–º«Ãiü–è8Æð±ÁÏð6úò:zº³8ˆ)ùïè¥+1&WA èã8ÎÊ£PLcÛ¡fe]‚…¸ @#XEäœ gpRþzzØdE0¢©,jËÐ7ðºÁ×j±z*󻨩Æ4*õ5ÞBªµ752gÐSjë¢Ö%÷í¬ÿΉ²I0õ-a‘iEüRXº¦¼W¼µ›Ú´)„¸Ú »×+;±[÷_úÒ—ðÀý÷cË–-ƒ¸_‹.ºccãøâÿw:72T¤}õðaüä'?Áý÷ßlܘ 2ë.º“§'±÷ŽÃ*ípU`õêUX¶t)Ö®YƒeË–áÁĆ °cǧ±tÙ’|ƒ<ð›8xà`¬+*×ÐZ Îà¿kÖ®Á¢E‹°vÝZ¬[wØ={öà÷ÿ÷±pÑÂá._±šþËßþ-îà7Ñï÷±~ýzÜyǦÁììž~ê),[º ÷ÞsQПÿüçñå/Ï<ó n¹ùf@·Ür ®Ýzm~Ü[6oÆ+‡_Æ¥›.ÅÂ… ñæ›obÃúõX¹j%Ö®Y;ðoÞÐ@áwðÜþóßþ->õ©;±}ûõizyìÖ]´PÅììŽ;† 6”y•´r €,C£ËÐè*Œ`ÙpÍ¡‡K0¦›ÑÈj4ÃuJŨn„܂fè*ÚÈ*,ÒÏbVö#¡Ÿ—â¶bT6 %ÒWCôÛÇ6Œè:€…¸'ä‹X¤¿HÂiù6–¦ßƈ¬¡:ß4i)N7ßÄXº=¬Ã9݃Q¹ŠÌá(T&1ƒç1¦˜Å¨N¡‡`ZžÀˆnÄB¹%û¸Œèj(çäŒèôt# Š ÝŽ6`Р¯“˜”‡0‘n¸lD¢ÁUϧý¾ÖÁŒŠT–°t‹û2ؤ"&ëüeUüF…ev5j™\k,Ô¹^èp…6:a“L!Ù¦œ·%ßÎv>*ݶú{j:rȶ#¾ÄX+”—ë:yò$¦§§±eëV{(°qã%¸ñÆ177kZÉ Å;'Obll 7n,Ÿ–€F›¯Ù<°ùÚ*rg0 ëMí=½ù書í¶Û°tébsMLLàÖÛn¦Ç ë\ß~Vê:U©ŸÒvíz·Ür .\h¢žÅ‹ãª+¯Âƒ_0Ÿ&YoíÄ‰ãØ»oöíÛ‡—^z)k¦ÁîÝ»±dÉb(€…‹bÅòæ¯]·¯¿þ:fggw~êSøÂ¾€mÛ¶áž{îÁ²eË + =Åw=· ¿õ[¿5¨ÅµœULŒM@X´h!n¹åVüë?øìر·ß~ûàºWDq‰W@úPô­ý’.„`¢DQx À(zøD{æ`Á Œácht˜~JBƒE¹8Õ[Ñ…”l,š†mNa‡0)_+'•È£yIO`Ç1¦[q¶ù!–¥«ÑÇ1ÌÉk˜Hw"É1Ìá]‚¾¼…ëô  ‚1\c@á€`L¯Â4~Œ¾¾ƒ.t‚E6Á(N5_½¸¢£æa› äDGg7ã+µÂ_Ю¿1‰šÃh•ÑÖáq+ÁïZ¡ƒš—G1š.Es2´ñd]pdÓvP¤’£D^ Q4ÃþmÄ(ÛÜœ¥k¬¤÷à:ÎNÅ’%K*"‘ÁŠ+òæÄ:;;‹E‹Q«œ` ,ÀâÅ‹Ë&ÐðÜ9::Zœ¯lC+V¬Ä™³§ÍFÒÂ~˜Ø-ðZÜ@¿Ÿpúô麱ÇW4M´­ö”ÓãÌ™³X³f n¾ù&\vÙåè÷ç̳ë§>/^<|¶Í¶W4BŸ[‡»îº ×_wž}î9üÑý>ûÙÏâÆÿéÆšëÏat´g±yRð]ãããøõ_ÿu|òŸÄOwþÿîßýoøµò«Ø¾}{Y(u¯´ªnÁ¶¸.AÂ『ºÎÿàJY Åu*@#©XNJiiS“k°Xй 4º}9ÑQÌâ(Ž!É$§ßÀYùÌ`Fõ#èã$âF$Vä¿Vî8£÷ÅZ³„b qfð Fõc“+•²°)¯Sš"r¿WeAÎÓ‰Xl,»©‘cŸpÊ™E¬èBÆâ ÷ú#mÆ¿‰,ôl .FAU\\%ÖïV¥[E§wíŒæ 1J .®ZßÉÃÎO]Ε+V-ý] ƒìàÁƒƒ´‰#,¼7ß|3мà“'qôè›Øºu+ªŒAŦ£8{ö,Ξ=[é:tË–-#æâý…'5Ǧi°fÍì߿۶m 'âÔÔÔ€g à hü-ZˆññqÌÎÎaåÊ•ük5œªÈkMCŒàh¯‡‹Ö¯ÇªÕ«qýõ×ãÿøqÝu×Yíᘞ>}&"~âépûtÓ¥X¿a=>ö±½x衇pýöí0ªÂZÁ_rÉÅ@å V wätl^˜ÃkèéÕn^ªk”iÀƒ* V"ÉÛIË"¡«ÑŽfÆ IDATåÅU8+ßFO7a4]` #ºçä³hd #i“Ðf)‡b™¥¢­‡7…`–n{•}Œ¦+0Ží˜ùOþg0Š+c6KÜ»ê©TÝŠØ5ÕðLêwZY°ÚUÕ¯DvÐý®ñ|¼ÚÇ«ã‚Fx„MÑÖÍ{ˆ:S!`«ŸXî¨ÚßÛM€hfèhŸ<ÆÆF±}ûvüõ_ÿ'|U(vþô§øÉO~‚‘‘‘¡­Y½K—,Å#ß{ĈLMOáøØ¿ߠèը;ÿ쓟ü{ì19rÄp»ß8z<òΞ=|6àÅ *¬Ž¦lÛ¶ O<ñ^ýuÃWÀØè(V¯^íø­ö3ÏÙUbhŽ),–áœìB_'‰«©˜Æs8'/˜«¾¶Ì=&ÐÓK1…—hrx 3x“ò7ýj½´sr³²ãéC¤ÿz$LcZžÅhÿãÃì#€yrPK¤*ÇYùÞà~t½èÔrX Lo–Ìý.Î4aû"X˜¹¼,òÀ¸öDF!¨WPóyÃHÔ®-ïFÔ" 5ƒ‚Rƒ3‚ùÛCŠìŽ® ÏyHº Ojû¯–жÖÝѪ~|ÍU^?Aן: ŸQÇ%mÙûî»ù—‰ó¿þÜ~ûíhšÏ>û,Ž=ŠÛn»mÖÚúÕÚukq÷=wã«_ý*žßý<>ñ‰OàäɓصkΞ=‹k®¹sss9BLšòdkM–U7ß| NšÄŸýÙŸáÚk¯ÅÆqðàAìÙ³—_q9,XMK¿ßj/~áõS?§Ý+V¬ÀïüÎïà _øn¸á\vÙå8zô üìg?ÃÍ7ߌ[o½%_Ïྊ_ÅM7Ý„“'Oâþí¿ÅŸü$–¯X½{÷âà¸ûž{pÉÅ— TEò÷^/%ôûƒ{^µj5þäOþ$ßÛÎ;qà 7 ×T17×ÏiÓwÞ7ß| ø‡ˆŸÚE‹áСCx饗ðÿúÐôüéÿtà°¶x1žß½W\q…QÂàšù€ê•r­¬Åuª$äVýpÎOè½8Û<„É‘ÿci3šffe7¦0¢«ŒÓêä35AuÊ.27„:Œ`aÿ³˜lþsÍ>Œ¦ÍfGö¡¯oaqú_Š`4–c,ÝàÜ „®Š¬E/]޹æ5Œâ²|_ý;1Õ<ŒÉæÏ0–¶A0sÍS€Ž`Aº V2¥²žRf–4XŽÅýŽÓ#ÿ¦Ï §Wf\›V*s0uÑj’æÖ™šh¶ú™ZS‰aÓ ÛÅT¯&zp=)†ÍÊÇ{Œ sT 3 Þbu%Ú­7ŽéôŒ}04&”We ™ýi°Éc?uGPÅÌì9{0ŠMÃÚÿB©½¦ö‘'MVŒ@,ǹæs랆¼Íf؉Ì:¥Ø‚³Í×+€Hc”¢S*ÝaimÒ¤$5ºÂ¬@­âÔ§uØSP7®MÛ¦(ìˆa{@kß‘?¯Ÿ¾í8ªC:˜9ážs;Ù6<[Í9—ˆrY .¤1!Uõ³ÿJ2„{X˜ÀGY5¯eg¤[3s†³Wôœ4(*XHÔ©EÆT}‰é£ÛîÕ<† Žànê`›&µšr©’k¥¤®¾hÿD&}èÛb­ºÈ¼&:.‚ÉÔ|D.ó4Ô-‚%)‹ "€¹>víÚ…ï?ò}`ÉhšGÞx{^؃õë×ctt´”¸ŽcŒOËu6M“áF=Â¥Sqtµ;äS”þv˜Å5Òäû³møÔ‰Õ<14 2ÕËðscÙ4oD¦³Ù 7YÇ÷ä˜A™êqíÚÏé`eeg@µþ+ìµÇ>$ì¡á'NÍ#Rý?£[r÷óþý~ô#ƒíé\<+ÞíœK;ñOÄÌÙqn1¯+Õy¹\Ɉ´6Ò€AÆuÜ`ŠLm¢ãûkÞ¦ÄÑóØ¡p¯Þ6®Þà²ËhtÏã]T(üçDjO©¹ b´âmÆ-ýÏýÌÔfçs>už¼ÉT„ :ŠÎAøc>Ó¤"ð‰Šq·¿*êÉ©øÎçßÁžÀO.gcÜ,±Ru=T/^iŒºŠön/aB‚³ÌÔÔ]ŸÚ28Ä='󼵡¾žo3ˆÕFœÇó/ÀÓcÑQ­,ÓxÚH·Xïyzž8&‰Õð·^¥b3ç¹Z"Sï ÏV{ ]c§i½P µºb檙[° ºv¡1K[zfÃÈNÍKƒ­¨{O0ÿ´­Òºauûu¤›üÇ_¼ý£X¸ª†Â‹0Ë¥…®Ðœ…}–sK~³¨ËÅ‹ðóµãÊœc¶Ðôå PY64WÍ.bÙF‘>!×£>ªïŠùýy¼Þ ñ ÷ª€?”qúeºØô~·óáòÿ—fàÏí&~!áÿ¨†A¬êð™æ¤tщ¿:f´j-Ø"’.ZW¤íeg×P€F—›º‰1ÕwZ$FsëøÅ®ï¹5’ìiÁ¥j½˜XíµÜøJµ~-­h…| Ž–œCººè›OVö‚ç&†Qð`±µ?ƒ7÷†„&ø(Í .GH0z †ømæfÛqP”å(Á¸ƒ)¬@€¿soޔ̙-sÔ©ÿK‚‡¹ÐЍ¯ë&û&VŒªÜZM!Åf¡_Ë•?Oy’k¥<ìk’ƒ?±ÙDÌ8bD~>I¹¶}s6ÂìÙ\A){7»(Y;ü^}-ÚHi¹ƒÉDjí:I°T³ü¿“Ëì¾ß“\„ÇYÇP Ô„Û±JÃAîYU`æøiÀôب‘]éK‹;ƒô’ ‰ÎxG¢àµôÕùx#êˆf¾Ó6ÝB€¨-Tx[Ë`P mÍѯä(ÎŽg<»¦šµ§µB™Â éŒ³ß òöRZƯ3Ã$´#ªB§Ã[5*+o:hS¬V¦9Í0‹×µ>õ|õP† oE¼(T¯§&`É2<µMÄa– × šÃÌ­šÏ¯ªÎ“êÚV­b¹–]l´©–PDðGF1VcqÓS˜s+•È×F·ð{œM¢i7H r·«—ýl½;b“w씨n¥ÎTÍAgž`»·†*^1“øæ¸O•b ø¤+§wÒr¢Óa?ÓÕ–Õ:ƒˆ•Ã('°Íu'i7ÙäT”S¹&ºßÔFŽm”;t·fð¾S WóÐPTÔdûÌZI׊“¨º3¸ÒäRß6v[Çi£®2N)DW§=?d`Ý›wæ’«û¸9Y”gÜÏj)¨‹vÄ!)ZKjDi}(Ì!®/ºM*ÁO§Š£žZË*$Ãy¬òÚíŠfÍØ'›á$œ*h+( N@6”†]—? ¸ËÔ<²£\ ×#s¤Fš 2å1I&S¼«gƉ(¯Ž¬ÕzA˜Z\7Š5›E14’!éX(L5ú-|‚80)ˆ SJ|°Ò¢ÜI2G%JH˰Ãj¬Û˜ŒO‘ª°#"ÎëGÚ—‰$j ] YÏ ±:ý>’sb JT±2ÔDöWï8¢Y¾KIó_‡ô:¥º£Õùû[½<†hÍXĤ©¢Ö^˜ ×%À:$pC!m”,Ö‹X£ø»ÓGÓb‰Qu fSŸ›±`…ÅdjUÞ–ŨÀ>àÀòv\9Š1s’çžÓwäúš¸ÙÃT¶v›y­êkm’©K…Æ(¨i1©pFDß(jÀ…„LUµb¥†Ï+_ÉÌ öjáxU¾|£ã¢8|$¦vrI¥À*„ûqè7 MvCÑDŽáõ&­SÁ‡›jâgPJL>þÉxÆvgK­Òˆ/ÀfJÛÂfòÞ'£æ›Ú:ÎÁñ|}ÊÉ⎅1¨’Óž£Ô’˜QÉc÷àˆ†ÂÆ;G’8=Lz4İõæ&™X]Ƹ›21óMtX³ãS2ˆoŠo›˜÷‰u—Ò±h# 欧…Gª·¼[û@XzJ,ŒV‘†© J‚ªŽú¥T²QKdvÁ€$F‹¢‘FKuG˜T‹rV^"*nu/Zq"¼WÔjü%Š!dQ'ÂT/±Úñ£½™ÅÊ| Žc-ÑË‰ïæ‹($v±d}+pA*?f®´×àj—Îr‹Éìð/÷ˆ @™d_Pà¹æe¯æ9–{’¬i˜kç®ÙkÚ¥­ÈªKÁ…<^ÛÌK@s]h®úLÇea¼ÃŠqŽ‹Q`ÎY†0g'vSlEvMwÛÎúààÐÆ=tÔ2jž^ÖIk§¦Fb5œ!F„°"3J'-<ÙÈæI;±‡Üh®ý IÓ%EBˆ"}7¡p\]ùŽþV,þÉûëŠ:h‚­x¨Ú…ô™ÕEuù3­bž•Ø¡8CÕ^¿ttÑéž-UUöRïR¢’>úæO^ùsŒ´i0‘šºLâ:yiÝ›Y¹ÈJ$ðßØÈ­œdFÅ™? ×Å:Õ”+p-ˆU6lÍ|k^_<—“ R¶¥^ Å=‹d£8CïW¡€ªZ \T\o©Ù,Qé¦ÛæKm„M‰öôž*¢š•ÖÈÂTpx&‰ñ]ˆJ¸ØcÖ@EÑél©©Œ˜BˆÚRN!’yQv,/ûriÙ$´*€¦bk)ž-+*ŠXÍ2µNë콡ìƒ[Q÷*V¡”³ÔUìIÎR<µ!©Ël‰H(ž ‡Í¤«Ç^¶êÿÕ‹PÔ ˜sÐá¼Lö@5I  -©Ì}+c”ëÆôl@uD/üŠ,©¥VBÈDÀâL1Hâ@}eβދ炗8gãVkÚ’«±$¨ªZïùÍV¬6_ÖToëñ´b|,:ßO;‚ˆ‰¼Ì\3µ: ö¨/mÆ IÃù5äÐ/Zñ[RÈ#<òù»çËîí`:gÑÅó®|/×¼›Zãy½j"Aañ½Ž>Ø5½·+¯‰q~xßàÏ´÷<¨ó ç{R ¨DœâÎ(“p¾Àær^ñ½=Ü8uœaýÏa}¸”T®>àī¸ÕoÕ÷3±º_½Ü!Õb¤Ã'4Ë“ u²„NPë¦Îì‹¥¸]É^’¡n!bR°SÔ)AŒíjc©ÉöÀµ¾`Ä!EøŠ`p¾vÐF”ù” ˆ«H…{°u2möpTˆ¢ˆªRÅãwûgãÉæVÙ\Œ¼PST–¤DË,Å+N¯Ü½&‰h–B²›ÊæZ°‹*LÄ"Qr]X]]‡˜»«ÜDÉsYL“ÑÎ3ÉRCJâœ"nûW‹0ÈX:–|‚Ϭ­@±%u©b³®c·JÜÜw Š£mî›æ )Àa@…"´ö¹æ=1˜¤}3•ÀذGŒ"Aûèº@ë˪ŒkéÆÓ™u¦€|ï{ß;o/°_Úô~}àQøeÆtæÑ/íÜþ~5…(¢Ä÷|3—:'0eâ<0 ÜJ®°´Sq6ÒJÁÖ”O DÂJ¹¨7#7t7K0W£`¬|mò je<é_;ˆµ ~5׬–ïèâîÚj4'² µÜŠL›Fð©—ú±Â† ï¸LÛ äxKÕÓ@èR„i{êäÆ`ä€*y’¡9z2º:Hp×LcgisjÝ®!ç?Ž˜n¤•´ä3º!/WE—ñtx&@e¾Ù5ÀãËëUi~Ò·VÄ<Õ NăO K‡S÷Ýîo½•_¦óõ8äCP0¨ãÀóÀñ°lg6’ûMé[4xÐú O¨ëUkÒDá>¸ÑA\v*¶ÆÀño¶ÝHx7 bDÊ—é¤U@a꺭uò?ê˜HÓ“q÷XÛŒCËL£ïˆ£ö¨8æ€Ö.Ü7µfϯÞdêÎ4)|¯%y;IêðœÝ¬ªt}£H_„uèrl 7n¹<ãÁ@*„¤ªaèNÖ+`a}Hmzª¥Lñ5¨W³ZgØJ¶GJóßòÌkUƒ¨…çÊv¢?ȳ"°ÁY¨Bb·•÷ðÏ[LÓ2w“¡aÁʵdã°‰°d²'VôsºxœZSH­œ<AÈÁeÆ¥,0@hˆ„"EÇJßXÙ(– Šã*K†÷t;Tè7öT÷÷ÝÊ`©‡ÖzÎä<‡ èš‚\”FÊ™jåž’SÑÚÂô$wc_?"ê´-¥'ލx ’fêšz «;þÕ©¤ ²y$Eñ‚™˜ªd¸!Ú„(,Ù‡ tD³Ð„&µz0I*^,>2þ]B¶2x{2ó£º8M–”2°<@ˆL”¬&¸´†F©·Úg›ª‡¨Eg+eTdÂ`AÞC…TREYÁJQáÐ˰0lÅ€+øF€{j‹vàý˜4úU¼ó{$§S&Vï3©NQÖàPÔèÜGÓç¾V–Ö°áUlPª­¸zš O\¸[ÔTiH1UÉiŒ±ßƒ3¼A˜ÀNTÙµ#ªs0"ž,âø–ÜàRâ{BzÀ2t!âÁì5ÙFЦYŽçB»^Ie‰ÛTBD]Ýð œ 1r±k§ì“ú†‚Ç´ùé§° zÝ­n©ºÏù4¢‰i +‡ª¸¬CŒ@…y€ç±B‡‘CkF)¡r¬$s‘伓Ý¡F6(ŠM¢’Êâ½w2gKTiÇþó²9ZMòE&Ä–œ¤[šÆ½Ü&'/U™^Ê=¹…ÏÒVi¤" jZѵ.îíS !¹úhŒëZnpQS²¼4vÒxúÎ ƒf©0Žˆ“Xþ&Ùd¯/5¥„(«è>S½9DÜFÁÔrI}”ìBÔ6z c_‚ÕꤸF­pÕ°4Å_+š²™Êu;©³,AåÖx¬¦ŠêbHìËLÉŠŽ¤j4›¢°…ÏP…í³iÞð„A‡Î¿’i@â §,l6b!jˆó£ôÌ ©HÜwÁCh2åÅÙlUuÒÔFšU¾!,‹%£ˆSÅšÁw€¢&u¡.¢¡!K‰«Ãx.i>ÅÚ÷‹³œ4Q1Ñ.ù¨Ä47J…û¹¬V6ÁTøJÊê4E ]{ÕÚHYÂ+Št¢<ÈåÈœ³¡¤%ÛµONqE0i¢«ïj‡®Xpâ%ºE„©žË„‚PrfQHF ¨¨…S=…æ—¸±ª–Za/Æ‚TU¸[býóÅYA¤ð±ë\Õ$zÔ×ü(Ñ‚Q£"D ,hYHÜ0çõ^(ÀKèPWÔGÕú‡°µb·c$BuP‰‘… ðj-…‹éduæÙ4HÓ—G,/¾¦ÃÓŸ=:Y)×÷|ä%pÌ7ë T<\Åu )¢T'o TÓ3šdè607ÒïöY©D†YR"„B'“ª?«K L=’ÚRÙ hÙ Õ¯Ôaɉ>‚;/Ÿ*St[¦Œ¯­Ã‰Ô²,N’¸>Ïÿ†)Ñ^™_–úfë´bj®\̤÷=ExNíq‹ЃïäUZÒ¹¸=\ðžÁjê"ÂJǰÎÞí)A›bTIeKTT\åk(öG J·ZÑDAœ¬ü1ÊNÈ;¥W à¹Ñb¤ª4*ýº(D\»?0òE]×É:|íRYÂiüh¥ïoÚôF§Ç½?Y=;Ï“4blú¬` #™ëZDAÖÝh½¤6%VC]ðeJßPOIˆºW¹–%¹ 9^*õíA(1´¸`[Z¹-¸Ë*3ð„Á^wbcrKc3VE€›à´ŸÊ? ÆäÖ¬» ®Ó’Žœ:5ÍÍvU”ër*­Dkþ™ SBö$Áž6QzÿÃ›Š’8¥ØEìµ²¬¤3¶];ñ,÷ VUˆexа`¡Â¨y†2®7¨‘EÚ¼—‰ áÏ {”ÛÚ’Ä&`þOzÎ%ŒŠTdÃÙž»`™ºêe|¾Ynbiªª‰ ™æ¦°T/u“b,ÖQ©[òܰÒUJDzQ 8K­9ÖS—X8«G]$Ì¥ ‰¡ú™ ÙThÐ äݪå}ÇP2õËPù\¤Øv …„ܹ/Yƒp4–kepåE –žØnf"®ÒȼÔvÍOºDjÔÏbÅèʪ±¾»£g ebC¤†ts¨X PVâž¹‰ ]’fjñ ô»ŠmhîM¢µ¦x¥m­Õ,¼ÞR7ý<±'Fp)[I v´Çu2©ÁðߪÝ'W ,ht%#-'í¸uÉc'.FÈK-Ãüç˜"H\BìZ–C¢ ì¥^c±Ú[T®áòÔâ3 ÒЙBiÝ©L*µá:†ÏÆôö RU»ŽSº¢TÁ7?ŽÔ¹-VsVµÛ7Ï*Hsm‰Öe Ø“‹²$H.© ´®j‡K!3—rtl¡íÚís/®q”UY0´?ܯ± j\½Üa“-¨éîI–V1˜–ÚŽInW—ŒM4QNzÂÉ›ýÝJg‹©C˜F)‰ ›­»IyHbäx”:{Ìên!I¹Î‚¹ûæúôðÄHš E!È]\Ÿ’ÄV|¡¨HK…޶P ±È­s “íí„¢%{¨9ùN#¸‹o vBx¸")•®u.ì‹í曎´ñ^H¢Ëgœ-0Qœ£ÃòŸ¡£Ò©ô‘ŸØ‰hE&€ºÕ¤ØhÅ×Ä„Âu XÒÌÉñüæ´r0NV AéKņîFöIÝ܉vX ãZT…mÙCÀ™„¯£òú€ EQÖ «|e±ž4Ïäá‡~B^îëÿ'c^¹Í ³íÂŒüýj”ŠØ·Rë$÷š+œ³½w'W&Mkè®jxÀ•^ã{xí~*÷C·ÞUccœ›¹°VÒHC¤gh <ÙŠz18n|¿.àÉâžÞ¨U¾…3;u`]U PU¢¥eèã3k@ìT|‹ý¸šk³žÁªé ˜ %êÝèÍ|ö|Zv¦¯—zŒƒŸ'Nn„OØ2‰òwh„y*¤¥;V¨Ÿp`|GWLÔ ñüè…aŸ)ª¢¥ ó·f®:âà¼+)®'=’A‹^p¹¯\š2݆'¡ÀRßP:dµµB똯ì§Á1Æ‹t!ÜO¸>çEªp5˜ :ËžjŠÇRK2"6Q*Dj%Ø‚u•×ÎZhði¨lEö¿B —êœÿªèHå:Bç,x+D€¯WàÎ~l`îWçÙðÄ—JmËiu VZ(‡Z­³ulxÕc±‹¼Våèb'Ôצ봋ÎÏ_u,aõrBII}ˆnf Ñ©±­¤¢„Ž /¸ì_ÝÁ£iTÝÉßæèÃíy‰õB·qiðŠc¹z‰"f°?‘*gƒTf™#À[ºk&ƒ;?G„AòÉŸ¨ ÑÁ>…9‘$ŽEH°ßÇœw;îJÑ@è\i<5íÃïLÅf4Œ´¾™:p-‚Zˆšx Ý1(H‡dDx7cä¢öØhÕ-î@õK2¼{ÐÚAÐ^ˆ†…:ÎÛ"”À¹pÊŒüXRcs\WÈ¡'™x=(xù,s¿ÉJUiEaHW­¦‚Ãçq÷Ñ[²·óÊI•±IîµÚUEU²ËÐBɧºWÓ_ V®ZZÓ¼Ya'û¿ƒ°“’¸ËÊΈº“Q¤¯c¢9îöÔœ£: Ê8å‡ÚÝa㵎 ìÛQÇy±¸înìñ9¸Ý^¦ÁÌ c†ÔÈ|‹¦Eˆ5H6—Æ”© =߆g3K¤¯C*l‹h‰ ôõQCôk‘Ͷaâ/“½’CwWØÌÆa$¥"§Åô%u×ã#Wõn÷.óqêÀð@tž. â`5ÌÐÊú%ÎX U°E6wB‘«š`Ÿ­œö{íÆûάXÄ_Y¬Z&"ª­/i¨YÑÎ,»Dô°*Å,ÕÃO­ÉÄx¥TW QK ¯Ö×;*Yº<¹½ `ÑI-ò›;õ`øé•Ô´` ª&h _•çE3í¨iQI(%÷3€u ’‹ÐPä¨|JE9eÂ~rZ[8–äoqªéÔ9±Ñ<·R‰ò÷½=µu+zº*÷9øl†™$K‡s‰¼\—Ú8ßdI­`hïÐJMÒŠì™_W¶ã™†ë!sžqQ€WC´š†‘xP±˜f²»‹¢ê"¦Aô,ªµÃö–JM¶ÇæÖ>—–ª˜¥t ¤%žxˆò<:ÂílÕhš µì0ä´@.¦ œ§€°äÓ]©Žæj - QeÍɇõú+0 o¨ÇQ°×ŸŒrE´+•^ºx’67yqe¯X&ü·ëÅžàZ1óõ ÚÊp%•¸¹2*§Ѻû©ˆJŠƒ˜hÊöC6›{tP±^¨,ÖÉð Pˆâgªbé’ÕÃ˘ß2…ëh ¼Õ]ÉÏR`©‚j2 ®‰ÛÌ,F‰,ßd7j×ÉÊBóý¨©¡šlÉ79]Ú%ŒõTó¯fZÃë©}O#Œh“M:gZév CbÜj(j½`¬´ãk¬ãY pª$ð¡««´(i¡ûùq×mBüT[Æ C­+?ã(²Ò,ÐØ$á%“±ªë2'VvEÊ'°2ð)HŽ;±Šš¬ºïRÒöÒÂQH¾K\øÏ–(ßžþ ±ËWQŽÝN§ÙVZŠå^‡§}R—I„Eg’‰ñ†×jXOå>ž¬ÎTªGèÉD^ÉD?…çßV&,uøž”œ(F{ëÉ7+R޲LéÏÉEq˜šBæ£F€%B¸ê¦~Ò(o1l†‘à»û¨D²V0Ôf‰ZS®úÆŠ]Iäie¹½D&jÍãñ‚%ª‹€N ¥Ï«t˜Œ-§†šˆu~w]:Ö¥Rw3µ®øºÓÜ̧çk’ ©_,Wàê’Aw±€o…¸XDm“@E"ºH´Ê”=‰ $ãð䀶(nm"zv°uéPk©î”.ŽdjdœJGO¨Æc­¬ø”„õÚäÍÙˆ8<­IºhY†[\„$¬‡³Øn=GXFäA¢¹¶Ø°O‚%A„0eæPÆG§l½7^ÃÙ%iyÏ6"ž·ò¸âi%–Jàãúé¤üÅkŒàÖÆë68UÙšµ½NAo°ë¯ÍtAÎè7"˜'U¦V)<ô¬˜"e£tÍ–nê„@´´¾5…Нw+'kr 𥰝­¿HjÃê2àAÐW“¥˜ZŠ-óÒÖ{‰vÓKPHj7†"Æ ác‹‹=?eéùéü:8hÛÌpG…¡÷Õ v½ç]+9$b¥Õ£¹ž­Ñ%Y­°“z˜‰šSÞ²öD´‚… l¹Ti„Ùjq~bܨ–ÍÙdZö8©Ô[–LXa«L=|ÎÉžvŠ0dÛPT 3*ð#§\ã5½Ú jq%¶äÆCs.5ÅeµJ:=en‘‘ƒ²†ã ý¥Pœ­ôµ5¼UÃØçÝB¨NRh Fº%6×dÕÅ;¦Ãug­õpŽ&²ï§“9EÂõH'¬)Vn§âÔázn…!­\Ž“iʵ”áï…¨mÎ7~2zsúðù¨æQNIJ¹û1…f1 å–ãš½l…w+¼)jkŸê«Æ®!gVby ‰]mdî£?®1‰­³|ùâüspf ®…‚9£ Q²5˜4–r‚:¬ Ó¼(È`/Ö…2Õ¥þj;êš#N«N$Å:!Sâ$—YdUÜ&Æut+8ã$«4vqU´‚?m¿‡â]Öweª¡8¥%Ú»ÔªGJg/mt8Zi¦àŽ…ÚÓfÒkl¯h¦Ö:oN¢|BjþŠ¢@k™˜(å°žWk<ÄfJ¨FhÍImÀÔ¿–HêôÙ|ÝÏb À÷ µ8U«¨‹J'ÓàÓÄžq9Œæ…äŽbW¸j5—:”fç÷+ˆXB®}j”tó¥ó ÚzK>ñ@sœV¿Ð¹šÙÁ·Wšˆ«m»´í"Ïâì'p¬%?e½¹IL$%™*ºŽV–zÁ@<`Aà=d<ΠË’uS©Zz¢>²«¬ž1Sa"sî~™sÈñ…j`¹»).Š¢èÃÔ¹È>è0º®[îê™hˆN(c~âÍNjÚÇ] Ÿé%Q°S˜à¬0J%*$´Ù’àYlP¬àh‘ã¡ñ°,øÉ ,ñ]Kԫ愤'@µFs·‡[.HUߘ‘ "ÀrEE¶‰Äb©X*ÈI{Y)« òè\3ƒ'ãöq© d¶,ƒÅ|V ”eÀs„ϋߋW¶BTó‹¬Â1`å“ ÐE'F¢B,"H¨Vئšêp²mÄæ€¯E(׬¶f)QÙr¸ÎŠÔzÉÈD}}ŸºÓ,áä›2*‰‹¨Éôœ¯]±˜@(ìœ0. ßøÆ7.ð±/¼.¼.¼~é_Í…!¸ðºðºðº°Ù]x]x]x]x]Øì.¼.¼.¼.¼.lv^^^^¿P¯ÿ@;ÖˆA²õIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/ide.ui000066400000000000000000000117051217176075400204200ustar00rootroot00000000000000 Ide 0 0 770 405 IDE :/ide.png:/ide.png 0 0 IDE toolbar :/empty.png:/empty.png New empty file true :/script-new.png:/script-new.png Generate skeleton true :/script-open.png:/script-open.png Open file true :/script-save.png:/script-save.png Save true :/script-save-as.png:/script-save-as.png Save as true :/script-run.png:/script-run.png Load true :/undo.png:/undo.png Undo true :/redo.png:/redo.png Redo true :/comment.png:/comment.png Comment true :/uncomment.png:/uncomment.png Uncomment true dff-1.3.0+dfsg.1/dff/ui/gui/resources/idewizard.ui000066400000000000000000000152551217176075400216450ustar00rootroot00000000000000 IdeWizard 0 0 400 300 Integrated Development Environment Wizard :/ide.png:/ide.png General Informations Fill all script information such as name, type and saving location. Name: Category: true Work location: 0 Browse Type: Qt::Vertical 20 40 0 Script true Graphical Driver Qt::Vertical 20 40 Description Describe here the goal of the module Module's description Author informations Fill all author's informations in order to complete header Author's first name: Author's last name: Author's electronic mail: auth_fname label_4 auth_lname label_3 label_2 auth_mail dff-1.3.0+dfsg.1/dff/ui/gui/resources/interpreter.ui000066400000000000000000000056211217176075400222220ustar00rootroot00000000000000 Interpreter 0 0 256 192 255 255 255 0 0 0 255 255 255 0 0 0 106 104 100 212 208 200 Courier false Python interpreter :/interpreter.png:/interpreter.png QFrame::StyledPanel QFrame::Raised Python Interpreter dff-1.3.0+dfsg.1/dff/ui/gui/resources/is_deleted.ui000066400000000000000000000020451217176075400217550ustar00rootroot00000000000000 IsDeleted 0 No true Yes Qt::Horizontal 40 20 dff-1.3.0+dfsg.1/dff/ui/gui/resources/is_file_or_folder.ui000066400000000000000000000020561217176075400233230ustar00rootroot00000000000000 FileOrFolder 0 File true Folder Qt::Horizontal 209 20 dff-1.3.0+dfsg.1/dff/ui/gui/resources/mainwindow.ui000066400000000000000000000165611217176075400220400ustar00rootroot00000000000000 MainWindow 0 0 800 598 Digital Forensics Framework 0 0 800 18 File Module IDE ? Edit View Toolbar 16 16 Qt::ToolButtonTextBesideIcon TopToolBarArea false About DFF ... Load Load module :/fileopen.png:/fileopen.png Open evidence true :/dev_hd.png:/dev_hd.png Open device true :/exit.png:/exit.png Exit true :/configure.png:/configure.png Preferences true :/maximize.png:/maximize.png Maximize true :/randr.png:/randr.png Fullscreen mode true :/view_detailed.png:/view_detailed.png Browser true :/shell.png:/shell.png Console Console true :/interpreter.png:/interpreter.png Live scripting Live scripting true :/help.png:/help.png Documentation true :/script-new.png:/script-new.png IDE Open the IDE true :/module2.png:/module2.png Browse dff-1.3.0+dfsg.1/dff/ui/gui/resources/modulebrowserdialog.ui000066400000000000000000000032141217176075400237240ustar00rootroot00000000000000 moduleBrowser 0 0 572 272 Module browser Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() moduleBrowser accept() 248 254 157 274 buttonBox rejected() moduleBrowser reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/modulegeneratorwidget.ui000066400000000000000000000142071217176075400242570ustar00rootroot00000000000000 moduleGeneratorWidget 0 0 500 296 Module Informations true 64 64 :/module2.png 0 1 0 64 16777215 96 true <!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:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> <tr> <td style="border: none;"> <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;"></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;"></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; font-family:'Sans'; font-size:10pt;"></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; font-family:'Sans'; font-size:10pt;"></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; font-family:'Sans'; font-size:10pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></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; font-family:'Sans Serif'; font-size:9pt;"></p></td></tr></table></body></html> Arguments Qt::Horizontal Activate Description Qt::Vertical 20 40 dff-1.3.0+dfsg.1/dff/ui/gui/resources/modules.ui000066400000000000000000000035241217176075400213270ustar00rootroot00000000000000 Modules 0 0 400 300 0 0 Modules :/hex_page.png:/hex_page.png true Name Key Value Info Type dff-1.3.0+dfsg.1/dff/ui/gui/resources/node_f_box.ui000066400000000000000000000070501217176075400217570ustar00rootroot00000000000000 NodeFBox 1 0 0 1 Quick search: Search recursively 32 32 Launch quick search :/search_small.png:/search_small.png 24 24 true 32 32 Advanced search :/search_advance.png:/search_advance.png 24 24 true 32 32 Index options :/db_opt.png:/db_opt.png 24 24 true Qt::Horizontal 40 20 dff-1.3.0+dfsg.1/dff/ui/gui/resources/nodeactions.ui000066400000000000000000000060351217176075400221650ustar00rootroot00000000000000 nodeActions 0 0 400 297 Browser :/view_detailed.png:/view_detailed.png false Open in new tab :/exec.png:/exec.png Open true :/exec.png:/exec.png Open with true :/hexedit.png:/hexedit.png Hex viewer true :/extract.png:/extract.png Extract true Relevant module :/bookmark_add.png:/bookmark_add.png Bookmark Add nodes to bookmark Open parent folder Open parent folder :/tag:/tag Tags Tag nodes dff-1.3.0+dfsg.1/dff/ui/gui/resources/nodefilterbox.ui000066400000000000000000000101701217176075400225160ustar00rootroot00000000000000 FindFile Find file Pattern: Syntax: Regular expression Fixed string Wildcard Attribute: Name Size Date Qt::Horizontal 40 20 Case sensitive sorting Case sensitive filter Qt::Horizontal 40 20 dff-1.3.0+dfsg.1/dff/ui/gui/resources/output.ui000066400000000000000000000024051217176075400212140ustar00rootroot00000000000000 Output 0 0 400 300 0 0 Output :/info.png:/info.png dff-1.3.0+dfsg.1/dff/ui/gui/resources/preferences.ui000066400000000000000000000542441217176075400221650ustar00rootroot00000000000000 PreferencesDialog 0 0 458 376 Preferences Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok 0 Global Working environment No footprint DFF user directory: Browse Qt::Horizontal 40 20 0 170 0 0 170 0 106 104 100 Provided path does not exists, will ask for creation on submit. true 0 170 0 0 170 0 106 104 100 Provided path is a readable directory. true History History file full path: Browse No history file Qt::Horizontal 40 20 Qt::Vertical 20 40 0 0 Language Interface language Use interface language: Qt::Horizontal 40 20 Qt::Vertical 20 40 Indexation 0 0 :/index_search_64x64.png false 0 0 Please select in which directory you want to save indexes' files. If those directories do not exist they will be created when the changes are applied. Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true Index files location Root index Browse Index name Browse 0 170 0 0 170 0 106 104 100 Provided path does not exists, will ask for creation on submit. 0 170 0 0 170 0 106 104 100 Provided path is a readable directory. Qt::Vertical 20 40 Help and documentation Help and documentation settings Full path of the help and documentation file: Browse true Please provide an help.qhc file along with an help.qch file at same directory level. true 255 0 0 255 0 0 106 104 100 Provided path is not a readable file. true 0 170 0 0 170 0 106 104 100 50 false false Provided path is a readable file. true Qt::Vertical 20 40 dff-1.3.0+dfsg.1/dff/ui/gui/resources/search_customtable.ui000066400000000000000000000115061217176075400235250ustar00rootroot00000000000000 searchCustomTable 0 0 580 390 Form 0 0 5 5 Qt::Horizontal 40 20 true 16 16 30 32 :/add.png:/add.png 16 24 30 32 :/remove.png:/remove.png 16 24 30 32 :/configure.png:/configure.png 24 24 ... :/filesave.png:/filesave.png ... :/folder_documents_128.png:/folder_documents_128.png 2 true Query name :/filter:/filter Enabled 5 Query dff-1.3.0+dfsg.1/dff/ui/gui/resources/search_panel.ui000066400000000000000000000216001217176075400222760ustar00rootroot00000000000000 searchPanel 0 0 289 623 250 0 Form Quick search false true 0 0 5 0 0 Wildcard Regexp Fuzzy Fixed Custom 0 2 Types : ... :/lphoto:/lphoto true ... :/sound.png:/sound.png true ... :/video.png:/video.png true ... :/document.png:/document.png true Qt::Horizontal 40 20 true Advanced search false true false 0 0 5 0 0 Options 0 0 2 0 0 Search from root 0 0 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Found Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 40 20 Start :/viewmag:/viewmag 18 24 false Stop :/mail_delete:/mail_delete 18 24 dff-1.3.0+dfsg.1/dff/ui/gui/resources/search_requests.ui000066400000000000000000000041021217176075400230500ustar00rootroot00000000000000 Form true 0 0 259 47 Form OR AND NOT name contains date mime Wildcard Regular expression Fuzzy Fixed string dff-1.3.0+dfsg.1/dff/ui/gui/resources/select_attributes.ui000066400000000000000000000114201217176075400233760ustar00rootroot00000000000000 SelectAttributesWiz 0 0 505 361 Select attributes :/menuedit Attribute selection location Select attributes from Current list true Current selected file All selected files Group attributes by Types true Generated module :/menuedit Generating attribute list 0 layoutWidget label_3 label_3 progress currentnode :/menuedit Select attributes -1 dff-1.3.0+dfsg.1/dff/ui/gui/resources/selection_actions.ui000066400000000000000000000017141217176075400233630ustar00rootroot00000000000000 selectionActions 0 0 400 300 Browser :/view_detailed.png:/view_detailed.png Select all Unselect all Clear selection dff-1.3.0+dfsg.1/dff/ui/gui/resources/shell.ui000066400000000000000000000055641217176075400207740ustar00rootroot00000000000000 Shell 0 0 256 192 255 255 255 0 0 0 255 255 255 0 0 0 106 104 100 212 208 200 Courier false Shell :/shell.png:/shell.png QFrame::StyledPanel QFrame::Raised Welcome to DFF shell dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/000077500000000000000000000000001217176075400216705ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/images/000077500000000000000000000000001217176075400231355ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/images/stylesheet-branch-closed.png000066400000000000000000000005161217176075400305400ustar00rootroot00000000000000‰PNG  IHDR _žüsBIT|dˆ pHYs##rAwÞtEXtSoftwarewww.inkscape.org›î<ËIDATW}I 1E³K$ѽ .¼BÐÞFpëÒž@WnÄ mqÄ §Cµßi¡uñ)Rõ¨ÿSÂ+ª„ 0 Eœ„×´µšš¹$¥c§ih‰:ð YŒöÐ [fNÑÈ.g…Qà­¡™U4vš{NqÝ3§ž€Uòˆáš;CØõuP›èå…3òôŠÇš>²XÍ]ص^€æs$h€ÁÐn|,\¢A½æÊWH¬»¾ƒÖÈRÜ7oN˶KPæ×¡jÿN}’WŸ™‰Äy©IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/images/stylesheet-branch-end.png000066400000000000000000000002661217176075400300370ustar00rootroot00000000000000‰PNG  IHDRQ::’¨œ!PLTEÿÿÿcVMcVMcVMcVMcVMcVMcVMcVMcVMcVM Èìã tRNS|Y:3ex/\?xÅU9IDATHÇc`ÀŽ‚ ÄQ•£*GUŽ$•‹”0€v•…‚@€2•mi“1€Ã(£` YT“š‚±ŠŸIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/images/stylesheet-branch-more.png000066400000000000000000000002101217176075400302200ustar00rootroot00000000000000‰PNG  IHDR5VqPLTEÿÿÿcVMcVMcVMcVMcVMcVM_[êtRNSJF36RS”ƒŸNIDAT[cdFù`ŠœddNqz¨Ä~Ò‰™»¢IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/images/stylesheet-branch-open.png000066400000000000000000000005321217176075400302260ustar00rootroot00000000000000‰PNG  IHDR ÍäñsBIT|dˆ pHYs##rAwÞtEXtSoftwarewww.inkscape.org›î<×IDATÁ1J\QÐóß Q‚®!kHaeá~²û JIö!Dp…è5öƒgð=ï#ïË9µ¿·s.ù•"ˆš“Ù\UA"â¢Ù~Ûýø“úŒ EÂŒ Efþ|Z_Û"µ:½è¡cBSØl}p¼HÆ·«á)•“0… “2%¦Š^-ßo^†ghwÇ˦.DG¯èUիկ߫ñ  Àr=œ¥ÕCTêâqù:ü€÷É{›|«dS²©Nï“w¨$öwwàn=\ü |Ø|c_|IEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/images/stylesheet-vline.png000066400000000000000000000001741217176075400271510ustar00rootroot00000000000000‰PNG  IHDRQ:µÒ]< PLTEÿÿÿcVMcVMcVMÕ§$-tRNS|:3tHÁIDAT8Oc`€Î,`TtTtTtTt8Š™ãwU¦lIEND®B`‚dff-1.3.0+dfsg.1/dff/ui/gui/resources/stylesheets/treeview.qss000066400000000000000000000015621217176075400242560ustar00rootroot00000000000000 QTreeView::branch:has-siblings:!adjoins-item { border-image: url(ui/gui/resources/stylesheets/images/stylesheet-vline.png) 0; } QTreeView::branch:has-siblings:adjoins-item { border-image: url(ui/gui/resources/stylesheets/images/stylesheet-branch-more.png) 0; } QTreeView::branch:!has-children:!has-siblings:adjoins-item { border-image: url(ui/gui/resources/stylesheets/images/stylesheet-branch-end.png) 0; } QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:closed:has-children:has-siblings { border-image: none; image: url(ui/gui/resources/stylesheets/images/stylesheet-branch-closed.png); } QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings { border-image: none; image: url(ui/gui/resources/stylesheets/images/stylesheet-branch-open.png); }dff-1.3.0+dfsg.1/dff/ui/gui/resources/tagedit.ui000066400000000000000000000040551217176075400213000ustar00rootroot00000000000000 edittag 0 0 395 116 Edit tag Name : tagEdit Default set color Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() edittag accept() 248 254 157 274 buttonBox rejected() edittag reject() 316 260 286 274 dff-1.3.0+dfsg.1/dff/ui/gui/resources/tags.ui000066400000000000000000000132621217176075400206150ustar00rootroot00000000000000 Tags 0 0 581 373 Tags management QLayout::SetDefaultConstraint QLayout::SetFixedSize :/tag Add and remove tags from selected nodes Add new or delete existings tags (Double-click to edit) Qt::Vertical 20 40 true Tags management false false Selected nodes tags Available tags << >> New :/add.png:/add.png Delete :/cancel.png:/cancel.png Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Ok buttonBox_6 accepted() Tags accept() 449 403 267 213 buttonBox_6 rejected() Tags reject() 449 403 267 213 dff-1.3.0+dfsg.1/dff/ui/gui/resources/taskmanager.ui000066400000000000000000000037321217176075400221550ustar00rootroot00000000000000 TaskManager false 0 0 0 0 0 0 256 192 0 0 Task Manager :/script-run.png:/script-run.png PID Name State Info Duration dff-1.3.0+dfsg.1/dff/ui/gui/resources/varianttreewidget.ui000066400000000000000000000030551217176075400234060ustar00rootroot00000000000000 VariantTreeWidget 0 0 256 192 0 0 true Attribute Value 0 0 100 30 dff-1.3.0+dfsg.1/dff/ui/gui/translator.py000066400000000000000000000040231217176075400200440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # import sys from PyQt4 import QtCore, QtGui from PyQt4.QtCore import QTranslator from dff.ui.conf import Conf class Translator(): """ This singleton class handle Qt and DFF translations self.dff stores DFF translations self.generic stores generic translator from QT No need to translate what is already translated. For Ok, Cancel, etc. """ class __Translator(): def __init__(self): self.dff = QTranslator() self.generic = QTranslator() self.Conf = Conf() self.loadLanguage() def loadLanguage(self): """ Load DFF translation + a Qt translation file FIXME need to check if qt4 directory exists in /usr/share or /usr/local/share """ l1 = self.generic.load('/usr/share/qt4/translations/qt_' + str(self.Conf.getLanguage()).lower()[:2]) l2 = self.dff.load(sys.modules['dff.ui.gui'].__path__[0] + "/i18n/Dff_" + str(self.Conf.getLanguage()).lower()[:2]) return l1 and l2 def getDFF(self): return self.dff def getGeneric(self): return self.generic __instance = None def __init__(self): if Translator.__instance is None: Translator.__instance = Translator.__Translator() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) dff-1.3.0+dfsg.1/dff/ui/gui/utils/000077500000000000000000000000001217176075400164425ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/utils/CMakeLists.txt000066400000000000000000000011671217176075400212070ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py action.py menu.py menumanager.py utils.py ) dff-1.3.0+dfsg.1/dff/ui/gui/utils/__init__.py000066400000000000000000000011151217176075400205510ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["action", "menu", "utils"] dff-1.3.0+dfsg.1/dff/ui/gui/utils/action.py000066400000000000000000000060101217176075400202660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Francois Percot # from PyQt4.QtGui import QAction, QIcon from PyQt4.QtCore import SIGNAL from utils import Utils # XXX Move to action after complete portage class newAction(QAction): def __init__(self, parent, mainWindow, text, type, icon = None): super(newAction, self).__init__(mainWindow) self.__mainWindow = mainWindow self.type = type self.parent = parent if icon: self.setIcon(QIcon(icon)) self.hasOneArg = Utils.hasOneNodeArg(text, type) if text <> 0 : self.setText(str(text)) self.connect(self, SIGNAL("triggered()"), self.sendSignal) self.connect(self, SIGNAL("launchScript"), self.__mainWindow.applyModule) self.connect(self, SIGNAL("execModule"), Utils.execModule) def sendSignal(self): if self.hasOneArg and (self.parent.model.currentNode() != None) : selection = [self.parent.model.currentNode()] self.emit(SIGNAL("execModule"), self.text(), self.type, self.hasOneArg, selection) else : selection = self.parent.model.selection.getNodes() if len(selection) == 0: selection = [self.parent.model.currentNode()] # XXX here give list ? try : self.emit(SIGNAL("launchScript"), self.text(), self.type, selection) except TypeError: self.emit(SIGNAL("launchScript"), self.text(), self.type, None) class Action(QAction): def __init__(self, parent, mainWindow, text, type, icon = None): super(Action, self).__init__(mainWindow) self.__mainWindow = mainWindow self.type = type self.parent = parent if icon: self.setIcon(QIcon(icon)) self.hasOneArg = Utils.hasOneNodeArg(text, type) if text <> 0 : self.setText(str(text)) self.connect(self, SIGNAL("triggered()"), self.sendSignal) self.connect(self, SIGNAL("launchScript"), self.__mainWindow.applyModule) self.connect(self, SIGNAL("execModule"), Utils.execModule) def sendSignal(self): if self.hasOneArg and self.parent.callbackSelected : self.emit(SIGNAL("execModule"), self.text(), self.type, self.hasOneArg, self.parent.callbackSelected()) else : try : self.emit(SIGNAL("launchScript"), self.text(), self.type, self.parent.callbackSelected()) except TypeError: self.emit(SIGNAL("launchScript"), self.text(), self.type, None) dff-1.3.0+dfsg.1/dff/ui/gui/utils/menu.py000066400000000000000000000243531217176075400177670ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy MOUNIER # from PyQt4.QtGui import QMenu, QIcon, QAction, QPixmap, QMessageBox, QDialog from PyQt4.QtCore import SIGNAL, SLOT, QString, QObject, QEvent from dff.api.loader import loader from dff.api.vfs.vfs import vfs from dff.api.vfs.libvfs import VFS, VLink, Node, TagsManager from dff.api.types.libtypes import typeId, Variant, RCVariant from dff.api.events.libevents import event, EventHandler from dff.api.gui.dialog.tagmanager import TagManagerDialog from dff.ui.gui.utils.utils import Utils from dff.ui.gui.utils.action import Action from dff.ui.gui.resources.ui_bookmarkdialog import Ui_AddBookmark from dff.ui.gui.resources.ui_selection_actions import Ui_selectionActions class tagMenu(QMenu): def __init__(self, parent, main, model=None): QMenu.__init__(self, main) self.model = model self.browser = parent self.parent = parent self.tagsmanager = TagsManager.get() self.setTitle(QString("Tags")) self.connect(self, SIGNAL("aboutToShow"), self.refreshTagMenu) self.manageAction = QAction(QString(self.tr("Manage tags")), self) self.connect(self.manageAction, SIGNAL("triggered(bool)"), self.openDialog) self.connect(self, SIGNAL("triggered(QAction*)"), self.tagNodes) self.refreshTagMenu() def refreshTagMenu(self): self.addAction(self.manageAction) self.addSeparator() tags = self.tagsmanager.tags() for tag in tags: self.addAction(QString.fromUtf8(tag.name())) def openDialog(self): selected = self.getSelectedNodes() tagDialog = TagManagerDialog(self, selected) tagDialog.exec_() def tagNodes(self, action): if action != self.manageAction: name = action.text() tagname = str(unicode(name).decode('utf-8', 'replace')) selected = self.getSelectedNodes() for node in selected: if node.isTagged(tagname): node.removeTag(tagname) else: node.setTag(tagname) def getSelectedNodes(self): if self.model != None: mod = self.model else: mod = self.browser.model() checked = mod.selection.get() if len(checked) > 0: selected = mod.selection.getNodes() else: selected = [mod.currentNode()] return selected class selectionMenu(QMenu, Ui_selectionActions): def __init__(self, manager, model): QMenu.__init__(self, manager) self.setupUi(self) self.manager = manager self.model = model self.setTitle(QString(self.tr("Selection"))) self.connect(self.actionSelect_all, SIGNAL("triggered()"), self.model.selectAll) self.connect(self.actionUnselect_all, SIGNAL("triggered()"), self.model.unselectAll) self.connect(self.actionClear_selection, SIGNAL("triggered()"), self.model.selection.clear) self.addAction(self.actionSelect_all) self.addAction(self.actionUnselect_all) self.addAction(self.actionClear_selection) def selectAll(self): self.model.selectAll() class typeFilterMenu(QMenu): def __init__(self, main, model): QMenu.__init__(self, main) self.model = model self.filters = ["Image", "Video", "Text", "Audio", "Application"] self.connect(self, SIGNAL("triggered(QAction*)"), self.filterModel) self.createBaseTypeFilters() def createBaseTypeFilters(self): for filt in self.filters: self.addAction(QAction(QString(filt), self)) def filterModel(self, action): name = action.text() pattern = "(( mime in[\"" + str(name.toLower()) + "\"]))" self.model.filter(str(name), pattern) class MenuRelevant(QMenu): def __init__(self, parent, mainWindow, node = None, selectItem = None): QMenu.__init__(self, mainWindow) self.loader = loader.loader() self.callbackSelected = self.selectNode self.parent = parent self.mainWindow = mainWindow self.node = node self.Load() actions = [] def selectNode(self): return [self.node] def Load(self): self.listMenuAction = [] actions = [] self.parent.submenuRelevant.clear() if self.node: modules = self.node.compatibleModules() if len(modules): self.parent.submenuRelevant.setEnabled(True) for modname in modules: module = self.loader.modules[modname] self.parent.submenuRelevant.addAction(Action(self, self.mainWindow, modname, module.tags, module.icon)) for i in range(0, len(actions)) : if actions[i].hasOneArg : self.addAction(actions[i]) self.addSeparator() for i in range(0, len(actions)) : if not actions[i].hasOneArg : self.addAction(actions[i]) return self.parent.submenuRelevant.setEnabled(False) class MenuTags(): def __init__(self, parent, mainWindow, selectItem = None): """ Init menus""" self.parent = parent self.mainWindow = mainWindow self.selectItem = selectItem self.Load() self.parent.menuModule.connect(self.parent.menuModule, SIGNAL("aboutToShow()"), self.refreshQMenuModules) def Load(self): self.listMenuAction = [] setags = Utils.getSetTags() selist = list(setags) selist.sort() for tags in selist: if not tags == "builtins": self.listMenuAction.append(self.parent.menuModule.addMenu(MenuModules(self.parent, self.mainWindow, tags, self.selectItem))) def refreshQMenuModules(self): setags = Utils.getSetTags() for menu in self.listMenuAction: self.parent.menuModule.removeAction(menu) self.Load() class MenuModules(QMenu): def __init__(self, parent, mainWindow, tags, selectItem = None): QMenu.__init__(self, tags, parent) self.tags = tags self.__mainWindow = mainWindow self.callbackSelected = selectItem self.loader = loader.loader() self.Load() def Load(self): modules = self.loader.modules actions = [] for mod in modules : m = modules[mod] try : if m.tags == self.tags: actions.append(Action(self, self.__mainWindow, mod, self.tags, m.icon)) except AttributeError, e: pass for i in range(0, len(actions)) : if actions[i].hasOneArg : self.addAction(actions[i]) self.addSeparator() for i in range(0, len(actions)) : if not actions[i].hasOneArg : self.addAction(actions[i]) def refresh(self): self.clear() self.Load() class BookmarkManager(QObject): categories = [] def __init__(self, model): self.model = model self.vfs = vfs() self.rootNode = self.vfs.getnode('/Bookmarks/') def getSelectedNodes(self): checked = self.model.selection.get() if len(checked) > 0: selected = self.model.selection.getNodes() else: selected = [self.model.currentNode()] return selected def launch(self): selected = self.getSelectedNodes() if len(selected) == 0: QMessageBox.warning(self, self.tr("Bookmark"), self.tr("You must specify at least one node."), QMessageBox.Ok) return bookdiag = bookmarkDialog(self) bookdiag.exec_() def createCategory(self, category): if category != "": newNodeBook = BookNode(self.rootNode, str(category.toUtf8())) newNodeBook.__disown__() BookmarkManager.categories.append(category) return True else: return False class bookmarkDialog(QDialog, Ui_AddBookmark): def __init__(self, manager): super(QDialog, self).__init__() self.vfs = vfs() self.VFS = VFS.Get() self.setupUi(self) self.manager = manager self.initShape() def initShape(self): self.connect(self.newBox, SIGNAL("clicked()"), self.createCategoryBack) self.connect(self.existBox, SIGNAL("clicked()"), self.existingCategoryBack) self.connect(self, SIGNAL("accepted()"), self.acceptBookmark) for cat in BookmarkManager.categories: self.catcombo.addItem(cat) if len(BookmarkManager.categories) != 0: self.newBox.setChecked(True) self.existBox.setVisible(True) else: self.existBox.setVisible(False) def getSelectedCategory(self): if self.newBox.isChecked(): return self.catname.text() else: return self.catcombo.currentText() def createCategoryBack(self): if self.existBox.isChecked(): self.newBox.setChecked(True) self.existBox.setChecked(False) else: self.newBox.setChecked(True) def existingCategoryBack(self): if self.newBox.isChecked(): self.existBox.setChecked(True) self.newBox.setChecked(False) else: self.existBox.setChecked(True) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) else: QDialog.changeEvent(self, event) def acceptBookmark(self): selectedCategory = self.getSelectedCategory() # Check is is new or existing category try: i = BookmarkManager.categories.index(selectedCategory) except ValueError: if not self.manager.createCategory(selectedCategory): return selectedBookName = selectedCategory selectedBookmark = self.vfs.getnode('/Bookmarks/' + str(selectedBookName.toUtf8())) selected = self.manager.getSelectedNodes() for node in selected: if node: n = VLink(node, selectedBookmark) n.__disown__() e = event() e.thisown = False e.value = RCVariant(Variant(selectedBookmark)) self.VFS.notify(e) class BookNode(Node): def __init__(self, parent, name): Node.__init__(self, name, 0, parent, None) self.__disown__() self.setDir() def icon(self): return (":bookmark.png") dff-1.3.0+dfsg.1/dff/ui/gui/utils/menumanager.py000066400000000000000000000236411217176075400213210ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # from PyQt4.QtGui import QMenu, QIcon, QWidget, QCursor, QApplication, QAction, QMessageBox, QImage from PyQt4.QtCore import SIGNAL, SLOT, QObject, QEvent, QString, QBuffer, QByteArray from dff.api.loader import loader from dff.api.vfs.libvfs import VFS, ABSOLUTE_ATTR_NAME from dff.api.types.libtypes import typeId, Variant from dff.api.taskmanager.taskmanager import TaskManager from dff.api.taskmanager.processus import ProcessusManager from dff.api.gui.dialog.extractor import Extractor from dff.ui.gui.utils.utils import Utils from dff.ui.gui.utils.action import newAction, Action from dff.ui.gui.utils.menu import tagMenu, selectionMenu, BookmarkManager from dff.ui.gui.resources.ui_nodeactions import Ui_nodeActions modulePriority = {} class MenuManager(QWidget, Ui_nodeActions): def __init__(self, selection, listmodel): super(QWidget, self).__init__() self.setupUi(self) self.processusManager = ProcessusManager() self.loader = loader.loader() self.lmodules = self.loader.modules self.taskmanager = TaskManager() self.mainwindow = QApplication.instance().mainWindow self.createActions() self.checkedSelection = selection self.selection = None self.model = listmodel self.bookManager = BookmarkManager(self.model) def createActions(self): self.extractor = Extractor(self.mainwindow) self.connect(self.extractor, SIGNAL("filled"), self.launchExtract) self.actionOpen.setParent(self.mainwindow) self.actionOpen_in_new_tab.setParent(self.mainwindow) self.connect(self.actionOpen, SIGNAL("triggered()"), self.openDefault) self.connect(self.actionOpen_in_new_tab, SIGNAL("triggered()"), self.openAsNewTab) self.connect(self.actionOpen_parent_folder, SIGNAL("triggered()"), self.openParentFolder) self.connect(self.actionHex_viewer, SIGNAL("triggered()"), self.launchHexedit) self.connect(self.actionExtract, SIGNAL("triggered()"), self.extractNodes) self.connect(self.actionBookmark, SIGNAL("triggered()"), self.bookmark) def createMenu(self): nodeclicked = self.model.currentNode() self.mainmenu = QMenu(self.mainwindow) self.selection = self.model.currentNode() self.setOpenRelevant() self.setOpenWith() self.mainmenu.addAction(self.actionOpen) self.mainmenu.addAction(self.actionOpen_with) self.mainmenu.addAction(self.actionOpen_in_new_tab) self.mainmenu.addAction(self.actionOpen_parent_folder) if nodeclicked.isDir() or nodeclicked.hasChildren(): self.actionOpen_parent_folder.setVisible(False) self.actionOpen_parent_folder.setEnabled(False) self.actionOpen_in_new_tab.setVisible(True) self.actionOpen_in_new_tab.setEnabled(True) else: self.actionOpen_in_new_tab.setVisible(False) self.actionOpen_in_new_tab.setEnabled(False) self.actionOpen_parent_folder.setVisible(True) self.actionOpen_parent_folder.setEnabled(True) self.mainmenu.addSeparator() selection = selectionMenu(self, self.model) self.mainmenu.addMenu(selection) tags = tagMenu(self, self.mainwindow, self.model) self.actionTags.setMenu(tags) self.mainmenu.addAction(self.actionTags) self.mainmenu.addAction(self.actionBookmark) self.bookseparator = self.mainmenu.addSeparator() self.mainmenu.addAction(self.actionHex_viewer) self.mainmenu.addAction(self.actionExtract) self.mainmenu.popup(QCursor.pos()) self.mainmenu.show() def setOpenRelevant(self): if self.selection != None: node = self.selection modules = node.compatibleModules() if len(modules): relevant = QMenu() for modname in modules: module = self.loader.modules[modname] relevant.addAction(newAction(self, self.mainwindow, modname, module.tags, module.icon)) self.actionOpen.setMenu(relevant) def setOpenWith(self): owmenu = QMenu() setags = Utils.getSetTags() selist = list(setags) selist.sort() owmenu.addAction(self.mainwindow.actionBrowse_modules) owmenu.addSeparator() for tags in selist: if not tags == "builtins": action = QAction(QString(tags), self.mainwindow) menu = self.getMenuFromModuleTag(tags) action.setMenu(menu) owmenu.addAction(action) self.actionOpen_with.setMenu(owmenu) def getMenuFromModuleTag(self, tagname): menu = QMenu() modules = self.loader.modules for mod in modules : m = modules[mod] try : if m.tags == tagname: menu.addAction(newAction(self, self.mainwindow, mod, tagname, m.icon)) # actions.append(newAction(self, self.__mainWindow, mod, self.tags, m.icon)) except AttributeError, e: pass return menu ##################################### # CALLBACKS ##################################### def selectAll(self): self.model.selectAll() def openAsNewTab(self): node = self.model.currentNode() self.mainwindow.addNodeBrowser(node) def openParentFolder(self): node = self.model.currentNode().parent() self.mainwindow.addNodeBrowser(node) def launchHexedit(self): node = self.model.currentNode() conf = self.loader.get_conf("hexadecimal") errnodes = "" # for node in nodes: if node.size(): try: arg = conf.generate({"file": node}) self.taskmanager.add("hexadecimal", arg, ["thread", "gui"]) except RuntimeError: errnodes += node.absolute() + "\n" else: errnodes += node.absolute() + "\n" if len(errnodes): msg = QMessageBox(self) msg.setWindowTitle(self.tr("Empty files")) msg.setText(self.tr("the following nodes could not be opened with Hex viewer because they are either empty or folders\n")) msg.setIcon(QMessageBox.Warning) msg.setDetailedText(errnodes) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def bookmark(self): self.bookManager.launch() def extractNodes(self): if len(self.model.selection.get()) == 0: nodes = [self.model.currentNode()] else: nodes = self.model.selection.getNodes() self.extractor.launch(nodes) def launchExtract(self): args = self.extractor.getArgs() conf = self.loader.get_conf("extract") try: margs = conf.generate(args) self.taskmanager.add("extract", margs, ["thread", "gui"]) except RuntimeError as e: msg = QMessageBox(self) msg.setWindowTitle(self.tr("Extraction Error")) msg.setText(self.tr("An issue occured while extracting \n")) msg.setIcon(QMessageBox.Warning) msg.setDetailedText(str(e)) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def openDefault(self, node = None): if not node: node = self.model.currentNode() mods = node.compatibleModules() if len(mods): for mod in mods: if "Viewers" in self.lmodules[mod].tags: break try: priority = modulePriority[mod] except KeyError: modulePriority[mod] = 0 priority = 0 if self.lmodules[mod]: conf = self.lmodules[mod].conf arguments = conf.arguments() marg = {} for argument in arguments: if argument.type() == typeId.Node: marg[argument.name()] = node args = conf.generate(marg) if self.processusManager.exist(self.lmodules[mod], args): mbox = QMessageBox(QMessageBox.Warning, self.tr("Module already applied"), self.tr("This module was already applied with the same configuration ! Do you want to apply it again ?"), QMessageBox.Yes | QMessageBox.No, self) reply = mbox.exec_() if reply == QMessageBox.No: return else: if not priority: mbox = QMessageBox(QMessageBox.Question, self.tr("Apply module"), self.tr("Do you want to apply module ") + str(mod) + self.tr(" on this node ?"), QMessageBox.Yes | QMessageBox.No, self) mbox.addButton(self.tr("Always"), QMessageBox.AcceptRole) reply = mbox.exec_() if reply == QMessageBox.No: return elif reply == QMessageBox.AcceptRole: modulePriority[mod] = 1 self.taskmanager.add(mod, args, ["thread", "gui"]) return else: errnodes = "" if node.size(): conf = self.lmodules["hexadecimal"].conf try: arg = conf.generate({"file": node}) self.taskmanager.add("hexadecimal", arg, ["thread", "gui"]) except RuntimeError: errnodes += node.absolute() + "\n" else: errnodes += node.absolute() + "\n" if len(errnodes): msg = QMessageBox(self) msg.setWindowTitle(self.tr("Empty files")) msg.setText(self.tr("the following nodes could not be opened with Hex viewer because they are either empty or folders\n")) msg.setIcon(QMessageBox.Warning) msg.setDetailedText(errnodes) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) # self.mainwindow.changeEvent(event) # self.menuModule.setTitle(self.actionOpen_with.text()) # self.submenuRelevant.setTitle(self.actionRelevant_module.text()) # self.model.translation() # self.treeModel.translation() else: QWidget.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/ui/gui/utils/utils.py000066400000000000000000000074661217176075400201710ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Francois Percot # from types import StringType from PyQt4.QtGui import QMessageBox from dff.api.vfs.libvfs import Node from dff.api.loader import loader from dff.api.taskmanager.taskmanager import TaskManager from dff.api.types.libtypes import typeId, ConfigManager, Argument, Parameter class Utils(): def __init__(self): pass @staticmethod def getSetTags(): lmodules = loader.loader().modules setags = set() for mod in lmodules: try: setags.add(lmodules[mod].tags) except AttributeError: pass try : setags.remove('') except KeyError: pass return setags @staticmethod def formatSize(size): lsize = [" KB", " MB", " GB", "TB", "PB", "EB"] if size < 1024 : return str(size) + " bytes" for i in range(0, len(lsize)): tmp_size = size / 1024 if (tmp_size < 1024): return str(tmp_size) + lsize[i] else: size = tmp_size return str(tmp_size) + lsize[i] @staticmethod def getPath(node): if not node : return "" if node.name() == "": return str("/") else : return str(node.absolute()) @staticmethod def getValue(arg): if arg <> None: if arg.type == "int": return str(arg.get_int()) elif arg.type == "string": return str(arg.get_string()) elif arg.type == "node": node = arg.get_node() return Utils.getPath(node) elif arg.type == "bool" : return str(arg.get_bool()) elif arg.type == "path" : return str(arg.get_path().path) return "TYPE NOT DEFINE" @staticmethod def getArgsDriver(driver_name): l = loader.loader() return l.getdriver(driver_name).conf.descr_l @staticmethod def getArgs(modules_name): l = loader.loader() if type(modules_name) == StringType : return l.modules[modules_name].conf.arguments() else : return None @staticmethod def hasOneNodeArg(module, type): configs = ConfigManager.Get() mconf = configs.configByName(str(module)) if len(mconf.arguments()) > 1: return None argsnode = mconf.argumentsByType(typeId.Node) required = mconf.argumentsByRequirementType(Argument.Required) if len(argsnode) == 0: return None if len(argsnode) == 1: return argsnode[0].name() return None @staticmethod def execModule(name, type, nameArg, listNode): tm = TaskManager() configs = ConfigManager.Get() mconf = configs.configByName(str(name)) arg = mconf.argumentByName(nameArg) if isinstance(listNode, Node): args = mconf.generate({arg.name(): listNode}) tm.add(str(name), args, ["thread", "gui"]) else: if arg.inputType() == Argument.List: args = mconf.generate({arg.name(): listNode}) tm.add(str(name), args, ["thread", "gui"]) else: for i in listNode: args = mconf.generate({arg.name(): i}) tm.add(str(name), args, ["thread", "gui"]) dff-1.3.0+dfsg.1/dff/ui/gui/widget/000077500000000000000000000000001217176075400165655ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/ui/gui/widget/CMakeLists.txt000066400000000000000000000013311217176075400213230ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( __init__.py help.py taskmanager.py SelectMimeTypes.py mime_types.py modules.py modulesmanager.py interpreter.py shell.py stdio.py preview.py ) dff-1.3.0+dfsg.1/dff/ui/gui/widget/SelectMimeTypes.py000066400000000000000000000140641217176075400222200ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon from PyQt4 import QtCore, QtGui from PyQt4.QtCore import Qt, SIGNAL from PyQt4.QtGui import QWidget, QLabel, QPushButton, QDialog, QTableWidget, QTableWidgetItem, QAbstractItemView, QIcon, QTreeWidgetItem, QCheckBox from dff.api.datatype.mimetree import MimeTree from dff.ui.gui.widget.mime_types import IndexMimeTypes class RootCheckBox(QCheckBox): def __init__(self): QCheckBox.__init__(self) self.children = [] self.connect(self, SIGNAL("clicked()"), self.updateChildren) def addChild(self, child): self.children.append(child) def updateChildren(self): state = self.checkState() for child in self.children: if child.isEnabled(): child.setCheckState(state) def update(self, val): checked = 0 for child in self.children: if child.checkState() == Qt.Checked: checked += 1 if checked == 0: self.setCheckState(Qt.Unchecked) elif self.checkState() == Qt.Unchecked: self.setCheckState(Qt.Checked) class MimeTypesTree(): def __init__(self, tree): self.mm = MimeTree() self.tree = tree self.typeItems = [] self.populate() def populate(self): self.tree.connect(self.tree, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self.clicked) self.tree.connect(self.tree, SIGNAL("itemPressed(QTreeWidgetItem *, int)"), self.clicked) for mimetype, mimecontent in self.mm.mimetypes.iteritems(): mimetypeItem = QTreeWidgetItem(self.tree, [mimetype]) mimetypeItem.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) mimetypeItem.setCheckState(0, Qt.Unchecked) rCheckBox = RootCheckBox() rCheckBox.setEnabled(False) self.tree.setItemWidget(mimetypeItem, 1, rCheckBox) self.typeItems.append(mimetypeItem) for value in mimecontent: filetypeItem = QTreeWidgetItem(mimetypeItem, [value]) filetypeItem.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) filetypeItem.setCheckState(0, Qt.Unchecked) checkBox = QCheckBox() checkBox.setEnabled(False) rCheckBox.addChild(checkBox) rCheckBox.connect(checkBox, SIGNAL("stateChanged(int)"), rCheckBox.update) self.tree.setItemWidget(filetypeItem, 1, checkBox) self.tree.resizeColumnToContents(0) def setCheckStateOfChildren(self, item, column, checked): children = item.childCount() for i in range(0, children): if checked == Qt.Checked: self.tree.itemWidget(item.child(i), 1).setEnabled(True) else: self.tree.itemWidget(item.child(i), 1).setCheckState(False) self.tree.itemWidget(item.child(i), 1).setEnabled(False) item.child(i).setCheckState(0, checked) def isAllChildren(self, item, column): children = item.childCount() checked = 0 for i in range(0, children): if item.child(i).checkState(column) == Qt.Checked: checked += 1 if checked == 0: self.tree.itemWidget(item, 1).setEnabled(False) item.setCheckState(0, Qt.Unchecked) elif item.checkState(column) == Qt.Unchecked: self.tree.itemWidget(item, 1).setEnabled(True) item.setCheckState(0, Qt.Checked) def clicked(self, item, column): if column == 0: if item.childCount() != 0: if item.checkState(0) == Qt.Checked: self.tree.itemWidget(item, 1).setEnabled(True) self.setCheckStateOfChildren(item, column, Qt.Checked) else: self.tree.itemWidget(item, 1).setEnabled(False) self.setCheckStateOfChildren(item, column, Qt.Unchecked) else: parent = item.parent() if parent != None and parent.childCount() != 0: self.isAllChildren(parent, column) if item.checkState(0) == Qt.Checked: self.tree.itemWidget(item, 1).setEnabled(True) else: self.tree.itemWidget(item, 1).setEnabled(False) self.tree.itemWidget(item, 1).setCheckState(False) def createGroupBox(self, items): gb = QGroupBox(items["type"]) gb.setCheckable(True) gb.setChecked(False) vbox = QVBoxLayout() for item in items["value"]: button = QCheckBox(item) vbox.addWidget(button) vbox.addStretch(1) gb.setLayout(vbox) return gb def selectedItems(self): selected = [] for typeItem in self.typeItems: i = 0 if typeItem.checkState(0) == Qt.Checked: mimetype = str(typeItem.text(0)) children = typeItem.childCount() tmplist = [] ccount = 0 for i in range(0, children): child = typeItem.child(i) if child.checkState(0) == Qt.Checked: ccount += 1 if not child.isDisabled(): text = mimetype + "/" + str(child.text(0)) tmplist.append(text) if ccount == children: selected.append(mimetype) else: selected.extend(tmplist) return selected dff-1.3.0+dfsg.1/dff/ui/gui/widget/__init__.py000066400000000000000000000012351217176075400206770ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ["interpreter", "shell", "env", "modules", "taskmanager", "stdio", "postprocessconfig", "postprocessstate"] dff-1.3.0+dfsg.1/dff/ui/gui/widget/help.py000066400000000000000000000103341217176075400200700ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from PyQt4.QtGui import QIcon, QHBoxLayout, QPushButton, QWidget, QGridLayout, QVBoxLayout, QTextBrowser, QSplitter, QSizePolicy, QDockWidget, QMessageBox from PyQt4.QtCore import QRect, QSize, Qt, SIGNAL, QTimer, QThread, QString, QUrl, QVariant, QStringList, QFile from PyQt4.QtWebKit import QWebView, QWebPage, QWebFrame from PyQt4.QtHelp import QHelpEngine class Help(QDockWidget): def __init__(self, parent=None, path=None): QDockWidget.__init__(self, parent) self.name = self.tr("Help") self.setFloating(False) self.setFeatures(QDockWidget.NoDockWidgetFeatures) self.__mainWidget = QSplitter(Qt.Horizontal) self.__uname = QWidget() mainWidgetLayout = QVBoxLayout(self.__uname) mainWidgetLayout.setContentsMargins(0, 0, 0, 0) # create helper + search engine self.__helper = QHelpEngine(path, self) if not self.__helper.setupData() is True: dialog = QMessageBox() msg = QString(self.tr("An error occurred while setting help engine up :\n")) msg += (self.__helper.error() + "\n") msg += self.tr("It might mean that the format of your help file is not correct.\n") msg += self.tr("You can check on-line help at http://wiki.digital-forensic.org") dialog.setText(msg) dialog.setIcon(QMessageBox.Warning) dialog.setWindowTitle(self.tr("Error while loading help")) dialog.exec_() return self.__toc = self.__helper.contentWidget() self.__helpBrowser = HelpBrowser(self.__helper) # build main widget self.__toolbar = QWidget() self.__toolbarLayout = QHBoxLayout(self.__toolbar) home = QPushButton(QIcon(":home.png"), "") previous = QPushButton(QIcon(":previous.png"), "") next = QPushButton(QIcon(":next.png"), "") # building toolbar self.__toolbarLayout.addWidget(home) self.__toolbarLayout.addWidget(previous) self.__toolbarLayout.addWidget(next) self.__toolbarLayout.setContentsMargins(0, 0, 0, 0) mainWidgetLayout.addWidget(self.__toolbar) mainWidgetLayout.addWidget(self.__helpBrowser) self.__mainWidget.insertWidget(0, self.__toc) self.__mainWidget.insertWidget(1, self.__uname) self.__mainWidget.setStretchFactor(1, 1) self.setWidget(self.__mainWidget) #connecting `previous`, `home` and `next` buttons self.connect(next, SIGNAL("clicked(bool)"), self.__helpBrowser.nextPage) self.connect(previous, SIGNAL("clicked(bool)"), self.__helpBrowser.prevPage) self.connect(home, SIGNAL("clicked(bool)"), self.__helpBrowser.goHome) self.connect(self.__helper.contentWidget(), SIGNAL("linkActivated(const QUrl &)"), self.__helpBrowser.setSource) class HelpBrowser(QTextBrowser): def __init__(self, help_engine, parent=None): super(HelpBrowser, self).__init__(parent) self.__helpEngine = help_engine self.setSource(QUrl("qthelp://arxsys.fr.digital_forensics_framework.1_0/doc/main_page.html")) #param checked is not used def prevPage(self, checked): self.backward() #param checked is not used def nextPage(self, checked): self.forward() # param checked not used def goHome(self, checked): self.setSource(QUrl("qthelp://arxsys.fr.digital_forensics_framework.1_0/doc/main_page.html")) def loadResource(self, type, url): if url.scheme() == "qthelp": return self.__helpEngine.fileData(url) return super(HelpBrowser, self).loadResource(type, url) dff-1.3.0+dfsg.1/dff/ui/gui/widget/interpreter.py000066400000000000000000000276371217176075400215210ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import os, sys, inspect, threading import signal; signal.signal(signal.SIGINT, signal.SIG_DFL) from code import InteractiveInterpreter from PyQt4.QtGui import QAction, QApplication, QTextEdit, QTextCursor , QPalette, QColor, QBrush, QHBoxLayout, QIcon, QDockWidget from PyQt4.QtCore import Qt, QString, QThread, QSemaphore, SIGNAL, QObject, QEvent from dff.ui.redirect import RedirectIO from dff.ui.gui.resources.ui_interpreter import Ui_Interpreter class InterpreterView(QTextEdit, InteractiveInterpreter, Ui_Interpreter): def __init__(self, parent=None, log=''): QTextEdit.__init__(self, parent) InteractiveInterpreter.__init__(self, None) self.setupUi(self) self.name = self.windowTitle() self.log = log or '' self.__canwrite = True if parent is None: self.eofKey = Qt.Key_D else: self.eofKey = None self.line = QString() self.lines = [] self.point = 0 self.more = 0 self.reading = 0 self.history = [] self.pointer = 0 self.cursor_pos = 0 self.fgcolor = QColor("white") self.selcolor = QColor("green") self.strcolor = QColor("red") self.redirect = RedirectIO() self.sig = "Iputtext" self.connect(self, SIGNAL(self.sig), self.puttext) self.redirect.addparent(self, ["dff.ui.gui.widget.interpreter", "code", "__console__", "pydoc"]) self.ps1 = ">>> " self.ps2 = "... " self.writePrompt() api_imports = ["from dff.api.types.libtypes import Variant, VList, VMap, vtime, typeId, Argument, Parameter, ConfigManager, Constant, Config, Path", "from dff.api.vfs.vfs import vfs", "from dff.api.vfs.libvfs import VFS, FileMapping, ABSOLUTE_ATTR_NAME, RELATIVE_ATTR_NAME", "from dff.api.filters.libfilters import Filter", "from dff.api.search.libsearch import Search", "from dff.api.events.libevents import EventHandler, event", "from dff.api.datatype.libdatatype import DataTypeManager, DataTypeHandler", "from dff.api.loader.loader import loader", "from dff.api.module.module import Module, Script", "from dff.api.taskmanager.taskmanager import TaskManager"] for api_import in api_imports: self.more = self.runsource(api_import) def writePrompt(self): self.write('\n') self.write(self.ps1) def write(self, str): self.redirect.write(str) def puttext(self, text): cursor = self.textCursor() cursor.movePosition(QTextCursor.End) pos1 = cursor.position() cursor.insertText(text) self.cursor_pos = cursor.position() self.setTextCursor(cursor) self.ensureCursorVisible() cursor.setPosition(pos1, QTextCursor.KeepAnchor) format = cursor.charFormat() format.setForeground(QBrush(self.fgcolor)) cursor.setCharFormat(format) def get_interpreter(self): """ Return the interpreter object """ return self def moveCursor(self, operation, mode=QTextCursor.MoveAnchor): """ Convenience function to move the cursor This function will be present in PyQT4.2 """ cursor = self.textCursor() cursor.movePosition(operation, mode) self.setTextCursor(cursor) def flush(self): pass def isatty(self): return 1 def clear(self): """ Clear """ def readline(self): self.reading = 1 self.__clearLine() self.moveCursor(QTextCursor.End) while self.reading: QtGui.qApp.processEvents() if self.line.length() == 0: return '\n' else: return str(self.line) def writelines(self, text): """ Simulate stdin, stdout, and stderr. """ map(self.write, text) def fakeUser(self, lines): """ Simulate a user: lines is a sequence of strings, (Python statements). """ for line in lines: self.line = QString(line.rstrip()) self.write(self.line) self.write('\n') self.run() def runsource_callback(self, source): self.__canwrite = False self.more = self.runsource(source) if self.more: self.write(self.ps2) else: self.write(self.ps1) self.lines = [] self.__clearLine() self.__canwrite = True def run(self): self.pointer = 0 self.history.append(QString(self.line)) try: self.lines.append(str(self.line)) except Exception,e: print e source = '\n'.join(self.lines) thread = threading.Thread(target=self.runsource_callback, args=(source, )) thread.start() #self.more = self.runsource(source) #if self.more: # self.write(self.ps2) #else: # self.write(self.ps1) # self.lines = [] #self.__clearLine() def __clearLine(self): """ Clear input line buffer """ self.line.truncate(0) self.point = 0 def __insertText(self, text): """ Insert text at the current cursor position. """ self.line.insert(self.point, text) self.point += text.length() cursor = self.textCursor() cursor.insertText(text) self.color_line() def keyPressEvent(self, e): """ Handle user input a key at a time. """ text = e.text() key = e.key() if not self.__canwrite: e.ignore() return if key == Qt.Key_Backspace: if self.point: cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) cursor.removeSelectedText() self.color_line() self.point -= 1 self.line.remove(self.point, 1) elif key == Qt.Key_Delete: cursor = self.textCursor() cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) cursor.removeSelectedText() self.color_line() self.line.remove(self.point, 1) elif key == Qt.Key_Return or key == Qt.Key_Enter: self.write('\n') if self.reading: self.reading = 0 else: self.run() elif key == Qt.Key_Tab: self.__insertText(text) elif key == Qt.Key_Left: if self.point : self.moveCursor(QTextCursor.Left) self.point -= 1 elif key == Qt.Key_Right: if self.point < self.line.length(): self.moveCursor(QTextCursor.Right) self.point += 1 elif key == Qt.Key_Home: cursor = self.textCursor () cursor.setPosition(self.cursor_pos) self.setTextCursor (cursor) self.point = 0 elif key == Qt.Key_End: self.moveCursor(QTextCursor.EndOfLine) self.point = self.line.length() elif key == Qt.Key_Up: if len(self.history): if self.pointer == 0: self.pointer = len(self.history) self.pointer -= 1 self.__recall() elif key == Qt.Key_Down: if len(self.history): self.pointer += 1 if self.pointer == len(self.history): self.pointer = 0 self.__recall() elif text.length(): self.__insertText(text) return else: e.ignore() def __recall(self): """ Display the current item from the command history. """ cursor = self.textCursor () cursor.select( QTextCursor.LineUnderCursor ) cursor.removeSelectedText() if self.more: self.write(self.ps2) else: self.write(self.ps1) self.__clearLine() self.__insertText(self.history[self.pointer]) def mousePressEvent(self, e): """ Keep the cursor after the last prompt. """ if e.button() == Qt.LeftButton: self.moveCursor(QTextCursor.End) def contentsContextMenuEvent(self,ev): """ Suppress the right button context menu. """ pass def dragEnterEvent(self, event): event.setAccepted(event.mimeData().hasFormat("text/plain")) def dragMoveEvent(self, event): if (event.mimeData().hasFormat("text/plain")): event.setDropAction(QtCore.Qt.MoveAction) event.accept() else: event.ignore() def dropEvent(self, event): if(event.mimeData().hasFormat("text/plain")): line = event.mimeData().text() self.__insertTextAtEnd(line) self.setFocus() event.setDropAction(QtCore.Qt.MoveAction) event.accept() else: event.ignore() def color_line(self): """ Color the current line """ cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine) newpos = cursor.position() pos = -1 while(newpos != pos): cursor.movePosition(QTextCursor.NextWord) pos = newpos newpos = cursor.position() cursor.select(QTextCursor.WordUnderCursor) word = str(cursor.selectedText ().toAscii()) if(not word) : continue color = self.get_color(word) format = cursor.charFormat() format.setForeground(QBrush(color)) cursor.setCharFormat(format) keywords = set(["and", "del", "from", "not", "while", "as", "elif", "global", "or", "with", "assert", "else", "if", "pass", "yield", "break", "except", "import", "print", "class", "exec", "in", "raise", "continue", "finally", "is", "return", "def", "for", "lambda", "try"]) def get_color(self, word): stripped = word.strip() if(stripped in self.keywords): return (self.selcolor) elif(self.is_python_string(stripped)): return (self.strcolor) else: return (self.fgcolor) def is_python_string(self, str): """ Return True if str is enclosed by a string mark """ return ((str.startswith("'''") and str.endswith("'''")) or (str.startswith('"""') and str.endswith('"""')) or \ (str.startswith("'") and str.endswith("'")) or (str.startswith('"') and str.endswith('"'))) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.writePrompt() else: QTextEdit.changeEvent(self, event) class InterpreterActions(QObject): def __init__(self, mainwindow): QObject.__init__(self) self.mainwindow = mainwindow def create(self): self.mainwindow.addSingleDock("Interpreter", InterpreterView) dff-1.3.0+dfsg.1/dff/ui/gui/widget/mime_types.py000066400000000000000000000037631217176075400213230ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon class IndexMimeTypes(): def __init__(self): self.types = {"application/images" : IndexMimeTypes.images, "application/videos" : IndexMimeTypes.videos, "application/animation" : IndexMimeTypes.animation, "application/document": IndexMimeTypes.document, "application/mail" : IndexMimeTypes.mail, "application/audio" : IndexMimeTypes.audio, "application/pgp" : IndexMimeTypes.pgp, "application/package" : IndexMimeTypes.package, "application/registry" : IndexMimeTypes.registry, "application/archiver": IndexMimeTypes.archiver, "application/vm" : IndexMimeTypes.vm, } def images(self): return ["art", "gif", "jpg", "png", "bmp", "tif"] def videos(self): return ["avi", "mov", "mpg"] def animation(self): return ["fws"] def document(self): return ["doc", "pdf", "txt", "wpc", "pdf", "htm"] def mail(self): return ["pst", "ost", "dbx", "idx", "mbx", "aolmail"] def audio(self): return ["wav", "ra"] def pgp(self): return ["pgd", "pgp", "txt"] def package(self): return ["rpm"] def registry(self): return ["dat"] def archiver(self): return ["zip"] def vm(self): return ["java"] dff-1.3.0+dfsg.1/dff/ui/gui/widget/modules.py000066400000000000000000000054561217176075400206210ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER # from PyQt4.QtGui import QAction, QApplication, QDockWidget, QIcon, QHBoxLayout, QPushButton, QTabWidget, QTreeWidget, QTreeWidgetItem, QWidget, QDialog, QGridLayout, QLabel, QComboBox, QMessageBox from PyQt4.QtCore import QRect, QSize, Qt, SIGNAL, QEvent from dff.api.loader import loader from dff.api.taskmanager.taskmanager import TaskManager from dff.api.types.libtypes import typeId from dff.ui.gui.utils.utils import Utils from dff.ui.gui.resources.ui_modules import Ui_Modules class Modules(QTreeWidget, Ui_Modules): def __init__(self, parent): QTreeWidget.__init__(self, parent) self.name = "Modules" self.tm = TaskManager() self.loader = loader.loader() self.setupUi(self) self.initTreeModule() def initTreeModule(self): self.itemModuleDic = dict() self.itemListArgDic = dict() self.itemArgDic = dict() self.itemListResDic = dict() self.itemResDic = dict() def LoadInfoModules(self): modules = self.loader.modules for mod in modules : try : itemModule = self.itemModuleDic[mod] except KeyError: itemModule = QTreeWidgetItem(self) self.itemModuleDic[mod] = itemModule itemModule.setText(0, str(mod)) itemConfig = QTreeWidgetItem(itemModule) itemConfig.setText(0, "Config") conf = modules[mod].conf args = conf.arguments() for arg in args: itemConfKey = QTreeWidgetItem(itemConfig) itemConfKey.setText(0, "var") itemConfKey.setText(1, arg.name()) itemConfKey.setText(4, typeId.Get().typeToName(arg.type())) if len(arg.description()): itemConfKey.setText(3, arg.description()) parameters = arg.parameters() if len(parameters): itemConfKey.setText(2, str(parameters)) def deleteInfoModule(self): self.clear() def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) else: QTreeWidget.changeEvent(self, event) dff-1.3.0+dfsg.1/dff/ui/gui/widget/modulesmanager.py000066400000000000000000000113371217176075400221470ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER # from PyQt4.QtGui import QDialog, QWidget, QVBoxLayout, QSplitter, QStackedWidget, QTabWidget, QListWidget, QIcon, QPixmap, QListView, QListWidgetItem from PyQt4.QtCore import Qt, SIGNAL from dff.api.loader import loader from dff.api.gui.widget.generateModuleShape import moduleShapeGenerator from dff.ui.gui.utils.utils import Utils from dff.ui.gui.resources.ui_modulegeneratorwidget import Ui_moduleGeneratorWidget from dff.ui.gui.resources.ui_modulebrowserdialog import Ui_moduleBrowser class browserDialog(QDialog, Ui_moduleBrowser): def __init__(self, main): QDialog.__init__(self) Ui_moduleGeneratorWidget.__init__(self) self.setupUi(self) self.main = main self.browser = modulesManager(self) self.lcontainer.addWidget(self.browser) class modulesManager(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.name = "moduleManager" self.stacked = stackedWidget(self) self.initWidget() self.initShape() def initWidget(self): self.toolbox = tabBox(self) def initShape(self): self.mainvbox = QVBoxLayout() self.splitter = QSplitter() self.splitter.setOrientation(Qt.Vertical) self.splitter.addWidget(self.toolbox) self.splitter.addWidget(self.stacked) self.mainvbox.addWidget(self.splitter) self.setLayout(self.mainvbox) cw = self.toolbox.currentWidget() cw.setCurrentItem(cw.item(0)) cw.emit(SIGNAL("itemPressed(QListWidgetItem *)"), cw.item(0)) def execute(self): args = self.stacked.currentWidget().validateModule() self.stacked.currentWidget().launchTask(args) class stackedWidget(QStackedWidget): def __init__(self, parent): QStackedWidget.__init__(self) self.previousw = None class tabBox(QTabWidget): def __init__(self, parent): QTabWidget.__init__(self) self.stacked = parent.stacked self.browser = parent self.tags = Utils.getSetTags() self.itemWidgets = [] self.fillToolBox() def fillToolBox(self): for tag in self.tags: if tag != "builtins": itemw = itemWidget(tag, self) self.addTab(itemw.getList(), tag) class listWidget(QListWidget): def __init__(self, stacked): QListWidget.__init__(self) self.stacked = stacked self.loader = loader.loader() self.setResizeMode(QListView.Adjust) self.setMovement(QListView.Static) self.setViewMode(QListView.IconMode) self.connect(self, SIGNAL("itemPressed(QListWidgetItem *)"), self.GMShape) def generator(self, name, tags): return moduleShapeGenerator(name, tags) def GMShape(self, item): module = self.loader.modules[str(item.text())] if self.stacked.previousw: self.stacked.removeWidget(self.stacked.previousw) self.stacked.previousw.close() del self.stacked.previousw msgen = self.generator(module.name, module.tags) self.stacked.previousw = msgen self.stacked.addWidget(self.stacked.previousw) class itemWidget(): def __init__(self, tag, box): self.tag = tag self.box = box self.browser = box.browser self.stacked = box.stacked self.loader = loader.loader() self.itemodules = [] self.getModules() self.listw = None def getModules(self): self.modules = self.loader.modules for mod in self.modules : m = self.modules[mod] try : if m.tags == self.tag: self.itemodules.append(m) except AttributeError, e: pass def getList(self): if not self.listw: self.listw = listWidget(self.stacked) for mod in self.itemodules: if mod.icon: icon = QIcon(QPixmap(mod.icon)) else: icon = QIcon(QPixmap(":module2.png")) item = QListWidgetItem(icon, mod.name, self.listw) self.listw.addItem(item) return self.listw else: return self.listw dff-1.3.0+dfsg.1/dff/ui/gui/widget/preview.py000066400000000000000000000070431217176075400206240ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # from PyQt4.QtGui import QStackedWidget, QIcon, QPixmap, QApplication, QWidget, QToolBar, QVBoxLayout from PyQt4.QtCore import QRect, QSize, Qt, SIGNAL, QEvent from dff.api.loader.loader import loader class Preview(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.layout = QVBoxLayout(self) self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.stack = QStackedWidget(self) self.toolBar = QToolBar(self) self.connect(self.toolBar, SIGNAL('actionTriggered(QAction*)'), self.clicked) self.layout.addWidget(self.toolBar) self.layout.addWidget(self.stack) self.setLayout(self.layout) self.__mainWindow = parent self.name = "Preview" self.loader = loader() self.lmodules = self.loader.modules void = QWidget() self.previousWidget = void self.stack.addWidget(void) self.setWindowIcon(QIcon(QPixmap(":viewer.png"))) self.retranslateUi(self) self.previousNode = None self.currentNode = None self.mustUpdate = True def updateCheckState(self, state): self.mustUpdate = state if state: self.setDisabled(False) self.update(self.currentNode) else: self.setDisabled(True) def clicked(self, action): if self.isVisible() and self.mustUpdate and self.currentNode and self.currentNode.size(): self.display(self.currentNode, str(action.text())) def update(self, node): if self.isVisible() and self.mustUpdate and node and node.size(): if self.previousNode == node.this: return else: self.toolBar.clear() self.toolBar.addAction("hexadecimal") self.previousNode = node.this self.currentNode = node previewModules = [] compat = node.compatibleModules() if len(compat): for module in compat: if "Viewers" in self.lmodules[module].tags: previewModules.append(module) self.toolBar.addAction(module) if not len(previewModules): self.display(node, "hexadecimal") else: self.display(node, str(previewModules[0])) elif node and node.size(): self.currentNode = node def display(self, node, previewModule): try: args = {} args["file"] = node args["preview"] = True conf = self.loader.get_conf(previewModule) genargs = conf.generate(args) if self.previousWidget: self.stack.removeWidget(self.previousWidget) self.previousWidget.close() del self.previousWidget self.previousWidget = self.lmodules[previewModule].create() self.previousWidget.start(genargs) self.previousWidget.g_display() if str(self.previousWidget).find("player.PLAYER") == -1: self.previousWidget.setAttribute(Qt.WA_DeleteOnClose) self.stack.addWidget(self.previousWidget) except: pass def retranslateUi(self, widget): widget.setWindowTitle(QApplication.translate("Preview", "Preview", None, QApplication.UnicodeUTF8)) dff-1.3.0+dfsg.1/dff/ui/gui/widget/shell.py000066400000000000000000000267261217176075400202630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import os, sys, inspect, threading import signal; signal.signal(signal.SIGINT, signal.SIG_DFL) from PyQt4.QtGui import QAction, QApplication, QTextEdit, QTextCursor , QPalette, QColor, QBrush, QHBoxLayout, QIcon, QDockWidget, QFont, QFontMetrics from PyQt4.QtCore import Qt, QString, QThread, QSemaphore, SIGNAL, QObject, QEvent from dff.api.vfs import vfs from dff.api.taskmanager.taskmanager import TaskManager from dff.ui.console.console import Console, completion from dff.ui.redirect import RedirectIO from dff.ui.gui.resources.ui_shell import Ui_Shell class ShellView(QTextEdit, Console, Ui_Shell): def __init__(self, parent=None, log=''): QTextEdit.__init__(self, parent) Console.__init__(self, sigstp=False) self.setupUi(self) self.name = self.windowTitle() self.completion = completion.Completion(self) self.hookTermSize() taskmanager = TaskManager() self.vfs = vfs.vfs() self.log = log or '' if parent is None: self.eofKey = Qt.Key_D else: self.eofKey = None self.line = QString() self.lines = [] self.point = 0 self.more = 0 self.reading = 0 self.pointer = 0 self.cursor_pos = 0 self.fgcolor = QColor("white") self.selcolor = QColor("green") self.preloop() self.redirect = RedirectIO() self.sig = "Sputtext" self.connect(self, SIGNAL(self.sig), self.puttext) self.redirect.addparent(self, ["dff.ui.gui.widget.shell", "dff.ui.console.console", "dff.ui.console.completion", "dff.ui.console.line_to_arguments", "dff.api.taskmanager.taskmanager", "dff.api.taskmanager.scheduler", "dff.api.taskmanager.processus"], True) self.writePrompt() def hookTermSize(self): ca = getattr(sys.modules['dff.ui.console.utils'], "ConsoleAttributes") nt = getattr(ca, "_ConsoleAttributes__nt") posix = getattr(ca, "_ConsoleAttributes__posix") setattr(nt, "terminalSize", self.get_term_size) setattr(posix, "terminalSize", self.get_term_size) def writePrompt(self): self.cwd = self.vfs.getcwd() self.ps1 = self.cwd.absolute() + " > " self.write('\n') self.write(self.ps1) def write(self, str): self.redirect.write(str) def puttext(self, text): cursor = self.textCursor() cursor.movePosition(QTextCursor.End) pos1 = cursor.position() cursor.insertText(text) self.cursor_pos = cursor.position() self.setTextCursor(cursor) self.ensureCursorVisible() cursor.setPosition(pos1, QTextCursor.KeepAnchor) format = cursor.charFormat() format.setForeground(QBrush(self.fgcolor)) cursor.setCharFormat(format) def get_interpreter(self): return self.interpreter def moveCursor(self, operation, mode=QTextCursor.MoveAnchor): cursor = self.textCursor() cursor.movePosition(operation, mode) self.setTextCursor(cursor) def flush(self): pass def isatty(self): return 1 def clear(self): pass def readline(self): self.reading = 1 self.__clearLine() self.moveCursor(QTextCursor.End) while self.reading: QtGui.qApp.processEvents() if self.line.length() == 0: return '\n' else: return str(self.line) def writelines(self, text): map(self.write, text) def fakeUser(self, lines): for line in lines: self.line = QString(line.rstrip()) self.write(self.line) self.write('\n') self.run() def run(self): self.pointer = 0 try: self.lines.append(str(self.line)) except Exception,e: print e line = '\n'.join(self.lines) line = self.precmd(line) stop = self.onecmd(line, True) stop = self.postcmd(stop, line) self.cwd = self.vfs.getcwd() self.ps1 = self.cwd.absolute() + " > " if self.more: self.write(self.ps2) else: self.write(self.ps1) self.lines = [] self.__clearLine() def __clearLine(self): """ Clear input line buffer """ self.line.truncate(0) self.point = 0 def __insertText(self, text): """ Insert text at the current cursor position. """ self.line.insert(self.point, text) self.point += text.length() cursor = self.textCursor() cursor.insertText(text) self.color_line() def get_term_size(self): n = int(self.document().textWidth()/ 7.4) return n def insert_comp(self, text, matches): res = "" if isinstance(matches, dict) and matches["matched"] != 0: if matches["matched"] > 1: self.write("\n") if "type" in matches: if hasattr(self.completion, "insert_" + matches["type"] + "_comp"): func = getattr(self.completion, "insert_" + matches["type"] + "_comp") res = func(text, matches) else: pass else: pass if isinstance(matches, str): start = len(text) if start > 0: ins = matches[start:] else: ins = matches ins = QString(ins) self.line.insert(self.point, ins) self.point += ins.length() if res != "" and res != None: res = QString(res) self.line.insert(self.point, res) self.point += res.length() self.cwd = self.vfs.getcwd() self.ps1 = "\n" + self.cwd.absolute() + " > " self.write(self.ps1) self.write(QString(self.line)) n = len(self.line) - self.point for i in range(0, n): self.moveCursor(QTextCursor.Left) def keyPressEvent(self, e): text = e.text() key = e.key() try: if self.proc: if key == Qt.Key_Z and ord(str(text[0])) == 26: proc = self.proc proc.event.set() proc.exec_flags += ["thread"] self.write("\n[" + str(proc.pid) + "]" + " background " + proc.name() + "\n") e.ignore() self.lines = [] self.__clearLine() return else: e.ignore() return except AttributeError: pass if key == Qt.Key_Backspace: if self.point: cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) cursor.removeSelectedText() self.color_line() self.point -= 1 self.line.remove(self.point, 1) elif key == Qt.Key_Delete: cursor = self.textCursor() cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) cursor.removeSelectedText() self.color_line() self.line.remove(self.point, 1) elif key == Qt.Key_Return or key == Qt.Key_Enter: self.write('\n') if self.reading: self.reading = 0 else: self.lthread = threading.Thread(target = self.run) self.lthread.start() elif key == Qt.Key_Tab: pline = str(self.line) lstrip = pline[:self.point] text = lstrip.split(' ')[-1] matches = self.complete(pline, self.point) self.insert_comp(text, matches) elif key == Qt.Key_Left: if self.point : self.moveCursor(QTextCursor.Left) self.point -= 1 elif key == Qt.Key_Right: if self.point < self.line.length(): self.moveCursor(QTextCursor.Right) self.point += 1 elif key == Qt.Key_Home: cursor = self.textCursor () cursor.setPosition(self.cursor_pos) self.setTextCursor (cursor) self.point = 0 elif key == Qt.Key_End: self.moveCursor(QTextCursor.EndOfLine) self.point = self.line.length() elif key == Qt.Key_Up: cmd = self.history.getnext() self.histclear() if cmd: self.__insertText(QString(cmd)) elif key == Qt.Key_Down: cmd = self.history.getprev() self.histclear() if cmd: self.__insertText(QString(cmd)) elif text.length(): self.__insertText(text) return else: e.ignore() return e.accept() def histclear(self): cursor = self.textCursor () cursor.select(QTextCursor.LineUnderCursor) cursor.removeSelectedText() if self.more: self.write(self.ps2) else: self.write(self.ps1) self.__clearLine() def mousePressEvent(self, e): """ Keep the cursor after the last prompt. """ if e.button() == Qt.LeftButton: self.moveCursor(QTextCursor.End) def contentsContextMenuEvent(self,ev): """ Suppress the right button context menu. """ pass def dragEnterEvent(self, event): event.setAccepted(event.mimeData().hasFormat("text/plain")) def dragMoveEvent(self, event): if (event.mimeData().hasFormat("text/plain")): event.setDropAction(QtCore.Qt.MoveAction) event.accept() else: event.ignore() def dropEvent(self, event): if(event.mimeData().hasFormat("text/plain")): line = event.mimeData().text() self.__insertTextAtEnd(line) self.setFocus() event.setDropAction(QtCore.Qt.MoveAction) event.accept() else: event.ignore() def color_line(self): cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfLine) newpos = cursor.position() pos = -1 while(newpos != pos): cursor.movePosition(QTextCursor.NextWord) pos = newpos newpos = cursor.position() cursor.select(QTextCursor.WordUnderCursor) word = str(cursor.selectedText ().toAscii()) if(not word) : continue color= self.get_color(word) format = cursor.charFormat() format.setForeground(QBrush(color)) cursor.setCharFormat(format) def get_color(self, word): stripped = word.strip() if(stripped in self.completenames("")): return (self.selcolor) else: return (self.fgcolor) def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.writePrompt() else: QTextEdit.changeEvent(self, event) class ShellActions(): def __init__(self, mainwindow): self.mainwindow = mainwindow def create(self): self.mainwindow.addSingleDock("Shell", ShellView) dff-1.3.0+dfsg.1/dff/ui/gui/widget/stdio.py000066400000000000000000000055211217176075400202640ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER # import os, sys from PyQt4.QtGui import QDockWidget, QAction, QApplication, QTextEdit, QWidget, QHBoxLayout, QTabWidget, QPlainTextEdit from PyQt4.QtCore import Qt, SIGNAL, QThread, QObject from dff.ui.redirect import RedirectIO from dff.ui.gui.resources.ui_errors import Ui_Errors from dff.ui.gui.resources.ui_output import Ui_Output class CIO(QThread): def __init__(self, IOout, fd, sig): QThread.__init__(self) self.ioOut = IOout self.pipe = os.pipe() if not (fd == 2 and os.name == 'nt'): # On Windows stderr must not be closed for redirection to work os.close(fd) os.dup2(self.pipe[1], fd) self.sig = sig def run(self): while (True): try : buff = os.read(self.pipe[0], 4096) self.ioOut.emit(SIGNAL(self.sig), buff) except OSError: pass class STDOut(QPlainTextEdit, Ui_Output): def __init__(self, parent, debug): QPlainTextEdit.__init__(self) self.setupUi(self) self.setReadOnly(1) self.parent = parent self.name = "Output" self.debug = debug self.sigout = "IOOUTputtext" self.connect(self, SIGNAL(self.sigout), self.puttext) if sys.__stdout__.fileno() < 0 and not self.debug: # Open it if it does not exist, mostly for Windows sys.__stdout__ = os.fdopen(1, 'wb', 0) sys.stdout = sys.__stdout__ if sys.__stdout__.fileno() >= 0 and not self.debug: self.cioout = CIO(self, sys.__stdout__.fileno(), self.sigout) self.cioout.start() def puttext(self, text): self.insertPlainText(text) class STDErr(QPlainTextEdit, Ui_Errors): def __init__(self, parent, debug): QPlainTextEdit.__init__(self) self.setupUi(self) self.setReadOnly(1) self.parent = parent self.name = "Errors" self.debug = debug self.sigerr = "IOERRputtext" self.connect(self, SIGNAL(self.sigerr), self.puttext) if sys.__stderr__.fileno() < 0 and not self.debug: # Open it if it does not exist, mostly for Windows sys.__stderr__ = os.fdopen(2, 'wb', 0) sys.stderr = sys.__stderr__ if sys.__stderr__.fileno() >= 0 and not self.debug: self.cioerr = CIO(self, sys.__stderr__.fileno(), self.sigerr) self.cioerr.start() def puttext(self, text): self.insertPlainText(text) dff-1.3.0+dfsg.1/dff/ui/gui/widget/taskmanager.py000066400000000000000000000142011217176075400214320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # Jeremy MOUNIER # import time from datetime import datetime from Queue import Empty from PyQt4.QtCore import QRect, QSize, Qt, SIGNAL, QEvent from PyQt4.QtGui import QAction, QApplication, QDockWidget, QIcon, QHBoxLayout, QPushButton, QTabWidget, QTreeWidget, QTreeWidgetItem, QWidget, QDialog, QGridLayout, QLabel, QComboBox, QVBoxLayout, QHBoxLayout, QDialogButtonBox, QTextEdit from dff.api.taskmanager.processus import ProcessusManager from dff.api.gui.widget.textedit import TextEdit from dff.api.gui.widget.varianttreewidget import VariantTreeWidget from dff.ui.gui.resources.ui_taskmanager import Ui_TaskManager class ProcessusItem(QTreeWidgetItem): def __init__(self, parent = None): QTreeWidgetItem.__init__(self, parent) def __lt__(self, cmpitem): column = self.treeWidget().sortColumn() if column == 0: return int(self.text(column)) < int(cmpitem.text(column)) else: return self.text(column) < cmpitem.text(column) class Processus(QTreeWidget, Ui_TaskManager): def __init__(self, parent): super(QTreeWidget, self).__init__() self.setupUi(self) self.tr("Fail") self.tr("Finish") self.tr("Running") self.__mainWindow = parent self.name = "Task manager" self.initTreeProcess() self.setSortingEnabled(True) def initTreeProcess(self): self.connect(self, SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"), self.procClicked) self.procItemDic = dict() self.procChildItemDic = dict() def procClicked(self, item, column): dial = procMB(self, self.__mainWindow, item.text(0)) dial.exec_() def LoadInfoProcess(self): processusManager = ProcessusManager() for proc in processusManager: try: item = self.procItemDic[proc] except KeyError: item = ProcessusItem(self) self.procItemDic[proc] = item item.setText(0, str(proc.pid)) item.setText(1, str(proc.name)) if item.text(2) != self.tr(proc.state): item.setText(2, self.tr(proc.state)) if item.text(3) != str(proc.stateinfo): item.setText(3, str(proc.stateinfo)) duration = self.procDuration(proc) item.setText(4, str(duration)) def procDuration(self, proc): if proc.timestart: stime = datetime.fromtimestamp(proc.timestart) if proc.timeend: etime = datetime.fromtimestamp(proc.timeend) else: etime = datetime.fromtimestamp(time.time()) delta = etime - stime else: delta = 0 return delta def deleteInfoProcess(self): self.clear() def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) else: QTreeWidget.changeEvent(self, event) class procMB(QDialog): def __init__(self, parent, mainWindow, pid): QDialog.__init__(self, parent) self.translation() self.setWindowTitle(self.nameTitle) self.processusManager = ProcessusManager() self.pid = pid res = {} args = {} self.tabwidget = QTabWidget(self) stream = None proc = self.processusManager[int(str(self.pid))] res = proc.res args = proc.args if proc.streamOut == None: try : proc.streamOut = '' txt = proc.stream.get(0) proc.streamOut += txt while txt: txt = proc.stream.get(0) proc.streamOut += txt except Empty: pass if proc.streamOut and proc.streamOut != '': stream = proc.streamOut self.box = QVBoxLayout() self.setLayout(self.box) self.box.addWidget(self.tabwidget) self.dialogButtonsLayout = QHBoxLayout() self.dialogButtonsBox = QDialogButtonBox() self.dialogButtonsBox.setStandardButtons(QDialogButtonBox.Ok) self.connect(self.dialogButtonsBox, SIGNAL("accepted()"), self.accept) self.dialogButtonsLayout.addWidget(self.dialogButtonsBox) self.setMinimumSize(800, 600) if args and len(args) > 0: self.treeargs = VariantTreeWidget(self) self.treeargs.fillMap(self.treeargs, args) self.tabwidget.addTab(self.treeargs, self.argname) for i in [0, 1]: self.treeargs.resizeColumnToContents(i) if stream: textWidget = TextEdit(proc) textWidget.emit(SIGNAL("puttext"), proc.streamOut) self.tabwidget.addTab(textWidget, self.outputname) if proc.error_result != '': #XXX FIX for swig problem with results, this should not work in console anymore textWidget = QTextEdit() textWidget.setReadOnly(1) textWidget.append(proc.error_result) self.tabwidget.addTab(textWidget, self.tr('Error')) if len(res) > 0: self.treeres = VariantTreeWidget(self) self.treeres.fillMap(self.treeres, res) self.tabwidget.addTab(self.treeres, self.resname) for i in [0, 1]: self.treeres.resizeColumnToContents(i) else: label = QLabel(self.noResult) label.setAlignment(Qt.AlignCenter) self.tabwidget.addTab(label, self.resname) self.box.addLayout(self.dialogButtonsLayout) def translation(self): self.outputname = self.tr("Output") self.argname = self.tr("Provided Arguments") self.resname = self.tr("Results") self.nameTitle = self.tr('Processus Information') self.noResult = self.tr("No results") dff-1.3.0+dfsg.1/dff/ui/history.py000066400000000000000000000051311217176075400165710ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # Solal Jacob # from dff.ui.conf import Conf class history(): class __history(): def __init__(self): self.conf = Conf() self.hist = [] self.wfile = None self.current = 0 self.load() def load(self): self.path = self.conf.historyFileFullPath if self.wfile: self.wfile.close() try: if not self.conf.noHistoryFile and not self.conf.noFootPrint: self.rfile = open(self.path, 'r') self.wfile = open(self.path, 'a') self.hist = self.rfile.readlines() self.rfile.close() self.current = len(self.hist) except IOError: if not self.conf.noHistoryFile and not self.conf.noFootPrint: self.wfile = open(self.path, 'a') return def getnext(self): self.current -= 1 if self.current < 0: self.current = 0 try : cmd = self.hist[self.current] except IndexError: return None return cmd.strip('\n') def getprev(self): self.current += 1 if self.current >= len(self.hist): self.current = len(self.hist) - 1 return None cmd = self.hist[self.current] return cmd.strip('\n') def save(self): if not self.conf.noHistoryFile and not self.conf.noFootPrint: self.wfile.close() def add(self, cmd): try: self.hist += [ cmd ] if not self.conf.noHistoryFile and not self.conf.noFootPrint: self.wfile.write(cmd + "\n") self.wfile.flush() except IOError: print "can't write on history" return def clear(self): self.hist = [] if not self.conf.noHistoryFile and not self.conf.noFootPrint: self.wfile.close() self.wfile = open(self.path, 'w') __instance = None def __init__(self): if history.__instance is None: history.__instance = history.__history() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) dff-1.3.0+dfsg.1/dff/ui/redirect.py000066400000000000000000000065171217176075400167020ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # import sys, inspect, os from PyQt4.QtGui import QApplication, QTextEdit, QTextCursor , QPalette, QColor, QBrush, QHBoxLayout, QIcon from PyQt4.QtCore import Qt, QString, QThread, QSemaphore, SIGNAL, QObject from dff.api.loader import loader from dff.api.taskmanager.processus import ProcessusManager from dff.api.taskmanager.scheduler import sched class RedirectWrite(QThread): __parent = None def __init__(self, parent, out): QThread.__init__(self) RedirectWrite.__parent = parent self.sout = out self.processusManager = ProcessusManager() def run(self): self.exec_() def write(self, text): frame = inspect.currentframe().f_back fname = frame.f_globals['__name__'] if frame: try : self.loader.modules[fname] except KeyError: pass for (nparent, lframe, ismod) in self.lparent: if fname in lframe: nparent.emit(SIGNAL(nparent.sig), text) del frame return if fname in self.loader.modules: try: inst = frame.f_locals['self'] for proc in self.processusManager: if proc.inst == inst: if not "thread" in proc.exec_flags: for (nparent, lframe, ismod) in self.lparent: if ismod: nparent.emit(SIGNAL(nparent.sig), text) del frame return else: proc.stream.put(text) return except KeyError: pass del frame if self.ioOut != None and self.sout == 'out': self.ioOut.emit(SIGNAL(self.ioOut.sigout), text) elif self.ioOut != None and self.sout == 'err': self.ioOut.emit(SIGNAL(self.ioOut.sigerr), text) elif self.sout == 'err': sys.__stderr__.write(text) else : sys.__stdout__.write(text) def __getattr__(self, attr): return getattr(RedirectWrite.__parent, attr) class RedirectIO(): class __RedirectIO(): def __init__(self, IOout = None, debug = False): self.lparent = [] self.debug = debug self.oldstdout = sys.__stdout__ self.oldstderr = sys.__stderr__ self.ioOut = IOout self.processusManager = ProcessusManager() self.loader = loader.loader() if not self.debug: sys.stdout = RedirectWrite(self, 'out') sys.stderr = RedirectWrite(self, 'err') self.write = sys.stdout.write def addparent(self, nparent, lframe, ismod = False): self.lparent += [(nparent, lframe, ismod)] __instance = None def __init__(self, IOout = None, debug = False): if RedirectIO.__instance is None: RedirectIO.__instance = RedirectIO.__RedirectIO(IOout, debug) if IOout: RedirectIO.__instance.ioOut = IOout def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) dff-1.3.0+dfsg.1/dff/ui/ui.py000066400000000000000000000076661217176075400155240ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob import sys, os, getopt from distutils.sysconfig import get_python_lib from dff.api.loader.loader import loader from dff.ui.conf import Conf from dff.ui.redirect import RedirectIO # ensure dist-packages will be loaded be pyshared on Debian # else private modules won't be found if not os.path.exists(os.path.join("dff", "modules")) and os.path.exists(os.path.join(get_python_lib(), "dff")): sys.path.insert(0, os.path.join(get_python_lib())) class UI(): """This classes manage and let you launch different type of user interfaces""" def __init__(self, debug = False, verbosity = 0): self.debug = debug self.verbosity = verbosity RedirectIO(None, self.debug) self.loader = loader() def launch(self, modulesPaths = None): print 'This method must be overwritten by an inherited classes' def modulesLocalPath(self, modulesPaths): modulesLocalPath = [] for modulesPath in modulesPaths: if os.name != "posix": modulesPath = modulesPath.replace('/', '\\') if os.path.exists(modulesPath): modulesLocalPath.append(modulesPath) else: modulesLocalPath.append(os.path.join(get_python_lib(), modulesPath)) return modulesLocalPath def loadModules(self, modulesPaths, displayOutput = None): modulesPaths = self.modulesLocalPath(modulesPaths) self.loader.do_load(modulesPaths, displayOutput, reload = False) class Usage(): PROGRAM_USAGE = """DFF\nDigital Forensic Framework\n Usage: """ + sys.argv[0] + """ [options] Options: -v --version display current version -g --graphical launch graphical interface -b --batch=FILENAME executes batch contained in FILENAME -l --language=LANG use LANG as interface language -h --help display this help message -d --debug redirect IO to system console --verbosity=LEVEL set verbosity level when debugging [0-3] -c --config=FILEPATH use config file from FILEPATH """ VERSION = "1.3.0" def __init__(self, argv): self.argv = argv self.graphical = 0 self.test = '' self.confPath = '' self.debug = False self.verbosity = 0 self.batch = None # Configuration self.main() self.conf = Conf(self.confPath) def main(self): """Check command line argument""" try: opts, args = getopt.getopt(self.argv, "vgdht:l:c:b:", [ "version", "graphical", "debug", "help", "test=", "language=", "verbosity=", "config=", "batch="]) except getopt.GetoptError: self.usage() for opt, arg in opts: if opt in ("-h", "--help"): self.usage() elif opt in ("-g", "--graphical"): self.graphical = 1 elif opt in ("-t", "--test"): self.test = arg elif opt in ("-l", "--language"): self.conf.setLanguage(arg[:2]) elif opt in ("-v", "--version"): print "dff version " + self.VERSION sys.exit(1) elif opt in ("-d", "--debug"): self.debug = True elif opt == "--verbosity": self.verbosity = int(arg) elif opt in ("-c", "--config"): self.confPath = str(arg) elif opt in ("-b", "--batch"): self.batch = str(arg) return def usage(self): """Show usage""" print self.PROGRAM_USAGE sys.exit(2) dff-1.3.0+dfsg.1/dff/unsupported/000077500000000000000000000000001217176075400164715ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/CMakeLists.txt000066400000000000000000000015511217176075400212330ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file(__init__.py) add_subdirectory(archives) add_subdirectory(crypto) add_subdirectory(node) add_subdirectory(phone) add_subdirectory(process) add_subdirectory(search) add_subdirectory(test) add_subdirectory(utils) add_subdirectory(viewer) add_subdirectory(volumes) dff-1.3.0+dfsg.1/dff/unsupported/__init__.py000066400000000000000000000000001217176075400205700ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/archives/000077500000000000000000000000001217176075400202755ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/archives/CMakeLists.txt000066400000000000000000000012071217176075400230350ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file(__init__.py) add_subdirectory(zip) dff-1.3.0+dfsg.1/dff/unsupported/archives/zip/000077500000000000000000000000001217176075400210775ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/archives/zip/CMakeLists.txt000066400000000000000000000011431217176075400236360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py unzip.py mzipfile.py ) dff-1.3.0+dfsg.1/dff/unsupported/archives/zip/__init__.py000066400000000000000000000011141217176075400232050ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['unzip', 'mzipfile'] dff-1.3.0+dfsg.1/dff/unsupported/archives/zip/mzipfile.py000066400000000000000000001472541217176075400233050ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # """ Read and write ZIP files. """ import struct, os, time, sys, shutil import binascii, cStringIO try: import zlib # We may need its compression method crc32 = zlib.crc32 except ImportError: zlib = None crc32 = binascii.crc32 __all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile", "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ] class BadZipfile(Exception): pass class LargeZipFile(Exception): """ Raised when writing a zipfile, the zipfile requires ZIP64 extensions and those extensions are disabled. """ error = BadZipfile # The exception raised by this module ZIP64_LIMIT= (1 << 31) - 1 ZIP_FILECOUNT_LIMIT = 1 << 16 ZIP_MAX_COMMENT = (1 << 16) - 1 # constants for Zip file compression methods ZIP_STORED = 0 ZIP_DEFLATED = 8 # Other ZIP compression methods not supported # Below are some formats and associated data for reading/writing headers using # the struct module. The names and structures of headers/records are those used # in the PKWARE description of the ZIP file format: # http://www.pkware.com/documents/casestudies/APPNOTE.TXT # (URL valid as of January 2008) # The "end of central directory" structure, magic number, size, and indices # (section V.I in the format document) structEndArchive = "<4s4H2LH" stringEndArchive = "PK\005\006" sizeEndCentDir = struct.calcsize(structEndArchive) _ECD_SIGNATURE = 0 _ECD_DISK_NUMBER = 1 _ECD_DISK_START = 2 _ECD_ENTRIES_THIS_DISK = 3 _ECD_ENTRIES_TOTAL = 4 _ECD_SIZE = 5 _ECD_OFFSET = 6 _ECD_COMMENT_SIZE = 7 # These last two indices are not part of the structure as defined in the # spec, but they are used internally by this module as a convenience _ECD_COMMENT = 8 _ECD_LOCATION = 9 # The "central directory" structure, magic number, size, and indices # of entries in the structure (section V.F in the format document) structCentralDir = "<4s4B4HL2L5H2L" stringCentralDir = "PK\001\002" sizeCentralDir = struct.calcsize(structCentralDir) # indexes of entries in the central directory structure _CD_SIGNATURE = 0 _CD_CREATE_VERSION = 1 _CD_CREATE_SYSTEM = 2 _CD_EXTRACT_VERSION = 3 _CD_EXTRACT_SYSTEM = 4 _CD_FLAG_BITS = 5 _CD_COMPRESS_TYPE = 6 _CD_TIME = 7 _CD_DATE = 8 _CD_CRC = 9 _CD_COMPRESSED_SIZE = 10 _CD_UNCOMPRESSED_SIZE = 11 _CD_FILENAME_LENGTH = 12 _CD_EXTRA_FIELD_LENGTH = 13 _CD_COMMENT_LENGTH = 14 _CD_DISK_NUMBER_START = 15 _CD_INTERNAL_FILE_ATTRIBUTES = 16 _CD_EXTERNAL_FILE_ATTRIBUTES = 17 _CD_LOCAL_HEADER_OFFSET = 18 # The "local file header" structure, magic number, size, and indices # (section V.A in the format document) structFileHeader = "<4s2B4HL2L2H" stringFileHeader = "PK\003\004" sizeFileHeader = struct.calcsize(structFileHeader) _FH_SIGNATURE = 0 _FH_EXTRACT_VERSION = 1 _FH_EXTRACT_SYSTEM = 2 _FH_GENERAL_PURPOSE_FLAG_BITS = 3 _FH_COMPRESSION_METHOD = 4 _FH_LAST_MOD_TIME = 5 _FH_LAST_MOD_DATE = 6 _FH_CRC = 7 _FH_COMPRESSED_SIZE = 8 _FH_UNCOMPRESSED_SIZE = 9 _FH_FILENAME_LENGTH = 10 _FH_EXTRA_FIELD_LENGTH = 11 # The "Zip64 end of central directory locator" structure, magic number, and size structEndArchive64Locator = "<4sLQL" stringEndArchive64Locator = "PK\x06\x07" sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator) # The "Zip64 end of central directory" record, magic number, size, and indices # (section V.G in the format document) structEndArchive64 = "<4sQ2H2L4Q" stringEndArchive64 = "PK\x06\x06" sizeEndCentDir64 = struct.calcsize(structEndArchive64) _CD64_SIGNATURE = 0 _CD64_DIRECTORY_RECSIZE = 1 _CD64_CREATE_VERSION = 2 _CD64_EXTRACT_VERSION = 3 _CD64_DISK_NUMBER = 4 _CD64_DISK_NUMBER_START = 5 _CD64_NUMBER_ENTRIES_THIS_DISK = 6 _CD64_NUMBER_ENTRIES_TOTAL = 7 _CD64_DIRECTORY_SIZE = 8 _CD64_OFFSET_START_CENTDIR = 9 def is_zipfile(filename): """Quickly see if file is a ZIP file by checking the magic number.""" try: fpin = open(filename, "rb") endrec = _EndRecData(fpin) fpin.close() if endrec: return True # file has correct magic number except IOError: pass return False def _EndRecData64(fpin, offset, endrec): """ Read the ZIP64 end-of-archive records and use that to update endrec """ fpin.seek(offset - sizeEndCentDir64Locator, 2) data = fpin.read(sizeEndCentDir64Locator) sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data) if sig != stringEndArchive64Locator: return endrec if diskno != 0 or disks != 1: raise BadZipfile("zipfiles that span multiple disks are not supported") # Assume no 'zip64 extensible data' fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2) data = fpin.read(sizeEndCentDir64) sig, sz, create_version, read_version, disk_num, disk_dir, \ dircount, dircount2, dirsize, diroffset = \ struct.unpack(structEndArchive64, data) if sig != stringEndArchive64: return endrec # Update the original endrec using data from the ZIP64 record endrec[_ECD_SIGNATURE] = sig endrec[_ECD_DISK_NUMBER] = disk_num endrec[_ECD_DISK_START] = disk_dir endrec[_ECD_ENTRIES_THIS_DISK] = dircount endrec[_ECD_ENTRIES_TOTAL] = dircount2 endrec[_ECD_SIZE] = dirsize endrec[_ECD_OFFSET] = diroffset return endrec def _EndRecData(fpin): """Return data from the "End of Central Directory" record, or None. The data is a list of the nine items in the ZIP "End of central dir" record followed by a tenth item, the file seek offset of this record.""" # Determine file size fpin.seek(0, 2) filesize = fpin.tell() # Check to see if this is ZIP file with no archive comment (the # "end of central directory" structure should be the last item in the # file if this is the case). fpin.seek(-sizeEndCentDir, 2) data = fpin.read() if data[0:4] == stringEndArchive and data[-2:] == "\000\000": # the signature is correct and there's no comment, unpack structure endrec = struct.unpack(structEndArchive, data) endrec=list(endrec) # Append a blank comment and record start offset endrec.append("") endrec.append(filesize - sizeEndCentDir) if endrec[_ECD_OFFSET] == 0xffffffff: # the value for the "offset of the start of the central directory" # indicates that there is a "Zip64 end of central directory" # structure present, so go look for it return _EndRecData64(fpin, -sizeEndCentDir, endrec) return endrec # Either this is not a ZIP file, or it is a ZIP file with an archive # comment. Search the end of the file for the "end of central directory" # record signature. The comment is the last item in the ZIP file and may be # up to 64K long. It is assumed that the "end of central directory" magic # number does not appear in the comment. maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0) fpin.seek(maxCommentStart, 0) data = fpin.read() start = data.rfind(stringEndArchive) if start >= 0: # found the magic number; attempt to unpack and interpret recData = data[start:start+sizeEndCentDir] endrec = list(struct.unpack(structEndArchive, recData)) comment = data[start+sizeEndCentDir:] # check that comment length is correct if endrec[_ECD_COMMENT_SIZE] == len(comment): # Append the archive comment and start offset endrec.append(comment) endrec.append(maxCommentStart + start) if endrec[_ECD_OFFSET] == 0xffffffff: # There is apparently a "Zip64 end of central directory" # structure present, so go look for it return _EndRecData64(fpin, start - filesize, endrec) return endrec # Unable to find a valid end of central directory structure return class ZipInfo (object): """Class with attributes describing each file in the ZIP archive.""" __slots__ = ( 'orig_filename', 'filename', 'date_time', 'compress_type', 'comment', 'extra', 'create_system', 'create_version', 'extract_version', 'reserved', 'flag_bits', 'volume', 'internal_attr', 'external_attr', 'header_offset', 'CRC', 'compress_size', 'file_size', '_raw_time', ) def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)): self.orig_filename = filename # Original file name in archive # Terminate the file name at the first null byte. Null bytes in file # names are used as tricks by viruses in archives. null_byte = filename.find(chr(0)) if null_byte >= 0: filename = filename[0:null_byte] # This is used to ensure paths in generated ZIP files always use # forward slashes as the directory separator, as required by the # ZIP format specification. if os.sep != "/" and os.sep in filename: filename = filename.replace(os.sep, "/") self.filename = filename # Normalized file name self.date_time = date_time # year, month, day, hour, min, sec # Standard values: self.compress_type = ZIP_STORED # Type of compression for the file self.comment = "" # Comment for each file self.extra = "" # ZIP extra data if sys.platform == 'win32': self.create_system = 0 # System which created ZIP archive else: # Assume everything else is unix-y self.create_system = 3 # System which created ZIP archive self.create_version = 20 # Version which created ZIP archive self.extract_version = 20 # Version needed to extract archive self.reserved = 0 # Must be zero self.flag_bits = 0 # ZIP flag bits self.volume = 0 # Volume number of file header self.internal_attr = 0 # Internal attributes self.external_attr = 0 # External file attributes # Other attributes are set by class ZipFile: # header_offset Byte offset to the file header # CRC CRC-32 of the uncompressed file # compress_size Size of the compressed file # file_size Size of the uncompressed file def FileHeader(self): """Return the per-file header as a string.""" dt = self.date_time dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2] dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2) if self.flag_bits & 0x08: # Set these to zero because we write them after the file data CRC = compress_size = file_size = 0 else: CRC = self.CRC compress_size = self.compress_size file_size = self.file_size extra = self.extra if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT: # File is larger than what fits into a 4 byte integer, # fall back to the ZIP64 extension fmt = '= 24: counts = unpack('> 1) & 0x7FFFFFFF) ^ poly else: crc = ((crc >> 1) & 0x7FFFFFFF) table[i] = crc return table crctable = _GenerateCRCTable() def _crc32(self, ch, crc): """Compute the CRC32 primitive on one byte.""" return ((crc >> 8) & 0xffffff) ^ self.crctable[(crc ^ ord(ch)) & 0xff] def __init__(self, pwd): self.key0 = 305419896 self.key1 = 591751049 self.key2 = 878082192 for p in pwd: self._UpdateKeys(p) def _UpdateKeys(self, c): self.key0 = self._crc32(c, self.key0) self.key1 = (self.key1 + (self.key0 & 255)) & 4294967295 self.key1 = (self.key1 * 134775813 + 1) & 4294967295 self.key2 = self._crc32(chr((self.key1 >> 24) & 255), self.key2) def __call__(self, c): """Decrypt a single character.""" c = ord(c) k = self.key2 | 2 c = c ^ (((k * (k^1)) >> 8) & 255) c = chr(c) self._UpdateKeys(c) return c class ZipExtFile: """File-like object for reading an archive member. Is returned by ZipFile.open(). """ def __init__(self, fileobj, zipinfo, decrypt=None): self.fileobj = fileobj self.decrypter = decrypt self.bytes_read = 0L self.rawbuffer = '' self.readbuffer = '' self.linebuffer = '' self.eof = False self.univ_newlines = False self.nlSeps = ("\n", ) self.lastdiscard = '' self.compress_type = zipinfo.compress_type self.compress_size = zipinfo.compress_size self.closed = False self.mode = "r" self.name = zipinfo.filename # read from compressed files in 64k blocks self.compreadsize = 64*1024 if self.compress_type == ZIP_DEFLATED: self.dc = zlib.decompressobj(-15) def set_univ_newlines(self, univ_newlines): self.univ_newlines = univ_newlines # pick line separator char(s) based on universal newlines flag self.nlSeps = ("\n", ) if self.univ_newlines: self.nlSeps = ("\r\n", "\r", "\n") def __iter__(self): return self def next(self): nextline = self.readline() if not nextline: raise StopIteration() return nextline def close(self): self.closed = True def _checkfornewline(self): nl, nllen = -1, -1 if self.linebuffer: # ugly check for cases where half of an \r\n pair was # read on the last pass, and the \r was discarded. In this # case we just throw away the \n at the start of the buffer. if (self.lastdiscard, self.linebuffer[0]) == ('\r','\n'): self.linebuffer = self.linebuffer[1:] for sep in self.nlSeps: nl = self.linebuffer.find(sep) if nl >= 0: nllen = len(sep) return nl, nllen return nl, nllen def readline(self, size = -1): """Read a line with approx. size. If size is negative, read a whole line. """ if size < 0: size = sys.maxint elif size == 0: return '' # check for a newline already in buffer nl, nllen = self._checkfornewline() if nl >= 0: # the next line was already in the buffer nl = min(nl, size) else: # no line break in buffer - try to read more size -= len(self.linebuffer) while nl < 0 and size > 0: buf = self.read(min(size, 100)) if not buf: break self.linebuffer += buf size -= len(buf) # check for a newline in buffer nl, nllen = self._checkfornewline() # we either ran out of bytes in the file, or # met the specified size limit without finding a newline, # so return current buffer if nl < 0: s = self.linebuffer self.linebuffer = '' return s buf = self.linebuffer[:nl] self.lastdiscard = self.linebuffer[nl:nl + nllen] self.linebuffer = self.linebuffer[nl + nllen:] # line is always returned with \n as newline char (except possibly # for a final incomplete line in the file, which is handled above). return buf + "\n" def readlines(self, sizehint = -1): """Return a list with all (following) lines. The sizehint parameter is ignored in this implementation. """ result = [] while True: line = self.readline() if not line: break result.append(line) return result def read(self, size = None): # act like file() obj and return empty string if size is 0 if size == 0: return '' # determine read size bytesToRead = self.compress_size - self.bytes_read # adjust read size for encrypted files since the first 12 bytes # are for the encryption/password information if self.decrypter is not None: bytesToRead -= 12 if size is not None and size >= 0: if self.compress_type == ZIP_STORED: lr = len(self.readbuffer) bytesToRead = min(bytesToRead, size - lr) elif self.compress_type == ZIP_DEFLATED: if len(self.readbuffer) > size: # the user has requested fewer bytes than we've already # pulled through the decompressor; don't read any more bytesToRead = 0 else: # user will use up the buffer, so read some more lr = len(self.rawbuffer) bytesToRead = min(bytesToRead, self.compreadsize - lr) # avoid reading past end of file contents if bytesToRead + self.bytes_read > self.compress_size: bytesToRead = self.compress_size - self.bytes_read # try to read from file (if necessary) if bytesToRead > 0: bytes = self.fileobj.read(bytesToRead) self.bytes_read += len(bytes) self.rawbuffer += bytes # handle contents of raw buffer if self.rawbuffer: newdata = self.rawbuffer self.rawbuffer = '' # decrypt new data if we were given an object to handle that if newdata and self.decrypter is not None: newdata = ''.join(map(self.decrypter, newdata)) # decompress newly read data if necessary if newdata and self.compress_type == ZIP_DEFLATED: newdata = self.dc.decompress(newdata) self.rawbuffer = self.dc.unconsumed_tail if self.eof and len(self.rawbuffer) == 0: # we're out of raw bytes (both from the file and # the local buffer); flush just to make sure the # decompressor is done newdata += self.dc.flush() # prevent decompressor from being used again self.dc = None self.readbuffer += newdata # return what the user asked for if size is None or len(self.readbuffer) <= size: bytes = self.readbuffer self.readbuffer = '' else: bytes = self.readbuffer[:size] self.readbuffer = self.readbuffer[size:] return bytes class ZipFile: """ Class with methods to open, read, write, close, list zip files. z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False) file: Either the path to the file, or a file-like object. If it is a path, the file will be opened and closed by ZipFile. mode: The mode can be either read "r", write "w" or append "a". compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib). allowZip64: if True ZipFile will create files with ZIP64 extensions when needed, otherwise it will raise an exception when this would be necessary. """ fp = None # Set here since __del__ checks it def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False): """Open the ZIP file with mode read "r", write "w" or append "a".""" if mode not in ("r", "w", "a"): raise RuntimeError('ZipFile() requires mode "r", "w", or "a"') if compression == ZIP_STORED: pass elif compression == ZIP_DEFLATED: if not zlib: raise RuntimeError,\ "Compression requires the (missing) zlib module" else: raise RuntimeError, "That compression method is not supported" self._allowZip64 = allowZip64 self._didModify = False self.debug = 0 # Level of printing: 0 through 3 self.NameToInfo = {} # Find file info given name self.filelist = [] # List of ZipInfo instances for archive self.compression = compression # Method of compression self.mode = key = mode.replace('b', '')[0] self.pwd = None self.comment = '' # Check if we were passed a file-like object if isinstance(file, basestring): self._filePassed = 0 self.filename = file modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'} try: self.fp = open(file, modeDict[mode]) except IOError: if mode == 'a': mode = key = 'w' self.fp = open(file, modeDict[mode]) else: raise else: self._filePassed = 1 self.fp = file self.filename = getattr(file, 'name', None) if key == 'r': self._GetContents() elif key == 'w': pass elif key == 'a': try: # See if file is a zip file self._RealGetContents() # seek to start of directory and overwrite self.fp.seek(self.start_dir, 0) except BadZipfile: # file is not a zip file, just append self.fp.seek(0, 2) else: if not self._filePassed: self.fp.close() self.fp = None raise RuntimeError, 'Mode must be "r", "w" or "a"' def _GetContents(self): """Read the directory, making sure we close the file if the format is bad.""" try: self._RealGetContents() except BadZipfile: if not self._filePassed: self.fp.close() self.fp = None raise def _RealGetContents(self): """Read in the table of contents for the ZIP file.""" fp = self.fp endrec = _EndRecData(fp) if not endrec: raise BadZipfile, "File is not a zip file" if self.debug > 1: print endrec size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory self.comment = endrec[_ECD_COMMENT] # archive comment # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd if endrec[_ECD_SIGNATURE] == stringEndArchive64: # If Zip64 extension structures are present, account for them concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator) if self.debug > 2: inferred = concat + offset_cd print "given, inferred, offset", offset_cd, inferred, concat # self.start_dir: Position of start of central directory self.start_dir = offset_cd + concat fp.seek(self.start_dir, 0) data = fp.read(size_cd) fp = cStringIO.StringIO(data) total = 0 while total < size_cd: centdir = fp.read(sizeCentralDir) if centdir[0:4] != stringCentralDir: raise BadZipfile, "Bad magic number for central directory" centdir = struct.unpack(structCentralDir, centdir) if self.debug > 2: print centdir filename = fp.read(centdir[_CD_FILENAME_LENGTH]) # Create ZipInfo instance to store file information x = ZipInfo(filename) x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH]) x.comment = fp.read(centdir[_CD_COMMENT_LENGTH]) x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size) = centdir[1:12] x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) x._raw_time = t x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, t>>11, (t>>5)&0x3F, (t&0x1F) * 2 ) x._decodeExtra() x.header_offset = x.header_offset + concat x.filename = x._decodeFilename() self.filelist.append(x) self.NameToInfo[x.filename] = x # update total bytes read from central directory total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]) if self.debug > 2: print "total", total def namelist(self): """Return a list of file names in the archive.""" l = [] for data in self.filelist: l.append(data.filename) return l def infolist(self): """Return a list of class ZipInfo instances for files in the archive.""" return self.filelist def printdir(self): """Print a table of contents for the zip file.""" print "%-46s %19s %12s" % ("File Name", "Modified ", "Size") for zinfo in self.filelist: date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6] print "%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size) def testzip(self): """Read all the files and check the CRC.""" chunk_size = 2 ** 20 for zinfo in self.filelist: try: # Read by chunks, to avoid an OverflowError or a # MemoryError with very large embedded files. f = self.open(zinfo.filename, "r") while f.read(chunk_size): # Check CRC-32 pass except BadZipfile: return zinfo.filename def getinfo(self, name): """Return the instance of ZipInfo given 'name'.""" info = self.NameToInfo.get(name) if info is None: raise KeyError( 'There is no item named %r in the archive' % name) return info def setpassword(self, pwd): """Set default password for encrypted files.""" self.pwd = pwd def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" return self.open(name, "r", pwd).read() def open(self, name, mode="r", pwd=None): """Return file-like object for 'name'.""" if mode not in ("r", "U", "rU"): raise RuntimeError, 'open() requires mode "r", "U", or "rU"' if not self.fp: raise RuntimeError, \ "Attempt to read ZIP archive that was already closed" # Only open a new file for instances where we were not # given a file object in the constructor if self._filePassed: zef_file = self.fp else: zef_file = open(self.filename, 'rb') # Make sure we have an info object if isinstance(name, ZipInfo): # 'name' is already an info object zinfo = name else: # Get info object for name zinfo = self.getinfo(name) zef_file.seek(zinfo.header_offset, 0) # Skip the file header: fheader = zef_file.read(sizeFileHeader) if fheader[0:4] != stringFileHeader: raise BadZipfile, "Bad magic number for file header" fheader = struct.unpack(structFileHeader, fheader) fname = zef_file.read(fheader[_FH_FILENAME_LENGTH]) if fheader[_FH_EXTRA_FIELD_LENGTH]: zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH]) if fname != zinfo.orig_filename: raise BadZipfile, \ 'File name in directory "%s" and header "%s" differ.' % ( zinfo.orig_filename, fname) # check for encrypted flag & handle password is_encrypted = zinfo.flag_bits & 0x1 zd = None if is_encrypted: if not pwd: pwd = self.pwd if not pwd: raise RuntimeError, "File %s is encrypted, " \ "password required for extraction" % name zd = _ZipDecrypter(pwd) # The first 12 bytes in the cypher stream is an encryption header # used to strengthen the algorithm. The first 11 bytes are # completely random, while the 12th contains the MSB of the CRC, # or the MSB of the file time depending on the header type # and is used to check the correctness of the password. bytes = zef_file.read(12) h = map(zd, bytes[0:12]) if zinfo.flag_bits & 0x8: # compare against the file type from extended local headers check_byte = (zinfo._raw_time >> 8) & 0xff else: # compare against the CRC otherwise check_byte = (zinfo.CRC >> 24) & 0xff if ord(h[11]) != check_byte: raise RuntimeError("Bad password for file", name) # build and return a ZipExtFile if zd is None: zef = ZipExtFile(zef_file, zinfo) else: zef = ZipExtFile(zef_file, zinfo, zd) # set universal newlines on ZipExtFile if necessary if "U" in mode: zef.set_univ_newlines(True) return zef def extract(self, member, path=None, pwd=None): """Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. `member' may be a filename or a ZipInfo object. You can specify a different directory using `path'. """ if not isinstance(member, ZipInfo): member = self.getinfo(member) if path is None: path = os.getcwd() return self._extract_member(member, path, pwd) def extractall(self, path=None, members=None, pwd=None): """Extract all members from the archive to the current working directory. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the list returned by namelist(). """ if members is None: members = self.namelist() for zipinfo in members: self.extract(zipinfo, path, pwd) def _extract_member(self, member, targetpath, pwd): """Extract the ZipInfo object 'member' to a physical file on the path targetpath. """ # build the destination pathname, replacing # forward slashes to platform specific separators. if targetpath[-1:] == "/": targetpath = targetpath[:-1] # don't include leading "/" from file name if present if os.path.isabs(member.filename): targetpath = os.path.join(targetpath, member.filename[1:]) else: targetpath = os.path.join(targetpath, member.filename) targetpath = os.path.normpath(targetpath) # Create all upper directories if necessary. upperdirs = os.path.dirname(targetpath) if upperdirs and not os.path.exists(upperdirs): os.makedirs(upperdirs) source = self.open(member, pwd=pwd) target = file(targetpath, "wb") shutil.copyfileobj(source, target) source.close() target.close() return targetpath def _writecheck(self, zinfo): """Check for errors before writing a file to the archive.""" if zinfo.filename in self.NameToInfo: if self.debug: # Warning for duplicate names print "Duplicate name:", zinfo.filename if self.mode not in ("w", "a"): raise RuntimeError, 'write() requires mode "w" or "a"' if not self.fp: raise RuntimeError, \ "Attempt to write ZIP archive that was already closed" if zinfo.compress_type == ZIP_DEFLATED and not zlib: raise RuntimeError, \ "Compression requires the (missing) zlib module" if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED): raise RuntimeError, \ "That compression method is not supported" if zinfo.file_size > ZIP64_LIMIT: if not self._allowZip64: raise LargeZipFile("Filesize would require ZIP64 extensions") if zinfo.header_offset > ZIP64_LIMIT: if not self._allowZip64: raise LargeZipFile("Zipfile size would require ZIP64 extensions") def write(self, filename, arcname=None, compress_type=None): """Put the bytes from filename into the archive under the name arcname.""" if not self.fp: raise RuntimeError( "Attempt to write to ZIP archive that was already closed") st = os.stat(filename) mtime = time.localtime(st.st_mtime) date_time = mtime[0:6] # Create ZipInfo instance to store file information if arcname is None: arcname = filename arcname = os.path.normpath(os.path.splitdrive(arcname)[1]) while arcname[0] in (os.sep, os.altsep): arcname = arcname[1:] zinfo = ZipInfo(arcname, date_time) zinfo.external_attr = (st[0] & 0xFFFF) << 16L # Unix attributes if compress_type is None: zinfo.compress_type = self.compression else: zinfo.compress_type = compress_type zinfo.file_size = st.st_size zinfo.flag_bits = 0x00 zinfo.header_offset = self.fp.tell() # Start of header bytes self._writecheck(zinfo) self._didModify = True fp = open(filename, "rb") # Must overwrite CRC and sizes with correct data later zinfo.CRC = CRC = 0 zinfo.compress_size = compress_size = 0 zinfo.file_size = file_size = 0 self.fp.write(zinfo.FileHeader()) if zinfo.compress_type == ZIP_DEFLATED: cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15) else: cmpr = None while 1: buf = fp.read(1024 * 8) if not buf: break file_size = file_size + len(buf) CRC = crc32(buf, CRC) & 0xffffffff if cmpr: buf = cmpr.compress(buf) compress_size = compress_size + len(buf) self.fp.write(buf) fp.close() if cmpr: buf = cmpr.flush() compress_size = compress_size + len(buf) self.fp.write(buf) zinfo.compress_size = compress_size else: zinfo.compress_size = file_size zinfo.CRC = CRC zinfo.file_size = file_size # Seek backwards and write CRC and file sizes position = self.fp.tell() # Preserve current position in file self.fp.seek(zinfo.header_offset + 14, 0) self.fp.write(struct.pack(" ZIP64_LIMIT \ or zinfo.compress_size > ZIP64_LIMIT: extra.append(zinfo.file_size) extra.append(zinfo.compress_size) file_size = 0xffffffff compress_size = 0xffffffff else: file_size = zinfo.file_size compress_size = zinfo.compress_size if zinfo.header_offset > ZIP64_LIMIT: extra.append(zinfo.header_offset) header_offset = 0xffffffffL else: header_offset = zinfo.header_offset extra_data = zinfo.extra if extra: # Append a ZIP64 field to the extra's extra_data = struct.pack( '>sys.stderr, (structCentralDir, stringCentralDir, create_version, zinfo.create_system, extract_version, zinfo.reserved, zinfo.flag_bits, zinfo.compress_type, dostime, dosdate, zinfo.CRC, compress_size, file_size, len(zinfo.filename), len(extra_data), len(zinfo.comment), 0, zinfo.internal_attr, zinfo.external_attr, header_offset) raise self.fp.write(centdir) self.fp.write(filename) self.fp.write(extra_data) self.fp.write(zinfo.comment) pos2 = self.fp.tell() # Write end-of-zip-archive record centDirOffset = pos1 if pos1 > ZIP64_LIMIT: # Need to write the ZIP64 end-of-archive records zip64endrec = struct.pack( structEndArchive64, stringEndArchive64, 44, 45, 45, 0, 0, count, count, pos2 - pos1, pos1) self.fp.write(zip64endrec) zip64locrec = struct.pack( structEndArchive64Locator, stringEndArchive64Locator, 0, pos2, 1) self.fp.write(zip64locrec) centDirOffset = 0xFFFFFFFF # check for valid comment length if len(self.comment) >= ZIP_MAX_COMMENT: if self.debug > 0: msg = 'Archive comment is too long; truncating to %d bytes' \ % ZIP_MAX_COMMENT self.comment = self.comment[:ZIP_MAX_COMMENT] endrec = struct.pack(structEndArchive, stringEndArchive, 0, 0, count % ZIP_FILECOUNT_LIMIT, count % ZIP_FILECOUNT_LIMIT, pos2 - pos1, centDirOffset, len(self.comment)) self.fp.write(endrec) self.fp.write(self.comment) self.fp.flush() if not self._filePassed: self.fp.close() self.fp = None class PyZipFile(ZipFile): """Class to create ZIP archives with Python library files and packages.""" def writepy(self, pathname, basename = ""): """Add all files from "pathname" to the ZIP archive. If pathname is a package directory, search the directory and all package subdirectories recursively for all *.py and enter the modules into the archive. If pathname is a plain directory, listdir *.py and enter all modules. Else, pathname must be a Python *.py file and the module will be put into the archive. Added modules are always module.pyo or module.pyc. This method will compile the module.py into module.pyc if necessary. """ dir, name = os.path.split(pathname) if os.path.isdir(pathname): initname = os.path.join(pathname, "__init__.py") if os.path.isfile(initname): # This is a package directory, add it if basename: basename = "%s/%s" % (basename, name) else: basename = name if self.debug: print "Adding package in", pathname, "as", basename fname, arcname = self._get_codename(initname[0:-3], basename) if self.debug: print "Adding", arcname self.write(fname, arcname) dirlist = os.listdir(pathname) dirlist.remove("__init__.py") # Add all *.py files and package subdirectories for filename in dirlist: path = os.path.join(pathname, filename) root, ext = os.path.splitext(filename) if os.path.isdir(path): if os.path.isfile(os.path.join(path, "__init__.py")): # This is a package directory, add it self.writepy(path, basename) # Recursive call elif ext == ".py": fname, arcname = self._get_codename(path[0:-3], basename) if self.debug: print "Adding", arcname self.write(fname, arcname) else: # This is NOT a package directory, add its files at top level if self.debug: print "Adding files from directory", pathname for filename in os.listdir(pathname): path = os.path.join(pathname, filename) root, ext = os.path.splitext(filename) if ext == ".py": fname, arcname = self._get_codename(path[0:-3], basename) if self.debug: print "Adding", arcname self.write(fname, arcname) else: if pathname[-3:] != ".py": raise RuntimeError, \ 'Files added with writepy() must end with ".py"' fname, arcname = self._get_codename(pathname[0:-3], basename) if self.debug: print "Adding file", arcname self.write(fname, arcname) def _get_codename(self, pathname, basename): """Return (filename, archivename) for the path. Given a module name path, return the correct file path and archive name, compiling if necessary. For example, given /python/lib/string, return (/python/lib/string.pyc, string). """ file_py = pathname + ".py" file_pyc = pathname + ".pyc" file_pyo = pathname + ".pyo" if os.path.isfile(file_pyo) and \ os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime: fname = file_pyo # Use .pyo file elif not os.path.isfile(file_pyc) or \ os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime: import py_compile if self.debug: print "Compiling", file_py try: py_compile.compile(file_py, file_pyc, None, True) except py_compile.PyCompileError,err: print err.msg fname = file_pyc else: fname = file_pyc archivename = os.path.split(fname)[1] if basename: archivename = "%s/%s" % (basename, archivename) return (fname, archivename) def main(args = None): import textwrap USAGE=textwrap.dedent("""\ Usage: zipfile.py -l zipfile.zip # Show listing of a zipfile zipfile.py -t zipfile.zip # Test if a zipfile is valid zipfile.py -e zipfile.zip target # Extract zipfile into target dir zipfile.py -c zipfile.zip src ... # Create zipfile from sources """) if args is None: args = sys.argv[1:] if not args or args[0] not in ('-l', '-c', '-e', '-t'): print USAGE sys.exit(1) if args[0] == '-l': if len(args) != 2: print USAGE sys.exit(1) zf = ZipFile(args[1], 'r') zf.printdir() zf.close() elif args[0] == '-t': if len(args) != 2: print USAGE sys.exit(1) zf = ZipFile(args[1], 'r') zf.testzip() print "Done testing" elif args[0] == '-e': if len(args) != 3: print USAGE sys.exit(1) zf = ZipFile(args[1], 'r') out = args[2] for path in zf.namelist(): if path.startswith('./'): tgt = os.path.join(out, path[2:]) else: tgt = os.path.join(out, path) tgtdir = os.path.dirname(tgt) if not os.path.exists(tgtdir): os.makedirs(tgtdir) fp = open(tgt, 'wb') fp.write(zf.read(path)) fp.close() zf.close() elif args[0] == '-c': if len(args) < 3: print USAGE sys.exit(1) def addToZip(zf, path, zippath): if os.path.isfile(path): zf.write(path, zippath, ZIP_DEFLATED) elif os.path.isdir(path): for nm in os.listdir(path): addToZip(zf, os.path.join(path, nm), os.path.join(zippath, nm)) # else: ignore zf = ZipFile(args[1], 'w', allowZip64=True) for src in args[2:]: addToZip(zf, src, os.path.basename(src)) zf.close() if __name__ == "__main__": main() dff-1.3.0+dfsg.1/dff/unsupported/archives/zip/unzip.py000066400000000000000000000145361217176075400226270ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_unzip_version__ = "1.0.0" from dff.api.vfs import vfs from dff.api.vfs.libvfs import VFS, FdManager, fdinfo, Node, fso from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.exceptions.libexceptions import vfsError, envError from dff.api.types.libtypes import vtime, Variant, VMap, Argument, typeId from dff.api.events.libevents import event import traceback import mzipfile class ZipNode(Node): __slots__ = ( 'orig_filename', 'filename', 'compress_type', 'comment', 'extra', 'create_system', 'create_version', 'extract_version', 'reserved', 'flag_bits', 'volume', 'internal_attr', 'external_attr', 'header_offset', 'CRC', 'compress_size', '_raw_time', ) def __init__(self, name, size, parent, fsobj, zipfile): Node.__init__(self, name, size, parent, fsobj) self.zipfile = zipfile self.setFile() self.reader = fsobj self.__disown__() def _attributes(self): attr = VMap() zipattr = self.reader.zipcontent.getinfo(self.zipfile) for key in ZipNode.__slots__: val = getattr(zipattr, key) if key != "date_time": attr[key] = Variant(val) vt = vtime() vt.thisown = False vt.year = zipattr.date_time[0] vt.month = zipattr.date_time[1] vt.day = zipattr.date_time[2] vt.hour = zipattr.date_time[3] vt.minute = zipattr.date_time[4] vt.second = zipattr.date_time[5] attr["create"] = Variant(vt) return attr class UNZIP(fso): def __init__(self): fso.__init__(self, "unzip") self.name = "unzip" self.VFS = VFS.Get() self.vfs = vfs.vfs() self.fdm = FdManager() self.origin = None self.zipcontent = None self.file = None self.mapped_files = {} def start(self, args): origin = args['file'].value() self.makeZipTree(origin) def makeZipTree(self, origin): self.origin = origin self.file = self.origin.open() self.zipcontent = mzipfile.ZipFile(self.file) for zipfile in self.zipcontent.namelist(): idx = zipfile.rfind("/") if idx != -1: path = zipfile[:idx] filename = zipfile[idx+1:] else: path = "" filename = zipfile parent = self.vfs.getnode(self.origin.absolute() + "/" + path) if parent == None: parent = self.makeDirs(path) attr = self.zipcontent.getinfo(zipfile) node = ZipNode(filename, attr.file_size, parent, self, zipfile) node.__disown__() e = event() e.value = Variant(self.origin) self.VFS.notify(e) def makeDirs(self, folders): sfolders = folders.split("/") prev = self.origin for folder in sfolders: node = self.vfs.getnode(prev.absolute() + "/" + folder) if node == None: node = Node(folder, 0, prev, self) node.setDir() node.__disown__() prev = node return node def mappedFile(self, zipfile): info = self.zipcontent.getinfo(zipfile) buff = "" if info.file_size > 0: buff = self.zipcontent.read(zipfile) return buff def nodeToZipFile(self, node): abs = node.absolute() orig = self.origin.absolute() zipfile = abs.replace(orig, "")[1:] return zipfile def vopen(self, node): if not node.size(): return 0 zipfile = self.nodeToZipFile(node) if zipfile in self.mapped_files.keys(): buff = self.mapped_files[zipfile]["buff"] self.mapped_files[zipfile]["opened"] += 1 else: buff = self.mappedFile(zipfile) self.mapped_files[zipfile] = {} self.mapped_files[zipfile]["buff"] = buff self.mapped_files[zipfile]["opened"] = 1 fi = fdinfo() fi.thisown = False fi.node = node fi.offset = 0 fd = self.fdm.push(fi) return fd def vread(self, fd, buff, size): fi = self.fdm.get(fd) zipfile = self.nodeToZipFile(fi.node) buff = self.mapped_files[zipfile]["buff"] if fi.node.size() < fi.offset + size: size = fi.node.size() - fi.offset if size <= 0: return (0, "") else: res = (size, buff[fi.offset:fi.offset+size]) fi.offset += size return res def vseek(self, fd, offset, whence): fi = self.fdm.get(fd) if whence == 0: if offset <= fi.node.size(): fi.offset = offset else: formatted_lines = traceback.format_exc().splitlines() raise vfsError("[unzip::vseek]" + formatted_lines[-1]) if whence == 1: if fi.offset + offset > fi.node.size(): fi.offset += offset else: formatted_lines = traceback.format_exc().splitlines() raise vfsError("[unzip::vseek]" + formatted_lines[-1]) if whence == 2: fi.offset = fi.node.size() return fi.offset def vclose(self, fd): try: fi = self.fdm.get(fd) zipfile = self.nodeToZipFile(fi.node) self.fdm.remove(fd) if self.mapped_files[zipfile]["opened"] == 1: del self.mapped_files[zipfile] else: self.mapped_files[zipfile]["opened"] -= 1 return 0 except: return 0 def vtell(self, fd): fi = self.fdm.get(fd) return fi.offset def status(self): return len(self.mapped_files) class unzip(Module): """Decompress zip file and create their content in virtual memory through module SHM. This version of unzip store all data in RAM so don't decompress huge file.""" def __init__(self): Module.__init__(self, "unzip", UNZIP) self.conf.addArgument({"name": "file", "input": Argument.Required|Argument.Single|typeId.Node, "description": "zip file to decompress" }) self.conf.addConstant({"name": "mime-type", "type": typeId.String, "description": "managed mime type", "values": ["Zip"]}) self.tags = "Archives" self.icon = ":zip" dff-1.3.0+dfsg.1/dff/unsupported/crypto/000077500000000000000000000000001217176075400200115ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/crypto/CMakeLists.txt000066400000000000000000000011251217176075400225500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin install_file( __init__.py unxor.py ) dff-1.3.0+dfsg.1/dff/unsupported/crypto/__init__.py000066400000000000000000000011001217176075400221120ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['unxor'] dff-1.3.0+dfsg.1/dff/unsupported/crypto/unxor.py000066400000000000000000000043451217176075400215440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_unxor_version__ = "1.0.0" from dff.api.module import * from dff.api.exceptions.libexceptions import * from dff.api.types.libtypes import Argument, typeId, Variant from dff.modules.shm.touch import * class UNXOR(Script): def __init__(self): Script.__init__(self, "unxor") self.vfs = vfs.vfs() self.touch = TOUCH().touch def start(self, args): try: node = args['file'].value() key = args['key'].value() res = self.unxor(node, key) self.res["result"] = Variant(res) except: pass def unxor(self, node, key): dfilename = node.absolute() + "/decrypted" dfile = self.touch(dfilename).open() file = node.open() decrypt = "" ki = 0 try: buff = file.read(4096) except vfsError, e: return "error" while len(buff) > 0: for x in range(len(buff)): dfile.write(chr(ord(buff[x]) ^ ord(key[ki]))) ki = (ki + 1) % len(key) try: buff = file.read(4096) except vfsError, e: file.close() dfile.close() return dfilename + " decrypted" file.close() dfile.close() return dfilename + " decrypted" class unxor(Module): """Decrypt a XORed file ex: unxor /myfile key""" def __init__(self): Module.__init__(self, "unxor", UNXOR) self.conf.addArgument({"name": "file", "description": "xored file", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "key", "description": "key to unxor", "input": Argument.Required|Argument.Single|typeId.String}) self.tags = "Crypto" self.icon = ":unlock" dff-1.3.0+dfsg.1/dff/unsupported/node/000077500000000000000000000000001217176075400174165ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/node/CMakeLists.txt000066400000000000000000000011571217176075400221620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file(fchunks.py) dff-1.3.0+dfsg.1/dff/unsupported/node/fchunks.py000066400000000000000000000061011217176075400214270ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_merge_version__ = "1.0.0" import time from dff.api.module.module import Module from dff.api.module.script import Script from dff.api.types.libtypes import Variant, VList, VMap, Argument, Parameter, typeId from dff.api.search.libsearch import Search class FCHUNKS(Script): def __init__(self): Script.__init__(self, "fchunks") def start(self, args): self.sample = args['sample'].value() self.dump = args['dump'].value() if args.has_key("chunk_size"): self.csize = args["chunk_size"].value() else: self.csize = 512 self.search = Search() self.search.setPatternSyntax(Search.Fixed) self.search.setCaseSensitivity(Search.CaseSensitive) fdump = self.dump.open() fsample = self.sample.open() stime = time.time() buff = fdump.read(10*1024*1024) while len(buff) > 0: fsample.seek(0) buff2 = fsample.read(self.csize) while len(buff2) > 0: self.search.setPattern(buff2) idx = self.search.find(buff) if idx != -1: print hex(fsample.tell()-len(buff2)), "--", hex(fsample.tell()), " matched @ ", hex(fdump.tell()-len(buff)+idx) buff2 = fsample.read(self.csize) buff = fdump.read(10*1024*1024) print fdump.tell(), "/", self.dump.size() print "run in: ", time.time() - stime fsample.close() fdump.close() class fchunks(Module): """This module is designed to concat 2 files.""" def __init__(self): Module.__init__(self, "fchunks", FCHUNKS) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "sample", "description": "each fragment of this file will be search in the reference dump" }) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "dump", "description": "the dump where to look for the fragments" }) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.UInt32, "name": "chunk_size", "description": "minimum size of chunk to look for (default is 512)", "parameters": {"type": Parameter.Editable, "predefined": [512, 1024, 2048, 4096, 8192]} }) self.tags = "Node" dff-1.3.0+dfsg.1/dff/unsupported/phone/000077500000000000000000000000001217176075400176025ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/phone/CMakeLists.txt000066400000000000000000000011371217176075400223440ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( smsdecode.py ) add_subdirectory (k800i) dff-1.3.0+dfsg.1/dff/unsupported/phone/__init__.py000066400000000000000000000011151217176075400217110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['smsdecode', 'k800i'] dff-1.3.0+dfsg.1/dff/unsupported/phone/k800i/000077500000000000000000000000001217176075400204355ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/phone/k800i/CMakeLists.txt000066400000000000000000000011411217176075400231720ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( K800i.py K800iRecover.py __init__.py ) dff-1.3.0+dfsg.1/dff/unsupported/phone/k800i/K800i.py000066400000000000000000000347301217176075400216110ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_K800i_version__ = "1.0.0" from struct import unpack from dff.api.vfs import * from dff.api.module.module import * from dff.api.types.libtypes import Variant, VMap, Argument, typeId, Parameter from dff.api.vfs.libvfs import * from dff.modules.spare import SpareNode class SEPartition(): def __init__(self, buff): self.name = unpack('28s', buff[0:28])[0] self.name = self.name[:self.name.find('\x00')] self.val1 = unpack('> 16) mask = mask << 16 virtblock = (table.blockList[0][block] ^ mask) - 1 realblock = (table.mapId *960 + block) if virtblock <= self.nblocks: try : omap = self.imap[virtblock][0] oblock = self.imap[virtblock][1] self.aalloc += 1 except KeyError: self.map[virtblock] = realblock self.imap[virtblock] = (table, block) def fileMapping(self, fm): for block in xrange(0, self.nblocks): try : realblock = self.map[block] except KeyError: realblock = block if realblock >= self.nblocks: fm.push(block * self.blockSize, self.blockSize) else: fm.push(block * self.blockSize, self.blockSize, self.fullfs, realblock * self.blockSize) def _attributes(self): attr = VMap() vmap = VMap() for t in self.tables.map: vmap[hex(t)] = Variant(hex(self.tables.map[t].write)) attr["tables"] = Variant(vmap) attr["reallocated blocks"] = Variant(self.aalloc) return attr class Partition(Node): def __init__(self, mfso, parent, virtual, partTable, blockSize): self.ssize = partTable.size * blockSize Node.__init__(self, "part_" + str(partTable.name[1:]), self.ssize, parent, mfso) self.__disown__() self.virtual = virtual self.blockSize = blockSize self.partTable = partTable self.setFile() def fileMapping(self, fm): startOff = (self.partTable.start - 1) * self.blockSize if (startOff + self.ssize) > self.virtual.size(): leak = (startOff + self.ssize) - self.virtual.size() leakOff = self.virtual.size() - startOff fm.push(0, leakOff, self.virtual, startOff) fm.push(leakOff, leak) else: fm.push(0, self.ssize, self.virtual, startOff) def _attributes(self): attr = VMap() attr["partition start"] = Variant(self.partTable.start) attr["blocksize"] = Variant(self.partTable.blocksize) attr["size in block"] = Variant(self.partTable.size) return attr class K800I(mfso): def __init__(self): mfso.__init__(self, "K800i") self.name = "K800i" self.__disown__() def start(self, args): try: self.nor = args['nor'].value() self.nand = args['nand'].value() except IndexError: return try: self.spareSize = args["spare-size"].value() except IndexError: self.spareSize = 16 try: self.pageSize = args["page-size"].value() except IndexError: self.pageSize = 512 self.k800n = Node("k800") self.k800n.__disown__() self.boot = SEBootBlock(self.nor, self.pageSize) self.blockSize = self.boot.blockSize self.nandClean = SpareNode(self, self.nand, "nandfs", self.pageSize, self.spareSize, self.k800n) self.norFs = NorFs(self, self.k800n, self.nor, "norfs", self.boot) self.fullFs = FullFs(self, self.k800n, self.norFs, self.nandClean, "fullfs", self.boot) self.gdfs = GDFS(self, self.k800n, self.nor, "gdfs", self.boot) self.firmware = Firmware(self, self.k800n, self.nor, "firmware", self.boot.norfsoffset) self.tables = Tables(self.fullFs, self.blockSize) self.virtual = VirtualMap(self, self.k800n, self.fullFs, self.tables, "virtual", self.blockSize) self.separt = SEPartitionBlock(self.virtual, self.boot.partitionblock, self.blockSize) self.createPart() self.registerTree(self.nand, self.k800n) def createPart(self): for part in self.separt.partTable: if part.start > 0: p = Partition(self, self.k800n, self.virtual, part, self.blockSize) class K800i(Module): """This modules permit to browse the content of a K800i phones.""" def __init__(self): Module.__init__(self, "k800i", K800I) self.conf.addArgument({"name": "nor", "description": "K800i nor dump", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "nand", "description": "K800i nand dump", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "spare-size", "description": "size of nand spare", "input": Argument.Optional|Argument.Single|typeId.UInt32, "parameters": {"type": Parameter.Editable, "predefined": [16, 8, 32, 64]} }) self.conf.addArgument({"name": "page-size", "description": "size of nand page", "input": Argument.Optional|Argument.Single|typeId.UInt32, "parameters": {"type": Parameter.Editable, "predefined": [512, 256, 1024, 2048, 4096]} }) self.tags = "Mobile" dff-1.3.0+dfsg.1/dff/unsupported/phone/k800i/K800iRecover.py000066400000000000000000000167141217176075400231410ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob < sja@arxsys.fr> # __dff_module_K800iRecover_version__ = "1.0.0" import sys from struct import unpack from PyQt4 import QtCore, QtGui, Qt from PyQt4.QtCore import Qt, QSize, QString, SIGNAL, QThread, SLOT, QSignalMapper from PyQt4.QtGui import QPushButton, QLabel, QWidget, QHBoxLayout, QVBoxLayout, QScrollArea, QIcon, QTableWidget, QTableWidgetItem, QComboBox, QInputDialog, QLineEdit, QSplitter, QMessageBox from dff.api.vfs import vfs from dff.api.module.module import * from dff.api.types.libtypes import Parameter, Argument, typeId, Variant from dff.api.vfs.libvfs import * from dff.modules.spare import SpareNode from dff.modules.k800i.K800i import * class K800IRec(QWidget, mfso): def __init__(self): mfso.__init__(self, "K800i-Recover") self.name = "K800i-Recover" self.icon = None self.__disown__() def start(self, args): self.vfs = vfs.vfs() self.dumpnumber = 1 try : self.nor = args['nor'].value() self.nand = args['nand'].value() except IndexError: return try: self.spareSize = args["spare-size"].value() except IndexError: self.spareSize = 16 try: self.pageSize = args["page-size"].value() except IndexError: self.pageSize = 512 self.k800n = Node("k800-base") self.k800n.__disown__() self.boot = SEBootBlock(self.nor, self.pageSize) self.blockSize = self.boot.blockSize self.nandClean = SpareNode(self, self.nand, "nandfs", self.pageSize, self.spareSize, self.k800n) self.norFs = NorFs(self, self.k800n, self.nor, "norfs", self.boot) self.fullFs = FullFs(self, self.k800n, self.norFs, self.nandClean, "fullfs", self.boot) self.gdfs = GDFS(self, self.k800n, self.nor, "gdfs", self.boot) self.firmware = Firmware(self, self.k800n, self.nor, "firmware", self.boot.norfsoffset) self.tables = Tables(self.fullFs, self.blockSize) self.registerTree(self.nand, self.k800n) def createDump(self): text, ok = QInputDialog.getText(self, "Create dump", "dump name:", QLineEdit.Normal, "k800-restore-" + str(self.dumpnumber)) if ok and text != "": if (self.vfs.getnode(self.nand.absolute() + "/" + str(text)) == None): self.dumpnumber += 1 newroot = Node(str(text)) newroot.__disown__() for id in range(0, len(self.tables.tablesIdWriteMap) - 1): write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16) self.tables.map[id] = self.tables.tablesIdWriteMap[id][write] virtual = VirtualMap(self, newroot, self.fullFs, self.tables, "virtual", self.blockSize) separt = SEPartitionBlock(virtual, self.boot.partitionblock, self.blockSize) self.createPart(separt, newroot, virtual) self.registerTree(self.nand, newroot) else : box = QMessageBox(QMessageBox.Warning, "Error", "Error node already exists", QMessageBox.NoButton, self) box.exec_() self.createDump() def createPart(self, separt, newroot, virtual): for part in separt.partTable: if part.start > 0: p = Partition(self, newroot, virtual, part, self.blockSize) def g_display(self): QWidget.__init__(self, None) self.layout = QVBoxLayout(self) self.hlayout = QSplitter(self) self.layout.insertWidget(0, self.hlayout) self.layout.setStretchFactor(self.hlayout, 1) self.gTable() self.viewTable() self.button = QPushButton("&Create dump") self.connect(self.button, SIGNAL("clicked()"), self.createDump) self.layout.addWidget(self.button) def viewTable(self): self.vtable = QTableWidget() self.vtable.setColumnCount(20) self.vtable.setRowCount(48) self.hlayout.addWidget(self.vtable) def viewTableUpdate(self, id): write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16) t = self.tables.tablesIdWriteMap[id][write] l = t.blockList for x in xrange(0, len(t.blockList[0])): block = t.blockList[0][x] c = ((x) % 20) r = ((x) / 20) item = QTableWidgetItem(QString(hex(block))) tipBlock = (id * 960) + x item.setToolTip(QString(hex(tipBlock))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.vtable.setItem(r ,c, item) def gTable(self): self.gtable = QTableWidget() self.gtable.setColumnCount(1) self.gtable.setRowCount(len(self.tables.tablesIdWriteMap)) self.gtable.setHorizontalHeaderItem(0, QTableWidgetItem(QString("version"))) self.hlayout.addWidget(self.gtable) self.sigMapper = QSignalMapper(self) for id in self.tables.tablesIdWriteMap: wlist = self.tables.tablesIdWriteMap[id] cbox = QComboBox(self.gtable) self.connect(cbox, SIGNAL("activated(QString)"), self.sigMapper, SLOT("map()")) self.sigMapper.setMapping(cbox, id) l = [] for write in wlist: l.append(write) l.sort() l.reverse() for write in l: cbox.addItem(QString(hex(write))) self.gtable.setCellWidget(id, 0, cbox) self.gtable.setVerticalHeaderItem(id, QTableWidgetItem(QString(hex(id)))) self.connect(self.sigMapper, SIGNAL("mapped(int)"), self.viewTableUpdate) self.gtable.setMaximumWidth(self.gtable.columnWidth(0) + self.gtable.verticalHeader().sectionSize(0) + 30) def updateWidget(self): pass class K800iRecover(Module): """This modules give access to K800i block-versioning table and permit to generate virtual mapping and partitions according to the choosen table. By choosing different table you could come back to previous version of the filesystem and recover deleted files""" def __init__(self): Module.__init__(self, "K800i-Recover", K800IRec) self.conf.addArgument({"name": "nor", "description": "K800i nor dump", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "nand", "description": "K800i nand dump", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "spare-size", "description": "size of nand spare", "input": Argument.Optional|Argument.Single|typeId.UInt32, "parameters": {"type": Parameter.Editable, "predefined": [16, 8, 32, 64]} }) self.conf.addArgument({"name": "page-size", "description": "size of nand page", "input": Argument.Optional|Argument.Single|typeId.UInt32, "parameters": {"type": Parameter.Editable, "predefined": [512, 256, 1024, 2048, 4096]} }) self.tags = "Mobile" dff-1.3.0+dfsg.1/dff/unsupported/phone/k800i/__init__.py000066400000000000000000000011731217176075400225500ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob __all__ = ['K800i', 'K800iRecover'] dff-1.3.0+dfsg.1/dff/unsupported/phone/smsdecode.py000066400000000000000000000163661217176075400221360ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_smsdecode_version__ = "1.0.0" import struct import binascii from dff.api.vfs import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import Argument, typeId, Variant class SMS(Script): def __init__(self): Script.__init__(self, "smsdecode") def start(self, args): try : node = args["file"].value() self.unpack(node) if args.has_key("header"): res = self.header() else: res = self.info() self.res["result"] = Variant(res) except KeyError: pass def unpack(self, node): self.vfs = vfs.vfs() f = node.open() buff = f.read() f.close() off = 0 self.status = struct.unpack('B', buff[off]) off += 1 self.smsc_info_len = struct.unpack('B', buff[off]) off += 1 self.smsc_info_type_of_addr = struct.unpack('B', buff[off]) off += 1 self.smsc_info_center_number_len = self.smsc_info_len[0] - 1 noff = off noff += self.smsc_info_center_number_len self.smsc_info_center_number_oct = struct.unpack(str(self.smsc_info_center_number_len) + 'B', buff[off:noff]) off = noff if (("%x" % self.smsc_info_type_of_addr) == "91"): self.smsc_info_center_number = "+" else: self.smsc_info_center_number = "" for i in self.smsc_info_center_number_oct: self.smsc_info_center_number += self.byte_swap(i) if i < 10: self.smsc_info_center_number += "0" self.smsc_info_center_number = self.smsc_info_center_number.strip('f') self.sms_deliver_msg_start = struct.unpack('B', buff[off]) off += 1 self.sender_number_len_dig = struct.unpack('B', buff[off]) off += 1 self.sender_number_type = struct.unpack('B', buff[off]) off += 1 self.sender_number_len_oct = self.sender_number_len_dig[0] / 2 if self.sender_number_len_dig[0] % 2: self.sender_number_len_oct += 1 noff = off + self.sender_number_len_oct self.sender_number_oct = struct.unpack(str(self.sender_number_len_oct) + 'B', buff[off:noff]) off = noff if (("%x" % self.sender_number_type) == "91"): self.sender_number = "+" else: self.sender_number = "" for i in self.sender_number_oct: self.sender_number += self.byte_swap(i) if i < 10: self.sender_number +="0" self.sender_number = self.sender_number.strip('f') self.tp_pid = struct.unpack('B', buff[off]) off += 1 self.tp_dcs = struct.unpack('B', buff[off]) off += 1 noff = off + 7 self.timestamp = struct.unpack('7B', buff[off:noff]) off = noff self.tp_udl = struct.unpack('B', buff[off]) off += 1 if self.tp_dcs[0]: self.sms_len = self.tp_udl[0] else: self.sms_len = self.tp_udl[0] - (self.tp_udl[0] / 8) noff = off + self.sms_len self.sms_byte = struct.unpack(str(self.sms_len) + 'B', buff[off:noff]) self.sms_buff = self.s7bit_to_ascii(self.sms_byte) self.year = self.byte_swap(self.timestamp[0]) self.month = self.byte_swap(self.timestamp[1]) self.day = self.byte_swap(self.timestamp[2]) self.hour = self.byte_swap(self.timestamp[3]) self.minute = self.byte_swap(self.timestamp[4]) self.second = self.byte_swap(self.timestamp[5]) self.gmt = self.byte_swap(self.timestamp[6]) def byte_swap(self, buff): tmp = "%x" % buff if len(tmp) == 1: return tmp[0] return tmp[1] + tmp[0] def tup_hex(self, buff): res = "" for i in buff: res += "%x" % i return res def byte_to_bits_string(self, x): return "".join(map(lambda y:str((x>>y)&1), range(7, -1, -1))) def bytes_to_bits(self, bytes): bits_list = [] for i in bytes: bits_list += self.byte_to_bits_string(i)[::-1] return bits_list def s7bit_to_ascii(self, buff): bits_list = self.bytes_to_bits(buff) i = 0 lchar = "" while i < len(bits_list): x = 6 bstr = "0" while x >= 0: if (x+i) < len(bits_list): bstr += bits_list[x+i] x -= 1 else: return lchar i += 7 lchar += "%c" % int(bstr, 2) return lchar def header(self): h = "" h += "Status 0x%x\n" % self.status h += "SMSC information, length: %d octets\n" % self.smsc_info_len h += "SMSC information, type of address: 0x%x \n" % self.smsc_info_type_of_addr h += "debug SMSC information, center number length: %d octects\n" % self.smsc_info_center_number_len h += "SMSC information, center number: " + self.tup_hex(self.smsc_info_center_number_oct) + "\n" h += "SMS-Deliver message first octect: 0x%x\n" % self.sms_deliver_msg_start h += "Length of the sender number: %d digits\n" % self.sender_number_len_dig h += "Length of the sender number: %d octet\n" % self.sender_number_len_oct h += "Type of sender number: 0x%x\n" % self.sender_number_type h += "Sender number: " + self.tup_hex(self.sender_number_oct) + "\n" h += "TP Protocol Identifier: 0x%x\n" % self.tp_pid h += "TP Data coding scheme: 0x%x\n" % self.tp_dcs h += "Time Stamp: "+ self.tup_hex(self.timestamp) + "\n" if self.tp_dcs[0]: h += "TP User data length: %d in octect\n" % self.sms_len else: h += "TP User data length: %d in septet \n" % self.sms_len h += "SMS buff: " + self.sms_buff + "\n" return h def info(self): i = "" if self.status[0] == 0: i += "Status: unused\n" elif self.status[0] == 1: i += "Status: read\n" elif self.status[0] == 3: i += "Status: unread\n" elif self.status[0] == 5: i += "Status: send\n" elif self.status[0] == 7: i += "Status: unsend\n" i += "Center number: " + self.smsc_info_center_number + "\n" i += "Sender number: " + self.sender_number + "\n" i += "Date :" + self.day + "/" + self.month + "/" + self.year + " " + self.hour + ":" + self.minute + ":" + self.second + " GMT:" + self.gmt + "\n" i += "Message : " + self.sms_buff + "\n" return i class smsdecode(Module): """ A sms decoder. ex: smsdecode /myfile.sms""" def __init__(self): Module.__init__(self, "smsdecode", SMS) self.conf.addArgument({"name": "file", "description": "SMS file", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "header", "description": "Display detailed SMS header information", "input": Argument.Empty}) self.tags = "Mobile" dff-1.3.0+dfsg.1/dff/unsupported/process/000077500000000000000000000000001217176075400201475ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/process/CMakeLists.txt000066400000000000000000000011451217176075400227100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( evalexp.py post_process.py pipe_exec.py ) dff-1.3.0+dfsg.1/dff/unsupported/process/__init__.py000066400000000000000000000011471217176075400222630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ['batch', 'evalexpr', 'post_process', 'extract'] dff-1.3.0+dfsg.1/dff/unsupported/process/evalexp.py000066400000000000000000000025661217176075400221760ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_evalexp_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module.module import * from dff.api.module.script import * from dff.api.types.libtypes import typeId, Argument, Variant class EVAL(Script): def __init__(self): Script.__init__(self, "eval") def start(self, args): try: expr = args["expression"].value() except IndexError: raise envError("modules evalexp need an expression to evaluate") buff = eval(expr) self.res["result"] = Variant(buff) class evalexp(Module): """Calculate a mathematical expression Ex: evalexp 2+2""" def __init__(self): Module.__init__(self, "eval", EVAL) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.String, "name":"expression", "description":"expression to compute" }) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/unsupported/process/pipe_exec.py000066400000000000000000000034041217176075400224630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_pipe_exec_version__ = "1.0.0" from subprocess import * from dff.api.vfs import * from dff.api.module.script import * from dff.api.module.module import * from dff.api.types.libtypes import typeId, Argument class PIPE_EXEC(Script): def __init__(self): Script.__init__(self, "pipe_exec") self.vfs = vfs.vfs() def start(self, args): try: cmd = args["command"].value() node = args["file"].value() except IndexError : raise envError("pipe_exec need command and file value.") file = node.open() buff = file.read() file.close() Popen(cmd,1, shell=1, stdin=PIPE).communicate(buff) class pipe_exec(Module): """open a file and pipe it to an external command ex: exec_pipe /file.txt less Take care this use as many ram as the file size, must be used for test purpose only.""" def __init__(self): Module.__init__(self, "pipe_exec", PIPE_EXEC) self.conf.addArgument({"name":"file", "description":"File to pipe.", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name":"command", "description":"External command line to execute.", "input": Argument.Required|Argument.Single|typeId.String}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/unsupported/process/post_process.py000066400000000000000000000026171217176075400232520ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_postprocess_version__ = "1.0.0" from dff.api.module.script import Script from dff.api.taskmanager.taskmanager import TaskManager from dff.api.module.module import Module from dff.api.types.libtypes import Variant, Argument, typeId, ConfigManager class POST_PROCESS(Script): def __init__(self): Script.__init__(self, "post_process") self.tm = TaskManager() def start(self, args): mod = args["module"] if mod: self.tm.addPostProcess(str(mod)) return class post_process(Module): """Process a command on each new file created on the vfs""" def __init__(self): Module.__init__(self, "post_process", POST_PROCESS) self.conf.addArgument({"name":"module", "description": "Module to add to the post processing list", "input" : Argument.Required|Argument.Single|typeId.String}) self.tags = "builtins" dff-1.3.0+dfsg.1/dff/unsupported/search/000077500000000000000000000000001217176075400177365ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/search/CMakeLists.txt000066400000000000000000000011601217176075400224740ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob add_subdirectory(indexer) dff-1.3.0+dfsg.1/dff/unsupported/search/indexer/000077500000000000000000000000001217176075400213745ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/search/indexer/CMakeLists.txt000066400000000000000000000034731217176075400241430ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon # Christophe Malinge if(${CLUCENE_CONFIG_INCLUDE_PATH} AND ${CLUCENE_LIBRARY}) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) include_directories(${PYTHON_INCLUDE_PATH} ${QT_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/api/include ${CMAKE_HOME_DIRECTORY}/api/tree ${CMAKE_HOME_DIRECTORY}/api/index/ ${CMAKE_HOME_DIRECTORY}/api/index/CLucene ${CLUCENE_CONFIG_INCLUDE_PATH}) set(indexer_srcs indexer.cpp ) set_source_files_properties(indexer.i PROPERTIES CPLUSPLUS ON) swig_add_module(INDEXER python indexer.i ${indexer_srcs}) if (UNIX) swig_link_libraries(INDEXER ${PYTHON_LIBRARIES} exceptions vfs tree libindex) else (UNIX) swig_link_libraries(INDEXER ${PYTHON_LIBRARIES} exceptions vfs tree libindex ${QT_QTCORE_LIBRARIES} ${QT_QTCLUCENE_LIBRARIES}) endif (UNIX) if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(${SWIG_MODULE_INDEXER_REAL_NAME} PROPERTIES PREFIX "../" SUFFIX ".pyd" ) endif(CMAKE_GENERATOR MATCHES "Visual Studio") set(indexer_files INDEXER.py ) install_lib(${SWIG_MODULE_INDEXER_REAL_NAME}) install_file(indexer ${indexer_files}) endif(${CLUCENE_CONFIG_INCLUDE_PATH} AND ${CLUCENE_LIBRARY}) dff-1.3.0+dfsg.1/dff/unsupported/search/indexer/indexer.cpp000066400000000000000000000042421217176075400235400ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include #include #include "indexer.hpp" #include "variant.hpp" Indexer::Indexer() : mfso("Indexer"), __node(NULL), __index(NULL) { } Indexer::~Indexer() { } void Indexer::start(std::map args) { try { std::map::iterator it; it = args.find("node"); if (it == args.end()) { std::cerr << "Cannot load 'node' argument. Exiting module." << std::endl; return ; } this->__node = it->second->value(); it = args.find("index"); if (it == args.end()) { std::cerr << "Cannot load 'index' argument. Exiting module." << std::endl; return ; } std::string path = it->second->value(); __index = new Index(path); if (!__index->createIndex()) { std::cerr << "Could not create index. Modules 'indexer' will stop." << std::endl; this->stateinfo = std::string("An error occured while creating the index."); return ; } this->__recurseNode(this->__node); this->__index->closeIndex(); delete __index; } catch(vfsError & e) { this->stateinfo = e.error; } return ; } void Indexer::__recurseNode(Node * node) { if (!node) return ; if (node->size() && node->isFile()) this->__index->indexData(node); if (node->hasChildren()) // if the node has children, get all of them { std::vector nodes_list = node->children(); std::vector::iterator it, end; end = nodes_list.end(); for (it = nodes_list.begin(); it != end; it++) this->__recurseNode(*it); } } dff-1.3.0+dfsg.1/dff/unsupported/search/indexer/indexer.hpp000066400000000000000000000017531217176075400235510ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #ifndef __INDEXER_H_ # define __INDEXER_H_ #include "vfs.hpp" #include "argument.hpp" #include "mfso.hpp" #include "index.hpp" class Indexer : public mfso { public: Indexer(); ~Indexer(); virtual void start(std::maparg); private: Node * __node; Index * __index; private: void __recurseNode(Node * node); }; #endif /* __INDEXER_H_ */ dff-1.3.0+dfsg.1/dff/unsupported/search/indexer/indexer.i000066400000000000000000000037051217176075400232110ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Romain Bertholon * */ #include "pyrun.swg" %module INDEXER #ifndef WIN32 %include "stdint.i" #else %include "wstdint.i" #endif %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "std_vector.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "mfso.hpp" #include "node.hpp" #include "vfile.hpp" #include "vlink.hpp" #include "index.hpp" #include "indexer.hpp" %} %import "../../../api/vfs/libvfs.i" %include "indexer.hpp" /* namespace std { }; */ %pythoncode %{ from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId, Variant, Parameter from dff.ui.conf import Conf from PyQt4.QtCore import QDir class INDEXER(Module): """This module is a dff module.""" def __init__(self): Module.__init__(self, 'indexer', Indexer) self.dff_conf = Conf() path = self.dff_conf.index_path self.conf.addArgument({"name": "node", "description": "dir to index", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.String, "name": "index", "description": "directory where the index will be stored", "parameters": {"type": Parameter.NotEditable, "predefined": [str(path)]} }) self.tags = "Search" self.icon = ":index" %} dff-1.3.0+dfsg.1/dff/unsupported/test/000077500000000000000000000000001217176075400174505ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/test/CMakeLists.txt000066400000000000000000000011621217176075400222100ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob install_file( huge_node.py gen_nodes.py ) add_subdirectory(readlines) dff-1.3.0+dfsg.1/dff/unsupported/test/gen_nodes.py000066400000000000000000000055701217176075400217720ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_gen_nodes_version__ = "1.0.0" from struct import unpack from dff.api.types.libtypes import Variant, VMap, Parameter, Argument, typeId from dff.api.vfs.libvfs import AttributesHandler from dff.api.vfs.vfs import vfs from dff.api.module.module import Module from dff.api.vfs.libvfs import mfso, Node class GenNodes(mfso): def __init__(self): mfso.__init__(self, "GenNodes") self.name = "GenNodes" self.__disown__() def start(self, args): self.parent = args["parent"].value() if args.has_key("count"): self.count = args["count"].value() else: self.count = 50000 #self.start = args["start_offset"].value() #self.number_of_nodes = args["number_of_nodes"].value() self.root = Node("node-test") self.__disown__() for x in xrange(0, self.count): xnode = Node(str(x), 0, self.root, self) if (x % 10000) == 0: print "have create " + str(x) + " nodes" xnode.setDir() xnode.__disown__() self.registerTree(self.parent, self.root) class gen_nodes(Module): """This modules permit to test the framework by generating a large amount of nodes.""" def __init__(self): Module.__init__(self, "gen_nodes", GenNodes) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.Node, "name": "parent", "description": "files or folders will be added as child(ren) of this node or as the root node by default", "parameters": {"type": Parameter.Editable, "predefined": [vfs().getnode("/")]} }) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.UInt64, "name": "count", "description": "number of nodes to create", "parameters:": {"type": Parameter.Editable, "predefined": [1000, 5000, 10000, 25000, 50000, 70000, 100000, 500000, 1000000, 2**64-1]} }) #self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.UInt64, #"name": "start_offset", #"description": "Address start of the new node" #}) self.tags = "Node" dff-1.3.0+dfsg.1/dff/unsupported/test/huge_node.py000066400000000000000000000041541217176075400217630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_gen_nodes_version__ = "1.0.0" from struct import unpack from dff.api.types.libtypes import Variant, VMap, Parameter, Argument, typeId from dff.api.vfs.libvfs import AttributesHandler, mfso, Node from dff.api.vfs.vfs import vfs from dff.api.module.module import Module class HugeNode(Node): def __init__(self, mfso, name, size): Node.__init__(self, name, size, None, mfso) self.__disown__() def fileMapping(self, fm): fm.push(0, self.size(), None, 0) def _attributes(self): vm = VMap() return vm class HugeNodes(mfso): def __init__(self): mfso.__init__(self, "HugeNodes") self.name = "HugeNodes" self.__disown__() def start(self, args): self.parent = args["parent"].value() hn = HugeNode(self, "huge node " + str(2**64-1), 2**64-1) hn.thisown = False hn.__disown__() self.registerTree(self.parent, hn) class huge_node(Module): """This modules permit to test the framework by generating a large amount of nodes.""" def __init__(self): Module.__init__(self, "huge_node", HugeNodes) self.conf.addArgument({"input": Argument.Optional|Argument.Single|typeId.Node, "name": "parent", "description": "files or folders will be added as child(ren) of this node or as the root node by default", "parameters": {"type": Parameter.Editable, "predefined": [vfs().getnode("/")]} }) self.tags = "Node" dff-1.3.0+dfsg.1/dff/unsupported/test/readlines/000077500000000000000000000000001217176075400214165ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/test/readlines/CMakeLists.txt000066400000000000000000000013461217176075400241620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob dff_cpp_module(READLINES CPP_FILES readlines.cpp SWIG_FILE readlines.i LINK_LIBRARIES exceptions types vfs EXTRA_FILES __init__.py ) dff-1.3.0+dfsg.1/dff/unsupported/test/readlines/__init__.py000066400000000000000000000011041217176075400235230ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin __all__ = ["READLINES"] dff-1.3.0+dfsg.1/dff/unsupported/test/readlines/readlines.cpp000066400000000000000000000022561217176075400240750ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "readlines.hpp" #include "vfile.hpp" readlines::readlines(): fso("readlines") { } readlines::~readlines() { } void readlines::start(std::map args) { std::map::iterator argit; std::string line; VFile* f; int32_t i; if ((argit = args.find("file")) != args.end()) { this->__inode = argit->second->value(); f = this->__inode->open(); i = 0; while (f->readline().size()) i++; std::cout << "total lines: " << i << std::endl; } else throw(envError("readlines module requires a file argument")); } dff-1.3.0+dfsg.1/dff/unsupported/test/readlines/readlines.hpp000066400000000000000000000024251217176075400241000ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __READLINES_HH__ #define __READLINES_HH__ #include "fso.hpp" #include "node.hpp" #include #include #include #include "variant.hpp" #include "vfs.hpp" class readlines : public fso { private: Node* __inode; public: readlines(); ~readlines(); int32_t vopen(Node* handle) {return 0;} int32_t vread(int fd, void *buff, unsigned int size) {return 0;} int32_t vclose(int fd) {return 0;} uint64_t vseek(int fd, uint64_t offset, int whence) {return 0;} int32_t vwrite(int fd, void *buff, unsigned int size) { return 0; }; uint32_t status(void) {return 0;} uint64_t vtell(int32_t fd) {return 0;} virtual void start(std::map args); }; #endif dff-1.3.0+dfsg.1/dff/unsupported/test/readlines/readlines.i000066400000000000000000000030041217176075400235330ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module READLINES %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "fso.hpp" #include "mfso.hpp" #include "node.hpp" #include "vlink.hpp" #include "vfile.hpp" #include "rootnode.hpp" #include "readlines.hpp" %} %import "../../../api/vfs/libvfs.i" %include "readlines.hpp" %pythoncode %{ __dff_module_READLINES_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import * from dff.api.vfs import vfs class READLINES(Module): """Add file from your operating system to the VFS""" def __init__(self): Module.__init__(self, 'readlines', readlines) self.conf.addArgument({"input": Argument.Required|Argument.Single|typeId.Node, "name": "file", "description": "text file to read lines", }) self.tags = "Connectors" %} dff-1.3.0+dfsg.1/dff/unsupported/utils/000077500000000000000000000000001217176075400176315ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/utils/CMakeLists.txt000066400000000000000000000010741217176075400223730ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob add_subdirectory(shm) dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/000077500000000000000000000000001217176075400204205ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/CMakeLists.txt000066400000000000000000000013361217176075400231630ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob dff_cpp_module(SHM CPP_FILES shm.cpp SWIG_FILE shm.i LINK_LIBRARIES exceptions types vfs EXTRA_FILES __init__.py touch.py ) dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/__init__.py000066400000000000000000000010731217176075400225320ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob __all__ = ['touch'] dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/shm.cpp000066400000000000000000000134461217176075400217230ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #include "shm.hpp" ShmNode::ShmNode(std::string name, uint64_t size, fso* fsobj): Node(name, size, NULL, fsobj) { this->setFile(); } ShmNode::~ShmNode() { } void ShmNode::setId(uint32_t id) { this->__id = id; } uint32_t ShmNode::id() { return this->__id; } Shm::Shm(): fso("shm") { this->__fdm = new FdManager(); } Shm::~Shm() { } void Shm::start(std::map args) { std::map::iterator it; Node* parent; std::string filename; Node* node; if ((it = args.find("parent")) != args.end()) parent = it->second->value(); else throw vfsError("shm requires < parent > argument"); if ((it = args.find("filename")) != args.end()) filename = it->second->value(); else throw vfsError("shm requires < filename > argument"); node = this->addnode(parent, filename); std::string n = "file " + node->absolute() + " created\n"; this->res["result"] = new Variant(n); return ; } Node* Shm::addnode(Node* parent, std::string filename) { ShmNode* node; uint32_t id; pdata* data; node = new ShmNode(filename, 0, this); id = this->__nodesdata.size(); node->setId(id); data = new pdata; data->buff = NULL; data->len = 0; this->__nodesdata.push_back(data); this->registerTree(parent, node); return node; } int32_t Shm::vopen(Node *node) { fdinfo* fi; int32_t fd; if (node == NULL) throw vfsError("[SHM] vopen() provided node is NULL\n"); fi = new fdinfo; fi->node = node; fi->offset = 0; fd = this->__fdm->push(fi); return (fd); } int32_t Shm::vread(int32_t fd, void *buff, uint32_t size) { fdinfo* fi; ShmNode* node; uint32_t id; pdata* data; std::string err; try { fi = this->__fdm->get(fd); node = dynamic_cast(fi->node); id = node->id(); if (id > this->__nodesdata.size()) throw vfsError("[SHM] vread() node id does not exist\n"); data = this->__nodesdata[id]; if ((node->size() == 0) || (data->len == 0) || (data->len < fi->offset) || (node->size() < fi->offset)) throw vfsError("[SHM] vread() either file size is 0 or offset is too high\n"); if ((data->len - fi->offset) < size) size = data->len - fi->offset; memcpy(buff, (char *)data->buff + fi->offset, size); fi->offset += size; return (size); } catch (const std::exception& e) { err = std::string("[SHM] vread() cannot read file\n") + e.what(); throw vfsError(err); } catch (vfsError e) { throw vfsError("[SHM] vread() cannot read file\n" + e.error); } } int32_t Shm::vwrite(int32_t fd, void *buff, uint32_t size) { fdinfo* fi; ShmNode* node; uint32_t id; pdata* data; std::string err; try { fi = this->__fdm->get(fd); node = dynamic_cast(fi->node); id = node->id(); if (id > this->__nodesdata.size()) throw vfsError("[SHM] vwrite() node id does not exist\n"); data = this->__nodesdata[id]; if (data->len < fi->offset) throw vfsError("[SHM] vwrite() offset is too high\n"); if (data->len == 0) { data->buff = new char[size]; data->len = size; } else if (data->len < (fi->offset + size)) { size = (uint32_t)(fi->offset + size - data->len); data->buff = realloc(data->buff, sizeof(char) * (data->len + size)); data->len += size; } memcpy((char*)data->buff + fi->offset, buff, size); fi->offset += size; node->setSize(data->len); return size; } catch (const std::exception& e) { err = std::string("[SHM] vwrite() cannot write file\n") + e.what(); throw vfsError(err); } catch (vfsError e) { throw vfsError("[SHM] vwrite() cannot write file\n" + e.error); } } uint64_t Shm::vseek(int32_t fd, uint64_t offset, int32_t whence) { fdinfo* fi; ShmNode* node; uint32_t id; std::string err; try { fi = this->__fdm->get(fd); node = dynamic_cast(fi->node); id = node->id(); if (id > this->__nodesdata.size()) throw vfsError("[SHM] vseek() node id does not exist\n"); if (whence == 0) if (offset < node->size()) fi->offset = offset; else throw vfsError("[SHM] vseek() offset is too high\n"); else if (whence == 1) if (fi->offset + offset < node->size()) fi->offset += offset; else throw vfsError("[SHM] vseek() offset is too high\n"); else if (whence == 2) fi->offset = node->size(); return (fi->offset); } catch (const std::exception& e) { err = std::string("[SHM]: vseek() cannot seek\n") + e.what(); throw vfsError(err); } catch (vfsError e) { throw vfsError("[SHM] vseek() cannot seek\n" + e.error); } } int32_t Shm::vclose(int32_t fd) { std::string err; try { this->__fdm->remove(fd); return (0); } catch (const std::exception& e) { err = std::string("[SHM] vclose() error while closing fd\n") + e.what(); throw vfsError(err); } } uint64_t Shm::vtell(int32_t fd) { fdinfo* fi; std::string err; try { fi = this->__fdm->get(fd); return (fi->offset); } catch (const std::exception& e) { err = std::string("[SHM] vtell() can not tell offset\n") + e.what(); throw vfsError(err); } } uint32_t Shm::status(void) { return (0); } dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/shm.hpp000066400000000000000000000032561217176075400217260ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal Jacob */ #ifndef __MEM_HH__ #define __MEM_HH__ #include "mfso.hpp" #ifndef WIN32 #include #endif #include #include #include #include #include #include #include "variant.hpp" #include "exceptions.hpp" #include "vfs.hpp" #include "vfile.hpp" #include "vlink.hpp" #include "node.hpp" class ShmNode: public Node { private: uint32_t __id; public: ShmNode(std::string name, uint64_t size, fso* fsobj); ~ShmNode(); void setId(uint32_t id); uint32_t id(); }; class Shm: public fso { private: std::vector __nodesdata; FdManager* __fdm; class Node* __root; public: Shm(); ~Shm(); Node* addnode(Node* parent, std::string filename); virtual void start(std::map args); virtual int32_t vopen(Node* node); virtual int32_t vread(int32_t fd, void *buff, uint32_t size); virtual int32_t vwrite(int32_t fd, void *buff, uint32_t size); virtual int32_t vclose(int32_t fd); virtual uint64_t vseek(int32_t fd, uint64_t offset, int32_t whence); virtual uint64_t vtell(int32_t fd); virtual uint32_t status(void); }; #endif dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/shm.i000066400000000000000000000034571217176075400213720ustar00rootroot00000000000000/* * DFF -- An Open Source Digital Forensics Framework * Copyright (C) 2009-2013 ArxSys * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * See http://www.digital-forensic.org for more information about this * project. Please do not directly contact any of the maintainers of * DFF for assistance; the project provides a web site, mailing lists * and IRC channels for your use. * * Author(s): * Solal J. */ #include "pyrun.swg" %module SHM %include "std_string.i" %include "std_list.i" %include "std_set.i" %include "std_map.i" %include "windows.i" %{ #include "variant.hpp" #include "vtime.hpp" #include "shm.hpp" #include "rootnode.hpp" %} %import "../../../api/vfs/libvfs.i" %include "shm.hpp" %pythoncode %{ __dff_module_shm_version__ = "1.0.0" from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId class SHM(Module): """SHM create a copy of the parent file to a new node named filename.\ It permit to have access to file with write permission without doing any modification in any other files.\n\ SHM create files stored in RAM so don't use it for huge files.\n\ SHM is also used by other modules (zip, touch, ...) to create file with content in the VFS in fast way.\n""" def __init__(self): Module.__init__(self, 'shm', Shm) self.conf.addArgument({"input": Argument.Single|Argument.Required|typeId.String, "name": "filename", "description": "file name of the created file"}) self.conf.addArgument({"input": Argument.Single|Argument.Required|typeId.Node, "name": "parent", "description": "file to copy"}) self.tags = "Utils" %} dff-1.3.0+dfsg.1/dff/unsupported/utils/shm/touch.py000066400000000000000000000044751217176075400221260ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Solal Jacob # __dff_module_touch_version__ = "1.0.0" from dff.api.vfs import * from dff.api.module import * from dff.api.types.libtypes import Argument, typeId from dff.api.taskmanager.taskmanager import * from SHM import * class TOUCH(Script): class __Touch(Script): def __init__(self): Script.__init__(self, "touch") self.vfs = vfs.vfs() self.shm = SHM().create() def start(self, arg): fname = arg["filename"].value() if self.touch(fname): self.res["result"] = Variant("SHM create file " + fname) else: self.res["error"] = Variant("Can't find path") def touch(self, fname): plist = fname.split('/') snode = '' for path in plist: if path != '': snode += '/' node = self.vfs.getnode(snode) if not self.vfs.getnode(snode + path): node = self.shm.addnode(node, path) snode += path return node # if not fname.count('/'): # parent = self.vfs.getcwd().path + "/" + self.vfs.getcwd().name # filename = fname # else: # f = fname.rfind('/') # parent = fname[:f+1] # filename = fname[f+1:] # return node __instance = None def __init__(self): if TOUCH.__instance is None: TOUCH.__instance = TOUCH.__Touch() def __setattr__(self, attr, value): setattr(self.__instance, attr, value) def __getattr__(self, attr): return getattr(self.__instance, attr) class touch(Module): """Create an empty file with write permissions through SHM.""" def __init__(self): Module.__init__(self, "touch", TOUCH) self.tags = "Node" self.conf.addArgument({"name": "filename", "input": Argument.Single|Argument.Required|typeId.String, "description": "Path/Name of file to create"}) dff-1.3.0+dfsg.1/dff/unsupported/viewer/000077500000000000000000000000001217176075400177725ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/viewer/CMakeLists.txt000066400000000000000000000011541217176075400225330ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob install_file(hist.py) dff-1.3.0+dfsg.1/dff/unsupported/viewer/hist.py000066400000000000000000000071601217176075400213170ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # __dff_module_player_version__ = "1.0.0" from PyQt4 import QtGui, QtCore from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure from matplotlib.text import Text from dff.api.module.script import Script from dff.api.module.module import Module from dff.api.types.libtypes import Argument, typeId class HIST(QtGui.QWidget, Script): def __init__(self): Script.__init__(self, "file histogram") self.freq = [0 for i in xrange(0, 256)] self.xcount = [i for i in xrange(0, 256)] def start(self, args): self.stateinfo = "counting byte occurences 0%" try: self.node = args["file"].value() f = self.node.open() buff = f.read(10*1024*1024) size = self.node.size() read = 0 while len(buff) > 0: for c in buff: self.freq[ord(c)] += 1 read += 1 self.stateinfo = "counting byte occurences " + str(float(read*100/size)) + "%" buff = f.read(10*1024*1024) f.close() except: pass def updateWidget(self): pass def g_display(self): QtGui.QWidget.__init__(self) self.oldtxt = None self.fig = Figure(figsize=(5, 5), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) self.canvas.updateGeometry() self.canvas.mpl_connect('motion_notify_event', self.on_motion) self.ax = self.fig.add_axes([0.2,0.2,0.5,0.7]) self.ax.set_xlabel("Byte") self.ax.set_ylabel("Frequency") self.ax.set_title("Byte Distribution of file \"" + self.node.name() + "\"") self.ax.set_xlim(0, 256) self.rects = self.ax.bar(self.xcount, self.freq, width=1, color='g', edgecolor='k') self.ax.set_xticks([i for i in xrange(0, 256, 10)]) for label in self.ax.xaxis.get_ticklabels(): label.set_color('black') label.set_rotation(45) label.set_fontsize(12) for label in self.ax.yaxis.get_ticklabels(): label.set_color('black') label.set_rotation(-45) label.set_fontsize(12) self.ax.grid(True) self.ax.autoscale(enable=True, axis='y') self.txt = self.fig.text(0, 0.1, '') self.orect = None vbox = QtGui.QVBoxLayout(self) vbox.addWidget(self.canvas) def on_motion(self, event): if event.xdata != None: x = int(event.xdata) rect = self.rects[x] if self.orect != None and self.orect != rect: self.orect.set_facecolor('g') rect.set_facecolor('b') self.orect = rect self.txt.set_text("byte: " + hex(x) + " -- frequency: " + str(self.freq[x])) self.canvas.draw() def setupUi(self): pass class hist(Module): def __init__(self): """Histogram diplay""" Module.__init__(self, "hist", HIST) self.conf.addArgument({"name": "file", "description": "input file used to generate histogram", "input": Argument.Required|Argument.Single|typeId.Node}) self.tags = "Viewers" dff-1.3.0+dfsg.1/dff/unsupported/volumes/000077500000000000000000000000001217176075400201635ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/volumes/CMakeLists.txt000066400000000000000000000011551217176075400227250ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # Solal Jacob add_subdirectory(raid) dff-1.3.0+dfsg.1/dff/unsupported/volumes/raid/000077500000000000000000000000001217176075400211025ustar00rootroot00000000000000dff-1.3.0+dfsg.1/dff/unsupported/volumes/raid/CMakeLists.txt000066400000000000000000000011541217176075400236430ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain BERTHOLON install_file( __init__.py decoder.py header.py raid.py ) dff-1.3.0+dfsg.1/dff/unsupported/volumes/raid/__init__.py000066400000000000000000000010751217176075400232160ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon __all__ = ["raid"] dff-1.3.0+dfsg.1/dff/unsupported/volumes/raid/decoder.py000066400000000000000000000055411217176075400230660ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Jeremy Mounier # import binascii import struct STRING_T = 0 UINT8_T = 1 INT8_T = 2 UINT16_T = 3 INT16_T = 4 UINT32_T = 5 INT32_T = 6 UINT64_T = 7 INT64_T = 8 VOID_T = 9 TEMP_OFFSET = 0 TEMP_SIZE = 1 TEMP_TYPE = 2 class decoder(): def __init__(self, vfile, offset, template): self.vfile = vfile self.offset = offset self.temp = template self.decoded = False self.decode() def template(self): return sorted(self.temp.iteritems(), key=lambda (k,v): (v,k)) def readTemplate(self): buff = "" for field, data in self.template(): self.vfile.seek(self.offset + data[TEMP_OFFSET]) buff += self.vfile.read(data[TEMP_SIZE]) return buff def pattern(self): pattern = "<" for field, data in self.template(): if data[TEMP_TYPE] == INT8_T: pattern += "b" elif data[TEMP_TYPE] == UINT8_T: pattern += "B" elif data[TEMP_TYPE] == INT16_T: pattern += "h" elif data[TEMP_TYPE] == UINT16_T: pattern += "H" elif data[TEMP_TYPE] == INT32_T: pattern += "i" elif data[TEMP_TYPE] == UINT32_T: pattern += "I" elif data[TEMP_TYPE] == INT64_T: pattern += "q" elif data[TEMP_TYPE] == UINT64_T: pattern += "Q" elif data[TEMP_TYPE] == STRING_T: pattern += str(data[TEMP_SIZE]) + "s" elif data[TEMP_TYPE] == VOID_T: pattern += str(data[TEMP_SIZE]) + "P" return pattern def decode(self): if not self.decoded: buff = self.readTemplate() if self.templateSize() == len(buff): res = struct.unpack(self.pattern(), buff) cp = 0 self.filds = {} for key, values in self.template(): setattr(self, key, res[cp]) cp += 1 self.decoded = True def dump(self): for field, data in self.template(): print field, " : ", getattr(self, field) # Unused : information purpose def templateSize(self): size = 0 for field, data in self.template(): size += data[TEMP_SIZE] return size dff-1.3.0+dfsg.1/dff/unsupported/volumes/raid/header.py000066400000000000000000000100451217176075400227040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon # import unicodedata from datetime import datetime from decoder import * from dff.api.types.libtypes import VList MD_SB_GENERIC_CONSTANT_WORDS = 32 MD_SB_GENERIC_STATE_WORDS = 32 MD_SB_PERSONALITY_WORDS = 64 MD_SB_DESCRIPTOR_WORDS = 32 MD_SB_DISKS = 27 MD_SB_DISKS_WORDS = (MD_SB_DISKS * MD_SB_DESCRIPTOR_WORDS) MD_SB_GENERIC_WORDS = (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS) MD_SB_RESERVED_WORDS = (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS \ - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS) MD_SUPERBLOCK = { # constant array information - 128 bytes # "magic":[0, 0x4, UINT32_T], # MD_SB_MAGIC: 0xa92b4efc - little endian # "major_version":[4, 0x4, UINT32_T], # 1 # "feature_map":[8, 0x4, UINT32_T], # 0 for now # "pad0":[12, 0x4, UINT32_T], # always set to 0 when writing # "set_uuid":[16, 16, STRING_T], "set_name":[32, 32, STRING_T], "ctime":[64, 0x8, UINT64_T], # lo 40 bits are seconds, top 24 are microseconds or 0# "level":[72, 0x4, UINT32_T], # -4 (multipath), -1 (linear), 0,1,4,5 # "layout":[76, 0x4, UINT32_T], # only for raid5 currently # "size":[80, 0x8, UINT64_T], # used size of component devices, in 512byte sectors # "chunksize":[88, 0x4, UINT32_T], # in 512byte sectors # "raid_disks":[92, 0x4, UINT32_T], # sectors after start of superblock that bitmap starts # NOTE: signed, so bitmap can be before superblock # only meaningful of feature_map[0] is set. "bitmap_offset":[96, 0x4, UINT32_T], # These are only valid with feature bit '4' # "new_level":[100, 0x4, UINT32_T], # new level we are reshaping to # "reshape_position":[104, 0x8, UINT64_T], # next address in array-space for reshape # "delta_disks":[112, 0x4, UINT32_T], # change in number of raid_disks # "new_layout":[116, 0x4, UINT32_T], # new layout # "new_chunk":[120, 0x4, UINT32_T], # new chunk size (bytes) # "pad":[124, 0x4, STRING_T], # constant this-device information - 64 bytes # "data_offset":[128, 0x8, UINT64_T], # sector start of data, often 0 # "data_size":[136, 0x8, UINT64_T], # sectors in this device that can be used for data # "super_offset":[144, 0x8, UINT64_T], # sector start of this superblock # "recovery_offset":[152, 0x8, UINT64_T],# sectors before this offset (from data_offset) have been recovered # "dev_number":[160, 0x4, UINT32_T], # permanent identifier of this device - not role in raid # "cnt_corrected_read":[164, 0x4, UINT32_T], # number of read errors that were corrected by re-writing # "device_uuid":[168, 16, STRING_T], # user-space setable, ignored by kernel # "devflags":[184, 0x1, UINT8_T], # per-device flags. Only one defined...# #define WriteMostly1 1 # mask for writemostly flag in above # "pad2":[185, 0x7, STRING_T], # set to 0 when writing # # array state information - 64 bytes # "utime":[192, 0x8, UINT64_T], # 40 bits second, 24 btes microseconds # "events":[200, 0x8, UINT64_T], # incremented when superblock updated # "resync_offset":[208, 0x8, UINT64_T], # data before this offset (from data_offset) known to be in sync # "sb_csum":[216, 0x4, UINT32_T], # checksum upto dev_roles[max_dev] # "max_dev":[220, 0x4, UINT32_T], # size of dev_roles[] array to consider # "pad3":[224, 0x20, STRING_T], # set to 0 when writing # } class MdSuperblock(decoder): def __init__(self, vfile, offset, template): decoder.__init__(self, vfile, offset, template) dff-1.3.0+dfsg.1/dff/unsupported/volumes/raid/raid.py000066400000000000000000000064271217176075400224040ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Romain Bertholon < rbe@digital-forensic.org> # __dff_module_winreg_version__ = "1.0.0" import datetime from header import MdSuperblock, MD_SUPERBLOCK from dff.api.vfs import * from dff.api.module.module import * from dff.api.types.libtypes import Argument, typeId from dff.api.vfs.libvfs import * class Raid1Node(Node): def __init__(self, name, size, node, mfso, sb): Node.__init__(self, name, size, node.parent(), mfso) self.__disown__() self.sb = sb self.node = node def fileMapping(self, fm): fm.push(0, self.node.size() - self.sb.data_offset * 512,\ self.node, self.sb.data_offset * 512) class RAID(mfso): def __init__(self): mfso.__init__(self, "raid") self.name = "raid" self.__disown__() self.node = None def start(self, args): vol1 = args['volume1'].value() vol2 = args['volume2'].value() vfile = vol1.open() super_block = MdSuperblock(vfile, 4096, MD_SUPERBLOCK) self.dispInfo(super_block) if super_block.level == 1: self.node = Raid1Node('raid_volume', super_block.data_size, vol1,\ self, super_block) else: print "Raid %d not handled." % (sb.level, ) vfile.close() def dispInfo(self, sb): print "" print "Magic :", hex(sb.magic) print " - Feature map :", hex(sb.feature_map) print " - Name :", sb.set_name print " - Creation time : ", datetime.datetime.fromtimestamp(sb.ctime).strftime('%Y-%m-%d %H:%M:%S') tmp = "" for i in sb.set_uuid: tmp += hex(ord(i)).replace('0x', '') print " - Uuid : 0x", tmp print "" print "Raid level :", sb.level print " - Raid devices :", sb.raid_disks print " - Size :", sb.size print " - Data size :", sb.data_size print " - Data offset :", sb.data_offset print " - Super offset :", sb.super_offset print "" print "State" print " - Update Time :", datetime.datetime.fromtimestamp(sb.utime).strftime('%Y-%m-%d %H:%M:%S') print " - Events :", sb.events print " - Checksum :", hex(sb.sb_csum) print "" class raid(Module): """This modules permit to virtualy reconstruct raid volumes on the VFS.""" def __init__(self): Module.__init__(self, "raid", RAID) self.conf.addArgument({"name": "volume1", "description": "raid volume", "input": Argument.Required|Argument.Single|typeId.Node}) self.conf.addArgument({"name": "volume2", "description": "raid volume", "input": Argument.Required|Argument.Single|typeId.Node}) self.tags = "Volumes" self.icon = ":database" dff-1.3.0+dfsg.1/doc/000077500000000000000000000000001217176075400141075ustar00rootroot00000000000000dff-1.3.0+dfsg.1/doc/man/000077500000000000000000000000001217176075400146625ustar00rootroot00000000000000dff-1.3.0+dfsg.1/doc/man/dff.1000066400000000000000000000025661217176075400155140ustar00rootroot00000000000000.TH DFF "1" "February 2011" "dff version 0.9" "User Commands" .SH NAME dff \- A powerful, efficient and modular digital forensics tool. .SH SYNOPSIS .B dff [\fIoptions\fR] .SH DESCRIPTION Digital Forensics Framework .B dff is a simple but powerful open source tool with a flexible module system which will help you in your digital forensics works, including files recovery due to error or crash, evidence research and analysis, etc. The source code is written in C++ and Python, allowing performances and great extensibility. .SH OPTIONS .TP \fB\-v\fR \fB\-\-version\fR display current version .TP \fB\-g\fR \fB\-\-graphical\fR launch graphical interface .TP \fB\-l\fR \fB\-\-language\fR=\fILANG\fR use \fILANG\fR as interface language, available: es, en, fr. .TP \fB\-h\fR, \fB\-\-help\fR display this help message .TP \fB\-d\fR, \fB\-\-debug\fR redirect IO to system console .TP \fB\-\-verbose\fR=\fILEVEL\fR set verbosity level when debugging, available \fILEVEL\fR: 0 to 3 .TP \fB\-c\fR, \fB\-\-config=\fIFILEPATH\fR use config file from given \fIFILEPATH\fR .TP \fB\-b\fR, \fB\-\-batch=\fIFILENAME\fR executes batch contained in \fIFILENAME\fR .SH "SEE ALSO" Project's wiki with up-to-date documentation for \fBdff\fR is provided at this url: \fIhttp://wiki.digital-forensic.org/\fR. .TP Embeded help is also available through the \fIHelp\fR menu in \fBdff\fR. dff-1.3.0+dfsg.1/prerequisites/000077500000000000000000000000001217176075400162465ustar00rootroot00000000000000dff-1.3.0+dfsg.1/prerequisites/CMakeLists.txt000066400000000000000000000057671217176075400210250ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin FILE(GLOB dependencies ${CMAKE_CURRENT_BINARY_DIR}/*) foreach(file ${dependencies}) IF (NOT IS_DIRECTORY(${file})) split_path_file_extension(${file}) string(TOLOWER ${__FILE__} file_lower) IF (NOT PYTHON_INSTALLER) STRING(REGEX MATCH "^python.*" PYTHON_INSTALLER "${file_lower}") if (NOT PYTHON_INSTALLER STREQUAL "") set (PYTHON_INSTALLER ${__FILE__}) endif () ENDIF (NOT PYTHON_INSTALLER) IF (NOT PYQT_INSTALLER) STRING(REGEX MATCH "^pyqt.*" PYQT_INSTALLER "${file_lower}") if (NOT PYQT_INSTALLER STREQUAL "") set (PYQT_INSTALLER ${__FILE__}) endif () ENDIF (NOT PYQT_INSTALLER) IF (NOT VCREDIST_INSTALLER) STRING(REGEX MATCH "^vcredist.*" VCREDIST_INSTALLER "${file_lower}") if (NOT VCREDIST_INSTALLER STREQUAL "") set (VCREDIST_INSTALLER ${__FILE__}) endif () ENDIF (NOT VCREDIST_INSTALLER) IF (NOT APSW_INSTALLER) STRING(REGEX MATCH "^apsw.*" APSW_INSTALLER "${file_lower}") if (NOT APSW_INSTALLER STREQUAL "") set (APSW_INSTALLER ${__FILE__}) endif () ENDIF (NOT APSW_INSTALLER) IF (NOT PIL_INSTALLER) STRING(REGEX MATCH "^pil.*" PIL_INSTALLER "${file_lower}") if (NOT PIL_INSTALLER STREQUAL "") set (PIL_INSTALLER ${__FILE__}) endif () ENDIF () if (BUILD_UNSUPPORTED) if (NOT MATPLOTLIB_INSTALLER) STRING(REGEX MATCH "^matplotlib.*" MATPLOTLIB_INSTALLER "${file_lower}") if (NOT MATPLOTLIB_INSTALLER STREQUAL "") set (MATPLOTLIB_INSTALLER ${__FILE__}) endif () endif () if (NOT NUMPY_INSTALLER) STRING(REGEX MATCH "^numpy.*" NUMPY_INSTALLER "${file_lower}") if (NOT NUMPY_INSTALLER STREQUAL "") set (NUMPY_INSTALLER ${__FILE__}) endif () endif () endif() ENDIF (NOT IS_DIRECTORY(${file})) endforeach() set(PYTHON_INSTALLER ${PYTHON_INSTALLER} PARENT_SCOPE) set(PYQT_INSTALLER ${PYQT_INSTALLER} PARENT_SCOPE) set(VCREDIST_INSTALLER ${VCREDIST_INSTALLER} PARENT_SCOPE) set(APSW_INSTALLER ${APSW_INSTALLER} PARENT_SCOPE) set(PIL_INSTALLER ${PIL_INSTALLER} PARENT_SCOPE) if (BUILD_UNSUPPORTED) set(MATPLOTLIB_INSTALLER ${MATPLOTLIB_INSTALLER} PARENT_SCOPE) set(NUMPY_INSTALLER ${NUMPY_INSTALLER} PARENT_SCOPE) endif() set(dependencies ${PYTHON_INSTALLER} ${PYQT_INSTALLER} ${VCREDIST_INSTALLER} ${APSW_INSTALLER} ${PIL_INSTALLER} ) if (BUILD_UNSUPPORTED) set(dependencies ${dependencies} ${MATPLOTLIB_INSTALLER} ${NUMPY_INSTALLER} ) endif() install_file(${dependencies}) dff-1.3.0+dfsg.1/ressources/000077500000000000000000000000001217176075400155375ustar00rootroot00000000000000dff-1.3.0+dfsg.1/ressources/Doxyfile000066400000000000000000001542421217176075400172550ustar00rootroot00000000000000# Doxyfile 1.5.4 # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file that # follow. The default is UTF-8 which is also the encoding used for all text before # the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into # libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of # possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = "Digital Forensics Framework" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = /var/doc/dff # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, # Italian, Japanese, Japanese-en (Japanese with English messages), Korean, # Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, # Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is # documented as struct with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code where the coding convention is that all structs are # typedef'ed and only the typedef is referenced never the struct's name. TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be extracted # and appear in the documentation as a namespace called 'anonymous_namespace{file}', # where file will be replaced with the base name of the file that contains the anonymous # namespace. By default anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = api ui/console # This tag can be used to specify the character encoding of the source files that # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default # input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. # See http://www.gnu.org/software/libiconv for the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.hpp *.cpp *.py # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = YES # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.svn/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the output. # The symbol name can be a fully qualified name, a word, or if the wildcard * is used, # a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH # then you must also enable this option. If you don't then doxygen will produce # a warning and turn it on anyway SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to # produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to # specify the directory where the mscgen tool resides. If left empty the tool is assumed to # be found in the default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will # generate a caller dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected # functions only using the \callergraph command. CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = /usr/bin/ # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the number # of direct children of the root node in a graph is already larger than # MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO dff-1.3.0+dfsg.1/ressources/arxsys.bmp000066400000000000000000001027161217176075400175770ustar00rootroot00000000000000BMÎ…6(–9 ˜…ÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿþþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿþÿÿÿüûøÿðíßÿïìÛÿþþûÿþþÿÿýÿþÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿþûÿÿþþÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿø÷ïÿ¸§rÿš5ÿñì×ÿÿÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿüÿÿþùÿÿþþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿûÿÿÿúÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöö÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÁ–ÿ‰j ÿ¾«sÿÿÿÿÿÿþÿÿÿÿþÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿüÿÿÿúÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþþþÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿöòãÿž„7ÿ‹nÿùôâÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿÿÿÿÿ²~ÿŒmÿÁ¯xÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿýÿÿÿþÿÿÿÿÿÿÿþÿþÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿþÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿýþÿÿÿÿÿÿþÿÿÿÿÿÿÿôïÝÿ”w#ÿ‘t ÿùõäÿÿÿÿÿþþÿÿþÿþÿÿÿÿÿþÿþÿÿÿþÿÿþÿÿÿÿþÿÿþþÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿÿþýÿÿÿÿÿÿÿþÿÿÿÿÿÿÿýÿÿÿýÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿÿýÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿþÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿþþÿþÿÿÿÿÿÿÿ»©qÿŒlÿÁ²ÿÿÿÿÿþþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿþÿþÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþþÿÿÿþÿÿÿþÿÿþþÿÿþüÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿþÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿÿÿÿÿÿþþÿÿÿÿÿÿòîÚÿ‹oÿŸ†8ÿòïÞÿÿÿÿÿÿþÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿþýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿþÿÿÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿýþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿúÿÿÿúÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿÿþÿþÿÿÿþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ·¦kÿŠk ÿÏÁ–ÿÿÿÿÿþÿÿÿÿÿþÿþÿþÿÿþÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþþþÿþÿþÿÿÿÿÿÿÿÿÿÿÿúÿÿÿúÿÿÿýÿÿÿÿÿÿÿÿÿþþÿÿþÿþÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿýÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿ²³³ÿŸŸ¡ÿðððÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÝÝÞÿ’“ÿ¹¹¹ÿÿÿÿÿÿÿÿÿëëëÿ“’”ÿ©¨ªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥¥¥ÿ“’”ÿ×××ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿìììÿ›œÿ–––ÿùùùÿýÿÿÿÿÿÿÿÿÿþÿÿÿûÿ÷ñÝÿ˽ÿ¨Hÿ–y&ÿnÿŽoÿ—{+ÿª”OÿÐÁ–ÿ÷óáÿþþúÿþÿÿÿýÿþÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿðëÕÿˆiÿ¬”NÿôñåÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿÿýÿþûïÿÕÇžÿ¤Dÿsÿ‹nÿ˜}.ÿº§nÿðëÓÿÿÿüÿÿÿþÿþÿÿÿÿÿþÿÿÿþÿÿþÿÿþÿþÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿ»¼¼ÿHIKÿÎÎÏÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’”•ÿJMNÿÐÐÐÿÿÿÿÿÿÿÿÿÞßßÿQTUÿuwxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÐÑÑÿIKLÿ}~ÿïððÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿûûûÿ ¡¡ÿCEFÿ±±²ÿüüüÿÿþÿÿÿÿþÿ÷ôçÿŵÿ‹mÿˆj ÿ”x!ÿ›.ÿ¡‡:ÿ ‡:ÿ™},ÿ”w ÿ†g ÿŽrÿÏÀÿù÷ìÿÿÿÿÿþþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿþÿþÿþþÿÿüûóÿ³ _ÿ‰j ÿßÕ³ÿÿþýÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿýÿìæËÿŸ†<ÿ„eÿ•y$ÿž„6ÿ¢‰<ÿš/ÿ‘sÿoÿÑÄ™ÿýüõÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäääÿ_abÿ——™ÿûûûÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿëêìÿklmÿjklÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿ¢¢£ÿGIJÿ«««ÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÍÍÍÿMOPÿƒƒ„ÿôôôÿÿÿÿÿÿþþÿôñáÿ¯šXÿ…dÿ¢‰;ÿȹ‡ÿéáÇÿù÷éÿýûóÿýûòÿøöèÿæßÃÿƶƒÿžƒ3ÿƒcÿ³¡bÿúøìÿÿÿÿÿÿþÿÿþÿþÿÿþÿÿÿþÿÿþÿÿÿÿÿþÿþþÿÿýüõÿ¸¤fÿ‡fÿ²œ[ÿüûòÿþþÿÿÿÿþÿÿÿÿÿÿþÿÿÿþÿÿþÿÿÿÿÿÿÿëåÎÿ›‚3ÿoÿ¾®vÿìæÎÿüúðÿþüôÿú÷ëÿá×·ÿª“LÿŒnÿÞÓ±ÿþþüÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿ’“”ÿVVXÿòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿¾¿ÿMNPÿ¹¹¹ÿÿÿÿÿþþþÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿììíÿvwxÿRTUÿØÙÙÿÿÿÿÿþþþÿÿþþÿÿÿÿÿòòòÿefgÿ\]_ÿØØÙÿÿÿÿÿþþÿÿþþ÷ÿº¨nÿ…eÿ²Ÿ_ÿïêÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîéÑÿ©’Jÿˆi ÿ¾®zÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿíèÑÿoÿŽmÿ‹lÿëäÈÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿþýùÿº©wÿ‚c ÿÏ”ÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîèÐÿ™}*ÿ¬•RÿûúòÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÁÂÿPQSÿ»º¼ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøøøÿ‘’’ÿTVWÿñññÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÇÈÿXZ[ÿlkmÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿ†ˆˆÿOQRÿ¨¨©ÿÿÿÿÿýÿÿÿÿÿÿÿäܾÿˆh ÿ¨GÿòîÜÿþÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿþþÿÿÿþÿÿÿÿÿÿöñÝÿ”x$ÿ™~-ÿçâÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿÿÿ¹¥iÿpÿ¯–Jÿ”vÿ´^ÿÿÿþÿþþÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþýÿïìÜÿÔʨÿüûòÿÿÿÿÿþþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿûúòÿ´ `ÿ‘tÿùôäÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿíííÿnopÿkjlÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿââãÿ]_aÿ———ÿûûûÿþþþÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿ“”•ÿNPQÿ™˜šÿÿÿÿÿÿÿÿÿ¼»½ÿSUVÿqstÿÿÿþÿÿÿÿÿþþÿÿÿÿþÿ«“PÿqÿÕÊ¥ÿÿÿÿÿþÿÿÿÿÿþÿþÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿ˼ÿ‡h ÿË¿“ÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôïÚÿŒoÿŸ†:ÿðìÑÿ¦ŽFÿ‡iÿòíÖÿÿÿÿÿþÿÿÿÿþÿÿÿþÿÿþþÿÿÿþÿÿþÿþÿþþüÿþþýÿþÿÿÿÿÿþÿýÿÿÿþþÿÿÿþÿÿÿÿÿÿýüõÿ¸¤gÿŽpÿ÷òàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜™šÿKMNÿ×××ÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿýýýÿ»»¼ÿHJLÿÑÑÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþþÿÿÿÿÿùøøÿhjkÿRTUÿÏÏÏÿêêêÿgijÿUWXÿàààÿÿÿÿÿþþÿÿÿÿÿÿù÷ëÿ’z1ÿ£ŒHÿøöêÿÿÿÿÿÿÿþÿÿþÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿþÿÿÿÿÿÿñêÔÿˆg ÿ½ªqÿþýøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼«pÿ‹mÿ²ÿÿÿÿÿÐØÿoÿ´ dÿÿÿÿÿÿÿÿÿýÿþÿþÿÿÿÿþþÿþÿþÿýþÿÿÿÿÿÿÿÿÿÿÿþþÿþþþÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿñíÚÿ£Š;ÿ›3ÿù÷ëÿþÿÿÿþÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿþÿþÿÿÿÿÿÿÿþÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÚÙÙÿUWXÿ‰‰‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùøùÿ~~€ÿssuÿíìíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿÿÿÿÿþþþÿÿÿÿÿÔÔÔÿRTUÿnppÿŠ‹ŒÿJLMÿ²±³ÿÿÿÿÿþþþÿÿÿþÿþÿÿÿÿþýÿöóåÿåÞÈÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿþÿþÿþþÿÿùøëÿŽpÿ°œ\ÿ÷öîÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿôïÜÿ“w#ÿ”x%ÿ÷õäÿÿÿÿÿüûîÿš1ÿqÿïêÖÿÿÿÿÿþþþÿÿþþÿþÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿðíÛÿ»ªoÿ„dÿŶƒÿýü÷ÿÿþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿþÿÿÿýÿÿÿþÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿssuÿ[]]ÿíîîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæåçÿMMOÿ¥¥§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþþþÿÿÿÿÿ«¬¬ÿKMNÿJKMÿˆ‰Šÿùùùÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþþÿÿÿþÿÿù÷ëÿ’uÿ¬˜Vÿöôêÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿñ~ÿ‰i ÿijÿÿÿÿÿþþÿÿÿÿÿÿ̾ÿŠkÿ¸¦nÿÿÿÿÿþÿÿÿýÿþÿÿþÿÿþþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿèâÌÿÄ´ƒÿ¤Aÿ†fÿ©”Pÿóïàÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿþÿÿÿÿÿþÿÿÿþþÿÿÿþÿÿþÿþÿÿÿÿÿþþÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿ¿¾¿ÿMOPÿŠŒŒÿ³³´ÿ®¯¯ÿ¯®°ÿ®¯¯ÿ¯®°ÿ®¯¯ÿ®¯¯ÿ¯®°ÿ­¯¯ÿ¯®°ÿ®¯¯ÿ®¯¯ÿ°¯±ÿ…‡ˆÿ[\]ÿÔÔÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿçççÿQSTÿIKLÿÅÆÆÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿúöæÿ‰lÿ´ cÿùøñÿÿÿÿÿÿþÿÿÿÿÿÿóïÞÿŸ†8ÿqÿúöåÿÿÿÿÿÿþÿÿÿÿÿÿýûîÿ“w&ÿœ1ÿëæÒÿÿÿÿÿþþÿÿýÿþÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿÿúÿÜÑ®ÿ©“Oÿ–z%ÿ‡h ÿŽrÿŶƒÿöòäÿÿÿýÿýÿþÿÿÿþÿÿþÿÿÿþÿÿÿÿþÿýÿÿÿýþþÿÿþÿÿþÿÿÿýÿþÿþþÿÿþÿþÿÿÿþÿþÿÿÿýþþÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVXYÿQSUÿORUÿOQRÿOQRÿOQRÿOQRÿOQRÿOQRÿOQRÿOQRÿOQRÿOQRÿOQRÿQRVÿRTUÿ{}~ÿúúúÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ…„†ÿLOPÿOQRÿjlmÿõõõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýþÿÿÿÿÿÿÿÿþÿÞÖ´ÿ…eÿóÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÏÁ–ÿˆi ÿŵÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿʼÿ‡g ÿǹ‰ÿÿÿþÿÿÿÿÿþÿþÿÿÿÿÿþþÿÿÿÿÿÿòìÔÿ¡ˆAÿŠkÿŒmÿƒ6ÿÍ¿’ÿùöåÿþþúÿÿÿþÿÿÿÿÿþþþÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿýÿÿÿþþÿÿÿþþÿþþþÿÿÿÿÿÿÿÿÿôñíÿþýýÿþþþÿÿÿþÿýÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿ ¢£ÿPRSÿ–—˜ÿ¹¹¹ÿ¶µ·ÿ´¶¶ÿ¶µ·ÿ¶¶¶ÿ¶¶¶ÿ¶µ·ÿ¶¶¶ÿ¶µ·ÿ¶¶·ÿ»º»ÿ„‚„ÿRTUÿ¯±±ÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿxz{ÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»»»ÿIKLÿЉ‹ÿ®®¯ÿKMNÿœÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿøÿ¯—RÿsÿÚЯÿÿÿÿÿÿþÿÿÿÿÿÿõòæÿ©“LÿpÿóñÛÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿþþþÿû÷çÿ‘t!ÿ¤Š@ÿñíÝÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿóïÛÿ’w)ÿpÿ«”PÿåܽÿÿÿùÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿþÿþÿÿÿÿþÿÿþþÿÿÿÿÿÿþÿÿÿÿþÿÿþÿÿÿþþþÿÿÿÿÿóñìÿððèÿþþüÿõóðÿýýüÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæææÿLMNÿ¦©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrqsÿ]_`ÿîííÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿVXYÿtvwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþþþÿÿÿÿÿâããÿWZ[ÿbdeÿééèÿúùúÿ~€ÿMOPÿËÌÌÿÿÿÿÿþÿþÿÿÿÿÿÿþÿÿþÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿþÿÓÄ™ÿˆi ÿ¨“MÿûúðÿÿÿÿÿþÿÿÿþþýÿÜÔ²ÿ†g ÿ¿®wÿüü÷ÿþþþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿýýøÿǸ‡ÿ…eÿØÌ¦ÿþþûÿþÿÿÿÿÿÿÿÿÿÿÿ¿­yÿŒlÿ¹§lÿÿÿýÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿþþÿÿÿÿÿÿÿÿÿþÿþÿÿþÿÿÿÿÿÿñïåÿöòçÿæã×ÿëéßÿýýúÿ÷öòÿþþýÿýÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿ€ÿoqrÿëììÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿþþþÿÿÿÿÿÒÓÓÿTTVÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞààÿWYZÿacdÿõõõÿÿÿÿÿþÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿ÷÷÷ÿ‚ƒÿLNOÿÀÁÂÿÿÿÿÿÿÿÿÿÛÜÜÿWYZÿfgjÿíìíÿÿÿÿÿþþþÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿøÿÏÖÿrÿ’v"ÿåßÃÿÿÿÿÿþþÿÿþþÿÿýüôÿ¬–RÿsÿæàÆÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿìçÑÿ“x#ÿ¦Fÿüùîÿþþþÿÿÿÿÿÿÿûÿ­—Tÿ†g ÿû÷äÿÿÿÿÿþþþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿýýüÿìèÛÿèãÑÿÑÉ®ÿùöëÿêçÜÿìéßÿüûøÿúùöÿÿþþÿþþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿ¾¾¿ÿIKLÿÎÏÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’’ÿMOPÿÙÙÙÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞààÿXZ[ÿTUWÿµ´µÿÿÿÿÿþþþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿ²³³ÿKMNÿ’’”ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²²´ÿHJLÿ‘’ÿÿÿÿÿÿÿÿÿþÿþÿÿþÿÿÿÿþÿþÿÿÿÿÿÿÿþÿÿÿÿþÿÿþÿþÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿîèÏÿ°œ]ÿoÿqÿߨ´ÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿåàÄÿ‡h ÿ¶£eÿûúòÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþý÷ÿ½«pÿ„eÿäÚºÿÿÿÿÿÿÿÿÿÿÿûÿ®˜Uÿ…f ÿÿýíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿþÿþþÿÿÿþÿÿÿÿÿÿÿþÿÿþþýÿâÜÇÿ·ÿñíÚÿø›ÿÿÿöÿëæÛÿóñêÿ÷õòÿþþüÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããÿabcÿ””–ÿúúúÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿççèÿjlmÿmlnÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßààÿWYZÿQSTÿhjkÿßßßÿÿÿÿÿÿÿÿÿÿÿÿÿôôôÿéééÿÿÿÿÿþþþÿÿÿÿÿßààÿacdÿeegÿòòòÿÿÿÿÿþþþÿþþþÿÿÿÿÿþþþÿ{}~ÿTVWÿÃÃÄÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿÿþÿÿÿþÿÿÿþÿÿýÿÿÿÿþÿÿÿÿþÿÿÿÿÿóîØÿ¹¦kÿrÿŠj ÿž„8ÿëåËÿÿÿüÿÿÿÿÿÿþÿÿþþÿÿÿÿÿÿ®™Vÿ’uÿÚÒ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÙ»ÿ”x ÿ¨‘JÿÿÿüÿþÿÿÿÿÿÿÿÄ´„ÿ‹jÿÎÀ’ÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿøÿ×̨ÿÚÒ³ÿÿÿüÿÿÿþÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿþþþÿÿÿÿÿÿÿûÿÍ ÿÓȦÿòðßÿÁ¸›ÿüüõÿêçÜÿúúöÿõôðÿþÿþÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿ“””ÿUUVÿñññÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼»¼ÿNOQÿ¼¼¼ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞààÿUWXÿprsÿ‡†ˆÿabcÿµµµÿËËËÿª¬­ÿ``bÿz{|ÿðððÿÿÿÿÿøøøÿ‹‹ÿJLMÿËËËÿþþþÿþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿçççÿTVWÿrstÿééèÿÿÿÿÿþÿÿÿÿþþÿÿÿþÿþÿÿÿÿÿÿÿÿÿþÿüüôÿëæÍÿ¶£fÿŒnÿm ÿ•w"ÿÀ¯{ÿüøëÿÿÿþÿþþÿÿÿþþÿþþÿÿÿÿÿÿëåËÿ‰kÿ¨‘Lÿÿþöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿ­—Tÿ…e ÿêâÃÿÿÿÿÿÿÿÿÿù÷çÿ›‚8ÿŒpÿÁ°wÿà×¶ÿãÛºÿÑÇœÿ¨Hÿ…e ÿ¢ŽMÿñîãÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿþþþÿÿÿÿÿÿÿüÿ²¤xÿíéÑÿàÛÆÿßÙÅÿîëàÿöóíÿõóïÿþýûÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÂÂÿLOPÿºººÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÿŒŽÿTWXÿõõõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáââÿcdeÿƒ„…ÿîïïÿvxyÿMOQÿJLMÿOPSÿhgjÿŸ ¡ÿóòóÿÿÿÿÿÉÉÉÿTVWÿš›œÿùùùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿýýýÿ···ÿSTUÿ­­®ÿûûûÿÿÿÿÿþÿÿÿþþÿÿÿÿÿÿÿÿûÿçáÉÿ¹§lÿ‹mÿ‰h ÿš€.ÿµ¤hÿîèÑÿÿÿÿÿÿÿÿÿþþÿÿÿþþÿÿþÿÿÿþÿÿÿÿÿÿ¹§sÿ”y'ÿØÍ©ÿÿÿÿÿþþÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÚÑ®ÿ•z*ÿ¯œcÿÿÿÿÿþþÿÿÿÿÿÿóíÙÿ¥Kÿqÿ‡h ÿ†g ÿ‰jÿ—}*ÿ³ dÿðìØÿÿÿÿÿþþþÿþÿÿÿÿþÿÿÿÿþÿÿÿÿÿþþÿÿÿÿþÿþþÿÿÿÿÿÿõôåÿªœlÿýýîÿÎǬÿñîãÿìèÞÿþýüÿôòîÿÿÿÿÿþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿîîîÿnppÿijkÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿßààÿZ\]ÿšœœÿûûûÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöõõÿÍÌÍÿÖÖÖÿÿÿÿÿîíîÿ¼¼½ÿ²³´ÿ¾¿ÀÿááâÿÿÿÿÿÿÿÿÿÿÿÿÿÕÕÕÿÊÌÌÿíîîÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿøøøÿÍÍÎÿÏÎÏÿüüüÿþþþÿþþþÿÿÿÿÿüùïÿƶ†ÿ–y$ÿ…dÿƒ3ÿĵ‚ÿéäÏÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþûÿÞÖ¾ÿÜÔ¹ÿýýõÿþÿÿÿþþÿÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿýüöÿÝÕºÿÚÒ¸ÿÿÿýÿÿÿÿÿþþÿÿÿÿÿÿýüôÿÙѲÿʽÿȺÿÑÆ ÿæàÉÿÿÿþÿÿÿÿÿþþÿÿÿþÿÿÿÿþÿþÿÿÿýÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÍŤÿÌàÿìè×ÿáÜÊÿæáÕÿüûøÿöôðÿþþýÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜š›ÿMOPÿÕÔÔÿÿÿÿÿÿÿÿÿÿÿÿÿýþþÿýýýÿ·¸¸ÿLMNÿÑÑÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿûùîÿ¶£gÿŒmÿŽqÿȹ†ÿïë×ÿÿÿüÿÿÿÿÿþÿÿÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿþþÿþþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþþÿþÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿþÿÿÿÿÿþÿþÿþÿþÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿùÿ§•`ÿõóáÿÝØÁÿêçÜÿñïæÿýüúÿ÷öôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÙÙØÿVXYÿƒ…†ÿÿÿÿÿþþþÿÿÿÿÿþÿÿÿøøøÿvuwÿvwxÿîíîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþþÿÿÿÿÿÿÿÿüÿƹ‰ÿŒmÿ˜|-ÿîêÏÿþýùÿÿÿÿÿÿþÿÿþþþÿÿÿÿÿþÿþÿþÿÿÿÿÿÿÿþÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿþþÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿýÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþþÿÿÿÿþÿÊâÿÓÍ®ÿàÙÄÿôòçÿàÛËÿÿÿýÿ÷õñÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿpqrÿ[]^ÿêééÿÿÿÿÿþþþÿÿÿÿÿàààÿHJKÿ§¨¨ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîêØÿž…7ÿŽoÿîéÏÿÿÿþÿþþÿÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿýÿþÿÿÿþÿÿÿþÿþÿÿÿÿÿÿÿýþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿ÷ôâÿ¸©{ÿäÞÊÿðíáÿâÜÍÿÿÿþÿöõñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÁÀÁÿNPQÿ®®¯ÿÿÿÿÿÿÿÿÿÿÿÿÿ˜™™ÿY[\ÿÖÕÕÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿà×·ÿ…dÿ°yÿýýöÿþþÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþÿÿÿÿþþÿÿÿþÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿþÿþÿþÿÿÿþÿýÿþÿþÿþÿÿþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿùøìÿº«|ÿçáÍÿíèÙÿÝÚÌÿÿÿýÿøøõÿüüûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿZ[\ÿy{|ÿùùùÿÿÿÿÿùùùÿTWXÿ}ÿûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýúÿÑØÿ‚bÿàÖµÿÿÿþÿÿþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿúùñÿ¶ŒÿßÙÁÿèäÓÿæâØÿù÷òÿûúøÿúù÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿ£££ÿVWXÿÒÑÒÿÿÿÿÿ¸·¸ÿNPQÿµµ¶ÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýùÿÌ¿“ÿƒcÿãÜÀÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿþÿþÿþÿÿÿÿþÿÿþÿþÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþþýÿûùöÿþÿüÿõóëÿûúôÿõôëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿúúóÿż•ÿÜ×ÀÿäáÐÿëéßÿñðèÿüûùÿúúøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿååæÿKMNÿ£¤¥ÿÿÿÿÿiklÿ]_`ÿðððÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþýÿÚΨÿ‚aÿÚÌ¥ÿþþüÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿþÿþÿÿþþÿþþÿÿÿÿÿÿþþÿÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûúÿúúøÿãÝÑÿÿÿùÿÄ»ÿêæÑÿÎŦÿÿÿÿÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿþÿÿûúôÿŽ—ÿÚÖ¿ÿåáÐÿìêßÿñðèÿüûùÿúúøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿùùùÿ~~€ÿvwxÿ¾¾¾ÿVXYÿŽÿÿÿÿÿþþÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçáÉÿŽpÿ²[ÿûúïÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿ÷ÿßÙ¿ÿÿÿöÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûúÿúûøÿçãÕÿÿÿúÿÆ»›ÿéãÌÿÌÁŸÿÿÿÿÿýþÿÿÿþÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþþþÿúùñÿÁ¶ÿßÙÁÿèãÑÿæäØÿøöñÿûúøÿúúøÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿ¾¿¿ÿUWXÿfijÿNQRÿÛÛÛÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷öìÿ²Ÿ`ÿ‡g ÿØÎ¥ÿÿÿøÿÿÿÿÿÿÿÿÿþÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÍ¿Žÿ‚e ÿ®œgÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüûúÿúú÷ÿìçÞÿûùòÿÉ¿ ÿêãÍÿÌÁŸÿÿÿÿÿÿÿÿÿþþÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿùøîÿ½®ÿåßÊÿîèØÿÝÚËÿÿÿüÿùøöÿüüûÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããÿghiÿJLMÿnpqÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿæàÆÿ›€/ÿŒmÿ̽ÿòïÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿðë×ÿŵÿŠjÿ—}+ÿäÝÂÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿúù÷ÿïìäÿñðæÿÐɱÿæáËÿÉÀžÿöõíÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ôäÿ·¨{ÿåßËÿðìÞÿáÛÌÿÿÿþÿ÷õñÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿ”•–ÿADEÿÃÄÄÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿäÝÁÿ¢ˆ=ÿƒcÿ¢ˆ<ÿº¦kÿɹˆÿ̽ÿǶƒÿ·¢dÿžƒ4ÿƒcÿ¢‡<ÿãÚ½ÿÿÿÿÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùöÿ÷õïÿèãÖÿìêÝÿÕδÿËÁœÿêæÖÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔίÿÍĤÿàÛÅÿóñæÿàÛÍÿÿÿýÿ÷õòÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀ¿Àÿgghÿòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿýÿÿÿÿþÿÿþþÿÿÿÿÿÿÿÿþÿöòãÿ;Žÿ˜}.ÿ„f ÿ†g ÿˆgÿ…e ÿ†f ÿƒ6ÿÍÀÿôñáÿÿÿþÿþÿÿÿþþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿù÷ôÿþýûÿáÛÍÿûùðÿÎŨÿÕ̪ÿÞÕ»ÿþþüÿÿÿÿÿþÿþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿ£’]ÿóïÝÿÝ×ÁÿèæÛÿðîåÿþþûÿõôòÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãååÿÀÀÀÿûûûÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿþÿþÿÿÿþÿþÿÿÿÿÿÿÿþþÿÿÿÿûÿþýñÿóíØÿãÚºÿßÖ´ÿçàÂÿøóßÿþýóÿÿÿüÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿûûùÿúú÷ÿçåÛÿóðæÿÛ×Âÿߨ¿ÿÀ²ˆÿúùðÿþÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÛÕ»ÿ¾´ŒÿðìÚÿßÙÆÿæáÔÿüû÷ÿôôïÿÿÿþÿþÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþþÿöõòÿÿþûÿßÙÊÿðíàÿÝÖ¿ÿÁµŒÿáÚ¾ÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿþþÿÿÿÿÿÿþþôÿ¢‘]ÿÿýîÿÓÌ´ÿíêßÿëçÛÿýüúÿõóîÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿù÷õÿûúøÿêçÝÿïìáÿÚÔ¿ÿìèÑÿ­ŸoÿòïÝÿÿÿÿÿþþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿÿüÿÁµŽÿàÙ»ÿçâÎÿØÑ»ÿñîäÿöôíÿöôðÿüüúÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿþþÿõòïÿþýùÿåâÔÿìèÙÿÖÏ·ÿéãÉÿ°¢sÿøõéÿÿÿÿÿþþÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿþÿÕΰÿɾ˜ÿñîÛÿÈ¿¤ÿù÷ïÿêæÚÿù÷ôÿ÷õóÿÿÿÿÿþþþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿÿÿÿÿÿüûùÿöõïÿóñéÿëèÜÿâÜÉÿØÑ¹ÿêåÊÿ± tÿöôæÿÿÿÿÿþþÿÿþÿþÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿþþÿÿÿÿÿÿÞÙÀÿ¼°…ÿóðÝÿÆ»ÿùøìÿëæÜÿõóìÿöõòÿýüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿ÷÷óÿûú÷ÿéäÚÿ÷õëÿÕθÿÛÓ½ÿéãÉÿ®¡sÿñïßÿÿÿýÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿþÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþþÿÿþþþÿÿÿüÿÛÔ¶ÿ­žqÿöõãÿȽ¢ÿ÷óéÿïîãÿêæÝÿúú÷ÿúù÷ÿþþþÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿýþýÿöôñÿüû÷ÿâÝÐÿüûóÿÔηÿÚÕ½ÿçâÊÿ­žoÿâÜÁÿ÷öìÿþÿüÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüü÷ÿõòâÿ¹®†ÿ¶«€ÿþûìÿÐȯÿíéÜÿòïèÿàÜÎÿÿÿýÿ÷öóÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿþÿÿÿÿÿýüûÿ÷öóÿúùôÿãÞÒÿõóéÿáÜÈÿ×Ò¹ÿìèÓÿ¿³Šÿ¸ÿÜÓµÿèãÏÿ÷õëÿþþùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿüûõÿðíßÿâÛÄÿÑÇ¥ÿ¹«ÿÞØ½ÿîêÙÿÔ̳ÿéåÕÿñïåÿåâ×ÿÿÿþÿöõòÿûûùÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿüûúÿ÷õòÿúúõÿêæÛÿëèÝÿëçØÿÜÕ¿ÿÞ׿ÿÛÔ»ÿÖÍ­ÿÑÇ£ÿÌÀšÿȼ”ÿÌÁÿÌÁŸÿÌÁŸÿɼ™ÿɼ—ÿÍÄŸÿÓɧÿÚÓ·ÿáÛÄÿÚÓºÿÞØÄÿïíàÿêèÝÿîëâÿüüøÿöõñÿûûùÿÿÿÿÿþþÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿüüûÿöõðÿùøôÿôóëÿåàÒÿíêÝÿóïâÿß×ÃÿÐĨÿÐȬÿàÚÁÿðëÙÿðë×ÿìæÏÿîèÑÿðíÚÿíçÓÿÚÔ¼ÿÍŪÿÑÉ®ÿçàÏÿõôèÿéæÚÿæáÔÿ÷öðÿø÷óÿøöòÿýýûÿÿÿÿÿþþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿþÿÿÿÿÿÿÿÿÿÿÿþþýÿ÷öòÿöôñÿÿÿûÿêèÝÿÛÖÇÿôòéÿþýõÿñîàÿ×Ò»ÿǼžÿŹ—ÿƺšÿŹ˜ÿø—ÿÊÁ¦ÿÞÚÅÿùöëÿÿþöÿêèÝÿÜÖÆÿóòéÿþþûÿöôñÿùøõÿþþþÿþþþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿþÿþÿþþÿÿÿÿÿÿûûùÿóñîÿüüúÿÿÿþÿåâØÿÞØÉÿæãØÿúøñÿÿþ÷ÿþþøÿÿÿùÿÿÿùÿÿþ÷ÿÿý÷ÿ÷öîÿãßÔÿÝ×Èÿñîæÿÿÿüÿüüùÿôòîÿûúøÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿ÷öóÿ÷õòÿüûùÿÿþüÿ÷÷òÿåäÚÿèäÙÿçâÖÿêæÛÿéåÚÿéãÖÿèãØÿèæÜÿûúöÿþþýÿûúøÿöõñÿ÷öóÿÿÿÿÿþÿÿÿÿþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿþþþÿúù÷ÿùøõÿùøöÿûúøÿûú÷ÿúú÷ÿûú÷ÿûúøÿúú÷ÿüú÷ÿúúöÿùùöÿùøõÿúù÷ÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿþÿþýýÿýýüÿüüûÿüûúÿüûúÿüûúÿüûùÿýüúÿýýüÿþþýÿÿÿÿÿÿÿÿÿýÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿÿÿÿþÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdff-1.3.0+dfsg.1/ressources/dff.desktop000066400000000000000000000002161217176075400176700ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=DFF GenericName=Digital Forensics Framework Exec=dff -g Icon=dff Terminal=false Categories=Qt;Utility; dff-1.3.0+dfsg.1/ressources/dff.ico000066400000000000000000000410761217176075400170020ustar00rootroot00000000000000@@ (B(@€ !23/<1/c^QR1<][F/  +A$$$Ÿ111ð }^***¨222ß"""drjXA)  (;v///é333ÿ444ÿ ƒa***«333ÿ222þ---ã zsfR:#!7g(((»333ÿ333ÿ222ÿ444ÿ „a***«333ÿ222þ333ÿ333ÿ"""À xpaK4- Y'''­000î333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ222þ333ÿ444ÿ///î »‚um\E-  +? ”000ë222þ333ÿ222þ333þ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ222þ333ÿ222þ///î¥uuiV?(  %>l...Ü333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ***Û Ž|rdO8! 2h'''¶333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ222ù!!!¾ to_I2  ,O'''±000ì333ÿ333ÿ333þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ...ë »}ul[D,  +A„000í222þ333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ333ÿ///ë—yuhT=% $>k+++Ì444ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ111ÿ111ÿ111ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ444ÿ&&&Î {qdN7!/b(((¶222ù333ÿ222þ333þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿeeeÿ©©©ÿYYYÿ///ÿ333ÿ333ÿ333ÿ333ÿ333þ222þ333ÿ000ó"""Á‰so^H0 +E&&&ª111ò333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ:::ÿËËËÿÿÿÿÿëëëÿ222ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ///ð´zvkYA&3u000é333ÿ222þ333ÿ333ÿ333ÿ222ÿ222ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ777ÿ­­­ÿÿÿÿÿÿÿÿÿŸŸŸÿ+++ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ---â }tcF###E,,,µ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ,,,ÿ+++ÿ...ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ\\\ÿðððÿÿÿÿÿîîîÿQQQÿ111ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333þ222þ333ÿ333ÿ$$$Æ ‘vX)###222s222î333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ555ÿ¡¡¡ÿ½½½ÿuuuÿ***ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ000ÿ®®®ÿþþþÿÿÿÿÿ¦¦¦ÿ666ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ///ï ‹^----222£333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ***ÿ···ÿÿÿÿÿÿÿÿÿþþþÿhhhÿ...ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ111ÿAAAÿùùùÿÿÿÿÿùùùÿPPPÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_----222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ&&&ÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿ«««ÿ)))ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ***ÿÿÿÿÿÿÿÿÿÿ¾¾¾ÿ000ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_----222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ)))ÿÉÉÉÿÿÿÿÿÿÿÿÿÿÿÿÿwwwÿ---ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ111ÿÙÙÙÿÿÿÿÿÿÿÿÿlllÿ...ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿEEEÿ­­­ÿÌÌÌÿxxxÿ444ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿeeeÿÿÿÿÿÿÿÿÿÈÈÈÿ'''ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ999ÿˆˆˆÿ¨¨¨ÿ+++ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ888ÿªªªÿýýýÿrrrÿ///ÿ666ÿ777ÿ555ÿ333ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ888ÿÑÑÑÿ÷÷÷ÿ'''ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ,,,ÿ+++ÿ___ÿµµµÿçççÿìììÿÅÅÅÿwwwÿ777ÿ222ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ'''ÿµµµÿÿÿÿÿFFFÿ...ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ---ÿ–––ÿýýýÿîîîÿ§§§ÿžžžÿÓÓÓÿÿÿÿÿ²²²ÿ---ÿ333ÿ333ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿbbbÿÿ¤¤¤ÿŸŸŸÿ­­­ÿ777ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ000ÿpppÿ÷÷÷ÿÐÐÐÿ;;;ÿ555ÿ555ÿ;;;ÿ™™™ÿÿÿÿÿÿ+++ÿ333ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ333ÿ222ÿ111ÿ222ÿ333ÿ999ÿÚÚÚÿúúúÿ×××ÿÿÿÿÿÿÿÿÿ^^^ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ666ÿ´´´ÿÿÿÿÿ777ÿ111ÿ333ÿ333ÿ222ÿ333ÿØØØÿöööÿ...ÿ222ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ333ÿ,,,ÿ===ÿRRRÿ===ÿ...ÿ555ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÿqqqÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „a***«333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿCCCÿ×××ÿÀÀÀÿ---ÿ333ÿ333ÿ333ÿ333ÿ)))ÿŸŸŸÿýýýÿVVVÿ///ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ333ÿ,,,ÿtttÿÛÛÛÿêêêÿŸŸŸÿcccÿÈÈÈÿÿÿÿÿÿÿÿÿþþþÿìììÿ˜˜˜ÿÿ(((ÿ222ÿ000ÿ111ÿ333ÿ333ÿ333ÿ333ÿ333ÿ444ÿ „`***ª333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿCCCÿØØØÿ¾¾¾ÿ...ÿ333ÿ333ÿ333ÿ333ÿ***ÿžžžÿýýýÿYYYÿ///ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ222ÿQQQÿãããÿÿÿÿÿôôôÿ›››ÿíííÿüüüÿÙÙÙÿòòòÿþþþÿæææÿ¬¬¬ÿÿÿÿÿÏÏÏÿ<<<ÿTTTÿIIIÿ222ÿ222ÿ333ÿ333ÿ333ÿ444ÿ €[+++¨333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ999ÿ¹¹¹ÿþþþÿ444ÿ222ÿ222ÿ222ÿ222ÿ000ÿ×××ÿ÷÷÷ÿ333ÿ222ÿ333ÿ333ÿ222ÿ’_,---222£333ÿ222ÿpppÿüüüÿÿÿÿÿûûûÿžžžÿ§§§ÿfffÿ"""ÿQQQÿƒƒƒÿiiiÿAAAÿ°°°ÿÅÅÅÿ©©©ÿÿÿÿÿÿÿÿÿ˜˜˜ÿ---ÿ222ÿ333ÿ333ÿ444ÿ oG---¡333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ///ÿwwwÿÿÿÿÿÃÃÃÿDDDÿ///ÿ,,,ÿ>>>ÿ———ÿÿÿÿÿœœœÿ)))ÿ333ÿ333ÿ333ÿ222ÿ‘_,---222£333ÿ222ÿeeeÿõõõÿÿÿÿÿÿÿÿÿöööÿÔÔÔÿ444ÿ222ÿ000ÿ---ÿ...ÿ000ÿ000ÿIIIÿÿÿÿÿÿÿÿÿÿÿÿÿðððÿ???ÿ111ÿ222þ333ÿ444ÿP,/// 333ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ333ÿ›››ÿÿÿÿÿáááÿ¯¯¯ÿªªªÿÍÍÍÿÿÿÿÿºººÿ666ÿ222ÿ333ÿ333ÿ333ÿ222þ‘_,---222£333ÿ222ÿ555ÿ¼¼¼ÿÿÿÿÿÿÿÿÿÿÿÿÿœœœÿ000ÿ222ÿ333ÿ333ÿ333ÿ333ÿ222ÿ777ÿñññÿÿÿÿÿÿÿÿÿæææÿ111ÿ222ÿ333ÿ333ÿ000Þ1&!!!g222ð333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ555ÿgggÿÜÜÜÿÿÿÿÿÿÿÿÿìììÿ………ÿ;;;ÿ222ÿ333ÿ333ÿ333ÿ333ÿ222þ‘_,---222£333ÿ333ÿ222ÿ...ÿ}}}ÿ©©©ÿoooÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿgggÿãããÿÜÜÜÿTTTþ///ÿ222ÿ222ð***’&-EQ_(((¿222ù333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ111ÿ***ÿ555ÿ777ÿ)))ÿ///ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ222ÿ,,,ÿ)))ÿ---ÿ222ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ...ÿ(((þ&&&þ000ÿ222ó...©C:dXw'˜†´MD‘th†+++Ê333ü333ÿ222þ333þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222ÿ111ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333þ222ÿ333ÿ///¾ P*2 *%Z,©•¿3Æ®ó5͵ÿ3Ä­õ'™†Ë„rt‹...Ù444ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ111ë$$$_$3E#‡vœ4ɱú5Ì´ÿ5Ì´ÿ5˳þ5Ì´ÿ5Ì´ÿ3Ȱûrd±|wnž222ö333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ222é,,,Ÿ,(Fh\0»¥á5ζÿ5Ì´ÿ4˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5Ï·ÿ-°›àKBœm u***É111ó333ÿ333ÿ333þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ222û---¥N"4eXw,¬˜È4ʲý5͵ÿ4˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5ζÿ4ʲý)ŸŒÑC;˜tkŒ+++É333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ///ÓO,4T+§”¿3ǯõ5Ì´ÿ2˳ÿ+ɰþ+ɰÿ+ɰÿ+ɰÿ+ɰÿ+ɰÿ+ɰÿ+ɰÿ+ɰÿ*ɰÿ-ʱþ4̳ÿ5Ì´ÿ3Å®÷&”È}vsŠ000é333ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ222þ111ï(((y1 Kvh3Ưö5͵ÿ5Ì´ÿ3˳ÿgØÆÿÝ÷òÿæùöÿæùöÿæùöÿæùöÿæùöÿæùöÿæùöÿæùöÿèù÷ÿ¿îçÿ@θÿ4˳þ4˳þ5ζÿ3Æ®ø`U§vh$$$®111õ222ÿ333ÿ222þ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ‘^,---222£333ÿ333ÿ333ÿ333ÿ333ÿ222þ333ÿ333ÿ111ì,,,Ÿ7&Bpc‚/µŸ×6Ï·ÿ5Ì´ÿ4˳þ5Ì´ÿ2˳ÿãÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿJѼÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5϶ÿ+©•ÚUK¡{j€)))Å222õ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ333ÿ222þ^,---222£333ÿ333ÿ333ÿ333ÿ222þ333ÿ222ÿ...¨K)1UKo.±œÍ4ȱù5͵ÿ4˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5ζÿ3Æ®÷+¤Ö71’rp‹,,,Ï333ÿ333ÿ222þ333ÿ333ÿ333ÿ222ýŠ[+---222£333ÿ333ÿ222þ333þ333ÿ111ã T*6R) ·4ʲú4˳þ5Ì´ÿ5˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ë´þ4˳þ5Ì´ÿ4˳þ3ǰù#†v¾}yn“111ö333ÿ222þ333þ333ÿ333üyO'...222£333ÿ333ÿ222ÿ111ê*** + #Nqd‰2Á«í5ζÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ëáÿa×ÄÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ6иÿ1½§îXN¢ qi'''º111ò333ÿ333ÿ222ü\4333333¢333ÿ222÷...—>$=ug„.²žÒ5ζÿ5Í´ÿ4˳þ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿ­êàÿUÔÀÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5͵ÿ5͵ÿ+§“ØUL um†)))Á333þ333ÿ J 333333¬222°)))+%92\.³Ï4ɱù5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿÿÿÿÿøýüÿYÕÁÿ?ηÿÇñêÿÿÿÿÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5˳þ5Ì´ÿ5Í´ÿ3Ưø+¦“Ø!Šst‚---ÖP333333A9 +¨””5͵ÿ5Ì´ÿ4˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿÿÿÿÿÔôïÿ@θÿ5Ì´ÿ•äØÿÿÿÿÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ4Ȱúug² |iO/3ǰ3ǰ\4ʲÕ5͵ÿ5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿâÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ“ä×ÿzÝÎÿâ÷ôÿÿÿÿÿÿÿÿÿÿÿÿÿùþýÿJÑ»ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ6Ѹÿ/¶¡àtf )$B 5Ì´ 5Ì´±5Ì´ÿ4Ì´ÿ5˳þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ2˳ÿãÖÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿJѼÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5ζÿ2¬³XM#4Ì´4Ì´J5Ì´ê5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ3˳ÿhÙÇÿá÷ôÿÿÿÿÿúýýÿìú÷ÿìú÷ÿìú÷ÿëú÷ÿïûøÿþþþÿüþþÿÃïèÿ@θÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4ɱæ*¡O *%4Ì´5Ì´”5Ë´î5Ë´ÿ4Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ0ʲÿ0ʲÿÿÿÿÿÐóíÿ+ɰÿ)ɯÿ)ɯÿ&È®ÿRÓ¾ÿýþþÿÑóîÿ"Ç­ÿ4˳ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5Ì´ÿ4ʲë1¾¨– -'5Ì´4Ì´.4̳5Ë´ü4̳ÿ5Ì´þ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ3˳ÿ:ͶÿÿÿÿÿÓôîÿ6Ì´ÿ4˳ÿ5Ì´ÿ1˲ÿ[ÖÂÿýþþÿÓôîÿ,ʰÿ4˳ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ4ʲ÷2¿©¢(œŠ:5Ì´5Ì´4̳15Ë´¿5Ì´ÿ5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ3˳ÿ;ͶÿÿÿÿÿÓóîÿ6Ì´ÿ4˳ÿ5Ì´ÿ1˲ÿZÖÁÿýþþÿÓôïÿ,ʰÿ4˳ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5Ì´ÿ3Ä­Æ(œŠA -( 4ͳ5Ì´Y5Ì´ê5Ë´þ5Ì´ÿ5Ì´þ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ3˳ÿ6Ì´ÿÿÿÿÿÖôðÿ;Ͷÿ4˳ÿ5Ì´ÿ1ʲÿcØÅÿýþþÿÐóíÿ+ɰÿ4˳ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´þ4˳þ5Ì´ÿ5Ì´ÿ4ɲí,«—a5Ë´5Ì´–5Ë´æ5Ì´ÿ5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5̳ÿ'ȯÿäøõÿóüúÿoÚÉÿ0ʲÿ0ʲÿ3˳ÿ¯ëáÿÿÿÿÿªéßÿ,ɰÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ5Ì´ÿ4ɱç2¿©˜WM!5Ì´5Ë´25Ì´š5Ì´ÿ5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ0ʲÿpÛÉÿÿÿÿÿèùöÿšåÙÿƒàÐÿ¶ìãÿüþþÿûþýÿLѼÿ2˳ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ4˳ÿ1¾§) Œ;5Í´5Ì´5˳14Ì´Ö5˳ÿ5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ4˳ÿ6Ì´ÿŽâÕÿÿÿÿÿÿÿÿÿüþþÿÿÿÿÿùýýÿ_ÖÃÿ2˳ÿ4˳ÿ5Ì´ÿ5Ì´ÿ5˳þ4Ì´þ5Ì´ÿ3ǯÖ'˜‡@ -( 5Ì´4̳m5̳å5Ì´ÿ5˳ÿ5Ì´þ5Ì´þ4˳ÿ0ʲÿYÕÁÿ§éÞÿ¼îæÿ•ä×ÿ>ηÿ3˳ÿ5Ì´ÿ5Ì´ÿ4˳þ5Ì´ÿ4˳þ4ʲê/µŸu ;ı5̳5˳5Ì´ê5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ1˲ÿ+ɰÿ*ɰÿ-ɱÿ3˳ÿ4˳ÿ4˳þ5Ì´ÿ5Ì´ÿ4ɲí1¾§’yk$5ͳ5ɶ4Ì´+5̳¢5̳ÿ5Ì´ÿ5Ì´þ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5Ì´ÿ5˳þ5Ì´ÿ4Ì´ÿ1¾¨¢%‘€3 4Ì´?5˳ä5Ì´ÿ5Ì´ÿ5Ì´ÿ5˳þ4Ì´ÿ5Ì´ÿ4˳þ4Ȱß)œŠF 3̸5̳5Ì´z5Ì´à5Ì´ÿ5Ì´ÿ5˳ÿ4ʲà0½¦€ 5˳5Ì´"5Ì´…4˳â4ɱ„-«—" )$5Ì´5Ì´4˳,¯šÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿÿÿÿÿÿðƒÿÿÿÿÿÿÀ€ÿÿÿÿÿÿ€?ÿÿÿÿü€ÿÿÿÿø€ÿÿÿÿà€ÿÿÿÿ€€ÿÿÿþ€?ÿÿü€ÿÿð€ÿÿÀ€ÿÿ€€þ€ü€ø€ø€ø€ø€ø€ø€ø€ø€ø€ø€ø€ø€ø€ø€øÀøàø0ø< øðøàÀø€`ø8øxøàøÀÀøpø øpùàŸÿ€ÿÿ?þ?ÿ€ÿÿÀÿÿðÿÿüÿÿÿÿÿÿ€ÿÿÿÿàÿÿÿÿøÿÿÿÿþ?ÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿðÿÿÿÿÿÿüÿÿÿÿÿÿþ?ÿÿÿÿÿÿÿÿÿÿÿdff-1.3.0+dfsg.1/ressources/dff.png000066400000000000000000000120241217176075400170030ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞbKGDÿÿÿ ½§“ pHYs  šœ´IDATxÚÝ[{tTÕ¹ÿíó˜™3“I˜WB@0 %ˆ!QYí½"P°Ò[aQ¢\‘¶Ö-ºÔ½\ôê¥u-[]V­âE´ÕVhŠ-&ƨ ¨A„äe„d2 I&™Ì+óÌÌ9gß?r&a’L^´÷îµfeæäÌìýû¾ß÷û¾ý8ÀeneÕE‰ïÙÒªBÃk›ËâÔ˜ËÙYiU¾_X€_8•eÕl}¥$ÿ å62ë*íe¹TT/@ þíð[Ü ((¥ö€_|óß—œü-€°âùÿ…¾¡|á”’?‚ìø5JA ¡  ”RI‚ýÜÙà}Þ][ ‚(($ôÿ”J[®{¼ð[ä?Ü©tH“õÝg €"Ð#½Uw&°í¿l¨™(#Œ»öU~·~çpŸ!ª‹r@ñ!¸€%ñ>™Šå(  £Š‡BÈuƒÒŸ*?v¿øòÓöóO˜4=+{Ýâ?§ʪ¿¹Òê²™VJBúÔP —–ÕìÔ×d7@~P¥D)SGÓdL1,Õ¸”R0 ŽÕ^üb4 „€:uìΈrhÔàFè-“U·ß¸Ì47–¿ò~fKãA%¦ƒÙÙÙWfffþ”aö¡ñš)æð+/:”$­¶†™j4KÒÓÓ÷x<ž·Z[[kùãÚ-+Ödþëªu“×[²Ts9ž¨dyxmHüwÊ2B@X† ‘#-MÛ¶·îÿêhO3Ùb±dgee«ÕêùÉô‰RJ$I2HSp“¤ ®Ú꣛Ùl^š‘‘QÚÞÞöêû%]¼_Òuæ§å,úÎwk&[Õs$‰^<’úÊ7Cø‹(ÿ†lçB åuy¿¤ëOFFF¦Õjý® ó !ÚŽK„@)U)º7xL*•êG¹¹ÓWfff=SWW÷öë/´zöìj?ºnCöâå+-?S©¡/¢|ÁZø#Màa'3ðk!J!(ˉȽï¼Öþ·¿½í¨EÐ3kÖ¬ez½~9!DKI%+‘a/äçç³<Ï¿IY—ª€(Šg½^ïãíím±˜¨±dñÓŸ|!ocötÍu<Ïh)• ɽ)”Ò„°”aÔ„€ Ú+GÎ|å?õäýçÞÐ˲Œd2™³¬VëX–ÍL5SJiSSÓv¯×{À _ —ð2++‹aYv%!dÞHÁ²l– ?4FFÓÒÑî9U¾×YIÒj4óz}oå8CÀQ–Q†á‘ü¥ÇrD– ן žÙµ­µì/·Uð[,–©¹¹Óo1™LÅ ÃèâÀS­E<ϱH$Ò¡dgÒ:`$H¢,˲ùZ­v‰Éd²ú|¾ÏOóÖ~þ±û„£M934Whuì$e#d HQBaY ­%bßù»ÖwßÜ~ᨭ!Ü"Ÿ——·Öh4~çùñ¯Œ´óz½c€¢CÑq7ßl6§¥¥Õt´wŸ>]íoy÷-ÇÇÙÓ…èÔéš|†éSÅxÚì+_eqß;e[l(³5„²nnîµÓ¦M{€çùéø„~F\N¨YýÐi4š•™™™ù‚ Ôùz¼Í‡÷{¾:þ…·òªyz“65óŠêêjäååA¯×T*º»»±mÛ6¬]»¡PçÏŸ‡ÃáJ˜8%Å1© 77‡B4½Hô”é.Ž9•J…¼¼Ÿ§OŸÆ±cÇú e2™°~ýz<öØcÐjµ „€eSš’‘5ñ”—,Æ=ž ø”·ÆÔj5‚Á l6‚Á xžÇqhhh@,C]]@¸\.LTóûýhllÄ7Þ­V 9a)ŠR ­V‹… ¢··uuu)9`$ëÑ8â7¿ù òóóa±Xðå—_"==õõõ‡Eã¤-bÿþýX²d vìØ7"ö‡àúõë1{öl¼ð $ <ÏŸ’ÑíðáÃX½z5n¹å,_¾‡ÇM˜†ÁðÆoà¾ûîCii)>üðC„Ãaaîܹ(--Å®]» ÑhRúMn,2 ˜:u*"‘ìv;t:Ý„O4üË/¿Œ£G¢¸¸‹-Ïó¨¯¯ÇæÍ›qèС”@mmí„z>ÞT*6oތիWã‘GÁ–-[ V«A,Ëe9õÖ‘ˆ`2/˜L&lÚ´ K—.ÅÉ“'!B*Õט<ŸŸŸ5kÖ€a#‰@’$ˆ¢Ø/ˆ#u¨‡ñÔSOáºë®‹o§RŠòòr¨Tª O)ŦM›ú¯½ýöÛýê˜te4ƒ‘$©|Üë………EqB¼‰D°nÝ:äåå<ˆÊÊÊþùÈh¢7%Ð$œ&„€ã8TTTô¦”âÀ#ŸT›,ËÈÊÊÂý÷ßߟ _|ñŤ3ÑÑ´KL …䌌Œ“”Ò„C²UWAðÄO «« S§NEEE>ûì3‚0!Ôàú»wï^´··§þâSe’WÅ^ Øâ¿ÄÀ‹3gÎ<-ÂCjµú–dSTI’ðì³ÏöÏÏÇ|¼Í;‹/!%%%ˆÅbíÑÄ©µÏç;ÒÙÙYå÷ûʦ¨8ètX¡´ÔØØXÅqÜf³ùÐäÉ“7±,›™hQBÈ„^bãy«V­BFF`ß¾}8wî\*âß lµÙlïƒA¥4 ÀÀ 8(”°§B¢(^p8å‡ãd^^Þ=:îfBˆ>Õ͈±6–e1mÚ4@ww7¶oßÞŸ÷‡r½$I=n·»²µµõ‹ø¦©Ü  €wÐ5ÁDýQèt¹\U½½½§U*•Šçù\B—ÚÙ€Á‹(§Óù¹$I³Ù|%ÏóW' ³ööv„Ãa<ÿüóèêêJ6Áé§»$IŸÏw´¹¹yŸÛíþ}'Aº\Ð  UùVð YЄxéðx„\.—ÏårµX,[­Ö_r—™`´ Ÿš››÷úýþ.Åñ´æPÀÇÓZÊq~¹ 0PÄxX8N¯Ó鬚5kÖz½^¿*!f%Ji³×ëÝ×ÔÔt@ºò]wÝ]Š1b£¥û ÜÅØ€ “ÉTèõzc²,ûsrrH4µ9€Šg i­ßp×u·Ëúì°b€À$e `6½BqWB>a‚ý_¾}í ¼€¼IEND®B`‚dff-1.3.0+dfsg.1/ressources/dff.xpm000066400000000000000000000113431217176075400170260ustar00rootroot00000000000000/* XPM */ static char * dff_xpm[] = { "32 32 163 2", " c None", ". c #B1C933", "+ c #B3CB35", "@ c #B4CC34", "# c #B3CB34", "$ c #AFC733", "% c #B4CC35", "& c #B0C92C", "* c #AFC827", "= c #AEC533", "- c #B7CD3E", "; c #ECF2CD", "> c #F5F8E5", ", c #C7D96A", "' c #B2CB32", ") c #B4CB35", "! c #B4CB34", "~ c #AEC827", "{ c #F4F8E4", "] c #CFDE81", "^ c #C0D459", "/ c #FFFFFF", "( c #BBD04B", "_ c #B0C733", ": c #ACC232", "< c #AFC829", "[ c #FFFEFF", "} c #AFC82A", "| c #B2CA30", "1 c #E1EBB0", "2 c #CEDE7C", "3 c #B3CC34", "4 c #ABC51E", "5 c #FEFFFE", "6 c #A9C418", "7 c #ABC61E", "8 c #DFE9AA", "9 c #CADB71", "0 c #AFC633", "a c #B1CA2E", "b c #E8EFC1", "c c #FEFEFE", "d c #FEFEFF", "e c #B3CB33", "f c #B2CA34", "g c #A7BD30", "h c #B6CE35", "i c #B1CA2D", "j c #ECF1CB", "k c #DDE7A3", "l c #CEDD7C", "m c #A2B82F", "n c #333333", "o c #323232", "p c #97AB2C", "q c #B8D135", "r c #E8F0C4", "s c #D6E392", "t c #B7D035", "u c #819225", "v c #242423", "w c #313131", "x c #2F2F2E", "y c #7D8D24", "z c #A9BF31", "A c #F8FAEC", "B c #EFF4D5", "C c #BAD236", "D c #9AAF2D", "E c #2F2F2F", "F c #2E2E2D", "G c #8B9D28", "H c #EDF2CF", "I c #B8D136", "J c #91A42A", "K c #282828", "L c #343434", "M c #1F1F1F", "N c #B3CC33", "O c #C6D866", "P c #D2E086", "Q c #CFDE7F", "R c #B4CC33", "S c #A7BE30", "T c #2D2D2C", "U c #303030", "V c #96AA2C", "W c #B7CF36", "X c #59651A", "Y c #232423", "Z c #202020", "` c #323231", " . c #8C9F29", ".. c #A9C031", "+. c #B9D136", "@. c #788923", "#. c #2D2D2D", "$. c #2A2A2A", "%. c #5B5B5B", "&. c #353535", "*. c #636363", "=. c #2D2E2D", "-. c #5C681B", ";. c #272727", ">. c #252525", ",. c #959595", "'. c #EEEEEE", "). c #2C2C2C", "!. c #232323", "~. c #292929", "{. c #424242", "]. c #DCDCDC", "^. c #E9E9E9", "/. c #E5E5E5", "(. c #4C4C4C", "_. c #AFAFAF", ":. c #AEAEAE", "<. c #949494", "[. c #B8B8B8", "}. c #898989", "|. c #EFEFEF", "1. c #868686", "2. c #858585", "3. c #242424", "4. c #E1E1E1", "5. c #262626", "6. c #3D3D3D", "7. c #F4F4F4", "8. c #363636", "9. c #9C9C9C", "0. c #505050", "a. c #C3C3C3", "b. c #494949", "c. c #1D1D1D", "d. c #DBDBDB", "e. c #3B3B3B", "f. c #686868", "g. c #BBBBBB", "h. c #E4E4E4", "i. c #DADADA", "j. c #4D4D4D", "k. c #F1F1F1", "l. c #1E1E1E", "m. c #D1D1D1", "n. c #D6D6D6", "o. c #D7D7D7", "p. c #464646", "q. c #9B9B9B", "r. c #5C5C5C", "s. c #5A5A5A", "t. c #A7A7A7", "u. c #FCFCFC", "v. c #484848", "w. c #2E2E2E", "x. c #C5C5C5", "y. c #2B2B2B", "z. c #C6C6C6", "A. c #626262", "B. c #131313", "C. c #1B1B1B", "D. c #212121", "E. c #0C0C0C", "F. c #181818", " . ", " + @ # $ ", " + # % & * # @ = ", " + + + - ; > , ' # # . ", " ) + @ ! ~ { ] ^ / ( % % # _ : ", " ) ) % % % % < [ } | 1 2 + % % # @ # ", " ) # 3 % % % % % 4 5 6 7 8 9 + % % % % # # 0 ", " @ + % @ % % % % a b c / / d d e % % % % # % % f ", " g h # % # % % % i j / k l / / # % % % % % ) @ m ", " n o p q # % % % i j c r s / / # % % # % # t u v w ", " w n o x y z % + # i j / A B 5 / # % ) # C D E n ", " w n n o w F G 3 # i H / / / / / # # I J K L o n M ", " w n n n o o o z N O P P P P Q R S T n o n n n M ", " w n n n n n o o U V W + % + % X Y o o n o n n n Z ", " w n n n n o o n n o ` ...+.@. #.o n o n o n n n Z ", " w n $.%.&.n o o w *.%.E =. -. ;.L o n n K ;.>.o o n Z ", " w U ,./ '.;.).E !./ / ~.n w o o n o n {.].^./.(.n n Z ", " w E _./ :.<.[.}.|.1.2.#.n 3. n o n n ).4.(.5.6.7.3.n Z ", " w n 8.9.0.a./ 4.b.w w n o c. n n n n o d.;.n 5.d.e.n Z ", " w n n U o f.g.h.L n n n o c. n n n n ).i.j.#.6.k.3.n Z ", " w n n n n 3.c l.n n n n o c. n n n n n E m.n.o.p.n n Z ", " w n n n n j.q.~.n n n n o c. n n n n n / r.~.).o o n Z ", " w n o n M / / s.n n n n o c. n n o #.t.u.o n n n n n Z ", " o o n ).t.d.o n n n n o c. n n n v./ 1.o o n o o n M ", " o n n #.;.n n n n n o c. n n w.x.|.y.n n o n o M ", " $.E o n o n n n n o c. n n w.z.A.n n o L Z ", " ;.o n o n n n o c. n n o ).w o n K B. ", " #.n o n n o c. n n o n o U C. ", " ).n o o c. n n o L >. ", " $.E o c. n L D.E. ", " y.3.$.w.F. ", " "}; dff-1.3.0+dfsg.1/ressources/linux_launcher.sh000077500000000000000000000013231217176075400211150ustar00rootroot00000000000000#!/bin/sh # # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge # # # This script starts DFF. Its right place is in /usr/bin or # /usr/local/bin (installer does it). python ${PYTHON_SITE_PACKAGES_PATH}/dff/dff.py $* dff-1.3.0+dfsg.1/testsuite/000077500000000000000000000000001217176075400153735ustar00rootroot00000000000000dff-1.3.0+dfsg.1/testsuite/CMakeLists.txt000066400000000000000000000035661217176075400201450ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe Malinge ## Main purpose of this macro if to copy Python test files at build. # without it python is unable to load DFF API macro(deploytestfile target_name) foreach(file ${ARGN}) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) # Be carreful, SWiG generate .py files, which sits in builddir, # so we have to check if file exists in source dir before copying it. add_custom_target("testdeploy.${target_name}.${file}" ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${file} ${CMAKE_CURRENT_BINARY_DIR}/${file} ) endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}) endforeach(file ${ARGN}) endmacro(deploytestfile target_name) # Define 'simple' files to deploy SET(testsuite_srcs dffunittest.py # Base unittest file, specific test follows local.py hashtest.py enverrortest.py vfserrortest.py ) deploytestfile(testsuite ${testsuite_srcs}) # Here we use configure_file because content of those files have variable # to be replaced by CMake configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fattest.py ${CMAKE_CURRENT_BINARY_DIR}/fattest.py) # unittest ADD_TEST(modules.fs.local python local.py) ADD_TEST(modules.parser.hash python hashtest.py) ADD_TEST(modules.fs.fat python fattest.py) ADD_TEST(modules.api.env.error python enverrortest.py) ADD_TEST(modules.api.vfs.error python vfserrortest.py) dff-1.3.0+dfsg.1/testsuite/dffunittest.py000066400000000000000000000134641217176075400203140ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe M. # import unittest, sys, os, fcntl from cStringIO import StringIO sys.path.insert(0, sys.path[0] + '/..') if os.name == "posix": try : import dl sys.setdlopenflags(sys.getdlopenflags() | dl.RTLD_GLOBAL) except ImportError: import ctypes sys.setdlopenflags(sys.getdlopenflags() | ctypes.RTLD_GLOBAL) from api.manager.manager import ApiManager from ui.ui import ui, usage from api.taskmanager.taskmanager import * from ui.console.console import console from api.loader.loader import loader class DffUnittest(unittest.TestCase): debugTest = 0 def setUp(self): """ Initialize framework Load modules Load console without loop Redirect stdout and stderr to readable fileobjects """ if not self.debugTest: sys.stdout = StringIO() sys.stderr = StringIO() self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) self.ui = ui('console') loader().do_load(sys.path[0] + '/modules/') self.ui.c = console() self.tm = TaskManager() self.vfs = vfs.vfs() if not self.debugTest: self._restore_streams() # Close and re '.. = StringIO()' to drop output from modules loader # FIXME [...] sys.stderr.close() [...] AttributeError: __RedirectIO instance has no attribute 'close' try: sys.stdout.close() except AttributeError: del sys.stdout try: sys.stderr.close() except AttributeError: del sys.stderr sys.stdout = StringIO() sys.stderr = StringIO() def tearDown(self): """ Restore stdout and stderr before end of each tests """ sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ def _set_nonblock(self, fileobj): """ Set a fileobject non-blocking """ fd = fileobj.fileno() n = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, n|os.O_NONBLOCK) def _hook_streams(self, stdout, stderr): """ Avoid output of driver in current shell """ self.old_stdout = os.dup(stdout) self.old_stderr = os.dup(stderr) self.pipeOut = os.pipe() self.pipeErr = os.pipe() os.close(stdout) os.dup2(self.pipeOut[1], stdout) os.close(stderr) os.dup2(self.pipeErr[1], stderr) self.driverOut = os.fdopen(self.pipeOut[0]) self.driverErr = os.fdopen(self.pipeErr[0]) self._set_nonblock(self.driverOut) self._set_nonblock(self.driverErr) def _close(self, *fds): for fd in fds: if type(fd) == file: fd.close() else: try: os.close(fd) except: pass def _restore_streams(self): """ Restore stdout and stderr for tests be able to display informations Fetch stdout and stderr from driver and return both in a tuple """ try: readOut = self.driverOut.read(4096) except: readOut = None try: readErr = self.driverErr.read(4096) except: readErr = None self.driverOut.flush() self.driverErr.flush() os.dup2(self.old_stdout, sys.__stdout__.fileno()) os.dup2(self.old_stderr, sys.__stderr__.fileno()) self._close(self.old_stdout, self.old_stderr, self.driverOut, self.driverErr, self.pipeOut[1], self.pipeErr[1], self.pipeOut[0], self.pipeErr[0]) return (readOut, readErr) def _getResultsArrayByProcName(self, procName): """ Return array of results from last processus name procName execution. """ val_map = None outTest = [] for i in range(len(self.tm.lprocessus) - 1, 0, -1): if self.tm.lprocessus[i].name == procName: val_map = self.tm.env.get_val_map(self.tm.lprocessus[i].res.val_m) break if val_map: outArray = [] for type, name, val in val_map: outArray.append(str(name) + ':') outArray.append(str(val)) return outArray raise UserWarning def _readExpectedOutputAsArray(self, filePath): outArray = [] with open(filePath, 'r') as f: for line in f: if len(line.rstrip()): outArray.append(line.rstrip()) return outArray def _getOutputArray(self, stringBuff): sArray = stringBuff.split('\n') outArray = [] for oneLine in sArray: if len(oneLine) > 1: outArray.append(oneLine) return outArray def _getEnvObjByProcName(self, procName): """ Return environement array from last processus named procName execution. """ val_map = None outTest = [] for i in range(len(self.tm.lprocessus) - 1, -1, -1): outTest.append(self.tm.lprocessus[i].name) if self.tm.lprocessus[i].name == procName: return self.tm.lprocessus[i].args raise UserWarning dff-1.3.0+dfsg.1/testsuite/dftt/000077500000000000000000000000001217176075400163345ustar00rootroot00000000000000dff-1.3.0+dfsg.1/testsuite/dftt/5-fat-daylight.zip000066400000000000000000000254321217176075400216050ustar00rootroot00000000000000PKKs„0 R0 °YF5-fat-daylight/COPYING-GNU.txtUX ]ap@]ap@õ\[sÛF²~ÎÔùSz±T3‘sö’(•*J¢,îJ”BRvô¶ 9±.Ìúëž xqrÖµY[$ÐÓÓÓ—¯/£ï¾ÓôçãèIŒãþ~|º¼^iúo0š Ôwüýùd*›•…þè4…Ñç?ýt®”¾*7Û*{YÕúôêŒ>üûO ¥o*cô¤\ÖoieôMÙ‹´&‰óžÒ‡ÿüå'=5ëMnôcžÎM¢'MVýã?$ú²´5Þ¿ïkýÇóóó÷ç?þð7­Ÿ&}¥¯¦Ú–ÄWfõÆT묮ÍB×¥žƒ:-z‘ÙºÊf ‘£ggÄÌ_fÆ*].u½¢7óln kô¢œ7kSÔ‰¦çõ|•/Yñ¢³䋲Öiž—ofÑS$ –ÐceÒõ,7$=]OÉêeYé5q®­—þ[›½Âa~¡ßÒ­Þ–M¥–$¸E¹Æ7vÅÏóÌm®îi}¹%¾‹ºJ-ñWÓZ||¦0UšëÇfFK«;·b7+jS,d©—&­RúÙðRú[Ká;åy~ÿžYƒOÛÐcX4l‡–À³¼Q ñhucI[zDfU—5íYK7›œ„ÅY>|¦«7ªÕ›w6’`Á»I‹­.éJoªò¥J×úmU‚rS¯ÊÊ’”Ö¤ô¤j¬±t:)ׯ½vLG;››—¤.$¾ÙVyaße³*­¶úÈβÂÖ&]ôδ~.=O ÞìV 3,zDZ¥,Ë´æóÊú»1éHƒ¥ê9Ið8ªÌÒT¶Cp˜@'Õ¦¢õi‡Dþ0gvO÷â3Mkh…Z¥¯r‘vD¶#&³ÇŸ>uºS½°*(¶'RƒWZZgKÖo™]%a)ÚËÜd¯ ÒTs^ÐÉT,°C¶V+ÿ")-ý½Šgœ¦v´‘^'åÓÄã\¸‘BæMøõr¿%òä¾å[ »(AÓ‚2ÉÙòéLK¼Z›y-¦Ã>Ïò©&’ee ©9´È yÆ,[(RV¸'Ólên¡Æ¡Òö‹|UâT*nÅ”§zj*ïtV!“¶yZ3ñ¹©ê”6LOlèËl–åY9?Ê"QuðDcI&àȉ].²%Ô—EqC_˜¯)¼tâŸ8HÎ6ó•N½ÈIV+³SôSñŽÙgè¥!B¼NC~à%súGÚ‘©‚„¿ÒJå 3ÒÐÕžX¿»£ÎôÊ– , ª©}«"Í#:}R‰À‡]‘JÐ3k¯ Uàƒ˜ª( ý+«”?ذ9¤%¤÷õJ×ot¦µÙØŸõéùÇ% œ]©“ZªÓg$?²s§&Qdz[e$TÈÈò—¹y!3çˆg9>»—Ä'L4¿ç0ÄǯÇ\÷sKÂY˜'Æî“ü­Û ¨ÂXhC¢ðl^áÂ)¸ñQ¸âÚš^³á(Ä%½_! myIÞ]'ØÐA —{1†™ÏØÓçkƒULn%lRké+ ƒ7£œ·°±»îȈ™7¯¬@>¦cÅ’Ž$+Ò<¡5dK2$ íkŽ¥U¹hæÂœ.i'kÎqô8…ˆ–rñè=°ijŽ0¢.7ø:ß&¼HìžÀR½"HA¡›Ö¢pYÖBx÷.8nðu8KzßÊäµÌ¼þÞ±’Sóê€ÈHÆ™ŠÐCäÄ&²b‘½f‹LérÆŽD x†,¾Ð†tsÎÖÆqhÕ’¡¿) ™š¢cÏ9MÒ ¨ 3+K|.fô<7©ãDà6$æ7 j!ªéTëƒðòô1äžK˜õ<Ûàüƒår|*i‡â5A†B;HZ÷åt]‰¶Í ,K ½žú‡†¿—éÛé`|?Ñýѵ¾z]§Ã‡ÑDß<ŒéÇÇçáèc¢¯‡“éxxù„¯øÁû‡ëáÍðªÀü=FN‡ ’SG6í@pÌ[Y}qžȎͪ¢AìÝH³¾B)Z·³*s›n´]%©·~c¡šD†'†=ûÉ£ðwBèÙàŘ%°Ïa!Ú¸g¿G:yÂ[™¥bͼ²§¦Ö†âœ6o9ú4@—XÍ^éÄH¿˜Š0ßn8Oß~›Î˜Ú9-+Ï:±9uîPÖ›²b5`0‘(Ç@È!°ø÷Xe¬w¹!6/à;°>1•“m6é DvzKž‘Á’Dœ„° ƒ÷yÞ¼c‰²®¤u_ÊŸŒ>‰W?òÀ•;Ë`—. ØL¬>¡ØqB†Ò'÷þ*¡tr°:fM2˜ðl²h‡S‡ q±ŒÊšÚflòA‰ºW•Þr©ª¦Ø½sÊé˜EâS#?Jn \ǯ¨¬—àö’ÄÙr `7šÕõž¢)¿ò)¹A³ô*8+!æf†ð9;.ÚçŽÏzê³”¬j·AËbwÂ&¥‘HpÞ“nÿLÂ걚#óÎÆ8ǃkÀæ¬` YShˆ‘ñ‘›7-þUÍ&›7ecsY|ûrÒ]údC§C›`Œà˜ŒŸR­¥9Ïã61ÏÓlMR!¦}ä¿Ð_ŒÙÀ$ Ý)yÍúˆüƒô¸ã %óÃæÓ™5­‚XF{ ¤žaÙæ‡芎·â›[G¥yI§+¸­}šŽ*œ’d: ^Ž!W»ÚZ2ŽÜéµ³O×d%x[G%u8±Ü8ƒ=xá/ݯ>3÷ ™5çC«9ß1EÙUuXa¼ÇtžM‰g£'Ž‹ka÷¨+N\,=&»ö®#t^%·¹s•ÎÈnè%©îµ1¢$² k¢8þ³âRRzÖ&ó´±’A̸Ìr Ÿs’- –öóv*Ç4,ü*Û´Ï1YÞâs„‚÷@ d[Nñ䩞ð1Ûãƒud#y‘pœe¹Ô–|:ȼQpæo€Uuëü™•P‡}í¸@w°LƒßcØ].‘uùˆÔ­’B ^Ÿ¢Ø³j¨@Ž!úeûó3݃è} /H¯Wª]Hm†³”§ªaˆüŒÛ<9Zr°QN(¢„Žò—tRBª÷°¨¿d˜Ž!Ô˜ªEÚ Þ‚Câ.ƒ“¯p(” Ð¢OEQ6ä]PtA˜¢ãñôA—2÷ÁñÜ瘖ò—Ä#° Î „ðÂY[°àê[|ëEã½´ù¸˜Â®Á¸0jòÜÇ/Óœì–ú53o;>‘©´ïtðunØ]ýŒÛ Ùµ5ùÒ×ýoL±ŽCzоT ŠŽÈqbäw³þÓd•”`„â±Þ!w_7ág×RTàšœ‹&A_yÍÖ<8U°}ŸR¨­q…ÒI~EÀÐQÓL8.¡ö0©- ¢Æ¥\@£Šb‹;ð°5d}Ð3,`Þ[“Œ_‘‡Õ°„ØådxØDÔ±¸VÝÐØgSÚqH\ïHíÎÒ(:7uxAí(MבTèmv=œcŠ‹‘Ô$³ ¢vƒ ;Öpº %4|RèÞò^Hu% à¶"yž€†)‡øŠ’¸;z…£­Ü2d6-¤Bpò)ÛªÌKZ-(ðùÓKú aZŠcSz1‰Úà”ëïup˜NNŒŒ¢úU[«¸tDIvW¡£A(€™•B=w¡é”Vœ8´Kqz£ÌWSIúë gRB #?(ì(*+‚s9ª>²¡íyX µÈ¤·³†§K_^ %OÖå<²Hå!µ‹µØAò‡ß@"gø9Õ¯eÞ ¨¿¤¬×ÖeE‰•óéíþû¶^hVyÿq'n“uYÊÁ(÷ã·¡úîv¹G )ÁÔßgˆQåìߨ©ø8Þ¼©Ùß‘ˆ¿jâ-îœyø EQä P2s6%% ’@‹ŸúsŠÉÀÒßpø,7ë*©)s \“e‚z`&@µIHâlÞ[mTTø”XÓݰ;¼9Q+×i•‘þ7¾0Ô t]“€Èöw–{bÈè×4Ï„É,'ï\sýMöµ5iÅš6­`€Äa›8@îTv–  iè10r.Ÿ! ú™Êcm'¸X_ŽÂ"{¦°+ñ(FïNçøIþsgp\þ²“ÿâ æÇ´++ ñQÎÊøÔf> ‰ý;}¨#[FáêYš/…ø3c\ÛVÊK.@¢ð””¶í•;|Aïþb¬õÇÆËû 5 Z‡´œäRIyGOš™3‘>A —NƒlÙ:©ˆ /Ü”ãX‡È‰‡ÐŒs•ÚnfFòäŽè ' 1ÓR‘ ¦/«+^]–ôý˜=¾èsZ¤A®”µY evyc93I­-ç™/ˆ‘ ¤P|³ÌŠLj­È³Üó⇫l#elåã˜Ë\Œa*äyžÆÀ¡Ýíò–þB¶SvcøÄ³ÉÞ~bsᢆ«Ç¡›ÇÍÁPê  6~íi»” e’ÑŒ3…s:k-aþ›Àš4šÑé©ì!56¹@ 7~æv¨(FU’´Ú­­ ºq‘ Ž·»dJ$Õ¦`ÜÂ<‡¥”ƒí©³P.4w¥GA~¹‡"ê€X‘ [ãêd¬èÄŸ"ê¼´È`tœºV4kÃFæ=Õú·4à:¹fp¹C`Oû<Üf0ÊÄ苆q¾U‡`eÇK¢I|ܼ¬"ßž¹Ž¹9×J𢡒ˆÈN¹(ºZÿo‹ ER’r å\Dü£––P¢©Ð^óuƒB.'P.Ô{wAt3Q`"­ØÔŠ1ΣÁòèòÇW‡ÿD_It{Eiƒ0P»`†(’á ;}Ïl©`‡^À€ÐÜ ÎUjV, ßfçãE„ð-ª †þ›Ÿ\Ȫvü&0ƦÃÇ„ô¾Ø3@ù ]ô¿e“‹gɳ”’G†{‘£óé]œmB%7õNf3%}sšUÇ[°³ Û(fGó)¾”m»­\WÒ#~ä`PªínïCfoñ¦>+«¸I·ÊfY-¥ú<} Ý{—(îïGèPp)Ñ›žm¥1ÆõŠÀÞ)ÞŸºãÑ"û™wÐpœ­‘õSWÔíœqÍmjTý˜Ñÿ§±'öÕŽwR7êðמôQêlm@ùÔÿƒ×ñPÃŽ9åGŠì­Ñ»4åÉî™#îÖ£¿ç‹¬›}Qv¶9Ò õ#Î=e\årÙTÜ¯ê œ¸¬-ª¿Ó!ÙtÎÕ9ÖkÅŠ[\=Õµ$7¡"(‰2[úÿ9Ωµ@×RŠÜ1ïc'#û[O—عœB&:”µÿ»Y¼p-O@J”JÏYEÄ1þ¡¥;Oß?@½FŸJ·y¹ÙBׯ&smŒ=KT¤… †YެÐS7ÿ‚M W„ü‘Pºìn=õ™Óõ#3©ÒKìØH"í6±e„ ?±nÇß•‘ 7ÿ„×ãš~éиÅÔ©—ÍÖMNfj¤Y$ Š!/W¶^_Åm›hZÏÐYrù=zÍ…þ½CôöŠyÄö\Û2)õ§¦gÊ& '3¢º*·”&lßóHAdÜNð«óØ[òNl®Å² °0Lj—íÃO”F2ª }ÈÙópbáF>¡ Ä•ð,…¨8Îñc38CtÔ+­PâCþû‚ᢦÏ^AŠþ¹29´$ؤ+Ä( £< ½LÆ8oò”ëþã#ï_Þ ô]ÿ3IsðûÕàqª?ßFêä?‰ŸÉ´†#ýy<œG™ qÇ÷S}ûpw=ó´î÷´:¿¨ûãép0QÄǧáuwS'ý ±}¢?§·OÓÀ<6×=ëG׉ ™Ðà÷Çñ`BûWD{xOèËáèêîéš/‰ÂèaJr¢ŸÓÖS'fˆ¾ºŒI~£iÿrx7¤%19|3œŽh ž/î çWOw}ÚÄÓøña2@ý"$"$ðñpòOÝŸ('ØßžúI—hÜ÷GW|P;‰íêç‡'D Ú÷Ý5Pþj ¯7ƒ«éð/=IËLžîNÞ“) èîNWÄoü¬'ƒñ§áä ÆƒÇþÄéñTFâ[>ôpx¤%ƒOЧÑv;üöDû9   ÑÿHÚaFç®>iqœÐîá'ü }Ñþ3©Ñƒ¾ï?Ë`ö³Sb3Lnwµ‚”¢ÕÎþådpIü ™-bÁ]÷ïû“D%à¥Ý0y¢'ƒ«!þAß“êÑY߉TÈŠ~{Â)ÒŽˆîÓqbkÐCwd°AèÚÈë­½k—§íÚ;ú½¸{˜@Ùh‘i_3Çô÷åO#’›SÿêêiL¦…'ðq3y"cŽøPöËÖ<_{{b9ë›þðîi¼§c´ò‰$Y×Âx%›œ%¬zxCK]ݺÓÓ«}Ö·t—z¬ýiÏ#ë(²…ÉÐÉäÁQprdÇÆ—Oiüü~Ìþã‘[“ês6*Ö)ÇúðwD`ÇE9 v‘qA5/7œjç(£ûmnJÏ˾ÿakE9ˆ”Éâ¤v.ãFÊ€bפWH1ôÈœ;Ç ¬VÝX 10\ØÁ`R§¸] Íb_>ô7â|I¶®S×rj¡QæõÈQÊ$N…lºÄÖÀqx{íæù>î1á×cAg0\•(23HáÕl]ÏŠÀ»u0­6æbvÅ…v¾ÛÏþ$ÀÂó…+[éMÉâð$o´‘¦ßnD\'!¹!È_ O~ßO DxG` *!=£Üc©)ä§2L”²ðTø¯L«{½úL"üJ+0 D}=¿Êºœ—Fˆ:ç}n7vNYÐo{9L&(ëÃ㞇n·“Ù¶ƒôÞq Ô^¤‹å~‘»¶ÆTN»SÒgûø¹wXq+Ö¥a+LõÔNÎt‘YÑq&2.B îpB>À_„®UÈåÝœ'ýH'mØÓ$Ü?¦'†õD… FG9>*¾Å‹<˺­£°ëu;HÑ™9NØGDmÌV–ÈgI׿ùýÝ[þÉ}Ÿ_)\JäA<#‚2šx`-k–@Ë£jUYІä> r|Y.uÏθFg<5ñîÑß*I!Ç*LôæÙq¦Š§é9vNV®Tt]É‚Œ§úXÂ~hïõû¯?%;æ kÖ]SÞ{{N©„»@Ú¿œ<Üô¸{Žaó«„Ó]oI¿ÿÅWWßÞõZ«ØumèáX`r¬¹îx¦à.R…â‘ÏÇ.âåæïbFz2·²Únåq“«ùöü1ám§¾þÚmçjI'‰‘\W³8º~p"Y™è_¹åùâ@Mbfoy)–¬¬O­¤¿ ‚…ù ÷JãŽóÏ~UséLaé‹t¾9•_{üjØz?7_úyê~á|¡¸xöt[þ©½ùúóë.® æêJLýU(ÍOU ¥_ç6Ì=×XìÛÔ}.v1:°5È-¼9Ùßp©f¬X¹š\|­p5yw[áã[©;©å+U§ 7n'‚ |úëï³Åä½l4n¶øCvúv]i ªutL&k›/ÿ–HVêûWJÝ]U=‡c‡ëN“O}Úòcyùdyyׇ×Ë£›&ïL.\žWÏ^ˆÅÇ߯yâü®âÝèò¹út:WÓ6Û•¨Ù7Ruo¦=šm0{8(Kõ¾¾»;|¨¶º;sth4<4|d8Ê…Cù·2¹ðhæà¡ôöµÕ»£z˜Éå†rQÒ•Ë ‡é·…G2ÇÂüPåùt._[ýïRÏÞø©ïËÅÿxLyÿx¼Ø—êÝÓ†½oô†?ÞÙÒ´¥)bQŒOFýž¾ÎÎGýσw§›¦£~<Љ‡}àÿcksWçÖðÑŸ¬2[[ì5[V€UíoPKBs„0žP-ºà 5-fat-daylight/index.htmlUX Lap@Lap@õ…VmoÛ6þÎ_Á¹’‰ìØËúE@Ö4C†6 ÖöÓ°´x²ˆÒ¤@ž¢º¿~w¤¬8 Öˆ"‘÷Æçžç˜²Å­­Ê”®J4h¡º¹ú$¯ÕΚM‹ò£z0nå'ˆXγA9Oæ¢\{½“ëMí­—³ ýÔõŒ6jp¡R–íòGiW$«Uum6••7>€‹¦&ïm²#y»UÇ/.NÈk•½”l4—³±{3Ÿë±ˆMágœûùr9WäYÎ÷õ N|ë0xÝ×h¼Ë±Ë®ŸZ%RriRfúR’Nr¾”õ]·×ƒ­ÄÁËÆXˆ…”:ZTQÔ‚–ÆIlÙŽSJåtúôôû½Øo·È7%ÝǵV¤ü­(52]ð5Ä1¹¡Ù¦ŒŒoT´ª)cÌ9xâ %¶ ɃÞy”‘Fó@1|2ýæ] uÛäÈœ ƒrÑrDÁkœ…MÙEMNg¡ržSà$„àC”µï­–ðÕD,#ßU©×~pÖ+ý?p5ÉNâ5gÜ:6òHë£é:í¾-Ôwa› ùáúBø|¢)j‰X½nÖ¯–ÍjõëùZ-Öõ…Z­ÍËúü¥Z¼ZÖk":VOÚ!è%€©£½ÓÔ;Žú=‡a(6®/|ØÌ­!–Q«¦—‚¥öâ÷û÷³JÒ“¹x*£ÊíHYÓAúH52R ¨Þ&YSMyŠùÅY£ðLr*¾™nVÑ#1»œ³íœý2µo˜“‡ C©è÷€° T퉜#ã ªnÓ^ZUÆ=’-qHd~ˑ߅¼ó˜w’]€ØÛ §žnÕNjÓ4›†œ&E jèÐJ VúØù^†>+‚½riûxBÙèåƒ ¤½ÔU±g!g#w–—²»Èi‰Á152eÙ*©=dØb#ë‡ÇR‘‘'¬JTkÂ`í5ûrv>#Ejlém±ø™gòô£™™Ç¶ÕÚ1§­øãí¨þkz¦E ̦“½®òD(ð+Vž¾ºúC¹žw~*—‹Å/òL.ß,÷’ÁóãÜx¡§s>º¯ž»ÏÇÂç逕˜N|¨ýqN >|!XFMsãi*Ik¾€ÝɘÓ’TDn/¸š0r#÷S1³,¨1S‰û™Z9‚Z$&¦qCA…áqÕcëCfóoÁ\Þª qê¸_¨½5ÐV,º>è ÐýÉž©±Hj$G±ÅS‡ê<DLòIóÄÏ}s–¯3¼Å(²kk«¨èp µ;0iÂß§:ägG2РÜIäÛwÝ^}”±ó.úuÂPÍ ¼b.-³˜»¡ÁmgÇšco2¶d;°¶3ä!¢àž K|Ï$OÓRS¬<«-›{:Ÿ´ë Ç×A †Ú ÑlÜ?Ut¯bä.áAet=ô$7Ž"Fó´ö=ŽwÕweµ‹‚‡›Ò:rÎ=uBsU°U&U´e¹HëC‹Š®Â58h þtrXS¦Fx¦ÖÅ«õ»$$J@‡½œYhpò¼àý§<û›/=×è:|Ƶtqü#²Þž„·Ž;ÓÈ|À ­;N‚H_Öbg®€vâÀ ½²x3Ø Gx™¸ˆK ‹u¡’o9 Wa¡ˆ.0 ÷ AóX×§7£ÒWr‰ÂŠÛ4u}Ä4Ïÿî~Éñuçµ»mS7BŽ’-Ãn$ëÙ|“UÅÍ’ ^)žðn]ï—ˆâ…gœWDÑÅl°^k ¹>ÜŽÞS™©xs–4E!XfŸ:Öp¬>SèWÜ'£Û@óPÌóPKKs„0 R0 °YF @¤5-fat-daylight/COPYING-GNU.txtUX]ap@]ap@PK0’=0ÉU 0€ @¤ü5-fat-daylight/daylight.ddUXÿåf@‹”@PKBs„0žP-ºà  @¤t#5-fat-daylight/index.htmlUXLap@Lap@PK ”=0¿xÈö£ @¤u(5-fat-daylight/readme.txtUXü`p@˜@PKR²)dff-1.3.0+dfsg.1/testsuite/enverrortest.py000066400000000000000000000072001217176075400205060ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe M. # import unittest, sys, os from dffunittest import DffUnittest from api.exceptions.libexceptions import * class EnvTests(DffUnittest): """ Validate environement variable module """ def __init__(self, name='runTest'): unittest.TestCase.__init__(self, name) def runTest(self): """ For debugging usage ; when methods are called directly """ pass testFile = "/etc/passwd" def test01_ValueError(self): """ #01 ValueError raise when loading a non-existent path """ badPath = '/non/existent' self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) self.ui.cmd('local --path ' + badPath) driverStdout, driverStderr = self._restore_streams() expectedStdout = 'Value error: local path < ' + badPath + ' > doesn\'t exist\n' self.assertFalse(driverStdout) self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertFalse(driverStderr) self.assertFalse(sys.stderr.getvalue()) def test02_GoodEnv(self): """ #02 Get three existing value from environement module """ self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) self.ui.cmd('local --path ' + self.testFile + ' --parent /') driverStdout, driverStderr = self._restore_streams() # Obtain environement object by processus name env = self._getEnvObjByProcName('local') # Validate type of the object returned by get_path self.assertEqual("", str(type(env.get_path('path')))) # Validate --path argument self.assertEqual(self.testFile, env.get_path('path').path) # Validate type of the object returned by get_node self.assertEqual("", str(type(env.get_node('parent')))) # Validate '/' is root of VFS self.assertTrue(env.get_node('parent').is_root) self.assertFalse(env.get_node('parent').is_file) self.assertFalse(driverStderr) self.assertFalse(sys.stderr.getvalue()) def test03_BadEnv(self): """ #03 Error getting a non-existent value from environement module """ # Obtain environement object by processus name # remember, load are persistant env = self._getEnvObjByProcName('local') for type, name, val in self.tm.env.get_val_map(env.val_m): print type, name, val env.thisown = 0 self.assertFalse(env.val_m.has_key('bad')) self.assertRaises(IndexError, lambda: env.val_m['bad']) self.assertRaises(IndexError, lambda: self.tm.env.vars_db['bad']) # FIXME unable to test env.get_bool('bad') because it segfault suite = unittest.TestSuite() suite.addTest(EnvTests('test01_ValueError')) suite.addTest(EnvTests('test02_GoodEnv')) suite.addTest(EnvTests('test03_BadEnv')) res = unittest.TextTestRunner(verbosity=2).run(suite) if (len(res.errors) or len(res.failures)): sys.exit(1) #testC = EnvTests() #testC.setUp() #testC.test01_GoodEnv() #testC.test02_BadEnv() dff-1.3.0+dfsg.1/testsuite/fattest.py000066400000000000000000000127051217176075400174240ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe M. # import unittest, sys, os from dffunittest import DffUnittest class FatTests(DffUnittest): """ Tests on fat filesystem VFS driver """ def __init__(self, name='runTest'): unittest.TestCase.__init__(self, name) # It has to be preprocessed by CMake to find path of test image testFile = '${CMAKE_SOURCE_DIR}/testsuite/dftt/5-fat-daylight.zip' vfsTestFilePath = '/5-fat-daylight.zip/5-fat-daylight/daylight.dd' expectedLoadOutput = '${CMAKE_SOURCE_DIR}/testsuite/results/fattest.5-fat-daylight.load.txt' expectedListOutput = '${CMAKE_SOURCE_DIR}/testsuite/results/fattest.5-fat-daylight.ls.txt' expectedListAccurateOutput = '${CMAKE_SOURCE_DIR}/testsuite/results/fattest.5-fat-daylight.ls_accurate.txt' def test01_LoadDumpFailure(self): """ #01 Load an non-existent FAT dump and validate error """ self.ui.cmd('local --path ' + self.testFile + ' --parent /') self.ui.cmd('unzip ' + os.path.basename(self.testFile)) if not self.debugTest: precOutput = sys.stdout.getvalue() # launch command self.ui.cmd('fatfs ' + self.vfsTestFilePath[:-1]) # This call must throw UserWarning because vfsTestFilePath minus # last character is non-existant # resultArrayString = self._getResultsArrayByProcName('fat') self.assertRaises(UserWarning, lambda: self._getResultsArrayByProcName('fatfs')) # No result ; VFS module path not found expectedOutput = 'Value error: node < ' + self.vfsTestFilePath[:-1] + ' > doesn\'t exist\n' if not self.debugTest: self.assertEqual(sys.stdout.getvalue()[len(precOutput):], expectedOutput) self.assertFalse(sys.stderr.getvalue()) def test02_LoadDump(self): """ #02 Load a FAT dump and validate filesystem metadata """ if not self.debugTest: precOutput = sys.stdout.getvalue() # avoid output from driver loading in current stdout/stderr self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) # launch command self.ui.cmd('fatfs ' + self.vfsTestFilePath) # get command line output driverStdout, driverStderr = self._restore_streams() # get framework result from taskmanager resultArrayString = self._getResultsArrayByProcName('Fat File System') # read expected output from text file expectedArrayString = self._readExpectedOutputAsArray(self.expectedLoadOutput) i = 0 for oneLine in resultArrayString: # compare lines one by one for accurate output in case of failure self.assertEqual(expectedArrayString[i], oneLine) i += 1 # validate console output # strangely modules loading appears here, so [-len(expectedOut):] on output if not self.debugTest: self.assertFalse(driverStdout) self.assertFalse(driverStderr) self.assertFalse(sys.stderr.getvalue()) def test03_RecurseListing(self): """ #03 Recurse list content of the FAT dump """ if not self.debugTest: precOutput = sys.stdout.getvalue() # launch command self.ui.cmd('ls --recursive') consoleArrayString = self._getOutputArray(sys.stdout.getvalue()[len(precOutput):]) expectedArrayString = self._readExpectedOutputAsArray(self.expectedListOutput) i = 0 for oneLine in consoleArrayString: # compare lines one by one for accurate output in case of failure self.assertEqual(expectedArrayString[i], oneLine) i += 1 self.assertFalse(sys.stderr.getvalue()) def test04_RecurseAccurateListing(self): """ #04 Recurse list content of the FAT dump with fullpath and size of entry """ precOutput = sys.stdout.getvalue() # avoid output from driver loading in current stdout/stderr self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) # launch command self.ui.cmd('ls --recursive --long') self._restore_streams() consoleArrayString = self._getOutputArray(sys.stdout.getvalue()[len(precOutput):]) expectedArrayString = self._readExpectedOutputAsArray(self.expectedListAccurateOutput) i = 0 for oneLine in consoleArrayString: # compare lines one by one for accurate output in case of failure self.assertEqual(expectedArrayString[i], oneLine) i += 1 self.assertFalse(sys.stderr.getvalue()) suite = unittest.TestSuite() suite.addTest(FatTests('test01_LoadDumpFailure')) suite.addTest(FatTests('test02_LoadDump')) suite.addTest(FatTests('test03_RecurseListing')) suite.addTest(FatTests('test04_RecurseAccurateListing')) res = unittest.TextTestRunner(verbosity=2).run(suite) if (len(res.errors) or len(res.failures)): sys.exit(1) dff-1.3.0+dfsg.1/testsuite/hashtest.py000066400000000000000000000137151217176075400175770ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe M. # import unittest, sys, os, hashlib from dffunittest import DffUnittest class HashTests(DffUnittest): """ Tests on 'hash' module We load a file present on every computer, and validate hashing functionality. Algorithm checked : - md5 - sha1 - sha224 - sha256 - sha384 - sha512 TODO - test on a huge file """ # FIXME what about windows ? testFile = '/etc/passwd' def __init__(self, name='runTest'): unittest.TestCase.__init__(self, name) self.outBuff = '' def setUp(self): DffUnittest.setUp(self) # avoid output from driver loading in current stdout/stderr self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) # launch command self.ui.cmd('local --path ' + self.testFile + ' --parent /') # get output self._restore_streams() def _hashLocalFile(self, hash, file): if hash == "md5": m = hashlib.md5() elif hash == "sha1": m = hashlib.sha1() elif hash == "sha224": m = hashlib.sha224() elif hash == "sha256": m = hashlib.sha256() elif hash == "sha384": m = hashlib.sha384() elif hash == "sha512": m = hashlib.sha512() else: return with open(file, 'r') as f: buff = f.read(512) while len(buff) > 0: m.update(buff) buff = f.read(512) return m.hexdigest() def test01_HashMD5(self): """ #01 MD5 hash of a file present on every Unix """ self.outBuff += sys.stdout.getvalue() # launch command self.ui.cmd('hash --file /' + os.path.basename(self.testFile) + ' --algorithm md5') expectedStdout = self.outBuff + 'result:\n' + self._hashLocalFile('md5', self.testFile) + ' /' + os.path.basename(self.testFile) + '\n' # validate output from framework self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertEqual(sys.stderr.getvalue(), '') def test02_HashSHA1(self): """ #02 SHA1 hash of a file present on every Unix """ self.outBuff += sys.stdout.getvalue() # launch command self.ui.cmd('hash --file /' + os.path.basename(self.testFile) + ' --algorithm sha1') expectedStdout = self.outBuff + 'result:\n' + self._hashLocalFile('sha1', self.testFile) + ' /' + os.path.basename(self.testFile) + '\n' # validate output from framework self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertEqual(sys.stderr.getvalue(), '') def test03_HashSHA224(self): """ #03 SHA224 hash of a file present on every Unix """ self.outBuff += sys.stdout.getvalue() # launch command self.ui.cmd('hash --file /' + os.path.basename(self.testFile) + ' --algorithm sha224') expectedStdout = self.outBuff + 'result:\n' + self._hashLocalFile('sha224', self.testFile) + ' /' + os.path.basename(self.testFile) + '\n' # validate output from framework self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertEqual(sys.stderr.getvalue(), '') def test04_HashSHA256(self): """ #04 SHA256 hash of a file present on every Unix """ self.outBuff += sys.stdout.getvalue() # launch command self.ui.cmd('hash --file /' + os.path.basename(self.testFile) + ' --algorithm sha256') expectedStdout = self.outBuff + 'result:\n' + self._hashLocalFile('sha256', self.testFile) + ' /' + os.path.basename(self.testFile) + '\n' # validate output from framework self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertEqual(sys.stderr.getvalue(), '') def test05_HashSHA384(self): """ #05 SHA384 hash of a file present on every Unix """ self.outBuff += sys.stdout.getvalue() # launch command self.ui.cmd('hash --file /' + os.path.basename(self.testFile) + ' --algorithm sha384') expectedStdout = self.outBuff + 'result:\n' + self._hashLocalFile('sha384', self.testFile) + ' /' + os.path.basename(self.testFile) + '\n' # validate output from framework self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertEqual(sys.stderr.getvalue(), '') def test06_HashSHA512(self): """ #06 SHA512 hash of a file present on every Unix """ self.outBuff += sys.stdout.getvalue() # launch command self.ui.cmd('hash --file /' + os.path.basename(self.testFile) + ' --algorithm sha512') expectedStdout = self.outBuff + 'result:\n' + self._hashLocalFile('sha512', self.testFile) + ' /' + os.path.basename(self.testFile) + '\n' # validate output from framework self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertEqual(sys.stderr.getvalue(), '') suite = unittest.TestSuite() suite.addTest(HashTests('test01_HashMD5')) suite.addTest(HashTests('test02_HashSHA1')) suite.addTest(HashTests('test03_HashSHA224')) suite.addTest(HashTests('test04_HashSHA256')) suite.addTest(HashTests('test05_HashSHA384')) suite.addTest(HashTests('test06_HashSHA512')) res = unittest.TextTestRunner(verbosity=2).run(suite) if (len(res.errors) or len(res.failures)): sys.exit(1) dff-1.3.0+dfsg.1/testsuite/libtypestest.py000077500000000000000000000320241217176075400205040ustar00rootroot00000000000000#!/usr/bin/python -i # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin import api import traceback import sys, os if os.name == "posix": try : import dl sys.setdlopenflags(sys.getdlopenflags() | dl.RTLD_GLOBAL) except ImportError: import ctypes sys.setdlopenflags(sys.getdlopenflags() | ctypes.RTLD_GLOBAL) from api.types.libtypes import * from api.vfs.libvfs import VFS from modules.connector.local import LOCAL from modules.builtins.ls import LS v = VFS.Get() ## STRING_OptionalSingleInputWithFixedParam = Argument("string", OptionalSingleInputWithFixedParam|typeId.String, ## "an optional string argument with fixed parameters and single input") ## STRING_OptionalSingleInputWithCustomizableParam = Argument("string", OptionalSingleInputWithCustomizableParam|typeId.String, ## "an optional string argument with customizable parameters and single input") ## STRING_RequiredSingleInputWithFixedParam = Argument("string", RequiredSingleInputWithFixedParam|typeId.String, ## "a required string argument with fixed parameters and single input") ## STRING_RequiredSingleInputWithCustomizableParam = Argument("string", RequiredSingleInputWithCustomizableParam|typeId.String, ## "a required string argument with customizable parameters and single input") ## STRING_OptionalListInputWithFixedParam = Argument("string", OptionalListInputWithFixedParam|typeId.String, ## "an optional string argument with fixed parameters and list input") ## STRING_OptionalListInputWithCustomizableParam = Argument("string", OptionalListInputWithCustomizableParam|typeId.String, ## "an optional string argument with customizable parameters and list input") ## STRING_RequiredListInputWithFixedParam = Argument("string", RequiredListInputWithFixedParam|typeId.String, ## "a required string argument with fixed parameters and list input") ## STRING_RequiredListInputWithCustomizableParam = Argument("string", RequiredListInputWithCustomizableParam|typeId.String, ## "an optional string argument with customizable parameters and list input") ## STRING_OptionalSingleInputWithFixedParam.setEnabled(True) ## print "flags:", hex(STRING_OptionalSingleInputWithFixedParam.flags()) ## print "type:", hex(STRING_OptionalSingleInputWithFixedParam.type()) ## print "inputype:", hex(STRING_OptionalSingleInputWithFixedParam.inputType()) ## print "paramstype:", hex(STRING_OptionalSingleInputWithFixedParam.parametersType()) ## print "neededtype:", hex(STRING_OptionalSingleInputWithFixedParam.requirementType()) ## print "=== TESTING SETTING METHOD ===" ## print " Optional --> Required" ## print " SingleInput --> ListInput" ## print " FixedParams --> CustomizableParams" ## print " String --> UInt64" ## STRING_OptionalSingleInputWithFixedParam.setType(typeId.UInt64) ## STRING_OptionalSingleInputWithFixedParam.setInputType(ListInput) ## STRING_OptionalSingleInputWithFixedParam.setParametersType(CustomizableParam) ## STRING_OptionalSingleInputWithFixedParam.setRequirementType(Required) ## print "flags:", hex(STRING_OptionalSingleInputWithFixedParam.flags()) ## print "type:", hex(STRING_OptionalSingleInputWithFixedParam.type()) ## print "inputype:", hex(STRING_OptionalSingleInputWithFixedParam.inputType()) ## print "paramstype:", hex(STRING_OptionalSingleInputWithFixedParam.parametersType()) ## print "neededtype:", hex(STRING_OptionalSingleInputWithFixedParam.requirementType()) ## print type(STRING_OptionalSingleInputWithFixedParam) No = 0 Enabled = True Disabled = False conf = [{"name": "arg1", "input": Argument.Optional|Argument.Single|typeId.Node, "description": "optional and unique argument of type Node with parameter either provided by user or based on default", "parameters": {"type": Parameter.Customizable, "predefined": ["/", "/logical evidences"], #"default": "/"#predefined parameters are provided when user configure input }, "runtime": {"status": Disabled, "parameters": "/" } }, {"name": "arg2", "input": Argument.Optional|Argument.Single|typeId.Int32, "description": "optional argument of type Int32 with fixed parameter selected by user", # !!! When parameter is fixed, "predefined" field MUST be filled !!! "parameters": {"type": Parameter.Fixed, "predefined": [512, 1024, 2048, 4096], #fixed predefined parameters, modules is not able to manage other type }, "runtime": {"status": Enabled, "parameters": 512 } }, {"name": "arg3", "input": Argument.Optional|Argument.List|typeId.String, "description": "optional list of argument of type String with fixed parameters selected by user", # !!! When parameters are fixed, they MUST be setted in "predefined" field !!! "parameters": {"type": Parameter.Fixed, "predefined": ["md5", "sha1", "sha256", "sha512"] #fixed predefined parameters, modules is not able to manage other type }, "runtime": {"status": Enabled, "parameters": ["md5", "sha512"] } #md5 and sha512 parameters used by default (if not filled by user or if preconfigured for automation) }, {"name": "arg4" "input": Argument.Optional|Argument.List|typeId.String, "description": "optional list of argument of type String with parameters either provided by user or based on default", "parameters": {"type": Parameter.Customizable, "predefined": ["md5", "sha1", "sha256", "sha512"] #fixed predefined parameters, modules is not able to manage other type }, #default is used for run time execution. parameters defined here will be used as default when not specified or when configured #for automation "runtime": {"status": Enabled, "parameters": ["md5", "sha512"] #md5 and sha512 parameters used by default (if not filled by user or if preconfigured for automation) } }, {"name": "arg5", "input": Argument.Required|Argument.Single|typeId.Int64, "description": "required argument of type Int64 with fixed parameter selected by user", "parameters": {"type": Parameter.Fixed, "predefined": [2**60, -(2**60)], #fixed predefined parameters, modules is not able to manage other type }, # !!! When parameter is fixed, "predefined" field MUST be filled !!! "runtime": {"parameters": 2**60} }, {"name": "arg6", "input": Argument.Required|Argument.List|typeId.Path, "description:": "required list of argument of types Path with parameters provided by user" #no predefined parameters, no default }, {"name": "arg7", "input": Argument.Empty, "description": "optional argument with no parameter enabled by default", "runtime": {"status": Enabled} }, {"name": "arg8", "input": No, "description": "optional argument with no parameter disabled by default", "runtime": {"status": Disabled} }, {"name": "arg9", "input": Argument.Required|Argument.List|typeId.String, "description": "required ", "parameters": {"type": Parameter.Fixed, "predefined": ["md5", "sha1", "sha256", "sha512"], }, "runtime": {"parameters": ["md5", "sha512"]} } ] pyListToVariant(["test", "for", "string", "weird behaviour if no =..."], 1) res = pyListToVariant(["test", "for", "string", "weird behaviour if no =..."], 1) print type(res) lres = res.value() for x in lres: print x cstr = pyObjectToVariant("test", typeId.String) print cstr cint = pyObjectToVariant(10000000, typeId.UInt16) print cint l = LOCAL.local() vm = VMap() vm.thisown = False n = v.GetNode("/") print n.name() vn = Variant(n) vn.thisown = False vm["parent"] = vn vl = VList() vl.thisown = False #print "GENERATING Variant(Path) for" for node in os.listdir("/home/udgover"): path = Path("/home/udgover/" + node) #print " ", path.path path.thisown = False vp = Variant(path) vp.thisown = False vl.append(vp) vvl = Variant(vl) vvl.thisown = False vm["path"] = vvl try: l.start(**vm) except TypeError: l.start(vm) vm = VMap() vm.thisown = False n = v.GetNode("/") vn = Variant(n) vn.thisown = False vm["node"] = vn vb = Variant(True) vb.thisown = True vm["long"] = vb vm["recursive"] = vb ls = LS() ls.start(**vm) import time, traceback vlist = VList() vlist2 = VList() pylist = [] pylist2 = [] vmap = VMap() vmap2 = VMap() pymap = {} pymap2 = {} nbitem = 10 print "=" * 50 print "Creating vlist, vvlist, pylist, pylist2, vmap, vvmap, pymap and pymap2 with", nbitem, "items :" t = time.time() for i in xrange(0, nbitem): vlist.append(i) vlist2.append(i) pylist.append(i) pylist2.append(i) vmap[str(i)] = i vmap2[str(i)] = i pymap[str(i)] = i pymap2[str(i)] = i pylist2[nbitem - 1] = 0 vlist2[nbitem-1] = nbitem pymap2[str(nbitem - 1)] = 0 vmap2[str(nbitem-1)] = nbitem vvlist = Variant(vlist) vvlist2 = Variant(vlist2) vvmap = Variant(vmap) vvmap2 = Variant(vmap2) vstr1 = Variant("str1") vstr2 = Variant("str2") vmaplist = VMap() vmaplist2 = VMap() vmaplist["LIST"] = vvlist vmaplist["str"] = vstr1 vmaplist2["LIST"] = vvlist2 vmaplist2["str"] = vstr2 vvmaplist = Variant(vmaplist) vvmaplist2 = Variant(vmaplist2) vlistmap = VList() vlistmap2 = VList() vlistmap.append(vmap) vlistmap2.append(vmap2) vvlistmap = Variant(vlistmap) vvlistmap2 = Variant(vlistmap2) extime = time.time() - t print "exec time:", extime print ("=" * 50) + "\n" tests = [ "vstr1 op vstr1", "vstr2 op vstr1", "vstr1 op 'str1'", "vstr1 op ''", "vstr1 op 'different'", "vlist op vlist", "vlist op vlist2", "vlist op pylist", "vlist op pylist2", "vvlist op vvlist", "vvlist op vvlist2", "vvlist op vlist", "vvlist op vlist2", "vvlist op pylist", "vvlist op pylist2", "nbitem - 1 in vlist", "Variant(nbitem - 1) in vlist", "nbitem in vlist", "Variant(nbitem) in vlist", "vmap op vmap", "vmap op vmap2", "vmap op pymap", "vmap op pymap2", "vvmap op vvmap", "vvmap op vvmap2", "vvmap op vmap", "vvmap op vmap2", "vvmap op pymap", "vvmap op pymap2", "vlistmap op vlistmap", "vlistmap op vlistmap2", "vvlistmap op vvlistmap", "vvlistmap op vvlistmap2", "vmaplist op vmaplist", "vmaplist op vmaplist2", "vvmaplist op vvmaplist", "vvmaplist op vvmaplist2"] print "=" * 50 print "Starting tests:" print tests print ("=" * 50) + "\n" def evalexpr(first, second, operator): print "=" * 50 real_test = first + operator + second print "Current test --->", real_test print eval(first) print "\n", 25*" ", operator, "\n" print eval(second), "\n" try: t = time.time() res = eval(real_test) extime = time.time() - t print "\n< " + real_test + " > terminated" print "result:" + (" " * 3), res print "exec time:", extime print ("=" * 50) + "\n" except: print "error with test", test traceback.print_exc(file=sys.stdout) for test in tests: idx = test.find("op") if idx != -1: first = test[:idx] second = test[idx+2:] for operator in ["==", "!=", ">", "<", ">=", "<="]: evalexpr(first, second, operator) else: idx = test.find("in") operator = "in" first = test[:idx] second = test[idx+2:] print "==", Variant(123456) == Variant(123456), 123456 == 123456 print "!=", Variant(123456) != Variant(123456), 123456 != 123456 print ">", Variant(123456) > Variant(123456), 123456 > 123456 print "<", Variant(123456) < Variant(123456), 123456 < 123456 print ">=", Variant(123456) >= Variant(123456), 123456 >= 123456 print "<=", Variant(123456) <= Variant(123456), 123456 <= 123456 dff-1.3.0+dfsg.1/testsuite/local.py000066400000000000000000000151651217176075400170470ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe M. # import unittest, sys, os, random from dffunittest import DffUnittest class LocalTests(DffUnittest): """ Tests on 'local' VFS driver We load several things, and validate basic functionality of the framework. Keep in mind that VFS loads are persistant from one test to another. TODO - seek - negative seek - open & close many files - load same file two times, open both, seek one, check both position are OK """ def __init__(self, name='runTest'): unittest.TestCase.__init__(self, name) # FIXME what about windows ? testFile = '/etc/passwd' def test01_LoadOneFile(self): """ #01 Load a file present on every Unix """ # launch command self.ui.cmd('local --path ' + self.testFile + ' --parent /') # validate output from framework self.assertFalse(sys.stdout.getvalue()) self.assertFalse(sys.stderr.getvalue()) def test02_LsOneFile(self): """ #02 ls previously loaded file and validate size Check if --long (switch for size output) is right size of the file """ self.ui.cmd('ls --long /') fileSize = str(os.stat(self.testFile).st_size) expectedStdout = '/' + os.path.basename(self.testFile) + '\t' + fileSize + '\n' self.assertEqual(sys.stdout.getvalue(), expectedStdout) self.assertFalse(sys.stderr.getvalue()) def _itemsCount(self, path, onlyFiles = False): """ Return number of file in a given directory In case 'onlyFiles' is set, return only files count. """ itemsCount = 0 for root, dirs, files in os.walk(path): if onlyFiles: itemsCount += len(files) else: itemsCount += len(dirs) + len(files) return itemsCount def test03_LoadOneDirectory(self): """ #03 Load current working directory and validate number of files loaded Make sure number of nodes loaded is the same number as number of file stored in current working directory. """ testDirectory = os.getcwd() self.ui.cmd('local --path ' + testDirectory + ' --parent /') # Expected output after local execution # TODO Amount of loaded items is now in 'info -> local' # expectedItems = str(self._itemsCount(os.getcwd())) # expectedStdout = 'nodes created:\n' + expectedItems + '\nresult:\nno problem\n' # self.assertEqual(sys.stdout.getvalue(), expectedStdout) # In case of assertion failure above, hidden files exist in directory # loaded by this test # validate output from framework self.assertFalse(sys.stdout.getvalue()) self.assertFalse(sys.stderr.getvalue()) def test04_ReadFile(self): """ #04 Read 128 byte in previously loaded file Make sure content is equal on disk and in vfs """ readAmount = 128 with open(self.testFile, 'r') as f: expectedContent = f.read(128) checknode = self.vfs.getnode('/passwd') nodeFile = checknode.open() buff = nodeFile.read(128) self.assertEqual(expectedContent, buff) def _randomItem(self, path): """ Return a random filepath in a given directory """ itemsCount = self._itemsCount(path, True) randomItemPosition = 0 while randomItemPosition == 0 or randomItemPosition > itemsCount: randomItemPosition = int(random.random() * itemsCount) i = 0 for root, dirs, files in os.walk(path): j = 0 for j in range(len(files)): i += 1 if i == randomItemPosition: return root + '/' + files[j] def test05_RandomReadFile(self): """ #05 Randomly check 100 file content Read 'randomReadSize' from beginning of file and make sure same content is obtained from disk and from VFS. This test reads directly through the VFS object. """ checkAmount = 100 while checkAmount: # Obtain a random filepath from given directory randomFilepath = self._randomItem(os.getcwd()) # Compute a random size to read randomReadSize = int(random.random() * os.stat(randomFilepath).st_size) # Open reference file with open(randomFilepath, 'r') as f: # Save reference data expectedContent = f.read(randomReadSize) # Set node path according to VFS format vfsNodePath = '/' + randomFilepath[len(os.getcwd()) - len(os.path.basename(os.getcwd())):] # Open node file nodeFile = self.vfs.getnode(vfsNodePath).open() # Save rode date from VFS buff = nodeFile.read(randomReadSize) # Close node file nodeFile.close() # Compare both data self.assertEqual(expectedContent, buff) # Reference file is automatically close ; 'with' statement checkAmount -= 1 def test07_LargeSeek(self): """ #07 Large boundary seek Seek to limit of addressable offset, read and validate. First we create a huge file. Max : int32 2147483647 1.99 GB uint32 4294967295 3.99 GB ulonglong 18446744073709551615 16777215.99 TB """ def runTest(self): pass suite = unittest.TestSuite() suite.addTest(LocalTests('test01_LoadOneFile')) suite.addTest(LocalTests('test02_LsOneFile')) suite.addTest(LocalTests('test03_LoadOneDirectory')) suite.addTest(LocalTests('test04_ReadFile')) suite.addTest(LocalTests('test05_RandomReadFile')) res = unittest.TextTestRunner(verbosity=2).run(suite) if (len(res.errors) or len(res.failures)): sys.exit(1) #print "call -> LocalTests()" #testC = LocalTests() #print "call -> setUp()" #testC.setUp() #print "call -> test01_LoadOneFile()" #testC.test01_LoadOneFile() #print "call -> tearDown()" #testC.tearDown() dff-1.3.0+dfsg.1/testsuite/mfso/000077500000000000000000000000001217176075400163375ustar00rootroot00000000000000dff-1.3.0+dfsg.1/testsuite/mfso/createdump.py000077500000000000000000000026111217176075400210450ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic Baguelin # from string import ascii_letters import sys alphabet_mapping = [0, 26, 1, 25, 2, 24, 3, 23, 4, 22, 5, 21, 6, 20, 7, 19, 8, 18, 9, 17, 10, 16, 11, 15, 12, 14, 13] def hard_mapping(): file = open("hard_mapping.txt", "wb") for loop in xrange(0, 5): for letter in alphabet_mapping: pass def simple_mapping(): file = open("simple_mapping.txt", "wb") for loop in xrange(0, 10): for letter in ascii_letters: file.write(letter * 2) file.close() if __name__ == "__main__": if len(sys.argv) == 2: if sys.argv[1] == "simple": simple_mapping() elif sys.argv[1] == "hard": hard_mapping() else: print "usage:", sys.argv[0], "[simple|hard]" else: print "usage:", sys.argv[0], "[simple|hard]" dff-1.3.0+dfsg.1/testsuite/mfso/mfso_contiguous.py000066400000000000000000000044201217176075400221340ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. from api.vfs import * #from api.module.script import* from api.module.module import Module #from api.env import * from api.env.libenv import * from api.variant.libvariant import Variant #from api.type.libtype import * #from api.module import * from api.vfs.libvfs import * #from api.exceptions.libexceptions import * from string import ascii_letters class MfsoContiguousNode(Node): def __init__(self, letter, mfso, origin): Node.__init__(self, letter, 1040, origin, mfso) self.thisown = False self.origin = origin self.size = 1040 setattr(self, "attributes", self.attributes) setattr(self, "fileMapping", self.fileMapping) def fileMapping(self): fm = FileMapping() fm.thisown = False i = 0 voffset = 0 while i != self.size: fm.push(voffset, 2, self.origin, i) voffset += 2 i += 2 return fm def attributes(self): #print "Python node attributes requested" attr = Attributes() attr.thisown = False sizeattr = Variant(self.size) sizeattr.thisown = False attr.push("size", sizeattr) return attr class MfsoContiguous(mfso): def __init__(self): mfso.__init__(self, "mfso_contiguous") self.name = "nothing" def map(self): i = 0 MfsoContiguousNode("contiguous_chunck", self, self.parent) def start(self, args): self.parent = args.get_node("parent") #self.file = self.parent.open() self.map() class mfso_contiguous(Module): def __init__(self): Module.__init__(self, 'mfso_contiguous', MfsoContiguous) self.conf.add("parent", "node") self.tags = "file system" dff-1.3.0+dfsg.1/testsuite/mfso/mfsotest.py000066400000000000000000000045421217176075400205620ustar00rootroot00000000000000# DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Frederic B. from api.vfs import * #from api.module.script import* from api.module.module import Module #from api.env import * from api.env.libenv import * from api.variant.libvariant import Variant #from api.type.libtype import * #from api.module import * from api.vfs.libvfs import * #from api.exceptions.libexceptions import * from string import ascii_letters class MfsoTestNode(Node): def __init__(self, letter, mfso, origin, start): Node.__init__(self, letter, 10, origin, mfso) self.thisown = False self.origin = origin self.start = start self.size = 10 setattr(self, "attributes", self.attributes) setattr(self, "fileMapping", self.fileMapping) def fileMapping(self): fm = FileMapping() fm.thisown = False voffset = 0 for i in xrange(0, 5): fm.push(voffset, 2, self.origin, self.start + i * 52 * 2) voffset += 2 return fm def attributes(self): #print "Python node attributes requested" attr = Attributes() attr.thisown = False sizeattr = Variant(self.size) sizeattr.thisown = False attr.push("size", sizeattr) return attr class MfsoTest(mfso): def __init__(self): mfso.__init__(self, "mfsotest") print dir() self.name = "nothing" self.res = results(self.name) def map(self): i = 0 for letter in ascii_letters: MfsoTestNode(letter, self, self.parent, i) i+=2 def start(self, args): self.parent = args.get_node("parent") #self.file = self.parent.open() self.map() class mfsotest(Module): def __init__(self): Module.__init__(self, 'mfsotest', MfsoTest) self.conf.add("parent", "node") self.tags = "file system" dff-1.3.0+dfsg.1/testsuite/results/000077500000000000000000000000001217176075400170745ustar00rootroot00000000000000dff-1.3.0+dfsg.1/testsuite/results/fattest.5-fat-daylight.load.txt000066400000000000000000000002011217176075400247340ustar00rootroot00000000000000cluster size: 1 number of entries in root directory: 224 number of fat: 2 oemname: MSDOS5.0 reserved cluster: 1 sector size: 512 dff-1.3.0+dfsg.1/testsuite/results/fattest.5-fat-daylight.ls.txt000066400000000000000000000001761217176075400244460ustar00rootroot000000000000005-fat-daylight.zip/ 5-fat-daylight/ COPYING-GNU.txt daylight.dd/ index.html readme.txt Fat File System/ winter.txt summer.txt dff-1.3.0+dfsg.1/testsuite/results/fattest.5-fat-daylight.ls_accurate.txt000066400000000000000000000007401217176075400263120ustar00rootroot00000000000000/5-fat-daylight.zip /5-fat-daylight.zip/5-fat-daylight /5-fat-daylight.zip/5-fat-daylight/COPYING-GNU.txt/ 18009 /5-fat-daylight.zip/5-fat-daylight/daylight.dd /5-fat-daylight.zip/5-fat-daylight/index.html/ 2499 /5-fat-daylight.zip/5-fat-daylight/readme.txt/ 419 /5-fat-daylight.zip/5-fat-daylight/daylight.dd/Fat File System /5-fat-daylight.zip/5-fat-daylight/daylight.dd/Fat File System/winter.txt/ 8 /5-fat-daylight.zip/5-fat-daylight/daylight.dd/Fat File System/summer.txt/ 8 dff-1.3.0+dfsg.1/testsuite/vfserrortest.py000066400000000000000000000076771217176075400205360ustar00rootroot00000000000000#!/usr/bin/python # DFF -- An Open Source Digital Forensics Framework # Copyright (C) 2009-2013 ArxSys # This program is free software, distributed under the terms of # the GNU General Public License Version 2. See the LICENSE file # at the top of the source tree. # # See http://www.digital-forensic.org for more information about this # project. Please do not directly contact any of the maintainers of # DFF for assistance; the project provides a web site, mailing lists # and IRC channels for your use. # # Author(s): # Christophe M. # import unittest, sys, os from dffunittest import DffUnittest from api.exceptions.libexceptions import * class VfsTests(DffUnittest): """ Validate environement variable module """ def __init__(self, name='runTest'): unittest.TestCase.__init__(self, name) # def runTest(self): # """ For debugging usage ; when methods are called directly # """ # pass testFile = "/etc/passwd" nonExistentFilePath = "/chifoumi/pouf/pif/paf" def test01_BadLocalOpen(self): """ #01 Output error when loading non existent filepath """ self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) self.ui.cmd('local --path ' + self.nonExistentFilePath + ' --parent /') driverStdout, driverStderr = self._restore_streams() self.assertEqual(sys.stdout.getvalue(), 'Value error: local path < ' + self.nonExistentFilePath + " > doesn't exist\n") self.assertFalse(driverStdout) self.assertFalse(driverStderr) self.assertFalse(sys.stderr.getvalue()) def test02_BadReadDirectory(self): """ #02 Raise error when reading a directory for data """ self._hook_streams(sys.__stdout__.fileno(), sys.__stderr__.fileno()) self.ui.cmd('local --path ' + self.testFile + ' --parent /') driverStdout, driverStderr = self._restore_streams() node = self.vfs.getnode('/') self.assertRaises(vfsError, lambda: node.open()) try: node.open() except vfsError, e: self.assertEqual("Node::open(void) throw\nCan't Open file", e.error) self.assertFalse(driverStderr) self.assertFalse(sys.stderr.getvalue()) def test03_BadSeek0File(self): """ #03 Validate error raising : negative seek from 0 """ node = self.vfs.getnode(os.path.basename(self.testFile)) f = node.open() self.assertRaises(OverflowError, lambda: f.seek(-1)) try: f.seek(-1) except OverflowError, e: self.assertEqual("in method 'VFile_seek', argument 2 of type 'dff_ui64'", e.message) def test04_BadSeekNFile(self): """ #04 Validate error raising : negative seek from +N """ node = self.vfs.getnode(os.path.basename(self.testFile)) f = node.open() f.seek(os.stat(self.testFile).st_size / 2) self.assertRaises(OverflowError, lambda: f.seek(-1)) try: f.seek(-1) except OverflowError, e: self.assertEqual("in method 'VFile_seek', argument 2 of type 'dff_ui64'", e.message) def test05_BadSeekMaxFile(self): """ #05 Validate empty read starting at filesize """ node = self.vfs.getnode(os.path.basename(self.testFile)) f = node.open() f.seek(os.stat(self.testFile).st_size) self.assertFalse('', f.read(512)) suite = unittest.TestSuite() suite.addTest(VfsTests('test01_BadLocalOpen')) suite.addTest(VfsTests('test02_BadReadDirectory')) suite.addTest(VfsTests('test03_BadSeek0File')) suite.addTest(VfsTests('test04_BadSeekNFile')) suite.addTest(VfsTests('test05_BadSeekMaxFile')) res = unittest.TextTestRunner(verbosity=2).run(suite) if (len(res.errors) or len(res.failures)): sys.exit(1) #testC = EnvTests() #testC.setUp() #testC.test01_GoodEnv() #testC.test02_BadEnv()