# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Classes to hold information parsed from a request.

To simplify our servlets and avoid duplication of code, we parse some
info out of the request as soon as we get it and then pass a MonorailRequest
object to the servlet-specific request handler methods.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import endpoints
import logging
import re
from six.moves import urllib

import ezt
import flask
import six

from google.appengine.api import app_identity
from google.appengine.api import oauth

import settings
from businesslogic import work_env
from features import features_constants
from framework import authdata
from framework import exceptions
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_views
from framework import monorailcontext
from framework import permissions
from framework import profiler
from framework import sql
from framework import template_helpers
from mrproto import api_pb2_v1
from tracker import tracker_bizobj
from tracker import tracker_constants


_HOSTPORT_RE = re.compile(r'^[-a-z0-9.]+(:\d+)?$', re.I)


# TODO(jrobbins): Stop extending MonorailContext and change whole servlet
# framework to pass around separate objects for mc and mr.
class MonorailRequestBase(monorailcontext.MonorailContext):
  """A base class with common attributes for internal and external requests."""

  def __init__(self, services, requester=None, cnxn=None):
    super(MonorailRequestBase, self).__init__(
        services, cnxn=cnxn, requester=requester)

    self.project_name = None
    self.project = None
    self.config = None

  @property
  def project_id(self):
    return self.project.project_id if self.project else None


class MonorailApiRequest(MonorailRequestBase):
  """A class to hold information parsed from the Endpoints API request."""

  # pylint: disable=attribute-defined-outside-init
  def __init__(self, request, services, cnxn=None):
    requester_object = (
        endpoints.get_current_user() or
        oauth.get_current_user(
            framework_constants.OAUTH_SCOPE))
    requester = requester_object.email().lower()
    super(MonorailApiRequest, self).__init__(
        services, requester=requester, cnxn=cnxn)
    self.me_user_id = self.auth.user_id
    self.viewed_username = None
    self.viewed_user_auth = None
    self.issue = None
    self.granted_perms = set()

    # query parameters
    self.params = {
        'can': 1,
        'start': 0,
        'num': tracker_constants.DEFAULT_RESULTS_PER_PAGE,
        'q': '',
        'sort': '',
        'groupby': '',
        'projects': [],
        'hotlists': []
    }
    self.use_cached_searches = True
    self.mode = None

    if hasattr(request, 'projectId'):
      self.project_name = request.projectId
      with work_env.WorkEnv(self, services) as we:
        self.project = we.GetProjectByName(self.project_name)
        self.params['projects'].append(self.project_name)
        self.config = we.GetProjectConfig(self.project_id)
        if hasattr(request, 'additionalProject'):
          self.params['projects'].extend(request.additionalProject)
          self.params['projects'] = list(set(self.params['projects']))
    self.LookupLoggedInUserPerms(self.project)
    if hasattr(request, 'projectId'):
      with work_env.WorkEnv(self, services) as we:
        if hasattr(request, 'issueId'):
          self.issue = we.GetIssueByLocalID(
              self.project_id, request.issueId, use_cache=False)
          self.granted_perms = tracker_bizobj.GetGrantedPerms(
              self.issue, self.auth.effective_ids, self.config)
    if hasattr(request, 'userId'):
      self.viewed_username = request.userId.lower()
      if self.viewed_username == 'me':
        self.viewed_username = requester
      self.viewed_user_auth = authdata.AuthData.FromEmail(
          self.cnxn, self.viewed_username, services)
    elif hasattr(request, 'groupName'):
      self.viewed_username = request.groupName.lower()
      try:
        self.viewed_user_auth = authdata.AuthData.FromEmail(
            self.cnxn, self.viewed_username, services)
      except exceptions.NoSuchUserException:
        self.viewed_user_auth = None

    # Build q.
    if hasattr(request, 'q') and request.q:
      self.params['q'] = request.q
    if hasattr(request, 'publishedMax') and request.publishedMax:
      self.params['q'] += ' opened<=%d' % request.publishedMax
    if hasattr(request, 'publishedMin') and request.publishedMin:
      self.params['q'] += ' opened>=%d' % request.publishedMin
    if hasattr(request, 'updatedMax') and request.updatedMax:
      self.params['q'] += ' modified<=%d' % request.updatedMax
    if hasattr(request, 'updatedMin') and request.updatedMin:
      self.params['q'] += ' modified>=%d' % request.updatedMin
    if hasattr(request, 'owner') and request.owner:
      self.params['q'] += ' owner:%s' % request.owner
    if hasattr(request, 'status') and request.status:
      self.params['q'] += ' status:%s' % request.status
    if hasattr(request, 'label') and request.label:
      self.params['q'] += ' label:%s' % request.label

    if hasattr(request, 'can') and request.can:
      if request.can == api_pb2_v1.CannedQuery.all:
        self.params['can'] = 1
      elif request.can == api_pb2_v1.CannedQuery.new:
        self.params['can'] = 6
      elif request.can == api_pb2_v1.CannedQuery.open:
        self.params['can'] = 2
      elif request.can == api_pb2_v1.CannedQuery.owned:
        self.params['can'] = 3
      elif request.can == api_pb2_v1.CannedQuery.reported:
        self.params['can'] = 4
      elif request.can == api_pb2_v1.CannedQuery.starred:
        self.params['can'] = 5
      elif request.can == api_pb2_v1.CannedQuery.to_verify:
        self.params['can'] = 7
      else: # Endpoints should have caught this.
        raise exceptions.InputException(
            'Canned query %s is not supported.', request.can)
    if hasattr(request, 'startIndex') and request.startIndex:
      self.params['start'] = request.startIndex
    if hasattr(request, 'maxResults') and request.maxResults:
      self.params['num'] = request.maxResults
    if hasattr(request, 'sort') and request.sort:
      self.params['sort'] = request.sort

    self.query_project_names = self.GetParam('projects')
    self.group_by_spec = self.GetParam('groupby')
    self.group_by_spec = ' '.join(ParseColSpec(
        self.group_by_spec, ignore=tracker_constants.NOT_USED_IN_GRID_AXES))
    self.sort_spec = self.GetParam('sort')
    self.sort_spec = ' '.join(ParseColSpec(self.sort_spec))
    self.query = self.GetParam('q')
    self.can = self.GetParam('can')
    self.start = self.GetParam('start')
    self.num = self.GetParam('num')

  def GetParam(self, query_param_name, default_value=None,
               _antitamper_re=None):
    return self.params.get(query_param_name, default_value)

  def GetPositiveIntParam(self, query_param_name, default_value=None):
    """Returns 0 if the user-provided value is less than 0."""
    return max(self.GetParam(query_param_name, default_value=default_value),
               0)


