 |
Changeset 3137
- Timestamp:
- 01/27/08 08:44:54
(10 months ago)
- Author:
- lmartin92
- Message:
Updates all the FtpClient? issues
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r3090 |
r3137 |
|
| 36 | 36 | private timeval tv; |
|---|
| 37 | 37 | private SocketSet ss; |
|---|
| 38 | | package Socket socket_; |
|---|
| | 38 | protected Socket socket_; |
|---|
| 39 | 39 | private bool timeout; |
|---|
| 40 | 40 | |
|---|
| … | … | |
| 203 | 203 | /*********************************************************************** |
|---|
| 204 | 204 | |
|---|
| | 205 | Read content from socket. This is implemented as a callback |
|---|
| | 206 | from the reader() method so we can expose the timout support |
|---|
| | 207 | to subclasses |
|---|
| | 208 | |
|---|
| | 209 | ***********************************************************************/ |
|---|
| | 210 | |
|---|
| | 211 | protected uint socketReader (void[] dst) |
|---|
| | 212 | { |
|---|
| | 213 | return socket_.receive (dst); |
|---|
| | 214 | } |
|---|
| | 215 | |
|---|
| | 216 | /*********************************************************************** |
|---|
| | 217 | |
|---|
| 205 | 218 | Release this SocketConduit |
|---|
| 206 | 219 | |
|---|
| … | … | |
| 223 | 236 | /*********************************************************************** |
|---|
| 224 | 237 | |
|---|
| 225 | | Read content from the socket. Note that the operation |
|---|
| 226 | | may timeout if method setTimeout() has been invoked with |
|---|
| 227 | | a non-zero value. |
|---|
| | 238 | Callback routine to read content from the socket. Note |
|---|
| | 239 | that the operation may timeout if method setTimeout() |
|---|
| | 240 | has been invoked with a non-zero value. |
|---|
| 228 | 241 | |
|---|
| 229 | 242 | Returns the number of bytes read from the socket, or |
|---|
| … | … | |
| 240 | 253 | override uint read (void[] dst) |
|---|
| 241 | 254 | { |
|---|
| 242 | | return read (dst, (void[] dst){return cast(uint) socket_.receive(dst);}); |
|---|
| 243 | | } |
|---|
| 244 | | |
|---|
| 245 | | /*********************************************************************** |
|---|
| 246 | | |
|---|
| 247 | | Callback routine to write the provided content to the |
|---|
| 248 | | socket. This will stall until the socket responds in |
|---|
| 249 | | some manner. Returns the number of bytes sent to the |
|---|
| 250 | | output, or IConduit.Eof if the socket cannot write. |
|---|
| 251 | | |
|---|
| 252 | | ***********************************************************************/ |
|---|
| 253 | | |
|---|
| 254 | | override uint write (void[] src) |
|---|
| 255 | | { |
|---|
| 256 | | int count = socket_.send (src); |
|---|
| 257 | | if (count <= 0) |
|---|
| 258 | | count = Eof; |
|---|
| 259 | | return count; |
|---|
| 260 | | } |
|---|
| 261 | | |
|---|
| 262 | | /*********************************************************************** |
|---|
| 263 | | |
|---|
| 264 | | Internal routine to handle socket read under a timeout. |
|---|
| 265 | | Note that this is synchronized, in order to serialize |
|---|
| 266 | | socket access |
|---|
| 267 | | |
|---|
| 268 | | ***********************************************************************/ |
|---|
| 269 | | |
|---|
| 270 | | package final synchronized uint read (void[] dst, uint delegate(void[]) dg) |
|---|
| 271 | | { |
|---|
| | 255 | // ensure just one read at a time |
|---|
| | 256 | synchronized (this) |
|---|
| | 257 | { |
|---|
| 272 | 258 | // reset timeout; we assume there's no thread contention |
|---|
| 273 | 259 | timeout = false; |
|---|
| … | … | |
| 296 | 282 | |
|---|
| 297 | 283 | // invoke the actual read op |
|---|
| 298 | | int count = dg (dst); |
|---|
| | 284 | int count = socketReader (dst); |
|---|
| 299 | 285 | if (count <= 0) |
|---|
| 300 | 286 | count = Eof; |
|---|
| 301 | 287 | return count; |
|---|
| 302 | | } |
|---|
| 303 | | |
|---|
| | 288 | } |
|---|
| | 289 | } |
|---|
| | 290 | |
|---|
| | 291 | /*********************************************************************** |
|---|
| | 292 | |
|---|
| | 293 | Callback routine to write the provided content to the |
|---|
| | 294 | socket. This will stall until the socket responds in |
|---|
| | 295 | some manner. Returns the number of bytes sent to the |
|---|
| | 296 | output, or IConduit.Eof if the socket cannot write. |
|---|
| | 297 | |
|---|
| | 298 | ***********************************************************************/ |
|---|
| | 299 | |
|---|
| | 300 | override uint write (void[] src) |
|---|
| | 301 | { |
|---|
| | 302 | int count = socket_.send (src); |
|---|
| | 303 | if (count <= 0) |
|---|
| | 304 | count = Eof; |
|---|
| | 305 | return count; |
|---|
| | 306 | } |
|---|
| | 307 | |
|---|
| 304 | 308 | /*********************************************************************** |
|---|
| 305 | 309 | |
|---|
| r3134 |
r3137 |
|
| 1 | 1 | /******************************************************************************* |
|---|
| 2 | 2 | |
|---|
| 3 | | copyright: Copyright (c) 2006 UWB. All rights reserved |
|---|
| | 3 | copyright: Copyright (c) 2006 UWB. All rights reserved |
|---|
| 4 | 4 | |
|---|
| 5 | 5 | license: BSD style: $(LICENSE) |
|---|
| … | … | |
| 9 | 9 | author: UWB |
|---|
| 10 | 10 | |
|---|
| | 11 | modifications are: |
|---|
| | 12 | |
|---|
| | 13 | copyrighted as Copyright (c) 2008 (c) Lester L. Martin II. All rights reserved |
|---|
| | 14 | |
|---|
| | 15 | licensed as BSD style: $(LICENSE) |
|---|
| | 16 | |
|---|
| | 17 | versioned as Initial modified release: _________ 2008 |
|---|
| | 18 | |
|---|
| | 19 | authored by Lester L. Martin II |
|---|
| | 20 | |
|---|
| 11 | 21 | *******************************************************************************/ |
|---|
| 12 | 22 | |
|---|
| 13 | 23 | module tango.net.ftp.FtpClient; |
|---|
| 14 | 24 | |
|---|
| 15 | | private import tango.net.Socket; |
|---|
| | 25 | private import tango.net.Socket, |
|---|
| | 26 | tango.net.SocketConduit; |
|---|
| 16 | 27 | |
|---|
| 17 | 28 | private import tango.net.ftp.Telnet; |
|---|
| … | … | |
| 34 | 45 | |
|---|
| 35 | 46 | private import Timestamp = tango.text.convert.TimeStamp; |
|---|
| | 47 | |
|---|
| | 48 | private import tango.text.Util; |
|---|
| 36 | 49 | |
|---|
| 37 | 50 | |
|---|
| … | … | |
| 53 | 66 | /// Indicates IMAGE format (8 bit binary octets.) |
|---|
| 54 | 67 | image, |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | ///A FtpAddress structure that contains all that is needed to access a FTPConnection; Contributed by Bobef |
|---|
| | 71 | struct FtpAddress |
|---|
| | 72 | { |
|---|
| | 73 | static FtpAddress* opCall(char[] str) |
|---|
| | 74 | { |
|---|
| | 75 | if(str.length==0) return null; |
|---|
| | 76 | try |
|---|
| | 77 | { |
|---|
| | 78 | auto ret=new FtpAddress; |
|---|
| | 79 | //remove ftp:// |
|---|
| | 80 | auto i=locatePattern(str,"ftp://"); |
|---|
| | 81 | if(i==0) str=str[6..$]; |
|---|
| | 82 | |
|---|
| | 83 | //check for username and/or password user[:pass]@ |
|---|
| | 84 | i=locatePrior(str,'@'); |
|---|
| | 85 | if(i!=str.length) |
|---|
| | 86 | { |
|---|
| | 87 | char[] up=str[0..i]; |
|---|
| | 88 | str=str[i+1..$]; |
|---|
| | 89 | i=locate(up,':'); |
|---|
| | 90 | if(i!=up.length) |
|---|
| | 91 | { |
|---|
| | 92 | ret.user=up[0..i]; |
|---|
| | 93 | ret.pass=up[i+1..$]; |
|---|
| | 94 | } |
|---|
| | 95 | else ret.user=up; |
|---|
| | 96 | } |
|---|
| | 97 | |
|---|
| | 98 | //check for port |
|---|
| | 99 | i=locatePrior(str,':'); |
|---|
| | 100 | if(i!=str.length) |
|---|
| | 101 | { |
|---|
| | 102 | ret.port=cast(uint)Integer.toLong(str[i+1..$]); |
|---|
| | 103 | str=str[0..i]; |
|---|
| | 104 | } |
|---|
| | 105 | |
|---|
| | 106 | //check any directories after the adress |
|---|
| | 107 | i=locate(str,'/'); |
|---|
| | 108 | if(i!=str.length) ret.directory=str[i+1..$]; |
|---|
| | 109 | |
|---|
| | 110 | //the rest should be the address |
|---|
| | 111 | ret.address=str[0..i]; |
|---|
| | 112 | if(ret.address.length==0) return null; |
|---|
| | 113 | |
|---|
| | 114 | return ret; |
|---|
| | 115 | |
|---|
| | 116 | }catch(Object o) {return null;} |
|---|
| | 117 | } |
|---|
| | 118 | |
|---|
| | 119 | char[] address; |
|---|
| | 120 | char[] directory; |
|---|
| | 121 | char[] user = "anonymous"; |
|---|
| | 122 | char[] pass = "anonymous@anonymous"; |
|---|
| | 123 | uint port=21; |
|---|
| 55 | 124 | } |
|---|
| 56 | 125 | |
|---|
| … | … | |
| 154 | 223 | } |
|---|
| 155 | 224 | |
|---|
| | 225 | class FtpSocketConduit : SocketConduit |
|---|
| | 226 | { |
|---|
| | 227 | public this(Socket sock) |
|---|
| | 228 | { |
|---|
| | 229 | this.socket_ = sock; |
|---|
| | 230 | } |
|---|
| | 231 | |
|---|
| | 232 | void setSocket(Socket sock) |
|---|
| | 233 | { |
|---|
| | 234 | this.socket_ = sock; |
|---|
| | 235 | } |
|---|
| | 236 | } |
|---|
| | 237 | |
|---|
| 156 | 238 | /// A connection to an FTP server. |
|---|
| 157 | 239 | /// |
|---|
| … | … | |
| 221 | 303 | /// username = username to be sent |
|---|
| 222 | 304 | /// password = password to be sent, if requested |
|---|
| | 305 | |
|---|
| | 306 | |
|---|
| | 307 | this(FtpAddress fad) |
|---|
| | 308 | { |
|---|
| | 309 | this.connect(fad.address, fad.user, fad.pass, fad.port); |
|---|
| | 310 | } |
|---|
| | 311 | |
|---|
| | 312 | public void connect(FtpAddress fad) |
|---|
| | 313 | { |
|---|
| | 314 | this.connect(fad.address, fad.user, fad.pass, fad.port); |
|---|
| | 315 | } |
|---|
| | 316 | |
|---|
| 223 | 317 | public void connect(char[] hostname, char[] username, char[] password, int port = 21) |
|---|
| 224 | 318 | in |
|---|
| … | … | |
| 359 | 453 | { |
|---|
| 360 | 454 | this.sendCommand("CDUP"); |
|---|
| 361 | | this.readResponse("200"); |
|---|
| | 455 | FtpResponse fr = this.readResponse(); |
|---|
| | 456 | if(fr.code == "200" || fr.code == "250") |
|---|
| | 457 | return; |
|---|
| | 458 | else |
|---|
| | 459 | exception(fr); |
|---|
| 362 | 460 | } |
|---|
| 363 | 461 | |
|---|
| … | … | |
| 450 | 548 | this.readResponse("250"); |
|---|
| 451 | 549 | } |
|---|
| | 550 | |
|---|
| | 551 | ///returns 1 if it's a file 2 if it's a directory and 0 if it doesn't exist; contributed by Bobef |
|---|
| | 552 | int exist(char[] file) |
|---|
| | 553 | { |
|---|
| | 554 | try |
|---|
| | 555 | { |
|---|
| | 556 | auto fi=getFileInfo(file); |
|---|
| | 557 | if(fi.type==FtpFileType.file) return 1; |
|---|
| | 558 | else if(fi.type==FtpFileType.dir || fi.type==FtpFileType.cdir || fi.type==FtpFileType.pdir) return 2; |
|---|
| | 559 | } |
|---|
| | 560 | catch(FTPException o) {if(o.response_code!="501") throw o;} |
|---|
| | 561 | return 0; |
|---|
| | 562 | } |
|---|
| | 563 | |
|---|
| | 564 | ///determines the size of a file; Contributed by Bobef |
|---|
| | 565 | long size(char[] file) |
|---|
| | 566 | { |
|---|
| | 567 | try return getFileInfo(file).size; |
|---|
| | 568 | catch(FTPException o) {if(o.response_code!="501") throw o;} |
|---|
| | 569 | return -1; |
|---|
| | 570 | } |
|---|
| 452 | 571 | |
|---|
| 453 | 572 | /// Determine the size in bytes of a file. |
|---|
| … | … | |
| 1817 | 1936 | return Integer.parse (s); |
|---|
| 1818 | 1937 | } |
|---|
| | 1938 | |
|---|
| | 1939 | public InputStream input() |
|---|
| | 1940 | { |
|---|
| | 1941 | return new FtpSocketConduit(getDataSocket); |
|---|
| | 1942 | } |
|---|
| | 1943 | |
|---|
| | 1944 | public OutputStream output() |
|---|
| | 1945 | { |
|---|
| | 1946 | return new FtpSocketConduit(getDataSocket); |
|---|
| | 1947 | } |
|---|
| | 1948 | |
|---|
| | 1949 | ///get's the modification time of a file; contributed by Bobef |
|---|
| | 1950 | Time* modified(char[] file) |
|---|
| | 1951 | { |
|---|
| | 1952 | auto ret=new Time; |
|---|
| | 1953 | try |
|---|
| | 1954 | { |
|---|
| | 1955 | *ret=filemtime(file); |
|---|
| | 1956 | return ret; |
|---|
| | 1957 | } |
|---|
| | 1958 | catch(FTPException o) |
|---|
| | 1959 | { |
|---|
| | 1960 | if(o.response_code!="501") try |
|---|
| | 1961 | { |
|---|
| | 1962 | *ret=getFileInfo(file).modify; |
|---|
| | 1963 | return ret; |
|---|
| | 1964 | } |
|---|
| | 1965 | catch(FTPException o) {if(o.response_code!="501") throw o;} |
|---|
| | 1966 | } |
|---|
| | 1967 | return null; |
|---|
| | 1968 | } |
|---|
| | 1969 | |
|---|
| | 1970 | } |
|---|
| | 1971 | |
|---|
| | 1972 | enum FtpCommand : int |
|---|
| | 1973 | { |
|---|
| | 1974 | LIST, //get |
|---|
| | 1975 | APPE, //put |
|---|
| | 1976 | NLST, //get |
|---|
| | 1977 | REST, //put | get |
|---|
| | 1978 | RETR, //get |
|---|
| | 1979 | STOR, //put |
|---|
| | 1980 | |
|---|
| | 1981 | } |
|---|
| | 1982 | |
|---|
| | 1983 | bool usedRest = false; |
|---|
| | 1984 | |
|---|
| | 1985 | bool prepareInputStream(FTPConnection ftp, InputStream input, FtpCommand ftpc, char[][] parameters) |
|---|
| | 1986 | { |
|---|
| | 1987 | bool success; |
|---|
| | 1988 | |
|---|
| | 1989 | with(FtpCommand) |
|---|
| | 1990 | { |
|---|
| | 1991 | FtpSocketConduit fsc = cast(FtpSocketConduit) input; |
|---|
| | 1992 | fsc.setSocket(ftp.getDataSocket()); |
|---|
| | 1993 | if(usedRest && ftpc != RETR) |
|---|
| | 1994 | ftp.exception("You must use RETR or STOR after a REST command."); |
|---|
| | 1995 | switch(ftpc) |
|---|
| | 1996 | { |
|---|
| | 1997 | case LIST: |
|---|
| | 1998 | ftp.sendCommand("LIST", parameters); |
|---|
| | 1999 | break; |
|---|
| | 2000 | case NLST: |
|---|
| | 2001 | ftp.sendCommand("NLST", parameters); |
|---|
| | 2002 | break; |
|---|
| | 2003 | case REST: |
|---|
| | 2004 | ftp.sendCommand("REST", parameters); |
|---|
| | 2005 | usedRest = true; |
|---|
| | 2006 | break; |
|---|
| | 2007 | case RETR: |
|---|
| | 2008 | ftp.sendCommand("RETR", parameters); |
|---|
| | 2009 | usedRest = usedRest ? false : usedRest; |
|---|
| | 2010 | break; |
|---|
| | 2011 | } |
|---|
| | 2012 | } |
|---|
| | 2013 | |
|---|
| | 2014 | return success; |
|---|
| | 2015 | } |
|---|
| | 2016 | |
|---|
| | 2017 | bool prepareOutputStream(FTPConnection ftp, OutputStream output, FtpCommand ftpc, char[][] parameters) |
|---|
| | 2018 | { |
|---|
| | 2019 | bool success; |
|---|
| | 2020 | |
|---|
| | 2021 | with(FtpCommand) |
|---|
| | 2022 | { |
|---|
| | 2023 | output = ftp.output; |
|---|
| | 2024 | if(usedRest && ftpc != STOR) |
|---|
| | 2025 | ftp.exception("You must use RETR or STOR after a REST command."); |
|---|
| | 2026 | switch(ftpc) |
|---|
| | 2027 | { |
|---|
| | 2028 | case APPE: |
|---|
| | 2029 | ftp.sendCommand("APPE", parameters); |
|---|
| | 2030 | break; |
|---|
| | 2031 | case STOR: |
|---|
| | 2032 | ftp.sendCommand("STOR", parameters); |
|---|
| | 2033 | usedRest = usedRest ? false : usedRest; |
|---|
| | 2034 | break; |
|---|
| | 2035 | case REST: |
|---|
| | 2036 | ftp.sendCommand("REST", parameters); |
|---|
| | 2037 | usedRest = true; |
|---|
| | 2038 | break; |
|---|
| | 2039 | } |
|---|
| | 2040 | } |
|---|
| | 2041 | |
|---|
| | 2042 | return success; |
|---|
| 1819 | 2043 | } |
|---|
| 1820 | 2044 | |
|---|
| r3038 |
r3137 |
|
| 34 | 34 | |
|---|
| 35 | 35 | /// The number of milliseconds to wait for socket communication or connection. |
|---|
| 36 | | protected TimeSpan timeout = TimeSpan.millis(5000); |
|---|
| | 36 | protected TimeSpan timeout = TimeSpan.millis(2500); |
|---|
| 37 | 37 | |
|---|
| 38 | 38 | /// provided by host |
|---|
Download in other formats:
|
 |
 |
|
 |
Copyright © 2006-2008 Tango. All Rights Reserved. | Page Width:
Static or
Dynamic