hydrus/include/HydrusSerialisable.py

461 lines
14 KiB
Python
Raw Normal View History

2015-04-22 22:57:25 +00:00
import json
2017-01-25 22:56:55 +00:00
import zlib
2015-04-22 22:57:25 +00:00
2018-01-17 22:52:10 +00:00
LZ4_OK = False
try:
2018-08-22 21:10:59 +00:00
import lz4
2018-01-17 22:52:10 +00:00
import lz4.block
LZ4_OK = True
2018-07-18 21:07:15 +00:00
except: # ImportError wasn't enough here as Linux went up the shoot with a __version__ doesn't exist bs
2018-01-17 22:52:10 +00:00
2018-10-24 21:34:02 +00:00
print( 'Could not import lz4--nbd.' )
2018-01-17 22:52:10 +00:00
2015-04-22 22:57:25 +00:00
SERIALISABLE_TYPE_BASE = 0
SERIALISABLE_TYPE_BASE_NAMED = 1
2019-06-05 19:42:39 +00:00
SERIALISABLE_TYPE_SHORTCUT_SET = 2
2015-05-13 20:22:39 +00:00
SERIALISABLE_TYPE_SUBSCRIPTION = 3
SERIALISABLE_TYPE_PERIODIC = 4
2015-10-07 21:56:22 +00:00
SERIALISABLE_TYPE_GALLERY_IDENTIFIER = 5
2017-09-20 19:47:31 +00:00
SERIALISABLE_TYPE_TAG_IMPORT_OPTIONS = 6
SERIALISABLE_TYPE_FILE_IMPORT_OPTIONS = 7
2018-06-27 19:27:05 +00:00
SERIALISABLE_TYPE_FILE_SEED_CACHE = 8
2015-05-20 21:31:40 +00:00
SERIALISABLE_TYPE_HDD_IMPORT = 9
2015-06-03 21:05:13 +00:00
SERIALISABLE_TYPE_SERVER_TO_CLIENT_CONTENT_UPDATE_PACKAGE = 10
SERIALISABLE_TYPE_SERVER_TO_CLIENT_SERVICE_UPDATE_PACKAGE = 11
2015-06-17 20:01:41 +00:00
SERIALISABLE_TYPE_MANAGEMENT_CONTROLLER = 12
2015-06-24 22:10:14 +00:00
SERIALISABLE_TYPE_GUI_SESSION = 13
SERIALISABLE_TYPE_PREDICATE = 14
SERIALISABLE_TYPE_FILE_SEARCH_CONTEXT = 15
SERIALISABLE_TYPE_EXPORT_FOLDER = 16
2018-05-23 21:05:06 +00:00
SERIALISABLE_TYPE_WATCHER_IMPORT = 17
2018-04-05 01:22:26 +00:00
SERIALISABLE_TYPE_SIMPLE_DOWNLOADER_IMPORT = 18
2015-09-09 22:04:39 +00:00
SERIALISABLE_TYPE_IMPORT_FOLDER = 19
2018-07-18 21:07:15 +00:00
SERIALISABLE_TYPE_MULTIPLE_GALLERY_IMPORT = 20
2015-10-07 21:56:22 +00:00
SERIALISABLE_TYPE_DICTIONARY = 21
SERIALISABLE_TYPE_CLIENT_OPTIONS = 22
2015-10-14 21:02:25 +00:00
SERIALISABLE_TYPE_CONTENT = 23
2017-03-02 02:14:56 +00:00
SERIALISABLE_TYPE_PETITION = 24
2015-10-14 21:02:25 +00:00
SERIALISABLE_TYPE_ACCOUNT_IDENTIFIER = 25
SERIALISABLE_TYPE_LIST = 26
2016-09-21 19:54:04 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_HTML = 27
2016-09-07 20:01:05 +00:00
SERIALISABLE_TYPE_URLS_IMPORT = 28
2016-10-05 20:22:40 +00:00
SERIALISABLE_TYPE_PARSE_NODE_CONTENT_LINK = 29
2017-12-13 22:33:07 +00:00
SERIALISABLE_TYPE_CONTENT_PARSER = 30
2016-09-21 19:54:04 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_JSON = 31
2016-10-05 20:22:40 +00:00
SERIALISABLE_TYPE_PARSE_ROOT_FILE_LOOKUP = 32
2017-03-02 02:14:56 +00:00
SERIALISABLE_TYPE_BYTES_DICT = 33
SERIALISABLE_TYPE_CONTENT_UPDATE = 34
SERIALISABLE_TYPE_CREDENTIALS = 35
SERIALISABLE_TYPE_DEFINITIONS_UPDATE = 36
SERIALISABLE_TYPE_METADATA = 37
SERIALISABLE_TYPE_BANDWIDTH_RULES = 38
SERIALISABLE_TYPE_BANDWIDTH_TRACKER = 39
SERIALISABLE_TYPE_CLIENT_TO_SERVER_UPDATE = 40
2017-04-12 21:46:46 +00:00
SERIALISABLE_TYPE_SHORTCUT = 41
SERIALISABLE_TYPE_APPLICATION_COMMAND = 42
2017-04-26 21:58:12 +00:00
SERIALISABLE_TYPE_DUPLICATE_ACTION_OPTIONS = 43
2018-04-25 22:07:52 +00:00
SERIALISABLE_TYPE_TAG_FILTER = 44
2017-07-05 21:09:28 +00:00
SERIALISABLE_TYPE_NETWORK_BANDWIDTH_MANAGER = 45
2017-06-28 20:23:21 +00:00
SERIALISABLE_TYPE_NETWORK_SESSION_MANAGER = 46
SERIALISABLE_TYPE_NETWORK_CONTEXT = 47
SERIALISABLE_TYPE_NETWORK_LOGIN_MANAGER = 48
2017-08-09 21:33:51 +00:00
SERIALISABLE_TYPE_MEDIA_SORT = 49
2019-05-08 21:06:42 +00:00
SERIALISABLE_TYPE_URL_CLASS = 50
2017-09-27 21:52:54 +00:00
SERIALISABLE_TYPE_STRING_MATCH = 51
2017-11-08 22:07:12 +00:00
SERIALISABLE_TYPE_CHECKER_OPTIONS = 52
2017-10-04 17:51:58 +00:00
SERIALISABLE_TYPE_NETWORK_DOMAIN_MANAGER = 53
2017-11-08 22:07:12 +00:00
SERIALISABLE_TYPE_SUBSCRIPTION_QUERY = 54
2017-11-15 22:35:49 +00:00
SERIALISABLE_TYPE_STRING_CONVERTER = 55
SERIALISABLE_TYPE_FILENAME_TAGGING_OPTIONS = 56
2018-06-27 19:27:05 +00:00
SERIALISABLE_TYPE_FILE_SEED = 57
2017-12-13 22:33:07 +00:00
SERIALISABLE_TYPE_PAGE_PARSER = 58
2018-01-31 22:58:15 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_COMPOUND = 59
2018-02-07 23:40:33 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_CONTEXT_VARIABLE = 60
2018-02-21 21:59:37 +00:00
SERIALISABLE_TYPE_TAG_SUMMARY_GENERATOR = 61
2018-04-11 22:30:40 +00:00
SERIALISABLE_TYPE_PARSE_RULE_HTML = 62
SERIALISABLE_TYPE_SIMPLE_DOWNLOADER_PARSE_FORMULA = 63
2018-05-16 20:09:50 +00:00
SERIALISABLE_TYPE_MULTIPLE_WATCHER_IMPORT = 64
2018-06-27 19:27:05 +00:00
SERIALISABLE_TYPE_SERVICE_TAG_IMPORT_OPTIONS = 65
SERIALISABLE_TYPE_GALLERY_SEED = 66
SERIALISABLE_TYPE_GALLERY_SEED_LOG = 67
2018-07-18 21:07:15 +00:00
SERIALISABLE_TYPE_GALLERY_IMPORT = 68
2018-08-22 21:10:59 +00:00
SERIALISABLE_TYPE_GALLERY_URL_GENERATOR = 69
SERIALISABLE_TYPE_NESTED_GALLERY_URL_GENERATOR = 70
2018-10-03 21:00:15 +00:00
SERIALISABLE_TYPE_DOMAIN_METADATA_PACKAGE = 71
2018-10-17 21:00:09 +00:00
SERIALISABLE_TYPE_LOGIN_CREDENTIAL_DEFINITION = 72
SERIALISABLE_TYPE_LOGIN_SCRIPT_DOMAIN = 73
SERIALISABLE_TYPE_LOGIN_STEP = 74
2019-01-23 22:19:16 +00:00
SERIALISABLE_TYPE_CLIENT_API_MANAGER = 75
SERIALISABLE_TYPE_CLIENT_API_PERMISSIONS = 76
2019-02-27 23:03:30 +00:00
SERIALISABLE_TYPE_SERVICE_KEYS_TO_TAGS = 77
2019-08-21 21:34:01 +00:00
SERIALISABLE_TYPE_MEDIA_COLLECT = 78
2015-04-22 22:57:25 +00:00
SERIALISABLE_TYPES_TO_OBJECT_TYPES = {}
2019-01-09 22:59:03 +00:00
def CreateFromNetworkBytes( network_string ):
2015-05-13 20:22:39 +00:00
2017-01-25 22:56:55 +00:00
try:
2019-01-09 22:59:03 +00:00
obj_bytes = zlib.decompress( network_string )
2017-01-25 22:56:55 +00:00
except zlib.error:
2018-01-17 22:52:10 +00:00
if LZ4_OK:
2019-01-09 22:59:03 +00:00
obj_bytes = lz4.block.decompress( network_string )
2018-01-17 22:52:10 +00:00
else:
raise
2017-01-25 22:56:55 +00:00
2015-06-03 21:05:13 +00:00
2019-01-09 22:59:03 +00:00
obj_string = str( obj_bytes, 'utf-8' )
2015-06-03 21:05:13 +00:00
return CreateFromString( obj_string )
def CreateFromString( obj_string ):
obj_tuple = json.loads( obj_string )
2015-06-24 22:10:14 +00:00
return CreateFromSerialisableTuple( obj_tuple )
2015-06-03 21:05:13 +00:00
2015-06-24 22:10:14 +00:00
def CreateFromSerialisableTuple( obj_tuple ):
2015-06-03 21:05:13 +00:00
if len( obj_tuple ) == 3:
2015-06-24 22:10:14 +00:00
( serialisable_type, version, serialisable_info ) = obj_tuple
2015-06-03 21:05:13 +00:00
obj = SERIALISABLE_TYPES_TO_OBJECT_TYPES[ serialisable_type ]()
else:
2015-06-24 22:10:14 +00:00
( serialisable_type, name, version, serialisable_info ) = obj_tuple
2015-06-03 21:05:13 +00:00
obj = SERIALISABLE_TYPES_TO_OBJECT_TYPES[ serialisable_type ]( name )
2015-05-13 20:22:39 +00:00
2015-06-24 22:10:14 +00:00
obj.InitialiseFromSerialisableInfo( version, serialisable_info )
2015-05-13 20:22:39 +00:00
return obj
2015-06-03 21:05:13 +00:00
2018-04-11 22:30:40 +00:00
def GetNonDupeName( original_name, disallowed_names ):
i = 1
non_dupe_name = original_name
while non_dupe_name in disallowed_names:
non_dupe_name = original_name + ' (' + str( i ) + ')'
i += 1
return non_dupe_name
def SetNonDupeName( obj, disallowed_names ):
non_dupe_name = GetNonDupeName( obj.GetName(), disallowed_names )
obj.SetName( non_dupe_name )
2015-04-22 22:57:25 +00:00
class SerialisableBase( object ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BASE
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Base Serialisable Object'
2015-06-03 21:05:13 +00:00
SERIALISABLE_VERSION = 1
2015-04-22 22:57:25 +00:00
def _GetSerialisableInfo( self ):
raise NotImplementedError()
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
raise NotImplementedError()
2015-07-22 19:40:39 +00:00
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
2015-04-22 22:57:25 +00:00
2015-07-22 19:40:39 +00:00
return old_serialisable_info
2015-04-22 22:57:25 +00:00
2016-07-20 19:57:10 +00:00
2019-01-09 22:59:03 +00:00
def DumpToNetworkBytes( self ):
2015-10-14 21:02:25 +00:00
obj_string = self.DumpToString()
2019-01-09 22:59:03 +00:00
obj_bytes = bytes( obj_string, 'utf-8' )
return zlib.compress( obj_bytes, 9 )
2015-10-14 21:02:25 +00:00
2015-04-22 22:57:25 +00:00
2015-10-14 21:02:25 +00:00
def DumpToString( self ):
2015-04-22 22:57:25 +00:00
2015-10-14 21:02:25 +00:00
obj_tuple = self.GetSerialisableTuple()
2015-04-22 22:57:25 +00:00
2015-10-14 21:02:25 +00:00
return json.dumps( obj_tuple )
2015-04-22 22:57:25 +00:00
2016-10-05 20:22:40 +00:00
def Duplicate( self ):
return CreateFromString( self.DumpToString() )
2015-10-14 21:02:25 +00:00
def GetSerialisableTuple( self ):
2015-04-22 22:57:25 +00:00
2019-02-06 22:41:35 +00:00
if hasattr( self, '_lock' ):
with getattr( self, '_lock' ):
serialisable_info = self._GetSerialisableInfo()
else:
serialisable_info = self._GetSerialisableInfo()
return ( self.SERIALISABLE_TYPE, self.SERIALISABLE_VERSION, serialisable_info )
2015-05-13 20:22:39 +00:00
2015-06-24 22:10:14 +00:00
def InitialiseFromSerialisableInfo( self, version, serialisable_info ):
2015-04-22 22:57:25 +00:00
2015-07-22 19:40:39 +00:00
while version < self.SERIALISABLE_VERSION:
2015-04-22 22:57:25 +00:00
2015-07-22 19:40:39 +00:00
( version, serialisable_info ) = self._UpdateSerialisableInfo( version, serialisable_info )
2015-04-22 22:57:25 +00:00
self._InitialiseFromSerialisableInfo( serialisable_info )
class SerialisableBaseNamed( SerialisableBase ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BASE_NAMED
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Named Base Serialisable Object'
2015-04-22 22:57:25 +00:00
def __init__( self, name ):
SerialisableBase.__init__( self )
self._name = name
2015-10-14 21:02:25 +00:00
def GetSerialisableTuple( self ):
return ( self.SERIALISABLE_TYPE, self._name, self.SERIALISABLE_VERSION, self._GetSerialisableInfo() )
2016-07-20 19:57:10 +00:00
2015-04-22 22:57:25 +00:00
def GetName( self ): return self._name
def SetName( self, name ): self._name = name
2015-10-07 21:56:22 +00:00
2017-08-09 21:33:51 +00:00
def SetNonDupeName( self, disallowed_names ):
2018-04-11 22:30:40 +00:00
self._name = GetNonDupeName( self._name, disallowed_names )
2017-08-09 21:33:51 +00:00
2015-10-07 21:56:22 +00:00
class SerialisableDictionary( SerialisableBase, dict ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_DICTIONARY
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Serialisable Dictionary'
2015-10-07 21:56:22 +00:00
SERIALISABLE_VERSION = 1
def __init__( self, *args, **kwargs ):
dict.__init__( self, *args, **kwargs )
SerialisableBase.__init__( self )
def _GetSerialisableInfo( self ):
simple_key_simple_value_pairs = []
simple_key_serialisable_value_pairs = []
serialisable_key_simple_value_pairs = []
serialisable_key_serialisable_value_pairs = []
2019-01-09 22:59:03 +00:00
for ( key, value ) in list(self.items()):
2015-10-07 21:56:22 +00:00
if isinstance( key, SerialisableBase ):
2015-10-14 21:02:25 +00:00
serialisable_key = key.GetSerialisableTuple()
2015-10-07 21:56:22 +00:00
if isinstance( value, SerialisableBase ):
2015-10-14 21:02:25 +00:00
serialisable_value = value.GetSerialisableTuple()
2015-10-07 21:56:22 +00:00
serialisable_key_serialisable_value_pairs.append( ( serialisable_key, serialisable_value ) )
else:
serialisable_value = value
serialisable_key_simple_value_pairs.append( ( serialisable_key, serialisable_value ) )
else:
serialisable_key = key
if isinstance( value, SerialisableBase ):
2015-10-14 21:02:25 +00:00
serialisable_value = value.GetSerialisableTuple()
2015-10-07 21:56:22 +00:00
simple_key_serialisable_value_pairs.append( ( serialisable_key, serialisable_value ) )
else:
serialisable_value = value
simple_key_simple_value_pairs.append( ( serialisable_key, serialisable_value ) )
return ( simple_key_simple_value_pairs, simple_key_serialisable_value_pairs, serialisable_key_simple_value_pairs, serialisable_key_serialisable_value_pairs )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
( simple_key_simple_value_pairs, simple_key_serialisable_value_pairs, serialisable_key_simple_value_pairs, serialisable_key_serialisable_value_pairs ) = serialisable_info
for ( key, value ) in simple_key_simple_value_pairs:
self[ key ] = value
for ( key, serialisable_value ) in simple_key_serialisable_value_pairs:
value = CreateFromSerialisableTuple( serialisable_value )
self[ key ] = value
for ( serialisable_key, value ) in serialisable_key_simple_value_pairs:
key = CreateFromSerialisableTuple( serialisable_key )
self[ key ] = value
for ( serialisable_key, serialisable_value ) in serialisable_key_serialisable_value_pairs:
key = CreateFromSerialisableTuple( serialisable_key )
value = CreateFromSerialisableTuple( serialisable_value )
self[ key ] = value
2015-10-14 21:02:25 +00:00
SERIALISABLE_TYPES_TO_OBJECT_TYPES[ SERIALISABLE_TYPE_DICTIONARY ] = SerialisableDictionary
2017-03-02 02:14:56 +00:00
class SerialisableBytesDictionary( SerialisableBase, dict ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BYTES_DICT
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Serialisable Dictionary With Bytestring Key/Value Support'
2017-03-02 02:14:56 +00:00
SERIALISABLE_VERSION = 1
def __init__( self, *args, **kwargs ):
dict.__init__( self, *args, **kwargs )
SerialisableBase.__init__( self )
def _GetSerialisableInfo( self ):
pairs = []
2019-01-09 22:59:03 +00:00
for ( key, value ) in list(self.items()):
2017-03-02 02:14:56 +00:00
2017-03-15 20:13:04 +00:00
if isinstance( key, int ):
encoded_key = key
else:
2019-01-09 22:59:03 +00:00
encoded_key = key.hex()
2017-03-15 20:13:04 +00:00
2017-03-02 02:14:56 +00:00
if isinstance( value, ( list, tuple, set ) ):
2019-01-09 22:59:03 +00:00
encoded_value = [ item.hex() for item in value ]
2017-03-02 02:14:56 +00:00
2017-12-06 22:06:56 +00:00
elif value is None:
encoded_value = value
2017-03-02 02:14:56 +00:00
else:
2019-01-09 22:59:03 +00:00
encoded_value = value.hex()
2017-03-02 02:14:56 +00:00
pairs.append( ( encoded_key, encoded_value ) )
return pairs
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
for ( encoded_key, encoded_value ) in serialisable_info:
2017-03-15 20:13:04 +00:00
if isinstance( encoded_key, int ):
key = encoded_key
else:
2019-01-09 22:59:03 +00:00
key = bytes.fromhex( encoded_key )
2017-03-15 20:13:04 +00:00
2017-03-02 02:14:56 +00:00
if isinstance( encoded_value, ( list, tuple, set ) ):
2019-01-09 22:59:03 +00:00
value = [ bytes.fromhex( encoded_item ) for encoded_item in encoded_value ]
2017-03-02 02:14:56 +00:00
2017-12-06 22:06:56 +00:00
elif encoded_value is None:
value = encoded_value
2017-03-02 02:14:56 +00:00
else:
2019-01-09 22:59:03 +00:00
value = bytes.fromhex( encoded_value )
2017-03-02 02:14:56 +00:00
self[ key ] = value
SERIALISABLE_TYPES_TO_OBJECT_TYPES[ SERIALISABLE_TYPE_BYTES_DICT ] = SerialisableBytesDictionary
2015-10-14 21:02:25 +00:00
class SerialisableList( SerialisableBase, list ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_LIST
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Serialisable List'
2015-10-14 21:02:25 +00:00
SERIALISABLE_VERSION = 1
def __init__( self, *args, **kwargs ):
list.__init__( self, *args, **kwargs )
SerialisableBase.__init__( self )
def _GetSerialisableInfo( self ):
return [ obj.GetSerialisableTuple() for obj in self ]
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
for obj_tuple in serialisable_info:
self.append( CreateFromSerialisableTuple( obj_tuple ) )
2017-01-25 22:56:55 +00:00
SERIALISABLE_TYPES_TO_OBJECT_TYPES[ SERIALISABLE_TYPE_LIST ] = SerialisableList