29 #define fetch_metadata(name) \
30 item = metadata->GetItem(name, false); \
31 if (item == NULL || StrEmpty(item->value)) { \
32 DEBUG(grf, 0, "Base " SET_TYPE "set detail loading: %s field missing.", name); \
33 DEBUG(grf, 0, " Is %s readable for the user running OpenTTD?", full_filename); \
45 template <
class T,
size_t Tnum_files,
bool Tsearch_in_tars>
48 memset(
this, 0,
sizeof(*
this));
60 for (
const IniItem *item = metadata->
item; item != NULL; item = item->
next) {
61 if (strncmp(
"description.", item->
name, 12) != 0)
continue;
67 for (uint i = 0; item->
value[i] !=
'\0' && i < 4; i++) {
68 this->shortname |= ((uint8)item->
value[i]) << (i * 8);
72 this->version = atoi(item->
value);
74 item = metadata->
GetItem(
"fallback",
false);
75 this->fallback = (item != NULL && strcmp(item->
value,
"0") != 0 && strcmp(item->
value,
"false") != 0);
81 for (uint i = 0; i < Tnum_files; i++) {
82 MD5File *file = &this->files[i];
85 if (item == NULL || (item->
value == NULL && !allow_empty_filename)) {
90 const char *filename = item->
value;
91 if (filename == NULL) {
102 item = md5s->
GetItem(filename,
false);
103 if (item == NULL || item->
value == NULL) {
104 DEBUG(grf, 0,
"No MD5 checksum specified for: %s (in %s)", filename, full_filename);
107 char *c = item->
value;
108 for (uint i = 0; i <
sizeof(file->
hash) * 2; i++, c++) {
110 if (
'0' <= *c && *c <=
'9') {
112 }
else if (
'a' <= *c && *c <=
'f') {
114 }
else if (
'A' <= *c && *c <=
'F') {
117 DEBUG(grf, 0,
"Malformed MD5 checksum specified for: %s (in %s)", filename, full_filename);
121 file->
hash[i / 2] = j << 4;
123 file->
hash[i / 2] |= j;
128 item = origin->
GetItem(filename,
false);
129 if (item == NULL) item = origin->
GetItem(
"default",
false);
131 DEBUG(grf, 1,
"No origin warning message specified for: %s", filename);
144 DEBUG(grf, 1,
"MD5 checksum mismatch for: %s (in %s)", filename, full_filename);
149 DEBUG(grf, 1,
"The file %s specified in %s is missing", filename, full_filename);
157 template <
class Tbase_set>
161 DEBUG(grf, 1,
"Checking %s for base " SET_TYPE " set", filename);
163 Tbase_set *
set =
new Tbase_set();
167 char *path =
stredup(filename + basepath_length);
168 char *psep = strrchr(path, PATHSEPCHAR);
175 if (set->FillSetDetails(ini, path, filename)) {
176 Tbase_set *duplicate = NULL;
178 if (strcmp(c->name, set->name) == 0 || c->shortname ==
set->shortname) {
183 if (duplicate != NULL) {
185 if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
186 duplicate->valid_files >
set->valid_files) {
187 DEBUG(grf, 1,
"Not adding %s (%i) as base " SET_TYPE " set (duplicate, %s)", set->name, set->version,
188 duplicate->valid_files > set->valid_files ?
"less valid files" :
"lower version");
193 while (*prev != duplicate) prev = &(*prev)->next;
196 set->next = duplicate->next;
203 DEBUG(grf, 1,
"Removing %s (%i) as base " SET_TYPE " set (duplicate, %s)", duplicate->name, duplicate->version,
204 duplicate->valid_files < set->valid_files ?
"less valid files" :
"lower version");
211 while (*last != NULL) last = &(*last)->next;
217 DEBUG(grf, 1,
"Adding %s (%i) as base " SET_TYPE " set", set->name, set->version);
233 template <
class Tbase_set>
245 if (strcmp(name, s->name) == 0) {
260 template <
class Tbase_set>
265 p +=
seprintf(p, last,
"%18s: %s", s->name, s->GetDescription());
266 int invalid = s->GetNumInvalid();
268 int missing = s->GetNumMissing();
270 p +=
seprintf(p, last,
" (%i corrupt file%s)\n", invalid, invalid == 1 ?
"" :
"s");
272 p +=
seprintf(p, last,
" (unusable: %i missing file%s)\n", missing, missing == 1 ?
"" :
"s");
283 #if defined(ENABLE_NETWORK)
288 for (; s != NULL; s = s->next) {
289 if (s->GetNumMissing() != 0)
continue;
291 if (s->shortname != ci->
unique_id)
continue;
292 if (!md5sum)
return s->files[0].filename;
295 memset(md5, 0,
sizeof(md5));
296 for (uint i = 0; i < Tbase_set::NUM_FILES; i++) {
297 for (uint j = 0; j <
sizeof(md5); j++) {
298 md5[j] ^= s->files[i].hash[j];
301 if (memcmp(md5, ci->
md5sum,
sizeof(md5)) == 0)
return s->files[0].filename;
306 template <
class Tbase_set>
315 template <
class Tbase_set>
321 template <
class Tbase_set>
333 template <
class Tbase_set>
348 template <
class Tbase_set>
354 if (s->GetNumMissing() != 0)
continue;
364 template <
class Tbase_set>
369 if (index == 0)
return s;
372 error(
"Base" SET_TYPE "::GetSet(): index %d out of range", index);
379 template <
class Tbase_set>
389 template <
class Tbase_set>
400 #define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type) \
401 template const char *repl_type::ini_set; \
402 template const char *repl_type::GetExtension(); \
403 template bool repl_type::AddFile(const char *filename, size_t pathlength, const char *tar_filename); \
404 template bool repl_type::HasSet(const struct ContentInfo *ci, bool md5sum); \
405 template bool repl_type::SetSet(const char *name); \
406 template char *repl_type::GetSetsList(char *p, const char *last); \
407 template int repl_type::GetNumSets(); \
408 template int repl_type::GetIndexOfUsedSet(); \
409 template const set_type *repl_type::GetSet(int index); \
410 template const set_type *repl_type::GetUsedSet(); \
411 template bool repl_type::DetermineBestSet(); \
412 template set_type *repl_type::GetAvailableSets(); \
413 template const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const set_type *s);