Пример #1
0
def _check_key(key, allow_unicode_keys, key_prefix=b''):
    """Checks key and add key_prefix."""
    if allow_unicode_keys:
        if isinstance(key, six.text_type):
            key = key.encode('utf8')
    elif isinstance(key, VALID_STRING_TYPES):
        try:
            if isinstance(key, bytes):
                key = key.decode().encode('ascii')
            else:
                key = key.encode('ascii')
        except (UnicodeEncodeError, UnicodeDecodeError):
            raise MemcacheIllegalInputError("Non-ASCII key: %r" % key)

    key = key_prefix + key
    parts = key.split()

    if len(key) > 250:
        raise MemcacheIllegalInputError("Key is too long: %r" % key)
    # second statement catches leading or trailing whitespace
    elif len(parts) > 1 or parts[0] != key:
        raise MemcacheIllegalInputError("Key contains whitespace: %r" % key)
    elif b'\00' in key:
        raise MemcacheIllegalInputError("Key contains null: %r" % key)

    return key
Пример #2
0
    def set(self, key, value, expire=0, noreply=True):
        if isinstance(key, six.text_type):
            raise MemcacheIllegalInputError(key)
        if isinstance(value, six.text_type):
            raise MemcacheIllegalInputError(value)
        if isinstance(key, six.string_types):
            try:
                key = key.encode('ascii')
            except (UnicodeEncodeError, UnicodeDecodeError):
                raise MemcacheIllegalInputError
        if isinstance(value, six.string_types):
            try:
                value = value.encode('ascii')
            except (UnicodeEncodeError, UnicodeDecodeError):
                raise MemcacheIllegalInputError

        flags = 0
        if self.serializer:
            value, flags = self.serializer(key, value)

        if expire:
            expire += time.time()

        self._contents[key] = expire, value, flags
        return True
Пример #3
0
    def _check_cas(self, cas):
        """Check that a value is a valid input for 'cas' -- either an int or a
        string containing only 0-9

        The value will be (re)encoded so that we can accept strings or bytes.
        """
        # convert non-binary values to binary
        if isinstance(cas, (six.integer_types, six.string_types)):
            try:
                cas = six.text_type(cas).encode(self.encoding)
            except UnicodeEncodeError:
                raise MemcacheIllegalInputError(
                    'non-ASCII cas value: %r' % cas)
        elif not isinstance(cas, six.binary_type):
            raise MemcacheIllegalInputError(
                'cas must be integer, string, or bytes, got bad value: %r' % cas
            )

        if not cas.isdigit():
            raise MemcacheIllegalInputError(
                'cas must only contain values in 0-9, got bad value: %r'
                % cas
            )

        return cas
Пример #4
0
def _check_key(key, key_prefix=b''):
    """Checks key and add key_prefix."""
    if isinstance(key, six.text_type):
        try:
            key = key.encode('ascii')
        except UnicodeEncodeError:
            raise MemcacheIllegalInputError("No ascii key: %r" % (key, ))
    key = key_prefix + key
    if b' ' in key:
        raise MemcacheIllegalInputError("Key contains spaces: %r" % (key, ))
    if len(key) > 250:
        raise MemcacheIllegalInputError("Key is too long: %r" % (key, ))
    return key
Пример #5
0
def _check_key(key, key_prefix=b''):
    """Checks key and add key_prefix."""
    if isinstance(key, VALID_STRING_TYPES):
        try:
            key = key.encode('ascii')
        except (UnicodeEncodeError, UnicodeDecodeError):
            raise MemcacheIllegalInputError("Non-ASCII key: '%r'" % (key, ))
    key = key_prefix + key
    if b' ' in key or b'\n' in key:
        raise MemcacheIllegalInputError(
            "Key contains space and/or newline: '%r'" % (key, ))
    if len(key) > 250:
        raise MemcacheIllegalInputError("Key is too long: '%r'" % (key, ))
    return key
Пример #6
0
    def set(self, key, value, expire=0, noreply=True):
        if isinstance(key, six.text_type):
            raise MemcacheIllegalInputError(key)
        if isinstance(value, six.text_type):
            raise MemcacheIllegalInputError(value)

        was_serialized = False
        if self.serializer:
            value = self.serializer(key, value)

        if expire:
            expire += time.time()

        self._contents[key] = expire, value, was_serialized
        return True
Пример #7
0
    def _check_integer(self, value, name):
        """Check that a value is an integer and encode it as a binary string"""
        if not isinstance(value, six.integer_types):  # includes "long" on py2
            raise MemcacheIllegalInputError(
                '%s must be integer, got bad value: %r' % (name, value))

        return six.text_type(value).encode(self.encoding)
