diff --git a/pom.xml b/pom.xml
index b668aa7..22792a4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,28 +4,28 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.0
+
+
com.alterdekim
jstud
1.0-SNAPSHOT
jar
- 1.8
- 1.8
+ 14
+ 14
UTF-8
- com.alterdekim.Main
- org.slf4j
- slf4j-api
- 2.0.9
-
-
- org.slf4j
- slf4j-simple
- 2.0.9
+ log4j
+ log4j
+ 1.2.17
org.bouncycastle
@@ -42,21 +42,39 @@
protobuf-java-util
3.24.4
-
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
- org.nanohttpd
- nanohttpd
- 2.3.1
+ org.springframework.boot
+ spring-boot-starter-validation
- org.apache.maven.plugins
- maven-assembly-plugin
- 2.3
- maven-plugin
+ mysql
+ mysql-connector-java
+ 8.0.33
+
+
+ org.projectlombok
+ lombok
+ true
+ 1.18.28
+ provided
+
+
+ org.springframework.integration
+ spring-integration-ip
+
+
+ org.springframework.integration
+ spring-integration-core
+ 6.0.0
@@ -69,32 +87,6 @@
-
org.xolstice.maven.plugins
protobuf-maven-plugin
@@ -114,28 +106,23 @@
- org.apache.maven.plugins
- maven-assembly-plugin
+ org.springframework.boot
+ spring-boot-maven-plugin
- package
- single
+ repackage
-
-
-
-
- com.alterdekim.Main
-
-
-
-
- jar-with-dependencies
-
-
+
+
+
+ org.projectlombok
+ lombok
+
+
+
diff --git a/src/main/java/com/alterdekim/Connection.java b/src/main/java/com/alterdekim/Connection.java
index db6b0f8..fec8cc6 100644
--- a/src/main/java/com/alterdekim/Connection.java
+++ b/src/main/java/com/alterdekim/Connection.java
@@ -1,11 +1,10 @@
package com.alterdekim;
import com.alterdekim.db.Database;
-import com.alterdekim.login.LoginServer;
import com.alterdekim.services.*;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Compute32;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -14,19 +13,21 @@ import java.io.*;
import java.util.HashMap;
import java.util.Map;
+
+@Slf4j
public class Connection extends Thread {
/*
All files were merged into protocol.proto
*/
- private static final Logger log = LoggerFactory.getLogger(Connection.class);
-
private final SSLSocket fromClient;
private OutputStream outToClient;
+ @Getter
private Map services;
+ @Getter
private final Database db;
public Connection(SSLSocket socket, Database db) {
@@ -40,10 +41,6 @@ public class Connection extends Thread {
log.warn("Tried to stopListening");
}
- public Map getServices() {
- return services;
- }
-
public void send(BattleNetPacket bp) throws Exception {
// log.info("Sending response: " + bp.getHeader().getServiceId() + " / " + bp.getHeader().getMethodId());
this.outToClient.write(bp.Encode());
@@ -55,10 +52,6 @@ public class Connection extends Thread {
this.outToClient.flush();
}
- public Database getDb() {
- return db;
- }
-
private void init() {
this.services = new HashMap<>();
this.services.put(0, new ConnectionService(""));
diff --git a/src/main/java/com/alterdekim/Main.java b/src/main/java/com/alterdekim/Main.java
index 242e20a..91b2a75 100644
--- a/src/main/java/com/alterdekim/Main.java
+++ b/src/main/java/com/alterdekim/Main.java
@@ -1,19 +1,13 @@
package com.alterdekim;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Scanner;
+import lombok.extern.slf4j.Slf4j;
+@Slf4j
public class Main {
- private static final Logger log = LoggerFactory.getLogger(Main.class);
-
- public static void main(String[] args) {
- new Server(1119).startListening();
+ // public static void main(String[] args) {
+ // new Server(1119).startListening();
/* System.out.println(Util.bytesToHex(exampleProtocol.Test.newBuilder()
.setA(9999)
.setB("testing")
@@ -38,5 +32,5 @@ public class Main {
e.printStackTrace();
}
}*/
- }
+ // }
}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/Server.java b/src/main/java/com/alterdekim/Server.java
index 529989b..11978ba 100644
--- a/src/main/java/com/alterdekim/Server.java
+++ b/src/main/java/com/alterdekim/Server.java
@@ -2,8 +2,8 @@ package com.alterdekim;
import com.alterdekim.db.Database;
-import com.alterdekim.login.LoginServer;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.Util;
+import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -11,10 +11,9 @@ import javax.net.ssl.*;
import java.io.IOException;
import java.util.LinkedList;
+@Slf4j
public class Server implements Runnable {
- private static final Logger log = LoggerFactory.getLogger(Server.class);
-
private SSLServerSocket serverSocket;
private int portNumber;
private Thread acceptThread;
@@ -49,11 +48,6 @@ public class Server implements Runnable {
public void startListening() {
acceptThread = new Thread(this);
acceptThread.start();
- try {
- new LoginServer(8080);
- } catch ( Exception e ) {
- e.printStackTrace();
- }
}
public void stopListening() {
for(Connection c:connections) {
diff --git a/src/main/java/com/alterdekim/db/Database.java b/src/main/java/com/alterdekim/db/Database.java
index 932112c..79a05dd 100644
--- a/src/main/java/com/alterdekim/db/Database.java
+++ b/src/main/java/com/alterdekim/db/Database.java
@@ -1,18 +1,8 @@
package com.alterdekim.db;
-import org.ektorp.CouchDbConnector;
-import org.ektorp.CouchDbInstance;
-import org.ektorp.http.HttpClient;
-import org.ektorp.http.StdHttpClient;
-import org.ektorp.impl.StdCouchDbConnector;
-import org.ektorp.impl.StdCouchDbInstance;
-import org.ektorp.support.DesignDocument;
-import org.ektorp.support.DesignDocumentFactory;
-import org.ektorp.support.View;
-
public class Database {
- private CouchDbConnector lobbyConnector;
+ //private CouchDbConnector lobbyConnector;
private String host;
private int port;
diff --git a/src/main/java/com/alterdekim/hearthhack/Application.java b/src/main/java/com/alterdekim/hearthhack/Application.java
new file mode 100644
index 0000000..c0a1fda
--- /dev/null
+++ b/src/main/java/com/alterdekim/hearthhack/Application.java
@@ -0,0 +1,14 @@
+package com.alterdekim.hearthhack;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableScheduling
+public class Application {
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/hearthhack/config/TcpServerSocketConfiguration.java b/src/main/java/com/alterdekim/hearthhack/config/TcpServerSocketConfiguration.java
new file mode 100644
index 0000000..94449ec
--- /dev/null
+++ b/src/main/java/com/alterdekim/hearthhack/config/TcpServerSocketConfiguration.java
@@ -0,0 +1,42 @@
+package com.alterdekim.hearthhack.config;
+
+import com.alterdekim.hearthhack.handler.BattleNetSocketHandler;
+import com.alterdekim.hearthhack.parser.BattleNetSerializerDeserializer;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.config.EnableIntegration;
+import org.springframework.integration.dsl.IntegrationFlow;
+import org.springframework.integration.ip.dsl.Tcp;
+import org.springframework.integration.ip.dsl.TcpInboundGatewaySpec;
+import org.springframework.integration.ip.dsl.TcpServerConnectionFactorySpec;
+
+@Slf4j
+@Configuration
+@EnableIntegration
+public class TcpServerSocketConfiguration {
+
+ private final int socketPort = 1119;
+
+ @Bean
+ public IntegrationFlow server(BattleNetSocketHandler serverSocketHandler) {
+ TcpServerConnectionFactorySpec connectionFactory =
+ Tcp.netServer(socketPort)
+ .deserializer(new BattleNetSerializerDeserializer())
+ .serializer(new BattleNetSerializerDeserializer())
+ .soTcpNoDelay(true);
+
+ TcpInboundGatewaySpec inboundGateway =
+ Tcp.inboundGateway(connectionFactory);
+
+ return IntegrationFlow
+ .from(inboundGateway)
+ .handle(serverSocketHandler::handleMessage)
+ .get();
+ }
+
+ @Bean
+ public BattleNetSocketHandler serverSocketHandler() {
+ return new BattleNetSocketHandler();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/hearthhack/handler/BattleNetSocketHandler.java b/src/main/java/com/alterdekim/hearthhack/handler/BattleNetSocketHandler.java
new file mode 100644
index 0000000..4862e2d
--- /dev/null
+++ b/src/main/java/com/alterdekim/hearthhack/handler/BattleNetSocketHandler.java
@@ -0,0 +1,14 @@
+package com.alterdekim.hearthhack.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHeaders;
+
+@Slf4j
+public class BattleNetSocketHandler {
+ public String handleMessage(Message> message, MessageHeaders messageHeaders) {
+ log.info(message.getPayload() + "");
+ // TODO implement something useful to process the incoming message here...
+ return message.getPayload().toString();
+ }
+}
diff --git a/src/main/java/com/alterdekim/hearthhack/parser/BattleNetSerializerDeserializer.java b/src/main/java/com/alterdekim/hearthhack/parser/BattleNetSerializerDeserializer.java
new file mode 100644
index 0000000..6683578
--- /dev/null
+++ b/src/main/java/com/alterdekim/hearthhack/parser/BattleNetSerializerDeserializer.java
@@ -0,0 +1,27 @@
+package com.alterdekim.hearthhack.parser;
+
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.serializer.Deserializer;
+import org.springframework.core.serializer.Serializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+@Slf4j
+@Data
+public class BattleNetSerializerDeserializer implements Serializer, Deserializer {
+
+
+ @Override
+ public byte[] deserialize(InputStream inputStream) throws IOException {
+ return inputStream.readAllBytes();
+ }
+
+ @Override
+ public void serialize(byte[] object, OutputStream outputStream) throws IOException {
+ outputStream.write(object);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/utils/BattleNetErrors.java b/src/main/java/com/alterdekim/hearthhack/util/BattleNetErrors.java
similarity index 99%
rename from src/main/java/com/alterdekim/utils/BattleNetErrors.java
rename to src/main/java/com/alterdekim/hearthhack/util/BattleNetErrors.java
index e6c90c3..bf11959 100644
--- a/src/main/java/com/alterdekim/utils/BattleNetErrors.java
+++ b/src/main/java/com/alterdekim/hearthhack/util/BattleNetErrors.java
@@ -1,7 +1,6 @@
-package com.alterdekim.utils;
+package com.alterdekim.hearthhack.util;
-public enum BattleNetErrors// : uint
-{
+public enum BattleNetErrors {
// Token: 0x04000CAF RID: 3247
ERROR_OK,
// Token: 0x04000CB0 RID: 3248
@@ -1240,4 +1239,4 @@ public enum BattleNetErrors// : uint
ERROR_REPORT_REJECTED,
// Token: 0x04000F19 RID: 3865
ERROR_REPORT_TOO_MANY_REQUESTS
- }
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/utils/BattleNetPacket.java b/src/main/java/com/alterdekim/hearthhack/util/BattleNetPacket.java
similarity index 79%
rename from src/main/java/com/alterdekim/utils/BattleNetPacket.java
rename to src/main/java/com/alterdekim/hearthhack/util/BattleNetPacket.java
index ec50786..c755bf6 100644
--- a/src/main/java/com/alterdekim/utils/BattleNetPacket.java
+++ b/src/main/java/com/alterdekim/hearthhack/util/BattleNetPacket.java
@@ -1,6 +1,8 @@
-package com.alterdekim.utils;
+package com.alterdekim.hearthhack.util;
import com.alterdekim.Protocol;
+import lombok.Getter;
+import lombok.Setter;
import java.io.ByteArrayOutputStream;
@@ -10,18 +12,14 @@ public class BattleNetPacket {
private int bodySize = -1;
+ @Getter
+ @Setter
private Protocol.Header header;
+ @Getter
+ @Setter
private byte[] body;
- public Protocol.Header getHeader() {
- return header;
- }
-
- public byte[] getBody() {
- return body;
- }
-
public BattleNetPacket(Protocol.Header header, byte[] body) {
this.header = header;
this.body = body;
@@ -32,29 +30,17 @@ public class BattleNetPacket {
this.body = null;
}
- public void setHeader(Protocol.Header header) {
- this.header = header;
- }
-
- public void setBody(byte[] body) {
- this.body = body;
- }
-
public int Decode(byte[] bytes, int offset, int available) throws Exception {
int num = 0;
if (this.headerSize < 0) {
- if (available < 2) {
- return num;
- }
+ if (available < 2) return num;
this.headerSize = ((int)bytes[offset] << 8) + (int)bytes[offset + 1];
available -= 2;
num += 2;
offset += 2;
}
if (this.header == null) {
- if (available < this.headerSize) {
- return num;
- }
+ if (available < this.headerSize) return num;
this.header = Protocol.Header.getDefaultInstance();
byte[] s = new byte[this.headerSize];
System.arraycopy(bytes, offset, s, 0, this.headerSize);
@@ -65,9 +51,7 @@ public class BattleNetPacket {
offset += this.headerSize;
}
if (this.body == null) {
- if (available < this.bodySize) {
- return num;
- }
+ if (available < this.bodySize) return num;
byte[] destinationArray = new byte[this.bodySize];
System.arraycopy(bytes, offset, destinationArray, 0, this.bodySize);
this.body = destinationArray;
diff --git a/src/main/java/com/alterdekim/utils/Compute32.java b/src/main/java/com/alterdekim/hearthhack/util/Compute32.java
similarity index 87%
rename from src/main/java/com/alterdekim/utils/Compute32.java
rename to src/main/java/com/alterdekim/hearthhack/util/Compute32.java
index 3701088..74326be 100644
--- a/src/main/java/com/alterdekim/utils/Compute32.java
+++ b/src/main/java/com/alterdekim/hearthhack/util/Compute32.java
@@ -1,4 +1,4 @@
-package com.alterdekim.utils;
+package com.alterdekim.hearthhack.util;
public class Compute32 {
public static int Hash(String str) {
diff --git a/src/main/java/com/alterdekim/utils/Util.java b/src/main/java/com/alterdekim/hearthhack/util/Util.java
similarity index 99%
rename from src/main/java/com/alterdekim/utils/Util.java
rename to src/main/java/com/alterdekim/hearthhack/util/Util.java
index 5f90dfa..d6955f2 100644
--- a/src/main/java/com/alterdekim/utils/Util.java
+++ b/src/main/java/com/alterdekim/hearthhack/util/Util.java
@@ -1,4 +1,4 @@
-package com.alterdekim.utils;
+package com.alterdekim.hearthhack.util;
import com.google.protobuf.MessageOrBuilder;
import com.google.protobuf.util.JsonFormat;
diff --git a/src/main/java/com/alterdekim/login/LoginServer.java b/src/main/java/com/alterdekim/login/LoginServer.java
deleted file mode 100644
index 3d7b22d..0000000
--- a/src/main/java/com/alterdekim/login/LoginServer.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.alterdekim.login;
-
-import fi.iki.elonen.NanoHTTPD;
-
-import java.io.IOException;
-
-public class LoginServer extends NanoHTTPD {
- public LoginServer(int port) throws IOException {
- super(port);
- start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
- }
-
- @Override
- public Response serve(IHTTPSession session) {
- return newChunkedResponse(Response.Status.OK, "text/html", Thread.currentThread().getContextClassLoader().getResourceAsStream("login.html"));
- }
-}
diff --git a/src/main/java/com/alterdekim/services/AccountService.java b/src/main/java/com/alterdekim/services/AccountService.java
index 4b43fb8..7c16cc6 100644
--- a/src/main/java/com/alterdekim/services/AccountService.java
+++ b/src/main/java/com/alterdekim/services/AccountService.java
@@ -2,8 +2,8 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/alterdekim/services/AuthService.java b/src/main/java/com/alterdekim/services/AuthService.java
index 4dc8dc9..90c184f 100644
--- a/src/main/java/com/alterdekim/services/AuthService.java
+++ b/src/main/java/com/alterdekim/services/AuthService.java
@@ -2,13 +2,11 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Compute32;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
public class AuthService extends Service {
diff --git a/src/main/java/com/alterdekim/services/ChannelService.java b/src/main/java/com/alterdekim/services/ChannelService.java
index 5d6af54..d6db00c 100644
--- a/src/main/java/com/alterdekim/services/ChannelService.java
+++ b/src/main/java/com/alterdekim/services/ChannelService.java
@@ -2,7 +2,7 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/alterdekim/services/ConnectionService.java b/src/main/java/com/alterdekim/services/ConnectionService.java
index 81fa310..d3800c5 100644
--- a/src/main/java/com/alterdekim/services/ConnectionService.java
+++ b/src/main/java/com/alterdekim/services/ConnectionService.java
@@ -2,8 +2,8 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
diff --git a/src/main/java/com/alterdekim/services/FriendsService.java b/src/main/java/com/alterdekim/services/FriendsService.java
index b838c90..5bf69fe 100644
--- a/src/main/java/com/alterdekim/services/FriendsService.java
+++ b/src/main/java/com/alterdekim/services/FriendsService.java
@@ -2,8 +2,7 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/alterdekim/services/GameUtilitiesService.java b/src/main/java/com/alterdekim/services/GameUtilitiesService.java
index 94ff5ab..63e172e 100644
--- a/src/main/java/com/alterdekim/services/GameUtilitiesService.java
+++ b/src/main/java/com/alterdekim/services/GameUtilitiesService.java
@@ -2,8 +2,8 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/alterdekim/services/PresenceService.java b/src/main/java/com/alterdekim/services/PresenceService.java
index 88d5adc..4dfced7 100644
--- a/src/main/java/com/alterdekim/services/PresenceService.java
+++ b/src/main/java/com/alterdekim/services/PresenceService.java
@@ -2,10 +2,8 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.exampleProtocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
-import com.google.protobuf.AbstractMessage;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/alterdekim/services/ResourcesService.java b/src/main/java/com/alterdekim/services/ResourcesService.java
index 9588b1b..9c93ef1 100644
--- a/src/main/java/com/alterdekim/services/ResourcesService.java
+++ b/src/main/java/com/alterdekim/services/ResourcesService.java
@@ -2,8 +2,8 @@ package com.alterdekim.services;
import com.alterdekim.Connection;
import com.alterdekim.Protocol;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Util;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Util;
import com.google.protobuf.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/alterdekim/services/Service.java b/src/main/java/com/alterdekim/services/Service.java
index c5e63b8..558e555 100644
--- a/src/main/java/com/alterdekim/services/Service.java
+++ b/src/main/java/com/alterdekim/services/Service.java
@@ -1,8 +1,8 @@
package com.alterdekim.services;
import com.alterdekim.Connection;
-import com.alterdekim.utils.BattleNetPacket;
-import com.alterdekim.utils.Compute32;
+import com.alterdekim.hearthhack.util.BattleNetPacket;
+import com.alterdekim.hearthhack.util.Compute32;
public abstract class Service {
diff --git a/src/main/resources/login.html b/src/main/resources/login.html
deleted file mode 100644
index 5234a7c..0000000
--- a/src/main/resources/login.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
- Login
-
-
-
-
-
-
-
\ No newline at end of file