This file is indexed.

/usr/share/doc/python-jabber/examples/mailchecker.py is in python-jabber 0.5.0-1.6.

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
## Stick this in the <browse/> element of your jabber.xml
## <service jid="mailcheck" name="IMAP Mail Checker">
##   <ns>jabber:iq:register</ns>
##   <ns>jabber:iq:gateway</ns>
## </service>
##
## Stick this in with the other <service/> elements
## <service id="mailcheck">
##     <accept>
##         <ip/>
##         <secret>secret</secret>
##         <port>6969</port>
##     </accept>
## </service>


import jabber
import sys
import sha
import imaplib
import pickle
import string

# mailchecker client
class MCClient:
    jid = None
    username = None
    password = None
    hostname = None
    directory = None
    folders = []
    online = 0
    status = None
    imap = None

    def __init__(self, jid, username, password, hostname, directory, folders):
        self.jid = jid
        self.username = username
        self.password = password
        self.hostname = hostname
        self.directory = directory
        self.folders = string.split(folders, ':')

    def doit(self, con):
        """query the mail server for new messages"""
        pass

    def cleanup(self):
        """Close down IMAP connection and perform any other necessary cleanup"""
        pass

    def setStatus(self, status):
        """Set the client's "verbose" status"""
        self.status = status

    def setShow(self, show):
        """Set the client's show mode; one of away, chat, xa, dnd, or 'None'"""
        # http://docs.jabber.org/jpg/html/main.html#REFSHOW
        # One of away, chat, xa, or dnd.
        self.show = show
        self.setOnline(1)

    def setOnline(self, online):
        """Set whether the user is online or not"""
        self.online = online

    def isOnline(self):
        """Return the state of the user's online'ness"""
        return(self.online)

    def isAvailable(self):
        """Return a boolean based on the user's show status"""
        
        # return false if xa, dnd or away (?)
        if (self.show == None) or (self.show == 'chat'):
            return(1)
        else:
            return(0)
    
# dict of keys
keys = {}

def iqCB(con, iq):
    print "Iq:", str(iq)
    resultIq = jabber.Iq(to=iq.getFrom())
    resultIq.setID(iq.getID())
    resultIq.setFrom(iq.getTo())

    query_result = resultIq.setQuery(iq.getQuery())

    type = iq.getType()
    query_ns = iq.getQuery()

    # switch on type: get, set, result error
    # switch on namespaces

    if query_ns == jabber.NS_REGISTER:
        if type == 'get':
            resultIq.setType('result')

            # generate a key to be passed to the user; it will be checked
            # later.  yes, we're storing a sha object
            iq_from = str(iq.getFrom())
            keys[iq_from] = sha.new(iq_from)

            # tell the client the fields we want
            fields = {
                'username': None,
                'password': None,
                'instructions': 'Enter your username, password, IMAP hostname, directory, and :-separated list of folders to check',
                'key': keys[iq_from].hexdigest(),
                'hostname': None,
                'directory': None,
                'folders': 'INBOX'
                }

            for field in fields.keys():
                field_node = query_result.insertTag(field)
                if fields[field]:
                    field_node.putData(fields[field])

            con.send(resultIq)

        elif type == 'set':
            # before anything else, verify the key
            client_key_node = iq.getQueryNode().getTag('key')
            if not client_key_node:
                resultIq.setType('error')
                resultIq.setError('no key given!')
                con.send(resultIq)
            else:
                # verify key
                if keys[str(iq.getFrom())].hexdigest() == client_key_node.getData():
                    # key is good
                    if iq.getQueryNode().getTag('remove'):
                        # user is trying to unregister
                        # TODO. :-)
                        del clients[iq.getFrom().getStripped()]
                    else:
                        # someone is trying to register
                        jid = iq.getFrom().getStripped()
                        username = iq.getQueryNode().getTag('username')
                        if username:
                            username = str(username.getData())

                        password = iq.getQueryNode().getTag('password')
                        if password:
                            password = str(password.getData())
                        
                        hostname = iq.getQueryNode().getTag('hostname')
                        if hostname:
                            hostname = str(hostname.getData())
                        
                        directory = iq.getQueryNode().getTag('directory')
                        if directory:
                            directory = str(directory.getData())
                        
                        folders = iq.getQueryNode().getTag('folders')
                        if folders:
                            folders = str(folders.getData())
                        
                        
                        client = MCClient(jid, username, password, hostname, directory, folders)

                        clients[client.jid] = client

                        # subscribe to the client's presence
                        sub_req = jabber.Presence(iq.getFrom(), type='subscribe')
                        sub_req.setFrom(str(iq.getTo()) + "/registered")
                        con.send(sub_req)

                        resultIq.setType('result')
                        con.send(resultIq)
                else:
                    resultIq.setType('error')
                    resultIq.setError('invalid key', 400)
                    con.send(resultIq)

                # done with key; delete it
                del keys[str(iq.getFrom())]
        else:
            print "don't know how to handle type", type, "for query", query_ns
            
    elif (query_ns == jabber.NS_AGENT) and (type == 'get'):
        # someone wants information about us
        resultIq.setType('result')

        responses = {
            'name': "Mailchecker",
            # 'url': None,
            'description': "This is the mailchecker component",
            'transport': "don't know what should go here...",
            'register': None, # we can be registered with
            'service': 'test' # nothing really standardized here...
            }

        for response in responses.keys():
            resp_node = query_result.insertTag(response)
            if responses[response]:
                resp_node.putData(responses[response])

        con.send(resultIq)

    else:
        print "don't know how to handle type", type, "for query", query_ns

