| 1 | #!/usr/bin/python
|
|---|
| 2 | #############################################################
|
|---|
| 3 | # tdbutil
|
|---|
| 4 | #
|
|---|
| 5 | # Purpose:
|
|---|
| 6 | # Contains functions that are used to pack and unpack data
|
|---|
| 7 | # from Samba's tdb databases. Samba sometimes represents complex
|
|---|
| 8 | # data structures as a single value in a database. These functions
|
|---|
| 9 | # allow other python scripts to package data types into a single python
|
|---|
| 10 | # string and unpackage them.
|
|---|
| 11 | #
|
|---|
| 12 | #
|
|---|
| 13 | # XXXXX: This code is no longer used; it's just here for testing
|
|---|
| 14 | # compatibility with the new (much faster) C implementation.
|
|---|
| 15 | #
|
|---|
| 16 | ##############################################################
|
|---|
| 17 | import string
|
|---|
| 18 |
|
|---|
| 19 | def pack(format,list):
|
|---|
| 20 | retstring = ''
|
|---|
| 21 | listind = 0
|
|---|
| 22 |
|
|---|
| 23 | # Cycle through format entries
|
|---|
| 24 | for type in format:
|
|---|
| 25 | # Null Terminated String
|
|---|
| 26 | if (type == 'f' or type == 'P'):
|
|---|
| 27 | retstring = retstring + list[listind] + "\000"
|
|---|
| 28 | # 4 Byte Number
|
|---|
| 29 | if (type == 'd'):
|
|---|
| 30 | retstring = retstring + PackNum(list[listind],4)
|
|---|
| 31 | # 2 Byte Number
|
|---|
| 32 | if (type == 'w'):
|
|---|
| 33 | retstring = retstring + PackNum(list[listind],2)
|
|---|
| 34 | # Pointer Value
|
|---|
| 35 | if (type == 'p'):
|
|---|
| 36 | if (list[listind]):
|
|---|
| 37 | retstring = retstring + PackNum(1,4)
|
|---|
| 38 | else:
|
|---|
| 39 | retstring = retstring + PackNum(0,4)
|
|---|
| 40 | # Buffer and Length
|
|---|
| 41 | if (type == 'B'):
|
|---|
| 42 | # length
|
|---|
| 43 | length = list[listind]
|
|---|
| 44 | retstring = retstring + PackNum(length,4)
|
|---|
| 45 | length = int(length)
|
|---|
| 46 | listind = listind + 1
|
|---|
| 47 | # buffer
|
|---|
| 48 | retstring = retstring + list[listind][:length]
|
|---|
| 49 |
|
|---|
| 50 | listind = listind + 1
|
|---|
| 51 |
|
|---|
| 52 | return retstring
|
|---|
| 53 |
|
|---|
| 54 | def unpack(format,buffer):
|
|---|
| 55 | retlist = []
|
|---|
| 56 | bufind = 0
|
|---|
| 57 |
|
|---|
| 58 | lasttype = ""
|
|---|
| 59 | for type in format:
|
|---|
| 60 | # Pointer Value
|
|---|
| 61 | if (type == 'p'):
|
|---|
| 62 | newvalue = UnpackNum(buffer[bufind:bufind+4])
|
|---|
| 63 | bufind = bufind + 4
|
|---|
| 64 | if (newvalue):
|
|---|
| 65 | newvalue = 1L
|
|---|
| 66 | else:
|
|---|
| 67 | newvalue = 0L
|
|---|
| 68 | retlist.append(newvalue)
|
|---|
| 69 | # Previous character till end of data
|
|---|
| 70 | elif (type == '$'):
|
|---|
| 71 | if (lasttype == 'f'):
|
|---|
| 72 | while (bufind < len(buffer)):
|
|---|
| 73 | newstring = ''
|
|---|
| 74 | while (buffer[bufind] != '\000'):
|
|---|
| 75 | newstring = newstring + buffer[bufind]
|
|---|
| 76 | bufind = bufind + 1
|
|---|
| 77 | bufind = bufind + 1
|
|---|
| 78 | retlist.append(newstring)
|
|---|
| 79 | # Null Terminated String
|
|---|
| 80 | elif (type == 'f' or type == 'P'):
|
|---|
| 81 | newstring = ''
|
|---|
| 82 | while (buffer[bufind] != '\000'):
|
|---|
| 83 | newstring = newstring + buffer[bufind]
|
|---|
| 84 | bufind = bufind + 1
|
|---|
| 85 | bufind = bufind + 1
|
|---|
| 86 | retlist.append(newstring)
|
|---|
| 87 | # 4 Byte Number
|
|---|
| 88 | elif (type == 'd'):
|
|---|
| 89 | newvalue = UnpackNum(buffer[bufind:bufind+4])
|
|---|
| 90 | bufind = bufind + 4
|
|---|
| 91 | retlist.append(newvalue)
|
|---|
| 92 | # 2 Byte Number
|
|---|
| 93 | elif (type == 'w'):
|
|---|
| 94 | newvalue = UnpackNum(buffer[bufind:bufind+2])
|
|---|
| 95 | bufind = bufind + 2
|
|---|
| 96 | retlist.append(newvalue)
|
|---|
| 97 | # Length and Buffer
|
|---|
| 98 | elif (type == 'B'):
|
|---|
| 99 | # Length
|
|---|
| 100 | length = UnpackNum(buffer[bufind:bufind+4])
|
|---|
| 101 | bufind = bufind + 4
|
|---|
| 102 | retlist.append(length)
|
|---|
| 103 | length = int(length)
|
|---|
| 104 | # Buffer
|
|---|
| 105 | retlist.append(buffer[bufind:bufind+length])
|
|---|
| 106 | bufind = bufind + length
|
|---|
| 107 |
|
|---|
| 108 | lasttype = type
|
|---|
| 109 |
|
|---|
| 110 | return ((retlist,buffer[bufind:]))
|
|---|
| 111 |
|
|---|
| 112 | def PackNum(myint,size):
|
|---|
| 113 | retstring = ''
|
|---|
| 114 | size = size * 2
|
|---|
| 115 | hint = hex(myint)[2:]
|
|---|
| 116 |
|
|---|
| 117 | # Check for long notation
|
|---|
| 118 | if (hint[-1:] == 'L'):
|
|---|
| 119 | hint = hint[:-1]
|
|---|
| 120 |
|
|---|
| 121 | addon = size - len(hint)
|
|---|
| 122 | for i in range(0,addon):
|
|---|
| 123 | hint = '0' + hint
|
|---|
| 124 |
|
|---|
| 125 | while (size > 0):
|
|---|
| 126 | val = string.atoi(hint[size-2:size],16)
|
|---|
| 127 | retstring = retstring + chr(val)
|
|---|
| 128 | size = size - 2
|
|---|
| 129 |
|
|---|
| 130 | return retstring
|
|---|
| 131 |
|
|---|
| 132 | def UnpackNum(buffer):
|
|---|
| 133 | size = len(buffer)
|
|---|
| 134 | mystring = ''
|
|---|
| 135 |
|
|---|
| 136 | for i in range(size-1,-1,-1):
|
|---|
| 137 | val = hex(ord(buffer[i]))[2:]
|
|---|
| 138 | if (len(val) == 1):
|
|---|
| 139 | val = '0' + val
|
|---|
| 140 | mystring = mystring + val
|
|---|
| 141 | if (len(mystring) > 4):
|
|---|
| 142 | return string.atol(mystring,16)
|
|---|
| 143 | else:
|
|---|
| 144 | return string.atoi(mystring,16)
|
|---|