Commit b5fdbe84 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa Committed by Daniel Stenberg
Browse files

Support Metalink.

This change adds experimental Metalink support to curl.
To enable Metalink support, run configure with --with-libmetalink.
To feed Metalink file to curl, use --metalink option like this:

  $ curl -O --metalink foo.metalink

We use libmetalink to parse Metalink files.
parent efb8471a
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ curl_verbose_msg="enabled (--disable-verbose)"
   curl_rtsp_msg="no      (--enable-rtsp)"
   curl_rtmp_msg="no      (--with-librtmp)"
    init_ssl_msg=${curl_ssl_msg}
curl_metalink_msg="no      (--with-libmetalink)"

dnl
dnl Save anything in $LIBS for later
@@ -2216,6 +2217,63 @@ dnl **********************************************************************

CURL_CHECK_CA_BUNDLE

dnl **********************************************************************
dnl Check for libmetalink
dnl **********************************************************************

OPT_LIBMETALINK=no

AC_ARG_WITH(libmetalink,dnl
AC_HELP_STRING([--with-libmetalink=PATH],[where to look for libmetalink, PATH points to the installation root])
AC_HELP_STRING([--without-libmetalink], [disable libmetalink detection]),
  OPT_LIBMETALINK=$withval)

if test X"$OPT_LIBMETALINK" != Xno; then

  addlib=""
  addld=""
  addcflags=""
  version=""
  libmetalinklib=""
  PKGTEST="no"
  if test "x$OPT_LIBMETALINK" = "xyes"; then
    dnl this is with no partiular path given
    PKGTEST="yes"
    CURL_CHECK_PKGCONFIG(libmetalink)
  else
    dnl When particular path is given, set PKG_CONFIG_LIBDIR using the path.
    LIBMETALINK_PCDIR="$OPT_LIBMETALINK/lib/pkgconfig"
    AC_MSG_NOTICE([PKG_CONFIG_LIBDIR will be set to "$LIBMETALINK_PCDIR"])
    if test -f "$LIBMETALINK_PCDIR/libmetalink.pc"; then
      PKGTEST="yes"
    fi
    if test "$PKGTEST" = "yes"; then
      CURL_CHECK_PKGCONFIG(libmetalink, [$LIBMETALINK_PCDIR])
    fi
  fi
  if test "$PKGTEST" = "yes" && test "$PKGCONFIG" != "no"; then
    addlib=`$PKGCONFIG --libs-only-l libmetalink`
    addld=`$PKGCONFIG --libs-only-L libmetalink`
    addcflags=`$PKGCONFIG --cflags-only-I libmetalink`
    version=`$PKGCONFIG --modversion libmetalink`
    libmetalinklib=`echo $addld | $SED -e 's/-L//'`
  fi
  if test -n "$addlib"; then

    AC_MSG_NOTICE([detected libmetalink version $version])
    curl_metalink_msg="enabled"
    LIBMETALINK_LIBS=$addlib
    LIBMETALINK_LDFLAGS=$addld
    LIBMETALINK_CFLAGS=$addcflags
    AC_SUBST([LIBMETALINK_LIBS])
    AC_SUBST([LIBMETALINK_LDFLAGS])
    AC_SUBST([LIBMETALINK_CFLAGS])
    AC_DEFINE(HAVE_LIBMETALINK, 1, [if libmetalink is available])

  fi
fi
AM_CONDITIONAL([HAVE_LIBMETALINK], [test -n "x$LIBMETALINK_LIBS"])

dnl **********************************************************************
dnl Check for the presence of LIBSSH2 libraries and headers
dnl **********************************************************************
@@ -3319,6 +3377,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
  LDAPS support:    ${curl_ldaps_msg}
  RTSP support:     ${curl_rtsp_msg}
  RTMP support:     ${curl_rtmp_msg}
  metalink support: ${curl_metalink_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
])

+1 −0
Original line number Diff line number Diff line
curl_SOURCES += tool_metalink.c tool_metalink.h
+6 −2
Original line number Diff line number Diff line
@@ -50,11 +50,15 @@ AM_CPPFLAGS = -DCURL_STATICLIB
endif

include Makefile.inc
if HAVE_LIBMETALINK
include Makefile-metalink.inc
endif # HAVE_LIBMETALINK

# This might hold -Werror
CFLAGS += @CURL_CFLAG_EXTRAS@
CFLAGS += @CURL_CFLAG_EXTRAS@ @LIBMETALINK_CFLAGS@

curl_LDADD = $(top_builddir)/lib/libcurl.la @CURL_LIBS@
curl_LDADD = $(top_builddir)/lib/libcurl.la @CURL_LIBS@ @LIBMETALINK_LIBS@
curl_LDFLAGS = @LIBMETALINK_LDFLAGS@
curl_DEPENDENCIES = $(top_builddir)/lib/libcurl.la
BUILT_SOURCES = hugehelp.c
CLEANFILES = hugehelp.c
+11 −0
Original line number Diff line number Diff line
@@ -25,6 +25,10 @@

#include "tool_sdecls.h"

#ifdef HAVE_LIBMETALINK
#include "tool_metalink.h"
#endif /* HAVE_LIBMETALINK */

struct Configurable {
  CURL *easy;               /* once we have one, we keep it here */
  bool remote_time;
@@ -198,6 +202,13 @@ struct Configurable {
  bool xattr;               /* store metadata in extended attributes */
  long gssapi_delegation;
  bool ssl_allow_beast;     /* allow this SSL vulnerability */
#ifdef HAVE_LIBMETALINK
  struct metalinkfile *metalinkfile_list; /* point to the first node */
  struct metalinkfile *metalinkfile_last; /* point to the last/current node */

  struct metalink *metalink_list; /* point to the first node */
  struct metalink *metalink_last; /* point to the last/current node */
#endif /* HAVE_LIBMETALINK */
}; /* struct Configurable */

void free_config_fields(struct Configurable *config);
+73 −0
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@
#include "tool_parsecfg.h"
#include "tool_version.h"

#ifdef HAVE_LIBMETALINK
#  include "tool_metalink.h"
#endif /* HAVE_LIBMETALINK */

#include "memdebug.h" /* keep this as LAST include */

#ifdef MSDOS
@@ -170,6 +174,9 @@ static const struct LongShort aliases[]= {
  {"$G", "delegation",               TRUE},
  {"$H", "mail-auth",                TRUE},
  {"$I", "post303",                  FALSE},
#ifdef HAVE_LIBMETALINK
  {"$J", "metalink",                 TRUE},
#endif /* HAVE_LIBMETALINK */
  {"0",  "http1.0",                  FALSE},
  {"1",  "tlsv1",                    FALSE},
  {"2",  "sslv2",                    FALSE},
@@ -819,6 +826,72 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
      case 'H': /* --mail-auth */
        GetStr(&config->mail_auth, nextarg);
        break;
#ifdef HAVE_LIBMETALINK
      case 'J': /* --metalink */
        {
          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;
              }
            }
          }
          break;
        }
#endif /* HAVE_LIBMETALINK */
      }
      break;
    case '#': /* --progress-bar */
Loading