View Javadoc

1   /**
2    * This file is part of Waarp Project.
3    * 
4    * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
5    * COPYRIGHT.txt in the distribution for a full listing of individual contributors.
6    * 
7    * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
8    * the GNU General Public License as published by the Free Software Foundation, either version 3 of
9    * the License, or (at your option) any later version.
10   * 
11   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
12   * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13   * Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License along with Waarp . If not, see
16   * <http://www.gnu.org/licenses/>.
17   */
18  package org.waarp.ftp.core.control;
19  
20  import io.netty.channel.Channel;
21  import org.waarp.common.command.exception.CommandAbstractException;
22  import org.waarp.common.file.Restart;
23  import org.waarp.common.file.filesystembased.FilesystemBasedOptsMLSxImpl;
24  import org.waarp.ftp.core.command.AbstractCommand;
25  import org.waarp.ftp.core.command.FtpCommandCode;
26  import org.waarp.ftp.core.data.FtpTransfer;
27  import org.waarp.ftp.core.file.FtpAuth;
28  import org.waarp.ftp.core.file.FtpDir;
29  import org.waarp.ftp.core.session.FtpSession;
30  
31  /**
32   * This class is to be implemented in order to allow Business actions according to FTP service
33   * 
34   * @author Frederic Bregier
35   * 
36   */
37  public abstract class BusinessHandler {
38      /**
39       * NettyHandler that holds this BusinessHandler
40       */
41      private NetworkHandler networkHandler = null;
42  
43      /**
44       * FtpSession
45       */
46      private FtpSession session = null;
47  
48      /**
49       * Constructor with no argument (mandatory)
50       */
51      public BusinessHandler() {
52          // nothing to do
53      }
54  
55      /**
56       * Called when the NetworkHandler is created
57       * 
58       * @param networkHandler
59       *            the networkHandler to set
60       */
61      public void setNetworkHandler(NetworkHandler networkHandler) {
62          this.networkHandler = networkHandler;
63          session = this.networkHandler.getFtpSession();
64      }
65  
66      /**
67       * @return the networkHandler
68       */
69      public NetworkHandler getNetworkHandler() {
70          return networkHandler;
71      }
72  
73      // Some helpful functions
74      /**
75       * 
76       * @return the ftpSession
77       */
78      public FtpSession getFtpSession() {
79          return session;
80      }
81  
82      /**
83       * Create a new AuthInterface according to business choice
84       * 
85       * @return the new FtpAuth
86       */
87      public abstract FtpAuth getBusinessNewAuth();
88  
89      /**
90       * Create a new FtpDir according to business choice
91       * 
92       * @return the new FtpDir
93       */
94      public abstract FtpDir getBusinessNewDir();
95  
96      /**
97       * Create a new Restart according to business choice
98       * 
99       * @return the new Restart
100      */
101     public abstract Restart getBusinessNewRestart();
102 
103     /**
104      * 
105      * @param arg
106      *            the argument from HELP command
107      * @return the string to return to the client for the HELP command
108      */
109     public abstract String getHelpMessage(String arg);
110 
111     /**
112      * 
113      * @return the string to return to the client for the FEAT command
114      */
115     public abstract String getFeatMessage();
116 
117     protected String getSslFeatMessage() {
118         StringBuilder builder = new StringBuilder().append("AUTH TLS\n").append("AUTH SSL\n")
119                 .append("CCC\n").append("PROT P\n").append("PROT C");
120         return builder.toString();
121     }
122 
123     /**
124      * 
125      * @return the string to return to the client for the FEAT command without surrounding by
126      *         "Extensions supported:\n" and "\nEnd"
127      */
128     protected String getDefaultFeatMessage() {
129         StringBuilder builder = new StringBuilder();
130         builder.append(FtpCommandCode.MDTM.name()).append('\n')
131                 .append(FtpCommandCode.MLSD.name()).append(getFtpSession().getDir().getOptsMLSx().getFeat())
132                 .append('\n')
133                 .append(FtpCommandCode.MLST.name()).append(getFtpSession().getDir().getOptsMLSx().getFeat())
134                 .append('\n')
135                 .append(FtpCommandCode.SIZE.name()).append('\n')
136                 .append(FtpCommandCode.XCUP.name()).append('\n')
137                 .append(FtpCommandCode.XCWD.name()).append('\n')
138                 .append(FtpCommandCode.XMKD.name()).append('\n')
139                 .append(FtpCommandCode.XPWD.name()).append('\n')
140                 .append(FtpCommandCode.XRMD.name()).append('\n')
141                 .append(FtpCommandCode.PASV.name()).append('\n')
142                 .append(FtpCommandCode.ALLO.name()).append('\n')
143                 .append(FtpCommandCode.EPRT.name()).append('\n')
144                 .append(FtpCommandCode.EPSV.name()).append('\n')
145                 .append(FtpCommandCode.XCRC.name()).append(" \"filename\"").append('\n')
146                 .append(FtpCommandCode.XMD5.name()).append(" \"filename\"").append('\n')
147                 .append(FtpCommandCode.XSHA1.name()).append(" \"filename\"").append('\n')
148                 .append(FtpCommandCode.SITE.name()).append(' ').append(FtpCommandCode.XCRC.name())
149                 // .append(" \"filename\"")
150                 .append('\n')
151                 .append(FtpCommandCode.SITE.name()).append(' ').append(FtpCommandCode.XMD5.name())
152                 // .append(" \"filename\"")
153                 .append('\n')
154                 .append(FtpCommandCode.SITE.name()).append(' ').append(FtpCommandCode.XSHA1.name())
155                 // .append(" \"filename\"")
156                 .append('\n')
157                 .append("LAN EN*").append('\n')
158                 .append(FtpCommandCode.REST.name()).append(" STREAM\n");
159         //builder.append("UTF8");
160         return builder.toString();
161     }
162 
163     /**
164      * @param args
165      * @return the string to return to the client for the FEAT command
166      * @exception CommandAbstractException
167      */
168     public abstract String getOptsMessage(String[] args)
169             throws CommandAbstractException;
170 
171     /**
172      * Check if a command pass to SITE command is legal
173      * 
174      * @param session
175      * @param line
176      * @return the AbstractCommand to execute if it is a Specialized Command, else Null
177      */
178     public abstract AbstractCommand getSpecializedSiteCommand(FtpSession session, String line);
179 
180     /**
181      * 
182      * @param args
183      * @return the string to return to the client for the FEAT command for the MLSx argument
184      */
185     protected String getMLSxOptsMessage(String[] args) {
186         String[] properties = new String[0];
187         if (args.length >= 2) {
188             properties = args[1].split(";");
189         }
190 
191         FilesystemBasedOptsMLSxImpl optsMLSx = (FilesystemBasedOptsMLSxImpl) getFtpSession()
192                 .getDir().getOptsMLSx();
193         optsMLSx.setOptsModify((byte) 0);
194         optsMLSx.setOptsPerm((byte) 0);
195         optsMLSx.setOptsSize((byte) 0);
196         optsMLSx.setOptsType((byte) 0);
197         for (int i = 0; i < properties.length; i++) {
198             if (properties[i].toLowerCase() == "modify") {
199                 optsMLSx.setOptsModify((byte) 1);
200             }            else if (properties[i].toLowerCase() == "perm") {
201                 optsMLSx.setOptsPerm((byte) 1);
202             }            else if (properties[i].toLowerCase() == "size") {
203                 optsMLSx.setOptsSize((byte) 1);
204             }            else if (properties[i].toLowerCase() == "type") {
205                 optsMLSx.setOptsType((byte) 1);
206             }        
207         }
208         return args[0] + " " + FtpCommandCode.OPTS.name() + optsMLSx.getFeat();
209     }
210 
211     /**
212      * Is executed when the channel is closed, just before cleaning and just after.<br>
213      * <I>Note: In some circumstances, it could be a good idea to call the clean operation on
214      * FtpAuth in order to relax constraints on user authentication. It will be called however at
215      * least when the session will be clean just after this call.</I>
216      */
217     public abstract void executeChannelClosed();
218 
219     /**
220      * To Clean the session attached objects
221      */
222     protected abstract void cleanSession();
223 
224     /**
225      * Clean the BusinessHandler.
226      * 
227      */
228     public void clear() {
229         cleanSession();
230     }
231 
232     /**
233      * Is executed when the channel is connected after the handler is on, before answering OK or not
234      * on connection, except if the global service is going to shutdown.
235      * 
236      * @param channel
237      */
238     public abstract void executeChannelConnected(Channel channel);
239 
240     /**
241      * Run when an exception is get before the channel is closed. This must set a correct answer.
242      * 
243      * @param e
244      */
245     public abstract void exceptionLocalCaught(Throwable e);
246 
247     /**
248      * This method is called for every received message before the execution of the command. If an
249      * exception is raised, the reply is immediate and no action taken.
250      * 
251      * @exception CommandAbstractException
252      */
253     public abstract void beforeRunCommand() throws CommandAbstractException;
254 
255     /**
256      * This method is called for every received message after the execution of the command but
257      * before the final reply to the client. If an exception is raised, the reply is immediate. This
258      * is the last call before finishing the command.
259      * 
260      * @exception CommandAbstractException
261      */
262     public abstract void afterRunCommandOk() throws CommandAbstractException;
263 
264     /**
265      * Run when a FTP exception is catch (the channel is not necessary closed after). This must set
266      * a correct answer and a correct code of reply. If the code of reply is 421, then the channel
267      * will be closed after this call. This is the last call before finishing the command.
268      * 
269      * @param e
270      */
271     public abstract void afterRunCommandKo(CommandAbstractException e);
272 
273     /**
274      * Run when a transfer is finished (eventually in error) but before answering. Note that this is
275      * called only for a Transfer Request (or LIST) but called before afterRunCommandXX is called
276      * (Ok or Ko).
277      * 
278      * @param transfer
279      * @exception CommandAbstractException
280      */
281     public abstract void afterTransferDoneBeforeAnswer(FtpTransfer transfer)
282             throws CommandAbstractException;
283 }