1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2012, 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 http://curl.haxx.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 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#include <curl/curl.h>
26#include "urldata.h"
27#include "sslgen.h"
28
29#define _MPRINTF_REPLACE /* use the internal *printf() functions */
30#include <curl/mprintf.h>
31
32#ifdef USE_ARES
33#  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
34     (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
35#    define CARES_STATICLIB
36#  endif
37#  include <ares.h>
38#endif
39
40#ifdef USE_LIBIDN
41#include <stringprep.h>
42#endif
43
44#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
45#include <iconv.h>
46#endif
47
48#ifdef USE_LIBRTMP
49#include <librtmp/rtmp.h>
50#endif
51
52#ifdef USE_LIBSSH2
53#include <libssh2.h>
54#endif
55
56#ifdef HAVE_LIBSSH2_VERSION
57/* get it run-time if possible */
58#define CURL_LIBSSH2_VERSION libssh2_version(0)
59#else
60/* use build-time if run-time not possible */
61#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
62#endif
63
64char *curl_version(void)
65{
66  static char version[200];
67  char *ptr = version;
68  size_t len;
69  size_t left = sizeof(version);
70
71  strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION);
72  len = strlen(ptr);
73  left -= len;
74  ptr += len;
75
76  if(left > 1) {
77    len = Curl_ssl_version(ptr + 1, left - 1);
78
79    if(len > 0) {
80      *ptr = ' ';
81      left -= ++len;
82      ptr += len;
83    }
84  }
85
86#ifdef HAVE_LIBZ
87  len = snprintf(ptr, left, " zlib/%s", zlibVersion());
88  left -= len;
89  ptr += len;
90#endif
91#ifdef USE_ARES
92  /* this function is only present in c-ares, not in the original ares */
93  len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL));
94  left -= len;
95  ptr += len;
96#endif
97#ifdef USE_LIBIDN
98  if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
99    len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL));
100    left -= len;
101    ptr += len;
102  }
103#endif
104#ifdef USE_WIN32_IDN
105  len = snprintf(ptr, left, " WinIDN");
106  left -= len;
107  ptr += len;
108#endif
109#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
110#ifdef _LIBICONV_VERSION
111  len = snprintf(ptr, left, " iconv/%d.%d",
112                 _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
113#else
114  /* version unknown */
115  len = snprintf(ptr, left, " iconv");
116#endif /* _LIBICONV_VERSION */
117  left -= len;
118  ptr += len;
119#endif
120#ifdef USE_LIBSSH2
121  len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
122  left -= len;
123  ptr += len;
124#endif
125#ifdef USE_LIBRTMP
126  {
127    char suff[2];
128    if(RTMP_LIB_VERSION & 0xff) {
129      suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
130      suff[1] = '\0';
131    }
132    else
133      suff[0] = '\0';
134
135    snprintf(ptr, left, " librtmp/%d.%d%s",
136             RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
137             suff);
138/*
139  If another lib version is added below this one, this code would
140  also have to do:
141
142    len = what snprintf() returned
143
144    left -= len;
145    ptr += len;
146*/
147  }
148#endif
149
150  return version;
151}
152
153/* data for curl_version_info
154
155   Keep the list sorted alphabetically. It is also written so that each
156   protocol line has its own #if line to make things easier on the eye.
157 */
158
159static const char * const protocols[] = {
160#ifndef CURL_DISABLE_DICT
161  "dict",
162#endif
163#ifndef CURL_DISABLE_FILE
164  "file",
165#endif
166#ifndef CURL_DISABLE_FTP
167  "ftp",
168#endif
169#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
170  "ftps",
171#endif
172#ifndef CURL_DISABLE_GOPHER
173  "gopher",
174#endif
175#ifndef CURL_DISABLE_HTTP
176  "http",
177#endif
178#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
179  "https",
180#endif
181#ifndef CURL_DISABLE_IMAP
182  "imap",
183#endif
184#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
185  "imaps",
186#endif
187#ifndef CURL_DISABLE_LDAP
188  "ldap",
189#if !defined(CURL_DISABLE_LDAPS) && \
190    ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
191     (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
192  "ldaps",
193#endif
194#endif
195#ifndef CURL_DISABLE_POP3
196  "pop3",
197#endif
198#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
199  "pop3s",
200#endif
201#ifdef USE_LIBRTMP
202  "rtmp",
203#endif
204#ifndef CURL_DISABLE_RTSP
205  "rtsp",
206#endif
207#ifdef USE_LIBSSH2
208  "scp",
209#endif
210#ifdef USE_LIBSSH2
211  "sftp",
212#endif
213#ifndef CURL_DISABLE_SMTP
214  "smtp",
215#endif
216#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
217  "smtps",
218#endif
219#ifndef CURL_DISABLE_TELNET
220  "telnet",
221#endif
222#ifndef CURL_DISABLE_TFTP
223  "tftp",
224#endif
225
226  NULL
227};
228
229static curl_version_info_data version_info = {
230  CURLVERSION_NOW,
231  LIBCURL_VERSION,
232  LIBCURL_VERSION_NUM,
233  OS, /* as found by configure or set by hand at build-time */
234  0 /* features is 0 by default */
235#ifdef ENABLE_IPV6
236  | CURL_VERSION_IPV6
237#endif
238#ifdef HAVE_KRB4
239  | CURL_VERSION_KERBEROS4
240#endif
241#ifdef USE_SSL
242  | CURL_VERSION_SSL
243#endif
244#ifdef USE_NTLM
245  | CURL_VERSION_NTLM
246#endif
247#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
248  | CURL_VERSION_NTLM_WB
249#endif
250#ifdef USE_WINDOWS_SSPI
251  | CURL_VERSION_SSPI
252#endif
253#ifdef HAVE_LIBZ
254  | CURL_VERSION_LIBZ
255#endif
256#ifdef USE_HTTP_NEGOTIATE
257  | CURL_VERSION_GSSNEGOTIATE
258#endif
259#ifdef DEBUGBUILD
260  | CURL_VERSION_DEBUG
261#endif
262#ifdef CURLDEBUG
263  | CURL_VERSION_CURLDEBUG
264#endif
265#ifdef CURLRES_ASYNCH
266  | CURL_VERSION_ASYNCHDNS
267#endif
268#ifdef HAVE_SPNEGO
269  | CURL_VERSION_SPNEGO
270#endif
271#if (CURL_SIZEOF_CURL_OFF_T > 4) && \
272    ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
273  | CURL_VERSION_LARGEFILE
274#endif
275#if defined(CURL_DOES_CONVERSIONS)
276  | CURL_VERSION_CONV
277#endif
278#if defined(USE_TLS_SRP)
279  | CURL_VERSION_TLSAUTH_SRP
280#endif
281  ,
282  NULL, /* ssl_version */
283  0,    /* ssl_version_num, this is kept at zero */
284  NULL, /* zlib_version */
285  protocols,
286  NULL, /* c-ares version */
287  0,    /* c-ares version numerical */
288  NULL, /* libidn version */
289  0,    /* iconv version */
290  NULL, /* ssh lib version */
291};
292
293curl_version_info_data *curl_version_info(CURLversion stamp)
294{
295#ifdef USE_LIBSSH2
296  static char ssh_buffer[80];
297#endif
298
299#ifdef USE_SSL
300  static char ssl_buffer[80];
301  Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
302  version_info.ssl_version = ssl_buffer;
303#endif
304
305#ifdef HAVE_LIBZ
306  version_info.libz_version = zlibVersion();
307  /* libz left NULL if non-existing */
308#endif
309#ifdef USE_ARES
310  {
311    int aresnum;
312    version_info.ares = ares_version(&aresnum);
313    version_info.ares_num = aresnum;
314  }
315#endif
316#ifdef USE_LIBIDN
317  /* This returns a version string if we use the given version or later,
318     otherwise it returns NULL */
319  version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION);
320  if(version_info.libidn)
321    version_info.features |= CURL_VERSION_IDN;
322#elif defined(USE_WIN32_IDN)
323  version_info.features |= CURL_VERSION_IDN;
324#endif
325
326#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
327#ifdef _LIBICONV_VERSION
328  version_info.iconv_ver_num = _LIBICONV_VERSION;
329#else
330  /* version unknown */
331  version_info.iconv_ver_num = -1;
332#endif /* _LIBICONV_VERSION */
333#endif
334
335#ifdef USE_LIBSSH2
336  snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
337  version_info.libssh_version = ssh_buffer;
338#endif
339
340  (void)stamp; /* avoid compiler warnings, we don't use this */
341
342  return &version_info;
343}
344