def _prepare_binary_timestamp(self, value):
        """Prepare a timestamp object for the MySQL binary protocol

        This method prepares a timestamp of type datetime.datetime or
        datetime.date for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        """
        if isinstance(value, datetime.datetime):
            field_type = FieldType.DATETIME
        elif isinstance(value, datetime.date):
            field_type = FieldType.DATE
        else:
            raise ValueError("Argument must a datetime.datetime or datetime.date")

        packed = utils.int2store(value.year) + utils.int1store(value.month) + utils.int1store(value.day)

        if isinstance(value, datetime.datetime):
            packed = (
                packed + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)
            )
            if value.microsecond > 0:
                packed += utils.int4store(value.microsecond)

        packed = utils.int1store(len(packed)) + packed
        return (packed, field_type)
Esempio n. 2
0
 def make_auth_ssl(self, charset=33, client_flags=0,
                   max_allowed_packet=1073741824):
     """Make a SSL authentication packet"""
     return utils.int4store(client_flags) +\
            utils.int4store(max_allowed_packet) +\
            utils.int1store(charset) +\
            b'\x00' * 23
Esempio n. 3
0
    def binlog_dump(self, log_file, offset):
        """
        COM_BINLOG_DUMP
        +=============================================+
        | packet header    |  packet length    0 : 3 |   
        |                  +-------------------------+   
        |                  |  sequence number  3 : 1 |
        +============================================+
        | command packet   |  command code     4 : 1 |    COM_BINLOG_DUMP
        |                  +------------------------―+
        |                  |  offset           5 : 4 |
        |                  +-------------------------+
        |                  |  flags            9 : 2 |
        |                  +-------------------------+
        |                  |  server id        11 : 4|
        |                  +-------------------------+
        |                  |  log name         15 : x|
        +============================================+
        """

        payload = ''
        payload += utils.int1store(ServerCmd.BINLOG_DUMP)
        payload += utils.int4store(offset)
        payload += utils.int2store(0)
        payload += utils.int4store(self.get_server_id())
        payload += log_file
        payload += '\x00'
        log.debug("len(payload) = %d" % len(payload))

        # send BIGLOGDUMP command and parse ok packet response.
        self._socket.send(payload, 0)
        ok_packet = self._socket.recv()
        parser = MySQLProtocol()
        ok_packet = parser.parse_ok(ok_packet)
        print ok_packet
Esempio n. 4
0
    def make_auth(
        self,
        seed,
        username=None,
        password=None,
        database=None,
        charset=33,
        client_flags=0,
        max_allowed_packet=1073741824,
    ):
        """Make a MySQL Authentication packet"""
        if not seed:
            raise errors.ProgrammingError("Seed missing")

        auth = self._prepare_auth(username, password, database, client_flags, seed)
        data = (
            utils.int4store(client_flags)
            + utils.int4store(max_allowed_packet)
            + utils.int1store(charset)
            + b"\x00" * 23
            + auth[0]
            + auth[1]
            + auth[2]
        )
        return data
Esempio n. 5
0
    def binlog_dump(self, log_file, offset):
        """
        COM_BINLOG_DUMP
        +=============================================+
        | packet header    |  packet length    0 : 3 |   
        |                  +-------------------------+   
        |                  |  sequence number  3 : 1 |
        +============================================+
        | command packet   |  command code     4 : 1 |    COM_BINLOG_DUMP
        |                  +------------------------―+
        |                  |  offset           5 : 4 |
        |                  +-------------------------+
        |                  |  flags            9 : 2 |
        |                  +-------------------------+
        |                  |  server id        11 : 4|
        |                  +-------------------------+
        |                  |  log name         15 : x|
        +============================================+
        """

        payload = ""
        payload += utils.int1store(ServerCmd.BINLOG_DUMP)
        payload += utils.int4store(offset)
        payload += utils.int2store(0)
        payload += utils.int4store(self.get_server_id())
        payload += log_file
        payload += "\x00"
        log.debug("len(payload) = %d" % len(payload))

        # send BIGLOGDUMP command and parse ok packet response.
        self._socket.send(payload, 0)
        ok_packet = self._socket.recv()
        parser = MySQLProtocol()
        ok_packet = parser.parse_ok(ok_packet)
        print ok_packet
Esempio n. 6
0
 def make_auth_ssl(self, charset=33, client_flags=0,
                   max_allowed_packet=1073741824):
     """Make a SSL authentication packet"""
     return utils.int4store(client_flags) + \
            utils.int4store(max_allowed_packet) + \
            utils.int1store(charset) + \
            '\x00' * 23
