OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is govered by a BSD-style |
| 3 # license that can be found in the LICENSE file or at |
| 4 # https://developers.google.com/open-source/licenses/bsd |
| 5 |
| 6 """Servlet to safely display textual issue attachments. |
| 7 |
| 8 Unlike most attachments, this is not a download, it is a full HTML page |
| 9 with safely escaped user content. |
| 10 """ |
| 11 |
| 12 import httplib |
| 13 import logging |
| 14 |
| 15 import webapp2 |
| 16 |
| 17 from google.appengine.api import app_identity |
| 18 |
| 19 from third_party import cloudstorage |
| 20 from third_party import ezt |
| 21 |
| 22 from features import prettify |
| 23 from framework import filecontent |
| 24 from framework import permissions |
| 25 from framework import servlet |
| 26 from framework import template_helpers |
| 27 from services import issue_svc |
| 28 from tracker import tracker_bizobj |
| 29 from tracker import tracker_helpers |
| 30 from tracker import tracker_views |
| 31 |
| 32 |
| 33 class AttachmentText(servlet.Servlet): |
| 34 """AttachmentText displays textual attachments much like source browsing.""" |
| 35 |
| 36 _PAGE_TEMPLATE = 'tracker/issue-attachment-text.ezt' |
| 37 _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ISSUES |
| 38 |
| 39 def GatherPageData(self, mr): |
| 40 """Parse the attachment ID from the request and serve its content. |
| 41 |
| 42 Args: |
| 43 mr: commonly used info parsed from the request. |
| 44 |
| 45 Returns: |
| 46 Dict of values used by EZT for rendering almost the page. |
| 47 """ |
| 48 with self.profiler.Phase('get issue, comment, and attachment'): |
| 49 try: |
| 50 attachment, issue = tracker_helpers.GetAttachmentIfAllowed( |
| 51 mr, self.services) |
| 52 except issue_svc.NoSuchIssueException: |
| 53 webapp2.abort(404, 'issue not found') |
| 54 except issue_svc.NoSuchAttachmentException: |
| 55 webapp2.abort(404, 'attachment not found') |
| 56 except issue_svc.NoSuchCommentException: |
| 57 webapp2.abort(404, 'comment not found') |
| 58 |
| 59 content = [] |
| 60 if attachment.gcs_object_id: |
| 61 bucket_name = app_identity.get_default_gcs_bucket_name() |
| 62 full_path = '/' + bucket_name + attachment.gcs_object_id |
| 63 logging.info("reading gcs: %s" % full_path) |
| 64 with cloudstorage.open(full_path, 'r') as f: |
| 65 content = f.read() |
| 66 |
| 67 filesize = len(content) |
| 68 |
| 69 # This servlet only displays safe textual attachments. The user should |
| 70 # not have been given a link to this servlet for any other kind. |
| 71 if not tracker_views.IsViewableText(attachment.mimetype, filesize): |
| 72 self.response.status = httplib.BAD_REQUEST |
| 73 raise servlet.AlreadySentResponseException('not a text file') |
| 74 |
| 75 u_text, is_binary, too_large = filecontent.DecodeFileContents(content) |
| 76 lines = prettify.PrepareSourceLinesForHighlighting(u_text.encode('utf8')) |
| 77 |
| 78 config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) |
| 79 granted_perms = tracker_bizobj.GetGrantedPerms( |
| 80 issue, mr.auth.effective_ids, config) |
| 81 page_perms = self.MakePagePerms( |
| 82 mr, issue, permissions.DELETE_ISSUE, permissions.CREATE_ISSUE, |
| 83 granted_perms=granted_perms) |
| 84 |
| 85 page_data = { |
| 86 'issue_tab_mode': 'issueDetail', |
| 87 'local_id': issue.local_id, |
| 88 'filename': attachment.filename, |
| 89 'filesize': template_helpers.BytesKbOrMb(filesize), |
| 90 'file_lines': lines, |
| 91 'is_binary': ezt.boolean(is_binary), |
| 92 'too_large': ezt.boolean(too_large), |
| 93 'code_reviews': None, |
| 94 'page_perms': page_perms, |
| 95 } |
| 96 if is_binary or too_large: |
| 97 page_data['should_prettify'] = ezt.boolean(False) |
| 98 else: |
| 99 page_data.update(prettify.BuildPrettifyData( |
| 100 len(lines), attachment.filename)) |
| 101 |
| 102 return page_data |
OLD | NEW |