com.nuvolect.securesuite.util.OmniFile.java Source code

Java tutorial

Introduction

Here is the source code for com.nuvolect.securesuite.util.OmniFile.java

Source

/*
 * Copyright (c) 2017. Nuvolect LLC
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * Contact legal@nuvolect.com for a less restrictive commercial license if you would like to use the
 * software without the GPLv3 restrictions.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program.  If not,
 * see <http://www.gnu.org/licenses/>.
 *
 */

package com.nuvolect.securesuite.util;//

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.nuvolect.securesuite.main.CConst;
import com.nuvolect.securesuite.webserver.MimeUtil;
import com.nuvolect.securesuite.webserver.connector.FileObj;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedOutputStream;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Locale;

/**
 * Represent a file that can either be an encrypted file or a standard java file.
 * Mirror support methods as necessary.
 */
public class OmniFile {

    private static boolean DEBUG = LogUtil.DEBUG;

    /**
     * Volume ID for the specified file. The volume ID ends with the '_' underscore character.
     */
    private final String m_volumeId;
    /**
     * Standard unix clear-text file. When the crypt file is in use this file is null.
     */
    private java.io.File m_std_file;
    /**
     * Encrypted unix file. When the standard java file is in use thsi file is null.
     */
    private info.guardianproject.iocipher.File m_cry_file;

    /**
     * Convenience boolean for standard(clear)/encrypted file.
     */
    private boolean m_isCryp;
    /**
     * Flag set when file is created indicating file is a root directory of the volume.
     */
    private boolean m_isRoot; // File is root of the filesystem
    /**
     * Hash, if the file was created from a hash, otherwise null;
     */
    private String m_volumeHash;

    /**
     * Debugging only
     */
    private String m_name; // Name as reported by file system
    private String m_absolutePath; // Complete path including root
    private String m_path; // Path relative to the volume
    private String m_lastModified; // Text of last time modified

    public void calcDebug(String myTag) {

        m_name = this.getName();
        m_path = this.getPath();
        m_absolutePath = this.getAbsolutePath();
        m_lastModified = TimeUtil.friendlyTimeMDYM(this.lastModified());
        //            LogUtil.log( OmniFile.class, myTag+ " OmniFile:  "+ m_name+" last modified: "+ m_lastModified);
    }

    /**
     * Create an OmniFile from volumeId and path components.
     * @param volumeId
     * @param path
     */
    public OmniFile(String volumeId, String path) {

        m_volumeId = volumeId;
        m_isRoot = Omni.isRoot(volumeId, path);
        m_isCryp = m_volumeId.contentEquals(Omni.cryptoVolumeId);
        m_volumeHash = null;

        if (m_isCryp) {
            m_cry_file = new info.guardianproject.iocipher.File(path);
            /**
             * It appears as though IOCipher is ignoring file/folder timestamps, a big issue.
             */
            //            long time = System.currentTimeMillis();
            //            boolean success = m_cry_file.setLastModified( time );
            //            if( ! success)
            //                LogUtil.log(LogUtil.LogType.OMNI_FILE, "setLastModfiedFailed for: "+path);
            //            if( time != lastModified())
            //                LogUtil.log(LogUtil.LogType.OMNI_FILE,
            //                        "time: "+time+" not equal "+lastModified());
        } else {
            String root = Omni.getRoot(volumeId);
            String absolutePath = (root + path).replace("//", "/");
            m_std_file = new java.io.File(absolutePath);
        }

        if (DEBUG)
            calcDebug("OmniFile( vId, path)");
    }

    /**
     * Create an OmniFile from a volumeHash which has the
     * volume id on the front end of a hash.
     * @param volumeHash
     */
    public OmniFile(String volumeHash) {

        if (volumeHash.startsWith("/"))
            volumeHash = volumeHash.substring(1);

        m_volumeHash = volumeHash;
        String segments[] = volumeHash.split("_");
        m_volumeId = segments[0];
        m_isRoot = Omni.isRoot(volumeHash);
        m_isCryp = m_volumeId.contentEquals(Omni.cryptoVolumeId);

        String path = (OmniHash.decode(segments[1]) + "/").replace("//", "/");
        String rootPath = Omni.getRoot(m_volumeId);
        if (!rootPath.contentEquals("/"))
            path = (rootPath + path).replace("//", "/");

        if (m_isCryp)
            m_cry_file = new info.guardianproject.iocipher.File(path);
        else
            m_std_file = new java.io.File(path);

        if (DEBUG)
            calcDebug("OmniFile( volumeHash)");
    }

    /**
     * Get the hash of the file not including the volume root.
     * @return
     */
    public String getHash() {

        return m_volumeId + "_" + OmniHash.encode(getPath());
    }

