You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ftpserver-users@mina.apache.org by "Zhu, Yan-Bo (TSG-GDCC-CD)" <ya...@hp.com> on 2009/10/21 07:38:10 UTC

implement a ftplet to limit the size of upload files

Hi,

I need to limit the size of upload files ,are there any good suggestions?
Is implementing a ftplet possible to do this?

Thanks for the help!
Bob Zhu

RE: implement a ftplet to limit the size of upload files

Posted by "Zhu, Yan-Bo (TSG-GDCC-CD)" <ya...@hp.com>.
It's really useful for me. thanks.
-- awaitUninterruptibly : it makes sure the 150 150_FILE_STATUS_OKAY command is sent before proceeding.
So, if 150 command is not sent before proceeding , is it a matter?

Thanks ,Bob Zhu 
---------------
>>
>>
I think your code is OK  except for  a  problem:
 - Restarting a failed transfer would mean that the user can safely
ignore your limit. To solve this, you could take into account the
skipLen value in order to prevent users from circumventing your
limits.


  The pieces of code you didn't understand:
  -- First block:              // 24-10-2007 - added check if PORT or
PASV is issued, see
//            // https://issues.apache.org/jira/browse/FTPSERVER-110

This block checks if a PORT or PASV command was issued previously. In
FTP, you must send a PORT or PASV command before any command that
sends data (stor, retr, mlsd etc.).

 -- awaitUninterruptibly : it makes sure the 150 150_FILE_STATUS_OKAY
command is sent before proceeding.
 --ServerFtpStatistics: this component keeps statistics of the
FTPServer usage. If you don't know it, you probably don't need it.
Still, I think your code doesn't break it in any way.



 2009/10/21 Zhu, Yan-Bo (TSG-GDCC-CD) <ya...@hp.com>:
> I'v figured out a implementation by copy the sourcecode in STOR.java to my Ftplet's onUpload method.
> The following the sourcecode ,pls notice the "//" at the start of some lines ,
> Some changes are needed:
> 1, LocalizedFtpReply.translate(....)method is not usable in ftplet,
> 2, create a new FilterOutputStream object and pass it to transferFromClient to limit the size .
> When I test from a ftp client ,it seems like that the result is what I want .
> But I'm not sure there is no bug because I'm not fully understand the code I commented by "//".
>
> Could someone give me some suggestions?
> Thanks.
> ::::::::::::::::::::::::::::
>                 try {
>
>            // get state variable
>            long skipLen = session.getFileOffset();
>
>            // argument check
>            String fileName = request.getArgument();
>            if (fileName == null) {
>                session
>                        .write(new DefaultFtpReply(
>                                        FtpReply.REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS,
>                                        "STOR REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS"));
>                return  FtpletResult.SKIP;
>            }
>
> //            // 24-10-2007 - added check if PORT or PASV is issued, see
> //            // https://issues.apache.org/jira/browse/FTPSERVER-110
> //            DataConnectionFactory connFactory = session.getDataConnection();
> //            if (connFactory instanceof IODataConnectionFactory) {
> //                InetAddress address = ((IODataConnectionFactory) connFactory)
> //                        .getInetAddress();
> //                if (address == null) {
> //                    session.write(new DefaultFtpReply(
> //                            FtpReply.REPLY_503_BAD_SEQUENCE_OF_COMMANDS,
> //                            "PORT or PASV must be issued first"));
> //                    return;
> //                }
> //            }
>
>            // get filename
>            FtpFile file = null;
>            try {
>                file = session.getFileSystemView().getFile(fileName);
>            } catch (Exception ex) {
>                System.out.println("Exception getting file object"+ ex);
>            }
>            if (file == null) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_550_REQUESTED_ACTION_NOT_TAKEN,
>                        "STOR.REPLY_550_REQUESTED_ACTION_NOT_TAKEN"));
>                return FtpletResult.SKIP;
>            }
>            fileName = file.getAbsolutePath();
>
>            // get permission
>            if (!file.isWritable()) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_550_REQUESTED_ACTION_NOT_TAKEN,
>                        "STOR.REPLY_550_REQUESTED_ACTION_NOT_TAKEN"));
>                return FtpletResult.SKIP;
>            }
>
>            // get data connection
>            session.write(
>                   new DefaultFtpReply(
>                            FtpReply.REPLY_150_FILE_STATUS_OKAY, "STOR.REPLY_150_FILE_STATUS_OKAY"))
> //               .awaitUninterruptibly(10000)
>                                ;
>
>            DataConnection dataConnection;
>            try {
>                dataConnection = session.getDataConnection().openConnection();
>            } catch (Exception e) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_425_CANT_OPEN_DATA_CONNECTION, "STOR.REPLY_425_CANT_OPEN_DATA_CONNECTION"
>                        ));
>                return FtpletResult.SKIP;
>            }
>
>            // transfer data
>            boolean failure = false;
>            OutputStream outStream = null;
>            try {
>                outStream = file.createOutputStream(skipLen);
>                                final int writelimit = 2048;
>                long transSz = dataConnection.transferFromClient(
>                                        session, new FilterOutputStream( outStream){
>                                        private  int count =0;
>                                        public void write(int b) throws IOException {
>                                                        count++;
>                                                        if( count > writelimit ) throw new IOException ("Write too many bytes");
>                                                        out.write(b);
>                                        }
>
>                                });
>
>                // attempt to close the output stream so that errors in
>                // closing it will return an error to the client (FTPSERVER-119)
>                if(outStream != null) {
>                    outStream.close();
>                }
>
>                // notify the statistics component
> //                ServerFtpStatistics ftpStat = (ServerFtpStatistics) context
> //                        .getFtpStatistics();
> //                ftpStat.setUpload(session, file, transSz);
>
>
>            } catch (SocketException ex) {
>                failure = true;
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED,
>                        "STOR.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED"));
>            } catch (IOException ex) {
>                failure = true;
>                session
>                        .write(new DefaultFtpReply(
>                                        FtpReply.REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN,
>                                        "STOR.REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN"));
>            } finally {
>                // make sure we really close the output stream
>                outStream.close();
>            }
>
>            // if data transfer ok - send transfer complete message
>            if (!failure) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_226_CLOSING_DATA_CONNECTION, "STOR.REPLY_226_CLOSING_DATA_CONNECTION"));
>
>            }
>        } finally {
> //            session.resetState();
>            session.getDataConnection().closeDataConnection();
>        }
>
>                }catch(Exception e) {
>                        System.out.println(e);
>                }
>
>                return FtpletResult.SKIP;
>
>
>
> -------------------------------------------------------------------------------------------------
>>>Topic: implement a ftplet to limit the size of upload files
>
>>>Hi,
>
>>>I need to limit the size of upload files ,are there any good suggestions?
>>>Is implementing a ftplet possible to do this?
>
>>>Thanks for the help!
>>>Bob Zhu
>

