attachments, in order: (1) 0...the proposed patch to sugar (2) suga..9.1 sugar part of a draft patch for 9.1, only read it if you're interested, scarcely tested. (3) 0...s-l proposed patch for sugar-toolkit (4) tool...9.1 the sugar-toolkit part of the draft 9.1 patch (5) 0...fixes some minor pylint cleanup to sugar, to be applied after patch 1 above.
So, the important parts here are (1) and (3). Patch (1) makes sugar registry service not add bundles unless they're in ~/Activities. (The registry can add such bundles, but the service will refuse to). Patch (3) makes activitybundle.py refuse to install loopholed activities unless called with securitycheck=False.
From 4db7faf72edc7eaa2aa4631a98aa29819f2e5ec8 Mon Sep 17 00:00:00 2001 From: Jameson Quinn <[EMAIL PROTECTED]> Date: Mon, 4 Aug 2008 19:17:11 -0600 Subject: [PATCH] bug #5657 - don't add bundles to registry unless they're in ~/Activities --- service/bundleregistry.py | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/service/bundleregistry.py b/service/bundleregistry.py index e7c30a8..5d3fec8 100644 --- a/service/bundleregistry.py +++ b/service/bundleregistry.py @@ -174,12 +174,15 @@ class BundleRegistry(gobject.GObject): bundle_dirs.sort(lambda d1, d2: cmp(bundles[d1], bundles[d2])) for folder in bundle_dirs: try: - self.add_bundle(folder) + self.add_bundle(folder, securitycheck=False) except Exception, e: logging.error('Error while processing installed activity ' \ 'bundle: %s, %s, %s' % (folder, e.__class__, e)) - def add_bundle(self, bundle_path): + def add_bundle(self, bundle_path, securitycheck=True): + if securitycheck and not bundle_path.startswith( + os.path.expanduser("~/Activities")): + return False try: bundle = ActivityBundle(bundle_path) except MalformedBundleException: -- 1.5.2.5
diff --git a/service/activityregistryservice.py b/service/activityregistryservice.py index 6ba5598..7b3415a 100644 --- a/service/activityregistryservice.py +++ b/service/activityregistryservice.py @@ -24,6 +24,11 @@ _ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry' _ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry' _ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry' +def log_it(s): + f = file("/home/chema/.sugar/default/logs/hardcoded","ab") + f.write(s+"\n") + f.close() + class ActivityRegistry(dbus.service.Object): def __init__(self): bus = dbus.SessionBus() @@ -64,11 +69,8 @@ class ActivityRegistry(dbus.service.Object): @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='', out_signature='aa{sv}') def GetActivities(self): - result = [] registry = bundleregistry.get_registry() - for bundle in registry: - result.append(self._bundle_to_dict(bundle)) - return result + return (bundle for bundle in registry) @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='s', out_signature='a{sv}') @@ -78,7 +80,8 @@ class ActivityRegistry(dbus.service.Object): if not bundle: return {} - return self._bundle_to_dict(bundle) + log_it("service about to return "+str(bundle)) + return bundle @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='s', out_signature='aa{sv}') @@ -90,18 +93,15 @@ class ActivityRegistry(dbus.service.Object): name = bundle.get_name().lower() bundle_id = bundle.get_bundle_id().lower() if name.find(key) != -1 or bundle_id.find(key) != -1: - result.append(self._bundle_to_dict(bundle)) + result.append(bundle) return result @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='s', out_signature='aa{sv}') def GetActivitiesForType(self, mime_type): - result = [] registry = bundleregistry.get_registry() - for bundle in registry.get_activities_for_type(mime_type): - result.append(self._bundle_to_dict(bundle)) - return result + return registry.get_activities_for_type(mime_type) @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='sib', out_signature='') @@ -127,32 +127,14 @@ class ActivityRegistry(dbus.service.Object): def ActivityChanged(self, activity_info): pass - def _bundle_to_dict(self, bundle): - registry = bundleregistry.get_registry() - favorite = registry.is_bundle_favorite(bundle.get_bundle_id(), - bundle.get_activity_version()) - x, y = registry.get_bundle_position(bundle.get_bundle_id(), - bundle.get_activity_version()) - return {'name': bundle.get_name(), - 'icon': bundle.get_icon(), - 'bundle_id': bundle.get_bundle_id(), - 'version': bundle.get_activity_version(), - 'path': bundle.get_path(), - 'command': bundle.get_command(), - 'show_launcher': bundle.get_show_launcher(), - 'favorite': favorite, - 'installation_time': bundle.get_installation_time(), - 'position_x': x, - 'position_y': y} - - def _bundle_added_cb(self, bundle_registry, bundle): - self.ActivityAdded(self._bundle_to_dict(bundle)) - - def _bundle_removed_cb(self, bundle_registry, bundle): - self.ActivityRemoved(self._bundle_to_dict(bundle)) - - def _bundle_changed_cb(self, bundle_registry, bundle): - self.ActivityChanged(self._bundle_to_dict(bundle)) + def _bundle_added_cb(self, bundle_registry, bundledict): + self.ActivityAdded(bundledict) + + def _bundle_removed_cb(self, bundle_registry, bundledict): + self.ActivityRemoved(bundledict) + + def _bundle_changed_cb(self, bundle_registry, bundledict): + self.ActivityChanged(bundledict) _instance = None diff --git a/service/bundleregistry.py b/service/bundleregistry.py index e7c30a8..e1556de 100644 --- a/service/bundleregistry.py +++ b/service/bundleregistry.py @@ -20,6 +20,7 @@ import traceback import gobject import simplejson +import dbus from sugar.bundle.activitybundle import ActivityBundle from sugar.bundle.bundle import MalformedBundleException @@ -27,6 +28,8 @@ from sugar import env import config +VALID_BITFROST = set("P_ROOT") + class BundleRegistry(gobject.GObject): """Service that tracks the available activity bundles""" @@ -42,9 +45,10 @@ class BundleRegistry(gobject.GObject): def __init__(self): gobject.GObject.__init__(self) + self._mime_defaults = self._load_mime_defaults() - self._bundles = [] + self._bundles = {} for activity_dir in self._get_activity_directories(): self._scan_directory(activity_dir) @@ -58,6 +62,9 @@ class BundleRegistry(gobject.GObject): % traceback.format_exc()) self._merge_default_favorites() + + self._bundledict_cache = {} + self._typebundle_cache = {} def _get_activity_directories(self): directories = [] @@ -87,7 +94,7 @@ class BundleRegistry(gobject.GObject): because JSON doesn't support tuples and python won't accept a list as a dictionary key. """ - if ' ' in bundle_id: + if ' ' in str(bundle_id): raise ValueError('bundle_id cannot contain spaces') return '%s %s' % (bundle_id, version) @@ -130,7 +137,7 @@ class BundleRegistry(gobject.GObject): for bundle_id in default_activities: max_version = -1 - for bundle in self._bundles: + for bundle in self._bundles.itervalues(): if bundle.get_bundle_id() == bundle_id and \ max_version < bundle.get_activity_version(): max_version = bundle.get_activity_version() @@ -144,14 +151,14 @@ class BundleRegistry(gobject.GObject): self._write_favorites_file() def get_bundle(self, bundle_id): - """Returns an bundle given his service name""" - for bundle in self._bundles: + """Returns an bundle given its service name""" + for bundle in self._bundles.itervalues(): if bundle.get_bundle_id() == bundle_id: - return bundle + return self._bundle_to_dict(bundle) return None def __iter__(self): - return self._bundles.__iter__() + return (self._bundle_to_dict(bundle) for bundle in self._bundles.itervalues()) def _scan_directory(self, path): if not os.path.isdir(path): @@ -174,56 +181,72 @@ class BundleRegistry(gobject.GObject): bundle_dirs.sort(lambda d1, d2: cmp(bundles[d1], bundles[d2])) for folder in bundle_dirs: try: - self.add_bundle(folder) + self.add_bundle(folder, securitycheck=False) except Exception, e: logging.error('Error while processing installed activity ' \ 'bundle: %s, %s, %s' % (folder, e.__class__, e)) - + def add_bundle(self, bundle_path): try: bundle = ActivityBundle(bundle_path) except MalformedBundleException: return False - self._bundles.append(bundle) - self.emit('bundle-added', bundle) + key = self._get_favorite_key(bundle.get_bundle_id(), + bundle.get_activity_version()) + if key in self._bundles: + oldpath = self._bundles[key].get_path() + logging.error('Adding bundle with duplicate key: %s, %s' % + (bundle_path, key, oldpath)) + #now keep the older one - more stable. + if os.stat(oldpath).st_ctime < os.stat(bundle_path).st_ctime: + return False + self._bundles[key] = bundle + if self._typebundle_cache: + self._update_caches(key, remove=False) + self.emit('bundle-added', self._bundle_to_dict(bundle)) return True def remove_bundle(self, bundle_path): - for bundle in self._bundles: + for key, bundle in self._bundles.iteritems(): if bundle.get_path() == bundle_path: - self._bundles.remove(bundle) - self.emit('bundle-removed', bundle) + self._update_caches(key, remove=True) + bundle = self._bundles.pop(key) + self.emit('bundle-removed', self._bundle_to_dict(bundle)) return True return False def get_activities_for_type(self, mime_type): + if mime_type in self._typebundle_cache: + return self._typebundle_cache[mime_type] result = [] - for bundle in self._bundles: - if bundle.get_mime_types() and mime_type in bundle.get_mime_types(): + for bundle in self._bundles.itervalues(): + types = bundle.get_mime_types() + if types and mime_type in types: if self.get_default_for_type(mime_type) == \ bundle.get_bundle_id(): - result.insert(0, bundle) + result.insert(0, self._bundle_to_dict(bundle)) else: - result.append(bundle) + result.append(self._bundle_to_dict(bundle)) + self._typebundle_cache[mime_type] = result return result def get_default_for_type(self, mime_type): if self._mime_defaults.has_key(mime_type): - return self._mime_defaults[mime_type] + return self._bundle_to_dict(self._mime_defaults[mime_type]) else: return None def _find_bundle(self, bundle_id, version): - for bundle in self._bundles: - if bundle.get_bundle_id() == bundle_id and \ - bundle.get_activity_version() == version: - return bundle + key = self._get_favorite_key(bundle_id, version) + if key in self._bundles: + return self._bundles[key] raise ValueError('No bundle %r with version %r exists.' % \ (bundle_id, version)) def set_bundle_favorite(self, bundle_id, version, favorite): key = self._get_favorite_key(bundle_id, version) + self._update_caches(key, remove=True) if favorite and not key in self._favorite_bundles: self._favorite_bundles[key] = None elif not favorite and key in self._favorite_bundles: @@ -233,14 +256,15 @@ class BundleRegistry(gobject.GObject): self._write_favorites_file() bundle = self._find_bundle(bundle_id, version) - self.emit('bundle-changed', bundle) + self.emit('bundle-changed', self._bundle_to_dict(bundle)) - def is_bundle_favorite(self, bundle_id, version): - key = self._get_favorite_key(bundle_id, version) + def is_bundle_favorite(self, key): return key in self._favorite_bundles def set_bundle_position(self, bundle_id, version, x, y): key = self._get_favorite_key(bundle_id, version) + self._bundledict_cache.pop(key, none) + #_typebundle_cache has this data too but so what? if key not in self._favorite_bundles: raise ValueError('Bundle %s %s not favorite' % (bundle_id, version)) @@ -254,25 +278,90 @@ class BundleRegistry(gobject.GObject): self._write_favorites_file() bundle = self._find_bundle(bundle_id, version) - self.emit('bundle-changed', bundle) + self.emit('bundle-changed', self._bundle_to_dict(bundle)) - def get_bundle_position(self, bundle_id, version): + def get_bundle_position(self, key): """Get the coordinates where the user wants the representation of this bundle to be displayed. Coordinates are relative to a 1000x1000 area. """ - key = self._get_favorite_key(bundle_id, version) if key not in self._favorite_bundles or \ self._favorite_bundles[key] is None or \ 'position' not in self._favorite_bundles[key]: return (-1, -1) else: return tuple(self._favorite_bundles[key]['position']) + + def _invalidate_caches(self): + self._bundledict_cache = {} + self._typebundle_cache = {} + + def _update_caches(self, key, remove): + """Fix the caches to add a bundle or remove it. + + NOTE: call this BEFORE you remove a key from self._bundles + + remove: True to remove or change, False to add.""" + if remove: + self._bundledict_cache.pop(key,None) + #else: be lazy + + types = bundle.get_mime_types() + for type in types: + if type in self._typebundle_cache: + if remove: + del self._typebundle_cache[type] + else: + self._typebundle_cache[type] += (self._bundle_to_dict(bundle),) def _write_favorites_file(self): path = env.get_profile_path('favorite_activities') favorites_data = {'defaults-mtime': self._last_defaults_mtime, 'favorites': self._favorite_bundles} simplejson.dump(favorites_data, open(path, 'w'), indent=1) + + def _validate_bitfrost(self, bundle): + requested = bundle.get_bitfrost_requests().intersection(VALID_BITFROST) +# if "P_ROOT" in requested: +# #only allow root for .../share/sugar/activities +# #do not check full path for jhbuild compatibility. +# path = os.path.split(bundle.get_path()) +# if path[-4:-1] != ["share", "sugar", "activities"]: +# requested = requested.difference(["P_ROOT"]) +# +# #only allow root if owner is the same as owner of this module, +# #and permissions are same or tighter. +# else: +# bundle_s = os.stat(path) +# thismod_s = os.stat(sys.modules[__name__].__file__) +# if (bundle_s.st_uid != thismod_s.st_uid or +# ((bundle_s.st_mode | thismod_s.st_mode) > +# thismod_s.st_mode)): +# requested = requested.difference(["P_ROOT"]) + return requested + + def _bundle_to_dict(self, bundle): + key = self._get_favorite_key(bundle.get_bundle_id(), + bundle.get_activity_version()) + if key not in self._bundledict_cache: + favorite = self.is_bundle_favorite(key) + x, y = self.get_bundle_position(key) + result = {'name': bundle.get_name(), + 'icon': bundle.get_icon(), + 'bundle_id': bundle.get_bundle_id(), + 'version': bundle.get_activity_version(), + 'path': bundle.get_path(), + 'command': bundle.get_command(), + 'show_launcher': bundle.get_show_launcher(), + 'favorite': favorite, + 'installation_time': bundle.get_installation_time(), + 'position_x': x, + 'position_y': y, + 'bitfrost': dbus.Array(self._validate_bitfrost(bundle), + signature="as")} + self._bundledict_cache[key] = result + return result + else: + return self._bundledict_cache[key] _instance = None
From 0e7977843908d805fdf07b4466b1c87a6ffdf379 Mon Sep 17 00:00:00 2001 From: Jameson Quinn <[EMAIL PROTECTED]> Date: Wed, 6 Aug 2008 10:38:44 -0600 Subject: [PATCH] bug #5657: don't install applications in Rainbow's loophole, unless forced --- src/sugar/activity/activityfactory.py | 12 +++++++----- src/sugar/bundle/activitybundle.py | 7 ++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/sugar/activity/activityfactory.py b/src/sugar/activity/activityfactory.py index 4d6871f..c94ff5d 100644 --- a/src/sugar/activity/activityfactory.py +++ b/src/sugar/activity/activityfactory.py @@ -54,6 +54,12 @@ _RAINBOW_SERVICE_NAME = "org.laptop.security.Rainbow" _RAINBOW_ACTIVITY_FACTORY_PATH = "/" _RAINBOW_ACTIVITY_FACTORY_INTERFACE = "org.laptop.security.Rainbow" +RAINBOW_LOOPHOLE_LIST = [ 'org.laptop.JournalActivity', + 'org.laptop.Terminal', + 'org.laptop.Log', + 'org.laptop.Analyze' + ] + _children_pid = [] def _sigchild_handler(signum, frame): @@ -193,11 +199,7 @@ class ActivityCreationHandler(gobject.GObject): self._handle = handle self._use_rainbow = os.path.exists('/etc/olpc-security') - if service_name in [ 'org.laptop.JournalActivity', - 'org.laptop.Terminal', - 'org.laptop.Log', - 'org.laptop.Analyze' - ]: + if service_name in RAINBOW_LOOPHOLE_LIST: self._use_rainbow = False bus = dbus.SessionBus() diff --git a/src/sugar/bundle/activitybundle.py b/src/sugar/bundle/activitybundle.py index 2c235d8..25f8f9e 100644 --- a/src/sugar/bundle/activitybundle.py +++ b/src/sugar/bundle/activitybundle.py @@ -352,7 +352,12 @@ class ActivityBundle(Bundle): os.path.basename(info_file))) return install_path - def install(self): + def install(self, securitycheck=True): + if securitycheck: + from sugar.activity.activityfactory import RAINBOW_LOOPHOLE_LIST + if self._bundle_id in RAINBOW_LOOPHOLE_LIST: + raise MalformedBundleException( + "No privileges to install a P_ROOT activity") activities_path = env.get_user_activities_path() act = activity.get_registry().get_activity(self._bundle_id) if act is not None and act.path.startswith(activities_path): -- 1.5.2.5
diff --git a/src/sugar/activity/activityfactory.py b/src/sugar/activity/activityfactory.py index 4d6871f..9912ca5 100644 --- a/src/sugar/activity/activityfactory.py +++ b/src/sugar/activity/activityfactory.py @@ -29,7 +29,7 @@ from sugar.activity import registry from sugar import util from sugar import env -from errno import EEXIST +from errno import EEXIST, ENOSPC import os @@ -150,6 +150,9 @@ def open_log_file(activity): except OSError, e: if e.errno == EEXIST: i += 1 + elif e.errno == ENOSPC: + # not the end of the world; let's try to keep going. + return ('/dev/null', open('/dev/null','w')) else: raise e @@ -241,11 +244,9 @@ class ActivityCreationHandler(gobject.GObject): self._handle.object_id, self._handle.uri) - if not self._use_rainbow: - p = subprocess.Popen(command, env=environ, cwd=activity.path, - stdout=log_file, stderr=log_file) - _children_pid.append(p.pid) - else: + use_rainbow = (os.path.exists('/etc/olpc-security') and + "P_ROOT" in activity["bitfrost"]) + if use_rainbow: log_file.close() system_bus = dbus.SystemBus() factory = system_bus.get_object(_RAINBOW_SERVICE_NAME, @@ -260,6 +261,10 @@ class ActivityCreationHandler(gobject.GObject): reply_handler=self._create_reply_handler, error_handler=self._create_error_handler, dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE) + else: + p = subprocess.Popen(command, env=environ, cwd=activity.path, + stdout=log_file, stderr=log_file) + _children_pid.append(p.pid) def _no_reply_handler(self, *args): pass diff --git a/src/sugar/activity/registry.py b/src/sugar/activity/registry.py index da2eb27..cc78b19 100644 --- a/src/sugar/activity/registry.py +++ b/src/sugar/activity/registry.py @@ -27,17 +27,13 @@ _ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry' def _activity_info_from_dict(info_dict): if not info_dict: - return None - return ActivityInfo(info_dict['name'], info_dict['icon'], - info_dict['bundle_id'], info_dict['version'], - info_dict['path'], info_dict['show_launcher'], - info_dict['command'], info_dict['favorite'], - info_dict['installation_time'], - info_dict['position_x'], info_dict['position_y']) + return {} + return ActivityInfo(**dict((str(key),val) + for key,val in info_dict.iteritems())) class ActivityInfo(object): - def __init__(self, name, icon, bundle_id, version, path, show_launcher, - command, favorite, installation_time, position_x, position_y): + """A convenience class whose members are: + self.name = name self.icon = icon self.bundle_id = bundle_id @@ -48,6 +44,12 @@ class ActivityInfo(object): self.favorite = favorite self.installation_time = installation_time self.position = (position_x, position_y) + self.bitfrost = bitfrost + """ + def __init__(self, **args): + self.position = (args["position_x"], args["position_y"]) + del args["position_x"], args["position_y"] + self.__dict__.update(args) class ActivityRegistry(gobject.GObject): __gsignals__ = { @@ -83,24 +85,12 @@ class ActivityRegistry(gobject.GObject): self._service_name_to_activity_info = {} self._mime_type_to_activities = {} - def _convert_info_list(self, info_list): - result = [] - - for info_dict in info_list: - result.append(_activity_info_from_dict(info_dict)) - - return result - def get_activities(self): info_list = self._registry.GetActivities() - return self._convert_info_list(info_list) + return (_activity_info_from_dict(info) for info in info_list) def _get_activities_cb(self, reply_handler, info_list): - result = [] - for info_dict in info_list: - result.append(_activity_info_from_dict(info_dict)) - - reply_handler(result) + reply_handler(_activity_info_from_dict(info) for info in info_list) def _get_activities_error_cb(self, error_handler, e): if error_handler: @@ -111,7 +101,7 @@ class ActivityRegistry(gobject.GObject): def get_activities_async(self, reply_handler=None, error_handler=None): if not reply_handler: logging.error('Function get_activities_async called' \ - 'without a reply handler. Can not run.') + 'without a reply handler. Can not run.') return self._registry.GetActivities( @@ -120,26 +110,33 @@ class ActivityRegistry(gobject.GObject): error_handler=lambda e: \ self._get_activities_error_cb(error_handler, e)) + def safe_permissions(self, bitfrost_permissions): + return "P_ROOT" not in bitfrost_permissions + def get_activity(self, service_name): if self._service_name_to_activity_info.has_key(service_name): return self._service_name_to_activity_info[service_name] info_dict = self._registry.GetActivity(service_name) + activity_info = _activity_info_from_dict(info_dict) - - self._service_name_to_activity_info[service_name] = activity_info + + #extra security precaution (to prevent dbus DOS from escalating privs): + # do not cache unsafe permissions + if self.safe_permissions(activity_info["bitfrost"]): + self._service_name_to_activity_info[service_name] = activity_info return activity_info def find_activity(self, name): info_list = self._registry.FindActivity(name) - return self._convert_info_list(info_list) + return (_activity_info_from_dict(info) for info in info_list) def get_activities_for_type(self, mime_type): if self._mime_type_to_activities.has_key(mime_type): return self._mime_type_to_activities[mime_type] info_list = self._registry.GetActivitiesForType(mime_type) - activities = self._convert_info_list(info_list) + activities = (_activity_info_from_dict(info) for info in info_list) self._mime_type_to_activities[mime_type] = activities return activities diff --git a/src/sugar/bundle/activitybundle.py b/src/sugar/bundle/activitybundle.py index 88ef5f1..dd620fa 100644 --- a/src/sugar/bundle/activitybundle.py +++ b/src/sugar/bundle/activitybundle.py @@ -23,8 +23,7 @@ import os import tempfile from sugar.bundle.bundle import Bundle, MalformedBundleException, \ - AlreadyInstalledException, RegistrationException, \ - NotInstalledException + AlreadyInstalledException, RegistrationException, NotInstalledException from sugar import activity from sugar import env @@ -43,18 +42,22 @@ class ActivityBundle(Bundle): _zipped_extension = '.xo' _unzipped_extension = '.activity' _infodir = 'activity' + + _name = None + _icon = None + _bundle_id = None + _mime_types = None + _show_launcher = True + _activity_version = 0 + _bitfrost_requests = frozenset() + def __init__(self, path): Bundle.__init__(self, path) self.activity_class = None self.bundle_exec = None - self._name = None - self._icon = None - self._bundle_id = None - self._mime_types = None - self._show_launcher = True - self._activity_version = 0 + self._installation_time = os.stat(path).st_mtime info_file = self.get_file('activity/activity.info') if info_file is None: @@ -65,7 +68,7 @@ class ActivityBundle(Bundle): if linfo_file: self._parse_linfo(linfo_file) - self.manifest = None #This should be replaced by following function + self.manifest = None # This should be replaced by following function self.read_manifest() def _raw_manifest(self): @@ -176,7 +179,14 @@ class ActivityBundle(Bundle): raise MalformedBundleException( 'Activity bundle %s has invalid version number %s' % (self._path, version)) - + + if cp.has_option(section, "bitfrost_requests"): + bitfrost = cp.get(section, "bitfrost_requests") + #bitfrost_requests = P_SOMETHING, P_SOMETHING_ELSE, p_some garbage, P_MAL FORMED, + #becomes set("P_SOMETHING","P_SOMETHING_ELSE","P_MAL FORMED") + bitfrost = (word.strip() for word in bitfrost.split(",") if word.strip().startswith("P_")) + self._bitfrost_requests = set(bitfrost) + def _get_linfo_file(self): lang = locale.getdefaultlocale()[0] if not lang: @@ -226,7 +236,7 @@ class ActivityBundle(Bundle): def get_installation_time(self): """Get a timestamp representing the time at which this activity was installed.""" - return os.stat(self._path).st_mtime + return self._installation_time def get_bundle_id(self): """Get the activity bundle id""" @@ -259,6 +269,8 @@ class ActivityBundle(Bundle): return command + def get_bitfrost_requests(self): + return self._bitfrost_requests def get_mime_types(self): """Get the MIME types supported by the activity""" @@ -275,10 +287,10 @@ class ActivityBundle(Bundle): return False def need_upgrade(self): - """Returns True if installing this activity bundle is meaningful - + """Returns True if installing this activity bundle is meaningful - that is, if an identical version of this activity is not already installed. - + Until we have cryptographic hashes to check identity, returns True always. See http://dev.laptop.org/ticket/7534.""" return True @@ -352,7 +364,11 @@ class ActivityBundle(Bundle): os.path.basename(info_file))) return install_path - def install(self): + def install(self, securitycheck=True): + if securitycheck: + if "P_ROOT" in self.get_bitfrost_requests(): + raise MalformedBundleException( + "No privileges to install a P_ROOT activity") activities_path = env.get_user_activities_path() act = activity.get_registry().get_activity(self._bundle_id) if act is not None and act.path.startswith(activities_path):
From 91ac9e1222bd54a84f8414ca7c2e712f8459eee4 Mon Sep 17 00:00:00 2001 From: Jameson Quinn <[EMAIL PROTECTED]> Date: Wed, 6 Aug 2008 10:29:04 -0600 Subject: [PATCH] some minor pylint fixes --- service/bundleregistry.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/service/bundleregistry.py b/service/bundleregistry.py index 5d3fec8..04adbc2 100644 --- a/service/bundleregistry.py +++ b/service/bundleregistry.py @@ -54,7 +54,7 @@ class BundleRegistry(gobject.GObject): try: self._load_favorites() except Exception, e: - logging.error('Error while loading favorite_activities\n%s.' \ + logging.error('Error while loading favorite_activities\n %s.' \ % traceback.format_exc()) self._merge_default_favorites() @@ -104,8 +104,8 @@ class BundleRegistry(gobject.GObject): if not isinstance(first_key, basestring): raise ValueError('Invalid format in %s.' % favorites_path) - first_value = favorite_bundles.values()[0] - if first_value is not None and not isinstance(first_value, dict): + first_val = favorite_bundles.values()[0] + if first_val is not None and not isinstance(first_val, dict): raise ValueError('Invalid format in %s.' % favorites_path) self._last_defaults_mtime = float(favorites_data['defaults-mtime']) -- 1.5.2.5
_______________________________________________ Sugar mailing list Sugar@lists.laptop.org http://lists.laptop.org/listinfo/sugar