File Coverage

blib/lib/AnyEvent/FTP/Server/Role/TransferPrep.pm
Criterion Covered Total %
statement 61 75 81.3
branch 5 8 62.5
condition n/a
subroutine 17 17 100.0
pod 1 7 14.2
total 84 107 78.5


line stmt bran cond sub pod time code
1             package AnyEvent::FTP::Server::Role::TransferPrep;
2              
3 23     23   239812 use strict;
  23         86  
  23         769  
4 23     23   125 use warnings;
  23         82  
  23         603  
5 23     23   456 use 5.010;
  23         84  
6 23     23   597 use Moo::Role;
  23         17618  
  23         160  
7 23     23   12112 use AnyEvent;
  23         23249  
  23         987  
8 23     23   2887 use AnyEvent::Socket qw( tcp_server tcp_connect );
  23         107405  
  23         1937  
9 23     23   3210 use AnyEvent::Handle;
  23         32898  
  23         22370  
10              
11             # ABSTRACT: Interface for PASV, PORT and REST commands
12             our $VERSION = '0.18'; # VERSION
13              
14              
15             has data => (
16             is => 'rw',
17             );
18              
19              
20             has restart_offset => (
21             is => 'rw',
22             );
23              
24              
25             sub clear_data
26             {
27 70     70 1 258 my($self) = @_;
28 70         330 $self->data(undef);
29 70         375 $self->restart_offset(undef);
30             }
31              
32              
33 6     6 0 165 sub help_pasv { 'PASV (returns address/port)' }
34              
35             sub cmd_pasv
36             {
37 43     43 0 137 my($self, $con, $req) = @_;
38              
39 43         101 my $count = 0;
40              
41             tcp_server undef, undef, sub {
42 41     41   4489 my($fh, $host, $port) = @_;
43 41 50       215 return close $fh if ++$count > 1;
44              
45 41         85 my $handle;
46             $handle = AnyEvent::Handle->new(
47             fh => $fh,
48             on_error => sub {
49 0         0 $_[0]->destroy;
50 0         0 undef $handle;
51             },
52             on_eof => sub {
53 0         0 $handle->destroy;
54 0         0 undef $handle;
55             },
56 41         530 autocork => 1,
57             );
58              
59 41         4022 $self->data($handle);
60             # TODO this should be with the 227 message below.
61             # demoting this to a TODO (was a F-I-X-M-E)
62             # since I can't remember why I thought it needed
63             # doing. plicease 12-05-2014
64 41         219 $self->done;
65              
66             }, sub {
67 43     43   11996 my($fh, $host, $port) = @_;
68 43         556 my $ip_and_port = join(',', split(/\./, $con->ip), $port >> 8, $port & 0xff);
69              
70 43         129 my $w;
71             $w = AnyEvent->timer(after => 0, cb => sub {
72 43         2638 $con->send_response(227 => "Entering Passive Mode ($ip_and_port)");
73 43         616 undef $w;
74 43         669 });
75              
76 43         721 };
77              
78 43         2715 return;
79             }
80              
81              
82 6     6 0 26 sub help_port { 'PORT h1,h2,h3,h4,p1,p2' }
83              
84             sub cmd_port
85             {
86 29     29 0 101 my($self, $con, $req) = @_;
87              
88 29 50       91 if($req->args =~ /(\d+,\d+,\d+,\d+),(\d+),(\d+)/)
89             {
90 29         387 my $ip = join '.', split /,/, $1;
91 29         195 my $port = $2*256 + $3;
92              
93             tcp_connect $ip, $port, sub {
94 29     29   3163 my($fh) = @_;
95 29 50       218 unless($fh)
96             {
97 0         0 $con->send_response(500 => "Illegal PORT command");
98 0         0 $self->done;
99 0         0 return;
100             }
101              
102 29         72 my $handle;
103             $handle = AnyEvent::Handle->new(
104             fh => $fh,
105             on_error => sub {
106 0         0 $_[0]->destroy;
107 0         0 undef $handle;
108             },
109             on_eof => sub {
110 0         0 $handle->destroy;
111 0         0 undef $handle;
112             },
113 29         444 );
114              
115 29         3412 $self->data($handle);
116 29         149 $con->send_response(200 => "Port command successful");
117 29         161 $self->done;
118              
119 29         333 };
120              
121             }
122             else
123             {
124 0         0 $con->send_response(500 => "Illegal PORT command");
125 0         0 $self->done;
126 0         0 return;
127             }
128             }
129              
130              
131 6     6 0 133 sub help_rest { 'REST byte-count' }
132              
133             sub cmd_rest
134             {
135 10     10 0 48 my($self, $con, $req) = @_;
136              
137 10 100       53 if($req->args =~ /^\s*(\d+)\s*$/)
138             {
139 8         38 my $offset = $1;
140 8         66 $con->send_response(350 => "Restarting at $offset. Send STORE or RETRIEVE to initiate transfer");
141 8         52 $self->restart_offset($offset);
142             }
143             else
144             {
145 2         5 $con->send_response(501 => "REST requires a value greater than or equal to 0");
146             }
147 10         61 $self->done;
148             }
149              
150             1;
151              
152             __END__