_utils.py 3.7 KB

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