1 package net.nutch.protocol.ftp; 2 3 import java.io.BufferedReader ; 4 import java.io.IOException ; 5 import java.io.InputStream ; 6 import java.io.InputStreamReader ; 7 import java.io.OutputStream ; 8 9 import java.net.InetAddress ; 10 import java.net.Socket ; 11 12 import java.util.List ; 13 15 import org.apache.commons.net.MalformedServerReplyException; 16 17 import org.apache.commons.net.ftp.FTP; 18 import org.apache.commons.net.ftp.FTPCommand; 19 import org.apache.commons.net.ftp.FTPFile; 20 import org.apache.commons.net.ftp.FTPFileEntryParser; 21 import org.apache.commons.net.ftp.FTPReply; 22 23 import org.apache.commons.net.ftp.FTPConnectionClosedException; 24 25 57 58 public class Client extends FTP 59 { 60 private int __dataTimeout; 61 private int __passivePort; 62 private String __passiveHost; 63 private int __fileType, __fileFormat; 64 private boolean __remoteVerificationEnabled; 65 private FTPFileEntryParser __entryParser; 66 private String __systemName; 67 68 public Client() 70 { 71 __initDefaults(); 72 __dataTimeout = -1; 73 __remoteVerificationEnabled = true; 74 } 75 76 private void __initDefaults() 78 { 79 __passiveHost = null; 80 __passivePort = -1; 81 __fileType = FTP.ASCII_FILE_TYPE; 82 __fileFormat = FTP.NON_PRINT_TEXT_FORMAT; 83 __systemName = null; 84 __entryParser = null; 85 } 86 87 private void __parsePassiveModeReply(String reply) 89 throws MalformedServerReplyException 90 { 91 int i, index, lastIndex; 92 String octet1, octet2; 93 StringBuffer host; 94 95 reply = reply.substring(reply.indexOf('(') + 1, 96 reply.indexOf(')')).trim(); 97 98 host = new StringBuffer (24); 99 lastIndex = 0; 100 index = reply.indexOf(','); 101 host.append(reply.substring(lastIndex, index)); 102 103 for (i = 0; i < 3; i++) 104 { 105 host.append('.'); 106 lastIndex = index + 1; 107 index = reply.indexOf(',', lastIndex); 108 host.append(reply.substring(lastIndex, index)); 109 } 110 111 lastIndex = index + 1; 112 index = reply.indexOf(',', lastIndex); 113 114 octet1 = reply.substring(lastIndex, index); 115 octet2 = reply.substring(index + 1); 116 117 try 119 { 120 index = Integer.parseInt(octet1); 121 lastIndex = Integer.parseInt(octet2); 122 } 123 catch (NumberFormatException e) 124 { 125 throw new MalformedServerReplyException( 126 "Could not parse passive host information.\nServer Reply: " + reply); 127 } 128 129 index <<= 8; 130 index |= lastIndex; 131 132 __passiveHost = host.toString(); 133 __passivePort = index; 134 } 135 136 protected Socket __openPassiveDataConnection(int command, String arg) 138 throws IOException , FtpExceptionCanNotHaveDataConnection { 139 Socket socket; 140 141 144 if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) 145 throw new FtpExceptionCanNotHaveDataConnection( 146 "pasv() failed. " + getReplyString()); 147 148 try { 149 __parsePassiveModeReply(getReplyStrings()[0]); 150 } catch (MalformedServerReplyException e) { 151 throw new FtpExceptionCanNotHaveDataConnection(e.getMessage()); 152 } 153 154 175 socket = _socketFactory_.createSocket(__passiveHost, __passivePort); 176 177 if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) { 178 socket.close(); 179 return null; 180 } 181 182 if (__remoteVerificationEnabled && !verifyRemote(socket)) 183 { 184 InetAddress host1, host2; 185 186 host1 = socket.getInetAddress(); 187 host2 = getRemoteAddress(); 188 189 socket.close(); 190 191 throw new FtpExceptionCanNotHaveDataConnection( 193 "Host attempting data connection " + host1.getHostAddress() + 194 " is not same as server " + host2.getHostAddress() + 195 " So we intentionally close it for security precaution." 196 ); 197 } 198 199 if (__dataTimeout >= 0) 200 socket.setSoTimeout(__dataTimeout); 201 202 return socket; 203 } 204 205 209 public void setDataTimeout(int timeout) 210 { 211 __dataTimeout = timeout; 212 } 213 214 220 public void disconnect() throws IOException 221 { 222 __initDefaults(); 223 super.disconnect(); 224 } 227 228 237 public void setRemoteVerificationEnabled(boolean enable) 238 { 239 __remoteVerificationEnabled = enable; 240 } 241 242 249 public boolean isRemoteVerificationEnabled() 250 { 251 return __remoteVerificationEnabled; 252 } 253 254 268 public boolean login(String username, String password) throws IOException 269 { 270 user(username); 271 272 if (FTPReply.isPositiveCompletion(getReplyCode())) 273 return true; 274 275 if (!FTPReply.isPositiveIntermediate(getReplyCode())) 278 return false; 279 280 return FTPReply.isPositiveCompletion(pass(password)); 281 } 282 283 295 public boolean logout() throws IOException 296 { 297 return FTPReply.isPositiveCompletion(quit()); 298 } 299 300 public void retrieveList(String path, List entries, int limit, 302 FTPFileEntryParser parser) 303 throws IOException , 304 FtpExceptionCanNotHaveDataConnection, 305 FtpExceptionUnknownForcedDataClose, 306 FtpExceptionControlClosedByForcedDataClose { 307 Socket socket = __openPassiveDataConnection(FTPCommand.LIST, path); 308 309 if (socket == null) 310 throw new FtpExceptionCanNotHaveDataConnection("LIST " 311 + ((path == null) ? "" : path)); 312 313 BufferedReader reader = 314 new BufferedReader (new InputStreamReader (socket.getInputStream())); 315 316 boolean mandatory_close = false; 318 319 int count = 0; 321 String line = parser.readNextEntry(reader); 322 while (line != null) { 323 FTPFile ftpFile = parser.parseFTPEntry(line); 324 if (ftpFile == null) { 326 line = parser.readNextEntry(reader); 327 continue; 328 } 329 entries.add(ftpFile); 330 count += line.length(); 331 if (limit > 0 && count > limit) { 334 mandatory_close = true; 335 break; 336 } 337 line = parser.readNextEntry(reader); 338 } 339 340 socket.close(); 344 345 351 try { 352 int reply = getReply(); 353 if (!_notBadReply(reply)) 354 throw new FtpExceptionUnknownForcedDataClose(getReplyString()); 355 } catch (FTPConnectionClosedException e) { 356 throw new FtpExceptionControlClosedByForcedDataClose(e.getMessage()); 362 } 363 364 } 365 366 public void retrieveFile(String path, OutputStream os, int limit) 368 throws IOException , 369 FtpExceptionCanNotHaveDataConnection, 370 FtpExceptionUnknownForcedDataClose, 371 FtpExceptionControlClosedByForcedDataClose { 372 373 Socket socket = __openPassiveDataConnection(FTPCommand.RETR, path); 374 375 if (socket == null) 376 throw new FtpExceptionCanNotHaveDataConnection("RETR " 377 + ((path == null) ? "" : path)); 378 379 InputStream input = socket.getInputStream(); 380 381 386 388 boolean mandatory_close = false; 390 391 int len; int count = 0; 392 byte[] buf = 393 new byte[org.apache.commons.net.io.Util.DEFAULT_COPY_BUFFER_SIZE]; 394 while((len=input.read(buf,0,buf.length)) != -1){ 395 count += len; 396 if (limit > 0 && count > limit) { 399 os.write(buf,0,len-(count-limit)); 400 mandatory_close = true; 401 break; 402 } 403 os.write(buf,0,len); 404 os.flush(); 405 } 406 407 socket.close(); 411 412 418 421 try { 422 int reply = getReply(); 423 if (!_notBadReply(reply)) 424 throw new FtpExceptionUnknownForcedDataClose(getReplyString()); 425 } catch (FTPConnectionClosedException e) { 426 throw new FtpExceptionControlClosedByForcedDataClose(e.getMessage()); 432 } 433 434 } 435 436 private boolean _notBadReply(int reply) { 438 439 if (FTPReply.isPositiveCompletion(reply)) { 440 } else if (reply == 426) { } else if (reply == 450) { } else if (reply == 451) { } else if (reply == 451) { } else { 458 return false; 460 } 461 462 return true; 463 } 464 465 484 public boolean setFileType(int fileType) throws IOException 485 { 486 if (FTPReply.isPositiveCompletion(type(fileType))) 487 { 488 __fileType = fileType; 489 __fileFormat = FTP.NON_PRINT_TEXT_FORMAT; 490 return true; 491 } 492 return false; 493 } 494 495 513 public String getSystemName() 514 throws IOException , FtpExceptionBadSystResponse 515 { 516 if (__systemName == null && FTPReply.isPositiveCompletion(syst())) { 521 __systemName = (getReplyStrings()[0]).substring(4); 522 } else { 523 throw new FtpExceptionBadSystResponse( 524 "Bad response of SYST: " + getReplyString()); 525 } 526 527 return __systemName; 528 } 529 530 543 public boolean sendNoOp() throws IOException 544 { 545 return FTPReply.isPositiveCompletion(noop()); 546 } 547 548 557 } 558 | Popular Tags |