diff options
-rwxr-xr-x | indra/newview/viewer_manifest.py | 4 | ||||
-rwxr-xr-x | indra/viewer_components/manager/base/llsd.py (renamed from indra/viewer_components/manager/llsd.py) | 0 | ||||
-rwxr-xr-x | indra/viewer_components/manager/base/lluuid.py | 319 | ||||
-rwxr-xr-x | indra/viewer_components/manager/util/fastest_elementtree.py | 64 |
4 files changed, 386 insertions, 1 deletions
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 9194a2161a..ac9b8d8ebe 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -712,9 +712,11 @@ class Darwin_i386_Manifest(ViewerManifest): if self.prefix(dst="MacOS"): self.path2basename("../viewer_components/updater/scripts/darwin", "*.py") - #this copies over the python wrapper script, see SL-322 + #this copies over the python wrapper script and associated utilities, see SL-321, SL-322 and SL-323 self.path2basename("../viewer_components/manager","SL_Launcher") self.path2basename("../viewer_components/manager","*.py") + self.path2basename("../viewer_components/manager/base","*py") + self.path2basename("../viewer_components/manager/util","*py") self.end_prefix() # most everything goes in the Resources directory diff --git a/indra/viewer_components/manager/llsd.py b/indra/viewer_components/manager/base/llsd.py index 4527b115f9..4527b115f9 100755 --- a/indra/viewer_components/manager/llsd.py +++ b/indra/viewer_components/manager/base/llsd.py diff --git a/indra/viewer_components/manager/base/lluuid.py b/indra/viewer_components/manager/base/lluuid.py new file mode 100755 index 0000000000..7413ffe10d --- /dev/null +++ b/indra/viewer_components/manager/base/lluuid.py @@ -0,0 +1,319 @@ +"""\ +@file lluuid.py +@brief UUID parser/generator. + +$LicenseInfo:firstyear=2004&license=mit$ + +Copyright (c) 2004-2009, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +""" + +import random, socket, string, time, re +import uuid +try: + # Python 2.6 + from hashlib import md5 +except ImportError: + # Python 2.5 and earlier + from md5 import new as md5 + +def _int2binstr(i,l): + s='' + for a in range(l): + s=chr(i&0xFF)+s + i>>=8 + return s + +def _binstr2int(s): + i = long(0) + for c in s: + i = (i<<8) + ord(c) + return i + +class UUID(object): + """ + A class which represents a 16 byte integer. Stored as a 16 byte 8 + bit character string. + + The string version is to be of the form: + AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex) + where A=network address, B=timestamp, C=random. + """ + + NULL_STR = "00000000-0000-0000-0000-000000000000" + + # the UUIDREGEX_STRING is helpful for parsing UUID's in text + hex_wildcard = r"[0-9a-fA-F]" + word = hex_wildcard + r"{4,4}-" + long_word = hex_wildcard + r"{8,8}-" + very_long_word = hex_wildcard + r"{12,12}" + UUID_REGEX_STRING = long_word + word + word + word + very_long_word + uuid_regex = re.compile(UUID_REGEX_STRING) + + rand = random.Random() + ip = '' + try: + ip = socket.gethostbyname(socket.gethostname()) + except(socket.gaierror, socket.error): + # no ip address, so just default to somewhere in 10.x.x.x + ip = '10' + for i in range(3): + ip += '.' + str(rand.randrange(1,254)) + hexip = ''.join(["%04x" % long(i) for i in ip.split('.')]) + lastid = '' + + def __init__(self, possible_uuid=None): + """ + Initialize to first valid UUID in argument (if a string), + or to null UUID if none found or argument is not supplied. + + If the argument is a UUID, the constructed object will be a copy of it. + """ + self._bits = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + if possible_uuid is None: + return + + if isinstance(possible_uuid, type(self)): + self.set(possible_uuid) + return + + uuid_match = UUID.uuid_regex.search(possible_uuid) + if uuid_match: + uuid_string = uuid_match.group() + s = string.replace(uuid_string, '-', '') + self._bits = _int2binstr(string.atol(s[:8],16),4) + \ + _int2binstr(string.atol(s[8:16],16),4) + \ + _int2binstr(string.atol(s[16:24],16),4) + \ + _int2binstr(string.atol(s[24:],16),4) + + def __len__(self): + """ + Used by the len() builtin. + """ + return 36 + + def __nonzero__(self): + return self._bits != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + def __str__(self): + uuid_string = self.toString() + return uuid_string + + __repr__ = __str__ + + def __getitem__(self, index): + return str(self)[index] + + def __eq__(self, other): + if isinstance(other, (str, unicode)): + return other == str(self) + return self._bits == getattr(other, '_bits', '') + + def __ne__(self, other): + return not self.__eq__(other) + + def __le__(self, other): + return self._bits <= other._bits + + def __ge__(self, other): + return self._bits >= other._bits + + def __lt__(self, other): + return self._bits < other._bits + + def __gt__(self, other): + return self._bits > other._bits + + def __hash__(self): + return hash(self._bits) + + def set(self, uuid): + self._bits = uuid._bits + + def setFromString(self, uuid_string): + """ + Given a string version of a uuid, set self bits + appropriately. Returns self. + """ + s = string.replace(uuid_string, '-', '') + self._bits = _int2binstr(string.atol(s[:8],16),4) + \ + _int2binstr(string.atol(s[8:16],16),4) + \ + _int2binstr(string.atol(s[16:24],16),4) + \ + _int2binstr(string.atol(s[24:],16),4) + return self + + def setFromMemoryDump(self, gdb_string): + """ + We expect to get gdb_string as four hex units. eg: + 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2 + Which will be translated to: + db547d14-1b3f4bc3-9b984f71-d22f890a + Returns self. + """ + s = string.replace(gdb_string, '0x', '') + s = string.replace(s, ' ', '') + t = '' + for i in range(8,40,8): + for j in range(0,8,2): + t = t + s[i-j-2:i-j] + self.setFromString(t) + + def toString(self): + """ + Return as a string matching the LL standard + AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex) + where A=network address, B=timestamp, C=random. + """ + return uuid_bits_to_string(self._bits) + + def getAsString(self): + """ + Return a different string representation of the form + AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex) + where A=network address, B=timestamp, C=random. + """ + i1 = _binstr2int(self._bits[0:4]) + i2 = _binstr2int(self._bits[4:8]) + i3 = _binstr2int(self._bits[8:12]) + i4 = _binstr2int(self._bits[12:16]) + return '%08lx-%08lx-%08lx-%08lx' % (i1,i2,i3,i4) + + def generate(self): + """ + Generate a new uuid. This algorithm is slightly different + from c++ implementation for portability reasons. + Returns self. + """ + m = md5() + m.update(uuid.uuid1().bytes) + self._bits = m.digest() + return self + + def isNull(self): + """ + Returns 1 if the uuid is null - ie, equal to default uuid. + """ + return (self._bits == "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") + + def xor(self, rhs): + """ + xors self with rhs. + """ + v1 = _binstr2int(self._bits[0:4]) ^ _binstr2int(rhs._bits[0:4]) + v2 = _binstr2int(self._bits[4:8]) ^ _binstr2int(rhs._bits[4:8]) + v3 = _binstr2int(self._bits[8:12]) ^ _binstr2int(rhs._bits[8:12]) + v4 = _binstr2int(self._bits[12:16]) ^ _binstr2int(rhs._bits[12:16]) + self._bits = _int2binstr(v1,4) + \ + _int2binstr(v2,4) + \ + _int2binstr(v3,4) + \ + _int2binstr(v4,4) + + +# module-level null constant +NULL = UUID() + +def printTranslatedMemory(four_hex_uints): + """ + We expect to get the string as four hex units. eg: + 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2 + Which will be translated to: + db547d14-1b3f4bc3-9b984f71-d22f890a + """ + uuid = UUID() + uuid.setFromMemoryDump(four_hex_uints) + print uuid.toString() + +def isUUID(id_str): + """ + This function returns: + - 1 if the string passed is a UUID + - 0 is the string passed is not a UUID + - None if it neither of the if's below is satisfied + """ + if not id_str or len(id_str) < 5 or len(id_str) > 36: + return 0 + + if isinstance(id_str, UUID) or UUID.uuid_regex.match(id_str): + return 1 + + return None + +def isPossiblyID(id_str): + """ + This function returns 1 if the string passed has some uuid-like + characteristics. Otherwise returns 0. + """ + + is_uuid = isUUID(id_str) + if is_uuid is not None: + return is_uuid + + # build a string which matches every character. + hex_wildcard = r"[0-9a-fA-F]" + chars = len(id_str) + next = min(chars, 8) + matcher = hex_wildcard+"{"+str(next)+","+str(next)+"}" + chars = chars - next + if chars > 0: + matcher = matcher + "-" + chars = chars - 1 + for block in range(3): + next = max(min(chars, 4), 0) + if next: + matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}" + chars = chars - next + if chars > 0: + matcher = matcher + "-" + chars = chars - 1 + if chars > 0: + next = min(chars, 12) + matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}" + #print matcher + uuid_matcher = re.compile(matcher) + if uuid_matcher.match(id_str): + return 1 + return 0 + +def uuid_bits_to_string(bits): + i1 = _binstr2int(bits[0:4]) + i2 = _binstr2int(bits[4:6]) + i3 = _binstr2int(bits[6:8]) + i4 = _binstr2int(bits[8:10]) + i5 = _binstr2int(bits[10:12]) + i6 = _binstr2int(bits[12:16]) + return '%08lx-%04lx-%04lx-%04lx-%04lx%08lx' % (i1,i2,i3,i4,i5,i6) + +def uuid_bits_to_uuid(bits): + return UUID(uuid_bits_to_string(bits)) + + +try: + from mulib import stacked + stacked.NoProducer() # just to exercise stacked +except: + #print "Couldn't import mulib.stacked, not registering UUID converter" + pass +else: + def convertUUID(uuid, req): + req.write(str(uuid)) + + stacked.add_producer(UUID, convertUUID, "*/*") + stacked.add_producer(UUID, convertUUID, "text/html") diff --git a/indra/viewer_components/manager/util/fastest_elementtree.py b/indra/viewer_components/manager/util/fastest_elementtree.py new file mode 100755 index 0000000000..4fcf662dd9 --- /dev/null +++ b/indra/viewer_components/manager/util/fastest_elementtree.py @@ -0,0 +1,64 @@ +"""\ +@file fastest_elementtree.py +@brief Concealing some gnarly import logic in here. This should export the interface of elementtree. + +$LicenseInfo:firstyear=2008&license=mit$ + +Copyright (c) 2008-2009, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +""" + +# The parsing exception raised by the underlying library depends +# on the ElementTree implementation we're using, so we provide an +# alias here. +# +# Use ElementTreeError as the exception type for catching parsing +# errors. + + +# Using cElementTree might cause some unforeseen problems, so here's a +# convenient off switch. +use_celementree = True + +try: + if not use_celementree: + raise ImportError() + # Python 2.3 and 2.4. + from cElementTree import * + ElementTreeError = SyntaxError +except ImportError: + try: + if not use_celementree: + raise ImportError() + # Python 2.5 and above. + from xml.etree.cElementTree import * + ElementTreeError = SyntaxError + except ImportError: + # Pure Python code. + try: + # Python 2.3 and 2.4. + from elementtree.ElementTree import * + except ImportError: + # Python 2.5 and above. + from xml.etree.ElementTree import * + + # The pure Python ElementTree module uses Expat for parsing. + from xml.parsers.expat import ExpatError as ElementTreeError |