示例#1
0
    def process_one(self, challenge):
        """
        """
        vitals = ['username']
        if 'SaltedPassword' not in self.values:
            vitals.append('password')
        if 'Iterations' not in self.values:
            vitals.append('password')

        self.check_values(vitals)

        username = bytes(self.values['username'])

        self._step = 1
        self._cnonce = bytes(('%s' % random.random())[2:])
        self._soup = b'n=' + username + b',r=' + self._cnonce
        self._gs2header = b''

        if not self.sasl.tls_active():
            if self._cb:
                self._gs2header = b'p=tls-unique,,'
            else:
                self._gs2header = b'y,,'
        else:
            self._gs2header = b'n,,'

        return self._gs2header + self._soup
示例#2
0
    def process(self, challenge=None):
        """
        """
        if challenge is None:
            if self.has_values([
                    'username', 'realm', 'nonce', 'key_hash', 'nc', 'cnonce',
                    'qops'
            ]):
                self._qops = self.values['qops']
                return self.response()
            else:
                return None

        d = parse_challenge(challenge)
        if b'rspauth' in d:
            self.mutual_auth(d[b'rspauth'])
        else:
            if b'realm' not in d:
                d[b'realm'] = self.sasl.def_realm
            for key in ['nonce', 'realm']:
                if bytes(key) in d:
                    self.values[key] = d[bytes(key)]
            self.values['nc'] = 0
            self._qops = [b'auth']
            if b'qop' in d:
                self._qops = [x.strip() for x in d[b'qop'].split(b',')]
            self.values['qops'] = self._qops
            if b'maxbuf' in d:
                self._max_buffer = int(d[b'maxbuf'])
            return self.response()
示例#3
0
    def process(self, challenge=None):
        """
        """
        if challenge is None:
            if self.has_values(["username", "realm", "nonce", "key_hash", "nc", "cnonce", "qops"]):
                self._qops = self.values["qops"]
                return self.response()
            else:
                return None

        d = parse_challenge(challenge)
        if b"rspauth" in d:
            self.mutual_auth(d[b"rspauth"])
        else:
            if b"realm" not in d:
                d[b"realm"] = self.sasl.def_realm
            for key in ["nonce", "realm"]:
                if bytes(key) in d:
                    self.values[key] = d[bytes(key)]
            self.values["nc"] = 0
            self._qops = [b"auth"]
            if b"qop" in d:
                self._qops = [x.strip() for x in d[b"qop"].split(b",")]
            self.values["qops"] = self._qops
            if b"maxbuf" in d:
                self._max_buffer = int(d[b"maxbuf"])
            return self.response()
示例#4
0
    def process_one(self, challenge):
        """
        """
        vitals = ["username"]
        if "SaltedPassword" not in self.values:
            vitals.append("password")
        if "Iterations" not in self.values:
            vitals.append("password")

        self.check_values(vitals)

        username = bytes(self.values["username"])

        self._step = 1
        self._cnonce = bytes(("%s" % random.random())[2:])
        self._soup = b"n=" + username + b",r=" + self._cnonce
        self._gs2header = b""

        if not self.sasl.tls_active():
            if self._cb:
                self._gs2header = b"p=tls-unique,,"
            else:
                self._gs2header = b"y,,"
        else:
            self._gs2header = b"n,,"

        return self._gs2header + self._soup
示例#5
0
    def process_one(self, challenge):
        """
        """
        vitals = ['username']
        if 'SaltedPassword' not in self.values:
            vitals.append('password')
        if 'Iterations' not in self.values:
            vitals.append('password')

        self.check_values(vitals)

        username = bytes(self.values['username'])

        self._step = 1
        self._cnonce = bytes(('%s' % random.random())[2:])
        self._soup = b'n=' + username + b',r=' + self._cnonce
        self._gs2header = b''

        if not self.sasl.tls_active():
            if self._cb:
                self._gs2header = b'p=tls-unique,,'
            else:
                self._gs2header = b'y,,'
        else:
            self._gs2header = b'n,,'

        return self._gs2header + self._soup
