From 45c787b241dbcd319a5dd838b54c70c52d889a10 Mon Sep 17 00:00:00 2001
From: ErikasKontenis <e.kontenis@gmail.com>
Date: Sun, 29 Sep 2019 22:59:23 +0300
Subject: [PATCH] its compiling now

---
 key.pem               | 13 ++++++++
 src/connection.cpp    | 37 ++++++++++++++++-----
 src/const.h           |  8 +++++
 src/definitions.h     |  5 ++-
 src/networkmessage.h  |  1 +
 src/otserv.cpp        | 10 ++++--
 src/outputmessage.h   |  6 +++-
 src/party.cpp         |  8 +++++
 src/party.h           |  1 +
 src/protocollogin.cpp |  6 ++--
 src/spells.cpp        | 76 ++++++++++++++++++++++---------------------
 src/spells.h          | 18 +++++-----
 12 files changed, 127 insertions(+), 62 deletions(-)
 create mode 100644 key.pem

diff --git a/key.pem b/key.pem
new file mode 100644
index 0000000..ec19bb4
--- /dev/null
+++ b/key.pem
@@ -0,0 +1,13 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCbZGkDtFsHrJVlaNhzU71xZROd15QHA7A+bdB5OZZhtKg3qmBWHXzLlFL6AIBZ
+SQmIKrW8pYoaGzX4sQWbcrEhJhHGFSrT27PPvuetwUKnXT11lxUJwyHFwkpb1R/UYPAbThW+sN4Z
+MFKKXT8VwePL9cQB1nd+EKyqsz2+jVt/9QIDAQABAoGAQovTtTRtr3GnYRBvcaQxAvjIV9ZUnFRm
+C7Y3i1KwJhOZ3ozmSLrEEOLqTgoc7R+sJ1YzEiDKbbete11EC3gohlhW56ptj0WDf+7ptKOgqiEy
+Kh4qt1sYJeeGz4GiiooJoeKFGdtk/5uvMR6FDCv6H7ewigVswzf330Q3Ya7+jYECQQERBxsga6+5
+x6IofXyNF6QuMqvuiN/pUgaStUOdlnWBf/T4yUpKvNS1+I4iDzqGWOOSR6RsaYPYVhj9iRABoKyx
+AkEAkbNzB6vhLAWht4dUdGzaREF3p4SwNcu5bJRa/9wCLSHaS9JaTq4lljgVPp1zyXyJCSCWpFnl
+0WvK3Qf6nVBIhQJBANS7rK8+ONWQbxENdZaZ7Rrx8HUTwSOS/fwhsGWBbl1Qzhdq/6/sIfEHkfeH
+1hoH+IlpuPuf21MdAqvJt+cMwoECQF1LyBOYduYGcSgg6u5mKVldhm3pJCA+ZGxnjuGZEnet3qeA
+eb05++112fyvO85ABUun524z9lokKNFh45NKLjUCQGshzV43P+RioiBhtEpB/QFzijiS4L2HKNu1
+tdhudnUjWkaf6jJmQS/ppln0hhRMHlk9Vus/bPx7LtuDuo6VQDo=
+-----END RSA PRIVATE KEY-----
diff --git a/src/connection.cpp b/src/connection.cpp
index 859066c..56a3861 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -182,45 +182,66 @@ void Connection::parsePacket(const boost::system::error_code& error)
 	if (error) {
 		close(FORCE_CLOSE);
 		return;
-	} else if (connectionState != CONNECTION_STATE_OPEN) {
+	}
+	else if (connectionState != CONNECTION_STATE_OPEN) {
 		return;
 	}
 
+	//Check packet checksum
+	uint32_t checksum;
+	int32_t len = msg.getLength() - msg.getBufferPosition() - NetworkMessage::CHECKSUM_LENGTH;
+	if (len > 0) {
+		checksum = adlerChecksum(msg.getBuffer() + msg.getBufferPosition() + NetworkMessage::CHECKSUM_LENGTH, len);
+	}
+	else {
+		checksum = 0;
+	}
+
+	uint32_t recvChecksum = msg.get<uint32_t>();
+	if (recvChecksum != checksum) {
+		// it might not have been the checksum, step back
+		msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH);
+	}
+
 	if (!receivedFirst) {
 		// First message received
 		receivedFirst = true;
 
 		if (!protocol) {
 			// Game protocol has already been created at this point
-			protocol = service_port->make_protocol(msg, shared_from_this());
+			protocol = service_port->make_protocol(recvChecksum == checksum, msg, shared_from_this());
 			if (!protocol) {
 				close(FORCE_CLOSE);
 				return;
 			}
-		} else {
+		}
+		else {
 			msg.skipBytes(1);    // Skip protocol ID
 		}
 
 		protocol->onRecvFirstMessage(msg);
-	} else {
+	}
+	else {
 		protocol->onRecvMessage(msg);    // Send the packet to the current protocol
 	}
 
 	try {
 		readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT));
 		readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr<Connection>(shared_from_this()),
