net.alegen.datpass.library.configure.XMLConfigurator.java Source code

Java tutorial

Introduction

Here is the source code for net.alegen.datpass.library.configure.XMLConfigurator.java

Source

/*
 * EasyHash - command line utility for creating hashes
 * Copyright (C) 2013 Alexandru Geana (alegen)
 *
 * 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.
 *
 * 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 net.alegen.datpass.library.configure;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.alegen.datpass.library.Profile;
import net.alegen.datpass.library.crypto.CryptoManager;
import net.alegen.datpass.library.crypto.CryptoManager.EncryptionOutput;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class XMLConfigurator implements Configurator {

    private static final Logger log = LoggerFactory.getLogger(Configurator.class);

    public static Configurator getInstance(String configFileName) {
        Configurator newInstance = null;
        try {
            if (configFileName == null)
                newInstance = new XMLConfigurator();
            else
                newInstance = new XMLConfigurator(configFileName);
        } catch (IOException | JDOMException e) {
            return null;
        }
        return newInstance;
    }

    private final Element root;
    String configFileName;

    private XMLConfigurator() throws IOException, JDOMException {
        this("dpasscfg.xml");
    }

    public XMLConfigurator(String configFileName) throws IOException, JDOMException {
        try {
            this.configFileName = configFileName;
            File configFile = new File(configFileName);
            if (!configFile.exists()) {
                this.root = new Element(XmlConstants.DATPASS);
                Document doc = new Document(this.root);
                XMLOutputter xmlOutput = new XMLOutputter();
                xmlOutput.setFormat(Format.getPrettyFormat());
                FileWriter fileWriter = new FileWriter(configFileName);
                xmlOutput.output(doc, fileWriter);
                fileWriter.flush();
                fileWriter.close();
            } else
                this.root = new SAXBuilder().build(configFile).getRootElement();
        } catch (JDOMException e) {
            log.error("The XML configuration file is not valid. Please check for syntax errors.");
            throw e;
        } catch (IOException e) {
            log.error("There was a problem when trying to read the XML configuration file.");
            throw e;
        }
    }

    private Element getProfileRoot(String profileName) {
        Element profilesElem = this.root.getChild(XmlConstants.PROFILES);
        for (Element elem : profilesElem.getChildren())
            if (elem.getName().equals(XmlConstants.PROFILE)) {
                String xmlname = elem.getAttributeValue(FieldManager.NAME_FIELD);
                if (xmlname != null && xmlname.equals(profileName))
                    return elem;
            }
        return null;
    }

    private boolean isValidField(Element element) {
        if (element.getChild(XmlConstants.CIPHERTEXT) != null && element.getChild(XmlConstants.ENC_SALT) != null
                && element.getChild(XmlConstants.ENC_IV) != null && element.getChild(XmlConstants.HMAC) != null)
            return true;
        return false;
    }

    public boolean profileExists(String profileName) {
        for (String profile : this.listProfiles())
            if (profile.equals(profileName))
                return true;
        return false;
    }

    @Override
    public Profile loadProfile(String profileName, String password) {
        Element xmlprofile = this.getProfileRoot(profileName);
        if (xmlprofile != null) {
            Profile profile = new Profile(profileName);
            for (Element xmlfield : xmlprofile.getChildren())
                if (this.isValidField(xmlfield)) {
                    EncryptionOutput encOutput = new CryptoManager.EncryptionOutput(xmlfield);
                    String xmlhmac = xmlfield.getChild(XmlConstants.HMAC).getTextNormalize();

                    String genhmac = CryptoManager.getInstance().generateHmac(encOutput, password);
                    if (xmlhmac != genhmac)
                        return null;

                    String plaintext = CryptoManager.getInstance().decrypt(encOutput, password);
                    profile.setValue(xmlfield.getName(), plaintext);
                }
            return profile;
        }
        return null;
    }

    @Override
    public List<String> listProfiles() {
        List<String> profiles = new ArrayList<String>();
        Element profilesElem = this.root.getChild(XmlConstants.PROFILES);
        if (profilesElem != null)
            for (Element elem : profilesElem.getChildren())
                if (elem.getName() == XmlConstants.PROFILE) {
                    String name = elem.getAttributeValue(FieldManager.NAME_FIELD);
                    if (name != null)
                        profiles.add(name);
                }
        return profiles;
    }

    @Override
    public boolean saveProfile(Profile profile, String profileKey) {
        String profileName = profile.getValue(FieldManager.NAME_FIELD);
        if (this.profileExists(profileName))
            return false;
        if (!FieldManager.getInstance().verityProfileFields(profile))
            return false;
        Element profilesElem = this.root.getChild(XmlConstants.PROFILES);
        if (profilesElem == null) {
            profilesElem = new Element(XmlConstants.PROFILES);
            this.root.addContent(profilesElem);
        }
        Element newProfileElem = new Element(XmlConstants.PROFILE);
        newProfileElem.setAttribute(FieldManager.NAME_FIELD, profile.getValue(FieldManager.NAME_FIELD));
        for (Map.Entry<FieldManager.Field, String> field : profile.getValues().entrySet()) {
            if (!field.getKey().toString().equals(FieldManager.NAME_FIELD)) {
                Element fieldElem = new Element(field.getKey().toString());
                CryptoManager.EncryptionOutput output = CryptoManager.getInstance().encrypt(field.getValue(),
                        profileKey);
                String generatedHmac = CryptoManager.getInstance().generateHmac(output, profileKey);
                Element ciphertextElem = new Element(XmlConstants.CIPHERTEXT);
                ciphertextElem.setText(output.getCypherText());
                fieldElem.addContent(ciphertextElem);
                Element encSaltElem = new Element(XmlConstants.ENC_SALT);
                encSaltElem.setText(output.getSalt());
                fieldElem.addContent(encSaltElem);
                Element encIvElem = new Element(XmlConstants.ENC_IV);
                encIvElem.setText(output.getIV());
                fieldElem.addContent(encIvElem);
                Element hmacElem = new Element(XmlConstants.HMAC);
                hmacElem.setText(generatedHmac);
                fieldElem.addContent(hmacElem);
                newProfileElem.addContent(fieldElem);
            }
        }
        profilesElem.addContent(newProfileElem);
        return true;
    }

    @Override
    public void removeProfile(String profileName) {
        Element profilesElem = this.root.getChild(XmlConstants.PROFILES);
        for (Element elem : profilesElem.getChildren()) {
            String name = elem.getAttributeValue(FieldManager.NAME_FIELD);
            if (name != null && name.equals(profileName)) {
                elem.detach();
                return;
            }
        }
    }

    @Override
    public boolean saveConfig() {
        XMLOutputter xmlOutput = new XMLOutputter();
        Format format = Format.getPrettyFormat();
        format.setIndent("    ");
        xmlOutput.setFormat(format);
        try {
            xmlOutput.output(this.root.getDocument(), new FileOutputStream(configFileName));
            return true;
        } catch (IOException e) {
            log.error("An IO exception occured while saving data.");
            return false;
        }
    }

    public boolean setValue(String name, String value) {
        if (name == null || name.isEmpty() || value == null || value.isEmpty())
            return false;
        Element appValuesElem = this.root.getChild(XmlConstants.APP_VALUES);
        if (appValuesElem == null) {
            appValuesElem = new Element(XmlConstants.APP_VALUES);
            this.root.addContent(appValuesElem);
        }
        boolean elemExists = false;
        for (Element valueElem : appValuesElem.getChildren()) {
            String nameAttrib = valueElem.getAttributeValue(XmlConstants.NAME);
            if (nameAttrib != null && nameAttrib.equals(name)) {
                elemExists = true;
                valueElem.setText(value);
                break;
            }
        }
        if (!elemExists) {
            Element newElem = new Element(XmlConstants.VALUE);
            newElem.setAttribute(XmlConstants.NAME, name);
            newElem.setText(value);
            appValuesElem.addContent(newElem);
        }
        return true;
    }

    public String getValue(String name) {
        if (name == null || name.isEmpty())
            throw new IllegalArgumentException();
        Element appValuesElem = this.root.getChild(XmlConstants.APP_VALUES);
        if (appValuesElem != null)
            for (Element valueElem : appValuesElem.getChildren())
                if (valueElem.getAttributeValue(XmlConstants.NAME).equals(name))
                    return valueElem.getText();
        return null;
    }

    public Map<String, String> allValues() {
        Map<String, String> retVal = new HashMap<String, String>();
        Element appValuesElem = this.root.getChild(XmlConstants.APP_VALUES);
        for (Element valueElem : appValuesElem.getChildren())
            retVal.put(valueElem.getAttributeValue(XmlConstants.NAME), valueElem.getText());
        return retVal;
    }

    public static class XmlConstants {

        private XmlConstants() {
        }

        public static final String DATPASS = "datpass";
        public static final String PROFILES = "profiles";
        public static final String PROFILE = "profile";
        public static final String CIPHERTEXT = "ciphertext";
        public static final String ENC_SALT = "enc-salt";
        public static final String ENC_IV = "enc-iv";
        public static final String HMAC = "hmac";
        public static final String APP_VALUES = "app-values";
        public static final String VALUE = "value";
        public static final String NAME = "name";
    }
}