class MonorailRequest(MonorailRequestBase):
  """A class to hold information parsed from the HTTP request.

  The goal of MonorailRequest is to do almost all URL path and query string
  procesing in one place, which makes the servlet code simpler.

  Attributes:
   cnxn: connection to the SQL databases.
   logged_in_user_id: int user ID of the signed-in user, or None.
   effective_ids: set of signed-in user ID and all their user group IDs.
   user_pb: User object for the signed in user.
   project_name: string name of the current project.
   project_id: int ID of the current projet.
   viewed_username: string username of the user whose profile is being viewed.
   can: int "canned query" number to scope the user's search.
   num: int number of results to show per pagination page.
   start: int position in result set to show on this pagination page.
   etc: there are many more, all read-only.
  """

  # pylint: disable=attribute-defined-outside-init
  def __init__(self, services, params=None):
    """Initialize the MonorailRequest object."""
    # Note: mr starts off assuming anon until ParseRequest() is called.
    super(MonorailRequest, self).__init__(services)
    self.form_overrides = {}
    if params:
      self.form_overrides.update(params)
    self.debug_enabled = False
    self.use_cached_searches = True

    self.hotlist_id = None
    self.hotlist = None
    self.hotlist_name = None

    self.viewed_username = None
    self.viewed_user_auth = authdata.AuthData()

  def ParseRequest(self, request, services, do_user_lookups=True):
    """Parse tons of useful info from the given flask request object.

    Args:
      request: flask Request object w/ path and query params.
      services: connections to backend servers including DB.
      do_user_lookups: Set to False to disable lookups during testing.
    """
    with self.profiler.Phase('basic parsing'):
      self.request = request
      self.request_path = request.base_url[len(request.host_url) - 1:]
      self.current_page_url = request.url
      self.current_page_url_encoded = urllib.parse.quote_plus(
          six.ensure_str(self.current_page_url))

      # Only accept a hostport from the request that looks valid.
      if not _HOSTPORT_RE.match(request.host):
        raise exceptions.InputException(
            'request.host looks funny: %r', request.host)

      logging.info('Flask Request: %s', self.current_page_url)

    with self.profiler.Phase('path parsing'):
      (viewed_user_val, self.project_name, self.hotlist_id,
       self.hotlist_name) = _ParsePathIdentifiers(self.request_path)
      self.viewed_username = _GetViewedEmail(
          viewed_user_val, self.cnxn, services)
    with self.profiler.Phase('qs parsing'):
      self._ParseQueryParameters()
    with self.profiler.Phase('overrides parsing'):
      self._ParseFormOverrides()

    if not self.project:  # It can be already set in unit tests.
      self._LookupProject(services)
    if self.project_id and services.config:
      self.config = services.config.GetProjectConfig(self.cnxn, self.project_id)

    if do_user_lookups:
      if self.viewed_username:
        self._LookupViewedUser(services)
      self._LookupLoggedInUser(services)

    if not self.hotlist:
      self._LookupHotlist(services)

    if self.query is None:
      self.query = self._CalcDefaultQuery()

    prod_debug_allowed = self.perms.HasPerm(
        permissions.VIEW_DEBUG, self.auth.user_id, None)
    self.debug_enabled = (
        request.values.get('debug') and
        (settings.local_mode or prod_debug_allowed))
    # temporary option for perf testing on staging instance.
    if request.values.get('disable_cache'):
      if settings.local_mode or 'staging' in request.host:
        self.use_cached_searches = False

  def _CalcDefaultQuery(self):
    """When URL has no q= param, return the default for members or ''."""
    if (self.can == 2 and self.project and self.auth.effective_ids and
        framework_bizobj.UserIsInProject(self.project, self.auth.effective_ids)
        and self.config):
      return self.config.member_default_query
    else:
      return ''

  def _ParseQueryParameters(self):
    """Parse and convert all the query string params used in any servlet."""
    self.start = self.GetPositiveIntParam('start', default_value=0)
    self.num = self.GetPositiveIntParam(
        'num', default_value=tracker_constants.DEFAULT_RESULTS_PER_PAGE)
    # Prevent DoS attacks that try to make us serve really huge result pages.
    self.num = min(self.num, settings.max_artifact_search_results_per_page)

    self.invalidation_timestep = self.GetIntParam(
        'invalidation_timestep', default_value=0)

    self.continue_issue_id = self.GetIntParam(
        'continue_issue_id', default_value=0)
    self.redir = self.GetParam('redir')

    # Search scope, a.k.a., canned query ID
    # TODO(jrobbins): make configurable
    self.can = self.GetIntParam(
        'can', default_value=tracker_constants.OPEN_ISSUES_CAN)

    # Search query
    self.query = self.GetParam('q')

    # Sorting of search results (needed for result list and flipper)
    self.sort_spec = self.GetParam(
        'sort', default_value='',
        antitamper_re=framework_constants.SORTSPEC_RE)
    self.sort_spec = ' '.join(ParseColSpec(self.sort_spec))

    # Note: This is set later in request handling by ComputeColSpec().
    self.col_spec = None

    # Grouping of search results (needed for result list and flipper)
    self.group_by_spec = self.GetParam(
        'groupby', default_value='',
        antitamper_re=framework_constants.SORTSPEC_RE)
    self.group_by_spec = ' '.join(ParseColSpec(
        self.group_by_spec, ignore=tracker_constants.NOT_USED_IN_GRID_AXES))

    # For issue list and grid mode.
    self.cursor = self.GetParam('cursor')
    self.preview = self.GetParam('preview')
    self.mode = self.GetParam('mode') or 'list'
    self.x = self.GetParam('x', default_value='')
    self.y = self.GetParam('y', default_value='')
    self.cells = self.GetParam('cells', default_value='ids')

    # For the dashboard and issue lists included in the dashboard.
    self.ajah = self.GetParam('ajah')  # AJAH = Asychronous Javascript And HTML
    self.table_title = self.GetParam('table_title')
    self.panel_id = self.GetIntParam('panel')

    # For pagination of updates lists
    self.before = self.GetPositiveIntParam('before')
    self.after = self.GetPositiveIntParam('after')

    # For cron tasks and backend calls
    self.lower_bound = self.GetIntParam('lower_bound')
    self.upper_bound = self.GetIntParam('upper_bound')
    self.shard_id = self.GetIntParam('shard_id')

    # For specifying which objects to operate on
    self.local_id = self.GetIntParam('id')
    self.local_id_list = self.GetIntListParam('ids')
    self.seq = self.GetIntParam('seq')
    self.aid = self.GetIntParam('aid')
    self.signed_aid = self.GetParam('signed_aid')
    self.specified_user_id = self.GetIntParam('u', default_value=0)
    self.specified_logged_in_user_id = self.GetIntParam(
        'logged_in_user_id', default_value=0)
    self.specified_me_user_ids = self.GetIntListParam('me_user_ids')

    # TODO(jrobbins): Phase this out after next deployment.  If an old
    # version of the default GAE module sends a request with the old
    # me_user_id= parameter, then accept it.
    specified_me_user_id = self.GetIntParam(
        'me_user_id', default_value=0)
    if specified_me_user_id:
      self.specified_me_user_ids = [specified_me_user_id]

    self.specified_project = self.GetParam('project')
    self.specified_project_id = self.GetIntParam('project_id')
    self.query_project_names = self.GetListParam('projects', default_value=[])
    self.template_name = self.GetParam('template')
    self.component_path = self.GetParam('component')
    self.field_name = self.GetParam('field')

    # For image attachments
    self.inline = bool(self.GetParam('inline'))
    self.thumb = bool(self.GetParam('thumb'))

    # For JS callbacks
    self.token = self.GetParam('token')
    self.starred = bool(self.GetIntParam('starred'))

    # For issue reindexing utility servlet
    self.auto_submit = self.GetParam('auto_submit')

    # For issue dependency reranking servlet
    self.parent_id = self.GetIntParam('parent_id')
    self.target_id = self.GetIntParam('target_id')
    self.moved_ids = self.GetIntListParam('moved_ids')
    self.split_above = self.GetBoolParam('split_above')

    # For adding issues to hotlists servlet
    self.hotlist_ids_remove = self.GetIntListParam('hotlist_ids_remove')
    self.hotlist_ids_add = self.GetIntListParam('hotlist_ids_add')
    self.issue_refs = self.GetListParam('issue_refs')

  def _ParseFormOverrides(self):
    """Support deep linking by allowing the user to set form fields via QS."""
    allowed_overrides = {
        'template_name': self.GetParam('template_name'),
        'initial_summary': self.GetParam('summary'),
        'initial_description': (self.GetParam('description') or
                                self.GetParam('comment')),
        'initial_comment': self.GetParam('comment'),
        'initial_status': self.GetParam('status'),
        'initial_owner': self.GetParam('owner'),
        'initial_cc': self.GetParam('cc'),
        'initial_blocked_on': self.GetParam('blockedon'),
        'initial_blocking': self.GetParam('blocking'),
        'initial_merge_into': self.GetIntParam('mergeinto'),
        'initial_components': self.GetParam('components'),
        'initial_hotlists': self.GetParam('hotlists'),

        # For the people pages
        'initial_add_members': self.GetParam('add_members'),
        'initially_expanded_form': ezt.boolean(self.GetParam('expand_form')),

        # For user group admin pages
        'initial_name': (self.GetParam('group_name') or
                         self.GetParam('proposed_project_name')),
        }

    # Only keep the overrides that were actually provided in the query string.
    self.form_overrides.update(
        (k, v) for (k, v) in allowed_overrides.items()
        if v is not None)

  def _LookupViewedUser(self, services):
    """Get information about the viewed user (if any) from the request."""
    try:
      with self.profiler.Phase('get viewed user, if any'):
        self.viewed_user_auth = authdata.AuthData.FromEmail(
            self.cnxn, self.viewed_username, services, autocreate=False)
    except exceptions.NoSuchUserException:
      logging.info('could not find user %r', self.viewed_username)
      flask.abort(404, 'user not found')

    if not self.viewed_user_auth.user_id:
      flask.abort(404, 'user not found')

  def _LookupProject(self, services):
    """Get information about the current project (if any) from the request.

    Raises:
      NoSuchProjectException if there is no project with that name.
    """
    logging.info('project_name is %r', self.project_name)
    if self.project_name:
      self.project = services.project.GetProjectByName(
          self.cnxn, self.project_name)
      if not self.project:
        raise exceptions.NoSuchProjectException()

  def _LookupHotlist(self, services):
    """Get information about the current hotlist (if any) from the request."""
    with self.profiler.Phase('get current hotlist, if any'):
      if self.hotlist_name:
        hotlist_id_dict = services.features.LookupHotlistIDs(
            self.cnxn, [self.hotlist_name], [self.viewed_user_auth.user_id])
        try:
          self.hotlist_id = hotlist_id_dict[(
              self.hotlist_name, self.viewed_user_auth.user_id)]
        except KeyError:
          flask.abort(404, 'invalid hotlist')

      if not self.hotlist_id:
        logging.info('no hotlist_id or bad hotlist_name, so no hotlist')
      else:
        self.hotlist = services.features.GetHotlistByID(
            self.cnxn, self.hotlist_id)
        if not self.hotlist or (
            self.viewed_user_auth.user_id and
            self.viewed_user_auth.user_id not in self.hotlist.owner_ids):
          flask.abort(404, 'invalid hotlist')

  def _LookupLoggedInUser(self, services):
    """Get information about the signed-in user (if any) from the request."""
    self.auth = authdata.AuthData.FromRequest(self.cnxn, services)
    self.me_user_id = (self.GetIntParam('me') or
                       self.viewed_user_auth.user_id or self.auth.user_id)

    self.LookupLoggedInUserPerms(self.project)

  def ComputeColSpec(self, config):
    """Set col_spec based on param, default in the config, or site default."""
    if self.col_spec is not None:
      return  # Already set.
    default_col_spec = ''
    if config:
      default_col_spec = config.default_col_spec

    col_spec = self.GetParam(
        'colspec', default_value=default_col_spec,
        antitamper_re=framework_constants.COLSPEC_RE)
    cols_lower = col_spec.lower().split()
    if self.project and any(
        hotlist_col in cols_lower for hotlist_col in [
            'rank', 'adder', 'added']):
      # if the the list is a project list and the 'colspec' is a carry-over
      # from hotlists, set col_spec to None so it will be set to default in
      # in the next if statement
      col_spec = None

    if not col_spec:
      # If col spec is still empty then default to the global col spec.
      col_spec = tracker_constants.DEFAULT_COL_SPEC

    self.col_spec = ' '.join(ParseColSpec(col_spec,
                             max_parts=framework_constants.MAX_COL_PARTS))

  def PrepareForReentry(self, echo_data):
    """Expose the results of form processing as if it was a new GET.

    This method is called only when the user submits a form with invalid
    information which they are being asked to correct it.  Updating the MR
    object allows the normal servlet get() method to populate the form with
    the entered values and error messages.

    Args:
      echo_data: dict of {page_data_key: value_to_reoffer, ...} that will
          override whatever HTML form values are nomally shown to the
          user when they initially view the form.  This allows them to
          fix user input that was not valid.
    """
    self.form_overrides.update(echo_data)

  def GetParam(self, query_param_name, default_value=None,
               antitamper_re=None):
    """Get a query parameter from the URL as a utf8 string."""
    value = None
    if hasattr(self.request, 'params'):
      value = self.request.params.get(query_param_name)
    else:
      value = self.request.values.get(query_param_name)
    assert value is None or isinstance(value, six.string_types)
    using_default = value is None
    if using_default:
      value = default_value

    if antitamper_re and not antitamper_re.match(value):
      if using_default:
        logging.error('Default value fails antitamper for %s field: %s',
                      query_param_name, value)
      else:
        logging.info('User seems to have tampered with %s field: %s',
                     query_param_name, value)
      raise exceptions.InputException()

    return value

  def GetIntParam(self, query_param_name, default_value=None):
    """Get an integer param from the URL or default."""
    value = None
    if hasattr(self.request, 'params'):
      value = self.request.params.get(query_param_name)
    else:
      value = self.request.values.get(query_param_name)
    if value is None or value == '':
      return default_value

    try:
      return int(value)
    except (TypeError, ValueError):
      raise exceptions.InputException(
          'Invalid value for integer param: %r' % value)

  def GetPositiveIntParam(self, query_param_name, default_value=None):
    """Returns 0 if the user-provided value is less than 0."""
    value = self.GetIntParam(query_param_name, default_value=default_value)
    if value is None:
      return 0
    return max(value, 0)

  def GetListParam(self, query_param_name, default_value=None):
    """Get a list of strings from the URL or default."""
    params = None
    if hasattr(self.request, 'params'):
      params = self.request.params.get(query_param_name)
    else:
      params = self.request.values.get(query_param_name)
    if params is None:
      return default_value
    if not params:
      return []
    return params.split(',')

  def GetIntListParam(self, query_param_name, default_value=None):
    """Get a list of ints from the URL or default."""
    param_list = self.GetListParam(query_param_name)
    if param_list is None:
      return default_value

    try:
      return [int(p) for p in param_list]
    except (TypeError, ValueError):
      raise exceptions.InputException('Invalid value for integer list param')

  def GetBoolParam(self, query_param_name, default_value=None):
    """Get a boolean param from the URL or default."""
    value = None
    if hasattr(self.request, 'params'):
      value = self.request.params.get(query_param_name)
    else:
      value = self.request.values.get(query_param_name)

    if value is None:
      return default_value

    if (not value) or (value.lower() == 'false'):
      return False
    return True


