mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
metalink: parse downloaded Metalink file
Parse downloaded Metalink file and add downloads described there. Fixed compile error without metalink support.
This commit is contained in:
parent
1919352a10
commit
53f2c02ac7
@ -829,65 +829,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'J': /* --metalink */
|
||||
{
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
metalink_error_t r;
|
||||
metalink_t* metalink;
|
||||
metalink_file_t **files;
|
||||
struct metalink *ml;
|
||||
|
||||
r = metalink_parse_file(nextarg, &metalink);
|
||||
|
||||
if(r != 0) {
|
||||
fprintf(stderr, "ERROR: code=%d\n", r);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ml = new_metalink(metalink);
|
||||
|
||||
if(config->metalink_list) {
|
||||
config->metalink_last->next = ml;
|
||||
config->metalink_last = ml;
|
||||
}
|
||||
else {
|
||||
config->metalink_list = config->metalink_last = ml;
|
||||
}
|
||||
|
||||
for(files = metalink->files; *files; ++files) {
|
||||
struct getout *url;
|
||||
/* Skip an entry which has no resource. */
|
||||
if(!(*files)->resources[0]) continue;
|
||||
if(config->url_get ||
|
||||
((config->url_get = config->url_list) != NULL)) {
|
||||
/* there's a node here, if it already is filled-in continue to
|
||||
find an "empty" node */
|
||||
while(config->url_get && (config->url_get->flags & GETOUT_URL))
|
||||
config->url_get = config->url_get->next;
|
||||
}
|
||||
|
||||
/* now there might or might not be an available node to fill in! */
|
||||
|
||||
if(config->url_get)
|
||||
/* existing node */
|
||||
url = config->url_get;
|
||||
else
|
||||
/* there was no free node, create one! */
|
||||
url=new_getout(config);
|
||||
|
||||
if(url) {
|
||||
struct metalinkfile *mlfile;
|
||||
/* Set name as url */
|
||||
GetStr(&url->url, (*files)->name);
|
||||
|
||||
/* set flag metalink here */
|
||||
url->flags |= GETOUT_URL | GETOUT_METALINK;
|
||||
mlfile = new_metalinkfile(*files);
|
||||
|
||||
if(config->metalinkfile_list) {
|
||||
config->metalinkfile_last->next = mlfile;
|
||||
config->metalinkfile_last = mlfile;
|
||||
}
|
||||
else {
|
||||
config->metalinkfile_list = config->metalinkfile_last = mlfile;
|
||||
}
|
||||
}
|
||||
if(parse_metalink(config, nextarg) == -1) {
|
||||
warnf(config, "Could not parse Metalink file: %s\n", nextarg);
|
||||
/* TODO Is PARAM_BAD_USE appropriate here? */
|
||||
return PARAM_BAD_USE;
|
||||
}
|
||||
#else
|
||||
warnf(config, "--metalink option is ignored because the binary is "
|
||||
|
@ -21,9 +21,23 @@
|
||||
***************************************************************************/
|
||||
#include "tool_setup.h"
|
||||
#include "tool_metalink.h"
|
||||
#include "tool_getparam.h"
|
||||
#include "tool_paramhlp.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
/* Copied from tool_getparam.c */
|
||||
#define GetStr(str,val) do { \
|
||||
if(*(str)) { \
|
||||
free(*(str)); \
|
||||
*(str) = NULL; \
|
||||
} \
|
||||
if((val)) \
|
||||
*(str) = strdup((val)); \
|
||||
if(!(val)) \
|
||||
return PARAM_NO_MEM; \
|
||||
} WHILE_FALSE
|
||||
|
||||
struct metalinkfile *new_metalinkfile(metalink_file_t *metalinkfile) {
|
||||
struct metalinkfile *f;
|
||||
f = (struct metalinkfile*)malloc(sizeof(struct metalinkfile));
|
||||
@ -64,3 +78,67 @@ void clean_metalink(struct Configurable *config)
|
||||
}
|
||||
config->metalink_last = 0;
|
||||
}
|
||||
|
||||
int parse_metalink(struct Configurable *config, const char *infile)
|
||||
{
|
||||
metalink_error_t r;
|
||||
metalink_t* metalink;
|
||||
metalink_file_t **files;
|
||||
struct metalink *ml;
|
||||
|
||||
r = metalink_parse_file(infile, &metalink);
|
||||
|
||||
if(r != 0) {
|
||||
return -1;
|
||||
}
|
||||
ml = new_metalink(metalink);
|
||||
|
||||
if(config->metalink_list) {
|
||||
config->metalink_last->next = ml;
|
||||
config->metalink_last = ml;
|
||||
}
|
||||
else {
|
||||
config->metalink_list = config->metalink_last = ml;
|
||||
}
|
||||
|
||||
for(files = metalink->files; *files; ++files) {
|
||||
struct getout *url;
|
||||
/* Skip an entry which has no resource. */
|
||||
if(!(*files)->resources[0]) continue;
|
||||
if(config->url_get ||
|
||||
((config->url_get = config->url_list) != NULL)) {
|
||||
/* there's a node here, if it already is filled-in continue to
|
||||
find an "empty" node */
|
||||
while(config->url_get && (config->url_get->flags & GETOUT_URL))
|
||||
config->url_get = config->url_get->next;
|
||||
}
|
||||
|
||||
/* now there might or might not be an available node to fill in! */
|
||||
|
||||
if(config->url_get)
|
||||
/* existing node */
|
||||
url = config->url_get;
|
||||
else
|
||||
/* there was no free node, create one! */
|
||||
url=new_getout(config);
|
||||
|
||||
if(url) {
|
||||
struct metalinkfile *mlfile;
|
||||
/* Set name as url */
|
||||
GetStr(&url->url, (*files)->name);
|
||||
|
||||
/* set flag metalink here */
|
||||
url->flags |= GETOUT_URL | GETOUT_METALINK;
|
||||
mlfile = new_metalinkfile(*files);
|
||||
|
||||
if(config->metalinkfile_list) {
|
||||
config->metalinkfile_last->next = mlfile;
|
||||
config->metalinkfile_last = mlfile;
|
||||
}
|
||||
else {
|
||||
config->metalinkfile_list = config->metalinkfile_last = mlfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -48,4 +48,6 @@ int count_next_metalink_resource(struct metalinkfile *mlfile);
|
||||
|
||||
void clean_metalink(struct Configurable *config);
|
||||
|
||||
int parse_metalink(struct Configurable *config, const char *infile);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_METALINK_H */
|
||||
|
@ -130,7 +130,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
struct OutStruct heads;
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
struct metalinkfile *mlfile_last;
|
||||
struct metalinkfile *mlfile_last = NULL;
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
CURL *curl = NULL;
|
||||
@ -392,10 +392,6 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
mlfile_last = config->metalinkfile_list;
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
/*
|
||||
** Nested loops start here.
|
||||
*/
|
||||
@ -409,16 +405,23 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
char *outfiles;
|
||||
int infilenum;
|
||||
URLGlob *inglob;
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
int metalink; /* nonzero for metalink download */
|
||||
struct metalinkfile *mlfile;
|
||||
metalink_resource_t **mlres;
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
outfiles = NULL;
|
||||
infilenum = 1;
|
||||
inglob = NULL;
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
if(urlnode->flags & GETOUT_METALINK) {
|
||||
metalink = 1;
|
||||
if(mlfile_last == NULL) {
|
||||
mlfile_last = config->metalinkfile_list;
|
||||
}
|
||||
mlfile = mlfile_last;
|
||||
mlfile_last = mlfile_last->next;
|
||||
mlres = mlfile->file->resources;
|
||||
@ -428,6 +431,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
mlfile = NULL;
|
||||
mlres = NULL;
|
||||
}
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
/* urlnode->url is the full URL (it might be NULL) */
|
||||
|
||||
@ -497,12 +501,15 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
if(metalink) {
|
||||
/* For Metalink download, we don't use glob. Instead we use
|
||||
the number of resources as urlnum. */
|
||||
urlnum = count_next_metalink_resource(mlfile);
|
||||
}
|
||||
else if(!config->globoff) {
|
||||
else
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
if(!config->globoff) {
|
||||
/* Unless explicitly shut off, we expand '{...}' and '[...]'
|
||||
expressions and return total number of URLs in pattern set */
|
||||
res = glob_url(&urls, urlnode->url, &urlnum,
|
||||
@ -533,20 +540,24 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
long retry_sleep;
|
||||
char *this_url;
|
||||
HeaderData hdrdata;
|
||||
int metalink_next_res;
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
int metalink_next_res = 0;
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
outfile = NULL;
|
||||
infdopen = FALSE;
|
||||
infd = STDIN_FILENO;
|
||||
uploadfilesize = -1; /* -1 means unknown */
|
||||
metalink_next_res = 0;
|
||||
|
||||
/* default output stream is stdout */
|
||||
memset(&outs, 0, sizeof(struct OutStruct));
|
||||
outs.stream = stdout;
|
||||
outs.config = config;
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
if(metalink) {
|
||||
/* For Metalink download, use name in Metalink file as
|
||||
filename. */
|
||||
outfile = strdup(mlfile->file->name);
|
||||
if(!outfile) {
|
||||
res = CURLE_OUT_OF_MEMORY;
|
||||
@ -559,6 +570,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
if(urls) {
|
||||
res = glob_next_url(&this_url, urls);
|
||||
if(res)
|
||||
@ -583,7 +595,9 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
goto show_error;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
}
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
if((urlnode->flags&GETOUT_USEREMOTE) ||
|
||||
(outfile && !curlx_strequal("-", outfile)) ) {
|
||||
@ -1429,6 +1443,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
continue; /* curl_easy_perform loop */
|
||||
}
|
||||
} /* if retry_numretries */
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
else if(metalink) {
|
||||
/* Metalink: Decide to try the next resource or
|
||||
not. Basically, we want to try the next resource if
|
||||
@ -1451,6 +1466,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
else
|
||||
metalink_next_res = 1;
|
||||
}
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
|
||||
/* In all ordinary cases, just break out of loop here */
|
||||
break; /* curl_easy_perform loop */
|
||||
@ -1562,10 +1578,21 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
if(!metalink && res == CURLE_OK && outs.filename) {
|
||||
/* Check the content-type header field and if it indicates
|
||||
Metalink file, parse it and add getout for them. */
|
||||
char *content_type;
|
||||
curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
|
||||
if(content_type != NULL) {
|
||||
printf("file=%s, content-type=%s\n", outs.filename, content_type);
|
||||
if(content_type &&
|
||||
Curl_raw_equal("application/metalink+xml", content_type)) {
|
||||
if(!(config->mute)) {
|
||||
fprintf(config->errors, "\nParsing Metalink file: %s\n",
|
||||
outs.filename);
|
||||
}
|
||||
if(parse_metalink(config, outs.filename) == 0)
|
||||
fprintf(config->errors,
|
||||
"Metalink file is parsed successfully\n");
|
||||
else
|
||||
fprintf(config->errors, "Could not parse Metalink file.\n");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
@ -1586,14 +1613,18 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
infd = STDIN_FILENO;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBMETALINK
|
||||
if(metalink) {
|
||||
/* Should exit if error is fatal. */
|
||||
if(is_fatal_error(res)) {
|
||||
break;
|
||||
}
|
||||
if(!metalink_next_res || *(++mlres) == NULL)
|
||||
break;
|
||||
}
|
||||
else if(urlnum > 1) {
|
||||
else
|
||||
#endif /* HAVE_LIBMETALINK */
|
||||
if(urlnum > 1) {
|
||||
/* when url globbing, exit loop upon critical error */
|
||||
if(is_fatal_error(res))
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user