Edgewall Software
Modify

Opened 16 years ago

Closed 15 years ago

#8276 closed defect (fixed)

UnicodeEncodeError: 'ascii' codec can't encode characters in position 94-96: ordinal not in range(128)

Reported by: david4liu@… Owned by: Christian Boos
Priority: high Milestone: 0.11.6
Component: ticket system Version: 0.11.5
Severity: major Keywords: config unicode review
Cc: tumma72@…, osimons, felix.schwarz@… Branch:
Release Notes:
API Changes:
Internal Changes:

Description

How to Reproduce

While doing a POST operation on /newticket, Trac issued an internal error.

(please provide additional details here)

Request parameters:

{'__FORM_TOKEN': u'10f55ceac7d80a875397f225',
 'field_description': u'\u6d4b\u8bd5\u4e00\u4e0b\u4e2d\u6587',
 'field_drp_resources': u'',
 'field_owner': u'liuyun',
 'field_remaining_time': u'',
 'field_reporter': u'admin',
 'field_sprint': u'\u63d0\u4f9b\u53ef\u6d4b\u8bd5\u7684\u7248\u672c',
 'field_status': u'new',
 'field_summary': u'\u6d4b\u8bd5\u4e00\u4e0b\u4e2d\u6587',
 'field_type': u'task',
 'submit': u'Create ticket'}

User Agent was: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)

System Information

Trac 0.11.4
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)]
setuptools 0.6c9
SQLite 3.6.11
pysqlite 2.5.5
Genshi 0.5.1
mod_python 3.3.1
Agilo 0.7.3.3-r1417-20090313
jQuery: 1.2.6

Python Traceback

Attachments (3)

tracerror.png (59.2 KB ) - added by dazjorz@… 15 years ago.
Trac error report
config.patch (1.0 KB ) - added by tumma72@… 15 years ago.
config.patch to guard from unicode properties values written in the config file
t8276-unicode-for-sections-and-keys-r8424.diff (20.8 KB ) - added by Christian Boos 15 years ago.
Consistently handle conversion to and from utf-8 when storing resp. retrieving from the ConfigParser, not only for values but also for section and key names.

Download all attachments as: .zip

Change History (31)

comment:1 by anonymous, 16 years ago

User Agent was: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)

comment:2 by anonymous, 16 years ago

While doing a POST operation on /newticket, Trac issued an internal error.

(please provide additional details here)

comment:2 by anonymous, 16 years ago

While doing a POST operation on /newticket, Trac issued an internal error.

(please provide additional details here)

comment:3 by Remy Blank, 16 years ago

It seem the traceback went missing in the description. Could you please find the traceback corresponding to this issue in your Trac log, and paste it here? Thanks.

comment:4 by Christian Boos, 15 years ago

Keywords: needinfo added
Milestone: 0.11.5

comment:5 by dazjorz@…, 15 years ago

I just had the same issue. It happens simply when inserting non-ASCII characters in input, AFAIK. Here you go:

# File "/usr/lib/python2.5/site-packages/trac/web/main.py", line 423, in _dispatch_request Code fragment:

  1. try:
  2. if not env and env_error:
  3. raise HTTPInternalError(env_error)
  4. try:
  5. dispatcher = RequestDispatcher(env)
  6. dispatcher.dispatch(req)
  7. except RequestDone:
  8. pass
  9. resp = req._response or []
  10. except HTTPException, e:

Local variables: Name Value after [u' except RequestDone:', u' pass', u' resp = … before [u' try:', u' if not env and env_error:', u' raise … dispatcher <trac.web.main.RequestDispatcher object at 0xacb86ec> e UnicodeEncodeError('ascii', u'But then again, that shouldn\'t be … env <trac.env.Environment object at 0xa929e8c> env_error None exc_info (<type 'exceptions.UnicodeEncodeError'>, UnicodeEncodeError('ascii', u'But … filename '/usr/lib/python2.5/site-packages/trac/web/main.py' frames [{'function': '_dispatch_request', 'lines_before': [u' try:', u' … has_admin True line u' dispatcher.dispatch(req)' lineno 422 message u"UnicodeEncodeError: 'ascii' codec can't encode characters in position … req <Request "POST u'/ticket/222'"> resp [] tb <traceback object at 0xb08d25c> tb_hide None traceback 'Traceback (most recent call last):\n File … # File "/usr/lib/python2.5/site-packages/trac/web/main.py", line 197, in dispatch Code fragment:

  1. req.args.get('FORM_TOKEN') != req.form_token:
  2. raise HTTPBadRequest('Missing or invalid form token. '
  3. 'Do you have cookies enabled?')
  4. # Process the request and render the template
  5. resp = chosen_handler.process_request(req)
  6. if resp:
  7. if len(resp) == 2: # Clearsilver
  8. chrome.populate_hdf(req)
  9. template, content_type = \
  10. self._post_process_request(req, *resp)

Local variables: Name Value chosen_handler <trac.ticket.web_ui.TicketModule object at 0xacb874c> chrome <trac.web.chrome.Chrome object at 0xacac72c> ctype 'application/x-www-form-urlencoded' err (<type 'exceptions.UnicodeEncodeError'>, UnicodeEncodeError('ascii', u'But … handler <trac.ticket.web_ui.TicketModule object at 0xacb874c> options {} req <Request "POST u'/ticket/222'"> self <trac.web.main.RequestDispatcher object at 0xacb86ec> # File "/usr/lib/python2.5/site-packages/trac/ticket/web_ui.py", line 170, in process_request Code fragment:

  1. def process_request(self, req):
  2. if 'id' in req.args:
  3. if req.path_info.startswith('/newticket'):
  4. raise TracError(_("id can't be set for a new ticket request."))
  5. return self._process_ticket_request(req)
  6. return self._process_newticket_request(req)
  7. # ITemplateProvider methods
  8. def get_htdocs_dirs(self):

Local variables: Name Value req <Request "POST u'/ticket/222'"> self <trac.ticket.web_ui.TicketModule object at 0xacb874c> # File "/usr/lib/python2.5/site-packages/trac/ticket/web_ui.py", line 494, in _process_ticket_request Code fragment:

  1. # things.
  2. valid = self._validate_ticket(req, ticket) and not problems
  3. if 'preview' not in req.args:
  4. if valid:
  5. # redirected if successful
  6. self._do_save(req, ticket, action)
  7. # else fall through in a preview
  8. req.argspreview = True
  9. # Preview an existing ticket (after a Preview or a failed Save)
  10. data.update({

Local variables: Name Value action u'leave' actions ['leave', 'resolve', 'reassign'] data {'comment': None, 'preserve_newlines': False, 'ticket': … field_changes {} id 222 problems [] req <Request "POST u'/ticket/222'"> self <trac.ticket.web_ui.TicketModule object at 0xacb874c> ticket <trac.ticket.model.Ticket object at 0xaf7376c> valid True version None # File "/usr/lib/python2.5/site-packages/trac/ticket/web_ui.py", line 989, in _do_save Code fragment:

  1. # — Save changes
  2. now = datetime.now(utc)
  3. if ticket.save_changes(get_reporter_id(req, 'author'),
  4. req.args.get('comment'), when=now,
  5. cnum=internal_cnum):
  6. try:
  7. tn = TicketNotifyEmail(self.env)
  8. tn.notify(ticket, newticket=False, modtime=now)
  9. except Exception, e:
  10. self.log.exception("Failure sending notification on change to "

Local variables: Name Value action u'leave' cnum u'4' controllers [<trac.ticket.default_workflow.ConfigurableTicketWorkflow object at … internal_cnum u'4' now datetime.datetime(2009, 6, 29, 20, 0, 59, 523283, tzinfo≤FixedOffset … replyto u req <Request "POST u'/ticket/222'"> self <trac.ticket.web_ui.TicketModule object at 0xacb874c> ticket <trac.ticket.model.Ticket object at 0xaf7376c> # File "/usr/lib/python2.5/site-packages/trac/ticket/model.py", line 282, in save_changes Code fragment:

  1. old_values = self._old
  2. self._old = {}
  3. self.time_changed = when
  4. for listener in TicketSystem(self.env).change_listeners:
  5. listener.ticket_changed(self, comment, author, old_values)
  6. return True
  7. def get_changelog(self, when=None, db=None):
  8. """Return the changelog as a list of tuples of the form
  9. (time, author, field, oldvalue, newvalue, permanent).

Local variables: Name Value author u'sjors' cc cclist [] cnum u'4' comment u'But then again, that shouldn\'t be necessary. Around the community, this … cursor <trac.db.util.IterableCursor object at 0xafa526c> custom_fields [] db <trac.db.pool.PooledConnection object at 0xafa104c> f {'type': 'text', 'name': 'cc', 'label': 'Cc'} handle_ta True listener <likebackplugin.likebackplugin.LikeBackPlugin object at 0xacb85ec> old_values {} self <trac.ticket.model.Ticket object at 0xaf7376c> when datetime.datetime(2009, 6, 29, 20, 0, 59, 523283, tzinfo≤FixedOffset … when_ts 1246305659 # File "build/bdist.linux-i686/egg/likebackplugin/likebackplugin.py", line 39, in ticket_changed Local variables: Name Value author u'sjors' comment u'But then again, that shouldn\'t be necessary. Around the community, this … old_values {} self <likebackplugin.likebackplugin.LikeBackPlugin object at 0xacb85ec> ticket <trac.ticket.model.Ticket object at 0xaf7376c> values {'comment': u'But then again, that shouldn\'t be necessary. Around the … # File "/usr/lib/python2.5/urllib.py", line 1250, in urlencode

by dazjorz@…, 15 years ago

Attachment: tracerror.png added

Trac error report

in reply to:  5 comment:6 by Christian Boos, 15 years ago

Replying to dazjorz@…:

I just had the same issue.

No, you have an issue with the "likebackplugin" (no idea what this is), so please report that error to that plugin's maintainer.

comment:7 by dazjorz@…, 15 years ago

Oops, right, okay, sorry for the noise.

comment:8 by Christian Boos, 15 years ago

Keywords: needinfo removed
Resolution: wontfix
Status: newclosed

And for the original issue (in description), this looks like an AgiloForScrum issue (Agilo 0.7.3.3-r1417-20090313).

Please report it to them.

comment:9 by tumma72@…, 15 years ago

Keywords: config unicode added
Resolution: wontfix
Severity: criticalmajor
Status: closedreopened
Version: 0.11.40.11.5

Hi cboos, I had a look at this, and effectively the bug comes out with AgiloForScrum, but it is not an agilo bug, if you try to save a value using the config API that contains unicode characters inside, it will fail, and also break the whole config and trac environment. Also other plugins are using the Configuration to save data into the trac.ini, and for example the labels of custom fields are quite a natural place where people would like to use localized strings.

For what I found out, the config.py is "encoding" in utf-8 in two places… one in the Section.set() if the value is not None, and another time in the save() of the Configuration. Now till there is no true unicode character in the string, the double encode is not generating any error, as soon as there is a real unicode sequence inside… it breaks. At least I would suggest to put there a safeguard, something like:

                  for key, val in options:
                        if key in self[section].overridden:
                            fileobj.write('# %s = <inherited>\n' % key)
                        else:
                            val = val.replace(CRLF, '\n').replace('\n', '\n ')
                            try:
                                val = val.encode('utf-8')
                            except UnicodeDecodeError, e:
                                continue
                            fileobj.write('%s = %s\n' % (key, val))

So at least only a property will be skipped and not the whole config messed up, causing significant issues in having to reconfigure the whole project manually. If I come up with something more sensible than this, I'll let you know :-)

comment:10 by tumma72@…, 15 years ago

Here you go, I made it a patch, it is just a parachute for now, you may come up with something more sensible, but at least this avoids to destroy the whole config file, and catches alse error in the coercion to 'ascii' while writing to the file.

Index: trac/config.py
===================================================================
--- trac/config.py	(revision 8367)
+++ trac/config.py	(working copy)
@@ -208,8 +208,15 @@
                             fileobj.write('# %s = <inherited>\n' % key)
                         else:
                             val = val.replace(CRLF, '\n').replace('\n', '\n ')
-                            fileobj.write('%s = %s\n' % (key,
-                                                         val.encode('utf-8')))
+                            try:
+                                val = val.encode('utf-8')
+                            except UnicodeDecodeError, e:
+                                pass # we ignore this
+                            try:
+                                fileobj.write('%s = %s\n' % (key, val))
+                            except UnicodeDecodeError, e:
+                                continue # we go forward writing the rest
                     fileobj.write('\n')
             finally:
                 fileobj.close()

Also attached.

HTH Best ANdreaT

by tumma72@…, 15 years ago

Attachment: config.patch added

config.patch to guard from unicode properties values written in the config file

comment:11 by Christian Boos, 15 years ago

Well, val must be an unicode object at this point. If not, then it's a bug and we should fix that. Do you have any reproduction recipe I could try out?

I do have several non-ascii stuff in my trac.ini, and it's working fine, e.g.

[ticket-custom]
changelog = textarea
changelog.cols = 50
changelog.label = Changelög
changelog.rows = 3

comment:12 by tumma72@…, 15 years ago

Cc: tumma72@… added

Ok, may be you can try to help me, cause as of now I am getting puzzled myself :-) So I try to explain… if I send the string in unicode from inside an input field of a web form, it get in as req.args argument in unicode… apparently, and it is something like u'Bl\xf8d' that to me looks ok. See the console output of the server, with repr() and type()

Serving on 0.0.0.0:8001 view at http://127.0.0.1:8001/
Storing: blood.label u'Bl\xf8d' <type 'unicode'>
Storing: blood.order u'0' <type 'unicode'>
Storing: blood u'text' <type 'unicode'>

after this print I call the self.env.config.set() passing the parameters… after the self.env.config.save() and the result is an exception in the following code fragment:

                        if key in self[section].overridden:
                            fileobj.write('# %s = <inherited>\n' % key)
                        else:
                            val = val.replace(CRLF, '\n').replace('\n', '\n ')
                            fileobj.write('%s = %s\n' % (key,
                                                         val.encode('utf-8')))
                    fileobj.write('\n')
            finally:
                fileobj.close()
            self._old_sections = deepcopy(self.parser._sections)
        except Exception:

with Local variables:

NameValue
currentFalse
defaultNone
fileobj<closed file '/var/lib/trac/test_me_more/conf/trac.ini', mode 'w' at …
keyu'blood.label'
option'max_size'
options[('blood', u'text'), (u'blood.label', u'Bl\xf8d'), (u'blood.order', u'0')]
section'ticket-custom'
sections[('account-manager', [('authentication_url', u), ('force_passwd_change', …
self<Configuration '/var/lib/trac/test_me_more/conf/trac.ini'>
valu'Bl\xf8d'

Following the trace the error appears to be in the coercion of the utf-encoded string into the string to write into the file… here it breaks and the whole config is ending at the last valid line… messing up everything :-) So from here my suggestion to put at least a guard (see patch).

Now the puzzling part… if I write a simple python script that does the same thing on the same environment works:

# -*- coding: utf-8 -*-
from trac.env import Environment
from trac.util.text import to_unicode

def main():
    """This should break the config with unicode characters"""
    env = Environment('/var/lib/trac/test_me_more')
    value = u'Bl\xf8d'
    env.config.set('break-me', 'test', value)
    env.config.save()

if __name__ == '__main__':
    main()

So any idea? I am really starting to think that the mixture of headache and Friday evening is playing a role on me ;-)

Thanks ANdreaT

comment:13 by tumma72@…, 15 years ago

I forgot the trivial part… the error is:

Trac detected an internal error:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)

That is the Decoding to ASCII that apparently is done at line 212 of the piece above that is the call to val.encode('utf-8')

Sorry for omitting this in the before post :-(

Ciao ANdreaT

comment:14 by tumma72@…, 15 years ago

Don't hate me I am trying to figure this out… the same error is happening if you take the sting in unicode and you try to encode it twice, that is what according to my first analysis was happening:

>>> test = u'Bl\xf8d'
>>> test.encode('utf-8')
'Bl\xc3\xb8d'
>>> test.encode('utf-8').encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)
>>>

It is the exact same error, I thought the reason is that the first time the encoding is done in config.py 410:

        if value is None:
            self.overridden[name] = True
            value = ''
        else:
==>   value = to_unicode(value).encode('utf-8')
        return self.config.parser.set(self.name, name, value)

And than again here, in save() config.py 210:

                        if key in self[section].overridden:
                            fileobj.write('# %s = <inherited>\n' % key)
                        else:
                            val = val.replace(CRLF, '\n').replace('\n', '\n ')
                            fileobj.write('%s = %s\n' % (key,
==>                                                                   val.encode('utf-8')))
                    fileobj.write('\n')

But as said if you try to write directly it seems to work :-(

Ideas?

comment:15 by Christian Boos, 15 years ago

Strange indeed. I added this change:

  • trac/config.py

     
    181181        """Write the configuration options to the primary file."""
    182182        if not self.filename:
    183183            return
     184
     185        self.set('break-me', 'test', u'Bl\xf8d')
    184186
    185187        # Only save options that differ from the defaults
    186188        sections = []

And triggered a save in the web admin, then looked at the .ini:

[break-me]
test = Blød

So if I understand you correctly, you would have got an error instead. Can you try? If it works for you then I didn't understand you correctly and you could give me some diff to reproduce the issue :-)

comment:16 by tumma72@…, 15 years ago

Yes it is breaking if I do it from an Admin page module… As said with the script on the environment is working just fine. Something wired must happen that I am not seeing here. I made another test, from an admin page trying to write the config, as per the example you made:

    self.env.config.set('break-me', 'test', u'Bl\xf8d')
    print "Saving the config..."
    for opt, value in self.env.config.parser._sections['break-me'].items():
        print opt, repr(value)
    self.env.config.save()

It is breaking and the output on the console is:

Saving the config...
__name__ 'break-me'
test 'Bl\xc3\xb8d'

As you can see the test key is already an encoded string… this happens because the set() method is encoding it… that when the save() is called it is encoded again… than it explodes, with the same error as if you would do:

>>> test = 'Bl\xc3\xb8d'
>>> test.encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)

So I am really puzzled :-(

comment:17 by Christian Boos, 15 years ago

I also can see:

__name__ 'break-me'
test 'Bl\xc3\xb8d'

This is expected. I think you missed the fact that the ConfigParser class is not unicode aware, so we have to store keys and values in the parser as str objects, utf-8 encoded. So that's what set() does.

I think we actually don't do it yet for keys or even section names, and that counts as a bug ;-)

Then, in save(), we retrieve the values from that ConfigParser and use to_unicode(), which produces an unicode value from the str (even if by extraordinaire you'd get an unicode value out of the parser, to_unicode(uni) yields uni unmodified).

Last time I looked (0.7.2 I think), you had some wrapping code around the config. Maybe now you're doing something more intrusive?

Again, the problem comes from the fact you're having a str object instead of an unicode one, and in the trac/config.py save() code I don't yet see how this can happen. Maybe apply:

  • trac/config.py

     
    181181        """Write the configuration options to the primary file."""
    182182        if not self.filename:
    183183            return
     184
     185        self.set('break-me', 'test', u'Bl\xf8d')
     186        for opt, value in self.parser._sections['break-me'].items():
     187            print opt, repr(value)
    184188
    185189        # Only save options that differ from the defaults
    186190        sections = []
     
    192196                    default = self.parent.get(section, option)
    193197                current = self.parser.has_option(section, option) and \
    194198                          to_unicode(self.parser.get(section, option))
     199                print repr(option), repr(current)
    195200                if current is not False and current != default:
    196201                    options.append((option, current))
    197202            if options:
    198203                sections.append((section, sorted(options)))
     204        print repr(sections)
    199205
    200206        try:
    201207            fileobj = open(self.filename, 'w')

and from there we can see what we have for differences?

I get:

test 'Bl\xc3\xb8d'
...
'test' u'Bl\xf8d'
...
[... ('break-me', [('test', u'Bl\xf8d')]),...]

in reply to:  17 comment:18 by Christian Boos, 15 years ago

Milestone: 0.11.6
Owner: set to Christian Boos
Status: reopenednew

I think we actually don't do it yet for keys or even section names, and that counts as a bug ;-)

After chatting with Andrea, we found out (he found out actually ;-) ), that the above is really the cause of the backtrace: if an unicode input is given for the key in config.set(section, key, value), then it's stored as unicode in the ConfigParser and later the "%s = %s\n" = (key, val.encode('utf-8')) line will fail, as key being unicode here will force the conversion of the utf-8 str to unicode…

Working on a fix to accept unicode input on section and key arguments of the methods, as it should be.

comment:19 by Andrea Tomasini <andrea.tomasini@…>, 15 years ago

Thanks Christian, in the meanwhile for the AgiloForScrum users, there will be a new release fixing this issue today… around 16:00 GMT+2 :-)

by Christian Boos, 15 years ago

Consistently handle conversion to and from utf-8 when storing resp. retrieving from the ConfigParser, not only for values but also for section and key names.

comment:20 by Christian Boos, 15 years ago

Cc: osimons added
Keywords: review added
Status: newassigned

With attachment:t8276-unicode-for-sections-and-keys-r8424.diff, the section names and key names can be given to the Config and Section methods as unicode and they will be properly encoded to UTF-8 strings before being stored in the parser.

I've also renamed the name method argument to key, in order to better distinguish it from the section name (self.name in Section class).

Please review and test.

comment:21 by andrea Tomasini <andrea.tomasini@…>, 15 years ago

Works for me thanks :-) I had to rename the call in a couple of places… but works fine now ;-)

comment:22 by osimons, 15 years ago

Patch makes sense, tests pass. I've installed it on my dev setup with various plugins+++, and all seems to work well.

Should be OK to commit as far as I can tell.

comment:23 by Christian Boos, 15 years ago

Resolution: fixed
Status: assignedclosed

Great, thanks for the review both of you!

Patch applied in [8458].

comment:24 by Christian Boos, 15 years ago

Resolution: fixed
Status: closedreopened

Just found one problem with the change.

Now the config keys are returned as unicode objects, which is good except in some places where unicode objects can't be used, e.g. in the following code:

Traceback (most recent call last):
  File "C:\Workspace\src\trac\repos\trunk\trac\web\main.py", line 467, in _dispatch_request
    dispatcher.dispatch(req)
  File "C:\Workspace\src\trac\repos\trunk\trac\web\main.py", line 212, in dispatch
    resp = chosen_handler.process_request(req)
  File "C:\Workspace\src\trac\repos\trunk\trac\ticket\web_ui.py", line 190, in process_request
    return self._process_ticket_request(req)
  File "C:\Workspace\src\trac\repos\trunk\trac\ticket\web_ui.py", line 540, in _process_ticket_request
    get_reporter_id(req, 'author'), field_changes)
  File "C:\Workspace\src\trac\repos\trunk\trac\ticket\web_ui.py", line 1231, in _insert_ticket_data
    fields = self._prepare_fields(req, ticket)
  File "C:\Workspace\src\trac\repos\trunk\trac\ticket\web_ui.py", line 1132, in _prepare_fields
    field['rendered'] = self._query_link(req, name, ticket[name])
  File "C:\Workspace\src\trac\repos\trunk\trac\ticket\web_ui.py", line 1103, in _query_link
    return tag.a(text or value, href=req.href.query(**args))
TypeError: <lambda>() keywords must be strings

args is the following:

{'status': u'!closed', u'customer': ...

Before, it used to be simply 'customer' (it's the name of ticket custom field).

comment:25 by Felix Schwarz <felix.schwarz@…>, 15 years ago

Cc: felix.schwarz@… added

comment:26 by Christian Boos, 15 years ago

So after the merge of r8458 as a part of r8469, I also committed the fix for the error shown in comment:24, as r8471.

This particular error was only concerning trunk, but I also spotted a few other places which could benefit from a similar fix. The question is, should r8471 (and the side fix for Href in r8470) be backported for 0.11.6dev?

comment:27 by Christian Boos, 15 years ago

Resolution: fixed
Status: reopenedclosed

On trunk, r8470 and r8470 needed a follow-up, done by Remy in r8563.

I think we can leave the 0.11-stable branch as it is, so I'm closing.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Christian Boos.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Christian Boos to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.