示例#6
0
    def process(self, challenge=None):
        """
        """
        if challenge is None:
            if self.has_values(['username', 'realm', 'nonce', 'key_hash',
                                'nc', 'cnonce', 'qops']):
                self._qops = self.values['qops']
                return self.response()
            else:
                return None

        d = parse_challenge(challenge)
        if b'rspauth' in d:
            self.mutual_auth(d[b'rspauth'])
        else:
            if b'realm' not in d:
                d[b'realm'] = self.sasl.def_realm
            for key in ['nonce', 'realm']:
                if bytes(key) in d:
                    self.values[key] = d[bytes(key)]
            self.values['nc'] = 0
            self._qops = [b'auth']
            if b'qop' in d:
                self._qops = [x.strip() for x in d[b'qop'].split(b',')]
            self.values['qops'] = self._qops
            if b'maxbuf' in d:
                self._max_buffer = int(d[b'maxbuf'])
            return self.response()
示例#7
0
文件: auth.py 项目: taoGit/SleekXMPP
 def set_value(self, values):
     if not self['mechanism'] in self.plain_mechs:
         if values:
             self.xml.text = bytes(base64.b64encode(values)).decode('utf-8')
         else:
             self.xml.text = '='
     else:
         self.xml.text = bytes(values).decode('utf-8')
示例#8
0
 def set_value(self, values):
     if not self['mechanism'] in self.plain_mechs:
         if values:
             self.xml.text = bytes(base64.b64encode(values)).decode('utf-8')
         else:
             self.xml.text = '='
     else:
         self.xml.text = bytes(values).decode('utf-8')
示例#9
0
文件: plain.py 项目: stlcours/emesene
    def process(self, challenge=None):
        """
        Process a challenge request and return the response.

        :param challenge: A challenge issued by the server that
                          must be answered for authentication.
        """
        user = bytes(self.values['username'])
        password = bytes(self.values['password'])
        return b'\x00' + user + b'\x00' + password
示例#10
0
    def process(self, challenge=None):
        """
        Process a challenge request and return the response.

        :param challenge: A challenge issued by the server that
                          must be answered for authentication.
        """
        user = bytes(self.values["username"])
        password = bytes(self.values["password"])
        return b"\x00" + user + b"\x00" + password
示例#11
0
    def process(self, challenge):
        """
        """
        if challenge is None:
            return None

        self.check_values(['username', 'password'])
        username = bytes(self.values['username'])
        password = bytes(self.values['password'])

        mac = hmac.HMAC(key=password, digestmod=self.hash)

        mac.update(challenge)

        return username + b' ' + bytes(mac.hexdigest())
示例#12
0
    def process(self, challenge):
        """
        """
        if challenge is None:
            return None

        self.check_values(['username', 'password'])
        username = bytes(self.values['username'])
        password = bytes(self.values['password'])

        mac = hmac.HMAC(key=password, digestmod=self.hash)

        mac.update(challenge)

        return username + b' ' + bytes(mac.hexdigest())
示例#13
0
 def set_binval(self, value):
     self.del_binval()
     parent = self.parent()
     if value:
         xml = ET.Element('{%s}BINVAL' % self.namespace)
         xml.text = bytes(base64.b64encode(value)).decode('utf-8')
         parent.append(xml)
示例#14
0
    def gen_hash(self, a2):
        """
        """
        if not self.has_values(["key_hash"]):
            key_hash = self.hash()
            user = bytes(self.values["username"])
            password = bytes(self.values["password"])
            realm = bytes(self.values["realm"])
            kh = user + b":" + realm + b":" + password
            key_hash.update(kh)
            self.values["key_hash"] = key_hash.digest()

        a1 = self.hash(self.values["key_hash"])
        a1h = b":" + self.values["nonce"] + b":" + self._cnonce
        a1.update(a1h)
        response = self.hash()
        self._a1 = a1.digest()
        rv = bytes(a1.hexdigest().lower())
        rv += b":" + self.values["nonce"]
        rv += b":" + bytes("%08x" % self.values["nc"])
        rv += b":" + self._cnonce
        rv += b":" + self._qop
        rv += b":" + bytes(self.hash(a2).hexdigest().lower())
        response.update(rv)
        return bytes(response.hexdigest().lower())
