From e4dcb85c1f9cd0520abe30b7b567a7e3ff75a0ca Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Fri, 31 Jul 2015 12:17:20 +0200 Subject: [PATCH] merge fix for #878 --- Foundation/include/Poco/UUID.h | 12 ++-- Foundation/include/Poco/UUIDGenerator.h | 7 +++ Foundation/src/UUID.cpp | 44 ++++++++++----- Foundation/src/UUIDGenerator.cpp | 11 +++- .../testsuite/src/UUIDGeneratorTest.cpp | 7 +++ Foundation/testsuite/src/UUIDTest.cpp | 55 +++++++++++++++++++ 6 files changed, 116 insertions(+), 20 deletions(-) diff --git a/Foundation/include/Poco/UUID.h b/Foundation/include/Poco/UUID.h index f38ab0818..bff45275f 100644 --- a/Foundation/include/Poco/UUID.h +++ b/Foundation/include/Poco/UUID.h @@ -46,10 +46,12 @@ class Foundation_API UUID public: enum Version { - UUID_TIME_BASED = 0x01, - UUID_DCE_UID = 0x02, - UUID_NAME_BASED = 0x03, - UUID_RANDOM = 0x04 + UUID_TIME_BASED = 0x01, + UUID_DCE_UID = 0x02, + UUID_NAME_BASED = 0x03, + UUID_RANDOM = 0x04, + UUID_NAME_BASED_SHA1 = 0x05 + }; UUID(); @@ -141,7 +143,7 @@ protected: static void appendHex(std::string& str, UInt8 n); static void appendHex(std::string& str, UInt16 n); static void appendHex(std::string& str, UInt32 n); - static UInt8 nibble(char hex); + static Int16 nibble(char hex); void fromNetwork(); void toNetwork(); diff --git a/Foundation/include/Poco/UUIDGenerator.h b/Foundation/include/Poco/UUIDGenerator.h index d03f06617..ffa713eef 100644 --- a/Foundation/include/Poco/UUIDGenerator.h +++ b/Foundation/include/Poco/UUIDGenerator.h @@ -61,6 +61,13 @@ public: UUID createFromName(const UUID& nsid, const std::string& name, DigestEngine& de); /// Creates a name-based UUID, using the given digest engine. + /// + /// Note: in order to create a standard-compliant UUID, the given DigestEngine + /// must be either an instance of MD5Engine or SHA1Engine. The version field of + /// the UUID will be set accordingly. + + UUID createFromName(const UUID& nsid, const std::string& name, DigestEngine& de, UUID::Version version); + /// Creates a name-based UUID, using the given digest engine and version. UUID createRandom(); /// Creates a random UUID. diff --git a/Foundation/src/UUID.cpp b/Foundation/src/UUID.cpp index 0d49970e3..265b113d7 100644 --- a/Foundation/src/UUID.cpp +++ b/Foundation/src/UUID.cpp @@ -127,6 +127,7 @@ void UUID::parse(const std::string& uuid) throw SyntaxException(uuid); } + bool UUID::tryParse(const std::string& uuid) { if (uuid.size() < 32) @@ -141,35 +142,50 @@ bool UUID::tryParse(const std::string& uuid) return false; } + UUID newUUID; std::string::const_iterator it = uuid.begin(); - _timeLow = 0; + newUUID._timeLow = 0; for (int i = 0; i < 8; ++i) { - _timeLow = (_timeLow << 4) | nibble(*it++); + Int16 n = nibble(*it++); + if (n < 0) return false; + newUUID._timeLow = (newUUID._timeLow << 4) | n; } if (haveHyphens) ++it; - _timeMid = 0; + newUUID._timeMid = 0; for (int i = 0; i < 4; ++i) { - _timeMid = (_timeMid << 4) | nibble(*it++); + Int16 n = nibble(*it++); + if (n < 0) return false; + newUUID._timeMid = (newUUID._timeMid << 4) | n; } if (haveHyphens) ++it; - _timeHiAndVersion = 0; + newUUID._timeHiAndVersion = 0; for (int i = 0; i < 4; ++i) { - _timeHiAndVersion = (_timeHiAndVersion << 4) | nibble(*it++); + Int16 n = nibble(*it++); + if (n < 0) return false; + newUUID._timeHiAndVersion = (newUUID._timeHiAndVersion << 4) | n; } if (haveHyphens) ++it; - _clockSeq = 0; + newUUID._clockSeq = 0; for (int i = 0; i < 4; ++i) { - _clockSeq = (_clockSeq << 4) | nibble(*it++); + Int16 n = nibble(*it++); + if (n < 0) return false; + newUUID._clockSeq = (newUUID._clockSeq << 4) | n; } if (haveHyphens) ++it; for (int i = 0; i < 6; ++i) { - _node[i] = (nibble(*it++) << 4) | nibble(*it++) ; + Int16 n1 = nibble(*it++); + if (n1 < 0) return false; + Int16 n2 = nibble(*it++); + if (n2 < 0) return false; + + newUUID._node[i] = (n1 << 4) | n2; } + swap(newUUID); return true; } @@ -282,16 +298,16 @@ void UUID::appendHex(std::string& str, UInt32 n) } -UInt8 UUID::nibble(char hex) +Int16 UUID::nibble(char hex) { if (hex >= 'a' && hex <= 'f') - return UInt8(hex - 'a' + 10); + return hex - 'a' + 10; else if (hex >= 'A' && hex <= 'F') - return UInt8(hex - 'A' + 10); + return hex - 'A' + 10; else if (hex >= '0' && hex <= '9') - return UInt8(hex - '0'); + return hex - '0'; else - return UInt8(0); + return -1; } diff --git a/Foundation/src/UUIDGenerator.cpp b/Foundation/src/UUIDGenerator.cpp index a822ada01..8647ec626 100644 --- a/Foundation/src/UUIDGenerator.cpp +++ b/Foundation/src/UUIDGenerator.cpp @@ -19,6 +19,7 @@ #include "Poco/RandomStream.h" #include "Poco/DigestEngine.h" #include "Poco/MD5Engine.h" +#include "Poco/SHA1Engine.h" #include "Poco/SingletonHolder.h" #include @@ -62,6 +63,14 @@ UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name) UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name, DigestEngine& de) +{ + UUID::Version version = UUID::UUID_NAME_BASED; + if (dynamic_cast(&de)) version = UUID::UUID_NAME_BASED_SHA1; + return createFromName(nsid, name, de, version); +} + + +UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name, DigestEngine& de, UUID::Version version) { poco_assert_dbg (de.digestLength() >= 16); @@ -80,7 +89,7 @@ UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name, Di { buffer[i] = d[i]; } - return UUID(buffer, UUID::UUID_NAME_BASED); + return UUID(buffer, version); } diff --git a/Foundation/testsuite/src/UUIDGeneratorTest.cpp b/Foundation/testsuite/src/UUIDGeneratorTest.cpp index 75ef6db35..8e69d3e6d 100644 --- a/Foundation/testsuite/src/UUIDGeneratorTest.cpp +++ b/Foundation/testsuite/src/UUIDGeneratorTest.cpp @@ -15,6 +15,7 @@ #include "CppUnit/TestSuite.h" #include "Poco/UUIDGenerator.h" #include "Poco/UUID.h" +#include "Poco/SHA1Engine.h" #include @@ -84,6 +85,12 @@ void UUIDGeneratorTest::testNameBased() UUID uuid6 = gen.createFromName(UUID::uri(), "http://www.appinf.com/uuid"); assert (uuid6 == uuid1); + + Poco::SHA1Engine sha1; + UUID uuid7 = gen.createFromName(UUID::uri(), "http://www.appinf.com/uuid", sha1); + assert (uuid7.version() == UUID::UUID_NAME_BASED_SHA1); + assert (uuid7.variant() == 2); + assert (uuid7 != uuid1); } diff --git a/Foundation/testsuite/src/UUIDTest.cpp b/Foundation/testsuite/src/UUIDTest.cpp index 6b04a56eb..613fc0468 100644 --- a/Foundation/testsuite/src/UUIDTest.cpp +++ b/Foundation/testsuite/src/UUIDTest.cpp @@ -14,6 +14,7 @@ #include "CppUnit/TestCaller.h" #include "CppUnit/TestSuite.h" #include "Poco/UUID.h" +#include "Poco/Exception.h" using Poco::UUID; @@ -39,6 +40,60 @@ void UUIDTest::testParse() uuid.parse("6BA7B8109DAD11D180B400C04FD430C8"); assert (uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8"); + + try + { + uuid.parse("6xA7B8109DAD11D180B400C04FD430C8"); + fail("invalid UUID - must throw"); + } + catch (Poco::SyntaxException&) + { + } + + try + { + uuid.parse("6xa7b810-9dad-11d1-80b4-00c04fd430c8"); + fail("invalid UUID - must throw"); + } + catch (Poco::SyntaxException&) + { + } + + try + { + uuid.parse("6ba7b810-xdad-11d1-80b4-00c04fd430c8"); + fail("invalid UUID - must throw"); + } + catch (Poco::SyntaxException&) + { + } + + try + { + uuid.parse("6ba7b810-9dad-x1d1-80b4-00c04fd430c8"); + fail("invalid UUID - must throw"); + } + catch (Poco::SyntaxException&) + { + } + + try + { + uuid.parse("6ba7b810-9dad-11d1-x0b4-00c04fd430c8"); + fail("invalid UUID - must throw"); + } + catch (Poco::SyntaxException&) + { + } + + try + { + uuid.parse("6ba7b810-9dad-11d1-80b4-00x04fd430c8"); + fail("invalid UUID - must throw"); + } + catch (Poco::SyntaxException&) + { + } }