SSH_Agent This an advanced kde-ssh agent with all features an agent should have: Features: -Tray-Icon -Add/Delete keys -Generate/Authorize keys -Import/Export Keys -Convert/Edit Keys -Edit authorized keys file -Kill the ssh-agent -Connect using ssh-agent and kio, or nxclient -Hostlist for ssh-connections -Update function -KMenu items -Putty-Key Wrapper for openssh-agent -KSA-File format wich parses connection data from an ksa-xml file Changelog: 1.0 -> 1.1 Added lock/unlock functionality Added tooltips and whatisThis info Runtime checks for puttygen/ssh-tools Typo and small bugfixes Many small improvements 1.1 -> 1.2 Login menu with hostlist (~/.ssh/known_hosts_kssh) All dialogs fixed (icons and info) More checks and warnings Typo and small bugfixes again GUI-layout was slightly modified Update function Many small improvements Added Putty-Key Wrapper for openssh-agent 1.2 -> 1.3 New Konqueror Sidebar menu which stores logins to get restored by a simple click System-wide startup script (kssh-agent) which gets installed if started by root Some dialogs where substituted by better ones (Menu -> Combo, etc...) Small bugfixes (Tray, restart after update, etc...) Code cleanup and small improvements 1.3 -> 1.4 Added NXSessions and SSH Tunnel options Added NXSessions and SSH Tunnels to session menu Added mimetypes for nx sessions New path to session sidebar menu: .kde/share/config/netresources More code cleanup and small improvements Hostlist now saved when user was added Hostlist is now sorted on exit 1.4 -> 1.5 Automatically load default keys on startup Fix bug to read key from removeable-media ( wrote media2path wrapper) Added ksa-xml parser Added ksa-xml file format Many small improvements KSA-XML-Format: <connection> <name>Remote SSH terminal</name> <protocol>ssh</protocol> <hostname>subdomain.domain.tdl</hostname> <username>username</username> <command></command> <info>Example kssh-agent file to start ssh terminal connection to a remote host.</info> </connection> Matthias Fenner GPL 1.5 SSH_Agent 0 0 273 140 4 4 0 0 273 140 273 140 KSSH-Agent image0 #Set version var @ConstVarKSVER.setText(1.5) #Start systray @ExecSystrayStart.execute #Get Dynamic variables @DynVarKmdrEPid.setText(@exec(echo @dcopid | cut -d'-' -f 3)) @DynVarKmdrFile.setText(@exec(ps aux | grep @DynVarKmdrEPid.text | grep kmdr | grep $USER | grep -v grep | awk '{print $12}')) #Detect first run @AdvScriptFirstRun.execute #Create refresh wrapper @RefreshViewBash.execute #Create agent-file exe-wrapper @SecureConnectFileBash.execute #Default editor values @keyrate.setCurrentItem(@ConstVarBitrate.text) @keytype.addUniqueItem(@ConstVarSSHTYPE.text) @keytype.addUniqueItem(dsa) @keytype.addUniqueItem(rsa) #Default converter values @ConvertKeyLoc.setText(@ConstVarSSHDIR.text/id_@ConstVarSSHTYPE.text)) @GenOutFile.setText(@ConstVarSSHDIR.text/id_@ConstVarSSHTYPE.text) #Default exporter values @PublicKeyLoc.setText(@ConstVarSSHDIR.text/id_@ConstVarSSHTYPE.text.pub) @TempAA.setText(@exec(echo $USER)|@exec(hostname).@exec(dnsdomainname)) @LoginInfo.addUniqueItem(@String.replace(@TempAA.text, |, @)) #Agent status @if (@String.contains(@exec(ps --no-heading -u $USER), ssh-agent)) @StatusSSHA.setEnabled(true) @endif #Add Default keys @if(@String.isEmpty(@exec(ssh-add -l | grep -v "The agent has no identities."))) @execBegin if test -e $HOME/.ssh/id_dsa ; then ssh-add $HOME/.ssh/id_dsa fi if test -e $HOME/.ssh/id_rsa ; then ssh-add $HOME/.ssh/id_rsa fi @execEnd @endif #Read Keys @RefreshView.execute #Delete temp vars @TempAA.setText("") #Write host list @WriteHostList.execute #Sort hostlist @ExecSortHostList.execute #Remove temp files rm ~/.ssh/.ksshrefresh.sh rm ~/.ssh/.ksshexe.sh #Remove tray icon kill -15 @DynSystrayPID.Text false AdvScriptUpdateFunction 40 -88 32 32 @execBegin #Download online version wget -t 1 -T 5 -O @ConstVarSSHDIR.text/kssh.tmp.kmdr 'http://kde-apps.org/content/download.php?content=37287&id=1' #Get online version as integer KOVER=`grep '<version>' @ConstVarSSHDIR.text/kssh.tmp.kmdr | head -1 | cut -d'>' -f 2 | cut -d'<' -f 1 | sed s/"\."//g | cut -c0-2` #Get current version as integer KCVER=@String.replace(@ConstVarKSVER.text, ., "") #Ask to check for new updates kdialog --dontagain @ConstVarKCONF.text:AskForUpdates --caption "Update-Check" --icon lock --yesno "Do you want to check for new updates?" || exit #Check file test -e @ConstVarSSHDIR.text/kssh.tmp.kmdr || kdialog --icon lock --caption "Download error" --msgbox "Download failed" test -e @ConstVarSSHDIR.text/kssh.tmp.kmdr || exit #Compare versions if test "$KCVER" -lt "$KOVER" ; then if test -n "`kdialog --dontagain @ConstVarKCONF.text:AskForUpdateInstall --icon lock --caption 'Update available' --yesno 'New update available - Do you want to install it ?' && echo 1`" ; then rm -f "$HOME/.ssh/kssh-agentrc" kfmclient move ".ssh/kssh.tmp.kmdr" "@DynVarKmdrFile.text" echo '#!/bin/sh' > @ConstVarSSHDIR.text/kssh.update echo "kill -15 @DynVarKmdrEPid.text" >> @ConstVarSSHDIR.text/kssh.update echo "kmdr-executor @DynVarKmdrFile.text &" >> @ConstVarSSHDIR.text/kssh.update echo 'sleep 2' >> @ConstVarSSHDIR.text/kssh.update echo 'rm @ConstVarSSHDIR.text/kssh.update' >> @ConstVarSSHDIR.text/kssh.update #Restart Application kill -15 `ps aux | grep "ksystraycmd" | grep $USER | grep 'SSH-Agent' | awk '{print $2}'` setsid sh @ConstVarSSHDIR.text/kssh.update fi else kdialog --icon lock --caption "No update available" --msgbox "You already have the most recent version" fi #Cleanup rm -f @ConstVarSSHDIR.text/kssh.tmp.kmdr @execEnd AdvScriptFirstRun 5 -83 32 32 @execBegin if test -f "$HOME/.ssh/kssh-agentrc" ; then #No first run exit else touch "$HOME/.ssh/kssh-agentrc" # #Install wrapper script and install kssh-agent into kde-bin # if [ "$USER" == "root" ] ; then KDEBINDIR="`dirname `which kstart``" cat <<EOFWRSCRIPT>$KDEBINDIR/kssh-agent kstart --skiptaskbar --alldesktops --type Tool kmdr-executor $KDEBINDIR/kssh-agent.kmdr EOFWRSCRIPT cp -f @DynVarKmdrFile.text $KDEBINDIR/kssh-agent.kmdr chmod +x $KDEBINDIR/kssh-agent fi # #First run of kde-ssh-agent # echo "First run of kde ssh-agent: Installing menu items ..." echo -n > @ConstVarKCONF.text #Dirs mkdir -p @ConstVarSessionDir.text/{Terminals,Directories,Applications,Tunnels} mkdir -p $HOME/.kde/share/applnk/System mkdir -p $HOME/.kde/share/applnk/.hidden mkdir -p $HOME/.kde/share/mimelnk/application #NX-Sessions mkdir -p $HOME/.nx/config test -L "@ConstVarSessionDir.text/NXSesssions" || ln -sf $HOME/.nx/config @ConstVarSessionDir.text/NXSesssions # #KSSH Menu item # cat <<EOFMAINMENUITEM>$HOME/.kde/share/applnk/System/KSSH.desktop [Desktop Entry] Comment=Kommander frontend for ssh-agent Comment[de]=Kommander frontend for ssh-agent Encoding=UTF-8 Exec=kstart --skiptaskbar --alldesktops --type Tool kmdr-executor @DynVarKmdrFile.text GenericName=KDE SSH Agent GenericName[de]=KDE SSH Agent Icon=lock MimeType= Name=KSSH-Agent Name[de]=KSSH-Agent Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOFMAINMENUITEM # #Putty wrapper # cat <<EOFWRAPMENUITEM>$HOME/.kde/share/applnk/.hidden/KsshPPKWrap.desktop [Desktop Entry] Comment=Add Putty ssh-key to openssh agent Encoding=UTF-8 GenericName=KSSHWrap Icon=lock Hidden=false MimeType=application/ppk;application/x-tex-pk Name=Putty Key-Wrapper Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOFWRAPMENUITEM echo 'Exec=touch ~/.ssh/.pwrap-$$(basename %f)-$$$$ ; chmod 700 ~/.ssh/.pwrap-$$(basename %f)-$$$$ ; echo `kdialog --caption "Enter Password..." --icon unlock --password "Please enter password for $$(basename %f)"` | puttygen -P -O private-openssh -o ~/.ssh/.pwrap-$$(basename %f)-$$$$ %f || (kdialog --msgbox "Bad passphrase" --icon unlock --caption "Error" ; rm -f ~/.ssh/.pwrap-$$(basename %f)-$$$$) && ssh-add ~/.ssh/.pwrap-$$(basename %f)-$$$$ ; rm -f ~/.ssh/.pwrap-$$(basename %f)-$$$$ ; sh ~/.ssh/.ksshrefresh.sh' >> $HOME/.kde/share/applnk/.hidden/KsshPPKWrap.desktop # #Putty Mimetype # cat <<EOFMIMEITEM>$HOME/.kde/share/mimelnk/application/ppk.desktop [Desktop Entry] Comment=Putty Private Key Hidden=false Icon=lock MimeType=application/ppk Patterns=*.ppk;*.PPK Type=MimeType EOFMIMEITEM # #KSA wrapper # cat <<EOFWRAPMENUITEMB>$HOME/.kde/share/applnk/System/KSSHExe.desktop [Desktop Entry] Comment=Execute KSSH-Agent Connection Encoding=UTF-8 GenericName=KSSHAgentWrapper Icon=lock Hidden=false MimeType=application/ksa Name=KSSHAgentWrapper Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= Exec=~/.ssh/.ksshexe.sh %f EOFWRAPMENUITEMB # #KSA Mimetype # cat <<EOFMIMEITEMB>$HOME/.kde/share/mimelnk/application/ksa.desktop [Desktop Entry] Comment=SSH Connection Information Hidden=false Icon=unlock MimeType=application/ksa Patterns=*.ksa;*.KSA Type=MimeType EOFMIMEITEMB # #NXSession Mimetype # cat <<EOFNXSMIMEITEM>$HOME/.kde/share/mimelnk/application/nxs.desktop [Desktop Entry] Comment=NX Session File Hidden=false Icon=nx MimeType=application/nxs Patterns=*.nxs;*.NXS Type=MimeType EOFNXSMIMEITEM # # Konqueror Menu # cat <<EOFKSIDEBARTNG>$HOME/.kde/share/apps/konqsidebartng/virtual_folders/services/SSHConnections.desktop [Desktop Entry] Icon=connect_creating Name=Network Sessions Name[de]=Netzwerk Sitzungen Type=Link URL=@ConstVarSessionDir.text EOFKSIDEBARTNG #Terminals cat <<EOFMEN>@ConstVarSessionDir.text/Terminals/.directory [Desktop Entry] Icon=konsole EOFMEN #Folders cat <<EOFMEN>@ConstVarSessionDir.text/Directories/.directory [Desktop Entry] Icon=folder_locked EOFMEN #Applications cat <<EOFMEN>@ConstVarSessionDir.text/Applications/.directory [Desktop Entry] Icon=exec EOFMEN #NX Sessions cat <<EOFMEN>@ConstVarSessionDir.text/NXSessions/.directory [Desktop Entry] Icon=nx EOFMEN #Tunnel Sessions cat <<EOFMEN>@ConstVarSessionDir.text/Tunnels/.directory [Desktop Entry] Icon=connect_established EOFMEN fi @execEnd RefreshViewBash 100 -131 32 32 cat <<EOF>~/.ssh/.ksshrefresh.sh #!/bin/sh DCOPID=@dcopid ssh-add -l | grep -v 'The agent has no identities.' | cut -d' ' -f 3 > "$HOME/.kssh.keylisttemp" #Clear list dcop \$DCOPID KommanderIf clear CurrentKeys #Run throught the keys while read KEY do dcop \$DCOPID KommanderIf addUniqueItem CurrentKeys "\$KEY" done<"$HOME/.kssh.keylisttemp" #Cleanup rm -f "$HOME/.kssh.keylisttemp" EOF chmod 700 ~/.ssh/.ksshrefresh.sh DynVarKmdrFile -57 -247 131 26 DynVarKmdrEPid -37 -207 81 26 WriteHostList 143 -142 32 32 echo -n > @ConstVarKHOSTS.text for i in `seq 0 @LoginInfo.count` do dcop @dcopid KommanderIf item LoginInfo $i >> @ConstVarKHOSTS.text done zlabTempVars 10 155 56 16 8 TempVars zlabFileTemp 180 155 71 16 8 Config-Files TempA 10 170 32 22 ConstVarTempSSH 130 170 32 22 TempAAA 10 170 32 22 ConstVarBitrate 95 170 32 22 4 Inndex of default bitrate zlabsshdefaults 80 155 66 16 8 SSH-Defaults: ConstVarSSHTYPE 60 170 32 22 dsa Default SSH key type ConstVarKHOSTS 175 195 80 22 ~/.ssh/known_hosts_kssh Host and userlist TempAA 10 170 32 22 ConstVarKSVER 10 210 56 22 DynSystrayPID 10 235 56 22 zlabTempVer 5 195 45 16 8 OtherTempVars ConstVarKCONF 175 220 80 22 ~/.ssh/kssh-agentrc KDE SSH Config ConstVarSSHDIR 175 170 80 22 ~/.ssh Location of ssh-user-dir ConstVarSessionDir 175 245 81 22 $HOME/.kde/share/config/netresources ExecSortHostList 115 205 32 32 cat @ConstVarKHOSTS.text | sort -r | uniq > @ConstVarKHOSTS.text.tmp mv @ConstVarKHOSTS.text.tmp @ConstVarKHOSTS.text ExecSystrayStart 80 245 32 32 @execBegin ksystraycmd --quitonhide --tooltip "KDE SSH-Agent" --window "KSSH-Agent" & sleep 1 dcop @dcopid KommanderIf setText DynSystrayPID $! @execEnd RefreshView 80 205 32 32 ssh-add -l | grep -v "@ConstVarSSHDIR.text/id_rsa" | grep -v "@ConstVarSSHDIR.text/id_dsa" | cut -d' ' -f 1,4,2 | awk '{print $3" "$1" "$2}' | sed -e s/"("//g | sed -e s/")"//g > @ConstVarSSHDIR.text/list.tmp # while read Keyelement do dcop @dcopid KommanderIf insertItem SSHKEYLIST "$Keyelement" 0 done<"@ConstVarSSHDIR.text/list.tmp" rm -f @ConstVarSSHDIR.text/list.tmp #Key-List @CurrentKeys.clear @forEach(i,@exec("ssh-add -l | grep -v 'The agent has no identities.'") ) @CurrentKeys.addUniqueItem(@String.section(@i," ", 2)) @endif #User list @LoginInfo.Clear @TempAA.setText(@exec(echo $USER)|@exec(hostname).@exec(dnsdomainname)) @LoginInfo.addUniqueItem(@String.replace(@TempAA.text, |, @)) @execBegin if test -e @ConstVarKHOSTS.text ; then while read string do dcop @dcopid KommanderIf addUniqueItem LoginInfo $string done<@ConstVarKHOSTS.text fi @execEnd #Del temp vars @TempAA.setText("") exit SecureConnectFileBash 346 293 32 32 cat <<EOF>~/.ssh/.ksshexe.sh #!/bin/sh function xmlsparse { #Needed vars xmlfname=\$2 # e.G. test.xml # Filename to read as xml-data xmlident=\$1 # e.G. <username> # Identifier to ready xml-data from #Simple Checks test -f "\$xmlfname" || echo "Usage KSSHExe [xml-filename]" test -f "\$xmlfname" || exit #Computed vars TMPCNT=\$(expr \`echo \$xmlident | wc -m\` + 2) TMPVAR=\`grep "^<\$xmlident>" \$xmlfname | cut -c \$TMPCNT-\` #Check if identifier was found test -z "\$TMPVAR" && exit #Check if delimiter was found CHKVAR=\`grep "^</\$xmlident>" \$xmlfname | cut -c \$TMPCNT-\` test -z "\$TMPVAR" && exit #Get next vars to cut end of line TMPCNTA=\`expr \$TMPCNT + 1\` TMPCNTB=\$(expr \`echo \$TMPVAR | wc -m\` - \$TMPCNTA) #Output var echo \$TMPVAR | cut -c 1-\$TMPCNTB } dcop kmdr-executor-@DynVarKmdrEPid.text KommanderIf setText LoginInfo "\`xmlsparse username \$1\`@\`xmlsparse hostname \$1\`" dcop kmdr-executor-@DynVarKmdrEPid.text KommanderIf setText TempA "\`xmlsparse command \$1\`" dcop kmdr-executor-@DynVarKmdrEPid.text KommanderIf setText TempAA "\`xmlsparse protocol \$1\`" dcop kmdr-executor-@DynVarKmdrEPid.text KommanderIf execute SecureConnectExec EOF chmod +x ~/.ssh/.ksshexe.sh XMLAgentFile 386 293 91 22 SecureConnectExec 341 298 32 32 # #Save Connections # @switch(@TempAA.text) @case(ssh) @execBegin #Write SSH Terminal Connection Info cat <<EOFT>@ConstVarSessionDir.text/Terminals/@LoginInfo.text.desktop [Desktop Entry] Comment=SSH-Terminal Connection Comment[en]=SSH-Terminal Connection Comment[de]=SSH-Terminal Verbindung Encoding=UTF-8 Exec=konsole -e ssh @LoginInfo.text GenericName=SSH-Terminal Icon=konsole MimeType= Name=@LoginInfo.text Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOFT @execEnd @case(fish) @execBegin #Write SSH Terminal Connection Info cat <<EOFS>@ConstVarSessionDir.text/Directories/@LoginInfo.text.desktop [Desktop Entry] Encoding=UTF-8 Icon=folder_locked Type=Link URL=fish://@LoginInfo.text EOFS @execEnd @case(sshexec) @execBegin #Write SSH terminal execcution info cat <<EOFA>@ConstVarSessionDir.text/Applications/@LoginInfo.text-@TempAAA.text.desktop [Desktop Entry] Comment=Remote Application Comment[en]=Remote Application Comment[de]=Entferntes Programm Encoding=UTF-8 Exec=konsole -e ssh -t @LoginInfo.text "@TempA.text" GenericName=SSH-Terminal GenericName[en]=SSH-Terminal GenericName[de]=SSH-Terminal Icon=terminal MimeType= Name=@TempAAA.text on @LoginInfo.text Name[en]=@TempAAA.text on @LoginInfo.text Name[de]=@TempAAA.text auf @LoginInfo.text Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOF @execEnd @case(shexec) @execBegin #Write SSH shell execution info cat <<EOFA>@ConstVarSessionDir.text/Applications/@LoginInfo.text-@TempAAA.text.desktop [Desktop Entry] Comment=Remote Shell Command Comment[en]=Remote Shell Command Comment[de]=Entfernter Shell Befehl Encoding=UTF-8 Exec=ssh -t @LoginInfo.text "@TempA.text" GenericName=SSH-Executor GenericName[en]=SSH-Executor GenericName[de]=SSH-Executor Icon=exec MimeType= Name=@TempAAA.text on @LoginInfo.text Name[en]=@TempAAA.text on @LoginInfo.text Name[de]=@TempAAA.text auf @LoginInfo.text Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOF @execEnd @case(xexec) @execBegin #Write SSH shell execution info cat <<EOFA>@ConstVarSessionDir.text/Applications/@LoginInfo.text-@TempAAA.text.desktop [Desktop Entry] Comment=Remote GUI Application Comment[en]=Remote GUI Application Comment[de]=Entferntes GUI Programm Encoding=UTF-8 Exec=ssh -T -X @LoginInfo.text "@TempA.text" GenericName=SSH-X11-Forwarder GenericName[de]=SSH-X11-Forwarder Icon=window_new MimeType= Name=@TempAAA.text on @LoginInfo.text Name[en]=@TempAAA.text on @LoginInfo.text Name[de]=@TempAAA.text auf @LoginInfo.text Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOF @execEnd @case(tunnel) @execBegin #Create Tunnel Options while read forwards do export TUNNELOPTS="$TUNNELOPTS $forwards" done<@ConstVarSSHDIR.text/.tunnel.tmp rm -f @ConstVarSSHDIR.text/.tunnel.tmp #Write SSH shell tunnel info cat <<EOFA>@ConstVarSessionDir.text/Tunnels/@LoginInfo.text.desktop [Desktop Entry] Comment=Secure Tunnel Encoding=UTF-8 Exec=ksystraycmd --hidden --ownicon --icon connect_established konsole --notabbar --notoolbar --nomenubar --geometry 80x40+0+0 -e ssh -t -n $TUNNELOPTS @LoginInfo.text GenericName=SSH-Port-Forwarder GenericName[de]=SSH-Port-Forwarder Icon=connect_no MimeType= Name=SSH tunnel to @LoginInfo.text Name[en]=SSH tunnel to @LoginInfo.text Name[de]=SSH Tunnel zu @LoginInfo.text Path= StartupNotify=true Terminal=false TerminalOptions= Type=Application X-DCOP-ServiceType= X-KDE-SubstituteUID=false X-KDE-Username= EOF @execEnd @end # #Execute # @switch(@TempAA.text) @case(ssh) @exec(setsid kfmclient exec ssh://@LoginInfo.text) @case(fish) @exec(setsid kfmclient exec fish://@LoginInfo.text) @case(sshexec) @exec(setsid kfmclient exec "file://@ConstVarSessionDir.text/Applications/@LoginInfo.text-@TempAAA.text.desktop") @case(shexec) @exec(setsid ssh -T @LoginInfo.text "@TempA.text" &) @case(xexec) @exec(setsid ssh -X @LoginInfo.text "@TempA.text" &) @case(nxs) @exec(setsid nxclient --wizard &) @case(nx) @exec(setsid nxclient --wizard &) @case(tunnel) @exec(setsid kfmclient exec "file://@ConstVarSessionDir.text/Tunnels/@LoginInfo.text.desktop") @end # #Remove Temp vars # @TempA.setText("") @TempAA.setText("") @TempAAA.setText("") AgentTab true 0 0 275 150 0 0 0 221 223 228 255 255 255 255 255 255 85 85 85 199 199 199 0 0 0 255 255 255 0 0 0 255 255 255 239 239 239 0 0 0 103 141 178 255 255 255 0 0 238 82 24 139 128 128 128 221 223 228 255 255 255 255 255 255 85 85 85 199 199 199 199 199 199 255 255 255 128 128 128 255 255 255 239 239 239 0 0 0 86 117 148 255 255 255 0 0 238 82 24 139 0 0 0 221 223 228 255 255 255 255 255 255 85 85 85 199 199 199 0 0 0 255 255 255 0 0 0 255 255 255 239 239 239 0 0 0 103 141 178 255 255 255 0 0 238 82 24 139 Cursor 10 NoFocus tab &Manage Seperator_5 -5 105 300 5 0 12 234 Seperator_4 -5 5 300 5 0 12 234 ExecKnownHosts 100 80 30 20 NoFocus image1 kwrite @ConstVarSSHDIR.text/known_hosts & Edit known hosts Click here to edit your known hosts file StatusSSHA false 175 80 25 20 NoFocus image2 false @RefreshView.execute @exec(kdialog --msgbox "SSH-Agent is up and running") Agent status This button indicates the status of your ssh-agent. If it is enabled, your agent is up and running. Click on the button to refresh the list of activated keys. ExecExitAgent 235 80 30 20 NoFocus image3 @exec(kdialog --dontagain @ConstVarKCONF.text:WarnQuitAgent --icon lock --yesno "Do you really want to stop your ssh-agent?" && kill -15 `ps -u $USER | grep ssh-agent | awk '{print $1}'`) @RefreshView.execute Quit agent Click here to kill the ssh-agent Seperator_2_2 0 70 300 5 0 12 234 ExecRefreshKeylist 205 80 25 20 NoFocus image4 #Refresh keylist @RefreshView.execute #Agent status @if (@String.contains(@exec(ps --no-heading -u $USER), ssh-agent)) @StatusSSHA.setEnabled(true) @endif Refresh active keys Click here to refresh the ssh-agent key list ExecLock 5 80 30 20 NoFocus image5 @exec(ssh-add -x) @RefreshView.execute Lock agent Click here to lock your ssh-agent ExecUnlock 40 80 25 20 NoFocus image6 @exec(ssh-add -X) @RefreshView.execute Unlock agent Click here to unlock your ssh-agent CurrentKeys 5 15 260 20 NoFocus true false false Active keys This box holds all the keys you have added to the agent. Please ensure that the ssh-agent is active ExecRemoveKey 140 45 125 20 NoFocus &Remove all keys @exec(kdialog --dontagain @ConstVarKCONF.text:WarnRemoveAll --icon lock --yesno "Do you really want to remove all keys from the list?" && ssh-add -D) @RefreshView.execute Click here to flush all key of the current ssh-agent. ExecAuthorizedKeys 70 80 25 20 NoFocus image7 kwrite @ConstVarSSHDIR.text/authorized_keys & Edit authorized keys Click here to edit your authorized keys file ExecAddKey 5 45 125 20 NoFocus &Add private key @TempA.setText(@exec(kdialog --icon lock --caption="Select private key to add:" --getopenurl @ConstVarSSHDIR.text)) @if (@String.contains(@TempA.text, /)) @execBegin if test -n "`echo @TempA.text | grep 'media:/'`" ; then DEVID="`echo @TempA.text | cut -d'/' -f 2`" DEVCNTVAR=$(expr `echo $DEVID | wc -m` + 8) DEVPATH="`echo @TempA.text | cut -c $DEVCNTVAR-`" DEVPRE="`mount | grep $DEVID | awk '{print $3}'`" chmod 700 "$DEVPRE/$DEVPATH" ssh-add "$DEVPRE/$DEVPATH" kdialog --msgbox "$DEVPRE/$DEVPATH" else chmod 700 @TempA.text ssh-add @TempA.text fi @execEnd @endif @RefreshView.execute @TempA.setText("") Click here to add private key to the active ssh-agent ExecSSHVer 140 80 30 20 NoFocus image8 #Get Version information @execBegin #Output Version info kdialog --caption "Version" --icon lock --msgbox "`ssh -V 2>&1`\n`puttygen -V`\nKDE SSH-Agent @ConstVarKSVER.text" #Check for puttygen test -z "`which puttygen`" && kdialog --caption "PuTTYgen is not installed" --icon lock --msgbox "Puttygen not found - please install putty-tools" #Check for ssh test -z "`which ssh`" && kdialog --caption "SSH client is not installed" --icon lock --msgbox "SSH client not found - Please install openSSH" #Check for updates @execEnd #Check for updates @AdvScriptUpdateFunction.execute Version information Click here to view the current version information tab L&ogin Seperator_4_2 -5 5 300 5 0 12 234 Seperator_4_3 -5 105 300 5 0 12 234 Seperator_2_3_2 0 70 300 5 0 12 234 PublicKeyLoc 90 15 155 20 true Public key to export to server SelFileE 245 15 20 20 NoFocus image9 @TempAAA.setText(@exec(kdialog --miniicon lock --caption="Select public key:" --getopenfilename @ConstVarSSHDIR.text)) @if (@String.contains(@TempAAA.text,/)) @PublicKeyLoc.setText(@TempAAA.text) @endif @TempAAA.setText("") Select file Use this button to select the keyfile Label4_2_2_2_2 5 45 80 20 1 User@Host: ExportKey 5 80 125 20 NoFocus E&xport public key #Test for empty input keyfile @if(@String.contains(@PublicKeyLoc.text,/)) #Copy the public key and add to auth-file @exec(konsole --noclose -e ssh-copy-id -i @PublicKeyLoc.text @LoginInfo.text) @endif Copy the public key to the remote server and authorize it AddUserHost 90 45 22 20 image10 @TempA.setText(@exec(kdialog --icon lock --inputbox "Enter user and hostname to add:")) @LoginInfo.addUniqueItem(@TempA.text) @LoginInfo.setCurrentItem(@expr(@LoginInfo.count - 1)) @WriteHostList.execute @TempA.setText("") Add entry Click here to add new entry to the list LoginInfo 111 45 154 20 true true Label4_2_2_2 5 15 70 20 1 Public Key: SecureConnectBtn 140 80 125 20 NoFocus Connect using &SSH #TempA is Command-var #TempAA is Protocol-var #Get Protocol using ComboBox (deactivated) @#TempAA.setText(@#exec(kdialog --dontagain @ConstVarKCONF.text:defprot --miniicon lock --caption "Login Information" --combobox "Select protocol:" ssh fish sftp)) @if (@String.isEmpty(@TempAA.text)) #Get protocol using Menu @TempAA.setText(@exec(kdialog --dontagain @ConstVarKCONF.text:defprot --miniicon lock --geometry 250X230+150+150 --caption "Login Information" --menu "Select protocol:" "ssh" "Open SSH Terminal" "fish" "Open SCP Filemanager" "sshexec" "Execute in Terminal" "shexec" "Execute in Background" "xexec" "Execute X11-Application" "nxs" "NX Session Wizard" "tunnel" "Start SSH-Tunnel")) @endif @if (@String.isEmpty(@TempA.text)) #Read command string @switch(@TempAA.text) @case(sshexec) @TempA.setText(@exec(kdialog --icon lock --inputbox "Please enter Terminal-Application to execute:" "mc")) @case(shexec) @TempA.setText(@exec(kdialog --icon lock --inputbox "Please enter Shell-Command to execute:" "find /")) @case(xexec) @TempA.setText(@exec(kdialog --icon lock --inputbox "Please enter X11-Application to execute:" "xterm")) @case(tunnel) @TempA.setText(@exec(kdialog --icon lock --geometry 200x230+0+0 --caption "SSH Tunnel" --textinputbox "Tunnel Options:" "`echo -e '\n-L 139:127.0.0.1:139\n-R 139:127.0.0.1:139'` " > @ConstVarSSHDIR.text/.tunnel.tmp)) @end @endif #Desane command name @TempAAA.setText(@exec(echo @TempA.text | awk '{print $1}' | sed s/'$'//g | sed s/\"//g)) #Save and execute connection @SecureConnectExec.execute Click here to login to the remote system tab &Generate Seperator_2 -5 70 300 5 0 12 234 GenOutFile 90 45 155 20 Enter filename of private key to generate. The public key will have a ".pub" suffix Label4 5 15 71 20 1 Type/Bitrate: Label4_3 5 45 71 20 1 Output-File: SelFileG 245 45 20 20 NoFocus image9 @TempAAA.setText(@exec(kdialog --miniicon lock --caption="Select location for new private key:" --getopenfilename @ConstVarSSHDIR.text)) @if (@String.contains(@TempAAA.text,/)) @GenOutFile.setText(@TempAAA.text) @endif @TempAAA.setText("") Select file Use this buttion to select the keyfile 16384 8192 4096 2048 1024 512 256 128 64 keyrate 165 15 65 20 StrongFocus true Select key bitrate - Default is 1024 Bit Label4_5 145 15 19 20 12 1 / AlignCenter Label4_5_2 235 15 25 20 12 1 bit AlignCenter keytype 90 15 55 20 true Select key type ExecAuthorizeKey 140 80 125 20 NoFocus Auth&orize public key @TempAAA.setText(@exec(kdialog --caption "Select public key to add" --getopenfilename @ConstVarSSHDIR.text '*.pub')) @if (@String.contains(@TempAAA.text, /)) @exec(cat @TempAAA.text >> @ConstVarSSHDIR.text/authorized_keys) @endif @TempAAA.setText("") Add selected key to local public key list ExecGenerate 5 80 125 20 NoFocus Ge&nerate new keys @if (@String.contains(@GenOutFile.text,/)) @exec(konsole --noclose --caption "SSH-Keygen" -e ssh-keygen -b "@keyrate.text" -t "@keytype.text" -f @GenOutFile.text) @endif Generate new openSSH kay pair Seperator -10 5 300 5 0 12 234 Seperator_3 -10 105 300 5 0 12 234 tab &Convert Seperator_6 0 5 300 5 0 12 234 Seperator_3_2 0 105 300 5 0 12 234 Seperator_2_3 -5 70 300 5 0 12 234 private-putty private-openssh private-sshcom fingerprint public-putty public-openssh keyformat 90 45 175 20 true true Select key output-type Please select the output type of key conversation ConvertKeyLoc 90 15 155 20 Please enter input file for conversion SelFileC 245 15 20 20 NoFocus image9 @TempAAA.setText(@exec(kdialog --miniicon lock --caption="Select private key:" --getopenfilename @ConstVarSSHDIR.text)) @if (@String.contains(@TempAAA.text,/)) @ConvertKeyLoc.setText(@TempAAA.text) @endif @TempAAA.setText("") Select file Use this buttion to select the keyfile zlabEditInfile 5 15 65 20 1 Input-File: zlabEditOutType 5 45 75 20 1 Output-Type: ExecConvertKey 5 80 125 20 NoFocus Convert &keyfile #Check for puttygen @if (@String.isEmpty(@exec(which puttygen))) @exec(kdialog --caption "PuTTYgen is not installed!" --icon lock --msgbox "Puttygen not found - please install putty-tools") @endif #Select suffix for key-file @switch(@keyformat.text) @case(private-putty) @TempA.setText(*.ppk) @case(private-openssh) @TempA.setText() @case(private-sshcom) @TempA.setText() @case(fingerprint) @TempA.setText(*.txt) @case(public-putty) @TempA.setText(*.pub) @case(public-openssh) @TempA.setText(*.pub) @end #Test for empty input file and puttygen @if(@String.contains(@ConvertKeyLoc.text,/) && @String.contains(@exec(which puttygen), puttygen)) #Set Ouput file @TempAA.setText(@exec(kdialog --icon lock --caption "Save key as:" --getsavefilename @ConstVarSSHDIR.text @TempA.text)) @endif #Test for empty output file and puttygen @if(@String.contains(@TempAA.text,/) && @String.contains(@exec(which puttygen), puttygen)) #Do the convertion @exec(konsole --noclose -e puttygen -O @String.replace(@keyformat.text, "-putty", "") -o @TempAA.text @ConvertKeyLoc.text) @endif #Delete Temp vars @TempA.setText("") @TempAA.setText("") @TempAAA.setText("") Convert keyfile to the selected output type using puttygen ExecChangePass 140 80 125 20 NoFocus Change &password #Test for empty input file @if(@String.contains(@ConvertKeyLoc.text,/)) @exec(konsole --noclose -e ssh-keygen -p -f @ConvertKeyLoc.text) @endif Use this button to change the passphrase of the selected openSSH private key 789cb59bd7ae2ccb919eeff91407ac3b42a8e9ae2e0b4117cb7bef97a08bb4e597f703bdbbb2f3ff2b776f6aa8810eceb049821faa2a5c464644e63afcb77ffc717b7af4c73ffeed6faf6fe2ad557fa846bcfcf10ffd3e8edffff37ffd8f7fffdbdfd3f20ff7ef2acffe48fefedffef6f7b3b73fd41fc78f0f660971e4209acdd279592ef9019ca48b522c79dcf4bc98f84178ced3b29afbe7a5e7c2f1cc3f979eab5456a9674556e0f1dbb34a3538863c9b1ac88b674b9ecf534bbef79c64f3ca1b3fbe795e6469552d595c7bceb205e58de4143c405e9e1595f4df576421bc3cf9e1b9c8f22af7df3f900bf043ecb9ccb4c8bc3cbc5f6555a5fcf7902fb3b2f2f18b1fc91578dc221b017b609fca64a5fdfb83679d09bebf0dcee7a258b27af16cdcfb3efef1135981074dd695f5ef5f2c39996706f6c5cf640bee8b89855faff1c773b20c887feee39d2c9c7e1f7f6d3da7f9ac42bebc90e7e01efaf27c2116fe7d6f7f52e409ec895fc90bf0f84eae84f7bff7f14c4aa71ff9b1e3b9ca259e6bbf5e8970cf910f6fe41cdcfbf825322fb83e73cf2ad7c2eb33f04fbbe7debef89d5c827b49ae845fef718d6c84f7af4b3d5b678f5f0fe39f2f66b980bef8832cc1ddb9e7b9d3efd773f8041789f4f9a6bd7f8bc4bd8f7c356445fd05b898e37d0bf98be979fc49d6e0ee8d6cb17ed6afdf2273eced6d212f2b66c2e7bff1fe2c72f71cf9fa0576cffdfbe3063993debef6ca735124c2e7cff040cef1dcf8fdb128ddf75e5efd469e0bbf3f63bfdf1795fbdeb3fd0ceced6d0fc929d6bbf6fb69211cc3de75cf72fa3efe216778de6e9273ac97c93cabe97bfb45ce68bf210be9fd6d608f2e0ae86f272e913f31d6db38f6cf45ebd93a7bfcf7f69bccefe39bc0de9ef6915c49bfdf629f6fe9ccc9c37eeac915f445be5ea4f3f0fe3a59e07d3b0becdf6f024bec87926c24e2e5f7439ab878f8f5699fc992dffbfd902e0a857c8b37c81afa2dbe4fdd732fbfbe236be9f74febfd4f33c7d89f7e3dd2bcb09057bf04f6f9d2c3debc4ca45f8f1afa0bf71cf27cfd48cb7206b6b781fdf7d6e7575a95aea47a7d5be404cfd5a5675128c4abfe004fefb7c79ee5c426212fa4df4ffd253997a8a7be7ea5aad05c2fd8a7a6f73bdfbf52572fd01f25e2a50bd69f9a5ca678df7c05f6f9d3211f4c6ef9fd2778d2d7de80a7ef7541cea45f4f81e7b630ccd71db0b3dfcbd79b81fdfb9defc7d9ac989788ff27787abf4e02fbf7b52617c8a77e7a5f28bfde1d9ebbfa56fafcb7f87e3ec98b773d276589efd55960ef6fe7f763b6700384f7573d81cb8acf7dffc9d222c37379072e85f4fbbbab3d67455e7affed0fd8c987fe3db2c4fbf22d30fae14836cae74f9d7bce8ba2427ec19fdcadb7cfe7e68b4c79d10659415ed7782edcf77eff34b0a72853d4bb7a41ceb15f9a6fb284bfa2266bcaf3f5262b0bce5b75411615fcdb074fefc72ab05f8faef35cb9f7b1bfa1bf72f9e3f7579390f97d8fefabcab550ff3dec73fb07f342acc956223f4f02a3bf7f80abb9f2fa3a5fdf3219f4a760974fe897be7f67aa5095b7c720fecac513f5eb00ece479fd1dd6cbed2fce7b19d8e58bb7b7bd053bfb31dfec9253057d7cbf722a7c3c7d7dcd4c31cd47585f532d607f7c484e99efbeff656ebf213f9a35b05b3fc4270f8cfe5b81ddf7a8875e7f3e73fa7cfec447e02a57deffceefe77c5e56c897b8202becc7fe0aececc7fb17e44a61bff8f8bbe98bf2fa39b980ffd6db972fca39e6cf7a8d9c80bb8a2cd12fe3926c919ff131b82ab15f8ccfff3cad66ccd74b72097dbdcfe73c2b35e4f590bf1c9f31cf9c9005f3ed9dac15e643dfaff2bc34ecaff83e77fab0ffe14f317d3f58b2c4fa0ef0af2c33c4bb4ec905e6ff1afeb9dd857c8c6232fb537c4a56caafe7e0f325afca1cf9d290ddc08a79589315f53f9235bf4fc846f9fc1e103f511688fff043ae605f1481dd810afd7f8d5c201fe33332e5b5f0478899f2fb71f0f5df15f312f2ed1659607eec1fc0d3f7daef975c5519f44582cc7e387c912dde8fcfc14e1ffc817cb71f713eb0115960de35c867edf2c3ef97c1f7d365f7c4f9209260e71ff6fb0f59427fff0d76fa30ff5d9353ede331f8fee7baa944bd32f0df3a7dfeb929c982f5698dacf0bcd9204ffe617f599140dfe0e353cc4a05f9763330eac14836605b802bf6c348912be8b70bb2c47eeaafc162a130affafee5bab5c679c76c8183fdeb64031e7cfd73dd98e73b13812bf6eb06f626628e7ad11e910bedebc5e0fb49b170f6239eaf644bfdfb8191cf77e06a86e7cd03798e7933d264897a64b6c98af56b03ecd613f52a2167cae7cfb81e18f9e7fb819b162ccf9b884feae4c3ff8cac501f86946cd00f1bc42f9de23bf27b516ae4a3aff745e6fcf1f22343d6589f21271bd63bc43373f981f9a1222f982f31b980fdf125b9a43f887feee285ef4fc90b9c77f43e99f132824c7b224bb6a8b735e2993b7b7cfc9b6d72867ada6e91a546bdf4f5dc4d2b09f59f9139afe89aac19df826ce93fe4b9d335ea6f139333c437fa21d3df0ef9e8ea2deacf70424eb05fcc5e60dc6f9c92533cd70764ce6b4692e97f047b4b974f38dfed900be4d3303daf502f3a5fcf0a37ef309fcfc829ec6bf7c88af3c53959731e6fc8b46728c1628efad96d9333d8536f9273ac471305c6fbd8ffc2ad3fee1b6a72caf3eb3939837d569015fa739b920ded433e2ffb01e2abc873ac57d49017c8976e875c307f76c915d62f5a234b8dfa731b18e7b72fb2d5e87fbe7ebac343c6f8de907370dd920b9cd73579b277a8c809ea7f23c825e38578ab8ae7dbe1925c50df5560f8f74cb6888fe273a7cfaf5f734ea63e7d3431d66f8cc929fbd32e99f1aab7c8b44f18b2427cba3bb2d6b8efda271b708ffdece653ecff0efb438b19cf8b0979cef3593731d7b325a7e85fb62497cc374916a877cd1e59623ff4fefce5a6db9cfbef9a5c227ef6845cf1bea521f3fe41f17d172ff4c30bf202f1d2c7e414f11a2372c6f97a8f5cc1fe7a3b30eac73dd96a2f7f3c088cfd49fbe55c7bfb0d9ebb6ec8f38d2027385fe89ebcc0fa461d39477fb4dbe40af1b31559c09e7a872c194f45d68867b31f18f5f31b2c67b0dff8f52edd3c80f37bdf81c502fb59dd4c8cf5d503798a9f20e79c07f6c912f60f0bb245fec957b08b0fee1b0f0323bf737282f835d03777f5c5fbd7bf81837db7e4c91e492ed1afa23e30ee1b62f214af3958a61afbdfe78b3b8d08e853d0e7ba13d6a73f2367d0af4772ce7cdf214be6cb015953ffeec4588f46930de2d34cef5bec4709ff12170fdcb75c92178cd75160ec473c77f30defe3f0fd42e49847d4ddc4b0775464c17e3e0446bf5e274bf68f883ce517d66f31ada7f2e7a7d2754bae87260b9eff76c9fcbe3b241be8abf7c8cc97c6805dbee27eed919c6ad8ff45ce35f697ef3fa5abf6d86f830cece5ab8f89e17f349225ea65d39115d773fade205f6a41b65c3fc43f9bd6a3a17c5968fcfdc0d773775a33b8ef302d78da2fa3214bce4f5f81b1dff7c886f146fee52edeb88fd90f8cfe61c909d7e3949c633f59acaf3b7da29ecb845cc25ff51918fbb723579827d4fdc4982ff5035980474b56ec07d3738dfd30d664c37c427c8b697d9b63728a7c8eafc805f6a7f2f7b7a53bcef17cf246e6f92c7a24335e56912d19f12a9d3ebf1ef50179817ad8d4e414eb393c9133ee2fca9bec198fc925b8be270beded91a87f95e0fd88fa224ff16ac816fbc562bf546e3d71ff7c404e109f5a91277b4fc839f683f2f5dd8547223e6687ccfb8c11f9e7aa1bf4454f13233ee6903c677e37e49cfe6f902becb7f1842c90ef12fb4f4efe35580f29e7d85fd69013c65f9353e46b7d48ceb89f4ec905fb01eab93bed327f33b2a2bf1d59339f7f02c37f3e97bc2f889ec9b4c71e92a7f85e9233c6ff88cc78372db900eb9c2c118ff13430fe1ef04ad606f1c67ed482f73ba6271be6075926b0d71c4d0c7b477e2f179c172c3985fd767a3f677c4d60af4f4cefd33e89fc34533c654e66fcd41ad9603da317b08b17eadb313945bc6c4dcea0df7c9235f6470b79d6ad27ce4fdb64f64bf91d18f955902df4abf5c0a82fa8e756a6885ff44ace180ff43fab66c6e777ebfb913b6de7d03f3e8025cf8fe664627c1f7d930bec0733271b83fbde33b2050f3e3fdc6993f7cded59601f0ff943a63fb2044bde9f456f64ae9f6dc805d6aff5f565797ae4df839ec8fcfb835c033b79b8cf7824f3fc674ec994675b7205ffec2bd8c50bf5f39d9c18bfbe9d5f6f775a9cf45560b7dfb11e4f649e7fa3f789a1cf9c914beef75bf0a4af7d23cfc11de29dba7e84792c220bfe3d0adfa793bf729d4c7bcc2539613d8e27467f6f5fc839f237fa20331ecd1558cd90bff6869c209fc6f3c0b84f423cb360df1d78b2476e90a95f5c9035ea6b03f9d9e47ff342a6befa99bca03eac979b1f70be10f760b73f31cf46e414f53dfa240bd6b36bf0a4afbe2153fe78414eb1fe6641ce0cee73914fc5a4bfbf21f3ef2972132c795fdabe9205eb2bd6af70f2707f0ff9a5d0fcfbd40c3c7d2fb7c819fdf9222bce3ba7648df5abbbc038dfd9c0b82fbb271bd67fe46fe9e28df3c22b99f6c577e41cf118fc7ce84e5393bdc8d7cad98778223faa495e7d4d4e11dffa899c31de9781a1af23e7e0e68d5c20fee69b5c1afcfd15f9eafa3fe62381efc5648fdc26e79cb7914fee34c07ce6f74e1feed7eec8d4d7dc93a94ff879b2924e1efef9a61d7281f56d477078dff7b7e5ed16ded7b764d60bb19818f6690976f988f37c464ed94f6764c6cf5e937370fb402e189f922c0cf68befa79576fabc3d2225573c8fed06f6f197c86fad16a807ea6162dab71e18eb7f419eecf920331eed3bb9028fd781513f103fe3ea25ced3a80766d25ff7e48cfd6d832cf0fd781318f3ca165919dc5740be953c1f8a8c2cd83fd7c98ae74fe48b5539f55f920bec87f1962c21bfdd272bc6dbc74bcca6fd2f72b2a4be33f0e44f3d900bc6ef802c216fbc236be8d3866c0ce6019f8f621ef43d92a94f1464c579e509ac12d4073b9273da3371097febabc0e8f79764c6b7bd20d3bef19e6cc002fa12a71ffe9f8383bf3959c39f3623d3bfee956ce9afcf57b108fe3d9335fc136560f47facc7c2e9c3df872ec815fd7b088c796946a6be0eebe5ba0d78cc02fb7ea6ce03fbf923f2e75b914ef1161599f7b7e61763fe457cd360df23b964fd9c58a03e752f640bfde31c3cd9d3fb7c76d327cfa7d13ed9d09e97c09857aec1933e7b4916accf0d7892df9d92e7d4ff1a18f3f4333931a877789e4ffe5be443eee4e39f37b0e0e9fb6e414e184fec87c27d8ffafa0676f30ae2f94cae103f7343a67c3b3d97f0c75e05c67d5d02d60bd81bf9f3922827f9fa8e5c52fe0b99f9636ec9d41721fee5242fbe26a760791f18ebe3cf33ee343de77dd87b609cf7e664de1faa949cf13ee68d5c729e7d216bce2f3d78d2372ec819f5fb79d79d6e13e8131f81516feec902f9615ec992fedf9115e71bf224bfcfc9b9f5fd43be07f6f646fe3c22a4abf7a8179f64de5fb63fe41ce739fd4ea63d7a4696b4ef8d4c7bcc3d798a07bf9fec195372011e86c0e8bfd87fee7c8bf397f80207fb76c805fb654616aca7c764daa73f02fbf8e93979b2f79d3cd98bfaa2267b063ed725ec155781513ffcfcefa623da1b61bf2efb39eeb712b2e67ac15e374d42be68c815e445a87faefff2be6a83ccfbc9f6945cd2ff1db284ff2a0f0cff3fc98af9f34136f07750e0a01ffe5ba71ff5569073e47f7b47ae309fa8824cf9fa8b6ce0af5e04863eec0f1bf46d9285c57dbbef17eef4c5fbcf2e260bec37a5c993bfbb64057f55499ef47f07c6df1f52b2c57c14df82dd788b79c8f71377ba2aa13fba0c8cbfd77d9227fdd3fb9afeff90297f7c013bf9a8bf2d59818d8ff7f27606f18eae02e37e629b2ce9bf214ffe5664cb7e0afb9249bef6f924ddf917fda95f232738bf8b6f32f545d764de3f360bb2c47a77576405ffe52159331e966c100fb51f18eb81f55cf66fac07ed71fd08eb5193b545fff0fb45a68ae7cfe8864c7ba421537f5704c67a1e910de35593192f751018f644e0c99e1ef2b3c91f794cb6f4af013b7ff0f7de5f8cfbf343f29cf20539c13c1d21ff72174ff863c9b4b77f244ff6c29f65bf867d1b8121cfef4f77fae1fda0d8261bae574da6fdf2043cd9dfff90e7d4d706863fc7e405f4f59b81711e80bc72f227ba2753bfd8215bae0fe2553afdb0e7943ce9efc8f45751fea4afdf22a7e0c8f7275939f9d087fa504df2950a8cf3574ba63e79464ee86f4f9efcdd266798b723df4fdc6960067fc41e794e7f3a32e5c973f282fe0ce494f277c839e44bec17e9fcc17a623f49270ff6f6e405eb6b44a63c359233c4a7c6fa2ac5f3689480277bc50179b27720a7b0575e0486bdbbe402f3698df571dd90f79da81f3ad87b49a63dfd1eb9e4bc8b7c77fd8bf6a15e9bc93f71489eec19c919ec9157e49cf2f7c915e75bd413ebbe87bc237246790fe49cf2aec905d6a33f200bcaf3fdd64daffc5e6832f5cb4772016e0732ede90fc992f3b0af5f6e1aa57e714ce6f7f2895cc29edaef1f373dcef8f78357f21cfd446a32ed8b4af2e4df33b9c279ab3f222bceabbebfb8ea4bfde2844cfdfd3159733ef2f9eaa6b592ef9f922b9e4f7d7ebae962e233b2807ee1ebe3f2fffec4e7e76489fcd07e3ddc7490c03f21c992dffbfdedbab522fbfae0c63bde1f74f0cf689e3785df0fca6a9ea78dcf6fbdd0ecafdd0c6c72cc07bdf76f993d641fff6574d16f07dfefb59b9e59bfc9a6c473e1eba58b26cf2bc2f73fe72de777e9f3cb59cbf9d8f8fee3a4a5ac078accf9b349c99ca794df6fcebb9cfe6d902bcc9b4d1618f3ab5f3f333305de6f7232e731e1cf5766ee18fa0a32e7a5a60c8cf3bd9f278ceb46f0aff1f9e3bce5f33626733e697d3e38ef261664f6ffd6afaf8bcec48a6cc83ebf9db7139bc0f8e7692cd9927bb09d59dc97f97ee8bc9f9e3781d15f4fc0766ef1cf07fbfde2a23fe3fb6d60c8ebc8738bf332ecab26f9daef07239c7d383fe27de1de47bf83bf7262e3ebab1bd72de2af7d3d71b4807cb94f4ec1d6fbe7ac59707e4ac97c6e7c7d739483d516b900b73edf6d363d6fe7643ed73781f1cf37f8fc72446eefc92558fb78d9ca0a8bffff8a0c8cf385df0fcba7e0ba262b70ebfb937bcae7fa89cce72a098cbfeff97c5a1258fbfdb7243ef7f965fdbf967cf676f61647ff35bfa56ce8f02c6219ab58ff453fe5a4096859eaf01a4c6ce3fa2ffe5927d5c9a60e1137711b77711f0ff1183fc48ff153fc1cbfc4aff15bfc1e7fc49ff157fc1dffc46bf17abc116fc65bf176bc13efc67bf1beb3f9203e8c8fe2e3f8243e8dcfe2f3f822be8cafe26b27b159fa421d37f16d7c17dfc7b3781e27f1224ee32ccee3222ee3ca1912452292918a7464221bd55113b55117f5d1108dd143f4183d45cfd14bf41abd45efd147f4197d45dfd14fb416ad3ba937938e6823da8cb6e259b41ded44bbd15eb41f1d4487d151741c9d44a7d159741e5d4497d155741ddd44b7d15d741fcda27994b8df224aa32ccaa3222aa34ac422124248e18e4bae6159277563d2216ad1c4836845277a3188513c8847f1249ec58b78156fe25d7c884ff125bec58f5813eb62436c8aade85e6c8b1db12bf6c4be38885271288ea2421c8b13712acec4b9b81097a211f52f3fc495b81637e256dc897b31137391888548452672518852542e4936a49b27577e6e9894cb7669652d1bd9ca4ef67290a37c908ff2493ecb17f92aae7ef921dfe4bbfc909ff24b7ecb1fb926d7e586dc945b725beec85db927f77f93befa3b9087ee77248fe5893c9567f25c5ec84b7925afe58dbc7552df828e3b792f67722e13b990a9cc642e0b59ba293e56915a5afcaf342c43ef8659e5dab52b08b56a54ab3ad5ab418dea413d3aa977930ef5a49ed58b7a556fea5d7da84ff5a5bed58f5a53eb6a436dfebf34782d5b6a5beda85db5a7f6d5813a5447ea589d381da74eea53d071a6ced585ba5457ea5adda85b75e734ddab993b7d27ff9906af65a15295a95c15aa74137aacdd64b0bc5a7252cf261dda8d2adaaa4b5deb46b7bad3bd1ef4a81ff4e33f4bd34ffa59bffcdf5af4ab7ed3effa437fea2ffdad7ff49a5ed71b4eaa0e3a36f596ded63b7a57efe97d7da00ff5913ed627ff24e7549fe9737da12ff595befe3dcbf48dbed577fadecda57337ab2d74aa3337156de9cda0a3d0a5aedc1ce8d2d8447acff54437e319bd2ac5b836696ad398d674a6378319cdc36fcf1fcd9379362fe6d5bc9977f3e1e6b04f27b59874982ff36d7ee277b366d6cd86d9345b66dbecfc2661d7ec997d73600ecd91393627e6d49c99f3dfdeb83097e6ca5c9b1b736beeccbd9b8de64eea57d091b86966cdacc59f6e6ac9dca451b8d9a75a956063cb0ee7ba906bd5b6b68d6d6db7f2466f073bda07fb689fecb37d3133fbeaa426930efb66dfedc75283fdb45ff6dbfed835bbbef2fd86ddb45b76dbeed85dbb67f7ed813db447d1b7385d79e7d89ed8537b66cfed85bdb457f6dade38a9610fda5b7b67ef8386999b40123745a4e1fbe54ce0fbba6b0b512d6a59ab5ad7a6b6753dbd5337755b77755f0ff5583fd48ff553fdeca4de4e3aea97fab57efba5a17eaf3feacffaabfef65fffd46bf57abd516fd65bf576bd53efd67bf57e7d501fd647f53156be3ea94febb3fa5c67f5457d595fd5d7f54d7deba4be041d77f57d3dfb4dc3bc4ed453bda8d33aabf3baa8cbba6ae2266a44231bd5e8c634b6a99ba6699baee99ba1199b87e6b1796a9ecdacbe6e5eea9be6b5797352432d69de9b8fe6f39f35345fb16abe9b9f66ad596f369acd66abd96e769add66afd96f0e9ac3e6a8396e4e9ad3e6ac396f2e9acbe6aab96e6e9a5b7be335dc35f74eea7bd0316be6b15cd5d024cda2499bacc9ddaf68caa66ae3366a452b5bd5ead6b4b6addba6c5bf3affebdbc1ccedeba4a11ddb8766decc261ded63fbd43eaffad0fe07f5e23fffb5afed5bd0f0de7e38a98f41c767fbd57eaf46a9fdf9533ad6daf5a061c3fdbedacfa063b3dd6ab757d7a1ddf9533a76dbbda061bf3d705243bd6a0fdba3f67845c3497bfaa7749cb5e741c3457be9a41e061d57ed757bb3a2e1b6bd5bf9f2de3cacfeda99fbcdc36fa5c3b48b360d1ab2367752af828ea22d7fd35075f1af2fbba8139dec54a73bd3d9aeee1a97465dd7774337760fdd4a8fe99ebae74943f7d2bdb6651bea6ef7d6bdffa6e1a3fb5cf9f2abfbee7ebab56ebddbe836bbad6ebbdbe976bbbd6ebf3be80ebba395378fbb93a0e1b43bebdebb50afbaf3eee2370d97ddd5ca97d7dd4d77dbdd75f7f255deaa4775aa95eb71b9f95cee876eb6f2e6bc4b828685fbcf45771e74a45df69b86bc2b56be2cbbea5f69b037fd4a54fba817938668dd69c9ba74d2d1cbfe370dbdeecdca97b6afff9586faa66f56de6cfb6ed2d0f7f175af7a19740cfd181fac6878e85756b27fea9fff9586e6b55fa908fd6bff3669e8dfdd7fc67e083a3efacffe6b45c377bfb2cffbb57e5d47fd46bfd96ff5dbfd4ebfdbeff5fbfd417fd81ff5c7fdca64d19ff66741c3b9fbefcffe23e8b8e82ffbab150dd76eaafc137bb0bfe96f8386f3fece49bd083aeefb593fffa5a14fe4f99fd2b1e8d3a021eb7327f53ee828fab2af7e6918e221fa333a0631c849c3a0dcff2afbb007073d98c1ae68a887e64fe968876ed230f4c3e0a4863971188787e1f19786ee76781a9effbf35bc0cafc3dba421da1cde9dd431e8f8183e87af5f1a963b6ef81e7e86b5617dd8183687ad617bd8197687bd617f38180e87a3e17838194e87b3e17cb8182e87abe17ab8196e87bbe17ed210dfbafff53984bc1a66c37c4856352cf7c3b018d2211bf2a118caa11ae3311ac5284735ead18c76acc7666cc76eecc7611cc787f1717c1a9f7f69185fc6572735f4daf16d7c1f3f7ed7f01fefb8950e74f1ab6afccaa5150d9fe397931a6ae2f83dfe8c6be3fa5fa9a13f1f379cd4efa06373dc1ab7c79d7177dc1bf7c783f1703c5a6a198fc793f1d47c8e67f6753c1f2feadbf172bc6ac7f17abc196fc7bbf17e9c8df36e312663125f8f0bb7ebf23175d2b3311f0b27716b0cbdd66929c7ea21fe6b7f633596d35d06ee641ea207f1201fd45ff4934e5af4eb4ee6bffc6ee97ffff7bffd1fcf95730e 789c659657531c3910c7dff9145bee37eaaa3d3b49525ddd03c989b8804957f7a0913418307989aefbeea7f9ab35c6bed55233bfed56e828de2f4e8e7636278bef17eee7767ee626ee9bbd9b2cfa87cbcb97bffff9ebc7c2bb693b19bea59994effe5878379b4fdc64ebfa2a0c4075049adab6ee0d7836b2052f8fec06b63cb287fc56b8e9d37aa7c2adf0677017e5984f69be6f55df83cdc065d9ea5e0fccc7c25d92f30eb8ca4c47e0a6f5225f03b7233f80551b44bf01eb28ef209f83ad2a44be04ee22c31e3e070755897c65e06aaa1a59ff0c1c371076e02a337d03372adb7723acc51f3db88d9ce6776035b2056b6584096c9415f6e04e39e10076235f80bd127fd09d70f607fc5985a88ff8f2c9c075118f9be6e37cf55467ff68b08e5c80cf842bb1e70bd868c90fc2796bab1bc98f16dce9b2afc01538447983fdb685559acf1fc0bd167ff1f7819b4a77b21ff2a3a9b5ed15e44638db7b0d6eb4d8cbf7e056bb147f5223a7fdb47090f50fc126ca6bf027b03585c85f85a7b21ffcdf749193bd8f23a7fd510f8d8bf3533dad0a4fc53ee44be347f9837029eba7f30793f3712e5ccb7976c17d9cdf82af84737da23eda22729aff02ae8cd427e3bcad3156e287fc6f9dc9fedc007b23fea20be12c5f070793f30bf15485c9f9047b95b285f8731f6c6c25fd660fec6cce7fd4b70a56891cf5a06b9bd747bde8d6ba147f2ac12a32fa079d087bc9ef9970107f1c807597f3bb00bb4efccd6053774afc83fe616c67d279782a9ceb0dfbdb22b6a7140fc86deb245e7c09364eea81917fd68e7c289cfbe547b073d23f18f1ed0a97eb1ffdba6b5cf607eaa56b9d977c863f637bc8f6a3febbce17727eacdf395f8a7dc8ef2e444ef5b109eebdc48bb70676a5cfe7433dbac6d73d2e13fe0a565e89ff93bef65af67f065b6f657facef7a1fe4bc4f03fbc28bff18f78daf4321f701faaf6f43ce77f833b6b34afc87feea7528657ff4476f42f62ffa81b7717e5a0ffdc8bbc8a8177e116e653efab9f791537fb91556727f207f7c08b93f57c2393ea8bf5006e957bc2e9cf305fd326ae7fe01fb4317c399ce87fb32f85ee2c1b89f42889cfc85fae98b5eee23827ffbe86d591ff5da47078b1cf18994fb21fa578fcfc0b3f9cfc1c4963b766f7f7babc39e03f77ccadfe2f38ccf7fd7e18ba8f19d2ff98aaff9866ff98eef79ce0fbfe8787ee4277ee6177e8d63899779855779eda74ed4f8c01ff9137f8ef22fbcce1bf1b9c95bbccd3ba34ee019eff25e94ecc7e72e7f8d6f077cc8477c9c74a22d275cf0944baeb88ecf86dba8a358b3e173e274d712911d47478e5fc953881a867a3a4df7399dd1b98c0bfa1e352ee98aae316ee836fd0f4077744ff3f8f7408ff444cff442af329668399d99566895d6647ca08fe3fb27fa3cda754e5f681d638336698bb6857668f6c68773daa5bd38f629da4d07783f1c34dee83cd0111dd30915348d7b1554524533aaff17d3636aa825c5f7a4c9a4357ed71906319d5aa6e55f72e3df3f17fe0374627b19 789c6d9649731c370c85effa1553c6cd9582677a252b958376d95a2cd996b5a47200c96e6dd63e5a53f9efe13ca0275e62f9a0aff048820f205aefde8e0e77b7476fdf2ddc4f657a1647f154ee466fd3c3e5e5cb9f7ffdf1f7c29b4933c2ff6a54bcf96de10d87511ced5c5f7533906f19a8f4a573017c6fec5d042f81a51497c0abe05006a7ebd7c071ce61cefd8ce9d6386a9cd7c1a94c16bf017765e7c7e034e3aaac26be01af80f33f5f627d09aeabd2b738ef05dc64bd47fcc9b832de00bbacc7fdf89371ad4cba5fa8c43bc40b70cc8c7c69d5387af5e319dc559dee4f9fc17d3dd6385fcdb89e54492ac4d794eb52703f11e346703feec165d52b13ceafab7ac8b703bbba10adcfb2b1d7fde86ece9aff1958f2799acff99cd57ff85b87ccea3ffca8631d05cd2153e364f9c1df3ae538f4f2aadc5441e3cfc675d07c23b8af9ba0fb5dceb89934850878dd3805d48fe14753342168fe17e0aaee747faac04dd3daf91a6fda36aa1f38af718de8794cca395e83519fc637a5c56f8d9de62be8af5c0c517fe9c3c001fd261bcaade87e023f9bd404f59370ffa66b3acd9ff09edab22d747f423e6dd59641f59d711b709f3df8ddd6ce27bc2f3e05376e12b57e1370db0efede18a788fe933be5bc5efdbc063b9792d67b0f2c6d1fd18f7ca2ecfa6e02467fb661880bfc69a31b9b7fefc1a915cd9f1f8d7bf36351d94f12eacbe319bb71ce5ff3c3fdddc48dad5f90afab5d11b5dea8af6b5c15f57da35f5c7431e97bc17dfcc41751fb09f7f745667d7ffbe0da37ea177d05b7beb3fba31ede7997b43ee8172fde9b7e131ca5543da11f7de743823f84fef7bd1449eb897c642c561fba1c58fd17cc1f29a4d0fe64bc973c3e9ba4f303ef532ab17c05f516273ea99f0c0e129409f35862c803128cf72f7d1827f8455f8c0bed1fc2fb0ae350773a7f6ab08b450f3ff978c6799c855ef3c3feb1c9cf5befcbc65daff7c1bc883e4d7a7d8fb85f0cb1efd4af0be51cd77c5ae3b257ff578deb5efb7b171c53a371c1bc8c7dd6a3be74683cc47be356990e8c9dedff71c6693c3035c6c1d8818b39a39ff3e7a7ec349f15638bf38e71347e304eb6fe085ccfe3cacd3cbea5dc8d2d7fbcf7d4ce59f77349ccbf6de521cea86f8e4e8c351ebbc2786a6cfe9207a7acd7fe3e361ef4f03375733deed78dbbcae2ded8fca65763f35b302fbac9c08c7eeb8a7c9ece8f2de3a13e78fff9733ed463d1d8db7ae52ac7b5ff0e8c2d4ea8e76c9c1a4f8dcd6fea8dcd6fc6df275d3bc419f5eedc5cbf643cd407f33b9f667e13de6317baced6637ee4d5431cfd9a570ff5417f67f5509f4de3c16f7c3f72b4e8753e04e3c17fd43f476be30de3c13fcc83ac1eea81799bd5839fa847560ffa3de3c15ff47f561b8baef7f947e7d795f1e00fbe2f7dea073ff78d073f303f66a4bc376562e1c0911377dce7df7ef8d16f0c9ff2199ff3057fe34bbefa5fcd35dff02ddff13d4ff9811ff9e97f34cffcc2afbcc84bbccc2bbcca6bbcfe8b6683dff307dee42ddee61dfec8bbbcc79f7ed27ce62fbccf5ff9800ff928ab8e79cc132eb8fc4e5371cd0db7ecd8f39498888402454a7aa67ebba9a7133aa5333aa70bfa469774c69b7445d77443b7a6b9a37b9ad2033dd2133dd30bbdd2222dd129d7b44c2ba659a5355aa70d7a4f1f6893b6689b76e823edd25e567db27cf299f499bed03e7da5033aa4233aa671ceafa60915ff69b2aaa48a6a6aa825977ddaca1f371612f95ec3f97b2251f258919e8fe4444ee54ccee5e2474d567d934bb99213dae17db9961bb995bb9f3559752f5379904779926779915759fc5593554bb22c2bb22a6bf9f775d9c89a7f7e5ff8177878f7e5 789c3d96c95224390c86ef3c4545ebd631a1cecdb9c4c41c8066df1be80626e6e0b4d35040155014343031ef3e2afda2020ef5a594b2f45b96f3dbd7d1c5f1c1e8ebb795e7b99f8fc328dcf8d9e86b7c994cdefffee7af7f57bee4f568f15fb951f1e58f952f27f351181d3e4c8705f0bd007529cf32b7603f36cec1ec17ecb34ff613e322cbd57ebc64d81f94f3bcc94ab5d392db0553a55c08c3df1b77603a5f72a37c60dc679dc6c3fa55eeb3a0bcbae4a8fe5bca2e8fb0d38771cab45e3ffde43c53fb0c5ce4c677ca4d51e62a1679e32a473d1fc64daef570a1dc167d8efc6e957d31141a8f554f1f241cf866c91a9fef8cab42f524b764d8af978cf593b12bb03f517928db02eb0fca49ecb57230feb49f2cb8cfca5424e55e39afb212f9ad2b17e560f59d2ab7ae28a0f777e3b240ff6c2877ae2dd10f67cabd1b4add3fde540e2e94c847f7a78f755622feee824356f795d6479a6f28ea58c17fcf78a8d03fbaffa16cf2caab5dfb2554f23eeadb07cb86f5ea3f37ae2aed0f3e307695e64f8db26bea4af5a064dc38e8a1fd1c6a590ff51f1a770efb7165dcbb4ab9546ee47dd81f8d3bd8fdfd92d1ff37c6b2a4fa67c60398e0df4a3cc47f320ec63f968cf767c683835eafe03677aa17b171e1500ff4e9c4aefad1bab1ab711ec6c6758dfd7d56f6e28ffdbb5c32f47d356e109f768cdb1ae7e9d1b8aba1cf6f63efb01f3f978cfdd8560e121ffdf662ecac9edad8fcb9538eb21ee2bf290f6d02d32fe5d4f6b5beefd16fa9930e533b195735fa295f70cc84a1e793715363dee8798f79e76af4dbbb71dfa05eedff5874b1413f6b3db1ecf206f9ec19770df6efc878b0f7b59e5809438f33b0cf1be8adfa46d795884fa7c69ffe05d8172df4783776f0f7bd718df549cf4f6cbad4a01fdec03e433c7f6bec5acdcfd39231bf4be3da58fb25b6521ff45935ee1be80d7d3b9fc3df27e3b6557faffd1abdef5ae8ade72ff6520ffcefc0723d605eeafc8c41ecd8af0de3d0e13caf81655cc05fef83187b5150e3e93c1d7219e7883f18bb0efda67a0d85efe14f17e0be849db51f8752f2819e97c6ae43fd3acf07278cfbc8581a187ae87c1eba9079e8afe76308c1f5b81f74fe0e31343dfa03f90da1ee918fce939405914859efe79487d4e33c6a7da91046ff68fea98c598ff3a3e72f35b10ab85ff4be4e6d6c02f4d47993ba3844cc07edd7e4638ac84fe7610a4315b1ffad721c9a087d74dea634a401f62958ae67f4efcb92a1df9a716efc605c0cc867d7d80d9867adb15c796acf8c53c279feb564adf764cec49e7b0e1c79e0c4d77cc363bee53bbee7c9c95cdf21b14ef9811ff98967fccc737ee157fecd6ffcce1fbcaa3e9ed7789dbff3066ff2166ff30eeff21eeff3011ff2111fe3eee51f7cca677cce3ff997fd5df0255f71c639a31f039712e35c6d153baeb9915f2d77c444040da3e4b1b988413d058a3450a26ba11b1ad32ddde13b806774bf88211e136e68ba58851ec4eb919e68866f09a9655b9e3cd384e634a517f178a5dff2e48ddee903df1f52ed8e3c59158f442fb4261eebf45d9e6cd0266da9cf0dbfd0f6a2164a7c251e0fe2b143bbe2b347fb74a03e63516c6f510b1dca2a47742c1e27423fe894cee85c7d6ee927ef93ea221e17744957f22ba39c0a2a49ef3b72545323b57474f4a921b5e2d179f6f2dda571ee7dcf8b5598c63ef8e807c9e3940a9ffcb5bff163f599c8ce1d712e9ade8a1eef52cb3e9df95b7fe7effdc44fad3756f9980bf2744733faa02d3aa073aafc831ffba9f4c67f7faefc0f95079040 789c5595596fdb4610c7dffd2984cc5b504c44915c7251f4c18e73d8890fc5898f147d18eee1fb96933845bf7b97ff1929ad5610f4e3cceececd572f27c7fb3b9397afd61e17b2380f9370260f9397f1e9fafaf9cfbffef87bed45e526e3b7994d662f7e5b7b315f4cc264f7f6268dc0b100d533d70701871507f0b0e208fe61ec83ee971567f0fa92e3144c2baec079c53086378cc5f86ec535f8ca78880df8d438c40e7c0dae57f61f821bd705e8536becc300fe6a2cea1fa9ff4d5725bdefd27896f4beb315b7238bfadb96f3701ff5c6cbf37e2aaff627b073f5007be946b97309f6b072e7daa187fc64c51e7c6cec06c49b34fedd6a7f03eebb3a21de720196360bec25bd5f5c33c03f51ff06570bf2459d71ab727e367683eebf5db1daaff531f4d3acfb553f14b9037f57ee2b936f81a36b44ebe92338b94ad49e603c537b45f39bbaa9d69344e34a99de8fdc4cfbdace47bd344d172c3fe760d7c65eed5957ee5dd6fb6b70ef2a8f78d1b672dfa99c3e18f7a67f0ff6fd34e979a8df46ba9c50afb4af5ce4c8b7a05f9ae26faff972e0e29fd9b307ceaeeab53e17cabd64c819f6b7556ff964d4533b1b1718f16dbbde5b7d213f6d3f2e9cf746d95759fbe10b587ab1fa467d9462eb23fc13d4479b0a6bfcd06f6d1e1718f5efea7161ff6b70e39ba4f13902b7e3c2fd5eb94f51fb6d0e76de258dc726d89771a1fd330587729ee6e3c8b8d7faa60de3216b7d23fe2ef956eda77b639fd4ffdd91bbcae7acf6229f9df759eb83909f4ec465d5473d74412a9357e024b5e51bfdd557d21abf03d7126cff0cdc8833f913582424f50ff55c86d3b23e191c0ba39f04f3b14f12d57e46bffbe950697c09f9f233c97a3ee33edf0db5e51ff3c7cbd0ea79f4cd38658d37ee2bc3cf597c302f7d0cd6bf8cf928d52049e70de68394691575de3b639f30bf898ccd3f46bea529acfb1fc0ed9092ee57eec32c6b7c1f471eaa20163fd4d7300badd9f709dc14b9f617e6edd0066fe7213f434998d613635e0ee56d650cff071f82d60b61de0c12a7761ffa21cc62a3f6f00eb829acfea1fe838bb5d537de17c117567df46f90d8583e500f6188adfacf9f8dbdd51fea31c42859fb1dfd1d520cca7c30726c62527f7953394d4d8e79175d6195bf05f769668cfe89651ad8fcc03c8b213963ccdf985297f57d89f990aae4351e8c7ca4260d169f4363eb4fc67c4b253b49e72de2957c91ebfb1cf55e764fad9f615f8a85f53ee433a5bcf407f32e976ac8dadf9827b974a3cd5fc42377d967e49b10cf2c79d07a66bcaf72cc56df8cf992f11979be582e26161e3870e4f4ebe92f9d22cf7cca677cce177cc9577ccd377cfb5f9da271c7f7fcc08fbc28eb89bff177fec1cffc73a9c3ebbcc1af7993dff05b7ec7ef79abfcdbe60f45ebe34a47ca193bbccb7bbccf73fec407e5ff2e7fe62f7cc847f02194db8ff984bf16b9ae69a113ae78562ca84da7e1965d9175e579cf9e988884060a1449631128d3299df19ccee9a2ac4bba1a4fa3eba27343b7a67347f7f4509e3ed2829e9637d237fa4e3fe8193a917ed23a6d94a7af6993ded05bd37947eff992b6a093f88ab6e9037d84646775ce2e6df31ded99efd7b44ff3b23ed141917da62f74480774549e1eabeff3059dd0579a528535c36f4d4d79d2925bea14ad8efa32d658c816171219f8e8bf3995c0871225492998f27b4ac7e319ffcf7bd13a9373b9904b7aa62dda93ab319fd0f9e7f7b57f015b8a9521 789c7596c96e1c390c86ef7e8a86790b064c57752d120673f01adbf19acd4e0673a05492f7bdbd0ee6dd87f553f121405239f8b32889cb4fcaefdf4d8ef67726efde2fdccf657e1a27f144ee26ef8687cbcb97bffff9ebdf85c5aa9be07f3da917ff585894d5499cd0b46a6ae7473e98837de3dd80f5357068926fc0ebe0d456be07bf8e5c556d5df8129cdac167f0c9c875dbcd6436323970ecbcc09e6723cfa69d488bf52370dd65117006fbbe2ebc53b811f8471be0dcfb50e1bc83919b69df16fb6370d58bc01f427c4dd30f01fe7003f6cab69f8c9d860cfb54b80a1df8012ccaf0976b70726d705847bc4d764db0f8f6476e2be782f9b3099e396fccc87fdbba1022f2b504ee5c8ae64f04f77a1eeac56b6f6cfedf141e02f2c101ec5cb4f358c0dee59070ff2e5894910f1e46ee2ab537ffbf836bdf453b1ff177ced72160dd83bd8fd1ec1fc1d14b44be18f5ea92ee9f229e2b70963a5a7ca723f753991933ead3377a1eee9315702f61407ee51aecc40f960fe457ab5947e497cec151d9fc6dc18334e69f2c174e83d5b30227c9763ec31f37953e223efe04aea42dfb91df31fb83d5bf2edc0ce8173e03771223f2cb9fc14ec4e2a30be3301d4cffd0bb93e0078b1ffe6bf5a703ea4be81fad6657ee839e5d92bee8e3059c4315ad5fa05f3f0d2921df04ff7d2562f5666facfe9a7e2e0ab7163fc15fafdd64f5e275633ddffae5aab00ca6d76be338b5fb18fefa4ee3313dd87e554fb278bf807bc9a66762633dcff2f701ecd41f8bffb6b0947add1bc7c6ce63f3c78768fed014acf92bfde2ded8ceb3f34374c9f482fed1e43709f63a1d474ea131fd8add9f4357f4bd6dace585bf847e9169ec93f987fa4b156665ff7de1ceeac395b1da5b3eee0abbb21ffdaadd5097fcae146e4b7ef70af7c9e635e69734c115fd1f1ac79c4c4ff05fda904c3f8279255d9008ff05fd2a2e4463ea8d875932bd987f3e56564f7902ab9aac3fe4191c7e329d1ac7a26fc63c56f13783ad6f15ee069c2fc7c6439f4d0f1fc1aabe68f3ebbef0acecff064eba6efd140ba764f15d18eb7363f5eec0aa363b4fd05fa31a8c69afb01fec7dc2bc52b5d7a57f7f806bcda7f587b14e2bcb3f436fa35a93e903f35dabdd58bf0817ce565f813e821ba6c68cfa051f87d2af64aceb76fef61b9b5e307fc6ea957e782a9c8b3dde43ed86c6fc1129dc16bda25e21abbf569fddc23a02611f0a3b63c67cd1eab7d62f8cf75dabd1db79120b87a237d4678cbee8f7d078a84afd302fa24e1beb377a29dc59fd18ef9daa438a3f43e1c1f44876bfd775c4c7cb85a3dd2fc85f0c4367f5a4b6702e7ac67b16e3e02d5fb45438da7d84f73726bdce78f98dcdffaf608daeec5f29fcb3df905f8da64ea65ff49b9ede67eb5fccbf54e98363f306ef696a53ce965fd433a53c2b8cfed4d59f8cfbf354d9f2857ec9556e6c9d50ef71355b7ef0f7536e739f6dbe6e1676d9ea837e57f7f503a35f721a3f30fa35e3dfc807732696df7c7430c71ee2c091074e9cf9984ff894cff89c2ff892aff89a0936376a71cb777ccf737ee0477ee2677ee1575ee2655ee11bd8acf21aaff307dee04dde2adf47dee61ddee53d5e85cd3e1ff027fecc5f74ed2b7fe3433ed29fbef30f9e72c5fbb0a979c60db7dc71cf8e3d31116f9150a048035b1d13653aa6133aa5333aa70bbaa42bbaa61bbaa53bba27d3de5c2d1ee8919ee8995ee895966899566895d6689d3e1062a70db5d8a42dfee5a38f6ab14d1bb0d9518b5ddad3dfeed3017da2cff485be2a7d538b43da81cd915a7ca71ffadb295554d38c1a6a953ab5e8e908364e2dbc306f894e64d121a08f7252cafa07d13159ff9fa8c5a99cfdea8f9ccbb15cc8096c2ee54aaee5466ee54eee652e0ff2284ff22c2f6a712197b0799525592e7eac2396c3f11658acc82b6c56654dd67ff3adc9eae27f7f2efc0f5211eed1 789c65d6c972e4360c00d0bbbfa26b709b4a61448914a54ae5e07ddfc76b2a079012bdefddde52f9f7b001b426ae34edc333218a0409b67f7c1f9dee6d8fbeff987b19d3f82a8ee2253d8fbe7793bbbb8f3ffffae3efb96fa61ef18f1f95df7e9bfbb63f1ec5d1cec37d3f059e65405554ae36ec037655b535b18fa6b685f5be66afb38d35b563efb32b5bd6d25fb3a98ab6656f8b6df415fb636a679c512fb24b577acb3e563befd9cbecfcd1f757ecd6d95ac6df614717259e36a7ae6d551a8ea777756d643d176c57bb46e6bfc4ce9f46c67f60fbdaabb7d86ddd6afcfb6099df21bbf7b66dd8c04e756a12bb9cda5b575bc9ef393bbfdef266a0617b575781fd53ecbb569e2fd8cdac9fded86d150ce78faec5b631b29f63b16f5b1e9faed8a1ea0d1bbc3ac9f3d088ad97fcc091ba3191c7bb14fb20eb03995fb4469fdf5047d3717c12fbd8cafe10bbcbeb91fcbf4cdd98c6483ff1f38dcdf329d81f629b74bc1576de9d56f6778ded6da5f1abea3c21f68aba96f5d2b2daab97d48de66f51ddaa17d4a49e5707c3e793f8fc3779f7f4fd9fea4ef321fdbded0d9f1790fede91ee8f9bba253241f69bd7d3863690ec77cf4e6d0a72fe265353919bf47fce1ca47ec26089e7f9534db5f403e7939a5aeb019ec5be28a5bf6393f795ec979d3ae4d182bc8fe383c94de67fca2e7393f3c1cf872a5451ea23b25d7051dec7f516724195727e92b83535e70ff7d83901fafc099b3f1cffc44e3e94bcbf70256e0a1d8ff3158b966ac9c72edbe626e36dccdcc9fbf8fcc77c3e8d8ccff98ba971a5d4079ff7ae6c0ac3f9003ebf9d6b7c29cfdf8b73937cf07cf2f1f63df703afbf0bcdac7edec45de8a5deb9deba98fbf97c03aa839ef776b08cff28ee62cfe70ff87ee9ba21fe75eabec94df67f73b0dc475c1f7dc84df697f3992fa726713d01df1f2924a3f7fdad3a683fbf3fc53e38c98ff4c7543989bf51c724e3cf0f96fc72be52978c937ab8533b27fbf7a0ae9dbcef66b08c3f8bef647ce2f5a6de5321f5375127f585b8290ba9d7b1ba2aa4fe2fd556e393ba2e787ef4a26e0aa90fa76e0b39cfb53a4a3ff583e5fbe659ddc9fbc1aafb42d67b206e0b313da94b1dbf1a2ce7ef505de9fc3ab5d3fe357553c8fdf83858c68feab690fb7d5f9d4b9cfb1fd4bd8e570ee6f34b419dd4b29f3d55321ed160be2fc0a86dc1e793eed48d188a99f5fe04752b86737550af0e96fbfd563d9b1fceacf167eaa4df7727e25068ffa97af6fdb5a72ed5adbad3fadc55f746cee7f16059efbb3ac9fc606bb0ece7b6381646f6e366e652ea61475d4a3faca8f5fb0f36c55d59ca780bea4afb1707f37d014b83657ecb6aa796faec7b5b72fee04dedf5fed37ac90750d633192cf9d1facb09136bbda4b6927abd56e736f5fe581a0212068cd8618f0961f6f75f317881977885d77883b77887f75917ff8b79c0477cc2677cc1314ef015dff0fd6b0c7ee027cee3022ee252d632aee02aaee1e2979875dcc04ddcc26d1d750777710ff7bfc41ce021fec4a361fec77882a778f625e61c0b34580e31155a7458ff8a418f0db680004010728bd0410f092ee072160357700d3770fb9f7607f7f0008ff034c43cc30b8c61f2a5bdc21bbcc3c710f309f3b0008bda96725b8615588535581f62366013b6609bdb4efedd853dd8870338849f43cc111cc3099cc2199c4301064aa8c082831afc10d3e47f6190f2ff0d1428520707942b8e2ee892ae6631744d37744b77744f0ff4484ff44c2f34a609bdd2db10f34e1ff449f3b4408bb444cbb442abb446ebb4419b39e69fdfe7fe05d985f873 789c6d96d94e1d471086ef790a44dd595179d6ee1e45b960c73660b0cd62a25c546f2c66e7b04679f7ccf9abcfb1a504234b1f5d5d7b55cffb778bc77b3b8befde2f3c4c64721e16c399dc2fbe8b8f5757af7ffef5c7df0b4bb559c46fbbd82cfdb6b0b43f590c8bbb37d7690a7c3c0255f89932edcc19c2725db8ad051c0a9b3a80570bdbda83370bbb3a435f5d38b438e7f5c2d9c01e67e5da1be8e317e5c68901c7c25e2cf80e5cd7a6873cbd1476bdc6f35db909e2c0ea7f33f2004ee0b6ad3ce2e34fe0be6a357ed6f8fab65279d9009bda75d04fdb85a5d8df05db5103eecb1ad8cd9868ca75d58a8f387f05b7ad910ebc0236eda0cc9760dba6e2dff69c5bc8237ff5509b0acc1e1c47d6f87f80733d28cbb4d8d4745d2fa8875c815de77c0dc6fd661859ebbd3ce5b6eabb807ad167b06d72d5e3fc062cbd1530ed8343ef9419fa3b339607f59387c23e6afe105fe77a67d51eead7890951fd6370b45544bef879ca637942a3f9ec958d04e506dc74b6d2fb2adf9ae495918fbeb3266a3ce887de98a4f7f944d9b611fed016d8da3ec03e558525a1ffe90dec4c6334fe6365eba3ce07faab1f66e7a2f2c1f406f525f52f58affa05fd6dc67c57ca59d9ba52affbc23969fd1fc1b5190cea47cbca73f9b3c229693c2db899c9cb85b26b92d6e716dcda18745e570be7a4fa8f945dabf23480bb393b703fb2f6ef4de14ef3c1ea9f7175d47c9c17eeca7dcc83b1fd50697d36956d8ab0cfe57cbcaff17c013b57a9bf827d60066713f60319b03853ea7550d8167b9867135c1db41fbf15b6ea3fd9396b7db11f4c74a1e8c37c9be45c393f9cb2adc673ec1b42fcb6713e693c983fdbdaa0f5a1afca2e167f31cfb61b59eb817d31a6c396fc9f82c7f26abcbca63cf449f725ea67dd608a7df4bb954e1a8d6f45d9a5a0f3a6fabccb41fbe952797049f3f9048e2e0edaff1d38bb5c58ede5993d2ee783d5f925ccafab3a57eb3e389ab3eef38fe0bab3b5d613fbc2354353f4635fb87698cde31e7870b37d2b603fe4d2df77ca52697d18fdedb21d530ac6fda192a6ec1fccd32012355e463d062fd16bffa23f8634b4b5ee17bc2752873e6b7f7c0037a1cb6a1ff32aadefb2ce17fc1309266b3e30df12bccfaa0ffb76b43663bc3792bc2ffee0fdf5adcf49fd4dcaa152fd8c79f62e147b8cfde47db019f524d42f3483d7fdca787f431752f11ffb23d8211b7d0f4559ea5ef721f66908b1cb5a2fecdb10a32bfd7ca29cacc6c7d8ff21475fec7f544e52ced17fb11ecf35bf784f623bb2eac7fb39365bcedabfd85f31f9a8fb93b12f52e753abf731afc9c4a1d6f7e14d79b4a7f380fd90eb1c4afed10f390c9d7eaf30f293a3a44eed639fe53c94ef15fe50581ab5773867f5c729fbaed2ef91c7c2bd329d17ceb5d667a21cbb4afb736bcefa3d640b1bfddee283c2b6d2fa9c2aa754fc7f289c4bfca49cabe2ef59e15abfc7d8146e4bbc9b857db97f5f3894f8570b67cddffee4ffff31b1b0df9fcc6438701cff4f9ce712a77cc6e77cc13fe632977cc5d77cc3b77c07bee7079ef0233ff1b3caf00bbff21b2ff30aaff21aaff3066ff2d628f1813ff2a722b3cd3bbccb9f798ff7f90b7fe56f7c304a1cf2111fab3ffc9d4fb8e29a1b6eb9e39e0d5b763c104f25548688843c058a9428d3299dd1395dd00f952832977445d77443b77447f7f440137aa4277aa6975f645ee98d96698556698dd6698336698b3ed047fa44dbb4536476e933edd13e7da1aff48d0ee8908ee898bed3095554ffcc2135d452473d19b2e4c625c5326e12f1127ecaec4f64ec5dc9722a67722e17f2432ee54aae67fea88c5a941bb9953bb9970799a8c4af326a511ee5499ee5455ea756fe4f0616df64595664f5e7dffe23b326ebb2219bbffe6de99fdf17fe05720fe9a6 789c559659535d390ec7dff329a8e82d35a53ebb7daaab1f8090859d4008616a1ee4e500093b17084ccd776fdfbf746f677292825f24dbb256fff16ee5647f67e5dd1f6f1e6632bb882bf15cee57dea5c7abab977fffe7afffbe795b0f2bf3bfa35b69defeebcddb83d94a5cd9bdb9ce73a0cb02d474fd142af01578e8b34ce06be3857c5d7968420bee8c538860a7ec9aa0fbaf81ddd0860e7c603c04376739572efaba7e15ec873ef4e05763a7faf462ec83071f194f21817f82c7729edab76f3c0601ef816508765e6b1c8d778d93d9ffd538dbfecd9221e7111c864a547fc7389a7dc7caae0aeacf7ac1b1c6fdcf8c6b65fa058ec55ebdff3765d798dc2f19c1a40fe0344818c11f8da3ddf71338177bf57e9f8d17feda542ef6a9fd95711bd57f27c69d9d773ae7b65ac44b26e33e6a7ce18fb65e3283fb7e1cd5fe0de54144e3ff041e9cc4019cc16ec9bade17567de46b3bba18d5bfb7e050f6833ec33f6d2cf7c7f942e0b4d097649c22fc258fe05c58e571ce5d55ce43be0beaa1ab7da5fa04fdae73c1fc710f1e16faf4601c6cfd0cec7c17d5ff7760ef46f3f70f63d3a79971d2fd05f9dc8dbed278cab5b1edc7c8af2eba2e409f11af2eb956d43f87cabe367fdc180f11e78bda9bbd57a6f773eeab729efaffdeb88bc84779351e2d1eab4b467e33f2b7af5d258837df1ad7a2e76f2a97fd341fbe180f76bfe72507f036b819bcd7fd71ffbe2dfba97f4f8c83f607463fe93bd7a89c5f96acf1c2fdfbc14de60fd443ef7c4aeaef2db0f79dd693ac196795b38047e745f3818cb3f64746fef6c18d26efc1c98fd6ef50cf7df641eb43509ffd3456ea3f1ae63c54beb5fdb697acfb5d18478d07c39f43e38268bf08ca0b3925e364f1da551eeb08ff12f27d68177246ff1e3a2f56bf62bc90abbef84efb9da03f0e61f409faace725ef83f637f4e7211739fa89ec1b87a4f58679e0aa51743d6d1927d3df33ce49f3e3d8784a5a4fdf95a54a9aafb0dfd5a561e07e1c8c45eb430e9517e709f2cf35c51eb55ff7438301a3fe5d375a7f945363ebc782783937f6da2f05f1717eb4fa61cc1717c66cf5867c7471ec34df79304e11fd981be385feba721948da6fc5d8a93f18f9ebf218cddede78d2f5acf64e8bfdb8325ec86b65b1fc63cc735faa3769fee13ebef847ef17d08f7d3b7aeb6f9877be1f17fd0af55ebc9f13f60fb0d7fb2257ffc03e1f2426bd2fe2edd398745e4aa55ce47a7fc4c34f52ebfc0ca8b7b1922e6a3e74caa1ca1acfdab83686ff8bb7bbacf9d12c59df13983fa30b83d98379367ab1fec387caa1b2fc785eb2d603f2732cd9a5f94cd9d8e2c5a8b73114b9ea1f19b7aacf7a9f28363ff8557929877f8b7716eb516f630e9dd50fe6ad3432e9fc0ac87729d34099d16f24845ee72963fe8436f659fb19f2ab48fbacfd1aef87f27ce993e603fa5f7071307df4fbe0a3337df4af124e6f72d47728d965fec67c8b551cac3eb17fec527960421ff517637259edbd342e050fc6fc4b5d4a59fdf9649c8db17f1a7235e9f99857c9e72a6bfe609e25c99dc931efcae3ae99347ff15e48d3fc831cf3bdac76aa4f93b19f10ff80fe97bbdc648dd799b1337b6e8cbdda2f988785ec3e82f75a963c4dea8f0de5a952a6b325ab3f607fce53a34ce74bc63c60bc17a67aea9409f3621ae6050e39faeb342f78edf7cf4bd67e128cc518f931d7b6f5b0b748c3a4f180bd13feccf960a61f130b078ee54b9c795afcff4287cff89c2ff807ffb4ef92aff8fa771dbee15bbee3fb227be0193f969f4f859ef9d76f3a2ffccaabbcc6ebfc9e37f8037f2cbfaff127fecc9baac35bbccd3bbc5bbe3ddee703fec2877c04fecac7fc0d3a27fc9d4fb9e29a1b6eb9e3befceb7860c79e47629deb24142852a24c139dd1395dd00ffa49977445d774039d5bbaa37b7aa0193dd2136fd033fda2177aa5555aa3757a0f9d0dfa401fe9137da64dda2a3adbb443bbb447fb45f380be40e7908ee82b1dd3373aa1efd8e7942aaaa9a1963ad2393e90235f1a0b0b89f08694929392d632c9999ccb85d69afc944bb9926bb991dba27327f7f2203379942779965fea437991575995355997f7b2211fe4a37c92cfb2295bb2fd4fbc644776654ff6e540bec8a11cc95739966f72f27b4c8bd6773995322b4aff69a5935e0671ff1f776895b752e050dc194a230a71991bfffbf3cddfa68f6847 789c7d96c96e5d370c86f7790a23dc050573461d1d145dc4b16367f094d149d1053579763c26b68bbe7b757ff21a5db4f5f5e68378240e3f293d7fb6b2bfbbb5f2ecf993eb1bb9398a2bf150ae569ea5dbb3b3fbdffff8edcf274f5bb7b2f89ffd4af7f497274ff76e56e2caf6f7f3bc00fa50819aa6092180fd23c7054b6b1c65009f2d39cce03de3240edf7f546e9b30627dcdb815bfe0908c3bb597f347d6f3e7258706ebdf8d7bc179bc6f3c88fa3f198f51edd9d8a93dad3fb2da7f329e04f1d1d23f6ff19e1acf11fef2576391027b679ca3c67fa2dc0d09c99563e33909be7f0d6edba4dfcb7b70dff7b1c77e1adfd096a0f9e894fb36e87923d8f58dee47fafdd4393d9f345e5fd3077fe548b98f59ebb56e5c22be97065cba59f3c1a8675bd319d5bf97e0b10b6142bd22d8f5bde8f97bca43c8eaff605c72c27e5fc052ed91cf10c0a97eaef9d7fdd33867d43bc882bb766802f2c747ca634cd83f10781c268d8fa097ce8d29c33fda054f6e2a9abf43b0af0e693d2ec0b3eb93c6837c75612801fed22a384fa9c05f86feba32fad462bd5f70df3829f04760dfb7838f9adf597974c6e89f7e1a93e69b5e287b5710bf28fbb11608eb9bca5393900f413cfd3cb6da8fa2e7cf6ed27cd0b171507bd6f3c47549f5ff000e6356bd08faa38f356158a71d65df14ddff7ec143e3a68c78f916dc0ed1f4ea94dd6cfa1e8d43d2fe46fd87c165657aa53cc5a47ad0efddb4d4ef8571491affa9f2dc587e0ec0931f8aeafb33d8fb46ed858c5bfb5e79f64d467cfcc3b835fe060ebe373e7d64d5cf99f26cf521f4df10bdd7fc30f4366437e87ce113653fe8f7fc065cbcd3fde9ca38ebba5c2e78ecbcb77e84dec7716eb47f18fd35bab168bf11f61fa7d96bfc7207f653ca3a8f8e95bd316d83e76aaffa85fe4771bdcdf323e52924fd1ef3774c6ed47e6232f66acf9bc641e79314709ea3ed0f3db9c64f197a20cc63d7fa62f9bc060fd53fd54b5696653da137571dd67ea207e5baaef308f9717eea6c9e434f75d8b98cfe66cc4b97279bf714957d31bda1bf5cf19dce33ba53965ee701b5c6c1cec37c9aba7a1d40bf0c7d4fc36cfa62f837390959f5f713ece762fe6f8153a80e80b1ee1bb17546fcbed63fea7d83f9e8c7508af64f528ed1f487fa79278de5f3c0b8d77a0bf4edbde4a2fa437ff8791e75be5151166ffad0f353f55ff5a0df9710f57c0ac6a9e8bc6b94e3a0fa27f83777a12baa7fc43b8f2164d503f2394fc1997fb7cab131bddc8083b436afee95eb75a8f72dce9f4bb4fde9d678b4f8a06fa9d7afd697d0cfd2a5b1a87e314fa4176ff547bdc5a5acfb13ce97a9eeaff1be03cf755deba9fbd53fbb1fd5be54ffb4fe6a5fb2337ff15e0a6df50ff912bc0fc2184c6fb2b3e4a4f711e641f0c99bbfd04798b3f59344e364fe20defa18f336bfd15fa1d6c7eabba15c3af30ff32a0eb1b7f982fac4312ee71dde3bd1c76cf7d7b5f2f23c6e94cbb21fde826b754c8fe8c718cad23fe837e628765f14e5d458fd30ef6229965fc27c4c4d1e347e413e531bb3f5f3aa72eaf5fd4038bf5637583fe1fd942407cb97ae8734a9fe04fa4f31f9acefc303e3657f205f292f9950afdc2efd13f897bbbaaef1e0fd9afbdc59bd307fb2cbd60fbc6eec8ca1875cbbcd18f1e739cf76bf22ff39e4c9de238827c7baaefe5d1b5b7c8cf75dae7f560fe8a9b4f5a7fb434fb5faadadaf199b1e04f3bbb8d2db7e78af95a9fe741df195b92cfdc7fd5db36df71fe37d56ab6ff567bc3f6af5bd7d8f7cd6ec2df5b36b6cfeeeddfcffefdf6c98583870fc6f1b4e9cb9f0011ffed3868ff8984ff894cff89cbff3055ff2155ff30ddffec3e607ffe43bbee7077ec1abfc92d7789d5ff1066ff2eb479b37fc96dff1166ff30eeff21ebfe70ffc913ff167fec2fbfc55df11dc70cb5d5dd75fcf038fec7862cf3331b44524142852a24c850ee8908ee8984ee894cee89cbec3e6822ee98aaee9866ee907fda43bbaa7077a41abf492d6681d36af688336e935bda1b7f48eb6689b766897f6e83d7da08ff409369fe90bedd357fa460db5d4514f038de468224fb3c01f59ccb550075b6d1f297220877224c77222a77226e7027fe4422ee54aaee5466ee587fc943bb997077921abf252d6343fb22eaf648377654336e5b5bc91b7f24eb6645b766457f6cce6bd7c58e6463eca27f92c5f645fbeca3769a4359baecee941eae34426f132070e14a4ceba18126af1d7af4ffe0608da782e 789c7dd55b5315391007f0773ec529fbcdda6a27c92493d4d63e00de5041f08a6eed436e23a080c001456bbffbe6fc3bb8eb56610d2f3fa6cf4ca7d3e9b97777b1bfbbbdb87b6fed6219978779910fe2f9e26eb93c3ebefef3af3fbeafdd516eb1fad361a1effcb676676fb9c88b9dd393ba024f0d34f8320e0e7670c87598e017704a7af0b015e7494c87ddbefb08ce310f01f17bddb5db8bd3d09f378ab392fbb4d1adbbafe01243fffdf3eed8bddb7df33e234e6988f04bb8c6414c9bddb6fb529c6e7c00cfcd097eb2724beec64fbb7df707715b9f78d93d777f8195af43869f75cfdd5be2a0ba2fc4d177af7787eefbb0f6b67bbbdb0d057ed09dba1f76e7eec7dd37f93c12b7f7cbfd7371d4ddd86f354e7540bfd09ed89bee6fe2560ff15977eefe0c4f2128055fc33e448566a437706c1ee1af700e49a11f6907ae212be9af199e6351b2bfb4b2d6496b793efa55db30ab19463feb29282def43bfe8149c467fd3208e5a5b18fd65541c35eac3a8b731d19961e5c8700ad6c879a9e2e48df41ff235390f46fae974e551c564a4de6f611db391faa23f47138b917c5fc3360e23de47389f638866447d58c3730ea3fc5ead6c5db256d657bbb335f07b38c668a59eafc4691233ea6d5bbe56f2fd08d7348a19fd60e76cadcc8b4f2b3b93bd937a9fc0634a0ef9f2a6b8dd977cf661dbee4b3ccebf736d7b719fb19f6ecac9a1fe8cf3e27cce4ef2c57c70398d4ee6c599b80c4ef243be6e2ec6497e61e5c9e661c2fa19eb9d4ab693c447719926d9df02d712c584fa4e73beb99fc5254cd2cf78be576916731297760070ff1ddcead37d0cfb1cbdac0fe7cfa75cbdac07e7cfcf79f6b29fc8270c651033ce6f306508a81f6f759b20f553dd6d40c098072d5915647f310f822f3ac8fbd1efa19414a41e9847616ef1f27eac37aa6283ac6f435ca728cf473f45535294fdc4bc8db64c51ea8df9185d5551ce13ea13a7e2bbd13fd1971025bf75717551be37a85f4cedf9529f2b714d51f2c53c8ea53d5ff60bfb196b8b97fdc23c8a737b9ee48ffe4baa9488f3c598f749d794247fcc8f34969aa49e9857c9b6f12df5c2bc4aaeba6e9cdfe4cb9c247fccfb14daf3643e613ea45455927c71fedb76cf49f2c3bc4bb5ea6eccfb362c5392fc8ec4b3e9c6f9caa6ce59ea8bf9906db559e601bebf799a4d967cd06fb97d7eb2bc1fdfb3f67a93a59ff0bd2a761e0b7ebfb7bcb9983872e2cc85ebbffffd5fcccc1ff8800ff9883fde1af3898ff9844ff9339fdd1a73ce17bce44bbee22fb7c67ce56bfec6ebbcc19b3fc7f07d7ec00ff9113fe62d7ec24ff9196ff30e3fe75ddee317fc52ce3dbfe637fc96f7f91dbfe781156b363cb265c7134b6f0562228a942853a14a337da08355141db2a3239987bc4f9fe8984ee8943ed3199dd3052de952a2e84abef1f495aee9db8f6b15b52e51b4419bf2dda607fd7af823ea113da62d7a424fe9d9cf6ba76d44ecd073dabdad3eb4d7225ed04b7a45af7f11f386ded23ebda3f7bf881948912643e3ad31961c4de42944fe4fccdfbfaffd0311f26a8c StatusSSHA toggled(bool) SSH_Agent setHidden(bool) keytype keyrate GenOutFile ConvertKeyLoc keyformat PublicKeyLoc SelFileG SelFileC SelFileE CurrentKeys ExecAddKey ExecRemoveKey TempAA TempA TempAAA