This file is indexed.

/usr/share/pyshared/MeMaker/motor.py is in memaker 1.5-0ubuntu5.

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
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Motor - Merge XML v.0.2a
# Copyright 2007 Christopher Denter (motor AT the-space-station DOT com)
# Thanks to Aaron Spike for getting me into the whole thing and helping 
# with early lxml-based versions. :)
# Copyright 2008 Gryc Ueusp <gryc.ueusp@gmail.com>
#
# see __doc__ of class ObjectStack for further information.
#
# This program 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.
#
# This program 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 this program. See the file LICENSE.
# If not, see <http://www.gnu.org/licenses/>.

import xml.dom.minidom as xdm                   # Yes, we now use pythons in-built XML-functionality 
#from xml.dom import ext                        # for DOM to get rid of extra dependencies we actually don't need
import re

class ObjectStack(object):
    """
    You can think of objects of this class as a face with certain 'features'
    such as a nose, eyes, mouth and so forth. You can interactively add new
    or other features and delete / replace other ones you don't like. All
    features are stored within a single xml-powered hierarchy. You can print
    the contents of our face (the xml/svg-code) to the screen or save it to
    disk. Objects of this class keep those face information.
    """
    def __init__(self, debug=False):
        """
        create a new skeleton into which we can embed our features.
        """
        self.clearMe()
        self.feature_types = ['ear', 'head', 'mouth', 'nose', 'eye', 'eyebrow', 'beard', 'hair', 'glasses', 'hat', 'accessory']
        self.debug = debug

    def clearMe(self):
        """
        the title says it: clear the contents of our avatar.
        """
        self.base = xdm.parseString(\
        '''
        <svg
        xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        xmlns:memaker="http://launchpad.net/memaker"
	    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	    xmlns:cc="http://web.resource.org/cc/"
	    xmlns:dc="http://purl.org/dc/elements/1.1/"
	    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
	    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd">
        </svg>
        ''')
        self.features = {}
        self.featureList = []
        self.sortedFeatures = []

    def makeIdsUnique(self, documentElement, featuretype='unknown'):
        """
        Makes id attributes unique by appending the name of the feature that
        they came from to their previous id attribute.
        Uses helper method appendElement() and replaceAttribute()
        Then, replace each reference to the old id in the rest of the feature
        with its new id.
        Hopefully this wont do something really stupid I'll regret later...
        """
        replacements = []
        documentElement = self.appendElement(documentElement, replacements, 'id', featuretype)

        for replacement in replacements:
            documentElement = self.replaceAttribute(documentElement, replacement[0], replacement[1])
        return documentElement

    def replaceAttribute(self, documentElement, original='', replacement=''):
        """
        Replaces all instances of original in documentElement with replacement,
        if original is immediately followed by `"`, `'`, `$`, or `)`, and if
        original is an attribute.
        """
        for childnode in documentElement.childNodes:
            if childnode.nodeType == childnode.ELEMENT_NODE:
                if childnode.attributes.items():
                    for attribute in childnode.attributes.items():
                        if re.compile(""+original+"('|\"|$|\))").search(attribute[1], 1):
                            replacedattribute = re.sub(original, replacement, attribute[1])
                            childnode.setAttribute(attribute[0], replacedattribute)
                            if self.debug: print 'replacing '+original+' with '+replacement
                    childnode = self.replaceAttribute(childnode, original, replacement) #Mmmm Recursive Functions! :D
        return documentElement

    def appendElement(self, documentElement, replacements, attribute_to_append='id', text_to_append='appended2'):
        """
        Takes documentElement, iterates over it and appends text_to_append to 
        the value of attribute_to_append.
        It ignores attribute values that start with "_", as inkscape doesnt start
        its attributes with "_", and if you really need your ids to be the same 
        coming out as they go in, you should change them yourself and prefix them 
        with "_".
        This is probably "Bad", but it's better than unilaterally changing
        ids that a user would have meticulously set by hand.
        Returns a documentElement with all replacements replaced.
        """
        #I'd like to note that this shouldnt be 5 indentation levels deep. This is bad.
        for childnode in documentElement.childNodes:
            if childnode.nodeType == childnode.ELEMENT_NODE:
                if childnode.attributes.items():
                    for attribute in childnode.attributes.items():
                        if attribute[0] == attribute_to_append:
                            if attribute[1][0] != "_":
                                childnode.setAttribute(attribute_to_append, attribute[1]+text_to_append)
                                replacements.append((attribute[1], attribute[1]+text_to_append))
                                if self.debug: print 'appending '+text_to_append+' to '+attribute_to_append
                    childnode = self.appendElement(childnode, replacements, attribute_to_append, text_to_append) #Mmmm Recursive Functions! :D
        return documentElement

    def amIEmpty(self):
        """
        check if this object displays nothing
        """
        if self.features != {} and self.featureList != []:
            return False
        else:
            return True

    def createGTag(self, path, featureType):
        """
        We store different features in different <g/>-Tags and place an attribute that
        tells us from which file that feature came. We can use that later to get a feature
        by its attribute in order to move it, replace it or delete it.
        """
        g = xdm.parseString("<g></g>")
        g.childNodes[0].setAttribute("memaker:file", "%s" % featureType)
        self.features[featureType] = path                     # the operating-system already assures that there are only unique paths
        return g.documentElement

    def writeToFile(self, filename="Me.svg"):
        """
        write the contents of an svgObject to a file
        """
        try:                                                #fetch I/O-Errors
            dummy = open(filename, "w")
            dummy.write(self.printMe())
            dummy.close()
        except IOError, inst:
            print "Unexpected Error '%s' while writing to '%s'. Do you have writing permissions?" % (inst, filename)

    def printMe(self):
        """
        In case one needs the contents of the xml-file this object keeps, return them to the caller.
        """
        return self.base.toprettyxml()                          # well, that was hard, wasn't it? :)

    def addFeature(self, path, featureType, save=False, filename="Me.svg"):
        """
        call addFeature() with a path to a svg-file. The function then takes all the contents
        of that files <svg/>-Tags and adds them to the svg-file this object keeps.
        """
        if featureType not in self.feature_types:
            print "unsupported featureType! must be one of the following:"
            for featype in self.feature_types:
                print featype,
            return None

        elif path in self.features.values():
            if self.debug: print "That feature has already been added to this face. I can't add it twice. Aborting..."
            return None

        else:
            if featureType in self.featureList:                 # we already have an item of that kind. remove the old one first!
                self.deleteFeature(featureType)
                if self.debug: print "replacing old feature"

            self.featureList.append(featureType)

            try:                                                # fetch I/O-Errors
                new_entry = xdm.parse(path)
            except IOError, inst:
                print "Unexpected Error: %s \nwhile parsing '%s'. \n" \
                      "Is there a file? Is it readable and parsable?" % (inst, path)
                return None                                     # abort in case we couldn't parse the file...

            if self.debug:
                print "Parsing: '%s'..." % (path)
                #print new_entry.toprettyxml()                  # turn this on if you are really crazy

            new_entry = self.makeIdsUnique(new_entry, featureType)

            cloned = new_entry.getElementsByTagName("svg")[0]
            gtag = self.base.documentElement.appendChild(self.createGTag(path, featureType))

            while cloned.hasChildNodes():                       # appendChild() REMOVES the element it appends! 
                if self.debug: print "Adding: '%s'..." % (cloned.firstChild)
                gtag.appendChild(cloned.firstChild)

            if self.debug:
                print self.features
                print "This face now contains: " + str(self.featureList)

            self.sortFeatures()

            return self

    def raiseFeature(self, featureType):
        """
        If we want to raise a feature, we need to move it in the downward direction in the xml-code.
        """
        if self.hasFeature(featureType):
            to_move = self.getFeature(featureType)[0]
            if to_move.nextSibling != None:                         # That'd mean that it is already on top.
                tmp = self.base.documentElement.removeChild(to_move.nextSibling)
                self.base.documentElement.insertBefore(tmp, to_move)

