From 67297ae805d42af60fbcce4f804353259e3d8015 Mon Sep 17 00:00:00 2001
From: Jure Grabnar
Date: Mon, 31 Mar 2014 21:37:54 +0200
Subject: [PATCH 1/2] Fix metalink issues when type is not present
---
src/ChangeLog | 14 ++++++++++++++
src/metalink.c | 23 ++++++++++++++++-------
src/metalink.h | 4 +++-
src/retr.c | 10 ++++++++++
src/url.c | 22 ++++++++++++++++++++++
src/url.h | 1 +
6 files changed, 66 insertions(+), 8 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 537a707..74d061e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,17 @@
+2014-03-31 Jure Grabnar
+
+ * metalink.h: Change type of 'mlink_resource.type' to enum url_scheme.
+ Include url.h.
+ * metalink.c (parse_metalink): Find out resources' protocol type from URL if
+ not present in tag in metalink file.
+ Include url.h.
+ (elect_resources): Do not crash when protocol type is NULL.
+ Count number of resources still available, if zero, assign NULL.
+ * url.c:
+ (url_scheme_str_to_enum): New function: extracts protocol type from string
+ without "://" suffix.
+ * retr.c: Add check for number of resources available. Do not crash when zero.
+
2014-03-26 Darshit Shah
* ftp.c (getftp): Rearrange parameters to fix compiler warning
diff --git a/src/metalink.c b/src/metalink.c
index 76db2fa..4ff565d 100644
--- a/src/metalink.c
+++ b/src/metalink.c
@@ -42,6 +42,7 @@ as that of the covered work. */
#include "sha256.h"
#include "metalink.h"
#include "utils.h"
+#include "url.h"
#define HASH_TYPES 3
@@ -119,7 +120,7 @@ parse_metalink(char *input_file)
file->chunk_checksum = NULL;
file->num_of_res = file->num_of_checksums = 0;
- for (resources = (*files)->resources; *resources; ++resources)
+ for (resources = (*files)->resources; resources && *resources; ++resources)
{
mlink_resource *resource;
@@ -134,7 +135,12 @@ parse_metalink(char *input_file)
++(file->num_of_res);
resource->url = xstrdup ((*resources)->url);
- resource->type = ((*resources)->type ? xstrdup ((*resources)->type) : NULL);
+
+ if ((*resources)->type)
+ resource->type = url_scheme_str_to_enum ((*resources)->type);
+ else
+ resource->type = url_scheme (resource->url);
+
resource->location = ((*resources)->location ? xstrdup ((*resources)->location) : NULL);
resource->preference = (*resources)->preference;
resource->maxconnections = (*resources)->maxconnections;
@@ -143,7 +149,7 @@ parse_metalink(char *input_file)
(file->resources) = resource;
}
- for (checksums = (*files)->checksums; *checksums; ++checksums)
+ for (checksums = (*files)->checksums; checksums && *checksums; ++checksums)
{
mlink_checksum *checksum = malloc (sizeof(mlink_checksum));
@@ -215,19 +221,23 @@ elect_resources (mlink *mlink)
while (res_next = res->next)
{
- if (strcmp(res_next->type, "ftp") && strcmp(res_next->type, "http"))
+ if (schemes_are_similar_p (res_next->type, SCHEME_INVALID))
{
res->next = res_next->next;
free(res_next);
+
+ --(file->num_of_res);
}
else
res = res_next;
}
res = file->resources;
- if (strcmp(res->type, "ftp") && strcmp(res->type, "http"))
+ if (schemes_are_similar_p (res->type, SCHEME_INVALID))
{
file->resources = res->next;
- free(res);
+ free (res);
+
+ --(file->num_of_res);
}
}
}
@@ -301,7 +311,6 @@ delete_mlink(mlink *metalink)
while (res)
{
xfree_null (res->url);
- xfree_null (res->type);
xfree_null (res->location);
res_temp = res;
diff --git a/src/metalink.h b/src/metalink.h
index 3906e22..264320c 100644
--- a/src/metalink.h
+++ b/src/metalink.h
@@ -32,6 +32,8 @@ as that of the covered work. */
#ifndef MLINK_H
#define MLINK_H
+#include "url.h"
+
typedef struct metalink_piece_hash
{
struct metalink_piece_hash *next;
@@ -53,7 +55,7 @@ typedef struct metalink_resource
struct metalink_resource *next;
char *url;
- char *type;
+ enum url_scheme type;
char *location;
int preference;
int maxconnections;
diff --git a/src/retr.c b/src/retr.c
index 8c361de..d89fc83 100644
--- a/src/retr.c
+++ b/src/retr.c
@@ -1095,6 +1095,16 @@ retrieve_from_file (const char *file, bool html, int *count)
file = mlink->files;
while (file)
{
+ if (!file->num_of_res)
+ {
+ logprintf (LOG_VERBOSE, _("Downloading %s failed. File could "
+ "not be downloaded from any of the "
+ "URLs listed in metalink file.\n"),
+ file->name);
+ file = file->next;
+ continue;
+ }
+
memset (thread_ctx, '\0', opt.jobs * (sizeof *thread_ctx));
/* If chunk_size is too small, set it equal to MIN_CHUNK_SIZE. */
diff --git a/src/url.c b/src/url.c
index a237fcf..95babfd 100644
--- a/src/url.c
+++ b/src/url.c
@@ -440,6 +440,28 @@ url_scheme (const char *url)
return SCHEME_INVALID;
}
+/* Returns the scheme type from string
+ if the scheme is supported, or
+ SCHEME_INVALID if not. */
+
+enum url_scheme
+url_scheme_str_to_enum (const char *str)
+{
+ int i;
+
+ for (i = 0; supported_schemes[i].name; i++)
+ if (0 == strncasecmp (str, supported_schemes[i].name,
+ strlen (supported_schemes[i].name)))
+ {
+ if (!(supported_schemes[i].flags & scm_disabled))
+ return (enum url_scheme) i;
+ else
+ return SCHEME_INVALID;
+ }
+
+ return SCHEME_INVALID;
+}
+
#define SCHEME_CHAR(ch) (c_isalnum (ch) || (ch) == '-' || (ch) == '+')
/* Return 1 if the URL begins with any "scheme", 0 otherwise. As
diff --git a/src/url.h b/src/url.h
index 6d18ed8..cb26ef4 100644
--- a/src/url.h
+++ b/src/url.h
@@ -111,6 +111,7 @@ void url_set_file (struct url *, const char *);
void url_free (struct url *);
enum url_scheme url_scheme (const char *);
+enum url_scheme url_scheme_str_to_enum (const char *str);
bool url_has_scheme (const char *);
bool url_valid_scheme (const char *);
int scheme_default_port (enum url_scheme);
--
1.9.0