diff --git a/CHANGELOG b/CHANGELOG index 97021f27f..ee51e22bb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,15 @@ This is the changelog file for the POCO C++ Libraries. +Release 1.5.3 (2013-12-xx) +========================== + +- fixed GH# 316: Poco::DateTimeFormatter::append() gives wrong result for + Poco::LocalDateTime +- Poco::Data::MySQL: added SQLite thread cleanup handler +- Poco::Net::X509Certificate: improved and fixed domain name verification for + wildcard domains + + Release 1.5.2 (2013-09-16) ========================== diff --git a/DLLVersion.rc b/DLLVersion.rc index 596a448b7..77006074b 100644 --- a/DLLVersion.rc +++ b/DLLVersion.rc @@ -4,8 +4,8 @@ #include "winres.h" -#define POCO_VERSION 1,5,2,0 -#define POCO_VERSION_STR "1.5.2" +#define POCO_VERSION 1,5,3,0 +#define POCO_VERSION_STR "1.5.3" VS_VERSION_INFO VERSIONINFO FILEVERSION POCO_VERSION diff --git a/Data/MySQL/src/SessionHandle.cpp b/Data/MySQL/src/SessionHandle.cpp index c87e3a8e8..6304577ba 100644 --- a/Data/MySQL/src/SessionHandle.cpp +++ b/Data/MySQL/src/SessionHandle.cpp @@ -36,17 +36,62 @@ #include "Poco/Data/MySQL/SessionHandle.h" #include "Poco/Data/DataException.h" +#include "Poco/SingletonHolder.h" +#ifdef POCO_OS_FAMILY_UNIX +#include +#endif + #define POCO_MYSQL_VERSION_NUMBER ((NDB_VERSION_MAJOR<<16) | (NDB_VERSION_MINOR<<8) | (NDB_VERSION_BUILD&0xFF)) + namespace Poco { namespace Data { namespace MySQL { +#ifdef POCO_OS_FAMILY_UNIX +class ThreadCleanupHelper +{ +public: + ThreadCleanupHelper() + { + if (pthread_key_create(&_key, &ThreadCleanupHelper::cleanup) != 0) + throw Poco::SystemException("cannot create TLS key for mysql cleanup"); + } + + void init() + { + if (pthread_setspecific(_key, reinterpret_cast(1))) + throw Poco::SystemException("cannot set TLS key for mysql cleanup"); + } + + static ThreadCleanupHelper& instance() + { + return *_sh.get(); + } + + static void cleanup(void* data) + { + mysql_thread_end(); + } + +private: + pthread_key_t _key; + static Poco::SingletonHolder _sh; +}; + + +Poco::SingletonHolder ThreadCleanupHelper::_sh; +#endif + + SessionHandle::SessionHandle(MYSQL* mysql): _pHandle(0) { init(mysql); +#ifdef POCO_OS_FAMILY_UNIX + ThreadCleanupHelper::instance().init(); +#endif } diff --git a/Foundation/include/Poco/Version.h b/Foundation/include/Poco/Version.h index e79bb4db5..f5752c345 100644 --- a/Foundation/include/Poco/Version.h +++ b/Foundation/include/Poco/Version.h @@ -54,7 +54,7 @@ // Ax are alpha releases // Bx are beta releases // -#define POCO_VERSION 0x01050200 +#define POCO_VERSION 0x01050300 #endif // Foundation_Version_INCLUDED diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index 95791a983..d03e538d5 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -1081,6 +1081,8 @@ void SocketImpl::error(int code, const std::string& arg) #if defined(POCO_OS_FAMILY_UNIX) case EPIPE: throw IOException("Broken pipe", code); + case EBADF: + throw IOException("Bad socket descriptor", code); #endif default: throw IOException(NumberFormatter::format(code), arg, code); diff --git a/Net/src/WebSocketImpl.cpp b/Net/src/WebSocketImpl.cpp index 6864ec2fc..6e64ae00f 100644 --- a/Net/src/WebSocketImpl.cpp +++ b/Net/src/WebSocketImpl.cpp @@ -1,7 +1,7 @@ // // WebSocketImpl.cpp // -// $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#9 $ +// $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#10 $ // // Library: Net // Package: WebSocket @@ -43,7 +43,7 @@ #include "Poco/MemoryStream.h" #include "Poco/Format.h" #include - +#include namespace Poco { namespace Net { @@ -130,18 +130,19 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int) int maskOffset = 0; if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4; lengthByte &= 0x7f; - if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH) + if (lengthByte > 0 || maskOffset > 0) { - n = receiveNBytes(header + 2, lengthByte + maskOffset); + if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH) + { + n = receiveNBytes(header + 2, lengthByte + maskOffset); + } + else + { + n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2); + } + if (n <= 0) throw WebSocketException("Incomplete header received", WebSocket::WS_ERR_INCOMPLETE_FRAME); + n += 2; } - else - { - n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2); - } - - if (n <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); - - n += 2; Poco::MemoryInputStream istr(header, n); Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); Poco::UInt8 flags; diff --git a/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h b/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h index aec004cbe..6369513bd 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h +++ b/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h @@ -1,7 +1,7 @@ // // X509Certificate.h // -// $Id: //poco/1.4/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h#1 $ +// $Id: //poco/1.4/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h#2 $ // // Library: NetSSL_OpenSSL // Package: SSLCore @@ -108,7 +108,7 @@ public: protected: static bool containsWildcards(const std::string& commonName); - static bool matchByAlias(const std::string& alias, const HostEntry& heData); + static bool matchByAlias(const std::string& alias, const std::string& hostName); private: enum diff --git a/NetSSL_OpenSSL/src/X509Certificate.cpp b/NetSSL_OpenSSL/src/X509Certificate.cpp index ffe72870b..fcc28dd7d 100644 --- a/NetSSL_OpenSSL/src/X509Certificate.cpp +++ b/NetSSL_OpenSSL/src/X509Certificate.cpp @@ -1,7 +1,7 @@ // // X509Certificate.cpp // -// $Id: //poco/1.4/NetSSL_OpenSSL/src/X509Certificate.cpp#2 $ +// $Id: //poco/1.4/NetSSL_OpenSSL/src/X509Certificate.cpp#3 $ // // Library: NetSSL_OpenSSL // Package: SSLCore @@ -107,51 +107,47 @@ bool X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, c std::string commonName; std::set dnsNames; certificate.extractNames(commonName, dnsNames); + if (!commonName.empty()) dnsNames.insert(commonName); bool ok = (dnsNames.find(hostName) != dnsNames.end()); - - char buffer[NAME_BUFFER_SIZE]; - X509_NAME* subj = 0; - if (!ok && (subj = X509_get_subject_name(const_cast(certificate.certificate()))) && X509_NAME_get_text_by_NID(subj, NID_commonName, buffer, sizeof(buffer)) > 0) + if (!ok) { - buffer[NAME_BUFFER_SIZE - 1] = 0; - std::string commonName(buffer); // commonName can contain wildcards like *.appinf.com - try + for (std::set::const_iterator it = dnsNames.begin(); !ok && it != dnsNames.end(); ++it) { - // two cases: strData contains wildcards or not - if (containsWildcards(commonName)) + try { - // a compare by IPAddress is not possible with wildcards - // only allow compare by name - const HostEntry& heData = DNS::resolve(hostName); - ok = matchByAlias(commonName, heData); - } - else - { - // it depends on hostName if we compare by IP or by alias - IPAddress ip; - if (IPAddress::tryParse(hostName, ip)) + // two cases: strData contains wildcards or not + if (containsWildcards(*it)) { - // compare by IP - const HostEntry& heData = DNS::resolve(commonName); - const HostEntry::AddressList& addr = heData.addresses(); - HostEntry::AddressList::const_iterator it = addr.begin(); - HostEntry::AddressList::const_iterator itEnd = addr.end(); - for (; it != itEnd && !ok; ++it) - { - ok = (*it == ip); - } + // a compare by IPAddress is not possible with wildcards + // only allow compare by name + ok = matchByAlias(*it, hostName); } else { - // compare by name - const HostEntry& heData = DNS::resolve(hostName); - ok = matchByAlias(commonName, heData); + // it depends on hostName if we compare by IP or by alias + IPAddress ip; + if (IPAddress::tryParse(hostName, ip)) + { + // compare by IP + const HostEntry& heData = DNS::resolve(*it); + const HostEntry::AddressList& addr = heData.addresses(); + HostEntry::AddressList::const_iterator it = addr.begin(); + HostEntry::AddressList::const_iterator itEnd = addr.end(); + for (; it != itEnd && !ok; ++it) + { + ok = (*it == ip); + } + } + else + { + // compare by name + ok = matchByAlias(*it, hostName); + } } } - } - catch (HostNotFoundException&) - { - return false; + catch (HostNotFoundException&) + { + } } } return ok; @@ -164,8 +160,9 @@ bool X509Certificate::containsWildcards(const std::string& commonName) } -bool X509Certificate::matchByAlias(const std::string& alias, const HostEntry& heData) +bool X509Certificate::matchByAlias(const std::string& alias, const std::string& hostName) { + const HostEntry& heData = DNS::resolve(hostName); // fix wildcards std::string aliasRep = Poco::replace(alias, ".", "\\."); Poco::replaceInPlace(aliasRep, "*", ".*"); @@ -183,11 +180,16 @@ bool X509Certificate::matchByAlias(const std::string& alias, const HostEntry& he found = expr.match(*it); } // Handle the case where the list of aliases is empty. - if (aliases.empty()) + if (!found) { - // Compare the host name against the wildcard host name in the certificate. + // Compare the resolved host name against the wildcard host name in the certificate. found = expr.match(heData.name()); } + if (!found) + { + // Compare the original host name against the wildcard host name in the certificate. + found = expr.match(hostName); + } return found; } diff --git a/VERSION b/VERSION index 4cda8f19e..8af85beb5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.2 +1.5.3