safedata viewer

This commit is contained in:
potzplitz 2024-03-28 19:05:25 +01:00
parent c22481fcf0
commit 4c041a8969
12 changed files with 413 additions and 4 deletions

View file

@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8
encoding/src=UTF-8

11
pom.xml
View file

@ -52,7 +52,16 @@
<artifactId>logback-classic</artifactId>
<version>1.2.13</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version> <!-- oder die neueste Version -->
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version> <!-- oder die neueste Version -->
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>

View file

@ -67,7 +67,7 @@ public class GuiData {
public void IndexData(ArrayList<String> migrate) throws IOException {
DatabaseManager mgr = new DatabaseManager();
mgr.queryData("levels");
File filelength = new File("C:\\ExtremeDemonList\\levels");
File[] filelengthindex = filelength.listFiles();

View file

@ -0,0 +1,68 @@
package gui;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import data.FetchData;
import data.ManageFiles;
public class AttemptsProgress {
JProgressBar bar = new JProgressBar();
JTextArea area = new JTextArea();
JScrollPane scroll = new JScrollPane(area);
JFrame main = new JFrame("Updater");
public void build() {
main.setSize(400, 300);
main.setLayout(null);
main.setResizable(false);
main.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
JLabel info = new JLabel("Speicherstand wird gelesen...");
info.setBounds(120, 1, 500, 30);
area.setEditable(false);
area.setLineWrap(true);
area.setWrapStyleWord(true);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setBounds(1, 60, 383, 201);
FetchData data = new FetchData();
bar.setBounds(1, 29, 382, 30);
bar.setMinimum(0);
bar.setMaximum(data.allLevels().size() - 1);
bar.setStringPainted(true);
main.add(info);
main.add(scroll);
main.add(bar);
main.setVisible(true);
}
public void update(String level, int attempts, int selection, int index) {
bar.setValue(index);
area.append(level + " >>> " + attempts + " Attempts\n");
area.setCaretPosition(area.getDocument().getLength());
}
public void close() {
JOptionPane.showMessageDialog(null, "Attempts wurden erfolgreich übertragen.", "Fertig", JOptionPane.INFORMATION_MESSAGE);
main.dispose();
}
}

View file

@ -229,7 +229,11 @@ public class MainGUI {
@Override
public void actionPerformed(ActionEvent e) {
data.modifyData(data.getLevelname().get(index), comp[index], Integer.parseInt(attempts.getText()));
if(!(comp[index] == Boolean.parseBoolean(data.getCompleted().get(index))) || !(attempts.getText().equals(data.getAttempts().get(index) + ""))) {
data.modifyData(data.getLevelname().get(index), comp[index], Integer.parseInt(attempts.getText()));
}
if(!comp[index]) {
contents.setBackground(Color.WHITE);

View file

@ -1,6 +1,17 @@
package gui;
import java.awt.Button;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import readsafefile.SafeFileManager;
import settingsfunctions.ReadAttempts;
public class SettingsGui {
@ -12,6 +23,78 @@ public class SettingsGui {
settings.setSize(500, 500);
settings.setVisible(true);
int val = 120;
int valold = 20;
StringBuilder str = new StringBuilder();
int jbuffer = 0;
for(int i = 0; i <= 3; i++) {
for(int j = 0; j <= 100; j++) {
str.append("_");
jbuffer = j;
}
JLabel separator = new JLabel(str.toString());
separator.setBounds(0, valold, 500, 30);
separator.setVisible(true);
settings.add(separator);
valold += val;
str.delete(0, jbuffer);
}
JLabel datenbank = new JLabel("Spielstand");
datenbank.setBounds(1, 10, 100, 30);
datenbank.setFont(new Font(null, Font.BOLD, 16));
datenbank.setVisible(true);
JLabel data = new JLabel("Datenbank");
data.setBounds(1, 130, 100, 30);
data.setFont(new Font(null, Font.BOLD, 16));
Button refresh = new Button("Speicherstand neu laden");
refresh.setBounds(250, 86, 150, 30);
refresh.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SafeFileManager mgr = new SafeFileManager();
try {
mgr.DecryptSafeFile();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
Button button = new Button("Attempts Indexieren");
button.setBounds(60, 86, 150, 30);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ReadAttempts atts = new ReadAttempts();
try {
atts.readAttempts();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
Button delete = new Button("Datenbank löschen");
delete.setBounds(150, 206, 150, 30);
settings.add(button);
settings.add(datenbank);
settings.add(refresh);
settings.add(data);
settings.add(delete);
}

View file

@ -1,6 +1,7 @@
package main;
import java.io.IOException;
import java.util.zip.DataFormatException;
import data.FetchData;
import data.ManageFiles;
@ -8,11 +9,14 @@ import database.DatabaseManager;
import filestructure.CreateFileStructure;
import gui.LoadMenu;
import preload.PreChecks;
import readsafefile.DecryptXOR;
import readsafefile.ReadAttemptsFromXML;
import readsafefile.SafeFileManager;
import settingsfunctions.LoadSettings;
public class Main {
public static void main(String[] args) throws IOException {
public static void main(String[] args) throws IOException, DataFormatException {
LoadMenu load = new LoadMenu();
load.onLoad();

View file

@ -8,4 +8,6 @@
requires jdash.common;
requires jlayer;
requires java.sql;
requires java.xml;
requires org.apache.commons.codec;
}

View file

@ -0,0 +1,67 @@
package readsafefile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.zip.DataFormatException;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import org.apache.commons.codec.binary.Base64;
public class DecryptXOR {
private static final String[] SAVES = {"CCGameManager.dat"};
private static final int XOR_KEY = 11;
private static byte[] xor(byte[] data, int key) {
byte[] result = new byte[data.length];
for (int i = 0; i < data.length; i++) {
result[i] = (byte) (data[i] ^ key);
}
return result;
}
private static byte[] decrypt(String data) throws IOException {
byte[] decodedData = Base64.decodeBase64(data.replace('-', '+').replace('_', '/'));
ByteArrayInputStream bis = new ByteArrayInputStream(decodedData);
GZIPInputStream gzipInputStream = new GZIPInputStream(bis);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = gzipInputStream.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
gzipInputStream.close();
bis.close();
bos.close();
return bos.toByteArray();
}
public static void decryptAndWriteFiles() throws IOException {
String appDataPath = System.getenv("LOCALAPPDATA") + "\\GeometryDash\\";
for (String save : SAVES) {
File inputFile = new File(appDataPath + save);
if (!inputFile.exists()) {
System.err.println("Input file not found: " + inputFile.getAbsolutePath());
continue;
}
byte[] encryptedData = new byte[(int) inputFile.length()];
try (FileInputStream fis = new FileInputStream(inputFile)) {
fis.read(encryptedData);
}
byte[] decryptedData = decrypt(new String(xor(encryptedData, XOR_KEY)));
File outputFile = new File("C:\\ExtremeDemonList\\userdata\\" + save + ".xml");
try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(outputFile), StandardCharsets.UTF_8)) {
osw.write(new String(decryptedData, StandardCharsets.UTF_8));
}
System.out.println("File decrypted and written: " + outputFile.getAbsolutePath());
}
}
}

View file

@ -0,0 +1,83 @@
package readsafefile;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class ReadAttemptsFromXML {
public String getAttempts(String level) {
String atts = "0";
try {
// Pfad zur XML-Datei
String filePath = "C:\\ExtremeDemonList\\userdata\\CCGameManager.dat.xml";
// XML-Datei einlesen und als DOM-Dokument parsen
File xmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
// Nach dem Eintrag für "Theory of Everything" suchen
NodeList levelNodes = doc.getElementsByTagName("d");
int index = 1;
for (int i = 0; i < levelNodes.getLength(); i++) {
Node levelNode = levelNodes.item(i);
if (levelNode.getNodeType() == Node.ELEMENT_NODE) {
Element levelElement = (Element) levelNode;
NodeList nameNodes = levelElement.getElementsByTagName("s");
for (int j = 0; j < nameNodes.getLength(); j++) {
Node nameNode = nameNodes.item(j);
if (nameNode.getNodeType() == Node.ELEMENT_NODE) {
Element nameElement = (Element) nameNode;
String name = nameElement.getTextContent();
if (name.equalsIgnoreCase(level)) {
// Wenn der Name übereinstimmt, die Anzahl der Versuche extrahieren
NodeList keyNodes = levelElement.getElementsByTagName("k");
for (int k = 0; k < keyNodes.getLength(); k++) {
Node keyNode = keyNodes.item(k);
if (keyNode.getNodeType() == Node.ELEMENT_NODE) {
Element keyElement = (Element) keyNode;
String key = keyElement.getTextContent();
if (key.equals("k18") && index == 2) {
// Wert des Schlüssels "k18" (Versuche) ausgeben
NodeList valueNodes = levelElement.getElementsByTagName("i");
Node valueNode = valueNodes.item(k);
atts = valueNode.getTextContent(); // Sobald die Anzahl der Versuche gefunden wurde, die Schleife beenden
}
if(key.equals("GS_7")) {
NodeList valueNodes = levelElement.getElementsByTagName("i");
Node valueNode = valueNodes.item(k);
System.out.println(valueNode.getTextContent() + " = practice percent");
}
}
}
index++;
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return atts;
}
}

View file

@ -0,0 +1,56 @@
package readsafefile;
import java.io.IOException;
import data.FetchData;
import database.Sqlite;
import gui.AttemptsProgress;
public class SafeFileManager {
public void DecryptSafeFile() throws IOException {
DecryptXOR dec = new DecryptXOR();
dec.decryptAndWriteFiles();
}
public void ReadIndexAttempts() throws IOException {
AttemptsProgress prog = new AttemptsProgress();
prog.build();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Sqlite database = new Sqlite("levels");
database.queryData("levels");
FetchData fetch = new FetchData();
try {
fetch.getGithubString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ReadAttemptsFromXML read = new ReadAttemptsFromXML();
String attempts;
for(int i = 0; i < fetch.allLevels().size(); i++) {
attempts = read.getAttempts(database.getLevelname().get(i));
prog.update(database.getLevelname().get(i), Integer.parseInt(attempts), 1, i);
database.modifyData(database.getLevelname().get(i), Boolean.parseBoolean(database.getCompleted().get(i)), Integer.parseInt(attempts));
}
}
});
thread.start();
}
}

View file

@ -0,0 +1,28 @@
package settingsfunctions;
import java.io.File;
import java.io.IOException;
import javax.swing.JOptionPane;
import readsafefile.SafeFileManager;
public class ReadAttempts {
public void readAttempts() throws IOException {
int response = JOptionPane.showConfirmDialog(null, "Es werden nun von allen Extreme Demons die Attempts in die Datenbank geschrieben. Dies kann eine Weile dauern. Trotzdem fortfahren?", "Attempts Einlesen", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (response == JOptionPane.YES_OPTION) {
SafeFileManager mgr = new SafeFileManager();
File file = new File("C:\\ExtremeDemonList\\userdata\\CCGameManager.dat.xml");
if(!file.exists()) {
mgr.DecryptSafeFile();
}
mgr.ReadIndexAttempts();
}
}
}