1 51 52 package com.enterprisedt.net.ftp; 53 54 import java.io.IOException ; 55 import java.io.PrintWriter ; 56 import java.io.BufferedReader ; 57 import java.io.InputStream ; 58 import java.io.OutputStream ; 59 import java.io.InputStreamReader ; 60 import java.io.OutputStreamWriter ; 61 import java.io.Writer ; 62 63 import java.net.Socket ; 64 import java.net.ServerSocket ; 65 import java.net.InetAddress ; 66 67 74 public class FTPControlSocket { 75 76 79 private static String cvsId = "@(#)$Id: FTPControlSocket.java,v 1.1.1.1 2005/06/23 15:22:59 smontoro Exp $"; 80 81 84 static final String EOL = "\r\n"; 85 86 89 static final int CONTROL_PORT = 21; 90 91 94 private static final String DEBUG_ARROW = "---> "; 95 96 99 private static final String PASSWORD_MESSAGE = DEBUG_ARROW + "PASS"; 100 101 105 private boolean debugResponses = false; 106 107 111 private PrintWriter log = new PrintWriter (System.out); 112 113 116 private Socket controlSock = null; 117 118 121 private Writer writer = null; 122 123 127 private BufferedReader reader = null; 128 129 139 public FTPControlSocket(String remoteHost, int controlPort, 140 PrintWriter log, int timeout) 141 throws IOException , FTPException { 142 143 setLogStream(log); 144 145 debugResponses(true); 147 controlSock = new Socket (remoteHost, controlPort); 148 setTimeout(timeout); 149 initStreams(); 150 validateConnection(); 151 152 debugResponses(false); 154 } 155 156 166 public FTPControlSocket(InetAddress remoteAddr, int controlPort, 167 PrintWriter log, int timeout) 168 throws IOException , FTPException { 169 170 setLogStream(log); 171 172 debugResponses(true); 174 controlSock = new Socket (remoteAddr, controlPort); 175 setTimeout(timeout); 176 initStreams(); 177 validateConnection(); 178 179 debugResponses(false); 181 } 182 183 184 188 private void validateConnection() 189 throws IOException , FTPException { 190 191 String reply = readReply(); 192 validateReply(reply, "220"); 193 } 194 195 196 200 private void initStreams() 201 throws IOException { 202 203 InputStream is = controlSock.getInputStream(); 205 reader = new BufferedReader (new InputStreamReader (is)); 206 207 OutputStream os = controlSock.getOutputStream(); 209 writer = new OutputStreamWriter (os); 210 } 211 212 213 218 String getRemoteHostName() { 219 InetAddress addr = controlSock.getInetAddress(); 220 return addr.getHostName(); 221 } 222 223 224 233 void setTimeout(int millis) 234 throws IOException { 235 236 if (controlSock == null) 237 throw new IllegalStateException ( 238 "Failed to set timeout - no control socket"); 239 240 controlSock.setSoTimeout(millis); 241 } 242 243 244 247 public void logout() 248 throws IOException { 249 250 if (log != null) { 251 log.flush(); 252 log = null; 253 } 254 255 IOException ex = null; 256 try { 257 writer.close(); 258 } 259 catch (IOException e) { 260 ex = e; 261 } 262 try { 263 reader.close(); 264 } 265 catch (IOException e) { 266 ex = e; 267 } 268 try { 269 controlSock.close(); 270 } 271 catch (IOException e) { 272 ex = e; 273 } 274 if (ex != null) 275 throw ex; 276 } 277 278 279 288 FTPDataSocket createDataSocket(FTPConnectMode connectMode) 289 throws IOException , FTPException { 290 291 if (connectMode == FTPConnectMode.ACTIVE) { 292 return new FTPDataSocket(createDataSocketActive()); 293 } 294 else { return new FTPDataSocket(createDataSocketPASV()); 296 } 297 } 298 299 300 306 ServerSocket createDataSocketActive() 307 throws IOException , FTPException { 308 309 ServerSocket socket = new ServerSocket (0); 311 312 InetAddress localhost = controlSock.getLocalAddress(); 314 315 setDataPort(localhost, (short)socket.getLocalPort()); 317 318 return socket; 319 } 320 321 322 323 329 private short toUnsignedShort(byte value) { 330 return ( value < 0 ) 331 ? (short) (value + 256) 332 : (short) value; 333 } 334 335 341 protected byte[] toByteArray (short value) { 342 343 byte[] bytes = new byte[2]; 344 bytes[0] = (byte) (value >> 8); bytes[1] = (byte) (value & 0x00FF); return bytes; 347 } 348 349 350 357 private void setDataPort(InetAddress host, short portNo) 358 throws IOException , FTPException { 359 360 byte[] hostBytes = host.getAddress(); 361 byte[] portBytes = toByteArray(portNo); 362 363 String cmd = new StringBuffer ("PORT ") 365 .append (toUnsignedShort (hostBytes[0])) .append (",") 366 .append (toUnsignedShort (hostBytes[1])) .append (",") 367 .append (toUnsignedShort (hostBytes[2])) .append (",") 368 .append (toUnsignedShort (hostBytes[3])) .append (",") 369 .append (toUnsignedShort (portBytes[0])) .append (",") 370 .append (toUnsignedShort (portBytes[1])) .toString (); 371 372 String reply = sendCommand(cmd); 374 validateReply(reply, "200"); 375 } 376 377 378 385 Socket createDataSocketPASV() 386 throws IOException , FTPException { 387 388 String reply = sendCommand("PASV"); 391 validateReply(reply, "227"); 392 393 403 int startIP = reply.indexOf('('); 405 int endIP = reply.indexOf(')'); 406 407 if (startIP < 0 && endIP < 0) { 409 startIP = reply.toUpperCase().lastIndexOf("MODE") + 4; 410 endIP = reply.length(); 411 } 412 413 String ipData = reply.substring(startIP+1,endIP); 414 int parts[] = new int[6]; 415 416 int len = ipData.length(); 417 int partCount = 0; 418 StringBuffer buf = new StringBuffer (); 419 420 for (int i = 0; i < len && partCount <= 6; i++) { 422 423 char ch = ipData.charAt(i); 424 if (Character.isDigit(ch)) 425 buf.append(ch); 426 else if (ch != ',') { 427 throw new FTPException("Malformed PASV reply: " + reply); 428 } 429 430 if (ch == ',' || i+1 == len) { try { 433 parts[partCount++] = Integer.parseInt(buf.toString()); 434 buf.setLength(0); 435 } 436 catch (NumberFormatException ex) { 437 throw new FTPException("Malformed PASV reply: " + reply); 438 } 439 } 440 } 441 442 String ipAddress = parts[0] + "."+ parts[1]+ "." + 445 parts[2] + "." + parts[3]; 446 447 int port = (parts[4] << 8) + parts[5]; 449 450 return new Socket (ipAddress, port); 452 } 453 454 455 456 462 String sendCommand(String command) 463 throws IOException { 464 465 log(DEBUG_ARROW + command); 466 467 writer.write(command + EOL); 469 writer.flush(); 470 471 return readReply(); 473 } 474 475 485 String readReply() 486 throws IOException { 487 488 String firstLine = reader.readLine(); 489 if (firstLine == null || firstLine.length() == 0) 490 throw new IOException ("Unexpected null reply received"); 491 492 StringBuffer reply = new StringBuffer (firstLine); 493 494 log(reply.toString()); 495 496 String replyCode = reply.toString().substring(0, 3); 497 498 if (reply.charAt(3) == '-') { 501 502 boolean complete = false; 503 while (!complete) { 504 String line = reader.readLine(); 505 if (line == null) 506 throw new IOException ("Unexpected null reply received"); 507 508 log(line); 509 510 if (line.length() > 3 && 511 line.substring(0, 3).equals(replyCode) && 512 line.charAt(3) == ' ') { 513 reply.append(line.substring(3)); 514 complete = true; 515 } 516 else { reply.append(" "); 518 reply.append(line); 519 } 520 } } return reply.toString(); 523 } 524 525 526 536 FTPReply validateReply(String reply, String expectedReplyCode) 537 throws IOException , FTPException { 538 539 String replyCode = reply.substring(0, 3); 541 String replyText = reply.substring(4); 542 FTPReply replyObj = new FTPReply(replyCode, replyText); 543 544 if (replyCode.equals(expectedReplyCode)) 545 return replyObj; 546 547 throw new FTPException(replyText, replyCode); 549 } 550 551 562 FTPReply validateReply(String reply, String [] expectedReplyCodes) 563 throws IOException , FTPException { 564 565 String replyCode = reply.substring(0, 3); 567 String replyText = reply.substring(4); 568 569 FTPReply replyObj = new FTPReply(replyCode, replyText); 570 571 for (int i = 0; i < expectedReplyCodes.length; i++) 572 if (replyCode.equals(expectedReplyCodes[i])) 573 return replyObj; 574 575 throw new FTPException(replyText, replyCode); 577 } 578 579 580 586 void debugResponses(boolean on) { 587 debugResponses = on; 588 } 589 590 597 void setLogStream(PrintWriter log) { 598 if (log != null) 599 this.log = log; 600 else 601 debugResponses = false; 602 } 603 604 605 610 void log(String msg) { 611 if (debugResponses && log != null) { 612 if (!msg.startsWith(PASSWORD_MESSAGE)) 613 log.println(msg); 614 else 615 log.println(PASSWORD_MESSAGE + " ********"); 616 } 617 } 618 619 } 620 621 622 | Popular Tags |