source: trunk/src/network/ssl/qsslsocket_openssl_symbols.cpp@ 795

Last change on this file since 795 was 788, checked in by Dmitry A. Kuminov, 15 years ago

network: Added OpenSSL support (closes #167).

File size: 36.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42
43#include "qsslsocket_openssl_symbols_p.h"
44
45#include <QtCore/qlibrary.h>
46#include <QtCore/qmutex.h>
47#include <private/qmutexpool_p.h>
48#include <QtCore/qdatetime.h>
49#if defined(Q_OS_UNIX)
50#include <QtCore/qdir.h>
51#endif
52
53QT_BEGIN_NAMESPACE
54
55/*
56 Note to maintainer:
57 -------------------
58
59 We load OpenSSL symbols dynamically. Because symbols are known to
60 disappear, and signatures sometimes change, between releases, we need to
61 be careful about how this is done. To ensure we don't end up dereferencing
62 null function pointers, and continue running even if certain functions are
63 missing, we define helper functions for each of the symbols we load from
64 OpenSSL, all prefixed with "q_" (declared in
65 qsslsocket_openssl_symbols_p.h). So instead of calling SSL_connect
66 directly, we call q_SSL_connect, which is a function that checks if the
67 actual SSL_connect fptr is null, and returns a failure if it is, or calls
68 SSL_connect if it isn't.
69
70 This requires a somewhat tedious process of declaring each function we
71 want to call in OpenSSL thrice: once with the q_, in _p.h, once using the
72 DEFINEFUNC macros below, and once in the function that actually resolves
73 the symbols, below the DEFINEFUNC declarations below.
74
75 There's one DEFINEFUNC macro declared for every number of arguments
76 exposed by OpenSSL (feel free to extend when needed). The easiest thing to
77 do is to find an existing entry that matches the arg count of the function
78 you want to import, and do the same.
79
80 The first macro arg is the function return type. The second is the
81 verbatim name of the function/symbol. Then follows a list of N pairs of
82 argument types with a variable name, and just the variable name (char *a,
83 a, char *b, b, etc). Finally there's two arguments - a suitable return
84 statement for the error case (for an int function, return 0 or return -1
85 is usually right). Then either just "return" or DUMMYARG, the latter being
86 for void functions.
87
88 Note: Take into account that these macros and declarations are processed
89 at compile-time, and the result depends on the OpenSSL headers the
90 compiling host has installed, but the symbols are resolved at run-time,
91 possibly with a different version of OpenSSL.
92*/
93
94#ifdef SSLEAY_MACROS
95DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
96#endif
97DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
98DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
99DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
100DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
101DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
102DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
103DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return)
104DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return)
105DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
106DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
107DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
108DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
109DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
110DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
111DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
112DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG)
113#if OPENSSL_VERSION_NUMBER < 0x00908000L
114DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, unsigned char **b, b, long c, c, return 0, return)
115#else // 0.9.8 broke SC and BC by changing this signature.
116DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return)
117#endif
118DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return)
119DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
120DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
121DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
122DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
123DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return)
124DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return)
125DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return)
126DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return)
127DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return)
128DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return)
129DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
130#ifdef SSLEAY_MACROS
131DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
132DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
133#else
134DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
135DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
136DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
137DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
138#endif
139DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
140DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
141DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return)
142DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return)
143DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG)
144DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
145DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
146DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
147DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
148#if OPENSSL_VERSION_NUMBER >= 0x10000000L
149DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
150DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
151#else
152DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
153DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
154#endif
155DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
156DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
157DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
158DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
159#if OPENSSL_VERSION_NUMBER >= 0x00908000L
160// 0.9.8 broke SC and BC by changing this function's signature.
161DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
162#else
163DEFINEFUNC(int, SSL_CTX_check_private_key, SSL_CTX *a, a, return -1, return)
164#endif
165DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
166DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
167#if OPENSSL_VERSION_NUMBER >= 0x10000000L
168DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return)
169#else
170DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return)
171#endif
172DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
173DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
174DEFINEFUNC3(void, SSL_CTX_set_verify, SSL_CTX *a, a, int b, b, int (*c)(int, X509_STORE_CTX *), c, return, DUMMYARG)
175DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUMMYARG)
176DEFINEFUNC2(int, SSL_CTX_use_certificate, SSL_CTX *a, a, X509 *b, b, return -1, return)
177DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
178DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return)
179DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return)
180DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
181DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
182#if OPENSSL_VERSION_NUMBER >= 0x00908000L
183// 0.9.8 broke SC and BC by changing this function's signature.
184DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return)
185#else
186DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, SSL *a, a, return 0, return)
187#endif
188#if OPENSSL_VERSION_NUMBER >= 0x10000000L
189DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
190#else
191DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
192#endif
193DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
194DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
195DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
196#if OPENSSL_VERSION_NUMBER >= 0x00908000L
197// 0.9.8 broke SC and BC by changing this function's signature.
198DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
199#else
200DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
201#endif
202DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
203DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
204DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return)
205DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
206DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG)
207DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG)
208DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG)
209DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return)
210#if OPENSSL_VERSION_NUMBER >= 0x10000000L
211DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
212DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
213DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
214DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
215DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
216DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
217DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
218DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
219#else
220DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
221DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
222DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
223DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
224DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
225DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
226DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
227DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
228#endif
229DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
230DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
231#ifndef SSLEAY_MACROS
232DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return)
233#endif
234DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return 0, return)
235DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG)
236DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return 0, return)
237DEFINEFUNC(int, X509_get_ext_count, X509 *a, a, return 0, return)
238DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return 0, return)
239DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
240DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
241DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
242DEFINEFUNC3(char *, X509_NAME_oneline, X509_NAME *a, a, char *b, b, int c, c, return 0, return)
243DEFINEFUNC(EVP_PKEY *, X509_PUBKEY_get, X509_PUBKEY *a, a, return 0, return)
244DEFINEFUNC(void, X509_STORE_free, X509_STORE *a, a, return, DUMMYARG)
245DEFINEFUNC(X509_STORE *, X509_STORE_new, DUMMYARG, DUMMYARG, return 0, return)
246DEFINEFUNC2(int, X509_STORE_add_cert, X509_STORE *a, a, X509 *b, b, return 0, return)
247DEFINEFUNC(void, X509_STORE_CTX_free, X509_STORE_CTX *a, a, return, DUMMYARG)
248DEFINEFUNC4(int, X509_STORE_CTX_init, X509_STORE_CTX *a, a, X509_STORE *b, b, X509 *c, c, STACK_OF(X509) *d, d, return -1, return)
249DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, return -1, return)
250DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return)
251#ifdef SSLEAY_MACROS
252DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
253DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
254DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
255DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
256#endif
257DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
258DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
259
260#ifdef Q_OS_SYMBIAN
261#define RESOLVEFUNC(func, ordinal, lib) \
262 if (!(_q_##func = _q_PTR_##func(lib->resolve(#ordinal)))) \
263 qWarning("QSslSocket: cannot resolve "#func);
264#elif defined(Q_OS_OS2)
265#define RESOLVEFUNC(func) \
266 if (!(_q_##func = _q_PTR_##func(libs.first->resolve("_"#func))) \
267 && !(_q_##func = _q_PTR_##func(libs.second->resolve("_"#func)))) \
268 qWarning("QSslSocket: cannot resolve "#func);
269#else
270#define RESOLVEFUNC(func) \
271 if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
272 && !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \
273 qWarning("QSslSocket: cannot resolve "#func);
274#endif
275
276#if !defined QT_LINKED_OPENSSL
277
278#ifdef QT_NO_LIBRARY
279bool q_resolveOpenSslSymbols()
280{
281 qWarning("QSslSocket: unable to resolve symbols. "
282 "QT_NO_LIBRARY is defined which means runtime resolving of "
283 "libraries won't work.");
284 qWarning("Either compile Qt statically or with support for runtime resolving "
285 "of libraries.");
286 return false;
287}
288#else
289
290# ifdef Q_OS_UNIX
291static bool libGreaterThan(const QString &lhs, const QString &rhs)
292{
293 QStringList lhsparts = lhs.split(QLatin1Char('.'));
294 QStringList rhsparts = rhs.split(QLatin1Char('.'));
295 Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);
296
297 for (int i = 1; i < rhsparts.count(); ++i) {
298 if (lhsparts.count() <= i)
299 // left hand side is shorter, so it's less than rhs
300 return false;
301
302 bool ok = false;
303 int b = 0;
304 int a = lhsparts.at(i).toInt(&ok);
305 if (ok)
306 b = rhsparts.at(i).toInt(&ok);
307 if (ok) {
308 // both toInt succeeded
309 if (a == b)
310 continue;
311 return a > b;
312 } else {
313 // compare as strings;
314 if (lhsparts.at(i) == rhsparts.at(i))
315 continue;
316 return lhsparts.at(i) > rhsparts.at(i);
317 }
318 }
319
320 // they compared strictly equally so far
321 // lhs cannot be less than rhs
322 return true;
323}
324
325static QStringList findAllLibSsl()
326{
327 QStringList paths;
328# ifdef Q_OS_DARWIN
329 paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH"))
330 .split(QLatin1Char(':'), QString::SkipEmptyParts);
331# else
332 paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
333 .split(QLatin1Char(':'), QString::SkipEmptyParts);
334# endif
335 paths << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
336
337 QStringList foundSsls;
338 foreach (const QString &path, paths) {
339 QDir dir = QDir(path);
340 QStringList entryList = dir.entryList(QStringList() << QLatin1String("libssl.*"), QDir::Files);
341
342 qSort(entryList.begin(), entryList.end(), libGreaterThan);
343 foreach (const QString &entry, entryList)
344 foundSsls << path + QLatin1Char('/') + entry;
345 }
346
347 return foundSsls;
348}
349# endif
350
351static QPair<QLibrary*, QLibrary*> loadOpenSsl()
352{
353 QPair<QLibrary*,QLibrary*> pair;
354 pair.first = 0;
355 pair.second = 0;
356
357# ifdef Q_OS_WIN
358 QLibrary *ssleay32 = new QLibrary(QLatin1String("ssleay32"));
359 if (!ssleay32->load()) {
360 // Cannot find ssleay32.dll
361 delete ssleay32;
362 return pair;
363 }
364
365 QLibrary *libeay32 = new QLibrary(QLatin1String("libeay32"));
366 if (!libeay32->load()) {
367 delete ssleay32;
368 delete libeay32;
369 return pair;
370 }
371
372 pair.first = ssleay32;
373 pair.second = libeay32;
374 return pair;
375# elif defined(Q_OS_SYMBIAN)
376 QLibrary *libssl = new QLibrary(QLatin1String("libssl"));
377 if (!libssl->load()) {
378 // Cannot find ssleay32.dll
379 delete libssl;
380 return pair;
381 }
382
383 QLibrary *libcrypto = new QLibrary(QLatin1String("libcrypto"));
384 if (!libcrypto->load()) {
385 delete libcrypto;
386 delete libssl;
387 return pair;
388 }
389
390 pair.first = libssl;
391 pair.second = libcrypto;
392 return pair;
393# elif defined(Q_OS_UNIX)
394 QLibrary *&libssl = pair.first;
395 QLibrary *&libcrypto = pair.second;
396 libssl = new QLibrary;
397 libcrypto = new QLibrary;
398
399 // Try to find the libssl library on the system.
400 //
401 // Up until Qt 4.3, this only searched for the "ssl" library at version -1, that
402 // is, libssl.so on most Unix systems. However, the .so file isn't present in
403 // user installations because it's considered a development file.
404 //
405 // The right thing to do is to load the library at the major version we know how
406 // to work with: the SHLIB_VERSION_NUMBER version (macro defined in opensslv.h)
407 //
408 // However, OpenSSL is a well-known case of binary-compatibility breakage. To
409 // avoid such problems, many system integrators and Linux distributions change
410 // the soname of the binary, letting the full version number be the soname. So
411 // we'll find libssl.so.0.9.7, libssl.so.0.9.8, etc. in the system. For that
412 // reason, we will search a few common paths (see findAllLibSsl() above) in hopes
413 // we find one that works.
414 //
415 // It is important, however, to try the canonical name and the unversioned name
416 // without going through the loop. By not specifying a path, we let the system
417 // dlopen(3) function determine it for us. This will include any DT_RUNPATH or
418 // DT_RPATH tags on our library header as well as other system-specific search
419 // paths. See the man page for dlopen(3) on your system for more information.
420
421#ifdef Q_OS_OPENBSD
422 libcrypto->setLoadHints(QLibrary::ExportExternalSymbolsHint);
423#endif
424#ifdef SHLIB_VERSION_NUMBER
425 // first attempt: the canonical name is libssl.so.<SHLIB_VERSION_NUMBER>
426 libssl->setFileNameAndVersion(QLatin1String("ssl"), QLatin1String(SHLIB_VERSION_NUMBER));
427 libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER));
428 if (libcrypto->load() && libssl->load()) {
429 // libssl.so.<SHLIB_VERSION_NUMBER> and libcrypto.so.<SHLIB_VERSION_NUMBER> found
430 return pair;
431 } else {
432 libssl->unload();
433 libcrypto->unload();
434 }
435#endif
436
437 // second attempt: find the development files libssl.so and libcrypto.so
438 libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
439 libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1);
440 if (libcrypto->load() && libssl->load()) {
441 // libssl.so.0 and libcrypto.so.0 found
442 return pair;
443 } else {
444 libssl->unload();
445 libcrypto->unload();
446 }
447
448 // third attempt: loop on the most common library paths and find libssl
449 QStringList sslList = findAllLibSsl();
450 foreach (const QString &ssl, sslList) {
451 QString crypto = ssl;
452 crypto.replace(QLatin1String("ssl"), QLatin1String("crypto"));
453 libssl->setFileNameAndVersion(ssl, -1);
454 libcrypto->setFileNameAndVersion(crypto, -1);
455 if (libcrypto->load() && libssl->load()) {
456 // libssl.so.0 and libcrypto.so.0 found
457 return pair;
458 } else {
459 libssl->unload();
460 libcrypto->unload();
461 }
462 }
463
464 // failed to load anything
465 delete libssl;
466 delete libcrypto;
467 libssl = libcrypto = 0;
468 return pair;
469# elif defined(Q_OS_OS2)
470 // note: the k* versions of libraries were in use once; support them for
471 // backward compatibility
472 static const char *ssl_dll[] = { "ssl10", "kssl10" };
473 static const char *crypto_dll[] = { "crypto10", "kcrypt10" };
474
475 QLibrary *libssl;
476 for (size_t i = 0; i < sizeof(ssl_dll)/sizeof(ssl_dll[0]); ++i) {
477 libssl = new QLibrary(QLatin1String(ssl_dll[i]));
478 if (libssl->load())
479 break;
480 delete libssl;
481 libssl = 0;
482 }
483 if (!libssl) {
484 return pair;
485 }
486
487 QLibrary *libcrypto;
488 for (size_t i = 0; i < sizeof(crypto_dll)/sizeof(crypto_dll[0]); ++i) {
489 libcrypto = new QLibrary(QLatin1String(crypto_dll[i]));
490 if (libcrypto->load())
491 break;
492 delete libcrypto;
493 libcrypto = 0;
494 }
495 if (!libcrypto) {
496 delete libssl;
497 return pair;
498 }
499
500 pair.first = libssl;
501 pair.second = libcrypto;
502 return pair;
503# else
504 // not implemented for this platform yet
505 return pair;
506# endif
507}
508
509bool q_resolveOpenSslSymbols()
510{
511 static volatile bool symbolsResolved = false;
512 static volatile bool triedToResolveSymbols = false;
513#ifndef QT_NO_THREAD
514 QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init));
515#endif
516 if (symbolsResolved)
517 return true;
518 if (triedToResolveSymbols)
519 return false;
520 triedToResolveSymbols = true;
521
522 QPair<QLibrary *, QLibrary *> libs = loadOpenSsl();
523 if (!libs.first || !libs.second)
524 // failed to load them
525 return false;
526
527#ifdef Q_OS_SYMBIAN
528#ifdef SSLEAY_MACROS
529 RESOLVEFUNC(ASN1_dup, 125, libs.second )
530#endif
531 RESOLVEFUNC(ASN1_INTEGER_get, 48, libs.second )
532 RESOLVEFUNC(ASN1_STRING_data, 71, libs.second )
533 RESOLVEFUNC(ASN1_STRING_length, 76, libs.second )
534 RESOLVEFUNC(BIO_ctrl, 184, libs.second )
535 RESOLVEFUNC(BIO_free, 209, libs.second )
536 RESOLVEFUNC(BIO_new, 222, libs.second )
537 RESOLVEFUNC(BIO_new_mem_buf, 230, libs.second )
538 RESOLVEFUNC(BIO_read, 244, libs.second )
539 RESOLVEFUNC(BIO_s_mem, 251, libs.second )
540 RESOLVEFUNC(BIO_write, 269, libs.second )
541 RESOLVEFUNC(BN_num_bits, 387, libs.second )
542 RESOLVEFUNC(CRYPTO_free, 469, libs.second )
543 RESOLVEFUNC(CRYPTO_num_locks, 500, libs.second )
544 RESOLVEFUNC(CRYPTO_set_id_callback, 513, libs.second )
545 RESOLVEFUNC(CRYPTO_set_locking_callback, 516, libs.second )
546 RESOLVEFUNC(DSA_free, 594, libs.second )
547 RESOLVEFUNC(ERR_error_string, 744, libs.second )
548 RESOLVEFUNC(ERR_get_error, 749, libs.second )
549 RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second )
550 RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second )
551 RESOLVEFUNC(EVP_PKEY_free, 867, libs.second )
552 RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second )
553 RESOLVEFUNC(EVP_PKEY_get1_RSA, 870, libs.second )
554 RESOLVEFUNC(EVP_PKEY_new, 876, libs.second )
555 RESOLVEFUNC(EVP_PKEY_type, 882, libs.second )
556 RESOLVEFUNC(OBJ_nid2sn, 1036, libs.second )
557 RESOLVEFUNC(OBJ_obj2nid, 1037, libs.second )
558#ifdef SSLEAY_MACROS // ### verify
559 RESOLVEFUNC(PEM_ASN1_read_bio, 1180, libs.second )
560#else
561 RESOLVEFUNC(PEM_read_bio_DSAPrivateKey, 1219, libs.second )
562 RESOLVEFUNC(PEM_read_bio_RSAPrivateKey, 1228, libs.second )
563 RESOLVEFUNC(PEM_write_bio_DSAPrivateKey, 1260, libs.second )
564 RESOLVEFUNC(PEM_write_bio_RSAPrivateKey, 1271, libs.second )
565#endif
566 RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY, 1220, libs.second )
567 RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY, 1230, libs.second )
568 RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY, 1261, libs.second )
569 RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY, 1273, libs.second )
570 RESOLVEFUNC(RAND_seed, 1426, libs.second )
571 RESOLVEFUNC(RAND_status, 1429, libs.second )
572 RESOLVEFUNC(RSA_free, 1450, libs.second )
573 RESOLVEFUNC(sk_free, 2571, libs.second )
574 RESOLVEFUNC(sk_num, 2576, libs.second )
575 RESOLVEFUNC(sk_pop_free, 2578, libs.second )
576 RESOLVEFUNC(sk_value, 2585, libs.second )
577 RESOLVEFUNC(SSL_CIPHER_description, 11, libs.first )
578 RESOLVEFUNC(SSL_CTX_check_private_key, 21, libs.first )
579 RESOLVEFUNC(SSL_CTX_ctrl, 22, libs.first )
580 RESOLVEFUNC(SSL_CTX_free, 24, libs.first )
581 RESOLVEFUNC(SSL_CTX_new, 35, libs.first )
582 RESOLVEFUNC(SSL_CTX_set_cipher_list, 40, libs.first )
583 RESOLVEFUNC(SSL_CTX_set_default_verify_paths, 44, libs.first )
584 RESOLVEFUNC(SSL_CTX_set_verify, 56, libs.first )
585 RESOLVEFUNC(SSL_CTX_set_verify_depth, 57, libs.first )
586 RESOLVEFUNC(SSL_CTX_use_certificate, 64, libs.first )
587 RESOLVEFUNC(SSL_CTX_use_certificate_file, 67, libs.first )
588 RESOLVEFUNC(SSL_CTX_use_PrivateKey, 58, libs.first )
589 RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey, 61, libs.first )
590 RESOLVEFUNC(SSL_CTX_use_PrivateKey_file, 60, libs.first )
591 RESOLVEFUNC(SSL_accept, 82, libs.first )
592 RESOLVEFUNC(SSL_clear, 92, libs.first )
593 RESOLVEFUNC(SSL_connect, 93, libs.first )
594 RESOLVEFUNC(SSL_free, 99, libs.first )
595 RESOLVEFUNC(SSL_get_ciphers, 104, libs.first )
596 RESOLVEFUNC(SSL_get_current_cipher, 106, libs.first )
597 RESOLVEFUNC(SSL_get_error, 110, libs.first )
598 RESOLVEFUNC(SSL_get_peer_cert_chain, 117, libs.first )
599 RESOLVEFUNC(SSL_get_peer_certificate, 118, libs.first )
600 RESOLVEFUNC(SSL_get_verify_result, 132, libs.first )
601 RESOLVEFUNC(SSL_library_init, 137, libs.first )
602 RESOLVEFUNC(SSL_load_error_strings, 139, libs.first )
603 RESOLVEFUNC(SSL_new, 140, libs.first )
604 RESOLVEFUNC(SSL_read, 143, libs.first )
605 RESOLVEFUNC(SSL_set_accept_state, 148, libs.first )
606 RESOLVEFUNC(SSL_set_bio, 149, libs.first )
607 RESOLVEFUNC(SSL_set_connect_state, 152, libs.first )
608 RESOLVEFUNC(SSL_shutdown, 173, libs.first )
609 RESOLVEFUNC(SSL_write, 188, libs.first )
610 RESOLVEFUNC(SSLv2_client_method, 192, libs.first )
611 RESOLVEFUNC(SSLv3_client_method, 195, libs.first )
612 RESOLVEFUNC(SSLv23_client_method, 189, libs.first )
613 RESOLVEFUNC(TLSv1_client_method, 198, libs.first )
614 RESOLVEFUNC(SSLv2_server_method, 194, libs.first )
615 RESOLVEFUNC(SSLv3_server_method, 197, libs.first )
616 RESOLVEFUNC(SSLv23_server_method, 191, libs.first )
617 RESOLVEFUNC(TLSv1_server_method, 200, libs.first )
618 RESOLVEFUNC(X509_NAME_oneline, 1830, libs.second )
619 RESOLVEFUNC(X509_PUBKEY_get, 1844, libs.second )
620 RESOLVEFUNC(X509_STORE_free, 1939, libs.second )
621 RESOLVEFUNC(X509_STORE_new, 1942, libs.second )
622 RESOLVEFUNC(X509_STORE_add_cert, 1936, libs.second )
623 RESOLVEFUNC(X509_STORE_CTX_free, 1907, libs.second )
624 RESOLVEFUNC(X509_STORE_CTX_init, 1919, libs.second )
625 RESOLVEFUNC(X509_STORE_CTX_new, 1920, libs.second )
626 RESOLVEFUNC(X509_STORE_CTX_set_purpose, 1931, libs.second )
627 RESOLVEFUNC(X509_cmp, 1992, libs.second )
628#ifndef SSLEAY_MACROS
629 RESOLVEFUNC(X509_dup, 1997, libs.second )
630#endif
631 RESOLVEFUNC(X509_EXTENSION_get_object, 1785, libs.second )
632 RESOLVEFUNC(X509_free, 2001, libs.second )
633 RESOLVEFUNC(X509_get_ext, 2012, libs.second )
634 RESOLVEFUNC(X509_get_ext_count, 2016, libs.second )
635 RESOLVEFUNC(X509_get_ext_d2i, 2017, libs.second )
636 RESOLVEFUNC(X509_get_issuer_name, 2018, libs.second )
637 RESOLVEFUNC(X509_get_subject_name, 2022, libs.second )
638 RESOLVEFUNC(X509_verify_cert, 2069, libs.second )
639 RESOLVEFUNC(d2i_X509, 2309, libs.second )
640 RESOLVEFUNC(i2d_X509, 2489, libs.second )
641#ifdef SSLEAY_MACROS
642 RESOLVEFUNC(i2d_DSAPrivateKey, 2395, libs.second )
643 RESOLVEFUNC(i2d_RSAPrivateKey, 2476, libs.second )
644 RESOLVEFUNC(d2i_DSAPrivateKey, 2220, libs.second )
645 RESOLVEFUNC(d2i_RSAPrivateKey, 2296, libs.second )
646#endif
647 RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf, 1153, libs.second )
648 RESOLVEFUNC(OPENSSL_add_all_algorithms_conf, 1152, libs.second )
649#else // Q_OS_SYMBIAN
650#ifdef SSLEAY_MACROS
651 RESOLVEFUNC(ASN1_dup)
652#endif
653 RESOLVEFUNC(ASN1_INTEGER_get)
654 RESOLVEFUNC(ASN1_STRING_data)
655 RESOLVEFUNC(ASN1_STRING_length)
656 RESOLVEFUNC(BIO_ctrl)
657 RESOLVEFUNC(BIO_free)
658 RESOLVEFUNC(BIO_new)
659 RESOLVEFUNC(BIO_new_mem_buf)
660 RESOLVEFUNC(BIO_read)
661 RESOLVEFUNC(BIO_s_mem)
662 RESOLVEFUNC(BIO_write)
663 RESOLVEFUNC(BN_num_bits)
664 RESOLVEFUNC(CRYPTO_free)
665 RESOLVEFUNC(CRYPTO_num_locks)
666 RESOLVEFUNC(CRYPTO_set_id_callback)
667 RESOLVEFUNC(CRYPTO_set_locking_callback)
668 RESOLVEFUNC(DSA_free)
669 RESOLVEFUNC(ERR_error_string)
670 RESOLVEFUNC(ERR_get_error)
671 RESOLVEFUNC(EVP_des_ede3_cbc)
672 RESOLVEFUNC(EVP_PKEY_assign)
673 RESOLVEFUNC(EVP_PKEY_free)
674 RESOLVEFUNC(EVP_PKEY_get1_DSA)
675 RESOLVEFUNC(EVP_PKEY_get1_RSA)
676 RESOLVEFUNC(EVP_PKEY_new)
677 RESOLVEFUNC(EVP_PKEY_type)
678 RESOLVEFUNC(OBJ_nid2sn)
679 RESOLVEFUNC(OBJ_obj2nid)
680#ifdef SSLEAY_MACROS // ### verify
681 RESOLVEFUNC(PEM_ASN1_read_bio)
682#else
683 RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
684 RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
685 RESOLVEFUNC(PEM_write_bio_DSAPrivateKey)
686 RESOLVEFUNC(PEM_write_bio_RSAPrivateKey)
687#endif
688 RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
689 RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
690 RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY)
691 RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY)
692 RESOLVEFUNC(RAND_seed)
693 RESOLVEFUNC(RAND_status)
694 RESOLVEFUNC(RSA_free)
695 RESOLVEFUNC(sk_free)
696 RESOLVEFUNC(sk_num)
697 RESOLVEFUNC(sk_pop_free)
698 RESOLVEFUNC(sk_value)
699 RESOLVEFUNC(SSL_CIPHER_description)
700 RESOLVEFUNC(SSL_CTX_check_private_key)
701 RESOLVEFUNC(SSL_CTX_ctrl)
702 RESOLVEFUNC(SSL_CTX_free)
703 RESOLVEFUNC(SSL_CTX_new)
704 RESOLVEFUNC(SSL_CTX_set_cipher_list)
705 RESOLVEFUNC(SSL_CTX_set_default_verify_paths)
706 RESOLVEFUNC(SSL_CTX_set_verify)
707 RESOLVEFUNC(SSL_CTX_set_verify_depth)
708 RESOLVEFUNC(SSL_CTX_use_certificate)
709 RESOLVEFUNC(SSL_CTX_use_certificate_file)
710 RESOLVEFUNC(SSL_CTX_use_PrivateKey)
711 RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey)
712 RESOLVEFUNC(SSL_CTX_use_PrivateKey_file)
713 RESOLVEFUNC(SSL_accept)
714 RESOLVEFUNC(SSL_clear)
715 RESOLVEFUNC(SSL_connect)
716 RESOLVEFUNC(SSL_free)
717 RESOLVEFUNC(SSL_get_ciphers)
718 RESOLVEFUNC(SSL_get_current_cipher)
719 RESOLVEFUNC(SSL_get_error)
720 RESOLVEFUNC(SSL_get_peer_cert_chain)
721 RESOLVEFUNC(SSL_get_peer_certificate)
722 RESOLVEFUNC(SSL_get_verify_result)
723 RESOLVEFUNC(SSL_library_init)
724 RESOLVEFUNC(SSL_load_error_strings)
725 RESOLVEFUNC(SSL_new)
726 RESOLVEFUNC(SSL_read)
727 RESOLVEFUNC(SSL_set_accept_state)
728 RESOLVEFUNC(SSL_set_bio)
729 RESOLVEFUNC(SSL_set_connect_state)
730 RESOLVEFUNC(SSL_shutdown)
731 RESOLVEFUNC(SSL_write)
732 RESOLVEFUNC(SSLv2_client_method)
733 RESOLVEFUNC(SSLv3_client_method)
734 RESOLVEFUNC(SSLv23_client_method)
735 RESOLVEFUNC(TLSv1_client_method)
736 RESOLVEFUNC(SSLv2_server_method)
737 RESOLVEFUNC(SSLv3_server_method)
738 RESOLVEFUNC(SSLv23_server_method)
739 RESOLVEFUNC(TLSv1_server_method)
740 RESOLVEFUNC(X509_NAME_oneline)
741 RESOLVEFUNC(X509_PUBKEY_get)
742 RESOLVEFUNC(X509_STORE_free)
743 RESOLVEFUNC(X509_STORE_new)
744 RESOLVEFUNC(X509_STORE_add_cert)
745 RESOLVEFUNC(X509_STORE_CTX_free)
746 RESOLVEFUNC(X509_STORE_CTX_init)
747 RESOLVEFUNC(X509_STORE_CTX_new)
748 RESOLVEFUNC(X509_STORE_CTX_set_purpose)
749 RESOLVEFUNC(X509_cmp)
750#ifndef SSLEAY_MACROS
751 RESOLVEFUNC(X509_dup)
752#endif
753 RESOLVEFUNC(X509_EXTENSION_get_object)
754 RESOLVEFUNC(X509_free)
755 RESOLVEFUNC(X509_get_ext)
756 RESOLVEFUNC(X509_get_ext_count)
757 RESOLVEFUNC(X509_get_ext_d2i)
758 RESOLVEFUNC(X509_get_issuer_name)
759 RESOLVEFUNC(X509_get_subject_name)
760 RESOLVEFUNC(X509_verify_cert)
761 RESOLVEFUNC(d2i_X509)
762 RESOLVEFUNC(i2d_X509)
763#ifdef SSLEAY_MACROS
764 RESOLVEFUNC(i2d_DSAPrivateKey)
765 RESOLVEFUNC(i2d_RSAPrivateKey)
766 RESOLVEFUNC(d2i_DSAPrivateKey)
767 RESOLVEFUNC(d2i_RSAPrivateKey)
768#endif
769 RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
770 RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
771#endif // Q_OS_SYMBIAN
772 symbolsResolved = true;
773 delete libs.first;
774 delete libs.second;
775 return true;
776}
777#endif // QT_NO_LIBRARY
778
779#else // !defined QT_LINKED_OPENSSL
780
781bool q_resolveOpenSslSymbols()
782{
783#ifdef QT_NO_OPENSSL
784 return false;
785#endif
786 return true;
787}
788#endif // !defined QT_LINKED_OPENSSL
789
790//==============================================================================
791// contributed by Jay Case of Sarvega, Inc.; http://sarvega.com/
792// Based on X509_cmp_time() for intitial buffer hacking.
793//==============================================================================
794QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
795{
796 char lBuffer[24];
797 char *pBuffer = lBuffer;
798
799 size_t lTimeLength = aTime->length;
800 char *pString = (char *) aTime->data;
801
802 if (aTime->type == V_ASN1_UTCTIME) {
803 if ((lTimeLength < 11) || (lTimeLength > 17))
804 return QDateTime();
805
806 memcpy(pBuffer, pString, 10);
807 pBuffer += 10;
808 pString += 10;
809 } else {
810 if (lTimeLength < 13)
811 return QDateTime();
812
813 memcpy(pBuffer, pString, 12);
814 pBuffer += 12;
815 pString += 12;
816 }
817
818 if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) {
819 *pBuffer++ = '0';
820 *pBuffer++ = '0';
821 } else {
822 *pBuffer++ = *pString++;
823 *pBuffer++ = *pString++;
824 // Skip any fractional seconds...
825 if (*pString == '.') {
826 pString++;
827 while ((*pString >= '0') && (*pString <= '9'))
828 pString++;
829 }
830 }
831
832 *pBuffer++ = 'Z';
833 *pBuffer++ = '\0';
834
835 time_t lSecondsFromUCT;
836 if (*pString == 'Z') {
837 lSecondsFromUCT = 0;
838 } else {
839 if ((*pString != '+') && (*pString != '-'))
840 return QDateTime();
841
842 lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
843 lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0');
844 lSecondsFromUCT *= 60;
845 if (*pString == '-')
846 lSecondsFromUCT = -lSecondsFromUCT;
847 }
848
849 tm lTime;
850 lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
851 lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
852 lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
853 lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
854 lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
855 lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
856 if (lTime.tm_year < 50)
857 lTime.tm_year += 100; // RFC 2459
858
859 QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
860 QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
861 QDateTime result(resDate, resTime, Qt::UTC);
862 result = result.addSecs(lSecondsFromUCT);
863 return result;
864}
865
866QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.