##// END OF EJS Templates
Added huge diff protection for RSS/ATOM feeds....
marcink -
r2783:a93c07ad beta
parent child Browse files
Show More
@@ -1,128 +1,134 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.feed
3 rhodecode.controllers.feed
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Feed controller for rhodecode
6 Feed controller for rhodecode
7
7
8 :created_on: Apr 23, 2010
8 :created_on: Apr 23, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27
27
28 from pylons import url, response, tmpl_context as c
28 from pylons import url, response, tmpl_context as c
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
32
32
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
34 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
35 from rhodecode.lib.base import BaseRepoController
35 from rhodecode.lib.base import BaseRepoController
36 from rhodecode.lib.diffs import DiffProcessor
36 from rhodecode.lib.diffs import DiffProcessor
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 class FeedController(BaseRepoController):
41 class FeedController(BaseRepoController):
42
42
43 @LoginRequired(api_access=True)
43 @LoginRequired(api_access=True)
44 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
44 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
45 'repository.admin')
45 'repository.admin')
46 def __before__(self):
46 def __before__(self):
47 super(FeedController, self).__before__()
47 super(FeedController, self).__before__()
48 #common values for feeds
48 #common values for feeds
49 self.description = _('Changes on %s repository')
49 self.description = _('Changes on %s repository')
50 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
50 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
51 self.language = 'en-us'
51 self.language = 'en-us'
52 self.ttl = "5"
52 self.ttl = "5"
53 self.feed_nr = 20
53 self.feed_nr = 20
54
54
55 def _get_title(self, cs):
55 def _get_title(self, cs):
56 return "%s" % (
56 return "%s" % (
57 h.shorter(cs.message, 160)
57 h.shorter(cs.message, 160)
58 )
58 )
59
59
60 def __changes(self, cs):
60 def __changes(self, cs):
61 changes = []
61 changes = []
62
62 _diff = cs.diff()
63 diffprocessor = DiffProcessor(cs.diff())
63 # we need to protect from parsing huge diffs here other way
64 # we can kill the server, 32*1024 chars is a reasonable limit
65 HUGE_DIFF = 32 * 1024
66 if len(_diff) > HUGE_DIFF:
67 changes = ['\n ' + _('Changeset was too big and was cut off...')]
68 return changes
69 diffprocessor = DiffProcessor(_diff)
64 stats = diffprocessor.prepare(inline_diff=False)
70 stats = diffprocessor.prepare(inline_diff=False)
65 for st in stats:
71 for st in stats:
66 st.update({'added': st['stats'][0],
72 st.update({'added': st['stats'][0],
67 'removed': st['stats'][1]})
73 'removed': st['stats'][1]})
68 changes.append('\n %(operation)s %(filename)s '
74 changes.append('\n %(operation)s %(filename)s '
69 '(%(added)s lines added, %(removed)s lines removed)'
75 '(%(added)s lines added, %(removed)s lines removed)'
70 % st)
76 % st)
71 return changes
77 return changes
72
78
73 def __get_desc(self, cs):
79 def __get_desc(self, cs):
74 desc_msg = []
80 desc_msg = []
75 desc_msg.append('%s %s %s:<br/>' % (cs.author, _('commited on'),
81 desc_msg.append('%s %s %s:<br/>' % (cs.author, _('commited on'),
76 h.fmt_date(cs.date)))
82 h.fmt_date(cs.date)))
77 desc_msg.append('<pre>')
83 desc_msg.append('<pre>')
78 desc_msg.append(cs.message)
84 desc_msg.append(cs.message)
79 desc_msg.append('\n')
85 desc_msg.append('\n')
80 desc_msg.extend(self.__changes(cs))
86 desc_msg.extend(self.__changes(cs))
81 desc_msg.append('</pre>')
87 desc_msg.append('</pre>')
82 return desc_msg
88 return desc_msg
83
89
84 def atom(self, repo_name):
90 def atom(self, repo_name):
85 """Produce an atom-1.0 feed via feedgenerator module"""
91 """Produce an atom-1.0 feed via feedgenerator module"""
86 feed = Atom1Feed(
92 feed = Atom1Feed(
87 title=self.title % repo_name,
93 title=self.title % repo_name,
88 link=url('summary_home', repo_name=repo_name,
94 link=url('summary_home', repo_name=repo_name,
89 qualified=True),
95 qualified=True),
90 description=self.description % repo_name,
96 description=self.description % repo_name,
91 language=self.language,
97 language=self.language,
92 ttl=self.ttl
98 ttl=self.ttl
93 )
99 )
94
100
95 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
101 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
96 feed.add_item(title=self._get_title(cs),
102 feed.add_item(title=self._get_title(cs),
97 link=url('changeset_home', repo_name=repo_name,
103 link=url('changeset_home', repo_name=repo_name,
98 revision=cs.raw_id, qualified=True),
104 revision=cs.raw_id, qualified=True),
99 author_name=cs.author,
105 author_name=cs.author,
100 description=''.join(self.__get_desc(cs)),
106 description=''.join(self.__get_desc(cs)),
101 pubdate=cs.date,
107 pubdate=cs.date,
102 )
108 )
103
109
104 response.content_type = feed.mime_type
110 response.content_type = feed.mime_type
105 return feed.writeString('utf-8')
111 return feed.writeString('utf-8')
106
112
107 def rss(self, repo_name):
113 def rss(self, repo_name):
108 """Produce an rss2 feed via feedgenerator module"""
114 """Produce an rss2 feed via feedgenerator module"""
109 feed = Rss201rev2Feed(
115 feed = Rss201rev2Feed(
110 title=self.title % repo_name,
116 title=self.title % repo_name,
111 link=url('summary_home', repo_name=repo_name,
117 link=url('summary_home', repo_name=repo_name,
112 qualified=True),
118 qualified=True),
113 description=self.description % repo_name,
119 description=self.description % repo_name,
114 language=self.language,
120 language=self.language,
115 ttl=self.ttl
121 ttl=self.ttl
116 )
122 )
117
123
118 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
124 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
119 feed.add_item(title=self._get_title(cs),
125 feed.add_item(title=self._get_title(cs),
120 link=url('changeset_home', repo_name=repo_name,
126 link=url('changeset_home', repo_name=repo_name,
121 revision=cs.raw_id, qualified=True),
127 revision=cs.raw_id, qualified=True),
122 author_name=cs.author,
128 author_name=cs.author,
123 description=''.join(self.__get_desc(cs)),
129 description=''.join(self.__get_desc(cs)),
124 pubdate=cs.date,
130 pubdate=cs.date,
125 )
131 )
126
132
127 response.content_type = feed.mime_type
133 response.content_type = feed.mime_type
128 return feed.writeString('utf-8')
134 return feed.writeString('utf-8')
General Comments 0
You need to be logged in to leave comments. Login now