示例#15
0
    def gen_hash(self, a2):
        """
        """
        if not self.has_values(['key_hash']):
            key_hash = self.hash()
            user = bytes(self.values['username'])
            password = bytes(self.values['password'])
            realm = bytes(self.values['realm'])
            kh = user + b':' + realm + b':' + password
            key_hash.update(kh)
            self.values['key_hash'] = key_hash.digest()

        a1 = self.hash(self.values['key_hash'])
        a1h = b':' + self.values['nonce'] + b':' + self._cnonce
        a1.update(a1h)
        response = self.hash()
        self._a1 = a1.digest()
        rv = bytes(a1.hexdigest().lower())
        rv += b':' + self.values['nonce']
        rv += b':' + bytes('%08x' % self.values['nc'])
        rv += b':' + self._cnonce
        rv += b':' + self._qop
        rv += b':' + bytes(self.hash(a2).hexdigest().lower())
        response.update(rv)
        return bytes(response.hexdigest().lower())
示例#16
0
    def gen_hash(self, a2):
        """
        """
        if not self.has_values(['key_hash']):
            key_hash = self.hash()
            user = bytes(self.values['username'])
            password = bytes(self.values['password'])
            realm = bytes(self.values['realm'])
            kh = user + b':' + realm + b':' + password
            key_hash.update(kh)
            self.values['key_hash'] = key_hash.digest()

        a1 = self.hash(self.values['key_hash'])
        a1h = b':' + self.values['nonce'] + b':' + self._cnonce
        a1.update(a1h)
        response = self.hash()
        self._a1 = a1.digest()
        rv = bytes(a1.hexdigest().lower())
        rv += b':' + self.values['nonce']
        rv += b':' + bytes('%08x' % self.values['nc'])
        rv += b':' + self._cnonce
        rv += b':' + self._qop
        rv += b':' + bytes(self.hash(a2).hexdigest().lower())
        response.update(rv)
        return bytes(response.hexdigest().lower())
示例#17
0
 def Hi(self, text, salt, iterations):
     """
     """
     text = bytes(text)
     ui_1 = self.HMAC(text, salt + b'\0\0\0\01')
     ui = ui_1
     for i in range(iterations - 1):
         ui_1 = self.HMAC(text, ui_1)
         ui = XOR(ui, ui_1)
     return ui
示例#18
0
 def Hi(self, text, salt, iterations):
     """
     """
     text = bytes(text)
     ui_1 = self.HMAC(text, salt + b'\0\0\0\01')
     ui = ui_1
     for i in range(iterations - 1):
         ui_1 = self.HMAC(text, ui_1)
         ui = XOR(ui, ui_1)
     return ui
示例#19
0
    def process(self, challenge=None):
        if challenge is not None:
            values = {}
            for kv in challenge.split(b'&'):
                key, value = kv.split(b'=')
                values[key] = value

            resp_data = {
                'method': values[b'method'],
                'v': '1.0',
                'call_id': '1.0',
                'nonce': values[b'nonce'],
                'access_token': self.values['access_token'],
                'api_key': self.values['api_key']
            }
            
            for k, v in resp_data.items():
                resp_data[k] = bytes(v).decode('utf-8')

            resp = '&'.join(['%s=%s' % (k, v) for k, v in resp_data.items()])
            return bytes(resp)
        return b''
示例#20
0
    def process(self, challenge=None):
        if challenge is not None:
            values = {}
            for kv in challenge.split(b'&'):
                key, value = kv.split(b'=')
                values[key] = value

            resp_data = {
                'method': values[b'method'],
                'v': '1.0',
                'call_id': '1.0',
                'nonce': values[b'nonce'],
                'access_token': self.values['access_token'],
                'api_key': self.values['api_key']
            }

            for k, v in resp_data.items():
                resp_data[k] = bytes(v).decode('utf-8')

            resp = '&'.join(['%s=%s' % (k, v) for k, v in resp_data.items()])
            return bytes(resp)
        return b''
示例#21
0
def parse_challenge(stuff):
    """
    """
    ret = {}
    var = b""
    val = b""
    in_var = True
    in_quotes = False
    new = False
    escaped = False
    for c in stuff:
        if sys.version_info >= (3, 0):
            c = bytes([c])
        if in_var:
            if c.isspace():
                continue
            if c == b"=":
                in_var = False
                new = True
            else:
                var += c
        else:
            if new:
                if c == b'"':
                    in_quotes = True
                else:
                    val += c
                new = False
            elif in_quotes:
                if escaped:
                    escaped = False
                    val += c
                else:
                    if c == b"\\":
                        escaped = True
                    elif c == b'"':
                        in_quotes = False
                    else:
                        val += c
            else:
                if c == b",":
                    if var:
                        ret[var] = val
                    var = b""
                    val = b""
                    in_var = True
                else:
                    val += c
    if var:
        ret[var] = val
    return ret
