diff options
author | Nils Schwabe | 2014-06-30 17:11:03 +0200 |
---|---|---|
committer | Nils Schwabe | 2014-06-30 17:11:03 +0200 |
commit | 1a3dbab6ca7118f4ca9f61043f416f074ede13bc (patch) | |
tree | fad14555be544c3ba2afdf31b8f315364a67e7a6 /src/main/java/org/openslx/imagemaster/ftp | |
parent | [Webinterface] Add "images" tab (diff) | |
download | masterserver-1a3dbab6ca7118f4ca9f61043f416f074ede13bc.tar.gz masterserver-1a3dbab6ca7118f4ca9f61043f416f074ede13bc.tar.xz masterserver-1a3dbab6ca7118f4ca9f61043f416f074ede13bc.zip |
Add implementation for the new up- and download protocoll
Remove some old stuff that is not needed anymore
Fix some small bugs
Diffstat (limited to 'src/main/java/org/openslx/imagemaster/ftp')
4 files changed, 0 insertions, 649 deletions
diff --git a/src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java b/src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java deleted file mode 100644 index eba3f55..0000000 --- a/src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.openslx.imagemaster.ftp; - -import java.io.File; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - -import org.apache.log4j.Logger; -import org.openslx.imagemaster.App; -import org.openslx.imagemaster.Globals; -import org.openslx.imagemaster.db.DbImage; - -public class FtpCredentialsScheduler extends TimerTask -{ - - private static Logger log = Logger.getLogger( FtpCredentialsScheduler.class ); - - public static final long timeout = Long.valueOf( Globals.getPropertyInt( Globals.PropInt.FTPTIMEOUT ) ) * 60L * 1000L; // timeout in ms - - @Override - public void run() - { - synchronized ( App.ftpServer.users ) { - List<DbImage> uploadingImages = DbImage.getUploadingImages(); // get the uploading images - // List to save the users that need to be deleted after iterating the map - List<String> usersToDelete = new LinkedList<>(); - // check all folders - for ( Map.Entry<String, MasterFtpServer.Infos> entry : App.ftpServer.users.entrySet() ) { - if ( entry == null ) - continue; - String username = entry.getKey(); - File dir = new File( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username ); - if ( !dir.exists() ) - continue; - File[] list = dir.listFiles(); - if ( list.length == 1 ) { - // check file size first - DbImage currentImage = null; - for (DbImage img : uploadingImages) { // find the image that was uploaded by this user - if (img.ftpUser == username) currentImage = img; - } - if (currentImage != null && list[0].getTotalSpace() == currentImage.fileSize) { - ImageProcessor.processImageAfterUpload( username, list[0].getName() ); - } else if ( ( new Date().getTime() - list[0].lastModified() ) >= timeout ) { // check timeout - log.info( username + "'s files are too old. Deleting him and his folder." ); - usersToDelete.add( username ); - } - } else if ( list.length > 1 ) { - log.info( "User '" + username + "' uploaded too many files. Deleting his account and his folder." ); - usersToDelete.add( username ); - } else { - // check the creation time of the user - if ( ( System.currentTimeMillis() - App.ftpServer.users.get( username ).getCreateTime() ) >= timeout ) { - log.info( username + " did nothing for too long. Deleting him and his folder" ); - usersToDelete.add( username ); - } - } - } - // now delete users - for (String u : usersToDelete) { - App.ftpServer.removeUser( u ); - ImageProcessor.removeImageFromProcessList( u ); - } - - } - } - - public static void startScheduling() - { - Timer timer = new Timer( "FtpScheduler" ); - - // start timer now and fire every 60 seconds - timer.schedule( new FtpCredentialsScheduler(), 0, 60000 ); - } - -} diff --git a/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java deleted file mode 100644 index 2e480dc..0000000 --- a/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.openslx.imagemaster.ftp; - -import java.io.File; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; -import org.openslx.imagemaster.Globals; -import org.openslx.imagemaster.Globals.PropInt; -import org.openslx.imagemaster.db.DbImage; -import org.openslx.imagemaster.db.DbUser; -import org.openslx.imagemaster.thrift.iface.ImageData; -import org.openslx.imagemaster.thrift.iface.ImageDataError; -import org.openslx.imagemaster.thrift.iface.ImageDataException; - -public class ImageProcessor -{ - - private static Logger log = Logger.getLogger( ImageProcessor.class ); - // key: ftpUser, value: imageData - private static HashMap<String, ImageData> images = new HashMap<>(); - - /** - * After (re)starting server: check for dead !uploading! images in database - */ - public static void checkUploading() { - long timeout = Globals.getPropertyInt( PropInt.FTPTIMEOUT ) * 60L * 1000L; - List<DbImage> uploadingImages = DbImage.getUploadingImages(); - - log.info( uploadingImages.size() + " image(s) are uploading" ); - - if (uploadingImages.isEmpty()) return; - - Iterator<DbImage> iter = uploadingImages.iterator(); - while (iter.hasNext()) { - DbImage dbImage = iter.next(); - log.debug( "Akutlle Systemzeit: " + System.currentTimeMillis() ); - log.debug( "Timestamp: " + dbImage.timestamp.getTime() ); - log.debug( "Differenz: " + (System.currentTimeMillis() - dbImage.timestamp.getTime()) ); - log.debug( "Timeout: " + timeout ); - if (System.currentTimeMillis() - dbImage.timestamp.getTime() >= timeout) { - DbImage.delete( dbImage.UUID ); - log.info( "Deleted dbimage from db: " + dbImage.UUID + " due to timeout"); - } else { - // add image to process list again - ImageData imageData = new ImageData( dbImage.UUID, dbImage.imageVersion, dbImage.imageName, dbImage.imageCreateTime.getTime(), dbImage.imageUpdateTime.getTime(), dbImage.imageOwner, dbImage.contentOperatingSystem, dbImage.isValid, dbImage.isDeleted, dbImage.shortDescription, dbImage.longDescription, dbImage.fileSize ); - images.put( dbImage.ftpUser, imageData ); - log.info( "Added image to processlist again: " + dbImage.UUID ); - } - } - } - - /** - * Process an image after upload - * - * @param username the user that uploaded the file - * @param filename the name of the file that was uploaded (_no_ absolute path) - * @return - */ - public static boolean processImageAfterUpload( String username, String filename ) - { - if ( !images.containsKey( username ) ) { - return false; - } - - log.info( "Will now process '" + filename + "' from user '" + username - + "'" ); - - // move image to right location - String oldFileName = Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username + "/" + filename; - String newFileName = Globals.getPropertyString( Globals.PropString.IMAGEDIR ) + "/" + images.get( username ).uuid + ".vmdk"; - - File imageFile = new File( oldFileName ); - - if ( !imageFile.exists() ) { - // image file does not exist - return false; - } - - imageFile.renameTo( new File( newFileName ) ); - - log.info( "Moved file from " + oldFileName + " to " + newFileName ); - - File tempUserDir = new File( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username ); - tempUserDir.delete(); - - // update database - DbImage.update( images.get( username ), newFileName ); - log.info( "Updated db: " + images.get( username ).uuid ); - - images.remove( username ); - return true; - } - - /** - * Try to add imageData to database. - * - * @param imageData - * the data for the image to add - * @exception ImageDataException If the imagedata contains errors - */ - public static void addImageDataToProcess( ImageData imageData, String username, String password ) throws ImageDataException - { - log.info( "Adding image to process list: " + imageData.imageName + ", submitted by " + username ); - - if ( imageData.uuid == null || imageData.imageName == null - || imageData.imageOwner == null || imageData.conentOperatingSystem == null - || imageData.imageShortDescription == null - || imageData.imageLongDescription == null ) { - throw new ImageDataException(ImageDataError.INVALID_DATA, "Missing arguments."); - } - - if ( imageData.uuid.isEmpty() || imageData.imageName.isEmpty() - || imageData.imageOwner.isEmpty() || imageData.conentOperatingSystem.isEmpty() - || imageData.imageShortDescription.isEmpty() - || imageData.imageLongDescription.isEmpty() ) { - throw new ImageDataException(ImageDataError.INVALID_DATA, "Missing arguments."); - } - - if (!imageData.uuid.matches( "^[0-9a-f]{8}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{12}$" )) { - throw new ImageDataException(ImageDataError.INVALID_DATA, "UUID not valid."); - } else if (imageData.imageName.length() < 5 || imageData.imageName.length() > 50) { - throw new ImageDataException(ImageDataError.INVALID_DATA, "ImageName not valid. (Length must be 5 to 50)"); - } else if (!DbUser.exists( imageData.imageOwner )) { - throw new ImageDataException(ImageDataError.INVALID_DATA, "ImageOwner not known."); - } else if ( imageData.fileSize <= 0 ) { - throw new ImageDataException(ImageDataError.INVALID_DATA, "Filesize needs to be greater than 0."); - } - - if ( DbImage.exists( imageData ) ) { - throw new ImageDataException( ImageDataError.INVALID_DATA, "Image with this UUID is already existing." ); - } - - // if everything went fine, add image to db - DbImage.insert( imageData, System.currentTimeMillis(), username, password); - - // and to processinglist - images.put( username, imageData ); - } - - /** - * Removes image from process list (and also from db) - * @param username the user that uploaded the image - * @return - */ - public static boolean removeImageFromProcessList( String username) { - - if (!images.containsKey( username )) { - return false; - } - - DbImage.delete( images.get( username ).uuid ); - images.remove( username ); - - log.info( "Deleted image from process list and db. (User: " + username + ")" ); - - return true; - } -} diff --git a/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java b/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java deleted file mode 100644 index c24b318..0000000 --- a/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java +++ /dev/null @@ -1,313 +0,0 @@ -package org.openslx.imagemaster.ftp; - -import java.io.File; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -import org.apache.ftpserver.FtpServer; -import org.apache.ftpserver.FtpServerFactory; -import org.apache.ftpserver.ftplet.Authority; -import org.apache.ftpserver.ftplet.FtpException; -import org.apache.ftpserver.ftplet.Ftplet; -import org.apache.ftpserver.ftplet.UserManager; -import org.apache.ftpserver.impl.FtpIoSession; -import org.apache.ftpserver.listener.Listener; -import org.apache.ftpserver.listener.ListenerFactory; -import org.apache.ftpserver.ssl.SslConfigurationFactory; -import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory; -import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor; -import org.apache.ftpserver.usermanager.impl.BaseUser; -import org.apache.ftpserver.usermanager.impl.WritePermission; -import org.apache.log4j.Logger; -import org.openslx.imagemaster.Globals; -import org.openslx.imagemaster.Globals.PropString; -import org.openslx.imagemaster.db.DbFtpUser; -import org.openslx.imagemaster.thrift.iface.FtpCredentials; -import org.openslx.imagemaster.util.RandomString; -import org.openslx.imagemaster.util.Util; - -public class MasterFtpServer implements Runnable -{ - - private static Logger log = Logger.getLogger( MasterFtpServer.class ); - private FtpServer server; - private UserManager userManager; - private Listener listener; - // key: ftpUsername, value: infos - public final HashMap<String, Infos> users = new HashMap<>(); - private boolean ini = false; - - public enum Mode - { - UPLOADING, DOWNLOADING; - - @Override - public String toString() { - if (this == UPLOADING) { - return "uploading"; - } else if (this == DOWNLOADING) { - return "downloading"; - } else { - return ""; - } - } - } - - /** - * Class to hold infos of a ftp user. - * - * @author nils - * - */ - public class Infos - { - private final Long createTime; - private final Mode mode; - private final String fileName; - private final String serverSessionId; - - public Infos(Long createTime, Mode mode, String fileName, String serverSessionId) - { - this.createTime = createTime; - this.mode = mode; - this.fileName = fileName; - this.serverSessionId = serverSessionId; - } - - public Long getCreateTime() - { - return this.createTime; - } - - public Mode getMode() - { - return this.mode; - } - - public String getFileName() - { - return this.fileName; - } - - public String getServerSessionId() { - return this.serverSessionId; - } - } - - public void init( int port ) - { - if ( ini ) - return; - - FtpServerFactory serverFactory = new FtpServerFactory(); - ListenerFactory factory = new ListenerFactory(); - - // config ssl - SslConfigurationFactory sslConfigFactory = new SslConfigurationFactory(); - sslConfigFactory.setKeystoreFile( new File( Globals.getPropertyString( PropString.FTPKEYSTOREFILE ) ) ); - sslConfigFactory.setKeyAlias( Globals.getPropertyString( PropString.FTPKEYSTOREALIAS ) ); - sslConfigFactory.setKeystorePassword( Globals.getPropertyString( PropString.FTPKEYSTOREPASSWORD ) ); - - // set the port of the listener - factory.setPort( port ); - factory.setSslConfiguration( sslConfigFactory.createSslConfiguration() ); - factory.setImplicitSsl( true ); - - // replace the default listener - listener = factory.createListener(); - serverFactory.addListener( "default", listener ); - - // create user manager - PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory(); - File userFile = new File( "ftp.properties" ); - userManagerFactory.setFile( userFile ); - userManagerFactory.setPasswordEncryptor( new SaltedPasswordEncryptor() ); - userManager = userManagerFactory.createUserManager(); - serverFactory.setUserManager( userManager ); - - // add the Ftplet - HashMap<String, Ftplet> map = new HashMap<String, Ftplet>(); - map.put( "Ftplet1", new MasterFtplet() ); - serverFactory.setFtplets( map ); - - // start the server - server = serverFactory.createServer(); - ini = true; - } - - /** - * Add a user with username and password. - * @param username - * @param password - * @param mode - * @param fileName the filename of the file, that is allowed to access (if downloading) - * @param add user to db - * @return - */ - public boolean addUser( String serverSessionId, String username, String password, Mode mode, String fileName, boolean toDb) - { - String dir = Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username + "/"; - - BaseUser user = new BaseUser(); - user.setName( username ); - user.setPassword( password ); - List<Authority> authorities = new ArrayList<Authority>(); - - String file = ""; - - if (mode == Mode.UPLOADING) { - user.setHomeDirectory( dir ); - // uploading satellite is allowed to write - authorities.add( new WritePermission() ); - } else if (mode == Mode.DOWNLOADING) { - // the downloading satellite may access the whole dir, but this is restricted in MasterFtplet - user.setHomeDirectory( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) ); - // downloading satellite is only allowed to read - file = fileName; - } - - user.setAuthorities( authorities ); - - try { - userManager.save( user ); - synchronized ( users ) { - users.put( username, new Infos( System.currentTimeMillis(), mode, file, serverSessionId) ); - if (toDb) - DbFtpUser.addUser( new DbFtpUser( username, password, mode.toString(), fileName, serverSessionId, new Timestamp(System.currentTimeMillis()) ) ); - } - } catch ( FtpException e ) { - return false; - } - - return true; - } - - public FtpCredentials addUser( final String serverSessionId, Mode mode, String fileName ) - { - FtpCredentials ftpCredentials = null; - - String generatedUser = RandomString.generate( 10, false ); - String generatedPass = RandomString.generate( 16, true ); - - - BaseUser user = new BaseUser(); - user.setName( generatedUser ); - user.setPassword( generatedPass ); - List<Authority> authorities = new ArrayList<Authority>(); - - String file = ""; - String dir = ""; - - if (mode == Mode.UPLOADING) { - // generate the home dir - dir = Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + generatedUser + "/"; - if ( !new File( dir ).mkdir() ) { - return null; - } - // uploading satellite is allowed to write - authorities.add( new WritePermission() ); - } else if (mode == Mode.DOWNLOADING) { - // the downloading satellite may access the whole dir, but this is restricted in MasterFtplet - dir = Globals.getPropertyString( Globals.PropString.IMAGEDIR ); - // downloading satellite is only allowed to read - file = fileName; - } - - user.setHomeDirectory( dir ); - user.setAuthorities( authorities ); - - try { - userManager.save( user ); - ftpCredentials = new FtpCredentials( generatedUser, generatedPass, fileName ); - synchronized ( users ) { - users.put( ftpCredentials.username, new Infos( System.currentTimeMillis(), mode, file, serverSessionId) ); - DbFtpUser.addUser( new DbFtpUser( generatedUser, generatedPass, mode.toString(), fileName, serverSessionId, new Timestamp(System.currentTimeMillis()) ) ); - } - } catch ( FtpException e ) { - // TODO: handle this - } - - log.info( "Generated user/pass: " + generatedUser + "\t" - + generatedPass + "\n with home dir: " + dir ); - - return ftpCredentials; - } - - public boolean removeUser( final String username ) - { - if ( !users.containsKey( username ) ) - return false; - - try { - // first find active session and close it - Iterator<FtpIoSession> iter = listener.getActiveSessions().iterator(); - while ( iter.hasNext() ) { - FtpIoSession session = (FtpIoSession)iter.next(); - if ( session.getUser() == null ) - continue; - if ( session.getUser().getName() == username ) { - session.close(); - } - } - // afterwards delete user - userManager.delete( username ); - // remove user from map (cache) - synchronized ( users ) { - users.remove( username ); - DbFtpUser.removeUserByName( username ); - } - // remove his home dir - try { - File dir = new File( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username ); - Util.deleteFolder( dir ); - } catch (Exception e) { - // don't care because it could be a downloading user - } - return true; - } catch ( FtpException e ) { - return false; - } - } - - @Override - public void run() - { - try { - //if (!ini) throw new Exception("FTP server needs to be initalized."); - log.info( "Starting FTP Sever" ); - server.start(); - } catch ( FtpException e1 ) { - e1.printStackTrace(); - } - } - - public void addDbFtpUsers() - { - List<DbFtpUser> list = DbFtpUser.getAllUsers(); - Iterator<DbFtpUser> iter = list.iterator(); - - int n = 0; - - while (iter.hasNext()) { - DbFtpUser user = iter.next(); - Mode mode; - if ( user.mode.equalsIgnoreCase( "downloading" ) ) { - mode = Mode.DOWNLOADING; - } else { - mode = Mode.UPLOADING; - } - // don't readd user if it timeouted - if ( (System.currentTimeMillis() - user.timestamp.getTime()) < FtpCredentialsScheduler.timeout ) { - this.addUser( user.sessionId, user.username, user.password, mode, user.filename, false ); - n++; - } else { - DbFtpUser.removeUserByName( user.username ); - } - } - - log.info( "Added " + n + " FTP users from DB." ); - } -} diff --git a/src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java b/src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java deleted file mode 100644 index c514f5e..0000000 --- a/src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.openslx.imagemaster.ftp; - -import java.io.IOException; - -import org.apache.ftpserver.ftplet.FtpException; -import org.apache.ftpserver.ftplet.FtpReply; -import org.apache.ftpserver.ftplet.FtpRequest; -import org.apache.ftpserver.ftplet.FtpSession; -import org.apache.ftpserver.ftplet.Ftplet; -import org.apache.ftpserver.ftplet.FtpletContext; -import org.apache.ftpserver.ftplet.FtpletResult; -import org.apache.log4j.Logger; -import org.openslx.imagemaster.App; -import org.openslx.imagemaster.serversession.ServerSessionManager; - -public class MasterFtplet implements Ftplet -{ - private static Logger log = Logger.getLogger( MasterFtplet.class ); - - @Override - public void init( FtpletContext ftpletContext ) throws FtpException - { - // not used - } - - @Override - public void destroy() - { - // not used - } - - @Override - public FtpletResult beforeCommand( FtpSession session, FtpRequest request ) - throws FtpException, IOException - { - if ( session.getUser() != null ) { - // check if masterserver is still knowing this user - if (App.ftpServer.users.containsKey( session.getUser().getName() )) { - MasterFtpServer.Infos infos = App.ftpServer.users.get( session.getUser().getName() ); - if (infos.getMode() == MasterFtpServer.Mode.DOWNLOADING) { // filter the downloading clients - if (request.getCommand().equals("RETR")) { - // check if user is getting the right file - if (!infos.getFileName().equals(request.getArgument())) { - // the client tries to retrieve a file, that he is not allowed to get - String organization = ServerSessionManager.getSession( App.ftpServer.users.get( session.getUser().getName() ).getServerSessionId() ).getOrganization(); - log.info( "A user from organization '" + organization + "' tried to download a file (" + request.getArgument() + "), that he was not allowed to." ); - throw new FtpException( "550 File unavailable." ); // after the exception, the client will be automatically be disconnected - } - } else if ( request.getCommand().equals( "MLSD" ) // list dirs - || request.getCommand().equals( "NSLT" ) // list files - || request.getCommand().equals( "CWD" ) // change working dir - ) { - - // TODO: block all other commands except login and retrieve - return FtpletResult.DISCONNECT; // disconnect the client on wrong command - } - } - } else { - // user is not valid anymore - throw new FtpException( "430 Invalid username or password." ); // ERROR CODE 430 --> invalid username or password - // after the exception, the client will be automatically be disconnected - } - - } - - return FtpletResult.DEFAULT; - } - - @Override - public FtpletResult afterCommand( FtpSession session, FtpRequest request, - FtpReply reply ) throws FtpException, IOException - { - // not used - return FtpletResult.DEFAULT; - } - - @Override - public FtpletResult onConnect( FtpSession session ) throws FtpException, - IOException - { - if (session.getUser() != null) { - log.info( session.getUser().getName() + " connected" ); - } - return FtpletResult.DEFAULT; - } - - @Override - public FtpletResult onDisconnect( FtpSession session ) throws FtpException, - IOException - { - if (session.getUser() != null) { - log.info( session.getUser().getName() + " disconnected" ); - } - return FtpletResult.DEFAULT; - } - -} |