Esempio n. 7
0
    def make_change_user(self, seed, username=None, password=None, database=None, charset=33, client_flags=0):
        """Make a MySQL packet with the Change User command"""
        if not seed:
            raise errors.ProgrammingError("Seed missing")

        auth = self._prepare_auth(username, password, database, client_flags, seed)
        data = utils.int1store(ServerCmd.CHANGE_USER) + auth[0] + auth[1] + auth[2] + utils.int2store(charset)
        return data
Esempio n. 8
0
    def test_int1store(self):
        """Use int1store to pack an integer (2^8) as a string."""
        data = 2**(8 - 1)
        exp = struct.pack('<B', data)

        try:
            result = utils.int1store(data)
        except ValueError, e:
            self.fail("int1store failed: %s" % e)
Esempio n. 9
0
 def test_int1store(self):
     """Use int1store to pack an integer (2^8) as a string."""
     data = 2**(8-1)
     exp = struct.pack('<B',data)
     
     try:
         result = utils.int1store(data)
     except ValueError, e:
         self.fail("int1store failed: %s" % e)
Esempio n. 10
0
    def test_read_lc_string_1(self):
        """Read a length code string from a buffer ( <= 250 bytes)"""
        exp = b"a" * 2**(8 - 1)
        expsize = len(exp)
        lcs = utils.int1store(expsize) + exp

        (rest, result) = utils.read_lc_string(lcs)
        if result != exp or len(result) != expsize:
            self.fail("Wrong result. Expected '%d', got '%d'" %\
                expsize, len(result))
    def test_read_lc_string_1(self):
        """Read a length code string from a buffer ( <= 250 bytes)"""
        exp = bytearray(b"a" * 2 ** (8 - 1))
        expsize = len(exp)
        lcs = utils.int1store(expsize) + exp

        (_, result) = utils.read_lc_string(lcs)
        if result != exp or len(result) != expsize:
            self.fail("Wrong result. Expected '{0}', got '{1}'".format(
                expsize, len(result)))
Esempio n. 12
0
 def test_read_lc_string_1(self):
     """Read a length code string from a buffer ( <= 250 bytes)"""
     exp = "a" * 2**(8-1)
     expsize = len(exp)
     lcs = utils.int1store(expsize) + exp
     
     (rest, result) = utils.read_lc_string(lcs)
     if result != exp or len(result) != expsize:
         self.fail("Wrong result. Expected '%d', got '%d'" %\
             expsize, len(result))
Esempio n. 13
0
    def test_read_lc_string_1(self):
        """Read a length code string from a buffer ( <= 250 bytes)"""
        exp = bytearray(b"a" * 2**(8 - 1))
        expsize = len(exp)
        lcs = utils.int1store(expsize) + exp

        (_, result) = utils.read_lc_string(lcs)
        if result != exp or len(result) != expsize:
            self.fail("Wrong result. Expected '{0}', got '{1}'".format(
                expsize, len(result)))
    def test_int1store(self):
        """Use int1store to pack an integer (2^8) as a string."""
        data = 2 ** (8 - 1)
        exp = struct.pack('<B', data)

        try:
            result = utils.int1store(data)
        except ValueError as err:
            self.fail("int1store failed: {0}".format(str(err)))
        else:
            self._check_int_result(result, exp, data)
Esempio n. 15
0
    def test_int1store(self):
        """Use int1store to pack an integer (2^8) as a string."""
        data = 2**(8 - 1)
        exp = struct.pack('<B', data)

        try:
            result = utils.int1store(data)
        except ValueError as err:
            self.fail("int1store failed: {0}".format(str(err)))
        else:
            self._check_int_result(result, exp, data)
Esempio n. 16
0
    def make_change_user(self, seed, username=None, password=None,
                         database=None, charset=33, client_flags=0):
        """Make a MySQL packet with the Change User command"""
        if not seed:
            raise errors.ProgrammingError('Seed missing')

        auth = self._prepare_auth(username, password, database,
                                  client_flags, seed)
        data = utils.int1store(ServerCmd.CHANGE_USER) +\
               auth[0] + auth[1] + auth[2] + utils.int2store(charset)
        return data
