aboutsummaryrefslogtreecommitdiff
path: root/AptUrl
diff options
context:
space:
mode:
authorLibravatar Clement Lefebvre <root@linuxmint.com>2022-06-20 13:36:09 +0200
committerLibravatar Mubashshir <ahm@jadupc.com>2023-08-03 15:30:24 +0600
commit6797ff836182c0727c71ee07e08bafc31f5b56e6 (patch)
tree6429de09c97acd6e188e75e4048b0b9baf2c8f0a /AptUrl
downloadapturl-6797ff836182c0727c71ee07e08bafc31f5b56e6.tar.gz
apturl-6797ff836182c0727c71ee07e08bafc31f5b56e6.zip
Import Debian version 0.5.2+linuxmint13
apturl (0.5.2+linuxmint13) vanessa; urgency=medium . * bump - rebuild using XZ compression . apturl (0.5.2+linuxmint12) vanessa; urgency=medium . * Depend on mint-common . apturl (0.5.2+linuxmint11) ulyana; urgency=medium . * UI: Fix underlined label . apturl (0.5.2+linuxmint10) ulyana; urgency=medium . [ gogogogi ] * Update hr.po (#5) . [ Michael Webster ] * Fix dep resolution, improve initial query dialog (#4) . apturl (0.5.2+linuxmint9) ulyana; urgency=medium . * Switch from synaptic to mintcommon-aptdaemon backend . apturl (0.5.2+linuxmint8) ulyana; urgency=medium . * Fix refreshing cache . apturl (0.5.2+linuxmint7) tara; urgency=medium . * Fix xapp dependency * Set dialog title . apturl (0.5.2+linuxmint6) tara; urgency=medium . * UI: don't skip taskbar, set icon properly . apturl (0.5.2+linuxmint5) sylvia; urgency=medium . [ monsta ] * drop aptdaemon deps - not needed anymore (#2) . apturl (0.5.2+linuxmint4) serena; urgency=medium . [ gogogogi ] * Fix po.hr . apturl (0.5.2+linuxmint3) sarah; urgency=medium . * Updated translations . apturl (0.5.2+linuxmint2) sarah; urgency=medium . * Remove channel/section support and dependencies on Ubuntu components and webkit . apturl (0.5.2+linuxmint1) sarah; urgency=medium . * Removed QT interface * Remove backends (will be reimplemented without dependencies on Ubuntu components) * Specify Gtk version in gi * Implemented synaptics installations . apturl (0.5.2ubuntu11) xenial; urgency=medium . * Drop webkit1 support, we're switching to pure webkit2 now . apturl (0.5.2ubuntu10) xenial; urgency=medium . * debian/apturl.install: - don't install the gconf schemas, it's probably useful to no one nowadays (would only work for applications using the GNOME2 libgnome) and creates a depends on gconf which we want to drop from the iso . apturl (0.5.2ubuntu9) wily; urgency=medium . * data/apturl-gtk.ui: set the dimension on the scrolledwindow rather than the textview so the description is showing with a non zero height . apturl (0.5.2ubuntu8) wily; urgency=medium . * Use webkit2 in addition to webkit1. (LP: #1469221) . apturl (0.5.2ubuntu7) wily; urgency=medium . * Don't include Debian version in the python module version (LP: #1465549) . apturl (0.5.2ubuntu6) vivid; urgency=medium . [ Tim Lunn ] * Don't use legacy icon names, these are no longer available in adwaita-icon-theme. (LP: #1437150) . [ Iain Lane ] * For dialog-question, go back to using the stock icon name as Humanity doesn't yet have an icon with the new name. . apturl (0.5.2ubuntu5) vivid; urgency=medium . * Switch gnome-icon-theme to adwaita-icon-theme, which is its successor. (LP: #1414613) . apturl (0.5.2ubuntu4) trusty; urgency=medium . * Drop libgtk2-perl Recommends to Suggests. . apturl (0.5.2ubuntu3) trusty; urgency=low . * AptUrl/AptUrl.py: don't use decode on a str (lp: #1050826) . apturl (0.5.2ubuntu2) saucy; urgency=low . * adjust backend to reuse the bits from update-manager (LP: #1200775) . apturl (0.5.2ubuntu1) raring; urgency=low . * AptUrl/gtk/backend/__init__.py: Drop "action-done" signal definition; update-manager's GTK backend already defines it with different arguments, so this is ineffective and confusing. * AptUrl/gtk/GtkUI.py, _on_backend_done(): Add additional error signal arguments, as defined by update-manager's backend. * AptUrl/gtk/backend/InstallBackend{Aptdaemon,Synaptic}.py: Call action-done signal with error arguments. (LP: #1103024) * data/apturl-gtk.ui: Drop obsolete "has_separator" property. Fixes a warning. . apturl (0.5.1ubuntu6) quantal; urgency=low . * AptUrl/gtk/backend/InstallBackendAptdaemon.py: Work around incompatible Update Manager API change (as described in Launchpad bug #1026257). LP: #1020980 . apturl (0.5.1ubuntu5) quantal; urgency=low . * debian/control: Move python3-aptdaemon dependency to apturl binary package (from apturl-common) since only the gtk backend needs it. . apturl (0.5.1ubuntu4) quantal; urgency=low . [ Brian Murray ] * Port to Python 3: - Use Python 3 style print functions * AptUrl/Parser.py: - ensure MAX_URL_LEN/10 returns an int . [ Colin Watson ] * AptUrl/gtk/backend/InstallBackendSynaptic.py: - Keep a reference to the data tuple passed to GObject.child_watch_add to avoid attempts to destroy it without a thread context. - Open temporary synaptic selections file in text mode. . [ Barry Warsaw ] * Additional Python 3 fixes: + Port setup.py to Python 3. + Use the new python-apt API since the legacy API is not available in Python 3. + ki18n() takes bytes. + Fix relative imports so the code can be run from source. + Fixed some additional packaging paths. + Change #! lines to use python3. + Changed debian/control and debian/rules to use python3. + Change debian/compat == 9 + apturl now must require python3-aptdaemon.gtk3widgets (i.e. not | synaptic) due to the Python 3 port of update-manager. * Other changes: + Remove the need for threads in the KDE front-end. + Enable running the test suite via `python3 -m unittest discover` + i18n updates. + Various and sundry pyflakes, whitespace, style, line length, and spelling fixes. . apturl (0.5.1ubuntu3) precise; urgency=low . * Take the unicode representation of the parser error message instead of the string representation, so that we get clean i18n handling. LP: #911144. . apturl (0.5.1ubuntu2) precise; urgency=low . * debian/control: Fix dependencies: python-gobject → python-gi. . apturl (0.5.1ubuntu1) oneiric-proposed; urgency=low . * add support for multiarch package names (LP: #872146) . apturl (0.5ubuntu1) oneiric; urgency=low . * port to gtk3, update dependencies . apturl (0.4.3ubuntu1) oneiric; urgency=low . * improve exception handling and shorten overly long strings * add aptdaemon backend * add dependencies to python-aptdaemon-gtk . apturl (0.4.2ubuntu5) natty; urgency=low . * debian/apturl-common.install: - fix install file by removing no longer relevant usr/share/omf (this fixes a FTBFS) . apturl (0.4.2ubuntu4) natty; urgency=low . * data/apturl.desktop: - Add a desktop file to register mime type. LP: #698181 . apturl (0.4.2ubuntu3) natty; urgency=low . * Don't hardcode python2.6 in the packaging. * Build using dh_python2 instead of dh_pycentral. . apturl (0.4.2ubuntu2) natty; urgency=low . [ Harald Sitter ] * Make apturl-kde explicity depend on python-qt4 and python-kde4 . [ Colin Watson ] * Make apturl recommend libgtk2-perl (>= 1:1.130) rather than libgnome2-perl, matching debconf 1.5.36ubuntu3. . apturl (0.4.2ubuntu1) natty; urgency=low . * Switch from glade to GtkBuilder (LP: #403533) . apturl (0.4.1ubuntu7) maverick; urgency=low . * Fix KDE protocol files to enlist in the local protocol class + This makes KRunner in KDE SC 4.5 pick up apt:foo as call to apturl again * Bump standards version to 3.9.1 * Switch to dpkg-source 3 * Switch all packages to arch:any rather than all . apturl (0.4.1ubuntu6) maverick; urgency=low . * Port apturl-kde to qapt-batch (LP: #497803) * Replace the dependency on install-package with one on qapt-batch . apturl (0.4.1ubuntu5) maverick; urgency=low . * Fix LP: #576944 - Move the Firefox preferences to /etc/firefox - update setup.py - add debian/apturl-common.postinst - add debian/apturl-common.preinst * Don't install apturl.js in /usr/share/firerox - Firefox doesn't see this - update debian/apturl-common.install - update setup.py * Add a couple of extra preferences for Firefox - update data/apturl.js . apturl (0.4.1ubuntu4) lucid; urgency=low . * Drop python-gtkhtml2 recommends (moved to webkit). . apturl (0.4.1ubuntu3) lucid; urgency=low . * apturl.8: - add example for the "channel" parameter * AptUrl/gtk/GtkUI.py: - use webkit instead of gtkhtml (ucid-duplicated-packages spec) * debian/control: - add python-webkit depend on debian/control . apturl (0.4.1ubuntu2) karmic; urgency=low . * Reupload merged 0.4.0ubuntu5 and 0.4.1ubuntu1, forgot to bzr push -.- . apturl (0.4.1ubuntu1) karmic; urgency=low . [ Harald Sitter ] * Borrow encoding wrappers from GDebi to fix encodings in KDE UI . [ Michael Vogt ] * AptUrl/gtk/GtkUI.py: - Use software-properites to enable componenents * debian/control: - Remove dependency on gnome-app-install - Add software-properties-gtk . apturl (0.4.0ubuntu5) karmic; urgency=low . * Borrow encoding wrappers from GDebi to fix encodings in KDE UI (implemented via Helpers). These new wrappers utf8, _ and _n are used throughout the whole application. * Fix minor formatting error in KDE UI's _get_dialog * link apturl's manpage to the apturl-gtk and apturl-kde manpages since they share the same argument parser anyway * Bump standards version to 3.8.3 * Port package build system to dh 7 + Build-depend on debhelper 7 . apturl (0.4.0ubuntu4) karmic; urgency=low . * build without "DH_PYCENTRAL=include-links" for now, to work around breakage when upgrading from the previous version that was build without the include-links option (LP: #422825) . apturl (0.4.0ubuntu3) karmic; urgency=low . * Make KDE frontend use a Qt UI file (should make it easier to maintain) * Enable KDE frontend to few HTML when about to enable a software channel * Clean-up setup.py * Make apturl script fall back to KDE frontend when -gtk is not installed even if KDE_FULL_SESSION is not set * Resolve self-relations of apturl binary package * fix crash on ctrl-c (in KDE frontend) . apturl (0.4.0ubuntu2) karmic; urgency=low . * fix FTBFS * fix crash on ctrl-c . apturl (0.4.0ubuntu1) karmic; urgency=low . [ Harald Sitter ] * Add KDE frontend (LP: #293533) . [ Michael Vogt ] * build with DH_PYCENTRAL=include-links . apturl (0.3.6ubuntu1) karmic; urgency=low . * AptUrl/AptUrl.py, AptUrl/UI.py, AptUrl/gtk/GtkUI.py: - show channel info when enabling channels * debian/control: - recommend python-gthtml2 (for the channel info UI) . apturl (0.3.5ubuntu1) karmic; urgency=low . * AptUrl/AptUrl.py: - when enabling sections, do not skip that if the requested package is already known to the package cache * AptUrl/Parser.py: - support proper url synatax with "&" (thanks to asac) * AptUrl/AptUrl.py: - reopen the cache properly after a refresh=yes . apturl (0.3.3ubuntu1) jaunty; urgency=low . * AptUrl/AptUrl.py: - fix crash on "refresh=yes" (LP: #327075) . apturl (0.3.2ubuntu2) jaunty; urgency=low . * AptUrl/gtk/GtkUI.py: - fix gettext domain (LP: #304950) * data/apturl.glade: - fix missing translatable property (LP: #304925) Thanks to Gabor Kelemen * AptUrl/Helpers.py: - fix crash for packages with no long description (LP: #288576) . apturl (0.3.1ubuntu1) jaunty; urgency=low . * AptUrl/AptUrl.py: - add additional sanitizing into the channel code . apturl (0.3.0ubuntu1) jaunty; urgency=low . * add README * add basic string substituion for the variables "$kernel" (uname -r) and "$distro" (lsb_release -s) this allows stuff like: "apt:linux-backports-module-$kernel" * add new field "channel" that looks into /usr/share/app-install/channels for known repositories that the user might want to add * refactored the UI code so that its easy to add a Qt frontend, see AptUrl/UI.py and AptUrl/gtk/GtkUI.py (volunteers welcome :) * improved whitelist checking . apturl (0.2.7ubuntu1) intrepid; urgency=low . [ Siegfried-Angel Gevatter Pujals ] * apturl: - Show a different error message if the requested package is virtual; this is the first step to fix Launchpad bug #230760. - Show an error dialog if the /etc/apt/sources.list is invalid instead of just crashing (LP: #206640). - Catch KeyboardInterrupt's so that they don't show a traceback. - Add a new exit code (RESULT_BADARGS, 4) for when the problem is with the arguments with which apturl was called. - Only ask once when enabling new components, and only list those which aren't already enabled. - Fix a crash which happened after enabling the requested component(s). - Don't show an error message if the user didn't want to enable a component; just silently skip the package. - Improve the description: + Don't show the summary twice. + Remove single line breaks, like packages.ubuntu.com does. + Parse the Homepage field out of the description. - Do not ask if you want to keep a software channel if it wasn't added. - Use a constant to determine wheter new software channels can be added or not (disabled by default, but that's better than having the code commented out). * AptUrl/Helpers.py: - Add it. * data/apturl.glade: - Add a missing "can_default" property to fix an assertion error. - Change the labels of the buttons on the installation confirmation dialog so that they conform to the HIG. Thanks to Bruce Cowan (LP: #140472). - Make the description field bigger and more visually appealing. * AptUrl/Parser.py: - Raise an Exception if one of the given package names contains characters which are not allowed by the Debian Policy. - Raise an Exception if one of the ?... values contains a space. * apturl.8: - Document all possible exit codes. - Add a new example, and improve the comment of an existing one. - Change the URL in "Bugs" from /apturl to /ubuntu/+source/apturl, as that's where most bugs are. * debian/control: - Add Vcs-Browser field. - Write all dependendency and build dependencies each on a line. - Add python-gobject to the build dependencies (needed for the timer). * debian/rules: - Fix the clean rule so that it removes build/ and AptUrl/Version.py. - Move the stuff from binary-arch to binary-indep, and remove the binary-indep target to please lintian. * debian/copyright: - Update copyright years and author names. . [ Артём Попов ] * data/apturl.protocol, setup.py: - Register apturl in KDE as a protocol (LP: #227622). . apturl (0.2.6ubuntu1) intrepid; urgency=low . * apturl: - add new ?refresh=1 option that allows forcing a apt-get update before the package gets installed (thanks to Vadim Peretokin, LP: #258173) . apturl (0.2.5ubuntu1) intrepid; urgency=low . * apturl: - Hide python-apt's "API not stable yet" warning. - If a package is already installed, show an informational box, not an error message (LP: #237012). - Give error dialogs the same icon as question dialogs have. * apturl.8, debian/rules: - Add a manpage (LP: #159422). * debian/control: - Bump the minimum debhelper version to 5.0.51~, as required for dh_icons. - Improve the description. * debian/copyright: - Include the full GPL header. . apturl (0.2.4ubuntu1) intrepid; urgency=low . * make dialog less greedy to not cover up Synaptic (LP: #252028) . apturl (0.2.3ubuntu1) intrepid; urgency=low . * set always on top to prevent window from being hidden (LP: #234992) . apturl (0.2.2ubuntu1) hardy; urgency=low . * apturl: - only add/ask about component enabling if the component is actually not yet available (#163049) - return correct error code when enabling a component failed/got cancelt - fix missing destroy in question() helper - ensure that component is fully availabe (LP: #208722) . apturl (0.2.1ubuntu1) hardy; urgency=low . [ Michael Vogt ] * apturl: - fix broken enable of components * debian/control: - add missing python-apt dependency . [ Fabien Tassin ] * setup.py: - add support for firefox-3.0 (LP: #207281) . apturl (0.2.0ubuntu1) hardy; urgency=low . * apturl: - run gtk.init_check() (LP: #197062) - make the description better (split into summary/long descr) - fix filename creation (LP: #138315) - typo (LP: #200504) - return proper exit codes on success/cancel/failure (LP: #132276) - only run if the apt cache is not broken * data/apturl.glade: - default button is 'no' - make it resizable * po/POTFILES.in: - add missing files (LP: #173846) * date/apturl.schemas.in, setup.py: - register apturl in gnome as a protocol . apturl (0.1.2ubuntu1) hardy; urgency=low . * support --http-proxy for better integration with the proxy settings of firefox (LP: #162609) * merged patch from Andy Owen to display a description . apturl (0.1.1ubuntu1) hardy; urgency=low . * AptUrl/Parser.py: - Implemented multipackage installation (LP: #154593) * tests/apturlparse.py: - add test for the new multipackage feature . apturl (0.1ubuntu2) gutsy-proposed; urgency=low . * support --http-proxy for better integration with the proxy settings of firefox (LP: #162609) . apturl (0.1ubuntu1) gutsy; urgency=low . * debian/control: - fix typo in description (LP: #131828) - add missing synaptic dependency (LP: #132067) * apturl: - check for already installed or unavailable packages earlier (LP: #137053, LP: #137055) - fix incorrect reference to GDebi (LP: #137065) - disable adding repositories for now (LP: #139227) . apturl (0.0+bzr20070816) gutsy; urgency=low . * added i18n support * added support for "minver" * added support to add repositories and sections * added suppor for removing sources again . apturl (0.0+bzr20070709) gutsy; urgency=low . * properly integrate with firefox . apturl (0.0+bzr20070702) gutsy; urgency=low . * Initial Release. * Implements subset of https://wiki.ubuntu.com/AptFirefoxFileHandler (to unblock firefox-distro-addon-support spec)
Diffstat (limited to 'AptUrl')
-rw-r--r--AptUrl/AptUrl.py193
-rw-r--r--AptUrl/Helpers.py66
-rw-r--r--AptUrl/Parser.py153
-rw-r--r--AptUrl/UI.py23
-rw-r--r--AptUrl/Version.py0
-rw-r--r--AptUrl/__init__.py0
-rw-r--r--AptUrl/gtk/GtkUI.py158
-rw-r--r--AptUrl/gtk/__init__.py0
8 files changed, 593 insertions, 0 deletions
diff --git a/AptUrl/AptUrl.py b/AptUrl/AptUrl.py
new file mode 100644
index 0000000..e712e5b
--- /dev/null
+++ b/AptUrl/AptUrl.py
@@ -0,0 +1,193 @@
+# Copyright (c) 2007-2008 Canonical
+#
+# AUTHOR:
+# Michael Vogt <mvo@ubuntu.com>
+# With contributions by Siegfried-A. Gevatter <rainct@ubuntu.com>
+#
+# This file is part of AptUrl
+#
+# AptUrl 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 2 of the License, or (at
+# your option) any later version.
+#
+# AptUrl 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 AptUrl; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import apt
+import apt_pkg
+
+from . import Parser
+from . import Helpers
+from .Helpers import _
+
+from optparse import OptionParser
+
+import os
+import os.path
+
+# adding new repositories is currently disabled because some people have
+# security concerns about this feature
+allow_new_repositories = False
+
+# return codes
+(RESULT_OK,
+ RESULT_CANCELT,
+ RESULT_ERROR,
+ RESULT_BADARGS) = list(range(4))
+
+class AptUrlController(object):
+
+ def __init__(self, ui):
+ self.ui = ui
+
+ def openCache(self):
+ try:
+ self.cache = apt.Cache()
+ except SystemError as strerr:
+ if not '/etc/apt/sources.list' in str(strerr):
+ raise
+ self.ui.error(_("Invalid /etc/apt/sources.list file"), strerr)
+ return False
+ if self.cache._depcache.broken_count > 0:
+ err_header = _("Software index is broken")
+ err_body = _("This is a major failure of your software "
+ "management system. Please check for broken packages "
+ "with synaptic, check the file permissions and "
+ "correctness of the file '/etc/apt/sources.list' and "
+ "reload the software information with: "
+ "'sudo apt-get update' and 'sudo apt-get install -f'."
+ )
+ self.ui.error(err_header, err_body)
+ return False
+ return True
+
+ def parseArgs(self):
+ parser = OptionParser()
+ parser.add_option("-p", "--http-proxy", dest="http_proxy",
+ default=None, help="use http proxy")
+ (options, args) = parser.parse_args()
+
+ # eval and add proxy
+ if options.http_proxy is not None:
+ proxy = options.http_proxy
+ if not ":" in proxy:
+ proxy += ":3128"
+ os.environ["http_proxy"] = "http://%s" % proxy
+
+ # parse
+ try:
+ apturl_list = Parser.parse(args[0])
+ except IndexError as e:
+ self.ui.error(_("Need a url to continue, exiting"))
+ return []
+ except Parser.InvalidUrlException as e:
+ self.ui.error(_("Invalid url: '%s' given, exiting") % e.url,
+ str(e))
+ return []
+ return (apturl_list)
+
+ def verifyInstall(self, apturl):
+ " verify that the install package actually is installed "
+ # check if the package got actually installed
+ self.openCache()
+ pkg = self.cache[apturl.package]
+ if (not pkg.is_installed or
+ pkg._pkg.current_state != apt_pkg.CURSTATE_INSTALLED or
+ self.cache._depcache.broken_count > 0):
+ return False
+ return True
+
+ def main(self):
+ # global return code
+ ret = RESULT_OK
+ ui = self.ui
+
+ # parse arguments
+ apturl_list = self.parseArgs()
+ if not apturl_list:
+ return RESULT_BADARGS
+
+ # open cache
+ if not self.openCache():
+ return RESULT_ERROR
+
+ # now go over the url list
+ for apturl in apturl_list:
+ # FIXME: move this code block into a func like
+ # evalAptUrl()
+
+ if not apturl.schema in ("apt", "apt+http"):
+ self.ui.error(_("Can not deal with protocol '%s' ")
+ % apturl.schema)
+ continue
+
+ if apturl.refresh is not None:
+ ui.doUpdate()
+ if not self.openCache():
+ return RESULT_ERROR
+
+ # now check the package
+ if apturl.package not in self.cache:
+ try:
+ package_in_cache = bool(self.cache._cache[apturl.package])
+ except KeyError:
+ package_in_cache = False
+ if package_in_cache:
+ ui.error(_("Package '%s' is virtual.") % apturl.package)
+ continue
+ else:
+ ui.error(_("Could not find package '%s'.")
+ % apturl.package)
+ continue
+
+ if (self.cache[apturl.package].is_installed and
+ apturl.minver is None):
+ ui.message(_("Package '%s' is already installed")
+ % apturl.package)
+ continue
+
+ # ask the user
+ pkg = self.cache[apturl.package]
+ (sum, desc, homepage) = Helpers.parse_pkg(pkg)
+ if not ui.askInstallPackage(apturl.package, sum, desc, homepage):
+ ret = RESULT_CANCELT
+ continue
+
+ # try to install it
+ try:
+ self.cache[apturl.package].mark_install()
+ except SystemError as e:
+ ui.error(_("Can not install '%s' (%s) ") % (apturl.package, e))
+ continue
+ if apturl.minver is not None:
+ verStr = self.cache[apturl.package].candidate.version
+ if apt_pkg.version_compare(verStr, apturl.minver) < 1:
+ ui.error(_(
+ "Package '%s' requests minimal version '%s', but "
+ "only '%s' is available") % (apturl.package,
+ apturl.minver,
+ verStr))
+ continue
+
+ changes = self.cache.get_changes()
+ additional_pkgs = []
+
+ for pkg in changes:
+ if pkg.marked_install:
+ additional_pkgs.append(pkg.name)
+
+ # install it
+ ui.doInstall(apturl, extra_pkg_names=additional_pkgs)
+
+ if not self.verifyInstall(apturl):
+ ret = RESULT_ERROR
+
+ # return values
+ return ret
diff --git a/AptUrl/Helpers.py b/AptUrl/Helpers.py
new file mode 100644
index 0000000..d00b862
--- /dev/null
+++ b/AptUrl/Helpers.py
@@ -0,0 +1,66 @@
+# Copyright (c) 2008 Canonical
+#
+# AUTHOR:
+# Siegfried-A. Gevatter <rainct@ubuntu.com>
+#
+# This file is part of AptUrl
+#
+# AptUrl 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 2 of the License, or (at
+# your option) any later version.
+#
+# AptUrl 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 AptUrl; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import gettext
+import subprocess
+
+def _(str):
+ return utf8(gettext.gettext(str))
+
+def _n(singular, plural, n):
+ return utf8(gettext.ngettext(singular, plural, n))
+
+def utf8(str):
+ if str is bytes:
+ try:
+ return str.decode('UTF-8')
+ except UnicodeDecodeError:
+ # assume latin1 as fallback
+ return str.decode('latin1')
+ else:
+ return str
+
+def get_dist():
+ return subprocess.check_output(
+ 'lsb_release -c -s'.split(),
+ universal_newlines=True).strip()
+
+
+def parse_pkg(pkgobj):
+ summary = ""
+ description = ""
+ pkg_description = pkgobj.candidate.description
+ if pkg_description.count("\n") > 0:
+ summary, description = pkg_description.split('\n', 1)
+ else:
+ summary = pkg_description
+ lines = description.rstrip('\n').split('\n')
+ if len(lines) > 1 and lines[-1].startswith('Homepage: '):
+ homepage = lines[-1].split(' ', 1)[1]
+ description = '\n'.join(lines[:-1])
+ else:
+ homepage = pkgobj.candidate.homepage
+ return (summary, description, homepage)
+
+def format_description(description):
+ const = 'APTURL_DOUBLE_EMPTY_LINE_PLACEHOLDER'
+ return description.replace('\n\n', const).replace('\n', ' ').replace(
+ const, '\n\n')
diff --git a/AptUrl/Parser.py b/AptUrl/Parser.py
new file mode 100644
index 0000000..0543d07
--- /dev/null
+++ b/AptUrl/Parser.py
@@ -0,0 +1,153 @@
+# Copyright (c) 2007-2008 Canonical
+#
+# AUTHOR:
+# Michael Vogt <mvo@ubuntu.com>
+# With contributions by Siegfried-A. Gevatter <rainct@ubuntu.com>
+#
+# This file is part of AptUrl
+#
+# AptUrl 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 2 of the License, or (at
+# your option) any later version.
+#
+# AptUrl 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 AptUrl; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+import string
+from string import Template
+from .Helpers import get_dist
+from .Helpers import _
+
+class InvalidUrlException(Exception):
+ def __init__(self, url, msg=""):
+ self.url = url
+ self.message = msg
+ def __str__(self):
+ return self.message
+
+MAX_URL_LEN=255
+
+# substituion mapping
+apturl_substitution_mapping = {
+ "distro" : get_dist(),
+ "kernel" : os.uname()[2]
+}
+
+# whitelist for the uri
+whitelist = []
+whitelist.extend(string.ascii_letters)
+whitelist.extend(string.digits)
+whitelist.extend(['_',':','?','/','+','.','~','=','<','>','-',',','$','&'])
+
+
+class AptUrl(object):
+ " a class that contains the parsed data from an apt url "
+ def __init__(self):
+ self.package = None
+ self.schema = None
+ self.minver = None
+ self.refresh = None
+ # for added repos
+ self.keyfile = None
+ self.repo_url = None
+ self.dist = '/'
+ # for known sections
+ self.section = []
+ # for known channels
+ self.channel = None
+
+def is_format_package_name(string):
+ " return True if string would be an acceptable name for a Debian package "
+
+ return (string.replace("+", "").replace("-", "").replace(".", "").replace(":", "").isalnum()
+ and string.islower() and string[0].isalnum() and len(string) > 1)
+
+def do_apt_url_substitution(apt_url, mapping):
+ " substitute known templates against the field package and channel "
+ for field in ["package","channel"]:
+ if getattr(apt_url, field):
+ s=Template(getattr(apt_url, field))
+ setattr(apt_url, field, s.substitute(mapping))
+
+def match_against_whitelist(raw_url):
+ " test if the url matches the internal whitelist "
+ for char in raw_url:
+ if not char in whitelist:
+ raise InvalidUrlException(
+ raw_url, _("Non whitelist char in the uri"))
+ return True
+
+def set_value(apt_url, s):
+ " set a key,value pair from string s to AptUrl object "
+ (key, value) = s.split("=")
+ try:
+ if ' ' in value:
+ raise InvalidUrlException(apt_url, _("Whitespace in key=value"))
+ if type(getattr(apt_url, key)) == type([]):
+ getattr(apt_url, key).append(value)
+ else:
+ setattr(apt_url, key, value)
+ except Exception as e:
+ raise InvalidUrlException(apt_url, _("Exception '%s'") % e)
+
+
+def parse(full_url, mapping=apturl_substitution_mapping):
+ " parse an apt url and return a list of AptUrl objects "
+ # apt:pkg1?k11=v11?k12=v12,pkg2?k21=v21?k22=v22,...
+ res = []
+
+ if len(full_url) > MAX_URL_LEN:
+ url = "%s ..." % full_url[0:(MAX_URL_LEN // 10)]
+ raise InvalidUrlException(url, _("Url string '%s' too long") % url)
+
+ # check against whitelist
+ match_against_whitelist(full_url)
+ for url in full_url.split(";"):
+ if not ":" in url:
+ raise InvalidUrlException(url, _("No ':' in the uri"))
+
+ # now parse it
+
+ (schema, packages) = url.split(":", 1)
+ packages = packages.split(",")
+
+ for package in packages:
+ apt_url = AptUrl()
+ apt_url.schema = schema
+ # check for schemas of the form: apt+http://
+ if schema.startswith("apt+"):
+ apt_url.repo_url = schema[len("apt+"):] + ":" + package.split("?",1)[0]
+ else:
+ if "?" in package:
+ apt_url.package = package.split("?")[0].lstrip("/")
+ else:
+ apt_url.package = package.lstrip("/")
+
+ # now parse the ?... bits
+ if "?" in package:
+ key_value_pairs = package.split("?")[1:]
+ for s in key_value_pairs:
+ if "&" in s:
+ and_key_value_pairs = s.split("&")
+ for s in and_key_value_pairs:
+ set_value(apt_url, s)
+ else:
+ set_value(apt_url, s)
+
+ # do substitution (if needed)
+ do_apt_url_substitution(apt_url, mapping)
+
+ # check if the package name is valid
+ if not is_format_package_name(apt_url.package):
+ raise InvalidUrlException(url, "Invalid package name '%s'" % apt_url.package)
+
+ res.append(apt_url)
+ return res
diff --git a/AptUrl/UI.py b/AptUrl/UI.py
new file mode 100644
index 0000000..0fd502c
--- /dev/null
+++ b/AptUrl/UI.py
@@ -0,0 +1,23 @@
+
+from .Helpers import _, _n
+
+class AbstractUI(object):
+ # generic dialogs
+ def error(self, summary, msg):
+ return False
+ def yesNoQuestion(self, summary, msg, title, default='no'):
+ pass
+ def message(self, summary, msg):
+ return True
+
+ def askInstallPackage(self):
+ pass
+
+ # install/update progress
+ def doUpdate(self):
+ pass
+ def doInstall(self, apturl, extra_pkg_names=None):
+ pass
+
+ # UI specific actions for enabling stuff
+
diff --git a/AptUrl/Version.py b/AptUrl/Version.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AptUrl/Version.py
diff --git a/AptUrl/__init__.py b/AptUrl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AptUrl/__init__.py
diff --git a/AptUrl/gtk/GtkUI.py b/AptUrl/gtk/GtkUI.py
new file mode 100644
index 0000000..dcc905f
--- /dev/null
+++ b/AptUrl/gtk/GtkUI.py
@@ -0,0 +1,158 @@
+import gi
+gi.require_version('Gtk', '3.0')
+gi.require_version('XApp', '1.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
+from gi.repository import XApp
+GObject.threads_init()
+
+import os
+import sys
+import apt_pkg
+import subprocess
+import tempfile
+
+from AptUrl.UI import AbstractUI
+from AptUrl import Helpers
+from AptUrl.Helpers import _
+
+import mintcommon.aptdaemon
+
+APTURL_UI_FILE = os.environ.get(
+ # Set this envar to use a test .ui file.
+ 'APTURL_UI_FILE',
+ # System file to use if the envar is not set.
+ '/usr/share/apturl/apturl-gtk.ui'
+ )
+
+
+class GtkUI(AbstractUI):
+ def __init__(self):
+ Gtk.init_check(sys.argv)
+ # create empty dialog
+ self.dia_xml = Gtk.Builder()
+ self.dia_xml.set_translation_domain("apturl")
+ self.dia_xml.add_from_file(APTURL_UI_FILE)
+ self.dia = self.dia_xml.get_object('confirmation_dialog')
+ self.dia.start_available = lambda: Gtk.main_quit()
+ self.dia.start_error = lambda: Gtk.main_quit()
+ self.dia.exit = lambda: Gtk.main_quit()
+ self.dia.realize()
+ self.require_update = False
+
+ # generic dialogs
+ def _get_dialog(self, dialog_type, summary, msg="",
+ buttons=Gtk.ButtonsType.CLOSE):
+ " internal helper for dialog construction "
+ d = Gtk.MessageDialog(parent=self.dia,
+ flags=Gtk.DialogFlags.MODAL,
+ type=dialog_type,
+ buttons=buttons)
+ d.set_title("")
+ d.set_markup("<big><b>%s</b></big>\n\n%s" % (summary, msg))
+ XApp.set_window_icon_name(d, "package-x-generic")
+ d.set_keep_above(True)
+ d.realize()
+ d.get_window().set_functions(Gdk.WMFunction.MOVE)
+ return d
+
+ def error(self, summary, msg=""):
+ d = self._get_dialog(Gtk.MessageType.ERROR, summary, msg)
+ d.run()
+ d.destroy()
+ return False
+
+ def message(self, summary, msg="", title=""):
+ d = self._get_dialog(Gtk.MessageType.INFO, summary, msg)
+ d.set_title(title)
+ d.run()
+ d.destroy()
+ return True
+
+ def yesNoQuestion(self, summary, msg, title="", default='no'):
+ d = self._get_dialog(Gtk.MessageType.QUESTION, summary, msg,
+ buttons=Gtk.ButtonsType.YES_NO)
+ d.set_title(title)
+ res = d.run()
+ d.destroy()
+ if res != Gtk.ResponseType.YES:
+ return False
+ return True
+
+ def askInstallPackage(self, package, summary, description, homepage):
+ # populate the dialog
+ dia = self.dia
+ dia_xml = self.dia_xml
+ header = _("Install additional software?")
+ body = _("Do you want to install package '%s'?") % package
+ dia.set_title(package)
+ header_label = dia_xml.get_object('header_label')
+ header_label.set_markup("<b><big>%s</big></b>" % header)
+ body_label = dia_xml.get_object('body_label')
+ body_label.set_label(body)
+ description_text_view = dia_xml.get_object('description_text_view')
+ tbuf = Gtk.TextBuffer()
+ desc = "%s\n\n%s" % (summary, Helpers.format_description(description))
+ tbuf.set_text(desc)
+ description_text_view.set_buffer(tbuf)
+ XApp.set_window_icon_name(dia, "package-x-generic")
+
+ # check if another package manager is already running
+ # FIXME: just checking for the existance of the file is
+ # not sufficient, it need to be tested if it can
+ # be locked via apt_pkg.get_lock()
+ # - but that needs to run as root
+ # - a dbus helper might be the best answer here
+ #args = (update_button_status, dia_xml.get_object("yes_button"),
+ # dia_xml.get_object("infolabel"))
+ #args[0](*args[1:])
+ #timer_id = GObject.timeout_add(750, *args )
+
+ # show the dialog
+ res = dia.run()
+ #GObject.source_remove(timer_id)
+ if res != Gtk.ResponseType.YES:
+ dia.hide()
+ return False
+
+ return True
+
+ # progress etc
+ def doUpdate(self):
+ self.require_update = True
+
+ def doInstall(self, apturl, extra_pkg_names=[]):
+ self.dia.hide()
+ packages = []
+ packages.append(apturl.package)
+ packages += extra_pkg_names
+ self.install_packages(packages)
+
+ def install_packages(self, package_names):
+ self.apt = mintcommon.aptdaemon.APT(None)
+ self.package_names = package_names
+ self.busy = True
+ if self.require_update:
+ self.apt.set_finished_callback(self.on_update_before_install_finished)
+ self.apt.update_cache()
+ else:
+ self.on_update_before_install_finished()
+ while self.busy:
+ while Gtk.events_pending():
+ Gtk.main_iteration()
+
+ def on_update_before_install_finished(self, transaction=None, exit_state=None):
+ self.apt.set_finished_callback(self.on_install_finished)
+ self.apt.set_cancelled_callback(self.on_install_finished)
+ self.apt.install_packages(self.package_names)
+
+ def on_install_finished(self, transaction=None, exit_state=None):
+ del self.package_names
+ del self.apt
+ self.busy = False
+ self.dia.exit()
+
+if __name__ == "__main__":
+ ui = GtkUI()
+ ui.error("foo","bar")
diff --git a/AptUrl/gtk/__init__.py b/AptUrl/gtk/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AptUrl/gtk/__init__.py