diff --git a/CHANGELOG b/CHANGELOG index 28cccd5f1..c27da5027 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ This is the changelog file for the POCO C++ Libraries. +Release 1.10.1 (2020-02-xx) +========================== + +- TODO + + Release 1.10.0 (2020-01-27) ========================== diff --git a/DLLVersion.rc b/DLLVersion.rc index d357cf9ec..10eb82cb5 100644 --- a/DLLVersion.rc +++ b/DLLVersion.rc @@ -4,8 +4,8 @@ #include "winres.h" -#define POCO_VERSION 1,10,0,0 -#define POCO_VERSION_STR "1.10.0" +#define POCO_VERSION 1,10,1,0 +#define POCO_VERSION_STR "1.10.1" VS_VERSION_INFO VERSIONINFO FILEVERSION POCO_VERSION diff --git a/Data/SQLite/src/sqlite3.c b/Data/SQLite/src/sqlite3.c index c3e9f317f..55dc686ee 100644 --- a/Data/SQLite/src/sqlite3.c +++ b/Data/SQLite/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.31.0. By combining all the individual C code files into this +** version 3.31.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -1165,9 +1165,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.31.0" -#define SQLITE_VERSION_NUMBER 3031000 -#define SQLITE_SOURCE_ID "2020-01-22 18:38:59 f6affdd41608946fcfcea914ece149038a8b25a62bbe719ed2561c649b86d824" +#define SQLITE_VERSION "3.31.1" +#define SQLITE_VERSION_NUMBER 3031001 +#define SQLITE_SOURCE_ID "2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -56233,30 +56233,48 @@ SQLITE_PRIVATE int sqlite3PagerOpen( ** Database file handle (pVfs->szOsFile bytes) ** Sub-journal file handle (journalFileSize bytes) ** Main journal file handle (journalFileSize bytes) - ** \0\1\0 journal prefix (3 bytes) - ** Journal filename (nPathname+8+1 bytes) - ** \2\0 WAL prefix (2 bytes) - ** WAL filename (nPathname+4+1 bytes) - ** \3\0 database prefix (2 bytes) + ** \0\0\0\0 database prefix (4 bytes) ** Database file name (nPathname+1 bytes) ** URI query parameters (nUriByte bytes) - ** \0\0 terminator (2 bytes) + ** Journal filename (nPathname+8+1 bytes) + ** WAL filename (nPathname+4+1 bytes) + ** \0\0\0 terminator (3 bytes) + ** + ** Some 3rd-party software, over which we have no control, depends on + ** the specific order of the filenames and the \0 separators between them + ** so that it can (for example) find the database filename given the WAL + ** filename without using the sqlite3_filename_database() API. This is a + ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party + ** software is in widespread use, so we try to avoid changing the filename + ** order and formatting if possible. In particular, the details of the + ** filename format expected by 3rd-party software should be as follows: + ** + ** - Main Database Path + ** - \0 + ** - Multiple URI components consisting of: + ** - Key + ** - \0 + ** - Value + ** - \0 + ** - \0 + ** - Journal Path + ** - \0 + ** - WAL Path (zWALName) + ** - \0 */ pPtr = (u8 *)sqlite3MallocZero( ROUND8(sizeof(*pPager)) + /* Pager structure */ ROUND8(pcacheSize) + /* PCache object */ ROUND8(pVfs->szOsFile) + /* The main db file */ journalFileSize * 2 + /* The two journal files */ - 3 + /* Journal prefix */ - nPathname + 8 + 1 + /* Journal filename */ -#ifndef SQLITE_OMIT_WAL - 2 + /* WAL prefix */ - nPathname + 4 + 1 + /* WAL filename */ -#endif - 2 + /* Database prefix */ + 4 + /* Database prefix */ nPathname + 1 + /* database filename */ nUriByte + /* query parameters */ - 2 /* Terminator */ + nPathname + 8 + 1 + /* Journal filename */ +#ifndef SQLITE_OMIT_WAL + nPathname + 4 + 1 + /* WAL filename */ +#endif + 3 /* Terminator */ ); assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); if( !pPtr ){ @@ -56270,9 +56288,20 @@ SQLITE_PRIVATE int sqlite3PagerOpen( pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); + /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ + pPtr += 4; /* Skip zero prefix */ + pPager->zFilename = (char*)pPtr; + if( nPathname>0 ){ + memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1; + if( zUri ){ + memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte; + }else{ + pPtr++; + } + } + /* Fill in Pager.zJournal */ - pPtr[1] = '\001'; pPtr += 3; if( nPathname>0 ){ pPager->zJournal = (char*)pPtr; memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; @@ -56283,12 +56312,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen( #endif }else{ pPager->zJournal = 0; - pPtr++; } #ifndef SQLITE_OMIT_WAL /* Fill in Pager.zWal */ - pPtr[0] = '\002'; pPtr[1] = 0; pPtr += 2; if( nPathname>0 ){ pPager->zWal = (char*)pPtr; memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; @@ -56299,21 +56326,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( #endif }else{ pPager->zWal = 0; - pPtr++; } #endif - /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ - pPtr[0] = '\003'; pPtr[1] = 0; pPtr += 2; - pPager->zFilename = (char*)pPtr; - if( nPathname>0 ){ - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1; - if( zUri ){ - memcpy(pPtr, zUri, nUriByte); /* pPtr += nUriByte; // not needed */ - } - /* Double-zero terminator implied by the sqlite3MallocZero */ - } - if( nPathname ) sqlite3DbFree(0, zPathname); pPager->pVfs = pVfs; pPager->vfsFlags = vfsFlags; @@ -58433,8 +58448,8 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ ** sqlite3_uri_parameter() and sqlite3_filename_database() and friends. */ SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){ - static const char zFake[] = { 0x00, 0x01, 0x00, 0x00, 0x00 }; - return (nullIfMemDb && pPager->memDb) ? &zFake[3] : pPager->zFilename; + static const char zFake[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename; } /* @@ -117491,6 +117506,9 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); nExpr = pExpr->x.pList->nExpr; pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION + if( pDef==0 ) return 0; +#endif if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ return 0; } @@ -122767,11 +122785,11 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.26.0 and later */ #define sqlite3_normalized_sql sqlite3_api->normalized_sql /* Version 3.28.0 and later */ -#define sqlite3_stmt_isexplain sqlite3_api->isexplain -#define sqlite3_value_frombind sqlite3_api->frombind +#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain +#define sqlite3_value_frombind sqlite3_api->value_frombind /* Version 3.30.0 and later */ #define sqlite3_drop_modules sqlite3_api->drop_modules -/* Version 3.31.0 andn later */ +/* Version 3.31.0 and later */ #define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64 #define sqlite3_uri_key sqlite3_api->uri_key #define sqlite3_filename_database sqlite3_api->filename_database @@ -163282,6 +163300,21 @@ SQLITE_API int sqlite3_test_control(int op, ...){ return rc; } +/* +** The Pager stores the Database filename, Journal filename, and WAL filename +** consecutively in memory, in that order. The database filename is prefixed +** by four zero bytes. Locate the start of the database filename by searching +** backwards for the first byte following four consecutive zero bytes. +** +** This only works if the filename passed in was obtained from the Pager. +*/ +static const char *databaseName(const char *zName){ + while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ + zName--; + } + return zName; +} + /* ** This is a utility routine, useful to VFS implementations, that checks ** to see if a database file was a URI that contained a specific query @@ -163295,6 +163328,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ */ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ if( zFilename==0 || zParam==0 ) return 0; + zFilename = databaseName(zFilename); zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ int x = strcmp(zFilename, zParam); @@ -163310,6 +163344,7 @@ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char * */ SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N){ if( zFilename==0 || N<0 ) return 0; + zFilename = databaseName(zFilename); zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] && (N--)>0 ){ zFilename += sqlite3Strlen30(zFilename) + 1; @@ -163343,25 +163378,6 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64( return bDflt; } -/* -** The Pager stores the Journal filename, WAL filename, and Database filename -** consecutively in memory, in that order, with prefixes \000\001\000, -** \002\000, and \003\000, in that order. Thus the three names look like query -** parameters if you start at the first prefix. -** -** This routine backs up a filename to the start of the first prefix. -** -** This only works if the filenamed passed in was obtained from the Pager. -*/ -static const char *startOfNameList(const char *zName){ - while( zName[0]!='\001' || zName[1]!=0 ){ - zName -= 3; - while( zName[0]!='\000' ){ zName--; } - zName++; - } - return zName-1; -} - /* ** Translate a filename that was handed to a VFS routine into the corresponding ** database, journal, or WAL file. @@ -163373,14 +163389,26 @@ static const char *startOfNameList(const char *zName){ ** corruption. */ SQLITE_API const char *sqlite3_filename_database(const char *zFilename){ + return databaseName(zFilename); return sqlite3_uri_parameter(zFilename - 3, "\003"); } SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){ - const char *z = sqlite3_uri_parameter(startOfNameList(zFilename), "\001"); - return ALWAYS(z) && z[0] ? z : 0; + zFilename = databaseName(zFilename); + zFilename += sqlite3Strlen30(zFilename) + 1; + while( zFilename[0] ){ + zFilename += sqlite3Strlen30(zFilename) + 1; + zFilename += sqlite3Strlen30(zFilename) + 1; + } + return zFilename + 1; } SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){ - return sqlite3_uri_parameter(startOfNameList(zFilename), "\002"); +#ifdef SQLITE_OMIT_WAL + return 0; +#else + zFilename = sqlite3_filename_journal(zFilename); + zFilename += sqlite3Strlen30(zFilename) + 1; + return zFilename; +#endif } /* @@ -219999,8 +220027,8 @@ static int fts5QueryCksum( ** contain valid utf-8, return non-zero. */ static int fts5TestUtf8(const char *z, int n){ - assert_nc( n>0 ); int i = 0; + assert_nc( n>0 ); while( i. - + const std::string& getUserInfo() const; /// Returns the user-info part of the URI. - + void setUserInfo(const std::string& userInfo); /// Sets the user-info part of the URI. - + const std::string& getHost() const; /// Returns the host part of the URI. - + void setHost(const std::string& host); /// Sets the host part of the URI. - + unsigned short getPort() const; /// Returns the port number part of the URI. /// @@ -150,39 +150,45 @@ public: /// well-known port number (e.g., 80 for http) for /// the given scheme is returned if it is known. /// Otherwise, 0 is returned. - + void setPort(unsigned short port); /// Sets the port number part of the URI. - + + unsigned short getSpecifiedPort() const; + /// Returns the port number part of the URI. + /// + /// If no explicit port number has been specified, + /// returns 0. + std::string getAuthority() const; /// Returns the authority part (userInfo, host and port) - /// of the URI. + /// of the URI. /// /// If the port number is a well-known port /// number for the given scheme (e.g., 80 for http), it /// is not included in the authority. - + void setAuthority(const std::string& authority); /// Parses the given authority part for the URI and sets /// the user-info, host, port components accordingly. - + const std::string& getPath() const; /// Returns the decoded path part of the URI. - + void setPath(const std::string& path); /// Sets the path part of the URI. - + std::string getQuery() const; /// Returns the decoded query part of the URI. /// - /// Note that encoded ampersand characters ('&', "%26") - /// will be decoded, which could cause ambiguities if the query + /// Note that encoded ampersand characters ('&', "%26") + /// will be decoded, which could cause ambiguities if the query /// string contains multiple parameters and a parameter name /// or value contains an ampersand as well. /// In such a case it's better to use getRawQuery() or /// getQueryParameters(). - - void setQuery(const std::string& query); + + void setQuery(const std::string& query); /// Sets the query part of the URI. /// /// The query string will be percent-encoded. If the query @@ -192,28 +198,28 @@ public: /// characters in the query will not be encoded. This could /// lead to ambiguity issues if the query string contains multiple /// name-value parameters separated by ampersand, and if any - /// name or value also contains an ampersand. In such a + /// name or value also contains an ampersand. In such a /// case, it's better to use setRawQuery() with a properly /// percent-encoded query string, or use addQueryParameter() - /// or setQueryParameters(), which take care of appropriate + /// or setQueryParameters(), which take care of appropriate /// percent encoding of parameter names and values. void addQueryParameter(const std::string& param, const std::string& val = ""); /// Adds "param=val" to the query; "param" may not be empty. /// If val is empty, only '=' is appended to the parameter. - /// + /// /// In addition to regular encoding, function also encodes '&' and '=', /// if found in param or val. const std::string& getRawQuery() const; /// Returns the query string in raw form, which usually /// means percent encoded. - - void setRawQuery(const std::string& query); + + void setRawQuery(const std::string& query); /// Sets the query part of the URI. /// /// The given query string must be properly percent-encoded. - + QueryParameters getQueryParameters() const; /// Returns the decoded query string parameters as a vector /// of name-value pairs. @@ -226,19 +232,19 @@ public: const std::string& getFragment() const; /// Returns the fragment part of the URI. - + void setFragment(const std::string& fragment); /// Sets the fragment part of the URI. - + void setPathEtc(const std::string& pathEtc); /// Sets the path, query and fragment parts of the URI. - + std::string getPathEtc() const; /// Returns the encoded path, query and fragment parts of the URI. - + std::string getPathAndQuery() const; - /// Returns the encoded path and query parts of the URI. - + /// Returns the encoded path and query parts of the URI. + void resolve(const std::string& relativeURI); /// Resolves the given relative URI against the base URI. /// See section 5.2 of RFC 3986 for the algorithm used. @@ -253,10 +259,10 @@ public: /// A relative reference does not contain a scheme identifier. /// Relative references are usually resolved against an absolute /// base reference. - + bool empty() const; /// Returns true if the URI is empty, false otherwise. - + bool operator == (const URI& uri) const; /// Returns true if both URIs are identical, false otherwise. /// @@ -273,22 +279,22 @@ public: bool operator != (const std::string& uri) const; /// Parses the given URI and returns true if both URIs are identical, /// false otherwise. - + void normalize(); /// Normalizes the URI by removing all but leading . and .. segments from the path. /// - /// If the first path segment in a relative path contains a colon (:), - /// such as in a Windows path containing a drive letter, a dot segment (./) + /// If the first path segment in a relative path contains a colon (:), + /// such as in a Windows path containing a drive letter, a dot segment (./) /// is prepended in accordance with section 3.3 of RFC 3986. - + void getPathSegments(std::vector& segments); /// Places the single path segments (delimited by slashes) into the /// given vector. - + static void encode(const std::string& str, const std::string& reserved, std::string& encodedStr); /// URI-encodes the given string by escaping reserved and non-ASCII /// characters. The encoded string is appended to encodedStr. - + static void decode(const std::string& str, std::string& decodedStr, bool plusAsSpace = false); /// URI-decodes the given string by replacing percent-encoded /// characters with the actual character. The decoded string @@ -300,15 +306,15 @@ public: protected: bool equals(const URI& uri) const; /// Returns true if both uri's are equivalent. - + bool isWellKnownPort() const; /// Returns true if the URI's port number is a well-known one /// (for example, 80, if the scheme is http). - + unsigned short getWellKnownPort() const; /// Returns the well-known port number for the URI's scheme, /// or 0 if the port number is not known. - + void parse(const std::string& uri); /// Parses and assigns an URI from the given string. Throws a /// SyntaxException if the uri is not valid. @@ -349,7 +355,7 @@ protected: static const std::string RESERVED_QUERY_PARAM; static const std::string RESERVED_FRAGMENT; static const std::string ILLEGAL; - + private: std::string _scheme; std::string _userInfo; @@ -368,44 +374,50 @@ inline const std::string& URI::getScheme() const { return _scheme; } - + inline const std::string& URI::getUserInfo() const { return _userInfo; } - + inline const std::string& URI::getHost() const { return _host; } - + inline const std::string& URI::getPath() const { return _path; } - + inline const std::string& URI::getRawQuery() const { return _query; } - + inline const std::string& URI::getFragment() const { return _fragment; } +inline unsigned short URI::getSpecifiedPort() const +{ + return _port; +} + + inline void swap(URI& u1, URI& u2) { u1.swap(u2); } - + } // namespace Poco diff --git a/Foundation/include/Poco/Version.h b/Foundation/include/Poco/Version.h index 274d52fde..5c69fe3bb 100644 --- a/Foundation/include/Poco/Version.h +++ b/Foundation/include/Poco/Version.h @@ -35,7 +35,7 @@ // Ax: alpha releases // Bx: beta releases // -#define POCO_VERSION 0x010A0000 +#define POCO_VERSION 0x010A0100 #endif // Foundation_Version_INCLUDED diff --git a/Foundation/src/AsyncChannel.cpp b/Foundation/src/AsyncChannel.cpp index b9be051bc..317eea6e4 100644 --- a/Foundation/src/AsyncChannel.cpp +++ b/Foundation/src/AsyncChannel.cpp @@ -18,7 +18,10 @@ #include "Poco/Formatter.h" #include "Poco/AutoPtr.h" #include "Poco/LoggingRegistry.h" +#include "Poco/NumberParser.h" #include "Poco/Exception.h" +#include "Poco/String.h" +#include "Poco/Format.h" namespace Poco { @@ -31,23 +34,23 @@ public: _msg(msg) { } - + ~MessageNotification() { } - + const Message& message() const { return _msg; } - + private: Message _msg; }; -AsyncChannel::AsyncChannel(Channel::Ptr pChannel, Thread::Priority prio): - _pChannel(pChannel), +AsyncChannel::AsyncChannel(Channel::Ptr pChannel, Thread::Priority prio): + _pChannel(pChannel), _thread("AsyncChannel") { _thread.setPriority(prio); @@ -70,7 +73,7 @@ AsyncChannel::~AsyncChannel() void AsyncChannel::setChannel(Channel::Ptr pChannel) { FastMutex::ScopedLock lock(_channelMutex); - + _pChannel = pChannel; } @@ -94,10 +97,10 @@ void AsyncChannel::close() if (_thread.isRunning()) { while (!_queue.empty()) Thread::sleep(100); - - do + + do { - _queue.wakeUpAll(); + _queue.wakeUpAll(); } while (!_thread.tryJoin(100)); } @@ -106,6 +109,18 @@ void AsyncChannel::close() void AsyncChannel::log(const Message& msg) { + if (_queueSize != 0 && _queue.size() >= _queueSize) + { + ++_dropCount; + return; + } + + if (_dropCount != 0) + { + _queue.enqueueNotification(new MessageNotification(Message(msg, Poco::format("Dropped %z messages.", _dropCount)))); + _dropCount = 0; + } + open(); _queue.enqueueNotification(new MessageNotification(msg)); @@ -115,11 +130,24 @@ void AsyncChannel::log(const Message& msg) void AsyncChannel::setProperty(const std::string& name, const std::string& value) { if (name == "channel") + { setChannel(LoggingRegistry::defaultRegistry().channelForName(value)); + } else if (name == "priority") + { setPriority(value); + } + else if (name == "queueSize") + { + if (Poco::icompare(value, "none") == 0 || Poco::icompare(value, "unlimited") == 0 || value.empty()) + _queueSize = 0; + else + _queueSize = Poco::NumberParser::parseUnsigned(value); + } else + { Channel::setProperty(name, value); + } } @@ -137,12 +165,12 @@ void AsyncChannel::run() nf = _queue.waitDequeueNotification(); } } - - + + void AsyncChannel::setPriority(const std::string& value) { Thread::Priority prio = Thread::PRIO_NORMAL; - + if (value == "lowest") prio = Thread::PRIO_LOWEST; else if (value == "low") @@ -155,7 +183,7 @@ void AsyncChannel::setPriority(const std::string& value) prio = Thread::PRIO_HIGHEST; else throw InvalidArgumentException("thread priority", value); - + _thread.setPriority(prio); } diff --git a/Foundation/src/LogStream.cpp b/Foundation/src/LogStream.cpp index 02022b66e..96adeb186 100644 --- a/Foundation/src/LogStream.cpp +++ b/Foundation/src/LogStream.cpp @@ -23,10 +23,11 @@ namespace Poco { // -LogStreamBuf::LogStreamBuf(Logger& logger, Message::Priority priority): +LogStreamBuf::LogStreamBuf(Logger& logger, Message::Priority priority, std::size_t bufferCapacity): _logger(logger), _priority(priority) { + _message.reserve(bufferCapacity); } @@ -41,6 +42,12 @@ void LogStreamBuf::setPriority(Message::Priority priority) } +void LogStreamBuf::reserve(std::size_t capacity) +{ + _message.reserve(capacity); +} + + int LogStreamBuf::writeToDevice(char c) { if (c == '\n' || c == '\r') @@ -62,8 +69,8 @@ int LogStreamBuf::writeToDevice(char c) // -LogIOS::LogIOS(Logger& logger, Message::Priority priority): - _buf(logger, priority) +LogIOS::LogIOS(Logger& logger, Message::Priority priority, std::size_t bufferCapacity): + _buf(logger, priority, bufferCapacity) { poco_ios_init(&_buf); } @@ -85,25 +92,25 @@ LogStreamBuf* LogIOS::rdbuf() // -LogStream::LogStream(Logger& logger, Message::Priority priority): - LogIOS(logger, priority), +LogStream::LogStream(Logger& logger, Message::Priority priority, std::size_t bufferCapacity): + LogIOS(logger, priority, bufferCapacity), std::ostream(&_buf) { } -LogStream::LogStream(const std::string& loggerName, Message::Priority priority): - LogIOS(Logger::get(loggerName), priority), +LogStream::LogStream(const std::string& loggerName, Message::Priority priority, std::size_t bufferCapacity): + LogIOS(Logger::get(loggerName), priority, bufferCapacity), std::ostream(&_buf) { } - + LogStream::~LogStream() { } - + LogStream& LogStream::fatal() { return priority(Message::PRIO_FATAL); @@ -116,7 +123,7 @@ LogStream& LogStream::fatal(const std::string& message) return priority(Message::PRIO_FATAL); } - + LogStream& LogStream::critical() { return priority(Message::PRIO_CRITICAL); diff --git a/Foundation/src/URI.cpp b/Foundation/src/URI.cpp index eb4fbf584..0c2d2312e 100644 --- a/Foundation/src/URI.cpp +++ b/Foundation/src/URI.cpp @@ -49,19 +49,18 @@ URI::URI(const char* uri): parse(std::string(uri)); } - + URI::URI(const std::string& scheme, const std::string& pathEtc): _scheme(scheme), _port(0) { toLowerInPlace(_scheme); - _port = getWellKnownPort(); std::string::const_iterator beg = pathEtc.begin(); std::string::const_iterator end = pathEtc.end(); parsePathEtc(beg, end); } - + URI::URI(const std::string& scheme, const std::string& authority, const std::string& pathEtc): _scheme(scheme) { @@ -181,7 +180,7 @@ URI& URI::operator = (URI&& uri) noexcept return *this; } - + URI& URI::operator = (const std::string& uri) { clear(); @@ -268,18 +267,16 @@ void URI::setScheme(const std::string& scheme) { _scheme = scheme; toLowerInPlace(_scheme); - if (_port == 0) - _port = getWellKnownPort(); } - + void URI::setUserInfo(const std::string& userInfo) { _userInfo.clear(); decode(userInfo, _userInfo); } - + void URI::setHost(const std::string& host) { _host = host; @@ -300,7 +297,7 @@ void URI::setPort(unsigned short port) _port = port; } - + std::string URI::getAuthority() const { std::string auth; @@ -324,7 +321,7 @@ std::string URI::getAuthority() const return auth; } - + void URI::setAuthority(const std::string& authority) { _userInfo.clear(); @@ -335,14 +332,14 @@ void URI::setAuthority(const std::string& authority) parseAuthority(beg, end); } - + void URI::setPath(const std::string& path) { _path.clear(); decode(path, _path); } - + void URI::setRawQuery(const std::string& query) { _query = query; @@ -384,7 +381,7 @@ URI::QueryParameters URI::getQueryParameters() const std::string value; while (it != end && *it != '=' && *it != '&') { - if (*it == '+') + if (*it == '+') name += ' '; else name += *it; @@ -395,7 +392,7 @@ URI::QueryParameters URI::getQueryParameters() const ++it; while (it != end && *it != '&') { - if (*it == '+') + if (*it == '+') value += ' '; else value += *it; @@ -407,7 +404,7 @@ URI::QueryParameters URI::getQueryParameters() const URI::decode(name, decodedName); URI::decode(value, decodedValue); result.push_back(std::make_pair(decodedName, decodedValue)); - if (it != end && *it == '&') ++it; + if (it != end && *it == '&') ++it; } return result; } @@ -440,7 +437,7 @@ void URI::setPathEtc(const std::string& pathEtc) parsePathEtc(beg, end); } - + std::string URI::getPathEtc() const { std::string pathEtc; @@ -471,7 +468,7 @@ std::string URI::getPathAndQuery() const return pathAndQuery; } - + void URI::resolve(const std::string& relativeURI) { URI parsedURI(relativeURI); @@ -524,7 +521,7 @@ void URI::resolve(const URI& relativeURI) } } } - _fragment = relativeURI._fragment; + _fragment = relativeURI._fragment; } @@ -539,7 +536,7 @@ bool URI::empty() const return _scheme.empty() && _host.empty() && _path.empty() && _query.empty() && _fragment.empty(); } - + bool URI::operator == (const URI& uri) const { return equals(uri); @@ -577,7 +574,7 @@ bool URI::equals(const URI& uri) const && _fragment == uri._fragment; } - + void URI::normalize() { removeDotSegments(!isRelative()); @@ -587,7 +584,7 @@ void URI::normalize() void URI::removeDotSegments(bool removeLeading) { if (_path.empty()) return; - + bool leadingSlash = *(_path.begin()) == '/'; bool trailingSlash = *(_path.rbegin()) == '/'; std::vector segments; @@ -651,10 +648,10 @@ void URI::encode(const std::string& str, const std::string& reserved, std::strin { for (auto c: str) { - if ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || - c == '-' || c == '_' || + c == '-' || c == '_' || c == '.' || c == '~') { encodedStr += c; @@ -668,7 +665,7 @@ void URI::encode(const std::string& str, const std::string& reserved, std::strin } } - + void URI::decode(const std::string& str, std::string& decodedStr, bool plusAsSpace) { bool inQuery = false; @@ -782,7 +779,7 @@ void URI::parse(const std::string& uri) } parsePathEtc(it, end); } - else + else { it = uri.begin(); parsePathEtc(it, end); @@ -842,9 +839,9 @@ void URI::parseHostAndPort(std::string::const_iterator& it, const std::string::c else throw URISyntaxException("bad or invalid port number", port); } - else _port = getWellKnownPort(); + else _port = 0; } - else _port = getWellKnownPort(); + else _port = 0; _host = host; toLowerInPlace(_host); } @@ -872,7 +869,7 @@ void URI::parsePathEtc(std::string::const_iterator& it, const std::string::const { ++it; parseFragment(it, end); - } + } } @@ -944,7 +941,7 @@ void URI::buildPath(const std::vector& segments, bool leadingSlash, else _path += '/'; _path.append(s); } - if (trailingSlash) + if (trailingSlash) _path += '/'; } diff --git a/Foundation/testsuite/src/URITest.cpp b/Foundation/testsuite/src/URITest.cpp index 9358e9ccd..f76a28397 100644 --- a/Foundation/testsuite/src/URITest.cpp +++ b/Foundation/testsuite/src/URITest.cpp @@ -40,58 +40,60 @@ void URITest::testConstruction() assertTrue (uri.getPath().empty()); assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); - + uri.setScheme("ftp"); assertTrue (uri.getScheme() == "ftp"); assertTrue (uri.getPort() == 21); - + uri.setScheme("HTTP"); assertTrue (uri.getScheme() == "http"); - + uri.setAuthority("www.appinf.com"); assertTrue (uri.getAuthority() == "www.appinf.com"); assertTrue (uri.getPort() == 80); - + assertTrue (uri.getSpecifiedPort() == 0); + uri.setAuthority("user@services.appinf.com:8000"); assertTrue (uri.getUserInfo() == "user"); assertTrue (uri.getHost() == "services.appinf.com"); assertTrue (uri.getPort() == 8000); - + assertTrue (uri.getSpecifiedPort() == 8000); + uri.setPath("/index.html"); assertTrue (uri.getPath() == "/index.html"); - + uri.setPath("/file%20with%20spaces.html"); assertTrue (uri.getPath() == "/file with spaces.html"); - + uri.setPathEtc("/query.cgi?query=foo"); assertTrue (uri.getPath() == "/query.cgi"); assertTrue (uri.getQuery() == "query=foo"); assertTrue (uri.getFragment().empty()); assertTrue (uri.getPathEtc() == "/query.cgi?query=foo"); assertTrue (uri.getPathAndQuery() == "/query.cgi?query=foo"); - + uri.setPathEtc("/query.cgi?query=bar#frag"); assertTrue (uri.getPath() == "/query.cgi"); assertTrue (uri.getQuery() == "query=bar"); assertTrue (uri.getFragment() == "frag"); assertTrue (uri.getPathEtc() == "/query.cgi?query=bar#frag"); assertTrue (uri.getPathAndQuery() == "/query.cgi?query=bar"); - + uri.setQuery("query=test"); assertTrue (uri.getQuery() == "query=test"); - + uri.setFragment("result"); assertTrue (uri.getFragment() == "result"); - + URI uri2("file", "/home/guenter/foo.bar"); assertTrue (uri2.getScheme() == "file"); assertTrue (uri2.getPath() == "/home/guenter/foo.bar"); - + URI uri3("http", "www.appinf.com", "/index.html"); assertTrue (uri3.getScheme() == "http"); assertTrue (uri3.getAuthority() == "www.appinf.com"); assertTrue (uri3.getPath() == "/index.html"); - + URI uri4("http", "www.appinf.com:8000", "/index.html"); assertTrue (uri4.getScheme() == "http"); assertTrue (uri4.getAuthority() == "www.appinf.com:8000"); @@ -110,6 +112,7 @@ void URITest::testConstruction() assertTrue (uri6.getUserInfo() == "user"); assertTrue (uri6.getHost() == "www.appinf.com"); assertTrue (uri6.getPort() == 80); + assertTrue (uri6.getSpecifiedPort() == 80); assertTrue (uri6.getAuthority() == "user@www.appinf.com"); assertTrue (uri6.getPath() == "/index.html"); @@ -118,9 +121,10 @@ void URITest::testConstruction() assertTrue (uri7.getUserInfo() == "user"); assertTrue (uri7.getHost() == "www.appinf.com"); assertTrue (uri7.getPort() == 80); + assertTrue (uri7.getSpecifiedPort() == 0); assertTrue (uri7.getAuthority() == "user@www.appinf.com"); assertTrue (uri7.getPath() == "/index.html"); - + URI uri8("http", "www.appinf.com", "/index.html", "query=test"); assertTrue (uri8.getScheme() == "http"); assertTrue (uri8.getAuthority() == "www.appinf.com"); @@ -150,9 +154,10 @@ void URITest::testConstruction() assertTrue (uri10.getUserInfo().empty()); assertTrue (uri10.getHost() == "2001:db8::7"); assertTrue (uri10.getPort() == 389); + assertTrue (uri10.getSpecifiedPort() == 0); assertTrue (uri10.getAuthority() == "[2001:db8::7]"); assertTrue (uri10.getPathEtc() == "/c=GB?objectClass?one"); - + URI uri11("http", "www.appinf.com", "/index.html?query=test#fragment"); assertTrue (uri11.getScheme() == "http"); assertTrue (uri11.getAuthority() == "www.appinf.com"); @@ -180,7 +185,7 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); assertTrue (!uri.isRelative()); - + uri = "ftp://anonymous@ftp.appinf.com/pub/"; assertTrue (uri.getScheme() == "ftp"); assertTrue (uri.getUserInfo() == "anonymous"); @@ -201,7 +206,7 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment() == "top"); assertTrue (!uri.isRelative()); - + uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all"; assertTrue (uri.getScheme() == "http"); assertTrue (uri.getHost() == "www.appinf.com"); @@ -219,7 +224,7 @@ void URITest::testParse() assertTrue (uri.getQuery() == "keyword=test&scope=all"); assertTrue (uri.getFragment() == "result"); assertTrue (!uri.isRelative()); - + uri = "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"; assertTrue (uri.getScheme() == "http"); assertTrue (uri.getHost() == "www.appinf.com"); @@ -228,7 +233,7 @@ void URITest::testParse() assertTrue (uri.getQuery() == "keyword=test encoded&scope=all"); assertTrue (uri.getFragment() == "result"); assertTrue (!uri.isRelative()); - + uri = "ldap://[2001:db8::7]/c=GB?objectClass?one"; assertTrue (uri.getScheme() == "ldap"); assertTrue (uri.getUserInfo().empty()); @@ -238,7 +243,7 @@ void URITest::testParse() assertTrue (uri.getPath() == "/c=GB"); assertTrue (uri.getQuery() == "objectClass?one"); assertTrue (uri.getFragment().empty()); - + uri = "mailto:John.Doe@example.com"; assertTrue (uri.getScheme() == "mailto"); assertTrue (uri.getUserInfo().empty()); @@ -248,7 +253,7 @@ void URITest::testParse() assertTrue (uri.getPath() == "John.Doe@example.com"); assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); - + uri = "tel:+1-816-555-1212"; assertTrue (uri.getScheme() == "tel"); assertTrue (uri.getUserInfo().empty()); @@ -258,7 +263,7 @@ void URITest::testParse() assertTrue (uri.getPath() == "+1-816-555-1212"); assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); - + uri = "telnet://192.0.2.16:80"; assertTrue (uri.getScheme() == "telnet"); assertTrue (uri.getUserInfo().empty()); @@ -268,7 +273,7 @@ void URITest::testParse() assertTrue (uri.getPath().empty()); assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); - + uri = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"; assertTrue (uri.getScheme() == "urn"); assertTrue (uri.getUserInfo().empty()); @@ -278,7 +283,7 @@ void URITest::testParse() assertTrue (uri.getPath() == "oasis:names:specification:docbook:dtd:xml:4.1.2"); assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); - + uri = ""; assertTrue (uri.getScheme().empty()); assertTrue (uri.getAuthority().empty()); @@ -289,9 +294,9 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); assertTrue (uri.empty()); - + // relative references - + uri = "/foo/bar"; assertTrue (uri.getScheme().empty()); assertTrue (uri.getAuthority().empty()); @@ -346,8 +351,8 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment() == "frag"); assertTrue (uri.isRelative()); - - uri = "?query=test"; + + uri = "?query=test"; assertTrue (uri.getScheme().empty()); assertTrue (uri.getAuthority().empty()); assertTrue (uri.getUserInfo().empty()); @@ -358,7 +363,7 @@ void URITest::testParse() assertTrue (uri.getFragment().empty()); assertTrue (uri.isRelative()); - uri = "?query=test#frag"; + uri = "?query=test#frag"; assertTrue (uri.getScheme().empty()); assertTrue (uri.getAuthority().empty()); assertTrue (uri.getUserInfo().empty()); @@ -368,8 +373,8 @@ void URITest::testParse() assertTrue (uri.getQuery() == "query=test"); assertTrue (uri.getFragment() == "frag"); assertTrue (uri.isRelative()); - - uri = "#frag"; + + uri = "#frag"; assertTrue (uri.getScheme().empty()); assertTrue (uri.getAuthority().empty()); assertTrue (uri.getUserInfo().empty()); @@ -380,7 +385,7 @@ void URITest::testParse() assertTrue (uri.getFragment() == "frag"); assertTrue (uri.isRelative()); - uri = "#"; + uri = "#"; assertTrue (uri.getScheme().empty()); assertTrue (uri.getAuthority().empty()); assertTrue (uri.getUserInfo().empty()); @@ -390,7 +395,7 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); assertTrue (uri.isRelative()); - + uri = "file:///a/b/c"; assertTrue (uri.getScheme() == "file"); assertTrue (uri.getAuthority().empty()); @@ -412,7 +417,7 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); assertTrue (!uri.isRelative()); - + uri = "file:///c:/Windows/system32/"; assertTrue (uri.getScheme() == "file"); assertTrue (uri.getAuthority().empty()); @@ -434,7 +439,7 @@ void URITest::testParse() assertTrue (uri.getQuery().empty()); assertTrue (uri.getFragment().empty()); assertTrue (uri.isRelative()); - + uri = "ws://www.appinf.com/ws"; assertTrue (uri.getScheme() == "ws"); assertTrue (uri.getPort() == 80); @@ -452,42 +457,42 @@ void URITest::testToString() uri = "http://www.appinf.com/"; assertTrue (uri.toString() == "http://www.appinf.com/"); - + uri = "ftp://anonymous@ftp.appinf.com/pub/"; assertTrue (uri.toString() == "ftp://anonymous@ftp.appinf.com/pub/"); uri = "https://www.appinf.com/index.html#top"; assertTrue (uri.toString() == "https://www.appinf.com/index.html#top"); - + uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all"; assertTrue (uri.toString() == "http://www.appinf.com/search.cgi?keyword=test&scope=all"); uri = "http://www.appinf.com/search.cgi?keyword=test&scope=all#result"; assertTrue (uri.toString() == "http://www.appinf.com/search.cgi?keyword=test&scope=all#result"); - + uri = "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"; assertTrue (uri.toString() == "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"); - + uri = "ldap://[2001:db8::7]/c=GB?objectClass?one"; assertTrue (uri.toString() == "ldap://[2001:db8::7]/c=GB?objectClass?one"); - + uri = "mailto:John.Doe@example.com"; assertTrue (uri.toString() == "mailto:John.Doe@example.com"); - + uri = "tel:+1-816-555-1212"; assertTrue (uri.toString() == "tel:+1-816-555-1212"); - + uri = "telnet://192.0.2.16:80"; assertTrue (uri.toString() == "telnet://192.0.2.16:80"); - + uri = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"; assertTrue (uri.toString() == "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"); - + uri = ""; assertTrue (uri.toString() == ""); // relative references - + uri = "/foo/bar"; assertTrue (uri.toString() == "/foo/bar"); @@ -505,31 +510,31 @@ void URITest::testToString() uri = "index.html#frag"; assertTrue (uri.toString() == "index.html#frag"); - - uri = "?query=test"; + + uri = "?query=test"; assertTrue (uri.toString() == "?query=test"); - uri = "?query=test#frag"; + uri = "?query=test#frag"; assertTrue (uri.toString() == "?query=test#frag"); - - uri = "#frag"; + + uri = "#frag"; assertTrue (uri.toString() == "#frag"); - uri = "#"; + uri = "#"; assertTrue (uri.toString() == ""); - + uri = "file:///a/b/c"; assertTrue (uri.toString() == "file:///a/b/c"); - + uri = "file://localhost/a/b/c"; assertTrue (uri.toString() == "file://localhost/a/b/c"); - + uri = "file:///c:/Windows/system32/"; assertTrue (uri.toString() == "file:///c:/Windows/system32/"); uri = "./c:/Windows/system32/"; assertTrue (uri.toString() == "./c:/Windows/system32/"); - + uri = "http://www.appinf.com"; uri.setRawQuery("query=test"); assertTrue (uri.toString() == "http://www.appinf.com/?query=test"); @@ -543,19 +548,19 @@ void URITest::testCompare() assertTrue (uri1 == uri2); assertTrue (uri1 == "http://www.appinf.com:"); assertTrue (uri1 != "http://www.google.com"); - + uri1 = "/foo/bar"; assertTrue (uri1 == "/foo/bar"); assertTrue (uri1 != "/foo/baz"); - + uri1 = "?query"; assertTrue (uri1 == "?query"); assertTrue (uri1 != "?query2"); - + uri1 = "#frag"; assertTrue (uri1 == "#frag"); assertTrue (uri1 != "#frag2"); - + uri1 = "/index.html#frag"; assertTrue (uri1 == "/index.html#frag"); assertTrue (uri1 != "/index.html"); @@ -567,15 +572,15 @@ void URITest::testNormalize() URI uri("http://www.appinf.com"); uri.normalize(); assertTrue (uri.toString() == "http://www.appinf.com"); - + uri = "http://www.appinf.com/"; uri.normalize(); assertTrue (uri.toString() == "http://www.appinf.com/"); - + uri = "http://www.appinf.com/foo/bar/./index.html"; uri.normalize(); assertTrue (uri.toString() == "http://www.appinf.com/foo/bar/index.html"); - + uri = "http://www.appinf.com/foo/bar/../index.html"; uri.normalize(); assertTrue (uri.toString() == "http://www.appinf.com/foo/index.html"); @@ -615,7 +620,7 @@ void URITest::testNormalize() uri = "http://www.appinf.com/../foo/../"; uri.normalize(); assertTrue (uri.toString() == "http://www.appinf.com/"); - + uri = "file:///c:/Windows/system32/"; uri.normalize(); assertTrue (uri.toString() == "file:///c:/Windows/system32/"); @@ -630,13 +635,13 @@ void URITest::testNormalize() void URITest::testResolve() { URI uri("http://www.appinf.com"); - + uri.resolve("/index.html"); assertTrue (uri.toString() == "http://www.appinf.com/index.html"); - + uri.resolve("#frag"); assertTrue (uri.toString() == "http://www.appinf.com/index.html#frag"); - + uri = "http://www.appinf.com/html"; uri.resolve("../images/foo.gif"); assertTrue (uri.toString() == "http://www.appinf.com/images/foo.gif"); @@ -664,7 +669,7 @@ void URITest::testResolve() uri = "/a/b/c/d/e"; uri.resolve("./../../f/./g"); assertTrue (uri.toString() == "/a/b/f/g"); - + uri = "/a/b/../c/"; uri.resolve("../d"); assertTrue (uri.toString() == "/a/d"); @@ -704,7 +709,7 @@ void URITest::testResolve() uri = "http://www.appinf.com/html/"; uri.resolve("http://www.google.com/"); assertTrue (uri.toString() == "http://www.google.com/"); - + uri = "http://www.appinf.com/"; URI uri2(uri, "index.html"); assertTrue (uri2.toString() == "http://www.appinf.com/index.html"); @@ -719,7 +724,7 @@ void URITest::testSwap() { URI uri1("http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"); URI uri2("mailto:John.Doe@example.com"); - + uri1.swap(uri2); assertTrue (uri1.toString() == "mailto:John.Doe@example.com"); assertTrue (uri2.toString() == "http://www.appinf.com/search.cgi?keyword=test%20encoded&scope=all#result"); @@ -792,11 +797,11 @@ void URITest::testEncodeDecode() str = ""; URI::encode("http://google.com/search?q=hello+world#frag ment", "", str); assertTrue (str == "http://google.com/search?q=hello+world#frag%20ment"); - + str = ""; URI::decode("http://google.com/search?q=hello+world#frag%20ment", str, true); assertTrue (str == "http://google.com/search?q=hello world#frag ment"); - + str = ""; URI::decode("http://google.com/search?q=hello%2Bworld#frag%20ment", str); assertTrue (str == "http://google.com/search?q=hello+world#frag ment"); @@ -812,7 +817,7 @@ void URITest::testFromPath() Path path2("/var/www/site/with space.html", Path::PATH_UNIX); URI uri2(path2); assertTrue (uri2.toString() == "file:///var/www/site/with%20space.html"); - + Path path3("c:\\www\\index.html", Path::PATH_WINDOWS); URI uri3(path3); assertTrue (uri3.toString() == "file:///c:/www/index.html"); diff --git a/Net/src/FTPClientSession.cpp b/Net/src/FTPClientSession.cpp index edc3c4daa..d77fb39b4 100644 --- a/Net/src/FTPClientSession.cpp +++ b/Net/src/FTPClientSession.cpp @@ -429,7 +429,7 @@ std::string FTPClientSession::extractPath(const std::string& response) if (*it == '"') { ++it; - if (it == end || (it != end && *it != '"')) break; + if (it == end || *it != '"') break; } path += *it++; } diff --git a/NetSSL_OpenSSL/include/Poco/Net/Context.h b/NetSSL_OpenSSL/include/Poco/Net/Context.h index 5d150b83b..35b640a45 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/Context.h +++ b/NetSSL_OpenSSL/include/Poco/Net/Context.h @@ -164,10 +164,28 @@ public: /// Specifies a file containing Diffie-Hellman parameters. /// If empty, the default parameters are used. + bool dhUse2048Bits; + /// If set to true, will use 2048-bit MODP Group with 256-bit + /// prime order subgroup (RFC5114) instead of 1024-bit for DH. + std::string ecdhCurve; - /// Specifies the name of the curve to use for ECDH, based - /// on the curve names specified in RFC 4492. - /// Defaults to "prime256v1". + /// OpenSSL 1.0.1 and earlier: + /// Specifies the name of the curve to use for ECDH, based + /// on the curve names specified in RFC 4492. + /// Defaults to "prime256v1". + /// OpenSSL 1.0.2 to 1.1.0: + /// Specifies the colon-separated list of curves + /// to be used for ECDH, based on the curve names + /// defined by OpenSSL, such as + /// "X448:X25519:P-521:P-384:P-256" + /// Defaults to the subset supported by the OpenSSL version + /// among the above. + /// OpenSSL 1.1.1 and above: + /// Specifies the colon-separated list of groups + /// (some of which can be curves) to be used for ECDH + /// and other TLSv1.3 ephemeral key negotiation, based + /// on the group names defined by OpenSSL. Defaults to + /// "X448:X25519:ffdhe4096:ffdhe3072:ffdhe2048:ffdhe6144:ffdhe8192:P-521:P-384:P-256" }; Context(Usage usage, const Params& params); @@ -383,7 +401,7 @@ private: void init(const Params& params); /// Initializes the Context with the given parameters. - void initDH(const std::string& dhFile); + void initDH(bool use2048Bits, const std::string& dhFile); /// Initializes the Context with Diffie-Hellman parameters. void initECDH(const std::string& curve); diff --git a/NetSSL_OpenSSL/src/Context.cpp b/NetSSL_OpenSSL/src/Context.cpp index 8f5f34a07..c17af1b27 100644 --- a/NetSSL_OpenSSL/src/Context.cpp +++ b/NetSSL_OpenSSL/src/Context.cpp @@ -34,7 +34,8 @@ Context::Params::Params(): verificationMode(VERIFY_RELAXED), verificationDepth(9), loadDefaultCAs(false), - cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") + cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"), + dhUse2048Bits(false) { } @@ -174,7 +175,7 @@ void Context::init(const Params& params) SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY); SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF); - initDH(params.dhParamsFile); + initDH(params.dhUse2048Bits, params.dhParamsFile); initECDH(params.ecdhCurve); } catch (...) @@ -421,20 +422,33 @@ void Context::requireMinimumProtocol(Protocols protocol) { case PROTO_SSLV2: throw Poco::InvalidArgumentException("SSLv2 is no longer supported"); + case PROTO_SSLV3: disableProtocols(PROTO_SSLV2); break; + case PROTO_TLSV1: disableProtocols(PROTO_SSLV2 | PROTO_SSLV3); break; + case PROTO_TLSV1_1: +#if defined(SSL_OP_NO_TLSv1_1) && !defined(OPENSSL_NO_TLS1) disableProtocols(PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1); +#else + throw Poco::InvalidArgumentException("TLSv1.1 is not supported by the available OpenSSL library"); +#endif break; + case PROTO_TLSV1_2: +#if defined(SSL_OP_NO_TLSv1_2) && !defined(OPENSSL_NO_TLS1) disableProtocols(PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1 | PROTO_TLSV1_1); +#else + throw Poco::InvalidArgumentException("TLSv1.2 is not supported by the available OpenSSL library"); +#endif break; + case PROTO_TLSV1_3: - disableProtocols(PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1 | PROTO_TLSV1_1 | PROTO_TLSV1_2); + throw Poco::InvalidArgumentException("TLSv1.3 is not supported by the available OpenSSL library"); break; } #endif @@ -467,6 +481,24 @@ void Context::createSSLContext() { case CLIENT_USE: case TLS_CLIENT_USE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + _pSSLContext = SSL_CTX_new(TLS_client_method()); + minTLSVersion = TLS1_VERSION; +#else + _pSSLContext = SSL_CTX_new(SSLv23_client_method()); +#endif + break; + + case SERVER_USE: + case TLS_SERVER_USE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + _pSSLContext = SSL_CTX_new(TLS_server_method()); + minTLSVersion = TLS1_VERSION; +#else + _pSSLContext = SSL_CTX_new(SSLv23_server_method()); +#endif + break; + case TLSV1_CLIENT_USE: #if OPENSSL_VERSION_NUMBER >= 0x10100000L _pSSLContext = SSL_CTX_new(TLS_client_method()); @@ -476,8 +508,6 @@ void Context::createSSLContext() #endif break; - case SERVER_USE: - case TLS_SERVER_USE: case TLSV1_SERVER_USE: #if OPENSSL_VERSION_NUMBER >= 0x10100000L _pSSLContext = SSL_CTX_new(TLS_server_method()); @@ -576,20 +606,9 @@ void Context::createSSLContext() } -void Context::initDH(const std::string& dhParamsFile) +void Context::initDH(bool use2048Bits, const std::string& dhParamsFile) { #ifndef OPENSSL_NO_DH - // 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) - // -----BEGIN DH PARAMETERS----- - // MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y - // mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 - // +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV - // w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 - // sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR - // jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= - // -----END DH PARAMETERS----- - // - static const unsigned char dh1024_p[] = { 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, @@ -620,6 +639,58 @@ void Context::initDH(const std::string& dhParamsFile) 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, }; + static const unsigned char dh2048_p[] = + { + 0x87,0xA8,0xE6,0x1D,0xB4,0xB6,0x66,0x3C,0xFF,0xBB,0xD1,0x9C, + 0x65,0x19,0x59,0x99,0x8C,0xEE,0xF6,0x08,0x66,0x0D,0xD0,0xF2, + 0x5D,0x2C,0xEE,0xD4,0x43,0x5E,0x3B,0x00,0xE0,0x0D,0xF8,0xF1, + 0xD6,0x19,0x57,0xD4,0xFA,0xF7,0xDF,0x45,0x61,0xB2,0xAA,0x30, + 0x16,0xC3,0xD9,0x11,0x34,0x09,0x6F,0xAA,0x3B,0xF4,0x29,0x6D, + 0x83,0x0E,0x9A,0x7C,0x20,0x9E,0x0C,0x64,0x97,0x51,0x7A,0xBD, + 0x5A,0x8A,0x9D,0x30,0x6B,0xCF,0x67,0xED,0x91,0xF9,0xE6,0x72, + 0x5B,0x47,0x58,0xC0,0x22,0xE0,0xB1,0xEF,0x42,0x75,0xBF,0x7B, + 0x6C,0x5B,0xFC,0x11,0xD4,0x5F,0x90,0x88,0xB9,0x41,0xF5,0x4E, + 0xB1,0xE5,0x9B,0xB8,0xBC,0x39,0xA0,0xBF,0x12,0x30,0x7F,0x5C, + 0x4F,0xDB,0x70,0xC5,0x81,0xB2,0x3F,0x76,0xB6,0x3A,0xCA,0xE1, + 0xCA,0xA6,0xB7,0x90,0x2D,0x52,0x52,0x67,0x35,0x48,0x8A,0x0E, + 0xF1,0x3C,0x6D,0x9A,0x51,0xBF,0xA4,0xAB,0x3A,0xD8,0x34,0x77, + 0x96,0x52,0x4D,0x8E,0xF6,0xA1,0x67,0xB5,0xA4,0x18,0x25,0xD9, + 0x67,0xE1,0x44,0xE5,0x14,0x05,0x64,0x25,0x1C,0xCA,0xCB,0x83, + 0xE6,0xB4,0x86,0xF6,0xB3,0xCA,0x3F,0x79,0x71,0x50,0x60,0x26, + 0xC0,0xB8,0x57,0xF6,0x89,0x96,0x28,0x56,0xDE,0xD4,0x01,0x0A, + 0xBD,0x0B,0xE6,0x21,0xC3,0xA3,0x96,0x0A,0x54,0xE7,0x10,0xC3, + 0x75,0xF2,0x63,0x75,0xD7,0x01,0x41,0x03,0xA4,0xB5,0x43,0x30, + 0xC1,0x98,0xAF,0x12,0x61,0x16,0xD2,0x27,0x6E,0x11,0x71,0x5F, + 0x69,0x38,0x77,0xFA,0xD7,0xEF,0x09,0xCA,0xDB,0x09,0x4A,0xE9, + 0x1E,0x1A,0x15,0x97, + }; + + static const unsigned char dh2048_g[] = + { + 0x3F,0xB3,0x2C,0x9B,0x73,0x13,0x4D,0x0B,0x2E,0x77,0x50,0x66, + 0x60,0xED,0xBD,0x48,0x4C,0xA7,0xB1,0x8F,0x21,0xEF,0x20,0x54, + 0x07,0xF4,0x79,0x3A,0x1A,0x0B,0xA1,0x25,0x10,0xDB,0xC1,0x50, + 0x77,0xBE,0x46,0x3F,0xFF,0x4F,0xED,0x4A,0xAC,0x0B,0xB5,0x55, + 0xBE,0x3A,0x6C,0x1B,0x0C,0x6B,0x47,0xB1,0xBC,0x37,0x73,0xBF, + 0x7E,0x8C,0x6F,0x62,0x90,0x12,0x28,0xF8,0xC2,0x8C,0xBB,0x18, + 0xA5,0x5A,0xE3,0x13,0x41,0x00,0x0A,0x65,0x01,0x96,0xF9,0x31, + 0xC7,0x7A,0x57,0xF2,0xDD,0xF4,0x63,0xE5,0xE9,0xEC,0x14,0x4B, + 0x77,0x7D,0xE6,0x2A,0xAA,0xB8,0xA8,0x62,0x8A,0xC3,0x76,0xD2, + 0x82,0xD6,0xED,0x38,0x64,0xE6,0x79,0x82,0x42,0x8E,0xBC,0x83, + 0x1D,0x14,0x34,0x8F,0x6F,0x2F,0x91,0x93,0xB5,0x04,0x5A,0xF2, + 0x76,0x71,0x64,0xE1,0xDF,0xC9,0x67,0xC1,0xFB,0x3F,0x2E,0x55, + 0xA4,0xBD,0x1B,0xFF,0xE8,0x3B,0x9C,0x80,0xD0,0x52,0xB9,0x85, + 0xD1,0x82,0xEA,0x0A,0xDB,0x2A,0x3B,0x73,0x13,0xD3,0xFE,0x14, + 0xC8,0x48,0x4B,0x1E,0x05,0x25,0x88,0xB9,0xB7,0xD2,0xBB,0xD2, + 0xDF,0x01,0x61,0x99,0xEC,0xD0,0x6E,0x15,0x57,0xCD,0x09,0x15, + 0xB3,0x35,0x3B,0xBB,0x64,0xE0,0xEC,0x37,0x7F,0xD0,0x28,0x37, + 0x0D,0xF9,0x2B,0x52,0xC7,0x89,0x14,0x28,0xCD,0xC6,0x7E,0xB6, + 0x18,0x4B,0x52,0x3D,0x1D,0xB2,0x46,0xC3,0x2F,0x63,0x07,0x84, + 0x90,0xF0,0x0E,0xF8,0xD6,0x47,0xD1,0x48,0xD4,0x79,0x54,0x51, + 0x5E,0x23,0x27,0xCF,0xEF,0x98,0xC5,0x82,0x66,0x4B,0x4C,0x0F, + 0x6C,0xC4,0x16,0x59, + }; + DH* dh = 0; if (!dhParamsFile.empty()) { @@ -646,19 +717,38 @@ void Context::initDH(const std::string& dhParamsFile) throw SSLContextException("Error creating Diffie-Hellman parameters", msg); } #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) - BIGNUM* p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); - BIGNUM* g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); - DH_set0_pqg(dh, p, 0, g); - DH_set_length(dh, 160); + if (use2048Bits) + { + BIGNUM* p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), 0); + BIGNUM* g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), 0); + DH_set0_pqg(dh, p, 0, g); + DH_set_length(dh, 256); + } + else + { + BIGNUM* p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); + BIGNUM* g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); + DH_set0_pqg(dh, p, 0, g); + DH_set_length(dh, 160); + } if (!p || !g) { DH_free(dh); throw SSLContextException("Error creating Diffie-Hellman parameters"); } #else - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); - dh->length = 160; + if (use2048Bits) + { + dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), 0); + dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), 0); + dh->length = 256; + } + else + { + dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); + dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); + dh->length = 160; + } if ((!dh->p) || (!dh->g)) { DH_free(dh); @@ -678,8 +768,25 @@ void Context::initDH(const std::string& dhParamsFile) void Context::initECDH(const std::string& curve) { -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL + const std::string groups(curve.empty() ? + #if OPENSSL_VERSION_NUMBER >= 0x1010100fL + "X448:X25519:ffdhe4096:ffdhe3072:ffdhe2048:ffdhe6144:ffdhe8192:P-521:P-384:P-256" + #elif OPENSSL_VERSION_NUMBER >= 0x1010000fL + // while OpenSSL 1.1.0 didn't support Ed25519 (EdDSA using Curve25519), + // it did support X25519 (ECDH using Curve25516). + "X25519:P-521:P-384:P-256" + #else + "P-521:P-384:P-256" + #endif + : curve); + if (SSL_CTX_set1_curves_list(_pSSLContext, groups.c_str()) == 0) + { + throw SSLContextException("Cannot set ECDH groups", groups); + } + SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_ECDH_USE); + #elif OPENSSL_VERSION_NUMBER >= 0x0090800fL int nid = 0; if (!curve.empty()) { diff --git a/NetSSL_Win/src/Context.cpp b/NetSSL_Win/src/Context.cpp index 1d5bfc488..3c5272634 100644 --- a/NetSSL_Win/src/Context.cpp +++ b/NetSSL_Win/src/Context.cpp @@ -163,14 +163,14 @@ Poco::Net::X509Certificate Context::certificate() void Context::loadCertificate() { - std::wstring wcertStore; - Poco::UnicodeConverter::convert(_certStoreName, wcertStore); + std::wstring wcertStoreName; + Poco::UnicodeConverter::convert(_certStoreName, wcertStoreName); if (!_hCertStore) { if (_options & OPT_USE_MACHINE_STORE) - _hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, _certStoreName.c_str()); + _hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, wcertStoreName.c_str()); else - _hCertStore = CertOpenSystemStoreW(0, wcertStore.c_str()); + _hCertStore = CertOpenSystemStoreW(0, wcertStoreName.c_str()); } if (!_hCertStore) throw CertificateException("Failed to open certificate store", _certStoreName, GetLastError()); @@ -502,16 +502,16 @@ void Context::requireMinimumProtocol(Protocols protocol) case PROTO_SSLV3: _disabledProtocols = PROTO_SSLV2; break; - case PROTO_TLSV1: + case PROTO_TLSV1: _disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3; break; - case PROTO_TLSV1_1: + case PROTO_TLSV1_1: _disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1; break; - case PROTO_TLSV1_2: + case PROTO_TLSV1_2: _disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1 | PROTO_TLSV1_1; break; - case PROTO_TLSV1_3: + case PROTO_TLSV1_3: _disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1 | PROTO_TLSV1_1 | PROTO_TLSV1_2; break; } diff --git a/NetSSL_Win/src/X509Certificate.cpp b/NetSSL_Win/src/X509Certificate.cpp index 952ef0f59..bcb79ea1e 100644 --- a/NetSSL_Win/src/X509Certificate.cpp +++ b/NetSSL_Win/src/X509Certificate.cpp @@ -381,13 +381,13 @@ void* X509Certificate::nid2oid(NID nid) void X509Certificate::loadCertificate(const std::string& certName, const std::string& certStoreName, bool useMachineStore) { - std::wstring wcertStore; - Poco::UnicodeConverter::convert(certStoreName, wcertStore); + std::wstring wcertStoreName; + Poco::UnicodeConverter::convert(certStoreName, wcertStoreName); HCERTSTORE hCertStore; if (useMachineStore) - hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, certStoreName.c_str()); + hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, wcertStoreName.c_str()); else - hCertStore = CertOpenSystemStoreW(0, wcertStore.c_str()); + hCertStore = CertOpenSystemStoreW(0, wcertStoreName.c_str()); if (!hCertStore) throw CertificateException("Failed to open certificate store", certStoreName, GetLastError()); diff --git a/VERSION b/VERSION index 81c871de4..4dae2985b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.10.0 +1.10.1 diff --git a/cmake/PocoMacros.cmake b/cmake/PocoMacros.cmake index 4490b7b64..14ebbb6c7 100644 --- a/cmake/PocoMacros.cmake +++ b/cmake/PocoMacros.cmake @@ -233,20 +233,27 @@ configure_file("cmake/Poco${target_name}Config.cmake" @ONLY ) -set(ConfigPackageLocation "lib/cmake/${PROJECT_NAME}") +# Set config script install location in a location that find_package() will +# look for, which is different on MS Windows than for UNIX +# Note: also set in root CMakeLists.txt +if (WIN32) + set(PocoConfigPackageLocation "cmake") +else() + set(PocoConfigPackageLocation "lib/cmake/${PROJECT_NAME}") +endif() install( EXPORT "${target_name}Targets" FILE "${PROJECT_NAME}${target_name}Targets.cmake" NAMESPACE "${PROJECT_NAME}::" - DESTINATION "lib${LIB_SUFFIX}/cmake/${PROJECT_NAME}" + DESTINATION "${PocoConfigPackageLocation}" ) install( FILES "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}${target_name}Config.cmake" "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}${target_name}ConfigVersion.cmake" - DESTINATION "lib${LIB_SUFFIX}/cmake/${PROJECT_NAME}" + DESTINATION "${PocoConfigPackageLocation}" COMPONENT Devel ) diff --git a/doc/99100-ReleaseNotes.page b/doc/99100-ReleaseNotes.page index 435c55798..56fa99686 100644 --- a/doc/99100-ReleaseNotes.page +++ b/doc/99100-ReleaseNotes.page @@ -1,6 +1,14 @@ POCO C++ Libraries Release Notes AAAIntroduction +!!!Release 1.10.1 + +!!Summary of Changes + + - TODO + + + !!!Release 1.10.0 !!Summary of Changes diff --git a/libversion b/libversion index d7765fe47..2fb681e3f 100644 --- a/libversion +++ b/libversion @@ -1 +1 @@ -70 \ No newline at end of file +71 \ No newline at end of file