Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/curl/lib/version.c
Line
Count
Source
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
25
#include "curl_setup.h"
26
27
#ifdef USE_NGHTTP2
28
#include <nghttp2/nghttp2.h>
29
#endif
30
31
#include <curl/curl.h>
32
#include "urldata.h"
33
#include "vtls/vtls.h"
34
#include "http2.h"
35
#include "vssh/ssh.h"
36
#include "vquic/vquic.h"
37
#include "easy_lock.h"
38
39
#ifdef USE_ARES
40
#  include <ares.h>
41
#endif
42
43
#ifdef USE_LIBIDN2
44
#include <idn2.h>
45
#endif
46
47
#ifdef USE_LIBPSL
48
#include <libpsl.h>
49
#endif
50
51
#ifdef USE_LIBRTMP
52
#include <librtmp/rtmp.h>
53
#include "curl_rtmp.h"
54
#endif
55
56
#ifdef HAVE_LIBZ
57
#include <zlib.h>
58
#endif
59
60
#ifdef HAVE_BROTLI
61
#if defined(__GNUC__) || defined(__clang__)
62
/* Ignore -Wvla warnings in brotli headers */
63
#pragma GCC diagnostic push
64
#pragma GCC diagnostic ignored "-Wvla"
65
#endif
66
#include <brotli/decode.h>
67
#if defined(__GNUC__) || defined(__clang__)
68
#pragma GCC diagnostic pop
69
#endif
70
#endif
71
72
#ifdef HAVE_ZSTD
73
#include <zstd.h>
74
#endif
75
76
#ifdef USE_GSASL
77
#include <gsasl.h>
78
#endif
79
80
#ifdef HAVE_GSSAPI
81
# ifdef HAVE_GSSGNU
82
#  include <gss.h>
83
# else
84
#  ifdef HAVE_GSSAPI_H
85
#   include <gssapi.h>
86
#  else
87
#   include <gssapi/gssapi.h>
88
#  endif
89
# endif
90
#endif
91
92
#ifdef USE_OPENLDAP
93
#include <ldap.h>
94
#endif
95
96
#ifdef HAVE_BROTLI
97
static void brotli_version(char *buf, size_t bufsz)
98
{
99
  uint32_t brotli_version = BrotliDecoderVersion();
100
  unsigned int major = brotli_version >> 24;
101
  unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
102
  unsigned int patch = brotli_version & 0x00000FFF;
103
  (void)curl_msnprintf(buf, bufsz, "brotli/%u.%u.%u", major, minor, patch);
104
}
105
#endif
106
107
#ifdef HAVE_ZSTD
108
static void zstd_version(char *buf, size_t bufsz)
109
70
{
110
70
  unsigned int version = ZSTD_versionNumber();
111
70
  unsigned int major = version / (100 * 100);
112
70
  unsigned int minor = (version - (major * 100 * 100)) / 100;
113
70
  unsigned int patch = version - (major * 100 * 100) - (minor * 100);
114
70
  (void)curl_msnprintf(buf, bufsz, "zstd/%u.%u.%u", major, minor, patch);
115
70
}
116
#endif
117
118
#ifdef USE_OPENLDAP
119
static void oldap_version(char *buf, size_t bufsz)
120
{
121
  LDAPAPIInfo api;
122
  api.ldapai_info_version = LDAP_API_INFO_VERSION;
123
124
  if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) {
125
    unsigned int patch = (unsigned int)(api.ldapai_vendor_version % 100);
126
    unsigned int major = (unsigned int)(api.ldapai_vendor_version / 10000);
127
    unsigned int minor =
128
      (((unsigned int)api.ldapai_vendor_version - major * 10000)
129
       - patch) / 100;
130
    curl_msnprintf(buf, bufsz, "%s/%u.%u.%u",
131
                   api.ldapai_vendor_name, major, minor, patch);
132
    ldap_memfree(api.ldapai_vendor_name);
133
    ber_memvfree((void **)api.ldapai_extensions);
134
  }
135
  else
136
    curl_msnprintf(buf, bufsz, "OpenLDAP");
137
}
138
#endif
139
140
#ifdef USE_LIBPSL
141
static void psl_version(char *buf, size_t bufsz)
142
{
143
#if defined(PSL_VERSION_MAJOR) && (PSL_VERSION_MAJOR > 0 ||     \
144
                                   PSL_VERSION_MINOR >= 11)