Re: implement a ftplet to limit the size of upload files

Posted by David Latorre <dv...@gmail.com>.
I think your code is OK  except for  a  problem:
 - Restarting a failed transfer would mean that the user can safely
ignore your limit. To solve this, you could take into account the
skipLen value in order to prevent users from circumventing your
limits.


  The pieces of code you didn't understand:
  -- First block:              // 24-10-2007 - added check if PORT or
PASV is issued, see
//            // https://issues.apache.org/jira/browse/FTPSERVER-110

This block checks if a PORT or PASV command was issued previously. In
FTP, you must send a PORT or PASV command before any command that
sends data (stor, retr, mlsd etc.).

 -- awaitUninterruptibly : it makes sure the 150 150_FILE_STATUS_OKAY
command is sent before proceeding.
 --ServerFtpStatistics: this component keeps statistics of the
FTPServer usage. If you don't know it, you probably don't need it.
Still, I think your code doesn't break it in any way.



 2009/10/21 Zhu, Yan-Bo (TSG-GDCC-CD) <ya...@hp.com>:
> I'v figured out a implementation by copy the sourcecode in STOR.java to my Ftplet's onUpload method.
> The following the sourcecode ,pls notice the "//" at the start of some lines ,
> Some changes are needed:
> 1, LocalizedFtpReply.translate(....)method is not usable in ftplet,
> 2, create a new FilterOutputStream object and pass it to transferFromClient to limit the size .
> When I test from a ftp client ,it seems like that the result is what I want .
> But I'm not sure there is no bug because I'm not fully understand the code I commented by "//".
>
> Could someone give me some suggestions?
> Thanks.
> ::::::::::::::::::::::::::::
>                 try {
>
>            // get state variable
>            long skipLen = session.getFileOffset();
>
>            // argument check
>            String fileName = request.getArgument();
>            if (fileName == null) {
>                session
>                        .write(new DefaultFtpReply(
>                                        FtpReply.REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS,
>                                        "STOR REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS"));
>                return  FtpletResult.SKIP;
>            }
>
> //            // 24-10-2007 - added check if PORT or PASV is issued, see
> //            // https://issues.apache.org/jira/browse/FTPSERVER-110
> //            DataConnectionFactory connFactory = session.getDataConnection();
> //            if (connFactory instanceof IODataConnectionFactory) {
> //                InetAddress address = ((IODataConnectionFactory) connFactory)
> //                        .getInetAddress();
> //                if (address == null) {
> //                    session.write(new DefaultFtpReply(
> //                            FtpReply.REPLY_503_BAD_SEQUENCE_OF_COMMANDS,
> //                            "PORT or PASV must be issued first"));
> //                    return;
> //                }
> //            }
>
>            // get filename
>            FtpFile file = null;
>            try {
>                file = session.getFileSystemView().getFile(fileName);
>            } catch (Exception ex) {
>                System.out.println("Exception getting file object"+ ex);
>            }
>            if (file == null) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_550_REQUESTED_ACTION_NOT_TAKEN,
>                        "STOR.REPLY_550_REQUESTED_ACTION_NOT_TAKEN"));
>                return FtpletResult.SKIP;
>            }
>            fileName = file.getAbsolutePath();
>
>            // get permission
>            if (!file.isWritable()) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_550_REQUESTED_ACTION_NOT_TAKEN,
>                        "STOR.REPLY_550_REQUESTED_ACTION_NOT_TAKEN"));
>                return FtpletResult.SKIP;
>            }
>
>            // get data connection
>            session.write(
>                   new DefaultFtpReply(
>                            FtpReply.REPLY_150_FILE_STATUS_OKAY, "STOR.REPLY_150_FILE_STATUS_OKAY"))
> //               .awaitUninterruptibly(10000)
>                                ;
>
>            DataConnection dataConnection;
>            try {
>                dataConnection = session.getDataConnection().openConnection();
>            } catch (Exception e) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_425_CANT_OPEN_DATA_CONNECTION, "STOR.REPLY_425_CANT_OPEN_DATA_CONNECTION"
>                        ));
>                return FtpletResult.SKIP;
>            }
>
>            // transfer data
>            boolean failure = false;
>            OutputStream outStream = null;
>            try {
>                outStream = file.createOutputStream(skipLen);
>                                final int writelimit = 2048;
>                long transSz = dataConnection.transferFromClient(
>                                        session, new FilterOutputStream( outStream){
>                                        private  int count =0;
>                                        public void write(int b) throws IOException {
>                                                        count++;
>                                                        if( count > writelimit ) throw new IOException ("Write too many bytes");
>                                                        out.write(b);
>                                        }
>
>                                });
>
>                // attempt to close the output stream so that errors in
>                // closing it will return an error to the client (FTPSERVER-119)
>                if(outStream != null) {
>                    outStream.close();
>                }
>
>                // notify the statistics component
> //                ServerFtpStatistics ftpStat = (ServerFtpStatistics) context
> //                        .getFtpStatistics();
> //                ftpStat.setUpload(session, file, transSz);
>
>
>            } catch (SocketException ex) {
>                failure = true;
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED,
>                        "STOR.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED"));
>            } catch (IOException ex) {
>                failure = true;
>                session
>                        .write(new DefaultFtpReply(
>                                        FtpReply.REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN,
>                                        "STOR.REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN"));
>            } finally {
>                // make sure we really close the output stream
>                outStream.close();
>            }
>
>            // if data transfer ok - send transfer complete message
>            if (!failure) {
>                session.write(new DefaultFtpReply(
>                        FtpReply.REPLY_226_CLOSING_DATA_CONNECTION, "STOR.REPLY_226_CLOSING_DATA_CONNECTION"));
>
>            }
>        } finally {
> //            session.resetState();
>            session.getDataConnection().closeDataConnection();
>        }
>
>                }catch(Exception e) {
>                        System.out.println(e);
>                }
>
>                return FtpletResult.SKIP;
>
>
>
> -------------------------------------------------------------------------------------------------
>>>Topic: implement a ftplet to limit the size of upload files
>
>>>Hi,
>
>>>I need to limit the size of upload files ,are there any good suggestions?
>>>Is implementing a ftplet possible to do this?
>
>>>Thanks for the help!
>>>Bob Zhu
>

