This file is indexed.

/usr/share/pyshared/JobService/settings.py is in jobservice 0.8.0-0ubuntu4.

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
# This file is part of jobservice.
# Copyright 2010 Jacob Peddicord <jpeddicord@ubuntu.com>
#
# jobservice is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# jobservice is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with jobservice.  If not, see <http://www.gnu.org/licenses/>.

import logging
from os import rename
from os.path import exists
from cStringIO import StringIO
from subprocess import Popen, PIPE
from xml.etree.cElementTree import ElementTree
import JobService

log = logging.getLogger('sls')

class ServiceSettings:
    """Service-level settings (SLS) for a single service."""
    
    def __init__(self, jobname):
        self.jobname = jobname
        if '/' in jobname:
            basename = jobname.split('/')[0]
        else:
            basename = jobname
        self.filename = ''
        for loc in (JobService.SLS_LOCAL, JobService.SLS_SYSTEM, JobService.SLS_DEFAULT):
            if not loc:
                continue
            self.filename = loc.format(basename)
            if exists(self.filename):
                log.debug('Using ' + self.filename)
                break
        self.tree = ElementTree()
        self.tree.parse(self.filename)
        self.selements = {}
        self.settings = {}
    
    def get_all_settings(self):
        """Return a list of setting names available on this service."""
        lst = []
        for e in self.tree.findall('setting'):
            name = e.get('name')
            self.selements[name] = e
            lst.append(name)
        return lst
    
    def get_setting(self, name, lang=''):
        """Return details of a specific setting by name in the format:
        (name, type, description, current, possible[], constraints{})
        """
        ele = self.selements[name]
        # current value
        raw = ''
        data = ele.find('data')
        if data != None:
            fixed = data.get('val')
            if fixed:
                raw = fixed
            else:
                # find the first source we can obtain a value from
                for p in ele.findall('data/parse'):
                    parse = p.text.replace('%n', name)
                    parse = parse.replace('%j', self.jobname)
                    # load from file
                    if p.get('file'):
                        prescan = p.get('after')
                        with open(p.get('file')) as f:
                            raw = self._raw_value(parse, f, prescan=prescan)
                        break
                    # load from external helper
                    elif p.get('get'):
                        cmd = p.get('get').replace('%j', self.jobname)
                        proc = Popen(cmd, shell=True, stdout=PIPE)
                        sio = StringIO(proc.communicate()[0])
                        raw = self._raw_value(parse, sio)
                        break
        # get available values
        values = []
        self.settings[name] = raw
        for v in ele.findall('values/value'):
            values.append((v.get('name'), v.findtext('description', '')))
            if v.findtext('raw') == raw:
                self.settings[name] = v.get('name')
        vals = ele.find('values')
        constraints = vals.attrib if vals != None else {}
        return (name, ele.get('type'), ele.findtext('description'),
                self.settings[name], values, constraints)
    
    def set_setting(self, name, value):
        ele = self.selements[name]
        # don't do anything with an empty data element
        data = ele.find('data')
        if not len(data):
            return
        # translate the value into something for the file
        newval = value
        for v in ele.findall('values/value'):
            if v.get('name') == value:
                newval = v.findtext('raw')
                break
        # write out values
        for p in data.findall('parse'):
            parse = p.text.replace('%n', name)
            parse = parse.replace('%j', self.jobname)
            # write to file
            if p.get('file'):
                filename = p.get('file')
                prescan = p.get('after')
                # write the new values
                read = open(filename)
                write = open('{0}.new'.format(filename), 'w')
                self._raw_value(parse, read, write, newval, prescan)
                write.close()
                read.close()
                # replace the original with backup
                rename(read.name, '{0}~'.format(read.name))
                rename(write.name, read.name)
            # send to an external program for processing
            elif p.get('set'):
                cmd = p.get('set').replace('%j', self.jobname)
                proc = Popen(cmd, shell=True, stdin=PIPE)
                proc.communicate(parse.replace('%s', newval))
    
    def _raw_value(self, parse, read, write=None, newval=None, prescan=None):
        """
        Read or write (if write is not None) a raw value to a conf file.
        read & write are file objects.
        
        If the setting line has been commented, it will still be read normally.
        On write, the comment will be removed. Default settings are assumed
        to be commented out, so when changing them we'll need to uncomment.
        
        If "prescan" is set, will not begin scanning until the string provided
        has been passed.
        """
        assert parse
        before, after = parse.strip().split('%s')
        value = False
        scanning = False if prescan else True
        for line in read:
            if not scanning and prescan:
                if line.find(prescan) != -1:
                    scanning = True
            beforepos = line.find(before)
            # the last check is to make sure this is the right line,
            # but we only perform it if we _might_ have it for speed.
            if scanning and beforepos >= 0 and line.lstrip(' #;\t').find(before) == 0:
                if write:
                    data = ''.join((line[:beforepos], before, newval, after, '\n'))
                    write.write(data.lstrip('#;'))
                else:
                    start = beforepos + len(before)
                    if after:
                        value = line[start:line.find(after, start)]
                    else:
                        value = line[start:len(line)-1] # \n at the end
                    return value
                continue
            if write:
                write.write(line)
        return ''