    /**
     * Returns a new file made from the pathname of the parent of this file.
     * This is the path up to but not including the last name in the path. {@code null} is
     * returned when there is no parent.
     *
     * @return a new file representing this file's parent or {@code null}.
     */
    public OmniFile getParentFile() {

        if (m_isCryp) {

            info.guardianproject.iocipher.File parent = m_cry_file.getParentFile();
            if (parent == null)
                return null;
            else
                return new OmniFile(m_volumeId, parent.getPath());
        } else {
            if (m_isRoot)
                return null;
            java.io.File parent = m_std_file.getParentFile();
            if (parent == null)
                return null;
            else {
                String parentPath = parent.getPath();
                String path = OmniUtil.getShortPath(m_volumeId, parentPath);
                return new OmniFile(m_volumeId, path);
            }
        }
    }

    public String getVolumeId() {
        return m_volumeId;
    }

    /**
     * Return a short path of the file, not including root.
     * Member vars m_volumeId and m_std_file must be set.
     * @return
     */
    public String getPath() {

        if (m_isRoot)
            return CConst.ROOT;

        String absolutePath;
        if (m_isCryp)
            absolutePath = m_cry_file.getPath();
        else
            absolutePath = m_std_file.getPath();

        String root = Omni.getRoot(this.m_volumeId);
        String path = ("/" + StringUtils.removeStart(absolutePath, root)).replace("//", "/");
        return path;
    }

    public String getAbsolutePath() {

        if (m_isCryp)
            return m_cry_file.getAbsolutePath();
        else
            return m_std_file.getAbsolutePath();
    }

    public String getCanonicalPath() throws IOException {

        if (m_isCryp)
            return m_cry_file.getCanonicalPath();
        else
            return m_std_file.getCanonicalPath();
    }

    public String getName() {

        if (this.isRoot())
            return Omni.getVolumeName(m_volumeId);

        String name;
        if (m_isCryp)
            name = m_cry_file.getName();
        else
            name = m_std_file.getName();

        return name;
    }

    public String getExtension() {

        return FilenameUtils.getExtension(getName()).toLowerCase(Locale.US);
    }

    public OmniFile[] listFiles() {

        if (m_isCryp) {

            info.guardianproject.iocipher.File files[] = m_cry_file.listFiles();
            if (files == null || files.length == 0)
                return new OmniFile[0];
            OmniFile[] omniFiles = new OmniFile[files.length];

            for (int i = 0; i < files.length; i++)
                omniFiles[i] = new OmniFile(m_volumeId, files[i].getPath());

            return omniFiles;
        } else {
            java.io.File files[] = m_std_file.listFiles();
            if (files == null || files.length == 0)
                return new OmniFile[0];
            OmniFile[] omniFiles = new OmniFile[files.length];

            for (int i = 0; i < files.length; i++) {
                String path = OmniUtil.getShortPath(m_volumeId, files[i].getPath());
                omniFiles[i] = new OmniFile(m_volumeId, path);
            }

            return omniFiles;
        }
    }

    public OmniFile[] listFiles(FileFilter filter) {

        java.io.File files[] = m_std_file.listFiles(filter);
        if (files == null || files.length == 0)
            return new OmniFile[0];
        OmniFile[] omniFiles = new OmniFile[files.length];

        for (int i = 0; i < files.length; i++) {
            String path = OmniUtil.getShortPath(m_volumeId, files[i].getPath());
            omniFiles[i] = new OmniFile(m_volumeId, path);
        }

        return omniFiles;
    }

    public long lastModified() {
        if (m_isCryp)
            return m_cry_file.lastModified();
        else
            return m_std_file.lastModified();
    }

    public void setLastModified(long timeInSec) {

        if (timeInSec <= 0)
            return;

        if (m_isCryp)
            m_cry_file.setLastModified(timeInSec);
        else
            m_std_file.setLastModified(timeInSec);
    }

    /**
     * Set last modfied time based on the current time.
     */
    public void setLastModified() {
        long timeInSec = System.currentTimeMillis() / 1000;
        if (m_isCryp)
            m_cry_file.setLastModified(timeInSec);
        else
            m_std_file.setLastModified(timeInSec);
    }

    public long length() {
        if (m_isCryp)
            return m_cry_file.length();
        else
            return m_std_file.length();
    }

    public long getTotalSpace() {
        if (m_isCryp)
            return m_cry_file.getTotalSpace();
        else
            return m_std_file.getTotalSpace();
    }

    public long getFreeSpace() {
        if (m_isCryp)
            return m_cry_file.getFreeSpace();
        else
            return m_std_file.getFreeSpace();
    }

    public boolean canRead() {
        if (m_isCryp)
            return m_cry_file.canRead();
        else
            return m_std_file.canRead();
    }

    public boolean canWrite() {
        if (m_isCryp)
            return m_cry_file.canWrite();
        else
            return m_std_file.canWrite();
    }

    public boolean exists() {
        if (m_isCryp)
            return m_cry_file.exists();
        else
            return m_std_file.exists();
    }

    public boolean isFile() {
        if (m_isCryp)
            return m_cry_file.isFile();
        else
            return m_std_file.isFile();
    }

    public boolean isDirectory() {
        if (m_isCryp)
            return m_cry_file.isDirectory();
        else
            return m_std_file.isDirectory();
    }