def _ParsePathIdentifiers(path):
  """Parse out the workspace being requested (if any).

  Args:
    path: A string beginning with the request's path info.

  Returns:
    (viewed_user_val, project_name).
  """
  viewed_user_val = None
  project_name = None
  hotlist_id = None
  hotlist_name = None

  # Strip off any query params
  split_path = path.lstrip('/').split('?')[0].split('/')
  if len(split_path) >= 2:
    if split_path[0] == 'hotlists':
      if split_path[1].isdigit():
        hotlist_id = int(split_path[1])
    if split_path[0] == 'p':
      project_name = split_path[1]
    if split_path[0] == 'u' or split_path[0] == 'users':
      viewed_user_val = urllib.parse.unquote(split_path[1])
      if len(split_path) >= 4 and split_path[2] == 'hotlists':
        try:
          hotlist_id = int(urllib.parse.unquote(split_path[3].split('.')[0]))
        except ValueError:
          raw_last_path = (split_path[3][:-3] if
                        split_path[3].endswith('.do') else split_path[3])
          last_path = urllib.parse.unquote(raw_last_path)
          match = framework_bizobj.RE_HOTLIST_NAME.match(
              last_path)
          if not match:
            raise exceptions.InputException(
                'Could not parse hotlist id or name')
          else:
            hotlist_name = last_path.lower()

    if split_path[0] == 'g':
      viewed_user_val = urllib.parse.unquote(split_path[1])

  return viewed_user_val, project_name, hotlist_id, hotlist_name


