bwCGI.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #!/usr/bin/python3
  2. # bwCGI.py by Bill Weinman <http://bw.org/contact/>
  3. # Copyright (c) 1995-2010 The BearHeart Group, LLC
  4. #
  5. from cgi import FieldStorage
  6. import cgitb
  7. import os
  8. __version__ = '0.3.2'
  9. _cookie_var = 'HTTP_COOKIE'
  10. class bwCGI:
  11. ''' handy cgi stuff '''
  12. _header_state = False # True after header has been sent
  13. cgi_cookies = dict()
  14. cgi_headers = dict()
  15. def __init__(self, **kwargs):
  16. self.set_header('Content-type', kwargs.get('content_type', 'text/html'))
  17. if _cookie_var in os.environ:
  18. self.parse_cookies()
  19. def set_header(self, k, v):
  20. '''
  21. set a header
  22. use str for single value, list for multiples values
  23. '''
  24. if k in self.cgi_headers:
  25. if isinstance(self.cgi_headers[k], list): self.cgi_headers[k].append(v)
  26. else: self.cgi_headers[k] = [ self.cgi_headers[k], v ]
  27. else:
  28. self.cgi_headers[k] = str(v)
  29. return v
  30. def get_header(self, k):
  31. return self.cgi_headers.get(k, None)
  32. def send_header(self):
  33. ''' send the header(s), only once '''
  34. if self._header_state: return
  35. for k in self.cgi_headers:
  36. value = self.cgi_headers[k]
  37. if isinstance(value, list):
  38. for v in value: print('{}: {}'.format(k, v))
  39. else:
  40. print('{}: {}'.format(k, value))
  41. print()
  42. self._header_state = True
  43. cgitb.enable() # only after the header has been sent
  44. def set_cookie(self, key, value, **kwargs):
  45. ''' kwargs can include expires, path, or domain
  46. '''
  47. cookie = '{}={}'.format(str(key), str(value))
  48. if kwargs.keys():
  49. for k in kwargs.keys():
  50. cookie = '{}; {}={}'.format(cookie, k, kwargs[k])
  51. self.set_header('Set-Cookie', cookie)
  52. def parse_cookies(self):
  53. for ck in os.environ[_cookie_var].split(';'):
  54. lhs, rhs = ck.strip().split('=')
  55. self.cgi_cookies[lhs.strip()] = rhs.strip()
  56. def get_cookies(self):
  57. return self.cgi_cookies;
  58. def get_cookie(self, key):
  59. return self.cgi_cookies.get(key, None)
  60. def linkback(self):
  61. ''' return a relative URI for use as a linkback to this script '''
  62. for e in ( 'REQUEST_URI', 'SCRIPT_NAME' ):
  63. if e in os.environ:
  64. l = os.environ[e]
  65. break
  66. else: return '*** cannot make linkback ***'
  67. if '?' in l: l = l[0:l.find('?')]
  68. return os.path.basename(l)
  69. def vars(self):
  70. return FieldStorage()
  71. # utility methods
  72. def entity_encode(self, s):
  73. ''' convert unicode to XML entities
  74. returns encoded string
  75. '''
  76. outbytes = bytearray()
  77. for c in s:
  78. if ord(c) > 127:
  79. outbytes += bytes('&#{:d};'.format(ord(c)), encoding = 'utf_8')
  80. else: outbytes.append(ord(c))
  81. return str(outbytes, encoding = 'utf_8')
  82. def test():
  83. if _cookie_var not in os.environ:
  84. os.environ[_cookie_var] = 'one=1; two=2; three=3'
  85. cgi = bwCGI(content_type='text/plain')
  86. cgi.set_header('X-bwCGI', __version__)
  87. cgi.set_header('X-number', 42)
  88. cgi.set_cookie('one', 1)
  89. cgi.set_cookie('two', 2)
  90. cgi.set_cookie('three', 3, path='/', expires='31-Dec-2010 23:59:59 GMT', domain='.bw.org')
  91. cgi.set_cookie('five', 5)
  92. cgi.send_header() # should only see one set of headers
  93. cgi.send_header()
  94. cgi.send_header()
  95. print('Hello, CGI')
  96. print('header X-bwCGI:', cgi.get_header('X-bwCGI'))
  97. print('header Eggs:', cgi.get_header('Eggs'))
  98. print('Cookies:')
  99. print(sorted(cgi.get_cookies()))
  100. print('cookie one:', cgi.get_cookie('one'))
  101. print('cookie seven:', cgi.get_cookie('seven'))
  102. if __name__ == '__main__': test()