145
  int num = psl_check_version_number(0);
146
  curl_msnprintf(buf, bufsz, "libpsl/%d.%d.%d",
147
                 num >> 16, (num >> 8) & 0xff, num & 0xff);
148
#else
149
  curl_msnprintf(buf, bufsz, "libpsl/%s", psl_get_version());
150
#endif
151
}
152
#endif
153
154
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
155
#define USE_IDN
156
#endif
157
158
#ifdef USE_IDN
159
static void idn_version(char *buf, size_t bufsz)
160
{
161
#ifdef USE_LIBIDN2
162
  curl_msnprintf(buf, bufsz, "libidn2/%s", idn2_check_version(NULL));
163
#elif defined(USE_WIN32_IDN)
164
  curl_msnprintf(buf, bufsz, "WinIDN");
165
#elif defined(USE_APPLE_IDN)
166
  curl_msnprintf(buf, bufsz, "AppleIDN");
167
#endif
168
}
169
#endif
170
171
/*
172
 * curl_version() returns a pointer to a static buffer.
173
 *
174
 * It is implemented to work multi-threaded by making sure repeated invokes
175
 * generate the exact same string and never write any temporary data like
176
 * zeros in the data.
177
 */
178
179
#define VERSION_PARTS 16 /* number of substrings we can concatenate */
180
181
char *curl_version(void)
182
51
{
183
51
  static char out[300];
184
51
  char *outp;
185
51
  size_t outlen;
186
51
  const char *src[VERSION_PARTS];
187
51
#ifdef USE_SSL
188
51
  char ssl_version[200];
189
51
#endif
190
51
#ifdef HAVE_LIBZ
191
51
  char z_version[30];
192
51
#endif
193
#ifdef HAVE_BROTLI
194
  char br_version[30];
195
#endif
196
51
#ifdef HAVE_ZSTD
197
51
  char zstd_ver[30];
198
51
#endif
199
#ifdef USE_ARES
200
  char cares_version[30];
201
#endif
202
#ifdef USE_IDN
203
  char idn_ver[30];
204
#endif
205
#ifdef USE_LIBPSL
206
  char psl_ver[30];
207
#endif
208
#ifdef USE_SSH
209
  char ssh_version[30];
210
#endif
211
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NGHTTP2)
212
  char h2_version[30];
213
#endif
214
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HTTP3)
215
  char h3_version[30];
216
#endif
217
#ifdef USE_LIBRTMP
218
  char rtmp_version[30];
219
#endif
220
#ifdef USE_GSASL
221
  char gsasl_buf[30];
222
#endif
223
#ifdef HAVE_GSSAPI
224
  char gss_buf[40];
225
#endif
226
#ifdef USE_OPENLDAP
227
  char ldap_buf[30];
228
#endif
229
51
  int i = 0;
230
51
  int j;
231
232
#ifdef DEBUGBUILD
233
  /* Override version string when environment variable CURL_VERSION is set */
234
  const char *debugversion = getenv("CURL_VERSION");
235
  if(debugversion) {
236
    curl_msnprintf(out, sizeof(out), "%s", debugversion);
237
    return out;
238
  }
239
#endif
240
241
51
  src[i++] = LIBCURL_NAME "/" LIBCURL_VERSION;
242
51
#ifdef USE_SSL
243
51
  Curl_ssl_version(ssl_version, sizeof(ssl_version));
244
51
  src[i++] = ssl_version;
245
51
#endif
246
51
#ifdef HAVE_LIBZ
247
51
  curl_msnprintf(z_version, sizeof(z_version), "zlib/%s", zlibVersion());
248
51
  src[i++] = z_version;
249
51
#endif
250
#ifdef HAVE_BROTLI
251
  brotli_version(br_version, sizeof(br_version));
252
  src[i++] = br_version;
253
#endif
254
51
#ifdef HAVE_ZSTD
255
51
  zstd_version(zstd_ver, sizeof(zstd_ver));
256
51
  src[i++] = zstd_ver;
257
51
#endif
258
#ifdef USE_ARES
259
  curl_msnprintf(cares_version, sizeof(cares_version),
260
                 "c-ares/%s", ares_version(NULL));
261
  src[i++] = cares_version;
262
#endif
263
#ifdef USE_IDN
264
  idn_version(idn_ver, sizeof(idn_ver));