-		                                    std::placeholders::_1));
+			std::placeholders::_1));
 
 		// Wait to the next packet
 		boost::asio::async_read(socket,
-		                        boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH),
-		                        std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1));
-	} catch (boost::system::system_error& e) {
+			boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH),
+			std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1));
+	}
+	catch (boost::system::system_error& e) {
 		std::cout << "[Network error - Connection::parsePacket] " << e.what() << std::endl;
 		close(FORCE_CLOSE);
 	}
 }
 
+
 void Connection::send(const OutputMessage_ptr& msg)
 {
 	std::lock_guard<std::recursive_mutex> lockClass(connectionLock);
diff --git a/src/const.h b/src/const.h
index 8490b1f..f596521 100644
--- a/src/const.h
+++ b/src/const.h
@@ -335,4 +335,12 @@ static constexpr int32_t CHANNEL_PARTY = 0x01;
 static constexpr int32_t CHANNEL_RULE_REP = 0x02;
 static constexpr int32_t CHANNEL_PRIVATE = 0xFFFF;
 
+//Reserved player storage key ranges;
+//[10000000 - 20000000];
+static constexpr int32_t PSTRG_RESERVED_RANGE_START = 10000000;
+static constexpr int32_t PSTRG_RESERVED_RANGE_SIZE = 10000000;
+//[1000 - 1500];
+static constexpr int32_t PSTRG_OUTFITS_RANGE_START = (PSTRG_RESERVED_RANGE_START + 1000);
+static constexpr int32_t PSTRG_OUTFITS_RANGE_SIZE = 500;
+
 #endif
diff --git a/src/definitions.h b/src/definitions.h
index 4ab6c38..cec245e 100644
--- a/src/definitions.h
+++ b/src/definitions.h
@@ -22,12 +22,15 @@
 
 static constexpr auto STATUS_SERVER_NAME = "Sabrehaven";
 static constexpr auto STATUS_SERVER_VERSION = "1.0";
-static constexpr auto STATUS_SERVER_DEVELOPERS = "Sabrehaven Developers Team";
+static constexpr auto STATUS_SERVER_DEVELOPERS = "OTLand community & Sabrehaven Developers Team";
 
 static constexpr auto CLIENT_VERSION_MIN = 772;
 static constexpr auto CLIENT_VERSION_MAX = 772;
 static constexpr auto CLIENT_VERSION_STR = "7.72";
 
+static constexpr auto AUTHENTICATOR_DIGITS = 6U;
+static constexpr auto AUTHENTICATOR_PERIOD = 30U;
+
 #ifndef __FUNCTION__
 #define __FUNCTION__ __func__
 #endif
diff --git a/src/networkmessage.h b/src/networkmessage.h
index 7d11153..b588f5a 100644
--- a/src/networkmessage.h
+++ b/src/networkmessage.h
@@ -37,6 +37,7 @@ class NetworkMessage
 		// 2 bytes for encrypted message size
 		static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 4;
 		enum { HEADER_LENGTH = 2 };
+		enum { CHECKSUM_LENGTH = 4 };
 		enum { XTEA_MULTIPLE = 8 };
 		enum { MAX_BODY_LENGTH = NETWORKMESSAGE_MAXSIZE - HEADER_LENGTH - XTEA_MULTIPLE };
 		enum { MAX_PROTOCOL_BODY_LENGTH = MAX_BODY_LENGTH - 10 };
diff --git a/src/otserv.cpp b/src/otserv.cpp
index c6ee693..e6762a4 100644
--- a/src/otserv.cpp
+++ b/src/otserv.cpp
@@ -163,9 +163,13 @@ void mainLoader(int, char*[], ServiceManager* services)
 #endif
 
 	//set RSA key
-	const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113");
-	const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101");
-	g_RSA.setKey(p, q);
+	try {
+		g_RSA.loadPEM("key.pem");
+	}
+	catch (const std::exception& e) {
+		startupErrorMessage(e.what());
+		return;
+	}
 
 	std::cout << ">> Establishing database connection..." << std::flush;
 
diff --git a/src/outputmessage.h b/src/outputmessage.h
index 01897ff..92c690d 100644
--- a/src/outputmessage.h
+++ b/src/outputmessage.h
@@ -43,7 +43,11 @@ class OutputMessage : public NetworkMessage
 			add_header(info.length);
 		}
 
