1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24#include "tool_setup.h" 25#include "tool_xattr.h" 26 27#include "memdebug.h" /* keep this as LAST include */ 28 29#ifdef USE_XATTR 30 31/* mapping table of curl metadata to extended attribute names */ 32static const struct xattr_mapping { 33 const char *attr; /* name of the xattr */ 34 CURLINFO info; 35} mappings[] = { 36 /* mappings proposed by 37 * https://freedesktop.org/wiki/CommonExtendedAttributes/ 38 */ 39 { "user.xdg.referrer.url", CURLINFO_REFERER }, 40 { "user.mime_type", CURLINFO_CONTENT_TYPE }, 41 { NULL, CURLINFO_NONE } /* last element, abort here */ 42}; 43 44/* returns a new URL that needs to be freed */ 45/* @unittest: 1621 */ 46#ifdef UNITTESTS 47char *stripcredentials(const char *url); 48#else 49static 50#endif 51char *stripcredentials(const char *url) 52{ 53 CURLU *u; 54 CURLUcode uc; 55 char *nurl; 56 u = curl_url(); 57 if(u) { 58 uc = curl_url_set(u, CURLUPART_URL, url, 0); 59 if(uc) 60 goto error; 61 62 uc = curl_url_set(u, CURLUPART_USER, NULL, 0); 63 if(uc) 64 goto error; 65 66 uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0); 67 if(uc) 68 goto error; 69 70 uc = curl_url_get(u, CURLUPART_URL, &nurl, 0); 71 if(uc) 72 goto error; 73 74 curl_url_cleanup(u); 75 76 return nurl; 77 } 78error: 79 curl_url_cleanup(u); 80 return NULL; 81} 82 83static int xattr(int fd, 84 const char *attr, /* name of the xattr */ 85 const char *value) 86{ 87 int err = 0; 88 if(value) { 89#ifdef DEBUGBUILD 90 (void)fd; 91 if(getenv("CURL_FAKE_XATTR")) { 92 printf("%s => %s\n", attr, value); 93 } 94 return 0; 95#else 96#ifdef HAVE_FSETXATTR_6 97 err = fsetxattr(fd, attr, value, strlen(value), 0, 0); 98#elif defined(HAVE_FSETXATTR_5) 99 err = fsetxattr(fd, attr, value, strlen(value), 0); 100#elif defined(__FreeBSD_version) || defined(__MidnightBSD_version) 101 { 102 ssize_t rc = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, 103 attr, value, strlen(value)); 104 /* FreeBSD's extattr_set_fd returns the length of the extended 105 attribute */ 106 err = (rc < 0 ? -1 : 0); 107 } 108#endif 109#endif 110 } 111 return err; 112} 113/* store metadata from the curl request alongside the downloaded 114 * file using extended attributes 115 */ 116int fwrite_xattr(CURL *curl, const char *url, int fd) 117{ 118 int i = 0; 119 int err = 0; 120 121 /* loop through all xattr-curlinfo pairs and abort on a set error */ 122 while(!err && mappings[i].attr) { 123 char *value = NULL; 124 CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value); 125 if(!result && value) 126 err = xattr(fd, mappings[i].attr, value); 127 i++; 128 } 129 if(!err) { 130 char *nurl = stripcredentials(url); 131 if(!nurl) 132 return 1; 133 err = xattr(fd, "user.xdg.origin.url", nurl); 134 curl_free(nurl); 135 } 136 return err; 137} 138#endif 139