265
  src[i++] = idn_ver;
266
#endif
267
#ifdef USE_LIBPSL
268
  psl_version(psl_ver, sizeof(psl_ver));
269
  src[i++] = psl_ver;
270
#endif
271
#ifdef USE_SSH
272
  Curl_ssh_version(ssh_version, sizeof(ssh_version));
273
  src[i++] = ssh_version;
274
#endif
275
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NGHTTP2)
276
  Curl_http2_ver(h2_version, sizeof(h2_version));
277
  src[i++] = h2_version;
278
#endif
279
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HTTP3)
280
  Curl_quic_ver(h3_version, sizeof(h3_version));
281
  src[i++] = h3_version;
282
#endif
283
#ifdef USE_LIBRTMP
284
  Curl_rtmp_version(rtmp_version, sizeof(rtmp_version));
285
  src[i++] = rtmp_version;
286
#endif
287
#ifdef USE_GSASL
288
  curl_msnprintf(gsasl_buf, sizeof(gsasl_buf), "libgsasl/%s",
289
                 gsasl_check_version(NULL));
290
  src[i++] = gsasl_buf;
291
#endif
292
#ifdef HAVE_GSSAPI
293
#ifdef HAVE_GSSGNU
294
  curl_msnprintf(gss_buf, sizeof(gss_buf), "libgss/%s",
295
                 GSS_VERSION);
296
#elif defined(CURL_KRB5_VERSION)
297
  curl_msnprintf(gss_buf, sizeof(gss_buf), "mit-krb5/%s",
298
                 CURL_KRB5_VERSION);
299
#else
300
  curl_msnprintf(gss_buf, sizeof(gss_buf), "mit-krb5");
301
#endif
302
  src[i++] = gss_buf;
303
#endif /* HAVE_GSSAPI */
304
#ifdef USE_OPENLDAP
305
  oldap_version(ldap_buf, sizeof(ldap_buf));
306
  src[i++] = ldap_buf;
307
#endif
308
309
51
  DEBUGASSERT(i <= VERSION_PARTS);
310
311
51
  outp = &out[0];
312
51
  outlen = sizeof(out);
313
255
  for(j = 0; j < i; j++) {
314
204
    size_t n = strlen(src[j]);
315
    /* we need room for a space, the string and the final zero */
316
204
    if(outlen <= (n + 2))
317
0
      break;
318
204
    if(j) {
319
      /* prepend a space if not the first */
320
153
      *outp++ = ' ';
321
153
      outlen--;
322
153
    }
323
204
    memcpy(outp, src[j], n);
324
204
    outp += n;
325
204
    outlen -= n;
326
204
  }
327
51
  *outp = 0;
328
329
51
  return out;
330
51
}
331
332
/* data for curl_version_info
333
334
   Keep the list sorted alphabetically. It is also written so that each
335
   protocol line has its own #if line to make things easier on the eye.
336
 */
