/*
* Freeplane - mind map editor
* Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
* This file is modified by Dimitry Polivaev in 2008.
*
* 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 2 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 org.freeplane.features.map;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;
import org.freeplane.core.extension.IExtension;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.clipboard.ClipboardController;
import org.freeplane.features.map.MapWriter.Mode;
public class EncryptionModel implements IExtension {
public static EncryptionModel getModel(final NodeModel node) {
return (EncryptionModel) node.getExtension(EncryptionModel.class);
}
private String encryptedContent;
private boolean isAccessible = true;
/**
* is only set to false by the load mechanism. If the node is generated or
* it is decrypted once, this is always true.
*/
private boolean isDecrypted = true;
private IEncrypter mEncrypter;
/**
* password have to be stored in a StringBuilder as Strings cannot be deleted
* or overwritten.
*/
final private NodeModel node;
public EncryptionModel(final NodeModel node) {
this.node = node;
encryptedContent = null;
setAccessible(true);
isDecrypted = true;
}
/**
* @param encryptedContent
*/
public EncryptionModel(final NodeModel node, final String encryptedContent) {
this.node = node;
this.encryptedContent = encryptedContent;
setAccessible(false);
isDecrypted = false;
}
/**
*/
public boolean checkPassword(final IEncrypter encrypter) {
final String decryptedNode = decryptXml(encryptedContent, encrypter);
if (decryptedNode == null || !decryptedNode.equals("") && !decryptedNode.startsWith("<node ")) {
LogUtils.warn("Wrong password supplied (stored!=given).");
return false;
}
setEncrypter(encrypter);
return true;
}
/**
* @param mapController
* @return true, if the password was correct.
*/
public boolean decrypt(final MapController mapController, final IEncrypter encrypter) {
if (!checkPassword(encrypter)) {
return false;
}
setAccessible(true);
if (!isDecrypted) {
try {
final String childXml = decryptXml(encryptedContent, encrypter);
final String[] childs = childXml.split(ClipboardController.NODESEPARATOR);
for (int i = 0; i < childs.length; i++) {
final String string = childs[i];
if (string.length() == 0) {
continue;
}
pasteXML(string, node, mapController);
}
isDecrypted = true;
}
catch (final Exception e) {
LogUtils.severe(e);
setAccessible(false);
return true;
}
}
return true;
}
/**
* @return null if the password is wrong.
*/
private String decryptXml(final String encryptedString, final IEncrypter encrypter) {
final String decrypted = encrypter.decrypt(encryptedString);
return decrypted;
}
/**
*/
private String encryptXml(final StringBuffer childXml) {
try {
final String encrypted = mEncrypter.encrypt(childXml.toString());
return encrypted;
}
catch (final Exception e) {
throw new IllegalArgumentException("Can't encrypt the node.", e);
}
}
/**
* @param mapController
* @param mode
* @throws IOException
*/
private void generateEncryptedContent(final MapController mapController) throws IOException {
final StringWriter sWriter = new StringWriter();
for (final Iterator<NodeModel> i = node.getChildren().listIterator(); i.hasNext();) {
final NodeModel child = i.next();
mapController.getMapWriter().writeNodeAsXml(sWriter, child, MapWriter.Mode.FILE, true, true, false);
if (i.hasNext()) {
sWriter.write(ClipboardController.NODESEPARATOR);
}
}
final StringBuffer childXml = sWriter.getBuffer();
encryptedContent = encryptXml(childXml);
}
public String getEncryptedContent(final MapController mapController) {
if (isDecrypted) {
try {
generateEncryptedContent(mapController);
}
catch (final Exception e) {
LogUtils.severe(e);
}
}
return encryptedContent;
}
/**
* @return Returns the isAccessible (ie. if the node is decrypted
* (isAccessible==true) or not).
*/
public boolean isAccessible() {
return isAccessible;
}
private void pasteXML(final String pasted, final NodeModel target, final MapController mapController) {
try {
final NodeModel node = mapController.getMapReader().createNodeTreeFromXml(target.getMap(),
new StringReader(pasted), Mode.FILE);
mapController.insertNodeIntoWithoutUndo(node, target, target.getChildCount());
}
catch (final Exception ee) {
LogUtils.severe(ee);
}
}
/**
* @param isAccessible
* The isAccessible to set.
*/
public void setAccessible(final boolean isAccessible) {
this.isAccessible = isAccessible;
}
public void setEncrypter(final IEncrypter encrypter) {
mEncrypter = encrypter;
}
}