Re: implement a ftplet to limit the size of upload files

Posted by "Zhu, Yan-Bo (TSG-GDCC-CD)" <ya...@hp.com>.
I'v figured out a implementation by copy the sourcecode in STOR.java to my Ftplet's onUpload method.
The following the sourcecode ,pls notice the "//" at the start of some lines ,
Some changes are needed:
1, LocalizedFtpReply.translate(....)method is not usable in ftplet, 
2, create a new FilterOutputStream object and pass it to transferFromClient to limit the size .
When I test from a ftp client ,it seems like that the result is what I want .
But I'm not sure there is no bug because I'm not fully understand the code I commented by "//".

Could someone give me some suggestions?
Thanks.
::::::::::::::::::::::::::::
		 try {

            // get state variable
            long skipLen = session.getFileOffset();

            // argument check
            String fileName = request.getArgument();
            if (fileName == null) {
                session
                        .write(new DefaultFtpReply(
                                        FtpReply.REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS,
                                        "STOR REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS"));
                return  FtpletResult.SKIP;
            }
	
//            // 24-10-2007 - added check if PORT or PASV is issued, see
//            // https://issues.apache.org/jira/browse/FTPSERVER-110
//            DataConnectionFactory connFactory = session.getDataConnection();
//            if (connFactory instanceof IODataConnectionFactory) {
//                InetAddress address = ((IODataConnectionFactory) connFactory)
//                        .getInetAddress();
//                if (address == null) {
//                    session.write(new DefaultFtpReply(
//                            FtpReply.REPLY_503_BAD_SEQUENCE_OF_COMMANDS,
//                            "PORT or PASV must be issued first"));
//                    return;
//                }
//            }
        
            // get filename
            FtpFile file = null;
            try {
                file = session.getFileSystemView().getFile(fileName);
            } catch (Exception ex) {
                System.out.println("Exception getting file object"+ ex);
            }
            if (file == null) {
                session.write(new DefaultFtpReply(
                        FtpReply.REPLY_550_REQUESTED_ACTION_NOT_TAKEN,
                        "STOR.REPLY_550_REQUESTED_ACTION_NOT_TAKEN"));
                return FtpletResult.SKIP;
            }
            fileName = file.getAbsolutePath();

            // get permission
            if (!file.isWritable()) {
                session.write(new DefaultFtpReply(
                        FtpReply.REPLY_550_REQUESTED_ACTION_NOT_TAKEN,
                        "STOR.REPLY_550_REQUESTED_ACTION_NOT_TAKEN"));
                return FtpletResult.SKIP;
            }

            // get data connection
            session.write(
                   new DefaultFtpReply(
                            FtpReply.REPLY_150_FILE_STATUS_OKAY, "STOR.REPLY_150_FILE_STATUS_OKAY"))
//               .awaitUninterruptibly(10000)
				;

            DataConnection dataConnection;
            try {
                dataConnection = session.getDataConnection().openConnection();
            } catch (Exception e) {
                session.write(new DefaultFtpReply(
                        FtpReply.REPLY_425_CANT_OPEN_DATA_CONNECTION, "STOR.REPLY_425_CANT_OPEN_DATA_CONNECTION"
                        ));
                return FtpletResult.SKIP;
            }

            // transfer data
            boolean failure = false;
            OutputStream outStream = null;
            try {
                outStream = file.createOutputStream(skipLen);
				final int writelimit = 2048;
                long transSz = dataConnection.transferFromClient(
					session, new FilterOutputStream( outStream){
					private  int count =0;
					public void write(int b) throws IOException {
							count++;
							if( count > writelimit ) throw new IOException ("Write too many bytes");
							out.write(b);
					}
					 
				});

                // attempt to close the output stream so that errors in 
                // closing it will return an error to the client (FTPSERVER-119) 
                if(outStream != null) {
                    outStream.close();
                }

                // notify the statistics component
//                ServerFtpStatistics ftpStat = (ServerFtpStatistics) context
//                        .getFtpStatistics();
//                ftpStat.setUpload(session, file, transSz);
		
                
            } catch (SocketException ex) {
                failure = true;
                session.write(new DefaultFtpReply(
                        FtpReply.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED,
                        "STOR.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED"));
            } catch (IOException ex) {
                failure = true;
                session
                        .write(new DefaultFtpReply(
                                        FtpReply.REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN,
                                        "STOR.REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN"));
            } finally {
                // make sure we really close the output stream
                outStream.close();
            }

            // if data transfer ok - send transfer complete message
            if (!failure) {
                session.write(new DefaultFtpReply(
                        FtpReply.REPLY_226_CLOSING_DATA_CONNECTION, "STOR.REPLY_226_CLOSING_DATA_CONNECTION"));

            }
        } finally {
//            session.resetState();
            session.getDataConnection().closeDataConnection();
        }

		}catch(Exception e) {
			System.out.println(e);
		}
		
		return FtpletResult.SKIP;



-------------------------------------------------------------------------------------------------
>>Topic: implement a ftplet to limit the size of upload files

>>Hi,

>>I need to limit the size of upload files ,are there any good suggestions?
>>Is implementing a ftplet possible to do this?

>>Thanks for the help!
>>Bob Zhu