337
338
static const char * const supported_protocols[] = {
339
#ifndef CURL_DISABLE_DICT
340
  "dict",
341
#endif
342
#ifndef CURL_DISABLE_FILE
343
  "file",
344
#endif
345
#ifndef CURL_DISABLE_FTP
346
  "ftp",
347
#endif
348
#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
349
  "ftps",
350
#endif
351
#ifndef CURL_DISABLE_GOPHER
352
  "gopher",
353
#endif
354
#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
355
  "gophers",
356
#endif
357
#ifndef CURL_DISABLE_HTTP
358
  "http",
359
#endif
360
#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
361
  "https",
362
#endif
363
#ifndef CURL_DISABLE_IMAP
364
  "imap",
365
#endif
366
#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
367
  "imaps",
368
#endif
369
#ifndef CURL_DISABLE_LDAP
370
  "ldap",
371
#if !defined(CURL_DISABLE_LDAPS) && \
372
    ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
373
     (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
374
  "ldaps",
375
#endif
376
#endif
377
#ifndef CURL_DISABLE_MQTT
378
  "mqtt",
379
#endif
380
#ifndef CURL_DISABLE_POP3
381
  "pop3",
382
#endif
383
#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
384
  "pop3s",
385
#endif
386
#ifdef USE_LIBRTMP
387
  "rtmp",
388
  "rtmpe",
389
  "rtmps",
390
  "rtmpt",
391
  "rtmpte",
392
  "rtmpts",
393
#endif
394
#ifndef CURL_DISABLE_RTSP
395
  "rtsp",
396
#endif
397
#ifdef USE_SSH
398
  "scp",
399
  "sftp",
400
#endif
401
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
402
  "smb",
403
#  ifdef USE_SSL
404
  "smbs",
405
#  endif
406
#endif
407
#ifndef CURL_DISABLE_SMTP
408
  "smtp",
409
#endif
410
#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
411
  "smtps",
412
#endif
413
#ifndef CURL_DISABLE_TELNET
414
  "telnet",
415
#endif
416
#ifndef CURL_DISABLE_TFTP
417
  "tftp",
418
#endif
419
#ifndef CURL_DISABLE_HTTP
420
  /* WebSocket support relies on HTTP */
421
#ifndef CURL_DISABLE_WEBSOCKETS
422
  "ws",
423
#endif
424
#if defined(USE_SSL) && !defined(CURL_DISABLE_WEBSOCKETS)
425
  "wss",
426
#endif
427
#endif
428
429
  NULL
430
};
431
432
/*
433
 * Feature presence runtime check functions.
434
 *
435
 * Warning: the value returned by these should not change between
436
 * curl_global_init() and curl_global_cleanup() calls.
437
 */
438
439
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
440
static int idn_present(curl_version_info_data *info)
441
{
442
#if defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
443
  (void)info;
444
  return TRUE;
445
#else
446
  return info->libidn != NULL;
447
#endif
448
}
449
#endif
450
451
#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
452
  !defined(CURL_DISABLE_HTTP)
453
static int https_proxy_present(curl_version_info_data *info)
454
19
{
455
19
  (void)info;
456
19
  return Curl_ssl_supports(NULL, SSLSUPP_HTTPS_PROXY);
457
19
}
458
#endif
459
460
#if defined(USE_SSL) && defined(USE_ECH)
461
static int ech_present(curl_version_info_data *info)
462
{
463
  (void)info;
464
  return Curl_ssl_supports(NULL, SSLSUPP_ECH);
465
}
466
#endif
467
468
/*
469
 * Features table.
470
 *
471
 * Keep the features alphabetically sorted.
472
 * Use FEATURE() macro to define an entry: this allows documentation check.
473
 */
474
475
#define FEATURE(name, present, bitmask) {(name), (present), (bitmask)}
476
477
struct feat {
478
  const char *name;
479
  int        (*present)(curl_version_info_data *info);
480
  int        bitmask;
481
};
482
483
static const struct feat features_table[] = {
484
#ifndef CURL_DISABLE_ALTSVC
485
  FEATURE("alt-svc",     NULL,                CURL_VERSION_ALTSVC),
486
#endif
487
#if defined(USE_ARES) && defined(CURLRES_THREADED) && defined(USE_HTTPSRR)
488
  FEATURE("asyn-rr", NULL,             0),
489
#endif
490
#ifdef CURLRES_ASYNCH
491
  FEATURE("AsynchDNS",   NULL,                CURL_VERSION_ASYNCHDNS),
492
#endif
493
#ifdef HAVE_BROTLI
494
  FEATURE("brotli",      NULL,                CURL_VERSION_BROTLI),
495
#endif
496
#ifdef DEBUGBUILD
497
  FEATURE("Debug",       NULL,                CURL_VERSION_DEBUG),
498
#endif
499
#if defined(USE_SSL) && defined(USE_ECH)
500
  FEATURE("ECH",         ech_present,         0),
501
502
#ifndef USE_HTTPSRR
503
#error "ECH enabled but not HTTPSRR, must be a config error"
504
#endif
505
#endif
506
#ifdef USE_GSASL
507
  FEATURE("gsasl",       NULL,                CURL_VERSION_GSASL),
508
#endif
509
#ifdef HAVE_GSSAPI
510
  FEATURE("GSS-API",     NULL,                CURL_VERSION_GSSAPI),
511
#endif
512
#ifndef CURL_DISABLE_HSTS
513
  FEATURE("HSTS",        NULL,                CURL_VERSION_HSTS),
514
#endif
515
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NGHTTP2)
516
  FEATURE("HTTP2",       NULL,                CURL_VERSION_HTTP2),
517
#endif
518
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HTTP3)
519
  FEATURE("HTTP3",       NULL,                CURL_VERSION_HTTP3),
