3 # CLI client for the FEX service for retrieving files
 
   7 # Author: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
 
   9 # Perl Artistic Licence
 
  12 use strict qw'vars subs';
 
  21 use Time::HiRes 'time';
 
  22 use constant k => 2**10;
 
  23 use constant M => 2**20;
 
  25 eval 'use Net::INET6Glue::INET_is_INET6';
 
  30 our ($fexhome,$idf,$tmpdir,$windoof,$useragent);
 
  32 our $bs = 2**16; # blocksize for tcp-reading and writing file
 
  33 our $version = 20150120;
 
  34 our $CTYPE = 'ISO-8859-1';
 
  35 our $fexsend = $ENV{FEXSEND} || 'fexsend';
 
  37 my %SSL = (SSL_version => 'TLSv1');
 
  40 # inquire default character set
 
  41 # cannot use "use I18N::Langinfo" because of no windows support!
 
  44   require I18N::Langinfo;
 
  45   I18N::Langinfo->import(qw'langinfo CODESET');
 
  46   $CTYPE = langinfo(CODESET());
 
  49 if ($Config{osname} =~ /^mswin/i) {
 
  50   $windoof = $Config{osname};
 
  51   $ENV{HOME} = $ENV{USERPROFILE};
 
  52   $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/fex';
 
  53   $tmpdir = $ENV{FEXTMP} || $ENV{TMP} || "$fexhome/tmp";
 
  55   $useragent = sprintf("fexget-$version (%s %s)",
 
  56                        $Config{osname},$Config{archname});
 
  57   $SSL{SSL_verify_mode} = 0;
 
  58   chdir $ENV{USERPROFILE}.'\Desktop';
 
  59   # open XX,'>XXXXXX';close XX;
 
  61   $0 =~ s:(.*)/:: and $ENV{PATH} .= ":$1";
 
  62   $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex';
 
  63   $tmpdir = $ENV{FEXTMP} || "$fexhome/tmp";
 
  65   $_ = `(lsb_release -d||uname -a)2>/dev/null`||'';
 
  68   $useragent = "fexget-$version ($_)";
 
  71 if (-f ($_ = '/etc/fex/config.pl')) {
 
  72   eval { require } or warn $@;
 
  76 usage: $0 [-v] [-m limit] [-s filename] [-o] [-k] [-X] [-P proxy:port] F*EX-URL(s)
 
  77    or: $0 [-v] -d F*EX-URL(s)
 
  78    or: $0 [-v] -f F*EX-URL(s) e-mail-address
 
  82 options: -v verbose mode
 
  84          -s save to filename (-s- means: write to STDOUT/pipe)
 
  85          -o overwrite existing file
 
  86          -k keep on server after download
 
  87          -X do not extract archive files or autoview file
 
  88          -d delete without download
 
  89          -f forward a file to another recipient
 
  90          -a get all files (implies -X)
 
  91          -l list files on server
 
  92          -i tag alternate server/account, see: $fexsend -h
 
  93          -P use Proxy for connection to the F*EX server
 
  94          -H show hints and examples
 
  95 argument: F*EX-URL may be file number (see: $0 -l)
 
  99 When you download a file with extension .jpg .gif .png or .tif an image viewer
 
 100 will be started. This can be xv or xdg-open.
 
 101 In $HOME/.fex/config.pl you can set your prefered autoview applications:
 
 104   '\.(gif|jpg|png|tiff?)' => 'my_prefered_image_viewer',
 
 105   '\.(avi|mp4|mov)'       => 'vlc -f',
 
 109 For HTTPS you can set the environment variables:
 
 110 SSLVERIFY=1                 # activate server identity verification
 
 111 SSLVERSION=TLSv1            # this is the default
 
 112 SSLCAPATH=/etc/ssl/certs    # path to trusted (root) certificates
 
 113 SSLCAFILE=/etc/ssl/cert.pem # file with trusted (root) certificates
 
 114 SSLCIPHERLIST=HIGH:!3DES    # see http://www.openssl.org/docs/apps/ciphers.html
 
 116 You can set these environment variables also in $HOME/.fex/config.pl, as well as
 
 117 the $opt_* variables, e.g.:
 
 119 $ENV{SSLVERSION} = 'TLSv1';
 
 124 if ($windoof and not @ARGV and not $ENV{PROMPT}) {
 
 125   # restart with cmd.exe to have mouse cut+paste
 
 126   my $cmd = "cmd /k \"$0\"";
 
 132 my $atype = '\.(tgz|tar|zip|7z)$';
 
 134 my $proxy_prefix = '';
 
 137 our ($opt_h,$opt_v,$opt_l,$opt_d,$opt_m,$opt_z,$opt_K,$opt_o,$opt_a);
 
 138 our ($opt_s,$opt_k,$opt_i,$opt_V,$opt_X,$opt_f,$opt_P,$opt_L,$opt_H);
 
 139 $opt_m = $opt_h = $opt_v = $opt_l = $opt_d = $opt_K = $opt_o = $opt_a = 0;
 
 140 $opt_V = $opt_X = $opt_f = $opt_L = $opt_H = 0;
 
 142 $opt_s = $opt_k = $opt_i = $opt_P = '';
 
 143 $_ = "$fexhome/config.pl"; require if -f;
 
 144 getopts('hvVHlLdkzoaXf+m:s:i:K:P:') or die $usage;
 
 145 $opt_k = '?KEEP' if $opt_k;
 
 147 if ($opt_m =~ /(\d+)/) {
 
 153 print "Version: $version\n" if $opt_V;
 
 154 die $usage                  if $opt_h;
 
 160 # set SSL/TLS options
 
 161 $SSL{SSL_verify_mode} = $ENV{SSLVERIFY} if defined($ENV{SSLVERIFY});
 
 171   $SSL{$opt} = $ENV{$env} if defined($ENV{$env});
 
 174 if ($SSL{SSL_verify_mode}) {
 
 176   unless ($SSL{SSL_ca_path} or $SSL{SSL_ca_file}) {
 
 177     die "$0: \$SSLVERIFYMODE, but not valid \$SSLCAPATH or \$SSLCAFILE\n";
 
 179 } elsif (defined($SSL{SSL_verify_mode})) {
 
 180   # user has set SSLVERIFY=0 !
 
 183   $SSL{SSL_verify_mode} = 1 if $SSL{SSL_ca_path} or $SSL{SSL_ca_file};
 
 188   return if $SSL{SSL_ca_file} or $SSL{SSL_ca_path};
 
 189   foreach (qw(/etc/ssl/certs/ca-certificates.crt)) {
 
 191       $SSL{SSL_ca_file} = $_;
 
 195   foreach (qw(/etc/ssl/certs /etc/pki/tls/certs)) {
 
 197       $SSL{SSL_ca_path} = $_;
 
 203 my $ffl = "$tmpdir/fexget";             # F*EX files list (cache)
 
 219   my $cmd = "$fexsend -Z";
 
 220   $cmd .= " -i $opt_i" if $opt_i;
 
 221   warn "$cmd\n" if $opt_v;
 
 223   die "$0: cannot run $cmd : $!\n";
 
 232   my $cmd = "$fexsend -L";
 
 233   $cmd .= " -i $opt_i" if $opt_i;
 
 234   warn "$cmd\n" if $opt_v;
 
 236   die "$0: cannot run $cmd : $!\n";
 
 240   if ($opt_P =~ /^([\w.-]+:\d+)(:(\d+))?/) {
 
 242     $chunksize = $3 || 0;
 
 244     die "$0: proxy must be: SERVER:PORT\n";
 
 253   if (open $ffl,$ffl) {
 
 255       push @ARGV,$1 if /^\s+(\d+)/;
 
 264         print "download-URL: ";
 
 265         chomp($url = <STDIN>);
 
 266         if ($url =~ /^http/) {
 
 277 my ($file,%files,$download,$server,$port,$fop);
 
 280   unless ($ENV{FEXID} or -f $ENV{HOME}.'/.fex/id') {
 
 281     die "$0: no local FEXID\n";
 
 284   if ($opt_f =~ /^\d+$|^https?:/) {
 
 285     die "$0: $opt_f is not an e-mail address\n";
 
 289 URL: foreach my $url (@ARGV) {
 
 291   # do not overrun server
 
 294   if ($url !~ /^http/) {
 
 296       open $ffl,$ffl or die "$0: no $ffl, use first: $0 -l\n";
 
 299         if (/^from (.+) :$/) {
 
 301         } elsif (/^\s*(\d+)\)\s+\d+ MB.* (http\S+)/) {
 
 302           push @{$files{all}},$2;
 
 303           push @{$files{$from}},$2;
 
 309     if ($url =~ /^(\d+)$/) {
 
 310       $url = ${files{all}}[$1-1] or die "$0: unknown file number\n";
 
 314   if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/.*fop/\S+)}) {
 
 316     $port   = $4 || ($1?443:80);
 
 319     die "$0: unknown F*EX URL $url\n";
 
 323     if    ($port == 80)   { $proxy_prefix = "http://$server" }
 
 324     elsif ($port == 443)  { $proxy_prefix = "" }
 
 325     else                  { $proxy_prefix = "http://$server:$port" }
 
 328   serverconnect($server,$port);
 
 339       ($file) = grep { $_ = $1 if /^X-File:\s+(.+)/ } @r;
 
 340       $file = $url unless $file;
 
 342       printf "%s deleted\n",urldecode($file);
 
 345       die "$0: server response: $_";
 
 356       print "$file kept\n";
 
 359       die "$0: server response: $_";
 
 364   $download = download($server,$port,$fop);
 
 365   exit if $opt_s eq '-';
 
 366   unlink $download unless -s $download;
 
 367   exit 2 unless -f $download;
 
 374   if (not $opt_X and $download =~ /\.gpg$/) {
 
 376       print "decrypt \"$download\"? ";
 
 379         print "keeping \"$download\"\n";
 
 383     if (system('gpg',$download) == 0) {
 
 385       $download =~ s/\.gpg$//;
 
 391     foreach my $a (keys %autoview) {
 
 392       if ($download =~ /$a$/i and $autoview{$a}) {
 
 393         printf "run \"%s %s\" [Yn] ? ",$autoview{$a},basename($download);
 
 395         system sprintf("%s %s",$autoview{$a},quote($download)) if /^y|^$/i;
 
 400     if ($ENV{DISPLAY} and $download =~ /\.(gif|jpg|png|tiff?)$/i) {
 
 401       # see also mimeopen and xdg-mime
 
 402       if (my $xv = $xv || pathsearch('xv') || pathsearch('xdg-open')) {
 
 403         printf "run \"%s %s\" [Yn] ? ",basename($xv),basename($download);
 
 405         system $xv,$download if /^y|^$/i;
 
 410     if ($download =~ /$atype/) {
 
 411       if    ($download =~ /\.(tgz|tar.gz)$/)  { extract('tar tvzf','tar xvzf') }
 
 412       elsif ($download =~ /\.tar$/)           { extract('tar tvf','tar xvf') } 
 
 413       elsif ($download =~ /\.zip$/i)          { extract('unzip -l','unzip') } 
 
 414       elsif ($download =~ /\.7z$/i)           { extract('7z l','7z x') }
 
 415       else { die "$0: unknown archive \"$download\"\n" }
 
 419         die "$0: keeping \"$download\"\n";
 
 435   if (-t and not $windoof) {
 
 436     print "Files in archive:\n";
 
 437     system(split(' ',$l),$download);
 
 441       $xd = inquire("extract to directory (Ctrl-C to keep archive): ",$d);
 
 442       last if $xd =~ s:^(\./*)*!?$:./:;
 
 444         print "keeping $download\n";
 
 449           print "directory $xd does already exist, add \"!\" to overwrite\n";
 
 453           print "cannot mkdir $xd - $!\n";
 
 458         print "cannot chdir $xd - $!\n";
 
 464   print "extracting to $xd :\n";
 
 465   system(split(' ',$x),$download);
 
 474   if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) {
 
 476     $port   = $4 || ($1?443:80);
 
 479     die "$0: unknown F*EX URL $url\n";
 
 482   sendheader("$server:$port","GET $del HTTP/1.1","User-Agent: $useragent");
 
 485     last if /^\n/; # ignore HTML output
 
 486     warn "<-- $_" if $opt_v;
 
 489   die "$0: no response from fex server $server\n" unless @r;
 
 497   my ($uri,$dkey,$list,$cmd,$n);
 
 500   if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) {
 
 502     $port   = $4 || ($1?443:80);
 
 505     die "$0: unknown F*EX URL $url\n";
 
 510     "GET $uri?COPY HTTP/1.1",
 
 511     "User-Agent: $useragent",
 
 515   die "$0: no reply from fex server $server\n" unless $_;
 
 516   warn "<-- $_" if $opt_v;
 
 518   unless (/^HTTP.*200/) {
 
 525     last if /^\n/; # ignore HTML output
 
 526     $dkey = $1 if /^Location:.*\/(\w+)\/.+/;
 
 527     warn "<-- $_" if $opt_v;
 
 530   $cmd = 'fexsend -l >/dev/null 2>&1';
 
 531   print "$cmd\n" if $opt_v;
 
 532   system 'fexsend -l >/dev/null 2>&1';
 
 533   $list = $ENV{HOME}.'/.fex/tmp/fexlist';
 
 534   open $list,$list or die "$0: cannot open $list - $!\n";
 
 536     if (/^\s+(\d+)\) (\w+)/ and $2 eq $dkey) {
 
 538       $cmd = "fexsend -b $n $opt_f";
 
 539       print "$cmd\n" if $opt_v;
 
 547     $cmd = "fexsend -d $n >/dev/null 2>&1";
 
 548     print "$cmd\n" if $opt_v;
 
 551     warn "$0: forwarding failed\n";
 
 562   if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) {
 
 564     $port   = $4 || ($1?443:80);
 
 565     $keep    = "$5?KEEP=$opt_K";
 
 567     die "$0: unknown F*EX URL $url\n";
 
 570   push @hh,"GET $keep HTTP/1.1",
 
 571            "Host: $server:$port",
 
 572            "User-Agent: $useragent",
 
 576     warn $_,"\n" if $opt_v;
 
 584   die "$0: no response from fex server $server\n" unless @r;
 
 585   grep { warn "\t$_" } @r if $opt_v;
 
 591   my ($server,$port,$fop,$nocheck) = @_;
 
 592   my ($file,$download,$ssl,$pipe,$filesize,$checkstorage);
 
 594   my ($t0,$t1,$t2,$tt,$tm,$ts,$kBs,$b,$bt,$tb,$B,$buf);
 
 604       $pipe = $download = $opt_s;
 
 605     } elsif (-p $opt_s or -c $opt_s) {
 
 608       $download = $file.'.tmp';
 
 609       $seek = -s $download || 0;
 
 612     # ask server for real file name
 
 613     serverconnect($server, $port);
 
 614     sendheader("$server:$port","HEAD $proxy_prefix$fop HTTP/1.1","User-Agent: $useragent");
 
 615     my $reply = $_ = <$SH>;
 
 616     unless (defined $_ and /\w/) {
 
 617       die "$0: no response from server\n";
 
 619     warn "<-- $_" if $opt_v;
 
 620     unless (/^HTTP\/[\d.]+ 200/) {
 
 622       die "$0: server response: $_";
 
 626       warn "<-- $_" if $opt_v;
 
 628       if (/^Content-Disposition: attachment; filename="(.+)"/i) {
 
 629         $file = locale(decode_utf8($1));
 
 637     $download = $file.'.tmp';
 
 638     $seek = -s $download || 0;
 
 641   push @hh,"GET $proxy_prefix$fop$opt_k HTTP/1.1",
 
 642            "User-Agent: $useragent",
 
 644   push @hh,"Range: bytes=$seek-" if $seek;
 
 646   # HTTPS needs a new connection for actually downloading the file
 
 647   serverconnect($server,$port) if $opt_P and $port == 443;
 
 648   sendheader("$server:$port",@hh);
 
 650   die "$0: no response from fex server $server\n" unless $_;
 
 653   if (/^HTTP\/[\d.]+ 2/) {
 
 654     warn "<-- $_" if $opt_v;
 
 657       warn "<-- $_" if $opt_v;
 
 659       if (/^Content-length:\s*(\d+)/i) {
 
 661       } elsif (/^X-Size: (\d+)/i) {
 
 666     s/HTTP\/[\d.]+ \d+ //;
 
 667     die "$0: bad server reply: $_";
 
 673     if ($opt_s and $opt_s eq $download) {
 
 674       open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n";
 
 675       $checkstorage = $filesize unless $nocheck;
 
 677       if (-e $file and not $opt_o) {
 
 678         die "$0: destination file \"$file\" does already exist\n";
 
 681         open X,'>>',$download or die "$0: cannot write to \"$download\" - $!\n";
 
 683         open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n";
 
 684         $checkstorage = $filesize unless $nocheck;
 
 687     if ($checkstorage and not $nocheck) {
 
 690       print STDERR "checking storage...\r";
 
 692       while (-s $download < $checkstorage) {
 
 693         syswrite X,$buf or do {
 
 695           die "\n$0: cannot write $download - $!\n";
 
 698         print STDERR "checking storage... ".$n." MB\r";
 
 702         die "\n$0: cannot write $download - $!\n";
 
 704       print STDERR "checking storage... ".$n." MB ok!\n";
 
 707         open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n";
 
 709         # retry after timeout
 
 710         return(download($server,$port,$fop,'nocheck'))
 
 715   $t0 = $t1 = $t2 = int(time);
 
 717   printf STDERR "resuming at byte %s\n",$seek if $seek;
 
 718   print $rcamel[0] if ${'opt_+'};
 
 719   while ($B < $length and $b = read $SH,$buf,$bs) {
 
 725     if (${'opt_+'} and int($t2*10)>$tc) {
 
 726       print $rcamel[$tc%2+1];
 
 729     if (int($t2) > $t1) {
 
 730       $kBs = int($bt/k/($t2-$t1));
 
 731       $kBs = int($tb/k/($t2-$t0)) if $kBs < 10;
 
 734       # smaller block size is better on slow links
 
 735       $bs = 4096 if $bs>4096 and $tb/($t2-$t0)<65536;
 
 737         printf STDERR "%s: %d kB (%d%%) %d kB/s \r",
 
 740                       int(($tb+$seek)/($length+$seek)*100),
 
 743         printf STDERR "%s: %d MB (%d%%) %d kB/s        \r",
 
 746                       int(($tb+$seek)/($length+$seek)*100),
 
 751       if ($t2 == $t0 and $B > $opt_m*k) {
 
 752         print "\nsleeping...\r" if $opt_v;
 
 755         while ($t2 > $t0 and $tb/k/($t2-$t0) > $opt_m) {
 
 756           print "\nsleeping...\r" if $opt_v;
 
 766   print $rcamel[2] if ${'opt_+'};
 
 771   $kBs = int($tb/k/($tt||1));
 
 773     printf STDERR "$file: %d MB, last %d MB in %d s (%d kB/s)      \n",
 
 774                   int(($tb+$seek)/M),int($tb/M),$tt,$kBs;
 
 776     printf STDERR "$file: %d MB in %d s (%d kB/s)      \n",
 
 780   if ($tb != $length) {
 
 785       die "$0: $server annouced $length bytes, but only $tb bytes has been read\n";
 
 789   unless ($pipe or -p $download or -c $download) {
 
 790     my @s = stat $file if -e $file;
 
 791     rename $download,$file
 
 792       or die "$0: cannot rename \"$download\" to \"$file\" - $!\n";
 
 793     chmod $s[2],$file if @s;
 
 796   return sprintf("%s/%s",getcwd(),$file);
 
 801   my $cmd = "$fexsend -L";
 
 802   $cmd .= " -i $opt_i" if $opt_i;
 
 807   open $cmd,"$cmd|" or die "$0: cannot run $cmd : $!\n";
 
 808   open $ffl,'>',$ffl or die "$0: cannot open $ffl : $!\n";
 
 811     if (/\d MB .*http/) {
 
 813       printf {$ffl} "%4d) %s",$n,$_;
 
 815       printf        "%4d) %s",$n,$_;
 
 828     if ($CTYPE =~ /UTF-?8/i) {
 
 830     } elsif (grep { $CTYPE =~ /^$_$/i } Encode->encodings()) {
 
 831       return encode($CTYPE,$string);
 
 833       return encode('ISO-8859-1',$string);
 
 844   foreach my $dir (split(':',$ENV{PATH})) {
 
 845     return "$dir/$prg" if -x "$dir/$prg";
 
 852   s/([^\w¡-ÿ_%\/=~:.,-])/\\$1/g;
 
 866     if (defined $default) {
 
 868         chomp($tty = `tty 2>/dev/null`);
 
 869         eval { local $^W; require "sys/ioctl.ph"; };
 
 872       if (defined(&TIOCSTI) and $tty and open($tty,'>',$tty)) {
 
 874         foreach my $a (split("",$default)) { ioctl($tty,&TIOCSTI,$a) } 
 
 875         chomp($_ = <STDIN>||'');
 
 877         $prompt =~ s/([\?:=]\s*)/ [$default]$1/ or $prompt .= " [$default]";
 
 879         chomp($_ = <STDIN>||'');
 
 880         $_ = $default unless length;
 
 884       chomp($_ = <STDIN>||'');
 
 892 ### common functions ###
 
 896   my @d = localtime((stat shift)[9]);
 
 897   return sprintf('%d%02d%02d',$d[5]+1900,$d[4]+1,$d[3]);
 
 903   s/\%([a-f\d]{2})/chr(hex($1))/ige;
 
 909   # set SSL/TLS options
 
 910   $SSL{SSL_verify_mode} = $ENV{SSLVERIFY} if defined($ENV{SSLVERIFY});
 
 920     $SSL{$opt} = $ENV{$env} if defined($ENV{$env});
 
 923   if ($SSL{SSL_verify_mode}) {
 
 925     unless ($SSL{SSL_ca_path} or $SSL{SSL_ca_file}) {
 
 926       die "$0: \$SSLVERIFYMODE, but not valid \$SSLCAPATH or \$SSLCAFILE\n";
 
 928   } elsif (defined($SSL{SSL_verify_mode})) {
 
 929     # user has set SSLVERIFY=0 !
 
 932     $SSL{SSL_verify_mode} = 1 if $SSL{SSL_ca_path} or $SSL{SSL_ca_file};
 
 938   return if $SSL{SSL_ca_file} or $SSL{SSL_ca_path};
 
 939   foreach (qw(/etc/ssl/certs/ca-certificates.crt)) {
 
 941       $SSL{SSL_ca_file} = $_;
 
 945   foreach (qw(/etc/ssl/certs /etc/pki/tls/certs)) {
 
 947       $SSL{SSL_ca_path} = $_;
 
 955   my ($server,$port) = @_;
 
 956   my $connect = "CONNECT $server:$port HTTP/1.1";
 
 959   if ($opt_v and $port == 443 and %SSL) {
 
 960     foreach my $v (keys %SSL) {
 
 961       printf "%s => %s\n",$v,$SSL{$v};
 
 966     tcpconnect(split(':',$proxy));
 
 968       printf "--> %s\n",$connect if $opt_v;
 
 969       nvtsend($connect,"");
 
 972       printf "<-- $_"if $opt_v;
 
 973       unless (/^HTTP.1.. 200/) {
 
 974         die "$0: proxy error : $_";
 
 976       eval "use IO::Socket::SSL";
 
 977       die "$0: cannot load IO::Socket::SSL\n" if $@;
 
 978       $SH = IO::Socket::SSL->start_SSL($SH,%SSL);
 
 981     tcpconnect($server,$port);
 
 983 #  if ($port == 443 and $opt_v) {
 
 984 #    printf "%s\n",$SH->get_cipher();
 
 989 # set up tcp/ip connection
 
 991   my ($server,$port) = @_;
 
 999     # eval "use IO::Socket::SSL qw(debug3)";
 
1000     eval "use IO::Socket::SSL";
 
1001     die "$0: cannot load IO::Socket::SSL\n" if $@;
 
1002     $SH = IO::Socket::SSL->new(
 
1003       PeerAddr => $server,
 
1009     $SH = IO::Socket::INET->new(
 
1010       PeerAddr => $server,
 
1019     die "$0: cannot connect $server:$port - $@\n";
 
1022   print "TCPCONNECT to $server:$port\n" if $opt_v;
 
1031   push @head,"Host: $sp";
 
1033   foreach $head (@head) {
 
1034     print "--> $head\n" if $opt_v;
 
1035     print {$SH} $head,"\r\n";
 
1037   print "-->\n" if $opt_v;
 
1043   local $SIG{PIPE} = sub { $sigpipe = "@_" };
 
1047   die "$0: internal error: no active network handle\n" unless $SH;
 
1048   die "$0: remote host has closed the link\n" unless $SH->connected;
 
1050   foreach my $line (@_) {
 
1051     print {$SH} $line,"\r\n";
 
1062 # from MIME::Base64::Perl
 
1069   $res = join '',map(pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs));
 
1070   $res =~ tr|` -_|AA-Za-z0-9+/|;
 
1071   $padding = (3-length($_[0])%3)%3;
 
1072   $res =~ s/.{$padding}$/'=' x $padding/e if $padding;