mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 16:18:48 -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 */
|
case 'J': /* --metalink */
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBMETALINK
|
#ifdef HAVE_LIBMETALINK
|
||||||
metalink_error_t r;
|
if(parse_metalink(config, nextarg) == -1) {
|
||||||
metalink_t* metalink;
|
warnf(config, "Could not parse Metalink file: %s\n", nextarg);
|
||||||
metalink_file_t **files;
|
/* TODO Is PARAM_BAD_USE appropriate here? */
|
||||||
struct metalink *ml;
|
return PARAM_BAD_USE;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
warnf(config, "--metalink option is ignored because the binary is "
|
warnf(config, "--metalink option is ignored because the binary is "
|
||||||
|
@ -21,9 +21,23 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "tool_setup.h"
|
#include "tool_setup.h"
|
||||||
#include "tool_metalink.h"
|
#include "tool_metalink.h"
|
||||||
|
#include "tool_getparam.h"
|
||||||
|
#include "tool_paramhlp.h"
|
||||||
|
|
||||||
#include "memdebug.h" /* keep this as LAST include */
|
#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 *new_metalinkfile(metalink_file_t *metalinkfile) {
|
||||||
struct metalinkfile *f;
|
struct metalinkfile *f;
|
||||||
f = (struct metalinkfile*)malloc(sizeof(struct metalinkfile));
|
f = (struct metalinkfile*)malloc(sizeof(struct metalinkfile));
|
||||||
@ -64,3 +78,67 @@ void clean_metalink(struct Configurable *config)
|
|||||||
}
|
}
|
||||||
config->metalink_last = 0;
|
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);
|
void clean_metalink(struct Configurable *config);
|
||||||
|
|
||||||
|
int parse_metalink(struct Configurable *config, const char *infile);
|
||||||
|
|
||||||
#endif /* HEADER_CURL_TOOL_METALINK_H */
|
#endif /* HEADER_CURL_TOOL_METALINK_H */
|
||||||
|
@ -130,7 +130,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
struct OutStruct heads;
|
struct OutStruct heads;
|
||||||
|
|
||||||
#ifdef HAVE_LIBMETALINK
|
#ifdef HAVE_LIBMETALINK
|
||||||
struct metalinkfile *mlfile_last;
|
struct metalinkfile *mlfile_last = NULL;
|
||||||
#endif /* HAVE_LIBMETALINK */
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
|
||||||
CURL *curl = NULL;
|
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.
|
** Nested loops start here.
|
||||||
*/
|
*/
|
||||||
@ -409,16 +405,23 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
char *outfiles;
|
char *outfiles;
|
||||||
int infilenum;
|
int infilenum;
|
||||||
URLGlob *inglob;
|
URLGlob *inglob;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
int metalink; /* nonzero for metalink download */
|
int metalink; /* nonzero for metalink download */
|
||||||
struct metalinkfile *mlfile;
|
struct metalinkfile *mlfile;
|
||||||
metalink_resource_t **mlres;
|
metalink_resource_t **mlres;
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
|
||||||
outfiles = NULL;
|
outfiles = NULL;
|
||||||
infilenum = 1;
|
infilenum = 1;
|
||||||
inglob = NULL;
|
inglob = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
if(urlnode->flags & GETOUT_METALINK) {
|
if(urlnode->flags & GETOUT_METALINK) {
|
||||||
metalink = 1;
|
metalink = 1;
|
||||||
|
if(mlfile_last == NULL) {
|
||||||
|
mlfile_last = config->metalinkfile_list;
|
||||||
|
}
|
||||||
mlfile = mlfile_last;
|
mlfile = mlfile_last;
|
||||||
mlfile_last = mlfile_last->next;
|
mlfile_last = mlfile_last->next;
|
||||||
mlres = mlfile->file->resources;
|
mlres = mlfile->file->resources;
|
||||||
@ -428,6 +431,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
mlfile = NULL;
|
mlfile = NULL;
|
||||||
mlres = NULL;
|
mlres = NULL;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
|
||||||
/* urlnode->url is the full URL (it might be NULL) */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
if(metalink) {
|
if(metalink) {
|
||||||
/* For Metalink download, we don't use glob. Instead we use
|
/* For Metalink download, we don't use glob. Instead we use
|
||||||
the number of resources as urlnum. */
|
the number of resources as urlnum. */
|
||||||
urlnum = count_next_metalink_resource(mlfile);
|
urlnum = count_next_metalink_resource(mlfile);
|
||||||
}
|
}
|
||||||
else if(!config->globoff) {
|
else
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
if(!config->globoff) {
|
||||||
/* Unless explicitly shut off, we expand '{...}' and '[...]'
|
/* Unless explicitly shut off, we expand '{...}' and '[...]'
|
||||||
expressions and return total number of URLs in pattern set */
|
expressions and return total number of URLs in pattern set */
|
||||||
res = glob_url(&urls, urlnode->url, &urlnum,
|
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;
|
long retry_sleep;
|
||||||
char *this_url;
|
char *this_url;
|
||||||
HeaderData hdrdata;
|
HeaderData hdrdata;
|
||||||
int metalink_next_res;
|
#ifdef HAVE_LIBMETALINK
|
||||||
|
int metalink_next_res = 0;
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
|
||||||
outfile = NULL;
|
outfile = NULL;
|
||||||
infdopen = FALSE;
|
infdopen = FALSE;
|
||||||
infd = STDIN_FILENO;
|
infd = STDIN_FILENO;
|
||||||
uploadfilesize = -1; /* -1 means unknown */
|
uploadfilesize = -1; /* -1 means unknown */
|
||||||
metalink_next_res = 0;
|
|
||||||
|
|
||||||
/* default output stream is stdout */
|
/* default output stream is stdout */
|
||||||
memset(&outs, 0, sizeof(struct OutStruct));
|
memset(&outs, 0, sizeof(struct OutStruct));
|
||||||
outs.stream = stdout;
|
outs.stream = stdout;
|
||||||
outs.config = config;
|
outs.config = config;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
if(metalink) {
|
if(metalink) {
|
||||||
|
/* For Metalink download, use name in Metalink file as
|
||||||
|
filename. */
|
||||||
outfile = strdup(mlfile->file->name);
|
outfile = strdup(mlfile->file->name);
|
||||||
if(!outfile) {
|
if(!outfile) {
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
res = CURLE_OUT_OF_MEMORY;
|
||||||
@ -559,6 +570,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
if(urls) {
|
if(urls) {
|
||||||
res = glob_next_url(&this_url, urls);
|
res = glob_next_url(&this_url, urls);
|
||||||
if(res)
|
if(res)
|
||||||
@ -583,7 +595,9 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
goto show_error;
|
goto show_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
|
||||||
if((urlnode->flags&GETOUT_USEREMOTE) ||
|
if((urlnode->flags&GETOUT_USEREMOTE) ||
|
||||||
(outfile && !curlx_strequal("-", outfile)) ) {
|
(outfile && !curlx_strequal("-", outfile)) ) {
|
||||||
@ -1429,6 +1443,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
continue; /* curl_easy_perform loop */
|
continue; /* curl_easy_perform loop */
|
||||||
}
|
}
|
||||||
} /* if retry_numretries */
|
} /* if retry_numretries */
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
else if(metalink) {
|
else if(metalink) {
|
||||||
/* Metalink: Decide to try the next resource or
|
/* Metalink: Decide to try the next resource or
|
||||||
not. Basically, we want to try the next resource if
|
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
|
else
|
||||||
metalink_next_res = 1;
|
metalink_next_res = 1;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
|
||||||
/* In all ordinary cases, just break out of loop here */
|
/* In all ordinary cases, just break out of loop here */
|
||||||
break; /* curl_easy_perform loop */
|
break; /* curl_easy_perform loop */
|
||||||
@ -1562,10 +1578,21 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
|
|
||||||
#ifdef HAVE_LIBMETALINK
|
#ifdef HAVE_LIBMETALINK
|
||||||
if(!metalink && res == CURLE_OK && outs.filename) {
|
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;
|
char *content_type;
|
||||||
curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
|
curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
|
||||||
if(content_type != NULL) {
|
if(content_type &&
|
||||||
printf("file=%s, content-type=%s\n", outs.filename, 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 */
|
#endif /* HAVE_LIBMETALINK */
|
||||||
@ -1586,14 +1613,18 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
infd = STDIN_FILENO;
|
infd = STDIN_FILENO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBMETALINK
|
||||||
if(metalink) {
|
if(metalink) {
|
||||||
|
/* Should exit if error is fatal. */
|
||||||
if(is_fatal_error(res)) {
|
if(is_fatal_error(res)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!metalink_next_res || *(++mlres) == NULL)
|
if(!metalink_next_res || *(++mlres) == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(urlnum > 1) {
|
else
|
||||||
|
#endif /* HAVE_LIBMETALINK */
|
||||||
|
if(urlnum > 1) {
|
||||||
/* when url globbing, exit loop upon critical error */
|
/* when url globbing, exit loop upon critical error */
|
||||||
if(is_fatal_error(res))
|
if(is_fatal_error(res))
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user