1"""
2websocket - WebSocket client library for Python
3
4Copyright (C) 2010 Hiroki Ohtani(liris)
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1335  USA
20
21"""
22import six
23
24__all__ = ["NoLock", "validate_utf8", "extract_err_message"]
25
26
27class NoLock(object):
28
29    def __enter__(self):
30        pass
31
32    def __exit__(self, exc_type, exc_value, traceback):
33        pass
34
35try:
36    # If wsaccel is available we use compiled routines to validate UTF-8
37    # strings.
38    from wsaccel.utf8validator import Utf8Validator
39
40    def _validate_utf8(utfbytes):
41        return Utf8Validator().validate(utfbytes)[0]
42
43except ImportError:
44    # UTF-8 validator
45    # python implementation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
46
47    _UTF8_ACCEPT = 0
48    _UTF8_REJECT = 12
49
50    _UTF8D = [
51        # The first part of the table maps bytes to character classes that
52        # to reduce the size of the transition table and create bitmasks.
53        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
54        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
55        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57        1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
58        7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
59        8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
60        10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
61
62        # The second part is a transition table that maps a combination
63        # of a state of the automaton and a character class to a state.
64        0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
65        12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
66        12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
67        12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
68        12,36,12,12,12,12,12,12,12,12,12,12, ]
69
70    def _decode(state, codep, ch):
71        tp = _UTF8D[ch]
72
73        codep = (ch & 0x3f) | (codep << 6) if (
74            state != _UTF8_ACCEPT) else (0xff >> tp) & ch
75        state = _UTF8D[256 + state + tp]
76
77        return state, codep
78
79    def _validate_utf8(utfbytes):
80        state = _UTF8_ACCEPT
81        codep = 0
82        for i in utfbytes:
83            if six.PY2:
84                i = ord(i)
85            state, codep = _decode(state, codep, i)
86            if state == _UTF8_REJECT:
87                return False
88
89        return True
90
91
92def validate_utf8(utfbytes):
93    """
94    validate utf8 byte string.
95    utfbytes: utf byte string to check.
96    return value: if valid utf8 string, return true. Otherwise, return false.
97    """
98    return _validate_utf8(utfbytes)
99
100
101def extract_err_message(exception):
102    if exception.args:
103        return exception.args[0]
104    else:
105        return None
106