def parse_column(self, packet): """Parse a MySQL column-packet""" column = {} (packet, column['catalog']) = utils.read_lc_string(packet[4:]) (packet, column['db']) = utils.read_lc_string(packet) (packet, column['table']) = utils.read_lc_string(packet) (packet, column['org_table']) = utils.read_lc_string(packet) (packet, column['name']) = utils.read_lc_string(packet) (packet, column['org_name']) = utils.read_lc_string(packet) packet = packet[1:] # filler 1 * \x00 (packet, column['charset']) = utils.read_int(packet, 2) (packet, column['length']) = utils.read_int(packet, 4) (packet, column['type']) = utils.read_int(packet, 1) (packet, column['flags']) = utils.read_int(packet, 2) (packet, column['decimal']) = utils.read_int(packet, 1) packet = packet[2:] # filler 2 * \x00 return ( column['name'], column['type'], None, # display_size None, # internal_size None, # precision None, # scale ~column['flags'] & FieldFlag.NOT_NULL, # null_ok column['flags'], # MySQL specific )
def parse_eof(self, packet): """Parse a MySQL EOF-packet""" res = {} packet = packet[1:] # disregard the first checking byte (packet, res['warning_count']) = utils.read_int(packet[4:], 2) (packet, res['status_flag']) = utils.read_int(packet, 2) return res
def parse_column(self, packet): """Parse a MySQL column-packet""" column = {} (packet, column['catalog']) = utils.read_lc_string(packet[4:]) (packet, column['db']) = utils.read_lc_string(packet) (packet, column['table']) = utils.read_lc_string(packet) (packet, column['org_table']) = utils.read_lc_string(packet) (packet, column['name']) = utils.read_lc_string(packet) (packet, column['org_name']) = utils.read_lc_string(packet) packet = packet[1:] # filler 1 * \x00 (packet, column['charset']) = utils.read_int(packet, 2) (packet, column['length']) = utils.read_int(packet,4) (packet, column['type']) = utils.read_int(packet, 1) (packet, column['flags']) = utils.read_int(packet, 2) (packet, column['decimal']) = utils.read_int(packet, 1) packet = packet[2:] # filler 2 * \x00 return ( column['name'].decode('utf-8'), column['type'], None, # display_size None, # internal_size None, # precision None, # scale ~column['flags'] & FieldFlag.NOT_NULL, # null_ok column['flags'], # MySQL specific )
def test_read_int(self): """Read an integer from a buffer.""" buf = b'34581adbkdasdf' self.assertEqual(51, utils.read_int(buf, 1)[1]) self.assertEqual(13363, utils.read_int(buf, 2)[1]) self.assertEqual(3486771, utils.read_int(buf, 3)[1]) self.assertEqual(943010867, utils.read_int(buf, 4)[1]) self.assertEqual(7089898577412305971, utils.read_int(buf, 8)[1])
def test_read_int(self): """Read an integer from a buffer.""" buf = '34581adbkdasdf' self.assertEqual(51, utils.read_int(buf,1)[1]) self.assertEqual(13363, utils.read_int(buf,2)[1]) self.assertEqual(3486771, utils.read_int(buf,3)[1]) self.assertEqual(943010867, utils.read_int(buf,4)[1]) self.assertEqual(7089898577412305971, utils.read_int(buf,8)[1])
def parse_eof(self, packet): """Parse a MySQL EOF-packet""" if not (packet[4] == '\xfe' and len(packet) <= 9): raise errors.InterfaceError("Failed parsing EOF packet.") res = {} packet = packet[5:] # disregard the first checking byte (packet, res['warning_count']) = utils.read_int(packet, 2) (packet, res['status_flag']) = utils.read_int(packet, 2) return res
def __init__(self, column_type, column_schema, buf): self.type = column_type self.name = column_schema["COLUMN_NAME"] self.collation_name = column_schema["COLLATION_NAME"] self.character_set_name = column_schema["CHARACTER_SET_NAME"] self.comment = column_schema["COLUMN_COMMENT"] self.unsigned = False head = buf if column_schema["COLUMN_TYPE"].find("unsigned") != -1: self.unsigned = True if self.type == FieldType.VAR_STRING or self.type == FieldType.STRING: self.__read_string_metadata(packet, column_schema) elif self.type == FieldType.VARCHAR: head, self.max_length = utils.read_int(head, 2) elif self.type == FieldType.BLOB: head, self.length_size = utils.read_int(head, 1) elif self.type == FieldType.GEOMETRY: head, self.length_size = utils.read_int(head, 1) elif self.type == FieldType.NEWDECIMAL: head, self.precision = utils.read_int(head, 1) head, self.decimals = utils.read_int(head, 1) elif self.type == FieldType.DOUBLE: head, self.size = utils.read_int(head, 1) elif self.type == FieldType.FLOAT: head, self.size = utils.read_int(head, 1) elif self.type == FieldType.BIT: head, bits = utils.read_int(head, 1) head, bytes = utils.read_int(head, 1) self.bits = (bytes * 8) + bits self.bytes = int((self.bits + 7) / 8)
def __read_string_metadata(self, head, column_schema): head, byte0 = utils.read_int(head, 1) head, byte1 = utils.read_int(head, 1) metadata = (byte0 << 8) + byte1 real_type = metadata >> 8 if real_type == FieldType.SET or real_type == FieldType.ENUM: self.type = real_type self.size = metadata & 0x00ff self.__read_enum_metadata(column_schema) else: self.max_length = (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff)
def __read_string_metadata(self, head, column_schema): head, byte0 = utils.read_int(head, 1) head, byte1 = utils.read_int(head, 1) metadata = (byte0 << 8) + byte1 real_type = metadata >> 8 if real_type == FieldType.SET or real_type == FieldType.ENUM: self.type = real_type self.size = metadata & 0x00ff self.__read_enum_metadata(column_schema) else: self.max_length = (( (metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff)
def parse_handshake(self, packet): """Parse a MySQL Handshake-packet""" res = {} (packet, res["protocol"]) = utils.read_int(packet[4:], 1) (packet, res["server_version_original"]) = utils.read_string(packet, end=b"\x00") (packet, res["server_threadid"]) = utils.read_int(packet, 4) (packet, res["scramble"]) = utils.read_bytes(packet, 8) packet = packet[1:] # Filler 1 * \x00 (packet, res["capabilities"]) = utils.read_int(packet, 2) (packet, res["charset"]) = utils.read_int(packet, 1) (packet, res["server_status"]) = utils.read_int(packet, 2) packet = packet[13:] # Filler 13 * \x00 (packet, scramble_next) = utils.read_bytes(packet, 12) res["scramble"] += scramble_next return res
def parse_binary_prepare_ok(self, packet): """Parse a MySQL Binary Protocol OK packet""" if not packet[4] == 0: raise errors.InterfaceError("Failed parsing Binary OK packet") ok_pkt = {} try: (packet, ok_pkt['statement_id']) = utils.read_int(packet[5:], 4) (packet, ok_pkt['num_columns']) = utils.read_int(packet, 2) (packet, ok_pkt['num_params']) = utils.read_int(packet, 2) packet = packet[1:] # Filler 1 * \x00 (packet, ok_pkt['warning_count']) = utils.read_int(packet, 2) except ValueError: raise errors.InterfaceError("Failed parsing Binary OK packet") return ok_pkt
def parse_handshake(self, packet): """Parse a MySQL Handshake-packet""" res = {} (packet, res['protocol']) = utils.read_int(packet[4:], 1) (packet, res['server_version_original']) = utils.read_string( packet, end='\x00') (packet, res['server_threadid']) = utils.read_int(packet, 4) (packet, res['scramble']) = utils.read_bytes(packet, 8) packet = packet[1:] # Filler 1 * \x00 (packet, res['capabilities']) = utils.read_int(packet, 2) (packet, res['charset']) = utils.read_int(packet, 1) (packet, res['server_status']) = utils.read_int(packet, 2) packet = packet[13:] # Filler 13 * \x00 (packet, scramble_next) = utils.read_bytes(packet, 12) res['scramble'] += scramble_next return res
def get_exception(packet): """Returns an exception object based on the MySQL error Returns an exception object based on the MySQL error in the given packet. Returns an Error-Object. """ errno = errmsg = None if packet[4] != '\xff': raise ValueError("Packet is not an error packet") sqlstate = None try: packet = packet[5:] (packet, errno) = utils.read_int(packet, 2) if packet[0] != '\x23': # Error without SQLState errmsg = packet.decode('utf8') else: (packet, sqlstate) = utils.read_bytes(packet[1:], 5) sqlstate = sqlstate.decode('utf8') errmsg = packet.decode('utf8') except StandardError as err: return InterfaceError("Failed getting Error information (%r)" % err) else: return get_mysql_exception(errno, errmsg, sqlstate)
def parse_binary_prepare_ok(self, packet): """Parse a MySQL Binary Protocol OK packet""" if not packet[4] == '\x00': raise errors.InterfaceError("Failed parsing Binary OK packet") ok_packet = {} try: (packet, ok_packet['statement_id']) = utils.read_int(packet[5:], 4) (packet, ok_packet['num_columns']) = utils.read_int(packet, 2) (packet, ok_packet['num_params']) = utils.read_int(packet, 2) packet = packet[1:] # Filler 1 * \x00 (packet, ok_packet['warning_count']) = utils.read_int(packet, 2) except ValueError: raise errors.InterfaceError("Failed parsing Binary OK packet") return ok_packet
def parse_ok(self, packet): """Parse a MySQL OK-packet""" if not packet[4] == '\x00': raise errors.InterfaceError("Failed parsing OK packet.") ok = {} try: (packet, ok['field_count']) = utils.read_int(packet[4:], 1) (packet, ok['affected_rows']) = utils.read_lc_int(packet) (packet, ok['insert_id']) = utils.read_lc_int(packet) (packet, ok['server_status']) = utils.read_int(packet, 2) (packet, ok['warning_count']) = utils.read_int(packet, 2) if packet: (packet, ok['info_msg']) = utils.read_lc_string(packet) except ValueError: raise errors.InterfaceError("Failed parsing OK packet.") return ok