| 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 """Implemention of the issue list output as a CSV file.""" | 
|  | 7 | 
|  | 8 import settings | 
|  | 9 from framework import framework_helpers | 
|  | 10 from framework import permissions | 
|  | 11 from framework import urls | 
|  | 12 from tracker import issuelist | 
|  | 13 from tracker import tablecell | 
|  | 14 from tracker import tracker_constants | 
|  | 15 | 
|  | 16 | 
|  | 17 class IssueListCsv(issuelist.IssueList): | 
|  | 18   """IssueListCsv provides to the user a list of issues as a CSV document. | 
|  | 19 | 
|  | 20   Overrides the standard IssueList servlet but uses a different EZT template | 
|  | 21   to provide the same content as the IssueList only as CSV.  Adds the HTTP | 
|  | 22   header to offer the result as a download. | 
|  | 23   """ | 
|  | 24 | 
|  | 25   _PAGE_TEMPLATE = 'tracker/issue-list-csv.ezt' | 
|  | 26   _DEFAULT_RESULTS_PER_PAGE = settings.max_artifact_search_results_per_page | 
|  | 27 | 
|  | 28   def GatherPageData(self, mr): | 
|  | 29     if not mr.auth.user_id: | 
|  | 30       raise permissions.PermissionException( | 
|  | 31           'Anonymous users are not allowed to download issue list CSV') | 
|  | 32 | 
|  | 33     # Sets headers to allow the response to be downloaded. | 
|  | 34     self.content_type = 'text/csv; charset=UTF-8' | 
|  | 35     download_filename = '%s-issues.csv' % mr.project_name | 
|  | 36     self.response.headers.add( | 
|  | 37         'Content-Disposition', 'attachment; filename=%s' % download_filename) | 
|  | 38     self.response.headers.add('X-Content-Type-Options', 'nosniff') | 
|  | 39 | 
|  | 40     # Rewrite the colspec to add some extra columns that make the CSV | 
|  | 41     # file more complete. | 
|  | 42     with self.profiler.Phase('finishing config work'): | 
|  | 43       config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) | 
|  | 44 | 
|  | 45     mr.ComputeColSpec(config) | 
|  | 46     mr.col_spec = _RewriteColspec(mr.col_spec) | 
|  | 47     page_data = issuelist.IssueList.GatherPageData(self, mr) | 
|  | 48 | 
|  | 49     # CSV files are at risk for PDF content sniffing by Acrobat Reader. | 
|  | 50     page_data['prevent_sniffing'] = True | 
|  | 51 | 
|  | 52     # If we're truncating the results, add a URL to the next page of results | 
|  | 53     page_data['next_csv_link'] = None | 
|  | 54     pagination = page_data['pagination'] | 
|  | 55     if pagination.next_url: | 
|  | 56       page_data['next_csv_link'] = framework_helpers.FormatAbsoluteURL( | 
|  | 57           mr, urls.ISSUE_LIST_CSV, start=pagination.last) | 
|  | 58       page_data['item_count'] = pagination.last - pagination.start + 1 | 
|  | 59 | 
|  | 60     return page_data | 
|  | 61 | 
|  | 62   def GetCellFactories(self): | 
|  | 63     return tablecell.CSV_CELL_FACTORIES | 
|  | 64 | 
|  | 65 | 
|  | 66 # Whenever the user request one of these columns, we replace it with the | 
|  | 67 # list of alternate columns.  In effect, we split the requested column | 
|  | 68 # into two CSV columns. | 
|  | 69 _CSV_COLS_TO_REPLACE = { | 
|  | 70     'summary': ['Summary', 'AllLabels'], | 
|  | 71     'opened': ['Opened', 'OpenedTimestamp'], | 
|  | 72     'closed': ['Closed', 'ClosedTimestamp'], | 
|  | 73     'modified': ['Modified', 'ModifiedTimestamp'], | 
|  | 74     } | 
|  | 75 | 
|  | 76 | 
|  | 77 def _RewriteColspec(col_spec): | 
|  | 78   """Rewrite the given colspec to expand special CSV columns.""" | 
|  | 79   new_cols = [] | 
|  | 80 | 
|  | 81   for col in col_spec.split(): | 
|  | 82     rewriten_cols = _CSV_COLS_TO_REPLACE.get(col.lower(), [col]) | 
|  | 83     new_cols.extend(rewriten_cols) | 
|  | 84 | 
|  | 85   return ' '.join(new_cols) | 
| OLD | NEW | 
|---|