Imported Upstream version 7.59.0
[platform/upstream/curl.git] / src / tool_metalink.c
index 5873adf..bbbfc2a 100644 (file)
@@ -5,11 +5,11 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
  *
  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  * copies of the Software, and permit persons to whom the Software is
 #ifdef USE_METALINK
 
 #include <sys/stat.h>
+#include <stdlib.h>
 
 #ifdef HAVE_FCNTL_H
 #  include <fcntl.h>
 #endif
 
+#undef HAVE_NSS_CONTEXT
+
 #ifdef USE_OPENSSL
 #  include <openssl/md5.h>
 #  include <openssl/sha.h>
@@ -49,6 +52,7 @@
 #  define MD5_CTX    void *
 #  define SHA_CTX    void *
 #  define SHA256_CTX void *
+#  define HAVE_NSS_CONTEXT
    static NSSInitContext *nss_context;
 #elif defined(USE_POLARSSL)
 #  include <polarssl/md5.h>
@@ -92,8 +96,6 @@ struct win32_crypto_hash {
 #  error "Can't compile METALINK support without a crypto library."
 #endif
 
-#include "rawstr.h"
-
 #define ENABLE_CURLX_PRINTF
 /* use our own printf() functions */
 #include "curlx.h"
@@ -118,7 +120,9 @@ struct win32_crypto_hash {
     return PARAM_NO_MEM; \
 } WHILE_FALSE
 
-#ifdef USE_GNUTLS_NETTLE
+#if defined(USE_OPENSSL)
+/* Functions are already defined */
+#elif defined(USE_GNUTLS_NETTLE)
 
 static int MD5_Init(MD5_CTX *ctx)
 {
@@ -376,7 +380,7 @@ static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
   sha256_finish(ctx, digest);
 }
 
-#elif defined(_WIN32) && !defined(USE_OPENSSL)
+#elif defined(_WIN32)
 
 static void win32_crypto_final(struct win32_crypto_hash *ctx,
                                unsigned char *digest,
@@ -535,6 +539,7 @@ digest_context *Curl_digest_init(const digest_params *dparams)
   ctxt->digest_hash = dparams;
 
   if(dparams->digest_init(ctxt->digest_hashctx) != 1) {
+    free(ctxt->digest_hashctx);
     free(ctxt);
     return NULL;
   }
@@ -553,7 +558,8 @@ int Curl_digest_update(digest_context *context,
 
 int Curl_digest_final(digest_context *context, unsigned char *result)
 {
-  (*context->digest_hash->digest_final)(result, context->digest_hashctx);
+  if(result)
+    (*context->digest_hash->digest_final)(result, context->digest_hashctx);
 
   free(context->digest_hashctx);
   free(context);
@@ -563,18 +569,13 @@ int Curl_digest_final(digest_context *context, unsigned char *result)
 
 static unsigned char hex_to_uint(const char *s)
 {
-  int v[2];
-  int i;
-  for(i = 0; i < 2; ++i) {
-    v[i] = Curl_raw_toupper(s[i]);
-    if('0' <= v[i] && v[i] <= '9') {
-      v[i] -= '0';
-    }
-    else if('A' <= v[i] && v[i] <= 'Z') {
-      v[i] -= 'A'-10;
-    }
-  }
-  return (unsigned char)((v[0] << 4) | v[1]);
+  char buf[3];
+  unsigned long val;
+  buf[0] = s[0];
+  buf[1] = s[1];
+  buf[2] = 0;
+  val = strtoul(buf, NULL, 16);
+  return (unsigned char)(val&0xff);
 }
 
 /*
@@ -623,6 +624,7 @@ static int check_hash(const char *filename,
   result = malloc(digest_def->dparams->digest_resultlen);
   if(!result) {
     close(fd);
+    Curl_digest_final(dctx, NULL);
     return -1;
   }
   while(1) {
@@ -684,13 +686,15 @@ static metalink_checksum *new_metalink_checksum_from_hex_digest
     return 0;
 
   for(i = 0; i < len; i += 2) {
-    digest[i/2] = hex_to_uint(hex_digest+i);
+    digest[i/2] = hex_to_uint(hex_digest + i);
   }
   chksum = malloc(sizeof(metalink_checksum));
   if(chksum) {
     chksum->digest_def = digest_def;
     chksum->digest = digest;
   }
+  else
+    free(digest);
   return chksum;
 }
 
@@ -747,7 +751,7 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
         ++digest_alias) {
       metalink_checksum_t **p;
       for(p = fileinfo->checksums; *p; ++p) {
-        if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) &&
+        if(curl_strequal(digest_alias->alias_name, (*p)->type) &&
            check_hex_digest((*p)->hash, digest_alias->digest_def)) {
           f->checksum =
             new_metalink_checksum_from_hex_digest(digest_alias->digest_def,
@@ -777,13 +781,29 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
          metainfo file URL may be appeared in fileinfo->metaurls.
       */
       if((*p)->type == NULL ||
-         Curl_raw_equal((*p)->type, "http") ||
-         Curl_raw_equal((*p)->type, "https") ||
-         Curl_raw_equal((*p)->type, "ftp") ||
-         Curl_raw_equal((*p)->type, "ftps")) {
+         curl_strequal((*p)->type, "http") ||
+         curl_strequal((*p)->type, "https") ||
+         curl_strequal((*p)->type, "ftp") ||
+         curl_strequal((*p)->type, "ftps")) {
         res = new_metalink_resource((*p)->url);
-        tail->next = res;
-        tail = res;
+        if(res) {
+          tail->next = res;
+          tail = res;
+        }
+        else {
+          tail = root.next;
+
+          /* clean up the linked list */
+          while(tail) {
+            res = tail->next;
+            free(tail->url);
+            free(tail);
+            tail = res;
+          }
+          free(f->filename);
+          free(f);
+          return NULL;
+        }
       }
     }
     f->resource = root.next;
@@ -818,7 +838,7 @@ int parse_metalink(struct OperationConfig *config, struct OutStruct *outs,
     if(!(*files)->resources) {
       fprintf(config->global->errors, "Metalink: parsing (%s) WARNING "
               "(missing or invalid resource)\n",
-              metalink_url, (*files)->name);
+              metalink_url);
       continue;
     }
     if(config->url_get ||
@@ -881,12 +901,12 @@ size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb,
    * it does not match then it fails with CURLE_WRITE_ERROR. So at this
    * point returning a value different from sz*nmemb indicates failure.
    */
-  const size_t failure = (sz * nmemb) ? 0 : 1;
+  const size_t failure = (sz && nmemb) ? 0 : 1;
 
   if(!config)
     return failure;
 
-  rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb);
+  rv = metalink_parse_update(outs->metalink_parser, buffer, sz * nmemb);
   if(rv == 0)
     return sz * nmemb;
   else {
@@ -906,9 +926,9 @@ static int check_content_type(const char *content_type, const char *media_type)
   if(!*ptr) {
     return 0;
   }
-  return Curl_raw_nequal(ptr, media_type, media_type_len) &&
-    (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
-     *(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';');
+  return curl_strnequal(ptr, media_type, media_type_len) &&
+    (*(ptr + media_type_len) == '\0' || *(ptr + media_type_len) == ' ' ||
+     *(ptr + media_type_len) == '\t' || *(ptr + media_type_len) == ';');
 }
 
 int check_metalink_content_type(const char *content_type)
@@ -971,7 +991,7 @@ void clean_metalink(struct OperationConfig *config)
 
 void metalink_cleanup(void)
 {
-#ifdef USE_NSS
+#ifdef HAVE_NSS_CONTEXT
   if(nss_context) {
     NSS_ShutdownContext(nss_context);
     nss_context = NULL;