This file is indexed.

/usr/share/pyshared/screenlets/session.py is in screenlets 0.1.6-0ubuntu2.

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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# 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.  If not, see <http://www.gnu.org/licenses/>.

#  screenlets.session (c) RYX (aka Rico Pfaus) 2007 <ryx@ryxperience.com>
#
# INFO:
# This module contains the ScreenletSession-class which handles the lower-level
# things like startup, multiple instances and sessions. It should also become
# the interface for load/save operations. The ScreenletSession is further
# responsible for handling command-line args to the Screenlet and should maybe
# offer some convenient way of setting Screenlet-options via commandline (so
# one can do "NotesScreenlet --theme_name=green --scale=0.5" and launch the
# Note with the given theme and scale)..
#
#
# INFO:
# - When a screenlet gets launched:
#   - the first instance of a screenlet creates the Session-object (within the
#     __main__-code)
#   - the session object investigates the config-dir for the given Screenlet
#     and restores available instances
#   - else (if no instance was found) it simply creates a new instance of the 
#     given screenlet and runs its mainloop
# - the --session argument allows setting the name of the session that will be
#   used by the Screenlet (to allow multiple configs for one Screenlet)
#
# TODO:
# - set attributes via commandline??
#

import os
import glob
import random
from xdg import BaseDirectory

import backend			# import screenlets.backend module
import services
import utils

import dbus	# TEMPORARY!! only needed for workaround
from stat import S_IRWXU, S_IRWXG, S_IRWXO
import gettext
import screenlets
gettext.textdomain('screenlets')
gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX +  '/share/locale')

def _(s):
	return gettext.gettext(s)


# temporary path for saving files for opened screenlets
TMP_DIR		= '/tmp/screenlets'
TMP_FILE	= 'screenlets.' + os.environ['USER'] + '.running'


