This file is indexed.

/usr/share/pyshared/gluon/contrib/comet_messaging.py is in python-gluon 1.99.7-1.

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
#!/usr/bin/python
"""
This file is part of the web2py Web Framework
Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)

Attention: Requires Chrome or Safari. For IE of Firefox you need https://github.com/gimite/web-socket-js

1) install tornado (requires Tornado 2.1)

   easy_install tornado

2) start this app:

   python gluon/contrib/comet_messaging.py -k mykey -p 8888

3) from any web2py app you can post messages with

   from gluon.contrib.comet_messaging import comet_send
   comet_send('http://127.0.0.1:8888','Hello World','mykey','mygroup')

4) from any template you can receive them with

   <script>
   $(document).ready(function(){
      if(!web2py_comet('ws://127.0.0.1:8888/realtime/mygroup',function(e){alert(e.data)}))
         alert("html5 websocket not supported by your browser, try Google Chrome");
   });
   </script>

When the server posts a message, all clients connected to the page will popup an alert message
Or if you want to send json messages and store evaluated json in a var called data:

   <script>
   $(document).ready(function(){
      var data;
      web2py_comet('ws://127.0.0.1:8888/realtime/mygroup',function(e){data=eval('('+e.data+')')});
   });
   </script>

- All communications between web2py and comet_messaging will be digitally signed with hmac.
- All validation is handled on the web2py side and there is no need to modify comet_messaging.py
- Multiple web2py instances can talk with one or more comet_messaging servers.
- "ws://127.0.0.1:8888/realtime/" must be contain the IP of the comet_messaging server.
- Via group='mygroup' name you can support multiple groups of clients (think of many chat-rooms)

Here is a complete sample web2py action:

    def index():
        form=LOAD('default','ajax_form',ajax=True)
        script=SCRIPT('''
            jQuery(document).ready(function(){
              var callback=function(e){alert(e.data)};
              if(!web2py_comet('ws://127.0.0.1:8888/realtime/mygroup',callback))
                alert("html5 websocket not supported by your browser, try Google Chrome");
            });
        ''')
        return dict(form=form, script=script)

    def ajax_form():
        form=SQLFORM.factory(Field('message'))
        if form.accepts(request,session):
            from gluon.contrib.comet_messaging import comet_send
            comet_send('http://127.0.0.1:8888',form.vars.message,'mykey','mygroup')
        return form

Acknowledgements:
Tornado code inspired by http://thomas.pelletier.im/2010/08/websocket-tornado-redis/

"""

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import hmac
import sys
import optparse
import urllib
import time

listeners = {}
names = {}
tokens = {}

def comet_send(url,message,hmac_key=None,group='default'):
    sig = hmac_key and hmac.new(hmac_key,message).hexdigest() or ''
    params = urllib.urlencode({'message': message, 'signature': sig, 'group':group})
    f = urllib.urlopen(url, params)
    data= f.read()
    f.close()
    return data

class PostHandler(tornado.web.RequestHandler):
    """
    only authorized parties can post messages
    """
    def post(self):
        if hmac_key and not 'signature' in self.request.arguments: return 'false'
        if 'message' in self.request.arguments:
            message = self.request.arguments['message'][0]
            group = self.request.arguments.get('group',['default'])[0]
            print '%s:MESSAGE to %s:%s' % (time.time(), group, message)
            if hmac_key:
                signature = self.request.arguments['signature'][0]
                if not hmac.new(hmac_key,message).hexdigest()==signature: return 'false'
            for client in listeners.get(group,[]): client.write_message(message)
            return 'true'
        return 'false'

class TokenHandler(tornado.web.RequestHandler):
    """
    if running with -t post a token to allow a client to join using the token
    the message here is the token (any uuid)
    allows only authorized parties to joins, for example, a chat
    """
    def post(self):
        if hmac_key and not 'message' in self.request.arguments: return 'false'
        if 'message' in self.request.arguments:
            message = self.request.arguments['message'][0]
            if hmac_key:
                signature = self.request.arguments['signature'][0]
                if not hmac.new(hmac_key,message).hexdigest()==signature: return 'false'
            tokens[message] = None
            return 'true'
        return 'false'

class DistributeHandler(tornado.websocket.WebSocketHandler):
    def open(self,params):
        group,token,name = params.split('/')+[None,None]
        self.group = group or 'default'
        self.token = token or 'none'
        self.name = name or 'anonymous'
        # only authorized parties can join
        if DistributeHandler.tokens:
            if not self.token in tokens or not token[self.token]==None:
                self.close()
            else:
                tokens[self.token] = self
        if not self.group in listeners: listeners[self.group]=[]
        # notify clients that a member has joined the groups
        for client in listeners.get(self.group,[]): client.write_message('+'+self.name)
        listeners[self.group].append(self)
        names[self] = self.name
        print '%s:CONNECT to %s' % (time.time(), self.group)
    def on_message(self, message):
        pass
    def on_close(self):
        if self.group in listeners: listeners[self.group].remove(self)
        del names[self]
        # notify clients that a member has left the groups
        for client in listeners.get(self.group,[]): client.write_message('-'+self.name)
        print '%s:DISCONNECT from %s' % (time.time(), self.group)

if __name__ == "__main__":
    usage = __doc__
    version= ""
    parser = optparse.OptionParser(usage, None, optparse.Option, version)
    parser.add_option('-p',
                      '--port',
                      default='8888',
                      dest='port',
                      help='socket')
    parser.add_option('-l',
                      '--listen',
                      default='0.0.0.0',
                      dest='address',
                      help='listener address')
    parser.add_option('-k',
                      '--hmac_key',
                      default='',
                      dest='hmac_key',
                      help='hmac_key')
    parser.add_option('-t',
                      '--tokens',
                      action='store_true',
                      default=False,
                      dest='tokens',
                      help='require tockens to join')
    (options, args) = parser.parse_args()
    hmac_key = options.hmac_key
    DistributeHandler.tokens = options.tokens
    urls=[
        (r'/', PostHandler),
        (r'/token', TokenHandler),
        (r'/realtime/(.*)', DistributeHandler)]
    application = tornado.web.Application(urls, auto_reload=True)
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(int(options.port), address=options.address)
    tornado.ioloop.IOLoop.instance().start()