This file is indexed.

/usr/share/pyshared/Pyro/EventService/Server.py is in pyro 1:3.14-1.2.

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
#############################################################################
#  
#	Event Service daemon and server classes
#
#	This is part of "Pyro" - Python Remote Objects
#	which is (c) Irmen de Jong - irmen@razorvine.net
#
#############################################################################

import time, types, re, sys, traceback, os
import Pyro.core, Pyro.naming, Pyro.util, Pyro.constants
from Pyro.errors import *
from Pyro.EventService.Event import Event
import Queue
from threading import Thread

Log=Pyro.util.Log

# SUBSCRIBER - each subscriber has one of these worker threads
class Subscriber(Thread):
	def __init__(self, remote):
		Thread.__init__(self)
		self.remote=remote
		# set the callback method to ONEWAY mode:
		self.remote._setOneway("event")
		self.queue=Queue.Queue(Pyro.config.PYRO_ES_QUEUESIZE)
	def run(self):
		while 1:
			event=self.queue.get()
			if isinstance(event,Event):
				try:
					self.remote.event(event)
				except ProtocolError,x:
					break
			else:
				break # it was no Event, so exit
		# this reads all pending items from the queue so that any
		# tasks that are blocked on the queue can continue.
		(queue, self.queue) = (self.queue, None)
		try:
			while 1:
				queue.get(block=0)
		except Queue.Empty:
			pass
		# release the remote connection
		self.remote._release()
		del self.remote
	def send(self, event):
		if self.queue:
			self.queue.put(event, block=Pyro.config.PYRO_ES_BLOCKQUEUE)
	def running(self):
		return self.queue

# The EVENTSERVICE is the actual Pyro server.
#
# BTW: Subscribers are remembered trough their proxy class.
# This class is capable of being a correct key in a dictionary.
class EventService(Pyro.core.ObjBase):
	def __init__(self):
		Pyro.core.ObjBase.__init__(self)
		self.subscribers={}			# subject -> { threadname-> subscriberthread }
		self.subscribersMatch={}	# subjectPattern -> { threadname->subscriberthread }
		self.subscriptionWorkers={}	# subscriber -> subscription thread object
	def _mksequence(self, seq):
		if not (type(seq) in (types.TupleType,types.ListType)):
			return (seq,)
		return seq
	def getSubscriptionWorker(self, subscriber):
		# If this subscriber doesn't have its own subscription thread, create one.
		if subscriber not in self.subscriptionWorkers:
			worker = Subscriber(subscriber)
			worker.start()
			self.subscriptionWorkers[subscriber]=worker
			return worker
		else:
			return self.subscriptionWorkers[subscriber]
	def subscribe(self, subjects, subscriber):
		if not subjects: return
		# Subscribe into a dictionary; this way; somebody can subscribe
		# only once to this subject. Subjects are exact strings.
		for subject in self._mksequence(subjects):
			worker=self.getSubscriptionWorker(subscriber)
			self.subscribers.setdefault(subject.lower(),{}) [worker.getName()]=worker
	def subscribeMatch(self, subjects, subscriber):
		if not subjects: return
		# Subscribe into a dictionary; this way; somebody can subscribe
		# only once to this subject. Subjects are regex patterns.
		for subject in self._mksequence(subjects):
			worker=self.getSubscriptionWorker(subscriber)
			matcher = re.compile(subject,re.IGNORECASE)
			self.subscribersMatch.setdefault(matcher,{}) [worker.getName()]=worker
	def unsubscribe(self, subjects, subscriber):
		if not subjects: return
		for subject in self._mksequence(subjects):
			try:
				blaat=self.subscribers[subject.lower()]  # check for subject
				worker=self.subscriptionWorkers[subscriber]
				del self.subscribers[subject.lower()] [worker.getName()]
				self.killWorkerIfLastSubject(subscriber, worker)
			except KeyError,x:
				try:
					m=re.compile(subject,re.IGNORECASE)
					worker=self.subscriptionWorkers[subscriber]
					del self.subscribersMatch[m] [worker.getName()]
					self.killWorkerIfLastSubject(subscriber,worker)
				except KeyError,x:
					pass

	def publish(self, subjects, message):
		if not subjects: return
		# keep the creation time, this must be the same for all events.
		creationTime=time.time()
		# publish a message. Subjects must be exact strings
		for subject in self._mksequence(subjects):
			event = Event(subject, message, creationTime)
			subjectLC=subject.lower()
			try:
				for (name,s) in self.subscribers[subjectLC].items():
					try:
						if s.running():
							s.send(event)  
						else:
							try:
								del self.subscribers[subjectLC][name]
							except KeyError:
								pass
					except Queue.Full:
						pass
			except KeyError:
				pass
			# process the subject patterns
			for (m,subs) in self.subscribersMatch.items():
				if m.match(subject):
					# send event to all subscribers
					for (name,s) in subs.items():	
						try:
							if s.running():
								s.send(event)  
							else:
								try:
									del subs[name]
								except KeyError:
									pass
						except Queue.Full:
							pass

	def killWorkerIfLastSubject(self, subscriber, worker):
		item=(worker.getName(),worker)
		for v in self.subscribers.values():
			if item in v.items():
				return
		for v in self.subscribersMatch.values():
			if item in v.items():
				return
		worker.send("QUIT")
		del self.subscriptionWorkers[subscriber]


class EventServiceStarter(object):
	def __init__(self, identification=None):
		Pyro.core.initServer()
		self.running=1
		self.identification=identification
		self.started = Pyro.util.getEventObject()
	def start(self, *args, **kwargs):			# see _start for allowed arguments
		kwargs["startloop"]=1
		self._start(*args, **kwargs )
	def initialize(self, *args, **kwargs):		# see _start for allowed arguments
		kwargs["startloop"]=0
		self._start( *args, **kwargs )
	def getServerSockets(self):
		return self.daemon.getServerSockets()
	def waitUntilStarted(self,timeout=None):
		self.started.wait(timeout)
		return self.started.isSet()
	def _start(self,hostname='',port=None,startloop=1,useNameServer=1,norange=0):
		daemon = Pyro.core.Daemon(host=hostname,port=port,norange=norange)
		if self.identification:
			daemon.setAllowedIdentifications([self.identification])
			print 'Requiring connection authentication.'

		if useNameServer:
			locator = Pyro.naming.NameServerLocator(identification=self.identification)
			ns = locator.getNS()
	
			# check if ES already running
			try:
				ns.resolve(Pyro.constants.EVENTSERVER_NAME)
				print 'The Event Server appears to be already running.'
				print 'You cannot start multiple Event Servers.'
				ans=raw_input('Start new Event Server anyway (y/n)? ')
				if ans!='y':
					return
				ns.unregister(Pyro.constants.EVENTSERVER_NAME)
			except NamingError:
				pass
	
			daemon.useNameServer(ns)

		es = EventService()

		esURI=daemon.connect(es, Pyro.constants.EVENTSERVER_NAME)
		print 'URI=',esURI

		message = daemon.validateHostnameAndIP()
		if message:
			print "\nWARNING:",message,"\n"

		print 'Event Server started.'

		self.started.set()		# signal that we've started.

		if startloop:
			Log.msg('ES daemon','This is the Pyro Event Server.')
			
			try:
				if os.name!="java":
					# I use a timeout here otherwise you can't break gracefully on Windows
					daemon.setTimeout(20)
				daemon.requestLoop(lambda s=self: s.running)
			except KeyboardInterrupt:
				Log.warn('ES daemon','shutdown on user break signal')
				print 'Shutting down on user break signal.'
				self.shutdown(es)
			except:
				try:
					(exc_type, exc_value, exc_trb) = sys.exc_info()
					out = ''.join(traceback.format_exception(exc_type, exc_value, exc_trb)[-5:])
					Log.error('ES daemon', 'Unexpected exception, type',exc_type,
						'\n--- partial traceback of this exception follows:\n',
						out,'\n--- end of traceback')
					print '*** Exception occured!!! Partial traceback:'
					print out
					print '*** Resuming operations...'
				finally:	
					del exc_type, exc_value, exc_trb    # delete refs to allow proper GC

			Log.msg('ES daemon','Shut down gracefully.')
			print 'Event Server gracefully stopped.'
		else:
			# no loop, store the required objects for getServerSockets()
			self.daemon=daemon
			self.es=es
			if os.name!="java":
				daemon.setTimeout(20)  # XXX fixed timeout

	def mustContinueRunning(self):
		return self.running
	def handleRequests(self, timeout=None):
		# this method must be called from a custom event loop
		self.daemon.handleRequests(timeout=timeout)
	def shutdown(self,es):
		if es:
			# internal shutdown call with specified ES object
			daemon=es.getDaemon()
		else:
			# custom shutdown call w/o specified ES object, use stored instance
			daemon=self.daemon
			es=self.es
			del self.es, self.daemon
		try:
			daemon.disconnect(es) # clean up nicely
		except NamingError,x:
			Log.warn('ES daemon','disconnect error during shutdown:',x)
		except ConnectionClosedError,x:
			Log.warn('ES daemon','lost connection with Name Server, cannot unregister')
		self.running=0
		daemon.shutdown()


def start(argv):
	Args = Pyro.util.ArgParser()
	Args.parse(argv,'hNn:p:i:')
	if Args.hasOpt('h'):
		print 'Usage: pyro-es [-h] [-n hostname] [-p port] [-N] [-i identification]'
		print '  where -p = ES server port (0 for auto)'
		print '        -n = non-default hostname to bind on'
		print '        -N = do not use the name server'
		print '        -i = the required authentication ID for ES clients,'
		print '             also used to connect to other Pyro services'
		print '        -h = print this help'
		raise SystemExit
	hostname = Args.getOpt('n',None)
	port = Args.getOpt('p',None)
	useNameServer = not Args.hasOpt('N')
	ident = Args.getOpt('i',None)
	if port:
		port=int(port)
	norange=(port==0)
	Args.printIgnored()
	if Args.args:
		print 'Ignored arguments:',' '.join(Args.args)

	print '*** Pyro Event Server ***'
	starter=EventServiceStarter(identification=ident)
	starter.start(hostname,port,useNameServer=useNameServer,norange=norange)


# allow easy starting of the ES by using python -m
if __name__=="__main__":
	start(sys.argv[1:])