Esempio n. 17
0
    def _prepare_binary_timestamp(self, value):
        """Prepare a timestamp object for the MySQL binary protocol

        This method prepares a timestamp of type datetime.datetime or
        datetime.date for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        """
        if isinstance(value, datetime.datetime):
            field_type = FieldType.DATETIME
        elif isinstance(value, datetime.date):
            field_type = FieldType.DATE
        else:
            raise ValueError(
                "Argument must a datetime.datetime or datetime.date")

        packed = (utils.int2store(value.year) +
                  utils.int1store(value.month) +
                  utils.int1store(value.day))

        if isinstance(value, datetime.datetime):
            packed = (packed + utils.int1store(value.hour) +
                      utils.int1store(value.minute) +
                      utils.int1store(value.second))
            if value.microsecond > 0:
                packed += utils.int4store(value.microsecond)

        packed = utils.int1store(len(packed)) + packed
        return (packed, field_type)
Esempio n. 18
0
    def make_auth(self, seed, username=None, password=None, database=None,
                  charset=33, client_flags=0,
                  max_allowed_packet=1073741824):
        """Make a MySQL Authentication packet"""
        if not seed:
            raise errors.ProgrammingError('Seed missing')

        auth = self._prepare_auth(username, password, database,
                                  client_flags, seed)
        return utils.int4store(client_flags) +\
               utils.int4store(max_allowed_packet) +\
               utils.int1store(charset) +\
               '\x00' * 23 + auth[0] + auth[1] + auth[2]
Esempio n. 19
0
    def _prepare_binary_time(self, value):
        """Prepare a time object for the MySQL binary protocol

        This method prepares a time object of type datetime.timedelta or
        datetime.time for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        """
        if not isinstance(value, (datetime.timedelta, datetime.time)):
            raise ValueError("Argument must a datetime.timedelta or datetime.time")

        field_type = FieldType.TIME
        negative = 0
        mcs = None
        packed = b""

        if isinstance(value, datetime.timedelta):
            if value.days < 0:
                negative = 1
            (hours, remainder) = divmod(value.seconds, 3600)
            (mins, secs) = divmod(remainder, 60)
            packed += (
                utils.int4store(abs(value.days))
                + utils.int1store(hours)
                + utils.int1store(mins)
                + utils.int1store(secs)
            )
            mcs = value.microseconds
        else:
            packed += (
                utils.int4store(0)
                + utils.int1store(value.hour)
                + utils.int1store(value.minute)
                + utils.int1store(value.second)
            )
            mcs = value.microsecond
        if mcs:
            packed += utils.int4store(mcs)

        packed = utils.int1store(negative) + packed
        packed = utils.int1store(len(packed)) + packed

        return (packed, field_type)
Esempio n. 20
0
 def test_int1store(self):
     """Use int1store to pack an integer (2^8) as a string."""
     data = 2**(8-1)
     exp = struct.pack('<B',data)
     
     try:
         result = utils.int1store(data)
     except ValueError as e:
         self.fail("int1store failed: %s" % e)
     else:
         if not isinstance(result, str):
             self.fail("Wrong result. Expected %s, we got %s" %\
                 (type(exp), type(result)))
         elif exp != result:
             self.fail("Wrong result. Expected %s, we got %s" %\
                 (data, result))
Esempio n. 21
0
    def test_int1store(self):
        """Use int1store to pack an integer (2^8) as a string."""
        data = 2**(8 - 1)
        exp = struct.pack('<B', data)

        try:
            result = utils.int1store(data)
        except ValueError as e:
            self.fail("int1store failed: %s" % e)
        else:
            if not isinstance(result, bytes):
                self.fail("Wrong result. Expected %s, we got %s" %\
                    (type(exp), type(result)))
            elif exp != result:
                self.fail("Wrong result. Expected %s, we got %s" %\
                    (data, result))
Esempio n. 22
0
    def _prepare_binary_time(self, value):
        """Prepare a time object for the MySQL binary protocol

        This method prepares a time object of type datetime.timedelta or
        datetime.time for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        """
        if not isinstance(value, (datetime.timedelta, datetime.time)):
            raise ValueError(
                "Argument must a datetime.timedelta or datetime.time")

        field_type = FieldType.TIME
        negative = 0
        mcs = None
        packed = ''

        if isinstance(value, datetime.timedelta):
            if value.days < 0:
                negative = 1
            (hours, remainder) = divmod(value.seconds, 3600)
            (mins, secs) = divmod(remainder, 60)
            packed += (utils.int4store(abs(value.days)) +
                       utils.int1store(hours) +
                       utils.int1store(mins) +
                       utils.int1store(secs))
            mcs = value.microseconds
        else:
            packed += (utils.int4store(0) +
                       utils.int1store(value.hour) +
                       utils.int1store(value.minute) +
                       utils.int1store(value.second))
            mcs = value.microsecond
        if mcs:
            packed += utils.int4store(mcs)

        packed = utils.int1store(negative) + packed
        packed = utils.int1store(len(packed)) + packed

        return (packed, field_type)
