Package org.blync.client

Source Code of org.blync.client.DataAccess$CryptoResult

/*
* Copyright 2009-2010 Marcel Zumstein, Oxinia GmbH
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/

package org.blync.client;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;

import javax.microedition.io.*;
import javax.microedition.io.file.*;

import org.blync.client.mail.MailMainScreen;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;


/**
*
* @author Marcel
*/
public class DataAccess {
    private static DataAccess instance;

    private BufferedBlockCipher cipher = null;
    private static final int KEY_LENGTH = 24;
    private static final int BUFFER_SIZE = 2048;
    private static int ENCRYPTED_BUFFER_SIZE = BUFFER_SIZE;
    private static String baseDir;
    private static String mailBaseDir;
    private static String inboxDir;
    private static String sentDir;
    private static String draftsDir;
    private static String attachmentDir;
    private static String tempDir;
    private static String contactsDir;
    private static String appointmentDir;
    private static String taskDir;
    private LogScreen logger = LogScreen.getInstance();
    private String userName;
    private String password;
    private boolean cryptoInitialized = false;
    private boolean debug = true; // TODO: remove

    // data types
    public static final int BASE = 0;
    public static final int ATTACHMENT = 1;
    public static final int MAIL = 2;
//    public static final int INBOX = 3;
//    public static final int SENT = 4;
//    public static final int DRAFTS = 5;
    public static final int CONTACT = 6;
    public static final int APPOINTMENT = 7;
    public static final int TASK = 8;
    public static final int TEMP = 9;

    public static final String FILE_USER_NAME = "user";
    public static final String FILE_LOGIN = "login";

    private DataAccess() {
        initDirectories();
    }

    /**
     * Get the singleton instance
     */
    public static DataAccess getInstance() {
        if (instance == null) {
            instance = new DataAccess();
        }
        return instance;
    }
/*
    public Image loadImage(String fileName) {
        ByteArrayOutputStream oStream = new ByteArrayOutputStream();
        loadData(ATTACHMENT, fileName, oStream);
        byte[] bytes = oStream.toByteArray();
        return Image.createImage(bytes, 0, bytes.length);
    }
*/
    /**
     * Get the content of a file as text
     */
    public String loadText(int type, String fileName) {
        return loadText(type, fileName, true);
    }

    /**
     * Get the content of a file as text
     */
    public String loadText(int type, String fileName, boolean encrypted) {
        ByteArrayOutputStream oStream = new ByteArrayOutputStream();
        loadData(type, fileName, oStream, encrypted);
        byte[] bytes = oStream.toByteArray();
        return new String(bytes);
    }

    /**
     * Save a string to a file
     */
    public void saveText(int type, String fileName, String text) {
        saveText(type, fileName, text, true);
    }

    /**
     * Save a string to a file
     */
    public void saveText(int type, String fileName, String text, boolean encrypted) {
        InputStream iStream = new ByteArrayInputStream(text.getBytes());
        saveData(type, fileName, iStream, encrypted);
    }

    /**
     * Move a mail from one folder to another.
     */
/*    public void moveMail(String folder, String fileName, String targetFolder) {
        String mail = loadText(DataAccess.MAIL, folder + "/" + fileName, false);
        if (mail.length() > 0) {
            saveText(DataAccess.MAIL, targetFolder + "/" + fileName, mail, false);
            deleteFile(MAIL, folder + "/" + fileName);
        }
    } */

    /**
     * Load data via an output stream
     */
    public void loadData(int type, String fileName, OutputStream oStream) {
        loadData(type, fileName, oStream, true);
    }

    /**
     * Load data via an output stream
     */
    public void loadData(int type, String fileName, OutputStream oStream, boolean encrypted) {
        loadData(getDir(type) + fileName, oStream, encrypted);
    }