示例#22
0
def parse_challenge(stuff):
    """
    """
    ret = {}
    var = b''
    val = b''
    in_var = True
    in_quotes = False
    new = False
    escaped = False
    for c in stuff:
        if sys.version_info >= (3, 0):
            c = bytes([c])
        if in_var:
            if c.isspace():
                continue
            if c == b'=':
                in_var = False
                new = True
            else:
                var += c
        else:
            if new:
                if c == b'"':
                    in_quotes = True
                else:
                    val += c
                new = False
            elif in_quotes:
                if escaped:
                    escaped = False
                    val += c
                else:
                    if c == b'\\':
                        escaped = True
                    elif c == b'"':
                        in_quotes = False
                    else:
                        val += c
            else:
                if c == b',':
                    if var:
                        ret[var] = val
                    var = b''
                    val = b''
                    in_var = True
                else:
                    val += c
    if var:
        ret[var] = val
    return ret
示例#23
0
    def process_two(self, challenge):
        """
        """
        data = parse_challenge(challenge)

        self._step = 2
        self._soup += b',' + challenge + b','
        self._nonce = data[b'r']
        self._salt = b64decode(data[b's'])
        self._iter = int(data[b'i'])

        if self._nonce[:len(self._cnonce)] != self._cnonce:
            raise SASLCancelled(self.sasl, self)

        cbdata = self.sasl.tls_active()
        c = self._gs2header
        if not cbdata and self._cb:
            c += None

        r = b'c=' + b64encode(c).replace(b'\n', b'')
        r += b',r=' + self._nonce
        self._soup += r

        if 'Iterations' in self.values:
            if self.values['Iterations'] != self._iter:
                if 'SaltedPassword' in self.values:
                    del self.values['SaltedPassword']
        if 'Salt' in self.values:
            if self.values['Salt'] != self._salt:
                if 'SaltedPassword' in self.values:
                    del self.values['SaltedPassword']

        self.values['Iterations'] = self._iter
        self.values['Salt'] = self._salt

        if 'SaltedPassword' not in self.values:
            self.check_values(['password'])
            password = bytes(self.values['password'])
            salted_pass = self.Hi(password, self._salt, self._iter)
            self.values['SaltedPassword'] = salted_pass

        salted_pass = self.values['SaltedPassword']
        client_key = self.HMAC(salted_pass, b'Client Key')
        stored_key = self.H(client_key)
        client_sig = self.HMAC(stored_key, self._soup)
        client_proof = XOR(client_key, client_sig)
        r += b',p=' + b64encode(client_proof).replace(b'\n', b'')
        server_key = self.HMAC(self.values['SaltedPassword'], b'Server Key')
        self.server_sig = self.HMAC(server_key, self._soup)
        return r
示例#24
0
    def process_two(self, challenge):
        """
        """
        data = parse_challenge(challenge)

        self._step = 2
        self._soup += b',' + challenge + b','
        self._nonce = data[b'r']
        self._salt = b64decode(data[b's'])
        self._iter = int(data[b'i'])

        if self._nonce[:len(self._cnonce)] != self._cnonce:
            raise SASLCancelled(self.sasl, self)

        cbdata = self.sasl.tls_active()
        c = self._gs2header
        if not cbdata and self._cb:
            c += None

        r = b'c=' + b64encode(c).replace(b'\n', b'')
        r += b',r=' + self._nonce
        self._soup += r

        if 'Iterations' in self.values:
            if self.values['Iterations'] != self._iter:
                if 'SaltedPassword' in self.values:
                    del self.values['SaltedPassword']
        if 'Salt' in self.values:
            if self.values['Salt'] != self._salt:
                if 'SaltedPassword' in self.values:
                    del self.values['SaltedPassword']

        self.values['Iterations'] = self._iter
        self.values['Salt'] = self._salt

        if 'SaltedPassword' not in self.values:
            self.check_values(['password'])
            password = bytes(self.values['password'])
            salted_pass = self.Hi(password, self._salt, self._iter)
            self.values['SaltedPassword'] = salted_pass

        salted_pass = self.values['SaltedPassword']
        client_key = self.HMAC(salted_pass, b'Client Key')
        stored_key = self.H(client_key)
        client_sig = self.HMAC(stored_key, self._soup)
        client_proof = XOR(client_key, client_sig)
        r += b',p=' + b64encode(client_proof).replace(b'\n', b'')
        server_key = self.HMAC(self.values['SaltedPassword'], b'Server Key')
        self.server_sig = self.HMAC(server_key, self._soup)
        return r