Esempio n. 23
0
    def _prepare_auth(self, usr, pwd, dbname, flags, seed):
        """Prepare elements of the authentication packet"""
        if usr is not None and len(usr) > 0:
            _username = usr.encode("utf-8") + b"\x00"
        else:
            _username = b"\x00"

        if pwd is not None and len(pwd) > 0:
            _password = utils.int1store(20) + self._scramble_password(pwd.encode("utf-8"), seed)
        else:
            _password = b"\x00"

        if dbname is not None and len(dbname):
            _database = dbname.encode("utf-8") + b"\x00"
        else:
            _database = b"\x00"

        return (_username, _password, _database)
Esempio n. 24
0
 def _prepare_auth(self, usr, pwd, db, flags, seed):
     """Prepare elements of the authentication packet"""
     if usr is not None and len(usr) > 0:
         _username = usr.encode('utf-8') + b'\x00'
     else:
         _username = b'\x00'
     
     if pwd is not None and len(pwd) > 0:
         _password = utils.int1store(20) +\
             self._scramble_password(pwd.encode('utf-8'),seed)
     else:
         _password = b'\x00'
     
     if db is not None and len(db):
         _database = db.encode('utf-8') + b'\x00'
     else:
         _database = b'\x00'
     
     return (_username, _password, _database)
Esempio n. 25
0
    def _prepare_auth(self, usr, pwd, db, flags, seed):
        """Prepare elements of the authentication packet"""
        if usr is not None and len(usr) > 0:
            _username = usr + '\x00'
        else:
            _username = '******'

        if pwd is not None and len(pwd) > 0:
            _password = utils.int1store(20) +\
                self._scramble_password(pwd,seed)
        else:
            _password = '******'

        if db is not None and len(db):
            _database = db + '\x00'
        else:
            _database = '\x00'

        return (_username, _password, _database)
Esempio n. 26
0
    def _prepare_auth(self, usr, pwd, dbname, flags, seed):
        """Prepare elements of the authentication packet"""

        if usr is not None and len(usr) > 0:
            if isinstance(usr, unicode):
                usr = usr.encode('utf8')
            _username = usr + '\x00'
        else:
            _username = '******'

        if pwd is not None and len(pwd) > 0:
            if isinstance(pwd, unicode):
                pwd = pwd.encode('utf8')
            _password = utils.int1store(20) +\
                self._scramble_password(pwd, seed)
        else:
            _password = '******'

        if dbname is not None and len(dbname):
            _database = dbname.encode('utf8') + '\x00'
        else:
            _database = '\x00'

        return (_username, _password, _database)
Esempio n. 27
0
    def _prepare_auth(self, usr, pwd, dbname, flags, seed):
        """Prepare elements of the authentication packet"""

        if usr is not None and len(usr) > 0:
            if isinstance(usr, unicode):
                usr = usr.encode('utf8')
            _username = usr + '\x00'
        else:
            _username = '******'

        if pwd is not None and len(pwd) > 0:
            if isinstance(pwd, unicode):
                pwd = pwd.encode('utf8')
            _password = utils.int1store(20) +\
                self._scramble_password(pwd, seed)
        else:
            _password = '******'

        if dbname is not None and len(dbname):
            _database = dbname.encode('utf8') + '\x00'
        else:
            _database = '\x00'

        return (_username, _password, _database)