    private void loadData(String path, OutputStream oStream, boolean encrypted) {
        try {
            FileConnection fc = (FileConnection)
                    Connector.open("file:///" + path, Connector.READ);
            if (fc.exists()) {
            DataInputStream fis = fc.openDataInputStream();
            byte[] encBuffer = new byte[ENCRYPTED_BUFFER_SIZE];
//            int totalEnc = 0;
//            int totalDec = 0;
            int length;
            while ((length = fis.read(encBuffer)) != -1) {
                if (length < ENCRYPTED_BUFFER_SIZE) {
                    int extraLength = fis.read(encBuffer, length, ENCRYPTED_BUFFER_SIZE - length);
                    if (extraLength != -1) {
                        length += extraLength;
                    }
                }
                if (encrypted && !debug) {
                    CryptoResult decryptResult = performDecrypt(getKey(), encBuffer, length);
                    oStream.write(decryptResult.getData(), 0, decryptResult.getLength());
                }
                else {
                    oStream.write(encBuffer, 0, length);
                }
//                totalEnc += length;
//                totalDec += decryptResult.getLength();
            }
    //            System.out.println("Encyrpted length: " + totalEnc);
    //            System.out.println("Decyrpted length: " + totalDec);
            fis.close();
                fc.close();
            }
        }
        catch (Exception e) {
            log("loadData", e.toString());
        }
    }

    /**
     * Save data via an input stream
     */
    public void saveData(int type, String fileName, InputStream iStream) {
        saveData(type, fileName, iStream, true);
    }

    /**
     * Save data via an input stream
     */
    public void saveData(int type, String fileName, InputStream iStream, boolean encrypted) {
        saveData(getDir(type) + fileName, iStream, encrypted);
    }

    private void saveData(String path, InputStream iStream, boolean encrypted) {
        try {
            initPath(path);
            FileConnection fc = (FileConnection)
                Connector.open("file:///" + path);
            if (!fc.exists()) {
                fc.create();
            }
            fc.truncate(0); // overwrite all
            OutputStream fos = fc.openOutputStream();
            int length;
            byte[] buffer = new byte[BUFFER_SIZE];
            while ((length = iStream.read(buffer, 0, BUFFER_SIZE)) != -1) {
                if (encrypted && !debug) {
                    CryptoResult encryptResult = performEncrypt(getKey(), buffer, length);
                    fos.write(encryptResult.getData(), 0, encryptResult.getLength());
                }
                else {
                    fos.write(buffer, 0, length);
                }
            }
            fos.close();
            fc.close();
        }
        catch (IOException e) {
            log("saveData", e.toString());
            log("saveData", "file:///" + path);
        }
    }

    public boolean createFolder(int type, String folderName) {
        try {
            initDirectory(getDir(type) + folderName);
            return true;
        }
        catch (IOException e) {
            log("createFolder", e.toString());
            return false;
        }
    }

    public boolean renameFolder(int type, String sourceName, String targetName) {
        try {
            FileConnection fc = (FileConnection) Connector.open("file:///" + getDir(type) + sourceName);
            fc.rename(targetName);
            fc.close();

            return true;
        }
        catch (IOException e) {
            log("renameFolder", e.toString());
            return false;
        }
    }


    /**
     * Create an unencoded copy of a file in a temporary directory
     */
    public void decodeFile(int type, String fileName) {
        try {
            initPath(getDir(TEMP) + fileName);
           
            FileConnection codedFc = (FileConnection)
                    Connector.open("file:///" + getDir(type) + fileName, Connector.READ);
            FileConnection decodedFc = (FileConnection)
                    Connector.open("file:///" + getDir(TEMP) + fileName);
            if (!decodedFc.exists()) {
                decodedFc.create();
            }

            DataInputStream fis = codedFc.openDataInputStream();
            OutputStream fos = decodedFc.openOutputStream();
            byte[] encBuffer = new byte[ENCRYPTED_BUFFER_SIZE];
            int length;
            while ((length = fis.read(encBuffer)) != -1) {
                if (length < ENCRYPTED_BUFFER_SIZE) {
                    int extraLength = fis.read(encBuffer, length, ENCRYPTED_BUFFER_SIZE - length);
                    if (extraLength != -1) {
                        length += extraLength;
                    }
                }
                CryptoResult decryptResult = performDecrypt(getKey(), encBuffer, length);
                fos.write(decryptResult.getData(), 0, decryptResult.getLength());
            }
            fis.close();
            fos.close();
            codedFc.close();
            decodedFc.close();
        }
        catch (Exception e) {
            log("decodeFile", e.toString());
        }

    }

