def process_request(self, req): # did the user ask for any special report? id = req.args.getint('id', self.REPORT_LIST_ID) req.perm(self.realm, id).require('REPORT_VIEW') data = {} action = req.args.get('action', 'view') template = None if req.method == 'POST': if action == 'new': self._do_create(req) elif action == 'delete': self._do_delete(req, id) elif action == 'edit': self._do_save(req, id) else: raise HTTPBadRequest(_("Invalid request arguments.")) elif action in ('copy', 'edit', 'new'): template = 'report_edit.html' data = self._render_editor(req, id, action == 'copy') Chrome(self.env).add_wiki_toolbars(req) elif action == 'delete': template = 'report_delete.html' data = self._render_confirm_delete(req, id) elif id == self.REPORT_LIST_ID: template, data, content_type = self._render_list(req) if content_type: # i.e. alternate format return template, data, {'content_type': content_type} if action == 'clear': if 'query_href' in req.session: del req.session['query_href'] if 'query_tickets' in req.session: del req.session['query_tickets'] else: template, data, content_type = self._render_view(req, id) if content_type: # i.e. alternate format return template, data, {'content_type': content_type} from trac.ticket.query import QueryModule show_query_link = 'TICKET_VIEW' in req.perm(TicketSystem.realm) and \ self.env.is_component_enabled(QueryModule) if (id != self.REPORT_LIST_ID or action == 'new') and \ 'REPORT_VIEW' in req.perm(self.realm, self.REPORT_LIST_ID): add_ctxtnav(req, _('Available Reports'), href=req.href.report()) add_link(req, 'up', req.href.report(), _('Available Reports')) elif show_query_link: add_ctxtnav(req, _('Available Reports')) # Kludge: only show link to custom query if the query module # is actually enabled if show_query_link: add_ctxtnav(req, _('New Custom Query'), href=req.href.query()) data['query_href'] = req.href.query() data['saved_query_href'] = req.session.get('query_href') else: data['query_href'] = None add_stylesheet(req, 'common/css/report.css') return template, data
def process_request(self, req): if req.method != 'POST': raise HTTPBadRequest(_("Invalid request arguments.")) req.perm.assert_permission('TICKET_BATCH_MODIFY') comment = req.args.get('batchmod_value_comment', '') action = req.args.get('action') # Get new ticket values from POST request. new_values = {} for field in TicketSystem(self.env).get_ticket_fields(): name = field['name'] if name not in ('id', 'resolution', 'status', 'owner', 'time', 'changetime', 'summary', 'description') + \ (('reporter',) if 'TICKET_ADMIN' not in req.perm else ()) \ and field['type'] != 'textarea': arg_name = 'batchmod_value_' + name if arg_name in req.args: new_values[name] = req.args.get(arg_name) selected_tickets = to_list(req.args.get('selected_tickets', '')) self._save_ticket_changes(req, selected_tickets, new_values, comment, action) # Always redirect back to the query page we came from req.redirect(req.args.get('query_href') or req.href.query())
def process_request(self, req): if req.method != 'POST': raise HTTPBadRequest(_("Invalid request arguments.")) req.perm.assert_permission('TICKET_BATCH_MODIFY') comment = req.args.get('batchmod_value_comment', '') action = req.args.get('action') try: new_values = self._get_new_ticket_values(req) except TracError as e: new_values = None add_warning( req, tag_("The changes could not be saved: " "%(message)s", message=to_unicode(e))) if new_values is not None: selected_tickets = self._get_selected_tickets(req) self._save_ticket_changes(req, selected_tickets, new_values, comment, action) # Always redirect back to the query page we came from req.redirect(req.args.get('query_href') or req.href.query())
def process_request(self, req): req.perm.require('FORM_EDIT_VAL') try: self.log.debug('UPDATE ARGS:' + str(req.args)) args = dict(req.args) backpath = args.pop('__backpath__', None) context = json.loads( unquote_plus(args.pop('__context__', '[null, null, null]'))) if None in context: # TRANSLATOR: HTTP error message raise HTTPBadRequest(_("__context__ is required")) basever = args.pop('__basever__', None) keep_history = args.pop('__keep_history__', None) track_fields = args.pop('__track_fields__', None) args.pop('__FORM_TOKEN', None) # Ignore. # wipe not JSON serializable arguments rejargs = [] for key, value in args.iteritems(): try: len(value) except AttributeError: rejargs.append(key) pass for key in rejargs: args.pop(key) who = req.authname result = json.dumps(args, separators=(',', ':')) self.save_tracform(context, result, who, basever, keep_history=keep_history, track_fields=track_fields) buffer = 'OK' if backpath is not None: req.send_response(302) req.send_header('Content-Type', 'text/plain') req.send_header('Location', backpath) req.send_header('Content-Length', str(len(buffer))) req.end_headers() req.write(buffer) else: req.send_response(200) req.send_header('Content-Type', 'text/plain') req.send_header('Content-Length', str(len(buffer))) req.end_headers() req.write(buffer) except Exception, e: buffer = str(e) req.send_response(500) req.send_header('Content-type', 'text/plain') req.send_header('Content-Length', str(len(buffer))) req.end_headers() req.write(buffer)
def __get_content_length(self, req): value = req.get_header('Content-Length') if value is None: return None if isinstance(value, unicode): value = value.encode('utf-8') size = None if value.isdigit(): try: size = int(value) except: pass if size is None or size < 0: raise HTTPBadRequest('Invalid Content-Length: %r' % value) return size
def process_request(self, req): try: self.log.debug('UPDATE ARGS:' + str(req.args)) args = dict(req.args) backpath = args.pop('__backpath__', None) context = args.pop('__context__', None) basever = args.pop('__basever__', None) keep_history = args.pop('__keep_history__', None) track_fields = args.pop('__track_fields__', None) args.pop('__FORM_TOKEN', None) # Ignore. if context is None: raise HTTPBadRequest('__context__ is required') who = str(req.session.sid) if not self.has_user(who): who = 'anonymous' result = [] for name, value in args.iteritems(): name = urllib.quote(str(name)) if isinstance(value, (list, tuple)): for item in value: item = str(item) result.append('%s=%s' % (name, urllib.quote(item))) else: value = str(value) result.append('%s=%s' % (name, urllib.quote(value))) self.save_tracform(context, '&'.join(result), who, basever, keep_history=keep_history, track_fields=track_fields) if backpath is not None: req.send_response(302) req.send_header('Content-type', 'text/plain') req.send_header('Location', backpath) req.end_headers() req.write('OK') else: req.send_response(200) req.send_header('Content-type', 'text/plain') req.end_headers() req.write('OK') except Exception, e: req.send_response(500) req.send_header('Content-type', 'text/plain') req.end_headers() req.write(str(e))
def process_request(self, req): req.perm.require('FORM_EDIT_VAL') try: self.log.debug('UPDATE ARGS:' + str(req.args)) args = dict(req.args) backpath = args.pop('__backpath__', None) context = json.loads( unquote_plus(args.pop('__context__', None)) or \ '(None, None, None)') basever = args.pop('__basever__', None) keep_history = args.pop('__keep_history__', None) track_fields = args.pop('__track_fields__', None) args.pop('__FORM_TOKEN', None) # Ignore. if context is None: # TRANSLATOR: HTTP error message raise HTTPBadRequest(_("__context__ is required")) who = req.authname result = json.dumps(args, separators=(',', ':')) self.save_tracform(context, result, who, basever, keep_history=keep_history, track_fields=track_fields) buffer = 'OK' if backpath is not None: req.send_response(302) req.send_header('Content-Type', 'text/plain') req.send_header('Location', backpath) req.send_header('Content-Length', str(len(buffer))) req.end_headers() req.write(buffer) else: req.send_response(200) req.send_header('Content-Type', 'text/plain') req.send_header('Content-Length', str(len(buffer))) req.end_headers() req.write(buffer) except Exception, e: buffer = str(e) req.send_response(500) req.send_header('Content-type', 'text/plain') req.send_header('Content-Length', str(len(buffer))) req.end_headers() req.write(buffer)
def process_request(self, req): req.perm.require('TICKET_VIEW') if req.method == 'POST': req.perm.require('BACKLOG_ADMIN') if 'move_after' in req.path_info: return self._move_after(req) elif 'move_before' in req.path_info: return self._move_before(req) elif 'assign' in req.path_info: return self._assign_milestone(req) else: raise HTTPBadRequest("Invalid POST request") if req.path_info.startswith('/backlog/milestone/'): milestone = req.path_info[19:] else: milestone = None if milestone == '(unscheduled)': milestone = None data = { 'title': (milestone or "Unscheduled"), } class Report(object): def __init__(self): self.id = -1 data['tickets'] = self._get_active_tickets(milestone) data['form_token'] = req.form_token data['active_milestones'] = self._get_active_milestones(milestone) data['base_path'] = req.base_path data['shown_fields'] = req.session.get( 'backlog_fields') or self._ticket_fields if 'BACKLOG_ADMIN' in req.perm: data['allow_sorting'] = True add_stylesheet(req, 'backlog/css/backlog.css') return 'backlog.html', data, None
def process_request(self, req): milestone_id = req.args.get('id') action = req.args.get('action', 'view') if not milestone_id and action == 'view': req.redirect(req.href.roadmap()) req.perm(self.realm, milestone_id).require('MILESTONE_VIEW') add_link(req, 'up', req.href.roadmap(), _("Roadmap")) try: milestone = Milestone(self.env, milestone_id) except ResourceNotFound: if 'MILESTONE_CREATE' not in req.perm(self.realm, milestone_id): raise milestone = Milestone(self.env) milestone.name = milestone_id action = 'edit' # rather than 'new', so it works for POST/save if req.method == 'POST': if 'cancel' in req.args: if milestone.exists: req.redirect(req.href.milestone(milestone.name)) else: req.redirect(req.href.roadmap()) elif action == 'edit': return self._do_save(req, milestone) elif action == 'delete': self._do_delete(req, milestone) else: raise HTTPBadRequest(_("Invalid request arguments.")) elif action in ('new', 'edit'): return self._render_editor(req, milestone) elif action == 'delete': return self._render_confirm(req, milestone) if not milestone.name: req.redirect(req.href.roadmap()) return self._render_view(req, milestone)
def dispatch(self, req): """Find a registered handler that matches the request and let it process it. In addition, this method initializes the data dictionary passed to the the template and adds the web site chrome. """ self.log.debug('Dispatching %r', req) chrome = Chrome(self.env) # Setup request callbacks for lazily-evaluated properties req.callbacks.update({ 'authname': self.authenticate, 'chrome': chrome.prepare_request, 'perm': self._get_perm, 'session': self._get_session, 'locale': self._get_locale, 'lc_time': self._get_lc_time, 'tz': self._get_timezone, 'form_token': self._get_form_token, 'use_xsendfile': self._get_use_xsendfile, 'xsendfile_header': self._get_xsendfile_header, }) try: try: # Select the component that should handle the request chosen_handler = None try: for handler in self._request_handlers.values(): if handler.match_request(req): chosen_handler = handler break if not chosen_handler and \ (not req.path_info or req.path_info == '/'): chosen_handler = self._get_valid_default_handler(req) # pre-process any incoming request, whether a handler # was found or not self.log.debug("Chosen handler is %s", chosen_handler) chosen_handler = \ self._pre_process_request(req, chosen_handler) except TracError as e: raise HTTPInternalError(e) if not chosen_handler: if req.path_info.endswith('/'): # Strip trailing / and redirect target = unicode_quote(req.path_info.rstrip('/')) if req.query_string: target += '?' + req.query_string req.redirect(req.href + target, permanent=True) raise HTTPNotFound('No handler matched request to %s', req.path_info) req.callbacks['chrome'] = partial(chrome.prepare_request, handler=chosen_handler) # Protect against CSRF attacks: we validate the form token # for all POST requests with a content-type corresponding # to form submissions if req.method == 'POST': ctype = req.get_header('Content-Type') if ctype: ctype, options = cgi.parse_header(ctype) if ctype in ('application/x-www-form-urlencoded', 'multipart/form-data') and \ req.args.get('__FORM_TOKEN') != req.form_token: if self.env.secure_cookies and req.scheme == 'http': msg = _('Secure cookies are enabled, you must ' 'use https to submit forms.') else: msg = _('Do you have cookies enabled?') raise HTTPBadRequest( _('Missing or invalid form token.' ' %(msg)s', msg=msg)) # Process the request and render the template resp = chosen_handler.process_request(req) if resp: if len(resp) == 2: # old Clearsilver template and HDF data self.log.error( "Clearsilver template are no longer " "supported (%s)", resp[0]) raise TracError( _("Clearsilver templates are no longer supported, " "please contact your Trac administrator.")) # Genshi template, data, content_type, method = \ self._post_process_request(req, *resp) if 'hdfdump' in req.args: req.perm.require('TRAC_ADMIN') # debugging helper - no need to render first out = io.BytesIO() pprint(data, out) req.send(out.getvalue(), 'text/plain') self.log.debug("Rendering response from handler") output = chrome.render_template( req, template, data, content_type, method=method, iterable=chrome.use_chunked_encoding) req.send(output, content_type or 'text/html') else: self.log.debug("Empty or no response from handler. " "Entering post_process_request.") self._post_process_request(req) except RequestDone: raise except: # post-process the request in case of errors err = sys.exc_info() try: self._post_process_request(req) except RequestDone: raise except Exception as e: self.log.error( "Exception caught while post-processing" " request: %s", exception_to_unicode(e, traceback=True)) raise err[0], err[1], err[2] except PermissionError as e: raise HTTPForbidden(e) except ResourceNotFound as e: raise HTTPNotFound(e) except TracError as e: raise HTTPInternalError(e)
def dispatch(self, req): """Find a registered handler that matches the request and let it process it. In addition, this method initializes the data dictionary passed to the the template and adds the web site chrome. """ self.log.debug('Dispatching %r', req) chrome = Chrome(self.env) try: # Select the component that should handle the request chosen_handler = None for handler in self._request_handlers.values(): if handler.match_request(req): chosen_handler = handler break if not chosen_handler and req.path_info in ('', '/'): chosen_handler = self._get_valid_default_handler(req) # pre-process any incoming request, whether a handler # was found or not self.log.debug("Chosen handler is %s", chosen_handler) chosen_handler = self._pre_process_request(req, chosen_handler) if not chosen_handler: if req.path_info.endswith('/'): # Strip trailing / and redirect target = unicode_quote(req.path_info.rstrip('/')) if req.query_string: target += '?' + req.query_string req.redirect(req.href + target, permanent=True) raise HTTPNotFound('No handler matched request to %s', req.path_info) req.callbacks['chrome'] = partial(chrome.prepare_request, handler=chosen_handler) # Protect against CSRF attacks: we validate the form token # for all POST requests with a content-type corresponding # to form submissions if req.method == 'POST': ctype = req.get_header('Content-Type') if ctype: ctype, options = cgi.parse_header(ctype) if ctype in ('application/x-www-form-urlencoded', 'multipart/form-data') and \ req.args.get('__FORM_TOKEN') != req.form_token: if self.env.secure_cookies and req.scheme == 'http': msg = _('Secure cookies are enabled, you must ' 'use https to submit forms.') else: msg = _('Do you have cookies enabled?') raise HTTPBadRequest(_('Missing or invalid form token.' ' %(msg)s', msg=msg)) # Process the request and render the template resp = chosen_handler.process_request(req) if resp: template, data, metadata = \ self._post_process_request(req, *resp) if 'hdfdump' in req.args: req.perm.require('TRAC_ADMIN') # debugging helper - no need to render first out = io.BytesIO() pprint({'template': template, 'metadata': metadata, 'data': data}, out) req.send(out.getvalue(), 'text/plain') self.log.debug("Rendering response with template %s", template) metadata.setdefault('iterable', chrome.use_chunked_encoding) content_type = metadata.get('content_type') output = chrome.render_template(req, template, data, metadata) req.send(output, content_type or 'text/html') else: self.log.debug("Empty or no response from handler. " "Entering post_process_request.") self._post_process_request(req) except RequestDone: raise except Exception as e: # post-process the request in case of errors err = sys.exc_info() try: self._post_process_request(req) except RequestDone: raise except TracError as e2: self.log.warning("Exception caught while post-processing" " request: %s", exception_to_unicode(e2)) except Exception as e2: if not (type(e) is type(e2) and e.args == e2.args): self.log.error("Exception caught while post-processing" " request: %s", exception_to_unicode(e2, traceback=True)) if isinstance(e, PermissionError): raise HTTPForbidden(e) if isinstance(e, ResourceNotFound): raise HTTPNotFound(e) if isinstance(e, NotImplementedError): tb = traceback.extract_tb(err[2])[-1] self.log.warning("%s caught from %s:%d in %s: %s", e.__class__.__name__, tb[0], tb[1], tb[2], to_unicode(e) or "(no message)") raise HTTPInternalServerError(TracNotImplementedError(e)) if isinstance(e, TracError): raise HTTPInternalServerError(e) raise err[0], err[1], err[2]
def process_request(self, req): action = req.args.get('action', 'view') pagename = req.args.get('page', self.START_PAGE) version = None if req.args.get('version'): # Allow version to be empty version = req.args.getint('version') old_version = req.args.getint('old_version') if pagename.startswith('/') or pagename.endswith('/') or \ '//' in pagename: pagename = re.sub(r'/{2,}', '/', pagename.strip('/')) req.redirect(req.href.wiki(pagename)) if not validate_page_name(pagename): raise TracError(_("Invalid Wiki page name '%(name)s'", name=pagename)) page = WikiPage(self.env, pagename) versioned_page = WikiPage(self.env, pagename, version) req.perm(versioned_page.resource).require('WIKI_VIEW') if version and versioned_page.version != version: raise ResourceNotFound( _('No version "%(num)s" for Wiki page "%(name)s"', num=version, name=page.name)) add_stylesheet(req, 'common/css/wiki.css') if req.method == 'POST': if action == 'edit': if 'cancel' in req.args: req.redirect(req.href.wiki(page.name)) has_collision = version != page.version for a in ('preview', 'diff', 'merge'): if a in req.args: action = a break versioned_page.text = req.args.get('text') valid = self._validate(req, versioned_page) if action == 'edit' and not has_collision and valid: return self._do_save(req, versioned_page) else: return self._render_editor(req, page, action, has_collision) elif action == 'edit_comment': self._do_edit_comment(req, versioned_page) elif action == 'delete': self._do_delete(req, versioned_page) elif action == 'rename': return self._do_rename(req, page) elif action == 'diff': style, options, diff_data = get_diff_options(req) contextall = diff_data['options']['contextall'] req.redirect(req.href.wiki(versioned_page.name, action='diff', old_version=old_version, version=version, contextall=contextall or None)) else: raise HTTPBadRequest(_("Invalid request arguments.")) elif action == 'delete': return self._render_confirm_delete(req, page) elif action == 'rename': return self._render_confirm_rename(req, page) elif action == 'edit': return self._render_editor(req, page) elif action == 'edit_comment': return self._render_edit_comment(req, versioned_page) elif action == 'diff': return self._render_diff(req, versioned_page) elif action == 'history': return self._render_history(req, versioned_page) else: format = req.args.get('format') if format: Mimeview(self.env).send_converted(req, 'text/x-trac-wiki', versioned_page.text, format, versioned_page.name) return self._render_view(req, versioned_page)
def process_request(self, req): acctmgr = self.acctmgr if req.authname != 'anonymous': req.redirect(req.href.prefs('account')) action = req.args.get('action') name = req.args.get('name', '') if isinstance(name, list): raise HTTPBadRequest(_("Invalid request arguments.")) name = name.strip() username = req.args.get('username', '') if isinstance(username, list): raise HTTPBadRequest(_("Invalid request arguments.")) username = acctmgr.handle_username_casing(username.strip()) data = { '_dgettext': dgettext, 'acctmgr': {'name': name, 'username': username}, 'ignore_auth_case': self.config.getbool('trac', 'ignore_auth_case') } verify_enabled = self.env.is_enabled(EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email data['verify_account_enabled'] = verify_enabled if req.method == 'POST' and action == 'create': try: try: # Check request and prime account on success. acctmgr.validate_account(req, True) except NotificationError, e: chrome.add_warning(req, _( "Error raised while sending a change notification." ) + _("You should report that issue to a Trac admin.")) self.log.error( 'Unable to send registration notification: %s', exception_to_unicode(e, traceback=True)) except RegistrationError, e: chrome.add_warning(req, e) else: if self.require_approval: set_user_attribute(self.env, username, 'approval', N_('pending')) # Notify admin user about registration pending for review. try: acctmgr._notify('registration_approval_required', username) except NotificationError, e: chrome.add_warning(req, _( "Error raised while sending a change " "notification.") + _( "You should report that issue to a Trac admin.")) self.log.error( 'Unable to send admin notification: %s', exception_to_unicode(e, traceback=True)) else: chrome.add_notice(req, tag_( "Your username has been registered successfully, " "but your account requires administrative " "approval. Please proceed according to local " "policy.")) if verify_enabled: chrome.add_notice(req, tag_( "Your username has been successfully registered but " "your account still requires activation. Please " "login as user %(user)s, and follow the " "instructions.", user=tag.b(username))) req.redirect(req.href.login()) chrome.add_notice(req, tag_( "Registration has been finished successfully. " "You may log in as user %(user)s now.", user=tag.b(username))) req.redirect(req.href.login())
db.commit() # Send an empty response for asynchronous requests if async: req.send("", 'text/plain', 200) # Redirect back to resource if so configured: if redirectback and len(del_res) == 1: if options['show_messages_on_resource_page']: req.session['watchlist_message'] = _( "You are no longer watching this resource.") req.redirect(req.href(realm, del_res[0])) action = 'view' # Up to here all watchlist actions except 'view' got handled and # either redirected the request or set the action to 'view'. if action != "view": raise HTTPBadRequest( _("Invalid watchlist action '%(action)s'!", action=action)) # Display watchlist page: if onwatchlistpage: wldict['show_messages'] = options[ 'show_messages_while_on_watchlist_page'] else: wldict['show_messages'] = options[ 'show_messages_on_watchlist_page'] wldict['perm'] = req.perm offset = req.tz.utcoffset(datetime.now(req.tz)) if offset is None: offset = 0 else: offset = offset.seconds / 60
def process_request(self, req): tf = req.session.get('lc_time', 'iso8601') def _formatter(value, field_type): if field_type == 'time': return format_date(value, tf) return value req.perm.require('TICKET_VIEW') if req.method == 'POST': req.perm.require('BACKLOG_ADMIN') if 'move_after' in req.path_info: return self._move_after(req) elif 'move_before' in req.path_info: return self._move_before(req) elif 'assign' in req.path_info: return self._assign_milestone(req) else: raise HTTPBadRequest("Invalid POST request") if req.path_info.startswith('/backlog/milestone/'): milestone = req.path_info[19:] req.session['backlog_milestone'] = milestone else: milestone = req.session.get('backlog_milestone') or None data = { 'title': (milestone or "Unscheduled"), 'formatter': _formatter, } all_custom_fields = TicketSystem(self.env).get_custom_fields() all_shown_fields = req.session.get('backlog_fields') \ or self._ticket_fields data['tickets'] = self._get_active_tickets(milestone) data['form_token'] = req.form_token data['active_milestones'] = self._get_active_milestones(milestone, time_format=tf) data['base_path'] = req.base_path data['custom_field_labels'] = { \ cf["name"] : cf["label"] for cf in all_custom_fields } data['custom_field_types'] = { \ cf['name'] : cf['type'] for cf in all_custom_fields } data['custom_fields_shown'] = [ \ cf['name'] for cf in all_custom_fields \ if (cf['name'] in all_shown_fields) ] data['shown_fields'] = all_shown_fields if 'BACKLOG_ADMIN' in req.perm: data['allow_sorting'] = True add_stylesheet(req, 'backlog/css/backlog.css') return 'backlog.html', data, None