index.wsgi 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # CMS WSGI wrapper
  5. #
  6. # Copyright (C) 2011-2018 Michael Buesch <m@bues.ch>
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation, either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. import sys
  21. import atexit
  22. try:
  23. from urllib.parse import parse_qs
  24. except ImportError:
  25. from cgi import parse_qs
  26. sys.path.append("/var/cms") # workaround for old WSGI
  27. try:
  28. from cms_cython import *
  29. except ImportError as e:
  30. try:
  31. from cms import *
  32. except ImportError as e:
  33. raise Exception("Failed to import cms.py. "\
  34. "Wrong python-path in WSGIDaemonProcess?:\n" + str(e))
  35. cms = None
  36. maxPostContentLength = 0
  37. def __initCMS(environ):
  38. global cms
  39. global maxPostContentLength
  40. if cms:
  41. return # Already initialized
  42. try:
  43. domain = environ["cms.domain"]
  44. cmsBase = environ["cms.cmsBase"]
  45. wwwBase = environ["cms.wwwBase"]
  46. except KeyError as e:
  47. raise Exception("WSGI environment %s not set" % str(e))
  48. debug = False
  49. try:
  50. debug = stringBool(environ["cms.debug"])
  51. except KeyError as e:
  52. pass
  53. try:
  54. maxPostContentLength = int(environ["cms.maxPostContentLength"], 10)
  55. except (KeyError, ValueError) as e:
  56. pass
  57. # Initialize the CMS module
  58. cms = CMS(dbPath = cmsBase + "/db",
  59. wwwPath = wwwBase,
  60. domain = domain,
  61. debug = debug)
  62. atexit.register(cms.shutdown)
  63. def __recvBody(environ):
  64. try:
  65. body_len = int(environ["CONTENT_LENGTH"], 10)
  66. except (ValueError, KeyError) as e:
  67. body_len = 0
  68. try:
  69. body_type = environ["CONTENT_TYPE"]
  70. except KeyError as e:
  71. body_type = "text/plain"
  72. if body_len < 0 or \
  73. (maxPostContentLength >= 0 and\
  74. body_len > maxPostContentLength):
  75. body = body_type = None
  76. else:
  77. body = environ["wsgi.input"].read(body_len)
  78. return body, body_type
  79. #post_env = env.copy()
  80. #post_env['QUERY_STRING'] = ''
  81. #post = cgi.FieldStorage(
  82. # fp=env['wsgi.input'],
  83. # environ=post_env,
  84. # keep_blank_values=True
  85. # )
  86. def application(environ, start_response):
  87. __initCMS(environ)
  88. if cms.debug:
  89. startStamp = datetime.now()
  90. status = "200 OK"
  91. additional_headers = []
  92. method = environ["REQUEST_METHOD"].upper()
  93. path = environ["PATH_INFO"]
  94. query = parse_qs(environ["QUERY_STRING"])
  95. protocol = environ["wsgi.url_scheme"].lower()
  96. try:
  97. if method in {"GET", "HEAD"}:
  98. response_body, response_mime = cms.get(path, query, protocol)
  99. if method == "HEAD":
  100. response_body = b""
  101. elif method == "POST":
  102. body, body_type = __recvBody(environ)
  103. if body is None:
  104. response_body, response_mime, status = (
  105. b"POSTed data is too long\n",
  106. "text/plain",
  107. "405 Method Not Allowed"
  108. )
  109. else:
  110. response_body, response_mime = cms.post(path, query,
  111. body, body_type,
  112. protocol)
  113. else:
  114. response_body, response_mime, status = (
  115. b"INVALID REQUEST_METHOD\n",
  116. "text/plain",
  117. "405 Method Not Allowed"
  118. )
  119. except (CMSException) as e:
  120. status = e.httpStatus
  121. response_body, response_mime, additional_headers = cms.getErrorPage(e, protocol)
  122. if cms.debug and response_mime.startswith("text/html"):
  123. delta = datetime.now() - startStamp
  124. sec = float(delta.seconds) + float(delta.microseconds) / 1000000
  125. response_body += ("\n<!-- generated in %.3f seconds -->" % sec).encode("UTF-8")
  126. response_headers = [ ('Content-Type', response_mime),
  127. ('Content-Length', str(len(response_body))) ]
  128. response_headers.extend(additional_headers)
  129. start_response(status, response_headers)
  130. return (response_body,)