Merge pull request #354 Sanitize SQLite Queries

adds support to prevent sql injection via using prepared statements and also fixes an issue with the runmacro command.
This commit is contained in:
David Markowitz 2022-05-24 17:31:58 -07:00 committed by GitHub
commit 769f789a43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 435 additions and 419 deletions

View File

@ -13,3 +13,8 @@ void CDClientDatabase::Connect(const std::string& filename) {
CppSQLite3Query CDClientDatabase::ExecuteQuery(const std::string& query) { CppSQLite3Query CDClientDatabase::ExecuteQuery(const std::string& query) {
return conn->execQuery(query.c_str()); return conn->execQuery(query.c_str());
} }
//! Makes prepared statements
CppSQLite3Statement CDClientDatabase::CreatePreppedStmt(const std::string& query) {
return conn->compileStatement(query.c_str());
}

View File

@ -40,4 +40,10 @@ namespace CDClientDatabase {
*/ */
CppSQLite3Query ExecuteQuery(const std::string& query); CppSQLite3Query ExecuteQuery(const std::string& query);
//! Queries the CDClient and parses arguments
/*!
\param query The query with formatted arguments
\return prepared SQLite Statement
*/
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
}; };

View File

@ -4,12 +4,12 @@
//! Constructor //! Constructor
CDBehaviorParameterTable::CDBehaviorParameterTable(void) { CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
#ifdef CDCLIENT_CACHE_ALL #ifdef CDCLIENT_CACHE_ALL
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
while (!tableData.eof()) { while (!tableData.eof()) {
CDBehaviorParameter entry; CDBehaviorParameter entry;
entry.behaviorID = tableData.getIntField(0, -1); entry.behaviorID = tableData.getIntField(0, -1);
entry.parameterID = tableData.getStringField(1, ""); entry.parameterID = tableData.getStringField(1, "");
entry.value = tableData.getFloatField(2, -1.0f); entry.value = tableData.getFloatField(2, -1.0f);
//Check if we have an entry with this ID: //Check if we have an entry with this ID:
auto it = m_entries.find(entry.behaviorID); auto it = m_entries.find(entry.behaviorID);
@ -25,8 +25,8 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
jit->second.insert(std::make_pair(entry.parameterID, entry.value)); jit->second.insert(std::make_pair(entry.parameterID, entry.value));
} }
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
#endif #endif
@ -37,7 +37,7 @@ CDBehaviorParameterTable::~CDBehaviorParameterTable(void) { }
//! Returns the table's name //! Returns the table's name
std::string CDBehaviorParameterTable::GetName(void) const { std::string CDBehaviorParameterTable::GetName(void) const {
return "BehaviorParameter"; return "BehaviorParameter";
} }
float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue) float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue)
@ -59,17 +59,17 @@ float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::s
} }
#ifndef CDCLIENT_CACHE_ALL #ifndef CDCLIENT_CACHE_ALL
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;");
query.bind(1, (int) behaviorID);
query << "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = " << std::to_string(behaviorID); auto tableData = query.execQuery();
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
m_Entries.insert_or_assign(behaviorID, 0); m_Entries.insert_or_assign(behaviorID, 0);
while (!tableData.eof()) { while (!tableData.eof()) {
const std::string parameterID = tableData.getStringField(0, ""); const std::string parameterID = tableData.getStringField(0, "");
const float value = tableData.getFloatField(1, 0); const float value = tableData.getFloatField(1, 0);
size_t parameterHash = 0; size_t parameterHash = 0;
GeneralUtils::hash_combine(parameterHash, behaviorID); GeneralUtils::hash_combine(parameterHash, behaviorID);
@ -77,8 +77,8 @@ float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::s
m_Entries.insert_or_assign(parameterHash, value); m_Entries.insert_or_assign(parameterHash, value);
tableData.nextRow(); tableData.nextRow();
} }
const auto& it2 = m_Entries.find(hash); const auto& it2 = m_Entries.find(hash);
if (it2 != m_Entries.end()) { if (it2 != m_Entries.end()) {

View File

@ -191,8 +191,8 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
behavior = new JetPackBehavior(behaviorId); behavior = new JetPackBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT: case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
behavior = new SkillEventBehavior(behaviorId); behavior = new SkillEventBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM: break; case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM: break;
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED: case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
behavior = new SkillCastFailedBehavior(behaviorId); behavior = new SkillCastFailedBehavior(behaviorId);
@ -281,13 +281,12 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId)
return behavior; return behavior;
} }
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
{ auto query = CDClientDatabase::CreatePreppedStmt(
std::stringstream query; "SELECT templateID FROM BehaviorTemplate WHERE behaviorID = ?;");
query.bind(1, (int) behaviorId);
query << "SELECT templateID FROM BehaviorTemplate WHERE behaviorID = " << std::to_string(behaviorId); auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
// Make sure we do not proceed if we are trying to load an invalid behavior // Make sure we do not proceed if we are trying to load an invalid behavior
if (result.eof()) if (result.eof())
@ -358,18 +357,25 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
} }
} }
std::stringstream query; // The SQlite result object becomes invalid if the query object leaves scope.
// So both queries are defined before the if statement
CppSQLite3Query result;
auto typeQuery = CDClientDatabase::CreatePreppedStmt(
"SELECT effectName FROM BehaviorEffect WHERE effectType = ? AND effectID = ?;");
if (!type.empty()) auto idQuery = CDClientDatabase::CreatePreppedStmt(
{ "SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = ?;");
query << "SELECT effectName FROM BehaviorEffect WHERE effectType = '" << typeString << "' AND effectID = " << std::to_string(effectId) << ";";
}
else
{
query << "SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = " << std::to_string(effectId) << ";";
}
auto result = CDClientDatabase::ExecuteQuery(query.str()); if (!type.empty()) {
typeQuery.bind(1, typeString.c_str());
typeQuery.bind(2, (int) effectId);
result = typeQuery.execQuery();
} else {
idQuery.bind(1, (int) effectId);
result = idQuery.execQuery();
}
if (result.eof() || result.fieldIsNull(0)) if (result.eof() || result.fieldIsNull(0))
{ {
@ -414,15 +420,11 @@ Behavior::Behavior(const uint32_t behaviorId)
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
} }
/* auto query = CDClientDatabase::CreatePreppedStmt(
* Get standard info "SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = ?;");
*/ query.bind(1, (int) behaviorId);
std::stringstream query; auto result = query.execQuery();
query << "SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = " << std::to_string(behaviorId);
auto result = CDClientDatabase::ExecuteQuery(query.str());
// Make sure we do not proceed if we are trying to load an invalid behavior // Make sure we do not proceed if we are trying to load an invalid behavior
if (result.eof()) if (result.eof())
@ -495,11 +497,11 @@ std::map<std::string, float> Behavior::GetParameterNames() const
{ {
std::map<std::string, float> parameters; std::map<std::string, float> parameters;
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;");
query.bind(1, (int) this->m_behaviorId);
query << "SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = " << std::to_string(this->m_behaviorId); auto tableData = query.execQuery();
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
while (!tableData.eof()) while (!tableData.eof())
{ {

View File

@ -39,15 +39,15 @@ void SwitchMultipleBehavior::Calculate(BehaviorContext* context, RakNet::BitStre
// TODO // TODO
} }
void SwitchMultipleBehavior::Load() void SwitchMultipleBehavior::Load() {
{ auto query = CDClientDatabase::CreatePreppedStmt(
const auto b = std::to_string(this->m_behaviorId); "SELECT replace(bP1.parameterID, 'behavior ', '') as key, bP1.value as behavior, "
std::stringstream query; "(select bP2.value FROM BehaviorParameter bP2 WHERE bP2.behaviorID = ?1 AND bP2.parameterID LIKE 'value %' "
query << "SELECT replace(bP1.parameterID, 'behavior ', '') as key, bP1.value as behavior, " "AND replace(bP1.parameterID, 'behavior ', '') = replace(bP2.parameterID, 'value ', '')) as value "
<< "(select bP2.value FROM BehaviorParameter bP2 WHERE bP2.behaviorID = " << b << " AND bP2.parameterID LIKE 'value %' " "FROM BehaviorParameter bP1 WHERE bP1.behaviorID = ?1 AND bP1.parameterID LIKE 'behavior %';");
<< "AND replace(bP1.parameterID, 'behavior ', '') = replace(bP2.parameterID, 'value ', '')) as value " query.bind(1, (int) this->m_behaviorId);
<< "FROM BehaviorParameter bP1 WHERE bP1.behaviorID = " << b << " AND bP1.parameterID LIKE 'behavior %'";
auto result = CDClientDatabase::ExecuteQuery(query.str()); auto result = query.execQuery();
while (!result.eof()) { while (!result.eof()) {
const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1)); const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1));

View File

@ -35,11 +35,11 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
m_SoftTimer = 5.0f; m_SoftTimer = 5.0f;
//Grab the aggro information from BaseCombatAI: //Grab the aggro information from BaseCombatAI:
std::stringstream componentQuery; auto componentQuery = CDClientDatabase::CreatePreppedStmt(
"SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = ?;");
componentQuery.bind(1, (int) id);
componentQuery << "SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = " << std::to_string(id); auto componentResult = componentQuery.execQuery();
auto componentResult = CDClientDatabase::ExecuteQuery(componentQuery.str());
if (!componentResult.eof()) if (!componentResult.eof())
{ {
@ -64,12 +64,11 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
/* /*
* Find skills * Find skills
*/ */
auto skillQuery = CDClientDatabase::CreatePreppedStmt(
"SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);");
skillQuery.bind(1, (int) parent->GetLOT());
std::stringstream query; auto result = skillQuery.execQuery();
query << "SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = " << std::to_string(parent->GetLOT()) << " )";
auto result = CDClientDatabase::ExecuteQuery(query.str());
while (!result.eof()) { while (!result.eof()) {
const auto skillId = static_cast<uint32_t>(result.getIntField(0)); const auto skillId = static_cast<uint32_t>(result.getIntField(0));

View File

@ -371,11 +371,11 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
return pair->second; return pair->second;
} }
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT * FROM BuffParameters WHERE BuffID = ?;");
query.bind(1, (int) buffId);
query << "SELECT * FROM BuffParameters WHERE BuffID = " << std::to_string(buffId) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
std::vector<BuffParameter> parameters {}; std::vector<BuffParameter> parameters {};

View File

@ -375,11 +375,11 @@ void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignore
m_FactionIDs.push_back(factionID); m_FactionIDs.push_back(factionID);
m_DirtyHealth = true; m_DirtyHealth = true;
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT enemyList FROM Factions WHERE faction = ?;");
query.bind(1, (int) factionID);
query << "SELECT enemyList FROM Factions WHERE faction = " << std::to_string(factionID); auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof()) return; if (result.eof()) return;

View File

@ -189,6 +189,7 @@ void InventoryComponent::AddItem(
return; return;
} }
auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound, lootSourceType); auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound, lootSourceType);
if (missions != nullptr && !IsTransferInventory(inventoryType)) if (missions != nullptr && !IsTransferInventory(inventoryType))
@ -818,7 +819,7 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b
outBitStream->Write(ldfStream); outBitStream->Write(ldfStream);
} }
outBitStream->Write1(); outBitStream->Write1();
} }
m_Dirty = false; m_Dirty = false;
@ -1182,22 +1183,21 @@ bool InventoryComponent::IsEquipped(const LOT lot) const
return false; return false;
} }
void InventoryComponent::CheckItemSet(const LOT lot) void InventoryComponent::CheckItemSet(const LOT lot) {
{
// Check if the lot is in the item set cache // Check if the lot is in the item set cache
if (std::find(m_ItemSetsChecked.begin(), m_ItemSetsChecked.end(), lot) != m_ItemSetsChecked.end()) if (std::find(m_ItemSetsChecked.begin(), m_ItemSetsChecked.end(), lot) != m_ItemSetsChecked.end()) {
{
return; return;
} }
std::stringstream query; const std::string lot_query = "%" + std::to_string(lot) + "%";
query << "SELECT setID FROM ItemSets WHERE itemIDs LIKE '%" << std::to_string(lot) << "%'"; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT setID FROM ItemSets WHERE itemIDs LIKE ?;");
query.bind(1, lot_query.c_str());
auto result = CDClientDatabase::ExecuteQuery(query.str()); auto result = query.execQuery();
while (!result.eof()) while (!result.eof()) {
{
const auto id = result.getIntField(0); const auto id = result.getIntField(0);
bool found = false; bool found = false;
@ -1470,6 +1470,7 @@ std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip
{ {
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, result.skillID); missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, result.skillID);
} }
// If item is not a proxy, add its buff to the added buffs. // If item is not a proxy, add its buff to the added buffs.
if (item->GetParent() == LWOOBJID_EMPTY) buffs.push_back(static_cast<uint32_t>(entry.behaviorID)); if (item->GetParent() == LWOOBJID_EMPTY) buffs.push_back(static_cast<uint32_t>(entry.behaviorID));
} }
@ -1787,4 +1788,3 @@ void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document)
petInventoryElement->LinkEndChild(petElement); petInventoryElement->LinkEndChild(petElement);
} }
} }

