#!/usr/bin/env perl
#########################################################################
use strict;
use Win32::Registry;

#usage:
#  perl -w far-fpt-password.pl [crypted-key or settings-file]
#
#  registry data used by default
#

#########################################################################
sub DecryptPassword($)
{
   my ($Src) = @_; my ($Dst) = ("");
   if ( length($Src) > 2 )
   {
      my ($b1, $b2, $b3) = (
        ord(substr($Src,0,1)),ord(substr($Src,1,1)),ord(substr($Src,2,1))
      );
      if ( $b1 && $b2 && $b3 )
      {
         my ($i, $XorMask) = (0, $b1 ^ $b2 | 80);
         for ( my $n = 2; $n < length($Src); ++$n )
         {
            my $v = ord(substr($Src,$n,1)) ^ $XorMask;
            last if ( !$v || $v == $XorMask );
            $Dst .= chr($v);
         }  
      }
   }
   return $Dst;
}

#########################################################################
sub BinaryPassword($)
{
   my ($Src) = @_; my ($Dst) = ("");
   $Src = substr($Src, 4) if ( $Src =~ m!^hex:! );
   while($Src) {$Dst .= chr(hex(substr($Src,0,2))); $Src=substr($Src,2);}
   return $Dst;
}

#########################################################################
my ($item, $ftp, $h, $u, $p);

if ( scalar(@ARGV) > 0 ) # decrypt command line parameters
{
   for $item (@ARGV)
   {
      print "$item:\n";
      ($h, $u, $p) = (undef, undef, undef);

      if ( -f $item )
      {
         open(SRC, $item) || die "Can't open file: $item -- $!";
         while( my $s = <SRC> )
         {
            $h = $1 if ( $s =~ m!^Url=(.+)\s*$! );
            $u = $1 if ( $s =~ m!^User=(.+)\s*$! );
            $p = $1 if ( $s =~ m!^Password=(.+)\s*$! );
         }
         close(SRC);
      }
      else { $p = $item; }

      $p = DecryptPassword(BinaryPassword($p));
      print "  ";
      print "host=$h " if ( $h );
      print "user=$u " if ( $u );
      print "passw=$p\n";
   }   
}
else # show registry settings
{
   for my $far qw(Far Far2)
   {
      for ( $item = 0; $item < 100; ++$item )
      {
         my $key = "Software\\$far\\Plugins\\FTP\\Hosts";
         $::HKEY_CURRENT_USER->Open("$key\\Item$item", $ftp) || next;
         print $far, "($item): ";

         ($h, $u, $p) = (undef, undef, undef);
         $ftp->QueryValueEx("Hostname", ::REG_SZ,     $h);
         $ftp->QueryValueEx("User",     ::REG_SZ,     $u);
         $ftp->QueryValueEx("Password", ::REG_BINARY, $p);

         $p = DecryptPassword($p);
         print sprintf("host=%s user=%s passw=%s\n", $h, $u, $p);
 
         $ftp->Close();
      }
   }
}

#########################################################################
1;
