From af96c6fed931564c95037539f07e9c8e33c69529 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Thu, 25 Jul 2013 12:05:29 -0400 Subject: QHttpMultiPart: fix data corruption in readData method When readData() is called repeatedly, we need to keep track which part of the multipart message we are currently reading from. Hereby we also need to take the boundary size into account, and not only the size of the multipart; otherwise we would skip a not completely read part. This would then later lead to advancing the read pointer by negative indexes and data loss. Task-number: QTBUG-32534 Change-Id: Ibb6dff16adaf4ea67181d23d1d0c8459e33a0ed0 Reviewed-by: Jonathan Liu Reviewed-by: Shane Kearns --- src/network/access/qhttpmultipart.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qhttpmultipart.cpp b/src/network/access/qhttpmultipart.cpp index 4397ef8205..5985ed94e0 100644 --- a/src/network/access/qhttpmultipart.cpp +++ b/src/network/access/qhttpmultipart.cpp @@ -497,7 +497,8 @@ qint64 QHttpMultiPartIODevice::readData(char *data, qint64 maxSize) // skip the parts we have already read while (index < multiPart->parts.count() && - readPointer >= partOffsets.at(index) + multiPart->parts.at(index).d->size()) + readPointer >= partOffsets.at(index) + multiPart->parts.at(index).d->size() + + multiPart->boundary.count() + 6) // 6 == 2 boundary dashes, \r\n after boundary, \r\n after multipart index++; // read the data -- cgit v1.2.3 From 88f4baf089fddb227a22c5bc220d4a64610c0821 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 29 Jul 2013 12:25:48 +0200 Subject: Windows: Clear window under mouse in destruction of platform window. Task-number: QTBUG-32042 Change-Id: I8aa5df84b7ca6deb47e0c3eff9a6a7d2c4793553 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowscontext.cpp | 5 +++++ src/plugins/platforms/windows/qwindowscontext.h | 1 + src/plugins/platforms/windows/qwindowsmousehandler.h | 1 + src/plugins/platforms/windows/qwindowswindow.cpp | 5 ++++- 4 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 872fd07729..7c6e82d0dc 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -582,6 +582,11 @@ QWindow *QWindowsContext::windowUnderMouse() const return d->m_mouseHandler.windowUnderMouse(); } +void QWindowsContext::clearWindowUnderMouse() +{ + d->m_mouseHandler.clearWindowUnderMouse(); +} + /*! \brief Find a child window at a screen point. diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index d60b632beb..6b80075379 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -166,6 +166,7 @@ public: unsigned cwex_flags) const; QWindow *windowUnderMouse() const; + void clearWindowUnderMouse(); inline bool windowsProc(HWND hwnd, UINT message, QtWindows::WindowsEventType et, diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index caf30e6b1a..7a7b92ca7e 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -72,6 +72,7 @@ public: static Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderMouse.data(); } + void clearWindowUnderMouse() { m_windowUnderMouse = 0; } private: inline bool translateMouseWheelEvent(QWindow *window, HWND hwnd, diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index dc51dbfc88..6549b9da3e 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -871,6 +871,9 @@ void QWindowsWindow::destroyWindow() qDebug() << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); + QWindowsContext *context = QWindowsContext::instance(); + if (context->windowUnderMouse() == window()) + context->clearWindowUnderMouse(); if (hasMouseCapture()) setMouseGrabEnabled(false); unregisterDropSite(); @@ -893,7 +896,7 @@ void QWindowsWindow::destroyWindow() #endif // !Q_OS_WINCE if (m_data.hwnd != GetDesktopWindow()) DestroyWindow(m_data.hwnd); - QWindowsContext::instance()->removeWindow(m_data.hwnd); + context->removeWindow(m_data.hwnd); m_data.hwnd = 0; } } -- cgit v1.2.3 From 7654f71f80266fd35f3c8b04d2534c876afec3a6 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Tue, 16 Jul 2013 14:18:58 +0200 Subject: Fix handling of non-latin1 shortcuts This patch enables non-latin1 shortcut handling on Qt5/X11. Task-number: QTBUG-32274 Change-Id: Ia084258b956128ffade8eddfbcb18af334d79a59 Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 69 +++++++++++++++++++++--------- src/plugins/platforms/xcb/qxcbkeyboard.h | 4 +- 2 files changed, 51 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index ae8bcb802b..38cbfaf183 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -575,7 +575,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::AltModifier | Qt::ShiftModifier, // 5 Qt::AltModifier | Qt::ControlModifier, // 6 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::NoModifier // Fall-back to raw Key_* + Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts }; Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const @@ -594,8 +594,9 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const return ret; } -void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) +void QXcbKeyboard::readXKBConfig() { + clearXKBConfig(); xcb_generic_error_t *error; xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *config_reply; @@ -626,15 +627,30 @@ void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) length -= len + 1; } while (p < end || i < 5); - xkb_names->rules = qstrdup(names[0]); - xkb_names->model = qstrdup(names[1]); - xkb_names->layout = qstrdup(names[2]); - xkb_names->variant = qstrdup(names[3]); - xkb_names->options = qstrdup(names[4]); + xkb_names.rules = qstrdup(names[0]); + xkb_names.model = qstrdup(names[1]); + xkb_names.layout = qstrdup(names[2]); + xkb_names.variant = qstrdup(names[3]); + xkb_names.options = qstrdup(names[4]); free(config_reply); } +void QXcbKeyboard::clearXKBConfig() +{ + if (xkb_names.rules) + delete[] xkb_names.rules; + if (xkb_names.model) + delete[] xkb_names.model; + if (xkb_names.layout) + delete[] xkb_names.layout; + if (xkb_names.variant) + delete[] xkb_names.variant; + if (xkb_names.options) + delete[] xkb_names.options; + memset(&xkb_names, 0, sizeof(xkb_names)); +} + void QXcbKeyboard::updateKeymap() { m_config = true; @@ -646,22 +662,13 @@ void QXcbKeyboard::updateKeymap() return; } } - - struct xkb_rule_names xkb_names = {0, 0, 0, 0, 0}; - - readXKBConfig(&xkb_names); + readXKBConfig(); // Compile a keymap from RMLVO (rules, models, layouts, variants and options) names if (xkb_keymap) xkb_keymap_unref(xkb_keymap); xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0); - delete[] xkb_names.rules; - delete[] xkb_names.model; - delete[] xkb_names.layout; - delete[] xkb_names.variant; - delete[] xkb_names.options; - if (!xkb_keymap) { qWarning("Qt: Failed to compile a keymap"); m_config = false; @@ -830,7 +837,7 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); xkb_mod_mask_t depressed; - + struct xkb_keymap *fallback_keymap = 0; int qtKey = 0; //obtain a list of possible shortcuts for the given key event for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) { @@ -846,8 +853,23 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const depressed |= (1 << controlMod); // update a keyboard state from a set of explicit masks - xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, - baseLayout, latchedLayout, lockedLayout); + if (i == 8) { + // Add a fall back key for layouts with non Latin-1 characters + if (baseQtKey > 255) { + struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 }; + fallback_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0); + if (!fallback_keymap) + continue; + xkb_state_unref(kb_state); + kb_state = xkb_state_new(fallback_keymap); + if (!kb_state) + continue; + } else + continue; + } else { + xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, + baseLayout, latchedLayout, lockedLayout); + } sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode()); if (sym == XKB_KEY_NoSymbol) @@ -862,8 +884,11 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const result += (qtKey + mods); } } + if (kb_state) + xkb_state_unref(kb_state); + if (fallback_keymap) + xkb_keymap_unref(fallback_keymap); - xkb_state_unref(kb_state); return result; } @@ -933,6 +958,7 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) , core_device_id(0) #endif { + memset(&xkb_names, 0, sizeof(xkb_names)); updateKeymap(); #ifndef QT_NO_XKB if (connection->hasXKB()) { @@ -974,6 +1000,7 @@ QXcbKeyboard::~QXcbKeyboard() #ifdef QT_NO_XKB xcb_key_symbols_free(m_key_symbols); #endif + clearXKBConfig(); } #ifndef QT_NO_XKB diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 770a7eabea..0256602782 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -91,7 +91,8 @@ protected: int keysymToQtKey(xcb_keysym_t keysym) const; int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, QString text) const; - void readXKBConfig(struct xkb_rule_names *names); + void readXKBConfig(); + void clearXKBConfig(); #ifdef QT_NO_XKB void updateModifiers(); @@ -107,6 +108,7 @@ private: struct xkb_context *xkb_context; struct xkb_keymap *xkb_keymap; struct xkb_state *xkb_state; + struct xkb_rule_names xkb_names; struct _mod_masks { uint alt; -- cgit v1.2.3 From 1ff8ed1bf5c8f0fe0f0c2e7a5ab62ae539f8c97e Mon Sep 17 00:00:00 2001 From: Venu Date: Thu, 1 Aug 2013 12:24:43 +0200 Subject: Doc: Corrected the example path in the tutorial Task-number: QTBUG-32688 Change-Id: I12c264f29bc1d49322c60debdec3758859f62fa8 Reviewed-by: Jerome Pasion --- src/widgets/doc/src/modelview.qdoc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/widgets/doc/src/modelview.qdoc b/src/widgets/doc/src/modelview.qdoc index 97d1c72e85..b2f9da9563 100644 --- a/src/widgets/doc/src/modelview.qdoc +++ b/src/widgets/doc/src/modelview.qdoc @@ -73,7 +73,7 @@ This tutorial includes example code for you to edit and integrate into your project. The tutorial's source code is located in Qt's - \c examples/tutorials/modelview directory. + \e examples/widgets/tutorials/modelview directory. For more detailed information you may also want to look at the \l{model-view-programming.html}{reference documentation} @@ -190,14 +190,14 @@ Below are 7 very simple and independent applications that show different sides of model/view programming. The source code can be found inside the - \c{examples/tutorials/modelview} directory. + \c{examples/widgets/tutorials/modelview} directory. \section2 2.1 A Read Only Table We start with an application that uses a QTableView to show data. We will add editing capabilities later. - (file source: examples/tutorials/modelview/1_readonly/main.cpp) + (file source: examples/widgets/tutorials/modelview/1_readonly/main.cpp) \snippet tutorials/modelview/1_readonly/main.cpp Quoting ModelView Tutorial We have the usual \l {modelview-part2-main-cpp.html}{main()} function: @@ -218,12 +218,12 @@ We have a table data set, so let's start with QAbstractTableModel since it is easier to use than the more general QAbstractItemModel. - (file source: examples/tutorials/modelview/1_readonly/mymodel.h) + (file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.h) \snippet tutorials/modelview/1_readonly/mymodel.h Quoting ModelView Tutorial QAbstractTableModel requires the implementation of three abstract methods. - (file source: examples/tutorials/modelview/1_readonly/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.cpp) \snippet tutorials/modelview/1_readonly/mymodel.cpp Quoting ModelView Tutorial The number of rows and columns is provided by @@ -259,7 +259,7 @@ result shown above. The difference is that this time we use parameter int role to return different pieces of information depending on its value. - (file source: examples/tutorials/modelview/2_formatting/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/2_formatting/mymodel.cpp) \snippet tutorials/modelview/2_formatting/mymodel.cpp Quoting ModelView Tutorial Each formatting property will be requested from the model with a separate @@ -320,7 +320,7 @@ We still have a read only table, but this time the content changes every second because we are showing the current time. - (file source: examples/tutorials/modelview/3_changingmodel/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp) \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_QVariant Something is missing to make the clock tick. We need to tell the view every @@ -328,12 +328,12 @@ this with a timer. In the constructor, we set its interval to 1 second and connect its timeout signal. - (file source: examples/tutorials/modelview/3_changingmodel/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp) \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_a Here is the corresponding slot: - (file source: examples/tutorials/modelview/3_changingmodel/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp) \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_b We ask the view to read the data in the top left cell again by emitting the @@ -349,7 +349,7 @@ The header content, however, is set via the model, so we reimplement the \l{QAbstractItemModel::headerData()}{headerData()} method: - (file source: examples/tutorials/modelview/4_headers/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/4_headers/mymodel.cpp) \snippet tutorials/modelview/4_headers/mymodel.cpp quoting mymodel_c Note that method \l{QAbstractItemModel::headerData()}{headerData()} also has @@ -368,7 +368,7 @@ enabled. This is done by reimplementing the following virtual methods: \l{QAbstractItemModel::}{setData()} and \l{QAbstractItemModel::}{flags()}. - (file source: examples/tutorials/modelview/5_edit/mymodel.h) + (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.h) \snippet tutorials/modelview/5_edit/mymodel.h Quoting ModelView Tutorial We use \c the two-dimensional array QString \c m_gridData to store our data. @@ -377,7 +377,7 @@ interface. We have also introduced the \c editCompleted() signal, which makes it possible to transfer the modified text to the window title. - (file source: examples/tutorials/modelview/5_edit/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp) \snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_e \l{QAbstractItemModel::setData()}{setData()} will be called each time the @@ -388,7 +388,7 @@ checkbox to be selected, calls would also be made with the role set to \l Qt::CheckStateRole. - (file source: examples/tutorials/modelview/5_edit/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp) \snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_f Various properties of a cell can be adjusted with @@ -432,7 +432,7 @@ \image tree_2_with_algorithm.png - (file source: examples/tutorials/modelview/6_treeview/mainwindow.cpp) + (file source: examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp) \snippet tutorials/modelview/6_treeview/mainwindow.cpp Quoting ModelView Tutorial We simply instantiate a QStandardItemModel and add a couple of @@ -450,7 +450,7 @@ So let's create a couple of items: - (file source: examples/tutorials/modelview/7_selections/mainwindow.cpp) + (file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp) \snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_a Views manage selections within a separate selection model, which can be @@ -458,7 +458,7 @@ retrieve the selection Model in order to connect a slot to its \l{QAbstractItemView::}{selectionChanged()} signal. - (file source: examples/tutorials/modelview/7_selections/mainwindow.cpp) + (file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp) \snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_b We get the model index that corresponds to the selection by calling -- cgit v1.2.3 From 608a9c12ae342d7093e949f0153c407f5817e2d8 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 2 Aug 2013 16:12:40 +0200 Subject: Enable qsrand() on builds without thread-safe posix The #ifdef clause in qsrand() needs to be the same as in qrand(). Otherwise, we will store the seed in thread-local storage in qsrand(), never passing it into srand(), and then we'll use regular rand() because the rand_r() function is missing, thus always using a random seed of 1 in all applications. Task-number: QTBUG-32781 Change-Id: I00240a1954ae746b87b031f3a0470a6cbe747571 Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index bcd0d06777..85cb698afc 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2322,7 +2322,7 @@ Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value */ void qsrand(uint seed) { -#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) SeedStorage *seedStorage = randTLS(); if (seedStorage) { SeedStorageType *pseed = seedStorage->localData(); -- cgit v1.2.3 From feacbdb746681d8c51c78a6082d456c498b843b4 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Thu, 25 Jul 2013 14:40:06 +0200 Subject: Android: Get SSL root certificates from TrustManager On Android, when not using Ministro, we cannot read certificates from the file system, so we have to get them through Java APIs instead. Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit 591584d9a940d374e20a62573d71054e0081c6ac) Task-Number: QTBUG-32508 Change-Id: Ia157e28bc3b2c141e3444d628e7a7c59eca39db0 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../src/org/qtproject/qt5/android/QtNative.java | 33 ++++ src/network/ssl/qsslsocket_openssl.cpp | 65 ++++---- src/network/ssl/qsslsocket_openssl_android.cpp | 179 +++++++++++++++++++++ src/network/ssl/qsslsocket_p.h | 3 + src/network/ssl/ssl.pri | 2 + 5 files changed, 253 insertions(+), 29 deletions(-) create mode 100644 src/network/ssl/qsslsocket_openssl_android.cpp (limited to 'src') diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 4586ae2002..22e3701e47 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -57,6 +57,12 @@ import android.view.ContextMenu; import android.view.Menu; import android.view.MotionEvent; +import java.security.KeyStore; +import java.security.cert.X509Certificate; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + public class QtNative { private static Activity m_activity = null; @@ -534,6 +540,33 @@ public class QtNative }); } + private static byte[][] getSSLCertificates() + { + ArrayList certificateList = new ArrayList(); + + try { + TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + factory.init((KeyStore) null); + + for (TrustManager manager : factory.getTrustManagers()) { + if (manager instanceof X509TrustManager) { + X509TrustManager trustManager = (X509TrustManager) manager; + + for (X509Certificate certificate : trustManager.getAcceptedIssuers()) { + byte buffer[] = certificate.getEncoded(); + certificateList.add(buffer); + } + } + } + } catch (Exception e) { + Log.e(QtTAG, "Failed to get certificates", e); + } + + byte[][] certificateArray = new byte[certificateList.size()][]; + certificateArray = certificateList.toArray(certificateArray); + return certificateArray; + } + // screen methods public static native void setDisplayMetrics(int screenWidthPixels, int screenHeightPixels, diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 675bd7d9f7..4e6275f306 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -686,41 +686,48 @@ QList QSslSocketPrivate::systemCaCertificates() } #elif defined(Q_OS_UNIX) QSet certFiles; -# ifdef Q_OS_ANDROID - QList directories; - directories << qgetenv("MINISTRO_SSL_CERTS_PATH"); // Set by Ministro -# else - QList directories = unixRootCertDirectories(); -# endif QDir currentDir; QStringList nameFilters; -# ifdef Q_OS_ANDROID - nameFilters << QLatin1String("*.der"); -#else + QList directories; + QSsl::EncodingFormat platformEncodingFormat; +# ifndef Q_OS_ANDROID + directories = unixRootCertDirectories(); nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt"); -# endif - currentDir.setNameFilters(nameFilters); - for (int a = 0; a < directories.count(); a++) { - currentDir.setPath(QLatin1String(directories.at(a))); - QDirIterator it(currentDir); - while(it.hasNext()) { - it.next(); - // use canonical path here to not load the same certificate twice if symlinked - certFiles.insert(it.fileInfo().canonicalFilePath()); - } - } - QSetIterator it(certFiles); - while(it.hasNext()) { -# ifdef Q_OS_ANDROID - systemCerts.append(QSslCertificate::fromPath(it.next(), QSsl::Der)); + platformEncodingFormat = QSsl::Pem; # else - systemCerts.append(QSslCertificate::fromPath(it.next(), QSsl::Pem)); -# endif - } + // Q_OS_ANDROID + QByteArray ministroPath = qgetenv("MINISTRO_SSL_CERTS_PATH"); // Set by Ministro + directories << ministroPath; + nameFilters << QLatin1String("*.der"); + platformEncodingFormat = QSsl::Der; +# ifndef Q_OS_ANDROID_NO_SDK + if (ministroPath.isEmpty()) { + QList certificateData = fetchSslCertificateData(); + for (int i = 0; i < certificateData.size(); ++i) { + systemCerts.append(QSslCertificate::fromData(certificateData.at(i), QSsl::Der)); + } + } else +# endif //Q_OS_ANDROID_NO_SDK +# endif //Q_OS_ANDROID + { + currentDir.setNameFilters(nameFilters); + for (int a = 0; a < directories.count(); a++) { + currentDir.setPath(QLatin1String(directories.at(a))); + QDirIterator it(currentDir); + while (it.hasNext()) { + it.next(); + // use canonical path here to not load the same certificate twice if symlinked + certFiles.insert(it.fileInfo().canonicalFilePath()); + } + } + QSetIterator it(certFiles); + while (it.hasNext()) + systemCerts.append(QSslCertificate::fromPath(it.next(), platformEncodingFormat)); # ifndef Q_OS_ANDROID - systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva - systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss # endif + } #endif #ifdef QSSLSOCKET_DEBUG qDebug() << "systemCaCertificates retrieval time " << timer.elapsed() << "ms"; diff --git a/src/network/ssl/qsslsocket_openssl_android.cpp b/src/network/ssl/qsslsocket_openssl_android.cpp new file mode 100644 index 0000000000..fa612a75a6 --- /dev/null +++ b/src/network/ssl/qsslsocket_openssl_android.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtNetwork 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** +** +** In addition, as a special exception, the copyright holders listed above give +** permission to link the code of its release of Qt with the OpenSSL project's +** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the +** same license as the original version), and distribute the linked executables. +** +** You must comply with the GNU General Public License version 2 in all +** respects for all of the code used other than the "OpenSSL" code. If you +** modify this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version of this file. +** +****************************************************************************/ + +#include "qsslsocket_openssl_p.h" + + + +#include +#include + +static JavaVM *javaVM = 0; +static jclass appClass; + +static jmethodID getSslCertificatesMethodID; + +struct AttachedJNIEnv +{ + AttachedJNIEnv() + { + attached = false; + if (javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { + if (javaVM->AttachCurrentThread(&jniEnv, NULL) < 0) { + __android_log_print(ANDROID_LOG_ERROR, "Qt", "AttachCurrentThread failed"); + jniEnv = 0; + return; + } + attached = true; + } + } + + ~AttachedJNIEnv() + { + if (attached) + javaVM->DetachCurrentThread(); + } + bool attached; + JNIEnv *jniEnv; +}; + +static const char logTag[] = "Qt"; +static const char classErrorMsg[] = "Can't find class \"%s\""; +static const char methodErrorMsg[] = "Can't find method \"%s%s\""; + + +#define FIND_AND_CHECK_CLASS(CLASS_NAME) \ +clazz = env->FindClass(CLASS_NAME); \ +if (!clazz) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, classErrorMsg, CLASS_NAME); \ + return JNI_FALSE; \ +} + +#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ +VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ +if (!VAR) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \ + return JNI_FALSE; \ +} + +static bool registerNatives(JNIEnv *env) +{ + jclass clazz; + FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative"); + appClass = static_cast(env->NewGlobalRef(clazz)); + +#if 0 //we don't call C++ functions from Java at this time + if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives failed"); + return JNI_FALSE; + } +#endif + + GET_AND_CHECK_STATIC_METHOD(getSslCertificatesMethodID, appClass, "getSSLCertificates", "()[[B"); + + return true; +} + +Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) +{ + typedef union { + JNIEnv *nativeEnvironment; + void *venv; + } UnionJNIEnvToVoid; + + __android_log_print(ANDROID_LOG_INFO, logTag, "Network start"); + UnionJNIEnvToVoid uenv; + uenv.venv = NULL; + javaVM = 0; + + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed"); + return -1; + } + JNIEnv *env = uenv.nativeEnvironment; + if (!registerNatives(env)) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives failed"); + return -1; + } + + javaVM = vm; + return JNI_VERSION_1_4; +} + +QList QSslSocketPrivate::fetchSslCertificateData() +{ + QList certificateData; + AttachedJNIEnv env; + + if (env.jniEnv) { + jobjectArray jcertificates = + static_cast(env.jniEnv->CallStaticObjectMethod(appClass, getSslCertificatesMethodID)); + jint nCertificates = env.jniEnv->GetArrayLength(jcertificates); + + for (int i = 0; i < nCertificates; ++i) { + jbyteArray jCert = static_cast(env.jniEnv->GetObjectArrayElement(jcertificates, i)); + + const uint sz = env.jniEnv->GetArrayLength(jCert); + jbyte *buffer = env.jniEnv->GetByteArrayElements(jCert, 0); + certificateData.append(QByteArray(reinterpret_cast(buffer), sz)); + + env.jniEnv->ReleaseByteArrayElements(jCert, buffer, JNI_ABORT); // don't copy back the elements + env.jniEnv->DeleteLocalRef(jCert); + } + } + + return certificateData; +} diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 9369dab8e7..6ce34ba06f 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -197,6 +197,9 @@ public: private: static bool ensureLibraryLoaded(); static void ensureCiphersAndCertsLoaded(); +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + static QList fetchSslCertificateData(); +#endif static bool s_libraryLoaded; static bool s_loadedCiphersAndCerts; diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 1d8c8e1ab7..0fe231357b 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -28,6 +28,8 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { ssl/qsslcertificateextension.cpp \ ssl/qsslcontext.cpp +android:!android-no-sdk: SOURCES += ssl/qsslsocket_openssl_android.cpp + # Add optional SSL libs # Static linking of OpenSSL with msvc: # - Binaries http://slproweb.com/products/Win32OpenSSL.html -- cgit v1.2.3 From 3e078cf36db538c95fd9b491a69196e882c24e0a Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 8 Aug 2013 11:05:26 +0200 Subject: Don't release the printer after using it to change a property The printer should not be released after changing a property on it as it is still needed by QPrinter elsewhere. It is released as appropriate automatically already. Task-number: QTBUG-32831 Change-Id: Idb2d98b25b62f343015a0a0fb3c9a0d506546132 Reviewed-by: Liang Qi Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 2dedf99582..ee8d7ea157 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -187,10 +187,8 @@ void QMacPrintEnginePrivate::setPaperName(const QString &name) if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { CFArrayRef array; - if (PMPrinterGetPaperList(printer, &array) != noErr) { - PMRelease(printer); + if (PMPrinterGetPaperList(printer, &array) != noErr) return; - } int count = CFArrayGetCount(array); for (int i = 0; i < count; ++i) { PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(array, i))); @@ -208,7 +206,6 @@ void QMacPrintEnginePrivate::setPaperName(const QString &name) } } } - PMRelease(printer); } } -- cgit v1.2.3