mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-10-27 11:06:50 +01:00 
			
		
		
		
	GH# 878: check for valid hex characters, support SHA-1 name-based UUIDs (v5)
This commit is contained in:
		| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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 <cstring> | ||||
|  | ||||
| @@ -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<SHA1Engine*>(&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); | ||||
| } | ||||
|  | ||||
| 	 | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "CppUnit/TestSuite.h" | ||||
| #include "Poco/UUIDGenerator.h" | ||||
| #include "Poco/UUID.h" | ||||
| #include "Poco/SHA1Engine.h" | ||||
| #include <set> | ||||
|  | ||||
|  | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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&) | ||||
| 	{ | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Guenter Obiltschnig
					Guenter Obiltschnig