20#ifdef FREECIV_HAVE_SYS_TYPES_H
23#ifdef HAVE_SYS_SOCKET_H
24#include <sys/socket.h>
54static void nf_cb(
const char *msg,
void *data)
84 char local_name[2048];
86 int filenbr, total_files;
88 const char *control_capstr;
89 const char *baseURLpart;
90 enum modpack_type
type;
97 bool partial_failure =
FALSE;
103 return _(
"Recursive dependencies too deep");
106 if (URL == NULL || URL[0] ==
'\0') {
107 return _(
"No URL given");
113 return _(
"This does not look like modpack URL");
117 start_idx > 0 && URL[start_idx - 1] !=
'/';
122 if (start_idx <= 0) {
123 return _(
"This does not look like modpack URL");
126 log_normal(
_(
"Installing modpack %s from %s"), URL + start_idx, URL);
129 return _(
"Cannot install to given directory hierarchy");
136 fc_snprintf(buf,
sizeof(buf),
_(
"Downloading \"%s\" control file."), URL + start_idx);
142 if (control == NULL) {
143 return _(
"Failed to get and parse modpack control file");
147 if (control_capstr == NULL) {
149 return _(
"Modpack control file has no capability string");
154 log_error(
" control file options: %s", control_capstr);
159 return _(
"Modpack control file is incompatible");
163 if (mpname == NULL) {
164 return _(
"Modpack name not defined in control file");
168 return _(
"Modpack version not defined in control file");
173 if (!modpack_type_is_valid(
type)) {
174 return _(
"Illegal modpack type");
177 if (
type == MPT_SCENARIO) {
187 if (baseURLpart[0] ==
'.') {
188 char URLstart[start_idx];
190 strncpy(URLstart, URL, start_idx - 1);
191 URLstart[start_idx - 1] =
'\0';
193 URLstart, baseURLpart + 1);
199 URL_len = strlen(baseURL);
200 if (baseURL[URL_len - 1] ==
'/') {
201 baseURL[URL_len - 1] =
'\0';
207 "dependencies.list%d.modpack", dep);
208 if (dep_name != NULL) {
210 const char *inst_ver;
211 const char *dep_typestr;
212 enum modpack_type dep_type;
216 "dependencies.list%d.URL", dep);
218 if (dep_URL == NULL) {
219 return _(
"Dependency has no download URL");
224 if (!modpack_type_is_valid(dep_type)) {
225 return _(
"Illegal dependency modpack type");
230 if (inst_ver != NULL) {
234 "dependencies.list%d.version", dep);
236 if (dep_ver != NULL && cvercmp_max(dep_ver, inst_ver)) {
243 char dep_URL_full[2048];
245 log_debug(
"Dependency modpack \"%s\" needed.", dep_name);
248 mcb(
_(
"Download dependency modpack"));
251 if (dep_URL[0] ==
'.') {
252 char URLstart[start_idx];
254 strncpy(URLstart, URL, start_idx - 1);
255 URLstart[start_idx - 1] =
'\0';
256 fc_snprintf(dep_URL_full,
sizeof(dep_URL_full),
"%s%s",
257 URLstart, dep_URL + 1);
272 }
while (dep_name != NULL);
278 "files.list%d.src", total_files);
280 if (src_name != NULL) {
283 }
while (src_name != NULL);
287 pbcb(1, total_files + 1);
290 for (filenbr = 0; filenbr < total_files; filenbr++) {
291 const char *dest_name;
293#ifndef DIR_SEPARATOR_IS_DEFAULT
294 char *dest_name_copy;
296#define dest_name_copy dest_name
300 bool illegal_filename =
FALSE;
303 "files.list%d.src", filenbr);
306 "files.list%d.dest", filenbr);
308 if (dest_name == NULL || dest_name[0] ==
'\0') {
310 dest_name = src_name;
313#ifndef DIR_SEPARATOR_IS_DEFAULT
314 dest_name_copy =
fc_malloc(strlen(dest_name) + 1);
317 for (i = 0; dest_name[i] !=
'\0'; i++) {
318 if (dest_name[i] ==
'.' && dest_name[i + 1] ==
'.') {
326 partial_failure =
TRUE;
327 illegal_filename =
TRUE;
330#ifndef DIR_SEPARATOR_IS_DEFAULT
331 if (dest_name[i] ==
'/') {
334 dest_name_copy[i] = dest_name[i];
339#ifndef DIR_SEPARATOR_IS_DEFAULT
340 dest_name_copy[i] =
'\0';
343 if (!illegal_filename) {
347#ifndef DIR_SEPARATOR_IS_DEFAULT
348 free(dest_name_copy);
353 return _(
"Cannot create required directories");
359 fc_snprintf(buf,
sizeof(buf),
_(
"Downloading %s"), src_name);
363 fc_snprintf(fileURL,
sizeof(fileURL),
"%s/%s", baseURL, src_name);
364 log_debug(
"Download \"%s\" as \"%s\".", fileURL, local_name);
369 fc_snprintf(buf,
sizeof(buf),
_(
"Failed to download %s"),
373 partial_failure =
TRUE;
376#ifndef DIR_SEPARATOR_IS_DEFAULT
377 free(dest_name_copy);
383 pbcb(filenbr + 2, total_files + 1);
387 if (partial_failure) {
390 return _(
"Some parts of the modpack failed to install.");
408 const char *list_capstr;
416 if (list_file == NULL) {
417 return _(
"Cannot fetch and parse modpack list");
426 if (start_idx <= 0) {
427 return _(
"Invalid modpack list URL");
431 if (list_capstr == NULL) {
433 return _(
"Modpack list has no capability string");
437 log_error(
"Incompatible modpack list file:");
438 log_error(
" list file options: %s", list_capstr);
443 return _(
"Modpack list is incompatible");
457 const char *mp_type_str;
458 const char *mp_subtype;
459 const char *mp_notes;
462 "modpacks.list%d.name", modpack_count);
464 "modpacks.list%d.version",
467 "modpacks.list%d.license",
470 "modpacks.list%d.type",
473 "modpacks.list%d.subtype",
476 "modpacks.list%d.URL", modpack_count);
478 "modpacks.list%d.notes", modpack_count);
480 if (mp_name != NULL && mpURL != NULL) {
481 char mpURL_full[2048];
484 if (!modpack_type_is_valid(
type)) {
485 log_error(
"Illegal modpack type \"%s\"", mp_type_str ? mp_type_str :
"NULL");
490 if (mp_subtype == NULL) {
494 if (mpURL[0] ==
'.') {
495 char URLstart[start_idx];
498 URLstart[start_idx - 1] =
'\0';
499 fc_snprintf(mpURL_full,
sizeof(mpURL_full),
"%s%s",
500 URLstart, mpURL + 1);
505 cb(mp_name, mpURL_full, mpver, mplic,
type,
_(mp_subtype), mp_notes);
508 }
while (mp_name != NULL);
bool has_capabilities(const char *us, const char *them)
static const char * download_modpack_recursive(const char *URL, const struct fcmp_params *fcmp, dl_msg_callback mcb, dl_pb_callback pbcb, int recursion)
const char * download_modpack(const char *URL, const struct fcmp_params *fcmp, dl_msg_callback mcb, dl_pb_callback pbcb)
static void nf_cb(const char *msg, void *data)
const char * download_modpack_list(const struct fcmp_params *fcmp, modpack_list_setup_cb cb, dl_msg_callback mcb)
void(* modpack_list_setup_cb)(const char *name, const char *URL, const char *version, const char *license, enum modpack_type type, const char *subtype, const char *notes)
void(* dl_msg_callback)(const char *msg)
void(* dl_pb_callback)(int downloaded, int max)
#define log_debug(message,...)
#define log_normal(message,...)
#define log_error(message,...)
const char * mpdb_installed_version(const char *name, enum modpack_type type)
bool mpdb_update_modpack(const char *name, enum modpack_type type, const char *version)
struct section_file * netfile_get_section_file(const char *URL, nf_errmsg cb, void *data)
bool netfile_download_file(const char *URL, const char *filename, nf_errmsg cb, void *data)
void secfile_destroy(struct section_file *secfile)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool make_dir_for_file(char *filename)
#define DIR_SEPARATOR_CHAR
static int recursion[AIT_LAST]
int fc_snprintf(char *str, size_t n, const char *format,...)
int fc_strcasecmp(const char *str0, const char *str1)
#define sz_strlcpy(dest, src)