From 6064f21c66b8494de3c3383e857730a1490e00b2 Mon Sep 17 00:00:00 2001 From: Hubert Tarasiuk Date: Fri, 3 Jul 2015 00:21:35 +0200 Subject: [PATCH] Geolocation support for Metalink resources. * doc/wget.text: Add information about --preferred-location. * src/init.c: Add --preferred-location option. * src/main.c (option_data): Handle --preferred-location argument. (main): Sort resources based on location if requested. * src/metalink.c (metalink_res_cmp): Compare based on location if priority and preference are equal. * src/options.h (options): Add preferred_location option. --- doc/wget.texi | 5 +++++ src/init.c | 4 ++++ src/main.c | 25 +++++++++++++++++++++++++ src/metalink.c | 11 +++++++++++ src/options.h | 1 + 5 files changed, 46 insertions(+) diff --git a/doc/wget.texi b/doc/wget.texi index a9a0f6bc..0b683d8e 100644 --- a/doc/wget.texi +++ b/doc/wget.texi @@ -518,6 +518,11 @@ Issues HTTP HEAD request instead of GET and extracts Metalink metadata from response headers. Then it switches to Metalink download. If no valid Metalink metadata is found, it falls back to ordinary HTTP download. +@cindex preferred-location +@item --preferred-location +Set preferred location for Metalink resources. This has effect if multiple +resources with same priority are available. + @cindex force html @item -F diff --git a/src/init.c b/src/init.c index dbff1b35..ed4171e3 100644 --- a/src/init.c +++ b/src/init.c @@ -245,6 +245,9 @@ static const struct { { "postdata", &opt.post_data, cmd_string }, { "postfile", &opt.post_file_name, cmd_file }, { "preferfamily", NULL, cmd_spec_prefer_family }, +#ifdef HAVE_METALINK + { "preferred-location", &opt.preferred_location, cmd_string }, +#endif { "preservepermissions", &opt.preserve_perm, cmd_boolean }, #ifdef HAVE_SSL { "privatekey", &opt.private_key, cmd_file }, @@ -1801,6 +1804,7 @@ cleanup (void) xfree (opt.input_filename); #ifdef HAVE_METALINK xfree (opt.input_metalink); + xfree (opt.preferred_location); #endif xfree (opt.output_document); free_vec (opt.accepts); diff --git a/src/main.c b/src/main.c index a66f7bc4..79a37b5b 100644 --- a/src/main.c +++ b/src/main.c @@ -274,6 +274,9 @@ static struct cmdline_option option_data[] = { "post-data", 0, OPT_VALUE, "postdata", -1 }, { "post-file", 0, OPT_VALUE, "postfile", -1 }, { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 }, +#ifdef HAVE_METALINK + { "preferred-location", 0, OPT_VALUE, "preferred-location", -1 }, +#endif { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 }, { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 }, { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 }, @@ -595,6 +598,8 @@ Download:\n"), #ifdef HAVE_METALINK N_("\ --metalink-over-http use Metalink metadata from HTTP response headers\n"), + N_("\ + --preferred-location preferred location for Metalink resources\n"), #endif "\n", @@ -1771,6 +1776,26 @@ outputting to a regular file.\n")); } else { + /* We need to sort the resources if preferred location + was specified by the user. */ + if (opt.preferred_location && opt.preferred_location[0]) + { + metalink_file_t **mfile_ptr; + for (mfile_ptr = metalink->files; *mfile_ptr; mfile_ptr++) + { + metalink_resource_t **mres_ptr; + metalink_file_t *mfile = *mfile_ptr; + size_t mres_count = 0; + + for (mres_ptr = mfile->resources; *mres_ptr; mres_ptr++) + mres_count++; + + stable_sort (mfile->resources, + mres_count, + sizeof (metalink_resource_t *), + metalink_res_cmp); + } + } retr_err = retrieve_from_metalink (metalink); if (retr_err != RETROK) { diff --git a/src/metalink.c b/src/metalink.c index b7518643..f5ae1c19 100644 --- a/src/metalink.c +++ b/src/metalink.c @@ -448,6 +448,17 @@ int metalink_res_cmp (const void* v1, const void* v2) return res2->preference - res1->preference; if (res1->priority != res2->priority) return res1->priority - res2->priority; + if (opt.preferred_location) + { + int cmp = 0; + if (res1->location && + !strcasecmp (opt.preferred_location, res1->location)) + cmp -= 1; + if (res2->location && + !strcasecmp (opt.preferred_location, res2->location)) + cmp += 1; + return cmp; + } return 0; } diff --git a/src/options.h b/src/options.h index c377b50f..1ede7b34 100644 --- a/src/options.h +++ b/src/options.h @@ -61,6 +61,7 @@ struct options #ifdef HAVE_METALINK char *input_metalink; /* Input metalink file */ bool metalink_over_http; /* Use Metalink if present in HTTP response */ + char *preferred_location; /* Preferred location for Metalink resources */ #endif char *choose_config; /* Specified config file */ bool noconfig; /* Ignore all config files? */