View File

@ -450,11 +450,11 @@ const std::vector<uint32_t>& MissionComponent::QueryAchievements(MissionTaskType
} }
bool MissionComponent::RequiresItem(const LOT lot) { bool MissionComponent::RequiresItem(const LOT lot) {
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT type FROM Objects WHERE id = ?;");
query.bind(1, (int) lot);
query << "SELECT type FROM Objects WHERE id = " << std::to_string(lot); auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof()) { if (result.eof()) {
return false; return false;

View File

@ -172,13 +172,12 @@ void PetComponent::OnUse(Entity* originator)
std::string buildFile; std::string buildFile;
if (cached == buildCache.end()) if (cached == buildCache.end()) {
{ auto query = CDClientDatabase::CreatePreppedStmt(
std::stringstream query; "SELECT ValidPiecesLXF, PuzzleModelLot, Timelimit, NumValidPieces, imagCostPerBuild FROM TamingBuildPuzzles WHERE NPCLot = ?;");
query.bind(1, (int) m_Parent->GetLOT());
query << "SELECT ValidPiecesLXF, PuzzleModelLot, Timelimit, NumValidPieces, imagCostPerBuild FROM TamingBuildPuzzles WHERE NPCLot = " << std::to_string(m_Parent->GetLOT()) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof()) if (result.eof())
{ {

View File

@ -40,11 +40,11 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo
const auto zoneId = worldId.GetMapID(); const auto zoneId = worldId.GetMapID();
const auto cloneId = worldId.GetCloneID(); const auto cloneId = worldId.GetCloneID();
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT id FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, (int) zoneId);
query << "SELECT id FROM PropertyTemplate WHERE mapID = " << std::to_string(zoneId) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof() || result.fieldIsNull(0)) if (result.eof() || result.fieldIsNull(0))
{ {
@ -103,11 +103,11 @@ std::vector<NiPoint3> PropertyManagementComponent::GetPaths() const
{ {
const auto zoneId = dZoneManager::Instance()->GetZone()->GetWorldID(); const auto zoneId = dZoneManager::Instance()->GetZone()->GetWorldID();
std::stringstream query {}; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT path FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, (int) zoneId);
query << "SELECT path FROM PropertyTemplate WHERE mapID = " << std::to_string(zoneId) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
std::vector<NiPoint3> paths {}; std::vector<NiPoint3> paths {};

View File

@ -198,14 +198,16 @@ void RenderComponent::PlayEffect(const int32_t effectId, const std::u16string& e
return; return;
} }
std::stringstream query; const std::string effectType_str = GeneralUtils::UTF16ToWTF8(effectType);
query << "SELECT animation_length FROM Animations WHERE animation_type IN (SELECT animationName FROM BehaviorEffect WHERE effectID = " << std::to_string(effectId) << " AND effectType = '" << GeneralUtils::UTF16ToWTF8(effectType) << "');"; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT animation_length FROM Animations WHERE animation_type IN (SELECT animationName FROM BehaviorEffect WHERE effectID = ? AND effectType = ?);");
query.bind(1, effectId);
query.bind(2, effectType_str.c_str());
auto result = CDClientDatabase::ExecuteQuery(query.str()); auto result = query.execQuery();
if (result.eof() || result.fieldIsNull(0)) if (result.eof() || result.fieldIsNull(0)) {
{
result.finalize(); result.finalize();
m_DurationCache[effectId] = 0; m_DurationCache[effectId] = 0;

View File

@ -19,11 +19,11 @@
#include "PacketUtils.h" #include "PacketUtils.h"
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) { RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;");
query.bind(1, rocketId);
query << "SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = " << std::to_string(rocketId); auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (!result.eof() && !result.fieldIsNull(0)) if (!result.eof() && !result.fieldIsNull(0))
{ {

View File

@ -88,14 +88,13 @@ void SkillComponent::SyncPlayerProjectile(const LWOOBJID projectileId, RakNet::B
const auto sync_entry = this->m_managedProjectiles.at(index); const auto sync_entry = this->m_managedProjectiles.at(index);
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);");
query.bind(1, (int) sync_entry.lot);
query << "SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = " << std::to_string(sync_entry.lot) << ")"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str()); if (result.eof()) {
if (result.eof())
{
Game::logger->Log("SkillComponent", "Failed to find skill id for (%i)!\n", sync_entry.lot); Game::logger->Log("SkillComponent", "Failed to find skill id for (%i)!\n", sync_entry.lot);
return; return;
@ -430,8 +429,7 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry)
{ {
auto* other = EntityManager::Instance()->GetEntity(entry.branchContext.target); auto* other = EntityManager::Instance()->GetEntity(entry.branchContext.target);
if (other == nullptr) if (other == nullptr) {
{
if (entry.branchContext.target != LWOOBJID_EMPTY) if (entry.branchContext.target != LWOOBJID_EMPTY)
{ {
Game::logger->Log("SkillComponent", "Invalid projectile target (%llu)!\n", entry.branchContext.target); Game::logger->Log("SkillComponent", "Invalid projectile target (%llu)!\n", entry.branchContext.target);
@ -440,14 +438,12 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry)
return; return;
} }
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);");
query.bind(1, (int) entry.lot);
auto result = query.execQuery();
query << "SELECT behaviorID FROM SkillBehavior WHERE skillID = (SELECT skillID FROM ObjectSkills WHERE objectTemplate = " << std::to_string(entry.lot) << ")"; if (result.eof()) {
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof())
{
Game::logger->Log("SkillComponent", "Failed to find skill id for (%i)!\n", entry.lot); Game::logger->Log("SkillComponent", "Failed to find skill id for (%i)!\n", entry.lot);
return; return;

View File

@ -2515,11 +2515,11 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent
const auto zoneId = worldId.GetMapID(); const auto zoneId = worldId.GetMapID();
const auto cloneId = worldId.GetCloneID(); const auto cloneId = worldId.GetCloneID();
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT id FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, (int) zoneId);
query << "SELECT id FROM PropertyTemplate WHERE mapID = " << std::to_string(zoneId) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof() || result.fieldIsNull(0)) { if (result.eof() || result.fieldIsNull(0)) {
return; return;

View File

@ -386,11 +386,11 @@ void Item::DisassembleModel()
const auto componentId = table->GetByIDAndType(GetLot(), COMPONENT_TYPE_RENDER); const auto componentId = table->GetByIDAndType(GetLot(), COMPONENT_TYPE_RENDER);
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT render_asset FROM RenderComponent WHERE id = ?;");
query.bind(1, (int) componentId);
query << "SELECT render_asset FROM RenderComponent WHERE id = " << std::to_string(componentId) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof()) if (result.eof())
{ {

View File

@ -15,11 +15,11 @@ ItemSet::ItemSet(const uint32_t id, InventoryComponent* inventoryComponent)
this->m_PassiveAbilities = ItemSetPassiveAbility::FindAbilities(id, m_InventoryComponent->GetParent(), this); this->m_PassiveAbilities = ItemSetPassiveAbility::FindAbilities(id, m_InventoryComponent->GetParent(), this);
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT skillSetWith2, skillSetWith3, skillSetWith4, skillSetWith5, skillSetWith6, itemIDs FROM ItemSets WHERE setID = ?;");
query.bind(1, (int) id);
query << "SELECT skillSetWith2, skillSetWith3, skillSetWith4, skillSetWith5, skillSetWith6, itemIDs FROM ItemSets WHERE setID = " << std::to_string(id); auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof()) if (result.eof())
{ {
@ -33,11 +33,11 @@ ItemSet::ItemSet(const uint32_t id, InventoryComponent* inventoryComponent)
continue; continue;
} }
std::stringstream skillQuery; auto skillQuery = CDClientDatabase::CreatePreppedStmt(
"SELECT SkillID FROM ItemSetSkills WHERE SkillSetID = ?;");
skillQuery.bind(1, result.getIntField(i));
skillQuery << "SELECT SkillID FROM ItemSetSkills WHERE SkillSetID = " << std::to_string(result.getIntField(i)); auto skillResult = skillQuery.execQuery();
auto skillResult = CDClientDatabase::ExecuteQuery(skillQuery.str());
if (skillResult.eof()) if (skillResult.eof())
{ {

View File

@ -15,13 +15,12 @@
std::map<uint32_t, Precondition*> Preconditions::cache = {}; std::map<uint32_t, Precondition*> Preconditions::cache = {};
Precondition::Precondition(const uint32_t condition) Precondition::Precondition(const uint32_t condition) {
{ auto query = CDClientDatabase::CreatePreppedStmt(
std::stringstream query; "SELECT type, targetLOT, targetCount FROM Preconditions WHERE id = ?;");
query.bind(1, (int) condition);
query << "SELECT type, targetLOT, targetCount FROM Preconditions WHERE id = " << std::to_string(condition) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof()) if (result.eof())
{ {

View File

@ -64,48 +64,48 @@
#include "ScriptedActivityComponent.h" #include "ScriptedActivityComponent.h"
void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) { void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) {
std::string chatCommand; std::string chatCommand;
std::vector<std::string> args; std::vector<std::string> args;
uint32_t breakIndex = 0; uint32_t breakIndex = 0;
for (uint32_t i = 1; i < command.size(); ++i) { for (uint32_t i = 1; i < command.size(); ++i) {
if (command[i] == L' ') { if (command[i] == L' ') {
breakIndex = i; breakIndex = i;
break; break;
} }
chatCommand.push_back(static_cast<unsigned char>(command[i])); chatCommand.push_back(static_cast<unsigned char>(command[i]));
breakIndex++; breakIndex++;
} }
uint32_t index = ++breakIndex; uint32_t index = ++breakIndex;
while (true) { while (true) {
std::string arg; std::string arg;
while (index < command.size()) { while (index < command.size()) {
if (command[index] == L' ') { if (command[index] == L' ') {
args.push_back(arg); args.push_back(arg);
arg = ""; arg = "";
index++; index++;
continue; continue;
} }
arg.push_back(static_cast<char>(command[index])); arg.push_back(static_cast<char>(command[index]));
index++; index++;
} }
if (arg != "") { if (arg != "") {
args.push_back(arg); args.push_back(arg);
} }
break; break;
} }
//Game::logger->Log("SlashCommandHandler", "Received chat command \"%s\"\n", GeneralUtils::UTF16ToWTF8(command).c_str()); //Game::logger->Log("SlashCommandHandler", "Received chat command \"%s\"\n", GeneralUtils::UTF16ToWTF8(command).c_str());
User* user = UserManager::Instance()->GetUser(sysAddr); User* user = UserManager::Instance()->GetUser(sysAddr);
if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) { if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) {
if (args.size() != 1) return; if (args.size() != 1) return;
uint32_t level; uint32_t level;
@ -127,10 +127,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
level = user->GetMaxGMLevel(); level = user->GetMaxGMLevel();
} }
if (level == entity->GetGMLevel()) return; if (level == entity->GetGMLevel()) return;
bool success = user->GetMaxGMLevel() >= level; bool success = user->GetMaxGMLevel() >= level;
if (success) {
if (success) {
if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN && level == GAME_MASTER_LEVEL_CIVILIAN) if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN && level == GAME_MASTER_LEVEL_CIVILIAN)
{ {
GameMessages::SendToggleGMInvis(entity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendToggleGMInvis(entity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS);
@ -301,7 +302,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
return; return;
} }
if ((chatCommand == "leave-zone")) { if (chatCommand == "leave-zone") {
const auto currentZone = dZoneManager::Instance()->GetZone()->GetZoneID().GetMapID(); const auto currentZone = dZoneManager::Instance()->GetZone()->GetZoneID().GetMapID();
auto newZone = 0; auto newZone = 0;
@ -342,7 +343,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}); });
} }
if ((chatCommand == "join" && !args.empty())) { if (chatCommand == "join" && !args.empty()) {
ChatPackets::SendSystemMessage(sysAddr, u"Requesting private map..."); ChatPackets::SendSystemMessage(sysAddr, u"Requesting private map...");
const auto& password = args[0]; const auto& password = args[0];
@ -395,8 +396,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
auto stmt = Database::CreatePreppedStmt("INSERT INTO command_log (character_id, command) VALUES (?, ?);"); auto stmt = Database::CreatePreppedStmt("INSERT INTO command_log (character_id, command) VALUES (?, ?);");
stmt->setInt(1, entity->GetCharacter()->GetID()); stmt->setInt(1, entity->GetCharacter()->GetID());
stmt->setString(2, GeneralUtils::UTF16ToWTF8(command).c_str()); stmt->setString(2, GeneralUtils::UTF16ToWTF8(command).c_str());
stmt->execute(); stmt->execute();
delete stmt; delete stmt;
if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_FORUM_MODERATOR) { // could break characters so only allow if GM > 0 if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_FORUM_MODERATOR) { // could break characters so only allow if GM > 0
int32_t minifigItemId; int32_t minifigItemId;
@ -599,6 +600,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "runmacro" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { if (chatCommand == "runmacro" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
if (args.size() != 1) return; if (args.size() != 1) return;
// Only process if input does not contain separator charaters
if (args[0].find("/") != std::string::npos) return;
if (args[0].find("\\") != std::string::npos) return;
std::ifstream infile("./res/macros/" + args[0] + ".scm"); std::ifstream infile("./res/macros/" + args[0] + ".scm");
if (infile.good()) { if (infile.good()) {
@ -920,13 +925,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
return; return;
} }
pos.SetX(x); pos.SetX(x);
pos.SetY(y); pos.SetY(y);
pos.SetZ(z); pos.SetZ(z);
Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to %f, %f, %f\n", entity->GetObjectID(), pos.x, pos.y, pos.z);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
} else if (args.size() == 2) {
Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to %f, %f, %f\n", entity->GetObjectID(), pos.x, pos.y, pos.z);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
} else if (args.size() == 2) {
float x, z; float x, z;
if (!GeneralUtils::TryParse(args[0], x)) if (!GeneralUtils::TryParse(args[0], x))
@ -945,12 +951,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
pos.SetY(0.0f); pos.SetY(0.0f);
pos.SetZ(z); pos.SetZ(z);
Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to X: %f, Z: %f\n", entity->GetObjectID(), pos.x, pos.z);
Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to X: %f, Z: %f\n", entity->GetObjectID(), pos.x, pos.z); GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); } else {
} else { ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /teleport <x> (<y>) <z> - if no Y given, will teleport to the height of the terrain (or any physics object).");
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /teleport <x> (<y>) <z> - if no Y given, will teleport to the height of the terrain (or any physics object)."); }
}
auto* possessorComponent = entity->GetComponent<PossessorComponent>(); auto* possessorComponent = entity->GetComponent<PossessorComponent>();
@ -1190,7 +1195,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
//------------------------------------------------- //-------------------------------------------------
if (chatCommand == "buffme" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { if (chatCommand == "buffme" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
auto dest = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); auto dest = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE));
if (dest) { if (dest) {
dest->SetHealth(999); dest->SetHealth(999);
@ -1200,9 +1205,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
dest->SetImagination(999); dest->SetImagination(999);
dest->SetMaxImagination(999.0f); dest->SetMaxImagination(999.0f);
} }
EntityManager::Instance()->SerializeEntity(entity);
EntityManager::Instance()->SerializeEntity(entity); }
}
if (chatCommand == "startcelebration" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { if (chatCommand == "startcelebration" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) {
int32_t celebration; int32_t celebration;
@ -1216,7 +1220,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration); GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration);
} }
if (chatCommand == "buffmed" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { if (chatCommand == "buffmed" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
auto dest = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); auto dest = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE));
if (dest) { if (dest) {
dest->SetHealth(9); dest->SetHealth(9);
@ -1226,11 +1230,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
dest->SetImagination(9); dest->SetImagination(9);
dest->SetMaxImagination(9.0f); dest->SetMaxImagination(9.0f);
} }
EntityManager::Instance()->SerializeEntity(entity);
}
EntityManager::Instance()->SerializeEntity(entity); if (chatCommand == "refillstats" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
}
if (chatCommand == "refillstats" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
auto dest = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); auto dest = static_cast<DestroyableComponent*>(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE));
if (dest) { if (dest) {
dest->SetHealth((int)dest->GetMaxHealth()); dest->SetHealth((int)dest->GetMaxHealth());
@ -1238,22 +1242,28 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
dest->SetImagination((int)dest->GetMaxImagination()); dest->SetImagination((int)dest->GetMaxImagination());
} }
EntityManager::Instance()->SerializeEntity(entity); EntityManager::Instance()->SerializeEntity(entity);
} }
if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) {
std::string query = "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE '%" + args[0] + "%' OR `name` LIKE '%" + args[0] + "%' OR `description` LIKE '%" + args[0] + "%'"; auto query = CDClientDatabase::CreatePreppedStmt(
auto tables = CDClientDatabase::ExecuteQuery(query.c_str()); "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE ?1 OR `name` LIKE ?1 OR `description` LIKE ?1 LIMIT 50");
while (!tables.eof()) {
std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1);
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message, message.size()));
tables.nextRow();
}
}
if (chatCommand == "spawn" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) { const std::string query_text = "%" + args[0] + "%";
ControllablePhysicsComponent* comp = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS)); query.bind(1, query_text.c_str());
if (!comp) return;
auto tables = query.execQuery();
while (!tables.eof()) {
std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1);
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message, message.size()));
tables.nextRow();
}
}
if (chatCommand == "spawn" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) {
ControllablePhysicsComponent* comp = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS));
if (!comp) return;
uint32_t lot; uint32_t lot;
@ -1440,7 +1450,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
const auto objid = entity->GetObjectID(); const auto objid = entity->GetObjectID();
if (force || CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery if (force || CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery
bool darwin = true; //Putting this on true, as I'm sick of having to wait 3-4 seconds on a transfer while trying to quickly moderate properties bool darwin = true; //Putting this on true, as I'm sick of having to wait 3-4 seconds on a transfer while trying to quickly moderate properties
Character* character = entity->GetCharacter(); Character* character = entity->GetCharacter();
@ -1487,15 +1497,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
WorldPackets::SendTransferToWorld(sysAddr, serverIP, serverPort, mythranShift); WorldPackets::SendTransferToWorld(sysAddr, serverIP, serverPort, mythranShift);
}); });
return;
return; });
}); } else {
} else { std::string msg = "ZoneID not found or allowed: ";
std::string msg = "ZoneID not found or allowed: "; msg.append(args[0]);
msg.append(args[0]); ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(msg, msg.size()));
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(msg, msg.size())); }
} }
}
if (chatCommand == "createprivate" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 3) if (chatCommand == "createprivate" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 3)
{ {
@ -1973,4 +1982,3 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
} }

View File

@ -998,11 +998,11 @@ void HandlePacket(Packet* packet) {
const auto zoneId = Game::server->GetZoneID(); const auto zoneId = Game::server->GetZoneID();
const auto cloneId = g_CloneID; const auto cloneId = g_CloneID;
std::stringstream query; auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT id FROM PropertyTemplate WHERE mapID = ?;");
query.bind(1, (int) zoneId);
query << "SELECT id FROM PropertyTemplate WHERE mapID = " << std::to_string(zoneId) << ";"; auto result = query.execQuery();
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof() || result.fieldIsNull(0)) { if (result.eof() || result.fieldIsNull(0)) {
Game::logger->Log("WorldServer", "No property templates found for zone %d, not sending BBB\n", zoneId); Game::logger->Log("WorldServer", "No property templates found for zone %d, not sending BBB\n", zoneId);