113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci
2713498266Sopenharmony_ci#ifdef USE_NGHTTP2
2813498266Sopenharmony_ci#include <nghttp2/nghttp2.h>
2913498266Sopenharmony_ci#endif
3013498266Sopenharmony_ci
3113498266Sopenharmony_ci#include <curl/curl.h>
3213498266Sopenharmony_ci#include "urldata.h"
3313498266Sopenharmony_ci#include "vtls/vtls.h"
3413498266Sopenharmony_ci#include "http2.h"
3513498266Sopenharmony_ci#include "vssh/ssh.h"
3613498266Sopenharmony_ci#include "vquic/vquic.h"
3713498266Sopenharmony_ci#include "curl_printf.h"
3813498266Sopenharmony_ci#include "easy_lock.h"
3913498266Sopenharmony_ci
4013498266Sopenharmony_ci#ifdef USE_ARES
4113498266Sopenharmony_ci#  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) &&   \
4213498266Sopenharmony_ci  defined(_WIN32)
4313498266Sopenharmony_ci#    define CARES_STATICLIB
4413498266Sopenharmony_ci#  endif
4513498266Sopenharmony_ci#  include <ares.h>
4613498266Sopenharmony_ci#endif
4713498266Sopenharmony_ci
4813498266Sopenharmony_ci#ifdef USE_LIBIDN2
4913498266Sopenharmony_ci#include <idn2.h>
5013498266Sopenharmony_ci#endif
5113498266Sopenharmony_ci
5213498266Sopenharmony_ci#ifdef USE_LIBPSL
5313498266Sopenharmony_ci#include <libpsl.h>
5413498266Sopenharmony_ci#endif
5513498266Sopenharmony_ci
5613498266Sopenharmony_ci#ifdef USE_LIBRTMP
5713498266Sopenharmony_ci#include <librtmp/rtmp.h>
5813498266Sopenharmony_ci#endif
5913498266Sopenharmony_ci
6013498266Sopenharmony_ci#ifdef HAVE_LIBZ
6113498266Sopenharmony_ci#include <zlib.h>
6213498266Sopenharmony_ci#endif
6313498266Sopenharmony_ci
6413498266Sopenharmony_ci#ifdef HAVE_BROTLI
6513498266Sopenharmony_ci#if defined(__GNUC__)
6613498266Sopenharmony_ci/* Ignore -Wvla warnings in brotli headers */
6713498266Sopenharmony_ci#pragma GCC diagnostic push
6813498266Sopenharmony_ci#pragma GCC diagnostic ignored "-Wvla"
6913498266Sopenharmony_ci#endif
7013498266Sopenharmony_ci#include <brotli/decode.h>
7113498266Sopenharmony_ci#if defined(__GNUC__)
7213498266Sopenharmony_ci#pragma GCC diagnostic pop
7313498266Sopenharmony_ci#endif
7413498266Sopenharmony_ci#endif
7513498266Sopenharmony_ci
7613498266Sopenharmony_ci#ifdef HAVE_ZSTD
7713498266Sopenharmony_ci#include <zstd.h>
7813498266Sopenharmony_ci#endif
7913498266Sopenharmony_ci
8013498266Sopenharmony_ci#ifdef USE_GSASL
8113498266Sopenharmony_ci#include <gsasl.h>
8213498266Sopenharmony_ci#endif
8313498266Sopenharmony_ci
8413498266Sopenharmony_ci#ifdef USE_OPENLDAP
8513498266Sopenharmony_ci#include <ldap.h>
8613498266Sopenharmony_ci#endif
8713498266Sopenharmony_ci
8813498266Sopenharmony_ci#ifdef HAVE_BROTLI
8913498266Sopenharmony_cistatic void brotli_version(char *buf, size_t bufsz)
9013498266Sopenharmony_ci{
9113498266Sopenharmony_ci  uint32_t brotli_version = BrotliDecoderVersion();
9213498266Sopenharmony_ci  unsigned int major = brotli_version >> 24;
9313498266Sopenharmony_ci  unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
9413498266Sopenharmony_ci  unsigned int patch = brotli_version & 0x00000FFF;
9513498266Sopenharmony_ci  (void)msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
9613498266Sopenharmony_ci}
9713498266Sopenharmony_ci#endif
9813498266Sopenharmony_ci
9913498266Sopenharmony_ci#ifdef HAVE_ZSTD
10013498266Sopenharmony_cistatic void zstd_version(char *buf, size_t bufsz)
10113498266Sopenharmony_ci{
10213498266Sopenharmony_ci  unsigned long zstd_version = (unsigned long)ZSTD_versionNumber();
10313498266Sopenharmony_ci  unsigned int major = (unsigned int)(zstd_version / (100 * 100));
10413498266Sopenharmony_ci  unsigned int minor = (unsigned int)((zstd_version -
10513498266Sopenharmony_ci                                       (major * 100 * 100)) / 100);
10613498266Sopenharmony_ci  unsigned int patch = (unsigned int)(zstd_version -
10713498266Sopenharmony_ci                                      (major * 100 * 100) - (minor * 100));
10813498266Sopenharmony_ci  (void)msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
10913498266Sopenharmony_ci}
11013498266Sopenharmony_ci#endif
11113498266Sopenharmony_ci
11213498266Sopenharmony_ci/*
11313498266Sopenharmony_ci * curl_version() returns a pointer to a static buffer.
11413498266Sopenharmony_ci *
11513498266Sopenharmony_ci * It is implemented to work multi-threaded by making sure repeated invokes
11613498266Sopenharmony_ci * generate the exact same string and never write any temporary data like
11713498266Sopenharmony_ci * zeros in the data.
11813498266Sopenharmony_ci */
11913498266Sopenharmony_ci
12013498266Sopenharmony_ci#define VERSION_PARTS 16 /* number of substrings we can concatenate */
12113498266Sopenharmony_ci
12213498266Sopenharmony_cichar *curl_version(void)
12313498266Sopenharmony_ci{
12413498266Sopenharmony_ci  static char out[300];
12513498266Sopenharmony_ci  char *outp;
12613498266Sopenharmony_ci  size_t outlen;
12713498266Sopenharmony_ci  const char *src[VERSION_PARTS];
12813498266Sopenharmony_ci#ifdef USE_SSL
12913498266Sopenharmony_ci  char ssl_version[200];
13013498266Sopenharmony_ci#endif
13113498266Sopenharmony_ci#ifdef HAVE_LIBZ
13213498266Sopenharmony_ci  char z_version[40];
13313498266Sopenharmony_ci#endif
13413498266Sopenharmony_ci#ifdef HAVE_BROTLI
13513498266Sopenharmony_ci  char br_version[40] = "brotli/";
13613498266Sopenharmony_ci#endif
13713498266Sopenharmony_ci#ifdef HAVE_ZSTD
13813498266Sopenharmony_ci  char zst_version[40] = "zstd/";
13913498266Sopenharmony_ci#endif
14013498266Sopenharmony_ci#ifdef USE_ARES
14113498266Sopenharmony_ci  char cares_version[40];
14213498266Sopenharmony_ci#endif
14313498266Sopenharmony_ci#if defined(USE_LIBIDN2)
14413498266Sopenharmony_ci  char idn_version[40];
14513498266Sopenharmony_ci#endif
14613498266Sopenharmony_ci#ifdef USE_LIBPSL
14713498266Sopenharmony_ci  char psl_version[40];
14813498266Sopenharmony_ci#endif
14913498266Sopenharmony_ci#ifdef USE_SSH
15013498266Sopenharmony_ci  char ssh_version[40];
15113498266Sopenharmony_ci#endif
15213498266Sopenharmony_ci#ifdef USE_NGHTTP2
15313498266Sopenharmony_ci  char h2_version[40];
15413498266Sopenharmony_ci#endif
15513498266Sopenharmony_ci#ifdef ENABLE_QUIC
15613498266Sopenharmony_ci  char h3_version[40];
15713498266Sopenharmony_ci#endif
15813498266Sopenharmony_ci#ifdef USE_LIBRTMP
15913498266Sopenharmony_ci  char rtmp_version[40];
16013498266Sopenharmony_ci#endif
16113498266Sopenharmony_ci#ifdef USE_HYPER
16213498266Sopenharmony_ci  char hyper_buf[30];
16313498266Sopenharmony_ci#endif
16413498266Sopenharmony_ci#ifdef USE_GSASL
16513498266Sopenharmony_ci  char gsasl_buf[30];
16613498266Sopenharmony_ci#endif
16713498266Sopenharmony_ci#ifdef USE_OPENLDAP
16813498266Sopenharmony_ci  char ldap_buf[30];
16913498266Sopenharmony_ci#endif
17013498266Sopenharmony_ci  int i = 0;
17113498266Sopenharmony_ci  int j;
17213498266Sopenharmony_ci
17313498266Sopenharmony_ci#ifdef DEBUGBUILD
17413498266Sopenharmony_ci  /* Override version string when environment variable CURL_VERSION is set */
17513498266Sopenharmony_ci  const char *debugversion = getenv("CURL_VERSION");
17613498266Sopenharmony_ci  if(debugversion) {
17713498266Sopenharmony_ci    strncpy(out, debugversion, sizeof(out)-1);
17813498266Sopenharmony_ci    out[sizeof(out)-1] = '\0';
17913498266Sopenharmony_ci    return out;
18013498266Sopenharmony_ci  }
18113498266Sopenharmony_ci#endif
18213498266Sopenharmony_ci
18313498266Sopenharmony_ci  src[i++] = LIBCURL_NAME "/" LIBCURL_VERSION;
18413498266Sopenharmony_ci#ifdef USE_SSL
18513498266Sopenharmony_ci  Curl_ssl_version(ssl_version, sizeof(ssl_version));
18613498266Sopenharmony_ci  src[i++] = ssl_version;
18713498266Sopenharmony_ci#endif
18813498266Sopenharmony_ci#ifdef HAVE_LIBZ
18913498266Sopenharmony_ci  msnprintf(z_version, sizeof(z_version), "zlib/%s", zlibVersion());
19013498266Sopenharmony_ci  src[i++] = z_version;
19113498266Sopenharmony_ci#endif
19213498266Sopenharmony_ci#ifdef HAVE_BROTLI
19313498266Sopenharmony_ci  brotli_version(&br_version[7], sizeof(br_version) - 7);
19413498266Sopenharmony_ci  src[i++] = br_version;
19513498266Sopenharmony_ci#endif
19613498266Sopenharmony_ci#ifdef HAVE_ZSTD
19713498266Sopenharmony_ci  zstd_version(&zst_version[5], sizeof(zst_version) - 5);
19813498266Sopenharmony_ci  src[i++] = zst_version;
19913498266Sopenharmony_ci#endif
20013498266Sopenharmony_ci#ifdef USE_ARES
20113498266Sopenharmony_ci  msnprintf(cares_version, sizeof(cares_version),
20213498266Sopenharmony_ci            "c-ares/%s", ares_version(NULL));
20313498266Sopenharmony_ci  src[i++] = cares_version;
20413498266Sopenharmony_ci#endif
20513498266Sopenharmony_ci#ifdef USE_LIBIDN2
20613498266Sopenharmony_ci  msnprintf(idn_version, sizeof(idn_version),
20713498266Sopenharmony_ci            "libidn2/%s", idn2_check_version(NULL));
20813498266Sopenharmony_ci  src[i++] = idn_version;
20913498266Sopenharmony_ci#elif defined(USE_WIN32_IDN)
21013498266Sopenharmony_ci  src[i++] = (char *)"WinIDN";
21113498266Sopenharmony_ci#endif
21213498266Sopenharmony_ci
21313498266Sopenharmony_ci#ifdef USE_LIBPSL
21413498266Sopenharmony_ci  {
21513498266Sopenharmony_ci    int num = psl_check_version_number(0);
21613498266Sopenharmony_ci    msnprintf(psl_version, sizeof(psl_version), "libpsl/%d.%d.%d",
21713498266Sopenharmony_ci              num >> 16, (num >> 8) & 0xff, num & 0xff);
21813498266Sopenharmony_ci    src[i++] = psl_version;
21913498266Sopenharmony_ci  }
22013498266Sopenharmony_ci#endif
22113498266Sopenharmony_ci
22213498266Sopenharmony_ci#ifdef USE_SSH
22313498266Sopenharmony_ci  Curl_ssh_version(ssh_version, sizeof(ssh_version));
22413498266Sopenharmony_ci  src[i++] = ssh_version;
22513498266Sopenharmony_ci#endif
22613498266Sopenharmony_ci#ifdef USE_NGHTTP2
22713498266Sopenharmony_ci  Curl_http2_ver(h2_version, sizeof(h2_version));
22813498266Sopenharmony_ci  src[i++] = h2_version;
22913498266Sopenharmony_ci#endif
23013498266Sopenharmony_ci#ifdef ENABLE_QUIC
23113498266Sopenharmony_ci  Curl_quic_ver(h3_version, sizeof(h3_version));
23213498266Sopenharmony_ci  src[i++] = h3_version;
23313498266Sopenharmony_ci#endif
23413498266Sopenharmony_ci#ifdef USE_LIBRTMP
23513498266Sopenharmony_ci  {
23613498266Sopenharmony_ci    char suff[2];
23713498266Sopenharmony_ci    if(RTMP_LIB_VERSION & 0xff) {
23813498266Sopenharmony_ci      suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
23913498266Sopenharmony_ci      suff[1] = '\0';
24013498266Sopenharmony_ci    }
24113498266Sopenharmony_ci    else
24213498266Sopenharmony_ci      suff[0] = '\0';
24313498266Sopenharmony_ci
24413498266Sopenharmony_ci    msnprintf(rtmp_version, sizeof(rtmp_version), "librtmp/%d.%d%s",
24513498266Sopenharmony_ci              RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
24613498266Sopenharmony_ci              suff);
24713498266Sopenharmony_ci    src[i++] = rtmp_version;
24813498266Sopenharmony_ci  }
24913498266Sopenharmony_ci#endif
25013498266Sopenharmony_ci#ifdef USE_HYPER
25113498266Sopenharmony_ci  msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
25213498266Sopenharmony_ci  src[i++] = hyper_buf;
25313498266Sopenharmony_ci#endif
25413498266Sopenharmony_ci#ifdef USE_GSASL
25513498266Sopenharmony_ci  msnprintf(gsasl_buf, sizeof(gsasl_buf), "libgsasl/%s",
25613498266Sopenharmony_ci            gsasl_check_version(NULL));
25713498266Sopenharmony_ci  src[i++] = gsasl_buf;
25813498266Sopenharmony_ci#endif
25913498266Sopenharmony_ci#ifdef USE_OPENLDAP
26013498266Sopenharmony_ci  {
26113498266Sopenharmony_ci    LDAPAPIInfo api;
26213498266Sopenharmony_ci    api.ldapai_info_version = LDAP_API_INFO_VERSION;
26313498266Sopenharmony_ci
26413498266Sopenharmony_ci    if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) {
26513498266Sopenharmony_ci      unsigned int patch = api.ldapai_vendor_version % 100;
26613498266Sopenharmony_ci      unsigned int major = api.ldapai_vendor_version / 10000;
26713498266Sopenharmony_ci      unsigned int minor =
26813498266Sopenharmony_ci        ((api.ldapai_vendor_version - major * 10000) - patch) / 100;
26913498266Sopenharmony_ci      msnprintf(ldap_buf, sizeof(ldap_buf), "%s/%u.%u.%u",
27013498266Sopenharmony_ci                api.ldapai_vendor_name, major, minor, patch);
27113498266Sopenharmony_ci      src[i++] = ldap_buf;
27213498266Sopenharmony_ci      ldap_memfree(api.ldapai_vendor_name);
27313498266Sopenharmony_ci      ber_memvfree((void **)api.ldapai_extensions);
27413498266Sopenharmony_ci    }
27513498266Sopenharmony_ci  }
27613498266Sopenharmony_ci#endif
27713498266Sopenharmony_ci
27813498266Sopenharmony_ci  DEBUGASSERT(i <= VERSION_PARTS);
27913498266Sopenharmony_ci
28013498266Sopenharmony_ci  outp = &out[0];
28113498266Sopenharmony_ci  outlen = sizeof(out);
28213498266Sopenharmony_ci  for(j = 0; j < i; j++) {
28313498266Sopenharmony_ci    size_t n = strlen(src[j]);
28413498266Sopenharmony_ci    /* we need room for a space, the string and the final zero */
28513498266Sopenharmony_ci    if(outlen <= (n + 2))
28613498266Sopenharmony_ci      break;
28713498266Sopenharmony_ci    if(j) {
28813498266Sopenharmony_ci      /* prepend a space if not the first */
28913498266Sopenharmony_ci      *outp++ = ' ';
29013498266Sopenharmony_ci      outlen--;
29113498266Sopenharmony_ci    }
29213498266Sopenharmony_ci    memcpy(outp, src[j], n);
29313498266Sopenharmony_ci    outp += n;
29413498266Sopenharmony_ci    outlen -= n;
29513498266Sopenharmony_ci  }
29613498266Sopenharmony_ci  *outp = 0;
29713498266Sopenharmony_ci
29813498266Sopenharmony_ci  return out;
29913498266Sopenharmony_ci}
30013498266Sopenharmony_ci
30113498266Sopenharmony_ci/* data for curl_version_info
30213498266Sopenharmony_ci
30313498266Sopenharmony_ci   Keep the list sorted alphabetically. It is also written so that each
30413498266Sopenharmony_ci   protocol line has its own #if line to make things easier on the eye.
30513498266Sopenharmony_ci */
30613498266Sopenharmony_ci
30713498266Sopenharmony_cistatic const char * const supported_protocols[] = {
30813498266Sopenharmony_ci#ifndef CURL_DISABLE_DICT
30913498266Sopenharmony_ci  "dict",
31013498266Sopenharmony_ci#endif
31113498266Sopenharmony_ci#ifndef CURL_DISABLE_FILE
31213498266Sopenharmony_ci  "file",
31313498266Sopenharmony_ci#endif
31413498266Sopenharmony_ci#ifndef CURL_DISABLE_FTP
31513498266Sopenharmony_ci  "ftp",
31613498266Sopenharmony_ci#endif
31713498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
31813498266Sopenharmony_ci  "ftps",
31913498266Sopenharmony_ci#endif
32013498266Sopenharmony_ci#ifndef CURL_DISABLE_GOPHER
32113498266Sopenharmony_ci  "gopher",
32213498266Sopenharmony_ci#endif
32313498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
32413498266Sopenharmony_ci  "gophers",
32513498266Sopenharmony_ci#endif
32613498266Sopenharmony_ci#ifndef CURL_DISABLE_HTTP
32713498266Sopenharmony_ci  "http",
32813498266Sopenharmony_ci#endif
32913498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
33013498266Sopenharmony_ci  "https",
33113498266Sopenharmony_ci#endif
33213498266Sopenharmony_ci#ifndef CURL_DISABLE_IMAP
33313498266Sopenharmony_ci  "imap",
33413498266Sopenharmony_ci#endif
33513498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
33613498266Sopenharmony_ci  "imaps",
33713498266Sopenharmony_ci#endif
33813498266Sopenharmony_ci#ifndef CURL_DISABLE_LDAP
33913498266Sopenharmony_ci  "ldap",
34013498266Sopenharmony_ci#if !defined(CURL_DISABLE_LDAPS) && \
34113498266Sopenharmony_ci    ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
34213498266Sopenharmony_ci     (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
34313498266Sopenharmony_ci  "ldaps",
34413498266Sopenharmony_ci#endif
34513498266Sopenharmony_ci#endif
34613498266Sopenharmony_ci#ifndef CURL_DISABLE_MQTT
34713498266Sopenharmony_ci  "mqtt",
34813498266Sopenharmony_ci#endif
34913498266Sopenharmony_ci#ifndef CURL_DISABLE_POP3
35013498266Sopenharmony_ci  "pop3",
35113498266Sopenharmony_ci#endif
35213498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
35313498266Sopenharmony_ci  "pop3s",
35413498266Sopenharmony_ci#endif
35513498266Sopenharmony_ci#ifdef USE_LIBRTMP
35613498266Sopenharmony_ci  "rtmp",
35713498266Sopenharmony_ci  "rtmpe",
35813498266Sopenharmony_ci  "rtmps",
35913498266Sopenharmony_ci  "rtmpt",
36013498266Sopenharmony_ci  "rtmpte",
36113498266Sopenharmony_ci  "rtmpts",
36213498266Sopenharmony_ci#endif
36313498266Sopenharmony_ci#ifndef CURL_DISABLE_RTSP
36413498266Sopenharmony_ci  "rtsp",
36513498266Sopenharmony_ci#endif
36613498266Sopenharmony_ci#if defined(USE_SSH) && !defined(USE_WOLFSSH)
36713498266Sopenharmony_ci  "scp",
36813498266Sopenharmony_ci#endif
36913498266Sopenharmony_ci#ifdef USE_SSH
37013498266Sopenharmony_ci  "sftp",
37113498266Sopenharmony_ci#endif
37213498266Sopenharmony_ci#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
37313498266Sopenharmony_ci  "smb",
37413498266Sopenharmony_ci#  ifdef USE_SSL
37513498266Sopenharmony_ci  "smbs",
37613498266Sopenharmony_ci#  endif
37713498266Sopenharmony_ci#endif
37813498266Sopenharmony_ci#ifndef CURL_DISABLE_SMTP
37913498266Sopenharmony_ci  "smtp",
38013498266Sopenharmony_ci#endif
38113498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
38213498266Sopenharmony_ci  "smtps",
38313498266Sopenharmony_ci#endif
38413498266Sopenharmony_ci#ifndef CURL_DISABLE_TELNET
38513498266Sopenharmony_ci  "telnet",
38613498266Sopenharmony_ci#endif
38713498266Sopenharmony_ci#ifndef CURL_DISABLE_TFTP
38813498266Sopenharmony_ci  "tftp",
38913498266Sopenharmony_ci#endif
39013498266Sopenharmony_ci#ifdef USE_WEBSOCKETS
39113498266Sopenharmony_ci  "ws",
39213498266Sopenharmony_ci#endif
39313498266Sopenharmony_ci#if defined(USE_SSL) && defined(USE_WEBSOCKETS)
39413498266Sopenharmony_ci  "wss",
39513498266Sopenharmony_ci#endif
39613498266Sopenharmony_ci
39713498266Sopenharmony_ci  NULL
39813498266Sopenharmony_ci};
39913498266Sopenharmony_ci
40013498266Sopenharmony_ci/*
40113498266Sopenharmony_ci * Feature presence run-time check functions.
40213498266Sopenharmony_ci *
40313498266Sopenharmony_ci * Warning: the value returned by these should not change between
40413498266Sopenharmony_ci * curl_global_init() and curl_global_cleanup() calls.
40513498266Sopenharmony_ci */
40613498266Sopenharmony_ci
40713498266Sopenharmony_ci#if defined(USE_LIBIDN2)
40813498266Sopenharmony_cistatic int idn_present(curl_version_info_data *info)
40913498266Sopenharmony_ci{
41013498266Sopenharmony_ci  return info->libidn != NULL;
41113498266Sopenharmony_ci}
41213498266Sopenharmony_ci#else
41313498266Sopenharmony_ci#define idn_present     NULL
41413498266Sopenharmony_ci#endif
41513498266Sopenharmony_ci
41613498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
41713498266Sopenharmony_ci  !defined(CURL_DISABLE_HTTP)
41813498266Sopenharmony_cistatic int https_proxy_present(curl_version_info_data *info)
41913498266Sopenharmony_ci{
42013498266Sopenharmony_ci  (void) info;
42113498266Sopenharmony_ci  return Curl_ssl_supports(NULL, SSLSUPP_HTTPS_PROXY);
42213498266Sopenharmony_ci}
42313498266Sopenharmony_ci#endif
42413498266Sopenharmony_ci
42513498266Sopenharmony_ci/*
42613498266Sopenharmony_ci * Features table.
42713498266Sopenharmony_ci *
42813498266Sopenharmony_ci * Keep the features alphabetically sorted.
42913498266Sopenharmony_ci * Use FEATURE() macro to define an entry: this allows documentation check.
43013498266Sopenharmony_ci */
43113498266Sopenharmony_ci
43213498266Sopenharmony_ci#define FEATURE(name, present, bitmask) {(name), (present), (bitmask)}
43313498266Sopenharmony_ci
43413498266Sopenharmony_cistruct feat {
43513498266Sopenharmony_ci  const char *name;
43613498266Sopenharmony_ci  int        (*present)(curl_version_info_data *info);
43713498266Sopenharmony_ci  int        bitmask;
43813498266Sopenharmony_ci};
43913498266Sopenharmony_ci
44013498266Sopenharmony_cistatic const struct feat features_table[] = {
44113498266Sopenharmony_ci#ifndef CURL_DISABLE_ALTSVC
44213498266Sopenharmony_ci  FEATURE("alt-svc",     NULL,                CURL_VERSION_ALTSVC),
44313498266Sopenharmony_ci#endif
44413498266Sopenharmony_ci#ifdef CURLRES_ASYNCH
44513498266Sopenharmony_ci  FEATURE("AsynchDNS",   NULL,                CURL_VERSION_ASYNCHDNS),
44613498266Sopenharmony_ci#endif
44713498266Sopenharmony_ci#ifdef HAVE_BROTLI
44813498266Sopenharmony_ci  FEATURE("brotli",      NULL,                CURL_VERSION_BROTLI),
44913498266Sopenharmony_ci#endif
45013498266Sopenharmony_ci#ifdef DEBUGBUILD
45113498266Sopenharmony_ci  FEATURE("Debug",       NULL,                CURL_VERSION_DEBUG),
45213498266Sopenharmony_ci#endif
45313498266Sopenharmony_ci#ifdef USE_GSASL
45413498266Sopenharmony_ci  FEATURE("gsasl",       NULL,                CURL_VERSION_GSASL),
45513498266Sopenharmony_ci#endif
45613498266Sopenharmony_ci#ifdef HAVE_GSSAPI
45713498266Sopenharmony_ci  FEATURE("GSS-API",     NULL,                CURL_VERSION_GSSAPI),
45813498266Sopenharmony_ci#endif
45913498266Sopenharmony_ci#ifndef CURL_DISABLE_HSTS
46013498266Sopenharmony_ci  FEATURE("HSTS",        NULL,                CURL_VERSION_HSTS),
46113498266Sopenharmony_ci#endif
46213498266Sopenharmony_ci#if defined(USE_NGHTTP2)
46313498266Sopenharmony_ci  FEATURE("HTTP2",       NULL,                CURL_VERSION_HTTP2),
46413498266Sopenharmony_ci#endif
46513498266Sopenharmony_ci#if defined(ENABLE_QUIC)
46613498266Sopenharmony_ci  FEATURE("HTTP3",       NULL,                CURL_VERSION_HTTP3),
46713498266Sopenharmony_ci#endif
46813498266Sopenharmony_ci#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
46913498266Sopenharmony_ci  !defined(CURL_DISABLE_HTTP)
47013498266Sopenharmony_ci  FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
47113498266Sopenharmony_ci#endif
47213498266Sopenharmony_ci#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
47313498266Sopenharmony_ci  FEATURE("IDN",         idn_present,         CURL_VERSION_IDN),
47413498266Sopenharmony_ci#endif
47513498266Sopenharmony_ci#ifdef ENABLE_IPV6
47613498266Sopenharmony_ci  FEATURE("IPv6",        NULL,                CURL_VERSION_IPV6),
47713498266Sopenharmony_ci#endif
47813498266Sopenharmony_ci#ifdef USE_KERBEROS5
47913498266Sopenharmony_ci  FEATURE("Kerberos",    NULL,                CURL_VERSION_KERBEROS5),
48013498266Sopenharmony_ci#endif
48113498266Sopenharmony_ci#if (SIZEOF_CURL_OFF_T > 4) && \
48213498266Sopenharmony_ci    ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
48313498266Sopenharmony_ci  FEATURE("Largefile",   NULL,                CURL_VERSION_LARGEFILE),
48413498266Sopenharmony_ci#endif
48513498266Sopenharmony_ci#ifdef HAVE_LIBZ
48613498266Sopenharmony_ci  FEATURE("libz",        NULL,                CURL_VERSION_LIBZ),
48713498266Sopenharmony_ci#endif
48813498266Sopenharmony_ci#ifdef CURL_WITH_MULTI_SSL
48913498266Sopenharmony_ci  FEATURE("MultiSSL",    NULL,                CURL_VERSION_MULTI_SSL),
49013498266Sopenharmony_ci#endif
49113498266Sopenharmony_ci#ifdef USE_NTLM
49213498266Sopenharmony_ci  FEATURE("NTLM",        NULL,                CURL_VERSION_NTLM),
49313498266Sopenharmony_ci#endif
49413498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
49513498266Sopenharmony_ci  defined(NTLM_WB_ENABLED)
49613498266Sopenharmony_ci  FEATURE("NTLM_WB",     NULL,                CURL_VERSION_NTLM_WB),
49713498266Sopenharmony_ci#endif
49813498266Sopenharmony_ci#if defined(USE_LIBPSL)
49913498266Sopenharmony_ci  FEATURE("PSL",         NULL,                CURL_VERSION_PSL),
50013498266Sopenharmony_ci#endif
50113498266Sopenharmony_ci#ifdef USE_SPNEGO
50213498266Sopenharmony_ci  FEATURE("SPNEGO",      NULL,                CURL_VERSION_SPNEGO),
50313498266Sopenharmony_ci#endif
50413498266Sopenharmony_ci#ifdef USE_SSL
50513498266Sopenharmony_ci  FEATURE("SSL",         NULL,                CURL_VERSION_SSL),
50613498266Sopenharmony_ci#endif
50713498266Sopenharmony_ci#ifdef USE_WINDOWS_SSPI
50813498266Sopenharmony_ci  FEATURE("SSPI",        NULL,                CURL_VERSION_SSPI),
50913498266Sopenharmony_ci#endif
51013498266Sopenharmony_ci#ifdef GLOBAL_INIT_IS_THREADSAFE
51113498266Sopenharmony_ci  FEATURE("threadsafe",  NULL,                CURL_VERSION_THREADSAFE),
51213498266Sopenharmony_ci#endif
51313498266Sopenharmony_ci#ifdef USE_TLS_SRP
51413498266Sopenharmony_ci  FEATURE("TLS-SRP",     NULL,                CURL_VERSION_TLSAUTH_SRP),
51513498266Sopenharmony_ci#endif
51613498266Sopenharmony_ci#ifdef CURLDEBUG
51713498266Sopenharmony_ci  FEATURE("TrackMemory", NULL,                CURL_VERSION_CURLDEBUG),
51813498266Sopenharmony_ci#endif
51913498266Sopenharmony_ci#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE)
52013498266Sopenharmony_ci  FEATURE("Unicode",     NULL,                CURL_VERSION_UNICODE),
52113498266Sopenharmony_ci#endif
52213498266Sopenharmony_ci#ifdef USE_UNIX_SOCKETS
52313498266Sopenharmony_ci  FEATURE("UnixSockets", NULL,                CURL_VERSION_UNIX_SOCKETS),
52413498266Sopenharmony_ci#endif
52513498266Sopenharmony_ci#ifdef HAVE_ZSTD
52613498266Sopenharmony_ci  FEATURE("zstd",        NULL,                CURL_VERSION_ZSTD),
52713498266Sopenharmony_ci#endif
52813498266Sopenharmony_ci  {NULL,             NULL,                0}
52913498266Sopenharmony_ci};
53013498266Sopenharmony_ci
53113498266Sopenharmony_cistatic const char *feature_names[sizeof(features_table) /
53213498266Sopenharmony_ci                                 sizeof(features_table[0])] = {NULL};
53313498266Sopenharmony_ci
53413498266Sopenharmony_ci
53513498266Sopenharmony_cistatic curl_version_info_data version_info = {
53613498266Sopenharmony_ci  CURLVERSION_NOW,
53713498266Sopenharmony_ci  LIBCURL_VERSION,
53813498266Sopenharmony_ci  LIBCURL_VERSION_NUM,
53913498266Sopenharmony_ci  OS,   /* as found by configure or set by hand at build-time */
54013498266Sopenharmony_ci  0,    /* features bitmask is built at run-time */
54113498266Sopenharmony_ci  NULL, /* ssl_version */
54213498266Sopenharmony_ci  0,    /* ssl_version_num, this is kept at zero */
54313498266Sopenharmony_ci  NULL, /* zlib_version */
54413498266Sopenharmony_ci  supported_protocols,
54513498266Sopenharmony_ci  NULL, /* c-ares version */
54613498266Sopenharmony_ci  0,    /* c-ares version numerical */
54713498266Sopenharmony_ci  NULL, /* libidn version */
54813498266Sopenharmony_ci  0,    /* iconv version */
54913498266Sopenharmony_ci  NULL, /* ssh lib version */
55013498266Sopenharmony_ci  0,    /* brotli_ver_num */
55113498266Sopenharmony_ci  NULL, /* brotli version */
55213498266Sopenharmony_ci  0,    /* nghttp2 version number */
55313498266Sopenharmony_ci  NULL, /* nghttp2 version string */
55413498266Sopenharmony_ci  NULL, /* quic library string */
55513498266Sopenharmony_ci#ifdef CURL_CA_BUNDLE
55613498266Sopenharmony_ci  CURL_CA_BUNDLE, /* cainfo */
55713498266Sopenharmony_ci#else
55813498266Sopenharmony_ci  NULL,
55913498266Sopenharmony_ci#endif
56013498266Sopenharmony_ci#ifdef CURL_CA_PATH
56113498266Sopenharmony_ci  CURL_CA_PATH,  /* capath */
56213498266Sopenharmony_ci#else
56313498266Sopenharmony_ci  NULL,
56413498266Sopenharmony_ci#endif
56513498266Sopenharmony_ci  0,    /* zstd_ver_num */
56613498266Sopenharmony_ci  NULL, /* zstd version */
56713498266Sopenharmony_ci  NULL, /* Hyper version */
56813498266Sopenharmony_ci  NULL, /* gsasl version */
56913498266Sopenharmony_ci  feature_names
57013498266Sopenharmony_ci};
57113498266Sopenharmony_ci
57213498266Sopenharmony_cicurl_version_info_data *curl_version_info(CURLversion stamp)
57313498266Sopenharmony_ci{
57413498266Sopenharmony_ci  size_t n;
57513498266Sopenharmony_ci  const struct feat *p;
57613498266Sopenharmony_ci  int features = 0;
57713498266Sopenharmony_ci
57813498266Sopenharmony_ci#if defined(USE_SSH)
57913498266Sopenharmony_ci  static char ssh_buffer[80];
58013498266Sopenharmony_ci#endif
58113498266Sopenharmony_ci#ifdef USE_SSL
58213498266Sopenharmony_ci#ifdef CURL_WITH_MULTI_SSL
58313498266Sopenharmony_ci  static char ssl_buffer[200];
58413498266Sopenharmony_ci#else
58513498266Sopenharmony_ci  static char ssl_buffer[80];
58613498266Sopenharmony_ci#endif
58713498266Sopenharmony_ci#endif
58813498266Sopenharmony_ci#ifdef HAVE_BROTLI
58913498266Sopenharmony_ci  static char brotli_buffer[80];
59013498266Sopenharmony_ci#endif
59113498266Sopenharmony_ci#ifdef HAVE_ZSTD
59213498266Sopenharmony_ci  static char zstd_buffer[80];
59313498266Sopenharmony_ci#endif
59413498266Sopenharmony_ci
59513498266Sopenharmony_ci  (void)stamp; /* avoid compiler warnings, we don't use this */
59613498266Sopenharmony_ci
59713498266Sopenharmony_ci#ifdef USE_SSL
59813498266Sopenharmony_ci  Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
59913498266Sopenharmony_ci  version_info.ssl_version = ssl_buffer;
60013498266Sopenharmony_ci#endif
60113498266Sopenharmony_ci
60213498266Sopenharmony_ci#ifdef HAVE_LIBZ
60313498266Sopenharmony_ci  version_info.libz_version = zlibVersion();
60413498266Sopenharmony_ci  /* libz left NULL if non-existing */
60513498266Sopenharmony_ci#endif
60613498266Sopenharmony_ci#ifdef USE_ARES
60713498266Sopenharmony_ci  {
60813498266Sopenharmony_ci    int aresnum;
60913498266Sopenharmony_ci    version_info.ares = ares_version(&aresnum);
61013498266Sopenharmony_ci    version_info.ares_num = aresnum;
61113498266Sopenharmony_ci  }
61213498266Sopenharmony_ci#endif
61313498266Sopenharmony_ci#ifdef USE_LIBIDN2
61413498266Sopenharmony_ci  /* This returns a version string if we use the given version or later,
61513498266Sopenharmony_ci     otherwise it returns NULL */
61613498266Sopenharmony_ci  version_info.libidn = idn2_check_version(IDN2_VERSION);
61713498266Sopenharmony_ci#endif
61813498266Sopenharmony_ci
61913498266Sopenharmony_ci#if defined(USE_SSH)
62013498266Sopenharmony_ci  Curl_ssh_version(ssh_buffer, sizeof(ssh_buffer));
62113498266Sopenharmony_ci  version_info.libssh_version = ssh_buffer;
62213498266Sopenharmony_ci#endif
62313498266Sopenharmony_ci
62413498266Sopenharmony_ci#ifdef HAVE_BROTLI
62513498266Sopenharmony_ci  version_info.brotli_ver_num = BrotliDecoderVersion();
62613498266Sopenharmony_ci  brotli_version(brotli_buffer, sizeof(brotli_buffer));
62713498266Sopenharmony_ci  version_info.brotli_version = brotli_buffer;
62813498266Sopenharmony_ci#endif
62913498266Sopenharmony_ci
63013498266Sopenharmony_ci#ifdef HAVE_ZSTD
63113498266Sopenharmony_ci  version_info.zstd_ver_num = (unsigned int)ZSTD_versionNumber();
63213498266Sopenharmony_ci  zstd_version(zstd_buffer, sizeof(zstd_buffer));
63313498266Sopenharmony_ci  version_info.zstd_version = zstd_buffer;
63413498266Sopenharmony_ci#endif
63513498266Sopenharmony_ci
63613498266Sopenharmony_ci#ifdef USE_NGHTTP2
63713498266Sopenharmony_ci  {
63813498266Sopenharmony_ci    nghttp2_info *h2 = nghttp2_version(0);
63913498266Sopenharmony_ci    version_info.nghttp2_ver_num = h2->version_num;
64013498266Sopenharmony_ci    version_info.nghttp2_version = h2->version_str;
64113498266Sopenharmony_ci  }
64213498266Sopenharmony_ci#endif
64313498266Sopenharmony_ci
64413498266Sopenharmony_ci#ifdef ENABLE_QUIC
64513498266Sopenharmony_ci  {
64613498266Sopenharmony_ci    static char quicbuffer[80];
64713498266Sopenharmony_ci    Curl_quic_ver(quicbuffer, sizeof(quicbuffer));
64813498266Sopenharmony_ci    version_info.quic_version = quicbuffer;
64913498266Sopenharmony_ci  }
65013498266Sopenharmony_ci#endif
65113498266Sopenharmony_ci
65213498266Sopenharmony_ci#ifdef USE_HYPER
65313498266Sopenharmony_ci  {
65413498266Sopenharmony_ci    static char hyper_buffer[30];
65513498266Sopenharmony_ci    msnprintf(hyper_buffer, sizeof(hyper_buffer), "Hyper/%s", hyper_version());
65613498266Sopenharmony_ci    version_info.hyper_version = hyper_buffer;
65713498266Sopenharmony_ci  }
65813498266Sopenharmony_ci#endif
65913498266Sopenharmony_ci
66013498266Sopenharmony_ci#ifdef USE_GSASL
66113498266Sopenharmony_ci  {
66213498266Sopenharmony_ci    version_info.gsasl_version = gsasl_check_version(NULL);
66313498266Sopenharmony_ci  }
66413498266Sopenharmony_ci#endif
66513498266Sopenharmony_ci
66613498266Sopenharmony_ci  /* Get available features, build bitmask and names array. */
66713498266Sopenharmony_ci  n = 0;
66813498266Sopenharmony_ci  for(p = features_table; p->name; p++)
66913498266Sopenharmony_ci    if(!p->present || p->present(&version_info)) {
67013498266Sopenharmony_ci      features |= p->bitmask;
67113498266Sopenharmony_ci      feature_names[n++] = p->name;
67213498266Sopenharmony_ci    }
67313498266Sopenharmony_ci
67413498266Sopenharmony_ci  feature_names[n] = NULL;  /* Terminate array. */
67513498266Sopenharmony_ci  version_info.features = features;
67613498266Sopenharmony_ci
67713498266Sopenharmony_ci  return &version_info;
67813498266Sopenharmony_ci}
679