diff options
Diffstat (limited to 'external/libcurl_android/jni/libcurl/src/tool_metalink.c')
-rwxr-xr-x | external/libcurl_android/jni/libcurl/src/tool_metalink.c | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/external/libcurl_android/jni/libcurl/src/tool_metalink.c b/external/libcurl_android/jni/libcurl/src/tool_metalink.c deleted file mode 100755 index 3573b058..00000000 --- a/external/libcurl_android/jni/libcurl/src/tool_metalink.c +++ /dev/null @@ -1,963 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2014, 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. - * - * 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 - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#include "tool_setup.h" - -#ifdef USE_METALINK - -#include <sys/stat.h> - -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif - -#ifdef USE_SSLEAY -# ifdef USE_OPENSSL -# include <openssl/md5.h> -# include <openssl/sha.h> -# else -# include <md5.h> -# include <sha.h> -# endif -#elif defined(USE_GNUTLS_NETTLE) -# include <nettle/md5.h> -# include <nettle/sha.h> -# define MD5_CTX struct md5_ctx -# define SHA_CTX struct sha1_ctx -# define SHA256_CTX struct sha256_ctx -#elif defined(USE_GNUTLS) -# include <gcrypt.h> -# define MD5_CTX gcry_md_hd_t -# define SHA_CTX gcry_md_hd_t -# define SHA256_CTX gcry_md_hd_t -#elif defined(USE_NSS) -# include <nss.h> -# include <pk11pub.h> -# define MD5_CTX void * -# define SHA_CTX void * -# define SHA256_CTX void * - static NSSInitContext *nss_context; -#elif defined(USE_POLARSSL) -# include <polarssl/md5.h> -# include <polarssl/sha1.h> -# include <polarssl/sha256.h> -# define MD5_CTX md5_context -# define SHA_CTX sha1_context -# define SHA256_CTX sha256_context -#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ - (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ - (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ - (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) -/* For Apple operating systems: CommonCrypto has the functions we need. - The library's headers are even backward-compatible with OpenSSL's - headers as long as we define COMMON_DIGEST_FOR_OPENSSL first. - - These functions are available on Tiger and later, as well as iOS 2.0 - and later. If you're building for an older cat, well, sorry. */ -# define COMMON_DIGEST_FOR_OPENSSL -# include <CommonCrypto/CommonDigest.h> -#elif defined(_WIN32) -/* For Windows: If no other crypto library is provided, we fallback - to the hash functions provided within the Microsoft Windows CryptoAPI */ -# include <wincrypt.h> -/* Custom structure in order to store the required provider and hash handle */ -struct win32_crypto_hash { - HCRYPTPROV hCryptProv; - HCRYPTHASH hHash; -}; -/* Custom Microsoft AES Cryptographic Provider defines required for MinGW */ -# ifndef ALG_SID_SHA_256 -# define ALG_SID_SHA_256 12 -# endif -# ifndef CALG_SHA_256 -# define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) -# endif -# define MD5_CTX struct win32_crypto_hash -# define SHA_CTX struct win32_crypto_hash -# define SHA256_CTX struct win32_crypto_hash -#else -# 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" - -#include "tool_getparam.h" -#include "tool_paramhlp.h" -#include "tool_cfgable.h" -#include "tool_metalink.h" -#include "tool_msgs.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 - -#ifdef USE_GNUTLS_NETTLE - -static int MD5_Init(MD5_CTX *ctx) -{ - md5_init(ctx); - return 1; -} - -static void MD5_Update(MD5_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - md5_update(ctx, inputLen, input); -} - -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) -{ - md5_digest(ctx, 16, digest); -} - -static int SHA1_Init(SHA_CTX *ctx) -{ - sha1_init(ctx); - return 1; -} - -static void SHA1_Update(SHA_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - sha1_update(ctx, inputLen, input); -} - -static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) -{ - sha1_digest(ctx, 20, digest); -} - -static int SHA256_Init(SHA256_CTX *ctx) -{ - sha256_init(ctx); - return 1; -} - -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - sha256_update(ctx, inputLen, input); -} - -static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) -{ - sha256_digest(ctx, 32, digest); -} - -#elif defined(USE_GNUTLS) - -static int MD5_Init(MD5_CTX *ctx) -{ - gcry_md_open(ctx, GCRY_MD_MD5, 0); - return 1; -} - -static void MD5_Update(MD5_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - gcry_md_write(*ctx, input, inputLen); -} - -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) -{ - memcpy(digest, gcry_md_read(*ctx, 0), 16); - gcry_md_close(*ctx); -} - -static int SHA1_Init(SHA_CTX *ctx) -{ - gcry_md_open(ctx, GCRY_MD_SHA1, 0); - return 1; -} - -static void SHA1_Update(SHA_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - gcry_md_write(*ctx, input, inputLen); -} - -static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) -{ - memcpy(digest, gcry_md_read(*ctx, 0), 20); - gcry_md_close(*ctx); -} - -static int SHA256_Init(SHA256_CTX *ctx) -{ - gcry_md_open(ctx, GCRY_MD_SHA256, 0); - return 1; -} - -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - gcry_md_write(*ctx, input, inputLen); -} - -static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) -{ - memcpy(digest, gcry_md_read(*ctx, 0), 32); - gcry_md_close(*ctx); -} - -#elif defined(USE_NSS) - -static int nss_hash_init(void **pctx, SECOidTag hash_alg) -{ - PK11Context *ctx; - - /* we have to initialize NSS if not initialized alraedy */ - if(!NSS_IsInitialized() && !nss_context) { - static NSSInitParameters params; - params.length = sizeof params; - nss_context = NSS_InitContext("", "", "", "", ¶ms, NSS_INIT_READONLY - | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN - | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); - } - - ctx = PK11_CreateDigestContext(hash_alg); - if(!ctx) - return /* failure */ 0; - - if(PK11_DigestBegin(ctx) != SECSuccess) { - PK11_DestroyContext(ctx, PR_TRUE); - return /* failure */ 0; - } - - *pctx = ctx; - return /* success */ 1; -} - -static void nss_hash_final(void **pctx, unsigned char *out, unsigned int len) -{ - PK11Context *ctx = *pctx; - unsigned int outlen; - PK11_DigestFinal(ctx, out, &outlen, len); - PK11_DestroyContext(ctx, PR_TRUE); -} - -static int MD5_Init(MD5_CTX *pctx) -{ - return nss_hash_init(pctx, SEC_OID_MD5); -} - -static void MD5_Update(MD5_CTX *pctx, - const unsigned char *input, - unsigned int input_len) -{ - PK11_DigestOp(*pctx, input, input_len); -} - -static void MD5_Final(unsigned char digest[16], MD5_CTX *pctx) -{ - nss_hash_final(pctx, digest, 16); -} - -static int SHA1_Init(SHA_CTX *pctx) -{ - return nss_hash_init(pctx, SEC_OID_SHA1); -} - -static void SHA1_Update(SHA_CTX *pctx, - const unsigned char *input, - unsigned int input_len) -{ - PK11_DigestOp(*pctx, input, input_len); -} - -static void SHA1_Final(unsigned char digest[20], SHA_CTX *pctx) -{ - nss_hash_final(pctx, digest, 20); -} - -static int SHA256_Init(SHA256_CTX *pctx) -{ - return nss_hash_init(pctx, SEC_OID_SHA256); -} - -static void SHA256_Update(SHA256_CTX *pctx, - const unsigned char *input, - unsigned int input_len) -{ - PK11_DigestOp(*pctx, input, input_len); -} - -static void SHA256_Final(unsigned char digest[32], SHA256_CTX *pctx) -{ - nss_hash_final(pctx, digest, 32); -} - -#elif defined(USE_POLARSSL) - -static int MD5_Init(MD5_CTX *ctx) -{ - md5_starts(ctx); - return 1; -} - -static void MD5_Update(MD5_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - md5_update(ctx, input, inputLen); -} - -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) -{ - md5_finish(ctx, digest); -} - -static int SHA1_Init(SHA_CTX *ctx) -{ - sha1_starts(ctx); - return 1; -} - -static void SHA1_Update(SHA_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - sha1_update(ctx, input, inputLen); -} - -static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) -{ - sha1_finish(ctx, digest); -} - -static int SHA256_Init(SHA256_CTX *ctx) -{ - sha256_starts(ctx, 0); /* 0 = sha256 */ - return 1; -} - -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - sha256_update(ctx, input, inputLen); -} - -static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) -{ - sha256_finish(ctx, digest); -} - -#elif defined(_WIN32) && !defined(USE_SSLEAY) - -static void win32_crypto_final(struct win32_crypto_hash *ctx, - unsigned char *digest, - unsigned int digestLen) -{ - unsigned long length; - CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0); - if(length == digestLen) - CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0); - if(ctx->hHash) - CryptDestroyHash(ctx->hHash); - if(ctx->hCryptProv) - CryptReleaseContext(ctx->hCryptProv, 0); -} - -static int MD5_Init(MD5_CTX *ctx) -{ - if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash); - } - return 1; -} - -static void MD5_Update(MD5_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); -} - -static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) -{ - win32_crypto_final(ctx, digest, 16); -} - -static int SHA1_Init(SHA_CTX *ctx) -{ - if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - CryptCreateHash(ctx->hCryptProv, CALG_SHA1, 0, 0, &ctx->hHash); - } - return 1; -} - -static void SHA1_Update(SHA_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); -} - -static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) -{ - win32_crypto_final(ctx, digest, 20); -} - -static int SHA256_Init(SHA256_CTX *ctx) -{ - if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, - PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { - CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash); - } - return 1; -} - -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); -} - -static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) -{ - win32_crypto_final(ctx, digest, 32); -} - -#endif /* CRYPTO LIBS */ - -const digest_params MD5_DIGEST_PARAMS[] = { - { - (Curl_digest_init_func) MD5_Init, - (Curl_digest_update_func) MD5_Update, - (Curl_digest_final_func) MD5_Final, - sizeof(MD5_CTX), - 16 - } -}; - -const digest_params SHA1_DIGEST_PARAMS[] = { - { - (Curl_digest_init_func) SHA1_Init, - (Curl_digest_update_func) SHA1_Update, - (Curl_digest_final_func) SHA1_Final, - sizeof(SHA_CTX), - 20 - } -}; - -const digest_params SHA256_DIGEST_PARAMS[] = { - { - (Curl_digest_init_func) SHA256_Init, - (Curl_digest_update_func) SHA256_Update, - (Curl_digest_final_func) SHA256_Final, - sizeof(SHA256_CTX), - 32 - } -}; - -static const metalink_digest_def SHA256_DIGEST_DEF[] = { - {"sha-256", SHA256_DIGEST_PARAMS} -}; - -static const metalink_digest_def SHA1_DIGEST_DEF[] = { - {"sha-1", SHA1_DIGEST_PARAMS} -}; - -static const metalink_digest_def MD5_DIGEST_DEF[] = { - {"md5", MD5_DIGEST_PARAMS} -}; - -/* - * The alias of supported hash functions in the order by preference - * (basically stronger hash comes first). We included "sha-256" and - * "sha256". The former is the name defined in the IANA registry named - * "Hash Function Textual Names". The latter is widely (and - * historically) used in Metalink version 3. - */ -static const metalink_digest_alias digest_aliases[] = { - {"sha-256", SHA256_DIGEST_DEF}, - {"sha256", SHA256_DIGEST_DEF}, - {"sha-1", SHA1_DIGEST_DEF}, - {"sha1", SHA1_DIGEST_DEF}, - {"md5", MD5_DIGEST_DEF}, - {NULL, NULL} -}; - -digest_context *Curl_digest_init(const digest_params *dparams) -{ - digest_context *ctxt; - - /* Create digest context */ - ctxt = malloc(sizeof *ctxt); - - if(!ctxt) - return ctxt; - - ctxt->digest_hashctx = malloc(dparams->digest_ctxtsize); - - if(!ctxt->digest_hashctx) { - free(ctxt); - return NULL; - } - - ctxt->digest_hash = dparams; - - if(dparams->digest_init(ctxt->digest_hashctx) != 1) { - free(ctxt); - return NULL; - } - - return ctxt; -} - -int Curl_digest_update(digest_context *context, - const unsigned char *data, - unsigned int len) -{ - (*context->digest_hash->digest_update)(context->digest_hashctx, data, len); - - return 0; -} - -int Curl_digest_final(digest_context *context, unsigned char *result) -{ - (*context->digest_hash->digest_final)(result, context->digest_hashctx); - - free(context->digest_hashctx); - free(context); - - return 0; -} - -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]); -} - -/* - * Check checksum of file denoted by filename. The expected hash value - * is given in hex_hash which is hex-encoded string. - * - * This function returns 1 if it succeeds or one of the following - * integers: - * - * 0: - * Checksum didn't match. - * -1: - * Could not open file; or could not read data from file. - * -2: - * Hash algorithm not available. - */ -static int check_hash(const char *filename, - const metalink_digest_def *digest_def, - const unsigned char *digest, FILE *error) -{ - unsigned char *result; - digest_context *dctx; - int check_ok, flags, fd; - - flags = O_RDONLY; -#ifdef O_BINARY - /* O_BINARY is required in order to avoid binary EOF in text mode */ - flags |= O_BINARY; -#endif - - fd = open(filename, flags); - if(fd == -1) { - fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename, - digest_def->hash_name, strerror(errno)); - return -1; - } - - dctx = Curl_digest_init(digest_def->dparams); - if(!dctx) { - fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename, - digest_def->hash_name, "failed to initialize hash algorithm"); - close(fd); - return -2; - } - - result = malloc(digest_def->dparams->digest_resultlen); - while(1) { - unsigned char buf[4096]; - ssize_t len = read(fd, buf, sizeof(buf)); - if(len == 0) { - break; - } - else if(len == -1) { - fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename, - digest_def->hash_name, strerror(errno)); - Curl_digest_final(dctx, result); - close(fd); - return -1; - } - Curl_digest_update(dctx, buf, (unsigned int)len); - } - Curl_digest_final(dctx, result); - check_ok = memcmp(result, digest, - digest_def->dparams->digest_resultlen) == 0; - /* sha*sum style verdict output */ - if(check_ok) - fprintf(error, "Metalink: validating (%s) [%s] OK\n", filename, - digest_def->hash_name); - else - fprintf(error, "Metalink: validating (%s) [%s] FAILED (digest mismatch)\n", - filename, digest_def->hash_name); - - free(result); - close(fd); - return check_ok; -} - -int metalink_check_hash(struct GlobalConfig *config, - metalinkfile *mlfile, - const char *filename) -{ - int rv; - fprintf(config->errors, "Metalink: validating (%s)...\n", filename); - if(mlfile->checksum == NULL) { - fprintf(config->errors, - "Metalink: validating (%s) FAILED (digest missing)\n", filename); - return -2; - } - rv = check_hash(filename, mlfile->checksum->digest_def, - mlfile->checksum->digest, config->errors); - return rv; -} - -static metalink_checksum *new_metalink_checksum_from_hex_digest -(const metalink_digest_def *digest_def, const char *hex_digest) -{ - metalink_checksum *chksum; - unsigned char *digest; - size_t i; - size_t len = strlen(hex_digest); - digest = malloc(len/2); - for(i = 0; i < len; i += 2) { - digest[i/2] = hex_to_uint(hex_digest+i); - } - chksum = malloc(sizeof(metalink_checksum)); - chksum->digest_def = digest_def; - chksum->digest = digest; - return chksum; -} - -static metalink_resource *new_metalink_resource(const char *url) -{ - metalink_resource *res; - res = malloc(sizeof(metalink_resource)); - res->next = NULL; - res->url = strdup(url); - return res; -} - -/* Returns nonzero if hex_digest is properly formatted; that is each - letter is in [0-9A-Za-z] and the length of the string equals to the - result length of digest * 2. */ -static int check_hex_digest(const char *hex_digest, - const metalink_digest_def *digest_def) -{ - size_t i; - for(i = 0; hex_digest[i]; ++i) { - char c = hex_digest[i]; - if(!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z'))) { - return 0; - } - } - return digest_def->dparams->digest_resultlen * 2 == i; -} - -static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo) -{ - metalinkfile *f; - f = (metalinkfile*)malloc(sizeof(metalinkfile)); - f->next = NULL; - f->filename = strdup(fileinfo->name); - f->checksum = NULL; - f->resource = NULL; - if(fileinfo->checksums) { - const metalink_digest_alias *digest_alias; - for(digest_alias = digest_aliases; digest_alias->alias_name; - ++digest_alias) { - metalink_checksum_t **p; - for(p = fileinfo->checksums; *p; ++p) { - if(Curl_raw_equal(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, - (*p)->hash); - break; - } - } - if(f->checksum) { - break; - } - } - } - if(fileinfo->resources) { - metalink_resource_t **p; - metalink_resource root, *tail; - root.next = NULL; - tail = &root; - for(p = fileinfo->resources; *p; ++p) { - metalink_resource *res; - /* Filter by type if it is non-NULL. In Metalink v3, type - includes the type of the resource. In curl, we are only - interested in HTTP, HTTPS and FTP. In addition to them, - Metalink v3 file may contain bittorrent type URL, which - points to the BitTorrent metainfo file. We ignore it here. - In Metalink v4, type was deprecated and all - fileinfo->resources point to the target file. BitTorrent - 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")) { - res = new_metalink_resource((*p)->url); - tail->next = res; - tail = res; - } - } - f->resource = root.next; - } - return f; -} - -int parse_metalink(struct OperationConfig *config, struct OutStruct *outs, - const char *metalink_url) -{ - metalink_error_t r; - metalink_t* metalink; - metalink_file_t **files; - bool warnings = FALSE; - - /* metlaink_parse_final deletes outs->metalink_parser */ - r = metalink_parse_final(outs->metalink_parser, NULL, 0, &metalink); - outs->metalink_parser = NULL; - if(r != 0) { - return -1; - } - if(metalink->files == NULL) { - fprintf(config->global->errors, "Metalink: parsing (%s) WARNING " - "(missing or invalid file name)\n", - metalink_url); - metalink_delete(metalink); - return -1; - } - for(files = metalink->files; *files; ++files) { - struct getout *url; - /* Skip an entry which has no resource. */ - if(!(*files)->resources) { - fprintf(config->global->errors, "Metalink: parsing (%s) WARNING " - "(missing or invalid resource)\n", - metalink_url, (*files)->name); - 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) { - metalinkfile *mlfile; - mlfile = new_metalinkfile(*files); - if(!mlfile->checksum) { - warnings = TRUE; - fprintf(config->global->errors, - "Metalink: parsing (%s) WARNING (digest missing)\n", - metalink_url); - } - /* Set name as url */ - GetStr(&url->url, mlfile->filename); - - /* set flag metalink here */ - url->flags |= GETOUT_URL | GETOUT_METALINK; - - if(config->metalinkfile_list) { - config->metalinkfile_last->next = mlfile; - config->metalinkfile_last = mlfile; - } - else { - config->metalinkfile_list = config->metalinkfile_last = mlfile; - } - } - } - metalink_delete(metalink); - return (warnings) ? -2 : 0; -} - -size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb, - void *userdata) -{ - struct OutStruct *outs = userdata; - struct OperationConfig *config = outs->config; - int rv; - - /* - * Once that libcurl has called back tool_write_cb() the returned value - * is checked against the amount that was intended to be written, if - * 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; - - if(!config) - return failure; - - rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb); - if(rv == 0) - return sz * nmemb; - else { - fprintf(config->global->errors, "Metalink: parsing FAILED\n"); - return failure; - } -} - -/* - * Returns nonzero if content_type includes mediatype. - */ -static int check_content_type(const char *content_type, const char *media_type) -{ - const char *ptr = content_type; - size_t media_type_len = strlen(media_type); - for(; *ptr && (*ptr == ' ' || *ptr == '\t'); ++ptr); - 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) == ';'); -} - -int check_metalink_content_type(const char *content_type) -{ - return check_content_type(content_type, "application/metalink+xml"); -} - -int count_next_metalink_resource(metalinkfile *mlfile) -{ - int count = 0; - metalink_resource *res; - for(res = mlfile->resource; res; res = res->next, ++count); - return count; -} - -static void delete_metalink_checksum(metalink_checksum *chksum) -{ - if(chksum == NULL) { - return; - } - Curl_safefree(chksum->digest); - Curl_safefree(chksum); -} - -static void delete_metalink_resource(metalink_resource *res) -{ - if(res == NULL) { - return; - } - Curl_safefree(res->url); - Curl_safefree(res); -} - -static void delete_metalinkfile(metalinkfile *mlfile) -{ - metalink_resource *res; - if(mlfile == NULL) { - return; - } - Curl_safefree(mlfile->filename); - delete_metalink_checksum(mlfile->checksum); - for(res = mlfile->resource; res;) { - metalink_resource *next; - next = res->next; - delete_metalink_resource(res); - res = next; - } - Curl_safefree(mlfile); -} - -void clean_metalink(struct OperationConfig *config) -{ - while(config->metalinkfile_list) { - metalinkfile *mlfile = config->metalinkfile_list; - config->metalinkfile_list = config->metalinkfile_list->next; - delete_metalinkfile(mlfile); - } - config->metalinkfile_last = 0; -} - -void metalink_cleanup(void) -{ -#ifdef USE_NSS - if(nss_context) { - NSS_ShutdownContext(nss_context); - nss_context = NULL; - } -#endif -} - -#endif /* USE_METALINK */ |