class ScreenletSession (object):
	"""The ScreenletSession manages instances of a Screenlet and handles
	saving/restoring options. Each Screenlet contains a reference to its 
	session. Multiple instances of the same Screenlet share the same
	session-object."""
	
	# constructor
	def __init__ (self, screenlet_classobj, backend_type='caching', name='default'):
		object.__init__(self)
		# check type
		if not screenlet_classobj.__name__.endswith('Screenlet'):
			# TODO: also check for correct type (Screenlet-subclass)!!
			raise Exception("ScreenletSession.__init__ has to be called with a valid Screenlet-classobject as first argument!")
		# init props
		self.name 		= name
		self.screenlet 	= screenlet_classobj
		self.instances 	= []
		self.tempfile	= TMP_DIR + '/' + TMP_FILE
		# check sys.args for "--session"-argument and override name, if set
		self.__parse_commandline()
		# set session path (and create dir-tree if not existent)
		p = screenlet_classobj.__name__[:-9] + '/' + self.name + '/'
		self.path = BaseDirectory.load_first_config('screenlets/' + p)
		if self.path == None:
			self.path = BaseDirectory.save_config_path('screenlets/' + p)
		if self.path == None: self.path = os.path.join(screenlets.DIR_CONFIG,p)
		if self.path:
			if backend_type == 'caching':
				self.backend = backend.CachingBackend(path=self.path)
			elif backend_type == 'gconf':
				self.backend = backend.GconfBackend()	
		else:
			# no config-dir? use dummy-backend and note about problem
			self.backend = backend.ScreenletsBackend()
			print "Unable to init backend - settings will not be saved!"
		# WORKAROUND: connect to daemon (ideally the daemon should watch the 
		#             tmpfile for changes!!)


		# NOTE: daemon will be started by bus.get_object anyway!!!
		#check for daemon
		#proc = os.popen("""ps axo "%p,%a" | grep "python.*screenlets-daemon.py" | grep -v grep|cut -d',' -f1""").read()
	
		#procs = proc.split('\n')
		#if len(procs) <= 1:
		#	os.system('python -u ' + screenlets.INSTALL_PREFIX + '/share/screenlets-manager/screenlets-daemon.py &')
		#	print 'No Daemon, Launching Daemon'
		self.connect_daemon()
	
	def connect_daemon (self):
		"""Connect to org.screenlets.ScreenletsDaemon."""
		self.daemon_iface = None
		bus = dbus.SessionBus()
		if bus:
			try:
				proxy_obj = bus.get_object(screenlets.DAEMON_BUS, screenlets.DAEMON_PATH) 
				if proxy_obj:
					self.daemon_iface = dbus.Interface(proxy_obj, screenlets.DAEMON_IFACE)
			except Exception, ex:
				print "Error in screenlets.session.connect_daemon: %s" % ex
	
	def create_instance (self, id=None, **keyword_args):
		"""Create a new instance with ID 'id' and add it to this session. The 
		function returns either the new Screenlet-instance or None."""
		# if id is none or already exists
		if id==None or id=='' or self.get_instance_by_id(id) != None:
			print "ID is unset or already in use - creating new one!"
			id = self.__get_next_id()
			dirlst = glob.glob(self.path + '*')
			tdlen = len(self.path)
			for filename in dirlst:
				filename = filename[tdlen:]		# strip path from filename
				print 'Loaded config from: %s' % filename
				if filename.endswith(id + '.ini'):
				# create new instance
					sl = self.create_instance(id=filename[:-4], enable_saving=False)
					if sl:
						# set options for the screenlet
						print "Set options in %s" % sl.__name__
						#self.__restore_options_from_file (sl, self.path + filename)
						self.__restore_options_from_backend(sl, self.path+filename)
						sl.enable_saving(True)
						# and call init handler
						sl.finish_loading()
						return sl
		sl = self.screenlet(id=id, session=self, **keyword_args)
		if sl:
			self.instances.append(sl)		# add screenlet to session
			# and cause initial save to store INI-file in session dir
			sl.x = sl.x
			return sl
		return None
	
	def delete_instance (self, id):
		"""Delete the given instance with ID 'id' and remove its session file.
		When the last instance within the session is removed, the session dir 
		is completely removed."""
		sl = self.get_instance_by_id(id)
		if sl:
			# remove instance from session
			self.instances.remove(sl)
			# remove session file
			try:
				self.backend.delete_instance(id)
			except Exception:
				print "Failed to remove INI-file for instance (not critical)."
			# if this was the last instance
			if len(self.instances) == 0:
				# maybe show confirmation popup?
				print "Removing last instance from session"
				# TODO: remove whole session directory
				print "TODO: remove self.path: %s" % self.path
				try:
					os.rmdir(self.path)
				except:
					print "Failed to remove session dir '%s' - not empty?" % self.name
				# ...
				# quit gtk on closing screenlet
				sl.quit_on_close = True
			else:
				print "Removing instance from session but staying alive"
				sl.quit_on_close = False
			# delete screenlet instance
			sl.close()
			del sl
			return True
		return False
	
	def get_instance_by_id (self, id):
		"""Return the instance with the given id from within this session."""
		for inst in self.instances:
			if inst.id == id:
				return inst
		return None

	def quit_instance (self, id):
		"""quit the given instance with ID 'id'"""
		
		sl = self.get_instance_by_id(id)
		if sl:
			print self.instances
			# remove instance from session


			if len(self.instances) == 1:
				sl.quit_on_close = True
			else:
				print "Removing instance from session but staying alive"
				sl.quit_on_close = False
			self.backend.flush()
			sl.close()
			self.instances.remove(sl)
			
			# remove session file
			return True
		return False

	
	def start (self):
		"""Start a new session (or restore an existing session) for the
		current Screenlet-class. Creates a new instance when none is found.
		Returns True if everything worked well, else False."""
		# check for a running instance first and use dbus-call to add
		# a new instance in that case
		#sln = self.screenlet.get_short_name()
		sln = self.screenlet.__name__[:-9]
		running = utils.list_running_screenlets()
		if running and running.count(self.screenlet.__name__) > 0:
		#if services.service_is_running(sln):
			print "Found a running session of %s, adding new instance by service." % sln
			srvc = services.get_service_by_name(sln)
			if srvc:
				print "Adding new instance through: %s" % str(srvc)
				srvc.add('')
				return False
		# ok, we have a new session running - indicate that to the system
		self.__register_screenlet()
		# check for existing entries in the session with the given name
		print "Loading instances in: %s" % self.path
		if self.__load_instances():
			# restored existing entries?
			print "Restored instances from session '%s' ..." % self.name
			# call mainloop of first instance (starts application)
			#self.instances[0].main()
			self.__run_session(self.instances[0])
		else:
			# create new first instance
			print 'No instance(s) found in session-path, creating new one.'
			sl = self.screenlet(session=self, id=self.__get_next_id())
			if sl:
				# add screenlet to session
				self.instances.append(sl)
				# now cause a save of the options to initially create the
				# INI-file for this instance
				self.backend.save_option(sl.id, 'x', sl.x)
				# call on_init-handler
				sl.finish_loading()
				# call mainloop and give control to Screenlet
				#sl.main()
				self.__run_session(sl)
			else:
				print 'Failed creating instance of: %s' % self.classobj.__name__
				# remove us from the running screenlets
				self.__unregister_screenlet()
				return False
		# all went well
		return True
	
	def __register_screenlet (self):
		"""Create new entry for this session in the global TMP_FILE."""

		# if tempfile not exists, create it
		if  not self.__create_tempdir():
			return False # error already returned

		# if screenlet not already added
 		running = utils.list_running_screenlets()
		if running == None : running = []
		if running.count(self.screenlet.__name__) == 0:
		# open temp file for appending data
			try:
				f = open(self.tempfile, 'a') # No need to create a empty file , append will do just fine
			except IOError, e:
				print "Unable to open %s" % self.tempfile
				return False
			else:
				print "Creating new entry for %s in %s" % (self.screenlet.__name__, self.tempfile)
				f.write(self.screenlet.__name__ + '\n')
				f.close()
		else: print "Screenlet has already been added to %s" % self.tempfile
		# WORKAROUND: for now we manually add this to the daemon,
		#             ideally the daemon should watch the tmpdir for changes
		if self.daemon_iface:
			self.daemon_iface.register_screenlet(self.screenlet.__name__)
	
	def __create_tempdir (self):
		"""Create the global temporary file for saving screenlets. The file is 
		used for indicating which screnlets are currently running."""

		# check for existence of TMP_DIR and create it if missing
		if not os.path.isdir(TMP_DIR):
			try:
				if os.path.exists(TMP_DIR):
					# something exists, but is not a directory
					os.remove(TMP_DIR)

				print "No global tempdir found, creating new one."
				os.mkdir(TMP_DIR)
				# make the tmp directory accessible for all users
				
				os.chmod(TMP_DIR, S_IRWXU | S_IRWXG | S_IRWXO)
				print 'Temp directory %s created.' % TMP_DIR
			except OSError, e:
				print 'Error: Unable to create temp directory %s - screenlets-manager will not work properly.' % TMP_DIR
				print "Error was: %s"%e
				return False
		return True

	
	def __unregister_screenlet (self, name=None):
		"""Delete this session's entry from the gloabl tempfile (and delete the
		entire file if no more running screenlets are set."""
		if not name:
			name = self.screenlet.__name__
		# WORKAROUND: for now we manually unregister from the daemon,
		#             ideally the daemon should watch the tmpfile for changes
		if self.daemon_iface:
			try:
				self.daemon_iface.unregister_screenlet(name)
			except Exception, ex:
				print "Failed to unregister from daemon: %s" % ex
		# /WORKAROUND
		# get running screenlets
		running = utils.list_running_screenlets()
		if running and len(running) > 0:
			pass#print "Removing entry for %s from global tempfile %s" % (name, self.tempfile)
			try:
				running.remove(name)
			except:
				# not found, so ok
				print "Entry not found. Will (obviously) not be removed."
				return True
			# still running screenlets?
			if running and len(running) > 0:
				# re-save new list of running screenlets
				f = open(self.tempfile, 'w')
				if f:
					for r in running:
						f.write(r + '\n')
					f.close()
					return True
				else:
					print "Error global tempfile not found. Some error before?"
				return False
			else:
				print 'No more screenlets running.'
				self.__delete_tempfile(name)
		else:
			print 'No screenlets running?'
			return False
	
	def __delete_tempfile (self, name=None):
		"""Delete the tempfile for this session."""
		if self.tempfile and os.path.isfile(self.tempfile):
			print "Deleting global tempfile %s" % self.tempfile
			try:
				os.remove(self.tempfile)
				return True
			except:
				print "Error: Failed to delete global tempfile"
				return False
	
	def __get_next_id (self):
		"""Get the next ID for an instance of the assigned Screenlet."""
		num = 1
		sln = self.screenlet.__name__[:-9]
		id = sln + str(num)
		while self.get_instance_by_id(id) != None:
			id = sln + str(num)
			num += 1
		return id
		
	def __load_instances (self):
		"""Check for existing instances in the current session, create them 
		and store them into self.instances if any are found. Returns True if 
		at least one instance was found, else False."""
		dirlst = glob.glob(self.path + '*')
		tdlen = len(self.path)
		for filename in dirlst:
			filename = filename[tdlen:]		# strip path from filename
			print 'Loaded config from: %s' % filename
			if filename.endswith('.ini'):
				# create new instance
				sl = self.create_instance(id=filename[:-4], enable_saving=False)
				if sl:
					# set options for the screenlet
					print "Set options in %s" % sl.__name__
					#self.__restore_options_from_file (sl, self.path + filename)
					self.__restore_options_from_backend(sl, self.path+filename)
					sl.enable_saving(True)
					# and call init handler
					sl.finish_loading()
				else:
					print "Failed to create instance of '%s'!" % filename[:-4]
		# if instances were found, return True, else False
		if len(self.instances) > 0:
			return True
		return False
	
	# replacement for above function
	def __restore_options_from_backend (self, screenlet, filename):
		"""Restore and apply a screenlet's options from the backend."""
		# disable the canvas-updates in the screenlet
		screenlet.disable_updates = True
		# get options for SL from backend
		opts = self.backend.load_instance(screenlet.id)
		if opts:
			for o in opts:
				# get the attribute's Option-object from Screenlet
				opt = screenlet.get_option_by_name(o)
				# NOTE: set attribute in Screenlet by calling the
				# on_import-function for the Option (to import
				# the value as the required type)
				if opt:
					setattr(screenlet, opt.name, opt.on_import(opts[o]))
		# re-enable updates and call redraw/reshape
		screenlet.disable_updates = False
		screenlet.redraw_canvas()
		screenlet.update_shape()
	
	def __run_session (self, main_instance):
		"""Run the session by calling the main handler of the given Screenlet-
		instance. Handles sigkill (?) and keyboard interrupts."""
		# add sigkill-handler
		import signal
		def on_kill(*args):
			#print "Screenlet has been killed. TODO: make this an event"
			pass
		signal.signal(signal.SIGTERM, on_kill)
		# set name of tempfile for later (else its missing after kill)
		tempfile = self.screenlet.__name__
		# start
		try:
			# start mainloop of screenlet
			main_instance.main()
		except KeyboardInterrupt:
			# notify when daemon is closed
			self.backend.flush()
			print "Screenlet '%s' has been interrupted by keyboard. TODO: make this an event" % self.screenlet.__name__
		except Exception, ex:
			print "Exception in ScreenletSession: " + ex
		# finally delete the tempfile
		self.__unregister_screenlet(name=tempfile)
	
	def __parse_commandline (self):
		"""Check commandline args for "--session" argument and set session
		name if found. Runs only once during __init__.
		TODO: handle more arguments and maybe allow setting options by
		commandline"""
		import sys
		for arg in sys.argv[1:]:
			# name of session?
			if arg.startswith('--session=') and len(arg)>10:
				self.name = arg[10:]



def create_session (classobj, backend='caching', threading=False):
	"""A very simple utility-function to easily create/start a new session."""

	if threading:
		import gtk
		gtk.gdk.threads_init()
	session = ScreenletSession(classobj, backend_type=backend)
	session.start()