| | 1 | # -*- coding: utf-8 -*- |
| | 2 | # |
| | 3 | # Copyright (C) 2010 Edgewall Software |
| | 4 | # All rights reserved. |
| | 5 | # |
| | 6 | # This software is licensed as described in the file COPYING, which |
| | 7 | # you should have received as part of this distribution. The terms |
| | 8 | # are also available at http://trac.edgewall.org/wiki/TracLicense. |
| | 9 | # |
| | 10 | # This software consists of voluntary contributions made by many |
| | 11 | # individuals. For the exact contribution history, see the revision |
| | 12 | # history and logs, available at http://trac.edgewall.org/log/. |
| | 13 | |
| | 14 | import re |
| | 15 | |
| | 16 | from trac.config import Option |
| | 17 | from trac.core import Component, implements |
| | 18 | from trac.web.api import IRequestFilter |
| | 19 | |
| | 20 | |
| | 21 | class AltLinkLoginRewriter(Component): |
| | 22 | """Rewrite selected alternative format links to require authentication. |
| | 23 | |
| | 24 | This component rewrites alternative format links matching the regexp in |
| | 25 | `[web] altlink_rewrite` for authenticated users to redirect through |
| | 26 | `/login`, therefore requiring authentication. The default regexp matches |
| | 27 | all links containing a `format=rss` or `format=ics` query argument, |
| | 28 | therefore ensuring that e.g. RSS readers log in before requesting a feed. |
| | 29 | |
| | 30 | This component doesn't work with form-based login. |
| | 31 | """ |
| | 32 | |
| | 33 | implements(IRequestFilter) |
| | 34 | |
| | 35 | altlink_login_rewrite = Option('web', 'altlink_login_rewrite', |
| | 36 | r'.*\?(.*&)?format=(rss|ics)(&.*)?$', |
| | 37 | """Regexp pattern defining the alternative format links that should be |
| | 38 | rewritten to require authentication.""") |
| | 39 | |
| | 40 | _pattern = None |
| | 41 | |
| | 42 | # IRequestFilter methods |
| | 43 | |
| | 44 | def pre_process_request(self, req, handler): |
| | 45 | return handler |
| | 46 | |
| | 47 | def post_process_request(self, req, template, data, content_type): |
| | 48 | if req.authname and req.authname != 'anonymous': |
| | 49 | if self._pattern is None: |
| | 50 | self._pattern = re.compile(self.altlink_login_rewrite) |
| | 51 | for link in req.chrome.get('links', {}).get('alternate', []): |
| | 52 | href = link.get('href') |
| | 53 | if href is not None and self._pattern.match(href): |
| | 54 | link['href'] = req.href.login(referer=href) |
| | 55 | return template, data, content_type |