This file is indexed.

/usr/share/pyshared/MoinMoin/userprefs/prefs.py is in python-moinmoin 1.9.3-1ubuntu2.3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - Preferences Form

    @copyright: 2001-2004 Juergen Hermann <jh@web.de>,
                2003-2007 MoinMoin:ThomasWaldmann
    @license: GNU GPL, see COPYING for details.
"""

import time
from MoinMoin import user, util, wikiutil, events
from MoinMoin.theme import load_theme_fallback
from MoinMoin.widget import html
from MoinMoin.userprefs import UserPrefBase


#################################################################
# This is still a mess.
#
# The plan for refactoring would be:
# split the plugin into multiple preferences pages:
#    - account details (name, email, timezone, ...)
#    - wiki settings (editor, fancy diffs, theme, ...)
#    - quick links (or leave in wiki settings?)
####


class Settings(UserPrefBase):
    def __init__(self, request):
        """ Initialize user settings form. """
        UserPrefBase.__init__(self, request)
        self.request = request
        self._ = request.getText
        self.cfg = request.cfg
        _ = self._
        self.title = _("Preferences")
        self.name = 'prefs'

    def _decode_pagelist(self, key):
        """ Decode list of pages from form input

        Each line is a page name, empty lines ignored.

        @param key: the form key to get
        @rtype: list of unicode strings
        @return: list of normalized names
        """
        text = self.request.form.get(key, '')
        text = text.replace('\r', '')
        items = []
        for item in text.split('\n'):
            item = item.strip()
            if not item:
                continue
            items.append(item)
        return items

    def _save_user_prefs(self):
        _ = self._
        form = self.request.form
        request = self.request

        if not 'name' in request.user.auth_attribs:
            # Require non-empty name
            new_name = wikiutil.clean_input(form.get('name', request.user.name)).strip()

            # Don't allow changing the name to an invalid one
            if not user.isValidName(request, new_name):
                return 'error', _("""Invalid user name {{{'%s'}}}.
