diff options
39 files changed, 1448 insertions, 985 deletions
diff --git a/config.tests/avx512/avx512.cpp b/config.tests/avx512/avx512.cpp index ca1a5d1357..29e88ebf15 100644 --- a/config.tests/avx512/avx512.cpp +++ b/config.tests/avx512/avx512.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the configuration of the Qt Toolkit. @@ -39,15 +39,18 @@ #include <immintrin.h> -#ifndef AVX512WANT -# error ".pro file must define AVX512WANT macro to the AVX-512 feature to be tested" +#ifndef __AVX512F__ +# error "There doesn't seem to be AVX-512 support in this compiler" +#endif +#ifndef WANT_AVX512 +# error ".pro file must define WANT_AVX512 macro to the AVX-512 feature to be tested" #endif // The following checks if __AVXx__ is defined, where x is the value in -// AVX512WANT +// WANT_AVX512 #define HAS2(x) __AVX512 ## x ## __ #define HAS(x) HAS2(x) -#if !HAS(AVX512WANT) +#if !HAS(WANT_AVX512) # error "Feature not supported" #endif @@ -62,36 +65,36 @@ int main(int, char**argv) d = _mm512_loadu_pd((double *)argv + 64); f = _mm512_loadu_ps((float *)argv + 128); -#ifdef __AVX512ER__ +#ifdef WANT_AVX512ER /* AVX512 Exponential and Reciprocal */ f = _mm512_exp2a23_round_ps(f, 8); #endif -#ifdef __AVX512CD__ +#ifdef WANT_AVX512CD /* AVX512 Conflict Detection */ i = _mm512_maskz_conflict_epi32(m, i); #endif -#ifdef __AVX512PF__ +#ifdef WANT_AVX512PF /* AVX512 Prefetch */ _mm512_mask_prefetch_i64scatter_pd(argv, 0xf, i, 2, 2); #endif -#ifdef __AVX512DQ__ +#ifdef WANT_AVX512DQ /* AVX512 Doubleword and Quadword support */ m = _mm512_movepi32_mask(i); #endif -#ifdef __AVX512BW__ +#ifdef WANT_AVX512BW /* AVX512 Byte and Word support */ i = _mm512_mask_loadu_epi8(i, m, argv - 8); #endif -#ifdef __AVX512VL__ +#ifdef WANT_AVX512VL /* AVX512 Vector Length */ __m256i i2 = _mm256_maskz_loadu_epi32(0, argv); _mm256_mask_storeu_epi32(argv + 1, m, i2); #endif -#ifdef __AVX512IFMA__ +#ifdef WANT_AVX512IFMA /* AVX512 Integer Fused Multiply-Add */ i = _mm512_madd52lo_epu64(i, i, i); #endif -#ifdef __AVX512VBMI__ +#ifdef WANT_AVX512VBMI /* AVX512 Vector Byte Manipulation Instructions */ i = _mm512_permutexvar_epi8(i, i); #endif diff --git a/config.tests/avx512/avx512.pro b/config.tests/avx512/avx512.pro index 1edf5e5432..d295f6320c 100644 --- a/config.tests/avx512/avx512.pro +++ b/config.tests/avx512/avx512.pro @@ -7,4 +7,4 @@ value = $$eval($$varname) !defined($$varname, "var"): error("This compiler does not support AVX512") QMAKE_CXXFLAGS += $$value -DEFINES += AVX512WANT=$$AVX512 +DEFINES += WANT_AVX512=$$AVX512 WANT_AVX512$$AVX512 diff --git a/config.tests/common/aesni/aesni.cpp b/config.tests/common/aesni/aesni.cpp deleted file mode 100644 index a177183c72..0000000000 --- a/config.tests/common/aesni/aesni.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <wmmintrin.h> - -int main(int, char**) -{ - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_aesenc_si128(a, a); - __m128i c = _mm_aesdec_si128(a, b); - (void)c; - return 0; -} diff --git a/config.tests/common/aesni/aesni.pro b/config.tests/common/aesni/aesni.pro deleted file mode 100644 index 49cb132ef7..0000000000 --- a/config.tests/common/aesni/aesni.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES = aesni.cpp -!defined(QMAKE_CFLAGS_AESNI, "var"): error("This compiler does not support AES New Instructions") -else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AESNI diff --git a/config.tests/common/rdrnd/rdrnd.cpp b/config.tests/common/rdrnd/rdrnd.cpp deleted file mode 100644 index 597f7257bf..0000000000 --- a/config.tests/common/rdrnd/rdrnd.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <immintrin.h> - -int main(int, char**) -{ - unsigned short us; - unsigned int ui; - if (_rdrand16_step(&us)) - return 1; - if (_rdrand32_step(&ui)) - return 1; -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) - unsigned long long ull; - if (_rdrand64_step(&ull)) - return 1; -#endif - return 0; -} diff --git a/config.tests/common/rdrnd/rdrnd.pro b/config.tests/common/rdrnd/rdrnd.pro deleted file mode 100644 index 37e636dc3f..0000000000 --- a/config.tests/common/rdrnd/rdrnd.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES += rdrnd.cpp -!defined(QMAKE_CFLAGS_RDRND, "var"): error("This compiler does not support the RDRAND instruction") -else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_RDRND diff --git a/config.tests/common/shani/shani.cpp b/config.tests/common/shani/shani.cpp deleted file mode 100644 index 0fe6e87dd8..0000000000 --- a/config.tests/common/shani/shani.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <immintrin.h> - -int main(int, char**) -{ - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_sha1rnds4_epu32(a, a, 0); - __m128i c = _mm_sha1msg1_epu32(a, b); - __m128i d = _mm_sha256msg2_epu32(b, c); - (void)d; - return 0; -} diff --git a/config.tests/common/shani/shani.pro b/config.tests/common/shani/shani.pro deleted file mode 100644 index 278f49ef90..0000000000 --- a/config.tests/common/shani/shani.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES = shani.cpp -!defined(QMAKE_CFLAGS_SHANI, "var"): error("This compiler does not support Secure Hash Algorithm extensions") -else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SHANI diff --git a/config.tests/x86_simd/main.cpp b/config.tests/x86_simd/main.cpp new file mode 100644 index 0000000000..8120cb9d3f --- /dev/null +++ b/config.tests/x86_simd/main.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// All of our supported compilers support <immintrin.h> +#include <immintrin.h> +#define T(x) (QT_COMPILER_SUPPORTS_ ## x) + +#if !defined(__INTEL_COMPILER) && !defined(_MSC_VER) && !defined(NO_ATTRIBUTE) +/* GCC requires attributes for a function */ +# define attribute_target(x) __attribute__((__target__(x))) +#else +# define attribute_target(x) +#endif + +#if T(SSE2) +attribute_target("sse2") void test_sse2() +{ + __m128i a = _mm_setzero_si128(); + _mm_maskmoveu_si128(a, _mm_setzero_si128(), 0); +} +#endif + +#if T(SSE3) +attribute_target("sse3") void test_sse3() +{ + __m128d a = _mm_set1_pd(6.28); + __m128d b = _mm_set1_pd(3.14); + __m128d result = _mm_addsub_pd(a, b); + (void) _mm_movedup_pd(result); +} +#endif + +#if T(SSSE3) +attribute_target("ssse3") void test_ssse3() +{ + __m128i a = _mm_set1_epi32(42); + _mm_abs_epi8(a); + (void) _mm_sign_epi16(a, _mm_set1_epi32(64)); +} +#endif + +#if T(SSE4_1) +attribute_target("sse4.1") void test_sse4_1() +{ + __m128 a = _mm_setzero_ps(); + _mm_ceil_ps(a); + __m128i result = _mm_mullo_epi32(_mm_set1_epi32(42), _mm_set1_epi32(64)); + (void)result; +} +#endif + +#if T(SSE4_2) +attribute_target("sse4.2") void test_sse4_2() +{ + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_set1_epi32(42); + (void) _mm_cmpestrm(a, 16, b, 16, 0); +} +#endif + +#if T(AESNI) +attribute_target("aes,sse4.2") void test_aesni() +{ + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_aesenc_si128(a, a); + __m128i c = _mm_aesdec_si128(a, b); + (void)c; +} +#endif + +#if T(F16C) +attribute_target("f16c") void test_f16c() +{ + __m128i a = _mm_setzero_si128(); + __m128 b = _mm_cvtph_ps(a); + __m256 b256 = _mm256_cvtph_ps(a); + (void) _mm_cvtps_ph(b, 0); + (void) _mm256_cvtps_ph(b256, 0); +} +#endif + +#if T(RDRND) +attribute_target("rdrnd") int test_rdrnd() +{ + unsigned short us; + unsigned int ui; + if (_rdrand16_step(&us)) + return 1; + if (_rdrand32_step(&ui)) + return 1; +# if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + unsigned long long ull; + if (_rdrand64_step(&ull)) + return 1; +# endif +} +#endif + +#if T(SHANI) +attribute_target("sha") void test_shani() +{ + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_sha1rnds4_epu32(a, a, 0); + __m128i c = _mm_sha1msg1_epu32(a, b); + __m128i d = _mm_sha256msg2_epu32(b, c); + (void)d; +} +#endif + +#if T(AVX) +attribute_target("avx") void test_avx() +{ + __m256d a = _mm256_setzero_pd(); + __m256d b = _mm256_set1_pd(42.42); + (void) _mm256_add_pd(a, b); +} +#endif + +#if T(AVX2) +attribute_target("avx2") void test_avx2() +{ + _mm256_zeroall(); + __m256i a = _mm256_setzero_si256(); + __m256i b = _mm256_and_si256(a, a); + (void) _mm256_add_epi8(a, b); +} +#endif + +#if T(AVX512F) +attribute_target("avx512f") void test_avx512f(char *ptr) +{ + /* AVX512 Foundation */ + __mmask16 m = ~1; + __m512i i; + __m512d d; + __m512 f; + i = _mm512_maskz_loadu_epi32(0, ptr); + d = _mm512_loadu_pd((double *)ptr + 64); + f = _mm512_loadu_ps((float *)ptr + 128); + _mm512_mask_storeu_epi64(ptr, m, i); + _mm512_mask_storeu_ps(ptr + 64, m, f); + _mm512_mask_storeu_pd(ptr + 128, m, d); +} +#endif + +#if T(AVX512ER) +attribute_target("avx512er") void test_avx512er() +{ + /* AVX512 Exponential and Reciprocal */ + __m512 f; + f = _mm512_exp2a23_round_ps(f, 8); +} +#endif + +#if T(AVX512CD) +attribute_target("avx512cd") void test_avx512cd() +{ + /* AVX512 Conflict Detection */ + __mmask16 m = ~1; + __m512i i; + i = _mm512_maskz_conflict_epi32(m, i); +} +#endif + +#if T(AVX512PF) +attribute_target("avx512pf") void test_avx512pf(void *ptr) +{ + /* AVX512 Prefetch */ + __m512i i; + __mmask16 m = 0xf; + _mm512_mask_prefetch_i64scatter_pd(ptr, m, i, 2, 2); +} +#endif + +#if T(AVX512DQ) +attribute_target("avx512dq") void test_avx512dq() +{ + /* AVX512 Doubleword and Quadword support */ + __m512i i; + __mmask16 m = ~1; + m = _mm512_movepi32_mask(i); +} +#endif + +#if T(AVX512BW) +attribute_target("avx512bw") void test_avx512bw(char *ptr) +{ + /* AVX512 Byte and Word support */ + __m512i i; + __mmask16 m = ~1; + i = _mm512_mask_loadu_epi8(i, m, ptr - 8); +} +#endif + +#if T(AVX512VL) +attribute_target("avx512vl") void test_avx512vl(char *ptr) +{ + /* AVX512 Vector Length */ + __mmask16 m = ~1; + __m256i i2 = _mm256_maskz_loadu_epi32(0, ptr); + _mm256_mask_storeu_epi32(ptr + 1, m, i2); +} +#endif + +#if T(AVX512IFMA) +attribute_target("avx512ifma") void test_avx512ifma() +{ + /* AVX512 Integer Fused Multiply-Add */ + __m512i i; + i = _mm512_madd52lo_epu64(i, i, i); +} +#endif + +int main() +{ + return 0; +} diff --git a/config.tests/x86_simd/x86_simd.pro b/config.tests/x86_simd/x86_simd.pro new file mode 100644 index 0000000000..5751432980 --- /dev/null +++ b/config.tests/x86_simd/x86_simd.pro @@ -0,0 +1,11 @@ +SOURCES = main.cpp +for (config, SIMD) { + uc = $$upper($$config) + DEFINES += QT_COMPILER_SUPPORTS_$${uc} + + add_cflags { + cflags = QMAKE_CFLAGS_$${uc} + !defined($$cflags, var): error("This compiler does not support $${uc}") + QMAKE_CXXFLAGS += $$eval($$cflags) + } +} diff --git a/configure.json b/configure.json index a5a64565e1..a0b9765d18 100644 --- a/configure.json +++ b/configure.json @@ -218,7 +218,7 @@ }, "testTypeAliases": { - "compile": [ "library", "architecture" ] + "compile": [ "library", "architecture", "x86Simd", "x86SimdAlways" ] }, "tests": { @@ -362,206 +362,88 @@ }, "sse2": { "label": "SSE2 instructions", - "type": "compile", - "test": { - "include": "emmintrin.h", - "main": [ - "__m128i a = _mm_setzero_si128();", - "_mm_maskmoveu_si128(a, _mm_setzero_si128(), 0);" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_SSE2, var): error(\"This compiler does not support SSE2\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2" - ] - } + "type": "x86Simd" }, "sse3": { "label": "SSE3 instructions", - "type": "compile", - "test": { - "include": "pmmintrin.h", - "main": [ - "__m128d a = _mm_set1_pd(6.28);", - "__m128d b = _mm_set1_pd(3.14);", - "__m128d result = _mm_addsub_pd(a, b);", - "(void) _mm_movedup_pd(result);" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_SSE3, var): error(\"This compiler does not support SSE3\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE3" - ] - } + "type": "x86Simd" }, "ssse3": { "label": "SSSE3 instructions", - "type": "compile", - "test": { - "include": "tmmintrin.h", - "main": [ - "__m128i a = _mm_set1_epi32(42);", - "_mm_abs_epi8(a);", - "(void) _mm_sign_epi16(a, _mm_set1_epi32(64));" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_SSSE3, var): error(\"This compiler does not support SSSE3\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSSE3" - ] - } + "type": "x86Simd" }, "sse4_1": { "label": "SSE4.1 instructions", - "type": "compile", - "test": { - "include": "smmintrin.h", - "main": [ - "__m128 a = _mm_setzero_ps();", - "_mm_ceil_ps(a);", - "__m128i result = _mm_mullo_epi32(_mm_set1_epi32(42), _mm_set1_epi32(64));", - "(void)result;" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_SSE4_1, var): error(\"This compiler does not support SSE4.1\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_1" - ] - } + "type": "x86Simd" }, "sse4_2": { "label": "SSE4.2 instructions", - "type": "compile", - "test": { - "include": "nmmintrin.h", - "main": [ - "__m128i a = _mm_setzero_si128();", - "__m128i b = _mm_set1_epi32(42);", - "(void) _mm_cmpestrm(a, 16, b, 16, 0);" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_SSE4_2, var): error(\"This compiler does not support SSE4.2\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_2" - ] - } + "type": "x86Simd" }, "aesni": { "label": "AES new instructions", - "type": "compile", - "test": "common/aesni" + "type": "x86Simd" }, "f16c": { "label": "F16C instructions", - "type": "compile", - "test": { - "include": "immintrin.h", - "main": [ - "__m128i a = _mm_setzero_si128();", - "__m128 b = _mm_cvtph_ps(a);", - "__m256 b256 = _mm256_cvtph_ps(a);", - "(void) _mm_cvtps_ph(b, 0);", - "(void) _mm256_cvtps_ph(b256, 0);" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_F16C, var): error(\"This compiler does not support F16C\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_F16C" - ] - } + "type": "x86Simd" }, "rdrnd": { "label": "RDRAND instruction", - "type": "compile", - "test": "common/rdrnd" + "type": "x86Simd" }, "shani": { "label": "SHA new instructions", - "type": "compile", - "test": "common/shani" + "type": "x86Simd" }, "avx": { "label": "AVX instructions", - "type": "compile", - "test": { - "include": "immintrin.h", - "main": [ - "__m256d a = _mm256_setzero_pd();", - "__m256d b = _mm256_set1_pd(42.42);", - "(void) _mm256_add_pd(a, b);" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_AVX, var): error(\"This compiler does not support AVX\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX" - ] - } + "type": "x86Simd" }, "avx2": { "label": "AVX2 instructions", - "type": "compile", - "test": { - "include": "immintrin.h", - "main": [ - "// AVX", - "_mm256_zeroall();", - "__m256i a = _mm256_setzero_si256();", - "// AVX2", - "__m256i b = _mm256_and_si256(a, a);", - "(void) _mm256_add_epi8(a, b);" - ], - "qmake": [ - "!defined(QMAKE_CFLAGS_AVX2, var): error(\"This compiler does not support AVX2\")", - "QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX2" - ] - } + "type": "x86Simd" }, "avx512f": { "label": "AVX512 F instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=F" + "type": "x86Simd" }, "avx512er": { "label": "AVX512 ER instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=ER" + "type": "x86Simd" }, "avx512cd": { "label": "AVX512 CD instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=CD" + "type": "x86Simd" }, "avx512pf": { "label": "AVX512 PF instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=PF" + "type": "x86Simd" }, "avx512dq": { "label": "AVX512 DQ instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=DQ" + "type": "x86Simd" }, "avx512bw": { "label": "AVX512 BW instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=BW" + "type": "x86Simd" }, "avx512vl": { "label": "AVX512 VL instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=VL" + "type": "x86Simd" }, "avx512ifma": { "label": "AVX512 IFMA instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=IFMA" + "type": "x86Simd" }, "avx512vbmi": { "label": "AVX512 VBMI instructions", - "type": "compile", - "test": "avx512", - "args": "AVX512=VBMI" + "type": "x86Simd" + }, + "x86SimdAlways": { + "label": "Intrinsics without -mXXX argument", + "type": "x86SimdAlways", + "test": "x86_simd" }, "mips_dsp": { "label": "MIPS DSP instructions", @@ -1111,6 +993,14 @@ { "type": "define", "name": "QT_COMPILER_SUPPORTS_SHA", "value": 1 } ] }, + "x86SimdAlways": { + "label": "Intrinsics without -mXXX option", + "condition": "(arch.i386 || arch.x86_64) && tests.x86SimdAlways", + "output": [ + "privateConfig", + { "type": "define", "name": "QT_COMPILER_SUPPORTS_SIMD_ALWAYS", "value": 1 } + ] + }, "mips_dsp": { "label": "DSP", "condition": "arch.mips && tests.mips_dsp", @@ -1399,6 +1289,11 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5 }, { "type": "feature", + "args": "x86SimdAlways", + "condition": "(arch.i386 || arch.x86_64) && !config.msvc" + }, + { + "type": "feature", "args": "neon", "condition": "arch.arm || arch.arm64" }, diff --git a/configure.pri b/configure.pri index 83c0dee141..8ce4aea9ca 100644 --- a/configure.pri +++ b/configure.pri @@ -395,6 +395,29 @@ defineTest(qtConfTest_buildParts) { return(true) } +defineTest(qtConfTest_x86Simd) { + simd = $$section(1, ".", -1) # last component + $${1}.args = CONFIG+=add_cflags DEFINES+=NO_ATTRIBUTE SIMD=$$simd + $${1}.test = x86_simd + qtConfTest_compile($${1}) +} + +defineTest(qtConfTest_x86SimdAlways) { + configs = + fpfx = $${currentConfig}.features + tpfx = $${currentConfig}.tests + + # Make a list of all passing features whose tests have type=x86Simd + for (f, $${tpfx}._KEYS_) { + !equals($${tpfx}.$${f}.type, "x86Simd"): \ + next() + qtConfCheckFeature($$f) + equals($${fpfx}.$${f}.available, true): configs += $$f + } + $${1}.literal_args = $$system_quote(SIMD=$$join(configs, " ")) + qtConfTest_compile($${1}) +} + # custom outputs # this reloads the qmakespec as completely as reasonably possible. diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf index 395c0535a9..9f5da91806 100644 --- a/mkspecs/common/msvc-version.conf +++ b/mkspecs/common/msvc-version.conf @@ -82,6 +82,20 @@ greaterThan(QMAKE_MSC_VER, 1909) { MSVC_VER = 15.0 COMPAT_MKSPEC = win32-msvc2017 QMAKE_CXXFLAGS += -Zc:referenceBinding + + # Only Visual Studio 2017 version 15.3 / Visual C++ 19.11 & up have support + # for AVX-512. We enable the switches anyway and let configure check if they + # work. + QMAKE_CFLAGS_AVX512F = -arch:AVX512 + QMAKE_CFLAGS_AVX512ER = -arch:AVX512 + QMAKE_CFLAGS_AVX512CD = -arch:AVX512 + QMAKE_CFLAGS_AVX512PF = -arch:AVX512 + QMAKE_CFLAGS_AVX512DQ = -arch:AVX512 + QMAKE_CFLAGS_AVX512BW = -arch:AVX512 + QMAKE_CFLAGS_AVX512VL = -arch:AVX512 + QMAKE_CFLAGS_AVX512IFMA = -arch:AVX512 + QMAKE_CFLAGS_AVX512VBMI = -arch:AVX512 + # For now permissive fails as soon as UWP API comes into play. In qtbase this # API is used in direct2d, but also in multimedia, positioning and sensors. # We can try again with a later version of Visual Studio. diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index cdaa6329f9..6d8b6ee1a0 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -45,6 +45,7 @@ #include <QtCore/qtextstream.h> #include <QtCore/private/qcore_unix_p.h> +#include <QtCore/private/qlocale_tools_p.h> #include <errno.h> #include <sys/stat.h> @@ -121,6 +122,7 @@ public: inline QByteArray fileSystemType() const; inline QByteArray device() const; inline QByteArray options() const; + inline QByteArray subvolume() const; private: #if defined(Q_OS_BSD4) QT_STATFSBUF *stat_buf; @@ -136,9 +138,36 @@ private: QByteArray m_device; QByteArray m_options; #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) + struct mountinfoent : public mntent { + // Details from proc(5) section from /proc/<pid>/mountinfo: + //(1) mount ID: a unique ID for the mount (may be reused after umount(2)). + int mount_id; + //(2) parent ID: the ID of the parent mount (or of self for the top of the mount tree). +// int parent_id; + //(3) major:minor: the value of st_dev for files on this filesystem (see stat(2)). +// dev_t rdev; + //(4) root: the pathname of the directory in the filesystem which forms the root of this mount. + char *subvolume; + //(5) mount point: the pathname of the mount point relative to the process's root directory. +// char *mnt_dir; // in mntent + //(6) mount options: per-mount options. +// char *mnt_opts; // in mntent + //(7) optional fields: zero or more fields of the form "tag[:value]"; see below. +// int flags; + //(8) separator: the end of the optional fields is marked by a single hyphen. + + //(9) filesystem type: the filesystem type in the form "type[.subtype]". +// char *mnt_type; // in mntent + //(10) mount source: filesystem-specific information or "none". +// char *mnt_fsname; // in mntent + //(11) super options: per-superblock options. + char *superopts; + }; + FILE *fp; - mntent mnt; QByteArray buffer; + mountinfoent mnt; + bool usingMountinfo; #elif defined(Q_OS_HAIKU) BVolumeRoster m_volumeRoster; @@ -239,6 +268,10 @@ inline QByteArray QStorageIterator::options() const return QByteArray(); } +inline QByteArray QStorageIterator::subvolume() const +{ + return QByteArray(); +} #elif defined(Q_OS_SOLARIS) static const char pathMounted[] = "/etc/mnttab"; @@ -280,6 +313,10 @@ inline QByteArray QStorageIterator::device() const return QByteArray(mnt.mnt_mntopts); } +inline QByteArray QStorageIterator::subvolume() const +{ + return QByteArray(); +} #elif defined(Q_OS_ANDROID) static const QLatin1String pathMounted("/proc/mounts"); @@ -337,6 +374,10 @@ inline QByteArray QStorageIterator::options() const return m_options; } +inline QByteArray QStorageIterator::subvolume() const +{ + return QByteArray(); +} #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) static const char pathMounted[] = "/etc/mtab"; @@ -346,13 +387,28 @@ static const int bufferSize = 1024; // 2 paths (mount point+device) and metainfo inline QStorageIterator::QStorageIterator() : buffer(QByteArray(bufferSize, 0)) { - fp = ::setmntent(pathMounted, "r"); + fp = nullptr; + +#ifdef Q_OS_LINUX + // first, try to open /proc/self/mountinfo, which has more details + fp = ::fopen("/proc/self/mountinfo", "re"); +#endif + if (fp) { + usingMountinfo = true; + } else { + usingMountinfo = false; + fp = ::setmntent(pathMounted, "r"); + } } inline QStorageIterator::~QStorageIterator() { - if (fp) - ::endmntent(fp); + if (fp) { + if (usingMountinfo) + ::fclose(fp); + else + ::endmntent(fp); + } } inline bool QStorageIterator::isValid() const @@ -362,7 +418,127 @@ inline bool QStorageIterator::isValid() const inline bool QStorageIterator::next() { - return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != nullptr; + mnt.subvolume = nullptr; + mnt.superopts = nullptr; + if (!usingMountinfo) + return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != nullptr; + + // Helper function to parse paths that the kernel inserts escape sequences + // for. The unescaped string is left at \a src and is properly + // NUL-terminated. Returns a pointer to the delimiter that terminated the + // path, or nullptr if it failed. + auto parseMangledPath = [](char *src) { + // The kernel escapes with octal the following characters: + // space ' ', tab '\t', backslask '\\', and newline '\n' + char *dst = src; + while (*src) { + switch (*src) { + case ' ': + // Unescaped space: end of the field. + *dst = '\0'; + return src; + + default: + *dst++ = *src++; + break; + + case '\\': + // It always uses exactly three octal characters. + ++src; + char c = (*src++ - '0') << 6; + c |= (*src++ - '0') << 3; + c |= (*src++ - '0'); + *dst++ = c; + break; + } + } + + // Found a NUL before the end of the field. + src = nullptr; + return src; + }; + + char *ptr = buffer.data(); + if (fgets(ptr, buffer.size(), fp) == nullptr) + return false; + + size_t len = strlen(buffer.data()); + if (len == 0) + return false; + if (ptr[len - 1] == '\n') + ptr[len - 1] = '\0'; + + // parse the line + bool ok; + mnt.mnt_freq = 0; + mnt.mnt_passno = 0; + + mnt.mount_id = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok); + if (!ptr || !ok) + return false; + + int parent_id = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok); + Q_UNUSED(parent_id); + if (!ptr || !ok) + return false; + + int rdevmajor = qstrtoll(ptr, const_cast<const char **>(&ptr), 10, &ok); + if (!ptr || !ok) + return false; + if (*ptr != ':') + return false; + int rdevminor = qstrtoll(ptr + 1, const_cast<const char **>(&ptr), 10, &ok); + if (!ptr || !ok) + return false; + Q_UNUSED(rdevmajor); + Q_UNUSED(rdevminor); + + if (*ptr != ' ') + return false; + + mnt.subvolume = ++ptr; + ptr = parseMangledPath(ptr); + if (!ptr) + return false; + + // unset a subvolume of "/" -- it's not a *sub* volume + if (mnt.subvolume + 1 == ptr) + *mnt.subvolume = '\0'; + + mnt.mnt_dir = ++ptr; + ptr = parseMangledPath(ptr); + if (!ptr) + return false; + + mnt.mnt_opts = ++ptr; + ptr = strchr(ptr, ' '); + if (!ptr) + return false; + + // we don't parse the flags, so just find the separator + if (char *const dashed = strstr(ptr, " - ")) { + *ptr = '\0'; + ptr = dashed + strlen(" - ") - 1; + } else { + return false; + } + + mnt.mnt_type = ++ptr; + ptr = strchr(ptr, ' '); + if (!ptr) + return false; + *ptr = '\0'; + + mnt.mnt_fsname = ++ptr; + ptr = parseMangledPath(ptr); + if (!ptr) + return false; + + mnt.superopts = ++ptr; + ptr += strcspn(ptr, " \n"); + *ptr = '\0'; + + return true; } inline QString QStorageIterator::rootPath() const @@ -382,9 +558,28 @@ inline QByteArray QStorageIterator::device() const inline QByteArray QStorageIterator::options() const { + // Merge the two options, starting with the superblock options and letting + // the per-mount options override. + const char *superopts = mnt.superopts; + + // Both mnt_opts and superopts start with "ro" or "rw", so we can skip the + // superblock's field (see show_mountinfo() in fs/proc_namespace.c). + if (superopts && superopts[0] == 'r') { + if (superopts[2] == '\0') // no other superopts besides "ro" / "rw"? + superopts = nullptr; + else if (superopts[2] == ',') + superopts += 3; + } + + if (superopts) + return QByteArray(superopts) + ',' + mnt.mnt_opts; return QByteArray(mnt.mnt_opts); } +inline QByteArray QStorageIterator::subvolume() const +{ + return QByteArray(mnt.subvolume); +} #elif defined(Q_OS_HAIKU) inline QStorageIterator::QStorageIterator() { @@ -447,6 +642,10 @@ inline QByteArray QStorageIterator::options() const return QByteArray(); } +inline QByteArray QStorageIterator::subvolume() const +{ + return QByteArray(); +} #else inline QStorageIterator::QStorageIterator() @@ -487,31 +686,11 @@ inline QByteArray QStorageIterator::options() const return QByteArray(); } -#endif - -static QByteArray extractSubvolume(const QStorageIterator &it) +inline QByteArray QStorageIterator::subvolume() const { -#ifdef Q_OS_LINUX - if (it.fileSystemType() == "btrfs") { - const QByteArrayList opts = it.options().split(','); - QByteArray id; - for (const QByteArray &opt : opts) { - static const char subvol[] = "subvol="; - static const char subvolid[] = "subvolid="; - if (opt.startsWith(subvol)) - return std::move(opt).mid(strlen(subvol)); - if (opt.startsWith(subvolid)) - id = std::move(opt).mid(strlen(subvolid)); - } - - // if we didn't find the subvolume name, return the subvolume ID - return id; - } -#else - Q_UNUSED(it); -#endif return QByteArray(); } +#endif void QStorageInfoPrivate::initRootPath() { @@ -539,7 +718,7 @@ void QStorageInfoPrivate::initRootPath() rootPath = mountDir; device = it.device(); fileSystemType = fsName; - subvolume = extractSubvolume(it); + subvolume = it.subvolume(); } } } diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h index 1d8c253f53..abc2f1efc1 100644 --- a/src/corelib/kernel/qsystemerror_p.h +++ b/src/corelib/kernel/qsystemerror_p.h @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE -class Q_CORE_EXPORT QSystemError +class QSystemError { public: enum ErrorScope @@ -66,51 +66,27 @@ public: NativeError }; - inline QSystemError(int error, ErrorScope scope); - inline QSystemError(); + Q_DECL_CONSTEXPR explicit QSystemError(int error, ErrorScope scope) + : errorCode(error), errorScope(scope) + { + } + Q_DECL_CONSTEXPR QSystemError() = default; - inline QString toString() const; - inline ErrorScope scope() const; - inline int error() const; + QString toString() const { return string(errorScope, errorCode); } + Q_DECL_CONSTEXPR ErrorScope scope() const { return errorScope; } + Q_DECL_CONSTEXPR int error() const { return errorCode; } - static QString string(ErrorScope errorScope, int errorCode); - static QString stdString(int errorCode = -1); + static Q_CORE_EXPORT QString string(ErrorScope errorScope, int errorCode); + static Q_CORE_EXPORT QString stdString(int errorCode = -1); #ifdef Q_OS_WIN - static QString windowsString(int errorCode = -1); + static Q_CORE_EXPORT QString windowsString(int errorCode = -1); #endif //data members - int errorCode; - ErrorScope errorScope; + int errorCode = 0; + ErrorScope errorScope = NoError; }; -QSystemError::QSystemError(int error, QSystemError::ErrorScope scope) -: errorCode(error), errorScope(scope) -{ - -} - -QSystemError::QSystemError() -: errorCode(0), errorScope(NoError) -{ - -} - -QString QSystemError::toString() const -{ - return string(errorScope, errorCode); -} - -QSystemError::ErrorScope QSystemError::scope() const -{ - return errorScope; -} - -int QSystemError::error() const -{ - return errorCode; -} - QT_END_NAMESPACE #endif // QSYSTEMERROR_P_H diff --git a/src/corelib/mimetypes/mimetypes.qrc b/src/corelib/mimetypes/mimetypes.qrc index f0cf47cd49..19bc1d3e2a 100644 --- a/src/corelib/mimetypes/mimetypes.qrc +++ b/src/corelib/mimetypes/mimetypes.qrc @@ -1,5 +1,5 @@ <RCC> - <qresource prefix="/qt-project.org/qmime"> + <qresource prefix="/qt-project.org/qmime/packages"> <file alias="freedesktop.org.xml">mime/packages/freedesktop.org.xml</file> </qresource> </RCC> diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 687f0b3e03..f90fd12e3b 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -51,6 +51,7 @@ #include <QtCore/QFile> #include <QtCore/QFileInfo> #include <QtCore/QSet> +#include <QtCore/QStandardPaths> #include <QtCore/QBuffer> #include <QtCore/QUrl> #include <QtCore/QDebug> @@ -69,34 +70,102 @@ QMimeDatabasePrivate *QMimeDatabasePrivate::instance() } QMimeDatabasePrivate::QMimeDatabasePrivate() - : m_provider(0), m_defaultMimeType(QLatin1String("application/octet-stream")) + : m_defaultMimeType(QLatin1String("application/octet-stream")) { } QMimeDatabasePrivate::~QMimeDatabasePrivate() { - delete m_provider; - m_provider = 0; + qDeleteAll(m_providers); } -QMimeProviderBase *QMimeDatabasePrivate::provider() +Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test + +bool QMimeDatabasePrivate::shouldCheck() +{ + if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000) + return false; + m_lastCheck.start(); + return true; +} + +#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) +#define QT_USE_MMAP +#endif + +void QMimeDatabasePrivate::loadProviders() { - if (!m_provider) { - QMimeProviderBase *binaryProvider = new QMimeBinaryProvider(this); - if (binaryProvider->isValid()) { - m_provider = binaryProvider; + // We use QStandardPaths every time to check if new files appeared + QStringList mimeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory); + const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool { + return QFileInfo::exists(mimeDir + QStringLiteral("/packages/freedesktop.org.xml")); } + ); + if (fdoIterator == mimeDirs.constEnd()) + mimeDirs.prepend(QLatin1String(":/qt-project.org/qmime")); + //qDebug() << "mime dirs:" << mimeDirs; + + QVector<QMimeProviderBase *> currentProviders = m_providers; + m_providers.clear(); + m_providers.reserve(mimeDirs.size()); + for (const QString &mimeDir : qAsConst(mimeDirs)) { + const QString cacheFile = mimeDir + QStringLiteral("/mime.cache"); + QFileInfo fileInfo(cacheFile); + // Check if we already have a provider for this dir + const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), [mimeDir](QMimeProviderBase *prov) { return prov->directory() == mimeDir; }); + if (it == currentProviders.end()) { + QMimeProviderBase *provider = nullptr; +#if defined(QT_USE_MMAP) + if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && fileInfo.exists()) { + provider = new QMimeBinaryProvider(this, mimeDir); + //qDebug() << "Created binary provider for" << mimeDir; + if (!provider->isValid()) { + delete provider; + provider = nullptr; + } + } +#endif + if (!provider) { + provider = new QMimeXMLProvider(this, mimeDir); + //qDebug() << "Created XML provider for" << mimeDir; + } + m_providers.append(provider); } else { - delete binaryProvider; - m_provider = new QMimeXMLProvider(this); + QMimeProviderBase *provider = *it; + currentProviders.erase(it); + provider->ensureLoaded(); + if (!provider->isValid()) { + delete provider; + provider = new QMimeXMLProvider(this, mimeDir); + //qDebug() << "Created XML provider to replace binary provider for" << mimeDir; + } + m_providers.append(provider); } } - return m_provider; + qDeleteAll(currentProviders); } -void QMimeDatabasePrivate::setProvider(QMimeProviderBase *theProvider) +QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers() { - delete m_provider; - m_provider = theProvider; + Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex + if (m_providers.isEmpty()) { + loadProviders(); + m_lastCheck.start(); + } else { + if (shouldCheck()) + loadProviders(); + } + return m_providers; +} + +QString QMimeDatabasePrivate::resolveAlias(const QString &nameOrAlias) +{ + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) { + const QString ret = provider->resolveAlias(nameOrAlias); + if (!ret.isEmpty()) + return ret; + } + return nameOrAlias; } /*! @@ -105,7 +174,14 @@ void QMimeDatabasePrivate::setProvider(QMimeProviderBase *theProvider) */ QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias) { - return provider()->mimeTypeForName(provider()->resolveAlias(nameOrAlias)); + const auto allProviders = providers(); + const QString mimeName = resolveAlias(nameOrAlias); + for (QMimeProviderBase *provider : allProviders) { + const QMimeType mime = provider->mimeTypeForName(mimeName); + if (mime.isValid()) + return mime; + } + return {}; } QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName) @@ -113,11 +189,113 @@ QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName) if (fileName.endsWith(QLatin1Char('/'))) return QStringList() << QLatin1String("inode/directory"); - QStringList matchingMimeTypes = provider()->findByFileName(QFileInfo(fileName).fileName()).m_matchingMimeTypes; + const QString shortName = QFileInfo(fileName).fileName(); + const QMimeGlobMatchResult result = findByFileName(shortName); + QStringList matchingMimeTypes = result.m_matchingMimeTypes; matchingMimeTypes.sort(); // make it deterministic return matchingMimeTypes; } +QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileName) +{ + QMimeGlobMatchResult result; + // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly. + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) + provider->addFileNameMatches(fileName, result); + return result; +} + +void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate) +{ + QMutexLocker locker(&mutex); + if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand + Q_ASSERT(mimePrivate.fromCache); + QMimeBinaryProvider::loadMimeTypePrivate(mimePrivate); + } +} + +void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate) +{ + QMutexLocker locker(&mutex); + if (mimePrivate.fromCache) { + mimePrivate.genericIconName.clear(); + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) { + provider->loadGenericIcon(mimePrivate); + if (!mimePrivate.genericIconName.isEmpty()) + break; + } + } +} + +void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate) +{ + QMutexLocker locker(&mutex); + if (mimePrivate.fromCache) { + mimePrivate.iconName.clear(); + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) { + provider->loadIcon(mimePrivate); + if (!mimePrivate.iconName.isEmpty()) + break; + } + } +} + +static QString fallbackParent(const QString &mimeTypeName) +{ + const QStringRef myGroup = mimeTypeName.leftRef(mimeTypeName.indexOf(QLatin1Char('/'))); + // All text/* types are subclasses of text/plain. + if (myGroup == QLatin1String("text") && mimeTypeName != QLatin1String("text/plain")) + return QLatin1String("text/plain"); + // All real-file mimetypes implicitly derive from application/octet-stream + if (myGroup != QLatin1String("inode") && + // ignore non-file extensions + myGroup != QLatin1String("all") && myGroup != QLatin1String("fonts") && myGroup != QLatin1String("print") && myGroup != QLatin1String("uri") + && mimeTypeName != QLatin1String("application/octet-stream")) { + return QLatin1String("application/octet-stream"); + } + return QString(); +} + +QStringList QMimeDatabasePrivate::mimeParents(const QString &mimeName) +{ + QMutexLocker locker(&mutex); + return parents(mimeName); +} + +QStringList QMimeDatabasePrivate::parents(const QString &mimeName) +{ + Q_ASSERT(!mutex.tryLock()); + QStringList result; + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) + provider->addParents(mimeName, result); + if (result.isEmpty()) { + const QString parent = fallbackParent(mimeName); + if (!parent.isEmpty()) + result.append(parent); + } + return result; +} + +QStringList QMimeDatabasePrivate::listAliases(const QString &mimeName) +{ + QMutexLocker locker(&mutex); + QStringList result; + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) + provider->addAliases(mimeName, result); + return result; +} + +bool QMimeDatabasePrivate::mimeInherits(const QString &mime, const QString &parent) +{ + QMutexLocker locker(&mutex); + return inherits(mime, parent); +} + static inline bool isTextFile(const QByteArray &data) { // UTF16 byte order marks @@ -145,7 +323,10 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy } *accuracyPtr = 0; - QMimeType candidate = provider()->findByMagic(data, accuracyPtr); + QMimeType candidate; + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) + provider->findByMagic(data, accuracyPtr, candidate); if (candidate.isValid()) return candidate; @@ -172,7 +353,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa if (fileName.endsWith(QLatin1Char('/'))) candidatesByName.addMatch(QLatin1String("inode/directory"), 100, QString()); else - candidatesByName = provider()->findByFileName(QFileInfo(fileName).fileName()); + candidatesByName = findByFileName(QFileInfo(fileName).fileName()); if (candidatesByName.m_allMatchingMimeTypes.count() == 1) { *accuracyPtr = 100; const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0)); @@ -222,21 +403,25 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa QList<QMimeType> QMimeDatabasePrivate::allMimeTypes() { - return provider()->allMimeTypes(); + QList<QMimeType> result; + const auto allProviders = providers(); + for (QMimeProviderBase *provider : allProviders) + provider->addAllMimeTypes(result); + return result; } bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent) { - const QString resolvedParent = provider()->resolveAlias(parent); - //Q_ASSERT(provider()->resolveAlias(mime) == mime); + const QString resolvedParent = resolveAlias(parent); std::stack<QString, QStringList> toCheck; toCheck.push(mime); while (!toCheck.empty()) { if (toCheck.top() == resolvedParent) return true; - const auto parents = provider()->parents(toCheck.top()); + const QString mimeName = toCheck.top(); toCheck.pop(); - for (const QString &par : parents) + const auto parentList = parents(mimeName); + for (const QString &par : parentList) toCheck.push(par); } return false; @@ -460,7 +645,7 @@ QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) co QString QMimeDatabase::suffixForFileName(const QString &fileName) const { QMutexLocker locker(&d->mutex); - return d->provider()->findByFileName(QFileInfo(fileName).fileName()).m_foundSuffix; + return d->findByFileName(QFileInfo(fileName).fileName()).m_foundSuffix; } /*! @@ -550,6 +735,7 @@ QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const */ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const { + QMutexLocker locker(&d->mutex); int accuracy = 0; const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly); const QMimeType result = d->mimeTypeForFileNameAndData(fileName, device, &accuracy); @@ -576,6 +762,7 @@ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIO */ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const { + QMutexLocker locker(&d->mutex); QBuffer buffer(const_cast<QByteArray *>(&data)); buffer.open(QIODevice::ReadOnly); int accuracy = 0; diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index 3f63f5f103..1c38f46115 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -59,7 +59,9 @@ #include "qmimetype_p.h" #include "qmimeglobpattern_p.h" +#include <QtCore/qelapsedtimer.h> #include <QtCore/qmutex.h> +#include <QtCore/qvector.h> QT_BEGIN_NAMESPACE @@ -77,22 +79,37 @@ public: static QMimeDatabasePrivate *instance(); - QMimeProviderBase *provider(); - void setProvider(QMimeProviderBase *theProvider); - inline QString defaultMimeType() const { return m_defaultMimeType; } bool inherits(const QString &mime, const QString &parent); QList<QMimeType> allMimeTypes(); - + QString resolveAlias(const QString &nameOrAlias); + QStringList parents(const QString &mimeName); QMimeType mimeTypeForName(const QString &nameOrAlias); QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr); QMimeType findByData(const QByteArray &data, int *priorityPtr); QStringList mimeTypeForFileName(const QString &fileName); + QMimeGlobMatchResult findByFileName(const QString &fileName); + + // API for QMimeType. Takes care of locking the mutex. + void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate); + void loadGenericIcon(QMimeTypePrivate &mimePrivate); + void loadIcon(QMimeTypePrivate &mimePrivate); + QStringList mimeParents(const QString &mimeName); + QStringList listAliases(const QString &mimeName); + bool mimeInherits(const QString &mime, const QString &parent); - mutable QMimeProviderBase *m_provider; +private: + QVector<QMimeProviderBase *> providers(); + bool shouldCheck(); + void loadProviders(); + + mutable QVector<QMimeProviderBase *> m_providers; + QElapsedTimer m_lastCheck; + +public: const QString m_defaultMimeType; QMutex mutex; }; diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp index a4d2b046fa..e7b2b879a1 100644 --- a/src/corelib/mimetypes/qmimeglobpattern.cpp +++ b/src/corelib/mimetypes/qmimeglobpattern.cpp @@ -206,10 +206,9 @@ void QMimeGlobPatternList::match(QMimeGlobMatchResult &result, } } -QMimeGlobMatchResult QMimeAllGlobPatterns::matchingGlobs(const QString &fileName) const +void QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const { // First try the high weight matches (>50), if any. - QMimeGlobMatchResult result; m_highWeightGlobs.match(result, fileName); // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50 @@ -230,8 +229,6 @@ QMimeGlobMatchResult QMimeAllGlobPatterns::matchingGlobs(const QString &fileName // Finally, try the low weight matches (<=50) m_lowWeightGlobs.match(result, fileName); - - return result; } void QMimeAllGlobPatterns::clear() diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h index 21332e71bc..103729c4ff 100644 --- a/src/corelib/mimetypes/qmimeglobpattern_p.h +++ b/src/corelib/mimetypes/qmimeglobpattern_p.h @@ -152,7 +152,7 @@ public: void addGlob(const QMimeGlobPattern &glob); void removeMimeType(const QString &mimeType); - QMimeGlobMatchResult matchingGlobs(const QString &fileName) const; + void matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const; void clear(); PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain" diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 5bbf1bba9d..6356a3581b 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -65,7 +65,7 @@ static const char magicRuleTypes_string[] = "\0"; static const int magicRuleTypes_indices[] = { - 0, 8, 15, 22, 29, 35, 41, 50, 59, 65, 0 + 0, 8, 15, 22, 29, 35, 41, 50, 59, 64, 0 }; QMimeMagicRule::Type QMimeMagicRule::type(const QByteArray &theTypeName) diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index ed7ebb2ef5..ec0a6bf0ef 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -61,46 +61,18 @@ static void initResources() QT_BEGIN_NAMESPACE -static QString fallbackParent(const QString &mimeTypeName) -{ - const QStringRef myGroup = mimeTypeName.leftRef(mimeTypeName.indexOf(QLatin1Char('/'))); - // All text/* types are subclasses of text/plain. - if (myGroup == QLatin1String("text") && mimeTypeName != QLatin1String("text/plain")) - return QLatin1String("text/plain"); - // All real-file mimetypes implicitly derive from application/octet-stream - if (myGroup != QLatin1String("inode") && - // ignore non-file extensions - myGroup != QLatin1String("all") && myGroup != QLatin1String("fonts") && myGroup != QLatin1String("print") && myGroup != QLatin1String("uri") - && mimeTypeName != QLatin1String("application/octet-stream")) { - return QLatin1String("application/octet-stream"); - } - return QString(); -} - -QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db) - : m_db(db) +QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory) + : m_db(db), m_directory(directory) { } -Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test -bool QMimeProviderBase::shouldCheck() -{ - if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000) - return false; - m_lastCheck.start(); - return true; -} - -QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db) - : QMimeProviderBase(db), m_mimetypeListLoaded(false) +QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory) + : QMimeProviderBase(db, directory), m_mimetypeListLoaded(false) { + ensureLoaded(); } -#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) -#define QT_USE_MMAP -#endif - struct QMimeBinaryProvider::CacheFile { CacheFile(const QString &fileName); @@ -154,7 +126,6 @@ bool QMimeBinaryProvider::CacheFile::load() bool QMimeBinaryProvider::CacheFile::reload() { - //qDebug() << "reload!" << file->fileName(); m_valid = false; if (file.isOpen()) { file.close(); @@ -163,18 +134,14 @@ bool QMimeBinaryProvider::CacheFile::reload() return load(); } -QMimeBinaryProvider::CacheFile *QMimeBinaryProvider::CacheFileList::findCacheFile(const QString &fileName) const +QMimeBinaryProvider::~QMimeBinaryProvider() { - for (const_iterator it = begin(); it != end(); ++it) { - if ((*it)->file.fileName() == fileName) - return *it; - } - return 0; + delete m_cacheFile; } -QMimeBinaryProvider::~QMimeBinaryProvider() +bool QMimeBinaryProvider::isValid() { - qDeleteAll(m_cacheFiles); + return m_cacheFile != nullptr; } // Position of the "list offsets" values, at the beginning of the mime.cache file @@ -190,79 +157,33 @@ enum { PosGenericIconsListOffset = 36 }; -bool QMimeBinaryProvider::isValid() +bool QMimeBinaryProvider::checkCacheChanged() { -#if defined(QT_USE_MMAP) - if (!qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE")) - return false; - - Q_ASSERT(m_cacheFiles.isEmpty()); // this method is only ever called once - checkCache(); - - if (m_cacheFiles.count() > 1) + QFileInfo fileInfo(m_cacheFile->file); + if (fileInfo.lastModified() > m_cacheFile->m_mtime) { + // Deletion can't happen by just running update-mime-database. + // But the user could use rm -rf :-) + m_cacheFile->reload(); // will mark itself as invalid on failure return true; - if (m_cacheFiles.isEmpty()) - return false; - - // We found exactly one file; is it the user-modified mimes, or a system file? - const QString foundFile = m_cacheFiles.constFirst()->file.fileName(); - const QString localCacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/mime/mime.cache"); - - return foundFile != localCacheFile; -#else - return false; -#endif -} - -bool QMimeBinaryProvider::CacheFileList::checkCacheChanged() -{ - bool somethingChanged = false; - for (CacheFile *cacheFile : qAsConst(*this)) { - QFileInfo fileInfo(cacheFile->file); - if (!fileInfo.exists() || fileInfo.lastModified() > cacheFile->m_mtime) { - // Deletion can't happen by just running update-mime-database. - // But the user could use rm -rf :-) - cacheFile->reload(); // will mark itself as invalid on failure - somethingChanged = true; - } - } - if (somethingChanged) { - auto deleteIfNoLongerValid = [](CacheFile *cacheFile) -> bool { - const bool invalid = !cacheFile->isValid(); - if (invalid) - delete cacheFile; - return invalid; - }; - erase(std::remove_if(begin(), end(), deleteIfNoLongerValid), end()); } - return somethingChanged; + return false; } -void QMimeBinaryProvider::checkCache() +void QMimeBinaryProvider::ensureLoaded() { - if (!shouldCheck()) - return; - - // First iterate over existing known cache files and check for uptodate - if (m_cacheFiles.checkCacheChanged()) - m_mimetypeListLoaded = false; - - // Then check if new cache files appeared - const QStringList cacheFileNames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/mime.cache")); - if (cacheFileNames != m_cacheFileNames) { - for (const QString &cacheFileName : cacheFileNames) { - CacheFile *cacheFile = m_cacheFiles.findCacheFile(cacheFileName); - if (!cacheFile) { - //qDebug() << "new file:" << cacheFileName; - cacheFile = new CacheFile(cacheFileName); - if (cacheFile->isValid()) // verify version - m_cacheFiles.append(cacheFile); - else - delete cacheFile; - } - } - m_cacheFileNames = cacheFileNames; + if (!m_cacheFile) { + const QString cacheFileName = m_directory + QLatin1String("/mime.cache"); + m_cacheFile = new CacheFile(cacheFileName); m_mimetypeListLoaded = false; + } else { + if (checkCacheChanged()) + m_mimetypeListLoaded = false; + else + return; // nothing to do + } + if (!m_cacheFile->isValid()) { // verify existence and version + delete m_cacheFile; + m_cacheFile = nullptr; } } @@ -270,6 +191,7 @@ static QMimeType mimeTypeForNameUnchecked(const QString &name) { QMimeTypePrivate data; data.name = name; + data.fromCache = true; // The rest is retrieved on demand. // comment and globPatterns: in loadMimeTypePrivate // iconName: in loadIcon @@ -279,7 +201,6 @@ static QMimeType mimeTypeForNameUnchecked(const QString &name) QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name) { - checkCache(); if (!m_mimetypeListLoaded) loadMimeTypeList(); if (!m_mimetypeNames.contains(name)) @@ -287,28 +208,23 @@ QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name) return mimeTypeForNameUnchecked(name); } -QMimeGlobMatchResult QMimeBinaryProvider::findByFileName(const QString &fileName) +void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) { - checkCache(); - QMimeGlobMatchResult result; if (fileName.isEmpty()) - return result; + return; + Q_ASSERT(m_cacheFile); const QString lowerFileName = fileName.toLower(); - // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly. - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - // Check literals (e.g. "Makefile") - matchGlobList(result, cacheFile, cacheFile->getUint32(PosLiteralListOffset), fileName); - // Check complex globs (e.g. "callgrind.out[0-9]*") - matchGlobList(result, cacheFile, cacheFile->getUint32(PosGlobListOffset), fileName); - // Check the very common *.txt cases with the suffix tree - const int reverseSuffixTreeOffset = cacheFile->getUint32(PosReverseSuffixTreeOffset); - const int numRoots = cacheFile->getUint32(reverseSuffixTreeOffset); - const int firstRootOffset = cacheFile->getUint32(reverseSuffixTreeOffset + 4); - matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false); - if (result.m_matchingMimeTypes.isEmpty()) - matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true); - } - return result; + // Check literals (e.g. "Makefile") + matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName); + // Check complex globs (e.g. "callgrind.out[0-9]*") + matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName); + // Check the very common *.txt cases with the suffix tree + const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset); + const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset); + const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4); + matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false); + if (result.m_matchingMimeTypes.isEmpty()) + matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true); } void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName) @@ -406,124 +322,106 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi return false; } -QMimeType QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr) -{ - checkCache(); - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - const int magicListOffset = cacheFile->getUint32(PosMagicListOffset); - const int numMatches = cacheFile->getUint32(magicListOffset); - //const int maxExtent = cacheFile->getUint32(magicListOffset + 4); - const int firstMatchOffset = cacheFile->getUint32(magicListOffset + 8); - - for (int i = 0; i < numMatches; ++i) { - const int off = firstMatchOffset + i * 16; - const int numMatchlets = cacheFile->getUint32(off + 8); - const int firstMatchletOffset = cacheFile->getUint32(off + 12); - if (matchMagicRule(cacheFile, numMatchlets, firstMatchletOffset, data)) { - const int mimeTypeOffset = cacheFile->getUint32(off + 4); - const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); - *accuracyPtr = cacheFile->getUint32(off); - // Return the first match. We have no rules for conflicting magic data... - // (mime.cache itself is sorted, but what about local overrides with a lower prio?) - return mimeTypeForNameUnchecked(QLatin1String(mimeType)); - } +void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) +{ + const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset); + const int numMatches = m_cacheFile->getUint32(magicListOffset); + //const int maxExtent = cacheFile->getUint32(magicListOffset + 4); + const int firstMatchOffset = m_cacheFile->getUint32(magicListOffset + 8); + + for (int i = 0; i < numMatches; ++i) { + const int off = firstMatchOffset + i * 16; + const int numMatchlets = m_cacheFile->getUint32(off + 8); + const int firstMatchletOffset = m_cacheFile->getUint32(off + 12); + if (matchMagicRule(m_cacheFile, numMatchlets, firstMatchletOffset, data)) { + const int mimeTypeOffset = m_cacheFile->getUint32(off + 4); + const char *mimeType = m_cacheFile->getCharStar(mimeTypeOffset); + *accuracyPtr = m_cacheFile->getUint32(off); + // Return the first match. We have no rules for conflicting magic data... + // (mime.cache itself is sorted, but what about local overrides with a lower prio?) + candidate = mimeTypeForNameUnchecked(QLatin1String(mimeType)); + return; } } - return QMimeType(); } -QStringList QMimeBinaryProvider::parents(const QString &mime) +void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result) { - checkCache(); const QByteArray mimeStr = mime.toLatin1(); - QStringList result; - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - const int parentListOffset = cacheFile->getUint32(PosParentListOffset); - const int numEntries = cacheFile->getUint32(parentListOffset); - - int begin = 0; - int end = numEntries - 1; - while (begin <= end) { - const int medium = (begin + end) / 2; - const int off = parentListOffset + 4 + 8 * medium; - const int mimeOffset = cacheFile->getUint32(off); - const char *aMime = cacheFile->getCharStar(mimeOffset); - const int cmp = qstrcmp(aMime, mimeStr); - if (cmp < 0) { - begin = medium + 1; - } else if (cmp > 0) { - end = medium - 1; - } else { - const int parentsOffset = cacheFile->getUint32(off + 4); - const int numParents = cacheFile->getUint32(parentsOffset); - for (int i = 0; i < numParents; ++i) { - const int parentOffset = cacheFile->getUint32(parentsOffset + 4 + 4 * i); - const char *aParent = cacheFile->getCharStar(parentOffset); - result.append(QString::fromLatin1(aParent)); - } - break; + const int parentListOffset = m_cacheFile->getUint32(PosParentListOffset); + const int numEntries = m_cacheFile->getUint32(parentListOffset); + + int begin = 0; + int end = numEntries - 1; + while (begin <= end) { + const int medium = (begin + end) / 2; + const int off = parentListOffset + 4 + 8 * medium; + const int mimeOffset = m_cacheFile->getUint32(off); + const char *aMime = m_cacheFile->getCharStar(mimeOffset); + const int cmp = qstrcmp(aMime, mimeStr); + if (cmp < 0) { + begin = medium + 1; + } else if (cmp > 0) { + end = medium - 1; + } else { + const int parentsOffset = m_cacheFile->getUint32(off + 4); + const int numParents = m_cacheFile->getUint32(parentsOffset); + for (int i = 0; i < numParents; ++i) { + const int parentOffset = m_cacheFile->getUint32(parentsOffset + 4 + 4 * i); + const char *aParent = m_cacheFile->getCharStar(parentOffset); + const QString strParent = QString::fromLatin1(aParent); + if (!result.contains(strParent)) + result.append(strParent); } + break; } } - if (result.isEmpty()) { - const QString parent = fallbackParent(mime); - if (!parent.isEmpty()) - result.append(parent); - } - return result; } QString QMimeBinaryProvider::resolveAlias(const QString &name) { - checkCache(); const QByteArray input = name.toLatin1(); - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - const int aliasListOffset = cacheFile->getUint32(PosAliasListOffset); - const int numEntries = cacheFile->getUint32(aliasListOffset); - int begin = 0; - int end = numEntries - 1; - while (begin <= end) { - const int medium = (begin + end) / 2; - const int off = aliasListOffset + 4 + 8 * medium; - const int aliasOffset = cacheFile->getUint32(off); - const char *alias = cacheFile->getCharStar(aliasOffset); - const int cmp = qstrcmp(alias, input); - if (cmp < 0) { - begin = medium + 1; - } else if (cmp > 0) { - end = medium - 1; - } else { - const int mimeOffset = cacheFile->getUint32(off + 4); - const char *mimeType = cacheFile->getCharStar(mimeOffset); - return QLatin1String(mimeType); - } + const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset); + const int numEntries = m_cacheFile->getUint32(aliasListOffset); + int begin = 0; + int end = numEntries - 1; + while (begin <= end) { + const int medium = (begin + end) / 2; + const int off = aliasListOffset + 4 + 8 * medium; + const int aliasOffset = m_cacheFile->getUint32(off); + const char *alias = m_cacheFile->getCharStar(aliasOffset); + const int cmp = qstrcmp(alias, input); + if (cmp < 0) { + begin = medium + 1; + } else if (cmp > 0) { + end = medium - 1; + } else { + const int mimeOffset = m_cacheFile->getUint32(off + 4); + const char *mimeType = m_cacheFile->getCharStar(mimeOffset); + return QLatin1String(mimeType); } } - return name; } -QStringList QMimeBinaryProvider::listAliases(const QString &name) +void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result) { - checkCache(); - QStringList result; const QByteArray input = name.toLatin1(); - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - const int aliasListOffset = cacheFile->getUint32(PosAliasListOffset); - const int numEntries = cacheFile->getUint32(aliasListOffset); - for (int pos = 0; pos < numEntries; ++pos) { - const int off = aliasListOffset + 4 + 8 * pos; - const int mimeOffset = cacheFile->getUint32(off + 4); - const char *mimeType = cacheFile->getCharStar(mimeOffset); - - if (input == mimeType) { - const int aliasOffset = cacheFile->getUint32(off); - const char *alias = cacheFile->getCharStar(aliasOffset); - result.append(QString::fromLatin1(alias)); - } + const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset); + const int numEntries = m_cacheFile->getUint32(aliasListOffset); + for (int pos = 0; pos < numEntries; ++pos) { + const int off = aliasListOffset + 4 + 8 * pos; + const int mimeOffset = m_cacheFile->getUint32(off + 4); + const char *mimeType = m_cacheFile->getCharStar(mimeOffset); + + if (input == mimeType) { + const int aliasOffset = m_cacheFile->getUint32(off); + const char *alias = m_cacheFile->getCharStar(aliasOffset); + const QString strAlias = QString::fromLatin1(alias); + if (!result.contains(strAlias)) + result.append(strAlias); } } - return result; } void QMimeBinaryProvider::loadMimeTypeList() @@ -533,31 +431,30 @@ void QMimeBinaryProvider::loadMimeTypeList() m_mimetypeNames.clear(); // Unfortunately mime.cache doesn't have a full list of all mimetypes. // So we have to parse the plain-text files called "types". - const QStringList typesFilenames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/types")); - for (const QString &typeFilename : typesFilenames) { - QFile file(typeFilename); - if (file.open(QIODevice::ReadOnly)) { - QTextStream stream(&file); - stream.setCodec("ISO 8859-1"); - QString line; - while (stream.readLineInto(&line)) - m_mimetypeNames.insert(line); - } + QFile file(m_directory + QStringLiteral("/types")); + if (file.open(QIODevice::ReadOnly)) { + QTextStream stream(&file); + stream.setCodec("ISO 8859-1"); + QString line; + while (stream.readLineInto(&line)) + m_mimetypeNames.insert(line); } } } -QList<QMimeType> QMimeBinaryProvider::allMimeTypes() +void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result) { - QList<QMimeType> result; loadMimeTypeList(); - result.reserve(m_mimetypeNames.count()); - - for (QSet<QString>::const_iterator it = m_mimetypeNames.constBegin(); - it != m_mimetypeNames.constEnd(); ++it) - result.append(mimeTypeForNameUnchecked(*it)); - - return result; + if (result.isEmpty()) { + result.reserve(m_mimetypeNames.count()); + for (const QString &name : m_mimetypeNames) + result.append(mimeTypeForNameUnchecked(name)); + } else { + for (const QString &name : m_mimetypeNames) + if (std::find_if(result.constBegin(), result.constEnd(), [name](const QMimeType &mime) -> bool { return mime.name() == name; }) + == result.constEnd()) + result.append(mimeTypeForNameUnchecked(name)); + } } void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) @@ -681,36 +578,29 @@ QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posList void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data) { - checkCache(); const QByteArray inputMime = data.name.toLatin1(); - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - const QLatin1String icon = iconForMime(cacheFile, PosIconsListOffset, inputMime); - if (!icon.isEmpty()) { - data.iconName = icon; - return; - } + const QLatin1String icon = iconForMime(m_cacheFile, PosIconsListOffset, inputMime); + if (!icon.isEmpty()) { + data.iconName = icon; } } void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data) { - checkCache(); const QByteArray inputMime = data.name.toLatin1(); - for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) { - const QLatin1String icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime); - if (!icon.isEmpty()) { - data.genericIconName = icon; - return; - } + const QLatin1String icon = iconForMime(m_cacheFile, PosGenericIconsListOffset, inputMime); + if (!icon.isEmpty()) { + data.genericIconName = icon; } } //// -QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db) - : QMimeProviderBase(db), m_loaded(false) +QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory) + : QMimeProviderBase(db, directory) { initResources(); + ensureLoaded(); } QMimeXMLProvider::~QMimeXMLProvider() @@ -719,81 +609,63 @@ QMimeXMLProvider::~QMimeXMLProvider() bool QMimeXMLProvider::isValid() { + // If you change this method, adjust the logic in QMimeDatabasePrivate::loadProviders, + // which assumes isValid==false is only possible in QMimeBinaryProvider. return true; } QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name) { - ensureLoaded(); - return m_nameMimeTypeMap.value(name); } -QMimeGlobMatchResult QMimeXMLProvider::findByFileName(const QString &fileName) +void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) { - ensureLoaded(); - - return m_mimeTypeGlobs.matchingGlobs(fileName); + m_mimeTypeGlobs.matchingGlobs(fileName, result); } -QMimeType QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr) +void QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) { - ensureLoaded(); - - QString candidate; - + QString candidateName; + bool foundOne = false; for (const QMimeMagicRuleMatcher &matcher : qAsConst(m_magicMatchers)) { if (matcher.matches(data)) { const int priority = matcher.priority(); if (priority > *accuracyPtr) { *accuracyPtr = priority; - candidate = matcher.mimetype(); + candidateName = matcher.mimetype(); + foundOne = true; } } } - return mimeTypeForName(candidate); + if (foundOne) + candidate = mimeTypeForName(candidateName); } void QMimeXMLProvider::ensureLoaded() { - if (!m_loaded || shouldCheck()) { - bool fdoXmlFound = false; - QStringList allFiles; - - const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory); - //qDebug() << "packageDirs=" << packageDirs; - for (const QString &packageDir : packageDirs) { - QDir dir(packageDir); - const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); - //qDebug() << static_cast<const void *>(this) << packageDir << files; - if (!fdoXmlFound) - fdoXmlFound = files.contains(QLatin1String("freedesktop.org.xml")); - QStringList::const_iterator endIt(files.constEnd()); - for (QStringList::const_iterator it(files.constBegin()); it != endIt; ++it) { - allFiles.append(packageDir + QLatin1Char('/') + *it); - } - } - - if (!fdoXmlFound) { - // We could instead install the file as part of installing Qt? - allFiles.prepend(QLatin1String(":/qt-project.org/qmime/freedesktop.org.xml")); - } + QStringList allFiles; + const QString packageDir = m_directory + QStringLiteral("/packages"); + QDir dir(packageDir); + const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); + allFiles.reserve(files.count()); + for (const QString &xmlFile : files) + allFiles.append(packageDir + QLatin1Char('/') + xmlFile); - if (m_allFiles == allFiles) - return; - m_allFiles = allFiles; + if (m_allFiles == allFiles) + return; + m_allFiles = allFiles; - m_nameMimeTypeMap.clear(); - m_aliases.clear(); - m_parents.clear(); - m_mimeTypeGlobs.clear(); - m_magicMatchers.clear(); + m_nameMimeTypeMap.clear(); + m_aliases.clear(); + m_parents.clear(); + m_mimeTypeGlobs.clear(); + m_magicMatchers.clear(); - //qDebug() << "Loading" << m_allFiles; + //qDebug() << "Loading" << m_allFiles; - for (const QString &file : qAsConst(allFiles)) - load(file); - } + for (const QString &file : qAsConst(allFiles)) + load(file); } void QMimeXMLProvider::load(const QString &fileName) @@ -805,8 +677,6 @@ void QMimeXMLProvider::load(const QString &fileName) bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage) { - m_loaded = true; - QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (errorMessage) @@ -828,19 +698,16 @@ void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern &glob) void QMimeXMLProvider::addMimeType(const QMimeType &mt) { + Q_ASSERT(!mt.d.data()->fromCache); m_nameMimeTypeMap.insert(mt.name(), mt); } -QStringList QMimeXMLProvider::parents(const QString &mime) +void QMimeXMLProvider::addParents(const QString &mime, QStringList &result) { - ensureLoaded(); - QStringList result = m_parents.value(mime); - if (result.isEmpty()) { - const QString parent = fallbackParent(mime); - if (!parent.isEmpty()) + for (const QString &parent : m_parents.value(mime)) { + if (!result.contains(parent)) result.append(parent); } - return result; } void QMimeXMLProvider::addParent(const QString &child, const QString &parent) @@ -848,16 +715,20 @@ void QMimeXMLProvider::addParent(const QString &child, const QString &parent) m_parents[child].append(parent); } -QStringList QMimeXMLProvider::listAliases(const QString &name) +void QMimeXMLProvider::addAliases(const QString &name, QStringList &result) { - ensureLoaded(); // Iterate through the whole hash. This method is rarely used. - return m_aliases.keys(name); + for (auto it = m_aliases.constBegin(), end = m_aliases.constEnd() ; it != end ; ++it) { + if (it.value() == name) { + if (!result.contains(it.key())) + result.append(it.key()); + } + } + } QString QMimeXMLProvider::resolveAlias(const QString &name) { - ensureLoaded(); return m_aliases.value(name, name); } @@ -866,10 +737,18 @@ void QMimeXMLProvider::addAlias(const QString &alias, const QString &name) m_aliases.insert(alias, name); } -QList<QMimeType> QMimeXMLProvider::allMimeTypes() +void QMimeXMLProvider::addAllMimeTypes(QList<QMimeType> &result) { - ensureLoaded(); - return m_nameMimeTypeMap.values(); + if (result.isEmpty()) { // fast path + result = m_nameMimeTypeMap.values(); + } else { + for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) { + const QString newMime = it.key(); + if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const QMimeType &mime) -> bool { return mime.name() == newMime; }) + == result.constEnd()) + result.append(it.value()); + } + } } void QMimeXMLProvider::addMagicMatcher(const QMimeMagicRuleMatcher &matcher) diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index 3eae672823..b2be545cf8 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -59,7 +59,6 @@ #include "qmimeglobpattern_p.h" #include <QtCore/qdatetime.h> #include <QtCore/qset.h> -#include <QtCore/qelapsedtimer.h> QT_BEGIN_NAMESPACE @@ -68,25 +67,25 @@ class QMimeMagicRuleMatcher; class QMimeProviderBase { public: - QMimeProviderBase(QMimeDatabasePrivate *db); + QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory); virtual ~QMimeProviderBase() {} virtual bool isValid() = 0; virtual QMimeType mimeTypeForName(const QString &name) = 0; - virtual QMimeGlobMatchResult findByFileName(const QString &fileName) = 0; - virtual QStringList parents(const QString &mime) = 0; + virtual void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) = 0; + virtual void addParents(const QString &mime, QStringList &result) = 0; virtual QString resolveAlias(const QString &name) = 0; - virtual QStringList listAliases(const QString &name) = 0; - virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) = 0; - virtual QList<QMimeType> allMimeTypes() = 0; - virtual void loadMimeTypePrivate(QMimeTypePrivate &) {} + virtual void addAliases(const QString &name, QStringList &result) = 0; + virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) = 0; + virtual void addAllMimeTypes(QList<QMimeType> &result) = 0; virtual void loadIcon(QMimeTypePrivate &) {} virtual void loadGenericIcon(QMimeTypePrivate &) {} + virtual void ensureLoaded() {} + + QString directory() const { return m_directory; } QMimeDatabasePrivate *m_db; -protected: - bool shouldCheck(); - QElapsedTimer m_lastCheck; + QString m_directory; }; /* @@ -95,20 +94,21 @@ protected: class QMimeBinaryProvider : public QMimeProviderBase { public: - QMimeBinaryProvider(QMimeDatabasePrivate *db); + QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory); virtual ~QMimeBinaryProvider(); virtual bool isValid() override; virtual QMimeType mimeTypeForName(const QString &name) override; - virtual QMimeGlobMatchResult findByFileName(const QString &fileName) override; - virtual QStringList parents(const QString &mime) override; + void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override; + void addParents(const QString &mime, QStringList &result) override; virtual QString resolveAlias(const QString &name) override; - virtual QStringList listAliases(const QString &name) override; - virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) override; - virtual QList<QMimeType> allMimeTypes() override; - virtual void loadMimeTypePrivate(QMimeTypePrivate &) override; + void addAliases(const QString &name, QStringList &result) override; + void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; + void addAllMimeTypes(QList<QMimeType> &result) override; + static void loadMimeTypePrivate(QMimeTypePrivate &); virtual void loadIcon(QMimeTypePrivate &) override; virtual void loadGenericIcon(QMimeTypePrivate &) override; + void ensureLoaded() override; private: struct CacheFile; @@ -118,15 +118,9 @@ private: bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data); QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime); void loadMimeTypeList(); - void checkCache(); - - class CacheFileList : public QList<CacheFile *> - { - public: - CacheFile *findCacheFile(const QString &fileName) const; - bool checkCacheChanged(); - }; - CacheFileList m_cacheFiles; + bool checkCacheChanged(); + + CacheFile *m_cacheFile = nullptr; QStringList m_cacheFileNames; QSet<QString> m_mimetypeNames; bool m_mimetypeListLoaded; @@ -138,17 +132,18 @@ private: class QMimeXMLProvider : public QMimeProviderBase { public: - QMimeXMLProvider(QMimeDatabasePrivate *db); + QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory); ~QMimeXMLProvider(); virtual bool isValid() override; virtual QMimeType mimeTypeForName(const QString &name) override; - virtual QMimeGlobMatchResult findByFileName(const QString &fileName) override; - virtual QStringList parents(const QString &mime) override; + void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override; + void addParents(const QString &mime, QStringList &result) override; virtual QString resolveAlias(const QString &name) override; - virtual QStringList listAliases(const QString &name) override; - virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) override; - virtual QList<QMimeType> allMimeTypes() override; + void addAliases(const QString &name, QStringList &result) override; + void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; + void addAllMimeTypes(QList<QMimeType> &result) override; + void ensureLoaded() override; bool load(const QString &fileName, QString *errorMessage); @@ -160,11 +155,8 @@ public: void addMagicMatcher(const QMimeMagicRuleMatcher &matcher); private: - void ensureLoaded(); void load(const QString &fileName); - bool m_loaded; - typedef QHash<QString, QMimeType> NameMimeTypeMap; NameMimeTypeMap m_nameMimeTypeMap; diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp index 28113babfe..8f6237c1cb 100644 --- a/src/corelib/mimetypes/qmimetype.cpp +++ b/src/corelib/mimetypes/qmimetype.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QMimeTypePrivate::QMimeTypePrivate() - : loaded(false) + : loaded(false), fromCache(false) {} QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other) @@ -76,7 +76,6 @@ void QMimeTypePrivate::clear() genericIconName.clear(); iconName.clear(); globPatterns.clear(); - loaded = false; } void QMimeTypePrivate::addGlobPattern(const QString &pattern) @@ -256,7 +255,7 @@ QString QMimeType::name() const */ QString QMimeType::comment() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); QStringList languageList; languageList << QLocale().name(); @@ -296,7 +295,7 @@ QString QMimeType::comment() const */ QString QMimeType::genericIconName() const { - QMimeDatabasePrivate::instance()->provider()->loadGenericIcon(*d); + QMimeDatabasePrivate::instance()->loadGenericIcon(*d); if (d->genericIconName.isEmpty()) { // From the spec: // If the generic icon name is empty (not specified by the mimetype definition) @@ -324,7 +323,7 @@ QString QMimeType::genericIconName() const */ QString QMimeType::iconName() const { - QMimeDatabasePrivate::instance()->provider()->loadIcon(*d); + QMimeDatabasePrivate::instance()->loadIcon(*d); if (d->iconName.isEmpty()) { // Make default icon name from the mimetype name d->iconName = name(); @@ -344,7 +343,7 @@ QString QMimeType::iconName() const */ QStringList QMimeType::globPatterns() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); return d->globPatterns; } @@ -368,12 +367,12 @@ QStringList QMimeType::globPatterns() const */ QStringList QMimeType::parentMimeTypes() const { - return QMimeDatabasePrivate::instance()->provider()->parents(d->name); + return QMimeDatabasePrivate::instance()->mimeParents(d->name); } static void collectParentMimeTypes(const QString &mime, QStringList &allParents) { - const QStringList parents = QMimeDatabasePrivate::instance()->provider()->parents(mime); + const QStringList parents = QMimeDatabasePrivate::instance()->mimeParents(mime); for (const QString &parent : parents) { // I would use QSet, but since order matters I better not if (!allParents.contains(parent)) @@ -425,7 +424,7 @@ QStringList QMimeType::allAncestors() const */ QStringList QMimeType::aliases() const { - return QMimeDatabasePrivate::instance()->provider()->listAliases(d->name); + return QMimeDatabasePrivate::instance()->listAliases(d->name); } /*! @@ -439,7 +438,7 @@ QStringList QMimeType::aliases() const */ QStringList QMimeType::suffixes() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); QStringList result; for (const QString &pattern : qAsConst(d->globPatterns)) { @@ -480,7 +479,7 @@ QString QMimeType::preferredSuffix() const */ QString QMimeType::filterString() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); QString filter; if (!d->globPatterns.empty()) { @@ -508,7 +507,7 @@ bool QMimeType::inherits(const QString &mimeTypeName) const { if (d->name == mimeTypeName) return true; - return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName); + return QMimeDatabasePrivate::instance()->mimeInherits(d->name, mimeTypeName); } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h index b0bfad2f65..aa38a1adf5 100644 --- a/src/corelib/mimetypes/qmimetype_p.h +++ b/src/corelib/mimetypes/qmimetype_p.h @@ -74,6 +74,7 @@ public: void addGlobPattern(const QString &pattern); bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first + bool fromCache; // true if this comes from the binary provider QString name; LocaleHash localeComments; QString genericIconName; @@ -94,6 +95,7 @@ QT_END_NAMESPACE { \ QMimeTypePrivate qMimeTypeData; \ qMimeTypeData.name = name; \ + qMimeTypeData.loaded = true; \ qMimeTypeData.genericIconName = genericIconName; \ qMimeTypeData.iconName = iconName; \ qMimeTypeData.globPatterns = globPatterns; \ @@ -112,6 +114,7 @@ QT_END_NAMESPACE ) \ { \ QMimeTypePrivate qMimeTypeData; \ + qMimeTypeData.loaded = true; \ qMimeTypeData.name = std::move(name); \ qMimeTypeData.genericIconName = std::move(genericIconName); \ qMimeTypeData.iconName = std::move(iconName); \ diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index 5ecd339908..0a55560ab0 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -201,6 +201,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString return false; #else QMimeTypePrivate data; + data.loaded = true; int priority = 50; QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules QList<QMimeMagicRule> rules; // toplevel rules diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index a462d7bb58..fafc3e37b0 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -164,11 +164,7 @@ # if !defined(__MIPS_DSPR2__) && defined(__mips_dspr2) && defined(Q_PROCESSOR_MIPS_32) # define __MIPS_DSPR2__ # endif -#elif (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \ - || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && Q_CC_GNU >= 409) \ - || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 308)) \ - && !defined(QT_BOOTSTRAPPED) -# define QT_COMPILER_SUPPORTS_SIMD_ALWAYS +#elif defined(Q_PROCESSOR_X86) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) # define QT_COMPILER_SUPPORTS_HERE(x) ((__ ## x ## __) || QT_COMPILER_SUPPORTS(x)) # if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) /* GCC requires attributes for a function */ diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index cd3966fb47..c8ba86bc9a 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -747,8 +747,7 @@ QString QPlatformTheme::removeMnemonics(const QString &original) int currPos = 0; int l = original.length(); while (l) { - if (original.at(currPos) == QLatin1Char('&') - && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { + if (original.at(currPos) == QLatin1Char('&')) { ++currPos; --l; if (l == 0) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index c6ae7c1b79..2067c86023 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -596,8 +596,7 @@ static QString qt_mac_removeMnemonics(const QString &original) int currPos = 0; int l = original.length(); while (l) { - if (original.at(currPos) == QLatin1Char('&') - && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { + if (original.at(currPos) == QLatin1Char('&')) { ++currPos; --l; if (l == 0) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 8883b6360f..b1a49b7d98 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -148,7 +148,7 @@ void tst_QMimeDatabase::initTestCase() qDebug() << "\nGlobal XDG_DATA_DIRS: " << m_globalXdgDir; const QString freeDesktopXml = QStringLiteral("freedesktop.org.xml"); - const QString xmlFileName = QLatin1String(RESOURCE_PREFIX) + freeDesktopXml; + const QString xmlFileName = QLatin1String(RESOURCE_PREFIX "packages/") + freeDesktopXml; const QString xmlTargetFileName = globalPackageDir + QLatin1Char('/') + freeDesktopXml; QVERIFY2(copyResourceFile(xmlFileName, xmlTargetFileName, &errorMessage), qPrintable(errorMessage)); #endif @@ -1042,17 +1042,21 @@ void tst_QMimeDatabase::installNewLocalMimeType() QCOMPARE(db.mimeTypeForFile(qmlTestFile).name(), QString::fromLatin1("text/x-qml")); - // Now test removing the local mimetypes again (note, this leaves a mostly-empty mime.cache file) - for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) - QFile::remove(destDir + m_additionalMimeFileNames.at(i)); + // Now test removing local mimetypes + for (int i = 1 ; i <= 3 ; ++i) + QFile::remove(destDir + QStringLiteral("invalid-magic%1.xml").arg(i)); if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); - QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), - QString::fromLatin1("application/octet-stream")); - QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); + QVERIFY(!db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid()); // deleted + QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); // still present - // And now the user goes wild and uses rm -rf + // The user deletes the cache -> the XML provider makes things still work QFile::remove(m_localMimeDir + QString::fromLatin1("/mime.cache")); + QVERIFY(!db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid()); // deleted + QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); // still present + + // Finally, the user deletes the whole local dir + QVERIFY2(QDir(m_localMimeDir).removeRecursively(), qPrintable(m_localMimeDir + ": " + qt_error_string())); QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), QString::fromLatin1("application/octet-stream")); QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); diff --git a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro index 7c1cd5b66b..f2108ab518 100644 --- a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro +++ b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro @@ -6,4 +6,7 @@ QT = core network testlib TARGET = tst_qsslcertificate +RESOURCES += \ + qsslcertificate.qrc + TESTDATA += certificates/* more-certificates/* verify-certs/* pkcs12/* diff --git a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.qrc b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.qrc new file mode 100644 index 0000000000..fe5d510120 --- /dev/null +++ b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.qrc @@ -0,0 +1,79 @@ +<RCC> + <qresource prefix="/"> + <file>certificates/ca-cert.pem</file> + <file>certificates/ca-cert.pem.digest-md5</file> + <file>certificates/ca-cert.pem.digest-sha1</file> + <file>certificates/cert-ss-san-utf8.pem</file> + <file>certificates/cert-ss-san-utf8.pem.san</file> + <file>certificates/cert-ss-san.pem</file> + <file>certificates/cert-ss-san.pem.san</file> + <file>certificates/cert-ss.der</file> + <file>certificates/cert-ss.der.pubkey</file> + <file>certificates/cert-ss.pem</file> + <file>certificates/cert-ss.pem.digest-md5</file> + <file>certificates/cert-ss.pem.digest-sha1</file> + <file>certificates/cert-ss.pem.pubkey</file> + <file>certificates/cert.der</file> + <file>certificates/cert.der.pubkey</file> + <file>certificates/cert.pem</file> + <file>certificates/cert.pem.digest-md5</file> + <file>certificates/cert.pem.digest-sha1</file> + <file>certificates/cert.pem.pubkey</file> + <file>certificates/dsa-cert-ss.der.pubkey</file> + <file>certificates/dsa-cert-ss.pem</file> + <file>certificates/dsa-cert-ss.pem.digest-md5</file> + <file>certificates/dsa-cert-ss.pem.digest-sha1</file> + <file>certificates/dsa-cert-ss.pem.pubkey</file> + <file>certificates/ec-cert-ss.der.pubkey</file> + <file>certificates/ec-cert-ss.pem</file> + <file>certificates/ec-cert-ss.pem.digest-md5</file> + <file>certificates/ec-cert-ss.pem.digest-sha1</file> + <file>certificates/ec-cert-ss.pem.pubkey</file> + <file>certificates/gencertificates.sh</file> + <file>certificates/san.cnf</file> + <file>more-certificates/badguy-nul-cn.crt</file> + <file>more-certificates/badguy-nul-san.crt</file> + <file>more-certificates/blacklisted-anssi-tresor.pem</file> + <file>more-certificates/blacklisted-google.com-diginotar.pem</file> + <file>more-certificates/blacklisted-nic-india-2007.pem</file> + <file>more-certificates/blacklisted-nic-india-2011.pem</file> + <file>more-certificates/blacklisted-nic-india-2014.pem</file> + <file>more-certificates/blacklisted-turktrust-e-islem.kktcmerkezbankasi.org.pem</file> + <file>more-certificates/blacklisted-turktrust-ego.gov.tr.pem</file> + <file>more-certificates/blacklisted1.pem</file> + <file>more-certificates/blacklisted2.pem</file> + <file>more-certificates/blacklisted3.pem</file> + <file>more-certificates/blacklisted4.pem</file> + <file>more-certificates/blacklisted5.pem</file> + <file>more-certificates/blacklisted6.pem</file> + <file>more-certificates/blacklisted7.pem</file> + <file>more-certificates/blacklisted8.pem</file> + <file>more-certificates/blacklisted9.pem</file> + <file>more-certificates/cert-large-expiration-date.pem</file> + <file>more-certificates/cert-large-expiration-date.txt.0.9.8</file> + <file>more-certificates/cert-large-expiration-date.txt.1.0.0</file> + <file>more-certificates/cert-large-expiration-date.txt.1.0.1</file> + <file>more-certificates/cert-large-expiration-date.txt.1.0.1c</file> + <file>more-certificates/cert-large-serial-number.pem</file> + <file>more-certificates/malformed-just-begin-no-newline.pem</file> + <file>more-certificates/malformed-just-begin.pem</file> + <file>more-certificates/natwest-banking.pem</file> + <file>more-certificates/no-ending-newline.pem</file> + <file>more-certificates/test-cn-two-cns-cert.pem</file> + <file>more-certificates/test-cn-with-drink-cert.pem</file> + <file>more-certificates/trailing-whitespace.pem</file> + <file>pkcs12/inter.crt</file> + <file>pkcs12/leaf-nokey.p12</file> + <file>pkcs12/leaf.crt</file> + <file>pkcs12/leaf.key</file> + <file>pkcs12/leaf.p12</file> + <file>pkcs12/README</file> + <file>verify-certs/cacert.pem</file> + <file>verify-certs/README</file> + <file>verify-certs/test-addons-mozilla-org-cert.pem</file> + <file>verify-certs/test-intermediate-ca-cert.pem</file> + <file>verify-certs/test-intermediate-is-ca-cert.pem</file> + <file>verify-certs/test-intermediate-not-ca-cert.pem</file> + <file>verify-certs/test-ocsp-good-cert.pem</file> + </qresource> +</RCC> diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index 064efc120b..d845315e85 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -57,11 +57,8 @@ class tst_QSslCertificate : public QObject void compareCertificates(const QSslCertificate & cert1, const QSslCertificate & cert2); #endif - QString oldCurrentDir; - public slots: void initTestCase(); - void cleanupTestCase(); #ifndef QT_NO_SSL private slots: @@ -111,23 +108,11 @@ private slots: // ### add tests for certificate bundles (multiple certificates concatenated into a single // structure); both PEM and DER formatted #endif -private: - QString testDataDir; }; void tst_QSslCertificate::initTestCase() { - testDataDir = QFileInfo(QFINDTESTDATA("certificates")).absolutePath(); - if (testDataDir.isEmpty()) - testDataDir = QCoreApplication::applicationDirPath(); - - if (QDir::current().absolutePath() != testDataDir) { - oldCurrentDir = QDir::current().absolutePath(); - QVERIFY2(QDir::setCurrent(testDataDir), - qPrintable(QString("Cannot change directory to %1").arg(testDataDir))); - } - - QDir dir(testDataDir + "/certificates"); + QDir dir(":/certificates"); QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable); QRegExp rxCert(QLatin1String("^.+\\.(pem|der)$")); QRegExp rxSan(QLatin1String("^(.+\\.(?:pem|der))\\.san$")); @@ -151,13 +136,6 @@ void tst_QSslCertificate::initTestCase() } } -void tst_QSslCertificate::cleanupTestCase() -{ - if (!oldCurrentDir.isEmpty()) { - QDir::setCurrent(oldCurrentDir); - } -} - #ifndef QT_NO_SSL void tst_QSslCertificate::hash() @@ -232,7 +210,7 @@ void tst_QSslCertificate::constructor_device() if (!QSslSocket::supportsSsl()) return; - QFile f(testDataDir + "/verify-certs/test-ocsp-good-cert.pem"); + QFile f(":/verify-certs/test-ocsp-good-cert.pem"); bool ok = f.open(QIODevice::ReadOnly); QVERIFY(ok); @@ -241,7 +219,7 @@ void tst_QSslCertificate::constructor_device() f.close(); // Check opening a DER as a PEM fails - QFile f2(testDataDir + "/certificates/cert.der"); + QFile f2(":/certificates/cert.der"); ok = f2.open(QIODevice::ReadOnly); QVERIFY(ok); @@ -250,7 +228,7 @@ void tst_QSslCertificate::constructor_device() f2.close(); // Check opening a DER as a DER works - QFile f3(testDataDir + "/certificates/cert.der"); + QFile f3(":/certificates/cert.der"); ok = f3.open(QIODevice::ReadOnly); QVERIFY(ok); @@ -259,7 +237,7 @@ void tst_QSslCertificate::constructor_device() f3.close(); // Check opening a PEM as a DER fails - QFile f4(testDataDir + "/verify-certs/test-ocsp-good-cert.pem"); + QFile f4(":/verify-certs/test-ocsp-good-cert.pem"); ok = f4.open(QIODevice::ReadOnly); QVERIFY(ok); @@ -445,7 +423,7 @@ void tst_QSslCertificate::subjectAlternativeNames() void tst_QSslCertificate::utf8SubjectNames() { - QSslCertificate cert = QSslCertificate::fromPath("certificates/cert-ss-san-utf8.pem", QSsl::Pem, + QSslCertificate cert = QSslCertificate::fromPath(":/certificates/cert-ss-san-utf8.pem", QSsl::Pem, QRegExp::FixedString).first(); QVERIFY(!cert.isNull()); @@ -568,60 +546,60 @@ void tst_QSslCertificate::fromPath_data() QTest::newRow("empty regexp der") << QString() << int(QRegExp::RegExp) << false << 0; QTest::newRow("empty wildcard pem") << QString() << int(QRegExp::Wildcard) << true << 0; QTest::newRow("empty wildcard der") << QString() << int(QRegExp::Wildcard) << false << 0; - QTest::newRow("\"certificates\" fixed pem") << QString("certificates") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("\"certificates\" fixed der") << QString("certificates") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"certificates\" regexp pem") << QString("certificates") << int(QRegExp::RegExp) << true << 0; - QTest::newRow("\"certificates\" regexp der") << QString("certificates") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"certificates\" wildcard pem") << QString("certificates") << int(QRegExp::Wildcard) << true << 0; - QTest::newRow("\"certificates\" wildcard der") << QString("certificates") << int(QRegExp::Wildcard) << false << 0; - QTest::newRow("\"certificates/cert.pem\" fixed pem") << QString("certificates/cert.pem") << int(QRegExp::FixedString) << true << 1; - QTest::newRow("\"certificates/cert.pem\" fixed der") << QString("certificates/cert.pem") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"certificates/cert.pem\" regexp pem") << QString("certificates/cert.pem") << int(QRegExp::RegExp) << true << 1; - QTest::newRow("\"certificates/cert.pem\" regexp der") << QString("certificates/cert.pem") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"certificates/cert.pem\" wildcard pem") << QString("certificates/cert.pem") << int(QRegExp::Wildcard) << true << 1; - QTest::newRow("\"certificates/cert.pem\" wildcard der") << QString("certificates/cert.pem") << int(QRegExp::Wildcard) << false << 0; - QTest::newRow("\"certificates/*\" fixed pem") << QString("certificates/*") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("\"certificates/*\" fixed der") << QString("certificates/*") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"certificates/*\" regexp pem") << QString("certificates/*") << int(QRegExp::RegExp) << true << 0; - QTest::newRow("\"certificates/*\" regexp der") << QString("certificates/*") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"certificates/*\" wildcard pem") << QString("certificates/*") << int(QRegExp::Wildcard) << true << 7; - QTest::newRow("\"certificates/ca*\" wildcard pem") << QString("certificates/ca*") << int(QRegExp::Wildcard) << true << 1; - QTest::newRow("\"certificates/cert*\" wildcard pem") << QString("certificates/cert*") << int(QRegExp::Wildcard) << true << 4; - QTest::newRow("\"certificates/cert-[sure]*\" wildcard pem") << QString("certificates/cert-[sure]*") << int(QRegExp::Wildcard) << true << 3; - QTest::newRow("\"certificates/cert-[not]*\" wildcard pem") << QString("certificates/cert-[not]*") << int(QRegExp::Wildcard) << true << 0; - QTest::newRow("\"certificates/*\" wildcard der") << QString("certificates/*") << int(QRegExp::Wildcard) << false << 2; - QTest::newRow("\"c*/c*.pem\" fixed pem") << QString("c*/c*.pem") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("\"c*/c*.pem\" fixed der") << QString("c*/c*.pem") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"c*/c*.pem\" regexp pem") << QString("c*/c*.pem") << int(QRegExp::RegExp) << true << 0; - QTest::newRow("\"c*/c*.pem\" regexp der") << QString("c*/c*.pem") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"c*/c*.pem\" wildcard pem") << QString("c*/c*.pem") << int(QRegExp::Wildcard) << true << 5; - QTest::newRow("\"c*/c*.pem\" wildcard der") << QString("c*/c*.pem") << int(QRegExp::Wildcard) << false << 0; - QTest::newRow("\"d*/c*.pem\" fixed pem") << QString("d*/c*.pem") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("\"d*/c*.pem\" fixed der") << QString("d*/c*.pem") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"d*/c*.pem\" regexp pem") << QString("d*/c*.pem") << int(QRegExp::RegExp) << true << 0; - QTest::newRow("\"d*/c*.pem\" regexp der") << QString("d*/c*.pem") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"d*/c*.pem\" wildcard pem") << QString("d*/c*.pem") << int(QRegExp::Wildcard) << true << 0; - QTest::newRow("\"d*/c*.pem\" wildcard der") << QString("d*/c*.pem") << int(QRegExp::Wildcard) << false << 0; - QTest::newRow("\"c.*/c.*.pem\" fixed pem") << QString("c.*/c.*.pem") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("\"c.*/c.*.pem\" fixed der") << QString("c.*/c.*.pem") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"c.*/c.*.pem\" regexp pem") << QString("c.*/c.*.pem") << int(QRegExp::RegExp) << true << 5; - QTest::newRow("\"c.*/c.*.pem\" regexp der") << QString("c.*/c.*.pem") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"c.*/c.*.pem\" wildcard pem") << QString("c.*/c.*.pem") << int(QRegExp::Wildcard) << true << 0; - QTest::newRow("\"c.*/c.*.pem\" wildcard der") << QString("c.*/c.*.pem") << int(QRegExp::Wildcard) << false << 0; - QTest::newRow("\"d.*/c.*.pem\" fixed pem") << QString("d.*/c.*.pem") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("\"d.*/c.*.pem\" fixed der") << QString("d.*/c.*.pem") << int(QRegExp::FixedString) << false << 0; - QTest::newRow("\"d.*/c.*.pem\" regexp pem") << QString("d.*/c.*.pem") << int(QRegExp::RegExp) << true << 0; - QTest::newRow("\"d.*/c.*.pem\" regexp der") << QString("d.*/c.*.pem") << int(QRegExp::RegExp) << false << 0; - QTest::newRow("\"d.*/c.*.pem\" wildcard pem") << QString("d.*/c.*.pem") << int(QRegExp::Wildcard) << true << 0; - QTest::newRow("\"d.*/c.*.pem\" wildcard der") << QString("d.*/c.*.pem") << int(QRegExp::Wildcard) << false << 0; + QTest::newRow("\"certificates\" fixed pem") << QString(":/certificates") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("\"certificates\" fixed der") << QString(":/certificates") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"certificates\" regexp pem") << QString(":/certificates") << int(QRegExp::RegExp) << true << 0; + QTest::newRow("\"certificates\" regexp der") << QString(":/certificates") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"certificates\" wildcard pem") << QString(":/certificates") << int(QRegExp::Wildcard) << true << 0; + QTest::newRow("\"certificates\" wildcard der") << QString(":/certificates") << int(QRegExp::Wildcard) << false << 0; + QTest::newRow("\"certificates/cert.pem\" fixed pem") << QString(":/certificates/cert.pem") << int(QRegExp::FixedString) << true << 1; + QTest::newRow("\"certificates/cert.pem\" fixed der") << QString(":/certificates/cert.pem") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"certificates/cert.pem\" regexp pem") << QString(":/certificates/cert.pem") << int(QRegExp::RegExp) << true << 1; + QTest::newRow("\"certificates/cert.pem\" regexp der") << QString(":/certificates/cert.pem") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"certificates/cert.pem\" wildcard pem") << QString(":/certificates/cert.pem") << int(QRegExp::Wildcard) << true << 1; + QTest::newRow("\"certificates/cert.pem\" wildcard der") << QString(":/certificates/cert.pem") << int(QRegExp::Wildcard) << false << 0; + QTest::newRow("\"certificates/*\" fixed pem") << QString(":/certificates/*") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("\"certificates/*\" fixed der") << QString(":/certificates/*") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"certificates/*\" regexp pem") << QString(":/certificates/*") << int(QRegExp::RegExp) << true << 0; + QTest::newRow("\"certificates/*\" regexp der") << QString(":/certificates/*") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"certificates/*\" wildcard pem") << QString(":/certificates/*") << int(QRegExp::Wildcard) << true << 7; + QTest::newRow("\"certificates/ca*\" wildcard pem") << QString(":/certificates/ca*") << int(QRegExp::Wildcard) << true << 1; + QTest::newRow("\"certificates/cert*\" wildcard pem") << QString(":/certificates/cert*") << int(QRegExp::Wildcard) << true << 4; + QTest::newRow("\"certificates/cert-[sure]*\" wildcard pem") << QString(":/certificates/cert-[sure]*") << int(QRegExp::Wildcard) << true << 3; + QTest::newRow("\"certificates/cert-[not]*\" wildcard pem") << QString(":/certificates/cert-[not]*") << int(QRegExp::Wildcard) << true << 0; + QTest::newRow("\"certificates/*\" wildcard der") << QString(":/certificates/*") << int(QRegExp::Wildcard) << false << 2; + QTest::newRow("\"c*/c*.pem\" fixed pem") << QString(":/c*/c*.pem") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("\"c*/c*.pem\" fixed der") << QString(":/c*/c*.pem") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"c*/c*.pem\" regexp pem") << QString(":/c*/c*.pem") << int(QRegExp::RegExp) << true << 0; + QTest::newRow("\"c*/c*.pem\" regexp der") << QString(":/c*/c*.pem") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"c*/c*.pem\" wildcard pem") << QString(":/c*/c*.pem") << int(QRegExp::Wildcard) << true << 5; + QTest::newRow("\"c*/c*.pem\" wildcard der") << QString(":/c*/c*.pem") << int(QRegExp::Wildcard) << false << 0; + QTest::newRow("\"d*/c*.pem\" fixed pem") << QString(":/d*/c*.pem") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("\"d*/c*.pem\" fixed der") << QString(":/d*/c*.pem") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"d*/c*.pem\" regexp pem") << QString(":/d*/c*.pem") << int(QRegExp::RegExp) << true << 0; + QTest::newRow("\"d*/c*.pem\" regexp der") << QString(":/d*/c*.pem") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"d*/c*.pem\" wildcard pem") << QString(":/d*/c*.pem") << int(QRegExp::Wildcard) << true << 0; + QTest::newRow("\"d*/c*.pem\" wildcard der") << QString(":/d*/c*.pem") << int(QRegExp::Wildcard) << false << 0; + QTest::newRow("\"c.*/c.*.pem\" fixed pem") << QString(":/c.*/c.*.pem") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("\"c.*/c.*.pem\" fixed der") << QString(":/c.*/c.*.pem") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"c.*/c.*.pem\" regexp pem") << QString(":/c.*/c.*.pem") << int(QRegExp::RegExp) << true << 5; + QTest::newRow("\"c.*/c.*.pem\" regexp der") << QString(":/c.*/c.*.pem") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"c.*/c.*.pem\" wildcard pem") << QString(":/c.*/c.*.pem") << int(QRegExp::Wildcard) << true << 0; + QTest::newRow("\"c.*/c.*.pem\" wildcard der") << QString(":/c.*/c.*.pem") << int(QRegExp::Wildcard) << false << 0; + QTest::newRow("\"d.*/c.*.pem\" fixed pem") << QString(":/d.*/c.*.pem") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("\"d.*/c.*.pem\" fixed der") << QString(":/d.*/c.*.pem") << int(QRegExp::FixedString) << false << 0; + QTest::newRow("\"d.*/c.*.pem\" regexp pem") << QString(":/d.*/c.*.pem") << int(QRegExp::RegExp) << true << 0; + QTest::newRow("\"d.*/c.*.pem\" regexp der") << QString(":/d.*/c.*.pem") << int(QRegExp::RegExp) << false << 0; + QTest::newRow("\"d.*/c.*.pem\" wildcard pem") << QString(":/d.*/c.*.pem") << int(QRegExp::Wildcard) << true << 0; + QTest::newRow("\"d.*/c.*.pem\" wildcard der") << QString(":/d.*/c.*.pem") << int(QRegExp::Wildcard) << false << 0; #ifdef Q_OS_LINUX - QTest::newRow("absolute path wildcard pem") << (testDataDir + "/certificates/*.pem") << int(QRegExp::Wildcard) << true << 7; + QTest::newRow("absolute path wildcard pem") << (":/certificates/*.pem") << int(QRegExp::Wildcard) << true << 7; #endif - QTest::newRow("trailing-whitespace") << QString("more-certificates/trailing-whitespace.pem") << int(QRegExp::FixedString) << true << 1; - QTest::newRow("no-ending-newline") << QString("more-certificates/no-ending-newline.pem") << int(QRegExp::FixedString) << true << 1; - QTest::newRow("malformed-just-begin") << QString("more-certificates/malformed-just-begin.pem") << int(QRegExp::FixedString) << true << 0; - QTest::newRow("malformed-just-begin-no-newline") << QString("more-certificates/malformed-just-begin-no-newline.pem") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("trailing-whitespace") << QString(":/more-certificates/trailing-whitespace.pem") << int(QRegExp::FixedString) << true << 1; + QTest::newRow("no-ending-newline") << QString(":/more-certificates/no-ending-newline.pem") << int(QRegExp::FixedString) << true << 1; + QTest::newRow("malformed-just-begin") << QString(":/more-certificates/malformed-just-begin.pem") << int(QRegExp::FixedString) << true << 0; + QTest::newRow("malformed-just-begin-no-newline") << QString(":/more-certificates/malformed-just-begin-no-newline.pem") << int(QRegExp::FixedString) << true << 0; } void tst_QSslCertificate::fromPath() @@ -722,7 +700,7 @@ void tst_QSslCertificate::certInfo() "dc:c2:eb:b7:bb:50:18:05:ba:ad:af:08:49:fe:98:63" "55:ba:e7:fb:95:5d:91"; - QSslCertificate cert = QSslCertificate::fromPath("certificates/cert.pem", QSsl::Pem, + QSslCertificate cert = QSslCertificate::fromPath(":/certificates/cert.pem", QSsl::Pem, QRegExp::FixedString).first(); QVERIFY(!cert.isNull()); @@ -779,7 +757,7 @@ void tst_QSslCertificate::certInfo() void tst_QSslCertificate::certInfoQByteArray() { - QSslCertificate cert = QSslCertificate::fromPath("certificates/cert.pem", QSsl::Pem, + QSslCertificate cert = QSslCertificate::fromPath(":/certificates/cert.pem", QSsl::Pem, QRegExp::FixedString).first(); QVERIFY(!cert.isNull()); @@ -828,11 +806,11 @@ void tst_QSslCertificate::task256066toPem() void tst_QSslCertificate::nulInCN() { -#ifdef QT_SECURETRANSPORT +#if defined(QT_SECURETRANSPORT) || defined(Q_OS_WINRT) QSKIP("Generic QSslCertificatePrivate fails this test"); #endif QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/badguy-nul-cn.crt"); + QSslCertificate::fromPath(":/more-certificates/badguy-nul-cn.crt"); QCOMPARE(certList.size(), 1); const QSslCertificate &cert = certList.at(0); @@ -847,11 +825,11 @@ void tst_QSslCertificate::nulInCN() void tst_QSslCertificate::nulInSan() { -#ifdef QT_SECURETRANSPORT +#if defined(QT_SECURETRANSPORT) || defined(Q_OS_WINRT) QSKIP("Generic QSslCertificatePrivate fails this test"); #endif QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/badguy-nul-san.crt"); + QSslCertificate::fromPath(":/more-certificates/badguy-nul-san.crt"); QCOMPARE(certList.size(), 1); const QSslCertificate &cert = certList.at(0); @@ -871,7 +849,7 @@ void tst_QSslCertificate::nulInSan() void tst_QSslCertificate::largeSerialNumber() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/cert-large-serial-number.pem"); + QSslCertificate::fromPath(":/more-certificates/cert-large-serial-number.pem"); QCOMPARE(certList.size(), 1); @@ -883,7 +861,7 @@ void tst_QSslCertificate::largeSerialNumber() void tst_QSslCertificate::largeExpirationDate() // QTBUG-12489 { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/cert-large-expiration-date.pem"); + QSslCertificate::fromPath(":/more-certificates/cert-large-expiration-date.pem"); QCOMPARE(certList.size(), 1); @@ -896,8 +874,8 @@ void tst_QSslCertificate::largeExpirationDate() // QTBUG-12489 void tst_QSslCertificate::blacklistedCertificates() { - QList<QSslCertificate> blacklistedCerts = QSslCertificate::fromPath("more-certificates/blacklisted*.pem", QSsl::Pem, QRegExp::Wildcard); - QVERIFY2(blacklistedCerts.count() > 0, "Please run this test from the source directory"); + QList<QSslCertificate> blacklistedCerts = QSslCertificate::fromPath(":/more-certificates/blacklisted*.pem", QSsl::Pem, QRegExp::Wildcard); + QVERIFY(blacklistedCerts.count() > 0); for (int a = 0; a < blacklistedCerts.count(); a++) { QVERIFY(blacklistedCerts.at(a).isBlacklisted()); } @@ -905,34 +883,34 @@ void tst_QSslCertificate::blacklistedCertificates() void tst_QSslCertificate::selfsignedCertificates() { - QVERIFY(QSslCertificate::fromPath(testDataDir + "/certificates/cert-ss.pem").first().isSelfSigned()); - QVERIFY(!QSslCertificate::fromPath(testDataDir + "/certificates/cert.pem").first().isSelfSigned()); + QVERIFY(QSslCertificate::fromPath(":/certificates/cert-ss.pem").first().isSelfSigned()); + QVERIFY(!QSslCertificate::fromPath(":/certificates/cert.pem").first().isSelfSigned()); QVERIFY(!QSslCertificate().isSelfSigned()); } void tst_QSslCertificate::toText() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/cert-large-expiration-date.pem"); + QSslCertificate::fromPath(":/more-certificates/cert-large-expiration-date.pem"); QCOMPARE(certList.size(), 1); const QSslCertificate &cert = certList.at(0); // Openssl's cert dump method changed slightly between 0.9.8, 1.0.0 and 1.01 versions, so we want it to match any output - QFile f098(testDataDir + "/more-certificates/cert-large-expiration-date.txt.0.9.8"); + QFile f098(":/more-certificates/cert-large-expiration-date.txt.0.9.8"); QVERIFY(f098.open(QIODevice::ReadOnly | QFile::Text)); QByteArray txt098 = f098.readAll(); - QFile f100(testDataDir + "/more-certificates/cert-large-expiration-date.txt.1.0.0"); + QFile f100(":/more-certificates/cert-large-expiration-date.txt.1.0.0"); QVERIFY(f100.open(QIODevice::ReadOnly | QFile::Text)); QByteArray txt100 = f100.readAll(); - QFile f101(testDataDir + "/more-certificates/cert-large-expiration-date.txt.1.0.1"); + QFile f101(":/more-certificates/cert-large-expiration-date.txt.1.0.1"); QVERIFY(f101.open(QIODevice::ReadOnly | QFile::Text)); QByteArray txt101 = f101.readAll(); - QFile f101c(testDataDir + "/more-certificates/cert-large-expiration-date.txt.1.0.1c"); + QFile f101c(":/more-certificates/cert-large-expiration-date.txt.1.0.1c"); QVERIFY(f101c.open(QIODevice::ReadOnly | QFile::Text)); QByteArray txt101c = f101c.readAll(); @@ -950,8 +928,8 @@ void tst_QSslCertificate::toText() void tst_QSslCertificate::multipleCommonNames() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/test-cn-two-cns-cert.pem"); - QVERIFY2(certList.count() > 0, "Please run this test from the source directory"); + QSslCertificate::fromPath(":/more-certificates/test-cn-two-cns-cert.pem"); + QVERIFY(certList.count() > 0); QStringList commonNames = certList[0].subjectInfo(QSslCertificate::CommonName); QVERIFY(commonNames.contains(QString("www.example.com"))); @@ -961,15 +939,15 @@ void tst_QSslCertificate::multipleCommonNames() void tst_QSslCertificate::subjectAndIssuerAttributes() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/test-cn-with-drink-cert.pem"); - QVERIFY2(certList.count() > 0, "Please run this test from the source directory"); + QSslCertificate::fromPath(":/more-certificates/test-cn-with-drink-cert.pem"); + QVERIFY(certList.count() > 0); QList<QByteArray> attributes = certList[0].subjectInfoAttributes(); QVERIFY(attributes.contains(QByteArray("favouriteDrink"))); attributes.clear(); - certList = QSslCertificate::fromPath(testDataDir + "/more-certificates/natwest-banking.pem"); - QVERIFY2(certList.count() > 0, "Please run this test from the source directory"); + certList = QSslCertificate::fromPath(":/more-certificates/natwest-banking.pem"); + QVERIFY(certList.count() > 0); attributes = certList[0].subjectInfoAttributes(); QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3"))); @@ -999,17 +977,17 @@ void tst_QSslCertificate::verify() errors.clear(); // Verify a valid cert signed by a CA - QList<QSslCertificate> caCerts = QSslCertificate::fromPath(testDataDir + "/verify-certs/cacert.pem"); + QList<QSslCertificate> caCerts = QSslCertificate::fromPath(":/verify-certs/cacert.pem"); QSslSocket::addDefaultCaCertificate(caCerts.first()); - toVerify = QSslCertificate::fromPath(testDataDir + "/verify-certs/test-ocsp-good-cert.pem"); + toVerify = QSslCertificate::fromPath(":/verify-certs/test-ocsp-good-cert.pem"); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.count() == 0); errors.clear(); // Test a blacklisted certificate - toVerify = QSslCertificate::fromPath(testDataDir + "/verify-certs/test-addons-mozilla-org-cert.pem"); + toVerify = QSslCertificate::fromPath(":/verify-certs/test-addons-mozilla-org-cert.pem"); errors = QSslCertificate::verify(toVerify); bool foundBlack = false; foreach (const QSslError &error, errors) { @@ -1022,7 +1000,7 @@ void tst_QSslCertificate::verify() errors.clear(); // This one is expired and untrusted - toVerify = QSslCertificate::fromPath(testDataDir + "/more-certificates/cert-large-serial-number.pem"); + toVerify = QSslCertificate::fromPath(":/more-certificates/cert-large-serial-number.pem"); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.contains(QSslError(QSslError::SelfSignedCertificate, toVerify[0]))); VERIFY_VERBOSE(errors.contains(QSslError(QSslError::CertificateExpired, toVerify[0]))); @@ -1030,15 +1008,15 @@ void tst_QSslCertificate::verify() toVerify.clear(); // This one is signed by a valid cert, but the signer is not a valid CA - toVerify << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-intermediate-not-ca-cert.pem").first(); - toVerify << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-ocsp-good-cert.pem").first(); + toVerify << QSslCertificate::fromPath(":/verify-certs/test-intermediate-not-ca-cert.pem").first(); + toVerify << QSslCertificate::fromPath(":/verify-certs/test-ocsp-good-cert.pem").first(); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.contains(QSslError(QSslError::InvalidCaCertificate, toVerify[1]))); toVerify.clear(); // This one is signed by a valid cert, and the signer is a valid CA - toVerify << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-intermediate-is-ca-cert.pem").first(); - toVerify << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-intermediate-ca-cert.pem").first(); + toVerify << QSslCertificate::fromPath(":/verify-certs/test-intermediate-is-ca-cert.pem").first(); + toVerify << QSslCertificate::fromPath(":/verify-certs/test-intermediate-ca-cert.pem").first(); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.count() == 0); @@ -1068,8 +1046,8 @@ QString tst_QSslCertificate::toString(const QList<QSslError>& errors) void tst_QSslCertificate::extensions() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/more-certificates/natwest-banking.pem"); - QVERIFY2(certList.count() > 0, "Please run this test from the source directory"); + QSslCertificate::fromPath(":/more-certificates/natwest-banking.pem"); + QVERIFY(certList.count() > 0); QSslCertificate cert = certList[0]; QList<QSslCertificateExtension> extensions = cert.extensions(); @@ -1166,8 +1144,8 @@ void tst_QSslCertificate::extensions() void tst_QSslCertificate::extensionsCritical() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "/verify-certs/test-addons-mozilla-org-cert.pem"); - QVERIFY2(certList.count() > 0, "Please run this test from the source directory"); + QSslCertificate::fromPath(":/verify-certs/test-addons-mozilla-org-cert.pem"); + QVERIFY(certList.count() > 0); QSslCertificate cert = certList[0]; QList<QSslCertificateExtension> extensions = cert.extensions(); @@ -1249,7 +1227,7 @@ void tst_QSslCertificate::threadSafeConstMethods() if (!QSslSocket::supportsSsl()) return; - QByteArray encoded = readFile(testDataDir + "/certificates/cert.pem"); + QByteArray encoded = readFile(":/certificates/cert.pem"); QSslCertificate certificate(encoded); QVERIFY(!certificate.isNull()); @@ -1287,12 +1265,12 @@ void tst_QSslCertificate::version_data() QTest::newRow("null certificate") << QSslCertificate() << QByteArray(); QList<QSslCertificate> certs; - certs << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-ocsp-good-cert.pem"); + certs << QSslCertificate::fromPath(":/verify-certs/test-ocsp-good-cert.pem"); QTest::newRow("v3 certificate") << certs.first() << QByteArrayLiteral("3"); certs.clear(); - certs << QSslCertificate::fromPath(testDataDir + "/certificates/cert.pem"); + certs << QSslCertificate::fromPath(":/certificates/cert.pem"); QTest::newRow("v1 certificate") << certs.first() << QByteArrayLiteral("1"); } @@ -1314,7 +1292,7 @@ void tst_QSslCertificate::pkcs12() return; } - QFile f(testDataDir + QLatin1String("/pkcs12/leaf.p12")); + QFile f(QLatin1String(":/pkcs12/leaf.p12")); bool ok = f.open(QIODevice::ReadOnly); QVERIFY(ok); @@ -1329,12 +1307,12 @@ void tst_QSslCertificate::pkcs12() QVERIFY(ok); f.close(); - QList<QSslCertificate> leafCert = QSslCertificate::fromPath(testDataDir + QLatin1String("/pkcs12/leaf.crt")); + QList<QSslCertificate> leafCert = QSslCertificate::fromPath(QLatin1String(":/pkcs12/leaf.crt")); QVERIFY(!leafCert.isEmpty()); QCOMPARE(cert, leafCert.first()); - QFile f2(testDataDir + QLatin1String("/pkcs12/leaf.key")); + QFile f2(QLatin1String(":/pkcs12/leaf.key")); ok = f2.open(QIODevice::ReadOnly); QVERIFY(ok); @@ -1344,7 +1322,7 @@ void tst_QSslCertificate::pkcs12() QVERIFY(!leafKey.isNull()); QCOMPARE(key, leafKey); - QList<QSslCertificate> caCert = QSslCertificate::fromPath(testDataDir + QLatin1String("/pkcs12/inter.crt")); + QList<QSslCertificate> caCert = QSslCertificate::fromPath(QLatin1String(":/pkcs12/inter.crt")); QVERIFY(!caCert.isEmpty()); QVERIFY(!caCerts.isEmpty()); @@ -1352,7 +1330,7 @@ void tst_QSslCertificate::pkcs12() QCOMPARE(caCerts, caCert); // QTBUG-62335 - Fail (found no private key) but don't crash: - QFile nocert(testDataDir + QLatin1String("/pkcs12/leaf-nokey.p12")); + QFile nocert(QLatin1String(":/pkcs12/leaf-nokey.p12")); ok = nocert.open(QIODevice::ReadOnly); QVERIFY(ok); QTest::ignoreMessage(QtWarningMsg, "Unable to convert private key"); diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro index 8c3877631a..760369df39 100644 --- a/tests/auto/network/ssl/qsslkey/qsslkey.pro +++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro @@ -9,4 +9,7 @@ qtConfig(private_tests) { TARGET = tst_qsslkey +RESOURCES += \ + qsslkey.qrc + TESTDATA += keys/* rsa-without-passphrase.pem rsa-with-passphrase.pem diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.qrc b/tests/auto/network/ssl/qsslkey/qsslkey.qrc new file mode 100644 index 0000000000..4b994ac7af --- /dev/null +++ b/tests/auto/network/ssl/qsslkey/qsslkey.qrc @@ -0,0 +1,65 @@ +<RCC> + <qresource prefix="/"> + <file>rsa-without-passphrase.pem</file> + <file>rsa-with-passphrase-3des.pem</file> + <file>rsa-with-passphrase-des.pem</file> + <file>rsa-with-passphrase-rc2.pem</file> + <file>keys/dsa-pri-1024.der</file> + <file>keys/dsa-pri-1024.pem</file> + <file>keys/dsa-pri-512.der</file> + <file>keys/dsa-pri-512.pem</file> + <file>keys/dsa-pri-576.der</file> + <file>keys/dsa-pri-576.pem</file> + <file>keys/dsa-pri-960.der</file> + <file>keys/dsa-pri-960.pem</file> + <file>keys/dsa-pub-1024.der</file> + <file>keys/dsa-pub-1024.pem</file> + <file>keys/dsa-pub-512.der</file> + <file>keys/dsa-pub-512.pem</file> + <file>keys/dsa-pub-576.der</file> + <file>keys/dsa-pub-576.pem</file> + <file>keys/dsa-pub-960.der</file> + <file>keys/dsa-pub-960.pem</file> + <file>keys/ec-pri-224-secp224r1.der</file> + <file>keys/ec-pri-224-secp224r1.pem</file> + <file>keys/ec-pri-256-prime256v1.der</file> + <file>keys/ec-pri-256-prime256v1.pem</file> + <file>keys/ec-pri-384-secp384r1.der</file> + <file>keys/ec-pri-384-secp384r1.pem</file> + <file>keys/ec-pub-224-secp224r1.der</file> + <file>keys/ec-pub-224-secp224r1.pem</file> + <file>keys/ec-pub-256-prime256v1.der</file> + <file>keys/ec-pub-256-prime256v1.pem</file> + <file>keys/ec-pub-384-secp384r1.der</file> + <file>keys/ec-pub-384-secp384r1.pem</file> + <file>keys/genkeys.sh</file> + <file>keys/rsa-pri-1023.der</file> + <file>keys/rsa-pri-1023.pem</file> + <file>keys/rsa-pri-1024.der</file> + <file>keys/rsa-pri-1024.pem</file> + <file>keys/rsa-pri-2048.der</file> + <file>keys/rsa-pri-2048.pem</file> + <file>keys/rsa-pri-40.der</file> + <file>keys/rsa-pri-40.pem</file> + <file>keys/rsa-pri-511.der</file> + <file>keys/rsa-pri-511.pem</file> + <file>keys/rsa-pri-512.der</file> + <file>keys/rsa-pri-512.pem</file> + <file>keys/rsa-pri-999.der</file> + <file>keys/rsa-pri-999.pem</file> + <file>keys/rsa-pub-1023.der</file> + <file>keys/rsa-pub-1023.pem</file> + <file>keys/rsa-pub-1024.der</file> + <file>keys/rsa-pub-1024.pem</file> + <file>keys/rsa-pub-2048.der</file> + <file>keys/rsa-pub-2048.pem</file> + <file>keys/rsa-pub-40.der</file> + <file>keys/rsa-pub-40.pem</file> + <file>keys/rsa-pub-511.der</file> + <file>keys/rsa-pub-511.pem</file> + <file>keys/rsa-pub-512.der</file> + <file>keys/rsa-pub-512.pem</file> + <file>keys/rsa-pub-999.der</file> + <file>keys/rsa-pub-999.pem</file> + </qresource> +</RCC> diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp index 0112af4ed7..3c88cddf9a 100644 --- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp +++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp @@ -97,17 +97,11 @@ private slots: #endif #endif -private: - QString testDataDir; }; void tst_QSslKey::initTestCase() { - testDataDir = QFileInfo(QFINDTESTDATA("rsa-without-passphrase.pem")).absolutePath(); - if (testDataDir.isEmpty()) - testDataDir = QCoreApplication::applicationDirPath(); - - QDir dir(testDataDir + "/keys"); + QDir dir(":/keys"); QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable); QRegExp rx(QLatin1String("^(rsa|dsa|ec)-(pub|pri)-(\\d+)-?\\w*\\.(pem|der)$")); foreach (QFileInfo fileInfo, fileInfoList) { @@ -392,9 +386,9 @@ void tst_QSslKey::passphraseChecks_data() { QTest::addColumn<QString>("fileName"); - QTest::newRow("DES") << QString(testDataDir + "/rsa-with-passphrase-des.pem"); - QTest::newRow("3DES") << QString(testDataDir + "/rsa-with-passphrase-3des.pem"); - QTest::newRow("RC2") << QString(testDataDir + "/rsa-with-passphrase-rc2.pem"); + QTest::newRow("DES") << QString(":/rsa-with-passphrase-des.pem"); + QTest::newRow("3DES") << QString(":/rsa-with-passphrase-3des.pem"); + QTest::newRow("RC2") << QString(":/rsa-with-passphrase-rc2.pem"); } void tst_QSslKey::passphraseChecks() @@ -440,7 +434,7 @@ void tst_QSslKey::passphraseChecks() void tst_QSslKey::noPassphraseChecks() { // be sure and check a key without passphrase too - QString fileName(testDataDir + "/rsa-without-passphrase.pem"); + QString fileName(":/rsa-without-passphrase.pem"); QFile keyFile(fileName); { if (!keyFile.isOpen()) diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro index 4ccf0f24b0..5249c1aac5 100644 --- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro +++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro @@ -14,6 +14,9 @@ win32 { } } +RESOURCES += \ + qsslsocket.qrc + DEFINES += SRCDIR=\\\"$$PWD/\\\" requires(qtConfig(private_tests)) diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.qrc b/tests/auto/network/ssl/qsslsocket/qsslsocket.qrc new file mode 100644 index 0000000000..fb486c8e0b --- /dev/null +++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.qrc @@ -0,0 +1,21 @@ +<RCC> + <qresource prefix="/"> + <file>certs/aspiriniks.ca.crt</file> + <file>certs/bogus-ca.crt</file> + <file>certs/bogus-ca.key</file> + <file>certs/bogus-client.crt</file> + <file>certs/bogus-client.key</file> + <file>certs/bogus-server.crt</file> + <file>certs/bogus-server.key</file> + <file>certs/ca.crt</file> + <file>certs/fake-login.live.com.key</file> + <file>certs/fake-login.live.com.pem</file> + <file>certs/fluke.cert</file> + <file>certs/fluke.key</file> + <file>certs/inter.crt</file> + <file>certs/leaf.crt</file> + <file>certs/leaf.key</file> + <file>certs/qt-test-server-cacert.pem</file> + <file>certs/xn--schufele-2za.crt</file> + </qresource> +</RCC> diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 8324a9c8fa..4e12a16696 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -705,7 +705,7 @@ void tst_QSslSocket::connectToHostEncrypted() QSslSocketPtr socket = newSocket(); this->socket = socket.data(); - QVERIFY(socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"))); + QVERIFY(socket->addCaCertificates(QLatin1String(":/certs/qt-test-server-cacert.pem"))); #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); @@ -739,7 +739,7 @@ void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName() QSslSocketPtr socket = newSocket(); this->socket = socket.data(); - socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + socket->addCaCertificates(QLatin1String(":/certs/qt-test-server-cacert.pem")); #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); @@ -803,10 +803,10 @@ void tst_QSslSocket::localCertificate() // values. This test should just run the codepath inside qsslsocket_openssl.cpp QSslSocketPtr socket = newSocket(); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); + QList<QSslCertificate> localCert = QSslCertificate::fromPath(":/certs/qt-test-server-cacert.pem"); socket->setCaCertificates(localCert); - socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert")); - socket->setPrivateKey(QLatin1String(SRCDIR "certs/fluke.key")); + socket->setLocalCertificate(QLatin1String(":/certs/fluke.cert")); + socket->setPrivateKey(QLatin1String(":/certs/fluke.key")); socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); QFETCH_GLOBAL(bool, setProxy); @@ -832,7 +832,7 @@ void tst_QSslSocket::peerCertificateChain() QSslSocketPtr socket = newSocket(); this->socket = socket.data(); - QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(QLatin1String(":/certs/qt-test-server-cacert.pem")); QCOMPARE(caCertificates.count(), 1); socket->addCaCertificates(caCertificates); #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND @@ -895,7 +895,7 @@ void tst_QSslSocket::privateKeyOpaque() if (!QSslSocket::supportsSsl()) return; - QFile file(SRCDIR "certs/fluke.key"); + QFile file(":/certs/fluke.key"); QVERIFY(file.open(QIODevice::ReadOnly)); QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); QVERIFY(!key.isNull()); @@ -908,9 +908,9 @@ void tst_QSslSocket::privateKeyOpaque() // values. This test should just run the codepath inside qsslsocket_openssl.cpp QSslSocketPtr socket = newSocket(); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); + QList<QSslCertificate> localCert = QSslCertificate::fromPath(":/certs/qt-test-server-cacert.pem"); socket->setCaCertificates(localCert); - socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert")); + socket->setLocalCertificate(QLatin1String(":/certs/fluke.cert")); socket->setPrivateKey(QSslKey(reinterpret_cast<Qt::HANDLE>(pkey))); socket->setPeerVerifyMode(QSslSocket::QueryPeer); @@ -928,7 +928,7 @@ void tst_QSslSocket::protocol() QSslSocketPtr socket = newSocket(); this->socket = socket.data(); - QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); + QList<QSslCertificate> certs = QSslCertificate::fromPath(":/certs/qt-test-server-cacert.pem"); socket->setCaCertificates(certs); #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND @@ -1075,8 +1075,8 @@ class SslServer : public QTcpServer { Q_OBJECT public: - SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", - const QString &certFile = SRCDIR "certs/fluke.cert", + SslServer(const QString &keyFile = ":/certs/fluke.key", + const QString &certFile = ":/certs/fluke.cert", const QString &interFile = QString()) : socket(0), config(QSslConfiguration::defaultConfiguration()), @@ -1167,6 +1167,9 @@ protected slots: void tst_QSslSocket::protocolServerSide_data() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QTest::addColumn<QSsl::SslProtocol>("serverProtocol"); QTest::addColumn<QSsl::SslProtocol>("clientProtocol"); QTest::addColumn<bool>("works"); @@ -1347,6 +1350,9 @@ void tst_QSslSocket::protocolServerSide() void tst_QSslSocket::serverCipherPreferences() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) { qWarning("SSL not supported, skipping test"); return; @@ -1422,7 +1428,7 @@ void tst_QSslSocket::setCaCertificates() QSslSocket socket; QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); - socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem")); + socket.setCaCertificates(QSslCertificate::fromPath(":/certs/qt-test-server-cacert.pem")); QCOMPARE(socket.caCertificates().size(), 1); socket.setCaCertificates(socket.defaultCaCertificates()); QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); @@ -1438,7 +1444,7 @@ void tst_QSslSocket::localCertificateChain() return; QSslSocket socket; - socket.setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert")); + socket.setLocalCertificate(QLatin1String(":/certs/fluke.cert")); QSslConfiguration conf = socket.sslConfiguration(); QList<QSslCertificate> chain = conf.localCertificateChain(); @@ -1449,6 +1455,9 @@ void tst_QSslSocket::localCertificateChain() void tst_QSslSocket::setLocalCertificateChain() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) return; @@ -1456,9 +1465,9 @@ void tst_QSslSocket::setLocalCertificateChain() if (setProxy) return; - SslServer server(QLatin1String(SRCDIR "certs/leaf.key"), - QLatin1String(SRCDIR "certs/leaf.crt"), - QLatin1String(SRCDIR "certs/inter.crt")); + SslServer server(QLatin1String(":/certs/leaf.key"), + QLatin1String(":/certs/leaf.crt"), + QLatin1String(":/certs/inter.crt")); QVERIFY(server.listen()); @@ -1486,6 +1495,9 @@ void tst_QSslSocket::setPrivateKey() void tst_QSslSocket::setSocketDescriptor() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) return; @@ -1524,7 +1536,7 @@ void tst_QSslSocket::setSslConfiguration_data() QTest::newRow("empty") << QSslConfiguration() << false; QSslConfiguration conf = QSslConfiguration::defaultConfiguration(); QTest::newRow("default") << conf << false; // does not contain test server cert - QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); + QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(":/certs/qt-test-server-cacert.pem"); conf.setCaCertificates(testServerCert); QTest::newRow("set-root-cert") << conf << true; conf.setProtocol(QSsl::SecureProtocols); @@ -1627,7 +1639,7 @@ void tst_QSslSocket::addDefaultCaCertificate() // Reset the global CA chain QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); - QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); + QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(":/certs/qt-test-server-cacert.pem"); QCOMPARE(flukeCerts.size(), 1); QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates(); QVERIFY(!globalCerts.contains(flukeCerts.first())); @@ -1739,7 +1751,7 @@ void tst_QSslSocket::isMatchingHostname() { // with normalization: (the certificate has *.SCHÄUFELE.DE as a CN) // openssl req -x509 -nodes -subj "/CN=*.SCHÄUFELE.DE" -newkey rsa:512 -keyout /dev/null -out xn--schufele-2za.crt - QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/xn--schufele-2za.crt"); + QList<QSslCertificate> certs = QSslCertificate::fromPath(":/certs/xn--schufele-2za.crt"); QVERIFY(!certs.isEmpty()); QSslCertificate cert = certs.first(); @@ -1795,7 +1807,7 @@ protected: socket->ignoreSslErrors(); // Only set the certificate - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert"); + QList<QSslCertificate> localCert = QSslCertificate::fromPath(":/certs/fluke.cert"); QVERIFY(!localCert.isEmpty()); QVERIFY(!localCert.first().isNull()); socket->setLocalCertificate(localCert.first()); @@ -1808,6 +1820,9 @@ protected: void tst_QSslSocket::setEmptyKey() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) return; @@ -1829,6 +1844,9 @@ void tst_QSslSocket::setEmptyKey() void tst_QSslSocket::spontaneousWrite() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -1874,6 +1892,9 @@ void tst_QSslSocket::spontaneousWrite() void tst_QSslSocket::setReadBufferSize() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2024,13 +2045,13 @@ protected: socket = new QSslSocket(this); connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); - QFile file(SRCDIR "certs/fluke.key"); + QFile file(":/certs/fluke.key"); QVERIFY(file.open(QIODevice::ReadOnly)); QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); QVERIFY(!key.isNull()); socket->setPrivateKey(key); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert"); + QList<QSslCertificate> localCert = QSslCertificate::fromPath(":/certs/fluke.cert"); QVERIFY(!localCert.isEmpty()); QVERIFY(!localCert.first().isNull()); socket->setLocalCertificate(localCert.first()); @@ -2134,6 +2155,9 @@ void tst_QSslSocket::waitForMinusOne() #ifdef Q_OS_WIN QSKIP("QTBUG-24451 - indefinite wait may hang"); #endif +#ifdef Q_OS_WINRT // This can stay in case the one above goes away + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2203,8 +2227,8 @@ protected: { socket = new QSslSocket(this); - socket->setPrivateKey(SRCDIR "certs/fluke.key"); - socket->setLocalCertificate(SRCDIR "certs/fluke.cert"); + socket->setPrivateKey(":/certs/fluke.key"); + socket->setLocalCertificate(":/certs/fluke.cert"); socket->setSocketDescriptor(socketDescriptor); socket->startServerEncryption(); } @@ -2212,6 +2236,9 @@ protected: void tst_QSslSocket::verifyMode() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2319,7 +2346,7 @@ void tst_QSslSocket::resetProxy() // make sure the connection works, and then set a nonsense proxy, and then // make sure it does not work anymore QSslSocket socket; - socket.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + socket.addCaCertificates(QLatin1String(":/certs/qt-test-server-cacert.pem")); socket.setProxy(goodProxy); socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString())); @@ -2338,7 +2365,7 @@ void tst_QSslSocket::resetProxy() // set the nonsense proxy and make sure the connection does not work, // and then set the right proxy and make sure it works QSslSocket socket2; - socket2.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + socket2.addCaCertificates(QLatin1String(":/certs/qt-test-server-cacert.pem")); socket2.setProxy(badProxy); socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); QVERIFY(! socket2.waitForConnected(10000)); @@ -2357,7 +2384,7 @@ void tst_QSslSocket::ignoreSslErrorsList_data() // construct the list of errors that we will get with the SSL handshake and that we will ignore QList<QSslError> expectedSslErrors; // fromPath gives us a list of certs, but it actually only contains one - QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(":/certs/qt-test-server-cacert.pem")); QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0)); QSslError wrongError(FLUKE_CERTIFICATE_ERROR); @@ -2430,6 +2457,9 @@ void tst_QSslSocket::ignoreSslErrorsListWithSlot() void tst_QSslSocket::abortOnSslErrors() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2526,11 +2556,14 @@ void tst_QSslSocket::writeBigChunk() void tst_QSslSocket::blacklistedCertificates() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; - SslServer server(SRCDIR "certs/fake-login.live.com.key", SRCDIR "certs/fake-login.live.com.pem"); + SslServer server(":/certs/fake-login.live.com.key", ":/certs/fake-login.live.com.pem"); QSslSocket *receiver = new QSslSocket(this); connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop())); @@ -2642,7 +2675,7 @@ void tst_QSslSocket::resume_data() QTest::newRow("DoNotIgnoreErrors") << false << QList<QSslError>() << false; QTest::newRow("ignoreAllErrors") << true << QList<QSslError>() << true; - QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(":/certs/qt-test-server-cacert.pem")); QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0)); QSslError wrongError(FLUKE_CERTIFICATE_ERROR); errorsList.append(wrongError); @@ -2712,8 +2745,8 @@ class WebSocket : public QSslSocket Q_OBJECT public: explicit WebSocket(qintptr socketDescriptor, - const QString &keyFile = SRCDIR "certs/fluke.key", - const QString &certFile = SRCDIR "certs/fluke.cert"); + const QString &keyFile = ":/certs/fluke.key", + const QString &certFile = ":/certs/fluke.cert"); protected slots: void onReadyReadFirstBytes(void); @@ -2783,6 +2816,9 @@ protected: void tst_QSslSocket::qtbug18498_peek() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2850,6 +2886,9 @@ protected: void tst_QSslSocket::qtbug18498_peek2() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2918,13 +2957,13 @@ void tst_QSslSocket::qtbug18498_peek2() QCOMPARE(a[2], 'S'); QCOMPARE(server->readAll(), QByteArray("TLS\r\n")); - QFile file(SRCDIR "certs/fluke.key"); + QFile file(":/certs/fluke.key"); QVERIFY(file.open(QIODevice::ReadOnly)); QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); QVERIFY(!key.isNull()); server->setPrivateKey(key); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert"); + QList<QSslCertificate> localCert = QSslCertificate::fromPath(":/certs/fluke.cert"); QVERIFY(!localCert.isEmpty()); QVERIFY(!localCert.first().isNull()); server->setLocalCertificate(localCert.first()); @@ -2964,6 +3003,9 @@ void tst_QSslSocket::qtbug18498_peek2() void tst_QSslSocket::dhServer() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) QSKIP("No SSL support"); @@ -3073,6 +3115,9 @@ void tst_QSslSocket::dhServerCustomParams() void tst_QSslSocket::ecdhServer() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) { qWarning("SSL not supported, skipping test"); return; @@ -3118,10 +3163,10 @@ void tst_QSslSocket::verifyClientCertificate_data() QTest::newRow("NoCert:VerifyPeer") << QSslSocket::VerifyPeer << noCerts << noKey << false; // self-signed certificate - QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert"); + QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(":/certs/fluke.cert"); QCOMPARE(flukeCerts.size(), 1); - QFile flukeFile(SRCDIR "certs/fluke.key"); + QFile flukeFile(":/certs/fluke.key"); QVERIFY(flukeFile.open(QIODevice::ReadOnly)); QSslKey flukeKey(flukeFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); QVERIFY(!flukeKey.isNull()); @@ -3132,10 +3177,10 @@ void tst_QSslSocket::verifyClientCertificate_data() QTest::newRow("SelfSignedCert:VerifyPeer") << QSslSocket::VerifyPeer << flukeCerts << flukeKey << false; // valid certificate, but wrong usage (server certificate) - QList<QSslCertificate> serverCerts = QSslCertificate::fromPath(SRCDIR "certs/bogus-server.crt"); + QList<QSslCertificate> serverCerts = QSslCertificate::fromPath(":/certs/bogus-server.crt"); QCOMPARE(serverCerts.size(), 1); - QFile serverFile(SRCDIR "certs/bogus-server.key"); + QFile serverFile(":/certs/bogus-server.key"); QVERIFY(serverFile.open(QIODevice::ReadOnly)); QSslKey serverKey(serverFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); QVERIFY(!serverKey.isNull()); @@ -3146,10 +3191,10 @@ void tst_QSslSocket::verifyClientCertificate_data() QTest::newRow("ValidServerCert:VerifyPeer") << QSslSocket::VerifyPeer << serverCerts << serverKey << false; // valid certificate, correct usage (client certificate) - QList<QSslCertificate> validCerts = QSslCertificate::fromPath(SRCDIR "certs/bogus-client.crt"); + QList<QSslCertificate> validCerts = QSslCertificate::fromPath(":/certs/bogus-client.crt"); QCOMPARE(validCerts.size(), 1); - QFile validFile(SRCDIR "certs/bogus-client.key"); + QFile validFile(":/certs/bogus-client.key"); QVERIFY(validFile.open(QIODevice::ReadOnly)); QSslKey validKey(validFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); QVERIFY(!validKey.isNull()); @@ -3160,7 +3205,7 @@ void tst_QSslSocket::verifyClientCertificate_data() QTest::newRow("ValidClientCert:VerifyPeer") << QSslSocket::VerifyPeer << validCerts << validKey << true; // valid certificate, correct usage (client certificate), with chain - validCerts += QSslCertificate::fromPath(SRCDIR "certs/bogus-ca.crt"); + validCerts += QSslCertificate::fromPath(":/certs/bogus-ca.crt"); QCOMPARE(validCerts.size(), 2); QTest::newRow("ValidClientCert:AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << validCerts << validKey << true; @@ -3179,6 +3224,9 @@ void tst_QSslSocket::verifyClientCertificate() // success instead of failure etc.). QSKIP("This test can not work with Secure Transport"); #endif +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif if (!QSslSocket::supportsSsl()) { qWarning("SSL not supported, skipping test"); return; @@ -3190,7 +3238,7 @@ void tst_QSslSocket::verifyClientCertificate() QFETCH(QSslSocket::PeerVerifyMode, peerVerifyMode); SslServer server; - server.addCaCertificates = QLatin1String(SRCDIR "certs/bogus-ca.crt"); + server.addCaCertificates = QLatin1String(":/certs/bogus-ca.crt"); server.ignoreSslErrors = false; server.peerVerifyMode = peerVerifyMode; QVERIFY(server.listen()); @@ -3689,6 +3737,9 @@ void tst_QSslSocket::simplePskConnect() void tst_QSslSocket::ephemeralServerKey_data() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QTest::addColumn<QString>("cipher"); QTest::addColumn<bool>("emptyKey"); @@ -3763,6 +3814,9 @@ void tst_QSslSocket::allowedProtocolNegotiation() void tst_QSslSocket::pskServer() { +#ifdef Q_OS_WINRT + QSKIP("Server-side encryption is not implemented on WinRT."); +#endif QFETCH_GLOBAL(bool, setProxy); if (!QSslSocket::supportsSsl() || setProxy) return; |