    public boolean mkdirs() {
        if (m_isCryp)
            return m_cry_file.mkdirs();
        else
            return m_std_file.mkdirs();
    }

    public boolean mkdir() {
        if (m_isCryp)
            return m_cry_file.mkdir();
        else
            return m_std_file.mkdir();
    }

    public boolean createNewFile() {
        try {
            if (m_isCryp)
                return m_cry_file.createNewFile();
            else
                return m_std_file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean renameFile(OmniFile newFile) {
        if (m_isCryp)
            return m_cry_file.renameTo(newFile.getCryFile());
        else
            return m_std_file.renameTo(newFile.getStdFile());
    }

    public boolean isCryp() {
        return m_isCryp;
    }

    public boolean isStd() {
        return !m_isCryp;
    }

    public info.guardianproject.iocipher.File getCryFile() {
        return m_cry_file;
    }

    public java.io.File getStdFile() {
        return m_std_file;
    }

    public OutputStream getOutputStream() throws FileNotFoundException {
        if (m_isCryp)
            return new info.guardianproject.iocipher.FileOutputStream(m_cry_file);
        else
            return new java.io.FileOutputStream(m_std_file);
    }

    public InputStream getFileInputStream() {

        try {

            if (m_isCryp)
                return new info.guardianproject.iocipher.FileInputStream(m_cry_file);
            else
                return new java.io.FileInputStream(m_std_file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean delete() {
        if (m_isCryp)
            return m_cry_file.delete();
        else
            return m_std_file.delete();
    }

    public String getMime() {

        if (this.isDirectory())
            return "directory";

        if (m_volumeHash != null) {

            String hash = m_volumeHash;

            String segments[] = m_volumeHash.split("_");
            if (segments.length > 1) {
                hash = segments[1];
            }

            try {
                String path = OmniHash.decodeWithException(hash);
                String extension = FilenameUtils.getExtension(path).toLowerCase(Locale.US);
                return MimeUtil.getMime(extension);
            } catch (UnsupportedEncodingException e) {
                return "";
            }
        }

        return MimeUtil.getMime(this);
    }

    public boolean isRoot() {

        return m_isRoot;
    }

    /**
     * Return an arrayList of file objects for this file.
     * @param httpIpPort
     * @return
     */
    public JsonArray listFileObjects(String httpIpPort) {

        if (DEBUG)
            LogUtil.log(OmniFile.class, "ListFileObjects from:  " + this.getPath() + ", hash: " + this.getHash());

        JsonArray filesArray = new JsonArray();
        OmniFile[] files = this.listFiles();
        if (files == null || files.length == 0)
            return filesArray;

        int i = 0;
        String indent = "";
        String volumeId = this.getVolumeId();

        for (OmniFile file : files) {

            JsonObject fileObj = FileObj.makeObj(volumeId, file, httpIpPort);
            filesArray.add(fileObj);

            String type = file.isDirectory() ? " dir  " : " file ";
            if (DEBUG)
                LogUtil.log(OmniFile.class,
                        "ListFileObjects " + indent + ++i + type + file.getName() + ", hash: " + file.getHash());
        }

        return filesArray;
    }

    public JsonObject getFileObject(String url) {
        return FileObj.makeObj(getVolumeId(), this, url);
    }

    /**
     * Return contents of a file as a string.
     * @return
     */
    public String readFile() {

        String fileContents = "";
        StringBuilder sb = new StringBuilder();

        try {
            InputStream is = this.getFileInputStream();

            byte[] buffer = new byte[4096];
            int len;
            while ((len = is.read(buffer)) > 0) {

                String s = new String(buffer, 0, len, "UTF-8");
                sb.append(s);
            }
            fileContents = sb.toString();

            if (is != null)
                is.close();
        } catch (FileNotFoundException e) {
            LogUtil.logException(OmniFile.class, e);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return fileContents;
    }

    /**
     * Write a string to the file.
     * @param fileContents
     * @return
     */
    public boolean writeFile(String fileContents) {

        boolean success = true;
        try {
            OutputStream out = null;

            out = new BufferedOutputStream(this.getOutputStream());

            out.write(fileContents.getBytes());

            if (out != null)
                out.close();
        } catch (IOException e) {
            LogUtil.logException(OmniFile.class, "File write failed: ", e);
            success = false;
        }
        return success;
    }

    /**
     * Return the dimensions of an file if it is an image.
     * Return an empty string if the file is not an image.
     * @return
     */
    public String getDim() {

        return OmniImage.getDim(this);
    }

    /**
     * Return a PhotoSwipe object
     * @param httpIpPort
     * @return JSONObject
     */
    public JsonObject getPsObject(String httpIpPort) {
        JsonObject psObject = new JsonObject();
        psObject.addProperty("name", getName());
        psObject.addProperty("src", httpIpPort + "/" + getHash());
        OmniImage.addPsImageSize(this, psObject);
        return psObject;
    }
}