Name may contain any Unicode alpha numeric character, with optional one
space between words. Group page name is not allowed.""", wiki=True) % wikiutil.escape(new_name)

            # Is this an existing user trying to change information or a new user?
            # Name required to be unique. Check if name belong to another user.
            existing_id = user.getUserId(request, new_name)
            if existing_id is not None and existing_id != request.user.id:
                return 'error', _("This user name already belongs to somebody else.")

            if not new_name:
                return 'error', _("Empty user name. Please enter a user name.")

            # done sanity checking the name, set it
            request.user.name = new_name


        if not 'email' in request.user.auth_attribs:
            # try to get the email
            new_email = wikiutil.clean_input(form.get('email', request.user.email)).strip()

            # Require email
            if not new_email and 'email' not in request.cfg.user_form_remove:
                return 'error', _("Please provide your email address. If you lose your"
                                  " login information, you can get it by email.")

            # Email should be unique - see also MoinMoin/script/accounts/moin_usercheck.py
            if new_email and request.cfg.user_email_unique:
                other = user.get_by_email_address(request, new_email)
                if other is not None and other.id != request.user.id:
                    return 'error', _("This email already belongs to somebody else.")

            # done checking the email, set it
            request.user.email = new_email


        if not 'jid' in request.user.auth_attribs:
            # try to get the jid
            new_jid = wikiutil.clean_input(form.get('jid', '')).strip()

            jid_changed = request.user.jid != new_jid
            previous_jid = request.user.jid

            if new_jid and request.cfg.user_jid_unique:
                other = user.get_by_jabber_id(request, new_jid)
                if other is not None and other.id != request.user.id:
                    return 'error', _("This jabber id already belongs to somebody else.")

            if jid_changed:
                set_event = events.JabberIDSetEvent(request, new_jid)
                unset_event = events.JabberIDUnsetEvent(request, previous_jid)
                events.send_event(unset_event)
                events.send_event(set_event)

            # done checking the JID, set it
            request.user.jid = new_jid


        if not 'aliasname' in request.user.auth_attribs:
            # aliasname
            request.user.aliasname = wikiutil.clean_input(form.get('aliasname', '')).strip()

        # editor size
        request.user.edit_rows = util.web.getIntegerInput(request, 'edit_rows',
                                                          request.user.edit_rows, 0, 999)

        # try to get the editor
        request.user.editor_default = wikiutil.clean_input(form.get('editor_default', self.cfg.editor_default))
        request.user.editor_ui = wikiutil.clean_input(form.get('editor_ui', self.cfg.editor_ui))

        # time zone
        request.user.tz_offset = util.web.getIntegerInput(request, 'tz_offset',
                                                          request.user.tz_offset, -84600, 84600)

        # datetime format
        try:
            dt_d_combined = Settings._date_formats.get(form['datetime_fmt'], '')
            request.user.datetime_fmt, request.user.date_fmt = dt_d_combined.split(' & ')
        except (KeyError, ValueError):
            request.user.datetime_fmt = '' # default
            request.user.date_fmt = '' # default

        # try to get the (optional) theme
        theme_name = wikiutil.clean_input(form.get('theme_name', self.cfg.theme_default))
        if theme_name != request.user.theme_name:
            # if the theme has changed, load the new theme
            # so the user has a direct feedback
            # WARNING: this should be refactored (i.e. theme load
            # after userform handling), cause currently the
            # already loaded theme is just replaced (works cause
            # nothing has been emitted yet)
            request.user.theme_name = theme_name
            if load_theme_fallback(request, theme_name) > 0:
                theme_name = wikiutil.escape(theme_name)
                return 'error', _("The theme '%(theme_name)s' could not be loaded!") % locals()

        # try to get the (optional) preferred language
        request.user.language = wikiutil.clean_input(form.get('language', ''))
        if request.user.language == u'': # For language-statistics
            from MoinMoin import i18n
            request.user.real_language = i18n.get_browser_language(request)
        else:
            request.user.real_language = ''

        # I want to handle all inputs from user_form_fields, but
        # don't want to handle the cases that have already been coded
        # above.
        # This is a horribly fragile kludge that's begging to break.
        # Something that might work better would be to define a
        # handler for each form field, instead of stuffing them all in
        # one long and inextensible method.  That would allow for
        # plugins to provide methods to validate their fields as well.
        already_handled = ['name', 'email',
                           'aliasname', 'edit_rows', 'editor_default',
                           'editor_ui', 'tz_offset', 'datetime_fmt',
                           'theme_name', 'language', 'real_language', 'jid']
        for field in self.cfg.user_form_fields:
            key = field[0]
            if ((key in self.cfg.user_form_disable)
                or (key in already_handled)):
                continue
            default = self.cfg.user_form_defaults[key]
            value = form.get(key, default)
            value = wikiutil.clean_input(value)
            setattr(request.user, key, value)

        # checkbox options
        for key, label in self.cfg.user_checkbox_fields:
            if key not in self.cfg.user_checkbox_disable and key not in self.cfg.user_checkbox_remove:
                value = form.get(key, "0")
                try:
                    value = int(value)
                except ValueError:
                    # value we got is crap, do not setattr this value, just pass
                    pass
                else:
                    setattr(request.user, key, value)

        # quicklinks for navibar
        request.user.quicklinks = self._decode_pagelist('quicklinks')

        # save data
        request.user.save()
        if request.user.disabled:
            # set valid to false so the current request won't
            # show the user as logged-in any more
            request.user.valid = False

        result = _("User preferences saved!")
        return result


    def handle_form(self):
        request = self.request
        form = request.form

        if 'cancel' in form:
            return

        if request.method != 'POST':
            return

        if not wikiutil.checkTicket(request, form['ticket']):
            return

        if 'save' in form: # Save user profile
            return self._save_user_prefs()

    # form generation part

    _date_formats = { # datetime_fmt & date_fmt
        'iso': '%Y-%m-%d %H:%M:%S & %Y-%m-%d',
        'us': '%m/%d/%Y %I:%M:%S %p & %m/%d/%Y',
        'euro': '%d.%m.%Y %H:%M:%S & %d.%m.%Y',
        'rfc': '%a %b %d %H:%M:%S %Y & %a %b %d %Y',
    }

    def _tz_select(self, enabled=True):
        """ Create time zone selection. """
        tz = 0
        if self.request.user.valid:
            tz = int(self.request.user.tz_offset)

        options = []
        now = time.time()
        for halfhour in range(-47, 48):
            offset = halfhour * 1800
            t = now + offset

            options.append((
                str(offset),
                '%s [%s%s:%s]' % (
                    time.strftime(self.cfg.datetime_fmt, util.timefuncs.tmtuple(t)),
                    "+-"[offset < 0],
                    "%02d" % (abs(offset) / 3600),
                    "%02d" % (abs(offset) % 3600 / 60),
                ),
            ))

        return util.web.makeSelection('tz_offset', options, str(tz), 1, False, enabled)


    def _dtfmt_select(self):
        """ Create date format selection. """
        _ = self._
        try:
            dt_d_combined = '%s & %s' % (self.request.user.datetime_fmt, self.request.user.date_fmt)
            selected = [
                k for k, v in self._date_formats.items()
                    if v == dt_d_combined][0]
        except IndexError:
            selected = ''
        options = [('', _('Default'))] + self._date_formats.items()

        return util.web.makeSelection('datetime_fmt', options, selected)


    def _lang_select(self, enabled=True):
        """ Create language selection. """
        from MoinMoin import i18n
        _ = self._
        cur_lang = self.request.user.valid and self.request.user.language or ''
        langs = i18n.wikiLanguages().items()
        langs.sort(lambda x, y: cmp(x[1]['x-language'], y[1]['x-language']))
        options = [('', _('<Browser setting>'))]
        for lang in langs:
            name = lang[1]['x-language']
            options.append((lang[0], name))

        return util.web.makeSelection('language', options, cur_lang, 1, False, enabled)

    def _theme_select(self):
        """ Create theme selection. """
        cur_theme = self.request.user.valid and self.request.user.theme_name or self.cfg.theme_default
        options = [("<default>", "<%s>" % self._("Default"))]
        for theme in wikiutil.getPlugins('theme', self.request.cfg):
            options.append((theme, theme))

        return util.web.makeSelection('theme_name', options, cur_theme)

    def _editor_default_select(self):
        """ Create editor selection. """
        editor_default = self.request.user.valid and self.request.user.editor_default or self.cfg.editor_default
        options = [("<default>", "<%s>" % self._("Default"))]
        for editor in ['text', 'gui', ]:
            options.append((editor, editor))
        return util.web.makeSelection('editor_default', options, editor_default)

    def _editor_ui_select(self):
        """ Create editor selection. """
        editor_ui = self.request.user.valid and self.request.user.editor_ui or self.cfg.editor_ui
        options = [("<default>", "<%s>" % self._("Default")),
                   ("theonepreferred", self._("the one preferred")),
                   ("freechoice", self._("free choice")),
                  ]
        return util.web.makeSelection('editor_ui', options, editor_ui)


    def create_form(self):
        """ Create the complete HTML form code. """
        _ = self._
        request = self.request
        self._form = self.make_form()

        if request.user.valid:
            buttons = [('save', _('Save')), ('cancel', _('Cancel')), ]
            uf_remove = self.cfg.user_form_remove
            uf_disable = self.cfg.user_form_disable
            for attr in request.user.auth_attribs:
                uf_disable.append(attr)
            for key, label, type, length, textafter in self.cfg.user_form_fields:
                default = self.cfg.user_form_defaults[key]
                if not key in uf_remove:
                    if key in uf_disable:
                        self.make_row(_(label),
                                  [html.INPUT(type=type, size=length, name=key, disabled="disabled",
                                   value=getattr(request.user, key)), ' ', _(textafter), ])
                    else:
                        self.make_row(_(label),
                                  [html.INPUT(type=type, size=length, name=key, value=getattr(request.user, key)), ' ', _(textafter), ])

            if not self.cfg.theme_force and not "theme_name" in self.cfg.user_form_remove:
                self.make_row(_('Preferred theme'), [self._theme_select()])

            if not self.cfg.editor_force:
                if not "editor_default" in self.cfg.user_form_remove:
                    self.make_row(_('Editor Preference'), [self._editor_default_select()])
                if not "editor_ui" in self.cfg.user_form_remove:
                    self.make_row(_('Editor shown on UI'), [self._editor_ui_select()])

            if not "tz_offset" in self.cfg.user_form_remove:
                self.make_row(_('Time zone'), [
                    _('Your time is'), ' ',
                    self._tz_select(),
                    html.BR(),
                    _('Server time is'), ' ',
                    time.strftime(self.cfg.datetime_fmt, util.timefuncs.tmtuple()),
                    ' (UTC)',
                ])

            if not "datetime_fmt" in self.cfg.user_form_remove:
                self.make_row(_('Date format'), [self._dtfmt_select()])

            if not "language" in self.cfg.user_form_remove:
                self.make_row(_('Preferred language'), [self._lang_select()])

            # boolean user options
            bool_options = []
            checkbox_fields = self.cfg.user_checkbox_fields
            checkbox_fields.sort(lambda a, b: cmp(a[1](_), b[1](_)))
            for key, label in checkbox_fields:
                if not key in self.cfg.user_checkbox_remove:
                    bool_options.extend([
                        html.INPUT(type="checkbox", name=key, value="1",
                            checked=getattr(request.user, key, 0),
                            disabled=key in self.cfg.user_checkbox_disable and True or None),
                        ' ', label(_), html.BR(),
                    ])
            self.make_row(_('General options'), bool_options, valign="top")

            self.make_row(_('Quick links'), [
                html.TEXTAREA(name="quicklinks", rows="6", cols="50")
                    .append('\n'.join(request.user.getQuickLinks())),
            ], valign="top")

            self._form.append(html.INPUT(type="hidden", name="action", value="userprefs"))
            self._form.append(html.INPUT(type="hidden", name="handler", value="prefs"))

            ticket = wikiutil.createTicket(request)
            self._form.append(html.INPUT(type="hidden", name="ticket", value="%s" % ticket))

        # Add buttons
        button_cell = []
        for name, label in buttons:
            if not name in self.cfg.user_form_remove:
                button_cell.extend([
                    html.INPUT(type="submit", name=name, value=label),
                    ' ',
                ])
        self.make_row('', button_cell)

        return unicode(self._form)