~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/codehosting/safe_open.py

Merge safe-open branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
205
205
            cls.transformFallbackLocationHook,
206
206
            'SafeBranchOpener.transformFallbackLocationHook')
207
207
 
208
 
    def checkAndFollowBranchReference(self, url):
 
208
    def checkAndFollowBranchReference(self, url, open_dir=None):
209
209
        """Check URL (and possibly the referenced URL) for safety.
210
210
 
211
211
        This method checks that `url` passes the policy's `checkOneURL`
222
222
                raise BranchLoopError()
223
223
            self._seen_urls.add(url)
224
224
            self.policy.checkOneURL(url)
225
 
            next_url = self.followReference(url)
 
225
            next_url = self.followReference(url, open_dir=open_dir)
226
226
            if next_url is None:
227
227
                return url
228
228
            url = next_url
243
243
            return url
244
244
        new_url, check = opener.policy.transformFallbackLocation(branch, url)
245
245
        if check:
246
 
            return opener.checkAndFollowBranchReference(new_url)
 
246
            return opener.checkAndFollowBranchReference(new_url,
 
247
                getattr(cls._threading_data, "open_dir"))
247
248
        else:
248
249
            return new_url
249
250
 
250
 
    def runWithTransformFallbackLocationHookInstalled(
251
 
            self, callable, *args, **kw):
 
251
    def _runWithTransformFallbackLocationHookInstalled(
 
252
            self, open_dir, callable, *args, **kw):
252
253
        assert (self.transformFallbackLocationHook in
253
254
                Branch.hooks['transform_fallback_location'])
254
255
        self._threading_data.opener = self
 
256
        self._threading_data.open_dir = open_dir
255
257
        try:
256
258
            return callable(*args, **kw)
257
259
        finally:
 
260
            del self._threading_data.open_dir
258
261
            del self._threading_data.opener
259
262
            # We reset _seen_urls here to avoid multiple calls to open giving
260
263
            # spurious loop exceptions.
261
264
            self._seen_urls = set()
262
265
 
263
 
    def followReference(self, url):
 
266
    def followReference(self, url, open_dir=None):
264
267
        """Get the branch-reference value at the specified url.
265
268
 
266
269
        This exists as a separate method only to be overriden in unit tests.
267
270
        """
268
 
        bzrdir = BzrDir.open(url)
 
271
        if open_dir is None:
 
272
            open_dir = BzrDir.open
 
273
        bzrdir = open_dir(url)
269
274
        return bzrdir.get_branch_reference()
270
275
 
271
 
    def open(self, url):
 
276
    def open(self, url, open_dir=None):
272
277
        """Open the Bazaar branch at url, first checking for safety.
273
278
 
274
279
        What safety means is defined by a subclasses `followReference` and
275
280
        `checkOneURL` methods.
276
281
        """
277
 
        url = self.checkAndFollowBranchReference(url)
278
 
        return self.runWithTransformFallbackLocationHookInstalled(
279
 
            Branch.open, url)
 
282
        url = self.checkAndFollowBranchReference(url, open_dir=open_dir)
 
283
        if open_dir is None:
 
284
            open_dir = BzrDir.open
 
285
        def open_branch(url):
 
286
            dir = open_dir(url)
 
287
            return dir.open_branch()
 
288
        return self._runWithTransformFallbackLocationHookInstalled(
 
289
            open_dir, open_branch, url)
280
290
 
281
291
 
282
292
def safe_open(allowed_scheme, url):