def presenceCB(con, pres):
    print "Presence:", str(pres)

    # presence reply to use later on
    p = jabber.Presence(to=pres.getFrom())
    p.setFrom(pres.getTo())
    
    type = pres.getType()

    # find the client object
    if str(pres.getFrom().getStripped()) in clients.keys():
        client = clients[pres.getFrom().getStripped()]
    else:
        print("not able to find client for " + pres.getFrom().getStripped())
        
        client = None
        if type != 'unsubscribed':
            type = 'unsubscribe'
            
    if not type:
        type = 'available'

    print(pres.getFrom().getStripped() + " is " + type)

    if type == 'unavailable':
        # user went offline
        client.setOnline(0)

        p.setType('unavailable')
        con.send(p)
        
    elif type == 'subscribe':
        # user wants to subscribe to our presence; oblige, and ask for his
        p.setType('subscribed')
        con.send(p)

        p.setType('subscribe')
        con.send(p)

    elif type == 'unsubscribe':
        p.setType('unsubscribed')
        con.send(p)

        p.setType('unsubscribe')
        con.send(p)
        
    elif type == 'unsubscribed':
        # now unsubscribe from the user's presence
        pass

    elif type == 'probe':
        # send our presence
        p.setType('available')
        con.send(p)
        
    elif type == 'available':
        # user is online
        client.setStatus(pres.getStatus())
        client.setShow(pres.getShow())

        p.setType('available')
        con.send(p)

con = jabber.Component(host='webtechtunes.hq.insight.com', debug=0, port=6969, log='log')

try:
    clients = pickle.load(open('clients.p'))
except IOError, e:
    print(e)
    clients = {}
    
try:
    con.connect()
except IOError, e:
    print "Couldn't connect: %s" % e
    sys.exit(0)
else:
    print "Connected"
    
con.process(1)

if con.auth('secret'):
    print "connected"
else:
    print "problems with handshake: ", con.lastErr, con.lastErrCode
    sys.exit(1)

# con.registerHandler('message',messageCB)
con.registerHandler('presence',presenceCB)
con.registerHandler('iq',iqCB)

p = jabber.Presence(type='available')
p.setFrom('mailcheck/registered')
for c in clients.keys():
    p.setTo(clients[c].jid)
    con.send(p)

try:
    while(1):
        con.process(10)

        # whoo baby, is this a kludge.  Should really have a bona-fide event
        # loop or thread that processes the user's email checking, or at least
        # build up a timer type element that only runs this once every five
        # minutes or so...
        for c in clients.keys():
            clients[c].doit()
            
except KeyboardInterrupt:
    p = jabber.Presence(type='unavailable')
    p.setFrom('mailcheck/registered')
    for c in clients.keys():
        p.setTo(clients[c].jid)
        con.send(p)

    pickle.dump(clients, open('clients.p', 'w'))

    con.disconnect()