Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import warnings 

2 

3from webob.compat import ( 

4 escape, 

5 string_types, 

6 text_, 

7 text_type, 

8 ) 

9 

10from webob.headers import _trans_key 

11 

12def html_escape(s): 

13 """HTML-escape a string or object 

14 

15 This converts any non-string objects passed into it to strings 

16 (actually, using ``unicode()``). All values returned are 

17 non-unicode strings (using ``&#num;`` entities for all non-ASCII 

18 characters). 

19 

20 None is treated specially, and returns the empty string. 

21 """ 

22 if s is None: 

23 return '' 

24 __html__ = getattr(s, '__html__', None) 

25 if __html__ is not None and callable(__html__): 

26 return s.__html__() 

27 if not isinstance(s, string_types): 

28 __unicode__ = getattr(s, '__unicode__', None) 

29 if __unicode__ is not None and callable(__unicode__): 

30 s = s.__unicode__() 

31 else: 

32 s = str(s) 

33 s = escape(s, True) 

34 if isinstance(s, text_type): 

35 s = s.encode('ascii', 'xmlcharrefreplace') 

36 return text_(s) 

37 

38def header_docstring(header, rfc_section): 

39 if header.isupper(): 

40 header = _trans_key(header) 

41 major_section = rfc_section.split('.')[0] 

42 link = 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec%s.html#sec%s' % ( 

43 major_section, rfc_section) 

44 return "Gets and sets the ``%s`` header (`HTTP spec section %s <%s>`_)." % ( 

45 header, rfc_section, link) 

46 

47 

48def warn_deprecation(text, version, stacklevel): 

49 # version specifies when to start raising exceptions instead of warnings 

50 if version in ('1.2', '1.3', '1.4', '1.5', '1.6', '1.7'): 

51 raise DeprecationWarning(text) 

52 else: 

53 cls = DeprecationWarning 

54 warnings.warn(text, cls, stacklevel=stacklevel + 1) 

55 

56status_reasons = { 

57 # Status Codes 

58 # Informational 

59 100: 'Continue', 

60 101: 'Switching Protocols', 

61 102: 'Processing', 

62 

63 # Successful 

64 200: 'OK', 

65 201: 'Created', 

66 202: 'Accepted', 

67 203: 'Non-Authoritative Information', 

68 204: 'No Content', 

69 205: 'Reset Content', 

70 206: 'Partial Content', 

71 207: 'Multi Status', 

72 226: 'IM Used', 

73 

74 # Redirection 

75 300: 'Multiple Choices', 

76 301: 'Moved Permanently', 

77 302: 'Found', 

78 303: 'See Other', 

79 304: 'Not Modified', 

80 305: 'Use Proxy', 

81 307: 'Temporary Redirect', 

82 308: 'Permanent Redirect', 

83 

84 # Client Error 

85 400: 'Bad Request', 

86 401: 'Unauthorized', 

87 402: 'Payment Required', 

88 403: 'Forbidden', 

89 404: 'Not Found', 

90 405: 'Method Not Allowed', 

91 406: 'Not Acceptable', 

92 407: 'Proxy Authentication Required', 

93 408: 'Request Timeout', 

94 409: 'Conflict', 

95 410: 'Gone', 

96 411: 'Length Required', 

97 412: 'Precondition Failed', 

98 413: 'Request Entity Too Large', 

99 414: 'Request URI Too Long', 

100 415: 'Unsupported Media Type', 

101 416: 'Requested Range Not Satisfiable', 

102 417: 'Expectation Failed', 

103 418: "I'm a teapot", 

104 422: 'Unprocessable Entity', 

105 423: 'Locked', 

106 424: 'Failed Dependency', 

107 426: 'Upgrade Required', 

108 428: 'Precondition Required', 

109 429: 'Too Many Requests', 

110 451: 'Unavailable for Legal Reasons', 

111 431: 'Request Header Fields Too Large', 

112 

113 # Server Error 

114 500: 'Internal Server Error', 

115 501: 'Not Implemented', 

116 502: 'Bad Gateway', 

117 503: 'Service Unavailable', 

118 504: 'Gateway Timeout', 

119 505: 'HTTP Version Not Supported', 

120 507: 'Insufficient Storage', 

121 510: 'Not Extended', 

122 511: 'Network Authentication Required', 

123} 

124 

125# generic class responses as per RFC2616 

126status_generic_reasons = { 

127 1: 'Continue', 

128 2: 'Success', 

129 3: 'Multiple Choices', 

130 4: 'Unknown Client Error', 

131 5: 'Unknown Server Error', 

132} 

133 

134try: 

135 # py3.3+ have native comparison support 

136 from hmac import compare_digest 

137except ImportError: # pragma: nocover (Python 2.7.7 backported this) 

138 compare_digest = None 

139 

140def strings_differ(string1, string2, compare_digest=compare_digest): 

141 """Check whether two strings differ while avoiding timing attacks. 

142 

143 This function returns True if the given strings differ and False 

144 if they are equal. It's careful not to leak information about *where* 

145 they differ as a result of its running time, which can be very important 

146 to avoid certain timing-related crypto attacks: 

147 

148 http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf 

149 

150 .. versionchanged:: 1.5 

151 Support :func:`hmac.compare_digest` if it is available (Python 2.7.7+ 

152 and Python 3.3+). 

153 

154 """ 

155 len_eq = len(string1) == len(string2) 

156 if len_eq: 

157 invalid_bits = 0 

158 left = string1 

159 else: 

160 invalid_bits = 1 

161 left = string2 

162 right = string2 

163 

164 if compare_digest is not None: 

165 invalid_bits += not compare_digest(left, right) 

166 else: 

167 for a, b in zip(left, right): 

168 invalid_bits += a != b 

169 return invalid_bits != 0 

170