Merge lp:~intellectronica/launchpad/revert-production-devel-mess into lp:launchpad/db-devel

Proposed by Eleanor Berger
Status: Merged
Approved by: Björn Tillenius
Approved revision: 9089
Merge reported by: Björn Tillenius
Merged at revision: not available
Proposed branch: lp:~intellectronica/launchpad/revert-production-devel-mess
Merge into: lp:launchpad/db-devel
Diff against target: 292 lines (+155/-23) (has conflicts)
6 files modified
.bzrignore (+4/-0)
lib/canonical/launchpad/pagetests/standalone/xx-offsite-form-post.txt (+22/-6)
lib/canonical/launchpad/testing/browser.py (+20/-0)
lib/canonical/launchpad/webapp/publication.py (+26/-5)
lib/lp/archiveuploader/dscfile.py (+28/-12)
lib/lp/archiveuploader/tests/test_dscfile.py (+55/-0)
Text conflict in .bzrignore
To merge this branch: bzr merge lp:~intellectronica/launchpad/revert-production-devel-mess
Reviewer Review Type Date Requested Status
Björn Tillenius (community) Approve
Review via email: mp+21052@code.launchpad.net

Description of the change

This branch reverts revisions 9086, 9084 and 9083. It corrects a previous attempt at reverting code which I haven't executed correctly, and fixes the build error in current production-devel.

To post a comment you must log in.
Revision history for this message
Björn Tillenius (bjornt) wrote :

On Wed, Mar 10, 2010 at 01:42:25PM -0000, Tom Berger wrote:

> === modified file '.bzrignore'
> --- .bzrignore 2010-03-09 02:42:40 +0000
> +++ .bzrignore 2010-03-10 13:42:24 +0000
> @@ -60,5 +60,9 @@
> .testrepository
> .memcache.pid
> ./pipes
> +<<<<<<< TREE
> lib/canonical/launchpad/apidoc/wadl-development-*.xml
> tags.new
> +=======
> +tags.new
> +>>>>>>> MERGE-SOURCE

This doesn't look right. However, it seems like you specified the wrong
merge target. I got the branch, and confirmed that the diff against
r9082 contains only the diff of r9085, so it looks good to be merged
into production-devel.

    vote approve

