diff --git a/chat/pom.xml b/chat/pom.xml
index c771398..01c19d0 100644
--- a/chat/pom.xml
+++ b/chat/pom.xml
@@ -64,6 +64,12 @@
sqlite-jdbc
3.48.0.0
+
+ org.slf4j
+ slf4j-api
+ 2.0.16
+
+
diff --git a/chat/src/main/java/module-info.java b/chat/src/main/java/module-info.java
index 4fb2698..ce8c6ff 100644
--- a/chat/src/main/java/module-info.java
+++ b/chat/src/main/java/module-info.java
@@ -7,6 +7,7 @@ module rtgre.chat {
requires net.synedra.validatorfx;
requires org.json;
requires java.sql;
+ requires org.xerial.sqlitejdbc;
opens rtgre.chat to javafx.fxml;
diff --git a/chat/src/main/java/rtgre/ChatLauncher.java b/chat/src/main/java/rtgre/ChatLauncher.java
index c22c2aa..a3b515d 100644
--- a/chat/src/main/java/rtgre/ChatLauncher.java
+++ b/chat/src/main/java/rtgre/ChatLauncher.java
@@ -18,6 +18,8 @@ public class ChatLauncher {
ChatApplication.main(args);
}
} catch (Exception e) {
+ System.out.println(e.getMessage());
+ e.printStackTrace();
System.out.println("test2");
ChatApplication.main(args);
}
diff --git a/chat/src/main/java/rtgre/chat/ChatApplication.java b/chat/src/main/java/rtgre/chat/ChatApplication.java
index 70e5dc9..ec92f49 100644
--- a/chat/src/main/java/rtgre/chat/ChatApplication.java
+++ b/chat/src/main/java/rtgre/chat/ChatApplication.java
@@ -6,23 +6,28 @@ import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.ResourceBundle;
+import java.nio.file.Files;
+import java.util.*;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class ChatApplication extends Application {
public static final Logger LOGGER = Logger.getLogger(ChatApplication.class.getCanonicalName());
-
+ private ChatController controller;
+ private Stage stage;
static {
try {
InputStream is = ChatApplication.class
.getResource("logging.properties").openStream();
LogManager.getLogManager().readConfiguration(is);
+ if (!Files.exists(new File("target/").toPath())) {
+ Files.createDirectory(new File("target").toPath());
+ }
} catch (Exception e) {
LOGGER.log(Level.INFO, "Cannot read configuration file", e);
}
@@ -41,6 +46,44 @@ public class ChatApplication extends Application {
stage.setMinHeight(400);
stage.setScene(scene);
stage.show();
+ this.controller = fxmlLoader.getController();
+ this.stage = stage;
+
+ try {
+ Properties properties = new Properties();
+ properties.load(getClass().getResourceAsStream("config.properties"));
+ if (!properties.getProperty("width").isEmpty() && !properties.getProperty("height").isEmpty()) {
+ stage.setWidth(Double.parseDouble(properties.getProperty("width")));
+ stage.setHeight(Double.parseDouble(properties.getProperty("height")));
+ }
+ if (properties.getProperty("posx").isEmpty() || properties.getProperty("height").isEmpty()) {
+ stage.centerOnScreen();
+ } else {
+ stage.setX(Double.parseDouble(properties.getProperty("posx")));
+ stage.setY(Double.parseDouble(properties.getProperty("posy")));
+ }
+ } catch (IOException e) {
+ LOGGER.warning("Cannot load stage config!");
+ }
+ }
+
+ @Override
+ public void stop() {
+ try {
+ Properties properties = new Properties();
+ properties.load(getClass().getResourceAsStream("config.properties"));
+ properties.setProperty("width", String.valueOf(stage.getWidth()));
+ properties.setProperty("height", String.valueOf(stage.getHeight()));
+ properties.setProperty("posx", String.valueOf(stage.getX()));
+ properties.setProperty("posy", String.valueOf(stage.getY()));
+
+ properties.setProperty("split1", String.valueOf(controller.senderSplitPane.getDividerPositions()[0]));
+ properties.setProperty("split2", String.valueOf(controller.exchangeSplitPane.getDividerPositions()[0]));
+ LOGGER.finest(properties.toString());
+ properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
+ } catch (IOException e) {
+ LOGGER.warning("Cannot store stage info in config!");
+ }
}
public static void main(String[] args) {
diff --git a/chat/src/main/java/rtgre/chat/ChatController.java b/chat/src/main/java/rtgre/chat/ChatController.java
index a01087c..3de0de4 100644
--- a/chat/src/main/java/rtgre/chat/ChatController.java
+++ b/chat/src/main/java/rtgre/chat/ChatController.java
@@ -36,12 +36,12 @@ import rtgre.modeles.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
-import java.util.Date;
-import java.util.Objects;
-import java.util.ResourceBundle;
+import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -69,6 +69,7 @@ public class ChatController implements Initializable {
public Label statusLabel;
public Label dateTimeLabel;
public Contact contact;
+ public SplitPane senderSplitPane;
private ContactMap contactMap = new ContactMap();
private ObservableList contactObservableList = FXCollections.observableArrayList();
private ObservableList postsObservableList = FXCollections.observableArrayList();
@@ -78,7 +79,8 @@ public class ChatController implements Initializable {
private RoomMap roomMap = new RoomMap();
private ObservableList roomObservableList = FXCollections.observableArrayList();
private ResourceBundle i18nBundle;
-
+ private Properties properties = new Properties();
+ private Vector hostlist;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
@@ -87,14 +89,41 @@ public class ChatController implements Initializable {
this.avatarImageView.setImage(image);
this.i18nBundle = resourceBundle;
+ try {
+ InputStream in = ChatController.class.getResourceAsStream("config.properties");
+ System.out.println(ChatController.class.getResource("config.properties").getPath());
+ properties.load(in);
+ if (contact != null) {
+ this.contact.setAvatar(Contact.base64ToImage(properties.getProperty("avatar")));
+ }
+ this.avatarImageView.setImage(SwingFXUtils.toFXImage(Contact.base64ToBufferedImage(properties.getProperty("avatar")), null));
+ for (String host : (String[]) properties.getProperty("hosts").split(",")) {
+ host = host.replace("[", "").replace("]", "").replace(" ", "");
+ hostComboBox.getItems().addAll(host);
+ }
+ hostComboBox.setValue(!properties.getProperty("lasthost").isEmpty() ? properties.getProperty("lasthost") : hostComboBox.getItems().get(0));
+ loginTextField.setText(!properties.getProperty("login").isEmpty() ? properties.getProperty("login") : "");
+ if (!properties.getProperty("split2").isEmpty()) {
+ exchangeSplitPane.setDividerPositions(Double.parseDouble(properties.getProperty("split2")));
+ }
+ if (!properties.getProperty("split1").isEmpty()) {
+ exchangeSplitPane.setDividerPositions(Double.parseDouble(properties.getProperty("split2")));
+ }
+
+ } catch (IOException e) {
+ LOGGER.warning("Impossible de charger le fichier de configuration! Configuration par défaut chargée");
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ LOGGER.warning("Impossible de charger le fichier de configuration! Configuration par défaut chargée");
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ }
Thread dateTimeLoop = new Thread(this::dateTimeLoop);
dateTimeLoop.setDaemon(true);
dateTimeLoop.start();
- hostComboBox.getItems().addAll("localhost:2024");
- hostComboBox.getItems().addAll("localhost:2025");
- hostComboBox.setValue("localhost:2024");
hostComboBox.setOnAction(this::statusNameUpdate);
statusLabel.setText(i18nBundle.getString("disconnected"));
@@ -141,6 +170,8 @@ public class ChatController implements Initializable {
if (controller.isOk()) {
hostComboBox.getItems().add(controller.hostTextField.getText());
hostComboBox.setValue(controller.hostTextField.getText());
+ properties.setProperty("hosts", hostComboBox.getItems().toString());
+ properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
}
} catch (IOException e) {
LOGGER.warning("Impossible d'ouvrir la fenêtre de dialogue: fxml introuvable \n" + e.getMessage());
@@ -206,12 +237,21 @@ public class ChatController implements Initializable {
File selectedFile = fileChooser.showOpenDialog(stage);
if (selectedFile != null) {
avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
- contact.setAvatar(ImageIO.read(selectedFile));
+ if (contact != null) {
+ contact.setAvatar(ImageIO.read(selectedFile));
+ }
+ properties.setProperty("avatar", Contact.imageToBase64(ImageIO.read(selectedFile)));
+ properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
+
}
} catch (IOException e) {
LOGGER.warning("Impossible de lire l'image!");
}
- client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject()));
+ try {
+ client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject()));
+ } catch (Exception e) {
+ LOGGER.warning("Impossible d'envoyer l'évenement CONT! L'utilisateur est-il connecté?");
+ }
}
@@ -243,6 +283,14 @@ public class ChatController implements Initializable {
initPostListView();
this.statusLabel.setText("%s%s@%s:%s".formatted(i18nBundle.getString("connected"), this.contact.getLogin(), host, port));
this.connectionButton.setText(i18nBundle.getString("disconnect"));
+
+ try {
+ properties.setProperty("login", loginTextField.getText());
+ properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
+ } catch (Exception e) {
+ LOGGER.warning("Unable to store login in config!");
+ }
+
} catch (Exception e) {
new Alert(Alert.AlertType.ERROR, i18nBundle.getString("connectionError")).showAndWait();
connectionButton.setSelected(false);
@@ -281,6 +329,13 @@ public class ChatController implements Initializable {
private void statusNameUpdate(Event event) {
statusLabel.setText("not connected to " + hostComboBox.getValue());
+
+ properties.setProperty("lasthost", hostComboBox.getValue());
+ try {
+ properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
+ } catch (IOException e) {
+ LOGGER.warning("Unable to write last host to config!");
+ }
}
diff --git a/chat/src/main/java/rtgre/modeles/Contact.java b/chat/src/main/java/rtgre/modeles/Contact.java
index 063de9f..96932ad 100644
--- a/chat/src/main/java/rtgre/modeles/Contact.java
+++ b/chat/src/main/java/rtgre/modeles/Contact.java
@@ -176,4 +176,16 @@ public class Contact {
return null;
}
+ public static BufferedImage base64ToBufferedImage(String avatar64) {
+ byte[] bytes64 = Base64.getDecoder().decode(avatar64);
+ try {
+ BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes64));
+ return image;
+ } catch (IOException e) {
+ LOGGER.severe("Impossible de convertir le base64 en image");
+ }
+ return null;
+ }
+
+
}
diff --git a/chat/src/main/java/rtgre/modeles/DatabaseApi.java b/chat/src/main/java/rtgre/modeles/DatabaseApi.java
index f93b5a9..0fd4ca6 100644
--- a/chat/src/main/java/rtgre/modeles/DatabaseApi.java
+++ b/chat/src/main/java/rtgre/modeles/DatabaseApi.java
@@ -4,6 +4,7 @@ import javax.xml.transform.Result;
import java.io.File;
import java.sql.*;
import java.util.UUID;
+import org.sqlite.JDBC;
import static rtgre.chat.ChatApplication.LOGGER;
@@ -13,7 +14,7 @@ public class DatabaseApi {
public DatabaseApi() {
try {
- this.con = DriverManager.getConnection("jdbc:sqlite:chat/src/main/resources/rtgre/chat/dbase.db");
+ this.con = DriverManager.getConnection("jdbc:sqlite:target/dbase.db");
this.stmt = con.createStatement();
initDB(con);
LOGGER.info("Database connected!");
diff --git a/chat/src/main/java/rtgre/server/ChatServer.java b/chat/src/main/java/rtgre/server/ChatServer.java
index 6345a62..230b249 100644
--- a/chat/src/main/java/rtgre/server/ChatServer.java
+++ b/chat/src/main/java/rtgre/server/ChatServer.java
@@ -16,13 +16,13 @@ import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
+import static rtgre.chat.ChatApplication.LOGGER;
+
/**
* Programme serveur qui renvoie les chaines de caractères lues jusqu'à recevoir le message "fin"
*/
public class ChatServer {
- private static final Logger LOGGER = Logger.getLogger(ChatServer.class.getCanonicalName());
-
private Vector clientList;
private PostVector postVector;
private ContactMap contactMap;
@@ -41,6 +41,11 @@ public class ChatServer {
public static void main(String[] args) throws IOException {
+ try {
+ Class.forName("org.sqlite.JDBC");
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
ChatServer server = new ChatServer(2024);
//daisyConnect();
server.acceptClients();
diff --git a/chat/src/main/resources/rtgre/chat/chat-view.fxml b/chat/src/main/resources/rtgre/chat/chat-view.fxml
index 5db502c..3976f60 100644
--- a/chat/src/main/resources/rtgre/chat/chat-view.fxml
+++ b/chat/src/main/resources/rtgre/chat/chat-view.fxml
@@ -71,10 +71,10 @@
-
+
-
+
diff --git a/chat/src/main/resources/rtgre/chat/config.properties b/chat/src/main/resources/rtgre/chat/config.properties
new file mode 100644
index 0000000..5268e92
--- /dev/null
+++ b/chat/src/main/resources/rtgre/chat/config.properties
@@ -0,0 +1,10 @@
+hosts=localhost:2024,localhost:2025
+avatar=iVBORw0KGgoAAAANSUhEUgAAAWgAAAFoCAMAAABNO5HnAAAAnFBMVEVHcEy205G205G205AkJCO205G205GguYC205G10pAhIiG205G205EgICC205EeHh4fHx8fHx+205G20pC205G10pC205G20pCCk2m205H4u44/IxgeHh7pqn0vLy89IRZVNydJLR/ZnXRfTjnwtIdxYUd+glscHBzgsIGVbFGxzIzNxYvAzY+Pmmu2h2WZqnWrw4ajuH9BQTbiw48a1zdhAAAAGXRSTlMAypZk/eV+C/YYHlSpUiXfu4naRb47tjJahclkaQAAFnJJREFUeNrsnWuPqkgQhlcMoNH4QUcnQEzTIARQUf//n9vmplyay3ioahQqezl7spPB59S89Vb1hf/+m2KKKaaYYoopPiVUdcliw/7aRP9koaoTld7oLjf71VxRpPXhMJttt/IzttvZ7HBYS8p8vtpvlhPzNyMCrEiH2VZeLLSWWCzk7ewgKRPwvyXxZjdnhOVWvhziMuM9320m2l0Y/7yDuIj7Z6LdBHmlHLb/yDhHe3tQVhPsKmSWyFrvwVJ7gv0qezvlAAD5Cfug7JYTZZbKs4UGHIsZS+xRU56vt+CUM8lezzdjzeX1VkON7Xq1HJ8uS1i5XMxraUx6rf4qMwGUM71WfsfhQ5artawJDXkEEqJuBCZzIa2/ujKqe0nWBhKytP9WBVFX64U2oFisV9+Iejn/GRTmGPXPfPl1mGeDw5yI9VehZpi1wcb3oB5qNn9ZVqurn0FjTrT648uiujsMHnPiQHYfjfpX+gjMMWrp93PFWZG1DwpZWX6oOM+0D4vZJ0r173qhfVws1r+Takz6wYndj/apsfjZTek8JXUxnWfah8dsN6XzlNRp7H+0r4if/bC981zWviTk+YA99eYTvXO9p95MVXDUNVFVZO3LQlbUSTbGKh/7mfaVMTT3sZK1Lw15NSh5XmhfG4vhCPVS+mLO0drLQNrEzUH78jhspjKI5KgHUBJ3W20EsRXeu8xlbRQhzwUPkRbaSGIhcsj01bZuQDZvVJwFklalUXFmIaliOGujCxGkx8hZBOlxcsYnPVbO2KTHyxmX9Mh8nTCXN2rOmKTno+YcdeMT528ivZK10YeMMDXdbyfOmrYFXwnYzCbKUcyAV7eWh4lxEofl1Kh8QeOiLCbAz1AmY4dk8sD2MO0nY1c0efvJcHyy9VDXE9lyrNWpECLNlwB2JE0CjdKLTwKNI9OTQCPJ9OSgcUamwhx0ENwft9v1enXjYL+4Pe5B8K1ueing3HFwv11dx7ZNSg3DIEYWlJq27bjXx30opH/6Gy8p6IwZYpMyvITkGKdB4t+hjPZtGLCVj3R2DHLMmFQAV3gTajruQ7yO9OXxlmjOLni4jknbGeeTm9ruQ7jHW36ScDDKNjW6Q37CNkznev8C8cARjvt7lLO8tl2hqBe7z3Ac96tjEvIm5iythSpID84DXjgCVv5YmJGRex+3WNT/Pl36RRCOgLUgQdyaRM650XHQFtTCBET+/bQZR/C4Mti1qFm/Qmk9bvv6oTOPlZAZRyQmtawZatM0a2AT6ghK6n9bQVwKG44GN8c0GtK6nrV9+0AzjWOhg/v98bixeBQGRg+3DTWXNaGumGZRGXAlTCdHEbEk0oFRkJnretRGgtrkpbUY+Xi/HgLvS7pfOVON6D9oNDBKYDPU9XavFjURIx/S2z0hXCWMpxr1Pi6ibbtxY31zjDdQmyJIv9sfqmAbGpmDa+23oz+EeIgRXJuSugY1MUX4vDctHpC1S/xE1/7Pdm/aw25IasPko6YCSL9n8WCGHPdrQzfCTWzqXB8ubfgSOhzSb408INZjA7cxOetnc001kdTohwCdfmelFqBXCa5/x5zWRttpmnLwk5qY+EOmN7qWef/abMfDuTT+mtW0+f9Ilbok8Ph+ei4+oR/JjgHXceK1bcP4twl0p6R2gsGn9BzyabqNRHsgTd2hpzT8NCkecCSw+wnCIU3wC+IfUxpyC1iQ7oyJI1GRfkgbnJy2scXjb8ZDBVsojMf6r6Jo9KrTBqcioovHjzqYppAUpxoGKGl0j/eX9hBmASv4Y1P4DxWx4DwGPPHYQyT0zTaAKb8qYl6mKXY9XHTfXgowh743jit6z2kq0kxLAhdWUNKZL9MEPaXljbCVwqaRMnhKE3SVVkQ1K1iykSddUOk7C0QB6di09O7tcDlzPF7SGTmOe8PZTd3N4fXu7bA5c+phNsGipu3eEFh3cnh9l8IrNuc0pesWIqkNv5u6086DnkvhzUTnHKc0bVpGAN8MqaCXwrtNwPrtRtAtKzbXQHQ57HczR+AWuja8lKatS76gM5AOWzz67QpvT4GOfmDxQLeOXgnwzo/W7nDZ67V2wUs4qHuz0dS60zcCXX7ZtmnHql/H8Urn293Gr4q5FKfV5V1Q0m1Weg2R0PFOWkccZTOLoqQQSNLrlms5tv0q9Gsj3JWK51xmDUl6u0Fc/HaShLZZgX+YooTDLEceNeC+sTmecsRwSbIt3CHC8jk+XhT964U6t3j7EKId/SpHUgrjgw43KrASVjb5vlATArYs0Kgd/Q7uWBZnB0qcIXCOrqUo77MhYOLROMKTevYcWbUZRkIXVPtJGmznh4Q153gwumlVd4fEOfUhT6GGSumGeUe/c45bqs+adjeHBTpJapqtdAGldMO8o98Jqftcf74KSNrOAz64xVsF6XSQ+9yejF4KidP2LSMDkqU0VNdyqFtn2fS7tvK81SHAnnIQ02oDHe+IpLDlsHbbQb8DJS3IV0Vc0KHuk/Y/jUw8KFTTssLboCREoolz6gA6qogU1ndIyHt1kc0dsT1dD7u5PFiRrtnBu4E6Yo9bC5lA67pu0U4pDbuVqUakV0DfDrcWJpz1U4dvStKlRbjmcIV6OQdqu5Jy1juJdJrSxITafaCgnrFHNR0ZZ90yu6c0mO3givQG6m1jN4pYBzPOut6pMqSgoXpD7qgU7HYORHfne0/OnVLaSLeagI1Kd5hHOK9o8hye9Fz4hnDQ3PUssHt9XBzM1LH0Qhy7GI9YO8CMNK9lgTta+Kd+hRTiD2sndjGdu4oHhQXNqYZg7Up30PHV27bj+Cyc9Nb5LrzZl3EwswjbSQOD5rQscDdVdQQdXaHkh94pI3Y6HS0r9H27+XLY+OolLuZOpIFBc6oh3HUGnUBHSenxaR2tMPSd580TGfLkV5RRtvTasFp0mgCD5lRDSSRorsQW4+QlvF+3EZqm7fvWsfnLLL+lXQIGXa2GB5Ggqd/C68U7EhQmKexv73jq8gUt8gEMunKaBfCCDreDAdYBo9l8xK0hHOjKUjic6WhtWPJ9MwzpJqGmoA1L1XbsF6JAg3NuL4mAoCsn8Fdg36ptqGSCc25tXSBPi6/wbopuHJMSGuoIETY/A+DBIQXN3TUP/omvo0TjhMkEPHYoobm7xqUsYh9xQJ8aHwLw0OGhNFKCvH6t/jMiCYfeuFpLQO+ZmKmAp946dyzRDgys8BueAvDDl87BbSBv83frE9pC49zgPAjk0c6Skd5Dvm/lVp9KOmLUpzTkXUAlIw36Yps6f4ea0A0qDenuyicsYO98ramGmAodGY+adXECe63mHPHNNnUr/6GOGqGAWogLmm87iOnhgj7yyyGBvb5UwWoM66ohwWoK9bY9NbD34klwJ2ar1ZCfSiE26JD/gwV7TewaETS3GqIrR42VBq6FxR5cPWjoIo3sOWoHHsASXTwypALfNH8VOLdr7VmAX4xTGHZAX+nPnZSG+KBDnoIBX81WWDUEnSlFIs2p97htYdYc4o7uKlMlaNCcuRIxj/igPc5PlosKGvpVnJxxh33CB13dYAp/u7SMCrpq8HAnd1lUHwP8/SG4oCsGj4gwHdXekBDw14cUQG/AQVcuCRMDuuLv4O+lRwZdul6QGFQMaGoUXyUM/4I4ZNDFUSkxfeskAvTJ8gvGA+H+f2SNLuxXIqalC4vCwAPhfanYoAvNYagLjBCxLRQAOuc7iH0SCTpvphHeHIIOOuc7fF1ovKwHxrtwZKwW/HI5s7hcnr6DUEss6GziEXmO7Ok+ftZxOXvHODwv8x0CJv41Ew/ie9nTnS84oKHGpJf0g7A4hVTglIM7/6fh8+mOHhTpwpgUbPD/4nw8ZvvuxUw5OI04sa3c43kYg3+opazzMR9pESK+aNDPByk83hlhKQtqe7RX+CSpdgwGdF454FL6gLAKfimCzgzsUEDbxacDUuk1wgaaS/GTHP1hZbRfejwY0BLClrCcRFtR3UnHDMMATUwrey5QkVZQQVtJxOV+IBlNnPSpUEHPYUGnnC1/SNLhZ08FC3qOcFvHucA5un4jfo/FIEATM7RKpEFAlzaiwxytuORAJ7+ItEN4w3JKnsIqPhtQMSwdrYBZYsmBzqy0+ClpthYeVh4OBHTpsBDMVCnz0a/PEvkOMoRZR+I5Cg8H46NLx9+Ahh1ezts923Ahe5TKO/9z7fcTNPyoA6wHf1bDfBs+iDFprv3OQMOYjgPKoftzJaOjEd4ABv+5wR2s6agcuofpWC5HnnaIXZuNV2fzgzvQWli5RgLoYhSPox1EOGhC8soBO7xb4Vz1c66mtE2I+MVZ+4ikHJWrfoD2Kp0rn+foC+9YWL/iV58LRjkql1dBrRp6lR9RZqWF7+vImWjgsX/1zWTgi1nPxsAR7O+Yu3PKjRTSQhbg2dncIkv2sULB/o5Z+bDCGWoRXEK7BNY7lkkz7RC79y5VjjxnsDXw6iWwUFej5Jez0o/mi7UdfmKii5yBEppzrTHYFulqSoeGUNvhJMqBktCci7rBrp6/VLXDFjlWOpp2VTmgtinxXsQCdpPEuaodIquhRavKcYb67BLm60EqxuMU0lCk6QixLAf/9SBwl/xXU9oWWA19Gy+huS+82cDtkS6kdPQBfUdYb3hy/OJKIVwlrHmFE+SdHWXnYdnCesNjVApRrJ1W93pfwAusCpvwos/oCKuGoV+Y2oJyrnlhNeBd3dq5tN0xFFYNw7C0tfEM+LFXuK9C5ZC2hFVD38LjXPMqVLi3ZXFIh4Kq4SnE2Krb0K7AX35X3CxtCaqGnoXHue511aAiXU5qTxRoD0k26iUa4ej95Zx8Ts/7v70z7U5bB8KwkgpMaAmQNG2To+sPeGMJm/j//+16x4ANsq2ZscFzP/ScXg7YD2/fWWSk1feKBvQqew3At1tg0fC734Wsv+OfT37TgD65BuD4U2DR0FvBnhsJiaAx77BfxBlw3JGnbQrQ34g3mDvowNln8DQO+JwPmPd3uQCOVeDRSxpT0IXFHfhW//SSRhX04OcV0K9vmJeyuutU+PZ6BTTwPtLEkkYV9NkvZvGO+G2ApFEFnbuKReUduJLGFfR158D2jtX9Cvq6c8APlugkjSvoz583QL/gesf3ndbQ5796o+5ZECWNLOjnW5xx5x2IksYV9JU5B828Ay0f4mbCq3MOklmpL2kU8zjgCvrKhPQYf3t3KGlkQff+KoA2cEtplHyInAk/fxkKoJFHeBjmgW0cg58qnNHTIbx5IBuHUiokSIfg5oFtHEqpEGnHf0zzwDYOtVRI0R0Cmwe2cSh0hUTdISxpdM4KXSFZhQdo0+gGrVjb0VR4cDaNbtCqtR3GE7yY0yV0zoXP6hasHaJLGsam0Q36c/CjDGf8pgWGND5n5WaFZjkcKCEeCG6inKBpJK2bNAXnsoKmkbRe0hScSwuaSNI6izz8wq6SoEkKD52aJuE8KC9oX9K/P1tMmsQ3Pn9XEDRFe6iPNA3nUk0h6cRDVz29ornyX0Yl0ARDPE2kv2muu8TY7kzSzzQXXLP4OBBxLjGHpn7yQAtpMs7qCysNWD1Mo/IvmOdkl9yvzpmmawklPf+v0vYHNvTv6PX2KuQlXrjflV0atW1D7kQFUtqRl3jR6all5fwfHeiqpR1xPkw2e7DLYobc8wsqE1Lmw8yZwOUwU4Hu1+VMM/I4OXHytlfbNvz5jxBDjrP+kMA8VvbpVl7XWNtnr6Uw6d57fc7MIDCPw9c5PZ+1nQf54nUkoJ+ZjiAopg9fXzkEQ9r2V/ifncuYyKR1GAeJeYQdeBHHm4EOevDONAWueey2a/uskigHer3dLdtVcRBUHjvXkjw5p6Ua6ZnFpeXuWmcc4UkLWOaxlcLzPOeyOi4Tjv8WQm6xKo4PpjGQVmq3pif82OQ1IsphL4L38JBIV1qPpZ557GXImc+ulcm3Qc94RHrfhhnHxc8tEGq8vSUiQvOC7loJ89fXPPq+hIVA+umVaQ74Gm9vmRHoizPL7DKYg8N7I9AmPOneO9MefWCb3llmDHqh0GcXY/ZjEYM2LeDaY9DXzxnappeOGYMWG6WRxmXXmL52I2LQprNslUFjtOKuj8UMsphnzlTHR0VTp1lYvPDgHV3QCvqVgQRMNb3cb9euY8kUtJxfnYgqjJuibBiClpbjrrf7JYSy9VbQcCuIKWHOo3/nsXdYCmuDx8h9QZgN43f0BOcp7watEmIkxN0+JiyCPjA11EjSnoZzFoJsyNN3FOHH+MAj3ns9kxCQRKjt2aUj4gRwEmYqaQ0nh2xO3vAYkaPEuOvOoA1A0Oyl8qbpy51vFDHic8gZ0Lw4F5YIPxvGgjYvPypVt1tnzPfnhYFGlQ7RZ+w6UhYhju4+ASOkhoNDbJl+caIoQtxSOu62irafXhlwfJTcGG+5da1AxsIT1yMho+X0TofnOUcBbdNytyWV/fbBwKNUL7515aUd50eCRsuZQ4ubgj61bi5LsYbovGuMTHdry1SDnJW0jhP4bEdN0FnYprVW9RDNo9HC0kON9M6VogTmo6R1VB2lBJ24iJBq6zJInIMHEG6TXgaYRbmIScvaZcdMlhZ0HNJdKhTQBmsM6bVVGvNR0k7N453mTlXOQV96c2EGj/PNxmXncK/KTab5sJZN24sKxpGpM50dYaNSivRaikqc03xYr/JIOJuiYsh1YzhfI710Ta/qLSak5aZ+IqzM2b+KYqfG5lxMeueI6pxT86hcetgbWcc4kvqjyD7wOReRjhey65Ou6B6L+pyvLKFTcA5ID3IegKnH2e8bzBoZcZ76sylqRs5jIQMaznlV3tb06t5gmhArVHlpXVefc84DOIM+EedL0jo4e0fSVkmj3lj6OPtGfUaakPN5N17Xny80LRfzMrYhNXIOSe9P+m5CzsGE6TjL22ninPFpX9SqPxbKyJkLTZEh3fvBiOM9mU8vLU/XDR5rD9+pVVDbm6M769Fz3I8n9fTbOyOPj6e4TxEaI0Na3kR9iplrvAwvfizk6YM1IF7DdcQ193SSFhl0prWYFbK2ZwvLBOLsf+FhN/7nlTUiXvyCWlcizBV1IOvFLCcxzmcLR8JhjhqXwfMLa0gY/Z6jm/MZ6UDXzmIzm82j52bms9lmET/fBMfZJ+30+gZrTBj/xgIgzlEH0paW5TiWJeXl/+MQ1zD+xxoVo4lAQl0YIBcwGbGGxXDKKVFz4UF8+nTIWPNIg9iHEmqY71iMpwZrYoyASIvgeVB0yh4fj1hDA8o+Il1zPMjhB06GrLFhTMcCMjiPeft/cM4hP6qptgFcfVw8DQodkxFreEDaB1qMp0PW/EAQ9cPLGbjQ6+R8T6Jui5xxyo9Ozkf/mLQwKTa6di4Udfv8YzIyWBujZUmxfa5xFHWLimreXsyxf/B2mPOIGYx1qDtzVrHqpmfFyWjI7iOajJqP7wZzjJp7zfTme8KcoO4wPyRqfh8pMH/Y1JwWZjy9X8xxt8ibkAGnQ3bv4TsIsazH92nNubKmc+uHEHNW1jRu7TvzkBnsoQLfQh7HMghZ88elfPQQjuDLj005me9NIYU9nnSUMysEMLBDyEbHNwc212jKHeRrsDXQDhl3kG/CjmlXwc3HHeNK4p5OAuA3ifMA8GQaIO7SXmV5+8B94j7ySUA9G+FfTQO+PuBOxFqhn4TR0e2iiy666KKLFsX/ygvUYRpjuTsAAAAASUVORK5CYII=
+login=
+width=600
+height=400
+posx=
+posy=
+lasthost=
+split1=
+split2=
\ No newline at end of file