def _GetViewedEmail(viewed_user_val, cnxn, services):
  """Returns the viewed user's email.

  Args:
    viewed_user_val: Could be either int (user_id) or str (email).
    cnxn: connection to the SQL database.
    services: Interface to all persistence storage backends.

  Returns:
    viewed_email
  """
  if not viewed_user_val:
    return None

  try:
    viewed_userid = int(viewed_user_val)
    viewed_email = services.user.LookupUserEmail(cnxn, viewed_userid)
    if not viewed_email:
      logging.info('userID %s not found', viewed_userid)
      flask.abort(404, 'user not found')
  except ValueError:
    viewed_email = viewed_user_val

  return viewed_email


def ParseColSpec(
    col_spec, max_parts=framework_constants.MAX_SORT_PARTS,
    ignore=None):
  """Split a string column spec into a list of column names.

  We dedup col parts because an attacker could try to DoS us or guess
  zero or one result by measuring the time to process a request that
  has a very long column list.

  Args:
    col_spec: a unicode string containing a list of labels.
    max_parts: optional int maximum number of parts to consider.
    ignore: optional list of column name parts to ignore.

  Returns:
    A list of the extracted labels. Non-alphanumeric
    characters other than the period will be stripped from the text.
  """
  cols = framework_constants.COLSPEC_COL_RE.findall(col_spec)
  result = []  # List of column headers with no duplicates.
  # Set of column parts that we have processed so far.
  seen = set()
  if ignore:
    seen = set(ignore_col.lower() for ignore_col in ignore)
    max_parts += len(ignore)

  for col in cols:
    parts = []
    for part in col.split('/'):
      if (part.lower() not in seen and len(seen) < max_parts
          and len(part) < framework_constants.MAX_COL_LEN):
        parts.append(part)
        seen.add(part.lower())
    if parts:
      result.append('/'.join(parts))
  return result