    /**
     * Will delete an empty subdirectory; returns false if subdirectory is not empty.
     */
    public boolean deleteFolder(int type, String directoryName) {
        try {
            FileConnection dir = (FileConnection)
            Connector.open("file:///" + getDir(type) + directoryName);
            if (dir.exists()) {
                Enumeration enumDir = dir.list();
                if (enumDir.hasMoreElements()) {
                    return false; // directory not emtpy
                }
                dir.delete();
            }
        }
        catch (IOException e) {
            log("deleteFolder", e.toString());
            return false;
        }

        return true;
    }

    private void deleteDirectory(String directoryName, boolean recursive, boolean deleteRootFolder, boolean deleteSubFolders) {
        try {
            FileConnection dir = (FileConnection)
            Connector.open("file:///" + directoryName);
            if (dir.exists()) {
                Enumeration enumDir = dir.list();
                while (enumDir.hasMoreElements()) {
                    String fileName = (String)enumDir.nextElement();
                    FileConnection fc = (FileConnection)
                        Connector.open("file:///" + directoryName + fileName);
                    if (fc.isDirectory()) {
                        if (recursive) {
                            deleteDirectory(directoryName + fileName, true, deleteSubFolders, deleteSubFolders);
                        }
                    }
                    else {
                        fc.delete();
                    }
                    fc.close();
                }
                if (deleteRootFolder) {
                    dir.delete();
                }
            }
            dir.close();
        }
        catch (IOException e) {
            log("deleteDirectory", e.toString());
        }
    }

    /**
     * Delete a file from the file system
     */
    public void deleteFile(int type, String fileName) {
        try {
            if (type == MAIL/*type == INBOX || type == SENT || type == DRAFTS*/) {
                deleteDirectory(getDir(ATTACHMENT) + fileName + "/", true, true, true);
            }
            FileConnection fc = (FileConnection)
            Connector.open("file:///" + getDir(type) + fileName);
            if (fc.exists()) {
                fc.delete();
            }
            fc.close();
        }
        catch (IOException e) {
            log("deleteFile", e.toString());
        }
    }

    /**
     * Check whether a file exists on the file system
     */
    public boolean fileExists(int type, String fileName) {
        boolean exists = false;
        try {
            FileConnection fc = (FileConnection)
            Connector.open("file:///" + getDir(type) + fileName);
            exists = fc.exists();
            fc.close();
        }
        catch (IOException e) {
            log("fileExists", e.toString());
        }
        return exists;
    }

    /**
     * Delete all content
     */
    public void deleteAll() {
        deleteDirectory(getDir(MAIL), true, false, false);
        deleteDirectory(getDir(APPOINTMENT), false, false, false);
        deleteDirectory(getDir(TASK), false, false, false);
        deleteDirectory(getDir(CONTACT), false, false, false);
        deleteDirectory(getDir(ATTACHMENT), true, false, true);
        deleteDirectory(getDir(BASE), false, false, false);
        deleteTempDir();
    }

    public void deleteTempDir() {
        deleteDirectory(getDir(TEMP), true, false, true);
    }

