class UUIDParseFailureKind: FORMAT = 2 class UUIDParseNumbers: NOSPACE = 2 class UUIDParseResult: def __init__(self): self.parsedGuid = Guid() self.kind = None self.message = None def setFailure(self, kind, message): self.kind = kind self.message = message class URandom: def __init__(self): try: self.__urand = open("/dev/urandom", "rb") except: self.__urand = None def read(self, length : int) -> bytes: if self.__urand is not None: return self.__urand.read(length) else: # If /dev/urandom isn't available (eg: in non-unix systems), use mt_rand(). # __pr_bits = "" # for cnt in range(0, 16): # __pr_bits += chr ( __mt_rand ( 0, 255 ) ) pass import os return os.urandom(length) class Guid: __urand = None def __init__(self): if Guid.__urand is None: Guid.__urand = URandom() self.__a = 0 self.__b = 0 self.__c = 0 self.__d = 0 self.__e = 0 self.__f = 0 self.__g = 0 self.__h = 0 self.__i = 0 self.__j = 0 self.__k = 0 @staticmethod def __stringToInt(guidString : str, parsePos : int, requiredLength : int, flags : int, result : int, parseResult): parseWhat = guidString[parsePos:(parsePos+requiredLength)] result = int(parseWhat, 16) parsePos += requiredLength return (parsePos, result) @staticmethod def from_bytes(b : bytes): guid = Guid() guid.__a = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0] guid.__b = (b[5] << 8) | b[4] guid.__c = ((b[7] << 8) | b[6]) guid.__d = b[8] guid.__e = b[9] guid.__f = b[10] guid.__g = b[11] guid.__h = b[12] guid.__i = b[13] guid.__j = b[14] guid.__k = b[15] return guid @staticmethod def __tryParseGuidWithDashes(guidString : str) -> UUIDParseResult: result = UUIDParseResult() print (guidString) if guidString == "": return result guidString = guidString.replace("{", "").replace("}", "").replace("-", "") import codecs try: myBytes = codecs.decode(guidString, 'hex') except: return result guidBytes = [ myBytes[3], myBytes[2], myBytes[1], myBytes[0], myBytes[5], myBytes[4], myBytes[7], myBytes[6], myBytes[8], myBytes[9], myBytes[10], myBytes[11], myBytes[12], myBytes[13], myBytes[14], myBytes[15] ] result.parsedGuid = Guid.from_bytes(guidBytes) return result """ startPos = 0 temp = 0 templ = 0 currentPos = 0 result = UUIDParseResult() hasDashes = True if (len(guidString) < 1): print(guidString) result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[?]") return result # check to see that it's the proper length if guidString[0] == '{': if len(guidString) != 38 or guidString[37] != '}': print(guidString) result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[38]") return result startPos = 1 elif guidString[0] == '(': if len(guidString) != 38 or guidString[37] != ')': print(guidString) result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[38]") return result startPos = 1 elif len(guidString) != 36: if len(guidString) != 32: print(guidString) result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidInvLen[36]") return result else: hasDashes = False if hasDashes: if (guidString[8 + startPos] != '-' or guidString[13 + startPos] != '-' or guidString[18 + startPos] != '-' or guidString[23 + startPos] != '-'): result.setFailure(UUIDParseFailureKind.FORMAT, "Format_GuidDashes") return result currentPos = startPos (parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 8, UUIDParseNumbers.NOSPACE, temp, result) result.parsedGuid.__a = temp currentPos = parsePos if hasDashes: currentPos = currentPos + 1; # Increment past the '-'; (parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, temp, result) result.parsedGuid.__b = temp currentPos = parsePos if hasDashes: currentPos = currentPos + 1 # Increment past the '-'; (parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, temp, result) result.parsedGuid.__c = temp currentPos = parsePos if hasDashes: currentPos = currentPos + 1 # Increment past the '-'; (parsePos, temp) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, temp, result) result.parsedGuid.__d = temp >> 8 result.parsedGuid.__e = temp - (temp >> 8) currentPos = parsePos if hasDashes: currentPos = currentPos + 1 # Increment past the '-'; startPos = currentPos (parsePos, templ) = Guid.__stringToInt(guidString, currentPos, 8, UUIDParseNumbers.NOSPACE, templ, result) currentPos = parsePos (parsePos, temp2) = Guid.__stringToInt(guidString, currentPos, 4, UUIDParseNumbers.NOSPACE, templ, result) # /* # if ($currentPos - $startPos != 12) { # $result->setFailure(UUIDParseFailureKind::FORMAT, "Format_GuidInvLen(*)") # return $result; # } # */ result.parsedGuid.__j = temp2 >> 8 result.parsedGuid.__k = temp2 - (temp2 >> 8) temp = templ result.parsedGuid.__f = temp >> 24 result.parsedGuid.__g = (temp >> 16) - (temp >> 24) result.parsedGuid.__h = (temp >> 8) - (temp >> 16) result.parsedGuid.__i = temp - (temp >> 8) return result """ def parse(value : str): if value is None: return None result = Guid.__tryParseGuidWithDashes(value) return result.parsedGuid def __eq__(self, other): # /* # if ( # $uuid->clock_seq_hi_and_reserved == self.clock_seq_hi_and_reserved # && $uuid->node == self.node # && $uuid->time_hi_and_version == self.time_hi_and_version # && $uuid->time_low == self.time_low # && $uuid->time_mid == self.time_mid # ) # { # return true; # } # */ return ( other.__a == self.__a and other.__b == self.__b and other.__c == self.__c and other.__d == self.__d and other.__e == self.__e and other.__f == self.__f and other.__g == self.__g and other.__h == self.__h and other.__i == self.__i and other.__j == self.__j and other.__k == self.__k ) @staticmethod def __init_bits(self): self.pr_bits = Guid.__urand.read(16) self.__a = (int(self.pr_bits[3]) << 24) | (int(self.pr_bits[2]) << 16) | (int(self.pr_bits[1]) << 8) | self.pr_bits[0] self.__b = ((int(self.pr_bits[5]) << 8) | self.pr_bits[4]) self.__c = ((int(self.pr_bits[7]) << 8) | self.pr_bits[6]) self.__d = self.pr_bits[8] self.__e = self.pr_bits[9] self.__f = self.pr_bits[10] self.__g = self.pr_bits[11] self.__h = self.pr_bits[12] self.__i = self.pr_bits[13] self.__j = self.pr_bits[14] self.__k = self.pr_bits[15] """ @brief Generates a Universally Unique IDentifier, version 4. This function generates a truly random UUID. The built in CakePHP String::uuid() function is not cryptographically secure. You should uses this function instead. @see http://tools.ietf.org/html/rfc4122#section-4.4 @see http://en.wikipedia.org/wiki/UUID @return UUID A UUID, made up of 32 hex digits and 4 hyphens. """ @staticmethod def generate(): uuid = Guid() uuid.__init_bits() return uuid @staticmethod def __hexToChar(a : int) -> str: a = a & 0xf v = 0 if a > 9: v = a - 10 + 0x61 else: v = a + 0x30 return chr(v) @staticmethod def __hexsToChars(a : int, b : int, hex : bool = False): guidChars = "" if hex: guidChars = "0x" guidChars += Guid.__hexToChar(a >> 4) guidChars += Guid.__hexToChar(a) if hex: guidChars += ",0x" guidChars += Guid.__hexToChar(b >> 4) guidChars += Guid.__hexToChar(b) return guidChars # public function __toString() # { # } # public function __toStringFormat($includeDashes = true, $prefix = "{", $suffix = "}") # { # $guidChars = $prefix; # $guidChars += Guid.__hexsToChars(self._a >> 24, self._a >> 16) # $guidChars += Guid.__hexsToChars(self._a >> 8, self._a) # if ($includeDashes) $guidChars += '-'; # $guidChars += Guid.__hexsToChars(self._b >> 8, self._b) # if ($includeDashes) $guidChars += '-'; # $guidChars += Guid.__hexsToChars(self._c >> 8, self._c) # if ($includeDashes) $guidChars += '-'; # $guidChars += Guid.__hexsToChars(self._d, self._e) # if ($includeDashes) $guidChars += '-'; # $guidChars += Guid.__hexsToChars(self._f, self._g) # $guidChars += Guid.__hexsToChars(self._h, self._i) # $guidChars += Guid.__hexsToChars(self._j, self._k) # $guidChars += $suffix; # return $guidChars; # } def format(input : str): output = input output = output[0:8] + "-" + output[8:(8+4)] + "-" + output[12:12+4] + "-" + output[16:16+4] + "-" + output[20:] return "{" + output + "}" def strip(self): guidChars = "" guidChars += Guid.__hexsToChars(self.__a >> 24, self.__a >> 16) guidChars += Guid.__hexsToChars(self.__a >> 8, self.__a) guidChars += Guid.__hexsToChars(self.__b >> 8, self.__b) guidChars += Guid.__hexsToChars(self.__c >> 8, self.__c) guidChars += Guid.__hexsToChars(self.__d, self.__e) guidChars += Guid.__hexsToChars(self.__f, self.__g) guidChars += Guid.__hexsToChars(self.__h, self.__i) guidChars += Guid.__hexsToChars(self.__j, self.__k) return guidChars.lower() def __str__(self): # //return self.format(strtoupper( sprintf ( '%08s%04s%04x%04x%012s', self.time_low, self.time_mid, self.time_hi_and_version, self.clock_seq_hi_and_reserved, self.node ) )) dash = True guidChars = "{" guidChars += Guid.__hexsToChars(self.__a >> 24, self.__a >> 16) guidChars += Guid.__hexsToChars(self.__a >> 8, self.__a) if (dash): guidChars += '-' guidChars += Guid.__hexsToChars(self.__b >> 8, self.__b) if (dash): guidChars += '-' guidChars += Guid.__hexsToChars(self.__c >> 8, self.__c) if (dash): guidChars += '-' guidChars += Guid.__hexsToChars(self.__d, self.__e) if (dash): guidChars += '-' guidChars += Guid.__hexsToChars(self.__f, self.__g) guidChars += Guid.__hexsToChars(self.__h, self.__i) guidChars += Guid.__hexsToChars(self.__j, self.__k) guidChars += "}" return guidChars.lower() @staticmethod def create(): from uuid import uuid4 u = uuid4() g = Guid.parse(str(u)) return g def __key(self): return (self.__a, self.__b, self.__c, self.__d, self.__e, self.__f, self.__g, self.__h, self.__i, self.__j, self.__k) def __hash__(self): return hash(self.__key()) def __eq__(self, other): if isinstance(other, Guid): return self.__key() == other.__key() return NotImplemented def to_bytes(self) -> bytes: a = self.__a.to_bytes(4, 'little') b = self.__b.to_bytes(2, 'little') c = self.__c.to_bytes(2, 'little') a0 = a[0] a1 = a[1] a2 = a[2] a3 = a[3] b0 = b[0] b1 = b[1] c0 = c[0] c1 = c[1] d = self.__d e = self.__e f = self.__f g = self.__g h = self.__h i = self.__i j = self.__j k = self.__k sss = [a0, a1, a2, a3, b0, b1, c0, c1, d, e, f, g, h, i, j, k] return bytes(sss)