Пример #8
0
def _check_key(key, allow_unicode_keys, key_prefix=b''):
    """Checks key and add key_prefix."""
    if allow_unicode_keys:
        if isinstance(key, six.text_type):
            key = key.encode('utf8')
    elif isinstance(key, VALID_STRING_TYPES):
        try:
            key = key.encode('ascii')
        except (UnicodeEncodeError, UnicodeDecodeError):
            raise MemcacheIllegalInputError("Non-ASCII key: '%r'" % (key,))
    key = key_prefix + key

    if len(key) > 250:
        raise MemcacheIllegalInputError("Key is too long: '%r'" % (key,))

    for c in bytearray(key):
        if c == ord(b' '):
            raise MemcacheIllegalInputError(
                "Key contains space: '%r'" % (key,)
            )
        elif c == ord(b'\n'):
            raise MemcacheIllegalInputError(
                "Key contains newline: '%r'" % (key,)
            )
        elif c == ord(b'\00'):
            raise MemcacheIllegalInputError(
              "Key contains null character: '%r'" % (key,)
            )
        elif c == ord(b'\r'):
            raise MemcacheIllegalInputError(
              "Key contains carriage return: '%r'" % (key,)
            )
    return key
Пример #9
0
    def _store_cmd(self, name, key, expire, noreply, data, cas=None):
        key = self.check_key(key)
        if not self.sock:
            self._connect()

        if self.serializer:
            data, flags = self.serializer(key, data)
        else:
            flags = 0

        if not isinstance(data, six.binary_type):
            try:
                data = six.text_type(data).encode('ascii')
            except UnicodeEncodeError as e:
                raise MemcacheIllegalInputError(str(e))

        extra = b''
        if cas is not None:
            extra += b' ' + cas
        if noreply:
            extra += b' noreply'

        cmd = (name + b' ' + key + b' ' +
               six.text_type(flags).encode('ascii') + b' ' +
               six.text_type(expire).encode('ascii') + b' ' +
               six.text_type(len(data)).encode('ascii') + extra + b'\r\n' +
               data + b'\r\n')

        try:
            self.sock.sendall(cmd)

            if noreply:
                return True

            buf = b''
            buf, line = _readline(self.sock, buf)
            self._raise_errors(line, name)

            if line in VALID_STORE_RESULTS[name]:
                if line == b'STORED':
                    return True
                if line == b'NOT_STORED':
                    return False
                if line == b'NOT_FOUND':
                    return None
                if line == b'EXISTS':
                    return False
            else:
                raise MemcacheUnknownError(line[:32])
        except Exception:
            self.close()
            raise
Пример #10
0
    def get(self, key, default=None):
        if isinstance(key, six.text_type):
            raise MemcacheIllegalInputError(key)

        if key not in self._contents:
            return default

        expire, value, was_serialized = self._contents[key]
        if expire and expire < time.time():
            del self._contents[key]
            return default

        if self.deserializer:
            return self.deserializer(key, value, 2 if was_serialized else 1)
        return value
Пример #11
0
    def get(self, key, default=None):
        if isinstance(key, six.text_type):
            raise MemcacheIllegalInputError(key)
        if isinstance(key, six.string_types):
            try:
                key = key.encode('ascii')
            except (UnicodeEncodeError, UnicodeDecodeError):
                raise MemcacheIllegalInputError

        if key not in self._contents:
            return default

        expire, value, flags = self._contents[key]
        if expire and expire < time.time():
            del self._contents[key]
            return default

        if self.deserializer:
            return self.deserializer(key, value, flags)
        return value
