Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,22 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javafx.version>22</javafx.version>
</properties>

<dependencies>
<!-- JavaFX dependencies -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>

Comment on lines 18 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a UI interface is really cool.

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand All @@ -25,11 +38,28 @@

<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>ua.com.javarush.gnew.Main</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.4.0</version>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
Expand Down
23 changes: 23 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# Caesar Cipher Encryptor/Decryptor

### What was implemented?
```
All main tasks from the technical requirements were completed.
The `Encrypt` and `Decrypt` methods function correctly.
```
### What was not implemented?
```
The program does not support command-line interaction via scanner (CLI).
Instead, a graphical user interface (GUI) was implemented.
```
### Project Features
```
- Multilingual Support: The program supports:
Encryption and decryption of text in English and Ukrainian.
Automatically detects the language of the text and selects the appropriate alphabet.

- Brute-force Implementation: A brute-force mode is available for decrypting encrypted text.

- Graphical User Interface (GUI): A user-friendly GUI was implemented
for easier interaction with the program.
```

## Run the program

Expand Down
72 changes: 60 additions & 12 deletions src/main/java/ua/com/javarush/gnew/Main.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,80 @@
package ua.com.javarush.gnew;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import ua.com.javarush.gnew.crypto.BruteForceResult;
import ua.com.javarush.gnew.crypto.Cypher;
import ua.com.javarush.gnew.exeptions.FileNotFoundException;
import ua.com.javarush.gnew.file.ChangeFileName;
import ua.com.javarush.gnew.file.FileManager;
import ua.com.javarush.gnew.runner.ArgumentsParser;
import ua.com.javarush.gnew.runner.Command;
import ua.com.javarush.gnew.runner.RunOptions;

import java.io.IOException;
import java.nio.file.Path;