    /**
     * Make sure data directories exist
     */
    private void initDirectories() {
        String dataDir = Resources.get(Resources.DATA_DIRECTORY);
        try {
/*            FileConnection fc = (FileConnection) Connector.open("file:///" + dataDir);
            if (!fc.exists()) {
                fc.mkdir();
                if (!fc.exists()) {
                    throw new Exception("Data directory " + dataDir + " not found");
                }
            } */

            baseDir = dataDir + "SyncClient/";
            mailBaseDir = baseDir + getDirName(MAIL);
            inboxDir = mailBaseDir + MailMainScreen.INBOX_NAME + "/";
            sentDir = mailBaseDir + MailMainScreen.SENT_NAME + "/";
            draftsDir = mailBaseDir + MailMainScreen.DRAFTS_NAME + "/";
            attachmentDir = baseDir + getDirName(ATTACHMENT);
            tempDir = baseDir + getDirName(TEMP);
            contactsDir = baseDir + getDirName(CONTACT);
            appointmentDir = baseDir + getDirName(APPOINTMENT);
            taskDir = baseDir + getDirName(TASK);

            initDirectory(baseDir);
            initDirectory(mailBaseDir);
            initDirectory(inboxDir);
            initDirectory(sentDir);
            initDirectory(draftsDir);
            initDirectory(attachmentDir);
            initDirectory(appointmentDir);
            initDirectory(taskDir);
            initDirectory(contactsDir);
            initDirectory(tempDir);
        }
        catch (IOException e) {
            log("initDirectory", e.toString());
        }
        catch (Exception e) {
            log("initDirectory", e.toString());
        }
    }

    /**
     *  make sure directory exists
     */
    private void initDirectory(String dirPath) throws IOException {
        FileConnection fc = (FileConnection) Connector.open("file:///" + dirPath);

        if (!fc.exists()) {
            fc.mkdir();
        }
        fc.close();
    }

    /**
     * make sure all directories in path exist
     */
    private void initPath(String path) throws IOException {
        int parsePos = 1;
        int dirSeparator = path.indexOf('/', parsePos);
        while (dirSeparator != -1) {
            initDirectory(path.substring(0, dirSeparator + 1));
            parsePos = dirSeparator + 1;
            dirSeparator = path.indexOf('/', parsePos);
        }
    }

    /**
     * Get a list of all existing files of a specific type
     */
    public Enumeration listDirectory(int type) {
        Enumeration enumDir = null;
        try {
            FileConnection fc = (FileConnection)
                Connector.open("file:///" + getDir(type));
            if (fc.exists()) {
                enumDir = fc.list();
            }
        }
        catch (IOException e) {
            log("loadList", e.toString());
        }
        catch (Exception e) {
            log("loadList", e.toString());
        }
        return enumDir;
    }

    /**
     * Get the subdirectory name for a specific type
     */
    public static String getDirName(int type) {
        switch (type) {
            case MAIL:
                return "Mails/";
            case CONTACT:
                return "Contacts/";
            case APPOINTMENT:
                return "Appointments/";
            case TASK:
                return "Tasks/";
            case ATTACHMENT:
                return "Attachments/";
            case TEMP:
                return "Temp/";
            case BASE:
            default:
                return "";

        }
    }

    /**
     * Get the full path for a specific type
     */
    private String getDir(int type) {
            switch (type) {
            case BASE:
                return baseDir;
            case MAIL:
                return mailBaseDir;
/*            case INBOX:
                return inboxDir;
            case SENT:
                return sentDir;
            case DRAFTS:
                return draftsDir; */
            case CONTACT:
                return contactsDir;
            case APPOINTMENT:
                return appointmentDir;
            case TASK:
                return taskDir;
            case ATTACHMENT:
                return attachmentDir;
            case TEMP:
                return tempDir;
            default:
                return "";
        }

    }
/*
    public boolean isDirectory(String fileName) {
        boolean isDirectory = false;
        try {
            FileConnection fc = (FileConnection)
                Connector.open("file:///" + attachmentDir + fileName, Connector.READ);
            isDirectory = fc.isDirectory();
        }
        catch (IOException e) {
            log("isDirectory", e.toString());
        }

        return isDirectory;
    }
*/