Пример #12
0
    def _store_cmd(self, name, values, expire, noreply, flags=None, cas=None):
        cmds = []
        keys = []

        extra = b''
        if cas is not None:
            extra += b' ' + cas
        if noreply:
            extra += b' noreply'
        expire = six.text_type(expire).encode(self.encoding)

        for key, data in six.iteritems(values):
            # must be able to reliably map responses back to the original order
            keys.append(key)

            key = self.check_key(key)
            if self.serializer:
                data, serializer_flags = self.serializer(key, data)
                # Use the serializer's flags when 'flags' haven't been specified
                # If 'flags' is specified, ignore the serializer_flags generated
                #  from serializer, otherwise use serializer_flags.
                if flags is None:
                    flags = serializer_flags
            # If no 'flags' or 'serializer' passed in, default flags to 0
            if flags is None:
                flags = 0

            if not isinstance(data, six.binary_type):
                try:
                    data = six.text_type(data).encode(self.encoding)
                except UnicodeEncodeError as e:
                    raise MemcacheIllegalInputError(
                            "Data values must be binary-safe: %s" % e)

            cmds.append(name + b' ' + key + b' ' +
                        six.text_type(flags).encode(self.encoding) +
                        b' ' + expire +
                        b' ' + six.text_type(len(data)).encode(self.encoding) +
                        extra + b'\r\n' + data + b'\r\n')

        if self.sock is None:
            self._connect()

        try:
            self.sock.sendall(b''.join(cmds))
            if noreply:
                return {k: True for k in keys}

            results = {}
            buf = b''
            for key in keys:
                buf, line = _readline(self.sock, buf)
                self._raise_errors(line, name)

                if line in VALID_STORE_RESULTS[name]:
                    if line == b'STORED':
                        results[key] = True
                    if line == b'NOT_STORED':
                        results[key] = False
                    if line == b'NOT_FOUND':
                        results[key] = None
                    if line == b'EXISTS':
                        results[key] = False
                else:
                    raise MemcacheUnknownError(line[:32])
            return results
        except Exception:
            self.close()
            raise
Пример #13
0
    def _store_cmd(self, name, values, expire, noreply, flags=None, cas=None):
        cmds = []
        keys = []

        extra = b''
        if cas is not None:
            cas = self._check_cas(cas)
            extra += b' ' + cas
        if noreply:
            extra += b' noreply'
        expire = self._check_integer(expire, "expire")

        for key, data in six.iteritems(values):
            # must be able to reliably map responses back to the original order
            keys.append(key)

            key = self.check_key(key)
            data, data_flags = self.serde.serialize(key, data)

            # If 'flags' was explicitly provided, it overrides the value
            # returned by the serializer.
            if flags is not None:
                data_flags = flags

            if not isinstance(data, six.binary_type):
                try:
                    data = six.text_type(data).encode(self.encoding)
                except UnicodeEncodeError as e:
                    raise MemcacheIllegalInputError(
                        "Data values must be binary-safe: %s" % e)

            cmds.append(name + b' ' + key + b' ' +
                        six.text_type(data_flags).encode(self.encoding) +
                        b' ' + expire + b' ' +
                        six.text_type(len(data)).encode(self.encoding) +
                        extra + b'\r\n' + data + b'\r\n')

        if self.sock is None:
            self._connect()

        try:
            self.sock.sendall(b''.join(cmds))
            if noreply:
                return {k: True for k in keys}

            results = {}
            buf = b''
            for key in keys:
                buf, line = _readline(self.sock, buf)
                self._raise_errors(line, name)

                if line in VALID_STORE_RESULTS[name]:
                    if line == b'STORED':
                        results[key] = True
                    if line == b'NOT_STORED':
                        results[key] = False
                    if line == b'NOT_FOUND':
                        results[key] = None
                    if line == b'EXISTS':
                        results[key] = False
                else:
                    raise MemcacheUnknownError(line[:32])
            return results
        except Exception:
            self.close()
            raise
Пример #14
0
    def _store_cmd(self, name, values, expire, noreply, cas=None):
        cmds = []
        keys = []

        extra = b''
        if cas is not None:
            extra += b' ' + cas
        if noreply:
            extra += b' noreply'
        expire = six.text_type(expire).encode('ascii')

        for key, data in six.iteritems(values):
            # must be able to reliably map responses back to the original order
            keys.append(key)

            key = self.check_key(key)
            if self.serializer:
                data, flags = self.serializer(key, data)
            else:
                flags = 0

            if not isinstance(data, six.binary_type):
                try:
                    data = six.text_type(data).encode('ascii')
                except UnicodeEncodeError as e:
                    raise MemcacheIllegalInputError(str(e))

            cmds.append(name + b' ' + key + b' ' +
                        six.text_type(flags).encode('ascii') + b' ' + expire +
                        b' ' + six.text_type(len(data)).encode('ascii') +
                        extra + b'\r\n' + data + b'\r\n')

        if not self.sock:
            self._connect()

        try:
            self.sock.sendall(b''.join(cmds))
            if noreply:
                return {k: True for k in keys}

            results = {}
            buf = b''
            for key in keys:
                buf, line = _readline(self.sock, buf)
                self._raise_errors(line, name)

                if line in VALID_STORE_RESULTS[name]:
                    if line == b'STORED':
                        results[key] = True
                    if line == b'NOT_STORED':
                        results[key] = False
                    if line == b'NOT_FOUND':
                        results[key] = None
                    if line == b'EXISTS':
                        results[key] = False
                else:
                    raise MemcacheUnknownError(line[:32])
            return results
        except Exception:
            self.close()
            raise