/****************************************************************************** * Copyright (c) 2010-2013, Linagora * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.studio.welcome; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.Key; import java.util.Properties; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.eclipse.core.runtime.IStatus; import com.ebmwebsourcing.petals.studio.PetalsStudioPlugin; import com.ebmwebsourcing.petals.studio.utils.Base64; import com.ebmwebsourcing.petals.studio.utils.VersionUtils; /** * @author Vincent Zurczak - EBM WebSourcing */ public final class RegistrationManager { private final static String EMAIL = "petals.studio.email"; private final static String COMPANY = "petals.studio.company"; private final static String NAME = "petals.studio.name"; private final static String PHONE = "petals.studio.phone"; private final static String LANG = "petals.studio.language"; private final static String REGISTERED = "petals.studio.done"; private final static String LAST_STUDIO_VERSION = "petals.studio.version"; private final static String JOKER = "petals.studio.joker"; private final static String PROXY_HOST = "petals.studio.proxy.host"; private final static String PROXY_USER = "petals.studio.proxy.user"; private final static String PROXY_PWD = "petals.studio.proxy.password"; private final static String PROXY_PORT = "petals.studio.proxy.port"; private final File registrationFile; private final Key secretKey; private final Cipher cipher; private RegistrationBean backupRegistrationBean; private static RegistrationManager instance; /** * Constructor. * @throws IOException if the registration file does not exist and could not be created * @throws GeneralSecurityException */ private RegistrationManager() throws IOException, GeneralSecurityException { // Get or create the backup file this.registrationFile = new File( System.getProperty( "user.home" ), ".PetalsStudio.backup" ); if( ! this.registrationFile.exists() && ! this.registrationFile.createNewFile()) { IOException e = new IOException( "Could not create the registration file." ); PetalsStudioPlugin.log( e, IStatus.ERROR, "Could not create the registration file." ); throw e; } // Get the key (always the same, we do not store critical data). // Plus, they are stored on the user's machine. // PBEKeySpec keySpec = new PBEKeySpec( "BlabluBloBlik".toCharArray()); // SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "PBKDF2WithHmacSHA1" ); // this.secretKey = keyFactory.generateSecret( keySpec ); this.secretKey = new SecretKeySpec( "BlabluBloBlik".getBytes(), "Blowfish" ); // Get the cipher this.cipher = Cipher.getInstance( "Blowfish" ); } /** * Backup registration data. * @param bean a registration bean * @return true if the backup succeeded, false otherwise */ public boolean backupRegistrationData( RegistrationBean bean ) { boolean registered = false; try { // Prepare the elements to serialize Properties properties = new Properties(); properties.setProperty( NAME, encode( bean.getName())); properties.setProperty( EMAIL, encode( bean.getEmail())); properties.setProperty( COMPANY, encode( bean.getCompany())); properties.setProperty( PHONE, encode( bean.getPhone())); properties.setProperty( LANG, encode( bean.getLanguage())); properties.setProperty( REGISTERED, encode( String.valueOf( bean.isRegistered()))); properties.setProperty( LAST_STUDIO_VERSION, encode( bean.getLastRegisteredVersion())); if( bean.getProxyHost() != null ) properties.setProperty( PROXY_HOST, encode( bean.getProxyHost())); if( bean.getProxyPassword() != null ) properties.setProperty( PROXY_PWD, encode( bean.getProxyPassword())); if( bean.getProxyUser() != null ) properties.setProperty( PROXY_USER, encode( bean.getProxyUser())); if( bean.getProxyPort() != null ) properties.setProperty( PROXY_PORT, encode( String.valueOf( bean.getProxyPort()))); // Serialize the elements FileOutputStream os = null; try { os = new FileOutputStream( this.registrationFile ); properties.store( os, "Written by Petals Studio" ); registered = true; this.backupRegistrationBean = bean; } catch( Exception e ) { PetalsStudioPlugin.log( e, IStatus.WARNING ); } finally { try { if( os != null ) os.close(); } catch( IOException e ) { PetalsStudioPlugin.log( e, IStatus.ERROR ); } } } catch( Exception e ) { PetalsStudioPlugin.log( e, IStatus.ERROR ); } return registered; } /** * Restores registration data from the backup file. * @return a registration bean (never null) */ public RegistrationBean restoreRegistrationData() { if( this.backupRegistrationBean == null ) { // Get the elements to read Properties properties = new Properties(); FileInputStream is = null; try { is = new FileInputStream( this.registrationFile ); properties.load( is ); } catch( Exception e ) { PetalsStudioPlugin.log( e, IStatus.WARNING ); } finally { try { if( is != null ) is.close(); } catch( IOException e ) { PetalsStudioPlugin.log( e, IStatus.ERROR ); } } // Fill-in the registration bean try { this.backupRegistrationBean = new RegistrationBean(); String name = properties.getProperty( NAME ); this.backupRegistrationBean.setName( decode( name )); String email = properties.getProperty( EMAIL ); this.backupRegistrationBean.setEmail( decode( email )); String company = properties.getProperty( COMPANY ); this.backupRegistrationBean.setCompany( decode( company )); String phone = properties.getProperty( PHONE ); this.backupRegistrationBean.setPhone( decode( phone )); String lang = properties.getProperty( LANG ); this.backupRegistrationBean.setLanguage( decode( lang )); String registeredAS = properties.getProperty( REGISTERED ); registeredAS = decode( registeredAS ); boolean registered = Boolean.valueOf( registeredAS ); this.backupRegistrationBean.setRegistered( registered ); String jokerAS = properties.getProperty( JOKER ); jokerAS = decode( jokerAS ); boolean joker = Boolean.valueOf( jokerAS ); this.backupRegistrationBean.setJoker( joker ); String lastVersion = properties.getProperty( LAST_STUDIO_VERSION ); this.backupRegistrationBean.setLastRegisteredVersion( decode( lastVersion )); String proxyHost = properties.getProperty( PROXY_HOST ); if( proxyHost != null ) this.backupRegistrationBean.setProxyHost( decode( proxyHost )); String proxyUser = properties.getProperty( PROXY_USER ); if( proxyUser != null ) this.backupRegistrationBean.setProxyUser( decode( proxyUser )); String proxyPwd = properties.getProperty( PROXY_PWD ); if( proxyPwd != null ) this.backupRegistrationBean.setProxyPassword( decode( proxyPwd )); String proxyPort = properties.getProperty( PROXY_PORT ); if( proxyPort != null ) { String value = decode( proxyPort ); int port = Integer.valueOf( value ); this.backupRegistrationBean.setProxyPort( port ); } } catch( Exception e ) { PetalsStudioPlugin.log( e, IStatus.ERROR ); } } return this.backupRegistrationBean; } /** * Encodes user information using the Blowfish encryption algorithm and a Base64. * @param s the string to encode * @return the encoded string * @throws Exception if something went wrong */ public String encode( String s ) throws Exception { String result = ""; if( s != null && s.trim().length() > 0 ) { this.cipher.init( Cipher.ENCRYPT_MODE, this.secretKey ); byte[] encrypted = this.cipher.doFinal( s.getBytes()); encrypted = Base64.encode( encrypted ); result = new String( encrypted ); } return result; } /** * Decodes user information using the Blowfish encryption algorithm and a Base64. * @param s the string to decode * @return the decoded string * @throws Exception if something went wrong */ private String decode( String s ) throws Exception { String result = ""; if( s != null && s.trim().length() > 0 ) { byte[] decrypted = Base64.decode( s.getBytes()); this.cipher.init( Cipher.DECRYPT_MODE, this.secretKey ); decrypted = this.cipher.doFinal( decrypted ); result = new String( decrypted ); } return result; } /** * @return the unique instance of this class * @throws IOException * @throws GeneralSecurityException */ public synchronized static RegistrationManager getInstance() throws IOException, GeneralSecurityException { if( instance == null ) instance = new RegistrationManager(); return instance; } /** * Determine whether the registration process is required. * @return true if the registration is required, false otherwise */ public static boolean needsRegistration() { boolean needsRegistration = true; try { // Get the saved data RegistrationManager mng = getInstance(); RegistrationBean bean = mng.restoreRegistrationData(); // Check the registration status and the last registered version String registeredVersion = VersionUtils.getTwoDigitVersion( bean.getLastRegisteredVersion()); String currentVersion = VersionUtils.getProductVersion( false ); // Dev mode if( VersionUtils.DEV_VERSION.equals( VersionUtils.getProductVersion( true ))) needsRegistration = false; // Consultants else if( bean.isJoker()) needsRegistration = false; // "1.0".compareTo( "1.1" ) returns a negative number else if( registeredVersion.trim().length() == 0 // Not registered || registeredVersion.compareTo( currentVersion ) < 0 ) // Former version needsRegistration = true; else if( ! bean.isRegistered()) needsRegistration = true; else needsRegistration = false; } catch( IOException e ) { PetalsStudioPlugin.log( e, IStatus.WARNING, "It could not be determined if the registration process was required. (IO)" ); } catch( GeneralSecurityException e ) { PetalsStudioPlugin.log( e, IStatus.WARNING, "It could not be determined if the registration process was required. (Security)" ); } return needsRegistration; } }