Esempio n. 28
0
    def make_stmt_execute(self, statement_id, data=(), parameters=(),
                          flags=0, long_data_used=None, charset='utf8'):
        """Make a MySQL packet with the Statement Execute command"""
        iteration_count = 1
        null_bitmap = [0] * ((len(data) + 7) // 8)
        values = []
        types = []
        packed = ''
        if long_data_used is None:
            long_data_used = {}
        if parameters and data:
            if len(data) != len(parameters):
                raise errors.InterfaceError(
                    "Failed executing prepared statement: data values does not"
                    " match number of parameters")
            for pos, _ in enumerate(parameters):
                value = data[pos]
                flags = 0
                if value is None:
                    null_bitmap[(pos // 8)] |= 1 << (pos % 8)
                    continue
                elif pos in long_data_used:
                    if long_data_used[pos][0]:
                        # We suppose binary data
                        field_type = FieldType.BLOB
                    else:
                        # We suppose text data
                        field_type = FieldType.STRING
                elif isinstance(value, (int, long)):
                    (packed, field_type,
                     flags) = self._prepare_binary_integer(value)
                    values.append(packed)
                elif isinstance(value, str):
                    values.append(utils.intstore(len(value)) + value)
                    field_type = FieldType.VARCHAR
                elif isinstance(value, unicode):
                    value = value.encode(charset)
                    values.append(utils.intstore(len(value)) + value)
                    field_type = FieldType.VARCHAR
                elif isinstance(value, Decimal):
                    values.append(utils.intstore(len(str(value))) + str(value))
                    field_type = FieldType.DECIMAL
                elif isinstance(value, float):
                    values.append(struct.pack('d', value))
                    field_type = FieldType.DOUBLE
                elif isinstance(value, (datetime.datetime, datetime.date)):
                    (packed, field_type) = self._prepare_binary_timestamp(
                        value)
                    values.append(packed)
                elif isinstance(value, (datetime.timedelta, datetime.time)):
                    (packed, field_type) = self._prepare_binary_time(value)
                    values.append(packed)
                else:
                    raise errors.ProgrammingError(
                        "MySQL binary protocol can not handle "
                        "'{classname}' objects".format(
                            classname=value.__class__.__name__))
                types.append(utils.int1store(field_type) +
                             utils.int1store(flags))

        packet = (
            utils.int4store(statement_id),
            utils.int1store(flags),
            utils.int4store(iteration_count),
            ''.join([struct.pack('B', bit) for bit in null_bitmap]),
            utils.int1store(1),
            ''.join(types),
            ''.join(values)
        )
        return ''.join(packet)
Esempio n. 29
0
 def make_command(self, command, argument=None):
     """Make a MySQL packet containing a command"""
     data = utils.int1store(command)
     if argument is not None:
         data += str(argument)
     return data
Esempio n. 30
0
    def make_stmt_execute(self, statement_id, data=(), parameters=(),
                          flags=0, long_data_used=None, charset='utf8'):
        """Make a MySQL packet with the Statement Execute command"""
        iteration_count = 1
        null_bitmap = [0] * ((len(data) + 7) // 8)
        values = []
        types = []
        packed = b''
        if long_data_used is None:
            long_data_used = {}
        if parameters and data:
            if len(data) != len(parameters):
                raise errors.InterfaceError(
                    "Failed executing prepared statement: data values does not"
                    " match number of parameters")
            for pos, _ in enumerate(parameters):
                value = data[pos]
                flags = 0
                if value is None:
                    null_bitmap[(pos // 8)] |= 1 << (pos % 8)
                    continue
                elif pos in long_data_used:
                    if long_data_used[pos][0]:
                        # We suppose binary data
                        field_type = FieldType.BLOB
                    else:
                        # We suppose text data
                        field_type = FieldType.STRING
                elif isinstance(value, int):
                    (packed, field_type,
                     flags) = self._prepare_binary_integer(value)
                    values.append(packed)
                elif isinstance(value, str):
                    value = value.encode(charset)
                    values.append(
                        utils.intstore(len(value)) + value)
                    field_type = FieldType.VARCHAR
                elif isinstance(value, bytes):
                    values.append(utils.intstore(len(value)) + value)
                    field_type = FieldType.BLOB
                elif isinstance(value, Decimal):
                    values.append(
                        utils.intstore(len(str(value).encode(charset))) +
                        str(value).encode(charset))
                    field_type = FieldType.DECIMAL
                elif isinstance(value, float):
                    values.append(struct.pack('d', value))
                    field_type = FieldType.DOUBLE
                elif isinstance(value, (datetime.datetime, datetime.date)):
                    (packed, field_type) = self._prepare_binary_timestamp(
                        value)
                    values.append(packed)
                elif isinstance(value, (datetime.timedelta, datetime.time)):
                    (packed, field_type) = self._prepare_binary_time(value)
                    values.append(packed)
                else:
                    raise errors.ProgrammingError(
                        "MySQL binary protocol can not handle "
                        "'{classname}' objects".format(
                            classname=value.__class__.__name__))
                types.append(utils.int1store(field_type) +
                             utils.int1store(flags))

        packet = (
            utils.int4store(statement_id),
            utils.int1store(flags),
            utils.int4store(iteration_count),
            b''.join([struct.pack('B', bit) for bit in null_bitmap]),
            utils.int1store(1),
            b''.join(types),
            b''.join(values)
            )
        return b''.join(packet)
Esempio n. 31
0
 def make_command(self, command, argument=None):
     """Make a MySQL packet containing a command"""
     data = utils.int1store(command)
     if argument is not None:
         data += argument
     return data