/**
* Copyright (c) 2014 Matthias Jaenicke <matthias.jaenicke@student.kit.edu>,
* Matthias Plappert <undkc@student.kit.edu>,
* Julien Duman <uncyc@student.kit.edu>,
* Christian Dreher <uaeef@student.kit.edu>,
* Wasilij Beskorovajnov <uajkm@student.kit.edu> and
* Aydin Tekin <aydin.tekin@student.kit.edu>
*
* Released under the MIT license (refer to LICENSE.md)
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package edu.kit.iks.Cryptographics.Caesar.Experiment;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import org.xnap.commons.i18n.I18n;
import edu.kit.iks.Cryptographics.VisualizationContainerController;
import edu.kit.iks.CryptographicsLib.AbstractVisualizationController;
import edu.kit.iks.CryptographicsLib.AbstractVisualizationInfo;
import edu.kit.iks.CryptographicsLib.Configuration;
import edu.kit.iks.CryptographicsLib.Logger;
import edu.kit.iks.CryptographicsLib.MouseClickListener;
/**
* Controller for the last step of the histogram experiment phase.
*
* @author Wasilij Beskorovajnov.
*
*/
public class HistogramController extends AbstractVisualizationController {
/**
* localization.
*/
private static I18n i18n = Configuration.getInstance().getI18n(
HistogramController.class);
/**
* The model of this Controller.
*/
private CryptoModel model;
/**
* Integer value that shows what step the visualization has proceed.
*/
private int step;
/**
* Constructor
*
* @param visualizationInfo
*/
public HistogramController(AbstractVisualizationInfo visualizationInfo) {
super(visualizationInfo);
}
@Override
public void loadView() {
this.view = new HistogramView();
this.model = CryptoModel.getInstance();
this.step = 0;
// generate listener for the button proceed.
this.generateProceedListener();
// generate listener for the next/back buttons.
this.generateNavigationActionListener();
}
@Override
public String getHelp() {
if (this.getView().getHistogramCipher() != null) {
return HistogramController.i18n
.tr("Remember 'E' is in most cases the most frequent letter in a text."
+ " The column in the histogram above E would be the tallest one."
+ " So the tallest column in the histogram of a cipher would be the value E was shifted to."
+ " For example, 'H' is the tallest one. Simply 'H'- 'E' = 8 - 5 = 3. Et voila 3 is the key.");
}
return HistogramController.i18n
.tr("In order to find an unknown key you must try all of them."
+ " If you are lucky, you dont have to try many. In the worst case you have to try all of them.");
}
@Override
public void unloadView() {
this.view = null;
this.model = null;
}
// ---------------------------------------------------------------------------//
// -------------------------------private methods---------------------------//
private void generateKeyInputActionListener() {
// Not really much input checking necessary because the keyboard has only numerical values.
this.getView().getKeyInput().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (HistogramController.this.getView().getKeyInput().getText()
.length() > 0) {
int key = 0;
try {
key = Integer.parseInt(HistogramController.this
.getView().getKeyInput().getText());
} catch (NumberFormatException e1) {
Logger.error(e1);
}
if (HistogramController.this.getModel().isKeyValid(key)) {
String decryptedCipher = HistogramController.this
.getModel().dec(
key,
HistogramController.this.getView()
.getHistogramCipher());
HistogramController.this
.getView()
.getPlainText()
.setText(
HistogramController.this.wrapHtml(
decryptedCipher, 400));
if (key == HistogramController.this.getView()
.getSecretKey()) {
HistogramController.this
.getView()
.getKeyInput()
.setBorder(
BorderFactory
.createLineBorder(Color.green));
String explanations = HistogramController.this.wrapHtml(
HistogramController.i18n
.tr("You found the right key! See how easy it is with histograms?"
+ " If you want to try one more press proceed. Otherwise you can go directly to further information."
+ " There you can learn more about caesar's cipher."),
600);
HistogramController.this.getView()
.getExplanations().setText(explanations);
HistogramController.this.getView().getProceed()
.setVisible(true);
HistogramController.this.getView().requestFocus();
HistogramController.this.getView().remove(
HistogramController.this.getView()
.getNumpad());
HistogramController.this.getView().setNumpad(null);
HistogramController.this.getView().validate();
HistogramController.this.getView().repaint();
} else {
HistogramController.this.getView().getKeyInput()
.setText("");
String explanations = HistogramController.this.wrapHtml(
HistogramController.this.getModel()
.genRandomBlamings()
+ " "
+ HistogramController.i18n
.tr("The key was wrong."),
600);
HistogramController.this.getView()
.getExplanations().setText(explanations);
HistogramController.this
.getView()
.getKeyInput()
.setBorder(
BorderFactory
.createLineBorder(Color.red));
}
} else {
String explanations = HistogramController.this.wrapHtml(
HistogramController.this.getModel()
.genRandomBlamings()
+ " "
+ HistogramController.i18n
.tr("This key is invalid. Please type a number between 1 and 26. If you dont understand why,"
+ " it is recommended to go to early stages."),
600);
HistogramController.this.getView().getExplanations()
.setText(explanations);
HistogramController.this
.getView()
.getKeyInput()
.setBorder(
BorderFactory
.createLineBorder(Color.red));
}
} else {
HistogramController.this.getView().getKeyInput()
.setText("");
String explanations = HistogramController.this.wrapHtml(
HistogramController.this.getModel()
.genRandomBlamings()
+ " "
+ HistogramController.i18n
.tr("The key field was empty!"),
600);
HistogramController.this.getView().getExplanations()
.setText(explanations);
HistogramController.this
.getView()
.getKeyInput()
.setBorder(
BorderFactory.createLineBorder(Color.red));
}
}
});
}
private void generateKeyInputFocusListener() {
this.getView().getKeyInput().addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent arg0) {
if (HistogramController.this.getView().getNumpad() == null) {
HistogramController.this.getView().createNumpad(
HistogramController.this.getView().getKeyInput());
}
if (HistogramController.this.getView().getKeyInput()
.isEditable()) {
HistogramController.this
.getView()
.getKeyInput()
.setBorder(
BorderFactory.createLineBorder(Color.blue,
5));
}
}
@Override
public void focusLost(FocusEvent arg0) {
// Nothing to do here.
}
});
}
private void generateNavigationActionListener() {
this.getView().getBackButton().addActionListener(new ActionListener() {
/*
* @see java.awt.event.ActionListener#actionPerformed(java.awt .event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent event) {
VisualizationContainerController containerController = (VisualizationContainerController) HistogramController.this
.getParentController();
containerController.presentPreviousVisualizationController();
}
});
this.getView().getNextButton().addActionListener(new ActionListener() {
/*
* @see java.awt.event.ActionListener#actionPerformed(java.awt .event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent event) {
VisualizationContainerController containerController = (VisualizationContainerController) HistogramController.this
.getParentController();
containerController.presentNextVisualizationController();
}
});
}
private void generateDecrementMouseListener() {
this.getView().getDecrement()
.addMouseListener(new MouseClickListener() {
@Override
public void clicked(MouseEvent e) {
int bruteForceKey = 0;
try {
bruteForceKey = Integer
.parseInt(HistogramController.this
.getView().getBruteForceKey()
.getText()) - 1;
} catch (NumberFormatException e1) {
e1.printStackTrace();
}
if (HistogramController.this.getModel().isKeyValid(
bruteForceKey)) {
HistogramController.this.getView()
.getBruteForceKey()
.setText("" + bruteForceKey);
HistogramController.this
.getView()
.getPlainText()
.setText(
(HistogramController.this
.getModel()
.dec(bruteForceKey,
HistogramController.this
.getView()
.getCipherBruteForce()
.getText())));
HistogramController.this.isKeyFound(bruteForceKey);
} else {
// Key wrong. Nothing to do.
}
}
});
}
private void isKeyFound(int bruteForceKey) {
// compare the keys.
if (bruteForceKey == HistogramController.this.getView().getSecretKey()) {
HistogramController.this.getView().getKeyControl()
.setBorder(BorderFactory.createLineBorder(Color.green, 5));
HistogramController.this
.getView()
.getAnnouncement()
.setText(
HistogramController.this.wrapHtml(
HistogramController.this.getModel()
.genRandomGrats()
+ " "
+ HistogramController.i18n
.tr("You found the secret key and are now able to read the secret message. The Key is")
+ " "
+ bruteForceKey
+ ". "
+ HistogramController.i18n
.tr("Now only the histogram technique left."),
500));
HistogramController.this
.getView()
.getExplanations()
.setText(
HistogramController.i18n.tr("The Key was")
+ " "
+ bruteForceKey
+ ". "
+ HistogramController.i18n
.tr("Congratulations! Yeay! Now lets try to break it with histograms."));
} else {
HistogramController.this
.getView()
.getAnnouncement()
.setText(
HistogramController.this.getModel()
.genRandomBlamings());
HistogramController.this.getView().getKeyControl()
.setBorder(BorderFactory.createLineBorder(Color.blue, 2));
}
}
private void generateIncrementMouseListener() {
this.getView().getIncrement()
.addMouseListener(new MouseClickListener() {
@Override
public void clicked(MouseEvent e) {
int bruteForceKey = 0;
try {
bruteForceKey = Integer
.parseInt(HistogramController.this
.getView().getBruteForceKey()
.getText()) + 1;
} catch (NumberFormatException e1) {
e1.printStackTrace();
}
if (HistogramController.this.getModel().isKeyValid(
bruteForceKey)) {
HistogramController.this.getView()
.getBruteForceKey()
.setText("" + bruteForceKey);
HistogramController.this
.getView()
.getPlainText()
.setText(
(HistogramController.this
.getModel()
.dec(bruteForceKey,
HistogramController.this
.getView()
.getCipherBruteForce()
.getText())));
HistogramController.this.isKeyFound(bruteForceKey);
} else {
// Key wrong. Nothing to do.
}
}
});
}
private void generateProceedListener() {
this.getView().getProceed().addMouseListener(new MouseClickListener() {
@Override
public void clicked(MouseEvent e) {
if (HistogramController.this.getStep() == 0) {
HistogramController.this.setStep(1);
HistogramController.this.getView()
.unloadExplanationAndForwardingPanel();
// Keys smaller than 5 are too simple and bigger then 20 could be annoying.
int secret = HistogramController.this.getModel()
.generateRandomInt(5, 20);
HistogramController.this.getView().setupBruteForceCore(
secret,
HistogramController.this.getModel()
.genRandomCipher(secret));
HistogramController.this.generateIncrementMouseListener();
HistogramController.this.generateDecrementMouseListener();
HistogramController.this
.getView()
.getKeyControl()
.setBorder(
BorderFactory.createLineBorder(Color.blue,
2));
HistogramController.this
.getView()
.setupExplanationAndForwarding(
HistogramController.this.wrapHtml(
HistogramController.i18n
.tr("Or: If you want to try a more elaborate way breaking Caesar-cipher "
+ "you can try histogram technique by pressing the button below."),
900), GridBagConstraints.PAGE_END);
HistogramController.this.generateProceedListener();
HistogramController.this
.getView()
.getProceed()
.setText(
HistogramController.i18n
.tr("Try histogram technique"));
} else if (HistogramController.this.getStep() == 1) {
// unload the old explanations.
HistogramController.this.getView()
.unloadExplanationAndForwardingPanel();
HistogramController.this.getView().remove(
HistogramController.this.getView().getKeyControl());
HistogramController.this.getView().setKeyControl(null);
String explanation = HistogramController.this.getModel()
.genRandomText();
HistogramController.this.getView()
.setHistogramOriginalText(
HistogramController.this.wrapHtml(
explanation, 400));
HistogramController.this.getView()
.setupExplanationAndForwarding(
HistogramController.this.wrapHtml(
explanation, 700),
GridBagConstraints.PAGE_START);
// Build the new experiment.
HistogramController.this.setStep(2);
HistogramController.this.generateProceedListener();
HistogramController.this.getView()
.setupHistogramContainer();
HistogramController.this.getView().setupPlainHistogram(
explanation);
HistogramController.this.getView().revalidate();
HistogramController.this.getView().repaint();
} else if (HistogramController.this.getStep() == 2) {
HistogramController.this.getView().getProceed()
.setVisible(false);
HistogramController.this.setStep(3);
String textToEncrypt = HistogramController.this.getView()
.getHistogramOriginalText();
String htmlCipher = HistogramController.this.getModel()
.enc(3, textToEncrypt);
HistogramController.this
.getView()
.getExplanations()
.setText(
HistogramController.this.wrapHtml(
HistogramController.i18n
.tr("When you look at the histogram of the cipher you can see that 'H' is now the most frequent one."
+ " It is obvious that the letter 'E' was shifted to 'H'. When we substract 'H' - 'E' we get the key."
+ " Put the key 3 in the box below and let the programm decrypt the cipher with it."),
700));
HistogramController.this.getView().setupCipherHistogram(
htmlCipher);
HistogramController.this.getView().setHistogramCipher(
htmlCipher);
HistogramController.this.getView().setSecretKey(3);
HistogramController.this.getView().setupKeyInput();
HistogramController.this.generateKeyInputFocusListener();
HistogramController.this.generateKeyInputActionListener();
HistogramController.this.getView().validate();
HistogramController.this.getView().repaint();
} else {
// Build the new experiment.
HistogramController.this.setStep(HistogramController.this
.getStep() + 1);
HistogramController.this.getView().unloadCipherHistogram();
HistogramController.this.getView().unloadKeyInput();
HistogramController.this.getView().getPlainText()
.setText("");
HistogramController.this.getView().requestFocus();
HistogramController.this
.getView()
.getExplanations()
.setText(
HistogramController.i18n
.tr("Ok lets try another one!"));
String plainText = HistogramController.this.getModel()
.genRandomText();
int key = HistogramController.this.getModel().generateKey();
String cipher = HistogramController.this.getModel().enc(
key, plainText);
HistogramController.this.getView().setupCipherHistogram(
HistogramController.this.wrapHtml(cipher, 400));
HistogramController.this.getView().setupKeyInput();
HistogramController.this.generateKeyInputFocusListener();
HistogramController.this.generateKeyInputActionListener();
HistogramController.this.getView().setHistogramCipher(
cipher);
HistogramController.this.getView().setSecretKey(key);
HistogramController.this.getView().getProceed()
.setVisible(false);
if (HistogramController.this.getView().getNumpad() != null) {
HistogramController.this.getView().remove(
HistogramController.this.getView().getNumpad());
HistogramController.this.getView().setNumpad(null);
}
HistogramController.this.getView().validate();
HistogramController.this.getView().repaint();
}
}
});
}
private String wrapHtml(String text, int width) {
return "<html><body><div width=" + width + "px>" + text
+ "</div></body></html>";
}
// ---------------------------------------------------------------------------------//
// -----------------------------------Getter/Setter---------------------------------//
/**
* @return the model
*/
public CryptoModel getModel() {
return this.model;
}
/**
* @return the step
*/
public int getStep() {
return this.step;
}
/**
* Gets the view
*
* @return The view of this controller
*/
@Override
public HistogramView getView() {
return (HistogramView) this.view;
}
/**
* @param model
* the model to set
*/
public void setModel(CryptoModel model) {
this.model = model;
}
/**
* @param step
* the step to set
*/
public void setStep(int step) {
this.step = step;
}
}