Source Code Cross Referenced for DataConnectionHandler.java in  » Net » DrFTPD » net » sf » drftpd » master » command » plugins » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » DrFTPD » net.sf.drftpd.master.command.plugins 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This file is part of DrFTPD, Distributed FTP Daemon.
0003:         *
0004:         * DrFTPD is free software; you can redistribute it and/or modify it under the
0005:         * terms of the GNU General Public License as published by the Free Software
0006:         * Foundation; either version 2 of the License, or (at your option) any later
0007:         * version.
0008:         *
0009:         * DrFTPD is distributed in the hope that it will be useful, but WITHOUT ANY
0010:         * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
0011:         * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
0012:         *
0013:         * You should have received a copy of the GNU General Public License along with
0014:         * DrFTPD; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
0015:         * Suite 330, Boston, MA 02111-1307 USA
0016:         */
0017:        package net.sf.drftpd.master.command.plugins;
0018:
0019:        import java.io.FileNotFoundException;
0020:        import java.io.IOException;
0021:        import java.io.PrintWriter;
0022:        import java.net.InetAddress;
0023:        import java.net.InetSocketAddress;
0024:        import java.net.ServerSocket;
0025:        import java.net.Socket;
0026:        import java.net.UnknownHostException;
0027:        import java.util.Collections;
0028:        import java.util.Iterator;
0029:        import java.util.List;
0030:        import java.util.Map;
0031:        import java.util.ResourceBundle;
0032:        import java.util.StringTokenizer;
0033:
0034:        import javax.net.ServerSocketFactory;
0035:        import javax.net.SocketFactory;
0036:        import javax.net.ssl.HandshakeCompletedEvent;
0037:        import javax.net.ssl.HandshakeCompletedListener;
0038:        import javax.net.ssl.SSLContext;
0039:        import javax.net.ssl.SSLSocket;
0040:
0041:        import net.sf.drftpd.NoAvailableSlaveException;
0042:        import net.sf.drftpd.NoSFVEntryException;
0043:        import net.sf.drftpd.ObjectNotFoundException;
0044:        import net.sf.drftpd.SlaveUnavailableException;
0045:        import net.sf.drftpd.event.TransferEvent;
0046:        import net.sf.drftpd.master.BaseFtpConnection;
0047:        import net.sf.drftpd.master.FtpRequest;
0048:        import net.sf.drftpd.master.command.CommandManager;
0049:        import net.sf.drftpd.master.command.CommandManagerFactory;
0050:        import net.sf.drftpd.master.config.ZipscriptConfig;
0051:
0052:        import org.apache.log4j.Logger;
0053:        import org.drftpd.ActiveConnection;
0054:        import org.drftpd.Bytes;
0055:        import org.drftpd.Checksum;
0056:        import org.drftpd.PassiveConnection;
0057:        import org.drftpd.SFVFile;
0058:        import org.drftpd.SSLGetContext;
0059:        import org.drftpd.commands.CommandHandler;
0060:        import org.drftpd.commands.CommandHandlerFactory;
0061:        import org.drftpd.commands.Reply;
0062:        import org.drftpd.commands.ReplyException;
0063:        import org.drftpd.commands.ReplySlaveUnavailableException;
0064:        import org.drftpd.commands.UnhandledCommandException;
0065:        import org.drftpd.commands.UserManagement;
0066:        import org.drftpd.master.RemoteSlave;
0067:        import org.drftpd.master.RemoteTransfer;
0068:        import org.drftpd.remotefile.FileStillTransferringException;
0069:        import org.drftpd.remotefile.LinkedRemoteFile;
0070:        import org.drftpd.remotefile.LinkedRemoteFileInterface;
0071:        import org.drftpd.remotefile.ListUtils;
0072:        import org.drftpd.remotefile.StaticRemoteFile;
0073:        import org.drftpd.slave.ConnectInfo;
0074:        import org.drftpd.slave.Connection;
0075:        import org.drftpd.slave.RemoteIOException;
0076:        import org.drftpd.slave.Transfer;
0077:        import org.drftpd.slave.TransferFailedException;
0078:        import org.drftpd.slave.TransferStatus;
0079:        import org.drftpd.usermanager.UserFileException;
0080:        import org.tanesha.replacer.ReplacerEnvironment;
0081:        import org.drftpd.SFVFile.SFVStatus;
0082:
0083:        /**
0084:         * @author mog
0085:         * @author zubov
0086:         * @version $Id: DataConnectionHandler.java 1593 2007-01-31 22:56:52Z zubov $
0087:         */
0088:        public class DataConnectionHandler implements  CommandHandler,
0089:                CommandHandlerFactory, Cloneable, HandshakeCompletedListener {
0090:            private static final Logger logger = Logger
0091:                    .getLogger(DataConnectionHandler.class);
0092:            private SSLContext _ctx;
0093:            private boolean _encryptedDataChannel;
0094:            private boolean _SSLHandshakeClientMode = false;
0095:            protected boolean _isPasv = false;
0096:            protected boolean _isPort = false;
0097:
0098:            /**
0099:             * Holds the address that getDataSocket() should connect to in PORT mode.
0100:             */
0101:            private InetSocketAddress _portAddress;
0102:            protected boolean _preTransfer = false;
0103:            private RemoteSlave _preTransferRSlave;
0104:            private long _resumePosition = 0;
0105:            private RemoteSlave _rslave;
0106:
0107:            /**
0108:             * ServerSocket for PASV mode.
0109:             */
0110:            private PassiveConnection _passiveConnection;
0111:            private RemoteTransfer _transfer;
0112:            private LinkedRemoteFileInterface _transferFile;
0113:            private char _type = 'A';
0114:            private boolean _handshakeCompleted;
0115:
0116:            public DataConnectionHandler() {
0117:                super ();
0118:                _handshakeCompleted = false;
0119:                try {
0120:                    _ctx = SSLGetContext.getSSLContext();
0121:                } catch (FileNotFoundException e) {
0122:                    _ctx = null;
0123:                    logger.warn("Couldn't load SSLContext, SSL/TLS disabled");
0124:                } catch (Exception e) {
0125:                    _ctx = null;
0126:                    logger
0127:                            .warn("Couldn't load SSLContext, SSL/TLS disabled",
0128:                                    e);
0129:                }
0130:            }
0131:
0132:            private Reply doAUTH(BaseFtpConnection conn) {
0133:                if (_ctx == null) {
0134:                    return new Reply(500, "TLS not configured");
0135:                }
0136:
0137:                Socket s = conn.getControlSocket();
0138:
0139:                //reply success
0140:                conn.getControlWriter().write(
0141:                        new Reply(234, conn.getRequest().getCommandLine()
0142:                                + " successful").toString());
0143:                conn.getControlWriter().flush();
0144:                SSLSocket s2 = null;
0145:                try {
0146:                    s2 = (SSLSocket) _ctx.getSocketFactory().createSocket(s,
0147:                            s.getInetAddress().getHostAddress(), s.getPort(),
0148:                            true);
0149:                    conn.setControlSocket(s2);
0150:                    s2.setUseClientMode(false);
0151:                    s2.addHandshakeCompletedListener(this );
0152:                    s2.startHandshake();
0153:                    while (!_handshakeCompleted) {
0154:                        synchronized (this ) {
0155:                            try {
0156:                                wait(10000);
0157:                            } catch (InterruptedException e) {
0158:                                s2.close();
0159:                                conn.stop("Took too long to negotiate SSL");
0160:                                return new Reply(400,
0161:                                        "Took too long to negotiate SSL");
0162:                            }
0163:                        }
0164:                    }
0165:                    // reset for possible auth later
0166:                    _handshakeCompleted = false;
0167:                } catch (IOException e) {
0168:                    logger.warn("", e);
0169:                    if (s2 != null) {
0170:                        try {
0171:                            s2.close();
0172:                        } catch (IOException e2) {
0173:                            logger.debug("error closing SSLSocket connection");
0174:                        }
0175:                    }
0176:                    conn.stop(e.getMessage());
0177:
0178:                    return null;
0179:                }
0180:                s2 = null;
0181:
0182:                return null;
0183:            }
0184:
0185:            /**
0186:             * <code>MODE &lt;SP&gt; <mode-code> &lt;CRLF&gt;</code><br>
0187:             *
0188:             * The argument is a single Telnet character code specifying the data
0189:             * transfer modes described in the Section on Transmission Modes.
0190:             */
0191:            private Reply doMODE(BaseFtpConnection conn) {
0192:                FtpRequest request = conn.getRequest();
0193:
0194:                // argument check
0195:                if (!request.hasArgument()) {
0196:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0197:                }
0198:
0199:                if (request.getArgument().equalsIgnoreCase("S")) {
0200:                    return Reply.RESPONSE_200_COMMAND_OK;
0201:                }
0202:
0203:                return Reply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM;
0204:            }
0205:
0206:            /**
0207:             * <code>PASV &lt;CRLF&gt;</code><br>
0208:             *
0209:             * This command requests the server-DTP to "listen" on a data port (which is
0210:             * not its default data port) and to wait for a connection rather than
0211:             * initiate one upon receipt of a transfer command. The response to this
0212:             * command includes the host and port address this server is listening on.
0213:             */
0214:            private Reply doPASVandCPSV(BaseFtpConnection conn) {
0215:                if (!_preTransfer) {
0216:                    return new Reply(500,
0217:                            "You need to use a client supporting PRET (PRE Transfer) to use PASV");
0218:                }
0219:
0220:                //reset();
0221:                _preTransfer = false;
0222:
0223:                if (isPort() == true) {
0224:                    throw new RuntimeException();
0225:                }
0226:
0227:                if (conn.getRequest().getCommand().equals("CPSV")) {
0228:                    _SSLHandshakeClientMode = true;
0229:                }
0230:
0231:                InetSocketAddress address = null;
0232:
0233:                if (_preTransferRSlave == null) {
0234:                    try {
0235:                        _passiveConnection = new PassiveConnection(
0236:                                _encryptedDataChannel ? _ctx : null, conn
0237:                                        .getGlobalContext().getPortRange(),
0238:                                false);
0239:                        try {
0240:                            address = new InetSocketAddress(conn
0241:                                    .getGlobalContext().getConfig()
0242:                                    .getPasvAddress(), _passiveConnection
0243:                                    .getLocalPort());
0244:                        } catch (NullPointerException e) {
0245:                            address = new InetSocketAddress(conn
0246:                                    .getControlSocket().getLocalAddress(),
0247:                                    _passiveConnection.getLocalPort());
0248:                        }
0249:                        _isPasv = true;
0250:                    } catch (Exception ex) {
0251:                        logger.warn("", ex);
0252:
0253:                        return new Reply(550, ex.getMessage());
0254:                    }
0255:                } else {
0256:                    try {
0257:                        String index = _preTransferRSlave.issueListenToSlave(
0258:                                _encryptedDataChannel, _SSLHandshakeClientMode);
0259:                        ConnectInfo ci = _preTransferRSlave
0260:                                .fetchTransferResponseFromIndex(index);
0261:                        _transfer = _preTransferRSlave.getTransfer(ci
0262:                                .getTransferIndex());
0263:                        address = new InetSocketAddress(_preTransferRSlave
0264:                                .getPASVIP(), _transfer.getAddress().getPort());
0265:                        _isPasv = true;
0266:                    } catch (SlaveUnavailableException e) {
0267:                        reset(conn);
0268:                        return Reply.RESPONSE_530_SLAVE_UNAVAILABLE;
0269:                    } catch (RemoteIOException e) {
0270:                        reset(conn);
0271:                        _preTransferRSlave
0272:                                .setOffline("Slave could not listen for a connection");
0273:                        logger.error("Slave could not listen for a connection",
0274:                                e);
0275:
0276:                        return new Reply(500,
0277:                                "Slave could not listen for a connection");
0278:                    }
0279:                }
0280:
0281:                if (conn.getRequest().getCommand().equals("CPSV")) {
0282:                    // can only reset it if the transfer was setup with CPSV
0283:                    _SSLHandshakeClientMode = false;
0284:                }
0285:
0286:                if (address.getAddress() == null
0287:                        || address.getAddress().getHostAddress() == null) {
0288:                    return new Reply(500,
0289:                            "Address for is unresolvable, check pasv_addr setting");
0290:                }
0291:
0292:                String addrStr = address.getAddress().getHostAddress().replace(
0293:                        '.', ',')
0294:                        + ','
0295:                        + (address.getPort() >> 8)
0296:                        + ','
0297:                        + (address.getPort() & 0xFF);
0298:
0299:                return new Reply(227, "Entering Passive Mode (" + addrStr
0300:                        + ").");
0301:            }
0302:
0303:            private Reply doPBSZ(BaseFtpConnection conn)
0304:                    throws UnhandledCommandException {
0305:                String cmd = conn.getRequest().getArgument();
0306:
0307:                if ((cmd == null) || !cmd.equals("0")) {
0308:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0309:                }
0310:
0311:                return Reply.RESPONSE_200_COMMAND_OK;
0312:            }
0313:
0314:            /**
0315:             * <code>PORT &lt;SP&gt; <host-port> &lt;CRLF&gt;</code><br>
0316:             *
0317:             * The argument is a HOST-PORT specification for the data port to be used in
0318:             * data connection. There are defaults for both the user and server data
0319:             * ports, and under normal circumstances this command and its reply are not
0320:             * needed. If this command is used, the argument is the concatenation of a
0321:             * 32-bit internet host address and a 16-bit TCP port address. This address
0322:             * information is broken into 8-bit fields and the value of each field is
0323:             * transmitted as a decimal number (in character string representation). The
0324:             * fields are separated by commas. A port command would be:
0325:             *
0326:             * PORT h1,h2,h3,h4,p1,p2
0327:             *
0328:             * where h1 is the high order 8 bits of the internet host address.
0329:             */
0330:            private Reply doPORT(BaseFtpConnection conn) {
0331:                FtpRequest request = conn.getRequest();
0332:                reset(conn);
0333:
0334:                InetAddress clientAddr = null;
0335:
0336:                // argument check
0337:                if (!request.hasArgument()) {
0338:                    //Syntax error in parameters or arguments
0339:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0340:                }
0341:
0342:                StringTokenizer st = new StringTokenizer(request.getArgument(),
0343:                        ",");
0344:
0345:                if (st.countTokens() != 6) {
0346:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0347:                }
0348:
0349:                // get data server
0350:                String dataSrvName = st.nextToken() + '.' + st.nextToken()
0351:                        + '.' + st.nextToken() + '.' + st.nextToken();
0352:
0353:                try {
0354:                    clientAddr = InetAddress.getByName(dataSrvName);
0355:                } catch (UnknownHostException ex) {
0356:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0357:                }
0358:
0359:                String portHostAddress = clientAddr.getHostAddress();
0360:                String clientHostAddress = conn.getControlSocket()
0361:                        .getInetAddress().getHostAddress();
0362:
0363:                if ((portHostAddress.startsWith("192.168.") && !clientHostAddress
0364:                        .startsWith("192.168."))
0365:                        || (portHostAddress.startsWith("10.") && !clientHostAddress
0366:                                .startsWith("10."))) {
0367:                    Reply response = new Reply(501);
0368:                    response.addComment("==YOU'RE BEHIND A NAT ROUTER==");
0369:                    response
0370:                            .addComment("Configure the firewall settings of your FTP client");
0371:                    response.addComment("  to use your real IP: "
0372:                            + conn.getControlSocket().getInetAddress()
0373:                                    .getHostAddress());
0374:                    response
0375:                            .addComment("And set up port forwarding in your router.");
0376:                    response
0377:                            .addComment("Or you can just use a PRET capable client, see");
0378:                    response
0379:                            .addComment("  http://drftpd.org/ for PRET capable clients");
0380:
0381:                    return response;
0382:                }
0383:
0384:                int clientPort;
0385:
0386:                // get data server port
0387:                try {
0388:                    int hi = Integer.parseInt(st.nextToken());
0389:                    int lo = Integer.parseInt(st.nextToken());
0390:                    clientPort = (hi << 8) | lo;
0391:                } catch (NumberFormatException ex) {
0392:                    reset(conn);
0393:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0394:
0395:                    //out.write(ftpStatus.getResponse(552, request, user, null));
0396:                }
0397:
0398:                _isPort = true;
0399:                _portAddress = new InetSocketAddress(clientAddr, clientPort);
0400:
0401:                if (portHostAddress.startsWith("127.")) {
0402:                    return new Reply(200,
0403:                            "Ok, but distributed transfers won't work with local addresses");
0404:                }
0405:
0406:                //Notify the user that this is not his IP.. Good for NAT users that
0407:                // aren't aware that their IP has changed.
0408:                if (!clientAddr
0409:                        .equals(conn.getControlSocket().getInetAddress())) {
0410:                    return new Reply(200,
0411:                            "FXP allowed. If you're not FXPing then set your IP to "
0412:                                    + conn.getControlSocket().getInetAddress()
0413:                                            .getHostAddress()
0414:                                    + " (usually in firewall settings)");
0415:                }
0416:
0417:                return Reply.RESPONSE_200_COMMAND_OK;
0418:            }
0419:
0420:            private Reply doPRET(BaseFtpConnection conn) {
0421:                reset(conn);
0422:
0423:                FtpRequest request = conn.getRequest();
0424:                FtpRequest ghostRequest = new FtpRequest(request.getArgument());
0425:                String cmd = ghostRequest.getCommand();
0426:
0427:                if (cmd.equals("LIST") || cmd.equals("NLST")
0428:                        || cmd.equals("MLSD")) {
0429:                    _preTransferRSlave = null;
0430:                    _preTransfer = true;
0431:
0432:                    return new Reply(200,
0433:                            "OK, will use master for upcoming transfer");
0434:                } else if (cmd.equals("RETR")) {
0435:                    try {
0436:                        LinkedRemoteFileInterface downFile = conn
0437:                                .getCurrentDirectory().lookupFile(
0438:                                        ghostRequest.getArgument());
0439:                        _preTransferRSlave = conn.getGlobalContext()
0440:                                .getSlaveSelectionManager().getASlave(
0441:                                        downFile.getAvailableSlaves(),
0442:                                        Transfer.TRANSFER_SENDING_DOWNLOAD,
0443:                                        conn, downFile);
0444:                        _preTransfer = true;
0445:
0446:                        return new Reply(200, "OK, will use "
0447:                                + _preTransferRSlave.getName()
0448:                                + " for upcoming transfer");
0449:                    } catch (NoAvailableSlaveException e) {
0450:                        return Reply.RESPONSE_530_SLAVE_UNAVAILABLE;
0451:                    } catch (FileNotFoundException e) {
0452:                        return Reply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN;
0453:                    }
0454:                } else if (cmd.equals("STOR")) {
0455:                    LinkedRemoteFile.NonExistingFile nef = conn
0456:                            .getCurrentDirectory().lookupNonExistingFile(
0457:                                    ghostRequest.getArgument());
0458:
0459:                    if (nef.exists()) {
0460:                        return Reply.RESPONSE_553_REQUESTED_ACTION_NOT_TAKEN_FILE_EXISTS;
0461:                    }
0462:
0463:                    if (!ListUtils.isLegalFileName(nef.getPath())) {
0464:                        return Reply.RESPONSE_553_REQUESTED_ACTION_NOT_TAKEN;
0465:                    }
0466:
0467:                    try {
0468:                        _preTransferRSlave = conn.getGlobalContext()
0469:                                .getSlaveSelectionManager().getASlave(
0470:                                        conn.getGlobalContext()
0471:                                                .getSlaveManager()
0472:                                                .getAvailableSlaves(),
0473:                                        Transfer.TRANSFER_RECEIVING_UPLOAD,
0474:                                        conn, nef.getFile());
0475:                        _preTransfer = true;
0476:
0477:                        return new Reply(200, "OK, will use "
0478:                                + _preTransferRSlave.getName()
0479:                                + " for upcoming transfer");
0480:                    } catch (NoAvailableSlaveException e) {
0481:                        return Reply.RESPONSE_530_SLAVE_UNAVAILABLE;
0482:                    }
0483:                } else {
0484:                    return Reply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM;
0485:                }
0486:            }
0487:
0488:            private Reply doSSCN(BaseFtpConnection conn) {
0489:                if (_ctx == null) {
0490:                    return new Reply(500, "TLS not configured");
0491:                }
0492:
0493:                if (!(conn.getControlSocket() instanceof  SSLSocket)) {
0494:                    return new Reply(500, "You are not on a secure channel");
0495:                }
0496:
0497:                if (!_encryptedDataChannel) {
0498:                    return new Reply(500,
0499:                            "SSCN only works for encrypted transfers");
0500:                }
0501:
0502:                if (conn.getRequest().hasArgument()) {
0503:                    if (conn.getRequest().getArgument().equalsIgnoreCase("ON")) {
0504:                        _SSLHandshakeClientMode = true;
0505:                    }
0506:                    if (conn.getRequest().getArgument().equalsIgnoreCase("OFF")) {
0507:                        _SSLHandshakeClientMode = false;
0508:                    }
0509:                }
0510:                return new Reply(220, "SSCN:"
0511:                        + (_SSLHandshakeClientMode ? "CLIENT" : "SERVER")
0512:                        + " METHOD");
0513:            }
0514:
0515:            private Reply doPROT(BaseFtpConnection conn)
0516:                    throws UnhandledCommandException {
0517:                if (_ctx == null) {
0518:                    return new Reply(500, "TLS not configured");
0519:                }
0520:
0521:                if (!(conn.getControlSocket() instanceof  SSLSocket)) {
0522:                    return new Reply(500, "You are not on a secure channel");
0523:                }
0524:
0525:                FtpRequest req = conn.getRequest();
0526:
0527:                if (!req.hasArgument()) {
0528:                    //clear
0529:                    _encryptedDataChannel = false;
0530:
0531:                    return Reply.RESPONSE_200_COMMAND_OK;
0532:                }
0533:
0534:                if (!req.hasArgument() || (req.getArgument().length() != 1)) {
0535:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0536:                }
0537:
0538:                switch (Character.toUpperCase(req.getArgument().charAt(0))) {
0539:                case 'C':
0540:
0541:                    //clear
0542:                    _encryptedDataChannel = false;
0543:
0544:                    return Reply.RESPONSE_200_COMMAND_OK;
0545:
0546:                case 'P':
0547:
0548:                    //private
0549:                    _encryptedDataChannel = true;
0550:
0551:                    return Reply.RESPONSE_200_COMMAND_OK;
0552:
0553:                default:
0554:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0555:                }
0556:            }
0557:
0558:            /**
0559:             * <code>REST &lt;SP&gt; <marker> &lt;CRLF&gt;</code><br>
0560:             *
0561:             * The argument field represents the server marker at which file transfer is
0562:             * to be restarted. This command does not cause file transfer but skips over
0563:             * the file to the specified data checkpoint. This command shall be
0564:             * immediately followed by the appropriate FTP service command which shall
0565:             * cause file transfer to resume.
0566:             */
0567:            private Reply doREST(BaseFtpConnection conn) {
0568:                FtpRequest request = conn.getRequest();
0569:
0570:                // argument check
0571:                if (!request.hasArgument()) {
0572:                    reset(conn);
0573:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0574:                }
0575:
0576:                String skipNum = request.getArgument();
0577:
0578:                try {
0579:                    _resumePosition = Long.parseLong(skipNum);
0580:                } catch (NumberFormatException ex) {
0581:                    reset(conn);
0582:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0583:                }
0584:
0585:                if (_resumePosition < 0) {
0586:                    _resumePosition = 0;
0587:                    reset(conn);
0588:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0589:                }
0590:
0591:                return Reply.RESPONSE_350_PENDING_FURTHER_INFORMATION;
0592:            }
0593:
0594:            private Reply doSITE_RESCAN(BaseFtpConnection conn) {
0595:                FtpRequest request = conn.getRequest();
0596:                boolean forceRescan = (request.hasArgument() && request
0597:                        .getArgument().equalsIgnoreCase("force"));
0598:                LinkedRemoteFileInterface directory = conn
0599:                        .getCurrentDirectory();
0600:                SFVFile sfv;
0601:
0602:                try {
0603:                    sfv = conn.getCurrentDirectory().lookupSFVFile();
0604:                } catch (Exception e) {
0605:                    return new Reply(200, "Error getting SFV File: "
0606:                            + e.getMessage());
0607:                }
0608:
0609:                PrintWriter out = conn.getControlWriter();
0610:
0611:                for (Iterator i = sfv.getEntries().entrySet().iterator(); i
0612:                        .hasNext();) {
0613:                    Map.Entry entry = (Map.Entry) i.next();
0614:                    String fileName = (String) entry.getKey();
0615:                    Long checkSum = (Long) entry.getValue();
0616:                    LinkedRemoteFileInterface file;
0617:
0618:                    try {
0619:                        file = directory.lookupFile(fileName);
0620:                    } catch (FileNotFoundException ex) {
0621:                        out.write("200- SFV: "
0622:                                + Checksum.formatChecksum(checkSum.longValue())
0623:                                + " SLAVE: " + fileName + " MISSING"
0624:                                + BaseFtpConnection.NEWLINE);
0625:
0626:                        continue;
0627:                    }
0628:
0629:                    String status;
0630:                    long fileCheckSum = 0;
0631:
0632:                    try {
0633:                        if (forceRescan) {
0634:                            fileCheckSum = file.getCheckSumFromSlave();
0635:                        } else {
0636:                            fileCheckSum = file.getCheckSum();
0637:                        }
0638:                    } catch (NoAvailableSlaveException e1) {
0639:                        out.println("200- " + fileName + "SFV: "
0640:                                + Checksum.formatChecksum(checkSum.longValue())
0641:                                + " SLAVE: OFFLINE");
0642:
0643:                        continue;
0644:                    } catch (IOException ex) {
0645:                        out.print("200- " + fileName + " SFV: "
0646:                                + Checksum.formatChecksum(checkSum.longValue())
0647:                                + " SLAVE: IO error: " + ex.getMessage());
0648:
0649:                        continue;
0650:                    }
0651:
0652:                    if (fileCheckSum == 0L) {
0653:                        status = "FAILED - failed to checksum file";
0654:                    } else if (checkSum.longValue() == fileCheckSum) {
0655:                        status = "OK";
0656:                    } else {
0657:                        status = "FAILED - checksum mismatch";
0658:                    }
0659:
0660:                    out.println("200- " + fileName + " SFV: "
0661:                            + Checksum.formatChecksum(checkSum.longValue())
0662:                            + " SLAVE: "
0663:                            + Checksum.formatChecksum(fileCheckSum) + " "
0664:                            + status);
0665:
0666:                    continue;
0667:                }
0668:
0669:                return Reply.RESPONSE_200_COMMAND_OK;
0670:            }
0671:
0672:            private Reply doSITE_XDUPE(BaseFtpConnection conn) {
0673:                return Reply.RESPONSE_502_COMMAND_NOT_IMPLEMENTED;
0674:
0675:                //		resetState();
0676:                //
0677:                //		if (!request.hasArgument()) {
0678:                //			if (this.xdupe == 0) {
0679:                //				out.println("200 Extended dupe mode is disabled.");
0680:                //			} else {
0681:                //				out.println(
0682:                //					"200 Extended dupe mode " + this.xdupe + " is enabled.");
0683:                //			}
0684:                //			return;
0685:                //		}
0686:                //
0687:                //		short myXdupe;
0688:                //		try {
0689:                //			myXdupe = Short.parseShort(request.getArgument());
0690:                //		} catch (NumberFormatException ex) {
0691:                //			out.print(FtpResponse.RESPONSE_501_SYNTAX_ERROR);
0692:                //			return;
0693:                //		}
0694:                //
0695:                //		if (myXdupe > 0 || myXdupe < 4) {
0696:                //			out.print(
0697:                //				FtpResponse.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM);
0698:                //			return;
0699:                //		}
0700:                //		this.xdupe = myXdupe;
0701:                //		out.println("200 Activated extended dupe mode " + myXdupe + ".");
0702:            }
0703:
0704:            /**
0705:             * <code>STRU &lt;SP&gt; &lt;structure-code&gt; &lt;CRLF&gt;</code><br>
0706:             *
0707:             * The argument is a single Telnet character code specifying file structure.
0708:             */
0709:            private Reply doSTRU(BaseFtpConnection conn) {
0710:                FtpRequest request = conn.getRequest();
0711:
0712:                // argument check
0713:                if (!request.hasArgument()) {
0714:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0715:                }
0716:
0717:                if (request.getArgument().equalsIgnoreCase("F")) {
0718:                    return Reply.RESPONSE_200_COMMAND_OK;
0719:                }
0720:
0721:                return Reply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM;
0722:            }
0723:
0724:            /**
0725:             * <code>SYST &lt;CRLF&gt;</code><br>
0726:             *
0727:             * This command is used to find out the type of operating system at the
0728:             * server.
0729:             */
0730:            private Reply doSYST(BaseFtpConnection conn) {
0731:                /*
0732:                 * String systemName = System.getProperty("os.name"); if(systemName ==
0733:                 * null) { systemName = "UNKNOWN"; } else { systemName =
0734:                 * systemName.toUpperCase(); systemName = systemName.replace(' ', '-'); }
0735:                 * String args[] = {systemName};
0736:                 */
0737:                return Reply.RESPONSE_215_SYSTEM_TYPE;
0738:
0739:                //String args[] = { "UNIX" };
0740:                //out.write(ftpStatus.getResponse(215, request, user, args));
0741:            }
0742:
0743:            /**
0744:             * <code>TYPE &lt;SP&gt; &lt;type-code&gt; &lt;CRLF&gt;</code><br>
0745:             *
0746:             * The argument specifies the representation type.
0747:             */
0748:            private Reply doTYPE(BaseFtpConnection conn) {
0749:                FtpRequest request = conn.getRequest();
0750:
0751:                // get type from argument
0752:                if (!request.hasArgument()) {
0753:                    return Reply.RESPONSE_501_SYNTAX_ERROR;
0754:                }
0755:
0756:                // set it
0757:                if (setType(request.getArgument().charAt(0))) {
0758:                    return Reply.RESPONSE_200_COMMAND_OK;
0759:                }
0760:
0761:                return Reply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM;
0762:            }
0763:
0764:            public Reply execute(BaseFtpConnection conn) throws ReplyException {
0765:                String cmd = conn.getRequest().getCommand();
0766:
0767:                if ("MODE".equals(cmd)) {
0768:                    return doMODE(conn);
0769:                }
0770:
0771:                if ("PASV".equals(cmd) || "CPSV".equals(cmd)) {
0772:                    return doPASVandCPSV(conn);
0773:                }
0774:
0775:                if ("PORT".equals(cmd)) {
0776:                    return doPORT(conn);
0777:                }
0778:
0779:                if ("PRET".equals(cmd)) {
0780:                    return doPRET(conn);
0781:                }
0782:
0783:                if ("REST".equals(cmd)) {
0784:                    return doREST(conn);
0785:                }
0786:
0787:                if ("RETR".equals(cmd) || "STOR".equals(cmd)
0788:                        || "APPE".equals(cmd)) {
0789:                    return transfer(conn);
0790:                }
0791:
0792:                if ("SITE RESCAN".equals(cmd)) {
0793:                    return doSITE_RESCAN(conn);
0794:                }
0795:
0796:                if ("SITE XDUPE".equals(cmd)) {
0797:                    return doSITE_XDUPE(conn);
0798:                }
0799:
0800:                if ("STRU".equals(cmd)) {
0801:                    return doSTRU(conn);
0802:                }
0803:
0804:                if ("SYST".equals(cmd)) {
0805:                    return doSYST(conn);
0806:                }
0807:
0808:                if ("TYPE".equals(cmd)) {
0809:                    return doTYPE(conn);
0810:                }
0811:
0812:                if ("AUTH".equals(cmd)) {
0813:                    return doAUTH(conn);
0814:                }
0815:
0816:                if ("PROT".equals(cmd)) {
0817:                    return doPROT(conn);
0818:                }
0819:
0820:                if ("PBSZ".equals(cmd)) {
0821:                    return doPBSZ(conn);
0822:                }
0823:
0824:                if ("SSCN".equals(cmd)) {
0825:                    return doSSCN(conn);
0826:                }
0827:
0828:                throw UnhandledCommandException.create(
0829:                        DataConnectionHandler.class, conn.getRequest());
0830:            }
0831:
0832:            /**
0833:             * Get the data socket.
0834:             *
0835:             * Used by LIST and NLST and MLST.
0836:             */
0837:            public Socket getDataSocket() throws IOException {
0838:                Socket dataSocket;
0839:
0840:                // get socket depending on the selection
0841:                if (isPort()) {
0842:                    try {
0843:                        ActiveConnection ac = new ActiveConnection(
0844:                                _encryptedDataChannel ? _ctx : null,
0845:                                _portAddress, _SSLHandshakeClientMode);
0846:                        dataSocket = ac.connect(0);
0847:                    } catch (IOException ex) {
0848:                        logger.warn("Error opening data socket", ex);
0849:                        dataSocket = null;
0850:                        throw ex;
0851:                    }
0852:                } else if (isPasv()) {
0853:                    try {
0854:                        dataSocket = _passiveConnection.connect(0);
0855:                    } finally {
0856:                        if (_passiveConnection != null) {
0857:                            _passiveConnection.abort();
0858:                            _passiveConnection = null;
0859:                        }
0860:                    }
0861:                } else {
0862:                    throw new IllegalStateException("Neither PASV nor PORT");
0863:                }
0864:                // Already done since we are using ActiveConnection and PasvConnection
0865:                /*        dataSocket.setSoTimeout(Connection.TIMEOUT); // 15 seconds timeout
0866:
0867:                 if (dataSocket instanceof SSLSocket) {
0868:                 SSLSocket ssldatasocket = (SSLSocket) dataSocket;
0869:                 ssldatasocket.setUseClientMode(false);
0870:                 ssldatasocket.startHandshake();
0871:                 }*/
0872:
0873:                return dataSocket;
0874:            }
0875:
0876:            public String[] getFeatReplies() {
0877:                if (_ctx != null) {
0878:                    return new String[] { "PRET", "AUTH SSL", "PBSZ", "CPSV",
0879:                            "SSCN" };
0880:                }
0881:
0882:                return new String[] { "PRET" };
0883:            }
0884:
0885:            public String getHelp(String cmd) {
0886:                ResourceBundle bundle = ResourceBundle
0887:                        .getBundle(DataConnectionHandler.class.getName());
0888:                if ("".equals(cmd))
0889:                    return bundle.getString("help.general") + "\n";
0890:                else if ("rescan".equals(cmd))
0891:                    return bundle.getString("help.rescan") + "\n";
0892:                else
0893:                    return "";
0894:            }
0895:
0896:            public RemoteSlave getTranferSlave() {
0897:                return _rslave;
0898:            }
0899:
0900:            public synchronized RemoteTransfer getTransfer()
0901:                    throws ObjectNotFoundException {
0902:                if (_transfer == null)
0903:                    throw new ObjectNotFoundException();
0904:                return _transfer;
0905:            }
0906:
0907:            public LinkedRemoteFileInterface getTransferFile() {
0908:                return _transferFile;
0909:            }
0910:
0911:            /**
0912:             * Get the user data type.
0913:             */
0914:            public char getType() {
0915:                return _type;
0916:            }
0917:
0918:            public CommandHandler initialize(BaseFtpConnection conn,
0919:                    CommandManager initializer) {
0920:                try {
0921:                    return (DataConnectionHandler) clone();
0922:                } catch (CloneNotSupportedException e) {
0923:                    throw new RuntimeException(e);
0924:                }
0925:            }
0926:
0927:            public boolean isEncryptedDataChannel() {
0928:                return _encryptedDataChannel;
0929:            }
0930:
0931:            /**
0932:             * Guarantes pre transfer is set up correctly.
0933:             */
0934:            public boolean isPasv() {
0935:                return _isPasv;
0936:            }
0937:
0938:            public boolean isPort() {
0939:                return _isPort;
0940:            }
0941:
0942:            public boolean isPreTransfer() {
0943:                return _preTransfer || isPasv();
0944:            }
0945:
0946:            public synchronized boolean isTransfering() {
0947:                return _transfer != null && _rslave != null
0948:                        && _transferFile != null;
0949:            }
0950:
0951:            public void load(CommandManagerFactory initializer) {
0952:            }
0953:
0954:            protected synchronized void reset(BaseFtpConnection conn) {
0955:                _rslave = null;
0956:                if (_transfer != null) {
0957:                    try {
0958:                        _transfer.abort("reset");
0959:                    } catch (Throwable t) {
0960:                        logger.debug(
0961:                                "reset failed to abort transfer on the slave",
0962:                                t);
0963:                    }
0964:                }
0965:                _transfer = null;
0966:                if (_transferFile != null) {
0967:                    if ((conn.getRequest().getCommand().equals("STOR") == true)
0968:                            && (_transferFile.getXfertime() == -1)) {
0969:
0970:                        // Transfer failed on STOR
0971:
0972:                        _transferFile.setXfertime(0);
0973:                    }
0974:                    _transferFile = null;
0975:                }
0976:                _preTransfer = false;
0977:                _preTransferRSlave = null;
0978:
0979:                if (_passiveConnection != null) { //isPasv() && _preTransferRSlave == null
0980:                    _passiveConnection.abort();
0981:                }
0982:
0983:                _isPasv = false;
0984:                _passiveConnection = null;
0985:                _isPort = false;
0986:                _resumePosition = 0;
0987:            }
0988:
0989:            /**
0990:             * Set the data type. Supported types are A (ascii) and I (binary).
0991:             *
0992:             * @return true if success
0993:             */
0994:            private boolean setType(char type) {
0995:                type = Character.toUpperCase(type);
0996:
0997:                if ((type != 'A') && (type != 'I')) {
0998:                    return false;
0999:                }
1000:
1001:                _type = type;
1002:
1003:                return true;
1004:            }
1005:
1006:            /**
1007:             * <code>STOU &lt;CRLF&gt;</code><br>
1008:             *
1009:             * This command behaves like STOR except that the resultant file is to be
1010:             * created in the current directory under a name unique to that directory.
1011:             * The 250 Transfer Started response must include the name generated.
1012:             */
1013:
1014:            //TODO STOU
1015:            /*
1016:             * public void doSTOU(FtpRequest request, PrintWriter out) {
1017:             *  // reset state variables resetState();
1018:             *  // get filenames String fileName =
1019:             * user.getVirtualDirectory().getAbsoluteName("ftp.dat"); String
1020:             * physicalName = user.getVirtualDirectory().getPhysicalName(fileName); File
1021:             * requestedFile = new File(physicalName); requestedFile =
1022:             * IoUtils.getUniqueFile(requestedFile); fileName =
1023:             * user.getVirtualDirectory().getVirtualName(requestedFile.getAbsolutePath());
1024:             * String args[] = {fileName};
1025:             *  // check permission
1026:             * if(!user.getVirtualDirectory().hasCreatePermission(fileName, false)) {
1027:             * out.write(ftpStatus.getResponse(550, request, user, null)); return; }
1028:             *  // now transfer file data out.print(FtpResponse.RESPONSE_150_OK);
1029:             * InputStream is = null; OutputStream os = null; try { Socket dataSoc =
1030:             * mDataConnection.getDataSocket(); if (dataSoc == null) {
1031:             * out.write(ftpStatus.getResponse(550, request, user, args)); return; }
1032:             *
1033:             *
1034:             * is = dataSoc.getInputStream(); os = user.getOutputStream( new
1035:             * FileOutputStream(requestedFile) );
1036:             *
1037:             * StreamConnector msc = new StreamConnector(is, os);
1038:             * msc.setMaxTransferRate(user.getMaxUploadRate()); msc.setObserver(this);
1039:             * msc.connect();
1040:             *
1041:             * if(msc.hasException()) { out.write(ftpStatus.getResponse(451, request,
1042:             * user, null)); return; } else {
1043:             * mConfig.getStatistics().setUpload(requestedFile, user,
1044:             * msc.getTransferredSize()); }
1045:             *
1046:             * out.write(ftpStatus.getResponse(226, request, user, null));
1047:             * mDataConnection.reset(); out.write(ftpStatus.getResponse(250, request,
1048:             * user, args)); } catch(IOException ex) {
1049:             * out.write(ftpStatus.getResponse(425, request, user, null)); } finally {
1050:             * IoUtils.close(is); IoUtils.close(os); mDataConnection.reset(); } }
1051:             */
1052:
1053:            /**
1054:             * <code>RETR &lt;SP&gt; &lt;pathname&gt; &lt;CRLF&gt;</code><br>
1055:             *
1056:             * This command causes the server-DTP to transfer a copy of the file,
1057:             * specified in the pathname, to the server- or user-DTP at the other end of
1058:             * the data connection. The status and contents of the file at the server
1059:             * site shall be unaffected.
1060:             *
1061:             * RETR 125, 150 (110) 226, 250 425, 426, 451 450, 550 500, 501, 421, 530
1062:             * <p>
1063:             * <code>STOR &lt;SP&gt; &lt;pathname&gt; &lt;CRLF&gt;</code><br>
1064:             *
1065:             * This command causes the server-DTP to accept the data transferred via the
1066:             * data connection and to store the data as a file at the server site. If
1067:             * the file specified in the pathname exists at the server site, then its
1068:             * contents shall be replaced by the data being transferred. A new file is
1069:             * created at the server site if the file specified in the pathname does not
1070:             * already exist.
1071:             *
1072:             * STOR 125, 150 (110) 226, 250 425, 426, 451, 551, 552 532, 450, 452, 553
1073:             * 500, 501, 421, 530
1074:             *
1075:             * ''zipscript?? renames bad uploads to .bad, how do we handle this with
1076:             * resumes?
1077:             */
1078:            //TODO add APPE support
1079:            private Reply transfer(BaseFtpConnection conn)
1080:                    throws ReplyException {
1081:                ReplacerEnvironment env = new ReplacerEnvironment();
1082:                if (!_encryptedDataChannel
1083:                        && conn.getGlobalContext().getConfig().checkPermission(
1084:                                "denydatauncrypted", conn.getUserNull())) {
1085:                    reset(conn);
1086:                    return new Reply(530, "USE SECURE DATA CONNECTION");
1087:                }
1088:
1089:                try {
1090:                    FtpRequest request = conn.getRequest();
1091:                    char direction = conn.getDirection();
1092:                    String cmd = conn.getRequest().getCommand();
1093:                    boolean isStor = cmd.equals("STOR");
1094:                    boolean isRetr = cmd.equals("RETR");
1095:                    boolean isAppe = cmd.equals("APPE");
1096:                    boolean isStou = cmd.equals("STOU");
1097:                    String eventType = isRetr ? "RETR" : "STOR";
1098:
1099:                    if (isAppe || isStou) {
1100:                        throw UnhandledCommandException.create(
1101:                                DataConnectionHandler.class, conn.getRequest());
1102:                    }
1103:
1104:                    // argument check
1105:                    if (!request.hasArgument()) {
1106:                        // reset(); already done in finally block
1107:                        return Reply.RESPONSE_501_SYNTAX_ERROR;
1108:                    }
1109:
1110:                    //          Checks maxsim up/down
1111:                    // _simup OR _simdown = 0, exempt
1112:                    int comparison = 0;
1113:                    int count = conn.transferCounter(direction);
1114:                    env.add("maxsim", count);
1115:
1116:                    if (direction == Transfer.TRANSFER_RECEIVING_UPLOAD) {
1117:                        comparison = conn.getUserNull().getMaxSimUp();
1118:                        env.add("direction", "upload");
1119:                    } else {
1120:                        comparison = conn.getUserNull().getMaxSimDown();
1121:                        env.add("direction", "download");
1122:                    }
1123:
1124:                    if (comparison != 0 && count >= comparison)
1125:                        return new Reply(550, conn.jprintf(
1126:                                DataConnectionHandler.class,
1127:                                "transfer.err.maxsim", env));
1128:
1129:                    // get filenames
1130:                    LinkedRemoteFileInterface targetDir;
1131:                    String targetFileName;
1132:
1133:                    if (isRetr) {
1134:                        try {
1135:                            _transferFile = conn.getCurrentDirectory()
1136:                                    .lookupFile(request.getArgument());
1137:
1138:                            if (!_transferFile.isFile()) {
1139:                                // reset(); already done in finally block
1140:                                return new Reply(550, "Not a plain file");
1141:                            }
1142:
1143:                            targetDir = _transferFile.getParentFileNull();
1144:                            targetFileName = _transferFile.getName();
1145:                        } catch (FileNotFoundException ex) {
1146:                            // reset(); already done in finally block
1147:                            return new Reply(550, ex.getMessage());
1148:                        }
1149:                    } else if (isStor) {
1150:                        LinkedRemoteFile.NonExistingFile ret = conn
1151:                                .getCurrentDirectory().lookupNonExistingFile(
1152:                                        conn.getGlobalContext().getConfig()
1153:                                                .getFileName(
1154:                                                        request.getArgument()));
1155:                        targetDir = ret.getFile();
1156:                        targetFileName = ret.getPath();
1157:
1158:                        if (ret.exists()) {
1159:                            // target exists, this could be overwrite or resume
1160:                            //TODO overwrite & resume files.
1161:                            // reset(); already done in finally block
1162:                            return Reply.RESPONSE_553_REQUESTED_ACTION_NOT_TAKEN_FILE_EXISTS;
1163:
1164:                            //_transferFile = targetDir;
1165:                            //targetDir = _transferFile.getParent();
1166:                            //if(_transfereFile.getOwner().equals(getUser().getUsername()))
1167:                            // {
1168:                            //	// allow overwrite/resume
1169:                            //}
1170:                            //if(directory.isDirectory()) {
1171:                            //	return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN;
1172:                            //}
1173:                        }
1174:
1175:                        if (!ListUtils.isLegalFileName(targetFileName)
1176:                                || !conn.getGlobalContext().getConfig()
1177:                                        .checkPathPermission("privpath",
1178:                                                conn.getUserNull(), targetDir,
1179:                                                true)) {
1180:                            // reset(); already done in finally block
1181:                            return new Reply(553,
1182:                                    "Requested action not taken. File name not allowed.");
1183:                        }
1184:
1185:                        //do our zipscript sfv checks
1186:                        String checkName = targetFileName.toLowerCase();
1187:                        ZipscriptConfig zsCfg = conn.getGlobalContext()
1188:                                .getZsConfig();
1189:                        boolean SfvFirstEnforcedPath = zsCfg
1190:                                .checkSfvFirstEnforcedPath(targetDir, conn
1191:                                        .getUserNull());
1192:                        try {
1193:                            SFVFile sfv;
1194:                            try {
1195:                                sfv = conn.getCurrentDirectory()
1196:                                        .lookupSFVFile();
1197:                            } catch (FileStillTransferringException e) {
1198:                                // I have no idea how to handle this
1199:                                return new Reply(400,
1200:                                        "SFVFile still transferring.");
1201:                            }
1202:                            if (checkName.endsWith(".sfv")
1203:                                    && !zsCfg.multiSfvAllowed()) {
1204:                                return new Reply(533,
1205:                                        "Requested action not taken. Multiple SFV files not allowed.");
1206:                            }
1207:                            if (SfvFirstEnforcedPath
1208:                                    && !zsCfg.checkAllowedExtension(checkName)) {
1209:                                // filename not explicitly permitted, check for sfv entry
1210:                                boolean allow = false;
1211:                                if (zsCfg.restrictSfvEnabled()) {
1212:                                    for (Iterator iter = sfv.getNames()
1213:                                            .iterator(); iter.hasNext();) {
1214:                                        String name = (String) iter.next();
1215:                                        if (name.toLowerCase()
1216:                                                .equals(checkName)) {
1217:                                            allow = true;
1218:                                            break;
1219:                                        }
1220:                                    }
1221:                                    if (!allow) {
1222:                                        return new Reply(533,
1223:                                                "Requested action not taken. File not found in sfv.");
1224:                                    }
1225:                                }
1226:                            }
1227:                        } catch (FileNotFoundException e1) {
1228:                            // no sfv found in dir 
1229:                            if (!zsCfg.checkAllowedExtension(checkName)
1230:                                    && SfvFirstEnforcedPath) {
1231:                                // filename not explicitly permitted
1232:                                // ForceSfvFirst is on, and file is in an enforced path.
1233:                                return new Reply(533,
1234:                                        "Requested action not taken. You must upload sfv first.");
1235:                            }
1236:                        } catch (IOException e1) {
1237:                            //error reading sfv, do nothing
1238:                        } catch (NoAvailableSlaveException e1) {
1239:                            //sfv not online, do nothing
1240:                        }
1241:                    } else {
1242:                        // reset(); already done in finally block
1243:                        throw UnhandledCommandException.create(
1244:                                DataConnectionHandler.class, request);
1245:                    }
1246:
1247:                    // check access
1248:                    if (!conn.getGlobalContext().getConfig()
1249:                            .checkPathPermission("privpath",
1250:                                    conn.getUserNull(), targetDir, true)) {
1251:                        // reset(); already done in finally block
1252:                        return new Reply(550, request.getArgument()
1253:                                + ": No such file");
1254:                    }
1255:
1256:                    switch (direction) {
1257:                    case Transfer.TRANSFER_SENDING_DOWNLOAD:
1258:
1259:                        if (!conn.getGlobalContext().getConfig()
1260:                                .checkPathPermission("download",
1261:                                        conn.getUserNull(), targetDir)) {
1262:                            // reset(); already done in finally block
1263:                            return Reply.RESPONSE_530_ACCESS_DENIED;
1264:                        }
1265:
1266:                        break;
1267:
1268:                    case Transfer.TRANSFER_RECEIVING_UPLOAD:
1269:
1270:                        if (!conn.getGlobalContext().getConfig()
1271:                                .checkPathPermission("upload",
1272:                                        conn.getUserNull(), targetDir)) {
1273:                            // reset(); already done in finally block
1274:                            return Reply.RESPONSE_530_ACCESS_DENIED;
1275:                        }
1276:
1277:                        break;
1278:
1279:                    default:
1280:                        // reset(); already done in finally block
1281:                        throw UnhandledCommandException.create(
1282:                                DataConnectionHandler.class, request);
1283:                    }
1284:
1285:                    //check credits
1286:                    if (isRetr) {
1287:                        if ((conn.getUserNull().getKeyedMap().getObjectFloat(
1288:                                UserManagement.RATIO) != 0)
1289:                                && (conn.getGlobalContext().getConfig()
1290:                                        .getCreditLossRatio(_transferFile,
1291:                                                conn.getUserNull()) != 0)
1292:                                && (conn.getUserNull().getCredits() < _transferFile
1293:                                        .length())) {
1294:                            // reset(); already done in finally block
1295:                            return new Reply(550, "Not enough credits.");
1296:                        }
1297:                    }
1298:
1299:                    //setup _rslave
1300:                    //if (isCpsv)
1301:                    if (isPasv()) {
1302:                        //				isPasv() means we're setup correctly
1303:                        //				if (!_preTransfer || _preTransferRSlave == null)
1304:                        //					return FtpReply.RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS;
1305:                        //check pretransfer
1306:                        if (isRetr
1307:                                && !_transferFile.getSlaves().contains(
1308:                                        _preTransferRSlave)) {
1309:                            // reset(); already done in finally block
1310:                            return Reply.RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS;
1311:                        }
1312:
1313:                        _rslave = _preTransferRSlave;
1314:
1315:                        //_preTransferRSlave = null;
1316:                        //_preTransfer = false;
1317:                        //code above to be handled by reset()
1318:                    } else {
1319:                        try {
1320:                            if (direction == Transfer.TRANSFER_SENDING_DOWNLOAD) {
1321:                                _rslave = conn
1322:                                        .getGlobalContext()
1323:                                        .getSlaveSelectionManager()
1324:                                        .getASlave(
1325:                                                _transferFile
1326:                                                        .getAvailableSlaves(),
1327:                                                Transfer.TRANSFER_SENDING_DOWNLOAD,
1328:                                                conn, _transferFile);
1329:                            } else if (direction == Transfer.TRANSFER_RECEIVING_UPLOAD) {
1330:                                _rslave = conn
1331:                                        .getGlobalContext()
1332:                                        .getSlaveSelectionManager()
1333:                                        .getASlave(
1334:                                                conn.getGlobalContext()
1335:                                                        .getSlaveManager()
1336:                                                        .getAvailableSlaves(),
1337:                                                Transfer.TRANSFER_RECEIVING_UPLOAD,
1338:                                                conn, targetDir);
1339:                            } else {
1340:                                // reset(); already done in finally block
1341:                                throw new RuntimeException();
1342:                            }
1343:                        } catch (NoAvailableSlaveException ex) {
1344:                            //TODO Might not be good to 450 reply always
1345:                            //from rfc: 450 Requested file action not taken. File unavailable (e.g., file busy).
1346:                            // reset(); already done in finally block
1347:                            throw new ReplySlaveUnavailableException(ex, 450);
1348:                        }
1349:                    }
1350:
1351:                    if (isStor) {
1352:                        //setup upload
1353:                        if (_rslave == null) {
1354:                            // reset(); already done in finally block
1355:                            throw new NullPointerException();
1356:                        }
1357:
1358:                        List rslaves = Collections.singletonList(_rslave);
1359:                        StaticRemoteFile uploadFile = new StaticRemoteFile(
1360:                                rslaves, targetFileName, conn.getUserNull()
1361:                                        .getName(), conn.getUserNull()
1362:                                        .getGroup(), 0L, System
1363:                                        .currentTimeMillis(), 0L);
1364:                        synchronized (this ) {
1365:                            uploadFile.setXfertime(-1); // used for new files to be
1366:                            // uploaded, see getXfertime()
1367:                            _transferFile = targetDir.addFile(uploadFile);
1368:                        }
1369:                    }
1370:
1371:                    // setup _transfer
1372:
1373:                    if (isPort()) {
1374:                        try {
1375:                            String index = _rslave.issueConnectToSlave(
1376:                                    _portAddress.getAddress().getHostAddress(),
1377:                                    _portAddress.getPort(),
1378:                                    _encryptedDataChannel,
1379:                                    _SSLHandshakeClientMode);
1380:                            ConnectInfo ci = _rslave
1381:                                    .fetchTransferResponseFromIndex(index);
1382:                            synchronized (this ) {
1383:                                _transfer = _rslave.getTransfer(ci
1384:                                        .getTransferIndex());
1385:                            }
1386:                        } catch (Exception ex) {
1387:                            logger.fatal("rslave=" + _rslave, ex);
1388:                            // reset(); already done in finally block
1389:                            return new Reply(450, ex.getClass().getName()
1390:                                    + " from slave: " + ex.getMessage());
1391:                        }
1392:                    } else if (isPasv()) {
1393:                        //_transfer is already set up by doPASV()
1394:                    } else {
1395:                        // reset(); already done in finally block
1396:                        if (isStor) {
1397:                            _transferFile.delete();
1398:                        }
1399:                        return Reply.RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS;
1400:                    }
1401:
1402:                    {
1403:                        PrintWriter out = conn.getControlWriter();
1404:                        out.write(new Reply(150,
1405:                                "File status okay; about to open data connection "
1406:                                        + (isRetr ? "from " : "to ")
1407:                                        + _rslave.getName() + ".").toString());
1408:                        out.flush();
1409:                    }
1410:
1411:                    TransferStatus status = null;
1412:
1413:                    //transfer
1414:                    try {
1415:                        //TODO ABORtable transfers
1416:                        if (isRetr) {
1417:                            _transfer.sendFile(_transferFile.getPath(),
1418:                                    getType(), _resumePosition);
1419:
1420:                            while (true) {
1421:                                status = _transfer.getTransferStatus();
1422:
1423:                                if (status.isFinished()) {
1424:                                    break;
1425:                                }
1426:
1427:                                try {
1428:                                    Thread.sleep(100);
1429:                                } catch (InterruptedException e1) {
1430:                                }
1431:                            }
1432:                        } else if (isStor) {
1433:                            _transfer.receiveFile(_transferFile.getPath(),
1434:                                    getType(), _resumePosition);
1435:
1436:                            while (true) {
1437:                                status = _transfer.getTransferStatus();
1438:                                _transferFile.setLength(status.getTransfered());
1439:                                if (status.isFinished()) {
1440:                                    break;
1441:                                }
1442:                                try {
1443:                                    Thread.sleep(100);
1444:                                } catch (InterruptedException e1) {
1445:                                }
1446:                            }
1447:                        } else {
1448:                            throw new RuntimeException();
1449:                        }
1450:                    } catch (IOException ex) {
1451:                        logger.debug("", ex);
1452:                        if (ex instanceof  TransferFailedException) {
1453:                            // the below chunk makes no sense, we don't process it anywhere
1454:                            /*                    status = ((TransferFailedException) ex).getStatus();
1455:                             conn.getGlobalContext()
1456:                             .dispatchFtpEvent(new TransferEvent(conn, eventType,
1457:                             _transferFile, conn.getClientAddress(), _rslave,
1458:                             _transfer.getAddress().getAddress(), _type, false));
1459:                             */
1460:                            if (isRetr) {
1461:                                conn.getUserNull().updateCredits(
1462:                                        -status.getTransfered());
1463:                            }
1464:                        }
1465:
1466:                        Reply reply = null;
1467:
1468:                        if (isStor) {
1469:                            _transferFile.delete();
1470:                            logger
1471:                                    .error(
1472:                                            "IOException during transfer, deleting file",
1473:                                            ex);
1474:                            reply = new Reply(426,
1475:                                    "Transfer failed, deleting file");
1476:                        } else {
1477:                            logger.error("IOException during transfer", ex);
1478:                            reply = new Reply(426, ex.getMessage());
1479:                        }
1480:
1481:                        reply.addComment(ex.getMessage());
1482:                        // reset(); already done in finally block
1483:                        return reply;
1484:                    } catch (SlaveUnavailableException e) {
1485:                        logger.debug("", e);
1486:                        Reply reply = null;
1487:
1488:                        if (isStor) {
1489:                            _transferFile.delete();
1490:                            logger
1491:                                    .error(
1492:                                            "Slave went offline during transfer, deleting file",
1493:                                            e);
1494:                            reply = new Reply(426,
1495:                                    "Slave went offline during transfer, deleting file");
1496:                        } else {
1497:                            logger.error("Slave went offline during transfer",
1498:                                    e);
1499:                            reply = new Reply(426,
1500:                                    "Slave went offline during transfer");
1501:                        }
1502:
1503:                        reply.addComment(e.getLocalizedMessage());
1504:                        // reset(); already done in finally block
1505:                        return reply;
1506:                    }
1507:
1508:                    //		TransferThread transferThread = new TransferThread(rslave,
1509:                    // transfer);
1510:                    //		System.err.println("Calling interruptibleSleepUntilFinished");
1511:                    //		try {
1512:                    //			transferThread.interruptibleSleepUntilFinished();
1513:                    //		} catch (Throwable e1) {
1514:                    //			e1.printStackTrace();
1515:                    //		}
1516:                    //		System.err.println("Finished");
1517:                    env = new ReplacerEnvironment();
1518:                    env.add("bytes", Bytes.formatBytes(status.getTransfered()));
1519:                    env.add("speed", Bytes.formatBytes(status.getXferSpeed())
1520:                            + "/s");
1521:                    env.add("seconds", ""
1522:                            + ((float) status.getElapsed() / 1000F));
1523:                    env.add("checksum", Checksum.formatChecksum(status
1524:                            .getChecksum()));
1525:
1526:                    Reply response = new Reply(226, conn.jprintf(
1527:                            DataConnectionHandler.class, "transfer.complete",
1528:                            env));
1529:                    synchronized (conn.getGlobalContext()) { // need to synchronize
1530:                        // here so only one
1531:                        // TransferEvent can be sent at a time
1532:                        if (isStor) {
1533:                            if (_resumePosition == 0) {
1534:                                _transferFile.setCheckSum(status.getChecksum());
1535:                            } else {
1536:                                // try {
1537:                                // checksum = _transferFile.getCheckSumFromSlave();
1538:                                // } catch (NoAvailableSlaveException e) {
1539:                                // response.addComment(
1540:                                // "No available slaves when getting checksum from
1541:                                // slave: "
1542:                                // + e.getMessage());
1543:                                // logger.warn("", e);
1544:                                // checksum = 0;
1545:                                // } catch (IOException e) {
1546:                                // response.addComment(
1547:                                // "IO error getting checksum from slave: "
1548:                                // + e.getMessage());
1549:                                // logger.warn("", e);
1550:                                // checksum = 0;
1551:                                // }
1552:                            }
1553:
1554:                            _transferFile.setLastModified(System
1555:                                    .currentTimeMillis());
1556:                            _transferFile.setLength(status.getTransfered());
1557:                            _transferFile.setXfertime(status.getElapsed());
1558:                        }
1559:
1560:                        boolean zipscript = zipscript(isRetr, isStor, status
1561:                                .getChecksum(), response, targetFileName,
1562:                                targetDir);
1563:
1564:                        if (zipscript) {
1565:                            // transferstatistics
1566:                            if (isRetr) {
1567:
1568:                                float ratio = conn.getGlobalContext()
1569:                                        .getConfig().getCreditLossRatio(
1570:                                                _transferFile,
1571:                                                conn.getUserNull());
1572:
1573:                                if (ratio != 0) {
1574:                                    conn
1575:                                            .getUserNull()
1576:                                            .updateCredits(
1577:                                                    (long) (-status
1578:                                                            .getTransfered() * ratio));
1579:                                }
1580:
1581:                                if (!conn.getGlobalContext().getConfig()
1582:                                        .checkPathPermission("nostatsdn",
1583:                                                conn.getUserNull(),
1584:                                                conn.getCurrentDirectory())) {
1585:                                    conn.getUserNull().updateDownloadedBytes(
1586:                                            status.getTransfered());
1587:                                    conn.getUserNull().updateDownloadedTime(
1588:                                            status.getElapsed());
1589:                                    conn.getUserNull().updateDownloadedFiles(1);
1590:                                }
1591:                            } else {
1592:
1593:                                conn.getUserNull().updateCredits(
1594:                                        (long) (status.getTransfered() * conn
1595:                                                .getGlobalContext().getConfig()
1596:                                                .getCreditCheckRatio(
1597:                                                        _transferFile,
1598:                                                        conn.getUserNull())));
1599:                                if (!conn.getGlobalContext().getConfig()
1600:                                        .checkPathPermission("nostatsup",
1601:                                                conn.getUserNull(),
1602:                                                conn.getCurrentDirectory())) {
1603:                                    conn.getUserNull().updateUploadedBytes(
1604:                                            status.getTransfered());
1605:                                    conn.getUserNull().updateUploadedTime(
1606:                                            status.getElapsed());
1607:                                    conn.getUserNull().updateUploadedFiles(1);
1608:                                }
1609:                            }
1610:
1611:                            try {
1612:                                conn.getUserNull().commit();
1613:                            } catch (UserFileException e) {
1614:                                logger.warn("", e);
1615:                            }
1616:                        }
1617:
1618:                        // Dispatch for both STOR and RETR
1619:                        conn.getGlobalContext().dispatchFtpEvent(
1620:                                new TransferEvent(conn, eventType,
1621:                                        _transferFile, conn.getClientAddress(),
1622:                                        _rslave, _transfer.getAddress()
1623:                                                .getAddress(), getType()));
1624:                        return response;
1625:                    }
1626:                } finally {
1627:                    reset(conn);
1628:                }
1629:            }
1630:
1631:            public void unload() {
1632:            }
1633:
1634:            /**
1635:             * @param isRetr
1636:             * @param isStor
1637:             * @param status
1638:             * @param response
1639:             * @param targetFileName
1640:             * @param targetDir
1641:             *            Returns true if crc check was okay, i.e, if credits should be
1642:             *            altered
1643:             */
1644:            private boolean zipscript(boolean isRetr, boolean isStor,
1645:                    long checksum, Reply response, String targetFileName,
1646:                    LinkedRemoteFileInterface targetDir) {
1647:                // zipscript
1648:                logger.debug("Running zipscript on file " + targetFileName
1649:                        + " with CRC of " + checksum);
1650:
1651:                if (isRetr) {
1652:                    //compare checksum from transfer to cached checksum
1653:                    logger.debug("checksum from transfer = " + checksum);
1654:
1655:                    if (checksum != 0) {
1656:                        response.addComment("Checksum from transfer: "
1657:                                + Checksum.formatChecksum(checksum));
1658:
1659:                        long cachedChecksum;
1660:                        cachedChecksum = _transferFile.getCheckSumCached();
1661:
1662:                        if (cachedChecksum == 0) {
1663:                            _transferFile.setCheckSum(checksum);
1664:                        } else if (cachedChecksum != checksum) {
1665:                            response
1666:                                    .addComment("WARNING: checksum from transfer didn't match cached checksum");
1667:                            logger.info("checksum from transfer "
1668:                                    + Checksum.formatChecksum(checksum)
1669:                                    + "didn't match cached checksum"
1670:                                    + Checksum.formatChecksum(cachedChecksum)
1671:                                    + " for " + _transferFile.toString()
1672:                                    + " from slave " + _rslave.getName(),
1673:                                    new Throwable());
1674:                        }
1675:
1676:                        //compare checksum from transfer to checksum from sfv
1677:                        try {
1678:                            long sfvChecksum;
1679:                            try {
1680:                                sfvChecksum = _transferFile.getParentFileNull()
1681:                                        .lookupSFVFile().getChecksum(
1682:                                                _transferFile.getName());
1683:                                if (sfvChecksum == checksum) {
1684:                                    response
1685:                                            .addComment("checksum from transfer matched checksum in .sfv");
1686:                                } else {
1687:                                    response
1688:                                            .addComment("WARNING: checksum from transfer didn't match checksum in .sfv");
1689:                                }
1690:                            } catch (FileStillTransferringException e) {
1691:                                response
1692:                                        .addComment("checksum from sfv doesn't exist yet, SFVFile is being uploaded");
1693:                            }
1694:                        } catch (NoAvailableSlaveException e1) {
1695:                            response
1696:                                    .addComment("slave with .sfv offline, checksum not verified");
1697:                        } catch (FileNotFoundException e1) {
1698:                            //continue without verification
1699:                        } catch (NoSFVEntryException e1) {
1700:                            //file not found in .sfv, continue
1701:                        } catch (IOException e1) {
1702:                            logger.info("", e1);
1703:                            response.addComment("IO Error reading sfv file: "
1704:                                    + e1.getMessage());
1705:                        }
1706:                    } else { // slave has disabled download crc
1707:
1708:                        //response.addComment("Slave has disabled download checksum");
1709:                    }
1710:                } else if (isStor) {
1711:                    if (!targetFileName.toLowerCase().endsWith(".sfv")) {
1712:                        try {
1713:                            long sfvChecksum;
1714:                            try {
1715:                                sfvChecksum = targetDir.lookupSFVFile()
1716:                                        .getChecksum(targetFileName);
1717:                                if (checksum == sfvChecksum) {
1718:                                    response
1719:                                            .addComment("checksum match: SLAVE/SFV:"
1720:                                                    + Long
1721:                                                            .toHexString(checksum));
1722:                                } else if (checksum == 0) {
1723:                                    response
1724:                                            .addComment("checksum match: SLAVE/SFV: DISABLED");
1725:                                } else {
1726:                                    response
1727:                                            .addComment("checksum mismatch: SLAVE: "
1728:                                                    + Long
1729:                                                            .toHexString(checksum)
1730:                                                    + " SFV: "
1731:                                                    + Long
1732:                                                            .toHexString(sfvChecksum));
1733:                                    response.addComment(" deleting file");
1734:                                    response
1735:                                            .setMessage("Checksum mismatch, deleting file");
1736:                                    _transferFile.delete();
1737:
1738:                                    //				getUser().updateCredits(
1739:                                    //					- ((long) getUser().getRatio() * transferedBytes));
1740:                                    //				getUser().updateUploadedBytes(-transferedBytes);
1741:                                    // response.addComment(conn.status());
1742:                                    return false; // don't modify credits
1743:
1744:                                    //				String badtargetFilename = targetFilename + ".bad";
1745:                                    //
1746:                                    //				try {
1747:                                    //					LinkedRemoteFile badtargetFile =
1748:                                    //						targetDir.getFile(badtargetFilename);
1749:                                    //					badtargetFile.delete();
1750:                                    //					response.addComment(
1751:                                    //						"zipscript - removing "
1752:                                    //							+ badtargetFilename
1753:                                    //							+ " to be replaced with new file");
1754:                                    //				} catch (FileNotFoundException e2) {
1755:                                    //					//good, continue...
1756:                                    //					response.addComment(
1757:                                    //						"zipscript - checksum mismatch, renaming to "
1758:                                    //							+ badtargetFilename);
1759:                                    //				}
1760:                                    //				targetFile.renameTo(targetDir.getPath() +
1761:                                    // badtargetFilename);
1762:                                }
1763:                            } catch (FileStillTransferringException e) {
1764:                                response
1765:                                        .addComment("No sfv to compare to (SFVTransferring), file allowed");
1766:                            }
1767:                        } catch (NoAvailableSlaveException e) {
1768:                            response
1769:                                    .addComment("zipscript - SFV unavailable, slave(s) with .sfv file is offline");
1770:                        } catch (NoSFVEntryException e) {
1771:                            response
1772:                                    .addComment("zipscript - no entry in sfv for file");
1773:                        } catch (IOException e) {
1774:                            response
1775:                                    .addComment("zipscript - SFV unavailable, IO error: "
1776:                                            + e.getMessage());
1777:                        }
1778:                    }
1779:                }
1780:
1781:                return true; // modify credits, transfer was okay
1782:            }
1783:
1784:            public synchronized void handshakeCompleted(
1785:                    HandshakeCompletedEvent arg0) {
1786:                _handshakeCompleted = true;
1787:                notifyAll();
1788:            }
1789:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.