cms.middleware.multilingual: 90 total statements, 0.0% covered

Generated: Wed 2013-03-13 10:33 CET

Source file: /media/Envs/Envs/filer-gallery/lib/python2.7/site-packages/cms/middleware/multilingual.py

Stats: 0 executed, 80 missed, 10 excluded, 59 ignored

  1. # -*- coding: utf-8 -*-
  2. from __future__ import with_statement
  3. from cms.test_utils.util.context_managers import SettingsOverride
  4. from cms.utils.i18n import get_default_language
  5. from django.conf import settings
  6. from django.core.urlresolvers import reverse
  7. from django.middleware.locale import LocaleMiddleware
  8. from django.utils import translation
  9. import re
  10. import urllib
  11. import urlparse
  12. HAS_LANG_PREFIX_RE = re.compile(r"^/(%s)/.*" % "|".join([re.escape(lang[0]) for lang in settings.CMS_LANGUAGES]))
  13. def has_lang_prefix(path):
  14. check = HAS_LANG_PREFIX_RE.match(path)
  15. if check is not None:
  16. return check.group(1)
  17. else:
  18. return False
  19. def patch_response(content, pages_root, language):
  20. # Customarily user pages are served from http://the.server.com/~username/
  21. # When a user uses django-cms for his pages, the '~' of the url appears quoted in href links.
  22. # We have to quote pages_root for the regular expression to match.
  23. #
  24. # The used regex is quite complex. The exact pattern depends on the used settings.
  25. # The regex extracts the path of the url without the leading page root, but only matches urls
  26. # that don't already contain a language string or aren't considered multilingual.
  27. #
  28. # Here is an annotated example pattern (_r_ is a shorthand for the value of pages_root):
  29. # pattern: <a([^>]+)href=("|\')(?=_r_)(?!(/fr/|/de/|/en/|/pt-br/|/media/|/media/admin/))(_r_(.*?))("|\')(.*?)>
  30. # |-\1--| |-\2-| |---------------------\3---------------------| | |-\5--|||-\6-||-\7-|
  31. # |---\4---|
  32. # input (_r_=/): <a href="/admin/password_change/" class="foo">
  33. # matched groups: (u' ', None, u'/admin/password_change/', u'admin/password_change/', u' class="foo"')
  34. #
  35. # Notice that (?=...) and (?!=...) do not consume input or produce a group in the match object.
  36. # If the regex matches, the extracted path we want is stored in the fourth group (\4).
  37. quoted_root = urllib.quote(pages_root)
  38. ignore_paths = ['%s%s/' % (quoted_root, lang[0]) for lang in settings.CMS_LANGUAGES]
  39. ignore_paths += [settings.MEDIA_URL]
  40. if getattr(settings, 'ADMIN_MEDIA_PREFIX', False):
  41. ignore_paths += [settings.ADMIN_MEDIA_PREFIX]
  42. if getattr(settings,'STATIC_URL', False):
  43. ignore_paths += [settings.STATIC_URL]
  44. HREF_URL_FIX_RE = re.compile(ur'<a([^>]+)href=("|\')(?=%s)(?!(%s))(%s(.*?))("|\')(.*?)>' % (
  45. quoted_root,
  46. "|".join([re.escape(p) for p in ignore_paths]),
  47. quoted_root
  48. ))
  49. # Unlike in href links, the '~' (see above) the '~' in form actions appears unquoted.
  50. #
  51. # For understanding this regex, please read the documentation for HREF_URL_FIX_RE above.
  52. ignore_paths = ['%s%s/' % (pages_root, lang[0]) for lang in settings.CMS_LANGUAGES]
  53. ignore_paths += [settings.MEDIA_URL]
  54. if getattr(settings, 'ADMIN_MEDIA_PREFIX', False):
  55. ignore_paths += [settings.ADMIN_MEDIA_PREFIX]
  56. if getattr(settings,'STATIC_URL', False):
  57. ignore_paths += [settings.STATIC_URL]
  58. FORM_URL_FIX_RE = re.compile(ur'<form([^>]+)action=("|\')(?=%s)(?!(%s))(%s(.*?))("|\')(.*?)>' % (
  59. pages_root,
  60. "|".join([re.escape(p) for p in ignore_paths]),
  61. pages_root
  62. ))
  63. content = HREF_URL_FIX_RE.sub(ur'<a\1href=\2/%s%s\5\6\7>' % (language, pages_root), content)
  64. content = FORM_URL_FIX_RE.sub(ur'<form\1action=\2/%s%s\5\6\7>' % (language, pages_root), content).encode("utf8")
  65. return content
  66. class MultilingualURLMiddleware(object):
  67. def get_language_from_request(self, request):
  68. prefix = has_lang_prefix(request.path_info)
  69. lang = None
  70. if prefix:
  71. request.path = "/" + "/".join(request.path.split("/")[2:])
  72. request.path_info = "/" + "/".join(request.path_info.split("/")[2:])
  73. t = prefix
  74. if t in settings.CMS_FRONTEND_LANGUAGES:
  75. lang = t
  76. if not lang:
  77. languages = []
  78. for frontend_lang in settings.CMS_FRONTEND_LANGUAGES:
  79. languages.append((frontend_lang,frontend_lang))
  80. with SettingsOverride(LANGUAGES=languages):
  81. lang = translation.get_language_from_request(request)
  82. if not lang:
  83. lang = get_default_language()
  84. old_lang = None
  85. if hasattr(request, "session") and request.session.get("django_language", None):
  86. old_lang = request.session["django_language"]
  87. if not old_lang and hasattr(request, "COOKIES") and request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME, None):
  88. old_lang = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
  89. if old_lang != lang:
  90. if hasattr(request, 'session'):
  91. request.session['django_language'] = lang
  92. return lang
  93. def process_request(self, request):
  94. language = self.get_language_from_request(request)
  95. translation.activate(language)
  96. request.LANGUAGE_CODE = language
  97. def process_response(self, request, response):
  98. language = getattr(request, 'LANGUAGE_CODE', self.get_language_from_request(request))
  99. local_middleware = LocaleMiddleware()
  100. response = local_middleware.process_response(request, response)
  101. path = unicode(request.path)
  102. if not hasattr(request, 'session') and request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) != language:
  103. response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)
  104. # note: pages_root is assumed to end in '/'.
  105. # testing this and throwing an exception otherwise, would probably be a good idea
  106. if (not path.startswith(settings.MEDIA_URL) and
  107. not path.startswith(settings.STATIC_URL) and
  108. not (getattr(settings, 'STATIC_URL', False) and path.startswith(settings.STATIC_URL)) and
  109. response.status_code == 200 and
  110. response.has_header('Content-Type') and
  111. response._headers['content-type'][1].split(';')[0] == "text/html"):
  112. pages_root = urllib.unquote(reverse("pages-root"))
  113. try:
  114. decoded_response = response.content.decode('utf-8')
  115. except UnicodeDecodeError:
  116. decoded_response = response.content
  117. response.content = patch_response(
  118. decoded_response,
  119. pages_root,
  120. request.LANGUAGE_CODE
  121. )
  122. if response.status_code == 301 or response.status_code == 302:
  123. location = response['Location']
  124. if location.startswith('.'):
  125. location = urlparse.urljoin(request.path, location)
  126. response['Location'] = location
  127. if (not has_lang_prefix(location) and location.startswith("/") and
  128. not location.startswith(settings.MEDIA_URL) and
  129. not (getattr(settings, 'STATIC_URL', False) and location.startswith(settings.STATIC_URL))):
  130. response['Location'] = "/%s%s" % (language, location)
  131. if request.COOKIES.get('django_language') != language:
  132. response.set_cookie("django_language", language)
  133. return response