-		void addCryptoHeader() {
+		void addCryptoHeader(bool addChecksum) {
+			if (addChecksum) {
+				add_header(adlerChecksum(buffer + outputBufferStart, info.length));
+			}
+
 			writeMessageLength();
 		}
 
diff --git a/src/party.cpp b/src/party.cpp
index 9ac0bed..e0d80a4 100644
--- a/src/party.cpp
+++ b/src/party.cpp
@@ -473,3 +473,11 @@ void Party::clearPlayerPoints(Player* player)
 		updateSharedExperience();
 	}
 }
+
+bool Party::canOpenCorpse(uint32_t ownerId) const
+{
+	if (Player* player = g_game.getPlayerByID(ownerId)) {
+		return leader->getID() == ownerId || player->getParty() == this;
+	}
+	return false;
+}
diff --git a/src/party.h b/src/party.h
index 58c72ec..96fce94 100644
--- a/src/party.h
+++ b/src/party.h
@@ -65,6 +65,7 @@ class Party
 		bool empty() const {
 			return memberList.empty() && inviteList.empty();
 		}
+		bool canOpenCorpse(uint32_t ownerId) const;
 
 		void shareExperience(uint64_t experience, Creature* source/* = nullptr*/);
 		bool setSharedExperience(Player* player, bool sharedExpActive);
diff --git a/src/protocollogin.cpp b/src/protocollogin.cpp
index fb2602b..fad7a98 100644
--- a/src/protocollogin.cpp
+++ b/src/protocollogin.cpp
@@ -198,13 +198,13 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
 
 	uint32_t accountNumber = msg.get<uint32_t>();
 	if (!accountNumber) {
-		disconnectClient("Invalid account number.");
+		disconnectClient("Invalid account number.", version);
 		return;
 	}
 
 	std::string password = msg.getString();
 	if (password.empty()) {
-		disconnectClient("Invalid password.");
+		disconnectClient("Invalid password.", version);
 		return;
 	}
 
@@ -218,5 +218,5 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
 	std::string authToken = msg.getString();
 
 	auto thisPtr = std::static_pointer_cast<ProtocolLogin>(shared_from_this());
-	g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, version)));
+	g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, authToken, version)));
 }
diff --git a/src/spells.cpp b/src/spells.cpp
index a79f0b8..b08a048 100644
--- a/src/spells.cpp
+++ b/src/spells.cpp
@@ -1801,47 +1801,46 @@ ReturnValue RuneSpell::canExecuteAction(const Player* player, const Position& to
 	return RETURNVALUE_NOERROR;
 }
 
-bool RuneSpell::executeUse(Player* player, Item* item, const Position&, Thing* target, const Position& toPosition)
+bool RuneSpell::executeUse(Player* player, Item* item, const Position&, Thing* target, const Position& toPosition, bool isHotkey)
 {
 	if (!playerRuneSpellCheck(player, toPosition)) {
 		return false;
 	}
 
-	bool result = false;
-	if (scripted) {
-		LuaVariant var;
-
-		if (needTarget) {
-			var.type = VARIANT_NUMBER;
-
-			if (target == nullptr) {
-				Tile* toTile = g_game.map.getTile(toPosition);
-				if (toTile) {
-					const Creature* visibleCreature = toTile->getTopCreature();
-					if (visibleCreature) {
-						var.number = visibleCreature->getID();
-					}
-				}
-			} else {
-				var.number = target->getCreature()->getID();
-			}
-		} else {
-			var.type = VARIANT_POSITION;
-			var.pos = toPosition;
-		}
-
-		result = internalCastSpell(player, var);
-	} else if (runeFunction) {
-		result = runeFunction(this, player, toPosition);
+	if (!scripted) {
+		return false;
 	}
 
-	if (!result) {
+	LuaVariant var;
+
+	if (needTarget) {
+		var.type = VARIANT_NUMBER;
+
+		if (target == nullptr) {
+			Tile* toTile = g_game.map.getTile(toPosition);
+			if (toTile) {
+				const Creature* visibleCreature = toTile->getBottomVisibleCreature(player);
+				if (visibleCreature) {
+					var.number = visibleCreature->getID();
+				}
+			}
+		}
+		else {
+			var.number = target->getCreature()->getID();
+		}
+	}
+	else {
+		var.type = VARIANT_POSITION;
+		var.pos = toPosition;
+	}
+
+	if (!internalCastSpell(player, var, isHotkey)) {
 		return false;
 	}
 
 	postCastSpell(player);
 	if (hasCharges && item && g_config.getBoolean(ConfigManager::REMOVE_RUNE_CHARGES)) {
-		int32_t newCount = std::max<int32_t>(0, item->getCharges() - 1);
+		int32_t newCount = std::max<int32_t>(0, item->getItemCount() - 1);
 		g_game.transformItem(item, item->getID(), newCount);
 	}
 	return true;
@@ -1852,7 +1851,7 @@ bool RuneSpell::castSpell(Creature* creature)
 	LuaVariant var;
 	var.type = VARIANT_NUMBER;
 	var.number = creature->getID();
-	return internalCastSpell(creature, var);
+	return internalCastSpell(creature, var, false);
 }
 
 bool RuneSpell::castSpell(Creature* creature, Creature* target)
@@ -1860,23 +1859,24 @@ bool RuneSpell::castSpell(Creature* creature, Creature* target)
 	LuaVariant var;
 	var.type = VARIANT_NUMBER;
 	var.number = target->getID();
-	return internalCastSpell(creature, var);
+	return internalCastSpell(creature, var, false);
 }
 
-bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var)
+bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey)
 {
 	bool result;
 	if (scripted) {
-		result = executeCastSpell(creature, var);
-	} else {
+		result = executeCastSpell(creature, var, isHotkey);
+	}
+	else {
 		result = false;
 	}
 	return result;
 }
 
-bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
+bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey)
 {
-	//onCastSpell(creature, var)
+	//onCastSpell(creature, var, isHotkey)
 	if (!scriptInterface->reserveScriptEnv()) {
 		std::cout << "[Error - RuneSpell::executeCastSpell] Call stack overflow" << std::endl;
 		return false;
@@ -1894,5 +1894,7 @@ bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
 
 	LuaScriptInterface::pushVariant(L, var);
 
-	return scriptInterface->callFunction(2);
+	LuaScriptInterface::pushBoolean(L, isHotkey);
+
+	return scriptInterface->callFunction(3);
 }
diff --git a/src/spells.h b/src/spells.h
index 24ddab3..d0907fe 100644
--- a/src/spells.h
+++ b/src/spells.h
@@ -56,7 +56,7 @@ class Spells final : public BaseEvents
 		TalkActionResult_t playerSaySpell(Player* player, std::string& words);
 
 		static Position getCasterPosition(Creature* creature, Direction dir);
-		std::string getScriptBaseName() const final;
+		std::string getScriptBaseName() const override;
 
 	protected:
 		void clear() final;
@@ -94,9 +94,9 @@ class CombatSpell final : public Event, public BaseSpell
 		CombatSpell(const CombatSpell&) = delete;
 		CombatSpell& operator=(const CombatSpell&) = delete;
 
-		bool castSpell(Creature* creature) final;
-		bool castSpell(Creature* creature, Creature* target) final;
-		bool configureEvent(const pugi::xml_node&) final {
+		bool castSpell(Creature* creature) override;
+		bool castSpell(Creature* creature, Creature* target) override;
+		bool configureEvent(const pugi::xml_node&) override {
 			return true;
 		}
 
@@ -109,7 +109,7 @@ class CombatSpell final : public Event, public BaseSpell
 		}
 
 	protected:
-		std::string getScriptEventName() const final {
+		std::string getScriptEventName() const override {
 			return "onCastSpell";
 		}
 
@@ -209,7 +209,7 @@ class InstantSpell : public TalkAction, public Spell
 		//scripting
 		bool executeCastSpell(Creature* creature, const LuaVariant& var);
 
-		bool isInstant() const final {
+		bool isInstant() const override {
 			return true;
 		}
 		bool getHasParam() const {
@@ -291,13 +291,13 @@ class RuneSpell final : public Action, public Spell
 			return targetCreature;
 		}
 
-		bool executeUse(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition) final;
+		bool executeUse(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition, bool isHotkey) override;
 
 		bool castSpell(Creature* creature) final;
 		bool castSpell(Creature* creature, Creature* target) final;
 
 		//scripting
-		bool executeCastSpell(Creature* creature, const LuaVariant& var);
+		bool executeCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey);
 
 		bool isInstant() const final {
 			return false;
@@ -312,7 +312,7 @@ class RuneSpell final : public Action, public Spell
 		static RuneSpellFunction Illusion;
 		static RuneSpellFunction Convince;
 
-		bool internalCastSpell(Creature* creature, const LuaVariant& var);
+		bool internalCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey);
 
 		RuneSpellFunction* runeFunction = nullptr;
 		uint16_t runeId = 0;