    public String getStoredUserName() {
        return loadText(BASE, FILE_USER_NAME, false);
    }

    /**
     * Checks the password for the user account
     */
    public boolean isPasswordOk(String userName, String password) {
        this.password = password;
        String login = loadText(BASE, FILE_LOGIN);
        boolean ok = login.equals("ok");
        if (ok) {
            setLogin(userName, password);
        }
        else {
            this.password = "";
        }
        return ok;
    }

    public void setLogin(String userName, String password) {
        this.userName = userName;
        this.password = password;
        saveText(BASE, FILE_USER_NAME, userName, false);
        saveText(BASE, FILE_LOGIN, "ok", true);
    }

    public String getUserName() {
        return userName;
    }

    public String getPassword() {
        return password;
    }

    private BufferedBlockCipher getCipher() {
        if (cipher == null) {
            BlockCipher engine = new DESedeEngine();
            cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(engine));

            String name = cipher.getUnderlyingCipher().getAlgorithmName();
//            System.out.println("Using " + name);
        }
        return cipher;
    }
   
    private void initCrypto() {
        if (!cryptoInitialized) {
            cipher = getCipher();
            cipher.init(true, new KeyParameter(getKey()));
            ENCRYPTED_BUFFER_SIZE = cipher.getOutputSize(BUFFER_SIZE);
            cryptoInitialized = true;
        }
    }

    private final CryptoResult performEncrypt(byte[] key, byte[] plainText, int length)
    {
        initCrypto();
        cipher = getCipher();
        cipher.init(true, new KeyParameter(key));

        byte[] encText = new byte[cipher.getOutputSize(length)];

        int oLen = cipher.processBytes(plainText, 0, length, encText, 0);
        try
        {
            oLen += cipher.doFinal(encText, oLen);
        }
        catch (CryptoException ce)
        {
            log("performEncrypt", ce.toString());
        }
//        p(encText, length);
        return new CryptoResult(encText, oLen);
    }

    private final CryptoResult performDecrypt(byte[] key, byte[] cipherText, int length)
    {
        initCrypto();
        cipher = getCipher();
        cipher.init(false, new KeyParameter(key));
//        System.out.println("Encrypted length: " + length);

        byte[] plainText = new byte[cipher.getOutputSize(length)];
//        System.out.println("Buffer length: " + plainText.length);

        int oLen = cipher.processBytes(cipherText, 0, length, plainText, 0);
        try {
            oLen += cipher.doFinal(plainText, oLen);
        }

        catch (CryptoException ce) { /*
            System.out.println("cipher");
            System.out.println(new String(cipherText));
            System.out.println("plain");
            System.out.println(new String(plainText)); */
            log("performDecrypt", ce.toString());
        }

//        System.out.println("Decrypted length: " + oLen);
        return new CryptoResult(plainText, oLen);
    }

    private byte[] getKey() {
        if (password == null || password.length() == 0) {
            throw new java.lang.Error("No password");
        }
        byte[] pwBytes = password.getBytes();
        byte[] key = new byte[KEY_LENGTH];
        int pwLength = java.lang.Math.min(KEY_LENGTH, pwBytes.length);
        for (int i = 0; i < pwLength; i++) {
            key[i] = pwBytes[i];
        }
        for (int i = pwLength; i < KEY_LENGTH; i++) {
            key[i] = 0;
        }
        return key;
    }

    private void log(String function, String entry) {
        if (logger != null) {
            logger.log(function, entry);
        }
    }

    /**
     * Helper class for decyrpting data
     */
    private class CryptoResult {
        private byte[] data;
        private int length;

        public CryptoResult(byte[] data, int length) {
            this.data = data;
            this.length = length;
        }

        public byte[] getData() {
            return data;
        }

        public int getLength() {
            return length;
        }
    }
}
TOP

Related Classes of org.blync.client.DataAccess$CryptoResult

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.