示例#25
0
    def process_two(self, challenge):
        """
        """
        data = parse_challenge(challenge)

        self._step = 2
        self._soup += b"," + challenge + b","
        self._nonce = data[b"r"]
        self._salt = b64decode(data[b"s"])
        self._iter = int(data[b"i"])

        if self._nonce[: len(self._cnonce)] != self._cnonce:
            raise SASLCancelled(self.sasl, self)

        cbdata = self.sasl.tls_active()
        c = self._gs2header
        if not cbdata and self._cb:
            c += None

        r = b"c=" + b64encode(c).replace(b"\n", b"")
        r += b",r=" + self._nonce
        self._soup += r

        if "Iterations" in self.values:
            if self.values["Iterations"] != self._iter:
                if "SaltedPassword" in self.values:
                    del self.values["SaltedPassword"]
        if "Salt" in self.values:
            if self.values["Salt"] != self._salt:
                if "SaltedPassword" in self.values:
                    del self.values["SaltedPassword"]

        self.values["Iterations"] = self._iter
        self.values["Salt"] = self._salt

        if "SaltedPassword" not in self.values:
            self.check_values(["password"])
            password = bytes(self.values["password"])
            salted_pass = self.Hi(password, self._salt, self._iter)
            self.values["SaltedPassword"] = salted_pass

        salted_pass = self.values["SaltedPassword"]
        client_key = self.HMAC(salted_pass, b"Client Key")
        stored_key = self.H(client_key)
        client_sig = self.HMAC(stored_key, self._soup)
        client_proof = XOR(client_key, client_sig)
        r += b",p=" + b64encode(client_proof).replace(b"\n", b"")
        server_key = self.HMAC(self.values["SaltedPassword"], b"Server Key")
        self.server_sig = self.HMAC(server_key, self._soup)
        return r
示例#26
0
    def response(self):
        """
        """
        vitals = ['username']
        if not self.has_values(['key_hash']):
            vitals.append('password')
        self.check_values(vitals)

        resp = {}
        if 'auth-int' in self._qops:
            self._qop = b'auth-int'
        resp['qop'] = self._qop
        if 'realm' in self.values:
            resp['realm'] = quote(self.values['realm'])

        resp['username'] = quote(bytes(self.values['username']))
        resp['nonce'] = quote(self.values['nonce'])
        if self.values['nc']:
            self._cnonce = self.values['cnonce']
        else:
            self._cnonce = bytes('%s' % random.random())[2:]
        resp['cnonce'] = quote(self._cnonce)
        self.values['nc'] += 1
        resp['nc'] = bytes('%08x' % self.values['nc'])

        service = bytes(self.sasl.service)
        host = bytes(self.sasl.host)
        self._digest_uri = service + b'/' + host
        resp['digest-uri'] = quote(self._digest_uri)

        a2 = b'AUTHENTICATE:' + self._digest_uri
        if self._qop != b'auth':
            a2 += b':00000000000000000000000000000000'
            resp['maxbuf'] = b'16777215'  # 2**24-1
        resp['response'] = self.gen_hash(a2)
        return b','.join([bytes(k) + b'=' + bytes(v) for k, v in resp.items()])