520
#endif
521
#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
522
  !defined(CURL_DISABLE_HTTP)
523
  FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
524
#endif
525
#ifdef USE_HTTPSRR
526
  FEATURE("HTTPSRR",     NULL,                0),
527
#endif
528
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
529
  FEATURE("IDN",         idn_present,         CURL_VERSION_IDN),
530
#endif
531
#ifdef USE_IPV6
532
  FEATURE("IPv6",        NULL,                CURL_VERSION_IPV6),
533
#endif
534
#ifdef USE_KERBEROS5
535
  FEATURE("Kerberos",    NULL,                CURL_VERSION_KERBEROS5),
536
#endif
537
#if (SIZEOF_CURL_OFF_T > 4) && \
538
    ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
539
  FEATURE("Largefile",   NULL,                CURL_VERSION_LARGEFILE),
540
#endif
541
#ifdef HAVE_LIBZ
542
  FEATURE("libz",        NULL,                CURL_VERSION_LIBZ),
543
#endif
544
#ifdef CURL_WITH_MULTI_SSL
545
  FEATURE("MultiSSL",    NULL,                CURL_VERSION_MULTI_SSL),
546
#endif
547
#ifdef USE_NTLM
548
  FEATURE("NTLM",        NULL,                CURL_VERSION_NTLM),
549
#endif
550
#ifdef USE_LIBPSL
551
  FEATURE("PSL",         NULL,                CURL_VERSION_PSL),
552
#endif
553
#ifdef USE_APPLE_SECTRUST
554
  FEATURE("AppleSecTrust", NULL,              0),
555
#endif
556
#ifdef USE_SPNEGO
557
  FEATURE("SPNEGO",      NULL,                CURL_VERSION_SPNEGO),
558
#endif
559
#ifdef USE_SSL
560
  FEATURE("SSL",         NULL,                CURL_VERSION_SSL),
561
#endif
562
#ifdef USE_SSLS_EXPORT
563
  FEATURE("SSLS-EXPORT", NULL,                0),
564
#endif
565
#ifdef USE_WINDOWS_SSPI
566
  FEATURE("SSPI",        NULL,                CURL_VERSION_SSPI),
567
#endif
568
#ifdef GLOBAL_INIT_IS_THREADSAFE
569
  FEATURE("threadsafe",  NULL,                CURL_VERSION_THREADSAFE),
570
#endif
571
#ifdef USE_TLS_SRP
572
  FEATURE("TLS-SRP",     NULL,                CURL_VERSION_TLSAUTH_SRP),
573
#endif
574
#ifdef CURLDEBUG
575
  FEATURE("TrackMemory", NULL,                CURL_VERSION_CURLDEBUG),
576
#endif
577
#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE)
578
  FEATURE("Unicode",     NULL,                CURL_VERSION_UNICODE),
579
#endif
580
#ifdef USE_UNIX_SOCKETS
581
  FEATURE("UnixSockets", NULL,                CURL_VERSION_UNIX_SOCKETS),
582
#endif
583
#ifdef HAVE_ZSTD
584
  FEATURE("zstd",        NULL,                CURL_VERSION_ZSTD),
585
#endif
586
  {NULL,                 NULL,                0}
587
};
588
589
static const char *feature_names[sizeof(features_table) /
590
                                 sizeof(features_table[0])] = {NULL};
