Edgewall Software

Ticket #5998: 5998-extended-default-query-r7524.patch

File 5998-extended-default-query-r7524.patch, 5.1 KB (added by rblank, 3 years ago)

Patch against 0.11-stable allowing query strings in default custom queries

  • trac/ticket/query.py

    diff --git a/trac/ticket/query.py b/trac/ticket/query.py
    a b  
    3535from trac.util.presentation import Paginator 
    3636from trac.util.text import shorten_line 
    3737from trac.util.translation import _ 
    38 from trac.web import IRequestHandler 
     38from trac.web import parse_query_string, IRequestHandler 
    3939from trac.web.href import Href 
    4040from trac.web.chrome import add_ctxtnav, add_link, add_script, add_stylesheet, \ 
    4141                            INavigationContributor, Chrome 
     
    739739        req.perm.assert_permission('TICKET_VIEW') 
    740740 
    741741        constraints = self._get_constraints(req) 
     742        args = req.args 
    742743        if not constraints and not 'order' in req.args: 
    743744            # If no constraints are given in the URL, use the default ones. 
    744745            if req.authname and req.authname != 'anonymous': 
     
    751752                user = email or name or None 
    752753                       
    753754            self.log.debug('QueryModule: Using default query: %s', str(qstring)) 
    754             constraints = Query.from_string(self.env, qstring).constraints 
    755             # Substitute $USER, or ensure no field constraints that depend on 
    756             # $USER are used if we have no username. 
    757             for field, vals in constraints.items(): 
    758                 for (i, val) in enumerate(vals): 
    759                     if user: 
    760                         vals[i] = val.replace('$USER', user) 
    761                     elif val.endswith('$USER'): 
    762                         del constraints[field] 
    763                         break 
     755            if qstring.startswith('?'): 
     756                ticket_fields = [f['name'] for f in 
     757                                 TicketSystem(self.env).get_ticket_fields()] 
     758                ticket_fields.append('id') 
     759                args = parse_query_string(qstring[1:]) 
     760                constraints = dict((k, args.getlist(k)) for k in args  
     761                                   if k in ticket_fields) 
     762            else: 
     763                constraints = Query.from_string(self.env, qstring).constraints 
     764                # Substitute $USER, or ensure no field constraints that depend 
     765                # on $USER are used if we have no username. 
     766                for field, vals in constraints.items(): 
     767                    for (i, val) in enumerate(vals): 
     768                        if user: 
     769                            vals[i] = val.replace('$USER', user) 
     770                        elif val.endswith('$USER'): 
     771                            del constraints[field] 
     772                            break 
    764773 
    765         cols = req.args.get('col') 
     774        cols = args.get('col') 
    766775        if isinstance(cols, basestring): 
    767776            cols = [cols] 
    768777        # Since we don't show 'id' as an option to the user, 
    769778        # we need to re-insert it here.             
    770779        if cols and 'id' not in cols:  
    771780            cols.insert(0, 'id') 
    772         rows = req.args.get('row', []) 
     781        rows = args.get('row', []) 
    773782        if isinstance(rows, basestring): 
    774783            rows = [rows] 
    775784        format = req.args.get('format') 
    776         max = req.args.get('max') 
     785        max = args.get('max') 
    777786        if max is None and format in ('csv', 'tab'): 
    778787            max = 0 # unlimited unless specified explicitly 
    779788        query = Query(self.env, req.args.get('report'), 
    780                       constraints, cols, req.args.get('order'), 
    781                       'desc' in req.args, req.args.get('group'), 
    782                       'groupdesc' in req.args, 'verbose' in req.args, 
     789                      constraints, cols, args.get('order'), 
     790                      'desc' in args, args.get('group'), 
     791                      'groupdesc' in args, 'verbose' in args, 
    783792                      rows, 
    784                       req.args.get('page'),  
     793                      args.get('page'),  
    785794                      max) 
    786795 
    787796        if 'update' in req.args: 
  • trac/web/api.py

    diff --git a/trac/web/api.py b/trac/web/api.py
    a b  
    2626import urlparse 
    2727 
    2828from trac.core import Interface, TracError 
    29 from trac.util import get_last_traceback, md5 
     29from trac.util import get_last_traceback, md5, unquote 
    3030from trac.util.datefmt import http_date, localtz 
    3131from trac.web.href import Href 
    3232from trac.web.wsgi import _FileWrapper 
     
    9797        if not isinstance(val, list): 
    9898            val = [val] 
    9999        return val 
     100 
     101 
     102def parse_query_string(query_string): 
     103    """Parse a query string into a _RequestArgs.""" 
     104    args = _RequestArgs() 
     105    for arg in query_string.split('&'): 
     106        nv = arg.split('=', 1) 
     107        if len(nv) == 2: 
     108            (name, value) = nv 
     109        else: 
     110            (name, value) = (nv[0], '') 
     111        name = unquote(name.replace('+', ' ')) 
     112        if isinstance(name, unicode): 
     113            name = name.encode('utf-8') 
     114        value = unquote(value.replace('+', ' ')) 
     115        if not isinstance(value, unicode): 
     116            value = unicode(value, 'utf-8') 
     117        if name in args: 
     118            if isinstance(args[name], list): 
     119                args[name].append(value) 
     120            else: 
     121                args[name] = [args[name], value] 
     122        else: 
     123            args[name] = value 
     124    return args 
    100125 
    101126 
    102127class RequestDone(Exception):