#!/usr/bin/perl -w # $Id: 350filters.t,v 1.6 2003/04/30 23:10:57 rbrown Exp $ use strict; use Test; use POSIX qw(dup2); use IO::Handle; use FileHandle; BEGIN { `which uudecode` && `which compress` && `which gzip` or do { print "1..0 # external filter missing for test.\n"; exit; }; plan tests => 13; } # Skip all tests if required executable compress doesn't exist (true # for patent-free Debian systems, for example). unless (on_path ("compress")) { for (my $i = 0; $i < 13; ++$i) { skip ("missing 'compress' command", 1); } exit 0; } use Net::FTPServer::InMem::Server; pipe INFD0, OUTFD0 or die "pipe: $!"; pipe INFD1, OUTFD1 or die "pipe: $!"; my $pid = fork (); die unless defined $pid; unless ($pid) { # Child process (the server). POSIX::dup2 (fileno INFD0, 0); POSIX::dup2 (fileno OUTFD1, 1); close INFD0; close OUTFD0; close INFD1; close OUTFD1; my $ftps = Net::FTPServer::InMem::Server->run (['--test', '-d', '-C', '/dev/null', '-o', 'limit memory=-1', '-o', 'limit nr processes=-1', '-o', 'limit nr files=-1']); exit; } # Parent process (the test script). close INFD0; close OUTFD1; OUTFD0->autoflush (1); $_ = ; print OUTFD0 "USER rich\r\n"; $_ = ; ok (/^331/); print OUTFD0 "PASS 123456\r\n"; $_ = ; ok (/^230 Welcome rich\./); # Use binary mode. print OUTFD0 "TYPE I\r\n"; $_ = ; ok (/^200/); # Enter passive mode and get a port number. print OUTFD0 "PASV\r\n"; $_ = ; ok (/^227 Entering Passive Mode \(127,0,0,1,(.*),(.*)\)/); my $port = $1 * 256 + $2; # Generate a file containing some textual data. my $tmpfile = ".350filters.t.$$"; open TMP, ">$tmpfile" or die "$tmpfile: $!"; print TMP < $tmpfile.b") == 0 or die "compress: $!"; ok (compare_files ($tmpfile, "$tmpfile.b")); ok (download_file ("$tmpfile.gz", "$tmpfile.a")); system ("gzip -cd $tmpfile.a > $tmpfile.b") == 0 or die "gzip: $!"; ok (compare_files ($tmpfile, "$tmpfile.b")); ok (download_file ("$tmpfile.gz.uue", "$tmpfile.a")); system ("uudecode -o $tmpfile.b < $tmpfile.a") == 0 or die "uudecode: $!"; system ("gzip -cd $tmpfile.b > $tmpfile.a") == 0 or die "gzip: $!"; ok (compare_files ($tmpfile, "$tmpfile.a")); unlink $tmpfile; unlink "$tmpfile.a"; unlink "$tmpfile.b"; print OUTFD0 "QUIT\r\n"; $_ = ; exit; # This function uploads a file to the server. sub upload_file { my $filename = shift; # Snarf the local file. open UPLOAD, "<$filename" or die "$filename: $!"; my $buffer; { local $/ = undef; $buffer = ; } close UPLOAD; # Send the STOR command. print OUTFD0 "STOR $filename\r\n"; $_ = ; return 0 unless /^150/; # Connect to the passive mode port. my $sock = new IO::Socket::INET (PeerAddr => "127.0.0.1:$port", Proto => "tcp") or die "socket: $!"; # Write to socket. $sock->print ($buffer); $sock->close; # Check return code. $_ = ; return /^226/; } # Download a file from the server into a local file. sub download_file { my $remote_filename = shift; my $local_filename = shift; # Send the RETR command. print OUTFD0 "RETR $remote_filename\r\n"; $_ = ; return 0 unless /^150/; # Connect to the passive mode port. my $sock = new IO::Socket::INET (PeerAddr => "127.0.0.1:$port", Proto => "tcp") or die "socket: $!"; # Read all the data into a buffer. my $buffer = ""; my $posn = 0; my $r; while (($r = $sock->read ($buffer, 65536, $posn)) > 0) { $posn += $r; } $sock->close; # Check return code. $_ = ; return 0 unless /^226/; # Save to load file. open DOWNLOAD, ">$local_filename" or die "$local_filename: $!"; print DOWNLOAD $buffer; close DOWNLOAD; # OK! return 1; } # Compare two local files. sub compare_files { my $filename1 = shift; my $filename2 = shift; system ("cmp $filename1 $filename2") == 0 or return 0; return 1; } sub on_path { foreach (split /:/, $ENV{PATH}) { return 1 if -x "$_/$_[0]"; } 0; }