1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
15 #include <fc_config.h>
18 #ifdef HAVE_SYS_TYPES_H
19 #include <sys/types.h>
21 #ifdef HAVE_SYS_SOCKET_H
22 #include <sys/socket.h>
28 #include "capability.h"
38 /**************************************************************************
39 Message callback called by netfile module when downloading files.
40 **************************************************************************/
41 static void nf_cb(const char *msg
, void *data
)
43 dl_msg_callback mcb
= (dl_msg_callback
) data
;
50 /**************************************************************************
51 Download modpack from a given URL
52 **************************************************************************/
53 const char *download_modpack(const char *URL
,
54 const struct fcmp_params
*fcmp
,
59 char local_name
[2048];
61 int filenbr
, total_files
;
62 struct section_file
*control
;
63 const char *control_capstr
;
65 enum modpack_type type
;
71 bool partial_failure
= FALSE
;
73 if (URL
== NULL
|| URL
[0] == '\0') {
74 return _("No URL given");
77 if (strlen(URL
) < strlen(MODPACK_SUFFIX
)
78 || strcmp(URL
+ strlen(URL
) - strlen(MODPACK_SUFFIX
), MODPACK_SUFFIX
)) {
79 return _("This does not look like modpack URL");
82 for (start_idx
= strlen(URL
) - strlen(MODPACK_SUFFIX
);
83 start_idx
> 0 && URL
[start_idx
- 1] != '/';
88 log_normal(_("Installing modpack %s from %s"), URL
+ start_idx
, URL
);
90 if (fcmp
->inst_prefix
== NULL
) {
91 return _("Cannot install to given directory hierarchy");
95 mcb(_("Downloading modpack control file."));
98 control
= netfile_get_section_file(URL
, nf_cb
, mcb
);
100 if (control
== NULL
) {
101 return _("Failed to get and parse modpack control file");
104 control_capstr
= secfile_lookup_str(control
, "info.options");
105 if (control_capstr
== NULL
) {
106 secfile_destroy(control
);
107 return _("Modpack control file has no capability string");
110 if (!has_capabilities(MODPACK_CAPSTR
, control_capstr
)) {
111 log_error("Incompatible control file:");
112 log_error(" control file options: %s", control_capstr
);
113 log_error(" supported options: %s", MODPACK_CAPSTR
);
115 secfile_destroy(control
);
117 return _("Modpack control file is incompatible");
120 mpname
= secfile_lookup_str(control
, "info.name");
121 if (mpname
== NULL
) {
122 return _("Modpack name not defined in control file");
124 mpver
= secfile_lookup_str(control
, "info.version");
126 return _("Modpack version not defined in control file");
129 typestr
= secfile_lookup_str(control
, "info.type");
130 type
= modpack_type_by_name(typestr
, fc_strcasecmp
);
131 if (!modpack_type_is_valid(type
)) {
132 return _("Illegal modpack type");
135 if (type
== MPT_SCENARIO
) {
136 fc_snprintf(local_dir
, sizeof(local_dir
),
137 "%s/scenarios", fcmp
->inst_prefix
);
139 fc_snprintf(local_dir
, sizeof(local_dir
),
140 "%s/" DATASUBDIR
, fcmp
->inst_prefix
);
143 baseURL
= secfile_lookup_str(control
, "info.baseURL");
147 src_name
= secfile_lookup_str_default(control
, NULL
,
148 "files.list%d.src", total_files
);
150 if (src_name
!= NULL
) {
153 } while (src_name
!= NULL
);
156 /* Control file already downloaded */
157 pbcb(1, total_files
+ 1);
161 for (filenbr
= 0; filenbr
< total_files
; filenbr
++) {
162 const char *dest_name
;
164 bool illegal_filename
= FALSE
;
166 src_name
= secfile_lookup_str_default(control
, NULL
,
167 "files.list%d.src", filenbr
);
169 dest_name
= secfile_lookup_str_default(control
, NULL
,
170 "files.list%d.dest", filenbr
);
172 if (dest_name
== NULL
|| dest_name
[0] == '\0') {
173 /* Missing dest name is ok, we just default to src_name */
174 dest_name
= src_name
;
177 for (i
= 0; dest_name
[i
] != '\0'; i
++) {
178 if (dest_name
[i
] == '.' && dest_name
[i
+1] == '.') {
182 fc_snprintf(buf
, sizeof(buf
), _("Illegal path for %s"),
186 partial_failure
= TRUE
;
187 illegal_filename
= TRUE
;
191 if (!illegal_filename
) {
192 fc_snprintf(local_name
, sizeof(local_name
),
193 "%s/%s", local_dir
, dest_name
);
194 for (i
= strlen(local_name
) - 1 ; local_name
[i
] != '/' ; i
--) {
197 local_name
[i
] = '\0';
198 if (!make_dir(local_name
)) {
199 secfile_destroy(control
);
200 return _("Cannot create required directories");
207 fc_snprintf(buf
, sizeof(buf
), _("Downloading %s"), src_name
);
211 fc_snprintf(fileURL
, sizeof(fileURL
), "%s/%s", baseURL
, src_name
);
212 if (!netfile_download_file(fileURL
, local_name
, nf_cb
, mcb
)) {
216 fc_snprintf(buf
, sizeof(buf
), _("Failed to download %s"),
220 partial_failure
= TRUE
;
225 /* Count download of control file also */
226 pbcb(filenbr
+ 2, total_files
+ 1);
230 if (partial_failure
) {
231 secfile_destroy(control
);
233 return _("Some parts of the modpack failed to install.");
236 update_install_info_lists(mpname
, type
, mpver
);
238 secfile_destroy(control
);
243 /**************************************************************************
244 Download modpack list
245 **************************************************************************/
246 const char *download_modpack_list(const struct fcmp_params
*fcmp
,
247 modpack_list_setup_cb cb
,
250 struct section_file
*list_file
;
251 const char *list_capstr
;
256 list_file
= netfile_get_section_file(fcmp
->list_url
, nf_cb
, mcb
);
258 if (list_file
== NULL
) {
259 return _("Cannot fetch and parse modpack list");
262 list_capstr
= secfile_lookup_str(list_file
, "info.options");
263 if (list_capstr
== NULL
) {
264 secfile_destroy(list_file
);
265 return _("Modpack list has no capability string");
268 if (!has_capabilities(MODLIST_CAPSTR
, list_capstr
)) {
269 log_error("Incompatible modpack list file:");
270 log_error(" list file options: %s", list_capstr
);
271 log_error(" supported options: %s", MODLIST_CAPSTR
);
273 secfile_destroy(list_file
);
275 return _("Modpack list is incompatible");
278 msg
= secfile_lookup_str_default(list_file
, NULL
, "info.message");
289 const char *mp_type_str
;
290 const char *mp_subtype
;
291 const char *mp_notes
;
293 mp_name
= secfile_lookup_str_default(list_file
, NULL
,
294 "modpacks.list%d.name", modpack_count
);
295 mpver
= secfile_lookup_str_default(list_file
, NULL
,
296 "modpacks.list%d.version",
298 mplic
= secfile_lookup_str_default(list_file
, NULL
,
299 "modpacks.list%d.license",
301 mp_type_str
= secfile_lookup_str_default(list_file
, NULL
,
302 "modpacks.list%d.type",
304 mp_subtype
= secfile_lookup_str_default(list_file
, NULL
,
305 "modpacks.list%d.subtype",
307 mpURL
= secfile_lookup_str_default(list_file
, NULL
,
308 "modpacks.list%d.URL", modpack_count
);
309 mp_notes
= secfile_lookup_str_default(list_file
, NULL
,
310 "modpacks.list%d.notes", modpack_count
);
312 if (mp_name
!= NULL
&& mpURL
!= NULL
) {
313 enum modpack_type type
= modpack_type_by_name(mp_type_str
, fc_strcasecmp
);
314 if (!modpack_type_is_valid(type
)) {
315 log_error("Illegal modpack type \"%s\"", mp_type_str
? mp_type_str
: "NULL");
320 if (mp_subtype
== NULL
) {
323 cb(mp_name
, mpURL
, mpver
, mplic
, type
, mp_subtype
, mp_notes
);
326 } while (mp_name
!= NULL
);