mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
feat(dashboard): check uploaded character XML before storing it
The XML upload is the one place hand-written XML reaches the game, whose load path trusts the XML because the server writes it itself. Instead of making the game skip bad data at load, the upload is checked against what the load path assumes and refused (400, with the problems) when the game couldn't load it: required elements, attributes that must parse (flags read with std::stoul/stoull), required item and mission fields, known inventory types, mission states and character versions, items and missions that exist in the CDClient, unique item IDs and slots, and the acct attribute matching the owner. Suspicious but loadable content is returned as warnings that need confirm=true (409 otherwise): contraband (same matching as the world, now shared in ContrabandRules.h), stacks above the stack size, coins, level or u-score out of reach, a GM level above the account's. Contraband marked flag-and-remove is removed only if the uploader asks; once stored, findings are flagged (CONTRABAND) and audited. The XML editor shows the findings and offers "Save anyway". Related: issue 1332. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
55
dDatabase/GameDatabase/ITables/ContrabandRules.h
Normal file
55
dDatabase/GameDatabase/ITables/ContrabandRules.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef __CONTRABANDRULES__H__
|
||||
#define __CONTRABANDRULES__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eInventoryType.h"
|
||||
#include "IContraband.h"
|
||||
|
||||
/**
|
||||
* The pure contraband rules, shared by world servers (Contraband.h, checking characters as they load and receive
|
||||
* items) and the dashboard (checking an uploaded character XML), so both find the same items.
|
||||
*/
|
||||
namespace Contraband {
|
||||
struct Entry {
|
||||
std::string reason;
|
||||
IContraband::eContrabandAction action{};
|
||||
};
|
||||
|
||||
using List = std::map<LOT, Entry>;
|
||||
|
||||
struct HeldItem {
|
||||
LWOOBJID id{};
|
||||
LOT lot{};
|
||||
uint32_t count{};
|
||||
eInventoryType inventory{};
|
||||
};
|
||||
|
||||
struct Finding {
|
||||
HeldItem item;
|
||||
Entry entry;
|
||||
};
|
||||
|
||||
// The held items that are on the list, in the order given
|
||||
inline std::vector<Finding> Find(const std::vector<HeldItem>& items, const List& list) {
|
||||
std::vector<Finding> found;
|
||||
if (list.empty()) return found;
|
||||
for (const auto& item : items) {
|
||||
const auto it = list.find(item.lot);
|
||||
if (it != list.end() && item.count > 0) found.push_back({ item, it->second });
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// Whether an account at this GM level is checked
|
||||
inline bool Applies(eGameMasterLevel accountLevel, bool ignoreStaff) {
|
||||
return !ignoreStaff || accountLevel <= eGameMasterLevel::CIVILIAN;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //!__CONTRABANDRULES__H__
|
||||
Reference in New Issue
Block a user