#                index = self.featureList.index(featureType)
#                print featureType, index, self.featureList
#                self.featureList[index], self.featureList[index+1] = self.featureList[index+1], self.featureList[index]
#
#                self.sortFeatures()

                if self.debug: print "Successfully raised %s!" % (featureType)
            else:
                if self.debug:
                    print "This feature is already on top. It cannot be raised higher."
                    print self.featureList
                    print self.features
                return True

    def lowerFeature(self, featureType):
        """
        In order to lower a feature we can just raise the feature preceding it.
        """
        if self.hasFeature(featureType):
            to_move = self.getFeature(featureType)[0]
            if to_move.previousSibling.nodeType == 1 and to_move.previousSibling.hasAttribute("memaker:file"):
                self.raiseFeature(self.getFeatureType(to_move.previousSibling))
                if self.debug: print "and thus successfully lowered %s!" % (featureType)
            else:
                if self.debug: print "This feature is already at the lowest possible position"
                return True

    def deleteFeature(self, featureType):
        """
        delete a feature. get it and its parentNode and delete
        it from its parentNode. The deleted feature is returned.
        """
        if self.hasFeature(featureType):
            feature, parentNode = self.getFeature(featureType)
            del self.features[featureType]
            self.featureList.remove(featureType)
            return parentNode.removeChild(feature)                      # let DOM do the trick

    def hasFeature(self, featureType):
        """
        check if our face has the feature of type featureType.
        """
        if featureType in self.featureList:
            if self.debug: print "found feature"
            return True
        else:
            if self.debug: print "There is no such feature!"
            return False

    def replaceFeature(self, path, featureType):
        """
        replace an old feature with a new one. expects a path to the new feature and which feature to be removed.
        you can only replace features of the same type
        """
        pass

    def getFeatureType(self, feature):
        """
        get the original path of a feature
        """
        return feature.getAttribute("memaker:file")

    def getFeature(self, featureType, attribute="memaker:file"):
        """
        get a Feature by the attribute we previously assigned it (as we added it to the face this object keeps).
        If we find the feature, we return it. Otherwise we return None.
        """
        if featureType not in self.feature_types:
            print "featureType NOT KNOWN!"

        if self.hasFeature(featureType):
            for feature in self.base.getElementsByTagName("g"):        # we iterate over all <g/>-Tags
                if feature.hasAttribute(attribute):                    # if one of those has the attribute we are looking for
                    actual_value = feature.getAttribute(attribute)     # we get that attributes value.

                    if featureType == actual_value:                    # if it is the correct value
                        if self.debug: print "I found a feature that matches your criteria. Returning it and its parentNode"
                        #return self.makeIdsUnique(feature), feature.parentNode             # we return that feature and its parentNode
                        return feature, feature.parentNode             # we return that feature and its parentNode
                    else:
                        if self.debug:
                            print "feature: %s, attribute: %s, value: %s : No match. You were looking for: %s" \
                                % (feature, attribute, actual_value, featureType)

        print "A bug occurred! Please report this bug on launchpad.net/memaker : None of the features of this face has the attribute %s" % (attribute)

    def sortFeatures(self):
        """
        sort the features of this face in a reasonable way (as good as possible)
        """
        tmp = xdm.parseString(\
        '''
        <svg
		width="400"
		height="400"
        xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        xmlns:memaker="http://launchpad.net/memaker"
	    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	    xmlns:cc="http://web.resource.org/cc/"
	    xmlns:dc="http://purl.org/dc/elements/1.1/"
	    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
	    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd">
        </svg>
        ''')
        for featureType in self.feature_types:
            if self.debug: print "sorting"
            if featureType in self.featureList:
                tmp.documentElement.appendChild(self.getFeature(featureType)[0])
                #if self.debug: print tmp.toprettyxml()                            # only for masochists :)
        self.base = tmp