--
Björn Tillenius | https://launchpad.net/~bjornt

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-03-09 02:42:40 +0000
3+++ .bzrignore 2010-03-10 13:42:24 +0000
4@@ -60,5 +60,9 @@
5 .testrepository
6 .memcache.pid
7 ./pipes
8+<<<<<<< TREE
9 lib/canonical/launchpad/apidoc/wadl-development-*.xml
10 tags.new
11+=======
12+tags.new
13+>>>>>>> MERGE-SOURCE
14
15=== modified file 'lib/canonical/launchpad/pagetests/standalone/xx-offsite-form-post.txt'
16--- lib/canonical/launchpad/pagetests/standalone/xx-offsite-form-post.txt 2009-07-09 19:48:42 +0000
17+++ lib/canonical/launchpad/pagetests/standalone/xx-offsite-form-post.txt 2010-03-10 13:42:24 +0000
18@@ -1,9 +1,7 @@
19 = Referrer Checking on Form Posts =
20
21 To help mitigate cross site request forgery attacks, we check that the
22-referrer for a form post is either not present or is a URI from one of
23-the Launchpad sites.
24-
25+referrer for a form post exists and is a URI from one of the Launchpad sites.
26
27 First a helper to set up a browser object that doesn't handle the
28 "Referer" header automatically. We need to poke into the internal
29@@ -43,15 +41,33 @@
30 OffsiteFormPostError: not a url
31
32
33-We do allow the post if there is no referrer:
34+It also fails if there is no referrer.
35+
36+Note that we have to set up a monkeypatch to test this in order to work
37+around Zope bug 98437 (https://bugs.edge.launchpad.net/zope3/+bug/98437).
38+
39+ >>> from canonical.launchpad.webapp.servers import LaunchpadBrowserRequest
40+ >>> original_init = LaunchpadBrowserRequest.__init__
41+ >>> def __init__(self, body_instream, environ, response=None):
42+ ... if environ.get('HTTP_REFERER') == 'localhost':
43+ ... # When this line is not printed, the monkeypatch can be removed!
44+ ... print 'MONKEYPATCH ACTIVATED'
45+ ... del environ['HTTP_REFERER']
46+ ... original_init(self, body_instream, environ, response=None)
47+ ...
48+ >>> LaunchpadBrowserRequest.__init__ = __init__
49
50 >>> browser = setupBrowserWithReferrer(None)
51 >>> browser.open('http://launchpad.dev/people/+newteam')
52+ MONKEYPATCH ACTIVATED
53 >>> browser.getControl('Name', index=0).value = 'team3'
54 >>> browser.getControl('Display Name').value = 'Team 3'
55 >>> browser.getControl('Create').click()
56- >>> print browser.url
57- http://launchpad.dev/~team3
58+ Traceback (most recent call last):
59+ ...
60+ OffsiteFormPostError: No value for REFERER header
61+
62+ >>> LaunchpadBrowserRequest.__init__ = original_init
63
64
65 Or if the referrer is from a site managed by launchpad:
66
67=== modified file 'lib/canonical/launchpad/testing/browser.py'
68--- lib/canonical/launchpad/testing/browser.py 2010-02-10 18:07:02 +0000
69+++ lib/canonical/launchpad/testing/browser.py 2010-03-10 13:42:24 +0000
70@@ -94,6 +94,26 @@
71 super(Browser, self)._changed()
72 transaction.commit()
73
74+ def _clickSubmit(self, form, control, coord):
75+ # XXX gary 2010-03-08 bug=98437
76+ # This change is taken from
77+ # https://bugs.edge.launchpad.net/zope3/+bug/98437/comments/9 . It
78+ # should be pushed upstream, per that comment.
79+ labels = control.get_labels()
80+ if labels:
81+ label = labels[0].text
82+ else:
83+ label = None
84+ self.mech_browser.form = form
85+ self._start_timer()
86+ try:
87+ self.mech_browser.submit(id=control.id, name=control.name,
88+ label=label, coord=coord)
89+ except Exception, e:
90+ fix_exception_name(e)
91+ raise
92+ self._stop_timer()
93+
94
95 def setUp(test):
96 """Set up appserver tests."""
97
98=== modified file 'lib/canonical/launchpad/webapp/publication.py'
99--- lib/canonical/launchpad/webapp/publication.py 2010-03-04 22:42:07 +0000
100+++ lib/canonical/launchpad/webapp/publication.py 2010-03-10 13:42:24 +0000
101@@ -38,7 +38,8 @@
102 from zope.event import notify
103 from zope.interface import implements, providedBy
104 from zope.publisher.interfaces import IPublishTraverse, Retry
105-from zope.publisher.interfaces.browser import IDefaultSkin, IBrowserRequest
106+from zope.publisher.interfaces.browser import (
107+ IDefaultSkin, IBrowserRequest, IBrowserApplicationRequest)
108 from zope.publisher.publish import mapply
109 from zope.security.proxy import removeSecurityProxy
110 from zope.security.management import newInteraction
111@@ -63,6 +64,7 @@
112 from canonical.launchpad.webapp.menu import structured
113 from canonical.launchpad.webapp.opstats import OpStats
114 from lazr.uri import URI, InvalidURIError
115+from lazr.restful.interfaces import IWebServiceClientRequest
116 from canonical.launchpad.webapp.vhosts import allvhosts
117
118
119@@ -312,9 +314,9 @@
120
121 The OffsiteFormPostError exception is raised if the following
122 holds true:
123- 1. the request method is POST
124- 2. the HTTP referer header is not empty
125- 3. the host portion of the referrer is not a registered vhost
126+ 1. the request method is POST *AND*
127+ 2. a. the HTTP referer header is empty *OR*
128+ b. the host portion of the referrer is not a registered vhost
129 """
130 if request.method != 'POST':
131 return
132@@ -324,9 +326,28 @@
133 # form posts.
134 if request['PATH_INFO'] == '/+openid':
135 return
136+ if (IWebServiceClientRequest.providedBy(request) or
137+ not IBrowserRequest.providedBy(request) or
138+ 'oauth_consumer_key' in request.form or
139+ 'oauth_token' in request.form):
140+ # We only want to check for the referrer header if we are in
141+ # the middle of a browser request. If it is a webservice
142+ # request (which extends a normal browser request) or an
143+ # XMLRPC request (which doesn't), we can just return.
144+ # Checking for an oauth request is messy, because it is
145+ # still a browser request. Even though it is far from
146+ # satisfying, we check for the specified form fields because
147+ # it works and another better approach has not yet come to
148+ # light.
149+ # XXX gary 2010-03-09 bug=535122
150+ # Actually, the oauth_token should always be in a normal POST
151+ # request with a REFERER header, so we should be able to remove
152+ # that condition when the launchpadlib bug referenced above is
153+ # fixed.
154+ return
155 referrer = request.getHeader('referer') # match HTTP spec misspelling
156 if not referrer:
157- return
158+ raise OffsiteFormPostError('No value for REFERER header')
159 # XXX: jamesh 2007-04-26 bug=98437:
160 # The Zope testing infrastructure sets a default (incorrect)
161 # referrer value of "localhost" or "localhost:9000" if no
162
163=== modified file 'lib/lp/archiveuploader/dscfile.py'
164--- lib/lp/archiveuploader/dscfile.py 2010-02-16 02:30:15 +0000
165+++ lib/lp/archiveuploader/dscfile.py 2010-03-10 13:42:24 +0000
166@@ -13,6 +13,7 @@
167 'SignableTagFile',
168 'DSCFile',
169 'DSCUploadedFile',
170+ 'findCopyright',
171 ]
172
173 import apt_pkg
174@@ -524,18 +525,8 @@
175 # XXX cprov 20070713: We should access only the expected directory
176 # name (<sourcename>-<no_epoch(no_revision(version))>).
177
178- # Instead of trying to predict the unpacked source directory name,
179- # we simply use glob to retrive everything like:
180- # 'tempdir/*/debian/copyright'
181- globpath = os.path.join(tmpdir, "*", "debian/copyright")
182- for fullpath in glob.glob(globpath):
183- if not os.path.exists(fullpath):
184- continue
185- self.logger.debug("Copying copyright contents.")
186- self.copyright = open(fullpath).read().strip()
187-
188- if self.copyright is None:
189- yield UploadWarning("No copyright file found.")
190+ for error in findCopyright(self, tmpdir, self.logger):
191+ yield error
192
193 self.logger.debug("Cleaning up source tree.")
194 try:
195@@ -676,6 +667,31 @@
196 yield error
197
198
199+def findCopyright(dsc_file, source_dir, logger):
200+ """Find and store any debian/copyright.
201+
202+ :param dsc_file: A DSCFile object where the copyright will be stored.
203+ :param source_dir: The directory where the source was extracted.
204+ :param logger: A logger object for debug output.
205+ """
206+ # Instead of trying to predict the unpacked source directory name,
207+ # we simply use glob to retrive everything like:
208+ # 'tempdir/*/debian/copyright'
209+ globpath = os.path.join(source_dir, "*", "debian/copyright")
210+ for fullpath in glob.glob(globpath):
211+ if not os.path.exists(fullpath):
212+ continue
213+ if os.path.islink(fullpath):
214+ yield UploadError(
215+ "Symbolic link for debian/copyright not allowed")
216+ return
217+ logger.debug("Copying copyright contents.")
218+ dsc_file.copyright = open(fullpath).read().strip()
219+
220+ if dsc_file.copyright is None:
221+ yield UploadWarning("No copyright file found.")
222+
223+
224 def check_format_1_0_files(filename, file_type_counts, component_counts,
225 bzip2_count):
226 """Check that the given counts of each file type suit format 1.0.
227
228=== added file 'lib/lp/archiveuploader/tests/test_dscfile.py'
229--- lib/lp/archiveuploader/tests/test_dscfile.py 1970-01-01 00:00:00 +0000
230+++ lib/lp/archiveuploader/tests/test_dscfile.py 2010-03-10 13:42:24 +0000
231@@ -0,0 +1,55 @@
232+# Copyright 2010 Canonical Ltd. This software is licensed under the
233+# GNU Affero General Public License version 3 (see the file LICENSE).
234+
235+"""Test dscfile.py"""
236+
237+__metaclass__ = type
238+
239+import os
240+import unittest
241+
242+from lp.archiveuploader.dscfile import findCopyright
243+from lp.archiveuploader.nascentuploadfile import UploadError
244+from lp.archiveuploader.tests import mock_logger_quiet
245+from lp.testing import TestCase
246+
247+
248+class TestDscFile(TestCase):
249+
250+ class MockDSCFile:
251+ copyright = None
252+
253+ def setUp(self):
254+ super(TestDscFile, self).setUp()
255+ self.tmpdir = self.makeTemporaryDirectory()
256+ self.dir_path = os.path.join(self.tmpdir, "foo", "debian")
257+ os.makedirs(self.dir_path)
258+ self.file_path = os.path.join(self.dir_path, "copyright")
259+ self.dsc_file = self.MockDSCFile()
260+
261+ def testBadDebianCopyright(self):
262+ """Test that a symlink instead of a real file will fail."""
263+ os.symlink("/etc/passwd", self.file_path)
264+ errors = list(findCopyright(
265+ self.dsc_file, self.tmpdir, mock_logger_quiet))
266+
267+ self.assertEqual(len(errors), 1)
268+ self.assertIsInstance(errors[0], UploadError)
269+ self.assertEqual(
270+ errors[0].message,
271+ "Symbolic link for debian/copyright not allowed")
272+
273+ def testGoodDebianCopyright(self):
274+ copyright = "copyright for dummies"
275+ file = open(self.file_path, "w")
276+ file.write(copyright)
277+ file.close()
278+
279+ errors = list(findCopyright(
280+ self.dsc_file, self.tmpdir, mock_logger_quiet))
281+
282+ self.assertEqual(len(errors), 0)
283+ self.assertEqual(self.dsc_file.copyright, copyright)
284+
285+def test_suite():
286+ return unittest.TestLoader().loadTestsFromName(__name__)
287
288=== modified file 'lib/lp/code/model/branchjob.py'
289=== modified file 'lib/lp/code/model/branchmergeproposaljob.py'
290=== modified file 'lib/lp/code/model/tests/test_branchjob.py'
291=== modified file 'lib/lp/registry/browser/configure.zcml'
292=== modified file 'lib/lp/registry/browser/person.py'

Subscribers

People subscribed via source and target branches

to status/vote changes: