yubikey-personalization-gui-3.1.24/0000775000175000017500000000000012642452213015734 5ustar klasklasyubikey-personalization-gui-3.1.24/ChangeLog0000664000175000017500000024345112642452214017520 0ustar klasklas2016-01-04 Klas Lindfors * NEWS: NEWS for 3.1.24 2016-01-04 Klas Lindfors * src/version.h: update copyright years 2015-12-30 Klas Lindfors * src/src.pro: name mac installer correctly 2015-12-30 Klas Lindfors * src/ui/mainwindow.cpp: don't show a key if version is 0 2015-12-28 Klas Lindfors * src/src.pro: fixup sed invocation 2015-12-28 Klas Lindfors * installer/win-nsis/ykpers.nsi, src/src.pro: newer qt has qtaccessiblewidgets included and new names on some dlls on mac libqtcocoa also depends on QtDBus 2015-12-29 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: drop devel key 2015-12-28 Klas Lindfors * : new images for 2.3, neo, plus and edge 2015-12-28 Klas Lindfors * resources/lin/yubikey-personalization-gui.xpm: new application icons 2015-12-21 Klas Lindfors * tests/yubikeyutiltest.cpp, tests/yubikeyutiltest.h: add tests for getNextHex()/getNextModhex() with random output 2015-12-21 Klas Lindfors * lib/yubikeyutil.cpp: getNextModhex() has to call qstrModhexClean() 2015-12-21 Klas Lindfors * tests/yubikeyutiltest.cpp, tests/yubikeyutiltest.h: add tests that show that getNextModhex() is broken 2015-10-09 Klas Lindfors * src/src.pro: for osx always set ICON, for pkgconfig set QMAKE_INFO_PLIST 2015-10-09 Klas Lindfors * resources/mac/Info.plist.in, src/src.pro: use @SHORT_VERSION@ and @FULL_VERSION@ for Info.plist 2015-10-09 Klas Lindfors * prepare-travis.sh, src/src.pro: if we're using pkgconfig it makes sense to enable it always 2015-10-08 Klas Lindfors * .travis.yml, prepare-travis.sh: add travis build for osx 2015-10-01 Klas Lindfors * NEWS, src/src.pro: bump versions 2015-10-01 Klas Lindfors * NEWS: NEWS for 3.1.23 2015-09-30 Klas Lindfors * tests/scanedittest.cpp: simplify test by not using new/delete 2015-09-30 Klas Lindfors * src/ui/staticpage.cpp: make sure scanedit is initialized fixes #56 2015-09-25 Klas Lindfors * NEWS, src/src.pro: bump versions 2015-09-25 Klas Lindfors * NEWS: NEWS for 3.1.22 2015-09-23 Klas Lindfors * .gitignore: ignore 2015-09-22 Klas Lindfors * : fixup neo picture 2015-09-22 Klas Lindfors * lib/scanedit.cpp: remove debugging for every encode case and add debug for failure 2015-09-22 Klas Lindfors * lib/de-scanedit.cpp: add <> for german layout 2015-09-22 Klas Lindfors * .gitignore, lib/common.h, lib/de-scanedit.cpp, lib/de-scanedit.h, lib/lib.pro, lib/scanedit.cpp, src/ui/staticpage.cpp, src/ui/staticpage.ui: add german layout to scancode passwords 2015-09-22 Klas Lindfors * lib/common.h, src/ui/staticpage.cpp: modularize scanedit so it's instantiated when selected 2015-09-22 Klas Lindfors * .gitignore, lib/lib.pro, lib/scanedit.cpp, lib/scanedit.h, lib/us-scanedit.cpp, lib/us-scanedit.h, src/ui/staticpage.cpp, tests/scanedittest.cpp: add inheritance for scanedit parts 2015-09-22 Klas Lindfors * lib/scanedit.cpp, lib/scanedit.h, src/ui/staticpage.cpp, src/ui/staticpage.h, tests/scanedittest.cpp: refactor scanedit to only use one lookup table 2015-09-22 Klas Lindfors * src/ui/mainwindow.cpp: use edge picture for 4.2 2015-09-04 Klas Lindfors * .gitignore, lib/common.h, src/yubikeyfinder.h, tests/test.cpp, tests/tests.pro, tests/versiontest.cpp, tests/versiontest.h: move YK_VERSION macro to common, add tests for it and fix it 2015-09-04 Klas Lindfors * src/yubikeyfinder.h: fixup YK_VERSION macro so higher versions are recognized 2015-07-09 Klas Lindfors * lib/yubikeyutil.cpp, src/ui/toolpage.cpp: take some care to set resultLen on errors 2015-07-09 Klas Lindfors * tests/yubikeyutiltest.cpp, tests/yubikeyutiltest.h: test getNextModhex() with uneven amount 2015-05-29 Klas Lindfors * lib/lib.pro, src/src.pro, tests/tests.pro: change syntax for accepting CXXFLAGS and LDFLAGS they now have to be given as options to qmake, instead of env 2015-06-23 Konstantinos Georgantas * README: fix typo 2015-05-29 Klas Lindfors * NEWS, src/src.pro: bump versions 2015-05-29 Klas Lindfors * NEWS: NEWS for 3.1.21 2015-05-27 Klas Lindfors * : update product images with the correct fido logo 2015-04-20 Klas Lindfors * tests/tests.pro: add no_testcase_installs for tests to avoid installation fixes #49 2015-04-07 Klas Lindfors * lib/lib.pro, src/src.pro, tests/tests.pro: restructure compiler flags and add CPPFLAGS from env 2015-04-01 Klas Lindfors * lib/yubikeyutil.cpp: yubikey_hex_decode() and yubikey_modhex_decode() take dstlen 2015-04-01 Klas Lindfors * NEWS, src/src.pro: bump versions 2015-04-01 Klas Lindfors * src/src.pro: fix windows build with signatures 2015-04-01 Klas Lindfors * NEWS: NEWS for 3.1.20 2015-04-01 Klas Lindfors * do-source-release.sh: fixup release script 2015-04-01 Klas Lindfors * src/src.pro: correct search path 2015-03-30 Klas Lindfors * : update neo pictures 2015-03-30 Klas Lindfors * : update plus pictures 2015-03-30 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: add edge graphics 2015-03-30 Klas Lindfors * lib/yubikeyutil.cpp, lib/yubikeyutil.h: drop unused hexdump function 2015-03-30 Klas Lindfors * tests/yubikeyutiltest.cpp, tests/yubikeyutiltest.h: adding test that the random function returns different stuff 2015-03-30 Klas Lindfors * src/yubikeyfinder.cpp: mark more ver 4 as not supporting ndef 2015-03-26 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/diagnostics.cpp, src/ui/mainwindow.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/toolpage.cpp: add more includes 2015-03-26 Klas Lindfors * .travis.yml: format changes 2015-03-26 Klas Lindfors * .travis.yml: split travis script and install 2015-03-26 Klas Lindfors * lib/yubikeyutil.cpp: simplify getNextModhex() by having it call getNextHex() needs to do some coding-decoding, but less logic 2015-03-26 Klas Lindfors * tests/yubikeyutiltest.cpp, tests/yubikeyutiltest.h: some tests for getNextHex() and getNextModhex() 2015-03-26 Klas Lindfors * lib/yubikeyutil.cpp: include QRegExp 2015-03-26 Klas Lindfors * .gitignore, tests/scanedittest.cpp, tests/test.cpp, tests/tests.pro, tests/yubikeyutiltest.cpp, tests/yubikeyutiltest.h: refactor tests a bit so we can have several classes and add a simple test of YubikeyUtil 2015-03-26 Klas Lindfors * lib/common.h, lib/yubikeyutil.cpp, src/ui/aboutpage.cpp, src/ui/chalresppage.cpp, src/ui/confirmbox.cpp, src/ui/diagnostics.cpp, src/ui/mainwindow.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/toolpage.cpp, src/ui/yubiaccbox.cpp, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeywriter.cpp: refactor so common.h pulls in less of qt 2015-03-25 Klas Lindfors * .travis.yml: all needed before check 2015-03-25 Klas Lindfors * .travis.yml: add travis.yml 2015-03-25 Klas Lindfors * .gitignore: ignore 2015-03-25 Klas Lindfors * lib/lib.pro, src/src.pro, tests/tests.pro: re-enable silent compilation and add warn_on for debug 2015-03-24 Klas Lindfors * .gitignore, YKPersonalization.pro, {src => lib}/common.h, {src => lib}/crandom.cpp, {src => lib}/crandom.h, lib/lib.pro, {src => lib}/otpdef.h, {src/ui => lib}/scanedit.cpp, {src/ui => lib}/scanedit.h, {src => lib}/yubikeyutil.cpp, {src => lib}/yubikeyutil.h, src/src.pro, tests/scanedittest.cpp, tests/scanedittest.h, tests/tests.pro: refactor for testability, and add a simple test this breaks the application up in a library part and an application part, the library part is statically linked and pulled in for both tests and the gui app. 2015-03-24 Klas Lindfors * src/ui/scanedit.cpp: | was at wrong position so translation from scancode to text got wrong 2015-03-16 Klas Lindfors * YKPersonalization.pro: switch timestamp url 2015-03-16 Klas Lindfors * : new logo for installer 2015-03-16 Klas Lindfors * : new logo 2015-03-16 Klas Lindfors * src/version.h: bump copyrights for 2015 2015-03-13 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions 2015-03-13 Klas Lindfors * NEWS: NEWS for 3.1.19 2015-03-13 Klas Lindfors * YKPersonalization.pro: switch to osslsigncode for signing windows binaries 2015-03-05 Klas Lindfors * src/ui/aboutpage.cpp, src/ui/aboutpage.ui: remove the build timestamp fixes #48 2014-11-28 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: include neo-n in neo 3.3 picture 2014-11-28 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions 2014-11-28 Klas Lindfors * NEWS: NEWS for 3.1.18 2014-11-28 Klas Lindfors * resources/images/README.mng: update text about creating mng 2014-11-28 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: image for plus 2014-11-24 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeyfinder.h: no support for ndef in yk4 so the exclusion struct has to be expanded to hold a second range for every feature.. 2014-11-11 Klas Lindfors * YKPersonalization.pro: drop QTPLUGIN line, caused the plugins to be linked in at times fixes #46 2014-10-31 Klas Lindfors * YKPersonalization.pro: check that the binaries are correctly linked 2014-10-30 Klas Lindfors * resources/mac/Info.plist.in: apparently the app store doesn't allow build number so I wonder in what field that should go.. 2014-10-30 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions. 2014-10-30 Klas Lindfors * NEWS: NEWS for 3.1.17 2014-10-30 Klas Lindfors * YKPersonalization.pro, resources/mac/Info.plist.in: add so a build number can be set for osX builds 2014-10-30 Klas Lindfors * YKPersonalization.pro: try to get by with codesign --deep 2014-10-30 Klas Lindfors * YKPersonalization.pro: more mac fixups 2014-10-30 Klas Lindfors * YKPersonalization.pro: switch mac build to qt5 2014-10-29 Henrik Stråth * README: Update README 2014-10-29 Henrik Stråth * README: Update README 2014-10-29 Henrik Stråth * README: Update README 2014-10-29 Henrik Stråth * README: Update README 2014-10-29 Henrik Stråth * README.adoc: symlinked README 2014-10-23 Christian Hesse * src/ui/mainwindow.cpp, src/ui/mainwindow.ui, src/yubikeyfinder.cpp, src/yubikeyfinder.h: show U2F in supported features 2014-10-23 Klas Lindfors * src/common.h, src/help.h, src/ui/aboutpage.cpp, src/ui/chalresppage.cpp, src/ui/confirmbox.cpp, src/ui/helpbox.cpp, src/ui/mainwindow.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/toolpage.cpp, src/version.h, src/yubikeywriter.cpp: restructure to get rid of lupdate warnings for translations relates to #42 2014-10-23 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: include the qtaccessiblewidgets plugin when bundling fixes #43 2014-10-23 Klas Lindfors * src/yubikeylogger.h: Q_OBJECT has to be declared before public.. fixes #44 2014-10-22 Klas Lindfors * src/yubikeylogger.cpp: add another tr() 2014-10-22 Klas Lindfors * src/yubikeylogger.h: add forgotten Q_OBJECT macro to yubikeylogger 2014-10-01 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: add two new logfields, accesscodes padded out with 12 characters to be used for the Yubico format that specifies that the access code is always 12 characters, zeroes if unset. fixes #41 2014-09-16 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions 2014-09-16 Klas Lindfors * NEWS: 3.1.16 2014-09-16 Klas Lindfors * src/yubikeyutil.cpp: Q_WS_* is not supported on qt5 change to Q_OS_* fixes #40 2014-09-12 Klas Lindfors * : commit 8fb1b1dfcea2c9e1a8abfd19157cc97f2c74bcfa Author: Klas Lindfors Date: Fri Sep 12 07:51:28 2014 +0100 2014-09-11 Klas Lindfors * YKPersonalization.pro: drop some more debug stuff from qtgui on mac 2014-09-11 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions 2014-09-11 Klas Lindfors * NEWS: NEWS for 3.1.15 2014-09-11 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: new picture for version 3.3+ with u2f logo 2014-09-11 Klas Lindfors * YKPersonalization.pro: make sure the qtgui is writable 2014-09-11 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: switch the windows build to qt5 2014-09-09 Klas Lindfors * src/ui/aboutpage.ui: move the support link to it's own line 2014-09-09 Klas Lindfors * src/common.h, src/ui/aboutpage.cpp: fixup support link since it's no longer mail 2014-09-04 mistertoh * src/ui/aboutpage.ui: Update Link for Help and Discussion 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp: fixup xml syntax 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp: add CryptoModuleInfo with configSlot 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: add tokenLength formatter to get responseFormat correct 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp: user serial:slot for Key@Id 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: write start and end of PSKC info 2014-08-28 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/yubikeylogger.h: register aboutToQuit() handler and call closeLogFile() there 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: close the logFile when things change 2014-08-28 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: implement secret key in base64 for logging specifically for the pskc format 2014-08-28 Klas Lindfors * src/ui/settingpage.ui, src/yubikeylogger.cpp, src/yubikeylogger.h: add a first stab at an experimental PSKC output format this is clearly a naive least-effort implementation.. relates to #4 2014-07-15 Alessio Di Mauro * src/ui/staticpage.cpp, src/ui/staticpage.ui: Added graying out of text boxes and buttons when no layout is selected. 2014-07-07 Alessio Di Mauro * src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/staticpage.ui: Added dropdown menu for keyboard layout selection. 2014-04-23 Klas Lindfors * src/yubikeyconfig.cpp: make sure to initialize all variables in constructor specifically m_hmacLT64 2014-04-23 Klas Lindfors * src/yubikeyutil.cpp: reduce scope of val 2014-04-23 Klas Lindfors * src/ui/diagnostics.cpp: put the "unknown os" in #else 2014-04-23 Klas Lindfors * src/yubikeylogger.cpp: fixup logging so all modes are logged use a switch-case instead of if to get warnings if we miss a case. resolves #36 2014-04-22 Klas Lindfors * : Merge pull request #35 from dudebout/patch-1 Adds a missind dependency in the README 2014-04-16 Klas Lindfors * src/common.h: add head to html template 2014-02-27 David Wittman * src/ui/oathpage.ui, src/ui/otppage.ui, src/ui/staticpage.ui: Typo fix in UI: s/Quicky/Quickly/ 2014-01-28 Klas Lindfors * src/yubikeyutil.cpp: change around qDebug() usage to get rid of warnings 2014-01-10 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions 2014-01-10 Klas Lindfors * NEWS: news for 3.1.14 2014-01-10 Klas Lindfors * src/ui/confirmbox.ui: set a minimum width for the confirmbox text 2014-01-10 Klas Lindfors * src/ui/confirmbox.ui: let the confirmbox expand 2014-01-10 Klas Lindfors * src/ui/toolpage.ui: drop the placeholdertext completely 2014-01-10 Klas Lindfors * src/ui/diagnostics.cpp: fixup mac version 2014-01-10 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions after release 2014-01-10 Klas Lindfors * NEWS: NEWS for 3.1.13 2014-01-10 Klas Lindfors * : commit be3540fa8b3c5e9dc45b5587b4b427f28dde9fd8 Author: mistertoh Date: Fri Jan 10 11:20:10 2014 +0100 2014-01-10 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.ui: don't use placeholder for the default neo url, just set it as text and improve reset on Ndef page 2014-01-07 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.ui: change the NDEF example to be the default string 2014-01-07 Klas Lindfors * COPYING, resources/win/resources.rc, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.h, src/version.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeywriter.cpp, src/yubikeywriter.h: bump copyright 2014-01-07 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/helpbox.ui, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.h: make the help pages non-modal and make it a child of mainwindow and just send signals there when we want it shown. 2014-01-07 Klas Lindfors * src/ui/diagnostics.ui, src/ui/mainwindow.cpp: make the diagnostics window non-modal 2014-01-03 Klas Lindfors * src/yubikeyfinder.cpp: clear touchLevel when initing 2014-01-03 Klas Lindfors * src/yubikeyfinder.cpp: add touch level to key diagnostics 2014-01-03 Klas Lindfors * src/yubikeywriter.cpp: more diagnostics for successful write-key operations 2014-01-03 Klas Lindfors * src/ui/diagnostics.cpp, src/ui/diagnostics.h: add an info diagnostics message with varios versions 2014-01-03 Klas Lindfors * src/yubikeyfinder.cpp: force serial to a string in diagnostic message otherwise we will call the wrong arg() 2014-01-03 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeywriter.cpp: add qualifier to usb errors. 2014-01-03 Klas Lindfors * src/ui/diagnostics.cpp: add date to the diagnostic messages 2014-01-03 Klas Lindfors * src/yubikeyfinder.cpp: add diagnostic message when a key is inserted 2014-01-03 Klas Lindfors * YKPersonalization.pro, src/ui/diagnostics.cpp, src/ui/diagnostics.h, src/ui/diagnostics.ui, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/mainwindow.ui, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeywriter.cpp, src/yubikeywriter.h: add a diagnostics view with more complete error messages 2014-01-02 Klas Lindfors * src/ui/settingpage.ui: try to make version compability on settingpage clearer 2013-12-30 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions after release 2013-12-30 Klas Lindfors * NEWS: NEWS for 3.1.12 2013-12-30 Klas Lindfors * : commit b9e5bdcd47f777e7bd29b1021f9d9cfa627527c2 Author: mistertoh Date: Mon Dec 30 14:24:16 2013 +0100 2013-12-02 Klas Lindfors * src/help.h: fix typo defer -> differ 2013-12-02 Klas Lindfors * : commit 90de271eb1dd877f4db807e3645b9a2b6c73f27a Author: mistertoh Date: Mon Dec 2 14:41:49 2013 +0100 2013-10-28 Klas Lindfors * : Merge pull request #28 from mistertoh/master Fix Icon Position 2013-10-28 Klas Lindfors * : Merge pull request #27 from mistertoh/master Fix Typo Challenge Response -> Challenge-Response 2013-10-28 Klas Lindfors * : Merge pull request #26 from mistertoh/master Fix Typo 2013-10-09 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions 2013-10-09 Klas Lindfors * NEWS: release 3.1.11 2013-09-26 Klas Lindfors * src/help.h, src/yubikeylogger.cpp: add endl and tab variables to logging 2013-09-26 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: make the logging local resolver take the name as string to reduce the amount of similar resolvers 2013-09-26 Klas Lindfors * src/ui/settingpage.cpp: disable the format edit when not in flexible format 2013-09-26 Klas Lindfors * NEWS: add NEWS for flexible logging 2013-09-26 Klas Lindfors * build-homepage.sh: drop build-homepage script 2013-09-26 Klas Lindfors * BLURB: add category to BLURB 2013-09-26 Klas Lindfors * BLURB: BLURB for yubikey-personalization-gui 2013-09-26 Klas Lindfors * src/help.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/settingpage.cpp, src/ui/settingpage.ui: add help for the flexible logging format 2013-09-26 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: add getting a list of lognames 2013-09-26 Klas Lindfors * YKPersonalization.pro, src/common.h, src/help.h, src/ui/helpbox.cpp: move help texts to it's own header to reduce re-compile times due to changed texts.. 2013-09-26 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/ui/settingpage.ui, src/yubikeylogger.cpp, src/yubikeylogger.h: add a flexible logformat with configurable input 2013-09-26 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.ui: change the radio buttons for logformat to a combobox 2013-09-26 Klas Lindfors * src/common.h, src/ui/yubiaccbox.cpp: move defines for accbox to yubiaccbox.cpp from common.h 2013-09-26 Klas Lindfors * src/common.h, src/ui/settingpage.cpp: localize OUT_CHAR_RATE defines to settingpage.cpp 2013-09-26 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: refactor building of the logging string to use a lookup table and format-strings, calling methods in the YubikeyConfig class by name instead. This will allow building more flexible logging schemes. 2013-09-26 Klas Lindfors * src/yubikeyconfig.h: make YubikeyConfig a QObject and it's getter methods invokable this will make the getter methods available for calling by name through the meta object. 2013-09-20 Klas Lindfors * NEWS: add NEWS for the next version 2013-09-19 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeyfinder.h: fix so we recheck the key after regaining focus add a new state to the finder NoFocus, when running the find cycle re-read all info if NoFocus is set as well. 2013-09-17 Klas Lindfors * resources/win/resources.rc, src/version.h: and change around again utf8 in src/version.h latin1 in resources/win/resources.rc 2013-09-17 Klas Lindfors * src/ui/aboutpage.cpp, src/version.h: revert back to latin1 for the copyright sign but use tr() utf8 broke in the windows resource file and in some versions of qt. 2013-09-17 Klas Lindfors * YKPersonalization.pro, resources/win/resources.rc: make version numbering work on windows 2013-09-17 Klas Lindfors * : Merge pull request #24 from eworm-de/encoding fix encoding for copyright sign 2013-09-17 Klas Lindfors * src/common.h, src/ui/mainwindow.cpp, src/yubikeyfinder.cpp, src/yubikeywriter.cpp: Allow writing of keys with unknown firmware Print a warning in place of "YubiKey inserted" fixes #23 2013-09-17 Klas Lindfors * YKPersonalization.pro, src/ui/confirmbox.cpp, src/ui/mainwindow.cpp, src/ui/otppage.cpp, src/ui/scanedit.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.h, src/yubikeyfinder.cpp, src/yubikeywriter.cpp: support qt5 2013-09-17 Klas Lindfors * src/common.h, src/ui/aboutpage.cpp, src/ui/chalresppage.cpp, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/mainwindow.ui, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/toolpage.cpp, src/ui/yubiaccbox.cpp, src/yubikeyfinder.cpp, src/yubikeyfinder.h: handle error messages when opening key Adds proper output for the case when there's more than one key present fixes #9 2013-08-05 Klas Lindfors * src/ui/toolpage.ui: re-add the importBox as a qWidget fixes compilation errors and hopefully doesn't show the box fixes #22 2013-07-05 Klas Lindfors * build-homepage.sh: drop news file from homepage 2013-07-24 Simon Josefsson * resources/lin/yubikey-personalization-gui.desktop: Add Keywords to desktop file. 2013-07-04 Klas Lindfors * src/ui/toolpage.ui: drop box around import 2013-07-04 Klas Lindfors * YKPersonalization.pro, src/version.h: fix windows build by fiddling some with version 2013-07-04 Klas Lindfors * NEWS, YKPersonalization.pro: bump versions post-release 2013-07-04 Klas Lindfors * do-source-release.sh: fix release script for new VERSION format 2013-07-04 Klas Lindfors * NEWS: release 3.1.10 2013-07-02 Klas Lindfors * src/yubikeylogger.cpp: don't try to open file if we don't have a filename 2013-07-02 Klas Lindfors * src/yubikeywriter.cpp: drop the write_config way and only write it out with qDebug() 2013-07-01 Klas Lindfors * src/ui/settingpage.ui: make sure all text is shown 2013-07-01 Klas Lindfors * src/yubikeywriter.cpp: set acces code mode to the library 2013-07-01 Klas Lindfors * src/common.h, src/ui/chalresppage.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.h, src/yubikeyconfig.cpp, src/yubikeyconfig.h: code to set the mode of acccode in the yubikeyconfig object 2013-07-01 Klas Lindfors * src/common.h, src/main.cpp, src/ui/aboutpage.cpp, src/ui/chalresppage.cpp, src/ui/mainwindow.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/scanedit.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/toolpage.cpp, src/ui/yubiaccbox.cpp, src/yubikeyconfig.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeylogger.h, src/yubikeyutil.cpp, src/yubikeywriter.cpp, src/yubikeywriter.h: include cleanup. 2013-07-01 Klas Lindfors * src/ui/yubiaccbox.cpp: if we want to keep accCode, return the old one as new 2013-07-01 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/mainwindow.h: move around inclusions of "other" forms to avoid unnecessary re-compilations 2013-06-28 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.ui: disable import when no key is inserted 2013-06-28 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui: add serial checkbox for ndef and zap acc code 2013-06-28 Klas Lindfors * YKPersonalization.pro: move around 2013-06-28 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/staticpage.cpp, src/ui/toolpage.cpp, src/ui/yubiaccbox.cpp: mark unused parameters as unused 2013-06-28 Klas Lindfors * src/ui/scanedit.cpp: use toUInt() to get an unsigned variable for comparison 2013-06-28 Klas Lindfors * src/yubikeywriter.cpp: fix warning 2013-06-28 Klas Lindfors * src/yubikeyutil.cpp: fix warnings 2013-06-25 Klas Lindfors * YKPersonalization.pro: add build config flag force_pkgconfig 2013-06-25 Klas Lindfors * README: we now depend on 1.14.0 of yubikey-personalization 2013-06-24 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.ui: try to make uri example clearer with a placeholder on ndefEdit 2013-06-07 Klas Lindfors * src/ui/yubiaccbox.cpp: remove unecessary check if m_serial is set 2013-06-07 Klas Lindfors * src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.h: implement serial functionality 2013-06-07 Klas Lindfors * src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.ui: add serial checkboxes 2013-06-06 Klas Lindfors * src/ui/yubiaccbox.ui: set stylesheet for the accbox 2013-06-05 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui: refactor settingpage usage of access code to use new box 2013-06-05 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/chalresppage.ui: refactor chalresppage to use new access code box 2013-06-05 Klas Lindfors * src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/staticpage.ui: refactor staticpage to use new access box 2013-06-05 Klas Lindfors * src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/oathpage.ui: refactor the oath page to use new access code box 2013-06-05 Klas Lindfors * src/ui/otppage.cpp, src/ui/otppage.h, src/ui/otppage.ui: refactor to use the broken-out config protection box 2013-06-05 Klas Lindfors * YKPersonalization.pro, src/ui/yubiaccbox.cpp, src/ui/yubiaccbox.h, src/ui/yubiaccbox.ui: break out the config protection box into it's own widget 2013-06-03 Klas Lindfors * src/ui/toolpage.cpp: make sure the buffer for decoding hex/modhex into is large enough it has to be number of bytes * 2 for decoding. fixes #18 2013-05-03 Klas Lindfors * YKPersonalization.pro: only enable silent if nosilent isn't set 2013-05-03 Klas Lindfors * src/ui/scanedit.cpp: old bug make sure we don't access after end of array code was changed earlier to xor with SHIFT before and store it 2013-05-03 Klas Lindfors * src/ui/settingpage.ui: move box around to fix ui issues 2013-05-02 Klas Lindfors * src/common.h, src/ui/mainwindow.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/toolpage.cpp: handle strong_pw stuff as settings 2013-05-02 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/toolpage.cpp, src/ui/toolpage.h: let the import feature select slots 2013-05-02 Klas Lindfors * YKPersonalization.pro: only use productbuild for app store builds 2013-04-30 Klas Lindfors * src/common.h, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/settingpage.cpp, src/ui/toolpage.cpp: handle hmac_lt64 as a setting 2013-04-30 Klas Lindfors * src/common.h, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/settingpage.cpp, src/ui/toolpage.cpp: treat btn_trig as a setting 2013-04-30 Klas Lindfors * src/common.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/settingpage.cpp, src/ui/toolpage.cpp: handle oath digits by remembering the setting 2013-04-29 Klas Lindfors * YKPersonalization.pro, do-source-release.sh, src/version.h: only keep version in YKPersonalization.pro 2013-04-29 Klas Lindfors * src/ui/settingpage.ui: export and import 2013-04-26 Klas Lindfors * src/ui/toolpage.cpp: save filename if import was ok 2013-04-26 Klas Lindfors * src/ui/toolpage.cpp: import alot of settings 2013-04-26 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/toolpage.cpp, src/ui/toolpage.h: switch page according to inmported cfg 2013-04-26 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/mainwindow.h: add code to switch to specific tab on page 2013-04-26 Klas Lindfors * src/ui/chalresppage.h, src/ui/oathpage.h, src/ui/otppage.h, src/ui/settingpage.h, src/ui/staticpage.h, src/ui/toolpage.h: make setCurrentPage a public slot 2013-04-26 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/toolpage.h: add a reloadSettings slot/signal 2013-04-26 Klas Lindfors * src/ui/chalresppage.h, src/ui/oathpage.h, src/ui/otppage.h, src/ui/settingpage.h, src/ui/staticpage.h, src/ui/toolpage.h: move all Page elements to public 2013-04-26 Klas Lindfors * src/yubikeywriter.cpp: use YK_STATUS object from yubikeyfinder instead 2013-04-26 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeyfinder.h: move the ykstatus object to class level and make it fetchable for others 2013-04-25 Klas Lindfors * src/ui/toolpage.cpp: start on importing configuration 2013-04-25 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/ui/toolpage.cpp, src/ui/toolpage.h: filenames for import 2013-04-25 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui: add basis of import tab to toolpage 2013-04-22 Klas Lindfors * : re-generate .icns file for mac 2013-04-22 Klas Lindfors * resources/mac/Info.plist.in: add CFBundleShortVersionString 2013-04-22 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions 2013-04-22 Klas Lindfors * NEWS: NEWS 2013-04-22 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/yubikeylogger.cpp, src/yubikeylogger.h, src/yubikeywriter.cpp, src/yubikeywriter.h: remember selected locations for log and export and reuse resolves #16 2013-04-19 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeywriter.cpp: better default paths for file dialogs 2013-04-19 Klas Lindfors * src/common.h, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/mainwindow.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/settingpage.ui: add a setting for enable/disable export config 2013-04-18 Klas Lindfors * src/yubikeywriter.cpp: YKP_FORMAT_JSON changed to YKP_FORMAT_YCFG 2013-04-18 Klas Lindfors * YKPersonalization.pro: deal with moving qt_menu.nib if it's already moved 2013-04-18 Klas Lindfors * src/ui/settingpage.ui: move around logging settings 2013-04-18 Klas Lindfors * : commit 2dab637d23070be7a6e146a1d5e4b2e60673ba0d Author: Klas Lindfors Date: Thu Apr 18 13:57:52 2013 +0100 2013-04-18 Klas Lindfors * YKPersonalization.pro: add for_store build flags 2013-04-18 Klas Lindfors * resources/mac/Info.plist.in: add application category 2013-04-18 Klas Lindfors * YKPersonalization.pro: for mac use config for_store to select appropriate certificates 2013-04-18 Klas Lindfors * YKPersonalization.pro: run productbuild instead of pkgbuild 2013-04-16 Klas Lindfors * YKPersonalization.pro: add license files for osx 2013-04-16 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: include licenses in windows installer 2013-04-16 Klas Lindfors * YKPersonalization.pro: merge two win32 blocks 2013-04-16 Klas Lindfors * YKPersonalization.pro, resources/mac/Entitlements.plist: use app sandbox on osX 2013-04-16 Klas Lindfors * README: update instructions 2013-04-16 Klas Lindfors * YKPersonalization.pro: simplify mac build 2013-04-16 Klas Lindfors * YKPersonalization.pro: rework macx build to work with binary package of libykpers 2013-04-15 Klas Lindfors * YKPersonalization.pro: change around so the dll files come from the packed up zip 2013-04-15 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeywriter.cpp: set filters for selected files 2013-04-15 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui, src/yubikeylogger.cpp, src/yubikeylogger.h: change around for logging to go by QFileDialog With this the user has to select which file to log to when the first write occurs. solves #3 2013-04-15 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: add json dll for windows build 2013-04-15 Klas Lindfors * installer/win32/Installer.sln, installer/win32/Installer/Installer.vdproj: drop old windows installer 2013-04-15 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/chalresppage.ui, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/oathpage.ui, src/ui/otppage.cpp: implement export for oath and chalresp 2013-04-15 Klas Lindfors * src/ui/otppage.cpp: same rules for export as write 2013-04-15 Klas Lindfors * src/yubikeywriter.cpp: little bit more error-checking 2013-04-15 Klas Lindfors * src/common.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/otppage.ui: add exporting of otp 2013-04-15 Klas Lindfors * src/yubikeywriter.cpp, src/yubikeywriter.h: add exportConfig method and split out assembling the configuration 2013-04-11 Dain Nilsson * do-source-release.sh: Use publish script in YUBICO_GITHUB_REPO 2013-04-05 Klas Lindfors * build-homepage.sh, do-source-release.sh: change release scripts around to work with yubico.github.com 2013-04-04 Simon Josefsson * resources/lin/yubikey-personalization-gui.1, src/common.h, src/crandom.cpp, src/crandom.h, src/main.cpp, src/otpdef.h, src/ui/aboutpage.cpp, src/ui/aboutpage.h, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/confirmbox.cpp, src/ui/confirmbox.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/scanedit.cpp, src/ui/scanedit.h, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/toolpage.cpp, src/ui/toolpage.h, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeylogger.cpp, src/yubikeylogger.h, src/yubikeyutil.cpp, src/yubikeyutil.h, src/yubikeywriter.cpp, src/yubikeywriter.h: Bump copyright years. 2013-03-18 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions post-release 2013-03-18 Klas Lindfors * NEWS: release 3.1.8 2013-03-15 Klas Lindfors * src/ui/oathpage.cpp, src/ui/oathpage.h: correctly add the MUI part to public id for oath fixes #12 broken in 5fa2fb7 and released in 3.1.3.. 2013-03-14 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions post-release 2013-03-14 Klas Lindfors * build-homepage.sh: no -e for homepage build 2013-03-14 Klas Lindfors * NEWS: release 3.1.7 2013-03-14 Klas Lindfors * src/ui/otppage.cpp: switch to using fromLocalFile() to construct instead of specing file:// 2013-03-14 Klas Lindfors * NEWS: NEWS for 3.1.7 2013-03-13 Klas Lindfors * README: LED_INV didn't appear until version 1.12 2013-03-13 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/ui/settingpage.ui, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeywriter.cpp: move around and add LED_INV support 2013-03-11 Klas Lindfors * src/ui/oathpage.cpp, src/ui/oathpage.h: cleanup, remove unused stuff m_pubIdFormat was never read, calls to update...() didn't have any effect. 2013-03-11 Klas Lindfors * src/ui/oathpage.cpp: drop commented code 2013-03-11 Klas Lindfors * src/ui/oathpage.cpp: fixup entering of MUI contained code that overwrote the bounds of m_pubid and did other unnecessary things. Fixes #11 2013-02-28 Klas Lindfors * src/common.h, src/ui/otppage.cpp, src/ui/otppage.h: change around so we don't send the uploaded key as a GET instead write a temp file with an auto-submitting form that does a POST to upload.yubico.com 2013-02-26 Klas Lindfors * src/ui/staticpage.ui: add a + to indicate that it's version 2.2 and later 2013-02-21 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions post-release 2013-02-21 Klas Lindfors * NEWS: news for override box 2013-02-21 Klas Lindfors * src/common.h, src/ui/confirmbox.cpp, src/ui/toolpage.cpp: make the override box on ndef without http work 2013-02-21 Klas Lindfors * YKPersonalization.pro: point to rcc for win32 build 2013-02-21 Klas Lindfors * YKPersonalization.pro: declare that we use exceptions 2013-02-21 Klas Lindfors * NEWS: release 3.1.6 2013-02-18 Klas Lindfors * src/yubikeywriter.cpp: only set imf if the key is capable of it 2013-02-18 Dain Nilsson * src/yubikeyfinder.cpp: Fixed memory leak introduced in last commit. 2013-02-08 Dain Nilsson * src/yubikeyfinder.cpp: Only lock the YubiKey when we have window focus. 2013-01-10 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions after release 2013-01-10 Klas Lindfors * NEWS: release 3.1.5 2013-01-10 Klas Lindfors * YKPersonalization.pro: add ykpers-version.c for inline build of ykpers 2013-01-09 Klas Lindfors * COPYING, NEWS, YKPersonalization.pro, do-source-release.sh, src/version.h: bump versions and copyrights 2013-01-09 Klas Lindfors * YKPersonalization.pro: set version to 3.1.4 2013-01-09 Klas Lindfors * NEWS: news for 3.1.4 2013-01-09 Klas Lindfors * src/common.h, src/ui/confirmbox.cpp, src/ui/confirmbox.h, src/ui/toolpage.cpp: add a confirm if the entered uri does not start with http 2013-01-07 Klas Lindfors * build-homepage.sh: add NEWS to homepage 2012-12-28 Klas Lindfors * README, YKPersonalization.pro, src/ui/aboutpage.cpp, src/ui/aboutpage.ui: display library version on about page 2012-12-21 Klas Lindfors * NEWS, src/version.h: bump versions after release 2012-12-21 Klas Lindfors * do-source-release.sh: remove trailing comma 2012-12-21 Klas Lindfors * do-source-release.sh: update do-source-release properly. 2012-12-21 Klas Lindfors * NEWS: news and release for 3.1.3 2012-12-21 Klas Lindfors * do-source-release.sh: remove USER 2012-12-21 Klas Lindfors * do-source-release.sh: switch to gh-pages for releases 2012-12-21 Klas Lindfors * build-homepage.sh: script to build the homepage in the gh-pages branch 2012-12-21 Klas Lindfors * README: change some formatting to match asciidoc better 2012-12-21 Klas Lindfors * README: README updates 2012-12-21 Klas Lindfors * YKPersonalization.pro.user.lin, YKPersonalization.pro.user.mac, YKPersonalization.pro.user.win: drop files that we generate anyways 2012-12-21 Klas Lindfors * README.binary_dists: some useful qmake invocations 2012-12-21 Klas Lindfors * YKPersonalization.pro: add code for signing windows binaries as part of the build 2012-12-20 Klas Lindfors * YKPersonalization.pro: no $$ when checking isEmpty() 2012-12-20 Klas Lindfors * YKPersonalization.pro: cleanup libraries and remove unused header 2012-12-20 Klas Lindfors * src/ui/oathpage.h: mui should be unsigned 2012-12-20 Klas Lindfors * src/ui/oathpage.cpp: make sure we zero-out mui on reset 2012-12-20 Klas Lindfors * YKPersonalization.pro: fix release build for windows, cleanup. 2012-12-20 Klas Lindfors * src/ui/oathpage.cpp, src/ui/oathpage.h: don't do fancy bcd tricks with MUI, just keep it in an int 2012-12-20 Klas Lindfors * YKPersonalization.pro: config for creating windows debug builds 2012-12-20 Klas Lindfors * src/yubikeyfinder.cpp: fix a file descriptor leak that caused windows to fail after 44 writes 2012-12-18 Klas Lindfors * NEWS, src/common.h, src/yubikeywriter.cpp, src/yubikeywriter.h: don't reuse the general error message for challenge-response 2012-12-18 Klas Lindfors * YKPersonalization.pro: make compiling silent 2012-12-18 Klas Lindfors * NEWS: add NEWS for 3.1.3 2012-12-18 Klas Lindfors * src/common.h, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/mainwindow.ui: add support for stopping animation (and saving that in settings) 2012-12-17 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi, resources/images/README.mng, resources/resources.qrc, src/ui/mainwindow.cpp: switch from gifs to mng 2012-12-17 Klas Lindfors * : new pictures 2012-12-11 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: new picture for production neo 2012-11-20 Klas Lindfors * src/ui/settingpage.ui: change wording for update to update settings 2012-11-12 Klas Lindfors * src/ui/settingpage.cpp: add forgotten save on selecting pacing 2012-11-12 Klas Lindfors * src/yubikeywriter.cpp: fixup last commit that was broken, remove correct ykst 2012-11-12 Klas Lindfors * src/yubikeywriter.cpp: remove unnecessary status struct and call yk_check_firmware2() when we have it 2012-11-12 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.ui, src/yubikeywriter.cpp, src/yubikeywriter.h: support for writing SLOT_NDEF2 for production neo 2012-11-12 Klas Lindfors * src/ui/mainwindow.cpp: correct picture for production neo 2012-11-12 Klas Lindfors * src/yubikeyfinder.cpp: features for yubikey 3.0 (neo) 2012-11-09 Klas Lindfors * src/ui/otppage.cpp: run the editingFinished hook on public id after setting it to serial 2012-11-07 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions to 3.1.3 2012-11-07 Klas Lindfors * NEWS: release 3.1.2 2012-11-06 Klas Lindfors * src/ui/settingpage.ui: put ... to show that update leads to a new page 2012-10-31 Klas Lindfors * src/ui/settingpage.ui: some wording on versions and box sizes. 2012-10-31 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.ui: remove save button and write out that we autosave 2012-10-26 Klas Lindfors * NEWS: news for 3.1.2 2012-10-26 Klas Lindfors * installer/win-nsis/ykpers.nsi: create all start menu items in the same place and make sure they're removed when uninstalled 2012-10-26 Klas Lindfors * installer/win-nsis/ykpers.nsi: set a default startmenu folder under Yubico 2012-10-23 Klas Lindfors * src/ui/otppage.cpp: set new parameters on key insertion, not removal 2012-10-23 Klas Lindfors * src/ui/mainwindow.cpp: remove the movie field if it's set before setting a new one 2012-10-23 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/staticpage.cpp, src/ui/staticpage.h: keep track of the keys state when writing multiple keys otherwise we'll trigger on the keyFound event after it's written 2012-10-19 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/yubikeywriter.cpp: add message on successful config deletion 2012-10-19 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui, src/yubikeywriter.cpp, src/yubikeywriter.h: add access code entry for ndef programming 2012-10-19 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui: add access code entry for delete 2012-10-18 Klas Lindfors * src/ui/toolpage.cpp: call deleteConfig() 2012-10-18 Klas Lindfors * src/yubikeywriter.cpp, src/yubikeywriter.h: deleteConfig() slot 2012-10-18 Klas Lindfors * src/yubikeyfinder.cpp: clear the finder object when starting, so it re-reads key 2012-10-18 Klas Lindfors * src/yubikeywriter.cpp, src/yubikeywriter.h: break out accesscode formatting into it's own function 2012-10-18 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui: start with ui for deleting configuration 2012-10-18 Klas Lindfors * src/ui/mainwindow.ui: make the serial numbers selectable and copyable 2012-10-17 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions after release 2012-10-17 Klas Lindfors * NEWS: add NEWS and release date for 3.1.1 2012-10-15 Klas Lindfors * src/ui/scanedit.cpp: don't try to access the usb2key arrays if the scancode is to high 2012-10-15 Klas Lindfors * src/ui/staticpage.cpp: take the scancodes directly from the scancode field, it's always populated 2012-10-12 Klas Lindfors * YKPersonalization.pro: do else:fedora to avoid debian branch falling into later else 2012-10-12 Klas Lindfors * src/ui/staticpage.cpp: set scancodes to password mode when hidden 2012-10-12 Klas Lindfors * src/ui/staticpage.cpp: set len to zero when clearing 2012-10-12 Klas Lindfors * src/ui/staticpage.cpp, src/ui/staticpage.h: capture a pressed return when editing text 2012-10-12 Klas Lindfors * installer/win-nsis/ykpers.nsi: don't show the components at all as we only have one 2012-10-12 Klas Lindfors * : commit 791a91cfffaded71855c788ae1932e5881f9da5c Author: Klas Lindfors Date: Fri Oct 12 08:36:48 2012 +0200 2012-10-11 Maxim Burgerhout * resources/lin/yubikey-personalization-gui.desktop, resources/lin/yubikey-personalization-gui.xpm: Add .desktop, .xpm and .png files These are from the yubikey-personalization-gui-dpkg repo on github. Putting them here will enable us to grab them from the tarball in the future, instead of directly from github. 2012-10-11 Maxim Burgerhout * YKPersonalization.pro: Linux build -> Generic Linux build 2012-10-11 Maxim Burgerhout * YKPersonalization.pro: Create a separate 'fedora' build target Copying this from the 'debian' target to make sure changes there will not bite us, and vice versa. 2012-10-11 Klas Lindfors * src/ui/chalresppage.ui, src/ui/oathpage.ui, src/ui/otppage.ui, src/ui/settingpage.ui, src/ui/staticpage.ui, src/ui/toolpage.ui: change height of radio buttons so whole button can be seen 2012-10-11 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.ui: use validators instead of inputmask for all customer prefix fields 2012-10-11 Klas Lindfors * src/ui/scanedit.cpp, src/ui/scanedit.h, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/staticpage.ui: rework the scancode input. allow editing and pasting, allow going back and forth between scan codes and text. 2012-10-10 Klas Lindfors * src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/staticpage.ui: add field for scan code input allowing either direct input as scan codes also showing the scancodes that will be programmed for standard text 2012-10-10 Klas Lindfors * src/yubikeyfinder.cpp: clear the struct when no key found, not when closing. when closing, clear m_yk 2012-10-10 Klas Lindfors * src/yubikeyfinder.cpp: always closeKey() when we're done with it in yubikeyfinder 2012-10-10 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeywriter.cpp: only do yk_init() / yk_release() in constructor/destructor of yubikeyfinder 2012-10-08 Klas Lindfors * YKPersonalization.pro: change name of linux installer 2012-10-08 Klas Lindfors * : commit a5339e308fc784cf6a996c8050a81bcf9e6abda9 Merge: 27b8dac 88ba617 Author: Klas Lindfors Date: Mon Oct 8 11:00:57 2012 +0200 2012-10-08 Klas Lindfors * resources/lin/YubiKey Personalization Tool.sh: fix binary name 2012-10-08 Klas Lindfors * YKPersonalization.pro: fix search paths for linux "installer" 2012-10-08 Klas Lindfors * : commit a79a710011ebddc22fbab5477cc6b4b4a452cc54 Author: Klas Lindfors Date: Mon Oct 8 09:30:45 2012 +0100 2012-10-04 Klas Lindfors * YKPersonalization.pro: other libdir for natively installed qt.. 2012-10-04 Klas Lindfors * YKPersonalization.pro, resources/mac/installer.plist: installer fixups 2012-10-04 Klas Lindfors * YKPersonalization.pro: remove the headers from qt frameworks 2012-10-04 Klas Lindfors * .gitignore: add .DS_Store to .gitignore 2012-10-04 Klas Lindfors * YKPersonalization.pro: run install_name_tool for native builds 2012-10-04 Klas Lindfors * YKPersonalization.pro: use codesign and pkgbuild to build a signed installer 2012-10-04 Klas Lindfors * YKPersonalization.pro: fix installer name for native mac build 2012-10-04 Klas Lindfors * YKPersonalization.pro: native mac build fixes 2012-10-04 Klas Lindfors * YKPersonalization.pro: declare that we need qgif 2012-10-03 Klas Lindfors * .gitignore: ignore build artifacts and .swp files 2012-10-03 Klas Lindfors * : commit c373d05f7fb586c4810941eaa8cee32af2e30841 Author: Klas Lindfors Date: Wed Oct 3 10:05:31 2012 +0200 2012-10-03 Klas Lindfors * src/yubikeylogger.cpp: spelling timstamp -> timestamp 2012-10-03 Klas Lindfors * src/yubikeylogger.cpp: do start logging in traditional format 2012-10-03 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/ui/settingpage.ui: add controls for the logging format 2012-10-03 Klas Lindfors * src/yubikeylogger.cpp: implement the yubico logging format 2012-10-03 Klas Lindfors * src/yubikeylogger.cpp: spelling timstamp -> timestamp 2012-10-03 Klas Lindfors * src/yubikeylogger.cpp: do start logging in traditional format 2012-10-03 Klas Lindfors * src/ui/settingpage.cpp: set logging format on load 2012-10-03 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/ui/settingpage.ui: add controls for the logging format 2012-10-03 Klas Lindfors * src/yubikeylogger.cpp, src/yubikeylogger.h: add support for different formats to logger 2012-10-03 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/settingpage.cpp, src/ui/staticpage.cpp, src/yubikeyconfig.cpp, src/yubikeyconfig.h: add serial to yubikeyconfig class 2012-10-01 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/mainwindow.ui, src/yubikeyfinder.cpp, src/yubikeyfinder.h: use touchLevel to find out what slots on inserted YubiKey is programmed 2012-10-01 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions after release 2012-09-28 Klas Lindfors * NEWS, YKPersonalization.pro, src/version.h: bump versions for release 2012-09-28 Klas Lindfors * README: information about cross compiling 2012-09-28 Klas Lindfors * NEWS: NEWS 2012-09-28 Klas Lindfors * .gitignore: ignores 2012-09-28 Klas Lindfors * : add logo for dmg (not working) 2012-09-28 Klas Lindfors * YKPersonalization.pro: avoid rr-moved 2012-09-28 Klas Lindfors * : logo with correct color 2012-09-28 Klas Lindfors * YKPersonalization.pro: more dmg building 2012-09-28 Klas Lindfors * YKPersonalization.pro: switch to build_installer for both win and mac. start with dmg building 2012-09-28 Klas Lindfors * YKPersonalization.pro: only add libusb.h if we're building on linux 2012-09-28 Klas Lindfors * YKPersonalization.pro: move native dmg for mac into else of cross 2012-09-28 Klas Lindfors * YKPersonalization.pro, resources/mac/qt.conf: add qt.conf for mac 2012-09-28 Klas Lindfors * YKPersonalization.pro: change name of TARGET to TARGET_ARCH 2012-09-28 Klas Lindfors * YKPersonalization.pro: properly change the name 2012-09-28 Klas Lindfors * YKPersonalization.pro: finishing up the building of osx bundle 2012-09-28 Klas Lindfors * YKPersonalization.pro: only remove -arch if cross is defined 2012-09-28 Klas Lindfors * YKPersonalization.pro: remove trailing " 2012-09-28 Klas Lindfors * installer/win-nsis/ykpers.nsi: win-installer updates for new compilation unit 2012-09-28 Klas Lindfors * YKPersonalization.pro: mac updates 2012-09-28 Klas Lindfors * : new yubikey neo picture 2012-09-27 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: call makensis from make, output from nsis in build/release 2012-09-27 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: more build fixes, mostly win32 cross compiling. 2012-09-27 Klas Lindfors * YKPersonalization.pro, installer/win-nsis/ykpers.nsi: static-libstdc++ and static-libgcc gets rid of some deps 2012-09-27 Klas Lindfors * YKPersonalization.pro: att SDK includes to QT_INCDIR 2012-09-27 Klas Lindfors * YKPersonalization.pro: take pointer to SDK and define QT_MAC_USE_COCOA 2012-09-27 Klas Lindfors * YKPersonalization.pro: x86_64 for macx, that's what qt distributes. 2012-09-27 Klas Lindfors * YKPersonalization.pro: start with support for cross-compiling 2012-09-27 Klas Lindfors * YKPersonalization.pro: QMAKE_TARGET instead of QMAKE_HOST to find out the target 2012-09-27 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: new picture for 2.0 and 2.1 keys 2012-09-27 Klas Lindfors * installer/win-nsis/ykpers.nsi: correct \ instead of / 2012-09-27 Klas Lindfors * src/ui/settingpage.ui: move up help button 2012-09-27 Klas Lindfors * installer/win-nsis/ykpers.nsi: base for nsi installer 2012-09-27 Klas Lindfors * src/ui/settingpage.cpp: use another constructor to work with older qt 2012-09-26 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: add picture for 2.3 2012-09-26 Klas Lindfors * : update 2.2 picture 2012-09-26 Klas Lindfors * src/ui/settingpage.ui: shuffle things around on settingpage 2012-09-26 Klas Lindfors * src/ui/toolpage.ui: move boxes around on the toolpage 2012-09-26 Klas Lindfors * src/common.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/settingpage.cpp, src/ui/settingpage.ui: help for manual update 2012-09-26 Klas Lindfors * src/ui/settingpage.ui: line up help buttons 2012-09-26 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui: allow customer prefix to be entered in hex or modhex as well 2012-09-26 Klas Lindfors * src/ui/settingpage.ui: different wording on 2.3 features 2012-09-25 Klas Lindfors * src/ui/settingpage.ui, src/ui/toolpage.ui: move around some elements 2012-09-25 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp: new 2.2 key image 2012-09-25 Klas Lindfors * src/yubikeywriter.cpp: store the challenge in a QByteArray to be sure it isn't deallocated 2012-09-25 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui, src/yubikeywriter.cpp, src/yubikeywriter.h: ndef writing code 2012-09-25 Klas Lindfors * src/yubikeyfinder.cpp: neo has oath-hotp and imf from 2.1.7 2012-09-25 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp, src/yubikeyfinder.cpp, src/yubikeyfinder.h: image fixing. images for neo and devel key. use pngs. 2012-09-24 Klas Lindfors * src/ui/mainwindow.ui: remove empty buddy 2012-09-24 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeyfinder.h: more NEO support. add ability to exclude versions from feature_matrix 2012-09-24 Klas Lindfors * src/common.h: typo 2012-09-24 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/mainwindow.ui, src/yubikeyfinder.cpp, src/yubikeyfinder.h: show if the key supports Ndef 2012-09-24 Klas Lindfors * src/common.h, src/ui/aboutpage.cpp, src/ui/aboutpage.ui: add link to settings to main area in about. 2012-09-24 Klas Lindfors * src/common.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/settingpage.cpp, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeywriter.cpp: change updatable to allow update 2012-09-24 Klas Lindfors * src/common.h, src/ui/settingpage.cpp, src/ui/settingpage.ui, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeywriter.cpp: add FAST_TRIG and USE_NUMERIC_KEYPAD 2012-09-24 Klas Lindfors * src/common.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui: enable swapping configurations in UI. 2012-09-24 Klas Lindfors * src/ui/settingpage.ui, src/yubikeyconfig.h, src/yubikeylogger.cpp, src/yubikeywriter.cpp: support for slot swapping 2012-09-24 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui: controls for setting/disabling access code on update 2012-09-24 Klas Lindfors * src/ui/settingpage.cpp: messages on key update 2012-09-24 Klas Lindfors * src/ui/settingpage.cpp, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeywriter.cpp: support for dormant configuration 2012-09-24 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui: more stuff for doing key update 2012-09-24 Klas Lindfors * src/yubikeyconfig.h, src/yubikeylogger.cpp, src/yubikeywriter.cpp: add support for updating configuration 2012-09-24 Klas Lindfors * src/ui/chalresppage.cpp: chalresppage doesn't need QDesktopServices 2012-09-24 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui: make settingpage into several pages, start doing update stuff 2012-09-24 Klas Lindfors * src/ui/toolpage.h: toolpage doesn't need yubikeyconfig.h 2012-09-24 Klas Lindfors * src/common.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/settingpage.cpp, src/ui/settingpage.ui, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeywriter.cpp: add updatable flag 2012-09-24 Klas Lindfors * src/main.cpp, src/ui/settingpage.cpp: do all application setup in main.cpp 2012-09-24 Klas Lindfors * src/yubikeyconfig.cpp, src/yubikeywriter.cpp: use ykConfig object instead of settings do proper setup of ykConfig in constructor 2012-09-24 Klas Lindfors * src/yubikeyutil.cpp: mark as const 2012-09-24 Klas Lindfors * src/ui/settingpage.ui: move help button and remove tabstop 2012-09-24 Klas Lindfors * src/ui/toolpage.ui: update texts 2012-09-24 Klas Lindfors * src/ui/mainwindow.cpp, src/ui/mainwindow.ui, src/yubikeyfinder.cpp, src/yubikeyfinder.h: add support label for updatable 2012-09-24 Klas Lindfors * src/ui/settingpage.cpp, src/ui/settingpage.ui: make the settingspage autosave 2012-09-24 Klas Lindfors * src/ui/chalresppage.cpp, src/yubikeyfinder.cpp, src/yubikeyfinder.h: disable fixed hmac-sha1 challenge for 2.2 key 2012-09-24 Klas Lindfors * src/ui/mainwindow.cpp: clean up when key is removed 2012-09-21 Klas Lindfors * resources/resources.qrc, src/ui/mainwindow.cpp, src/ui/mainwindow.ui: show correct image for inserted yubikey some are animated, then build qmovie objects 2012-09-21 Klas Lindfors * src/ui/settingpage.cpp, src/version.h: add CompanyDomain to QCoreApplication 2012-09-21 Klas Lindfors * src/ui/settingpage.cpp: turn off SERIAL_USB_VISIBLE by default 2012-09-21 Klas Lindfors * src/yubikeywriter.cpp: no need to get status for challenge-response 2012-09-21 Klas Lindfors * src/yubikeyfinder.cpp, src/yubikeyfinder.h: State_Preset -> State_Present 2012-09-21 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h: only enable perform button when key is inserted 2012-09-21 Klas Lindfors * src/common.h, src/ui/toolpage.cpp: show status message when more options have to be selected 2012-09-21 Klas Lindfors * src/yubikeyfinder.cpp: do yk_init()/yk_release() in start/stop functions it should be a good idea to not do yk_init() for every openKey, this should make our use of libusb more consistent. 2012-09-21 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui, src/yubikeywriter.cpp: implement a tool feature for testing challenge-response in key 2012-09-21 Klas Lindfors * src/ui/aboutpage.ui, src/ui/chalresppage.ui, src/ui/mainwindow.ui, src/ui/oathpage.ui, src/ui/otppage.ui, src/ui/settingpage.ui, src/ui/staticpage.ui, src/ui/toolpage.ui: change green color to correct Yubico green 2012-09-21 Klas Lindfors * src/ui/toolpage.cpp, src/ui/toolpage.ui: activate the tool base page and add a backbutton to the converter page 2012-09-21 Klas Lindfors * src/yubikeywriter.cpp, src/yubikeywriter.h: add function for doing challenge-response 2012-09-19 Klas Lindfors * src/ui/oathpage.cpp, src/ui/oathpage.ui: trigger the editingFinished on imf when user edited 2012-09-19 Klas Lindfors * src/ui/oathpage.cpp, src/ui/oathpage.ui: let the reset button be enabled 2012-09-19 Klas Lindfors * src/ui/oathpage.cpp, src/yubikeyconfig.h: use int instead of short/char for oath imf, gives us larger span 2012-09-19 Klas Lindfors * src/yubikeywriter.cpp: check if ykp_set_oath_imf() fails, then throw. 2012-09-19 Klas Lindfors * src/yubikeywriter.cpp: don't bother with yk_core_config new (1.7) interface returns empty config 2012-09-19 Klas Lindfors * src/yubikeywriter.cpp: use ykp_set_oath_imf() instead of setting manually in config 2012-09-17 Klas Lindfors * src/common.h, src/ui/otppage.cpp, src/ui/otppage.ui: add a multi-option for pubid from serial 2012-09-17 Klas Lindfors * src/ui/otppage.cpp: spelling on debug output 2012-09-17 Klas Lindfors * src/ui/otppage.cpp, src/ui/otppage.h: build default public id on key serial 2012-09-17 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/oathpage.cpp, src/ui/otppage.cpp, src/ui/staticpage.cpp: spelling in debug messages 2012-09-17 Klas Lindfors * src/ui/otppage.cpp, src/ui/otppage.ui: private identity is a secret and should be randomized 2012-09-17 Klas Lindfors * src/ui/chalresppage.cpp, src/ui/chalresppage.ui: add static secret for multi hmac-sha1 chal-resp 2012-09-12 Klas Lindfors * src/ui/otppage.cpp, src/ui/otppage.ui: let the reset button be enabled, resets the form 2012-09-12 Klas Lindfors * src/yubikeywriter.cpp: updates for new api in ykpers 1.7 2012-09-12 Klas Lindfors * src/otpdef.h, src/ui/otppage.cpp: don't insert the 0x28 prefix before customer prefix 2012-09-12 Klas Lindfors * do-source-release.sh: check version in YKPersonalization.pro and src/version.h 2012-09-12 Klas Lindfors * YKPersonalization.pro: bump forgotten version number 2012-06-07 Klas Lindfors * NEWS, src/version.h: bump version post-release 2012-06-07 Klas Lindfors * NEWS: NEWS for 3.0.6 2012-06-07 Klas Lindfors * .gitignore: ignore deps and libs 2012-06-07 Klas Lindfors * README: describe how you get dependencies 2012-06-07 Klas Lindfors * do-source-release.sh: no need to remove dlls, removed from repo now 2012-06-07 Klas Lindfors * .gitignore: ignores ignore Makefile ignore src/ui/ui_*.h ignore build/ 2012-06-07 Klas Lindfors * deps/libusb-1.0/libusb.h, deps/libykpers/.gitignore, deps/libykpers/.gitmodules, deps/libykpers/AUTHORS, deps/libykpers/COPYING, deps/libykpers/Makefile.am, deps/libykpers/NEWS, deps/libykpers/README, deps/libykpers/configure.ac, deps/libykpers/contrib/README, deps/libykpers/contrib/programming.sh, deps/libykpers/libykpers-1.map, deps/libykpers/rfc4634/hmac.c, deps/libykpers/rfc4634/sha-private.h, deps/libykpers/rfc4634/sha.h, deps/libykpers/rfc4634/sha1.c, deps/libykpers/rfc4634/sha224-256.c, deps/libykpers/rfc4634/sha384-512.c, deps/libykpers/rfc4634/usha.c, deps/libykpers/tests/Makefile.am, deps/libykpers/tests/selftest.c, deps/libykpers/tests/test_args_to_config.c, deps/libykpers/tests/test_key_generation.c, deps/libykpers/ykchalresp.1, deps/libykpers/ykchalresp.c, deps/libykpers/ykcore/Makefile.am, deps/libykpers/ykcore/ykcore.c, deps/libykpers/ykcore/ykcore.h, deps/libykpers/ykcore/ykcore_backend.h, deps/libykpers/ykcore/ykcore_lcl.h, deps/libykpers/ykcore/ykcore_libusb-1.0.c, deps/libykpers/ykcore/ykcore_libusb.c, deps/libykpers/ykcore/ykcore_osx.c, deps/libykpers/ykcore/ykcore_stub.c, deps/libykpers/ykcore/ykcore_win32.c, deps/libykpers/ykcore/ykcore_windows.c, deps/libykpers/ykcore/ykdef.h, deps/libykpers/ykcore/ykstatus.c, deps/libykpers/ykcore/ykstatus.h, deps/libykpers/ykcore/yktsd.h, deps/libykpers/ykpbkdf2.c, deps/libykpers/ykpbkdf2.h, deps/libykpers/ykpers-1.pc.in, deps/libykpers/ykpers.c, deps/libykpers/ykpers.h, deps/libykpers/ykpers4win.mk, deps/libykpers/ykpersonalize.1, deps/libykpers/ykpersonalize.c, deps/libyubikey/AUTHORS, deps/libyubikey/COPYING, deps/libyubikey/ChangeLog, deps/libyubikey/INSTALL, deps/libyubikey/Makefile.am, deps/libyubikey/Makefile.in, deps/libyubikey/NEWS, deps/libyubikey/README, deps/libyubikey/THANKS, deps/libyubikey/aclocal.m4, deps/libyubikey/config.guess, deps/libyubikey/config.sub, deps/libyubikey/configure, deps/libyubikey/configure.ac, deps/libyubikey/depcomp, deps/libyubikey/install-sh, deps/libyubikey/libyubikey.map, deps/libyubikey/ltmain.sh, deps/libyubikey/m4/ld-version-script.m4, deps/libyubikey/m4/libtool.m4, deps/libyubikey/m4/ltoptions.m4, deps/libyubikey/m4/ltsugar.m4, deps/libyubikey/m4/ltversion.m4, deps/libyubikey/m4/lt~obsolete.m4, deps/libyubikey/missing, deps/libyubikey/modhex.c, deps/libyubikey/selftest.c, deps/libyubikey/simple.mk, deps/libyubikey/ykaes.c, deps/libyubikey/ykcrc.c, deps/libyubikey/ykgenerate.c, deps/libyubikey/ykhex.c, deps/libyubikey/ykmodhex.c, deps/libyubikey/ykparse.c, deps/libyubikey/yktoken.c, deps/libyubikey/yubikey.h: remove deps and libs, just copies from elsewhere, see README for how to get them. 2012-06-07 Klas Lindfors * .gitignore: ignore YKPersonalization.pro.user 2012-06-05 Simon Josefsson * COPYING, NEWS, src/common.h, src/crandom.cpp, src/crandom.h, src/main.cpp, src/otpdef.h, src/ui/aboutpage.cpp, src/ui/aboutpage.h, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/confirmbox.cpp, src/ui/confirmbox.h, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/scanedit.cpp, src/ui/scanedit.h, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/toolpage.cpp, src/ui/toolpage.h, src/version.h, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeylogger.cpp, src/yubikeylogger.h, src/yubikeyutil.cpp, src/yubikeyutil.h, src/yubikeywriter.cpp, src/yubikeywriter.h: Bump copyright years. 2012-06-05 Klas Lindfors * NEWS, src/version.h: bump versions post-release 2012-06-05 Klas Lindfors * NEWS, src/version.h: prepare version 3.0.5 2012-06-05 Klas Lindfors * do-source-release.sh: check if we've handled the NEWS file correctly 2012-06-05 Klas Lindfors * do-source-release.sh: create a ChangeLog with git2cl 2012-06-04 Klas Lindfors * NEWS: NEWS file 2012-06-04 Klas Lindfors * do-source-release.sh: add small script for doing release 2012-06-04 Klas Lindfors * : commit 8bfa06bc2955d5b31046138bc7eb192e57ec28b6 Author: Simon Josefsson Date: Mon Jun 4 15:04:03 2012 +0200 2012-06-04 Klas Lindfors * YKPersonalization.pro, src/version.h: bump versions post-release 2012-06-04 Klas Lindfors * YKPersonalization.pro, src/version.h: bump version to 3.0.3 for release 2012-06-01 Klas Lindfors * YKPersonalization.pro: add inheriting of flags 2012-06-01 Klas Lindfors * resources/lin/yubikey-personalization-gui.1: add man page for linux distribution 2012-05-31 Klas Lindfors * YKPersonalization.pro: add debian target for building with system linked deps 2012-05-31 Klas Lindfors * src/yubikeyfinder.h, src/yubikeywriter.h: includes for deps with <> 2012-05-10 Simon Josefsson * : Don't store libusb binary. 2012-05-10 Simon Josefsson * README: Add more info. Line wrap. 2012-05-10 Simon Josefsson * README: Mention dependencies. 2012-05-10 Simon Josefsson * COPYING, README: Add build instructions. 2011-11-28 Simon Josefsson * COPYING, README, YKPersonalization.pro, YKPersonalization.pro.user.lin, YKPersonalization.pro.user.mac, YKPersonalization.pro.user.win, deps/libusb-1.0/libusb.h, deps/libykpers/.gitignore, deps/libykpers/.gitmodules, deps/libykpers/AUTHORS, deps/libykpers/COPYING, deps/libykpers/Makefile.am, deps/libykpers/NEWS, deps/libykpers/README, deps/libykpers/configure.ac, deps/libykpers/contrib/README, deps/libykpers/contrib/programming.sh, deps/libykpers/libykpers-1.map, deps/libykpers/rfc4634/hmac.c, deps/libykpers/rfc4634/sha-private.h, deps/libykpers/rfc4634/sha.h, deps/libykpers/rfc4634/sha1.c, deps/libykpers/rfc4634/sha224-256.c, deps/libykpers/rfc4634/sha384-512.c, deps/libykpers/rfc4634/usha.c, deps/libykpers/tests/Makefile.am, deps/libykpers/tests/selftest.c, deps/libykpers/tests/test_args_to_config.c, deps/libykpers/tests/test_key_generation.c, deps/libykpers/ykchalresp.1, deps/libykpers/ykchalresp.c, deps/libykpers/ykcore/Makefile.am, deps/libykpers/ykcore/ykcore.c, deps/libykpers/ykcore/ykcore.h, deps/libykpers/ykcore/ykcore_backend.h, deps/libykpers/ykcore/ykcore_lcl.h, deps/libykpers/ykcore/ykcore_libusb-1.0.c, deps/libykpers/ykcore/ykcore_libusb.c, deps/libykpers/ykcore/ykcore_osx.c, deps/libykpers/ykcore/ykcore_stub.c, deps/libykpers/ykcore/ykcore_win32.c, deps/libykpers/ykcore/ykcore_windows.c, deps/libykpers/ykcore/ykdef.h, deps/libykpers/ykcore/ykstatus.c, deps/libykpers/ykcore/ykstatus.h, deps/libykpers/ykcore/yktsd.h, deps/libykpers/ykpbkdf2.c, deps/libykpers/ykpbkdf2.h, deps/libykpers/ykpers-1.pc.in, deps/libykpers/ykpers.c, deps/libykpers/ykpers.h, deps/libykpers/ykpers4win.mk, deps/libykpers/ykpersonalize.1, deps/libykpers/ykpersonalize.c, deps/libyubikey/AUTHORS, deps/libyubikey/COPYING, deps/libyubikey/ChangeLog, deps/libyubikey/INSTALL, deps/libyubikey/Makefile.am, deps/libyubikey/Makefile.in, deps/libyubikey/NEWS, deps/libyubikey/README, deps/libyubikey/THANKS, deps/libyubikey/aclocal.m4, deps/libyubikey/config.guess, deps/libyubikey/config.sub, deps/libyubikey/configure, deps/libyubikey/configure.ac, deps/libyubikey/depcomp, deps/libyubikey/install-sh, deps/libyubikey/libyubikey.map, deps/libyubikey/ltmain.sh, deps/libyubikey/m4/ld-version-script.m4, deps/libyubikey/m4/libtool.m4, deps/libyubikey/m4/ltoptions.m4, deps/libyubikey/m4/ltsugar.m4, deps/libyubikey/m4/ltversion.m4, deps/libyubikey/m4/lt~obsolete.m4, deps/libyubikey/missing, deps/libyubikey/modhex.c, deps/libyubikey/selftest.c, deps/libyubikey/simple.mk, deps/libyubikey/ykaes.c, deps/libyubikey/ykcrc.c, deps/libyubikey/ykgenerate.c, deps/libyubikey/ykhex.c, deps/libyubikey/ykmodhex.c, deps/libyubikey/ykparse.c, deps/libyubikey/yktoken.c, deps/libyubikey/yubikey.h, installer/win32/Installer.sln, installer/win32/Installer/Installer.vdproj, resources/lin/YubiKey Personalization Tool.sh, resources/mac/Info.plist.in, resources/resources.qrc, resources/win/resources.rc, src/common.h, src/crandom.cpp, src/crandom.h, src/main.cpp, src/otpdef.h, src/ui/aboutpage.cpp, src/ui/aboutpage.h, src/ui/aboutpage.ui, src/ui/chalresppage.cpp, src/ui/chalresppage.h, src/ui/chalresppage.ui, src/ui/confirmbox.cpp, src/ui/confirmbox.h, src/ui/confirmbox.ui, src/ui/helpbox.cpp, src/ui/helpbox.h, src/ui/helpbox.ui, src/ui/mainwindow.cpp, src/ui/mainwindow.h, src/ui/mainwindow.ui, src/ui/oathpage.cpp, src/ui/oathpage.h, src/ui/oathpage.ui, src/ui/otppage.cpp, src/ui/otppage.h, src/ui/otppage.ui, src/ui/scanedit.cpp, src/ui/scanedit.h, src/ui/settingpage.cpp, src/ui/settingpage.h, src/ui/settingpage.ui, src/ui/staticpage.cpp, src/ui/staticpage.h, src/ui/staticpage.ui, src/ui/toolpage.cpp, src/ui/toolpage.h, src/ui/toolpage.ui, src/version.h, src/yubikeyconfig.cpp, src/yubikeyconfig.h, src/yubikeyfinder.cpp, src/yubikeyfinder.h, src/yubikeylogger.cpp, src/yubikeylogger.h, src/yubikeyutil.cpp, src/yubikeyutil.h, src/yubikeywriter.cpp, src/yubikeywriter.h: Initial import. 2011-11-28 Simon Josefsson * README: test 2011-11-28 Simon Josefsson * README: typo 2011-11-25 Simon Josefsson * Add. yubikey-personalization-gui-3.1.24/README.binary_dists0000664000175000017500000000117612642452141021312 0ustar klasklasThese are good-to-have qmake invocations for windows and osx binary distributions: windows cross compiled with installer and signed binaries: $ TARGET_ARCH=i686-w64-mingw32 QTDIR=$win_qt_location SPC_FILE=$spc_file PVK_FILE=$pvk_file qmake -spec win32-g++-4.6 "CONFIG+= cross build_installer sign_binaries" os x native compile with installer and signed binaries: $ qmake -spec macx-llvm "CONFIG += build_installer release" os x cross compiled, just application: TARGET_ARCH=x86_64-apple-darwin11 OSX_SDK=$sdk_location QT_LIBDIR=$qt_library_frameworks_location QT_PLUGINDIR=$qt_plugins_location qmake -spec macx-g++42 "CONFIG += cross" yubikey-personalization-gui-3.1.24/do-source-release.sh0000775000175000017500000000261712642452141021617 0ustar klasklas#!/bin/sh set -e VERSION=$1 PGP_KEYID=$2 if [ "x$PGP_KEYID" = "x" ]; then echo "try with $0 VERSION PGP_KEYID" echo "example: $0 3.0.4 9D1C0E79" exit fi if ! head -3 NEWS | grep -q "Version $VERSION .released `date -I`"; then echo "You need to update date/version in NEWS" exit fi if ! head -10 src/src.pro | grep -q "VERSION_MAJOR.*= `echo $VERSION | cut -d. -f1`"; then echo "You need to update version in src/src.pro" exit fi if ! head -10 src/src.pro | grep -q "VERSION_MINOR.*= `echo $VERSION | cut -d. -f2`"; then echo "You need to update version in src/src.pro" exit fi if ! head -10 src/src.pro | grep -q "VERSION_BUILD.*= `echo $VERSION | cut -d. -f3`"; then echo "You need to update version in src/src.pro" exit fi if [ "x$YUBICO_GITHUB_REPO" = "x" ]; then echo "you need to define YUBICO_GITHUB_REPO" exit fi releasename=yubikey-personalization-gui-${VERSION} git push git tag -u ${PGP_KEYID}! -m $VERSION $releasename git push --tags tmpdir=`mktemp -d /tmp/release.XXXXXX` releasedir=${tmpdir}/${releasename} mkdir -p $releasedir git archive $releasename --format=tar | tar -xC $releasedir git2cl > $releasedir/ChangeLog tar -cz --directory=$tmpdir --file=${releasename}.tar.gz $releasename gpg --detach-sign --default-key $PGP_KEYID ${releasename}.tar.gz $YUBICO_GITHUB_REPO/publish yubikey-personalization-gui $VERSION ${releasename}.tar.gz* rm -rf $tmpdir rm -rf $stagedir yubikey-personalization-gui-3.1.24/tests/0000775000175000017500000000000012642452141017076 5ustar klasklasyubikey-personalization-gui-3.1.24/tests/yubikeyutiltest.h0000664000175000017500000000355712642452141022540 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include class TestYubikeyUtil : public QObject { Q_OBJECT private slots: void testHexDecode(); void testHexEncode(); void testModhexDecode(); void testModhexEncode(); void testGetNextHex1(); void testGetNextHex2(); void testGetNextHex3(); void testGetNextHex4(); void testGetNextHexRand(); void testGetNextModhex1(); void testGetNextModhex2(); void testGetNextModhex3(); void testGetNextModhex4(); void testGetNextModhex5(); void testGetNextModhexRand(); void testGenerateRandomHex(); void testGenerateRandomModhex(); }; yubikey-personalization-gui-3.1.24/tests/scanedittest.cpp0000664000175000017500000000365412642452141022304 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include "scanedittest.h" #include "us-scanedit.h" void TestScanEdit::testCharacters() { ScanEdit edit = UsScanEdit(); QString characters = "abcdefghijklmnopqrstuvwxyz1234567890\\n\\t -=[]\\\\;'`,./"; QString scancodes = edit.textToScanCodes(characters); QString result = edit.scanCodesToText(scancodes); QCOMPARE(result, characters); } void TestScanEdit::testCharacters2() { ScanEdit edit = UsScanEdit(); QString characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+{}|:\"~<>?"; QString scancodes = edit.textToScanCodes(characters); QString result = edit.scanCodesToText(scancodes); QCOMPARE(result, characters); } yubikey-personalization-gui-3.1.24/tests/scanedittest.h0000664000175000017500000000270012642452141021740 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include class TestScanEdit : public QObject { Q_OBJECT private slots: void testCharacters(); void testCharacters2(); }; yubikey-personalization-gui-3.1.24/tests/yubikeyutiltest.cpp0000664000175000017500000001045012642452141023061 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include "yubikeyutiltest.h" #include "yubikeyutil.h" void TestYubikeyUtil::testHexDecode() { unsigned char result[3]; size_t len = 3; unsigned char expect[] = "foo"; YubiKeyUtil::qstrHexDecode(result, &len, QString("666f6f")); QVERIFY(memcmp(expect, result, 3) == 0); } void TestYubikeyUtil::testHexEncode() { unsigned char string[] = "foo"; QString result = YubiKeyUtil::qstrHexEncode(string, 3); QCOMPARE(result, QString("666f6f")); } void TestYubikeyUtil::testModhexDecode() { unsigned char result[3]; size_t len = 3; unsigned char expect[] = "foo"; YubiKeyUtil::qstrModhexDecode(result, &len, QString("hhhvhv")); QVERIFY(memcmp(expect, result, 3) == 0); } void TestYubikeyUtil::testModhexEncode() { unsigned char string[] = "foo"; QString result = YubiKeyUtil::qstrModhexEncode(string, 3); QCOMPARE(result, QString("hhhvhv")); } void TestYubikeyUtil::testGetNextHex1() { QString result = YubiKeyUtil::getNextHex(6, "000000", GEN_SCHEME_INCR); QCOMPARE(result, QString("000001")); } void TestYubikeyUtil::testGetNextHex2() { QString result = YubiKeyUtil::getNextHex(6, "0fffff", GEN_SCHEME_INCR); QCOMPARE(result, QString("100000")); } void TestYubikeyUtil::testGetNextHex3() { QString result = YubiKeyUtil::getNextHex(6, "ffffff", GEN_SCHEME_INCR); QCOMPARE(result, QString("000000")); } void TestYubikeyUtil::testGetNextHex4() { QString result = YubiKeyUtil::getNextHex(6, " 1 fff f f ", GEN_SCHEME_INCR); QCOMPARE(result, QString("200000")); } void TestYubikeyUtil::testGetNextHexRand() { QString result = YubiKeyUtil::getNextHex(6, "cccccc", GEN_SCHEME_RAND); QVERIFY(result != ""); } void TestYubikeyUtil::testGetNextModhex1() { QString result = YubiKeyUtil::getNextModhex(6, "cccccc", GEN_SCHEME_INCR); QCOMPARE(result, QString("cccccb")); } void TestYubikeyUtil::testGetNextModhex2() { QString result = YubiKeyUtil::getNextModhex(6, "cvvvvv", GEN_SCHEME_INCR); QCOMPARE(result, QString("bccccc")); } void TestYubikeyUtil::testGetNextModhex3() { QString result = YubiKeyUtil::getNextModhex(6, "vvvvvv", GEN_SCHEME_INCR); QCOMPARE(result, QString("cccccc")); } void TestYubikeyUtil::testGetNextModhex4() { QString result = YubiKeyUtil::getNextModhex(6, "vvvvv", GEN_SCHEME_INCR); QCOMPARE(result, QString("vvvvvb")); } void TestYubikeyUtil::testGetNextModhex5() { QString result = YubiKeyUtil::getNextModhex(6, " cc cc cc ", GEN_SCHEME_INCR); QCOMPARE(result, QString("cccccb")); } void TestYubikeyUtil::testGetNextModhexRand() { QString result = YubiKeyUtil::getNextModhex(6, "bbbbbb", GEN_SCHEME_RAND); QVERIFY(result != ""); } void TestYubikeyUtil::testGenerateRandomHex() { QString first = YubiKeyUtil::generateRandomHex(16); QString second = YubiKeyUtil::generateRandomHex(16); QVERIFY(first != second); } void TestYubikeyUtil::testGenerateRandomModhex() { QString first = YubiKeyUtil::generateRandomModhex(16); QString second = YubiKeyUtil::generateRandomModhex(16); QVERIFY(first != second); } yubikey-personalization-gui-3.1.24/tests/test.cpp0000664000175000017500000000057712642452141020572 0ustar klasklas#include "scanedittest.h" #include "yubikeyutiltest.h" #include "versiontest.h" int main(int argc, char** argv) { int status = 0; TestScanEdit scanEdit; TestYubikeyUtil yubikeyUtil; TestVersion version; status |= QTest::qExec(&scanEdit, argc, argv); status |= QTest::qExec(&yubikeyUtil, argc, argv); status |= QTest::qExec(&version, argc, argv); return status; } yubikey-personalization-gui-3.1.24/tests/versiontest.h0000664000175000017500000000264312642452141021641 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include class TestVersion : public QObject { Q_OBJECT private slots: void testVersions(); }; yubikey-personalization-gui-3.1.24/tests/tests.pro0000664000175000017500000000460512642452141020767 0ustar klasklasQT += testlib QT -= gui SOURCES += test.cpp scanedittest.cpp yubikeyutiltest.cpp versiontest.cpp HEADERS += scanedittest.h yubikeyutiltest.h versiontest.h CONFIG += testcase no_testcase_installs CONFIG += console CONFIG -= app_bundle INCLUDEPATH += ../lib !nosilent { CONFIG += silent } CONFIG(debug, debug|release) { TARGET_DIR = ..$${DIR_SEPARATOR}build$${DIR_SEPARATOR}debug CONFIG += console no_lflags_merge LIBS += $$quote(-L../lib/debug) -llib } else { TARGET_DIR = ..$${DIR_SEPARATOR}build$${DIR_SEPARATOR}release DEFINES += QT_NO_DEBUG_OUTPUT LIBS += $$quote(-L../lib/release) -llib } DESTDIR = "$$TARGET_DIR" QMAKE_CXXFLAGS += $$CXXFLAGS $$CPPFLAGS QMAKE_LFLAGS += $$LDFLAGS cross { message("Doing a cross platform build..") # pickup compiler from environment isEmpty(TARGET_ARCH) { error("Cross compiling without a target is completely invalid, set TARGET_ARCH") } QMAKE_CC = $${TARGET_ARCH}-gcc QMAKE_CXX = $${TARGET_ARCH}-g++ QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_C = $$QMAKE_CC win32 { QMAKE_LIB = $${TARGET_ARCH}-ar -ru QMAKE_RC = $${TARGET_ARCH}-windres $$quote(-DVERSION_WIN_STR=\'\\\"$${VERSION}\\0\\\"\') QMAKE_MOC = $$[QT_INSTALL_BINS]/moc QMAKE_UIC = $$[QT_INSTALL_BINS]/uic QMAKE_IDC = $$[QT_INSTALL_BINS]/idc QMAKE_RCC = $$[QT_INSTALL_BINS]/rcc QMAKE_LFLAGS += -static-libstdc++ -static-libgcc } !isEmpty (QTDIR) { _QT_INCDIR = $${QTDIR}$${DIR_SEPARATOR}include _QT_LIBDIR = $${QTDIR}$${DIR_SEPARATOR}lib _QT_BINDIR = $${QTDIR}$${DIR_SEPARATOR}bin _QT_PLUGINDIR = $${QTDIR}$${DIR_SEPARATOR}plugins } else { _QT_INCDIR = $$(QT_INCDIR) _QT_LIBDIR = $$(QT_LIBDIR) _QT_BINDIR = $$(QT_BINDIR) _QT_PLUGINDIR = $$(QT_PLUGINDIR) } !isEmpty (_QT_INCDIR) { QMAKE_INCDIR_QT = $$_QT_INCDIR } !isEmpty (_QT_LIBDIR) { QMAKE_LIBDIR_QT = $$_QT_LIBDIR } } unix:!macx|force_pkgconfig { LIBS += -lyubikey } macx:!force_pkgconfig { INCLUDEPATH += libs/macx/include LIBS += ../libs/macx/lib/libyubikey.dylib } win32 { LIBS += $$quote(-L$$_QT_BINDIR) $$quote(-L$$_QT_LIBDIR) !contains(QMAKE_TARGET.arch, x86_64) { LIBS += $$quote(-L../libs/win32/bin) -llibyubikey-0 } else { LIBS += $$quote(-L../libs/win64/bin) -llibyubikey-0 } } yubikey-personalization-gui-3.1.24/tests/versiontest.cpp0000664000175000017500000000320412642452141022166 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include "versiontest.h" #include "common.h" void TestVersion::testVersions() { QVERIFY(YK_VERSION(2,2,3) < YK_VERSION(2,2,4)); QVERIFY(YK_VERSION(0,9,9) < YK_VERSION(1,3,0)); QVERIFY(YK_VERSION(3,0,0) < YK_VERSION(4,0,0)); QVERIFY(YK_VERSION(2,99,99) < YK_VERSION(3,0,0)); QVERIFY(YK_VERSION(4,1,10) < YK_VERSION(4,2,0)); } yubikey-personalization-gui-3.1.24/prepare-travis.sh0000775000175000017500000000103512642452141021236 0ustar klasklas#!/bin/sh set -e set -x if [ "x$TRAVIS_OS_NAME" != "xosx" ]; then sudo add-apt-repository -y ppa:yubico/stable sudo apt-get update -qq sudo apt-get install -qq -y --no-install-recommends libyubikey-dev libykpers-1-dev qt4-qmake libqt4-dev QMAKE=qmake else brew update brew install qt5 brew install libyubikey brew install ykpers QMAKE=/usr/local/opt/qt5/bin/qmake CXXFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" fi $QMAKE 'CONFIG += debug nosilent force_pkgconfig' "CXXFLAGS=$CXXFLAGS" "LDFLAGS=$LDFLAGS" yubikey-personalization-gui-3.1.24/README.adoc0000777000175000017500000000000012642452141020374 2READMEustar klasklasyubikey-personalization-gui-3.1.24/YKPersonalization.pro0000664000175000017500000000025012642452141022100 0ustar klasklasTEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ lib \ src \ tests src.depends = lib tests.depends = lib QMAKE_CLEAN += src/Makefile tests/Makefile lib/Makefile yubikey-personalization-gui-3.1.24/README0000664000175000017500000000766612642452141016633 0ustar klasklasQt based Cross-Platform YubiKey Personalization Tool ==================================================== See the file COPYING for copyright and license statement. Introduction ------------ The YubiKey Personalization Tool is a Qt based Cross-Platform utility designed to facilitate re-configuration of YubiKeys on Windows, Linux and Mac platforms. The tool provides a same simple step-by-step approach to make configuration of YubiKeys easy to follow and understand, while still being powerful enough to exploit all functionality both of the YubiKey 1 and YubiKey 2 generation of keys. The tool provides the same functionality and user interface on Windows, Linux and Mac platforms. The Cross-Platform YubiKey Personalization Tool provides the following main functions: * Programming the YubiKey in "Yubico OTP" mode * Programming the YubiKey in "OATH-HOTP" mode * Programming the YubiKey in "Static Password" mode * Programming the YubiKey in "Challenge-Response" mode * Programming the NDEF feature of the YubiKey NEO * Testing the challenge-response functionality of a YubiKey * Deleting the configuration of a YubiKey * Checking type and firmware version of the YubiKey Building from Git ----------------- You may check out the sources using Git with the following command: ----------- $ git clone git://github.com/Yubico/yubikey-personalization-gui.git ----------- This will create a directory 'yubikey-personalization-gui'. Enter the directory: ----------- $ cd yubikey-personalization-gui ----------- Dependencies ------------ yubikey-personalization-gui depends on version 1.14.0 or higher of libykpers. When building on Windows and mac you will need a binary build of https://developers.yubico.com/yubikey-personalization[yubikey-personalization], the contents should then be places in libs/win32, libs/win64 and libs/macx respectively. For building on linux pkg-config is used to find these dependencies. ----------- $ sudo apt-get install libusb-1.0-0-dev qt4-qmake libykpers-1-dev \ libyubikey-dev libqt4-dev ----------- Command-line build ------------------ Run these commands: ----------- $ qmake && make ----------- Cross Compiling from Linux -------------------------- The project can be cross compiled from linux for OS X and Windows. As a first step you need a cross-compiler chain for that OS, for windows you want mingw-w64. Then you need unpacked http://qt-project.org[Qt binaries] for that platform. You can then do (for Windows): TARGET_ARCH=i686-w64-mingw32 QTDIR= qmake \ -spec win32-g++-4.6 "CONFIG+=cross" To build installers you can add build_installer to the CONFIG variable for qmake. This requires makensis to be in path for windows and genisoimage and dmg (from libhfs-dmg) for Mac. Opening the project in Qt designer ---------------------------------- Locate the qtcreator executable file and click on it to open the Qt Designer. To open the project in Qt Designer, select 'File' > 'Open File or Project' from the tool bar, navigate to the project folder, select YKPersonalisation.pro file and click on the 'Open' button. To set the path of the 'Build' diractory select 'Projects' > 'Build Settings' Browse project folder path. Building -------- To generate the build system, select 'Build' > "Clean Project YKPersonalization" option from the tool bar. Then select 'Build' > 'Run qmake' option from the tool bar. To build the project, select 'Build' > 'Build Project YKPersonalization' option from the tool bar. Based on your platform, the successful build will create a 'YubiKey Personalization Tool' executable file into the respective build folder. The build creates a `YKPersonalization.exe` file on Windows, `YubiKey Personalization Tool.sh` file on Linux and `YubiKey Personalization Tool.app` file on Mac. Example on Linux: To run the YubiKey Personalization Tool, open the command shell and execute the following command: [source, sh] ----------- $ build/release/yubikey-personalization-gui ----------- yubikey-personalization-gui-3.1.24/lib/0000775000175000017500000000000012642452141016502 5ustar klasklasyubikey-personalization-gui-3.1.24/lib/yubikeyutil.cpp0000664000175000017500000002274712642452141021601 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "yubikeyutil.h" #include #include #include #ifdef Q_OS_WIN #include "crandom.h" #endif YubiKeyUtil::~YubiKeyUtil() { } int YubiKeyUtil::hexModhexDecode(unsigned char *result, size_t *resultLen, const char *str, size_t strLen, size_t minSize, size_t maxSize, bool modhex) { if ((strLen % 2 != 0) || (strLen < minSize) || (strLen > maxSize)) { *resultLen = 0; return -1; } *resultLen = strLen / 2; if (modhex) { if (yubikey_modhex_p(str)) { yubikey_modhex_decode((char *)result, str, *resultLen); return 1; } } else { if (yubikey_hex_p(str)) { yubikey_hex_decode((char *)result, str, *resultLen); return 1; } } return 0; } int YubiKeyUtil::hexModhexEncode(char *result, size_t *resultLen, const unsigned char *str, size_t strLen, bool modhex) { *resultLen = strLen * 2; if (modhex) { yubikey_modhex_encode((char *)result, (char *)str, strLen); return 1; } else { yubikey_hex_encode((char *)result, (char *)str, strLen); return 1; } return 0; } QString YubiKeyUtil::qstrHexEncode(const unsigned char *str, size_t strLen) { char result[strLen * 2 + 1]; size_t resultLen; memset(&result, 0, sizeof(result)); int rc = hexModhexEncode(result, &resultLen, str, strLen, false); if(rc > 0) { qDebug() << "hex encoded string: " << QString(result) << sizeof(result); return QString::fromLocal8Bit(result); } return QString(""); } void YubiKeyUtil::qstrHexDecode(unsigned char *result, size_t *resultLen, const QString &str) { if(str.size() % 2 != 0) { return; } char hex[MAX_SIZE]; YubiKeyUtil::qstrToRaw(hex, sizeof(hex), str); size_t hexLen = strlen(hex); //Hex decode hexModhexDecode(result, resultLen, hex, hexLen, 0, MAX_SIZE, false); } QString YubiKeyUtil::qstrModhexEncode(const unsigned char *str, size_t strLen) { char result[strLen * 2 + 1]; size_t resultLen; memset(&result, 0, sizeof(result)); int rc = hexModhexEncode(result, &resultLen, str, strLen, true); if(rc > 0) { qDebug() << "modhex encoded string: " << QString(result) << sizeof(result); return QString::fromLocal8Bit(result); } return QString(""); } void YubiKeyUtil::qstrModhexDecode(unsigned char *result, size_t *resultLen, const QString &str) { if(str.size() % 2 != 0) { *resultLen = 0; return; } char modhex[MAX_SIZE]; YubiKeyUtil::qstrToRaw(modhex, sizeof(modhex), str); size_t modhexLen = strlen(modhex); //Hex decode hexModhexDecode(result, resultLen, modhex, modhexLen, 0, MAX_SIZE, true); } void YubiKeyUtil::qstrDecDecode(unsigned char *result, size_t *resultLen, const QString &str) { if(str.size() % 2 != 0) { *resultLen = 0; return; } *resultLen = str.size() / 2; for(size_t i = 0; i < *resultLen; i++) { unsigned char val = str.mid(i * 2, 2).toInt(); result[i] = ((val / 10) << 4) | (val % 10); } } void YubiKeyUtil::qstrToRaw(char *result, size_t resultLen, const QString &str) { QByteArray strByteArr = str.toLocal8Bit(); size_t strLen = strByteArr.size() + 1; strLen = (resultLen < strLen)? resultLen : strLen; memset(result, 0, strLen); strncpy(result, (char *) strByteArr.data(), strLen); } void YubiKeyUtil::qstrClean(QString *str, size_t maxSize, bool reverse) { *str = str->toLower(); QRegExp rx("[^0-9a-f]"); *str = str->replace(rx, QString("")); if(maxSize > 0) { if(reverse) { *str = str->rightJustified(maxSize, '0', true); } else { *str = str->leftJustified(maxSize, '0', true); } } } void YubiKeyUtil::qstrModhexClean(QString *str, size_t maxSize, bool reverse) { *str = str->toLower(); QRegExp rx("[^b-lnrt-v]"); *str = str->replace(rx, QString("")); if(maxSize > 0) { if(reverse) { *str = str->rightJustified(maxSize, 'c', true); } else { *str = str->leftJustified(maxSize, 'c', true); } } } int YubiKeyUtil::generateRandom(unsigned char *result, size_t resultLen) { size_t bufSize = resultLen; unsigned char buf[bufSize]; memset(&buf, 0, sizeof(buf)); size_t bufLen = 0; #ifdef Q_OS_WIN CRandom random; random.getRand(buf, bufSize); bufLen = sizeof(buf); #else const char *random_places[] = { "/dev/srandom", "/dev/urandom", "/dev/random", 0 }; const char **random_place; for (random_place = random_places; *random_place; random_place++) { FILE *random_file = fopen(*random_place, "r"); if (random_file) { size_t read_bytes = 0; while (read_bytes < bufSize) { size_t n = fread(&buf[read_bytes], 1, bufSize - read_bytes, random_file); read_bytes += n; } fclose(random_file); bufLen = sizeof(buf); break; /* from for loop */ } } #endif if(bufLen > 0) { memcpy(result, buf, bufLen); return 1; } return 0; } QString YubiKeyUtil::generateRandomHex(size_t resultLen) { QString result(""); if (resultLen % 2 != 0) { return result; } size_t bufSize = resultLen / 2; unsigned char buf[bufSize]; memset(&buf, 0, sizeof(buf)); if(generateRandom(buf, bufSize) > 0) { result = qstrHexEncode(buf, bufSize); } return result; } QString YubiKeyUtil::generateRandomModhex(size_t resultLen) { QString result(""); if (resultLen % 2 != 0) { return result; } size_t bufSize = resultLen / 2; unsigned char buf[bufSize]; memset(&buf, 0, sizeof(buf)); if(generateRandom(buf, bufSize) > 0) { result = qstrModhexEncode(buf, bufSize); } return result; } QString YubiKeyUtil::getNextHex(size_t resultLen, const QString &str, int scheme) { QString result(""); qDebug() << "str = " << str << " len = " << str.length(); switch(scheme) { case GEN_SCHEME_FIXED: result = str; break; case GEN_SCHEME_INCR: { //Hex clean QString hexStr(str); qstrClean(&hexStr, resultLen); //Hex decode unsigned char hexDecoded[MAX_SIZE]; size_t hexDecodedLen = 0; memset(&hexDecoded, 0, sizeof(hexDecoded)); qstrHexDecode(hexDecoded, &hexDecodedLen, hexStr); if(hexDecodedLen <= 0) { break; } qDebug() << "hexDecoded = " << QString((char*)hexDecoded) << " len = " << hexDecodedLen; //Increment for (int i = hexDecodedLen; i--; ) { if (++hexDecoded[i]) { break; } } //Hex encode result = qstrHexEncode(hexDecoded, hexDecodedLen); qDebug() << "hexEncoded = " << result << " len = " << result.size(); } break; case GEN_SCHEME_RAND: result = generateRandomHex(resultLen); break; } return result; } QString YubiKeyUtil::getNextModhex(size_t resultLen, const QString &str, int scheme) { QString tmpStr(str); qstrModhexClean(&tmpStr, resultLen); unsigned char result[resultLen]; size_t len; QString hex; qstrModhexDecode(result, &len, tmpStr); if(len == 0) { return ""; } hex = qstrHexEncode(result, len); hex = getNextHex(resultLen, hex, scheme); qstrHexDecode(result, &len, hex); return qstrModhexEncode(result, len); } yubikey-personalization-gui-3.1.24/lib/us-scanedit.cpp0000664000175000017500000001310012642452141021420 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include "us-scanedit.h" #define SHIFT 0x80 UsScanEdit::UsScanEdit() { keyMap = QMap(); keyMap[0x00] = 0; keyMap[0x01] = 0; keyMap[0x02] = 0; keyMap[0x03] = 0; keyMap[0x04] = 0; keyMap[0x05] = 0; keyMap[0x06] = 0; keyMap[0x07] = 0; keyMap[0x08] = 0; keyMap[0x09] = 0x2b; /* \t */ keyMap[0x0a] = 0x28; /* \n */ keyMap[0x0b] = 0; keyMap[0x0c] = 0; keyMap[0x0d] = 0; keyMap[0x0e] = 0; keyMap[0x0f] = 0; keyMap[0x10] = 0; keyMap[0x11] = 0; keyMap[0x12] = 0; keyMap[0x13] = 0; keyMap[0x14] = 0; keyMap[0x15] = 0; keyMap[0x16] = 0; keyMap[0x17] = 0; keyMap[0x18] = 0; keyMap[0x19] = 0; keyMap[0x1a] = 0; keyMap[0x1b] = 0; keyMap[0x1c] = 0; keyMap[0x1d] = 0; keyMap[0x1e] = 0; keyMap[0x1f] = 0; keyMap[0x20] = 0x2c; /* */ keyMap[0x21] = 0x1e | SHIFT; /* ! */ keyMap[0x22] = 0x34 | SHIFT; /* " */ keyMap[0x23] = 0x20 | SHIFT; /* # */ keyMap[0x24] = 0x21 | SHIFT; /* $ */ keyMap[0x25] = 0x22 | SHIFT; /* % */ keyMap[0x26] = 0x24 | SHIFT; /* & */ keyMap[0x27] = 0x34; /* ' */ keyMap[0x28] = 0x26 | SHIFT; /* ( */ keyMap[0x29] = 0x27 | SHIFT; /* ) */ keyMap[0x2a] = 0x25 | SHIFT; /* * */ keyMap[0x2b] = 0x2e | SHIFT; /* + */ keyMap[0x2c] = 0x36; /* , */ keyMap[0x2d] = 0x2d; /* - */ keyMap[0x2e] = 0x37; /* . */ keyMap[0x2f] = 0x38; /* / */ keyMap[0x30] = 0x27; /* 0 */ keyMap[0x31] = 0x1e; /* 1 */ keyMap[0x32] = 0x1f; /* 2 */ keyMap[0x33] = 0x20; /* 3 */ keyMap[0x34] = 0x21; /* 4 */ keyMap[0x35] = 0x22; /* 5 */ keyMap[0x36] = 0x23; /* 6 */ keyMap[0x37] = 0x24; /* 7 */ keyMap[0x38] = 0x25; /* 8 */ keyMap[0x39] = 0x26; /* 9 */ keyMap[0x3a] = 0x33 | SHIFT; /* : */ keyMap[0x3b] = 0x33; /* ; */ keyMap[0x3c] = 0x36 | SHIFT; /* < */ keyMap[0x3d] = 0x2e; /* = */ keyMap[0x3e] = 0x37 | SHIFT; /* > */ keyMap[0x3f] = 0x38 | SHIFT; /* ? */ keyMap[0x40] = 0x1f | SHIFT; /* @ */ keyMap[0x41] = 0x04 | SHIFT; /* A */ keyMap[0x42] = 0x05 | SHIFT; /* B */ keyMap[0x43] = 0x06 | SHIFT; /* C */ keyMap[0x44] = 0x07 | SHIFT; /* D */ keyMap[0x45] = 0x08 | SHIFT; /* E */ keyMap[0x46] = 0x09 | SHIFT; /* F */ keyMap[0x47] = 0x0a | SHIFT; /* G */ keyMap[0x48] = 0x0b | SHIFT; /* H */ keyMap[0x49] = 0x0c | SHIFT; /* I */ keyMap[0x4a] = 0x0d | SHIFT; /* J */ keyMap[0x4b] = 0x0e | SHIFT; /* K */ keyMap[0x4c] = 0x0f | SHIFT; /* L */ keyMap[0x4d] = 0x10 | SHIFT; /* M */ keyMap[0x4e] = 0x11 | SHIFT; /* N */ keyMap[0x4f] = 0x12 | SHIFT; /* O */ keyMap[0x50] = 0x13 | SHIFT; /* P */ keyMap[0x51] = 0x14 | SHIFT; /* Q */ keyMap[0x52] = 0x15 | SHIFT; /* R */ keyMap[0x53] = 0x16 | SHIFT; /* S */ keyMap[0x54] = 0x17 | SHIFT; /* T */ keyMap[0x55] = 0x18 | SHIFT; /* U */ keyMap[0x56] = 0x19 | SHIFT; /* V */ keyMap[0x57] = 0x1a | SHIFT; /* W */ keyMap[0x58] = 0x1b | SHIFT; /* X */ keyMap[0x59] = 0x1c | SHIFT; /* Y */ keyMap[0x5a] = 0x1d | SHIFT; /* Z */ keyMap[0x5b] = 0x2f; /* [ */ keyMap[0x5c] = 0x32; /* \ */ keyMap[0x5d] = 0x30; /* ] */ keyMap[0x5e] = 0x23 | SHIFT; /* ^ */ keyMap[0x5f] = 0x2d | SHIFT; /* _ */ keyMap[0x60] = 0x35; /* ` */ keyMap[0x61] = 0x04; /* a */ keyMap[0x62] = 0x05; /* b */ keyMap[0x63] = 0x06; /* c */ keyMap[0x64] = 0x07; /* d */ keyMap[0x65] = 0x08; /* e */ keyMap[0x66] = 0x09; /* f */ keyMap[0x67] = 0x0a; /* g */ keyMap[0x68] = 0x0b; /* h */ keyMap[0x69] = 0x0c; /* i */ keyMap[0x6a] = 0x0d; /* j */ keyMap[0x6b] = 0x0e; /* k */ keyMap[0x6c] = 0x0f; /* l */ keyMap[0x6d] = 0x10; /* m */ keyMap[0x6e] = 0x11; /* n */ keyMap[0x6f] = 0x12; /* o */ keyMap[0x70] = 0x13; /* p */ keyMap[0x71] = 0x14; /* q */ keyMap[0x72] = 0x15; /* r */ keyMap[0x73] = 0x16; /* s */ keyMap[0x74] = 0x17; /* t */ keyMap[0x75] = 0x18; /* u */ keyMap[0x76] = 0x19; /* v */ keyMap[0x77] = 0x1a; /* w */ keyMap[0x78] = 0x1b; /* x */ keyMap[0x79] = 0x1c; /* y */ keyMap[0x7a] = 0x1d; /* z */ keyMap[0x7b] = 0x2f | SHIFT; /* { */ keyMap[0x7c] = 0x32 | SHIFT; /* | */ keyMap[0x7d] = 0x30 | SHIFT; /* } */ keyMap[0x7e] = 0x35 | SHIFT; /* ~ */ keyMap[0x7f] = 0; } yubikey-personalization-gui-3.1.24/lib/de-scanedit.h0000664000175000017500000000271612642452141021041 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #ifndef DE_SCANEDIT_H #define DE_SCANEDIT_H #include "scanedit.h" class DeScanEdit : public ScanEdit { public: DeScanEdit(); }; #endif // DE_SCANEDIT_H yubikey-personalization-gui-3.1.24/lib/crandom.cpp0000664000175000017500000000335212642452141020634 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include "crandom.h" CRandom::CRandom(void) { m_crypt = 0; if (!CryptAcquireContext(&m_crypt, 0, 0, PROV_RSA_FULL, 0)) if (!CryptAcquireContext(&m_crypt, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET)) m_crypt = 0; } CRandom::~CRandom(void) { if (m_crypt) CryptReleaseContext(m_crypt, 0); } bool CRandom::getRand(BYTE *buf, int size) { if (!m_crypt) return false; return CryptGenRandom(m_crypt, size, buf) != 0; } yubikey-personalization-gui-3.1.24/lib/scanedit.h0000664000175000017500000000311012642452141020440 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #ifndef SCANEDIT_H #define SCANEDIT_H #include #include class ScanEdit { protected: QMap keyMap; ScanEdit(); public: QString textToScanCodes(const QString text); QString scanCodesToText(const QString scanCode); }; #endif // SCANEDIT_H yubikey-personalization-gui-3.1.24/lib/common.h0000664000175000017500000002346212642452141020152 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef COMMON_H #define COMMON_H #include "otpdef.h" #define YK_VERSION(MAJOR, MINOR, BUILD) (MAJOR * 10000 + MINOR * 100 + BUILD) //typedef std::vector::size_type size_t; enum AccMode { Acc_None, Acc_Serial, Acc_Random, }; #define MAX_SIZE 256 #define SCHEME_INCR_ID_RAND_SECRET 0 #define SCHEME_RAND_SECRET 0 #define SCHEME_RAND_ALL 1 #define SCHEME_ID_FROM_SERIAL_RAND_SECRET 2 #define SCHEME_FIXED 2 #define GEN_SCHEME_FIXED 0 #define GEN_SCHEME_INCR 1 #define GEN_SCHEME_RAND 2 #define GEN_SCHEME_SERIAL 3 #define WRITE_CONFIG 0 #define EXPORT_CONFIG 1 #define SUPPORT_LINK "http://yubi.co/forum" #define UPLOAD_URL "upload
serial:
prefix:
uid:
aeskey:

" #define ERR_NOERROR 0 #define ERR_OTHER 1 #define ERR_NOKEY 2 #define ERR_MORETHANONE 3 #define ERR_UNKNOWN_FIRMWARE 4 #define KEYMAP_NONE 0 #define KEYMAP_US 1 #define KEYMAP_DE 2 //Timeouts #define TIMEOUT_STATUS 10000 #define TIMEOUT_FINDER 1000 //Stylesheets #define SS_MENU_CHECKED "color:rgb(0,0,0);border:2px groove rgb(255,255,255);" #define SS_MENU_UNCHECKED "color:rgb(122,171,32);border:2px groove rgb(255,255,255);" #define SS_MENU_DISABLED "color:rgb(118,116,108);border:2px groove rgb(255,255,255);" #define SS_STATUS_SUCCESS "font:12px \"Verdana\";color:green;" #define SS_STATUS_ERROR "font:12px \"Verdana\";color:rgb(221,97,99);" #define SS_YKSTATUS_SUCCESS "font:11px \"Verdana\";font-weight:bold;color:rgb(122,171,32);" #define SS_YKSTATUS_ERROR "font:11px \"Verdana\";font-weight:bold;color:rgb(221, 97, 99);" #define SS_COPY_BTN "background-image: url(:/res/images/clipboard.png); border-radius: 2px;" #define SS_BLANK_BTN "background-image: url(:/res/images/blank.png); border-radius: 2px;" #define SS_LINK_ENABLED "font: 12px \"Verdana\"; text-decoration: underline; text-align: left; color: rgb(5, 67, 168);" #define SS_LINK_DISABLED "font: 12px \"Verdana\"; text-decoration: underline; text-align: left; color: rgb(118,116,108);" //Messages #define ERR "Error" #define NA "N/A" #define TOVERFLOW "Overflow" #define KEY_FOUND "YubiKey is inserted" #define NO_KEY_FOUND "No YubiKey inserted" #define MORE_THAN_ONE "More than one\nYubiKey inserted" #define OTHER_ERROR "Unknown error occurred" #define UNKNOWN_FIRMWARE "Unknown firmware" #define KEY_CONFIGURED "YubiKey%1 has been successfully configured" #define KEY_EXPORTED "YubiKey configuration has been successfully exported" #define REMOVE_KEY "Please remove this YubiKey" #define SETTINGS_SAVED "Settings have been successfully saved" #define SETTINGS_RESTORED "Default settings have been restored" #define VALUE_COPIED "Value copied to clipboard" #define ERR_KEY_NOT_FOUND "YubiKey not found. Please insert YubiKey in USB port" #define ERR_FEATURE_NOT_SUPPORTED "Selected configuration is not supported by the YubiKey being programmed" #define ERR_FIRMWARE_NOT_SUPPORTED "This YubiKey firmware version is not supported" #define ERR_PROCESSING "YubiKey could not be configured. Perhaps protected with configuration protection access code?" #define ERR_PROCESSING_CHALRESP "Challenge response could not be performed. Perhaps the YubiKey is not configured for challenge-response?" #define ERR_CONF_SLOT_NOT_SELECTED "No configuration slot selected. Please select the configuration slot to be programmed" #define ERR_CHAL_TYPE_NOT_SELECTED "No Challenge-Response Type selected. Please select the one to use" //Warnings #define OVERWRITE_CONF_SLOT1 "Overwrite configuration slot 1?" #define WARN_OVERWRITE_CONF_SLOT1 "If you have a YubiKey VIP, this slot should contain a Symantec VIP credential by default. You should refrain from rewriting this Slot as a Symantec VIP credential can only be programmed during manufacture - you will thus not be able to get a new one.\n\nIf you have any other YubiKey, this slot should contain a Yubico OTP credential by default. This credential is required for using the YubiKey with many of our services and that of our partners. If you overwrite this and want to use it again later, you will need to reprogram it and upload the new one to our YubiCloud validation service.\n\nAre you sure you want to overwrite the configuration slot 1?" #define RESTORE_SETTING "Restore default settings?" #define WARN_RESTORE_SETTING "Are you sure you want to restore the default settings?" #define WARN_EMPTY_PASS "No password set. Please set the password" #define DIFF_PUBLIC_ID_LEN "Change Public Identity length?" #define WARN_DIFF_PUBLIC_ID_LEN "Yubico OTP validation server requires Public Identity to be of 12 characters (6 bytes) in order to correctly extract the Secret Key. If you change the Public Identity to any other length, the Yubico OTP validation server won't be able to extract the Secret Key and the OTP validation will fail.\n\nAre you sure you want to change the default Public Idenity length?" #define ENABLE_CONF_PROTECTION "Enable configuration protection?" #define WARN_ENABLE_CONF_PROTECTION "YubiKey Personalization Tool logging is currently disabled. It is not possible to retrieve the configuration protection access code from the YubiKey. If protection access code is forgotten, you may not be able to program the YubiKey again. Yubico highly recommends to enable logging and archive the relevant log records. \n\nAre you sure you still want to enable the configuration protection?" #define NDEF_WITHOUT_HTTP "Write NDEF without HTTP?" #define WARN_NDEF_WITHOUT_HTTP "The NDEF URI entered does not start with http, are you sure that is what you want?" //Settings #define SG_CUSTOMER_PREFIX_USED "Customer/Used" #define SG_CUSTOMER_PREFIX "Customer/Prefix" #define SG_LOG_DISABLED "Log/Disabled" #define SG_LOG_FILENAME "Log/Filename" #define SG_LOG_FORMAT "Log/Format" #define SG_LOG_FLEXIBLE "Log/Flexible" #define SG_EXPORT_FILENAME "Export/Filename" #define SG_IMPORT_FILENAME "Import/Filename" #define SG_TAB_FIRST "Flag/TabTirst" #define SG_APPEND_TAB1 "Flag/AppendTab1" #define SG_APPEND_TAB2 "Flag/AppendTab2" #define SG_APPEND_CR "Flag/AppendCr" #define SG_APPEND_DELAY1 "Flag/AppendDelay1" #define SG_APPEND_DELAY2 "Flag/AppendDelay2" #define SG_SR_BTN_VISIBLE "Flag/SerialBtnVisible" #define SG_SR_USB_VISIBLE "Flag/serialUsbVisible" #define SG_SR_API_VISIBLE "Flag/serialApiVisible" #define SG_PACING_10MS "Flag/Pacing10ms" #define SG_PACING_20MS "Flag/Pacing20ms" #define SG_MAN_UPDATE "Flag/ManUpdate" #define SG_ALLOW_UPDATE "Flag/AllowUpdate" #define SG_FAST_TRIG "Flag/FastTrig" #define SG_USE_NUMERIC_KEYPAD "Flag/UseNumericKeypad" #define SG_LED_INVERT "Flag/LedInvert" #define SG_OATH_HOTP8 "Flag/OathHotp8" #define SG_REQUIRE_INPUT "Flag/RequireInput" #define SG_HMAC_LT64 "Flag/HmacLt64" #define SG_STRONG_PW1 "Flag/StrongPw1" #define SG_STRONG_PW2 "Flag/StrongPw2" #define SG_STRONG_PW3 "Flag/StrongPw3" #define SG_OVERWRITE_CONF_SLOT1 "DontAsk/Slot1Overwriting" #define SG_DIFF_PUBLIC_ID_LEN "DontAsk/PublicIdLen" #define SG_ENABLE_CONF_PROTECTION "DontAsk/ConfProtection" #define SG_NDEF_WITHOUT_HTTP "DontAsk/NdefWithoutHttp" #define SG_ANIMATIONS_PREFERENCE "Preference/Animations" #define SG_EXPORT_PREFERENCE "Preference/Export" #endif // COMMON_H yubikey-personalization-gui-3.1.24/lib/yubikeyutil.h0000664000175000017500000000612112642452141021232 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef YUBIKEYUTIL_H #define YUBIKEYUTIL_H #include #include "common.h" class YubiKeyUtil { public: ~YubiKeyUtil(); static int hexModhexDecode (unsigned char *result, size_t *resultLen, const char *str, size_t strLen, size_t minSize, size_t maxSize, bool modhex); static int hexModhexEncode (char *result, size_t *resultLen, const unsigned char *str, size_t strLen, bool modhex); static QString qstrHexEncode (const unsigned char *str, size_t strLen); static void qstrHexDecode (unsigned char *result, size_t *resultLen, const QString &str); static QString qstrModhexEncode (const unsigned char *str, size_t strLen); static void qstrModhexDecode (unsigned char *result, size_t *resultLen, const QString &str); static void qstrDecDecode (unsigned char *result, size_t *resultLen, const QString &str); static void qstrToRaw (char *result, size_t resultLen, const QString &str); static void qstrClean (QString *str, size_t maxSize, bool reverse = false); static void qstrModhexClean (QString *str, size_t maxSize, bool reverse = false); static int generateRandom (unsigned char *result, size_t resultLen); static QString generateRandomHex (size_t resultLen); static QString generateRandomModhex( size_t resultLen); static QString getNextHex (size_t resultLen, const QString &str, int scheme); static QString getNextModhex( size_t resultLen, const QString &str, int scheme); }; #endif // YUBIKEYUTIL_H yubikey-personalization-gui-3.1.24/lib/scanedit.cpp0000664000175000017500000000533412642452141021005 0ustar klasklas/* Copyright (C) 2011-2015 Yubico AB. 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. 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 HOLDER 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. */ #include "scanedit.h" #include "yubikeyutil.h" #include "common.h" #include ScanEdit::ScanEdit() { } QString ScanEdit::textToScanCodes(const QString text) { QString scanCode; for(int i = 0; i < text.length(); i++) { QChar ch = text.at(i); unsigned char code = 0; if(ch == '\\') { if(i + 1 != text.length()) { QChar next = text.at(i + 1); if(next == '\\') { i++; } else if(next == 't') { i++; ch = '\t'; } else if(next == 'n') { i++; ch = '\n'; } } } code = keyMap.value(ch.toLatin1() & 0xff, 0); if(code == 0) { qDebug() << "no mapping for" << ch; } QString hexTxt = YubiKeyUtil::qstrHexEncode(&code, 1); scanCode += hexTxt; } return scanCode; } QString ScanEdit::scanCodesToText(const QString scanCode) { QString text; for(int i = 0; i < scanCode.length(); i += 2) { bool ok; unsigned int code = scanCode.mid(i, 2).toUInt(&ok, 16); if(ok == true) { QString key; key += keyMap.key(code, 0); if(key == "\n") key = "\\n"; if(key == "\t") key = "\\t"; if(key == "\\") key = "\\\\"; text += key; } } return text; } yubikey-personalization-gui-3.1.24/lib/crandom.h0000664000175000017500000000304212642452141020275 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef CRANDOM_H #define CRANDOM_H #include #include class CRandom { private: HCRYPTPROV m_crypt; public: CRandom(); ~CRandom(void); bool getRand(BYTE *buf, int size); }; #endif // CRANDOM_H yubikey-personalization-gui-3.1.24/lib/us-scanedit.h0000664000175000017500000000271612642452141021100 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #ifndef US_SCANEDIT_H #define US_SCANEDIT_H #include "scanedit.h" class UsScanEdit : public ScanEdit { public: UsScanEdit(); }; #endif // US_SCANEDIT_H yubikey-personalization-gui-3.1.24/lib/de-scanedit.cpp0000664000175000017500000001226012642452141021367 0ustar klasklas/* Copyright (C) 2015 Yubico AB. 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. 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 HOLDER 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. */ #include "de-scanedit.h" #define SHIFT 0x80 DeScanEdit::DeScanEdit() { keyMap = QMap(); keyMap[0x09] = 0x2b; /* \t */ keyMap[0x0a] = 0x28; /* \n */ keyMap[0x20] = 0x2c; /* */ keyMap[0x21] = 0x1e | SHIFT; /* ! */ keyMap[0x22] = 0x1f | SHIFT; /* " */ keyMap[0x23] = 0x32; /* # */ keyMap[0x24] = 0x21 | SHIFT; /* $ */ keyMap[0x25] = 0x22 | SHIFT; /* % */ keyMap[0x26] = 0x23 | SHIFT; /* & */ keyMap[0x27] = 0x32 | SHIFT; /* ' */ keyMap[0x28] = 0x25 | SHIFT; /* ( */ keyMap[0x29] = 0x26 | SHIFT; /* ) */ keyMap[0x2a] = 0x30 | SHIFT; /* * */ keyMap[0x2b] = 0x30; /* + */ keyMap[0x2c] = 0x36; /* , */ keyMap[0x2d] = 0x38; /* - */ keyMap[0x2e] = 0x37; /* . */ keyMap[0x2f] = 0x24 | SHIFT; /* / */ keyMap[0x30] = 0x27; /* 0 */ keyMap[0x31] = 0x1e; /* 1 */ keyMap[0x32] = 0x1f; /* 2 */ keyMap[0x33] = 0x20; /* 3 */ keyMap[0x34] = 0x21; /* 4 */ keyMap[0x35] = 0x22; /* 5 */ keyMap[0x36] = 0x23; /* 6 */ keyMap[0x37] = 0x24; /* 7 */ keyMap[0x38] = 0x25; /* 8 */ keyMap[0x39] = 0x26; /* 9 */ keyMap[0x3a] = 0x37 | SHIFT; /* : */ keyMap[0x3b] = 0x36 | SHIFT; /* ; */ keyMap[0x3c] = 0x64; /* < */ keyMap[0x3d] = 0x27 | SHIFT; /* = */ keyMap[0x3e] = 0x64 | SHIFT; /* > */ keyMap[0x3f] = 0x2d | SHIFT; /* ? */ keyMap[0x40] = 0; /* @ */ keyMap[0x41] = 0x04 | SHIFT; /* A */ keyMap[0x42] = 0x05 | SHIFT; /* B */ keyMap[0x43] = 0x06 | SHIFT; /* C */ keyMap[0x44] = 0x07 | SHIFT; /* D */ keyMap[0x45] = 0x08 | SHIFT; /* E */ keyMap[0x46] = 0x09 | SHIFT; /* F */ keyMap[0x47] = 0x0a | SHIFT; /* G */ keyMap[0x48] = 0x0b | SHIFT; /* H */ keyMap[0x49] = 0x0c | SHIFT; /* I */ keyMap[0x4a] = 0x0d | SHIFT; /* J */ keyMap[0x4b] = 0x0e | SHIFT; /* K */ keyMap[0x4c] = 0x0f | SHIFT; /* L */ keyMap[0x4d] = 0x10 | SHIFT; /* M */ keyMap[0x4e] = 0x11 | SHIFT; /* N */ keyMap[0x4f] = 0x12 | SHIFT; /* O */ keyMap[0x50] = 0x13 | SHIFT; /* P */ keyMap[0x51] = 0x14 | SHIFT; /* Q */ keyMap[0x52] = 0x15 | SHIFT; /* R */ keyMap[0x53] = 0x16 | SHIFT; /* S */ keyMap[0x54] = 0x17 | SHIFT; /* T */ keyMap[0x55] = 0x18 | SHIFT; /* U */ keyMap[0x56] = 0x19 | SHIFT; /* V */ keyMap[0x57] = 0x1a | SHIFT; /* W */ keyMap[0x58] = 0x1b | SHIFT; /* X */ keyMap[0x59] = 0x1d | SHIFT; /* Y */ keyMap[0x5a] = 0x1c | SHIFT; /* Z */ keyMap[0x5b] = 0; /* [ */ keyMap[0x5c] = 0; /* \ */ keyMap[0x5d] = 0; /* ] */ keyMap[0x5e] = 0x35; /* ^ */ keyMap[0x5f] = 0x38 | SHIFT; /* _ */ keyMap[0x60] = 0x2d | SHIFT; /* ` */ keyMap[0x61] = 0x04; /* a */ keyMap[0x62] = 0x05; /* b */ keyMap[0x63] = 0x06; /* c */ keyMap[0x64] = 0x07; /* d */ keyMap[0x65] = 0x08; /* e */ keyMap[0x66] = 0x09; /* f */ keyMap[0x67] = 0x0a; /* g */ keyMap[0x68] = 0x0b; /* h */ keyMap[0x69] = 0x0c; /* i */ keyMap[0x6a] = 0x0d; /* j */ keyMap[0x6b] = 0x0e; /* k */ keyMap[0x6c] = 0x0f; /* l */ keyMap[0x6d] = 0x10; /* m */ keyMap[0x6e] = 0x11; /* n */ keyMap[0x6f] = 0x12; /* o */ keyMap[0x70] = 0x13; /* p */ keyMap[0x71] = 0x14; /* q */ keyMap[0x72] = 0x15; /* r */ keyMap[0x73] = 0x16; /* s */ keyMap[0x74] = 0x17; /* t */ keyMap[0x75] = 0x18; /* u */ keyMap[0x76] = 0x19; /* v */ keyMap[0x77] = 0x1a; /* w */ keyMap[0x78] = 0x1b; /* x */ keyMap[0x79] = 0x1d; /* y */ keyMap[0x7a] = 0x1c; /* z */ keyMap[0x7b] = 0; /* { */ keyMap[0x7c] = 0; /* | */ keyMap[0x7d] = 0; /* } */ keyMap[0x7e] = 0; /* ~ */ keyMap[0xa7] = 0x20 | SHIFT; /* § */ keyMap[0xb4] = 0x2e; /* ´ */ keyMap[0xc4] = 0x34 | SHIFT; /* Ä */ keyMap[0xd6] = 0x33 | SHIFT; /* Ö */ keyMap[0xdc] = 0x2f | SHIFT; /* Ü */ keyMap[0xdf] = 0x2d; /* ß */ keyMap[0xe4] = 0x34; /* ä */ keyMap[0xf6] = 0x33; /* ö */ keyMap[0xfc] = 0x2f; /* ü */ } yubikey-personalization-gui-3.1.24/lib/otpdef.h0000664000175000017500000000431712642452141020141 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef OTPDEF_H #define OTPDEF_H #define YUBICO_OTP_SERVER_PUBLIC_ID_PREFIX "vv" #define YUBICO_OTP_SERVER_PUBLIC_ID_SIZE 2 #define ACCESS_CODE_DEFAULT "000000000000" #define PUBLIC_ID_DEFAULT_SIZE 6 #define OATH_HOTP_PUBLIC_ID_SIZE 6 #define OATH_HOTP_OMP_SIZE 1 #define OATH_HOTP_TT_SIZE 1 #define OATH_HOTP_MUI_SIZE 4 #define MIN_CUSTOMER_PREFIX 1 #define MAX_CUSTOMER_PREFIX 99999 #define MAX_YUBICO_SERIAL 0x00ffffffUL #define MAX_OATH_SERIAL 99999UL #define OATH_HOTP_CUSTOMER_PREFIX_START 190 // openauthentication.org assigned manufacturer prefix #define YUBICO_OATH_MFG_PREFIX "e1" #define YUBICO_OMP_CODE 0xe1 // Modhex equivalent #define MAX_SCAN_EDIT_SIZE 38 #endif // OTPDEF_H yubikey-personalization-gui-3.1.24/lib/lib.pro0000664000175000017500000000307012642452141017772 0ustar klasklasTEMPLATE = lib CONFIG += exceptions staticlib !nosilent { CONFIG += silent } CONFIG(debug, debug|release) { message("Debug build") CONFIG += console no_lflags_merge warn_on DESTDIR = debug/ } else { message("Release build") DEFINES += QT_NO_DEBUG_OUTPUT DESTDIR = release/ } HEADERS += \ scanedit.h \ us-scanedit.h \ de-scanedit.h \ common.h \ otpdef.h \ yubikeyutil.h SOURCES += \ scanedit.cpp \ us-scanedit.cpp \ de-scanedit.cpp \ yubikeyutil.cpp QMAKE_CXXFLAGS += $$CXXFLAGS $$CPPFLAGS QMAKE_LFLAGS += $$LDFLAGS cross { message("Doing a cross platform build..") # pickup compiler from environment isEmpty(TARGET_ARCH) { error("Cross compiling without a target is completely invalid, set TARGET_ARCH") } QMAKE_CC = $${TARGET_ARCH}-gcc QMAKE_CXX = $${TARGET_ARCH}-g++ QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_C = $$QMAKE_CC win32 { QMAKE_LIB = $${TARGET_ARCH}-ar -ru QMAKE_RC = $${TARGET_ARCH}-windres $$quote(-DVERSION_WIN_STR=\'\\\"$${VERSION}\\0\\\"\') QMAKE_MOC = $$[QT_INSTALL_BINS]/moc QMAKE_UIC = $$[QT_INSTALL_BINS]/uic QMAKE_IDC = $$[QT_INSTALL_BINS]/idc QMAKE_RCC = $$[QT_INSTALL_BINS]/rcc QMAKE_LFLAGS += -static-libstdc++ -static-libgcc } } # # Windows specific configuration # win32 { HEADERS += crandom.h SOURCES += crandom.cpp INCLUDEPATH += ../libs/win32/include } macx:!force_pkgconfig { INCLUDEPATH += ../libs/macx/include CONFIG += x86_64 } yubikey-personalization-gui-3.1.24/COPYING0000664000175000017500000000245412642452141016774 0ustar klasklasCopyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. yubikey-personalization-gui-3.1.24/.gitignore0000664000175000017500000000124212642452141017723 0ustar klasklasYKPersonalization.pro.user Makefile Makefile.Release Makefile.Debug src/ui/ui_*.h build/ deps/ libs/ object_script.yubikey-personalization-gui.Debug object_script.yubikey-personalization-gui.Release .*.swp yubikey-personalization-gui-*.tar.gz yubikey-personalization-gui-*.tar.gz.sig .DS_Store lib/debug/ lib/release/ tests/tests.pro.user lib/scanedit.o lib/de-scanedit.o lib/us-scanedit.o lib/yubikeyutil.o tests/moc_scanedittest.cpp tests/moc_scanedittest.o tests/scanedittest.o tests/moc_yubikeyutiltest.cpp tests/moc_yubikeyutiltest.o tests/test.o tests/yubikeyutiltest.o tests/versiontest.o tests/moc_versiontest.cpp tests/moc_versiontest.o tests/release/ tests/debug/ yubikey-personalization-gui-3.1.24/src/0000775000175000017500000000000012642452141016523 5ustar klasklasyubikey-personalization-gui-3.1.24/src/src.pro0000664000175000017500000004245212642452141020043 0ustar klasklas# # global definitions # VERSION_MAJOR = 3 VERSION_MINOR = 1 VERSION_BUILD = 24 VERSION = "$${VERSION_MAJOR}.$${VERSION_MINOR}.$${VERSION_BUILD}" APP_NAME = $$quote(YubiKey Personalization Tool) # # common configuration # QT += core gui TEMPLATE = app TARGET = yubikey-personalization-gui DEFINES += VERSION_MAJOR=\\\"$${VERSION_MAJOR}\\\" VERSION_MINOR=\\\"$${VERSION_MINOR}\\\" VERSION_BUILD=\\\"$${VERSION_BUILD}\\\" VERSION=\\\"$${VERSION}\\\" CONFIG += exceptions # if this is qt5, add widgets greaterThan(QT_MAJOR_VERSION, 4) { QT += widgets macx { QT += printsupport QTPLUGIN.platforms = qcocoa } } !nosilent { CONFIG += silent } CONFIG(debug, debug|release) { message("Debug build") TARGET_DIR = ..$${DIR_SEPARATOR}build$${DIR_SEPARATOR}debug CONFIG += console no_lflags_merge warn_on LIBS += $$quote(-L../lib/debug) -llib } else { message("Release build") TARGET_DIR = ..$${DIR_SEPARATOR}build$${DIR_SEPARATOR}release DEFINES += QT_NO_DEBUG_OUTPUT LIBS += $$quote(-L../lib/release) -llib } UI_DIR = ./ui RCC_DIR = "$$TARGET_DIR/RCCFiles" MOC_DIR = "$$TARGET_DIR/MOCFiles" OBJECTS_DIR = "$$TARGET_DIR/ObjFiles" DESTDIR = "$$TARGET_DIR" DEPENDPATH += . ui INCLUDEPATH += ../lib . ui LICENSEFILES = json-c.txt \ libyubikey.txt \ yubikey-personalization.txt FORMS += \ ui/toolpage.ui \ ui/staticpage.ui \ ui/settingpage.ui \ ui/otppage.ui \ ui/oathpage.ui \ ui/mainwindow.ui \ ui/helpbox.ui \ ui/confirmbox.ui \ ui/chalresppage.ui \ ui/aboutpage.ui \ ui/diagnostics.ui \ ui/yubiaccbox.ui HEADERS += \ ui/toolpage.h \ ui/staticpage.h \ ui/settingpage.h \ ui/otppage.h \ ui/oathpage.h \ ui/mainwindow.h \ ui/helpbox.h \ ui/confirmbox.h \ ui/chalresppage.h \ ui/aboutpage.h \ ui/diagnostics.h \ ui/yubiaccbox.h \ yubikeywriter.h \ yubikeylogger.h \ yubikeyfinder.h \ yubikeyconfig.h \ version.h \ help.h SOURCES += \ main.cpp \ ui/toolpage.cpp \ ui/staticpage.cpp \ ui/settingpage.cpp \ ui/otppage.cpp \ ui/oathpage.cpp \ ui/mainwindow.cpp \ ui/helpbox.cpp \ ui/confirmbox.cpp \ ui/chalresppage.cpp \ ui/aboutpage.cpp \ ui/yubiaccbox.cpp \ ui/diagnostics.cpp \ yubikeywriter.cpp \ yubikeylogger.cpp \ yubikeyfinder.cpp \ yubikeyconfig.cpp RESOURCES += \ ../resources/resources.qrc OTHER_FILES += \ ../resources/win/resources.rc \ ../resources/mac/Yubico.icns \ ../resources/mac/Info.plist.in \ ../resources/mac/qt.conf QMAKE_CXXFLAGS += $$CXXFLAGS $$CPPFLAGS QMAKE_LFLAGS += $$LDFLAGS cross { message("Doing a cross platform build..") # pickup compiler from environment isEmpty(TARGET_ARCH) { error("Cross compiling without a target is completely invalid, set TARGET_ARCH") } QMAKE_CC = $${TARGET_ARCH}-gcc QMAKE_CXX = $${TARGET_ARCH}-g++ QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_C = $$QMAKE_CC win32 { QMAKE_LIB = $${TARGET_ARCH}-ar -ru QMAKE_RC = $${TARGET_ARCH}-windres $$quote(-DVERSION_WIN_STR=\'\\\"$${VERSION}\\0\\\"\') QMAKE_MOC = $$[QT_INSTALL_BINS]/moc QMAKE_UIC = $$[QT_INSTALL_BINS]/uic QMAKE_IDC = $$[QT_INSTALL_BINS]/idc QMAKE_RCC = $$[QT_INSTALL_BINS]/rcc QMAKE_LFLAGS += -static-libstdc++ -static-libgcc } !isEmpty (QTDIR) { _QT_INCDIR = $${QTDIR}$${DIR_SEPARATOR}include _QT_LIBDIR = $${QTDIR}$${DIR_SEPARATOR}lib _QT_BINDIR = $${QTDIR}$${DIR_SEPARATOR}bin _QT_PLUGINDIR = $${QTDIR}$${DIR_SEPARATOR}plugins } else { _QT_INCDIR = $$(QT_INCDIR) _QT_LIBDIR = $$(QT_LIBDIR) _QT_BINDIR = $$(QT_BINDIR) _QT_PLUGINDIR = $$(QT_PLUGINDIR) } !isEmpty (_QT_INCDIR) { QMAKE_INCDIR_QT = $$_QT_INCDIR } !isEmpty (_QT_LIBDIR) { QMAKE_LIBDIR_QT = $$_QT_LIBDIR } } # # Windows specific configuration # win32 { INCLUDEPATH += ../libs/win32/include ../libs/win32/include/ykpers-1 # The application icon RC_FILE = ../resources/win/resources.rc # The application dependencies !contains(QMAKE_TARGET.arch, x86_64) { message("Windows x86 build") LIBS += $$quote(-L../libs/win32/bin) -llibyubikey-0 -llibykpers-1-1 } else { message("Windows x86_64 build") LIBS += $$quote(-L../libs/win64/bin) -llibyubikey-0 -llibykpers-1-1 } LIBS += $$quote(-L$$_QT_BINDIR) $$quote(-L$$_QT_LIBDIR) CONFIG(debug, debug|release) { LIB_FILES += \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Cored.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Guid.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Widgetsd.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Testd.dll \ $$_QT_PLUGINDIR$${DIR_SEPARATOR}platforms$${DIR_SEPARATOR}qwindowsd.dll \ $$_QT_PLUGINDIR$${DIR_SEPARATOR}imageformats$${DIR_SEPARATOR}qmngd.dll } else { LIB_FILES += \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Core.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Gui.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Widgets.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}Qt5Test.dll \ $$_QT_PLUGINDIR$${DIR_SEPARATOR}platforms$${DIR_SEPARATOR}qwindows.dll \ $$_QT_PLUGINDIR$${DIR_SEPARATOR}imageformats$${DIR_SEPARATOR}qmng.dll } LIB_FILES += \ $$_QT_BINDIR$${DIR_SEPARATOR}libgcc_s_dw2-1.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}libwinpthread-1.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}libstdc++-6.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}icuin54.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}icuuc54.dll \ $$_QT_BINDIR$${DIR_SEPARATOR}icudt54.dll \ ..$${DIR_SEPARATOR}libs$${DIR_SEPARATOR}win32$${DIR_SEPARATOR}bin$${DIR_SEPARATOR}libjson-c-2.dll \ ..$${DIR_SEPARATOR}libs$${DIR_SEPARATOR}win32$${DIR_SEPARATOR}bin$${DIR_SEPARATOR}libyubikey-0.dll \ ..$${DIR_SEPARATOR}libs$${DIR_SEPARATOR}win32$${DIR_SEPARATOR}bin$${DIR_SEPARATOR}libykpers-1-1.dll isEmpty(TIMESTAMP_URL):TIMESTAMP_URL = 'http://tsa.starfieldtech.com' LIB_FILES_WIN = $${LIB_FILES} TARGET_DIR_WIN = $${DESTDIR} for(FILE, LIB_FILES_WIN) { QMAKE_POST_LINK +=$$quote($$QMAKE_COPY $${FILE} $${TARGET_DIR_WIN}$$escape_expand(\\n\\t)) } LICENSE_DIR = $${TARGET_DIR_WIN}$${DIR_SEPARATOR}licenses QMAKE_POST_LINK += $$quote($$QMAKE_MKDIR $${LICENSE_DIR}$$escape_expand(\\n\\t)) BASEDIR = ..$${DIR_SEPARATOR}libs$${DIR_SEPARATOR}win32$${DIR_SEPARATOR}licenses$${DIR_SEPARATOR} for(FILE, LICENSEFILES) { QMAKE_POST_LINK += $$quote($$QMAKE_COPY $${BASEDIR}$${FILE} $${LICENSE_DIR}$$escape_expand(\\n\\t)) } QMAKE_POST_LINK += $$quote($$QMAKE_COPY ..$${DIR_SEPARATOR}COPYING $${LICENSE_DIR}$${DIR_SEPARATOR}yubikey-personalization-gui.txt$$escape_expand(\\n\\t)) sign_binaries { isEmpty(CERT_FILE) { error("Must have a cert file to sign (CERT_FILE env variable).") } # sign all Yubico binaries SIGN_FILES = $${TARGET}.exe \ libyubikey-0.dll \ libykpers-1-1.dll for(FILE, SIGN_FILES) { QMAKE_POST_LINK += $$quote("osslsigncode sign -pkcs11engine /usr/lib/engines/engine_pkcs11.so -pkcs11module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -key slot_1-id_2 -certs $${CERT_FILE} -h sha256 -comm -t $${TIMESTAMP_URL} -n '$${APP_NAME}' -i 'https://www.yubico.com' $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${FILE} $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${FILE}-sign"$$escape_expand(\\n\\t)) QMAKE_POST_LINK += $$quote("mv $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${FILE}-sign $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${FILE}"$$escape_expand(\\n\\t)) } } build_installer { QMAKE_POST_LINK += $$quote("makensis -DYKPERS_VERSION=$${VERSION} ../installer/win-nsis/ykpers.nsi"$$escape_expand(\\n\\t)) sign_binaries { QMAKE_POST_LINK += $$quote("osslsigncode sign -pkcs11engine /usr/lib/engines/engine_pkcs11.so -pkcs11module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -key slot_1-id_2 -certs $${CERT_FILE} -h sha256 -comm -t $${TIMESTAMP_URL} -n '$${APP_NAME} Installer' -i 'https://www.yubico.com' $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${TARGET}-$${VERSION}.exe $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${TARGET}-$${VERSION}.exe-sign"$$escape_expand(\\n\\t)) QMAKE_POST_LINK += $$quote("mv $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${TARGET}-$${VERSION}.exe-sign $${TARGET_DIR_WIN}$${DIR_SEPARATOR}$${TARGET}-$${VERSION}.exe"$$escape_expand(\\n\\t)) } } } # # *nix specific configuration # unix:!macx|force_pkgconfig { message("Unix build") LIBS += -lyubikey CONFIG += link_pkgconfig QT_CONFIG -= no-pkg-config PKGCONFIG += ykpers-1 macx { QMAKE_INFO_PLIST = ../resources/mac/Info.plist.in } } # # MacOS X specific configuration # macx { ICON = ../resources/mac/Yubico.icns } macx:!force_pkgconfig { message("Mac build") INCLUDEPATH += ../libs/macx/include ../libs/macx/include/ykpers-1 LIBS += ../libs/macx/lib/libykpers-1.dylib ../libs/macx/lib/libyubikey.dylib CONFIG += x86_64 DEFINES += QT_MAC_USE_COCOA _QT_LIBDIR = $$[QT_INSTALL_LIBS] _QT_PLUGINDIR = $$[QT_INSTALL_PLUGINS] for_store { QMAKE_CFLAGS += -gdwarf-2 QMAKE_CXXFLAGS += -gdwarf-2 isEmpty(PACKAGE_SIGN_IDENTITY):PACKAGE_SIGN_IDENTITY = '3rd Party Mac Developer Application' isEmpty(INSTALLER_SIGN_IDENTITY):INSTALLER_SIGN_IDENTITY = '3rd Party Mac Developer Installer' } else { isEmpty(PACKAGE_SIGN_IDENTITY):PACKAGE_SIGN_IDENTITY = 'Developer ID Application' isEmpty(INSTALLER_SIGN_IDENTITY):INSTALLER_SIGN_IDENTITY = 'Developer ID Installer' } # The application dependencies LIBS += $$_SDK/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation LIBS += $$_SDK/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit # The application executable name TARGET = $$APP_NAME TARGET_MAC = $${TARGET} TARGET_MAC ~= s, ,\\ ,g BUILD = $$(BUILD) isEmpty(BUILD) { BUILD = 1 } # Copy required resources into the final app bundle and # put the current version number into Info.plist QMAKE_POST_LINK += $$quote(mkdir -p $${DESTDIR}/$${TARGET_MAC}.app/Contents/Resources && \ cp -R ../resources/mac/Yubico.icns $${DESTDIR}/$${TARGET_MAC}.app/Contents/Resources/. && \ cp ../resources/mac/qt.conf $${DESTDIR}/$${TARGET_MAC}.app/Contents/Resources/. && \ sed -e \'s|@SHORT_VERSION@|$$VERSION|g\' -e \'s|@FULL_VERSION@|$$VERSION|g\' \ < ../resources/mac/Info.plist.in > $${DESTDIR}/$${TARGET_MAC}.app/Contents/Info.plist) # copy the QT libraries into our bundle _BASEDIR = $${DESTDIR}/$${TARGET_MAC}.app/Contents _LIBDIR = $${_BASEDIR}/Frameworks _PLUGINDIR = $${_BASEDIR}/PlugIns QMAKE_POST_LINK += $$quote( && mkdir -p $$_LIBDIR && \ cp $$_QT_LIBDIR/QtCore.framework/Versions/5/QtCore $$_LIBDIR && \ cp $$_QT_LIBDIR/QtGui.framework/Versions/5/QtGui $$_LIBDIR && \ cp $$_QT_LIBDIR/QtWidgets.framework/Versions/5/QtWidgets $$_LIBDIR && \ cp $$_QT_LIBDIR/QtPrintSupport.framework/Versions/5/QtPrintSupport $$_LIBDIR && \ cp $$_QT_LIBDIR/QtDBus.framework/Versions/5/QtDBus $$_LIBDIR && \ mkdir -p $$_PLUGINDIR/imageformats && \ cp -R $$_QT_PLUGINDIR/imageformats/libqmng.dylib $$_PLUGINDIR/imageformats && \ mkdir -p $$_PLUGINDIR/platforms && \ cp -R $$_QT_PLUGINDIR/platforms/libqcocoa.dylib $$_PLUGINDIR/platforms) # copy libykpers and friends QMAKE_POST_LINK += $$quote( && mkdir -p $$_LIBDIR && \ cp ../libs/macx/lib/libyubikey.0.dylib $$_LIBDIR && \ cp ../libs/macx/lib/libykpers-1.1.dylib $$_LIBDIR && \ cp ../libs/macx/lib/libjson-c.2.dylib $$_LIBDIR) _LICENSEDIR = $${_BASEDIR}/licenses QMAKE_POST_LINK += $$quote(&& mkdir -p $$_LICENSEDIR && \ cp ../COPYING $$_LICENSEDIR/yubikey-personalization-gui.txt) for(FILE, LICENSEFILES) { QMAKE_POST_LINK += $$quote(&& cp ../libs/macx/licenses/$${FILE} $$_LICENSEDIR) } # fixup all library paths.. _BASE = $$quote(@executable_path/../Frameworks) _LIBBASE = $$quote(@executable_path/../lib) _QTCORE = $$quote(@rpath/QtCore.framework/Versions/5/QtCore) _QTGUI = $$quote(@rpath/QtGui.framework/Versions/5/QtGui) _QTWIDGETS = $$quote(@rpath/QtWidgets.framework/Versions/5/QtWidgets) _QTPRINTSUPPORT = $$quote(@rpath/QtPrintSupport.framework/Versions/5/QtPrintSupport) _QTDBUS = $$quote(@rpath/QtDBus.framework/Versions/5/QtDBus) isEmpty(TARGET_ARCH) { _INSTALL_NAME_TOOL = install_name_tool } else { _INSTALL_NAME_TOOL = $${TARGET_ARCH}-install_name_tool } QMAKE_POST_LINK += $$quote( && $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_BASEDIR/MacOS/$$TARGET_MAC && \ $$_INSTALL_NAME_TOOL -change $$_QTGUI $$_BASE/QtGui $$_BASEDIR/MacOS/$$TARGET_MAC && \ $$_INSTALL_NAME_TOOL -change $$_QTWIDGETS $$_BASE/QtWidgets $$_BASEDIR/MacOS/$$TARGET_MAC && \ $$_INSTALL_NAME_TOOL -change $$_QTPRINTSUPPORT $$_BASE/QtPrintSupport $$_BASEDIR/MacOS/$$TARGET_MAC && \ $$_INSTALL_NAME_TOOL -change $$_LIBBASE/libykpers-1.1.dylib $$_BASE/libykpers-1.1.dylib $$_BASEDIR/MacOS/$$TARGET_MAC && \ $$_INSTALL_NAME_TOOL -change $$_LIBBASE/libyubikey.0.dylib $$_BASE/libyubikey.0.dylib $$_BASEDIR/MacOS/$$TARGET_MAC && \ $$_INSTALL_NAME_TOOL -id $$_BASE/libjson-c.2.dylib $$_LIBDIR/libjson-c.2.dylib && \ $$_INSTALL_NAME_TOOL -id $$_BASE/libyubikey.0.dylib $$_LIBDIR/libyubikey.0.dylib && \ $$_INSTALL_NAME_TOOL -id $$_BASE/libykpers-1.1.dylib $$_LIBDIR/libykpers-1.1.dylib && \ $$_INSTALL_NAME_TOOL -change $$_LIBBASE/libyubikey.0.dylib $$_BASE/libyubikey.0.dylib $$_LIBDIR/libykpers-1.1.dylib && \ $$_INSTALL_NAME_TOOL -change $$_LIBBASE/libjson-c.2.dylib $$_BASE/libjson-c.2.dylib $$_LIBDIR/libykpers-1.1.dylib && \ $$_INSTALL_NAME_TOOL -id $$_BASE/QtCore $$_LIBDIR/QtCore && \ $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_LIBDIR/QtGui && \ $$_INSTALL_NAME_TOOL -id $$_BASE/QtGui $$_LIBDIR/QtGui && \ $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_LIBDIR/QtWidgets && \ $$_INSTALL_NAME_TOOL -change $$_QTGUI $$_BASE/QtGui $$_LIBDIR/QtWidgets && \ $$_INSTALL_NAME_TOOL -id $$_BASE/QtWidgets $$_LIBDIR/QtWidgets && \ $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_LIBDIR/QtPrintSupport && \ $$_INSTALL_NAME_TOOL -change $$_QTGUI $$_BASE/QtGui $$_LIBDIR/QtPrintSupport && \ $$_INSTALL_NAME_TOOL -change $$_QTWIDGETS $$_BASE/QtWidgets $$_LIBDIR/QtPrintSupport && \ $$_INSTALL_NAME_TOOL -id $$_BASE/QtPrintSupport $$_LIBDIR/QtPrintSupport && \ $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_LIBDIR/QtDBus && \ $$_INSTALL_NAME_TOOL -id $$_BASE/QtDBus $$_LIBDIR/QtDBus && \ $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_PLUGINDIR/imageformats/libqmng.dylib && \ $$_INSTALL_NAME_TOOL -change $$_QTGUI $$_BASE/QtGui $$_PLUGINDIR/imageformats/libqmng.dylib && \ $$_INSTALL_NAME_TOOL -change $$_QTCORE $$_BASE/QtCore $$_PLUGINDIR/platforms/libqcocoa.dylib && \ $$_INSTALL_NAME_TOOL -change $$_QTWIDGETS $$_BASE/QtWidgets $$_PLUGINDIR/platforms/libqcocoa.dylib && \ $$_INSTALL_NAME_TOOL -change $$_QTGUI $$_BASE/QtGui $$_PLUGINDIR/platforms/libqcocoa.dylib && \ $$_INSTALL_NAME_TOOL -change $$_QTDBUS $$_BASE/QtDBus $$_PLUGINDIR/platforms/libqcocoa.dylib && \ $$_INSTALL_NAME_TOOL -change $$_QTPRINTSUPPORT $$_BASE/QtPrintSupport $$_PLUGINDIR/platforms/libqcocoa.dylib) QMAKE_POST_LINK += $$quote( && \ if otool -L $$_LIBDIR/* $$_PLUGINDIR/*/* $$_BASEDIR/MacOS/$$TARGET_MAC | grep -e '$$_QT_LIBDIR' -e '$$_LIBBASE' | grep -q compatibility; then \ echo "Something is incorrectly linked!"; \ exit 1; \ fi) build_installer { # the productbuild path doesn't work pre 10.8 for_store { _INSTALLER_CMD = "productbuild --sign \'$$INSTALLER_SIGN_IDENTITY\' --component $${DESTDIR}/$${TARGET_MAC}.app /Applications/ $${DESTDIR}/yubikey-personalization-gui-$${VERSION}.pkg" } else { _INSTALLER_CMD = "rm -rf $${DESTDIR}/temp && \ mkdir -p $${DESTDIR}/temp/ && \ cp -R $${DESTDIR}/$${TARGET_MAC}.app $${DESTDIR}/temp && \ pkgbuild --sign \'$$INSTALLER_SIGN_IDENTITY\' --root ${DESTDIR}/temp/ --component-plist ../resources/mac/installer.plist --install-location '/Applications/' $${DESTDIR}/yubikey-personalization-gui-$${VERSION}.pkg" } QMAKE_POST_LINK += $$quote( && \ codesign --deep -s \'$$PACKAGE_SIGN_IDENTITY\' $${DESTDIR}/$${TARGET_MAC}.app \ --entitlements ../resources/mac/Entitlements.plist && \ $$_INSTALLER_CMD) } } # # Additional cleanup to be performed # win32 { TARGET_DIR_WIN = $${DESTDIR} QMAKE_CLEAN += $${TARGET_DIR_WIN}$${DIR_SEPARATOR}*.exe \ $${TARGET_DIR_WIN}$${DIR_SEPARATOR}*.dll \ $${TARGET_DIR_WIN}$${DIR_SEPARATOR}*.exe.bak } else:macx { QMAKE_CLEAN += -r $${DESTDIR}/*.app $${DESTDIR}/*.pkg $${DESTDIR}/*.dmg } else { QMAKE_CLEAN += -r $${DESTDIR}/* } yubikey-personalization-gui-3.1.24/src/yubikeyfinder.cpp0000664000175000017500000002242512642452141022105 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "yubikeyfinder.h" #include #include #include #include YubiKeyFinder* YubiKeyFinder::_instance = 0; // first version is inclusive, second is exclusive const unsigned int YubiKeyFinder::FEATURE_MATRIX[][2] = { { YK_VERSION(2,0,0), 0 }, //Feature_MultipleConfigurations { YK_VERSION(2,0,0), 0 }, //Feature_ProtectConfiguration2 { YK_VERSION(1,3,0), 0 }, //Feature_StaticPassword { YK_VERSION(2,0,0), 0 }, //Feature_ScanCodeMode { YK_VERSION(2,0,0), 0 }, //Feature_ShortTicket { YK_VERSION(2,0,0), 0 }, //Feature_StrongPwd { YK_VERSION(2,1,0), 0 }, //Feature_OathHotp { YK_VERSION(2,2,0), 0 }, //Feature_ChallengeResponse { YK_VERSION(2,1,4), 0 }, //Feature_SerialNumber { YK_VERSION(2,1,7), 0 }, //Feature_MovingFactor { YK_VERSION(2,3,0), 0 }, //Feature_ChallengeResponseFixed { YK_VERSION(2,3,0), 0 }, //Feature_Updatable { YK_VERSION(2,1,4), 0 }, //Feature_Ndef { YK_VERSION(2,4,0), 0 }, //Feature_LedInvert { YK_VERSION(3,3,0), 0 }, //Feature_U2F }; // when a featureset should be excluded from versions (NEO, I'm looking at you.) const unsigned int YubiKeyFinder::FEATURE_MATRIX_EXCLUDE[][4] = { { YK_VERSION(2,1,4), YK_VERSION(2,2,0), 0, 0 }, //Feature_MultipleConfigurations { YK_VERSION(2,1,4), YK_VERSION(2,2,0), 0, 0 }, //Feature_ProtectConfiguration2 { YK_VERSION(2,1,4), YK_VERSION(2,1,8), 0, 0 }, //Feature_StaticPassword { YK_VERSION(2,1,4), YK_VERSION(2,1,8), 0, 0 }, //Feature_ScanCodeMode { 0, 0, 0, 0 }, //Feature_ShortTicket { YK_VERSION(2,1,4), YK_VERSION(2,1,8), 0, 0 }, //Feature_StrongPwd { 0, 0, 0, 0 }, //Feature_OathHotp { 0, 0, 0, 0 }, //Feature_ChallengeResponse { 0, 0, 0, 0 }, //Feature_SerialNumber { 0, 0, 0, 0 }, //Feature_MovingFactor { 0, 0, 0, 0 }, //Feature_ChallengeResponseFixed { 0, 0, 0, 0 }, //Feature_Updatable { YK_VERSION(2,2,0), YK_VERSION(3,0,0), YK_VERSION(4,0,0), YK_VERSION(4,9,0) }, //Feature_Ndef { YK_VERSION(3,0,0), YK_VERSION(3,1,0), 0, 0 }, //Feature_LedInvert { 0, 0, 0, 0 }, //Feature_U2F }; YubiKeyFinder::YubiKeyFinder() { // init the ykpers library yk_init(); //Initialize fields init(); //Create timer m_timer = new QTimer( this ); connect(m_timer, SIGNAL(timeout()), this, SLOT(findKey())); } YubiKeyFinder::~YubiKeyFinder() { yk_release(); if(m_timer != 0) { delete m_timer; m_timer = 0; } if(_instance) { delete _instance; } if(m_ykds) { ykds_free(m_ykds); } } YubiKeyFinder* YubiKeyFinder::getInstance() { if(_instance == NULL) { _instance = new YubiKeyFinder(); } return _instance; } QString YubiKeyFinder::versionStr() { if(m_version > 0) { return tr("%1.%2.%3"). arg(m_versionMajor). arg(m_versionMinor). arg(m_versionBuild); } return ""; } bool YubiKeyFinder::checkFeatureSupport(Feature feature) { if(m_version > 0 && (unsigned int) feature < sizeof(FEATURE_MATRIX)/sizeof(FEATURE_MATRIX[0])) { bool supported = ( m_version >= FEATURE_MATRIX[feature][0] && (FEATURE_MATRIX[feature][1] == 0 || m_version < FEATURE_MATRIX[feature][1]) ); if(supported) { if(FEATURE_MATRIX_EXCLUDE[feature][0] != 0) if(m_version >= FEATURE_MATRIX_EXCLUDE[feature][0]) if(m_version < FEATURE_MATRIX_EXCLUDE[feature][1]) return false; if(FEATURE_MATRIX_EXCLUDE[feature][2] != 0) if(m_version >= FEATURE_MATRIX_EXCLUDE[feature][2]) if(m_version < FEATURE_MATRIX_EXCLUDE[feature][3]) return false; } return supported; } return false; } void YubiKeyFinder::init() { m_state = State_Absent; m_yk = 0; m_version = 0; m_versionMajor = 0; m_versionMinor = 0; m_versionBuild = 0; m_serial = 0; m_touchLevel = 0; m_ykds = ykds_alloc(); } void YubiKeyFinder::start() { //Start timer init(); if(m_timer && !m_timer->isActive()) { m_timer->start(TIMEOUT_FINDER); } } void YubiKeyFinder::stop() { //Stop timer if(m_timer && m_timer->isActive()) { m_timer->stop(); // doing closeKey() here might look out of place and may cause findKey() // to fail unexpectedly, but it's needed to not leak file descriptors // when writing the key. closeKey(); } } bool YubiKeyFinder::openKey() { bool flag = true; if (!(m_yk = yk_open_first_key())) { flag = false; } return flag; } bool YubiKeyFinder::closeKey() { bool flag = true; if(m_yk != 0) { if (!yk_close_key(m_yk)) { flag = false; } m_yk = 0; } return flag; } void YubiKeyFinder::findKey() { if(QApplication::activeWindow() == 0) { //No focus, avoid locking the YubiKey. m_state = State_NoFocus; return; } bool error = false; //qDebug() << "-------------------------"; //qDebug() << "Starting key search"; //qDebug() << "-------------------------"; try { if(m_yk == 0 && !openKey()) { throw 0; } if (!yk_get_status(m_yk, m_ykds)) { throw 0; } //qDebug() << "Key found"; //Check pervious state if(m_state == State_Absent || m_state == State_NoFocus) { m_state = State_Present; //Get version m_versionMajor = ykds_version_major(m_ykds); m_versionMinor = ykds_version_minor(m_ykds); m_versionBuild = ykds_version_build(m_ykds); m_version = YK_VERSION(m_versionMajor, m_versionMinor, m_versionBuild); m_touchLevel = ykds_touch_level(m_ykds); //Get serial number if(checkFeatureSupport(Feature_SerialNumber)) { if (!yk_get_serial(m_yk, 0, 0, &m_serial)) { qDebug() << "Failed to read serial number (serial-api-visible disabled?)."; } else { qDebug() << "Serial number: " << m_serial; } } //Get supported features size_t featuresCount = sizeof(FEATURE_MATRIX)/sizeof(FEATURE_MATRIX[0]); bool featuresMatrix[featuresCount]; for(size_t i = 0; i < featuresCount; i++) { featuresMatrix[i] = checkFeatureSupport((Feature)i); } int error = ERR_NOERROR; if(!yk_check_firmware_version2(m_ykds)) { error = ERR_UNKNOWN_FIRMWARE; } emit keyFound(true, featuresMatrix, error); emit diagnostics(QString("Found key with version %1, serial %2 and touch %3.") .arg(versionStr(), QString::number(m_serial), QString::number(m_touchLevel))); } } catch(...) { error = true; } closeKey(); if(error) { init(); m_state = State_Absent; int error = ERR_OTHER; if(yk_errno == YK_EMORETHANONE) { error = ERR_MORETHANONE; } else if(yk_errno == YK_ENOKEY) { error = ERR_NOKEY; } else if(yk_errno == YK_EUSBERR) { emit diagnostics(QString("USB Error: %1").arg(yk_usb_strerror())); } else if(yk_errno) { emit diagnostics(yk_strerror(yk_errno)); } yk_errno = 0; ykp_errno = 0; emit keyFound(false, NULL, error); } //qDebug() << "-------------------------"; //qDebug() << "Stopping key search"; //qDebug() << "-------------------------"; } yubikey-personalization-gui-3.1.24/src/yubikeylogger.cpp0000664000175000017500000003207312642452141022115 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include "yubikeylogger.h" #include #include #include #include #include #include #define LOG_FILENAME_DEF "configuration_log.csv" #define LOG_SEPARATOR "," QString YubiKeyLogger::m_filename = defaultLogFilename(); bool YubiKeyLogger::m_enabled = true; bool YubiKeyLogger::m_started = true; YubiKeyLogger::Format YubiKeyLogger::m_format = Format_Traditional; QFile* YubiKeyLogger::m_logFile = NULL; QString YubiKeyLogger::m_flexibleFormat = ""; #define STRING 1 #define BOOL 2 #define INT 3 #define UINT 4 struct logging_st YubiKeyLogger::logging_map[] = { { "eventType", NULL, STRING, YubiKeyLogger::resolve_eventType }, { "timestampLocal", NULL, STRING, YubiKeyLogger::resolve_timestamp }, { "configSlot", "configSlot", INT, NULL }, { "pubIdTxt", "pubIdTxt", STRING, NULL }, { "pvtIdTxt", "pvtIdTxt", STRING, NULL }, { "secretKeyTxt", "secretKeyTxt", STRING, NULL }, { "secretKeyB64", NULL, STRING, YubiKeyLogger::resolve_secretKeyB64 }, { "currentAccessCodeTxt", "currentAccessCodeTxt", STRING, NULL }, { "currentAccessCodeTxtPadded", NULL, STRING, YubiKeyLogger::resolve_accessCode }, { "newAccessCodeTxt", "newAccessCodeTxt", STRING, NULL }, { "newAccessCodeTxtPadded", NULL, STRING, YubiKeyLogger::resolve_accessCode }, { "hotpDigits", NULL, STRING, YubiKeyLogger::resolve_hotpDigits }, { "oathMovingFactorSeed", "oathMovingFactorSeed", UINT, NULL }, { "strongPw1", "strongPw1", BOOL, NULL }, { "strongPw2", "strongPw2", BOOL, NULL }, { "sendRef", "sendRef", BOOL, NULL }, { "chalBtnTrig", "chalBtnTrig", BOOL, NULL }, { "hmacLT64", "hmacLT64", BOOL, NULL }, { "timestampFixed", NULL, STRING, YubiKeyLogger::resolve_timestamp }, { "oathFixedModhex1", "oathFixedModhex1", BOOL, NULL }, { "oathFixedModhex2", "oathFixedModhex2", BOOL, NULL }, { "oathFixedModhex", "oathFixedModhex", BOOL, NULL }, { "tokenLength", NULL, STRING, YubiKeyLogger::resolve_tokenLength }, { "serial", "serial", STRING, NULL }, { "endl", NULL, STRING, YubiKeyLogger::resolve_symbol }, { "tab", NULL, STRING, YubiKeyLogger::resolve_symbol }, }; YubiKeyLogger::~YubiKeyLogger() { } QFile *YubiKeyLogger::getLogFile() { if(m_logFile == NULL) { m_filename = QFileDialog::getSaveFileName(NULL, tr("Select Log File"), m_filename, tr("Comma-sepparated values (*.csv)"), NULL, QFileDialog::DontConfirmOverwrite); if(m_filename.isEmpty()) { qDebug() << "No filename returned for logging"; return NULL; } m_logFile = new QFile(m_filename); if(!m_logFile->open(QIODevice::WriteOnly | QIODevice::Append)) { qDebug() << "File could not be opened for writing"; return NULL; } QSettings settings; settings.setValue(SG_LOG_FILENAME, m_filename); } return m_logFile; } void YubiKeyLogger::closeLogFile() { if(m_logFile != NULL) { if(m_format == Format_PSKC) { endPSKC(); } m_logFile->close(); delete(m_logFile); m_logFile = NULL; m_started = true; } } QString YubiKeyLogger::formatLog(YubiKeyConfig *ykConfig, QString format) { for(unsigned long i = 0; i < (sizeof(logging_map) / sizeof(logging_st)); i++) { QString token = QString("{") + logging_map[i].name + QString("}"); if(!format.contains(token)) { continue; } QString out; int type = logging_map[i].returnType; const char *configName = logging_map[i].configName; if(logging_map[i].resolver != NULL) { out = logging_map[i].resolver(ykConfig, logging_map[i].name); } else if(type == STRING) { QMetaObject::invokeMethod(ykConfig, configName, Qt::DirectConnection, Q_RETURN_ARG(QString, out)); } else if(type == BOOL) { bool ret; QMetaObject::invokeMethod(ykConfig, configName, Qt::DirectConnection, Q_RETURN_ARG(bool, ret)); out = ret ? "1" : "0"; } else if(type == INT) { int ret; QMetaObject::invokeMethod(ykConfig, configName, Qt::DirectConnection, Q_RETURN_ARG(int, ret)); out = QString::number(ret); } else if(type == UINT) { unsigned int ret; QMetaObject::invokeMethod(ykConfig, configName, Qt::DirectConnection, Q_RETURN_ARG(unsigned int, ret)); out = QString::number(ret); } qDebug() << "replacing " << token << " with " << out << " from " << configName << " type " << type; format.replace(token, out); } return format; } void YubiKeyLogger::logConfig(YubiKeyConfig *ykConfig) { //Check if logging is enabled if(!m_enabled) { return; } QString format = ""; if(m_format == Format_Traditional) { if(m_started) { format += "LOGGING START,{timestampLocal}{endl}"; m_started = false; } format += "{eventType},{timestampLocal},{configSlot},{pubIdTxt},{pvtIdTxt},{secretKeyTxt},{currentAccessCodeTxt},{newAccessCodeTxt},{oathFixedModhex1},{oathFixedModhex2},{oathFixedModhex},{hotpDigits},{oathMovingFactorSeed},{strongPw1},{strongPw2},{sendRef},{chalBtnTrig},{hmacLT64}"; } else if(m_format == Format_Yubico) { format = "{serial},"; if(ykConfig->programmingMode() == YubiKeyConfig::Mode_YubicoOtp) { format += "{pubIdTxt},{pvtIdTxt},"; } else if(ykConfig->programmingMode() == YubiKeyConfig::Mode_OathHotp) { format += "{pubIdTxt},{oathMovingFactorSeed},"; } else if(ykConfig->programmingMode() == YubiKeyConfig::Mode_ChalRespHmac) { format += ",0,"; } else { format += ",,"; } format += "{secretKeyTxt},{newAccessCodeTxtPadded},{timestampFixed},"; } else if(m_format == Format_PSKC) { if(m_started) { format += "{endl}{endl}"; m_started = false; } format += "Yubico{serial}"; format += "{configSlot}programmingMode() == YubiKeyConfig::Mode_YubicoOtp) { format += " Algorithm=\"http://www.yubico.com/#yubikey-aes\">"; } else if(ykConfig->programmingMode() == YubiKeyConfig::Mode_OathHotp) { format += " Algorithm=\"urn:ietf:params:xml:ns:keyprov:pskc:hotp\">"; } else { qDebug() << "PSKC is primarily for Oath-HOTP and Yubico-OTP"; format += ">"; } format += "{secretKeyB64}"; if(ykConfig->programmingMode() == YubiKeyConfig::Mode_OathHotp) { format += "{oathMovingFactorSeed}"; } format += ""; if(ykConfig->programmingMode() == YubiKeyConfig::Mode_YubicoOtp) { format += "CN={pubIdTxt}, UID={pvtIdTxt}"; } format += ""; } else if(m_format == Format_Flexible) { format = m_flexibleFormat; } else { qDebug() << "unknown format" << m_format; return; } format = formatLog(ykConfig, format); logString(format); } void YubiKeyLogger::enableLogging() { m_enabled = true; } void YubiKeyLogger::disableLogging() { m_enabled = false; } bool YubiKeyLogger::isLogging() { return m_enabled; } void YubiKeyLogger::setLogFilename(const QString &filename) { closeLogFile(); m_filename = filename; } QString YubiKeyLogger::logFilename() { return m_filename; } QString YubiKeyLogger::defaultLogFilename() { return QDir::homePath() + "/" + LOG_FILENAME_DEF; } void YubiKeyLogger::setLogFormat(Format format) { closeLogFile(); m_format = format; } void YubiKeyLogger::setFlexibleFormat(QString format) { m_flexibleFormat = format; } QString YubiKeyLogger::resolve_hotpDigits(YubiKeyConfig *ykConfig, QString name __attribute__((unused))) { QString ret = "0"; if(ykConfig->programmingMode() == YubiKeyConfig::Mode_OathHotp) { ret = (ykConfig->oathHotp8()? "8": "6"); } return ret; } QString YubiKeyLogger::resolve_eventType(YubiKeyConfig *ykConfig, QString name __attribute__((unused))) { switch(ykConfig->programmingMode()) { case YubiKeyConfig::Mode_YubicoOtp: return(tr("Yubico OTP")); case YubiKeyConfig::Mode_Static: { QString eventType = tr("Static Password"); if(ykConfig->shortTicket()) { if(ykConfig->staticTicket()) { eventType.append(tr(": Short")); } else { eventType.append(tr(": Scan Code")); } } return eventType; } case YubiKeyConfig::Mode_OathHotp: return(tr("OATH-HOTP")); case YubiKeyConfig::Mode_ChalRespYubico: return(tr("Challenge-Response: Yubico OTP")); case YubiKeyConfig::Mode_ChalRespHmac: return(tr("Challenge-Response: HMAC-SHA1")); case YubiKeyConfig::Mode_Update: return(tr("Configuration Update")); case YubiKeyConfig::Mode_Swap: return(tr("Configuration Swap")); } return(tr("Unknown programming mode")); } QString YubiKeyLogger::resolve_timestamp(YubiKeyConfig *ykConfig __attribute__((unused)), QString name) { QDateTime ts = QDateTime::currentDateTime(); if(name == "timestampLocal") { return ts.toString(Qt::SystemLocaleDate); } else { return ts.toString("yyyy-MM-ddThh:mm:ss"); } } QString YubiKeyLogger::resolve_symbol(YubiKeyConfig *ykConfig __attribute__((unused)), QString name) { if(name == "endl") { return "\n"; } else if(name == "tab") { return "\t"; } return ""; } QString YubiKeyLogger::resolve_secretKeyB64(YubiKeyConfig *ykConfig, QString name __attribute__((unused))) { QByteArray decodedSecret = QByteArray::fromHex(ykConfig->secretKeyTxt().toLatin1()); return decodedSecret.toBase64(); } QString YubiKeyLogger::resolve_tokenLength(YubiKeyConfig *ykConfig, QString name __attribute__((unused))) { int len = ykConfig->pubIdTxt().length(); if(ykConfig->programmingMode() == YubiKeyConfig::Mode_YubicoOtp) { len += 32; } else if(ykConfig->programmingMode() == YubiKeyConfig::Mode_OathHotp) { len += ykConfig->oathHotp8() ? 8 : 6; } return QString::number(len); } QString YubiKeyLogger::resolve_accessCode(YubiKeyConfig *ykConfig, QString name) { QString code; if(name == "currentAccessCodeTxtPadded") { code = ykConfig->currentAccessCodeTxt(); } else { code = ykConfig->newAccessCodeTxt(); } return code.rightJustified(12, '0'); } QStringList YubiKeyLogger::getLogNames() { QStringList list; for(unsigned int i = 0; i < (sizeof(logging_map) / sizeof(logging_st)); i++) { list << logging_map[i].name; } return list; } void YubiKeyLogger::endPSKC() { logString(""); } void YubiKeyLogger::logString(QString string) { QFile *file = getLogFile(); if(file == NULL) { qDebug() << "Failed to get logfile"; return; } QTextStream out(file); out << string << endl; file->flush(); } yubikey-personalization-gui-3.1.24/src/yubikeyconfig.h0000664000175000017500000002203212642452141021542 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef YUBIKEYCONFIG_H #define YUBIKEYCONFIG_H #include "common.h" #include class YubiKeyConfig : public QObject { Q_OBJECT public: YubiKeyConfig(); enum Mode { Mode_YubicoOtp, Mode_Static, Mode_OathHotp, Mode_ChalRespYubico, Mode_ChalRespHmac, Mode_Update, Mode_Swap, }; void setProgrammingMode(Mode mode) {m_mode = mode;} Q_INVOKABLE Mode programmingMode() const {return m_mode;} Q_INVOKABLE AccMode accMode() const {return m_accMode;} void setConfigSlot(int configSlot) {m_configSlot = configSlot;} Q_INVOKABLE int configSlot() const {return m_configSlot;} void setPubIdInHex(bool pubIdInHex) {m_pubIdInHex = pubIdInHex;} Q_INVOKABLE bool pubIdInHex() const {return m_pubIdInHex;} void setPubIdTxt(const QString &pubIdTxt); Q_INVOKABLE QString pubIdTxt() const {return m_pubIdTxt;} void setPvtIdTxt(const QString &pvtIdTxt); Q_INVOKABLE QString pvtIdTxt() const {return m_pvtIdTxt;} void setSecretKeyTxt(const QString &secretKeyTxt); Q_INVOKABLE QString secretKeyTxt() const {return m_secretKeyTxt;} void setCurrentAccessCodeTxt(const QString ¤tAccessCodeTxt); Q_INVOKABLE QString currentAccessCodeTxt() const {return m_currentAccessCodeTxt;} void setNewAccessCodeTxt(const QString &newAccessCodeTxt, AccMode accMode); Q_INVOKABLE QString newAccessCodeTxt() const {return m_newAccessCodeTxt;} void setSerial(const QString &serial) {m_serial = serial;} Q_INVOKABLE QString serial() const {return m_serial;} void setTabFirst(bool tabFirst) {m_tabFirst = tabFirst;} Q_INVOKABLE bool tabFirst() const {return m_tabFirst;} void setAppendTab1(bool appendTab1) {m_appendTab1 = appendTab1;} Q_INVOKABLE bool appendTab1() const {return m_appendTab1;} void setAppendTab2(bool appendTab2) {m_appendTab2 = appendTab2;} Q_INVOKABLE bool appendTab2() const {return m_appendTab2;} void setAppendCr(bool appendCr) {m_appendCr = appendCr;} Q_INVOKABLE bool appendCr() const {return m_appendCr;} void setAppendDelay1(bool appendDelay1) {m_appendDelay1 = appendDelay1;} Q_INVOKABLE bool appendDelay1() const {return m_appendDelay1;} void setAppendDelay2(bool appendDelay2) {m_appendDelay2 = appendDelay2;} Q_INVOKABLE bool appendDelay2() const {return m_appendDelay2;} void setProtectCfg2(bool protectCfg2) {m_protectCfg2 = protectCfg2;} Q_INVOKABLE bool protectCfg2() const {return m_protectCfg2;} void setSendRef(bool sendRef) {m_sendRef = sendRef;} Q_INVOKABLE bool sendRef() const {return m_sendRef;} void setTicketFirst(bool ticketFirst) {m_ticketFirst = ticketFirst;} Q_INVOKABLE bool ticketFirst() const {return m_ticketFirst;} void setPacing10ms(bool pacing10ms) {m_pacing10ms = pacing10ms;} Q_INVOKABLE bool pacing10ms() const {return m_pacing10ms;} void setPacing20ms(bool pacing20ms) {m_pacing20ms = pacing20ms;} Q_INVOKABLE bool pacing20ms() const {return m_pacing20ms;} void setAllowHidtrig(bool allowHidtrig) {m_allowHidtrig = allowHidtrig;} Q_INVOKABLE bool allowHidtrig() const {return m_allowHidtrig;} void setStaticTicket(bool staticTicket) {m_staticTicket = staticTicket;} Q_INVOKABLE bool staticTicket() const {return m_staticTicket;} void setShortTicket(bool shortTicket) {m_shortTicket = shortTicket;} Q_INVOKABLE bool shortTicket() const {return m_shortTicket;} void setStrongPw1(bool strongPw1) {m_strongPw1 = strongPw1;} Q_INVOKABLE bool strongPw1() const {return m_strongPw1;} void setStrongPw2(bool strongPw2) {m_strongPw2 = strongPw2;} Q_INVOKABLE bool strongPw2() const {return m_strongPw2;} void setManUpdate(bool manUpdate) {m_manUpdate = manUpdate;} Q_INVOKABLE bool manUpdate() const {return m_manUpdate;} void setOathFixedModhex1(bool oathFixedModhex1) {m_oathFixedModhex1 = oathFixedModhex1;} Q_INVOKABLE bool oathFixedModhex1() const {return m_oathFixedModhex1;} void setOathFixedModhex2(bool oathFixedModhex2) {m_oathFixedModhex2 = oathFixedModhex2;} Q_INVOKABLE bool oathFixedModhex2() const {return m_oathFixedModhex2;} void setOathFixedModhex(bool oathFixedModhex) {m_oathFixedModhex = oathFixedModhex;} Q_INVOKABLE bool oathFixedModhex() const {return m_oathFixedModhex;} void setOathHotp8(bool oathHotp8) {m_oathHotp8 = oathHotp8;} Q_INVOKABLE bool oathHotp8() const {return m_oathHotp8;} void setOathMovingFactorSeed(unsigned int oathMovingFactorSeed) {m_oathMovingFactorSeed = oathMovingFactorSeed;} Q_INVOKABLE unsigned int oathMovingFactorSeed() const {return m_oathMovingFactorSeed;} void setChalYubico(bool chalYubico) {m_chalYubico = chalYubico;} Q_INVOKABLE bool chalYubico() const {return m_chalYubico;} void setChalHmac(bool chalHmac) {m_chalHmac = chalHmac;} Q_INVOKABLE bool chalHmac() const {return m_chalHmac;} void setHmacLT64(bool hmacLT64) {m_hmacLT64 = hmacLT64;} Q_INVOKABLE bool hmacLT64() const {return m_hmacLT64;} void setChalBtnTrig(bool chalBtnTrig) {m_chalBtnTrig = chalBtnTrig;} Q_INVOKABLE bool chalBtnTrig() const {return m_chalBtnTrig;} void setSerialBtnVisible(bool serialBtnVisible) {m_serialBtnVisible = serialBtnVisible;} Q_INVOKABLE bool serialBtnVisible() const {return m_serialBtnVisible;} void setSerialUsbVisible(bool serialUsbVisible) {m_serialUsbVisible = serialUsbVisible;} Q_INVOKABLE bool serialUsbVisible() const {return m_serialUsbVisible;} void setSerialApiVisible(bool serialApiVisible) {m_serialApiVisible = serialApiVisible;} Q_INVOKABLE bool serialApiVisible() const {return m_serialApiVisible;} void setAllowUpdate(bool allowUpdate) {m_allowUpdate = allowUpdate;} Q_INVOKABLE bool allowUpdate() const {return m_allowUpdate;} void setDormant(bool dormant) {m_dormant = dormant;} Q_INVOKABLE bool dormant() const {return m_dormant;} void setFastTrig(bool fastTrig) {m_fastTrig = fastTrig;} Q_INVOKABLE bool fastTrig() const {return m_fastTrig;} void setUseNumericKeypad(bool useNumericKeypad) {m_useNumericKeypad = useNumericKeypad;} Q_INVOKABLE bool useNumericKeypad() const {return m_useNumericKeypad;} void setLedInvert(bool ledInvert) {m_ledInvert = ledInvert;} Q_INVOKABLE bool ledInvert() const {return m_ledInvert;} private: Mode m_mode; AccMode m_accMode; int m_configSlot; bool m_pubIdInHex; QString m_pubIdTxt; QString m_pvtIdTxt; QString m_secretKeyTxt; QString m_currentAccessCodeTxt; QString m_newAccessCodeTxt; QString m_serial; //Ticket flags bool m_tabFirst; bool m_appendTab1; bool m_appendTab2; bool m_appendCr; bool m_appendDelay1; bool m_appendDelay2; bool m_protectCfg2; //Configuration flags bool m_sendRef; bool m_ticketFirst; bool m_pacing10ms; bool m_pacing20ms; bool m_allowHidtrig; bool m_staticTicket; bool m_shortTicket; bool m_strongPw1; bool m_strongPw2; bool m_manUpdate; bool m_oathFixedModhex1; bool m_oathFixedModhex2; bool m_oathFixedModhex; bool m_oathHotp8; unsigned int m_oathMovingFactorSeed; bool m_chalYubico; bool m_chalHmac; bool m_hmacLT64; bool m_chalBtnTrig; bool m_serialBtnVisible; bool m_serialUsbVisible; bool m_serialApiVisible; // v2.3 settings bool m_allowUpdate; bool m_dormant; bool m_fastTrig; bool m_useNumericKeypad; bool m_ledInvert; }; #endif // YUBIKEYCONFIG_H yubikey-personalization-gui-3.1.24/src/yubikeyconfig.cpp0000664000175000017500000001021512642452141022075 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include "yubikeyconfig.h" #include "yubikeyutil.h" #include YubiKeyConfig::YubiKeyConfig() { m_mode = Mode_YubicoOtp; m_accMode = Acc_None; m_configSlot = 1; m_pubIdInHex = false; m_pubIdTxt.clear(); m_pvtIdTxt.clear(); m_secretKeyTxt.clear(); m_currentAccessCodeTxt.clear(); m_newAccessCodeTxt.clear(); m_serial.clear(); QSettings settings; m_tabFirst = settings.value(SG_TAB_FIRST).toBool(); m_appendTab1 = settings.value(SG_APPEND_TAB1).toBool(); m_appendTab2 = settings.value(SG_APPEND_TAB2).toBool(); m_appendCr = settings.value(SG_APPEND_CR).toBool(); m_appendDelay1 = settings.value(SG_APPEND_DELAY1).toBool(); m_appendDelay2= settings.value(SG_APPEND_DELAY2).toBool(); m_protectCfg2 = false; // XXX Not implemented m_sendRef = false; m_ticketFirst = false; m_pacing10ms = settings.value(SG_PACING_10MS).toBool(); m_pacing20ms = settings.value(SG_PACING_20MS).toBool(); m_allowHidtrig = false; m_staticTicket = false; m_shortTicket = false; m_strongPw1 = false; m_strongPw2 = false; m_manUpdate = false; m_oathFixedModhex1 = false; m_oathFixedModhex2 = false; m_oathFixedModhex = false; m_oathHotp8 = false; m_oathMovingFactorSeed = 0; m_chalYubico = false; m_chalHmac = false; m_chalBtnTrig = false; m_hmacLT64 = false; m_serialBtnVisible = settings.value(SG_SR_BTN_VISIBLE).toBool(); m_serialUsbVisible = settings.value(SG_SR_USB_VISIBLE).toBool(); m_serialApiVisible = settings.value(SG_SR_API_VISIBLE).toBool(); if(settings.contains(SG_ALLOW_UPDATE)) { m_allowUpdate = settings.value(SG_ALLOW_UPDATE).toBool(); } else { m_allowUpdate = true; } m_dormant = false; m_fastTrig = settings.value(SG_FAST_TRIG).toBool(); m_useNumericKeypad = settings.value(SG_USE_NUMERIC_KEYPAD).toBool(); m_ledInvert = settings.value(SG_LED_INVERT).toBool(); } void YubiKeyConfig::setPubIdTxt(const QString &pubIdTxt) { m_pubIdTxt = pubIdTxt; if(m_pubIdInHex) { YubiKeyUtil::qstrClean(&m_pubIdTxt, 0); } else { YubiKeyUtil::qstrModhexClean(&m_pubIdTxt, 0); } } void YubiKeyConfig::setPvtIdTxt(const QString &pvtIdTxt) { m_pvtIdTxt = pvtIdTxt; YubiKeyUtil::qstrClean(&m_pvtIdTxt, 0); } void YubiKeyConfig::setSecretKeyTxt(const QString &secretKeyTxt) { m_secretKeyTxt = secretKeyTxt; YubiKeyUtil::qstrClean(&m_secretKeyTxt, 0); } void YubiKeyConfig::setCurrentAccessCodeTxt(const QString ¤tAccessCodeTxt) { m_currentAccessCodeTxt = currentAccessCodeTxt; YubiKeyUtil::qstrClean(&m_currentAccessCodeTxt, 0); } void YubiKeyConfig::setNewAccessCodeTxt(const QString &newAccessCodeTxt, AccMode accMode) { m_newAccessCodeTxt = newAccessCodeTxt; YubiKeyUtil::qstrClean(&m_newAccessCodeTxt, 0); m_accMode = accMode; } yubikey-personalization-gui-3.1.24/src/yubikeywriter.h0000664000175000017500000000514312642452141021615 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef YUBIKEYWRITER_H #define YUBIKEYWRITER_H #include extern "C" { #include } #include "common.h" #include "yubikeyconfig.h" class YubiKeyConfig; class YubiKeyWriter : public QObject { Q_OBJECT public: static YubiKeyWriter* getInstance(); ~YubiKeyWriter(); static void setExportFilename(QString filename); static QString defaultExportFilename(void); private: static QString m_filename; YubiKeyWriter(); static YubiKeyWriter* _instance; QString reportError(bool chalresp); int encodeAccessCode(const QString accCode, unsigned char *accessCode, size_t *accessCodeLen); int assembleConfig(YubiKeyConfig *ykConfig, YKP_CONFIG *ykp, bool *useAccessCode, unsigned char *accessCode); public slots: void writeConfig(YubiKeyConfig *ykConfig); void exportConfig(YubiKeyConfig *ykConfig); void doChallengeResponse(const QString challenge, QString &response, int slot, bool hmac); void writeNdef(bool uri, const QString language, const QString payload, const QString accCode, int slot); void deleteConfig(int slot, const QString accCode); signals: void configWritten(bool written, const QString &msg); void errorOccurred(const QString &text); void diagnostics(const QString &text); }; #endif // YUBIKEYWRITER_H yubikey-personalization-gui-3.1.24/src/yubikeywriter.cpp0000664000175000017500000005256612642452141022163 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "yubikeywriter.h" #include "yubikeyfinder.h" #include "yubikeylogger.h" #include "yubikeyutil.h" #include #include #include #include #include #define EXPORT_FILENAME_DEF "export.ycfg" YubiKeyWriter* YubiKeyWriter::_instance = 0; QString YubiKeyWriter::m_filename = defaultExportFilename(); #define TKTFLAG(f, s) \ if(s) { if (!ykp_set_tktflag_##f(cfg, s)) { return 0; } } #define CFGFLAG(f, s) \ if(s) { if (!ykp_set_cfgflag_##f(cfg, s)) { return 0; } } #define EXTFLAG(f, s) \ if(s) { if (!ykp_set_extflag_##f(cfg, s)) { return 0; } } YubiKeyWriter::YubiKeyWriter() { } YubiKeyWriter::~YubiKeyWriter() { if(_instance) { delete _instance; } } YubiKeyWriter* YubiKeyWriter::getInstance() { if(_instance == NULL) { _instance = new YubiKeyWriter(); } return _instance; } QString YubiKeyWriter::reportError(bool chalresp = false) { QString errMsg; if (ykp_errno) { qDebug("Yubikey personalization error: %s\n", ykp_strerror(ykp_errno)); emit diagnostics(ykp_strerror(ykp_errno)); switch(ykp_errno) { case YKP_EYUBIKEYVER: case YKP_EOLDYUBIKEY: errMsg = tr(ERR_FEATURE_NOT_SUPPORTED); break; default: errMsg = tr(ERR_PROCESSING); break; } ykp_errno = 0; } else if (yk_errno) { if (yk_errno == YK_EUSBERR) { qDebug("USB error: %s\n", yk_usb_strerror()); emit diagnostics(QString("USB error: %1").arg(yk_usb_strerror())); } else { qDebug("Yubikey core error: %s\n", yk_strerror(yk_errno)); emit diagnostics(yk_strerror(yk_errno)); } switch(yk_errno) { case YK_ENOKEY: errMsg = tr(ERR_KEY_NOT_FOUND); break; case YK_EFIRMWARE: errMsg = tr(ERR_FIRMWARE_NOT_SUPPORTED); break; default: if(chalresp) { errMsg = tr(ERR_PROCESSING_CHALRESP); } else { errMsg = tr(ERR_PROCESSING); } break; } yk_errno = 0; } if(!errMsg.isEmpty()) { emit errorOccurred(errMsg); } return errMsg; } int YubiKeyWriter::assembleConfig(YubiKeyConfig *ykConfig, YKP_CONFIG *cfg, bool *useAccessCode, unsigned char *accessCode) { // Check features support bool flagSrNoSupport = false; bool flagUpdateSupport = false; bool flagImfSupport = false; bool flagLedInvSupport = false; YubiKeyFinder *finder = YubiKeyFinder::getInstance(); if(finder->checkFeatureSupport( YubiKeyFinder::Feature_SerialNumber)) { flagSrNoSupport = true; } if(finder->checkFeatureSupport( YubiKeyFinder::Feature_Updatable)) { flagUpdateSupport = true; } if(finder->checkFeatureSupport( YubiKeyFinder::Feature_MovingFactor)) { flagImfSupport = true; } if(finder->checkFeatureSupport( YubiKeyFinder::Feature_LedInvert)) { flagLedInvSupport = true; } //Programming Mode... bool longSecretKey = false; int command = ykConfig->configSlot() == 2 ? SLOT_CONFIG2 : SLOT_CONFIG; switch(ykConfig->programmingMode()) { case YubiKeyConfig::Mode_Update: // if we're doing an update it's other commands. command = ykConfig->configSlot() == 2 ? SLOT_UPDATE2 : SLOT_UPDATE1; break; case YubiKeyConfig::Mode_Swap: // swap has it's own command command = SLOT_SWAP; break; case YubiKeyConfig::Mode_YubicoOtp: break; case YubiKeyConfig::Mode_Static: CFGFLAG(STATIC_TICKET, ykConfig->staticTicket()); CFGFLAG(SHORT_TICKET, ykConfig->shortTicket()); CFGFLAG(STRONG_PW1, ykConfig->strongPw1()); CFGFLAG(STRONG_PW2, ykConfig->strongPw2()); CFGFLAG(MAN_UPDATE, ykConfig->manUpdate()); CFGFLAG(SEND_REF, ykConfig->sendRef()); break; case YubiKeyConfig::Mode_OathHotp: TKTFLAG(OATH_HOTP, true); CFGFLAG(OATH_HOTP8, ykConfig->oathHotp8()); CFGFLAG(OATH_FIXED_MODHEX1, ykConfig->oathFixedModhex1()); CFGFLAG(OATH_FIXED_MODHEX2, ykConfig->oathFixedModhex2()); CFGFLAG(OATH_FIXED_MODHEX, ykConfig->oathFixedModhex()); //Moving Factor Seed... if(flagImfSupport && !ykp_set_oath_imf(cfg, ykConfig->oathMovingFactorSeed())) { return 0; } //For OATH-HOTP, 160 bits key is also valid longSecretKey = true; break; case YubiKeyConfig::Mode_ChalRespYubico: TKTFLAG(CHAL_RESP, true); CFGFLAG(CHAL_YUBICO, ykConfig->chalYubico()); CFGFLAG(CHAL_BTN_TRIG, ykConfig->chalBtnTrig()); break; case YubiKeyConfig::Mode_ChalRespHmac: TKTFLAG(CHAL_RESP, true); CFGFLAG(CHAL_HMAC, ykConfig->chalHmac()); CFGFLAG(HMAC_LT64, ykConfig->hmacLT64()); CFGFLAG(CHAL_BTN_TRIG, ykConfig->chalBtnTrig()); //For HMAC (not Yubico) challenge-response, 160 bits key is also valid longSecretKey = true; break; } //Configuration slot... if (!ykp_configure_command(cfg, command)) { return 0; } //Public ID... if(ykConfig->pubIdTxt().length() > 0) { qDebug() << "Pub id: " << ykConfig->pubIdTxt() << "length:" << ykConfig->pubIdTxt().length(); char pubIdStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(pubIdStr, sizeof(pubIdStr), ykConfig->pubIdTxt()); size_t pubIdStrLen = strlen(pubIdStr); unsigned char pubId[MAX_SIZE]; size_t pubIdLen = 0; int rc = YubiKeyUtil::hexModhexDecode(pubId, &pubIdLen, pubIdStr, pubIdStrLen, 0, FIXED_SIZE * 2, !ykConfig->pubIdInHex()); if (rc <= 0) { qDebug("Invalid public id: %s", pubIdStr); return 0; } ykp_set_fixed(cfg, pubId, pubIdLen); } //Private ID... if(ykConfig->pvtIdTxt().length() > 0) { qDebug() << "Pvt id: " << ykConfig->pvtIdTxt() << "length:" << ykConfig->pvtIdTxt().length(); char pvtIdStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(pvtIdStr, sizeof(pvtIdStr), ykConfig->pvtIdTxt()); size_t pvtIdStrLen = strlen(pvtIdStr); unsigned char pvtId[MAX_SIZE]; size_t pvtIdLen = 0; int rc = YubiKeyUtil::hexModhexDecode(pvtId, &pvtIdLen, pvtIdStr, pvtIdStrLen, UID_SIZE * 2, UID_SIZE * 2, false); if (rc <= 0) { qDebug("Invalid private id: %s", pvtIdStr); return 0; } ykp_set_uid(cfg, pvtId, pvtIdLen); } //Secret Key... if(ykConfig->secretKeyTxt().length() > 0) { qDebug() << "Secret key: " << ykConfig->secretKeyTxt() << "length:" << ykConfig->secretKeyTxt().length(); char secretKeyStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(secretKeyStr, sizeof(secretKeyStr), ykConfig->secretKeyTxt()); int res = 0; if(longSecretKey && strlen(secretKeyStr) == 40) { res = ykp_HMAC_key_from_hex(cfg, secretKeyStr); } else { res = ykp_AES_key_from_hex(cfg, secretKeyStr); } if (res) { qDebug() << "Bad secret key: " << secretKeyStr; return 0; } } //Configuration protection... //Current Access Code... size_t accessCodeLen = 0; if(ykConfig->currentAccessCodeTxt().length() > 0) { int rc = encodeAccessCode(ykConfig->currentAccessCodeTxt(), accessCode, &accessCodeLen); if (rc <= 0) { qDebug() << "Invalid current access code: " << ykConfig->currentAccessCodeTxt(); return 0; } } //New Access Code... unsigned char newAccessCode[MAX_SIZE]; size_t newAccessCodeLen = 0; if(ykConfig->newAccessCodeTxt().length() > 0) { int rc = encodeAccessCode(ykConfig->newAccessCodeTxt(), newAccessCode, &newAccessCodeLen); if (rc <= 0) { qDebug() << "Invalid new access code: " << ykConfig->newAccessCodeTxt(); return 0; } if(ykConfig->accMode() > 0) { int accMode = 0; if(ykConfig->accMode() == Acc_None) { accMode = YKP_ACCCODE_NONE; } else if(ykConfig->accMode() == Acc_Serial) { accMode = YKP_ACCCODE_SERIAL; } else if(ykConfig->accMode() == Acc_Random) { accMode = YKP_ACCCODE_RANDOM; } ykp_set_acccode_type(cfg, accMode); } } if(accessCodeLen > 0) { *useAccessCode = true; } if(newAccessCodeLen > 0) { //Enable/change protection ykp_set_access_code(cfg, newAccessCode, newAccessCodeLen); } else if(accessCodeLen > 0) { //Keep same protection ykp_set_access_code(cfg, accessCode, accessCodeLen); } TKTFLAG(TAB_FIRST, ykConfig->tabFirst()); TKTFLAG(APPEND_TAB1, ykConfig->appendTab1()); TKTFLAG(APPEND_TAB2, ykConfig->appendTab2()); TKTFLAG(APPEND_CR, ykConfig->appendCr()); TKTFLAG(APPEND_DELAY1, ykConfig->appendDelay1()); TKTFLAG(APPEND_DELAY2, ykConfig->appendDelay2()); //TKTFLAG(PROTECT_CFG2, ykConfig->protectCfg2()); //CFGFLAG(SEND_REF, ykConfig->sendRef()); //CFGFLAG(TICKET_FIRST, ykConfig->ticketFirst()); CFGFLAG(PACING_10MS, ykConfig->pacing10ms()); CFGFLAG(PACING_20MS, ykConfig->pacing20ms()); //CFGFLAG(ALLOW_HIDTRIG, ykConfig->allowHidtrig()); //Serial # visibility... if(flagSrNoSupport) { EXTFLAG(SERIAL_BTN_VISIBLE, ykConfig->serialBtnVisible()); EXTFLAG(SERIAL_USB_VISIBLE, ykConfig->serialUsbVisible()); EXTFLAG(SERIAL_API_VISIBLE, ykConfig->serialApiVisible()); } if(flagUpdateSupport) { EXTFLAG(ALLOW_UPDATE, ykConfig->allowUpdate()); // XXX: let update support mean these as well.. EXTFLAG(DORMANT, ykConfig->dormant()); EXTFLAG(FAST_TRIG, ykConfig->fastTrig()); EXTFLAG(USE_NUMERIC_KEYPAD, ykConfig->useNumericKeypad()); } if(flagLedInvSupport) { EXTFLAG(LED_INV, ykConfig->ledInvert()); } return 1; } void YubiKeyWriter::writeConfig(YubiKeyConfig *ykConfig) { YubiKeyFinder::getInstance()->stop(); YK_KEY *yk = 0; YK_STATUS *ykst = YubiKeyFinder::getInstance()->status(); YKP_CONFIG *cfg = ykp_alloc(); bool error = false; qDebug() << "-------------------------"; qDebug() << "Starting write config"; qDebug() << "-------------------------"; try { if (!(yk = yk_open_first_key())) { throw 0; } else if (!yk_get_status(yk, ykst)) { throw 0; } ykp_configure_version(cfg, ykst); qDebug() << "writer:configuration slot:" << ykConfig->configSlot(); bool useAccessCode; unsigned char accessCode[MAX_SIZE]; if(!assembleConfig(ykConfig, cfg, &useAccessCode, accessCode)) { throw 0; } //Log configuration... qDebug() << "-------------------------"; qDebug() << "Config data to be written to key configuration..."; char conf_buf[1024]; ykp_export_config(cfg, conf_buf, 1024, YKP_FORMAT_LEGACY); qDebug() << conf_buf; qDebug() << "-------------------------"; // Write configuration... if (!yk_write_command(yk, ykp_core_config(cfg), ykp_command(cfg), useAccessCode ? accessCode : NULL)) { qDebug() << "Failure"; throw 0; } qDebug() << "Success... config written"; emit diagnostics(QString("Successfully wrote config to slot %1").arg(ykp_config_num(cfg))); YubiKeyLogger::logConfig(ykConfig); emit configWritten(true, NULL); } catch(...) { error = true; } if (cfg) { ykp_free_config(cfg); } if (yk && !yk_close_key(yk)) { error = true; } YubiKeyFinder::getInstance()->start(); if(error) { qDebug() << "Config not written"; QString errMsg = reportError(); emit configWritten(false, errMsg); } qDebug() << "-------------------------"; qDebug() << "Stopping write config"; qDebug() << "-------------------------"; } void YubiKeyWriter::exportConfig(YubiKeyConfig *ykConfig) { YubiKeyFinder::getInstance()->stop(); YK_KEY *yk = 0; YK_STATUS *ykst = YubiKeyFinder::getInstance()->status(); YKP_CONFIG *cfg = ykp_alloc(); bool error = false; qDebug() << "-------------------------"; qDebug() << "Starting write config"; qDebug() << "-------------------------"; try { if (!(yk = yk_open_first_key())) { throw 0; } ykp_configure_version(cfg, ykst); qDebug() << "writer:configuration slot:" << ykConfig->configSlot(); bool useAccessCode; unsigned char accessCode[MAX_SIZE]; if(!assembleConfig(ykConfig, cfg, &useAccessCode, accessCode)) { throw 0; } m_filename = QFileDialog::getSaveFileName(NULL, tr("Export File"), m_filename, tr("Yubico cfg format (*.ycfg)"), NULL); char data[1024]; int len = ykp_export_config(cfg, data, 1024, YKP_FORMAT_YCFG); if(!len) { throw 0; } QFile file(m_filename); if(!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { throw 0; } if(!file.write(data, len)) { throw 0; } file.close(); QSettings settings; settings.setValue(SG_EXPORT_FILENAME, m_filename); emit configWritten(true, NULL); emit diagnostics(QString("Exported config to file %1").arg(m_filename)); } catch(...) { error = true; } if (cfg) { ykp_free_config(cfg); } if (yk && !yk_close_key(yk)) { error = true; } YubiKeyFinder::getInstance()->start(); if(error) { qDebug() << "Config not exported"; QString errMsg = reportError(); emit configWritten(false, errMsg); } } void YubiKeyWriter::doChallengeResponse(const QString challenge, QString &response, int slot, bool hmac) { YubiKeyFinder::getInstance()->stop(); YK_KEY *yk = 0; bool error = false; qDebug() << "Challenge to slot " << slot << " with challenge: " << challenge; try { int yk_cmd; QByteArray chal_array = challenge.toLatin1(); const unsigned char *chal = reinterpret_cast(chal_array.constData()); unsigned char resp[64]; memset(resp, 0, sizeof(resp)); if (!(yk = yk_open_first_key())) { throw 0; } switch(slot) { case 1: yk_cmd = (hmac == true) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_OTP1; break; case 2: yk_cmd = (hmac == true) ? SLOT_CHAL_HMAC2 : SLOT_CHAL_OTP2; break; default: throw 0; break; } if(! yk_challenge_response(yk, yk_cmd, 1, challenge.length(), chal, sizeof(resp), resp)) { throw 0; } // 20 (160 bits) for hmac-sha1 and 16 (128 bits) for yubico mode if(hmac == true) { response = YubiKeyUtil::qstrHexEncode(resp, 20); } else { response = YubiKeyUtil::qstrModhexEncode(resp, 16); } emit diagnostics(QString("Successful challenge response with slot %1").arg(slot)); } catch(...) { error = true; } if (yk && !yk_close_key(yk)) { error = true; } YubiKeyFinder::getInstance()->start(); if(error) { qDebug() << "Challenge response failed."; QString errMsg = reportError(true); } } void YubiKeyWriter::writeNdef(bool uri, const QString language, const QString payload, const QString accCode, int slot) { YubiKeyFinder::getInstance()->stop(); YK_KEY *yk = 0; YK_NDEF *ndef = ykp_alloc_ndef(); bool error = false; qDebug() << "Writing ndef " << payload << " of type " << uri; try { if(accCode.length() > 0) { unsigned char accessCode[MAX_SIZE]; size_t accessCodeLen = 0; int rc = encodeAccessCode(accCode, accessCode, &accessCodeLen); if (rc <= 0) { qDebug() << "Invalid access code: " << accCode; throw 0; } ykp_set_ndef_access_code(ndef, accessCode); } QByteArray payload_array = payload.toUtf8(); const char *ndef_payload = payload_array.constData(); qDebug() << "payload: " << ndef_payload; if (!(yk = yk_open_first_key())) { throw 0; } if(uri) { if(!ykp_construct_ndef_uri(ndef, ndef_payload)) { throw 0; } } else { QByteArray lang_array = language.toUtf8(); const char *lang = lang_array.constData(); if(!ykp_construct_ndef_text(ndef, ndef_payload, lang, false)) { throw 0; } } qDebug() << "writing the ndef."; if(! yk_write_ndef2(yk, ndef, slot)) { throw 0; } emit configWritten(true, NULL); emit diagnostics(QString("Wrote NDEF for slot %1").arg(slot)); } catch(...) { error = true; } if(ndef && !ykp_free_ndef(ndef)) { error = true; } if (yk && !yk_close_key(yk)) { error = true; } YubiKeyFinder::getInstance()->start(); if(error) { qDebug() << "Writing NDEF failed."; QString errMsg = reportError(); emit configWritten(false, errMsg); } } void YubiKeyWriter::deleteConfig(int slot, const QString accCode) { bool error = false; YK_KEY *yk = NULL; YKP_CONFIG *cfg = ykp_alloc(); YubiKeyFinder::getInstance()->stop(); try { if (!(yk = yk_open_first_key())) { throw 0; } unsigned char accessCode[MAX_SIZE]; size_t accessCodeLen = 0; if(accCode.length() > 0) { int rc = encodeAccessCode(accCode, accessCode, &accessCodeLen); if (rc <= 0) { qDebug() << "Invalid access code: " << accCode; throw 0; } } // write NULL to delete config if (!yk_write_config(yk, NULL, slot, accessCodeLen > 0 ? accessCode : NULL)) { qDebug() << "Failed to delete."; throw 0; } emit configWritten(true, NULL); qDebug() << "successfully deleted slot " << slot; emit diagnostics(QString("Deleted slot %1").arg(slot)); } catch(...) { error = true; } if (cfg) { ykp_free_config(cfg); } if (yk && !yk_close_key(yk)) { error = true; } YubiKeyFinder::getInstance()->start(); if(error) { qDebug() << "Failed to delete configuration in slot" << slot; QString errMsg = reportError(); emit configWritten(false, errMsg); } } int YubiKeyWriter::encodeAccessCode(QString accCode, unsigned char* accessCode, size_t *accessCodeLen) { qDebug() << "access code: " << accCode << "length:" << accCode.length(); char accessCodeStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(accessCodeStr, sizeof(accessCodeStr), accCode); size_t accessCodeStrLen = strlen(accessCodeStr); int rc = YubiKeyUtil::hexModhexDecode(accessCode, accessCodeLen, accessCodeStr, accessCodeStrLen, ACC_CODE_SIZE * 2, ACC_CODE_SIZE * 2, false); return rc; } void YubiKeyWriter::setExportFilename(QString filename) { m_filename = filename; } QString YubiKeyWriter::defaultExportFilename() { return QDir::homePath() + "/" + EXPORT_FILENAME_DEF; } yubikey-personalization-gui-3.1.24/src/version.h0000664000175000017500000000367312642452141020372 0ustar klasklas/* Copyright (C) 2011-2016 Yubico AB. 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. 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 HOLDER 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. */ #ifndef VERSION_H #define VERSION_H #define VER_PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_BUILD,0 #define VER_PRODUCTVERSION_STR VERSION "\0" #define VER_FILEDESCRIPTION_STR "YubiKey Personalization Tool" #define VER_INTERNALNAME_STR "YKPersonalization" #define VER_LEGALCOPYRIGHT "Copyright © 2011-2016 Yubico" #define VER_LEGALTRADEMARKS1_STR "All Rights Reserved" #define VER_ORIGINALFILENAME_STR "YKPersonalization.exe" #define VER_PRODUCTNAME_STR "YKPersonalization" #define VER_COMPANYNAME_STR "Yubico" #define VER_COMPANYDOMAIN_STR "yubico.com" #endif // VERSION_H yubikey-personalization-gui-3.1.24/src/yubikeylogger.h0000664000175000017500000000620012642452141021553 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef YUBIKEYLOGGER_H #define YUBIKEYLOGGER_H #include #include #include #include #include #include "common.h" #include "yubikeyconfig.h" struct logging_st { const char *name; const char *configName; int returnType; QString (*resolver)(YubiKeyConfig*, QString); }; class YubiKeyLogger : public QObject { Q_OBJECT public: ~YubiKeyLogger(); enum Format { Format_Traditional, Format_Yubico, Format_Flexible, Format_PSKC, }; static void logConfig(YubiKeyConfig *ykConfig); static void enableLogging(); static void disableLogging(); static bool isLogging(); static void setLogFilename(const QString &filename); static QString logFilename(); static QString defaultLogFilename(); static void setLogFormat(Format format); static void setFlexibleFormat(QString); static QStringList getLogNames(); static void closeLogFile(void); private: static bool m_enabled; static QString m_filename; static bool m_started; static Format m_format; static QString m_flexibleFormat; static logging_st logging_map[]; static QString formatLog(YubiKeyConfig *ykConfig, QString format); static QFile *m_logFile; static QFile *getLogFile(void); static void endPSKC(); static void logString(QString); static QString resolve_eventType(YubiKeyConfig*, QString); static QString resolve_timestamp(YubiKeyConfig*, QString); static QString resolve_hotpDigits(YubiKeyConfig*, QString); static QString resolve_symbol(YubiKeyConfig*, QString); static QString resolve_secretKeyB64(YubiKeyConfig*, QString); static QString resolve_tokenLength(YubiKeyConfig*, QString); static QString resolve_accessCode(YubiKeyConfig*, QString); }; #endif // YUBIKEYLOGGER_H yubikey-personalization-gui-3.1.24/src/yubikeyfinder.h0000664000175000017500000000640012642452141021545 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef YUBIKEYFINDER_H #define YUBIKEYFINDER_H #include #include extern "C" { #include } #include "common.h" class YubiKeyFinder : public QObject { Q_OBJECT public: static YubiKeyFinder* getInstance(); ~YubiKeyFinder(); enum State { State_Absent, State_Present, State_Processing, State_NoFocus, }; enum Feature { Feature_MultipleConfigurations, Feature_ProtectConfiguration2, Feature_StaticPassword, Feature_ScanCodeMode, Feature_ShortTicket, Feature_StrongPwd, Feature_OathHotp, Feature_ChallengeResponse, Feature_SerialNumber, Feature_MovingFactor, Feature_ChallengeResponseFixed, Feature_Updatable, Feature_Ndef, Feature_LedInvert, Feature_U2F, }; State state() const {return m_state;} unsigned int version() const {return m_version;} unsigned int serial() const {return m_serial;} int touchLevel() const {return m_touchLevel;} YK_STATUS *status() const { return m_ykds;} QString versionStr(); void reportError(); bool checkFeatureSupport(Feature feature); private: YubiKeyFinder(); void init(); bool openKey(); bool closeKey(); static YubiKeyFinder* _instance; static const unsigned int FEATURE_MATRIX[][2]; static const unsigned int FEATURE_MATRIX_EXCLUDE[][4]; State m_state; YK_KEY *m_yk; YK_STATUS *m_ykds; unsigned int m_version; unsigned int m_versionMinor; unsigned int m_versionMajor; unsigned int m_versionBuild; unsigned int m_serial; int m_touchLevel; QTimer *m_timer; public slots: void findKey(); void start(); void stop(); signals: void keyFound(bool found, bool* featuresMatrix, int error); void errorOccurred(const QString &text); void diagnostics(const QString &text); }; #endif // YUBIKEYFINDER_H yubikey-personalization-gui-3.1.24/src/help.h0000664000175000017500000003027412642452141017632 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef HELP_H #define HELP_H #define HELP_CONFIG_SLOT "

YubiKey 2.x and later comes with two configuration slots. Each configuration slot works independent of each other and can be programmed in any of the following modes:

  1. Yubico OTP
  2. OATH-HOTP
  3. Static Password
  4. Challenge-Response (YubiKey 2.2 and onwards)

The first slot is used to generate the output when the YubiKey button is touched between 0.3 to 1.5 seconds and released and the second slot is used if the button is touched between 2 to 5 seconds.

When the YubiKey 2.X is shipped, it's first configuration slot is factory programmed for Yubico OTP mode (which works with online Yubico OTP validation server) and the second configuration slot is left blank.

" #define HELP_PUBLIC_ID "

Before the OTP string, a fixed optional Public Identity can be used as a prefix which identifies a particular YubiKey.

Important Note: Yubico OTP validation server requires Public Identity to be of 12 characters (6 bytes) in order to correctly extract the Secret Key. If you change the Public Identity to any other length, the Yubico OTP validation server won't be able to extract the Secret Key and the OTP validation will fail.

For additional information, please refer to YubiKey Personalization Tool user guide.

" #define HELP_PRIVATE_ID "

Private Identity is an optional secret field that is included as an input parameter in the OTP generation algorithm.

For additional information, please refer to YubiKey Personalization Tool user guide.

" #define HELP_SECRET_KEY "

Secret Key is a mandatory cryptographic key needed to compute the OTP or the Response code for a given Challenge.

" #define HELP_PARAM_GENERATION "

Parameter Generation Scheme defines how the Public Identity, Private Identity and Secret Key parameters are generated when multiple programming YubiKeys are to be programmed based on the initial inputs and then just inserting YubiKeys one by one.

The following options are available:

  1. Increment Identities; Randomize Secret: If this option is selected, the Public Identity and Private Identity values are incremented by one and the Secret Key is randomly generated for each new YubiKey to be programmed.
  2. Randomize all parameters: If this option is selected, all 3 parameters i.e. the Public Identity, Private Identity and Secret Key are randomly generated for each new YubiKey to be programmed.
  3. Fixed parameters: if this option is selected, all 3 parameters i.e. the Public Identity, Private Identity and Secret Key remain unchanged for each new YubiKey to be programmed.
  4. " #define HELP_CONFIG_PROTECTION "

    For security reasons and for avoiding accidental reprogramming, YubiKeys can be protected using configuration protection access code.

    If the configuration protection access code is set, no one can reprogram the YubiKey unless the correct access code is provided during reprogramming.

    The following operations are supported:

    1. YubiKey(s) unprotected - Keep it that way: Use this option if the YubiKey is currently unprotected and you want to keep it that way
    2. YubiKey(s) unprotected - Enable protection: Use this option if the YubiKey is currently unprotected and you want to enable the protection. You are required to provide the New Access Code if you select this option.
    3. YubiKey(s) protected - Disable protection: Use this option if the YubiKey is currently protected and you want to disable the protection. You are required to provide your Current Access Code if you select this option.
    4. YubiKey(s) protected - Keep it that way: Use this option if the YubiKey is currently protected and you want to keep it that way. You are required to provide your Current Access Code if you select this option.
    5. YubiKey(s) protected - Change access code: Use this option if the YubiKey is currently protected and you want to chagne the access code. You are required to provide your Current Access Code and New Access Code if you select this option.

    Important Note: It is not possible to retrieve the access code from the YubiKey. Yubico highly recommends users to record the access code for each YubiKey programmed. This can be achieved easily by ensuring that logging is enabled and archiving the relevant log records.

    " #define HELP_OUTPUT_FORMAT "

    When programmed in OTP mode, this option can be used to insert Tab and Enter characters at various positions in the OTP output string.

    The following options are available:

    1. A Tab before Public ID
    2. A Tab between Public ID and OTP
    3. A Tab after OTP
    4. An Enter at the end of the output string
    5. Each \"pressed\" button indicates the corresponding character is enabled at the specified position.

      " #define HELP_OUTPUT_SPEED "

      When programmed in OTP mode, this option can be used to introduce a small delay of 20, 40 or 60ms between the characters emitted by the YubiKey.

      This may be required under very rare and exceptional circumstances if some characters of the YubiKey output string are missed.

      Also, if there is some parsing - or GUI rendering delay for a particular application, an additional 500 ms delay can be inserted before and after sending the OTP.

      " #define HELP_SR_NO_VISIBILITY "

      Yubikey 2.2 or later has a non-alterable, factory programmed unique serial number which is different than the public identities configured.

      The following options are available for serial number reading:

      1. Button at startup: This option allows the serial number to be read at device powerup.
      2. USB descriptor: This option makes the device serial number visible in the serial number field in the USB device descriptor. Please note that the YubiKey must be removed and reinserted after this option is enabled in order for the operating system to recognize the updated device descriptor.
      3. API call: This option allows the device serial number to be read via a client-side application via a software interface, such as the Yubikey Client API.
      4. For additional information, please refer to YubiKey Personalization Tool user guide.

        " #define HELP_OATH_PUBLIC_ID "

        The YubiKey supports the Class A Token Identifier Specification as outlined by openauthentication.org.

        The general format of the 12 character (6 bytes) OATH Token Identifier is as follows:
        [MM][TT][UUUUUUUU],where -
        8 characters that uniquely identify the token for a given manufacturer and token type
        MMOATH Manufacturer prefix (OMP)A 2 character prefix, assigned by OATH.
        Yubico's OMP is \"ub\"
        TTToken Type (TT)A 2 character token type, assigned by the manufacturer
        UUUUUUUUManufacturer Unique Identifier (MUI)

        The Token Identifier can be configured to be all numeric, OMP Modhex, OMP + TT Modhex or all Modhex.

        " #define HELP_HOTP_LEN "

        According to the OATH-HOTP standard RFC 4226, the YubiKey supports 6 or 8 digit HOTP values.

        " #define HELP_HOTP_PARAM "

        According to the OATH-HOTP standard RFC 4226, moving factor is a counter value that must be synchronized between the HOTP generator (YubiKey) and the HOTP validator (server).

        " #define HELP_STATIC_SCAN_CODE "

        The Scan Code mode allows a YubiKey to be programmed to emit the desired static password.

        Type in the characters of your static password in the \"Password\" field using the keyboard and the tool will automatically fill-in the corresponding scan codes of characters in the field.

        The tool maps the scan codes assuming a US standard keyboard layout, so the results might differ depending on the layout you use. In such cases, try setting the keyboard layout to US standard and then typing the password as you normally would on your keyboard - the characters in the password field will not match but the eventual output will.

        " #define HELP_CHALRESP_YUBICO "

        The Challenge-Response mode allows programmatic interaction between a client-side application and the YubiKey by support of a client-side interface software, such as the YubiKey Client API.

        The challenge-response mode can either be Yubico OTP compatible mode or HMAC-SHA1.

        The Yubico OTP Challenge-Response mode takes a 6 byte challenge and creates a response using Yubico OTP algorithm. In this mode, the YubiKey makes use of some variable fields and hence generates a different response every time even if the challenge is same.

        " #define HELP_CHALRESP_HMAC "

        The Challenge-Response mode allows programmatic interaction between a client-side application and the YubiKey by support of a client-side interface software, such as the YubiKey Client API.

        The challenge-response mode can either be Yubico OTP compatible mode or HMAC-SHA1.

        The HMAC-SHA1 Challenge-Response mode takes a 0-64 byte challenge and creates a HMAC using HMAC-SHA1 algorithm in combination with a 20 byte secret key. In this mode, the YubiKey does not make use of any variable field and hence generates an identical response if the challenge is same.

        " #define HELP_CHALRESP_OPTION "

        If this option is selected, when a client-side interface software presents a Challenge to the YubiKey, the light starts flashing and the user has to touch the YubiKey button to acknowledge the challenge-response operation before the computed Response is sent back.

        " #define HELP_ALLOW_UPDATE_OPTION "

        If this option is selected the YubiKey configuration will be updatable, without rewriting the aes-key. Only non-security related settings are changeable with this.

        " #define HELP_SWAP_OPTION "

        If both slots are configured to allow updates they can be swapped with this option. That is slot 1 and slot 2 will change places.

        " #define HELP_MAN_UPDATE_OPTION "

        The manual update setting is to allow the static password in the YubiKey to be changed without reprogramming the key. If it is set it can be triggered by holding the button for 10 seconds, releasing and then tapping it again, the YubiKey will then generate a new static password.

        " #define HELP_LOG_FORMAT "

        With the flexible logging format the format can be specified manually, this is done by adding a number of variables enclosed in {}, newline and tab can be added with variables endl and tab. Currently supported variables are: " #endif // HELP_H yubikey-personalization-gui-3.1.24/src/ui/0000775000175000017500000000000012642452141017140 5ustar klasklasyubikey-personalization-gui-3.1.24/src/ui/oathpage.ui0000664000175000017500000015555612642452141021310 0ustar klasklas OathPage 0 0 730 650 0 0 730 650 StackedWidget font: 11px "Verdana"; color: rgb(0, 0, 0); 2 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in OATH-HOTP mode Qt::AlignCenter 10 50 710 171 border-color: rgb(0, 0, 0); Qt::AlignCenter 20 20 110 25 0 0 font: 12px; font-weight: bold; Quick false false false 20 100 110 25 font: 12px; font-weight: bold; Advanced false false false 20 45 671 20 Quickly program a YubiKey in OATH-HOTP mode Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 120 671 30 Allows you to program one or more YubiKeys in OATH-HOTP mode with greater control over the configuration values Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in OATH-HOTP mode - Quick Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 291 16 font-weight: normal; color: rgb(118, 116, 108) Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 132 711 130 font-weight: bold; OATH-HOTP Parameters (auto generated) false false 685 50 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 27 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 100 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 50 221 20 <!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:'Verdana'; font-weight:600; 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=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">HOTP Length</span></p></td></tr></table></body></html> Qt::RichText true 280 25 181 20 0 0 font-weight: normal; 00 00 00 00; QLineEdit::Normal 11 false true 240 100 371 20 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh; QLineEdit::Password 59 true 10 75 221 18 font-weight: normal; Hide secret true 240 51 71 17 font-weight: normal; 6 Digits true true 320 51 71 17 font-weight: normal; 8 Digits true false 10 100 221 20 font-weight:normal; Secret Key (20 bytes Hex) 10 25 221 17 font-weight: normal; OATH Token Identifier (6 bytes) 470 23 141 24 font: 12px; font-weight: bold; Generate MUI false false false 240 25 41 20 font: 12px; font-weight: bold; 10 272 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false 335 45 85 25 font: 12px; font-weight: bold; Back false false false 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot true 200 45 120 25 font: 12px; font-weight: bold; Regenerate false false false 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in OATH-HOTP mode - Advanced Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 331 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 true false 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 249 711 157 font-weight: bold; OATH-HOTP Parameters 685 127 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 240 125 330 20 0 0 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 59 580 123 100 24 font: 12px; font-weight: bold; Generate false false false 240 25 330 20 0 0 font-weight: normal; All numeric OMP Modhex, rest numeric OMP + TT Modhex, rest numeric All Modhex 320 50 111 20 0 0 font-weight: normal; nn nn nn nn; 00 00 00 00 11 11 281 50 30 20 0 0 font-weight: normal; nn; 00 2 2 241 50 30 20 0 0 font-weight: normal; nn; 00 2 2 440 48 130 24 font: 12px; font-weight: bold; Generate MUI false false false 10 125 221 20 font-weight:normal; Secret Key (20 bytes Hex) 10 25 221 17 font-weight: normal; OATH Token Identifier (6 bytes) 10 75 221 20 font-weight:normal; HOTP Length 320 76 71 17 font-weight: normal; 8 Digits true false 240 76 71 17 font-weight: normal; 6 Digits true true 10 100 221 20 font-weight:normal; Moving Factor Seed 240 99 191 20 0 0 font-weight: normal; Fixed zero Fixed Randomize false 440 99 130 20 font-weight: normal; 00000000; 0 8 8 685 27 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 102 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 50 221 16 font-weight: normal; color: rgb(118, 116, 108); OMP (1) + TT (1) + MUI (4) 685 77 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 416 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false false 200 45 85 25 font: 12px; font-weight: bold; Stop false false false 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot 400 45 85 25 font: 12px; font-weight: bold; Back false false false true 300 45 85 25 font: 12px; font-weight: bold; Reset false false false 580 45 100 25 font: 12px; font-weight: bold; Export false false false 10 132 350 107 font-weight: bold; Program Multiple YubiKeys true false 10 25 331 17 font-weight: normal; Automatically program YubiKeys when inserted 10 75 331 22 0 0 font-weight: normal; Increment Identities; Randomize Secret Randomize all parameters 10 52 191 20 font-weight:normal; Parameter Generation Scheme Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 325 52 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 506 711 130 font-weight: bold; Results 12 20 688 100 font: 11px "Verdana"; color: rgb(0, 0, 0); Qt::ScrollBarAlwaysOn true false Qt::SolidLine true 0 4 50 false 20 # OATH Token Identifier Status Timestamp 370 132 350 117 YubiAccBox QWidget

        yubiaccbox.h
        1 quickBtn advBtn quickConfigSlot1Radio quickConfigSlot2Radio quickPubIdCheck quickMUITxt quickMUIGenerateBtn quickHotpLen6Radio quickHotpLen8Radio quickHideParams quickSecretKeyTxt quickWriteConfigBtn quickResetBtn quickBackBtn quickConfigHelpBtn quickPubIdHelpBtn quickHotpLenHelpBtn quickSecretKeyHelpBtn advConfigSlot1Radio advConfigSlot2Radio advProgramMulKeysBox advAutoProgramKeysCheck advConfigParamsCombo advPubIdCheck advPubIdFormatCombo advOMPTxt advTTTxt advMUITxt advMUIGenerateBtn advHotpLen6Radio advHotpLen8Radio advMovingFactorSeedCombo advMovingFactorSeedTxt advSecretKeyTxt advSecretKeyGenerateBtn advWriteConfigBtn advStopBtn advResetBtn advBackBtn advResultsWidget advConfigHelpBtn advParamGenSchemeHelpBtn advPubIdHelpBtn advHotpLenHelpBtn advHotpParamsHelpBtn advSecretKeyHelpBtn yubikey-personalization-gui-3.1.24/src/ui/staticpage.ui0000664000175000017500000016212212642452141021627 0ustar klasklas StaticPage 0 0 730 650 0 0 730 650 StackedWidget font: 11px "Verdana"; color: rgb(0, 0, 0); 1 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Static Password mode Qt::AlignCenter 10 50 710 171 border-color: rgb(0, 0, 0); Qt::AlignCenter 20 20 110 25 0 0 font: 12px; font-weight: bold; Scan Code false false false 20 100 110 25 font: 12px; font-weight: bold; Advanced false false false 20 45 671 20 Quickly program a YubiKey to emit your desired static password Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 120 671 30 Allows you to program one or more YubiKeys to emit long, "hard to guess and remember" static passwords Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Static Password mode - Scan Code Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 240 711 190 font-weight: bold; Password false false 685 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 150 75 205 20 0 0 font-weight: normal; 76 QLineEdit::Normal false 10 50 110 20 font-weight:normal; Password Length 10 75 110 20 font-weight:normal; Password 40 146 661 31 font-weight:normal; It is strongly recommended to create a backup YubiKey with same password in case original YubiKey is lost/broken true 180 50 431 20 font-weight: normal; color: rgb(118, 116, 108) (Max. 38 chars for YubiKey 2.2+ and 16 chars for 2.0 and 2.1) 10 150 24 24 0 0 ArrowCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/recommend.png); color: lightgray; border-radius: 1px; false false 150 100 111 24 font: 12px; font-weight: bold; Insert Tab false false false 150 50 31 20 0 270 100 85 25 font: 12px; font-weight: bold; Clear false false false 10 25 221 18 font-weight: normal; Hide Password false 370 75 110 20 font-weight:normal; Scan codes 490 75 200 20 Verdana -1 50 false false font-weight: normal; 490 105 51 20 font-weight:normal; Keyboard 549 101 141 22 0 0 font-weight: normal; Choose a layout ... US Keyboard DE Keyboard 10 440 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false 400 45 85 25 font: 12px; font-weight: bold; Back false false false 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot false 300 45 85 25 font: 12px; font-weight: bold; Reset false false false false 200 45 85 25 font: 12px; font-weight: bold; Stop false false false 10 132 350 107 font-weight: bold; Program Multiple YubiKeys true false 10 25 331 17 font-weight: normal; Automatically program YubiKeys when inserted 10 520 711 130 font-weight: bold; Results 12 20 688 100 font: 11px "Verdana"; color: rgb(0, 0, 0); Qt::ScrollBarAlwaysOn true false Qt::SolidLine true 0 4 50 false 20 # Password Length Status Timestamp 370 132 350 117 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Static Password mode - Advanced Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 true false 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 249 711 161 font-weight: bold; Password Parameters 685 102 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 240 100 330 20 0 0 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 47 580 98 100 24 font: 12px; font-weight: bold; Generate false false false 240 50 330 20 0 0 font-weight: normal; 0 0 240 75 330 20 0 0 font-weight: normal; hh hh hh hh hh hh 00 00 00 00 00 00 17 17 580 48 100 24 font: 12px; font-weight: bold; Generate false false false 580 73 100 24 font: 12px; font-weight: bold; Generate false false false 685 52 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 77 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 25 221 20 font-weight:normal; Password Length 10 100 221 20 font-weight:normal; Secret Key (16 bytes Hex) 10 50 221 20 font-weight:normal; Public Identity (1-16 bytes Modhex) 10 75 221 20 font-weight:normal; Private Identity (6 bytes Hex) 360 23 42 20 font-weight: normal; QAbstractSpinBox::UpDownArrows QAbstractSpinBox::CorrectToNearestValue 32 64 2 32 10 125 221 20 font-weight:normal; Strong Password Policy 240 130 147 17 font-weight: normal; Upper and lower case 410 130 101 17 font-weight: normal; Alphanumeric 540 130 157 17 font-weight: normal; Send ! as prefix 240 25 72 17 font-weight: normal; 16 chars true false 340 25 17 17 font-weight: normal; true 410 25 31 20 font-weight:normal; chars 450 25 251 20 font-weight: normal; color: rgb(118, 116, 108) (16 chars for YubiKey 2.0 and above only) 10 421 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false false 200 45 85 25 font: 12px; font-weight: bold; Stop false false false 20 20 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot 400 45 85 25 font: 12px; font-weight: bold; Back false false false false 300 45 85 25 font: 12px; font-weight: bold; Reset false false false 10 132 350 107 font-weight: bold; Program Multiple YubiKeys true false 10 25 331 17 font-weight: normal; Automatically program YubiKeys when inserted 10 52 191 20 font-weight:normal; Parameter Generation Scheme Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 75 331 22 0 0 font-weight: normal; Increment Identities; Randomize Secret Randomize all parameters Fixed parameters 325 52 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 511 711 130 font-weight: bold; Results 12 20 688 100 font: 11px "Verdana"; color: rgb(0, 0, 0); Qt::ScrollBarAlwaysOn true false Qt::SolidLine true 0 5 50 false 20 # Password Length Public Identity (Modhex) Status Timestamp 370 132 350 117 YubiAccBox QWidget
        yubiaccbox.h
        1
        quickBtn advBtn quickConfigSlot1Radio quickConfigSlot2Radio quickProgramMulKeysBox quickAutoProgramKeysCheck quickHideParams quickStaticTxt quickInsertTabBtn quickClearBtn quickWriteConfigBtn quickStopBtn quickResetBtn quickBackBtn quickResultsWidget quickConfigHelpBtn quickStaticScanCodeHelpBtn quickStaticBkpHelpBtn advConfigSlot1Radio advConfigSlot2Radio advProgramMulKeysBox advAutoProgramKeysCheck advConfigParamsCombo advStaticLen16Radio advStaticLen32Radio advStaticLenBox advPubIdTxt advPubIdGenerateBtn advPvtIdTxt advPvtIdGenerateBtn advSecretKeyTxt advSecretKeyGenerateBtn advStrongPw1Check advStrongPw2Check advStrongPw3Check advWriteConfigBtn advStopBtn advResetBtn advBackBtn advResultsWidget advConfigHelpBtn advParamGenSchemeHelpBtn advPubIdHelpBtn advPvtIdHelpBtn advSecretKeyHelpBtn
        yubikey-personalization-gui-3.1.24/src/ui/otppage.ui0000664000175000017500000014210212642452141021136 0ustar klasklas OtpPage 0 0 730 650 0 0 730 650 StackedWidget font: 11px "Verdana"; color: rgb(0, 0, 0); 2 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Yubico OTP mode Qt::AlignCenter 10 50 710 171 border-color: rgb(0, 0, 0); Qt::AlignCenter 20 20 110 25 0 0 font: 12px; font-weight: bold; Quick false false false 20 100 110 25 font: 12px; font-weight: bold; Advanced false false false 20 45 671 20 Quickly program a YubiKey for use with Yubico Validation Server Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 120 671 30 Allows you to program one or more YubiKeys with greater control over the configuration values Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Yubico OTP mode - Quick Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 132 711 130 font-weight: bold; Yubico OTP Parameters (auto generated) false false 685 27 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 77 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 102 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false true 240 25 341 20 0 0 font-weight: normal; nn nn nn nn nn nn; QLineEdit::Normal true true 240 75 341 20 font-weight: normal; hh hh hh hh hh hh; QLineEdit::Password 17 true true 240 100 341 20 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh; QLineEdit::Password 47 true 10 50 221 18 font-weight: normal; Hide values true 10 25 221 20 font-weight:normal; Public Identity (6 bytes Modhex) 10 75 221 20 font-weight:normal; Private Identity (6 bytes Hex) 10 100 221 20 font-weight:normal; Secret Key (16 bytes Hex) 10 272 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false 505 45 85 25 font: 12px; font-weight: bold; Back false false false false 200 45 155 25 font: 12px; font-weight: bold; Upload to Yubico false false false 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot true 370 45 120 25 font: 12px; font-weight: bold; Regenerate false false false 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Yubico OTP mode - Advanced Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 true false 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 249 711 132 font-weight: bold; Yubico OTP Parameters 685 102 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 240 100 330 20 0 0 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 47 580 98 100 24 font: 12px; font-weight: bold; Generate false false false 239 25 331 20 0 0 font-weight: normal; nn nn nn nn nn nn nn nn nn nn nn nn nn nn nn nn; 00 00 00 00 00 00 47 47 240 75 330 20 0 0 font-weight: normal; hh hh hh hh hh hh; 00 00 00 00 00 00 17 17 580 23 100 24 font: 12px; font-weight: bold; Generate false false false 580 73 100 24 font: 12px; font-weight: bold; Generate false false false 685 27 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 685 77 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 25 225 17 font-weight: normal; Public Identity (1-16 bytes Modhex) 10 75 221 17 font-weight: normal; Private Identity (6 bytes Hex) 10 50 221 20 font-weight:normal; Public Identity Length 10 100 221 20 font-weight:normal; Secret Key (16 bytes Hex) 240 50 42 20 font-weight: normal; QAbstractSpinBox::UpDownArrows QAbstractSpinBox::CorrectToNearestValue 1 16 1 6 290 50 411 20 font-weight: normal; color: rgb(118, 116, 108) (6 bytes is default length as required by Yubico OTP validation server) 10 391 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false false 200 45 85 25 font: 12px; font-weight: bold; Stop false false false 20 20 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot 400 45 85 25 font: 12px; font-weight: bold; Back false false false true 300 45 85 25 font: 12px; font-weight: bold; Reset false false false 580 45 100 25 font: 12px; font-weight: bold; Export false false false 10 132 350 107 font-weight: bold; Program Multiple YubiKeys true false 10 25 331 17 font-weight: normal; Automatically program YubiKeys when inserted 10 52 191 20 font-weight:normal; Parameter Generation Scheme Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 75 331 22 0 0 font-weight: normal; Increment Identity; Randomize Secrets Randomize all parameters Identity from serial; Randomize Secrets 325 52 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 481 711 130 font-weight: bold; Results 12 20 688 100 font: 11px "Verdana"; color: rgb(0, 0, 0); Qt::ScrollBarAlwaysOn true false Qt::SolidLine true 0 4 50 false 20 # Public Identity (Modhex) Status Timestamp 370 132 350 117 YubiAccBox QWidget
        yubiaccbox.h
        1
        quickBtn advBtn quickConfigSlot1Radio quickConfigSlot2Radio quickPubIdTxt quickHideParams quickPvtIdTxt quickSecretKeyTxt quickWriteConfigBtn quickUploadBtn quickResetBtn quickBackBtn quickConfigHelpBtn quickPubIdHelpBtn quickPvtIdHelpBtn quickSecretKeyHelpBtn advConfigSlot1Radio advConfigSlot2Radio advProgramMulKeysBox advAutoProgramKeysCheck advConfigParamsCombo advPubIdCheck advPubIdTxt advPubIdGenerateBtn advPubIdLenBox advPvtIdCheck advPvtIdTxt advPvtIdGenerateBtn advSecretKeyTxt advSecretKeyGenerateBtn advWriteConfigBtn advStopBtn advResetBtn advBackBtn advResultsWidget advConfigHelpBtn advPubIdHelpBtn advPvtIdHelpBtn advSecretKeyHelpBtn advParamGenSchemeHelpBtn
        yubikey-personalization-gui-3.1.24/src/ui/settingpage.ui0000664000175000017500000012225612642452141022021 0ustar klasklas SettingPage 0 0 730 650 0 0 730 650 StackedWidget font: 11px "Verdana"; color: rgb(0, 0, 0); 0 0 0 730 650 Form font: 11px "Verdana"; color: rgb(0, 0, 0); 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Settings Qt::AlignCenter 10 35 711 70 font-weight: bold; General Settings 10 40 231 17 font-weight: normal; Use and enforce customer prefix true 240 40 61 20 font-weight: normal; 5 0 240 20 61 18 font-weight: normal; color: rgb(118, 116, 108); Decimal Qt::AlignCenter 340 20 61 18 font-weight: normal; color: rgb(118, 116, 108); ModHex Qt::AlignCenter true 340 40 61 20 font-weight: normal; 32767 0 440 20 61 18 font-weight: normal; color: rgb(118, 116, 108); Hex Qt::AlignCenter true 440 40 61 20 font-weight: normal; 4 0 10 450 711 50 font-weight: bold; Logging Settings 10 25 171 19 font-weight: normal; Log configuration output 200 25 125 22 0 0 font-weight: normal; Traditional format Yubico format Flexible format PSKC format false 350 25 325 20 font-weight: normal; 680 25 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 550 711 80 font-weight: bold; Actions 10 25 200 16 font-weight: normal; color: rgb(118, 116, 108) Settings are saved automatically true 10 45 171 25 font: 12px; font-weight: bold; Restore Defaults false false false false 480 45 171 27 Update Settings... 405 25 275 16 font-weight: normal; color: rgb(118, 116, 108) Update is available for YubiKey 2.3 and later 10 105 711 165 font-weight: bold; Output Settings 10 25 691 58 font-weight: bold; Output Format false 10 25 68 25 font: 12px; font-weight: bold; Tab true false false false 170 25 68 25 font: 12px; font-weight: bold; Tab true false false false 310 25 68 25 font: 12px; font-weight: bold; Tab true false false false 98 25 52 25 font-weight:normal; Public ID 258 25 32 25 font-weight:normal; OTP 398 25 68 25 font: 12px; font-weight: bold; Enter true true false false false 665 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 85 691 70 font-weight: bold; Output Speed Throttling 665 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 170 24 171 22 0 0 font-weight: normal; Standard Slow down by 20 ms Slow down by 40 ms Slow down by 60 ms 10 25 151 20 font-weight:normal; Output Character Rate 10 50 281 17 font-weight: normal; Add a short delay before sending OTP part 360 50 271 17 font-weight: normal; Add a short delay after sending OTP part 10 275 350 100 font-weight: bold; Serial # Visibility Settings 10 25 221 17 font-weight: normal; Button at startup (2.2+) 10 50 221 17 font-weight: normal; USB descriptor (2.2+/3.2+) 10 75 221 17 font-weight: normal; API call (2.2+/3.0+) 315 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 370 275 350 50 font-weight: bold; Static Password Settings 10 25 331 17 font-weight: normal; Enable manual update using the button (2.0+) 315 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 390 350 50 font-weight: bold; Update Settings 10 25 331 17 font-weight: normal; Enable updating of YubiKey configuration (2.3+/3.0+) 315 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 370 340 350 100 font-weight: bold; Extended Settings 10 25 331 17 font-weight: normal; Use numeric keypad for digits (2.3+) 10 50 340 17 font-weight: normal; Use fast triggering if only slot 1 is programmed (2.3+) 10 75 331 17 font-weight: normal; Invert led behaviour (2.4+/3.1+) 10 500 711 50 font-weight: bold; Application Settings 10 25 350 19 font-weight: normal; Enable configuration export and import (experimental) 0 0 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Update YubiKey Settings Qt::AlignCenter 10 210 711 50 font-weight: bold; 10 10 85 25 font: 12px; font-weight: bold; Update false false false true 110 10 85 25 font: 12px; font-weight: bold; Back false false false 370 10 85 25 font: 12px; font-weight: bold; Swap false false false 465 14 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 50 350 65 font-weight: bold; Configuration Slot 10 20 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be updated 10 40 151 19 font-weight: normal; Configuration Slot 1 true false 200 40 151 19 font-weight: normal; Configuration Slot 2 10 125 350 55 10 10 321 16 font-weight: normal; color: rgb(118, 116, 108); Select to make the configuration dormant 10 30 151 17 font-weight: normal; Dormant 370 50 350 117 YubiAccBox QWidget
        yubiaccbox.h
        1
        custPrefixCheck custPrefixDecTxt custPrefixModhexTxt custPrefixHexTxt tabFirstBtn appendTab1Btn appendTab2Btn appendCRBtn outCharRateCombo appendDelay1Check appendDelay2Check srBtnVisibleCheck srUsbVisibleCheck srApiVisibleCheck manUpdateCheck logOutputCheck restoreBtn outFormatHelpBtn outSpeedHelpBtn srVisibilityHelpBtn
        yubikey-personalization-gui-3.1.24/src/ui/mainwindow.ui0000664000175000017500000010307412642452141021660 0ustar klasklas MainWindow Qt::ApplicationModal true 0 0 900 700 0 0 900 710 0 0 YubiKey Personalization Tool :/res/win/Yubico.ico:/res/win/Yubico.ico font: 11px "Verdana"; color: rgb(0, 0, 0); 900 710 300 200 730 33 170 677 0 0 170 677 font: 11px "Verdana"; background-color: rgb(255, 255, 255); 0 0 3 677 0 0 3 677 Qt::Vertical 20 40 128 128 Qt::ActionsContextMenu Qt::AlignCenter 10 260 151 16 10 240 151 16 font-weight: bold; Firmware Version: 10 5 151 30 font-weight: bold; color: rgb(221, 97, 99); Qt::AlignCenter 8 380 155 200 font-weight: bold; background-color: rgb(255, 255, 255); Features Supported Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop false false 5 45 121 16 font-weight: normal; 2 2 Configurations 5 65 121 16 font-weight: normal; 2 OATH-HOTP 5 125 121 16 font-weight: normal; 2 Challenge-Response 128 45 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 128 65 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 128 125 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 128 85 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 5 85 121 16 font-weight: normal; 2 Static Password 5 25 121 16 font-weight: normal; 2 Yubico OTP 128 25 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 128 105 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 5 105 121 16 font-weight: normal; 2 Scan Code Mode 5 145 121 16 font-weight: normal; 2 Updatable 128 145 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 5 165 121 16 font-weight: normal; 2 Ndef 128 165 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 5 185 121 16 font-weight: normal; 2 Universal 2nd Factor 128 185 21 16 font-weight: normal; N/A Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 5 600 160 60 Qt::ActionsContextMenu font-weight: normal; :/res/images/logo.png false Qt::AlignCenter 0 8 275 155 105 font-weight: bold; background-color: rgb(255, 255, 255); Serial Number Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop false false 128 50 20 20 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/blank.png); border-radius: 2px; false false 55 50 70 20 font-weight: normal; Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse 55 25 70 20 font-weight: normal; Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse 128 25 20 20 0 0 PointingHandCursor Qt::DefaultContextMenu false Qt::LeftToRight false background-image: url(:/res/images/blank.png); border-radius: 2px; false false false 55 75 70 20 font-weight: normal; Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse 128 75 20 20 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/blank.png); border-radius: 2px; false false 5 25 50 20 font-weight: normal; Dec: 5 50 50 20 font-weight: normal; Hex: 5 75 50 20 font-weight: normal; Modhex: 10 200 151 16 font-weight: bold; Programming status: 10 220 151 16 0 60 725 650 0 0 730 650 0 30 900 3 0 0 900 3 false background-color: rgb(140, 192, 65); QFrame::Sunken 1 Qt::Horizontal 0 0 900 30 900 30 font: 13px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); background-color: rgb(255, 255, 255); border-color: rgb(140, 192, 65); selection-color: rgb(0, 0, 0); 10 4 95 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; Yubico OTP true false false 535 4 75 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; Settings false false false 115 4 100 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; OATH-HOTP true false false 225 4 130 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; Static Password true false false 365 4 160 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; Challenge-Response true false false 680 4 60 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; About false false false 620 4 50 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; Tools false false false 750 4 45 23 background-color: rgb(255, 255, 255); border: 2px groove rgb(255, 255, 255); border-radius: 5px; Exit false false false 0 33 725 27 10 5 16 16 16 16 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 30 5 691 16 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter otpMenuBtn oathHotpMenuBtn staticMenuBtn chalRespMenuBtn settingsMenuBtn toolsMenuBtn aboutMenuBtn serialNoDecCopyBtn serialNoHexCopyBtn serialNoModhexCopyBtn yubikey-personalization-gui-3.1.24/src/ui/otppage.cpp0000664000175000017500000006753112642452141021317 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "otppage.h" #include "yubikeywriter.h" #include "yubikeyutil.h" #include "yubikeyfinder.h" #include "ui_otppage.h" #include "ui/helpbox.h" #include "ui/confirmbox.h" #include #include #include #include #include #include #include #include #include "common.h" OtpPage::OtpPage(QWidget *parent) : QStackedWidget(parent), ui(new Ui::OtpPage) { ui->setupUi(this); m_customerPrefix = -1; m_ykConfig = 0; m_keyPresent = false; clearState(); //Connect pages connectPages(); //Connect help buttons connectHelpButtons(); //Connect other signals and slots connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); connect(ui->quickWriteConfigBtn, SIGNAL(clicked()), this, SLOT(writeQuickConfig())); connect(ui->quickUploadBtn, SIGNAL(clicked()), this, SLOT(uploadQuickConfig())); connect(ui->advResetBtn, SIGNAL(clicked()), this, SLOT(resetAdvPage())); //Load settings loadSettings(); ui->advResultsWidget->resizeColumnsToContents(); } OtpPage::~OtpPage() { if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } delete ui; } /* Common */ void OtpPage::connectPages() { //Map the values of the navigation buttons with the indexes of //the stacked widget //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //connect(ui->quickUploadBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickBtn, Page_Quick); mapper->setMapping(ui->quickBackBtn, Page_Base); //mapper->setMapping(ui->quickUploadBtn, Page_Upload); mapper->setMapping(ui->advBtn, Page_Advanced); mapper->setMapping(ui->advBackBtn, Page_Base); //Connect the mapper to the widget //The mapper will set a value to each button and //set that value to the widget //connect(pageMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentIndex(int))); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); //Set the current page m_currentPage = 0; setCurrentIndex(Page_Base); } void OtpPage::setCurrentPage(int pageIndex) { //Page changed... m_currentPage = pageIndex; switch(pageIndex){ case Page_Quick: resetQuickPage(); break; case Page_Advanced: resetAdvPage(); break; } setCurrentIndex(pageIndex); //Clear state m_keysProgrammedCtr = 0; clearState(); } void OtpPage::connectHelpButtons() { //Map the values of the help buttons //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickPubIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickPvtIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advParamGenSchemeHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advPubIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advPvtIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->quickPubIdHelpBtn, HelpBox::Help_PublicID); mapper->setMapping(ui->quickPvtIdHelpBtn, HelpBox::Help_PrivateID); mapper->setMapping(ui->quickSecretKeyHelpBtn, HelpBox::Help_SecretKey); mapper->setMapping(ui->advConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->advParamGenSchemeHelpBtn, HelpBox::Help_ParameterGeneration); mapper->setMapping(ui->advPubIdHelpBtn, HelpBox::Help_PublicID); mapper->setMapping(ui->advPvtIdHelpBtn, HelpBox::Help_PrivateID); mapper->setMapping(ui->advSecretKeyHelpBtn, HelpBox::Help_SecretKey); //Connect the mapper connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int))); connect(ui->advConfigProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); } void OtpPage::keyFound(bool found, bool* featuresMatrix) { if(found) { if(m_state == State_Initial) { ui->quickWriteConfigBtn->setEnabled(true); ui->advWriteConfigBtn->setEnabled(true); ui->advExportConfigBtn->setEnabled(true); if(!featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) { ui->quickConfigSlot2Radio->setEnabled(false); ui->advConfigSlot2Radio->setEnabled(false); } else { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); } } else if(this->currentIndex() == Page_Advanced && m_state >= State_Programming_Multiple && m_keyPresent == false) { if(m_keysProgrammedCtr > 0 && !m_ready) { changeAdvConfigParams(); } if(m_state == State_Programming_Multiple) { ui->advWriteConfigBtn->setEnabled(true); ui->advExportConfigBtn->setEnabled(true); } else { writeAdvConfig(WRITE_CONFIG); } } m_keyPresent = true; } else { ui->quickWriteConfigBtn->setEnabled(false); ui->advWriteConfigBtn->setEnabled(false); ui->advExportConfigBtn->setEnabled(false); m_keyPresent = false; if(m_state == State_Initial) { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); } } } void OtpPage::clearState() { m_state = State_Initial; m_ready = true; if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } } void OtpPage::loadSettings() { QSettings settings; m_customerPrefix = settings.value(SG_CUSTOMER_PREFIX).toInt(); if(m_customerPrefix > 0) { ui->advPubIdLenBox->setValue(PUBLIC_ID_DEFAULT_SIZE); ui->advPubIdLenBox->setEnabled(false); //Build Public Identity prefix based on customer prefix QByteArray prefix; // As per old tool prefix.resize(2); prefix[0] = (unsigned char) (m_customerPrefix >> 8U); prefix[1] = (unsigned char) m_customerPrefix; char pubIdPrefix[prefix.size() * 2 + 1]; size_t pubIdPrefixLen = 0; memset(&pubIdPrefix, 0, sizeof(pubIdPrefix)); YubiKeyUtil::hexModhexEncode(pubIdPrefix, &pubIdPrefixLen, (unsigned char *)prefix.data(), prefix.size(), true); m_pubIdPrefix = QString(pubIdPrefix); if(m_currentPage == Page_Advanced) { on_advPubIdTxt_editingFinished(); } } else { ui->advPubIdLenBox->setEnabled(true); m_pubIdPrefix = QString(""); } ui->advExportConfigBtn->setVisible(settings.value(SG_EXPORT_PREFERENCE).toBool()); } /* Quick Page handling */ void OtpPage::resetQuickPage() { if(ui->quickConfigSlot1Radio->isChecked()) { ui->quickConfigSlot2Radio->setChecked(true); } on_quickResetBtn_clicked(); ui->quickUploadBtn->setEnabled(false); } void OtpPage::on_quickResetBtn_clicked() { QString pubIdTxt = YubiKeyUtil::generateRandomModhex(PUBLIC_ID_DEFAULT_SIZE * 2); pubIdTxt.replace(0, 2, YUBICO_OTP_SERVER_PUBLIC_ID_PREFIX); ui->quickPubIdTxt->setText(pubIdTxt); on_quickPubIdTxt_editingFinished(); ui->quickPvtIdTxt->setText( YubiKeyUtil::generateRandomHex((size_t)UID_SIZE * 2)); on_quickPvtIdTxt_editingFinished(); ui->quickSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE * 2)); on_quickSecretKeyTxt_editingFinished(); } void OtpPage::on_quickHideParams_clicked(bool checked) { if(checked) { ui->quickPvtIdTxt->setEchoMode(QLineEdit::Password); ui->quickSecretKeyTxt->setEchoMode(QLineEdit::Password); } else { ui->quickPvtIdTxt->setEchoMode(QLineEdit::Normal); ui->quickSecretKeyTxt->setEchoMode(QLineEdit::Normal); } } void OtpPage::on_quickPubIdTxt_editingFinished() { QString txt = ui->quickPubIdTxt->text(); YubiKeyUtil::qstrModhexClean(&txt, (size_t)PUBLIC_ID_DEFAULT_SIZE * 2); ui->quickPubIdTxt->setText(txt); } void OtpPage::on_quickPvtIdTxt_editingFinished() { QString txt = ui->quickPvtIdTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)UID_SIZE * 2); ui->quickPvtIdTxt->setText(txt); } void OtpPage::on_quickSecretKeyTxt_editingFinished() { QString txt = ui->quickSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE * 2); ui->quickSecretKeyTxt->setText(txt); } bool OtpPage::validateQuickSettings() { if(!(ui->quickConfigSlot1Radio->isChecked() || ui->quickConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->quickConfigSlot1Radio->isChecked()) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } return true; } void OtpPage::writeQuickConfig() { //Clear status emit showStatusMessage(NULL, -1); //Validate settings if(!validateQuickSettings()) { return; } // m_state = State_Programming; //Write configuration ui->quickWriteConfigBtn->setEnabled(false); ui->quickUploadBtn->setEnabled(false); ui->quickBackBtn->setEnabled(false); if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_YubicoOtp); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->quickConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Public ID... m_ykConfig->setPubIdTxt(ui->quickPubIdTxt->text()); //Private ID... m_ykConfig->setPvtIdTxt(ui->quickPvtIdTxt->text()); //Secret Key... m_ykConfig->setSecretKeyTxt(ui->quickSecretKeyTxt->text()); //Prepare upload url m_uploadUrl.clear(); unsigned int serial = YubiKeyFinder::getInstance()->serial(); m_uploadUrl = tr(UPLOAD_URL). arg(serial == 0? "": QString::number(serial)). arg(m_ykConfig->pubIdTxt()). arg(m_ykConfig->pvtIdTxt()). arg(m_ykConfig->secretKeyTxt()); //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } void OtpPage::quickConfigWritten(bool written, __attribute__((unused)) const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); ui->quickWriteConfigBtn->setEnabled(true); ui->quickBackBtn->setEnabled(true); if(written && m_ykConfig != 0) { ui->quickUploadBtn->setEnabled(true); QString keyDetail = tr(" (Public ID: %1)").arg(m_ykConfig->pubIdTxt()); showStatusMessage(tr(KEY_CONFIGURED).arg(keyDetail), 0); } else { m_uploadUrl.clear(); ui->quickUploadBtn->setEnabled(false); } clearState(); } void OtpPage::uploadQuickConfig() { m_tempFile.setFileTemplate(QDir::tempPath() + "/ykpers.XXXXXX.html"); m_tempFile.open(); m_tempFile.write(m_uploadUrl.toLatin1(), m_uploadUrl.length()); m_tempFile.close(); qDebug() << "temporary file for upload is: " << m_tempFile.fileName(); QDesktopServices::openUrl(QUrl::fromLocalFile(m_tempFile.fileName())); } /* Advanced Page handling */ void OtpPage::resetAdvPage() { if(ui->advConfigSlot1Radio->isChecked()) { ui->advConfigSlot2Radio->setChecked(true); } ui->advConfigParamsCombo->setCurrentIndex(2); ui->advAutoProgramKeysCheck->setChecked(false); ui->advProgramMulKeysBox->setChecked(false); ui->advConfigProtectionBox->reset(); ui->advPubIdCheck->setChecked(true); ui->advPubIdTxt->clear(); set_advPubId_default(); on_advPubIdTxt_editingFinished(); ui->advPubIdLenBox->setValue(PUBLIC_ID_DEFAULT_SIZE); if(m_customerPrefix > 0) { ui->advPubIdLenBox->setEnabled(false); } else { ui->advPubIdLenBox->setEnabled(true); } ui->advPvtIdCheck->setChecked(true); ui->advPvtIdTxt->clear(); on_advPvtIdTxt_editingFinished(); ui->advSecretKeyTxt->clear(); on_advSecretKeyTxt_editingFinished(); ui->advStopBtn->setEnabled(false); } void OtpPage::freezeAdvPage(bool freeze) { bool disable = !freeze; ui->advConfigBox->setEnabled(disable); ui->advProgramMulKeysBox->setEnabled(disable); ui->advConfigProtectionBox->setEnabled(disable); ui->advKeyParamsBox->setEnabled(disable); ui->advWriteConfigBtn->setEnabled(disable); ui->advExportConfigBtn->setEnabled(disable); ui->advStopBtn->setEnabled(!disable); ui->advBackBtn->setEnabled(disable); } void OtpPage::on_advProgramMulKeysBox_clicked(bool checked) { if(checked) { changeAdvConfigParams(); } } void OtpPage::on_advPubIdCheck_stateChanged(int state) { bool disable = (state != 0); ui->advPubIdTxt->setEnabled(disable); ui->advPubIdGenerateBtn->setEnabled(disable); if(m_customerPrefix <= 0) { ui->advPubIdLenBox->setEnabled(disable); } } void OtpPage::set_advPubId_default() { QString txt = "cccccc"; unsigned int serial = YubiKeyFinder::getInstance()->serial(); //Convert serial number to modhex unsigned char buf[16]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; QString tmp = QString::number(serial, 16); size_t len = tmp.length(); if(len % 2 != 0) { len++; } YubiKeyUtil::qstrClean(&tmp, (size_t)len, true); YubiKeyUtil::qstrHexDecode(buf, &bufLen, tmp); txt.append(YubiKeyUtil::qstrModhexEncode(buf, bufLen)); ui->advPubIdTxt->setText(txt); on_advPubIdTxt_editingFinished(); } void OtpPage::on_advPubIdTxt_editingFinished() { QString txt = ui->advPubIdTxt->text(); int len = ui->advPubIdLenBox->value() * 2; YubiKeyUtil::qstrModhexClean(&txt, (size_t)len); if(m_customerPrefix > 0) { txt.replace(0, 4, m_pubIdPrefix); } ui->advPubIdTxt->setText(txt); len = txt.length(); ui->advPubIdTxt->setCursorPosition(len + len/2); } void OtpPage::on_advPubIdLenBox_valueChanged(int value) { if(value > FIXED_SIZE) { ui->advPubIdLenBox->setValue(PUBLIC_ID_DEFAULT_SIZE); } on_advPubIdTxt_editingFinished(); } void OtpPage::on_advPubIdGenerateBtn_clicked() { int len = ui->advPubIdLenBox->value(); QString txt = YubiKeyUtil::generateRandomModhex((size_t)len * 2); ui->advPubIdTxt->setText(txt); on_advPubIdTxt_editingFinished(); } void OtpPage::on_advPvtIdCheck_stateChanged(int state) { bool disable = (state != 0); ui->advPvtIdTxt->setEnabled(disable); ui->advPvtIdGenerateBtn->setEnabled(disable); } void OtpPage::on_advPvtIdTxt_editingFinished() { QString txt = ui->advPvtIdTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)UID_SIZE * 2); ui->advPvtIdTxt->setText(txt); } void OtpPage::on_advPvtIdGenerateBtn_clicked() { ui->advPvtIdTxt->setText( YubiKeyUtil::generateRandomHex((size_t)UID_SIZE * 2)); } void OtpPage::on_advSecretKeyTxt_editingFinished() { QString txt = ui->advSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE * 2); ui->advSecretKeyTxt->setText(txt); } void OtpPage::on_advSecretKeyGenerateBtn_clicked() { ui->advSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE * 2)); } void OtpPage::on_advExportConfigBtn_clicked() { qDebug() << "foo"; //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); writeAdvConfig(EXPORT_CONFIG); } void OtpPage::on_advWriteConfigBtn_clicked() { emit showStatusMessage(NULL, -1); if(!ui->advProgramMulKeysBox->isChecked()) { m_keysProgrammedCtr = 0; } //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); // Change state if(ui->advProgramMulKeysBox->isChecked()) { if(ui->advAutoProgramKeysCheck->isChecked()) { m_keysProgrammedCtr = 0; m_state = State_Programming_Multiple_Auto; } else { m_state = State_Programming_Multiple; } } else { m_keysProgrammedCtr = 0; m_state = State_Programming; } writeAdvConfig(WRITE_CONFIG); } void OtpPage::on_advStopBtn_clicked() { ui->advStopBtn->setEnabled(false); m_state = State_Initial; stopAdvConfigWritting(); } void OtpPage::stopAdvConfigWritting() { qDebug() << "Stopping adv configuration writing..."; if(m_state >= State_Programming_Multiple) { ui->advStopBtn->setEnabled(true); return; } m_keysProgrammedCtr = 0; clearState(); freezeAdvPage(false); } void OtpPage::changeAdvConfigParams() { qDebug() << "Changing adv configuration params..."; int index = ui->advConfigParamsCombo->currentIndex(); int idScheme = GEN_SCHEME_FIXED; int secretScheme = GEN_SCHEME_FIXED; switch(index) { case SCHEME_INCR_ID_RAND_SECRET: //Increment IDs only if in programming mode if(m_state != State_Initial) { idScheme = GEN_SCHEME_INCR; } secretScheme = GEN_SCHEME_RAND; break; case SCHEME_RAND_ALL: idScheme = GEN_SCHEME_RAND; secretScheme = GEN_SCHEME_RAND; break; case SCHEME_ID_FROM_SERIAL_RAND_SECRET: idScheme = GEN_SCHEME_SERIAL; secretScheme = GEN_SCHEME_RAND; break; } //Public ID... if(ui->advPubIdCheck->isChecked()) { if(idScheme == GEN_SCHEME_SERIAL) { set_advPubId_default(); } else { QString pubIdTxt = YubiKeyUtil::getNextModhex( ui->advPubIdLenBox->value() * 2, ui->advPubIdTxt->text(), idScheme); ui->advPubIdTxt->setText(pubIdTxt); on_advPubIdTxt_editingFinished(); } } //Private ID... if(ui->advPvtIdCheck->isChecked()) { QString pvtIdTxt = YubiKeyUtil::getNextHex( UID_SIZE * 2, ui->advPvtIdTxt->text(), secretScheme); ui->advPvtIdTxt->setText(pvtIdTxt); } //Secret Key... QString secretKeyTxt = YubiKeyUtil::getNextHex( KEY_SIZE * 2, ui->advSecretKeyTxt->text(), secretScheme); ui->advSecretKeyTxt->setText(secretKeyTxt); m_ready = true; } bool OtpPage::validateAdvSettings() { if(!(ui->advConfigSlot1Radio->isChecked() || ui->advConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->advConfigSlot1Radio->isChecked() && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } //Check if public id length is 6 if (!settings.value(SG_DIFF_PUBLIC_ID_LEN).toBool() && ui->advPubIdLenBox->value() != PUBLIC_ID_DEFAULT_SIZE && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_PublicID); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } if(!ui->advConfigProtectionBox->checkConfirm()) { return false; } return true; } void OtpPage::writeAdvConfig(int mode) { qDebug() << "Writing configuration..."; //Disable stop button while configuration is being written ui->advStopBtn->setEnabled(false); //Write configuration if(m_ykConfig != 0) { qDebug() << "ykConfig destroyed"; delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_YubicoOtp); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->advConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Public ID... if(ui->advPubIdCheck->isChecked()) { m_ykConfig->setPubIdTxt(ui->advPubIdTxt->text()); } //Private ID... if(ui->advPvtIdCheck->isChecked()) { m_ykConfig->setPvtIdTxt(ui->advPvtIdTxt->text()); } //Secret Key... m_ykConfig->setSecretKeyTxt(ui->advSecretKeyTxt->text()); //Configuration protection... m_ykConfig->setCurrentAccessCodeTxt( ui->advConfigProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->advConfigProtectionBox->newAccessCode(), ui->advConfigProtectionBox->newAccMode()); if(mode == WRITE_CONFIG) { //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } else if(mode == EXPORT_CONFIG) { connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigExported(bool, const QString &))); YubiKeyWriter::getInstance()->exportConfig(m_ykConfig); } } void OtpPage::advConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); QString message; if(written && m_ykConfig != 0) { qDebug() << "Configuration written...."; m_keysProgrammedCtr++; QString keyDetail(""); if(ui->advPubIdCheck->isChecked()) { keyDetail = tr(" (Public ID: %1)").arg(m_ykConfig->pubIdTxt()); } if(m_state == State_Programming){ message = tr(KEY_CONFIGURED).arg(keyDetail); } else { message = tr("%1. %2").arg(tr(KEY_CONFIGURED).arg(keyDetail)).arg(tr(REMOVE_KEY)); } showStatusMessage(message, 0); message = tr(KEY_CONFIGURED).arg(""); } else { qDebug() << "Configuration could not be written...."; message = msg; } advUpdateResults(written, message); m_ready = false; stopAdvConfigWritting(); } void OtpPage::advConfigExported(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigExported(bool, const QString &))); QString message; if(written && m_ykConfig != 0) { qDebug() << "Configuration exported...."; QString keyDetail(""); if(ui->advPubIdCheck->isChecked()) { keyDetail = tr(" (Public ID: %1)").arg(m_ykConfig->pubIdTxt()); } message = tr(KEY_EXPORTED); showStatusMessage(message, 0); } else { qDebug() << "Configuration could not be exported...."; message = msg; } m_ready = false; stopAdvConfigWritting(); } void OtpPage::advUpdateResults(bool written, const QString &msg) { int row = 0; ui->advResultsWidget->insertRow(row); //Sr. No.... QTableWidgetItem *srnoItem = new QTableWidgetItem( tr("%1").arg(ui->advResultsWidget->rowCount())); if(written) { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/tick.png")))); } else { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/cross.png")))); } srnoItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 0, srnoItem); //Public ID... QString pubId; if(ui->advPubIdCheck->isChecked() && m_ykConfig != 0) { pubId = m_ykConfig->pubIdTxt(); } else { pubId = NA; } QTableWidgetItem *idItem = new QTableWidgetItem( tr("%1").arg(pubId)); idItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 1, idItem); //Status... QTableWidgetItem *statusItem = new QTableWidgetItem( tr("%1").arg(msg)); statusItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 2, statusItem); //Timestamp... QDateTime timstamp = QDateTime::currentDateTime(); QTableWidgetItem *timeItem = new QTableWidgetItem( tr("%1").arg(timstamp.toString(Qt::SystemLocaleShortDate))); timeItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 3, timeItem); ui->advResultsWidget->resizeColumnsToContents(); ui->advResultsWidget->resizeRowsToContents(); } void OtpPage::setCurrentSlot(int slot) { if(m_currentPage == Page_Advanced) { ui->advConfigSlot1Radio->setChecked(slot == 1); ui->advConfigSlot2Radio->setChecked(slot == 2); } else if(m_currentPage == Page_Quick) { ui->quickConfigSlot1Radio->setChecked(slot == 1); ui->quickConfigSlot2Radio->setChecked(slot == 2); } } yubikey-personalization-gui-3.1.24/src/ui/yubiaccbox.cpp0000664000175000017500000001574412642452141022007 0ustar klasklas/* Copyright (C) 2013-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "yubiaccbox.h" #include "ui_yubiaccbox.h" #include "ui/helpbox.h" #include "ui/confirmbox.h" #include "yubikeyfinder.h" #include "yubikeyutil.h" #include "yubikeylogger.h" #include #include #include #define CONFIG_PROTECTION_DISABLED 0 #define CONFIG_PROTECTION_ENABLE 1 #define CONFIG_PROTECTION_DISABLE 2 #define CONFIG_PROTECTION_ENABLED 3 #define CONFIG_PROTECTION_CHANGE 4 YubiAccBox::YubiAccBox(QWidget *parent) : QWidget(parent), ui(new Ui::YubiAccBox) { ui->setupUi(this); QSignalMapper *mapper = new QSignalMapper(this); connect(ui->configProtectionHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); mapper->setMapping(ui->configProtectionHelpBtn, HelpBox::Help_ConfigurationProtection); connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int))); connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); } YubiAccBox::~YubiAccBox() { delete ui; } void YubiAccBox::reset() { ui->configProtectionCombo->setCurrentIndex(0); } void YubiAccBox::on_configProtectionCombo_currentIndexChanged(int index) { switch(index) { case CONFIG_PROTECTION_DISABLED: ui->currentAccessCodeTxt->clear(); ui->currentAccessCodeTxt->setEnabled(false); ui->currentUseSerial->setChecked(false); ui->currentUseSerial->setEnabled(false); ui->newAccessCodeTxt->clear(); ui->newAccessCodeTxt->setEnabled(false); ui->newUseSerial->setChecked(false); ui->newUseSerial->setEnabled(false); break; case CONFIG_PROTECTION_ENABLE: ui->currentAccessCodeTxt->clear(); ui->currentAccessCodeTxt->setEnabled(false); ui->currentUseSerial->setChecked(false); ui->currentUseSerial->setEnabled(false); on_newAccessCodeTxt_editingFinished(); ui->newAccessCodeTxt->setEnabled(true); ui->newUseSerial->setEnabled(true); break; case CONFIG_PROTECTION_DISABLE: case CONFIG_PROTECTION_ENABLED: on_currentAccessCodeTxt_editingFinished(); ui->currentAccessCodeTxt->setEnabled(true); ui->currentUseSerial->setEnabled(true); ui->newAccessCodeTxt->clear(); ui->newAccessCodeTxt->setEnabled(false); ui->newUseSerial->setChecked(false); ui->newUseSerial->setEnabled(false); break; case CONFIG_PROTECTION_CHANGE: on_currentAccessCodeTxt_editingFinished(); ui->currentAccessCodeTxt->setEnabled(true); ui->currentUseSerial->setEnabled(true); on_newAccessCodeTxt_editingFinished(); ui->newAccessCodeTxt->setEnabled(true); ui->newUseSerial->setEnabled(true); break; } } void YubiAccBox::keyFound(bool found, __attribute__((unused)) bool* featuresMatrix) { if(found) { m_serial = QString::number(YubiKeyFinder::getInstance()->serial()); int num = 12 - m_serial.length(); for(int i = 0; i < num; i++) { m_serial.prepend("0"); } if(!m_serial.isEmpty()) { if(ui->currentUseSerial->isChecked()) { setSerial(ui->currentAccessCodeTxt); } if(ui->newUseSerial->isChecked()) { setSerial(ui->newAccessCodeTxt); } } } else { m_serial.clear(); } } void YubiAccBox::on_currentUseSerial_clicked(bool checked) { if(checked) { setSerial(ui->currentAccessCodeTxt); } } void YubiAccBox::on_newUseSerial_clicked(bool checked) { if(checked) { setSerial(ui->newAccessCodeTxt); } } void YubiAccBox::setSerial(QLineEdit* line) { line->setText(m_serial); } void YubiAccBox::on_currentAccessCodeTxt_editingFinished() { QString txt = ui->currentAccessCodeTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)ACC_CODE_SIZE * 2); ui->currentAccessCodeTxt->setText(txt); } void YubiAccBox::on_newAccessCodeTxt_editingFinished() { QString txt = ui->newAccessCodeTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)ACC_CODE_SIZE * 2); ui->newAccessCodeTxt->setText(txt); } bool YubiAccBox::checkConfirm() { QSettings settings; if(!settings.value(SG_ENABLE_CONF_PROTECTION).toBool() && !YubiKeyLogger::isLogging() && ui->configProtectionCombo->currentIndex() == CONFIG_PROTECTION_ENABLE) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationProtection); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } return true; } QString YubiAccBox::newAccessCode() { if(ui->configProtectionCombo->currentIndex() == CONFIG_PROTECTION_DISABLE) { return ACCESS_CODE_DEFAULT; } else if(ui->configProtectionCombo->currentIndex() == CONFIG_PROTECTION_ENABLED) { return ui->currentAccessCodeTxt->text(); } else { return ui->newAccessCodeTxt->text(); } } QString YubiAccBox::currentAccessCode() { return ui->currentAccessCodeTxt->text(); } AccMode YubiAccBox::newAccMode() { if(ui->configProtectionCombo->currentIndex() == CONFIG_PROTECTION_DISABLE || ui->configProtectionCombo->currentIndex() == CONFIG_PROTECTION_DISABLED) { return Acc_None; } QCheckBox *lookat = ui->newUseSerial; if(ui->configProtectionCombo->currentIndex() == CONFIG_PROTECTION_ENABLED) { lookat = ui->currentUseSerial; } if(lookat->isChecked() == true) { return Acc_Serial; } return Acc_Random; } yubikey-personalization-gui-3.1.24/src/ui/aboutpage.cpp0000664000175000017500000001215412642452141021616 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include "aboutpage.h" #include "ui_aboutpage.h" #include "ui/mainwindow.h" #include "yubikeyfinder.h" #include "common.h" #include "version.h" #include #include #include #include AboutPage::AboutPage(QWidget *parent) : QWidget(parent), ui(new Ui::AboutPage) { ui->setupUi(this); //Set application version QString appVersion = tr("%1 %2"). arg(ui->appVersionLbl->text()). arg(VER_PRODUCTVERSION_STR); ui->appVersionLbl->setText(appVersion); // Set the library version QString libVersion = tr("%1 %2"). arg(ui->libVersionLbl->text()). arg(ykpers_check_version(NULL)); ui->libVersionLbl->setText(libVersion); //Set copyright QString copyright = tr("%1. %2."). arg(trUtf8(VER_LEGALCOPYRIGHT)). arg(VER_LEGALTRADEMARKS1_STR); ui->copyrightLbl->setText(copyright); connectButtons(); //Connect other signals and slots connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); } AboutPage::~AboutPage() { delete ui; } void AboutPage::connectButtons() { //Map the values of the buttons //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->otpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->oathBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->staticBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->chalRespBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->settingsBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->otpBtn, MainWindow::Page_Otp); mapper->setMapping(ui->oathBtn, MainWindow::Page_Oath); mapper->setMapping(ui->staticBtn, MainWindow::Page_Static); mapper->setMapping(ui->chalRespBtn, MainWindow::Page_ChalResp); mapper->setMapping(ui->settingsBtn, MainWindow::Page_Settings); //Connect the mapper connect(mapper, SIGNAL(mapped(int)), this, SLOT(btn_pressed(int))); } void AboutPage::keyFound(bool found, bool* featuresMatrix) { QString enabledLinkBtnSS = QString::fromUtf8(SS_LINK_ENABLED); QString disabledLinkBtnSS = QString::fromUtf8(SS_LINK_DISABLED); if(found) { if(featuresMatrix[YubiKeyFinder::Feature_OathHotp]) { ui->oathBtn->setEnabled(true); ui->oathBtn->setStyleSheet(enabledLinkBtnSS); } else { ui->oathBtn->setEnabled(false); ui->oathBtn->setStyleSheet(disabledLinkBtnSS); } if(featuresMatrix[YubiKeyFinder::Feature_StaticPassword]) { ui->staticBtn->setEnabled(true); ui->staticBtn->setStyleSheet(enabledLinkBtnSS); } else { ui->staticBtn->setEnabled(false); ui->staticBtn->setStyleSheet(disabledLinkBtnSS); } if(featuresMatrix[YubiKeyFinder::Feature_ChallengeResponse]) { ui->chalRespBtn->setEnabled(true); ui->chalRespBtn->setStyleSheet(enabledLinkBtnSS); } else { ui->chalRespBtn->setEnabled(false); ui->chalRespBtn->setStyleSheet(disabledLinkBtnSS); } } else { ui->oathBtn->setEnabled(true); ui->oathBtn->setStyleSheet(enabledLinkBtnSS); ui->staticBtn->setEnabled(true); ui->staticBtn->setStyleSheet(enabledLinkBtnSS); ui->chalRespBtn->setEnabled(true); ui->chalRespBtn->setStyleSheet(enabledLinkBtnSS); } } void AboutPage::btn_pressed(int pageIndex) { emit changePage(pageIndex); } void AboutPage::on_supportBtn_clicked() { QDesktopServices::openUrl(QUrl(tr(SUPPORT_LINK))); } yubikey-personalization-gui-3.1.24/src/ui/helpbox.cpp0000664000175000017500000001077112642452141021313 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include "ui/helpbox.h" #include "ui_helpbox.h" #include "common.h" #include "help.h" #include "yubikeylogger.h" HelpBox::HelpBox(QWidget *parent) : QDialog(parent), ui(new Ui::HelpBox) { ui->setupUi(this); } HelpBox::~HelpBox() { delete ui; } void HelpBox::setHelpIndex(Help helpIndex) { QString title; QString helpMsg; switch(helpIndex) { case Help_ConfigurationSlot: title = tr("Configuration Slots"); helpMsg = tr(HELP_CONFIG_SLOT); break; case Help_PublicID: title = tr("Public Identity"); helpMsg = tr(HELP_PUBLIC_ID); break; case Help_PrivateID: title = tr("Private Identity"); helpMsg = tr(HELP_PRIVATE_ID); break; case Help_SecretKey: title = tr("Secret Key"); helpMsg = tr(HELP_SECRET_KEY); break; case Help_ParameterGeneration: title = tr("Parameter Generation Scheme"); helpMsg = tr(HELP_PARAM_GENERATION); break; case Help_ConfigurationProtection: title = tr("Configuration Protection"); helpMsg = tr(HELP_CONFIG_PROTECTION); break; case Help_OutputFormat: title = tr("Output Format"); helpMsg = tr(HELP_OUTPUT_FORMAT); break; case Help_OutputSpeed: title = tr("Output Speed Throttling"); helpMsg = tr(HELP_OUTPUT_SPEED); break; case Help_SrNoVisibility: title = tr("Serial # Visibility"); helpMsg = tr(HELP_SR_NO_VISIBILITY); break; case Help_OathPublicID: title = tr("OATH Token Identifier"); helpMsg = tr(HELP_OATH_PUBLIC_ID); break; case Help_HotpLen: title = tr("HOTP Length"); helpMsg = tr(HELP_HOTP_LEN); break; case Help_HotpParam: title = tr("HOTP Moving Factor Seed"); helpMsg = tr(HELP_HOTP_PARAM); break; case Help_StaticScanCode: title = tr("Static Password Scan Code Mode"); helpMsg = tr(HELP_STATIC_SCAN_CODE); break; case Help_ChalRespYubico: title = tr("Challenge-Response Yubico OTP Mode"); helpMsg = tr(HELP_CHALRESP_YUBICO); break; case Help_ChalRespHmac: title = tr("Challenge-Response HMAC-SHA1 Mode"); helpMsg = tr(HELP_CHALRESP_HMAC); break; case Help_ChalRespOption: title = tr("Challenge-Response Options"); helpMsg = tr(HELP_CHALRESP_OPTION); break; case Help_AllowUpdate: title = tr("Allow Update"); helpMsg = tr(HELP_ALLOW_UPDATE_OPTION); break; case Help_Swap: title = tr("Swap"); helpMsg = tr(HELP_SWAP_OPTION); break; case Help_ManUpdate: title = tr("Manual Update"); helpMsg = tr(HELP_MAN_UPDATE_OPTION); break; case Help_LogFormat: { title = tr("Flexible Log Format"); helpMsg = tr(HELP_LOG_FORMAT); QStringList names = YubiKeyLogger::getLogNames(); helpMsg.append(names.join(", ")); helpMsg.append("

        "); } break; default: helpMsg = tr(""); } this->setWindowTitle(tr("Help: %1").arg(title)); ui->helpTxtBrowser->setText(helpMsg); } yubikey-personalization-gui-3.1.24/src/ui/yubiaccbox.h0000664000175000017500000000426112642452141021444 0ustar klasklas/* Copyright (C) 2013-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef YUBIACCBOX_H #define YUBIACCBOX_H #include #include #include "common.h" namespace Ui { class YubiAccBox; } class YubiAccBox : public QWidget { Q_OBJECT public: explicit YubiAccBox(QWidget *parent = 0); ~YubiAccBox(); void reset(); bool checkConfirm(); QString newAccessCode(); QString currentAccessCode(); AccMode newAccMode(); private: Ui::YubiAccBox *ui; QString m_serial; void setSerial(QLineEdit* line); private slots: void keyFound(bool found, bool* featuresMatrix); void on_currentUseSerial_clicked(bool checked); void on_newUseSerial_clicked(bool checked); void on_configProtectionCombo_currentIndexChanged(int index); void on_currentAccessCodeTxt_editingFinished(); void on_newAccessCodeTxt_editingFinished(); signals: void showHelp(int helpIndex); }; #endif // YUBIACCBOX_H yubikey-personalization-gui-3.1.24/src/ui/oathpage.h0000664000175000017500000001052012642452141021077 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef OATHPAGE_H #define OATHPAGE_H #include #include "yubikeyconfig.h" #include "common.h" namespace Ui { class OathPage; } class OathPage : public QStackedWidget { Q_OBJECT public: explicit OathPage(QWidget *parent = 0); ~OathPage(); enum Page { Page_Base, Page_Quick, Page_Advanced }; private: Ui::OathPage *ui; int m_currentPage; int m_customerPrefix; unsigned char m_pubId[2]; unsigned int m_pubIdMUI; enum State { State_Initial, State_Programming, State_Programming_Multiple, State_Programming_Multiple_Auto }; State m_state; YubiKeyConfig *m_ykConfig; unsigned int m_keysProgrammedCtr; bool m_ready; bool m_serialNumberSupported; bool m_keyPresent; public slots: void loadSettings(); QString getPublicId(bool bcd); void setCurrentPage(int pageIndex); void setCurrentSlot(int slot); private slots: void connectPages(); void connectHelpButtons(); void keyFound(bool found, bool* featuresMatrix); void updatePrefix(); void fixBCD(unsigned char *bp, int bcnt); void clearState(); // Quick Page void resetQuickPage(); void on_quickResetBtn_clicked(); void on_quickHideParams_clicked(bool checked); void on_quickPubIdCheck_stateChanged(int state); void resetQuickPrefix(); void updateQuickMUI(); void on_quickMUITxt_editingFinished(); void on_quickMUIGenerateBtn_clicked(); void on_quickSecretKeyTxt_editingFinished(); bool validateQuickSettings(); void writeQuickConfig(); void quickConfigWritten(bool written, const QString &msg); // Advanced Page void resetAdvPage(); void freezeAdvPage(bool freeze); void on_advProgramMulKeysBox_clicked(bool checked); void on_advConfigParamsCombo_currentIndexChanged(int index); void on_advPubIdFormatCombo_currentIndexChanged(int index); void on_advPubIdCheck_stateChanged(int state); void updateAdvOMP(int index); void on_advOMPTxt_editingFinished(); void updateAdvTT(int index); void on_advTTTxt_editingFinished(); void updateAdvMUI(int index); void on_advMUITxt_editingFinished(); void on_advMUIGenerateBtn_clicked(); void hotpLen_clicked(); void on_advMovingFactorSeedCombo_currentIndexChanged(int index); void on_advMovingFactorSeedTxt_editingFinished(); void on_advSecretKeyTxt_editingFinished(); void on_advSecretKeyGenerateBtn_clicked(); void on_advWriteConfigBtn_clicked(); void on_advExportConfigBtn_clicked(); void on_advStopBtn_clicked(); void changeAdvConfigParams(); void stopAdvConfigWritting(); bool validateAdvSettings(); void writeAdvConfig(int mode); void advConfigWritten(bool written, const QString &msg); void advConfigExported(bool written, const QString &msg); void advUpdateResults(bool written, const QString &msg); signals: void showStatusMessage(const QString &text, int status = 0); void showHelp(int helpIndex); }; #endif // OATHPAGE_H yubikey-personalization-gui-3.1.24/src/ui/confirmbox.h0000664000175000017500000000360412642452141021462 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef CONFIRMBOX_H #define CONFIRMBOX_H #include namespace Ui { class ConfirmBox; } class ConfirmBox : public QDialog { Q_OBJECT public: explicit ConfirmBox(QWidget *parent = 0); ~ConfirmBox(); enum Confirm { Confirm_ConfigurationSlot, Confirm_PublicID, Confirm_ConfigurationProtection, Confirm_NdefWithoutHttp, }; void setConfirmIndex(Confirm confirmIndex); private slots: void on_dontaskCheck_stateChanged(int state); private: Ui::ConfirmBox *ui; Confirm m_confirmIndex; }; #endif // CONFIRMBOX_H yubikey-personalization-gui-3.1.24/src/ui/settingpage.cpp0000664000175000017500000005171212642452141022164 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "settingpage.h" #include "yubikeyfinder.h" #include "yubikeyutil.h" #include "yubikeywriter.h" #include "yubikeylogger.h" #include "ui_settingpage.h" #include "ui/helpbox.h" #include "toolpage.h" #include #include #include #include #include #include #include "common.h" #define DECIMAL 0 #define MODHEX 1 #define HEX 2 #define OUT_CHAR_RATE_STD 0 #define OUT_CHAR_RATE_SLOWDOWN_20 1 #define OUT_CHAR_RATE_SLOWDOWN_40 2 #define OUT_CHAR_RATE_SLOWDOWN_60 3 SettingPage::SettingPage(QWidget *parent) : QStackedWidget(parent), ui(new Ui::SettingPage) { QSignalMapper *mapper = new QSignalMapper(this); ui->setupUi(this); m_ykConfig = NULL; //Connect help buttons connectHelpButtons(); connect(ui->updateBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->updateBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); mapper->setMapping(ui->updateBtn, Page_Update); mapper->setMapping(ui->updateBackBtn, Page_Base); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); m_currentPage = 0; setCurrentIndex(Page_Base); //Connect other signals and slots connect(ui->restoreBtn, SIGNAL(clicked()), this, SLOT(restore())); // autosave when changing settings connect(ui->custPrefixCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->logOutputCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->tabFirstBtn, SIGNAL(clicked()), this, SLOT(save())); connect(ui->appendTab1Btn, SIGNAL(clicked()), this, SLOT(save())); connect(ui->appendTab2Btn, SIGNAL(clicked()), this, SLOT(save())); connect(ui->appendCRBtn, SIGNAL(clicked()), this, SLOT(save())); connect(ui->appendDelay1Check, SIGNAL(clicked()), this, SLOT(save())); connect(ui->appendDelay2Check, SIGNAL(clicked()), this, SLOT(save())); connect(ui->srBtnVisibleCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->srUsbVisibleCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->srApiVisibleCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->manUpdateCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->updateCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->fastTrigCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->ledInvertCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->useNumericKeypadCheck, SIGNAL(clicked()), this, SLOT(save())); connect(ui->logFormatCombo, SIGNAL(activated(int)), this, SLOT(save())); connect(ui->logFormatEdit, SIGNAL(textEdited(QString)), this, SLOT(save())); connect(ui->outCharRateCombo, SIGNAL(activated(int)), this, SLOT(save())); connect(ui->exportCheck, SIGNAL(clicked()), this, SLOT(save())); connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); QRegExp modHexRx("^[cbdefghijklnrtuv]{0,4}$"); ui->custPrefixModhexTxt->setValidator(new QRegExpValidator(modHexRx, this)); QRegExp decRx("^[0-9]{0,5}$"); ui->custPrefixDecTxt->setValidator(new QRegExpValidator(decRx, this)); QRegExp hexRx("^[0-9a-f]{0,4}$"); ui->custPrefixHexTxt->setValidator(new QRegExpValidator(hexRx, this)); } SettingPage::~SettingPage() { delete ui->custPrefixModhexTxt->validator(); if(m_ykConfig != NULL) { delete m_ykConfig; } delete ui; } void SettingPage::connectHelpButtons() { //Map the values of the help buttons //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->outFormatHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->outSpeedHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->srVisibilityHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->updateHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->swapHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->manUpdateHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->logFormatEditHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->outFormatHelpBtn, HelpBox::Help_OutputFormat); mapper->setMapping(ui->outSpeedHelpBtn, HelpBox::Help_OutputSpeed); mapper->setMapping(ui->srVisibilityHelpBtn, HelpBox::Help_SrNoVisibility); mapper->setMapping(ui->updateHelpBtn, HelpBox::Help_AllowUpdate); mapper->setMapping(ui->swapHelpBtn, HelpBox::Help_Swap); mapper->setMapping(ui->manUpdateHelpBtn, HelpBox::Help_ManUpdate); mapper->setMapping(ui->logFormatEditHelpBtn, HelpBox::Help_LogFormat); //Connect the mapper connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int))); connect(ui->configProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); } void SettingPage::setCurrentPage(int pageIndex) { m_currentPage = pageIndex; setCurrentIndex(pageIndex); } void SettingPage::init() { load(); } void SettingPage::restoreDefaults() { QSettings settings; settings.setValue(SG_CUSTOMER_PREFIX_USED, false); settings.setValue(SG_CUSTOMER_PREFIX, 0); settings.setValue(SG_LOG_DISABLED, false); // we continue loading LOG_FILENAME since we use that to check if settings are loaded settings.setValue(SG_LOG_FILENAME, YubiKeyLogger::defaultLogFilename()); settings.setValue(SG_LOG_FORMAT, YubiKeyLogger::Format_Traditional); settings.setValue(SG_EXPORT_FILENAME, YubiKeyWriter::defaultExportFilename()); settings.setValue(SG_IMPORT_FILENAME, ToolPage::defaultImportFilename()); settings.setValue(SG_TAB_FIRST, false); settings.setValue(SG_APPEND_TAB1, false); settings.setValue(SG_APPEND_TAB2, false); settings.setValue(SG_APPEND_CR, true); settings.setValue(SG_APPEND_DELAY1, false); settings.setValue(SG_APPEND_DELAY2, false); settings.setValue(SG_PACING_10MS, false); settings.setValue(SG_PACING_20MS, false); settings.setValue(SG_SR_BTN_VISIBLE, true); settings.setValue(SG_SR_USB_VISIBLE, false); settings.setValue(SG_SR_API_VISIBLE, true); settings.setValue(SG_MAN_UPDATE, false); settings.setValue(SG_ALLOW_UPDATE, true); settings.setValue(SG_FAST_TRIG, false); settings.setValue(SG_USE_NUMERIC_KEYPAD, false); settings.setValue(SG_OATH_HOTP8, false); settings.setValue(SG_REQUIRE_INPUT, false); settings.setValue(SG_HMAC_LT64, true); settings.setValue(SG_STRONG_PW1, false); settings.setValue(SG_STRONG_PW2, false); settings.setValue(SG_STRONG_PW3, false); settings.setValue(SG_EXPORT_PREFERENCE, false); } void SettingPage::load() { QSettings settings; QString logFilename = settings.value(SG_LOG_FILENAME).toString(); bool logDisabled = settings.value(SG_LOG_DISABLED).toBool(); int logFormat = settings.value(SG_LOG_FORMAT).toInt(); if(logFilename.isEmpty()) { //This is the first time... set defaults restoreDefaults(); } YubiKeyLogger::setLogFilename(logFilename); QString exportFilename = settings.value(SG_EXPORT_FILENAME).toString(); if(!exportFilename.isEmpty()) { YubiKeyWriter::setExportFilename(exportFilename); } QString importFilename = settings.value(SG_IMPORT_FILENAME).toString(); if(!importFilename.isEmpty()) { ToolPage::setImportFilename(importFilename); } //General settings... //Customer prefix bool custPrefixUsed = settings.value(SG_CUSTOMER_PREFIX_USED).toBool(); if(custPrefixUsed) { ui->custPrefixCheck->setChecked(true); int custPrefix = settings.value(SG_CUSTOMER_PREFIX).toInt(); if(custPrefix > 0) { custPrefixChanged(DECIMAL, QString::number(custPrefix)); ui->custPrefixDecTxt->setEnabled(true); ui->custPrefixModhexTxt->setEnabled(true); ui->custPrefixHexTxt->setEnabled(true); } } else { ui->custPrefixCheck->setChecked(false); ui->custPrefixDecTxt->clear(); ui->custPrefixDecTxt->setEnabled(false); ui->custPrefixModhexTxt->clear(); ui->custPrefixModhexTxt->setEnabled(false); ui->custPrefixHexTxt->clear(); ui->custPrefixHexTxt->setEnabled(false); } // OTP output settings... ui->tabFirstBtn->setChecked(settings.value(SG_TAB_FIRST).toBool()); ui->appendTab1Btn->setChecked(settings.value(SG_APPEND_TAB1).toBool()); ui->appendTab2Btn->setChecked(settings.value(SG_APPEND_TAB2).toBool()); ui->appendCRBtn->setChecked(settings.value(SG_APPEND_CR).toBool()); ui->appendDelay1Check->setChecked(settings.value(SG_APPEND_DELAY1).toBool()); ui->appendDelay2Check->setChecked(settings.value(SG_APPEND_DELAY2).toBool()); bool pacing10ms = settings.value(SG_PACING_10MS).toBool(); bool pacing20ms = settings.value(SG_PACING_20MS).toBool(); int outCharRateIndex = 0; if(pacing10ms) { if(pacing20ms) { outCharRateIndex = OUT_CHAR_RATE_SLOWDOWN_60; } else { outCharRateIndex = OUT_CHAR_RATE_SLOWDOWN_20; } } else if(pacing20ms) { outCharRateIndex = OUT_CHAR_RATE_SLOWDOWN_40; } ui->outCharRateCombo->setCurrentIndex(outCharRateIndex); //Serial # visibility settings... ui->srBtnVisibleCheck->setChecked(settings.value(SG_SR_BTN_VISIBLE).toBool()); ui->srUsbVisibleCheck->setChecked(settings.value(SG_SR_USB_VISIBLE).toBool()); ui->srApiVisibleCheck->setChecked(settings.value(SG_SR_API_VISIBLE).toBool()); //Static Password settings... ui->manUpdateCheck->setChecked(settings.value(SG_MAN_UPDATE).toBool()); //Updatable settings... if(settings.contains(SG_ALLOW_UPDATE)) { ui->updateCheck->setChecked(settings.value(SG_ALLOW_UPDATE).toBool()); } else { ui->updateCheck->setChecked(true); } // extended settings.. ui->fastTrigCheck->setChecked(settings.value(SG_FAST_TRIG).toBool()); ui->useNumericKeypadCheck->setChecked(settings.value(SG_USE_NUMERIC_KEYPAD).toBool()); ui->ledInvertCheck->setChecked(settings.value(SG_LED_INVERT).toBool()); //Logging settings... if(logDisabled) { YubiKeyLogger::disableLogging(); ui->logOutputCheck->setChecked(false); ui->logFormatCombo->setEnabled(false); ui->logFormatEdit->setEnabled(false); } else { YubiKeyLogger::enableLogging(); ui->logOutputCheck->setChecked(true); ui->logFormatCombo->setEnabled(true); ui->logFormatCombo->setCurrentIndex(logFormat); YubiKeyLogger::setLogFormat((YubiKeyLogger::Format)logFormat); if(logFormat == YubiKeyLogger::Format_Flexible) { QString format = settings.value(SG_LOG_FLEXIBLE).toString(); ui->logFormatEdit->setEnabled(true); ui->logFormatEdit->setText(format); YubiKeyLogger::setFlexibleFormat(format); } else { ui->logFormatEdit->setEnabled(false); } } ui->exportCheck->setChecked(settings.value(SG_EXPORT_PREFERENCE).toBool()); //Signal everyone emit settingsChanged(); } void SettingPage::save() { QSettings settings; //General settings... //Customer prefix int custPrefix = 0; if(ui->custPrefixCheck->isChecked()) { settings.setValue(SG_CUSTOMER_PREFIX_USED, true); custPrefix = ui->custPrefixDecTxt->text().toInt(); } else { settings.setValue(SG_CUSTOMER_PREFIX_USED, false); } settings.setValue(SG_CUSTOMER_PREFIX, custPrefix); // OTP output settings... settings.setValue(SG_TAB_FIRST, ui->tabFirstBtn->isChecked()); settings.setValue(SG_APPEND_TAB1, ui->appendTab1Btn->isChecked()); settings.setValue(SG_APPEND_TAB2, ui->appendTab2Btn->isChecked()); settings.setValue(SG_APPEND_CR, ui->appendCRBtn->isChecked()); settings.setValue(SG_APPEND_DELAY1, ui->appendDelay1Check->isChecked()); settings.setValue(SG_APPEND_DELAY2, ui->appendDelay2Check->isChecked()); switch(ui->outCharRateCombo->currentIndex()) { case OUT_CHAR_RATE_STD: settings.setValue(SG_PACING_10MS, false); settings.setValue(SG_PACING_20MS, false); break; case OUT_CHAR_RATE_SLOWDOWN_20: settings.setValue(SG_PACING_10MS, true); settings.setValue(SG_PACING_20MS, false); break; case OUT_CHAR_RATE_SLOWDOWN_40: settings.setValue(SG_PACING_10MS, false); settings.setValue(SG_PACING_20MS, true); break; case OUT_CHAR_RATE_SLOWDOWN_60: settings.setValue(SG_PACING_10MS, true); settings.setValue(SG_PACING_20MS, true); break; } //Serial # visibility settings... settings.setValue(SG_SR_BTN_VISIBLE, ui->srBtnVisibleCheck->isChecked()); settings.setValue(SG_SR_USB_VISIBLE, ui->srUsbVisibleCheck->isChecked()); settings.setValue(SG_SR_API_VISIBLE, ui->srApiVisibleCheck->isChecked()); //Static Password settings... settings.setValue(SG_MAN_UPDATE, ui->manUpdateCheck->isChecked()); // Updatable settings... settings.setValue(SG_ALLOW_UPDATE, ui->updateCheck->isChecked()); // Extended settings settings.setValue(SG_FAST_TRIG, ui->fastTrigCheck->isChecked()); settings.setValue(SG_USE_NUMERIC_KEYPAD, ui->useNumericKeypadCheck->isChecked()); settings.setValue(SG_LED_INVERT, ui->ledInvertCheck->isChecked()); //Logging settings... if(ui->logOutputCheck->isChecked()) { settings.setValue(SG_LOG_DISABLED, false); settings.setValue(SG_LOG_FORMAT, ui->logFormatCombo->currentIndex()); if(ui->logFormatCombo->currentIndex() == YubiKeyLogger::Format_Flexible) { settings.setValue(SG_LOG_FLEXIBLE, ui->logFormatEdit->text()); } } else { settings.setValue(SG_LOG_DISABLED, true); } settings.setValue(SG_EXPORT_PREFERENCE, ui->exportCheck->isChecked()); //Reload settings load(); showStatusMessage(tr(SETTINGS_SAVED), 0); } void SettingPage::restore() { //Confirm restore //Confirm from client switch ( QMessageBox::question( this, tr(RESTORE_SETTING), tr(WARN_RESTORE_SETTING), tr("&Yes"), tr("&No"), QString::null, 1, 1 )) { case 0: restoreDefaults(); //Reload settings load(); showStatusMessage(tr(SETTINGS_RESTORED), 0); break; default: break; } } void SettingPage::on_custPrefixCheck_stateChanged(int state) { if(state == 0) { ui->custPrefixDecTxt->setEnabled(false); ui->custPrefixModhexTxt->setEnabled(false); ui->custPrefixHexTxt->setEnabled(false); } else { ui->custPrefixDecTxt->setEnabled(true); ui->custPrefixModhexTxt->setEnabled(true); ui->custPrefixHexTxt->setEnabled(true); } } void SettingPage::on_custPrefixDecTxt_editingFinished() { custPrefixChanged(DECIMAL, ui->custPrefixDecTxt->text()); save(); } void SettingPage::on_custPrefixModhexTxt_editingFinished() { custPrefixChanged(MODHEX, ui->custPrefixModhexTxt->text()); save(); } void SettingPage::on_custPrefixHexTxt_editingFinished() { custPrefixChanged(HEX, ui->custPrefixHexTxt->text()); save(); } void SettingPage::on_doUpdateBtn_clicked() { int slot; if(ui->updateSlot1Radio->isChecked()) { slot = 1; } else if(ui->updateSlot2Radio->isChecked()) { slot = 2; } else { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return; } if(m_ykConfig != NULL) { delete m_ykConfig; } m_ykConfig = new YubiKeyConfig(); m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_Update); m_ykConfig->setConfigSlot(slot); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); // access code m_ykConfig->setCurrentAccessCodeTxt( ui->configProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->configProtectionBox->newAccessCode(), ui->configProtectionBox->newAccMode()); if(ui->updateDormantCheck->isChecked()) { m_ykConfig->setDormant(true); } //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(updateConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } void SettingPage::updateConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(updateConfigWritten(bool, const QString &))); if(written) { qDebug() << "Configuration updated." << msg; emit showStatusMessage(tr("Configuration successfully updated.", 0)); } else { qDebug() << "Failed update."; emit showStatusMessage(msg, 1);; } } void SettingPage::on_swapBtn_clicked() { if(m_ykConfig != NULL) { delete m_ykConfig; } m_ykConfig = new YubiKeyConfig(); m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_Swap); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); // access code m_ykConfig->setCurrentAccessCodeTxt( ui->configProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->configProtectionBox->newAccessCode(), ui->configProtectionBox->newAccMode()); //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(swapWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } void SettingPage::swapWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(swapWritten(bool, const QString &))); if(written) { qDebug() << "Configurations swapped." << msg; emit showStatusMessage(tr("Configuration successfully swapped.", 0)); } else { qDebug() << "Failed swapping." << msg; emit showStatusMessage(msg, 1);; } } void SettingPage::keyFound(bool found, bool* featuresMatrix) { if(found) { if(featuresMatrix[YubiKeyFinder::Feature_Updatable]) { ui->updateBtn->setEnabled(true); } } else { ui->updateBtn->setEnabled(false); } } void SettingPage::custPrefixChanged(int type, QString src) { unsigned char buf[16]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; switch(type) { // decimal case DECIMAL: { QString tmp = QString::number(src.toULongLong(), 16); size_t len = tmp.length(); if(len % 2 != 0) { len++; } YubiKeyUtil::qstrClean(&tmp, (size_t)len, true); YubiKeyUtil::qstrHexDecode(buf, &bufLen, tmp); break; } // modhex case MODHEX: YubiKeyUtil::qstrModhexDecode(buf, &bufLen, src); break; // hex case HEX: YubiKeyUtil::qstrHexDecode(buf, &bufLen, src); break; } QString hex = YubiKeyUtil::qstrHexEncode(buf, bufLen); QString modhex = YubiKeyUtil::qstrModhexEncode(buf, bufLen); bool ok = false; qulonglong dec = hex.toULongLong(&ok, 16); if(dec > 0) { ui->custPrefixDecTxt->setText(QString::number(dec)); ui->custPrefixModhexTxt->setText(modhex); ui->custPrefixHexTxt->setText(hex); } } void SettingPage::reloadSettings() { load(); } yubikey-personalization-gui-3.1.24/src/ui/diagnostics.h0000664000175000017500000000337512642452141021630 0ustar klasklas/* Copyright (C) 2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef DIAGNOSTICS_H #define DIAGNOSTICS_H #include #include namespace Ui { class Diagnostics; } class Diagnostics : public QDialog { Q_OBJECT public: explicit Diagnostics(QWidget *parent = 0); ~Diagnostics(); private: Ui::Diagnostics *ui; QString osVersion(); void setup(); private slots: void addDiagnostic(QString text); void clicked(QAbstractButton *button); }; #endif // DIAGNOSTICS_H yubikey-personalization-gui-3.1.24/src/ui/diagnostics.cpp0000664000175000017500000001024612642452141022156 0ustar klasklas/* Copyright (C) 2014 Yubico AB. 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. 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 HOLDER 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. */ #include "ui/diagnostics.h" #include "ui_diagnostics.h" #include "yubikeywriter.h" #include "yubikeyfinder.h" #include "version.h" #include #include #include Diagnostics::Diagnostics(QWidget *parent) : QDialog(parent), ui(new Ui::Diagnostics) { ui->setupUi(this); ui->txtBrowser->clear(); connect(YubiKeyWriter::getInstance(), SIGNAL(errorOccurred(QString)), this, SLOT(addDiagnostic(QString))); connect(YubiKeyWriter::getInstance(), SIGNAL(diagnostics(QString)), this, SLOT(addDiagnostic(QString))); connect(YubiKeyFinder::getInstance(), SIGNAL(errorOccurred(QString)), this, SLOT(addDiagnostic(QString))); connect(YubiKeyFinder::getInstance(), SIGNAL(diagnostics(QString)), this, SLOT(addDiagnostic(QString))); connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(clicked(QAbstractButton*))); setup(); } Diagnostics::~Diagnostics() { delete ui; } void Diagnostics::addDiagnostic(QString text) { QDateTime ts = QDateTime::currentDateTime(); ui->txtBrowser->append(ts.toString("yyyy-MM-ddThh:mm:ss; ") + text); } void Diagnostics::clicked(QAbstractButton *button) { if(ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) { setup(); } } void Diagnostics::setup() { ui->txtBrowser->clear(); addDiagnostic(QString("App_version: %1; Lib_version: %2; QT_version: %3; OS_version: %4; Word_size: %5") .arg(VER_PRODUCTVERSION_STR, ykpers_check_version(NULL), qVersion(), osVersion(), QString::number(QSysInfo::WordSize))); } QString Diagnostics::osVersion() { #ifdef Q_OS_LINUX return "Linux"; #elif defined(Q_OS_MAC) QString mac = "OS X "; switch(QSysInfo::MacintoshVersion) { case QSysInfo::MV_LEOPARD: mac += "Leopard"; break; case QSysInfo::MV_SNOWLEOPARD: mac += "SnowLeopard"; break; case QSysInfo::MV_LION: mac += "Lion"; break; case QSysInfo::MV_MOUNTAINLION: mac += "MountainLion"; break; default: mac += "unknown"; break; } return mac; #elif defined(Q_OS_WIN32) QString win = "Windows "; switch(QSysInfo::WindowsVersion) { case QSysInfo::WV_2000: win += "2000"; break; case QSysInfo::WV_XP: win += "XP"; break; case QSysInfo::WV_2003: win += "2003"; break; case QSysInfo::WV_VISTA: win += "Vista"; break; case QSysInfo::WV_WINDOWS7: win += "7"; break; case QSysInfo::WV_WINDOWS8: win += "8"; break; default: win += "unknown"; break; } return win; #else return "Unknown OS"; #endif } yubikey-personalization-gui-3.1.24/src/ui/yubiaccbox.ui0000664000175000017500000001462412642452141021636 0ustar klasklas YubiAccBox 0 0 350 120 Form font: 11px "Verdana"; color: rgb(0, 0, 0); 0 0 350 120 font-weight: bold; Configuration Protection (6 bytes Hex) 10 24 330 22 font-weight: normal; YubiKey(s) unprotected - Keep it that way YubiKey(s) unprotected - Enable protection YubiKey(s) protected - Disable protection YubiKey(s) protected - Keep it that way YubiKey(s) protected - Change access code false 170 52 170 20 font-weight: normal; hh hh hh hh hh hh; 17 17 10 45 141 20 font-weight:normal; Current Access Code 10 80 141 20 font-weight:normal; New Access Code false 170 87 170 20 0 0 font-weight: normal; hh hh hh hh hh hh; 17 17 325 0 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false false 10 60 150 23 font: 11px "Verdana"; color: rgb(0, 0, 0); Use Serial Number false 10 95 150 23 font: 11px "Verdana"; color: rgb(0, 0, 0); Use Serial Number yubikey-personalization-gui-3.1.24/src/ui/helpbox.h0000664000175000017500000000422412642452141020754 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef HELPBOX_H #define HELPBOX_H #include namespace Ui { class HelpBox; } class HelpBox : public QDialog { Q_OBJECT public: explicit HelpBox(QWidget *parent = 0); ~HelpBox(); enum Help { Help_ConfigurationSlot, Help_PublicID, Help_PrivateID, Help_SecretKey, Help_ParameterGeneration, Help_ConfigurationProtection, Help_OutputFormat, Help_OutputSpeed, Help_SrNoVisibility, Help_OathPublicID, Help_HotpLen, Help_HotpParam, Help_StaticScanCode, Help_ChalRespYubico, Help_ChalRespHmac, Help_ChalRespOption, Help_AllowUpdate, Help_Swap, Help_ManUpdate, Help_LogFormat, }; void setHelpIndex(Help helpIndex); private: Ui::HelpBox *ui; }; #endif // HELPBOX_H yubikey-personalization-gui-3.1.24/src/ui/diagnostics.ui0000664000175000017500000000765112642452141022017 0ustar klasklas Diagnostics Qt::NonModal 0 0 500 260 0 0 500 100 500 260 YubiKey Diagnostics font: 11px "Verdana"; color: rgb(0, 0, 0); false 10 10 481 241 false font: 11px "Verdana"; QFrame::NoFrame QFrame::Plain QTextEdit::AutoBulletList false <!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:'Verdana'; font-size:11px; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> true Qt::Horizontal QDialogButtonBox::Close|QDialogButtonBox::Reset true buttonBox rejected() Diagnostics reject() 316 260 286 274 buttonBox accepted() Diagnostics accept() 248 254 157 274 yubikey-personalization-gui-3.1.24/src/ui/toolpage.cpp0000664000175000017500000004703112642452141021463 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "toolpage.h" #include "yubikeyfinder.h" #include "yubikeywriter.h" #include "yubikeyutil.h" #include "ui_toolpage.h" #include "ui/helpbox.h" #include "ui/confirmbox.h" #include "mainwindow.h" #include "otppage.h" #include "chalresppage.h" #include "oathpage.h" #include "staticpage.h" #include #include #include #include #include #include #include #include #include "common.h" #define IMPORT_FILENAME_DEF "import.ycfg" QString ToolPage::m_filename = defaultImportFilename(); ToolPage::ToolPage(QWidget *parent) : QStackedWidget(parent), ui(new Ui::ToolPage) { ui->setupUi(this); //Connect pages connectPages(); //Connect help buttons connectHelpButtons(); //Connect other signals and slots connect(ui->converterResetBtn, SIGNAL(clicked()), this, SLOT(resetConverterPage())); connect(ui->chalRespResetBtn, SIGNAL(clicked()), this, SLOT(resetChalRespPage())); connect(ui->chalRespPerformBtn, SIGNAL(clicked()), this, SLOT(performChallengeResponse())); connect(ui->chalRespChallenge, SIGNAL(editingFinished()), this, SLOT(on_chalRespChallenge_editingFinished())); connect(ui->ndefResetBtn, SIGNAL(clicked()), this, SLOT(resetNdefPage())); connect(ui->ndefProgramBtn, SIGNAL(clicked()), this, SLOT(programNdef())); connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); ui->zapAccCodeEdit->setEnabled(false); ui->ndefAccCodeEdit->setEnabled(false); ui->importBox->setVisible(false); loadSettings(); } ToolPage::~ToolPage() { delete ui; } /* Common */ void ToolPage::connectPages() { //Map the values of the navigation buttons with the indexes of //the stacked widget //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->converterBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->converterBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->chalRespBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->chalRespBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->ndefBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->ndefBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->zapBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->zapBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->importBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->importBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->converterBtn, Page_Converter); mapper->setMapping(ui->converterBackBtn, Page_Base); mapper->setMapping(ui->chalRespBtn, Page_ChalResp); mapper->setMapping(ui->chalRespBackBtn, Page_Base); mapper->setMapping(ui->ndefBtn, Page_Ndef); mapper->setMapping(ui->ndefBackBtn, Page_Base); mapper->setMapping(ui->zapBtn, Page_Zap); mapper->setMapping(ui->zapBackBtn, Page_Base); mapper->setMapping(ui->importBtn, Page_Import); mapper->setMapping(ui->importBackBtn, Page_Base); //Connect the mapper to the widget //The mapper will set a value to each button and //set that value to the widget //connect(pageMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentIndex(int))); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); //Set the current page m_currentPage = 0; setCurrentIndex(Page_Base); } void ToolPage::loadSettings() { QSettings settings; ui->importBox->setVisible(settings.value(SG_EXPORT_PREFERENCE).toBool()); } void ToolPage::setCurrentPage(int pageIndex) { //Page changed... m_currentPage = pageIndex; switch(pageIndex){ case Page_Converter: resetConverterPage(); break; } setCurrentIndex(pageIndex); } void ToolPage::connectHelpButtons() { } void ToolPage::resetChalRespPage() { ui->chalRespChallenge->clear(); ui->chalRespResponse->clear(); } void ToolPage::on_chalRespChallenge_editingFinished() { QString challenge = ui->chalRespChallenge->text().trimmed(); ui->chalRespChallenge->setText(challenge); } void ToolPage::performChallengeResponse() { QString challenge = ui->chalRespChallenge->text(); QString response = ""; bool hmac; int slot; if(ui->chalRespHmacRadio->isChecked()) { hmac = true; } else if(ui->chalRespYubicoRadio->isChecked()) { hmac = false; } else { emit showStatusMessage(tr(ERR_CHAL_TYPE_NOT_SELECTED), 1); return; } if(ui->chalRespSlot1Radio->isChecked()) { slot = 1; } else if(ui->chalRespSlot2Radio->isChecked()) { slot = 2; } else { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return; } YubiKeyWriter::getInstance()->doChallengeResponse(challenge, response, slot, hmac); qDebug() << "response was: " << response; ui->chalRespResponse->setText(response); } /* Quick Page handling */ void ToolPage::resetConverterPage() { convert(0, ""); ui->converterHexTxt->setCursorPosition(0); ui->converterHexTxt->setFocus(); } void ToolPage::convert(int updatedIndex, QString txt) { unsigned char buf[32]; memset(buf, 0, sizeof(buf)); size_t bufLen; switch(updatedIndex) { case 0: //Hex YubiKeyUtil::qstrHexDecode(buf, &bufLen, txt); break; case 1: //Modhex YubiKeyUtil::qstrModhexDecode(buf, &bufLen, txt); break; case 2: //Decimal QString tmp = QString::number(txt.toULongLong(), 16); size_t len = tmp.length(); if(len % 2 != 0) { len++; } YubiKeyUtil::qstrClean(&tmp, (size_t)len, true); YubiKeyUtil::qstrHexDecode(buf, &bufLen, tmp); break; } QString hex = YubiKeyUtil::qstrHexEncode(buf, bufLen); QString modhex = YubiKeyUtil::qstrModhexEncode(buf, bufLen); bool ok = false; qulonglong dec = hex.toULongLong(&ok, 16); int hexLen = hex.length(); int modhexLen = modhex.length(); ui->converterHexTxt->setText(hex); ui->converterModhexTxt->setText(modhex); ui->converterDecTxt->setText(QString::number(dec)); ui->converterHexCopyBtn->setEnabled(hexLen > 0); ui->converterModhexCopyBtn->setEnabled(modhexLen > 0); ui->converterDecCopyBtn->setEnabled( ui->converterDecTxt->text().length() > 0); ui->converterHexLenLbl->setText(tr("(%1 chars)").arg(hexLen)); ui->converterModhexLenLbl->setText(tr("(%1 chars)").arg(modhexLen)); if(hexLen != 0 && !ok) { ui->converterDecErrLbl->setText(tr(TOVERFLOW)); } else { ui->converterDecErrLbl->setText(tr("")); } } void ToolPage::on_converterHexTxt_editingFinished() { QString txt = ui->converterHexTxt->text(); YubiKeyUtil::qstrClean(&txt, 0, true); size_t len = txt.length(); if(len > 0) { if(len % 2 != 0) { len++; } YubiKeyUtil::qstrClean(&txt, (size_t)len, true); convert(0, txt); } ui->converterHexTxt->setCursorPosition(len + len/2); } void ToolPage::on_converterModhexTxt_editingFinished() { QString txt = ui->converterModhexTxt->text(); YubiKeyUtil::qstrModhexClean(&txt, 0, true); size_t len = txt.length(); if(len > 0) { if(len % 2 != 0) { len++; } YubiKeyUtil::qstrModhexClean(&txt, (size_t)len, true); convert(1, txt); } ui->converterModhexTxt->setCursorPosition(len + len/2); } void ToolPage::on_converterDecTxt_editingFinished() { QString txt = ui->converterDecTxt->text(); bool ok = false; qulonglong dec = txt.toULongLong(&ok); if(ok) { if(dec > 0) { size_t len = txt.length(); YubiKeyUtil::qstrClean(&txt, (size_t)len, true); convert(2, txt); ui->converterDecTxt->setCursorPosition(len); } } else { ui->converterDecErrLbl->setText(tr(TOVERFLOW)); } } void ToolPage::copyToClipboard(const QString &str) { QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(str); showStatusMessage(tr(VALUE_COPIED), 0); } void ToolPage::on_converterHexCopyBtn_clicked() { QString txt = ui->converterHexTxt->text(); YubiKeyUtil::qstrClean(&txt, 0, true); copyToClipboard(txt); } void ToolPage::on_converterModhexCopyBtn_clicked() { QString txt = ui->converterModhexTxt->text(); YubiKeyUtil::qstrModhexClean(&txt, 0, true); copyToClipboard(txt); } void ToolPage::on_converterDecCopyBtn_clicked() { copyToClipboard(ui->converterDecTxt->text()); } void ToolPage::resetNdefPage() { ui->ndefEdit->setText("https://my.yubico.com/neo/"); ui->ndefTextLangEdit->setText("en-US"); ui->ndefUriRadio->setChecked(true); ui->ndefAccCodeCheckbox->setChecked(false); ui->ndefSlot1Radio->setChecked(false); ui->ndefSlot2Radio->setChecked(false); } void ToolPage::programNdef() { QSettings settings; YubiKeyWriter *writer = YubiKeyWriter::getInstance(); bool uri = true; QString language; QString payload; int slot; if(ui->ndefTextRadio->isChecked()) { uri = false; language = ui->ndefTextLangEdit->text().trimmed(); if(language.isEmpty()) { return; } } payload = ui->ndefEdit->text().trimmed(); if(payload.isEmpty()) { return; } if(uri && !settings.value(SG_NDEF_WITHOUT_HTTP).toBool()) { if(!payload.startsWith("http")) { ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_NdefWithoutHttp); int ret = confirm.exec(); if(ret != 1) // 1 is yes return; } } if(ui->ndefSlot1Radio->isChecked()) { slot = 1; } else if(ui->ndefSlot2Radio->isChecked()) { slot = 2; } else { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return; } connect(writer, SIGNAL(configWritten(bool, const QString &)), this, SLOT(ndefWritten(bool, const QString &))); writer->writeNdef(uri, language, payload, ui->ndefAccCodeEdit->text().remove(" "), slot); } void ToolPage::ndefWritten(bool written, __attribute__((unused)) const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(ndefWritten(bool, const QString &))); if(written) { showStatusMessage(tr("NDEF successfully written")); } } void ToolPage::on_ndefTextRadio_toggled(bool checked) { if(checked) { ui->ndefTextLangEdit->setEnabled(true); ui->ndefEdit->setText(""); } else { ui->ndefTextLangEdit->setText("en-US"); ui->ndefTextLangEdit->setEnabled(false); ui->ndefEdit->setText("https://my.yubico.com/neo/"); } } void ToolPage::on_ndefAccCodeCheckbox_toggled(bool checked) { ui->ndefAccCodeEdit->setText("00 00 00 00 00 00"); ui->ndefAccCodeEdit->setEnabled(checked); ui->ndefUseSerial->setChecked(false); ui->ndefUseSerial->setEnabled(checked); } void ToolPage::on_ndefUseSerial_toggled(bool checked) { if(checked) { setSerial(ui->ndefAccCodeEdit); } } void ToolPage::on_zapPerformBtn_clicked() { int slot; if(ui->zapSlot1Radio->isChecked()) { slot = 1; } else if(ui->zapSlot2Radio->isChecked()) { slot = 2; } else { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return; } YubiKeyWriter *writer = YubiKeyWriter::getInstance(); connect(writer, SIGNAL(configWritten(bool, const QString &)), this, SLOT(zapDone(bool, const QString &))); writer->deleteConfig(slot, ui->zapAccCodeEdit->text().remove(" ")); } void ToolPage::zapDone(bool written, __attribute__((unused)) const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(zapDone(bool, const QString &))); if(written) { showStatusMessage(tr("Configuration successfully deleted.")); } } void ToolPage::on_zapAccCodeCheckbox_toggled(bool checked) { ui->zapAccCodeEdit->setText("00 00 00 00 00 00"); ui->zapAccCodeEdit->setEnabled(checked); ui->zapUseSerial->setChecked(false); ui->zapUseSerial->setEnabled(checked); } void ToolPage::on_zapUseSerial_toggled(bool checked) { if(checked) { setSerial(ui->zapAccCodeEdit); } } void ToolPage::on_importPerformBtn_clicked() { QString filename = QFileDialog::getOpenFileName(this, tr("Open file for import"), m_filename, tr("Yubico cfg format (*.ycfg);;All Files (*.*)")); if(filename.isEmpty()) { return; } QFile file(filename); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { showStatusMessage(tr("Failed to open selected file."), 1); } char data[1024]; int len = file.read(data, 1024); if(!len) { showStatusMessage(tr("Failed to read from selected file."), 1); } file.close(); YKP_CONFIG *cfg = ykp_alloc(); YK_STATUS *ykds = YubiKeyFinder::getInstance()->status(); ykp_configure_version(cfg, ykds); int ret = ykp_import_config(cfg, data, len, YKP_FORMAT_YCFG); if(ret) { QSettings settings; m_filename = filename; settings.setValue(SG_IMPORT_FILENAME, filename); MainWindow::Page page = MainWindow::Page_Otp; int tab = OtpPage::Page_Advanced; if(ykp_get_tktflag_OATH_HOTP(cfg)) { if(ykp_get_cfgflag_CHAL_HMAC(cfg)) { qDebug() << "importing mode chal-resp hmac"; page = MainWindow::Page_ChalResp; tab = ChalRespPage::Page_Advanced; settings.setValue(SG_REQUIRE_INPUT, ykp_get_cfgflag_CHAL_BTN_TRIG(cfg)); settings.setValue(SG_HMAC_LT64, ykp_get_cfgflag_HMAC_LT64(cfg)); } else if(ykp_get_cfgflag_CHAL_YUBICO(cfg)) { qDebug() << "importing mode chal-resp yubico"; page = MainWindow::Page_ChalResp; tab = ChalRespPage::Page_Quick; settings.setValue(SG_REQUIRE_INPUT, ykp_get_cfgflag_CHAL_BTN_TRIG(cfg)); } else { qDebug() << "importing mode oath hotp"; page = MainWindow::Page_Oath; tab = OathPage::Page_Advanced; settings.setValue(SG_OATH_HOTP8, ykp_get_cfgflag_OATH_HOTP8(cfg)); // XXX: handle seed and fixed_modhex } } else if(ykp_get_cfgflag_STATIC_TICKET(cfg)) { qDebug() << "importing mode static"; page = MainWindow::Page_Static; tab = StaticPage::Page_Advanced; settings.setValue(SG_STRONG_PW1, ykp_get_cfgflag_STRONG_PW1(cfg)); if(ykp_get_cfgflag_STRONG_PW2(cfg)) { settings.setValue(SG_STRONG_PW2, true); settings.setValue(SG_STRONG_PW3, ykp_get_cfgflag_SEND_REF(cfg)); } else { settings.setValue(SG_STRONG_PW2, false); } } else { qDebug() << "importing yubico otp"; } settings.setValue(SG_MAN_UPDATE, ykp_get_cfgflag_MAN_UPDATE(cfg)); settings.setValue(SG_PACING_10MS, ykp_get_cfgflag_PACING_10MS(cfg)); settings.setValue(SG_PACING_20MS, ykp_get_cfgflag_PACING_20MS(cfg)); settings.setValue(SG_APPEND_CR, ykp_get_tktflag_APPEND_CR(cfg)); settings.setValue(SG_APPEND_DELAY1, ykp_get_tktflag_APPEND_DELAY1(cfg)); settings.setValue(SG_APPEND_DELAY2, ykp_get_tktflag_APPEND_DELAY2(cfg)); settings.setValue(SG_APPEND_TAB1, ykp_get_tktflag_APPEND_TAB1(cfg)); settings.setValue(SG_APPEND_TAB2, ykp_get_tktflag_APPEND_TAB2(cfg)); settings.setValue(SG_TAB_FIRST, ykp_get_tktflag_TAB_FIRST(cfg)); settings.setValue(SG_SR_BTN_VISIBLE, ykp_get_extflag_SERIAL_BTN_VISIBLE(cfg)); settings.setValue(SG_SR_USB_VISIBLE, ykp_get_extflag_SERIAL_USB_VISIBLE(cfg)); settings.setValue(SG_SR_API_VISIBLE, ykp_get_extflag_SERIAL_API_VISIBLE(cfg)); settings.setValue(SG_USE_NUMERIC_KEYPAD, ykp_get_extflag_USE_NUMERIC_KEYPAD(cfg)); settings.setValue(SG_FAST_TRIG, ykp_get_extflag_FAST_TRIG(cfg)); settings.setValue(SG_ALLOW_UPDATE, ykp_get_extflag_ALLOW_UPDATE(cfg)); settings.setValue(SG_LED_INVERT, ykp_get_extflag_LED_INV(cfg)); int config = ykp_config_num(cfg); emit switchPage(page, tab, config); emit reloadSettings(); } else { showStatusMessage(tr("Failed to parse the configuration."), 1); } ykp_free_config(cfg); } void ToolPage::keyFound(bool found, bool* featuresMatrix) { if(found && featuresMatrix[YubiKeyFinder::Feature_ChallengeResponse]) { ui->chalRespPerformBtn->setEnabled(true); } else { ui->chalRespPerformBtn->setEnabled(false); } if(found && featuresMatrix[YubiKeyFinder::Feature_Ndef]) { ui->ndefProgramBtn->setEnabled(true); } else { ui->ndefProgramBtn->setEnabled(false); } if(found && featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) { ui->chalRespSlot2Radio->setEnabled(true); ui->zapSlot2Radio->setEnabled(true); ui->ndefSlot2Radio->setEnabled(true); } else { ui->chalRespSlot2Radio->setEnabled(false); ui->zapSlot2Radio->setEnabled(false); ui->ndefSlot2Radio->setEnabled(false); } ui->zapPerformBtn->setEnabled(found); ui->importPerformBtn->setEnabled(found); if(found) { m_serial = QString::number(YubiKeyFinder::getInstance()->serial()); int num = 12 - m_serial.length(); for(int i = 0; i < num; i++) { m_serial.prepend("0"); } if(!m_serial.isEmpty()) { if(ui->ndefUseSerial->isChecked()) { setSerial(ui->ndefAccCodeEdit); } if(ui->zapUseSerial->isChecked()) { setSerial(ui->zapAccCodeEdit); } } } else { m_serial.clear(); } } void ToolPage::setImportFilename(QString filename) { m_filename = filename; } QString ToolPage::defaultImportFilename() { return QDir::homePath() + "/" + IMPORT_FILENAME_DEF; } void ToolPage::setSerial(QLineEdit *line) { if(!m_serial.isEmpty()) { line->setText(m_serial); } } yubikey-personalization-gui-3.1.24/src/ui/toolpage.h0000664000175000017500000000667212642452141021136 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef TOOLPAGE_H #define TOOLPAGE_H #include #include namespace Ui { class ToolPage; } class ToolPage : public QStackedWidget { Q_OBJECT public: explicit ToolPage(QWidget *parent = 0); ~ToolPage(); static void setImportFilename(QString filename); static QString defaultImportFilename(void); enum Page { Page_Base, Page_Converter, Page_ChalResp, Page_Ndef, Page_Zap, Page_Import, }; private: Ui::ToolPage *ui; int m_currentPage; QString m_serial; static QString m_filename; void setSerial(QLineEdit *line); public slots: void loadSettings(); void setCurrentPage(int pageIndex); private slots: void connectPages(); void connectHelpButtons(); // Converter Page void resetConverterPage(); void convert(int updatedIndex, QString txt); void on_converterHexTxt_editingFinished(); void on_converterModhexTxt_editingFinished(); void on_converterDecTxt_editingFinished(); void copyToClipboard(const QString &str); void on_converterHexCopyBtn_clicked(); void on_converterModhexCopyBtn_clicked(); void on_converterDecCopyBtn_clicked(); // Challenge Response Page void resetChalRespPage(); void performChallengeResponse(); void on_chalRespChallenge_editingFinished(); // ndef page void resetNdefPage(); void programNdef(); void on_ndefTextRadio_toggled(bool checked); void ndefWritten(bool written, const QString &msg); void on_ndefAccCodeCheckbox_toggled(bool checked); void on_ndefUseSerial_toggled(bool checked); // zap page void on_zapPerformBtn_clicked(); void on_zapAccCodeCheckbox_toggled(bool checked); void on_zapUseSerial_toggled(bool checked); void zapDone(bool written, const QString &msg); // import page void on_importPerformBtn_clicked(); void keyFound(bool found, bool* featuresMatrix); signals: void showStatusMessage(const QString &text, int status = 0); void reloadSettings(); void switchPage(int page, int tab, int slot); void showHelp(int helpIndex); }; #endif // TOOLPAGE_H yubikey-personalization-gui-3.1.24/src/ui/mainwindow.h0000664000175000017500000000567412642452141021501 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include "qtimer.h" class ToolPage; class OtpPage; class OathPage; class StaticPage; class ChalRespPage; class SettingPage; class AboutPage; class Diagnostics; class HelpBox; class QStackedWidget; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); enum Page { Page_Otp, Page_Oath, Page_Static, Page_ChalResp, Page_Settings, Page_Tools, Page_About }; private: Ui::MainWindow *ui; int m_currentPage; OtpPage *m_otpPage; OathPage *m_oathPage; StaticPage *m_staticPage; ChalRespPage *m_chalRespPage; SettingPage *m_settingPage; ToolPage *m_toolPage; AboutPage *m_aboutPage; Diagnostics *m_diagnostics; HelpBox *m_help; QTimer *m_timer; QAction *animationAction; QAction *diagnosticsAction; void createPages(); private slots: void setCurrentPage(int pageIndex, int tab = 0, int slot = 0); // Device Widget void resetDeviceInfo(); void keyFound(bool found, bool* featuresMatrix, int error); // Status Widget void showStatusMessage(const QString &text, int status = 1); void clearStatusMessage(); void copyToClipboard(const QString &str); void on_serialNoDecCopyBtn_clicked(); void on_serialNoHexCopyBtn_clicked(); void on_serialNoModhexCopyBtn_clicked(); void toggleAnimation(bool checked); void triggerDiagnostics(); void triggerHelp(int index); void aboutToQuit(); }; #endif // MAINWINDOW_H yubikey-personalization-gui-3.1.24/src/ui/settingpage.h0000664000175000017500000000512612642452141021627 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef SETTINGPAGE_H #define SETTINGPAGE_H #include #include "yubikeyconfig.h" namespace Ui { class SettingPage; } class SettingPage : public QStackedWidget { Q_OBJECT public: explicit SettingPage(QWidget *parent = 0); ~SettingPage(); void init(); enum Page { Page_Base, Page_Update, }; private: Ui::SettingPage *ui; int m_currentPage; YubiKeyConfig *m_ykConfig; public slots: void reloadSettings(); void setCurrentPage(int pageIndex); private slots: void connectHelpButtons(); void restoreDefaults(); void load(); void save(); void restore(); void on_custPrefixCheck_stateChanged(int state); void on_custPrefixDecTxt_editingFinished(); void on_custPrefixModhexTxt_editingFinished(); void on_custPrefixHexTxt_editingFinished(); void on_doUpdateBtn_clicked(); void on_swapBtn_clicked(); void updateConfigWritten(bool written, const QString &msg); void swapWritten(bool written, const QString &msg); void keyFound(bool found, bool* featuresMatrix); void custPrefixChanged(int type, QString src); signals: void settingsChanged(); void showStatusMessage(const QString &text, int status = 0); void showHelp(int helpIndex); }; #endif // SETTINGPAGE_H yubikey-personalization-gui-3.1.24/src/ui/mainwindow.cpp0000664000175000017500000005617012642452141022031 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "ui/mainwindow.h" #include "ui/ui_mainwindow.h" #include "yubikeyfinder.h" #include "yubikeywriter.h" #include "yubikeyutil.h" #include "yubikeylogger.h" #include "ui/otppage.h" #include "ui/oathpage.h" #include "ui/staticpage.h" #include "ui/chalresppage.h" #include "ui/toolpage.h" #include "ui/settingpage.h" #include "ui/aboutpage.h" #include "ui/diagnostics.h" #include "ui/helpbox.h" #include #include #include #include #include #include #include #include "common.h" #include "version.h" #define TICKMAP QPixmap(":/res/images/tick.png") #define CROSSMAP QPixmap(":/res/images/cross.png") #define BLANKMAP QPixmap(":/res/images/blank.png") #define COPYMAP QPixmap(":/res/images/clipboard.png") MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setFixedSize(900, 710); m_timer = 0; //Create pages createPages(); //Connect other signals and slots connect(ui->exitMenuBtn, SIGNAL(clicked()), qApp, SLOT(quit())); connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*, int))); connect(YubiKeyWriter::getInstance(), SIGNAL(errorOccurred(QString)), this, SLOT(showStatusMessage(QString))); connect(m_otpPage, SIGNAL(showStatusMessage(const QString &,int)), this, SLOT(showStatusMessage(const QString &,int))); connect(m_oathPage, SIGNAL(showStatusMessage(const QString &,int)), this, SLOT(showStatusMessage(const QString &,int))); connect(m_staticPage, SIGNAL(showStatusMessage(const QString &,int)), this, SLOT(showStatusMessage(const QString &,int))); connect(m_chalRespPage, SIGNAL(showStatusMessage(const QString &,int)), this, SLOT(showStatusMessage(const QString &,int))); connect(m_settingPage, SIGNAL(showStatusMessage(const QString &,int)), this, SLOT(showStatusMessage(const QString &,int))); connect(m_toolPage, SIGNAL(showStatusMessage(const QString &,int)), this, SLOT(showStatusMessage(const QString &,int))); connect(m_aboutPage, SIGNAL(changePage(int)), this, SLOT(setCurrentPage(int))); connect(m_otpPage, SIGNAL(showHelp(int)), this, SLOT(triggerHelp(int))); connect(m_oathPage, SIGNAL(showHelp(int)), this, SLOT(triggerHelp(int))); connect(m_staticPage, SIGNAL(showHelp(int)), this, SLOT(triggerHelp(int))); connect(m_chalRespPage, SIGNAL(showHelp(int)), this, SLOT(triggerHelp(int))); connect(m_settingPage, SIGNAL(showHelp(int)), this, SLOT(triggerHelp(int))); connect(m_toolPage, SIGNAL(showHelp(int)), this, SLOT(triggerHelp(int))); connect(m_settingPage, SIGNAL(settingsChanged()), m_otpPage, SLOT(loadSettings())); connect(m_settingPage, SIGNAL(settingsChanged()), m_oathPage, SLOT(loadSettings())); connect(m_settingPage, SIGNAL(settingsChanged()), m_chalRespPage, SLOT(loadSettings())); connect(m_settingPage, SIGNAL(settingsChanged()), m_staticPage, SLOT(loadSettings())); connect(m_settingPage, SIGNAL(settingsChanged()), m_toolPage, SLOT(loadSettings())); connect(m_toolPage, SIGNAL(reloadSettings()), m_settingPage, SLOT(reloadSettings())); connect(m_toolPage, SIGNAL(switchPage(int, int, int)), this, SLOT(setCurrentPage(int, int, int))); //Intialize settings m_settingPage->init(); //Start YubiKey finder YubiKeyFinder::getInstance()->start(); // add action for toggling animation animationAction = new QAction(this); animationAction->setText("Device image animated"); animationAction->setCheckable(true); connect(animationAction, SIGNAL(triggered(bool)), this, SLOT(toggleAnimation(bool))); ui->deviceImage->addAction(animationAction); // add action for diagnostics diagnosticsAction = new QAction(this); diagnosticsAction->setText("Show detailed diagnostics"); connect(diagnosticsAction, SIGNAL(triggered()), this, SLOT(triggerDiagnostics())); ui->logoImg->addAction(diagnosticsAction); QSettings settings; if(settings.value(SG_ANIMATIONS_PREFERENCE, true).toBool()) { animationAction->setChecked(true); } else { animationAction->setChecked(false); } } MainWindow::~MainWindow() { if (m_timer != 0) { delete m_timer; } delete m_otpPage; delete m_oathPage; delete m_staticPage; delete m_chalRespPage; delete m_settingPage; delete m_toolPage; delete m_aboutPage; delete m_diagnostics; delete m_help; delete animationAction; delete diagnosticsAction; delete ui; } /* Menu Widget handling */ void MainWindow::createPages() { //Create pages m_otpPage = new OtpPage(this); m_oathPage = new OathPage(this); m_staticPage = new StaticPage(this); m_chalRespPage = new ChalRespPage(this); m_settingPage = new SettingPage(this); m_toolPage = new ToolPage(this); m_aboutPage = new AboutPage(this); m_diagnostics = new Diagnostics(this); m_help = new HelpBox(this); //Add pages to the pages widget ui->pagesWidget->addWidget(m_otpPage); ui->pagesWidget->addWidget(m_oathPage); ui->pagesWidget->addWidget(m_staticPage); ui->pagesWidget->addWidget(m_chalRespPage); ui->pagesWidget->addWidget(m_settingPage); ui->pagesWidget->addWidget(m_toolPage); ui->pagesWidget->addWidget(m_aboutPage); //Map the values of menu buttons with the indexes of the pages widget //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->otpMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->oathHotpMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->staticMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->chalRespMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->settingsMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->toolsMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->aboutMenuBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->otpMenuBtn, Page_Otp); mapper->setMapping(ui->oathHotpMenuBtn, Page_Oath); mapper->setMapping(ui->staticMenuBtn, Page_Static); mapper->setMapping(ui->chalRespMenuBtn, Page_ChalResp); mapper->setMapping(ui->settingsMenuBtn, Page_Settings); mapper->setMapping(ui->toolsMenuBtn, Page_Tools); mapper->setMapping(ui->aboutMenuBtn, Page_About); //Connect the mapper to the pages widget //The mapper will set a value to each button and set that value to //the pages widget //connect(mapper, SIGNAL(mapped(int)), ui->pagesWidget, SLOT(setCurrentIndex(int))); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); //Set the current page m_currentPage = 0; setCurrentPage(Page_About); } void MainWindow::setCurrentPage(int pageIndex, int tab, int slot) { // Page changed... // Clear status message clearStatusMessage(); // Toggle menu buttons QString disabledMenuBtnSS = QString::fromUtf8(SS_MENU_DISABLED); QString checkedMenuBtnSS = QString::fromUtf8(SS_MENU_CHECKED); QString uncheckedMenuBtnSS = QString::fromUtf8(SS_MENU_UNCHECKED); switch(m_currentPage){ case Page_Otp: ui->otpMenuBtn->setStyleSheet(uncheckedMenuBtnSS); break; case Page_Oath: if(m_oathPage->isEnabled()) { ui->oathHotpMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } else { ui->oathHotpMenuBtn->setStyleSheet(disabledMenuBtnSS); } break; case Page_Static: if(m_staticPage->isEnabled()) { ui->staticMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } else { ui->staticMenuBtn->setStyleSheet(disabledMenuBtnSS); } break; case Page_ChalResp: if(m_chalRespPage->isEnabled()) { ui->chalRespMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } else { ui->chalRespMenuBtn->setStyleSheet(disabledMenuBtnSS); } break; case Page_Settings: ui->settingsMenuBtn->setStyleSheet(uncheckedMenuBtnSS); break; case Page_Tools: ui->toolsMenuBtn->setStyleSheet(uncheckedMenuBtnSS); break; case Page_About: ui->aboutMenuBtn->setStyleSheet(uncheckedMenuBtnSS); break; } switch(pageIndex){ case Page_Otp: ui->otpMenuBtn->setStyleSheet(checkedMenuBtnSS); if(tab) m_otpPage->setCurrentPage(tab); if(slot) m_otpPage->setCurrentSlot(slot); break; case Page_Oath: ui->oathHotpMenuBtn->setStyleSheet(checkedMenuBtnSS); if(tab) m_oathPage->setCurrentPage(tab); if(slot) m_oathPage->setCurrentSlot(slot); break; case Page_Static: ui->staticMenuBtn->setStyleSheet(checkedMenuBtnSS); if(tab) m_staticPage->setCurrentPage(tab); if(slot) m_staticPage->setCurrentSlot(slot); break; case Page_ChalResp: ui->chalRespMenuBtn->setStyleSheet(checkedMenuBtnSS); if(tab) m_chalRespPage->setCurrentPage(tab); if(slot) m_chalRespPage->setCurrentSlot(slot); break; case Page_Settings: ui->settingsMenuBtn->setStyleSheet(checkedMenuBtnSS); if(tab) m_settingPage->setCurrentPage(tab); break; case Page_Tools: ui->toolsMenuBtn->setStyleSheet(checkedMenuBtnSS); if(tab) m_toolPage->setCurrentPage(tab); break; case Page_About: ui->aboutMenuBtn->setStyleSheet(checkedMenuBtnSS); break; } m_currentPage = pageIndex; ui->pagesWidget->setCurrentIndex(pageIndex); } /* Device Widget handling */ void MainWindow::resetDeviceInfo() { ui->statusLbl->clear(); ui->versionLbl->setText(tr(NA)); QString blankBtnSS = QString::fromUtf8(SS_BLANK_BTN); ui->serialNoDecLbl->setText(tr(NA)); ui->serialNoHexLbl->setText(tr(NA)); ui->serialNoModhexLbl->setText(tr(NA)); ui->serialNoDecCopyBtn->setStyleSheet(blankBtnSS); ui->serialNoHexCopyBtn->setStyleSheet(blankBtnSS); ui->serialNoModhexCopyBtn->setStyleSheet(blankBtnSS); ui->otpSupportLbl->setPixmap(QPixmap()); ui->otpSupportLbl->setText(tr(NA)); ui->multiConfigSupportLbl->setPixmap(QPixmap()); ui->multiConfigSupportLbl->setText(tr(NA)); ui->oathHotpSupportLbl->setPixmap(QPixmap()); ui->oathHotpSupportLbl->setText(tr(NA)); ui->staticPwdSupportLbl->setPixmap(QPixmap()); ui->staticPwdSupportLbl->setText(tr(NA)); ui->scanCodeSupportLbl->setPixmap(QPixmap()); ui->scanCodeSupportLbl->setText(tr(NA)); ui->chalRespSupportLbl->setPixmap(QPixmap()); ui->chalRespSupportLbl->setText(tr(NA)); ui->updatableSupportLbl->setPixmap(QPixmap()); ui->updatableSupportLbl->setText(tr(NA)); ui->ndefSupportLbl->setPixmap(QPixmap()); ui->ndefSupportLbl->setText(tr(NA)); ui->u2fSupportLbl->setPixmap(QPixmap()); ui->u2fSupportLbl->setText(tr(NA)); } void MainWindow::keyFound(bool found, bool* featuresMatrix, int error) { QString disabledMenuBtnSS = QString::fromUtf8(SS_MENU_DISABLED); QString checkedMenuBtnSS = QString::fromUtf8(SS_MENU_CHECKED); QString uncheckedMenuBtnSS = QString::fromUtf8(SS_MENU_UNCHECKED); QString copyBtnSS = QString::fromUtf8(SS_COPY_BTN); QString blankBtnSS = QString::fromUtf8(SS_BLANK_BTN); resetDeviceInfo(); if(ui->deviceImage->movie()) { delete(ui->deviceImage->movie()); ui->deviceImage->setMovie(NULL); } if(found) { YubiKeyFinder *finder = YubiKeyFinder::getInstance(); int touchLevel = finder->touchLevel(); qDebug() << "touchLevel is " << touchLevel; if(touchLevel & CONFIG1_VALID && touchLevel & CONFIG2_VALID) { ui->programLbl->setText(tr("Slot 1 and 2 configured")); } else if(touchLevel & CONFIG1_VALID) { ui->programLbl->setText(tr("Slot 1 configured")); } else if(touchLevel & CONFIG2_VALID) { ui->programLbl->setText(tr("Slot 2 configured")); } else { ui->programLbl->setText(tr("Not configured")); } unsigned int version = finder->version(); if(error == ERR_UNKNOWN_FIRMWARE) { ui->statusLbl->setStyleSheet(QString::fromUtf8(SS_YKSTATUS_ERROR)); ui->statusLbl->setText(tr(UNKNOWN_FIRMWARE)); } else { ui->statusLbl->setStyleSheet(QString::fromUtf8(SS_YKSTATUS_SUCCESS)); ui->statusLbl->setText(tr(KEY_FOUND)); } ui->versionLbl->setText(finder->versionStr()); qDebug() << "version is" << finder->versionStr(); QPixmap pixmap; QMovie *movie = new QMovie(); if(version == 0) { pixmap.load(":/res/images/blank.png"); } else if(version < YK_VERSION(2,0,0)) { pixmap.load(":/res/images/v1-3-not-animated.png"); } else if(version < YK_VERSION(2,1,4)) { movie->setFileName(":/res/images/V2-0-2-1-animated.mng"); } else if(version < YK_VERSION(2,2,0)) { // NEO Beta pixmap.load(":/res/images/neo_transparent.png"); } else if(version < YK_VERSION(2,3,0)){ movie->setFileName(":/res/images/v2-2-animated.mng"); } else if(version < YK_VERSION(3,0,0)){ movie->setFileName(":/res/images/v2-3-animated.mng"); } else if(version < YK_VERSION(3,3,0)){ pixmap.load(":/res/images/neo_production.png"); } else if(version < YK_VERSION(4,0,0)) { movie->setFileName(":/res/images/neo_production_33.mng"); } else if(version < YK_VERSION(4,1,0)) { movie->setFileName(":/res/images/plus.mng"); } else if(version < YK_VERSION(4,3,0)) { movie->setFileName(":/res/images/edge.mng"); } else { pixmap.load(":/res/images/blank.png"); } if(pixmap.isNull()) { ui->deviceImage->setMovie(movie); movie->start(); if(!animationAction->isChecked()) { movie->stop(); } } else { delete movie; ui->deviceImage->setPixmap(pixmap); } unsigned int serial = 0; if(featuresMatrix[YubiKeyFinder::Feature_SerialNumber]) { serial = YubiKeyFinder::getInstance()->serial(); } if(serial != 0) { ui->serialNoDecLbl->setText(QString::number(serial)); //Convert serial number in hex and modhex unsigned char buf[16]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; QString tmp = QString::number(serial, 16); size_t len = tmp.length(); if(len % 2 != 0) { len++; } YubiKeyUtil::qstrClean(&tmp, (size_t)len, true); YubiKeyUtil::qstrHexDecode(buf, &bufLen, tmp); QString hex = YubiKeyUtil::qstrHexEncode(buf, bufLen); QString modhex = YubiKeyUtil::qstrModhexEncode(buf, bufLen); ui->serialNoHexLbl->setText(hex); ui->serialNoModhexLbl->setText(modhex); ui->serialNoDecCopyBtn->setStyleSheet(copyBtnSS); ui->serialNoHexCopyBtn->setStyleSheet(copyBtnSS); ui->serialNoModhexCopyBtn->setStyleSheet(copyBtnSS); } else { ui->serialNoDecLbl->setText(tr(NA)); ui->serialNoHexLbl->setText(tr(NA)); ui->serialNoModhexLbl->setText(tr(NA)); ui->serialNoDecCopyBtn->setStyleSheet(blankBtnSS); ui->serialNoHexCopyBtn->setStyleSheet(blankBtnSS); ui->serialNoModhexCopyBtn->setStyleSheet(blankBtnSS); } ui->otpSupportLbl->setPixmap(TICKMAP); if(featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) { ui->multiConfigSupportLbl->setPixmap(TICKMAP); } else { ui->multiConfigSupportLbl->setPixmap(CROSSMAP); } if(featuresMatrix[YubiKeyFinder::Feature_OathHotp]) { ui->oathHotpSupportLbl->setPixmap(TICKMAP); if(m_currentPage == Page_Oath) { ui->oathHotpMenuBtn->setStyleSheet(checkedMenuBtnSS); } else { ui->oathHotpMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } ui->oathHotpMenuBtn->setEnabled(true); } else { ui->oathHotpSupportLbl->setPixmap(CROSSMAP); ui->oathHotpMenuBtn->setStyleSheet(disabledMenuBtnSS); ui->oathHotpMenuBtn->setEnabled(false); } if(featuresMatrix[YubiKeyFinder::Feature_StaticPassword]) { ui->staticPwdSupportLbl->setPixmap(TICKMAP); if(m_currentPage == Page_Static) { ui->staticMenuBtn->setStyleSheet(checkedMenuBtnSS); } else { ui->staticMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } ui->staticMenuBtn->setEnabled(true); } else { ui->staticPwdSupportLbl->setPixmap(CROSSMAP); ui->staticMenuBtn->setStyleSheet(disabledMenuBtnSS); ui->staticMenuBtn->setEnabled(false); } if(featuresMatrix[YubiKeyFinder::Feature_ScanCodeMode]) { ui->scanCodeSupportLbl->setPixmap(TICKMAP); } else { ui->scanCodeSupportLbl->setPixmap(CROSSMAP); } if(featuresMatrix[YubiKeyFinder::Feature_ChallengeResponse]) { ui->chalRespSupportLbl->setPixmap(TICKMAP); if(m_currentPage == Page_ChalResp) { ui->chalRespMenuBtn->setStyleSheet(checkedMenuBtnSS); } else { ui->chalRespMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } ui->chalRespMenuBtn->setEnabled(true); } else { ui->chalRespSupportLbl->setPixmap(CROSSMAP); ui->chalRespMenuBtn->setStyleSheet(disabledMenuBtnSS); ui->chalRespMenuBtn->setEnabled(false); } if(featuresMatrix[YubiKeyFinder::Feature_Updatable]) { ui->updatableSupportLbl->setPixmap(TICKMAP); } else { ui->updatableSupportLbl->setPixmap(CROSSMAP); } if(featuresMatrix[YubiKeyFinder::Feature_Ndef]) { ui->ndefSupportLbl->setPixmap(TICKMAP); } else { ui->ndefSupportLbl->setPixmap(CROSSMAP); } if(featuresMatrix[YubiKeyFinder::Feature_U2F]) { ui->u2fSupportLbl->setPixmap(TICKMAP); } else { ui->u2fSupportLbl->setPixmap(CROSSMAP); } } else { ui->programLbl->clear(); if(ui->deviceImage->pixmap()) { ui->deviceImage->setPixmap(QPixmap()); } ui->deviceImage->clear(); if(error == ERR_NOKEY) { ui->statusLbl->setText(tr(NO_KEY_FOUND)); } else if(error == ERR_MORETHANONE) { ui->statusLbl->setText(tr(MORE_THAN_ONE)); } else { ui->statusLbl->setText(tr(OTHER_ERROR)); } ui->statusLbl->setStyleSheet(QString::fromUtf8(SS_YKSTATUS_ERROR)); if(m_currentPage == Page_Oath) { ui->oathHotpMenuBtn->setStyleSheet(checkedMenuBtnSS); } else { ui->oathHotpMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } ui->oathHotpMenuBtn->setEnabled(true); if(m_currentPage == Page_Static) { ui->staticMenuBtn->setStyleSheet(checkedMenuBtnSS); } else { ui->staticMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } ui->staticMenuBtn->setEnabled(true); if(m_currentPage == Page_ChalResp) { ui->chalRespMenuBtn->setStyleSheet(checkedMenuBtnSS); } else { ui->chalRespMenuBtn->setStyleSheet(uncheckedMenuBtnSS); } ui->chalRespMenuBtn->setEnabled(true); } } /* Status Widget handling */ void MainWindow::showStatusMessage(const QString &text, int status) { qDebug() << "status: " << status << "\n"; if(status == -1) { clearStatusMessage(); } QString statuSS; switch(status) { case 0: ui->statusIconLbl->setPixmap(TICKMAP); statuSS = QString::fromUtf8(SS_STATUS_SUCCESS); break; case 1: ui->statusIconLbl->setPixmap(CROSSMAP); statuSS = QString::fromUtf8(SS_STATUS_ERROR); break; } ui->statusMsgLbl->setStyleSheet(statuSS); ui->statusMsgLbl->setText(text); if (m_timer != 0) { delete m_timer; m_timer = 0; } m_timer = new QTimer(this); connect(m_timer, SIGNAL(timeout()), this, SLOT(clearStatusMessage())); m_timer->start(TIMEOUT_STATUS); } void MainWindow::clearStatusMessage() { if (m_timer != 0) { delete m_timer; m_timer = 0; } ui->statusIconLbl->clear(); ui->statusMsgLbl->clear(); } void MainWindow::copyToClipboard(const QString &str) { QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(str); showStatusMessage(tr(VALUE_COPIED), 0); } void MainWindow::on_serialNoDecCopyBtn_clicked() { copyToClipboard(ui->serialNoDecLbl->text()); } void MainWindow::on_serialNoHexCopyBtn_clicked() { copyToClipboard(ui->serialNoHexLbl->text()); } void MainWindow::on_serialNoModhexCopyBtn_clicked() { copyToClipboard(ui->serialNoModhexLbl->text()); } void MainWindow::toggleAnimation(bool checked) { QSettings settings; settings.setValue(SG_ANIMATIONS_PREFERENCE, checked); animationAction->setChecked(checked); if(ui->deviceImage->movie()) { if(checked) { ui->deviceImage->movie()->start(); } else { ui->deviceImage->movie()->stop(); } } } void MainWindow::triggerDiagnostics() { m_diagnostics->show(); } void MainWindow::triggerHelp(int index) { m_help->setHelpIndex((HelpBox::Help)index); m_help->show(); } void MainWindow::aboutToQuit() { YubiKeyLogger::closeLogFile(); } yubikey-personalization-gui-3.1.24/src/ui/confirmbox.ui0000664000175000017500000001167612642452141021660 0ustar klasklas ConfirmBox Qt::ApplicationModal 0 0 530 190 0 0 530 190 530 190 Dialog font: 11px "Verdana"; color: rgb(0, 0, 0); QLayout::SetMinimumSize font-weight: normal; false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 0 QLayout::SetMinimumSize 0 0 430 0 430 500 Qt::LeftToRight true Qt::PlainText false Qt::AlignJustify|Qt::AlignTop true 0 font-weight: normal; Don't show this message again 0 0 Qt::Horizontal QDialogButtonBox::No|QDialogButtonBox::Yes true dontaskCheck buttonBox buttonBox accepted() ConfirmBox accept() 248 254 157 274 buttonBox rejected() ConfirmBox reject() 316 260 286 274 yubikey-personalization-gui-3.1.24/src/ui/aboutpage.h0000664000175000017500000000344112642452141021262 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #ifndef ABOUTPAGE_H #define ABOUTPAGE_H #include namespace Ui { class AboutPage; } class AboutPage : public QWidget { Q_OBJECT public: explicit AboutPage(QWidget *parent = 0); ~AboutPage(); private: Ui::AboutPage *ui; private slots: void connectButtons(); void keyFound(bool found, bool* featuresMatrix); void btn_pressed(int pageIndex); void on_supportBtn_clicked() ; signals: void changePage(int pageIndex); }; #endif // ABOUTPAGE_H yubikey-personalization-gui-3.1.24/src/ui/otppage.h0000664000175000017500000000774412642452141020764 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef OTPPAGE_H #define OTPPAGE_H #include #include #include "yubikeyconfig.h" namespace Ui { class OtpPage; } class OtpPage : public QStackedWidget { Q_OBJECT public: explicit OtpPage(QWidget *parent = 0); ~OtpPage(); enum Page { Page_Base, Page_Quick, Page_Advanced, Page_Upload }; private: Ui::OtpPage *ui; int m_currentPage; int m_customerPrefix; QString m_pubIdPrefix; enum State { State_Initial, State_Programming, State_Programming_Multiple, State_Programming_Multiple_Auto }; State m_state; YubiKeyConfig *m_ykConfig; unsigned int m_keysProgrammedCtr; bool m_ready; // remember the last state of the key. bool m_keyPresent; QString m_uploadUrl; QTemporaryFile m_tempFile; public slots: void loadSettings(); void setCurrentPage(int pageIndex); void setCurrentSlot(int slot); private slots: void connectPages(); void connectHelpButtons(); void keyFound(bool found, bool* featuresMatrix); void clearState(); // Quick Page void resetQuickPage(); void on_quickResetBtn_clicked(); void on_quickHideParams_clicked(bool checked); void on_quickPubIdTxt_editingFinished(); void on_quickPvtIdTxt_editingFinished(); void on_quickSecretKeyTxt_editingFinished(); bool validateQuickSettings(); void writeQuickConfig(); void quickConfigWritten(bool written, const QString &msg); void uploadQuickConfig(); // Advanced Page void resetAdvPage(); void freezeAdvPage(bool freeze); void on_advProgramMulKeysBox_clicked(bool checked); void set_advPubId_default(); void on_advPubIdCheck_stateChanged(int state); void on_advPubIdTxt_editingFinished(); void on_advPubIdGenerateBtn_clicked(); void on_advPubIdLenBox_valueChanged(int value); void on_advPvtIdCheck_stateChanged(int state); void on_advPvtIdTxt_editingFinished(); void on_advPvtIdGenerateBtn_clicked(); void on_advSecretKeyTxt_editingFinished(); void on_advSecretKeyGenerateBtn_clicked(); void on_advWriteConfigBtn_clicked(); void on_advExportConfigBtn_clicked(); void on_advStopBtn_clicked(); void changeAdvConfigParams(); void stopAdvConfigWritting(); bool validateAdvSettings(); void writeAdvConfig(int mode); void advConfigWritten(bool written, const QString &msg); void advConfigExported(bool written, const QString &msg); void advUpdateResults(bool written, const QString &msg); signals: void showStatusMessage(const QString &text, int status = 0); void showHelp(int helpIndex); }; #endif // OTPPAGE_H yubikey-personalization-gui-3.1.24/src/ui/chalresppage.h0000664000175000017500000001014712642452141021752 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef CHALRESPPAGE_H #define CHALRESPPAGE_H #include #include "yubikeyconfig.h" namespace Ui { class ChalRespPage; } class ChalRespPage : public QStackedWidget { Q_OBJECT public: explicit ChalRespPage(QWidget *parent = 0); ~ChalRespPage(); enum Page { Page_Base, Page_Quick, //Yubico OTP Page_Advanced //HMAC-SHA1 }; public slots: void loadSettings(); void setCurrentPage(int pageIndex); void setCurrentSlot(int slot); private: Ui::ChalRespPage *ui; int m_currentPage; enum State { State_Initial, State_Programming, State_Programming_Multiple, State_Programming_Multiple_Auto }; State m_state; YubiKeyConfig *m_ykConfig; unsigned int m_keysProgrammedCtr; bool m_ready; bool m_keyPresent; private slots: void connectPages(); void connectHelpButtons(); void keyFound(bool found, bool* featuresMatrix); void clearState(); // Quick Page void resetQuickPage(); void freezeQuickPage(bool freeze); void on_quickProgramMulKeysBox_clicked(bool checked); void on_quickConfigParamsCombo_currentIndexChanged(int index); void on_quickPvtIdCheck_stateChanged(int state); void on_quickPvtIdTxt_editingFinished(); void on_quickPvtIdGenerateBtn_clicked(); void on_quickSecretKeyTxt_editingFinished(); void on_quickSecretKeyGenerateBtn_clicked(); void on_quickWriteConfigBtn_clicked(); void on_quickExportConfigBtn_clicked(); void on_quickStopBtn_clicked(); void changeQuickConfigParams(); void stopQuickConfigWritting(); bool validateQuickSettings(); void writeQuickConfig(int mode); void quickConfigWritten(bool written, const QString &msg); void quickConfigExported(bool written, const QString &msg); void quickUpdateResults(bool written, const QString &msg); // Advanced Page void resetAdvPage(); void freezeAdvPage(bool freeze); void on_advProgramMulKeysBox_clicked(bool checked); void on_advConfigParamsCombo_currentIndexChanged(int index); void on_advSecretKeyTxt_editingFinished(); void on_advSecretKeyGenerateBtn_clicked(); void on_advWriteConfigBtn_clicked(); void on_advExportConfigBtn_clicked(); void on_advStopBtn_clicked(); void changeAdvConfigParams(); void stopAdvConfigWritting(); bool validateAdvSettings(); void writeAdvConfig(int mode); void advConfigWritten(bool written, const QString &msg); void advConfigExported(bool written, const QString &msg); void advUpdateResults(bool written, const QString &msg); void requireInput_clicked(bool checked); void hmac_lt64_clicked(); signals: void showStatusMessage(const QString &text, int status = 0); void showHelp(int helpIndex); }; #endif // CHALRESPPAGE_H yubikey-personalization-gui-3.1.24/src/ui/chalresppage.ui0000664000175000017500000014773312642452141022154 0ustar klasklas ChalRespPage 0 0 730 650 0 0 730 650 StackedWidget font: 11px "Verdana"; color: rgb(0, 0, 0); 2 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Challenge-Response mode Qt::AlignCenter 10 50 710 171 border-color: rgb(0, 0, 0); Qt::AlignCenter 20 20 141 25 0 0 font: 12px; font-weight: bold; Yubico OTP false false false 20 100 141 25 font: 12px; font-weight: bold; HMAC-SHA1 false false false 20 45 671 20 Allows you to program one or more YubiKeys in "Yubico OTP" Challenge-Response mode Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 120 671 30 Allows you to program one or more YubiKeys in "HMAC-SHA1" Challenge-Response mode Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 170 24 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 170 104 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Challenge-Response mode - Yubico OTP Qt::AlignCenter 10 132 350 107 font-weight: bold; Program Multiple YubiKeys true false 10 25 331 17 font-weight: normal; Automatically program YubiKeys when inserted 10 52 191 20 font-weight:normal; Parameter Generation Scheme Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 75 331 22 0 0 font-weight: normal; Increment Identities; Randomize Secret Randomize all parameters 325 52 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 50 711 72 font-weight: bold; Configuration Slot 10 25 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 true false 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 249 711 107 font-weight: bold; Yubico OTP Parameters 685 77 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 240 75 330 20 0 0 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 47 580 73 100 24 font: 12px; font-weight: bold; Generate false false false 10 75 221 20 font-weight:normal; Secret Key (16 bytes Hex) 10 50 221 17 font-weight: normal; Private Identity (6 bytes Hex) 240 50 330 20 0 0 font-weight: normal; hh hh hh hh hh hh; 00 00 00 00 00 00 17 17 580 48 100 24 font: 12px; font-weight: bold; Generate false false false 685 52 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 25 221 17 font-weight: normal; Require user input (button press) 685 27 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 366 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false false 200 45 85 25 font: 12px; font-weight: bold; Stop false false false 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot 400 45 85 25 font: 12px; font-weight: bold; Back false false false false 300 45 85 25 font: 12px; font-weight: bold; Reset false false false 580 45 100 25 font: 12px; font-weight: bold; Export false false false 10 456 711 130 font-weight: bold; Results 12 20 688 100 font: 11px "Verdana"; color: rgb(0, 0, 0); Qt::ScrollBarAlwaysOn true false Qt::SolidLine true 0 3 50 false 20 # Status Timestamp 370 132 350 117 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Program in Challenge-Response mode - HMAC-SHA1 Qt::AlignCenter 10 50 711 72 font-weight: bold; Configuration Slot 10 25 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be programmed 10 45 151 19 font-weight: normal; Configuration Slot 1 true false 240 45 151 19 font-weight: normal; Configuration Slot 2 685 45 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 366 711 80 font-weight: bold; Actions 10 45 175 25 font: 12px; font-weight: bold; Write Configuration false false false false 200 45 85 25 font: 12px; font-weight: bold; Stop false false false 10 25 691 16 font-weight: normal; color: rgb(118, 116, 108) Press Write Configuration button to program your YubiKey's selected configuration slot 400 45 85 25 font: 12px; font-weight: bold; Back false false false false 300 45 85 25 font: 12px; font-weight: bold; Reset false false false 580 45 100 25 font: 12px; font-weight: bold; Export false false false 10 132 350 107 font-weight: bold; Program Multiple YubiKeys true false 10 25 331 17 font-weight: normal; Automatically program YubiKeys when inserted 10 52 191 20 font-weight:normal; Parameter Generation Scheme Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 75 331 22 0 0 font-weight: normal; Randomize Secret Same Secret for all Keys 10 249 711 107 font-weight: bold; HMAC-SHA1 Parameters false 685 25 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 25 221 17 font-weight: normal; Require user input (button press) 240 50 111 17 font-weight: normal; Variable input true true 370 50 141 17 font-weight: normal; Fixed 64 byte input true false 10 50 131 20 font-weight:normal; HMAC-SHA1 Mode 10 75 221 20 font-weight:normal; Secret Key (20 bytes Hex) 240 75 330 20 0 0 font-weight: normal; hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 59 580 73 100 24 font: 12px; font-weight: bold; Generate false false false 685 77 16 16 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false background-image: url(:/res/images/question.png); color: lightgray; border-radius: 10px; false false 10 456 711 130 font-weight: bold; Results 12 20 688 100 font: 11px "Verdana"; color: rgb(0, 0, 0); Qt::ScrollBarAlwaysOn true false Qt::SolidLine true 0 3 50 false 20 # Status Timestamp 370 132 350 117 YubiAccBox QWidget
        yubiaccbox.h
        1
        quickBtn advBtn quickHelpBtn advHelpBtn quickConfigSlot1Radio quickConfigSlot2Radio quickProgramMulKeysBox quickAutoProgramKeysCheck quickConfigParamsCombo quickRequireUserInputCheck quickPvtIdCheck quickPvtIdTxt quickPvtIdGenerateBtn quickSecretKeyTxt quickSecretKeyGenerateBtn quickWriteConfigBtn quickStopBtn quickResetBtn quickBackBtn quickResultsWidget quickConfigHelpBtn quickChalRespOptionsHelpBtn quickPvtIdHelpBtn quickSecretKeyHelpBtn advConfigSlot1Radio advConfigSlot2Radio advProgramMulKeysBox advAutoProgramKeysCheck advConfigParamsCombo advRequireUserInputCheck advHmacVarInputRadio advHmacFixedInputRadio advSecretKeyTxt advSecretKeyGenerateBtn advWriteConfigBtn advStopBtn advResetBtn advBackBtn advResultsWidget advConfigHelpBtn advChalRespOptionsHelpBtn advSecretKeyHelpBtn
        yubikey-personalization-gui-3.1.24/src/ui/aboutpage.ui0000664000175000017500000003575112642452141021461 0ustar klasklas AboutPage 0 0 730 650 0 0 730 650 Form font: 11px "Verdana"; 30 80 671 450 background-color: rgb(255, 255, 255); border-color: rgb(0, 0, 0); border-radius: 5px; QFrame::StyledPanel QFrame::Sunken 0 71 121 168 23 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false font: 12px "Verdana"; text-decoration: underline; text-align: left; color: rgb(5, 67, 168); Yubico OTP Mode false false false true 70 211 168 23 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false font: 12px "Verdana"; text-decoration: underline; text-align: left; color: rgb(5, 67, 168); Challenge-Response Mode false false true 70 181 168 23 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false font: 12px "Verdana"; text-decoration: underline; text-align: left; color: rgb(5, 67, 168); Static Password Mode false false true 71 151 168 23 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false font: 12px "Verdana"; text-decoration: underline; text-align: left; color: rgb(5, 67, 168); OATH-HOTP Mode false false true 410 355 240 20 Application Version: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 420 631 20 Qt::RichText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0 73 671 2 background-color: rgb(140, 192, 65); 1 Qt::Horizontal 143 25 384 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); The Swiss Army Knife for the YubiKey Qt::AlignCenter 0 410 671 1 background-color: rgb(140, 192, 65); 1 Qt::Horizontal 20 96 271 20 font: 12px "Verdana"; font-weight: bold; color: rgb(118, 116, 108); Personalize your YubiKey in: 33 121 24 24 :/res/images/right.png Qt::AlignCenter 33 151 24 24 :/res/images/right.png Qt::AlignCenter 33 181 24 24 :/res/images/right.png Qt::AlignCenter 33 211 24 24 :/res/images/right.png Qt::AlignCenter 20 290 191 20 For help and discussion, head to 20 310 131 20 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false font: 12px "Verdana"; text-decoration: underline; color: rgb(5, 67, 168); http://yubi.co/forum false false true 33 241 24 24 :/res/images/right.png Qt::AlignCenter 70 241 168 23 0 0 PointingHandCursor Qt::DefaultContextMenu Qt::LeftToRight false font: 12px "Verdana"; text-decoration: underline; text-align: left; color: rgb(5, 67, 168); Update Settings false false true 410 380 240 20 Library Version: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter otpBtn oathBtn staticBtn chalRespBtn settingsBtn yubikey-personalization-gui-3.1.24/src/ui/staticpage.h0000664000175000017500000001053412642452141021440 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #ifndef STATICPAGE_H #define STATICPAGE_H #include #include "yubikeyconfig.h" #include "scanedit.h" namespace Ui { class StaticPage; } class StaticPage : public QStackedWidget { Q_OBJECT public: explicit StaticPage(QWidget *parent = 0); ~StaticPage(); enum Page { Page_Base, Page_Quick, Page_Advanced, Page_Upload }; private: Ui::StaticPage *ui; int m_currentPage; enum State { State_Initial, State_Programming, State_Programming_Multiple, State_Programming_Multiple_Auto }; State m_state; YubiKeyConfig *m_ykConfig; unsigned int m_keysProgrammedCtr; bool m_ready; bool m_keyPresent; ScanEdit *scanedit; public slots: void loadSettings(); void setCurrentPage(int pageIndex); void setCurrentSlot(int slot); private slots: void connectPages(); void connectHelpButtons(); void keyFound(bool found, bool* featuresMatrix); void clearState(); // Quick Page void resetQuickPage(); void freezeQuickPage(bool freeze); void on_quickHideParams_clicked(bool checked); void on_quickStaticTxt_textEdited(const QString &txt); void on_quickStaticTxt_returnPressed(); void on_quickInsertTabBtn_clicked(); void on_quickClearBtn_clicked(); void on_quickWriteConfigBtn_clicked(); void on_quickStopBtn_clicked(); void changeQuickConfigParams(); void stopQuickConfigWritting(); bool validateQuickSettings(); void writeQuickConfig(); void quickConfigWritten(bool written, const QString &msg); void quickUpdateResults(bool written, const QString &msg); // Advanced Page void resetAdvPage(); void freezeAdvPage(bool freeze); void on_advProgramMulKeysBox_clicked(bool checked); void on_advConfigParamsCombo_currentIndexChanged(int index); void on_advStaticLen16Radio_clicked(bool checked); void on_advStaticLen32Radio_clicked(bool checked); void on_advStaticLenBox_valueChanged(int value); void enablePubId(bool enable); void on_advPubIdTxt_editingFinished(); void on_advPubIdGenerateBtn_clicked(); void on_advPvtIdTxt_editingFinished(); void on_advPvtIdGenerateBtn_clicked(); void on_advSecretKeyTxt_editingFinished(); void on_advSecretKeyGenerateBtn_clicked(); void on_advStrongPw1Check_stateChanged(int state); void on_advStrongPw2Check_stateChanged(int state); void on_advStrongPw3Check_stateChanged(int state); void on_advWriteConfigBtn_clicked(); void on_advStopBtn_clicked(); void changeAdvConfigParams(); void stopAdvConfigWritting(); bool validateAdvSettings(); void writeAdvConfig(); void advConfigWritten(bool written, const QString &msg); void advUpdateResults(bool written, const QString &msg); void on_quickScanCodesTxt_textEdited(const QString &text); void on_quickKeymapCmb_currentIndexChanged(int index); signals: void showStatusMessage(const QString &text, int status = 0); void showHelp(int helpIndex); }; #endif // STATICPAGE_H yubikey-personalization-gui-3.1.24/src/ui/confirmbox.cpp0000664000175000017500000000623612642452141022021 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include "confirmbox.h" #include "ui_confirmbox.h" #include #include #include "common.h" ConfirmBox::ConfirmBox(QWidget *parent) : QDialog(parent), ui(new Ui::ConfirmBox) { ui->setupUi(this); } ConfirmBox::~ConfirmBox() { delete ui; } void ConfirmBox::setConfirmIndex(Confirm confirmIndex) { QString title; QString confirmMsg; switch(confirmIndex) { case Confirm_ConfigurationSlot: title = tr(OVERWRITE_CONF_SLOT1); confirmMsg = tr(WARN_OVERWRITE_CONF_SLOT1); break; case Confirm_PublicID: title = tr(DIFF_PUBLIC_ID_LEN); confirmMsg = tr(WARN_DIFF_PUBLIC_ID_LEN); break; case Confirm_ConfigurationProtection: title = tr(ENABLE_CONF_PROTECTION); confirmMsg = tr(WARN_ENABLE_CONF_PROTECTION); break; case Confirm_NdefWithoutHttp: title = tr(NDEF_WITHOUT_HTTP); confirmMsg = tr(WARN_NDEF_WITHOUT_HTTP); break; default: confirmMsg = tr(""); } m_confirmIndex = confirmIndex; this->setWindowTitle(tr("Confirm: %1").arg(title)); QPixmap question(QMessageBox::standardIcon(QMessageBox::Question)); ui->iconLbl->setPixmap(question); ui->msgLbl->setText(confirmMsg); } void ConfirmBox::on_dontaskCheck_stateChanged(int state) { bool checked = (state != 0); QSettings settings; switch(m_confirmIndex) { case Confirm_ConfigurationSlot: settings.setValue(SG_OVERWRITE_CONF_SLOT1, checked); break; case Confirm_PublicID: settings.setValue(SG_DIFF_PUBLIC_ID_LEN, checked); break; case Confirm_ConfigurationProtection: settings.setValue(SG_ENABLE_CONF_PROTECTION, checked); break; case Confirm_NdefWithoutHttp: settings.setValue(SG_NDEF_WITHOUT_HTTP, checked); break; } } yubikey-personalization-gui-3.1.24/src/ui/staticpage.cpp0000664000175000017500000010377312642452141022003 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "staticpage.h" #include "yubikeyfinder.h" #include "yubikeyutil.h" #include "yubikeywriter.h" #include "ui_staticpage.h" #include "ui/helpbox.h" #include "ui/confirmbox.h" #include #include #include #include #include #include #include #include #include "us-scanedit.h" #include "de-scanedit.h" #include "common.h" StaticPage::StaticPage(QWidget *parent) : QStackedWidget(parent), ui(new Ui::StaticPage) { ui->setupUi(this); m_ykConfig = 0; m_keyPresent = false; clearState(); //Connect pages connectPages(); //Connect help buttons connectHelpButtons(); //Connect other signals and slots connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); connect(ui->quickResetBtn, SIGNAL(clicked()), this, SLOT(resetQuickPage())); connect(ui->advResetBtn, SIGNAL(clicked()), this, SLOT(resetAdvPage())); ui->quickResultsWidget->resizeColumnsToContents(); ui->advResultsWidget->resizeColumnsToContents(); QRegExp rx("^[a-f0-9]{0,72}$"); ui->quickScanCodesTxt->setValidator(new QRegExpValidator(rx, this)); scanedit = NULL; } StaticPage::~StaticPage() { if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } delete ui; if(scanedit) { delete scanedit; } } /* Common */ void StaticPage::connectPages() { //Map the values of the navigation buttons with the indexes of //the stacked widget //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //connect(ui->quickUploadBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickBtn, Page_Quick); mapper->setMapping(ui->quickBackBtn, Page_Base); //mapper->setMapping(ui->quickUploadBtn, Page_Upload); mapper->setMapping(ui->advBtn, Page_Advanced); mapper->setMapping(ui->advBackBtn, Page_Base); //Connect the mapper to the widget //The mapper will set a value to each button and //set that value to the widget //connect(pageMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentIndex(int))); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); //Set the current page m_currentPage = 0; setCurrentIndex(Page_Base); } void StaticPage::setCurrentPage(int pageIndex) { //Page changed... m_currentPage = pageIndex; switch(pageIndex){ case Page_Quick: resetQuickPage(); break; case Page_Advanced: resetAdvPage(); break; } setCurrentIndex(pageIndex); //Clear state m_keysProgrammedCtr = 0; clearState(); } void StaticPage::connectHelpButtons() { //Map the values of the help buttons //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickStaticScanCodeHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advParamGenSchemeHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advPubIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advPvtIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->quickStaticScanCodeHelpBtn, HelpBox::Help_StaticScanCode); mapper->setMapping(ui->advConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->advParamGenSchemeHelpBtn, HelpBox::Help_ParameterGeneration); mapper->setMapping(ui->advPubIdHelpBtn, HelpBox::Help_PublicID); mapper->setMapping(ui->advPvtIdHelpBtn, HelpBox::Help_PrivateID); mapper->setMapping(ui->advSecretKeyHelpBtn, HelpBox::Help_SecretKey); //Connect the mapper connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int))); connect(ui->quickConfigProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); connect(ui->advConfigProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); } void StaticPage::loadSettings() { QSettings settings; ui->advStrongPw1Check->setChecked(settings.value(SG_STRONG_PW1).toBool()); ui->advStrongPw2Check->setChecked(settings.value(SG_STRONG_PW2).toBool()); ui->advStrongPw3Check->setChecked(settings.value(SG_STRONG_PW3).toBool()); } void StaticPage::keyFound(bool found, bool* featuresMatrix) { if(found) { if(m_state == State_Initial) { ui->quickWriteConfigBtn->setEnabled(true); ui->advWriteConfigBtn->setEnabled(true); if(!featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) { ui->quickConfigSlot2Radio->setEnabled(false); ui->advConfigSlot2Radio->setEnabled(false); } else { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); } if(!featuresMatrix[YubiKeyFinder::Feature_ShortTicket]) { ui->advStaticLen16Radio->setEnabled(false); ui->advStaticLen32Radio->setChecked(true); } if(!featuresMatrix[YubiKeyFinder::Feature_StrongPwd]) { ui->advStrongPw1Check->setEnabled(false); ui->advStrongPw2Check->setEnabled(false); ui->advStrongPw3Check->setEnabled(false); } if(!featuresMatrix[YubiKeyFinder::Feature_ScanCodeMode]) { ui->quickBtn->setEnabled(false); ui->quickConfigBox->setEnabled(false); ui->quickProgramMulKeysBox->setEnabled(false); ui->quickConfigProtectionBox->setEnabled(false); ui->quickKeyParamsBox->setEnabled(false); ui->quickWriteConfigBtn->setEnabled(false); } if(!featuresMatrix[YubiKeyFinder::Feature_StaticPassword]) { this->setEnabled(false); } } else if(m_state >= State_Programming_Multiple && m_keyPresent == false) { if(this->currentIndex() == Page_Quick) { if(m_state == State_Programming_Multiple) { ui->quickWriteConfigBtn->setEnabled(true); } else { writeQuickConfig(); } } else { if(m_state == State_Programming_Multiple) { ui->advWriteConfigBtn->setEnabled(true); } else { writeAdvConfig(); } } } m_keyPresent = true; } else { ui->quickBtn->setEnabled(true); ui->quickWriteConfigBtn->setEnabled(false); ui->advWriteConfigBtn->setEnabled(false); m_keyPresent = false; if(m_state == State_Initial) { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); ui->advStaticLen16Radio->setEnabled(true); ui->advStrongPw1Check->setEnabled(true); ui->advStrongPw2Check->setEnabled(true); ui->advStrongPw3Check->setEnabled(true); ui->quickConfigBox->setEnabled(true); ui->quickProgramMulKeysBox->setEnabled(true); ui->quickConfigProtectionBox->setEnabled(true); ui->quickKeyParamsBox->setEnabled(true); this->setEnabled(true); } else if(m_state >= State_Programming_Multiple) { if(m_keysProgrammedCtr > 0 && !m_ready) { if(this->currentIndex() == Page_Quick) { changeQuickConfigParams(); } else { changeAdvConfigParams(); } } } } } void StaticPage::clearState() { m_state = State_Initial; m_ready = true; if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } } /* Quick Page handling */ void StaticPage::resetQuickPage() { if(ui->quickConfigSlot1Radio->isChecked()) { ui->quickConfigSlot2Radio->setChecked(true); } ui->quickAutoProgramKeysCheck->setChecked(false); ui->quickProgramMulKeysBox->setChecked(false); ui->quickConfigProtectionBox->reset(); ui->quickStaticLenTxt->setText("0"); ui->quickStaticTxt->clear(); ui->quickStaticTxt->setEnabled(false); ui->quickScanCodesTxt->clear(); ui->quickScanCodesTxt->setEnabled(false); ui->quickInsertTabBtn->setEnabled(false); ui->quickClearBtn->setEnabled(false); ui->quickKeymapCmb->setCurrentIndex(0); ui->quickStopBtn->setEnabled(false); ui->quickResetBtn->setEnabled(false); } void StaticPage::freezeQuickPage(bool freeze) { bool disable = !freeze; ui->quickConfigBox->setEnabled(disable); ui->quickProgramMulKeysBox->setEnabled(disable); ui->quickConfigProtectionBox->setEnabled(disable); ui->quickKeyParamsBox->setEnabled(disable); ui->quickWriteConfigBtn->setEnabled(disable); ui->quickStopBtn->setEnabled(!disable); ui->quickResetBtn->setEnabled(disable); ui->quickBackBtn->setEnabled(disable); } void StaticPage::on_quickHideParams_clicked(bool checked) { if(checked) { ui->quickStaticTxt->setEchoMode(QLineEdit::Password); ui->quickScanCodesTxt->setEchoMode(QLineEdit::Password); } else { ui->quickStaticTxt->setEchoMode(QLineEdit::Normal); ui->quickScanCodesTxt->setEchoMode(QLineEdit::Normal); } } void StaticPage::on_quickStaticTxt_textEdited(const QString &txt) { QString scanCodes = scanedit->textToScanCodes(txt); ui->quickScanCodesTxt->setText(scanCodes); int len = scanCodes.length() / 2; ui->quickStaticLenTxt->setText(QString::number(len)); if(len >= MAX_SCAN_EDIT_SIZE) { ui->quickInsertTabBtn->setEnabled(false); } else { ui->quickInsertTabBtn->setEnabled(true); } } void StaticPage::on_quickStaticTxt_returnPressed() { QString text = ui->quickStaticTxt->text() + "\\n"; ui->quickStaticTxt->setText(text); on_quickStaticTxt_textEdited(text); } void StaticPage::on_quickInsertTabBtn_clicked() { QString text = ui->quickStaticTxt->text() + "\\t"; ui->quickStaticTxt->setText(text); ui->quickStaticTxt->setFocus(); on_quickStaticTxt_textEdited(text); } void StaticPage::on_quickClearBtn_clicked() { ui->quickScanCodesTxt->clear(); ui->quickStaticTxt->clear(); ui->quickStaticLenTxt->setText("0"); ui->quickInsertTabBtn->setEnabled(true); } void StaticPage::on_quickWriteConfigBtn_clicked() { emit showStatusMessage(NULL, -1); if(!ui->quickProgramMulKeysBox->isChecked()) { m_keysProgrammedCtr = 0; } //Validate settings if(!validateQuickSettings()) { return; } clearState(); freezeQuickPage(true); // Change state if(ui->quickProgramMulKeysBox->isChecked()) { if(ui->quickAutoProgramKeysCheck->isChecked()) { m_keysProgrammedCtr = 0; m_state = State_Programming_Multiple_Auto; } else { m_state = State_Programming_Multiple; } } else { m_keysProgrammedCtr = 0; m_state = State_Programming; } writeQuickConfig(); } void StaticPage::on_quickStopBtn_clicked() { ui->quickStopBtn->setEnabled(false); m_state = State_Initial; stopQuickConfigWritting(); } void StaticPage::stopQuickConfigWritting() { qDebug() << "Stopping quick configuration writing..."; if(m_state >= State_Programming_Multiple) { ui->quickStopBtn->setEnabled(true); return; } m_keysProgrammedCtr = 0; clearState(); freezeQuickPage(false); ui->quickResetBtn->setEnabled(true); } void StaticPage::changeQuickConfigParams() { m_ready = true; } bool StaticPage::validateQuickSettings() { if(!(ui->quickConfigSlot1Radio->isChecked() || ui->quickConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } //Check if configuration slot 1 is being programmed if (ui->quickStaticLenTxt->text().toInt() == 0) { QMessageBox::critical(this, tr(ERR), tr(WARN_EMPTY_PASS)); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->quickConfigSlot1Radio->isChecked() && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } if(!ui->quickConfigProtectionBox->checkConfirm()) { return false; } return true; } void StaticPage::writeQuickConfig() { qDebug() << "Writing configuration..."; //Disable stop button while configuration is being written ui->quickStopBtn->setEnabled(false); //Write configuration if(m_ykConfig != 0) { qDebug() << "ykConfig destroyed"; delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_Static); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->quickConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Parameters... QString staticTxt = ui->quickScanCodesTxt->text(); YubiKeyUtil::qstrClean(&staticTxt, 0); qDebug() << "static txt is: " << staticTxt; QString pubIdTxt(""); QString pvtIdTxt(""); QString secretKeyTxt(""); int staticLen = staticTxt.length() / 2; int len = staticLen; // If longer than size of fixed, fill up UID and key if(staticLen > FIXED_SIZE) { staticLen -= UID_SIZE; if(staticLen > FIXED_SIZE) { staticLen -= KEY_SIZE; secretKeyTxt = staticTxt.mid((len - KEY_SIZE) * 2, KEY_SIZE * 2); pvtIdTxt = staticTxt.mid((len - UID_SIZE - KEY_SIZE) * 2, UID_SIZE * 2); } else { pvtIdTxt = staticTxt.mid((len - UID_SIZE) * 2, UID_SIZE * 2); } } qDebug() << "staticLen:" << staticLen; // Keep what's left in the fixed part pubIdTxt = staticTxt.mid(0, staticLen * 2); qDebug() << "pubIdTxt:" << pubIdTxt; qDebug() << "pvtIdTxt:" << pvtIdTxt; qDebug() << "secretKeyTxt:" << secretKeyTxt; //Public ID... if(!pubIdTxt.isEmpty()) { m_ykConfig->setPubIdInHex(true); m_ykConfig->setPubIdTxt(pubIdTxt); } //Private ID... if(!pvtIdTxt.isEmpty()) { m_ykConfig->setPvtIdTxt(pvtIdTxt); } //Secret Key... if(!secretKeyTxt.isEmpty()) { m_ykConfig->setSecretKeyTxt(secretKeyTxt); } //Configuration protection... m_ykConfig->setCurrentAccessCodeTxt( ui->quickConfigProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->quickConfigProtectionBox->newAccessCode(), ui->quickConfigProtectionBox->newAccMode()); //Static Options... m_ykConfig->setShortTicket(true); //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } void StaticPage::quickConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); QString message; if(written) { int staticLen = ui->quickStaticLenTxt->text().toInt(); QString keyDetail = tr(" (Password Length: %1 chars)").arg(staticLen); if(m_state == State_Programming){ message = tr(KEY_CONFIGURED).arg(keyDetail); } else { message = tr("%1. %2").arg(tr(KEY_CONFIGURED).arg(keyDetail)).arg(tr(REMOVE_KEY)); } showStatusMessage(message, 0); message = tr(KEY_CONFIGURED).arg(""); } else { qDebug() << "Configuration could not be written...."; message = msg; } quickUpdateResults(written, message); m_ready = false; stopQuickConfigWritting(); } void StaticPage::quickUpdateResults(bool written, const QString &msg) { int row = 0; ui->quickResultsWidget->insertRow(row); //Sr. No.... QTableWidgetItem *srnoItem = new QTableWidgetItem( tr("%1").arg(ui->quickResultsWidget->rowCount())); if(written) { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/tick.png")))); } else { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/cross.png")))); } srnoItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->quickResultsWidget->setItem(row, 0, srnoItem); //Password Len.... int staticLen = ui->quickStaticLenTxt->text().toInt(); QTableWidgetItem *lenItem = new QTableWidgetItem( tr("%1").arg(QString::number(staticLen))); ui->quickResultsWidget->setItem(row, 1, lenItem); //Status... QTableWidgetItem *statusItem = new QTableWidgetItem( tr("%1").arg(msg)); statusItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->quickResultsWidget->setItem(row, 2, statusItem); //Timestamp... QDateTime timstamp = QDateTime::currentDateTime(); QTableWidgetItem *timeItem = new QTableWidgetItem( tr("%1").arg(timstamp.toString(Qt::SystemLocaleShortDate))); timeItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->quickResultsWidget->setItem(row, 3, timeItem); ui->quickResultsWidget->resizeColumnsToContents(); ui->quickResultsWidget->resizeRowsToContents(); } /* Advanced Page handling */ void StaticPage::resetAdvPage() { if(ui->advConfigSlot1Radio->isChecked()) { ui->advConfigSlot2Radio->setChecked(true); } ui->advConfigParamsCombo->setCurrentIndex(SCHEME_FIXED); ui->advAutoProgramKeysCheck->setChecked(false); ui->advProgramMulKeysBox->setChecked(false); ui->advConfigProtectionBox->reset(); ui->advStaticLen32Radio->setChecked(true); int minStaticLen = ui->advStaticLenBox->minimum(); ui->advStaticLenBox->setValue(minStaticLen); enablePubId(false); ui->advPvtIdTxt->clear(); on_advPvtIdTxt_editingFinished(); ui->advSecretKeyTxt->clear(); on_advSecretKeyTxt_editingFinished(); ui->advStopBtn->setEnabled(false); ui->advResetBtn->setEnabled(false); } void StaticPage::freezeAdvPage(bool freeze) { bool disable = !freeze; ui->advConfigBox->setEnabled(disable); ui->advProgramMulKeysBox->setEnabled(disable); ui->advConfigProtectionBox->setEnabled(disable); ui->advKeyParamsBox->setEnabled(disable); ui->advWriteConfigBtn->setEnabled(disable); ui->advStopBtn->setEnabled(!disable); ui->advResetBtn->setEnabled(disable); ui->advBackBtn->setEnabled(disable); } void StaticPage::on_advProgramMulKeysBox_clicked(bool checked) { if(checked) { changeAdvConfigParams(); } } void StaticPage::on_advConfigParamsCombo_currentIndexChanged(__attribute__((unused)) int index) { changeAdvConfigParams(); } void StaticPage::on_advStaticLenBox_valueChanged(int value) { int len = value / 2 - KEY_SIZE; if(len > 0) { enablePubId(true); QString modhexMask(""); for(int i = 1; i <= len; i++) { modhexMask.append("nn "); } ui->advPubIdTxt->setInputMask(modhexMask); on_advPubIdTxt_editingFinished(); } else { enablePubId(false); } } void StaticPage::on_advStaticLen16Radio_clicked(bool checked) { ui->advStaticLenBox->setEnabled(!checked); enablePubId(!checked); } void StaticPage::on_advStaticLen32Radio_clicked(__attribute__((unused)) bool checked) { ui->advStaticLenBox->setEnabled(true); on_advStaticLenBox_valueChanged(ui->advStaticLenBox->value()); } void StaticPage::enablePubId(bool enable) { if(!enable) { ui->advPubIdTxt->clear(); ui->advPubIdTxt->inputMask(); } else { on_advPubIdTxt_editingFinished(); } ui->advPubIdTxt->setEnabled(enable); ui->advPubIdGenerateBtn->setEnabled(enable); } void StaticPage::on_advPubIdTxt_editingFinished() { QString txt = ui->advPubIdTxt->text(); size_t len = ui->advPubIdTxt->maxLength() / 3; YubiKeyUtil::qstrModhexClean(&txt, (size_t)len * 2); ui->advPubIdTxt->setText(txt); len = txt.length(); ui->advPubIdTxt->setCursorPosition(len + len/2); } void StaticPage::on_advPubIdGenerateBtn_clicked() { size_t len = ui->advPubIdTxt->maxLength() / 3; QString txt = YubiKeyUtil::generateRandomModhex((size_t)len * 2); ui->advPubIdTxt->setText(txt); } void StaticPage::on_advPvtIdTxt_editingFinished() { QString txt = ui->advPvtIdTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)UID_SIZE * 2); ui->advPvtIdTxt->setText(txt); } void StaticPage::on_advPvtIdGenerateBtn_clicked() { ui->advPvtIdTxt->setText( YubiKeyUtil::generateRandomHex((size_t)UID_SIZE * 2)); } void StaticPage::on_advSecretKeyTxt_editingFinished() { QString txt = ui->advSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE * 2); ui->advSecretKeyTxt->setText(txt); } void StaticPage::on_advSecretKeyGenerateBtn_clicked() { ui->advSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE * 2)); } void StaticPage::on_advStrongPw1Check_stateChanged(int state) { QSettings settings; settings.setValue(SG_STRONG_PW1, state != 0); } void StaticPage::on_advStrongPw2Check_stateChanged(int state) { QSettings settings; settings.setValue(SG_STRONG_PW2, state != 0); if(state == 0) { ui->advStrongPw3Check->setChecked(false); } } void StaticPage::on_advStrongPw3Check_stateChanged(int state) { QSettings settings; settings.setValue(SG_STRONG_PW3, state != 0); if(!ui->advStrongPw2Check->isChecked() && state > 0) { ui->advStrongPw2Check->setChecked(true); } } void StaticPage::on_advWriteConfigBtn_clicked() { emit showStatusMessage(NULL, -1); if(!ui->advProgramMulKeysBox->isChecked()) { m_keysProgrammedCtr = 0; } //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); // Change state if(ui->advProgramMulKeysBox->isChecked()) { if(ui->advAutoProgramKeysCheck->isChecked()) { m_keysProgrammedCtr = 0; m_state = State_Programming_Multiple_Auto; } else { m_state = State_Programming_Multiple; } } else { m_keysProgrammedCtr = 0; m_state = State_Programming; } writeAdvConfig(); } void StaticPage::on_advStopBtn_clicked() { ui->advStopBtn->setEnabled(false); m_state = State_Initial; stopAdvConfigWritting(); } void StaticPage::stopAdvConfigWritting() { qDebug() << "Stopping adv configuration writing..."; if(m_state >= State_Programming_Multiple) { ui->advStopBtn->setEnabled(true); return; } m_keysProgrammedCtr = 0; clearState(); freezeAdvPage(false); ui->advResetBtn->setEnabled(true); } void StaticPage::changeAdvConfigParams() { int index = ui->advConfigParamsCombo->currentIndex(); if(index == SCHEME_FIXED) { m_ready = true; return; } int idScheme = GEN_SCHEME_FIXED; int secretScheme = GEN_SCHEME_FIXED; switch(index) { case SCHEME_INCR_ID_RAND_SECRET: //Increment IDs only if in programming mode if(m_state != State_Initial) { idScheme = GEN_SCHEME_INCR; } secretScheme = GEN_SCHEME_RAND; break; case SCHEME_RAND_ALL: idScheme = GEN_SCHEME_RAND; secretScheme = GEN_SCHEME_RAND; break; } //Public ID... int len = ui->advStaticLenBox->value() / 2 - KEY_SIZE; QString pubIdTxt = YubiKeyUtil::getNextModhex( len * 2, ui->advPubIdTxt->text(), idScheme); ui->advPubIdTxt->setText(pubIdTxt); on_advPubIdTxt_editingFinished(); //Private ID... QString pvtIdTxt = YubiKeyUtil::getNextHex( UID_SIZE * 2, ui->advPvtIdTxt->text(), idScheme); ui->advPvtIdTxt->setText(pvtIdTxt); //Secret Key... QString secretKeyTxt = YubiKeyUtil::getNextHex( KEY_SIZE * 2, ui->advSecretKeyTxt->text(), secretScheme); ui->advSecretKeyTxt->setText(secretKeyTxt); m_ready = true; } bool StaticPage::validateAdvSettings() { if(!(ui->advConfigSlot1Radio->isChecked() || ui->advConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->advConfigSlot1Radio->isChecked() && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } if(!ui->advConfigProtectionBox->checkConfirm()) { return false; } return true; } void StaticPage::writeAdvConfig() { qDebug() << "Writing configuration..."; //Disable stop button while configuration is being written ui->advStopBtn->setEnabled(false); //Write configuration if(m_ykConfig != 0) { qDebug() << "ykConfig destroyed"; delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_Static); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->advConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Public ID... m_ykConfig->setPubIdTxt(ui->advPubIdTxt->text()); //Private ID... m_ykConfig->setPvtIdTxt(ui->advPvtIdTxt->text()); //Secret Key... m_ykConfig->setSecretKeyTxt(ui->advSecretKeyTxt->text()); //Configuration protection... m_ykConfig->setCurrentAccessCodeTxt( ui->advConfigProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->advConfigProtectionBox->newAccessCode(), ui->advConfigProtectionBox->newAccMode()); //Static Options... m_ykConfig->setStaticTicket(true); if(ui->advStaticLen16Radio->isChecked()) { m_ykConfig->setShortTicket(true); } if(YubiKeyFinder::getInstance()->checkFeatureSupport( YubiKeyFinder::Feature_StrongPwd)) { if(ui->advStrongPw1Check->isChecked()) { m_ykConfig->setStrongPw1(true); } if(ui->advStrongPw2Check->isChecked()) { m_ykConfig->setStrongPw2(true); } if(ui->advStrongPw3Check->isChecked()) { m_ykConfig->setSendRef(true); } } QSettings settings; m_ykConfig->setManUpdate(settings.value(SG_MAN_UPDATE).toBool()); //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } void StaticPage::advConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); QString message; if(written && m_ykConfig != 0) { qDebug() << "Configuration written...."; m_keysProgrammedCtr++; int staticLen = 0; if(ui->advStaticLen16Radio->isChecked()) { staticLen = 16; } else { staticLen = ui->advStaticLenBox->value(); } QString keyDetail = tr(" (Password Length: %1 chars)").arg(staticLen); if(m_state == State_Programming){ message = tr(KEY_CONFIGURED).arg(keyDetail); } else { message = tr("%1. %2").arg(tr(KEY_CONFIGURED).arg(keyDetail)).arg(tr(REMOVE_KEY)); } showStatusMessage(message, 0); message = tr(KEY_CONFIGURED).arg(""); } else { qDebug() << "Configuration could not be written...."; message = msg; } advUpdateResults(written, message); m_ready = false; stopAdvConfigWritting(); } void StaticPage::advUpdateResults(bool written, const QString &msg) { int row = 0; ui->advResultsWidget->insertRow(row); //Sr. No.... QTableWidgetItem *srnoItem = new QTableWidgetItem( tr("%1").arg(ui->advResultsWidget->rowCount())); if(written) { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/tick.png")))); } else { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/cross.png")))); } srnoItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 0, srnoItem); //Password Len.... int staticLen = 0; if(ui->advStaticLen16Radio->isChecked()) { staticLen = 16; } else { staticLen = ui->advStaticLenBox->value(); } QTableWidgetItem *lenItem = new QTableWidgetItem( tr("%1").arg(QString::number(staticLen))); ui->advResultsWidget->setItem(row, 1, lenItem); //Public ID... QString pubId; if(m_ykConfig != 0 && m_ykConfig->pubIdTxt().length() > 0) { pubId = m_ykConfig->pubIdTxt(); } else { pubId = NA; } QTableWidgetItem *idItem = new QTableWidgetItem( tr("%1").arg(pubId)); idItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 2, idItem); //Status... QTableWidgetItem *statusItem = new QTableWidgetItem( tr("%1").arg(msg)); statusItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 3, statusItem); //Timestamp... QDateTime timstamp = QDateTime::currentDateTime(); QTableWidgetItem *timeItem = new QTableWidgetItem( tr("%1").arg(timstamp.toString(Qt::SystemLocaleShortDate))); timeItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 4, timeItem); ui->advResultsWidget->resizeColumnsToContents(); ui->advResultsWidget->resizeRowsToContents(); } void StaticPage::on_quickScanCodesTxt_textEdited(const QString &scanCodes) { QString text = scanedit->scanCodesToText(scanCodes); ui->quickStaticTxt->setText(text); int len = scanCodes.length() / 2; ui->quickStaticLenTxt->setText(QString::number(len)); if(len >= MAX_SCAN_EDIT_SIZE) { ui->quickInsertTabBtn->setEnabled(false); } else { ui->quickInsertTabBtn->setEnabled(true); } } void StaticPage::setCurrentSlot(int slot) { if(m_currentPage == Page_Advanced) { ui->advConfigSlot1Radio->setChecked(slot == 1); ui->advConfigSlot2Radio->setChecked(slot == 2); } else if(m_currentPage == Page_Quick) { ui->quickConfigSlot1Radio->setChecked(slot == 1); ui->quickConfigSlot2Radio->setChecked(slot == 2); } } void StaticPage::on_quickKeymapCmb_currentIndexChanged(int index) { // Reset these, independent of the chosen layout ui->quickStaticLenTxt->setText("0"); ui->quickStaticTxt->clear(); ui->quickScanCodesTxt->clear(); if(scanedit) { delete scanedit; scanedit = NULL; } if (index == KEYMAP_NONE) { ui->quickStaticTxt->setEnabled(false); ui->quickScanCodesTxt->setEnabled(false); ui->quickInsertTabBtn->setEnabled(false); ui->quickClearBtn->setEnabled(false); } else { if(index == KEYMAP_US) { scanedit = new UsScanEdit(); } else if(index == KEYMAP_DE) { scanedit = new DeScanEdit(); } ui->quickStaticTxt->setEnabled(true); ui->quickScanCodesTxt->setEnabled(true); ui->quickInsertTabBtn->setEnabled(true); ui->quickClearBtn->setEnabled(true); } } yubikey-personalization-gui-3.1.24/src/ui/toolpage.ui0000664000175000017500000012443512642452141021322 0ustar klasklas ToolPage 0 0 730 650 0 0 730 650 StackedWidget font: 11px "Verdana"; color: rgb(0, 0, 0); 3 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Tools Qt::AlignCenter 10 50 711 421 border-color: rgb(0, 0, 0); Qt::AlignCenter 20 20 191 25 0 0 font: 12px; font-weight: bold; Number Converter false false false 20 45 671 20 Convert between different number formats Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 100 191 25 0 0 font: 12px; font-weight: bold; Challenge-Response false false false 20 125 671 20 Test Challenge-Response functionality of YubiKey Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 180 191 25 0 0 font: 12px; font-weight: bold; NDEF Programming false false false 20 205 671 20 Program the static NDEF string of a Yubikey NEO Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 260 191 25 0 0 font: 12px; font-weight: bold; Delete Configuration false false false 20 285 671 20 Delete the configuration stored in the YubiKey Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 20 340 650 80 0 0 191 25 0 0 font: 12px; font-weight: bold; Import Configuration false false false 0 25 671 20 Import a configuration in ycfg format Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Number Converter Qt::AlignCenter 10 50 711 125 font-weight: bold; 180 60 381 20 0 0 font-weight: normal; nn nn nn nn nn nn nn nn nn nn nn nn nn nn nn nn 47 47 10 30 91 20 font-weight:normal; Hexadecimal 10 60 91 20 font-weight:normal; Modhex 180 30 381 20 0 0 font-weight: normal; nn nn nn nn nn nn nn nn nn nn nn nn nn nn nn nn 47 47 false 571 28 85 25 font: 12px; font-weight: bold; Copy false false false false 571 58 85 25 font: 12px; font-weight: bold; Copy false false false 10 90 91 20 font-weight:normal; Decimal 180 90 381 20 font-weight: normal; 00000000000000000000 0 20 20 false 571 88 85 25 font: 12px; font-weight: bold; Copy false false false 110 30 61 20 font-weight: normal; color: rgb(118, 116, 108) (0 chars) 110 60 61 20 font-weight: normal; color: rgb(118, 116, 108) (0 chars) 110 90 61 20 font-weight:normal; color:rgb(221, 97, 99); 10 185 711 60 font-weight: bold; Actions true 110 25 85 25 font: 12px; font-weight: bold; Reset false false false 10 25 85 25 font: 12px; font-weight: bold; Convert false false false 210 25 85 25 Back 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Challenge-Response Tester Qt::AlignCenter 10 50 711 225 0 70 361 50 10 0 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the challenge-response type 10 20 151 19 font-weight: normal; HMAC-SHA1 true false 200 20 151 19 font-weight: normal; Yubico OTP 0 0 361 60 10 10 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be used 10 30 151 19 font-weight: normal; Configuration Slot 1 true false 200 30 151 19 font-weight: normal; Configuration Slot 2 10 130 321 16 font-weight: normal; color: rgb(118, 116, 108); Input challenge, max 64 characters 10 150 361 20 0 0 font-weight: normal; 64 0 10 175 321 16 font-weight: normal; color: rgb(118, 116, 108); Response: 10 195 361 20 0 0 font-weight: normal; 64 true 10 295 711 50 font-weight: bold; 10 10 85 25 Perform 210 10 85 25 Back 110 10 85 25 Reset 0 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); NDEF Programming Qt::AlignCenter 10 300 711 50 font-weight: bold; 10 10 85 25 Program 210 10 85 25 Back 110 10 85 25 Reset 10 50 711 240 10 65 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the NDEF type 10 85 221 17 font-weight: normal; URI true true 10 105 151 17 font-weight: normal; Text 10 210 391 20 https://my.yubico.com/neo/ 80 false 10 145 113 26 en-US 10 125 321 16 font-weight: normal; color: rgb(118, 116, 108); NDEF text language (IANA language code) 10 190 321 16 font-weight: normal; color: rgb(118, 116, 108); NDEF payload, OTP will be appended on the end 530 10 150 100 10 10 125 23 Use Access Code 10 40 125 20 hh hh hh hh hh hh 00 00 00 00 00 00 false 10 65 150 23 font: 11px "Verdana"; color: rgb(0, 0, 0); Use Serial Number 10 10 361 50 0 0 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be used 0 20 151 19 font-weight: normal; Configuration Slot 1 true false 190 20 151 19 font-weight: normal; Configuration Slot 2 10 50 361 75 10 10 321 16 font-weight: normal; color: rgb(118, 116, 108); Select the configuration slot to be deleted 10 40 151 19 font-weight: normal; Configuration Slot 1 true false 200 40 151 19 font-weight: normal; Configuration Slot 2 10 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Delete Configuration Qt::AlignCenter 10 125 711 50 font-weight: bold; 10 10 85 25 Delete 110 10 85 25 Back 500 50 150 100 10 10 125 23 Use Access Code 10 40 125 20 hh hh hh hh hh hh 00 00 00 00 00 00 false 10 65 150 23 font: 11px "Verdana"; color: rgb(0, 0, 0); Use Serial Number 0 0 710 22 font: 18px "Verdana"; font-weight: bold; color: rgb(140, 192, 65); Import Configuration Qt::AlignCenter 10 70 711 50 font-weight: bold; 10 10 85 25 Import 110 10 85 25 Back 10 50 600 16 font-weight: normal; color: rgb(118, 116, 108); When you import and select a file all settings will be overwritten 10 115 600 16 font-weight: normal; color: rgb(118, 116, 108); Import is only available with a YubiKey inserted converterHexTxt converterModhexTxt converterDecTxt converterHexCopyBtn converterModhexCopyBtn converterDecCopyBtn converterConvertBtn converterResetBtn converterBtn yubikey-personalization-gui-3.1.24/src/ui/oathpage.cpp0000664000175000017500000010542312642452141021441 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "oathpage.h" #include "yubikeyutil.h" #include "yubikeyfinder.h" #include "yubikeywriter.h" #include "ui_oathpage.h" #include "ui/helpbox.h" #include "ui/confirmbox.h" #include #include #include #include #include #include #define OATH_FIXED_NUMERIC 0 #define OATH_FIXED_MODHEX1 1 #define OATH_FIXED_MODHEX2 2 #define OATH_FIXED_MODHEX 3 #define MOVING_FACTOR_ZERO 0 #define MOVING_FACTOR_FIXED 1 #define MOVING_FACTOR_RAND 2 OathPage::OathPage(QWidget *parent) : QStackedWidget(parent), ui(new Ui::OathPage) { ui->setupUi(this); m_customerPrefix = -1; memset(&m_pubId, 0, sizeof(m_pubId)); m_pubIdMUI = 0; m_ykConfig = 0; m_keyPresent = false; clearState(); //Connect pages connectPages(); //Connect help buttons connectHelpButtons(); //Connect other signals and slots connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); connect(ui->quickWriteConfigBtn, SIGNAL(clicked()), this, SLOT(writeQuickConfig())); connect(ui->advResetBtn, SIGNAL(clicked()), this, SLOT(resetAdvPage())); connect(ui->advMovingFactorSeedTxt, SIGNAL(editingFinished()), this, SLOT(on_advMovingFactorSeedTxt_editingFinished())); connect(ui->advHotpLen6Radio, SIGNAL(clicked()), this, SLOT(hotpLen_clicked())); connect(ui->advHotpLen8Radio, SIGNAL(clicked()), this, SLOT(hotpLen_clicked())); connect(ui->quickHotpLen6Radio, SIGNAL(clicked()), this, SLOT(hotpLen_clicked())); connect(ui->quickHotpLen8Radio, SIGNAL(clicked()), this, SLOT(hotpLen_clicked())); //Load settings loadSettings(); ui->advResultsWidget->resizeColumnsToContents(); } OathPage::~OathPage() { if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } delete ui; } /* Common */ void OathPage::connectPages() { //Map the values of the navigation buttons with the indexes of //the stacked widget //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickBtn, Page_Quick); mapper->setMapping(ui->quickBackBtn, Page_Base); mapper->setMapping(ui->advBtn, Page_Advanced); mapper->setMapping(ui->advBackBtn, Page_Base); //Connect the mapper to the widget //The mapper will set a value to each button and //set that value to the widget //connect(pageMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentIndex(int))); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); //Set the current page m_currentPage = 0; setCurrentIndex(Page_Base); } void OathPage::setCurrentPage(int pageIndex) { //Page changed... m_currentPage = pageIndex; switch(pageIndex){ case Page_Quick: resetQuickPage(); break; case Page_Advanced: resetAdvPage(); break; } setCurrentIndex(pageIndex); //Clear state m_keysProgrammedCtr = 0; clearState(); } void OathPage::connectHelpButtons() { //Map the values of the help buttons //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickPubIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickHotpLenHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advParamGenSchemeHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advPubIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advHotpLenHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advHotpParamsHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->quickPubIdHelpBtn, HelpBox::Help_OathPublicID); mapper->setMapping(ui->quickHotpLenHelpBtn, HelpBox::Help_HotpLen); mapper->setMapping(ui->quickSecretKeyHelpBtn, HelpBox::Help_SecretKey); mapper->setMapping(ui->advConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->advParamGenSchemeHelpBtn, HelpBox::Help_ParameterGeneration); mapper->setMapping(ui->advPubIdHelpBtn, HelpBox::Help_OathPublicID); mapper->setMapping(ui->advHotpLenHelpBtn, HelpBox::Help_HotpLen); mapper->setMapping(ui->advHotpParamsHelpBtn, HelpBox::Help_HotpParam); mapper->setMapping(ui->advSecretKeyHelpBtn, HelpBox::Help_SecretKey); //Connect the mapper connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int))); connect(ui->advConfigProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); } void OathPage::keyFound(bool found, bool* featuresMatrix) { if(found) { if(m_state == State_Initial) { ui->quickWriteConfigBtn->setEnabled(true); ui->advWriteConfigBtn->setEnabled(true); ui->advExportConfigBtn->setEnabled(true); if(!featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) { ui->quickConfigSlot2Radio->setEnabled(false); ui->advConfigSlot2Radio->setEnabled(false); } else { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); } if(!featuresMatrix[YubiKeyFinder::Feature_MovingFactor]) { ui->advMovingFactorSeedCombo->setEnabled(false); ui->advMovingFactorSeedTxt->setEnabled(false); } if(!featuresMatrix[YubiKeyFinder::Feature_OathHotp]) { this->setEnabled(false); } if(this->currentIndex() == Page_Quick) { resetQuickPrefix(); } } else if(this->currentIndex() == Page_Advanced && m_state >= State_Programming_Multiple && m_keyPresent == false) { if(m_state == State_Programming_Multiple) { ui->advWriteConfigBtn->setEnabled(true); ui->advExportConfigBtn->setEnabled(true); } else { writeAdvConfig(WRITE_CONFIG); } } m_keyPresent = true; } else { ui->quickWriteConfigBtn->setEnabled(false); ui->advWriteConfigBtn->setEnabled(false); ui->advExportConfigBtn->setEnabled(false); m_keyPresent = false; if(m_state == State_Initial) { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); ui->advMovingFactorSeedCombo->setEnabled(true); if(ui->advMovingFactorSeedCombo->currentIndex() == MOVING_FACTOR_ZERO) { ui->advMovingFactorSeedTxt->setEnabled(false); } else { ui->advMovingFactorSeedTxt->setEnabled(true); } this->setEnabled(true); } else if(this->currentIndex() == Page_Advanced && m_state >= State_Programming_Multiple) { if(m_keysProgrammedCtr > 0 && !m_ready) { changeAdvConfigParams(); } } } } void OathPage::clearState() { m_state = State_Initial; m_ready = true; if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } } void OathPage::updatePrefix() { if(m_currentPage == Page_Quick || m_customerPrefix > 0) { //OMP m_pubId[0] = YUBICO_OMP_CODE; //TT m_pubId[1] = OATH_HOTP_CUSTOMER_PREFIX_START + (unsigned char) (m_customerPrefix / 1000); if(m_customerPrefix > 0) { // make room for the prefix.. m_pubIdMUI %= 99999; int mui_part = m_customerPrefix % 1000; m_pubIdMUI += mui_part * 100000; } } QString pubIdTxt; QString muiTxt = QString::number(m_pubIdMUI).rightJustified(8, '0'); QString pubIdModhexTxt = YubiKeyUtil::qstrModhexEncode( m_pubId, 2); switch(m_currentPage) { case Page_Quick: ui->quickPrefixTxt->setText(pubIdModhexTxt.left(4)); ui->quickMUITxt->setText(muiTxt); break; case Page_Advanced: switch(ui->advPubIdFormatCombo->currentIndex()){ case OATH_FIXED_NUMERIC: fixBCD(m_pubId, 2); pubIdTxt = YubiKeyUtil::qstrHexEncode( m_pubId, 2); ui->advOMPTxt->setText(pubIdTxt.left(2)); ui->advTTTxt->setText(pubIdTxt.mid(2, 2)); ui->advMUITxt->setText(muiTxt); break; case OATH_FIXED_MODHEX1: fixBCD(m_pubId + 1, 1); pubIdTxt = YubiKeyUtil::qstrHexEncode( m_pubId, 2); ui->advOMPTxt->setText(pubIdModhexTxt.left(2)); ui->advTTTxt->setText(pubIdTxt.mid(2, 2)); ui->advMUITxt->setText(muiTxt); break; case OATH_FIXED_MODHEX2: ui->advOMPTxt->setText(pubIdModhexTxt.left(2)); ui->advTTTxt->setText(pubIdModhexTxt.mid(2, 2)); ui->advMUITxt->setText(muiTxt); break; case OATH_FIXED_MODHEX: unsigned char tempMUI[4]; tempMUI[0] = (m_pubIdMUI >> 24) & 0xff; tempMUI[1] = (m_pubIdMUI >> 16) & 0xff; tempMUI[2] = (m_pubIdMUI >> 8) & 0xff; tempMUI[3] = m_pubIdMUI & 0xff; muiTxt = YubiKeyUtil::qstrModhexEncode(tempMUI, 4); ui->advOMPTxt->setText(pubIdModhexTxt.left(2)); ui->advTTTxt->setText(pubIdModhexTxt.mid(2, 2)); ui->advMUITxt->setText(muiTxt); break; } break; } } void OathPage::fixBCD(unsigned char *bp, int bcnt) { while (bcnt--) { if ((*bp & 0x0f) > 0x09) *bp -= 0x09; if ((*bp & 0xf0) > 0x90) *bp -= 0x90; bp++; } } void OathPage::loadSettings() { QSettings settings; m_customerPrefix = settings.value(SG_CUSTOMER_PREFIX).toInt(); if(m_customerPrefix > 0) { ui->advPubIdFormatCombo->setCurrentIndex(OATH_FIXED_MODHEX2); } bool customerPrefixFlag = !(m_customerPrefix > 0); ui->advPubIdFormatCombo->setEnabled(customerPrefixFlag); ui->advOMPTxt->setEnabled(customerPrefixFlag); ui->advTTTxt->setEnabled(customerPrefixFlag); ui->advExportConfigBtn->setVisible(settings.value(SG_EXPORT_PREFERENCE).toBool()); bool hotp8 = settings.value(SG_OATH_HOTP8).toBool(); ui->advHotpLen6Radio->setChecked(!hotp8); ui->quickHotpLen6Radio->setChecked(!hotp8); ui->advHotpLen8Radio->setChecked(hotp8); ui->quickHotpLen8Radio->setChecked(hotp8); } /* Quick Page handling */ void OathPage::resetQuickPage() { memset(&m_pubId, 0, sizeof(m_pubId)); if(ui->quickConfigSlot1Radio->isChecked()) { ui->quickConfigSlot2Radio->setChecked(true); } ui->quickPubIdCheck->setChecked(true); on_quickResetBtn_clicked(); } void OathPage::on_quickResetBtn_clicked() { resetQuickPrefix(); ui->quickSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE_OATH * 2)); on_quickSecretKeyTxt_editingFinished(); } void OathPage::on_quickHideParams_clicked(bool checked) { if(checked) { ui->quickSecretKeyTxt->setEchoMode(QLineEdit::Password); } else { ui->quickSecretKeyTxt->setEchoMode(QLineEdit::Normal); } } void OathPage::on_quickPubIdCheck_stateChanged(int state) { bool disable = (state != 0); ui->quickPrefixTxt->setEnabled(disable); ui->quickMUITxt->setEnabled(disable); ui->quickMUIGenerateBtn->setEnabled(disable); } void OathPage::resetQuickPrefix() { ui->quickMUITxt->setText( QString::number(YubiKeyFinder::getInstance()->serial())); updateQuickMUI(); updatePrefix(); } void OathPage::updateQuickMUI() { QString txt = ui->quickMUITxt->text(); unsigned char buf[MAX_SIZE]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; YubiKeyUtil::qstrClean(&txt, OATH_HOTP_MUI_SIZE * 2, true); YubiKeyUtil::qstrDecDecode(buf, &bufLen, txt); ui->quickMUITxt->setText(txt); memcpy(m_pubId + 2, buf, OATH_HOTP_MUI_SIZE); } void OathPage::on_quickMUITxt_editingFinished() { updateQuickMUI(); updatePrefix(); } void OathPage::on_quickMUIGenerateBtn_clicked() { YubiKeyUtil::generateRandom((unsigned char*)&m_pubIdMUI, sizeof(m_pubIdMUI)); m_pubIdMUI %= 99999999; updatePrefix(); } void OathPage::on_quickSecretKeyTxt_editingFinished() { QString txt = ui->quickSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE_OATH * 2); ui->quickSecretKeyTxt->setText(txt); } bool OathPage::validateQuickSettings() { if(!(ui->quickConfigSlot1Radio->isChecked() || ui->quickConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->quickConfigSlot1Radio->isChecked()) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } return true; } void OathPage::writeQuickConfig() { //Clear status emit showStatusMessage(NULL, -1); //Validate settings if(!validateQuickSettings()) { return; } // m_state = State_Programming; //Write configuration ui->quickWriteConfigBtn->setEnabled(false); ui->quickResetBtn->setEnabled(false); ui->quickBackBtn->setEnabled(false); if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_OathHotp); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->quickConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Public ID... if(ui->quickPubIdCheck->isChecked()) { m_ykConfig->setPubIdTxt(getPublicId(true)); //OATH Public ID Type... m_ykConfig->setOathFixedModhex2(true); } //HOTP Len... m_ykConfig->setOathHotp8(ui->quickHotpLen8Radio->isChecked()); //HOTP Moving Factor Seed... m_ykConfig->setOathMovingFactorSeed(0); //Secret Key... m_ykConfig->setSecretKeyTxt(ui->quickSecretKeyTxt->text()); //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } void OathPage::quickConfigWritten(bool written, __attribute__((unused)) const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); ui->quickWriteConfigBtn->setEnabled(true); ui->quickResetBtn->setEnabled(true); ui->quickBackBtn->setEnabled(true); if(written && m_ykConfig != 0) { QString keyDetail(""); if(ui->quickPubIdCheck->isChecked()) { QString pubIdTxt = ui->quickPrefixTxt->text() + ui->quickMUITxt->text().replace(QRegExp("\\s"), QString("")); keyDetail = tr(" (OATH ID: %1)").arg(pubIdTxt); } showStatusMessage(tr(KEY_CONFIGURED).arg(keyDetail), 0); } clearState(); } /* Advanced Page handling */ void OathPage::resetAdvPage() { memset(&m_pubId, 0, sizeof(m_pubId)); m_pubIdMUI = 0; bool customerPrefixFlag = !(m_customerPrefix > 0); if(ui->advConfigSlot1Radio->isChecked()) { ui->advConfigSlot2Radio->setChecked(true); } ui->advConfigParamsCombo->setCurrentIndex(0); ui->advAutoProgramKeysCheck->setChecked(false); ui->advProgramMulKeysBox->setChecked(false); ui->advConfigProtectionBox->reset(); ui->advPubIdCheck->setChecked(true); if(customerPrefixFlag) { ui->advPubIdFormatCombo->setCurrentIndex(OATH_FIXED_NUMERIC); } else { ui->advPubIdFormatCombo->setCurrentIndex(OATH_FIXED_MODHEX2); } ui->advPubIdFormatCombo->setEnabled(customerPrefixFlag); on_advOMPTxt_editingFinished(); ui->advOMPTxt->setEnabled(customerPrefixFlag); on_advTTTxt_editingFinished(); ui->advTTTxt->setEnabled(customerPrefixFlag); on_advMUITxt_editingFinished(); ui->advMovingFactorSeedCombo->setCurrentIndex(0); ui->advMovingFactorSeedTxt->setText(tr("0")); ui->advMovingFactorSeedTxt->setEnabled(false); ui->advSecretKeyTxt->clear(); on_advSecretKeyTxt_editingFinished(); ui->advStopBtn->setEnabled(false); } void OathPage::freezeAdvPage(bool freeze) { bool disable = !freeze; ui->advConfigBox->setEnabled(disable); ui->advProgramMulKeysBox->setEnabled(disable); ui->advConfigProtectionBox->setEnabled(disable); ui->advKeyParamsBox->setEnabled(disable); ui->advWriteConfigBtn->setEnabled(disable); ui->advExportConfigBtn->setEnabled(disable); ui->advStopBtn->setEnabled(!disable); ui->advResetBtn->setEnabled(disable); ui->advBackBtn->setEnabled(disable); } void OathPage::on_advProgramMulKeysBox_clicked(bool checked) { if(checked) { changeAdvConfigParams(); } } void OathPage::on_advConfigParamsCombo_currentIndexChanged(__attribute__((unused)) int index) { changeAdvConfigParams(); } void OathPage::on_advPubIdCheck_stateChanged(int state) { bool disable = (state != 0); if(m_customerPrefix <= 0) { ui->advPubIdFormatCombo->setEnabled(disable); ui->advOMPTxt->setEnabled(disable); ui->advTTTxt->setEnabled(disable); } ui->advMUITxt->setEnabled(disable); ui->advMUIGenerateBtn->setEnabled(disable); } void OathPage::on_advPubIdFormatCombo_currentIndexChanged(__attribute__((unused)) int index) { updatePrefix(); } void OathPage::updateAdvOMP(int index) { QString txt = ui->advOMPTxt->text(); unsigned char buf[MAX_SIZE]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; if (index == OATH_FIXED_NUMERIC) { YubiKeyUtil::qstrClean(&txt, OATH_HOTP_OMP_SIZE * 2, true); YubiKeyUtil::qstrDecDecode(buf, &bufLen, txt); } else { YubiKeyUtil::qstrModhexClean(&txt, OATH_HOTP_OMP_SIZE * 2); YubiKeyUtil::qstrModhexDecode(buf, &bufLen, txt); } ui->advOMPTxt->setText(txt); memcpy(m_pubId + 0, buf, OATH_HOTP_OMP_SIZE); } void OathPage::on_advOMPTxt_editingFinished() { updateAdvOMP(ui->advPubIdFormatCombo->currentIndex()); updatePrefix(); } void OathPage::updateAdvTT(int index) { QString txt = ui->advTTTxt->text(); unsigned char buf[MAX_SIZE]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; if (index == OATH_FIXED_NUMERIC || index == OATH_FIXED_MODHEX1) { YubiKeyUtil::qstrClean(&txt, OATH_HOTP_TT_SIZE * 2, true); YubiKeyUtil::qstrDecDecode(buf, &bufLen, txt); } else { YubiKeyUtil::qstrModhexClean(&txt, OATH_HOTP_TT_SIZE * 2); YubiKeyUtil::qstrModhexDecode(buf, &bufLen, txt); } ui->advTTTxt->setText(txt); memcpy(m_pubId + 1, buf, OATH_HOTP_TT_SIZE); } void OathPage::on_advTTTxt_editingFinished() { updateAdvTT(ui->advPubIdFormatCombo->currentIndex()); updatePrefix(); } void OathPage::updateAdvMUI(int index) { QString txt = ui->advMUITxt->text(); if (index != OATH_FIXED_MODHEX) { YubiKeyUtil::qstrClean(&txt, OATH_HOTP_MUI_SIZE * 2, true); m_pubIdMUI = txt.toInt(); } else { unsigned char buf[MAX_SIZE]; memset(buf, 0, sizeof(buf)); size_t bufLen = 0; YubiKeyUtil::qstrModhexClean(&txt, OATH_HOTP_MUI_SIZE * 2); YubiKeyUtil::qstrModhexDecode(buf, &bufLen, txt); m_pubIdMUI = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3]); } } void OathPage::on_advMUITxt_editingFinished() { updateAdvMUI(ui->advPubIdFormatCombo->currentIndex()); updatePrefix(); } void OathPage::on_advMUIGenerateBtn_clicked() { YubiKeyUtil::generateRandom((unsigned char*)&m_pubIdMUI, sizeof(m_pubIdMUI)); m_pubIdMUI %= 99999999; updatePrefix(); } void OathPage::on_advMovingFactorSeedCombo_currentIndexChanged(int index) { switch(index) { case MOVING_FACTOR_ZERO: ui->advMovingFactorSeedTxt->setText("0"); ui->advMovingFactorSeedTxt->setEnabled(false); break; case MOVING_FACTOR_FIXED: ui->advMovingFactorSeedTxt->setEnabled(true); break; case MOVING_FACTOR_RAND: unsigned int tmp; YubiKeyUtil::generateRandom((unsigned char *) &tmp, sizeof(tmp)); ui->advMovingFactorSeedTxt->setText(QString::number(tmp)); on_advMovingFactorSeedTxt_editingFinished(); ui->advMovingFactorSeedTxt->setEnabled(true); break; } } void OathPage::on_advMovingFactorSeedTxt_editingFinished() { unsigned int val = ui->advMovingFactorSeedTxt->text().toUInt(); val = (((val + 8) >> 4UL) & 0xffff) << 4UL; ui->advMovingFactorSeedTxt->setText(QString::number(val)); } void OathPage::on_advSecretKeyTxt_editingFinished() { QString txt = ui->advSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE_OATH * 2); ui->advSecretKeyTxt->setText(txt); } void OathPage::on_advSecretKeyGenerateBtn_clicked() { ui->advSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE_OATH * 2)); ui->advSecretKeyTxt->setCursorPosition(0); } void OathPage::on_advWriteConfigBtn_clicked() { emit showStatusMessage(NULL, -1); if(!ui->advProgramMulKeysBox->isChecked()) { m_keysProgrammedCtr = 0; } //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); // Change state if(ui->advProgramMulKeysBox->isChecked()) { if(ui->advAutoProgramKeysCheck->isChecked()) { m_keysProgrammedCtr = 0; m_state = State_Programming_Multiple_Auto; } else { m_state = State_Programming_Multiple; } } else { m_keysProgrammedCtr = 0; m_state = State_Programming; } writeAdvConfig(WRITE_CONFIG); } void OathPage::on_advExportConfigBtn_clicked() { emit showStatusMessage(NULL, -1); //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); writeAdvConfig(EXPORT_CONFIG); } void OathPage::on_advStopBtn_clicked() { ui->advStopBtn->setEnabled(false); m_state = State_Initial; stopAdvConfigWritting(); } void OathPage::stopAdvConfigWritting() { qDebug() << "Stopping adv configuration writing..."; if(m_state >= State_Programming_Multiple) { ui->advStopBtn->setEnabled(true); return; } m_keysProgrammedCtr = 0; clearState(); freezeAdvPage(false); ui->advResetBtn->setEnabled(true); } void OathPage::changeAdvConfigParams() { int index = ui->advConfigParamsCombo->currentIndex(); int idScheme = GEN_SCHEME_FIXED; int secretScheme = GEN_SCHEME_FIXED; switch(index) { case SCHEME_INCR_ID_RAND_SECRET: //Increment IDs only if in programming mode if(m_state != State_Initial) { idScheme = GEN_SCHEME_INCR; } secretScheme = GEN_SCHEME_RAND; break; case SCHEME_RAND_ALL: idScheme = GEN_SCHEME_RAND; secretScheme = GEN_SCHEME_RAND; break; } //Public ID... if(ui->advPubIdCheck->isChecked()) { switch(idScheme) { case GEN_SCHEME_INCR: { m_pubIdMUI++; updatePrefix(); } break; case GEN_SCHEME_RAND: YubiKeyUtil::generateRandom((unsigned char*)&m_pubIdMUI, sizeof(m_pubIdMUI)); m_pubIdMUI %= 99999999; updatePrefix(); break; } } //HOTP Moving Factor Seed... if(ui->advMovingFactorSeedCombo->currentIndex() == MOVING_FACTOR_RAND) { unsigned int tmp; YubiKeyUtil::generateRandom((unsigned char *) &tmp, sizeof(tmp)); ui->advMovingFactorSeedTxt->setText(QString::number(tmp)); on_advMovingFactorSeedTxt_editingFinished(); } //Secret Key... QString secretKeyTxt = YubiKeyUtil::getNextHex( KEY_SIZE_OATH * 2, ui->advSecretKeyTxt->text(), secretScheme); ui->advSecretKeyTxt->setText(secretKeyTxt); on_advSecretKeyTxt_editingFinished(); m_ready = true; } bool OathPage::validateAdvSettings() { if(!(ui->advConfigSlot1Radio->isChecked() || ui->advConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->advConfigSlot1Radio->isChecked() && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } if(!ui->advConfigProtectionBox->checkConfirm()) { return false; } return true; } QString OathPage::getPublicId(bool bcd) { unsigned char pubId[6]; memcpy(pubId, m_pubId, 2); if(bcd) { int part = m_pubIdMUI / 1000000; pubId[2] = ((part / 10) << 4) + part % 10; part = m_pubIdMUI / 10000 % 100; pubId[3] = ((part / 10) << 4) + part % 10; part = m_pubIdMUI / 100 % 100; pubId[4] = ((part / 10) << 4) + part % 10; part = m_pubIdMUI % 100; pubId[5] = ((part / 10) << 4) + part % 10; } else { pubId[2] = (m_pubIdMUI >> 24) & 0xff; pubId[3] = (m_pubIdMUI >> 16) & 0xff; pubId[4] = (m_pubIdMUI >> 8) & 0xff; pubId[5] = m_pubIdMUI & 0xff; } QString pubIdTxt = YubiKeyUtil::qstrModhexEncode(pubId, 6); return pubIdTxt; } void OathPage::writeAdvConfig(int mode) { qDebug() << "Writing configuration..."; //Disable stop button while configuration is being written ui->advStopBtn->setEnabled(false); //Write configuration if(m_ykConfig != 0) { qDebug() << "ykConfig destroyed"; delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_OathHotp); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->advConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Public ID... if(ui->advPubIdCheck->isChecked()) { bool bcd = ui->advPubIdFormatCombo->currentIndex() < 3 ? true : false; m_ykConfig->setPubIdTxt(getPublicId(bcd)); //OATH Public ID Type... switch(ui->advPubIdFormatCombo->currentIndex()) { case 1: m_ykConfig->setOathFixedModhex1(true); break; case 2: m_ykConfig->setOathFixedModhex2(true); break; case 3: m_ykConfig->setOathFixedModhex(true); break; } } //HOTP Len... m_ykConfig->setOathHotp8(ui->advHotpLen8Radio->isChecked()); //HOTP Moving Factor Seed... if(YubiKeyFinder::getInstance()->checkFeatureSupport( YubiKeyFinder::Feature_MovingFactor)) { m_ykConfig->setOathMovingFactorSeed( ui->advMovingFactorSeedTxt->text().toUInt()); } //Secret Key... m_ykConfig->setSecretKeyTxt(ui->advSecretKeyTxt->text()); //Configuration protection... m_ykConfig->setCurrentAccessCodeTxt( ui->advConfigProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->advConfigProtectionBox->newAccessCode(), ui->advConfigProtectionBox->newAccMode()); if(mode == WRITE_CONFIG) { //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } else if(mode == EXPORT_CONFIG) { connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigExported(bool, const QString &))); YubiKeyWriter::getInstance()->exportConfig(m_ykConfig); } } void OathPage::advConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); QString message; if(written && m_ykConfig != 0) { qDebug() << "Configuration written...."; m_keysProgrammedCtr++; QString keyDetail(""); if(ui->advPubIdCheck->isChecked()) { QString pubIdTxt = ui->advOMPTxt->text() + ui->advTTTxt->text() + ui->advMUITxt->text().replace(QRegExp("\\s"), QString("")); keyDetail = tr(" (OATH ID: %1)").arg(pubIdTxt); } if(m_state == State_Programming){ message = tr(KEY_CONFIGURED).arg(keyDetail); } else { message = tr("%1. %2").arg(tr(KEY_CONFIGURED).arg(keyDetail)).arg(tr(REMOVE_KEY)); } showStatusMessage(message, 0); message = tr(KEY_CONFIGURED).arg(""); } else { qDebug() << "Configuration could not be written...."; message = msg; } advUpdateResults(written, message); m_ready = false; stopAdvConfigWritting(); } void OathPage::advConfigExported(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigExported(bool, const QString &))); QString message; if(written && m_ykConfig != 0) { qDebug() << "Configuration exported...."; message = tr(KEY_EXPORTED); showStatusMessage(message, 0); } else { qDebug() << "Configuration could not be exported...."; message = msg; } m_ready = false; stopAdvConfigWritting(); } void OathPage::advUpdateResults(bool written, const QString &msg) { int row = 0; ui->advResultsWidget->insertRow(row); //Sr. No.... QTableWidgetItem *srnoItem = new QTableWidgetItem( tr("%1").arg(ui->advResultsWidget->rowCount())); if(written) { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/tick.png")))); } else { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/cross.png")))); } srnoItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 0, srnoItem); //Public ID... QString pubIdTxt; if(ui->advPubIdCheck->isChecked() && m_ykConfig != 0) { pubIdTxt = ui->advOMPTxt->text() + ui->advTTTxt->text() + ui->advMUITxt->text().replace(QRegExp("\\s"), QString("")); } else { pubIdTxt = NA; } QTableWidgetItem *idItem = new QTableWidgetItem( tr("%1").arg(pubIdTxt)); idItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 1, idItem); //Status... QTableWidgetItem *statusItem = new QTableWidgetItem( tr("%1").arg(msg)); statusItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 2, statusItem); //Timestamp... QDateTime timstamp = QDateTime::currentDateTime(); QTableWidgetItem *timeItem = new QTableWidgetItem( tr("%1").arg(timstamp.toString(Qt::SystemLocaleShortDate))); timeItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 3, timeItem); ui->advResultsWidget->resizeColumnsToContents(); ui->advResultsWidget->resizeRowsToContents(); } void OathPage::hotpLen_clicked() { QSettings settings; QRadioButton *button = ui->advHotpLen8Radio; QRadioButton *button2 = ui->quickHotpLen8Radio; if(m_currentPage == Page_Quick) { button = ui->quickHotpLen8Radio; button2 = ui->advHotpLen8Radio; } if(button->isChecked()) { settings.setValue(SG_OATH_HOTP8, true); } else { settings.setValue(SG_OATH_HOTP8, false); } button2->toggle(); } void OathPage::setCurrentSlot(int slot) { if(m_currentPage == Page_Advanced) { ui->advConfigSlot1Radio->setChecked(slot == 1); ui->advConfigSlot2Radio->setChecked(slot == 2); } else if(m_currentPage == Page_Quick) { ui->quickConfigSlot1Radio->setChecked(slot == 1); ui->quickConfigSlot2Radio->setChecked(slot == 2); } } yubikey-personalization-gui-3.1.24/src/ui/chalresppage.cpp0000664000175000017500000007371712642452141022321 0ustar klasklas/* Copyright (C) 2011-2014 Yubico AB. 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. 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 HOLDER 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. */ #include "chalresppage.h" #include "ui_chalresppage.h" #include "ui/helpbox.h" #include "ui/confirmbox.h" #include "yubikeywriter.h" #include "yubikeyfinder.h" #include "yubikeyutil.h" #include "common.h" #include #include #include #include #include ChalRespPage::ChalRespPage(QWidget *parent) : QStackedWidget(parent), ui(new Ui::ChalRespPage) { ui->setupUi(this); m_ykConfig = 0; m_keyPresent = false; clearState(); //Connect pages connectPages(); //Connect help buttons connectHelpButtons(); //Connect other signals and slots connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)), this, SLOT(keyFound(bool, bool*))); connect(ui->quickResetBtn, SIGNAL(clicked()), this, SLOT(resetQuickPage())); connect(ui->advResetBtn, SIGNAL(clicked()), this, SLOT(resetAdvPage())); connect(ui->advRequireUserInputCheck, SIGNAL(clicked(bool)), this, SLOT(requireInput_clicked(bool))); connect(ui->quickRequireUserInputCheck, SIGNAL(clicked(bool)), this, SLOT(requireInput_clicked(bool))); connect(ui->advHmacVarInputRadio, SIGNAL(clicked()), this, SLOT(hmac_lt64_clicked())); connect(ui->advHmacFixedInputRadio, SIGNAL(clicked()), this, SLOT(hmac_lt64_clicked())); ui->quickResultsWidget->resizeColumnsToContents(); ui->advResultsWidget->resizeColumnsToContents(); loadSettings(); } ChalRespPage::~ChalRespPage() { if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } delete ui; } void ChalRespPage::loadSettings() { QSettings settings; ui->advExportConfigBtn->setVisible(settings.value(SG_EXPORT_PREFERENCE).toBool()); ui->quickExportConfigBtn->setVisible(settings.value(SG_EXPORT_PREFERENCE).toBool()); bool reqInput = settings.value(SG_REQUIRE_INPUT).toBool(); ui->quickRequireUserInputCheck->setChecked(reqInput); ui->advRequireUserInputCheck->setChecked(reqInput); bool hmaclt64 = true; if(settings.contains(SG_HMAC_LT64)) { hmaclt64 = settings.value(SG_HMAC_LT64).toBool(); } ui->advHmacVarInputRadio->setChecked(hmaclt64); ui->advHmacFixedInputRadio->setChecked(!hmaclt64); } /* Common */ void ChalRespPage::connectPages() { //Map the values of the navigation buttons with the indexes of //the stacked widget //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advBackBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickBtn, Page_Quick); mapper->setMapping(ui->quickBackBtn, Page_Base); mapper->setMapping(ui->advBtn, Page_Advanced); mapper->setMapping(ui->advBackBtn, Page_Base); //Connect the mapper to the widget //The mapper will set a value to each button and //set that value to the widget //connect(pageMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentIndex(int))); connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int))); //Set the current page m_currentPage = 0; setCurrentIndex(Page_Base); } void ChalRespPage::setCurrentPage(int pageIndex) { //Page changed... m_currentPage = pageIndex; switch(pageIndex){ case Page_Quick: resetQuickPage(); break; case Page_Advanced: resetAdvPage(); break; } setCurrentIndex(pageIndex); //Clear state m_keysProgrammedCtr = 0; clearState(); } void ChalRespPage::connectHelpButtons() { //Map the values of the help buttons //Create a QMapper QSignalMapper *mapper = new QSignalMapper(this); //Connect the clicked signal with the QSignalMapper connect(ui->quickHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickParamGenSchemeHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickChalRespOptionsHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickPvtIdHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->quickSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advConfigHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advChalRespOptionsHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); connect(ui->advSecretKeyHelpBtn, SIGNAL(clicked()), mapper, SLOT(map())); //Set a value for each button mapper->setMapping(ui->quickHelpBtn, HelpBox::Help_ChalRespYubico); mapper->setMapping(ui->advHelpBtn, HelpBox::Help_ChalRespHmac); mapper->setMapping(ui->quickConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->quickParamGenSchemeHelpBtn, HelpBox::Help_ParameterGeneration); mapper->setMapping(ui->quickChalRespOptionsHelpBtn, HelpBox::Help_ChalRespOption); mapper->setMapping(ui->quickPvtIdHelpBtn, HelpBox::Help_PrivateID); mapper->setMapping(ui->quickSecretKeyHelpBtn, HelpBox::Help_SecretKey); mapper->setMapping(ui->advConfigHelpBtn, HelpBox::Help_ConfigurationSlot); mapper->setMapping(ui->advChalRespOptionsHelpBtn, HelpBox::Help_ChalRespOption); mapper->setMapping(ui->advSecretKeyHelpBtn, HelpBox::Help_SecretKey); //Connect the mapper connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int))); connect(ui->quickConfigProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); connect(ui->advConfigProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int))); } void ChalRespPage::keyFound(bool found, bool* featuresMatrix) { if(found) { if(m_state == State_Initial) { ui->quickWriteConfigBtn->setEnabled(true); ui->quickExportConfigBtn->setEnabled(true); ui->advWriteConfigBtn->setEnabled(true); ui->advExportConfigBtn->setEnabled(true); if(!featuresMatrix[YubiKeyFinder::Feature_MultipleConfigurations]) { ui->quickConfigSlot2Radio->setEnabled(false); ui->advConfigSlot2Radio->setEnabled(false); } else { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); } if(!featuresMatrix[YubiKeyFinder::Feature_ChallengeResponseFixed]) { ui->advHmacFixedInputRadio->setEnabled(false); ui->advHmacVarInputRadio->setChecked(true); } else { ui->advHmacFixedInputRadio->setEnabled(true); } if(!featuresMatrix[YubiKeyFinder::Feature_ChallengeResponse]) { this->setEnabled(false); } } else if(m_state >= State_Programming_Multiple && m_keyPresent == false) { if(this->currentIndex() == Page_Quick) { if(m_state == State_Programming_Multiple) { ui->quickWriteConfigBtn->setEnabled(true); ui->quickExportConfigBtn->setEnabled(true); } else { writeQuickConfig(WRITE_CONFIG); } } else { if(m_state == State_Programming_Multiple) { ui->advWriteConfigBtn->setEnabled(true); ui->advExportConfigBtn->setEnabled(true); } else { writeAdvConfig(WRITE_CONFIG); } } } m_keyPresent = true; } else { ui->quickWriteConfigBtn->setEnabled(false); ui->quickExportConfigBtn->setEnabled(false); ui->advWriteConfigBtn->setEnabled(false); ui->advExportConfigBtn->setEnabled(false); ui->advHmacFixedInputRadio->setEnabled(true); m_keyPresent = false; if(m_state == State_Initial) { ui->quickConfigSlot2Radio->setEnabled(true); ui->advConfigSlot2Radio->setEnabled(true); this->setEnabled(true); } else if(m_state >= State_Programming_Multiple) { if(m_keysProgrammedCtr > 0 && !m_ready) { if(this->currentIndex() == Page_Quick) { changeQuickConfigParams(); } else { changeAdvConfigParams(); } } } } } void ChalRespPage::clearState() { m_state = State_Initial; m_ready = true; if(m_ykConfig != 0) { delete m_ykConfig; m_ykConfig = 0; } } /* Quick Page handling */ void ChalRespPage::resetQuickPage() { if(ui->quickConfigSlot1Radio->isChecked()) { ui->quickConfigSlot2Radio->setChecked(true); } ui->quickConfigParamsCombo->setCurrentIndex(0); ui->quickAutoProgramKeysCheck->setChecked(false); ui->quickProgramMulKeysBox->setChecked(false); ui->quickConfigProtectionBox->reset(); ui->quickPvtIdCheck->setChecked(true); ui->quickPvtIdTxt->clear(); on_quickPvtIdTxt_editingFinished(); ui->quickSecretKeyTxt->clear(); on_quickSecretKeyTxt_editingFinished(); ui->quickStopBtn->setEnabled(false); ui->quickResetBtn->setEnabled(false); } void ChalRespPage::freezeQuickPage(bool freeze) { bool disable = !freeze; ui->quickConfigBox->setEnabled(disable); ui->quickProgramMulKeysBox->setEnabled(disable); ui->quickConfigProtectionBox->setEnabled(disable); ui->quickKeyParamsBox->setEnabled(disable); ui->quickWriteConfigBtn->setEnabled(disable); ui->quickExportConfigBtn->setEnabled(disable); ui->quickStopBtn->setEnabled(!disable); ui->quickResetBtn->setEnabled(disable); ui->quickBackBtn->setEnabled(disable); } void ChalRespPage::on_quickProgramMulKeysBox_clicked(bool checked) { if(checked) { changeQuickConfigParams(); } } void ChalRespPage::on_quickConfigParamsCombo_currentIndexChanged(__attribute__((unused)) int index) { changeQuickConfigParams(); } void ChalRespPage::on_quickPvtIdCheck_stateChanged(int state) { if(ui->quickConfigParamsCombo->currentIndex() != SCHEME_RAND_ALL) { bool disable = (state != 0); ui->quickPvtIdTxt->setEnabled(disable); ui->quickPvtIdGenerateBtn->setEnabled(disable); } } void ChalRespPage::on_quickPvtIdTxt_editingFinished() { QString txt = ui->quickPvtIdTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)UID_SIZE * 2); ui->quickPvtIdTxt->setText(txt); } void ChalRespPage::on_quickPvtIdGenerateBtn_clicked() { ui->quickPvtIdTxt->setText( YubiKeyUtil::generateRandomHex((size_t)UID_SIZE * 2)); } void ChalRespPage::on_quickSecretKeyTxt_editingFinished() { QString txt = ui->quickSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE * 2); ui->quickSecretKeyTxt->setText(txt); } void ChalRespPage::on_quickSecretKeyGenerateBtn_clicked() { ui->quickSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE * 2)); } void ChalRespPage::on_quickWriteConfigBtn_clicked() { emit showStatusMessage(NULL, -1); if(!ui->quickProgramMulKeysBox->isChecked()) { m_keysProgrammedCtr = 0; } //Validate settings if(!validateQuickSettings()) { return; } clearState(); freezeQuickPage(true); // Change state if(ui->quickProgramMulKeysBox->isChecked()) { if(ui->quickAutoProgramKeysCheck->isChecked()) { m_keysProgrammedCtr = 0; m_state = State_Programming_Multiple_Auto; } else { m_state = State_Programming_Multiple; } } else { m_keysProgrammedCtr = 0; m_state = State_Programming; } writeQuickConfig(WRITE_CONFIG); } void ChalRespPage::on_quickExportConfigBtn_clicked() { emit showStatusMessage(NULL, -1); //Validate settings if(!validateQuickSettings()) { return; } clearState(); freezeQuickPage(true); writeQuickConfig(EXPORT_CONFIG); } void ChalRespPage::on_quickStopBtn_clicked() { ui->quickStopBtn->setEnabled(false); m_state = State_Initial; stopQuickConfigWritting(); } void ChalRespPage::stopQuickConfigWritting() { qDebug() << "Stopping quick configuration writing..."; if(m_state >= State_Programming_Multiple) { ui->quickStopBtn->setEnabled(true); return; } m_keysProgrammedCtr = 0; clearState(); freezeQuickPage(false); ui->quickResetBtn->setEnabled(true); } void ChalRespPage::changeQuickConfigParams() { int index = ui->quickConfigParamsCombo->currentIndex(); int idScheme = GEN_SCHEME_FIXED; int secretScheme = GEN_SCHEME_FIXED; switch(index) { case SCHEME_INCR_ID_RAND_SECRET: //Increment IDs only if in programming mode if(m_state != State_Initial) { idScheme = GEN_SCHEME_INCR; } secretScheme = GEN_SCHEME_RAND; break; case SCHEME_RAND_ALL: idScheme = GEN_SCHEME_RAND; secretScheme = GEN_SCHEME_RAND; break; } //Private ID... if(ui->quickPvtIdCheck->isChecked()) { QString pvtIdTxt = YubiKeyUtil::getNextHex( UID_SIZE * 2, ui->quickPvtIdTxt->text(), idScheme); ui->quickPvtIdTxt->setText(pvtIdTxt); } //Secret Key... QString secretKeyTxt = YubiKeyUtil::getNextHex( KEY_SIZE * 2, ui->quickSecretKeyTxt->text(), secretScheme); ui->quickSecretKeyTxt->setText(secretKeyTxt); m_ready = true; } bool ChalRespPage::validateQuickSettings() { if(!(ui->quickConfigSlot1Radio->isChecked() || ui->quickConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->quickConfigSlot1Radio->isChecked() && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } if(!ui->quickConfigProtectionBox->checkConfirm()) { return false; } return true; } void ChalRespPage::writeQuickConfig(int mode) { qDebug() << "Writing configuration..."; //Disable stop button while configuration is being written ui->quickStopBtn->setEnabled(false); //Write configuration if(m_ykConfig != 0) { qDebug() << "ykConfig destroyed"; delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_ChalRespYubico); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->quickConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Private ID... if(ui->quickPvtIdCheck->isChecked()) { m_ykConfig->setPvtIdTxt(ui->quickPvtIdTxt->text()); } //Secret Key... m_ykConfig->setSecretKeyTxt(ui->quickSecretKeyTxt->text()); //Configuration protection... //Current Access Code... m_ykConfig->setCurrentAccessCodeTxt( ui->quickConfigProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->quickConfigProtectionBox->newAccessCode(), ui->quickConfigProtectionBox->newAccMode()); //Challenge-Response Options... m_ykConfig->setChalYubico(true); m_ykConfig->setChalBtnTrig(ui->quickRequireUserInputCheck->isChecked()); if(mode == WRITE_CONFIG) { //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } else if(mode == EXPORT_CONFIG) { //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigExported(bool, const QString &))); YubiKeyWriter::getInstance()->exportConfig(m_ykConfig); } } void ChalRespPage::quickConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigWritten(bool, const QString &))); QString message; if(written) { qDebug() << "Configuration written...."; m_keysProgrammedCtr++; if(m_state == State_Programming){ message = tr(KEY_CONFIGURED).arg(""); } else { message = tr("%1. %2").arg(tr(KEY_CONFIGURED).arg(m_keysProgrammedCtr)).arg(tr(REMOVE_KEY)); } showStatusMessage(message, 0); message = tr(KEY_CONFIGURED).arg(""); } else { qDebug() << "Configuration could not be written...."; message = msg; } quickUpdateResults(written, message); m_ready = false; stopQuickConfigWritting(); } void ChalRespPage::quickConfigExported(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(quickConfigExported(bool, const QString &))); QString message; if(written) { qDebug() << "Configuration exported...."; message = tr(KEY_EXPORTED); showStatusMessage(message, 0); } else { qDebug() << "Configuration could not be exported...."; message = msg; } m_ready = false; stopQuickConfigWritting(); } void ChalRespPage::quickUpdateResults(bool written, const QString &msg) { int row = 0; ui->quickResultsWidget->insertRow(row); //Sr. No.... QTableWidgetItem *srnoItem = new QTableWidgetItem( tr("%1").arg(ui->quickResultsWidget->rowCount())); if(written) { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/tick.png")))); } else { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/cross.png")))); } srnoItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->quickResultsWidget->setItem(row, 0, srnoItem); //Status... QTableWidgetItem *statusItem = new QTableWidgetItem( tr("%1").arg(msg)); statusItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->quickResultsWidget->setItem(row, 1, statusItem); //Timestamp... QDateTime timstamp = QDateTime::currentDateTime(); QTableWidgetItem *timeItem = new QTableWidgetItem( tr("%1").arg(timstamp.toString(Qt::SystemLocaleShortDate))); timeItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->quickResultsWidget->setItem(row, 2, timeItem); ui->quickResultsWidget->resizeColumnsToContents(); ui->quickResultsWidget->resizeRowsToContents(); } /* Advanced Page handling */ void ChalRespPage::resetAdvPage() { if(ui->advConfigSlot1Radio->isChecked()) { ui->advConfigSlot2Radio->setChecked(true); } ui->advConfigParamsCombo->setCurrentIndex(0); ui->advAutoProgramKeysCheck->setChecked(false); ui->advProgramMulKeysBox->setChecked(false); ui->advConfigProtectionBox->reset(); ui->advSecretKeyTxt->clear(); on_advSecretKeyTxt_editingFinished(); ui->advStopBtn->setEnabled(false); ui->advResetBtn->setEnabled(false); } void ChalRespPage::freezeAdvPage(bool freeze) { bool disable = !freeze; ui->advConfigBox->setEnabled(disable); ui->advProgramMulKeysBox->setEnabled(disable); ui->advConfigProtectionBox->setEnabled(disable); ui->advKeyParamsBox->setEnabled(disable); ui->advWriteConfigBtn->setEnabled(disable); ui->advExportConfigBtn->setEnabled(disable); ui->advStopBtn->setEnabled(!disable); ui->advResetBtn->setEnabled(disable); ui->advBackBtn->setEnabled(disable); } void ChalRespPage::on_advProgramMulKeysBox_clicked(bool checked) { if(checked) { changeAdvConfigParams(); } } void ChalRespPage::on_advConfigParamsCombo_currentIndexChanged(__attribute__((unused)) int index) { changeAdvConfigParams(); } void ChalRespPage::on_advSecretKeyTxt_editingFinished() { QString txt = ui->advSecretKeyTxt->text(); YubiKeyUtil::qstrClean(&txt, (size_t)KEY_SIZE_OATH * 2); ui->advSecretKeyTxt->setText(txt); } void ChalRespPage::on_advSecretKeyGenerateBtn_clicked() { ui->advSecretKeyTxt->setText( YubiKeyUtil::generateRandomHex((size_t)KEY_SIZE_OATH * 2)); ui->advSecretKeyTxt->setCursorPosition(0); } void ChalRespPage::on_advWriteConfigBtn_clicked() { emit showStatusMessage(NULL, -1); if(!ui->advProgramMulKeysBox->isChecked()) { m_keysProgrammedCtr = 0; } //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); // Change state if(ui->advProgramMulKeysBox->isChecked()) { if(ui->advAutoProgramKeysCheck->isChecked()) { m_keysProgrammedCtr = 0; m_state = State_Programming_Multiple_Auto; } else { m_state = State_Programming_Multiple; } } else { m_keysProgrammedCtr = 0; m_state = State_Programming; } writeAdvConfig(WRITE_CONFIG); } void ChalRespPage::on_advExportConfigBtn_clicked() { emit showStatusMessage(NULL, -1); //Validate settings if(!validateAdvSettings()) { return; } clearState(); freezeAdvPage(true); writeAdvConfig(EXPORT_CONFIG); } void ChalRespPage::on_advStopBtn_clicked() { ui->advStopBtn->setEnabled(false); m_state = State_Initial; stopAdvConfigWritting(); } void ChalRespPage::stopAdvConfigWritting() { qDebug() << "Stopping adv configuration writing..."; if(m_state >= State_Programming_Multiple) { ui->advStopBtn->setEnabled(true); return; } m_keysProgrammedCtr = 0; clearState(); freezeAdvPage(false); ui->advResetBtn->setEnabled(true); } void ChalRespPage::changeAdvConfigParams() { int index = ui->advConfigParamsCombo->currentIndex(); // else we use a static secret. if(index == SCHEME_INCR_ID_RAND_SECRET) { //Secret Key... QString secretKeyTxt = YubiKeyUtil::getNextHex( KEY_SIZE_OATH * 2, ui->advSecretKeyTxt->text(), GEN_SCHEME_RAND); ui->advSecretKeyTxt->setText(secretKeyTxt); } on_advSecretKeyTxt_editingFinished(); m_ready = true; } bool ChalRespPage::validateAdvSettings() { if(!(ui->advConfigSlot1Radio->isChecked() || ui->advConfigSlot2Radio->isChecked())) { emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1); return false; } QSettings settings; //Check if configuration slot 1 is being programmed if (!settings.value(SG_OVERWRITE_CONF_SLOT1).toBool() && ui->advConfigSlot1Radio->isChecked() && m_keysProgrammedCtr == 0) { //Confirm from client ConfirmBox confirm(this); confirm.setConfirmIndex(ConfirmBox::Confirm_ConfigurationSlot); int ret = confirm.exec(); switch (ret) { case 1: //Yes break; default: //No return false; } } if(!ui->advConfigProtectionBox->checkConfirm()) { return false; } return true; } void ChalRespPage::writeAdvConfig(int mode) { qDebug() << "Writing configuration..."; //Disable stop button while configuration is being written ui->advStopBtn->setEnabled(false); //Write configuration if(m_ykConfig != 0) { qDebug() << "ykConfig destroyed"; delete m_ykConfig; m_ykConfig = 0; } m_ykConfig = new YubiKeyConfig(); //Programming mode... m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_ChalRespHmac); // set serial m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial())); //Configuration slot... int configSlot = 1; if(ui->advConfigSlot2Radio->isChecked()) { configSlot = 2; } m_ykConfig->setConfigSlot(configSlot); //Secret Key... m_ykConfig->setSecretKeyTxt(ui->advSecretKeyTxt->text()); //Configuration protection... m_ykConfig->setCurrentAccessCodeTxt( ui->advConfigProtectionBox->currentAccessCode()); m_ykConfig->setNewAccessCodeTxt( ui->advConfigProtectionBox->newAccessCode(), ui->advConfigProtectionBox->newAccMode()); //Challenge-Response Options... m_ykConfig->setChalHmac(true); m_ykConfig->setHmacLT64(ui->advHmacVarInputRadio->isChecked()); m_ykConfig->setChalBtnTrig(ui->advRequireUserInputCheck->isChecked()); if(mode == WRITE_CONFIG) { //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); YubiKeyWriter::getInstance()->writeConfig(m_ykConfig); } else if(mode == EXPORT_CONFIG) { //Write connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigExported(bool, const QString &))); YubiKeyWriter::getInstance()->exportConfig(m_ykConfig); } } void ChalRespPage::advConfigWritten(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigWritten(bool, const QString &))); QString message; if(written) { qDebug() << "Configuration written...."; m_keysProgrammedCtr++; if(m_state == State_Programming){ message = tr(KEY_CONFIGURED).arg(""); } else { message = tr("%1. %2").arg(tr(KEY_CONFIGURED).arg(m_keysProgrammedCtr)).arg(tr(REMOVE_KEY)); } showStatusMessage(message, 0); message = tr(KEY_CONFIGURED).arg(""); } else { qDebug() << "Configuration could not be written...."; message = msg; } advUpdateResults(written, message); m_ready = false; stopAdvConfigWritting(); } void ChalRespPage::advConfigExported(bool written, const QString &msg) { disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)), this, SLOT(advConfigExported(bool, const QString &))); QString message; if(written) { qDebug() << "Configuration written...."; message = tr(KEY_EXPORTED); showStatusMessage(message, 0); } else { qDebug() << "Configuration could not be exported...."; message = msg; } m_ready = false; stopAdvConfigWritting(); } void ChalRespPage::advUpdateResults(bool written, const QString &msg) { int row = 0; ui->advResultsWidget->insertRow(row); //Sr. No.... QTableWidgetItem *srnoItem = new QTableWidgetItem( tr("%1").arg(ui->advResultsWidget->rowCount())); if(written) { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/tick.png")))); } else { srnoItem->setIcon(QIcon(QPixmap(tr(":/res/images/cross.png")))); } srnoItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 0, srnoItem); //Status... QTableWidgetItem *statusItem = new QTableWidgetItem( tr("%1").arg(msg)); statusItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 1, statusItem); //Timestamp... QDateTime timstamp = QDateTime::currentDateTime(); QTableWidgetItem *timeItem = new QTableWidgetItem( tr("%1").arg(timstamp.toString(Qt::SystemLocaleShortDate))); timeItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); ui->advResultsWidget->setItem(row, 2, timeItem); ui->advResultsWidget->resizeColumnsToContents(); ui->advResultsWidget->resizeRowsToContents(); } void ChalRespPage::requireInput_clicked(bool checked) { QSettings settings; settings.setValue(SG_REQUIRE_INPUT, checked); if(m_currentPage == Page_Quick) { ui->advRequireUserInputCheck->setChecked(checked); } else { ui->quickRequireUserInputCheck->setChecked(checked); } } void ChalRespPage::hmac_lt64_clicked() { QSettings settings; settings.setValue(SG_HMAC_LT64, ui->advHmacVarInputRadio->isChecked()); } void ChalRespPage::setCurrentSlot(int slot) { if(m_currentPage == Page_Advanced) { ui->advConfigSlot1Radio->setChecked(slot == 1); ui->advConfigSlot2Radio->setChecked(slot == 2); } else if(m_currentPage == Page_Quick) { ui->quickConfigSlot1Radio->setChecked(slot == 1); ui->quickConfigSlot2Radio->setChecked(slot == 2); } } yubikey-personalization-gui-3.1.24/src/ui/helpbox.ui0000664000175000017500000000742112642452141021144 0ustar klasklas HelpBox Qt::NonModal 0 0 500 260 0 0 500 100 500 260 Help - YubiKey font: 11px "Verdana"; color: rgb(0, 0, 0); false 10 10 481 241 false font: 11px "Verdana"; QFrame::NoFrame QFrame::Plain QTextEdit::AutoBulletList false <!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:'Verdana'; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> true Qt::Horizontal QDialogButtonBox::Close buttonBox rejected() HelpBox reject() 316 260 286 274 buttonBox accepted() HelpBox accept() 248 254 157 274 yubikey-personalization-gui-3.1.24/src/main.cpp0000664000175000017500000000321312642452141020152 0ustar klasklas/* Copyright (C) 2011-2013 Yubico AB. 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. 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 HOLDER 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. */ #include #include "ui/mainwindow.h" #include "version.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); a.setOrganizationName(VER_COMPANYNAME_STR); a.setOrganizationDomain(VER_COMPANYDOMAIN_STR); a.setApplicationName(VER_PRODUCTNAME_STR); MainWindow w; w.show(); return a.exec(); } yubikey-personalization-gui-3.1.24/.travis.yml0000664000175000017500000000021512642452141020043 0ustar klasklaslanguage: cpp os: - linux - osx compiler: - gcc - clang before_install: ./prepare-travis.sh install: - make all script: make check yubikey-personalization-gui-3.1.24/installer/0000775000175000017500000000000012642452141017731 5ustar klasklasyubikey-personalization-gui-3.1.24/installer/win-nsis/0000775000175000017500000000000012642452141021500 5ustar klasklasyubikey-personalization-gui-3.1.24/installer/win-nsis/ykpers.nsi0000664000175000017500000001303312642452141023530 0ustar klasklas!include "MUI.nsh" ; The name of the installer Name "YubiKey Personalization Tool" ; The file to write OutFile "../../build/release/yubikey-personalization-gui-${YKPERS_VERSION}.exe" ; The default installation directory InstallDir "$PROGRAMFILES\Yubico\YubiKey Personalization Tool" ; Registry key to check for directory (so if you install again, it will ; overwrite the old one automatically) InstallDirRegKey HKLM "Software\Yubico\yubikey-personalization-gui" "Install_Dir" SetCompressor /SOLID lzma ShowInstDetails show Var MUI_TEMP Var STARTMENU_FOLDER Function .onInit # Display splash image. InitPluginsDir File /oname=$PLUGINSDIR\splash.bmp "yubico_logo.bmp" advsplash::show 1000 600 400 0x04025C $PLUGINSDIR\splash Pop $0 Delete $PLUGINSDIR\splash.bmp FunctionEnd ;Interface Settings !define MUI_ABORTWARNING ;-------------------------------- ; Pages !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_DIRECTORY ;Start Menu Folder Page Configuration !define MUI_STARTMENUPAGE_DEFAULTFOLDER "Yubico\YubiKey Personalization Tool" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU" !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Yubico\YubiKey Personalization Tool" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;Languages !insertmacro MUI_LANGUAGE "English" ;-------------------------------- Section "YubiKey Personalization Tool" SectionIn RO SetOutPath $INSTDIR FILE ../../build/release/yubikey-personalization-gui.exe FILE ../../build/release/libjson-c-2.dll FILE ../../build/release/libyubikey-0.dll FILE ../../build/release/libykpers-1-1.dll FILE ../../build/release/Qt5Core.dll FILE ../../build/release/Qt5Gui.dll FILE ../../build/release/Qt5Widgets.dll FILE ../../build/release/libgcc_s_dw2-1.dll FILE ../../build/release/libwinpthread-1.dll FILE ../../build/release/libstdc++-6.dll FILE ../../build/release/icuin54.dll FILE ../../build/release/icuuc54.dll FILE ../../build/release/icudt54.dll SetOutPath $INSTDIR\licenses FILE /r ../../build/release/licenses/ SetOutPath $INSTDIR\imageformats FILE ../../build/release/qmng.dll SetOutPath $INSTDIR\platforms FILE ../../build/release/qwindows.dll SectionEnd Var MYTMP # Last section is a hidden one. Section WriteUninstaller "$INSTDIR\uninstall.exe" ; Write the installation path into the registry WriteRegStr HKLM "Software\Yubico\yubikey-personalization-gui" "Install_Dir" "$INSTDIR" # Windows Add/Remove Programs support StrCpy $MYTMP "Software\Microsoft\Windows\CurrentVersion\Uninstall\yubikey-personalization-gui" WriteRegStr HKLM $MYTMP "DisplayName" "YubiKey Personalization Tool" WriteRegExpandStr HKLM $MYTMP "UninstallString" '"$INSTDIR\uninstall.exe"' WriteRegExpandStr HKLM $MYTMP "InstallLocation" "$INSTDIR" WriteRegStr HKLM $MYTMP "DisplayVersion" "${YKPERS_VERSION}" WriteRegStr HKLM $MYTMP "Publisher" "Yubico AB" WriteRegStr HKLM $MYTMP "URLInfoAbout" "http://www.yubico.com" WriteRegDWORD HKLM $MYTMP "NoModify" "1" WriteRegDWORD HKLM $MYTMP "NoRepair" "1" !insertmacro MUI_STARTMENU_WRITE_BEGIN Application ;Create shortcuts SetShellVarContext all SetOutPath "$SMPROGRAMS\$STARTMENU_FOLDER" CreateShortCut "YubiKey Personalization Tool.lnk" "$INSTDIR\yubikey-personalization-gui.exe" "" "$INSTDIR\yubikey-personalization-gui.exe" 0 CreateShortCut "Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 1 WriteINIStr "$SMPROGRAMS\$STARTMENU_FOLDER\Yubico Web page.url" \ "InternetShortcut" "URL" "http://www.yubico.com/" !insertmacro MUI_STARTMENU_WRITE_END SectionEnd ; Uninstaller Section "Uninstall" ; Remove registry keys DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\yubikey-personalization-gui" DeleteRegKey HKLM "Software\Yubico\yubikey-personalization-gui" DELETE "$INSTDIR\yubikey-personalization-gui.exe" DELETE "$INSTDIR\libjson-c-2.dll" DELETE "$INSTDIR\libyubikey-0.dll" DELETE "$INSTDIR\libykpers-1-1.dll" DELETE "$INSTDIR\Qt5Core.dll" DELETE "$INSTDIR\Qt5Gui.dll" DELETE "$INSTDIR\Qt5Widgets.dll" DELETE "$INSTDIR\libgcc_s_dw2-1.dll" DELETE "$INSTDIR\libwinpthread-1.dll" DELETE "$INSTDIR\libstdc++-6.dll" DELETE "$INSTDIR\icuin54.dll" DELETE "$INSTDIR\icuuc54.dll" DELETE "$INSTDIR\icudt54.dll" DELETE "$INSTDIR\licenses\*" DELETE "$INSTDIR\imageformats\qmng.dll" DELETE "$INSTDIR\platforms\qwindows.dll" RMDir "$INSTDIR\licenses" RMDir "$INSTDIR\imageformats" RMDir "$INSTDIR\accessible" RMDir "$INSTDIR\platforms" ; Remove uninstaller Delete $INSTDIR\uninstall.exe ; Remove shortcuts, if any !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP SetShellVarContext all Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Yubico Web page.url" Delete "$SMPROGRAMS\$MUI_TEMP\YubiKey Personalization Tool.lnk" ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" startMenuDeleteLoop: ClearErrors RMDir $MUI_TEMP GetFullPathName $MUI_TEMP "$MUI_TEMP\.." IfErrors startMenuDeleteLoopDone StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop startMenuDeleteLoopDone: DeleteRegKey /ifempty HKCU "Software\Yubico\yubikey-personalization-gui" ; Remove directories used RMDir "$INSTDIR" SectionEnd yubikey-personalization-gui-3.1.24/installer/win-nsis/yubico_logo.bmp0000664000175000017500000040173012642452141024517 0ustar klasklasBM6(n  ۃݿ̛˛˛˛˛˛˛˛˛˛˛˛˛˛˛˛˚ˌ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚhֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ޿<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚbԮ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚIΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚxڹ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚzۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚVѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚm׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚJΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚMϣ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ߱קѥЦѫӹtٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚk׳}ܼYҩ=ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛^ӫܽݩҘʌÂݾ}ܼ{ۻ}ܼݿŠζל̇uڸ^ӬE̟=ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚB̝Xҩtٷ͸הzۺUѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚC̞hֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢ۋÛ˛˛˛˛˛˛˛˛˛˛˛˛˛˛˛ˈۋÛ˛˛˛˛˛˛˛˛˛˛˛˛˛˛ˎįUѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚRХĜ̝̝̝̝̝̝̝̝̝̝̝̝̝̝̝̑ƮuڸJΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ=ʚXҩ\ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞{ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ=ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ=ʚQХ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ҫ]ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚMϣ~ܼdկ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚIΡhֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚIΡE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛yۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܽ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚIΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫxڹ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚQХTЦ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢yۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXѨNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚeկ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫl׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ_Ԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚhֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܽyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>ʛ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ\ӫQХ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϣ{ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫOϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ}ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>ʛ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚو<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚl׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚH͠{ۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛?˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ[Ҫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸhֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ~ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ~ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϣ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTЦ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܽ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˝H͠G͠>˛<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚnش<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛rٶ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛D̞G͠G͠A˝<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫxڹ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˝jֲݾÐƏʼnݾjֲD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸrٶ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚJΡnش<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚQХ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTЦ~ܼwڸG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚUѧkײ?˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˝wڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚiֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚUѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚWѨ¬Զٻؙܻܳk׳F͟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻC̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚOϤD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ]ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ_Ԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚsٷIΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ{ۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚcծ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚcծ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚOϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXҩ<ʚ<ʚ<ʚ<ʚ<ʚwڸvڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚIΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ޿<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܼ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ\ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚnش<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚF͟zۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚfհ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>ʛ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚuڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ҫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚOϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ҫfհ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾzۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫWѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚJΡ<ʚ<ʚݿ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTЦ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚbԮ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚsٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ}ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚH͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟H͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚrٶaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚC̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚoص<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚMϣyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚSЦ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫxڹ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚSЦ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTЦB̝<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚkײyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ[Ҫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚkײ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚG͠Vѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚPϤaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚvڸyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚpص<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚgְ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ{ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXҩQХ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚhֱaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚiֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚxڹA˝<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚRХbԮ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ\ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚG͠aԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚYҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚMϣ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚcծ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ}ܼpص<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ`ԭk׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚJΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚdկ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚzۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚgְaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚJΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ~ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ]ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚUѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚuڸoص<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚIΡ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ~ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟aԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ@˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚUѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚeկD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚrٶ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚL΢G͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ@˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˜Vѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚzۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚcծaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚhֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫPϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚxڹ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫeկ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ]ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ=ʚXҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩK΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ~ܼaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ{ۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ=ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞aԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚVѧ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTЦ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚuٷvڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ>˛<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚzۺNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚvڸRХ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚZҩaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫk׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚzۺ<ʚ<ʚvڸݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚcծ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚRХ^ӫ<ʚ<ʚ<ʚvڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚF͟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚUѧ[Ҫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܽaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚl׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݿ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚuڸD̞<ʚ<ʚ<ʚ<ʚwڸA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ_Ԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ҫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸܽ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚxڹ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܼ{ۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>ʛ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚgְG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚk׳@˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚbԮ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚQХaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚgְK΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ{ۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚC̞RХ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸiֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚL΢<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚiֱ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚMϣnشǩҬԫӡ~ܼWѨ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ@˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚB̝uٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ\ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚuٷaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϣ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚF͟aԭrٶ{ۺܼ|ۻuٷhֱTЦ=ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢}ܼوZҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚnش=ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫk׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸA˝<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚl׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚOϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫPϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ]ӫF͟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ@˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚTЦaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚC̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚܽD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚfհ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ{ۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ`ԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚݾ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚk׳aԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸsٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚXҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚqصnش<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫNϣ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸvڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ|ۻ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫuڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚvڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚF͟G͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢aԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚuٷD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚqص<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚgְ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫ>˛<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚPϤ~ܼ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞m׳<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ҫ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭaԭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚyۺ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚYҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚNϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^ӫD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷgְ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ=ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ^Ӭ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚYҩ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚD̞<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ[Ҫxڹ>˛<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚoصݾ?˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚWѨ¢ϠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΒǷǟ͠ΠΠΠΠΠΠΠΠΠΠΠΠΠΠ΢ϊהȠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΏݑƠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΏwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚvڸG͠<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚaԭƟ͠ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΕȰ݅eկE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>ʛ[Ӫ|ۻvڸPϤ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ>˛^Ӭwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚqصYҩMϣC̞<ʚ<ʚ>ʛG͠SЦbԮµ֕oص^ӬTѧK΢C̞=ʚ<ʚ<ʚ@˜G͠OϤYҩeկݾѾՈbԮRХA˜<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚH͠Xҩoص̼wڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ߼ܹۺ۾wڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚK΢<ʚB̝B̝B̝B̝B̝B̝B̝B̝B̝B̝B̝B̝B̝B̝B̝B̝A˜<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚwڸ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚtٷ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚE̟<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ<ʚ܍ĝ̝̝̝̝̝̝̝̝̝̝̝̝̝̝̝̌ϕȝ̝̝̝̝̝̝̝̝̝̝̝̝̝̝̝̜̎yubikey-personalization-gui-3.1.24/BLURB0000664000175000017500000000047512642452141016533 0ustar klasklasAuthor: Yubico Basename: yubikey-personalization-gui Homepage: http://opensource.yubico.com/yubikey-personalization-gui/ License: BSD-2-Clause Name: yubikey-personalization-gui Project: yubikey-personalization-gui Summary: Qt based Cross-Platform YubiKey Personalization Tool Yubico-Category: YubiKey Personalization yubikey-personalization-gui-3.1.24/resources/0000775000175000017500000000000012642452141017746 5ustar klasklasyubikey-personalization-gui-3.1.24/resources/resources.qrc0000664000175000017500000000146412642452141022474 0ustar klasklas images/cross.png images/question.png images/recommend.png images/right.png images/tick.png win/Yubico.ico images/clipboard.png images/blank.png images/logo.png images/v1-3-not-animated.png images/V2-0-2-1-animated.mng images/v2-2-animated.mng images/v2-3-animated.mng images/neo_transparent.png images/neo_production.png images/neo_production_33.mng images/plus.mng images/edge.mng yubikey-personalization-gui-3.1.24/resources/lin/0000775000175000017500000000000012642452141020530 5ustar klasklasyubikey-personalization-gui-3.1.24/resources/lin/yubikey-personalization-gui.desktop0000664000175000017500000000047312642452141027611 0ustar klasklas[Desktop Entry] Name=YubiKey Personalization Tool GenericName=YubiKey Personalization Tool Comment=Graphical interface for programing a YubiKey Exec=yubikey-personalization-gui Icon=yubikey-personalization-gui StartupNotify=true Terminal=false Type=Application Categories=Utility; Keywords=YubiKey;Personalization; yubikey-personalization-gui-3.1.24/resources/lin/yubikey-personalization-gui.10000664000175000017500000000405012642452141026273 0ustar klasklas.\" Copyright (c) 2012-2013 Yubico AB .\" All rights reserved. .\" .\" 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. .\" .\" 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. .\" .\" The following commands are required for all man pages. .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yubikey-personalization-gui "1" "June 2012" "yubikey-personalization-gui" .SH NAME yubikey-personalization-gui - personalize YubiKey OTP tokens .SH SYNOPSIS .B yubikey-personalization-gui .SH DESCRIPTION Graphical interface for configuration fo YubiKey OTP tokens. Help is available from within the program. .SH BUGS Report yubikey-personalization-gui bugs in .URL "https://github.com/Yubico/yubikey-personalization-gui/issues" "the issue tracker" .SH "SEE ALSO" YubiKeys can be obtained from .URL "http://www.yubico.com/" "Yubico" "." yubikey-personalization-gui-3.1.24/resources/lin/yubikey-personalization-gui.png0000664000175000017500000010711112642452141026721 0ustar klasklasPNG  IHDR>a pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-@riTXtXML:com.adobe.xmp Adobe Photoshop CC 2015 (Macintosh) 2015-12-28T15:09:11-08:00 2015-12-28T15:11:43-08:00 2015-12-28T15:11:43-08:00 image/png xmp.iid:2c7e0620-4e08-4b13-90e2-058b1bbfa0a2 adobe:docid:photoshop:c14c4edd-ee46-1178-b2b3-e9b1abea663f xmp.did:639a6b14-8f51-4518-ace3-55dc9a3b695d created xmp.iid:639a6b14-8f51-4518-ace3-55dc9a3b695d 2015-12-28T15:09:11-08:00 Adobe Photoshop CC 2015 (Macintosh) saved xmp.iid:e1c7722f-b168-40cc-911f-651ae1af4157 2015-12-28T15:11:43-08:00 Adobe Photoshop CC 2015 (Macintosh) / converted from application/vnd.adobe.photoshop to image/png derived converted from application/vnd.adobe.photoshop to image/png saved xmp.iid:2c7e0620-4e08-4b13-90e2-058b1bbfa0a2 2015-12-28T15:11:43-08:00 Adobe Photoshop CC 2015 (Macintosh) / xmp.iid:e1c7722f-b168-40cc-911f-651ae1af4157 xmp.did:639a6b14-8f51-4518-ace3-55dc9a3b695d xmp.did:639a6b14-8f51-4518-ace3-55dc9a3b695d adobe:docid:photoshop:2e4a2bae-e8cb-1178-b2ce-869477b6cf65 3 sRGB IEC61966-2.1 1 720000/10000 720000/10000 2 1 128 128 m cHRMz%u0`:o_FBIDATxw|]Yu/{v{Wq؞ޙzx R!WI <{d І6^<ݲni?,YW䱌 9U=gN>T.8Hd toܒ@0*9PLE+nHB[—4~)  |B͠Q &$tRBuIT "\)(I J^Ps+jR V.rH 0w%%p+B(0F`XJS.8$t0,XƀSHpGvnB)F+ Rcj9;t&6]͟9x š.&\MHpŋTɦd;B RP1;N!D@Sw` E{p!p\)~+K/<{=J&wgj - x3՚F.% 1R=3oQWB"TDݿOjDt)N |@(TӁ|Tw .J*fH{(MT#KJҠ& f KHzUa$QRD ]c5w+He]'G psQhP0+ θ!\Wa tv1F>”UߕV*-d N2%Y u)<"<@`T덦n8eq]OͨBLM(!?z$CnEQҹ!8?=1\[V,`S'zi/BFP# !tvl羖_J*PJP(LqBݛ#7:%,AϩPUIN|iDrF q\E\:}PO!l6BHwq PJ [9$DF ,ZD1ЬZ}n.q(!v^˚ࣔoMG8W0̟P U3 (iUR"핝4!}| (AH_iPA##VX =-a5T|*`<,֏zӒ;ga,1"(tfK`*@.a % Sh8om`~$w}ԙNB@|!tQtz6d˺߼a-r}:{rA0j,X325 ƾF&?vpxZNIP/cʓ8KU*yߖ=fYzZ ,+j"?732 jHk~ō_#F3RxQI־IVuWuPH6_ȯ .Ozn5wEן;>WS67gzrH›L`A0k ܰ7Ug#z &\D3Fӷ_<>.I@^OJĀX@9axɰGNjQ0^ދ鼵F ;z^L XNN % =~ա#h0^WJ)s<ťP D+@AǍ^Rы=dg%֙hStsm',_\ڠD[9@?`85gm˔RSYJ#ktqזsDmnx}ݦ n/}ƼNh:Ԩ`\?m1D>^O]󋽐5$Whh/b}w2A¶_\j6G ;]"a+m>-/<0R0O-v^$@qhoڂHe9y_:=z2ߴPG/aZ(!$”1b~k`A3Ȋ=]쒷t&flIQ%t8%Z\Pb:dpHrΤ[nf/eA)c5FV~2J\IJ'QM|yJS+NByj]H3Ms߸?-m/ºIpnؔw% [LmS<E%[lF%Z!AP r逜d;6SkҸw< x[}];&\&D|YY:`AaʃJC @ %عr%D~C/0勲\"PJ̺c]C<܈p?E_2L<oX};MEt.(#D'a: T΀[3vGL0FeTVD4i loG NY@.50Qޭzz#_)5IP*AEۯQSS}G~\{ v\ۈPD;%LUսo]yw}_Tf( C{xZ?qU T L)#Xjl8~A H0j`reD-=|s3c:/E$?' @/>,/%"+7ۑʄ.}>(#(!r6JviU-X:[ dao|DCQ{/#&ޝ3eS,h(HcW\q璮L'?7*y;ܫ򭲘/hA# BO==Ao 1[f}㍊B{q WKb;^V!u[CR_(HLU}[&x++[^0FjHEqIvf+Ht_hϯ3S  crƦ}~Ofd@!\ZcDͿ]/@˚;6E~XB#^Q_yC_Y4guٱ+ڵk?S9V*kDC[|P:~^!,25!9tD/b CZşXEw}; 矫گj@^}ObͶ(#/{蒘7 Il ?QC;v.]0{ο/f=Fľ; ,+v= )gЙpU/]K+bۏmmõ77.S[?dGot@Sd  Zzwpk ,*xQTxD8PLR6@ʇҨqNGb#~>[?$V$`,O\BӧCg1eF&Mj8p^Q/fsYb yqiGOgȊ-u|W xtNݷTJ͎8qM ;ȍ{D?b/6+yXA"OZDHoĔ܅G_:PJcEE T@-~3=oii+m?"N1rߔzoinNF\ 2r}8="%:>N#I^ x<q "ǗL\T&vҋmy]ғM]O;GI+ԾCmr.s] 8'?%_ʁ!o-M@iYKA-_TV^!$¡(pl|3F@OP5)́Đ;흳u\lG1 RWx0`P͛.L\66@)!0oTj"1е!tU4m\V.𺺃M X 9&f5E gN=O?T(^vU-")UAi jN46i7˜39(7z񠄄m h~K)a(ƆHC Jb5 PT..}`Lai? e5KE$4LIkmi(nnPT Qpp*4ifV)}4bN~"AşB"ojzi?HzPS+BV9 {?3S-I)P o| >{ԒZ:Wʂ3XoBPh .|{i0Hu@m}wc,;Ȅ0՗z4u1W[cأ^g6X?>Bh>%јn9=qs05^T\q;2u {cyH+ 4SR/"gs2XLڵbY9@8c(~w#]:_s~݁,Q<X԰;csnq,/iil6ѻ-6f{'П72\d-(zc+/"K#{OrO` Zsܾ'W/ $ziG$_=Ix55v! H]5P|E⊠3 Ԉ(oPJ,l )w'UVu@o*$~|H#S{!^FHuKh,$|MW_ xdw` R Qd\c`&@.f8|mMYB<TqG vU3gc0iJzW1lb lQM~ˈ[ͧkߗX3r鄀N9@rynyj{ \G~A`ro6v"B{T=u&J3 |s@1hoY\_.tZ (J0c .m۩P.5I^WA>A0a)1gQPH)1Tx&6x:a' $@c flم3%--P7.qq Z69$@{,4vXPfꖄ )L{HMQ<A#({㧐.&SaFpbNڻw }I(Yb s7_ZJLM]]8X}3,, Z%~= ( F` EE3J5Шx<s84<=sjup>J_pgvV!)q{FHp 3DXT@.:~ 4 th%:|kuAr @%DF(\qP:l5U0B,B$8$ C_p2 _-dbQO#lm}2ڪ7#7]V̠Z*"j2Qsh#fvYK1 \?(  T@cG^X`:0\xSCEO|&qajot!¶3.)VU"SЭp2zg,u( Q)Rqz%"0pz l5ŕ%f(@8:̸#Ob?}vZ^㧟ZE8 `v+65t )_x3pm\D(Ѵv *JZA軲 @@TH d.9ʈ]08?`#@81I daLAI CPO@J>ثJLI3S=ʤ e;Zg>=0} Шi@JU@OҪ?DU[/Xg!9jK (0:#O$!#g˜'+Q,QiĆ흵pjIJ@$': r Fz*hA$;"͚'+<4"F#p_xduk<+yȄcҏ9!RwjA( <{`W_?p\*2;op{%TsOA(j,w,-IH' FXP!a:7R`k?)%,{Ÿ BJhfjջt4]cŗ@&: 8.ԓap(ҝp90mPYLn}J-d)P˜>eV_>=ͣDv>~ A3*DLyM 3t_IvVhQOn;R'fł'[] ՍBxٸ(:i/I H0?>0u`ϱ'Qt!XQ 9'J{ؼs?@_OG :[)Ŕ_SLS FT}Oi)%Qi-iY!9JN,I៓GjG[<ރU''Dj?B!04FjG\Tx-5hmiCP8>4-{2G3B= ҧڰP ӕTK6JR( 76<px|RzM$z"W@՘;FI`|b/ g^zc3,Cd3p5aӵ5?_\Bhlh'T/ص"hsmٓzC}>[}z:ERRU)k hT..O83Nj= >-sL[q2ShHvoC/JR-R~an 'ux+PǪڮ5Z Y>caQA Ȃ?eo8>P RE?5W-( F;†s;F8 N@\9ˑd BfC3Leۓ\W_Ԛ-/f('+$  ((I@e{a6lٹϪ@_u<X4.nNnӒ-zr(cBJ_胗'?ǹ9C*`*)>4Ñ⃈-'%(%޼IPLuhin(Vd0QOu)HTh: EJsdJS~Eu!u8 FUc GxsB2pQ %;/O? TOg7b{fɫWo@4굅%hq3Veȃ*9%Or][B^ J t&ηfݩI P˸^',.AEOz](h.ДB.dU"wA%ap@=)Ä[wy AY0*T| 6FB3ќ€-t8( Ҁwn=]^BjAGR0oĬ8_O3(bǐ;yWWh~n>fvM-Q!O> %ѴAC-x ,5WRN Q 2qb`"uO+B83F4R#<Eu{KlnX%"ش} ?`tD)bb5 ,)eg bR7swƧG@APBqR&f-,*6)%o* ՜:b?; AגX MM(g<[?}^,d#"(8 tr^t4M|'RpH5ADU |3rfR']-& Dj?tc"7i `@9J)¤?cE +jCQȻG !δ?v({Y.AsixoݿDޛFKs'zv"[}HcĠiߜ[S0L,h;7F HBg!ATiQ gPJy/A[_x@Ia.Xf5_j`eb4驙QgsUioM}\r AY1ig?/𛠑Q5Ze۰aK/ @˿4xrZ E)Aw/\F|O |qh 0x2O'+#<$E?64M\]Gp@XؓD߆.JKTG3RwaP k+D1|}h(4zI#"WeBГ%$" 2 Twvuy‘]d —0f&Q)h@PPR* SaIJߞ3./@#:@u= w\ehjwSB#|CA`KSc6CB{ |hiC7@q(%a8tKYWz9"ދХ(cvuk?Wy6燌 qg͞'D7L {GBImA!@=`Dgv lbb/ Z2 ?Wh$;:ձr )5Z{w$jgJs3iCGCGZfέ(1Ha:Y˃.=biC( .hXV/+s$X"H\{4 w\<ͨN#) HFCާ*ߵN&,go!=g8RZZ61s;F"ԎuQ(]?$2f>xꥻY9kaOB!ax⃹ 1{M1=⣜dуFV+Bfoygܳ8pHƤ[ k4l>\MSהT3,r{ w 01*Ya# Ҙv{+cFgJ q Ih4S?gciphv^SJd-{IqSe7G8)R:v?YK󉌆;QUY Uy7Iiu mɯӜ; ,?C{ҵ+/_KY?g3dY'Y^E\EhtoJ*FnX@)+.|=֠AŤ@9xq_eHKOs&)<)gzꔈO-"Be$;@UOt7^<77"uH68{J[ ZSU;T(Ϲ1bnɀP>Vyih?fxigoS+IAM)c[ߍB!rU@ }guOU=gQ$^;-njex%]#f!]jJ@Qb ~ Fp!LCӇ-)=ғ-~Uhbgly] 2m]>hh=~I<}ƶmhdb^@E]O0OC ^+7L9zgHb1)!iP6}<\3p[G&96p6o0 s?P(9YV˽شO!{~O33:}2 M_h[S3X.D_J*3WK9} `"8nw[OH!n-;;C 8YHH0D$ɿr a40B@KaُÅ[Oac-G(_KgM'V &gM? 7]-$'~cΞ(h@,~ cb Neh?: }cb0%@Dcf(X$9}&u8Mr(~;t:f~Б^{C_5T7R $nG"dSSMm5SJ'?D&/vnܣ֍?|mLeCėݏܲi+{ T |d7[oWUɥ]  q^S5hKptp=;_?!Ԧ$0Z3~1Gfv4'Wq'׍z-9|oo\wʒA$B@KW.hHt`jw5P XoxfWF_ gn~3fp m>|ʏ$[scP 2ZLAW7tk[If JNq|2ʃ 0x 6nA\Y%G/|ݛZߵl"HBCTmX?|mBR44~g+s@9ۓRG>?CT^gxT*Eq@-8п>d'ޘh=dۯlF@)WR ӥ#Aod&W Ķ@hX<;SI| k:+v ;]5O@62ާw*ЄB.㣥Yvpψ{.y7Yn!/@p^5WCϵZr^}~X]Uftm dX#>#& w~uY.fn'm0.$5mSx |^7X]o4Avo=掌9fA!W9Rn~l'/i-ci nEN_}(ȤnjSҷfylF0=;GkK냿 }O-ml$tݟ\ۊLIݤ $%j }oUsx5^Y)EQ84|pC[4;@Ћ&~~W P>}-lou1͈mʟvY,SX=:/_ H h ֭YDk+j_T_e.5Eƥ,zohl g^hL5a4~O)AMp (׽`]9c?|40XxֹohhF󱌚կ®BG>$3 DhJ;(|?R~;W/q]"DFEw\wWu LN׵RJJFj@P.y>/w=h')4tp+_{fZ;SX2XtP%%&cxܭv͎`[vWg/^Vw7nlS(>}~JB(:C564v]W$- G~i+]kSM>%@4Pʉ?}b˴ܸX ȡw Fi<B)M __\N'+!2k`_ocYÂ+ M냿G{zju%t `X2l˧~@(Ř@!0LTE*+ذn>46B/r`A8ӀT{v[%-u#8R O{_cm5o[*#XU+b M=C}-ӷvTO}} @J794͟aFܳ8(C,/J]mJxD;=cd11C`n1 $,5X*?x3ܨ{^sCH6(}Hi 6_|wv36A0|Ѕwo0{in_PO+N{U\}^6 RqNs?oW$&s3lVGn1fnQͩ.hNtsѹтSj*H|W!զ#e~mWpw@pto>e 0fԪ@ACaJL=-k.pI-7ΫM6sבiwv7MsLRv@B,R/xnB4GQ-fP.A3'hI ߑ߽]}h[Yω{ -kM(_||oO*uzNi3 PLfyko仇9pxF@4]#"?b˷2畿Ev*O'rՑ,JђYg+9,C EpmW0|Y^!J"dőe:p/^&I=+B8A{߭Kw/ t} aF81߼&>ڭ]Gy,I2B)=ۚdA)H(=!cmĮBA; D_]`ĨЙt xF[73|ӎ֑ۛ-&c˺^ F{KZ< +=fVN$&K_#{~ _H qdգЩC}b(k0<8^|ћ.iJ\:~9L/S-V (Uү1IH韢$̛{ @0# #Ńw=CG h#a l5ߤ`Ӏߌ}_)CvmT tiGItn}ϴ_=9!?ΡdSp*L o+15Vd_}OT;;Ħ5ƺ Hsj-LvK|Ά U3Z]F FA3SהPPSQ{վիi҉&lx.R-&R-a NEu*v M+#3;Z-˰[b m5U ;?x}l-Vph բj2]L\vv%NƵ=~Ǿ 1EOVcmߊT/I:H"D5FR ~{uzh$iuŵݲGd-G_ /a`dsF#qڋTcѴQ8^%G<:<=ө*$Gt Q`!Dl9;5m)}+HѼDnܯoxWmIu-0L/J ;4$~_I~m񑟨滟3`:)px6xm|gt81za0Lê.ʪt/{3eK!5Qo){ 8%)~[w}e+CNS F0Oԙg‘4pJ##.q}e?ԾJG3|(XYBHs\[,(*V+Qkæyù=y(Nn3P m[_NF43ѨW?~?s:3/N OzH&+ w[K NYUmzgbyVY{$u ^; {0n\0JG?[ P TRA9/01!d5[ u[pIxU UΣv)+$C4w%w9pOU|`t5lԱg6roR xJ%;7_ve᫻6[[ V(Ns%9 f^ۊTf" `{ }OC<_d*+I)ud0;#2@I$G(Ӷ΍֎/^#s[Ո2 ,a5ޟT " DXA+`%(Nr9z{<տ~u:,dtLK:;* Px Za-I7v[ϱum3֤5=@iIQs_BJnIjU-k;g'cn- FU,͘e?O, 3̠JARNK%huZdޔlѻ-z{4B1 iиQ̑(ʻeE8%1~lj;<=G?x2KAx LI8Π餤 68'k#5$[QT*(AP7i ҈ a+DsnVPmw+vYv+UdYHU u(+BdlZҟKYy5w 6 r#8fD)PYAT!H-K0bFLR  c #D4E8AC", ", c #BFDD86", "' c #A6D056", ") c #9DCC45", "! c #A5CF52", "~ c #A3CE51", "{ c #A6D152", "] c #A1CD4C", "^ c #D0E6A5", "/ c #FDFEFC", "( c #FFFFFF", "_ c #EEEEEC", ": c #96C240", "< c #B4D870", "[ c #F0F7E3", "} c #C2DE8A", "| c #9DCB43", "1 c #A7D352", "2 c #A5D152", "3 c #9FCC47", "4 c #C5E091", "5 c #F3F3F2", "6 c #AED06B", "7 c #C5E090", "8 c #F8FBF2", "9 c #B2D66B", "0 c #A2CE4D", "a c #A4CE51", "b c #A8D453", "c c #A1CD4B", "d c #E1EFC4", "e c #C8E397", "f c #A4CF50", "g c #ABD954", "h c #A7D452", "i c #A0CD4A", "j c #A5D053", "k c #9EC453", "l c #F8F7F8", "m c #EEF1E7", "n c #7C9E39", "o c #A5D14F", "p c #A2CE4E", "q c #A8D552", "r c #DDEDC0", "s c #B9DA7A", "t c #9FCD46", "u c #DFECC7", "v c #C0D0A2", "w c #A0D042", "x c #CFE5A4", "y c #C9E399", "z c #A3CF50", "A c #A5CF53", "B c #B8DA79", "C c #E9F3D5", "D c #B0D566", "E c #ACD461", "F c #ACD45F", "G c #D8E6BB", "H c #A6D055", "I c #ABD658", "J c #E3E3E3", "K c #E8F2D3", "L c #AAD25D", "M c #9DCB44", "N c #FBFDF8", "O c #CEE5A1", "P c #A8CA66", "Q c #DAEBB8", "R c #A3CE4F", "S c #97B658", "T c #FAF8FE", "U c #E9F3D7", "V c #9FCD47", "W c #C3DF8C", "X c #FBFDF7", "Y c #9CCB42", "Z c #9FCE43", "` c #ECECEA", " . c #B5D872", ".. c #A4D04D", "+. c #B3BD9D", "@. c #ADD067", "#. c #A2CC4F", "$. c #9DCA43", "%. c #EEF6E0", "&. c #B8D977", "*. c #C4D899", "=. c #FBFDF9", "-. c #9CCA41", ";. c #A3CE50", ">. c #A2CD4F", ",. c #9CC649", "'. c #E1DCE9", "). c #D1DFB5", "!. c #A4CF4E", "~. c #A9D651", "{. c #A1CC4D", "]. c #A0CB4B", "^. c #FCFCFC", "/. c #FBFBFB", "(. c #E1EEC6", "_. c #A1CE4B", ":. c #A0C753", "<. c #FFFDFF", "[. c #D3E7AA", "}. c #A1CC4E", "|. c #A0CA4D", "1. c #9DB174", "2. c #F6F5F8", "3. c #95C33B", "4. c #A3CE4E", "5. c #9FCA4C", "6. c #A0CA4C", "7. c #B6D778", "8. c #FAF9FD", "9. c #F8F8F8", "0. c #FEFCFF", "a. c #A2D049", "b. c #DCE2CE", "c. c #FDFAFF", "d. c #ADD363", "e. c #A0CB4C", "f. c #9FC94B", "g. c #9ECD42", "h. c #C6C4C7", "i. c #97BC4E", "j. c #9EC94B", "k. c #9BC44A", "l. c #9BC548", "m. c #9EC94A", "n. c #C5DD94", "o. c #FBFBFC", "p. c #F4F4F4", "q. c #C9E199", "r. c #B6D083", "s. c #F2F5EC", "t. c #97C63C", "u. c #9DC84A", "v. c #9CC648", "w. c #8EAB53", "x. c #F6F5F9", "y. c #F3F3F3", "z. c #FFFEFF", "A. c #A8C56E", "B. c #99C348", "C. c #98C246", "D. c #9BC647", "E. c #94C03F", "F. c #7BA22D", "G. c #AEC580", "H. c #F0F0F1", "I. c #F0F0F0", "J. c #EEEFE7", "K. c #9CCB41", "L. c #A1CB4D", "M. c #97C340", "N. c #C9DAA3", "O. c #9DC749", "P. c #9BC547", "Q. c #9AC742", "R. c #B0B89E", "S. c #F2F2F2", "T. c #FBF9FF", "U. c #6B931B", "V. c #7CA42D", "W. c #8DB43E", "X. c #98C247", "Y. c #96C144", "Z. c #9AC446", "`. c #9CC64D", " + c #A0C653", ".+ c #C2D796", "++ c #EBECEC", "@+ c #ECECEC", "#+ c #EFEDF3", "$+ c #B1D36D", "%+ c #9DC849", "&+ c #99C345", "*+ c #98C244", "=+ c #8FB83F", "-+ c #DBD6E2", ";+ c #F4F2F9", ">+ c #8DB342", ",+ c #9FC653", "'+ c #9CC64A", ")+ c #99C445", "!+ c #96BF45", "~+ c #95BF43", "{+ c #BED48E", "]+ c #EFECF5", "^+ c #ECEAEF", "/+ c #E8E8E8", "(+ c #D1DEB5", "_+ c #9BC745", ":+ c #9AC546", "<+ c #98C344", "[+ c #97C143", "}+ c #95BF42", "|+ c #96A870", "1+ c #EFF0EF", "2+ c #E7E7E7", "3+ c #F1EEF6", "4+ c #F4EFFC", "5+ c #9FBC65", "6+ c #97C144", "7+ c #92BB42", "8+ c #94BF41", "9+ c #95C042", "0+ c #A8C968", "a+ c #E7E5EA", "b+ c #E4E4E4", "c+ c #EBE7F1", "d+ c #97C440", "e+ c #94BF40", "f+ c #93C238", "g+ c #BEBBC1", "h+ c #82A63A", "i+ c #95C041", "j+ c #93BE40", "k+ c #8FBC36", "l+ c #E9E4F1", "m+ c #E1E1E1", "n+ c #B7CF87", "o+ c #97C043", "p+ c #92BC3F", "q+ c #85A14D", "r+ c #E8E7E9", "s+ c #DEDDDD", "t+ c #7EA92A", "u+ c #98C541", "v+ c #96C340", "w+ c #8EBB37", "x+ c #CED7BA", "y+ c #DEDEDE", "z+ c #D8DCCE", "A+ c #8DBB34", "B+ c #92BD3E", "C+ c #91BC3E", "D+ c #93C139", "E+ c #A8AF9A", "F+ c #DFDFDF", "G+ c #DDDEDD", "H+ c #A7B38E", "I+ c #97C341", "J+ c #93BE3F", "K+ c #A5C467", "L+ c #E1E0E4", "M+ c #BACF93", "N+ c #91BC3D", "O+ c #89B03C", "P+ c #D2CFD9", "Q+ c #EAE8EE", "R+ c #7B9D39", "S+ c #91BB3E", "T+ c #8AB23C", "U+ c #93BF3E", "V+ c #8BBA31", "W+ c #D5DAC9", "X+ c #DEDEDD", "Y+ c #DDDDDD", "Z+ c #E1E1E3", "`+ c #E6E1EE", " @ c #95A672", ".@ c #E5E5E4", "+@ c #E0E0E1", "@@ c #DDDDDC", "#@ c #B1B99E", "$@ c #8DB938", "%@ c #96C33E", "&@ c #94BC46", "*@ c #E4E0E9", "=@ c #DBDCD8", "-@ c #90A666", ";@ c #E6E3EB", ">@ c #C9D5B0", ",@ c #8FBB37", "'@ c #91C036", ")@ c #BBB8C1", "!@ c #DDDDDE", "~@ c #E7E6E9", "{@ c #8CA160", "]@ c #E2E0E7", "^@ c #E2E2E2", "/@ c #73982B", "(@ c #90BB3D", "_@ c #8CB63C", ":@ c #94C03E", "<@ c #A5C06F", "[@ c #709032", "}@ c #92C133", "|@ c #C3CCAF", "1@ c #E2E0E6", "2@ c #A1C45C", "3@ c #92BD3D", "4@ c #86A050", "5@ c #E6E6E7", "6@ c #9CAE7B", "7@ c #95C140", "8@ c #98BA55", "9@ c #7D954B", "0@ c #95C23E", "a@ c #92BE3E", "b@ c #8FBD38", "c@ c #C5D3A6", "d@ c #E0DFE2", "e@ c #E2E1E3", "f@ c #A1B181", "g@ c #A0AE83", "h@ c #A1AF83", "i@ c #B7BAB0", "j@ c #E4E1EA", "k@ c #ADCB70", "l@ c #93BE3E", "m@ c #93BF3D", "n@ c #9AB75F", "o@ c #E4E1E8", "p@ c #E0E1E0", "q@ c #E1E1E0", "r@ c #E8E7EA", "s@ c #E4E4E6", "t@ c #D8DAD4", "u@ c #78943D", "v@ c #93C03E", "w@ c #94C040", "x@ c #84AC36", "y@ c #B8C0A5", "z@ c #EAE7EF", "A@ c #DCDCDC", "B@ c #7F9C44", "C@ c #9AAF6F", "D@ c #E2E1E5", "E@ c #E7E6EA", "F@ c #9AA87D", "G@ c #739927", "H@ c #95C13F", "I@ c #94C13E", "J@ c #94C23E", "K@ c #90BA3D", "L@ c #91BE39", "M@ c #82A53C", "N@ c #A7B48A", "O@ c #D2D3D0", "P@ c #EBE8F0", "Q@ c #E2DFE7", "R@ c #84B12B", "S@ c #A2C45F", "T@ c #F0EAF8", "U@ c #C0C5B3", "V@ c #92A36F", "W@ c #6E9425", "X@ c #8FB93D", "Y@ c #80AC2A", "Z@ c #779D2A", "`@ c #7D9C40", " # c #8EBA3B", ".# c #779837", "+# c #719823", "@# c #84AE32", "## c #96C43F", "$# c #8AB23B", "%# c #8CB53C", "&# c #98C63F", "*# c #86AD3A", "=# c #85AB3B", "-# c #86AC3A", " . . . . + . @ + ", " . . . . # . . . . # . @ @ $ ", " . . . % & * = - ; > , ' ) ! ~ { ", " @ . # ] ^ / ( ( _ : < ( ( ( [ } | ! @ 1 ", " 2 . 3 4 ( ( ( ( ( 5 6 7 ( ( ( ( ( 8 9 0 a b ", " 2 . c d ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( e f ~ g ", " h . i j k l ( ( ( ( ( ( ( ( ( ( ( ( ( ( m n o p ~ q ", " . i r s t u ( ( ( ( ( ( ( ( ( ( ( ( ( ( v w x y z 1 ", " { A B ( ( C ( D E E F G ( ( ( ( ( H E E I J K ( ( L . 1 ", " 2 . M N ( ( ( ( O ! . . P ( ( ( ( Q R . . S T ( ( ( U V { ", " @ ! W ( ( ( ( ( X Y . . Z ` ( ( ( .. f ..+.( ( ( ( ( @.a #. ", " f $.%.( ( ( ( ( ( &.# . # *.( ( =.-.;.>.,.'.( ( ( ( ( ).!.~. ", " {.].( ^.^.^.^.^./.(._.. . :.<./.[.>.}.|.1.( ^.^.^.^./.2.3.4. ", "5.6.7.8.9.9.9.9.9.9.0.z . . a.b.c.d.e.f.g.h.9.9.9.9.9.9.( i.j.k.", "l.m.n.o.l p.p.p.p.p.p.q.! f ;.r.s.t.u.v.w.x.p.p.p.p.y.o.z.A.u.B.", "C.D.E.F.G.H.I.I.I.I.I.J.K.>.L.M.N.O.P.Q.R.S.I.I.I.I.T.U.V.W.P.X.", "Y.Z.`. +.+++@+@+@+@+@+#+$+e.j.%+&+Z.*+=+-+@+@+@+@+@+;+>+,+'+)+!+", "~+*+{+]+^+/+/+/+/+/+/+/+(+_+v.:+<+[+}+|+1+/+/+/+/+/+2+3+4+5+6+7+", "8+9+0+a+b+b+b+b+b+b+b+b+c+d+&+[+9+e+f+g+J b+b+b+b+b+b+b+3+h+i+ ", " j+k+l+m+m+m+m+m+m+m+m+m+n+o+8+j+p+q+r+m+m+m+m+m+m+m+m+s+t+u+ ", " v+w+x+y+y+y+y+y+y+y+y+y+z+A+B+C+D+E+F+y+y+y+y+y+y+y+G+H+I+J+ ", " C+C+K+L+y+y+y+y+y+y+y+G+M+p+N+N+O+P+y+y+y+y+y+y+y+y+Q+R+S+T+ ", " U+V+W+X+Y+Z+y+y+y+y+`+p+N+N+N+ @.@y+y+y+y+y++@y+@@#@$@%@ ", " U+N+&@*@=@-@;@y+y+X+>@,@N+N+'@)@!@y+y+y+y+~@{@]@^@/@(@_@ ", " :@B+<@[@}@|@y+y+1@2@B+3@N+4@5@y+y+y+y+y+6@7@8@9@: 0@ ", " a@3@b@c@d@y+y+e@f@g@g@h@i@y+y+y+y+y+y+j@k@N+l@:@ ", " m@N+N+n@o@Y+y+y+p@q@q@r@s@y+y+y+y+y+y+t@u@:@:@ ", " N+v@w@x@y@z@Y+y+y+A@B@C@D@y+X+F+E@F@G@H@I@ ", " J@K@L@M@N@O@P@Q@R@S@T@a+U@V@W@J+K@%@ ", " X@%@K@v+Y@Z@`@ #9+.#+#@#M.K@##$# ", " %#K@&#N+N+N+N+N+3@&#X@*# ", " =#-#-# "}; yubikey-personalization-gui-3.1.24/resources/lin/YubiKey Personalization Tool.sh0000664000175000017500000000040312642452141026502 0ustar klasklas#!/bin/sh appname="yubikey-personalization-gui" dirname=`dirname "$0"` tmp="${dirname#?}" if [ "${dirname%$tmp}" != "/" ]; then dirname=$PWD/$dirname fi LD_LIBRARY_PATH=$dirname export LD_LIBRARY_PATH exec $dirname/$appname 2>/dev/null >/dev/null $* exit yubikey-personalization-gui-3.1.24/resources/mac/0000775000175000017500000000000012642452141020506 5ustar klasklasyubikey-personalization-gui-3.1.24/resources/mac/installer.plist0000664000175000017500000000076012642452141023563 0ustar klasklas BundleHasStrictIdentifier BundleIsRelocatable BundleIsVersionChecked BundleOverwriteAction upgrade RootRelativeBundlePath YubiKey Personalization Tool.app yubikey-personalization-gui-3.1.24/resources/mac/Yubico.icns0000664000175000017500000124150212642452141022623 0ustar klasklasicnsCBic07LPNG  IHDR>asRGB pHYs  @IDATxW7^ӓs؜w+#1c 6g88}q8?Gq38p[$䨬Yg'WWIڕeIիWEGLfS䯰PZ7tLõa&Ʋ)llISH?E\.O$k)D*L2<~$6#dDײy.MidRdoi&Idj!?\A(qIQe)z+-vuID[,UQg7$ʦY"!M:K,9:F;ri+){jU6Xl+!Pit0E+6hsTdg _V#pIӓ4k G{-~ g1Q I 866@@RUd⫴Pu}ИL5m I# "#r؜=9^Vd9(m>/7z5] $qdF^Ȅa$KR1-=&N|NY.xzAlMfyb3BeHGcQu+%2FmAD@"]<2wLOe 8(.9L8ʷ0$wc:) GN/[\N2pzgH7 dF#N q!#AVr.ӗNh _ف<N8Xҿ@yDJG \w Q,&`:~APKSVK;ArY0KW <'Z90 3)&6%EZ(WL1c Ӵv L#+|nl }u뼊[Lǝx$I.t=[J>( RR"YKm&/ZrvɃtc"1ܦd2ڄKqqӇE?2dl,&N47҈I.zef}kWqH ?=Bply+pvWP̼BΞ%ʠw'ÔQyJ59^kcx2P;|G; #j)t|RV?#Ǔ]h:- wHT7&%e$8Dj1Q&&z? P}kZ~Mwƈ0 Bu==8 b2dX밮u34C:3V( :}E={$-D:"_,)"X}##[Ts8=D(E}y.cڪs#mȊP$#, vVOmzh-Md7Eq{hxQ]~) ,{?.>¼<*ew+?fySt8YMZ1l6ha7{&|٭X7$MHueeDgP>1 #/CoxDk4 !7s*,fVX`alA̮H#T +oF]Y@1do/Wi YjnuV\IS'=poYLrj,\.kw<+?{̍|Vb_yѪsёMd?~1k;4}&,m tľτ_TG`2;8?:%֜5Ic&wy& s_L/ٳ{<|g~ƫGݾ~i|SZbnyscNr֞\׵3*r7㐙@O|*C^4Tv-lЂ6S2`;<^|n}oD^{ㇵGѼ6_M)]M3 3`4CĖk/0GxMƓ|L+5fۻy{zbzfCp$Pu?naj +bM< _bOOAFr1*$lNfU0\Mڇr0{ +rzfxOͪz3%_yL R?\2Zp%ϼSRq* ۿ8SSġS { KՁ^d虆M6 pq]5q`̊âP7?$#t2&^L_*`yI~z=ہ;W޿3&} 򧜙ݹu|*B౦41#uC?[wY]Og&^VOk?oqgiȽp̡3L#+:CMSgvLo~Jb,Ue0S,]*I :xgdk&>P1I(O{KWJ g7*ktR] 6Nvş9 ʧZR'0,|LP?u<O _^76ڰy5x-xAv,u64KIUXK\| 9{ `j_[!ko;B^6 & A}\N fý {Gh *s%E+h&tcPMk>PZfpww穉x zQūO5؋:%l}䐃MuVhV+yBXSNc&}Yڏr7^Y|λga\@ᏐQq?ΖkQԅ дHp0=_G6.hxW+mދsȾ!w+k>5('q6Y{dY. 1\bDӇs*Y,U.ϱ>k^`c5Cf+?\؛裔_&̎Qee\N^B;^O> 5WKTU䨾~df^Y0n#xq%|0 /xIYI!=D)\|`1`&I[ cditwBbE{׏"t9b[5<$#Y:ҊpPJ5ҫgy3iߋ^˶kQ(}*+*.-~7! >,4i!/Ňt*# Yt2&paFt*sC# ps]n6U(r1(XR3[F1ݼ$٣pGg FP`#>Xn[i[P^h䙍Aj;[ֳA|s6CI#3^)HQtהr~T"jaY;TANoZQ"ݚa0r,a*qf,֟x_ m#ɫ곽jD5"k^s2hH ύ/.|Vy%,#Pm:8tD_ NTߋgE^B5 Pۊr|G[9k:_d4Iqa Қs8lň̄ g˾|;wlJ#6%pew)C<}*/Ҝ,Ӹ.O>|˅# F^_׺ 9u "lQfrZZ3/ `Tm9%?61K0,ZW64u6aFF< + .!gǨ{JO"&Fńc+L漟}LYۉAFg@3nlƴ4{q64;HuԶm^XV8]52 W/i9;prjx:Oa.V ,> BV;#`q8t,u!̴yfJZZ!/K#L[FOUƲ/ 3Ý/k(߰$) RVmdᏑtם%YԺ\R+ uFl,>or'~:c4]rB7EhCRZE[aTza4r4=O}#s aҿXT`L!7l\ Y=XAns٠k8W8M*ч28OdӹԦ`2Ɯے7B d3NPNV$_=ɰ h,篊+UU <=띠kQF\3' dpJ.嫚@\uR|!FGyʑD'3(6n7 Pe'PɲDis+Js<*Vb.5p>).4i@bw$7&Hf¸%Õ$jhզfM//8*zꡦ5r[n_x/״ڨѶBV 67ya T$gV:=a)SZv&!6l) y]Ći;? PnLWXDplsYKCa%˰jnnYұ>96![&Auzu ,;FGXȭdUWƅpAOSPMǵh` \ c3mN/LGuCr3%add3 N:p 6'I_5?uݷ9cuJ&aTWI>G.Ӑ&o ~2V*!5쪔bܼ%" Ɓ-pl/#2՗GugCbS2n7$cG@ w9 z-JJ2%1ۤ+~YTB~N;Y(f,W̞9kP-IXs;٣ZbhPo$3q"U=B[䖣݅eÙg9E#~+p^.N 557PCT)}\;w`k*T dnEǭvxTX~ 7m,7y 1#>6㲸:KP YFӶ.695QCIS=ωW`j1mmrJ^) QJqTG0Ģd\x4 fq\#eIiQyvJ|qҍU–ѩ.깓 kkח'ueɊDFf ~"_OW"Hq~? 5M:`uqDTfJ. }=FG&y6t{V"W"߄dO+,Bɗ eÉKtXU7\)w'҄| Py2N;`s+0Sߛu11FBi`RjBV4c,il6|mi;$R.5P=ڌFQ~E>.#~q>JA ?HE `3 2g> ǒowRT{Q, QZ+@W9+mOCuf#lf>3%Ja)CZ?K> U<Ҵ J ԣ `c4(co<5N*ʘOMEo?xtմ&fbw$jscUUb*\'T lf9?O%4MRshٴ7Η?3Y]AsS` gR?>_knf.}Q ?Aj09dO (*&to Uce{ýa +5e5E^ Azb pk`:Q1a-ncvj6V;<(HA2y-ꃟF s +@w 7Be-of,M=&KamzG{FБ|MrԇV>'/4aDŽ4ce$Z@,[6`$8CR^ Tǯ0K-zaSzZ Ꮡ/``.zb|V:!Zq{DJ֜`7\y1!!cxb:`$%ઌp̝&+Y~PA5t0J|7қ+ZzK7(b'4.ŒQre[2\wh&a1HZ̶t>͞Lۤy:%.KqHB{0@')l"߂&7z}'F~VwQ~,z/?;V*ZD2a!=!4ӗfXSw}k=mv뙚ǸKqʎgcΌ#[R1@{bml k+XɌAG¢=@lg&-2̿8!mE&q5@Bq|{II,~+my3`HY=zd:c5 7>t~r 83ofVc[ yJa= d+֭e mb*? %D{4T)\Y /Mp1 Ks Tu&$%/Hׅb}vqxtp?SٶG`W"t_l'Gʛ/MsQ^%/Z-\\Jcyx!1*s,xdS{7 nwPG@h>s.QGn߼+n)5 (EB?m,A( Gއ06ᡱlǗc4"`^7|&5TkA` piGWP0όk,~gO3CfhLKO]4طHǮhImPM%ðOhب#]%ئ[Q[PIwK"gI$R@׺O8BxU 䊧gzfg qY-v{T@os+T@0äi8܃W'dV?ƃ̶QC))N?xDxS<&҇0\ :̸}& a,acZ k3 EHDHJcB5Qk{K/jsf8c@7LXeV{bu rINLhONK'Z-Q[FنBuދ8o.s-B+hkʒg"y'?Q`Vfum:!5fW$0 Ƌqk 4|(5I&xxw0=7 Ā*thз= ?pH65."c"& ĵƃόu0+,",~lGE&"A/)`T&}x'"{LZz.u )lWw2:r>k5`O3qƲҾ:phO):Po<+yql-oBbD9n xMhok4x0b mؠX}Y(O;__fAM@O3dXcm0Of:vN-pOp# CG T҉B<$;lN:ط=ò70aEU\>NdQ4P4tr |5}&0>bC(dvL ;&,2]OTI7È-rry7;1[Su6Lbr&[&cikZ0w}}:`MS]cQ)Hss6<7SMwwa򥉟ٕb,K¦rϯqlZX $ /#G<3~GIsoF *)(xxfQw=rrȯ EN;<~DAx9 Hߛ4්aNJ_SA$|xQpebFba`sp)9(l6P* KQ6 Ͻv$LD y!<8DLyqc IzF2"#g|HŝP _! \tS/[ 5Z7yxG!57.^?տCih^BTa^8x>U[5B+G]˵]YZd kFN`G(fߊ{J.K ŞCGv:`z͌x]?XOnnusa"^;@vg)eOzϞ/B& 'Av$wBЮg&S o3V@>pK":3;qxj9ώxf |UbMy¦qqW7u A>pGVǢ'0MD#IR0?˄r`_9_/:rf7,V5~<H_)_1TG;;Ms*/H_/$|~8`Z_ ДR}"T@] dEȐJƑ@~~ȯx:d^qy,Dzs֜Rq7|VGA yTI,)'D-V!-ZJkNJy~~3X"ow(>\ ?a[\|_zt8|0sbnz_"4Uw,EFS{@!p~|Kbh_Rar ?~Zu㑔B˽PDy].W}nh5A~S%s?mZLX2@i{yǮٝ:E80IЗ[}3]p[Ojhz_֏g}^K(KhJ&T3_q/'f!pVT-8ۻ#ړ0=f˚ @~H->K$}veՍ-OL;kW x ȝ80e_wcl4ۏгyR[> ̔ԓV:83b̯~|[S:睛dw_(8ؕmZ>3}sO0Vpw;/LCyo*Ծ\_] #W7V}Fks*G]tINK* kSmV^v1reҳ["5"4,>4Y[75H= 7v1 0*Dԇ:gezil5Tժj ءM[ulϭ{T}n\49zGJ&~U:"y w/?oƾO:?YaM NڛMeuuFudm}[ M{B:3gR27=X1X۾'ü #gM"4{ :\2_A^eT][agޞlkKK5?]cmh֝ | yd<3QV-f۬#, 3~7?=P<}=P ϭc%ϧozywc>Xo$S+L*rӪk+!m׭OZGȺJIUз{;hy)DL JSzAY]3\9rKLoP-&ӆsk(PJ&~ml4;Hv#70XaqTZY`ezahz?bըfZָN?g#/0!`[*g|˦~"a\0A*>h$i̎s[ζmt`װXc\F=~]z-,aN%tT`s8{6LgܸDʝ/~ +MgRBM"Lٲ4Vm^d ?3XưL. 7ps :'IQ[5ҥplXڴw?M9t>8"h,B[x;Z_'EU}0I'rv:L9pRDz۳jhlL-ߺoً7,lXVq۔ gXbX S߮ոۇ{|v%oi#T Nɩ3id:/C쒫~|A7{Fcn@`C'n3ܸ2§."s{y~>-m8etGg_^KoP|yr0g?WofoLU'\#ۑsJp3_gs֍7 } Գos \,qgiCG%6xJB8x$Aꉼ)u +3ZIxn\iǿO*yjfk˂  d&?lܫW2 :iVECZ^ysnx^(YztB\ *gϥ .sŸ#;PΝ٩U]4_ӉzdcZK7d#̷=2|~ea>/40آw8q᲍~h8 6y-W-U+䘘Kc`"YH}.дz&]L|ћg~v?*Vg^q{e1@]o_y#2-152rl 1 \`b!͏1-|Ϧ Sqw(x躼lUOpL _T r0ee/ռNjj=mknL>gf4 Q\֒|$>.QB{_潪 q0u{C=O_'gp9 {H|윗&ʿ{T+1qiDʫzܞ=_(YyUԺ.̷&F>[,O|m'Z9pҼ [[J^E0]ۜ>%ط'@y`dk[dUчȻfprJs`b`,dJ8J3ވu SX-FQgtrhu22o,eR5t)qڬ+խ{?c[Z0},eT wi7l{&J=;g& Wޗce'vVPg¬S4v\mлTnyX4oGY^U`P_ X4{UxZs&!+Z: ZUVetc>{m mwl?3IN(DA1@V:{VZ[AiL|?|!_Ad>~w3Iy$+3CMZ[ IDAT_l{Qƭ,- #Ky'}[t-%51B&Ezzۣ&zRoZW`U6Ԉo4d) QÑZm&=Xn-4 0UN `82nO_y> sFdB d"l'-`j~uҾ]չ1V) >ZA置`սBN"[2P3W}D2}X V,vo^r>x%͘;;VKc P‡7{mgF?SZ sҢq 8d#PO~7e:T7f,yyvD~jgs?'7u*dVFdQƝ|Yz-eᳶng1{f):epR =&\ӎMmoޭl}}ҥz=Anp܎01u@ P,i9s'MuURrԌ ߜ:|3?AI!Sni'#BNWϦ]X2>|n~[ʡ}R4PU᝻YSZm -?wd59T$hh9Tq73̳l f_؅)-oǣghGkeUmJҲ(X$S6Xgg*׋; [BF_?߷|w͑д_괸B kWf?;X *GCI4o+9JE " !HZk ÐƩPO@Ϲ`s 9U*NxH,6ϰܹIN䤑n '9Hr:UT s^#qtb *+ߞsKOF K xCub|AB`#wx?/W|}ea^KL !G@(<HcI6C`+YIk66`\*:xFa2Hr(IxF®iN~xXc3g e.>379dYfP6/~2\NwY{B,LqZx+7O_ ' 8,Hbi:q [/a;yy W:ymK\SD@@LLWpt|f@^,sM~6kbBR"f+G6.K"F%5)2pQMzml8fhWX,6`C2A02D*5$NkɑlK,Kp8}!b-btD ˼J% ٮ7n3B4)ab#:aN\(\I* )!$IFKg NIue2*099yZ7l{mDSA :> Bԁ9Npv|7c+ݽ#j߮Ԟ}dnbސduqNl' gۂ l)I0ICphِ%ѤVhc +{1oUڇXỳ#:|L$ED:1&&@؀:0֗[\/6AEQPFbx$pQW`N`\Z ApƆ] عC@ X4d:yV\y]XEXl8j(N ! 4-ZRDG\QXq A~ L:0qEp rFO~m'0sto,`-IENDB`ic09ωPNG  IHDRxsRGB pHYs  @IDATx]U;;^r$Hҥ " (MDK]QDD@t!~r鹲dngg{o׿Il/F@0?X+I8٤,O- xd/;ӤWifR`ѱ3oj`K_c=clئa6JU/3z7X" w؁GY4f7U!m<.o=4;/wLoK`J!sQ)}]1f2 hpyj #~Gs*[0I lVB46~NpR81 D"Dض/YQ>P5%E5JU34T%hhf#4jI|Ez4ɟ;]MVgZ6 նI3Xv{US0_G`Gp`GcTb<0U+iZ@hH د,tDpv8@ A#'2**M$5($\TWÁ&ee;v9؁k;aEely[f;q|'aH;O~׿'QgWdB @2T@!/ŅK=S@&P:[_I~u DT D>MߓSQ5nvV;I$Lic'~rj 9ǁ!o#Dٱ.6T޵h_DJߗP#M(G q-*q!OuHv^{0#4)h0A ՐNw[#N_-[: WqUa&Svhxo )ßbJ:'=jc7>^QпOVK)t98B) @!5㼽*IPiJ'SHdRML84hQQ'rB>+B.lGQ2bf CA9;VϗnYy-I.ߴ*!1D!?zISy(`8P˛ "h 'H&tƤjC|8elԝpE"?uֱ2 %" h$$dMӐ,+JO0Oyu?:FaI/j"G/BD3ثM?`o DS!׹,_Ut.ÞOje^ %u'1oiiHkDITvs*KqIey⯀!x}ջnZJXH=#E5u8-x3qD1˓*ld*0E8條&_U,*ॠP1ȁsQ^l:|R S}6$E[VET d*TӔ[1E ݏ@>"|5^答܄ T h6ߒ=8뤧Ƨƍh6H6"XcBmyBe+Xo~OBoYYk# "c2ƑdЩkQ (ʱ @\[$8LU,s )VĿMKM;@ r:,l8=^C|g,@T m@> |%^GubƄ,σdd0c|eت@MU1l0<ӖgU^XQp։@imPՌ߇#0tp`wBUkAPcm>5܅ B?O'I*;gs2~#0d ".HְnycJ&x~<ޗ~L5e~={g0~#zÙB Jo'oUeV *,lhCpV%grJ]Aзl03A#`qUgdGÁg0U# k<_UjHc:@G=@ +Cҗ)Tu 3)S+^-w3 (X&==?#0,p`X`7)ۈ,y(ia}:\D@Ubk=F>ڣYyk?}2&lA\أ['nd09NB΃:-U&9G` ?Y^]Xvˮ[q_Gxvi EavpH*9#X+=f=ED&c1] q *=?#d;f<U5ymQV~_]M_'N(3j G`8 pZȄi_z*װY|2{@"8{_e{?~k=mQfudU3 }!%G#p`׫Є6Cc_B-67G#ZZ یK6󘒯0̛vM[z g"80D@mԚ/AW0Q Go"@ZgݲմiFygTOw?sOwM8 @4]#ea~ގ P 3RXdkm~ g'HꇃLH"ö.̤L+g S~G 1Q@/3[䚺_YXz hO|7Ld{g(~Z07͵ gGql{2Tm/,IH; _H.ɇ9mo=o06AERCp~GHpv>'$,yg~#fkZ{GKk&x;~WlpaNJSUL>Q(PzrA-C?4z1p8#1xXi0?O@_|g}{i٘OB>v(8U8?}55EBGxʰL~Ee8~|@iZK~8|}uOib88 uifq+[\5NTĝv?%=hCl炳I#ߛHGC&(U?6G @vHV&"2/GW6\CA&J盝hF^Y!@g&j|d欐~S~FB lhY`0-x@1nH HXT25{79E@e@?@5l O=y?n{MlnQюjq E8 BեY.NĹ?׉#7O;oWB%8 x˓S?KM6=ۼ! v.5JØvѠ[INKDޑuoQEW;OM}Xh 9<4x﹛`at^O{W~L> VtfYX7V˓RfaJFRҖdJ:T?*GzITCHK uRFuĿm^6E\t1eM!g%?jyL~b!J- px@>d$HDNOwKwAtRNA2@;wA@3lXf- P f\Tv'j>)hQIHufd!kɂfflbD@f]M ɀL K =3#2bJNN#b?3dhKH"ΟA@}'-xE뎧ooˆRV)1+ q6(n.C/JZ@m:f~UC\<!$-'10caRp~kvVЙE%nf"e v,D]1 %2w6_ulk[(3Kر ɨ{ӐE%Yx(ѭ %7tPTpDb>AЁ0l@JsVqX;p!,؏j&87;_h崫B" :Z[XpS%GJ O`QSBQr :A rFǾdB/jP F&F\ESԺPAQ;.l=SQ Ɣ%sdtZc3Уp7S x)90}@[ `L~CAsid5 0 9 O|M7=ئ?trK:(o8 ,RFLNʲI(MYjusI&D0Ú YSX<;"o:K/ΘdqI3?$3s~H-0뛦ͫ/\o'RQk Hfɱ/s TwlWƫ޸LRGӊ}d YQ)~8%iJXTcecUTڴpu1CuJ9Z%IKؒ9VlX<7}=Z6Xoj4AF5p}3Hoh4!mm+CZInQjq 8f$Z M0BXqZt($h;;eR8ω]3)'$(ʿ@\e%5ҁ7v _ՖZz-kNkJ:=dŦC/v$@MzpKXAxNzF@5_cV֧'˛܍ J ='8OEHU4ojH;[VKQ 'Ǿ(gu 7*j>bYHXӿǩ?tʳ|畲r$U@pya~c1uGI,2O˹Q/i]%G'Uq[pŸs+4F}zݗxWݳ' %4!FOO{*~9饪_$! a $ݓh5gk O¿''5<%2TMu';RqV9{fV :dqL;Gi);!i<'VX황i 9F4@ҠC*3,؋hZ1Z z٧ ە`0)OGkx6&ߑcCĿ }I"C@g68\8DIYY* j(LDH`l"lL7aʫ3ڢ#~tj“_4x6tlUul{(WE/Fዶ3]Sum?cMW/! ͕8hhO$I.k(#@L5΁%Ն 8==I) ػ!gs`ϱ™B26-)鯗쬛>1P7`5p ; pG[]_=ugm:a4['t_x6%q׋(fjZ5?>T~BצH8HZ<->?{UǪ[L,G`jKjϙ>x>?W/5cIW1OPuHR֙׋#]s9k`JL2̝CfTOWKEՏLxlo:Ҧ@r@@Pb_s_h :I Bo\V}YߵK9=A_O>95u-|i=&XR 7@Ńl<[o6Y rd] v"+PM%*^` 'Y"5;O ͮTk3N/myxuq#Bo~,9ꌂ8Jn~/kGL@'~V2'&7V&C KL?3#'AO%)V5NRh~O"o ڙ*1LsPzQh/ `qN38 |I7xmvC-8rjT4M+7n*6":O3 X& D54_uo O- <Ics^8@@lԞf:Ƈ{^VѬ/6) m$1py:Kkoo6gi319wÝuӏ*}=//+Aw*M3sHW;:~p8ËavzWdU<;Hѵv  F@ՔRoKpqz\`dRwF3{ 3ΚfǞ|UD:.~ۤͰm3/̮ؠ1R[ WOƘ- r*'MS4=EQMÁ4hcsͶzVyf6PHbdUmc.V _t%l L%m *AR_VBPw+3]tLx~.S5J*J"tR @JQ84_15&<;Cooy(扮sd| P,eG_u-桫V^ 10ICi}k#FҼ= <ް芺7!Y.H䒳s\NR?RBM:&:t=sD4 @:h?$E*HrqD cd/0l-&`Xt{~EI'8F%Ez0RWgU΁̱BUV @)%x.YMȧυ!٤, B@LL@X#{[~W^gv6^`.a2':M!"O\$}! N51U o\xy;p4-?H){M /GHyBm|auz$^&@Ұrhئ{nM`: XŸOn:Ceǎi3_f]XHo_b|r3ʌ~R 06fTx'^~m'W/&'?s0oG#9R,n㱥?iuZE<@B2m[  VZgb>_޴; lB' uTNU}a%ZHX&|V0"O+c)>;N 拵3pRLqݼA eYc/0Tڦx_n7j`,z7Fɗ݊pدn6ɤm<|eÁ? A4E$ {?lG_@<2"k`=_ )k/1]o9r)gY&^oG`k,<{}}HIr ΊyP + rm]0FUzIUtҬ_OP3D _d:|.D1 ~m*_@ğϝ>`kS]ue/ƒQ>QKh^!yk:O8i`\' KC262q &o`0?_Y[MԺ -8BF ά?yd=bju2 OW!}O&XL¼޶s҄5o(>nK]ь獶ax%ws5O͸G-?G>4!yCtܿ 1:dc^Y{+bQϗܯjE(-%ޣo1Y;p4 'J̒[/l)1ĖUWYzdֆ!${ٝ۟:CPb)H` bG[msbkd/ʿANb}ezw5_;x9D@,4^*}onφbI1ZY LRf}^E}cmO`}5@Q.#R~Y1l8j4W?Ɔr h&NVwk??-ÉN΢RF8t4OZIyS6|#L 3fno_%#H(8yM`dPBGm5 IY@H}*DBIu͗;7}K #g~ǀP}7i//˯)y5N*}[j?Iv_pJG`?Jn9@&6MpW(l/;.wA3AX塓þ*5j7"ԮxLaѠŽ:ȉs ?u8hr]9Z.8/"|H:f,!鈚#ae}8 O"Ȍ|jϾֵ N|l{9b?"ɟB)䌣C?Z|Qכm (W2?$aQǘɪ/9=16m{w4!1&ʚZ@TbH5h "jH1ɤc'\\%L9b<ذ2贼%&@`>z ŀq9  {2gr:nlt2'>z(a& ')N^J{7EqV_ұ6韴s`-xA 5ϐߏe!S4h-T XB,ۘqgV>@;؅ټME ҧ?DSHf (쓷٦&uL*DD '3ojoym*+MOld ;k !W˧I1hb>3w[Qynłp8@5g-.H.g|Kyz>}jt%WBBa0j̵'@yU z@pR3I%>(6})q1UsoТkg- XOpvJ{2[LnJH@ƼJc~31511]:s!,Xz3"h̀!2%($a7XN,tF$ct]D/'[l |_+[<9[ E x6|`dV^of3JUͱ"m$ᱫ- 4y-n&uvA1R+*P`ѲHGa}毾޸+?` ?VLګj0iW`4sNb =C =}fv ; Z300!dG/BHéiI]WtXAmPMT%GAZ6~T[^G a4PMI8cɪV6vcұ6jbH2P t# X= OxhC4Iy22Q#R )6R>$>>] OlV+8/:QA"&6Q%в݂y[|U-+: b6?jh3vŃO:^'o)Yf j iy(yB BS1  1w>~>П/Z ;gĿ nnR,Gn22ٚ~e1! ͳ1GEpɨ|&ˆlk4(-/'U֯V"1Qj pr`5sZnS/^G]k~}b1 <#Ӣiqh iBs!f%d"L#gK$mȲ>:1k$gm>5P` zE9|u'xͬŵ3޵mrZqǒZ|Jr@5sX'u/"8t] .G?_d1/3IAk^ʌS}GWb`XȞw={Fb#G`2-DtrZa?{o~$rxӓK;bm}SU(k| &Tb}[*Nհۺ8BKPX$[jI7j]ℾ&j`N EAф&} ,dBJ YQ#}V_QZ#iaRCs~ ".6=ꄥ|'_Q(8)Sxͬrq=񧱭U&I}Z Q?9ow`4kP#AV{eƦ{JZvs;WA2K~O?.3F#QI fWՏj}Ca.~έwW[,5,H?~|z,R( '}PK&`'Sŷ?#?#sl ص9J_&H2o@&OKl ׭:21,^Vg}|dIIE[)Ѩ5{U e$dV~[Y Y?TYVvQ!.'!$K[?;b  հ@U+<1E͙MoE?if`FDLU܆Kæ,[DaRX;b7Y&AGMY44L3YDFsK` 7芯@JuYuP4 4747N;>}Hkϩ_m4:45d,),/W-k8aTC\ le i6jꌔ8ʵBE"biE;dINi\-kW)SkN%5^\ ׎ԑZ YWpEۙ ?p%S F jKO 7Y{V˂dA7mt A4 }kLG6xP06d!^veDf[vȒ_{k)9hEe [wtc2$)rm1_IQHqhGjze \%YMǶAbR#֩CXǢW%ƁgOAkd~ sqE9a[cQBb,H;K&%9sw1ZN{&D;>y?Kz,h9g d+h;✪U KSTiF%,pTdnYtlfޠXȹ&~J 3. G\S6zYGS$xq}5o>q}َ 9dXB´z?ܺ[w(_mTbY}IF}x =~}"ֽu/a<*ӑeD76F8B|% ?9^S4?Y/{0 Ԩ} &bKxKIX#ž}.^(Fm^)ʢK2سO?^xyu{/LbE7jr?5ͽ1A G[}ARN%rL+W6*Y+9̲#{r<8\,2^Mp/ԺgB_.´Ne 2^|E5lŀvRI8ZV7Ύ-}weh>\ eDg>,@9Ns8L$6klVRR24`] L *bTVNC|wsbɗ&̵O~`ЄDҿC`sN*kF񈒓L*V,H>qmWOrTR1LE݊I},b>ݰ3tlƾ nZ],ѦT (lCvݩ6>@ @rO*Qٮ/8 94#nb9h8 Cwَ[e8`u )ʳk.b}kx\X e̽o0$z&XBTcW=M>#XiS6b=_"cUUUxg}ErI܃12r$n!&-"fWd,_O|qA A$b!0꬇[+#ld0E0NF9XXR"-kuuod;I~ƻXg#2G !_& c. @kkX]sE2.G^>*^ #Ϊ"bd}Fԁ{dl3R^\ZPeʼ,ie}VPml2]2=NQɌWFUg#1Ś[Z0Xۂ?Q5/JNV|; sOU(ݰm1<ޠcӎp5e&:KO q`ppv #McO#N2[[ΒܓDu};V5bh5uffig20r̖h4šN0Ü˴3FpT-bSYqLG!3q# 'pmuNV$i2ߔJEqLDcB3k/$5̈br }H24)( .蘥 #h~&*.gӁIܖ V1)I6iҤ}D.s[&:S$ZQ^:qlh 0bZCL|I@sܴSH§̨Z 9o8,dYBT[RP>&8تm :2ʺX{nC@3$caz(,wcz1َH68]R8V(:iFdaCCUKV^kd'^R{dwF1TAehΗlVjkR ‡@}9Y X/NSNnvk>7#S@s,&?ޛH$wb}}G~o5rHjH" hJo!g `!aIVAp̻_wWבUygD~GuUwUfTUxwVxaᇹY7Nڟ84/oC ?YIm,u 0x?TFW67*3)W~c`[~v 6'ŧ6G{?g&3v15ç"7GmD!J6PitBG'͉c>Wq`φy I'*9 hXl>IK7re[ MaD*2Yy}_2β\q 'i6&7Q4`e]x=1KF'+9>ϥ^ᙍDj&]Z65Č p`e{"ιVD?m7mlӭonlS~n:kӉ?,{ 0)a?>j)w@b7g2Ү 9op쟧2 D'2`oG32|↑ `oR>P~e_%V p`./PE,:O$` 6@08J+_P-KQX9AFi+lфeFf8(͗K/e[ U(pu xO.Y|OL `MX"yL?fγ̭e Y(ԚΕ?`A"šͧ[q`mϕTo׷s6 ցN .@1X+:dm5 f3t%KF9N s0 @xbʀπ#k+x9C>`T/MSP~? .Ù2ew_8pczsjwy#w -+d_^z߅G%omn=H_R١X"!iMq$'jCq,T*Lbі{pFىVx|? >x]]L^QıIėR&7q&B{CUF'&)3XgQ>zP_We4}&sRNP;>L}z)%H`ݭdCᏏXE,Cjʵk"q`qq9>m\}JM&|8!9jM1He2t>Jlۅ?Fy26-ZA-,{|9+P|% J(Gs,`mQ4_Ge ,]c28 ՜V2MNMS88o,m?Ox]ǑM^mCn yؔ 7%3Qorwy4 6ՉX{!.OᏩDz<\?,ߧ}Jq#pѧ |p>ȋ śd< s}]*x5!_F-\|%>y =^Rjko_lU!YWc9(&/\,罊of~ [8Xc%TZL_eCZWFq Z- :#dl}X'"́W?eG@,Zt ʀ3i8Vx  _Y&SJ?/]{foWx|y s^2 b3X'8*wqJMnS}7Ǔ)ϥCv~ӿPӇb#=P`$s a(=Ne4D=q č?j?ݎ&_YG͉N-]xf˘O^zu;&ܛVjG}o?Y_6OqOUKfĎHv;0 |E{gpߺGSxcNYɓ1%KRGgfh~a T,+VM`ARu֫AH;PSl<xi}65>iY( )OƦCgMUG V>y/ KNz?Ahwp`=Y[Vgm;x_ZɌrA$;F!Q|qR/}6 BW%"B/f ~H- pfًzdE;KI-~l•Lt쟰㟰RT-|W|bVsawMrdZ5; M 6ǰ pvS'́Їͻ2ŵ=zg;;&\'B45n/%*#8+ҫ v".a1gxeXM {i\q5;Frs%ڽG0y ,o_J=|@yhOQQŢx6mkyl5:<2h2 z]P3v1om Gz9XHpo_lh#fP|ʁᏠ XiSv3Iq7 m Y)S*6y@<5p !5o<`ƁЫWN G5{lIV=koކw,  Kú<1]nT.:a#gjk&27jSp8MgoeLvu-?->܀?{ wH T!.&Ԇ_V+q_p⯬^ޭgm%K)˽ Ĺv *8$E#~$F7 lUZf< @O`'hsom){C vB5#(swduI/_\r@yc\@jPN8olBPitl.]@nWFO76)c|0 i[s3˰"_uH^,NlR̿Y݃C_4$'xTW|V_8vg&V=:nY_c&5\yDݗ ާOuQg=rgGx /;G48KH{҄xQ9(Sv (%Iy_}sㇴ4إ?> ІKoMl‘' uNЛ7xd-;1cy@H`leq}j'wyec`}轎iVa5қ ܩ R<lobb4}8zʻ;} Ȼd{ Z6Owm#}q<kd{m 0anpj6_|ȌCaX' ѶĠf/pT3;w!mtS_'O)B߸`g fB E,\ 1CZF`:Y>qr___}q<'c0)?]|#^m@)8&Mh M\Cer{>n+gdyCbA$z|@wnI?-:Ysm?Yj(-@Z5MN:G!.b?@iRgp e@?VFCN$2++Ɠ#oX3n (<-0Uvp) yq<[sy$hp:8 L㭭 D .6ï6١N)}-Z^L8k홝pyx಴DZi88!:kd@/ ?]U*Uzׅ QBB?ՅkW۷>MN7^:A+fo''v7Zt>E|Jᛛs,lw(d*>yZc"Sؑ](~@,'|#b?8P[_ߥZG6C";[ţY13AΆab9lҗs&ͳw8 (=P`bKhQL˖RqˊfW^yALf&KSwyy?TiFt"ۨlCК@%46jOA?1]>ƭZ@Chq@vvųڰ ަ & &(iZ=k2!R'TOt(02h`-ճc`Kj$pcw-1u=.] b'%y}p2*ϴ aM~ڇnU8>kH+s@/>ᏩZ_3eLm4]0](+x6ձp i=i`-*kㄨWH῅.á 2(MY?^&#+swo#a6]LMTgG x87|7 (ڮ/%GK8Nc}Ti@Z(K>uJ4>͋י}#La+!-̜mSM8񽺀]@{=XN#Ԣ2|(,F7|ёVx[aQFЇIVޯonÅ5*X1/=k53h͊xq 2p}]-؅$MרG,sfjov°$|86Ow`KhOQm5;Wm$Ƕz_N6mGq7.# H"vjhQ/.P EmilL /MAeV4^9?N}u%~= E4mQS9bû3p#.߭Jt_$r.țޖF:靐I,GɼU9j(u(QȠ9Ж[.|ϕe1d^Ywp56u488sdH04͆80Eh(՘νΛ9Y~"L|oQ=D=Z&C/.@ ~.JV G_xD~EisҝP*º9 6ZAo %,UUZYYBOC4p`izdfR' |87 z(iId'd.elFƀxRll„9`A8+'p̞X㼆6gfwzD_`é;[CVPNs)wN@ZT |p HW:VѿN;s0 >J+}XdF"']b{dl/E$:T _xn?~ HGpOtϮqo0jQap(BKCcl<ԋ<\Av{e`i0W[(Ra1sOޛx`l`ۭ|6%7F᪢LsB81 omP8[B':֮\>U9U{JtaD!7f<{K͆)8|_=f/e.Lj{fKƟ`m5km>c6>0}`#2'L2 %;*qeǩ>HOnxBXY;׏7C^sX\v{|Gq)_ݩ\HK.3א8HjWܙ lx:^DkWD_) vgn?yBݖ8 zg3D|v 058p:]6*#!:3ͱ셮 p@Çi&pt-'PgTr˻0}AVb!a'22]2PZT#tj -*8!)^ڠ AmAQ(coЪ .P6cq~qA^ W5X1ebi).g0$<$m~ ~8B7?| oN/VF,|!} t,%'}%<6*_Bj7R4 (-NAF#2E#\ZNU ~XzcQ[WYnU >|_sot_O/edu=WzN@MtaZCTMx& F2+0F)<=c@q\mI @IDAT{C<K) wvfY(a>:)VcmPVܜIoR ?f47;;Ks} |8-iPvU*S҂>6N MV YMhJ5n:$f mx:rpmp`%h4NRŒqX9rUxThѽO)&,QҍJJJ'D 4N#+(,=X_Bt໤I.:V!N՟bn\n=YޙPXkjj֧'dq$s4:`oKx7F @;Um& r`_{ :P7n o&SzXmվ{ˣ.,AIT<\ QNrhZԙ |߈AqucbH,?Yr8 l@`~r9ڻMqBn*9FC|t,S‚/kL Eib) Gh3{^g>x'y,TUPkOeX ``l]Q`܋>gF¢hS(FEWjA#a@d֙CfJv8&+R6_l@H7t,mUqA+A0_.̄p']Gp^= 1Z &tmRmS¹MxG!B: P Pwis'C #iT!9d:zr][m +3ԠZZTa[~PP Ѻ1 lOaR~VZV? v8 @:֨6{P ]",\-.b0mܫJ:-`,OGƚ# @`﬿kv"4_. 8M(PA3clyf~>m}|~vw(,8jJJ9!!X'Vբu9Bτ?4|8@MIN̪PzOwL('ٱ֯xy{tg:Ά+Gbl$ y( %lTz3wEL`2^d™ĚhDNL&;: egJgw0D!k]q#+6 U$RJBoz[OzdR'6(ji(:Zd*n_q^8g$M]L4^E-,y"ďWlrMr{+ί )Ch}_MXءGޓ6ѠAC*rWJZ-D:!;0O-`km𧳐Ţ^G54 @b+DgǮ4R\kT\T3^Lf"30ϊ<W?G%~6ë~9/ {]La6ϱA[<7̮ 0JPD8rN3Jꤞ#ZolѿR>Ţ<ȩڮҢ넨 XDڠΔWՐZw-a/"%x"e+ ,܈2Hܠ "0XfGP AKxj⨜GqNd3eP`d!(YPO:X+H o+-?DW= ЎYpNHXeF"*8VU} /ܱi9m֖,Me%HDHZOzZ%≮_0x~)ĆSZsMC?/eVEk25`)cdmiuF)Lb5 mi_|($/7T%v^X2I-Q,|lܦk7<`R=%|_~DiQn;-C%siHeS6{EOe`TTiiyIXYՉ `x&6f'*e&nZ0K8܅8?>Aj5 q|9ma&OY x0LʦF`#s6%6]̃ bc4@O#:qbVx{R_rȬ%-x049kpA@t9=Up`_ A(@valgپA=(ec,d9@߀ 2 ܫ yR6h~ &68x9Llhr  ,-;(Dlo%aUBOz%dlM?紬σ* )f+&ۨ5=~vl/ 85ʫ S +0p`q# НhscЯ΍z&>ΕgӆA8h[Buo3iLM/`\ՕޖEU>A[-*8!ublE ѐZ2-*S0O 'SIzJXRMhlWݦR<`ē cgYA7LGpb93,oc `:6*/[, ">->OdU=gTU N,ҽ40' [P* s2l"+kn\ىqBM+:sA[-*ީ[ a6(Tq_iG>ퟕ;^$Sȥǟ*l#A* S쐣.\.F(|tD=OMg6F c1\Nh/i7M#lM,9V!31;}Z`L*i6Qx 5CF)+H{y\ =|&khR5#'D8!ȉA *kP4- d~߲׮CQ?W^ՀkKNLeZFƀԀA:a>ϊտePm=7$|oO+3 _ pn"&UR\*~BP(Nl8Raqrz,AΏıH(ZчNǰa$ҖDZRji~N@U(хeY倔DrD,-( D ,:6@j=gً)` @0LhwArrox ]bpɿm4 '9(ݣo-~|b8jAWzDVoVT6Aiqj ި@7?vi]f K.Q2$2Mp9abxMu xȶN4ZIF 0y3[SwYVMq10N[Ј8zN~Ƀ92L$ }zT%COt(%;-lB]Q >x,?6IoCKU}FjQ6(hmVzҨ K(u:aja¸Z&eY"eE\FGd*h4Q)X*Lqrñh|MTr8&=$ %T^$216b 8ʀD(RNq9=@=oQqi޾G}6FPM!1. ' Q uh^:X1W(:77q/,..-8 g6K z'lPj4U<$NTw _N* M#yMgcBl"} $ ,`+vf,H n(=CC;1h3ˠ [0ZYqD=0O>$BATP3_' B?zJ`9w^agkbB݀fͲȢA=X|n [!A'ClMU&/+ҹH>80r)7y8 `Z wj>2&@<'N|uadmX{-ZZ] (yji'+'/Ju€ߩe7#Ntj&&&i*p[!i9( OeZM@}YP5>_D8ʶX $tux«~ EB_ .e,oE#) :A>倁n&I]R^i u0DS\,уӃin~B,G'#Dp+:gQ4-*yAܣN:xҺ#4ODCjQq+8?DaXT֡nY2g=G3P ؽlGjU(nlN `>U¿i:aƐbJߕGr =+I8zfKn6hFW|8}aw Op;9焨GvblEA@i-#(*A o4\G=f@|?ҥ˖`l9W2stj , r zRϭZEӝn{h0< 0 t,F7"pmX x1MrCf3̕l%QeXOj\t9e@+4} ݉n=ƥ+j'Ja|,GI]غOwn(IX~:C0c=h[:Eݮ^Z%HaKAH{#RKr-%DM:v?O֤_`MX&I/րhjQ}Xj nbDi揔Eȳx,#WLI>R|[ V EB pWan_z]y.yi bnsw(8mS*7JZڭe ·Nh/%LIgKO!(*H:Pc?rGQo@pՄ~Z2n eg:Ix8x_W<#+[gCS}p/™X: bgPi@ӬS6w mx\l(01%Qe6=oǷ B.jjQvt(:l)mY$ZJYf/D#iv,7_Nx( ?l6H~*l1'iF+iP$a꟯N Nz_!{ՊT"SKCT+9#9,AP<2]Ҕ1ݎEة-(Rr};hS4saA6f=- 8j'+k׬NG0)5$Ć[B:;cB5} ,---,ѿ Oa Cj, n(6AÝ >&b`&]}7_@.X 0ζ"X{k~x+Ck4y21$;?g8;*jPHeZ{cJEdӽҏ3ǡ'+Yf޴Zj(rvEei!'-[IJ~Iv0yN{ՕxRsˁp*Y4C7CN'b>};%h JJp/@8J p.ŷU䏕RM3N+`M|>!l`b?NJNyԗRj(- 4┞ܡM݋G7a3d}'08T=4) E{PCjQ hB,@*܇`)brgRvAiZZ^[/v/h5϶:al`!ʀ)xWmp4`,Ai!ѿA-0Ks݃p{TH̟2]#6nKलȪ͖);C_&{*M6o~1ߥvj Z2-$eJ7/&H+5aomΐY);0aa nGk>=NX:`41T5I"@C]O}(rbTl8+uxa0A]8 ô7'm;F(_{>Y+M!}x /<VЄGvNvqD7UEP j^: |@hQIvNp?mh64T,%<efH"rGg!0*_e>1 as#OđZ!Lc'UGq2´g/Ƒ S>VW[ b K9t禵k7ۦv1}o"y+NQY SWY;ykjt|KݹGeZ$04=Ybڈ?{3wFaJ~"Uaﵛ7illLld*D`2|*OD;0O7 nX(E4<_)KC@%aB0 f,־]/9*E4NuXVۣ%2XlEݡ")dprj - ՙ0,ѷ_STDB_wd~_ᄅr˥ W!^#Т g VKE%(]h/"_xR q8Qw|DSD4Mh*l5>|y"CPU+~T+?1 ]D2 B+Q_Q .b`^\Ppqd-)+vGZ~hvw'pOUW 󻴳PQp" NZ`mPAiIJڒ|FE4@2^Q`x6UZJs trǬH(JEL1F"6+h4/Υsuzu`e͆T<qЀ`Zk L=^lާlNZ|S}.5@yFkQ@w` ^,Qtn d ?G HNv`g8Ϯ9łuFiI1s"4SB™ĝN.ɏD6v;pāWyM|y 4 ТZ=K4<?M =$^ .S8J*0= ~^p~d,}c (ꨵer\x q bw5irFkBǍPmFinЮB0Vgy^mVgff-U >0beZkk׺{|G#g\ҢZm\H4N*m8.?<Ƒ;45=up4IXD-CsڭM!h/ I2x:׿#VUoܸA###Dp3X &"1~o*2ZXYܸd:91ZxY!ŶH*>EWgX F(` 5{|mκ3 %37o b .ѳGoI6#50I5(}N([v,`y=P`{i]HʊnU}r{ڦ>CoS <85x+"JS*hZY3 J4Z&/-V%lژ,,_&'+C>:C]3տP>;I'0I$K Ubzk$$W0ݑ@IH&K!L |b4k{Lo\PZTc TiQ4.=~>Bef3?=KOH K!~}iH-zTz4ã{Cd_XWUiee$@P3x{Xd|dSh<`5`p2 χ(L|UU,{dXQ.kH] ERX9E obs||< _{ԓΖZ&P ErGTE )ķo@zbNXdłK9 b4=C'* 10*c bg@) YJLC'זuMXK;;Lԍ* 'i*&dN=ܩj ЛޖƓޙCLjR8U]櫻\H6+W5h\m-ڋpc~p>@o^LyE'S-w-. wgt82(  \xq7y®P40 f;Uq.:T0&շkHd !NQI_悂8%|dq-wjx d"w*I5j wzE(,ss%p|L0s9/_CH!$Z $DChQtZJgݼ5IedW.1O8^XxpV5~^|/a K**-pD`bBZ6 s?Z`Ίa'Y\ sFu(qMemݣdMx%w;TT_CiQ\H4N^W':Ԅ pzE p-"n{'0''8uTCjgZE7O< 'vih!f? }iɊBST34ayW^9|%pM~E0st@c 8r\Ub}kد`0<0W''WAihBp}a[` pAj_H[+P>Т/{N i&/-#o=^[!XI!ZFo\x"XgP'~5P?b|8 1KHp 8p8}bdߥ|bGn=ҢwܡrݓF.,lPkHNݺӊ<:(LoSW+$2.88 F翺A[eKFziP4tvYJVՊFW {CnY/N%! Ku6?DƬ>QyǢ,:eמJ1)v@,S>> )X{/[}xl-1ݱ6vEeNQolPa=HBٙuB 0vG8'i\D%h~PBJ0RK"3K#RuIֿ7L-^ <... SI<מOa!fҹt nzw<5hQI'>.Ff W6/C9 P]Nc˫X8Fڷ8)?r͙HdB`_R@J0ҙDɵT6`†pӁ_V9i.A/GO^싟~ iq~WPǑ /(C}nТ\H4N0'д23Dޚ%w(~ [{%< II\!WNrOF8 KDK)2oHТ(G^p*gμ$݋ŖIfy[ƐBt v"2 &}%O*;ju=٭-t%h Q,X PUWi,uj6T͜O) R!$ [Gu&8;S–H~ 9\Nݥry 7ȢǙT Wy+,XF EԮf,1K󟓲<85Vx%F? K95ye>8'KSttʀӣQ1.|'Do/N "omPmhZY E_HBǴcާ<" \zb5j&ti'cG,)rl6O>Rfހ/,~p+%E[ >W0(.9&|dߣl|ZtsT҅D*FE%n94SIT֐ZTi4ٓDR)3 8{{|'9g"\D]#F/&}l?KYF V4JUt&U"?_WY J,b+Mv ~1eҢ QɝDڠ^ZZ=ړcD`p+  yzFNkiP NxJ8 hPk팓5.8Y'*4>>N{{|*b|Kj_~*Fв ]WL 06y(FB l藣\hI-I䤵AHǵAs!9Y)wt6rajg&DfA)bLp ]o~.?X|֠Fi J 8]` $x}@ct zAmP4ܤ%q$RD9(Z\T4+;Բ^Dj4 E.2jHINӛ ߹ɬ02yEC"w_̍"(P(-..R`_q%z`l&OZR?#y 3>9|9sQͼGOOx~׶-omPTբNZ!Z^Gӊ r˦~ŢPSA8pf8!i@ 0>xl5:{a3Ë#?9rAv <-kT7M丣= nqU}bDڠ AV^vu2u f+ZXI'4Gn͝2`_E oDO5xOn(mo[Mh0bofNAv²Y@ì@ *&Vhy_j T,oyQPyՠG Ԏ;KZ $Ćݺyxg-jD;,pZ(q}RZX\ joQ94Zf^kbpa=6ag}zŢT$RާO{nOx"ETjMB @O2 UORtFadɆYJjO βɼC @Y /i QAܣVCp!ڭKТFIIrh0k-YS8e{A?N6o4p ܣ_?/x41۝P~(Hb9V o}{lcVKp౽Yk7v+duSe& GCe\e6vڡlxatdECZ7n {{I :οu&l-ihQ6(hmVi-*勄jH-*鎋F+OFe9ilAK"t^ X ij] `kn ~8pİ5q oaawj˨)1!`hp$S~LXAb̈۞74f wwBU[PHu-`Pe|{ƒh"u1"Gga[chZNChQ1!; NI[sI:˴Ae~6gi25гW\1DlDq#f8 96:et_@!&w<$ <?l(ۘ Hnh u"$ҖZiH7/T4tjii(ne0SԮfL[d`eJ%SdqΎ1lt'<ڊej}r<6[Tk3 4%Ѓj8.P\{%zZ|<p9Yx&]$lݹ@4-ڛRChQ(_ԭuA4d!~VzZQ-FptaikFf!j: Ӆ ^ AoGL(DbZ<hvb||(xܐ/W}!nzU)D`t8HXȬ@l(ǡ׻I|i,Yb(+"Ĥ{]wRvvEa. ;JvV*( ڋ.B%jB+wVZ ]Bܽόԧ$f?K+v^ 7%13Z$- q7@LxQ])"\xk€G)i.7jOs;mpN*HY.Hmta>.V6 ]V[ ٍ8%ݩ})U/=NUO}˜i9yݹke@7nr1^P.eKө@S',QfZ s8J\At1BŁEΙ`MRoA7ys4 hts1`1<=}Q&Q6v1 達l@z em^R!!n T*Ov3~h*ۓuj/ ˇv5'kB[BrΰFb\uKքuOg&us#f~v>:_'B#{qsk(ҀQ(BqHKR aǏ3˜JFMdE-fϕ;ݫ`Vjz1f ~ V.lq &$X}tv/+btPJM3ҩ!RD+Ymf`f*M; 2v .<@|f3R.HH0R1pRRv@U-W&QGI[9?ű{߇qXJZV ?kǀ2d:E {f\ŏ,u < }G!*M"FkSC1_N8?5҆0b}K)|pe@yVמJY{v@V틝-TJp@eM#R V6\Չ /@VN"+va)^ybbvI%LXG2ڡ4D6>L64}YO1Ad["y@dvS&)+DpwMXð!٥C)kîUKfDz,*;+Hm1k\N(rڬ R&M=>M75k.&t}FnUa'SqU iej`m 7|8!2q0 EĐ=r JsRxtS>i&€ )T>c, 4{6;;]2 Q^L*8VT@*KP~(W烪>YEJ%5ڬlX\5:Cy(?Y~{]O P!ln -e{jqu(8xby&[Y0GHRy67%AL\0MЌL.Yus1P p"kf^lzq 3EIKEaFjp\ƿPOUjò*+?pt0JG}650^grP&'M=@iH@?6+0p2k_l`~(Le#Rb YN[v#e$)[o *[ER[<(bm0n)% 4bbj8UC1:8 :A| 7F""28{E-Ez~AMHq 0_C4uq&a@G˟Ao=i[ kpݎP. h[R#Rv#JlڃšF(-o<\oy&뉁bhJ8N)34͢!<0f׳m ݺa+*#bZpGBJ LA+]P%gǰ_IV@r '̓8RQfoHl% 0C);-顔m ;dzUO,ȹle׿9S,{٫S~P9(SUs95𣅩Sنl% NvU}7|VCJJ$%MVJD(1<`Yjk KiAb1@qJt}O' Kiߪjx?‘KYEXjJpt!sv# e.pN`T]QIY{dUu+@P_*[^hMӄ{(J k -Z 7KcwA?/ʧe<@,~nB8_udر=y4+dHA2S1+mVQ^\]S TFN- ";AR7ZN|ʀI=wZfav-sJ7BR[J`%@5*}"/N忶صk% h#v?App좑˧X4id)=@J 0vp,:w8y< {sA@ %83G@3vLyp Cۑ(ZhWD ;"М9x)+f]ƆnR K$"9RTYK\Ξ ciތbZ#nvbP 0cTlF1' }\t>c(S3bg S8]Lfzv6, 2d\V~@_&B{6ΏM'7@'|HkF&!󥌖3p !+r3LkX$,EE" n_R,ə{ͺ@W+ab0K:UHHq2;+HvEa8e6+aztkA,^G F&! D+GrYfy+47b`1tv(pgB(H`f(EF ;q6^1|SG(؝ٴ$n__%Cc;7ԌG`i"D,yjP>] b1u(؂`A \&g7kBӮbJ|Ry%]+8YUh)z`hnI`la8߽kD"57b`1@:w)E_qGnpb;mxMB0+&SW BoW xFyl;wuw[yU7b`1Pv0UFx1Pz@PJI*%Sɩ͟J< H x` 8(g@g/~U*Ldo~auψ'Ewg hog;+M';Yy"H@[<%@P6D "Y0 ?`a:za;W P%LFQq>9oC'&d+%5-|AbL5g*6J*K/M lo^\ 4 R("RY/ {r$:b cS+PN 9Z4lLw8fy}eUNR4,+\=;fv&m3 ja@7h Ŝy;D8<=y9T9vtQ8ZӯԊS$]kb:.A0+%Tpn ?"-P۸q0'?(n *n$!!|p+n__ ް-p,xN#Θɻx(fhDWH0dfZad\ 3'"Rt`Y ]|d,zr'8UڃXxLNz0N~k-GFXy+v-t{.a QnE="H ~VR2ا gl@$B M͟},**F5pLDq䅇25fݢ/)}qykoғU:]HHm;Y<%TuV] R=`yCṠDate J򢳳Cl߾g(r_sjrluA+>D%I3m"ϟJ8M.ZE 7!L@j οZYDzEaYMږ|zXL hzntW>Od[%22|0˅@4Jz1͢HpH3}k&m&$aֱh?j*ZgL 0Jg9p?yh[z)}y#r{v1` hC"5'pE^$x}p,X _ՠ\ӳ W51 =]ϗ;J9U ŢRV+_ƀs(߂MUcc w 4}C?'R߲Wv o e7}*̬>? ;CC6Õ)Fx:C)@g.QeQ0v;RI'uZqkIO>.})(UlظAR] Nn P|^[q }$|PoQ :8vK;45?L޽;3qs)pSb 8nr1 0jEׁ>ؗ9 vV*JUVgh_UNqnվkɏ荞p_"Xamlw?zª{[/ @ۣgPS?*+g+r^/g #_TD${uHܫGx>XRy^j1i|&T;ΒPٮTjgJPNz*e XO؅8--^wU8 \WRe?oy6Fgye[ aX!qB6?)>hǎ: vG̴9~v2 s*:fk$&Y xA &&Sȳ濿;VǀYԅWEW\QJvV*zM>$@IUisɆr%EZ{kxyKoLw-߮"Ldb̦( KET,I{KJmAe<~J+J SAX8G,@sNaQ6q?Ϙi; #Xby=1Z_aXðֹSy+V"25EۆG\犤^'R@UUUVՑZXF}h5'^ /Vc#jIJ7 QQx3v:Gg=S??@Paz'3jȣzܘyO/d-: xjEt$A6J Ix_ɞ -s6n'@̉_lЋi"'=TRxԮWTu[Uǹ;/N)5UVU ~:3Qԟߖaw՘sڽGͩp<(τ" h? -WO'AQyriYZ(!Q)7SL y1rwEpTb,֋c8\  5<Lgryq`5ԨfXpmz,]Wz@V]˹_ o_?]k1p/z6E(F (k:n1ԮυfI1r "\S'3GB08)rGbO'DwDʀT;iFU<QE6T E !R, 5M.nt34vUv7ncK^?Xzm [ #B@ Κ9q(X?8Bw/OүزzPx R`P W " "-8BIUVQ{5*Evk-"oHy<à?F]xe.v-e^mc 䏉˃0Uΐ!y_5[kH!sq0;%SVe9  DOgUDg°10)@1e[%0#=s||,kYM=JN+kVg>ԏb0/6XyR;wO!,/au\#ofzξ)VtRKssoû%$qwEa1312`[`;<q)1VݲHJ*[ ֮'?uK_m6 * ]˜G6[m}\1@2nG/|/+;Mt@:ݱ/o_V0 ,wI%gÊ Czy)NjNL恳j+ }bAl~^1H8Gک*+:O UJr֮ s.ꠝZK^E󗎀$LsYڒ].&E3w+`?@_q|iB1'ןߒλ;E< PEy藣t|8Fs絾D X!}3c-epzsZcJYBV֨lCQTS2hr53 xۈz'nL) v]ŀY5?{mHʌ6kF @G &~!P#?_n/X) _YOl0[a,ҋEL[,#lX@0Gb TL[VVV]diy-% i?md#8ܤ~~R==@#0@>D  $; 织g~z|R0\qOnbWCģ)^!WEQZ!q x;áI@b\ 4`-쾑~C lwOU\ng!+36T EUݱFcN cl$"7l njyDM.F3Lp^聃YY'ǹF))Q#g?'ЊdVCp2 0g/D@΂Ӽk "kގIg0_w0@2YAg /R8Y^\@W5DzLo^afĀ vpUs^r1(0x /RKO׿w3yɦl]rDe#@e@0|?!g)e ߛS9!7h6`HpV {\U PH|3KJ8˸V5 -2l*1.Tkkk;vo]Q6⩫o(\R͍'vs~ Ubb_]Ds&Q3 ʀ ?2sp_b*ƘyR* $- J5p@d%JVF W /Lt Jm&7hL O\y D0I5/W6c!`|oM3VrT$`媫'X߀BB[b"3zE>sۈŪh2mqI!һCbB=EvT./ ۊŦpE2EZ#[OED@ ve)^\kǵ²0Pw=_+l]AK@#2SF컐'm9_V+໛̥Gr{UXogF& KdbQkj 쳢Ri//V%Eʠ* 㽂fN*+m[_-:CtQ PΦ_Mo1k5k,=R/da'񼿳C;ܫ:cq~/d\)H7xk0; IHգpC&NpmUZ+HD/d_$km. p:_LBJF@0/߅JYhXuLaG[۷ή.cmp! Poz+X~f w!wCA(&}ppɱWqKB`Ui5qE ݤ.Y(( >Y77a.u=ŭ;bZiy?7 ƾ=-g(5XNFx >-"*҄? n7h `'4]zt#? 8пuJ̫Zc(W=Ē2~[ "%(O΂Ԭ+ h_GSհ*iݜaycjѿ=/! FV5D?L'XVsoڴIl޼ْo^ H(!Ʀ䏜!ec?F*O̚j ~WXu:uZ,(B<>P)Sk`~ \+S/TeN>wz`>(d>c9ƙ:YEZٕרJ#˨_㟢3?a ̭96%t_zU5~&B?Y_h7Z;?̽:zK%uj? -cG!kS $K sFdz_7Fj½c!1ō^0kF_cn(Z5 4ְGK9pcq57; tzL=t _*U䊐tnxK^8˃>nMūhsėkׅdLOL}c}necbT= ?XPDg}F"= z~t3mwi;޻(ZWЮ }a+qAvhPN.`7N'J;Otaߥ@ ]<}u>DVIE7ÙS`MxkWsђP"$Ro ՘i'۪EfeЋ4ԜG P?0 m#y.nr1 aɥ<@^R2@cK:գ{sf˦NHB!oM?_u=w<yj7.=oc.~OThgJJ)ݧ\ ? )]~e[ʠ}֧E`WUcoݰo1@?m҉˯k C_]P3 ~@aXҍ8 ~n<_z2`ۙs[Fm(@fox${:q-ĕ`mYa7E97 ^~_x?BO|By,ꂻXsL?Vp^~C/v$&L{HŅG!0yXO:y7NGnP߉u2`Y `"ziْWt pĀeg@ xԮlze5ֻ-jsP_杤Ooغmk Ž'.F?fa&7p$j`QR_Mw2mi?f?ZPYEAogh.LrtͼJDE@8PClI-7S ?j_[2)tM7?S?ѽ7E;( jl FKvo Q;fmIo]hg Jx/zw.bck.^^|kPWl_{J(jqbv,ϷP(Y|W/PbV_D`\ o^.OFz+ ? ӿsHhYН|3󴮖7kȑp'ny!'ξ1|7ZүE/FxMĸzAμ3ƅߊٱg=^*T? Gسgu@2S:|YCDgssYGa Єm2SOL iاa&_ S絋d-w<*_ޞ9dKZhE1P6Kw CH o~jLhPSwfHfk0`I~q11s7|`K"TNMt yq0ح7EBC)-+Ub)]'pSjXbLVJPTs?U܋caԿ>(k33w6(2Is.Dž{| wzpsd$t% W- 3ޙgGnn#@f9n'Z "L ^MtBN\ z_̾1v.2 x=! Z:쮞V}忑~cΝ;]3hW cWrN ' a *v BnzZ!Pqug/khKh| {U-|m U - 1`w (Y&*o۶mǵ{S/ P &ͷ02}% uTcߞy]#/d_y6>Drq`]7Uaz%G q3FhCl$ro>_|! b``?r_(f'/ ΰzec܅t1| O2#:9xdێB1׆F6pq=_*}%g1)SsNGknhtKcGJ(TE'~ΆI,R?P  b0}o Cٿ_~7o(euہR^z1GBw!_ݻ% 54pOܛW'=YωB`]xt㹹D/}#[oS9q<wylswI#b.r_Ծ̋/ܡt(0%~f@IDAT"U &?B_7Aȋ %HTm.zz\?+?Ч-[zcU?8} AсxJt8KTބq[}3za%5|VTO^€?fQ8n^zWaNjE4LxIZH m~X~#xTnu?&Z42'#e':g9'P7['dg۸/jWŤTJ~ Nr [KTQ_muSN;Pkdn? xD:t$#RJ/4a'qȉ7oYgC'0g?;k$_N_yn[,R YG l@7EbDwL ϏSi}C^ ~X:BnMǾnbŮ\ˊ~%qGT߾0 O=*?Edo߶e+Ԙ1}B0lcd䣁+dzHh^-Wo뎵EQaDTSƒdWe43 T՜شiws|ys=Y.e3 #/M|/D0+vBN$'{|SpOoO6`:~TvKp4*= 59"C@[*/B(8&l^cM ,vyZ[~fQ7P.FG_4J~\MhBXpM ʻR$WD ->ᒎ[cŽ|+{vDgr LM+Eob8ZRwzA+aǬsS3" ri3Q^KVKif1쏼wGX`CʜCBEg|o%OsmP9>{v2b$wF|?ٺ\QLE nT7AI_D+/t`IuwOYTO֖ESWC(*7J|o{8w > E)C4`:|dzoe]<ݟ3ֹ"z{|G_q2kʩ+ov4?z<;*rx+ X a@ysuimð=˜5p߹sp_LuWn 9~͞;Wf[pD0? 3Y~+7'omyp p¸#[+q"`|\0! )W`DZsC{#oS˖P"r o]FXSoW]{|P$bUköj!0ϴvQޅmȳTDXd`в7]-S-=ؿGS?Ψñ7J\J~C#7g6 d3s+.-Q?j.(5~g_O)0=@x6s;C$HRN~2)g-p-膠lҷ?Gs`_VדRz3{P ڀʎWl9ro<{yarɨKSbߤ"M?sM**ߦM򟋪V@ymQ8=kJVucC'n# ɯ,YrOkIP z" d\(!WDޣC_ ڑ:tڻm>?WV0Hߡ~ C"}ˏ}הR(nZ&Iqs-QfnVS#ƒ<S2wbj _>lGf0qwr3}&4>9l='*=Gcoy)WDM'? $ޣ _~6[ȷ,柣G)Z^ -._htܑR1 R Z.ڷ/b1=i0c4r`c ۍקҿ#{~ctW9xGm~uo)#܊MQ(㭬F<󟝈*5YI坈3_~ׂ>JnҢ7Ǐ%otg J?nㅃ;7Vj.tywLcDb^1|MS3?$nNr4 ~ bn8NIc=5hg-0ޓUK5t_];Ե&2#~YkyisV Aa(']u5qD8e$OmG)?lc_ 6}e~ci5,9ģؽU99'f16BFIĕ['&x ]p#gM ~Mxiw^?uUc4;Y]HBv <[yuJ o:/Kvޅ°к`(^};o231f<7Bڻ>[wץ\.׽%\n153~lߟ ),Jѿ? w ~zzsc@G & V I:՝nI!B/ۣê1Y?5)&Q3?lLlށ?@|]PSTEO-UF3ָc۽YxW{buڮwoy3mqP s&Nbϧۅ~Ktķ׎|5DTXJ%34_7! 8/aHb.dCP0k>B3kM}_jp8F7?&,`cpw8~5S5P=%%("n2~'_b%Rq˵ޭ4'؛zt(S^? ]t*bן8?{(BiҨ?}&o:MiZ?(rg,l]Sc&+6=9}l۱k3$zDGʡ/'~`w>J̣FG"YvS+0}_xoH?3ŕ RCĿ;vZe44$yS?/c#qXzu϶\0q; /ſ>G|}7^GKg~/"3wr8 }bCcMcFE[?$'mtckHD#o+ I^]'t4Q@ uQ'({OMĹÙm+X^Ew$6BM?o*7F>Lm8riAUۼfӻ5(n"'{LzP|'3{fΈ>˚5eI*Qo7~Ylk87  8uyWXb1ͺ@ly('%1Hl;$;ő@%ӻDD$R?|폕6 y`eOLZǺD([7j70g-1IZ DD/ɫrႉԖKA˾Kl|H~NڨSCәOk{U|@9W'kRϷPs/$A^y%½K8إ_}'*Y '|PHD[fco7O\7ӱYO!pO".vӱg8t7=S 䩬Wp.ʱ! OC8Nr!>E-W=䛱epXn8:}AS1&?r)V"$3UOaB!d[~z-O̞v #q1ogZr[?Oɧ~ 7J ӧ4鷸ž~y  sK7O{ju~ՎL7`gThHUM@L1"͊[ 7~,ԥ{4lyS<[q_rX;6<ο/2 HNk8x77E5X3+xȣO};ٙdcc E^J.-5t&*5a6["@ *HMRӒq8Xz|s~ē{^o()^2~}.e/hp;zD\֊|h)!d\lDŽ#xWyݿ?D!VG,\/!svG3qIT+1>N]u ԋȹ'%-X˿rь/`z.I%~ DNρ?}(mܵSOH,yH_7mK@g]8*}rGe7'"GD8~rڊ8eHٟys8?>pmS^:{_؆r3?xz郙G ?M"0w@T}z餥kmņM촉@;{rߗ U-<¯DpFO 0BjjXrn}H\ӿKvam ƺ[C_ƋH1iO͟bs疷;tC' ;=o $+b^|-gOLnIm[jV| ?Û]:ab1(:\ 78Oߍ|pbb\X~ Ciڷ\BofʛC6G΋A F,ʀ= 3+\&o~!]mI~ukV;(ZXBS9hꨝ~;!xkc$\%y]U ¢ s3/=\`BU(ӟ>|?k R6s ˂m?og?wv%7#)I˧M;?l).6cS(s-(`Z'Hgr?8<S ]͉/¯r`3O}n̻_y'i@Zi)xqN׶~;g`j7n pqE3;Xw++m}ik˧buzem݃l`f0YH[=0qQD}b붭O 6u<\>EYr*6еDgz|>T""@rO W }A$fu.,J>>xǻ]r'¹STXKCKk2G~;6(A &~<߲G^w^#tmŘM1Goc~?E#m~8XpO-q݄@-r&l&D&fOC4[]U.M`>!'Co038kkn8p[Ŗ &=鑩DB0K8x}߃D@.ȷf[{1# "0,tj,chG U |bϖ%6C?/u `@9w$.;)?@pP/D_/N)CAeڦjyC|Drc1SnsSơdǹݼ͟/~n?E& |q҆b_J=:'sD$ >ډ1q0я.h_sY?r].6]6?_ٙDaTCP 3>tA"D>'/ D@w_ܭpwM56Fc]p Ќ͟c"Zf}s/Ψ0WE\)vjHNJ5y# TZtWksn5SI~?&tWmh3W| AO*vl\\xP _-d<;}$eۡ:;;aK%ٓ|wyz~ )?NAT pxdaa ,lctTϻvvgwU>?h~7Ԡ?a#hDlTZtvv&U_ F^\$3b#{@9ٟ)[ {d!9VDǾkn;qC,< qRRTA~|Hclf_֣Nܷ-p/ jtZ/pD ;c#6 4y)b4~o/)X0h< C!:ֳe8bIG+/j+kSGhvTqgc_D!:K,C[Hwj$QPK~gj+P2Z{&(A~i(A`WKKm``_~໗tEBESrLO??^|{6D?AMz"ήD ?R/۞ @MfΓef ;qEV&#ͦhE5Ͽ8ݖ/o8)^0OyBF߃WciC߄Oe*в_{Ce~Ս}'!_~/L(XgY>#;K@ɓ? Դ_ʰϙrE0}W}2fx lSԚSS*GfTG?U#E?. ) ?#r{Bn3y`jҮla_e3dc-NQ(E'O}Ib1~\G~ȁ :W$Qz],=9(,w.qr1 KO4"jvCy0(1?ϟ'v h8iv$2 Pn xG~ۈakj²,C`U/.?* sɕ<=:I0Y3I5~+911??j?',Y*wպx#>mΟ}~+a.Y}m9E; noTfX6I B 0rNSFLDUc7e R!sZQtDfCј (pgxZ=|фՅP}FqgA~;0;o 7B+{.&8 w"dv4M=(k5c]3Z(?uJ_1Wcz_T-ԞrH:@LǏu0GD_HopbG>~fQ1@ DX'#_ϧrLDNWkn=HxMl3s+/OFqgbh~[?pH5\?%;=KvMb މ\9 FY0c"C& g2GZf)a f}`Xa°e~SEkp,f$@kI߹` @ϣ^NxY"XJ s8*O6B/~gTRa[-mS]a IJ}Z;&+B;WUu0 kEd,W;e3s"Ujb.Kwȴ-Hl)kԨ33=AOaghx 5ܟET!| k3-SC5,iW~+Polf?@?bʵ/z+s# @vw~3\ (G߶܉}ui;hBObpxNQ @_[S>Nss׏d^ HVwգݒ}eq彚s *ԵfjBm"~U`!?o uK<6cPS7_~Xx*Wِ* 8X7.\)IB% :6: m  H.0a̔J}>;F8RW~wk)MKMRf$ؚG?|gKYۭNɑ¤>7!ɕL/n:z\ KcGgxvy/oAgc zw{<(t UHm)}(_%_O4 , +;7fMttvMcqV'u/VF S?,zQ |@Yxb09`F}.5Xqkd7 ֏"a xR3Qo61xl',>vHw^;x=ra/DеOZEiQkNXob8K^p%(jPfJτAhK"d1DfP_ۖjtV?M2叁Bo S#,I  sm&ӟ6u/1Z_TO -/@`hD6M(WR(tG5ADg̝7Zcc0τQe}ﭽ7 XM{_)8|#@ٳ̞?|wdzU̵ы:e Q?ݦ s;@RUS WĒKE P̓9S}vd.{ hkٻcgcP(,DZ\~\þ6\jзk6e}[;?YN_9@Ks{~Iv^[=1t[Au։Ex'gS=ťy_}{?%Ze` 2z,vcE?`9y| $ 5f%G|8𜋽8NҰ#yԑ ;MX9Hwd@#a ڟ~ @@Tkg@> I$4x)$Jc?xw4HkK;18(1L%1bLxwӛ@F~Wo8v6"Wjޮ&Y ``V2Ne^X #1rݛxS+kL@ퟄ`^Nx#$ k # ./JMֳoha< nnep#_ukA$f}4coW.|34%u p1Տ?]Ny# y䆯|-܁ (ݭ:3G#NMȥY0@/Iͯ\,Sa@si!+"g.{a2;%ZT"gtKu-J8>htjӭW}c&2zk&JU_smY=LS\oףWI@I$fU]m5Q hb~ShTO_nQ;.Vp"@ɋ"sۣ`aFh=-?i2aVP۾S,IDY]"i+<5:t9pҏaqIH _{w.7 zi~'-@QEQ9 [_%rCpR%n5i^V]2l76flf/|)P( ( ( LHq֐#ߏ'spKKa՟Ք! {o|dhL~.m̿B"wv0a][?% "kLBn8ѽߊ ZlR$`ꊔfQp s z_4~u'wbt )=ӋYC>2+7h572>~Z<"qMDx]>Λ=rH>,H4[,7ܵ`۩;PvG* [ Ta9D {?7owK9M"< #E: ϑ_C }bֆvxbG~=M Px}PwlOE⦯^6ғFwlRy4Kʛwou53#NXI$~c?bˌf}$;h @>f/]iI__Xw`e _?]FOW1Ih azQ0v}zޗiumQ{U/DՔ^X }gWv=t5zH07%vm)u{j1PQb=?GE[tjx2?B%v2=IƑڻ)CKH%GԊ:w `O۫7f;QBq}M}gX~\`Ma}!3h}+oօ?Ft<]RR'3>.4mW< \SL7'߻\>9-!`|v(Kbdž xGEM\{(">N.6īBI`^HJ݂!~{ŎվMMi/TQX~OaZZjO}4:o;g+ AFKATFe"$Acw >>AJam@IDATeP/n឴b\`94ʄE,)(5qac2Sրz\JPMHP/Mz>s5pQl4n?7\Шp4Z4 7ן$ e>jSgaLI-T4G=wcE`u%Ѽ؃lhG8-Eg}:wk>jpªnDZTFcƀ~6 0LE,X1 s;i6X}ՕŞG݈7l?qӁ>`Utpu2wCEސZu>5>/WEyrdj4,@,5]GQ]?IB ;?  ec av;wGR7a HW)7\.NYG:/,!ڱ0HLtр^#F5i aRS-pO??{vPʗq:Y5X)Zm Pd%nb6[2_+y0 &] {>; ْ1k@=l, gޗb 4yXh Ɉ 07_Y!l>u8^3{sqoo}u63- XnyZT; 0-noxZ 6GksAԾ|( VY&M?B5`Y<`cˈrQᯨ$,5ĊjY`ڡK=1e;ytz4]k29Ƈ #`GA"?j$PwZp!_^m}aϣɿ?;irL5?HG'l.zÛ<}] <ȭ9w8_AXͮ]O&~'卻w٭.KK8w5(!,qR&Qf "Т6?S&-aW4UtB(j 9/c@pd_[R ]` KTN"'b@ZGXC#x-w/dNXr+U!?Uòdu^OѢkA՗1@7 2*<`M|ѻ =a%͢`[7׺wuM+?;̏iM%hrА&q xO>>Ʊ,:;;ʼn.ğ0kc^Ok30#52mowczoGRل'\\ "6CQKM}Kw;gp 8NAf\m?)\fdDJ Վ${]Kk3n{m8fRNOPBBwLwEvwWk6tw?@yȀVت?W?iW&p$M#ځߡ% B7Hk#|'sE7y .^ ="5ĽFM׸e=ٓJY-xF.v(SȖV}׮gf&Q(Ͼxoz=9 &~}i}s6;)-uӄu_5)55}Y۟4 ἒ"Dz~eK`~)8-wdgB;?lɣj`jS8m4/E6ր"8u`0F f )M7/yJaMKVڳDke8A:5 O@68-_.;BUÓ~ o2=}b |l~bО+{0wĐJjJ34??F2Z45vZګ"AO%G11͏$nB)J%x% `OLw2zLG ?ZX Msj} QPG; K`J$c`F6eI_+nk5';Wz=@,5"\~S8?f{6ηVI04 ǿ~#'7ظks5" `s܏{kuЗQBapH]W^eVWKYqJ?CG)p$q|pRw9 at* ~|[OäZ/OC2ը ㈳FF`GuЦ9BBi-w^❉ם| ,sŴ#`Ar՚z2o]@\L2OyS/Z3VC~j~Fx[ ~Z7{GAP `@淯wѥ@?NfU(J@(I"$%gPۢò[n{]x|({Z*f,vt%ѕTGNC<^L`Fޓ/6\hX_EԋIo t$Yċrc}17%тޙR' .c{ٞzg29ݙޠ1\O$0 n؅̞ [)ve0Ս!~OӾawf:sKӾA6=FÁԾzkto"J`|/zw%uu\\(^Lco"(ܪC0x~,>ЬQnհ??+OmARIc=JѠzv "t=>n„zDAAs~w/:;́K9QDIp*"RHP[1"[=h|,ͻDSCV/bӌo&Be&5~ۄ}~h ?I?UߨJz;bBBsR>#%Tm%, wCӷEn$ittZuG{og\~$D6;vd4cRY.Fzd$\3γPi;^^U\/JvEΖWYLf5 k dﶇhllpq;sYIf] m lzMӬV,uB_B~85=AeU?X)Wi~R`1/Z28ZXP/_޷#i41@ކt}d Hu" hdRHaSS8u6ܘ92gx[jE9Z4 ``S.ĭ>t m6o hfݖoǴX7v|]ۯ S?,kW3ϊa|L=TF]8 )Q̖~J VՎ8j<% -x `EO$ ^.kjTR՛~BDb&nF@F #``.[@2m?ڞv{)KK\c{EZS٨!XJa3) tCvͥ_oHqGLݣbDȷKg<4zӤO3bgߏ>L?tCt(j'`??!c5SXIߑ/ALlNK!E9^+qo)L|8*La^Չ1Yl `-t[5 b*r,׈G_^]oqb:1|0'3E IYx1ՃɋT\얽7~԰o%v#N{p~(,x5~ >bHk[z~] Fۢ;}YGFN h>4c (p>{eωq,Ϗ^{Yg.X?4j (4_p$ŤXtl d5y"@=ȧ;?Bwi'_E0&c23^@g] Tq$>HG0H/=OiNdb^Cw/?ԗI岃&d3-vZގJX,pb[N=wK'Ъu yidz'p=T (0+b=e\@]nHK\5ӛ.ˬ'Q=.4$`'hb`& h_V9i "lU*627xꅛ6vb KnyK1,,+ݎq|F;,F*Cqt7>!v1 Fq l)T>AĻB+5>kj9Ek%Lt+rրf\onJ}\u~C sK$#\@bזxrK|}IF<[%FR/.Y1ڟ#9lJvF]V>yVޑ7ޘm XXvv ƮƀA"M0POOkXjB3Y/7ޕ=gagW7۬N(LJXqf [I^isG 4ېg}yrqqpS~r|kÉi'hgše~iPcUc"C1K@c};ű _soͅ }5XkǀBEɎg>6=kFSj|%p ȔI#:p/`$v >[z ΌX|Xtr $D Tz{9`8Ōy&I͆{6X/{=EXljЋP%eid+ƴp~9ff7oxOG2֛ڴe|G ,K?7j@MhBL@JYٌMwϬ{8 R@]RGp4SƠ((,b⬈=*CZ/u6ӍR28Ųwx}iKAwgUmg%:[WZJAOȉq b :(TW=.yNZPL =;2]^ѳ{hoEs<= gLk1vͦ=!6 2i|Fe{IFi ɢ9w|0߃@seԵ ˗}MǨ~,V+PVāI(,VӲtpgvM5xn\cdE1] K\X.TD@V͡ x:bNwK1|:AϚ[.k:3PglspSXL{-jK|dl̇7d oɏr4hH%{Zt@nXèM)|6y5]GP(`\9372T!ЯkO+ j5&EjL:"eb /_z증k3+{Mp|u Pe @x0<*M42V8WCSBM7?Շ|ˬ YT|ʾgU 7|좆KeMNg۞x`!H  @B0Pp^SG!ݚzRf,_d|!3>0#>78Z8ln}T>#c0N('-- M߇l}!ZύMۗ!@8 _#!#ة-5e?}_XkF̭DrHLR!m7) +5zG b &jWP[=WOsAB6CG*D:F-x9osDZx|0=fB&;ޒ'070pCa+AMϹ~xN\M~ۘ&Pn?ȯ ?_LI:N@,yUk<ͩ~iP{PV#_!&K&e/Ya5uX ʍ^/kMK,+(%L0)9bH5ZE), A *d_ZhI&<$EN%Efةէs1gU: a Vgco-Eou\f5r`1rPՊ3yir-fW>rm7E<)CZ*ƒ!%YS:N&SQj!;a2 FG}DzDC}o.er1 "`b(>kO5x0{kbi5@>.-$ץ yOy!f;7-6ܓ/ UN;T>2KG`:ՙN%&4S%ڃ;@ZȖKp`a߹~Dqj [/C6A*()$,@icJ_7-sY3" hf FM"ƠdzK{sRCVѦSJh3G,r>G,Ηpj .[Hg*}J@"QG-l's +{-';ܨ4]RUM%VhohvbO' ''T/ (P_keQ`ZtHH\x}y cdy78De+r 0B*؄FRk2?, THAF?2e ; M:9AtA~f0!Ƀi"7"]LPyn(KόC.E넯.fFO]o.>|~9>-_e|H. <_<ےŢYk'~JKezI4)R+"32DO}o㥾O6.֖#@1@owV4}f}0_Cp?Zk8_ZA9a1]kћlt;'}Zy SZ$AGE|ބZh D K@S-{AQqXd8F7HV'g /0k^敄 ,VD*Չ; |!!҄^ZW÷9Pf|>5}j~V.W,~?@^x.#7F)z * 4Sɟi~2 (0@NL-X`eS8WR߇Oz z"k ?^ n&Z $p@z1|vB;RVܤ|fY`D=rzy”OM z]} -_wfI-)@^{ŧn3ONje +bdǼj_럼勞&Ei @ R$v/Foy/9vY  ;?(/jtބ<+0v%i!YY.be@I+N&[  |k](]圚9!fՃ '[:cY{0=lv 4{}ǡ,8Ǜ|2~ 9z=}Gs/?%TeIYGiIw~}P`~ϙ/Z A3* 9}&ykHR W^5H_ #:S Yxփ|`AÍm*g" E#O V?&8MMS&SqhfޙDe >y =ȥO7a.X:!W'L!K2c6e#E _hw${ V?iOs?' ?H@\*t 0>@ L?Ю~`֡26E(>]p?l']4~g'3N2 $Qv,c$c Mp'WPu x&0[/&UP@~)V%o}m]Bs>>_+7/S$ ?U.E>-t: c*^J`,%̷{>oҚbcH{@HX4)Z'gTƠ A|>'V j<'e{م5:˛nj %@9܂n꧋eSV2~ËK<' i! h~>y6.Sg^s2)BX(MrNt:e>愑]|㵗x{{&o 4Z%%-?+asm'n#'oDaO \O_MRS`!鯕n-t0ΥKSl+^Nŧ~7d@ERMI`v%?L _bOiÉͨM~T5>j3_,$BZ8h01r40WCxIesiD|0 Tcm>e=W~fFnٱ.jћ6=x_bda R/|!eZ_5+?>G8cA"AZdDpa,Γ"KԐg<k EՔCxg"uG+zGw27[+޵ʿ~'4>APOt |-P]HniX>Sv"ϸ (Oja T Jhw X1NƚXZϸ}۲z"ޱ@%E` ^Mc^$bb}s\I}O ORWrQk %iz:܀cn8X fO=uq)יP'rtHo T.h <3E5DTuy!A:)4ET?&M91`ÒjJ$$G5d|$fZub~帳gvǟx>R((Ip[쩈Av@ľpBg k6xk0w?^l_zp>Z.&^cq0\ 4S'_mJT;4 (phrR{M/IHK:D2(2S.K 8_wo_r-uFSVHLy'qd>4#}{ ʌ;#_>eAP'K~j~JJÒ"%. D$YL"`ϓ4 cpsJSp9 -8bAqf-II%ZGjli׺#S#=aG1|/& t>ۧO>!vPe9dր$* "d1"3 O@hH6/xqߵJH"MUwTSm }/Ҷg>{6e6!DH-6p /M$2OAr (e0 Z8@BscٿNShI 0V:2pnIfm @qst @rՔhEKX0p>smLܿs1ZF307'ZH>^j$4+T;zPRij P!O"@j" =0W@4Цj? o (0$8ڱΡoDŽ11[2Ox6jsz_D pL}Ijji $p%Q:4 vs`Z\BIb> ږf?n7Qv_6bC L#uHϣdX<-f;K?bf;i82o.C f~ p?ՔfM̚hՁg$H-܇c02FEqhS֮Ε3f?z!) ْ^7] ftHA4ڷOm딶!6P`n~@ 9I" c8D" ; ȗ -Z#]]ς`eRYdU%2`ޥ@1rogb|(2nJ c}^ĘwY:OWX1O-_e@}KJ@9HD@fH$Y p_10.e!H Fh1wl_޶zfmJd4[(Ң[ J  &dS.& R}f%RY~) 0;6hvXNI-_~&!s"%Km_FO졚@ H@ *vS4Hk'Itˀ<*r . ]:NBvim[yi&Hd2(È^[)ڝKw F!}ߖ47{s=tTBl51aX^跾%K'Kss6,$P[P:K32i KSYu2YX( (6[= S:̧.- j'ia(q^t(RIa`ObFgac=X'Nv#7X~M #=0?.f(jE@ȟa>y| u%WMI%@"u3H^md@i1ܷߕu-\*Kd92BaRhhׂyqˢW!`ɢ%`Jr 2)f8gp$8L6M{UHxٓ2ܝ 6٘ޝ9nw֬- V䑱#٤SO 9/?p) ԕۥNv T>'Z8'W4?d`+B˔<"eiqmO-i'[[2kg(E}HkLX%~&O#t<\GŴ|ڛ 2@=:\ #8>(cǜ&%'lK'KЗ|}C"{ԙO/:N% ).ιO {gYX A ʈ05/6YNks4ߢ54 F.9!T\ HW~ODY#W_u=,*,cLؘI zwgr?L[Qx;,  ke1;y̪u 4KЗR˧5SMI`^H@yqEDwN{  &\n&"Bu)@iRIA Z8p4Cl@am]Vaf -A ӄ3 2`h=`%C=Blۏ|s( 1#e|$˃cQT d탦?dìe΀Jh\ yVɍ9I @.A ϩ:bD۹S}">8t  tH"@+ב mr9Ǧ Ì`*ZLk\2`nnh!SAOo9X _qUx&M oАQˀ@JIT+4A~frERy4ac!8b&bBi? ,gёJ=bS!X>_x*7/-'49|.s.ɀ|~O5%y/E-Vx P] A@jR w'|%g:1yhv`V_7Ma)lvyKB[vc.wDY?lzp(mnfX,F#|&aR:ꀌ3Im߂\11a40QsX.JTQ5rpmDjHϥȴbC4~x'7p]b[ 0#I^9IU ߗ*@,@[^!U.w:/MFl3 A3`l6Z ݠa?>7{ԞyJym\fs29T΃@`ҙD1)ӐoS`/2l}Ama/1C[9n| /USXP`?JKY Hb ɀ܏@8X?tH7q4XEl,V1vAybQz+1jp`+l¶ tΝڻ :w^#O۪ωZ9\v9'sY\&Ք%J5%%%@ BPa`._$IDAT5ɖI@~o51 PQrbשטe \,Gx36}Cs ,A Ns /]vey|,$$0N2j Htd@ |流'y,I YN=.!P+*Mܯz+Yq'2$jj>yܟ2'y\,$$pPp%WZ#IbIs Y%1M~O'e,uՓ\?՜x=e9\I2P]zu&c`~$$p,$ %%@c#XNn^.W9I\j"Q~2=&ϑ&?suWOTG~۫Y5%%9"s$xJ3H$g> !Oզ[_LYzjYI@I$} *D Hߔf{zlB|Or{s>Νɲ,       Lkj3/)#ʼn+>['ӂ(˴i L:RK$ J3!@wJ|coЇ-q ږv(v5:毿*.V]CL{o,-"N{gHM,<~E:1ܯ/8茈0mxqOXtӏ=_tHIQiObސj-IUjdIqEugFD)|tZ1{EWהe!aP.*JjϬ&.HЅ'71z=wUX$b;'mK1o[[b7_~pybpz-]2kNI|jcfOĩ]|H%L.I"7é2v,ZLwքMėݶ\%zkKz m\. W2ےT, =3%BEN'V|*#Ud۞۹^t^>?kںvXȾnN ']g+33 hY)r+̧zIv2$*k9QNi_C|=tnm|,;}_kkWR]οtX܀Y=2 ]96{>c] F9ܟ~'-,>{\dkDIǾFT_FAŌaеk[kKKDkn޾U\vC8t0''KS,R/FmAusOԈn3 mxE.ߧ~<3n+n$̊KoMKuzpob}_KΎ .szzow;}h\WSSt=!~jHD?7d| M$s6s3   AOY   0 ,p7: ) KaV|ݤ+뼔=$6> |>秥B9Xu;bG%HJa|L2oO 7DK6B9>&g0 PMn$isD~pҶB9tIHo{`1`X   d`O Ny2t@/\Lhx ]eu!2$6D'nZ'9]lډ<RŁ[f۾ɼ?%׃ł}Ӿ6O;~}6epl>~Cfy̨$'2vr'C$(Qߜ2ڇJ.\BȌ]RT\O_&tXc=,gv,MY ؝p uF 0}1h'ς|';Hi}}lݟߐ8.!q@Ҟ[    dkˡ  c 65%v˯Z凎!rã $KWBo2h5Ζh;l}J9* 2WAHSL@+ 3hkf3 h}smNā!ǥb[   0 @ Nv0LUtl:oP-q܃Ͽo98`gg-3`y9~^g%p' i3 $̤ ݁Ziz3uqā~+]/,G}m { cZ͐"};LG;  DyLe<> ys@~6?%Kȯ/9iƕkE.Y]2{KJRƓ"=}$fкedƳ@@3XIz4 Q=Du5|[:64W>MQIAcrā o,A@ dž;  yOnG'ӛV[iⳢV1ܴzǯ8}!z'![%0&nK)Ub('(@HDJZg,댔#?iy>*l(U-0|$4& -   Џ b0ϣUu-W~~2ɽ?@Yu#Z[~ )ǑLV%¥NTi'5e %RU, ȣ$,@p>A@"G&  0J u2x~Y#F;T?;1Ժɐ#WTѧ?SƄ6w \pSDJ]72Ghp1m$*kʹڎ #?s[\P [4@@@ G# K`ox_>3ܝeY/wh̾WOӬmv=$ ={zGmBcYQP\D߁+3D_Fp` d/(4_޲zho&\4}A(3 C5GCpHD@@`e@XP3S>* HD=%o>魙>(tz3JoGE6zC}5s@x3j p=4ř ~o:m-,v/֙ب"B2#"c.6}x t|slTbh&LC^ɸQXl͗I{%>lL@,1LgRA0{%L @@G Isaa}sLƞ] W֮{9ҝ p."'@n>@cy.Ik(˪Tl3}RH᷉m}( T N 77,on\Z2֘"M; 4yxI& =A@riJT@ _|+SqB2[)~kZ{@(|(PO8t`o!AsQ{E /Hߨnu|h /X?* FbذhC>; C,"  E_ͩzFJ(,zBy$K>ȉG#%@PO>3EPXӾ9zlkAcu"u T$;`L nBG 0q*FlzȞM-?hcp# %@t'N<*rؐff,xMŚ]/pPEf,0K660qFx~`y-4ޖz>=T  SBn7Ȋ4gҠsbA2_ٹ1]Kk}wRsʂ.XrNr0Aܼp80f-  0h:>>G@q]ULʋhB.oy%L9]e ~U^R>ō\sޠ<^ oD {= S^ @|n}@` =@Ӊ 顸LBr_z٧jҼ|H  XL')v@t2T\yfXzzf'|P.0ֽρ: (LS ^b@7  F; ә=ZJ)bS 5҃Rz^VmoQaOFD@F zMwyp0 ?|s{|myehgO{ga1`l @&G& c8?=B6]>vk*WhmP"=*OS8\; "h7RIֵï96pz27 @@(pp  @W\|Io DJ;)c:,()MдT|?lzذفIp 7ћgB@@` @8@^P-gRAŎs + ɸv଼Jbb,9κjAo&N7oY=$`^`  p .) o&SՒ_KN MGItLa3$8ȔO ?s*>s+l[?˧~5+ґWx!b1h6@`0%8*E?^t˗ѺQcP@@`,¢Yxhk奟usywI%ޑ~}XtOI}Y D@lvT@`+2#m]P7w-K$O {iǝzu4$GM/J=h@Gz;v{ 8Dl oAr\n] @`<QOP~?G &" xS#\m>@#/=OnC4< ECMh?h~@ 6d== ) ~{@h 802IY :}G*G~ם5N1KB|cc d)Yp(6A Z^A}4?~ Egq1S vk~s{G~^ "J-Mgߡ, @N͈J`7An2=}8^,9UJP} z Q"27)_93i~  _4CL3*7-=F߾n?WdEI(H Jl!9PN} ?pC!7{wg U}yYV,M38s,4?;s H  UUͅ‚&`YMkCDĐ4\\o5w?HOoWy ^  @  b <(a8h oHy%9߾fb0 Kqxdp[8 m8dWLIW4Iw9N^Mm@@ C@x^BYKBO\_ '<*۔<  0yZ5  +iuN  SE@"˧]5Ǿ'j9RcddS:8a@ FAiPek)%ErS8(d{<uۯ.;'b]޶mRl&Ȇ?19nS)~@ C/faGMݺ24h'K.7=|ސT=_my?m: t8ERi3Ň!%@ڔ# A`ßzkȍN_X{},P? @@`0zJCqz7k./)%?E@&N@fh@; vuB@rn_-6id۫t+O#{82 @@MG++4N~,'! 6dھ\=(' ȑD5@ [qo O3%pā@@@ @RQU`12qX |L؛m[V' t({c; `{@"@ׯ^{e%-85Ko:HPU B@7D@6 YH QIV4JUԿ? E824M&S}K6weo<3\ӞԼAU doxb  p !0 px NQIV }ㇽ@@rIB_mhYKC}`Δ+$;3P;jӂi (~ȱ,\%2v<]5fnWih:NjX'zu餩KN ZPy&+ yG@Oԭ`D;]R=&T@@PFI1kkUM˂xo}?z[hv'8(@Şp( pXp~XPI =mVΤi?CX   ``A`CQ_~j.ZP"!= y@@ @8lT@`_|W> iPE H   O<؋K +=Wv˫CG@?LBOᠺ? "DC^>^@@@&NK)CŎU'_8$<غf?/P.Bvl! #0~'" H`ݲ,]L0$EHp/)9iI6:қ@n%d0<  UJ`̭k n1@fa@~Z~ %|ZՓxJrBeǟ[trXC]g.P2o^"9y~ %<RvW]0ܧn   0 #Ӭg}mrmaS}G( LD@`@*8LSdӸB, w) #:5Dx@hmFVԸ}vnK2CX@iޮ(LEiJ {*҅J.2*$bih((~ (+yW4zWubO2"@ W @ՖE@/v,=B=e#h\Ws[|S=;7FTUR2B@\sZ$\xڠE1Q{?igT@@%#3u^sիjꖛ2)h"W dxZ.4mԏzd}2g-Ő%-- H8,UvY$gHBUP{+h7eiAbdX)0S)Rn41TFZ B^P:ʿ]3?7hehevy={C1o/K"* Mq UvJsOaOF}% ¸G+JӭH.ͧ:5Ku7zX~3oS w'^27o5lGB3Q56*bfJX<>3J1׻I+#i$4 f3y$4S$5:9 ܪk]  D2FbZ»e}o > C(@䛓q#LH@<$3~oP}{UeQ-_QUU$Mrʑ!R dyޱP"U7-~~?͈B#"Gd'C.c8ծ =i?$N8 jZ)a"- p|jA:Oai*rkO/ܵ=2,Q>7XF9/d YT((@2 -&~D+rqO6i=.]S&S/P/>u`yt\*cAGe:.UA~(D3[XyҬ `O7BQQOyrM@vJGLӣiW-<<}o|]{Ssn9:P{f_<ⰻ g$I1 {.5DUm#?Kl1{݃(+R@Bàhcg0Ph8ɱBe_5֟o4)fC)Bx!) 4%`6 lP_oYOM&xlmf,A  ωo'4u>6uDOΰq8ʀӥ|$(í+Ec=%GFFF˽ a}[1 4DR`%i=C`1`DIJZtꕥ?k^ޣ?o{S;$ͨ+K3j#6mJ lp!4&i;CuJ v c^ʒF44t ^wF\-Å5(Hݛ_s#b=L 2y)7Ѹ)tE@Vw|m`Po-EL @Hz &K^5Zԭǃ_NCc4 1IdON_) 4"`5CK>ҏz >Xf~ݗT0eaS"v=?[ʊdvˆyI@\RE(RE`=z:F֘[P7YY RT(@^^79Wi (LjYqq=wVS\"z 8^1"iA4_EӸ<+V&rܯP> \T+Q^_( Uң O ޏu (LOSFXkjsEk_Nw$?"ID<ʠL@ ɗmE_IsOMhݷ? K%}hn]}␿Fc l+^8` ܧ>qaܷt$8G*hC536yxEH+8Se3(?ԻΑgei%6'WTOם~_[wy ̈0= QiB<(X{D@`J&KCxrʶrO4XU(LO6?Y)I,KL=W[ 9!9noEѬY ]Z J'ݩWklkE[%@Ae΂S׸zۭT|:~7A@"` zv;R@9`fI!@S ~WTw诊/z%4e_2¤AA`jD]Y"+, xW6Y+$ԓ]>ޑx*mG=l6 MC&IVPLᄉaūO|wnQtafdDx&T%`98L៍/Xh.d&B㆓odi"u%MsX ERy?{b"NȲg#&*)/j/u28ܻukC-1dL3Ύ6*qg_>|aR ӡj2М9H '`8 }8"Wu ?_ i%A~׭PLPkjQBUu즧~}~B]4f`WTCJ2k]۾nYʒREr .4pJ;N=uStLÆDm;|:>UҹK*MN&Wte"~ɛq2I;fDOvxr♩)e>IV3 '@=83!\ZkKɩT<ѿqGUw+K(nO 6 \Y2f?G4~fb! T Ian p8IST5B_Ab2Э9<lO WѿU(w*+я{@PESJPsΨ,#RzغaSz{_4SeĀ|:A}QWgZο>ob=@u&cc>8emM1M <\S\.G d~Y8GJ˷͈+KjΩAG@`RР iwWF.˦MKJ<[iJCQ1IiԞz^A?bՕ<  y4tuUraҭj\j72O( {Hx!3,-/;֍{7v%W#πQ MꍔN<Ⴂ{<6"3U)88 @@8"\&@?Nb5 _O{w ph>׍ks6.4TyH[+ ;G=A-xuAweYyE$4;7mԕ~fpbf=2h$Q |ClZ_߶UxP`oi,G/! @8$"'8dWPJ*5{>i>T)pIoetnYX MMspO?HU  p0S犚!wuYEt%}l{kvpAs#Q`Yػ2ZU525A" x@GJ 5v7ҖHӼ4M*4*K+'byF*gn/ >rzyHǍ Ӂ7DxJkÉ];zj|,4bm+H(x~YNF2zr;.:e﫭w4Vb2;  {M Q:]Gmz ;虙G"x~ ǂМV%ުT>Bly-2Sy"LSrmuˌGigdUhu9#`b<# ՝8V%E,tB&3>ɽ 6)E{g]]9KAgj~yuM 3nr(5%` ghkkkSfg¹k"3 >2Ed<徐Vc_yϤt =qX} o"MH 76ׅB':Z#?O#X"Qu'aE4䨍x} Fa-@6')lCx{[$Į"Uq `\66+3wUUo>gú*,d@0[O6h|RU\%ygefD@@`jx %1kO#w b7E[U%c!LMsdY؃Y~AG;֏{:~2 /3qbȎE)G $])SV^hػi?gWVBFJ,gtMx:":Y᨟8(vt3U]_;F^5FIKC̷q,㏶`k7w' `oLef=  lӢb"0UM:) VFO z ֻ˼ŊPDY5,"ªAypW]# upŠOSܤ6ZtҊqÆqI=H]f{C@gA&pfB HOwocp</qzY[x8z Z:wXEE  YH P9?:Y!J jjYX-hqN;U%Eծo3.5ut]oZ)!YDkN<䮶 .싄JkCA>@]A@ tVQ?kcFTbیa}_eB@>\#H% oӲ W;77гCirh?3#0 # Mnݲ,-)ṃ]<of]ZdG\tsҾP0½ܭ9j  d PXٷٞ-CHbH$ B@^&)P(];sËsCs zR3MC@3]>o_OGCU  L@c:Wo}]j<36i(YQw.M0X8eFyo b@u?hRlP'֘;,YU4_o]8Z=k'*3rU9%Ǎn !G8$`R$LOW:'_xpo 7],<3"8(x] dW{!w`ƥ?Irp{nt[ǶD4 .+I9~Ax x|,Rpd7|}qx-M˖Ty|]  pf/iQdxΧZ ?#RKgpGzx8iq{P[?-)@"@f@8A倿YHf6nǧ<ʟ,ӂKn),j`9t zVWdϢr 1%@1W>RwT&Tɝ!*iL njZzNaåxhF)'EKk5# K$ȞBI-ȯW5ޱX_WUw)D͡8G# Ӄ-/lg{Oݾ)m ~9g\S~wP_~|*f9L$}бo2@8X Ga %U$lB65ɝ.߹=iS7IaA@@`hvEuM\m?LJ>S4UGCQ{Rv@iI.9臁Oɸ :fDF94&`77Vc+Or`WKݛOnMRbF:旼{;rqQ Z^bxʍϴI),r {s7/ [7.7he4~Fۏ)8q%`T+ݳoܲl?L\ѽƍϺ  9N՟骓nr4( ? _eYJlm:r8sl 0>&@FH 0@~mC@Od{+oq˝ݩoseopv7mt1wDP #Pj9Ņ|ݫŌ x%@"(vlP hxr!%L?_D*t\zn=aq2p?T̍49<I  e\|5;Rp ۝"U+4]`L{d9| B B+hxWi)oGSjfBVm򼅁d-84悖W9}d kwL ~4MoG@fEp#aL=Sg<jN`!o|dBIȆkI nPixF r$ZNb՝Vmaea-k냂-/k w5,V.jj# m8"HӇ.(UG~^RF016ټ0.F"Ug!O9@͋EA@v,,yf"CDz +{;^:Z.T]ǝgW `/"ZSGe޶ɒ*Ygk3zJ],4DtӢ]zE2*   hxI!Ӱ=/oʄvpn?j'Tw+~׍%S<#8&9^ wu?ƌU^S0RЭP o (:HS]^z.Q7,  pHdNYTU_l=*UvF` \qU%w|Oܷd#DiϜ/)s/wnC?;퀥?Zymj? 2lM*;hrU ˊ?a;R;9VsE/.)?:)P\_m03n) J 0cV_zdI=&,>O(Puh鮗ٞ|ƥh8>Uǵ=ZU)8oU6 tO}di !qe0^N>ca<=%?P\O+IO[}v۬!`KA[T{e4QN%﬩   SC@&8,RRTlCǧ+QMS `NM3LY, '"4we &9{{íTD4z@28I"~FO)^3uG e/( =d#Q'   0uR8 egJ-w>iZxԕ gzDp VUlu_gr9EU! 萈"@S㊞8E7~Qs*0)>% ORmg5~MYrJ]? Ӂd;IS΢Ȳ/ZQqNّ4z^y_~Ӵ<ᦥ] 䈡:7qPXΙޓ ir @\86w$9/TNr}:l@t+&\Yf8S̐@@@&F@8CEDOm!ͱTI:FM "%.xU2/6dc"GdWFc3I%`RL@3W\TSG]'q7|]_|RpFG)QZiJ@Qg4P^X}eIU7͊ {: @,|U_ST 43`c&eDJL'<lwnO/)\ɚ[<~ɸɮHYCi3&$ubv,87Ϛ6DAA@v} :yƍ[$T<@eQ;.*4C@qq}P\ "?KCX`ی3 M8*m q']>R<)"'Eu,+5y(27Kb"@Ox3yzz{, Έ\ŎB_Ы;ou+/ ߥ{G[⃾Re~Z?0Ge7?305mr$HҊkeE>O&BJ>i4$j蘿KM,adZ3 !qNbV$F@v;}ӒAWֵ(ujnlwSK`_W-=tv{ѢA&ʋI6/*JN>qƿVJ&&GT`Zi)µjs KsdzT J4Mw{zgz*;}HRǯ6g6*CK._Yx(&Hz[^ؐTCӺ( ͙7Cwnmc_]fi qG!UH 0q&;J^_u/}z=iH4y-}g'iV(@ #Ц'?P|l["YYq{uUڮUՒ,ɒlUnr760B@ !j ?~~!c5Bh6KN}>{%Kݝ73ڣyϽ=\~9g>s s?h $eo(HW`ƿw+˲Mˏw:㎕NdלjH D@1)^k|#o2\-cNEUop(<LNw0]P / }kl.o&_"=|:4h! Dj%ԑ_8yl{&n{^NAON`_aMK01[d"d( dw|`,%itIц'ԖvՌ"@X#rd7O_9)A!/ U.j[ɤϿ3YR͡+~ѧT.*oK2OH \axA88%+ R92[ P!D"@X_R5/8B_hwy5a hvdeˡ[014^rCįkUᬐܬx p 0s΅O  f h8]dOƺwmC t'_E"D"0v{;EfPV$=ros&,ΘzĘȾT.Lȅ'7 MV_ `dURS \{ֿqDIcWQ D7:cWGM-+zeS+Hͼah̦+hxzHԋ:AU8#fs΀os]n$3TfKyPۉ DkKkռ-o1/Jn6@ 7ŚL z{'$s߰~䳝 uzcIe S%64 lW& LC"@ 3!P X_lmKs  YEYV v`*<H^)P>}55 :}wo|R:t T.3vln|p6`?J"@ Ep9ڽ7tC^,xr|NEOP/]v߾6xǣ=Z&ƀFXfy'>g3lؼﰻma~jG5!D"@*g`᥵{WkBð4z[:5[ &^yMDu<ևݱ,ojЩs<-V㣟&5"|և}~*3r]h%b2Z)]"@ DDNr' _  r9mÃO7$鞇ӿπޕd9x̎@oT goBwa 9?vCk`ZQ  Dj L%NĿ䎏~?#:ts8yowPMMCs @8U"`.(8 ßehhuZݪ*p GD6Z0D"@P_MxRgQ=8 ((Lo56+`[3J+A6zx ?*3c?Hƿz@ D[R{umfKlH}dMkx6o-&ĀhPcmFMê6ݵEupƋ8"@ DۂІ% OZh7x)0_=q`u z <&ೖD 𫆷I^>O?l ~(6gzk obޝMKMo X:5 D"@4B g\I43cmoyh"< y$%mK\6>X6T1N\ݱZ>j8"!x D"@tE4=Y``^NSh2*Sjqh!v@m): 8ل+h|P)@B@%x#5[?H*hrY5VcdGf@>sesTY"@ D,*Jv'\O$Arǐ 01E糯fԹ x^,ǚ:\o範Pk~×:(2aQ!D"@@YP:SF`M 5Zhky`Q>PڳIySmTtI@sS:!+ytGT)"@ D<_~q(w#}PTx7י,D4 mDMT* ԛ*ʆzrud |-jP*bOWu?z'e9IY"@ D@Fgϯ?^!Kc̺tW̼QUTM@1@D - N  ffΆ53I):+Ϊj~_<*YD"@*?ͷ'j#iDΦЯ ~7G?]`p<'{(Ĝxs*D Ll ~C@)H{-^d+8)I9(Z"@6_O>5xo KO^^`&䘀Hw/k6X}wv!k DPeރm]zk3\gy2kʼITsppxr"/~Of9ПD"@M~(b7Z $ʱ CX@<48:}fuW_7byG>(@7j0Z:([lwf3:US"(&zGS##CD`a DI $K>󳏻GF^׎"! ԫ#<$m;z*[KrEU+2o ?Xl"h@|250ԛzþ D"@N<`Ki[VdN Vzh#ق;nnj[`Ҁ"I|uմLpƅap{le?㗎J($xjDhk@FO#.c݁oؾ#{H@M$D"0 F~]H7f[J8_0[ƌ@L@W㦥[}72|N+h"&he& e3̳nv/ ՘9:,{}*C@[!xh"7oؿOIaA-%D"P #1O)pdƿnv׌XkJyP +r-Te5ZR@mIVY$W&bp؎ۣ&!ƳE3mS3$TV"@.1'=SU: C&֋ ;f.u cTBOh"֚:['}wjp>*:zolɿ[uYSi'͹FGգM/  NSby:% D2"PXi0GR=fga|!hL '7LRb[]$K %$w7 :ͳMH{!^UBjosnƏ?OS}2HWl`0柌Q/ݳSa?>kDoe^ zz`pk!$uN3Q["p L4~zLFMj"@ C _;OSAAD;Ȃ< I5. YhH崻" V+ -u%N]&A5/sEHIj?ܗc<\㙔%_GTUy='E32":ÿKPIU$D"P `}'͊/8o!O`roܾjWhşIhhpM  @'Ãtjb5.v ,KըE5OE`,E>ww^("@.̟j_'ORp_1f7l!RAgS2k^x,A?QV ; :<(h3ۮՙoeSJ#}T%cM `@OD|?;2<ҟۚو D9"}Яͷ{r -0oe@8YպpgﶛTZ.I×c-\ZqP:̫d '@ <P@O k?pb WM"@  ,ꓕYqȂpoa?`/h@3/乧c6dhyp@"@B|?؞{nS$5dS* T ""e>=0$BA MlKy/YϡUd` (H;c>pe+C:}s>ynR@>z'@B|PpN)?߶6_nO؄^#^a1 8Dx '_'CND;"@ J~/u9J7ӓ3k]|뮅*BjN4_k:mAuTyg4̬.=َ5!GW*Dpa ''7&(?V߿}0c_"@ eE˯k7n(L"x0O)V1՝ɦH"@}g(&DԘ/V[YT^S :lZFבahhah09 \a#Mܧ`L>="yx!iq@Oǿș\>˸P!D"@tF#'_샙(`PƆBSǍ%rYחEudIeVysM&e߰* W{Eʽ$u쿅&`k|D@#" 2,Sf¿t/=y)G" Dx \h'9@IDATHo01~p# )9pe;% KL\pAi*Ŧs=񯋯3ۄkKY'ѯ<@̬D쭸1&O|?ůiYHCz"@\3/>R 69ƫp.g ~n̦ ج P{J2*Ó0= &oᴨzQe*\uBs|=<\qEoDv~QP _ B"@70C/9G4]0Kc3L`dՕXT&Zt5Ϸo:SF+:<";ֺh]r28㏆?B-.$6׏us3{xj;Ϝ~g`V{NWG?<&yRl" ľ?? ,~"@@PtO^4L'BrjtA*>&Vo^_k*j c17o9p>fr"@" s/W=Zw r)\pWqVF:6Ue`58{Y 0=^Xo,G&D"P=ٯVyƿ`DSW/C]5W0[eG<\Y%GYjaƚV^=( p([ˬ6N3/vEM&/t?e5/m^=8|h_ y \ 3uDDOD<;jM H .S,%o?&*GDsC 7 /s^sM}9Q=\ }+t٥>zh^($(}ft̂[5ײlnç4[z!OS .x{AUCR{/Q5N^w~<<.'D"PG3B) 9X835M^t]spMG6`-x  kmhdr>hppm X")‹ǿ(yhh"@@qԃ+lY $7(Z2W/z[ah[nIG/qJph67])yQ/\c;Ix>Q& %T4@< -"$J+W9]zjnNsGk6>6-Iؕ/'ăE6 0)I!qjp  D"P\"7HJ&;')Aߒmΰ(dז+AqKFTY!IͶg5i&(Sm& S%50a#=f+*;E&C, 58f9#5j539 .r,[9(珫;q="@ D`rVݺ}m+998K37>^NRUdAI%۲m!0/: i 8V71(* 0 >Boi-{$l|8j+tq&{0j@:)j;!$GEP pl<Dhl}ADtkGzӶ'{W-m6I:,z"@ ۹cm+:=`&8/Ojܻ4r{5#8C8wlj|ɼpq}I{^gl}wNGR|ƇP[ff0{ ȋ2BfaP9o}>~"11?63w fμ'j)y'_]h\jN$D"Pf8m߱eJuOSb_3Lݘ7.ޑo of6z׼s0CCg)0.k/;H)hk"B@O]#D]U -p `)ѡ0o )T^ 暑La1UY{loZ8H8rJZY~ưh$,> D\.wڷ-g( "w_\:,Se;oJ^Z2rʰ_9Uo`Kiz}&> @{9]sVH(j)QFr JtX:*6>ֽᮀhab uo ` &k#> )$”-/ D"^e0T@01ng5 fKjkcNE[{dgƸ%*G5.so͵n"Bv% SH(RNeVd̨|o I\- 5w_`9 = Ih;< EylApsn*l5Ր"@@En w[ƽq"fw_E7R[xbPb6ٜ+o qѪdz b*v"oi"z`{ZB@xIeH)K"I_JLlUz6+ ] < VP0UY^yljf?/z\(D"@.[uz(ke5 W-W:+崘l\gD"@摀tpic۽G3yz,0/Gv03g5d2Vm5qpBE_j7ڱd6]b=.狘ؕo[g24,vA;;*@8 p4yΔ[zLkp.ʂ:@ DRX6MN-r2䨫$u2A-sn? :ᕱ!!kUż= }-^|`ڊD 76/3S*pW?ߣRZV3Sv%n)f|4Y_0@Vsdє[zswkhf>b]B;"@n&14vs񼒆 7J$suak# R;}\U|U\bwIB%9wip.`m])e{;m>%pU1ƋLk"@EX KbN-h5,x_O[R(/dowR͉ DJ Mb`Y6co)Yº+(`wI\g:+ȵiQ?˙ЎW^濫m+$#gq,d5UR*Q0X*gpաGIybҧQrTRndFoR6P7yݘcޞe"n{F D`N3z "&ְȾhoT3x5>;lGtoE_mooDs(kK[h!_xX\7O D\Ph3潦:j"1g]wWJ"\lQ]?rsM5^U_6zhP ή/9ޟ8?g;ݘ5MHFǎsSnsŶ6yg@,9kvQ-JzQ D@A=`wnКJ7̸+ ΍4$_Jiಀo['Rv.>*}M* A%ިjL{ri:y(- :[LFXKMo@kjKf/0K`Y<"@(G  0s708]?3 L @ 'ٔ–lm-eeP|&/ &\0p9JJl7@r^o]^1j*V-C eDQ!1, ̜[L?I D"'qOYW0oϠ]&ߥ9M}0_Q}mި ^x`mU4:'$0B9$v g.d9f'"< 6z6_Ϊ*V5/F&H SZTf3oZX"@ 3#"9x&'@)E<޾uW7Bk o׻7ep F 0=^"[uMMCy @0@%w"00>voCؗQ–g X1f{ӓnCCR \~Tw^ݍƿC"@ @:Żxhj8I]!֤'5ݏixݱ]5-H>W F큡SU P2%wTBb+vx O2ҟLCd"_j^G4T~w "G2f{O-vI% `,׿y)(n놱W`!YiUT3燥YXsقi\7r߳*'˶̨y8al{eÇ` wqQ@N{`l & mQoYƻ/9g{1n>t]*!/aQ1-i޾X{7wi^G3[;:1 +x=[?VS#c'!CoU# 8*ɞbbBçWid=[ 1@`ɪuw6#Y9ܗLO*G(P)@*׆}!~6 h#\4'> `or}QGHpɍ}P.J,kr, ߤKhzw>3 u;rj  GÌ"БN@yp18T8IX+EJcFGXwP2+2nwqޖ" bhU .p']RX*dǼ/m19̫ J˒-Ձ+EU=GU_p^1]0 @^I]kܫa;I,bICT&j +eQΜpYqˢTɹ!^}7ܜB@2w%rgꔸa12] L~C3"̿goWt[%5Cy%]\Za[dIAnG@{{hWP@r Ϯ~αtBm(EQ ̂=-IdLhdѝ *3&W+m,.Hh0tQ4&\y'X })j&p<:[; t~Sy9 *LKgw9ipo;\-Jy^;:fs WмH(w'rc+cPbK"qQ"T٨Lh; ": Pk $6 耘ǖB ͝1ڴ `Yɰp*D [i];oQq=ȩ_Ų霜xj `J;qfgkuF&,̎F{! ϖݡ:")N4/ F({/{Wj]W~+q liP &> J[â(TQ ƼTИ3aԟ:z/"Pq ~Ri6gzss9mKwwC }7ulۚTmG띗dE5lSH25\(h!*+@W˰dQ*4_Q_PwKxK\110gHb?DF "LT`Z Hq-WI4cЎD@p1XGsS/H <ѼF vߵu X,XkP(9N\Y}cO fZn.q_gMPl|U< u{CaHKUBFLjщ_4E(1g4mˈĊ̓1$@!"0v Q xr}j"PF=0O׺"NX'\q$- ZQ"hv+CكuAD#]aAkpmh`O7oĐtgmi@ljb0U,b El=zc&Nmxj:4gJ6 @Vo*D@#^F [LʞH;|ʾ-Ԁ7@hn_1ܳbm^o;SF*s2 ve 9_Ȳ(:/r &%jAcmW.]I Ɓΐw!I. 9<8&W5"lt [h, ) `i7ЖdiO3gURTYn,*$ӉtIaD=kLFߋ!T#^_й]I8ӯFQ@ZFۥ*엪I%%uu!ֶ};XMv [~,qty9LML@! "@ d~?L3cWɛfʱ_~gA ElCiF*+m;GzQe+_xHPkn(t mD1n7f|YDJUlwJyŚ[" _/g_p|-}/Ue8bJd55. #"yV~[+tP!PX?FG2}L/@9Ξ`/SJ]aQJ8h%GY2cd$ G#R:>ږ7UGW$ŸzO`#x4GeTp\PU@*!UdYYRܐ,˥ƯaP_UcFAi ;lJKr7L0Ye4;yd7^0$L9T+S1yKS L5}VMpL0bL@lT( jdY)?_}YlZ3~rܕ!5(El%i,koa Ģ0ᗵ"K 8?ܗg<i,T"KU~юTO\vfm pّs+4܃j###j7VIRHԭn ǃ3io G}.ڡ pvbTgZX4o Sd 6ᚮLR(h6{6N|+luM+kC 2? 2Sq, %F'YZ f3/ PsM"A r8LʫVU2D\f&N `?/d秘4U&2 qbk| ¼f5b(Yh]5t ( /PѿBc9d6BH.,/1K*UK9/ ./C2U;dbim6*3 jkknp7BxL$t ڢ=sj][@6 hѬ+eZl>%/nNhBE26ωd.SRbyXp ")vbJY%0>@ ZW!l_J@E2cSxA`~Q?]w\TN\>MnEg[`]Ҽu"+0Ǐ?fDu*Qipa[;w4X* I}ϡ;vD;\W%,)r? Z<&\#DZ!xZTd!dy~:C]# "kWb$̡\dƦٮ  ׭ֳRo~:@+nRzza ֺҹVhH"&+T%eu? 7Z98gbO?^qhq:(bY_ 3\,\ԓf`|=0T&A?\l6h,Lo2Tnj!gsE* +.,x0fkZX^uk^T@Eru▷W~jF c7WLCpb򿑾 Kbu2E[05wxj맿7AJGX׺Kw`:RyYޛ5I$gbWwDFDWeVs,0!v% "䊐|(K7=}UuUygU=ӳ##"P+rws55BUw+6] d`Dx}%-LV8t%͹IH/r;@HɉQX;m'O2yeW^;sV-) ivg +"j5>;'E p~_a$,'"ƠuXiEoi !]",M G4|KzG{ɋ#b6[ XTK}_4$¿y)qqOJE tt3Zm0kGvl _}՘;i<:;Cpw V,@3_+ +NI"Zuz~KIk+ЬdkP1~^f2+ZԉW9JqmQ"rHpC &a968#641[`wg N(v3qJ6?q? =h\*a~a;!e: ID!f#>.έ'^囍#lK+m @rXG!(h $GOG}ܒ@@Go!9R=>Af@FJ>?]AE(ː3+[Ki*[",S Ȗ ?9M8;]l*^ ٿ[Yǥqh8'ZfOŹ#0D(`52hqb 7 Io>a^6E%G +;!MQwQJo ,--E$D͗*46Ozzogo^ڴIk,R+t^63ȿAU{<=eь$xa.[ؘn,@TJj} 0^Ci#>)  B1F"#GGw@};` l  Zs%ty>.0pBM584k:Lm@GTߟ(qk S͌s8aj$;, cp @IϠp k%AxEIu &2["?,2[tÊC@|})~ { ,dJfbQ]HÖo ѶxLj猳@@ BV2h5 W91FnQyp,E+s7?Fcِo+:cg0 AڐecCbߊDLk#[_bX1fFe^-,ܒuCD~ī‰i8!ԩ~9\ 3S 0?j5#0DARr20ޛ#p c0cT nی #gL;8VNƠy#R,54?wV+2=,|$|?e>Ȫ&7YdKǿɚ¶y%x)qY' [nUG+( 0 Ǣ; ٧s#zj'u|gK/rSZp?(:ZmYdH&몏oʹj¤8#Bܔ~?Y5ŇM= ф$: m6:V/Ͻ˫8fW {\љL\ F`>w݅f1ŀpz{W BϗYȃ'#`mI_HV _?45ZRn&r+im Dih+(#oYǒz@VGLm-l,#0$#EXxۑ7b,C+g>vpÿZY ( ft KTy=.x"\M}&+\QL0ƥ䵷k)T5|= Dq↠'D"^8Gt*^k1|i.6% ]Dhuշ~n1Xg[pZB#3Bv,yjO!>t;Zɚ,x#ww]]7w%GxVp*HX(聑$!r5!9DVrm_AG5Nd!@cq=_oD *L~ǐK3QyZy!;0ꓹ`RJKL H~@m)8D!Kܷp#mi~ImwR `dc {1mȡbSh}KsMgX)+ `bG h6&H=K^;>>w#?5? \z&Uw!۵ /e>E@{޹ 2b3nӴAfj!H4#0z H3/?.V˃+[`[5)?<4!D[O$q9:OKLػ9ZsK!3{{#p(Q jwXAO@0%4}^WC^ 7T2ѭV VQ ^0b!zQ}_u W\ILI"+R Vm@y9t\/!mה+70RO7lB.<-XOhp/wrbN@+H *:>~91axxҎqFǟ`"d# zhi >Y3aN8_;<2Ķ7q}m&ɌOb i0rJzi ?'4ƠxXQv;P{G}F@JkX\}}:3Ɠn V$7MX][bc0~pvGQb6-VOz3Ct[ױ-蓆 +dX?V W"~ QJ\2r^ߚ6K^< h?{Ÿ;I=R^أe[1'T: sh nz\ݼUӶV˯g(ݓOzI8]F+@ٛ[+ x뗏X эjۇ/Gz ]/n"!NEQO?m o4 O';o]vʹ|13$92_KwTOWWX*)aF Yo_^}; Wܱ-Sod]hr  e gĕhB+&Ӎ<@4hRfCrbIj=b<8i۳&:Cv;fmړ= C"mj:Hv1Gl4v`/@WVV 0Vb@1h=ˮ4~?@ [ `[dD"A5eTd#pQCξL)njS:6Pn/Ww1h'F v#Sqz>/\pg(}R wQ/_DlfffO.>a.h,h٠ 1B4.nҚ( $w*lWʷ'ݐ})Bm~F!M(%/EgsXSO8Hw#=^ݓ; *mk7/#Dw_i|tp=Y,ܬ/(xd?YЭ#+?*kV@|F͙Oz82 @JA4Qo{}'ܩxpW֏q.|s{ޗA$#G}VG7<ϊY'\7'20?7Gt:_{hYNB P}7_FSA Bu0#3f@I-X''uR@༙߳ үBL>V* F_n}wrSP1I|wOl!;t.;QUQ# am k@/[?#FU66 "a醤_!AL @I `[}2V?IlWIg&c t4q=*'XB EB5wɛy09)QZH9S@]݅m4'oOpgm(}V Q$jľ=At|{R0A}h:ToM0-R޺;5E/;lrZ<['%@Gʷ?QXßWm7t`C%rs&uUΤ;&>EŖ*}_\~c}vtm ƉzP!':uEé^Q[mhG 9{V^ˀ茛lnmA*q]1B`klo?hͺOMH[@$kT p!fME̟f +{+M,ΆIKo95'^cnO>=0c"PSSk?'=NKvQ GW<ϊԉAm`N 9Y?p#K>~_.$^~==t zym+lW;ozډʷ Z|)u1d6>n#0j,ނfq{. <DN砲EH b[.l6@\ ,<\ɾv\zS߿SEz.d5 ["7ŠIV}˜E2+2Ku-nd `]Džu ~ri}gh.X Iaao7e_@r RPM_IN4R|Q$tϠ{ysn NoO&zpZޥH[Nwv*+V]8x#w D*[[x:0Ęs`|th ;[9 lo J[1p!J Wn_a'_ma.ZMDEN#@hvmA1t:1kGɄ}x)=1տ]8l9/_̫i=۳,JS8jK((Q)=BtK2; 3D<)~ӃW~К.O@<=q7R÷rMHy).sCI~҇ mneǍ%3(g.d)xIdRr**}̉@E!b@Q"O?e+)~0{r༐Yb]+ 'w Gڪǣ9D H•+W fF`|.f/ۆv|в,]ƧXJ~iq3YkI[ ̅*M˱G?| ^HY-Q%Lzo6f2F`%>(R ;hǂ?rahd y|jctnd0L%cP.Bǀ.<ӣGK3SX>^BauOdH$aaau'ʵoJݧGF+cd?KQ HK@CLJ^G.SѸɜMksbz#obXʽ Q)}5yEWI9l@Vr.v_q v_MdBpQ#'D u05 @mؼ| 1'W/}#4)<}tl 0V;"D1,+@瑬j pa q`el~І]L^r2A @66A騩 D"Q lr1uHaC1k:p'/2̀2.ӂ}EdcD9 qչWڊoAW 8фtyq+UV"H XV8rم)44h[TTp @[RKSacJF.)Y)4f_9݇#X )L#vghýcN.ȜQኄGKC%/KY(f\Y ok׌GP;TO '>Y7 ih+iADYhL\G#eHfH4R ^)Fl&$eXV ;w4<#41l`l*:H6yI85 f-Q2c@T*W7Ƒ@vN_Y/?umN #yCS\GK1Kj\)l(l]m##0 ,^8$`ȤA/8a_l8Ln] (ZZQ[(C \>E[OVAX9_@l6=+lv44Yul#XJژYp7 ӣPۦ9w)>K/ڱ4\U}J:YN˹!*g{޽ @L@BKG?hMT7_X958="S8jk"R$x3SvhG_`ow L:[kŖ/K{;uVseG?}=Wh9A d@GoC ;IIE`*ZFo~d THJKOcrN#p^2YAj=/7.?RB+EY_Aќq'0Q/aM4; Eb6y+ 2!sa{e<Mh JtX#q#&u(,jۿ)>(iN-AD m%tx@LW#ʵԆׇ`= T+{||1&3#jYVȶ6<L4V 'n;px n V=FmQ,_«H0Nr!w:! >ǩAP8Oi@͕C8>hPdYFɞM8Ry`}3n nf#oat:<%8d|X̾ ?eZ &CvvaSvC[=G2*zf=Qz(Ls󹥹XaGMh4 ^fO(O28 Y M.ZE)JD@ц( z5حePa0}B@d(c0N5Y 'XǛ *Ghonᖀ&= QWduň<\ YK{q.L]/I y{Gc1XDuNT!Y:/x8 K[wA9^Kpz¿m@ǁ**LXRD%Rp 7͕7bqAT@(VsB\)xP]bs @nR~whD_;_ s9EMS;{6"MabDEB I~߇&Nz8Muu~ذ0W=E;<Y<[0*.Rf=AIh۴O4 b =[d~ (VuщYa^oWQ= N%HA5: hrltyTk8S1cbRf `Lǯ6uwx "ܽ5[ ⧛*A8DC G<ϊh]H]K?JTOsswj^k;<::co Dhm6^˼Yn"9#ga)LZL3^e9W2K1%#@5} +VAL_ =IT04 B Jǐ)D`5>Q#س <+Qji_ma^0t^ƫ/ ӊbjq~3nP?R-%4ЪyUvdl n׽Z׻o0lpە˭xRI\I*U,rb>2!n0#wͼ /( 59hp,(@n= 1=XXXt:}8a>y[ȢQ[t)V ^:%Oq?(5;7, s1 oRluPJ4vG{1UbZbGH\ήfn|c`@?+v,8AφcAa60PD/&a81&`D @00c:Z}YMB Glh=[0*.Rf=;%dDbKc?\[ τ+׮][Ӊܫ-ծC-5QPQ~빲uKHrqV TF(S Tb-WlsZ\4%S<@跖_IPp>ο Ѩ)s;O@l4(L+hEʽ;?͵]"dp-$"tt$#ҥ 4X^@۩Eamm ^rBΛNhT,sKiNxN=(>5sVI?[ `)WCvF>+|S %嵻,-A|`0#`.:h~œ 76r ` 7i| K*0Cu#9Uҥ.RzQvQYȅ"6*0?[AQ&l4_3*ŤV|P` ?WbL,=Cd JO~`٪շs[ojV^:UT2/+~N ;,#pn< 9|;ӶSA)w`sAThE0po4ߝʛ|P2F)4Z$c@?  W!.gyK~;μDH1<4Me1SF\>{PEÑK[q FuV`QY0dpᨭy蟂Qy tiM`fgr1k/3+n\ƫ/ 3P֓f͹սVh bD/{|y%1N>'kPzΌ cxEx'3Wlj}!);>iAJ3 #e㋐`c?Ps&gAJԬ<S lǖbifgҼ*L7@oBoG ɣ`g!l|VNV^xVVns>#"Tf/Uk@0V-ˊYD D~Orz߅k LʋٕK߳3.` MKs"?= BMHᖀ&o xA0bբ !g =|FcB@5ZP=QC1*<Ӆi.xxd8__'K09kkF@rHKsRa78D7җZ+0 Ԗ]Wy FNMdr #^<֩(C߸Wf2 4X̾ F̘#` Qt ; pӎOk ypdOtC W$ ".-Ny6t*;qX-#H֕bCˍ׭>= F 7J~U_=PePCW~@t܄{) n`#ٖt)  KwV㰉bOL7aTS{2#0Zf[0 Q9em6Z- # '6=F q6h縍-Vg&WK8jn"%ɅK T.$.Y)LJW窐/p?P9pE`rżjuh58`@f"+ˊǩ')g+h+]@~ 1]e9N'Fxӷ ]sbH/ !Ç舁qZ ൧{0nT?צ PMſGN>.$.Y%:O[pϨe8T~W]C^}owOBrH%SsRhNhο.CJ۹ls;NVJ.@U,FױS[Wluǀ/Eo^_̠&Ԍ#@BbUpʟ&Z(`R nMA,3t Oj~ sN0Ͷ'5!ʄ7d}.Lqp)Ѕ%Y - Vݲ먻0T*l1^^|&Ur[Z1 Q||"Eɥ[+Jhh<}HNE]=fO2[+ m^j÷mJj=&-!0#0HU XF%m5-6 TQrB7(<:8ǏaP |%m1n|vxUS03L\]ȟr!qz:)Hh`Sa(:(?_2 Z[o`pS7i Y|Bnr h-A/(['៬Sm ^ /Y -+Qv-SG.4Z̗<8k;[h ڐElrԣRml".ιN̂ʅ%~ 2oGA?(R4$V_Q⻌ܒIg+ 3:F@#-/eK\#q*߹oMOk˩h[Mh/yx$74?TwY<op+3c5Yn€YxZ2-;) g$Ip F7*"\XAq"e ͣ-w*kG1b'',ZR,2 KCr΢#%z ^ٹ-HIJaqi"ę@O䬺4ʞnVwq7XM~!@?5&d<'9m7}abMX7_~rr}>?;"&Ҝ0Fv)t=duV@@YSTܿ{o9= ~{=lx'GWIpn[%Yϟt!qzي#t$Oo?ZWpuu=29(d`c Q\#7 5cxnRru-^gqHgBgϭKj jSorӑ-r{&<'K Oǐs/'rA%f&G܍^0M484({|x ?Bw8@\ND[! *hj1WݫsȝDgᨭb>I@J2ÔrrAҕ'mGs`/U`k2;qkFPd2]̘vq`YOh%'FE@IDAT`џm@GÆ!SFQ Q*b:dbrH$D6Ӄ 㖍/B9uZi >x1-Z O>V x pZv_[wZ"pj(yd;9 Q ] ;Zⶀ_ʧ.}yb?2}>P dYV8ǔs p^.db1v@p۱Kl=GF(rZ$*̠=H.=oB6#1cMQAnH\/sWzCe+V\ܿ+,dtí'x~rO}v M ) GvGS)Έ3O|ϳ^@?̃v QC~bY,++r81@9HJiQʹ:Α8mCe!& j~J ש ^^]vg@z֋l(QwF`(7pK@ [H upNJDۇ4,qݣw4Ştdu9 Gm1"˭!taK0/R!Ƴ Sv |, 6.Jd@*Zl_[~,*-tq|]nduHof\-s(%#o2l,&S7 @z]đGVJ\(%rEV8 K=/ f|r|Vz`S #!VήKa0P08m<=n}Dd @Ρ}s6 c/(1nN"Q[rQ9QH. ]\Iؑ,ǩ?s_Ÿt HR$ښ3He# rI$k;@$Y:غǑ;Y:\Kϗc)t Vf@B Th&sʭH\3|@ifcSf!||fӯ@ -e8R _Ap3p^b< ewO\+R㲓܇¾M<> "IgӰ«'F`XK"ӥh66D۟h9Y;R1 `ɺq+SUkUV؂?Iv=)!| Ύp;>N,0T ,$N`!V3jkcV?h:%{Nnob<=v! "At;Gm{d4#D.Lv)l#m.8~' hAnEH"+S0G -|/FOADhQ:b{8y!@fË[IAT.y8 `Zh_m7@3ln0q?r)yr?q`ǸQтu_pE<]'8[g@Bbg;T/ClZעdNFF-F'g$򭈪ᶸv@RLFl4.Θ!e9W{Box/'ͭ'5<7?y).iq81#@m"̦^E6jsnP Ě@75x!p_Uة5u"~Z}NzvyD 0uraʅ%/P8n]v~ W yDj C.0_&`Gj ܲUv|&|#GRHUJ2H%[m@Ǟbx^]h cRi!:I'?L(DߖE%F`xжQ%IrxhMRn Ç@9Ժ!9!ҙ|ήR{QvQY(`)(Ʒ$ߎQ4f?i?榳f# ydiw;գ;P _2`ffni+QV[D^$l}m+^d% lJDDmҎE&wk 0'F. &f\{  _ȍuE?x|+D4Aݮ/[lƎ](uWʞ{rq_G_?κAfszvĹj6ť%y 1CC  o4tdRpR8Sye -.F@(_A -pee%^ ^3niOnySoCւh@+< QBdV z Zp*]9vdz(H d?; @BY*"H%|(p852nqemEJʲR1`|  gś1ݵH'!xze]ZN c jI}B̶t/T:А]JEQȅyJ%NR·fF I`)G X%φGGGW_n}|,H~мdGtkGlD00uraʅ%ۦcd8.] P8n;.L wSq,Q{'Rpem͛0Q$(sEܯSZr M< -#J\,_DxB$7ҟOz25 ck7K&K׊& y]%zDxMrOV 5"°L1ox.Y888;o:z_)~[H==]kjqv @ q\`t[O*h;038ֱޥwf+@6Mi]Xs# b$c6{you\puwP؉<KJy)bJtS"eωQLP\ý KPN Ro(2^⻌!@ZH*ɗM:1q#nrJ4Հ8>>f+`P&MvZo唆!َυi0.- s\:KbCE$p|{w ϶uh|WWV 8`)ѴRҍpn=aVF\u-^V @j !EsZ`Vd-8@{^daCI7a6w#l2}>1Ӎ XxK~ޛ vP h,[nd ع2oޅ'h &"Rl`Tg\]ȟr!qz:8#(_ʇnw$jOVmnA##pŗ#Dvlˆ M*KMl?K.<:J*m,P@π^ˠ+NB$ZOӰhQ, E12y+h$0G|uD,)a BG mAsV=zJ= fBq! ɴ mʉ]QBR4>#0fPEA)~Rي17H @`c`g{ 32)FGCo\:=]p HمnT.UvT(q:8Rx݅yZq˅Ӝ8b{ ʜ |Qӛ;:YkZAFJTLFSR-ӑ?~HّzUͺ;fL~ | $ŏgEB"xFv0(p\mt=ftMAqOWxd;OT(Ȃq@B2B=Q҇nw$eԛvhbk%܎(Iff 1H`.]ƔZOK8G{'1.uW,l%jL[[ @2O+zVЮIy6 eoy`X1#0жI\G7ӲԎs?8b RvDŀz~߄>GsI6N3=餠Kau`S1>s!qr0pbcw<(.Pޢ08= vf ؕg2@ X4)/"qlhc\N#{q>:S9)dx+@] ( yz7sYVDݑ⻌$ LdfW1IIG(iHN߷V){8$ko[OsS G n\d.$.YΪoFBqK  `i) ,-- \q䅹) Ӿf_Xe XAK @?ӇcbzV+Y iGgpL3-.?%֜F`0Řa!Fc} ƚ6Gn_~E| $5o' . Y؅KuJ ]:\xP0)^OǥG%دl% Gfv`+nh=F` &i9[ا*Ь(h2-\(XK"Kڬ[/ PۡR|Kxp|mFaLtJI$"𧏁x7 _>-Z >|mUEvگ|-61ݭaoDF Fer!ur/Pd O>.]<҇qq[aI1*ЭI %e8 Hqci楣FGr+mzjpAj HTLK0ch&H?20=Y;cPۛ,Ǻ?,\Ni* ghzi 3!@$O[NpK@ n_c0@ V) ߶8թte,Uȅ%߾ @Be3<=S8 PyP9n;.m.(D 0)TZ9Hؗqwr9h1N#02bH W^Fgvˀf4bP]TV M% +u*z*D__)y۰||y{ S(8d3#L4 0`1 }WD_P!dvp7:|~~BDGNo#($.Y.l*zl.YwԟI_¦GINo;.] uu?0w|?Hr# R"qqujFp&M,əkFF{o @  G<2w) /sPn`뷿W{fUK,1adeVeFus3O̾rwԨk{tozǤ3+ ɣ% j NZ4ѐ8VVP (@|>Jq5}\| -t]K̇,öHF6&K:~ P![~24c)uET p[2 z'#'4ю-7WKvH723(Y3%o`?&qe8cܮ_~Y53ksb*em!^29 W|ɲY%O/S%R's|K}!rTV`I+D3l;"clxFpbI#= IiTbuu͇J*KP+dkf#8 ^l%* "?Dye}3@{xS`>8Q%XKF3/GM4l3>XC\PXS.gzR”H#R.]. ʀ20 @%X#>Cᬖe Pp v>y [[꽜۝ .PBru"G19PD[ed#x;[#YҪMA Y 98@N|i_Qhl&.m$nZWn#/ RokG߽놟]GͻwJ_65 펾z%pB7pS=Ѳ>;>re`m4di.t mkGju7k9B|}x'7!]8`^EQ}8$S2Ya/fʚ ) X9:;ZَS۸fcc U4DD J0(lMjzr~NR!m 3@5pIwq+v4>iJ_Rf`0((oJ3t|3։ 2qA˖cx9_\#-ƌdo : ǫ8C|vHm tKVYR,vB&[٫6e3@vð=:qF "Ճ[vzm0EE~-GM4>F@5f+c qſN|r59 JV\__X7[3G88bKK}u@ Ytp"Qvp(JlxVM)d b4*猍 K:eᚾZG֖~?ƕ;@"ja9#ۅfŵV&H_o,xǥgzM<`8 W v{Us/ C=Poe@2{OJ2'zQ+x@?uuC{_w΂08o:D(!mK3neU]d,A(9g -C,?Z: kkk:~M*ZYK :뭋-{[r{͝OK & D$WZ(`6J{w6m29ܞ#<\4yY'B8w G `RC|!75EFt@"[ÊgԀbIˎf X6K#5MY!Cwg8NoR'("{aoggc~pzGgĭnUN[$>0~䛸Sü!*|ЫaG2+8יeB0S `V| C8oЎOqwO"t2FUK_z+=ģh0@2 =hgx=zkҢJ=XA: ۧG't?xFYtS^xr0ԟo&h3(oW~0CEOF֥izG(ʀ<^Kxr׸ .mIw˯F_{~ '1s_@^ _j%]c? 8G  K;*e+C!25qbJ2D~ v >Xnw0C8{FOIe3yakw"w< `eb?xR4]YW'@J"3YDes_Q9{MzU </?M&T (>YR ucM5{[y_ `%i⸵xGF 2F5F̮9PCT̮1@W+%b uK)JΒs[Տ]moTd":dPcf 坍O7o:;FG鏄;•Gz |zQԹ7ԧ-oob și ,d<-ٌ`inkI{ﯭV0sG zz$`0f_4 2q[O<;֫U=Ϗg.d2s6lae$#%SBu26Ah])v2*wws$ ݖ}i|$*yr=@){GNzw=4=< |oݵن^[TWuZse0@+"?'jwS~ Q0+O; =xvMh\|,CNz>-Bf$ӵ J˲YҡrCQe1D>~.A/q51KI,--#4 (w+M8D8/Õ+ P\SfẂ{&ytg z7iq(*@!/{g4(4 Xn0XAZ+!Jv Z|&t=X*=qryA3`L9I$ j C|zrkp3v~/inT (:;vhv1FJKG/QR֘bhmhp_FTb,lZ8+EZ#d b-{5p'2nwH4-5 qK=XyN O i 9q0wW>Vi8}(%k|/OXRkkYiQe />; #@{kT4 J`>.Y@Lg|`~?,y8AḀf0N)e@Hg^r G,C, w^MzT+o</2峞>ĸ7p9p $spd;DlXl ʂKsFYa!r ,P ms|Egg(I___R4H< ͥy =p<~n 91%ML,{sչ/(E;#DcښcwޫyVjBPH=5^^M mkTPoz3ϋW''h0@N0B7F:dk ,A%9WrB(ƈ2+Xg]ۅ>SoݜTfza4[^oN{ +2Feg?Yhx2)ip1Лie@(½C飶(wo/W(j %]\~O,GG udJ3’ldkd ([WPvW i~W;x/g}{c̡?]]U Lcd<4 :-=^8Ld7!ZTWz R2S9!^gzJ?J6߿2Mf) 0P`$7 &'ޟlZUNw@ieR/>Tvh,q9?5lF6nrqdi3’ M^1fhY%ZB&8mェg\?ť ֨20U $~KvuNA|+e? 7}I~z?7.ioܹ8zDyqA,z= e@(=Z4|8 Z@Q7Āy4_P w{~y~GpBC]`ĖE3lbN)UWŪHY(bt |q?~Y*:RV>]y߼T53m.//nDz^It?hDI*zTHPr2V T#=2`.PR<( Nz])~+8/ZQ26GCdՑ)!K_-D4HAl(|m44OhxmyC=׋S=^B~w>}8ʵ``ٌdjcI,i2 d3@ڇͿAE'u#/ByF2V P_~E]ŝNFvW8>KDPxe$]`PBPvSl YUƁ"#.A`;&GGv&6eڨWe@dK0gzK:4o;$F=}]s?(%cf>|ݬW̓(@*} W¡Tmͼ*Wxv߸J¹c'ٳpttKK=Wmm ~8'8uM@9"f7r=J,A\ؖlW!YҠկK{CVA/*cT.°ފ1o']\ۭC}0KW*p1l>?0}yP|Ĝc0,C? u|#GCԭghZP@ OvfNRw轘e޸UmXGgxŕfW_MM(^_Erj!2Y5v,{@P2Cd JhOΑH#=҈ P;??߹wM˖Fe`hVvbu œ L|O|tqe=Ru :JFsLq ʀ2 -Ĺ#m-$Vd2S|+ōxI/2-9>:3Oƭ ^v3llSPB F{r!OPĬ݄2=,AU3kчt*U L?㍢} sf0`߼G. )uo6@1p@ g%)~(wp*PPTY9 [12QԊ}h܂hE`|M%q9K~?f%'~Ԏ5LGH!Y9$vd b2alӨ{Q7pm}0ʣ/k20 #]C_A-Z@5@ft)#c@` 9Og?4GzM0Lhe:EwHW\'9/Fob*Хi v]\6o^pѱ:3G6C QE6SIJQF !J;%\fa(1u4i20 X[?fW]2@ϕڻߌ^Q w<CG|GI [=({aGdh_fGU%Qb G蝧mz#yT1W.ȋ?_}2jzW8Z"e@``eik iD (i [^\x_ G\>^[V'n'Z }48]BO{M4h t]{rgjZP3`?E! z*V)a7^`hpmUGۓ)/#!YrӎGR2,9n&Ie#r-(AlՁ(VeKp2/9kۺߐWe`F\Z>Uoƒ:1P+^{%uE:=EC n_:bUW0z4 (o@?_[+| T)G΋kT}Uoh3(qpi538xq[\"9r@"v Y[3ʲ]9u?MQxe(4@AlWbIݝA FB=kk*hJ͕OϞ./<ڭDq3CPz4@IDATk~e~)\fewidI6Nj=p(z'뀫HP D~k*t轖 s=u"+=ս4.~ }* /=v,04[+qRf!"M4@AlWD,pT]uD9LV|Gj;5ŚIe@Սs쭎=8U@O@b_Tf@o_%m %s134 <+.ϝݻ@[ $=ƒC&y#g3 PYiQU{>nx L{ .oNq|ZIoY$b,PJA\)Rư Qd[WBZAPd(䖜!RxfA?JYi20 xظKݨ+:Zg6Y)OQJ/`@-'vg< ob ]'1X@*ʀ2p4`.Z1='>`uT+pQPx 5b2i/^Y.M/so D8D:.3 {{BeUR(D=4Jn1~p?9󳿍z@e@X'Ƞ;jؠn2@8c3to3Qk)=)-?Q0y3yK^ A?h}̼e@QV4_ÄiyߙtkAbbQm5Ad@|H>[X\Zh/p ?E[$,hDe$r.M%%vSr,AlՓ!Xƫ :'dK>Sw2e`Wrskc?h=yyDA|^K@!qZ[8K[BV^*;Q2 (o@k?ȯb?R7~~AbbՂ %mA a%h]@YOq7>O 1޼$EDX!/Y_m*d aKRr,A,3#(bَ!E2mQ2gs[EX__Y?7ݚTfz7,6#HVQ=3GX9NAM|BWdJA~e"1Nu %7c1p?cP+M9ք2 (WchA83nb

        8Jk/_ Z3i{ahtU>?ƛ7,(f%J(A$ˑM"تBPD, i?7wD~QcU20h3@; zt#f(Q܅)gtEKZۇYYzUJ7m7wﯺ$re@hX WࢃOuﳜ-V ^ =&GjBG=8 ~_}->BK-Tϑyㄒ(͒ ʂpLed{BPdRRd{8A}fNh$W֠ (NmGy~s(@/@qTJAsAey\9?d:F<D|FY_Oa얼ie@!h1ߝUMSĂjУ jx6d >:<m 4{8O9je|pm e,i# F{rNR-2K 6xu HĂA9PL1:;Z9?0Ӧd݁vHQ{gzJWLj O jYV}(/7nFO 7q,w $Db}>\E=i'0rbHeʀ2p Ľv* |/.hS`;F~g謐&s&f}ە1(猲B@\c԰”M>+q6|r4}8u˚jLP9\iTpX_OEf6B~5{h _ % л_8^{腽JܞmjT (7@߅=X(?B#%,?M tT-T1t3')>sB~8=9fM\]8p@ %(cIG33Bq 9)Ťd @8D&qz`,it^%inUj⛂)O$'|r' eF|m'P2໭M>p{-~ 81/!i@6]AuXVÒq?n|yV2 (=ov;(xMʺY3W|Zbb脟䳖5**C/kڸ铧xm[]X^#)7|vhh_+R!!bUC bm] 9 .%jZ@Ӯ_:+Vyʀ2.Bs=6YpfNkEnO,"T ң*aA&>(Ɖj4 (ʀ2 6?jHo] p rYP:mJJ|(DqP _9EKq|i 9$z!m1+1!\1kXmf%Mv׏XȶcREt_Hsz 'Gߣot%Ub`Oz@?x:facG-&>SMGǗ>O ~˞$0 ~5j"z#Q e@1h@9ڏUfYoxdP:XPϒ٢>.N @^h6BZ5c\O:ɷvegh%ٖ>GDa)Q&CD ^/:Coa۲'tH30?'4ǜGN-Ka 0&o$K2CX]5]Fp JԨ2\!5(ʀ2.'TƂЮ~aoI1iB8e[%;hTu35H)@vYҡRP!XҔ Meˊ JbGp@!|he@P$j:7ӢFo}p4Z`!k҆$-=}9R u@i:7;,c4GPa{Ԣ܃=v3Nv$H~*W@~Kf>m\G^up: oNNOk' 7_AܻZbBFX6K#욂1ڕs Œ(M~BR`($v۹6:k? ʀ2 13/wMƶ[~ƗC kG-FQ"uva,Fq? ɬ2Vz j)6ʽE:8^iJ)NTPUBlmK7WZ@3=;?MV}]lti kekJXr B9LQPb(쐢bv0Iz4Q'#"mO~bzUe@dy.6$ld'Ք@/;NK.- B '^?E0.4(ʀ2>v㏡*nP+{CwfTQ'R ܃x% ^_|(f fl<rbUE"QȒFAl2KZ@qgp?c(zSye@ Ik(aVr?"@$f5d::Q8lKA%Fh|k$Ԉ2 (߆ ~On{G^D,S)NϒA Fx ܒ;DV`2|7p|~^'GhSqŒZIJEWѡPe%U ;0ID{xJ.4g!i UPkJm|h=7iǃJp*%\Ňt]Ÿ 0EY*k/Xv;YC(3@,O3w 6o\l߸RF"٨~p9aϞ=Cw!_ te lA)+EcX_0I`J:WC&-* Dp:BJ|:/0be@d^[FɸKoy$<&-M:__#' >@$$2>0`OYZ/ͣWAwtrXUx@pkEas (h? <] ;grT)J:BX1CQ2?Rf/G6;fkK]h:s8?;{h ޜ1Bd WHf%53J)Mg2its,%P fKq כmmmCA5(ʀ2+4'-x*B \SDCJ}L\v>&4q`|ͅ 92"J<|zmVn~q B!_|uwMߎs7ZA8VF <%jn>HwFH pmu<~6q5.u;{K g0%#d brZ8"50K{;RX1t⊣9JR@P~{ДWe@ л^Y]~1ztpi#-a԰;ʷ1o!qфy|ٛq%q[kAˏn}M0qYG{&KSʀ2b ƙ \n (`o!KyIV c5$|Ft8~Ɂr@QCP?dv_on\X'w֊Օ%IA\)Rư Qd[DUzB~y[qD3;3?[~xM(ԇRk 2tLsn 8Ȼ#RzL&ʦ6ڍ>BbͰ@WןsݗUb^x'fg?l"zuܽ3 HyUu;9S|]"{^\i͕@o33-8l}(R?Pq I%HWYs.|(-"O>m\~=x'3m=p!1zNKKA\)Rư Mdmԡ1;EAI[R& g5zs=\ɍU%4gZehTmB\AYl⽀} N[{3X710 ZҌ@T =DH6vuA#&֐ٻ|/xryDjuoNϰ\c\.Χ.*^;i5zW,W>_Cmf{ Y @J*Ds"S`)YB׸^E-\]Z~!:m} ,,.݇{O-),RwgIqB YC!lQdI& (M*l1/a@TCtnM,j je^Z;Q%<GݬM)#sb+J5TOkj1[DM^"NC@y,l. (sSՏ{pzqq9urAP;\Q9<;[=G<*'GfT+JאTYʇJ8D#}k`&߇ׯ_'h;MvX'G j%ERZr,AU) b=2K 6xe4@AlDi(}o9\1ͷ]UNT2ЊOϺo=w}*{c2a8Rl{Ayfb\ ڑvm\q-7 i2ъi3eLS-5 rz6,V>=;5֖÷h_ZP |؆\ K$g!qOBDexp}X^^XZq#'=DbRr,AlU!XvOPąm]Ɏ)š<|?#\0~_y"be2cɡ ЗMbO|}dvF"v&>]Na{ܲUs)}m 襉m4M C-N=X 6c|4G7R:k Yàe[0Ȕ8 30 ?*g<{q%Ǿ@`x="d jJ%0K 6rH+7&#YCS-9޹U'qTY`W]rěf:4 0uC | C70ͿXNQb&c;7Zo:xpW<^ V|iO S W|.P+Vxo)'R bFz1th@ԆyE89Wv}Ǿ& <vώ&&u4e8U\)EcXOdk]+:2K 6ëD,9ҧ_5>GG+}O'6F;kp?\@><"(`~r3P6(^<1uZ:h ^G崲Rn~p@9m|9*]eYPzĞ&GjH>Tu@"f$s ^~,큿kxl⑀Nzd 8k9SXI9'i#!r4X(bW`I ȑv0ΔY(ber-e+jr/ί׮ǹ!/}} TU裏n$Rc2cK4`V`$dz4 ~\@[U# shHW A7kP[@V~ =z?H UG5HmɇJCdkbMpqpۂhG5w3mJ=,A圤8!)& #,+NRSVv ,m;HVPb:.>fy; Dϓc!o_y(3˃Ob@@zk2 (E{X~ 7=_kUGH2Ba! @: H~fEc8s-CPmAѼxN}8tsxJn)1Zsf ق03iWPĖ ,ir۲ J˜gEKY@M>C}@Tkd_>ϚMti=mғ1^'֋x6tCvi4s8m Jp.8 8w^.otXpq 9RNوAYrdX(,Ktx2q7ohioB G,ѝ喎lAsJ|4ٟtׄ!`D>+G@2 "4SPg Fg+B_>\Bp1XAE*˧]>$;%3jȶm&C0w a˗׶ *z1VS 1;-MT)ˑ-(%Alb4@# j`I'Mvr:1A=#r>`f?7 (u3@q| zmC|?H<>ڗW4%~2J.%,Fct7e@P51*qVog" w͋N&]3#͇+˨5v>Xf‘ :m@_mt$ ~3xv1{B19YYcN$]4pAl,id[WBZ%)'-V&jh\߻c}D[J J%_ 4OPfhάpNy;${$r{q)AAvmDy_E}!J1ʀ2p r|<ďq *IRTRP4g "fQØCg#x4hv:: J6=\ du8/Oa4*$QOιbְ.KV bmٲDB>;Đ,i:0Yk,rJfqH|{{gjL3r5 (7vz>27ncC+顾<~zQ& 4n&t?vXVͷOr,½ *$d >>A~K9L[F ʒ#x$ŲYrT"T!C-}݅GPW=q5~`BJYn]uި @9D e[ 8Jq^.@^<)q\~!?G(wDdNģFs*O O"K80pViNm\Bwhh%QۮxGZT.4\`1~NNY C'HQIɲZ%O;Jwp,{G`HV!(ëWV$53{^㵰9R 6qdI&P BتS>|v[ >^p׃f+Gј{=ŚIe`FH;קI'gYϯTiDgfx$L/\'V%L2xPmKp `a'H龛ζkmU )FhNIa _gèCt2C*#v,{u#gop smWM8{Ѕ k!/i$0K 6xe4@AlW*١C!P̞..5^.4 (EqF 6q{TY˥rMtfoo,Kx8%e+otZ2b `+n-3pNE r0QFVNkFyQ#k+pvҁWp~~8,q`Uɰur-VCTX^% 1JPĖM,iQI~XW*_`Hʀ20}OG%"&gL93Kd'yz%'f}%\ݜgکWe@ ,U>S H 9CȸAiv"@gm]!_GhC'ZkIk2Fi;`,58 zn#x*~nsxqw83BwM)َ t"Ė1`I&{,ٞ!ag,C(J8} 8n@bUIREز,idKaLX"Y;AKx`l+~16@_2 (aLkRҫ4H+r+Sy>nE 2#X,}jrt5AEsmLGsjgXMf%h\p6/^c<c2gK?Ç+A%e) )Y]*JLm2K (&fqwx@?* <|80De uoq+״2`3P>I'ke@Pn p t37@x T~]e0C9LbIK =r'A'G⑀4'&ɡ (d b 5`XҘN;ٶTՍ%MUU@11K2sr8X䬟bVt"Fe@Pz 5@ ȭV4 (ʀ2p衳Lg>h!E4"IR cI1{F :#U^m3!67o:|U$%娲@5,i & (Mu$adL% j31Ke:+|DqSe@U|M9^&\MP2VSeV03GZ|sDz]"YP#%!/#9PCti2e#\l fIVGJ^"6}Gn/簴iG@x2<A|t E b ,iR;ΔY ^% 1&) %2 (KlE.O"A=< g_>LoxIV ?^q JkR770+kZPe2Cgh%{"(a!(a!b+:[+YՑDrԇ*ĥmv^(J'SdI6b`I5XʂH1lP̮bb,ӷJ4OLa:`Sqe@PnN]%и2 (SKPz'}-_WaDea$  ,ʧŔ-ζ`,AnhoC_@ E)p2'rH1CYҀm1E%( E*% ;IH+W WUxAud|0ѲQe@P[ǀ=!u5 )ʀ2 \ׂ&X$9MqI%> b=d$qr(-4Kx شRй% ugEm!p I 8*㨲U{e 6FZ%Alb4@AlusɀXʱK,>_l.ql89mf_ʀ2 (X-VEPe(RGynd! f5͇J3B?a2oe+Ku?aggr^Й4χV|O. FbX#daI MP,id[,)ߎCl1,J3Ie! * IL_x)R 0h:(֨2 (O\g^tՠ H $ g5Zʀ2pHFV 't8'WKx bH&Y99PCt;첊$#%SBV"#iO'tEb|6B1V]% Plʐ,I@7QbIe5lQT@11K2&)FbtE$|kBلǏC@He o_K53UaQ Pe`os:T?MfvE;ˉ`RB)cdX,K:*2b̝ V!އgϞM@go/K|y\`F 5%Z Z["Seψ,E-1IȒʈQÞCPR@11K:!Yʸߟg2]LŅE:8APen1w*ʀ2 Q@g>*Y};#aa,[ˡdudg$Ecבm3m_r`Z.6x~+o>"LWVGAI[F Y^Yp+%6ȁdQy<*-%LizUe@; ?;jMe@(`=X.tgQ`ܔ I $"&r FY+dLAYKEx{@!%8x2gw/q`DY,)غ:"RĖ-DB~;ƖTKbl%G>~'tX|}:s"e@Py#4֔-VPẹ3Еp,0RptFHudFX3 fIcĺ ,A6<0ϒeT8-+8aVQ.IX^ e%L)2q5EѪrLlv0"$'l~*Nq?h661?dRzk E bwp7;Fԭd7 Do9 稣PAll,SfI&{x% L%N H&fI̒0# t9{8c%jRPe=1l/gzEr"ʀ2 (GVL:]]W`;(JXg]<T קT]:riy%94(ʀ2  nM"ʀ2 (9 4+Q8t%: v':p(ŗvaۑߦMVutأ,AVr$`p|rۃ.x}%:<ĵO^شf~5=Xq>eXٰ$K,@2K:gx h?C;@=;4(ʀ2 MB+M9~e@+ q l>?/@3};|()[3fkd#զP F~圱,|u<wz克Uo첤 bC!lQdIB:Da\@11K:V( W,9n ;94OW(t1,.-{ܬe 9G3 M?p~ޜ`m2 8g R "^Ώ{!rFpوk)'_9ǕէU4pU꿁v(RJLQPb(Kߎ2e4l[)2 e)ɲ&K2%db4tzKd_ 0PM*ʀ2&~ܿ@zhPe@j0mj'o#DI(RF24eIf%m0*$ѦRLWx#+m8k__)'2=nowoKP,T)XK2;v,0ed`+Ibo)GY4jTP@ƺdHR 7Z[ǀ' )EZ ?gDuZ]9Jf‘:g Q~ NdKzctX?p tlP㷃`K[e4@Almp"OY@1kYٰ$C$:A'4OGA%+:B' DP ?G91rsV&i[.^Ǩ҄2 (}G^@-39AZ FlX4{GC Fre4jB zas?q )\Q2 ë P]pn;4,VjP& (&fIQX6SfIV`I+G/_A5MJ yմ2 (o:+' x.uo e@Pd@[?n,If`oa#Jblekd XIU@Y 9RVFR!/HC >l ZH(+J e)C!"t-챤 (DHJL̒)f;/>Y>n uuYdi2 (Őg v|IBʀ2 L=4_ qlu0v!IR9Pbf?0^*ǒn&*$ bSQ 0(Ce;J8D_N l1Iҕ,),{"-KIU%mew#= M -\5h74(ʀ2 .i~;ʻ oGQ+ 4(2tརi2pm"?e(!49e `,ld JhPΑR4LGv=tWhv>=m!X(Mj(If0$aQ4`Lj表#+o2:l6\*ou蟤\ys8a@}3@IDAT_07@G*Qe@ c,6?8YMq|8DV@9 m[v3,%h JhTΑR44}A?p;@ &e(e]a eQ,i L6 h)$a',t8G9B nW? sPe@P)\]`L {#{gL[ʀ2 (w>F,W?Jq|/(!rЗ ,Y&3{$JA Ym ̿-2ړWbI& #,+0D,iQ,i`q,lI}}GrER6We1} &j`47SɂjTPe`d ?i@bԲ|/($d24KfXrjI RJ\?S P"El);L% 6xe4@#kz0HCR2L% J^=d&NN[~0@p&I(A%l!mL EXE'㠃@;ڣTTCQ. !YNHLV2dAH G FH`(~(gAgp.*0O(%5w_>&xwI{gx 6<Å_8VD_2f_9B]Uf!6X0̆8dY[ SNFPHFS(r%('I), ؂m߁_aT #;΀3p8Â,"(lu ͺQ}IaD7NeW./_dk?_5+  * $DD6Y[GEUjF1bCMfB4dfdjVd~hZ2 P ˢj!gBx_:h'qܷspޒ'e~1{& E:Iqݕf/pg@g~t7s?Ut$LI@=XHʼnEW , YX(6-haTaBY,p2J,=,1BbyRPJj!ȕE!NƁڿ|Hɼ> 1^tg2CIMQKnCN0➂О;΀3 \)069%;”Q#r { Y( e:SǨ!D(CMf=jQsR`XCj,MbB(2@*jkEÙPZPw?x_2'm8_~Su3 8C M.1&jxBxgp2xo;f0߂ڙԥ0"bqa=PW B(Xg4O'dYh*@( G"g G!Py g!$(F< 'rj:&ŇZCV [ݻgl{p 2]c x}AijhW:΀3 \f h_L_p`#HD)@B-%/{ړb 5BfP YDwGE PJ\8 QAw c5 1Fhx3H-'%gp.0iEQ/=>.sLcv 0{/<3 8W|ߪυ{s?vv!jo%ŬXT,A ) PbX h8j;Z 'Cb)Ί18PYJW $St6dCh!)qJ~ ~Eħ{dyO"S1pGi(jeñN&xI:gp*;\; {㱋'c1!TJP,ı dG P  h @He8)U#bS, P $TBJYBrxvSwϩ OoW%gp.60Pawtk3T H?DxrgZ,potj B4KP,D%f40WP3PPP,#9 5䬋(R\M8 Qs@ 5I8P PFnQ͒E+Nk$Dk!/4qgf&?5?Ou΀3 \@4ݸ[du&cVmy0i *=9sIp.-,k? Q93%bVT [(a U(dq,\Q i<پ(@*5dc9"Y r-TBba5FB-Ă_iAH( ,<Зfg-qUXJ,?*gxo#a"Zc_)m 7:ڏx`2 ?EdI^~??E `ݹ !jTQbVT2(%(aΆm `)d  Lgw8Tp"\A 2L͊ThbA<4hRסgނr'gx m DlÚXf~cqlӜp"E= 3Qn-,6 {fL2x}ۓnBZ;vy+q:Hڰq~}p8׬φmOP^@PUra2^ے_a6B4d%D)*D"5˫9(Y@ X6ZQq T7`:W' ] CQL[vXX{}Zjחfäj˺OWtlǿ&C|@{& Jԁ>-'292`T_JZSB#Ƶ|qn.ajԛr2E aş6g20Ÿ<c,W g;m VyW_}+Ek":QߩLNe_|>qƉ<֓,Z͙V l"˴\_30 `WЬ͆F ^-f%喠w B1+1 gC qme*`(!Py}fq(PB$&(7PL͊WR(0YA ,HEd0&h>k _ϻNw:pan~><9g xh՛V wӜv`O9֗a^DA_M ` ¥_<Ҵ E9W}b'Z_vt/冠my{-(@&C=Ndm'd`p" 5!!P)D**OE%B$g(EԬ2Z 5Ty |ç8 8'5gZ{5?\|a~~dc>xc{2{n4> 6LW]8s΀3 \^pYq=|01~Pk.A%XW0LDۉP#P93Rq8C H(Ui82gU-X,EqH4jj\8"BQZ (x'agbnN(?Ï> 7q3 8?$dC6 s׏Du +5XR.^פ4 kt?g5;K?ëo ryQP̊J\ț3;H DHT**Dj 40 -f g(DORԊ@ ,H ȆP 4}t Gh,  l` F冚s8F,YQ6 JRđ*C8gGCrxoA?%g ]8pN4K_8;v\/6k}`r`ףSBqv3 8|%Lw xV^]Ʈ!&B X@P& bBJ 5GRRJ,*fEE&"(Z7K2V@%lx0oܭ37;;OuF] 8?08 f{\ꑟ$Ɇ ۇa6筦$(`4:ZOH9v 6`e| 8Wzo5|aM S0 #Ye 5Ĵ-ndY,"%!zLNLE(*2rr.Vb'FPJn*$zl~5ޕtIQ) ضE3Y;BCm2 TkS5Y;*!jANA ,H ȆP Q#UQV?o8p@epB"6 GA68څW%4SW. {VK|C}vbg8?leOLsq#&uGЀx‘“Ҹ&fVp$Qq$sE" 5G9X"Z(bbY.cĢ QT*Ec d V0B`)s4R Q5#=hB}'ƍW8Eb Y)7Ћ-~xwףzcl5: ֨O >@Lmp؅/:G/;gU w~:ѷ^B$Eu6PClۢ Ь%DԪ 5%B$&3 $S"ӊ R P {U+jEUւ`2xQ%p'? ~_ 8?(!vུѨ\#ϧ9,A႓8Uct˹&ЈKkpcbyiΈ$izPŴ]_3 8C_2|S8NK!j2 f ZH4PL͊dHfbE#W+h"wVZQ+*%Wћ,0_Y p.w@W?s'фS4cPfSҏ0wkzZf'BgjdGpc _!JS'b3Q8Nf  5Y.BDbT(!(RpD0 E%BX@)jEj!JYA+*t4JLR)BIOS\p Λv޶fMVqKO#Pk#aA$; X^g4NC:Lnj.8΀30 í?ktļRM fU)T)P 'DBq"Bd@^4PB-D VT,/H" 4Y"P3V$/aSD^{gfýC.:cכZuxm`M1zI 5SdW:c'i,ۓ3 8 5C8ܺԎ}*vgpt 9Yδ`tf 9e ~jE݋` Ew/"&'5Q2S9=\p`'_'_>/81NѕS_a {aEBj2rDdPXd"Fyp6'B$5 uXbdXm$@U(y|0|쬿eg O7F+pvvrc+äǠ7zcl:'DMcZoóV?ވ04t y_7+g`Zm/Z70C=BֳYBC2*7ԬMF˅? P e)TBR4B-DDZ(bXe1ʉ VDhՊf:j*Kt@Bx'D# ~eWCÝxt@ Δ 76{p@7'^ڟ۰TAgP niq5ZލEBfʼn1gɎ@fDE"P3Q H@CMQnP͒EB2P jE-B1j!2e14eq+ěxZS8aZ6@nug{f``}Xz?[G֫aT&RBu~Qcۍ6`Og:p OlsxFGam7Oz5MQ7d\ ȀMX"Z bʪab%pSWo_;&˂%5:<9]ff*>|(m_(qp.,gro24 ;\! v͒(fy!٬+Z-*0FݩQ8כ/9425ݹJ :IvlK5̆!Py#%!z,pb /GlD, PJ R 'C]-:SZ&g'S@Pr*@(j P !rBa.SJ @+gTUL"HqnZ!sAj̕Df4⭊%Ix0 8ec&-ȗ'>ozK.UxͰ:&;6S40V;!7 21wjI֣hâ 843Gܙi&J=LYj'Y4d%Dj2Cn Z̟ P$D P ˢTԊJcb1a" v'.l fbL 8p':nJm΀3 \]𵴷g<\f'wCnPK@@4 (B$&((!PYEVtfI‹ LzYA 0@  j!sAnxj Tb&d?\Ha '?wc7}1Unu NrnWMalwv9q ~&Nxo};L 5;`EiY;΀3pu-|apu-j%5(PX U")(@QAXJJEZ,r4.LcbAшFB-Dr. CȄxBY҂W݇՞}Opp @/*6xŠtTa?'慣U 6۵zg/wa`X;l izgb U.sA?Dp0(tz,h8)#*EV9H((E)BD@%!2UT<p7< 5:J΢v'<ѣ0;U !΀3pm{kkp -17a< ?8h`вy[=Pr;(Qz˞gpɢpwoB~ P%BTP P]Pr"J$72PST P kED$Qh ZiDOTlg*qXjU(zv9B⡃Y YTb e!hRc>J"<7< 5cUBNA7 oW:,//%X+~jfTjgp.:jO`Up`wb`bRc,`d좨w\>Z@)a ~ ! I0ӭSgfl<g ݀&gX!n \EMtIJ+ḤF"X`jg< $Io'>۝:ʐWo8&(wYN z+Xz0)y'YG/9΀3Kv5Uo ନ=e" 5G9X%j2;U4DB"'VT JKQ8S3U'P%eK)"(%iB@0? m?i7;Eg{۰1saxӖpl҃A7R^H4@4u9Ep^պ3x`W\xWNԼ] 8UfJ;aӰo:d"ʎ 9PQU RR t"+sa R*-TBJ@ 82gO"x*1 %| 2 8m9L  0߀Ÿ Ԉ+ztp'Y m^v.@|] áhC.,/~p@ 7g=F;], u:ME(Dr(CcS<T)D%,p"P PFnQ͒E+*h:PRi,h ΄8_UKn KKV\ 8%aROխg1>@{ @^U;\Uךo7tGNO)':ƀEN䎭v8XލVHOc]uo`Ub>gp@홿^ Z7<lYB4dJ(bhZ R*-Bj!*q4e1BI'+2I|Ƥ }~[E/9%diZ{ (~v[/]k,i?zs7ǂ6fi}Uo[*#EOa<:4KvGUf?%D}SC;pdT\_3 8ge'J[Gaw8 +}̣\A ?(a"j!\4ZQ@D)*AbɻL0%g˚:XSOB/?I?x:NHrQg@ ҤǕa})ӓ ,OK_I%xVgى%A|( k"!Y>ެ( ;,ǝ*ƒ;|>\\/;ef ڗQ3hQemv~Qy?Ss(o;Hx ۭVW8΀3 3}au7 Q&H3 JQ*aNRqVPfV"Ej CȢf%I"y.Q`(̅dad0B^g:O?Gv^lklv&C/u]ZYמ4[(8v$X}lv.gȃڵW D̳ ۾G(qpjaSx+w['Baov3PBbyN TB, iQ=J"gdHj!#aѫDA rbAexⅇEp"+nNO~"StNI ^pgR0{ߏJWLý3USŷKq a+OGORrV &<8> 4v;N!S}WBg i/? z&0$H%B4(^F,TcAX Oz<#V)i+@gkͿyԇKd6<5~\ 8dI/j,5_PuZaf< PpK@=^k_8PvQ a/%VaM6zlH aB<Σ`0+ϩ&㠗y pt]_3 8gd Ɏ_ @7bv(9"s"p"]3jj!"51L#X C LZBǼYQND]ь]-⏧ͅO?R78d|w4+`ȿoEO`Nmc$uSk_w{knyj;2 i}7?dߕz(gp3p)8M uy %V~yp;'gpq^){^31oa`@~sDacPL)Vy+0a;a}s0oM%;΀3P|Y K/o1-ՆL +*!:qTjf1J@,0 QRdPc_7I ID Q'!WqcSt?Q EpO$?xC,l$.* C]:#l'O6í8(0q:x(Ke5aPR:}3|VۥZgpyF8 v[3A8U8 PJ@Vrf&R P [ VT,6:{ <$Z+DB\ ![G(~0-/@K?* 8Uf NXwNH P Ѡ@ 5'B P QhQ͒bhxEDp.-ej8p]1A &j+O^rĩI( y^oۯkKAH +;ɿޅj=9΀3 0Ӱ8y10D@&ajVcQUJB%Dr4r-B4bIeѻ$ Yx QߢIT"D劰Sx] r|uK)]>q\|Vi%^rgR1 GW+ KfO&Ja]`L A4 @2eS<ozvV 8r)+g{ؘ ug\ )lPtj˓p"pj*C~ %6xpsAyV bX:)REOZ &?VO;Nw^r3 \Rj/w6eެ٪WY{:,8ٳNP?W otw!m+nǕ)Vʓ 8΀@40Bq.#@($("9j!HmQ͒bhx:B8ኽ(QEsZ#TT#DTZđdBA('?2lDV0}LGxFS$|m 8x_6Vw\>y]x7L=~&!|=/pF4uF̱ L46~so㉅'=7Gz9eã-  8΀3P_Y曝ȳoŨvcNTPW‘⑉c*ΤAj UmE,ֳ`ⰅVN SF;WEVXpm!C?Y:%fG7JfgG[&=y&6^ _ptZ'r vRASχ0@vw 8΀3P@ Íփ2S8Aexh+ĂʭW8 $=D!T -:[̂dzD~z(dE̡%e Œ$PTZ[7$_r~ͅwv k_K+p3 8xpdW3͊q*q=]p>S9 i9+QWrP@Xaf4H)ۮPbpvuʾ6'nqg0ߺV:?(v]`2<2ۈ{̑ ! 7wqK@={_ivBU;(PZAVoFg+P:D# 0m36jЛ?GQ 841,xJV ~OAp$ DB䊇R*&PxCfL$%f䬂3<~$[!{\IKa-?Op3 \p`onހmQ0sW^`wdh)\OʌwXFxxZڐM2ͻ<`}D Y=3 8pu?ܙw0W)8 P q<*f@1, L2"3oVToYEX! gTŻ«nܼ18p.uX"~Mݠ,5aKom`6Έ2uRWJZJ#5$i÷n?Lpp<׺" 8c nZp(4Cw9RXrqhabI\4B]wA= b&*"GҵD'!_r|:Ipp?osg `adWכlw~ä_{/L|;%Á?_Pb߆]joHcϞQ=m6Ep} I#\p8΀3pEZ?XPf QB,a-LB,fPxTK.GAWDBHY>Tgmy섇χ Nr3 \`S|݉w{/ڋħ7?0Wŋ'?艿:ӢJS<w~;oNd9%*/ gpk~ ǯNNj,Z@+UH-Hgxjt*0C&E&3JrVAŀc%u|x߰j%In{? qY?;anwjfQ8y?mxc* x6+0:5g":p5| Wb> pg pwqXlVy:vUNXҘiaxj R`2j͊A3Jr "B$ "ڤAYsR~,\^^na23 8W ǯ~N˄[W'00:)hq7= jP~7ћ__ O6ou50Yf-΀3 3B7U11i7:R(D&5D*sPcSIu("x^bPLuB4\_܅3G[p_TO$3 8W\DStcb ՠ VTZ@3< 5:X\x**YbP,"pzk"r}FpQ'͐tᬦ|"?O.:c_u[;q+q)Jxݰ}pnIVυ*cN31ViT 6} o Q_r#IoEs3 89p3x% 5'T$Dfъ ZFQiNC]bȂRcJC%ܐY@"Y}ҌB7 c-̇۷oNYp>?ڌ}j vo G+""k;,wx[jj_3zw=Z$qQ;快 ZfkɿV1}oq8_>0 %)g QkOµGZ.E!cZ%1lxj*0QP#( X˹"r/ѿx_};$}x_W:nʷ%gR3PI7{7q2JjC{_<?zBY ʨwz0jq𙧃~u0l܈ x=fk4"0tpB,BVP?3ba B`K4 5EAٓ*D-^t"pX6S]xa>ބddKKTo#g n]b-YqOU ^Ν٠49ٹOyQQL^ =?fQkKXŧ9΀3 :6 T4.FP Q55 5oCMa3oD%>ު{WqISkw:Okea-q3q 840< pe'!ɢCvZ܍ TI`u)1"9RFM{txߵk Nކwu dhzۍFawokuWO[OswLy\8S`&|YX㜻ie}2L}xmF[e&o3 8I`R7z0۬cCm諄L* /Cc)1[#Jȑ\]P~OuB~,E}aݿܹ?3 8W?<;\( {\ ^9; V&Iڣ__lVKHYs.W`?$Zw?y 7.`^o{ދno3 8Ȳ44k3f3D@ Xs$$*d*EP!J"D-V5Xb#[h6YPV,Aj3DEB!$jjw~]e=5>{n + zgpxwtV5w>]W/Z}z_4G[w9@rP0WSXґ?!S:P[Fu#|}'gp dC-i"P Q5 5J"b*Q O#>)1$WXxq\8 xxBuV~̲g2Ѐ-[{//k5gtr< p~%oHp la'gpLM1i.ߔw9ҤPbj>Wş^ߥ(;mTp pq#|߅(= FV!>ZB KDXң,,p:fϯ؀WPxw~?;w?GUa΀3 \ZmR3υ%?EKtiK?Nr1F]^n6uU X p9&J]V{g( U4D;7GmÞItBpJ* dxUo+ RbPAP<wuT& oHde8f_e7.|-dgpxVc= CJPced쉼G%AJX$RxWD/V[U] ͐tÇ\;&pp@6<[V0O𰗽ևL;BL@O`9{0LǍ>7^p8޻I#KPJ. @ݵ3f4AfwK۽mIpH.woo.3n֢VYYUhU^"2+*39N'9.H Y502+D8J\c=9œ8&YgW_#g?AzLT# S.̈́jVBJb[[ؖ>av `!}Y_.oR3Drl4o8*DX㰴"H/,PJxS_h*RaV!(4ZTXTqU.g/󽨵.+u=+n^͕ QYxTJKL D Ȳm-W6'~%ݭ;P,.wCOM?OqX_JG"( Ue\0eEZbm*.y nW,zBU"@ 0f p,_u(j+ˌ(S#(JEU.p?6޼cA{/wA;,ߥ g=N,%( D Ȣ ' a@/%.8^ֲ Cٸ\. V!r.m@OYu/ Z2  D$< Fnq˜ƛVTMo,(]<ߪ\.UĹZ(px 6'Ј4e6g!3(X ad%`F@:pOV]/_u~=phHEgɒ ÑDޒ;Nd#9we&ƶEmJQ4H1I< ٝ"@MK]ama l8L}9ͬpE/Jua%U.f-\VZTLn^b4l_}_`  N@}lkw^[ݚ.nAsݯx.N_gfBAA?Fc psA v$Q@wTE % ﳠ<)N%y x2Ǣr8{oͫ{^Mm]Ѫ< xqSy"@Z$l`-@Dk`_ΥfF.6_f(}NF:K͘,/몽}dA:e|.sp"@@mp ;[Zom XfeRer.JEU.W\{Q-/S9]TR:lD57 01_%\4]x f>!L*9#%h/j.  AB2bD-( cCR 5z6|.G%Ƌa,l}PW^)$K~x |p+0)"@[&DPٮ-&BeƜ2..hDA邏 RV*\CJՔּKܬ sYb?`B;Oj#DE X|i|%y?E{֜f o=N]I?ޔ6([koCR!.M*`zw8k%)"@@ ѣeaT-T*\*/ǃT*<j\TCrulxl|7擪Q580`"'>D:QTp3_픂^, HԪ޵4da^E:nX'NVgί75`C;#znengT:y,0u^>ofLCU];}"D kqIŞ2>ܔ!KE%]ܧD-x.5[{9Vv# ez X.\zz,Tv! I2wK緒-XϠNedSv6)˄ŏa \ 2uoMg߲_P ^I%pTO 2lj%)"@{6+#Rħ!e.W8]Pl} otpxt.5*t߼xT ' N {eSB=EZ% 6[tR?~oLi0]]V_2S9IG3O DL@l迃QӷSjAɂo7vTt>}Ռ]6Rv .#=Ej "~)[Hz~P]C{ɞ?M8rk?q??a >+Y327sL!nz.%-!H#D @b{Ճ||)[셢J**Q%wE5}-UϹVxͭ͛xfZx ]b$ 0>{M|,T5 -C@YDVa-;|8pDX!o]'gYBjVz%02Hi5h7(3΄dӴWQ CPL@e =mXnBRFJ z眎T_*(b8vE3j'VؘkZsk/wד;/0}ð= ÀdCE)Dt(k/t%:dEt{qض~C,rKI|#7 >S8hG)FCT..uŶE|)("@@M0B hYMŇ2irMp\тE*D\vшzm2f e{9W`\d`ݩjSS .şiٍَ&$;f4X>r '`|4(t8G xY|NV%Е DB@d u )w0]HQ2.kUV.ᲶVΦnUW(Ƙ'@+?Tj  # ~1 /Vبz֚(Jj60UПNBeecC;lo,v;`{b@+ JUbmeڒҪG "`f''@1 gU.g/󽨖e 9S/ڜ͹j 3#0-n{DY[ލY 2h~mވ1' =a`/zqA 2򁱼{`7T ;[?AD:V&M&6+D"ol5uF^7C^x r8{7qYlYRsktӼ!8;/;/^[M$ުeX\u=D:,)7 Apgk Ov΢JV `'r/[ϊ6nhU"@:"nl-+~vG{Y]^DYwc&x BPך8))&n^Vw|zG_:SLmleDW|"@@'f{`_ ;\.^{M\V2[{ԼݱۆQWMD{ Q&"@:O ٍ;_v+w߲ NK<˧- >ȹ2xrR #=iNǍlzET`"bJ_?1zc( D AjZP /XU.*R\QMJ**Q%w]4*9?X; (p+@JDN' N";y%%nIRS{-vϖ||)Mݍx{ ;jB.im,#RuING$V/O9  `3HP`dqc)U.*RRPSS%eY{m ;{%%4gNr" |J^nF \ &Ћ][q,!m t;~qPF55>sg;b8b8ǯ7ZMA;{Q`oM A7j }vSzP"D}h,XF 3\%>ʖ|Z\ %J\.ઞd "c0= ]?*HzG~M\؎ʮq!h eBaec%fVwc:ȴEg^XFfAmsK\s q@ #;f(/CC8$!O:I(Eΰp9d`{j?YjhDsںiwe@"ᗻWKGK!Yr8n"AP|f) &-5ck.fG.s {Lu \y촉/L&f_ 3EXH@d ;O(CAAOu: ڎy>TR\<]r|U_fFt2;+!Fyhwc[;EfZ*> [-xJQdxe_ |F26*ϓ@&xdffe$|[Y@P)yad^Qo .8[K,_vQ\I e=82[Z*].hSlt:K`y&HZ(c W+ Dc|WpbYtn:#U=23=@]#6>McЯ|犁hBe 06n2c%6-%UBCh[5j& XAV .M;4ѭ[%lg _Xc!Y[Rˈh0xb{mUHS0ŭ{&WQ/PB=@08N#];5?O\Wh7d"?2V"nj.&5u.*,D l+[SEBv7T]||;m\6J3e@?sSoIU%"@}]e}/&J5H`z^ '{N8*PQ/?iEQ5Us ʦ͹Zdvӧ^u_&JDOط'v13,Bs E_s\*[{we i{4/7?{Kާ ODt8ToHn9\+_rkΥX 2>P(qC:M[۱)+qgQ;%dܜlF7$D4\e.)tAd< @?{SdwOr"|J$VEХv}a?翯|ʑ O2_r9?y ԉAN" Xzbff#QT̻ɆoE콀OtѻDt\ﯙaY# j1P]eRnm1 DjTN?===\f!iU"@:$rLe>c"fQV24+sP*\B?KmڹV`!\`Yw>Nu*M lrb)"@:nz` >|,Z\QrV ְ,Ϳk!  mM@93Da9j(crw\q]4E-6`$jTNx%SO+HW M@d-U9:i? i  DV6}pV3RTکL ZaQ+ lLm?԰ $eY4 < K@MqZ` 'ʛpR0||'َtuMPFoĆz/Tq%>Z_&D@?ݛ/݃#- vN?bWo]JƁX˻͝zTxUK5B]*- 5\SBXZ=6 1N^Q."@ڇHHH.Zw.+^|skrs_`?[3udZTO#QQ"@:(Jlwokkyff[6P[xdVzMp('O# SV'9ǀm}IvE[.cQt[~Hl+"Hl#5"P/I;{/*׾l z8.[y߾ZN@nv3=COm.x6nҳ\ʭQtjZE!ppضv2lo+/pX]TJܠStnX>cB0=4{C!V(K"ob'9JcU"@ZnҶv!;u19lnisjCH$u.9 ^ ؃W_ӹ,ְf>OA?cokٕK~('K#_ݗoQ=BFsCX M= B\hW[S,*+Af۲h"@@\sЖn(ˡys o-\036G hUɋv?$ O@K@y?F_|?MX{(y,ևΊu*=7F}˸\=RN'բ} ,/X`_N~ &`\ 'e( D%èeVEe;::R!4s>8a}}}kLh!>9&&Q? mZq7(! s1 ZqK)M|b}y%T&@hkH l'oeVԜ(g:S,!. v0W.'D x~ 3P}S> 7oͫm`0De0%"@@@.?bT3~nW/Ⱦ~^; ͌T|8{?rdYJ.S'׊ |Qx-Xkbb0@'$LPLK-oclJDv$[ifEs,ov)~Ϛ+ݎڌG`;nvܹk#݉"p+w- fYݠhe5+7 EقT˲$< luhz\XiYPQwq 7>f.=~>H|hjD]TG9uCaW Y%Dy551n'н(NRACߋq`|2qkw\m' (sBL$?{}9Bs=-"k:\\Ne EWCx`@$JDv"n`bG|h|WsXtOV>{ա$="&9Xȱ{A?A7u/kҖ\&jNr,xl EM~#ל3ٕp,5< ak>8ђ@ (+ -@@߰ W0l^͍o+ՈoB? pU9UfDW,eMj4~X0(f?BRkPPhx @5(:nsi|䒀{ EgcyGوh Sn9 l9]Zm dz)D[~X@"$If__j>[qŔ,#1~umbZ|ǘIibv ߹,[fr  EkQVmige]u3hE $DkIMAV}c@?+ŌƤSwuusσ!edMCU"@ 51}o:wdl,a?f:_xJLBV._lZYa|Aܽ 7_GS"6 , g_0ۈNuQA33h" D ĞN] \_ k/T:?&Į1 WV‰Dr+a$-ZU (ǵ('̍9pe@q?: dI"@qikl/?*CO&>&7V 8L 0۬W {%YNhj>5s6F+Sy[T?M뿖lR'C xT8}z&Ѧ&Ƅ-/C4k;%qsz,X#/{b"%gQ^1 >76xy6Aô('lC uxz:=a]3RnmX]2å^KNOKT%u= ٖ ġqFt>־<|匘=HGI%h*TY (+$7ѝtg'JG,g0p~F"rl?\߿?}`aڋ5YPYQYVMQ*f pcuԖ "0Z??3 k\pOc{ɵ\D"j$PV{if2CIsh72ksQ(rYVDV&2 ݄=Rk[F7.qna鄹n{PK L˫_cKVW ,*jVh>6Á g ̇,)"@ZO.7T 6l`'J _ W ]#Ddn}]߷}#hh `j>OR[ơ\ #SkjvP X(#`t0M;+g2)&^z#/qY%"@_gqu w˵er ugmKv _]#D L74ƣ`Dy~%۟w״!P&N8 2*?yZ2!r-!dhMⲖ|GRn|Ƕ$R&&Dϳ:c.NpxhqX"nfAn]x")XW"@:wv'7.XO]cCK@=*u,O:pn8GWy|E$.T -6.C@_jHR[{{3P8J@SȢ^ۭHoʃhJ@꽢"@E~]VwGF7xјkv,݈GdRxp\k-=9i' d'<>rܧ}/2CC3KRN"@@c `[1ʀ]! ֖_ j{C,he&mVwYPODt ]ߜ߽Ty -yk gm}3SCySU5A;c 'v੢Z[=T+H^}Ds v,P.h1 :2}^2/2f}}}  H~Uϲ$/w" }B#eکe|n(r'* r WB(*lV /G9 !H$Kk[%k1 `?ۆ>[u? >̕"4u}~vx=~?_?徑[dQ\6-MgCǣ))rr.1B&cqm>8PPkaY(qCO"POWg7j=jM>d>^VnbzVRԲ_?W<ߐj]O`~0ć@&9ɯ'KG,p5UD  haE@u唱s3ROQYs  E@Rhߟ$jL(XЉ_cȎFc3OHC`8pAْȟpteTکHJ|:M=o[ڧf zToA!v@ ݟ ¿nGaX"@ t6'KrjʼnfCB*t 0ū04W`G4_+(rٴ-ިvU B /cSsALÖ) WJDq5S8=,^ߴ[SD?tW]?wi܌ DN=ۉ=],2\Wc *ȫg :N>:$-ڂ xef?k+-s*a [0 È_ goΒxT'uHr]X'AJe.\`AlW( mE\LUv⧱A&{rNȚv-D\?;(MjBLJ1~%V'Y@Oɦqpj DUцS7t;2g~P;DWhc(.M/'xǭMB%^ . (o SqQ Z̯Fr$'tQ#)Z vW,P@Lnl@ˢ-zmD/ۚO.+?O666 4ufz`RJ"Eb@d޵@! #JVs_$D ȰE}"n=UN5S]cd^<@Fdr_^OThKBB9[ے`(PJCmi]KUOJ$/>e٪/F:'xa X3Hw\`zl>p!|­YaMk[w"iiaRNn ~?4懝wً6 ;9^eK.#*p0g[4s@oƚW\ȬElw1DplR[_;yWḊ@waA?M ͔ Bf>9u" N:&XΜ [kۙJ@(;r%NPP,-w~._$@C:Ҁ<W Tl0!)gI% H=}e0lF>l0c ?ε'|>622,@oJDN!ҙd̏{WkovK5;Zr.8pa|ϡ܉m:E!:`)@wϣ[Ɗ`xҭ<%3L8{x4<cP`?~I/E%2YyVQ;~D$8Wۈe~P@#٠m:I Xw@/I+q0)+;3uFaYn+WcɅ[;j ^DžJ"dڷUu* g&뿋Nb66>N\,DtKw_j{uy΁=AΣ lÎMn/hkQlI>B[Y/n~V(@,ЅKLP"ejfV E@]vN1¸4uֳ:@?cowB!vEQ(ߩ?ݓ}dr%[$ukf˹llgJ ]w| D3(RܝSO}D`p? x8ξ[~>b8ؠY,Rh @`(@ m<Vr2,iR@zt_"N̚l3lWv0^Qff]c3g^TV#:o;Ê\.`} \=h`ZK/r/ȭņd.S(ku4\{ rKgd`&H{5&T+(O~2&2!˂"F0N(bjo6FxMp8/p뿾>vFs+D4ٶ[{z]0gm ?]߲# 6f]M.:\/#lydT>Jg,]nf jSP+2?3zϼXkYKR?E*IC@l%uf" i#gz`[DSX'vCltt g"@ږAO ۑI3O3hn $ .߶- li'e@Fd9ʕpM Caav "@^XXszsL2mZ PJ*E:Kk,eU`P% ݟ,xhJ8OhfcGʓ+DYRX6>^]~0Po?jGm;bC˰óۛsjv+g nc#L3:NTN>Hy5};sy{Q{&:GќexF2"-hi7E ԏ_e%"Pl[5< 癦b D .~ufe"t[9~_qy?0wem: >ö2%b <_GYuT{8`G5\'%&xopjf6ϛ^!OP|l nyG؀~p[R d:X-P P);+nw2ˬR]t"lWl{w1xK9E]Md] 6b!\̝y-K@qPVn82$`|يݭM *:P W7f(U4,vܰbSa}g&k6a)@P$Ib\&G`kti}``[ w3v>vk!l C?V[Ϟ;(=ljo'@Fzi3ߘ3{0jǷ6v"^YP!R0 Wh0FRtNV([aDhhvb%VXlbZ,I8QY "YJNL~_Wf@`^v$t_'c;v\ c!f### 89QW|6ev<`Iɗ?2/Xd#Ex#u|yVΒ QFā~Ч]}X<\R .yp\z @R}v~8}?ܸ_|wjRԇJ",.3l{ [ASd\Χm.0 fnBpUxYHIkvȪ|ȭ\F2#ȏ'^4f4~Q7N% 2ztI;kS۲BSZ` 7_.gyƄ{($?po??kٺlb!sܕ 3dpr >cwTw*mkqXF묷6xV:\_wK09QxGC; ݽɥ6 5^VQz0Sw2_E6T³\>?QN ޑ/(c#>C~F/Y5?31VEQ[yV/i:-p%mnwe2lxX,Xܽs!&@b-H@Z&ϐ߂ϧd"ӣgÒ*ku]gg -M@|v:^ܽ_)>_H%ްss؎S%OmzND'_uSs>6^g|"dx9};$`2!qA-BvV>‡]W?$`g˟+O33K˫-&0Q_\3lۦRj;EG bK;c?>{}}k> bq?Y16l߲Q6Q?@?Ke_3~(43x037~ .UIzc \vy8v劯;-Q~5Ed]_@ȄpCT pݠ-yE$uXbD7 c$vi<~qQOo_._1‘,uW聂 k{} 4+EW WJ toހ"N,(ڱtNGwωȸΚܳaZϿA %פ;gR WfDKconc]ikJ?'=~Pl_o@ x@k?uLhNԀ!`2X-ldlx,2t?>[{F/Gn?ݎeZ)o^޳o{ATԕ@#Xy:j@ï_jXnE`cRˊ=y#|`YKY} n#- P3!`yAW$$ xX{+/azk⣋*fwP 2(dR m{pTB7mqkᳰ[!tQ[a}`z3JD4X\.=r+z'F'ʹ?} m 9NN.V |S't%?(mZ V2xD<8?K^RPÕ:)<=*(I4l?ЋkZJT*7_hj}P ЍJkg=[s;JJFCW ?)N1ǍA-l썀UQ8Qxʶ%>/BFb?gw?Op&7&F*P36RAʗ泙*lӬ>V,d?o)usz~?&׿Vwۜ#[YB;Lͻ  l C?pfpL3`)_G<DねZ[?_\8s QnLs&lJ4ozWOJO߿Ro /4:^INdUOB r-RB(9rg.bOLAwl‡/W4H ,iE¼$KGY`(l:(ݡXk _ΗSlljvwVFn=(Lr9u6Bch\ g&a:Ӑ*ìalY6|^~m#'ʵAEe/n!*`9xuǎg_ Y7~Z|$XQЃa$Ӭ[ª+˂\6ً Ãpn#1&_LU{lS^+@OClל~22^ olTNNӰ:QfA_ڼ2ÿ#=Pդ % hn%UУxJ&}joa? -{ DB6,M]/f#㷠C32wO~~rᚈ{z0)ߞ]z:z;o$z ps}71AqR'&† k̇dNzB/]9Pz'A_qm dN/zhCmIUi0ܸ,?VgtdW?z{6ɂ }2hQ zǁOZF1<B'kT]((`\o16<4Hԓ!m]3>Ĺ{`oQTFVeZc)!z|7Q WG$RCO_@&J|`LRwޕxsf¥qpG/Z3I3kQQ$v}*8;{)/w9J&%=R % SJD<!ilppð 򺹫cvcC;.ŭl~ȎN, i8誵Z}+A ( ?8nCg"yRۻ4uH37A%QM#_DAfdY|eÁCu;4~KG ?&>J;K짰,K\W!C]LIu=_T'$gp?n\{ߗ!Nՙ &z ҅=@ێ;_5gSz|ؓpJD!Dw _C*J: D?6O pIw5k\}R&8GT`Xῠ]hxN%@^K˟3[۝ Ure).t-6o!nǞ_KM:j8\wd9e;< P'/ I txȺzy#}G׬*L=-̹na'b@6%\ uwa}C:_8_ЮWKȷQa&׮}}Oe5crRTcI׫YJ[g{Ȉ?@fD,WDuvy߂Xίrmݫv` ӗL8s6oגÁNQ|~69{UTшQςBhϥOH>ϥML uzzҰ _/ 1$X$6N?2/T}klqҁ!^.^zϢ_EK[&*/ӈToB%j{@6Qt1?x oXE& S?~yJ>c-PW+)Cg ɴX1?/ZaG?n33z#kWh JQؿ~ۮ9-Or0VM0o۱XfK5u$LY;O_&w,/pY(tFR:g0_~?l4V'aFkUHՂd;˯ݡ~->I$R҃WqA0"#Czژfgw s%xׯ|y>=/DjrnZ U@KU}ڡkpeL8D@=PEGUvtq,i4vN-pw);%)Y˩1?aOxw;)56/_l /5Y9;J~q?Iuar\,3wx hpS k4?|90@$_ſ|(Z! R7\oxU]Tc1m'ݍ6XR7~]woػ!-άΟJ*}Emd)w#X63aeQ0ك]{46>κ`YUp'3pگaV5h//5= 84H$UVq cF ԝaNxs|Xm BP"0d` suƥ<&u,J><\ "=%wuur  Th$KǓvKÙµDS">]wUmBLDSĈGUp=uݴ1g.X)<D]9M"VK:-*R=kU!@@2+poHGp?nA?\|r:?ORef8.p\յk,FOn;ǘ(ص igCF_u ,PSܿ޵`"5^`x؏Czl57I%U\&#.F$KE"qդ'w雭ũ,wA l԰kS]޲q;sB/m7?Tgiʧ.^49E6砗.ffH{i6B .@n2">jNNrck%fM_ZdY)_}C''#P$~zߵ \0v NJާ!,\q@^ӛm?Rڳ,-y|z\ bݎgw%L9(WS ,:M8 E.<'~(6WA _ ~O^[:GC J+$miR "V}~iX#JK%4޼{(ʶo:Je(P})!"Ց9S ΔrU ۾QLfqaI23iyC.@aÝ4<7 FV.w,2 ?8w-o옯\0fc.ˮ\@_p("q8'8lާ7}&Qw}Nl=w+(5~[a%ED'₶'^hdL# GPX`ݗd_r5|?0LN3c\b3CWQa1> <KZZߢY^v"{a.xOL~'GRrU8#p4|,` 5\:|,Z ךl\Q]#-񽯅7RbÔx;SV]ٲ=w,n=ǂkw uip:k*AcGh$.j\ `\0fH8ҶoflLjkcwbEB.r{@L!e˄dΧ,C=^-r#(Ӿ?%ClX-P8Oxd(FAsE4X4wT \?^\c^u (.V ??Ocb 0YѰZBiFNoQYg]Js&ڮ8:ڳ1܍wLpݮ6QH6]AwM$zf06\,O)Ճ(! w=f2\BudiW9M_\ߤL4_Kk+C^Y@F;@wiJq3mLvqXi[貌|ׁC"y"S85F}qMq &QfvCn^ΦR-bψo0W_G1$>W H>߀I6āN< ؕPrөLgϩ4 @]u6zQm`oȩ'~1Wof;p&Bis רtDISI"@ hZ2&x_ݤq*)nN". b4q\?5 g ܼ=H(TJܰ|#?.#/zCz)lXV".XD>BC0[NcNՃ+ˣbہ{ģ?v]Qh~v_"EYL.?l~mxn·@qƃF$Evo L9j}6Y{ b = 葆7=6v-^w ޭMtZLSYnse A]9O3NfĂϝ Lt3!Û1:̽eHusrjb!%s\,da29̅KǺ_K#gncD4_^%T /eŷJ4T 0o1o^Jdg/~c HSdT:#Vxw.jnT',nC~(.iY"cvDE[|<MgťN<|Yf.R]E.Z(-OQ?D<!=G{^}۾~&VW$`tf#鈵9O+>G!3*8mKNpQ|M62 .Ea눪7^Hh+l>]-pjAxXnizxKtLv.!0NJmBڱ+hh۞vz>LQP/#B!_F_x\݊QЯcK[6otMwpa3o|!$0oAI>21)mB`0Y% +O[ kw7veAW?I?_-,{HX+"B-;~ŝwFƅ.x^A?Z4c[Akv0ߝzF/x#rbO>& lX(˻1N*N2Oڡy\4CLi%RDLzױ3oP|W (8.:TdZLҭڑwᤩ"aQC*X/"ꄛ1 @wN-vxl%9Q]\SFT)4Y5~db4&h%Sչ}l!`k3v䅽v;vt?c]]XrIcWovL쥼I ibX1x?LPN<mP,vR-L!j|ʿq'sfUI/sY!ٴEV Euy74:)Io5lkڈU+ni3SA5EVGq . h_qa)KP9"2="@Ed.'NPd|Nɇq7%k.oʕ+މelƉ{_=C-GcYH$m4b17@ek4OOLohuVۣƝcj^vQ),#UJ+* $LQq!O'UMŔҝ7dS//NB1c'ZIO"dt/S<2`%3(!'" ]?.x`VB'6q}EiP8yߖ ؂V,仇 XnK-n},$† 9 ~v@ӫQ*s7TG)WJbE8ٿuGST6ݢPV׌>rt_SM-SkD6"n Z9v9)T-E6|ػț#6R}d2P%cjwdHC(0 ?0"RD-#os" %KpO/F¿qDFdz;D%{ I3u?8GD\ uR9D>m ! ٷ`/Ekk+祇pU |!@0$ry7.}wݢ;TͣŜֲFqOk$:4"ƃ`45L/{E8,XCk OMI˭ݷ 0AQp)>AAw\m,oA}g[ð\O.!dގ8HO:NG6R&n@>5Dʵn.JqsýKSܱ#g^HbU.,]W?^jY wǗw[|S̈́u_LҮG\EFr4ESj* \@9J>tEDzӰ+D>ۭd_"EKK=L Ws`x}ѻqcH4H9(֙I B)13'jJ 3@-Xy*L~ \aulFHi"l^|Ș,`$bkI Knpf.X(hJe7L2_ >x~6>) ӡƵ;Mߡx.H|(S?B C=}+Ss2#ÿqRzj_?i$!FG-ףk ``4I_'aN^Cb%$'^9i`dmMv~? 7)=JLet-X?7_!8A)<" `=v?D Mahҏz=Ow]I7: ꭧxgUdH]_RhI%]r{#ڼ6jRo*%xBN."ju'F._/xDÑPPR:"S{C/`l!GRNZW-Ť+X2s!1ʽ>Ƨ &.1ɕ0y FWEj"Hxby)70֫kn;,Tꌤx\%qjȿDZOpB5b.W?y%RܿųCWb%,=< gϙ}<'b M*cEy=?I%RgA'LWp)pUVS {^ 40;0vS$2 ['K L0Ԯ  ,)EEGpOijLtkOhNE8:>6BŦ7{O`߫)ĂfRytxTϠ 4 ϶ltuƖkeڈȈH_"If_._!IE/Fa eq7#p- 408.ǧZ3(vԉ}z!Xs;TWoL` |,i/25u8-/%;߁NY1vK㟌.x俢h.L"mD-AkNÇ(?K$W U-)Z`zsG|/H9DM4%sr:˝qD^2 'OdDٿqHsxj'T/^0sML]DZj)gIY1 _Soe QRh2 `]^.}" X[8iqYpj㯞yz2ўX%?ީS9렘3:2dxIۚV2UbQ}@FdqW0Oo%+T*-YB^[_b#p-H H{d׽tl\s`l2N=V;ྛiLع$ "@*v'@/i3OF?}<86B_6>+LxT?o]'Ai sİKe[%͍_k9SPMlR1+kq8mڶGV:\q+ԑnKs7d~#Yr,BY^, I1$$4(4zjWGN~˝IR⿳".t+(O~Dޣ@7ք>~t aa)?JToмO-$'޷%]+"B^EMs1A߽c6 FTgiG=hCthޡcZM_ѣoEZbcG^? "ID뿌 G{Dה``JpM3$ )G Pi!EAqoxxKzwB}I:e*X\Rㆈl9poIG2^W)Aj$74}my4fJL0Ym i;/w9Pjش|׀yŪBQZA{BK[?f*1gH0zkD[H%}d!@qS[ص/R܍%tRgjy͖9XKuT]W8PJR+[4T Weo%b%R !(*FW+( )rF"USFIj\uǙ;!C4t݅+$#jW䥾^twX{#07~ahᒶxB', `rи HvC]SK't|'%\K0g]@(6?>ppCg4o@.?;IT㈖Y(HhrnR9m_ ^8?Ԁr|B6h4%bMaIe8tFx5+ៗԫrWbrslkYB&eh0a1K׌'\̼/t*P?#i:OǓd-O/og@o|f$U,6c&)o/]G}$^g\\ؒ}GF892LY9xS6_~r e1!d#  XfigGS;i;R&ֲMR|K=,ʀw.Z](c[M5ӤWC7D\_l!@ pךOqZ}^]i/ԥye?/+/Ȉt:%n^[*d91Jy1G\~K[tP}c\/ّ<7Z!Gr;Y׬SjPN&9’-W."@=;Du=q]v,h܅ڝT0([hZ:uUMܾ3dᦆ<6JOCb4~\$Qzg#] F 4K9Ejb]'׭n%)QazF(L[~?8 "@s'yP8ݰn!M(~hcQRi(Kdq"\| E\IJ12Ej:JfW|˨=mAŸ S)_^53˴ o"=I[q:F0L#`>q*/ cV+mM8aIiyg\&U,Fqȝm_W[w"HI^ng7ZlSg,M71*ȼ?#P"cݲI ِbA0ޞiKny #GrxMtzIq# [b`\6t)H XtEKǓc[#ߍK蘸tFM/v4b.Nm.m53w_>ؼ<)b7A\5r#iG:DHZnw/F F&%\$|x8@O#UMvh(oQ"[L`0cC4 W^/4D,0K.o'/ɥp .'%ȱHO4x+[ p0LN :z~a\"A"6opkֿ<L:K"xzX ' LR($j5qpueްT\[VO~{::ƥs< -.tr eY=Uq2U+dv&nrGvZş&bX+ 2jxܱ38llz*ZE Far-FTn}uˡ7=T(,Z ؏ " ;h̲Kl NL&7ׅJKy0(`!%o5i`qxv2Vg.Pޓ2dݍg ۱-^ wBX]Q.@^`ORv*Nnhh T,] gEkD m_m -6t$TaZMK'oyvS|Er /-.9/Y SAƏ._d7(!ȩ$f_)sؗT :(I-dǶP2"m"Cw~p:N3c똫fD@x@@쿍]vw؄e/"2X D4S{E] <0"",-ɟ1֫d4rG4ߑOuIDA+?4J.(KDr)X)dW6l4rdo;|luHic)"0ifpz-;]Vu(,~|.&Sl"U;4  H였ȋE!?]gʔ.#PYv/\p=LpmXcChw,P(oM4N!,®ڂ{׆_ܳ6txK!k>gie3öБ H D7An5mO~w*i:o-VlMX%]2eP24H5SS=b$~膸iTc=lvrNDz/ZH8W\uaʇ=~Ϣ/_H=㈳0]52**S Ÿ́ptsC")0y_r+C םWnǴ#J% P 7:9ЈqAGOs9VKQ}SkZdלZK+$?;sT洈)_QdLoq"_(#Pk`@Or-[pX`h|zǶE '_=o$l^D_4*lox H,a:'v # )=/Ț/N'??uv KGXHFBQm?+_:Qy'F,-޹'=Dxgsa #0gN{#̙} e$2;X/2K09%  Of6?6ݱW)U)#=?Uu3|[Hn|OB RgPzgW7|w!S&@)XWR?;g-`ދCh@a=6]]pmhޠ9">u#@Ds"^ >s>TyZ{iF~J?/3 a[̑OCz\Q`)Io=xXbMO?.[@O#U8|kg]_M(@̤h8_v#7u'410y 8Rf ʘ*^ist}"~ІkL'94 uOc6:'sD%|BGÃ|soũ;F{C?kihPoi.e򟸩[?uh.I ~j\(??"z#[$$2 ɹ&TUFSe/yx]u `aDaE9YFwQИA(꼳~@O6a76kZMc='Sҿ"~3MY0D"w= $@v2s0sNx ">Esشcm?oWYd>5Y4~sg7$j%ia&O[(_@r뵟p3 CtwwoDkoU%$P"q΂U7Rq~'G0DUqb7FciZd*f<6]zDrB M"_ Rn@IDATǔmY 3<IrlhѶ?xפ,#uj36R5V'NDoib䦖K/p&5r4[8Ks(k*EЅŒ6 s=NkDY( oe*i}G`T :b+m. 2@mecoEX H$9C @v20N!^xp\m4ՆNdl۞ H$nty|)o3W`%1G&t܎ߚ/4,v4M~ǥ?xܾq,ۤ"1ׅ )8Ym;%gT̹k/O >r[76QUnd9XϜ9r[ǃ`(Y[uH0$4t|ѷs(',Ty R۞ >BF:c+/,ȿ\f9^I&&G)Q#֑Py8WF^UuϏwWIwCbltJ6/xibj4s:bo46t3f:"@Ow9xuKcA#AIInSO|b \ffj"=V%p]88wm觉yV. 4:z)ۉLF%cOu|p"pǁx#uTF;)M}ݟn?2h1M|B2SGդaq) 3 ȅImNtM4.`H_ִ12S8LJUw5sCHGQ۞ xo*B LK+Qp@XJsI! `Ӝ6G"b]/6zw}?FGrWlpuL+zJm%KDkk\|ND`\p5m_$="l m}3Zgl3H?$#X?( ]O. X+ |蠶I@ziLf|ZxDm&|}ҹ.o%"R;}`^[F-hCL"\wQ;}iZVիW[ԻFf0e$F5d8@GbfDRls<hZc/qxcq#YOgLJaX?A ^DZťUɕv|=`̅"l%x펱}tsGZծ.T~&0~0Ԍ[?^zBfǖa_A5Tn*7F`F0z&f:lrHB" VQ[5M\:xgϤәtklm6ooE!R]EUGJ,)`>Q}>ESɞ]/DagTN Xܹ˿\f2L>܌#0#09DzSFN{cPUz*0}rZj$ K."ɿ!t7050ˇI>xe?gWl&;wm!i{8%nl"3e3~z>#0#0D O`J8TWyXٌ"4?T̶g>%@{ΨW q9^Vz` Q4HDMs+7F%/$x;mV}`n&>t }J7okDL Y%*؅Kmdա_=cSJZ0#05bEŸ87뷾u^_aqNE<"eV>3"=p6~FN>c.a%$,,,syZH|^q!q6֧a,sYmמeo7nб ň1#0 oRRv >'7uֹ[dMK&c> dZ;M]o|_{^6O/ -BbvPVްgȃ^ZA 亼`"1]6[s.e@̝IȰ6xWWU [th0#0#0mv;zdG< 3PEXlHgkgTbozv~q,H]|>F`F#LxpoJ7x J$)≈HK3oNŊ$2T|@&lQ,ufj^vB@|ǂ݄ЎB'Nl#e:.s᱔=z&<}X0N/j.#0#fnVhg0Oij G ڷ.<=ݟ4 H+f*Ž!V!3x9{%8B bA8cvad2/m_ה۹26D78gBO:Y!H?RPŕb `,essߴti_b=YD@P޸쉓{7.%Gm>1wuA0#0@~EϿ cGUz@Z[bU^毐IG/zfoI"?t쾉ơ X`هtn?Tͅj-a@L {hgMv ' &(+n$EwG5sw #0#0!)ns/l;X{$9wϋ^a'CFKK,X!EE7qG?o]Ma϶K?DrK5#@5n{"ȼL -+<῵Yq}+úD3#4sc^Reb}_ƞPH@ٯ0#0;Mob[:yiKnƎ w \LKF픟>xK4`hd*dd^K|6,rK#@pC"WxOmvt]OE쫉kreو!亀 ņ7|j#|EooNsaF`ZFĥ ^['sZ5M,\FJ$TU&N%\?tV0vW$H}X'Z10pX.pR@ XvHY~J6.*\@iF{.*)Ǟ(dh-M}7.# F`FRpR<{nש'aLp}O).S+ʾaR[|I+Z}\v&Bjso?H?$ĂN[s_w)KM8q};t)n%4 Y)}߭4ͨC0#0ULF/])#Fc.`ِ3 +"\J^#;7=sUhc$2c=V Zw =o+$@0o{\^{:kPiI % e5n[5ۖLhN)eF`y纏^[nS4R(aZE9Eb%y]Ӹx_z'|rWlizƂ?/I-!,F=sKpl$tw|9ݶX/MDiG!`֝ @Л_[nzwW4(F`F"B{|x˿! p|ipERhjw$_" !grdSNI*OZv? XpAXJ/px+`AKCP+'~ Ɇ#й/!fX"13D?MI O"wUt o=yp9L$O G?C#h?< &wO,X]@@ H'EH1 (m4-;?V8,.sS֌)cb?I/`;R.(.ƅ?O-'BcwwF`F$l;xtXW#&+"O]&yѰm%6H87:EUNa?Xt@%2S-?gZj. ,ca 4=?j|_=9(xol )"ʕe{VQ}+)F`F`hr#/m~a`_}$9[ف1+o P8tkSS?ck411On.B?I HOK-#pee"L ( @`{w<4EI3׃:kx'C"@x,%.D4:WzYxd7<=_in[s2 g#0@ęg6~k8pN͔^pM߾CN 9sLK `OD3v<޵d̡,'@êr/Ad8P # XFPa ELdbhrNfG|<LHhϺL썪N/;[8xӪ;Ec~Vp?F`JC@SBOu;8Q([LA} XpGxS* v=s;_ۯPxT?Ƚ$2tora!Pf E'@ J͏6m6{I!6Si.^pb7q]^dU tv%=/P7m% C3#0Ph=Mup}]i#Vj_@r'˿Qmȥ>t*s~K~5g4mi:b?[b]F=):",֡BI'2nM^_P7<35I1L8Ys4u'}^ص D@.#0#08=Nnn '?i/?`ж%Z\8DA_OYrhg:Q8 / y[jjʧ}x2@&E8v?1 sz/qNiC_-7=@Z K Ց{`fNZn޵X-I=0 0#0S:xyxϦ %WS0 BZV? s) t'fc TXBraECŃG [A\(6%2-x}uFu.ܳ-7pӃPG/pͩ޸w8q@T">nc?MؑHFX/wF`< D,O#'z67 d)/]:[x(qLTTV_%gv<WBoAA2?%?ޒ @NHYhQ>WEZh0Г@OBaա/xGeOFL \`F(WlGk<"iC1$.htYF(?i|L){^%Ĕ- H'#4?0,ƇFl~x@p|r@HDMפ*Q*@e՟̊H"r5b@HFϒK'M-mtG\#`FPtxE(o?Ld[c E|3+]$Yi Hs~%34mӰg4QYep>D5"@5ߓtK4}%'e kV~x?QJ|"f !@b bo|@.$@0I`6 ߓXcV?B.#0#P*6SI;ؓuؒFΩzK=t~cC-t[qp,y!5I=k?N.\<ʏ%F ɿ$H?̜V3\@HQ/gDq^3o=X}tQ$r)A~Ng?)+$En:_wdH? 67qS`oO0#TUԼQ^ԏlq'LXo^-'+O"(A̱/ܷ.7E h]11gí_lDN\B=@.OXݗO'mR2WhEH~r9}`)¿-$DrpR%Df DYIanY|Λ'WZ #0#d*rӯxQL;ğ1o _&Ziz?v/ΊOyt{-_Ef_1X@O p,L7U$E qO7|}-$(,\tNBH3!* g@" f[xMh] q0 HsaF` ~='_ɜfm8} ']@1u8vYdz#@z)k_ >A=M1e?c˄&[TnaYG>A1;')\I ߬}B@HU@7@\1U`R$㦕(ߥSzAf7' ̇gFU >GmM8z~pOB`43x)>\]e%-QsExT߿5 ܘϤrcAx-H$R_6I?L c{LȿryH@ S3{/-F*$Er{@ $ $ar3"NuNR\̌ploF`ZFpQ];z]؅Z$5q,r(U~懣׷e(#R918%/>\Yz0 'yDo,ѺwoVnNY@#x4KSɂ#؄IQc\}-O]~kӍ 2x7^[+i}ͤuLra<ť^;VuJؑkSdwNjeo]H\gOYNabR]/{9IA8.ٖt \U"SD@vrEx _ l&̓>ߝt_5vhKe `%xAS^ H&oVcnjۗ}Xv*t0.@!@f"FcfdTKSGk #P$^ N5Nn ܔȣLo7+5j\iE~`-+dڶwN%IMQ&u&?;ޟay4``O&E@n Ⱦd8FDjK~won_,֤b,L,;q?EE؟b!.4pF_,lcΕuܶ~{kSa6.@m gdĎ1v}d>>7m1F@847yKCǍg7F}N6x 1<9"nwR:\0;ڴiH H#|$`ǂnK]/"FCCJvp΁mHB RGF'?}$2`tAu4]ۧ{[\)$ 7#^qkHzwn_DЉ]7~T_.' +y0ͦ׎[u6) z 7s||zF`nP;ӃcgvNt:y׷*yN:&>X|1X/3ho Xj$C'&OҦp;K~c=0P^VX@4[SY ǡxg=亮+W/Un  erlyka݇?\4dV\B&<=*:ɭ0]BE@f?ş?n򏯈~c~+@B@+{/rnh4J*#?jϬŮFSsC<*`7@ P7|)cXwb]?y+m]a^U>@^`>k o<( O{u xAX_V8>g8Sȵ&!6͎|)ƫO3&Tue`(Vv6diq+.iE" ј&F{).@FZm3W?Gɍ7~oq":ʟF@*4Ο67@ tl3{ TMrw~]ٴH8JUCf h+  `t6w,ul.C{|$1Ah2aoҕU lE{zer:ٯ=̀ ?bcmsh$A`c*W4hPv}_ӽ^W+?_nzV!A (mk +ýiG!֏cXiXx^5_3;7&Aq^TD + ar7uq!9ET]3XoIWZj6Ms?#FBJ 睏,>g!WLW/^ËfD ɝ M e56HQrF -{'.M_}+cO[W;E 0ԋ^lQFr P3zFOY1 onwoX%z^|ȅzq^J* "WixwTȏez=~k,Yk ;.Q4yX(| }l }G#0d& P ?dt$A`~*W4h@c%y9%M!Cҷ;s;y0`j Ѡ&&o) 2zb`vAh+{[Z7{ @\ 9. 0wޖecAtW=)\kΓ$"ZN4eUOy) ߑs~:W>U;{YL9+ #8-c] 0`! ցƍn?.Kƭ?l֮ϭ1FN~K<X^H @ʁԞ.'zrNG^"O={/6]ucMQ5MmA@E+]NG}C'_xf,sjğ/H" $4Ӵ4qAЯl4W޽?V>K(5C@vk2[Xag?JlLY]E@\}z܍+ .P(GR75VEH] k6`U 5PONIj |iT7*bOc;kӆc W:Wo{d(Ft^44ҧA@X%?uYv'"uׅhX@Y) i_3hTԾz[/;fSA2 RA@'_X_w;5^[`6ro0_!@mUS=G O@|!M,CAMy$- B I(~EÉ3^F+_ꟵU ȃK=0n1f(2ڇ) 5F|YڗNZESם|>Kwzs( 4)3YY%P%Г͍}= ?F$4:5_ Ŭ5K/_4 ms_ j=ť."A\-"}X='a;4 UdO!ò?{0Vg`e! V<{܍!PNH(i4CSi?yUV ̄YIk )(HE-;=Ɓޟ] ;{nX4MHWzpce,4912.IbJ{29K*cxb0?7&mH% !ż=pdGOepVOE`mџX)7(4Fѭp?'7U!<^ykziNcr ?)W]Qe/Tjr:kY͟?} 0A"%bczS;^"Hs @ĿZ_g3to,Pp?7 ʪu~y3DwAey&+}67;<n0LeQ|0dȬp[X,IX<Dx˝/Cʍ,Ja0C/~3;1R;?S@R" -41DSH.Q4PʕC77/yCH3hꈺҠc$Ų>B!_q{͐صfP@zfuۧ0ZKIcߤ'i ,󧩿># D4,?#%g샤Ù% (phn4H9;\'mϳ^ ij>>IC};e͵A iX@r YWJV&gΣ>tܴ ndaE@}@Q ,+Hfnѡ5CCXOq(?>!)}NJbÉ!Uh" fh/wsGɞړZ)gAZ'vdeqkI@C pC|yi@cˍ'7Sms_8xJ{u?:zm~ 徖,/pF4ڰQ 0>TDW+¿?Cfwo`3"RA`>a_d.PK=LJrvGuw0̍%(M>E#[ǹ+W+W3_}O9eOȤlw[`#F=L@IDAT1 (ne"'TNn\k\G C_lrO'&|.06r4, Hluv^~zsq6V-ZmG;\A@?yvkHZzt y3U*]>'n OyUPwI~i{~{$9Y:$q@~y@FLJNLՓF/~q&') t%)VS/(aћԝ{C@eLa̿w69XuۺOG"JQI$ `| (ˇ?bgXLMPVm) S[XW^2x"#;2|{Gs)BC!Δ "?!" %!@cyƕfnYގ/Yw=ԘUx{HxP$ДWS`2қUR֬/@JQOyZo޹j}gRT 뚖>򤂀 ,oj~gD5Gm[Ͳ(FI!>D uu=4Oi$ǒtD=}eG?>H?DDZIG@ /Q؆vG @Z3_21jȟx.>Kjt0H6|P|L C^M@ET+G^\}juϺ[Gkv؞iY2<< ,`7SղGO=7'NtK9ŰٚſJj=Δ~vS1)lk-tn,YYT@ @8AlO7~zx3UV 7~[%8K@!#u&K fx w@1yԫ>K'vu&2kӹQӮuSd}\m]SZ:߯B#&WyGoz5{*ٶfx7!3BЃ՟-LYc8Ӣ#W$,I,ɗ^1Gb%DF#(@QbߛKo>5o u\e>Tڢᴴ&qͱ膡LiN$ UӔr%KU!?vz{zn|1X%  0 {r'{ ?tHLs<3Xcd'-bݚ.|bOQi_M6RRiY$fpJxIy'4޿C: !(yM8,8(IX`~;y@#=6n i Pd).٦ *Z6rWs79R$I@5b5/U ۈ{x24~`7|sn(ET΋W7Ȃ peڏS#O>ey3YEéL(RAX?\mY /1LX^F)So>2%Tծtl̇Ą$ vgHI>Lz#7܀KU >[ykoG?]ZƖu(8N3 {1R$JMQpIZ8L )'Czۛ6[kC|1K^3$  |p\o+g=|ŖToxNGLR x%b%[;ļu쓉^L_o@U ޡW3ovr2>2?2[Ic;,lye(ͧh>q wA^x1+O/$G;>uƽ Wčes"wS8y});%g, AET{PxwHӡgխnX|MUO,B K NQ}ϰG{ݮvmK[Rݾ]tH?<3\MkObr-ɽ/@XSz+glwvS߉ S;M׼J=p%@H" b(arKJb@٣ip 0{Td/:{F91,XujMk:׷JYW@A@hjFN{;;K'%+ɽ4H7#97w,Pچ % ⯓M/H\?/ogK/L o?)s>sCxW9\ٳ  P^%KRd, d@IX~G˔+G*>O-gԕ~Kr㚛@ɪB2rsA4)1xbdJpp$o~{#u\qk9V)ng4r+A{|>㇩ȼXD!#F n?=(Vgsø#G l7J(<$#QG{J~1}B}rI5R"yBTl(r#f8Gd9IYZ}ݐZ~cn]ǖ` C ʀR=E~zDj<~l`hh$ޭUg}b]|K57~f Dk?X\d">8݇ O|5ā2HN#Jft\y ː@aan 9H|ښ9XX^oF玃Q"cdEC ยyiOvv{o ?LֆEQ%-X() kiRMRNY}3G8P7iR5RGzcͮn٪iYjߖ]۾)4$PƐ%A@AIDGGޱ'O=VM2j1l7HWL4p9bOnV׏1AcA;O"u_$Gٟ-[H)Posk L'v\sDH[.^<Dx˝ ) qgF59c8~;df?G#lߩ= y%o"2$PZfjAIxϔ'(+'F_F  j yC͙kUMRkZI1|A `7ޯ|j穪xj4?2<(}#GIR-0)SnexU%B1YD%HZ=OcEFO.{OZ*TQP?d5dn ӑqB I+Q/o1ܑ璕8 %;*ȿw'G7<7]+l/q$†3k@!WYj()X0>fJ<@0ٱC+!o{ڎk̪ζހ?e A`!8#{UPz(~BzñJHI3Ѷګşc'ҏЈNGH0sXJ `9#dSBBdŤ<ޟ?9Ε$XDb?Cᎇ58dz"9uB'LR-\@  8I <lWyMI1`۪2qM)iiJj9rztWKJlKmVL1푫Wk`4L!Zħzxi@#@,W)鑱H/TǺ8 PuLvjM&k9/A=\i6_o XJŦ2T`Ze (Ԭi&o\25Zdn7,.uT}J(sԬ4 Y"Wۏ6"U %MYt9~{|:Qu _qf>?8#U@$ Y.2w*XvgT,0|{;C= {6!oOD۴mX$}Y졚$LMձ>XҤW@< 9KLt%AEעL;9zA"Uɿ6lWf5کGZO( bpxSEg JI]XRxz؎gxqpT{9:T6b>XAAA+p7k_>'Q`@Y*1XAʃ*&I&! IȪ 05v^N;#,qY%@ż]}_-rwKcX#CEf)N@E)*J2cDždDՉ SRvH߳L1p5m덐 t6 )J˿6>R!H Sa#Gc[gGhrY׌fDsp5Ԯ At}57DiZUjhE@FJ{̾K_~kّP o:d+$]A1(p *>˒A` S @@A Af3+ (P8/ y>s@/Ts$Фm3 jSYK6yWy N@bEX d\-x0:g{gDboˬhm^}-HM0|e!v>\BPX~XUHTvD#oҔ}㹞̩vV~(BzKC#fc^PnFD97'OcO)(ӹi: t.Qsfҏ= {A.񵎓$ `j\d 0ܹpg S+֑;CtD<Ƥ'<5ohNMH^۽8Чde%C P)$ɂ290.=Ty+vݏS@ LWuZ.iB\ æ^R(.VK!P! ?[VͥK¸-čdz,7|"yvho(y0ӭ?xOGy)뇛F׉eLj(zhH[Xᵃ/gp ãwQLQBwDzC$ t`:td piA1Yq'q@(<$Dك?c߽V#*:;J3 t]U'N@j2@4SI`0Ib^ *Uc%^KCb#gJO[fDIQ dI?~( Jϙ% @^8A;.tJ輸SB^w+pEG @5Ԭ7x4q?U7> ;D*i%"@ݙtCUZV5(+  (5I·WC2tbHKU*G,R-cVm+i=^=TsWaKu2"f(rQJ嬑/Xȱ|Hx{uC#~Z*ڸ~&3k=xJLM,K^s:Sؒu>N{+O Z&Y[_2K Ls yNN/XVl]b@ɞ|!8QP5MS kuײƸY8qHZ@ஒ"h tAu"()2"`9A-6=GS/(<[j]ޱSGqL%h+TpmUZ+MݧWW=E)ry9>|o6y󗬒9lTRz6's-Z]>ט^uFՋF⠏qHh*.omAXtwE{K;cQg?Cӽ9AvJ002,C1WzCI7p!˂#wd;,.x7E@lOMoxwszgf'auu arRGʠ P DMg,mdII|[ pdfӶb%~|_@g%oDMk[ִo2[ֶ*i؀G R  >mmQ!O R9ZvQ}@l`Dop`8ynf0?hp7ԒYil?i轈cdWzS9 h{)~ogo?z&5^o2"d3gmDZHݥvI` *\!`"(JsG(ǡ[)퟼1ߎ|OGwp-4oBJ"ԺHq^cJXIS@(t*gsAsLjvK 89NVv"L{dH)pֺ JcT(m. ! x8kG=5r~!Ur㧙JvRRJQ*%-_ȤcޱCb%Du&YDuWO~R@~C~DѶyOtH.}T)cўҫo>ڡA!uZ]X.g)?%>e p`ᰖ;sB99Cve2p|M @}-M㉶{MW~5koYK}I5T!i*4 fH!xx<pce&0Լj3 #ӄH!LP),ŧGsm㫛Wmt2`غfTɝCċhVtzx휬l?@܃H>(L.WJC )r/URh/;;aƎѸS/D5Lߧ4[tM~ý?J?DWLF=pq ۊ)'b.i9=JOV|UzN-hd>~rC 0`.єk q:wv\뜱 I %< F.Y1Ghd aj:@JGP)!a (N$))R'9}Y>lBEe`,{20>Ԃz<Վ:[7ۛ7mM`0DW(MJR hLڮNe. c?WiD}H~,岇Jv6Qh7Fǣ O5HTU^;Nk3rKR~"pDj E-|>\ 6yzd?J~[`2acL|R I\! BR#LwZ\scE!7a e1i#_ ؝~[ |:@'I@ֽH+M+KJ6YVAb͈c!yU H>me/Ci{8q;:N[odՍU grوZE%rH?Cԩ~(FHZ~P=(3OyﳩwNBZh*gz=lw+ a9"p!pd5gW Й1 ې):?o`yHOSM_X}#䕊Ns$ S"!ZHwD?Z\V5em#2#sabV⭽֞)Mu\{JKZ9aFC-Q?!2TnPԈph҅/? |!%O_nb+6Ńr)Onpa<9PMbn<͗ak'SPҋH3Gv:fQz}['@*4rwT_*釻忷ljO 40 |J*vgǰ (IQ%r-A`z3CǝJtA2JVsCh1}#Hxݡ/w}<amp$LTjO}1իT2d3Z\ LsEޅYH˝|F99Z8/i4+HF3MեJs Ps0E5MBAPQIq^:NIW=Z0\MXB&K%X!.J,g~ l*3\>翓G+yy.Z$0Gu-P4kJ98Ј/Ip!@cQ/;/G̞5?כP!L$%ȿɲ&IQrMApٌC'ew1q x|!5ө  ĵ>O[HnoLRPMCe_5^2+ MʀL"P0 y>FA 'QcEHz8ښ<l " "U UH B?5݇ ]j0:+'.@.^t_vDT l.erb*;^IeG=ܰΏp0]Zv⌫a~5dsEw_N~&"c1Bq:Bs_TOvcׯM8Ly?cXy| Z$tJrUr]A@GV](C) ;|=ODc  {sM!#()Hf|Qdh@A"Dsu}Ͽ4iH6`6fD6WjL:U91FVibk0׆Yc-玏D=PSCĵ\ڢ (+<?qsiv)~wPNApJIC^:#j(L16[ 0K[P) veO#,,.=AV??sҍ#J9E@)r1A`;=tXwkёsgnEEMWsߎ3-D /tDVj] ?f_x,Zb R4%w?V7xTT+G@<C 0W(DŽ%} !7˟o|ERv>\g z95Mz0&3\<H!D`-B^<=ο%nh3S ;9OğBQ9'fvZ?T4 9_zٯxsUz&< La(p I `@[ 3 )3 ~d&)F"kOG@7<-Q:D= E^y:5TVTR<̹;OX@c}~ h4뾏 OX+Ӑʛ~73݅lP/7Gfҏ%8rEI X4HB$w86(xF!ӽSS>?y'~y#0 $yoeAL7HqPd[HS;\yg'ۻȅAи}L$ и-R:u^,\DjzwG J5Hh2߭(YEg$A@XD`[ u 3}ra lc%JN{'oB.M5ngںOhj71@ B@s$aY&W*Vh|:Y PY#PTB)@"'[R I)P&AvSK('C=|xtվJcR;nRHu}rwD,] !fDz_Hwy 촯Vr;oez&Lݟa?+ pcA 4 ApwP萹Ι Ρ88TLC{3JևC_)\;A@!Ut(ibiTMrG+J! %EQm8/JIe u]ѧ: ?ucFCLkHmS:uNq񉖜y#DuM%Ǔ>+{IJz[A7P" 7gwƲ_ye ,x˝A݉p  lcp_@۪ހj;(H}$P !#q뮼*OV ؕR.ΰ<(CAPiJm:B 8)}E|SXD)?uAzOS }W3r*_;T*Jo~:y ĊyBCL\Lٸs?ކC}=& 4h!! !z?+"i_J+vI7׽-t^c~\ EJ АPʌBQPe((`e)`ȵi1'ܳ'~ ju_x_^ DݨYkDwDw62{)S+[+k}ӢIvB' y=ITJTWMt̵%zX(x;[%&I ШF2\pg /Jt]Ι;sl"Jp:lbZZ&nh'atxzNU%(pI@#!@wĩAD @՝R`(Ab IP*rS-dA x)A!S'PNx>>ݙ^0AUZVJÀ51X}?B΅k7v.7MLK@)uTߍ?#V>'k2!u2cX/תm аa?< Pt!1c52x~ p"@C*E/'#p~鳁zH@Ij\p4:A vP} /sC 8=,V`JR R5%.\O)O|ȼm-PE {&e D\A]2H?}ڥڬ< s?_zaO?\ K(.){<؎Eѥ&"ŋNB2,Mv:yxp c:C'Vv,NRse|mD' =nh4D)ji eXv;8%/X.M0ʭtz?9;w<1l bRԯs5~52 Vq>JI Dp؂%ΝKtn/tc;8mPKA$\dW&coNHw>C*sEH+,!u5]8@~ RlZH)!؆c Da]G|X4hQhT:U:[>5'm<ݹg$A`!<[iSOڞ9s)M3%dـ nyu꼭&lį"$\9 8ԃ##sp@.yM5UVJk MΏFVImfK4mIJD λOR0 5IѴXvvc_ "6xo(X|~j!~2IDATM-N&k7I),y@R>}dg/ǬĨeBS{ǂ_Jx 0?l>d&H(wfy|d|d&(Y1%dAVK\KWp~ݟܷ&H`儞$A`*\\p +:m9ngfn4!4c9~ryw TҰo|jwzrv|\4}/) c`7(g%|%I X._RC L=x%+ p+.>HH忰:oK]t1tD@IA@f@4rܓ^ʼNsG䝉?}&@Dzא$ Q,*#̀yVG+&{pl %RUk-(;0E _Dv  HO|7C۳;ϖ-%q,=31Ϥ | I L2Z4I[V8V܆ZDVwl4n/=%FPɊ  E-3/y=DbH@ztV{cI?[%H6K劀(뗕fF`(Jx>2_ok7_@՛($K +&/l?N-ag(|0@g3G eϙ|_$Q,/,'̌ۢ!nDz$A@XA`}lyUA`3w[+[(0~T)J[ͿkyuwH{B(f.[A` "Qi朑{:ЩRL7J} ؆c δ*IV"X_]Y&(ܣd?J %+Xw,RR"߱fot\*JU/KVA@z?ë*4 ?Vyܮ3mRV{&LAʏmYARWyBA`A-7$LٲrO=q,X !XU3ow\}>pm[tC]iˊ  hhGJ!g!WgJoݕ5]>5HVMLe?J&nk?+ 1)יxA@X`~Xy-A`p+ ȸ%T8֭XPZ|%:_;ּwM|*\Uh\NA@'ӉS~%S88SzЎ`R \ G2mgEH?&B I p1"F<{Y Jގ݊__ɥ̪ o;\}p MfD \lA@X_3< Ԙޙ#gKٟMV ):LQ3Gc8}>JAbDp1&EGPNPx)[ኬ6)vݳ]Xٻ-ڦo$   &ܯض! cŽ_>J8MkQ􋗓ĝ-LQ):["bA`! u9Dg& p{8@ DKUvQxxoi^clRUO*Q@QlA@ACm||jT3/}3oUT8wM& n?[Yׇ%("<{V?/W(̂hVj![)Qpµw+.  Ԏ" IA@R`4zb:]:3W($he{,x,g?Yۙ:nOA@Qԇ%F" 5nE@Ʉ m(R qyC 4O^3YA@SHW⿇\_|g4k=~ .ȥ0in?~.䟭? ו$!A`B+?YP@Q^|<+pu= gB.ixyoC)Z\A@Fz G=pYgO)xh{fzހj^6YAYBvg&Lxv'HH)(. 69I@MؙK"?ocP|Vkcݱ }aRJkdiS-^XG=SQ c}CgJ{!șEcσ~rs&(݄= Kszx2%  pY`A`:A9–DZ"A.V`#,`Dl},56Dk%7ΰ($A@Vp󇵟fgxiOso+d؇cq.g!$A@D0?UAbQL`VdJ&vny8ܵ1i:DNudEA`"PVJOUzFzJy=7r㾐'dT\O2%wLO&]13A ( pu,3w['+1p+\&=TXPB]WDךn0n&MSPH` ,9kUMҕ̾{Mϥ+{)FzNSs rv2 `_X.I9E@s \LfOgqx ΓZk_H (r1WU[ Pa"dEGZ}jV&7/y,Խ\A9Gqe7g&`ҏR? IQ,rWA@8[2[QvV~yXrI\G]ŶuzG"DEJ.!US|t4sdQA vR͗rtjOKY kQ-^?w lw`%<&t/c] (^ &(AA93g?rfE] J%;w 5$8H4@x;HA@3w@O|sc^L6~<%[Qb?JP0sp&\&I ,,XXn PP"uĞd/JVhԉڤ (jotW^4W2ntVA@@ ^U*vZcd>ZtW1+5dmg%[݊V0|- IQ,*rsA@&:T(X5_ȥTzC~(|of!mfxL,ApגeA@+AJcOU=s w;[.r$ҏJs&LAc?J&q >oʟ:k/lY6T*)* @&Jc `cxyli=9{CmOcyp!@ M/3=L{SƷ X0F`?$X^y~ѯv{//";8:4Z//RO=Dc@Ws\X#`mG O`D@]:&DIcB@W jƣHKyѢTB: /Tgo>:_)tPk1FܟGgk5y?ෑ/PG~j}g_Ɗ#`C w|F:FSB@ im:FqsVPFB|?տkL౒;26FMR_*v6Agm;IJzKrNIi^_f[fb88pjo/1#ȿ"qF@ViHyh|:JXՕ`sOԿ35[V+ij0$?9}kW~v^{MAQ9/><ɾD".G?me_ٌpY0'N#0>JP+@[1P?&؞Mc }!ǵFk 0gt+\k9sq~ r$ϻ?~ÍwHYjv[H[G$GA{I3Gm1Fs8pR #`A@"JPk9H?<Ԗ}F9/i2 'J5,͗u+=˥raGT؏KF}HIy{O?{ko_bIڝA ڏ=ӈSwV]D}Վ_fjS[0$Nܓ1%#W@`;<Ҧ|MИ,UbCdŧ^xq7}j1FI WQ~ӾeNN;il'=~/;&O7:~ّ5"g9~UlT[06Nן9M@L ЯDJ?L!SvXåA}T7KM5\??@e<[LeB`_0#_$cIR~ʕu~ڝVZOژDϱ~PO1e$"ԲEE5E^q@b/pྼFiu9ɻȽl lB@3V<%T(푂o%pɹr1U$6s WAրopB`$0=(QB{kww~WtRws6Ĕږ1_[M;Q/He}q?~pc\0FG +`u6/l"`TY^H _c߀|y o쀩^l^|ꥉo̝>S(>],Fܗ-$|E ?i|{3[|uݾߖ͝j`?4eH'O%GŸWVbZs Kk0)N`>RI)$J Ps&g (1fxV焙/rt@3Ss|y\-Lc/N|g̜)?[I2@!?FpPƴ~Lῴ{jy':f ml,1/#?PBO;FG?I}\/6&V0F|_`a#pH)./c@^Z}W)ՂJIy,>T=Է&|7:HLH0]aN$88u`U;;o_V+nRZK0F{EO;w$~+)1w~0Fj#`S I=5f8lx0%X>\xdl[*3 !eaVFH$6V}itv[+Xۿ`=\G#!)&&$^D_~ǤXp#`YY#p8"$Ҵ#g2 PA[WeT/$ 6[|ƒթb^ZOWstk 6Nk/Yo'Yi 1m-ʜ֏~dz_JEi'O-/;Nd_u.#`""F Q%D ՇZҦ<Ҙw|@D"̝48Wksb7/?Pؘ._7ex _?8&nfvƏ8ѳ0uzݏ?|z V1꿼rc>.=F./-N"O[^d?^D_q),[0Fpu8#`!Db.[ĝ$_Z?;+rPli4I# f$8>Q*}09WZ6pT^=~N  m7@mԇQBniN;H>Z1^Տ:#N7Vz>2T0WMiǃ<{ȓ.heŇfb0nj #`@$Ii+E8ÃsЖ6c>Ӥ6/>\]gA`G8CF _=iRY#p/"7V.`[g˟}6 rNm^/-]&}-_oT$HIُ6}"ұʌM;#ڨ#`D ۉc#`G s"EmXVKPM6GᲁtًsՅti(.b9j?^;?sf >_L\:$ϑ/Gdw?!냼sN+)_ڻrW_+%L_Yma; fpTkK?o.I!x$ߑh=""ye1&C;/Z0FN!B1FI:mͶS e3f')Òh,^.L͗`O3 I3g+gxv{ kL)@3ҤIg BAxo<|N/as>}~?ef?s ;/!=XˆKݕ^T>U|$f}s C$?JDO[1)wFe,F#pp.S#`:e;:Dc>clR Wi߼7=f zXL$e)P2X*%X㼀¹j J?E\yFtK nָg@K?|S0U/_|Age{:/cj2^wGݵ}.f} ԣHEEYG;KYVx( Kk0''NmE#`F &eT>x%XїZ 蓭YszȑTF }.'+X20?X^T#gs g+I$ Πnӯar p9h ]A{C_~ߙ;Xh1vN+Ywذo,]-c:1XlLMBˎd_F>b9Ž2m0F@87ŗdryV gl%bYvL~s=m $ѧkD,V1[z g,Uk9.4&Kg.Tg*3x[ f ̀T*Y<Hrfx#}u;05$"qKz^a߯u_JJOx*H\f}ױN#K}Y bJz}1+o;x@ʏoHeKgGUg;٪cLيC_k߇#`N6N3F"EE%bƸ|:X>6 3X=yԛH[u^g²lͲ#`N!N›K6F =MMbClB@110bCiVn5 Hg pgN?PÛ 氤`2I0]&A͙rsrF^Wj:7[5H&w{Ġ2^I;U{Fqxn]g I<;ħzAF|]ޠ_`H}Sw0jV򿅽!6}d Yoo$=5R{$)$w%{Wygeɹl~#c<ֱ>Xb0N#7#p^dZ$|*SgIY>8޹h"=,ݩ:=&)L@!XfP:5=_nN ,R)$ &A4 rD2 Vs9]'JTE9=JB5xAm1=G -ד o.a]>F8/( -ܓ) }i/zUZvW jQ}~0F8p`<#` MB#g;Y/ITdi\dIlt:tJHqI (-0HN~>ٺj~(GbN_,GG|jcem;?m0Fg8pp\#`٦<$m2m-/~y@Fig3S ͺ) `#L0_.)KW;C_ZAY<_;+d]dpÿ;^uR1ySg:}ea{c;/{3~1lt;/}#`0a0F#@$!eI)y ++FME6SwUs:@tw|WYUu$#egdj/Ilj0FHAna0FFD.T#Kmr"Tu69_eŒ~qjX?(Kgm}V;QOvVgI~T<Ť?F#`B q0FېPHi|˧25I4EZmFP=lŖ/jKdG=fD@Qi~<[>~weS"SEYmg5+bSSbY>~/e#`a8pB7F$DDE}Dzi$yu]S}XV9bYQӦMƧl,$QT/QӎƲlXGiU!Zu+f>em,F#`Gˍ0FD"R#G#qDeک>jGlQ̬9痟BB}dˬ-9ԊlC~џ.cSmhgX/[է#`q qF#pȦQ&H2`HGٱ?_霣y{3sGȟ;(=/eұ=}ң{ӎK~l]vVmm#`%%#`n<#נQTv<.hGBه@E?m mv򱞟;ێ1V^y ?[MYKϞ%lm˪HUw՗tg~ԔX-Ժ:0F;wr#`A KT&RYaDuNvyUwi?W: cg%ϗm0Fێb#`<"EID_t/.Odǘy|]WNqlʗl#_>VAZqi#?O?d G]#`0'Nͭ#`"f^D.:l#_˧JM_},|1쨣cEuwT[~e5d},Gѧ~r}#dV~/zli0FJ8m0G@ h3 rElK ;[Dz#`=3F1$ͳeyTQT/}y& t>j~X:vǩu͊yP9j~&zj1v}6b0FE #`F:a$bh+>맺tks/[-<>#`0F 'r@#`- p ~PAzb̼G;nT<0F[DRX\+IENDB`ic11 PNG  IHDR szzsRGB pHYs%%IR$ IDATX W l\Wι{<3s8vI4iD)m,+hhW jEU< ] "ڴ4*mZ ѸIl'8={qp8Nđϵ?y'#Bk as*0}.J;<8!/sf9!A$SEC|"ְ0! *boڔM߶ A/!QY?[Zf*mK(/A86w{/x[ӄZ6j濙+(Na򕪑wyQDXwVL³?@6WzE}a_]nä<^LX&o^O@sqY~Ή-]C3aY>v/ H/?'#я[l=tMd^b%BH, "|"oMγ/#T~TkJݾO vgklKߧ3N"C=j] z%RKgNCCߗg$mCmUQ_Ė?b(: _7txP\`Wϓ\֬f;cR -[KKyT38hj!"L?eMw aJ %qۊ_b0$s8y9\SØ@ICZLIU_" 9􎸻oz 3J&*ӂU[B7Cܿ Es ׬o MJ }5d-7n6`=GZ hy6&Jt`> .RWWDx'#">~M]&@Cwarmq=.*)tGYţDru]},{7sc< T* dA66܆}e#MtNnzCYͣ÷f4%feYx \1U|2XGq/Mϖh$!WiuZG)ɲL6-QLcۑj]DdvA3RL UDVb44pF{+l }ٰeڈX\g<;b@`3wK_yN}{W^FB^Vh4ő{DpNeߍNJ ˲:j܆^}v4! !n[oǂ0\,пZ{6cB~K'3|n:dp6l! ݦYFA5M8h ka1+aU(VU@*-њ!yYR Euqe'z:sMlj/6fPSYgnz i_lDZX+"!FZ1vH5bVn}s3MhhtnN OP"N@|y)Exo5=_ye(I\PuhbãS*yWٳepc.{0"tw!SƱX9νR^N2.D<G)ekE?p j4fe6E<S\ QuOg*)|7,vڊ(/]4(QX Xtc}( kYm BGPe'/ +˧8pqLv.n>.ؑDb8 wr?kJQH8v7d7o˚r[G"HTI1JA^*c2/D_ƿHA.Y{hfԳdS~*T(m=R=ymId/xߪ߰l>{Ȧ8^AǴGr=ؒ|T܂~j dMvʌ!3\eg?9ON~F-}]kHMM$%?w#R:rg93Z@5냗wNCnr-K <ڻe '<{3Zj?<>_UQʚPWj/@33G>I[οYqCCf x8G@b5(K7&sof~* [{Ѥy ֕+@ss8ƭ} ,F`3ornL\͏WJPDzp]r˅~(JiIENDB`ic12 ߉PNG  IHDR@@iqsRGB pHYs%%IR$ |IDATx{]y=;4T0$!i VMqql/xx&&6:0BHBB]zs5A$ٳΝsg#|+Ͷ$(S(P"Q -y^DY h$ $E`2Ds[QYv`A;p&43Mmr/H]N4LE# 2B ϋ`ЀrkzBy~Y|S9+`Mpdwȹ3DlYԓTdچ襁j#21l>Kt+VQOPN FY]!*5 c:r9b#w?79X^v 8Aꉕ8Axnn(QGeEd.G{$Df7!pO蜚-CG~-fKro GU7Vo>-}0'ٸQ}]nG5`!l|ڸ+-*3'ĻUX:Zj\*si bKx9cI%*rA0'm?:v@`ۘ?| }"1;ހRqF9Refk88xٟyE1(AB'SZouNnV'okw1U&"\ը *wkyڠ}A_핫a͍'_c.{^15eHrIA&4ܔM.k[tQ eX0A_0DmXZTo^=}[.w|l8zno+i+b )1WZjeہ_^6|cJVEyVA8.,iZ%#Uk ;Gtj% =[HwNk#goPPJ|4,թ5.UT6<5/:3piJ1hO1^'p FjμvЅP=H(?K/jlYRO 0\kL9GC !xѺ5=9+R|t+XSR;aP8Oͫ;65s6xJoeO=5jUsJOVo5\5sV \pHtHEu =xBeLxfuWh,49D|}& ֯!Ŏ}?tUbԑٝjcu9|l`ÑI1[{\A3GB[j|GF2b)NblɋϚc`G3(_\&MMQԷOlo`^x|_ =_ a+Y]U pe bǑ/ճ) 2M٫[n`^fϝ:xjy(+6PZ J U81U: e5I ~?xxZ 8T]OQ.QS_/~nMIQ% .1Wԩ痩/Q4B%Ƣta) qpر?^OxqS5v{U騴c^AT|eSM1/_{'Լazp*y+vJ!agf_hצ5p̌g*X2'WӤO;Pj3 =࢈£aHMP{l ).Hjҥ$SͺhZ|$*T)7Pj`6#v)=^"* Æ& :8{:s@lvx'-]| ϝCX#[eizDI"垠O -YD8#4^I9QH(@ Ҳ'T7 4B~HnGlZ5x.99"m+E?[Ekj5wlj>,!fkd#\,>O ªOxbӓc[Fw~=/wNndT)Ho['5C:Z4o,~d^ALn}xg ^pi(XQ'uɊr?,hE{cC4LxWs>)l^ȕr78B SAꣃ3zQ0y* %%M/>\Qj\1o8(SA,SEeݵN^77seADQ qDZ%g7>̂}W]*X}7X༗Yϛ]E쳩%*%*i%g̾K؏^Pn6=.ؓX4Kv!%wvgZGӯYyڃk 65ƱC h 4})2C}cXZ#5 Nk2YtYH7Gn@v HYVX6Usc\@Og '&PDLY&*a!(dvt:qc= H7/QoY WUC[H)"\w:Th's)u]E~[we Ѩ#Vͯ%Q,n^`_2?Y/Xe!M6`EX=,@r+=_A{:`v[MhkHCRHa<uFV.0'TE죌D>0/0 ҹ1rK$!M09vlhHQ2ԸtcZuKo)+<5V=9IfB=S``=81 8@8( F[kx8-%*K(t!q72pԂO8(d,oZDW '9UrdfExTZTxfJ1`;G,xjU4i_UA2G.'y!-^0ޝxn],Ȧ4r8"62$hfΏX;@%8*1-!UTw#93;ccgKD2@R͙ 2cb67gB¦A&'\hL Y`e0smJZ>~L >(O9`g pzӥ>WDE@>u|wcz_!d@T]SX*3b:8+`a],T1).:@P]ڢkCLcC';맀߇`MeXf?lNwnli"[X%aw2𬗝?>f ܶyvi9gZ>w袇¡JGC0B:.2 *mFߡx"[H,C{7_;ѯ )GFa l.6#L CeN9NQ; QcR/?#GfnTUϾ~UP{zBU6*K&QŻ PKKv>ġ)J;#wQ-vV9BލUm*^8{rV͹0G(<9pB4Gu4\Bwnv?E7J S,҄{bXkUG\^qK hX77M$۽y.|Iߙ`!px17|,\#FK~֟kou%a1eJno'h|qe]Ǯ1O4^= T;#X;0+UazØ*|`M5@YmuurbGu~)f.~tgC_}F KґeH[7vJZ7"yXcnz4x0E#DXp[rYԵKJHF=أ\5N7WiabM.zm+ІWhvv9kH՞tMqomyjMx7W.1r*-7V6|Kln{˶|8K-#ϲ4t& \s|U^8PMUaW#v_wp47>6O 1Db8Q! R * g4 ܊~o,B d~tZE+Cy,:T?9?τy󋟸&xUC= s:=Bss<l>*Gqlq 5paQ.dI{U+eFQ69s ;6lƚm67oVWڕ؟LqRE??8"ivlaSך0GOL{44MpY)T Kajh7lڞ2Q+Edrc_l==|I;&_[%2ń#h6BQEroxmv]ray՚ Y%'5BO&qvZ Q5L4k<KN)iYEԔC[v` LYn1lWRU/6 U+Hv)IXlXYc cW(Kw?w%t}ٰ53_~#b>.B,q8Pny^dy}-28lS=c#C%ZqM 8ڪ;nwRϢC%Ď !7ct`/ 3YbD.EBmi {;-?WuFlޞN&Ƀv.{o&ވתZaa ^E@eQM;ezѿ1s`[$4 }΋+`SK "3*_vs{W;$P 4<:Lv)}bzdV mQ!KQeA!g!0"JRBBKK=UUP =O=ݷ'2Xp Bq:"2\ o~%+o}\x$7U X_HDҎJ5PL9; 3<<&?h$Js._5& :2p^{$p'kPKUzlx6IIQl9uޢKpv5 l߰JbE`KlPSTrPG9'jo!z=; ly!Oj(qAg8ux>,\|~pE;_~!1"%5vW4ϼ 6(L1o\q| pa(N4ttw[bӎ7ؒ5W22Qk볌ď3:T>3x&@uUYRS]Q`|AX>0; 9s6G_z`tH Ax^c!/e}l6'6sͯݝ-P$RB(BXikx?!DJOqYtZ*[W,iөe[MIENDB`il32 ] ~}}a~dP\[[~}}~dP\[[~}}˘{eP\[[~}}j⻔}_Q\[[~}}Ă鬚\E_`_}}zӍWVWX}{~ߋ2 wӋtϏPց/-Յ\t󙢥%򛠥 ΒDݐЍ 钸bZ=ɐ㞝_뙡so㞧| Ҋ s} 원z 단[~ 󺄔 {VX݂ ۈ|܂~,=}ހ{nWl|镇o5 ʌz΋eq$L{^s{R'30t{x࡚m%?,+%Nd  {uؕ`e7 jsu^Եkt<0M 8(xvqg>DN GN_ne<9+CM ~G#]J2QURNILC82766CKROPRWD)Af>dW5-MVOJB82766C KROSP*EX ~62XQB62766CKQRP7~Ta9WU5-8CCBKUO0/WO4545CBCSR:2]Ћ?3?ZU%GDMW-)c1KKX-njRgE_ZdNT=T$#DMM7A^=(7)]5@S,KG: (T,I>V+U>V&U*t =P8K+}R@T/c2M&^>5I-<(Y*5I2Rg2DGO?y7LAc2M"?T>DDP4n-PE L42:4D CB&O 'A./Aڂ ';@ۂE"'?g>13ހ=15-4?C(Ct J$A';kB<e:7 *H!oF9"M}sZ!L!$$5L~s'O'## +,7C@2&&#)+8) /)$'(810016&"! (")+is325lT\ݜٳhKafLޚʅ;ϊLJ_{k{u鑯wʙҭxω}hl݊|VjeDȀ6Bn퓏O@^޾t'Ccjuʔz\X6 CdNdbc{mqM:c7 5̄cm{Vry\FsȼгʾղҾ³ӷڻ◕ݼsɮDӸ:Mέ赱ܭhMrן+%P|ϼxmB%P}^{]GD%5KKPWN12QJ05PT<25KJVF5yQlm2M>.7JS4@:7>/OAOcW`:+G1s}.7+x1@l'# kCQ$l|I@;bi%(F\7' c& Q3kdDܬ'*+(PUVC2%'4'<1$&(0C)NH[>*2$(1>.4 1*'/'0%l8mk SԶG }|d nFW;{YweE M00wV}{lR+;ٍ-9d`3s8mk4ʍ,t%|{j gV~bS eƞ`yubikey-personalization-gui-3.1.24/resources/mac/Info.plist.in0000664000175000017500000000164112642452141023065 0ustar klasklas CFBundleIconFile Yubico.icns CFBundlePackageType APPL CFBundleSignature ???? CFBundleExecutable YubiKey Personalization Tool CFBundleIdentifier com.yubico.YKPersonalization CFBundleName YubiKey Personalization Tool CFBundleVersion @FULL_VERSION@ CFBundleShortVersionString @SHORT_VERSION@ LSApplicationCategoryType public.app-category.utilities yubikey-personalization-gui-3.1.24/resources/mac/yubico-logo.png0000664000175000017500000002630112642452141023446 0ustar klasklasPNG  IHDRS}NsRGB pHYs  tIME  [v IDATx^gt$u0A.6as "YDE*~:S$ۏh h~O>e1"vav9 z=3=g]U]u\D,"D,&@D%J.EE(@p@RΤ& N,Ns$=ere&5! ր dV ROw~WJPNJ _/5X>3x즲](XVUX< Y%83\܎C(XԭAYVɱjeVH/-jqhV `hV `hV:(׵' X 6Hnb~OQ\ E&U4V ]Uu$VBcu,N'@).GF2JɞFE 'P1]rc#N<"2DP`(>G~BDIϮ%"C@-!b#}jD4#jcc%BDHk8L>h=I '  ƻbrPV2&f7 Npbx,9 LJd5΁\᷷z6-.K=0DHGJĠ:$4BKx<N#T  bTL*l6,:0氌A{AY`814=;1N R "3Y$TT;k\ktfZ[P 'xhO_CK1zsbpD E,Dt4= 7)eUO>qtQ @g{`RfcP@`LOcrh|s5{liBj]347QPzd葚 Z?ę"q\TJ9xNNj|br #JGgƟfpD4:968yWml$6ٚl*}So{v8r2B4O_T( zO=5UoݱP0?G O&IUCrDDөcϜ|νe[ʯ] l[mAAgr J*UP ӡ%fzZM];032b0a~un(2 @d@{׏Be%(5 Dt޶j*y1dz@D%BFud5j?wN(WBA`@DxT|*j ଚbCAeUK \ R}r_cEhYG#"yسS5Zzr{Cc."+̅;+x0JDY$9oOƳ!kAWSX*c_9:x"=RrPU%mH_c#L#VP?4pGJ5-J G+7<3"֠ҟxV@`bDT7u)%HGJɡQ0>J?<]Jgr bLώMwbb-D\y.^Se?ڄlTr5ֹq(> ĺG"gtǠ@VѱV%ke*$<9> KulhqǿI3݊'""ΉggEČibDCǞ9L9+)c]etn (u D$0Sg)Ew1Μ|ڵIϻ#/ SNhA97M=kmzcHlwWURm*y %#"qÃ\1H2ak)u& " lm,۩'" @kvx#ѳ_D:b8)&0|Ddb}` '5&&oZg,SPD"11ƣB40[2ǞxxLD OU9ۛ+kfV19 GNFՔLfÿ'GLMOI 6Xk% 23zĨ W6-f@@$˶Nĺzr, _㿎!ęu&z*)MeXt=EizKmsUr N3ѧ8"tl䱆Qcr* = \}ր  ?2paĂ}gƞ|"2 ;7}ֽ9&Q\W\Wl}FN ^qBJ@?I0yj(rHEļ"F_9"BNsU9ָ7,U`CLvڵ5_V{&8>WJ2e;L6T)(EDU>{30oih+ϝsc5{;5Ji{PHQ4yUaͻEHGCGT./e\smQ/DD`ÑS}Iƣ] - (?X%Ϯʬvpy4zFO` ɄՓ!"jwfM1"jIM2kqVoT{6oIq-!Z[NPp4zVӺY@V|Рd(F;> @dOOɂ{ڽqaR^iIEK(6IZ%4t~?vW}l?ݺ6Tޒ/6I  Tߞ-YBPX@`/o$mZ+nz5745ek.D\Zo<&@hj24سƲs tkkT}[kc~ LȤ.D4k+`btbtQʳhLO;ޟ]+L]r8eh- =s\ipxϤzE+Ӹ<K\)`[#3k⤖ۛLZʔws=C ĠS ^oK͝ddcCd@L*PP :6hb\VedDW: F soLE,,AZmb.@k 3r//d)D4ߣ"tb)?bR>m._KL$ڍ ^7. NJB@@`Q)NDJCʍn@L)1N[uSB쨽[Ue0Cƣ]׊7{r7Z} ( X- " $\+uSʴK$Xغ8d,Z{eڨ@`.6pW7pKQ85D|(1XUAg/YYb_ZǢYJHh3mU%݉<OQ\MB,1-ծM+WTxҸ JIb0(ҫ,J,e4 &6q|z2Dˑ+th rL.oEM^A9),RLJ1h3.(1!)}a7 @ZMrf$ %l"3phEel]mႫ!TٻS _QEBθa<Phq)%GFhW\*"hj*#E&_,̢lXܡI:㪴Rs$XKnՄ&I]~4S'S.൯gfrY ꋀނ.@!WyщKDd:"V.'m.ò @+j:Eえ*W" 5XfxG@sd:::B{ uQj5.KAGVx K>_B4Gbj=;䩩qBZ`7!2Ss2-+^{cs=; m=eaH}OMv\[7t!Q*=W]Bu/#"cց\7iy##ڼ-D7-~.L: " ({ZK )e6éѧxΙTFOj>2ȾodDcBk5YLPR6J&YϚ D$tsEd-%g(;I~@1<K7VT5\^`VF *$H' *jk M`k+k:+0өSDsʹБh^p-X,W 5ywj׆*:0,< E&=q/bf e:(COF|[0r`,;we:ZbfJÉh* 0%$tY$9~djF\b&@$$FGO_ӐĞLe]ZT5Me;N=mȤX3&Na.7 6LT" 'g. jBDluwLun89oiXCٶ9BC=9yۛZ|d~/Ėoֹ궷~TRSrޝ̕Bwa,өHręqgkrK@7[Eic{]JXd-2YM&Ήۛ<ۋΧ~Tf1VKk7R9nZ9WLnKkɯaQW";sEƪYQ#CG`t/`vg'U4j?@c{=Hg hh Wa%VWʱUl`(]̋f`snsJ-n,ۙ]DᔈjZ-{^{\5D?Z ̐)0`e˜T" qoe-1D$jr{c)sh\*n-&X®̒cQ^5476htYș֚[`JNi m} ϊ.Mwc}_`pzDDĝ[~`D4 Xw`>n/"m5Z@!R w4VK {Vy#. -5EdJK`k]W>[#".* !".7 D$"_sofȖ"lw]֚%u|Ie) LQ{w@DȘvY52Sr2"pi.oaG=eaeB&I@`(ծuշo 2)=dZ~M/@L(1x*mծSlMwm>;B0>PdʁYk6Tܲ^jR3 "Y7T|hA֛{xlKZD"eW}>[ᡇiw1rJDD*\J 7oѷqRj"Dv"4sBTz;X8)k]} O(PDdιUu7Sh(uɤ5 t(R+nz{(r".&1X"1ZCIq+<{]-AȶfOx 92փUӳT8֖_]slΊBJQ ZT+䀬>'m%(#fR CSYM2 B±ɷlVo片Cq%$<^.D:NkspTS#ӧgGtX c;Z[<ٯ-̕X&D<ʓ[͂( !ʞ&x:CX鉙Hrt:9I t*ڵνgoInEi^bZZ*gRX@`h0ޟHG?"f^huml)5M^Q.,"XJ?b4͏ S]+~Gr2+G'8) rPĤ((vidŖx~w(+1ZI)&G~Yγ>r*$Ef4Uy26BOMCxR""9] >婾Ju2LZB5Z~!Q@h1v%--fĖ8C(1Zq{(EdfnkJ  SR'JH`nk]Gf ԁ1Dts%k&olt,,*U.mI҂.ZVJFz$`E]z ~Lj c2"nm]<_eK pq9bUR˶{mzrY@D":;N"bȚ{l&^*\FV'x0 %"^aosoyUe5b7T:pqF󫬲e`8Qe09:6Wh> BZMN=ZjQbSӝÑP"lZ#8c04-?}',ZI3Dvz2kg2/uEMv^$Gj[dw<*06\O= Z*)/<'K洄bnx\L bLb][*{m"{oqR;vA1DM0mkdxO{UDwYt@$9x=sgkS.DˡfQޚ7wEN) ``u@{DNۚU$ *tjg:9L;S>[֔zs tZ{<[5Ӟˡ /XAXiZM|9w\rvN0" G[rц3盽WDpDg{pǣ[k/6F~ED'Ǟ=9S{セK?ީ*Wᡇnhk>9E9}7}f*#!ss9q`G*ns/~ XEGBJo/%j{~nT0Lt=r[c: Xz ?H/x<[s/\& 7//{Jy_}X/sT~dvp髽ZVwȓǧǞYm_~l7y~{kR<Z>kG+rۺ?5e&;RJC;Y)e47?뽵=ۻoӗD zw?Ƕ=PޔVlPy-"&}"~C:ߟHO~d0|Ot_ErG|7.pRj"&UQDzolzޖOJ<>…)\\1YtjX+5*lc慨іRbNz׺7+PX79LGx??Z*WzޜZ>5)<%25͟Txr< ?,0SZ`O |]swH`RswjծM9xbW{>e<vݻ;ӧem^оv{=^kt2 +3095:}5_tSCaK͝[`&pxAYכּg{ݒ`sYo5WɃ>{ík7 6IܼHbRGo(uMfh^T.s iVKdR(\&x,Sg5Vt$.c *)F;okY:=|ԛ'1&jal |i]M/Ec7}ʼ硍# zw}l}KͿyNXZX$'CRc XIt<0>J@(+1YϤ&^x o(r6Wߖ [gl䍾vLzFϸ}b8rպ6 [ {υ-9)5)e!j*;5\q92`eZb  Y%6TX];㿧O;YoqY{vĬ[Z`.813G`8@@Y"@L֔ڹ^ CM)d7Ʀ%;7qY L^xV*S E\W4bZ< `SxjWG[2nP$"nTw=l<3cGfl&vumT-6Dd( T:[ƢȩmYN1,3p0c̅NHϖIQrB E`4|N2AD [ɍH!b^1'FqGө1NȈdb?c]Ԥ2xU}ѹc PQKUY ^AEfY"3E謹/z,OwuDs{LpcqRc j:ީXLju nd(HCVq$X\G:s2k33_ @eB"3U8$hro1yUwoÿ2=7[/v͖|j= 0Q@1lK9#rWxb4ڙKRJVp[J:c#5mʹZx0VsUrb}tk^yJgkTw>q'cٻb׏B}`:2^q@ZwGsh,:)Hc>=\sI+n\sSg…_ `?:ى;ouo.֌(zҹ6&,UL˶~ƪEh;Cm$S;?rl#O[h-{smGG~?SzOC5;L~Xjʬw}œOw}a򷕿g t䩳Z_qK(hh*Xf+|%R#O/)\U`Hn(X,CVMޛ۾=`,s̢Cp$׷~@O=mu'ǟ96 (EkvLw̅vƟXkTq? "P↍'F~_ Q_3w7&u-ޫBv*O]*zhdo80 VZr5_}Gx&JeZpY7YtܻG ŇMm %nֹ6k $Ϗ}EoKJoD\ ޏU 0\*e~$#Ԅ$X띖P|P%gkmR$\|(\lxyJit5yziw>cJ8"2WYi5̪pIENDB`yubikey-personalization-gui-3.1.24/resources/mac/Entitlements.plist0000664000175000017500000000057412642452141024244 0ustar klasklas com.apple.security.app-sandbox com.apple.security.files.user-selected.read-write com.apple.security.device.usb yubikey-personalization-gui-3.1.24/resources/mac/qt.conf0000664000175000017500000000003212642452141021774 0ustar klasklas[Paths] Plugins = PlugIns yubikey-personalization-gui-3.1.24/resources/images/0000775000175000017500000000000012642452141021213 5ustar klasklasyubikey-personalization-gui-3.1.24/resources/images/question.png0000664000175000017500000000163412642452141023574 0ustar klasklasPNG  IHDRatEXtSoftwareAdobe ImageReadyqe<>IDATxLTmHSQ~{w^Vb-e ˢ/EGZՏ *~DPD!)AA}Q13 nr܇ssϹ={5mmmh4jLOX D0ϐљτ1 Z +dYV7xG0 BS?!z救wp:g~J!JDS-(R3rpuuu,EJPTV**++-@8n%q21^QSMMͦ @&:wFtt'KG8^?8tohA$8<0.Xl-C0_ͩ$&=lXDiqg,)la, HfT70d e(J\8~Dbѱ_Ӹ| N@*Wm3,b"eR*HpUQplU2 $9 4K/7uό,@Vm-H2@oM@XNJUU5ƠLgP#`xxǸLrooļ$tz2֜ȹ$Tdh>q9јѡOq,{ʏXN2q|,SyH8k@oo}獛 Xc^!;LF}X0}8wx\ޞ.7#SnW;K\.f[|]mJo7o^{ !v,*4ޛ0/U< |E$~ 0=Qi9}IENDB`yubikey-personalization-gui-3.1.24/resources/images/cross.png0000664000175000017500000000111312642452141023046 0ustar klasklasPNG  IHDRatIME 9fo pHYsiTSgAMA aIDATxRAk@f&1tݭ,[xj J_ + JVSuv-[ۍn&̌/*[I͗=`"LM~ ×/pRd Qo5^9!_F)$w@%"s?zYA5va(Wz6sZ ݅Fy(Sp dd3h.S!sC 8 0σd}N0Ez6c* yyuc(5ts_ܹՕ_W:M``4 t:7'1GÐ18tc 8/~?^Q޻ߦ@0&az =ې>lin].v6+d=v{e4ڷJտwzF-%Ou0ףtY -?"z|mO room@+ IENDB`yubikey-personalization-gui-3.1.24/resources/images/V2-0-2-1-animated.mng0000664000175000017500000002733412642452141024430 0ustar klasklasMNG  MHDR9d l TERM,sRGB pHYsHHFk>BACK)bKGD X FRAM,1(, IHDR91 PLTE,/,̶ʵE9ůxcONLѼss+ɳíx]ƶq4)͹ptjsrM)㓖Ыr]˶<2+"Ӿ*K@hgϺsz[ ƫͷ[J{'ʾvgóQCcQruw {XT տ"DzMP*:B[a e\jm ͹ímYdg  ͻ`M$& ԼֿIJμiTRUFͶҺǯr{aT ­mr [U˲ϻ© ůZL UI85SJ QC ѾGQǯl] Ӫ #! ϽndY Ġεʨ §^WFJEϿū˶\YUê;;7iq YcH ߻ū˹¿ʰ2*DZǵɯ gT ҷÿ+0Ӽp\ADAβeY͵bg1ǵXFDQ1; DZűdzŰɳDZdzɵϻųų˷ ͷ#z|_V!ȴw}qtRNSm7 IDATXřkgDž sȭ=b A a fDzQ|P  LK 5l),KOn{>؞q7b˾o>gޙT.Q?qo/~z'0%ѧWcmmtr\~z+ֿ,k"c%G;3U]*8<8 x"±% #8/Ƨb,VxS82LgW*uO@ttս+qgP!: \ Q yRp0*G/W'YPeYPbʛ<_&0[\PTejfH^G%R d>*Z"ƬEqDcZY5J%;ɢJLn,,/gqh I+SY"#N sz`?+Ge2 nd+%?#y|Hvf4g~V"%!Ep5Zd+dX[Uŗʧ2Z 5Y Kht&K=u صu`k!*>[ rZZLuj`V|qhFZ&]_?!B-A$#GQZ>f'dUJm-UIZw PfQϡC*z-'[Z`1PGj'E+lDdBRP W턒PuS&F$UX$əԤO\dJU/jK:܆A԰+`d7׊R07|yqxIj tBTy3#mIKRDN|U2s- ēmBTZ+Ԡ ;H+Yaoja/޻2cNT$mZ!8eowvv(xwD FEXs@VAffcʹ <M[U+gVQC/2h\n1$+PH8fm(Q YX۴A]]Ǯ;K ≂y~>AlEZ- xV ҢԈev+sSD$R)5)i#}L9;eM%kE'']9uDEROyp U$es'bks&)fʤ tu)ky3t0Y_*iKVq1Vb' ǖɯHZf^$co/ia; tkn$X/jqYiz@d/䞡JONjeNH#jF~}KIYn{@K5sP}.dBgW r?QrX'4,@,]=Sprއrk]מ^ZH$|nԇTm}ɰmaw.ug]ByZ-%ﺭ9n Yw?|[6Aaw7,6վ1YR?ZN~sZ3δ3l~ZM &f1w5hFD% )bO͍VsgIl8f6s6?%5ө[ig73p)δiv-хSTǻX jvjZ9-&OF$;jgwnnF>5H6x6zh8NlYOV|Ԃ?4taNqk/BW``4xcȵwxW QK"tq4wCn,&RO{>N^|r:UFgg|gWc?-O>o-'o}!HqIENDB`FRAM IHDR98IDATxIeuq3k议ꪞҢH%ʤM0l0 ^hiomw^ho0 ˦ũEʪ_;!+3ق 2߻ވ9qΉsNS{_/W݁3*ٓn(I;D λ=~2Q*"Z]hpYju}<㣅*/S+mH .PQܑds]A!;%;orsh=DXUdvw 0-u߮ !0oY38[4/E@ƭ"ppW^wڒէ4%d`:BliUci^D^P %DrKA%Yk wիYsXD)F'lӭT֛piOjfߙ I]LD%P:"HZ@cJDw\48tnolZ9bDab@>ڽB9D5A=H]ʩ! Dje}tI?Kamg.鬥XǖOs}!/ٛ";TC%jz.I/B,\~bgG1O񽷽s`oXu`C{q0׮sғՒm٤*VXvO?;~\Lqb6Ec52{͝~%W# \`ΔuLeOį-?M>X"pĕhXAAa)HW`1@kWNA2iCFC`UzI0d&нȠ yRQPK@[TpJEPxqX )<$:b;q]`sa"]vkaaY< dLbj=8[D (ĨjM%39P fYV֙sRTmh{8 sTR|.*%qk;2Kw:IͰ&A(SڡժQ2D|X8n xMfG*A:J-!o, MN3[lYJ3d[R(ap L'!@@tC*9T<1@ L^%%T]k.ii[vO.O] i`kTsHz:*"8iIsdC%kp@&[ IkРJ <f A'p纈nUz+\gQa{-37Zs i}WQMVM/}gGRRYaN\Yk|7+6m;KVG2 ZRJ:/x?g4*4͎oY/輝uFHv1h.%C,O6$쒙T7\ R(=pig!A1gYpqԿ!pOvxUoqJY$H;4A+z㯳c;r6s R̴b|bQP"B81e1%`eddH-Yc4UD8Jkm ^U1c eax]b!t/-6olY Z24ugy-)^U:+  g :1ܻ3np7Hɔ;\0{ě?=7a{k;hgMƜp?s( )KiAP|*Ly&sHɦ~2ehfK[iaJ+ >rtY+^ḷdKgIhv)X:Ҙe̵wsdJ{.Z- 4aH<.XDY)x7G_j? A~IG{#~hX0ucSTw< Mhvrޔ-0U󢞁y&V|1V2s["վaqmE1蓂b 7dTy6=. z}zM!OR@9|9PY5g7է弨C+Y 6auWTwbc]q8L蕌LޤgVh2:cu6H^C.+6M2Gl8{CUQ0!<:2zz}ϕk8:Aop+tGcr|r*uis8Ql>?Synu.~W*^{}.W+tVjzWɲl\kwmiL+KY!k9/ Җ lrV Fyײs]_r-5՝3uzrHO<ÂN:/pENg>s۫W^rwyWpu՝;r4,X jh7f )OoH{.;)N:cJnl뷷88U=\ݬa}+'˧ tE՜ӱg`l`Mբf3 +dѹ+vC^r#]^ɸwѿ?u:1Tb v3\^Δ 1SNg()7 dHP' rNUU礴q <W2:+A`MJK]ZZ#(Ah|H#KYTƔh74:kh'#)ѵ\᾵Mw?j@{S&e| ^' 7y WBeY5U6/.C\&YIw$RL f'v#w@kyL5g%gβ_w~x̽?=Cry d>ō3`}—(a4TBDZ,lJ &L~AWJwi1c0ݜ/4b1eaS2"Jۅ9y(L>*fͮ鳈ڬFΩst䀦4\ %Kvyv|nLoqЙ fY\MQqJشM)3y_B3 "R--)_]iÝbFD#"d1T/"-g+{dXэmYJI5OZyz-N2@T;W/s I] BtbL;em!Wm얆Nv CWlb`UsHޥ(Yѱ'Dn}1Bc78.T1t# h!⢌(E#}U. $ 7;̪S{Q2+T\֋AI#jn d\qY9ӵuݔDhYH`U;J*^3* "jSڹAFɓ )nf"*]JH7b1e\I;9! q uRSn0pIPe:n.2H:H9{D֩k]I# =/ $Xz:.Pf“:wܠک۔~*%H[Pq*]%T-BmK]c!35qiCZ9#7&Xډlh@oumFܔ6[P%$C0\L۬D%[YzGGD!J*nNl u>&\Oe5uٴ? u*=^=TVQMZ[H@6y]%il& EkГuzSZSMo:1;NEtC鱌(ts5Ơ6ǜO[Q@Y gM&U-*3ޥ5կ\f٦md@b'aj[6戲|Dǣyf¥9m(}gQh pO>d!p(ٲt޵V\ {bYꁠ ߇U%ZʎH&ݘ'M,1e9OMhq*C!>&tRv5*l3v%*"Uq8l=$015'sJzֶ-(ȜRL]] :Ga\pv*RKڐnn|o]XF-h org=/19Kau{?衭頉ށXDwYݺCoY.ꬣO/hLO 9{My?`ГLuk N>85@?^[8W,ل|_]TtkK7_WBQzڀ&Β<}EP+ot, o|~stslF'< yoq#?uY(ŀxg."5񔣇(JmrjIщUr2T,Nt#J4 jt)YAKRKԣ!L{u0NO)r0)v6F a< GAx]HzL(z5Pb*gҘ2#@ŀak(0  GƒkSWg)O=ρ譣 b/>,a E}-9Q @=yΩK`&cUI S(vx3 Sa:J=|X{u*=Hy8 8Q3*9X6>s.e@Sv4NƊt~7XOw/˃ a~:Vkv^ѱo ͖uKJUcxt @OC֦%gn\s7QV}y|PwX &Q-}aۦxO=;kapӐ뜃T_:bl8eZF<&ŴxNStm8*Zegr4)6+FEwuDm)(ܼvrkl~7;Fb_uI$Wn}c|*JJL,􀝵6Oe< :}EYNsrgvm<ؔ~z3-DDbj)䌵lɮQѢPb$E@, ^~5fvhT5AN1@SKխyL#0=Ōɮvj*lmӲh_Ϥy ǁ[Zdצ ɻ:RQ M&w5֓nk6OBfT(6uO⦳*ykg37?M7?ݜ Ll1¨UZF5܉\>7*wm¹5pxrh hcRD+%k0e+?޸O][Nw?\!:٘Cy-֫&3r:qxO2ȅnNT7!ϣc#PɂC_Bxꀠ">hX/ RcAY]nONeCVEQymT|/3uk3Xşb* K,l?Ŵ{ Mg 0h=ATJì<kF}}OOu{Ͽ_l2*YIK[D\s*2sU8M)Ř3^ʕg"WP=\ajت¹@`82=UUZNsj`.ABnIk-ZDZd247 !B*"sU97',w`F("K^:•';^mE羆K^;<9%QD0$E%tz9f ,."lKhH GQ\&4J׻8HlNE(to3x0Þe{e/ =[ [&gE 3nw/sK)p1,}H؈iIENDB`yubikey-personalization-gui-3.1.24/resources/images/blank.png0000664000175000017500000000011612642452141023006 0ustar klasklasPNG  IHDR IDATxc``Q0 T2IENDB`yubikey-personalization-gui-3.1.24/resources/images/README.mng0000664000175000017500000000044112642452141022652 0ustar klasklasGetting the MNG files in correct format can be a bit of work. Currently the method that seems to work best is to build with the convert tool from Imagemagick like: $ convert -delay 200 first.png second.png output.mng The trick is that the resulting image must be without JNG formatting. yubikey-personalization-gui-3.1.24/resources/images/v2-2-animated.mng0000664000175000017500000014047512642452141024177 0ustar klasklasMNG  MHDRd = TERMXssRGB pHYsHHFk>BACK)bKGD X FRAMG IHDR>a:IDATxwdU;SDfC%A$(A2` (`@,zf`bO:콿?^p`<> ꜽk]9njm&7Mk3یl68fn3یl68fn3یl68fn3Y3Io(q'̈́O=Yg=am}_zS4 ɳ^tጬYRkc~_?e]wݤq&I<4_Sghh4Q!$(Ij!@*I$ƉN~ I2^b=38j/?,~k 8,}ZZ9|9ht$Zuk1b qi(Haxъ'kKy}w[@b,Y! Jȝ:*d%PBUvx*=*Zk*&̛7V0:qi/\c*𥯳n{$J*˰6Y@H4Z`D'(>; ]I֚4?˲ׁzzxǻOC[`>uvY;-9&V/3-$|=/;, M3N~Y}i#mYӷ1yTY}N :)ӾZO7[ocRJz݆R&!cwc~7zXz;+W"8='kY;~}c!$JE~;w;uR}T%Y\$#nM(  BAgY_oL SiAͿ1g|{ΚU<  8(%pD pZK7EpTXw`mA2PJw""bbٍuC u8)aL5*Xp&uYW]qú+N!02fq&Y]|`])NGppH/J9@d <FF3~Xd |t @#f}gXJO9BD3b鷿z 72ɚBCRS )4us '@*ha(QȰ0;,Z-Y'gn,'B{6q-"y.VgZ\!wɼs!Dcz)D'!(p|Eρ<|xp4`QHD@ጶT'?O9#=j=>E~lg8Y3("˝{5"|."sjgCﺜR_SW*36$uƒ)':HoHm nֵ؀έ/.R!}OIEE+YZ"}P!18>:iLQ$Eo| >h.|>OR;CdݎVF҅eA+1ixhؿDPJG6ʬb.HJIj JIL 돁$ˈb"s~Goq*B8vnI台{/~B.u6}f&a06#Qg総-Y̒"()! ,(ZHb)"o )dg!ߨ]wR(O ;P2!3.DRIlum =iIW UPt*0jg YR^gb|CCdCrʱ[p"FVm"㷿o=oklYb8 D59]rμ x'1!̚L$S_ZO&uҏy8GFBZHͬl4#fg[O*g˼s)TyR !'_Jh)1Qh0%:9ZI2EA4lg7{6O"i9WИ Ӗm<, N"_vwW%2P|ʗ0A/I1 *RTY!^rl05=EC1M3zHZM$2WG."p9Q!9RJsG<P)tDOQ*f`}}{{ࢋy{LO+0rջϕWI^L; daWHtra$Tz 2: R=u>dv`LB254qgb|b 4! 8IK..fO8#Mpk2*d.5>,Ё/h7s+D/TSULU>R;=2s0w}#IRa"ohwAE* Qg-S9^EWWB@c|4Ů &B`||B/Ĺ .";9_ RN8']Ht 5s Ɖз0ka=#CjO:&-j=̛;c8 N=l zO /~ũukWI 80+ԭ>FXp>Dj#f|qDI+*݃4c(uuK8:ѱ$k+%6HwjNcU$A q!_D @p(V\_<&KpgQqDw(J̚GOo79-o=Qɏ6y/}b&,3mmȲ*21Mtd8HSl,2|. y-#oHGVG3f3:z0hk}%^~/ZLVc#+*V1-OwǛҬW~r/8=ƥ@(&iM"zR%`:s &C+?w j=1GR⿼Oy̿>g&WtL6UiS 'GQ_8Jwƶ1DD6appXXr-zNj$IFVg|g$W8+1E9dI832OP1BHuI?%,H48eFfo% %t&ER3+҄9sQW\~;86S7~zQ1Yhu:3! 0-|M(?ё EcZ$55M/P15>1{N=sp{3554z:Ҿ %B,IEĴk '1(GfZ.[ JWz5P7g-XN2w޼.O\rn/))ee1ևz_9lmPBՓ%|PR!DJqa\cjb9d-jeь[ET Ely!`b0EEMxEԤ$QD,];`(A(!"'iXǾqewiL Ş^J.|`8rᒋ(_p?7;pZAZj t4(YsvB @4r3%8tr5")edh9HU+lD4P!fxxBT` Kdv !8&2DsߖsCY/|WOYZLä@K $zi6<[R#[/}'zHGYtcۓ\z=hN `{>D[סoI1v/tDs*] 5Y;w1nB1ͺU*U|V3%K28H8fI'pҳTi ]EP:U~JV ?DQ-P8|F̙;U`%[o|ن|pO?i05=G5WgŸ݉)L@RB""MRr?L¼-q̑5}m-z\dOĞ$pOCzDGY#0da 0BX 2I:DIݖrERȬEX+`͢9>ѽ\ &I)tbf8cZ+y~KF8hVbo@E>7A*3~80|bGKh>Fs=ufm))}./;ʓO|^F KSVadJJlfB~zQ>B Piօ`=¸nڍ'[(dQDNGA2h5(#u H*YG*rI呉7zĬW@PBuF|u BB208qt3g,J"W_>]㓾7 Ш,MuV^ β`B*]eveg>Ň\Z*$t ]ͼY;/ػstf۬\ølM# \dւ eaܕ^ %÷79RB?eI\iY2E(1\ѱ|;ҟJ)P8 *Š tpOOֺ111ACo8S8sֺ҅czz]vܞoIH6#':mm].(g í -Blq9?aK߿o.=y|V,ڶAT[Q*ul% Kr]|G3M%!Jc3t}6XU[8!j$YS롯KW&>'M Fs],S,Rb=`̜}Qݯ[Gi^'ơRwp"0:Qa-*f44Zf]vSN#bIDI<'m) w8(' 蚏(L|@Ѷqw2=o;CTug柕N__H̶Sf1?yw󎫮WǬY6?yP((~Xk3(g|Y!KNipddY*&SJ!CG'aRh!h0~@sݷQaJSA A =/%^(3oy|#׳ǹ'JT -NyL#4Q>ĘS2o+yk;/O.=f͜uA0 Dy7^i~k%֡uDhcEQ @dB3]Gj]<= JWo300(Րmt$# MHbr]`.ݟ+FTS'/R4AK, c>7<ۂN;mbd& Bڑ̷qTxX\g1q)>tQ .GW_l=ٶp%o+ 8VZЋZ^y[/܂qɇZiJUwAyF[~ yIw)Td7|i6HmYۑ=' /dRn/0U˔jLQTP럋[ {ET8ڡa,|[iWj2UWe&UJj:1 Chm@[؅| Hp!S 0O+B?Xy[o틜l*}:]CWDO_XG} oa``(zf ^GKÏ`{QB?V NB;iOZ d]\|w@rn, yA(mPZ`= A0vQ AqƠ 7VsՇ#tv#WDooSM?qxÒ R.穖Kd\sl֬| 4&SYr Xv(u@j_blq)q" Xp-;˘ՄR#*:g4#Mk_.|.tL3ߵB]ќƵmkRŎ;Bqfc>旀@FG{)IX&khR*v՟xߠlqoVW.Ml6 MO7p^ğn ]Mk;Gy)Ό`CG4K\M{ԃ|)Q_ȋْ~} t~R}Z@:R]m/יo+DJyVb"42@'|h111EVC9ّ\yյlŇWC+iKˢE[j/܍5wQ(v3t2.䳮c8ya8-8ieP&y;c0~,D:hRs,hNՅq%J#u`ģov x~ .[5j=TIt~ rQsX E= 9fw]ɜs5{pSFh4)ΜʷH%7 /g+H #kW]a>ʖ58ZHȕzY7W}릈"%<`j:jJsUH+#I.TrD4{)+\w_H>M7G@|9ifpDdu'_5>F!#4')VopdD̫Jr\7&Xbn_6Q'^Ëלtζ5:WJ> eYgN 3D ^S7s|[..W(!rI&0Rwm's4lQ1,栗]Dpʋ.c2m EH\޾QK&~$ 'k ƥ^@vZEqчsƙV 3:O{Ѓaj|J@Gy;1:ZlZik40:%vSfy-8EX'@p 5S|.|hM_xŲ#%.Kyo~:G];^u#t"5(%.#9I2ad)\B[I'ifi!V1jg{!HӔwڅ+sss]ʕoޟjYhU P\.sEW+Ep9[Tɦ)Vfqϲ<\N:h . ! "MBP*k*\}6H?1@+pMZcdL3t(c k2 "YuS/L-.w\;@WS3t0 Y$-Xw,M g4Jfs0HŖ׿EIJRH5n^7|Kۋ7=B9W$sI`2K(A?g_J@j:u7q>{I\A[_vW# qɲ4.T)S-uȃ+uUJdf_'oy1g l:2FFBIMW _^gٖtbb\:o:] '>h E(#MȲBu.Z.ƦU>Ri/Ĩփ:r{Xa򅘁>,߉k?|=?M>)MGQDTO;]wG5XVYnc%rV4Y1&7BMH nsv;29b4 QaGvd)5o;c7:h.~Fsk?!IӜNSs?u (*vYΝM1_$I|ȡSvoV?3sn~뛹ץp%̝=ڱ5D2"Ke΀$WہN(j^pҮFpw|'O@lAj4hހkM(bb8])BPbZE}}u&h4|jw^{E_3TX b?~kf`VpPwѷ b|<.8 ^^]"ɁH(wo.41߶[_ T+i(*=|gF8$q>"&'骔iNO3ɉI$T< Ʃf[_/:T5 ᡥKp>>/]$ܞv^5?gӼ8h6ƃ¤M\9uѧot\x출C_fDqM׶W_Glᤢ^alz ԻwwĊ5ӟ(dx2.fZ~ǧcݸ}gܹϺF0u_KP@EWORV,[ĸs Sc h6SrUdA*`QQqoci) |b+ui5en 5M֎ML "ծnƉdN_/;+p ǟr2ݞYdh(XP,)W,zkfq4v̚=fv? |Z}|?GV#!s MB`uCh%(jwn<װ|kЧK\_~db弚pqMob>gJ]5DHMVj/rO>Ï=mʋIg)$?wkjdNg_*gQx䑇y׾ɏ٤ |b|sG?%+VBp5J1]<zj5#vհ,#-"^q߲uLL& ZiVtzuNҷ1k\.T\|oh5M׵nuX0姟TͿkV׿LݍLOѓw\{̟w:B\-11"3U)"uᑵJ8װpVhl]Gp9$vySƌy?IFKbh*none!/h-NFx!#n8 G%4YQ|YVL56(T˔syVayֻy'rOZO=&Vpw=LNM[~;Hj/k}w UHG^5nRqL2St׺GJ@}y/HRyZO>11(b,[Wu&_ HNX)l׮vY1ИjduScbzBD%g-$nO= ,c"9`U  3fhAiyxVjrҹbdI5]]NW 5l+Ymezj&+9$Z-/W6b1 ^z fAzbd{w06=#<;fJVkL7԰l.yӎ3g&'0::}wC'?y;i~)) 4- =]8g…gAV ";e_tc("H[ }=kU:,?T=g,ؿz*VZ^ò!)sԺ׿tLifE%lZ֮^>{hDwL&eWbhjV\lm۞Zsmt@.r̠(nOglm6sqf`3m6sq?¾DIENDB` IHDR>a/rIDATxi,y{{}w߱HBfd(&^ȶ*:T*)Hʕ8JʎlW*(J,JHI$( HH\\ng93=w}z̹T:wfzzy,-CoIpHw>CPs:>CIp?"EqWP %IRAvp(w4EQ\w{qfFH)mWIyI$ I1Mbqp_ \\aLHeJH 4MRN͂4wD(g0tk)g:K$iBS xMӨT*j5*ZjR1Q))SQ\ I|GTw5-KDH `4@fLTMvkC)a2Lp RNmmteR !2/3\QfeS1*UM;$IhO$M42m/gb=o&< r[C 6)_d%yN_J$X>6TU5MnjA.Ʉ( P əXf?˿ 0 "\7{ݬ7J:Hi$ #SdVU?\04$L鴻3:@i.a0iUU ap=VSp(7IQ*?c$rf7S9I$s(uTU% 6qFL&NqIWv}QH!AGEQFY^av] HJL&D(>ðr/:B )( zs  1E0/3;} M!DEQp)}p`a6+ br+m80t@B@!j5tԉTi:Zz Mm7Sov]W$YՎ'10e3;e_f0٢9д Q#ӈ8 H!"(;]!>l"ث30~߲6U٭;]t3צ( uI4@ U;dB>iiRqꘕ*!!cg{m1zEQ:q'ۮDQ[83{{_{ /_^=(y0btUvk5LDuLFn\WH+B0$5LeV2Aʔd j'(L`hF Lou]'ISBr1Zk#³PeY459iloo' D,Dy`ʼB)zQ׼ϯ׃)%QWyb ,/b A%2a0&zvv4M, @ՌBWsk\2$"IZC}݋6VQj'KoiQ> wȓ-3?O4LӼ)'-oGH"iIJFb(}!^g`8q0ȖeN;x"=0\(w$a0P1+Y<ǬʠdgZ{/Ayd2z cNDQjZ210gK\mW*6#{&'67pUUdU'9L)*]ZiY='9noK1)E:Wl2ry ȴ( u2,? 1BD ҴdgٛkU(A4PW@JUތ/;l,Juynyw?1!egBEPn1iX &UBZ!BfiVi4ޘ/3 pN+v|9,\d`~ ҙ(1gUT|Yݼ#bٔmgRTȮ[T7ȳ~shE!Rryi\f^}Q\BfbqqRww=@ވx.Obgݨ-^ΐENU]a7 /n8+kڧNPQrDE ʻl&םQia90Ӽ=.Wd2uUR xPH["kº) 旵I^x!Y|j'ݬ\J䌕 UVFQLSD"$b*B TB#wR ;r:(j(;=VߢT"P*G TU}(FJt7y><7[|2jUV~W'IBxDQDǤQJW/BE+躉Zdː"ߣ̸7?"S5*T E"1{ɠ0, yth48w&.?6fYE!)'!K?\B3o\DͲ05 ˰Qmk9s 8 cƲG>_3NuZJk8~ev~HN5\^ܯzDAXmehE8׽*I>w2Uc.+/|5z *BFxo_p]4HҘ а5nnШY;hO0lAw$I fxmv|:ie._~Μgw2rq@/sQT4Z :W.>u4FE?7bq$MPJu.VfaٻV8~"E2h,p$Q̏ ,& Cud* <̹xEtCЅL܀^¹$3ŪΕ+?kcW<"g9zjij9A"s8 |4NP EA3*tz=Zy!wMriwq QMc|~\Yʐ!?_<գ۷X]cU|/`86Xo5% 6v nJ* ș!1q'SU7,awʴg_%p+86DxԪ:R\?n1r`LPCG[˯NVcyy88.FEw8w:grO+;e'<# !IJբjQj7;;;b\8KLwf > cz Uɐ~h4u6Nr5V(r*5akgۢYoycǥA5 vxAHJ3z|<۶iTշ;*? p aW|Ђw.Z,UPBP]v,\:zc5jH~J̉HT[akU ǝ*~7zi$HT`TkEe,]AZ*rv{z= So0m y_~+Ӗ4JN,r_Ky'0ɫiTAo?(R=C8wr^X?`gzaVhTct]1*BKFFT]TI}mpc<#9߹@G8UАĨT];y[r-}L-~~|ٓ_d#mjY0ɛ/FK'~8׿KgΜ+aq]lըU|ߥbJ蚞 P4*^CU >89Z>al>vu[Iy|ٔ- #[tH3“]0;$}}\vgB67-67cY&Сm3xjBS4٤V_&ub} ô,в/`!(dNN5D,/똦µPpÏF#&( g3f !Yt̼IJ#K?A&>?z}g&W.]Z:&qc5 M4K=1dH!+Fa^Ҍo\,He:I30Pg_]+G8x/DQT(FTͬbUee4jJг'_ x<ƛV/ ϫy91! #KRH5 P2?mZV%o~ (a4^/j-M' _vY162rv3{NQl3cPgy x$Wv!ּXT>^u"Wd <_|Yvg͝~0LN_TdTqA"U+!AyF Vkc**/v"XɦE{|ZdEQIQU&)2I`6iL[tˡ|nnn8#\ϡ٬0JܺFݮbۭV,;NoE _d( 3Mjݺ(9&(ljuI(%'Qg> JjywQ8?yr7?FQ 7 bm4R4$; >/'~ƃwLuS wZ^6^) . ?tF {fRn^(D60 ,g=75k}[ ]qi|W ǮKYhEu_t틐| ȧDMSw00S,ˢPըT* @~x=*BXJ 慧ŷ>*m\i&: *Ͻ>|jв:>FȵöaTEdR"%"!|jUJj"߅i(gs,t]5w]'YO&#gB&H'ƟodkY^iѨ/M6V%c>pgȏ9v,;c&#uj9V (/ U |関(2EѴd˾睽w$y+3q)( v6xEt+MǢcs>0 ^˲0M&s)PdP =ޘ(~%yp2S#wX;F. ?h;s F4&G*sά9{$Wv O: cV] Ջœ!ы IˌBdAH:M+K)%PUɊYgqm<'j֘-|Gl9kS7j]K/@ TU*G?3*jSM^XH(H&%Dtz>i2g`gk RbTB"!&;e]8ǫO!C+=}saݲi!ʀffx5\מ|EPҘeѵMp`9 >OG:0 0qLjThz"^|ZM0DMY5~*c_Go,}B(Y{0;dww!DVm@ô%+f*clU޶8f{{ppg1M ˪eNB΀\} #ڵtiw\|K-L%a|gH,p(}Zv^>BkuZw>=>G5j(S$ 3a41ڤdU#ًSa0jђfݖ}^@lP4 dvUJ?p n^!ʝPVv{T*fьnc~QͭG,LgB3 wY=z8l )'2ݺO ?E$,ec{?%R.ѩZ W.b׫؍R]_~O *qMv,TSƓ4MaDd9qhjpXsOzT; B$|&30$iYP$qhE?DT'vaݥ]kizR+[_U񿰴 ( f8QJFA@Ŭh60 Un[L&`$ae+wV%IycFိW8yAB)h*J /7O:N=7^4{?a'W^[FU5Aϟ%dlQ)ڪ6y6!LoZtm&OaF"e ?|.uU.;[k=:'+ZBi*Rf\𥩤j0*·#,TUp2v\֎#I)\|KƗ"dkGe>KCegVTT>I!Q/SVi4^CUtS000;-TEaiy˲PЎ>zK͡Bui;,2Ia7W9~8dD4Wu_eWWn]4n4,z^ĺ_zHorshH8hwx4`9ziYg^D! :Bh>- uiR5*[nwmۤi61QH鯭P(iXHLއQImI1z"r՝?jv.kGבBLA EQIBd<4~]3r)= "gT@*k;%c6zӧ_Y/}L$4HtĶj;n5`82, RLg^[2$*MS(z8.JTU4MZNQwgFسC{t&la=VIDATxwUSnMBz# RTDw)J#: ? buDePDANH( $~{q H $׻ʳlsl~[lml6smqܶ8fnzS͜sX7H!Bl^B㗿6o㏡Ztomc>EN>׮Bkw{1yrF\[Rs:y,}c]va>-{ǐ!<.CJ=<|Fl[Ky'1n5H0 pEJBǷuB9z| c 2B ;nz k׮?ߖ7Xg?O1JZ >#pw d`kM 3Z~ҚR[$k`Z1P=ٗo}Nzs/CwqX`!4L֏v28It85 B(8됑fRw7FC4ju\HƦNg2iRqA? tww v qE5p)@JHE @@f_I38gCxTd3YV"N(,3c RI  g?`}?qMcPaDuYVۿtӿBKpBsT h֮]4|!Xc.!%(G&kcc8H"wsL>пf=^nu q84aMIG6 swc J+1H{|!ZbQ ctW6!i$X#(稏6R30:0BJ1>*xC$%o|^yΟ}w8wq{[a;q)RZ\Jp< " |Q(E E *<]]Uo.چJTV<'- k zSHfBkRo};_LzNv~9S@1&Oacýiy9Z_*Ӛ@ &~%1}L-ϙgŜٳh+!cZGY}Ǘ<̃>/gxdJmq #:QfK #I~i6jhEm}QF<_bA [xWAbLf=}gŌ[DzoB*]yvr "³"QI|avWVt9@b?|c򺟑QK&|(K$ _!Qsdc}!_[_ R 4Eq'3w̿JBq=fVc c+l^bq֡u\m}N>?[ӄp=~3yN͚Ɠ˗dDZsڞZ!F7A?ܴbs9rb8pB\xjWpk=& s-z9&I~ޣ#NVKA++o>084ظ I-}4_߈'9˧H7^O|["֠h@:!tΣRH!_ssF#WU~ X "t!R"/ vi!/q?سW4_ẃ|n.IPZYZ 6qk(ZOXA]5@ I-)QN8Xnw4q,l,Ys\kJhКHlB+ ,~/P^xᅛ6 ˾YȆUXg]R&|e(B9OWa3{$8'!GRX*Zfy`$4&#coXZqtZ&2PJejW>444W/:]t16 tlZkݸ,gX˙B>O#a3?S:o!{hѾPDJLphA --=C9>ZIeo( 'Ch!Q+1/ CkA3hu*ugRHE@e( 0&16BJ֒(B&\xSfifPјE̸PR aL/.EH VnfsK X*Rn/~e:@$b=,t4 ByN All :gym6nJOz$iL|A kta_r°Ya$ FI%bwQfBh@jB6EUl.GZah|SbZVh^y0Z_{j#Zti+)$xp.<5?V*EXdO,{$8dՂP ll$$M1(j]'|ycո Kq6ĄF 5)Qc,R%D(TCP gTWy׬Z5#~h g>(@- 2*+ J8*.ڪUs,yb18&c8YEM.E c,Y: ?ݏ$ZI"MҪ%Xش5T*'+y4&0$#_2ѬpXcQő}lXZ}I{(hqyg3ka_m`bV\ŧ?i~oiM3Τ32R@{R-T` "ǾN7MbJod{&BT0u\{*zVzd|-99AQe D}҅Q?\<Č-R]G_JيZgh/Ԓ)SrYgO_h4Y}Q<~o.Ti1ւjq(H?&a5WU0V&I;0wvH :* ud2FlZ{IFgĥ8Ed\ XJ-SJlgϵ6ҖTw.7ad_ 0jte4=_M{^ -'.s!/;̈́_.Yf%8a;#\i !}HlbHmxQߪGO]HogD(: =? L< R#e貇xl}\B_0`&ErXI'ZIErĺqỊ44UnC{xi1slYeY6l_*|BK[&_)E#3HABk-#-HJPRyŘ$P7vXEBUfD)$5|z>4CI HL8hÚ ,t$B&e#?{G"P@Rf"h6T@Y3:8_րV(r(ӂv^uFo n]+; )΃=I tL*:L*Б(UrS!5نK>9^y2B7qʩR@e~w!ckZÙ%+8!T%8!t}GoR 2HY0@%+bmgR'^"Cry3z`'s>٘lޱTq ) gvQ(~l 280mҢ/rS'}M fTn'11SNo#*(>vT*}-l:@pqqKALlij7oBES]*D*Al I Z+$ wp Q&1 rmkp~CS~|M[]vl0TJ(al:+Jkcd$>eUDb_<볊0rv -BX2 yf*,z׊3qÎyއ|Wp? 5D&'*j?5E(AN;Oؘ1Eh/E~R)f 38$#Sym kpÎg,ff)sQNai9d0'5XZ52zbR>G~:JWQQ7'ǜp"- Ͻx`M:>K_"qf !4k8-Ilb[\=g,*8clj֑$1 TǑg":B37jŴFkarVwLk h$#(amZ*<-Ja=Oc'R/!l;l1K#ÏRp<=ok=Z'H(`$1+)uI$ǢvX(`/:T=!$q wޓ\kU$`T~?Nz&P`Ȍ.&n'l4P2sӏ}voĢu4ߧx1䫰qv'bB$I@/-GX3tV;*io}3ʶ;^`e\r10I-]X I"jpBd$81(z/׷?I.D@Z"%15(*"D:H$8cP(P ?БkHWOﯱtOIRzXV8DxcHUPӻ%!;K4sq4]]M!4HaS+8ē7/.G=b o-Vĉ($![kQ35٪ ƣ8qc7:}kUXA6W؄0$(Cj0I2"6u8Բf3FO5ʕ.rEnۙ3<gzڋg^|#OXKv*%֤δmh^^Iy -U$\1v>[rc]zqM(2$njw IŠq !4Q&fx}ީ=-/۞$!зMd)g PKĵQT;)e L=gُJ ^a5Ȱ[l钥/b-቗&0nSoA&o|Bn){Vï^ͯ^Ŷ3 7'KV(rوxK1)ǰ23p螕1.B k͌(J nXY%ͰE`Kz:N;ȲOѨ>cyo6nOs8.yEZ4cKϚLTiB`rr>ςp4bkƌŌ4=@)*0=!-0kniINMJ[Nbdٗ7r9.Oa˨~R~Xj r+&4 g8j4p82$]vxPa8 kM_yMT0EH :lڰ#b*-BD*"+ AD-GɡGF侗*ծ.O4ҥ$XTwZMz u-0'ɨ(P\K3~bf  "O$AI/$"6H*k@Iq٘@VBuo*TP0 Te;:8S{Ȥ6O;^޾[aU,ƥr)#),*HAʏzX'q)"bø %8o x wzŤNy R-_(Z+gaGQ5؄Rj{ H-iC\d\OOww&=2ӧ`EA`b^i3s==Ņ7=avΝ 0aVN 8Е*f:Hs@؄u?1- 'd.1[WPC.C$I墱P騐E[OXbRw=*y'.SڝVʛSmRB@{| k"$YuKjTkKKg KɟC Zа K€Ivb_ N! xZ0֢u>-6|"eĤ Y\RiaGƔ)S_7$&a^˾ϮB&$,R~d,ʕ2׻4Z8KeRX&ܸ~sDQbgy$1IX'/gY)S~ZLDOO7׀NSOo?jl"qb*N<$|m%(УkL;[[ب! 7g _kcZVGH^EIDh 0(\>CJtK?vR*?TJEq Rx%i%RY$ծnV<8]v2/yv9lT/"@soo<Ǘ\;I֬^ 3s.` ;y hs)T1xwbA3=us^jY:0*2#CCy:;*d*yfMɧ^Z7Y>;0ׯA ؤ53BY2ڄRq1~.FRI&x*Fk>4KbN]z!6H8pZ]&:"a@x Nqq->tVP k$S^(ÎsgլYts_`tηM>sgڰVD nbcHrB@.Ïi3M:V]>.PV^,,Y9ȇZTCB 0 OM:?d4o2=&7v$,~~~: Zxq Jj\sE b;|ݶTL~ML&%2LP\3N{S69cOSNOw.R*1sz睰=dA8Թgs߼u&9c9E5=爝A#|?n֓$ *±KNRNA&v΅QhB5- A;[%?v֋A*d EYMwgbysp;P^whpM|%K.Th4GNN=jPD@!ew^un*q`f <mg)T;^Iz҅ZR}[i6a^I te˿Ἔ{FF)Tȶ)k9S;w>Rt?1{Wr>D\V@kMƎp}NDLZU 疻igB31 !Q.]T}LѶYN3NZy>!U2:tRJ2W0I0s 5=i:KV 'w2<\g6BOwR|.;y0>(LJ6oa`|_Gj39]8>d:HO/WQy4>G8W,w>ƙGo.;h,Io~zS4jB#G,ɳ˨bT7vR+OL>( #$tuP.V)r)L4YWǼ"I<$gq&w[")h,&'nO&L3G_˰T<7~j7RFҝ N"V đog>xɧHCE!RI9kɧY(aN`KE\RWPw:S:wޙM}^ݞ7p+9|rѬ9(拾ҁ !"rR?-9>u.L+1HPZiEƂYx\CT(H9>޲׌0.yc}9_x oغOܑ(wv,iwsfqۦlΟuXf;OrA MW>=lݗ:^N`Riv"aB2 $ Sz( r8|ǡ̘3RK$p7eVR"-cݚ)=%ECkJlFs?sR8殠 .u?qe\|̙Nb tλ,oҦ"ޱڎHIƥ?0<:1d3y R~.uC$|!͗ϖ]Wl&GXfpdLAeqݘ5s&sh`xdk~r##(Ad`1D hfks\.;MuIKߐ_ݓIlcGQ??1rM',:Ws#d=:9X7 =0cR@ݴ+[BӅQVehdZy ֔A *ĸ:RZ2(a^kVq컶 s|c*'kzVJ[Ŷ~b1p)۱U_f#A:G!-d\gg@Fh4J(a^IBVJTD_EsZNJ638#;w.]]]*dy;@{{'Sfb׎ap#O>Z0\Q) HoV`u޽~xr~xüټm41Iwd8}cQZ4F"Adڹ>;ef`T*lX)TB;$c"RMF===i+w7q1'0c=_殺0uT8MIk~c,s_zbhS{^S/i$SPė0Zz"՛hT204B0S8pwP`͆ Uds l6K1YxG=cOg rsڄԓ, ) j ?[o+DA_?懿XF_G^ۃ1MDw}aR|ܝ("b3f}@ZOoo8XR7 Z)m [CgGv}nx!ttlMa``5UʝUnFc0)dyyaG2"&/4P,0k\479??c /YXӒfPʋ8r >w5(i8hy 9,qQ_n ݌Hs8RB"28@}G[@3n2<4P7jeddvn{v}7M o7C<=07K~?ab-&&L!b%+7uq I\ )qV ⤠^wG >zN,S)z!^>ٛydMqTQ364jf̚vetwvQ.T.ϓjږpW̛3{rn5HWQ, )ҞtgM8RтVH.oYIHb)dRn;P)?󷿻TVh!*XkmkA 4IrW\7 IZ%c'6c|8i #lk#eX?i}i+9wf M:>`@1bnn֯Ej=Rg4ڽ| TPY_??Ib#'1} 2d35u>h^<\nKb /|./,JdrysrYc 702:ntkhk6Fm|{~bHaL˂85;2e2ƫٞ׷&LVxk֮\;fo}|>j( HK.'fXn]=T|ہdJWn+^r+Vw|X~Mk[HDcqr[&i0<6´3݇ξK>^B V{qG٤^Yii{^67@T\2: f,3~/;Sz7 p/V[mb7?`hpZrوBQ&̩}l"8Dvv{:7wY L>i(cPvL6G284@gWjwۓO{s-TmjJHkN\fZV> $ӧNPP{ۙՌ--^K)ԭB(Jn/ɯQ7pB0w\:HvsO70kۨ:׭clXO.chhɓ1o>SNcKF2yzq5fͻ{9Kvu{yږfn[`3-ml6smq?ΉcIENDB` IHDR>aIDATxyTŹUuN/3/n1 (ū#E`1((D⾡#EQ!ĝaT}:=W>[V!AB $(.888888888888888888888888888888888888888888888888888888888888888888887l]'ҬYSv ۴u(mmJ/8}"1!ee5isW}zݺ'ڤmF_]Gb Dq "֮emZZ5ϒ_1S3-TnŶOJDds˰CAӠ"BV)i ڶDTv!Mo m$6;&v;]z)6nDDJ)0ʠ4Aehp~/;d7r֡T DgH5Atemf%ckŊ%,JiD@)akP;8˙sAi RCn*~l8L{p*_TJscP(5 ڽ%CM(EpLK2 NŶߏ;j6t2X~nhp11֠JQ  4K1m|:nh*,nJUۻoWP8>E8B!7a"=2hN8 *DM"ۺ{mF_b\@`4D3L." ;IDs YܑN=TT Zchy ;C]gfjW쨫1^1h/:!rh}PlR"RO_v(ϷL9u᝷ϒ9H+w=?>]=Ȇ8?ၱ1^S(iJ|:k (d?[r),RW?.%hnw~؍rf ޽bGt!N"ʌ[ѥq\ QXr9=̼]zhXxCBsF)'&gZ`T A+ARԤ-o{kǎk /C2(_)!E`*U6DY.v8KA5N+-qpk'P(O.`âpQmx Sá\Ï+ٱu>ƍ 3A8'BwI(%BRHL2RvR @ia)f~Z? g˩(La2uT_mB넞CiTYYQ "B*Ԍv&:{ڕ}f9_@ /Q89;~ZH` "yDT5o[4 8?Ͻb 8[)AqG`RiakߵQ<ȴ>C+}c8Yg]1is?:Z(hPZo6(b)9zȾ *Bm-ߊW~_A+9'Б GBq^:O/\»e)kTqUS]W(~%xaB!LCqXL{FqN\#KyIW/8!Ͼ;c\Hiwb̹Y6h[ę&Ǫ9pȭ{s {ⶱS^^QToj1 W⽍S_ߋơx4?1oլf$7$wsXCߕ+4b̹QƗiqDd٧v4}h# !&}!QQYi5<Pm|$% 8gQJ껇Q|\e90} &$HW~ŇT-Ql{oqx`\JQjn>{ ;^"[m41}C@eu!F~aEa'0't^̾c#@oQ9 5Ny!7M|Elj[\՛VloQ`9p l&x)My L{ʀ*d !\wvldYovGLqy)ÔqHcNX-vޅ^Y=Fqw u"Ղź8DC#؟-Hd Ŷ"ݓbY88 ЩuɗvĺOTa-%zmNl.ir>+ypҊaө}{;= ƀA9Y,[^O@B.ˀ6M-n69Ylo nw " Chծ ~`SP_ruLνuΡ2/t߱+NPpu36)I/3%B+7Q5NPZ1 ]l9yg͸q#ĥXk9ksn5~C!Dx; I>͹7/F)fq(vm4(E" pj?!ҔJm|Q@!s(,kQާdYYj(7r4hFxU Oiw]PloP"" 9fa&oJ8ڌI7CQ}O޹gsôňu̸uZ]LPmu5^4'Cvk? .E$ݎXISxgކ_s~z o*zCLN͙ԫ4kYڽ| }y>(MߨкpXPhXX2u4"ryGϝx#iҢeܬQ>THcWUxޟ=%'m E}/Q\m8XcVq8.\{;+O[ڹ/UQ|UBøx׊mC\\]&|-PlC#_p;=W_< Ăq'%w1%_֢ F'Cc#i~ =h;B0!"N<)0dGmCWU'GSYtB  )8{lZz0J2 oτTաbWp)*?ugїӀŐy 8bc`t >Q\IkZ,p=0av%Q 5Z>dhʲZٺ/:|u"R7Xaf+9{y| /;:KL1w3*k(Vc%GK>QeU ua}0aāy()g]֕n9>}~s )(%O&ҤI%a],E㡕 0 ɰϯ{EGjJS6g9Ѽe3~h>˖YRctA4ߏs6 |˟%Wg.OP&"%L<O\H>V)xvh|itO‹Kf}eO#D 'BYYFI3H}|ч3X:(H{%~En7;u99?ך2_Mgžسusq3\2 "4 NsuخX|fgO//P N2P)gA ڹ3s~/:t6y٣Ǟݴ@՗[.eh <&1c#Oߏs6vͅ\q3fB"}o>mgFH$~>&#~c _xacZ^tm-\ɔ)&S( O ~8wiq; pީFf0&ӡ(E]m5W0;DVݭ[Ŷ_8|xT*&ٸӦ5 Z(܂JG?؁@mc՗+0Vp\[[Oe3+f -7\6tIm=YCG>qq픥DN JkRT A|m[7oɃӧ'7xjJLl_`9~T絛e#&]{%A+WQ3X8m`G㳂zz.;iϭAkUߜB@pP:AXPZѾMk>$ڗvj? q_{MPlgԚ|TDIbX *R3bj~wll#JAû2=aBD|AU3ʪzY1+'|CB kHrh,责LbۣMQ]]Ýb/1KܥsbQm낁IENDB`MEND! yubikey-personalization-gui-3.1.24/resources/images/tick.png0000664000175000017500000000064312642452141022656 0ustar klasklasPNG  IHDRatIME 5+أG pHYsiTSgAMA a2IDATxc`* ]36 OnIۓg"VX'g& eop+^0dDfYii_~3l\(FŸV I3WWU])MJJϿ?`ͷ`2ߟjqj2h+k2 ^cönhaĸ`>]AG࿣ÿ޾i?5P\+3ƍ7WWasõW9%ٙ>2GT:0Y,2oo3`Ռfq7 z>IENDB`yubikey-personalization-gui-3.1.24/resources/images/right.png0000664000175000017500000000130012642452141023030 0ustar klasklasPNG  IHDRw=gAMA atEXtSoftwareAdobe ImageReadyqe<RIDATHKKSQ |/e)HS *,d5M RlFbmpLt=9'Y`u!\t̜Mpsׁttt粳3EjӼSM=R a6:K[Ldbn~:) ^2^ho+J8:D+pq6pC{z]OTz^&I'x|eO$xO@-"^!4+`?>%M0V"*lb"uJܡ I_9]PXJ1Ҹ!ѤF&Ku#$eAڶ 7up˰A\3nG|a6yܘx" 6MvEhPl9ܻǔuUdp&UhDײPq5CA ̪WNĻ7\IyIENDB`yubikey-personalization-gui-3.1.24/resources/images/neo_transparent.png0000664000175000017500000003675712642452141025145 0ustar klasklasPNG  IHDR>a EiCCPICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧ5bKGD pHYs$$P$tIME  '+4 IDATx]gTU~vLHPX@EQea1-5fQuM *fLƞaӇz`nnթ[u(E)JQR(E)JQR(PR'YgMũD$N'ӲExI."uG~?'IN%ԯl:x8' )22*Ghw+'%W]yaeUe'J:ƐT"dFԟ_zV'ʱ'^6TnXP9B֭gS~v]/p?Xk/.h#mff@.! @П|juV~vsCN=c|7_" zO>cY: DJQ\c@l6 =b+}(U %W\qӍ\{ZmM Kn" ̶c0Wה}@ KɽU;yփh k#=gzmj43KT p|pרI}7:y?IɼtM^=t )%U{ڃ*s `1q7=$.vc?68ޏaA ₸P9Jmo6|Ǟh?ňcF-?ݥHJS.\J%B *_#oKXT4$]a6aFA,4m]v38 oϮC Wh"Aa&2'!P\NԹ"Hϟ2t5yCt@lښ:z7Nwh7.(z(]pȇf>4U?x\|Oyi`7T$B !ŚGw]3 `s^Gi+PϜ,EHi7qA8@HBū"9+!>Ax Ah::}<~SZzڢ2bO. x듅/ln{ 3w_0Puq0r9 uVAc%tݍ)>d޼_x~3Μ^}?{z`kxb܇Nq>x҃/ 6Wo6Ah08\6 FRݠ23@Bi4hwE21W>pgkBcf)Ki5 >=B0Lm55%#SZOeM|l}o|.yﵦ[6׈d u9 Q|5za3&tgm-@ 7_^bmS~E=a&6WWvݳcmCyx[ !MǨ&MנkrgCJ,mZ_|%Evcm5 AVDLA(mw eN"aYǶ$XrA)\ALӴs1'Mz{>öUF~v:xzxza*Pnm}7h߱#Dd'1p"HK$f:љf "1Żo۶M 4" D>b4Q l)<˞{|[:Y3^s"X +B40ui՛otϿd{hJm %:y_D9)?(H`XU+Hb;5k|_G[7֛e !4H??waHeö%LXtޣæ/=SzIN?z3f}r !HJRTyF)PD9!! 5 G`ak "m+ʐN?3vu5 AϪHKN)#ApСc;kRH 3z=_iVg䪸qAl'7g pB(C'D$PSS 6[wTDҳ? 8 ֮}L껐#?ૅo,n|u퐳Da8 `yC% z`p?N˂,^Ha TUx'Ҷذa]Cڷoʷ+-SI0NNrP.)w`۶CQIJPVsN2;m|<+0GKHEhU슝> 52z`2׉FOc﮻68~@`Q+D3t]`KƢHh$`ټU\X =a됶5j 3jmV;U/~hQ޵2acG )U\:q )?NgMYʮl5Mxc| JUhJfMO6 a}4gjҸL#[_k4U>iuHYlej cu#6-Hʍ!I5ضAB--?@U@Pp1!Hu[amgWC2BV%7AWAA#P p040V O$LLv 6lW^zN2iѽ{rr_>My@rb]S~=Z#oK cz\ *ڴqzp=Tńyxb1 {OtH^jL+<\_tϻ5\›8BC"G&]h4zDSO?}LC~qՌf֜́) $$N6.:?r,+É݁ޝ,q UO5fFڕ>pK}D|U7Rt='ǖ24OF |C, ֜ 3v79D6 h_aDc_ݥ=:jLRm+Eu" 2̓D"T* A55ܦM܈cGsI+]0~􉇎7yΪkF,5kƒ0Յf s ,aI uvI$|}֬E,CԌf[ T"Uqݱ[*R -h tYװb4C 8Y*-*) aAM n'4MǞ葇gODW}p>cdHO`ruŪ7(%ca^ Ȗ6u DE6ttfUe nr*ם x}@! |0 o!!G"x,X,DoUW^6hK'?|̝/۝-Dˈ۵ܤ\6)i+\^a"F,G"g3SƟrѸ'_#A?XV9wR߷F=0%a-H\S~,@4[-Bݚ f@.^xO 糺2AhgKVxN)2 /]' NM3lI9$-5cO8񧌹gGG-ϟrfwWW6vƒ++C D%XJh󮙋A-&pٮAh`Q^¡V!('@ Ć[pE !` A߻<8\ `13H$qnݪG}©#uyq'w}>Ħ-[u0t90PAz0gC`O8ɓ$Q .Q$z]-֮v69Yw=ƍ&4 ZL Y}aSg`}3~' wMx2libFr9_n施{zGG1QGcs^xi Wnxȯ]<с@֩ ~غy6A.(CJ*Klnܙeov qQ;ՔY_AcHRh 8x?O8;tI o{]{4Ѕ@βdBaB2u=9 `CIS+9&8W%4-[p3j D60 dٶ1?]razzk.={:$<w;WiV;h~\J^V<"'4t `3 0@Ί6RHDIp1moJf@"@,9Ѿ 7^7I躱0c^ŅsAz~NXTWWu ^^TcA2#o9FSGjTu542, a K @4Mo~(?uofzR"ƣ:o}s>.7A6zEz*mL?I & ]$K5t83@GD\c$6;BuAHeR0,L2y O{Ֆߡ`ƻD-[-) P8u/\&y5}CkWHmL){ՄCpB6o-hT;d 3^&n'iz/#]d8OQyEM~~{$pG׬^}EުPz0*Ah:|.tZڠp\KUh7K5 >#vWƩ $UJ@hD2lTn:tpC~Yvx/IS:7jTߺe# gR:*B(<(][?d9}@2ApW@ҪGrsDBGee9 iNճ/A?|C^xJeO~\ %wK^JTy X=oH1R(JJKɔp&[n<(Ɵ|c|d ^  hU&cQr ad/ I { =`ljB+S)S*D*i&E1|'Lr1f~}|vl1#a[@pAS18 ˝-Lui#@Ht5{U@ףi87iTIm(^O?ȑG/y%Jftkv+{!@d0q DBmNEwICGe7h|mwM$ D2C=ۈG~_LlCz[Av&R,$I _?v@5.0 ۽# ;&n~]!t-BIYEDebnݾYU0^x<G2F&iˮJ`p5Wڧ[׷? uöOnh E0?,U@5h FXqpCva@!`ƼopٙqQ m}5IS`7AضE­Zmݼ݇NP#(.E:B,jQ#7a߱ H=pͥk荒rjq>ɣZ`I8r!! 0f~9H ^{vmi3|QyƟ\Cx/GoO !"Xa#ss %^B3 *۝ohЭH;Tt8bF-ڲ}c=jc]unWƸO=o4鰭νq%٤[ o3A6/{=H7 w=,Сi^14TV5BNG[|9h۷߆]HrC9W\W޶jXmֻ7SX2,ۆaDA?mm3 X*QB0=&\W 'DaHDz\x4D5 =:eG|wJxPoxݖ3s%&~F@)6JHۆd`f Q>.d5l̘vVvؐ/c:fؐ?9#X4 cVa鿅G55L>"LClB ~ao׫KDjk?؄{/;ݻuF>Q[SKր>{ӌ; |2~.GԿ rCwf NgJ!jF1O|.,&%mɘxTs6z_(}`pץJ\u|=5l rZ4oP18s`یF, t5Ez}XƂmo3E`[y4X66t5 `q)q&4v„ ;S ͨ,dafP Vaߡ}NF@h6o/~/`H,.=/4V&[qoa9H!Z@^}}\6~fzRW ҧE :Ë~- BBӈ/\]-u߳3'ާGk+9숗>[6mM m5&ׁ{/{h?[e3tpҀ8@X}^O6-w0$ v=n z[ߋgHh lن?,f/Xy#5p&0oPf4h4L xf/qߝW$GY0bi¦A ZyOތTR˗N*p٩0>P\ v&˲p-pp=1|7<}Mѱ*X1Ⴙx˜{@h[9A*fF#H$ʐ͖\u+s17=ܳ+=Ns) Toެn ”>$\⧚竮ހ?k-qxz)"CJK  |8wzDҭiزՂ»:=[G&)p+$QD"i$iz b3Cǟq6k֬E_/_1zŊIE pnr/Qt0tV2\Rs+tj!>d)N:1!h޼ Hu?C\|<M0>-&OC( Cx΅ s潁ӮxIuhԀnDP^JQnߐ@4!G"6ڶlIS'uqW*.$Eo.M$l' ȹ9͘zl+-mi! Ԑ-{txȣG>PTav߼nF $mAde ۦn{uTY>`74u, jQSSӌFrp_[vm/'0{[cja6"NbaU6viaiEFp/!H6˟:wY.D= i &MhGߡ]ڢ~Bwy]t˯h|9+]ӱu[5cvNsBiYS{:~9\>\p:wja|@$&UUtI'_3SEzZ̙c_`(H"֭a[[+WiKmv7m8Z݅ΥCSto{C4i9?rx1~ (N?cŬُ"r5[a-o`&?/Zl i9̙.+,uۆ׳N Y-mHYh{o}}5ihcQM0ʫlTYM7sI&x͈1arF)~Aٜcy܀Ɯ7M&G cf7oڔ[ޒ rY:͓O?sɲ//Xފ7j*+˫SGG *6)&ǍL(gRqn٢ 7 ΦqE9_͝TxpdJdYI9dJ4[DcQeɘɍ*2{*./-㲒R*;~ŧ·2Q<[*T5r.+-47iF.+Is:L*++K+x-_vO8i}=pV3W+Ź$mZϿ ΛIEcQ#ʦ2tFvlݎ' m;&U8Hs:t"̓<'+o}[/O%50"3.481 -* y4!"WJRU>8#{,'-تMHD5K;#e.FB3"41-E>(J$.))%$&hR(%!",&)(#)$!ݯG"!&! %H7#4.1J)(*R#!(߯J:5)>9?rK*߲Vq}!MܫNV08/3 *)0=*:'&+`)!$$֧I .,- ޮQF#"'#5$0YSEz\. !&#"$NO3$bll?9'NH5JB4,۪IP*<82  )ΦNN=(,(4.8"NEMjV9*'.S>;&%!.,(NٰK# 0-4>."/01&D/C89b(1?Y2 S)M5( 1@T蒩+u5J2?0)Y/$%4J~)K*.MdIwG(Tw%lT1=SZ U]*e]*T%Jӓ.95rOZE Eu, h9fPTSӋ:d+/7ҢXUjIsUb2.+jjA/0+U\-&|UQ6^ҬT C_U+Rΐ*Ԛ$ Hw\eB\=ɽӊxFX`TUU< t; ɞgx&UKjzraV PuWvM)?zj3*UI~+,Փ/bLlHJ:@UuI^14ٔu%ׯWU e,jR R~2,]2KA%W1IƂN-U#%|Z󠗔tUYhխg3id%=s^2jB%I g,YZ=//;?,R뺦`4=I%o/ZjɄ \J}K-\ee,&5ee+; N\*M$S!QAEN􊙃RJ`{/4eIt5KT3]Mdj̓uMϫR5OM \%0 ${3Q $'9QJUOLS {;Pt/T_5+UTOR$]N0T\-R 碣jTE-WUk5TUsg\U$הઠyyw9QLW9TȪWj5+&\— A炠yR&Ԧ+Kզ[.֪@'i굠q#U E8>*^FVH}8S?ú!bzM\Bg8| ZquC8aC YHƂ"q8CX\7Q|Џ0BLL?e y<}FӜi%I63lN-ĜӐP,X״ "TAI!Cbؾ)6"pXDZ ӄOGT<&@e,|Gw·>A+-409F`*Qǩ͖k.6X1,?3FA1R,T0q c|:#rDS KǨú\JYD41v"G1THB1%,)@XE8,o n2km2GZҕBP1 E ƀ`$_Pقǘ"ٴ` \4 2<1K8@5" iFJ% urEzL_ﲺY&pb3ʖh웃CCCÄ54e-,@0fޝ(3,ƨ`E51gPȡ7?4U!EZiŕm.F")Bcx`Νo|3T2; !|dZSaiT4{3,H816M"guDv~ hd~"HZr4(Ic0~?4>H.^%w T ?'a9@L+X|XᑀT,w4ȶ  ~ELvz/ `RDD#}q;?8 CTw). AXBV`ֈ G8 LA\(ir(؈s)"04FpdvG+Nr`E#,& r7ph i(e 36 wj0 )AjҮR(G}c@SW 1 1G 5ܙdJ#L&[zgƦh*ebNJ18~ ' mDcP'(&H&pR/dQ_ |gR 8NCc`(kA5ŠE>=y\gֵ"/>OZ=!( $!w"c.6pA%QCi:Qq   2ƨ;+cEXcsdRVXH`oacAӔk|~¡ΝNBUA=x*J+&i#b[;G‡:/\ GiǷDÐ" ,dHB%6;y!珈Ȇn!ĶȂB_Ȇ,F9Z3?';P38PA"-LCE4h f:oA 2H( h!!Jij;:01< %|b-fSθL F@ >Y:~!ZRԀ1bXnd6ku𑰊Y 4r)0JI*FTTaraq5 Zr\alȎ@LQy`l aǤzbAfwߏp‹ 6~L~3jOBjҙ0}g*;Ss-R/Z!kfAiMT *>N&Lp,-vsiPi ^$ƀjւ'+CYH3 QAD3aoL@7EcZ!LĆ 6?BZ@\+XW4v Sim ZiBkʁ[" n0tYOiPڂ.0N.SY Hpc4 HA|Gln{ЧY  lgb"‰%Ʋ@Da=Ρ0_ZP[G9 i$P̰L"Vn֒ n@5Fɦ>]"ELðS 5P!(%tgkJARQ''Va K ?QI9,L@Z`wQiEjoޝ` ШwҴT]Ȩ `N0eASM Ei:')# *‘(tЃDcx(RG=cHOCN&,hVD4]WB=ђ :ەeü$B!Ѭ_ګ&n(%#M"hğ:B]h | 哣og9{vlPnT*Iq@|L,THB?3xҤݏ6J(ÇjN>=ӭmek>Zov~СQz|uv}b~w?ZxgkshTY1EYzm[]xR{߽nwイgU4MWyv,'~s wew|fʫknnσvl}Əjoox*QMȓl[_] XD[}$c:vc_v}Vκ/\=>`3Fy۝wtLt];vm}{n]S0s-1Y0Wf]`fw> \k[ݿKUD~-'{?.?cnJq5 Jl]s𝇏jM]kk?uofr58SU7=|O߿>*<ܙyjnɶ}\yʕ;=}lz\H o{||ޗ<5u{wqVhԽ3go^/7nw'Ϸ=(ۯ=Vk[sxm{{ʧ7~)Buk5-Mw?ysݿJ[񗟼ֶD/]޿}or_j߾-gU1칻vm'=ϾM6oֹWɊcQVٲg㋍wygjs_Oԃɿ8k6{Txy~gy}zR՞gv:[7>fԘ8|em U-kg=l}O}hS_\ hyg^>OΎO'O_e6ɩ{5%er3>j9y{jRƚs`.WV+i~ĕϼ4M2Lf*y[}V8):hYsU\zwS7#:99yAoS'=*G}w}۫?į7&6є'&rLS^Y^-ZdCIENDB`yubikey-personalization-gui-3.1.24/resources/images/plus.mng0000664000175000017500000012221612642452141022705 0ustar klasklasMNG  MHDRd = TERMCsRGBBACK)bKGD X FRAMȏT IHDR>atIME  v9IDATxy\EUufz$LaEDp|ܗGE\_G\GWEeqEPG}PqTĀHB$$=}ﭪd'::w~田Z^+r/`L3\^.޿066-_!SL!I|Otuud&z} bŊݦ|Z͛QJ={(ofyrB0{lڐRm66m Cz{{KH)Zymۨj6{xs2{lFGGT*\.G.{0{l$!^R<ϣX,1˗/H)1 ˡ~iӦjժG)^VZZZg||Yf5^߲e JYfǓ"|píj5-[ϯΌ3m6æ455h `Æ  ,}.]ʽK̙3~Gww7J)%J ɓ/1 q%a(QE>P(PVell B&MD?0lx}gzfDQPf=V !bEGGGhI2\*5wP11tǂ3&'`###0uTLx]ƍ98#Cz8fΜ9j5) ߿&.]{Fu1m‹ż)S'zzznR4r8P(1q!ZnJ\c ۷oHpZG[[l^'UFJe;6|ŵ=گ_-7g >?{g͚E$>g8OTV{l$-mn:R]pЄ]zcttbHZEkMP`ǎtuu100@6V$"fΜI?---!^SSbJB.kYy?S(m$)AkLFs~ϙ|4Q) hryI>|<fc}:::ZzzzؼysOw1_][d.0c5BIX:\^A^v\L2(}8ٺu+L8Wnhɓ'?SmmswN忤k ct!B"<5 6ԌEx\}מ7TzҿTOo!亄aܹs<^Yٷ?8r9Z`c@@XF`1?mVreszg9~Xx*~1pז]Ks X#> )aFqa I]`bq0 $Q U"`<ƻ9P'3AmW}( R )pȟHֺGWk(!7׈+h`F"a58X FIJbg#W~#Eɳiu8JG4ri!S1.5x ?P맺mF` ,"xI-}RϽLNc͇G!}qn) Ȫ<:6Ay>H!"Hcb‚nY1&X^dX AaLC[4p.tm(mLӞozBE s?Ķ- @ءzJ"=Hk4J*@X!IWZ6neɂV޸g5̈́h36EOPDkB"@ՐX~gtt,ٟsdG7s5~Z棎~6Zm=yϙ71J>Vy_כn#?y!mWē="UHw^ ICH*h¤ؿ$IDmd 6G#rO3}3kvu sᶡqLOkB kcb?:V}OzLW{;ӈ1aHcIz [A*Cg-.&ЩA ֠$65J{Ȯ_ϟ^6lh?gያ< ga 趍};wu5̜`oNf^У}>&u{=yXDDz@ܽmTDZR:C6u#c,R~|I3dprx1LBY0C/|]?.{Xk9W?1dAt8P>) X&*|iGXp qbhxa DYmfyT׺w%QE0vWI(@"2cϰu:t׭xT߱W@R~)7($3!H;hWHhn?ܯw@bW!V+TTV}k-?t ~#qO5)Ft'p*TDL /~7g1=z"\Cc1ha֠ƤOENH8甭9!& vtqŬݹ{Ise0y6X g65H+AI0}>?wAO ,4wҒizhYvCݫBtwDJ] @,"۽C P pCx1fw[ۯUyx:A]6dCaFص+r³ц3~m.2U^.$`w.޺ ˳A(/ 򈴌Su{P>B!{jv{9 c FFx^7mNi zJ[`RŦEĕ dUSBF'D䲔mukXuX5}1Rc\KӔ,XtJr*uM*-8{zeǺ= R@Hk!@y+0V#T)+!'R QyJ#i), uﷀT` ʃHYEiie(:eDqLy΢p_ y`3{-_}:dBZjԩYtHQ=,حo+ 0Zx I\'^+]^L$H "NtIIXlXJ`56ME --΃(L8C6"X+QeC 6a5}l?~I"tі84rh)tLiW_Pc NQ'.^Bb!ƕ~I0֢}q$P QQd4s)i6" juH\&(_ ]ĦimaE?gN^yT4vn[}|nMl-SQGOsF SK:(BM!Z'c] ֱK񂐠)Gy{+X0yHdcV5g%k1/:Qiٔ-Y`-迮}|.Ny4DcqZ `T+, +$V1Cy 9{naDs1IoIkh^J#C=p $37TۡB3FHZ|dD ^1w1W}|[|gZ ZGNҁ(ˤk`"P}Xo)o_DEHZuH:t&F,Ę8!Xm-TN!C a%]/ߤ|凩OA)k\-!( bIT,6AxQO D>'ϩi}зs~eQv2IHt%ǧU0BQy>qLwܳw©o]H PhO!tR/@cKP-%^ybVML>ӌ7mteF9yF$u,m#΀M"[la|tk 贏cd,r.mBk҅R)PU[ik5|aE"ĊE=XXq+}0 V!86<=ʣ+{u_Iu~5&/uפcLH>*ȸ@X P,)vpW4k1]}j\ڲSjZ fl`SxҰ$#l/iEPi-V+ &w4dڳNi:`:#<j538e: 4(I#>0ikHcl \UP28mߺ93g>~JmjWC/!G5{^J|pT=&]DTZD(C[a("ZE"Qa&[Iew`~W?Сz6 :ր(Si;41+pl"PǍ!8YP k܈ r)^"5y9w?5SIˌàVE-tGz5)v!qT KR8ҙ c検9na#R?ƥ?[+]R)` \.rrE!tF -8ʙ.(qraA'~6K\}:{CɄZy@MOK4*_9/hIkXX4 {*)W3)ï,9E@(Wmw KrĊ漻˴ITXhc!L}h2MT6`p+¨F|B,~6Oa=@i~ {'KP UJ4UQO3%)3Z e,6  Vx,c/ɇ/X?q,ϥߒFMZ1XːF%]nX2M8bdċBD 2V.x8m-z$pMf}#jґ#\pf6;MXʡ]?HZIѥhPw={. .c25xhMeL Piz!6A~)MmTt]bRpPSˤins`k h2u/xM{| cWNBbLT#\CʳbXKtNZڴիT}-CP(C!H{sIT-1C4V#*A uܳzl h K $AC<#,Kyj9eJz8ݪ=jξr^Q):0Q)0]g]'Ic^(]zV:m"&loڸlm 2" /H ǢQh8"$ƽn <#$&}ڧ8v\Þl2~k`DU35[_򎃞_Sw=Ԣc. [FvxV}:+#Cmv-2%P+-hKsoJza2ݫ&vGH02C@wAVT7& ^2AD1Fyi/}%!%B$I^ۻC(@%1IE;;wq?46' ըI"`[RiB d˵%z3~id3ģ/huv*@m*ti#dTȹ8EZXʫ6sTf׽H<,qJ+eZwd .ឍÜt6S5jmLZA6xʑ5KwP]"dEKiO}{ݞn2-ʸW؅i8Ƥ|?McࢀQ#vt͝)?n2[ ۿ - Ps-^(>d}c6kK|e.sZQ)\2% 75 J2M xDf֓sqe{5ݛXWC'h2&Z%}I:nMzL} sYo_.IPK=J2ZB6fdFxcEY}H =㚿툸i,fTg;@lj$6龟Nd]_Hwoꣴ"8郼o0cXi5[0_ TӰޅNJ)X B ǯR#Xh_MltL\^^'eJXK1=He{B&h- lbش> a\Huln|*QFBΧ+s|CLia{>o3'HᾝOz,e;F7oJITuc]P#yBzb(R-@Jh7m`uS2w젲v֐sJIlqSYrпsg~*e;\ZJ@ >^}t:))D1z{w]Y7үE}^1YuwOږP``tf[E -8?ଳ'Z=u}^;B0==TcA)O:Ҷmwl]Lzî[5mSmnӫJ.i]$[{g 0 ZC Io;)|õy'ޚTadsdr$Qr:]Xo (롶&m" c6:!ט)QX9) W)/ peuH㐴6FKTr" _)^k?Y?=R T#^O\ڱe*քʪnļyxa$fN7%ZXpA,-n w6OlRdXS]+G6~g!(p=PJIdϟ:ο'6ywn#,.i\EBOݺ-tfYn͋zt'4,|tY#It:):'t7'K:0 ,1H/t"H\hfI8p}a$G?1}Dt$2yĵkєGYҭwS 4g.~#{.H˴9k<]Q <ޒuH֏rM+isF:,14rE1x*k_$17#ߞ]޺)\@`J%()u0⯖^ƌ0g.a%V] EnXpMh2\^4%Nb]H[7=%}s(#h!ٖfƶoctYB ^3>*s/9=kex1$֌nu!CZZ!1+I y<1v? 4͞f*U- Tn rM A$IRC &=A=ÀLM)\U!^M/uuIOWl@/`h/S1Tȱ>V„>pJĘh~adZ>ƺGULa&ۥi7鼼tT(29?]IylArbWW~>~=Xx(uIaq!dcꖩc ~C&]?{c 񢔟 I'{O|Dqb Zz"3"eWl*5mxwF=QbWr-wRIBև.9I$0驆@*7]7PuF`i€bCz6oE(|-OFKӸm)ZȘ} 朗O?Ge$ wL=fvԁPa4BsH2z˝Dh IkVx{!ӣZM%ƽ;0 D: /0 PI/V()!N~/3eҤ-[X׀)6N0/ys*ˀ"Ӟ@o܋g$ ij H=P,^3D} ,Wq-Š:t+!Y əu_HX7 _L>эIT: +q쓟h=i~X(N^p KMy Ǡ2^ZEfJh?|c#GrD/w "Iq)x GF 0~Qd.uƥ~2QXHt6:%']ToL~}׍4<^>^129;KX5^}7~y<} ZHqҟŴ<JU ;Q[ZϞQ=˔G\?1E/>(%)kΘ?s!n oN+Jgd{vrՋ|NsLqp[+h?hv|DkD^0;IaX8B 0$jHOꓜ/3e&ZD ~䍗-\Oe<)C[Q\NLj3eR7&ˉ/M2*X+NxGog˖^̘>Rh)rsX|o>OLi{>zA?Bt%.Hr>>o=6w?wON9[.p>@Gfd3b%Ѫ+t|ůg_|x ] Tʆ~n5ivT]1dgYri,R)B}`F37l=ߺ^N?e1ǽ*e۷oZf֪Xo'tU3Q#15txHLSYvo$dCL>1)]˕\MnTj &;3xV|sxɫ#)naBǗ/Y_mEa=b Ϛ +6!pa2SbB,YJD坰 rg"?!۾Mgmls3C;(Z#5Yw|3>S39?BZx2E X^g-ao okdžvLH*tdwpm8%[2ʦ1@cMc#iZs9#Y*"XIvQ;Gyיȣڸih[rAjG%JBYnje'̞Lv,Qfi1h0C/0ַn0Bg BS0:٣ I4ϱ|r`|`li/X +|rYxyR/ͼE]Tzh"{Joff$~鏛9M7p|+g;W"2>l-A"aT[Pztu|lGuF>kVQ[ʤ;hHû|{xU7y'"%?ϦMxu#XmA[2l9,>%|9r&>焙 {+Dq첅m|\tŝ\y[^+t U(ΙKT*#B\ Mpv;0i.UF֬n IJ|<-(k:w[yTT Zd2U23CzC_:vo>TnHCTDNi⛗/ZgAϝqr-(8̿;/b)(IyCgqr3,<,^21=oq v!*X5LcPa2CY/X>w!G? i3Yܱ@M=.{'Cf3z 2|~>θn~C}V:>~R>~A-1ժFlpz$,GVb+6!-G"xKE"7A~s]I YTd&'?atyH`\#wOjEmMRB M16׶3~.N"{6 0ޚ,q |P{GXXB]|bEyeEu9ɤ63eiA& eyφi8G,q"y26̍<´*[JX yn:xzi3lӿb%fh4N=o{C{nTgwMz~&oٶ:uv35GIR:5jHh?yI/9rmbK˜"Wrg7񃋎d|G 0Z|(\Uaa-S:h`|NZ epͧOsSIU5pݦMIl MI$VHH16\\Ie ! =|8y|q+$&3t_[~3iT^vX VgZ[K_cFWD3Ju9xڵߊmҔi'VMb*>2.a֖ѥ*h2ӛ]7뾲?렣|VQ aWD/}u)rOCIjVIDQq8ܼWch]8QOs}ײ.l#7VOQێddd9U5L ]wqg?EEM*ϵctzHZٖ/e+rysǫx}ij<@ lg%v̷Z>~/qFhy\?v~'eۈJou5??P >L!Ș󿳊?gJsK\4xV\w%= )⭃Q9঻k|͐XC~rK{9e8`S4751ܽwetk|_}C~7ߗj ޔr2aL 1[ywsp̤Imdsҷ| o8sND^%O3ncW\V "d{'-لGW4C!"MMO+n߉(,sgu/}D^'OJo7 km3ȀhM-r+VAȷ "9p~{O'Bk!OwZ/ܧLȱq#Oɞ}>erg{3\^. `/}>8 69JIENDB` IHDR>atIME  v:IDATxwdU{PoM 1q@DatAuӠ3AE$~: fA@DAcs{W5 y:gu^]Z[c {eWV.{ `0??֭[)O& ۉa?!$ɥ^g<}O* xV -BfR2::J__C~QKK DGRc RJRO>'T*^=BGuXf sssJ\:&N? Xf qSVz-HyD}(b֭ )%ZkiRQ|r}<,:HXX,zJ%V^M<OjhhࠃJw_3+W>.1i\vDB@LLL /qF n㮻"Hvڿ===J%x^y=ֺ(D"jj_f)1??!&H=^=AI-ORDQTwBj]\\.?w!hhh zfR7gwSBcgze˖^]Aww7[likRTx֦d&]w]L,{TRTѣ(l6KEDQD"0fllarMMMR)FFFtA ;oL,00orПn%XB#_b|իBw}la 0w%eT)T@,e+8dvޏAJZ<c>o%2]l!@ښɖ湽By~a_#,ʹSV (&LE`7QӃR T=3BO13=L/~Uʗ]nOlu]Jeq5RV_V5ڀB 02`k'#1{k##}3O'Qc-#(0OHƵU'mL2u#%a2 96å=8 /aYU ,I?L3>=F^s/QZė^Jjq&PR>:0QĶʇ8ǏH6[BGgrGˁoby{Zz q-w3N&v,'VdH8St5Hiz#߶ o ˍV6 `bT+Vm~@ijG'6w6wL-25b07q6~ٟpt Z ( QL̳?/y8vƞw(ЃlR @]k4<ĥAl !Q@_ +/D&\cOUɷ4!*e4?n:3?9iQb*Bv$SS,۬<@F32p"ds^Qo<1k CmL8gGi\^ *J8qj|6@aXmV`́kEυ|Qq=Ù|t@&M M4CߛAˬ{[:H/~ENQ݌V O=H۷h1)|SZו`b)$t2W?]#}ND jن ԌDKc˯~L߱G1}Hz2̺b<q F#<c4Fkm. (2ږq}"k2=<`ryr@scޞƟm#b5ĺ]AZҦZ)h,Vh7s}c XdQGQ6G Hc@imS6m!\GP T JYit){ǖq=/`~@ Fn_q.MW?Zr׼\َ*P%Za|!P CFYY01 g˗#MЖQKh^7HL8c Bp>9P;G@2 PSXXHetjD{G8:Ns9:T!- :8C, fpbn9/>i1XiϿ_"\Չ*BاRmoMp Ѷ@+D 0ںaC1lV=Hks 1ؠ}LMM1R+!e)7r{3n;J[v5~:f8un 4pqbG}'>PCjdX3rie 8m ¥>ʹ⠾θ-ZH$Hk%bӐA6?Ex|yigBz[\@ȤgC ?! ]cnڷZ=ofb1*F c9!Xwt1haPFzi251}-|R6-@Z),7P)q9Ys;ʘD*m;4f)\ 1``41z׳2~ٶf6tZwFk"A{"E,VqLU0<ᡌ!lOI.>&F HOXwEﳺd4B|)16)M)Y16@=e+@`O/;f0_h{V@R5דڰ8 aQ=le'TJ6\.S"}"Oz$ )} DHDF!~2A s2:7Ddj=Q)-)!"ITQ")0H ̀T~`\g[ İݮjvb8MSY֖qH?`YzdA5%!<ֿg◌$24/q5pec,d RUe@9_2ϙbY@*_ *tA2`3l)mg±|8b~`r!R4R٠@D; zLbg';3MD~H<4p:k:!kL|G.&цnnr*#F'2Y䦊F lٔCZ8hF֬Ȓ }<ߣX(kqn%8( / -q]A-h%vgUdk R^!?@i1Sif[`V1DZsܿ/;/WqP):xpz XA%%O112̟# xK:yݫVshJڟ-;>$BK֫h?5>~_ijonBƦeBJ&J cT] +`[yJa'Њ0H৒L7:N/0RhmB`H7r9]glAMmv!pmLLq4_:|vBEDJ FhFKo 33>َeHlXcQAwDOC>Y ҳ^xBbj&lg42|隙*SIӚcW}t Owe ȆFP )<1X[QҦx*S qTmq($jс>mDGBkVt[8=u}Rx/~Բ|NZe6HG7k<\q4)?X@@#=IoͿWV 6r< <[qq84Сwµ R)= <ȎtAZ ‡PF|PUd ]l﮵_%[B∹b)/Y G\5#Tzn >  ј8#L=@mȐHi:iaIK<]È|G635(a yA@ͳ89AOhC \h2(,g]{Oh͟6`n`a- pg"\[EVR،F<;l3^Q4PUT-7IFsέ|G6uTsy 0A$0vZ͆8Q٭CZJYj1`@@dL pWPrsHcH'|xxKO! ݇R+$M 4f7gY.Ԋ9cme9(* zQ.FDslNsVA&oX!5RqF!  LI8#.51{+9 !|J)ocbDb/$}'>ҚK?O Ze˹3wM|i<1"m&oحZփ.|> 5zA.6zT O@ߘ&O-+f](m0(*(AypX* v?#cv\UOJtls Lf,0Ne6PlhEKIZiJFq?K:I@y}G<u+5+P^Tl.Zb0AT[ow5UFzeYe OИg{ƹ[rOFxW %tK-:9h;gXΡ\nf-( 0avr6+QƐ1}{st=, 4m;7o"$֯A#Q=0 P¦|7  п2o0D%"~a3H }T* KU)R27s[ٴ~ UF3^o@ƕ6d<с~OL7/C%xFCQカL ~eW^Ͷ͛ȦB8b:FH1jj-Ølm vsT옆[leCmNg$[|)Z>km w,Y MUsq}7N^XD.igr$2Bj ygpx u/ݰ(v58yg CT==ti5R̷` eZK>ŋ5O^vܱz5 rWM{7 Cuk`hƒ%H+" skY~J*ۦj>alOH3аpZ &y2&+:0c]W_Nb7~ `?YEDzVdZ ̮ÆqZX~(זW)y `aCSdS+*V"Iҩraf2RIiE+ UmCH@0}߽?_)h>(ejL#hH! IUoffiYމ8v^k,eJ'R\&Z 2hN8/-0oo\Z`y{3lʵaZ믓hntk@~pA3:-d?(;/06l3/L/ONjVzh;UY|/as|C4Weo;&s&̓_BU OXPʸOmc`vrQzѦ6$k`Kbrv<7 GGkHbc{|QUŮ*fz1H+p@g,|+S ldP =S%I/o(UkȰUc!sdcy2*aRRxk_ǼH~!)6dƦRb]׫=5ֶcj53 QkCyghb qE͖+()GsIdXKSASo >=IuRTVb? el|Ù/]RV(/ !w9^ /CEXF}$l^*0Msw)؀6y 64x{V5cY>vۨyk#Xk j-H<@ Rf[xb # U9{'" L2ElT&]FǠHLTjH^ö?(wpF rQov "!'+VTLRZÉU|!]{#~$^`|d_pS; h +4{O+n\ ?2s=h@$RU^-@f{RWY a6n]~;OV:ysJ8Rs;5_W;H $#윝g(-tP xƐP8P+RH*> ZqLg'ZA^DkuZä :o+.ҦnG61æejZ^mȒwC^\c  *$L(ҳs;ӛ0I5g4z>kwzn߼"5T4$Js :;@-Z(j]m۫E ~Q-t}zG#hG֬j0Lf>cFJ44Q拟S_:~DyJ *Z@ 0@\?0คG[{$Rj >VK#ڴْ16FZk.Pd鹱*Ƕ -7?H'BG9f[fڨ`Z9kWZ*OP^,S^0ЗI *$bZAKTs37U##j[8v](GE8GFrY vOX߭k?Hct!R oP>ny @] mx<72{T;^q2 8J;ټ~1nrW!$N$ G%}ڗUϯ~-6ht;h-$=7n.pM$Z(=|Cd0>6J8B0J%GJARkWqEPfrVRb|9y%WѾa&\oUfUUl;d&388H43>+1~-@ڼէ 5RFD&ER;ڴqǾ4\kn `8LMޫ.A3TLlMIVUkxzLWi:\;7n\Bl: u6&37ᩀkl?{l`jxW/=DF !QUޞ.1 fb'(߇w/v|8TyxgcPꚧۧ'*U#iH,aʑK HRL$qOb~#R+V#rm. i4qwV1h*D)`qS-WbGUc]ez*纇C3k3\l`a*B0<6D1O=W\fۼE `t}|$ qayA"EdsA[/~c!+ힲ= >{Sٰy5rkCUvOIRLJwѴnaNъ4MǯwWWYmdT |2ɘ1reS4vԻh k"'Ew_]* |+pt]ޥMBr9,~8?r%ŮYM- ynf~vOY摾uυy&4M= dё;= kʺFS\XDbvG!a4RBȁM˩j:SBOJ sWM e )8K8/]jVyH P)UiLelC *nR5B4noTsօ?)qg^H>azMi~Ǐ8FOv(lj_ů/מɋvU&J٣Zϳ.Uk[05:']Z0$269,&e[ {/4z]-[9'q7N2aOr8H%R !#yf-<ҙagf.ڝ|qp0[^ӮN44J#26=OX,alb7;(C;-jM ` W_@qBPBؐdfwo+O @\S?c'}N>еv/XB!Dd|r}\|];&ܖ~ŸqW_;w#` zӑ5>~ ƦVqvK) bb$$R>TR%%Ie_x.wZK*JeGC[Ȭ]aO3w3]~DSËx:s yoh|GI0=>4idfx3 )dy&H, {殫{XAMMpܚ,]of\)䍡cq D2]0df $ .E~Rw_|Iiz~˟:1IJ-4-Oqq5w&8Z2TfѸ;Gp:-!y4ljw5SN\%;h_Ԓko7qG! p6Ja[,2&+,'U짘T.R BF㈁J1?d!W 4 $!\~w1=aK>)v\y)-._l ).AޫOdsAkw8PƐ$W?WƧ$|s(R.!d@< \ᛨhs i33tp ~hLs׿L\jW/Q'$_HVt,RFwu |) (1>\3䂫N?g>v<+741c̎BSBk2 ϹO|9111[[}"GtfOsfag?L∃W"ׯwnv:*mcFo-|RN^Hx4QQFSR_.O Gf`"G|/ARĹH~ќzցwNR) C iffGoaӔ& 9&VV.wsz͞Us3̷rȭbT8XT ? ;O~\q^WNfOU'%5m  ґK$^gy,Ɔy0poǥS4"|['ўO <'nWZyʦ]k A2[ìٸay<@27?!d8~%96n<};f<)pk{5=\.{ `^epk{-@uIENDB` IHDR>atIME  v/mIDATxy$םy/gzNE A$v\.)R&nȻ$;֊Ic-KrcW{P2ǒ"A 0 08髮3+3uu ӿz~;Zkv%7K;KpӮ\dn>P8qf\0155<ǶmC<y p+|uY\\0 nYYY鹹.hh4߿QyΟ?eqboyQ5RJ 4M,y>uݝ̷:߿jJպydd2o`O鹸.`&l8q@JR !d .]󘝝ԩSs<\tQll6_ZZj1??mIlcǎuպ뺼[޽{4@>yna:LiN>MT~622m۔J%Μ939eYӦhS`]M!* D3{?ez.buehϣ+ <'#~!]Lmn-?{I!bvD}::P!1IFH3!:zTu}a^xj7ynA^zvj*&bG8YgOJ!J7[4iol IКB #>Ͻ-_-Phԛu,N׳vjfOd\ 6]K:B`%xhlu J8mi2b)NH;hPl*ko";G0m݇&44.趇a!w)ޅ^o~n 7_}>9F(o DԚg4U/M;\Fl/-s}1){:rGH&ǧV DHIx.j-q@WL$K0?J-d(AEx+]7 w(dhBp]APaY=< 2}wh@ zhaef V F<eIw/w(Zn6$6g@=RbYU.`rϷqe&rAٽZ)L˂IߒF; "L89*Ұo#_m#0vi%jt3~$[#BBFnHhE`4%Mb#_bl5~_Z)ٷPmbv5yp|/΋>m\hBK>!V/GR^ YD'mDE!A)?^kPs8.ҊBΪ61Ow ";s8ڀLE隙A~Ahn㣕hV(RTV6@ N,7 ZaZ>[Zt6cmF@|.DQ~@^c%WSov[2B#"o0ug|rk )#`nfn̐ъ:"r"~^to @T+Ur9 J0Jۦ=/ZҶB{oǻ hꬭX+Sp\&3a||2ؖ0д6[]?&u9>S-o:uVWY6цEv(C2[0gslyaNy 'OV@zTvOYx~>c8}S$piDf('l}\<-!@Md7"{5d_tRDf rB"oя^$z:>BZ6 %ZXh@QDj擼qn=^"t&J-9tq)%p: Yͭ L6L*z|M tQś¨p&4P7rO2=U$m1CUH$M H0, QYF@ tӶO7RpM U/ottLSHߣQaeq% ò&h{4㹾m!MlEYWY;Z7=~iW%o ,ysc-KjyWs~h6[uoa+RHczr0ы]~é yld~D 6Ō.@wv}c!R"US*9{< 11>A>׈6HU݅tC9.4Aƪ=|F*RcK&?'fۏp>h'tJ(BHH+iwrhxK $,JЁYBOJD!MZ%jY98mt&Lv%VPh)B R3vD?gu4~†QocBDXv,8Ս2Snʂ3:P7av.mKf|U8}H/0$DyCwAJۼJWgG<2ƴCFkaXQeD:4bA BwLSwC1`H4nz*˹5>$S)'')se \^GmvI-׏Th[,-ms8 mE7h!.l)L3F;P`D[9CkWۤ,@G9tq q\eVVW FGH%~5[h¥բJsW7=XV!+Ζbtq}+&vphEt$LJu]2,=Pn=W!+4=ڰ@{hg oc qVz}!fzjB N3>:whhEqnf?pbu}(zKTT ka͂Vʰ{7$M0L7'5't!%Z8&2+9Ҵ%G>zBK+.(Ɍ1V[uIPvUh@J$q''Xk߃6=#Sh&ښٯ`LK  zM.@ ^|_,Y^.lyvIָ~Jb[P-V+LN M;L ԴowW\"b}?J( 2X{L(D&&@k#`Lch#pQBѽ/G֪5r"'LONQ`jf#7l ]q,r}sGW^lrhK@8ګCD]Fh!0$h3"R C Biu}֣PTYZZX@ L:kѱݒA'.+ PG Z.4QB""6O#m GIVu}Inj4X+FÎ162J܎#~QgealIR# [=pf[l4[A!LFF$]@{aGt#NGi p UVԝX<$m++=DWVmPWh/2 =:4#Mbk BX EE_V c؏Ɏ վjRXYZauHSӬ9px~ItU I26&$3-BX@{IEU=ݫ_t֝$Ct0^ ͖`0U,a$'_\桇#6qtUsLTVW3Kf|,,=x{}@~_[DYlrwf'I%Ԡ=FF1g9W\sHvD՚EWE_ uH$4X8@uuȌOwGWk3P =ʳj:o/=mD^JǡZ_ͳ 0cq&'q-)y :!f,,CsoV*0?("zx6j:StmۤDGq󄐃 zf[bs!%BhJ@N 711ZGqе+**P<4:P(!Y`' g8Kc޽{Ig:*d 8E/ ra 8b4tO{z $ hV6X/Jq6%kG'_->c@4j򋋘B$>F4 9:j 4J TNFp ߷zp{&'j [2Μ>GTAKaC9>Ġ+4Ó ΜZA Q<PSIy 1qU2t',L^ZïmNX/! 2KK,-z-YcC2#v7t5=+?TpRϣh%zK8ɛuރGiV֨9eε?;1hV7Lɩ^Y/#m]{& ZCDFW-5o7N!%FZѢ/BB6##IZi+zTDDϸj|4鑃T*LE[yܯ6zaadɫ/QCA7~T+ N^(=Rn|Fj\V;罹WX%[Wޕ@#br~;oD[c4[Zv\'kuo3sUF8{c,X&2&t1o: @z6|z>aH!2R_ _eb*áÇvwޱh/@ҶABniaEyv5(4&_Xŗ>3I8Uf&NpJX60 N<^ƁJ%A~Stwf?b\BHHp[M,/(ך&L1=5¹7i]6zA9R {Xz୊ɽ7ᄫSHF,wo.r!O>6S(Ut8~#w}!iAȶX: ʼn_ߨs$S)a ݟalB''"jA@RX(ZXd3N~} =!, y?={GɎVk&=* <0nVri8Tm>hU i ϿDЪs!T[=+{mZH7DԒU._ɱ_!L0g/ X+-?Ӽ"t6ic$`IuxO?{aZ$x:ןZy'05;F0@a0VO-|?g惿j5td2x$IߎEIQF0 բ\\geiZ_[b1fgfdm>x;ͧ+F$^NXSR*WyyVj9:l b|/aU>xrE 8WF0BS_OV…gG7k8rd&~>0B4=<_X &9vQgwGW..Z[` JDՀ?n'#sMM=٩4 Ɠg~xfE#ŵ&+K௑(&Bf gG9 :@* =%rma~*\U6c(!;4L'> .5مu_z8K?]GV$,M=hrE@%|?_ Ê.34C>NOH J^zH 4s҈0o۔X^Za5W$grrFTU| NϿA𐅫 hWߘ'Qx!##J3}ctrbTR1-ſ>L=> 8r/3op,¬`r8<23gPWtL4$ JKK*(aJP\ᎻnavϻrF[A(X9Ijw߿77Yß|*~c7ᶠ\cdͥ8_r;ox}4sLEf_v≿qNE)1SC /Ď=mCy`&u<$as"m35! 31DkMuJ!gqqradQZ[SXXqtRJ @\~}(o2q! |燤V[>tc1oYy>VE= L'xxq7lk&>V|GO?%4BX aC|byi~oCS;c'%Cs'~K<3AZcNP(nFǟxئ˧=,;i$,3,L||_stQ$ՓsCH8HIʇD?~gW~mɃR^-#uRጅ9™_?iYd5~y0 u%r9׫`S(,ыt'?#G)a84ϭu+{ qY9:/)&fQ/r`xdd}Go ^qfo<=6 N/?dnh|3l#,Pk''*5Ο|9)FƧ(yz. {iTZ`ư02h8Ƥ_oCKND-H< oľG?Js'O[0pL{w}M(g_{n<n@upEY49OD &zg^PMLDΞVr NQgʹ]ɩ47]͑wiqU3?y)*p_0({/V,~˕{pȽ#e3]SqW+7RC鹹.]Vɭ7deR+W9+,= 1}(KWug_Ν}7܀n4In/`ҢF:MJ+yN829Càk<讳w>Ӝ;&O|qf6g%6q"g9) 2{f|2w\we>|ӏ35;4m0$f̤Xx ^?~JcMԛnMݷ.#D|O/gzf&atIME  v08IDATxyӽ|63LDE"{K"B$J vK]ծ%ڊMfwssג̼HM&{~ ː90,+ 0eX +a2C\`˰ qV!. 0eX +`HOwO<˗/]v7xkX> y8#Y֊X)t+|A}aXRT…3<24an%p̌(2A{F1X?aswf|8BD==y.[xS%Ax LIJ15RJZiorȔYu,= ƏoPWWR !Q 4!PZ<9愣7};H8JH)X!=4BHk RJuhB0rd3Gso?v@<ywF67#j5(BiyQTh@ 9N8cvȇ oڋ6[ZPJ D)E+<@km̿hR 4)h?'L'c;.}֚6˗R_ߐlwAz0yHub44sI3zUs +ȑM;\]tlf#TϾ@k<3lcc̆k¼Vz1jT ̜ɕ]ԇq(< ~iGT7Ǟ`y!&Xy]k 糶u->ҩt5eD$ ,ʕ2b?#oEHִ1m4.pAGWV+_>%)B1<;%q~}zz&NW8mJMMӓTT*R,hii1?R.k[9KyPJ_SfL.#CR7i6/79`60'ߕwVBY'䦛nўJfQLNvQ!tEJJhR`RRDgguu$; ?}ٳgfjeIz {GG=$Lz ,믳Ww[Q̩4<,6/7[ϓҖs{oN me&hTqTg9g?vǙD)55wALT,u pdYj9)M.4Oc\&M OD5ی݆9yϺf͛Cchڤ43!MMM}LU8{s=$W3‘:|qlB F fcwwV59i ruuA0w. (S gO{]-,+/=*Q?U%{%*2ߝvߙ8ͷ؂t&MXbqx  g4^)d%8A"#q]'V:k6ill$2scTlQFz2!jhA؀K]p=pYRRL:C.GXDJl6V(ҞnA~N )*6͕֬/bxcۗe˖Аx i?&ˏ*ɷ+y R$0+5tRrv1ARh@@ž7@Ѣ(N8RIIwOw*'.0nVLRMIc[d[Z+? I SZJB\&"RI\!J3rխ /ХbPa([Je::;# )K+o? giljJNҚ͑EٍqV!N0 :%*N9ASR!BiMRƓ^BJTY@BJr`|n0E ,VtÍtdrY v1q☺zr9JW|o0K3~9RSa\)K ){JEMplChT\ 4 [eSF) QHI6Y<) 'cے wx9h4#sܼ+hlٺ!s.=;nD' $р)"y8ID&`.&_|c==us}4h0Vj1xm˜zvqX*Ss؀ڌXWkHm%&G77l1bVvXf(q5aNM ]8 }*Q6@0'N;]GZ"<\. 8kLH@z!o\I[GGO؞r"%2+op쾚Q{]'pJiiY%HijDǑA$2, 4AO{GA#G6qɥ{5H"Zkn&F02 ԡt6Cb6nA{{ʳVm Z-]2@b8Q]-8c Rvܐ}q"IȠ1x]xHϒRX8꤭0Lq1;=wu{E7k6}A$'m{,pLRn@3cV4QɷV_?@#"8Ґ =uHiH!>@}x}Ɩo`Rj۸,ZvZ ~2,Rgz+V2)t)Ip)u ZQ)0rLOMm܆wؤPDJkG];lĈ\@T^F{V)uZTݘ#qбkJDJ%Z-I,Ϟ '#>H'oaR;YڙwA5|y LRa5\[0޻(8T X^ng5ߝiF ha76kR[X*IW䩩UX3i! S61QFmW\^AW^>,*_LW{zRR,͖c!{go'k;YQh?;v,x Qi՞lYj٘ B2!I>V0 `y~|>t*̻ 'L X*h_}4Mҙ9|@-4Dƛ֠8 v| _aJCmF,Hi~lHqjE0̤jYK̼nt-Z.^CUkd̙mn%EB'HI8@A/u_6{&eԚR)ES@h J^z=Ɔ,qIwĚXAX&mʚ7ߤT*'ޙvW\yG^o{O=$sO>T*Ra@~U[i,˥Rf8w,[/E:cкͯo H 5,el&F RD\J%6o_[*9c[h kcYf5ahۜNɤK8~ŝrGtȄ?8h!e47Ah[951*6Ţ\^V1!!-Q2\@Yf5Bxa 51]w-s}C>2 fy̚} 0YiҖLI"üQ*NnZdP9[Vj䖇Vq^!}t#VWNҐ>Wu/01qe@J%. ہ$>w)G^Ǝ˒%K|X^A9t!'&v;.h2q{vD U`O|8IT'S;::.#S q\z (b.R2+Tմe"JeRc 3N9s*5 IށfuSƞǤ)jƲ([YEBJeSV9v3银!R(E&UK:|<)H sk9%5ZIYgdJ|<F#hll /`}͇f͘kdTKE۪a 6,UDI"#.rlI76rڜ,Tb[Bt=4e|XU+<hl^u[UCӲ<mAttvR++?y_cw9c$@5MB-()<bc%/^DZ%dkCe?rLP"rAdgFd)&Ct0-$0 4mT*M{M*c&? 0_d'Gu颊kk6QɤE; ,lIϰkΥ8y7 hNbEı68jc8@M\J X,HZ\4gSN$N^t&SfԌ}><[Ek*I IÅTKOZNLSUrЫkZx`*44p,)ghOOOOk[[OhL*fԨoHmzW7i?_/R7skwϳ`P|5,&eX|^ϢH7j|{/AA AVI)V&cL1Κ3h ;q`d+)OrL>Koo_r\9иhyGfr&rPT>*\Va+~ t+v <05Ҳ |+KR7MKV*m 6Pnv6|w^ z9 {)$ @GyT~zÖ-&^A[8kRMp~ޙ@#81S,@J@ |̝={/eY5Ƿh HW7`Zhk뤿ߌ^@L56d}}{'dM =ˬ-ҥeZbq1!).^`ER6`{I)tX$rcno>' P+pSY|"0$D2w#wD{W۪m.N"D DX_mL⤔nHfA2iUsAen8ClYvI` U)cBkkto!c}+`̘1Jֹ5:(|~2,9~9; =w;"[` FNM q3/W=.Tt8EИIzBґ&,J+0ey ~55{d8v D1q3[[R({OhJf_F4{5To]Q4ׂJ}Kv $"¦b`c d$e,E;6V(N3o<9ùu]:S_^K<|' ~:ù'O`v/DƜuWw3#?pf(q'F6e)mR 2x N].:u_q 4YWWrُPOݑ7uRF1$6%mT,,HllmH&:tI `RL*L%1F𢅌1blp`5L;Přa/ @I/_>OTFs lzz+Hـ]ɱ>ʿ!ޙLʣ+/洫^%6ڰa8[Zâ-䭣Z׺fk%[ Zٳg^yW ɴQˢcEKd ;__ی2nE6V8㒧ϖCb)"%@rK9CcƁR4Hmy}㫬3UjE,`iZ q4!ГمrFj.e=}Z+9l~Λ3nL5B@}&`]t<›̥_`R,+HIy#f]$?KOۅ=vݘ|ie|vq<*sfeFoL`X%M!nW6ɭ $%gw[HI@ *V?-rh?, }N?t.Rҩ'*W~6}#S{v י}Sޖg&,5]w( ـWpY;/[n@wo!.ۘqNjkl42km=tuu/z7;U ډqc[)Tr>/-?]6;_BHɈ\cϵ2c<1#w8&)e)@GGO.zyx5HttvԘL,yS%`mk+Q']9ްq̱p9OıbqXʋaH\7Y^.H466ZcfT2+T.ݍ^ZΤ{\;ރAw~?wpAQrH &%uLwKΛ1\Q$~^?:7iJHf\7Db?ù'cDB Urk|ҿѫ|c[ul:N˟̘ S{{!%\l,ZwySwfrɵ&>1R*_ed̘=U?؅w=4eִ8§<ݖ}XCb7_.a/#аCC:x@oSo|\ql fo?{Y0@1QQMS*tF|if?鋘e}>|fL=>B_`Ԉ, O6aٴGgO/y[XA:$RJ"`j8'E.nFt ^jSfrgy˿D/_` !qdo cQDw!f#yLG*"|OM\2NLzOώcU o%I<ʕ(빻uܕm'|s3N~82@ /Zx>.^y?o$hτ8t+lz[BbD:hs]7&?hlHW4I̾Z+{m!LL& 8ΰGY'gl\pRH-Yb _Wə(W466r5Wn yrΚCO?\yTJkDruXX)M^)Nsײf Z IYgUsΝԃ2mʌ^ ?l'gr7eT*yz-TJ2tzI~9sp' EEz0T*bg붴x"o gY;IOO%R DN;_~ya6*6c~yR|n׿>a|H>,_QC\`˰ qV!. 0eX +a2C\`˰ qV!.n7kIENDB` IHDR>atIME  v,IDATxwxVUAzAtP:VqtbE"HbuDĮXR5$!$y9Opo}]\>{gu!ԡBԡfQGZ:ru#@-Gj9PQGZ:ru#@-Gj9PQGZ:ru#@-Gj94-]Q4E=E&@2dG).-b΃4)?!+^5B VC=l5d1OϽlѤEU!;+yzӤ~V2N-qWFQutM2K[1i$$^(B)Qdʊrw>`$?<+_ι'6sLA&Bѐt((V@*.B.-EOo9axk L}P4.n48Yy5= pif=p!CT1o#N BNx'9ih:dHXb[*.E`f>BA*/KpMpM: %%Q"]ݰUMOiӦ SX,seH6RÕ.BB46B(ECM*;%7vc[#=wiDH!`5CfVʟWSe呖۬?l&M-I˸iEg'TBxg^ q123xbF|Q3PU@@%tIX:/P {-*cv#V|)l¯{{w%+KCBJ`_NBQ?'@if=xCpNop&q3 lPT *:% `{wua. Pp؎ģ4ؼf+oYa;뾯S;sđhїٽc>"IpTNljmS oW@.B>/hpCbnKo֬sCxtiIvXI Dzsl!a3uz ѩ[3Pn/ĿFVzϧQA{^_TAzG PJɫ/r)о% S\o'z7>g/a):iA KNрq'-{Tq\4 uv7>'vt~6kJn?Z%7uͺQ8YȽرND^|=)_m| TXq?W.?+igx؈͛4>[V<0~ǵ$tB<3{oϸPԗ^VUUqERs'ѸÈjU_&3npkp6B8WHtxo/UEQde|MvƠȯ J鼷! `/pr\wHC`[qt 60̜8AC%{1 Ø}=V'QU Y E<624(=Z$EUAo~]t#}OF((@uՉWY:lZ^Zuɇ$cN8-QwӤ IGu]^x~g`$]+%zAh^O (E A*m{%PU{7cȦmAνi9OEbJt<0M՞{'Yښd/d疍 aMPk9ٹy~E5=GvǙ=6ԝIZ. =EOQ@8t _xH$:I839\t ==P4 |?lI2{;k7\ӍGGk'?G_~Oώ9ЌѰYS[]TDk*N(L6_#THXdZBt%/{qDŽ?>w+#(^'z)R'HCi\xBuT~F6ykϘ])S/Sp@N j)L~_p}!8RL8tؔ{4LtnD`:f$yA\E HС-d6[c)},}J2!  y"K!QB:H)¯+:PQ#O_izⲖn^G01=ئn߉g}ūiUfM'֧7r@4U29-w*fq9?b wIϏ`-@1W)%VeMBCOrihCmkl,'fǗ 7"i9D* }m?ۥ[I B&n)tϘD&I(`O}|cwOĒLC5 ̱@w\f-yūw2 h plg$y=2V|0ʪ10-mK&}ĥ'cHԺH%6"+oF!S~Fpi+}F$vQIs!y7HPK8+o\yJ 1B  !ǦoKuBL9qP3Do0UCyπ~ݘkV ӌqڐxy_A۴]>p3LZc[sI8\5=^+ۅ_ز;}C;9sxxEjaޯ !|3'/]T%ϋoƸ%~BYa3IXZ'@2 7 DUټ~nw^@cro᧴?&Vmcy\.M^>]3ػM2_STMJ:hűהE25u.*R(!qo /?s#W܁N[4pmޢK罔q{]O B;y~MO \a&x# <eϬ1nqqIZ&`ԈsZ&BWy->nh~Ӫ J<ҷ_[οm= |B(؎7&" c;7N$H&M?%;VpɭߐU 9}]\$eC(=@i_ΟbCbq|]@++HGZHii^6|Vo:u9+ۯG@_%W2fDKEf3eg!=UO漼%"ζ4(x\һO[|@/>T28WR.8G@ف2fy Yz.;?\O EѼݧ]#^@ѻC8;M?8g Y((( 3~'TTK"mκb)Y_xf` '~za8I6M"oGÜ JK˘6*tjgkX/P8H`%]hLι'Y  T](+i0LIWLZ)> A%Ur«Qe)g 3a zu 7U\C_ RU`v+_қi̙<@8%j݄0/hC GH79X\:-^|}#'ku紡~ ^xu;څPUe4/ON\ S+h >QQc6CЮ g 4o~Ѫ @ncj ޭ\t*&L^_: k̸JÚgQ\qk@$;M?8%wӶm x cU[D*<\>d9KHWvoW@*f*q)4Tѐ}v,}YØl }N^ŷìXi"( vjÓs;p[=%Q/Ƕ!oRHzfCgqT+= |ǎ{CiEg7d(]02)"Y)* "Ajt.( ۄg99{XesFE"nzB)~;Q-\8sXz\[na^_u6 ӿ{K ڼ{ [ VuQrb%tj׌?ݻ6h_DLVV%PJv5+zNF gbک-_pH!4t1Wo3׹҉xE:{SSHM?ݳ?o0kbƎF"#_RV }k}I I@q9L| ˗ýwb6$-GoA _X{ ?>A¡ w±2,|%sk k87qx|n8l(*RT/OpDnm%erhZhF,.+hZnMN7W5׽DͬZ0vWپ@"}AUwo(#!\?i-k7 WNTUDl?T@PqH% YYlb܅ .ya ?Hsn*{Z}t: ɧ[Tƞ\}kUfTġBSe ?vhtsza &a^e^ w< EAfvW=g Q7FVw ߸!gevs|Ҩ {۹(B(1/Wp)]gsxn!(+BE Ӑe/Wr% 8{d f!E2n#wQ)/9)ʮ3rօWgՂx|bg/#ߨ*T߉Dyz5?]5 D4*׏y|bj h* дKE >qlkv;'1#VucwDXW53tv؎K+7ɮ}@0q}ywxdrgؑDWxA7鿙«'A Cwp:g3/x'taĈ6T ؎TnJLؾUς 5 A0+?g0}2Pf=D@G5L-$ w .@ҡ3n؀%&@Z:;TcvmEEO~}{+zG{XW n8 6twm"!Vdruٵ }<=z4'J̇*RR{NJ_$w/xzfz߂xRC`aKr9Pٵ7ʘMM&H?H *MyC;?hy膂4pT-(.2ē< N/%(H`Dٳ3 Ѵ~%MMر>}r=7eVȊwcWJsX˞],~p0y H=]@('T;7_MBΊq[\2CCiRK9S#lGel: p:J$w+ay .I$#hUWfcSs~֌`X":Om%>3j^*zCxcZg$8 /+0Nlgڼ-<׿36\~Q,[v<+B'hѺ>[}FbUC -2 Pf=Ӑ|5JZ>fhRE0QpW౹9 Shnv6:t#"8}%ތP0H”4+l.yYMۋ=5 *Hݥ_7aף *o{HWuh&wOX>%^*% R);N,[Тu]F̄Mq2 yeL)# 5 UװF)W̴)w3mͿZԘ+87';ϱl!\t2yNt+ l5dPz^ (bάߔ+Щɢ'WXbE(#[қVѾq"#'uء&ڗ ! 3l[~؃*z0+4lL%QeRAh<5<2.>" t828*Jˉfs׍j*d@o>3nz:2aI=@,uέ߲tҌD>d߸}AIRGC\Tabd5 _{@Rqь R(6X"FeI^;L0xx XK&Oǎ*%/ǎ1{nEVzd"NZMr-k9=3ķ[.9 r̿D%b[;.0Uzĥbxq"h֒/Wd1JW!wWbF,Z8gyRMOMvb ӯ}6'JN;H8d?siޮ;~A (}έV8l_9dڣ2cz^p*0t qqlW%lbvsTzZ!/t2p➑SC8ּ͘6E  lHmʋдQ?F48"C#F8K0^&Q+vl4|WSo* <  XK/V(mK,K-q0h(UZ|8 w^]f>6E&PO" eEqdݳ`K3qZp ki:>3Wz]5Dh*]Xi;.-RYzo䞩7b#NJ.x`(dWHفLl(:M~+ @"bT4"-yytTADz#ǕX7ɥOqG^~RX]2׌WbK`x>EpL3IZd!3ȪW0(+$Cyq Y;q8q)1 )%ClEOh ?ISbJJNOc\= }=nZcL l%Mpd#4iԠQO#..{3^"$~zD=Dw'C oo3_Tn#A5 ,*J+* 4z??N=qx$Ci<\W᪳Xu nƲ~хˈ& P=^+%%1MeȤq5sQW*<8fdUBR m5'=#hV.PMv iټ%O-]D5#^`/ๅV$RJbE{h_]'$~wc UϟH7nHQK6D/z~Â?$wXĊb%b$#htHP `KDT0~ LȪ+<Hic;`@U5ʤC55@h$A2n ʊzq8NBU.IJ,B-"%5̤m:$cҢRr3syarztX]pU6z ~10B ywу&w},>c׾cKQ\Vm`$6(-&2eҍgGj KJXr9o Blf<4`?ZEߢD"AVVapj uFj9PQGZ:ru#@-Gj9PQGZ:ru#@-Gj9PQGZ:ru?^2rIENDB`MEND! yubikey-personalization-gui-3.1.24/resources/images/edge.mng0000664000175000017500000006524012642452141022631 0ustar klasklasMNG  MHDRd = TERMCsRGBBACK)bKGD X FRAMȏT IHDR>atIME  v7IDATxw]Uǿ[LIEE1PBS b)(cC&!kY5B0m44nVZ UTT`6J)4M< à4www6lbMMML62[^H$H$M Aqq1K/B!DA"[qcҥk\:BV\aU&&&`ԩW^M&aԩXd<v!2\{ngʔ)kX .m800@:7xwXE__˗/_ ̘14y'ymӧ{\L&ifY@Jm8klmrTl6o! )%mGey $8D^A>63Z!4̢"RMC\.Zzy,{ʆwV,g2(GwVR8mq***RR628]]]zMֹ\rѥ01i[ţʃ nr߿^xԩKiiZ`` .dtdz"VjM u \ޡ/x(q}Vt]fxG*zr9$yꢤ!oi%2 D"R5kOVwu8 y`:u ޻g_>}Py4HRxG" L211tttL&#@0 L$#4MXR}1;[n}#45 Є< ]P[[-d9{16߷Ua˩&c&I,q/8ʕ+<@AUU>J ΥZ\' Yty ]שcSOzߵb{l:S!hhhxS9۶ijjZAdb|:eI!4T! VRD c5n5?%ޥ]Vwޙ~7T`cR H R)!RAG{[4SZQ߻L `;aL2uP<| J h_FS4|I*+ߍKL {"!? :AAKIH)#S·aEm@()фaJ#Wdv-mC9CXB4N4M<rHRp _TB)_$ѾT,YBMC݇Y6+{ٻ"<)=ߏ/>@A` DB@)!TU(*+Yg xv;nfY4ϘHB7\=J> ‹)W ( ߊHtMP_([mVϴYޅsyuҷ9uQAOo)T*p w BCuVDE`J::}/}m~.s_qZlRCR |i3/7JEtqSq\|A/|]cmMd,zh{Ӧ\ R=[0(DP2EX(ccd38Y[8aQJV0Xl>gܬo!w~2p#2DTX#0Z \Opr9y5SNO&<yMC 1<"?$3~︝$iÕBz~ulo5M2I! E:jG3oAkl>У9 N FBPqXbv]SL-߆{=&/ u55<Ѓb LCq?x P;7Єo!/a=?d)8r/.~{c! pJJ#,| Ƞ$DA.uX; ZzMJ7O:;Zjjq|Guo 霌dୁܣ (N'hCT2?gE S@J*<ס;cc }dwW&da5-@:D^ !>=553~!X6JI:G1~w+t?y;?ﻛp1XBQg;k"5rTK$ԜO?l 4Whii*=];~I>wEu|hZpu"kLiovu-n~m|6ᗗ^¾JVPS :íRh+4$Z4;o6}xŗrgRZVFyyG,ߕR ~悫R*{_4 (axJKi,g>-[$<ܳ}}jc69U"~6 CjBhIw_/1^yq [m妣\z7r#Sl MTjwLpOEپ. ?M7pD躆B`&dT~#Ii)`K(|" nYZɧwޕEOl ]ffSoCn˫-|B)Ϗh}vouTJbJޏnXSDTz}AzqJxŗiڰZmt1Zzz9c&BJ6? W!Z?AHF니 / ,KHLRu,$JQV^S &H"B(*L*jPDCO0-x2 hF<0Ȝr7۽z~geٳBԄzP;" &4a_~Qi1}]tww#.,E{ד,@$a@eHM+ ;E.b̙y?r ]̜~~ r?/N}BCIE63'T!Y|q]tTpU1X2L%( C; Of`Zp蹼~H%y^aDD~ Щt鹴ncltxR8ySk }e;a T$e#Y>9Tbb" } TR+ay6'}2 W˶%Ӄ@L})Jj>7gZ܋|Sd"9jP[eG&@=r˥MR.PB#Va ݶU|>{W_tpϢ?N~D<Ϸ,ƔKVfA!WHS kL2 HH$6= `Z&1;n(|Y;qQ]SP;t7PR3Zfw~4HB<GBصЕIpmZi威~i =TP%5(I}W;2lRĬWWya`[͢"ڮ  pFacZK =QiU%%bJcbUu?翸jR4!>=_4MТ+LDPSDCxR I*b~ @[7Nh c|jbJ82z4/ab"f¢K|_ApT6rt$),;6 %sW_{`oÓ>CFt] =s2q߇,HB#B4'vRgC\{2fxbi?&#i[O̓f'N5$ސu槄)R\\PH& NUH)6d!?Tô`KR[S͵_N;.<](ϓk&3EhrGi @@\M<A5 mY*J٩W2gvަ0a0Kmt?nI(:+$}D|?Na6]] l$-+3- L~({ޑ+~[yʷH}H/H0]k/|y]2!:F={v%{@< .9Gtxta('=9:N PWo.(LeKй1bV,AS͹},@6_;3uu,l6؅NWfZW FslBOmEE]}Q+s^}cC<,S+g5 zA>$@if.!3q]'b愁kX4HuH$S~ 7t!_Y/`p`ۆvOc)WRR;?͚l$Z_LaR7L rpko|}jo<%ɷ>C( FIBw)0a:ڎU=F}C [%\@a X&J1GwW'1,+3Zh~Ƈ!:qihuZ5n,tQUI.@DLi|B/4`*<5^ ]IJ9GQV9TqɏhRL%H&tutсeY$Ri ێ됃Gxlꠡ FEmɤHa~i~f"hŰ{s=bNMMs+s;K̭k0Dk>SB}%$]{8SZ980k| |u]Y|%$I4a#==\=5\=Xy.C/$.^|-(Q~ i^0oCʼnRHP8eqsg &5#Ht!؂2Fs䲧x| MLr>%1?11Avh &}躆.`#oy3'))3ygax[+ M( ( N \X@!t-MGS:l|>Aup r㐀`"'W;!T{D](%œV+I}m̿Ygm]$-ˎ͆Y\Q+ln$Op35]:e QO]~ɞRTȭ(h۶I$  =#Hm>GFБG~% dQ1L~_F5͝ ' at/“^4A)E<4uz0-eݺmn ^.N KTTUD4q]'ڔ_uA!'ǸP&Ov$jYx`W24tb߾>Y#ZlLهj;@}m5V"Nue5$)t 11>F2M NWI4_lCFU WNjҜܩC?2f BfH=a/KIL²,0 ײ{; o}W߾=D|H`‡9`}BQUUͪU`hj,gYqr$ETOk һ5^n XMCFBM$B48\rxo F{d[_]9gwxV̖lU<}Xuh柷$U؉c#  B]); Xp5dL&`BM܊OK]9aqH$Rv^[WN,eo]:qǢsu?Qɽ2R[5Q2 j!pH b1FGB7m5Dk,,\@1ESIϨzT:ktvt044.g=\;c,}zSS[KkW 9OLy35 kC:wI׹矡w8*nmuݿ.4jM.IJH&8Ak!5qm\>`k';KKGE\y5|(*.[yrl;y6W@.ݐ+o?_Ϋve:r#5fz$́G"7Υ|2вhKxApG[P7CPp$bl*0La5= N C7l1{{QA޲h󛚦hMjM`7ORVp.1l[3%NS\Z'%cLLL2ED\1 !ExܹE3Ytu7bXd1N>^3,a(m|Z>+qlo~ۯ~= !iqCJx?ϰ;’|A g]NYئI.taa|lD"dsY?7c{q6 fc񨸑뼰a`0e͵c%%l9\_(W\-;M#li騼CʂT%]NIC%%De؍IUssKӳ__;d,}2$f߽9d2hf1b2y_Y-yn6N8:f\zzgAц`jsvwK0 4G~./ 3AX,5bLͷ[76Y+I'#c4MMbOҝ Ca8Yׅyҝ_Rs2S#w;g;A':Li' }/-롪xi5l~S9s7-ql6s,."Hch~gtVpE̿`~UC#иqEd%''@ :T5~tL _BGYZ61U|ٶ~?D\(vRZj݌d2Li._8T+泋9vioz˗/? > i]?wOntffYSޱjUsޏֶKJlݰ)#q\\C~(Iuyo'Nr-]7eȍ ʪOqcm)%匏Ѻ|9ғ$R)l+e\3jo nrk-c=eti 1kZ4Vk@NAi^*\v/ۅ=kr1wsj Er=(nVbZD Ӵ1oiӦm5ۨ] /2MqY9iyn4ÓA9_|0g4>8y.;4,E:&Z*X'S2$D>W_CztðLϿkQ/Xp=\))/ Ƴ.1^uS|WÜL/pcTSZVJoo+Wbd˴iji⦛own X_9{S\TP-/QBTѵd}o憻*JJKh]+ZI1ҩbLg6oG?@UW֪D<LQuu RGߚ:W)uZxǷTMIKիmV*L*@IU^Z*˫ե\AngAr:{3#U dz(kލ'\*()+%ϳ|븮K*2cka~:iډ'so'PQQI>7玓LZm* Ja6MMrˍ45 ;OS^YA>y%iX1bq˂^MV֙(o1N2 #?3w !cc,yEZ;=|_٬lVM\6+&.` felY6q٬lVM\3nDžCIENDB` IHDR>atIME  v2nIDATxw|TUƿ疙L !$BHB&RTł E"ذuW]{EEP z L2q'b|23{sRJI#,~_4 AMM [n% ?zIKKòCV9w`۶mGl"DU0(,,i; ~,QCq{^/J)Q۶4&M:tH$Rk 䐕' ~YYYXa IMHLL4MnJ]@QAAll,mI˖-ٱcǯ*B_`HJJ"  iӦ hӦ _֓9H$?w_G֭[:tץ7 hѢ{졬6m㡬{ o]ٲe ^7O(BQTU}pƘMz~ 0 4}x0~!h޼98=lQ?.>!as/0 <߽DZnpF~Y?Cuu5IIIvBGΝׯz`&D"{S/%P(t8G7M<1M4zH))**"8R8d|>& ܐp8+S&~~o`]47 *m۶H8ƶm)--UVD"QQQadffR\\LRRBau.F| PQQQ`A`fmG0IJ, ;\4 ]|8딕NJI^^AâIxz9/㿆E*3=9m TKZ$Ep Y$hN8P$RJx>r&G7 6=w_3^r<],, @b:ZFG͆ !% "4i ;6@1C璐|^4_>'n:NXXEDL&\UJ֏'! T@A-BE|M6|}i7ͥEun7D,vPu8a0 6qU%%_ں bH}#J*dv~+I}'((*aƴS4 P j `# S'2*ǡecbՀ I</ H}';qLxt9ΡZl6@H HDCu2 r` Y*3l4 ' D\k T 6QN 9<7"u;̢Jp 3(*R @ql)aB"/aZX|gu`Q,o' ]/oFm(%m_^B xʟvK@IPd_F|O7Ac*a*4@=#PaC@ϷHp/nɐ IqXaxv%79.Dfl~j+ɼ f ~']r)gy@)d6䒙3|0*aGox|iG}T] d{~^~kMðӹtT{N'3Cf_c i; :1\qO>r"'Î_j[$4%.ן5*=QC#鿌GIiQX5ܘA !T|8+H!8j"qشf+/~\&ׇ1;k(m3ro,|J-z=MjF_dQ\<5.gek;X}/?e$V,fт(q-V"R"pxv5h. x"atY[uQB HMEΆś8|CWG]ٹċ^'x>1CZ64o.קuןIOϧkwHS-|^?6~ܲg0 zTD*@ t;{ 7A Z!zYpVNUl/FJ8}sS2d5^>1'3%5[?ML.~ܹ+&ݳW9ksjbЙ1e%K8:9 1b BG*2[^clov'= E( NTmJB +T!v^ࢳSXh:F~5EűU^JQViS:!6%M}\:x2 ޝbҳ_ĐKO,mT^@wh#疲i|l荳6vV@#x ɚMg`󮙍{%~w۽m }h'#N m)'(9TF}pg6)8^@"#<4|I"Z/F̋PC:ӹЬ=Ю)7Z=KΣqe'bvDq"i"4/,9i>JJ+>e(ÏY!QF(n^ษoiG=[w$8x|c :aN|$vqIUs7_:n6#U<9Ioq nNڀvP&57%w|][u-OQ{'0-&:{gL@c h L;o=s16̯/sc!vݠp0D 1{p{C-oi'`%BӐn"ZYCTU:.`w|p(O `}.']7ݡO';xC+gLbfNK^pY-+5[>]L3a-̵pB8-)^{/9ǿuwr2w5.>^;veۮd5jm)@D]QK;ּ3gOx|Ũ-0vE c1eg1Om {${|9킙 5xZ'1`bddh ;|SOfնx`wNLӑRCo΂_c=_A[ !d-N!ӟІDNGtox PPP3ҹ ICVHL-(Dw_]N]T(^JcI)>h߉?]'<ʕ<&pfBwl#xj z0?/.P<cO)Ma:7O. ZLݐٖUNW$O]sK?)|K6Izm]s > 4;1cX}f}<}1\-"ڒ9.0LΛЏ7r(![ZnjGQfMWСF 'ju 3!Ͽ祇2n!T]}qBT( EA ɐ_pxH Bzb](IO3g a+K'pɥ;|V nwkK)[<+uEwF޶tswj%ZLπ+^3~Ƕ*p[Wu$n:Wq8(E1zuaVާF_Lt8;N?iEb#p?FJ7BA8ӥ r}-]t&M/A%wUAHE*/K=ޥ5(bћ;h޿V|"ՇE%bC%Lu ˤ>ĴT`Z RQZBrԣPf>r7gY2fiitsA([Qf?*r!RנSW^_1S.6~=R[V*U $8.)cK<8~PD)숹G:Fc"pptA8XnF n>ǏiqTc1x@''>Y8F;EL~(`OuY1M*1 \Q mOF3ԋ1S㺩9l:mN`o5*P/ò`f 45vɒǿǩܓb9jRkGh{ NtQR"Xi#EKV3 d'|cIH51-\Ezr3:_Ocmه3 . "mmVpgοj(kMHO BHnё))͈OHU[>ðr]npnw sdN8Տ˜9g@Q2HCH}PiR!1Y皿%r] JR @G ޔhӅ~7-fֹYR"\rFR<wD {ҙ< <4!\Q5v7OnoKTA=';kx9'u^%BpuZ)܆2u$TqҠ;n.6<7S Y * "x -BH ӶĴKY;,\t(%TV!0kB$'3r`z"L(EUCyX$UP lco+\~'$Q]}d?i駏A@.-Y~_ b#nf '=ty5}}9}Z)4GC@*8B$1AQt"g/~TKB뫨.]3p4B*ت]?[qwi(B0r6|@RQtV)a?˨%2;8oSz'i7fc0B?DnmnArz܄.axzo;*,Eq BRhi'Qa|=:PSk|j,# RD%(8yrOʘs|/^6,ĕ+,6zQ:f'v_20Ǫū+؊0g>M%?ZfӤi"8bޯϾQcy]xuP{@- o±OAKMl7we` L_r j$'^!hRqǭG$>d؄)nEشE[6PRVɆϼDmмH[B$hBJd{/Nj[{~BhC|rȬ]!L{gϠ!p&rl_ DtH+i. tީ_}~}w.'KGBKtSQlJ-zH[i$},N&6p`/i}ZĒAMxDU S!)/U,^yUNwكz 0-q3&p7#B8\fXVcy|H"xV1"WL{"A $3TC#l&>%Zubk⚅L<9W^ qōYs؊*‘Q&Ѻ֖/;l7?8 #WlB!a g5ի_%~jFΪ^M,</GIۮmsg= 1&nSQg>U!F&-R)^IhH;+1IV4f! ŋ\JyyBA84jSE a"ꖟu0ȰQߡ%bE kua 3/Ú]7m3zX b#Hi8ܭkv/;B4͟^o0iX6_ HUi1Q鷍tl [6"C$wnX6OUE$l"*$-XU#15Euza?1.6[ёf-"AjDLA(bƪy\uzY?  Jc9X #ZL9fB&>; 1Tg2-&͊7 ?"z:T=HGQؼ~/'I6_4,j d]Dͺ8\j&:$`EH [ߗF_rW%$2m]@؎J$`65%U4mK3O5wKK_ulTO ԄØ͛'U z_50ahk/u7r[8);Dbv©;SUɨ>1BV*#ZY|mҡisZ׾<*?$Zj 8Swv͇?i2}DA*|®]=7Oa2Hqnv0}Ɵʷ@MPiKY7Wu>]ERD9Eڮ?<>K^Q:tvʡ2c͆}jjfQ0M`u V{i<$`Z&c^=7Ƌe{=&^1RX|IsXjx[/ g͗/ b Dg$k#._ g Jl]SfwA֝1 \1mmԖV,^̋~yS/`>ic;1I}̺-̟ 1%2Cٓ3hfԽ#Fn)!U&h8$a2->H|yǵ7H)HH-b9 )BARRRy㝷دo}/&$p-^"bþ*ږGς*A o|m{ g`3Lx_IԵ&_: RHO!D~Eۼ"@eUyh4 `˲ k&NիhܴPN_뼶2ҲzcOHœݽ%-Õ@loV"NdWO YWGE"zzWa_O8TV*}O=? %^/Dl" c6qDQ5qQwxI q5op,_f 4M9Kpr!5;a"0tlZN<;vGC$c/ڇ途 w{>Wх_#T^XDТWR7(+ 'a`{\[jk7q۸h9`Kۖ58Anzw}/ G%B#'~c"ToOPUEP>^Aq%#Q+gy0I"e A%3s^3ZKQSrx/i"NRµZ9w#Rqg SKƛ-SY\"@6-0B#f8QYKvVoݺQ_Ì8!jkP)]õSZ6PeUntDOG #Mxq2{SRo֔p(N(,G`#Ī sֈZ?+X ǼC(bH[[XVb8xeƞWowE!@-^ʗ㧟 qTYd7ߦG~w48aO"s!!]4X416HF4p4 hh$@G#8 HF4p4 hh$@G#8 HF4p4 hh$@G#8 "tCIENDB`MEND! yubikey-personalization-gui-3.1.24/resources/images/neo_production.png0000664000175000017500000003710112642452141024752 0ustar klasklasPNG  IHDR>a MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3bKGDC pHYs  tIME_ IDATxwlUy^m=3BU:"bB, cb{hѠ&*Hh"*"( V\noeY3h3u9{eάg?,c>kz`d#F6r`d#F6r`d#F6rn7۰ ]^mky[֬i>ͯnFŶ[GuV& $FD ][5JBN9[gMQ,,(ce|z(ܻ,>fYUцւ#YQ!DV sAӳ\v7f#Fnl?w]fM!ZF)ROHnjbb 1bBiͲ : S߾ۋ#8c"2caH Xki0J"MUጡg-hi8cǾ__YU}o22X4Hex)nj hhES7R-ƈw:GGA)0Bc [lϝ5g5(vZs=;. JKJa(-7 H 9- Fu(d9G 4RXr%{.# Zws1v J4b{m֬Yk?+BNѡ[.Un@*/uQF333/g_xnjONe NhgnYd( ,KZ"ݥ%)_8󓟘>g.֪6m !P33-u~w7MS+k uU[)>eӟQ[V/oVnePb*4jb h"YQD4ESYAX鉷PK꺦]Dpً6ؼ(Ȳ,mxlZ Z dyƗe>ԥ?>:ءvPʸzDA#Eu9 4>@2E<1MR2!2ϡ %,[6A/_tq=!Ac!D#jLs%wN~sfF)g9KyYU*b!jr9R<>x'rBPDY{/C!F>C`jr?3HgϽ"3ad܌L}D>M]#tygw|PNQ]F$eMSTꪦd.CsV㬄T _B +Z:8g1`#6n0e?^ Ȅ0usD6JiIa$kZY8q>_w9]kdxټ5jj#hʒॅnhM4e<(˨,YXXkڝ/yKuz颅]vY]\qhyt$S@}C\zec>ԅd x[޶xi-BEN b>cYF]7+ZWT(Yj#4!9GYUdYFUX,K,*<*+%N8^ri&uUW/\vGMd""!x2+b ,7Lo߽Cܾ8@s̓m묌Xӓj' =2B 86Hm-%hATuC e u]g@ic,UYb]V0b7Q>zOW4}YQ3!b 4JAed.\(> xD28gOrЁ[;[Vw?0,F mG" !TAY~dYNS7dEo|C'gQZm G_'̿Ou_{ش2V(q,% ,z5ҥDG䭂^/#FٗOsM6au3kkcwҁ2%&UTThӢIi>P*!g%"V4Uxú 1mTTUmU)`qa~f:v:HT-:.[yA%+ݙyed>e"˘*kkx"1|bodotIsTU9,62cdTW%NÝ7 ^9ud%) ~zs?'Gp|:X԰7VJN45Sz]nZ:}}o գkQb{O4,.Θ b54`x@@hQhcak-Z-N0>M3??Oh%pk3Ok_DʈEK )k-VA↛nƧ/WIAb߀s.\/tڀRuhw:C~@R9B)Jb(|UVlD]UZq:KeJ*uei{ ^0u㞺ʲ+ZaD&puVNN]bmNGؕٺTuZ yHJ;X[ru]#BI7YkY;tk%5>b.K4tk"9'bd4 X"GkŭoB9~v!W {쳟Ί"2O\°.3n1?=|754\'blq#Dh Z!܃*f4[TaqDih|Hn<*mp(cJ 2ȉvCORi9}` "@ 2. blܼ k3iCS,[6_}Žfx/}vxOUW!20jZU-aPMëۅk=2 YDNB4`tA22FiG/%(-LYɦ1ˈQ*BdBk4Z½:!c6sslش ZX1c"_|5mHAAYn=MwM/9D|) >H 1h b 6q /8T!`|Ta$¹L%$Јoȳ,p@5 yyl&\K^~7\x~o|Cކ-[$O ZZ-Am6_G4\1೔DF "xn4d8W4u]vyifvCnz?yaA;gA&yZkqcei8SړeۦQ1Vӎ--?p4i'?a_sƒ~ĩo8Mc:sB©'*7Bq$m,޶ ]YY[Y_ ~g~˟unt0_3egg6}hT 2~ZV])^1Zv>^A 1upOdlb'Rro6?7Hy L\6U (&eO#UUe9qզknd57{!,cM1.>k~rc Q3 S*첮Ҳ )tʶOE5;.|n#y~alٺ/1\{o$}Mqhsye&dƧ4ȓ |$˲!*u˚$.`huٸi 5 EU[n r-o\z;eТҴ-iN:J&my.px0 l\C Hh("dAG%+d~TTj5L(`E(i_ݺR@iD詪E9ib*p&yM"2Q{l۶e.5so֍8>}ƧV?`v5N-N#aLz%vDR UbekX6`ȓS/Pv-}riM_ot) (@73JҒ8L͋"s8W`]x3t~ZLLLdwyܙm`xs~eIGF2C,wDM!"A!aD0IxeE\y:)^:ZB;P 9Ƞ]Q",/m@\bIh)e6nѬ%Ni>u_g/чrKKKsr&Gjw{uxn<`GFU1;}12mVkeZ-%֙urۤV1KÖO4׭hicѤBo*ƨ 6`M5v(0CSk?`;&;<[ܶ]1iE'4\|85uUSjX=[@]+P |7 yIՃT޵M7(DLnx[OV錏aABéah# y28dž qEPZޓۧ?3UY;RSmWgx{=a*KHk-xA:uKon.ƅr,SnCL%a|ϓdcb|~+^rwfMvǧ&&B"{iU+Z`8A9Mz{MSC(mFO3 O|eʒ^W3ZDڭ xǿ/o_zYgK0=}ȣe+!?ӯ#oıϺX$OCgTDQ 2G2aڵ)Z"Ō ^LB(*u+РD0FS˓ŧ7> Vk|dN4xA u?+x;`v"D/\_r~L| ġoEp8.{ i[nciq,+0ZnJwk~ 讳;4\'\\> dֵ]u]ٰfPIi&Em*KڝP)B^+=mWoF0TB:kMrRX] I'1OP.=-[PU5c48|]ל8 n=w= -nrh(#mR Zy7($95cD&!⭱8%mRkE4uEuMf eݤSe_7uq h1ZxD02v$mܸ1m:1zb>?'>q9wk^W-h[3YGBѢ (u"f)RHq(7q$t#QB)Zpe/)&z:TeI@Өxa2 , l'ch#Я,Kbr\OeILtcfȸ>x3~S_Lba~l/|Cc6Fh!|pfn%7u C3kXxQ4ZS(kF~5:4Y+G 75.)}Z"`vnmd x|k׮wÿvgn,UPVBa6~gA0pe)˜ܹ 5u] UQش!PV%ZNQpODR%\f {VC`|l2+-YcIQ5J[҇UiHh-4ȿU-7w$Ҋ+h2똞ro%xܼeޭMW|犥vۣ[-kK~W>}9׋gF&~3N@OL~B-=!\x2yuB!D<Ǥ1V^zjE^VFק 2l,@* ^\funG0oxӶO}+:ccd̪ӎ'4~`,/Ro(vRwIH! ^-+ZUPYK/1Jh nulB@$᥽4Z3>>Deh#>\:;܃v,_3ɤOAާfbjR&6N |'[m'&dtӢ^@)Rr1m 77hٔ2wXZ\ҫs#7EKdRMB( IտL;IΊnq˟_=ncdӆM {7EKuͣ015T|hXu_XHBQq ˜'? ۗwZEעbL;IDЉmb%*Zu:,..mf km]Ksxy tPGkY sw3 qX9MÖmc? {V(/]{ӟnGzcyVEDŽ=&*.0>5hijd׽J?É$TQo1119dztY{!Z8-]Mo%w@#a0 =, }8@BCRںut&K7wy.zO^{Up/S 7.jcy^c׭Xuho}'{~wjێ^T0Y^DGӫ~X"_v1:iwN|ҁL{uKrCe;g& v9EKiZԷ,9}"v͍NjOIuDs䬏<0pXCqY~%g?8 5SS}@[I4xOQw4֙@9 U]lu]Ww-t7f3>:_3ak~ɣLNwV5y-?o>z>n2紫Լg @4BG&شa39B299ryQ~^` MhnA)-UR—trՋ/=/2<_kjY'@wTJ6'r>v*JܗÇ8meb9uOzοq?<=~&BĤbڍ (-NV7"ɽ _`p9mJ 3řܻgYbEuͿZNX֞o& 9·dR= QE*Ӟ)0jFt!Ƶ}σ*&~뮽)}W\ ?䦌J"ꯊYXǸ\Zq"j3g7My3I[ %f,yŋ}Oxp3;XR N8jw^GH=90"W_?3^v tM뺵kZlj J:펐OC@r6o, R b)˞o}~|>N9ڭ6*F_}.0r#W?J{Gs'9#Gʩ:Ï0_k]q.*I{'Z{>}θ&\Ju5ٳ'aZE '{'<`iE&j^sYNeMSa& U{W o~O?cW'ogaq^~첋 audN klj ДYXn.Rr|&͉QP1L27st'z7|C1{ޭO\9@._я),3?.K]]nM3ޓ۪e6(t:|]YΓz[q:iX6ůnj6LJ;fsSC]߶\yUoӟ۸y<˧SN{<W(D:K-mco?\ ݕ}YeD(Eշc2Ͽ^he{mV^xGK$Ys?w9r3&lKxߝ*@fjE<6nDю?y\.vtj|l"$lm Ts\r9?/a2+ד ǘc֭@qǕb|||4ACv߮+]qepQw+'s; 33çxs/[7bjb[ׯciExVzoUgtw3qWlbc5*FNyaݹiKÎ:_lcp1ofe |_|zڝ#7g>&jbbTeGt(^`Y iӼRLL%DeimvJG #vv)'By51>&Yio~=`"oӕ;ĝ_\dmdY veIehXsOr~_2N5}qy&Qݸe7\vGw;qCഏ׿~:3[kɬaiK]d[ʿ|xwiqxǸ(t b4X+N׭\GWth9sow|o+ r0Jk.uUeDvyU2Gv)_~>v WcrB91}_U9fN|Q).DĿo} |Xr&Fo}Fv_L#9F0l#9F0l#9F0nc+G. IENDB`yubikey-personalization-gui-3.1.24/resources/images/neo_production_33.mng0000664000175000017500000006414312642452141025262 0ustar klasklasMNG  MHDRd = TERMCsRGBBACK)bKGD X FRAMȏT IHDR>atIME  v8"IDATxy\UL5WNw:9IT"u⻢UxUqA2ɐ 2, dNzC9gwU2% $ytU^gw fmLlɵM&[E166^>0HDǯ hmm%LNy+"s=\.f\}ׄaHGGdߛ^FGG_o!3gΤqfկxC8_}ww7ryFa޿zٳ9s&Ì4t _̙30 '^lyB(XhqR!HH)_/^׸+WN}h51Ƙ1cFk׮e||3f/œ s̩rO?8N[["@wwdߗ^  ̲e c/[l㏳pBfrJqu_39dofPJU&-r"`xx0 3of)J n:!2e ]]](H$Ո6i RǧR)p/ C rR!P(ֆ0&p/WbHMM SNs!+V`mev&)YfQ.y8Gam#'NekXjU5,Wk(Xjl(D"֚NFGGihh@)EOOϫKRHRtuuM=yMJwu?Rp(J0w_szms3f1lͤޜz{wy%4659.aCM:U+o{.m JRJ,G*\.d CONWW555!Xj?E*9B*b||t:]uw=p߃\6m:r"},])Mr3<T O;5Vb͚5տWC:W~ Z+R$! #fMg,.B}Eijj" C|'":;;I&DQME\)%RJ(}466SR6[m|g}֖V S2/bf~-XgG{;֬eBlqJ+!fum 4JI 6/hA@Oo,zvz8o|=NgB+pi!Ѐ8!Jm!"WTAAcC#Lwܞzz~M&CdJC# Sqh82Oc|8,8h0\\õ]]mt>Slހsq߃2uQ} ikk%RyQ@z.H@k\C)R vT(|#( #nۿ&xأ{(P6t51O +cr5ZN$Ҹ[u)%eJqL"gddowbݼ]ej+qy>0qz`( I&8C=CEFFFDaWG'A8hmH#JJbG]T2Oo_/Zeh 8C;s!r߃Ҋ`9!*Ukܴ2%%#d F%>|k_5%?XOO_;L(Rp@RyB֍˵W}77-W_vlM.xق3&4 Q)\[xKb4- *:ɘa)3466r5WrڗDO"q0e4N '}+/ :zg͕ej "q T'~MK|uDq80O{2T,MeV^,]\`E)m"a_ɧ?onm7V^Ŭ fsqDvApxH%q)b=Vı!}kEO x ?Z(,sT4PNijj}0 ܗ>hjniӦWimx8@8A`![ѫ je#q [ 8P>.HڀLq!4J*8Ҥ)6O߿9.%7*}ͥqJ#|!3 ߷ys]8F(icz@RHBSgկf e[ɕ>B0V$I_?|"(hkfڳ : ] ֵ  CFvIIn%  (ho__y}]S>ï5g"c1.ZkZ}'Cֶ~șg}U?=˗`v`ttiӫuжZ%Wh#mZz.Z)Ql 0p+ bX)%֭+2:6ﯹ=Uyɒ%og9}]P:6cqzymlaN.ɥ|zO;70\B-u̍eljug _uUBh3%q% Qy&44Ri.v}|gΜ9~@_?/?=l.KCC#*UgS:mh4Q! #}t2>>FooO> ;=T~D$&Laº}rtu9My%%"m^m_atҖJ)-PJY`$CCCE!H&!(G!|d"I`h9"D*3|S)C(PnJIs\&H$Yz8Tu7r4~g_<3Fu#p4-*ȟ}ݷJ'vqQ9qgRx>a9D8y.\B`r5%a-|#pJ*b" -AyT$A̳cem{9sikn6Afy S)6lӧ+de{P !pdlQO0 І.,K#&$y,_X%5mAk@BHR])SA`d]Ugg|MM$I°lWϔpߕٵcI2 LmiC\L1c_rhRpqh< hK@\AD3,bS 0es82N+M̤fڨl-RJšDQG>xwu'͜RA"MvZCG}!G2(GC"c%ceB2$| TȦSrX6ymDidcr>.M9{>(y >QdE@+EG$ hӈ!IJA>--̜N,~}ه>3bK O?JeR2FGG*;XD BC+)IKr$˓IHR2f|da⺶ T5Z|> \sM)E!8adOTI32|/A*a]}N9|M}1P(q\RJ;%axCgO߹Mc-kْ%M㈱H7Sq=X/$Sjry+[4Nؾk9dQMe DET`0QAHizA8y6aV\+:1T,N}SHq/p/~ \hii1|d9?t,mZizKc,_xi|OlCN͐F# CރQzk盗=ǯjyjkkИ8UeA"f x&6y/\&lq;"%dy-ín]03k׮ajKs R V2&fllU]=2b=ho3R=0W/5 xw8?j 5s9- \U5 ٘Py.ZM0$ /"\cwv8>L02;l A>{qE Î;eiox9b3b$gHViY8.ZfoV0Zc;@BŽ޻?HT[K:EV+ʶc ]wZ `bԩP+/*LfI&(2<~v^}}Wt=7g u&Zfuqs\~teN?b*_}dhAiNڇ'pghrPDf RDZi>D_9AxbA!hH&bqL dXIp_׽q,9cۨkB"HTK-vNڎ6IE(108HgOJrGLC(xH=lIG:4|=L7Mp:?H}M LٟgEXr`H`Jk\5p4F$Rt*Kd % ;;/[΁Ʀ*0 *35Pd.vej/vk6,^o!wkDXffcC?38o^ Pe慿uݡ7!4M \e7T}]+Ж%TQ[u=7+ifJWڼFZƱ=AT*gS2+~kU;r Xp6|3ijj&l]ue&8# dld22=͂ՆrW J ̳ynq=ΙOTK&9Ԙ\'f9{3QÏ< Zd,-m';T1Z;J+CΔƌ>IGL0{EX֍rݶ[*rEY `fo]Ex f͠l>o3|2b,;u=`Tz dd vzr>* Y8p|p\xG*bll^QՁcӸcmL:u1Yg§3Kʓ+^(P鏋*MYkUwW;|?ߖ"[%tT`_ao0Ny8Bm+_D_)! 졬C tzb"dY!Sd5 8#橧XoQG~֖VҩqÛQڶFMh=߹V~M954ԤU0½ZЕ?/rgڂ@Bu-\Ώ.| Dڠ~[gD M*e@+Qd v2yLuwwzA0d޼y+usN!#*_uT&UD" N?OWw7dl#rG塇f->-?ıô2Pϕ۷YmZX0QnW%tzC~`lXA&~25biGH80#Ir+GhB>Pj.Q)tXJz#sb%2#>OoЅz-|cۡZy5Ktm٤쿥P\pshmi_.+xkI8V ݣR#Lpܵ;v5Ln`$-A#ew Z巭@`x0ԇ9V*poGr,rvB!\bɦ;3gΤ,zwƆffx!*§ı!0% pTr"r80~vL[86/83[h-rqM:YMCC%:zY}"qmaJ] %$X6@I]%yV +b"e8 QZG>߀{8F~:8ndSiRY9{{vDKJ&J[H5(Tv 0pTCGX\GLLZs'th#JqL9(i$k5b[ϛl=S?# qETqqT&_qoN]wN>ӬsBMjT{Ђ ±yӾWv"'2 v'qPs+ӲU͘ʢI;fe+e%1}O4u5Dbddf!CT&j-_!GCp IqZ)7Jv2tc 0 TıHՁLl?J*3[h{Br:3iio d5( o}XŇ ^3d,ؚbI0}te_k.V_OiNn~@ihj#HY2* *Z%(3$UiKkN2|.A|?PC"eĴi-,k2Z{bִXl)u4Ye֌Z7F"*kodVleE5ʳڨgqm$]ksT<5T#V<82s$G2.t5ًd!3 ~W,>oc?Ĕ:ZZx]|a/ gwUtZke3V9Ü>qKTS,Xژk\Ϫfne_`W{LmۊT2tt1::F229;_^u38 .i$9-eNKeڼ`՘[coZF}M=|(⸪SI*?6Qi&p=8Pu(MX*z~_!_VӞL$cph8R9=)_s苧o?Xd"a,?cT%iTV[("%&&w\:Ealhҙtl&COoAt:g]2G]|xkO8Sihl/Qp`wNiZCu\|}UZz{'ΚC(.srʩLe{?E~˘ֆXg&}606j|S,D :!`v!GWT?SLj[׳D-8TuxiRf,+V 23jL& .Ђt:xhHnO.voesz- ]ŗjg\0iPC3>9_ǾA.A_ђ.53<`5n]GW8T" ^|Q[a3Bczbc[=M XbXuВ1~Tjm7|iY>><}|05b(UifMᦫ緗˷?>v9~7Xg8Ih c5.s.婎ONz%P*e\XvjT8Ҧl#m8 W>Qfppd"m4)#N9\t񅓽^|zL?ޗ9+`<($8c\ۼ V N}Ì:qMYˎǯ+@"rjIZI$aU@ L[K&TjTq!⺂5k)C2<["׿㏛쵚<c'O869X{Z#tX1bFfһ6?v;۵h_C1-H [7~-tCaҰr^R^hueTk+r+}HđT4+0l:C),׋t*k%Zy[ndztu0wYb[m9ňޕyLοHĸԶM<絜{]iQҨq`f_?|=ò\Lz)n*'ìlgZs dRȴ*Rn5L_UmTXAt:ɺ{zt:gAs榛o2߫~s$N6mϯp}ƾ/w,ZJ@[=i[{A; DOC!gc,Nγ^+Ig8픛x5OBk;w#=y*1է(H?4JX2pr9"ΚSe_a6"?:45'r,]#x/e#v 4,XOpǮ qUFP&Էk'8+{~t  `KO/wR?Ž} Hvߦn\7/G7Rl ZG7s{;aMz~{OW^H֙7uW.#8JGUW[@!\iH\0}}~@2 9CMZLV\_ PazJ/-j4qysmVmg"ؘLOgY5MNMΠ_5<ܿ~d!Whs[Xkٵ t5vsݍ'4 ^Mjg!}KnwQ~WВqfΘBX^Gmm=S/b²ı$,I%<סuRY i&%~F*I}w?¼C PWSϪ{= S8t+*Ȳ3=&2 j橻o'><}*`VYNu~4msYwŋ 1%LuE{z G0IuDZBKt8=}X<_8(-bYp444Lt{*O|\&C>W!ZHm6ǏOI8V k~W!XBM 7䧿+/<-A)+ƦdD粺"ghdpR[SCxn(=}~@"J/1cJ*w?0T@MM]=HXDw<>q·7|?ϥ?9f =fQm5 >u5,_8 ;N[it#?v5OgfUW3VH(%K;~\B)#˘0H%3A*x?ⳟdw*テ8'|bq,Q3^# ͜&Ӵ#۹r( 5f0GR&‡{kj|_~cOb(5aڵH%e (s˟na`hȥ?a8NF;?D8ɤ>.vyɾ8"{-~L:E&mr$l%7|4ʎ[-Ezuٝ8GAQY\q_dL L04\dmG'DT2Ek[3w޵I}?#V<5evމ;nl.7iȋKeH2V,FJq]aQi5sˍ8]y)5[aʔI|&G&dي <?_Ww~YN>dg^w;xժߡi_FM>G"HRbty]ĥAGI>N8t^M}ڭm m~p5ϮbztP1\uXr9c oq}s/ys\@26؎=:{FiF󛫞`>iNfϿ|j̘ބP`d|UW[,cnp}ޓA>=Aj 5VLAkj7;<VV0= ._8 HgkiˁRP\7̪իTy*ۛ">q𑌌Q[Wˆ0S˾;]fmB2e*tɤwvO.S\=`õ}vx dR5㐃g0wGhKvG?6mg]+78DM8|37-4p];r:rwÉg΃ahi`/qq)lF RIj 5iog*[nl~v 7|AIҢ3& I}UGk/?#5NmzFkq6yN's0EV/gA{[C|s'hcpXXV|476MfОqq0׾F}֟mՕQLMM c:̈@*.FF1(Zqη_d߇YH]&ǧ +d9֛7od߃v}q2lUydlHIڦr 6[/ !}.?ǔ#sn Gq(^i.o|Vgt&ӗ]Nz7?z 뮽G} ?9c=&7?;Maldk`#M&ml6rmr69Fn`#M&1Sw\_;IENDB` IHDR>atIME  v/ IDATxwxT)I@HRbEņ6 ^gi}3 ߅' RRRc*/7 @ff&Hyy97ns?P]EUUX,DEEaZ@ c*`'tؑLn7>>tt:(V?$b!::Yٹs'!@E4MCN'ȲLjj*y$I[zZ-. ׋}Mh߾=6 #hz[n'##7ǥ555DFFjl6UUU8p7^ ++ ʆ رcv:gi.2DDD 2,cuRG4***)))!66AYYYKIŸH߸H#nnx<bcc`NwE$ѩS'n7~TU%""JҨp`0Hv(++r!rDV?Lpݔ8Nz(BII Mbjp84 JUU&wSXXHQQQӿpl'..$ VY)--%,, Yx#2DUUTUEeV+ Z-pl sK?/ +!`رcKIݻw:[v2226ԖV)u%mhk'J-; ҁxlG1>^ { x))qE^LJfWm׏Ą̣V Pg]|> $1~K()v#G\@B+Iҗ_G*^JRT#H0h!"] {xΏ/V~'ޘw&|JZ 6ؿ{?k|M8"[vhUx')FzR E ])޹o1G"+M ZA X]z=GׁZ_h6 Zg@ \Gjw% AD'AH^Yd _HdB\KrsĞvg '|/@t +5Rzqat(D V_sqXLiqRϿe=#YB:9UЃt23[Y:蠫 ڍJ"w,=G?zⴶxǨq+. t(\udP @ Xp-QUPNB% M"F:-[t #厩w3Sn*Ш5 |h$ubbM;+4XC5*ySEyF(n )`5v=Zz8's[NO˪2o&h(U4~5 6v2t6SFlf:5{b!7{`.`z b:w gO[zH' >zc]߅A` H15" U V#'7[2 C,$D b'Sw >2"ୀp((a$_2Kٺ-=4"}_{_G/9*f)  ^A) +|ĝ, W/o73T +K\8{v^c!->m03$v,-la]g_5Pn Ђfu K0HH㶻AV $uSO|@; Hŝ-ipCwqo^Bm>#i8]~|iQ7Ыݷl\t>k(ƕl,G2vhX*"l[˗+p?5odٓp_LV3|@ Ʉ*/tnp ^oKOZŨWߠ x=yn =4_h NHltO<3 kB{(hfV>MOk}M\N=DmgvX'T6@Ėo 6iȼ|G.o8(~ [N;Zz8E̝p*]c c拆̫0CHeqBZFR:pۘaPZovO)?M"f@V⊀H=3G-k/daLLGݺ(KI-='F7$y çN}UX;@9A0f?\|]ZݾUQnB:v{{Jz|1Rq6v9O!6obWQMٺ\Vݼ_V5@I-SFᨹC;`')|#Lg*ɘn}Mi EAW -j_UQrcT>^9A[I5.9ٺb ƼCxALK*"KR ;ל;xoץsZ/Qk uz|xgĬ;fBu>f}Lf蘿CyL>sg)JuAe(6^C0󮯉> psCvRbs^'3!=+O#v q ٳ";E]A~^f5ߵ8طۧ妛S<"`DB`ISE1UQ&AiY+yf6t.v"|RkRX0s% m0f*lE[uDzʄRJ9Q `9T7{H LLOݎ\:.lW̟Nc؋`O!ۆ/= SDP ⇜h5}Oqh(. Y;ICŦKY^$RFĩYL2 mӾkKz ?ۛ!6}[N]፸e 9_3qhc%"Z bMGdeZfkqnEg4 Jn Cշ& 4gfUNiPqH׏1t1('0jYwG I 3@UY>^OVVc/گ mABvr:]ORֳ( VnFHtB^Y6 kD-[V˿=c~\Sgؠ\z,(QdphTtkƌW v<{ׯ\?#_0>@5fd7A9@le ωu3 :zti1"HbV}:[c]FWOR5 Uy!D^JWV _ZW5|Z"xxt;w7*rhWaȸb1{Уc <Ɓ|)Vwszqp#1^ ` 3ʼ-'n//Ɗ$J\r`v4T>#y)o4S<^2r7#B~جf""Cd5HGdT /קؓ:M t塦 nɣg {<a÷;K@k[Ab2F<K5~ vuVXݶ ԋ{ӛ)/3.9jc2}#Ԗ(KJj* =c?f6h$PtJ7慯=#Lސh*3^温'h|&~ާ b`[Q%G0~!/]6VV1 IiUΕ$ eۦrY9k93& ^ϲ-@P{+1aĴy R58>SG(/f8*n|(@y XMY5_07>p1:tM硿eȴxSYtBlCS j|IcɿW1s(Dtד(t9I}kwu=Jߋf9 AtQ{qe܍|c!7Bd9Z{ziXz3fїG9l()go,ޘ;zD9W495s'@YH\x{kV_&=D/@V$xtF^Ə {^oPTm1;X wyz] _ݝyO4z. o; r(xt~C^  e`$pZ(=_':5y% 8L6qO:" fޱTyi&  J+X# \hk f\G( 7&"*jӐ;C:ȭ%C:u{u |فH |Kp=$覷]iPRA{o'C8=PӌEALzt|xLr +/ <]`EF#b|Mހ̿iƦ0zfky$4gtk\Q $xolF`6 gkdyq%cLQ1XDeSJ6e@AցuDZrK9d<Y)TmoSw.;p9P=6Ehdzӌ@xro\ pH:mp'7gڽO(;Lb*YS2w+Ο.=27>ej1f~ Xs=`K C.'N% ~5W-@nQi.vMgSAOy j1>5ҐȖ"^{0e0wp x❥nXٹ6zD8ջkhSc/wbŧ`^,.3'=%~At5 ly|~%[WʛGJ`&LB,C1׫,~g#ìFjƊsn"Ў=x᧿2ɕ]u[[3Oɪ_K=\Oj`q5xa˶8O<=rAOlkkP_TDFC<[ &1t TzphS5)Q-jzV$(~M]@%(nC3,з#,'*9 Wm`?-צ6+u`.5eyDde՞Zr8d01Ε>[X&\5UDTlͭc\D0?C@F88n<,_4"Vh01S6$>]!< 1=[E1|L>/40[Q~,"$ˊE} $ׯI(2~Œ=X| f8ja"E%"9@ 7OcYt6|uWO).GJhI/B]Nq36a=q˨Ę33Xzt},NhoT:'qs}ˈa/8dpVrs']HQ~"n4U¯㯪C¬Or7L;^zh(W1XK( UHXq ==ڏ;aiܞ˔I/>Qc DDQ@-4py rL Ym|g;yHꔊԖ֐cfJQ;~@-\yEH ݼKh. _Ǚ>?53hDE"`7 AB L:]woa FӓF N=3*~ZJVj8=a 2+Oj{8GjXnU򪃤b* B}}#풻p͕WUHKX d%c))* ER))1P,~̻u:l*"2`_10 @!#K1<{*Jt+qJGȯ6ʣavN;9c!gep%@^!AWC;L8k{ת:dís?2"bTEErV MUo@Gpkװ% pShˈSv I>7[҈#SP򻤲Ov|%\׷x}fkhR` =`<@b$$ȭsc_mi%Pj/XC;#T9`jwȠdgN~w_h:R( @+ϾS Z-e%Q~zFuBCe=sV,{&69$ʍL UCBl)SN. /xWdS8fј0i0sFLchjQ­c)j$" hhGzb:{oaN'?|1qIAt" /N.ɤhc.O]]EؾE8 1SUgRU]۳2p`[aTDyYMMKv$ ɠdɚT̢{>dtbPEUu4w#gq6~t̍ ˉMJ>:IHYOazr;xs9uo>SO$OT l@N|vг-zgR )1rAl>\*,/-tČjƃ͛;d "2gB qNc]xA,ꨦ˗ Ǽ'"c!H=Κ0b^DE 5\];VtJ[/g}ŏdέXOC[%1J"uZAt 70~l:XCBj4 "i( B0ۯ,a -= 4gu-Uʭ?3o`1+/qc?b_̦XY]M=f6RB_$ 牒F!!^Ì^RXc5KFC|C8 PQUňKǠ+*i+A{bn.ƽ)]],]2 R ؛7'MHBK?seƁpCn}+lNXnQDckh?" v @YE#' l~Jqw]+׎/~u7&_ E ݌َ9 m ;W52c˼n\NtYS- EB$ 0w|SK۟!@IY)OZ_El- ,B\68+7%5 vF@8L2E0KyLՒ/([t4+ɞ7xqڜ滌9 %|30@#Qb!ʊnHT˸4%u~1Y+e 6h׎OxXl,(*nzcﶝ'ͻ?KV E@0I"92 +~SWӟ@8fQH40ܾ,Hfch}dو 1<|u|N8X5"H(TȌɗ5pB#q ^P-#9((o/׌rXYB "fyc:T50us^b0MF /0ou-=$NX1f(tO5BMT3}815ͳ^Q&BF{egR\OBj4ހQmJ*Y~(g4iqBPq1X\Zaa5++sPXj@ 6:F4v\KӗeUoR$e6t"?eGZJrK '\hΧo}Q8c!0co_YSL1\Zeňq1̿u^&8~1LC ܍L2W:'aq.R`pOC}=߽:ᗍ!W3җx~\12 (zZcA<]2; 4/8σA@q5K&0hʅ5cqS&>ǖF#UFkh*TDtO#Q_~mWqR`o~>g-2%u2q?ӇM`ݚ<2K }ǯ` & kYDw7ү@>CRZ8{^&#W6"*/ZhcqEXc{>EE SlAB@ hs͕'-5؛aP *#"Y*N"W%DAϽ峦U\2|lnph*hn!(IT,"G&ɇ0x-} G'5o5q j"V AA§4Dg'.m>p^9y/ HP,+͆"Tuv-re1>;Y8UU ju o.ӎÖVCyY>r?oXϧѧi<Ӝ֯OK_ZpI >]N]]S&^BNZZ mhIFV6rmhh#@+GZ9FV6rmhh#@+GZ9FV6rmhh#@+GZ99DIENDB`MEND! yubikey-personalization-gui-3.1.24/resources/images/logo.png0000664000175000017500000000607112642452141022665 0ustar klasklasPNG  IHDR+obKGD pHYs  tIME %3P IDATx{U?r j5⃪j4GR_5jIcRP|T+6JUC,E EUCvwxfιUKnvs79%#hx}MYm2~׿E%`MyzxV~o{XvA+ ȷGޮ5[-`mE-j{3w uZ`ke &I<&;F|ʵ0ldmC>$+{>1L#r]3xDN9StGkQJĹEx`Kml e4MYm7ʮX <] d_]\DP`w`#=`QvMuXq"yQvCOl` .bK2<^{0rZ 0Y`KB<*X3 qI88q 0 8HgχSeR>-=u8}2OExFe8뀷#o5ޕcJ<$ HusET%qn2ϣ5@g3 9Hd4.`e`QvQSf>h!iğ!RE=Ebhd(n `QGN? |KvA9=({ypCeYԓI\Lv-o@&+9=8:4H|p|FOXǙ@g'DNYQ7;lGjHD[i/ׁJ H}l⪍K%X #oV&iZ"DGo 4*0NyFًgqoT(NKFYhw%}*#lS+dѮ΋ks dK""i:;nn5NOQJqӧegSQ!tGrQLېVX.~x~Dd Mu4'ϩ-Q(u#0'>?c!'ׇQG?-U;yN]Xgg({6䫕Z=9c\5 k&2Wϥs ˍWemJYy(C2pXt{>!r)[!Vȗ"/nM`w }@"1{~jc{d1'QX@;Ȧjv&Mkl-'=L|:O0xPEN%ODa=b]٠VZ+\7+Ӝ~>hbnG}dEeƜ5\79*q 6JlEsLϖ&AMKoSΙK_٣/$#?gUzGG5iZKU= csRJeO5q`WO5왕R -wR/I|q*ތDNI= _ PJw%}XWeז܃0DO>I:!ss,e0 >x4E"~x~4!C83pCWXډg93lK?q@LW'jg26GNϐnRk>"\49=8%9q׈;C1vj]5j&SyEtpQvY"ZM"LѼ}4,dѮgQvi铥{6k1qiA8xZ!{W=|oiӋfq>qdV.C !_GW*-:`LC}>!"{';5,0iFUae;#/^ËQWh#Bv%ͦ!W+Vٛ/4ɄV%rlzP+($sTݑӓ;{F|%q t;fWZZnbLcE?Q&nResT]hV#tc1C<>Nw l>،D@F9ELH2f kq○nh2)':ZsBc({;sq˓x(@3ȯR@PagQHkk=Z@< ]((mX^~B\άM6K _M؈?KLLjQ׈802'q|T \˧U$|0rUhli}`@ 8&rw K|hggYtItb&k| 3E[H|@(>7+4[2Sc.B\We6'"GHTo(*cQ\g,@ )oQEe[nTǹX5ʾW'#Rj<&tnM6DV`ТfmD>I$RZ5gMDIENDB`yubikey-personalization-gui-3.1.24/resources/images/recommend.png0000664000175000017500000000271412642452141023676 0ustar klasklasPNG  IHDRw=IDATxڕV{LSW{R*PEc2̅]m?|u.F˖mnQ42u.i2HQy((*컧-D3=M{},]VX9 I3v~{V|?IU`vrc(AaO^%uwza07@T#Z=Prh=. RC*FPuat!n Odž!L>f7K|R;(~U.h`(l]3aQ^6Ί^!_iSOT<_"`XZ:p6֤mbEԖc\x` J<^[@au3V hsuXY'ox:.G΂Xt ?7`8D 0beyZ5 (d-vmVxx Edʚk=X/⥙Z#HGeY&\'E  1/jڰ -.'?쩱d>Tqb<9>x|ՅV ș$!j#٘:q4|+4FEc` !GIĠ؆39|X(,r頗hWo.yB;n>W:'$nDջ`hR`cFk<gG2c#xykW`γqpAr`F~l "E ţ5`\r穀zYKj=p 2P]G.>6{RϗPŋÇ*`E~_XHk7GGFNr2ߋEd}c"mG: '21'P v{cG]Z܎,^0tMjӳrۅ3_my"w.FQC1ߨ&|SLVqǯ86G^YFDS)Ee1`T/5=?<\G1]K ! 5`d م\tX97a6Yz٭Ck^ÔwF*VuQ$z((ȧ3K1li-ڄE)16&. ٱK5~S{`RV(.dǾ >t%\? w5n9pl7Klg,b;  ~mOgF/UrWzuFK$v Ɍqu{a*o zEp.lEx(-/B?$ЙZ1R {$T*XU`^us153un-d7OwمuI|~ #include "./../../src/version.h" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_PRODUCTVERSION PRODUCTVERSION VER_PRODUCTVERSION BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", VER_FILEDESCRIPTION_STR VALUE "FileVersion", VERSION_WIN_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", "Copyright 2011-2014 Yubico" VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VERSION_WIN_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1252 END END yubikey-personalization-gui-3.1.24/resources/win/Yubico.ico0000664000175000017500000101502712642452141022477 0ustar klasklas  ( ˛ h   ˛ >~tU  @@ (BZ >~& Wu(   !"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ !$ # $ # # $ $ # # # # # # # # # # # $ !$ !$ !$ $ #!              " $ !$ !$ !$ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ !$ # $ # # $ $ # # # # # # # $ !$ !% $    (5 A!&(K")*R"*+S"*+S"*+S")*S!(*O #F; /$    " !$ !$ $ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ !$ # $ # # $ $ # # # # !$ #% $ 8#0/U(JAm-dS2~e6s8~:<>?ŗ?Ř?Ř?Ř?ŗ?ė<;96w3j/lZ)SGu%:5\ #F*   ! !% !$ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ !$ # $ # # $ $ # !$ #% "    #B(G>i0p\6w;?͜CܧCީCܧC٥BԢ@Ϟ@˛?Ƙ?ė>Ė>Ė>Ė>ė?ŗ@ʚ@͝AҠBפCۧCީCݨBԢ=8~2f*UHw"--Q .  "% !$ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ !$ # $ # # $ #& !%  #0/S-eT7x>DۧDBإ@͝>=====================>?ȚBբCިD@̜:0xa&B;d8! #& $ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ !$ # # !$ #&   !&(H-gU9AѠDC٦?Ǚ===============================>”AӡDCۧ<1~e%<7_, #& !$ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ !$ $ $!$'$'H@n5s@͝DAգ>======================================@ΝDBڦ:,cR> !"& !% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ !$ !$ $ "%!&)-+aP;DCݩ>Ö============================================BԢE?Ƙ1}d!()K  "& !% # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ !$ $ !$!&( +-hU=EBӡ===============>?–@Ř@ǙAȚBʜ?Ö<======AȚAɛAǚ@ƙ?ė>==============?șEBԢ3l!**J #!$' $ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"% !$ $ $'!"& +_P=E@͝<============>@ƙAțBɛA×?;71{.q7?Ö====>91v4y7<=>?ƙAɛAȚ?×===========<>DBפ3i!=%!$' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& !$!"%!!%"&)'B;f@*hH]>bCeEoO ~_-m4y:=?ŗAʛ@Ǚ>=========<>E@Ϟ.lX* !!%!!% # # # # # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$' !% !%!$& $!&(!$25qEB֣<==========>BʛDʜ?.z]mJeDlP8gV~stgCț===3@bEu%y] hHaAdDuV-k6{;?•B˜@Ƙ=================oR1n8>B̝?•========>E>$61P %!#& # # # # # # # # # # # # # # # # # # # # # # # #!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!"%!$&!$& "% !% "%!$'!$&!%( $#60S>ǙE=========B˝>======Ė<========F̞=•[jLmdHҤ?×@Ę@Ę5“BřO~iFcC,c8@ƙAɛ=======>=====4o@Ǚ======35z04>=========•======<>@Ǚ==C$#ɴZ{UwY{Y{Y{Y{Y{Y{Y{Y{Y{Y{Y{Y{X{Y}`_a"&B===>>>>>>>>>>>?4ÓHxem'$C===AȚ<===<@ʜBԢ!= !#& # # # # # # # # # #!$&!$&!$&!$&!$&!$&!$&!$&!$&"*++\MsF<=====8uw`=(w]<@șEÙ!&h@=============:;ÕklmY_=+{a=AȚEƛyBt-eaC;B̝=====@ȚAӡ"!A !"% # # # # # # # #!#&!#&!#&!#&!#&!#&!#&"') *VI\E=======Bwl`=)z_E$dF*>============?-ʕYvY`=+z`D?rmLoT>Aƙ====4ÓEvel\c@pL>v]:/kAȚ>=====D&H;` !#& # # # # # # #!"&!"&!"&!"&!"&!"&!"&0w`E<=====@.)JyfC15=============>1ɕ`~uK|"wZR\=;B̝<===5#[Ÿ"@============?-ʕWuDtdD>@Ț====@˜=====?.5B.>============>1ʕ`v\`@>@Ț=====D'OAi !"% # # # #+]OfD<===============>0ǔNgq fG*kBɛ====.8.8>>>==========;8Ɩhqo`bB??Ř====>AӢ"0.Q  !$ # # #'D='D='E=$63*TH>>>>>C}˶pȩB>>>=========?-ʕVr} cD/sB˜>>>>=E0v`!#& # # ##10#10#004pEܧ=>>>>?6.!@?>>>>========5“BrglP| oMB@>>>>BΞ=2 # # #  >>>>Amũbţ)@?>>>>>======>0ʕ^xĻ^>:Bɛ>>>>>Dۨ'I=f !% # #)MD)MD&@;.hWEBϟ>>>>>>?п C???>>>>>====>0ƔLfp*x`fDɝ>>>>=E3g "% # #(H@(IA",-5mEܨ>????A-G[ġ,A@????>>>>>===;7ƖgspujGBA—????Cϟ=1 # ##,,"&("%'=CѠ?????Bʳ%B@@@@????>>>>==?-ɕUo| dE8Cɛ?????Eئ%>7[ !$ #'D=%;7(KB*AŘ@–??????"x˯!EAA@@@@????>>>>=6@qin4}fhE˞?????G/lY  !% #(JA$942fgEפ@@@@@A/G<9BBAAA@@@@???>>>>?/˕\{ntPEřA@@@@Fڧ8y  # #)QG$636qFڨ@@@@@C qȫ"GÙCBBBAAA@@@@???>>?2ƓKfq»iH?Bƚ@@@@C̝@ ; #!%'"++=DҢ@@@@@A]Ȥ-FØD—CCBBBAAA@@@????>=6ƕfvrpT0D˝@@@@@F٦&>8\ !$#10A×CȚAAAAA>+.DØEØDØD—C—CCBBBAAA@@@???A.ɕTq}BphG͠AAAAAI-^P  !$4{f6qFCțAAAAAB1HҸ%JśEęEØEØD˜D—C—CCBBAAA@@@@??9@rlok ~YG̟AAAAAH4i !%)J@6nlGئBBBBBD&eȧGƜ;ÕGŚFĚFęEęEØDØD˜D—C—CCBBAAA@@@?A0˖_ uQEƚC—BBBBHڨ<~ "&956nGکBBBBBD—!϶(KǝGƛGŚFŚFĚFęEęEØDØD—D—C—CBBBAAA@@A4ǕKissQ?DǚBBBBFӢ@20gW=H֥CCCCCD iέ.KȝHƜHƛGśGŚFŚFęFęEÙEØDØD—D—CCBBBAAA@@6ȗhzvwZ9FʝCCCCEʜEʝ")+J@&BEʜCC—C—C—C—B—$6ĕFȜIȝIǜHǜHƜHƛGśGŚFŚFęEęEÙEØDØD—C—CCBBBAAB1˖Vp}1zc+}HΡCC—C—C—DřH٨&<7Z0gV5DG͟DD—D—D—D—@/)ŽNʠJȝIȝIǝIǜHƜHƛGƛGŚGŚFĚFęEęEØEØD˜D—C—CCBBAA=Õ@ØqorHx#xJ͠DD—D—D—D—K)MCn -ZMRDGΠD˜DØDØDØDØ:lFɜEŚEęEęEęEęEęGĚFř/*,,,,'rӳ1ƓOˡLˠLʠLʟKʟKɞJɞJȞJȝIǝIǜHǜHƜGǛGƛGŚFŚFęEęEÙEØDØD—C—CCB6̙gz{\z0œ,,,,+*?–IśEęEęEęEęEęE˜M5yc 9qvHΠGƚFęFęFęFęFęFęFęFĚFĚFĚFĚFĚFĚBØ2=ʚI˟M̡MˡMˠLˠLʟKʟKɟKɞJɞJȞIȝIǝLǞAƙ?×KǝGŚGŚFĚFęEęEÙEØD˜D—C—D4̘Wr}:q3IˠFĚFĚFĚFĚFĚFĚFęFęFęFęFęFęFęF˜N7i :s~HϡFǛFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚBĘ3-ƑRΤN̡N̡M̡MˠLˠLˠLʟKʟKɟKɞJɞKƝ=ϝcb;˚JƜGƛGśGŚFĚFęEęEØEØD˜D—?ŗAȚstv:q3I̠FŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFŚFÙN7j :tIϡHǛGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚCĘ4WШ>ɚP͢N͢N̢N̡M̡MˡMˠLˠLʠLʟKʟKɞNʠ+Ï(MȞHƜHƛGƛGŚFŚFĚFęEÙEØDØF3ϙ`:q4J̠GŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGŚGÙO7k ;uIТGȜGƛGƛGƛGƛGƛGƛGƛGśJϢKѤKУKУKУGϡ8˙3ȕQϤOͣO͢N͢N͢N̡N̡M̡MˠLˠLʠLʟKʟGТ88”DƚHǜHƜHƛGƛGśGŚFĚFęEęEØEØ;əMow:p7“OتKУKУKУKУKУKУKѤHȝGĚGƛGƛGƛGƛGĚO7k 8n{JңIȝHƛHƛHƛHƛHƛHƛIȝCƚ4y1u3x3x3x/uiyٺ3ȕSϥPΣOΣOͣO͢N͢N͢N̡M̡MˡMˠLˠNɟ6ϛejѯ/LȞIǝIǜHƜHƛGƛGŚFŚFĚFęEęF˜8ϛi~6n j5z3x3x3x3x3x2w4uDKΡHśHƛHƛHƛHĚP8j BrJ͠HȝHǜHǜHǜHǜHǜHǜKʟ@ʛ ~_nSxZwZwZtW gHD͞J͡PΤPΤPΣOΣOΣOͣO͢N͢N̢N̡M̡M̡O͢.*NɠJȝIȝIǜIǜHƜHƛGśGŚFŚFęGÙ6ΛXt-j mMvZwZwZwZwZwZvY'pXDLԦHƛHǜHǜHǜHśP8j EhIǝIɞIǝIǝIǝIǝJǝ>ŘIƛ0ǔUЦPϤPϤPΤPΤPΣOΣOΣOͣO͢N͢N̢NˡEԤCAǚCǚJɞJȞJȝIǝIǜHǜHƜHƛGśGŚFĚBƚB˜uyz\*NѦIƜIǝIǝIǝIŜQ4ub :n\IʟJΡIȝIȝIȝIȝIȝAƙ>Ö_ԫ=ʙRϥQϤQϤPϤPϤPΤPΤPΣOΣOͣO͢O͢Q̢3Ϛwvֶ.OʠKɞJɞJȞIȝIǝIǜHǜHƛGƛGśIĚ6ќbZ'NФIȝIȝIȝIȝIǜR2hX -TICJśMԧJǞJȞJȞJȞJȞGǜ36ɖRϤQϤQϤQϤQϤQϤPϤPϤPΤPΣOΣOΣOͣPҦ3¾,NˠKʟKɟKɞJȞJȝIȝIǝIǜHƜHƛGś>˜NÜszH3M̢JȞJȞJȞJȞJǝS/[Nw ?}.JƝLУJȞJɞJɞJɞJɞJɞ)ݾ2ǔUЦQϤQϤQϤQϤQϤQϤQϤPϤPΤPΤPΣP͢A֣RKˠ@ȚLʠLʟKʟKɞJɞJȞJȝIȝIǜHǜHƜIś:ўl<{>˛KʟJɞJɞJɞJɞJʞR*JAd@GNרKǝKɞKɞKɞKɞMɟ(HΟH̟QϤQϤQϤQϤQϤQϤQϤQϤQϤPϤPϤPΤSΥ2˗ۼ/ÐQ̢LˠLʠLʟKɟKɞJɞJȞJȝIǝIǜJƜ:ОYu+tJӤKɞKɞKɞKɞKɞL͡Pޭ&74L>zGNէKɟKʟKʟKʟKʟMˠ,ټ0ƓUЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤPϤN֨:/đO͢MˡMˠLˠLʟKʟKɟKɞJɞJȞIȝIǝGȜCϟu~}ƿ tP֩JɞKʟKʟKʟKɞN֨L͢!#&81bT@QޮLɞLʟLʟLʟLʟNˠ3Òdѭcծ:ɘSϥQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤSͣ=֢cRϤ?șN̡M̡MˠLˠLˠLʟKʟKɟKɞJɞJȝKǝ8ԟczR֨LɞLʟLʟLʟLȞRG:oB\PةLʟLˠLˠLˠLˠMˠ?ȚMʟ8ȗQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤTѧ4Ǖ/ĒSΤN̡M̡MˡMˠLˠLʠLʟKʟKɞJɞJȞC͞OȞv}i*PХLˠLˠLˠLˠKɞTA  $A|D2OϣM̡MˠMˠMˠMˠMˠL˟3Ò0ƓUЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQΤKקD4ƕN͢M͢N̢N̡M̡MˡMˠLˠLʟKʟKʟKɞLȞ<աkK:˚O̡MˠMˠMˠMˠLɟW8|g "%9xcӠZw2LרMˠM̡M̡M̡M̡LʠW.ZLo !!&ʛQͤPΤC˝QϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤRͣ?֣]@ɛL΢PϤPϤPΤPΣPΣOΣOͣO͢N͢N͢N̡NˡAգ[x}+ĐSЦOΣOΣOΣOΣOΣQԧT$.-: "#%!!$FFDKpSڬNˡOΣOΣOΣOΣOΣQϤ.ő2ƓTЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤTЦ3ɖn׳8ȗTХQϤPϤPϤPΤPΣOΣOΣOͣO͢N͢N̢M͡E֥wFCӢPͣOΣOΣOΣOΣN̡WH!$!!%!!%7q`7q`5iZ:zg%SثQХPΣPΣPΣPΣPΣSϥ0Ɠxطqص5ȕSХQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤL֧?0ƓUЦQϤQϤQϤPϤPΤPΤPΣOΣOΣOͣO͢P̢?٤e)TӨO΢PΣPΣPΣPΣOʠ\7vb"#'! $! $/TK/TK.PH,JDLUPͣPΤPΤPΤPΤQΤH̠>ɚ?ʛM΢QϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤSΤ9ӟlF̞I͠QϤQϤQϤQϤPϤPϤPΤPΤPΣOΣOΣO͢IѣPϤ}ǿfä5̚SΥPΤPΤPΤPΤPΤQҧW%62>""&! $! $>s>s>t:~hFjUO̢PϤPϤPϤPϤPϤUЦ)Đ0ƓUЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤSҧ4ēwڸ5ǕUЦQϤQϤQϤQϤQϤPϤPϤPΤPΣPΣOΣQ̣@ڦm2OӦPΤPϤPϤPϤPϤO͢XH !$!!%!!%!!%=n=n=ns %"""";i;i;i;i:}g9xcOȟUܮQΣQϤQϤQϤQϤQϤVѧ)ďBʜK͡QϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤRͣA֣W2ƓSХQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤPϤKҥPӧ~Ƽ6ǕLϢRϤQϤQϤQϤQϤQϤRҦZ%80="#&!!$!!$!!$!!$=o=o=o=o=p9yeDVUQΣQϤQϤQϤQϤQϤRϥF͞?ɚ/ƒUЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤTЦ3˗SХB˜RϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤSΤAݨko׳1ǓVЧQϤQϤQϤQϤQϤPʡ\D!$(!$'!$'!$'!$'!$'DDDDDCCQϤSթQΤQϤQϤQϤQϤQϤWЧ.őwطZѨ>ʚRϥQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤO֧92ƓVЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤRΤGئ\˦pz+ĐQϥQϤQϤQϤQϤQϤQϤQХ\(F:H "&)!#&!#&!#&!#&!#&KKKKKKIM›YTڬQ͢QϤQϤQϤQϤQϤQϤPϤ,đ4ǔQϣPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣSϤ8ќj4ǔPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣPϣQϣBؤ«QΣ;əUЦQϤQϤQϤQϤQϤOʠ[G !!%!"&!"&!"&!"&!"&!"&EEEEEEECOˡTتQΣQϤQϤQϤQϤQϤUЦ;ɘO΢gհ?˛<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ9ɘ&ÍUЧ&Ď=ʚ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ<ʙ>ʚÊsߺ)ďWѧQϤQϤQϤQϤQϤQϤQѥ[)A;D"&)!#&!#&!#&!#&!#&!#&CCCCCCC@xINVP̢QϤQϤQϤQϤQϤQϤWЧ*Đܽ@ʛ1Ɠ.őM΢RϥQϤQϤQϤQϤQϤOɟ]D"%(!$&!$&!$&!$&!$&!$&!$&>q>q>q>q>q>q>q>q:|gMUޮP͢QϤQϤQϤQϤQϤRϤPϣ*Ő>Ț:ȘTЦ$Œ5ǕA˜M΢(ĎO΢:ɘVЦQϤQϤQϤQϤQϤQΣTڬX$!+!#' $ $ $ $ $ $ $4aS4aS4aS4aS4aS4aS4aS4bS/OF?r*XRХQϤQϤQϤQϤQϤQϤUЦ@˜=ș=ə7ȗWѧSХNΣ%Í8ϛ<șWЧTЦI͠(Îvط*ŐWѧQϤQϤQϤQϤQϤQϤOɠ_;g"#( $ $ $ $ $ $ $ $CCCCCCCCC~AzNĜ|V߰PˡQϤQϤQϤQϤQϤQϤWѧ2ǔZШ<ș8ɗWѧQϤQϤTХM̡-˕`<ĕ]߲O̢QϤUЦI͟(Î'ĎSХQϤQϤQϤQϤQϤQϤPʠYP͢ "&(!$&!$&!$&!$&!$&!$&!$&!$&B}B}B}B}B}B}B}B}B~Ay>rQϤT٬P͢QϤQϤQϤQϤQϤQϤWѧ(ďAʛ8ȗWѧQϤQϤQϤO͢]ڮ3ʖk[`=?tPΣVݯP̢QϤUЦI͠&Í,ŐK͡SϥQϤQϤQϤQϤQϤQΣSը[(A:E ""&!"%!!%!!%!!%!!%!!%!!%!!%!!%;j;j;j;j;j;j;j;j;j;k7q_C~7WQΤQϤQϤQϤQϤQϤQϤQϤRϤE˞AʛC˜WѧQϤQϤQϤP͢[ٮ9Κ,p\jK9pRФWݯP̢QϤUЦH͠E˞J̠G̟UЦQϤQϤQϤQϤQϤQϤOɟ^@v!$"#'!!%!!%!!%!!%!!%!!%!!%!!%!!%?r?r?r?r?r?r?r?r?r?r?r<~iLuVQͣQϤQϤQϤQϤQϤQϤSϥNΣI͠TХQϤQϤQϤP͢[ٮ9Λ*oZkJ9pRХWݯP͢QϤUЦJ͡H͟UЦQϤQϤQϤQϤQϤQϤOɟZM"$(!!%!!%!!%!!%!!%!!%!!%!!%!!%!!%?s?s?s?s?s?s?s?s?s?s?sϝN͢QϤQϤQϤQϤQϤQϤQϤQϤOɟ[QΣ$0."%(!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'JJJJJJJJJJJJJJJ?uK~UۭQͣQϤQϤQϤQϤQϤQϤQϤQϤSХ2Ǖ}ڻ4ǔLΡRϥQϤQϤQϤQϤQϤQϤQϤOɟZL!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJA{GS֩S֪QϤQϤQϤQϤQϤQϤQϤQϤSϥRϥ&ĎgӮxط%ÍJΡUЦQϤQϤQϤQϤQϤQϤQϤPʠWU߱!+)"(*!%(!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB|HTըQ͢RըQϤQϤQϤQϤQϤQϤQϤQϤRϥUЧ-őL͠L̡*ĐSХSХQϤQϤQϤQϤQϤQϤQϤPˡTܮW9xe "')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUۭHKS֩QϤQϤQϤQϤQϤQϤQϤQϤQϤWѧ9ɘ/Œ¸GrlձlֲlֲbӬlֲ,Đ9ɘWѨQϤQϤQϤQϤQϤQϤQϤQϤPʡV߯V@z"5l[#,,"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܮIDR֩RӧQΤQϤQϤQϤQϤQϤQϤQϤQϤVѦJ͠&ÍZШ ^@إ9Ǘ9Ș9Ș+đ9ȘTϤ'ÍL΢VЦQϤQϤQϤQϤQϤQϤQϤQϤPʠWT٫>r >q:|g"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRӧPˢSըQϤQϤQϤQϤQϤQϤQϤQϤQϤSϥVѦ6Ǖ.đݿ#s[ޱSϤSХSХG͟SХ}ں,Ő8ɗWѧRϤQϤQϤQϤQϤQϤQϤQϤQϤP̢WM›3bT;jB}:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRԨM›LkRѥRѦQΣQϤQϤQϤQϤQϤQϤQϤQϤVЦNϣ*Đ@ʛ"qYݰQΣQϤQϤE̝QϤ9ȗ,őPϤUЦQϤQϤQϤQϤQϤQϤQϤQϤQͣQϤWTت'64-KCAyA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞHNĜAQѥRӧQΣQϤQϤQϤQϤQϤQϤQϤQϤRϤVЧE̞)ĎI˟"qYݰQΣQϤQϤE̝QϤ=ə*ĐJ͠VЧQϤQϤQϤQϤQϤQϤQϤQϤQϤPˡRӧYJG(:81ZN@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞIMMQϤRӦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤSϤVѦC̝(ďCʜ"rYݰQΣQϤQϤE̝QϤvط8Ȗ+ĐI͠VѦRϤQϤQϤQϤQϤQϤQϤQϤQϤQϤPˡVX=m[7s`K+C>0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšKNÛRѥQҥQѦQΣQϤQϤQϤQϤQϤQϤQϤQϤQϤRϥUѦG͟+ő6ǖi԰kZ߲QΣQϤQϤE̝QϤTϥ.ő1ƔL͢UѦRϤQϤQϤQϤQϤQϤQϤQϤQϤQϤP̢RХWOǟD&+F@:iL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNŝPʠPˡMQϤRӧQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤRϤUЦNΣ7ȗ*ĐCʜoִƷ'|X٬QΣQϤQϤE̝QϤ\ѩ6Ǖ+Ő@˛SϥTЦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤPˢT٫VK-RG?t4cU:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OƝMP͢RҦQХQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤSХTЦJ͠5Ȗ+Đ<Ș[ѩ}ں7ϛSΤQϤQϤQϤC˜TХiհK͠/Œ.ƒ=ʚPϣTЦRϥQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤP̢QϤWUޯ@z>6p_1]OB}3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟN™MOɠIQϥRѥQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤTХSЦNΣ>ʛ2ǔ-ő3ƕH̟[ҩjձ|ں|ٹD̝RϥQϤQϤQϤKΡVЦt׶cӭRϤ;ș.Œ0Œ7ȗG̟RϥTЦRХQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQͣPˡUޯVKt:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNŝOƝQϣP͢QϤRХQϥQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤRϥSХSХSХRϤQϤQϤQϤQϤQϤQϤQϤSХSХSХSϥRϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQͣQ͢T٬VޯT٬L<9xeB|Fs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOɟPΣP͢QϤQХQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQΣP͢QХUUPΣIBJGs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOʠPΤNɟPͣQΤQϤQФQФQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQΤQͣQΣSتUݮSתJG8DAyKI=mDFs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOʠPΤOʠQͣPͣP̢PͣUQΤQϤQѥRѦQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQΣQϤRԧSתS֩OʠJ|H:~i>sGDKI=mDFs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOʠPΤOʠQͣPͣP̢P̢P͢PˡPɠrP͢QϤQϤQХQѥQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQϤQΤQΣQХSӧSթRԧP͢PʠN:C@wG?tAzGDKI=mDFs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOʠPΤOʠQͣPͣP̢P̢PΣPˢOŜNěQΣQΣbQ͢QͣQФQФQѥQХQХQХQϤQϤQϤQϤQϤQΣQΣQΣQΣQΣQΣQͣQϤQϤQϤQϤQΣQФQѦQХRҦRӧRҦQѦPˡNÝ{J3HJLDCH?tAzGDKI=mDFs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOʠPΤOʠQͣPͣP̢P̢PΣP̢OƝNƝQϣQͣPɟOƝOȟ-QΣ`PˡQͣQϤQϤQϤQϤQХRҦPΣTثWVVVVVRթQѦTڬQϤRӨRѥQϤQҦPͣPʡrNŝ?M KIHILLECH?tAzGDKI=mDFs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'IIIIIIIIIIIIIIJB{HUܭIFRըNŞINšLNƝP̢OȟMšN›OȠNƞOǞQϣOʠPΤOʠQͣPͣP̢P̢PΣP̢OƝNƝQΣQͣPˠOƝOǞQ͢NŝPɠPˡOȟ"PʠAP̢[Q͢oPʠQХN›JKKKKJOǞPɠJzP͢bMÛKL.I QϤM›MNĜLMJIJLLECH?tAzGDKI=mDFs:|g2dTB|3aS:jL+C=0YM@wA{:zf"**"')!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'!$'???????????????PNG  IHDR\rfIDATxw%IV ?'"]_63gvǬe]- >^~!! B@da .gM{W]nui"iW[y3##8qS7Z ,DR]"3s'[@dKpPԨr)ό@,@Dں݅QObШק%?4\h7-t8hDhNlwm F*92$~4a@@'dZ&-9"k@Y%*Eo#I%j"| vn$ʀmbOjsSHV7>*<0$!B׍²݌&ha*zb~2=}1nTsO/׶7_U/$Ll AMDh'@2Clu;oyp)(#af'T?,;ǗS>wg+ɭnMmpS3u< w2GIcDP4gfszANjYWgφ5kA^X[K$musohlo?!A$Y^0> ^!ioӯo,Ϣ C@b ilˋsSBWh2WEp9l+կ|+)8T--$6!$!SPZY?^}]9bӿz&+/M:わouSrX;cXe(%6Wke:OTti=?7/=B9blnf$AN$[}I?oSw=c_fn9޴/osK^-DtYc SNfv?Qf@ǖeA 91ud^ӛtgԞ!|UP@ Z-&똜 /`j fO-!IߋIՎځdvcOJÉteG5 J n'St \SmSgӟ}f۶ ʷR)xFJqI3,=Csı2Eo0*iP_* ` nXK|lj@5̦32p(݇ҽLMkdTS9:ې̐+lX)(oX|ν<_v]o2 /|BbX|T& 9c]ekn)MB^<$@9Ǖ7H Dur~z %=U]zE9?ۅ⇭eu~Կ3 '̢e@hݾ.Cͩ.j T!sGCj_xVsB gS2Q_̷8.E$pli&[F/¾Z;n*~B q>O^F- W`ֈuJpm`A%&1o.̈z0o)<2Wr#I GHf=TbđqwfMX7mu f^V[Y-Qgt}?OH$L 8f`Gnu߼ s^Wpww]9<<8)8( GfN! Z3fFA7_vg1]9x'>?#^/SP?O2:qTm?=w>:~3, H_ucړd1"66ÅǢF ~戴DQϛ} B,CN.=LrxR0, \7@Bb\wd>s8xk7 ǿ$ X?Ό0q}'6BLɃ7U ̋i98I^FB'+`Ħۉ#Ⱥ][}k,hۭ+\07y" HAdψ/+قZo9IG}w {or`˕)b"WHb{~$D?, ^ ~鿈_]Uӳ'Rs]e {<;ZUӟ-7ZKAVHOݖ:?Hlh'2#>nRsX뒨@g=%|Ƞ9S+Ǭe8@{G K }nz׃xf ml.pU>*\툭&"%7!I0N#);?(/-nuWl2y+%C!Ot隰 =>f$۸.`H еx.k% ImDMbAә {_ dk;a.OН: ':d%P:g*/w_Ew nM| 3966xHBܰp}:Gڊc}3{%tan% o+I??~wRaՊa-3z؏P1qHᨁ"p:kME(nhz fJC^_yB{:Q?>n ~A'6k +5Bx_?P=؊Mٙ)ۼx!< Dr.$畄zgԟ657C6u a! ?n :m ' %<ߞy0=un_۟ := D /y)7)Iln>dc̽_Mv搂 v?WTߖ+9!'m"Q% ˧\$;G#VH}?1:9WFs탈Ka! A Bs'ι{Kٷ)o>!(%d˹+ȫǦPvZ2(tjs^`[ |rr_۟5?~NLz,! v1 DF_DZ/ٕ=0rgAϮo|uSS]۝u?Ww##QJJ_X\';Vo¿/OODi1"5& ̤ʈpa?D扗:77Ё6̗E|7]]fD'An?YCۈ\V(B1B'^xkCl+[F/|/ c{A$k ?6dPa(M0o<٨F<Ƕ"Ui|@pPLbPfhCÄ7LNLcŎlX[|"6*?2Ϊ;sUadO~GI=&%¸ G }n[D1ʄ;.&-avH)P/+ѣCȌu#P" +/ғҳH+!ݓ5uqNz= SEX-u~2+6'Ħ΂eGV'G'c]'/4j!15l~ DVm\R[mL6ww uo љIZGd%IBbDI'H\sWg:6(@hC`Dbs` Xچ޿.ME dwNu=,kr ?,}g_#F>.w ߧ9]ѧt A ٝgR W: 4dzaa}lK_=#)onsQ5js bS3{z~UO@vnFT%U<ĦZHG%.m@5 Ǜ@%ѯ,k$̦ar٥wyYO!B" R?2op[ٙmjG1'.l-C*~̡S{eźY5|^{|zG{w(kx{ZDb{sFw~V}`{bEE(dOG?J^M Obq S_0W'i{ Sŧa@ ?9 2ڂq RGG8|/Fg,"~H?օʌ_wG, O%B3 wޛkZYt="w/ D>ﻐqcSഹ|O̰Ѿ?q|0~pj5¿=3ڢNK|1:rsIh u5P_闆j0wu=Pz)T {&=]- O0.X*2n&Z'M^p]B(k<|c?@h9g`n5y> (K'Ǘ݈^Vwt}Xz):M: jiF;.jY?ffךhMdr2p}w6jF=eDzvgFtdQ9@vdƕrkRxKfj|zM$2(/͡1]BWn7N/>cs_d}GnYމn::C(A˿YSGn@82P*v&f͍ t7:RzE(֔=e-(O7WTGm#θcZnM8*#1f]pTWqMZ`8tb[KRd (٧ǁ2(}{:M'&45^UGKk|{0J' -+|E[든+iAljvG7#:롍 836fj{& 6cx{ژTe I`pc$ Ep`=wbhhhKuGdW86U ύ0;.'˷w zxk\#xyCۓ/9G6BTcS;X늌Ӊƒ X7l J:<&`f]rM$g/[ETG&Hm>mH@-؝a8HNݒ(u=jæ#3v ?x*}ȹ݈"6$CK`*H_B05{cavFP"e7 7{6jjC?UbpmIlkvSVKԣ6G 7}ϳO !te 15` ((ߢcz0[T"K_  3׍0c GHF2Hi  :WC^1+ߝ-$Xf0[;.vӎȺ],>%}hD&pn0j LU_+yQrb0GЖ0|:ljm.`yJp}Ng/e&ϗ=~y2 `low}n3S7[0dn8Нۃ?H/n>itji\0P-DHm|9$cNJ0<2Re},fʴ5ZXTt wjwtɵ^A\i}?y+Ԍ($}ޣqs@bvV{Z}c#v?-&'1V;l~p"M0S=6V+︘g@jąCX73oȿk@kaq^@y_B1 qde@{AIbtM=U2#m#鍆iCNbd 8,Ϳh`qSWPLz-jva@O_'/G[[Iނ*@&Yr"vgj`fK^ kR7=5';N V\1.+{7I@ tew#2;~>ٳ~a,E~l[柗|'zIͅTMCD$nx;JXNe BݞH.[ù7,D{4~u`k`-,s˘Ⱥ](<I<_@gNaj&򑉩cvm@2Z_ '30}h4(044 ϻy !!N1:bto|`ÁN,trpRynghsM 3V8"@On/^d %8e˘(d%~HWT̐beuL]GY&.j N04H#\XL9/j1+U԰ ;.tۚ/)ȷIEr=3#Ui2V2W"7w '[0`@zs[>luT7k'.g_V(āGXӗG g`02c@d*-)155s/9W;A,۱j?˺+0|rcߤJ03"1 gKjm6Ш1x{lAzqhD!nm3~VF5tfo3`@2߼ٵ?@@!6Ys İځ N'P_dj7nsȿ; 㺰ºnydaac]]C~oe3عb:"PP(t()ubf"/b#mon%&-\Cozq@Mp=M(Ίֻd_Aa\JSra J@hwbvzR2: clAْKx٧Hq-^%Ji&8'Φ9Mޛ7? ;Ag&u1_; @?3wɆ+/؅GXKG&2 !ÝLI%]ֲܑ+,3|6|Q ''zǂ!X>Zn"1 v̘vحmf z'GbjP"M M$@-8c C$M`@4ɿ+NWܷd'YB1si"!v?mԈs6o,;S}3IXVO(0 1eksgf7KPhD[0Po>8yL.TmC"btS`XCOi+m62i>UG3~Ɔ99hʼNa͈~o Y`gvX:<{2߮Ċ \ INĭ?ls{П T`13o ,'A$ nz XNa9؅4򯣫 PJr ZFddO6YI^̲-Ev#N IŊ ܏? ;5Hǵ|, ǜulgv7D[ͬn“ۚD $L ATMGޛ 3"ˊ}=zW$W 't5 a [4{'jYVkř!D+S.]. xۺ2o:h5淖Ц?d~:- ZX(ށ66?J&`zj~2 5 fI)5O cfnZl!(0~FhlNhƚ_#f -uþ/V3 i& U\3dEصd ڃ,FeӍ[pjihSOdm"Z4P1={ Cc AvmmBQ,g?hEu|WzvQTخqttt^pao'>;?{s,Y9Vcق>Α 1Vܖ)Jaz@ض` vCCHe](CFª 5Bh7*¿A0 >D5ʔoigfx/K0[Isbm nO鵆!%$Qr%\I ?'vE*?FwIʍ4;AE_>X擁 8:f153v%i|&B B I]Xf]G }R @k b{jK Ĭ 0E)H(:O*@ ѤaU -Cvbu`/G翀HW6TU@ 4&?əcZk@Z~~Kr\~UntO d`Q"1C Q8qڰL.Y IR=u=>a\9X{13Cy7;0lQ ѕoʆDns0 Ҩ2bS#Ө;,Wֻհbsh"JoMo%D]N,6Ȁ5Lm=nH-\k@zťZ|NI7b!h>`:=,gCbiMdT̝EgS<jG0]߸qJW@2Yja0:::Oݺ3^E>@U='1Sq]_2\[A"zF|"ߦ"׮s e~?Rxfl!EwvADf . a()LLAT\`Psl0 il`#q+#^neXc#:XZl4w[pl3 K6LKP` /dDmq=#26vfxHWy8 )+i :lu ^d5$o-lEr/;6I[6 鈾Qv6Ai(GM#C6ٙ)6K#L 5p:Ͼlywd._Ӗ& n{hV+8< @$1l Zw-䗝;~{ , `X,iFlCڗxfoS%"hqVqENl2h `NK. m:2qz)4_O&+3=݋{%zI !Y8j_|Iw]8n6 avZb)Q<=x{$*zHDڃe,C9DAN ADAvfN*5#}Ud\v ``fXk=?%f0%_&q'Uazz*"f5=ɥנM%4}%Y|eJ;$p?:::`YS4Hzm9 U  @y;F31x3 EBI~ShkZ|tDbxY:^|"4cu(&gN`xRȫ |(ꇑK0? 2d}sWb L*MV&PCu:&$>Wp╚ )i}5@dn6apۏ`h`}sa9iLpv+ I l5Peoef*`{h4ہ޾/߄JX^@٠z-+:L&/y)!ӂoڒnSF*sQZlC_ "[' X}dUrY*S~Ng48%HT LV^1\'MeޫsWYfq]eR.>~R\BMy#{38mּx/͂kHsIQ^,RC[Ѩq0$Z ,3:qc W.]l_ovbpe &gOb`R hm \xSWa@U_wrCFvz= B (NifDIU5%h,RvE]f-q< b %Z UY4IGSWT r&q*|[ ه̽EV7b+l7.jI9 ۮ`4(֎M@{ps `BÔ;a*[::;Ҹ0GSA drvx*`0š54c&Z4+5 VA(/p\{!j+ˌ fkZH%BjÛj8"@oUCC!Pkv)7Yb3Sȵ‘"kL,.n^?U N+ټq9lXVl4ߦ}cYf ˰zY.nZfa01X= /bAޓ jV#AV1E t5%(y/4˓+m6`㴄X;ɣ(+t}_3JM{T\D9>^atfdNBkқnQha] XO.!U8a{՟+,bckt)e,ߓ@A>p۫ O5U(dqv~?D&t*9(]DwMV嶭hHN3ߋccc7y R[7z \CӒ|OSiA tev !t~/slvQ00zHteVLQ.i㕄 0,|񷽫67.W͐kު|\Y\"ߚTح܅e_V'Ȱ0U܇tsͯ6b~Va)sSӧnT2Dn1 徖r\0;nwj>/+N߇"s[K ,5&d}pDf jܿ6$9pr >複$X#Pu]fW?pQta,':W[$cb,R j J[/,X捠= mL+ӗ1W-激Ӌ$a/+/߸RL Qo=ݽܔ+r2^+p>J`a7SD= m`ϫv៕08]iٌIXxոW=ۇ"cctrJA 9Hin.l٢O85kO8:R%Ŗitc(;؃3NO;:c9Ua`KtVs݋r#z܇z=DP Ÿs_q穤5{s_@ZЕaw"7H*  -|“E`"H!l5Y+K~_bq(- Hx=Z()c)ZB@:2#.ӹlC ơm$` .Qn&Pc5Z{]ȏ`^4!z044 0ߒ?%H@7e`!)"[>Ix!&OD6߮ªJ*uAi{(jQ9Nub om <ӛGӻ6sF܅r|, `o5mo81,|FƆӌ7aҏՀhxo@kᢉBkH`(E\-ŨaB`gj|7tsBQ7.c5jSb-nuFՁmGdџy+_EpeqC\<*XNyi_`llh4鱷۵BH:>^BFbF֓!`O.? fB5B,[ĭ0 (yHl I  n|UwUk ,,#Ibڛrƞh " gfF5X#blbfLFu YJJ5V<[j$ qkjc cCrN^ѼQmV+~UHoEҏwRB(5ۈ9\x4㭘id&nxiHEy2Fy2KzNJJCP߷UxA=Z~eo]hA@7sN"y+׌˜j]q|E܌a=h4Btapp([,F!jZcte-)R7Q1s:aB3D9;#w%}E D dbӰ ykE~۰FA fz_*?P+Y T Hd{  3TR:$4nshU N3$dB08<>i(T9h E1ʣ/\Q@l8?~+*>UF]06 ~cJYAH$In9CѢJqErHU].E!I`e?+&êԬ* ߋ@0G EoSI7oWU[ն_|/bR6?4I?[5ˆ4ɉ)pfrUxdd% 6׮&š ]Wd5&$H͢Ӧm dz0Sc#5묭ɴ0a׸+Yq|K}1pKOBfϐ5LJ (G4K]@t+ \XKR$ @#/ԭK]K΂:É+'?-z3"t#2:3/ކ+w]ib 0 ݈]=m3Cksq{?$3LPrVa@H !$wzǽFܰ'Z"|>/Rt-[f! QpGߞ_[Bmwm>k_V),oi8A\ 02:\.VY&Qsvaip} ZLmy:9Ө&BBR0úq|쮀ײ`a9$J|j)e86*2L u/պ~[.vc/> Y >:3)'0=pe03\).W&R.^}ߑ yiFCK@B3s2>b_,Ā$xBT)V"zp 0ӿwl%_ք(~ ~ Lb |6 %Os ixH(EM}q&"bFS7bۨú5,պBpȥ4p5*COpW0Wk_Ff!. l4ɿLX3 <1shi<;ҬvN< XۢL xl|!)!nfQ2?y?fNźw>}'kJx(GD52]>IAHlGї} 15( .!=?xtް F&axdag5`XxssBuBJP& AǭqjB&vL|8Y2"jƊs̞NҜ~$lO!HTrt]&׃4"E^ !2Ks_/ڶjU?*D" ؁x1 Aڷɿ|k$ !@so04C GO S1 R]4tF7 pM΅ Z0 0HV/Xw5ZFгhT rcccpqo9]OIC㵞.@m!"xzdZ^qpLʙpu\core>[įsr\8?91lCXK֑S-@ Z'"\ˡW(@:?҈@kwsSw6&[t@澋G QEHjHf{V$E ɿ`d"Κ#gB&iANDrbd|q( FYcdHN:ڢYcY#24YQ,twB=4akGbC}0x 4 i24\sZo/0<\/݃y  KSl]7ϝ~N;S& [pZc087 Tpzq69` ?' [q6 ȥJr9W{:"cBb>;"i2VkR$,P,߶JP;%0dڜ4ߴ&wBl؞=>8 PjyԒsG/aJ$H yź(ou_`fՋ *)=>ԫ$#Ze\ gA*|Lle ?+x\rnh_H1e*#x5l䌗Ke6 8"jm`0`$ɿ  e`*%r;NۍnXѿExg*I(w-:Bj?A^g'ⳮO Jط.yԁ3ya8E,OWV0y~ Y#2ḖyZnk =ۋ"}I6VF/`2r(OX :\^'D`ͩO$Y\A+xG a|pW"(g_KWElLc?ƒP 9t5`1$'md6bu188"5y>tIsrU 9B˃m15W<e\q(>z4Ϟf IpD@{zY- 5?e3 l ##ZeB'νtrd5Ճ^l|ah(W6k(SizŔTdCȋSʳIicm>Y{1x"wReZ%'R/UhkRH()/'`<_׃5-k}ty+E5ȳuZ-fN''2.+OP^3Fo[3>"33#6U(y%:H]=׍xɇr###( ۣ lPuW}Z^t=d џȶI{y,qk*MǭS^e>2@peV>dm+* 08H_Fί﨟^ 6 ШiJFFF.p c(W'C^:苍ϝNPF󥸒B5<8zxh.YMCCyh"1qel q$z,\"ρCXX۞[ӌDBR䑔@d^rXWU**]d+ k,!ȁVd)U~{ p3` *MB%.`ִfF)׎'L^8ixJb$/͵ <;/|RHXDYՙV~翰>~Nd/\ThsW%&`%҅?dէa86L/p<`dd|vw_r QPrat(yLrˍ/UAXVtc `(=kIN*v)k\=br7GV!RozB95cӕ#ԋpD[LI6$E0 kjv`<|-H #3FLAןٱW^ |s`Dٖz@dlyZOl H82#,:U~R0_,A a_. /Cd cl\stVg-(#'v x 8{Kr1)'/85RR5B3?υp)n+t3b S ȿb{##J2_:Xt{01s(~WZ`(dJ+/~"n6($d:tՓ$A^ڃO೵I73k5Xi'xg꿕62r}5e8s3kHg\f酓|SOO0nߠJJxh>ĆHnB ^@ȠLҏTn̕'?ɗ^|T5+k5:]8rr+aHiVGkNœG?gZ;_. N@A`ܗOFe" /pa[ fY酳?1>6m^?ȏ=211Y6- r6hgf$Тg8L~`@*B(3Zŧl5grKmK6$m{_zLCpΕ`NU VN.Wg܏KJZ1U/ff͞wL&/QeU`f2ְ1S֐E0P[}׽3|c8t 'ei6+|vwс=2YRB[[_J{٠(ML #{Z^g-ߵ_}K:cJBQS@X >y(2 3O(ߡ,bU' q1yM}T\k,ƿiWu b(k޷ʃSt>韶l8.nw`yo!<+[5w=h,9p|`td\'3 g 8sY?O~rM$Pp-^k~g`&OǶ,$b]A\|֦ozP4 1  M J̜$şO#딊<đF{=yH%GL\QǞy}ϮwUpE nW5_'EHcm; Bв#Ltts/{Jّ(!eYG|g̾_vAI&)-]oS\-Or?[]$'4ZXre]mfOi.nF>Q+uY@bP1x% jx1 d |+dۥ#}đF؝y8jAG(āԂ{;s|وkj?)|ǖ>Wf7L 7B|j7*s?x?zzn^/%S?;}8>]C÷x);"ՒiK_}mwd)'T {g/xYos֦sI:}3?.?8ih.m[ueT5 cq΄C wy )\2=~Ȏvw}3X#HW! erU((v[K$MGfslL#TܽpORab1:_c?7YjCxbjK#&&˧6~s^p$8=:M{FH*j4){ ;q%A]Lu27,vd=>RAO~O-Y]"0Nk7n0_./A*y '#%QvFՊf-u@ɧ~e" r%{qte2@AU{\ju.'Զӕ! of0=׃QbhxR޼D́OCWHAM0|{IG+sX ܶgi>|KQ!]a/ĿI'(jXYs` Iȷ+kx3z\;UfY 6ќ+-lI nn ruc#f{ 8xyDF2y$  'sfw(ez0+aH_s!ۀ#rت?RzS:whsS*= uzX6ξ$l"xCJ7OIDBWoN^~>-;o}y/LZ1BGүէi c¯>uxU,3NbJlӴXFPU<8'XTY4CAةpA?uPYDqhg$v]B  zgn<1jˌ^ф ߟLe:ݥ6@n P )(_.̳Vq3"YS@@f26jit%< G;nwnĬz _QV") @`Eܖ X7sqȢks@=޺?)uᩝhT {q=QMIIҠ+ۆ*%aݽ%[:%|U9/"d03fFRne_/|w濨6T͕Q!=~^vwFՒX` xKKFm)AU[@k ៵woeΠ̉ E.)|? Gf!jOijP܅aq|gh""0?^ kR GRua(u$EX71rGR~ U.]yO~r'tI*M h/c߸r\ ! ksz>d0 ;Zd]@X3ܕEgd!;oȸ~C f ĶQ6ư,S6G@.C74HL\هKf}R 5%@NB -w:i]a8X_ʿ}E32ZS}.XҵI-:wMiS X:<+@GyW P]c?!k9Z޿9HW# C^JtmZ FPP,݂֡^ _{h6s2& 4W k9Mt Y3Stz9m$m 6u 'KG^R\N l]uj[b#Uvc>k_ )%U+j*i}0WR+k%P4?I1>4!Ik/~nD]b,) n%NW{^zΌ>Swylڝ@06Yz0f&_< edMiX;nXk![T 4Qd 4j/>+_|å7Sƒ%S@scF ʜnf3x8~ @od"B##͢hܢ0z2NXLAFu܁5hFǀ+^D9`~nozT`"eS}ϗ<[C?'`8Bxqdz~KFKZGc,H<9w{φl*JDQ xv(+q9<-UNEr.TKVHrb,%KA7 v`2٧vC $A` .z0 /? oz4BECCHZߚ?]V@U|x^, 2 U$4i_[NoS~ nvABMaGmJ?ܿS0zKRVޜP%} ;$I_8 7WghNןq$YÌn Tc~O>!fȖ{nxr!c'Na|lRQ|=W?us?6~w|ۂV91baFIƕߊ ?׊,.CUkHTt,6)gX@'_|kjB!e)ŞVyr>@1뙉8dGWn7W4Hh=I4Gaڈ?ƮSaֹ7MNf_70h$??}.8Ҳk\zb@Ƒ瑕0Jb4|u㆖mbL|IfprgzPSV}E@P̶^ϻ+Պ#m]5h{XM- !轏e=#6&^k?x|oS*[Ȇ{0=n/ctG&F&L>xnl6XRkc=6?Tw^Nm;Hy0N:7|aqkICCS٠$v>a9+RZPϙJq XDIkKG_I_<_Q;畤\m Ǔ˩kvLʨ XJeȿ!}7e 2EFJJ3ǣ3AY~$ɸuց AE7Yw9Nv?ȁh &s ` )!N}!dU+A!lJ ;?PD\ӣi~{_^v#k̘ĺbܜ9:EifĹTPkw`g \BOaK)1pR ܛFE$h )|JOO{=?tJn&l|{2gN 53yg1/Y1`WkpVP-!i4W8? J9| fPr̓E/h%j}⍓q1%;?L0n-k6a AZ?W}مömyC9 ߙr:M=xW,D-3ugpsOHDl0 ` E~& J J+fO%'l~0h#-cB=>EΝ?/^:5sH=MILm V@fvy%T }ooԾW S@߈W5w=֓3~"p}o.@G%( JSN:t Qk#݁ ΗlT"ؙM>WK>@vn a[.˻in<IDAT˵sPB|kwFC) =>i?W{ lKΑN84(q_6LƤsw|pM:l|۾I!5WMޱcB%);qhz_&иk |ӛS'suLĎ&vh$o2di+6aԎIx>a!tlB[8GQ za)7=rzO_[Ju"D?u^n>?isWMwG߱s$tN6\E>k_ƊH% $ae..}}?rZZ[DƐbSMo f/c~!SM̼^tjsz3PkM/|Yesna"~굯轇n5;y,I )Vm P0ߵݟ!s^h֣_\8D;MG~`뱸ZH Iqnd(OWUЪ#6]/X`Y.׎>Ng\ 0ntI Ρ^/<;ՊVv\+J֬y:9]?+JA?i +_6n:~NO?(i) !%0#; ,{+ gc 4?ؗ@JCylBPLZgs%yԫl+zfmԽɜui)KXQfq!Xi̤°&6g|a>њ9t)4f-KdRAĊ`"(lT Ї(R2kvjI{?-+J"41(8AtR|:fX@uīLO~ey d;MR,EX, Iqulos ~ v95}oE*}>ǧJKxA~[a=-ʈBRX>wq%;\n1E69S5ĺuSuO|'j1~ں`{NQ8G:%Dm /0tGkӅN^^osͯ?xzEUZDV`ak PJ" )Fzf?m7~*64mK`aatLCN?!f_8H_>< mF[+ftW3_i{o}ϗX [.Nߡӳ #=; %L:`5 C>ʽHi\ as/~{_HI Lh!?p X],.\,B)2b!)n,Wlzxϰ҆ & {z\8C&haqN#M= KS)\S6| aQFDrwˁUrrùYI͵ 0!(7cqXΝp̶n=莡0I"0nS;^C&R!#|HR<Dz9թ^\9N>mN}O}I,S (+D$`4c $z|T% ig,+)xر?yoXIKH. [ܱ[ NeȂwH(%Ea?g Oǧy8w~g|6՗bDL?"'gj+c^Q+ I7Kc4q Q҂^ϡZPҁcZ.čv]pD;ȧfp,<7 `(է(l{mzl9l% K| P\s{<Ɖ[q ĝ]/[ZiEkMBEՉ(&az_^}%p?Z˳)]/k)4$wꀃj !)%Q*f9u%?kw}%;SJҘ⤅LFynjpHH`Y.ˇ1 ¤YC~1CS jebP_NX)lHSC1rg'Y nKA~*5 LH)9Z4Wz M. Ҝ qì4\B9K^\=Kghym+Y WJڰ 35,We ϒR:e$^W$G)9Q"B6!?p;D.Q*a҉&ܣlO͝rDnBJ:^ YK*$AJ3# F8Y@ 1;{JssKLWI}~Nuh7hҹ!+Ā:v=^6iW9;-Wt3Zp25KԊB K: AFg //+dlOdynƥ.n5K/$gipŖq}Q̌Ed*6y=.F?Jf:$\tݟ}ާA}1ͨy?sDЉAhhh7Rq[CΜ:` )kC RBNFPW :u)n6N[ PD.oP%Mœ^lľw<\"Y2s,%x_ @;GFhFso,JA>(-j6 gjpBt[#u& w7J%:w[qYfo١+K $6yyA'([ Ȃ|doNDΑQ0RA@֨šAeJw}пk?|Y˚Zk 묃kn^!( vr秓'^j}kwO:5Mv)ed'2%nn|Ic4W¶1A+ϻc/Rnh\6d{;Uq#-Txf":z?Llpb{&jR" ɼJ5غ};14?'DJ2};qKZ!o:vs9$M6哯{XEs(Yo=oa7[[cIF̕e`">Cw5׌h W_{ WNA9$̦s9'ӇHJXyȈ^G6w Y>b=/aV} auR.UW1h =#y?9vS!kj uO-\i/I&Mk?~Xtb.UEʽyds./]cx:+H BE& *޶6<0'v;zUY',ZuCq{K ]һ9^^6̋g3SO_88w"ZKB.:>Y_K[ĿlݒWQ(+f#AA@KId 7köǶ; ~b`}JFڍey]VFz7h6K3cg_ϝgVfrEٲ,@_Bߦ[U`(,dE"\TZvkGv:UmD0";o\-L6z|2uXKsSdfl(ٮpp6do*~6]!:cŌ%"unD(+,Uw?Pn Qˈ;vn@jr\Fxbx.94/ϤBJmOμio:-_-n[ldCz3FYV*M*pmȾgľoľܯp$Jq" /.)ٔX DAP`{(X*2:f^[ˋӓNGG# ieM띫K:7vsxtqbF<fi" M(- UE,jj[_ U6kԯF 55’5(MҘ)i⮳HBE쒊&M[+:N/&ϧ璉 ][JKQvɗ2rk!#~[pEbF@B4f$! D^A$\QT-TzBMe՟+>'rDfud%iͤӬ_#0&u%"!`!iw X*b515sM7Lc9P3st}Q/%=^ӫkKZMcKA'- hd}+%~[pq!|0||>hVi̜FX~A ɉ_E(KnNecEIK'A6 lϛ_E]ȖhfiL+MS5Wj2|4a,VJ{MFmS&j5-"CHu:Sd9!mٟ" Ė$ut(f\0<. րN 'lA+ V K9V@WEDqq wNaf͌$nhN&!IdtmNX2C GH%Yt>FFD 7m+"ǖlUK16  `6LFww XB4\ˠ# ,$"  na>\12rwo&7`rU c3C2 )\%#ú=ggh>vM~2ȾY% F~wKfdC.[{ҿjy?8x& vIENDB`(    (PC1}d>.^N4{d be c1*{m'q`/]M'G:0c%D7% (PC0|cC)jbuNͤH[ΦϺ>z*x\S2mX$B6% 'M@4r^'<פ;1נ$t~&+'%*MB+ng(ΗPUVC2آ%hOV3jkɪed':6 l{cׯ& |QҧsVjx'} h;bͪiҰ%(F\ӭ7CʝQ$ǑlЯ|շwIÙ@#{ ku+x1Ȕ@О{l'k|G%1ϘÊsԴ‡}Ͳ.Θ7s_OAÖOէcϪW`:t+F;JS4ʗ@ʛ:М7Ô>yf/\LKJVͥF̟5ɖyۺQĜl׳mس2͘Mب>{h.VK7raKKP̣WЧN΢41Ɠ2ƓQҦJ͠0Ɠ5ƔP͢,T̢ڤ,ڞ7ѝCѠ@2e&F<-&D9#3+)UC+bM     8%C8!-(+=Fץ0ޢ"x?F8DF1vq)WD+cN   3j5slFƙ2ۡuA^Lʟn&ktCGѡ&I1ē3}={15n/iX A';@|~EĘ"-, :~e4͙DѺCB&ÎO'{A֣.iVE<}%˒oɫEś5D—A>ĘzL42n[wD "LƝDřA×Gti(ӗ:sDDțPǟ4̘nԳ-ĐPˡEŚI-ɔ׿(ŐYШ*ǒտ5ĔIƜ2͘Rg2ԝDK+ǒ}ڻRѦ@ʛTҦ/Ñcԭ2đMФ&^ţ>5mZI{>ӠVΥ+ŐUЦ>ΜVȡ&Uͤ*̕t=P8ybYG;Pԧ2ētٶ0œYѨ)Ɛ>ʛK̠Gե:(ɒTӨ,OD@tSͣ,̕<əM͢Qѥ7Ôpص4ȕXҨ+ƒgΫ=L!'%DMM٩7ƕܽAʜċ^ǥ=Ǚ(ҙ7)]5o\WKKXժ-ƒnֲjװRФgկE͞_ӬZҩdذNɟTͤ=ܧTͤ$8/#3-GDMnWܮ-Ðw̴t)Ïc1bPFC}B{C~SΤRը:ȗ2ʖ]Ţ?3͘?ėZUۭ%92 C}C}BzKU֫OФ0Ɠպ/WOĜ4hW5hV4iW5jXC~C}C}KQХRҦPϤ7ɗ~ۻTĜaӬ9̚WܮUݯ5m\ -PE8t_8u`8s_C~C}C}KRҦOˢSΥPФ*ĐE˞jXج~ڻ6Ɣ2ȕXۮQʠB}6q_2aQ7p\6n[6n[C~C}C}KRҧOʡPɠRϤ|WѧD̝)ďAʜfկ>ǘdԮWѧ5ƕ-ǒMӥVЦOȟdJB{8ye2`P7p\6n[6n[C~C}C}KRҧOˡPʠQ̢QΣ RϥUѦJΠ8ʗ,ő5ʗ[իL΢.ƒ1ǔ>˛QѦUΤRХ}NǞILC~8xd2`P7p\6n[6n[C~C}C}KRҧOˡPʠQ͢QΣQΤP̢ P͢SSΤSϤRϤQХQѦRΤSΤRͣP̢GLNƝPʠKLC~8xd2`P7p\6n[6n[?PNG  IHDR\rfIDATxw%IV ?'"]_63gvǬe]- >^~!! B@da .gM{W]nui"iW[y3##8qS7Z ,DR]"3s'[@dKpPԨr)ό@,@Dں݅QObШק%?4\h7-t8hDhNlwm F*92$~4a@@'dZ&-9"k@Y%*Eo#I%j"| vn$ʀmbOjsSHV7>*<0$!B׍²݌&ha*zb~2=}1nTsO/׶7_U/$Ll AMDh'@2Clu;oyp)(#af'T?,;ǗS>wg+ɭnMmpS3u< w2GIcDP4gfszANjYWgφ5kA^X[K$musohlo?!A$Y^0> ^!ioӯo,Ϣ C@b ilˋsSBWh2WEp9l+կ|+)8T--$6!$!SPZY?^}]9bӿz&+/M:わouSrX;cXe(%6Wke:OTti=?7/=B9blnf$AN$[}I?oSw=c_fn9޴/osK^-DtYc SNfv?Qf@ǖeA 91ud^ӛtgԞ!|UP@ Z-&똜 /`j fO-!IߋIՎځdvcOJÉteG5 J n'St \SmSgӟ}f۶ ʷR)xFJqI3,=Csı2Eo0*iP_* ` nXK|lj@5̦32p(݇ҽLMkdTS9:ې̐+lX)(oX|ν<_v]o2 /|BbX|T& 9c]ekn)MB^<$@9Ǖ7H Dur~z %=U]zE9?ۅ⇭eu~Կ3 '̢e@hݾ.Cͩ.j T!sGCj_xVsB gS2Q_̷8.E$pli&[F/¾Z;n*~B q>O^F- W`ֈuJpm`A%&1o.̈z0o)<2Wr#I GHf=TbđqwfMX7mu f^V[Y-Qgt}?OH$L 8f`Gnu߼ s^Wpww]9<<8)8( GfN! Z3fFA7_vg1]9x'>?#^/SP?O2:qTm?=w>:~3, H_ucړd1"66ÅǢF ~戴DQϛ} B,CN.=LrxR0, \7@Bb\wd>s8xk7 ǿ$ X?Ό0q}'6BLɃ7U ̋i98I^FB'+`Ħۉ#Ⱥ][}k,hۭ+\07y" HAdψ/+قZo9IG}w {or`˕)b"WHb{~$D?, ^ ~鿈_]Uӳ'Rs]e {<;ZUӟ-7ZKAVHOݖ:?Hlh'2#>nRsX뒨@g=%|Ƞ9S+Ǭe8@{G K }nz׃xf ml.pU>*\툭&"%7!I0N#);?(/-nuWl2y+%C!Ot隰 =>f$۸.`H еx.k% ImDMbAә {_ dk;a.OН: ':d%P:g*/w_Ew nM| 3966xHBܰp}:Gڊc}3{%tan% o+I??~wRaՊa-3z؏P1qHᨁ"p:kME(nhz fJC^_yB{:Q?>n ~A'6k +5Bx_?P=؊Mٙ)ۼx!< Dr.$畄zgԟ657C6u a! ?n :m ' %<ߞy0=un_۟ := D /y)7)Iln>dc̽_Mv搂 v?WTߖ+9!'m"Q% ˧\$;G#VH}?1:9WFs탈Ka! A Bs'ι{Kٷ)o>!(%d˹+ȫǦPvZ2(tjs^`[ |rr_۟5?~NLz,! v1 DF_DZ/ٕ=0rgAϮo|uSS]۝u?Ww##QJJ_X\';Vo¿/OODi1"5& ̤ʈpa?D扗:77Ё6̗E|7]]fD'An?YCۈ\V(B1B'^xkCl+[F/|/ c{A$k ?6dPa(M0o<٨F<Ƕ"Ui|@pPLbPfhCÄ7LNLcŎlX[|"6*?2Ϊ;sUadO~GI=&%¸ G }n[D1ʄ;.&-avH)P/+ѣCȌu#P" +/ғҳH+!ݓ5uqNz= SEX-u~2+6'Ħ΂eGV'G'c]'/4j!15l~ DVm\R[mL6ww uo љIZGd%IBbDI'H\sWg:6(@hC`Dbs` Xچ޿.ME dwNu=,kr ?,}g_#F>.w ߧ9]ѧt A ٝgR W: 4dzaa}lK_=#)onsQ5js bS3{z~UO@vnFT%U<ĦZHG%.m@5 Ǜ@%ѯ,k$̦ar٥wyYO!B" R?2op[ٙmjG1'.l-C*~̡S{eźY5|^{|zG{w(kx{ZDb{sFw~V}`{bEE(dOG?J^M Obq S_0W'i{ Sŧa@ ?9 2ڂq RGG8|/Fg,"~H?օʌ_wG, O%B3 wޛkZYt="w/ D>ﻐqcSഹ|O̰Ѿ?q|0~pj5¿=3ڢNK|1:rsIh u5P_闆j0wu=Pz)T {&=]- O0.X*2n&Z'M^p]B(k<|c?@h9g`n5y> (K'Ǘ݈^Vwt}Xz):M: jiF;.jY?ffךhMdr2p}w6jF=eDzvgFtdQ9@vdƕrkRxKfj|zM$2(/͡1]BWn7N/>cs_d}GnYމn::C(A˿YSGn@82P*v&f͍ t7:RzE(֔=e-(O7WTGm#θcZnM8*#1f]pTWqMZ`8tb[KRd (٧ǁ2(}{:M'&45^UGKk|{0J' -+|E[든+iAljvG7#:롍 836fj{& 6cx{ژTe I`pc$ Ep`=wbhhhKuGdW86U ύ0;.'˷w zxk\#xyCۓ/9G6BTcS;X늌Ӊƒ X7l J:<&`f]rM$g/[ETG&Hm>mH@-؝a8HNݒ(u=jæ#3v ?x*}ȹ݈"6$CK`*H_B05{cavFP"e7 7{6jjC?UbpmIlkvSVKԣ6G 7}ϳO !te 15` ((ߢcz0[T"K_  3׍0c GHF2Hi  :WC^1+ߝ-$Xf0[;.vӎȺ],>%}hD&pn0j LU_+yQrb0GЖ0|:ljm.`yJp}Ng/e&ϗ=~y2 `low}n3S7[0dn8Нۃ?H/n>itji\0P-DHm|9$cNJ0<2Re},fʴ5ZXTt wjwtɵ^A\i}?y+Ԍ($}ޣqs@bvV{Z}c#v?-&'1V;l~p"M0S=6V+︘g@jąCX73oȿk@kaq^@y_B1 qde@{AIbtM=U2#m#鍆iCNbd 8,Ϳh`qSWPLz-jva@O_'/G[[Iނ*@&Yr"vgj`fK^ kR7=5';N V\1.+{7I@ tew#2;~>ٳ~a,E~l[柗|'zIͅTMCD$nx;JXNe BݞH.[ù7,D{4~u`k`-,s˘Ⱥ](<I<_@gNaj&򑉩cvm@2Z_ '30}h4(044 ϻy !!N1:bto|`ÁN,trpRynghsM 3V8"@On/^d %8e˘(d%~HWT̐beuL]GY&.j N04H#\XL9/j1+U԰ ;.tۚ/)ȷIEr=3#Ui2V2W"7w '[0`@zs[>luT7k'.g_V(āGXӗG g`02c@d*-)155s/9W;A,۱j?˺+0|rcߤJ03"1 gKjm6Ш1x{lAzqhD!nm3~VF5tfo3`@2߼ٵ?@@!6Ys İځ N'P_dj7nsȿ; 㺰ºnydaac]]C~oe3عb:"PP(t()ubf"/b#mon%&-\Cozq@Mp=M(Ίֻd_Aa\JSra J@hwbvzR2: clAْKx٧Hq-^%Ji&8'Φ9Mޛ7? ;Ag&u1_; @?3wɆ+/؅GXKG&2 !ÝLI%]ֲܑ+,3|6|Q ''zǂ!X>Zn"1 v̘vحmf z'GbjP"M M$@-8c C$M`@4ɿ+NWܷd'YB1si"!v?mԈs6o,;S}3IXVO(0 1eksgf7KPhD[0Po>8yL.TmC"btS`XCOi+m62i>UG3~Ɔ99hʼNa͈~o Y`gvX:<{2߮Ċ \ INĭ?ls{П T`13o ,'A$ nz XNa9؅4򯣫 PJr ZFddO6YI^̲-Ev#N IŊ ܏? ;5Hǵ|, ǜulgv7D[ͬn“ۚD $L ATMGޛ 3"ˊ}=zW$W 't5 a [4{'jYVkř!D+S.]. xۺ2o:h5淖Ц?d~:- ZX(ށ66?J&`zj~2 5 fI)5O cfnZl!(0~FhlNhƚ_#f -uþ/V3 i& U\3dEصd ڃ,FeӍ[pjihSOdm"Z4P1={ Cc AvmmBQ,g?hEu|WzvQTخqttt^pao'>;?{s,Y9Vcق>Α 1Vܖ)Jaz@ض` vCCHe](CFª 5Bh7*¿A0 >D5ʔoigfx/K0[Isbm nO鵆!%$Qr%\I ?'vE*?FwIʍ4;AE_>X擁 8:f153v%i|&B B I]Xf]G }R @k b{jK Ĭ 0E)H(:O*@ ѤaU -Cvbu`/G翀HW6TU@ 4&?əcZk@Z~~Kr\~UntO d`Q"1C Q8qڰL.Y IR=u=>a\9X{13Cy7;0lQ ѕoʆDns0 Ҩ2bS#Ө;,Wֻհbsh"JoMo%D]N,6Ȁ5Lm=nH-\k@zťZ|NI7b!h>`:=,gCbiMdT̝EgS<jG0]߸qJW@2Yja0:::Oݺ3^E>@U='1Sq]_2\[A"zF|"ߦ"׮s e~?Rxfl!EwvADf . a()LLAT\`Psl0 il`#q+#^neXc#:XZl4w[pl3 K6LKP` /dDmq=#26vfxHWy8 )+i :lu ^d5$o-lEr/;6I[6 鈾Qv6Ai(GM#C6ٙ)6K#L 5p:Ͼlywd._Ӗ& n{hV+8< @$1l Zw-䗝;~{ , `X,iFlCڗxfoS%"hqVqENl2h `NK. m:2qz)4_O&+3=݋{%zI !Y8j_|Iw]8n6 avZb)Q<=x{$*zHDڃe,C9DAN ADAvfN*5#}Ud\v ``fXk=?%f0%_&q'Uazz*"f5=ɥנM%4}%Y|eJ;$p?:::`YS4Hzm9 U  @y;F31x3 EBI~ShkZ|tDbxY:^|"4cu(&gN`xRȫ |(ꇑK0? 2d}sWb L*MV&PCu:&$>Wp╚ )i}5@dn6apۏ`h`}sa9iLpv+ I l5Peoef*`{h4ہ޾/߄JX^@٠z-+:L&/y)!ӂoڒnSF*sQZlC_ "[' X}dUrY*S~Ng48%HT LV^1\'MeޫsWYfq]eR.>~R\BMy#{38mּx/͂kHsIQ^,RC[Ѩq0$Z ,3:qc W.]l_ovbpe &gOb`R hm \xSWa@U_wrCFvz= B (NifDIU5%h,RvE]f-q< b %Z UY4IGSWT r&q*|[ ه̽EV7b+l7.jI9 ۮ`4(֎M@{ps `BÔ;a*[::;Ҹ0GSA drvx*`0š54c&Z4+5 VA(/p\{!j+ˌ fkZH%BjÛj8"@oUCC!Pkv)7Yb3Sȵ‘"kL,.n^?U N+ټq9lXVl4ߦ}cYf ˰zY.nZfa01X= /bAޓ jV#AV1E t5%(y/4˓+m6`㴄X;ɣ(+t}_3JM{T\D9>^atfdNBkқnQha] XO.!U8a{՟+,bckt)e,ߓ@A>p۫ O5U(dqv~?D&t*9(]DwMV嶭hHN3ߋccc7y R[7z \CӒ|OSiA tev !t~/slvQ00zHteVLQ.i㕄 0,|񷽫67.W͐kު|\Y\"ߚTح܅e_V'Ȱ0U܇tsͯ6b~Va)sSӧnT2Dn1 徖r\0;nwj>/+N߇"s[K ,5&d}pDf jܿ6$9pr >複$X#Pu]fW?pQta,':W[$cb,R j J[/,X捠= mL+ӗ1W-激Ӌ$a/+/߸RL Qo=ݽܔ+r2^+p>J`a7SD= m`ϫv៕08]iٌIXxոW=ۇ"cctrJA 9Hin.l٢O85kO8:R%Ŗitc(;؃3NO;:c9Ua`KtVs݋r#z܇z=DP Ÿs_q穤5{s_@ZЕaw"7H*  -|“E`"H!l5Y+K~_bq(- Hx=Z()c)ZB@:2#.ӹlC ơm$` .Qn&Pc5Z{]ȏ`^4!z044 0ߒ?%H@7e`!)"[>Ix!&OD6߮ªJ*uAi{(jQ9Nub om <ӛGӻ6sF܅r|, `o5mo81,|FƆӌ7aҏՀhxo@kᢉBkH`(E\-ŨaB`gj|7tsBQ7.c5jSb-nuFՁmGdџy+_EpeqC\<*XNyi_`llh4鱷۵BH:>^BFbF֓!`O.? fB5B,[ĭ0 (yHl I  n|UwUk ,,#Ibڛrƞh " gfF5X#blbfLFu YJJ5V<[j$ qkjc cCrN^ѼQmV+~UHoEҏwRB(5ۈ9\x4㭘id&nxiHEy2Fy2KzNJJCP߷UxA=Z~eo]hA@7sN"y+׌˜j]q|E܌a=h4Btapp([,F!jZcte-)R7Q1s:aB3D9;#w%}E D dbӰ ykE~۰FA fz_*?P+Y T Hd{  3TR:$4nshU N3$dB08<>i(T9h E1ʣ/\Q@l8?~+*>UF]06 ~cJYAH$In9CѢJqErHU].E!I`e?+&êԬ* ߋ@0G EoSI7oWU[ն_|/bR6?4I?[5ˆ4ɉ)pfrUxdd% 6׮&š ]Wd5&$H͢Ӧm dz0Sc#5묭ɴ0a׸+Yq|K}1pKOBfϐ5LJ (G4K]@t+ \XKR$ @#/ԭK]K΂:É+'?-z3"t#2:3/ކ+w]ib 0 ݈]=m3Cksq{?$3LPrVa@H !$wzǽFܰ'Z"|>/Rt-[f! QpGߞ_[Bmwm>k_V),oi8A\ 02:\.VY&Qsvaip} ZLmy:9Ө&BBR0úq|쮀ײ`a9$J|j)e86*2L u/պ~[.vc/> Y >:3)'0=pe03\).W&R.^}ߑ yiFCK@B3s2>b_,Ā$xBT)V"zp 0ӿwl%_ք(~ ~ Lb |6 %Os ixH(EM}q&"bFS7bۨú5,պBpȥ4p5*COpW0Wk_Ff!. l4ɿLX3 <1shi<;ҬvN< XۢL xl|!)!nfQ2?y?fNźw>}'kJx(GD52]>IAHlGї} 15( .!=?xtް F&axdag5`XxssBuBJP& AǭqjB&vL|8Y2"jƊs̞NҜ~$lO!HTrt]&׃4"E^ !2Ks_/ڶjU?*D" ؁x1 Aڷɿ|k$ !@so04C GO S1 R]4tF7 pM΅ Z0 0HV/Xw5ZFгhT rcccpqo9]OIC㵞.@m!"xzdZ^qpLʙpu\core>[įsr\8?91lCXK֑S-@ Z'"\ˡW(@:?҈@kwsSw6&[t@澋G QEHjHf{V$E ɿ`d"Κ#gB&iANDrbd|q( FYcdHN:ڢYcY#24YQ,twB=4akGbC}0x 4 i24\sZo/0<\/݃y  KSl]7ϝ~N;S& [pZc087 Tpzq69` ?' [q6 ȥJr9W{:"cBb>;"i2VkR$,P,߶JP;%0dڜ4ߴ&wBl؞=>8 PjyԒsG/aJ$H yź(ou_`fՋ *)=>ԫ$#Ze\ gA*|Lle ?+x\rnh_H1e*#x5l䌗Ke6 8"jm`0`$ɿ  e`*%r;NۍnXѿExg*I(w-:Bj?A^g'ⳮO Jط.yԁ3ya8E,OWV0y~ Y#2ḖyZnk =ۋ"}I6VF/`2r(OX :\^'D`ͩO$Y\A+xG a|pW"(g_KWElLc?ƒP 9t5`1$'md6bu188"5y>tIsrU 9B˃m15W<e\q(>z4Ϟf IpD@{zY- 5?e3 l ##ZeB'νtrd5Ճ^l|ah(W6k(SizŔTdCȋSʳIicm>Y{1x"wReZ%'R/UhkRH()/'`<_׃5-k}ty+E5ȳuZ-fN''2.+OP^3Fo[3>"33#6U(y%:H]=׍xɇr###( ۣ lPuW}Z^t=d џȶI{y,qk*MǭS^e>2@peV>dm+* 08H_Fί﨟^ 6 ШiJFFF.p c(W'C^:苍ϝNPF󥸒B5<8zxh.YMCCyh"1qel q$z,\"ρCXX۞[ӌDBR䑔@d^rXWU**]d+ k,!ȁVd)U~{ p3` *MB%.`ִfF)׎'L^8ixJb$/͵ <;/|RHXDYՙV~翰>~Nd/\ThsW%&`%҅?dէa86L/p<`dd|vw_r QPrat(yLrˍ/UAXVtc `(=kIN*v)k\=br7GV!RozB95cӕ#ԋpD[LI6$E0 kjv`<|-H #3FLAןٱW^ |s`Dٖz@dlyZOl H82#,:U~R0_,A a_. /Cd cl\stVg-(#'v x 8{Kr1)'/85RR5B3?υp)n+t3b S ȿb{##J2_:Xt{01s(~WZ`(dJ+/~"n6($d:tՓ$A^ڃO೵I73k5Xi'xg꿕62r}5e8s3kHg\f酓|SOO0nߠJJxh>ĆHnB ^@ȠLҏTn̕'?ɗ^|T5+k5:]8rr+aHiVGkNœG?gZ;_. N@A`ܗOFe" /pa[ fY酳?1>6m^?ȏ=211Y6- r6hgf$Тg8L~`@*B(3Zŧl5grKmK6$m{_zLCpΕ`NU VN.Wg܏KJZ1U/ff͞wL&/QeU`f2ְ1S֐E0P[}׽3|c8t 'ei6+|vwс=2YRB[[_J{٠(ML #{Z^g-ߵ_}K:cJBQS@X >y(2 3O(ߡ,bU' q1yM}T\k,ƿiWu b(k޷ʃSt>韶l8.nw`yo!<+[5w=h,9p|`td\'3 g 8sY?O~rM$Pp-^k~g`&OǶ,$b]A\|֦ozP4 1  M J̜$şO#딊<đF{=yH%GL\QǞy}ϮwUpE nW5_'EHcm; Bв#Ltts/{Jّ(!eYG|g̾_vAI&)-]oS\-Or?[]$'4ZXre]mfOi.nF>Q+uY@bP1x% jx1 d |+dۥ#}đF؝y8jAG(āԂ{;s|وkj?)|ǖ>Wf7L 7B|j7*s?x?zzn^/%S?;}8>]C÷x);"ՒiK_}mwd)'T {g/xYos֦sI:}3?.?8ih.m[ueT5 cq΄C wy )\2=~Ȏvw}3X#HW! erU((v[K$MGfslL#TܽpORab1:_c?7YjCxbjK#&&˧6~s^p$8=:M{FH*j4){ ;q%A]Lu27,vd=>RAO~O-Y]"0Nk7n0_./A*y '#%QvFՊf-u@ɧ~e" r%{qte2@AU{\ju.'Զӕ! of0=׃QbhxR޼D́OCWHAM0|{IG+sX ܶgi>|KQ!]a/ĿI'(jXYs` Iȷ+kx3z\;UfY 6ќ+-lI nn ruc#f{ 8xyDF2y$  'sfw(ez0+aH_s!ۀ#rت?RzS:whsS*= uzX6ξ$l"xCJ7OIDBWoN^~>-;o}y/LZ1BGүէi c¯>uxU,3NbJlӴXFPU<8'XTY4CAةpA?uPYDqhg$v]B  zgn<1jˌ^ф ߟLe:ݥ6@n P )(_.̳Vq3"YS@@f26jit%< G;nwnĬz _QV") @`Eܖ X7sqȢks@=޺?)uᩝhT {q=QMIIҠ+ۆ*%aݽ%[:%|U9/"d03fFRne_/|w濨6T͕Q!=~^vwFՒX` xKKFm)AU[@k ៵woeΠ̉ E.)|? Gf!jOijP܅aq|gh""0?^ kR GRua(u$EX71rGR~ U.]yO~r'tI*M h/c߸r\ ! ksz>d0 ;Zd]@X3ܕEgd!;oȸ~C f ĶQ6ư,S6G@.C74HL\هKf}R 5%@NB -w:i]a8X_ʿ}E32ZS}.XҵI-:wMiS X:<+@GyW P]c?!k9Z޿9HW# C^JtmZ FPP,݂֡^ _{h6s2& 4W k9Mt Y3Stz9m$m 6u 'KG^R\N l]uj[b#Uvc>k_ )%U+j*i}0WR+k%P4?I1>4!Ik/~nD]b,) n%NW{^zΌ>Swylڝ@06Yz0f&_< edMiX;nXk![T 4Qd 4j/>+_|å7Sƒ%S@scF ʜnf3x8~ @od"B##͢hܢ0z2NXLAFu܁5hFǀ+^D9`~nozT`"eS}ϗ<[C?'`8Bxqdz~KFKZGc,H<9w{φl*JDQ xv(+q9<-UNEr.TKVHrb,%KA7 v`2٧vC $A` .z0 /? oz4BECCHZߚ?]V@U|x^, 2 U$4i_[NoS~ nvABMaGmJ?ܿS0zKRVޜP%} ;$I_8 7WghNןq$YÌn Tc~O>!fȖ{nxr!c'Na|lRQ|=W?us?6~w|ۂV91baFIƕߊ ?׊,.CUkHTt,6)gX@'_|kjB!e)ŞVyr>@1뙉8dGWn7W4Hh=I4Gaڈ?ƮSaֹ7MNf_70h$??}.8Ҳk\zb@Ƒ瑕0Jb4|u㆖mbL|IfprgzPSV}E@P̶^ϻ+Պ#m]5h{XM- !轏e=#6&^k?x|oS*[Ȇ{0=n/ctG&F&L>xnl6XRkc=6?Tw^Nm;Hy0N:7|aqkICCS٠$v>a9+RZPϙJq XDIkKG_I_<_Q;畤\m Ǔ˩kvLʨ XJeȿ!}7e 2EFJJ3ǣ3AY~$ɸuց AE7Yw9Nv?ȁh &s ` )!N}!dU+A!lJ ;?PD\ӣi~{_^v#k̘ĺbܜ9:EifĹTPkw`g \BOaK)1pR ܛFE$h )|JOO{=?tJn&l|{2gN 53yg1/Y1`WkpVP-!i4W8? J9| fPr̓E/h%j}⍓q1%;?L0n-k6a AZ?W}مömyC9 ߙr:M=xW,D-3ugpsOHDl0 ` E~& J J+fO%'l~0h#-cB=>EΝ?/^:5sH=MILm V@fvy%T }ooԾW S@߈W5w=֓3~"p}o.@G%( JSN:t Qk#݁ ΗlT"ؙM>WK>@vn a[.˻in<IDAT˵sPB|kwFC) =>i?W{ lKΑN84(q_6LƤsw|pM:l|۾I!5WMޱcB%);qhz_&иk |ӛS'suLĎ&vh$o2di+6aԎIx>a!tlB[8GQ za)7=rzO_[Ju"D?u^n>?isWMwG߱s$tN6\E>k_ƊH% $ae..}}?rZZ[DƐbSMo f/c~!SM̼^tjsz3PkM/|Yesna"~굯轇n5;y,I )Vm P0ߵݟ!s^h֣_\8D;MG~`뱸ZH Iqnd(OWUЪ#6]/X`Y.׎>Ng\ 0ntI Ρ^/<;ՊVv\+J֬y:9]?+JA?i +_6n:~NO?(i) !%0#; ,{+ gc 4?ؗ@JCylBPLZgs%yԫl+zfmԽɜui)KXQfq!Xi̤°&6g|a>њ9t)4f-KdRAĊ`"(lT Ї(R2kvjI{?-+J"41(8AtR|:fX@uīLO~ey d;MR,EX, Iqulos ~ v95}oE*}>ǧJKxA~[a=-ʈBRX>wq%;\n1E69S5ĺuSuO|'j1~ں`{NQ8G:%Dm /0tGkӅN^^osͯ?xzEUZDV`ak PJ" )Fzf?m7~*64mK`aatLCN?!f_8H_>< mF[+ftW3_i{o}ϗX [.Nߡӳ #=; %L:`5 C>ʽHi\ as/~{_HI Lh!?p X],.\,B)2b!)n,Wlzxϰ҆ & {z\8C&haqN#M= KS)\S6| aQFDrwˁUrrùYI͵ 0!(7cqXΝp̶n=莡0I"0nS;^C&R!#|HR<Dz9թ^\9N>mN}O}I,S (+D$`4c $z|T% ig,+)xر?yoXIKH. [ܱ[ NeȂwH(%Ea?g Oǧy8w~g|6՗bDL?"'gj+c^Q+ I7Kc4q Q҂^ϡZPҁcZ.čv]pD;ȧfp,<7 `(է(l{mzl9l% K| P\s{<Ɖ[q ĝ]/[ZiEkMBEՉ(&az_^}%p?Z˳)]/k)4$wꀃj !)%Q*f9u%?kw}%;SJҘ⤅LFynjpHH`Y.ˇ1 ¤YC~1CS jebP_NX)lHSC1rg'Y nKA~*5 LH)9Z4Wz M. Ҝ qì4\B9K^\=Kghym+Y WJڰ 35,We ϒR:e$^W$G)9Q"B6!?p;D.Q*a҉&ܣlO͝rDnBJ:^ YK*$AJ3# F8Y@ 1;{JssKLWI}~Nuh7hҹ!+Ā:v=^6iW9;-Wt3Zp25KԊB K: AFg //+dlOdynƥ.n5K/$gipŖq}Q̌Ed*6y=.F?Jf:$\tݟ}ާA}1ͨy?sDЉAhhh7Rq[CΜ:` )kC RBNFPW :u)n6N[ PD.oP%Mœ^lľw<\"Y2s,%x_ @;GFhFso,JA>(-j6 gjpBt[#u& w7J%:w[qYfo١+K $6yyA'([ Ȃ|doNDΑQ0RA@֨šAeJw}пk?|Y˚Zk 묃kn^!( vr秓'^j}kwO:5Mv)ed'2%nn|Ic4W¶1A+ϻc/Rnh\6d{;Uq#-Txf":z?Llpb{&jR" ɼJ5غ};14?'DJ2};qKZ!o:vs9$M6哯{XEs(Yo=oa7[[cIF̕e`">Cw5׌h W_{ WNA9$̦s9'ӇHJXyȈ^G6w Y>b=/aV} auR.UW1h =#y?9vS!kj uO-\i/I&Mk?~Xtb.UEʽyds./]cx:+H BE& *޶6<0'v;zUY',ZuCq{K ]һ9^^6̋g3SO_88w"ZKB.:>Y_K[ĿlݒWQ(+f#AA@KId 7köǶ; ~b`}JFڍey]VFz7h6K3cg_ϝgVfrEٲ,@_Bߦ[U`(,dE"\TZvkGv:UmD0";o\-L6z|2uXKsSdfl(ٮpp6do*~6]!:cŌ%"unD(+,Uw?Pn Qˈ;vn@jr\Fxbx.94/ϤBJmOμio:-_-n[ldCz3FYV*M*pmȾgľoľܯp$Jq" /.)ٔX DAP`{(X*2:f^[ˋӓNGG# ieM띫K:7vsxtqbF<fi" M(- UE,jj[_ U6kԯF 55’5(MҘ)i⮳HBE쒊&M[+:N/&ϧ璉 ][JKQvɗ2rk!#~[pEbF@B4f$! D^A$\QT-TzBMe՟+>'rDfud%iͤӬ_#0&u%"!`!iw X*b515sM7Lc9P3st}Q/%=^ӫkKZMcKA'- hd}+%~[pq!|0||>hVi̜FX~A ɉ_E(KnNecEIK'A6 lϛ_E]ȖhfiL+MS5Wj2|4a,VJ{MFmS&j5-"CHu:Sd9!mٟ" Ė$ut(f\0<. րN 'lA+ V K9V@WEDqq wNaf͌$nhN&!IdtmNX2C GH%Yt>FFD 7m+"ǖlUK16  `6LFww XB4\ˠ# ,$"  na>\12rwo&7`rU c3C2 )\%#ú=ggh>vM~2ȾY% F~wKfdC.[{ҿjy?8x& vIENDB`PNG  IHDR\rf~IDATxw`dYu';PJ9:NΉ!c ؀bzww֟?ql3b26 fyzfz:砖ԭ*UzJj[-UTj~FWOnzw=H|46c)6-ak!iR5Q0Ŝ=N(9 0D>\!)+ 1L1L"AY &N;ũQN<7ヿZOz8?3xs;okԷZ!" hm Dz"$CJ$18{y.>3VKr='3Ƭ$̄{VH՛cgr/?2Y%Mxp|?3ocf]*$IIDS tdAg|@8a`n;8&HVz70P#'ވс"nx]]Ȏz)iaе| `a@D0Q~)iw.gW?Z">O֮5nn'µ tgUQ"" W>2@PsKT6&6`y>7;cHo Cx B$#q|O?7'  O"q۠.Zj b!hù3O|WI&;p6=T!ylEe!â&A? ZmB!)|~?7>}?o?BfA3;LOA^ ,BAy):=>o/֝_?W9l@ w 3S]BDO?޾ z{#MZ{W"܈ _ ArH~)S~C[j ո-mL1h0Wq/FC5H+p񩯏<ߵ-~A;CW`␐t}4ax#<Z&2V  xS,% #O1#^- >{Pe_;Ú} -ayHRs`K$ Wv׎Ve4s$q%A Ri|W>z/b"ZoqS]Z"ʼ e"ɖQfJĭ7l%L3 2Gw8,h Fج{(!=cyE5eܴq7 t <̪㗈 @Xѡa3?4=}s>Wϖu`^_n4vh@pm"z/q^~>CdQfNt]1bV3Eza gCDHP,Z'gUهҾu9gBQI8"?-4{ $ 59:, zg}}Q'N~ޏz+uM`ͱ kI 40XVJ])SJDLJCjpa$X ,b} !lL@b]Uuxڛ.8"I =)wX&^Ϗ[~~X(%|;_B]+}f͊aNB=%v7FT[Fܒ¬Ȏffd&ɣ1#@$!”a$BmJJ{z0O^.oB2 Vfs!$žGweGZ&j=̪cg_|!aҏ` =TjRMkT{fjnQ4]UIPNXz;0,L3bОywv̼£"1R*V Z1PTRwo;h=~]#cO"QJB8 tŚZ*b6kUW4Ǯ$gkVB/W˜ ֗'fوl0VӊM 梗sGPE}6Kθg f_ 2h- dzS_~1D?88rdWԞrF߇4݈ϿVHk~װ֞f>"5ǮSݩ{=q!AƊ "RVu;:SꂗGgq6[ |JP ?5u7ߓN3 N'pP>Ͻ0-9XgVQNܥz^%#LCֆFA$DĪz_evYgJ䜚~&G U x-$Ga?;#f>z\=:H~]+^=%3m]ej 5g@$%Bv"ΛߠƲS{Cd4IQXj^o~/8t4߽==85|sWHǧ6ä?ҊW5kV%Y-~-ܞѲ m_ )#F{&5qON?f8 A[vQ+WTo|M;6ptpZٲq_y7޳3SB⣬n^ՌTKĝƷ%~iІI wɛ:~Foi|70ttID EBw6ߘO鏦F47 E.7Ɐ5&%N+iޝoO_wYp-||ws{3m4warI SFMdcD5bۍ=Z; RWZk tzd4Ύ6LMOz+ʻawU+`93W5{`jP㿨[c] cL-Fwn^UR XaXAh A=z7d?rrr2Sӵ LH]!kFjD54:-ƪlE49̂LMFWNd8UI$h5Y`Dk~kg &2/abrstI_~Q'+Jqxߕ˶Ly[mm|CXcf@QѺ{܃zuZLk{Ub}_`D;z 2d] fX|E`;^J, ̤ўY6F9w̟qJ\Q0#Ѥy;RJo{@0Fkz'ADmBGÊ[+ _:f9ٱPMDWb δe%nr `DBCfwn2LNfd) sE5ۑqg QX߅B^u}+֫@^_ݛ{lOK+_Lah@Z }0K=2͍ob `RX9hߤ^ڝ.Zk@+BQy{K}ν^fd-^z\GwĒ_+ߣ5(k-0 Kv͏L~\w& -аd y #Blagȿoܖ^st$2{;R&#6]ЙaɣS$lHZfi֊Ѳ.GF4),ܠ ,0eKZ.NX m[nN:)?9m;j'PsDvʋEb ⽽'oZv=~*xt$"R֏VlEm7~壟r7mnt桦' 'C?Zu~_;5vSU=SG7m$l6FGV"g<4rV[oy}wxpԴ}3L&f7Q _yYw {S-F<Լ. K V3Ϟ+`F4^grO'b.L6ohg}w+wuʼ m]deKu^1͝Q+ J5[mQ_9<ҽ)DMN7;q{z1L{V4+ԇUcC7Pn6BF~@Z I-MسʱkѶ]NbtUH[7{ Iwc) 鑃GYh;chEO[o8U~`(o=N :V=dBbhb8sziQA=|{Hg'ْlNj`⩕Y&wܞ'm_3tfuB_9ع_3DE!^z996wB xpߏ3GmӰ((H6Va%IWN w&T"XW` O?&GCNa_{n_OLK"=vR:=m 4??2`V(%We Pwز3U 8 8ҟބbN A{|{t2V@b"=AW9xh⦅Ό SW[ 򻫗; n/d_89WtypE OcVcQ<vL:\{wh{AHؾ0tHOW=W@ώ [$+F-c´ b&6w, ind^%=~?!4BkB ֶȋ|}h#'bV`f!%j_rs˞%Ev&oUC W. f]s=hhl2ݧΝȪͽ+B+BHDAT{up?S|%DC) s qpAԲ_L1)Qf"rSǖc_qINƒU3PuW7sm򵣻m8^/.{/w@!ڳy伾a|) .G_xhЂ_C[=;Rbyo{gPۛ~T٣ DU71CRfsW|̙֐Pխ/k-K|stG5ﭴˍ==aPkzig $hYнQ$dAk>Ioב@Ig)a_75 .J<7 mS'esgƪvg߉ӅpSW|ߢhk5{{ST}m_;Tb hf=wm DZ02qJNIksW篩M {F&#b4yвZEEXvDG=_qt]"*e V߿}n8Ŋ?`hH2~oK879(SDȲIYk[-mhuH(!7w݆cM6L7,P wJfgg^d52Vg$O}gt-jU#_?7cT ˿W׷x$p޴3?lK ¯u?U?7¡{;S|A.IYhaPعkQklFq' ǪVc0 olG_yv|WzT#?*<1%ovoՂhv7-`Ia^T@/ˑ7*DȊčz0覝 lﮮ_W^B CG6둙=~ޟZPPk 7z;C~oGK*&?F&}w8YO @]7dĪ춬%#@}u]{ 7ϖªJ6L1Z7Lqȝ.^40EԽ+Vm1:sٓU,*dbF=}hg&anQמ>;0vM5TS ﷽]5Ŷ-lǟ&  }u]_0ehݠ3!wzK`V5qˀbvsfeYx@)o34}#( AR+"x7z0wUJ8[Zng98'?Y(A \X;4e8#>9r@TaMOU3 bufi^|pbrXsE8nL5YQ]n\_x]!3^T9i Chhum{7Y_#"`Ka5(BFFc(c8>(V᭐bq/2N: ̼$q箮_S=w/[~Ň1iZ<|a3IEcNwrn|ъﭖ34,nnyD "r׸R$ȹ}0Ċ,|q }*щw5?_;}RĪ S]%᯸wD}du]O^'UaiԵZoȣ#l_܀':CQ#vյ-?7.D<");)Fː[緌(N&~ DGvHq,V)rKuRX>oU[~!Y_Dwzt$nWɛUEP̟r HIdEz6?}GyMM e"˯2K~NWbk;i.SP/CX"4X~-Bx+DRD)cd-}WH]33/$P8 N`dohimȘdVHtYVکJ!@$&ۢIs_=]r5._JqU0(35BOUXˀy;Fk=%K`f'{U lĩ18xX&hn7S쫪0wܙ|o׎XcaF'\.V&k-ޣ_[IJMn{55~v;45 pjXcIy8;QhooGgggClmzX9|^_5=mYZ65[Ě}ĭvwGDGjDgvhf^ZOe1݇;Z37 `ho ۮM fҺ `\ uLcKU!'/ XO_,[|]&1:j[s?+u,AUriidA \=N?_;$ Z[P#yՕUڭC|F|͏|M 7feomħy0}]4Gs_cb g4D61 ZWDŽ+JɁCЪVE.,Ʋk`3?B^$SZO 05-L3qw v)%/zs FZMIeHXeD!BI[[fHOzJ.3&W?@F ͛78{~/&_iJVFz׶#;G {yK&[܄'3=i*Δw$pۓ7i?MY5H(bptcQ`U|GƜ3_6?]ZZZ. "-FDʟ#f@j5uo1,, X24fu;A滖ёFN֎.Lq#`'|7 leR*aެ7 w~Tȥ',[WvXVƠ+q۾K Н 4hD\L811>Y)gfv觫Z* v=9ڵO#H+67^FgTLft[^uTk@K-o{;AZ KMo#ZhlEC9;S'j= <2;y M5B"ЬۋD"QiYHM}:Vk6Zoz{ɫXb?{MoWRWi;wxk&o0eݩ{j:f6' ӣ{Q̻9LNa2| X6,B ]mn~ukUbgD w|ڏri嬀-ol?͆)^R_ )" HފU0 28{f133/Q*n]\|K$tkmEKKKH[ewuyW#Noՙqa^%bu&qyGi7yMmW kHaTk+v%pUC/CkVAo˖-0͵[P +@1MݷUQ^fK~[›pN[xuܤ{hH2b"NIt6Vy`-`&rރLSLOUh/[0 ßhd26KVp୔/_E7#+ץ܀K@ǖn{Kcjh#ۼuWϢ9>Z F:c(UYZqAbk녟dyMH-܀z 6ߘ@4a{2r%cJU` X@p~^r 4g^.3/Kk3 (  ˶ѿys7m挀rѤ7s*¸vOn<3;"ޢUg }ĭ6#y+ o)LށY_`u0V؇ɉX 22 <|kBCeRP3)(ގE90MSlm}2$L9 2E㎻RwjָdfE j+G͊xkY$vomN ('Yc(IjT_^JBq=bo2,KfLM=꼢ZppmWiC SD]eV!Zd'uP` 4F)~NlZRoyϋ.FG]U+OEf&AɛRPqk6 *,*=_ AWf m~}ʣˠ9v-RYL0B FΎۏf!\/cY?P'N >DU*u#LDUٌu[oKܢ<1_|ޢBMN"Mkuw.6}E&\ !#H(85ptUc} __w=x;4k!އ_4:s.’hoi }t B b)@{-BȨ7IXOCF`0Y NEn&_:{9Ez)zlJ{hDCCC͟J˴{13Jbr5w: tp'_CҰ^Ԭ9Ï-샳 $C=h]SC7&#'chhxlvy]]?BKJ@-[E\R~e3`qm힣Cu{to} +Bf@ݙʩea ={Vp R@u#8y Җ?ϓ.0& ] yhll@G*V @}U4Gt!TiZ{C7c2//xb [i _BlPk80 h݀D-KʅTDo`J8ܡ_ߢniVkߏH$"w5ay'\Zєx-Kkq ۴THBcxZ.}9Vfֈ LQraBn8N {y`_џ.xr37K?H4?{ ^EbaѳDW6"7OXfm8Xo wQԪZPP.l'x+@pUCm .r~ HCs hՅ+^dlnt\{l$@koH4HIU: [&Tstu{)hfԅ7)vÙ`=L162200U8qAᏥ󮼄s3&Hi`-WVQKL6wbuXoכ!8qAؔx+*OD:U<&Yiat5A'NqwT]3Ù a__xBRX‹Y+| j J{hinF{{; ~x||WBo@" Xї3㡈<ќh!2Ռx0kn^˦/fF[&Ĭ V*UG,17"?0@  [`hl޲Ph] ?ĔZzDhL+J3&l846چMѭDتY#j6նtx،8#%*,OLmЬŰiӦu'@HBvTt5^BenB ڱ%ܣ zťAۃO,FبSuMB2.DW.4t2*A!uZXPEC_ _^K~9pCW$I4:}[!bX6a 3zaN; I`-6UZGBja^\M|vG6 `-`8އl&W+@(4/Qe=\Xp XƥfΖ/Be+:@$at5uash~> Hͭ l-jI6`"0yO5% (A@.O_RϑǡV|hѐlݬ14`EWpjQÔKv ڷDj63# h u!4kk\:\-N V\ Pໜvȷ?z.y3l^7ö"~32SLY M[4G4u'[TۙOT%B]B^鿗n]R>LOb ^Zpm3go X6k?;4e2.k5kApSݮ Nۢ&B7 QǬf%s=QjA{pr TP\) @sk}02 ">dݳe#5 ]Ci==H$s.z~fji!J:F"*3Ufu1b \qiP3WbY#f!mq/> m]0 f4Sp$)v1~\nåν܉E)-<7 Igs#0фI5!hX@LٛXEJ׮Xf@+yj d8{vݽ QfbsNhR/.[: ԺZ#IR<Ҩgk\5`EsCvmC.wu+pţ&pcz^IJjHE J #e$pvf7zz.NoL0x @ޘҦde\dy0,TfǴb$@8* ʒFLfu/ Vmh^ӏAUM/ DC' ;s;"2T#B tVTX@VhH${hYE-hA(33,ۭ~%Z;^]eY ߄r`;q0Q. C(!-H`xUX ^r7.FBo&Ⱬbf4:w^Q(#0JյXIXr7lX7?={[\89̰dB2&/ qBGCdRv7'*ly1%%Q8aY"م$kYL~[_oj#hxiڞ)͚AlbYכ5$&~,tC0(4Vr#qc$]+k/b,S%F .`(Ͽ;Gz& 5SZ[Zܼn/fF*Ba;B\e0 Y@FsDa I#F/ MAsZ=v;O|΃*nI^N:/I LOa"dTϿ@7 .6o 0Pi+5"va;+QShh !$A3*8V8oU ͑k ^`fNʅ]nY0<2\ v4"jQ+ AM@d2n(UZfi 'P{A%.ᘄr°(|%e#"Fx92љ3ϗyܯ0_aaF' *s@XT\R_:FpI+d3b6!^0I ׫igiæH09e$!b#\e2!#闵ΡH˴¢~;HĩC$1Us FY@Ѐ E%aXQ4̠Jw 3se]rift5mX (VHXh pn"^c&Q8u/B%A/ }ס #0+zs\wÎ&{)uxt\?c7ƃpҐBV_J$y AA!nA+e/ 7B+i~_/K`Ckh羙JE=_:I^'aǼ,?*SMBN_Ѿ) ʧi\YX\ rBF;  V˻Rj}#`GYj͢KF0#.&=렔ЬmVo : lټyźfi3лB<@ًTɹ3I$,D7lXWM[zH#iތ>2KT/9b/:>S6J?L? M족}~g &"1Ƭ\j@Df9c~r1D ޗf$ѻ0Z;{v\Rw4L10ne0ۍ7NT%w? vmh8mWlo,7' )TCW:a)E*Uw~)0l 8:{ZҔgUB$^yޜդ:O柯FczfфAj|s ~ wXpJN:t4V#ws2 4{B*s~#Ȃz1rk^`I]ya]ެcM9=y3g L,9W1{hKH-[/>267f +V?WX QgoAŤs\0% Q ".1 bf,=ϻi|jJhnnBkkۺ fڝS5z eANcosAg* s.b\im^Ͽ0[1@yne] }iςBfX.0stc*Ua,HPRКMY* -8" Gϔ6]B^R#:_i[E51سOhzzg\_1 415"57ʴqp%}b1Z/쏥 #,scFnŠ͈plW2P:pWKЀ[yb(0̊Ps̺vY3:wa(YrUU!&cm`M0D-V.{Z@$ҥأR(ʥR70to A#o0t}TD:{V 8X;s?*&#ßnb-Mhii^Dwh Y˅@s Ft"k:yp nAOr<4U^}tuw#TVU"@IL. 4|gi,`fEog7X`$ ù/ӆk]~C+@K׫!}R1DkJsU: &+'E5-p%4hA,_is,"xB΂[Ľt-' MO7@f4773vf%*$*y 66m>I-bi- Nn(*|) =*1R\GzQomCyQWD:b}"ߊ@Pٳ$`BGTEi70ʺA <0kH2 y0{n1" _Zc_6hְm6FR HgG9DvHtF.90< < ̿K7r() `#S.h߈ф?` /<.u“F*S?jAüv_A$xlznV2a Gn;RjQ bf(d1=cBBE5-r*u5Y!, H_Lsw,| `xc`4߼Bָf`hkf"A²,$Ap=|3) bhz֌G (fy6cncSP`hG̣Jy[;\&C]] W|W?La X!Yn^r"Xpf_+hB*,1t09vA%S#T GBmsKjWy'[N 6mB(eH b6hX#NdzJEi(mxԩa  S6*f I6ڢwQ/ܿ|_F۠F(BoohZ`f: H9\SN@a{DJ"} iϾWIa^~C@wo4W>Z7ረ38[H ~ikׅ?U5bHk,<0!lDƢ."@H)@ (N 'O"gLzH։/኉!*$\)|jA+e[ @vз$6>5 )`%Y bb;s>a@Xa?mo ;1},jd P__V߲ d>)$L;D2I En4G O {Bqc9r̕7U Zo)z|MMs?۶7Bbh$A (\ ~EW̻]8;ug0눗 I9U<JGZbo<r|\3 x50zJ ,Gv@& p2yj`a B@艓P`>+`LV]Ggs/ k=W8}Fn%8/~ɚ} ?ѳ$kH& ̦fj`d$IHB$n NN=r~T`ycAʯV\lMC%l$M?[F⍴oGC 瞁$k_R^YufR mb!$ au#dI؀E`,B8 !bw@$G%^y XҖ*i|T#4ںYi%h€4Ε[r?@~舳9y&J?C36P>4h]\p`)~>_.)%`x`}},kC/)uKBI$x]yUIOݙ;iXDr(%ypIXԙ^W$ʼ;Zk㡨,@[ 8_Ea5K C{VhVG(Lz ęjzf$a1yK}'^)A \/7 ʏ|~rD_&5-?j8=1puu] 0ڣwdt y i P8܄D"WQhVBhф"` n9"7Pc?Ӄ#cD(޴٧I `0 kU^[`6!_"!KR  Yo%o$3G0m/ Gr:X|y*/DqN6B@lEq r4 OCƆFlʀxg Sr6Nм@AKGv'I@Ͻ78>pIL*d$h3jAr>%J፵= M}}0Ms_&_y#D$fF΄a[YN3% >|b?||`479=<TArψU A&Ƌ0XҲޅTdy6hVbe@ L10 !h <>7^Tw=`蓻 /x|5@6f_*L0N<>Ff?AN (Z|(I0!32 AM͚,7wb79v$ ~iW"@mԄ_6HX* -vL )L<z0d>5٥ye_|+2If'3ǝNWT9tc\  < Wϔz^*?0&|466iCAB|~. X!D /$ա0C$%S'3 <}K5+A7h II ʃ ፶=#W00xDJikFe˲6<=1Ess~{$PJ21er X2 ɿ{` vC&PK!_:|)$Ao =TIiD\ܴb *OV'(8x{` +` p:c! o f==bW=hHi_$dspfذsٿԋNDN%R|n̤z@A&4 +dbp1ТT+翓FfXM6 !΃֙ܘ!HPQܩe4.cXZߑ#30c1+A1N%`0fb,3I4{hiiACcLHa`tjuA)AZ3b)ڿկnf2v^:O2J><F/= (q1߅s+',%w  Ahl t mak] q3GGHh/%{-*ho]8gt@ hG"@GGdž_& ibp젷 CZĚMו9|fB0S:t%@>2Log.fsհֽ3ֆpJc(L3p7U@BOO"Ȇ Zk+_⢛ *~,S$=>>p|ZLHNB^I>(A({΃ #]qOCPmMmVh; ۶i#lŇ >mU-$ꭲ? @|g3,2iWRX1Ŭe8;7;cN'̍T9y # V74lˀ BqlgIkeB;CeRO̘aBPsIX; k4>sJV81XI#(@Ӧhؗ Ah,Hi8d2VّR|gOƐ<Y5|ZXHNN:VAG;%}O0y.Rbb#J}C/4qf̾743`]W$:҃Q& .,8v$q}3G/ |5&Iqoyda_RuBH6b$LŚkD ץO$ eu盈O鼓6qCG *^A!|I,!|,ێc։Qxߦ.fӲܭAJ)MULdNRTt!-:3쒣 #8Q }I!пy0P(x_}sҎ'>b8cV@D|ɏBHhH5YH4Ъ[ #W=6Lb_v4 5xv~-r`P!4Z7DAe:JRW>56 J"H~缭]wTRCƾ/" vAV(Q__[n*kRgܯ>}ty2B$HytynIRk2B}_s;54l X!m1HNH[}iA2̥,wao3K#7AՑ&ѬO0yKs¯5m4Cߴx_Pkd`9k:!04z7mm&G?@haOX=5 {YڐF!,=`0Rr $fT($&Pʴ K!zvDL\Ta13M-,,{7 upi}δb5eK$l:p%q-]k8< LԖeڿh[ ,DG?dž_yŸе-d %bמVM5:K{ Nֽ̐-E_d7ZKTGGNDh%.zJ&>pTOdqVilY4]`yS. $XJl:pd(=$ H"aS? ?ghӃm۷&iG?<'hн=$h6ȋ]{涆!!. Hpi E_v每T1, !HrӨOII5&wEZ/g}s),N :[4@$@ g{/14\L+ }w ڒ f~35_Ł-P3qP41pȟ/_(b&ͭ3$S^ w4^mL#_8-ݟ i,-QĒf0?{ԷfY;"L΢w*=]TeO ;"nZWW+ (H5O6_f sVj^%Z 3!MC/;|꣆f ЊBSg3OJA9? oϢbJO.jŤ>|~f=HNޡUuMD^g&wQ D) ї>S|bBaI* 4agG-/m Xs$(]! uϖ%q,'[ǵ]+Z 9_}ؾ|?X]9BܵY|J[H&&3CW3',)@Ltnܧ=˝˜BhqvU VةEG>?oN^?[}aKTOeW>”kF$f{{-.˼Z3];482* 485x8Wh( YZY!~ ʑx' mtoAHqٔ\-] DZ?'83~5 yx/xb%Y.:Fy ? MRC޿}Ba DZj?KzjMr}"furwodMl#Z7` 0.Xjb !$֌PDgG}ps›=TA&c88UƟG33PGMضmO M)LĒmtm% (3 O{WoѱpJɿ~2,8ܝ[b[O!$9Ro>Fa mXͧuci $؅3ggYKQ~;$ѻ#pXK7lmCz+.Aּu:9*mߎD".LÒ[dZ{[#`Iyn5<~Pr! zS{fXϟV`t@,j6F24 !oxͦ-T!aF|qw"0-[gGW+vѾ!go I l޼] $ga7*&M$ Ͽ4--w~|O)g +dbENV2S#أ~aa]ʯVCK_fQm[CZ2bJvPV~mn0M}}}5ՂfSZ /3BwTKQkb0,RS#}/G#Fs%%X\=5B1x-oM|X+Yŕ6-rg_3M1k)`0 i`bb?淼yvoEh!Ȁg?[x< x?g8 V{`Si)PvHOf6ԷYwjJ|\{i~ HB]/A kt(hq7eݚ烡a[Fot7ee,w𙯧?l g ?J]9{zA{\/$G~kGw-!,SکfKDPJW^A>gaoD(T~+ ~}hAD4i?/FwcBP$^+**ͭ}vNw.pS/ZRkJCJf6(:ៅ q_8wzT\)?|g~Ll"8Gղ.UY{JO> hi;9!;lԽ2ɷz uZ-0s MU b8~-b n 3,&xҟGUj7 _Vmy*=D ZAa(æc네+Cp#Dlm`mB "?Ӈ>k-Ynˮ0si'g&\jh` H.sB]1кɾjha(8bcZ2 [j/Al`MÐ&\{O*CXD=3i܂~{8ק;^(Pޫ;0$geڷg:۪sp"!8rlrETmaDzн} %e<ՋSK<~/MdٌAo+1껕PJcv?64YfjATjJu ^B O zֹåRrAM o !(ys|虯Ac~F0g,B@}<7wc8h2nf Hԅi||\rq򺚯RlW4=;3MCZsUBq$f!Av?>=y"6Dӏ ]0%̒䰂Tnp1`ܤuu6b1C1B{<-&^W˵:JlW'>_NPZOA+IEгcDxږ8vX4::*{ ;vpȎnXD֟ yoՓ{hhҜ3M3dAG9_5#0 CTh?x:o|lly?5$# f@}ۅAu?Gbsj%D2.g乩}{)j=5<w/?Gi#xk'v,\Oku[gr3{<-e S{p@[oz `Zg?r?Mc ?F\]` _TԊ]?̞f׷ׁ)" db&'&'3GD^1nR̾ȩL-(z3&o%ی^@z(k4m%w1F f'<1a;fD঍) y@8.Lqm2& >ձ;Ԟ/Y܈eH,K'(BY5_En.ݏOվDz3 $+Y-Ye 2|"L[СrY;-VXtW qdѡđgkf 襍I4وYH[H\O7z"[2 K~b獉iKJC%h%έCu>`ڔ~j[!!q.ok\5Na`Sׄp\lj d ˖DIydYqt9m5#O7m4Kod_CRC bwCϹpG#O-$i.zK$ Mr6w==mm0ƕ  -M|Ogv'Y/bt"@aTD-0 ң'g=?]2qSJ)'^ۦ"qsΚ6 |ȏ=}GɣvD$"cNdcO9bHD $|3DRf ̂0mDxHB9DbNk;0NY : Y"+{R:[z{᝖ C$@@!0A[oф T)io<˄*%)yQveةeY" DɯL6k7~FyHVs|ZḉB3E]r]8|г.oýѸMd֤wЅb?1vP? gl&L#d X`6u&UBf>v''"vx.w5w9L堿wWi"l/ :BF"[+L:sTPo>Mszkם_dBsp]BWt?){M -1Y#dᵝR& \1?>dž_CiOH1K).M[ QoF4a=加T-;ǿ4=hGM wE.9k=J1Ih+fuw&:~Wumj R.zoX^J!3>t^ @ $A$ΎЋ+fJBdɼpNۇR{@U3!02z43G @Ɵm+: Y]l2?kon Sd %"q3.k fB:iT-uoˍhN N D@ fK\T vJ (L~BMx`dO`f!PA XaxDF$af^3iOd?'' ;cA>8jPspEü@\Z5>pO&c䛴ϑ( p]y4i"29a.ri2( < ҉HnLv{۸a3':D"H!+*iYH+OXxO".l&ff|qFs<>b23D⤩/ avvz ID bIUc^rJ 㧽/ӓ:PEE?@_&X7,@ @Tzۯ4kGA[r.Yp)Х4 63 4TM7&1٭S7pȎːc0 "D[teZ aFTp53>@;)K2ضbb:JXэVNjS'vι֖NаDޓZ#rg Vy'- /'5k%=RH' `GMM (鮞BYF;_~ӓtPD FJ?(n X` HqnQ'CQi?ݴOq٪eaY2nA(f\GxG()`f۳dƔ^R ݐ@x_5<ḼVLMW%mI=>#'\ lp #:Wd4voo9DqaQVkckfNAdW~=5Y!2$F 0L 6` 8/FF|Қc^;׽6zckHB($5\]lBOstv<=4x)E_Dܛ.ta/  FP=FmzG䖆PL\#%50ذ .~8Vs9t~d(>]:rL:\l@8/D$Y#,}0i%rC}yk8&v&0f_ٚ D`^QzqY,f5!2 Diά)7 l@8= ]9`[}7Z7Gr! j ypI'L;̟< &C$J&@ }aW γ $ι11 eHhbG6nnok1 'Din!c: ;G<D.v wNU\E4@гcUDX1峩{1ϼ6~%AVf!d.kZPY`VfH lX#\f&R-F"V/#qMfiP°(jHQTHIa`A5bt$ڼEA%CE0 Zsw9{\]TŬ&3Đ?1A5_! Ҁ(Y~ppNoVPC#!\y?-0 b :) B$)E4),Ҏ3V'm+L4%࠺'YŜvVNA{isZk rg )J@Q,n96V 5E\YR0X v90fe{٢|.9su"E<곦 7~Cï1lHafX1'ws.j0X(Cڤ,ڞ7ѝCѠ@2e&F<-&D9#3+)UC+bM     8%C8!-(+=Fץ0ޢ"x?F8DF1vq)WD+cN   3j5slFƙ2ۡuA^Lʟn&ktCGѡ&I1ē3}={15n/iX A';@|~EĘ"-, :~e4͙DѺCB&ÎO'{A֣.iVE<}%˒oɫEś5D—A>ĘzL42n[wD "LƝDřA×Gti(ӗ:sDDțPǟ4̘nԳ-ĐPˡEŚI-ɔ׿(ŐYШ*ǒտ5ĔIƜ2͘Rg2ԝDK+ǒ}ڻRѦ@ʛTҦ/Ñcԭ2đMФ&^ţ>5mZI{>ӠVΥ+ŐUЦ>ΜVȡ&Uͤ*̕t=P8ybYG;Pԧ2ētٶ0œYѨ)Ɛ>ʛK̠Gե:(ɒTӨ,OD@tSͣ,̕<əM͢Qѥ7Ôpص4ȕXҨ+ƒgΫ=L!'%DMM٩7ƕܽAʜċ^ǥ=Ǚ(ҙ7)]5o\WKKXժ-ƒnֲjװRФgկE͞_ӬZҩdذNɟTͤ=ܧTͤ$8/#3-GDMnWܮ-Ðw̴t)Ïc1bPFC}B{C~SΤRը:ȗ2ʖ]Ţ?3͘?ėZUۭ%92 C}C}BzKU֫OФ0Ɠպ/WOĜ4hW5hV4iW5jXC~C}C}KQХRҦPϤ7ɗ~ۻTĜaӬ9̚WܮUݯ5m\ -PE8t_8u`8s_C~C}C}KRҦOˢSΥPФ*ĐE˞jXج~ڻ6Ɣ2ȕXۮQʠB}6q_2aQ7p\6n[6n[C~C}C}KRҧOʡPɠRϤ|WѧD̝)ďAʜfկ>ǘdԮWѧ5ƕ-ǒMӥVЦOȟdJB{8ye2`P7p\6n[6n[C~C}C}KRҧOˡPʠQ̢QΣ RϥUѦJΠ8ʗ,ő5ʗ[իL΢.ƒ1ǔ>˛QѦUΤRХ}NǞILC~8xd2`P7p\6n[6n[C~C}C}KRҧOˡPʠQ͢QΣQΤP̢ P͢SSΤSϤRϤQХQѦRΤSΤRͣP̢GLNƝPʠKLC~8xd2`P7p\6n[6n[?(@ @  (J>,^O"!#10'F= #% #    !&!$'5!%'9!%'9 "&3#  !"% " # $!&)!#& $!"'!&(!$'!$'!$'!$'!$'!$'!$'(J>,^O"!#10'F= "$ " &=6H,`P3l8}:<>>–>Ö><96x1|d*VGq#/-A "!"% " # $!&)!#& $!"'!&(!$'!$'!$'!$'!$'!$'!$'(J>,^O"!#21'F=(QAc5q=CئDCݨBפAП?ʚ?Ƙ?Ƙ?Ƙ?Ǚ@˜AҡC٥CީDAП:0{c$=4P   !"% " # $!&)!#& $!"'!&(!$'!$'!$'!$'!$'!$'!$'(J>,^O#" #& #$&F=32i=DDߪ@̝<<>@BĘBț=<<>CǚBř?=<>AҡECڧ:+_N{ "&) " # $!&)!#& $!"'!&(!$'!$'!$'!$'!$'!$'!$'(J>,^O%;705uAϟE@˜<<@Cɜ@ʛ2"pq@>D-kt+<ÖD˝Cʜ?<=BդF>,fR  #!!% $!&)!#& $!"'!&(!$'!$'!$'!$'!$'!$'!$'(K?,`Q/oYAҡD>•;>EȜ<ə!~ib.mGybUw/~Aǚ2\ĢfIs1h|YXi1F̟Cʝ=;AΞF<&H;_!%)!&)!#& $!"'!&(!$'!$'!$'!$'!$'!$'!$'(J>&B: ,%?=F?Ƙ;>Fʞ. khO}o?ė{[|!z\zRp?ƙEΠ=;BգF4m  "+.!$' $!"'!&(!$'!$'!$'!$'!$'!$'!$' ! 6uvBգCإ;=FǛ0Ñ i/p"{Eӣ!ÌӼDk pKhAțD˞<=F?Ŗ!+&E"%* !%!"'!&(!$'!$'!$'!$'!$'!$'!$' 3kF?ƙ;B>ɚt(myJlNxüGlkF$xJѤ?;BئD'IėG+aL"'*!%(!$'!$'!$'!$'!$'!$'      6uG<=;/e-h6Ó><>ÖG'O@p#),!$'!$'!$'!$'!$'!$' 6vE<=@';=Ė}A/n=z=z=z=z=z1{=ucиLH.+FŚ;Bԣ@Ξ#")+!%(!%(!%(!%( &# &# &#!)% #6.C٦@ʛ>>>@*ɔUy_<&w3ЛqfE0Cƙ&rOu dIТ:F1zb")+!$'!$'")*"**0r]fD===?/̗:'WHѢ;E0z` %",aQ(MD/r]KAԢ===?*ʕRx$}`-?@ʛ>!$' !9Cؤ=;#kƧ!@===>5ǖ,y^HΟ>>==>&nb9Õ>Dܨ7v %,`Q7u]Cҡ>Bѿ A???>>/˗9vˬYwDęAƙAƙ #$ *WJ8wEգ@76H™0B@@@?>;&eG̟?G)NBa*UI?C͞B$aŤ E—BA@A@?A,˔Ox"j>ɚ@G3}e+YMABƙCϹqͯ%HÙCCBAA@@8Ɩ+zE~*BGۨ<9vFE͞BC 6ÔAėFęEĘD˜D—CAA@A(ďle}FřFңA <}nFРC@,!LǞGśGŚFęDÙD×CCBB4͙:wίsH̟DțDƚ&<83<~HԤD9=Vͦ6ŔKȞIǝHƜGƚGĚFęEØD˜C–B@×){GțDřEɜ1o[C?GΠEÙ@–Gęxд{еuαrͰ+ĐMʠKʞJɞJȝIƜHǜ?ƘGĚEÙEØD—E0ϙNzvrҲ{ϴ}ϵjҰ<ŗD—EřKب/bSUBHϡFęHśFę+(!|غ,ŐP̢LˠLʟKʟLȞFȜCFŚIƛEĚEęEØ=ʚ."tĊ*&5LƝFęFęO(D<^AKӥGęHƛFŚ@ŘAȚ:Ɩ6ĔA̝G˞O͢M̡M̡LʟG͟IJΡCřHƛFŚEęGØ.˕k:5̘Bǚ@ǙDʜIǜGŚGŚP'B:]EJΡHƛGƛNҥ<*g$j!f)ƑSϥOΣO͢N̢Oˢ4˘ff԰0KǝIƛGśGÙ:ў<|г1nd.p1p1mGJ΢HƛNܬ3o\]CKӥIǝ?ĘHʞaխ;ʙRϥPϤPΤOͣRΤ'ŽͿ%NɟIǝIǜHƛFǜ.%MѤIȝKϣ:qR@O۬JǝDǛ9”2ȔQϤQϤQϤQϤPΤHң?;ǗEȜKɟJȞIȝJě6ԟQ M͢K̠Mӥ0bS?DdMҥKɞKʞ,޿-őUϦQϤQϤQϤTϥ1͘vūn׳0ÑNˡKʟKɞJȞDΠ3{*MˠMӥL̡&64*C>NФLʟNˡ&F͟G̟RϥQϤQϤQϤSѦ.(ŽP͢LˠLʠKʟLȞ4Ҝj\4ȕNɟRJ@vMˠNФO̢.Ðyٸ*ŐUЦQϤQϤQϤRϤCӡOD˝EʝN̡M̡MˠLɟ@֣?ͱCDРMɟUEA}MˡOӧO̢=ǙRͤeկ8ȗSϥQϤQϤQϤUϥ-ʔʵxڹ/ĒQΤO͢N̢M̡L̡4ɖ)PҦMɟY7yd ;nGSܭN̡N͢0Ē4ǕPΣQϤQϤQϤQϤPҦ4,đSϥOΣO΢N͢Pʡ<ڥR˵)ĐRΤNˡV4hXP *#:iELSܭO̡Sϥ(Ï,đUЦQϤQϤQϤSϥ<ў\ LΡD̞QϥPΣOΣO̢IӤ8N?ϞP͢TݮO͢!!?w@v PΤQըQΤBʜJ̠KΡD̝RϥQϤQϤQϤUЦ*Ǒξݾ/ƒTЦQϤPϤOΤQ̣:٣j+RѦNʠZD?r;~iKU߰P͢UЦ(Ï+ĐTЦQϤQϤQϤQϤLӥ;0ƓRϥQϤQϤQϤQͤGڨBȯlѯ2ɖTЦO̢Y6r_R&:5-RG@v=nF6UݮQϣSХ;əWЦkֱ5ǕTХQϤQϤQϤSϥ5ϚnĨSϥA˜RϥQϤQϤQϤPХ9Н.őPФQͣWOǞ "#"('DDAyNÛT٫PΣUЧ'Í9ȗOϣSϥRϥRϥRϥVҨ+-őVЧRϥRϥRϥTΥCߪT޻iְ2ǔVѦOɟ];k|#3,#3,IIGLDTثQΣSХB˜>ɚrص 9ȗ4Ǖ4Ǖ4Ǖ5ȕ#ȏ=/ƒ4Ǖ4Ǖ4Ǖ5Ǖ2͗&ÎSϦPͣUݯT٬(E: &?5)I=)I<NɡNɡOʡLÛRӧRԧPͣWѧ+Đyٸbӭ޿wڸ޿޿޿޿޿mسwڸ޿޿޿޿ܾmݵCʜ?ʛTЦOɠ\>pz !#)B;)A:)A:CCCA|F5TڬRФQϤSϤ$`ӫD˜%Ȑtض+ŐXѨOˠXTت!  =m=m=m<j=lQ̢T٫P̣TЦD̞>ʚxٸ&Íbӭ(͔5wLOڪUث!&ÎSХQϤRѥZ7t`B"/+#1,#1,#1,B}B}B}B|AzC~SثSթP͢VЦI͠=ə@ʛZѩEҢ&ƺa }WYܯPҦ?ɛB˜NΣSХOȟ[J!''(A;*G?*F>*F>*F>DDDDDB{J+T٬RѥQΣRϥL΢QϤOӦ6feZܯMϣM΢SЦOʠYQͣ)>9)<7+D=+D=+D=+D=+D=EEEEFEC}MĜcSթQϤQϤQϤRϤ/Ǔ`:˚SХQϤPʡTۭ\6n[!$%*>:*?:*?:*?:*?:*?:EEEEEEEIPʡS׫QϤQϤRϤG̟RЦIեM͡QϤP̢TתY-QG8 EEEEEEEJOɟRѥQϤQФQϤWѧ;ə/ƒ[Ѫ&ÎN΢TЦPˡT٫\A|MEEEEEEEJPˠOɟPͣRҦQХPΣWѧI͠&Í_ҪŽl3Ҝ|6Ǖ2ƔVѧRϥP͢TتRӧDI8wd #EEEEEEEJPˠP̢OɠNƞnQѥQϤQϤSϥVЦ2Ɣ2Ɣzڹ1V٭1ƒN͡'ĎH͠WѧQΣP̢SتZ;~h10XL>v #EEEEEEEJPˠP̢OʡLOɠCRԧQѦQϣQϤVЧN΢,ő6Ȗq׵-Vۮ.ĐJ̠(Ď?ʚVѧRХP̢RҦVML;~h4dU>u #EEEEEEEJPˠP̢OʡLOɠRϣPˡRѦQХQϤQϤVЧM΢1Ɠ/ŒNΣ~ۻ6RҦ-őXѨ7Ȗ*ĐC˝VЦSХPΣPͣSתSԨOȟsDH=p4eV>u #EEEEEEEJPˠP̢OʡLPʡQ͢NěP̢OQϣQХQϤQϤQϤTЦSХC˝1Ɣ-ő:ɘQϤaӬiڳQӦP͢LΡaӬfԮUϦ?ɛ.Œ.Œ=ʚPϤUЦRϤPΣQΤRӧS֩RӧB~,CHJ=o4eV>u #EEEEEEEJPˠP̢OʡLPʡQΣNƝOȟPˠQϤiQϤQХQФQϤQϤRϤSХSХOϣD̞:ɘ>ʚTХQϤVЧD̞8ȗB˜M΢SХTХSϥQϤQͣRХS֩SթRҦQͣHJ?vEHJ=o4eV>u #EEEEEEEJPˠP̢OʡLPʡQΣNƝOɠP̡PΣPͣQΤ^QΤQФQϤQФQХQϤQϤRϤSϥRϥPΣQΣPΣRϤSϥRϤQϤQϤQϤQХRӧRӧRҦNƞK@MOƞLAzEHJ=o4eV>u #EEEEEEEJPˠP̢OʡLPʡQΣNƝOɠP̡PΣPͣPͣPͣPˡ)P͢xQΤQϤQФQХQХQХQϤSըTתTתRԨRѦRѦRӧRѥQХQϥOʠPˠcNŝGHNÛPɠLAzEHJ=o4eV>u #EEEEEEEJPˠP̢OʡLPʡQΣNƝOɠP̡PΣPͣPͣPͣPʡQͣQ͢OȞQ͢CQ͢oP̢QΣQϤP̢PˢPˢP̣P̢OˡNƝQϤcOȟ2NŝLOĜOƝIINÛPɠLAzEHJ=o4eV>u #????PNG  IHDR\rf~IDATxw`dYu';PJ9:NΉ!c ؀bzww֟?ql3b26 fyzfz:砖ԭ*UzJj[-UTj~FWOnzw=H|46c)6-ak!iR5Q0Ŝ=N(9 0D>\!)+ 1L1L"AY &N;ũQN<7ヿZOz8?3xs;okԷZ!" hm Dz"$CJ$18{y.>3VKr='3Ƭ$̄{VH՛cgr/?2Y%Mxp|?3ocf]*$IIDS tdAg|@8a`n;8&HVz70P#'ވс"nx]]Ȏz)iaе| `a@D0Q~)iw.gW?Z">O֮5nn'µ tgUQ"" W>2@PsKT6&6`y>7;cHo Cx B$#q|O?7'  O"q۠.Zj b!hù3O|WI&;p6=T!ylEe!â&A? ZmB!)|~?7>}?o?BfA3;LOA^ ,BAy):=>o/֝_?W9l@ w 3S]BDO?޾ z{#MZ{W"܈ _ ArH~)S~C[j ո-mL1h0Wq/FC5H+p񩯏<ߵ-~A;CW`␐t}4ax#<Z&2V  xS,% #O1#^- >{Pe_;Ú} -ayHRs`K$ Wv׎Ve4s$q%A Ri|W>z/b"ZoqS]Z"ʼ e"ɖQfJĭ7l%L3 2Gw8,h Fج{(!=cyE5eܴq7 t <̪㗈 @Xѡa3?4=}s>Wϖu`^_n4vh@pm"z/q^~>CdQfNt]1bV3Eza gCDHP,Z'gUهҾu9gBQI8"?-4{ $ 59:, zg}}Q'N~ޏz+uM`ͱ kI 40XVJ])SJDLJCjpa$X ,b} !lL@b]Uuxڛ.8"I =)wX&^Ϗ[~~X(%|;_B]+}f͊aNB=%v7FT[Fܒ¬Ȏffd&ɣ1#@$!”a$BmJJ{z0O^.oB2 Vfs!$žGweGZ&j=̪cg_|!aҏ` =TjRMkT{fjnQ4]UIPNXz;0,L3bОywv̼£"1R*V Z1PTRwo;h=~]#cO"QJB8 tŚZ*b6kUW4Ǯ$gkVB/W˜ ֗'fوl0VӊM 梗sGPE}6Kθg f_ 2h- dzS_~1D?88rdWԞrF߇4݈ϿVHk~װ֞f>"5ǮSݩ{=q!AƊ "RVu;:SꂗGgq6[ |JP ?5u7ߓN3 N'pP>Ͻ0-9XgVQNܥz^%#LCֆFA$DĪz_evYgJ䜚~&G U x-$Ga?;#f>z\=:H~]+^=%3m]ej 5g@$%Bv"ΛߠƲS{Cd4IQXj^o~/8t4߽==85|sWHǧ6ä?ҊW5kV%Y-~-ܞѲ m_ )#F{&5qON?f8 A[vQ+WTo|M;6ptpZٲq_y7޳3SB⣬n^ՌTKĝƷ%~iІI wɛ:~Foi|70ttID EBw6ߘO鏦F47 E.7Ɐ5&%N+iޝoO_wYp-||ws{3m4warI SFMdcD5bۍ=Z; RWZk tzd4Ύ6LMOz+ʻawU+`93W5{`jP㿨[c] cL-Fwn^UR XaXAh A=z7d?rrr2Sӵ LH]!kFjD54:-ƪlE49̂LMFWNd8UI$h5Y`Dk~kg &2/abrstI_~Q'+Jqxߕ˶Ly[mm|CXcf@QѺ{܃zuZLk{Ub}_`D;z 2d] fX|E`;^J, ̤ўY6F9w̟qJ\Q0#Ѥy;RJo{@0Fkz'ADmBGÊ[+ _:f9ٱPMDWb δe%nr `DBCfwn2LNfd) sE5ۑqg QX߅B^u}+֫@^_ݛ{lOK+_Lah@Z }0K=2͍ob `RX9hߤ^ڝ.Zk@+BQy{K}ν^fd-^z\GwĒ_+ߣ5(k-0 Kv͏L~\w& -аd y #Blagȿoܖ^st$2{;R&#6]ЙaɣS$lHZfi֊Ѳ.GF4),ܠ ,0eKZ.NX m[nN:)?9m;j'PsDvʋEb ⽽'oZv=~*xt$"R֏VlEm7~壟r7mnt桦' 'C?Zu~_;5vSU=SG7m$l6FGV"g<4rV[oy}wxpԴ}3L&f7Q _yYw {S-F<Լ. K V3Ϟ+`F4^grO'b.L6ohg}w+wuʼ m]deKu^1͝Q+ J5[mQ_9<ҽ)DMN7;q{z1L{V4+ԇUcC7Pn6BF~@Z I-MسʱkѶ]NbtUH[7{ Iwc) 鑃GYh;chEO[o8U~`(o=N :V=dBbhb8sziQA=|{Hg'ْlNj`⩕Y&wܞ'm_3tfuB_9ع_3DE!^z996wB xpߏ3GmӰ((H6Va%IWN w&T"XW` O?&GCNa_{n_OLK"=vR:=m 4??2`V(%We Pwز3U 8 8ҟބbN A{|{t2V@b"=AW9xh⦅Ό SW[ 򻫗; n/d_89WtypE OcVcQ<vL:\{wh{AHؾ0tHOW=W@ώ [$+F-c´ b&6w, ind^%=~?!4BkB ֶȋ|}h#'bV`f!%j_rs˞%Ev&oUC W. f]s=hhl2ݧΝȪͽ+B+BHDAT{up?S|%DC) s qpAԲ_L1)Qf"rSǖc_qINƒU3PuW7sm򵣻m8^/.{/w@!ڳy伾a|) .G_xhЂ_C[=;Rbyo{gPۛ~T٣ DU71CRfsW|̙֐Pխ/k-K|stG5ﭴˍ==aPkzig $hYнQ$dAk>Ioב@Ig)a_75 .J<7 mS'esgƪvg߉ӅpSW|ߢhk5{{ST}m_;Tb hf=wm DZ02qJNIksW篩M {F&#b4yвZEEXvDG=_qt]"*e V߿}n8Ŋ?`hH2~oK879(SDȲIYk[-mhuH(!7w݆cM6L7,P wJfgg^d52Vg$O}gt-jU#_?7cT ˿W׷x$p޴3?lK ¯u?U?7¡{;S|A.IYhaPعkQklFq' ǪVc0 olG_yv|WzT#?*<1%ovoՂhv7-`Ia^T@/ˑ7*DȊčz0覝 lﮮ_W^B CG6둙=~ޟZPPk 7z;C~oGK*&?F&}w8YO @]7dĪ춬%#@}u]{ 7ϖªJ6L1Z7Lqȝ.^40EԽ+Vm1:sٓU,*dbF=}hg&anQמ>;0vM5TS ﷽]5Ŷ-lǟ&  }u]_0ehݠ3!wzK`V5qˀbvsfeYx@)o34}#( AR+"x7z0wUJ8[Zng98'?Y(A \X;4e8#>9r@TaMOU3 bufi^|pbrXsE8nL5YQ]n\_x]!3^T9i Chhum{7Y_#"`Ka5(BFFc(c8>(V᭐bq/2N: ̼$q箮_S=w/[~Ň1iZ<|a3IEcNwrn|ъﭖ34,nnyD "r׸R$ȹ}0Ċ,|q }*щw5?_;}RĪ S]%᯸wD}du]O^'UaiԵZoȣ#l_܀':CQ#vյ-?7.D<");)Fː[緌(N&~ DGvHq,V)rKuRX>oU[~!Y_Dwzt$nWɛUEP̟r HIdEz6?}GyMM e"˯2K~NWbk;i.SP/CX"4X~-Bx+DRD)cd-}WH]33/$P8 N`dohimȘdVHtYVکJ!@$&ۢIs_=]r5._JqU0(35BOUXˀy;Fk=%K`f'{U lĩ18xX&hn7S쫪0wܙ|o׎XcaF'\.V&k-ޣ_[IJMn{55~v;45 pjXcIy8;QhooGgggClmzX9|^_5=mYZ65[Ě}ĭvwGDGjDgvhf^ZOe1݇;Z37 `ho ۮM fҺ `\ uLcKU!'/ XO_,[|]&1:j[s?+u,AUriidA \=N?_;$ Z[P#yՕUڭC|F|͏|M 7feomħy0}]4Gs_cb g4D61 ZWDŽ+JɁCЪVE.,Ʋk`3?B^$SZO 05-L3qw v)%/zs FZMIeHXeD!BI[[fHOzJ.3&W?@F ͛78{~/&_iJVFz׶#;G {yK&[܄'3=i*Δw$pۓ7i?MY5H(bptcQ`U|GƜ3_6?]ZZZ. "-FDʟ#f@j5uo1,, X24fu;A滖ёFN֎.Lq#`'|7 leR*aެ7 w~Tȥ',[WvXVƠ+q۾K Н 4hD\L811>Y)gfv觫Z* v=9ڵO#H+67^FgTLft[^uTk@K-o{;AZ KMo#ZhlEC9;S'j= <2;y M5B"ЬۋD"QiYHM}:Vk6Zoz{ɫXb?{MoWRWi;wxk&o0eݩ{j:f6' ӣ{Q̻9LNa2| X6,B ]mn~ukUbgD w|ڏri嬀-ol?͆)^R_ )" HފU0 28{f133/Q*n]\|K$tkmEKKKH[ewuyW#Noՙqa^%bu&qyGi7yMmW kHaTk+v%pUC/CkVAo˖-0͵[P +@1MݷUQ^fK~[›pN[xuܤ{hH2b"NIt6Vy`-`&rރLSLOUh/[0 ßhd26KVp୔/_E7#+ץ܀K@ǖn{Kcjh#ۼuWϢ9>Z F:c(UYZqAbk녟dyMH-܀z 6ߘ@4a{2r%cJU` X@p~^r 4g^.3/Kk3 (  ˶ѿys7m挀rѤ7s*¸vOn<3;"ޢUg }ĭ6#y+ o)LށY_`u0V؇ɉX 22 <|kBCeRP3)(ގE90MSlm}2$L9 2E㎻RwjָdfE j+G͊xkY$vomN ('Yc(IjT_^JBq=bo2,KfLM=꼢ZppmWiC SD]eV!Zd'uP` 4F)~NlZRoyϋ.FG]U+OEf&AɛRPqk6 *,*=_ AWf m~}ʣˠ9v-RYL0B FΎۏf!\/cY?P'N >DU*u#LDUٌu[oKܢ<1_|ޢBMN"Mkuw.6}E&\ !#H(85ptUc} __w=x;4k!އ_4:s.’hoi }t B b)@{-BȨ7IXOCF`0Y NEn&_:{9Ez)zlJ{hDCCC͟J˴{13Jbr5w: tp'_CҰ^Ԭ9Ï-샳 $C=h]SC7&#'chhxlvy]]?BKJ@-[E\R~e3`qm힣Cu{to} +Bf@ݙʩea ={Vp R@u#8y Җ?ϓ.0& ] yhll@G*V @}U4Gt!TiZ{C7c2//xb [i _BlPk80 h݀D-KʅTDo`J8ܡ_ߢniVkߏH$"w5ay'\Zєx-Kkq ۴THBcxZ.}9Vfֈ LQraBn8N {y`_џ.xr37K?H4?{ ^EbaѳDW6"7OXfm8Xo wQԪZPP.l'x+@pUCm .r~ HCs hՅ+^dlnt\{l$@koH4HIU: [&Tstu{)hfԅ7)vÙ`=L162200U8qAᏥ󮼄s3&Hi`-WVQKL6wbuXoכ!8qAؔx+*OD:U<&Yiat5A'NqwT]3Ù a__xBRX‹Y+| j J{hinF{{; ~x||WBo@" Xї3㡈<ќh!2Ռx0kn^˦/fF[&Ĭ V*UG,17"?0@  [`hl޲Ph] ?ĔZzDhL+J3&l846چMѭDتY#j6նtx،8#%*,OLmЬŰiӦu'@HBvTt5^BenB ڱ%ܣ zťAۃO,FبSuMB2.DW.4t2*A!uZXPEC_ _^K~9pCW$I4:}[!bX6a 3zaN; I`-6UZGBja^\M|vG6 `-`8އl&W+@(4/Qe=\Xp XƥfΖ/Be+:@$at5uash~> Hͭ l-jI6`"0yO5% (A@.O_RϑǡV|hѐlݬ14`EWpjQÔKv ڷDj63# h u!4kk\:\-N V\ Pໜvȷ?z.y3l^7ö"~32SLY M[4G4u'[TۙOT%B]B^鿗n]R>LOb ^Zpm3go X6k?;4e2.k5kApSݮ Nۢ&B7 QǬf%s=QjA{pr TP\) @sk}02 ">dݳe#5 ]Ci==H$s.z~fji!J:F"*3Ufu1b \qiP3WbY#f!mq/> m]0 f4Sp$)v1~\nåν܉E)-<7 Igs#0фI5!hX@LٛXEJ׮Xf@+yj d8{vݽ QfbsNhR/.[: ԺZ#IR<Ҩgk\5`EsCvmC.wu+pţ&pcz^IJjHE J #e$pvf7zz.NoL0x @ޘҦde\dy0,TfǴb$@8* ʒFLfu/ Vmh^ӏAUM/ DC' ;s;"2T#B tVTX@VhH${hYE-hA(33,ۭ~%Z;^]eY ߄r`;q0Q. C(!-H`xUX ^r7.FBo&Ⱬbf4:w^Q(#0JյXIXr7lX7?={[\89̰dB2&/ qBGCdRv7'*ly1%%Q8aY"م$kYL~[_oj#hxiڞ)͚AlbYכ5$&~,tC0(4Vr#qc$]+k/b,S%F .`(Ͽ;Gz& 5SZ[Zܼn/fF*Ba;B\e0 Y@FsDa I#F/ MAsZ=v;O|΃*nI^N:/I LOa"dTϿ@7 .6o 0Pi+5"va;+QShh !$A3*8V8oU ͑k ^`fNʅ]nY0<2\ v4"jQ+ AM@d2n(UZfi 'P{A%.ᘄr°(|%e#"Fx92љ3ϗyܯ0_aaF' *s@XT\R_:FpI+d3b6!^0I ׫igiæH09e$!b#\e2!#闵ΡH˴¢~;HĩC$1Us FY@Ѐ E%aXQ4̠Jw 3se]rift5mX (VHXh pn"^c&Q8u/B%A/ }ס #0+zs\wÎ&{)uxt\?c7ƃpҐBV_J$y AA!nA+e/ 7B+i~_/K`Ckh羙JE=_:I^'aǼ,?*SMBN_Ѿ) ʧi\YX\ rBF;  V˻Rj}#`GYj͢KF0#.&=렔ЬmVo : lټyźfi3лB<@ًTɹ3I$,D7lXWM[zH#iތ>2KT/9b/:>S6J?L? M족}~g &"1Ƭ\j@Df9c~r1D ޗf$ѻ0Z;{v\Rw4L10ne0ۍ7NT%w? vmh8mWlo,7' )TCW:a)E*Uw~)0l 8:{ZҔgUB$^yޜդ:O柯FczfфAj|s ~ wXpJN:t4V#ws2 4{B*s~#Ȃz1rk^`I]ya]ެcM9=y3g L,9W1{hKH-[/>267f +V?WX QgoAŤs\0% Q ".1 bf,=ϻi|jJhnnBkkۺ fڝS5z eANcosAg* s.b\im^Ͽ0[1@yne] }iςBfX.0stc*Ua,HPRКMY* -8" Gϔ6]B^R#:_i[E51سOhzzg\_1 415"57ʴqp%}b1Z/쏥 #,scFnŠ͈plW2P:pWKЀ[yb(0̊Ps̺vY3:wa(YrUU!&cm`M0D-V.{Z@$ҥأR(ʥR70to A#o0t}TD:{V 8X;s?*&#ßnb-Mhii^Dwh Y˅@s Ft"k:yp nAOr<4U^}tuw#TVU"@IL. 4|gi,`fEog7X`$ ù/ӆk]~C+@K׫!}R1DkJsU: &+'E5-p%4hA,_is,"xB΂[Ľt-' MO7@f4773vf%*$*y 66m>I-bi- Nn(*|) =*1R\GzQomCyQWD:b}"ߊ@Pٳ$`BGTEi70ʺA <0kH2 y0{n1" _Zc_6hְm6FR HgG9DvHtF.90< < ̿K7r() `#S.h߈ф?` /<.u“F*S?jAüv_A$xlznV2a Gn;RjQ bf(d1=cBBE5-r*u5Y!, H_Lsw,| `xc`4߼Bָf`hkf"A²,$Ap=|3) bhz֌G (fy6cncSP`hG̣Jy[;\&C]] W|W?La X!Yn^r"Xpf_+hB*,1t09vA%S#T GBmsKjWy'[N 6mB(eH b6hX#NdzJEi(mxԩa  S6*f I6ڢwQ/ܿ|_F۠F(BoohZ`f: H9\SN@a{DJ"} iϾWIa^~C@wo4W>Z7ረ38[H ~ikׅ?U5bHk,<0!lDƢ."@H)@ (N 'O"gLzH։/኉!*$\)|jA+e[ @vз$6>5 )`%Y bb;s>a@Xa?mo ;1},jd P__V߲ d>)$L;D2I En4G O {Bqc9r̕7U Zo)z|MMs?۶7Bbh$A (\ ~EW̻]8;ug0눗 I9U<JGZbo<r|\3 x50zJ ,Gv@& p2yj`a B@艓P`>+`LV]Ggs/ k=W8}Fn%8/~ɚ} ?ѳ$kH& ̦fj`d$IHB$n NN=r~T`ycAʯV\lMC%l$M?[F⍴oGC 瞁$k_R^YufR mb!$ au#dI؀E`,B8 !bw@$G%^y XҖ*i|T#4ںYi%h€4Ε[r?@~舳9y&J?C36P>4h]\p`)~>_.)%`x`}},kC/)uKBI$x]yUIOݙ;iXDr(%ypIXԙ^W$ʼ;Zk㡨,@[ 8_Ea5K C{VhVG(Lz ęjzf$a1yK}'^)A \/7 ʏ|~rD_&5-?j8=1puu] 0ڣwdt y i P8܄D"WQhVBhф"` n9"7Pc?Ӄ#cD(޴٧I `0 kU^[`6!_"!KR  Yo%o$3G0m/ Gr:X|y*/DqN6B@lEq r4 OCƆFlʀxg Sr6Nм@AKGv'I@Ͻ78>pIL*d$h3jAr>%J፵= M}}0Ms_&_y#D$fF΄a[YN3% >|b?||`479=<TArψU A&Ƌ0XҲޅTdy6hVbe@ L10 !h <>7^Tw=`蓻 /x|5@6f_*L0N<>Ff?AN (Z|(I0!32 AM͚,7wb79v$ ~iW"@mԄ_6HX* -vL )L<z0d>5٥ye_|+2If'3ǝNWT9tc\  < Wϔz^*?0&|466iCAB|~. X!D /$ա0C$%S'3 <}K5+A7h II ʃ ፶=#W00xDJikFe˲6<=1Ess~{$PJ21er X2 ɿ{` vC&PK!_:|)$Ao =TIiD\ܴb *OV'(8x{` +` p:c! o f==bW=hHi_$dspfذsٿԋNDN%R|n̤z@A&4 +dbp1ТT+翓FfXM6 !΃֙ܘ!HPQܩe4.cXZߑ#30c1+A1N%`0fb,3I4{hiiACcLHa`tjuA)AZ3b)ڿկnf2v^:O2J><F/= (q1߅s+',%w  Ahl t mak] q3GGHh/%{-*ho]8gt@ hG"@GGdž_& ibp젷 CZĚMו9|fB0S:t%@>2Log.fsհֽ3ֆpJc(L3p7U@BOO"Ȇ Zk+_⢛ *~,S$=>>p|ZLHNB^I>(A({΃ #]qOCPmMmVh; ۶i#lŇ >mU-$ꭲ? @|g3,2iWRX1Ŭe8;7;cN'̍T9y # V74lˀ BqlgIkeB;CeRO̘aBPsIX; k4>sJV81XI#(@Ӧhؗ Ah,Hi8d2VّR|gOƐ<Y5|ZXHNN:VAG;%}O0y.Rbb#J}C/4qf̾743`]W$:҃Q& .,8v$q}3G/ |5&Iqoyda_RuBH6b$LŚkD ץO$ eu盈O鼓6qCG *^A!|I,!|,ێc։Qxߦ.fӲܭAJ)MULdNRTt!-:3쒣 #8Q }I!пy0P(x_}sҎ'>b8cV@D|ɏBHhH5YH4Ъ[ #W=6Lb_v4 5xv~-r`P!4Z7DAe:JRW>56 J"H~缭]wTRCƾ/" vAV(Q__[n*kRgܯ>}ty2B$HytynIRk2B}_s;54l X!m1HNH[}iA2̥,wao3K#7AՑ&ѬO0yKs¯5m4Cߴx_Pkd`9k:!04z7mm&G?@haOX=5 {YڐF!,=`0Rr $fT($&Pʴ K!zvDL\Ta13M-,,{7 upi}δb5eK$l:p%q-]k8< LԖeڿh[ ,DG?dž_yŸе-d %bמVM5:K{ Nֽ̐-E_d7ZKTGGNDh%.zJ&>pTOdqVilY4]`yS. $XJl:pd(=$ H"aS? ?ghӃm۷&iG?<'hн=$h6ȋ]{涆!!. Hpi E_v每T1, !HrӨOII5&wEZ/g}s),N :[4@$@ g{/14\L+ }w ڒ f~35_Ł-P3qP41pȟ/_(b&ͭ3$S^ w4^mL#_8-ݟ i,-QĒf0?{ԷfY;"L΢w*=]TeO ;"nZWW+ (H5O6_f sVj^%Z 3!MC/;|꣆f ЊBSg3OJA9? oϢbJO.jŤ>|~f=HNޡUuMD^g&wQ D) ї>S|bBaI* 4agG-/m Xs$(]! uϖ%q,'[ǵ]+Z 9_}ؾ|?X]9BܵY|J[H&&3CW3',)@Ltnܧ=˝˜BhqvU VةEG>?oN^?[}aKTOeW>”kF$f{{-.˼Z3];482* 485x8Wh( YZY!~ ʑx' mtoAHqٔ\-] DZ?'83~5 yx/xb%Y.:Fy ? MRC޿}Ba DZj?KzjMr}"furwodMl#Z7` 0.Xjb !$֌PDgG}ps›=TA&c88UƟG33PGMضmO M)LĒmtm% (3 O{WoѱpJɿ~2,8ܝ[b[O!$9Ro>Fa mXͧuci $؅3ggYKQ~;$ѻ#pXK7lmCz+.Aּu:9*mߎD".LÒ[dZ{[#`Iyn5<~Pr! zS{fXϟV`t@,j6F24 !oxͦ-T!aF|qw"0-[gGW+vѾ!go I l޼] $ga7*&M$ Ͽ4--w~|O)g +dbENV2S#أ~aa]ʯVCK_fQm[CZ2bJvPV~mn0M}}}5ՂfSZ /3BwTKQkb0,RS#}/G#Fs%%X\=5B1x-oM|X+Yŕ6-rg_3M1k)`0 i`bb?淼yvoEh!Ȁg?[x< x?g8 V{`Si)PvHOf6ԷYwjJ|\{i~ HB]/A kt(hq7eݚ烡a[Fot7ee,w𙯧?l g ?J]9{zA{\/$G~kGw-!,SکfKDPJW^A>gaoD(T~+ ~}hAD4i?/FwcBP$^+**ͭ}vNw.pS/ZRkJCJf6(:ៅ q_8wzT\)?|g~Ll"8Gղ.UY{JO> hi;9!;lԽ2ɷz uZ-0s MU b8~-b n 3,&xҟGUj7 _Vmy*=D ZAa(æc네+Cp#Dlm`mB "?Ӈ>k-Ynˮ0si'g&\jh` H.sB]1кɾjha(8bcZ2 [j/Al`MÐ&\{O*CXD=3i܂~{8ק;^(Pޫ;0$geڷg:۪sp"!8rlrETmaDzн} %e<ՋSK<~/MdٌAo+1껕PJcv?64YfjATjJu ^B O zֹåRrAM o !(ys|虯Ac~F0g,B@}<7wc8h2nf Hԅi||\rq򺚯RlW4=;3MCZsUBq$f!Av?>=y"6Dӏ ]0%̒䰂Tnp1`ܤuu6b1C1B{<-&^W˵:JlW'>_NPZOA+IEгcDxږ8vX4::*{ ;vpȎnXD֟ yoՓ{hhҜ3M3dAG9_5#0 CTh?x:o|lly?5$# f@}ۅAu?Gbsj%D2.g乩}{)j=5<w/?Gi#xk'v,\Oku[gr3{<-e S{p@[oz `Zg?r?Mc ?F\]` _TԊ]?̞f׷ׁ)" db&'&'3GD^1nR̾ȩL-(z3&o%ی^@z(k4m%w1F f'<1a;fD঍) y@8.Lqm2& >ձ;Ԟ/Y܈eH,K'(BY5_En.ݏOվDz3 $+Y-Ye 2|"L[СrY;-VXtW qdѡđgkf 襍I4وYH[H\O7z"[2 K~b獉iKJC%h%έCu>`ڔ~j[!!q.ok\5Na`Sׄp\lj d ˖DIydYqt9m5#O7m4Kod_CRC bwCϹpG#O-$i.zK$ Mr6w==mm0ƕ  -M|Ogv'Y/bt"@aTD-0 ң'g=?]2qSJ)'^ۦ"qsΚ6 |ȏ=}GɣvD$"cNdcO9bHD $|3DRf ̂0mDxHB9DbNk;0NY : Y"+{R:[z{᝖ C$@@!0A[oф T)io<˄*%)yQveةeY" DɯL6k7~FyHVs|ZḉB3E]r]8|г.oýѸMd֤wЅb?1vP? gl&L#d X`6u&UBf>v''"vx.w5w9L堿wWi"l/ :BF"[+L:sTPo>Mszkם_dBsp]BWt?){M -1Y#dᵝR& \1?>dž_CiOH1K).M[ QoF4a=加T-;ǿ4=hGM wE.9k=J1Ih+fuw&:~Wumj R.zoX^J!3>t^ @ $A$ΎЋ+fJBdɼpNۇR{@U3!02z43G @Ɵm+: Y]l2?kon Sd %"q3.k fB:iT-uoˍhN N D@ fK\T vJ (L~BMx`dO`f!PA XaxDF$af^3iOd?'' ;cA>8jPspEü@\Z5>pO&c䛴ϑ( p]y4i"29a.ri2( < ҉HnLv{۸a3':D"H!+*iYH+OXxO".l&ff|qFs<>b23D⤩/ avvz ID bIUc^rJ 㧽/ӓ:PEE?@_&X7,@ @Tzۯ4kGA[r.Yp)Х4 63 4TM7&1٭S7pȎːc0 "D[teZ aFTp53>@;)K2ضbb:JXэVNjS'vι֖NаDޓZ#rg Vy'- /'5k%=RH' `GMM (鮞BYF;_~ӓtPD FJ?(n X` HqnQ'CQi?ݴOq٪eaY2nA(f\GxG()`f۳dƔ^R ݐ@x_5<ḼVLMW%mI=>#'\ lp #:Wd4voo9DqaQVkckfNAdW~=5Y!2$F 0L 6` 8/FF|Қc^;׽6zckHB($5\]lBOstv<=4x)E_Dܛ.ta/  FP=FmzG䖆PL\#%50ذ .~8Vs9t~d(>]:rL:\l@8/D$Y#,}0i%rC}yk8&v&0f_ٚ D`^QzqY,f5!2 Diά)7 l@8= ]9`[}7Z7Gr! j ypI'L;̟< &C$J&@ }aW γ $ι11 eHhbG6nnok1 'Din!c: ;G<D.v wNU\E4@гcUDX1峩{1ϼ6~%AVf!d.kZPY`VfH lX#\f&R-F"V/#qMfiP°(jHQTHIa`A5bt$ڼEA%CE0 Zsw9{\]TŬ&3Đ?1A5_! Ҁ(Y~ppNoVPC#!\y?-0 b :) B$)E4),Ҏ3V'm+L4%࠺'YŜvVNA{isZk rg )J@Q,n96V 5E\YR0X v90fe{٢|.9su"E<곦 7~Cï1lHafX1'ws.j0X(CV>ɣ:n:l eEk?* &B/."40p{ c10qY)>:|y 5c?wCΝ!oTֱu;Wt)%gDt=bF8+N)_slu*t]?=&ox_m>AbA >"tg2c\9:d}gST/[#a" Dqw?I|Nxѱsٔsک?/ux/߆K>1 _@ MDn"< ^6nadqEmIAX:}m#Q'*ᯏ>"҉o#=  _`1r9R9 ۿlvǠNSp\K7Oݯ }g򓅜Չ_Sw|^<ӵn۶F։O>:a}wߩu%F|DAG.F.x*~73.;Z6~kW8uJ۶mPqo9A9f"yn[1:BF˙~bg;1pyM*ÏHh1PoY0#~sfb0'ouӶ, =4D'AݩmrP!~zz?5yqnږV%o pi_&׈{uF Oj@XdwEt4Ժy[ wgO~n#fgBǀYVΦܿ:wx~fG杉uj` 3o]w t,չI/^hzͪ)QoMtl~THm!p\߫q"Ra={Cٴ=7~rvͫ *@ I]HP`v33A cKT圝H)c.B$C̬^ Bܵ+7$p}QlA?3>@_ 2RR謋2dz "7;~=maM~/#=i d0z#-] rN99gZٳvr֌9ZMQY*EDZK}kj_󏼳t۴ij݀?/~{_%c UxRӢ*7.#BM ]HG9 ;cI ͠TUh Wٮ۳*cM:09Uik\ܤpC@5?cOѵo\Zm8U}1Wu𩠞PQ_j s"6bBhϫdo]5_3ף0! ߳7;v݂9s*Q3>6[}\pR*v'3Yʜ=-b jR3[|{~W?o~-H9C#Ѳ\*[[ߝ!6$ /( ]&)m ?@"h$:#򋿀 #gYhkRTMD Q骼rdpzvzWO0pc?Ý1c4gAHm[`V *7܎-F 3㝭!42ElFw\pT34s\D~@S0D`C o0FB,d"Sv@vT#" QW8unXI ցb69W6Umiݫe1[~? .nsxZk'[#dK>̏8/>/Am<\I]6w~w[#vQ]Q>[7ٗ{wqb7J߇M ]ȣփ?1kk.vV/Ȗ^+($Uޙ#fhUjL/v 轧ѩH ~3L~{0VOI[^=A!/ܿgVejI>=o8f`H~#Gl Μ;p74!k`ǥ~'!=-u_ ۆc0 #߇Ʀ IWmR=ۚ_J%&M蓝G4Z=ά`M%b{[Ưe3;gu[ Ͼ[4] ͸.A ns][ZK 3zM38ܔ(LڔFIp\Ӄokj537[<x+A#¿&2+}_:R4vRh[^KKҥ_6vCXة"oȏ_rΎ[ gK%f<Q~PwGX8sKp@ dja9 ]NΞu3ָ, "w=uT~zWo?{a˒ ϾpC-`{Q_C &m'uDB ^ws(֘XBP~WLD_u,{{;څ?fGP5:5wsSv7]p_>OOV?4p v6{;jK .{dk[p2N0D Wl6@38o^=6. m)m`KioC+5{rG}-U]vo]3{~S k00G7+uz}zKn56:f?K;+'qmZٙBci;k݀od MuGdoJUus3k#R pmxwώMfw|4`k[?`|* 8[:QowzLG.LG /=ؿ?'2?:%L-AsP.7`| h3+`ϻ}o7жDԱyBMݲgo=-62?= l]=>kbapّ@_Ͼ\R61+Nvo%n5I " ZnN9 l!׃h| |~￝RS6wv'jJ5%bnC3$/c #w U:ZHE$Ú]& /?}nĉxCHfOCM?`2۽v u,h!͞^bMˍHP  ]֗F7 5 ք>w1a퇈~A7롎}ZxK=: "ec^g&w]坙 !)k2kWG[ZpMH` ௾~: Y"6pVCo`H.u4Ґa{(yD0 IfOЎtku'M%~}o'Oؿ# nR4v AZlia)}D)[z 1WR~ʩ;~oC߿d4 \B;#ӯcdO7x5C5d=s̝-n͜FiÏX:?}$@Y99r: MuM%b}ߤuvR^n0c# a]h7ǰ`Ώo`"ct1IeގT':Jb}S >?#77Ds_jl6mn?` ೇ ?עt7F/FTNu~"E "R6my;3VߦD6~wuUO-Q3D K' 1:uSIc߱_n|"}|zmh1]+N %A86_ | [ n N_0:u룧t(#<@{ iG_ BR0˧߇V`|h6ZaJ]|۱NwV~ޚ}g88h°Xm\G} jg}~h8Ô4:Uf,: srtU(5[PЅl*V>Ï[IeaJBe-wG{]16uSu7f(F;btygZ ~7wSBPDj#'~4p,~U}_杙H@%G0:uSk#'5ΝE_S4O}>sjW{DړU@Dh}~ꕯO\}@ #z/C?FWeVhv 9t vڮ !+΢~1^: uT9w4X~tGG:ixij!MdKd5Q$l&n\%}YU}?w1F TWg(Dݿ) ڋfW4M ϧQgWpg37$"[YD} ү'ԫv='>qF3D ?jO&>?0unaΟU}hI!HWغC7CALp]߸juH@Sh t>L5?[T|o|R6)tKsa aoz};~3(vv?"8dȚwle}UIUt J ʉ䴕 >QKo!< o}TB_&pNK_ԅiE[~NƜm/ wWDnf@vǚk/@XJTw ';HnY!vFEK>Lx"mpao[Kwt-} xHϫ  aNHnЛRSg2Ӧ_X@_eܠᗿr~SFG:N%;͵#d9UH(uΊK_HTwã*"2%IYMns7'OIMduHЯ?.s5ۋnޞ]ZDFEwv캅{h.?d*"8zř1Hɋ6阛)j%B[AkW{rk/h1.N}PpIF bWE0ڬ%7tO֨ c&wfǚUC!l?Nu1`7`H2Y;Xvx]qgrW=W}bCC_؜*9_o~-(O~rwT~L-TA'h1ui)mOcZiX8=elZU2Z-5kC<,ΌYQK(lMe/G:Nux툆@q_G>%V`v'צ㭆 gGYk _rO.rsTMvz߲&moPh"En7]2a(@$j1#6Z(gQp H֠>[~ZG>܋C5ϨR1) %C1νsDMmN4-x9_fuۻ+Ė3rz##׶L$ )ϜAp~Ik kV$v=yd[<ެG XϿ-=h Us4;~2]у00jf.bltqK(v0< \0`j3#E֍ȃFW 63W%b"ƛ2sveh"֞ Ʈe[[oW vOMLx4f@xׇ΃UvH[cOMEOšrAnDϡB'Zji:5:yolTɱ'o=Dx:]e~2eGЄoOp0A2MA2u)dʻE`fHؓ-`%`7|q"{ctQ-` d?|_f _f0|ٴ!E|13ï[oi/-|!:5~C* Cɣ`v7j0d +2"wːV= rc62Ƽk"#%4LT ? S8C%'?h4=`-sp!YT+~{lBQ)*UA4*{cV`Q7vOco>PhkzJXfm]H(`5<$l t.=۲&`1?ZwMM@ޙ@GHe™NFе+o!Y-'w<\XCCwUuv6~ [.w+4w1Џ*9r %pTé77I?=l*A$RUE؟;`v*Eu}-vAQtN  >W̌`6=ҏ5K iY NA>_Le]tJnI?_Δ3}&k%Doiu?؟ϸ!Ow۷x#1xչm!C_B{A9rˁ4l̹1>6^H5]Uڗ}n:7Uti-&~++:/?p\kxm֡F:? =Bf+LZ 5mF H*ɭվ S-`[-`7$6-ޝϺkrޒ~wŹg5!:M>/l K?j 4FfO#J׺K0ܵ 5+|`?ܙ/CWWfo(8[eԹ-BXC[@D/QeVh rZmoﭩ3Ph.2kNfQkuc6z?bرp]&m}q>T9@ux'ݣhA[tW6Rʺo{0dv.9)b4Z^߱y?|>zj堥_4+ǮB^7bկ̀޾(^OHz8}h۪yv@&@ٳY?Lf."Z',\*JGhkoG"Y_Mjbg`e4ڤF{*lH*hR-̀Zk 3zVitD^WWMJ*v1<V>0)ï5{|Gmy~-V[g`(3Hg2ޮo҅1LXcc3;olPɦio}Ix=1f HWR'&$5z++4w!YeFu) tiё͹ cS,)Qa<񑫙%Lkٿmʥ 1q*4v>XʏUdy w@=ʧ$UAT{a2joHa+(sM pQ0;XQ_ydb|`olD{{ǓHlQ[Zs@D  ܤX,J1^+_͡=r+o>D̎9 9`nvnJ`qJ0QU-L2z{{kYޕRR_AJyJP{O0*Kox ұ#*=*`$p0|Z0VVT(^xlk;3֏XUXw6P(;۞<%:qibΝE/I^ XhD;x]~Bc0kY:YF&nʄv saDg'gVhNΦ B"yޢ pS8p^0{vD߁pB CDp}7-+4zaNA,arrjC-(>e{Wۿ XOVu[o-km}ӳNżFjh5J~sFIJfFtFTjbٌM :ֶt`8A ^٠TI z%)\\#X)$ B;i'MH@Xwlpmòp<=EsB D*6Hw.f*f--<3eU7ԫ+ ~+zWTL̈́L7-$}}U{[h!Me3*J f@7E[}V>,{F^Bb?*gUS`76Ens`B-. )\XUK L`6?P$e=6 @Y&ܙ0P== 7C޸wI>벉e٠/ҷK0+܉ @H#<GPOX.jM`($v Sݿ#eePՉH$Zu QC$lhw>asQy 0hDT92#b+w{#mN@(YR*H(^kFco S0 }}}wo1~"ǯ|SQmGCP}XkB4uxJddw|})ЄϜYӮ`xx螊dDSًHAk} ,-ͅ&D [ZǸ PlljVb loEg-S$Q@kR *q >l7 @@OI m;I[_VnBz`,3Ikuj:5 ,2E|oo}HbW ]TI|o]ff&˅{?!kOb4}]f-GW&[(fBato&Ng\VneUDlS.X7?~!Pq5E_=.d$:u/^6Jτ9х+ ni?*|^sP]݈D"w},[3E)I73" =F<ml_̌Fh凓1:Pc5>Eǹ'`˒ C9+B "Z/$M Ӡ7CPRe&&t7:tD{Lf׬ Ҵ0.`||]ݝ 1LdXx+ N*J5EssPc7L2bMT3 Zc-z`$@ f  5j%4}+05Z!\*NZS}뭲&uJ~نnԶfa>G;T.cC!@F4wWڮAY0]c#d9fIIKGf0A 12|z..0:Β[KwvߊeL3b(:;$).\GA+wb-Rh݌uX D! !en ]ٯŁ! :@]:|Ȍ"]HHY#^zݎ?v>w.p~N6]J*S>Q ֢ǔ yc/~`2  Lv(}"jvc*6Pd#ׇ50>= 4ձWJS-`E0M;@Dw_fDCM$`p>?/UFA3H[u ZZ80Q~)zxQ}ɟ|ӟ(Ia*{n]7q(v^ޚ~ণp10+4 qW9dhyal " /Xa? -ç]:UV Bk\}gy$ }" L./[Vqk-?Bx5t]+ P!Ͱ*R1!ѨT2HDu~ Vq=.no0+$<4cdt`Yk ``4 n`Z_~[+â}nފ?̈F(:Fx? ((+Q1Kh&AUBA:C`$}xJVοO@f D[Gx`4FSz?V5[&~0)tt# ޥ)4 ؞Up]rK3(I=r5"M(@ed$Ls3X{< XkC1t|20u,_8`V pbлc]B PA @DB $JW&$ 0wWvm`2-\[s/V~9l+gλ~}+C\tEVhmmE@AATS. >V&f@  IkȐ"ufޙ չa)Ak d 'tYqccz YeNx*῅*V 5B__4M Qq "a[j!Ws 2}A3CZ# D<OsR6[oOCp"w"#1 .;xon5F $1 ]@wOM&T!`:}kU.g6 Xm:UFO;B+1cg+TO #LV,Z Xy Ri$3x\yZߍ3Q= @{u˼P_ Z0sH%_hlZF^ֻ@ g \`A ض,;bd2Up)5fE]\0"F@f|`SaB)m[^zN`ά{(4 h e -ai,w+OQ0ah}M )Ld,-̎w@EE?#{S \@T>BX )p]B h_/EλpM[q>eK&瑶@L_E *Ymt ո\"S'i:ibByZm!=A=Ճ3CH~bm/Jwh0=qoFSsXH\e-72;s)gp$tMRmEBΑc覜U&H23 x䂇R0H"m≯ 1z3{1=(]%; VGpBdJ?@ zeX!oDkr_i{x}%.̸`fhCkaL`,³8=}|ȞA֞3Ms3MP >o{ 6߂b@U kgbJnVGr >[V^犣1/;W9 _\0>U`mT X@`~N|Y\{@5y' ք&>\O>^b~U_>sUU3 Ae`Vh@43 <'VzK\*cVo<"jݞ [3aH&6H&[2r2Y\{ywnk,츽f#ʹ3v$t]Î^!/ֽf$tw(V}=*r4#0\ :e0(Xu9obl\ f?P 3/c9֢Q:#fktw1_5-4@KAL,|c@@caZ tm3Ms[[9"(vcSXR(ԺmKڹeZ97Sơ&r-|8]^s;VZAH&bAtuuQ7>[ " V/5x]zY珞vКۃwmG_8ֿ]|h v1T*BGG"ȝ34Wj fǶM4Y*Mp)Fh'mnThh <+p[ʂK~=(tCbGǝDd6E@$@՘`ӮE-4gXV -L9p @ɊAU5VB܉ށYpu߆kuR2l\ܼ')t=[!;㞐F1U8@<법MVqրQl+v}W!Od0 FK-|[XVdpӾ+-Eرc ø`I|OU*[r$<?Ǩ _|!"(`TT6 傴9+;=X#&\OPc%A*ʿkk&io({%@JBnEŚ7bl'ޭB\  ! qs|^֊=ocA_Y{oڇyoešr!03:::Z/कrU2p &]4 l*FR N|y^h <Ѭ+T߭4כˮߙοQu1;eT)%$\q3x ;S#n7EHo_,kW>f> iV=n&7f&$¿􄞜.s0&z"{Ɋ pfٳ6+qʻ SD?b8fbKpm3 uP1O:mT&?4NC` t3O, iux2)N-9 4!"X[r\ZuXo/oG"uGoP$@ZP/G>lʝ4ysjq{F*b"i(ەBjw !q=͗-}_we[8gn._k 29Dz1_ƹBrҙ&(a(QНwg5X箎 @!h7܋)ʹxUJL0M=;zB*;E^^)g9)8X#03a0ATrS(8Ibu\B܅ފ5XrڽkO 7ESs;3庶4Msm575dB$3)͋=UVf)b]E X4ru[5~,Qst)SwJ)R$hZq0Xl z0-5( {"E9:MJAL \hpsq :@A o=~YX=1T.g huߺ@Čl7dk`ՀW:|Bzǂ3pU__Xo+t2{afjہθN"`T/{t jUM'ˏivWvXwOu h0;#֔0n[tw1 >ežjbF0@G׆H``;a Zy@̹@XM:\=&*7@9r2wƭgV 0W:|QFMǬD gn&0H}rຶp%% ׬crx;Tzv~7,0;b$s. T M[= ( MSw";0vRXQ/CG/˞[VO*5Sc7P^E daȡz4 N L+| eBpє/UėTn%am:6x+&%*Q:Dr v_\s'X*%G2GK^:RidZ+ ziG 4jABRo@\\F<ӡg{JvεA(&(mԥkՇh;N='|EJ/ȭ+˄3# ݳ-A$pc3:}Y$ 5B(o[<|\jŐ#W*Iam,{©m 圼vJ ;7hooG8\wǵթv5CyA@z9vxvRHc_ Ď{Ɂ̬j(V] @ʺ)%d X 躎,\9yU#F\ /X{3XEV!ҁcY5\fPzsSw%M'$uWγչyx5}:wѩka:3X9ѣ+f0LDwOY̘$"HIhh6QU86t"$q ~h;1f'.|ux'*#%ŮZmPe8j?gKGঢ+457#GuH`bs1`?vOTn X˱&Q.#Э#_KS/TDL==BCȝZ4o!zzz՗Z7rձ dvB -f?gU+S,IJᶒWa\>\grn 8W [ez^Eޝo9F03"Z[[k5&λg?'Af eVN]:L B)"=kRHT~#u(VGYm8};| L#T> @SP}ŋ8?.M'˱.;#cWd 2SuXȝBB$v4o/&|>tww՝ KGKCh8_?wɛ/)y6"5cOϨcՐW@Ҿ]}pa(}OV 9Pw Dtn9td9ybx԰/dƊep̿Xװ2vp\Z'M^)|3K@Ym2{, 0ڏLh?Yw >~ wd.Hu*|&tq <mo1,mǸH{"|ZNԜ0OlYUw CCU5bֆڻ.G/|U2{5 SWvO Oz.=y̺/ u× _`w}*j NjWw{=7v!o(Ƴa+ٞI@ ~T@ s_8Mj%m,?]k>z8g`?Bw2W澝Mp幯Ԁ[!H`l/ Vƭ:Ff"L֎Qvt8r_~]] @23 ZxfN'/?\~E-iTT6]M X_;hqŢ?N(GD++*,1ʲsD7쯿W?{眂$@Ȼ^^Mar_--bwO$L:8g8wE*I"+K$rHIh𡘱WI+zYr?b tv̠lN#dQ"+4Ev D3ak/ &DDӗe[[H@*.*@apT Rؿ nTU_zY?MP*ܧR N5yS|c&Jl/̝ r:Bn' 51`=۲xJi:u1^$=9H`.=|Пc9A&3e>sZVIerg){q>(["_O'N$`9Y18q 7(cA s_^N&~4?r<ɥE)X])j"S@2Ό8_E AfkC_l>.H qxՑb_BD ؎9@-\t|m+H pHKE&B-YOK7;4-H``/K\x8:|0l)a_PH 4ʴKXPBI R=RD\މ9w\z|r+垿Z{0gE.k92•o`2v dC}xWn5D/YxOun0 #_:pIr{;8<9w]b?0/?7r0o ?P,6 pzX'J 4F&ݷ|Du:?ԩk #7VR HЕ3"sH YS 2(<[ekFՅ{キS[#ԘCWF"M=u8/@cxj%V>Ā/ [&~=WO䧤Fx?b֫P6.@ <;=JλCeNP  "Xv}g.=aP ]~ZXylCjGsμR{CpSѢo?b 9G6zXGHU VZt@|7Cg3\x+%믟bSP[TH;ݱkk-;7V!HDP2-FF kϽl,[[?}"! tlS#M`)rncp!nF~HYRS L _;|}쵥7IKtX*)_:c*j \>n?u䯴%4Cc٤{OO:3HPi@`)tS'sP|'-m.uDn:@RlvR[QpSaIX?VC1m ^'3kO4xaI35T$%v'^I`DQ*VLD`V3~Mμ=῝Ӛ44>+ OV!6 AtvuֺIU /9M a5牶؄&.؂D143Sm WKud sjx{:iM~4V`p<\揎?(fM@ `qXP8v^3cպQ\Ay?/б3`d&?M![PuY{禿5B `Ԅο0 'zZXY(W" 6Mɫ7.hĚ t(8_N=ix1xy3U$RJf;~rQ9kUm( ӯQ&u)\Wi%s@Ot<0<2j3 `}݁E?fD`r&" =O9N`@ig2Mrk,TޗW_ͥ;wNYzc!Pȹh-[kCu(7j?f3YsP@?m 4+e S4w#kO9){PRqyg/XQ/;9;SQeտbS:_=o^Te% : Cq!@O 7g_Õ9oE"z`8SͰ:z{{[~,hړvp `F꫹xg_dCUV߳nPrv~s}OHզ ` VKVE!c!+`vvSx;X -%3g%0>-OxBFsGrI@HQyꈚips;a!1}^/t2:kOJj)%Fs;(XUZPBc"D"qG  7*掚ʼw̺/<_g[a.ŦW3{x.ݶ4a Ls{ԶA "۷͵MC߅5ꤝ́@/eν R V)RM3-Os #Fk_4SZqpYږfno}9gyuW˓g>߀a}oIynn5?!Ҥoc@|K~oG CV%-"I6_ &>s-8ok+Z'S`տMXkrq#Jz~AYo}vχ.R#^9cS `q0[.5vSVA!)PxJ>pii?V':x?>s?ן/(K`TjL V𥹏{);{} cagz,&"XB_rRN¨صy܋ُ?飺DZګ\Ԕ A+kk}ɽABQ)119..qc;3um7O8O{\aN"0Z{Ht+*첞~OMt"мOb}^#$ Yu `DG6Y7䏻 beMzmw XN}S%]?adPLvE싙?|S% M`?XBNܵ{|A۷A  D#W9Na])9O+Zvn]kZm+8g?us%>M#4ж#_^+q?֧-,~`biC :bD~)]{|?+$bumf 5maFͱ^ >̻ߨO(3B߳&nhbr4v@ _s_)h ?ˏpCY9uijfOm_pj@ 7i ͸p({#ѥOFYf|1_P"3 u'HH !HmaSPNy;Ԛ&!]!w,H g< p%v rɨ{ȧkGb+S{[I#~M]7uN 9F'K ubV"Uc~Wz!=P/8dȧoF$*=V_} ̬ _o[IMTc9DON=s׾ط!gO54L13/y\\q}CF ٢޺F.텙bɷ Ϋk'翊c't-j=޽O CC M5W^3gf\9)f~` ?|˱'`hr_57˛-V@zp9`S{vY-GB6rәkz(.k Z!QO/9Io諚db;!hW]'RN X_xSSa4^_)ɧqa˙137$pNjb!?5hj7|'8M[q(`@7:r\\yU9 iP{!lR'. 9{V64ּFEB07! v/ =9~엵٫KG|!6o;S7>r"y5t凯Zx싙/&:`!¬98w=,@ /$YW@Ytot;.F5"XĚ>8 Ϧ/JfZQ&Pe+s_u_ө+O볙Qm!g7w@0md"s_x+s?̝t"95S 7(<:RfL|*m4^ cޜo8e)1kctrHݼ oB{aY5% ܀p3 ǟH}敯&jQqxM}ai`BTpm>GH."TXPz}A _xԌ䤅lځ12}'T]{'BФ窯6! Ǟ.-% :L' o&Uۙ\2Ŵ<~iɮڭno,h ohbwunRfpr)YVޅR& 4>ՙm{(_ThR'y5ƵJ9"+ŶSPܴ<4y&nL~V(oRDɶ}HKtZ9fS2gOB'Smg﯄m"@KN7׽'| H$c3#CQR&f,dlKUM.xuajv9- }KHqaERPN. fHG4bŎkqJdfnB3!JGY ґ^@7*3/\&ǟ?_?Rzɂ/Ƕ'htk)v1>lSzuC d h.&ldS. @SԐJ !Bc䐿QB!PaahRBȒMBT6V @1\8 eI7N trs1geg5\ob^IeuB5c6 b89𹗲/̞r]Fn_?˿B|k7V²brpmg?kѿOHk'qJK;ȤR 9Ë8+H:}Ff(}1'h~3}5syV2u2-Sœ[!fUv7$ˡ0D Ѝ)KC i$7ڗVq+tEDH""P#x[@* 2B> vϸ U|D b̜Fq_xprrqr.JB p/$M0D MQ\f~NEzny3Ǐ~#uJ~ވ_MV_]qgcm ;{|7}(~1ݤޭD!8BE!"\e7/ WOϹ^x)#$AjFx/a$L/xS%{I/ŹcY.zK$w]e@@pr`CxR-C G `[ vaf)86uIIZl8µ)X!B#HI OuS0Q]34S.TH "l)xI=9܁jkI0D4:GN?[5k5nP<-}x%o9PN V@.《PqM)[]k׭zًsSN$$GZjL>b=3WfX2; &,#EmZCzx?, IZcXz}etۯ~+uf:  [ `D\ZS=;IGuSt^ 6-dՅa dnf(r4<5? Ư -P'`H~xDem)M7?獁-;7"bԩ8rUe /n+Mh{qs & `X!j`#ϱXFG|!Kj'ؖM޶x$tO]^rWsSVN)hՆx]_/PaafuV,Zu={خ? ]ADзa\}cP3P5UƯ[.͞Z~2t͘]x{Ч`ߕqJQ' y`w,֔"ܨ;4ucrn.!![a<uxUWSS+S+ R*~Ĝ4? OpK ~y@O32:6nlav4wZة&$EJ l{R`rx`fֽ0=lq.̈gfh#O36]}Xf"h4@q +õdִv2Zv]V?; ?k:%|j33,cD!ng+C̈sfI _җ>o(XL(ixQS\rB#jzKN-aiU3Qj$`ЖTBtEa0lPPӮͳ̺sĀ=:z03=r)R'ڼF<k+}&Ж`[m?5VmS`IENDB`yubikey-personalization-gui-3.1.24/NEWS0000664000175000017500000001460212642452141016436 0ustar klasklasyubikey-personalization-gui NEWS -- History of user-visible changes. -*- outline -*- * Version 3.1.24 (released 2016-01-04) ** Fix a bug when doing consecutive programming that reset id to 0. ** Fix a case where the image on an old key might be shown momentarily. ** Updated icons and images. ** Updated mac and windows builds to qt 5.5. * Version 3.1.23 (released 2015-10-01) ** Fix a bug that caused a crash on selecting keyboard layout. * Version 3.1.22 (released 2015-09-25) ** Fix so version detection works correctly for versions with more than one digit. ** Add german keyboard layout. ** Fixup neo-n picture * Version 3.1.21 (released 2015-05-29) ** Fix a bug where decode functions where given src length instead of result. ** Fix an issue where test cases where installed by default. ** Update pictures. * Version 3.1.20 (released 2015-04-01) ** Some new pictures. ** Add some simplistic unit tests. ** Fix bug with translation of | in scancode to text. * Version 3.1.19 (released 2015-03-13) ** Remove build timestamp. ** Add picture of Neo-N * Version 3.1.18 (released 2014-11-28) ** Image and correct features for plus. * Version 3.1.17 (released 2014-10-30) ** Fixup the Yubico logformat so accesscode is padded out with 0 ** Make texts translatable. ** Include the accessibility plugin in bundles. ** Show U2F as a feature. ** Switch the mac bundle to qt5. * Version 3.1.16 (released 2014-09-16) ** Fix bug where no random numbers where generated on windows. * Version 3.1.15 (released 2014-09-11) ** Add logging output format PSKC. ** Force selection of keyboard layout before programing scancode mode. ** Text changes. ** New picture for YubiKey 3.3. * Version 3.1.14 (released 2014-01-10) ** Fix layout of the confirmbox window. * Version 3.1.13 (released 2014-01-10) ** Add a diagnostics view by right-clicking the Yubico logo shows a window with info about what's happening. ** Make the help window non-modal so it can be open while interacting with the interface. ** Change the NDEF-URL placeholder to a default string. * Version 3.1.12 (released 2013-12-30) ** Text fixes. * Version 3.1.11 (released 2013-10-09) ** Make sure there is no extra box shown around import on tools page. ** Show correct error when there's more than one key detected. ** Support for building and using qt5. ** Allow writing of a YubiKey with unknown firmware. ** Recheck the key properly after regaining focus, might be a new key. ** Add a "flexible" logging scheme, possible to be configured from the GUI. * Version 3.1.10 (released 2013-07-04) ** Add import page under tools for importing ycfg. ** Minor UI fixes. ** Fix for crash on scan-code entry. ** Fix for crash on the number-converter. ** Add serial-number checkbox for access code entry. * Version 3.1.9 (released 2013-04-22) ** Add experimental export support to ycfg-json format. ** Always ask what file to log to when saving configuration. ** Rework build-system to never compile-in libykpers and libyubikey. * Version 3.1.8 (released 2013-03-18) ** Fix programming of OATH MUI Identifier was never added to the token, broken since release 3.1.3. * Version 3.1.7 (released 2013-03-14) ** Try to make some version dependencies in the GUI clearer. ** Change around the "Upload to Yubico" feature: It used to spawn a web browser with a standard URL with all fields, instead write down a html page with a self-submitting POST form to a temp directory and point the web browser at that. ** Fixup entering of OATH MUI. ** Add support for new YubiKey feature: Inversed LED, appearing in firmware 2.4 and 3.1. * Version 3.1.6 (released 2013-02-21) ** Only lock the key when window has focus. ** Fix OATH configuration for 2.1 keys. ** Make the override box on the http warning for NDEF work. * Version 3.1.5 (released 2013-01-10) ** Fixup building on osx. * Version 3.1.4 (released 2013-01-09) ** Display library version on About page. ** Do confirmation if NDEF does not start with http. * Version 3.1.3 (released 2012-12-21) ** Bugfix for publidId as serial in multi-key writes. ** Correctly show and enable what the production NEO is capable of. ** Support for writing SLOT_NDEF2 for production NEO. ** Fix saving of pacing options. ** Switch animations to mng, higher quality. ** Create a setting for toggling animations on and off, accessible from context menu. ** Different error message for challenge-response than configuring. ** Fix a resource leak when auto-programming keys. ** Fix oath identity increments. * Version 3.1.2 (released 2012-11-07) ** Support for deleting YubiKey configurations. ** Re-read key after writing it, so we can see it changed. ** Add Access-code entry for NDEF programming. ** Fix bug which wrote same key multiple times in multi-write mode. ** Small windows installer fixes. * Version 3.1.1 (released 2012-10-17) ** For native mac builds, sign and use pkgbuilder to create pkg installer. ** Add logging format "Yubico" that corresponds to other tools. ** Show which slots of a key contain valid configuration. ** Refactor scancode input for static keys, now allows editing, pasting and entering raw scancodes. ** When scanning if the key is present, keep it open for as short as possible, should increase possibility for other concurrent accesses. * Version 3.1.0 (released 2012-09-28) ** Support for features in YubiKey 2.3. Requires updating the ykpers library to version 1.8.0. ** Support for writing NDEF of YubiKey NEO. ** Removes the dj prefix that was added for customer prefixes. ** Support for entering customer prefix in modhex or hex as well, show all formats. ** Option to allow public id to be based on key serial. ** View for testing out challenge response with YubiKey. ** Autosave settings when changing. ** Don't write HMAC-SHA1 without variable input on 2.2 key. ** Oath IMF is set as direct number, not as what was entered * 16, also use higher ceiling for this. ** New windows installer based on nsis. ** New pictures, and changing picture depending on YubiKey version. * Version 3.0.6 (released 2012-06-07) ** Bump copyright years. ** Drop deps/ and libs/ explaining in README where you get them. * Version 3.0.5 (released 2012-06-05) ** release scripting, fixed NEWS file. * Version 3.0.4 (released 2012-06-05) ** NEWS file, release scripting, drop libusb dependency. * Version 3.0.3 (released 2012-06-04) ** Fixes to build system to allow building without bundled dependencies on ** linux.