Adrià Vilanova Martínez | f19ea43 | 2024-01-23 20:20:52 +0100 | [diff] [blame] | 1 | # Copyright 2016 The Chromium Authors |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 4 | |
| 5 | """Issue Tracker code to serve out issue attachments. |
| 6 | |
| 7 | Summary of page classes: |
| 8 | AttachmentPage: Serve the content of an attachment w/ the appropriate |
| 9 | MIME type. |
| 10 | IssueAttachmentDeletion: Form handler for deleting attachments. |
| 11 | """ |
| 12 | from __future__ import print_function |
| 13 | from __future__ import division |
| 14 | from __future__ import absolute_import |
| 15 | |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 16 | import logging |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 17 | |
| 18 | from google.appengine.api import app_identity |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 19 | |
| 20 | from framework import exceptions |
| 21 | from framework import framework_constants |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 22 | from framework import gcs_helpers |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 23 | from framework import servlet |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 24 | from tracker import attachment_helpers |
| 25 | from tracker import tracker_helpers |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 26 | |
| 27 | |
| 28 | # This will likely appear blank or as a broken image icon in the browser. |
| 29 | NO_PREVIEW_ICON = '' |
| 30 | NO_PREVIEW_MIME_TYPE = 'image/png' |
| 31 | |
| 32 | |
| 33 | class AttachmentPage(servlet.Servlet): |
| 34 | """AttachmentPage serves issue attachments.""" |
| 35 | |
| 36 | def GatherPageData(self, mr): |
| 37 | """Parse the attachment ID from the request and serve its content. |
| 38 | |
| 39 | Args: |
| 40 | mr: commonly used info parsed from the request. |
| 41 | |
| 42 | Returns: dict of values used by EZT for rendering the page. |
| 43 | """ |
| 44 | if mr.signed_aid != attachment_helpers.SignAttachmentID(mr.aid): |
Adrià Vilanova Martínez | de94280 | 2022-07-15 14:06:55 +0200 | [diff] [blame] | 45 | self.abort(400, 'Please reload the issue page') |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 46 | |
| 47 | try: |
| 48 | attachment, _issue = tracker_helpers.GetAttachmentIfAllowed( |
| 49 | mr, self.services) |
| 50 | except exceptions.NoSuchIssueException: |
Adrià Vilanova Martínez | de94280 | 2022-07-15 14:06:55 +0200 | [diff] [blame] | 51 | self.abort(404, 'issue not found') |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 52 | except exceptions.NoSuchAttachmentException: |
Adrià Vilanova Martínez | de94280 | 2022-07-15 14:06:55 +0200 | [diff] [blame] | 53 | self.abort(404, 'attachment not found') |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 54 | except exceptions.NoSuchCommentException: |
Adrià Vilanova Martínez | de94280 | 2022-07-15 14:06:55 +0200 | [diff] [blame] | 55 | self.abort(404, 'comment not found') |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 56 | |
| 57 | if not attachment.gcs_object_id: |
Adrià Vilanova Martínez | de94280 | 2022-07-15 14:06:55 +0200 | [diff] [blame] | 58 | self.abort(404, 'attachment data not found') |
Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 59 | |
| 60 | bucket_name = app_identity.get_default_gcs_bucket_name() |
| 61 | |
| 62 | gcs_object_id = attachment.gcs_object_id |
| 63 | |
| 64 | logging.info('attachment id %d is %s', mr.aid, gcs_object_id) |
| 65 | |
| 66 | # By default GCS will return images and attachments displayable inline. |
| 67 | if mr.thumb: |
| 68 | # Thumbnails are stored in a separate obj always displayed inline. |
| 69 | gcs_object_id = gcs_object_id + '-thumbnail' |
| 70 | elif not mr.inline: |
| 71 | # Downloads are stored in a separate obj with disposiiton set. |
| 72 | filename = attachment.filename |
| 73 | if not framework_constants.FILENAME_RE.match(filename): |
| 74 | logging.info('bad file name: %s' % attachment.attachment_id) |
| 75 | filename = 'attachment-%d.dat' % attachment.attachment_id |
| 76 | if gcs_helpers.MaybeCreateDownload( |
| 77 | bucket_name, gcs_object_id, filename): |
| 78 | gcs_object_id = gcs_object_id + '-download' |
| 79 | |
Adrià Vilanova Martínez | f19ea43 | 2024-01-23 20:20:52 +0100 | [diff] [blame] | 80 | redirect_url = gcs_helpers.SignUrl(bucket_name, gcs_object_id) |
| 81 | raise exceptions.RedirectException(redirect_url) |
Adrià Vilanova Martínez | de94280 | 2022-07-15 14:06:55 +0200 | [diff] [blame] | 82 | |
Adrià Vilanova Martínez | f19ea43 | 2024-01-23 20:20:52 +0100 | [diff] [blame] | 83 | def GetAttachmentPage(self, **kwargs): |
| 84 | return self.handler(**kwargs) |