aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2012-04-28 23:46:32 +0900
committerDaniel Stenberg <daniel@haxx.se>2012-05-26 23:09:37 +0200
commit53f2c02ac75360b53a8eba8d575e5fa55f8b3372 (patch)
tree1f0022915b41e9a87def212cb5465a2b52d3d528 /src
parent1919352a10f7103d32fede9c2b8c427440dea517 (diff)
metalink: parse downloaded Metalink file
Parse downloaded Metalink file and add downloads described there. Fixed compile error without metalink support.
Diffstat (limited to 'src')
-rw-r--r--src/tool_getparam.c63
-rw-r--r--src/tool_metalink.c78
-rw-r--r--src/tool_metalink.h2
-rw-r--r--src/tool_operate.c53
4 files changed, 126 insertions, 70 deletions
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index bdb4b04ae..34f6420e0 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -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 "
diff --git a/src/tool_metalink.c b/src/tool_metalink.c
index a57297b78..4b4c6bcd3 100644
--- a/src/tool_metalink.c
+++ b/src/tool_metalink.c
@@ -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;
+}
diff --git a/src/tool_metalink.h b/src/tool_metalink.h
index e9f8162ab..39e6674d1 100644
--- a/src/tool_metalink.h
+++ b/src/tool_metalink.h
@@ -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 */
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 669d2dd46..4bcc8b40d 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -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;