This file is indexed.

/usr/lib/python3/dist-packages/metadataserver/fields.py is in python3-django-maas 2.4.0~beta2-6865-gec43e47e6-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# Copyright 2012-2016 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""Custom field types for the metadata server."""

__all__ = [
    'BinaryField',
    ]

from base64 import (
    b64decode,
    b64encode,
)

from django.db import connection
from maasserver.fields import Field


class Bin(bytes):
    """Wrapper class to convince django that a string is really binary.

    This is really just a "bytes," but gets around an idiosyncracy of Django
    custom field conversions: they must be able to tell on the fly whether a
    value was retrieved from the database (and needs to be converted to a
    python-side value), or whether it's already a python-side object (which
    can stay as it is).  The line between bytes and unicode is dangerously
    thin.

    So, to store a value in a BinaryField, wrap it in a Bin:

        my_model_object.binary_data = Bin(b"\x01\x02\x03")
    """

    def __new__(cls, initializer):
        """Wrap a bytes.

        :param initializer: Binary string of data for this Bin.  This must
            be a bytes.  Anything else is almost certainly a mistake, so e.g.
            this constructor will refuse to render None as b'None'.
        :type initializer: bytes
        """
        # We can't do this in __init__, because it passes its argument into
        # the upcall.  It ends up in object.__init__, which sometimes issues
        # a DeprecationWarning because it doesn't want any arguments.
        # Those warnings would sometimes make their way into logs, breaking
        # tests that checked those logs.
        if not isinstance(initializer, bytes):
            raise AssertionError(
                "Not a binary string: '%s'" % repr(initializer))
        return super(Bin, cls).__new__(cls, initializer)

    def __emittable__(self):
        """Emit base-64 encoded bytes.

        Exists as a hook for Piston's JSON encoder.
        """
        return b64encode(self).decode('ascii')


class BinaryField(Field):
    """A field that stores binary data.

    The data is base64-encoded internally, so this is not very efficient.
    Do not use this for large blobs.

    We do not have direct support for binary data in django at the moment.
    It's possible to create a django model Field based by a postgres BYTEA,
    but:

    1. Any data you save gets mis-interpreted as encoded text.  This won't
       be obvious until you test with data that can't be decoded.
    2. Any data you retrieve gets truncated at the first zero byte.
    """

    def to_python(self, value):
        """Django overridable: convert database value to python-side value."""
        if isinstance(value, str):
            # Encoded binary data from the database.  Convert.
            return Bin(b64decode(value))
        elif value is None or isinstance(value, Bin):
            # Already in python-side form.
            return value
        else:
            raise AssertionError(
                "Invalid BinaryField value (expected unicode): '%s'"
                % repr(value))

    def from_db_value(self, value, expression, connection, context):
        return self.to_python(value)

    def get_db_prep_value(self, value, connection=None, prepared=False):
        """Django overridable: convert python-side value to database value."""
        if value is None:
            # Equivalent of a NULL.
            return None
        elif isinstance(value, Bin):
            # Python-side form.  Convert to database form.
            return b64encode(value).decode("ascii")
        elif isinstance(value, bytes):
            # Binary string.  Require a Bin to make intent explicit.
            raise AssertionError(
                "Converting a binary string to BinaryField: "
                "either conversion is going the wrong way, or the value "
                "needs to be wrapped in a Bin.")
        elif isinstance(value, str):
            # Django 1.7 migration framework generates the default value based
            # on the 'internal_type' which, in this instance, is 'TextField';
            # Here we cope with the default empty value instead of raising
            # an exception.
            if value == '':
                return ''
            # Unicode here is almost certainly a sign of a mistake.
            raise AssertionError(
                "A unicode string is being mistaken for binary data.")
        else:
            raise AssertionError(
                "Invalid BinaryField value (expected Bin): '%s'"
                % repr(value))

    def get_internal_type(self):
        return 'TextField'

    def _get_default(self):
        """Cargo-cult of Django's `Field.get_default`.

        Django is totally smoking crack on this one. It forces a
        unicode string out of the default which is demonstrably not
        unicode. This corrects that behaviour.

        """
        if self.has_default():
            if callable(self.default):
                return self.default()
            return self.default
        if not self.empty_strings_allowed:
            return None
        if self.null:
            if not connection.features.interprets_empty_strings_as_nulls:
                return None
        return b""

    def get_default(self):
        """Override Django's crack-smoking ``Field.get_default``."""
        default = self._get_default()
        return None if default is None else Bin(default)