591
592
593
static curl_version_info_data version_info = {
594
  CURLVERSION_NOW,
595
  LIBCURL_VERSION,
596
  LIBCURL_VERSION_NUM,
597
  CURL_OS, /* as found by configure or set by hand at build-time */
598
  0,    /* features bitmask is built at runtime */
599
  NULL, /* ssl_version */
600
  0,    /* ssl_version_num, this is kept at zero */
601
  NULL, /* zlib_version */
602
  supported_protocols,
603
  NULL, /* c-ares version */
604
  0,    /* c-ares version numerical */
605
  NULL, /* libidn version */
606
  0,    /* iconv version */
607
  NULL, /* ssh lib version */
608
  0,    /* brotli_ver_num */
609
  NULL, /* brotli version */
610
  0,    /* nghttp2 version number */
611
  NULL, /* nghttp2 version string */
612
  NULL, /* quic library string */
613
#ifdef CURL_CA_BUNDLE
614
  CURL_CA_BUNDLE, /* cainfo */
615
#else
616
  NULL,
617
#endif
618
#ifdef CURL_CA_PATH
619
  CURL_CA_PATH,  /* capath */
620
#else
621
  NULL,
622
#endif
623
  0,    /* zstd_ver_num */
624
  NULL, /* zstd version */
625
  NULL, /* Hyper version */
626
  NULL, /* gsasl version */
627
  feature_names,
628
  NULL  /* rtmp version */
629
};
630
631
curl_version_info_data *curl_version_info(CURLversion stamp)
632
19
{
633
19
  size_t n;
634
19
  const struct feat *p;
635
19
  int features = 0;
636
637
#ifdef USE_SSH
638
  static char ssh_buf[80];  /* 'ssh_buffer' clashes with libssh/libssh.h */
639
#endif
640
19
#ifdef USE_SSL
641
#ifdef CURL_WITH_MULTI_SSL
642
  static char ssl_buffer[200];
643
#else
644
19
  static char ssl_buffer[80];
645
19
#endif
646
19
#endif
647
#ifdef HAVE_BROTLI
648
  static char brotli_buffer[80];
649
#endif
650
19
#ifdef HAVE_ZSTD
651
19
  static char zstd_buffer[80];
652
19
#endif
653
654
19
  (void)stamp;
655
656
19
#ifdef USE_SSL
657
19
  Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
658
19
  version_info.ssl_version = ssl_buffer;
659
19
#endif
660
661
19
#ifdef HAVE_LIBZ
662
19
  version_info.libz_version = zlibVersion();
663
  /* libz left NULL if non-existing */
664
19
#endif
665
#ifdef USE_ARES
666
  {
667
    int aresnum;
668
    version_info.ares = ares_version(&aresnum);
669
    version_info.ares_num = aresnum;
670
  }
671
#endif
672
#ifdef USE_LIBIDN2
673
  /* This returns a version string if we use the given version or later,
674
     otherwise it returns NULL */
675
  version_info.libidn = idn2_check_version(IDN2_VERSION);
676
#endif
677
678
#ifdef USE_SSH
679
  Curl_ssh_version(ssh_buf, sizeof(ssh_buf));
680
  version_info.libssh_version = ssh_buf;
681
#endif
682
683
#ifdef HAVE_BROTLI
684
  version_info.brotli_ver_num = BrotliDecoderVersion();
685
  brotli_version(brotli_buffer, sizeof(brotli_buffer));
686
  version_info.brotli_version = brotli_buffer;
687
#endif
688
689
19
#ifdef HAVE_ZSTD
690
19
  version_info.zstd_ver_num = (unsigned int)ZSTD_versionNumber();
691
19
  zstd_version(zstd_buffer, sizeof(zstd_buffer));
692
19
  version_info.zstd_version = zstd_buffer;
693
19
#endif
694
695
#ifdef USE_NGHTTP2
696
  {
697
    nghttp2_info *h2 = nghttp2_version(0);
698
    version_info.nghttp2_ver_num = (unsigned int)h2->version_num;
699
    version_info.nghttp2_version = h2->version_str;
700
  }
701
#endif
702
703
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HTTP3)
704
  {
705
    static char quicbuffer[80];
706
    Curl_quic_ver(quicbuffer, sizeof(quicbuffer));
707
    version_info.quic_version = quicbuffer;
708
  }
709
#endif
710
711
#ifdef USE_GSASL
712
  {
713
    version_info.gsasl_version = gsasl_check_version(NULL);
714
  }
715
#endif
716
717
  /* Get available features, build bitmask and names array. */
718
19
  n = 0;
719
266
  for(p = features_table; p->name; p++)
720
247
    if(!p->present || p->present(&version_info)) {
721
247
      features |= p->bitmask;
722
247
      feature_names[n++] = p->name;
723
247
    }
724
725
19
  feature_names[n] = NULL;  /* Terminate array. */
726
19
  version_info.features = features;
727
728
#ifdef USE_LIBRTMP
729
  {
730
    static char rtmp_version[30];
731
    Curl_rtmp_version(rtmp_version, sizeof(rtmp_version));
732
    version_info.rtmp_version = rtmp_version;
733
  }
734
#endif
735
736
19
  return &version_info;
737
19
}