# Path: xclib/utf8.py
# def utf8(u, opts='strict'):
#     return u.encode('utf-8', opts)
# 
# def unutf8(u, opts='strict'):
#     if opts == 'illegal':
#         try:
#             return u.decode('utf-8', 'strict')
#         except UnicodeError:
#             dec = u.decode('utf-8', 'ignore')
#             logging.error('Illegal UTF-8 sequence: %r' % dec)
#             sys.stderr.write('Illegal UTF-8 sequence: %r\n' % dec)
#             traceback.print_exc()
#             return 'illegal-utf8-sequence-' + dec
#     else:
#         return u.decode('utf-8', opts)


import logging
import hashlib
import hmac
import bcrypt
from datetime import datetime, timedelta
from struct import pack, unpack
from base64 import b64decode
from xclib.utf8 import utf8, unutf8
    def auth_with_cache(self, unreach=False):
        if self.ctx.db.cache_storage == 'none':
            return False
        jid = self.username + '@' + self.domain
        now = self.now # For tests
        for row in self.ctx.db.cache.execute('SELECT pwhash, remoteauth, anyauth FROM authcache WHERE jid = ?', (jid,)):
            (pwhash, tsv, tsa) = row
            if ((tsa + timedelta(seconds=self.ctx.ttls['query']) > now
                and tsv + timedelta(seconds=self.ctx.ttls['verify']) > now)
              or (unreach and tsv + timedelta(seconds=self.ctx.ttls['unreach']) > now)):
                if self.checkpw(pwhash):
                    # Update does not need to be atomic
                    self.ctx.db.cache.execute('UPDATE authcache SET anyauth = ? WHERE jid = ?', (now, jid))
                    return True
        return False

    def auth_update_cache(self):
        if self.ctx.db.cache_storage == 'none':
            return False
        jid = self.username + '@' + self.domain
        now = self.now
        try:
            if self.ctx.db.cache_storage == 'memory':
                rounds = self.ctx.bcrypt_rounds[1]
            else:
                rounds = self.ctx.bcrypt_rounds[0]
            salt = bcrypt.gensalt(rounds=rounds)
        except TypeError:
            # Old versions of bcrypt() apparently do not support the rounds option
            salt = bcrypt.gensalt()

# Path: xclib/utf8.py
# def utf8(u, opts='strict'):
#     return u.encode('utf-8', opts)
# 
# def unutf8(u, opts='strict'):
#     if opts == 'illegal':
#         try:
#             return u.decode('utf-8', 'strict')
#         except UnicodeError:
#             dec = u.decode('utf-8', 'ignore')
#             logging.error('Illegal UTF-8 sequence: %r' % dec)
#             sys.stderr.write('Illegal UTF-8 sequence: %r\n' % dec)
#             traceback.print_exc()
#             return 'illegal-utf8-sequence-' + dec
#     else:
#         return u.decode('utf-8', opts)


# Path: xclib/auth.py
import logging
import hashlib
import hmac
import bcrypt
from datetime import datetime, timedelta
from struct import pack, unpack
from base64 import b64decode
from xclib.utf8 import utf8, unutf8

    def auth_with_cache(self, unreach=False):
        if self.ctx.db.cache_storage == 'none':
            return False
        jid = self.username + '@' + self.domain
        now = self.now # For tests
        for row in self.ctx.db.cache.execute('SELECT pwhash, remoteauth, anyauth FROM authcache WHERE jid = ?', (jid,)):
            (pwhash, tsv, tsa) = row
            if ((tsa + timedelta(seconds=self.ctx.ttls['query']) > now
                and tsv + timedelta(seconds=self.ctx.ttls['verify']) > now)
              or (unreach and tsv + timedelta(seconds=self.ctx.ttls['unreach']) > now)):
                if self.checkpw(pwhash):
                    # Update does not need to be atomic
                    self.ctx.db.cache.execute('UPDATE authcache SET anyauth = ? WHERE jid = ?', (now, jid))
                    return True
        return False

    def auth_update_cache(self):
        if self.ctx.db.cache_storage == 'none':
            return False
        jid = self.username + '@' + self.domain
        now = self.now
        try:
            if self.ctx.db.cache_storage == 'memory':
                rounds = self.ctx.bcrypt_rounds[1]
            else:
                rounds = self.ctx.bcrypt_rounds[0]
            salt = bcrypt.gensalt(rounds=rounds)
        except TypeError:
            # Old versions of bcrypt() apparently do not support the rounds option
            salt = bcrypt.gensalt()

        pwhash = unutf8(bcrypt.hashpw(utf8(self.password), salt))