don't allow strange characters in unit type ids.

Using characters like " or ' in unit type ids has a high change of
breaking code, in particular the statistics code assumes that the
unit type ids can be used as wml varaible keys.
This commit is contained in:
gfgtdf 2016-07-09 21:40:05 +02:00
parent bbc32856f1
commit 69fb6aa9e7
3 changed files with 42 additions and 5 deletions

View file

@ -157,6 +157,8 @@ unit_type::unit_type(const config &cfg, const std::string & parent_id) :
animations_(),
build_status_(NOT_BUILT)
{
check_id(id_);
check_id(base_id_);
gender_types_[0] = nullptr;
gender_types_[1] = nullptr;
}
@ -1287,6 +1289,28 @@ const unit_race *unit_type_data::find_race(const std::string &key) const
return i != races_.end() ? &i->second : nullptr;
}
void unit_type::check_id(std::string& id)
{
assert(!id.empty());
//we don't allow leading whitepaces
if (id[0] == ' ') {
throw error("Found unit type id with a leading whitespace \"" + id + "\"");
}
bool gave_wanrning = false;
for (size_t pos = 0; pos < id.size(); ++pos) {
const char c = id[pos];
const bool valid = c == '_' || c == ' ' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
if (!valid) {
if (!gave_wanrning) {
ERR_UT << "Found unit type id with invalid chracters: \"" << id << "\"\n";
gave_wanrning = true;
}
id[pos] = '_';
}
}
}
unit_type_data unit_types;
@ -1316,3 +1340,4 @@ void adjust_profile(std::string& profile)
profile = temp;
}
}
static void check_id(std::string& id);

View file

@ -21,6 +21,7 @@
#include "units/race.hpp"
#include "units/attack_type.hpp"
#include "util.hpp"
#include "game_errors.hpp"
#include <boost/noncopyable.hpp>
#include <map>
@ -38,6 +39,14 @@ typedef std::map<std::string, movetype> movement_type_map;
class unit_type
{
public:
class error : public game::game_error
{
public:
error(const std::string& msg)
: game::game_error(msg)
{
}
};
/**
* Creates a unit type for the given config, but delays its build
* till later.
@ -53,6 +62,7 @@ public:
/// These are in order of increasing levels of being built.
/// HELP_INDEX is already defined in a windows header under some conditions.
enum BUILD_STATUS {NOT_BUILT, CREATED, VARIATIONS, HELP_INDEXED, FULL};
static void check_id(std::string& id);
private: // These will be called by build().
/// Load data into an empty unit_type (build to FULL).
void build_full(const movement_type_map &movement_types,

View file

@ -195,11 +195,13 @@ void intrusive_ptr_release(const unit * u)
*/
static const unit_type &get_unit_type(const std::string &type_id)
{
if ( type_id.empty() )
throw game::game_error("creating unit with an empty type field");
const unit_type *i = unit_types.find(type_id);
if (!i) throw game::game_error("unknown unit type: " + type_id);
if (type_id.empty()) {
throw unit_type::error("creating unit with an empty type field");
}
std::string new_id = type_id;
unit_type::check_id(new_id);
const unit_type *i = unit_types.find(new_id);
if (!i) throw unit_type::error("unknown unit type: " + type_id);
return *i;
}