示例#27
0
    def response(self):
        """
        """
        vitals = ["username"]
        if not self.has_values(["key_hash"]):
            vitals.append("password")
        self.check_values(vitals)

        resp = {}
        if "auth-int" in self._qops:
            self._qop = b"auth-int"
        resp["qop"] = self._qop
        if "realm" in self.values:
            resp["realm"] = quote(self.values["realm"])

        resp["username"] = quote(bytes(self.values["username"]))
        resp["nonce"] = quote(self.values["nonce"])
        if self.values["nc"]:
            self._cnonce = self.values["cnonce"]
        else:
            self._cnonce = bytes("%s" % random.random())[2:]
        resp["cnonce"] = quote(self._cnonce)
        self.values["nc"] += 1
        resp["nc"] = bytes("%08x" % self.values["nc"])

        service = bytes(self.sasl.service)
        host = bytes(self.sasl.host)
        self._digest_uri = service + b"/" + host
        resp["digest-uri"] = quote(self._digest_uri)

        a2 = b"AUTHENTICATE:" + self._digest_uri
        if self._qop != b"auth":
            a2 += b":00000000000000000000000000000000"
            resp["maxbuf"] = b"16777215"  # 2**24-1
        resp["response"] = self.gen_hash(a2)
        return b",".join([bytes(k) + b"=" + bytes(v) for k, v in resp.items()])
示例#28
0
    def response(self):
        """
        """
        vitals = ['username']
        if not self.has_values(['key_hash']):
            vitals.append('password')
        self.check_values(vitals)

        resp = {}
        if 'auth-int' in self._qops:
            self._qop = b'auth-int'
        resp['qop'] = self._qop
        if 'realm' in self.values:
            resp['realm'] = quote(self.values['realm'])

        resp['username'] = quote(bytes(self.values['username']))
        resp['nonce'] = quote(self.values['nonce'])
        if self.values['nc']:
            self._cnonce = self.values['cnonce']
        else:
            self._cnonce = bytes('%s' % random.random())[2:]
        resp['cnonce'] = quote(self._cnonce)
        self.values['nc'] += 1
        resp['nc'] = bytes('%08x' % self.values['nc'])

        service = bytes(self.sasl.service)
        host = bytes(self.sasl.host)
        self._digest_uri = service + b'/' + host
        resp['digest-uri'] = quote(self._digest_uri)

        a2 = b'AUTHENTICATE:' + self._digest_uri
        if self._qop != b'auth':
            a2 += b':00000000000000000000000000000000'
            resp['maxbuf'] = b'16777215'  # 2**24-1
        resp['response'] = self.gen_hash(a2)
        return b','.join([bytes(k) + b'=' + bytes(v) for k, v in resp.items()])
示例#29
0
 def get_value(self):
     if not self['mechanism'] in self.plain_mechs:
         return base64.b64decode(bytes(self.xml.text))
     else:
         return self.xml.text
示例#30
0
文件: stanza.py 项目: ekini/SleekXMPP
 def set_value(self, value):
     self.xml.text = ''
     if value:
         self.xml.text = b64encode(bytes(value))
示例#31
0
文件: stanza.py 项目: ekini/SleekXMPP
 def get_value(self):
     if self.xml.text:
         return b64decode(bytes(self.xml.text))
     return ''
示例#32
0
 def set_value(self, values):
     self.xml.text = bytes(base64.b64encode(values)).decode('utf-8')
示例#33
0
 def get_value(self):
     return base64.b64decode(bytes(self.xml.text))
示例#34
0
 def process(self, challenge=None):
     return bytes(self.values['access_token'])
示例#35
0
 def get_binval(self):
     parent = self.parent()
     xml = parent.find('{%s}BINVAL' % self.namespace)
     if xml is not None:
         return base64.b64decode(bytes(xml.text))
     return b''
示例#36
0
 def get_value(self):
     return base64.b64decode(bytes(self.xml.text))
示例#37
0
def to_b64(data):
    return bytes(base64.b64encode(bytes(data))).decode('utf-8')
示例#38
0
def from_b64(data):
    return bytes(base64.b64decode(bytes(data))).decode('utf-8')
示例#39
0
 def process(self, challenge=None):
     return bytes(self.values['access_token'])
示例#40
0
 def process(self, challenge=None):
     email = bytes(self.values['email'])
     token = bytes(self.values['access_token'])
     return b'\x00' + email + b'\x00' + token
示例#41
0
 def set_value(self, values):
     self.xml.text = bytes(base64.b64encode(values)).decode('utf-8')
示例#42
0
 def process(self, challenge=None):
     email = bytes(self.values['email'])
     token = bytes(self.values['access_token'])
     return b'\x00' + email + b'\x00' + token
示例#43
0
文件: auth.py 项目: taoGit/SleekXMPP
 def get_value(self):
     if not self['mechanism'] in self.plain_mechs:
         return base64.b64decode(bytes(self.xml.text))
     else:
         return self.xml.text