forked from github/server
fix write_faction_reference, check for f->alive in other places
TODO: 1. I added some new TODOs 2. What happens to morale when region owners die? 3. Needs tests
This commit is contained in:
parent
4050f994a4
commit
7fe07439f5
2
crypto
2
crypto
|
@ -1 +1 @@
|
||||||
Subproject commit e0f9891a91d69c042f82c1e13e48ab4c7160381d
|
Subproject commit 93dc9200fa4cb6bfa3883b19f6d33fd416ca43da
|
|
@ -1,3 +1,13 @@
|
||||||
|
{
|
||||||
|
strcpy.S:197
|
||||||
|
Memcheck:Cond
|
||||||
|
obj:/lib/x86_64-linux-gnu/libc-2.13.so
|
||||||
|
}
|
||||||
|
{
|
||||||
|
strcpy.S:1106
|
||||||
|
Memcheck:Value8
|
||||||
|
obj:/lib/x86_64-linux-gnu/libc-2.13.so
|
||||||
|
}
|
||||||
{
|
{
|
||||||
stpncpy sse3
|
stpncpy sse3
|
||||||
Memcheck:Cond
|
Memcheck:Cond
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
{
|
||||||
|
stpncpy in strcpy-sse2-unaligned.S:1659
|
||||||
|
Memcheck:Value8
|
||||||
|
fun:__stpncpy_sse2_unaligned
|
||||||
|
}
|
||||||
# old zlib version
|
# old zlib version
|
||||||
{
|
{
|
||||||
zlib1g-dev-1:1.2.3.4.dfsg
|
zlib1g-dev-1:1.2.3.4.dfsg
|
||||||
|
|
10
src/battle.c
10
src/battle.c
|
@ -228,21 +228,11 @@ static void message_faction(battle * b, faction * f, struct message *m)
|
||||||
void message_all(battle * b, message * m)
|
void message_all(battle * b, message * m)
|
||||||
{
|
{
|
||||||
bfaction *bf;
|
bfaction *bf;
|
||||||
plane *p = rplane(b->region);
|
|
||||||
watcher *w;
|
|
||||||
|
|
||||||
for (bf = b->factions; bf; bf = bf->next) {
|
for (bf = b->factions; bf; bf = bf->next) {
|
||||||
assert(bf->faction);
|
assert(bf->faction);
|
||||||
message_faction(b, bf->faction, m);
|
message_faction(b, bf->faction, m);
|
||||||
}
|
}
|
||||||
if (p)
|
|
||||||
for (w = p->watchers; w; w = w->next) {
|
|
||||||
for (bf = b->factions; bf; bf = bf->next)
|
|
||||||
if (bf->faction == w->faction)
|
|
||||||
break;
|
|
||||||
if (bf == NULL)
|
|
||||||
message_faction(b, w->faction, m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fbattlerecord(battle * b, faction * f, const char *s)
|
static void fbattlerecord(battle * b, faction * f, const char *s)
|
||||||
|
|
|
@ -392,7 +392,7 @@ static int tolua_faction_set_password(lua_State * L)
|
||||||
{
|
{
|
||||||
faction *self = (faction *)tolua_tousertype(L, 1, 0);
|
faction *self = (faction *)tolua_tousertype(L, 1, 0);
|
||||||
const char * passw = tolua_tostring(L, 2, 0);
|
const char * passw = tolua_tostring(L, 2, 0);
|
||||||
faction_setpassword(self, password_hash(passw, 0, PASSWORD_DEFAULT));
|
faction_setpassword(self, password_encode(passw, PASSWORD_DEFAULT));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,8 +153,8 @@ static int tolua_unit_get_group(lua_State * L)
|
||||||
static int tolua_unit_set_group(lua_State * L)
|
static int tolua_unit_set_group(lua_State * L)
|
||||||
{
|
{
|
||||||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||||
int result = join_group(self, tolua_tostring(L, 2, 0));
|
group *g = join_group(self, tolua_tostring(L, 2, 0));
|
||||||
lua_pushinteger(L, result);
|
lua_pushboolean(L, g!=NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#define VERSION_MAJOR 3
|
#define VERSION_MAJOR 3
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_BUILD 3
|
#define VERSION_BUILD 4
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "alliance.h"
|
#include "alliance.h"
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
#include <quicklist.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -61,9 +62,31 @@ static void test_alliance_join(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_alliance_dead_faction(CuTest *tc) {
|
||||||
|
faction *f, *f2;
|
||||||
|
alliance *al;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
f = test_create_faction(0);
|
||||||
|
f2 = test_create_faction(0);
|
||||||
|
al = makealliance(42, "Hodor");
|
||||||
|
setalliance(f, al);
|
||||||
|
setalliance(f2, al);
|
||||||
|
CuAssertPtrEquals(tc, f, alliance_get_leader(al));
|
||||||
|
CuAssertIntEquals(tc, 2, ql_length(al->members));
|
||||||
|
CuAssertPtrEquals(tc, al, f->alliance);
|
||||||
|
destroyfaction(&factions);
|
||||||
|
CuAssertIntEquals(tc, 1, ql_length(al->members));
|
||||||
|
CuAssertPtrEquals(tc, f2, alliance_get_leader(al));
|
||||||
|
CuAssertPtrEquals(tc, NULL, f->alliance);
|
||||||
|
CuAssertTrue(tc, !f->_alive);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_alliance_suite(void)
|
CuSuite *get_alliance_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_alliance_dead_faction);
|
||||||
SUITE_ADD_TEST(suite, test_alliance_make);
|
SUITE_ADD_TEST(suite, test_alliance_make);
|
||||||
SUITE_ADD_TEST(suite, test_alliance_join);
|
SUITE_ADD_TEST(suite, test_alliance_join);
|
||||||
return suite;
|
return suite;
|
||||||
|
|
|
@ -252,7 +252,7 @@ faction *addfaction(const char *email, const char *password,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!password) password = itoa36(rng_int());
|
if (!password) password = itoa36(rng_int());
|
||||||
faction_setpassword(f, password_hash(password, 0, PASSWORD_DEFAULT));
|
faction_setpassword(f, password_encode(password, PASSWORD_DEFAULT));
|
||||||
ADDMSG(&f->msgs, msg_message("changepasswd", "value", password));
|
ADDMSG(&f->msgs, msg_message("changepasswd", "value", password));
|
||||||
|
|
||||||
f->alliance_joindate = turn;
|
f->alliance_joindate = turn;
|
||||||
|
@ -567,7 +567,8 @@ void faction_setbanner(faction * self, const char *banner)
|
||||||
|
|
||||||
void faction_setpassword(faction * f, const char *pwhash)
|
void faction_setpassword(faction * f, const char *pwhash)
|
||||||
{
|
{
|
||||||
assert(pwhash && pwhash[0] == '$');
|
assert(pwhash);
|
||||||
|
// && pwhash[0] == '$');
|
||||||
free(f->_password);
|
free(f->_password);
|
||||||
f->_password = _strdup(pwhash);
|
f->_password = _strdup(pwhash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,12 +108,12 @@ static void test_addfaction(CuTest *tc) {
|
||||||
CuAssertPtrEquals(tc, NULL, (void *)f->ursprung);
|
CuAssertPtrEquals(tc, NULL, (void *)f->ursprung);
|
||||||
CuAssertPtrEquals(tc, (void *)factions, (void *)f);
|
CuAssertPtrEquals(tc, (void *)factions, (void *)f);
|
||||||
CuAssertStrEquals(tc, "test@eressea.de", f->email);
|
CuAssertStrEquals(tc, "test@eressea.de", f->email);
|
||||||
CuAssertIntEquals(tc, true, checkpasswd(f, "hurrdurr"));
|
CuAssertTrue(tc, checkpasswd(f, "hurrdurr"));
|
||||||
CuAssertPtrEquals(tc, (void *)lang, (void *)f->locale);
|
CuAssertPtrEquals(tc, (void *)lang, (void *)f->locale);
|
||||||
CuAssertIntEquals(tc, 1234, f->subscription);
|
CuAssertIntEquals(tc, 1234, f->subscription);
|
||||||
CuAssertIntEquals(tc, 0, f->flags);
|
CuAssertIntEquals(tc, 0, f->flags);
|
||||||
CuAssertIntEquals(tc, 0, f->age);
|
CuAssertIntEquals(tc, 0, f->age);
|
||||||
CuAssertIntEquals(tc, true, faction_alive(f));
|
CuAssertTrue(tc, faction_alive(f));
|
||||||
CuAssertIntEquals(tc, M_GRAY, f->magiegebiet);
|
CuAssertIntEquals(tc, M_GRAY, f->magiegebiet);
|
||||||
CuAssertIntEquals(tc, turn, f->lastorders);
|
CuAssertIntEquals(tc, turn, f->lastorders);
|
||||||
CuAssertPtrEquals(tc, f, findfaction(f->no));
|
CuAssertPtrEquals(tc, f, findfaction(f->no));
|
||||||
|
@ -124,10 +124,10 @@ static void test_check_passwd(CuTest *tc) {
|
||||||
faction *f;
|
faction *f;
|
||||||
|
|
||||||
f = test_create_faction(0);
|
f = test_create_faction(0);
|
||||||
faction_setpassword(f, password_hash("password", 0, PASSWORD_DEFAULT));
|
faction_setpassword(f, password_encode("password", PASSWORD_DEFAULT));
|
||||||
CuAssertIntEquals(tc, true, checkpasswd(f, "password"));
|
CuAssertTrue(tc, checkpasswd(f, "password"));
|
||||||
CuAssertIntEquals(tc, false, checkpasswd(f, "assword"));
|
CuAssertTrue(tc, !checkpasswd(f, "assword"));
|
||||||
CuAssertIntEquals(tc, false, checkpasswd(f, "PASSWORD"));
|
CuAssertTrue(tc, !checkpasswd(f, "PASSWORD"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_get_monsters(CuTest *tc) {
|
static void test_get_monsters(CuTest *tc) {
|
||||||
|
|
|
@ -179,7 +179,7 @@ void set_group(struct unit *u, struct group *g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool join_group(unit * u, const char *name)
|
group *join_group(unit * u, const char *name)
|
||||||
{
|
{
|
||||||
group *g = NULL;
|
group *g = NULL;
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ bool join_group(unit * u, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_group(u, g);
|
set_group(u, g);
|
||||||
return true;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_groups(struct storage *store, const faction * f)
|
void write_groups(struct storage *store, const faction * f)
|
||||||
|
|
|
@ -36,7 +36,7 @@ extern "C" {
|
||||||
} group;
|
} group;
|
||||||
|
|
||||||
extern struct attrib_type at_group; /* attribute for units assigned to a group */
|
extern struct attrib_type at_group; /* attribute for units assigned to a group */
|
||||||
extern bool join_group(struct unit *u, const char *name);
|
extern struct group *join_group(struct unit *u, const char *name);
|
||||||
extern void set_group(struct unit *u, struct group *g);
|
extern void set_group(struct unit *u, struct group *g);
|
||||||
extern struct group * get_group(const struct unit *u);
|
extern struct group * get_group(const struct unit *u);
|
||||||
extern void free_group(struct group *g);
|
extern void free_group(struct group *g);
|
||||||
|
|
|
@ -83,8 +83,8 @@ static void test_group(CuTest * tc)
|
||||||
assert(r && f);
|
assert(r && f);
|
||||||
u = test_create_unit(f, r);
|
u = test_create_unit(f, r);
|
||||||
assert(u);
|
assert(u);
|
||||||
CuAssertTrue(tc, join_group(u, "hodor"));
|
CuAssertPtrNotNull(tc, (g = join_group(u, "hodor")));
|
||||||
CuAssertPtrNotNull(tc, (g = get_group(u)));
|
CuAssertPtrEquals(tc, g, get_group(u));
|
||||||
CuAssertStrEquals(tc, "hodor", g->name);
|
CuAssertStrEquals(tc, "hodor", g->name);
|
||||||
CuAssertIntEquals(tc, 1, g->members);
|
CuAssertIntEquals(tc, 1, g->members);
|
||||||
set_group(u, 0);
|
set_group(u, 0);
|
||||||
|
|
|
@ -290,14 +290,3 @@ int read_plane_reference(plane ** pp, struct storage *store)
|
||||||
ur_add(id, pp, resolve_plane);
|
ur_add(id, pp, resolve_plane);
|
||||||
return AT_READ_OK;
|
return AT_READ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_watcher(const struct plane * p, const struct faction * f)
|
|
||||||
{
|
|
||||||
struct watcher *w;
|
|
||||||
if (!p)
|
|
||||||
return false;
|
|
||||||
w = p->watchers;
|
|
||||||
while (w && w->faction != f)
|
|
||||||
w = w->next;
|
|
||||||
return (w != NULL);
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct region;
|
struct region;
|
||||||
|
struct faction;
|
||||||
struct plane;
|
struct plane;
|
||||||
struct storage;
|
struct storage;
|
||||||
|
|
||||||
|
@ -43,15 +44,8 @@ extern "C" {
|
||||||
#define PFL_NOMONSTERS 16384 /* no monster randenc */
|
#define PFL_NOMONSTERS 16384 /* no monster randenc */
|
||||||
#define PFL_SEESPECIAL 32768 /* far seeing */
|
#define PFL_SEESPECIAL 32768 /* far seeing */
|
||||||
|
|
||||||
typedef struct watcher {
|
|
||||||
struct watcher *next;
|
|
||||||
struct faction *faction;
|
|
||||||
unsigned char mode;
|
|
||||||
} watcher;
|
|
||||||
|
|
||||||
typedef struct plane {
|
typedef struct plane {
|
||||||
struct plane *next;
|
struct plane *next;
|
||||||
struct watcher *watchers;
|
|
||||||
int id;
|
int id;
|
||||||
char *name;
|
char *name;
|
||||||
int minx, maxx, miny, maxy;
|
int minx, maxx, miny, maxy;
|
||||||
|
@ -76,7 +70,6 @@ extern "C" {
|
||||||
struct plane *get_homeplane(void);
|
struct plane *get_homeplane(void);
|
||||||
extern int rel_to_abs(const struct plane *pl, const struct faction *f,
|
extern int rel_to_abs(const struct plane *pl, const struct faction *f,
|
||||||
int rel, unsigned char index);
|
int rel, unsigned char index);
|
||||||
extern bool is_watcher(const struct plane *p, const struct faction *f);
|
|
||||||
extern void write_plane_reference(const plane * p, struct storage *store);
|
extern void write_plane_reference(const plane * p, struct storage *store);
|
||||||
extern int read_plane_reference(plane ** pp, struct storage *store);
|
extern int read_plane_reference(plane ** pp, struct storage *store);
|
||||||
extern int plane_width(const plane * pl);
|
extern int plane_width(const plane * pl);
|
||||||
|
|
|
@ -544,7 +544,8 @@ static void write_owner(struct gamedata *data, region_owner * owner)
|
||||||
write_faction_reference((f && f->_alive) ? f : NULL, data->store);
|
write_faction_reference((f && f->_alive) ? f : NULL, data->store);
|
||||||
// TODO: check that destroyfaction does the right thing.
|
// TODO: check that destroyfaction does the right thing.
|
||||||
// TODO: What happens to morale when the owner dies?
|
// TODO: What happens to morale when the owner dies?
|
||||||
write_faction_reference(owner->owner, data->store);
|
f = owner->owner;
|
||||||
|
write_faction_reference((f && f->_alive) ? f : NULL, data->store);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
WRITE_INT(data->store, -1);
|
WRITE_INT(data->store, -1);
|
||||||
|
@ -766,6 +767,7 @@ void write_unit(struct gamedata *data, const unit * u)
|
||||||
const race *irace = u_irace(u);
|
const race *irace = u_irace(u);
|
||||||
|
|
||||||
write_unit_reference(u, data->store);
|
write_unit_reference(u, data->store);
|
||||||
|
assert(u->faction->_alive);
|
||||||
write_faction_reference(u->faction, data->store);
|
write_faction_reference(u->faction, data->store);
|
||||||
WRITE_STR(data->store, u->_name);
|
WRITE_STR(data->store, u->_name);
|
||||||
WRITE_STR(data->store, u->display ? u->display : "");
|
WRITE_STR(data->store, u->display ? u->display : "");
|
||||||
|
@ -1159,6 +1161,58 @@ void write_spellbook(const struct spellbook *book, struct storage *store)
|
||||||
WRITE_TOK(store, "end");
|
WRITE_TOK(store, "end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char * getpasswd(int fno) {
|
||||||
|
const char *prefix = itoa36(fno);
|
||||||
|
size_t len = strlen(prefix);
|
||||||
|
FILE * F = fopen("passwords.txt", "r");
|
||||||
|
char line[80];
|
||||||
|
if (F) {
|
||||||
|
while (!feof(F)) {
|
||||||
|
fgets(line, sizeof(line), F);
|
||||||
|
if (line[len]==':' && strncmp(prefix, line, len)==0) {
|
||||||
|
size_t slen = strlen(line)-1;
|
||||||
|
assert(line[slen]=='\n');
|
||||||
|
line[slen] = 0;
|
||||||
|
fclose(F);
|
||||||
|
return _strdup(line+len+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(F);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_password(gamedata *data, faction *f) {
|
||||||
|
char name[128];
|
||||||
|
READ_STR(data->store, name, sizeof(name));
|
||||||
|
if (data->version == BADCRYPT_VERSION) {
|
||||||
|
char * pass = getpasswd(f->no);
|
||||||
|
if (pass) {
|
||||||
|
faction_setpassword(f, password_encode(pass, PASSWORD_DEFAULT));
|
||||||
|
free(pass); // TODO: remove this allocation!
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
free(f->_password);
|
||||||
|
f->_password = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
faction_setpassword(f, (data->version >= CRYPT_VERSION) ? name : password_encode(name, PASSWORD_DEFAULT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _test_read_password(gamedata *data, faction *f) {
|
||||||
|
read_password(data, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_password(gamedata *data, const faction *f) {
|
||||||
|
WRITE_TOK(data->store, (const char *)f->_password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _test_write_password(gamedata *data, const faction *f) {
|
||||||
|
write_password(data, f);
|
||||||
|
}
|
||||||
|
|
||||||
/** Reads a faction from a file.
|
/** Reads a faction from a file.
|
||||||
* This function requires no context, can be called in any state. The
|
* This function requires no context, can be called in any state. The
|
||||||
* faction may not already exist, however.
|
* faction may not already exist, however.
|
||||||
|
@ -1225,8 +1279,7 @@ faction *readfaction(struct gamedata * data)
|
||||||
set_email(&f->email, "");
|
set_email(&f->email, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_STR(data->store, name, sizeof(name));
|
read_password(data, f);
|
||||||
faction_setpassword(f, (data->version > CRYPT_VERSION) ? name : password_hash(name, 0, PASSWORD_DEFAULT));
|
|
||||||
if (data->version < NOOVERRIDE_VERSION) {
|
if (data->version < NOOVERRIDE_VERSION) {
|
||||||
READ_STR(data->store, 0, 0);
|
READ_STR(data->store, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -1313,6 +1366,7 @@ void writefaction(struct gamedata *data, const faction * f)
|
||||||
ally *sf;
|
ally *sf;
|
||||||
ursprung *ur;
|
ursprung *ur;
|
||||||
|
|
||||||
|
assert(f->_alive);
|
||||||
write_faction_reference(f, data->store);
|
write_faction_reference(f, data->store);
|
||||||
WRITE_INT(data->store, f->subscription);
|
WRITE_INT(data->store, f->subscription);
|
||||||
#if RELEASE_VERSION >= SPELL_LEVEL_VERSION
|
#if RELEASE_VERSION >= SPELL_LEVEL_VERSION
|
||||||
|
@ -1333,7 +1387,7 @@ void writefaction(struct gamedata *data, const faction * f)
|
||||||
WRITE_STR(data->store, f->name);
|
WRITE_STR(data->store, f->name);
|
||||||
WRITE_STR(data->store, f->banner);
|
WRITE_STR(data->store, f->banner);
|
||||||
WRITE_STR(data->store, f->email);
|
WRITE_STR(data->store, f->email);
|
||||||
WRITE_TOK(data->store, f->_password);
|
write_password(data, f);
|
||||||
WRITE_TOK(data->store, locale_name(f->locale));
|
WRITE_TOK(data->store, locale_name(f->locale));
|
||||||
WRITE_INT(data->store, f->lastorders);
|
WRITE_INT(data->store, f->lastorders);
|
||||||
WRITE_INT(data->store, f->age);
|
WRITE_INT(data->store, f->age);
|
||||||
|
@ -1384,32 +1438,6 @@ static int cb_sb_maxlevel(spellbook_entry *sbe, void *cbdata) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_watchers(storage *store, plane *pl) {
|
|
||||||
watcher *w = pl->watchers;
|
|
||||||
while (w) {
|
|
||||||
if (w->faction && w->faction->_alive) {
|
|
||||||
write_faction_reference(w->faction, store);
|
|
||||||
WRITE_INT(store, w->mode);
|
|
||||||
}
|
|
||||||
w = w->next;
|
|
||||||
}
|
|
||||||
write_faction_reference(NULL, store); /* mark the end of the list */
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_watchers(storage *store, plane *pl) {
|
|
||||||
variant fno = read_faction_reference(store);
|
|
||||||
while (fno.i) {
|
|
||||||
int n;
|
|
||||||
watcher *w = (watcher *)malloc(sizeof(watcher));
|
|
||||||
ur_add(fno, &w->faction, resolve_faction);
|
|
||||||
READ_INT(store, &n);
|
|
||||||
w->mode = (unsigned char)n;
|
|
||||||
w->next = pl->watchers;
|
|
||||||
pl->watchers = w;
|
|
||||||
fno = read_faction_reference(store);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int readgame(const char *filename, bool backup)
|
int readgame(const char *filename, bool backup)
|
||||||
{
|
{
|
||||||
int n, p, nread;
|
int n, p, nread;
|
||||||
|
@ -1528,7 +1556,13 @@ int readgame(const char *filename, bool backup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
read_watchers(&store, pl);
|
/* WATCHERS - eliminated in February 2016, ca. turn 966 */
|
||||||
|
if (gdata.version < CRYPT_VERSION) {
|
||||||
|
variant fno;
|
||||||
|
do {
|
||||||
|
fno = read_faction_reference(&store);
|
||||||
|
} while (fno.i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a_read(&store, &pl->attribs, pl);
|
a_read(&store, &pl->attribs, pl);
|
||||||
if (pl->id != 1094969858) { // Regatta
|
if (pl->id != 1094969858) { // Regatta
|
||||||
|
@ -1815,7 +1849,9 @@ int writegame(const char *filename)
|
||||||
WRITE_INT(&store, pl->miny);
|
WRITE_INT(&store, pl->miny);
|
||||||
WRITE_INT(&store, pl->maxy);
|
WRITE_INT(&store, pl->maxy);
|
||||||
WRITE_INT(&store, pl->flags);
|
WRITE_INT(&store, pl->flags);
|
||||||
write_watchers(&store, pl);
|
#if RELEASE_VERSION < CRYPT_VERSION
|
||||||
|
write_faction_reference(NULL, &store); /* mark the end of pl->watchers (gone since T966) */
|
||||||
|
#endif
|
||||||
a_write(&store, pl->attribs, pl);
|
a_write(&store, pl->attribs, pl);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,9 @@ extern "C" {
|
||||||
struct gamedata *gamedata_open(const char *filename, const char *mode);
|
struct gamedata *gamedata_open(const char *filename, const char *mode);
|
||||||
void gamedata_close(struct gamedata *data);
|
void gamedata_close(struct gamedata *data);
|
||||||
|
|
||||||
|
/* test-only functions that give access to internal implementation details (BAD) */
|
||||||
|
void _test_write_password(struct gamedata *data, const struct faction *f);
|
||||||
|
void _test_read_password(struct gamedata *data, struct faction *f);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,11 +3,25 @@
|
||||||
|
|
||||||
#include "save.h"
|
#include "save.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
#include "group.h"
|
||||||
|
#include "ally.h"
|
||||||
#include "faction.h"
|
#include "faction.h"
|
||||||
|
#include "plane.h"
|
||||||
|
#include "region.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include <triggers/changefaction.h>
|
||||||
|
#include <triggers/createunit.h>
|
||||||
|
#include <triggers/timeout.h>
|
||||||
|
#include <util/attrib.h>
|
||||||
|
#include <util/event.h>
|
||||||
|
#include <util/base36.h>
|
||||||
|
#include <util/password.h>
|
||||||
|
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
|
||||||
|
#include <storage.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static void test_readwrite_data(CuTest * tc)
|
static void test_readwrite_data(CuTest * tc)
|
||||||
|
@ -42,15 +56,17 @@ static void test_readwrite_unit(CuTest * tc)
|
||||||
u = test_create_unit(f, r);
|
u = test_create_unit(f, r);
|
||||||
join_path(datapath(), filename, path, sizeof(path));
|
join_path(datapath(), filename, path, sizeof(path));
|
||||||
|
|
||||||
data = gamedata_open(path, "w");
|
data = gamedata_open(path, "wb");
|
||||||
CuAssertPtrNotNull(tc, data); // TODO: intermittent test
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
|
||||||
write_unit(data, u);
|
write_unit(data, u);
|
||||||
gamedata_close(data);
|
gamedata_close(data);
|
||||||
|
|
||||||
free_gamedata();
|
free_gamedata();
|
||||||
f = test_create_faction(0);
|
f = test_create_faction(0);
|
||||||
renumber_faction(f, fno);
|
renumber_faction(f, fno);
|
||||||
data = gamedata_open(path, "r");
|
data = gamedata_open(path, "rb");
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
u = read_unit(data);
|
u = read_unit(data);
|
||||||
gamedata_close(data);
|
gamedata_close(data);
|
||||||
|
|
||||||
|
@ -61,10 +77,189 @@ static void test_readwrite_unit(CuTest * tc)
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_dead_faction_group(CuTest *tc) {
|
||||||
|
faction *f, *f2;
|
||||||
|
unit * u;
|
||||||
|
group *g;
|
||||||
|
ally *al;
|
||||||
|
int fno;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
f = test_create_faction(0);
|
||||||
|
fno = f->no;
|
||||||
|
CuAssertPtrEquals(tc, f, factions);
|
||||||
|
CuAssertPtrEquals(tc, 0, f->next);
|
||||||
|
f2 = test_create_faction(0);
|
||||||
|
CuAssertPtrEquals(tc, f2, factions->next);
|
||||||
|
u = test_create_unit(f2, test_create_region(0, 0, 0));
|
||||||
|
CuAssertPtrNotNull(tc, u);
|
||||||
|
g = join_group(u, "group");
|
||||||
|
CuAssertPtrNotNull(tc, g);
|
||||||
|
al = ally_add(&g->allies, f);
|
||||||
|
CuAssertPtrNotNull(tc, al);
|
||||||
|
|
||||||
|
CuAssertPtrEquals(tc, f, factions);
|
||||||
|
destroyfaction(&factions);
|
||||||
|
CuAssertTrue(tc, !f->_alive);
|
||||||
|
CuAssertPtrEquals(tc, f2, factions);
|
||||||
|
writegame("test.dat");
|
||||||
|
free_gamedata();
|
||||||
|
f = f2 = NULL;
|
||||||
|
readgame("test.dat", false);
|
||||||
|
CuAssertPtrEquals(tc, 0, findfaction(fno));
|
||||||
|
f2 = factions;
|
||||||
|
CuAssertPtrNotNull(tc, f2);
|
||||||
|
u = f2->units;
|
||||||
|
CuAssertPtrNotNull(tc, u);
|
||||||
|
g = get_group(u);
|
||||||
|
CuAssertPtrNotNull(tc, g);
|
||||||
|
CuAssertPtrEquals(tc, 0, g->allies);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_dead_faction_regionowner(CuTest *tc) {
|
||||||
|
faction *f;
|
||||||
|
region *r;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
config_set("rules.region_owners", "1");
|
||||||
|
f = test_create_faction(0);
|
||||||
|
test_create_unit(f, r = test_create_region(0, 0, 0));
|
||||||
|
region_set_owner(r, f, turn);
|
||||||
|
destroyfaction(&factions);
|
||||||
|
CuAssertTrue(tc, !f->_alive);
|
||||||
|
remove_empty_units();
|
||||||
|
writegame("test.dat");
|
||||||
|
free_gamedata();
|
||||||
|
f = NULL;
|
||||||
|
readgame("test.dat", false);
|
||||||
|
f = factions;
|
||||||
|
CuAssertPtrEquals(tc, 0, f);
|
||||||
|
r = regions;
|
||||||
|
CuAssertPtrNotNull(tc, r);
|
||||||
|
CuAssertPtrEquals(tc, 0, region_get_owner(r));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_dead_faction_changefaction(CuTest *tc) {
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
trigger *tr;
|
||||||
|
unit * u;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
f = test_create_faction(0);
|
||||||
|
f2 = test_create_faction(0);
|
||||||
|
u = test_create_unit(f2, r = test_create_region(0, 0, 0));
|
||||||
|
tr = trigger_changefaction(u, f);
|
||||||
|
add_trigger(&u->attribs, "timer", trigger_timeout(10, tr));
|
||||||
|
CuAssertPtrNotNull(tc, a_find(u->attribs, &at_eventhandler));
|
||||||
|
destroyfaction(&factions);
|
||||||
|
CuAssertTrue(tc, !f->_alive);
|
||||||
|
remove_empty_units();
|
||||||
|
writegame("test.dat");
|
||||||
|
free_gamedata();
|
||||||
|
f = NULL;
|
||||||
|
readgame("test.dat", false);
|
||||||
|
f = factions;
|
||||||
|
CuAssertPtrNotNull(tc, f);
|
||||||
|
r = regions;
|
||||||
|
CuAssertPtrNotNull(tc, r);
|
||||||
|
u = r->units;
|
||||||
|
CuAssertPtrNotNull(tc, u);
|
||||||
|
CuAssertPtrEquals(tc, 0, a_find(u->attribs, &at_eventhandler));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_dead_faction_createunit(CuTest *tc) {
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
trigger *tr;
|
||||||
|
unit * u;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
f = test_create_faction(0);
|
||||||
|
f2 = test_create_faction(0);
|
||||||
|
u = test_create_unit(f2, r = test_create_region(0, 0, 0));
|
||||||
|
tr = trigger_createunit(r, f, f->race, 1);
|
||||||
|
add_trigger(&u->attribs, "timer", trigger_timeout(10, tr));
|
||||||
|
CuAssertPtrNotNull(tc, a_find(u->attribs, &at_eventhandler));
|
||||||
|
destroyfaction(&factions);
|
||||||
|
CuAssertTrue(tc, !f->_alive);
|
||||||
|
remove_empty_units();
|
||||||
|
writegame("test.dat");
|
||||||
|
free_gamedata();
|
||||||
|
f = NULL;
|
||||||
|
readgame("test.dat", false);
|
||||||
|
f = factions;
|
||||||
|
CuAssertPtrNotNull(tc, f);
|
||||||
|
r = regions;
|
||||||
|
CuAssertPtrNotNull(tc, r);
|
||||||
|
u = r->units;
|
||||||
|
CuAssertPtrNotNull(tc, u);
|
||||||
|
CuAssertPtrEquals(tc, 0, a_find(u->attribs, &at_eventhandler));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_read_password(CuTest *tc) {
|
||||||
|
const char *path = "test.dat";
|
||||||
|
gamedata *data;
|
||||||
|
faction *f;
|
||||||
|
f = test_create_faction(0);
|
||||||
|
faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT));
|
||||||
|
data = gamedata_open(path, "wb");
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
_test_write_password(data, f);
|
||||||
|
gamedata_close(data);
|
||||||
|
data = gamedata_open(path, "rb");
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
_test_read_password(data, f);
|
||||||
|
gamedata_close(data);
|
||||||
|
CuAssertTrue(tc, checkpasswd(f, "secret"));
|
||||||
|
CuAssertIntEquals(tc, 0, remove(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_read_password_external(CuTest *tc) {
|
||||||
|
const char *path = "test.dat", *pwfile = "passwords.txt";
|
||||||
|
gamedata *data;
|
||||||
|
faction *f;
|
||||||
|
FILE * F;
|
||||||
|
|
||||||
|
remove(pwfile);
|
||||||
|
f = test_create_faction(0);
|
||||||
|
faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT));
|
||||||
|
CuAssertPtrNotNull(tc, f->_password);
|
||||||
|
data = gamedata_open(path, "wb");
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
WRITE_TOK(data->store, (const char *)f->_password);
|
||||||
|
WRITE_TOK(data->store, (const char *)f->_password);
|
||||||
|
gamedata_close(data);
|
||||||
|
data = gamedata_open(path, "rb");
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
data->version = BADCRYPT_VERSION;
|
||||||
|
_test_read_password(data, f);
|
||||||
|
CuAssertPtrEquals(tc, 0, f->_password);
|
||||||
|
F = fopen(pwfile, "wt");
|
||||||
|
fprintf(F, "%s:secret\n", itoa36(f->no));
|
||||||
|
fclose(F);
|
||||||
|
_test_read_password(data, f);
|
||||||
|
CuAssertPtrNotNull(tc, f->_password);
|
||||||
|
gamedata_close(data);
|
||||||
|
CuAssertTrue(tc, checkpasswd(f, "secret"));
|
||||||
|
CuAssertIntEquals(tc, 0, remove(path));
|
||||||
|
CuAssertIntEquals(tc, 0, remove(pwfile));
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_save_suite(void)
|
CuSuite *get_save_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_data);
|
SUITE_ADD_TEST(suite, test_readwrite_data);
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_unit);
|
SUITE_ADD_TEST(suite, test_readwrite_unit);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_createunit);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_changefaction);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_regionowner);
|
||||||
|
DISABLE_TEST(suite, test_readwrite_dead_faction_group);
|
||||||
|
SUITE_ADD_TEST(suite, test_read_password);
|
||||||
|
SUITE_ADD_TEST(suite, test_read_password_external);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,10 @@
|
||||||
#define SPELL_LEVEL_VERSION 348 /* f->max_spelllevel gets stored, not calculated */
|
#define SPELL_LEVEL_VERSION 348 /* f->max_spelllevel gets stored, not calculated */
|
||||||
#define OWNER_3_VERSION 349 /* regions store last owner, not last alliance */
|
#define OWNER_3_VERSION 349 /* regions store last owner, not last alliance */
|
||||||
#define ATTRIBOWNER_VERSION 350 /* all attrib_type functions know who owns the attribute */
|
#define ATTRIBOWNER_VERSION 350 /* all attrib_type functions know who owns the attribute */
|
||||||
#define CRYPT_VERSION 351 /* passwords are encrypted */
|
#define BADCRYPT_VERSION 351 /* passwords are encrypted, poorly */
|
||||||
#define RELEASE_VERSION CRYPT_VERSION /* current datafile */
|
#define CRYPT_VERSION 352 /* passwords are encrypted */
|
||||||
|
#define RELEASE_VERSION ATTRIBOWNER_VERSION /* current datafile */
|
||||||
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
|
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
|
||||||
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
#define MAX_VERSION BADCRYPT_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
||||||
|
|
||||||
#define STREAM_VERSION 2 /* internal encoding of binary files */
|
#define STREAM_VERSION 2 /* internal encoding of binary files */
|
||||||
|
|
|
@ -2172,7 +2172,7 @@ int password_cmd(unit * u, struct order *ord)
|
||||||
cmistake(u, ord, 283, MSG_EVENT);
|
cmistake(u, ord, 283, MSG_EVENT);
|
||||||
strlcpy(pwbuf, itoa36(rng_int()), sizeof(pwbuf));
|
strlcpy(pwbuf, itoa36(rng_int()), sizeof(pwbuf));
|
||||||
}
|
}
|
||||||
faction_setpassword(u->faction, password_hash(pwbuf, 0, PASSWORD_DEFAULT));
|
faction_setpassword(u->faction, password_encode(pwbuf, PASSWORD_DEFAULT));
|
||||||
ADDMSG(&u->faction->msgs, msg_message("changepasswd",
|
ADDMSG(&u->faction->msgs, msg_message("changepasswd",
|
||||||
"value", pwbuf));
|
"value", pwbuf));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1385,17 +1385,9 @@ static void prepare_reports(void)
|
||||||
|
|
||||||
for (r = regions; r; r = r->next) {
|
for (r = regions; r; r = r->next) {
|
||||||
unit *u;
|
unit *u;
|
||||||
plane *p = rplane(r);
|
|
||||||
|
|
||||||
reorder_units(r);
|
reorder_units(r);
|
||||||
|
|
||||||
if (p) {
|
|
||||||
watcher *w = p->watchers;
|
|
||||||
for (; w; w = w->next) {
|
|
||||||
faction_add_seen(w->faction, r, w->mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Region owner get always the Lighthouse report */
|
/* Region owner get always the Lighthouse report */
|
||||||
if (bt_lighthouse && config_token("rules.region_owner_pay_building", bt_lighthouse->_name)) {
|
if (bt_lighthouse && config_token("rules.region_owner_pay_building", bt_lighthouse->_name)) {
|
||||||
for (b = rbuildings(r); b; b = b->next) {
|
for (b = rbuildings(r); b; b = b->next) {
|
||||||
|
@ -1464,8 +1456,6 @@ static region *lastregion(faction * f)
|
||||||
|
|
||||||
/* we continue from the best region and look for travelthru etc. */
|
/* we continue from the best region and look for travelthru etc. */
|
||||||
for (r = f->last->next; r; r = r->next) {
|
for (r = f->last->next; r; r = r->next) {
|
||||||
plane *p = rplane(r);
|
|
||||||
|
|
||||||
/* search the region for travelthru-attributes: */
|
/* search the region for travelthru-attributes: */
|
||||||
if (fval(r, RF_TRAVELUNIT)) {
|
if (fval(r, RF_TRAVELUNIT)) {
|
||||||
travelthru_map(r, cb_set_last, f);
|
travelthru_map(r, cb_set_last, f);
|
||||||
|
@ -1474,9 +1464,6 @@ static region *lastregion(faction * f)
|
||||||
continue;
|
continue;
|
||||||
if (check_leuchtturm(r, f))
|
if (check_leuchtturm(r, f))
|
||||||
f->last = r;
|
f->last = r;
|
||||||
if (p && is_watcher(p, f)) {
|
|
||||||
f->last = r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return f->last->next;
|
return f->last->next;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
|
|
||||||
#include <kernel/config.h>
|
#include <kernel/config.h>
|
||||||
|
#include <kernel/plane.h>
|
||||||
#include <kernel/region.h>
|
#include <kernel/region.h>
|
||||||
#include <kernel/terrain.h>
|
#include <kernel/terrain.h>
|
||||||
#include <kernel/item.h>
|
#include <kernel/item.h>
|
||||||
|
@ -47,7 +48,7 @@ struct region *test_create_region(int x, int y, const terrain_type *terrain)
|
||||||
{
|
{
|
||||||
region *r = findregion(x, y);
|
region *r = findregion(x, y);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
r = new_region(x, y, NULL, 0);
|
r = new_region(x, y, findplane(x, y), 0);
|
||||||
}
|
}
|
||||||
if (!terrain) {
|
if (!terrain) {
|
||||||
terrain_type *t = get_or_create_terrain("plain");
|
terrain_type *t = get_or_create_terrain("plain");
|
||||||
|
|
|
@ -79,14 +79,20 @@ static void changefaction_write(const trigger * t, struct storage *store)
|
||||||
{
|
{
|
||||||
changefaction_data *td = (changefaction_data *)t->data.v;
|
changefaction_data *td = (changefaction_data *)t->data.v;
|
||||||
write_unit_reference(td->unit, store);
|
write_unit_reference(td->unit, store);
|
||||||
write_faction_reference(td->faction, store);
|
write_faction_reference(td->faction->_alive ? td->faction : NULL, store);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int changefaction_read(trigger * t, struct storage *store)
|
static int changefaction_read(trigger * t, struct storage *store)
|
||||||
{
|
{
|
||||||
|
variant var;
|
||||||
changefaction_data *td = (changefaction_data *)t->data.v;
|
changefaction_data *td = (changefaction_data *)t->data.v;
|
||||||
read_reference(&td->unit, store, read_unit_reference, resolve_unit);
|
read_reference(&td->unit, store, read_unit_reference, resolve_unit);
|
||||||
read_reference(&td->faction, store, read_faction_reference, resolve_faction);
|
var = read_faction_reference(store);
|
||||||
|
if (var.i == 0) {
|
||||||
|
return AT_READ_FAIL;
|
||||||
|
}
|
||||||
|
ur_add(var, &td->faction, resolve_faction);
|
||||||
|
// read_reference(&td->faction, store, read_faction_reference, resolve_faction);
|
||||||
return AT_READ_OK;
|
return AT_READ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ static int createunit_handle(trigger * t, void *data)
|
||||||
static void createunit_write(const trigger * t, struct storage *store)
|
static void createunit_write(const trigger * t, struct storage *store)
|
||||||
{
|
{
|
||||||
createunit_data *td = (createunit_data *)t->data.v;
|
createunit_data *td = (createunit_data *)t->data.v;
|
||||||
write_faction_reference(td->f, store);
|
write_faction_reference(td->f->_alive ? td->f : NULL, store);
|
||||||
write_region_reference(td->r, store);
|
write_region_reference(td->r, store);
|
||||||
write_race_reference(td->race, store);
|
write_race_reference(td->race, store);
|
||||||
WRITE_INT(store, td->number);
|
WRITE_INT(store, td->number);
|
||||||
|
@ -91,21 +91,27 @@ static void createunit_write(const trigger * t, struct storage *store)
|
||||||
static int createunit_read(trigger * t, struct storage *store)
|
static int createunit_read(trigger * t, struct storage *store)
|
||||||
{
|
{
|
||||||
createunit_data *td = (createunit_data *)t->data.v;
|
createunit_data *td = (createunit_data *)t->data.v;
|
||||||
|
variant var;
|
||||||
|
int result = AT_READ_OK;
|
||||||
|
|
||||||
int uc =
|
var = read_faction_reference(store);
|
||||||
read_reference(&td->f, store, read_faction_reference, resolve_faction);
|
if (var.i > 0) {
|
||||||
int rc =
|
td->f = findfaction(var.i);
|
||||||
|
if (!td->f) {
|
||||||
|
ur_add(var, &td->f, resolve_faction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = AT_READ_FAIL;
|
||||||
|
}
|
||||||
read_reference(&td->r, store, read_region_reference,
|
read_reference(&td->r, store, read_region_reference,
|
||||||
RESOLVE_REGION(global.data_version));
|
RESOLVE_REGION(global.data_version));
|
||||||
td->race = (const struct race *)read_race_reference(store).v;
|
td->race = (const struct race *)read_race_reference(store).v;
|
||||||
|
if (!td->race) {
|
||||||
if (uc == 0 && rc == 0) {
|
result = AT_READ_FAIL;
|
||||||
if (!td->f || !td->r)
|
|
||||||
return AT_READ_FAIL;
|
|
||||||
}
|
}
|
||||||
READ_INT(store, &td->number);
|
READ_INT(store, &td->number);
|
||||||
|
return result;
|
||||||
return AT_READ_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger_type tt_createunit = {
|
trigger_type tt_createunit = {
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <platform.h>
|
||||||
|
#include "gamedata.h"
|
||||||
|
|
||||||
|
#include <CuTest.h>
|
||||||
|
#include <tests.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void test_gamedata(CuTest * tc)
|
||||||
|
{
|
||||||
|
gamedata *data;
|
||||||
|
data = gamedata_open("test.dat", "wb", 0);
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
gamedata_close(data);
|
||||||
|
data = gamedata_open("test.dat", "rb", 0);
|
||||||
|
CuAssertPtrNotNull(tc, data);
|
||||||
|
gamedata_close(data);
|
||||||
|
CuAssertIntEquals(tc, 0, remove("test.dat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_gamedata_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_gamedata);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -2,7 +2,9 @@
|
||||||
#include "password.h"
|
#include "password.h"
|
||||||
|
|
||||||
#include <md5.h>
|
#include <md5.h>
|
||||||
|
#include <crypt_blowfish.h>
|
||||||
#include <mtrand.h>
|
#include <mtrand.h>
|
||||||
|
#include <drepper.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -25,73 +27,104 @@
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
char *password_gensalt(void) {
|
char *password_gensalt(char *salt, size_t salt_len) {
|
||||||
static char salt[SALTLEN + 1];
|
size_t buflen = salt_len-1;
|
||||||
char *cp = salt;
|
char *cp = salt;
|
||||||
int buflen = SALTLEN;
|
|
||||||
while (buflen) {
|
while (buflen) {
|
||||||
unsigned long ul = genrand_int32() & (unsigned long)time(0);
|
unsigned long ul = genrand_int32() & (unsigned long)time(0);
|
||||||
b64_from_24bit((char)(ul & 0xFF), (char)((ul >> 8) & 0xff), (char)((ul >> 16) & 0xFF), 4);
|
b64_from_24bit((char)(ul & 0xFF), (char)((ul >> 8) & 0xff), (char)((ul >> 16) & 0xFF), 4);
|
||||||
}
|
}
|
||||||
salt[SALTLEN] = 0;
|
salt[salt_len-1] = 0;
|
||||||
return salt;
|
return salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * password_hash_i(const char * passwd, const char *salt, int algo, char *result, size_t len) {
|
static bool password_is_implemented(int algo) {
|
||||||
assert(passwd);
|
return algo == PASSWORD_PLAINTEXT || algo == PASSWORD_BCRYPT || algo == PASSWORD_NOCRYPT || algo == PASSWORD_MD5 || algo == PASSWORD_APACHE_MD5;
|
||||||
if (!salt) {
|
|
||||||
salt = password_gensalt();
|
|
||||||
}
|
}
|
||||||
if (algo==PASSWORD_PLAIN) {
|
|
||||||
_snprintf(result, len, "$0$%s$%s", salt, passwd);
|
static const char * password_hash_i(const char * passwd, const char *input, int algo, char *result, size_t len) {
|
||||||
|
if (algo == PASSWORD_BCRYPT) {
|
||||||
|
char salt[MAXSALTLEN];
|
||||||
|
char setting[40];
|
||||||
|
if (!input) {
|
||||||
|
input = password_gensalt(salt, MAXSALTLEN);
|
||||||
}
|
}
|
||||||
else if (algo == PASSWORD_MD5) {
|
if (_crypt_gensalt_blowfish_rn("$2y$", 5, input, strlen(input), setting, sizeof(setting)) == NULL) {
|
||||||
return md5_crypt_r(passwd, salt, result, len);
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (algo == PASSWORD_APACHE_MD5) {
|
if (_crypt_blowfish_rn(passwd, setting, result, len) == NULL) {
|
||||||
apr_md5_encode(passwd, salt, result, len);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
else if (algo == PASSWORD_PLAINTEXT) {
|
||||||
const char * password_hash(const char * passwd, const char * salt, int algo) {
|
_snprintf(result, len, "%s", passwd);
|
||||||
static char result[64]; // TODO: static result buffers are bad mojo!
|
return result;
|
||||||
if (algo < 0) algo = PASSWORD_DEFAULT;
|
}
|
||||||
return password_hash_i(passwd, salt, algo, result, sizeof(result));
|
else if (algo == PASSWORD_NOCRYPT) {
|
||||||
|
_snprintf(result, len, "$0$%s", passwd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (password_is_implemented(algo)) {
|
||||||
|
char salt[MAXSALTLEN];
|
||||||
|
assert(passwd);
|
||||||
|
if (input) {
|
||||||
|
const char * dol = strchr(input, '$');
|
||||||
|
size_t salt_len;
|
||||||
|
if (dol) {
|
||||||
|
assert(dol > input && dol[0] == '$');
|
||||||
|
salt_len = dol - input;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
salt_len = strlen(input);
|
||||||
|
}
|
||||||
|
assert(salt_len < MAXSALTLEN);
|
||||||
|
memcpy(salt, input, salt_len);
|
||||||
|
salt[salt_len] = 0;
|
||||||
|
} else {
|
||||||
|
input = password_gensalt(salt, sizeof(salt));
|
||||||
|
}
|
||||||
|
if (algo == PASSWORD_MD5) {
|
||||||
|
return md5_crypt_r(passwd, input, result, len);
|
||||||
|
}
|
||||||
|
else if (algo == PASSWORD_APACHE_MD5) {
|
||||||
|
apr_md5_encode(passwd, input, result, len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool password_is_implemented(int algo) {
|
const char * password_encode(const char * passwd, int algo) {
|
||||||
return algo==PASSWORD_PLAIN || algo==PASSWORD_MD5 || algo==PASSWORD_APACHE_MD5;
|
static char result[64]; // TODO: static result buffers are bad mojo!
|
||||||
|
if (algo < 0) algo = PASSWORD_DEFAULT;
|
||||||
|
return password_hash_i(passwd, 0, algo, result, sizeof(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
int password_verify(const char * pwhash, const char * passwd) {
|
int password_verify(const char * pwhash, const char * passwd) {
|
||||||
char salt[MAXSALTLEN+1];
|
|
||||||
char hash[64];
|
char hash[64];
|
||||||
size_t len;
|
int algo = PASSWORD_PLAINTEXT;
|
||||||
int algo;
|
|
||||||
char *pos;
|
char *pos;
|
||||||
const char *dol, *result;
|
const char *result;
|
||||||
assert(passwd);
|
assert(passwd);
|
||||||
assert(pwhash);
|
assert(pwhash);
|
||||||
assert(pwhash[0] == '$');
|
if (pwhash[0] == '$') {
|
||||||
algo = pwhash[1];
|
algo = pwhash[1];
|
||||||
pos = strchr(pwhash+2, '$');
|
}
|
||||||
assert(pos && pos[0] == '$');
|
|
||||||
++pos;
|
|
||||||
dol = strchr(pos, '$');
|
|
||||||
assert(dol>pos && dol[0] == '$');
|
|
||||||
len = dol - pos;
|
|
||||||
assert(len <= MAXSALTLEN);
|
|
||||||
strncpy(salt, pos, len);
|
|
||||||
salt[len] = 0;
|
|
||||||
result = password_hash_i(passwd, salt, algo, hash, sizeof(hash));
|
|
||||||
if (!password_is_implemented(algo)) {
|
if (!password_is_implemented(algo)) {
|
||||||
return VERIFY_UNKNOWN;
|
return VERIFY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
if (algo == PASSWORD_PLAINTEXT) {
|
||||||
|
return (strcmp(passwd, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;
|
||||||
|
} else if (algo == PASSWORD_BCRYPT) {
|
||||||
|
char sample[200];
|
||||||
|
_crypt_blowfish_rn(passwd, pwhash, sample, sizeof(sample));
|
||||||
|
return (strcmp(sample, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;
|
||||||
|
}
|
||||||
|
pos = strchr(pwhash+2, '$');
|
||||||
|
assert(pos && pos[0] == '$');
|
||||||
|
pos = strchr(pos, '$')+1;
|
||||||
|
result = password_hash_i(passwd, pos, algo, hash, sizeof(hash));
|
||||||
if (strcmp(pwhash, result) == 0) {
|
if (strcmp(pwhash, result) == 0) {
|
||||||
return VERIFY_OK;
|
return VERIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PASSWORD_PLAIN '0'
|
#define PASSWORD_PLAINTEXT 0
|
||||||
|
#define PASSWORD_NOCRYPT '0'
|
||||||
#define PASSWORD_MD5 '1'
|
#define PASSWORD_MD5 '1'
|
||||||
#define PASSWORD_BCRYPT '2' // not implemented
|
#define PASSWORD_BCRYPT '2' // not implemented
|
||||||
#define PASSWORD_APACHE_MD5 'a'
|
#define PASSWORD_APACHE_MD5 'a'
|
||||||
#define PASSWORD_SHA256 '5' // not implemented
|
#define PASSWORD_SHA256 '5' // not implemented
|
||||||
#define PASSWORD_SHA512 '6' // not implemented
|
#define PASSWORD_SHA512 '6' // not implemented
|
||||||
#define PASSWORD_DEFAULT PASSWORD_APACHE_MD5
|
#define PASSWORD_DEFAULT PASSWORD_PLAINTEXT
|
||||||
|
|
||||||
#define VERIFY_OK 0 // password matches hash
|
#define VERIFY_OK 0 // password matches hash
|
||||||
#define VERIFY_FAIL 1 // password is wrong
|
#define VERIFY_FAIL 1 // password is wrong
|
||||||
#define VERIFY_UNKNOWN 2 // hashing algorithm not supported
|
#define VERIFY_UNKNOWN 2 // hashing algorithm not supported
|
||||||
int password_verify(const char *hash, const char *passwd);
|
int password_verify(const char *hash, const char *passwd);
|
||||||
const char * password_hash(const char *passwd, const char *salt, int algo);
|
const char * password_encode(const char *passwd, int algo);
|
||||||
|
|
|
@ -1,25 +1,43 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <CuTest.h>
|
|
||||||
#include "password.h"
|
#include "password.h"
|
||||||
|
#include <CuTest.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static void test_passwords(CuTest *tc) {
|
static void test_passwords(CuTest *tc) {
|
||||||
const char *hash;
|
const char *hash, *expect;
|
||||||
|
|
||||||
hash = password_hash("Hodor", "FqQLkl8g", PASSWORD_APACHE_MD5);
|
expect = "$apr1$FqQLkl8g$.icQqaDJpim4BVy.Ho5660";
|
||||||
|
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "Hodor"));
|
||||||
|
hash = password_encode("Hodor", PASSWORD_APACHE_MD5);
|
||||||
CuAssertPtrNotNull(tc, hash);
|
CuAssertPtrNotNull(tc, hash);
|
||||||
CuAssertStrEquals(tc, "$apr1$FqQLkl8g$.icQqaDJpim4BVy.Ho5660", hash);
|
CuAssertIntEquals(tc, 0, strncmp(hash, expect, 6));
|
||||||
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "Hodor"));
|
|
||||||
|
|
||||||
hash = password_hash("jollygood", "ZouUn04i", PASSWORD_MD5);
|
expect = "$1$ZouUn04i$yNnT1Oy8azJ5V.UM9ppP5/";
|
||||||
|
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "jollygood"));
|
||||||
|
hash = password_encode("jollygood", PASSWORD_MD5);
|
||||||
CuAssertPtrNotNull(tc, hash);
|
CuAssertPtrNotNull(tc, hash);
|
||||||
CuAssertStrEquals(tc, "$1$ZouUn04i$yNnT1Oy8azJ5V.UM9ppP5/", hash);
|
CuAssertIntEquals(tc, 0, strncmp(hash, expect, 3));
|
||||||
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "jollygood"));
|
|
||||||
|
|
||||||
hash = password_hash("password", "hodor", PASSWORD_PLAIN);
|
expect = "password";
|
||||||
|
hash = password_encode("password", PASSWORD_PLAINTEXT);
|
||||||
CuAssertPtrNotNull(tc, hash);
|
CuAssertPtrNotNull(tc, hash);
|
||||||
CuAssertStrEquals(tc, "$0$hodor$password", hash);
|
CuAssertStrEquals(tc, hash, expect);
|
||||||
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "password"));
|
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "password"));
|
||||||
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(hash, "arseword"));
|
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(expect, "arseword"));
|
||||||
|
|
||||||
|
expect = "$0$password";
|
||||||
|
hash = password_encode("password", PASSWORD_NOCRYPT);
|
||||||
|
CuAssertPtrNotNull(tc, hash);
|
||||||
|
CuAssertStrEquals(tc, hash, expect);
|
||||||
|
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "password"));
|
||||||
|
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(expect, "arseword"));
|
||||||
|
|
||||||
|
expect = "$2y$05$RJ8qAhu.foXyJLdc2eHTLOaK4MDYn3/v4HtOVCq0Plv2yxcrEB7Wm";
|
||||||
|
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "Hodor"));
|
||||||
|
hash = password_encode("Hodor", PASSWORD_BCRYPT);
|
||||||
|
CuAssertPtrNotNull(tc, hash);
|
||||||
|
CuAssertIntEquals(tc, 0, strncmp(hash, expect, 7));
|
||||||
|
|
||||||
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify("$9$saltyfish$password", "password"));
|
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify("$9$saltyfish$password", "password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ TESTS=../Debug/eressea/test_eressea
|
||||||
SERVER=../Debug/eressea/eressea
|
SERVER=../Debug/eressea/eressea
|
||||||
if [ -n "$VALGRIND" ]; then
|
if [ -n "$VALGRIND" ]; then
|
||||||
SUPP=../share/ubuntu-12_04.supp
|
SUPP=../share/ubuntu-12_04.supp
|
||||||
VALGRIND="$VALGRIND --suppressions=$SUPP --error-exitcode=1 --leak-check=no"
|
VALGRIND="$VALGRIND --track-origins=yes --gen-suppressions=all --suppressions=$SUPP --error-exitcode=1 --leak-check=no"
|
||||||
fi
|
fi
|
||||||
echo "running $TESTS"
|
echo "running $TESTS"
|
||||||
$VALGRIND $TESTS
|
$VALGRIND $TESTS
|
||||||
|
|
Loading…
Reference in New Issue