Commit | Line | Data |
---|---|---|
406c51ee JH |
1 | ## |
2 | ## Generic data connection package | |
3 | ## | |
4 | ||
5 | package Net::FTP::dataconn; | |
6 | ||
2e173144 CBW |
7 | use 5.008001; |
8 | ||
9 | use strict; | |
10 | use warnings; | |
11 | ||
406c51ee | 12 | use Carp; |
67ada6d4 | 13 | use Errno; |
2e173144 | 14 | use Net::Cmd; |
406c51ee | 15 | |
bfdb5bfe | 16 | our $VERSION = '3.08'; |
406c51ee | 17 | |
2e173144 CBW |
18 | $Net::FTP::IOCLASS or die "please load Net::FTP before Net::FTP::dataconn"; |
19 | our @ISA = $Net::FTP::IOCLASS; | |
406c51ee | 20 | |
b3f6f6a6 RGS |
21 | sub reading { |
22 | my $data = shift; | |
23 | ${*$data}{'net_ftp_bytesread'} = 0; | |
24 | } | |
406c51ee | 25 | |
406c51ee | 26 | |
b3f6f6a6 RGS |
27 | sub abort { |
28 | my $data = shift; | |
29 | my $ftp = ${*$data}{'net_ftp_cmd'}; | |
406c51ee | 30 | |
b3f6f6a6 RGS |
31 | # no need to abort if we have finished the xfer |
32 | return $data->close | |
33 | if ${*$data}{'net_ftp_eof'}; | |
406c51ee | 34 | |
07513bb4 | 35 | # for some reason if we continuously open RETR connections and not |
b3f6f6a6 RGS |
36 | # read a single byte, then abort them after a while the server will |
37 | # close our connection, this prevents the unexpected EOF on the | |
38 | # command channel -- GMB | |
39 | if (exists ${*$data}{'net_ftp_bytesread'} | |
40 | && (${*$data}{'net_ftp_bytesread'} == 0)) | |
41 | { | |
42 | my $buf = ""; | |
43 | my $timeout = $data->timeout; | |
44 | $data->can_read($timeout) && sysread($data, $buf, 1); | |
45 | } | |
46 | ||
47 | ${*$data}{'net_ftp_eof'} = 1; # fake | |
48 | ||
49 | $ftp->abort; # this will close me | |
406c51ee JH |
50 | } |
51 | ||
406c51ee | 52 | |
b3f6f6a6 RGS |
53 | sub _close { |
54 | my $data = shift; | |
55 | my $ftp = ${*$data}{'net_ftp_cmd'}; | |
56 | ||
57 | $data->SUPER::close(); | |
406c51ee | 58 | |
b3f6f6a6 | 59 | delete ${*$ftp}{'net_ftp_dataconn'} |
8723f121 SH |
60 | if defined $ftp |
61 | && exists ${*$ftp}{'net_ftp_dataconn'} | |
b3f6f6a6 | 62 | && $data == ${*$ftp}{'net_ftp_dataconn'}; |
406c51ee JH |
63 | } |
64 | ||
406c51ee | 65 | |
b3f6f6a6 RGS |
66 | sub close { |
67 | my $data = shift; | |
68 | my $ftp = ${*$data}{'net_ftp_cmd'}; | |
69 | ||
70 | if (exists ${*$data}{'net_ftp_bytesread'} && !${*$data}{'net_ftp_eof'}) { | |
71 | my $junk; | |
8723f121 | 72 | eval { local($SIG{__DIE__}); $data->read($junk, 1, 0) }; |
b3f6f6a6 RGS |
73 | return $data->abort unless ${*$data}{'net_ftp_eof'}; |
74 | } | |
406c51ee | 75 | |
b3f6f6a6 | 76 | $data->_close; |
406c51ee | 77 | |
8723f121 SH |
78 | return unless defined $ftp; |
79 | ||
b3f6f6a6 RGS |
80 | $ftp->response() == CMD_OK |
81 | && $ftp->message =~ /unique file name:\s*(\S*)\s*\)/ | |
82 | && (${*$ftp}{'net_ftp_unique'} = $1); | |
406c51ee | 83 | |
b3f6f6a6 | 84 | $ftp->status == CMD_OK; |
406c51ee JH |
85 | } |
86 | ||
b3f6f6a6 | 87 | |
67ada6d4 | 88 | sub _select { |
b3f6f6a6 RGS |
89 | my ($data, $timeout, $do_read) = @_; |
90 | my ($rin, $rout, $win, $wout, $tout, $nfound); | |
91 | ||
92 | vec($rin = '', fileno($data), 1) = 1; | |
406c51ee | 93 | |
b3f6f6a6 | 94 | ($win, $rin) = ($rin, $win) unless $do_read; |
406c51ee | 95 | |
b3f6f6a6 RGS |
96 | while (1) { |
97 | $nfound = select($rout = $rin, $wout = $win, undef, $tout = $timeout); | |
406c51ee | 98 | |
b3f6f6a6 | 99 | last if $nfound >= 0; |
406c51ee | 100 | |
b3f6f6a6 RGS |
101 | croak "select: $!" |
102 | unless $!{EINTR}; | |
103 | } | |
406c51ee | 104 | |
b3f6f6a6 | 105 | $nfound; |
406c51ee JH |
106 | } |
107 | ||
b3f6f6a6 RGS |
108 | |
109 | sub can_read { | |
110 | _select(@_[0, 1], 1); | |
406c51ee JH |
111 | } |
112 | ||
b3f6f6a6 RGS |
113 | |
114 | sub can_write { | |
115 | _select(@_[0, 1], 0); | |
406c51ee JH |
116 | } |
117 | ||
406c51ee | 118 | |
b3f6f6a6 RGS |
119 | sub cmd { |
120 | my $ftp = shift; | |
121 | ||
122 | ${*$ftp}{'net_ftp_cmd'}; | |
406c51ee JH |
123 | } |
124 | ||
b3f6f6a6 | 125 | |
686337f3 | 126 | sub bytes_read { |
b3f6f6a6 | 127 | my $ftp = shift; |
686337f3 | 128 | |
b3f6f6a6 | 129 | ${*$ftp}{'net_ftp_bytesread'} || 0; |
686337f3 JH |
130 | } |
131 | ||
406c51ee | 132 | 1; |
2e173144 CBW |
133 | |
134 | __END__ | |
135 | ||
136 | =head1 NAME | |
137 | ||
138 | Net::FTP::dataconn - FTP Client data connection class | |
139 | ||
140 | =head1 DESCRIPTION | |
141 | ||
142 | Some of the methods defined in C<Net::FTP> return an object which will | |
143 | be derived from this class. The dataconn class itself is derived from | |
144 | the C<IO::Socket::INET> class, so any normal IO operations can be performed. | |
145 | However the following methods are defined in the dataconn class and IO should | |
146 | be performed using these. | |
147 | ||
148 | =over 4 | |
149 | ||
150 | =item read ( BUFFER, SIZE [, TIMEOUT ] ) | |
151 | ||
152 | Read C<SIZE> bytes of data from the server and place it into C<BUFFER>, also | |
153 | performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not | |
154 | given, the timeout value from the command connection will be used. | |
155 | ||
156 | Returns the number of bytes read before any <CRLF> translation. | |
157 | ||
158 | =item write ( BUFFER, SIZE [, TIMEOUT ] ) | |
159 | ||
160 | Write C<SIZE> bytes of data from C<BUFFER> to the server, also | |
161 | performing any <CRLF> translation necessary. C<TIMEOUT> is optional, if not | |
162 | given, the timeout value from the command connection will be used. | |
163 | ||
164 | Returns the number of bytes written before any <CRLF> translation. | |
165 | ||
166 | =item bytes_read () | |
167 | ||
168 | Returns the number of bytes read so far. | |
169 | ||
170 | =item abort () | |
171 | ||
172 | Abort the current data transfer. | |
173 | ||
174 | =item close () | |
175 | ||
176 | Close the data connection and get a response from the FTP server. Returns | |
177 | I<true> if the connection was closed successfully and the first digit of | |
178 | the response from the server was a '2'. | |
179 | ||
180 | =back | |
181 | ||
182 | =cut |