def testFeeds(self): iface = model.Interface('http://test/test') main_feed = model.ZeroInstallFeed(test_feed, local_path = '/Hello') self.config.iface_cache._feeds[iface.uri] = main_feed iface.stability_policy = model.developer main_feed.last_checked = 100 iface.extra_feeds.append(model.Feed('http://sys-feed', None, False)) iface.extra_feeds.append(model.Feed('http://user-feed', 'Linux-*', True)) writer.save_interface(iface) writer.save_feed(main_feed) iface = model.Interface('http://test/test') self.assertEqual(None, iface.stability_policy) main_feed = model.ZeroInstallFeed(test_feed, local_path = '/Hello') self.config.iface_cache._feeds[iface.uri] = main_feed reader.update_user_overrides(iface) reader.update_user_feed_overrides(main_feed) self.assertEqual(model.developer, iface.stability_policy) self.assertEqual(100, main_feed.last_checked) self.assertEqual("[<Feed from http://user-feed>]", str(iface.extra_feeds)) feed = iface.extra_feeds[0] self.assertEqual('http://user-feed', feed.uri) self.assertEqual('Linux', feed.os) self.assertEqual(None, feed.machine)
def get_feed(self, url, force = False, selections_ok = False): """Get a feed from the cache. @param url: the URL of the feed @type url: str @param force: load the file from disk again @type force: bool @param selections_ok: if url is a local selections file, return that instead @type selections_ok: bool @return: the feed, or None if it isn't cached @rtype: L{model.ZeroInstallFeed}""" if not force: feed = self._feeds.get(url, False) if feed != False: return feed if url.startswith('distribution:'): master_feed = self.get_feed(url.split(':', 1)[1]) if not master_feed: return None # Can't happen? feed = self.distro.get_feed(master_feed) else: feed = reader.load_feed_from_cache(url, selections_ok = selections_ok) if selections_ok and feed and not isinstance(feed, model.ZeroInstallFeed): assert feed.selections is not None return feed # (it's actually a selections document) if feed: reader.update_user_feed_overrides(feed) self._feeds[url] = feed return feed
def testFeeds(self): iface = model.Interface('http://test/test') main_feed = model.ZeroInstallFeed(test_feed, local_path='/Hello') self.config.iface_cache._feeds[iface.uri] = main_feed iface.stability_policy = model.developer main_feed.last_checked = 100 iface.extra_feeds.append(model.Feed('http://sys-feed', None, False)) iface.extra_feeds.append( model.Feed('http://user-feed', 'Linux-*', True)) writer.save_interface(iface) writer.save_feed(main_feed) iface = model.Interface('http://test/test') self.assertEquals(None, iface.stability_policy) main_feed = model.ZeroInstallFeed(test_feed, local_path='/Hello') self.config.iface_cache._feeds[iface.uri] = main_feed reader.update_user_overrides(iface) reader.update_user_feed_overrides(main_feed) self.assertEquals(model.developer, iface.stability_policy) self.assertEquals(100, main_feed.last_checked) self.assertEquals("[<Feed from http://user-feed>]", str(iface.extra_feeds)) feed = iface.extra_feeds[0] self.assertEquals('http://user-feed', feed.uri) self.assertEquals('Linux', feed.os) self.assertEquals(None, feed.machine)
def get_feed(self, url, force=False, selections_ok=False): """Get a feed from the cache. @param url: the URL of the feed @type url: str @param force: load the file from disk again @type force: bool @param selections_ok: if url is a local selections file, return that instead @type selections_ok: bool @return: the feed, or None if it isn't cached @rtype: L{model.ZeroInstallFeed}""" if not force: feed = self._feeds.get(url, False) if feed != False: return feed if url.startswith('distribution:'): master_feed = self.get_feed(url.split(':', 1)[1]) if not master_feed: return None # e.g. when checking a selections document feed = self.distro.get_feed(master_feed) else: feed = reader.load_feed_from_cache(url, selections_ok=selections_ok) if selections_ok and feed and not isinstance( feed, model.ZeroInstallFeed): assert feed.selections is not None return feed # (it's actually a selections document) if feed: reader.update_user_feed_overrides(feed) self._feeds[url] = feed return feed
def do_import_feed(config, xml): if gui_driver is not None: config = gui_driver.config feed = model.ZeroInstallFeed(xml) reader.update_user_feed_overrides(feed) feed_url = xml.attrs['uri'] config.iface_cache._feeds[feed_url] = feed
def testStoreStability(self): main_feed = reader.load_feed('Hello.xml', local = True) impl = main_feed.implementations['sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'] impl.user_stability = model.developer writer.save_feed(main_feed) # Rating now visible main_feed = reader.load_feed('Hello.xml', local = True) reader.update_user_feed_overrides(main_feed) self.assertEqual(1, len(main_feed.implementations)) impl = main_feed.implementations['sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'] self.assertEqual(model.developer, impl.user_stability)
def _import_new_feed(self, feed_url, new_xml, modified_time, dry_run): """Write new_xml into the cache. @param feed_url: the URL for the feed being updated @type feed_url: str @param new_xml: the data to write @type new_xml: str @param modified_time: when new_xml was modified @type modified_time: int @type dry_run: bool @raises ReplayAttack: if the new mtime is older than the current one""" assert modified_time assert isinstance(new_xml, bytes), repr(new_xml) upstream_dir = basedir.save_cache_path(config_site, 'interfaces') cached = os.path.join(upstream_dir, escape(feed_url)) old_modified = None if os.path.exists(cached): with open(cached, 'rb') as stream: old_xml = stream.read() if old_xml == new_xml: logger.debug(_("No change")) # Update in-memory copy, in case someone else updated the disk copy self.get_feed(feed_url, force = True) return old_modified = int(os.stat(cached).st_mtime) if dry_run: print(_("[dry-run] would cache feed {url} as {cached}").format( url = feed_url, cached = cached)) from io import BytesIO from zeroinstall.injector import qdom root = qdom.parse(BytesIO(new_xml), filter_for_version = True) feed = model.ZeroInstallFeed(root) reader.update_user_feed_overrides(feed) self._feeds[feed_url] = feed return # Do we need to write this temporary file now? try: with open(cached + '.new', 'wb') as stream: stream.write(new_xml) os.utime(cached + '.new', (modified_time, modified_time)) new_mtime = reader.check_readable(feed_url, cached + '.new') assert new_mtime == modified_time old_modified = self._get_signature_date(feed_url) or old_modified if old_modified: if new_mtime < old_modified: raise ReplayAttack(_("New feed's modification time is " "before old version!\nInterface: %(iface)s\nOld time: %(old_time)s\nNew time: %(new_time)s\n" "Refusing update.") % {'iface': feed_url, 'old_time': _pretty_time(old_modified), 'new_time': _pretty_time(new_mtime)}) if new_mtime == old_modified: # You used to have to update the modification time manually. # Now it comes from the signature, this check isn't useful # and often causes problems when the stored format changes # (e.g., when we stopped writing last-modified attributes) pass #raise SafeException("Interface has changed, but modification time " # "hasn't! Refusing update.") except: os.unlink(cached + '.new') raise portable_rename(cached + '.new', cached) logger.debug(_("Saved as %s") % cached) self.get_feed(feed_url, force = True)
def _import_new_feed(self, feed_url, new_xml, modified_time, dry_run): """Write new_xml into the cache. @param feed_url: the URL for the feed being updated @type feed_url: str @param new_xml: the data to write @type new_xml: str @param modified_time: when new_xml was modified @type modified_time: int @type dry_run: bool @raises ReplayAttack: if the new mtime is older than the current one""" assert modified_time assert isinstance(new_xml, bytes), repr(new_xml) upstream_dir = basedir.save_cache_path(config_site, 'interfaces') cached = os.path.join(upstream_dir, escape(feed_url)) old_modified = None if os.path.exists(cached): with open(cached, 'rb') as stream: old_xml = stream.read() if old_xml == new_xml: logger.debug(_("No change")) # Update in-memory copy, in case someone else updated the disk copy self.get_feed(feed_url, force=True) return old_modified = int(os.stat(cached).st_mtime) if dry_run: print( _("[dry-run] would cache feed {url} as {cached}").format( url=feed_url, cached=cached)) from io import BytesIO from zeroinstall.injector import qdom root = qdom.parse(BytesIO(new_xml), filter_for_version=True) feed = model.ZeroInstallFeed(root) reader.update_user_feed_overrides(feed) self._feeds[feed_url] = feed return # Do we need to write this temporary file now? try: with open(cached + '.new', 'wb') as stream: stream.write(new_xml) os.utime(cached + '.new', (modified_time, modified_time)) new_mtime = reader.check_readable(feed_url, cached + '.new') assert new_mtime == modified_time old_modified = self._get_signature_date(feed_url) or old_modified if old_modified: if new_mtime < old_modified: raise ReplayAttack( _("New feed's modification time is " "before old version!\nInterface: %(iface)s\nOld time: %(old_time)s\nNew time: %(new_time)s\n" "Refusing update.") % { 'iface': feed_url, 'old_time': _pretty_time(old_modified), 'new_time': _pretty_time(new_mtime) }) if new_mtime == old_modified: # You used to have to update the modification time manually. # Now it comes from the signature, this check isn't useful # and often causes problems when the stored format changes # (e.g., when we stopped writing last-modified attributes) pass #raise SafeException("Interface has changed, but modification time " # "hasn't! Refusing update.") except: os.unlink(cached + '.new') raise portable_rename(cached + '.new', cached) logger.debug(_("Saved as %s") % cached) self.get_feed(feed_url, force=True)