public class Main {
public class Main extends Application {


@Override
public void start(Stage primaryStage) throws IOException {
Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("UI.fxml"));
primaryStage.setTitle("Caesar Cipher");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}

public static Cypher cypher = new Cypher();
public static FileManager fileManager = new FileManager();
public static ArgumentsParser argumentsParser = new ArgumentsParser();
public static ChangeFileName changeFileName = new ChangeFileName();

public static void main(String[] args) {
Cypher cypher = new Cypher();
FileManager fileManager = new FileManager();
ArgumentsParser argumentsParser = new ArgumentsParser();
RunOptions runOptions = argumentsParser.parse(args);

if (args.length == 0) {
launch();
}
try {
RunOptions runOptions = argumentsParser.parse(args);
String content = fileManager.read(runOptions.getFilePath());

if (runOptions.getCommand() == Command.ENCRYPT) {
String content = fileManager.read(runOptions.getFilePath());
String encryptedContent = cypher.encrypt(content, runOptions.getKey());
String fileName = runOptions.getFilePath().getFileName().toString();
String newFileName = fileName.substring(0, fileName.length() - 4) + " [ENCRYPTED].txt";

Path newFilePath = runOptions.getFilePath().resolveSibling(newFileName);
fileManager.write(newFilePath, encryptedContent);
Path newFilePath = changeFileName.newFileName(runOptions, "ENCRYPTED");
fileManager.write(newFilePath, cypher.encrypt(content, runOptions.getKey()));
} else if (runOptions.getCommand() == Command.DECRYPT) {

Path newFilePath = changeFileName.newFileName(runOptions, "DECRYPTED");
fileManager.write(newFilePath, cypher.decrypt(content, runOptions.getKey()));
} else if (runOptions.getCommand() == Command.BRUTEFORCE) {

BruteForceResult result = cypher.bruteforce(content);
Path newFilePath = changeFileName.newFileNameWithKey(runOptions, "BRUTEFORCED", result.getKey());
fileManager.write(newFilePath, result.getDecryptedContent());
}
} catch (FileNotFoundException e) {
System.out.println("File not found");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
Comment on lines 36 to 64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's always a good idea to keep the logic out of the main method.

}
}















185 changes: 185 additions & 0 deletions src/main/java/ua/com/javarush/gnew/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package ua.com.javarush.gnew.controller;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import ua.com.javarush.gnew.crypto.BruteForceResult;
import ua.com.javarush.gnew.crypto.Cypher;
import ua.com.javarush.gnew.file.ChangeFileName;
import ua.com.javarush.gnew.file.FileManager;
import ua.com.javarush.gnew.runner.Command;
import ua.com.javarush.gnew.runner.RunOptions;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Path;
import java.util.ResourceBundle;

public class Controller implements Initializable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good job here


private final FileChooser fileChooser = new FileChooser();
private final ChangeFileName changeFileName = new ChangeFileName();
private final FileManager fileManager = new FileManager();
private final Cypher cypher = new Cypher();
private String selectedPath;

@FXML
private Label actualPathLabel;

@FXML
private AnchorPane pane;

@FXML
private ComboBox<String> dropdown;

@FXML
private Button openNewFileDir;

@FXML
private Button choesePathButton;

@FXML
private TextField inputKey;

@FXML
private Button doCypherButton;

@FXML
private Label newFilePath;

@FXML
private Label status;

@FXML
void choeseButtonCliced(ActionEvent event) {
File selectedFile = fileChooser.showOpenDialog(new Stage());
if (selectedFile != null) {
updatePathLabel(selectedFile.toString());
updateUIForSelectedCommand();
openNewFileDir.setDisable(true);
}
}

private void updatePathLabel(String path) {
actualPathLabel.setText(path);
}

private void updateUIForSelectedCommand() {
String selectedCommand = dropdown.getValue();
if ("Encrypt".equals(selectedCommand) || "Decrypt".equals(selectedCommand)) {
inputKey.setDisable(false);
} else if ("Bruteforce".equals(selectedCommand)) {
doCypherButton.setDisable(false);
}
}

@FXML
void keyInputSelected(KeyEvent event) {
if (inputKey.isFocused()) {
doCypherButton.setDisable(false);
}
}

@FXML
void doCypher(ActionEvent event) {
if (isFormValid()) {
try {
processCommand();
resetUIAfterProcessing();
} catch (IOException e) {
status.setText("Произошла ошибка: " + e.getMessage());
}
} else {
status.setText("Поля не заполнены");
}
}

private boolean isFormValid() {
return !actualPathLabel.getText().isEmpty() && !dropdown.getSelectionModel().isEmpty();
}

private void processCommand() throws IOException {
String selectedCommand = dropdown.getValue();
Integer key = getKey();
Path filePath = Path.of(actualPathLabel.getText());
selectedPath = actualPathLabel.getText();
RunOptions runOptions = new RunOptions(getCommand(selectedCommand), key, filePath);
String content = fileManager.read(runOptions.getFilePath());

if ("Encrypt".equals(selectedCommand)) {
writeToFile(changeFileName.newFileName(runOptions, "ENCRYPTED"), cypher.encrypt(content, runOptions.getKey()));
} else if ("Decrypt".equals(selectedCommand)) {
writeToFile(changeFileName.newFileName(runOptions, "DECRYPTED"), cypher.decrypt(content, runOptions.getKey()));
} else if ("Bruteforce".equals(selectedCommand)) {
BruteForceResult result = cypher.bruteforce(content);
writeToFile(changeFileName.newFileNameWithKey(runOptions, "DECRYPTED", result.getKey()), result.getDecryptedContent());
}
}

private Command getCommand(String command) {
return switch (command) {
case "Encrypt" -> Command.ENCRYPT;
case "Decrypt" -> Command.DECRYPT;
case "Bruteforce" -> Command.BRUTEFORCE;
default -> throw new IllegalArgumentException("Unknown command: " + command);
};
}

private Integer getKey() {
return "Bruteforce".equals(dropdown.getValue()) ? 0 : Integer.parseInt(inputKey.getText());
}

private void writeToFile(Path filePath, String content) throws IOException {
fileManager.write(filePath, content);
}

private void resetUIAfterProcessing() {
inputKey.clear();
inputKey.setDisable(true);
doCypherButton.setDisable(true);
openNewFileDir.setDisable(false);
actualPathLabel.setText("");
status.setText("Done");
}

@FXML
void methodChoesed (ActionEvent event) {
choesePathButton.setDisable(false);
inputKey.setVisible(!"Bruteforce".equals(dropdown.getSelectionModel().getSelectedItem()));
}

@FXML
void newFileOpenPath(ActionEvent event) {
File file = new File(selectedPath);
try {
Desktop.getDesktop().open(file.getParentFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@FXML
void paneMouseClicked(MouseEvent event) {
if (inputKey.isFocused()) {
pane.requestFocus();
}
}

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
dropdown.getItems().addAll("Encrypt", "Decrypt", "Bruteforce");
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Текстовые файлы", "*.txt"));
fileChooser.setInitialDirectory(new File("C:\\Users\\evgen\\Desktop"));
}
}
19 changes: 19 additions & 0 deletions src/main/java/ua/com/javarush/gnew/crypto/BruteForceResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ua.com.javarush.gnew.crypto;

public class BruteForceResult {
private String key;
private String decryptedContent;

public BruteForceResult(String decryptedContent, String key) {
this.decryptedContent = decryptedContent;
this.key = key;
}

public String getDecryptedContent() {
return decryptedContent;
}

public String getKey() {
return key;
}
}
Loading